Subversion Repositories cheapmusic

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
25 - 1
<?php
2
/**
3
 * Copyright 2017 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
        $header = $this->getHeader('X_FORWARDED_HOST');
99
        if ($header && $this->isValidForwardedHost($header)) {
100
            $elements = explode(',', $header);
101
            $host = $elements[count($elements) - 1];
102
        } elseif (!$host = $this->getHeader('HOST')) {
103
            if (!$host = $this->getServerVar('SERVER_NAME')) {
104
                $host = $this->getServerVar('SERVER_ADDR');
105
            }
106
        }
107
 
108
        // trim and remove port number from host
109
        // host is lowercase as per RFC 952/2181
110
        $host = strtolower(preg_replace('/:\d+$/', '', trim($host)));
111
 
112
        // Port number
113
        $scheme = $this->getHttpScheme();
114
        $port = $this->getCurrentPort();
115
        $appendPort = ':' . $port;
116
 
117
        // Don't append port number if a normal port.
118
        if (($scheme == 'http' && $port == '80') || ($scheme == 'https' && $port == '443')) {
119
            $appendPort = '';
120
        }
121
 
122
        return $host . $appendPort;
123
    }
124
 
125
    protected function getCurrentPort()
126
    {
127
        // Check for proxy first
128
        $port = $this->getHeader('X_FORWARDED_PORT');
129
        if ($port) {
130
            return (string)$port;
131
        }
132
 
133
        $protocol = (string)$this->getHeader('X_FORWARDED_PROTO');
134
        if ($protocol === 'https') {
135
            return '443';
136
        }
137
 
138
        return (string)$this->getServerVar('SERVER_PORT');
139
    }
140
 
141
    /**
142
     * Returns the a value from the $_SERVER super global.
143
     *
144
     * @param string $key
145
     *
146
     * @return string
147
     */
148
    protected function getServerVar($key)
149
    {
150
        return isset($_SERVER[$key]) ? $_SERVER[$key] : '';
151
    }
152
 
153
    /**
154
     * Gets a value from the HTTP request headers.
155
     *
156
     * @param string $key
157
     *
158
     * @return string
159
     */
160
    protected function getHeader($key)
161
    {
162
        return $this->getServerVar('HTTP_' . $key);
163
    }
164
 
165
    /**
166
     * Checks if the value in X_FORWARDED_HOST is a valid hostname
167
     * Could prevent unintended redirections
168
     *
169
     * @param string $header
170
     *
171
     * @return boolean
172
     */
173
    protected function isValidForwardedHost($header)
174
    {
175
        $elements = explode(',', $header);
176
        $host = $elements[count($elements) - 1];
177
 
178
        return preg_match("/^([a-z\d](-*[a-z\d])*)(\.([a-z\d](-*[a-z\d])*))*$/i", $host) //valid chars check
179
            && 0 < strlen($host) && strlen($host) < 254 //overall length check
180
            && preg_match("/^[^\.]{1,63}(\.[^\.]{1,63})*$/", $host); //length of each label
181
    }
182
}