Completed
Pull Request — master (#574)
by Fosco
02:57
created

FacebookUrlDetectionHandler::getHttpScheme()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 2
eloc 2
nc 2
nop 0
1
<?php
2
/**
3
 * Copyright 2016 Facebook, Inc.
4
 *
5
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
 * use, copy, modify, and distribute this software in source code or binary
7
 * form for use in connection with the web services and APIs provided by
8
 * Facebook.
9
 *
10
 * As with any software that integrates with the Facebook platform, your use
11
 * of this software is subject to the Facebook Developer Principles and
12
 * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
 * shall be included in all copies or substantial portions of the software.
14
 *
15
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
 * DEALINGS IN THE SOFTWARE.
22
 *
23
 */
24
namespace Facebook\Url;
25
26
/**
27
 * Class FacebookUrlDetectionHandler
28
 *
29
 * @package Facebook
30
 */
31
class FacebookUrlDetectionHandler implements UrlDetectionInterface
32
{
33
    /**
34
     * @inheritdoc
35
     */
36
    public function getCurrentUrl()
37
    {
38
        return $this->getHttpScheme() . '://' . $this->getHostName() . $this->getServerVar('REQUEST_URI');
39
    }
40
41
    /**
42
     * Get the currently active URL scheme.
43
     *
44
     * @return string
45
     */
46
    protected function getHttpScheme()
47
    {
48
        return $this->isBehindSsl() ? 'https' : 'http';
49
    }
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 ($this->isValidForwardedHost() && $host = $this->getHeader('X_FORWARDED_HOST')) {
99
            $elements = explode(',', $host);
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)
148
    {
149
        return isset($_SERVER[$key]) ? $_SERVER[$key] : '';
150
    }
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)
160
    {
161
        return $this->getServerVar('HTTP_' . $key);
162
    }
163
164
    /**
165
     * Checks if the value in X_FORWARDED_HOST is a valid hostname
166
     * Could prevent unintended redirections
167
     */
168
    protected function isValidForwardedHost()
169
    {
170
        $host = $this->getHeader('X_FORWARDED_HOST');
171
        if (!$host) {
172
          return false;
0 ignored issues
show
Coding Style introduced by
It seems like the identation of this line is off (expected at least 12 spaces, but found 10).
Loading history...
173
        }
174
175
        $elements = explode(',', $host);
176
        $host = $elements[count($elements) - 1];
177
        
178
        return return (preg_match("/^([a-z\d](-*[a-z\d])*)(\.([a-z\d](-*[a-z\d])*))*$/i", $domain_name) //valid chars check
0 ignored issues
show
Bug introduced by
This code did not parse for me. Apparently, there is an error somewhere around this line:

Syntax error, unexpected T_RETURN, expecting ';'
Loading history...
179
            && preg_match("/^.{1,253}$/", $domain_name) //overall length check
180
            && preg_match("/^[^\.]{1,63}(\.[^\.]{1,63})*$/", $domain_name) ); //length of each label
181
    }
182
183
}
184