Completed
Pull Request — 1.11.x (#1599)
by José
28:19
created
plugin/buycourses/src/buy_course_plugin.class.php 1 patch
Doc Comments   +14 added lines, -14 removed lines patch added patch discarded remove patch
@@ -49,7 +49,7 @@  discard block
 block discarded – undo
49 49
 
50 50
     /**
51 51
      *
52
-     * @return StaticPlugin
52
+     * @return BuyCoursesPlugin
53 53
      */
54 54
     static function create()
55 55
     {
@@ -277,7 +277,7 @@  discard block
 block discarded – undo
277 277
     /**
278 278
      * Save a transfer account information
279 279
      * @param array $params The transfer account
280
-     * @return int Rows affected. Otherwise return false
280
+     * @return false|string Rows affected. Otherwise return false
281 281
      */
282 282
     public function saveTransferAccount($params)
283 283
     {
@@ -690,7 +690,7 @@  discard block
 block discarded – undo
690 690
     /**
691 691
      * Get session info
692 692
      * @param array $sessionId The session ID
693
-     * @return array
693
+     * @return Session
694 694
      */
695 695
     public function getSessionInfo($sessionId)
696 696
     {
@@ -783,7 +783,7 @@  discard block
 block discarded – undo
783 783
      * Register a sale
784 784
      * @param int $itemId The product ID
785 785
      * @param int $paymentType The payment type
786
-     * @return boolean
786
+     * @return false|string
787 787
      */
788 788
     public function registerSale($itemId, $paymentType)
789 789
     {
@@ -965,7 +965,7 @@  discard block
 block discarded – undo
965 965
 
966 966
     /**
967 967
      * Get payment types
968
-     * @return array
968
+     * @return string[]
969 969
      */
970 970
     public function getPaymentTypes()
971 971
     {
@@ -1004,7 +1004,7 @@  discard block
 block discarded – undo
1004 1004
 
1005 1005
     /**
1006 1006
      * Get the statuses for sales
1007
-     * @return array
1007
+     * @return string[]
1008 1008
      */
1009 1009
     public function getSaleStatuses()
1010 1010
     {
@@ -1017,7 +1017,7 @@  discard block
 block discarded – undo
1017 1017
 
1018 1018
     /**
1019 1019
      * Get the statuses for Payouts
1020
-     * @return array
1020
+     * @return string[]
1021 1021
      */
1022 1022
     public function getPayoutStatuses()
1023 1023
     {
@@ -1030,7 +1030,7 @@  discard block
 block discarded – undo
1030 1030
 
1031 1031
     /**
1032 1032
      * Get the list of product types
1033
-     * @return array
1033
+     * @return string[]
1034 1034
      */
1035 1035
     public function getProductTypes()
1036 1036
     {
@@ -1042,7 +1042,7 @@  discard block
 block discarded – undo
1042 1042
 
1043 1043
     /**
1044 1044
      * Get the list of service types
1045
-     * @return array
1045
+     * @return string[]
1046 1046
      */
1047 1047
     public function getServiceTypes()
1048 1048
     {
@@ -1424,7 +1424,7 @@  discard block
 block discarded – undo
1424 1424
     /**
1425 1425
      * Register a item
1426 1426
      * @param array $itemData The item data
1427
-     * @return int The item ID. Otherwise return false
1427
+     * @return false|string The item ID. Otherwise return false
1428 1428
      */
1429 1429
     public function registerItem(array $itemData)
1430 1430
     {
@@ -1582,7 +1582,7 @@  discard block
 block discarded – undo
1582 1582
     /**
1583 1583
      * Verify if the beneficiary have a paypal account
1584 1584
      * @param int $userId
1585
-     * @return true if the user have a paypal account, false if not
1585
+     * @return boolean if the user have a paypal account, false if not
1586 1586
      */
1587 1587
     public function verifyPaypalAccountByBeneficiary($userId)
1588 1588
     {
@@ -1704,7 +1704,7 @@  discard block
 block discarded – undo
1704 1704
     /**
1705 1705
      * Register addicional service
1706 1706
      * @param array params $service
1707
-     * @return mixed response
1707
+     * @return string|false response
1708 1708
      */
1709 1709
     public function storeService($service)
1710 1710
     {
@@ -1861,7 +1861,7 @@  discard block
 block discarded – undo
1861 1861
 
1862 1862
     /**
1863 1863
      * Get the statuses for sales
1864
-     * @return array
1864
+     * @return string[]
1865 1865
      */
1866 1866
     public function getServiceSaleStatuses()
1867 1867
     {
@@ -2118,7 +2118,7 @@  discard block
 block discarded – undo
2118 2118
      * @param int $paymentType The payment type
2119 2119
      * @param int $infoSelect The ID for Service Type
2120 2120
      * @param int $trial trial mode
2121
-     * @return boolean
2121
+     * @return false|string
2122 2122
      */
2123 2123
     public function registerServiceSale($serviceId, $paymentType, $infoSelect, $trial = null)
2124 2124
     {
Please login to merge, or discard this patch.
plugin/buycourses/src/Culqi/Client.php 3 patches
Doc Comments   +3 added lines patch added patch discarded remove patch
@@ -17,6 +17,9 @@
 block discarded – undo
17 17
     const BASE_URL = "https://integ-pago.culqi.com/api/v1";
18 18
 
19 19
 
20
+    /**
21
+     * @param string $method
22
+     */
20 23
     public function request($method, $url, $api_key, $data = NULL, $headers= array("Content-Type" => "application/json", "Accept" => "application/json") ) {
21 24
         try {
22 25
             $options = array(
Please login to merge, or discard this patch.
Indentation   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -7,8 +7,8 @@
 block discarded – undo
7 7
 class Client
8 8
 {
9 9
     /**
10
-    * La versión de API usada
11
-    */
10
+     * La versión de API usada
11
+     */
12 12
     const API_VERSION = "v1.2";
13 13
 
14 14
     /**
Please login to merge, or discard this patch.
Spacing   +9 added lines, -9 removed lines patch added patch discarded remove patch
@@ -17,22 +17,22 @@
 block discarded – undo
17 17
     const BASE_URL = "https://integ-pago.culqi.com/api/v1";
18 18
 
19 19
 
20
-    public function request($method, $url, $api_key, $data = NULL, $headers= array("Content-Type" => "application/json", "Accept" => "application/json") ) {
20
+    public function request($method, $url, $api_key, $data = NULL, $headers = array("Content-Type" => "application/json", "Accept" => "application/json")) {
21 21
         try {
22 22
             $options = array(
23 23
                 'auth' => new AuthBearer($api_key),
24 24
                 'timeout' => 120
25 25
             );
26
-            if($method == "GET") {
27
-                $url_params = is_array($data) ? '?' . http_build_query($data) : '';
28
-                $response = \Requests::get(Culqi::$api_base . $url . $url_params, $headers, $options);
29
-            } else if($method == "POST") {
30
-                $response = \Requests::post(Culqi::$api_base . $url, $headers, json_encode($data), $options);
26
+            if ($method == "GET") {
27
+                $url_params = is_array($data) ? '?'.http_build_query($data) : '';
28
+                $response = \Requests::get(Culqi::$api_base.$url.$url_params, $headers, $options);
29
+            } else if ($method == "POST") {
30
+                $response = \Requests::post(Culqi::$api_base.$url, $headers, json_encode($data), $options);
31 31
 
32 32
 
33
-            } else if($method == "PATCH") {
34
-                $response = \Requests::patch(Culqi::$api_base . $url, $headers, json_encode($data), $options);
35
-            } else if($method == "DELETE") {
33
+            } else if ($method == "PATCH") {
34
+                $response = \Requests::patch(Culqi::$api_base.$url, $headers, json_encode($data), $options);
35
+            } else if ($method == "DELETE") {
36 36
                 $response = \Requests::delete(Culqi::$api_base, $options);
37 37
             }
38 38
         } catch (\Exception $e) {
Please login to merge, or discard this patch.
plugin/buycourses/src/Culqi/Resource.php 1 patch
Doc Comments   +3 added lines patch added patch discarded remove patch
@@ -3,6 +3,9 @@
 block discarded – undo
3 3
 
4 4
 class Resource extends Client {
5 5
 
6
+    /**
7
+     * @param Culqi $culqi
8
+     */
6 9
     public function __construct($culqi)
7 10
     {
8 11
         $this->culqi = $culqi;
Please login to merge, or discard this patch.
plugin/buycourses/src/Requests.php 4 patches
Doc Comments   +4 added lines patch added patch discarded remove patch
@@ -226,6 +226,7 @@  discard block
 block discarded – undo
226 226
 	 */
227 227
 	/**
228 228
 	 * Send a GET request
229
+	 * @param string $url
229 230
 	 */
230 231
 	public static function get($url, $headers = array(), $options = array()) {
231 232
 		return self::request($url, $headers, null, self::GET, $options);
@@ -240,6 +241,7 @@  discard block
 block discarded – undo
240 241
 
241 242
 	/**
242 243
 	 * Send a DELETE request
244
+	 * @param string $url
243 245
 	 */
244 246
 	public static function delete($url, $headers = array(), $options = array()) {
245 247
 		return self::request($url, $headers, null, self::DELETE, $options);
@@ -263,6 +265,7 @@  discard block
 block discarded – undo
263 265
 	 */
264 266
 	/**
265 267
 	 * Send a POST request
268
+	 * @param string $url
266 269
 	 */
267 270
 	public static function post($url, $headers = array(), $data = array(), $options = array()) {
268 271
 		return self::request($url, $headers, $data, self::POST, $options);
@@ -288,6 +291,7 @@  discard block
 block discarded – undo
288 291
 	 * specification recommends that should send an ETag
289 292
 	 *
290 293
 	 * @link https://tools.ietf.org/html/rfc5789
294
+	 * @param string $url
291 295
 	 */
292 296
 	public static function patch($url, $headers, $data = array(), $options = array()) {
293 297
 		return self::request($url, $headers, $data, self::PATCH, $options);
Please login to merge, or discard this patch.
Indentation   +945 added lines, -945 removed lines patch added patch discarded remove patch
@@ -19,241 +19,241 @@  discard block
 block discarded – undo
19 19
  * @package Requests
20 20
  */
21 21
 class Requests {
22
-	/**
23
-	 * POST method
24
-	 *
25
-	 * @var string
26
-	 */
27
-	const POST = 'POST';
28
-
29
-	/**
30
-	 * PUT method
31
-	 *
32
-	 * @var string
33
-	 */
34
-	const PUT = 'PUT';
35
-
36
-	/**
37
-	 * GET method
38
-	 *
39
-	 * @var string
40
-	 */
41
-	const GET = 'GET';
42
-
43
-	/**
44
-	 * HEAD method
45
-	 *
46
-	 * @var string
47
-	 */
48
-	const HEAD = 'HEAD';
49
-
50
-	/**
51
-	 * DELETE method
52
-	 *
53
-	 * @var string
54
-	 */
55
-	const DELETE = 'DELETE';
56
-
57
-	/**
58
-	 * OPTIONS method
59
-	 *
60
-	 * @var string
61
-	 */
62
-	const OPTIONS = 'OPTIONS';
63
-
64
-	/**
65
-	 * TRACE method
66
-	 *
67
-	 * @var string
68
-	 */
69
-	const TRACE = 'TRACE';
70
-
71
-	/**
72
-	 * PATCH method
73
-	 *
74
-	 * @link https://tools.ietf.org/html/rfc5789
75
-	 * @var string
76
-	 */
77
-	const PATCH = 'PATCH';
78
-
79
-	/**
80
-	 * Default size of buffer size to read streams
81
-	 *
82
-	 * @var integer
83
-	 */
84
-	const BUFFER_SIZE = 1160;
85
-
86
-	/**
87
-	 * Current version of Requests
88
-	 *
89
-	 * @var string
90
-	 */
91
-	const VERSION = '1.7';
92
-
93
-	/**
94
-	 * Registered transport classes
95
-	 *
96
-	 * @var array
97
-	 */
98
-	protected static $transports = array();
99
-
100
-	/**
101
-	 * Selected transport name
102
-	 *
103
-	 * Use {@see get_transport()} instead
104
-	 *
105
-	 * @var array
106
-	 */
107
-	public static $transport = array();
108
-
109
-	/**
110
-	 * Default certificate path.
111
-	 *
112
-	 * @see Requests::get_certificate_path()
113
-	 * @see Requests::set_certificate_path()
114
-	 *
115
-	 * @var string
116
-	 */
117
-	protected static $certificate_path;
118
-
119
-	/**
120
-	 * This is a static class, do not instantiate it
121
-	 *
122
-	 * @codeCoverageIgnore
123
-	 */
124
-	private function __construct() {}
125
-
126
-	/**
127
-	 * Autoloader for Requests
128
-	 *
129
-	 * Register this with {@see register_autoloader()} if you'd like to avoid
130
-	 * having to create your own.
131
-	 *
132
-	 * (You can also use `spl_autoload_register` directly if you'd prefer.)
133
-	 *
134
-	 * @codeCoverageIgnore
135
-	 *
136
-	 * @param string $class Class name to load
137
-	 */
138
-	public static function autoloader($class) {
139
-		// Check that the class starts with "Requests"
140
-		if (strpos($class, 'Requests') !== 0) {
141
-			return;
142
-		}
143
-
144
-		$file = str_replace('_', '/', $class);
145
-		if (file_exists(dirname(__FILE__) . '/' . $file . '.php')) {
146
-			require_once(dirname(__FILE__) . '/' . $file . '.php');
147
-		}
148
-	}
149
-
150
-	/**
151
-	 * Register the built-in autoloader
152
-	 *
153
-	 * @codeCoverageIgnore
154
-	 */
155
-	public static function register_autoloader() {
156
-		spl_autoload_register(array('Requests', 'autoloader'));
157
-	}
158
-
159
-	/**
160
-	 * Register a transport
161
-	 *
162
-	 * @param string $transport Transport class to add, must support the Requests_Transport interface
163
-	 */
164
-	public static function add_transport($transport) {
165
-		if (empty(self::$transports)) {
166
-			self::$transports = array(
167
-				'Requests_Transport_cURL',
168
-				'Requests_Transport_fsockopen',
169
-			);
170
-		}
171
-
172
-		self::$transports = array_merge(self::$transports, array($transport));
173
-	}
174
-
175
-	/**
176
-	 * Get a working transport
177
-	 *
178
-	 * @throws Requests_Exception If no valid transport is found (`notransport`)
179
-	 * @return Requests_Transport
180
-	 */
181
-	protected static function get_transport($capabilities = array()) {
182
-		// Caching code, don't bother testing coverage
183
-		// @codeCoverageIgnoreStart
184
-		// array of capabilities as a string to be used as an array key
185
-		ksort($capabilities);
186
-		$cap_string = serialize($capabilities);
187
-
188
-		// Don't search for a transport if it's already been done for these $capabilities
189
-		if (isset(self::$transport[$cap_string]) && self::$transport[$cap_string] !== null) {
190
-			return new self::$transport[$cap_string]();
191
-		}
192
-		// @codeCoverageIgnoreEnd
193
-
194
-		if (empty(self::$transports)) {
195
-			self::$transports = array(
196
-				'Requests_Transport_cURL',
197
-				'Requests_Transport_fsockopen',
198
-			);
199
-		}
200
-
201
-		// Find us a working transport
202
-		foreach (self::$transports as $class) {
203
-			if (!class_exists($class)) {
204
-				continue;
205
-			}
206
-
207
-			$result = call_user_func(array($class, 'test'), $capabilities);
208
-			if ($result) {
209
-				self::$transport[$cap_string] = $class;
210
-				break;
211
-			}
212
-		}
213
-		if (self::$transport[$cap_string] === null) {
214
-			throw new Requests_Exception('No working transports found', 'notransport', self::$transports);
215
-		}
216
-
217
-		return new self::$transport[$cap_string]();
218
-	}
219
-
220
-	/**#@+
22
+    /**
23
+     * POST method
24
+     *
25
+     * @var string
26
+     */
27
+    const POST = 'POST';
28
+
29
+    /**
30
+     * PUT method
31
+     *
32
+     * @var string
33
+     */
34
+    const PUT = 'PUT';
35
+
36
+    /**
37
+     * GET method
38
+     *
39
+     * @var string
40
+     */
41
+    const GET = 'GET';
42
+
43
+    /**
44
+     * HEAD method
45
+     *
46
+     * @var string
47
+     */
48
+    const HEAD = 'HEAD';
49
+
50
+    /**
51
+     * DELETE method
52
+     *
53
+     * @var string
54
+     */
55
+    const DELETE = 'DELETE';
56
+
57
+    /**
58
+     * OPTIONS method
59
+     *
60
+     * @var string
61
+     */
62
+    const OPTIONS = 'OPTIONS';
63
+
64
+    /**
65
+     * TRACE method
66
+     *
67
+     * @var string
68
+     */
69
+    const TRACE = 'TRACE';
70
+
71
+    /**
72
+     * PATCH method
73
+     *
74
+     * @link https://tools.ietf.org/html/rfc5789
75
+     * @var string
76
+     */
77
+    const PATCH = 'PATCH';
78
+
79
+    /**
80
+     * Default size of buffer size to read streams
81
+     *
82
+     * @var integer
83
+     */
84
+    const BUFFER_SIZE = 1160;
85
+
86
+    /**
87
+     * Current version of Requests
88
+     *
89
+     * @var string
90
+     */
91
+    const VERSION = '1.7';
92
+
93
+    /**
94
+     * Registered transport classes
95
+     *
96
+     * @var array
97
+     */
98
+    protected static $transports = array();
99
+
100
+    /**
101
+     * Selected transport name
102
+     *
103
+     * Use {@see get_transport()} instead
104
+     *
105
+     * @var array
106
+     */
107
+    public static $transport = array();
108
+
109
+    /**
110
+     * Default certificate path.
111
+     *
112
+     * @see Requests::get_certificate_path()
113
+     * @see Requests::set_certificate_path()
114
+     *
115
+     * @var string
116
+     */
117
+    protected static $certificate_path;
118
+
119
+    /**
120
+     * This is a static class, do not instantiate it
121
+     *
122
+     * @codeCoverageIgnore
123
+     */
124
+    private function __construct() {}
125
+
126
+    /**
127
+     * Autoloader for Requests
128
+     *
129
+     * Register this with {@see register_autoloader()} if you'd like to avoid
130
+     * having to create your own.
131
+     *
132
+     * (You can also use `spl_autoload_register` directly if you'd prefer.)
133
+     *
134
+     * @codeCoverageIgnore
135
+     *
136
+     * @param string $class Class name to load
137
+     */
138
+    public static function autoloader($class) {
139
+        // Check that the class starts with "Requests"
140
+        if (strpos($class, 'Requests') !== 0) {
141
+            return;
142
+        }
143
+
144
+        $file = str_replace('_', '/', $class);
145
+        if (file_exists(dirname(__FILE__) . '/' . $file . '.php')) {
146
+            require_once(dirname(__FILE__) . '/' . $file . '.php');
147
+        }
148
+    }
149
+
150
+    /**
151
+     * Register the built-in autoloader
152
+     *
153
+     * @codeCoverageIgnore
154
+     */
155
+    public static function register_autoloader() {
156
+        spl_autoload_register(array('Requests', 'autoloader'));
157
+    }
158
+
159
+    /**
160
+     * Register a transport
161
+     *
162
+     * @param string $transport Transport class to add, must support the Requests_Transport interface
163
+     */
164
+    public static function add_transport($transport) {
165
+        if (empty(self::$transports)) {
166
+            self::$transports = array(
167
+                'Requests_Transport_cURL',
168
+                'Requests_Transport_fsockopen',
169
+            );
170
+        }
171
+
172
+        self::$transports = array_merge(self::$transports, array($transport));
173
+    }
174
+
175
+    /**
176
+     * Get a working transport
177
+     *
178
+     * @throws Requests_Exception If no valid transport is found (`notransport`)
179
+     * @return Requests_Transport
180
+     */
181
+    protected static function get_transport($capabilities = array()) {
182
+        // Caching code, don't bother testing coverage
183
+        // @codeCoverageIgnoreStart
184
+        // array of capabilities as a string to be used as an array key
185
+        ksort($capabilities);
186
+        $cap_string = serialize($capabilities);
187
+
188
+        // Don't search for a transport if it's already been done for these $capabilities
189
+        if (isset(self::$transport[$cap_string]) && self::$transport[$cap_string] !== null) {
190
+            return new self::$transport[$cap_string]();
191
+        }
192
+        // @codeCoverageIgnoreEnd
193
+
194
+        if (empty(self::$transports)) {
195
+            self::$transports = array(
196
+                'Requests_Transport_cURL',
197
+                'Requests_Transport_fsockopen',
198
+            );
199
+        }
200
+
201
+        // Find us a working transport
202
+        foreach (self::$transports as $class) {
203
+            if (!class_exists($class)) {
204
+                continue;
205
+            }
206
+
207
+            $result = call_user_func(array($class, 'test'), $capabilities);
208
+            if ($result) {
209
+                self::$transport[$cap_string] = $class;
210
+                break;
211
+            }
212
+        }
213
+        if (self::$transport[$cap_string] === null) {
214
+            throw new Requests_Exception('No working transports found', 'notransport', self::$transports);
215
+        }
216
+
217
+        return new self::$transport[$cap_string]();
218
+    }
219
+
220
+    /**#@+
221 221
 	 * @see request()
222 222
 	 * @param string $url
223 223
 	 * @param array $headers
224 224
 	 * @param array $options
225 225
 	 * @return Requests_Response
226 226
 	 */
227
-	/**
228
-	 * Send a GET request
229
-	 */
230
-	public static function get($url, $headers = array(), $options = array()) {
231
-		return self::request($url, $headers, null, self::GET, $options);
232
-	}
233
-
234
-	/**
235
-	 * Send a HEAD request
236
-	 */
237
-	public static function head($url, $headers = array(), $options = array()) {
238
-		return self::request($url, $headers, null, self::HEAD, $options);
239
-	}
240
-
241
-	/**
242
-	 * Send a DELETE request
243
-	 */
244
-	public static function delete($url, $headers = array(), $options = array()) {
245
-		return self::request($url, $headers, null, self::DELETE, $options);
246
-	}
247
-
248
-	/**
249
-	 * Send a TRACE request
250
-	 */
251
-	public static function trace($url, $headers = array(), $options = array()) {
252
-		return self::request($url, $headers, null, self::TRACE, $options);
253
-	}
254
-	/**#@-*/
255
-
256
-	/**#@+
227
+    /**
228
+     * Send a GET request
229
+     */
230
+    public static function get($url, $headers = array(), $options = array()) {
231
+        return self::request($url, $headers, null, self::GET, $options);
232
+    }
233
+
234
+    /**
235
+     * Send a HEAD request
236
+     */
237
+    public static function head($url, $headers = array(), $options = array()) {
238
+        return self::request($url, $headers, null, self::HEAD, $options);
239
+    }
240
+
241
+    /**
242
+     * Send a DELETE request
243
+     */
244
+    public static function delete($url, $headers = array(), $options = array()) {
245
+        return self::request($url, $headers, null, self::DELETE, $options);
246
+    }
247
+
248
+    /**
249
+     * Send a TRACE request
250
+     */
251
+    public static function trace($url, $headers = array(), $options = array()) {
252
+        return self::request($url, $headers, null, self::TRACE, $options);
253
+    }
254
+    /**#@-*/
255
+
256
+    /**#@+
257 257
 	 * @see request()
258 258
 	 * @param string $url
259 259
 	 * @param array $headers
@@ -261,720 +261,720 @@  discard block
 block discarded – undo
261 261
 	 * @param array $options
262 262
 	 * @return Requests_Response
263 263
 	 */
264
-	/**
265
-	 * Send a POST request
266
-	 */
267
-	public static function post($url, $headers = array(), $data = array(), $options = array()) {
268
-		return self::request($url, $headers, $data, self::POST, $options);
269
-	}
270
-	/**
271
-	 * Send a PUT request
272
-	 */
273
-	public static function put($url, $headers = array(), $data = array(), $options = array()) {
274
-		return self::request($url, $headers, $data, self::PUT, $options);
275
-	}
276
-
277
-	/**
278
-	 * Send an OPTIONS request
279
-	 */
280
-	public static function options($url, $headers = array(), $data = array(), $options = array()) {
281
-		return self::request($url, $headers, $data, self::OPTIONS, $options);
282
-	}
283
-
284
-	/**
285
-	 * Send a PATCH request
286
-	 *
287
-	 * Note: Unlike {@see post} and {@see put}, `$headers` is required, as the
288
-	 * specification recommends that should send an ETag
289
-	 *
290
-	 * @link https://tools.ietf.org/html/rfc5789
291
-	 */
292
-	public static function patch($url, $headers, $data = array(), $options = array()) {
293
-		return self::request($url, $headers, $data, self::PATCH, $options);
294
-	}
295
-	/**#@-*/
296
-
297
-	/**
298
-	 * Main interface for HTTP requests
299
-	 *
300
-	 * This method initiates a request and sends it via a transport before
301
-	 * parsing.
302
-	 *
303
-	 * The `$options` parameter takes an associative array with the following
304
-	 * options:
305
-	 *
306
-	 * - `timeout`: How long should we wait for a response?
307
-	 *    Note: for cURL, a minimum of 1 second applies, as DNS resolution
308
-	 *    operates at second-resolution only.
309
-	 *    (float, seconds with a millisecond precision, default: 10, example: 0.01)
310
-	 * - `connect_timeout`: How long should we wait while trying to connect?
311
-	 *    (float, seconds with a millisecond precision, default: 10, example: 0.01)
312
-	 * - `useragent`: Useragent to send to the server
313
-	 *    (string, default: php-requests/$version)
314
-	 * - `follow_redirects`: Should we follow 3xx redirects?
315
-	 *    (boolean, default: true)
316
-	 * - `redirects`: How many times should we redirect before erroring?
317
-	 *    (integer, default: 10)
318
-	 * - `blocking`: Should we block processing on this request?
319
-	 *    (boolean, default: true)
320
-	 * - `filename`: File to stream the body to instead.
321
-	 *    (string|boolean, default: false)
322
-	 * - `auth`: Authentication handler or array of user/password details to use
323
-	 *    for Basic authentication
324
-	 *    (Requests_Auth|array|boolean, default: false)
325
-	 * - `proxy`: Proxy details to use for proxy by-passing and authentication
326
-	 *    (Requests_Proxy|array|string|boolean, default: false)
327
-	 * - `max_bytes`: Limit for the response body size.
328
-	 *    (integer|boolean, default: false)
329
-	 * - `idn`: Enable IDN parsing
330
-	 *    (boolean, default: true)
331
-	 * - `transport`: Custom transport. Either a class name, or a
332
-	 *    transport object. Defaults to the first working transport from
333
-	 *    {@see getTransport()}
334
-	 *    (string|Requests_Transport, default: {@see getTransport()})
335
-	 * - `hooks`: Hooks handler.
336
-	 *    (Requests_Hooker, default: new Requests_Hooks())
337
-	 * - `verify`: Should we verify SSL certificates? Allows passing in a custom
338
-	 *    certificate file as a string. (Using true uses the system-wide root
339
-	 *    certificate store instead, but this may have different behaviour
340
-	 *    across transports.)
341
-	 *    (string|boolean, default: library/Requests/Transport/cacert.pem)
342
-	 * - `verifyname`: Should we verify the common name in the SSL certificate?
343
-	 *    (boolean: default, true)
344
-	 * - `data_format`: How should we send the `$data` parameter?
345
-	 *    (string, one of 'query' or 'body', default: 'query' for
346
-	 *    HEAD/GET/DELETE, 'body' for POST/PUT/OPTIONS/PATCH)
347
-	 *
348
-	 * @throws Requests_Exception On invalid URLs (`nonhttp`)
349
-	 *
350
-	 * @param string $url URL to request
351
-	 * @param array $headers Extra headers to send with the request
352
-	 * @param array|null $data Data to send either as a query string for GET/HEAD requests, or in the body for POST requests
353
-	 * @param string $type HTTP request type (use Requests constants)
354
-	 * @param array $options Options for the request (see description for more information)
355
-	 * @return Requests_Response
356
-	 */
357
-	public static function request($url, $headers = array(), $data = array(), $type = self::GET, $options = array()) {
358
-		if (empty($options['type'])) {
359
-			$options['type'] = $type;
360
-		}
361
-		$options = array_merge(self::get_default_options(), $options);
362
-
363
-		self::set_defaults($url, $headers, $data, $type, $options);
364
-
365
-		$options['hooks']->dispatch('requests.before_request', array(&$url, &$headers, &$data, &$type, &$options));
366
-
367
-		if (!empty($options['transport'])) {
368
-			$transport = $options['transport'];
369
-
370
-			if (is_string($options['transport'])) {
371
-				$transport = new $transport();
372
-			}
373
-		}
374
-		else {
375
-			$need_ssl = (0 === stripos($url, 'https://'));
376
-			$capabilities = array('ssl' => $need_ssl);
377
-			$transport = self::get_transport($capabilities);
378
-		}
379
-		$response = $transport->request($url, $headers, $data, $options);
380
-
381
-		$options['hooks']->dispatch('requests.before_parse', array(&$response, $url, $headers, $data, $type, $options));
382
-
383
-		return self::parse_response($response, $url, $headers, $data, $options);
384
-	}
385
-
386
-	/**
387
-	 * Send multiple HTTP requests simultaneously
388
-	 *
389
-	 * The `$requests` parameter takes an associative or indexed array of
390
-	 * request fields. The key of each request can be used to match up the
391
-	 * request with the returned data, or with the request passed into your
392
-	 * `multiple.request.complete` callback.
393
-	 *
394
-	 * The request fields value is an associative array with the following keys:
395
-	 *
396
-	 * - `url`: Request URL Same as the `$url` parameter to
397
-	 *    {@see Requests::request}
398
-	 *    (string, required)
399
-	 * - `headers`: Associative array of header fields. Same as the `$headers`
400
-	 *    parameter to {@see Requests::request}
401
-	 *    (array, default: `array()`)
402
-	 * - `data`: Associative array of data fields or a string. Same as the
403
-	 *    `$data` parameter to {@see Requests::request}
404
-	 *    (array|string, default: `array()`)
405
-	 * - `type`: HTTP request type (use Requests constants). Same as the `$type`
406
-	 *    parameter to {@see Requests::request}
407
-	 *    (string, default: `Requests::GET`)
408
-	 * - `cookies`: Associative array of cookie name to value, or cookie jar.
409
-	 *    (array|Requests_Cookie_Jar)
410
-	 *
411
-	 * If the `$options` parameter is specified, individual requests will
412
-	 * inherit options from it. This can be used to use a single hooking system,
413
-	 * or set all the types to `Requests::POST`, for example.
414
-	 *
415
-	 * In addition, the `$options` parameter takes the following global options:
416
-	 *
417
-	 * - `complete`: A callback for when a request is complete. Takes two
418
-	 *    parameters, a Requests_Response/Requests_Exception reference, and the
419
-	 *    ID from the request array (Note: this can also be overridden on a
420
-	 *    per-request basis, although that's a little silly)
421
-	 *    (callback)
422
-	 *
423
-	 * @param array $requests Requests data (see description for more information)
424
-	 * @param array $options Global and default options (see {@see Requests::request})
425
-	 * @return array Responses (either Requests_Response or a Requests_Exception object)
426
-	 */
427
-	public static function request_multiple($requests, $options = array()) {
428
-		$options = array_merge(self::get_default_options(true), $options);
429
-
430
-		if (!empty($options['hooks'])) {
431
-			$options['hooks']->register('transport.internal.parse_response', array('Requests', 'parse_multiple'));
432
-			if (!empty($options['complete'])) {
433
-				$options['hooks']->register('multiple.request.complete', $options['complete']);
434
-			}
435
-		}
436
-
437
-		foreach ($requests as $id => &$request) {
438
-			if (!isset($request['headers'])) {
439
-				$request['headers'] = array();
440
-			}
441
-			if (!isset($request['data'])) {
442
-				$request['data'] = array();
443
-			}
444
-			if (!isset($request['type'])) {
445
-				$request['type'] = self::GET;
446
-			}
447
-			if (!isset($request['options'])) {
448
-				$request['options'] = $options;
449
-				$request['options']['type'] = $request['type'];
450
-			}
451
-			else {
452
-				if (empty($request['options']['type'])) {
453
-					$request['options']['type'] = $request['type'];
454
-				}
455
-				$request['options'] = array_merge($options, $request['options']);
456
-			}
457
-
458
-			self::set_defaults($request['url'], $request['headers'], $request['data'], $request['type'], $request['options']);
459
-
460
-			// Ensure we only hook in once
461
-			if ($request['options']['hooks'] !== $options['hooks']) {
462
-				$request['options']['hooks']->register('transport.internal.parse_response', array('Requests', 'parse_multiple'));
463
-				if (!empty($request['options']['complete'])) {
464
-					$request['options']['hooks']->register('multiple.request.complete', $request['options']['complete']);
465
-				}
466
-			}
467
-		}
468
-		unset($request);
469
-
470
-		if (!empty($options['transport'])) {
471
-			$transport = $options['transport'];
472
-
473
-			if (is_string($options['transport'])) {
474
-				$transport = new $transport();
475
-			}
476
-		}
477
-		else {
478
-			$transport = self::get_transport();
479
-		}
480
-		$responses = $transport->request_multiple($requests, $options);
481
-
482
-		foreach ($responses as $id => &$response) {
483
-			// If our hook got messed with somehow, ensure we end up with the
484
-			// correct response
485
-			if (is_string($response)) {
486
-				$request = $requests[$id];
487
-				self::parse_multiple($response, $request);
488
-				$request['options']['hooks']->dispatch('multiple.request.complete', array(&$response, $id));
489
-			}
490
-		}
491
-
492
-		return $responses;
493
-	}
494
-
495
-	/**
496
-	 * Get the default options
497
-	 *
498
-	 * @see Requests::request() for values returned by this method
499
-	 * @param boolean $multirequest Is this a multirequest?
500
-	 * @return array Default option values
501
-	 */
502
-	protected static function get_default_options($multirequest = false) {
503
-		$defaults = array(
504
-			'timeout' => 10,
505
-			'connect_timeout' => 10,
506
-			'useragent' => 'php-requests/' . self::VERSION,
507
-			'protocol_version' => 1.1,
508
-			'redirected' => 0,
509
-			'redirects' => 10,
510
-			'follow_redirects' => true,
511
-			'blocking' => true,
512
-			'type' => self::GET,
513
-			'filename' => false,
514
-			'auth' => false,
515
-			'proxy' => false,
516
-			'cookies' => false,
517
-			'max_bytes' => false,
518
-			'idn' => true,
519
-			'hooks' => null,
520
-			'transport' => null,
521
-			'verify' => Requests::get_certificate_path(),
522
-			'verifyname' => true,
523
-		);
524
-		if ($multirequest !== false) {
525
-			$defaults['complete'] = null;
526
-		}
527
-		return $defaults;
528
-	}
529
-
530
-	/**
531
-	 * Get default certificate path.
532
-	 *
533
-	 * @return string Default certificate path.
534
-	 */
535
-	public static function get_certificate_path() {
536
-		if ( ! empty( Requests::$certificate_path ) ) {
537
-			return Requests::$certificate_path;
538
-		}
539
-
540
-		return dirname(__FILE__) . '/Requests/Transport/cacert.pem';
541
-	}
542
-
543
-	/**
544
-	 * Set default certificate path.
545
-	 *
546
-	 * @param string $path Certificate path, pointing to a PEM file.
547
-	 */
548
-	public static function set_certificate_path( $path ) {
549
-		Requests::$certificate_path = $path;
550
-	}
551
-
552
-	/**
553
-	 * Set the default values
554
-	 *
555
-	 * @param string $url URL to request
556
-	 * @param array $headers Extra headers to send with the request
557
-	 * @param array|null $data Data to send either as a query string for GET/HEAD requests, or in the body for POST requests
558
-	 * @param string $type HTTP request type
559
-	 * @param array $options Options for the request
560
-	 * @return array $options
561
-	 */
562
-	protected static function set_defaults(&$url, &$headers, &$data, &$type, &$options) {
563
-		if (!preg_match('/^http(s)?:\/\//i', $url, $matches)) {
564
-			throw new Requests_Exception('Only HTTP(S) requests are handled.', 'nonhttp', $url);
565
-		}
566
-
567
-		if (empty($options['hooks'])) {
568
-			$options['hooks'] = new Requests_Hooks();
569
-		}
570
-
571
-		if (is_array($options['auth'])) {
572
-			$options['auth'] = new Requests_Auth_Basic($options['auth']);
573
-		}
574
-		if ($options['auth'] !== false) {
575
-			$options['auth']->register($options['hooks']);
576
-		}
577
-
578
-		if (is_string($options['proxy']) || is_array($options['proxy'])) {
579
-			$options['proxy'] = new Requests_Proxy_HTTP($options['proxy']);
580
-		}
581
-		if ($options['proxy'] !== false) {
582
-			$options['proxy']->register($options['hooks']);
583
-		}
584
-
585
-		if (is_array($options['cookies'])) {
586
-			$options['cookies'] = new Requests_Cookie_Jar($options['cookies']);
587
-		}
588
-		elseif (empty($options['cookies'])) {
589
-			$options['cookies'] = new Requests_Cookie_Jar();
590
-		}
591
-		if ($options['cookies'] !== false) {
592
-			$options['cookies']->register($options['hooks']);
593
-		}
594
-
595
-		if ($options['idn'] !== false) {
596
-			$iri = new Requests_IRI($url);
597
-			$iri->host = Requests_IDNAEncoder::encode($iri->ihost);
598
-			$url = $iri->uri;
599
-		}
600
-
601
-		// Massage the type to ensure we support it.
602
-		$type = strtoupper($type);
603
-
604
-		if (!isset($options['data_format'])) {
605
-			if (in_array($type, array(self::HEAD, self::GET, self::DELETE))) {
606
-				$options['data_format'] = 'query';
607
-			}
608
-			else {
609
-				$options['data_format'] = 'body';
610
-			}
611
-		}
612
-	}
613
-
614
-	/**
615
-	 * HTTP response parser
616
-	 *
617
-	 * @throws Requests_Exception On missing head/body separator (`requests.no_crlf_separator`)
618
-	 * @throws Requests_Exception On missing head/body separator (`noversion`)
619
-	 * @throws Requests_Exception On missing head/body separator (`toomanyredirects`)
620
-	 *
621
-	 * @param string $headers Full response text including headers and body
622
-	 * @param string $url Original request URL
623
-	 * @param array $req_headers Original $headers array passed to {@link request()}, in case we need to follow redirects
624
-	 * @param array $req_data Original $data array passed to {@link request()}, in case we need to follow redirects
625
-	 * @param array $options Original $options array passed to {@link request()}, in case we need to follow redirects
626
-	 * @return Requests_Response
627
-	 */
628
-	protected static function parse_response($headers, $url, $req_headers, $req_data, $options) {
629
-		$return = new Requests_Response();
630
-		if (!$options['blocking']) {
631
-			return $return;
632
-		}
633
-
634
-		$return->raw = $headers;
635
-		$return->url = $url;
636
-
637
-		if (!$options['filename']) {
638
-			if (($pos = strpos($headers, "\r\n\r\n")) === false) {
639
-				// Crap!
640
-				throw new Requests_Exception('Missing header/body separator', 'requests.no_crlf_separator');
641
-			}
642
-
643
-			$headers = substr($return->raw, 0, $pos);
644
-			$return->body = substr($return->raw, $pos + strlen("\n\r\n\r"));
645
-		}
646
-		else {
647
-			$return->body = '';
648
-		}
649
-		// Pretend CRLF = LF for compatibility (RFC 2616, section 19.3)
650
-		$headers = str_replace("\r\n", "\n", $headers);
651
-		// Unfold headers (replace [CRLF] 1*( SP | HT ) with SP) as per RFC 2616 (section 2.2)
652
-		$headers = preg_replace('/\n[ \t]/', ' ', $headers);
653
-		$headers = explode("\n", $headers);
654
-		preg_match('#^HTTP/(1\.\d)[ \t]+(\d+)#i', array_shift($headers), $matches);
655
-		if (empty($matches)) {
656
-			throw new Requests_Exception('Response could not be parsed', 'noversion', $headers);
657
-		}
658
-		$return->protocol_version = (float) $matches[1];
659
-		$return->status_code = (int) $matches[2];
660
-		if ($return->status_code >= 200 && $return->status_code < 300) {
661
-			$return->success = true;
662
-		}
663
-
664
-		foreach ($headers as $header) {
665
-			list($key, $value) = explode(':', $header, 2);
666
-			$value = trim($value);
667
-			preg_replace('#(\s+)#i', ' ', $value);
668
-			$return->headers[$key] = $value;
669
-		}
670
-		if (isset($return->headers['transfer-encoding'])) {
671
-			$return->body = self::decode_chunked($return->body);
672
-			unset($return->headers['transfer-encoding']);
673
-		}
674
-		if (isset($return->headers['content-encoding'])) {
675
-			$return->body = self::decompress($return->body);
676
-		}
677
-
678
-		//fsockopen and cURL compatibility
679
-		if (isset($return->headers['connection'])) {
680
-			unset($return->headers['connection']);
681
-		}
682
-
683
-		$options['hooks']->dispatch('requests.before_redirect_check', array(&$return, $req_headers, $req_data, $options));
684
-
685
-		if ($return->is_redirect() && $options['follow_redirects'] === true) {
686
-			if (isset($return->headers['location']) && $options['redirected'] < $options['redirects']) {
687
-				if ($return->status_code === 303) {
688
-					$options['type'] = self::GET;
689
-				}
690
-				$options['redirected']++;
691
-				$location = $return->headers['location'];
692
-				if (strpos($location, 'http://') !== 0 && strpos($location, 'https://') !== 0) {
693
-					// relative redirect, for compatibility make it absolute
694
-					$location = Requests_IRI::absolutize($url, $location);
695
-					$location = $location->uri;
696
-				}
697
-
698
-				$hook_args = array(
699
-					&$location,
700
-					&$req_headers,
701
-					&$req_data,
702
-					&$options,
703
-					$return
704
-				);
705
-				$options['hooks']->dispatch('requests.before_redirect', $hook_args);
706
-				$redirected = self::request($location, $req_headers, $req_data, $options['type'], $options);
707
-				$redirected->history[] = $return;
708
-				return $redirected;
709
-			}
710
-			elseif ($options['redirected'] >= $options['redirects']) {
711
-				throw new Requests_Exception('Too many redirects', 'toomanyredirects', $return);
712
-			}
713
-		}
714
-
715
-		$return->redirects = $options['redirected'];
716
-
717
-		$options['hooks']->dispatch('requests.after_request', array(&$return, $req_headers, $req_data, $options));
718
-		return $return;
719
-	}
720
-
721
-	/**
722
-	 * Callback for `transport.internal.parse_response`
723
-	 *
724
-	 * Internal use only. Converts a raw HTTP response to a Requests_Response
725
-	 * while still executing a multiple request.
726
-	 *
727
-	 * @param string $response Full response text including headers and body (will be overwritten with Response instance)
728
-	 * @param array $request Request data as passed into {@see Requests::request_multiple()}
729
-	 * @return null `$response` is either set to a Requests_Response instance, or a Requests_Exception object
730
-	 */
731
-	public static function parse_multiple(&$response, $request) {
732
-		try {
733
-			$url = $request['url'];
734
-			$headers = $request['headers'];
735
-			$data = $request['data'];
736
-			$options = $request['options'];
737
-			$response = self::parse_response($response, $url, $headers, $data, $options);
738
-		}
739
-		catch (Requests_Exception $e) {
740
-			$response = $e;
741
-		}
742
-	}
743
-
744
-	/**
745
-	 * Decoded a chunked body as per RFC 2616
746
-	 *
747
-	 * @see https://tools.ietf.org/html/rfc2616#section-3.6.1
748
-	 * @param string $data Chunked body
749
-	 * @return string Decoded body
750
-	 */
751
-	protected static function decode_chunked($data) {
752
-		if (!preg_match('/^([0-9a-f]+)(?:;(?:[\w-]*)(?:=(?:(?:[\w-]*)*|"(?:[^\r\n])*"))?)*\r\n/i', trim($data))) {
753
-			return $data;
754
-		}
755
-
756
-
757
-
758
-		$decoded = '';
759
-		$encoded = $data;
760
-
761
-		while (true) {
762
-			$is_chunked = (bool) preg_match('/^([0-9a-f]+)(?:;(?:[\w-]*)(?:=(?:(?:[\w-]*)*|"(?:[^\r\n])*"))?)*\r\n/i', $encoded, $matches);
763
-			if (!$is_chunked) {
764
-				// Looks like it's not chunked after all
765
-				return $data;
766
-			}
767
-
768
-			$length = hexdec(trim($matches[1]));
769
-			if ($length === 0) {
770
-				// Ignore trailer headers
771
-				return $decoded;
772
-			}
773
-
774
-			$chunk_length = strlen($matches[0]);
775
-			$decoded .= substr($encoded, $chunk_length, $length);
776
-			$encoded = substr($encoded, $chunk_length + $length + 2);
777
-
778
-			if (trim($encoded) === '0' || empty($encoded)) {
779
-				return $decoded;
780
-			}
781
-		}
782
-
783
-		// We'll never actually get down here
784
-		// @codeCoverageIgnoreStart
785
-	}
786
-	// @codeCoverageIgnoreEnd
787
-
788
-	/**
789
-	 * Convert a key => value array to a 'key: value' array for headers
790
-	 *
791
-	 * @param array $array Dictionary of header values
792
-	 * @return array List of headers
793
-	 */
794
-	public static function flatten($array) {
795
-		$return = array();
796
-		foreach ($array as $key => $value) {
797
-			$return[] = sprintf('%s: %s', $key, $value);
798
-		}
799
-		return $return;
800
-	}
801
-
802
-	/**
803
-	 * Convert a key => value array to a 'key: value' array for headers
804
-	 *
805
-	 * @codeCoverageIgnore
806
-	 * @deprecated Misspelling of {@see Requests::flatten}
807
-	 * @param array $array Dictionary of header values
808
-	 * @return array List of headers
809
-	 */
810
-	public static function flattern($array) {
811
-		return self::flatten($array);
812
-	}
813
-
814
-	/**
815
-	 * Decompress an encoded body
816
-	 *
817
-	 * Implements gzip, compress and deflate. Guesses which it is by attempting
818
-	 * to decode.
819
-	 *
820
-	 * @param string $data Compressed data in one of the above formats
821
-	 * @return string Decompressed string
822
-	 */
823
-	public static function decompress($data) {
824
-		if (substr($data, 0, 2) !== "\x1f\x8b" && substr($data, 0, 2) !== "\x78\x9c") {
825
-			// Not actually compressed. Probably cURL ruining this for us.
826
-			return $data;
827
-		}
828
-
829
-		if (function_exists('gzdecode') && ($decoded = @gzdecode($data)) !== false) {
830
-			return $decoded;
831
-		}
832
-		elseif (function_exists('gzinflate') && ($decoded = @gzinflate($data)) !== false) {
833
-			return $decoded;
834
-		}
835
-		elseif (($decoded = self::compatible_gzinflate($data)) !== false) {
836
-			return $decoded;
837
-		}
838
-		elseif (function_exists('gzuncompress') && ($decoded = @gzuncompress($data)) !== false) {
839
-			return $decoded;
840
-		}
841
-
842
-		return $data;
843
-	}
844
-
845
-	/**
846
-	 * Decompression of deflated string while staying compatible with the majority of servers.
847
-	 *
848
-	 * Certain Servers will return deflated data with headers which PHP's gzinflate()
849
-	 * function cannot handle out of the box. The following function has been created from
850
-	 * various snippets on the gzinflate() PHP documentation.
851
-	 *
852
-	 * Warning: Magic numbers within. Due to the potential different formats that the compressed
853
-	 * data may be returned in, some "magic offsets" are needed to ensure proper decompression
854
-	 * takes place. For a simple progmatic way to determine the magic offset in use, see:
855
-	 * https://core.trac.wordpress.org/ticket/18273
856
-	 *
857
-	 * @since 2.8.1
858
-	 * @link https://core.trac.wordpress.org/ticket/18273
859
-	 * @link https://secure.php.net/manual/en/function.gzinflate.php#70875
860
-	 * @link https://secure.php.net/manual/en/function.gzinflate.php#77336
861
-	 *
862
-	 * @param string $gzData String to decompress.
863
-	 * @return string|bool False on failure.
864
-	 */
865
-	public static function compatible_gzinflate($gzData) {
866
-		// Compressed data might contain a full zlib header, if so strip it for
867
-		// gzinflate()
868
-		if (substr($gzData, 0, 3) == "\x1f\x8b\x08") {
869
-			$i = 10;
870
-			$flg = ord(substr($gzData, 3, 1));
871
-			if ($flg > 0) {
872
-				if ($flg & 4) {
873
-					list($xlen) = unpack('v', substr($gzData, $i, 2));
874
-					$i = $i + 2 + $xlen;
875
-				}
876
-				if ($flg & 8) {
877
-					$i = strpos($gzData, "\0", $i) + 1;
878
-				}
879
-				if ($flg & 16) {
880
-					$i = strpos($gzData, "\0", $i) + 1;
881
-				}
882
-				if ($flg & 2) {
883
-					$i = $i + 2;
884
-				}
885
-			}
886
-			$decompressed = self::compatible_gzinflate(substr($gzData, $i));
887
-			if (false !== $decompressed) {
888
-				return $decompressed;
889
-			}
890
-		}
891
-
892
-		// If the data is Huffman Encoded, we must first strip the leading 2
893
-		// byte Huffman marker for gzinflate()
894
-		// The response is Huffman coded by many compressors such as
895
-		// java.util.zip.Deflater, Ruby’s Zlib::Deflate, and .NET's
896
-		// System.IO.Compression.DeflateStream.
897
-		//
898
-		// See https://decompres.blogspot.com/ for a quick explanation of this
899
-		// data type
900
-		$huffman_encoded = false;
901
-
902
-		// low nibble of first byte should be 0x08
903
-		list(, $first_nibble)    = unpack('h', $gzData);
904
-
905
-		// First 2 bytes should be divisible by 0x1F
906
-		list(, $first_two_bytes) = unpack('n', $gzData);
907
-
908
-		if (0x08 == $first_nibble && 0 == ($first_two_bytes % 0x1F)) {
909
-			$huffman_encoded = true;
910
-		}
911
-
912
-		if ($huffman_encoded) {
913
-			if (false !== ($decompressed = @gzinflate(substr($gzData, 2)))) {
914
-				return $decompressed;
915
-			}
916
-		}
917
-
918
-		if ("\x50\x4b\x03\x04" == substr($gzData, 0, 4)) {
919
-			// ZIP file format header
920
-			// Offset 6: 2 bytes, General-purpose field
921
-			// Offset 26: 2 bytes, filename length
922
-			// Offset 28: 2 bytes, optional field length
923
-			// Offset 30: Filename field, followed by optional field, followed
924
-			// immediately by data
925
-			list(, $general_purpose_flag) = unpack('v', substr($gzData, 6, 2));
926
-
927
-			// If the file has been compressed on the fly, 0x08 bit is set of
928
-			// the general purpose field. We can use this to differentiate
929
-			// between a compressed document, and a ZIP file
930
-			$zip_compressed_on_the_fly = (0x08 == (0x08 & $general_purpose_flag));
931
-
932
-			if (!$zip_compressed_on_the_fly) {
933
-				// Don't attempt to decode a compressed zip file
934
-				return $gzData;
935
-			}
936
-
937
-			// Determine the first byte of data, based on the above ZIP header
938
-			// offsets:
939
-			$first_file_start = array_sum(unpack('v2', substr($gzData, 26, 4)));
940
-			if (false !== ($decompressed = @gzinflate(substr($gzData, 30 + $first_file_start)))) {
941
-				return $decompressed;
942
-			}
943
-			return false;
944
-		}
945
-
946
-		// Finally fall back to straight gzinflate
947
-		if (false !== ($decompressed = @gzinflate($gzData))) {
948
-			return $decompressed;
949
-		}
950
-
951
-		// Fallback for all above failing, not expected, but included for
952
-		// debugging and preventing regressions and to track stats
953
-		if (false !== ($decompressed = @gzinflate(substr($gzData, 2)))) {
954
-			return $decompressed;
955
-		}
956
-
957
-		return false;
958
-	}
959
-
960
-	public static function match_domain($host, $reference) {
961
-		// Check for a direct match
962
-		if ($host === $reference) {
963
-			return true;
964
-		}
965
-
966
-		// Calculate the valid wildcard match if the host is not an IP address
967
-		// Also validates that the host has 3 parts or more, as per Firefox's
968
-		// ruleset.
969
-		$parts = explode('.', $host);
970
-		if (ip2long($host) === false && count($parts) >= 3) {
971
-			$parts[0] = '*';
972
-			$wildcard = implode('.', $parts);
973
-			if ($wildcard === $reference) {
974
-				return true;
975
-			}
976
-		}
977
-
978
-		return false;
979
-	}
264
+    /**
265
+     * Send a POST request
266
+     */
267
+    public static function post($url, $headers = array(), $data = array(), $options = array()) {
268
+        return self::request($url, $headers, $data, self::POST, $options);
269
+    }
270
+    /**
271
+     * Send a PUT request
272
+     */
273
+    public static function put($url, $headers = array(), $data = array(), $options = array()) {
274
+        return self::request($url, $headers, $data, self::PUT, $options);
275
+    }
276
+
277
+    /**
278
+     * Send an OPTIONS request
279
+     */
280
+    public static function options($url, $headers = array(), $data = array(), $options = array()) {
281
+        return self::request($url, $headers, $data, self::OPTIONS, $options);
282
+    }
283
+
284
+    /**
285
+     * Send a PATCH request
286
+     *
287
+     * Note: Unlike {@see post} and {@see put}, `$headers` is required, as the
288
+     * specification recommends that should send an ETag
289
+     *
290
+     * @link https://tools.ietf.org/html/rfc5789
291
+     */
292
+    public static function patch($url, $headers, $data = array(), $options = array()) {
293
+        return self::request($url, $headers, $data, self::PATCH, $options);
294
+    }
295
+    /**#@-*/
296
+
297
+    /**
298
+     * Main interface for HTTP requests
299
+     *
300
+     * This method initiates a request and sends it via a transport before
301
+     * parsing.
302
+     *
303
+     * The `$options` parameter takes an associative array with the following
304
+     * options:
305
+     *
306
+     * - `timeout`: How long should we wait for a response?
307
+     *    Note: for cURL, a minimum of 1 second applies, as DNS resolution
308
+     *    operates at second-resolution only.
309
+     *    (float, seconds with a millisecond precision, default: 10, example: 0.01)
310
+     * - `connect_timeout`: How long should we wait while trying to connect?
311
+     *    (float, seconds with a millisecond precision, default: 10, example: 0.01)
312
+     * - `useragent`: Useragent to send to the server
313
+     *    (string, default: php-requests/$version)
314
+     * - `follow_redirects`: Should we follow 3xx redirects?
315
+     *    (boolean, default: true)
316
+     * - `redirects`: How many times should we redirect before erroring?
317
+     *    (integer, default: 10)
318
+     * - `blocking`: Should we block processing on this request?
319
+     *    (boolean, default: true)
320
+     * - `filename`: File to stream the body to instead.
321
+     *    (string|boolean, default: false)
322
+     * - `auth`: Authentication handler or array of user/password details to use
323
+     *    for Basic authentication
324
+     *    (Requests_Auth|array|boolean, default: false)
325
+     * - `proxy`: Proxy details to use for proxy by-passing and authentication
326
+     *    (Requests_Proxy|array|string|boolean, default: false)
327
+     * - `max_bytes`: Limit for the response body size.
328
+     *    (integer|boolean, default: false)
329
+     * - `idn`: Enable IDN parsing
330
+     *    (boolean, default: true)
331
+     * - `transport`: Custom transport. Either a class name, or a
332
+     *    transport object. Defaults to the first working transport from
333
+     *    {@see getTransport()}
334
+     *    (string|Requests_Transport, default: {@see getTransport()})
335
+     * - `hooks`: Hooks handler.
336
+     *    (Requests_Hooker, default: new Requests_Hooks())
337
+     * - `verify`: Should we verify SSL certificates? Allows passing in a custom
338
+     *    certificate file as a string. (Using true uses the system-wide root
339
+     *    certificate store instead, but this may have different behaviour
340
+     *    across transports.)
341
+     *    (string|boolean, default: library/Requests/Transport/cacert.pem)
342
+     * - `verifyname`: Should we verify the common name in the SSL certificate?
343
+     *    (boolean: default, true)
344
+     * - `data_format`: How should we send the `$data` parameter?
345
+     *    (string, one of 'query' or 'body', default: 'query' for
346
+     *    HEAD/GET/DELETE, 'body' for POST/PUT/OPTIONS/PATCH)
347
+     *
348
+     * @throws Requests_Exception On invalid URLs (`nonhttp`)
349
+     *
350
+     * @param string $url URL to request
351
+     * @param array $headers Extra headers to send with the request
352
+     * @param array|null $data Data to send either as a query string for GET/HEAD requests, or in the body for POST requests
353
+     * @param string $type HTTP request type (use Requests constants)
354
+     * @param array $options Options for the request (see description for more information)
355
+     * @return Requests_Response
356
+     */
357
+    public static function request($url, $headers = array(), $data = array(), $type = self::GET, $options = array()) {
358
+        if (empty($options['type'])) {
359
+            $options['type'] = $type;
360
+        }
361
+        $options = array_merge(self::get_default_options(), $options);
362
+
363
+        self::set_defaults($url, $headers, $data, $type, $options);
364
+
365
+        $options['hooks']->dispatch('requests.before_request', array(&$url, &$headers, &$data, &$type, &$options));
366
+
367
+        if (!empty($options['transport'])) {
368
+            $transport = $options['transport'];
369
+
370
+            if (is_string($options['transport'])) {
371
+                $transport = new $transport();
372
+            }
373
+        }
374
+        else {
375
+            $need_ssl = (0 === stripos($url, 'https://'));
376
+            $capabilities = array('ssl' => $need_ssl);
377
+            $transport = self::get_transport($capabilities);
378
+        }
379
+        $response = $transport->request($url, $headers, $data, $options);
380
+
381
+        $options['hooks']->dispatch('requests.before_parse', array(&$response, $url, $headers, $data, $type, $options));
382
+
383
+        return self::parse_response($response, $url, $headers, $data, $options);
384
+    }
385
+
386
+    /**
387
+     * Send multiple HTTP requests simultaneously
388
+     *
389
+     * The `$requests` parameter takes an associative or indexed array of
390
+     * request fields. The key of each request can be used to match up the
391
+     * request with the returned data, or with the request passed into your
392
+     * `multiple.request.complete` callback.
393
+     *
394
+     * The request fields value is an associative array with the following keys:
395
+     *
396
+     * - `url`: Request URL Same as the `$url` parameter to
397
+     *    {@see Requests::request}
398
+     *    (string, required)
399
+     * - `headers`: Associative array of header fields. Same as the `$headers`
400
+     *    parameter to {@see Requests::request}
401
+     *    (array, default: `array()`)
402
+     * - `data`: Associative array of data fields or a string. Same as the
403
+     *    `$data` parameter to {@see Requests::request}
404
+     *    (array|string, default: `array()`)
405
+     * - `type`: HTTP request type (use Requests constants). Same as the `$type`
406
+     *    parameter to {@see Requests::request}
407
+     *    (string, default: `Requests::GET`)
408
+     * - `cookies`: Associative array of cookie name to value, or cookie jar.
409
+     *    (array|Requests_Cookie_Jar)
410
+     *
411
+     * If the `$options` parameter is specified, individual requests will
412
+     * inherit options from it. This can be used to use a single hooking system,
413
+     * or set all the types to `Requests::POST`, for example.
414
+     *
415
+     * In addition, the `$options` parameter takes the following global options:
416
+     *
417
+     * - `complete`: A callback for when a request is complete. Takes two
418
+     *    parameters, a Requests_Response/Requests_Exception reference, and the
419
+     *    ID from the request array (Note: this can also be overridden on a
420
+     *    per-request basis, although that's a little silly)
421
+     *    (callback)
422
+     *
423
+     * @param array $requests Requests data (see description for more information)
424
+     * @param array $options Global and default options (see {@see Requests::request})
425
+     * @return array Responses (either Requests_Response or a Requests_Exception object)
426
+     */
427
+    public static function request_multiple($requests, $options = array()) {
428
+        $options = array_merge(self::get_default_options(true), $options);
429
+
430
+        if (!empty($options['hooks'])) {
431
+            $options['hooks']->register('transport.internal.parse_response', array('Requests', 'parse_multiple'));
432
+            if (!empty($options['complete'])) {
433
+                $options['hooks']->register('multiple.request.complete', $options['complete']);
434
+            }
435
+        }
436
+
437
+        foreach ($requests as $id => &$request) {
438
+            if (!isset($request['headers'])) {
439
+                $request['headers'] = array();
440
+            }
441
+            if (!isset($request['data'])) {
442
+                $request['data'] = array();
443
+            }
444
+            if (!isset($request['type'])) {
445
+                $request['type'] = self::GET;
446
+            }
447
+            if (!isset($request['options'])) {
448
+                $request['options'] = $options;
449
+                $request['options']['type'] = $request['type'];
450
+            }
451
+            else {
452
+                if (empty($request['options']['type'])) {
453
+                    $request['options']['type'] = $request['type'];
454
+                }
455
+                $request['options'] = array_merge($options, $request['options']);
456
+            }
457
+
458
+            self::set_defaults($request['url'], $request['headers'], $request['data'], $request['type'], $request['options']);
459
+
460
+            // Ensure we only hook in once
461
+            if ($request['options']['hooks'] !== $options['hooks']) {
462
+                $request['options']['hooks']->register('transport.internal.parse_response', array('Requests', 'parse_multiple'));
463
+                if (!empty($request['options']['complete'])) {
464
+                    $request['options']['hooks']->register('multiple.request.complete', $request['options']['complete']);
465
+                }
466
+            }
467
+        }
468
+        unset($request);
469
+
470
+        if (!empty($options['transport'])) {
471
+            $transport = $options['transport'];
472
+
473
+            if (is_string($options['transport'])) {
474
+                $transport = new $transport();
475
+            }
476
+        }
477
+        else {
478
+            $transport = self::get_transport();
479
+        }
480
+        $responses = $transport->request_multiple($requests, $options);
481
+
482
+        foreach ($responses as $id => &$response) {
483
+            // If our hook got messed with somehow, ensure we end up with the
484
+            // correct response
485
+            if (is_string($response)) {
486
+                $request = $requests[$id];
487
+                self::parse_multiple($response, $request);
488
+                $request['options']['hooks']->dispatch('multiple.request.complete', array(&$response, $id));
489
+            }
490
+        }
491
+
492
+        return $responses;
493
+    }
494
+
495
+    /**
496
+     * Get the default options
497
+     *
498
+     * @see Requests::request() for values returned by this method
499
+     * @param boolean $multirequest Is this a multirequest?
500
+     * @return array Default option values
501
+     */
502
+    protected static function get_default_options($multirequest = false) {
503
+        $defaults = array(
504
+            'timeout' => 10,
505
+            'connect_timeout' => 10,
506
+            'useragent' => 'php-requests/' . self::VERSION,
507
+            'protocol_version' => 1.1,
508
+            'redirected' => 0,
509
+            'redirects' => 10,
510
+            'follow_redirects' => true,
511
+            'blocking' => true,
512
+            'type' => self::GET,
513
+            'filename' => false,
514
+            'auth' => false,
515
+            'proxy' => false,
516
+            'cookies' => false,
517
+            'max_bytes' => false,
518
+            'idn' => true,
519
+            'hooks' => null,
520
+            'transport' => null,
521
+            'verify' => Requests::get_certificate_path(),
522
+            'verifyname' => true,
523
+        );
524
+        if ($multirequest !== false) {
525
+            $defaults['complete'] = null;
526
+        }
527
+        return $defaults;
528
+    }
529
+
530
+    /**
531
+     * Get default certificate path.
532
+     *
533
+     * @return string Default certificate path.
534
+     */
535
+    public static function get_certificate_path() {
536
+        if ( ! empty( Requests::$certificate_path ) ) {
537
+            return Requests::$certificate_path;
538
+        }
539
+
540
+        return dirname(__FILE__) . '/Requests/Transport/cacert.pem';
541
+    }
542
+
543
+    /**
544
+     * Set default certificate path.
545
+     *
546
+     * @param string $path Certificate path, pointing to a PEM file.
547
+     */
548
+    public static function set_certificate_path( $path ) {
549
+        Requests::$certificate_path = $path;
550
+    }
551
+
552
+    /**
553
+     * Set the default values
554
+     *
555
+     * @param string $url URL to request
556
+     * @param array $headers Extra headers to send with the request
557
+     * @param array|null $data Data to send either as a query string for GET/HEAD requests, or in the body for POST requests
558
+     * @param string $type HTTP request type
559
+     * @param array $options Options for the request
560
+     * @return array $options
561
+     */
562
+    protected static function set_defaults(&$url, &$headers, &$data, &$type, &$options) {
563
+        if (!preg_match('/^http(s)?:\/\//i', $url, $matches)) {
564
+            throw new Requests_Exception('Only HTTP(S) requests are handled.', 'nonhttp', $url);
565
+        }
566
+
567
+        if (empty($options['hooks'])) {
568
+            $options['hooks'] = new Requests_Hooks();
569
+        }
570
+
571
+        if (is_array($options['auth'])) {
572
+            $options['auth'] = new Requests_Auth_Basic($options['auth']);
573
+        }
574
+        if ($options['auth'] !== false) {
575
+            $options['auth']->register($options['hooks']);
576
+        }
577
+
578
+        if (is_string($options['proxy']) || is_array($options['proxy'])) {
579
+            $options['proxy'] = new Requests_Proxy_HTTP($options['proxy']);
580
+        }
581
+        if ($options['proxy'] !== false) {
582
+            $options['proxy']->register($options['hooks']);
583
+        }
584
+
585
+        if (is_array($options['cookies'])) {
586
+            $options['cookies'] = new Requests_Cookie_Jar($options['cookies']);
587
+        }
588
+        elseif (empty($options['cookies'])) {
589
+            $options['cookies'] = new Requests_Cookie_Jar();
590
+        }
591
+        if ($options['cookies'] !== false) {
592
+            $options['cookies']->register($options['hooks']);
593
+        }
594
+
595
+        if ($options['idn'] !== false) {
596
+            $iri = new Requests_IRI($url);
597
+            $iri->host = Requests_IDNAEncoder::encode($iri->ihost);
598
+            $url = $iri->uri;
599
+        }
600
+
601
+        // Massage the type to ensure we support it.
602
+        $type = strtoupper($type);
603
+
604
+        if (!isset($options['data_format'])) {
605
+            if (in_array($type, array(self::HEAD, self::GET, self::DELETE))) {
606
+                $options['data_format'] = 'query';
607
+            }
608
+            else {
609
+                $options['data_format'] = 'body';
610
+            }
611
+        }
612
+    }
613
+
614
+    /**
615
+     * HTTP response parser
616
+     *
617
+     * @throws Requests_Exception On missing head/body separator (`requests.no_crlf_separator`)
618
+     * @throws Requests_Exception On missing head/body separator (`noversion`)
619
+     * @throws Requests_Exception On missing head/body separator (`toomanyredirects`)
620
+     *
621
+     * @param string $headers Full response text including headers and body
622
+     * @param string $url Original request URL
623
+     * @param array $req_headers Original $headers array passed to {@link request()}, in case we need to follow redirects
624
+     * @param array $req_data Original $data array passed to {@link request()}, in case we need to follow redirects
625
+     * @param array $options Original $options array passed to {@link request()}, in case we need to follow redirects
626
+     * @return Requests_Response
627
+     */
628
+    protected static function parse_response($headers, $url, $req_headers, $req_data, $options) {
629
+        $return = new Requests_Response();
630
+        if (!$options['blocking']) {
631
+            return $return;
632
+        }
633
+
634
+        $return->raw = $headers;
635
+        $return->url = $url;
636
+
637
+        if (!$options['filename']) {
638
+            if (($pos = strpos($headers, "\r\n\r\n")) === false) {
639
+                // Crap!
640
+                throw new Requests_Exception('Missing header/body separator', 'requests.no_crlf_separator');
641
+            }
642
+
643
+            $headers = substr($return->raw, 0, $pos);
644
+            $return->body = substr($return->raw, $pos + strlen("\n\r\n\r"));
645
+        }
646
+        else {
647
+            $return->body = '';
648
+        }
649
+        // Pretend CRLF = LF for compatibility (RFC 2616, section 19.3)
650
+        $headers = str_replace("\r\n", "\n", $headers);
651
+        // Unfold headers (replace [CRLF] 1*( SP | HT ) with SP) as per RFC 2616 (section 2.2)
652
+        $headers = preg_replace('/\n[ \t]/', ' ', $headers);
653
+        $headers = explode("\n", $headers);
654
+        preg_match('#^HTTP/(1\.\d)[ \t]+(\d+)#i', array_shift($headers), $matches);
655
+        if (empty($matches)) {
656
+            throw new Requests_Exception('Response could not be parsed', 'noversion', $headers);
657
+        }
658
+        $return->protocol_version = (float) $matches[1];
659
+        $return->status_code = (int) $matches[2];
660
+        if ($return->status_code >= 200 && $return->status_code < 300) {
661
+            $return->success = true;
662
+        }
663
+
664
+        foreach ($headers as $header) {
665
+            list($key, $value) = explode(':', $header, 2);
666
+            $value = trim($value);
667
+            preg_replace('#(\s+)#i', ' ', $value);
668
+            $return->headers[$key] = $value;
669
+        }
670
+        if (isset($return->headers['transfer-encoding'])) {
671
+            $return->body = self::decode_chunked($return->body);
672
+            unset($return->headers['transfer-encoding']);
673
+        }
674
+        if (isset($return->headers['content-encoding'])) {
675
+            $return->body = self::decompress($return->body);
676
+        }
677
+
678
+        //fsockopen and cURL compatibility
679
+        if (isset($return->headers['connection'])) {
680
+            unset($return->headers['connection']);
681
+        }
682
+
683
+        $options['hooks']->dispatch('requests.before_redirect_check', array(&$return, $req_headers, $req_data, $options));
684
+
685
+        if ($return->is_redirect() && $options['follow_redirects'] === true) {
686
+            if (isset($return->headers['location']) && $options['redirected'] < $options['redirects']) {
687
+                if ($return->status_code === 303) {
688
+                    $options['type'] = self::GET;
689
+                }
690
+                $options['redirected']++;
691
+                $location = $return->headers['location'];
692
+                if (strpos($location, 'http://') !== 0 && strpos($location, 'https://') !== 0) {
693
+                    // relative redirect, for compatibility make it absolute
694
+                    $location = Requests_IRI::absolutize($url, $location);
695
+                    $location = $location->uri;
696
+                }
697
+
698
+                $hook_args = array(
699
+                    &$location,
700
+                    &$req_headers,
701
+                    &$req_data,
702
+                    &$options,
703
+                    $return
704
+                );
705
+                $options['hooks']->dispatch('requests.before_redirect', $hook_args);
706
+                $redirected = self::request($location, $req_headers, $req_data, $options['type'], $options);
707
+                $redirected->history[] = $return;
708
+                return $redirected;
709
+            }
710
+            elseif ($options['redirected'] >= $options['redirects']) {
711
+                throw new Requests_Exception('Too many redirects', 'toomanyredirects', $return);
712
+            }
713
+        }
714
+
715
+        $return->redirects = $options['redirected'];
716
+
717
+        $options['hooks']->dispatch('requests.after_request', array(&$return, $req_headers, $req_data, $options));
718
+        return $return;
719
+    }
720
+
721
+    /**
722
+     * Callback for `transport.internal.parse_response`
723
+     *
724
+     * Internal use only. Converts a raw HTTP response to a Requests_Response
725
+     * while still executing a multiple request.
726
+     *
727
+     * @param string $response Full response text including headers and body (will be overwritten with Response instance)
728
+     * @param array $request Request data as passed into {@see Requests::request_multiple()}
729
+     * @return null `$response` is either set to a Requests_Response instance, or a Requests_Exception object
730
+     */
731
+    public static function parse_multiple(&$response, $request) {
732
+        try {
733
+            $url = $request['url'];
734
+            $headers = $request['headers'];
735
+            $data = $request['data'];
736
+            $options = $request['options'];
737
+            $response = self::parse_response($response, $url, $headers, $data, $options);
738
+        }
739
+        catch (Requests_Exception $e) {
740
+            $response = $e;
741
+        }
742
+    }
743
+
744
+    /**
745
+     * Decoded a chunked body as per RFC 2616
746
+     *
747
+     * @see https://tools.ietf.org/html/rfc2616#section-3.6.1
748
+     * @param string $data Chunked body
749
+     * @return string Decoded body
750
+     */
751
+    protected static function decode_chunked($data) {
752
+        if (!preg_match('/^([0-9a-f]+)(?:;(?:[\w-]*)(?:=(?:(?:[\w-]*)*|"(?:[^\r\n])*"))?)*\r\n/i', trim($data))) {
753
+            return $data;
754
+        }
755
+
756
+
757
+
758
+        $decoded = '';
759
+        $encoded = $data;
760
+
761
+        while (true) {
762
+            $is_chunked = (bool) preg_match('/^([0-9a-f]+)(?:;(?:[\w-]*)(?:=(?:(?:[\w-]*)*|"(?:[^\r\n])*"))?)*\r\n/i', $encoded, $matches);
763
+            if (!$is_chunked) {
764
+                // Looks like it's not chunked after all
765
+                return $data;
766
+            }
767
+
768
+            $length = hexdec(trim($matches[1]));
769
+            if ($length === 0) {
770
+                // Ignore trailer headers
771
+                return $decoded;
772
+            }
773
+
774
+            $chunk_length = strlen($matches[0]);
775
+            $decoded .= substr($encoded, $chunk_length, $length);
776
+            $encoded = substr($encoded, $chunk_length + $length + 2);
777
+
778
+            if (trim($encoded) === '0' || empty($encoded)) {
779
+                return $decoded;
780
+            }
781
+        }
782
+
783
+        // We'll never actually get down here
784
+        // @codeCoverageIgnoreStart
785
+    }
786
+    // @codeCoverageIgnoreEnd
787
+
788
+    /**
789
+     * Convert a key => value array to a 'key: value' array for headers
790
+     *
791
+     * @param array $array Dictionary of header values
792
+     * @return array List of headers
793
+     */
794
+    public static function flatten($array) {
795
+        $return = array();
796
+        foreach ($array as $key => $value) {
797
+            $return[] = sprintf('%s: %s', $key, $value);
798
+        }
799
+        return $return;
800
+    }
801
+
802
+    /**
803
+     * Convert a key => value array to a 'key: value' array for headers
804
+     *
805
+     * @codeCoverageIgnore
806
+     * @deprecated Misspelling of {@see Requests::flatten}
807
+     * @param array $array Dictionary of header values
808
+     * @return array List of headers
809
+     */
810
+    public static function flattern($array) {
811
+        return self::flatten($array);
812
+    }
813
+
814
+    /**
815
+     * Decompress an encoded body
816
+     *
817
+     * Implements gzip, compress and deflate. Guesses which it is by attempting
818
+     * to decode.
819
+     *
820
+     * @param string $data Compressed data in one of the above formats
821
+     * @return string Decompressed string
822
+     */
823
+    public static function decompress($data) {
824
+        if (substr($data, 0, 2) !== "\x1f\x8b" && substr($data, 0, 2) !== "\x78\x9c") {
825
+            // Not actually compressed. Probably cURL ruining this for us.
826
+            return $data;
827
+        }
828
+
829
+        if (function_exists('gzdecode') && ($decoded = @gzdecode($data)) !== false) {
830
+            return $decoded;
831
+        }
832
+        elseif (function_exists('gzinflate') && ($decoded = @gzinflate($data)) !== false) {
833
+            return $decoded;
834
+        }
835
+        elseif (($decoded = self::compatible_gzinflate($data)) !== false) {
836
+            return $decoded;
837
+        }
838
+        elseif (function_exists('gzuncompress') && ($decoded = @gzuncompress($data)) !== false) {
839
+            return $decoded;
840
+        }
841
+
842
+        return $data;
843
+    }
844
+
845
+    /**
846
+     * Decompression of deflated string while staying compatible with the majority of servers.
847
+     *
848
+     * Certain Servers will return deflated data with headers which PHP's gzinflate()
849
+     * function cannot handle out of the box. The following function has been created from
850
+     * various snippets on the gzinflate() PHP documentation.
851
+     *
852
+     * Warning: Magic numbers within. Due to the potential different formats that the compressed
853
+     * data may be returned in, some "magic offsets" are needed to ensure proper decompression
854
+     * takes place. For a simple progmatic way to determine the magic offset in use, see:
855
+     * https://core.trac.wordpress.org/ticket/18273
856
+     *
857
+     * @since 2.8.1
858
+     * @link https://core.trac.wordpress.org/ticket/18273
859
+     * @link https://secure.php.net/manual/en/function.gzinflate.php#70875
860
+     * @link https://secure.php.net/manual/en/function.gzinflate.php#77336
861
+     *
862
+     * @param string $gzData String to decompress.
863
+     * @return string|bool False on failure.
864
+     */
865
+    public static function compatible_gzinflate($gzData) {
866
+        // Compressed data might contain a full zlib header, if so strip it for
867
+        // gzinflate()
868
+        if (substr($gzData, 0, 3) == "\x1f\x8b\x08") {
869
+            $i = 10;
870
+            $flg = ord(substr($gzData, 3, 1));
871
+            if ($flg > 0) {
872
+                if ($flg & 4) {
873
+                    list($xlen) = unpack('v', substr($gzData, $i, 2));
874
+                    $i = $i + 2 + $xlen;
875
+                }
876
+                if ($flg & 8) {
877
+                    $i = strpos($gzData, "\0", $i) + 1;
878
+                }
879
+                if ($flg & 16) {
880
+                    $i = strpos($gzData, "\0", $i) + 1;
881
+                }
882
+                if ($flg & 2) {
883
+                    $i = $i + 2;
884
+                }
885
+            }
886
+            $decompressed = self::compatible_gzinflate(substr($gzData, $i));
887
+            if (false !== $decompressed) {
888
+                return $decompressed;
889
+            }
890
+        }
891
+
892
+        // If the data is Huffman Encoded, we must first strip the leading 2
893
+        // byte Huffman marker for gzinflate()
894
+        // The response is Huffman coded by many compressors such as
895
+        // java.util.zip.Deflater, Ruby’s Zlib::Deflate, and .NET's
896
+        // System.IO.Compression.DeflateStream.
897
+        //
898
+        // See https://decompres.blogspot.com/ for a quick explanation of this
899
+        // data type
900
+        $huffman_encoded = false;
901
+
902
+        // low nibble of first byte should be 0x08
903
+        list(, $first_nibble)    = unpack('h', $gzData);
904
+
905
+        // First 2 bytes should be divisible by 0x1F
906
+        list(, $first_two_bytes) = unpack('n', $gzData);
907
+
908
+        if (0x08 == $first_nibble && 0 == ($first_two_bytes % 0x1F)) {
909
+            $huffman_encoded = true;
910
+        }
911
+
912
+        if ($huffman_encoded) {
913
+            if (false !== ($decompressed = @gzinflate(substr($gzData, 2)))) {
914
+                return $decompressed;
915
+            }
916
+        }
917
+
918
+        if ("\x50\x4b\x03\x04" == substr($gzData, 0, 4)) {
919
+            // ZIP file format header
920
+            // Offset 6: 2 bytes, General-purpose field
921
+            // Offset 26: 2 bytes, filename length
922
+            // Offset 28: 2 bytes, optional field length
923
+            // Offset 30: Filename field, followed by optional field, followed
924
+            // immediately by data
925
+            list(, $general_purpose_flag) = unpack('v', substr($gzData, 6, 2));
926
+
927
+            // If the file has been compressed on the fly, 0x08 bit is set of
928
+            // the general purpose field. We can use this to differentiate
929
+            // between a compressed document, and a ZIP file
930
+            $zip_compressed_on_the_fly = (0x08 == (0x08 & $general_purpose_flag));
931
+
932
+            if (!$zip_compressed_on_the_fly) {
933
+                // Don't attempt to decode a compressed zip file
934
+                return $gzData;
935
+            }
936
+
937
+            // Determine the first byte of data, based on the above ZIP header
938
+            // offsets:
939
+            $first_file_start = array_sum(unpack('v2', substr($gzData, 26, 4)));
940
+            if (false !== ($decompressed = @gzinflate(substr($gzData, 30 + $first_file_start)))) {
941
+                return $decompressed;
942
+            }
943
+            return false;
944
+        }
945
+
946
+        // Finally fall back to straight gzinflate
947
+        if (false !== ($decompressed = @gzinflate($gzData))) {
948
+            return $decompressed;
949
+        }
950
+
951
+        // Fallback for all above failing, not expected, but included for
952
+        // debugging and preventing regressions and to track stats
953
+        if (false !== ($decompressed = @gzinflate(substr($gzData, 2)))) {
954
+            return $decompressed;
955
+        }
956
+
957
+        return false;
958
+    }
959
+
960
+    public static function match_domain($host, $reference) {
961
+        // Check for a direct match
962
+        if ($host === $reference) {
963
+            return true;
964
+        }
965
+
966
+        // Calculate the valid wildcard match if the host is not an IP address
967
+        // Also validates that the host has 3 parts or more, as per Firefox's
968
+        // ruleset.
969
+        $parts = explode('.', $host);
970
+        if (ip2long($host) === false && count($parts) >= 3) {
971
+            $parts[0] = '*';
972
+            $wildcard = implode('.', $parts);
973
+            if ($wildcard === $reference) {
974
+                return true;
975
+            }
976
+        }
977
+
978
+        return false;
979
+    }
980 980
 }
Please login to merge, or discard this patch.
Spacing   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -142,8 +142,8 @@  discard block
 block discarded – undo
142 142
 		}
143 143
 
144 144
 		$file = str_replace('_', '/', $class);
145
-		if (file_exists(dirname(__FILE__) . '/' . $file . '.php')) {
146
-			require_once(dirname(__FILE__) . '/' . $file . '.php');
145
+		if (file_exists(dirname(__FILE__).'/'.$file.'.php')) {
146
+			require_once(dirname(__FILE__).'/'.$file.'.php');
147 147
 		}
148 148
 	}
149 149
 
@@ -503,7 +503,7 @@  discard block
 block discarded – undo
503 503
 		$defaults = array(
504 504
 			'timeout' => 10,
505 505
 			'connect_timeout' => 10,
506
-			'useragent' => 'php-requests/' . self::VERSION,
506
+			'useragent' => 'php-requests/'.self::VERSION,
507 507
 			'protocol_version' => 1.1,
508 508
 			'redirected' => 0,
509 509
 			'redirects' => 10,
@@ -533,11 +533,11 @@  discard block
 block discarded – undo
533 533
 	 * @return string Default certificate path.
534 534
 	 */
535 535
 	public static function get_certificate_path() {
536
-		if ( ! empty( Requests::$certificate_path ) ) {
536
+		if (!empty(Requests::$certificate_path)) {
537 537
 			return Requests::$certificate_path;
538 538
 		}
539 539
 
540
-		return dirname(__FILE__) . '/Requests/Transport/cacert.pem';
540
+		return dirname(__FILE__).'/Requests/Transport/cacert.pem';
541 541
 	}
542 542
 
543 543
 	/**
@@ -545,7 +545,7 @@  discard block
 block discarded – undo
545 545
 	 *
546 546
 	 * @param string $path Certificate path, pointing to a PEM file.
547 547
 	 */
548
-	public static function set_certificate_path( $path ) {
548
+	public static function set_certificate_path($path) {
549 549
 		Requests::$certificate_path = $path;
550 550
 	}
551 551
 
Please login to merge, or discard this patch.
Braces   +11 added lines, -22 removed lines patch added patch discarded remove patch
@@ -370,8 +370,7 @@  discard block
 block discarded – undo
370 370
 			if (is_string($options['transport'])) {
371 371
 				$transport = new $transport();
372 372
 			}
373
-		}
374
-		else {
373
+		} else {
375 374
 			$need_ssl = (0 === stripos($url, 'https://'));
376 375
 			$capabilities = array('ssl' => $need_ssl);
377 376
 			$transport = self::get_transport($capabilities);
@@ -447,8 +446,7 @@  discard block
 block discarded – undo
447 446
 			if (!isset($request['options'])) {
448 447
 				$request['options'] = $options;
449 448
 				$request['options']['type'] = $request['type'];
450
-			}
451
-			else {
449
+			} else {
452 450
 				if (empty($request['options']['type'])) {
453 451
 					$request['options']['type'] = $request['type'];
454 452
 				}
@@ -473,8 +471,7 @@  discard block
 block discarded – undo
473 471
 			if (is_string($options['transport'])) {
474 472
 				$transport = new $transport();
475 473
 			}
476
-		}
477
-		else {
474
+		} else {
478 475
 			$transport = self::get_transport();
479 476
 		}
480 477
 		$responses = $transport->request_multiple($requests, $options);
@@ -584,8 +581,7 @@  discard block
 block discarded – undo
584 581
 
585 582
 		if (is_array($options['cookies'])) {
586 583
 			$options['cookies'] = new Requests_Cookie_Jar($options['cookies']);
587
-		}
588
-		elseif (empty($options['cookies'])) {
584
+		} elseif (empty($options['cookies'])) {
589 585
 			$options['cookies'] = new Requests_Cookie_Jar();
590 586
 		}
591 587
 		if ($options['cookies'] !== false) {
@@ -604,8 +600,7 @@  discard block
 block discarded – undo
604 600
 		if (!isset($options['data_format'])) {
605 601
 			if (in_array($type, array(self::HEAD, self::GET, self::DELETE))) {
606 602
 				$options['data_format'] = 'query';
607
-			}
608
-			else {
603
+			} else {
609 604
 				$options['data_format'] = 'body';
610 605
 			}
611 606
 		}
@@ -642,8 +637,7 @@  discard block
 block discarded – undo
642 637
 
643 638
 			$headers = substr($return->raw, 0, $pos);
644 639
 			$return->body = substr($return->raw, $pos + strlen("\n\r\n\r"));
645
-		}
646
-		else {
640
+		} else {
647 641
 			$return->body = '';
648 642
 		}
649 643
 		// Pretend CRLF = LF for compatibility (RFC 2616, section 19.3)
@@ -706,8 +700,7 @@  discard block
 block discarded – undo
706 700
 				$redirected = self::request($location, $req_headers, $req_data, $options['type'], $options);
707 701
 				$redirected->history[] = $return;
708 702
 				return $redirected;
709
-			}
710
-			elseif ($options['redirected'] >= $options['redirects']) {
703
+			} elseif ($options['redirected'] >= $options['redirects']) {
711 704
 				throw new Requests_Exception('Too many redirects', 'toomanyredirects', $return);
712 705
 			}
713 706
 		}
@@ -735,8 +728,7 @@  discard block
 block discarded – undo
735 728
 			$data = $request['data'];
736 729
 			$options = $request['options'];
737 730
 			$response = self::parse_response($response, $url, $headers, $data, $options);
738
-		}
739
-		catch (Requests_Exception $e) {
731
+		} catch (Requests_Exception $e) {
740 732
 			$response = $e;
741 733
 		}
742 734
 	}
@@ -828,14 +820,11 @@  discard block
 block discarded – undo
828 820
 
829 821
 		if (function_exists('gzdecode') && ($decoded = @gzdecode($data)) !== false) {
830 822
 			return $decoded;
831
-		}
832
-		elseif (function_exists('gzinflate') && ($decoded = @gzinflate($data)) !== false) {
823
+		} elseif (function_exists('gzinflate') && ($decoded = @gzinflate($data)) !== false) {
833 824
 			return $decoded;
834
-		}
835
-		elseif (($decoded = self::compatible_gzinflate($data)) !== false) {
825
+		} elseif (($decoded = self::compatible_gzinflate($data)) !== false) {
836 826
 			return $decoded;
837
-		}
838
-		elseif (function_exists('gzuncompress') && ($decoded = @gzuncompress($data)) !== false) {
827
+		} elseif (function_exists('gzuncompress') && ($decoded = @gzuncompress($data)) !== false) {
839 828
 			return $decoded;
840 829
 		}
841 830
 
Please login to merge, or discard this patch.
plugin/buycourses/src/Requests/Cookie.php 4 patches
Doc Comments   +2 added lines, -1 removed lines patch added patch discarded remove patch
@@ -62,7 +62,7 @@  discard block
 block discarded – undo
62 62
 	 *
63 63
 	 * @param string $name
64 64
 	 * @param string $value
65
-	 * @param array|Requests_Utility_CaseInsensitiveDictionary $attributes Associative array of attribute data
65
+	 * @param Requests_Utility_CaseInsensitiveDictionary $attributes Associative array of attribute data
66 66
 	 */
67 67
 	public function __construct($name, $value, $attributes = array(), $flags = array(), $reference_time = null) {
68 68
 		$this->name = $name;
@@ -377,6 +377,7 @@  discard block
 block discarded – undo
377 377
 	 * specifies some of this handling, but not in a thorough manner.
378 378
 	 *
379 379
 	 * @param string Cookie header value (from a Set-Cookie header)
380
+	 * @param integer $reference_time
380 381
 	 * @return Requests_Cookie Parsed cookie object
381 382
 	 */
382 383
 	public static function parse($string, $name = '', $reference_time = null) {
Please login to merge, or discard this patch.
Indentation   +484 added lines, -484 removed lines patch added patch discarded remove patch
@@ -13,488 +13,488 @@
 block discarded – undo
13 13
  * @subpackage Cookies
14 14
  */
15 15
 class Requests_Cookie {
16
-	/**
17
-	 * Cookie name.
18
-	 *
19
-	 * @var string
20
-	 */
21
-	public $name;
22
-
23
-	/**
24
-	 * Cookie value.
25
-	 *
26
-	 * @var string
27
-	 */
28
-	public $value;
29
-
30
-	/**
31
-	 * Cookie attributes
32
-	 *
33
-	 * Valid keys are (currently) path, domain, expires, max-age, secure and
34
-	 * httponly.
35
-	 *
36
-	 * @var Requests_Utility_CaseInsensitiveDictionary|array Array-like object
37
-	 */
38
-	public $attributes = array();
39
-
40
-	/**
41
-	 * Cookie flags
42
-	 *
43
-	 * Valid keys are (currently) creation, last-access, persistent and
44
-	 * host-only.
45
-	 *
46
-	 * @var array
47
-	 */
48
-	public $flags = array();
49
-
50
-	/**
51
-	 * Reference time for relative calculations
52
-	 *
53
-	 * This is used in place of `time()` when calculating Max-Age expiration and
54
-	 * checking time validity.
55
-	 *
56
-	 * @var int
57
-	 */
58
-	public $reference_time = 0;
59
-
60
-	/**
61
-	 * Create a new cookie object
62
-	 *
63
-	 * @param string $name
64
-	 * @param string $value
65
-	 * @param array|Requests_Utility_CaseInsensitiveDictionary $attributes Associative array of attribute data
66
-	 */
67
-	public function __construct($name, $value, $attributes = array(), $flags = array(), $reference_time = null) {
68
-		$this->name = $name;
69
-		$this->value = $value;
70
-		$this->attributes = $attributes;
71
-		$default_flags = array(
72
-			'creation' => time(),
73
-			'last-access' => time(),
74
-			'persistent' => false,
75
-			'host-only' => true,
76
-		);
77
-		$this->flags = array_merge($default_flags, $flags);
78
-
79
-		$this->reference_time = time();
80
-		if ($reference_time !== null) {
81
-			$this->reference_time = $reference_time;
82
-		}
83
-
84
-		$this->normalize();
85
-	}
86
-
87
-	/**
88
-	 * Check if a cookie is expired.
89
-	 *
90
-	 * Checks the age against $this->reference_time to determine if the cookie
91
-	 * is expired.
92
-	 *
93
-	 * @return boolean True if expired, false if time is valid.
94
-	 */
95
-	public function is_expired() {
96
-		// RFC6265, s. 4.1.2.2:
97
-		// If a cookie has both the Max-Age and the Expires attribute, the Max-
98
-		// Age attribute has precedence and controls the expiration date of the
99
-		// cookie.
100
-		if (isset($this->attributes['max-age'])) {
101
-			$max_age = $this->attributes['max-age'];
102
-			return $max_age < $this->reference_time;
103
-		}
104
-
105
-		if (isset($this->attributes['expires'])) {
106
-			$expires = $this->attributes['expires'];
107
-			return $expires < $this->reference_time;
108
-		}
109
-
110
-		return false;
111
-	}
112
-
113
-	/**
114
-	 * Check if a cookie is valid for a given URI
115
-	 *
116
-	 * @param Requests_IRI $uri URI to check
117
-	 * @return boolean Whether the cookie is valid for the given URI
118
-	 */
119
-	public function uri_matches(Requests_IRI $uri) {
120
-		if (!$this->domain_matches($uri->host)) {
121
-			return false;
122
-		}
123
-
124
-		if (!$this->path_matches($uri->path)) {
125
-			return false;
126
-		}
127
-
128
-		return empty($this->attributes['secure']) || $uri->scheme === 'https';
129
-	}
130
-
131
-	/**
132
-	 * Check if a cookie is valid for a given domain
133
-	 *
134
-	 * @param string $string Domain to check
135
-	 * @return boolean Whether the cookie is valid for the given domain
136
-	 */
137
-	public function domain_matches($string) {
138
-		if (!isset($this->attributes['domain'])) {
139
-			// Cookies created manually; cookies created by Requests will set
140
-			// the domain to the requested domain
141
-			return true;
142
-		}
143
-
144
-		$domain_string = $this->attributes['domain'];
145
-		if ($domain_string === $string) {
146
-			// The domain string and the string are identical.
147
-			return true;
148
-		}
149
-
150
-		// If the cookie is marked as host-only and we don't have an exact
151
-		// match, reject the cookie
152
-		if ($this->flags['host-only'] === true) {
153
-			return false;
154
-		}
155
-
156
-		if (strlen($string) <= strlen($domain_string)) {
157
-			// For obvious reasons, the string cannot be a suffix if the domain
158
-			// is shorter than the domain string
159
-			return false;
160
-		}
161
-
162
-		if (substr($string, -1 * strlen($domain_string)) !== $domain_string) {
163
-			// The domain string should be a suffix of the string.
164
-			return false;
165
-		}
166
-
167
-		$prefix = substr($string, 0, strlen($string) - strlen($domain_string));
168
-		if (substr($prefix, -1) !== '.') {
169
-			// The last character of the string that is not included in the
170
-			// domain string should be a %x2E (".") character.
171
-			return false;
172
-		}
173
-
174
-		// The string should be a host name (i.e., not an IP address).
175
-		return !preg_match('#^(.+\.)\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$#', $string);
176
-	}
177
-
178
-	/**
179
-	 * Check if a cookie is valid for a given path
180
-	 *
181
-	 * From the path-match check in RFC 6265 section 5.1.4
182
-	 *
183
-	 * @param string $request_path Path to check
184
-	 * @return boolean Whether the cookie is valid for the given path
185
-	 */
186
-	public function path_matches($request_path) {
187
-		if (empty($request_path)) {
188
-			// Normalize empty path to root
189
-			$request_path = '/';
190
-		}
191
-
192
-		if (!isset($this->attributes['path'])) {
193
-			// Cookies created manually; cookies created by Requests will set
194
-			// the path to the requested path
195
-			return true;
196
-		}
197
-
198
-		$cookie_path = $this->attributes['path'];
199
-
200
-		if ($cookie_path === $request_path) {
201
-			// The cookie-path and the request-path are identical.
202
-			return true;
203
-		}
204
-
205
-		if (strlen($request_path) > strlen($cookie_path) && substr($request_path, 0, strlen($cookie_path)) === $cookie_path) {
206
-			if (substr($cookie_path, -1) === '/') {
207
-				// The cookie-path is a prefix of the request-path, and the last
208
-				// character of the cookie-path is %x2F ("/").
209
-				return true;
210
-			}
211
-
212
-			if (substr($request_path, strlen($cookie_path), 1) === '/') {
213
-				// The cookie-path is a prefix of the request-path, and the
214
-				// first character of the request-path that is not included in
215
-				// the cookie-path is a %x2F ("/") character.
216
-				return true;
217
-			}
218
-		}
219
-
220
-		return false;
221
-	}
222
-
223
-	/**
224
-	 * Normalize cookie and attributes
225
-	 *
226
-	 * @return boolean Whether the cookie was successfully normalized
227
-	 */
228
-	public function normalize() {
229
-		foreach ($this->attributes as $key => $value) {
230
-			$orig_value = $value;
231
-			$value = $this->normalize_attribute($key, $value);
232
-			if ($value === null) {
233
-				unset($this->attributes[$key]);
234
-				continue;
235
-			}
236
-
237
-			if ($value !== $orig_value) {
238
-				$this->attributes[$key] = $value;
239
-			}
240
-		}
241
-
242
-		return true;
243
-	}
244
-
245
-	/**
246
-	 * Parse an individual cookie attribute
247
-	 *
248
-	 * Handles parsing individual attributes from the cookie values.
249
-	 *
250
-	 * @param string $name Attribute name
251
-	 * @param string|boolean $value Attribute value (string value, or true if empty/flag)
252
-	 * @return mixed Value if available, or null if the attribute value is invalid (and should be skipped)
253
-	 */
254
-	protected function normalize_attribute($name, $value) {
255
-		switch (strtolower($name)) {
256
-			case 'expires':
257
-				// Expiration parsing, as per RFC 6265 section 5.2.1
258
-				if (is_int($value)) {
259
-					return $value;
260
-				}
261
-
262
-				$expiry_time = strtotime($value);
263
-				if ($expiry_time === false) {
264
-					return null;
265
-				}
266
-
267
-				return $expiry_time;
268
-
269
-			case 'max-age':
270
-				// Expiration parsing, as per RFC 6265 section 5.2.2
271
-				if (is_int($value)) {
272
-					return $value;
273
-				}
274
-
275
-				// Check that we have a valid age
276
-				if (!preg_match('/^-?\d+$/', $value)) {
277
-					return null;
278
-				}
279
-
280
-				$delta_seconds = (int) $value;
281
-				if ($delta_seconds <= 0) {
282
-					$expiry_time = 0;
283
-				}
284
-				else {
285
-					$expiry_time = $this->reference_time + $delta_seconds;
286
-				}
287
-
288
-				return $expiry_time;
289
-
290
-			case 'domain':
291
-				// Domain normalization, as per RFC 6265 section 5.2.3
292
-				if ($value[0] === '.') {
293
-					$value = substr($value, 1);
294
-				}
295
-
296
-				return $value;
297
-
298
-			default:
299
-				return $value;
300
-		}
301
-	}
302
-
303
-	/**
304
-	 * Format a cookie for a Cookie header
305
-	 *
306
-	 * This is used when sending cookies to a server.
307
-	 *
308
-	 * @return string Cookie formatted for Cookie header
309
-	 */
310
-	public function format_for_header() {
311
-		return sprintf('%s=%s', $this->name, $this->value);
312
-	}
313
-
314
-	/**
315
-	 * Format a cookie for a Cookie header
316
-	 *
317
-	 * @codeCoverageIgnore
318
-	 * @deprecated Use {@see Requests_Cookie::format_for_header}
319
-	 * @return string
320
-	 */
321
-	public function formatForHeader() {
322
-		return $this->format_for_header();
323
-	}
324
-
325
-	/**
326
-	 * Format a cookie for a Set-Cookie header
327
-	 *
328
-	 * This is used when sending cookies to clients. This isn't really
329
-	 * applicable to client-side usage, but might be handy for debugging.
330
-	 *
331
-	 * @return string Cookie formatted for Set-Cookie header
332
-	 */
333
-	public function format_for_set_cookie() {
334
-		$header_value = $this->format_for_header();
335
-		if (!empty($this->attributes)) {
336
-			$parts = array();
337
-			foreach ($this->attributes as $key => $value) {
338
-				// Ignore non-associative attributes
339
-				if (is_numeric($key)) {
340
-					$parts[] = $value;
341
-				}
342
-				else {
343
-					$parts[] = sprintf('%s=%s', $key, $value);
344
-				}
345
-			}
346
-
347
-			$header_value .= '; ' . implode('; ', $parts);
348
-		}
349
-		return $header_value;
350
-	}
351
-
352
-	/**
353
-	 * Format a cookie for a Set-Cookie header
354
-	 *
355
-	 * @codeCoverageIgnore
356
-	 * @deprecated Use {@see Requests_Cookie::format_for_set_cookie}
357
-	 * @return string
358
-	 */
359
-	public function formatForSetCookie() {
360
-		return $this->format_for_set_cookie();
361
-	}
362
-
363
-	/**
364
-	 * Get the cookie value
365
-	 *
366
-	 * Attributes and other data can be accessed via methods.
367
-	 */
368
-	public function __toString() {
369
-		return $this->value;
370
-	}
371
-
372
-	/**
373
-	 * Parse a cookie string into a cookie object
374
-	 *
375
-	 * Based on Mozilla's parsing code in Firefox and related projects, which
376
-	 * is an intentional deviation from RFC 2109 and RFC 2616. RFC 6265
377
-	 * specifies some of this handling, but not in a thorough manner.
378
-	 *
379
-	 * @param string Cookie header value (from a Set-Cookie header)
380
-	 * @return Requests_Cookie Parsed cookie object
381
-	 */
382
-	public static function parse($string, $name = '', $reference_time = null) {
383
-		$parts = explode(';', $string);
384
-		$kvparts = array_shift($parts);
385
-
386
-		if (!empty($name)) {
387
-			$value = $string;
388
-		}
389
-		elseif (strpos($kvparts, '=') === false) {
390
-			// Some sites might only have a value without the equals separator.
391
-			// Deviate from RFC 6265 and pretend it was actually a blank name
392
-			// (`=foo`)
393
-			//
394
-			// https://bugzilla.mozilla.org/show_bug.cgi?id=169091
395
-			$name = '';
396
-			$value = $kvparts;
397
-		}
398
-		else {
399
-			list($name, $value) = explode('=', $kvparts, 2);
400
-		}
401
-		$name = trim($name);
402
-		$value = trim($value);
403
-
404
-		// Attribute key are handled case-insensitively
405
-		$attributes = new Requests_Utility_CaseInsensitiveDictionary();
406
-
407
-		if (!empty($parts)) {
408
-			foreach ($parts as $part) {
409
-				if (strpos($part, '=') === false) {
410
-					$part_key = $part;
411
-					$part_value = true;
412
-				}
413
-				else {
414
-					list($part_key, $part_value) = explode('=', $part, 2);
415
-					$part_value = trim($part_value);
416
-				}
417
-
418
-				$part_key = trim($part_key);
419
-				$attributes[$part_key] = $part_value;
420
-			}
421
-		}
422
-
423
-		return new Requests_Cookie($name, $value, $attributes, array(), $reference_time);
424
-	}
425
-
426
-	/**
427
-	 * Parse all Set-Cookie headers from request headers
428
-	 *
429
-	 * @param Requests_Response_Headers $headers Headers to parse from
430
-	 * @param Requests_IRI|null $origin URI for comparing cookie origins
431
-	 * @param int|null $time Reference time for expiration calculation
432
-	 * @return array
433
-	 */
434
-	public static function parse_from_headers(Requests_Response_Headers $headers, Requests_IRI $origin = null, $time = null) {
435
-		$cookie_headers = $headers->getValues('Set-Cookie');
436
-		if (empty($cookie_headers)) {
437
-			return array();
438
-		}
439
-
440
-		$cookies = array();
441
-		foreach ($cookie_headers as $header) {
442
-			$parsed = self::parse($header, '', $time);
443
-
444
-			// Default domain/path attributes
445
-			if (empty($parsed->attributes['domain']) && !empty($origin)) {
446
-				$parsed->attributes['domain'] = $origin->host;
447
-				$parsed->flags['host-only'] = true;
448
-			}
449
-			else {
450
-				$parsed->flags['host-only'] = false;
451
-			}
452
-
453
-			$path_is_valid = (!empty($parsed->attributes['path']) && $parsed->attributes['path'][0] === '/');
454
-			if (!$path_is_valid && !empty($origin)) {
455
-				$path = $origin->path;
456
-
457
-				// Default path normalization as per RFC 6265 section 5.1.4
458
-				if (substr($path, 0, 1) !== '/') {
459
-					// If the uri-path is empty or if the first character of
460
-					// the uri-path is not a %x2F ("/") character, output
461
-					// %x2F ("/") and skip the remaining steps.
462
-					$path = '/';
463
-				}
464
-				elseif (substr_count($path, '/') === 1) {
465
-					// If the uri-path contains no more than one %x2F ("/")
466
-					// character, output %x2F ("/") and skip the remaining
467
-					// step.
468
-					$path = '/';
469
-				}
470
-				else {
471
-					// Output the characters of the uri-path from the first
472
-					// character up to, but not including, the right-most
473
-					// %x2F ("/").
474
-					$path = substr($path, 0, strrpos($path, '/'));
475
-				}
476
-				$parsed->attributes['path'] = $path;
477
-			}
478
-
479
-			// Reject invalid cookie domains
480
-			if (!empty($origin) && !$parsed->domain_matches($origin->host)) {
481
-				continue;
482
-			}
483
-
484
-			$cookies[$parsed->name] = $parsed;
485
-		}
486
-
487
-		return $cookies;
488
-	}
489
-
490
-	/**
491
-	 * Parse all Set-Cookie headers from request headers
492
-	 *
493
-	 * @codeCoverageIgnore
494
-	 * @deprecated Use {@see Requests_Cookie::parse_from_headers}
495
-	 * @return string
496
-	 */
497
-	public static function parseFromHeaders(Requests_Response_Headers $headers) {
498
-		return self::parse_from_headers($headers);
499
-	}
16
+    /**
17
+     * Cookie name.
18
+     *
19
+     * @var string
20
+     */
21
+    public $name;
22
+
23
+    /**
24
+     * Cookie value.
25
+     *
26
+     * @var string
27
+     */
28
+    public $value;
29
+
30
+    /**
31
+     * Cookie attributes
32
+     *
33
+     * Valid keys are (currently) path, domain, expires, max-age, secure and
34
+     * httponly.
35
+     *
36
+     * @var Requests_Utility_CaseInsensitiveDictionary|array Array-like object
37
+     */
38
+    public $attributes = array();
39
+
40
+    /**
41
+     * Cookie flags
42
+     *
43
+     * Valid keys are (currently) creation, last-access, persistent and
44
+     * host-only.
45
+     *
46
+     * @var array
47
+     */
48
+    public $flags = array();
49
+
50
+    /**
51
+     * Reference time for relative calculations
52
+     *
53
+     * This is used in place of `time()` when calculating Max-Age expiration and
54
+     * checking time validity.
55
+     *
56
+     * @var int
57
+     */
58
+    public $reference_time = 0;
59
+
60
+    /**
61
+     * Create a new cookie object
62
+     *
63
+     * @param string $name
64
+     * @param string $value
65
+     * @param array|Requests_Utility_CaseInsensitiveDictionary $attributes Associative array of attribute data
66
+     */
67
+    public function __construct($name, $value, $attributes = array(), $flags = array(), $reference_time = null) {
68
+        $this->name = $name;
69
+        $this->value = $value;
70
+        $this->attributes = $attributes;
71
+        $default_flags = array(
72
+            'creation' => time(),
73
+            'last-access' => time(),
74
+            'persistent' => false,
75
+            'host-only' => true,
76
+        );
77
+        $this->flags = array_merge($default_flags, $flags);
78
+
79
+        $this->reference_time = time();
80
+        if ($reference_time !== null) {
81
+            $this->reference_time = $reference_time;
82
+        }
83
+
84
+        $this->normalize();
85
+    }
86
+
87
+    /**
88
+     * Check if a cookie is expired.
89
+     *
90
+     * Checks the age against $this->reference_time to determine if the cookie
91
+     * is expired.
92
+     *
93
+     * @return boolean True if expired, false if time is valid.
94
+     */
95
+    public function is_expired() {
96
+        // RFC6265, s. 4.1.2.2:
97
+        // If a cookie has both the Max-Age and the Expires attribute, the Max-
98
+        // Age attribute has precedence and controls the expiration date of the
99
+        // cookie.
100
+        if (isset($this->attributes['max-age'])) {
101
+            $max_age = $this->attributes['max-age'];
102
+            return $max_age < $this->reference_time;
103
+        }
104
+
105
+        if (isset($this->attributes['expires'])) {
106
+            $expires = $this->attributes['expires'];
107
+            return $expires < $this->reference_time;
108
+        }
109
+
110
+        return false;
111
+    }
112
+
113
+    /**
114
+     * Check if a cookie is valid for a given URI
115
+     *
116
+     * @param Requests_IRI $uri URI to check
117
+     * @return boolean Whether the cookie is valid for the given URI
118
+     */
119
+    public function uri_matches(Requests_IRI $uri) {
120
+        if (!$this->domain_matches($uri->host)) {
121
+            return false;
122
+        }
123
+
124
+        if (!$this->path_matches($uri->path)) {
125
+            return false;
126
+        }
127
+
128
+        return empty($this->attributes['secure']) || $uri->scheme === 'https';
129
+    }
130
+
131
+    /**
132
+     * Check if a cookie is valid for a given domain
133
+     *
134
+     * @param string $string Domain to check
135
+     * @return boolean Whether the cookie is valid for the given domain
136
+     */
137
+    public function domain_matches($string) {
138
+        if (!isset($this->attributes['domain'])) {
139
+            // Cookies created manually; cookies created by Requests will set
140
+            // the domain to the requested domain
141
+            return true;
142
+        }
143
+
144
+        $domain_string = $this->attributes['domain'];
145
+        if ($domain_string === $string) {
146
+            // The domain string and the string are identical.
147
+            return true;
148
+        }
149
+
150
+        // If the cookie is marked as host-only and we don't have an exact
151
+        // match, reject the cookie
152
+        if ($this->flags['host-only'] === true) {
153
+            return false;
154
+        }
155
+
156
+        if (strlen($string) <= strlen($domain_string)) {
157
+            // For obvious reasons, the string cannot be a suffix if the domain
158
+            // is shorter than the domain string
159
+            return false;
160
+        }
161
+
162
+        if (substr($string, -1 * strlen($domain_string)) !== $domain_string) {
163
+            // The domain string should be a suffix of the string.
164
+            return false;
165
+        }
166
+
167
+        $prefix = substr($string, 0, strlen($string) - strlen($domain_string));
168
+        if (substr($prefix, -1) !== '.') {
169
+            // The last character of the string that is not included in the
170
+            // domain string should be a %x2E (".") character.
171
+            return false;
172
+        }
173
+
174
+        // The string should be a host name (i.e., not an IP address).
175
+        return !preg_match('#^(.+\.)\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$#', $string);
176
+    }
177
+
178
+    /**
179
+     * Check if a cookie is valid for a given path
180
+     *
181
+     * From the path-match check in RFC 6265 section 5.1.4
182
+     *
183
+     * @param string $request_path Path to check
184
+     * @return boolean Whether the cookie is valid for the given path
185
+     */
186
+    public function path_matches($request_path) {
187
+        if (empty($request_path)) {
188
+            // Normalize empty path to root
189
+            $request_path = '/';
190
+        }
191
+
192
+        if (!isset($this->attributes['path'])) {
193
+            // Cookies created manually; cookies created by Requests will set
194
+            // the path to the requested path
195
+            return true;
196
+        }
197
+
198
+        $cookie_path = $this->attributes['path'];
199
+
200
+        if ($cookie_path === $request_path) {
201
+            // The cookie-path and the request-path are identical.
202
+            return true;
203
+        }
204
+
205
+        if (strlen($request_path) > strlen($cookie_path) && substr($request_path, 0, strlen($cookie_path)) === $cookie_path) {
206
+            if (substr($cookie_path, -1) === '/') {
207
+                // The cookie-path is a prefix of the request-path, and the last
208
+                // character of the cookie-path is %x2F ("/").
209
+                return true;
210
+            }
211
+
212
+            if (substr($request_path, strlen($cookie_path), 1) === '/') {
213
+                // The cookie-path is a prefix of the request-path, and the
214
+                // first character of the request-path that is not included in
215
+                // the cookie-path is a %x2F ("/") character.
216
+                return true;
217
+            }
218
+        }
219
+
220
+        return false;
221
+    }
222
+
223
+    /**
224
+     * Normalize cookie and attributes
225
+     *
226
+     * @return boolean Whether the cookie was successfully normalized
227
+     */
228
+    public function normalize() {
229
+        foreach ($this->attributes as $key => $value) {
230
+            $orig_value = $value;
231
+            $value = $this->normalize_attribute($key, $value);
232
+            if ($value === null) {
233
+                unset($this->attributes[$key]);
234
+                continue;
235
+            }
236
+
237
+            if ($value !== $orig_value) {
238
+                $this->attributes[$key] = $value;
239
+            }
240
+        }
241
+
242
+        return true;
243
+    }
244
+
245
+    /**
246
+     * Parse an individual cookie attribute
247
+     *
248
+     * Handles parsing individual attributes from the cookie values.
249
+     *
250
+     * @param string $name Attribute name
251
+     * @param string|boolean $value Attribute value (string value, or true if empty/flag)
252
+     * @return mixed Value if available, or null if the attribute value is invalid (and should be skipped)
253
+     */
254
+    protected function normalize_attribute($name, $value) {
255
+        switch (strtolower($name)) {
256
+            case 'expires':
257
+                // Expiration parsing, as per RFC 6265 section 5.2.1
258
+                if (is_int($value)) {
259
+                    return $value;
260
+                }
261
+
262
+                $expiry_time = strtotime($value);
263
+                if ($expiry_time === false) {
264
+                    return null;
265
+                }
266
+
267
+                return $expiry_time;
268
+
269
+            case 'max-age':
270
+                // Expiration parsing, as per RFC 6265 section 5.2.2
271
+                if (is_int($value)) {
272
+                    return $value;
273
+                }
274
+
275
+                // Check that we have a valid age
276
+                if (!preg_match('/^-?\d+$/', $value)) {
277
+                    return null;
278
+                }
279
+
280
+                $delta_seconds = (int) $value;
281
+                if ($delta_seconds <= 0) {
282
+                    $expiry_time = 0;
283
+                }
284
+                else {
285
+                    $expiry_time = $this->reference_time + $delta_seconds;
286
+                }
287
+
288
+                return $expiry_time;
289
+
290
+            case 'domain':
291
+                // Domain normalization, as per RFC 6265 section 5.2.3
292
+                if ($value[0] === '.') {
293
+                    $value = substr($value, 1);
294
+                }
295
+
296
+                return $value;
297
+
298
+            default:
299
+                return $value;
300
+        }
301
+    }
302
+
303
+    /**
304
+     * Format a cookie for a Cookie header
305
+     *
306
+     * This is used when sending cookies to a server.
307
+     *
308
+     * @return string Cookie formatted for Cookie header
309
+     */
310
+    public function format_for_header() {
311
+        return sprintf('%s=%s', $this->name, $this->value);
312
+    }
313
+
314
+    /**
315
+     * Format a cookie for a Cookie header
316
+     *
317
+     * @codeCoverageIgnore
318
+     * @deprecated Use {@see Requests_Cookie::format_for_header}
319
+     * @return string
320
+     */
321
+    public function formatForHeader() {
322
+        return $this->format_for_header();
323
+    }
324
+
325
+    /**
326
+     * Format a cookie for a Set-Cookie header
327
+     *
328
+     * This is used when sending cookies to clients. This isn't really
329
+     * applicable to client-side usage, but might be handy for debugging.
330
+     *
331
+     * @return string Cookie formatted for Set-Cookie header
332
+     */
333
+    public function format_for_set_cookie() {
334
+        $header_value = $this->format_for_header();
335
+        if (!empty($this->attributes)) {
336
+            $parts = array();
337
+            foreach ($this->attributes as $key => $value) {
338
+                // Ignore non-associative attributes
339
+                if (is_numeric($key)) {
340
+                    $parts[] = $value;
341
+                }
342
+                else {
343
+                    $parts[] = sprintf('%s=%s', $key, $value);
344
+                }
345
+            }
346
+
347
+            $header_value .= '; ' . implode('; ', $parts);
348
+        }
349
+        return $header_value;
350
+    }
351
+
352
+    /**
353
+     * Format a cookie for a Set-Cookie header
354
+     *
355
+     * @codeCoverageIgnore
356
+     * @deprecated Use {@see Requests_Cookie::format_for_set_cookie}
357
+     * @return string
358
+     */
359
+    public function formatForSetCookie() {
360
+        return $this->format_for_set_cookie();
361
+    }
362
+
363
+    /**
364
+     * Get the cookie value
365
+     *
366
+     * Attributes and other data can be accessed via methods.
367
+     */
368
+    public function __toString() {
369
+        return $this->value;
370
+    }
371
+
372
+    /**
373
+     * Parse a cookie string into a cookie object
374
+     *
375
+     * Based on Mozilla's parsing code in Firefox and related projects, which
376
+     * is an intentional deviation from RFC 2109 and RFC 2616. RFC 6265
377
+     * specifies some of this handling, but not in a thorough manner.
378
+     *
379
+     * @param string Cookie header value (from a Set-Cookie header)
380
+     * @return Requests_Cookie Parsed cookie object
381
+     */
382
+    public static function parse($string, $name = '', $reference_time = null) {
383
+        $parts = explode(';', $string);
384
+        $kvparts = array_shift($parts);
385
+
386
+        if (!empty($name)) {
387
+            $value = $string;
388
+        }
389
+        elseif (strpos($kvparts, '=') === false) {
390
+            // Some sites might only have a value without the equals separator.
391
+            // Deviate from RFC 6265 and pretend it was actually a blank name
392
+            // (`=foo`)
393
+            //
394
+            // https://bugzilla.mozilla.org/show_bug.cgi?id=169091
395
+            $name = '';
396
+            $value = $kvparts;
397
+        }
398
+        else {
399
+            list($name, $value) = explode('=', $kvparts, 2);
400
+        }
401
+        $name = trim($name);
402
+        $value = trim($value);
403
+
404
+        // Attribute key are handled case-insensitively
405
+        $attributes = new Requests_Utility_CaseInsensitiveDictionary();
406
+
407
+        if (!empty($parts)) {
408
+            foreach ($parts as $part) {
409
+                if (strpos($part, '=') === false) {
410
+                    $part_key = $part;
411
+                    $part_value = true;
412
+                }
413
+                else {
414
+                    list($part_key, $part_value) = explode('=', $part, 2);
415
+                    $part_value = trim($part_value);
416
+                }
417
+
418
+                $part_key = trim($part_key);
419
+                $attributes[$part_key] = $part_value;
420
+            }
421
+        }
422
+
423
+        return new Requests_Cookie($name, $value, $attributes, array(), $reference_time);
424
+    }
425
+
426
+    /**
427
+     * Parse all Set-Cookie headers from request headers
428
+     *
429
+     * @param Requests_Response_Headers $headers Headers to parse from
430
+     * @param Requests_IRI|null $origin URI for comparing cookie origins
431
+     * @param int|null $time Reference time for expiration calculation
432
+     * @return array
433
+     */
434
+    public static function parse_from_headers(Requests_Response_Headers $headers, Requests_IRI $origin = null, $time = null) {
435
+        $cookie_headers = $headers->getValues('Set-Cookie');
436
+        if (empty($cookie_headers)) {
437
+            return array();
438
+        }
439
+
440
+        $cookies = array();
441
+        foreach ($cookie_headers as $header) {
442
+            $parsed = self::parse($header, '', $time);
443
+
444
+            // Default domain/path attributes
445
+            if (empty($parsed->attributes['domain']) && !empty($origin)) {
446
+                $parsed->attributes['domain'] = $origin->host;
447
+                $parsed->flags['host-only'] = true;
448
+            }
449
+            else {
450
+                $parsed->flags['host-only'] = false;
451
+            }
452
+
453
+            $path_is_valid = (!empty($parsed->attributes['path']) && $parsed->attributes['path'][0] === '/');
454
+            if (!$path_is_valid && !empty($origin)) {
455
+                $path = $origin->path;
456
+
457
+                // Default path normalization as per RFC 6265 section 5.1.4
458
+                if (substr($path, 0, 1) !== '/') {
459
+                    // If the uri-path is empty or if the first character of
460
+                    // the uri-path is not a %x2F ("/") character, output
461
+                    // %x2F ("/") and skip the remaining steps.
462
+                    $path = '/';
463
+                }
464
+                elseif (substr_count($path, '/') === 1) {
465
+                    // If the uri-path contains no more than one %x2F ("/")
466
+                    // character, output %x2F ("/") and skip the remaining
467
+                    // step.
468
+                    $path = '/';
469
+                }
470
+                else {
471
+                    // Output the characters of the uri-path from the first
472
+                    // character up to, but not including, the right-most
473
+                    // %x2F ("/").
474
+                    $path = substr($path, 0, strrpos($path, '/'));
475
+                }
476
+                $parsed->attributes['path'] = $path;
477
+            }
478
+
479
+            // Reject invalid cookie domains
480
+            if (!empty($origin) && !$parsed->domain_matches($origin->host)) {
481
+                continue;
482
+            }
483
+
484
+            $cookies[$parsed->name] = $parsed;
485
+        }
486
+
487
+        return $cookies;
488
+    }
489
+
490
+    /**
491
+     * Parse all Set-Cookie headers from request headers
492
+     *
493
+     * @codeCoverageIgnore
494
+     * @deprecated Use {@see Requests_Cookie::parse_from_headers}
495
+     * @return string
496
+     */
497
+    public static function parseFromHeaders(Requests_Response_Headers $headers) {
498
+        return self::parse_from_headers($headers);
499
+    }
500 500
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -344,7 +344,7 @@
 block discarded – undo
344 344
 				}
345 345
 			}
346 346
 
347
-			$header_value .= '; ' . implode('; ', $parts);
347
+			$header_value .= '; '.implode('; ', $parts);
348 348
 		}
349 349
 		return $header_value;
350 350
 	}
Please login to merge, or discard this patch.
Braces   +8 added lines, -16 removed lines patch added patch discarded remove patch
@@ -280,8 +280,7 @@  discard block
 block discarded – undo
280 280
 				$delta_seconds = (int) $value;
281 281
 				if ($delta_seconds <= 0) {
282 282
 					$expiry_time = 0;
283
-				}
284
-				else {
283
+				} else {
285 284
 					$expiry_time = $this->reference_time + $delta_seconds;
286 285
 				}
287 286
 
@@ -338,8 +337,7 @@  discard block
 block discarded – undo
338 337
 				// Ignore non-associative attributes
339 338
 				if (is_numeric($key)) {
340 339
 					$parts[] = $value;
341
-				}
342
-				else {
340
+				} else {
343 341
 					$parts[] = sprintf('%s=%s', $key, $value);
344 342
 				}
345 343
 			}
@@ -385,8 +383,7 @@  discard block
 block discarded – undo
385 383
 
386 384
 		if (!empty($name)) {
387 385
 			$value = $string;
388
-		}
389
-		elseif (strpos($kvparts, '=') === false) {
386
+		} elseif (strpos($kvparts, '=') === false) {
390 387
 			// Some sites might only have a value without the equals separator.
391 388
 			// Deviate from RFC 6265 and pretend it was actually a blank name
392 389
 			// (`=foo`)
@@ -394,8 +391,7 @@  discard block
 block discarded – undo
394 391
 			// https://bugzilla.mozilla.org/show_bug.cgi?id=169091
395 392
 			$name = '';
396 393
 			$value = $kvparts;
397
-		}
398
-		else {
394
+		} else {
399 395
 			list($name, $value) = explode('=', $kvparts, 2);
400 396
 		}
401 397
 		$name = trim($name);
@@ -409,8 +405,7 @@  discard block
 block discarded – undo
409 405
 				if (strpos($part, '=') === false) {
410 406
 					$part_key = $part;
411 407
 					$part_value = true;
412
-				}
413
-				else {
408
+				} else {
414 409
 					list($part_key, $part_value) = explode('=', $part, 2);
415 410
 					$part_value = trim($part_value);
416 411
 				}
@@ -445,8 +440,7 @@  discard block
 block discarded – undo
445 440
 			if (empty($parsed->attributes['domain']) && !empty($origin)) {
446 441
 				$parsed->attributes['domain'] = $origin->host;
447 442
 				$parsed->flags['host-only'] = true;
448
-			}
449
-			else {
443
+			} else {
450 444
 				$parsed->flags['host-only'] = false;
451 445
 			}
452 446
 
@@ -460,14 +454,12 @@  discard block
 block discarded – undo
460 454
 					// the uri-path is not a %x2F ("/") character, output
461 455
 					// %x2F ("/") and skip the remaining steps.
462 456
 					$path = '/';
463
-				}
464
-				elseif (substr_count($path, '/') === 1) {
457
+				} elseif (substr_count($path, '/') === 1) {
465 458
 					// If the uri-path contains no more than one %x2F ("/")
466 459
 					// character, output %x2F ("/") and skip the remaining
467 460
 					// step.
468 461
 					$path = '/';
469
-				}
470
-				else {
462
+				} else {
471 463
 					// Output the characters of the uri-path from the first
472 464
 					// character up to, but not including, the right-most
473 465
 					// %x2F ("/").
Please login to merge, or discard this patch.
plugin/buycourses/src/Requests/IDNAEncoder.php 4 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -357,7 +357,7 @@
 block discarded – undo
357 357
 	 * @param int $delta
358 358
 	 * @param int $numpoints
359 359
 	 * @param bool $firsttime
360
-	 * @return int New bias
360
+	 * @return double New bias
361 361
 	 */
362 362
 	protected static function adapt($delta, $numpoints, $firsttime) {
363 363
 #	function adapt(delta,numpoints,firsttime):
Please login to merge, or discard this patch.
Indentation   +300 added lines, -300 removed lines patch added patch discarded remove patch
@@ -11,378 +11,378 @@
 block discarded – undo
11 11
  * @see https://tools.ietf.org/html/rfc3492 Punycode/Bootstrap specification
12 12
  */
13 13
 class Requests_IDNAEncoder {
14
-	/**
15
-	 * ACE prefix used for IDNA
16
-	 *
17
-	 * @see https://tools.ietf.org/html/rfc3490#section-5
18
-	 * @var string
19
-	 */
20
-	const ACE_PREFIX = 'xn--';
14
+    /**
15
+     * ACE prefix used for IDNA
16
+     *
17
+     * @see https://tools.ietf.org/html/rfc3490#section-5
18
+     * @var string
19
+     */
20
+    const ACE_PREFIX = 'xn--';
21 21
 
22
-	/**#@+
22
+    /**#@+
23 23
 	 * Bootstrap constant for Punycode
24 24
 	 *
25 25
 	 * @see https://tools.ietf.org/html/rfc3492#section-5
26 26
 	 * @var int
27 27
 	 */
28
-	const BOOTSTRAP_BASE         = 36;
29
-	const BOOTSTRAP_TMIN         = 1;
30
-	const BOOTSTRAP_TMAX         = 26;
31
-	const BOOTSTRAP_SKEW         = 38;
32
-	const BOOTSTRAP_DAMP         = 700;
33
-	const BOOTSTRAP_INITIAL_BIAS = 72;
34
-	const BOOTSTRAP_INITIAL_N    = 128;
35
-	/**#@-*/
28
+    const BOOTSTRAP_BASE         = 36;
29
+    const BOOTSTRAP_TMIN         = 1;
30
+    const BOOTSTRAP_TMAX         = 26;
31
+    const BOOTSTRAP_SKEW         = 38;
32
+    const BOOTSTRAP_DAMP         = 700;
33
+    const BOOTSTRAP_INITIAL_BIAS = 72;
34
+    const BOOTSTRAP_INITIAL_N    = 128;
35
+    /**#@-*/
36 36
 
37
-	/**
38
-	 * Encode a hostname using Punycode
39
-	 *
40
-	 * @param string $string Hostname
41
-	 * @return string Punycode-encoded hostname
42
-	 */
43
-	public static function encode($string) {
44
-		$parts = explode('.', $string);
45
-		foreach ($parts as &$part) {
46
-			$part = self::to_ascii($part);
47
-		}
48
-		return implode('.', $parts);
49
-	}
37
+    /**
38
+     * Encode a hostname using Punycode
39
+     *
40
+     * @param string $string Hostname
41
+     * @return string Punycode-encoded hostname
42
+     */
43
+    public static function encode($string) {
44
+        $parts = explode('.', $string);
45
+        foreach ($parts as &$part) {
46
+            $part = self::to_ascii($part);
47
+        }
48
+        return implode('.', $parts);
49
+    }
50 50
 
51
-	/**
52
-	 * Convert a UTF-8 string to an ASCII string using Punycode
53
-	 *
54
-	 * @throws Requests_Exception Provided string longer than 64 ASCII characters (`idna.provided_too_long`)
55
-	 * @throws Requests_Exception Prepared string longer than 64 ASCII characters (`idna.prepared_too_long`)
56
-	 * @throws Requests_Exception Provided string already begins with xn-- (`idna.provided_is_prefixed`)
57
-	 * @throws Requests_Exception Encoded string longer than 64 ASCII characters (`idna.encoded_too_long`)
58
-	 *
59
-	 * @param string $string ASCII or UTF-8 string (max length 64 characters)
60
-	 * @return string ASCII string
61
-	 */
62
-	public static function to_ascii($string) {
63
-		// Step 1: Check if the string is already ASCII
64
-		if (self::is_ascii($string)) {
65
-			// Skip to step 7
66
-			if (strlen($string) < 64) {
67
-				return $string;
68
-			}
51
+    /**
52
+     * Convert a UTF-8 string to an ASCII string using Punycode
53
+     *
54
+     * @throws Requests_Exception Provided string longer than 64 ASCII characters (`idna.provided_too_long`)
55
+     * @throws Requests_Exception Prepared string longer than 64 ASCII characters (`idna.prepared_too_long`)
56
+     * @throws Requests_Exception Provided string already begins with xn-- (`idna.provided_is_prefixed`)
57
+     * @throws Requests_Exception Encoded string longer than 64 ASCII characters (`idna.encoded_too_long`)
58
+     *
59
+     * @param string $string ASCII or UTF-8 string (max length 64 characters)
60
+     * @return string ASCII string
61
+     */
62
+    public static function to_ascii($string) {
63
+        // Step 1: Check if the string is already ASCII
64
+        if (self::is_ascii($string)) {
65
+            // Skip to step 7
66
+            if (strlen($string) < 64) {
67
+                return $string;
68
+            }
69 69
 
70
-			throw new Requests_Exception('Provided string is too long', 'idna.provided_too_long', $string);
71
-		}
70
+            throw new Requests_Exception('Provided string is too long', 'idna.provided_too_long', $string);
71
+        }
72 72
 
73
-		// Step 2: nameprep
74
-		$string = self::nameprep($string);
73
+        // Step 2: nameprep
74
+        $string = self::nameprep($string);
75 75
 
76
-		// Step 3: UseSTD3ASCIIRules is false, continue
77
-		// Step 4: Check if it's ASCII now
78
-		if (self::is_ascii($string)) {
79
-			// Skip to step 7
80
-			if (strlen($string) < 64) {
81
-				return $string;
82
-			}
76
+        // Step 3: UseSTD3ASCIIRules is false, continue
77
+        // Step 4: Check if it's ASCII now
78
+        if (self::is_ascii($string)) {
79
+            // Skip to step 7
80
+            if (strlen($string) < 64) {
81
+                return $string;
82
+            }
83 83
 
84
-			throw new Requests_Exception('Prepared string is too long', 'idna.prepared_too_long', $string);
85
-		}
84
+            throw new Requests_Exception('Prepared string is too long', 'idna.prepared_too_long', $string);
85
+        }
86 86
 
87
-		// Step 5: Check ACE prefix
88
-		if (strpos($string, self::ACE_PREFIX) === 0) {
89
-			throw new Requests_Exception('Provided string begins with ACE prefix', 'idna.provided_is_prefixed', $string);
90
-		}
87
+        // Step 5: Check ACE prefix
88
+        if (strpos($string, self::ACE_PREFIX) === 0) {
89
+            throw new Requests_Exception('Provided string begins with ACE prefix', 'idna.provided_is_prefixed', $string);
90
+        }
91 91
 
92
-		// Step 6: Encode with Punycode
93
-		$string = self::punycode_encode($string);
92
+        // Step 6: Encode with Punycode
93
+        $string = self::punycode_encode($string);
94 94
 
95
-		// Step 7: Prepend ACE prefix
96
-		$string = self::ACE_PREFIX . $string;
95
+        // Step 7: Prepend ACE prefix
96
+        $string = self::ACE_PREFIX . $string;
97 97
 
98
-		// Step 8: Check size
99
-		if (strlen($string) < 64) {
100
-			return $string;
101
-		}
98
+        // Step 8: Check size
99
+        if (strlen($string) < 64) {
100
+            return $string;
101
+        }
102 102
 
103
-		throw new Requests_Exception('Encoded string is too long', 'idna.encoded_too_long', $string);
104
-	}
103
+        throw new Requests_Exception('Encoded string is too long', 'idna.encoded_too_long', $string);
104
+    }
105 105
 
106
-	/**
107
-	 * Check whether a given string contains only ASCII characters
108
-	 *
109
-	 * @internal (Testing found regex was the fastest implementation)
110
-	 *
111
-	 * @param string $string
112
-	 * @return bool Is the string ASCII-only?
113
-	 */
114
-	protected static function is_ascii($string) {
115
-		return (preg_match('/(?:[^\x00-\x7F])/', $string) !== 1);
116
-	}
106
+    /**
107
+     * Check whether a given string contains only ASCII characters
108
+     *
109
+     * @internal (Testing found regex was the fastest implementation)
110
+     *
111
+     * @param string $string
112
+     * @return bool Is the string ASCII-only?
113
+     */
114
+    protected static function is_ascii($string) {
115
+        return (preg_match('/(?:[^\x00-\x7F])/', $string) !== 1);
116
+    }
117 117
 
118
-	/**
119
-	 * Prepare a string for use as an IDNA name
120
-	 *
121
-	 * @todo Implement this based on RFC 3491 and the newer 5891
122
-	 * @param string $string
123
-	 * @return string Prepared string
124
-	 */
125
-	protected static function nameprep($string) {
126
-		return $string;
127
-	}
118
+    /**
119
+     * Prepare a string for use as an IDNA name
120
+     *
121
+     * @todo Implement this based on RFC 3491 and the newer 5891
122
+     * @param string $string
123
+     * @return string Prepared string
124
+     */
125
+    protected static function nameprep($string) {
126
+        return $string;
127
+    }
128 128
 
129
-	/**
130
-	 * Convert a UTF-8 string to a UCS-4 codepoint array
131
-	 *
132
-	 * Based on Requests_IRI::replace_invalid_with_pct_encoding()
133
-	 *
134
-	 * @throws Requests_Exception Invalid UTF-8 codepoint (`idna.invalidcodepoint`)
135
-	 * @param string $input
136
-	 * @return array Unicode code points
137
-	 */
138
-	protected static function utf8_to_codepoints($input) {
139
-		$codepoints = array();
129
+    /**
130
+     * Convert a UTF-8 string to a UCS-4 codepoint array
131
+     *
132
+     * Based on Requests_IRI::replace_invalid_with_pct_encoding()
133
+     *
134
+     * @throws Requests_Exception Invalid UTF-8 codepoint (`idna.invalidcodepoint`)
135
+     * @param string $input
136
+     * @return array Unicode code points
137
+     */
138
+    protected static function utf8_to_codepoints($input) {
139
+        $codepoints = array();
140 140
 
141
-		// Get number of bytes
142
-		$strlen = strlen($input);
141
+        // Get number of bytes
142
+        $strlen = strlen($input);
143 143
 
144
-		for ($position = 0; $position < $strlen; $position++) {
145
-			$value = ord($input[$position]);
144
+        for ($position = 0; $position < $strlen; $position++) {
145
+            $value = ord($input[$position]);
146 146
 
147
-			// One byte sequence:
148
-			if ((~$value & 0x80) === 0x80) {
149
-				$character = $value;
150
-				$length = 1;
151
-				$remaining = 0;
152
-			}
153
-			// Two byte sequence:
154
-			elseif (($value & 0xE0) === 0xC0) {
155
-				$character = ($value & 0x1F) << 6;
156
-				$length = 2;
157
-				$remaining = 1;
158
-			}
159
-			// Three byte sequence:
160
-			elseif (($value & 0xF0) === 0xE0) {
161
-				$character = ($value & 0x0F) << 12;
162
-				$length = 3;
163
-				$remaining = 2;
164
-			}
165
-			// Four byte sequence:
166
-			elseif (($value & 0xF8) === 0xF0) {
167
-				$character = ($value & 0x07) << 18;
168
-				$length = 4;
169
-				$remaining = 3;
170
-			}
171
-			// Invalid byte:
172
-			else {
173
-				throw new Requests_Exception('Invalid Unicode codepoint', 'idna.invalidcodepoint', $value);
174
-			}
147
+            // One byte sequence:
148
+            if ((~$value & 0x80) === 0x80) {
149
+                $character = $value;
150
+                $length = 1;
151
+                $remaining = 0;
152
+            }
153
+            // Two byte sequence:
154
+            elseif (($value & 0xE0) === 0xC0) {
155
+                $character = ($value & 0x1F) << 6;
156
+                $length = 2;
157
+                $remaining = 1;
158
+            }
159
+            // Three byte sequence:
160
+            elseif (($value & 0xF0) === 0xE0) {
161
+                $character = ($value & 0x0F) << 12;
162
+                $length = 3;
163
+                $remaining = 2;
164
+            }
165
+            // Four byte sequence:
166
+            elseif (($value & 0xF8) === 0xF0) {
167
+                $character = ($value & 0x07) << 18;
168
+                $length = 4;
169
+                $remaining = 3;
170
+            }
171
+            // Invalid byte:
172
+            else {
173
+                throw new Requests_Exception('Invalid Unicode codepoint', 'idna.invalidcodepoint', $value);
174
+            }
175 175
 
176
-			if ($remaining > 0) {
177
-				if ($position + $length > $strlen) {
178
-					throw new Requests_Exception('Invalid Unicode codepoint', 'idna.invalidcodepoint', $character);
179
-				}
180
-				for ($position++; $remaining > 0; $position++) {
181
-					$value = ord($input[$position]);
176
+            if ($remaining > 0) {
177
+                if ($position + $length > $strlen) {
178
+                    throw new Requests_Exception('Invalid Unicode codepoint', 'idna.invalidcodepoint', $character);
179
+                }
180
+                for ($position++; $remaining > 0; $position++) {
181
+                    $value = ord($input[$position]);
182 182
 
183
-					// If it is invalid, count the sequence as invalid and reprocess the current byte:
184
-					if (($value & 0xC0) !== 0x80) {
185
-						throw new Requests_Exception('Invalid Unicode codepoint', 'idna.invalidcodepoint', $character);
186
-					}
183
+                    // If it is invalid, count the sequence as invalid and reprocess the current byte:
184
+                    if (($value & 0xC0) !== 0x80) {
185
+                        throw new Requests_Exception('Invalid Unicode codepoint', 'idna.invalidcodepoint', $character);
186
+                    }
187 187
 
188
-					$character |= ($value & 0x3F) << (--$remaining * 6);
189
-				}
190
-				$position--;
191
-			}
188
+                    $character |= ($value & 0x3F) << (--$remaining * 6);
189
+                }
190
+                $position--;
191
+            }
192 192
 
193
-			if (
194
-				// Non-shortest form sequences are invalid
195
-				   $length > 1 && $character <= 0x7F
196
-				|| $length > 2 && $character <= 0x7FF
197
-				|| $length > 3 && $character <= 0xFFFF
198
-				// Outside of range of ucschar codepoints
199
-				// Noncharacters
200
-				|| ($character & 0xFFFE) === 0xFFFE
201
-				|| $character >= 0xFDD0 && $character <= 0xFDEF
202
-				|| (
203
-					// Everything else not in ucschar
204
-					   $character > 0xD7FF && $character < 0xF900
205
-					|| $character < 0x20
206
-					|| $character > 0x7E && $character < 0xA0
207
-					|| $character > 0xEFFFD
208
-				)
209
-			) {
210
-				throw new Requests_Exception('Invalid Unicode codepoint', 'idna.invalidcodepoint', $character);
211
-			}
193
+            if (
194
+                // Non-shortest form sequences are invalid
195
+                    $length > 1 && $character <= 0x7F
196
+                || $length > 2 && $character <= 0x7FF
197
+                || $length > 3 && $character <= 0xFFFF
198
+                // Outside of range of ucschar codepoints
199
+                // Noncharacters
200
+                || ($character & 0xFFFE) === 0xFFFE
201
+                || $character >= 0xFDD0 && $character <= 0xFDEF
202
+                || (
203
+                    // Everything else not in ucschar
204
+                        $character > 0xD7FF && $character < 0xF900
205
+                    || $character < 0x20
206
+                    || $character > 0x7E && $character < 0xA0
207
+                    || $character > 0xEFFFD
208
+                )
209
+            ) {
210
+                throw new Requests_Exception('Invalid Unicode codepoint', 'idna.invalidcodepoint', $character);
211
+            }
212 212
 
213
-			$codepoints[] = $character;
214
-		}
213
+            $codepoints[] = $character;
214
+        }
215 215
 
216
-		return $codepoints;
217
-	}
216
+        return $codepoints;
217
+    }
218 218
 
219
-	/**
220
-	 * RFC3492-compliant encoder
221
-	 *
222
-	 * @internal Pseudo-code from Section 6.3 is commented with "#" next to relevant code
223
-	 * @throws Requests_Exception On character outside of the domain (never happens with Punycode) (`idna.character_outside_domain`)
224
-	 *
225
-	 * @param string $input UTF-8 encoded string to encode
226
-	 * @return string Punycode-encoded string
227
-	 */
228
-	public static function punycode_encode($input) {
229
-		$output = '';
219
+    /**
220
+     * RFC3492-compliant encoder
221
+     *
222
+     * @internal Pseudo-code from Section 6.3 is commented with "#" next to relevant code
223
+     * @throws Requests_Exception On character outside of the domain (never happens with Punycode) (`idna.character_outside_domain`)
224
+     *
225
+     * @param string $input UTF-8 encoded string to encode
226
+     * @return string Punycode-encoded string
227
+     */
228
+    public static function punycode_encode($input) {
229
+        $output = '';
230 230
 #		let n = initial_n
231
-		$n = self::BOOTSTRAP_INITIAL_N;
231
+        $n = self::BOOTSTRAP_INITIAL_N;
232 232
 #		let delta = 0
233
-		$delta = 0;
233
+        $delta = 0;
234 234
 #		let bias = initial_bias
235
-		$bias = self::BOOTSTRAP_INITIAL_BIAS;
235
+        $bias = self::BOOTSTRAP_INITIAL_BIAS;
236 236
 #		let h = b = the number of basic code points in the input
237
-		$h = $b = 0; // see loop
237
+        $h = $b = 0; // see loop
238 238
 #		copy them to the output in order
239
-		$codepoints = self::utf8_to_codepoints($input);
240
-		$extended = array();
239
+        $codepoints = self::utf8_to_codepoints($input);
240
+        $extended = array();
241 241
 
242
-		foreach ($codepoints as $char) {
243
-			if ($char < 128) {
244
-				// Character is valid ASCII
245
-				// TODO: this should also check if it's valid for a URL
246
-				$output .= chr($char);
247
-				$h++;
248
-			}
249
-			// Check if the character is non-ASCII, but below initial n
250
-			// This never occurs for Punycode, so ignore in coverage
251
-			// @codeCoverageIgnoreStart
252
-			elseif ($char < $n) {
253
-				throw new Requests_Exception('Invalid character', 'idna.character_outside_domain', $char);
254
-			}
255
-			// @codeCoverageIgnoreEnd
256
-			else {
257
-				$extended[$char] = true;
258
-			}
259
-		}
260
-		$extended = array_keys($extended);
261
-		sort($extended);
262
-		$b = $h;
242
+        foreach ($codepoints as $char) {
243
+            if ($char < 128) {
244
+                // Character is valid ASCII
245
+                // TODO: this should also check if it's valid for a URL
246
+                $output .= chr($char);
247
+                $h++;
248
+            }
249
+            // Check if the character is non-ASCII, but below initial n
250
+            // This never occurs for Punycode, so ignore in coverage
251
+            // @codeCoverageIgnoreStart
252
+            elseif ($char < $n) {
253
+                throw new Requests_Exception('Invalid character', 'idna.character_outside_domain', $char);
254
+            }
255
+            // @codeCoverageIgnoreEnd
256
+            else {
257
+                $extended[$char] = true;
258
+            }
259
+        }
260
+        $extended = array_keys($extended);
261
+        sort($extended);
262
+        $b = $h;
263 263
 #		[copy them] followed by a delimiter if b > 0
264
-		if (strlen($output) > 0) {
265
-			$output .= '-';
266
-		}
264
+        if (strlen($output) > 0) {
265
+            $output .= '-';
266
+        }
267 267
 #		{if the input contains a non-basic code point < n then fail}
268 268
 #		while h < length(input) do begin
269
-		while ($h < count($codepoints)) {
269
+        while ($h < count($codepoints)) {
270 270
 #			let m = the minimum code point >= n in the input
271
-			$m = array_shift($extended);
272
-			//printf('next code point to insert is %s' . PHP_EOL, dechex($m));
271
+            $m = array_shift($extended);
272
+            //printf('next code point to insert is %s' . PHP_EOL, dechex($m));
273 273
 #			let delta = delta + (m - n) * (h + 1), fail on overflow
274
-			$delta += ($m - $n) * ($h + 1);
274
+            $delta += ($m - $n) * ($h + 1);
275 275
 #			let n = m
276
-			$n = $m;
276
+            $n = $m;
277 277
 #			for each code point c in the input (in order) do begin
278
-			for ($num = 0; $num < count($codepoints); $num++) {
279
-				$c = $codepoints[$num];
278
+            for ($num = 0; $num < count($codepoints); $num++) {
279
+                $c = $codepoints[$num];
280 280
 #				if c < n then increment delta, fail on overflow
281
-				if ($c < $n) {
282
-					$delta++;
283
-				}
281
+                if ($c < $n) {
282
+                    $delta++;
283
+                }
284 284
 #				if c == n then begin
285
-				elseif ($c === $n) {
285
+                elseif ($c === $n) {
286 286
 #					let q = delta
287
-					$q = $delta;
287
+                    $q = $delta;
288 288
 #					for k = base to infinity in steps of base do begin
289
-					for ($k = self::BOOTSTRAP_BASE; ; $k += self::BOOTSTRAP_BASE) {
289
+                    for ($k = self::BOOTSTRAP_BASE; ; $k += self::BOOTSTRAP_BASE) {
290 290
 #						let t = tmin if k <= bias {+ tmin}, or
291 291
 #								tmax if k >= bias + tmax, or k - bias otherwise
292
-						if ($k <= ($bias + self::BOOTSTRAP_TMIN)) {
293
-							$t = self::BOOTSTRAP_TMIN;
294
-						}
295
-						elseif ($k >= ($bias + self::BOOTSTRAP_TMAX)) {
296
-							$t = self::BOOTSTRAP_TMAX;
297
-						}
298
-						else {
299
-							$t = $k - $bias;
300
-						}
292
+                        if ($k <= ($bias + self::BOOTSTRAP_TMIN)) {
293
+                            $t = self::BOOTSTRAP_TMIN;
294
+                        }
295
+                        elseif ($k >= ($bias + self::BOOTSTRAP_TMAX)) {
296
+                            $t = self::BOOTSTRAP_TMAX;
297
+                        }
298
+                        else {
299
+                            $t = $k - $bias;
300
+                        }
301 301
 #						if q < t then break
302
-						if ($q < $t) {
303
-							break;
304
-						}
302
+                        if ($q < $t) {
303
+                            break;
304
+                        }
305 305
 #						output the code point for digit t + ((q - t) mod (base - t))
306
-						$digit = $t + (($q - $t) % (self::BOOTSTRAP_BASE - $t));
307
-						$output .= self::digit_to_char($digit);
306
+                        $digit = $t + (($q - $t) % (self::BOOTSTRAP_BASE - $t));
307
+                        $output .= self::digit_to_char($digit);
308 308
 #						let q = (q - t) div (base - t)
309
-						$q = floor(($q - $t) / (self::BOOTSTRAP_BASE - $t));
309
+                        $q = floor(($q - $t) / (self::BOOTSTRAP_BASE - $t));
310 310
 #					end
311
-					}
311
+                    }
312 312
 #					output the code point for digit q
313
-					$output .= self::digit_to_char($q);
313
+                    $output .= self::digit_to_char($q);
314 314
 #					let bias = adapt(delta, h + 1, test h equals b?)
315
-					$bias = self::adapt($delta, $h + 1, $h === $b);
315
+                    $bias = self::adapt($delta, $h + 1, $h === $b);
316 316
 #					let delta = 0
317
-					$delta = 0;
317
+                    $delta = 0;
318 318
 #					increment h
319
-					$h++;
319
+                    $h++;
320 320
 #				end
321
-				}
321
+                }
322 322
 #			end
323
-			}
323
+            }
324 324
 #			increment delta and n
325
-			$delta++;
326
-			$n++;
325
+            $delta++;
326
+            $n++;
327 327
 #		end
328
-		}
328
+        }
329 329
 
330
-		return $output;
331
-	}
330
+        return $output;
331
+    }
332 332
 
333
-	/**
334
-	 * Convert a digit to its respective character
335
-	 *
336
-	 * @see https://tools.ietf.org/html/rfc3492#section-5
337
-	 * @throws Requests_Exception On invalid digit (`idna.invalid_digit`)
338
-	 *
339
-	 * @param int $digit Digit in the range 0-35
340
-	 * @return string Single character corresponding to digit
341
-	 */
342
-	protected static function digit_to_char($digit) {
343
-		// @codeCoverageIgnoreStart
344
-		// As far as I know, this never happens, but still good to be sure.
345
-		if ($digit < 0 || $digit > 35) {
346
-			throw new Requests_Exception(sprintf('Invalid digit %d', $digit), 'idna.invalid_digit', $digit);
347
-		}
348
-		// @codeCoverageIgnoreEnd
349
-		$digits = 'abcdefghijklmnopqrstuvwxyz0123456789';
350
-		return substr($digits, $digit, 1);
351
-	}
333
+    /**
334
+     * Convert a digit to its respective character
335
+     *
336
+     * @see https://tools.ietf.org/html/rfc3492#section-5
337
+     * @throws Requests_Exception On invalid digit (`idna.invalid_digit`)
338
+     *
339
+     * @param int $digit Digit in the range 0-35
340
+     * @return string Single character corresponding to digit
341
+     */
342
+    protected static function digit_to_char($digit) {
343
+        // @codeCoverageIgnoreStart
344
+        // As far as I know, this never happens, but still good to be sure.
345
+        if ($digit < 0 || $digit > 35) {
346
+            throw new Requests_Exception(sprintf('Invalid digit %d', $digit), 'idna.invalid_digit', $digit);
347
+        }
348
+        // @codeCoverageIgnoreEnd
349
+        $digits = 'abcdefghijklmnopqrstuvwxyz0123456789';
350
+        return substr($digits, $digit, 1);
351
+    }
352 352
 
353
-	/**
354
-	 * Adapt the bias
355
-	 *
356
-	 * @see https://tools.ietf.org/html/rfc3492#section-6.1
357
-	 * @param int $delta
358
-	 * @param int $numpoints
359
-	 * @param bool $firsttime
360
-	 * @return int New bias
361
-	 */
362
-	protected static function adapt($delta, $numpoints, $firsttime) {
353
+    /**
354
+     * Adapt the bias
355
+     *
356
+     * @see https://tools.ietf.org/html/rfc3492#section-6.1
357
+     * @param int $delta
358
+     * @param int $numpoints
359
+     * @param bool $firsttime
360
+     * @return int New bias
361
+     */
362
+    protected static function adapt($delta, $numpoints, $firsttime) {
363 363
 #	function adapt(delta,numpoints,firsttime):
364 364
 #		if firsttime then let delta = delta div damp
365
-		if ($firsttime) {
366
-			$delta = floor($delta / self::BOOTSTRAP_DAMP);
367
-		}
365
+        if ($firsttime) {
366
+            $delta = floor($delta / self::BOOTSTRAP_DAMP);
367
+        }
368 368
 #		else let delta = delta div 2
369
-		else {
370
-			$delta = floor($delta / 2);
371
-		}
369
+        else {
370
+            $delta = floor($delta / 2);
371
+        }
372 372
 #		let delta = delta + (delta div numpoints)
373
-		$delta += floor($delta / $numpoints);
373
+        $delta += floor($delta / $numpoints);
374 374
 #		let k = 0
375
-		$k = 0;
375
+        $k = 0;
376 376
 #		while delta > ((base - tmin) * tmax) div 2 do begin
377
-		$max = floor(((self::BOOTSTRAP_BASE - self::BOOTSTRAP_TMIN) * self::BOOTSTRAP_TMAX) / 2);
378
-		while ($delta > $max) {
377
+        $max = floor(((self::BOOTSTRAP_BASE - self::BOOTSTRAP_TMIN) * self::BOOTSTRAP_TMAX) / 2);
378
+        while ($delta > $max) {
379 379
 #			let delta = delta div (base - tmin)
380
-			$delta = floor($delta / (self::BOOTSTRAP_BASE - self::BOOTSTRAP_TMIN));
380
+            $delta = floor($delta / (self::BOOTSTRAP_BASE - self::BOOTSTRAP_TMIN));
381 381
 #			let k = k + base
382
-			$k += self::BOOTSTRAP_BASE;
382
+            $k += self::BOOTSTRAP_BASE;
383 383
 #		end
384
-		}
384
+        }
385 385
 #		return k + (((base - tmin + 1) * delta) div (delta + skew))
386
-		return $k + floor(((self::BOOTSTRAP_BASE - self::BOOTSTRAP_TMIN + 1) * $delta) / ($delta + self::BOOTSTRAP_SKEW));
387
-	}
386
+        return $k + floor(((self::BOOTSTRAP_BASE - self::BOOTSTRAP_TMIN + 1) * $delta) / ($delta + self::BOOTSTRAP_SKEW));
387
+    }
388 388
 }
389 389
\ No newline at end of file
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -93,7 +93,7 @@
 block discarded – undo
93 93
 		$string = self::punycode_encode($string);
94 94
 
95 95
 		// Step 7: Prepend ACE prefix
96
-		$string = self::ACE_PREFIX . $string;
96
+		$string = self::ACE_PREFIX.$string;
97 97
 
98 98
 		// Step 8: Check size
99 99
 		if (strlen($string) < 64) {
Please login to merge, or discard this patch.
Braces   +2 added lines, -4 removed lines patch added patch discarded remove patch
@@ -291,11 +291,9 @@
 block discarded – undo
291 291
 #								tmax if k >= bias + tmax, or k - bias otherwise
292 292
 						if ($k <= ($bias + self::BOOTSTRAP_TMIN)) {
293 293
 							$t = self::BOOTSTRAP_TMIN;
294
-						}
295
-						elseif ($k >= ($bias + self::BOOTSTRAP_TMAX)) {
294
+						} elseif ($k >= ($bias + self::BOOTSTRAP_TMAX)) {
296 295
 							$t = self::BOOTSTRAP_TMAX;
297
-						}
298
-						else {
296
+						} else {
299 297
 							$t = $k - $bias;
300 298
 						}
301 299
 #						if q < t then break
Please login to merge, or discard this patch.
plugin/buycourses/src/Requests/IRI.php 4 patches
Doc Comments   +2 added lines, -1 removed lines patch added patch discarded remove patch
@@ -249,7 +249,7 @@  discard block
 block discarded – undo
249 249
 	 *
250 250
 	 * Returns false if $base is not absolute, otherwise an IRI.
251 251
 	 *
252
-	 * @param IRI|string $base (Absolute) Base IRI
252
+	 * @param string $base (Absolute) Base IRI
253 253
 	 * @param IRI|string $relative Relative IRI
254 254
 	 * @return IRI|false
255 255
 	 */
@@ -984,6 +984,7 @@  discard block
 block discarded – undo
984 984
 	 * Convert an IRI to a URI (or parts thereof)
985 985
 	 *
986 986
 	 * @param string|bool IRI to convert (or false from {@see get_iri})
987
+	 * @param false|string $string
987 988
 	 * @return string|false URI if IRI is valid, false otherwise.
988 989
 	 */
989 990
 	protected function to_uri($string) {
Please login to merge, or discard this patch.
Indentation   +1017 added lines, -1017 removed lines patch added patch discarded remove patch
@@ -64,1021 +64,1021 @@
 block discarded – undo
64 64
  * @property string $ifragment Fragment part of the IRI (after '#')
65 65
  */
66 66
 class Requests_IRI {
67
-	/**
68
-	 * Scheme
69
-	 *
70
-	 * @var string
71
-	 */
72
-	protected $scheme = null;
73
-
74
-	/**
75
-	 * User Information
76
-	 *
77
-	 * @var string
78
-	 */
79
-	protected $iuserinfo = null;
80
-
81
-	/**
82
-	 * ihost
83
-	 *
84
-	 * @var string
85
-	 */
86
-	protected $ihost = null;
87
-
88
-	/**
89
-	 * Port
90
-	 *
91
-	 * @var string
92
-	 */
93
-	protected $port = null;
94
-
95
-	/**
96
-	 * ipath
97
-	 *
98
-	 * @var string
99
-	 */
100
-	protected $ipath = '';
101
-
102
-	/**
103
-	 * iquery
104
-	 *
105
-	 * @var string
106
-	 */
107
-	protected $iquery = null;
108
-
109
-	/**
110
-	 * ifragment
111
-	 *
112
-	 * @var string
113
-	 */
114
-	protected $ifragment = null;
115
-
116
-	/**
117
-	 * Normalization database
118
-	 *
119
-	 * Each key is the scheme, each value is an array with each key as the IRI
120
-	 * part and value as the default value for that part.
121
-	 */
122
-	protected $normalization = array(
123
-		'acap' => array(
124
-			'port' => 674
125
-		),
126
-		'dict' => array(
127
-			'port' => 2628
128
-		),
129
-		'file' => array(
130
-			'ihost' => 'localhost'
131
-		),
132
-		'http' => array(
133
-			'port' => 80,
134
-		),
135
-		'https' => array(
136
-			'port' => 443,
137
-		),
138
-	);
139
-
140
-	/**
141
-	 * Return the entire IRI when you try and read the object as a string
142
-	 *
143
-	 * @return string
144
-	 */
145
-	public function __toString() {
146
-		return $this->get_iri();
147
-	}
148
-
149
-	/**
150
-	 * Overload __set() to provide access via properties
151
-	 *
152
-	 * @param string $name Property name
153
-	 * @param mixed $value Property value
154
-	 */
155
-	public function __set($name, $value) {
156
-		if (method_exists($this, 'set_' . $name)) {
157
-			call_user_func(array($this, 'set_' . $name), $value);
158
-		}
159
-		elseif (
160
-			   $name === 'iauthority'
161
-			|| $name === 'iuserinfo'
162
-			|| $name === 'ihost'
163
-			|| $name === 'ipath'
164
-			|| $name === 'iquery'
165
-			|| $name === 'ifragment'
166
-		) {
167
-			call_user_func(array($this, 'set_' . substr($name, 1)), $value);
168
-		}
169
-	}
170
-
171
-	/**
172
-	 * Overload __get() to provide access via properties
173
-	 *
174
-	 * @param string $name Property name
175
-	 * @return mixed
176
-	 */
177
-	public function __get($name) {
178
-		// isset() returns false for null, we don't want to do that
179
-		// Also why we use array_key_exists below instead of isset()
180
-		$props = get_object_vars($this);
181
-
182
-		if (
183
-			$name === 'iri' ||
184
-			$name === 'uri' ||
185
-			$name === 'iauthority' ||
186
-			$name === 'authority'
187
-		) {
188
-			$method = 'get_' . $name;
189
-			$return = $this->$method();
190
-		}
191
-		elseif (array_key_exists($name, $props)) {
192
-			$return = $this->$name;
193
-		}
194
-		// host -> ihost
195
-		elseif (($prop = 'i' . $name) && array_key_exists($prop, $props)) {
196
-			$name = $prop;
197
-			$return = $this->$prop;
198
-		}
199
-		// ischeme -> scheme
200
-		elseif (($prop = substr($name, 1)) && array_key_exists($prop, $props)) {
201
-			$name = $prop;
202
-			$return = $this->$prop;
203
-		}
204
-		else {
205
-			trigger_error('Undefined property: ' . get_class($this) . '::' . $name, E_USER_NOTICE);
206
-			$return = null;
207
-		}
208
-
209
-		if ($return === null && isset($this->normalization[$this->scheme][$name])) {
210
-			return $this->normalization[$this->scheme][$name];
211
-		}
212
-		else {
213
-			return $return;
214
-		}
215
-	}
216
-
217
-	/**
218
-	 * Overload __isset() to provide access via properties
219
-	 *
220
-	 * @param string $name Property name
221
-	 * @return bool
222
-	 */
223
-	public function __isset($name) {
224
-		return (method_exists($this, 'get_' . $name) || isset($this->$name));
225
-	}
226
-
227
-	/**
228
-	 * Overload __unset() to provide access via properties
229
-	 *
230
-	 * @param string $name Property name
231
-	 */
232
-	public function __unset($name) {
233
-		if (method_exists($this, 'set_' . $name)) {
234
-			call_user_func(array($this, 'set_' . $name), '');
235
-		}
236
-	}
237
-
238
-	/**
239
-	 * Create a new IRI object, from a specified string
240
-	 *
241
-	 * @param string|null $iri
242
-	 */
243
-	public function __construct($iri = null) {
244
-		$this->set_iri($iri);
245
-	}
246
-
247
-	/**
248
-	 * Create a new IRI object by resolving a relative IRI
249
-	 *
250
-	 * Returns false if $base is not absolute, otherwise an IRI.
251
-	 *
252
-	 * @param IRI|string $base (Absolute) Base IRI
253
-	 * @param IRI|string $relative Relative IRI
254
-	 * @return IRI|false
255
-	 */
256
-	public static function absolutize($base, $relative) {
257
-		if (!($relative instanceof Requests_IRI)) {
258
-			$relative = new Requests_IRI($relative);
259
-		}
260
-		if (!$relative->is_valid()) {
261
-			return false;
262
-		}
263
-		elseif ($relative->scheme !== null) {
264
-			return clone $relative;
265
-		}
266
-
267
-		if (!($base instanceof Requests_IRI)) {
268
-			$base = new Requests_IRI($base);
269
-		}
270
-		if ($base->scheme === null || !$base->is_valid()) {
271
-			return false;
272
-		}
273
-
274
-		if ($relative->get_iri() !== '') {
275
-			if ($relative->iuserinfo !== null || $relative->ihost !== null || $relative->port !== null) {
276
-				$target = clone $relative;
277
-				$target->scheme = $base->scheme;
278
-			}
279
-			else {
280
-				$target = new Requests_IRI;
281
-				$target->scheme = $base->scheme;
282
-				$target->iuserinfo = $base->iuserinfo;
283
-				$target->ihost = $base->ihost;
284
-				$target->port = $base->port;
285
-				if ($relative->ipath !== '') {
286
-					if ($relative->ipath[0] === '/') {
287
-						$target->ipath = $relative->ipath;
288
-					}
289
-					elseif (($base->iuserinfo !== null || $base->ihost !== null || $base->port !== null) && $base->ipath === '') {
290
-						$target->ipath = '/' . $relative->ipath;
291
-					}
292
-					elseif (($last_segment = strrpos($base->ipath, '/')) !== false) {
293
-						$target->ipath = substr($base->ipath, 0, $last_segment + 1) . $relative->ipath;
294
-					}
295
-					else {
296
-						$target->ipath = $relative->ipath;
297
-					}
298
-					$target->ipath = $target->remove_dot_segments($target->ipath);
299
-					$target->iquery = $relative->iquery;
300
-				}
301
-				else {
302
-					$target->ipath = $base->ipath;
303
-					if ($relative->iquery !== null) {
304
-						$target->iquery = $relative->iquery;
305
-					}
306
-					elseif ($base->iquery !== null) {
307
-						$target->iquery = $base->iquery;
308
-					}
309
-				}
310
-				$target->ifragment = $relative->ifragment;
311
-			}
312
-		}
313
-		else {
314
-			$target = clone $base;
315
-			$target->ifragment = null;
316
-		}
317
-		$target->scheme_normalization();
318
-		return $target;
319
-	}
320
-
321
-	/**
322
-	 * Parse an IRI into scheme/authority/path/query/fragment segments
323
-	 *
324
-	 * @param string $iri
325
-	 * @return array
326
-	 */
327
-	protected function parse_iri($iri) {
328
-		$iri = trim($iri, "\x20\x09\x0A\x0C\x0D");
329
-		$has_match = preg_match('/^((?P<scheme>[^:\/?#]+):)?(\/\/(?P<authority>[^\/?#]*))?(?P<path>[^?#]*)(\?(?P<query>[^#]*))?(#(?P<fragment>.*))?$/', $iri, $match);
330
-		if (!$has_match) {
331
-			throw new Requests_Exception('Cannot parse supplied IRI', 'iri.cannot_parse', $iri);
332
-		}
333
-
334
-		if ($match[1] === '') {
335
-			$match['scheme'] = null;
336
-		}
337
-		if (!isset($match[3]) || $match[3] === '') {
338
-			$match['authority'] = null;
339
-		}
340
-		if (!isset($match[5])) {
341
-			$match['path'] = '';
342
-		}
343
-		if (!isset($match[6]) || $match[6] === '') {
344
-			$match['query'] = null;
345
-		}
346
-		if (!isset($match[8]) || $match[8] === '') {
347
-			$match['fragment'] = null;
348
-		}
349
-		return $match;
350
-	}
351
-
352
-	/**
353
-	 * Remove dot segments from a path
354
-	 *
355
-	 * @param string $input
356
-	 * @return string
357
-	 */
358
-	protected function remove_dot_segments($input) {
359
-		$output = '';
360
-		while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..') {
361
-			// A: If the input buffer begins with a prefix of "../" or "./",
362
-			// then remove that prefix from the input buffer; otherwise,
363
-			if (strpos($input, '../') === 0) {
364
-				$input = substr($input, 3);
365
-			}
366
-			elseif (strpos($input, './') === 0) {
367
-				$input = substr($input, 2);
368
-			}
369
-			// B: if the input buffer begins with a prefix of "/./" or "/.",
370
-			// where "." is a complete path segment, then replace that prefix
371
-			// with "/" in the input buffer; otherwise,
372
-			elseif (strpos($input, '/./') === 0) {
373
-				$input = substr($input, 2);
374
-			}
375
-			elseif ($input === '/.') {
376
-				$input = '/';
377
-			}
378
-			// C: if the input buffer begins with a prefix of "/../" or "/..",
379
-			// where ".." is a complete path segment, then replace that prefix
380
-			// with "/" in the input buffer and remove the last segment and its
381
-			// preceding "/" (if any) from the output buffer; otherwise,
382
-			elseif (strpos($input, '/../') === 0) {
383
-				$input = substr($input, 3);
384
-				$output = substr_replace($output, '', strrpos($output, '/'));
385
-			}
386
-			elseif ($input === '/..') {
387
-				$input = '/';
388
-				$output = substr_replace($output, '', strrpos($output, '/'));
389
-			}
390
-			// D: if the input buffer consists only of "." or "..", then remove
391
-			// that from the input buffer; otherwise,
392
-			elseif ($input === '.' || $input === '..') {
393
-				$input = '';
394
-			}
395
-			// E: move the first path segment in the input buffer to the end of
396
-			// the output buffer, including the initial "/" character (if any)
397
-			// and any subsequent characters up to, but not including, the next
398
-			// "/" character or the end of the input buffer
399
-			elseif (($pos = strpos($input, '/', 1)) !== false) {
400
-				$output .= substr($input, 0, $pos);
401
-				$input = substr_replace($input, '', 0, $pos);
402
-			}
403
-			else {
404
-				$output .= $input;
405
-				$input = '';
406
-			}
407
-		}
408
-		return $output . $input;
409
-	}
410
-
411
-	/**
412
-	 * Replace invalid character with percent encoding
413
-	 *
414
-	 * @param string $string Input string
415
-	 * @param string $extra_chars Valid characters not in iunreserved or
416
-	 *                            iprivate (this is ASCII-only)
417
-	 * @param bool $iprivate Allow iprivate
418
-	 * @return string
419
-	 */
420
-	protected function replace_invalid_with_pct_encoding($string, $extra_chars, $iprivate = false) {
421
-		// Normalize as many pct-encoded sections as possible
422
-		$string = preg_replace_callback('/(?:%[A-Fa-f0-9]{2})+/', array(&$this, 'remove_iunreserved_percent_encoded'), $string);
423
-
424
-		// Replace invalid percent characters
425
-		$string = preg_replace('/%(?![A-Fa-f0-9]{2})/', '%25', $string);
426
-
427
-		// Add unreserved and % to $extra_chars (the latter is safe because all
428
-		// pct-encoded sections are now valid).
429
-		$extra_chars .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~%';
430
-
431
-		// Now replace any bytes that aren't allowed with their pct-encoded versions
432
-		$position = 0;
433
-		$strlen = strlen($string);
434
-		while (($position += strspn($string, $extra_chars, $position)) < $strlen) {
435
-			$value = ord($string[$position]);
436
-
437
-			// Start position
438
-			$start = $position;
439
-
440
-			// By default we are valid
441
-			$valid = true;
442
-
443
-			// No one byte sequences are valid due to the while.
444
-			// Two byte sequence:
445
-			if (($value & 0xE0) === 0xC0) {
446
-				$character = ($value & 0x1F) << 6;
447
-				$length = 2;
448
-				$remaining = 1;
449
-			}
450
-			// Three byte sequence:
451
-			elseif (($value & 0xF0) === 0xE0) {
452
-				$character = ($value & 0x0F) << 12;
453
-				$length = 3;
454
-				$remaining = 2;
455
-			}
456
-			// Four byte sequence:
457
-			elseif (($value & 0xF8) === 0xF0) {
458
-				$character = ($value & 0x07) << 18;
459
-				$length = 4;
460
-				$remaining = 3;
461
-			}
462
-			// Invalid byte:
463
-			else {
464
-				$valid = false;
465
-				$length = 1;
466
-				$remaining = 0;
467
-			}
468
-
469
-			if ($remaining) {
470
-				if ($position + $length <= $strlen) {
471
-					for ($position++; $remaining; $position++) {
472
-						$value = ord($string[$position]);
473
-
474
-						// Check that the byte is valid, then add it to the character:
475
-						if (($value & 0xC0) === 0x80) {
476
-							$character |= ($value & 0x3F) << (--$remaining * 6);
477
-						}
478
-						// If it is invalid, count the sequence as invalid and reprocess the current byte:
479
-						else {
480
-							$valid = false;
481
-							$position--;
482
-							break;
483
-						}
484
-					}
485
-				}
486
-				else {
487
-					$position = $strlen - 1;
488
-					$valid = false;
489
-				}
490
-			}
491
-
492
-			// Percent encode anything invalid or not in ucschar
493
-			if (
494
-				// Invalid sequences
495
-				!$valid
496
-				// Non-shortest form sequences are invalid
497
-				|| $length > 1 && $character <= 0x7F
498
-				|| $length > 2 && $character <= 0x7FF
499
-				|| $length > 3 && $character <= 0xFFFF
500
-				// Outside of range of ucschar codepoints
501
-				// Noncharacters
502
-				|| ($character & 0xFFFE) === 0xFFFE
503
-				|| $character >= 0xFDD0 && $character <= 0xFDEF
504
-				|| (
505
-					// Everything else not in ucschar
506
-					   $character > 0xD7FF && $character < 0xF900
507
-					|| $character < 0xA0
508
-					|| $character > 0xEFFFD
509
-				)
510
-				&& (
511
-					// Everything not in iprivate, if it applies
512
-					   !$iprivate
513
-					|| $character < 0xE000
514
-					|| $character > 0x10FFFD
515
-				)
516
-			) {
517
-				// If we were a character, pretend we weren't, but rather an error.
518
-				if ($valid) {
519
-					$position--;
520
-				}
521
-
522
-				for ($j = $start; $j <= $position; $j++) {
523
-					$string = substr_replace($string, sprintf('%%%02X', ord($string[$j])), $j, 1);
524
-					$j += 2;
525
-					$position += 2;
526
-					$strlen += 2;
527
-				}
528
-			}
529
-		}
530
-
531
-		return $string;
532
-	}
533
-
534
-	/**
535
-	 * Callback function for preg_replace_callback.
536
-	 *
537
-	 * Removes sequences of percent encoded bytes that represent UTF-8
538
-	 * encoded characters in iunreserved
539
-	 *
540
-	 * @param array $match PCRE match
541
-	 * @return string Replacement
542
-	 */
543
-	protected function remove_iunreserved_percent_encoded($match) {
544
-		// As we just have valid percent encoded sequences we can just explode
545
-		// and ignore the first member of the returned array (an empty string).
546
-		$bytes = explode('%', $match[0]);
547
-
548
-		// Initialize the new string (this is what will be returned) and that
549
-		// there are no bytes remaining in the current sequence (unsurprising
550
-		// at the first byte!).
551
-		$string = '';
552
-		$remaining = 0;
553
-
554
-		// Loop over each and every byte, and set $value to its value
555
-		for ($i = 1, $len = count($bytes); $i < $len; $i++) {
556
-			$value = hexdec($bytes[$i]);
557
-
558
-			// If we're the first byte of sequence:
559
-			if (!$remaining) {
560
-				// Start position
561
-				$start = $i;
562
-
563
-				// By default we are valid
564
-				$valid = true;
565
-
566
-				// One byte sequence:
567
-				if ($value <= 0x7F) {
568
-					$character = $value;
569
-					$length = 1;
570
-				}
571
-				// Two byte sequence:
572
-				elseif (($value & 0xE0) === 0xC0) {
573
-					$character = ($value & 0x1F) << 6;
574
-					$length = 2;
575
-					$remaining = 1;
576
-				}
577
-				// Three byte sequence:
578
-				elseif (($value & 0xF0) === 0xE0) {
579
-					$character = ($value & 0x0F) << 12;
580
-					$length = 3;
581
-					$remaining = 2;
582
-				}
583
-				// Four byte sequence:
584
-				elseif (($value & 0xF8) === 0xF0) {
585
-					$character = ($value & 0x07) << 18;
586
-					$length = 4;
587
-					$remaining = 3;
588
-				}
589
-				// Invalid byte:
590
-				else {
591
-					$valid = false;
592
-					$remaining = 0;
593
-				}
594
-			}
595
-			// Continuation byte:
596
-			else {
597
-				// Check that the byte is valid, then add it to the character:
598
-				if (($value & 0xC0) === 0x80) {
599
-					$remaining--;
600
-					$character |= ($value & 0x3F) << ($remaining * 6);
601
-				}
602
-				// If it is invalid, count the sequence as invalid and reprocess the current byte as the start of a sequence:
603
-				else {
604
-					$valid = false;
605
-					$remaining = 0;
606
-					$i--;
607
-				}
608
-			}
609
-
610
-			// If we've reached the end of the current byte sequence, append it to Unicode::$data
611
-			if (!$remaining) {
612
-				// Percent encode anything invalid or not in iunreserved
613
-				if (
614
-					// Invalid sequences
615
-					!$valid
616
-					// Non-shortest form sequences are invalid
617
-					|| $length > 1 && $character <= 0x7F
618
-					|| $length > 2 && $character <= 0x7FF
619
-					|| $length > 3 && $character <= 0xFFFF
620
-					// Outside of range of iunreserved codepoints
621
-					|| $character < 0x2D
622
-					|| $character > 0xEFFFD
623
-					// Noncharacters
624
-					|| ($character & 0xFFFE) === 0xFFFE
625
-					|| $character >= 0xFDD0 && $character <= 0xFDEF
626
-					// Everything else not in iunreserved (this is all BMP)
627
-					|| $character === 0x2F
628
-					|| $character > 0x39 && $character < 0x41
629
-					|| $character > 0x5A && $character < 0x61
630
-					|| $character > 0x7A && $character < 0x7E
631
-					|| $character > 0x7E && $character < 0xA0
632
-					|| $character > 0xD7FF && $character < 0xF900
633
-				) {
634
-					for ($j = $start; $j <= $i; $j++) {
635
-						$string .= '%' . strtoupper($bytes[$j]);
636
-					}
637
-				}
638
-				else {
639
-					for ($j = $start; $j <= $i; $j++) {
640
-						$string .= chr(hexdec($bytes[$j]));
641
-					}
642
-				}
643
-			}
644
-		}
645
-
646
-		// If we have any bytes left over they are invalid (i.e., we are
647
-		// mid-way through a multi-byte sequence)
648
-		if ($remaining) {
649
-			for ($j = $start; $j < $len; $j++) {
650
-				$string .= '%' . strtoupper($bytes[$j]);
651
-			}
652
-		}
653
-
654
-		return $string;
655
-	}
656
-
657
-	protected function scheme_normalization() {
658
-		if (isset($this->normalization[$this->scheme]['iuserinfo']) && $this->iuserinfo === $this->normalization[$this->scheme]['iuserinfo']) {
659
-			$this->iuserinfo = null;
660
-		}
661
-		if (isset($this->normalization[$this->scheme]['ihost']) && $this->ihost === $this->normalization[$this->scheme]['ihost']) {
662
-			$this->ihost = null;
663
-		}
664
-		if (isset($this->normalization[$this->scheme]['port']) && $this->port === $this->normalization[$this->scheme]['port']) {
665
-			$this->port = null;
666
-		}
667
-		if (isset($this->normalization[$this->scheme]['ipath']) && $this->ipath === $this->normalization[$this->scheme]['ipath']) {
668
-			$this->ipath = '';
669
-		}
670
-		if (isset($this->ihost) && empty($this->ipath)) {
671
-			$this->ipath = '/';
672
-		}
673
-		if (isset($this->normalization[$this->scheme]['iquery']) && $this->iquery === $this->normalization[$this->scheme]['iquery']) {
674
-			$this->iquery = null;
675
-		}
676
-		if (isset($this->normalization[$this->scheme]['ifragment']) && $this->ifragment === $this->normalization[$this->scheme]['ifragment']) {
677
-			$this->ifragment = null;
678
-		}
679
-	}
680
-
681
-	/**
682
-	 * Check if the object represents a valid IRI. This needs to be done on each
683
-	 * call as some things change depending on another part of the IRI.
684
-	 *
685
-	 * @return bool
686
-	 */
687
-	public function is_valid() {
688
-		$isauthority = $this->iuserinfo !== null || $this->ihost !== null || $this->port !== null;
689
-		if ($this->ipath !== '' &&
690
-			(
691
-				$isauthority && $this->ipath[0] !== '/' ||
692
-				(
693
-					$this->scheme === null &&
694
-					!$isauthority &&
695
-					strpos($this->ipath, ':') !== false &&
696
-					(strpos($this->ipath, '/') === false ? true : strpos($this->ipath, ':') < strpos($this->ipath, '/'))
697
-				)
698
-			)
699
-		) {
700
-			return false;
701
-		}
702
-
703
-		return true;
704
-	}
705
-
706
-	/**
707
-	 * Set the entire IRI. Returns true on success, false on failure (if there
708
-	 * are any invalid characters).
709
-	 *
710
-	 * @param string $iri
711
-	 * @return bool
712
-	 */
713
-	protected function set_iri($iri) {
714
-		static $cache;
715
-		if (!$cache) {
716
-			$cache = array();
717
-		}
718
-
719
-		if ($iri === null) {
720
-			return true;
721
-		}
722
-		if (isset($cache[$iri])) {
723
-			list($this->scheme,
724
-				 $this->iuserinfo,
725
-				 $this->ihost,
726
-				 $this->port,
727
-				 $this->ipath,
728
-				 $this->iquery,
729
-				 $this->ifragment,
730
-				 $return) = $cache[$iri];
731
-			return $return;
732
-		}
733
-
734
-		$parsed = $this->parse_iri((string) $iri);
735
-
736
-		$return = $this->set_scheme($parsed['scheme'])
737
-			&& $this->set_authority($parsed['authority'])
738
-			&& $this->set_path($parsed['path'])
739
-			&& $this->set_query($parsed['query'])
740
-			&& $this->set_fragment($parsed['fragment']);
741
-
742
-		$cache[$iri] = array($this->scheme,
743
-							 $this->iuserinfo,
744
-							 $this->ihost,
745
-							 $this->port,
746
-							 $this->ipath,
747
-							 $this->iquery,
748
-							 $this->ifragment,
749
-							 $return);
750
-		return $return;
751
-	}
752
-
753
-	/**
754
-	 * Set the scheme. Returns true on success, false on failure (if there are
755
-	 * any invalid characters).
756
-	 *
757
-	 * @param string $scheme
758
-	 * @return bool
759
-	 */
760
-	protected function set_scheme($scheme) {
761
-		if ($scheme === null) {
762
-			$this->scheme = null;
763
-		}
764
-		elseif (!preg_match('/^[A-Za-z][0-9A-Za-z+\-.]*$/', $scheme)) {
765
-			$this->scheme = null;
766
-			return false;
767
-		}
768
-		else {
769
-			$this->scheme = strtolower($scheme);
770
-		}
771
-		return true;
772
-	}
773
-
774
-	/**
775
-	 * Set the authority. Returns true on success, false on failure (if there are
776
-	 * any invalid characters).
777
-	 *
778
-	 * @param string $authority
779
-	 * @return bool
780
-	 */
781
-	protected function set_authority($authority) {
782
-		static $cache;
783
-		if (!$cache) {
784
-			$cache = array();
785
-		}
786
-
787
-		if ($authority === null) {
788
-			$this->iuserinfo = null;
789
-			$this->ihost = null;
790
-			$this->port = null;
791
-			return true;
792
-		}
793
-		if (isset($cache[$authority])) {
794
-			list($this->iuserinfo,
795
-				 $this->ihost,
796
-				 $this->port,
797
-				 $return) = $cache[$authority];
798
-
799
-			return $return;
800
-		}
801
-
802
-		$remaining = $authority;
803
-		if (($iuserinfo_end = strrpos($remaining, '@')) !== false) {
804
-			$iuserinfo = substr($remaining, 0, $iuserinfo_end);
805
-			$remaining = substr($remaining, $iuserinfo_end + 1);
806
-		}
807
-		else {
808
-			$iuserinfo = null;
809
-		}
810
-		if (($port_start = strpos($remaining, ':', strpos($remaining, ']'))) !== false) {
811
-			$port = substr($remaining, $port_start + 1);
812
-			if ($port === false || $port === '') {
813
-				$port = null;
814
-			}
815
-			$remaining = substr($remaining, 0, $port_start);
816
-		}
817
-		else {
818
-			$port = null;
819
-		}
820
-
821
-		$return = $this->set_userinfo($iuserinfo) &&
822
-				  $this->set_host($remaining) &&
823
-				  $this->set_port($port);
824
-
825
-		$cache[$authority] = array($this->iuserinfo,
826
-								   $this->ihost,
827
-								   $this->port,
828
-								   $return);
829
-
830
-		return $return;
831
-	}
832
-
833
-	/**
834
-	 * Set the iuserinfo.
835
-	 *
836
-	 * @param string $iuserinfo
837
-	 * @return bool
838
-	 */
839
-	protected function set_userinfo($iuserinfo) {
840
-		if ($iuserinfo === null) {
841
-			$this->iuserinfo = null;
842
-		}
843
-		else {
844
-			$this->iuserinfo = $this->replace_invalid_with_pct_encoding($iuserinfo, '!$&\'()*+,;=:');
845
-			$this->scheme_normalization();
846
-		}
847
-
848
-		return true;
849
-	}
850
-
851
-	/**
852
-	 * Set the ihost. Returns true on success, false on failure (if there are
853
-	 * any invalid characters).
854
-	 *
855
-	 * @param string $ihost
856
-	 * @return bool
857
-	 */
858
-	protected function set_host($ihost) {
859
-		if ($ihost === null) {
860
-			$this->ihost = null;
861
-			return true;
862
-		}
863
-		if (substr($ihost, 0, 1) === '[' && substr($ihost, -1) === ']') {
864
-			if (Requests_IPv6::check_ipv6(substr($ihost, 1, -1))) {
865
-				$this->ihost = '[' . Requests_IPv6::compress(substr($ihost, 1, -1)) . ']';
866
-			}
867
-			else {
868
-				$this->ihost = null;
869
-				return false;
870
-			}
871
-		}
872
-		else {
873
-			$ihost = $this->replace_invalid_with_pct_encoding($ihost, '!$&\'()*+,;=');
874
-
875
-			// Lowercase, but ignore pct-encoded sections (as they should
876
-			// remain uppercase). This must be done after the previous step
877
-			// as that can add unescaped characters.
878
-			$position = 0;
879
-			$strlen = strlen($ihost);
880
-			while (($position += strcspn($ihost, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ%', $position)) < $strlen) {
881
-				if ($ihost[$position] === '%') {
882
-					$position += 3;
883
-				}
884
-				else {
885
-					$ihost[$position] = strtolower($ihost[$position]);
886
-					$position++;
887
-				}
888
-			}
889
-
890
-			$this->ihost = $ihost;
891
-		}
892
-
893
-		$this->scheme_normalization();
894
-
895
-		return true;
896
-	}
897
-
898
-	/**
899
-	 * Set the port. Returns true on success, false on failure (if there are
900
-	 * any invalid characters).
901
-	 *
902
-	 * @param string $port
903
-	 * @return bool
904
-	 */
905
-	protected function set_port($port) {
906
-		if ($port === null) {
907
-			$this->port = null;
908
-			return true;
909
-		}
910
-
911
-		if (strspn($port, '0123456789') === strlen($port)) {
912
-			$this->port = (int) $port;
913
-			$this->scheme_normalization();
914
-			return true;
915
-		}
916
-
917
-		$this->port = null;
918
-		return false;
919
-	}
920
-
921
-	/**
922
-	 * Set the ipath.
923
-	 *
924
-	 * @param string $ipath
925
-	 * @return bool
926
-	 */
927
-	protected function set_path($ipath) {
928
-		static $cache;
929
-		if (!$cache) {
930
-			$cache = array();
931
-		}
932
-
933
-		$ipath = (string) $ipath;
934
-
935
-		if (isset($cache[$ipath])) {
936
-			$this->ipath = $cache[$ipath][(int) ($this->scheme !== null)];
937
-		}
938
-		else {
939
-			$valid = $this->replace_invalid_with_pct_encoding($ipath, '!$&\'()*+,;=@:/');
940
-			$removed = $this->remove_dot_segments($valid);
941
-
942
-			$cache[$ipath] = array($valid, $removed);
943
-			$this->ipath = ($this->scheme !== null) ? $removed : $valid;
944
-		}
945
-		$this->scheme_normalization();
946
-		return true;
947
-	}
948
-
949
-	/**
950
-	 * Set the iquery.
951
-	 *
952
-	 * @param string $iquery
953
-	 * @return bool
954
-	 */
955
-	protected function set_query($iquery) {
956
-		if ($iquery === null) {
957
-			$this->iquery = null;
958
-		}
959
-		else {
960
-			$this->iquery = $this->replace_invalid_with_pct_encoding($iquery, '!$&\'()*+,;=:@/?', true);
961
-			$this->scheme_normalization();
962
-		}
963
-		return true;
964
-	}
965
-
966
-	/**
967
-	 * Set the ifragment.
968
-	 *
969
-	 * @param string $ifragment
970
-	 * @return bool
971
-	 */
972
-	protected function set_fragment($ifragment) {
973
-		if ($ifragment === null) {
974
-			$this->ifragment = null;
975
-		}
976
-		else {
977
-			$this->ifragment = $this->replace_invalid_with_pct_encoding($ifragment, '!$&\'()*+,;=:@/?');
978
-			$this->scheme_normalization();
979
-		}
980
-		return true;
981
-	}
982
-
983
-	/**
984
-	 * Convert an IRI to a URI (or parts thereof)
985
-	 *
986
-	 * @param string|bool IRI to convert (or false from {@see get_iri})
987
-	 * @return string|false URI if IRI is valid, false otherwise.
988
-	 */
989
-	protected function to_uri($string) {
990
-		if (!is_string($string)) {
991
-			return false;
992
-		}
993
-
994
-		static $non_ascii;
995
-		if (!$non_ascii) {
996
-			$non_ascii = implode('', range("\x80", "\xFF"));
997
-		}
998
-
999
-		$position = 0;
1000
-		$strlen = strlen($string);
1001
-		while (($position += strcspn($string, $non_ascii, $position)) < $strlen) {
1002
-			$string = substr_replace($string, sprintf('%%%02X', ord($string[$position])), $position, 1);
1003
-			$position += 3;
1004
-			$strlen += 2;
1005
-		}
1006
-
1007
-		return $string;
1008
-	}
1009
-
1010
-	/**
1011
-	 * Get the complete IRI
1012
-	 *
1013
-	 * @return string
1014
-	 */
1015
-	protected function get_iri() {
1016
-		if (!$this->is_valid()) {
1017
-			return false;
1018
-		}
1019
-
1020
-		$iri = '';
1021
-		if ($this->scheme !== null) {
1022
-			$iri .= $this->scheme . ':';
1023
-		}
1024
-		if (($iauthority = $this->get_iauthority()) !== null) {
1025
-			$iri .= '//' . $iauthority;
1026
-		}
1027
-		$iri .= $this->ipath;
1028
-		if ($this->iquery !== null) {
1029
-			$iri .= '?' . $this->iquery;
1030
-		}
1031
-		if ($this->ifragment !== null) {
1032
-			$iri .= '#' . $this->ifragment;
1033
-		}
1034
-
1035
-		return $iri;
1036
-	}
1037
-
1038
-	/**
1039
-	 * Get the complete URI
1040
-	 *
1041
-	 * @return string
1042
-	 */
1043
-	protected function get_uri() {
1044
-		return $this->to_uri($this->get_iri());
1045
-	}
1046
-
1047
-	/**
1048
-	 * Get the complete iauthority
1049
-	 *
1050
-	 * @return string
1051
-	 */
1052
-	protected function get_iauthority() {
1053
-		if ($this->iuserinfo === null && $this->ihost === null && $this->port === null) {
1054
-			return null;
1055
-		}
1056
-
1057
-		$iauthority = '';
1058
-		if ($this->iuserinfo !== null) {
1059
-			$iauthority .= $this->iuserinfo . '@';
1060
-		}
1061
-		if ($this->ihost !== null) {
1062
-			$iauthority .= $this->ihost;
1063
-		}
1064
-		if ($this->port !== null) {
1065
-			$iauthority .= ':' . $this->port;
1066
-		}
1067
-		return $iauthority;
1068
-	}
1069
-
1070
-	/**
1071
-	 * Get the complete authority
1072
-	 *
1073
-	 * @return string
1074
-	 */
1075
-	protected function get_authority() {
1076
-		$iauthority = $this->get_iauthority();
1077
-		if (is_string($iauthority)) {
1078
-			return $this->to_uri($iauthority);
1079
-		}
1080
-		else {
1081
-			return $iauthority;
1082
-		}
1083
-	}
67
+    /**
68
+     * Scheme
69
+     *
70
+     * @var string
71
+     */
72
+    protected $scheme = null;
73
+
74
+    /**
75
+     * User Information
76
+     *
77
+     * @var string
78
+     */
79
+    protected $iuserinfo = null;
80
+
81
+    /**
82
+     * ihost
83
+     *
84
+     * @var string
85
+     */
86
+    protected $ihost = null;
87
+
88
+    /**
89
+     * Port
90
+     *
91
+     * @var string
92
+     */
93
+    protected $port = null;
94
+
95
+    /**
96
+     * ipath
97
+     *
98
+     * @var string
99
+     */
100
+    protected $ipath = '';
101
+
102
+    /**
103
+     * iquery
104
+     *
105
+     * @var string
106
+     */
107
+    protected $iquery = null;
108
+
109
+    /**
110
+     * ifragment
111
+     *
112
+     * @var string
113
+     */
114
+    protected $ifragment = null;
115
+
116
+    /**
117
+     * Normalization database
118
+     *
119
+     * Each key is the scheme, each value is an array with each key as the IRI
120
+     * part and value as the default value for that part.
121
+     */
122
+    protected $normalization = array(
123
+        'acap' => array(
124
+            'port' => 674
125
+        ),
126
+        'dict' => array(
127
+            'port' => 2628
128
+        ),
129
+        'file' => array(
130
+            'ihost' => 'localhost'
131
+        ),
132
+        'http' => array(
133
+            'port' => 80,
134
+        ),
135
+        'https' => array(
136
+            'port' => 443,
137
+        ),
138
+    );
139
+
140
+    /**
141
+     * Return the entire IRI when you try and read the object as a string
142
+     *
143
+     * @return string
144
+     */
145
+    public function __toString() {
146
+        return $this->get_iri();
147
+    }
148
+
149
+    /**
150
+     * Overload __set() to provide access via properties
151
+     *
152
+     * @param string $name Property name
153
+     * @param mixed $value Property value
154
+     */
155
+    public function __set($name, $value) {
156
+        if (method_exists($this, 'set_' . $name)) {
157
+            call_user_func(array($this, 'set_' . $name), $value);
158
+        }
159
+        elseif (
160
+                $name === 'iauthority'
161
+            || $name === 'iuserinfo'
162
+            || $name === 'ihost'
163
+            || $name === 'ipath'
164
+            || $name === 'iquery'
165
+            || $name === 'ifragment'
166
+        ) {
167
+            call_user_func(array($this, 'set_' . substr($name, 1)), $value);
168
+        }
169
+    }
170
+
171
+    /**
172
+     * Overload __get() to provide access via properties
173
+     *
174
+     * @param string $name Property name
175
+     * @return mixed
176
+     */
177
+    public function __get($name) {
178
+        // isset() returns false for null, we don't want to do that
179
+        // Also why we use array_key_exists below instead of isset()
180
+        $props = get_object_vars($this);
181
+
182
+        if (
183
+            $name === 'iri' ||
184
+            $name === 'uri' ||
185
+            $name === 'iauthority' ||
186
+            $name === 'authority'
187
+        ) {
188
+            $method = 'get_' . $name;
189
+            $return = $this->$method();
190
+        }
191
+        elseif (array_key_exists($name, $props)) {
192
+            $return = $this->$name;
193
+        }
194
+        // host -> ihost
195
+        elseif (($prop = 'i' . $name) && array_key_exists($prop, $props)) {
196
+            $name = $prop;
197
+            $return = $this->$prop;
198
+        }
199
+        // ischeme -> scheme
200
+        elseif (($prop = substr($name, 1)) && array_key_exists($prop, $props)) {
201
+            $name = $prop;
202
+            $return = $this->$prop;
203
+        }
204
+        else {
205
+            trigger_error('Undefined property: ' . get_class($this) . '::' . $name, E_USER_NOTICE);
206
+            $return = null;
207
+        }
208
+
209
+        if ($return === null && isset($this->normalization[$this->scheme][$name])) {
210
+            return $this->normalization[$this->scheme][$name];
211
+        }
212
+        else {
213
+            return $return;
214
+        }
215
+    }
216
+
217
+    /**
218
+     * Overload __isset() to provide access via properties
219
+     *
220
+     * @param string $name Property name
221
+     * @return bool
222
+     */
223
+    public function __isset($name) {
224
+        return (method_exists($this, 'get_' . $name) || isset($this->$name));
225
+    }
226
+
227
+    /**
228
+     * Overload __unset() to provide access via properties
229
+     *
230
+     * @param string $name Property name
231
+     */
232
+    public function __unset($name) {
233
+        if (method_exists($this, 'set_' . $name)) {
234
+            call_user_func(array($this, 'set_' . $name), '');
235
+        }
236
+    }
237
+
238
+    /**
239
+     * Create a new IRI object, from a specified string
240
+     *
241
+     * @param string|null $iri
242
+     */
243
+    public function __construct($iri = null) {
244
+        $this->set_iri($iri);
245
+    }
246
+
247
+    /**
248
+     * Create a new IRI object by resolving a relative IRI
249
+     *
250
+     * Returns false if $base is not absolute, otherwise an IRI.
251
+     *
252
+     * @param IRI|string $base (Absolute) Base IRI
253
+     * @param IRI|string $relative Relative IRI
254
+     * @return IRI|false
255
+     */
256
+    public static function absolutize($base, $relative) {
257
+        if (!($relative instanceof Requests_IRI)) {
258
+            $relative = new Requests_IRI($relative);
259
+        }
260
+        if (!$relative->is_valid()) {
261
+            return false;
262
+        }
263
+        elseif ($relative->scheme !== null) {
264
+            return clone $relative;
265
+        }
266
+
267
+        if (!($base instanceof Requests_IRI)) {
268
+            $base = new Requests_IRI($base);
269
+        }
270
+        if ($base->scheme === null || !$base->is_valid()) {
271
+            return false;
272
+        }
273
+
274
+        if ($relative->get_iri() !== '') {
275
+            if ($relative->iuserinfo !== null || $relative->ihost !== null || $relative->port !== null) {
276
+                $target = clone $relative;
277
+                $target->scheme = $base->scheme;
278
+            }
279
+            else {
280
+                $target = new Requests_IRI;
281
+                $target->scheme = $base->scheme;
282
+                $target->iuserinfo = $base->iuserinfo;
283
+                $target->ihost = $base->ihost;
284
+                $target->port = $base->port;
285
+                if ($relative->ipath !== '') {
286
+                    if ($relative->ipath[0] === '/') {
287
+                        $target->ipath = $relative->ipath;
288
+                    }
289
+                    elseif (($base->iuserinfo !== null || $base->ihost !== null || $base->port !== null) && $base->ipath === '') {
290
+                        $target->ipath = '/' . $relative->ipath;
291
+                    }
292
+                    elseif (($last_segment = strrpos($base->ipath, '/')) !== false) {
293
+                        $target->ipath = substr($base->ipath, 0, $last_segment + 1) . $relative->ipath;
294
+                    }
295
+                    else {
296
+                        $target->ipath = $relative->ipath;
297
+                    }
298
+                    $target->ipath = $target->remove_dot_segments($target->ipath);
299
+                    $target->iquery = $relative->iquery;
300
+                }
301
+                else {
302
+                    $target->ipath = $base->ipath;
303
+                    if ($relative->iquery !== null) {
304
+                        $target->iquery = $relative->iquery;
305
+                    }
306
+                    elseif ($base->iquery !== null) {
307
+                        $target->iquery = $base->iquery;
308
+                    }
309
+                }
310
+                $target->ifragment = $relative->ifragment;
311
+            }
312
+        }
313
+        else {
314
+            $target = clone $base;
315
+            $target->ifragment = null;
316
+        }
317
+        $target->scheme_normalization();
318
+        return $target;
319
+    }
320
+
321
+    /**
322
+     * Parse an IRI into scheme/authority/path/query/fragment segments
323
+     *
324
+     * @param string $iri
325
+     * @return array
326
+     */
327
+    protected function parse_iri($iri) {
328
+        $iri = trim($iri, "\x20\x09\x0A\x0C\x0D");
329
+        $has_match = preg_match('/^((?P<scheme>[^:\/?#]+):)?(\/\/(?P<authority>[^\/?#]*))?(?P<path>[^?#]*)(\?(?P<query>[^#]*))?(#(?P<fragment>.*))?$/', $iri, $match);
330
+        if (!$has_match) {
331
+            throw new Requests_Exception('Cannot parse supplied IRI', 'iri.cannot_parse', $iri);
332
+        }
333
+
334
+        if ($match[1] === '') {
335
+            $match['scheme'] = null;
336
+        }
337
+        if (!isset($match[3]) || $match[3] === '') {
338
+            $match['authority'] = null;
339
+        }
340
+        if (!isset($match[5])) {
341
+            $match['path'] = '';
342
+        }
343
+        if (!isset($match[6]) || $match[6] === '') {
344
+            $match['query'] = null;
345
+        }
346
+        if (!isset($match[8]) || $match[8] === '') {
347
+            $match['fragment'] = null;
348
+        }
349
+        return $match;
350
+    }
351
+
352
+    /**
353
+     * Remove dot segments from a path
354
+     *
355
+     * @param string $input
356
+     * @return string
357
+     */
358
+    protected function remove_dot_segments($input) {
359
+        $output = '';
360
+        while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..') {
361
+            // A: If the input buffer begins with a prefix of "../" or "./",
362
+            // then remove that prefix from the input buffer; otherwise,
363
+            if (strpos($input, '../') === 0) {
364
+                $input = substr($input, 3);
365
+            }
366
+            elseif (strpos($input, './') === 0) {
367
+                $input = substr($input, 2);
368
+            }
369
+            // B: if the input buffer begins with a prefix of "/./" or "/.",
370
+            // where "." is a complete path segment, then replace that prefix
371
+            // with "/" in the input buffer; otherwise,
372
+            elseif (strpos($input, '/./') === 0) {
373
+                $input = substr($input, 2);
374
+            }
375
+            elseif ($input === '/.') {
376
+                $input = '/';
377
+            }
378
+            // C: if the input buffer begins with a prefix of "/../" or "/..",
379
+            // where ".." is a complete path segment, then replace that prefix
380
+            // with "/" in the input buffer and remove the last segment and its
381
+            // preceding "/" (if any) from the output buffer; otherwise,
382
+            elseif (strpos($input, '/../') === 0) {
383
+                $input = substr($input, 3);
384
+                $output = substr_replace($output, '', strrpos($output, '/'));
385
+            }
386
+            elseif ($input === '/..') {
387
+                $input = '/';
388
+                $output = substr_replace($output, '', strrpos($output, '/'));
389
+            }
390
+            // D: if the input buffer consists only of "." or "..", then remove
391
+            // that from the input buffer; otherwise,
392
+            elseif ($input === '.' || $input === '..') {
393
+                $input = '';
394
+            }
395
+            // E: move the first path segment in the input buffer to the end of
396
+            // the output buffer, including the initial "/" character (if any)
397
+            // and any subsequent characters up to, but not including, the next
398
+            // "/" character or the end of the input buffer
399
+            elseif (($pos = strpos($input, '/', 1)) !== false) {
400
+                $output .= substr($input, 0, $pos);
401
+                $input = substr_replace($input, '', 0, $pos);
402
+            }
403
+            else {
404
+                $output .= $input;
405
+                $input = '';
406
+            }
407
+        }
408
+        return $output . $input;
409
+    }
410
+
411
+    /**
412
+     * Replace invalid character with percent encoding
413
+     *
414
+     * @param string $string Input string
415
+     * @param string $extra_chars Valid characters not in iunreserved or
416
+     *                            iprivate (this is ASCII-only)
417
+     * @param bool $iprivate Allow iprivate
418
+     * @return string
419
+     */
420
+    protected function replace_invalid_with_pct_encoding($string, $extra_chars, $iprivate = false) {
421
+        // Normalize as many pct-encoded sections as possible
422
+        $string = preg_replace_callback('/(?:%[A-Fa-f0-9]{2})+/', array(&$this, 'remove_iunreserved_percent_encoded'), $string);
423
+
424
+        // Replace invalid percent characters
425
+        $string = preg_replace('/%(?![A-Fa-f0-9]{2})/', '%25', $string);
426
+
427
+        // Add unreserved and % to $extra_chars (the latter is safe because all
428
+        // pct-encoded sections are now valid).
429
+        $extra_chars .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~%';
430
+
431
+        // Now replace any bytes that aren't allowed with their pct-encoded versions
432
+        $position = 0;
433
+        $strlen = strlen($string);
434
+        while (($position += strspn($string, $extra_chars, $position)) < $strlen) {
435
+            $value = ord($string[$position]);
436
+
437
+            // Start position
438
+            $start = $position;
439
+
440
+            // By default we are valid
441
+            $valid = true;
442
+
443
+            // No one byte sequences are valid due to the while.
444
+            // Two byte sequence:
445
+            if (($value & 0xE0) === 0xC0) {
446
+                $character = ($value & 0x1F) << 6;
447
+                $length = 2;
448
+                $remaining = 1;
449
+            }
450
+            // Three byte sequence:
451
+            elseif (($value & 0xF0) === 0xE0) {
452
+                $character = ($value & 0x0F) << 12;
453
+                $length = 3;
454
+                $remaining = 2;
455
+            }
456
+            // Four byte sequence:
457
+            elseif (($value & 0xF8) === 0xF0) {
458
+                $character = ($value & 0x07) << 18;
459
+                $length = 4;
460
+                $remaining = 3;
461
+            }
462
+            // Invalid byte:
463
+            else {
464
+                $valid = false;
465
+                $length = 1;
466
+                $remaining = 0;
467
+            }
468
+
469
+            if ($remaining) {
470
+                if ($position + $length <= $strlen) {
471
+                    for ($position++; $remaining; $position++) {
472
+                        $value = ord($string[$position]);
473
+
474
+                        // Check that the byte is valid, then add it to the character:
475
+                        if (($value & 0xC0) === 0x80) {
476
+                            $character |= ($value & 0x3F) << (--$remaining * 6);
477
+                        }
478
+                        // If it is invalid, count the sequence as invalid and reprocess the current byte:
479
+                        else {
480
+                            $valid = false;
481
+                            $position--;
482
+                            break;
483
+                        }
484
+                    }
485
+                }
486
+                else {
487
+                    $position = $strlen - 1;
488
+                    $valid = false;
489
+                }
490
+            }
491
+
492
+            // Percent encode anything invalid or not in ucschar
493
+            if (
494
+                // Invalid sequences
495
+                !$valid
496
+                // Non-shortest form sequences are invalid
497
+                || $length > 1 && $character <= 0x7F
498
+                || $length > 2 && $character <= 0x7FF
499
+                || $length > 3 && $character <= 0xFFFF
500
+                // Outside of range of ucschar codepoints
501
+                // Noncharacters
502
+                || ($character & 0xFFFE) === 0xFFFE
503
+                || $character >= 0xFDD0 && $character <= 0xFDEF
504
+                || (
505
+                    // Everything else not in ucschar
506
+                        $character > 0xD7FF && $character < 0xF900
507
+                    || $character < 0xA0
508
+                    || $character > 0xEFFFD
509
+                )
510
+                && (
511
+                    // Everything not in iprivate, if it applies
512
+                        !$iprivate
513
+                    || $character < 0xE000
514
+                    || $character > 0x10FFFD
515
+                )
516
+            ) {
517
+                // If we were a character, pretend we weren't, but rather an error.
518
+                if ($valid) {
519
+                    $position--;
520
+                }
521
+
522
+                for ($j = $start; $j <= $position; $j++) {
523
+                    $string = substr_replace($string, sprintf('%%%02X', ord($string[$j])), $j, 1);
524
+                    $j += 2;
525
+                    $position += 2;
526
+                    $strlen += 2;
527
+                }
528
+            }
529
+        }
530
+
531
+        return $string;
532
+    }
533
+
534
+    /**
535
+     * Callback function for preg_replace_callback.
536
+     *
537
+     * Removes sequences of percent encoded bytes that represent UTF-8
538
+     * encoded characters in iunreserved
539
+     *
540
+     * @param array $match PCRE match
541
+     * @return string Replacement
542
+     */
543
+    protected function remove_iunreserved_percent_encoded($match) {
544
+        // As we just have valid percent encoded sequences we can just explode
545
+        // and ignore the first member of the returned array (an empty string).
546
+        $bytes = explode('%', $match[0]);
547
+
548
+        // Initialize the new string (this is what will be returned) and that
549
+        // there are no bytes remaining in the current sequence (unsurprising
550
+        // at the first byte!).
551
+        $string = '';
552
+        $remaining = 0;
553
+
554
+        // Loop over each and every byte, and set $value to its value
555
+        for ($i = 1, $len = count($bytes); $i < $len; $i++) {
556
+            $value = hexdec($bytes[$i]);
557
+
558
+            // If we're the first byte of sequence:
559
+            if (!$remaining) {
560
+                // Start position
561
+                $start = $i;
562
+
563
+                // By default we are valid
564
+                $valid = true;
565
+
566
+                // One byte sequence:
567
+                if ($value <= 0x7F) {
568
+                    $character = $value;
569
+                    $length = 1;
570
+                }
571
+                // Two byte sequence:
572
+                elseif (($value & 0xE0) === 0xC0) {
573
+                    $character = ($value & 0x1F) << 6;
574
+                    $length = 2;
575
+                    $remaining = 1;
576
+                }
577
+                // Three byte sequence:
578
+                elseif (($value & 0xF0) === 0xE0) {
579
+                    $character = ($value & 0x0F) << 12;
580
+                    $length = 3;
581
+                    $remaining = 2;
582
+                }
583
+                // Four byte sequence:
584
+                elseif (($value & 0xF8) === 0xF0) {
585
+                    $character = ($value & 0x07) << 18;
586
+                    $length = 4;
587
+                    $remaining = 3;
588
+                }
589
+                // Invalid byte:
590
+                else {
591
+                    $valid = false;
592
+                    $remaining = 0;
593
+                }
594
+            }
595
+            // Continuation byte:
596
+            else {
597
+                // Check that the byte is valid, then add it to the character:
598
+                if (($value & 0xC0) === 0x80) {
599
+                    $remaining--;
600
+                    $character |= ($value & 0x3F) << ($remaining * 6);
601
+                }
602
+                // If it is invalid, count the sequence as invalid and reprocess the current byte as the start of a sequence:
603
+                else {
604
+                    $valid = false;
605
+                    $remaining = 0;
606
+                    $i--;
607
+                }
608
+            }
609
+
610
+            // If we've reached the end of the current byte sequence, append it to Unicode::$data
611
+            if (!$remaining) {
612
+                // Percent encode anything invalid or not in iunreserved
613
+                if (
614
+                    // Invalid sequences
615
+                    !$valid
616
+                    // Non-shortest form sequences are invalid
617
+                    || $length > 1 && $character <= 0x7F
618
+                    || $length > 2 && $character <= 0x7FF
619
+                    || $length > 3 && $character <= 0xFFFF
620
+                    // Outside of range of iunreserved codepoints
621
+                    || $character < 0x2D
622
+                    || $character > 0xEFFFD
623
+                    // Noncharacters
624
+                    || ($character & 0xFFFE) === 0xFFFE
625
+                    || $character >= 0xFDD0 && $character <= 0xFDEF
626
+                    // Everything else not in iunreserved (this is all BMP)
627
+                    || $character === 0x2F
628
+                    || $character > 0x39 && $character < 0x41
629
+                    || $character > 0x5A && $character < 0x61
630
+                    || $character > 0x7A && $character < 0x7E
631
+                    || $character > 0x7E && $character < 0xA0
632
+                    || $character > 0xD7FF && $character < 0xF900
633
+                ) {
634
+                    for ($j = $start; $j <= $i; $j++) {
635
+                        $string .= '%' . strtoupper($bytes[$j]);
636
+                    }
637
+                }
638
+                else {
639
+                    for ($j = $start; $j <= $i; $j++) {
640
+                        $string .= chr(hexdec($bytes[$j]));
641
+                    }
642
+                }
643
+            }
644
+        }
645
+
646
+        // If we have any bytes left over they are invalid (i.e., we are
647
+        // mid-way through a multi-byte sequence)
648
+        if ($remaining) {
649
+            for ($j = $start; $j < $len; $j++) {
650
+                $string .= '%' . strtoupper($bytes[$j]);
651
+            }
652
+        }
653
+
654
+        return $string;
655
+    }
656
+
657
+    protected function scheme_normalization() {
658
+        if (isset($this->normalization[$this->scheme]['iuserinfo']) && $this->iuserinfo === $this->normalization[$this->scheme]['iuserinfo']) {
659
+            $this->iuserinfo = null;
660
+        }
661
+        if (isset($this->normalization[$this->scheme]['ihost']) && $this->ihost === $this->normalization[$this->scheme]['ihost']) {
662
+            $this->ihost = null;
663
+        }
664
+        if (isset($this->normalization[$this->scheme]['port']) && $this->port === $this->normalization[$this->scheme]['port']) {
665
+            $this->port = null;
666
+        }
667
+        if (isset($this->normalization[$this->scheme]['ipath']) && $this->ipath === $this->normalization[$this->scheme]['ipath']) {
668
+            $this->ipath = '';
669
+        }
670
+        if (isset($this->ihost) && empty($this->ipath)) {
671
+            $this->ipath = '/';
672
+        }
673
+        if (isset($this->normalization[$this->scheme]['iquery']) && $this->iquery === $this->normalization[$this->scheme]['iquery']) {
674
+            $this->iquery = null;
675
+        }
676
+        if (isset($this->normalization[$this->scheme]['ifragment']) && $this->ifragment === $this->normalization[$this->scheme]['ifragment']) {
677
+            $this->ifragment = null;
678
+        }
679
+    }
680
+
681
+    /**
682
+     * Check if the object represents a valid IRI. This needs to be done on each
683
+     * call as some things change depending on another part of the IRI.
684
+     *
685
+     * @return bool
686
+     */
687
+    public function is_valid() {
688
+        $isauthority = $this->iuserinfo !== null || $this->ihost !== null || $this->port !== null;
689
+        if ($this->ipath !== '' &&
690
+            (
691
+                $isauthority && $this->ipath[0] !== '/' ||
692
+                (
693
+                    $this->scheme === null &&
694
+                    !$isauthority &&
695
+                    strpos($this->ipath, ':') !== false &&
696
+                    (strpos($this->ipath, '/') === false ? true : strpos($this->ipath, ':') < strpos($this->ipath, '/'))
697
+                )
698
+            )
699
+        ) {
700
+            return false;
701
+        }
702
+
703
+        return true;
704
+    }
705
+
706
+    /**
707
+     * Set the entire IRI. Returns true on success, false on failure (if there
708
+     * are any invalid characters).
709
+     *
710
+     * @param string $iri
711
+     * @return bool
712
+     */
713
+    protected function set_iri($iri) {
714
+        static $cache;
715
+        if (!$cache) {
716
+            $cache = array();
717
+        }
718
+
719
+        if ($iri === null) {
720
+            return true;
721
+        }
722
+        if (isset($cache[$iri])) {
723
+            list($this->scheme,
724
+                    $this->iuserinfo,
725
+                    $this->ihost,
726
+                    $this->port,
727
+                    $this->ipath,
728
+                    $this->iquery,
729
+                    $this->ifragment,
730
+                    $return) = $cache[$iri];
731
+            return $return;
732
+        }
733
+
734
+        $parsed = $this->parse_iri((string) $iri);
735
+
736
+        $return = $this->set_scheme($parsed['scheme'])
737
+            && $this->set_authority($parsed['authority'])
738
+            && $this->set_path($parsed['path'])
739
+            && $this->set_query($parsed['query'])
740
+            && $this->set_fragment($parsed['fragment']);
741
+
742
+        $cache[$iri] = array($this->scheme,
743
+                                $this->iuserinfo,
744
+                                $this->ihost,
745
+                                $this->port,
746
+                                $this->ipath,
747
+                                $this->iquery,
748
+                                $this->ifragment,
749
+                                $return);
750
+        return $return;
751
+    }
752
+
753
+    /**
754
+     * Set the scheme. Returns true on success, false on failure (if there are
755
+     * any invalid characters).
756
+     *
757
+     * @param string $scheme
758
+     * @return bool
759
+     */
760
+    protected function set_scheme($scheme) {
761
+        if ($scheme === null) {
762
+            $this->scheme = null;
763
+        }
764
+        elseif (!preg_match('/^[A-Za-z][0-9A-Za-z+\-.]*$/', $scheme)) {
765
+            $this->scheme = null;
766
+            return false;
767
+        }
768
+        else {
769
+            $this->scheme = strtolower($scheme);
770
+        }
771
+        return true;
772
+    }
773
+
774
+    /**
775
+     * Set the authority. Returns true on success, false on failure (if there are
776
+     * any invalid characters).
777
+     *
778
+     * @param string $authority
779
+     * @return bool
780
+     */
781
+    protected function set_authority($authority) {
782
+        static $cache;
783
+        if (!$cache) {
784
+            $cache = array();
785
+        }
786
+
787
+        if ($authority === null) {
788
+            $this->iuserinfo = null;
789
+            $this->ihost = null;
790
+            $this->port = null;
791
+            return true;
792
+        }
793
+        if (isset($cache[$authority])) {
794
+            list($this->iuserinfo,
795
+                    $this->ihost,
796
+                    $this->port,
797
+                    $return) = $cache[$authority];
798
+
799
+            return $return;
800
+        }
801
+
802
+        $remaining = $authority;
803
+        if (($iuserinfo_end = strrpos($remaining, '@')) !== false) {
804
+            $iuserinfo = substr($remaining, 0, $iuserinfo_end);
805
+            $remaining = substr($remaining, $iuserinfo_end + 1);
806
+        }
807
+        else {
808
+            $iuserinfo = null;
809
+        }
810
+        if (($port_start = strpos($remaining, ':', strpos($remaining, ']'))) !== false) {
811
+            $port = substr($remaining, $port_start + 1);
812
+            if ($port === false || $port === '') {
813
+                $port = null;
814
+            }
815
+            $remaining = substr($remaining, 0, $port_start);
816
+        }
817
+        else {
818
+            $port = null;
819
+        }
820
+
821
+        $return = $this->set_userinfo($iuserinfo) &&
822
+                  $this->set_host($remaining) &&
823
+                  $this->set_port($port);
824
+
825
+        $cache[$authority] = array($this->iuserinfo,
826
+                                    $this->ihost,
827
+                                    $this->port,
828
+                                    $return);
829
+
830
+        return $return;
831
+    }
832
+
833
+    /**
834
+     * Set the iuserinfo.
835
+     *
836
+     * @param string $iuserinfo
837
+     * @return bool
838
+     */
839
+    protected function set_userinfo($iuserinfo) {
840
+        if ($iuserinfo === null) {
841
+            $this->iuserinfo = null;
842
+        }
843
+        else {
844
+            $this->iuserinfo = $this->replace_invalid_with_pct_encoding($iuserinfo, '!$&\'()*+,;=:');
845
+            $this->scheme_normalization();
846
+        }
847
+
848
+        return true;
849
+    }
850
+
851
+    /**
852
+     * Set the ihost. Returns true on success, false on failure (if there are
853
+     * any invalid characters).
854
+     *
855
+     * @param string $ihost
856
+     * @return bool
857
+     */
858
+    protected function set_host($ihost) {
859
+        if ($ihost === null) {
860
+            $this->ihost = null;
861
+            return true;
862
+        }
863
+        if (substr($ihost, 0, 1) === '[' && substr($ihost, -1) === ']') {
864
+            if (Requests_IPv6::check_ipv6(substr($ihost, 1, -1))) {
865
+                $this->ihost = '[' . Requests_IPv6::compress(substr($ihost, 1, -1)) . ']';
866
+            }
867
+            else {
868
+                $this->ihost = null;
869
+                return false;
870
+            }
871
+        }
872
+        else {
873
+            $ihost = $this->replace_invalid_with_pct_encoding($ihost, '!$&\'()*+,;=');
874
+
875
+            // Lowercase, but ignore pct-encoded sections (as they should
876
+            // remain uppercase). This must be done after the previous step
877
+            // as that can add unescaped characters.
878
+            $position = 0;
879
+            $strlen = strlen($ihost);
880
+            while (($position += strcspn($ihost, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ%', $position)) < $strlen) {
881
+                if ($ihost[$position] === '%') {
882
+                    $position += 3;
883
+                }
884
+                else {
885
+                    $ihost[$position] = strtolower($ihost[$position]);
886
+                    $position++;
887
+                }
888
+            }
889
+
890
+            $this->ihost = $ihost;
891
+        }
892
+
893
+        $this->scheme_normalization();
894
+
895
+        return true;
896
+    }
897
+
898
+    /**
899
+     * Set the port. Returns true on success, false on failure (if there are
900
+     * any invalid characters).
901
+     *
902
+     * @param string $port
903
+     * @return bool
904
+     */
905
+    protected function set_port($port) {
906
+        if ($port === null) {
907
+            $this->port = null;
908
+            return true;
909
+        }
910
+
911
+        if (strspn($port, '0123456789') === strlen($port)) {
912
+            $this->port = (int) $port;
913
+            $this->scheme_normalization();
914
+            return true;
915
+        }
916
+
917
+        $this->port = null;
918
+        return false;
919
+    }
920
+
921
+    /**
922
+     * Set the ipath.
923
+     *
924
+     * @param string $ipath
925
+     * @return bool
926
+     */
927
+    protected function set_path($ipath) {
928
+        static $cache;
929
+        if (!$cache) {
930
+            $cache = array();
931
+        }
932
+
933
+        $ipath = (string) $ipath;
934
+
935
+        if (isset($cache[$ipath])) {
936
+            $this->ipath = $cache[$ipath][(int) ($this->scheme !== null)];
937
+        }
938
+        else {
939
+            $valid = $this->replace_invalid_with_pct_encoding($ipath, '!$&\'()*+,;=@:/');
940
+            $removed = $this->remove_dot_segments($valid);
941
+
942
+            $cache[$ipath] = array($valid, $removed);
943
+            $this->ipath = ($this->scheme !== null) ? $removed : $valid;
944
+        }
945
+        $this->scheme_normalization();
946
+        return true;
947
+    }
948
+
949
+    /**
950
+     * Set the iquery.
951
+     *
952
+     * @param string $iquery
953
+     * @return bool
954
+     */
955
+    protected function set_query($iquery) {
956
+        if ($iquery === null) {
957
+            $this->iquery = null;
958
+        }
959
+        else {
960
+            $this->iquery = $this->replace_invalid_with_pct_encoding($iquery, '!$&\'()*+,;=:@/?', true);
961
+            $this->scheme_normalization();
962
+        }
963
+        return true;
964
+    }
965
+
966
+    /**
967
+     * Set the ifragment.
968
+     *
969
+     * @param string $ifragment
970
+     * @return bool
971
+     */
972
+    protected function set_fragment($ifragment) {
973
+        if ($ifragment === null) {
974
+            $this->ifragment = null;
975
+        }
976
+        else {
977
+            $this->ifragment = $this->replace_invalid_with_pct_encoding($ifragment, '!$&\'()*+,;=:@/?');
978
+            $this->scheme_normalization();
979
+        }
980
+        return true;
981
+    }
982
+
983
+    /**
984
+     * Convert an IRI to a URI (or parts thereof)
985
+     *
986
+     * @param string|bool IRI to convert (or false from {@see get_iri})
987
+     * @return string|false URI if IRI is valid, false otherwise.
988
+     */
989
+    protected function to_uri($string) {
990
+        if (!is_string($string)) {
991
+            return false;
992
+        }
993
+
994
+        static $non_ascii;
995
+        if (!$non_ascii) {
996
+            $non_ascii = implode('', range("\x80", "\xFF"));
997
+        }
998
+
999
+        $position = 0;
1000
+        $strlen = strlen($string);
1001
+        while (($position += strcspn($string, $non_ascii, $position)) < $strlen) {
1002
+            $string = substr_replace($string, sprintf('%%%02X', ord($string[$position])), $position, 1);
1003
+            $position += 3;
1004
+            $strlen += 2;
1005
+        }
1006
+
1007
+        return $string;
1008
+    }
1009
+
1010
+    /**
1011
+     * Get the complete IRI
1012
+     *
1013
+     * @return string
1014
+     */
1015
+    protected function get_iri() {
1016
+        if (!$this->is_valid()) {
1017
+            return false;
1018
+        }
1019
+
1020
+        $iri = '';
1021
+        if ($this->scheme !== null) {
1022
+            $iri .= $this->scheme . ':';
1023
+        }
1024
+        if (($iauthority = $this->get_iauthority()) !== null) {
1025
+            $iri .= '//' . $iauthority;
1026
+        }
1027
+        $iri .= $this->ipath;
1028
+        if ($this->iquery !== null) {
1029
+            $iri .= '?' . $this->iquery;
1030
+        }
1031
+        if ($this->ifragment !== null) {
1032
+            $iri .= '#' . $this->ifragment;
1033
+        }
1034
+
1035
+        return $iri;
1036
+    }
1037
+
1038
+    /**
1039
+     * Get the complete URI
1040
+     *
1041
+     * @return string
1042
+     */
1043
+    protected function get_uri() {
1044
+        return $this->to_uri($this->get_iri());
1045
+    }
1046
+
1047
+    /**
1048
+     * Get the complete iauthority
1049
+     *
1050
+     * @return string
1051
+     */
1052
+    protected function get_iauthority() {
1053
+        if ($this->iuserinfo === null && $this->ihost === null && $this->port === null) {
1054
+            return null;
1055
+        }
1056
+
1057
+        $iauthority = '';
1058
+        if ($this->iuserinfo !== null) {
1059
+            $iauthority .= $this->iuserinfo . '@';
1060
+        }
1061
+        if ($this->ihost !== null) {
1062
+            $iauthority .= $this->ihost;
1063
+        }
1064
+        if ($this->port !== null) {
1065
+            $iauthority .= ':' . $this->port;
1066
+        }
1067
+        return $iauthority;
1068
+    }
1069
+
1070
+    /**
1071
+     * Get the complete authority
1072
+     *
1073
+     * @return string
1074
+     */
1075
+    protected function get_authority() {
1076
+        $iauthority = $this->get_iauthority();
1077
+        if (is_string($iauthority)) {
1078
+            return $this->to_uri($iauthority);
1079
+        }
1080
+        else {
1081
+            return $iauthority;
1082
+        }
1083
+    }
1084 1084
 }
Please login to merge, or discard this patch.
Spacing   +21 added lines, -21 removed lines patch added patch discarded remove patch
@@ -153,8 +153,8 @@  discard block
 block discarded – undo
153 153
 	 * @param mixed $value Property value
154 154
 	 */
155 155
 	public function __set($name, $value) {
156
-		if (method_exists($this, 'set_' . $name)) {
157
-			call_user_func(array($this, 'set_' . $name), $value);
156
+		if (method_exists($this, 'set_'.$name)) {
157
+			call_user_func(array($this, 'set_'.$name), $value);
158 158
 		}
159 159
 		elseif (
160 160
 			   $name === 'iauthority'
@@ -164,7 +164,7 @@  discard block
 block discarded – undo
164 164
 			|| $name === 'iquery'
165 165
 			|| $name === 'ifragment'
166 166
 		) {
167
-			call_user_func(array($this, 'set_' . substr($name, 1)), $value);
167
+			call_user_func(array($this, 'set_'.substr($name, 1)), $value);
168 168
 		}
169 169
 	}
170 170
 
@@ -185,14 +185,14 @@  discard block
 block discarded – undo
185 185
 			$name === 'iauthority' ||
186 186
 			$name === 'authority'
187 187
 		) {
188
-			$method = 'get_' . $name;
188
+			$method = 'get_'.$name;
189 189
 			$return = $this->$method();
190 190
 		}
191 191
 		elseif (array_key_exists($name, $props)) {
192 192
 			$return = $this->$name;
193 193
 		}
194 194
 		// host -> ihost
195
-		elseif (($prop = 'i' . $name) && array_key_exists($prop, $props)) {
195
+		elseif (($prop = 'i'.$name) && array_key_exists($prop, $props)) {
196 196
 			$name = $prop;
197 197
 			$return = $this->$prop;
198 198
 		}
@@ -202,7 +202,7 @@  discard block
 block discarded – undo
202 202
 			$return = $this->$prop;
203 203
 		}
204 204
 		else {
205
-			trigger_error('Undefined property: ' . get_class($this) . '::' . $name, E_USER_NOTICE);
205
+			trigger_error('Undefined property: '.get_class($this).'::'.$name, E_USER_NOTICE);
206 206
 			$return = null;
207 207
 		}
208 208
 
@@ -221,7 +221,7 @@  discard block
 block discarded – undo
221 221
 	 * @return bool
222 222
 	 */
223 223
 	public function __isset($name) {
224
-		return (method_exists($this, 'get_' . $name) || isset($this->$name));
224
+		return (method_exists($this, 'get_'.$name) || isset($this->$name));
225 225
 	}
226 226
 
227 227
 	/**
@@ -230,8 +230,8 @@  discard block
 block discarded – undo
230 230
 	 * @param string $name Property name
231 231
 	 */
232 232
 	public function __unset($name) {
233
-		if (method_exists($this, 'set_' . $name)) {
234
-			call_user_func(array($this, 'set_' . $name), '');
233
+		if (method_exists($this, 'set_'.$name)) {
234
+			call_user_func(array($this, 'set_'.$name), '');
235 235
 		}
236 236
 	}
237 237
 
@@ -287,10 +287,10 @@  discard block
 block discarded – undo
287 287
 						$target->ipath = $relative->ipath;
288 288
 					}
289 289
 					elseif (($base->iuserinfo !== null || $base->ihost !== null || $base->port !== null) && $base->ipath === '') {
290
-						$target->ipath = '/' . $relative->ipath;
290
+						$target->ipath = '/'.$relative->ipath;
291 291
 					}
292 292
 					elseif (($last_segment = strrpos($base->ipath, '/')) !== false) {
293
-						$target->ipath = substr($base->ipath, 0, $last_segment + 1) . $relative->ipath;
293
+						$target->ipath = substr($base->ipath, 0, $last_segment + 1).$relative->ipath;
294 294
 					}
295 295
 					else {
296 296
 						$target->ipath = $relative->ipath;
@@ -405,7 +405,7 @@  discard block
 block discarded – undo
405 405
 				$input = '';
406 406
 			}
407 407
 		}
408
-		return $output . $input;
408
+		return $output.$input;
409 409
 	}
410 410
 
411 411
 	/**
@@ -632,7 +632,7 @@  discard block
 block discarded – undo
632 632
 					|| $character > 0xD7FF && $character < 0xF900
633 633
 				) {
634 634
 					for ($j = $start; $j <= $i; $j++) {
635
-						$string .= '%' . strtoupper($bytes[$j]);
635
+						$string .= '%'.strtoupper($bytes[$j]);
636 636
 					}
637 637
 				}
638 638
 				else {
@@ -647,7 +647,7 @@  discard block
 block discarded – undo
647 647
 		// mid-way through a multi-byte sequence)
648 648
 		if ($remaining) {
649 649
 			for ($j = $start; $j < $len; $j++) {
650
-				$string .= '%' . strtoupper($bytes[$j]);
650
+				$string .= '%'.strtoupper($bytes[$j]);
651 651
 			}
652 652
 		}
653 653
 
@@ -862,7 +862,7 @@  discard block
 block discarded – undo
862 862
 		}
863 863
 		if (substr($ihost, 0, 1) === '[' && substr($ihost, -1) === ']') {
864 864
 			if (Requests_IPv6::check_ipv6(substr($ihost, 1, -1))) {
865
-				$this->ihost = '[' . Requests_IPv6::compress(substr($ihost, 1, -1)) . ']';
865
+				$this->ihost = '['.Requests_IPv6::compress(substr($ihost, 1, -1)).']';
866 866
 			}
867 867
 			else {
868 868
 				$this->ihost = null;
@@ -1019,17 +1019,17 @@  discard block
 block discarded – undo
1019 1019
 
1020 1020
 		$iri = '';
1021 1021
 		if ($this->scheme !== null) {
1022
-			$iri .= $this->scheme . ':';
1022
+			$iri .= $this->scheme.':';
1023 1023
 		}
1024 1024
 		if (($iauthority = $this->get_iauthority()) !== null) {
1025
-			$iri .= '//' . $iauthority;
1025
+			$iri .= '//'.$iauthority;
1026 1026
 		}
1027 1027
 		$iri .= $this->ipath;
1028 1028
 		if ($this->iquery !== null) {
1029
-			$iri .= '?' . $this->iquery;
1029
+			$iri .= '?'.$this->iquery;
1030 1030
 		}
1031 1031
 		if ($this->ifragment !== null) {
1032
-			$iri .= '#' . $this->ifragment;
1032
+			$iri .= '#'.$this->ifragment;
1033 1033
 		}
1034 1034
 
1035 1035
 		return $iri;
@@ -1056,13 +1056,13 @@  discard block
 block discarded – undo
1056 1056
 
1057 1057
 		$iauthority = '';
1058 1058
 		if ($this->iuserinfo !== null) {
1059
-			$iauthority .= $this->iuserinfo . '@';
1059
+			$iauthority .= $this->iuserinfo.'@';
1060 1060
 		}
1061 1061
 		if ($this->ihost !== null) {
1062 1062
 			$iauthority .= $this->ihost;
1063 1063
 		}
1064 1064
 		if ($this->port !== null) {
1065
-			$iauthority .= ':' . $this->port;
1065
+			$iauthority .= ':'.$this->port;
1066 1066
 		}
1067 1067
 		return $iauthority;
1068 1068
 	}
Please login to merge, or discard this patch.
Braces   +30 added lines, -60 removed lines patch added patch discarded remove patch
@@ -155,8 +155,7 @@  discard block
 block discarded – undo
155 155
 	public function __set($name, $value) {
156 156
 		if (method_exists($this, 'set_' . $name)) {
157 157
 			call_user_func(array($this, 'set_' . $name), $value);
158
-		}
159
-		elseif (
158
+		} elseif (
160 159
 			   $name === 'iauthority'
161 160
 			|| $name === 'iuserinfo'
162 161
 			|| $name === 'ihost'
@@ -187,8 +186,7 @@  discard block
 block discarded – undo
187 186
 		) {
188 187
 			$method = 'get_' . $name;
189 188
 			$return = $this->$method();
190
-		}
191
-		elseif (array_key_exists($name, $props)) {
189
+		} elseif (array_key_exists($name, $props)) {
192 190
 			$return = $this->$name;
193 191
 		}
194 192
 		// host -> ihost
@@ -200,16 +198,14 @@  discard block
 block discarded – undo
200 198
 		elseif (($prop = substr($name, 1)) && array_key_exists($prop, $props)) {
201 199
 			$name = $prop;
202 200
 			$return = $this->$prop;
203
-		}
204
-		else {
201
+		} else {
205 202
 			trigger_error('Undefined property: ' . get_class($this) . '::' . $name, E_USER_NOTICE);
206 203
 			$return = null;
207 204
 		}
208 205
 
209 206
 		if ($return === null && isset($this->normalization[$this->scheme][$name])) {
210 207
 			return $this->normalization[$this->scheme][$name];
211
-		}
212
-		else {
208
+		} else {
213 209
 			return $return;
214 210
 		}
215 211
 	}
@@ -259,8 +255,7 @@  discard block
 block discarded – undo
259 255
 		}
260 256
 		if (!$relative->is_valid()) {
261 257
 			return false;
262
-		}
263
-		elseif ($relative->scheme !== null) {
258
+		} elseif ($relative->scheme !== null) {
264 259
 			return clone $relative;
265 260
 		}
266 261
 
@@ -275,8 +270,7 @@  discard block
 block discarded – undo
275 270
 			if ($relative->iuserinfo !== null || $relative->ihost !== null || $relative->port !== null) {
276 271
 				$target = clone $relative;
277 272
 				$target->scheme = $base->scheme;
278
-			}
279
-			else {
273
+			} else {
280 274
 				$target = new Requests_IRI;
281 275
 				$target->scheme = $base->scheme;
282 276
 				$target->iuserinfo = $base->iuserinfo;
@@ -285,32 +279,26 @@  discard block
 block discarded – undo
285 279
 				if ($relative->ipath !== '') {
286 280
 					if ($relative->ipath[0] === '/') {
287 281
 						$target->ipath = $relative->ipath;
288
-					}
289
-					elseif (($base->iuserinfo !== null || $base->ihost !== null || $base->port !== null) && $base->ipath === '') {
282
+					} elseif (($base->iuserinfo !== null || $base->ihost !== null || $base->port !== null) && $base->ipath === '') {
290 283
 						$target->ipath = '/' . $relative->ipath;
291
-					}
292
-					elseif (($last_segment = strrpos($base->ipath, '/')) !== false) {
284
+					} elseif (($last_segment = strrpos($base->ipath, '/')) !== false) {
293 285
 						$target->ipath = substr($base->ipath, 0, $last_segment + 1) . $relative->ipath;
294
-					}
295
-					else {
286
+					} else {
296 287
 						$target->ipath = $relative->ipath;
297 288
 					}
298 289
 					$target->ipath = $target->remove_dot_segments($target->ipath);
299 290
 					$target->iquery = $relative->iquery;
300
-				}
301
-				else {
291
+				} else {
302 292
 					$target->ipath = $base->ipath;
303 293
 					if ($relative->iquery !== null) {
304 294
 						$target->iquery = $relative->iquery;
305
-					}
306
-					elseif ($base->iquery !== null) {
295
+					} elseif ($base->iquery !== null) {
307 296
 						$target->iquery = $base->iquery;
308 297
 					}
309 298
 				}
310 299
 				$target->ifragment = $relative->ifragment;
311 300
 			}
312
-		}
313
-		else {
301
+		} else {
314 302
 			$target = clone $base;
315 303
 			$target->ifragment = null;
316 304
 		}
@@ -362,8 +350,7 @@  discard block
 block discarded – undo
362 350
 			// then remove that prefix from the input buffer; otherwise,
363 351
 			if (strpos($input, '../') === 0) {
364 352
 				$input = substr($input, 3);
365
-			}
366
-			elseif (strpos($input, './') === 0) {
353
+			} elseif (strpos($input, './') === 0) {
367 354
 				$input = substr($input, 2);
368 355
 			}
369 356
 			// B: if the input buffer begins with a prefix of "/./" or "/.",
@@ -371,8 +358,7 @@  discard block
 block discarded – undo
371 358
 			// with "/" in the input buffer; otherwise,
372 359
 			elseif (strpos($input, '/./') === 0) {
373 360
 				$input = substr($input, 2);
374
-			}
375
-			elseif ($input === '/.') {
361
+			} elseif ($input === '/.') {
376 362
 				$input = '/';
377 363
 			}
378 364
 			// C: if the input buffer begins with a prefix of "/../" or "/..",
@@ -382,8 +368,7 @@  discard block
 block discarded – undo
382 368
 			elseif (strpos($input, '/../') === 0) {
383 369
 				$input = substr($input, 3);
384 370
 				$output = substr_replace($output, '', strrpos($output, '/'));
385
-			}
386
-			elseif ($input === '/..') {
371
+			} elseif ($input === '/..') {
387 372
 				$input = '/';
388 373
 				$output = substr_replace($output, '', strrpos($output, '/'));
389 374
 			}
@@ -399,8 +384,7 @@  discard block
 block discarded – undo
399 384
 			elseif (($pos = strpos($input, '/', 1)) !== false) {
400 385
 				$output .= substr($input, 0, $pos);
401 386
 				$input = substr_replace($input, '', 0, $pos);
402
-			}
403
-			else {
387
+			} else {
404 388
 				$output .= $input;
405 389
 				$input = '';
406 390
 			}
@@ -482,8 +466,7 @@  discard block
 block discarded – undo
482 466
 							break;
483 467
 						}
484 468
 					}
485
-				}
486
-				else {
469
+				} else {
487 470
 					$position = $strlen - 1;
488 471
 					$valid = false;
489 472
 				}
@@ -634,8 +617,7 @@  discard block
 block discarded – undo
634 617
 					for ($j = $start; $j <= $i; $j++) {
635 618
 						$string .= '%' . strtoupper($bytes[$j]);
636 619
 					}
637
-				}
638
-				else {
620
+				} else {
639 621
 					for ($j = $start; $j <= $i; $j++) {
640 622
 						$string .= chr(hexdec($bytes[$j]));
641 623
 					}
@@ -760,12 +742,10 @@  discard block
 block discarded – undo
760 742
 	protected function set_scheme($scheme) {
761 743
 		if ($scheme === null) {
762 744
 			$this->scheme = null;
763
-		}
764
-		elseif (!preg_match('/^[A-Za-z][0-9A-Za-z+\-.]*$/', $scheme)) {
745
+		} elseif (!preg_match('/^[A-Za-z][0-9A-Za-z+\-.]*$/', $scheme)) {
765 746
 			$this->scheme = null;
766 747
 			return false;
767
-		}
768
-		else {
748
+		} else {
769 749
 			$this->scheme = strtolower($scheme);
770 750
 		}
771 751
 		return true;
@@ -803,8 +783,7 @@  discard block
 block discarded – undo
803 783
 		if (($iuserinfo_end = strrpos($remaining, '@')) !== false) {
804 784
 			$iuserinfo = substr($remaining, 0, $iuserinfo_end);
805 785
 			$remaining = substr($remaining, $iuserinfo_end + 1);
806
-		}
807
-		else {
786
+		} else {
808 787
 			$iuserinfo = null;
809 788
 		}
810 789
 		if (($port_start = strpos($remaining, ':', strpos($remaining, ']'))) !== false) {
@@ -813,8 +792,7 @@  discard block
 block discarded – undo
813 792
 				$port = null;
814 793
 			}
815 794
 			$remaining = substr($remaining, 0, $port_start);
816
-		}
817
-		else {
795
+		} else {
818 796
 			$port = null;
819 797
 		}
820 798
 
@@ -839,8 +817,7 @@  discard block
 block discarded – undo
839 817
 	protected function set_userinfo($iuserinfo) {
840 818
 		if ($iuserinfo === null) {
841 819
 			$this->iuserinfo = null;
842
-		}
843
-		else {
820
+		} else {
844 821
 			$this->iuserinfo = $this->replace_invalid_with_pct_encoding($iuserinfo, '!$&\'()*+,;=:');
845 822
 			$this->scheme_normalization();
846 823
 		}
@@ -863,13 +840,11 @@  discard block
 block discarded – undo
863 840
 		if (substr($ihost, 0, 1) === '[' && substr($ihost, -1) === ']') {
864 841
 			if (Requests_IPv6::check_ipv6(substr($ihost, 1, -1))) {
865 842
 				$this->ihost = '[' . Requests_IPv6::compress(substr($ihost, 1, -1)) . ']';
866
-			}
867
-			else {
843
+			} else {
868 844
 				$this->ihost = null;
869 845
 				return false;
870 846
 			}
871
-		}
872
-		else {
847
+		} else {
873 848
 			$ihost = $this->replace_invalid_with_pct_encoding($ihost, '!$&\'()*+,;=');
874 849
 
875 850
 			// Lowercase, but ignore pct-encoded sections (as they should
@@ -880,8 +855,7 @@  discard block
 block discarded – undo
880 855
 			while (($position += strcspn($ihost, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ%', $position)) < $strlen) {
881 856
 				if ($ihost[$position] === '%') {
882 857
 					$position += 3;
883
-				}
884
-				else {
858
+				} else {
885 859
 					$ihost[$position] = strtolower($ihost[$position]);
886 860
 					$position++;
887 861
 				}
@@ -934,8 +908,7 @@  discard block
 block discarded – undo
934 908
 
935 909
 		if (isset($cache[$ipath])) {
936 910
 			$this->ipath = $cache[$ipath][(int) ($this->scheme !== null)];
937
-		}
938
-		else {
911
+		} else {
939 912
 			$valid = $this->replace_invalid_with_pct_encoding($ipath, '!$&\'()*+,;=@:/');
940 913
 			$removed = $this->remove_dot_segments($valid);
941 914
 
@@ -955,8 +928,7 @@  discard block
 block discarded – undo
955 928
 	protected function set_query($iquery) {
956 929
 		if ($iquery === null) {
957 930
 			$this->iquery = null;
958
-		}
959
-		else {
931
+		} else {
960 932
 			$this->iquery = $this->replace_invalid_with_pct_encoding($iquery, '!$&\'()*+,;=:@/?', true);
961 933
 			$this->scheme_normalization();
962 934
 		}
@@ -972,8 +944,7 @@  discard block
 block discarded – undo
972 944
 	protected function set_fragment($ifragment) {
973 945
 		if ($ifragment === null) {
974 946
 			$this->ifragment = null;
975
-		}
976
-		else {
947
+		} else {
977 948
 			$this->ifragment = $this->replace_invalid_with_pct_encoding($ifragment, '!$&\'()*+,;=:@/?');
978 949
 			$this->scheme_normalization();
979 950
 		}
@@ -1076,8 +1047,7 @@  discard block
 block discarded – undo
1076 1047
 		$iauthority = $this->get_iauthority();
1077 1048
 		if (is_string($iauthority)) {
1078 1049
 			return $this->to_uri($iauthority);
1079
-		}
1080
-		else {
1050
+		} else {
1081 1051
 			return $iauthority;
1082 1052
 		}
1083 1053
 	}
Please login to merge, or discard this patch.
plugin/buycourses/src/Requests/Session.php 3 patches
Doc Comments   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -232,7 +232,7 @@
 block discarded – undo
232 232
 	 *
233 233
 	 * @param array $request Request data (same form as {@see request_multiple})
234 234
 	 * @param boolean $merge_options Should we merge options as well?
235
-	 * @return array Request data
235
+	 * @return string Request data
236 236
 	 */
237 237
 	protected function merge_request($request, $merge_options = true) {
238 238
 		if ($this->url !== null) {
Please login to merge, or discard this patch.
Indentation   +204 added lines, -204 removed lines patch added patch discarded remove patch
@@ -18,136 +18,136 @@  discard block
 block discarded – undo
18 18
  * @subpackage Session Handler
19 19
  */
20 20
 class Requests_Session {
21
-	/**
22
-	 * Base URL for requests
23
-	 *
24
-	 * URLs will be made absolute using this as the base
25
-	 * @var string|null
26
-	 */
27
-	public $url = null;
21
+    /**
22
+     * Base URL for requests
23
+     *
24
+     * URLs will be made absolute using this as the base
25
+     * @var string|null
26
+     */
27
+    public $url = null;
28 28
 
29
-	/**
30
-	 * Base headers for requests
31
-	 * @var array
32
-	 */
33
-	public $headers = array();
29
+    /**
30
+     * Base headers for requests
31
+     * @var array
32
+     */
33
+    public $headers = array();
34 34
 
35
-	/**
36
-	 * Base data for requests
37
-	 *
38
-	 * If both the base data and the per-request data are arrays, the data will
39
-	 * be merged before sending the request.
40
-	 *
41
-	 * @var array
42
-	 */
43
-	public $data = array();
35
+    /**
36
+     * Base data for requests
37
+     *
38
+     * If both the base data and the per-request data are arrays, the data will
39
+     * be merged before sending the request.
40
+     *
41
+     * @var array
42
+     */
43
+    public $data = array();
44 44
 
45
-	/**
46
-	 * Base options for requests
47
-	 *
48
-	 * The base options are merged with the per-request data for each request.
49
-	 * The only default option is a shared cookie jar between requests.
50
-	 *
51
-	 * Values here can also be set directly via properties on the Session
52
-	 * object, e.g. `$session->useragent = 'X';`
53
-	 *
54
-	 * @var array
55
-	 */
56
-	public $options = array();
45
+    /**
46
+     * Base options for requests
47
+     *
48
+     * The base options are merged with the per-request data for each request.
49
+     * The only default option is a shared cookie jar between requests.
50
+     *
51
+     * Values here can also be set directly via properties on the Session
52
+     * object, e.g. `$session->useragent = 'X';`
53
+     *
54
+     * @var array
55
+     */
56
+    public $options = array();
57 57
 
58
-	/**
59
-	 * Create a new session
60
-	 *
61
-	 * @param string|null $url Base URL for requests
62
-	 * @param array $headers Default headers for requests
63
-	 * @param array $data Default data for requests
64
-	 * @param array $options Default options for requests
65
-	 */
66
-	public function __construct($url = null, $headers = array(), $data = array(), $options = array()) {
67
-		$this->url = $url;
68
-		$this->headers = $headers;
69
-		$this->data = $data;
70
-		$this->options = $options;
58
+    /**
59
+     * Create a new session
60
+     *
61
+     * @param string|null $url Base URL for requests
62
+     * @param array $headers Default headers for requests
63
+     * @param array $data Default data for requests
64
+     * @param array $options Default options for requests
65
+     */
66
+    public function __construct($url = null, $headers = array(), $data = array(), $options = array()) {
67
+        $this->url = $url;
68
+        $this->headers = $headers;
69
+        $this->data = $data;
70
+        $this->options = $options;
71 71
 
72
-		if (empty($this->options['cookies'])) {
73
-			$this->options['cookies'] = new Requests_Cookie_Jar();
74
-		}
75
-	}
72
+        if (empty($this->options['cookies'])) {
73
+            $this->options['cookies'] = new Requests_Cookie_Jar();
74
+        }
75
+    }
76 76
 
77
-	/**
78
-	 * Get a property's value
79
-	 *
80
-	 * @param string $key Property key
81
-	 * @return mixed|null Property value, null if none found
82
-	 */
83
-	public function __get($key) {
84
-		if (isset($this->options[$key])) {
85
-			return $this->options[$key];
86
-		}
77
+    /**
78
+     * Get a property's value
79
+     *
80
+     * @param string $key Property key
81
+     * @return mixed|null Property value, null if none found
82
+     */
83
+    public function __get($key) {
84
+        if (isset($this->options[$key])) {
85
+            return $this->options[$key];
86
+        }
87 87
 
88
-		return null;
89
-	}
88
+        return null;
89
+    }
90 90
 
91
-	/**
92
-	 * Set a property's value
93
-	 *
94
-	 * @param string $key Property key
95
-	 * @param mixed $value Property value
96
-	 */
97
-	public function __set($key, $value) {
98
-		$this->options[$key] = $value;
99
-	}
91
+    /**
92
+     * Set a property's value
93
+     *
94
+     * @param string $key Property key
95
+     * @param mixed $value Property value
96
+     */
97
+    public function __set($key, $value) {
98
+        $this->options[$key] = $value;
99
+    }
100 100
 
101
-	/**
102
-	 * Remove a property's value
103
-	 *
104
-	 * @param string $key Property key
105
-	 */
106
-	public function __isset($key) {
107
-		return isset($this->options[$key]);
108
-	}
101
+    /**
102
+     * Remove a property's value
103
+     *
104
+     * @param string $key Property key
105
+     */
106
+    public function __isset($key) {
107
+        return isset($this->options[$key]);
108
+    }
109 109
 
110
-	/**
111
-	 * Remove a property's value
112
-	 *
113
-	 * @param string $key Property key
114
-	 */
115
-	public function __unset($key) {
116
-		if (isset($this->options[$key])) {
117
-			unset($this->options[$key]);
118
-		}
119
-	}
110
+    /**
111
+     * Remove a property's value
112
+     *
113
+     * @param string $key Property key
114
+     */
115
+    public function __unset($key) {
116
+        if (isset($this->options[$key])) {
117
+            unset($this->options[$key]);
118
+        }
119
+    }
120 120
 
121
-	/**#@+
121
+    /**#@+
122 122
 	 * @see request()
123 123
 	 * @param string $url
124 124
 	 * @param array $headers
125 125
 	 * @param array $options
126 126
 	 * @return Requests_Response
127 127
 	 */
128
-	/**
129
-	 * Send a GET request
130
-	 */
131
-	public function get($url, $headers = array(), $options = array()) {
132
-		return $this->request($url, $headers, null, Requests::GET, $options);
133
-	}
128
+    /**
129
+     * Send a GET request
130
+     */
131
+    public function get($url, $headers = array(), $options = array()) {
132
+        return $this->request($url, $headers, null, Requests::GET, $options);
133
+    }
134 134
 
135
-	/**
136
-	 * Send a HEAD request
137
-	 */
138
-	public function head($url, $headers = array(), $options = array()) {
139
-		return $this->request($url, $headers, null, Requests::HEAD, $options);
140
-	}
135
+    /**
136
+     * Send a HEAD request
137
+     */
138
+    public function head($url, $headers = array(), $options = array()) {
139
+        return $this->request($url, $headers, null, Requests::HEAD, $options);
140
+    }
141 141
 
142
-	/**
143
-	 * Send a DELETE request
144
-	 */
145
-	public function delete($url, $headers = array(), $options = array()) {
146
-		return $this->request($url, $headers, null, Requests::DELETE, $options);
147
-	}
148
-	/**#@-*/
142
+    /**
143
+     * Send a DELETE request
144
+     */
145
+    public function delete($url, $headers = array(), $options = array()) {
146
+        return $this->request($url, $headers, null, Requests::DELETE, $options);
147
+    }
148
+    /**#@-*/
149 149
 
150
-	/**#@+
150
+    /**#@+
151 151
 	 * @see request()
152 152
 	 * @param string $url
153 153
 	 * @param array $headers
@@ -155,112 +155,112 @@  discard block
 block discarded – undo
155 155
 	 * @param array $options
156 156
 	 * @return Requests_Response
157 157
 	 */
158
-	/**
159
-	 * Send a POST request
160
-	 */
161
-	public function post($url, $headers = array(), $data = array(), $options = array()) {
162
-		return $this->request($url, $headers, $data, Requests::POST, $options);
163
-	}
158
+    /**
159
+     * Send a POST request
160
+     */
161
+    public function post($url, $headers = array(), $data = array(), $options = array()) {
162
+        return $this->request($url, $headers, $data, Requests::POST, $options);
163
+    }
164 164
 
165
-	/**
166
-	 * Send a PUT request
167
-	 */
168
-	public function put($url, $headers = array(), $data = array(), $options = array()) {
169
-		return $this->request($url, $headers, $data, Requests::PUT, $options);
170
-	}
165
+    /**
166
+     * Send a PUT request
167
+     */
168
+    public function put($url, $headers = array(), $data = array(), $options = array()) {
169
+        return $this->request($url, $headers, $data, Requests::PUT, $options);
170
+    }
171 171
 
172
-	/**
173
-	 * Send a PATCH request
174
-	 *
175
-	 * Note: Unlike {@see post} and {@see put}, `$headers` is required, as the
176
-	 * specification recommends that should send an ETag
177
-	 *
178
-	 * @link https://tools.ietf.org/html/rfc5789
179
-	 */
180
-	public function patch($url, $headers, $data = array(), $options = array()) {
181
-		return $this->request($url, $headers, $data, Requests::PATCH, $options);
182
-	}
183
-	/**#@-*/
172
+    /**
173
+     * Send a PATCH request
174
+     *
175
+     * Note: Unlike {@see post} and {@see put}, `$headers` is required, as the
176
+     * specification recommends that should send an ETag
177
+     *
178
+     * @link https://tools.ietf.org/html/rfc5789
179
+     */
180
+    public function patch($url, $headers, $data = array(), $options = array()) {
181
+        return $this->request($url, $headers, $data, Requests::PATCH, $options);
182
+    }
183
+    /**#@-*/
184 184
 
185
-	/**
186
-	 * Main interface for HTTP requests
187
-	 *
188
-	 * This method initiates a request and sends it via a transport before
189
-	 * parsing.
190
-	 *
191
-	 * @see Requests::request()
192
-	 *
193
-	 * @throws Requests_Exception On invalid URLs (`nonhttp`)
194
-	 *
195
-	 * @param string $url URL to request
196
-	 * @param array $headers Extra headers to send with the request
197
-	 * @param array|null $data Data to send either as a query string for GET/HEAD requests, or in the body for POST requests
198
-	 * @param string $type HTTP request type (use Requests constants)
199
-	 * @param array $options Options for the request (see {@see Requests::request})
200
-	 * @return Requests_Response
201
-	 */
202
-	public function request($url, $headers = array(), $data = array(), $type = Requests::GET, $options = array()) {
203
-		$request = $this->merge_request(compact('url', 'headers', 'data', 'options'));
185
+    /**
186
+     * Main interface for HTTP requests
187
+     *
188
+     * This method initiates a request and sends it via a transport before
189
+     * parsing.
190
+     *
191
+     * @see Requests::request()
192
+     *
193
+     * @throws Requests_Exception On invalid URLs (`nonhttp`)
194
+     *
195
+     * @param string $url URL to request
196
+     * @param array $headers Extra headers to send with the request
197
+     * @param array|null $data Data to send either as a query string for GET/HEAD requests, or in the body for POST requests
198
+     * @param string $type HTTP request type (use Requests constants)
199
+     * @param array $options Options for the request (see {@see Requests::request})
200
+     * @return Requests_Response
201
+     */
202
+    public function request($url, $headers = array(), $data = array(), $type = Requests::GET, $options = array()) {
203
+        $request = $this->merge_request(compact('url', 'headers', 'data', 'options'));
204 204
 
205
-		return Requests::request($request['url'], $request['headers'], $request['data'], $type, $request['options']);
206
-	}
205
+        return Requests::request($request['url'], $request['headers'], $request['data'], $type, $request['options']);
206
+    }
207 207
 
208
-	/**
209
-	 * Send multiple HTTP requests simultaneously
210
-	 *
211
-	 * @see Requests::request_multiple()
212
-	 *
213
-	 * @param array $requests Requests data (see {@see Requests::request_multiple})
214
-	 * @param array $options Global and default options (see {@see Requests::request})
215
-	 * @return array Responses (either Requests_Response or a Requests_Exception object)
216
-	 */
217
-	public function request_multiple($requests, $options = array()) {
218
-		foreach ($requests as $key => $request) {
219
-			$requests[$key] = $this->merge_request($request, false);
220
-		}
208
+    /**
209
+     * Send multiple HTTP requests simultaneously
210
+     *
211
+     * @see Requests::request_multiple()
212
+     *
213
+     * @param array $requests Requests data (see {@see Requests::request_multiple})
214
+     * @param array $options Global and default options (see {@see Requests::request})
215
+     * @return array Responses (either Requests_Response or a Requests_Exception object)
216
+     */
217
+    public function request_multiple($requests, $options = array()) {
218
+        foreach ($requests as $key => $request) {
219
+            $requests[$key] = $this->merge_request($request, false);
220
+        }
221 221
 
222
-		$options = array_merge($this->options, $options);
222
+        $options = array_merge($this->options, $options);
223 223
 
224
-		// Disallow forcing the type, as that's a per request setting
225
-		unset($options['type']);
224
+        // Disallow forcing the type, as that's a per request setting
225
+        unset($options['type']);
226 226
 
227
-		return Requests::request_multiple($requests, $options);
228
-	}
227
+        return Requests::request_multiple($requests, $options);
228
+    }
229 229
 
230
-	/**
231
-	 * Merge a request's data with the default data
232
-	 *
233
-	 * @param array $request Request data (same form as {@see request_multiple})
234
-	 * @param boolean $merge_options Should we merge options as well?
235
-	 * @return array Request data
236
-	 */
237
-	protected function merge_request($request, $merge_options = true) {
238
-		if ($this->url !== null) {
239
-			$request['url'] = Requests_IRI::absolutize($this->url, $request['url']);
240
-			$request['url'] = $request['url']->uri;
241
-		}
230
+    /**
231
+     * Merge a request's data with the default data
232
+     *
233
+     * @param array $request Request data (same form as {@see request_multiple})
234
+     * @param boolean $merge_options Should we merge options as well?
235
+     * @return array Request data
236
+     */
237
+    protected function merge_request($request, $merge_options = true) {
238
+        if ($this->url !== null) {
239
+            $request['url'] = Requests_IRI::absolutize($this->url, $request['url']);
240
+            $request['url'] = $request['url']->uri;
241
+        }
242 242
 
243
-		if (empty($request['headers'])) {
244
-			$request['headers'] = array();
245
-		}
246
-		$request['headers'] = array_merge($this->headers, $request['headers']);
243
+        if (empty($request['headers'])) {
244
+            $request['headers'] = array();
245
+        }
246
+        $request['headers'] = array_merge($this->headers, $request['headers']);
247 247
 
248
-		if (empty($request['data'])) {
249
-			if (is_array($this->data)) {
250
-				$request['data'] = $this->data;
251
-			}
252
-		}
253
-		elseif (is_array($request['data']) && is_array($this->data)) {
254
-			$request['data'] = array_merge($this->data, $request['data']);
255
-		}
248
+        if (empty($request['data'])) {
249
+            if (is_array($this->data)) {
250
+                $request['data'] = $this->data;
251
+            }
252
+        }
253
+        elseif (is_array($request['data']) && is_array($this->data)) {
254
+            $request['data'] = array_merge($this->data, $request['data']);
255
+        }
256 256
 
257
-		if ($merge_options !== false) {
258
-			$request['options'] = array_merge($this->options, $request['options']);
257
+        if ($merge_options !== false) {
258
+            $request['options'] = array_merge($this->options, $request['options']);
259 259
 
260
-			// Disallow forcing the type, as that's a per request setting
261
-			unset($request['options']['type']);
262
-		}
260
+            // Disallow forcing the type, as that's a per request setting
261
+            unset($request['options']['type']);
262
+        }
263 263
 
264
-		return $request;
265
-	}
264
+        return $request;
265
+    }
266 266
 }
Please login to merge, or discard this patch.
Braces   +1 added lines, -2 removed lines patch added patch discarded remove patch
@@ -249,8 +249,7 @@
 block discarded – undo
249 249
 			if (is_array($this->data)) {
250 250
 				$request['data'] = $this->data;
251 251
 			}
252
-		}
253
-		elseif (is_array($request['data']) && is_array($this->data)) {
252
+		} elseif (is_array($request['data']) && is_array($this->data)) {
254 253
 			$request['data'] = array_merge($this->data, $request['data']);
255 254
 		}
256 255
 
Please login to merge, or discard this patch.
plugin/buycourses/src/Requests/Response/Headers.php 1 patch
Indentation   +74 added lines, -74 removed lines patch added patch discarded remove patch
@@ -11,88 +11,88 @@
 block discarded – undo
11 11
  * @package Requests
12 12
  */
13 13
 class Requests_Response_Headers extends Requests_Utility_CaseInsensitiveDictionary {
14
-	/**
15
-	 * Get the given header
16
-	 *
17
-	 * Unlike {@see self::getValues()}, this returns a string. If there are
18
-	 * multiple values, it concatenates them with a comma as per RFC2616.
19
-	 *
20
-	 * Avoid using this where commas may be used unquoted in values, such as
21
-	 * Set-Cookie headers.
22
-	 *
23
-	 * @param string $key
24
-	 * @return string Header value
25
-	 */
26
-	public function offsetGet($key) {
27
-		$key = strtolower($key);
28
-		if (!isset($this->data[$key])) {
29
-			return null;
30
-		}
14
+    /**
15
+     * Get the given header
16
+     *
17
+     * Unlike {@see self::getValues()}, this returns a string. If there are
18
+     * multiple values, it concatenates them with a comma as per RFC2616.
19
+     *
20
+     * Avoid using this where commas may be used unquoted in values, such as
21
+     * Set-Cookie headers.
22
+     *
23
+     * @param string $key
24
+     * @return string Header value
25
+     */
26
+    public function offsetGet($key) {
27
+        $key = strtolower($key);
28
+        if (!isset($this->data[$key])) {
29
+            return null;
30
+        }
31 31
 
32
-		return $this->flatten($this->data[$key]);
33
-	}
32
+        return $this->flatten($this->data[$key]);
33
+    }
34 34
 
35
-	/**
36
-	 * Set the given item
37
-	 *
38
-	 * @throws Requests_Exception On attempting to use dictionary as list (`invalidset`)
39
-	 *
40
-	 * @param string $key Item name
41
-	 * @param string $value Item value
42
-	 */
43
-	public function offsetSet($key, $value) {
44
-		if ($key === null) {
45
-			throw new Requests_Exception('Object is a dictionary, not a list', 'invalidset');
46
-		}
35
+    /**
36
+     * Set the given item
37
+     *
38
+     * @throws Requests_Exception On attempting to use dictionary as list (`invalidset`)
39
+     *
40
+     * @param string $key Item name
41
+     * @param string $value Item value
42
+     */
43
+    public function offsetSet($key, $value) {
44
+        if ($key === null) {
45
+            throw new Requests_Exception('Object is a dictionary, not a list', 'invalidset');
46
+        }
47 47
 
48
-		$key = strtolower($key);
48
+        $key = strtolower($key);
49 49
 
50
-		if (!isset($this->data[$key])) {
51
-			$this->data[$key] = array();
52
-		}
50
+        if (!isset($this->data[$key])) {
51
+            $this->data[$key] = array();
52
+        }
53 53
 
54
-		$this->data[$key][] = $value;
55
-	}
54
+        $this->data[$key][] = $value;
55
+    }
56 56
 
57
-	/**
58
-	 * Get all values for a given header
59
-	 *
60
-	 * @param string $key
61
-	 * @return array Header values
62
-	 */
63
-	public function getValues($key) {
64
-		$key = strtolower($key);
65
-		if (!isset($this->data[$key])) {
66
-			return null;
67
-		}
57
+    /**
58
+     * Get all values for a given header
59
+     *
60
+     * @param string $key
61
+     * @return array Header values
62
+     */
63
+    public function getValues($key) {
64
+        $key = strtolower($key);
65
+        if (!isset($this->data[$key])) {
66
+            return null;
67
+        }
68 68
 
69
-		return $this->data[$key];
70
-	}
69
+        return $this->data[$key];
70
+    }
71 71
 
72
-	/**
73
-	 * Flattens a value into a string
74
-	 *
75
-	 * Converts an array into a string by imploding values with a comma, as per
76
-	 * RFC2616's rules for folding headers.
77
-	 *
78
-	 * @param string|array $value Value to flatten
79
-	 * @return string Flattened value
80
-	 */
81
-	public function flatten($value) {
82
-		if (is_array($value)) {
83
-			$value = implode(',', $value);
84
-		}
72
+    /**
73
+     * Flattens a value into a string
74
+     *
75
+     * Converts an array into a string by imploding values with a comma, as per
76
+     * RFC2616's rules for folding headers.
77
+     *
78
+     * @param string|array $value Value to flatten
79
+     * @return string Flattened value
80
+     */
81
+    public function flatten($value) {
82
+        if (is_array($value)) {
83
+            $value = implode(',', $value);
84
+        }
85 85
 
86
-		return $value;
87
-	}
86
+        return $value;
87
+    }
88 88
 
89
-	/**
90
-	 * Get an iterator for the data
91
-	 *
92
-	 * Converts the internal
93
-	 * @return ArrayIterator
94
-	 */
95
-	public function getIterator() {
96
-		return new Requests_Utility_FilteredIterator($this->data, array($this, 'flatten'));
97
-	}
89
+    /**
90
+     * Get an iterator for the data
91
+     *
92
+     * Converts the internal
93
+     * @return ArrayIterator
94
+     */
95
+    public function getIterator() {
96
+        return new Requests_Utility_FilteredIterator($this->data, array($this, 'flatten'));
97
+    }
98 98
 }
Please login to merge, or discard this patch.