1 | <?php |
||
31 | class FacebookUrlDetectionHandler implements UrlDetectionInterface |
||
32 | { |
||
33 | /** |
||
34 | * @inheritdoc |
||
35 | */ |
||
36 | public function getCurrentUrl() |
||
40 | |||
41 | /** |
||
42 | * Get the currently active URL scheme. |
||
43 | * |
||
44 | * @return string |
||
45 | */ |
||
46 | protected function getHttpScheme() |
||
50 | |||
51 | /** |
||
52 | * Tries to detect if the server is running behind an SSL. |
||
53 | * |
||
54 | * @return boolean |
||
55 | */ |
||
56 | protected function isBehindSsl() |
||
57 | { |
||
58 | // Check for proxy first |
||
59 | $protocol = $this->getHeader('X_FORWARDED_PROTO'); |
||
60 | if ($protocol) { |
||
61 | return $this->protocolWithActiveSsl($protocol); |
||
62 | } |
||
63 | |||
64 | $protocol = $this->getServerVar('HTTPS'); |
||
65 | if ($protocol) { |
||
66 | return $this->protocolWithActiveSsl($protocol); |
||
67 | } |
||
68 | |||
69 | return (string)$this->getServerVar('SERVER_PORT') === '443'; |
||
70 | } |
||
71 | |||
72 | /** |
||
73 | * Detects an active SSL protocol value. |
||
74 | * |
||
75 | * @param string $protocol |
||
76 | * |
||
77 | * @return boolean |
||
78 | */ |
||
79 | protected function protocolWithActiveSsl($protocol) |
||
80 | { |
||
81 | $protocol = strtolower((string)$protocol); |
||
82 | |||
83 | return in_array($protocol, ['on', '1', 'https', 'ssl'], true); |
||
84 | } |
||
85 | |||
86 | /** |
||
87 | * Tries to detect the host name of the server. |
||
88 | * |
||
89 | * Some elements adapted from |
||
90 | * |
||
91 | * @see https://github.com/symfony/HttpFoundation/blob/master/Request.php |
||
92 | * |
||
93 | * @return string |
||
94 | */ |
||
95 | protected function getHostName() |
||
96 | { |
||
97 | // Check for proxy first |
||
98 | if ($header = $this->getHeader('X_FORWARDED_HOST') && $this->isValidForwardedHost($header)) { |
||
99 | $elements = explode(',', $header); |
||
100 | $host = $elements[count($elements) - 1]; |
||
101 | } elseif (!$host = $this->getHeader('HOST')) { |
||
102 | if (!$host = $this->getServerVar('SERVER_NAME')) { |
||
103 | $host = $this->getServerVar('SERVER_ADDR'); |
||
104 | } |
||
105 | } |
||
106 | |||
107 | // trim and remove port number from host |
||
108 | // host is lowercase as per RFC 952/2181 |
||
109 | $host = strtolower(preg_replace('/:\d+$/', '', trim($host))); |
||
110 | |||
111 | // Port number |
||
112 | $scheme = $this->getHttpScheme(); |
||
113 | $port = $this->getCurrentPort(); |
||
114 | $appendPort = ':' . $port; |
||
115 | |||
116 | // Don't append port number if a normal port. |
||
117 | if (($scheme == 'http' && $port == '80') || ($scheme == 'https' && $port == '443')) { |
||
118 | $appendPort = ''; |
||
119 | } |
||
120 | |||
121 | return $host . $appendPort; |
||
122 | } |
||
123 | |||
124 | protected function getCurrentPort() |
||
125 | { |
||
126 | // Check for proxy first |
||
127 | $port = $this->getHeader('X_FORWARDED_PORT'); |
||
128 | if ($port) { |
||
129 | return (string)$port; |
||
130 | } |
||
131 | |||
132 | $protocol = (string)$this->getHeader('X_FORWARDED_PROTO'); |
||
133 | if ($protocol === 'https') { |
||
134 | return '443'; |
||
135 | } |
||
136 | |||
137 | return (string)$this->getServerVar('SERVER_PORT'); |
||
138 | } |
||
139 | |||
140 | /** |
||
141 | * Returns the a value from the $_SERVER super global. |
||
142 | * |
||
143 | * @param string $key |
||
144 | * |
||
145 | * @return string |
||
146 | */ |
||
147 | protected function getServerVar($key) |
||
151 | |||
152 | /** |
||
153 | * Gets a value from the HTTP request headers. |
||
154 | * |
||
155 | * @param string $key |
||
156 | * |
||
157 | * @return string |
||
158 | */ |
||
159 | protected function getHeader($key) |
||
163 | |||
164 | /** |
||
165 | * Checks if the value in X_FORWARDED_HOST is a valid hostname |
||
166 | * Could prevent unintended redirections |
||
167 | * |
||
168 | * @param string $header |
||
169 | * |
||
170 | * @return boolean |
||
171 | */ |
||
172 | protected function isValidForwardedHost($header) |
||
181 | } |
||
182 |
This error can happen if you refactor code and forget to move the variable initialization.
Let’s take a look at a simple example:
The above code is perfectly fine. Now imagine that we re-order the statements:
In that case,
$x
would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.