]> git.mxchange.org Git - quix0rs-gnu-social.git/commitdiff
Updating external libraries for net access
authorMikael Nordfeldth <mmn@hethane.se>
Sat, 5 Oct 2013 12:29:02 +0000 (14:29 +0200)
committerMikael Nordfeldth <mmn@hethane.se>
Sat, 5 Oct 2013 12:29:02 +0000 (14:29 +0200)
16 files changed:
extlib/HTTP/Request2.php
extlib/HTTP/Request2/Adapter.php
extlib/HTTP/Request2/Adapter/Curl.php
extlib/HTTP/Request2/Adapter/Mock.php
extlib/HTTP/Request2/Adapter/Socket.php
extlib/HTTP/Request2/CookieJar.php
extlib/HTTP/Request2/Exception.php
extlib/HTTP/Request2/MultipartBody.php
extlib/HTTP/Request2/Observer/Log.php
extlib/HTTP/Request2/Response.php
extlib/HTTP/Request2/SOCKS5.php [new file with mode: 0644]
extlib/HTTP/Request2/SocketWrapper.php [new file with mode: 0644]
extlib/Net/URL.php [deleted file]
extlib/Net/URL2.php [changed mode: 0644->0755]
extlib/data/generate-list.php [new file with mode: 0644]
extlib/data/public-suffix-list.php [new file with mode: 0644]

index 60beeaf2ef5f88f547b33e04f7c89ef32026714c..1a40df22139f7c770f1569f36ae5e0f8b400baed 100644 (file)
@@ -6,7 +6,7 @@
  *\r
  * LICENSE:\r
  *\r
- * Copyright (c) 2008-2011, Alexey Borzov <avb@php.net>\r
+ * Copyright (c) 2008-2012, Alexey Borzov <avb@php.net>\r
  * All rights reserved.\r
  *\r
  * Redistribution and use in source and binary forms, with or without\r
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
  *\r
- * @category   HTTP\r
- * @package    HTTP_Request2\r
- * @author     Alexey Borzov <avb@php.net>\r
- * @license    http://opensource.org/licenses/bsd-license.php New BSD License\r
- * @version    SVN: $Id: Request2.php 308735 2011-02-27 20:31:28Z avb $\r
- * @link       http://pear.php.net/package/HTTP_Request2\r
+ * @category HTTP\r
+ * @package  HTTP_Request2\r
+ * @author   Alexey Borzov <avb@php.net>\r
+ * @license  http://opensource.org/licenses/bsd-license.php New BSD License\r
+ * @version  SVN: $Id: Request2.php 324936 2012-04-07 07:49:03Z avb $\r
+ * @link     http://pear.php.net/package/HTTP_Request2\r
  */\r
 \r
 /**\r
@@ -54,19 +54,21 @@ require_once 'HTTP/Request2/Exception.php';
 /**\r
  * Class representing a HTTP request message\r
  *\r
- * @category   HTTP\r
- * @package    HTTP_Request2\r
- * @author     Alexey Borzov <avb@php.net>\r
- * @version    Release: 2.0.0RC1\r
- * @link       http://tools.ietf.org/html/rfc2616#section-5\r
+ * @category HTTP\r
+ * @package  HTTP_Request2\r
+ * @author   Alexey Borzov <avb@php.net>\r
+ * @license  http://opensource.org/licenses/bsd-license.php New BSD License\r
+ * @version  Release: 2.1.1\r
+ * @link     http://pear.php.net/package/HTTP_Request2\r
+ * @link     http://tools.ietf.org/html/rfc2616#section-5\r
  */\r
 class HTTP_Request2 implements SplSubject\r
 {\r
-   /**#@+\r
-    * Constants for HTTP request methods\r
-    *\r
-    * @link http://tools.ietf.org/html/rfc2616#section-5.1.1\r
-    */\r
+    /**#@+\r
+     * Constants for HTTP request methods\r
+     *\r
+     * @link http://tools.ietf.org/html/rfc2616#section-5.1.1\r
+     */\r
     const METHOD_OPTIONS = 'OPTIONS';\r
     const METHOD_GET     = 'GET';\r
     const METHOD_HEAD    = 'HEAD';\r
@@ -75,73 +77,73 @@ class HTTP_Request2 implements SplSubject
     const METHOD_DELETE  = 'DELETE';\r
     const METHOD_TRACE   = 'TRACE';\r
     const METHOD_CONNECT = 'CONNECT';\r
-   /**#@-*/\r
+    /**#@-*/\r
 \r
-   /**#@+\r
-    * Constants for HTTP authentication schemes\r
-    *\r
-    * @link http://tools.ietf.org/html/rfc2617\r
-    */\r
+    /**#@+\r
+     * Constants for HTTP authentication schemes\r
+     *\r
+     * @link http://tools.ietf.org/html/rfc2617\r
+     */\r
     const AUTH_BASIC  = 'basic';\r
     const AUTH_DIGEST = 'digest';\r
-   /**#@-*/\r
+    /**#@-*/\r
 \r
-   /**\r
-    * Regular expression used to check for invalid symbols in RFC 2616 tokens\r
-    * @link http://pear.php.net/bugs/bug.php?id=15630\r
-    */\r
+    /**\r
+     * Regular expression used to check for invalid symbols in RFC 2616 tokens\r
+     * @link http://pear.php.net/bugs/bug.php?id=15630\r
+     */\r
     const REGEXP_INVALID_TOKEN = '![\x00-\x1f\x7f-\xff()<>@,;:\\\\"/\[\]?={}\s]!';\r
 \r
-   /**\r
-    * Regular expression used to check for invalid symbols in cookie strings\r
-    * @link http://pear.php.net/bugs/bug.php?id=15630\r
-    * @link http://web.archive.org/web/20080331104521/http://cgi.netscape.com/newsref/std/cookie_spec.html\r
-    */\r
+    /**\r
+     * Regular expression used to check for invalid symbols in cookie strings\r
+     * @link http://pear.php.net/bugs/bug.php?id=15630\r
+     * @link http://web.archive.org/web/20080331104521/http://cgi.netscape.com/newsref/std/cookie_spec.html\r
+     */\r
     const REGEXP_INVALID_COOKIE = '/[\s,;]/';\r
 \r
-   /**\r
-    * Fileinfo magic database resource\r
-    * @var  resource\r
-    * @see  detectMimeType()\r
-    */\r
+    /**\r
+     * Fileinfo magic database resource\r
+     * @var  resource\r
+     * @see  detectMimeType()\r
+     */\r
     private static $_fileinfoDb;\r
 \r
-   /**\r
-    * Observers attached to the request (instances of SplObserver)\r
-    * @var  array\r
-    */\r
+    /**\r
+     * Observers attached to the request (instances of SplObserver)\r
+     * @var  array\r
+     */\r
     protected $observers = array();\r
 \r
-   /**\r
-    * Request URL\r
-    * @var  Net_URL2\r
-    */\r
+    /**\r
+     * Request URL\r
+     * @var  Net_URL2\r
+     */\r
     protected $url;\r
 \r
-   /**\r
-    * Request method\r
-    * @var  string\r
-    */\r
+    /**\r
+     * Request method\r
+     * @var  string\r
+     */\r
     protected $method = self::METHOD_GET;\r
 \r
-   /**\r
-    * Authentication data\r
-    * @var  array\r
-    * @see  getAuth()\r
-    */\r
+    /**\r
+     * Authentication data\r
+     * @var  array\r
+     * @see  getAuth()\r
+     */\r
     protected $auth;\r
 \r
-   /**\r
-    * Request headers\r
-    * @var  array\r
-    */\r
+    /**\r
+     * Request headers\r
+     * @var  array\r
+     */\r
     protected $headers = array();\r
 \r
-   /**\r
-    * Configuration parameters\r
-    * @var  array\r
-    * @see  setConfig()\r
-    */\r
+    /**\r
+     * Configuration parameters\r
+     * @var  array\r
+     * @see  setConfig()\r
+     */\r
     protected $config = array(\r
         'adapter'           => 'HTTP_Request2_Adapter_Socket',\r
         'connect_timeout'   => 10,\r
@@ -156,6 +158,7 @@ class HTTP_Request2 implements SplSubject
         'proxy_user'        => '',\r
         'proxy_password'    => '',\r
         'proxy_auth_scheme' => self::AUTH_BASIC,\r
+        'proxy_type'        => 'http',\r
 \r
         'ssl_verify_peer'   => true,\r
         'ssl_verify_host'   => true,\r
@@ -171,58 +174,59 @@ class HTTP_Request2 implements SplSubject
         'strict_redirects'  => false\r
     );\r
 \r
-   /**\r
-    * Last event in request / response handling, intended for observers\r
-    * @var  array\r
-    * @see  getLastEvent()\r
-    */\r
+    /**\r
+     * Last event in request / response handling, intended for observers\r
+     * @var  array\r
+     * @see  getLastEvent()\r
+     */\r
     protected $lastEvent = array(\r
         'name' => 'start',\r
         'data' => null\r
     );\r
 \r
-   /**\r
-    * Request body\r
-    * @var  string|resource\r
-    * @see  setBody()\r
-    */\r
+    /**\r
+     * Request body\r
+     * @var  string|resource\r
+     * @see  setBody()\r
+     */\r
     protected $body = '';\r
 \r
-   /**\r
-    * Array of POST parameters\r
-    * @var  array\r
-    */\r
+    /**\r
+     * Array of POST parameters\r
+     * @var  array\r
+     */\r
     protected $postParams = array();\r
 \r
-   /**\r
-    * Array of file uploads (for multipart/form-data POST requests)\r
-    * @var  array\r
-    */\r
+    /**\r
+     * Array of file uploads (for multipart/form-data POST requests)\r
+     * @var  array\r
+     */\r
     protected $uploads = array();\r
 \r
-   /**\r
-    * Adapter used to perform actual HTTP request\r
-    * @var  HTTP_Request2_Adapter\r
-    */\r
+    /**\r
+     * Adapter used to perform actual HTTP request\r
+     * @var  HTTP_Request2_Adapter\r
+     */\r
     protected $adapter;\r
 \r
-   /**\r
-    * Cookie jar to persist cookies between requests\r
-    * @var HTTP_Request2_CookieJar\r
-    */\r
+    /**\r
+     * Cookie jar to persist cookies between requests\r
+     * @var HTTP_Request2_CookieJar\r
+     */\r
     protected $cookieJar = null;\r
 \r
-   /**\r
-    * Constructor. Can set request URL, method and configuration array.\r
-    *\r
-    * Also sets a default value for User-Agent header.\r
-    *\r
-    * @param    string|Net_Url2     Request URL\r
-    * @param    string              Request method\r
-    * @param    array               Configuration for this Request instance\r
-    */\r
-    public function __construct($url = null, $method = self::METHOD_GET, array $config = array())\r
-    {\r
+    /**\r
+     * Constructor. Can set request URL, method and configuration array.\r
+     *\r
+     * Also sets a default value for User-Agent header.\r
+     *\r
+     * @param string|Net_Url2 $url    Request URL\r
+     * @param string          $method Request method\r
+     * @param array           $config Configuration for this Request instance\r
+     */\r
+    public function __construct(\r
+        $url = null, $method = self::METHOD_GET, array $config = array()\r
+    ) {\r
         $this->setConfig($config);\r
         if (!empty($url)) {\r
             $this->setUrl($url);\r
@@ -230,22 +234,24 @@ class HTTP_Request2 implements SplSubject
         if (!empty($method)) {\r
             $this->setMethod($method);\r
         }\r
-        $this->setHeader('user-agent', 'HTTP_Request2/2.0.0RC1 ' .\r
-                         '(http://pear.php.net/package/http_request2) ' .\r
-                         'PHP/' . phpversion());\r
+        $this->setHeader(\r
+            'user-agent', 'HTTP_Request2/2.1.1 ' .\r
+            '(http://pear.php.net/package/http_request2) PHP/' . phpversion()\r
+        );\r
     }\r
 \r
-   /**\r
-    * Sets the URL for this request\r
-    *\r
-    * If the URL has userinfo part (username & password) these will be removed\r
-    * and converted to auth data. If the URL does not have a path component,\r
-    * that will be set to '/'.\r
-    *\r
-    * @param    string|Net_URL2 Request URL\r
-    * @return   HTTP_Request2\r
-    * @throws   HTTP_Request2_LogicException\r
-    */\r
+    /**\r
+     * Sets the URL for this request\r
+     *\r
+     * If the URL has userinfo part (username & password) these will be removed\r
+     * and converted to auth data. If the URL does not have a path component,\r
+     * that will be set to '/'.\r
+     *\r
+     * @param string|Net_URL2 $url Request URL\r
+     *\r
+     * @return   HTTP_Request2\r
+     * @throws   HTTP_Request2_LogicException\r
+     */\r
     public function setUrl($url)\r
     {\r
         if (is_string($url)) {\r
@@ -274,23 +280,24 @@ class HTTP_Request2 implements SplSubject
         return $this;\r
     }\r
 \r
-   /**\r
-    * Returns the request URL\r
-    *\r
-    * @return   Net_URL2\r
-    */\r
+    /**\r
+     * Returns the request URL\r
+     *\r
+     * @return   Net_URL2\r
+     */\r
     public function getUrl()\r
     {\r
         return $this->url;\r
     }\r
 \r
-   /**\r
-    * Sets the request method\r
-    *\r
-    * @param    string\r
-    * @return   HTTP_Request2\r
-    * @throws   HTTP_Request2_LogicException if the method name is invalid\r
-    */\r
+    /**\r
+     * Sets the request method\r
+     *\r
+     * @param string $method one of the methods defined in RFC 2616\r
+     *\r
+     * @return   HTTP_Request2\r
+     * @throws   HTTP_Request2_LogicException if the method name is invalid\r
+     */\r
     public function setMethod($method)\r
     {\r
         // Method name should be a token: http://tools.ietf.org/html/rfc2616#section-5.1.1\r
@@ -305,64 +312,68 @@ class HTTP_Request2 implements SplSubject
         return $this;\r
     }\r
 \r
-   /**\r
-    * Returns the request method\r
-    *\r
-    * @return   string\r
-    */\r
+    /**\r
+     * Returns the request method\r
+     *\r
+     * @return   string\r
+     */\r
     public function getMethod()\r
     {\r
         return $this->method;\r
     }\r
 \r
-   /**\r
-    * Sets the configuration parameter(s)\r
-    *\r
-    * The following parameters are available:\r
-    * <ul>\r
-    *   <li> 'adapter'           - adapter to use (string)</li>\r
-    *   <li> 'connect_timeout'   - Connection timeout in seconds (integer)</li>\r
-    *   <li> 'timeout'           - Total number of seconds a request can take.\r
-    *                              Use 0 for no limit, should be greater than\r
-    *                              'connect_timeout' if set (integer)</li>\r
-    *   <li> 'use_brackets'      - Whether to append [] to array variable names (bool)</li>\r
-    *   <li> 'protocol_version'  - HTTP Version to use, '1.0' or '1.1' (string)</li>\r
-    *   <li> 'buffer_size'       - Buffer size to use for reading and writing (int)</li>\r
-    *   <li> 'store_body'        - Whether to store response body in response object.\r
-    *                              Set to false if receiving a huge response and\r
-    *                              using an Observer to save it (boolean)</li>\r
-    *   <li> 'proxy_host'        - Proxy server host (string)</li>\r
-    *   <li> 'proxy_port'        - Proxy server port (integer)</li>\r
-    *   <li> 'proxy_user'        - Proxy auth username (string)</li>\r
-    *   <li> 'proxy_password'    - Proxy auth password (string)</li>\r
-    *   <li> 'proxy_auth_scheme' - Proxy auth scheme, one of HTTP_Request2::AUTH_* constants (string)</li>\r
-    *   <li> 'ssl_verify_peer'   - Whether to verify peer's SSL certificate (bool)</li>\r
-    *   <li> 'ssl_verify_host'   - Whether to check that Common Name in SSL\r
-    *                              certificate matches host name (bool)</li>\r
-    *   <li> 'ssl_cafile'        - Cerificate Authority file to verify the peer\r
-    *                              with (use with 'ssl_verify_peer') (string)</li>\r
-    *   <li> 'ssl_capath'        - Directory holding multiple Certificate\r
-    *                              Authority files (string)</li>\r
-    *   <li> 'ssl_local_cert'    - Name of a file containing local cerificate (string)</li>\r
-    *   <li> 'ssl_passphrase'    - Passphrase with which local certificate\r
-    *                              was encoded (string)</li>\r
-    *   <li> 'digest_compat_ie'  - Whether to imitate behaviour of MSIE 5 and 6\r
-    *                              in using URL without query string in digest\r
-    *                              authentication (boolean)</li>\r
-    *   <li> 'follow_redirects'  - Whether to automatically follow HTTP Redirects (boolean)</li>\r
-    *   <li> 'max_redirects'     - Maximum number of redirects to follow (integer)</li>\r
-    *   <li> 'strict_redirects'  - Whether to keep request method on redirects via status 301 and\r
-    *                              302 (true, needed for compatibility with RFC 2616)\r
-    *                              or switch to GET (false, needed for compatibility with most\r
-    *                              browsers) (boolean)</li>\r
-    * </ul>\r
-    *\r
-    * @param    string|array    configuration parameter name or array\r
-    *                           ('parameter name' => 'parameter value')\r
-    * @param    mixed           parameter value if $nameOrConfig is not an array\r
-    * @return   HTTP_Request2\r
-    * @throws   HTTP_Request2_LogicException If the parameter is unknown\r
-    */\r
+    /**\r
+     * Sets the configuration parameter(s)\r
+     *\r
+     * The following parameters are available:\r
+     * <ul>\r
+     *   <li> 'adapter'           - adapter to use (string)</li>\r
+     *   <li> 'connect_timeout'   - Connection timeout in seconds (integer)</li>\r
+     *   <li> 'timeout'           - Total number of seconds a request can take.\r
+     *                              Use 0 for no limit, should be greater than\r
+     *                              'connect_timeout' if set (integer)</li>\r
+     *   <li> 'use_brackets'      - Whether to append [] to array variable names (bool)</li>\r
+     *   <li> 'protocol_version'  - HTTP Version to use, '1.0' or '1.1' (string)</li>\r
+     *   <li> 'buffer_size'       - Buffer size to use for reading and writing (int)</li>\r
+     *   <li> 'store_body'        - Whether to store response body in response object.\r
+     *                              Set to false if receiving a huge response and\r
+     *                              using an Observer to save it (boolean)</li>\r
+     *   <li> 'proxy_type'        - Proxy type, 'http' or 'socks5' (string)</li>\r
+     *   <li> 'proxy_host'        - Proxy server host (string)</li>\r
+     *   <li> 'proxy_port'        - Proxy server port (integer)</li>\r
+     *   <li> 'proxy_user'        - Proxy auth username (string)</li>\r
+     *   <li> 'proxy_password'    - Proxy auth password (string)</li>\r
+     *   <li> 'proxy_auth_scheme' - Proxy auth scheme, one of HTTP_Request2::AUTH_* constants (string)</li>\r
+     *   <li> 'proxy'             - Shorthand for proxy_* parameters, proxy given as URL,\r
+     *                              e.g. 'socks5://localhost:1080/' (string)</li>\r
+     *   <li> 'ssl_verify_peer'   - Whether to verify peer's SSL certificate (bool)</li>\r
+     *   <li> 'ssl_verify_host'   - Whether to check that Common Name in SSL\r
+     *                              certificate matches host name (bool)</li>\r
+     *   <li> 'ssl_cafile'        - Cerificate Authority file to verify the peer\r
+     *                              with (use with 'ssl_verify_peer') (string)</li>\r
+     *   <li> 'ssl_capath'        - Directory holding multiple Certificate\r
+     *                              Authority files (string)</li>\r
+     *   <li> 'ssl_local_cert'    - Name of a file containing local cerificate (string)</li>\r
+     *   <li> 'ssl_passphrase'    - Passphrase with which local certificate\r
+     *                              was encoded (string)</li>\r
+     *   <li> 'digest_compat_ie'  - Whether to imitate behaviour of MSIE 5 and 6\r
+     *                              in using URL without query string in digest\r
+     *                              authentication (boolean)</li>\r
+     *   <li> 'follow_redirects'  - Whether to automatically follow HTTP Redirects (boolean)</li>\r
+     *   <li> 'max_redirects'     - Maximum number of redirects to follow (integer)</li>\r
+     *   <li> 'strict_redirects'  - Whether to keep request method on redirects via status 301 and\r
+     *                              302 (true, needed for compatibility with RFC 2616)\r
+     *                              or switch to GET (false, needed for compatibility with most\r
+     *                              browsers) (boolean)</li>\r
+     * </ul>\r
+     *\r
+     * @param string|array $nameOrConfig configuration parameter name or array\r
+     *                                   ('parameter name' => 'parameter value')\r
+     * @param mixed        $value        parameter value if $nameOrConfig is not an array\r
+     *\r
+     * @return   HTTP_Request2\r
+     * @throws   HTTP_Request2_LogicException If the parameter is unknown\r
+     */\r
     public function setConfig($nameOrConfig, $value = null)\r
     {\r
         if (is_array($nameOrConfig)) {\r
@@ -370,6 +381,16 @@ class HTTP_Request2 implements SplSubject
                 $this->setConfig($name, $value);\r
             }\r
 \r
+        } elseif ('proxy' == $nameOrConfig) {\r
+            $url = new Net_URL2($value);\r
+            $this->setConfig(array(\r
+                'proxy_type'     => $url->getScheme(),\r
+                'proxy_host'     => $url->getHost(),\r
+                'proxy_port'     => $url->getPort(),\r
+                'proxy_user'     => rawurldecode($url->getUser()),\r
+                'proxy_password' => rawurldecode($url->getPassword())\r
+            ));\r
+\r
         } else {\r
             if (!array_key_exists($nameOrConfig, $this->config)) {\r
                 throw new HTTP_Request2_LogicException(\r
@@ -383,14 +404,15 @@ class HTTP_Request2 implements SplSubject
         return $this;\r
     }\r
 \r
-   /**\r
-    * Returns the value(s) of the configuration parameter(s)\r
-    *\r
-    * @param    string  parameter name\r
-    * @return   mixed   value of $name parameter, array of all configuration\r
-    *                   parameters if $name is not given\r
-    * @throws   HTTP_Request2_LogicException If the parameter is unknown\r
-    */\r
+    /**\r
+     * Returns the value(s) of the configuration parameter(s)\r
+     *\r
+     * @param string $name parameter name\r
+     *\r
+     * @return   mixed   value of $name parameter, array of all configuration\r
+     *                   parameters if $name is not given\r
+     * @throws   HTTP_Request2_LogicException If the parameter is unknown\r
+     */\r
     public function getConfig($name = null)\r
     {\r
         if (null === $name) {\r
@@ -404,14 +426,15 @@ class HTTP_Request2 implements SplSubject
         return $this->config[$name];\r
     }\r
 \r
-   /**\r
-    * Sets the autentification data\r
-    *\r
-    * @param    string  user name\r
-    * @param    string  password\r
-    * @param    string  authentication scheme\r
-    * @return   HTTP_Request2\r
-    */\r
+    /**\r
+     * Sets the autentification data\r
+     *\r
+     * @param string $user     user name\r
+     * @param string $password password\r
+     * @param string $scheme   authentication scheme\r
+     *\r
+     * @return   HTTP_Request2\r
+     */\r
     public function setAuth($user, $password = '', $scheme = self::AUTH_BASIC)\r
     {\r
         if (empty($user)) {\r
@@ -427,46 +450,47 @@ class HTTP_Request2 implements SplSubject
         return $this;\r
     }\r
 \r
-   /**\r
-    * Returns the authentication data\r
-    *\r
-    * The array has the keys 'user', 'password' and 'scheme', where 'scheme'\r
-    * is one of the HTTP_Request2::AUTH_* constants.\r
-    *\r
-    * @return   array\r
-    */\r
+    /**\r
+     * Returns the authentication data\r
+     *\r
+     * The array has the keys 'user', 'password' and 'scheme', where 'scheme'\r
+     * is one of the HTTP_Request2::AUTH_* constants.\r
+     *\r
+     * @return   array\r
+     */\r
     public function getAuth()\r
     {\r
         return $this->auth;\r
     }\r
 \r
-   /**\r
-    * Sets request header(s)\r
-    *\r
-    * The first parameter may be either a full header string 'header: value' or\r
-    * header name. In the former case $value parameter is ignored, in the latter\r
-    * the header's value will either be set to $value or the header will be\r
-    * removed if $value is null. The first parameter can also be an array of\r
-    * headers, in that case method will be called recursively.\r
-    *\r
-    * Note that headers are treated case insensitively as per RFC 2616.\r
-    *\r
-    * <code>\r
-    * $req->setHeader('Foo: Bar'); // sets the value of 'Foo' header to 'Bar'\r
-    * $req->setHeader('FoO', 'Baz'); // sets the value of 'Foo' header to 'Baz'\r
-    * $req->setHeader(array('foo' => 'Quux')); // sets the value of 'Foo' header to 'Quux'\r
-    * $req->setHeader('FOO'); // removes 'Foo' header from request\r
-    * </code>\r
-    *\r
-    * @param    string|array    header name, header string ('Header: value')\r
-    *                           or an array of headers\r
-    * @param    string|array|null header value if $name is not an array,\r
-    *                           header will be removed if value is null\r
-    * @param    bool            whether to replace previous header with the\r
-    *                           same name or append to its value\r
-    * @return   HTTP_Request2\r
-    * @throws   HTTP_Request2_LogicException\r
-    */\r
+    /**\r
+     * Sets request header(s)\r
+     *\r
+     * The first parameter may be either a full header string 'header: value' or\r
+     * header name. In the former case $value parameter is ignored, in the latter\r
+     * the header's value will either be set to $value or the header will be\r
+     * removed if $value is null. The first parameter can also be an array of\r
+     * headers, in that case method will be called recursively.\r
+     *\r
+     * Note that headers are treated case insensitively as per RFC 2616.\r
+     *\r
+     * <code>\r
+     * $req->setHeader('Foo: Bar'); // sets the value of 'Foo' header to 'Bar'\r
+     * $req->setHeader('FoO', 'Baz'); // sets the value of 'Foo' header to 'Baz'\r
+     * $req->setHeader(array('foo' => 'Quux')); // sets the value of 'Foo' header to 'Quux'\r
+     * $req->setHeader('FOO'); // removes 'Foo' header from request\r
+     * </code>\r
+     *\r
+     * @param string|array      $name    header name, header string ('Header: value')\r
+     *                                   or an array of headers\r
+     * @param string|array|null $value   header value if $name is not an array,\r
+     *                                   header will be removed if value is null\r
+     * @param bool              $replace whether to replace previous header with the\r
+     *                                   same name or append to its value\r
+     *\r
+     * @return   HTTP_Request2\r
+     * @throws   HTTP_Request2_LogicException\r
+     */\r
     public function setHeader($name, $value = null, $replace = true)\r
     {\r
         if (is_array($name)) {\r
@@ -510,41 +534,43 @@ class HTTP_Request2 implements SplSubject
         return $this;\r
     }\r
 \r
-   /**\r
-    * Returns the request headers\r
-    *\r
-    * The array is of the form ('header name' => 'header value'), header names\r
-    * are lowercased\r
-    *\r
-    * @return   array\r
-    */\r
+    /**\r
+     * Returns the request headers\r
+     *\r
+     * The array is of the form ('header name' => 'header value'), header names\r
+     * are lowercased\r
+     *\r
+     * @return   array\r
+     */\r
     public function getHeaders()\r
     {\r
         return $this->headers;\r
     }\r
 \r
-   /**\r
-    * Adds a cookie to the request\r
-    *\r
-    * If the request does not have a CookieJar object set, this method simply\r
-    * appends a cookie to "Cookie:" header.\r
-    *\r
-    * If a CookieJar object is available, the cookie is stored in that object.\r
-    * Data from request URL will be used for setting its 'domain' and 'path'\r
-    * parameters, 'expires' and 'secure' will be set to null and false,\r
-    * respectively. If you need further control, use CookieJar's methods.\r
-    *\r
-    * @param    string  cookie name\r
-    * @param    string  cookie value\r
-    * @return   HTTP_Request2\r
-    * @throws   HTTP_Request2_LogicException\r
-    * @see      setCookieJar()\r
-    */\r
+    /**\r
+     * Adds a cookie to the request\r
+     *\r
+     * If the request does not have a CookieJar object set, this method simply\r
+     * appends a cookie to "Cookie:" header.\r
+     *\r
+     * If a CookieJar object is available, the cookie is stored in that object.\r
+     * Data from request URL will be used for setting its 'domain' and 'path'\r
+     * parameters, 'expires' and 'secure' will be set to null and false,\r
+     * respectively. If you need further control, use CookieJar's methods.\r
+     *\r
+     * @param string $name  cookie name\r
+     * @param string $value cookie value\r
+     *\r
+     * @return   HTTP_Request2\r
+     * @throws   HTTP_Request2_LogicException\r
+     * @see      setCookieJar()\r
+     */\r
     public function addCookie($name, $value)\r
     {\r
         if (!empty($this->cookieJar)) {\r
-            $this->cookieJar->store(array('name' => $name, 'value' => $value),\r
-                                    $this->url);\r
+            $this->cookieJar->store(\r
+                array('name' => $name, 'value' => $value), $this->url\r
+            );\r
 \r
         } else {\r
             $cookie = $name . '=' . $value;\r
@@ -561,19 +587,21 @@ class HTTP_Request2 implements SplSubject
         return $this;\r
     }\r
 \r
-   /**\r
-    * Sets the request body\r
-    *\r
-    * If you provide file pointer rather than file name, it should support\r
-    * fstat() and rewind() operations.\r
-    *\r
-    * @param    string|resource|HTTP_Request2_MultipartBody  Either a string\r
-    *               with the body or filename containing body or pointer to\r
-    *               an open file or object with multipart body data\r
-    * @param    bool    Whether first parameter is a filename\r
-    * @return   HTTP_Request2\r
-    * @throws   HTTP_Request2_LogicException\r
-    */\r
+    /**\r
+     * Sets the request body\r
+     *\r
+     * If you provide file pointer rather than file name, it should support\r
+     * fstat() and rewind() operations.\r
+     *\r
+     * @param string|resource|HTTP_Request2_MultipartBody $body       Either a\r
+     *               string with the body or filename containing body or\r
+     *               pointer to an open file or object with multipart body data\r
+     * @param bool                                        $isFilename Whether\r
+     *               first parameter is a filename\r
+     *\r
+     * @return   HTTP_Request2\r
+     * @throws   HTTP_Request2_LogicException\r
+     */\r
     public function setBody($body, $isFilename = false)\r
     {\r
         if (!$isFilename && !is_resource($body)) {\r
@@ -594,15 +622,15 @@ class HTTP_Request2 implements SplSubject
         return $this;\r
     }\r
 \r
-   /**\r
-    * Returns the request body\r
-    *\r
-    * @return   string|resource|HTTP_Request2_MultipartBody\r
-    */\r
+    /**\r
+     * Returns the request body\r
+     *\r
+     * @return   string|resource|HTTP_Request2_MultipartBody\r
+     */\r
     public function getBody()\r
     {\r
-        if (self::METHOD_POST == $this->method &&\r
-            (!empty($this->postParams) || !empty($this->uploads))\r
+        if (self::METHOD_POST == $this->method\r
+            && (!empty($this->postParams) || !empty($this->uploads))\r
         ) {\r
             if (0 === strpos($this->headers['content-type'], 'application/x-www-form-urlencoded')) {\r
                 $body = http_build_query($this->postParams, '', '&');\r
@@ -622,29 +650,30 @@ class HTTP_Request2 implements SplSubject
         return $this->body;\r
     }\r
 \r
-   /**\r
-    * Adds a file to form-based file upload\r
-    *\r
-    * Used to emulate file upload via a HTML form. The method also sets\r
-    * Content-Type of HTTP request to 'multipart/form-data'.\r
-    *\r
-    * If you just want to send the contents of a file as the body of HTTP\r
-    * request you should use setBody() method.\r
-    *\r
-    * If you provide file pointers rather than file names, they should support\r
-    * fstat() and rewind() operations.\r
-    *\r
-    * @param    string  name of file-upload field\r
-    * @param    string|resource|array   full name of local file, pointer to\r
-    *               open file or an array of files\r
-    * @param    string  filename to send in the request\r
-    * @param    string  content-type of file being uploaded\r
-    * @return   HTTP_Request2\r
-    * @throws   HTTP_Request2_LogicException\r
-    */\r
-    public function addUpload($fieldName, $filename, $sendFilename = null,\r
-                              $contentType = null)\r
-    {\r
+    /**\r
+     * Adds a file to form-based file upload\r
+     *\r
+     * Used to emulate file upload via a HTML form. The method also sets\r
+     * Content-Type of HTTP request to 'multipart/form-data'.\r
+     *\r
+     * If you just want to send the contents of a file as the body of HTTP\r
+     * request you should use setBody() method.\r
+     *\r
+     * If you provide file pointers rather than file names, they should support\r
+     * fstat() and rewind() operations.\r
+     *\r
+     * @param string                $fieldName    name of file-upload field\r
+     * @param string|resource|array $filename     full name of local file,\r
+     *               pointer to open file or an array of files\r
+     * @param string                $sendFilename filename to send in the request\r
+     * @param string                $contentType  content-type of file being uploaded\r
+     *\r
+     * @return   HTTP_Request2\r
+     * @throws   HTTP_Request2_LogicException\r
+     */\r
+    public function addUpload(\r
+        $fieldName, $filename, $sendFilename = null, $contentType = null\r
+    ) {\r
         if (!is_array($filename)) {\r
             $fileData = $this->fopenWrapper($filename, empty($contentType));\r
             $this->uploads[$fieldName] = array(\r
@@ -671,8 +700,8 @@ class HTTP_Request2 implements SplSubject
                 'fp' => $fps, 'filename' => $names, 'size' => $sizes, 'type' => $types\r
             );\r
         }\r
-        if (empty($this->headers['content-type']) ||\r
-            'application/x-www-form-urlencoded' == $this->headers['content-type']\r
+        if (empty($this->headers['content-type'])\r
+            || 'application/x-www-form-urlencoded' == $this->headers['content-type']\r
         ) {\r
             $this->setHeader('content-type', 'multipart/form-data');\r
         }\r
@@ -680,13 +709,14 @@ class HTTP_Request2 implements SplSubject
         return $this;\r
     }\r
 \r
-   /**\r
-    * Adds POST parameter(s) to the request.\r
-    *\r
-    * @param    string|array    parameter name or array ('name' => 'value')\r
-    * @param    mixed           parameter value (can be an array)\r
-    * @return   HTTP_Request2\r
-    */\r
+    /**\r
+     * Adds POST parameter(s) to the request.\r
+     *\r
+     * @param string|array $name  parameter name or array ('name' => 'value')\r
+     * @param mixed        $value parameter value (can be an array)\r
+     *\r
+     * @return   HTTP_Request2\r
+     */\r
     public function addPostParameter($name, $value = null)\r
     {\r
         if (!is_array($name)) {\r
@@ -703,11 +733,11 @@ class HTTP_Request2 implements SplSubject
         return $this;\r
     }\r
 \r
-   /**\r
-    * Attaches a new observer\r
-    *\r
-    * @param    SplObserver\r
-    */\r
+    /**\r
+     * Attaches a new observer\r
+     *\r
+     * @param SplObserver $observer any object implementing SplObserver\r
+     */\r
     public function attach(SplObserver $observer)\r
     {\r
         foreach ($this->observers as $attached) {\r
@@ -718,11 +748,11 @@ class HTTP_Request2 implements SplSubject
         $this->observers[] = $observer;\r
     }\r
 \r
-   /**\r
-    * Detaches an existing observer\r
-    *\r
-    * @param    SplObserver\r
-    */\r
+    /**\r
+     * Detaches an existing observer\r
+     *\r
+     * @param SplObserver $observer any object implementing SplObserver\r
+     */\r
     public function detach(SplObserver $observer)\r
     {\r
         foreach ($this->observers as $key => $attached) {\r
@@ -733,9 +763,9 @@ class HTTP_Request2 implements SplSubject
         }\r
     }\r
 \r
-   /**\r
-    * Notifies all observers\r
-    */\r
+    /**\r
+     * Notifies all observers\r
+     */\r
     public function notify()\r
     {\r
         foreach ($this->observers as $observer) {\r
@@ -743,15 +773,15 @@ class HTTP_Request2 implements SplSubject
         }\r
     }\r
 \r
-   /**\r
-    * Sets the last event\r
-    *\r
-    * Adapters should use this method to set the current state of the request\r
-    * and notify the observers.\r
-    *\r
-    * @param    string  event name\r
-    * @param    mixed   event data\r
-    */\r
+    /**\r
+     * Sets the last event\r
+     *\r
+     * Adapters should use this method to set the current state of the request\r
+     * and notify the observers.\r
+     *\r
+     * @param string $name event name\r
+     * @param mixed  $data event data\r
+     */\r
     public function setLastEvent($name, $data = null)\r
     {\r
         $this->lastEvent = array(\r
@@ -761,56 +791,57 @@ class HTTP_Request2 implements SplSubject
         $this->notify();\r
     }\r
 \r
-   /**\r
-    * Returns the last event\r
-    *\r
-    * Observers should use this method to access the last change in request.\r
-    * The following event names are possible:\r
-    * <ul>\r
-    *   <li>'connect'                 - after connection to remote server,\r
-    *                                   data is the destination (string)</li>\r
-    *   <li>'disconnect'              - after disconnection from server</li>\r
-    *   <li>'sentHeaders'             - after sending the request headers,\r
-    *                                   data is the headers sent (string)</li>\r
-    *   <li>'sentBodyPart'            - after sending a part of the request body,\r
-    *                                   data is the length of that part (int)</li>\r
-    *   <li>'sentBody'                - after sending the whole request body,\r
-    *                                   data is request body length (int)</li>\r
-    *   <li>'receivedHeaders'         - after receiving the response headers,\r
-    *                                   data is HTTP_Request2_Response object</li>\r
-    *   <li>'receivedBodyPart'        - after receiving a part of the response\r
-    *                                   body, data is that part (string)</li>\r
-    *   <li>'receivedEncodedBodyPart' - as 'receivedBodyPart', but data is still\r
-    *                                   encoded by Content-Encoding</li>\r
-    *   <li>'receivedBody'            - after receiving the complete response\r
-    *                                   body, data is HTTP_Request2_Response object</li>\r
-    * </ul>\r
-    * Different adapters may not send all the event types. Mock adapter does\r
-    * not send any events to the observers.\r
-    *\r
-    * @return   array   The array has two keys: 'name' and 'data'\r
-    */\r
+    /**\r
+     * Returns the last event\r
+     *\r
+     * Observers should use this method to access the last change in request.\r
+     * The following event names are possible:\r
+     * <ul>\r
+     *   <li>'connect'                 - after connection to remote server,\r
+     *                                   data is the destination (string)</li>\r
+     *   <li>'disconnect'              - after disconnection from server</li>\r
+     *   <li>'sentHeaders'             - after sending the request headers,\r
+     *                                   data is the headers sent (string)</li>\r
+     *   <li>'sentBodyPart'            - after sending a part of the request body,\r
+     *                                   data is the length of that part (int)</li>\r
+     *   <li>'sentBody'                - after sending the whole request body,\r
+     *                                   data is request body length (int)</li>\r
+     *   <li>'receivedHeaders'         - after receiving the response headers,\r
+     *                                   data is HTTP_Request2_Response object</li>\r
+     *   <li>'receivedBodyPart'        - after receiving a part of the response\r
+     *                                   body, data is that part (string)</li>\r
+     *   <li>'receivedEncodedBodyPart' - as 'receivedBodyPart', but data is still\r
+     *                                   encoded by Content-Encoding</li>\r
+     *   <li>'receivedBody'            - after receiving the complete response\r
+     *                                   body, data is HTTP_Request2_Response object</li>\r
+     * </ul>\r
+     * Different adapters may not send all the event types. Mock adapter does\r
+     * not send any events to the observers.\r
+     *\r
+     * @return   array   The array has two keys: 'name' and 'data'\r
+     */\r
     public function getLastEvent()\r
     {\r
         return $this->lastEvent;\r
     }\r
 \r
-   /**\r
-    * Sets the adapter used to actually perform the request\r
-    *\r
-    * You can pass either an instance of a class implementing HTTP_Request2_Adapter\r
-    * or a class name. The method will only try to include a file if the class\r
-    * name starts with HTTP_Request2_Adapter_, it will also try to prepend this\r
-    * prefix to the class name if it doesn't contain any underscores, so that\r
-    * <code>\r
-    * $request->setAdapter('curl');\r
-    * </code>\r
-    * will work.\r
-    *\r
-    * @param    string|HTTP_Request2_Adapter\r
-    * @return   HTTP_Request2\r
-    * @throws   HTTP_Request2_LogicException\r
-    */\r
+    /**\r
+     * Sets the adapter used to actually perform the request\r
+     *\r
+     * You can pass either an instance of a class implementing HTTP_Request2_Adapter\r
+     * or a class name. The method will only try to include a file if the class\r
+     * name starts with HTTP_Request2_Adapter_, it will also try to prepend this\r
+     * prefix to the class name if it doesn't contain any underscores, so that\r
+     * <code>\r
+     * $request->setAdapter('curl');\r
+     * </code>\r
+     * will work.\r
+     *\r
+     * @param string|HTTP_Request2_Adapter $adapter Adapter to use\r
+     *\r
+     * @return   HTTP_Request2\r
+     * @throws   HTTP_Request2_LogicException\r
+     */\r
     public function setAdapter($adapter)\r
     {\r
         if (is_string($adapter)) {\r
@@ -818,7 +849,9 @@ class HTTP_Request2 implements SplSubject
                 if (false === strpos($adapter, '_')) {\r
                     $adapter = 'HTTP_Request2_Adapter_' . ucfirst($adapter);\r
                 }\r
-                if (preg_match('/^HTTP_Request2_Adapter_([a-zA-Z0-9]+)$/', $adapter)) {\r
+                if (!class_exists($adapter, false)\r
+                    && preg_match('/^HTTP_Request2_Adapter_([a-zA-Z0-9]+)$/', $adapter)\r
+                ) {\r
                     include_once str_replace('_', DIRECTORY_SEPARATOR, $adapter) . '.php';\r
                 }\r
                 if (!class_exists($adapter, false)) {\r
@@ -841,16 +874,19 @@ class HTTP_Request2 implements SplSubject
         return $this;\r
     }\r
 \r
-   /**\r
-    * Sets the cookie jar\r
-    *\r
-    * A cookie jar is used to maintain cookies across HTTP requests and\r
-    * responses. Cookies from jar will be automatically added to the request\r
-    * headers based on request URL.\r
-    *\r
-    * @param HTTP_Request2_CookieJar|bool   Existing CookieJar object, true to\r
-    *                                       create a new one, false to remove\r
-    */\r
+    /**\r
+     * Sets the cookie jar\r
+     *\r
+     * A cookie jar is used to maintain cookies across HTTP requests and\r
+     * responses. Cookies from jar will be automatically added to the request\r
+     * headers based on request URL.\r
+     *\r
+     * @param HTTP_Request2_CookieJar|bool $jar Existing CookieJar object, true to\r
+     *                                          create a new one, false to remove\r
+     *\r
+     * @return HTTP_Request2\r
+     * @throws HTTP_Request2_LogicException\r
+     */\r
     public function setCookieJar($jar = true)\r
     {\r
         if (!class_exists('HTTP_Request2_CookieJar', false)) {\r
@@ -873,22 +909,22 @@ class HTTP_Request2 implements SplSubject
         return $this;\r
     }\r
 \r
-   /**\r
-    * Returns current CookieJar object or null if none\r
-    *\r
-    * @return HTTP_Request2_CookieJar|null\r
-    */\r
+    /**\r
+     * Returns current CookieJar object or null if none\r
+     *\r
+     * @return HTTP_Request2_CookieJar|null\r
+     */\r
     public function getCookieJar()\r
     {\r
         return $this->cookieJar;\r
     }\r
 \r
-   /**\r
-    * Sends the request and returns the response\r
-    *\r
-    * @throws   HTTP_Request2_Exception\r
-    * @return   HTTP_Request2_Response\r
-    */\r
+    /**\r
+     * Sends the request and returns the response\r
+     *\r
+     * @throws   HTTP_Request2_Exception\r
+     * @return   HTTP_Request2_Response\r
+     */\r
     public function send()\r
     {\r
         // Sanity check for URL\r
@@ -899,7 +935,7 @@ class HTTP_Request2 implements SplSubject
             throw new HTTP_Request2_LogicException(\r
                 'HTTP_Request2 needs an absolute HTTP(S) request URL, '\r
                 . ($this->url instanceof Net_URL2\r
-                   ? 'none' : "'" . $this->url->__toString() . "'")\r
+                   ? "'" . $this->url->__toString() . "'" : 'none')\r
                 . ' given',\r
                 HTTP_Request2_Exception::INVALID_ARGUMENT\r
             );\r
@@ -916,7 +952,7 @@ class HTTP_Request2 implements SplSubject
         // strlen() and substr(); see bug #1781, bug #10605\r
         if (extension_loaded('mbstring') && (2 & ini_get('mbstring.func_overload'))) {\r
             $oldEncoding = mb_internal_encoding();\r
-            mb_internal_encoding('iso-8859-1');\r
+            mb_internal_encoding('8bit');\r
         }\r
 \r
         try {\r
@@ -937,15 +973,17 @@ class HTTP_Request2 implements SplSubject
         return $response;\r
     }\r
 \r
-   /**\r
-    * Wrapper around fopen()/fstat() used by setBody() and addUpload()\r
-    *\r
-    * @param  string|resource file name or pointer to open file\r
-    * @param  bool            whether to try autodetecting MIME type of file,\r
-    *                         will only work if $file is a filename, not pointer\r
-    * @return array array('fp' => file pointer, 'size' => file size, 'type' => MIME type)\r
-    * @throws HTTP_Request2_LogicException\r
-    */\r
+    /**\r
+     * Wrapper around fopen()/fstat() used by setBody() and addUpload()\r
+     *\r
+     * @param string|resource $file       file name or pointer to open file\r
+     * @param bool            $detectType whether to try autodetecting MIME\r
+     *                        type of file, will only work if $file is a\r
+     *                        filename, not pointer\r
+     *\r
+     * @return array array('fp' => file pointer, 'size' => file size, 'type' => MIME type)\r
+     * @throws HTTP_Request2_LogicException\r
+     */\r
     protected function fopenWrapper($file, $detectType = false)\r
     {\r
         if (!is_string($file) && !is_resource($file)) {\r
@@ -960,16 +998,12 @@ class HTTP_Request2 implements SplSubject
             'size' => 0\r
         );\r
         if (is_string($file)) {\r
-            $track = @ini_set('track_errors', 1);\r
             if (!($fileData['fp'] = @fopen($file, 'rb'))) {\r
-                $e = new HTTP_Request2_LogicException(\r
-                    $php_errormsg, HTTP_Request2_Exception::READ_ERROR\r
+                $error = error_get_last();\r
+                throw new HTTP_Request2_LogicException(\r
+                    $error['message'], HTTP_Request2_Exception::READ_ERROR\r
                 );\r
             }\r
-            @ini_set('track_errors', $track);\r
-            if (isset($e)) {\r
-                throw $e;\r
-            }\r
             if ($detectType) {\r
                 $fileData['type'] = self::detectMimeType($file);\r
             }\r
@@ -984,16 +1018,17 @@ class HTTP_Request2 implements SplSubject
         return $fileData;\r
     }\r
 \r
-   /**\r
-    * Tries to detect MIME type of a file\r
-    *\r
-    * The method will try to use fileinfo extension if it is available,\r
-    * deprecated mime_content_type() function in the other case. If neither\r
-    * works, default 'application/octet-stream' MIME type is returned\r
-    *\r
-    * @param    string  filename\r
-    * @return   string  file MIME type\r
-    */\r
+    /**\r
+     * Tries to detect MIME type of a file\r
+     *\r
+     * The method will try to use fileinfo extension if it is available,\r
+     * deprecated mime_content_type() function in the other case. If neither\r
+     * works, default 'application/octet-stream' MIME type is returned\r
+     *\r
+     * @param string $filename file name\r
+     *\r
+     * @return   string  file MIME type\r
+     */\r
     protected static function detectMimeType($filename)\r
     {\r
         // finfo extension from PECL available\r
@@ -1012,4 +1047,4 @@ class HTTP_Request2 implements SplSubject
         return empty($info)? 'application/octet-stream': $info;\r
     }\r
 }\r
-?>
\ No newline at end of file
+?>\r
index 2cabbf897b8ddcbe3e2a54d549461d3d7e70ac3a..3ab7d38cc3b2baa8293c8f3501ee9059aeeabd30 100644 (file)
@@ -6,7 +6,7 @@
  *\r
  * LICENSE:\r
  *\r
- * Copyright (c) 2008-2011, Alexey Borzov <avb@php.net>\r
+ * Copyright (c) 2008-2012, Alexey Borzov <avb@php.net>\r
  * All rights reserved.\r
  *\r
  * Redistribution and use in source and binary forms, with or without\r
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
  *\r
- * @category   HTTP\r
- * @package    HTTP_Request2\r
- * @author     Alexey Borzov <avb@php.net>\r
- * @license    http://opensource.org/licenses/bsd-license.php New BSD License\r
- * @version    SVN: $Id: Adapter.php 308322 2011-02-14 13:58:03Z avb $\r
- * @link       http://pear.php.net/package/HTTP_Request2\r
+ * @category HTTP\r
+ * @package  HTTP_Request2\r
+ * @author   Alexey Borzov <avb@php.net>\r
+ * @license  http://opensource.org/licenses/bsd-license.php New BSD License\r
+ * @version  SVN: $Id: Adapter.php 324415 2012-03-21 10:50:50Z avb $\r
+ * @link     http://pear.php.net/package/HTTP_Request2\r
  */\r
 \r
 /**\r
@@ -53,66 +53,69 @@ require_once 'HTTP/Request2/Response.php';
  * data, all actual work of sending the request to the remote server and\r
  * receiving its response is performed by adapters.\r
  *\r
- * @category   HTTP\r
- * @package    HTTP_Request2\r
- * @author     Alexey Borzov <avb@php.net>\r
- * @version    Release: 2.0.0RC1\r
+ * @category HTTP\r
+ * @package  HTTP_Request2\r
+ * @author   Alexey Borzov <avb@php.net>\r
+ * @license  http://opensource.org/licenses/bsd-license.php New BSD License\r
+ * @version  Release: 2.1.1\r
+ * @link     http://pear.php.net/package/HTTP_Request2\r
  */\r
 abstract class HTTP_Request2_Adapter\r
 {\r
-   /**\r
-    * A list of methods that MUST NOT have a request body, per RFC 2616\r
-    * @var  array\r
-    */\r
+    /**\r
+     * A list of methods that MUST NOT have a request body, per RFC 2616\r
+     * @var  array\r
+     */\r
     protected static $bodyDisallowed = array('TRACE');\r
 \r
-   /**\r
-    * Methods having defined semantics for request body\r
-    *\r
-    * Content-Length header (indicating that the body follows, section 4.3 of\r
-    * RFC 2616) will be sent for these methods even if no body was added\r
-    *\r
-    * @var  array\r
-    * @link http://pear.php.net/bugs/bug.php?id=12900\r
-    * @link http://pear.php.net/bugs/bug.php?id=14740\r
-    */\r
+    /**\r
+     * Methods having defined semantics for request body\r
+     *\r
+     * Content-Length header (indicating that the body follows, section 4.3 of\r
+     * RFC 2616) will be sent for these methods even if no body was added\r
+     *\r
+     * @var  array\r
+     * @link http://pear.php.net/bugs/bug.php?id=12900\r
+     * @link http://pear.php.net/bugs/bug.php?id=14740\r
+     */\r
     protected static $bodyRequired = array('POST', 'PUT');\r
 \r
-   /**\r
-    * Request being sent\r
-    * @var  HTTP_Request2\r
-    */\r
+    /**\r
+     * Request being sent\r
+     * @var  HTTP_Request2\r
+     */\r
     protected $request;\r
 \r
-   /**\r
-    * Request body\r
-    * @var  string|resource|HTTP_Request2_MultipartBody\r
-    * @see  HTTP_Request2::getBody()\r
-    */\r
+    /**\r
+     * Request body\r
+     * @var  string|resource|HTTP_Request2_MultipartBody\r
+     * @see  HTTP_Request2::getBody()\r
+     */\r
     protected $requestBody;\r
 \r
-   /**\r
-    * Length of the request body\r
-    * @var  integer\r
-    */\r
+    /**\r
+     * Length of the request body\r
+     * @var  integer\r
+     */\r
     protected $contentLength;\r
 \r
-   /**\r
-    * Sends request to the remote server and returns its response\r
-    *\r
-    * @param    HTTP_Request2\r
-    * @return   HTTP_Request2_Response\r
-    * @throws   HTTP_Request2_Exception\r
-    */\r
+    /**\r
+     * Sends request to the remote server and returns its response\r
+     *\r
+     * @param HTTP_Request2 $request HTTP request message\r
+     *\r
+     * @return   HTTP_Request2_Response\r
+     * @throws   HTTP_Request2_Exception\r
+     */\r
     abstract public function sendRequest(HTTP_Request2 $request);\r
 \r
-   /**\r
-    * Calculates length of the request body, adds proper headers\r
-    *\r
-    * @param    array   associative array of request headers, this method will\r
-    *                   add proper 'Content-Length' and 'Content-Type' headers\r
-    *                   to this array (or remove them if not needed)\r
-    */\r
+    /**\r
+     * Calculates length of the request body, adds proper headers\r
+     *\r
+     * @param array &$headers associative array of request headers, this method\r
+     *                        will add proper 'Content-Length' and 'Content-Type'\r
+     *                        headers to this array (or remove them if not needed)\r
+     */\r
     protected function calculateRequestLength(&$headers)\r
     {\r
         $this->requestBody = $this->request->getBody();\r
@@ -130,8 +133,8 @@ abstract class HTTP_Request2_Adapter
             $this->requestBody->rewind();\r
         }\r
 \r
-        if (in_array($this->request->getMethod(), self::$bodyDisallowed) ||\r
-            0 == $this->contentLength\r
+        if (in_array($this->request->getMethod(), self::$bodyDisallowed)\r
+            || 0 == $this->contentLength\r
         ) {\r
             // No body: send a Content-Length header nonetheless (request #12900),\r
             // but do that only for methods that require a body (bug #14740)\r
index fecfbd7abceb7d48f39de33d90eaa55923a2486d..c80c94584e5d0a35a38ab783edf97f2b71423d92 100644 (file)
@@ -6,7 +6,7 @@
  *\r
  * LICENSE:\r
  *\r
- * Copyright (c) 2008-2011, Alexey Borzov <avb@php.net>\r
+ * Copyright (c) 2008-2012, Alexey Borzov <avb@php.net>\r
  * All rights reserved.\r
  *\r
  * Redistribution and use in source and binary forms, with or without\r
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
  *\r
- * @category   HTTP\r
- * @package    HTTP_Request2\r
- * @author     Alexey Borzov <avb@php.net>\r
- * @license    http://opensource.org/licenses/bsd-license.php New BSD License\r
- * @version    SVN: $Id: Curl.php 310800 2011-05-06 07:29:56Z avb $\r
- * @link       http://pear.php.net/package/HTTP_Request2\r
+ * @category HTTP\r
+ * @package  HTTP_Request2\r
+ * @author   Alexey Borzov <avb@php.net>\r
+ * @license  http://opensource.org/licenses/bsd-license.php New BSD License\r
+ * @version  SVN: $Id: Curl.php 324746 2012-04-03 15:09:16Z avb $\r
+ * @link     http://pear.php.net/package/HTTP_Request2\r
  */\r
 \r
 /**\r
@@ -49,17 +49,19 @@ require_once 'HTTP/Request2/Adapter.php';
 /**\r
  * Adapter for HTTP_Request2 wrapping around cURL extension\r
  *\r
- * @category    HTTP\r
- * @package     HTTP_Request2\r
- * @author      Alexey Borzov <avb@php.net>\r
- * @version     Release: 2.0.0RC1\r
+ * @category HTTP\r
+ * @package  HTTP_Request2\r
+ * @author   Alexey Borzov <avb@php.net>\r
+ * @license  http://opensource.org/licenses/bsd-license.php New BSD License\r
+ * @version  Release: 2.1.1\r
+ * @link     http://pear.php.net/package/HTTP_Request2\r
  */\r
 class HTTP_Request2_Adapter_Curl extends HTTP_Request2_Adapter\r
 {\r
-   /**\r
-    * Mapping of header names to cURL options\r
-    * @var  array\r
-    */\r
+    /**\r
+     * Mapping of header names to cURL options\r
+     * @var  array\r
+     */\r
     protected static $headerMap = array(\r
         'accept-encoding' => CURLOPT_ENCODING,\r
         'cookie'          => CURLOPT_COOKIE,\r
@@ -67,22 +69,22 @@ class HTTP_Request2_Adapter_Curl extends HTTP_Request2_Adapter
         'user-agent'      => CURLOPT_USERAGENT\r
     );\r
 \r
-   /**\r
-    * Mapping of SSL context options to cURL options\r
-    * @var  array\r
-    */\r
+    /**\r
+     * Mapping of SSL context options to cURL options\r
+     * @var  array\r
+     */\r
     protected static $sslContextMap = array(\r
         'ssl_verify_peer' => CURLOPT_SSL_VERIFYPEER,\r
         'ssl_cafile'      => CURLOPT_CAINFO,\r
         'ssl_capath'      => CURLOPT_CAPATH,\r
         'ssl_local_cert'  => CURLOPT_SSLCERT,\r
         'ssl_passphrase'  => CURLOPT_SSLCERTPASSWD\r
-   );\r
+    );\r
 \r
-   /**\r
-    * Mapping of CURLE_* constants to Exception subclasses and error codes\r
-    * @var  array\r
-    */\r
+    /**\r
+     * Mapping of CURLE_* constants to Exception subclasses and error codes\r
+     * @var  array\r
+     */\r
     protected static $errorMap = array(\r
         CURLE_UNSUPPORTED_PROTOCOL  => array('HTTP_Request2_MessageException',\r
                                              HTTP_Request2_Exception::NON_HTTP_REDIRECT),\r
@@ -119,43 +121,44 @@ class HTTP_Request2_Adapter_Curl extends HTTP_Request2_Adapter
         CURLE_BAD_CONTENT_ENCODING  => array('HTTP_Request2_MessageException'),\r
     );\r
 \r
-   /**\r
-    * Response being received\r
-    * @var  HTTP_Request2_Response\r
-    */\r
+    /**\r
+     * Response being received\r
+     * @var  HTTP_Request2_Response\r
+     */\r
     protected $response;\r
 \r
-   /**\r
-    * Whether 'sentHeaders' event was sent to observers\r
-    * @var  boolean\r
-    */\r
+    /**\r
+     * Whether 'sentHeaders' event was sent to observers\r
+     * @var  boolean\r
+     */\r
     protected $eventSentHeaders = false;\r
 \r
-   /**\r
-    * Whether 'receivedHeaders' event was sent to observers\r
-    * @var boolean\r
-    */\r
+    /**\r
+     * Whether 'receivedHeaders' event was sent to observers\r
+     * @var boolean\r
+     */\r
     protected $eventReceivedHeaders = false;\r
 \r
-   /**\r
-    * Position within request body\r
-    * @var  integer\r
-    * @see  callbackReadBody()\r
-    */\r
+    /**\r
+     * Position within request body\r
+     * @var  integer\r
+     * @see  callbackReadBody()\r
+     */\r
     protected $position = 0;\r
 \r
-   /**\r
-    * Information about last transfer, as returned by curl_getinfo()\r
-    * @var  array\r
-    */\r
+    /**\r
+     * Information about last transfer, as returned by curl_getinfo()\r
+     * @var  array\r
+     */\r
     protected $lastInfo;\r
 \r
-   /**\r
-    * Creates a subclass of HTTP_Request2_Exception from curl error data\r
-    *\r
-    * @param resource curl handle\r
-    * @return HTTP_Request2_Exception\r
-    */\r
+    /**\r
+     * Creates a subclass of HTTP_Request2_Exception from curl error data\r
+     *\r
+     * @param resource $ch curl handle\r
+     *\r
+     * @return HTTP_Request2_Exception\r
+     */\r
     protected static function wrapCurlError($ch)\r
     {\r
         $nativeCode = curl_errno($ch);\r
@@ -170,13 +173,14 @@ class HTTP_Request2_Adapter_Curl extends HTTP_Request2_Adapter
         }\r
     }\r
 \r
-   /**\r
-    * Sends request to the remote server and returns its response\r
-    *\r
-    * @param    HTTP_Request2\r
-    * @return   HTTP_Request2_Response\r
-    * @throws   HTTP_Request2_Exception\r
-    */\r
+    /**\r
+     * Sends request to the remote server and returns its response\r
+     *\r
+     * @param HTTP_Request2 $request HTTP request message\r
+     *\r
+     * @return   HTTP_Request2_Response\r
+     * @throws   HTTP_Request2_Exception\r
+     */\r
     public function sendRequest(HTTP_Request2 $request)\r
     {\r
         if (!extension_loaded('curl')) {\r
@@ -219,22 +223,22 @@ class HTTP_Request2_Adapter_Curl extends HTTP_Request2_Adapter
         return $response;\r
     }\r
 \r
-   /**\r
-    * Returns information about last transfer\r
-    *\r
-    * @return   array   associative array as returned by curl_getinfo()\r
-    */\r
+    /**\r
+     * Returns information about last transfer\r
+     *\r
+     * @return   array   associative array as returned by curl_getinfo()\r
+     */\r
     public function getInfo()\r
     {\r
         return $this->lastInfo;\r
     }\r
 \r
-   /**\r
-    * Creates a new cURL handle and populates it with data from the request\r
-    *\r
-    * @return   resource    a cURL handle, as created by curl_init()\r
-    * @throws   HTTP_Request2_LogicException\r
-    */\r
+    /**\r
+     * Creates a new cURL handle and populates it with data from the request\r
+     *\r
+     * @return   resource    a cURL handle, as created by curl_init()\r
+     * @throws   HTTP_Request2_LogicException\r
+     */\r
     protected function createCurlHandle()\r
     {\r
         $ch = curl_init();\r
@@ -281,29 +285,29 @@ class HTTP_Request2_Adapter_Curl extends HTTP_Request2_Adapter
 \r
         // set HTTP version\r
         switch ($this->request->getConfig('protocol_version')) {\r
-            case '1.0':\r
-                curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);\r
-                break;\r
-            case '1.1':\r
-                curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);\r
+        case '1.0':\r
+            curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);\r
+            break;\r
+        case '1.1':\r
+            curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);\r
         }\r
 \r
         // set request method\r
         switch ($this->request->getMethod()) {\r
-            case HTTP_Request2::METHOD_GET:\r
-                curl_setopt($ch, CURLOPT_HTTPGET, true);\r
-                break;\r
-            case HTTP_Request2::METHOD_POST:\r
-                curl_setopt($ch, CURLOPT_POST, true);\r
-                break;\r
-            case HTTP_Request2::METHOD_HEAD:\r
-                curl_setopt($ch, CURLOPT_NOBODY, true);\r
-                break;\r
-            case HTTP_Request2::METHOD_PUT:\r
-                curl_setopt($ch, CURLOPT_UPLOAD, true);\r
-                break;\r
-            default:\r
-                curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $this->request->getMethod());\r
+        case HTTP_Request2::METHOD_GET:\r
+            curl_setopt($ch, CURLOPT_HTTPGET, true);\r
+            break;\r
+        case HTTP_Request2::METHOD_POST:\r
+            curl_setopt($ch, CURLOPT_POST, true);\r
+            break;\r
+        case HTTP_Request2::METHOD_HEAD:\r
+            curl_setopt($ch, CURLOPT_NOBODY, true);\r
+            break;\r
+        case HTTP_Request2::METHOD_PUT:\r
+            curl_setopt($ch, CURLOPT_UPLOAD, true);\r
+            break;\r
+        default:\r
+            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $this->request->getMethod());\r
         }\r
 \r
         // set proxy, if needed\r
@@ -315,14 +319,30 @@ class HTTP_Request2_Adapter_Curl extends HTTP_Request2_Adapter
             }\r
             curl_setopt($ch, CURLOPT_PROXY, $host . ':' . $port);\r
             if ($user = $this->request->getConfig('proxy_user')) {\r
-                curl_setopt($ch, CURLOPT_PROXYUSERPWD, $user . ':' .\r
-                            $this->request->getConfig('proxy_password'));\r
+                curl_setopt(\r
+                    $ch, CURLOPT_PROXYUSERPWD,\r
+                    $user . ':' . $this->request->getConfig('proxy_password')\r
+                );\r
                 switch ($this->request->getConfig('proxy_auth_scheme')) {\r
-                    case HTTP_Request2::AUTH_BASIC:\r
-                        curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_BASIC);\r
-                        break;\r
-                    case HTTP_Request2::AUTH_DIGEST:\r
-                        curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_DIGEST);\r
+                case HTTP_Request2::AUTH_BASIC:\r
+                    curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_BASIC);\r
+                    break;\r
+                case HTTP_Request2::AUTH_DIGEST:\r
+                    curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_DIGEST);\r
+                }\r
+            }\r
+            if ($type = $this->request->getConfig('proxy_type')) {\r
+                switch ($type) {\r
+                case 'http':\r
+                    curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);\r
+                    break;\r
+                case 'socks5':\r
+                    curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5);\r
+                    break;\r
+                default:\r
+                    throw new HTTP_Request2_NotImplementedException(\r
+                        "Proxy type '{$type}' is not supported"\r
+                    );\r
                 }\r
             }\r
         }\r
@@ -331,11 +351,11 @@ class HTTP_Request2_Adapter_Curl extends HTTP_Request2_Adapter
         if ($auth = $this->request->getAuth()) {\r
             curl_setopt($ch, CURLOPT_USERPWD, $auth['user'] . ':' . $auth['password']);\r
             switch ($auth['scheme']) {\r
-                case HTTP_Request2::AUTH_BASIC:\r
-                    curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);\r
-                    break;\r
-                case HTTP_Request2::AUTH_DIGEST:\r
-                    curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);\r
+            case HTTP_Request2::AUTH_BASIC:\r
+                curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);\r
+                break;\r
+            case HTTP_Request2::AUTH_DIGEST:\r
+                curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);\r
             }\r
         }\r
 \r
@@ -384,16 +404,16 @@ class HTTP_Request2_Adapter_Curl extends HTTP_Request2_Adapter
         return $ch;\r
     }\r
 \r
-   /**\r
-    * Workaround for PHP bug #47204 that prevents rewinding request body\r
-    *\r
-    * The workaround consists of reading the entire request body into memory\r
-    * and setting it as CURLOPT_POSTFIELDS, so it isn't recommended for large\r
-    * file uploads, use Socket adapter instead.\r
-    *\r
-    * @param    resource    cURL handle\r
-    * @param    array       Request headers\r
-    */\r
+    /**\r
+     * Workaround for PHP bug #47204 that prevents rewinding request body\r
+     *\r
+     * The workaround consists of reading the entire request body into memory\r
+     * and setting it as CURLOPT_POSTFIELDS, so it isn't recommended for large\r
+     * file uploads, use Socket adapter instead.\r
+     *\r
+     * @param resource $ch       cURL handle\r
+     * @param array    &$headers Request headers\r
+     */\r
     protected function workaroundPhpBug47204($ch, &$headers)\r
     {\r
         // no redirects, no digest auth -> probably no rewind needed\r
@@ -403,8 +423,8 @@ class HTTP_Request2_Adapter_Curl extends HTTP_Request2_Adapter
         ) {\r
             curl_setopt($ch, CURLOPT_READFUNCTION, array($this, 'callbackReadBody'));\r
 \r
-        // rewind may be needed, read the whole body into memory\r
         } else {\r
+            // rewind may be needed, read the whole body into memory\r
             if ($this->requestBody instanceof HTTP_Request2_MultipartBody) {\r
                 $this->requestBody = $this->requestBody->__toString();\r
 \r
@@ -421,14 +441,15 @@ class HTTP_Request2_Adapter_Curl extends HTTP_Request2_Adapter
         }\r
     }\r
 \r
-   /**\r
-    * Callback function called by cURL for reading the request body\r
-    *\r
-    * @param    resource    cURL handle\r
-    * @param    resource    file descriptor (not used)\r
-    * @param    integer     maximum length of data to return\r
-    * @return   string      part of the request body, up to $length bytes\r
-    */\r
+    /**\r
+     * Callback function called by cURL for reading the request body\r
+     *\r
+     * @param resource $ch     cURL handle\r
+     * @param resource $fd     file descriptor (not used)\r
+     * @param integer  $length maximum length of data to return\r
+     *\r
+     * @return   string      part of the request body, up to $length bytes\r
+     */\r
     protected function callbackReadBody($ch, $fd, $length)\r
     {\r
         if (!$this->eventSentHeaders) {\r
@@ -437,8 +458,8 @@ class HTTP_Request2_Adapter_Curl extends HTTP_Request2_Adapter
             );\r
             $this->eventSentHeaders = true;\r
         }\r
-        if (in_array($this->request->getMethod(), self::$bodyDisallowed) ||\r
-            0 == $this->contentLength || $this->position >= $this->contentLength\r
+        if (in_array($this->request->getMethod(), self::$bodyDisallowed)\r
+            || 0 == $this->contentLength || $this->position >= $this->contentLength\r
         ) {\r
             return '';\r
         }\r
@@ -454,21 +475,22 @@ class HTTP_Request2_Adapter_Curl extends HTTP_Request2_Adapter
         return $string;\r
     }\r
 \r
-   /**\r
-    * Callback function called by cURL for saving the response headers\r
-    *\r
-    * @param    resource    cURL handle\r
-    * @param    string      response header (with trailing CRLF)\r
-    * @return   integer     number of bytes saved\r
-    * @see      HTTP_Request2_Response::parseHeaderLine()\r
-    */\r
+    /**\r
+     * Callback function called by cURL for saving the response headers\r
+     *\r
+     * @param resource $ch     cURL handle\r
+     * @param string   $string response header (with trailing CRLF)\r
+     *\r
+     * @return   integer     number of bytes saved\r
+     * @see      HTTP_Request2_Response::parseHeaderLine()\r
+     */\r
     protected function callbackWriteHeader($ch, $string)\r
     {\r
         // we may receive a second set of headers if doing e.g. digest auth\r
         if ($this->eventReceivedHeaders || !$this->eventSentHeaders) {\r
             // don't bother with 100-Continue responses (bug #15785)\r
-            if (!$this->eventSentHeaders ||\r
-                $this->response->getStatus() >= 200\r
+            if (!$this->eventSentHeaders\r
+                || $this->response->getStatus() >= 200\r
             ) {\r
                 $this->request->setLastEvent(\r
                     'sentHeaders', curl_getinfo($ch, CURLINFO_HEADER_OUT)\r
@@ -532,14 +554,16 @@ class HTTP_Request2_Adapter_Curl extends HTTP_Request2_Adapter
         return strlen($string);\r
     }\r
 \r
-   /**\r
-    * Callback function called by cURL for saving the response body\r
-    *\r
-    * @param    resource    cURL handle (not used)\r
-    * @param    string      part of the response body\r
-    * @return   integer     number of bytes saved\r
-    * @see      HTTP_Request2_Response::appendBody()\r
-    */\r
+    /**\r
+     * Callback function called by cURL for saving the response body\r
+     *\r
+     * @param resource $ch     cURL handle (not used)\r
+     * @param string   $string part of the response body\r
+     *\r
+     * @return   integer     number of bytes saved\r
+     * @throws   HTTP_Request2_MessageException\r
+     * @see      HTTP_Request2_Response::appendBody()\r
+     */\r
     protected function callbackWriteBody($ch, $string)\r
     {\r
         // cURL calls WRITEFUNCTION callback without calling HEADERFUNCTION if\r
index c99defb899dc3a67feaec14803cfeaade3225c06..29d48dbb749af962938815a0ac94aecf7da7cc5d 100644 (file)
@@ -6,7 +6,7 @@
  *\r
  * LICENSE:\r
  *\r
- * Copyright (c) 2008-2011, Alexey Borzov <avb@php.net>\r
+ * Copyright (c) 2008-2012, Alexey Borzov <avb@php.net>\r
  * All rights reserved.\r
  *\r
  * Redistribution and use in source and binary forms, with or without\r
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
  *\r
- * @category   HTTP\r
- * @package    HTTP_Request2\r
- * @author     Alexey Borzov <avb@php.net>\r
- * @license    http://opensource.org/licenses/bsd-license.php New BSD License\r
- * @version    SVN: $Id: Mock.php 308322 2011-02-14 13:58:03Z avb $\r
- * @link       http://pear.php.net/package/HTTP_Request2\r
+ * @category HTTP\r
+ * @package  HTTP_Request2\r
+ * @author   Alexey Borzov <avb@php.net>\r
+ * @license  http://opensource.org/licenses/bsd-license.php New BSD License\r
+ * @version  SVN: $Id: Mock.php 324937 2012-04-07 10:05:57Z avb $\r
+ * @link     http://pear.php.net/package/HTTP_Request2\r
  */\r
 \r
 /**\r
@@ -63,55 +63,71 @@ require_once 'HTTP/Request2/Adapter.php';
  * $response = $req->send();\r
  * </code>\r
  *\r
- * @category   HTTP\r
- * @package    HTTP_Request2\r
- * @author     Alexey Borzov <avb@php.net>\r
- * @version    Release: 2.0.0RC1\r
+ * @category HTTP\r
+ * @package  HTTP_Request2\r
+ * @author   Alexey Borzov <avb@php.net>\r
+ * @license  http://opensource.org/licenses/bsd-license.php New BSD License\r
+ * @version  Release: 2.1.1\r
+ * @link     http://pear.php.net/package/HTTP_Request2\r
  */\r
 class HTTP_Request2_Adapter_Mock extends HTTP_Request2_Adapter\r
 {\r
-   /**\r
-    * A queue of responses to be returned by sendRequest()\r
-    * @var  array\r
-    */\r
+    /**\r
+     * A queue of responses to be returned by sendRequest()\r
+     * @var  array\r
+     */\r
     protected $responses = array();\r
 \r
-   /**\r
-    * Returns the next response from the queue built by addResponse()\r
-    *\r
-    * If the queue is empty it will return default empty response with status 400,\r
-    * if an Exception object was added to the queue it will be thrown.\r
-    *\r
-    * @param    HTTP_Request2\r
-    * @return   HTTP_Request2_Response\r
-    * @throws   Exception\r
-    */\r
+    /**\r
+     * Returns the next response from the queue built by addResponse()\r
+     *\r
+     * Only responses without explicit URLs or with URLs equal to request URL\r
+     * will be considered. If matching response is not found or the queue is\r
+     * empty then default empty response with status 400 will be returned,\r
+     * if an Exception object was added to the queue it will be thrown.\r
+     *\r
+     * @param HTTP_Request2 $request HTTP request message\r
+     *\r
+     * @return   HTTP_Request2_Response\r
+     * @throws   Exception\r
+     */\r
     public function sendRequest(HTTP_Request2 $request)\r
     {\r
-        if (count($this->responses) > 0) {\r
-            $response = array_shift($this->responses);\r
-            if ($response instanceof HTTP_Request2_Response) {\r
-                return $response;\r
-            } else {\r
-                // rethrow the exception\r
-                $class   = get_class($response);\r
-                $message = $response->getMessage();\r
-                $code    = $response->getCode();\r
-                throw new $class($message, $code);\r
+        $requestUrl = (string)$request->getUrl();\r
+        $response   = null;\r
+        foreach ($this->responses as $k => $v) {\r
+            if (!$v[1] || $requestUrl == $v[1]) {\r
+                $response = $v[0];\r
+                array_splice($this->responses, $k, 1);\r
+                break;\r
             }\r
-        } else {\r
+        }\r
+        if (!$response) {\r
             return self::createResponseFromString("HTTP/1.1 400 Bad Request\r\n\r\n");\r
+\r
+        } elseif ($response instanceof HTTP_Request2_Response) {\r
+            return $response;\r
+\r
+        } else {\r
+            // rethrow the exception\r
+            $class   = get_class($response);\r
+            $message = $response->getMessage();\r
+            $code    = $response->getCode();\r
+            throw new $class($message, $code);\r
         }\r
     }\r
 \r
-   /**\r
-    * Adds response to the queue\r
-    *\r
-    * @param    mixed   either a string, a pointer to an open file,\r
-    *                   an instance of HTTP_Request2_Response or Exception\r
-    * @throws   HTTP_Request2_Exception\r
-    */\r
-    public function addResponse($response)\r
+    /**\r
+     * Adds response to the queue\r
+     *\r
+     * @param mixed  $response either a string, a pointer to an open file,\r
+     *                         an instance of HTTP_Request2_Response or Exception\r
+     * @param string $url      A request URL this response should be valid for\r
+     *                         (see {@link http://pear.php.net/bugs/bug.php?id=19276})\r
+     *\r
+     * @throws   HTTP_Request2_Exception\r
+     */\r
+    public function addResponse($response, $url = null)\r
     {\r
         if (is_string($response)) {\r
             $response = self::createResponseFromString($response);\r
@@ -122,16 +138,17 @@ class HTTP_Request2_Adapter_Mock extends HTTP_Request2_Adapter
         ) {\r
             throw new HTTP_Request2_Exception('Parameter is not a valid response');\r
         }\r
-        $this->responses[] = $response;\r
+        $this->responses[] = array($response, $url);\r
     }\r
 \r
-   /**\r
-    * Creates a new HTTP_Request2_Response object from a string\r
-    *\r
-    * @param    string\r
-    * @return   HTTP_Request2_Response\r
-    * @throws   HTTP_Request2_Exception\r
-    */\r
+    /**\r
+     * Creates a new HTTP_Request2_Response object from a string\r
+     *\r
+     * @param string $str string containing HTTP response message\r
+     *\r
+     * @return   HTTP_Request2_Response\r
+     * @throws   HTTP_Request2_Exception\r
+     */\r
     public static function createResponseFromString($str)\r
     {\r
         $parts       = preg_split('!(\r?\n){2}!m', $str, 2);\r
@@ -147,13 +164,14 @@ class HTTP_Request2_Adapter_Mock extends HTTP_Request2_Adapter
         return $response;\r
     }\r
 \r
-   /**\r
-    * Creates a new HTTP_Request2_Response object from a file\r
-    *\r
-    * @param    resource    file pointer returned by fopen()\r
-    * @return   HTTP_Request2_Response\r
-    * @throws   HTTP_Request2_Exception\r
-    */\r
+    /**\r
+     * Creates a new HTTP_Request2_Response object from a file\r
+     *\r
+     * @param resource $fp file pointer returned by fopen()\r
+     *\r
+     * @return   HTTP_Request2_Response\r
+     * @throws   HTTP_Request2_Exception\r
+     */\r
     public static function createResponseFromFile($fp)\r
     {\r
         $response = new HTTP_Request2_Response(fgets($fp));\r
index 05cc4c715bb6b8f83adc502694d49dd3ae5337ef..fb2940a2ee352a8c46125f1b3eb086f66e7d80c6 100644 (file)
@@ -6,7 +6,7 @@
  *\r
  * LICENSE:\r
  *\r
- * Copyright (c) 2008-2011, Alexey Borzov <avb@php.net>\r
+ * Copyright (c) 2008-2012, Alexey Borzov <avb@php.net>\r
  * All rights reserved.\r
  *\r
  * Redistribution and use in source and binary forms, with or without\r
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
  *\r
- * @category   HTTP\r
- * @package    HTTP_Request2\r
- * @author     Alexey Borzov <avb@php.net>\r
- * @license    http://opensource.org/licenses/bsd-license.php New BSD License\r
- * @version    SVN: $Id: Socket.php 309921 2011-04-03 16:43:02Z avb $\r
- * @link       http://pear.php.net/package/HTTP_Request2\r
+ * @category HTTP\r
+ * @package  HTTP_Request2\r
+ * @author   Alexey Borzov <avb@php.net>\r
+ * @license  http://opensource.org/licenses/bsd-license.php New BSD License\r
+ * @version  SVN: $Id: Socket.php 324953 2012-04-08 07:24:12Z avb $\r
+ * @link     http://pear.php.net/package/HTTP_Request2\r
  */\r
 \r
-/**\r
- * Base class for HTTP_Request2 adapters\r
- */\r
+/** Base class for HTTP_Request2 adapters */\r
 require_once 'HTTP/Request2/Adapter.php';\r
 \r
+/** Socket wrapper class */\r
+require_once 'HTTP/Request2/SocketWrapper.php';\r
+\r
 /**\r
  * Socket-based adapter for HTTP_Request2\r
  *\r
  * This adapter uses only PHP sockets and will work on almost any PHP\r
  * environment. Code is based on original HTTP_Request PEAR package.\r
  *\r
- * @category    HTTP\r
- * @package     HTTP_Request2\r
- * @author      Alexey Borzov <avb@php.net>\r
- * @version     Release: 2.0.0RC1\r
+ * @category HTTP\r
+ * @package  HTTP_Request2\r
+ * @author   Alexey Borzov <avb@php.net>\r
+ * @license  http://opensource.org/licenses/bsd-license.php New BSD License\r
+ * @version  Release: 2.1.1\r
+ * @link     http://pear.php.net/package/HTTP_Request2\r
  */\r
 class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter\r
 {\r
-   /**\r
-    * Regular expression for 'token' rule from RFC 2616\r
-    */\r
+    /**\r
+     * Regular expression for 'token' rule from RFC 2616\r
+     */\r
     const REGEXP_TOKEN = '[^\x00-\x1f\x7f-\xff()<>@,;:\\\\"/\[\]?={}\s]+';\r
 \r
-   /**\r
-    * Regular expression for 'quoted-string' rule from RFC 2616\r
-    */\r
+    /**\r
+     * Regular expression for 'quoted-string' rule from RFC 2616\r
+     */\r
     const REGEXP_QUOTED_STRING = '"(?:\\\\.|[^\\\\"])*"';\r
 \r
-   /**\r
-    * Connected sockets, needed for Keep-Alive support\r
-    * @var  array\r
-    * @see  connect()\r
-    */\r
+    /**\r
+     * Connected sockets, needed for Keep-Alive support\r
+     * @var  array\r
+     * @see  connect()\r
+     */\r
     protected static $sockets = array();\r
 \r
-   /**\r
-    * Data for digest authentication scheme\r
-    *\r
-    * The keys for the array are URL prefixes.\r
-    *\r
-    * The values are associative arrays with data (realm, nonce, nonce-count,\r
-    * opaque...) needed for digest authentication. Stored here to prevent making\r
-    * duplicate requests to digest-protected resources after we have already\r
-    * received the challenge.\r
-    *\r
-    * @var  array\r
-    */\r
+    /**\r
+     * Data for digest authentication scheme\r
+     *\r
+     * The keys for the array are URL prefixes.\r
+     *\r
+     * The values are associative arrays with data (realm, nonce, nonce-count,\r
+     * opaque...) needed for digest authentication. Stored here to prevent making\r
+     * duplicate requests to digest-protected resources after we have already\r
+     * received the challenge.\r
+     *\r
+     * @var  array\r
+     */\r
     protected static $challenges = array();\r
 \r
-   /**\r
-    * Connected socket\r
-    * @var  resource\r
-    * @see  connect()\r
-    */\r
+    /**\r
+     * Connected socket\r
+     * @var  HTTP_Request2_SocketWrapper\r
+     * @see  connect()\r
+     */\r
     protected $socket;\r
 \r
-   /**\r
-    * Challenge used for server digest authentication\r
-    * @var  array\r
-    */\r
+    /**\r
+     * Challenge used for server digest authentication\r
+     * @var  array\r
+     */\r
     protected $serverChallenge;\r
 \r
-   /**\r
-    * Challenge used for proxy digest authentication\r
-    * @var  array\r
-    */\r
+    /**\r
+     * Challenge used for proxy digest authentication\r
+     * @var  array\r
+     */\r
     protected $proxyChallenge;\r
 \r
-   /**\r
-    * Sum of start time and global timeout, exception will be thrown if request continues past this time\r
-    * @var  integer\r
-    */\r
-    protected $deadline = null;\r
-\r
-   /**\r
-    * Remaining length of the current chunk, when reading chunked response\r
-    * @var  integer\r
-    * @see  readChunked()\r
-    */\r
+    /**\r
+     * Remaining length of the current chunk, when reading chunked response\r
+     * @var  integer\r
+     * @see  readChunked()\r
+     */\r
     protected $chunkLength = 0;\r
 \r
-   /**\r
-    * Remaining amount of redirections to follow\r
-    *\r
-    * Starts at 'max_redirects' configuration parameter and is reduced on each\r
-    * subsequent redirect. An Exception will be thrown once it reaches zero.\r
-    *\r
-    * @var  integer\r
-    */\r
+    /**\r
+     * Remaining amount of redirections to follow\r
+     *\r
+     * Starts at 'max_redirects' configuration parameter and is reduced on each\r
+     * subsequent redirect. An Exception will be thrown once it reaches zero.\r
+     *\r
+     * @var  integer\r
+     */\r
     protected $redirectCountdown = null;\r
 \r
-   /**\r
-    * Sends request to the remote server and returns its response\r
-    *\r
-    * @param    HTTP_Request2\r
-    * @return   HTTP_Request2_Response\r
-    * @throws   HTTP_Request2_Exception\r
-    */\r
+    /**\r
+     * Sends request to the remote server and returns its response\r
+     *\r
+     * @param HTTP_Request2 $request HTTP request message\r
+     *\r
+     * @return   HTTP_Request2_Response\r
+     * @throws   HTTP_Request2_Exception\r
+     */\r
     public function sendRequest(HTTP_Request2 $request)\r
     {\r
         $this->request = $request;\r
 \r
-        // Use global request timeout if given, see feature requests #5735, #8964\r
-        if ($timeout = $request->getConfig('timeout')) {\r
-            $this->deadline = time() + $timeout;\r
-        } else {\r
-            $this->deadline = null;\r
-        }\r
-\r
         try {\r
             $keepAlive = $this->connect();\r
             $headers   = $this->prepareHeaders();\r
-            if (false === @fwrite($this->socket, $headers, strlen($headers))) {\r
-                throw new HTTP_Request2_MessageException('Error writing request');\r
-            }\r
+            $this->socket->write($headers);\r
             // provide request headers to the observer, see request #7633\r
             $this->request->setLastEvent('sentHeaders', $headers);\r
             $this->writeBody();\r
 \r
-            if ($this->deadline && time() > $this->deadline) {\r
-                throw new HTTP_Request2_MessageException(\r
-                    'Request timed out after ' .\r
-                    $request->getConfig('timeout') . ' second(s)',\r
-                    HTTP_Request2_Exception::TIMEOUT\r
-                );\r
-            }\r
-\r
             $response = $this->readResponse();\r
 \r
             if ($jar = $request->getCookieJar()) {\r
@@ -210,12 +191,12 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
         }\r
     }\r
 \r
-   /**\r
-    * Connects to the remote server\r
-    *\r
-    * @return   bool    whether the connection can be persistent\r
-    * @throws   HTTP_Request2_Exception\r
-    */\r
+    /**\r
+     * Connects to the remote server\r
+     *\r
+     * @return   bool    whether the connection can be persistent\r
+     * @throws   HTTP_Request2_Exception\r
+     */\r
     protected function connect()\r
     {\r
         $secure  = 0 == strcasecmp($this->request->getUrl()->getScheme(), 'https');\r
@@ -226,21 +207,29 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
             $reqPort = $secure? 443: 80;\r
         }\r
 \r
-        if ($host = $this->request->getConfig('proxy_host')) {\r
+        $httpProxy = $socksProxy = false;\r
+        if (!($host = $this->request->getConfig('proxy_host'))) {\r
+            $host = $reqHost;\r
+            $port = $reqPort;\r
+        } else {\r
             if (!($port = $this->request->getConfig('proxy_port'))) {\r
                 throw new HTTP_Request2_LogicException(\r
                     'Proxy port not provided',\r
                     HTTP_Request2_Exception::MISSING_VALUE\r
                 );\r
             }\r
-            $proxy = true;\r
-        } else {\r
-            $host  = $reqHost;\r
-            $port  = $reqPort;\r
-            $proxy = false;\r
+            if ('http' == ($type = $this->request->getConfig('proxy_type'))) {\r
+                $httpProxy = true;\r
+            } elseif ('socks5' == $type) {\r
+                $socksProxy = true;\r
+            } else {\r
+                throw new HTTP_Request2_NotImplementedException(\r
+                    "Proxy type '{$type}' is not supported"\r
+                );\r
+            }\r
         }\r
 \r
-        if ($tunnel && !$proxy) {\r
+        if ($tunnel && !$httpProxy) {\r
             throw new HTTP_Request2_LogicException(\r
                 "Trying to perform CONNECT request without proxy",\r
                 HTTP_Request2_Exception::MISSING_VALUE\r
@@ -255,8 +244,8 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
 \r
         // RFC 2068, section 19.7.1: A client MUST NOT send the Keep-Alive\r
         // connection token to a proxy server...\r
-        if ($proxy && !$secure &&\r
-            !empty($headers['connection']) && 'Keep-Alive' == $headers['connection']\r
+        if ($httpProxy && !$secure && !empty($headers['connection'])\r
+            && 'Keep-Alive' == $headers['connection']\r
         ) {\r
             $this->request->setHeader('connection');\r
         }\r
@@ -265,7 +254,6 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
                       empty($headers['connection'])) ||\r
                      (!empty($headers['connection']) &&\r
                       'Keep-Alive' == $headers['connection']);\r
-        $host = ((!$secure || $proxy)? 'tcp://': 'ssl://') . $host;\r
 \r
         $options = array();\r
         if ($secure || $tunnel) {\r
@@ -283,76 +271,81 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
             ksort($options);\r
         }\r
 \r
+        // Use global request timeout if given, see feature requests #5735, #8964\r
+        if ($timeout = $this->request->getConfig('timeout')) {\r
+            $deadline = time() + $timeout;\r
+        } else {\r
+            $deadline = null;\r
+        }\r
+\r
         // Changing SSL context options after connection is established does *not*\r
         // work, we need a new connection if options change\r
-        $remote    = $host . ':' . $port;\r
-        $socketKey = $remote . (($secure && $proxy)? "->{$reqHost}:{$reqPort}": '') .\r
-                     (empty($options)? '': ':' . serialize($options));\r
+        $remote    = ((!$secure || $httpProxy || $socksProxy)? 'tcp://': 'ssl://')\r
+                     . $host . ':' . $port;\r
+        $socketKey = $remote . (\r
+                        ($secure && $httpProxy || $socksProxy)\r
+                        ? "->{$reqHost}:{$reqPort}" : ''\r
+                     ) . (empty($options)? '': ':' . serialize($options));\r
         unset($this->socket);\r
 \r
         // We use persistent connections and have a connected socket?\r
         // Ensure that the socket is still connected, see bug #16149\r
-        if ($keepAlive && !empty(self::$sockets[$socketKey]) &&\r
-            !feof(self::$sockets[$socketKey])\r
+        if ($keepAlive && !empty(self::$sockets[$socketKey])\r
+            && !self::$sockets[$socketKey]->eof()\r
         ) {\r
             $this->socket =& self::$sockets[$socketKey];\r
 \r
-        } elseif ($secure && $proxy && !$tunnel) {\r
-            $this->establishTunnel();\r
-            $this->request->setLastEvent(\r
-                'connect', "ssl://{$reqHost}:{$reqPort} via {$host}:{$port}"\r
-            );\r
-            self::$sockets[$socketKey] =& $this->socket;\r
-\r
         } else {\r
-            // Set SSL context options if doing HTTPS request or creating a tunnel\r
-            $context = stream_context_create();\r
-            foreach ($options as $name => $value) {\r
-                if (!stream_context_set_option($context, 'ssl', $name, $value)) {\r
-                    throw new HTTP_Request2_LogicException(\r
-                        "Error setting SSL context option '{$name}'"\r
-                    );\r
+            if ($socksProxy) {\r
+                require_once 'HTTP/Request2/SOCKS5.php';\r
+\r
+                $this->socket = new HTTP_Request2_SOCKS5(\r
+                    $remote, $this->request->getConfig('connect_timeout'),\r
+                    $options, $this->request->getConfig('proxy_user'),\r
+                    $this->request->getConfig('proxy_password')\r
+                );\r
+                // handle request timeouts ASAP\r
+                $this->socket->setDeadline($deadline, $this->request->getConfig('timeout'));\r
+                $this->socket->connect($reqHost, $reqPort);\r
+                if (!$secure) {\r
+                    $conninfo = "tcp://{$reqHost}:{$reqPort} via {$remote}";\r
+                } else {\r
+                    $this->socket->enableCrypto();\r
+                    $conninfo = "ssl://{$reqHost}:{$reqPort} via {$remote}";\r
                 }\r
-            }\r
-            $track = @ini_set('track_errors', 1);\r
-            $this->socket = @stream_socket_client(\r
-                $remote, $errno, $errstr,\r
-                $this->request->getConfig('connect_timeout'),\r
-                STREAM_CLIENT_CONNECT, $context\r
-            );\r
-            if (!$this->socket) {\r
-                $e = new HTTP_Request2_ConnectionException(\r
-                    "Unable to connect to {$remote}. Error: "\r
-                     . (empty($errstr)? $php_errormsg: $errstr), 0, $errno\r
+\r
+            } elseif ($secure && $httpProxy && !$tunnel) {\r
+                $this->establishTunnel();\r
+                $conninfo = "ssl://{$reqHost}:{$reqPort} via {$remote}";\r
+\r
+            } else {\r
+                $this->socket = new HTTP_Request2_SocketWrapper(\r
+                    $remote, $this->request->getConfig('connect_timeout'), $options\r
                 );\r
             }\r
-            @ini_set('track_errors', $track);\r
-            if (isset($e)) {\r
-                throw $e;\r
-            }\r
-            $this->request->setLastEvent('connect', $remote);\r
+            $this->request->setLastEvent('connect', empty($conninfo)? $remote: $conninfo);\r
             self::$sockets[$socketKey] =& $this->socket;\r
         }\r
+        $this->socket->setDeadline($deadline, $this->request->getConfig('timeout'));\r
         return $keepAlive;\r
     }\r
 \r
-   /**\r
-    * Establishes a tunnel to a secure remote server via HTTP CONNECT request\r
-    *\r
-    * This method will fail if 'ssl_verify_peer' is enabled. Probably because PHP\r
-    * sees that we are connected to a proxy server (duh!) rather than the server\r
-    * that presents its certificate.\r
-    *\r
-    * @link     http://tools.ietf.org/html/rfc2817#section-5.2\r
-    * @throws   HTTP_Request2_Exception\r
-    */\r
+    /**\r
+     * Establishes a tunnel to a secure remote server via HTTP CONNECT request\r
+     *\r
+     * This method will fail if 'ssl_verify_peer' is enabled. Probably because PHP\r
+     * sees that we are connected to a proxy server (duh!) rather than the server\r
+     * that presents its certificate.\r
+     *\r
+     * @link     http://tools.ietf.org/html/rfc2817#section-5.2\r
+     * @throws   HTTP_Request2_Exception\r
+     */\r
     protected function establishTunnel()\r
     {\r
         $donor   = new self;\r
         $connect = new HTTP_Request2(\r
             $this->request->getUrl(), HTTP_Request2::METHOD_CONNECT,\r
-            array_merge($this->request->getConfig(),\r
-                        array('adapter' => $donor))\r
+            array_merge($this->request->getConfig(), array('adapter' => $donor))\r
         );\r
         $response = $connect->send();\r
         // Need any successful (2XX) response\r
@@ -363,37 +356,23 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
             );\r
         }\r
         $this->socket = $donor->socket;\r
-\r
-        $modes = array(\r
-            STREAM_CRYPTO_METHOD_TLS_CLIENT,\r
-            STREAM_CRYPTO_METHOD_SSLv3_CLIENT,\r
-            STREAM_CRYPTO_METHOD_SSLv23_CLIENT,\r
-            STREAM_CRYPTO_METHOD_SSLv2_CLIENT\r
-        );\r
-\r
-        foreach ($modes as $mode) {\r
-            if (stream_socket_enable_crypto($this->socket, true, $mode)) {\r
-                return;\r
-            }\r
-        }\r
-        throw new HTTP_Request2_ConnectionException(\r
-            'Failed to enable secure connection when connecting through proxy'\r
-        );\r
+        $this->socket->enableCrypto();\r
     }\r
 \r
-   /**\r
-    * Checks whether current connection may be reused or should be closed\r
-    *\r
-    * @param    boolean                 whether connection could be persistent\r
-    *                                   in the first place\r
-    * @param    HTTP_Request2_Response  response object to check\r
-    * @return   boolean\r
-    */\r
+    /**\r
+     * Checks whether current connection may be reused or should be closed\r
+     *\r
+     * @param boolean                $requestKeepAlive whether connection could\r
+     *                               be persistent in the first place\r
+     * @param HTTP_Request2_Response $response         response object to check\r
+     *\r
+     * @return   boolean\r
+     */\r
     protected function canKeepAlive($requestKeepAlive, HTTP_Request2_Response $response)\r
     {\r
         // Do not close socket on successful CONNECT request\r
-        if (HTTP_Request2::METHOD_CONNECT == $this->request->getMethod() &&\r
-            200 <= $response->getStatus() && 300 > $response->getStatus()\r
+        if (HTTP_Request2::METHOD_CONNECT == $this->request->getMethod()\r
+            && 200 <= $response->getStatus() && 300 > $response->getStatus()\r
         ) {\r
             return true;\r
         }\r
@@ -409,40 +388,40 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
         return $requestKeepAlive && $lengthKnown && $persistent;\r
     }\r
 \r
-   /**\r
-    * Disconnects from the remote server\r
-    */\r
+    /**\r
+     * Disconnects from the remote server\r
+     */\r
     protected function disconnect()\r
     {\r
-        if (is_resource($this->socket)) {\r
-            fclose($this->socket);\r
+        if (!empty($this->socket)) {\r
             $this->socket = null;\r
             $this->request->setLastEvent('disconnect');\r
         }\r
     }\r
 \r
-   /**\r
-    * Handles HTTP redirection\r
-    *\r
-    * This method will throw an Exception if redirect to a non-HTTP(S) location\r
-    * is attempted, also if number of redirects performed already is equal to\r
-    * 'max_redirects' configuration parameter.\r
-    *\r
-    * @param    HTTP_Request2               Original request\r
-    * @param    HTTP_Request2_Response      Response containing redirect\r
-    * @return   HTTP_Request2_Response      Response from a new location\r
-    * @throws   HTTP_Request2_Exception\r
-    */\r
-    protected function handleRedirect(HTTP_Request2 $request,\r
-                                      HTTP_Request2_Response $response)\r
-    {\r
+    /**\r
+     * Handles HTTP redirection\r
+     *\r
+     * This method will throw an Exception if redirect to a non-HTTP(S) location\r
+     * is attempted, also if number of redirects performed already is equal to\r
+     * 'max_redirects' configuration parameter.\r
+     *\r
+     * @param HTTP_Request2          $request  Original request\r
+     * @param HTTP_Request2_Response $response Response containing redirect\r
+     *\r
+     * @return   HTTP_Request2_Response      Response from a new location\r
+     * @throws   HTTP_Request2_Exception\r
+     */\r
+    protected function handleRedirect(\r
+        HTTP_Request2 $request, HTTP_Request2_Response $response\r
+    ) {\r
         if (is_null($this->redirectCountdown)) {\r
             $this->redirectCountdown = $request->getConfig('max_redirects');\r
         }\r
         if (0 == $this->redirectCountdown) {\r
             $this->redirectCountdown = null;\r
             // Copying cURL behaviour\r
-            throw new HTTP_Request2_MessageException (\r
+            throw new HTTP_Request2_MessageException(\r
                 'Maximum (' . $request->getConfig('max_redirects') . ') redirects followed',\r
                 HTTP_Request2_Exception::TOO_MANY_REDIRECTS\r
             );\r
@@ -468,8 +447,9 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
         }\r
         $redirect = clone $request;\r
         $redirect->setUrl($redirectUrl);\r
-        if (303 == $response->getStatus() || (!$request->getConfig('strict_redirects')\r
-             && in_array($response->getStatus(), array(301, 302)))\r
+        if (303 == $response->getStatus()\r
+            || (!$request->getConfig('strict_redirects')\r
+                && in_array($response->getStatus(), array(301, 302)))\r
         ) {\r
             $redirect->setMethod(HTTP_Request2::METHOD_GET);\r
             $redirect->setBody('');\r
@@ -481,23 +461,24 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
         return $this->sendRequest($redirect);\r
     }\r
 \r
-   /**\r
-    * Checks whether another request should be performed with server digest auth\r
-    *\r
-    * Several conditions should be satisfied for it to return true:\r
-    *   - response status should be 401\r
-    *   - auth credentials should be set in the request object\r
-    *   - response should contain WWW-Authenticate header with digest challenge\r
-    *   - there is either no challenge stored for this URL or new challenge\r
-    *     contains stale=true parameter (in other case we probably just failed\r
-    *     due to invalid username / password)\r
-    *\r
-    * The method stores challenge values in $challenges static property\r
-    *\r
-    * @param    HTTP_Request2_Response  response to check\r
-    * @return   boolean whether another request should be performed\r
-    * @throws   HTTP_Request2_Exception in case of unsupported challenge parameters\r
-    */\r
+    /**\r
+     * Checks whether another request should be performed with server digest auth\r
+     *\r
+     * Several conditions should be satisfied for it to return true:\r
+     *   - response status should be 401\r
+     *   - auth credentials should be set in the request object\r
+     *   - response should contain WWW-Authenticate header with digest challenge\r
+     *   - there is either no challenge stored for this URL or new challenge\r
+     *     contains stale=true parameter (in other case we probably just failed\r
+     *     due to invalid username / password)\r
+     *\r
+     * The method stores challenge values in $challenges static property\r
+     *\r
+     * @param HTTP_Request2_Response $response response to check\r
+     *\r
+     * @return   boolean whether another request should be performed\r
+     * @throws   HTTP_Request2_Exception in case of unsupported challenge parameters\r
+     */\r
     protected function shouldUseServerDigestAuth(HTTP_Request2_Response $response)\r
     {\r
         // no sense repeating a request if we don't have credentials\r
@@ -512,8 +493,8 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
         $scheme = $url->getScheme();\r
         $host   = $scheme . '://' . $url->getHost();\r
         if ($port = $url->getPort()) {\r
-            if ((0 == strcasecmp($scheme, 'http') && 80 != $port) ||\r
-                (0 == strcasecmp($scheme, 'https') && 443 != $port)\r
+            if ((0 == strcasecmp($scheme, 'http') && 80 != $port)\r
+                || (0 == strcasecmp($scheme, 'https') && 443 != $port)\r
             ) {\r
                 $host .= ':' . $port;\r
             }\r
@@ -534,8 +515,8 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
 \r
         $ret = true;\r
         foreach ($prefixes as $prefix) {\r
-            if (!empty(self::$challenges[$prefix]) &&\r
-                (empty($challenge['stale']) || strcasecmp('true', $challenge['stale']))\r
+            if (!empty(self::$challenges[$prefix])\r
+                && (empty($challenge['stale']) || strcasecmp('true', $challenge['stale']))\r
             ) {\r
                 // probably credentials are invalid\r
                 $ret = false;\r
@@ -545,23 +526,24 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
         return $ret;\r
     }\r
 \r
-   /**\r
-    * Checks whether another request should be performed with proxy digest auth\r
-    *\r
-    * Several conditions should be satisfied for it to return true:\r
-    *   - response status should be 407\r
-    *   - proxy auth credentials should be set in the request object\r
-    *   - response should contain Proxy-Authenticate header with digest challenge\r
-    *   - there is either no challenge stored for this proxy or new challenge\r
-    *     contains stale=true parameter (in other case we probably just failed\r
-    *     due to invalid username / password)\r
-    *\r
-    * The method stores challenge values in $challenges static property\r
-    *\r
-    * @param    HTTP_Request2_Response  response to check\r
-    * @return   boolean whether another request should be performed\r
-    * @throws   HTTP_Request2_Exception in case of unsupported challenge parameters\r
-    */\r
+    /**\r
+     * Checks whether another request should be performed with proxy digest auth\r
+     *\r
+     * Several conditions should be satisfied for it to return true:\r
+     *   - response status should be 407\r
+     *   - proxy auth credentials should be set in the request object\r
+     *   - response should contain Proxy-Authenticate header with digest challenge\r
+     *   - there is either no challenge stored for this proxy or new challenge\r
+     *     contains stale=true parameter (in other case we probably just failed\r
+     *     due to invalid username / password)\r
+     *\r
+     * The method stores challenge values in $challenges static property\r
+     *\r
+     * @param HTTP_Request2_Response $response response to check\r
+     *\r
+     * @return   boolean whether another request should be performed\r
+     * @throws   HTTP_Request2_Exception in case of unsupported challenge parameters\r
+     */\r
     protected function shouldUseProxyDigestAuth(HTTP_Request2_Response $response)\r
     {\r
         if (407 != $response->getStatus() || !$this->request->getConfig('proxy_user')) {\r
@@ -574,8 +556,8 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
         $key = 'proxy://' . $this->request->getConfig('proxy_host') .\r
                ':' . $this->request->getConfig('proxy_port');\r
 \r
-        if (!empty(self::$challenges[$key]) &&\r
-            (empty($challenge['stale']) || strcasecmp('true', $challenge['stale']))\r
+        if (!empty(self::$challenges[$key])\r
+            && (empty($challenge['stale']) || strcasecmp('true', $challenge['stale']))\r
         ) {\r
             $ret = false;\r
         } else {\r
@@ -585,34 +567,35 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
         return $ret;\r
     }\r
 \r
-   /**\r
-    * Extracts digest method challenge from (WWW|Proxy)-Authenticate header value\r
-    *\r
-    * There is a problem with implementation of RFC 2617: several of the parameters\r
-    * are defined as quoted-string there and thus may contain backslash escaped\r
-    * double quotes (RFC 2616, section 2.2). However, RFC 2617 defines unq(X) as\r
-    * just value of quoted-string X without surrounding quotes, it doesn't speak\r
-    * about removing backslash escaping.\r
-    *\r
-    * Now realm parameter is user-defined and human-readable, strange things\r
-    * happen when it contains quotes:\r
-    *   - Apache allows quotes in realm, but apparently uses realm value without\r
-    *     backslashes for digest computation\r
-    *   - Squid allows (manually escaped) quotes there, but it is impossible to\r
-    *     authorize with either escaped or unescaped quotes used in digest,\r
-    *     probably it can't parse the response (?)\r
-    *   - Both IE and Firefox display realm value with backslashes in\r
-    *     the password popup and apparently use the same value for digest\r
-    *\r
-    * HTTP_Request2 follows IE and Firefox (and hopefully RFC 2617) in\r
-    * quoted-string handling, unfortunately that means failure to authorize\r
-    * sometimes\r
-    *\r
-    * @param    string  value of WWW-Authenticate or Proxy-Authenticate header\r
-    * @return   mixed   associative array with challenge parameters, false if\r
-    *                   no challenge is present in header value\r
-    * @throws   HTTP_Request2_NotImplementedException in case of unsupported challenge parameters\r
-    */\r
+    /**\r
+     * Extracts digest method challenge from (WWW|Proxy)-Authenticate header value\r
+     *\r
+     * There is a problem with implementation of RFC 2617: several of the parameters\r
+     * are defined as quoted-string there and thus may contain backslash escaped\r
+     * double quotes (RFC 2616, section 2.2). However, RFC 2617 defines unq(X) as\r
+     * just value of quoted-string X without surrounding quotes, it doesn't speak\r
+     * about removing backslash escaping.\r
+     *\r
+     * Now realm parameter is user-defined and human-readable, strange things\r
+     * happen when it contains quotes:\r
+     *   - Apache allows quotes in realm, but apparently uses realm value without\r
+     *     backslashes for digest computation\r
+     *   - Squid allows (manually escaped) quotes there, but it is impossible to\r
+     *     authorize with either escaped or unescaped quotes used in digest,\r
+     *     probably it can't parse the response (?)\r
+     *   - Both IE and Firefox display realm value with backslashes in\r
+     *     the password popup and apparently use the same value for digest\r
+     *\r
+     * HTTP_Request2 follows IE and Firefox (and hopefully RFC 2617) in\r
+     * quoted-string handling, unfortunately that means failure to authorize\r
+     * sometimes\r
+     *\r
+     * @param string $headerValue value of WWW-Authenticate or Proxy-Authenticate header\r
+     *\r
+     * @return   mixed   associative array with challenge parameters, false if\r
+     *                   no challenge is present in header value\r
+     * @throws   HTTP_Request2_NotImplementedException in case of unsupported challenge parameters\r
+     */\r
     protected function parseDigestChallenge($headerValue)\r
     {\r
         $authParam   = '(' . self::REGEXP_TOKEN . ')\\s*=\\s*(' .\r
@@ -637,8 +620,8 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
             }\r
         }\r
         // we only support qop=auth\r
-        if (!empty($paramsAry['qop']) &&\r
-            !in_array('auth', array_map('trim', explode(',', $paramsAry['qop'])))\r
+        if (!empty($paramsAry['qop'])\r
+            && !in_array('auth', array_map('trim', explode(',', $paramsAry['qop'])))\r
         ) {\r
             throw new HTTP_Request2_NotImplementedException(\r
                 "Only 'auth' qop is currently supported in digest authentication, " .\r
@@ -656,13 +639,14 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
         return $paramsAry;\r
     }\r
 \r
-   /**\r
-    * Parses [Proxy-]Authentication-Info header value and updates challenge\r
-    *\r
-    * @param    array   challenge to update\r
-    * @param    string  value of [Proxy-]Authentication-Info header\r
-    * @todo     validate server rspauth response\r
-    */\r
+    /**\r
+     * Parses [Proxy-]Authentication-Info header value and updates challenge\r
+     *\r
+     * @param array  &$challenge  challenge to update\r
+     * @param string $headerValue value of [Proxy-]Authentication-Info header\r
+     *\r
+     * @todo     validate server rspauth response\r
+     */\r
     protected function updateChallenge(&$challenge, $headerValue)\r
     {\r
         $authParam   = '!(' . self::REGEXP_TOKEN . ')\\s*=\\s*(' .\r
@@ -684,20 +668,21 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
         }\r
     }\r
 \r
-   /**\r
-    * Creates a value for [Proxy-]Authorization header when using digest authentication\r
-    *\r
-    * @param    string  user name\r
-    * @param    string  password\r
-    * @param    string  request URL\r
-    * @param    array   digest challenge parameters\r
-    * @return   string  value of [Proxy-]Authorization request header\r
-    * @link     http://tools.ietf.org/html/rfc2617#section-3.2.2\r
-    */\r
+    /**\r
+     * Creates a value for [Proxy-]Authorization header when using digest authentication\r
+     *\r
+     * @param string $user       user name\r
+     * @param string $password   password\r
+     * @param string $url        request URL\r
+     * @param array  &$challenge digest challenge parameters\r
+     *\r
+     * @return   string  value of [Proxy-]Authorization request header\r
+     * @link     http://tools.ietf.org/html/rfc2617#section-3.2.2\r
+     */\r
     protected function createDigestResponse($user, $password, $url, &$challenge)\r
     {\r
-        if (false !== ($q = strpos($url, '?')) &&\r
-            $this->request->getConfig('digest_compat_ie')\r
+        if (false !== ($q = strpos($url, '?'))\r
+            && $this->request->getConfig('digest_compat_ie')\r
         ) {\r
             $url = substr($url, 0, $q);\r
         }\r
@@ -713,8 +698,10 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
                 $challenge['nc'] = 1;\r
             }\r
             $nc     = sprintf('%08x', $challenge['nc']++);\r
-            $digest = md5($a1 . ':' . $challenge['nonce'] . ':' . $nc . ':' .\r
-                          $challenge['cnonce'] . ':auth:' . $a2);\r
+            $digest = md5(\r
+                $a1 . ':' . $challenge['nonce'] . ':' . $nc . ':' .\r
+                $challenge['cnonce'] . ':auth:' . $a2\r
+            );\r
         }\r
         return 'Digest username="' . str_replace(array('\\', '"'), array('\\\\', '\\"'), $user) . '", ' .\r
                'realm="' . $challenge['realm'] . '", ' .\r
@@ -729,102 +716,106 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
                 '');\r
     }\r
 \r
-   /**\r
-    * Adds 'Authorization' header (if needed) to request headers array\r
-    *\r
-    * @param    array   request headers\r
-    * @param    string  request host (needed for digest authentication)\r
-    * @param    string  request URL (needed for digest authentication)\r
-    * @throws   HTTP_Request2_NotImplementedException\r
-    */\r
+    /**\r
+     * Adds 'Authorization' header (if needed) to request headers array\r
+     *\r
+     * @param array  &$headers    request headers\r
+     * @param string $requestHost request host (needed for digest authentication)\r
+     * @param string $requestUrl  request URL (needed for digest authentication)\r
+     *\r
+     * @throws   HTTP_Request2_NotImplementedException\r
+     */\r
     protected function addAuthorizationHeader(&$headers, $requestHost, $requestUrl)\r
     {\r
         if (!($auth = $this->request->getAuth())) {\r
             return;\r
         }\r
         switch ($auth['scheme']) {\r
-            case HTTP_Request2::AUTH_BASIC:\r
-                $headers['authorization'] =\r
-                    'Basic ' . base64_encode($auth['user'] . ':' . $auth['password']);\r
-                break;\r
-\r
-            case HTTP_Request2::AUTH_DIGEST:\r
-                unset($this->serverChallenge);\r
-                $fullUrl = ('/' == $requestUrl[0])?\r
-                           $this->request->getUrl()->getScheme() . '://' .\r
-                            $requestHost . $requestUrl:\r
-                           $requestUrl;\r
-                foreach (array_keys(self::$challenges) as $key) {\r
-                    if ($key == substr($fullUrl, 0, strlen($key))) {\r
-                        $headers['authorization'] = $this->createDigestResponse(\r
-                            $auth['user'], $auth['password'],\r
-                            $requestUrl, self::$challenges[$key]\r
-                        );\r
-                        $this->serverChallenge =& self::$challenges[$key];\r
-                        break;\r
-                    }\r
+        case HTTP_Request2::AUTH_BASIC:\r
+            $headers['authorization'] = 'Basic ' . base64_encode(\r
+                $auth['user'] . ':' . $auth['password']\r
+            );\r
+            break;\r
+\r
+        case HTTP_Request2::AUTH_DIGEST:\r
+            unset($this->serverChallenge);\r
+            $fullUrl = ('/' == $requestUrl[0])?\r
+                       $this->request->getUrl()->getScheme() . '://' .\r
+                        $requestHost . $requestUrl:\r
+                       $requestUrl;\r
+            foreach (array_keys(self::$challenges) as $key) {\r
+                if ($key == substr($fullUrl, 0, strlen($key))) {\r
+                    $headers['authorization'] = $this->createDigestResponse(\r
+                        $auth['user'], $auth['password'],\r
+                        $requestUrl, self::$challenges[$key]\r
+                    );\r
+                    $this->serverChallenge =& self::$challenges[$key];\r
+                    break;\r
                 }\r
-                break;\r
+            }\r
+            break;\r
 \r
-            default:\r
-                throw new HTTP_Request2_NotImplementedException(\r
-                    "Unknown HTTP authentication scheme '{$auth['scheme']}'"\r
-                );\r
+        default:\r
+            throw new HTTP_Request2_NotImplementedException(\r
+                "Unknown HTTP authentication scheme '{$auth['scheme']}'"\r
+            );\r
         }\r
     }\r
 \r
-   /**\r
-    * Adds 'Proxy-Authorization' header (if needed) to request headers array\r
-    *\r
-    * @param    array   request headers\r
-    * @param    string  request URL (needed for digest authentication)\r
-    * @throws   HTTP_Request2_NotImplementedException\r
-    */\r
+    /**\r
+     * Adds 'Proxy-Authorization' header (if needed) to request headers array\r
+     *\r
+     * @param array  &$headers   request headers\r
+     * @param string $requestUrl request URL (needed for digest authentication)\r
+     *\r
+     * @throws   HTTP_Request2_NotImplementedException\r
+     */\r
     protected function addProxyAuthorizationHeader(&$headers, $requestUrl)\r
     {\r
-        if (!$this->request->getConfig('proxy_host') ||\r
-            !($user = $this->request->getConfig('proxy_user')) ||\r
-            (0 == strcasecmp('https', $this->request->getUrl()->getScheme()) &&\r
-             HTTP_Request2::METHOD_CONNECT != $this->request->getMethod())\r
+        if (!$this->request->getConfig('proxy_host')\r
+            || !($user = $this->request->getConfig('proxy_user'))\r
+            || (0 == strcasecmp('https', $this->request->getUrl()->getScheme())\r
+                && HTTP_Request2::METHOD_CONNECT != $this->request->getMethod())\r
         ) {\r
             return;\r
         }\r
 \r
         $password = $this->request->getConfig('proxy_password');\r
         switch ($this->request->getConfig('proxy_auth_scheme')) {\r
-            case HTTP_Request2::AUTH_BASIC:\r
-                $headers['proxy-authorization'] =\r
-                    'Basic ' . base64_encode($user . ':' . $password);\r
-                break;\r
-\r
-            case HTTP_Request2::AUTH_DIGEST:\r
-                unset($this->proxyChallenge);\r
-                $proxyUrl = 'proxy://' . $this->request->getConfig('proxy_host') .\r
-                            ':' . $this->request->getConfig('proxy_port');\r
-                if (!empty(self::$challenges[$proxyUrl])) {\r
-                    $headers['proxy-authorization'] = $this->createDigestResponse(\r
-                        $user, $password,\r
-                        $requestUrl, self::$challenges[$proxyUrl]\r
-                    );\r
-                    $this->proxyChallenge =& self::$challenges[$proxyUrl];\r
-                }\r
-                break;\r
-\r
-            default:\r
-                throw new HTTP_Request2_NotImplementedException(\r
-                    "Unknown HTTP authentication scheme '" .\r
-                    $this->request->getConfig('proxy_auth_scheme') . "'"\r
+        case HTTP_Request2::AUTH_BASIC:\r
+            $headers['proxy-authorization'] = 'Basic ' . base64_encode(\r
+                $user . ':' . $password\r
+            );\r
+            break;\r
+\r
+        case HTTP_Request2::AUTH_DIGEST:\r
+            unset($this->proxyChallenge);\r
+            $proxyUrl = 'proxy://' . $this->request->getConfig('proxy_host') .\r
+                        ':' . $this->request->getConfig('proxy_port');\r
+            if (!empty(self::$challenges[$proxyUrl])) {\r
+                $headers['proxy-authorization'] = $this->createDigestResponse(\r
+                    $user, $password,\r
+                    $requestUrl, self::$challenges[$proxyUrl]\r
                 );\r
+                $this->proxyChallenge =& self::$challenges[$proxyUrl];\r
+            }\r
+            break;\r
+\r
+        default:\r
+            throw new HTTP_Request2_NotImplementedException(\r
+                "Unknown HTTP authentication scheme '" .\r
+                $this->request->getConfig('proxy_auth_scheme') . "'"\r
+            );\r
         }\r
     }\r
 \r
 \r
-   /**\r
-    * Creates the string with the Request-Line and request headers\r
-    *\r
-    * @return   string\r
-    * @throws   HTTP_Request2_Exception\r
-    */\r
+    /**\r
+     * Creates the string with the Request-Line and request headers\r
+     *\r
+     * @return   string\r
+     * @throws   HTTP_Request2_Exception\r
+     */\r
     protected function prepareHeaders()\r
     {\r
         $headers = $this->request->getHeaders();\r
@@ -845,8 +836,9 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
             $requestUrl = $host;\r
 \r
         } else {\r
-            if (!$this->request->getConfig('proxy_host') ||\r
-                0 == strcasecmp($url->getScheme(), 'https')\r
+            if (!$this->request->getConfig('proxy_host')\r
+                || 'http' != $this->request->getConfig('proxy_type')\r
+                || 0 == strcasecmp($url->getScheme(), 'https')\r
             ) {\r
                 $requestUrl = '';\r
             } else {\r
@@ -857,8 +849,8 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
             $requestUrl .= (empty($path)? '/': $path) . (empty($query)? '': '?' . $query);\r
         }\r
 \r
-        if ('1.1' == $this->request->getConfig('protocol_version') &&\r
-            extension_loaded('zlib') && !isset($headers['accept-encoding'])\r
+        if ('1.1' == $this->request->getConfig('protocol_version')\r
+            && extension_loaded('zlib') && !isset($headers['accept-encoding'])\r
         ) {\r
             $headers['accept-encoding'] = 'gzip, deflate';\r
         }\r
@@ -881,15 +873,15 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
         return $headersStr . "\r\n";\r
     }\r
 \r
-   /**\r
-    * Sends the request body\r
-    *\r
-    * @throws   HTTP_Request2_MessageException\r
-    */\r
+    /**\r
+     * Sends the request body\r
+     *\r
+     * @throws   HTTP_Request2_MessageException\r
+     */\r
     protected function writeBody()\r
     {\r
-        if (in_array($this->request->getMethod(), self::$bodyDisallowed) ||\r
-            0 == $this->contentLength\r
+        if (in_array($this->request->getMethod(), self::$bodyDisallowed)\r
+            || 0 == $this->contentLength\r
         ) {\r
             return;\r
         }\r
@@ -904,9 +896,7 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
             } else {\r
                 $str = $this->requestBody->read($bufferSize);\r
             }\r
-            if (false === @fwrite($this->socket, $str, strlen($str))) {\r
-                throw new HTTP_Request2_MessageException('Error writing request');\r
-            }\r
+            $this->socket->write($str);\r
             // Provide the length of written string to the observer, request #7630\r
             $this->request->setLastEvent('sentBodyPart', strlen($str));\r
             $position += strlen($str);\r
@@ -914,22 +904,22 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
         $this->request->setLastEvent('sentBody', $this->contentLength);\r
     }\r
 \r
-   /**\r
-    * Reads the remote server's response\r
-    *\r
-    * @return   HTTP_Request2_Response\r
-    * @throws   HTTP_Request2_Exception\r
-    */\r
+    /**\r
+     * Reads the remote server's response\r
+     *\r
+     * @return   HTTP_Request2_Response\r
+     * @throws   HTTP_Request2_Exception\r
+     */\r
     protected function readResponse()\r
     {\r
         $bufferSize = $this->request->getConfig('buffer_size');\r
 \r
         do {\r
             $response = new HTTP_Request2_Response(\r
-                $this->readLine($bufferSize), true, $this->request->getUrl()\r
+                $this->socket->readLine($bufferSize), true, $this->request->getUrl()\r
             );\r
             do {\r
-                $headerLine = $this->readLine($bufferSize);\r
+                $headerLine = $this->socket->readLine($bufferSize);\r
                 $response->parseHeaderLine($headerLine);\r
             } while ('' != $headerLine);\r
         } while (in_array($response->getStatus(), array(100, 101)));\r
@@ -937,10 +927,10 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
         $this->request->setLastEvent('receivedHeaders', $response);\r
 \r
         // No body possible in such responses\r
-        if (HTTP_Request2::METHOD_HEAD == $this->request->getMethod() ||\r
-            (HTTP_Request2::METHOD_CONNECT == $this->request->getMethod() &&\r
-             200 <= $response->getStatus() && 300 > $response->getStatus()) ||\r
-            in_array($response->getStatus(), array(204, 304))\r
+        if (HTTP_Request2::METHOD_HEAD == $this->request->getMethod()\r
+            || (HTTP_Request2::METHOD_CONNECT == $this->request->getMethod()\r
+                && 200 <= $response->getStatus() && 300 > $response->getStatus())\r
+            || in_array($response->getStatus(), array(204, 304))\r
         ) {\r
             return $response;\r
         }\r
@@ -956,16 +946,16 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
             $toRead = ($chunked || null === $length)? null: $length;\r
             $this->chunkLength = 0;\r
 \r
-            while (!feof($this->socket) && (is_null($toRead) || 0 < $toRead)) {\r
+            while (!$this->socket->eof() && (is_null($toRead) || 0 < $toRead)) {\r
                 if ($chunked) {\r
                     $data = $this->readChunked($bufferSize);\r
                 } elseif (is_null($toRead)) {\r
-                    $data = $this->fread($bufferSize);\r
+                    $data = $this->socket->read($bufferSize);\r
                 } else {\r
-                    $data    = $this->fread(min($toRead, $bufferSize));\r
+                    $data    = $this->socket->read(min($toRead, $bufferSize));\r
                     $toRead -= strlen($data);\r
                 }\r
-                if ('' == $data && (!$this->chunkLength || feof($this->socket))) {\r
+                if ('' == $data && (!$this->chunkLength || $this->socket->eof())) {\r
                     break;\r
                 }\r
 \r
@@ -987,77 +977,19 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
         return $response;\r
     }\r
 \r
-   /**\r
-    * Reads until either the end of the socket or a newline, whichever comes first\r
-    *\r
-    * Strips the trailing newline from the returned data, handles global\r
-    * request timeout. Method idea borrowed from Net_Socket PEAR package.\r
-    *\r
-    * @param    int     buffer size to use for reading\r
-    * @return   Available data up to the newline (not including newline)\r
-    * @throws   HTTP_Request2_MessageException     In case of timeout\r
-    */\r
-    protected function readLine($bufferSize)\r
-    {\r
-        $line = '';\r
-        while (!feof($this->socket)) {\r
-            if ($this->deadline) {\r
-                stream_set_timeout($this->socket, max($this->deadline - time(), 1));\r
-            }\r
-            $line .= @fgets($this->socket, $bufferSize);\r
-            $info  = stream_get_meta_data($this->socket);\r
-            if ($info['timed_out'] || $this->deadline && time() > $this->deadline) {\r
-                $reason = $this->deadline\r
-                          ? 'after ' . $this->request->getConfig('timeout') . ' second(s)'\r
-                          : 'due to default_socket_timeout php.ini setting';\r
-                throw new HTTP_Request2_MessageException(\r
-                    "Request timed out {$reason}", HTTP_Request2_Exception::TIMEOUT\r
-                );\r
-            }\r
-            if (substr($line, -1) == "\n") {\r
-                return rtrim($line, "\r\n");\r
-            }\r
-        }\r
-        return $line;\r
-    }\r
-\r
-   /**\r
-    * Wrapper around fread(), handles global request timeout\r
-    *\r
-    * @param    int     Reads up to this number of bytes\r
-    * @return   Data read from socket\r
-    * @throws   HTTP_Request2_MessageException     In case of timeout\r
-    */\r
-    protected function fread($length)\r
-    {\r
-        if ($this->deadline) {\r
-            stream_set_timeout($this->socket, max($this->deadline - time(), 1));\r
-        }\r
-        $data = fread($this->socket, $length);\r
-        $info = stream_get_meta_data($this->socket);\r
-        if ($info['timed_out'] || $this->deadline && time() > $this->deadline) {\r
-            $reason = $this->deadline\r
-                      ? 'after ' . $this->request->getConfig('timeout') . ' second(s)'\r
-                      : 'due to default_socket_timeout php.ini setting';\r
-            throw new HTTP_Request2_MessageException(\r
-                "Request timed out {$reason}", HTTP_Request2_Exception::TIMEOUT\r
-            );\r
-        }\r
-        return $data;\r
-    }\r
-\r
-   /**\r
-    * Reads a part of response body encoded with chunked Transfer-Encoding\r
-    *\r
-    * @param    int     buffer size to use for reading\r
-    * @return   string\r
-    * @throws   HTTP_Request2_MessageException\r
-    */\r
+    /**\r
+     * Reads a part of response body encoded with chunked Transfer-Encoding\r
+     *\r
+     * @param int $bufferSize buffer size to use for reading\r
+     *\r
+     * @return   string\r
+     * @throws   HTTP_Request2_MessageException\r
+     */\r
     protected function readChunked($bufferSize)\r
     {\r
         // at start of the next chunk?\r
         if (0 == $this->chunkLength) {\r
-            $line = $this->readLine($bufferSize);\r
+            $line = $this->socket->readLine($bufferSize);\r
             if (!preg_match('/^([0-9a-f]+)/i', $line, $matches)) {\r
                 throw new HTTP_Request2_MessageException(\r
                     "Cannot decode chunked response, invalid chunk length '{$line}'",\r
@@ -1067,15 +999,15 @@ class HTTP_Request2_Adapter_Socket extends HTTP_Request2_Adapter
                 $this->chunkLength = hexdec($matches[1]);\r
                 // Chunk with zero length indicates the end\r
                 if (0 == $this->chunkLength) {\r
-                    $this->readLine($bufferSize);\r
+                    $this->socket->readLine($bufferSize);\r
                     return '';\r
                 }\r
             }\r
         }\r
-        $data = $this->fread(min($this->chunkLength, $bufferSize));\r
+        $data = $this->socket->read(min($this->chunkLength, $bufferSize));\r
         $this->chunkLength -= strlen($data);\r
         if (0 == $this->chunkLength) {\r
-            $this->readLine($bufferSize); // Trailing CRLF\r
+            $this->socket->readLine($bufferSize); // Trailing CRLF\r
         }\r
         return $data;\r
     }\r
index af7534f18dc1e1b9d7814bc047979960892f20c8..904186791ab8c3ff7db66fbdc1a803db6475da27 100644 (file)
@@ -6,7 +6,7 @@
  *\r
  * LICENSE:\r
  *\r
- * Copyright (c) 2008-2011, Alexey Borzov <avb@php.net>\r
+ * Copyright (c) 2008-2012, Alexey Borzov <avb@php.net>\r
  * All rights reserved.\r
  *\r
  * Redistribution and use in source and binary forms, with or without\r
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
  *\r
- * @category   HTTP\r
- * @package    HTTP_Request2\r
- * @author     Alexey Borzov <avb@php.net>\r
- * @license    http://opensource.org/licenses/bsd-license.php New BSD License\r
- * @version    SVN: $Id: CookieJar.php 308629 2011-02-24 17:34:24Z avb $\r
- * @link       http://pear.php.net/package/HTTP_Request2\r
+ * @category HTTP\r
+ * @package  HTTP_Request2\r
+ * @author   Alexey Borzov <avb@php.net>\r
+ * @license  http://opensource.org/licenses/bsd-license.php New BSD License\r
+ * @version  SVN: $Id: CookieJar.php 324415 2012-03-21 10:50:50Z avb $\r
+ * @link     http://pear.php.net/package/HTTP_Request2\r
  */\r
 \r
 /** Class representing a HTTP request message */\r
@@ -47,65 +47,70 @@ require_once 'HTTP/Request2.php';
 /**\r
  * Stores cookies and passes them between HTTP requests\r
  *\r
- * @category   HTTP\r
- * @package    HTTP_Request2\r
- * @author     Alexey Borzov <avb@php.net>\r
- * @version    Release: @package_version@\r
+ * @category HTTP\r
+ * @package  HTTP_Request2\r
+ * @author   Alexey Borzov <avb@php.net>\r
+ * @license  http://opensource.org/licenses/bsd-license.php New BSD License\r
+ * @version  Release: @package_version@\r
+ * @link     http://pear.php.net/package/HTTP_Request2\r
  */\r
 class HTTP_Request2_CookieJar implements Serializable\r
 {\r
-   /**\r
-    * Array of stored cookies\r
-    *\r
-    * The array is indexed by domain, path and cookie name\r
-    *   .example.com\r
-    *     /\r
-    *       some_cookie => cookie data\r
-    *     /subdir\r
-    *       other_cookie => cookie data\r
-    *   .example.org\r
-    *     ...\r
-    *\r
-    * @var array\r
-    */\r
+    /**\r
+     * Array of stored cookies\r
+     *\r
+     * The array is indexed by domain, path and cookie name\r
+     *   .example.com\r
+     *     /\r
+     *       some_cookie => cookie data\r
+     *     /subdir\r
+     *       other_cookie => cookie data\r
+     *   .example.org\r
+     *     ...\r
+     *\r
+     * @var array\r
+     */\r
     protected $cookies = array();\r
 \r
-   /**\r
-    * Whether session cookies should be serialized when serializing the jar\r
-    * @var bool\r
-    */\r
+    /**\r
+     * Whether session cookies should be serialized when serializing the jar\r
+     * @var bool\r
+     */\r
     protected $serializeSession = false;\r
 \r
-   /**\r
-    * Whether Public Suffix List should be used for domain matching\r
-    * @var bool\r
-    */\r
+    /**\r
+     * Whether Public Suffix List should be used for domain matching\r
+     * @var bool\r
+     */\r
     protected $useList = true;\r
 \r
-   /**\r
-    * Array with Public Suffix List data\r
-    * @var  array\r
-    * @link http://publicsuffix.org/\r
-    */\r
+    /**\r
+     * Array with Public Suffix List data\r
+     * @var  array\r
+     * @link http://publicsuffix.org/\r
+     */\r
     protected static $psl = array();\r
 \r
-   /**\r
-    * Class constructor, sets various options\r
-    *\r
-    * @param bool Controls serializing session cookies, see {@link serializeSessionCookies()}\r
-    * @param bool Controls using Public Suffix List, see {@link usePublicSuffixList()}\r
-    */\r
-    public function __construct($serializeSessionCookies = false, $usePublicSuffixList = true)\r
-    {\r
+    /**\r
+     * Class constructor, sets various options\r
+     *\r
+     * @param bool $serializeSessionCookies Controls serializing session cookies,\r
+     *                                      see {@link serializeSessionCookies()}\r
+     * @param bool $usePublicSuffixList     Controls using Public Suffix List,\r
+     *                                      see {@link usePublicSuffixList()}\r
+     */\r
+    public function __construct(\r
+        $serializeSessionCookies = false, $usePublicSuffixList = true\r
+    ) {\r
         $this->serializeSessionCookies($serializeSessionCookies);\r
         $this->usePublicSuffixList($usePublicSuffixList);\r
     }\r
 \r
-   /**\r
-    * Returns current time formatted in ISO-8601 at UTC timezone\r
-    *\r
-    * @return string\r
-    */\r
+    /**\r
+     * Returns current time formatted in ISO-8601 at UTC timezone\r
+     *\r
+     * @return string\r
+     */\r
     protected function now()\r
     {\r
         $dt = new DateTime();\r
@@ -113,28 +118,30 @@ class HTTP_Request2_CookieJar implements Serializable
         return $dt->format(DateTime::ISO8601);\r
     }\r
 \r
-   /**\r
-    * Checks cookie array for correctness, possibly updating its 'domain', 'path' and 'expires' fields\r
-    *\r
-    * The checks are as follows:\r
-    *   - cookie array should contain 'name' and 'value' fields;\r
-    *   - name and value should not contain disallowed symbols;\r
-    *   - 'expires' should be either empty parseable by DateTime;\r
-    *   - 'domain' and 'path' should be either not empty or an URL where\r
-    *     cookie was set should be provided.\r
-    *   - if $setter is provided, then document at that URL should be allowed\r
-    *     to set a cookie for that 'domain'. If $setter is not provided,\r
-    *     then no domain checks will be made.\r
-    *\r
-    * 'expires' field will be converted to ISO8601 format from COOKIE format,\r
-    * 'domain' and 'path' will be set from setter URL if empty.\r
-    *\r
-    * @param    array    cookie data, as returned by {@link HTTP_Request2_Response::getCookies()}\r
-    * @param    Net_URL2 URL of the document that sent Set-Cookie header\r
-    * @return   array    Updated cookie array\r
-    * @throws   HTTP_Request2_LogicException\r
-    * @throws   HTTP_Request2_MessageException\r
-    */\r
+    /**\r
+     * Checks cookie array for correctness, possibly updating its 'domain', 'path' and 'expires' fields\r
+     *\r
+     * The checks are as follows:\r
+     *   - cookie array should contain 'name' and 'value' fields;\r
+     *   - name and value should not contain disallowed symbols;\r
+     *   - 'expires' should be either empty parseable by DateTime;\r
+     *   - 'domain' and 'path' should be either not empty or an URL where\r
+     *     cookie was set should be provided.\r
+     *   - if $setter is provided, then document at that URL should be allowed\r
+     *     to set a cookie for that 'domain'. If $setter is not provided,\r
+     *     then no domain checks will be made.\r
+     *\r
+     * 'expires' field will be converted to ISO8601 format from COOKIE format,\r
+     * 'domain' and 'path' will be set from setter URL if empty.\r
+     *\r
+     * @param array    $cookie cookie data, as returned by\r
+     *                         {@link HTTP_Request2_Response::getCookies()}\r
+     * @param Net_URL2 $setter URL of the document that sent Set-Cookie header\r
+     *\r
+     * @return   array    Updated cookie array\r
+     * @throws   HTTP_Request2_LogicException\r
+     * @throws   HTTP_Request2_MessageException\r
+     */\r
     protected function checkAndUpdateFields(array $cookie, Net_URL2 $setter = null)\r
     {\r
         if ($missing = array_diff(array('name', 'value'), array_keys($cookie))) {\r
@@ -203,13 +210,15 @@ class HTTP_Request2_CookieJar implements Serializable
         return $cookie;\r
     }\r
 \r
-   /**\r
-    * Stores a cookie in the jar\r
-    *\r
-    * @param    array    cookie data, as returned by {@link HTTP_Request2_Response::getCookies()}\r
-    * @param    Net_URL2 URL of the document that sent Set-Cookie header\r
-    * @throws   HTTP_Request2_Exception\r
-    */\r
+    /**\r
+     * Stores a cookie in the jar\r
+     *\r
+     * @param array    $cookie cookie data, as returned by\r
+     *                         {@link HTTP_Request2_Response::getCookies()}\r
+     * @param Net_URL2 $setter URL of the document that sent Set-Cookie header\r
+     *\r
+     * @throws   HTTP_Request2_Exception\r
+     */\r
     public function store(array $cookie, Net_URL2 $setter = null)\r
     {\r
         $cookie = $this->checkAndUpdateFields($cookie, $setter);\r
@@ -230,13 +239,13 @@ class HTTP_Request2_CookieJar implements Serializable
         }\r
     }\r
 \r
-   /**\r
-    * Adds cookies set in HTTP response to the jar\r
-    *\r
-    * @param HTTP_Request2_Response response\r
-    * @param Net_URL2               original request URL, needed for setting\r
-    *                               default domain/path\r
-    */\r
+    /**\r
+     * Adds cookies set in HTTP response to the jar\r
+     *\r
+     * @param HTTP_Request2_Response $response HTTP response message\r
+     * @param Net_URL2               $setter   original request URL, needed for\r
+     *                               setting default domain/path\r
+     */\r
     public function addCookiesFromResponse(HTTP_Request2_Response $response, Net_URL2 $setter)\r
     {\r
         foreach ($response->getCookies() as $cookie) {\r
@@ -244,18 +253,19 @@ class HTTP_Request2_CookieJar implements Serializable
         }\r
     }\r
 \r
-   /**\r
-    * Returns all cookies matching a given request URL\r
-    *\r
-    * The following checks are made:\r
-    *   - cookie domain should match request host\r
-    *   - cookie path should be a prefix for request path\r
-    *   - 'secure' cookies will only be sent for HTTPS requests\r
-    *\r
-    * @param  Net_URL2\r
-    * @param  bool      Whether to return cookies as string for "Cookie: " header\r
-    * @return array\r
-    */\r
+    /**\r
+     * Returns all cookies matching a given request URL\r
+     *\r
+     * The following checks are made:\r
+     *   - cookie domain should match request host\r
+     *   - cookie path should be a prefix for request path\r
+     *   - 'secure' cookies will only be sent for HTTPS requests\r
+     *\r
+     * @param Net_URL2 $url      Request url\r
+     * @param bool     $asString Whether to return cookies as string for "Cookie: " header\r
+     *\r
+     * @return array|string Matching cookies\r
+     */\r
     public function getMatching(Net_URL2 $url, $asString = false)\r
     {\r
         $host   = $url->getHost();\r
@@ -291,11 +301,11 @@ class HTTP_Request2_CookieJar implements Serializable
         }\r
     }\r
 \r
-   /**\r
-    * Returns all cookies stored in a jar\r
-    *\r
-    * @return array\r
-    */\r
+    /**\r
+     * Returns all cookies stored in a jar\r
+     *\r
+     * @return array\r
+     */\r
     public function getAll()\r
     {\r
         $cookies = array();\r
@@ -309,47 +319,49 @@ class HTTP_Request2_CookieJar implements Serializable
         return $cookies;\r
     }\r
 \r
-   /**\r
-    * Sets whether session cookies should be serialized when serializing the jar\r
-    *\r
-    * @param    boolean\r
-    */\r
+    /**\r
+     * Sets whether session cookies should be serialized when serializing the jar\r
+     *\r
+     * @param boolean $serialize serialize?\r
+     */\r
     public function serializeSessionCookies($serialize)\r
     {\r
         $this->serializeSession = (bool)$serialize;\r
     }\r
 \r
-   /**\r
-    * Sets whether Public Suffix List should be used for restricting cookie-setting\r
-    *\r
-    * Without PSL {@link domainMatch()} will only prevent setting cookies for\r
-    * top-level domains like '.com' or '.org'. However, it will not prevent\r
-    * setting a cookie for '.co.uk' even though only third-level registrations\r
-    * are possible in .uk domain.\r
-    *\r
-    * With the List it is possible to find the highest level at which a domain\r
-    * may be registered for a particular top-level domain and consequently\r
-    * prevent cookies set for '.co.uk' or '.msk.ru'. The same list is used by\r
-    * Firefox, Chrome and Opera browsers to restrict cookie setting.\r
-    *\r
-    * Note that PSL is licensed differently to HTTP_Request2 package (refer to\r
-    * the license information in public-suffix-list.php), so you can disable\r
-    * its use if this is an issue for you.\r
-    *\r
-    * @param    boolean\r
-    * @link     http://publicsuffix.org/learn/\r
-    */\r
+    /**\r
+     * Sets whether Public Suffix List should be used for restricting cookie-setting\r
+     *\r
+     * Without PSL {@link domainMatch()} will only prevent setting cookies for\r
+     * top-level domains like '.com' or '.org'. However, it will not prevent\r
+     * setting a cookie for '.co.uk' even though only third-level registrations\r
+     * are possible in .uk domain.\r
+     *\r
+     * With the List it is possible to find the highest level at which a domain\r
+     * may be registered for a particular top-level domain and consequently\r
+     * prevent cookies set for '.co.uk' or '.msk.ru'. The same list is used by\r
+     * Firefox, Chrome and Opera browsers to restrict cookie setting.\r
+     *\r
+     * Note that PSL is licensed differently to HTTP_Request2 package (refer to\r
+     * the license information in public-suffix-list.php), so you can disable\r
+     * its use if this is an issue for you.\r
+     *\r
+     * @param boolean $useList use the list?\r
+     *\r
+     * @link     http://publicsuffix.org/learn/\r
+     */\r
     public function usePublicSuffixList($useList)\r
     {\r
         $this->useList = (bool)$useList;\r
     }\r
 \r
-   /**\r
-    * Returns string representation of object\r
-    *\r
-    * @return string\r
-    * @see    Serializable::serialize()\r
-    */\r
+    /**\r
+     * Returns string representation of object\r
+     *\r
+     * @return string\r
+     *\r
+     * @see    Serializable::serialize()\r
+     */\r
     public function serialize()\r
     {\r
         $cookies = $this->getAll();\r
@@ -367,12 +379,13 @@ class HTTP_Request2_CookieJar implements Serializable
         ));\r
     }\r
 \r
-   /**\r
-    * Constructs the object from serialized string\r
-    *\r
-    * @param string  string representation\r
-    * @see   Serializable::unserialize()\r
-    */\r
+    /**\r
+     * Constructs the object from serialized string\r
+     *\r
+     * @param string $serialized string representation\r
+     *\r
+     * @see   Serializable::unserialize()\r
+     */\r
     public function unserialize($serialized)\r
     {\r
         $data = unserialize($serialized);\r
@@ -393,17 +406,18 @@ class HTTP_Request2_CookieJar implements Serializable
         }\r
     }\r
 \r
-   /**\r
-    * Checks whether a cookie domain matches a request host.\r
-    *\r
-    * The method is used by {@link store()} to check for whether a document\r
-    * at given URL can set a cookie with a given domain attribute and by\r
-    * {@link getMatching()} to find cookies matching the request URL.\r
-    *\r
-    * @param    string  request host\r
-    * @param    string  cookie domain\r
-    * @return   bool    match success\r
-    */\r
+    /**\r
+     * Checks whether a cookie domain matches a request host.\r
+     *\r
+     * The method is used by {@link store()} to check for whether a document\r
+     * at given URL can set a cookie with a given domain attribute and by\r
+     * {@link getMatching()} to find cookies matching the request URL.\r
+     *\r
+     * @param string $requestHost  request host\r
+     * @param string $cookieDomain cookie domain\r
+     *\r
+     * @return   bool    match success\r
+     */\r
     public function domainMatch($requestHost, $cookieDomain)\r
     {\r
         if ($requestHost == $cookieDomain) {\r
@@ -425,17 +439,18 @@ class HTTP_Request2_CookieJar implements Serializable
         return substr('.' . $requestHost, -strlen($cookieDomain)) == $cookieDomain;\r
     }\r
 \r
-   /**\r
-    * Removes subdomains to get the registered domain (the first after top-level)\r
-    *\r
-    * The method will check Public Suffix List to find out where top-level\r
-    * domain ends and registered domain starts. It will remove domain parts\r
-    * to the left of registered one.\r
-    *\r
-    * @param  string        domain name\r
-    * @return string|bool   registered domain, will return false if $domain is\r
-    *                       either invalid or a TLD itself\r
-    */\r
+    /**\r
+     * Removes subdomains to get the registered domain (the first after top-level)\r
+     *\r
+     * The method will check Public Suffix List to find out where top-level\r
+     * domain ends and registered domain starts. It will remove domain parts\r
+     * to the left of registered one.\r
+     *\r
+     * @param string $domain domain name\r
+     *\r
+     * @return string|bool   registered domain, will return false if $domain is\r
+     *                       either invalid or a TLD itself\r
+     */\r
     public static function getRegisteredDomain($domain)\r
     {\r
         $domainParts = explode('.', ltrim($domain, '.'));\r
@@ -444,8 +459,10 @@ class HTTP_Request2_CookieJar implements Serializable
         if (empty(self::$psl)) {\r
             $path = '@data_dir@' . DIRECTORY_SEPARATOR . 'HTTP_Request2';\r
             if (0 === strpos($path, '@' . 'data_dir@')) {\r
-                $path = realpath(dirname(__FILE__) . DIRECTORY_SEPARATOR . '..'\r
-                                 . DIRECTORY_SEPARATOR . 'data');\r
+                $path = realpath(\r
+                    dirname(__FILE__) . DIRECTORY_SEPARATOR . '..'\r
+                    . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'data'\r
+                );\r
             }\r
             self::$psl = include_once $path . DIRECTORY_SEPARATOR . 'public-suffix-list.php';\r
         }\r
@@ -466,13 +483,14 @@ class HTTP_Request2_CookieJar implements Serializable
         return $result;\r
     }\r
 \r
-   /**\r
-    * Recursive helper method for {@link getRegisteredDomain()}\r
-    *\r
-    * @param  array         remaining domain parts\r
-    * @param  mixed         node in {@link HTTP_Request2_CookieJar::$psl} to check\r
-    * @return string|null   concatenated domain parts, null in case of error\r
-    */\r
+    /**\r
+     * Recursive helper method for {@link getRegisteredDomain()}\r
+     *\r
+     * @param array $domainParts remaining domain parts\r
+     * @param mixed $listNode    node in {@link HTTP_Request2_CookieJar::$psl} to check\r
+     *\r
+     * @return string|null   concatenated domain parts, null in case of error\r
+     */\r
     protected static function checkDomainsList(array $domainParts, $listNode)\r
     {\r
         $sub    = array_pop($domainParts);\r
@@ -480,7 +498,7 @@ class HTTP_Request2_CookieJar implements Serializable
 \r
         if (!is_array($listNode) || is_null($sub)\r
             || array_key_exists('!' . $sub, $listNode)\r
-         ) {\r
+        ) {\r
             return $sub;\r
 \r
         } elseif (array_key_exists($sub, $listNode)) {\r
index 530c23b9ceca81bff1a6eabae0ba5f2df644b36d..b7b8d8d0379eb82417900d81f97b9276d2707db1 100644 (file)
@@ -6,7 +6,7 @@
  *\r
  * LICENSE:\r
  *\r
- * Copyright (c) 2008-2011, Alexey Borzov <avb@php.net>\r
+ * Copyright (c) 2008-2012, Alexey Borzov <avb@php.net>\r
  * All rights reserved.\r
  *\r
  * Redistribution and use in source and binary forms, with or without\r
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
  *\r
- * @category   HTTP\r
- * @package    HTTP_Request2\r
- * @author     Alexey Borzov <avb@php.net>\r
- * @license    http://opensource.org/licenses/bsd-license.php New BSD License\r
- * @version    SVN: $Id: Exception.php 308629 2011-02-24 17:34:24Z avb $\r
- * @link       http://pear.php.net/package/HTTP_Request2\r
+ * @category HTTP\r
+ * @package  HTTP_Request2\r
+ * @author   Alexey Borzov <avb@php.net>\r
+ * @license  http://opensource.org/licenses/bsd-license.php New BSD License\r
+ * @version  SVN: $Id: Exception.php 324415 2012-03-21 10:50:50Z avb $\r
+ * @link     http://pear.php.net/package/HTTP_Request2\r
  */\r
 \r
 /**\r
@@ -49,10 +49,13 @@ require_once 'PEAR/Exception.php';
 /**\r
  * Base exception class for HTTP_Request2 package\r
  *\r
- * @category   HTTP\r
- * @package    HTTP_Request2\r
- * @version    Release: 2.0.0RC1\r
- * @link       http://pear.php.net/pepr/pepr-proposal-show.php?id=132\r
+ * @category HTTP\r
+ * @package  HTTP_Request2\r
+ * @author   Alexey Borzov <avb@php.net>\r
+ * @license  http://opensource.org/licenses/bsd-license.php New BSD License\r
+ * @version  Release: 2.1.1\r
+ * @link     http://pear.php.net/package/HTTP_Request2\r
+ * @link     http://pear.php.net/pepr/pepr-proposal-show.php?id=132\r
  */\r
 class HTTP_Request2_Exception extends PEAR_Exception\r
 {\r
@@ -76,34 +79,34 @@ class HTTP_Request2_Exception extends PEAR_Exception
     /** Redirect to a protocol other than http(s):// */\r
     const NON_HTTP_REDIRECT  = 50;\r
 \r
-   /**\r
-    * Native error code\r
-    * @var int\r
-    */\r
+    /**\r
+     * Native error code\r
+     * @var int\r
+     */\r
     private $_nativeCode;\r
 \r
-   /**\r
-    * Constructor, can set package error code and native error code\r
-    *\r
-    * @param string exception message\r
-    * @param int    package error code, one of class constants\r
-    * @param int    error code from underlying PHP extension\r
-    */\r
+    /**\r
+     * Constructor, can set package error code and native error code\r
+     *\r
+     * @param string $message    exception message\r
+     * @param int    $code       package error code, one of class constants\r
+     * @param int    $nativeCode error code from underlying PHP extension\r
+     */\r
     public function __construct($message = null, $code = null, $nativeCode = null)\r
     {\r
         parent::__construct($message, $code);\r
         $this->_nativeCode = $nativeCode;\r
     }\r
 \r
-   /**\r
-    * Returns error code produced by underlying PHP extension\r
-    *\r
-    * For Socket Adapter this may contain error number returned by\r
-    * stream_socket_client(), for Curl Adapter this will contain error number\r
-    * returned by curl_errno()\r
-    *\r
-    * @return integer\r
-    */\r
+    /**\r
+     * Returns error code produced by underlying PHP extension\r
+     *\r
+     * For Socket Adapter this may contain error number returned by\r
+     * stream_socket_client(), for Curl Adapter this will contain error number\r
+     * returned by curl_errno()\r
+     *\r
+     * @return integer\r
+     */\r
     public function getNativeCode()\r
     {\r
         return $this->_nativeCode;\r
@@ -113,11 +116,16 @@ class HTTP_Request2_Exception extends PEAR_Exception
 /**\r
  * Exception thrown in case of missing features\r
  *\r
- * @category   HTTP\r
- * @package    HTTP_Request2\r
- * @version    Release: 2.0.0RC1\r
+ * @category HTTP\r
+ * @package  HTTP_Request2\r
+ * @author   Alexey Borzov <avb@php.net>\r
+ * @license  http://opensource.org/licenses/bsd-license.php New BSD License\r
+ * @version  Release: 2.1.1\r
+ * @link     http://pear.php.net/package/HTTP_Request2\r
  */\r
-class HTTP_Request2_NotImplementedException extends HTTP_Request2_Exception {}\r
+class HTTP_Request2_NotImplementedException extends HTTP_Request2_Exception\r
+{\r
+}\r
 \r
 /**\r
  * Exception that represents error in the program logic\r
@@ -129,11 +137,16 @@ class HTTP_Request2_NotImplementedException extends HTTP_Request2_Exception {}
  *\r
  * The exception will usually contain a package error code.\r
  *\r
- * @category   HTTP\r
- * @package    HTTP_Request2\r
- * @version    Release: 2.0.0RC1\r
+ * @category HTTP\r
+ * @package  HTTP_Request2\r
+ * @author   Alexey Borzov <avb@php.net>\r
+ * @license  http://opensource.org/licenses/bsd-license.php New BSD License\r
+ * @version  Release: 2.1.1\r
+ * @link     http://pear.php.net/package/HTTP_Request2\r
  */\r
-class HTTP_Request2_LogicException extends HTTP_Request2_Exception {}\r
+class HTTP_Request2_LogicException extends HTTP_Request2_Exception\r
+{\r
+}\r
 \r
 /**\r
  * Exception thrown when connection to a web or proxy server fails\r
@@ -141,20 +154,30 @@ class HTTP_Request2_LogicException extends HTTP_Request2_Exception {}
  * The exception will not contain a package error code, but will contain\r
  * native error code, as returned by stream_socket_client() or curl_errno().\r
  *\r
- * @category   HTTP\r
- * @package    HTTP_Request2\r
- * @version    Release: 2.0.0RC1\r
+ * @category HTTP\r
+ * @package  HTTP_Request2\r
+ * @author   Alexey Borzov <avb@php.net>\r
+ * @license  http://opensource.org/licenses/bsd-license.php New BSD License\r
+ * @version  Release: 2.1.1\r
+ * @link     http://pear.php.net/package/HTTP_Request2\r
  */\r
-class HTTP_Request2_ConnectionException extends HTTP_Request2_Exception {}\r
+class HTTP_Request2_ConnectionException extends HTTP_Request2_Exception\r
+{\r
+}\r
 \r
 /**\r
  * Exception thrown when sending or receiving HTTP message fails\r
  *\r
  * The exception may contain both package error code and native error code.\r
  *\r
- * @category   HTTP\r
- * @package    HTTP_Request2\r
- * @version    Release: 2.0.0RC1\r
+ * @category HTTP\r
+ * @package  HTTP_Request2\r
+ * @author   Alexey Borzov <avb@php.net>\r
+ * @license  http://opensource.org/licenses/bsd-license.php New BSD License\r
+ * @version  Release: 2.1.1\r
+ * @link     http://pear.php.net/package/HTTP_Request2\r
  */\r
-class HTTP_Request2_MessageException extends HTTP_Request2_Exception {}\r
+class HTTP_Request2_MessageException extends HTTP_Request2_Exception\r
+{\r
+}\r
 ?>
\ No newline at end of file
index a7bd948bafe4e90bc7295b8f83e7ac64dff6a857..53e0c1b9eabfdda4a26ffeb1e9032317e5657593 100644 (file)
@@ -6,7 +6,7 @@
  *\r
  * LICENSE:\r
  *\r
- * Copyright (c) 2008-2011, Alexey Borzov <avb@php.net>\r
+ * Copyright (c) 2008-2012, Alexey Borzov <avb@php.net>\r
  * All rights reserved.\r
  *\r
  * Redistribution and use in source and binary forms, with or without\r
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
  *\r
- * @category   HTTP\r
- * @package    HTTP_Request2\r
- * @author     Alexey Borzov <avb@php.net>\r
- * @license    http://opensource.org/licenses/bsd-license.php New BSD License\r
- * @version    SVN: $Id: MultipartBody.php 308322 2011-02-14 13:58:03Z avb $\r
- * @link       http://pear.php.net/package/HTTP_Request2\r
+ * @category HTTP\r
+ * @package  HTTP_Request2\r
+ * @author   Alexey Borzov <avb@php.net>\r
+ * @license  http://opensource.org/licenses/bsd-license.php New BSD License\r
+ * @version  SVN: $Id: MultipartBody.php 324415 2012-03-21 10:50:50Z avb $\r
+ * @link     http://pear.php.net/package/HTTP_Request2\r
  */\r
 \r
 /**\r
  * The class helps to reduce memory consumption by streaming large file uploads\r
  * from disk, it also allows monitoring of upload progress (see request #7630)\r
  *\r
- * @category   HTTP\r
- * @package    HTTP_Request2\r
- * @author     Alexey Borzov <avb@php.net>\r
- * @version    Release: 2.0.0RC1\r
- * @link       http://tools.ietf.org/html/rfc1867\r
+ * @category HTTP\r
+ * @package  HTTP_Request2\r
+ * @author   Alexey Borzov <avb@php.net>\r
+ * @license  http://opensource.org/licenses/bsd-license.php New BSD License\r
+ * @version  Release: 2.1.1\r
+ * @link     http://pear.php.net/package/HTTP_Request2\r
+ * @link     http://tools.ietf.org/html/rfc1867\r
  */\r
 class HTTP_Request2_MultipartBody\r
 {\r
-   /**\r
-    * MIME boundary\r
-    * @var  string\r
-    */\r
+    /**\r
+     * MIME boundary\r
+     * @var  string\r
+     */\r
     private $_boundary;\r
 \r
-   /**\r
-    * Form parameters added via {@link HTTP_Request2::addPostParameter()}\r
-    * @var  array\r
-    */\r
+    /**\r
+     * Form parameters added via {@link HTTP_Request2::addPostParameter()}\r
+     * @var  array\r
+     */\r
     private $_params = array();\r
 \r
-   /**\r
-    * File uploads added via {@link HTTP_Request2::addUpload()}\r
-    * @var  array\r
-    */\r
+    /**\r
+     * File uploads added via {@link HTTP_Request2::addUpload()}\r
+     * @var  array\r
+     */\r
     private $_uploads = array();\r
 \r
-   /**\r
-    * Header for parts with parameters\r
-    * @var  string\r
-    */\r
+    /**\r
+     * Header for parts with parameters\r
+     * @var  string\r
+     */\r
     private $_headerParam = "--%s\r\nContent-Disposition: form-data; name=\"%s\"\r\n\r\n";\r
 \r
-   /**\r
-    * Header for parts with uploads\r
-    * @var  string\r
-    */\r
+    /**\r
+     * Header for parts with uploads\r
+     * @var  string\r
+     */\r
     private $_headerUpload = "--%s\r\nContent-Disposition: form-data; name=\"%s\"; filename=\"%s\"\r\nContent-Type: %s\r\n\r\n";\r
 \r
-   /**\r
-    * Current position in parameter and upload arrays\r
-    *\r
-    * First number is index of "current" part, second number is position within\r
-    * "current" part\r
-    *\r
-    * @var  array\r
-    */\r
+    /**\r
+     * Current position in parameter and upload arrays\r
+     *\r
+     * First number is index of "current" part, second number is position within\r
+     * "current" part\r
+     *\r
+     * @var  array\r
+     */\r
     private $_pos = array(0, 0);\r
 \r
 \r
-   /**\r
-    * Constructor. Sets the arrays with POST data.\r
-    *\r
-    * @param    array   values of form fields set via {@link HTTP_Request2::addPostParameter()}\r
-    * @param    array   file uploads set via {@link HTTP_Request2::addUpload()}\r
-    * @param    bool    whether to append brackets to array variable names\r
-    */\r
+    /**\r
+     * Constructor. Sets the arrays with POST data.\r
+     *\r
+     * @param array $params      values of form fields set via\r
+     *                           {@link HTTP_Request2::addPostParameter()}\r
+     * @param array $uploads     file uploads set via\r
+     *                           {@link HTTP_Request2::addUpload()}\r
+     * @param bool  $useBrackets whether to append brackets to array variable names\r
+     */\r
     public function __construct(array $params, array $uploads, $useBrackets = true)\r
     {\r
         $this->_params = self::_flattenArray('', $params, $useBrackets);\r
@@ -123,11 +127,11 @@ class HTTP_Request2_MultipartBody
         }\r
     }\r
 \r
-   /**\r
-    * Returns the length of the body to use in Content-Length header\r
-    *\r
-    * @return   integer\r
-    */\r
+    /**\r
+     * Returns the length of the body to use in Content-Length header\r
+     *\r
+     * @return   integer\r
+     */\r
     public function getLength()\r
     {\r
         $boundaryLength     = strlen($this->getBoundary());\r
@@ -144,11 +148,11 @@ class HTTP_Request2_MultipartBody
         return $length;\r
     }\r
 \r
-   /**\r
-    * Returns the boundary to use in Content-Type header\r
-    *\r
-    * @return   string\r
-    */\r
+    /**\r
+     * Returns the boundary to use in Content-Type header\r
+     *\r
+     * @return   string\r
+     */\r
     public function getBoundary()\r
     {\r
         if (empty($this->_boundary)) {\r
@@ -157,12 +161,13 @@ class HTTP_Request2_MultipartBody
         return $this->_boundary;\r
     }\r
 \r
-   /**\r
-    * Returns next chunk of request body\r
-    *\r
-    * @param    integer Amount of bytes to read\r
-    * @return   string  Up to $length bytes of data, empty string if at end\r
-    */\r
+    /**\r
+     * Returns next chunk of request body\r
+     *\r
+     * @param integer $length Number of bytes to read\r
+     *\r
+     * @return   string  Up to $length bytes of data, empty string if at end\r
+     */\r
     public function read($length)\r
     {\r
         $ret         = '';\r
@@ -172,18 +177,18 @@ class HTTP_Request2_MultipartBody
         while ($length > 0 && $this->_pos[0] <= $paramCount + $uploadCount) {\r
             $oldLength = $length;\r
             if ($this->_pos[0] < $paramCount) {\r
-                $param = sprintf($this->_headerParam, $boundary,\r
-                                 $this->_params[$this->_pos[0]][0]) .\r
-                         $this->_params[$this->_pos[0]][1] . "\r\n";\r
+                $param = sprintf(\r
+                    $this->_headerParam, $boundary, $this->_params[$this->_pos[0]][0]\r
+                ) . $this->_params[$this->_pos[0]][1] . "\r\n";\r
                 $ret    .= substr($param, $this->_pos[1], $length);\r
                 $length -= min(strlen($param) - $this->_pos[1], $length);\r
 \r
             } elseif ($this->_pos[0] < $paramCount + $uploadCount) {\r
                 $pos    = $this->_pos[0] - $paramCount;\r
-                $header = sprintf($this->_headerUpload, $boundary,\r
-                                  $this->_uploads[$pos]['name'],\r
-                                  $this->_uploads[$pos]['filename'],\r
-                                  $this->_uploads[$pos]['type']);\r
+                $header = sprintf(\r
+                    $this->_headerUpload, $boundary, $this->_uploads[$pos]['name'],\r
+                    $this->_uploads[$pos]['filename'], $this->_uploads[$pos]['type']\r
+                );\r
                 if ($this->_pos[1] < strlen($header)) {\r
                     $ret    .= substr($header, $this->_pos[1], $length);\r
                     $length -= min(strlen($header) - $this->_pos[1], $length);\r
@@ -214,11 +219,11 @@ class HTTP_Request2_MultipartBody
         return $ret;\r
     }\r
 \r
-   /**\r
-    * Sets the current position to the start of the body\r
-    *\r
-    * This allows reusing the same body in another request\r
-    */\r
+    /**\r
+     * Sets the current position to the start of the body\r
+     *\r
+     * This allows reusing the same body in another request\r
+     */\r
     public function rewind()\r
     {\r
         $this->_pos = array(0, 0);\r
@@ -227,14 +232,14 @@ class HTTP_Request2_MultipartBody
         }\r
     }\r
 \r
-   /**\r
-    * Returns the body as string\r
-    *\r
-    * Note that it reads all file uploads into memory so it is a good idea not\r
-    * to use this method with large file uploads and rely on read() instead.\r
-    *\r
-    * @return   string\r
-    */\r
+    /**\r
+     * Returns the body as string\r
+     *\r
+     * Note that it reads all file uploads into memory so it is a good idea not\r
+     * to use this method with large file uploads and rely on read() instead.\r
+     *\r
+     * @return   string\r
+     */\r
     public function __toString()\r
     {\r
         $this->rewind();\r
@@ -242,15 +247,16 @@ class HTTP_Request2_MultipartBody
     }\r
 \r
 \r
-   /**\r
-    * Helper function to change the (probably multidimensional) associative array\r
-    * into the simple one.\r
-    *\r
-    * @param    string  name for item\r
-    * @param    mixed   item's values\r
-    * @param    bool    whether to append [] to array variables' names\r
-    * @return   array   array with the following items: array('item name', 'item value');\r
-    */\r
+    /**\r
+     * Helper function to change the (probably multidimensional) associative array\r
+     * into the simple one.\r
+     *\r
+     * @param string $name        name for item\r
+     * @param mixed  $values      item's values\r
+     * @param bool   $useBrackets whether to append [] to array variables' names\r
+     *\r
+     * @return   array   array with the following items: array('item name', 'item value');\r
+     */\r
     private static function _flattenArray($name, $values, $useBrackets)\r
     {\r
         if (!is_array($values)) {\r
index 7865906f658208cf6f1d67cfcef3f5d33a133e05..8520f61c2136c13d13ade95a003bfd68e7dc827a 100644 (file)
@@ -6,7 +6,7 @@
  *\r
  * LICENSE:\r
  *\r
- * Copyright (c) 2008-2011, Alexey Borzov <avb@php.net>\r
+ * Copyright (c) 2008-2012, Alexey Borzov <avb@php.net>\r
  * All rights reserved.\r
  *\r
  * Redistribution and use in source and binary forms, with or without\r
@@ -38,7 +38,7 @@
  * @author   David Jean Louis <izi@php.net>\r
  * @author   Alexey Borzov <avb@php.net>\r
  * @license  http://opensource.org/licenses/bsd-license.php New BSD License\r
- * @version  SVN: $Id: Log.php 308680 2011-02-25 17:40:17Z avb $\r
+ * @version  SVN: $Id: Log.php 324415 2012-03-21 10:50:50Z avb $\r
  * @link     http://pear.php.net/package/HTTP_Request2\r
  */\r
 \r
@@ -87,7 +87,7 @@ require_once 'HTTP/Request2/Exception.php';
  * @author   David Jean Louis <izi@php.net>\r
  * @author   Alexey Borzov <avb@php.net>\r
  * @license  http://opensource.org/licenses/bsd-license.php New BSD License\r
- * @version  Release: 2.0.0RC1\r
+ * @version  Release: 2.1.1\r
  * @link     http://pear.php.net/package/HTTP_Request2\r
  */\r
 class HTTP_Request2_Observer_Log implements SplObserver\r
@@ -171,10 +171,10 @@ class HTTP_Request2_Observer_Log implements SplObserver
             $this->log('> ' . $event['data'] . ' byte(s) sent');\r
             break;\r
         case 'receivedHeaders':\r
-            $this->log(sprintf('< HTTP/%s %s %s',\r
-                $event['data']->getVersion(),\r
-                $event['data']->getStatus(),\r
-                $event['data']->getReasonPhrase()));\r
+            $this->log(sprintf(\r
+                '< HTTP/%s %s %s', $event['data']->getVersion(),\r
+                $event['data']->getStatus(), $event['data']->getReasonPhrase()\r
+            ));\r
             $headers = $event['data']->getHeader();\r
             foreach ($headers as $key => $val) {\r
                 $this->log('< ' . $key . ': ' . $val);\r
index 73e9a5dc82c64699c63995426f9615539fd49577..96682d795ba81f3006b83bdf8bbcebe36ebd13ee 100644 (file)
@@ -6,19 +6,19 @@
  *\r
  * LICENSE:\r
  *\r
- * Copyright (c) 2008-2011, Alexey Borzov <avb@php.net>\r
+ * Copyright (c) 2008-2012, Alexey Borzov <avb@php.net>\r
  * All rights reserved.\r
  *\r
  * Redistribution and use in source and binary forms, with or without\r
  * modification, are permitted provided that the following conditions\r
  * are met:\r
  *\r
- *    * Redistributions of source code must retain the above copyright\r
+ *     * Redistributions of source code must retain the above copyright\r
  *      notice, this list of conditions and the following disclaimer.\r
- *    * Redistributions in binary form must reproduce the above copyright\r
+ *     * Redistributions in binary form must reproduce the above copyright\r
  *      notice, this list of conditions and the following disclaimer in the\r
  *      documentation and/or other materials provided with the distribution.\r
- *    * The names of the authors may not be used to endorse or promote products\r
+ *     * The names of the authors may not be used to endorse or promote products\r
  *      derived from this software without specific prior written permission.\r
  *\r
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS\r
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
  *\r
- * @category   HTTP\r
- * @package    HTTP_Request2\r
- * @author     Alexey Borzov <avb@php.net>\r
- * @license    http://opensource.org/licenses/bsd-license.php New BSD License\r
- * @version    SVN: $Id: Response.php 309921 2011-04-03 16:43:02Z avb $\r
- * @link       http://pear.php.net/package/HTTP_Request2\r
+ * @category HTTP\r
+ * @package  HTTP_Request2\r
+ * @author   Alexey Borzov <avb@php.net>\r
+ * @license  http://opensource.org/licenses/bsd-license.php New BSD License\r
+ * @version  SVN: $Id: Response.php 324936 2012-04-07 07:49:03Z avb $\r
+ * @link     http://pear.php.net/package/HTTP_Request2\r
  */\r
 \r
 /**\r
@@ -66,84 +66,85 @@ require_once 'HTTP/Request2/Exception.php';
  * var_dump($response->getHeader(), $response->getCookies(), $response->getBody());\r
  * </code>\r
  *\r
- *\r
- * @category   HTTP\r
- * @package    HTTP_Request2\r
- * @author     Alexey Borzov <avb@php.net>\r
- * @version    Release: 2.0.0RC1\r
- * @link       http://tools.ietf.org/html/rfc2616#section-6\r
+ * @category HTTP\r
+ * @package  HTTP_Request2\r
+ * @author   Alexey Borzov <avb@php.net>\r
+ * @license  http://opensource.org/licenses/bsd-license.php New BSD License\r
+ * @version  Release: 2.1.1\r
+ * @link     http://pear.php.net/package/HTTP_Request2\r
+ * @link     http://tools.ietf.org/html/rfc2616#section-6\r
  */\r
 class HTTP_Request2_Response\r
 {\r
-   /**\r
-    * HTTP protocol version (e.g. 1.0, 1.1)\r
-    * @var  string\r
-    */\r
+    /**\r
+     * HTTP protocol version (e.g. 1.0, 1.1)\r
+     * @var  string\r
+     */\r
     protected $version;\r
 \r
-   /**\r
-    * Status code\r
-    * @var  integer\r
-    * @link http://tools.ietf.org/html/rfc2616#section-6.1.1\r
-    */\r
+    /**\r
+     * Status code\r
+     * @var  integer\r
+     * @link http://tools.ietf.org/html/rfc2616#section-6.1.1\r
+     */\r
     protected $code;\r
 \r
-   /**\r
-    * Reason phrase\r
-    * @var  string\r
-    * @link http://tools.ietf.org/html/rfc2616#section-6.1.1\r
-    */\r
+    /**\r
+     * Reason phrase\r
+     * @var  string\r
+     * @link http://tools.ietf.org/html/rfc2616#section-6.1.1\r
+     */\r
     protected $reasonPhrase;\r
 \r
-   /**\r
-    * Effective URL (may be different from original request URL in case of redirects)\r
-    * @var  string\r
-    */\r
+    /**\r
+     * Effective URL (may be different from original request URL in case of redirects)\r
+     * @var  string\r
+     */\r
     protected $effectiveUrl;\r
 \r
-   /**\r
-    * Associative array of response headers\r
-    * @var  array\r
-    */\r
+    /**\r
+     * Associative array of response headers\r
+     * @var  array\r
+     */\r
     protected $headers = array();\r
 \r
-   /**\r
-    * Cookies set in the response\r
-    * @var  array\r
-    */\r
+    /**\r
+     * Cookies set in the response\r
+     * @var  array\r
+     */\r
     protected $cookies = array();\r
 \r
-   /**\r
-    * Name of last header processed by parseHederLine()\r
-    *\r
-    * Used to handle the headers that span multiple lines\r
-    *\r
-    * @var  string\r
-    */\r
+    /**\r
+     * Name of last header processed by parseHederLine()\r
+     *\r
+     * Used to handle the headers that span multiple lines\r
+     *\r
+     * @var  string\r
+     */\r
     protected $lastHeader = null;\r
 \r
-   /**\r
-    * Response body\r
-    * @var  string\r
-    */\r
+    /**\r
+     * Response body\r
+     * @var  string\r
+     */\r
     protected $body = '';\r
 \r
-   /**\r
-    * Whether the body is still encoded by Content-Encoding\r
-    *\r
-    * cURL provides the decoded body to the callback; if we are reading from\r
-    * socket the body is still gzipped / deflated\r
-    *\r
-    * @var  bool\r
-    */\r
+    /**\r
+     * Whether the body is still encoded by Content-Encoding\r
+     *\r
+     * cURL provides the decoded body to the callback; if we are reading from\r
+     * socket the body is still gzipped / deflated\r
+     *\r
+     * @var  bool\r
+     */\r
     protected $bodyEncoded;\r
 \r
-   /**\r
-    * Associative array of HTTP status code / reason phrase.\r
-    *\r
-    * @var  array\r
-    * @link http://tools.ietf.org/html/rfc2616#section-10\r
-    */\r
+    /**\r
+     * Associative array of HTTP status code / reason phrase.\r
+     *\r
+     * @var  array\r
+     * @link http://tools.ietf.org/html/rfc2616#section-10\r
+     */\r
     protected static $phrases = array(\r
 \r
         // 1xx: Informational - Request received, continuing process\r
@@ -203,14 +204,34 @@ class HTTP_Request2_Response
 \r
     );\r
 \r
-   /**\r
-    * Constructor, parses the response status line\r
-    *\r
-    * @param    string Response status line (e.g. "HTTP/1.1 200 OK")\r
-    * @param    bool   Whether body is still encoded by Content-Encoding\r
-    * @param    string Effective URL of the response\r
-    * @throws   HTTP_Request2_MessageException if status line is invalid according to spec\r
-    */\r
+    /**\r
+     * Returns the default reason phrase for the given code or all reason phrases\r
+     *\r
+     * @param int $code Response code\r
+     *\r
+     * @return string|array|null Default reason phrase for $code if $code is given\r
+     *                           (null if no phrase is available), array of all\r
+     *                           reason phrases if $code is null\r
+     * @link   http://pear.php.net/bugs/18716\r
+     */\r
+    public static function getDefaultReasonPhrase($code = null)\r
+    {\r
+        if (null === $code) {\r
+            return self::$phrases;\r
+        } else {\r
+            return isset(self::$phrases[$code]) ? self::$phrases[$code] : null;\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Constructor, parses the response status line\r
+     *\r
+     * @param string $statusLine   Response status line (e.g. "HTTP/1.1 200 OK")\r
+     * @param bool   $bodyEncoded  Whether body is still encoded by Content-Encoding\r
+     * @param string $effectiveUrl Effective URL of the response\r
+     *\r
+     * @throws   HTTP_Request2_MessageException if status line is invalid according to spec\r
+     */\r
     public function __construct($statusLine, $bodyEncoded = true, $effectiveUrl = null)\r
     {\r
         if (!preg_match('!^HTTP/(\d\.\d) (\d{3})(?: (.+))?!', $statusLine, $m)) {\r
@@ -219,33 +240,29 @@ class HTTP_Request2_Response
                 HTTP_Request2_Exception::MALFORMED_RESPONSE\r
             );\r
         }\r
-        $this->version = $m[1];\r
-        $this->code    = intval($m[2]);\r
-        if (!empty($m[3])) {\r
-            $this->reasonPhrase = trim($m[3]);\r
-        } elseif (!empty(self::$phrases[$this->code])) {\r
-            $this->reasonPhrase = self::$phrases[$this->code];\r
-        }\r
+        $this->version      = $m[1];\r
+        $this->code         = intval($m[2]);\r
+        $this->reasonPhrase = !empty($m[3]) ? trim($m[3]) : self::getDefaultReasonPhrase($this->code);\r
         $this->bodyEncoded  = (bool)$bodyEncoded;\r
         $this->effectiveUrl = (string)$effectiveUrl;\r
     }\r
 \r
-   /**\r
-    * Parses the line from HTTP response filling $headers array\r
-    *\r
-    * The method should be called after reading the line from socket or receiving\r
-    * it into cURL callback. Passing an empty string here indicates the end of\r
-    * response headers and triggers additional processing, so be sure to pass an\r
-    * empty string in the end.\r
-    *\r
-    * @param    string  Line from HTTP response\r
-    */\r
+    /**\r
+     * Parses the line from HTTP response filling $headers array\r
+     *\r
+     * The method should be called after reading the line from socket or receiving\r
+     * it into cURL callback. Passing an empty string here indicates the end of\r
+     * response headers and triggers additional processing, so be sure to pass an\r
+     * empty string in the end.\r
+     *\r
+     * @param string $headerLine Line from HTTP response\r
+     */\r
     public function parseHeaderLine($headerLine)\r
     {\r
         $headerLine = trim($headerLine, "\r\n");\r
 \r
-        // empty string signals the end of headers, process the received ones\r
         if ('' == $headerLine) {\r
+            // empty string signals the end of headers, process the received ones\r
             if (!empty($this->headers['set-cookie'])) {\r
                 $cookies = is_array($this->headers['set-cookie'])?\r
                            $this->headers['set-cookie']:\r
@@ -261,8 +278,8 @@ class HTTP_Request2_Response
                 }\r
             }\r
 \r
-        // string of the form header-name: header value\r
         } elseif (preg_match('!^([^\x00-\x1f\x7f-\xff()<>@,;:\\\\"/\[\]?={}\s]+):(.+)$!', $headerLine, $m)) {\r
+            // string of the form header-name: header value\r
             $name  = strtolower($m[1]);\r
             $value = trim($m[2]);\r
             if (empty($this->headers[$name])) {\r
@@ -275,8 +292,8 @@ class HTTP_Request2_Response
             }\r
             $this->lastHeader = $name;\r
 \r
-        // continuation of a previous header\r
         } elseif (preg_match('!^\s+(.+)$!', $headerLine, $m) && $this->lastHeader) {\r
+            // continuation of a previous header\r
             if (!is_array($this->headers[$this->lastHeader])) {\r
                 $this->headers[$this->lastHeader] .= ' ' . trim($m[1]);\r
             } else {\r
@@ -286,12 +303,13 @@ class HTTP_Request2_Response
         }\r
     }\r
 \r
-   /**\r
-    * Parses a Set-Cookie header to fill $cookies array\r
-    *\r
-    * @param    string    value of Set-Cookie header\r
-    * @link     http://web.archive.org/web/20080331104521/http://cgi.netscape.com/newsref/std/cookie_spec.html\r
-    */\r
+    /**\r
+     * Parses a Set-Cookie header to fill $cookies array\r
+     *\r
+     * @param string $cookieString value of Set-Cookie header\r
+     *\r
+     * @link     http://web.archive.org/web/20080331104521/http://cgi.netscape.com/newsref/std/cookie_spec.html\r
+     */\r
     protected function parseCookie($cookieString)\r
     {\r
         $cookie = array(\r
@@ -301,14 +319,14 @@ class HTTP_Request2_Response
             'secure'  => false\r
         );\r
 \r
-        // Only a name=value pair\r
         if (!strpos($cookieString, ';')) {\r
+            // Only a name=value pair\r
             $pos = strpos($cookieString, '=');\r
             $cookie['name']  = trim(substr($cookieString, 0, $pos));\r
             $cookie['value'] = trim(substr($cookieString, $pos + 1));\r
 \r
-        // Some optional parameters are supplied\r
         } else {\r
+            // Some optional parameters are supplied\r
             $elements = explode(';', $cookieString);\r
             $pos = strpos($elements[0], '=');\r
             $cookie['name']  = trim(substr($elements[0], 0, $pos));\r
@@ -336,64 +354,69 @@ class HTTP_Request2_Response
         $this->cookies[] = $cookie;\r
     }\r
 \r
-   /**\r
-    * Appends a string to the response body\r
-    * @param    string\r
-    */\r
+    /**\r
+     * Appends a string to the response body\r
+     *\r
+     * @param string $bodyChunk part of response body\r
+     */\r
     public function appendBody($bodyChunk)\r
     {\r
         $this->body .= $bodyChunk;\r
     }\r
 \r
-   /**\r
-    * Returns the effective URL of the response\r
-    *\r
-    * This may be different from the request URL if redirects were followed.\r
-    *\r
-    * @return string\r
-    * @link   http://pear.php.net/bugs/bug.php?id=18412\r
-    */\r
+    /**\r
+     * Returns the effective URL of the response\r
+     *\r
+     * This may be different from the request URL if redirects were followed.\r
+     *\r
+     * @return string\r
+     * @link   http://pear.php.net/bugs/bug.php?id=18412\r
+     */\r
     public function getEffectiveUrl()\r
     {\r
         return $this->effectiveUrl;\r
     }\r
 \r
-   /**\r
-    * Returns the status code\r
-    * @return   integer\r
-    */\r
+    /**\r
+     * Returns the status code\r
+     *\r
+     * @return   integer\r
+     */\r
     public function getStatus()\r
     {\r
         return $this->code;\r
     }\r
 \r
-   /**\r
-    * Returns the reason phrase\r
-    * @return   string\r
-    */\r
+    /**\r
+     * Returns the reason phrase\r
+     *\r
+     * @return   string\r
+     */\r
     public function getReasonPhrase()\r
     {\r
         return $this->reasonPhrase;\r
     }\r
 \r
-   /**\r
-    * Whether response is a redirect that can be automatically handled by HTTP_Request2\r
-    * @return   bool\r
-    */\r
+    /**\r
+     * Whether response is a redirect that can be automatically handled by HTTP_Request2\r
+     *\r
+     * @return   bool\r
+     */\r
     public function isRedirect()\r
     {\r
         return in_array($this->code, array(300, 301, 302, 303, 307))\r
                && isset($this->headers['location']);\r
     }\r
 \r
-   /**\r
-    * Returns either the named header or all response headers\r
-    *\r
-    * @param    string          Name of header to return\r
-    * @return   string|array    Value of $headerName header (null if header is\r
-    *                           not present), array of all response headers if\r
-    *                           $headerName is null\r
-    */\r
+    /**\r
+     * Returns either the named header or all response headers\r
+     *\r
+     * @param string $headerName Name of header to return\r
+     *\r
+     * @return   string|array    Value of $headerName header (null if header is\r
+     *                           not present), array of all response headers if\r
+     *                           $headerName is null\r
+     */\r
     public function getHeader($headerName = null)\r
     {\r
         if (null === $headerName) {\r
@@ -404,42 +427,42 @@ class HTTP_Request2_Response
         }\r
     }\r
 \r
-   /**\r
-    * Returns cookies set in response\r
-    *\r
-    * @return   array\r
-    */\r
+    /**\r
+     * Returns cookies set in response\r
+     *\r
+     * @return   array\r
+     */\r
     public function getCookies()\r
     {\r
         return $this->cookies;\r
     }\r
 \r
-   /**\r
-    * Returns the body of the response\r
-    *\r
-    * @return   string\r
-    * @throws   HTTP_Request2_Exception if body cannot be decoded\r
-    */\r
+    /**\r
+     * Returns the body of the response\r
+     *\r
+     * @return   string\r
+     * @throws   HTTP_Request2_Exception if body cannot be decoded\r
+     */\r
     public function getBody()\r
     {\r
-        if (0 == strlen($this->body) || !$this->bodyEncoded ||\r
-            !in_array(strtolower($this->getHeader('content-encoding')), array('gzip', 'deflate'))\r
+        if (0 == strlen($this->body) || !$this->bodyEncoded\r
+            || !in_array(strtolower($this->getHeader('content-encoding')), array('gzip', 'deflate'))\r
         ) {\r
             return $this->body;\r
 \r
         } else {\r
             if (extension_loaded('mbstring') && (2 & ini_get('mbstring.func_overload'))) {\r
                 $oldEncoding = mb_internal_encoding();\r
-                mb_internal_encoding('iso-8859-1');\r
+                mb_internal_encoding('8bit');\r
             }\r
 \r
             try {\r
                 switch (strtolower($this->getHeader('content-encoding'))) {\r
-                    case 'gzip':\r
-                        $decoded = self::decodeGzip($this->body);\r
-                        break;\r
-                    case 'deflate':\r
-                        $decoded = self::decodeDeflate($this->body);\r
+                case 'gzip':\r
+                    $decoded = self::decodeGzip($this->body);\r
+                    break;\r
+                case 'deflate':\r
+                    $decoded = self::decodeDeflate($this->body);\r
                 }\r
             } catch (Exception $e) {\r
             }\r
@@ -454,29 +477,30 @@ class HTTP_Request2_Response
         }\r
     }\r
 \r
-   /**\r
-    * Get the HTTP version of the response\r
-    *\r
-    * @return   string\r
-    */\r
+    /**\r
+     * Get the HTTP version of the response\r
+     *\r
+     * @return   string\r
+     */\r
     public function getVersion()\r
     {\r
         return $this->version;\r
     }\r
 \r
-   /**\r
-    * Decodes the message-body encoded by gzip\r
-    *\r
-    * The real decoding work is done by gzinflate() built-in function, this\r
-    * method only parses the header and checks data for compliance with\r
-    * RFC 1952\r
-    *\r
-    * @param    string  gzip-encoded data\r
-    * @return   string  decoded data\r
-    * @throws   HTTP_Request2_LogicException\r
-    * @throws   HTTP_Request2_MessageException\r
-    * @link     http://tools.ietf.org/html/rfc1952\r
-    */\r
+    /**\r
+     * Decodes the message-body encoded by gzip\r
+     *\r
+     * The real decoding work is done by gzinflate() built-in function, this\r
+     * method only parses the header and checks data for compliance with\r
+     * RFC 1952\r
+     *\r
+     * @param string $data gzip-encoded data\r
+     *\r
+     * @return   string  decoded data\r
+     * @throws   HTTP_Request2_LogicException\r
+     * @throws   HTTP_Request2_MessageException\r
+     * @link     http://tools.ietf.org/html/rfc1952\r
+     */\r
     public static function decodeGzip($data)\r
     {\r
         $length = strlen($data);\r
@@ -603,13 +627,14 @@ class HTTP_Request2_Response
         return $unpacked;\r
     }\r
 \r
-   /**\r
-    * Decodes the message-body encoded by deflate\r
-    *\r
-    * @param    string  deflate-encoded data\r
-    * @return   string  decoded data\r
-    * @throws   HTTP_Request2_LogicException\r
-    */\r
+    /**\r
+     * Decodes the message-body encoded by deflate\r
+     *\r
+     * @param string $data deflate-encoded data\r
+     *\r
+     * @return   string  decoded data\r
+     * @throws   HTTP_Request2_LogicException\r
+     */\r
     public static function decodeDeflate($data)\r
     {\r
         if (!function_exists('gzuncompress')) {\r
diff --git a/extlib/HTTP/Request2/SOCKS5.php b/extlib/HTTP/Request2/SOCKS5.php
new file mode 100644 (file)
index 0000000..518289e
--- /dev/null
@@ -0,0 +1,158 @@
+<?php\r
+/**\r
+ * SOCKS5 proxy connection class\r
+ *\r
+ * PHP version 5\r
+ *\r
+ * LICENSE:\r
+ *\r
+ * Copyright (c) 2008-2012, Alexey Borzov <avb@php.net>\r
+ * All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions\r
+ * are met:\r
+ *\r
+ *    * Redistributions of source code must retain the above copyright\r
+ *      notice, this list of conditions and the following disclaimer.\r
+ *    * Redistributions in binary form must reproduce the above copyright\r
+ *      notice, this list of conditions and the following disclaimer in the\r
+ *      documentation and/or other materials provided with the distribution.\r
+ *    * The names of the authors may not be used to endorse or promote products\r
+ *      derived from this software without specific prior written permission.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS\r
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,\r
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\r
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\r
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\r
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\r
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\r
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ *\r
+ * @category HTTP\r
+ * @package  HTTP_Request2\r
+ * @author   Alexey Borzov <avb@php.net>\r
+ * @license  http://opensource.org/licenses/bsd-license.php New BSD License\r
+ * @version  SVN: $Id: SOCKS5.php 324953 2012-04-08 07:24:12Z avb $\r
+ * @link     http://pear.php.net/package/HTTP_Request2\r
+ */\r
+\r
+/** Socket wrapper class used by Socket Adapter */\r
+require_once 'HTTP/Request2/SocketWrapper.php';\r
+\r
+/**\r
+ * SOCKS5 proxy connection class (used by Socket Adapter)\r
+ *\r
+ * @category HTTP\r
+ * @package  HTTP_Request2\r
+ * @author   Alexey Borzov <avb@php.net>\r
+ * @license  http://opensource.org/licenses/bsd-license.php New BSD License\r
+ * @version  Release: 2.1.1\r
+ * @link     http://pear.php.net/package/HTTP_Request2\r
+ * @link     http://pear.php.net/bugs/bug.php?id=19332\r
+ * @link     http://tools.ietf.org/html/rfc1928\r
+ */\r
+class HTTP_Request2_SOCKS5 extends HTTP_Request2_SocketWrapper\r
+{\r
+    /**\r
+     * Constructor, tries to connect and authenticate to a SOCKS5 proxy\r
+     *\r
+     * @param string $address    Proxy address, e.g. 'tcp://localhost:1080'\r
+     * @param int    $timeout    Connection timeout (seconds)\r
+     * @param array  $sslOptions SSL context options\r
+     * @param string $username   Proxy user name\r
+     * @param string $password   Proxy password\r
+     *\r
+     * @throws HTTP_Request2_LogicException\r
+     * @throws HTTP_Request2_ConnectionException\r
+     * @throws HTTP_Request2_MessageException\r
+     */\r
+    public function __construct(\r
+        $address, $timeout = 10, array $sslOptions = array(),\r
+        $username = null, $password = null\r
+    ) {\r
+        parent::__construct($address, $timeout, $sslOptions);\r
+\r
+        if (strlen($username)) {\r
+            $request = pack('C4', 5, 2, 0, 2);\r
+        } else {\r
+            $request = pack('C3', 5, 1, 0);\r
+        }\r
+        $this->write($request);\r
+        $response = unpack('Cversion/Cmethod', $this->read(3));\r
+        if (5 != $response['version']) {\r
+            throw new HTTP_Request2_MessageException(\r
+                'Invalid version received from SOCKS5 proxy: ' . $response['version'],\r
+                HTTP_Request2_Exception::MALFORMED_RESPONSE\r
+            );\r
+        }\r
+        switch ($response['method']) {\r
+        case 2:\r
+            $this->performAuthentication($username, $password);\r
+        case 0:\r
+            break;\r
+        default:\r
+            throw new HTTP_Request2_ConnectionException(\r
+                "Connection rejected by proxy due to unsupported auth method"\r
+            );\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Performs username/password authentication for SOCKS5\r
+     *\r
+     * @param string $username Proxy user name\r
+     * @param string $password Proxy password\r
+     *\r
+     * @throws HTTP_Request2_ConnectionException\r
+     * @throws HTTP_Request2_MessageException\r
+     * @link http://tools.ietf.org/html/rfc1929\r
+     */\r
+    protected function performAuthentication($username, $password)\r
+    {\r
+        $request  = pack('C2', 1, strlen($username)) . $username\r
+                    . pack('C', strlen($password)) . $password;\r
+\r
+        $this->write($request);\r
+        $response = unpack('Cvn/Cstatus', $this->read(3));\r
+        if (1 != $response['vn'] || 0 != $response['status']) {\r
+            throw new HTTP_Request2_ConnectionException(\r
+                'Connection rejected by proxy due to invalid username and/or password'\r
+            );\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Connects to a remote host via proxy\r
+     *\r
+     * @param string $remoteHost Remote host\r
+     * @param int    $remotePort Remote port\r
+     *\r
+     * @throws HTTP_Request2_ConnectionException\r
+     * @throws HTTP_Request2_MessageException\r
+     */\r
+    public function connect($remoteHost, $remotePort)\r
+    {\r
+        $request = pack('C5', 0x05, 0x01, 0x00, 0x03, strlen($remoteHost))\r
+                   . $remoteHost . pack('n', $remotePort);\r
+\r
+        $this->write($request);\r
+        $response = unpack('Cversion/Creply/Creserved', $this->read(1024));\r
+        if (5 != $response['version'] || 0 != $response['reserved']) {\r
+            throw new HTTP_Request2_MessageException(\r
+                'Invalid response received from SOCKS5 proxy',\r
+                HTTP_Request2_Exception::MALFORMED_RESPONSE\r
+            );\r
+        } elseif (0 != $response['reply']) {\r
+            throw new HTTP_Request2_ConnectionException(\r
+                "Unable to connect to {$remoteHost}:{$remotePort} through SOCKS5 proxy",\r
+                0, $response['reply']\r
+            );\r
+        }\r
+    }\r
+}\r
+?>
\ No newline at end of file
diff --git a/extlib/HTTP/Request2/SocketWrapper.php b/extlib/HTTP/Request2/SocketWrapper.php
new file mode 100644 (file)
index 0000000..f56af40
--- /dev/null
@@ -0,0 +1,283 @@
+<?php\r
+/**\r
+ * Socket wrapper class used by Socket Adapter\r
+ *\r
+ * PHP version 5\r
+ *\r
+ * LICENSE:\r
+ *\r
+ * Copyright (c) 2008-2012, Alexey Borzov <avb@php.net>\r
+ * All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions\r
+ * are met:\r
+ *\r
+ *    * Redistributions of source code must retain the above copyright\r
+ *      notice, this list of conditions and the following disclaimer.\r
+ *    * Redistributions in binary form must reproduce the above copyright\r
+ *      notice, this list of conditions and the following disclaimer in the\r
+ *      documentation and/or other materials provided with the distribution.\r
+ *    * The names of the authors may not be used to endorse or promote products\r
+ *      derived from this software without specific prior written permission.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS\r
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,\r
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\r
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\r
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\r
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\r
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY\r
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ *\r
+ * @category HTTP\r
+ * @package  HTTP_Request2\r
+ * @author   Alexey Borzov <avb@php.net>\r
+ * @license  http://opensource.org/licenses/bsd-license.php New BSD License\r
+ * @version  SVN: $Id: SocketWrapper.php 324935 2012-04-07 07:10:50Z avb $\r
+ * @link     http://pear.php.net/package/HTTP_Request2\r
+ */\r
+\r
+/** Exception classes for HTTP_Request2 package */\r
+require_once 'HTTP/Request2/Exception.php';\r
+\r
+/**\r
+ * Socket wrapper class used by Socket Adapter\r
+ *\r
+ * Needed to properly handle connection errors, global timeout support and\r
+ * similar things. Loosely based on Net_Socket used by older HTTP_Request.\r
+ *\r
+ * @category HTTP\r
+ * @package  HTTP_Request2\r
+ * @author   Alexey Borzov <avb@php.net>\r
+ * @license  http://opensource.org/licenses/bsd-license.php New BSD License\r
+ * @version  Release: 2.1.1\r
+ * @link     http://pear.php.net/package/HTTP_Request2\r
+ * @link     http://pear.php.net/bugs/bug.php?id=19332\r
+ * @link     http://tools.ietf.org/html/rfc1928\r
+ */\r
+class HTTP_Request2_SocketWrapper\r
+{\r
+    /**\r
+     * PHP warning messages raised during stream_socket_client() call\r
+     * @var array\r
+     */\r
+    protected $connectionWarnings = array();\r
+\r
+    /**\r
+     * Connected socket\r
+     * @var resource\r
+     */\r
+    protected $socket;\r
+\r
+    /**\r
+     * Sum of start time and global timeout, exception will be thrown if request continues past this time\r
+     * @var  integer\r
+     */\r
+    protected $deadline;\r
+\r
+    /**\r
+     * Global timeout value, mostly for exception messages\r
+     * @var integer\r
+     */\r
+    protected $timeout;\r
+\r
+    /**\r
+     * Class constructor, tries to establish connection\r
+     *\r
+     * @param string $address    Address for stream_socket_client() call,\r
+     *                           e.g. 'tcp://localhost:80'\r
+     * @param int    $timeout    Connection timeout (seconds)\r
+     * @param array  $sslOptions SSL context options\r
+     *\r
+     * @throws HTTP_Request2_LogicException\r
+     * @throws HTTP_Request2_ConnectionException\r
+     */\r
+    public function __construct($address, $timeout, array $sslOptions = array())\r
+    {\r
+        $context = stream_context_create();\r
+        foreach ($sslOptions as $name => $value) {\r
+            if (!stream_context_set_option($context, 'ssl', $name, $value)) {\r
+                throw new HTTP_Request2_LogicException(\r
+                    "Error setting SSL context option '{$name}'"\r
+                );\r
+            }\r
+        }\r
+        set_error_handler(array($this, 'connectionWarningsHandler'));\r
+        $this->socket = stream_socket_client(\r
+            $address, $errno, $errstr, $timeout, STREAM_CLIENT_CONNECT, $context\r
+        );\r
+        restore_error_handler();\r
+        if (!$this->socket) {\r
+            $error = $errstr ? $errstr : implode("\n", $this->connectionWarnings);\r
+            throw new HTTP_Request2_ConnectionException(\r
+                "Unable to connect to {$address}. Error: {$error}", 0, $errno\r
+            );\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Destructor, disconnects socket\r
+     */\r
+    public function __destruct()\r
+    {\r
+        fclose($this->socket);\r
+    }\r
+\r
+    /**\r
+     * Wrapper around fread(), handles global request timeout\r
+     *\r
+     * @param int $length Reads up to this number of bytes\r
+     *\r
+     * @return   string Data read from socket\r
+     * @throws   HTTP_Request2_MessageException     In case of timeout\r
+     */\r
+    public function read($length)\r
+    {\r
+        if ($this->deadline) {\r
+            stream_set_timeout($this->socket, max($this->deadline - time(), 1));\r
+        }\r
+        $data = fread($this->socket, $length);\r
+        $this->checkTimeout();\r
+        return $data;\r
+    }\r
+\r
+    /**\r
+     * Reads until either the end of the socket or a newline, whichever comes first\r
+     *\r
+     * Strips the trailing newline from the returned data, handles global\r
+     * request timeout. Method idea borrowed from Net_Socket PEAR package.\r
+     *\r
+     * @param int $bufferSize buffer size to use for reading\r
+     *\r
+     * @return   string Available data up to the newline (not including newline)\r
+     * @throws   HTTP_Request2_MessageException     In case of timeout\r
+     */\r
+    public function readLine($bufferSize)\r
+    {\r
+        $line = '';\r
+        while (!feof($this->socket)) {\r
+            if ($this->deadline) {\r
+                stream_set_timeout($this->socket, max($this->deadline - time(), 1));\r
+            }\r
+            $line .= @fgets($this->socket, $bufferSize);\r
+            $this->checkTimeout();\r
+            if (substr($line, -1) == "\n") {\r
+                return rtrim($line, "\r\n");\r
+            }\r
+        }\r
+        return $line;\r
+    }\r
+\r
+    /**\r
+     * Wrapper around fwrite(), handles global request timeout\r
+     *\r
+     * @param string $data String to be written\r
+     *\r
+     * @return int\r
+     * @throws HTTP_Request2_MessageException\r
+     */\r
+    public function write($data)\r
+    {\r
+        if ($this->deadline) {\r
+            stream_set_timeout($this->socket, max($this->deadline - time(), 1));\r
+        }\r
+        $written = fwrite($this->socket, $data);\r
+        $this->checkTimeout();\r
+        // http://www.php.net/manual/en/function.fwrite.php#96951\r
+        if ($written < strlen($data)) {\r
+            throw new HTTP_Request2_MessageException('Error writing request');\r
+        }\r
+        return $written;\r
+    }\r
+\r
+    /**\r
+     * Tests for end-of-file on a socket\r
+     *\r
+     * @return bool\r
+     */\r
+    public function eof()\r
+    {\r
+        return feof($this->socket);\r
+    }\r
+\r
+    /**\r
+     * Sets request deadline\r
+     *\r
+     * @param int $deadline Exception will be thrown if request continues\r
+     *                      past this time\r
+     * @param int $timeout  Original request timeout value, to use in\r
+     *                      Exception message\r
+     */\r
+    public function setDeadline($deadline, $timeout)\r
+    {\r
+        $this->deadline = $deadline;\r
+        $this->timeout  = $timeout;\r
+    }\r
+\r
+    /**\r
+     * Turns on encryption on a socket\r
+     *\r
+     * @throws HTTP_Request2_ConnectionException\r
+     */\r
+    public function enableCrypto()\r
+    {\r
+        $modes = array(\r
+            STREAM_CRYPTO_METHOD_TLS_CLIENT,\r
+            STREAM_CRYPTO_METHOD_SSLv3_CLIENT,\r
+            STREAM_CRYPTO_METHOD_SSLv23_CLIENT,\r
+            STREAM_CRYPTO_METHOD_SSLv2_CLIENT\r
+        );\r
+\r
+        foreach ($modes as $mode) {\r
+            if (stream_socket_enable_crypto($this->socket, true, $mode)) {\r
+                return;\r
+            }\r
+        }\r
+        throw new HTTP_Request2_ConnectionException(\r
+            'Failed to enable secure connection when connecting through proxy'\r
+        );\r
+    }\r
+\r
+    /**\r
+     * Throws an Exception if stream timed out\r
+     *\r
+     * @throws HTTP_Request2_MessageException\r
+     */\r
+    protected function checkTimeout()\r
+    {\r
+        $info = stream_get_meta_data($this->socket);\r
+        if ($info['timed_out'] || $this->deadline && time() > $this->deadline) {\r
+            $reason = $this->deadline\r
+                ? "after {$this->timeout} second(s)"\r
+                : 'due to default_socket_timeout php.ini setting';\r
+            throw new HTTP_Request2_MessageException(\r
+                "Request timed out {$reason}", HTTP_Request2_Exception::TIMEOUT\r
+            );\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Error handler to use during stream_socket_client() call\r
+     *\r
+     * One stream_socket_client() call may produce *multiple* PHP warnings\r
+     * (especially OpenSSL-related), we keep them in an array to later use for\r
+     * the message of HTTP_Request2_ConnectionException\r
+     *\r
+     * @param int    $errno  error level\r
+     * @param string $errstr error message\r
+     *\r
+     * @return bool\r
+     */\r
+    protected function connectionWarningsHandler($errno, $errstr)\r
+    {\r
+        if ($errno & E_WARNING) {\r
+            array_unshift($this->connectionWarnings, $errstr);\r
+        }\r
+        return true;\r
+    }\r
+}\r
+?>\r
diff --git a/extlib/Net/URL.php b/extlib/Net/URL.php
deleted file mode 100644 (file)
index 3dcfef6..0000000
+++ /dev/null
@@ -1,485 +0,0 @@
-<?php
-// +-----------------------------------------------------------------------+
-// | Copyright (c) 2002-2004, Richard Heyes                                |
-// | All rights reserved.                                                  |
-// |                                                                       |
-// | Redistribution and use in source and binary forms, with or without    |
-// | modification, are permitted provided that the following conditions    |
-// | are met:                                                              |
-// |                                                                       |
-// | o Redistributions of source code must retain the above copyright      |
-// |   notice, this list of conditions and the following disclaimer.       |
-// | o Redistributions in binary form must reproduce the above copyright   |
-// |   notice, this list of conditions and the following disclaimer in the |
-// |   documentation and/or other materials provided with the distribution.|
-// | o The names of the authors may not be used to endorse or promote      |
-// |   products derived from this software without specific prior written  |
-// |   permission.                                                         |
-// |                                                                       |
-// | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   |
-// | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT     |
-// | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
-// | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  |
-// | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
-// | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT      |
-// | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
-// | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
-// | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT   |
-// | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
-// | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  |
-// |                                                                       |
-// +-----------------------------------------------------------------------+
-// | Author: Richard Heyes <richard at php net>                            |
-// +-----------------------------------------------------------------------+
-//
-// $Id: URL.php,v 1.49 2007/06/28 14:43:07 davidc Exp $
-//
-// Net_URL Class
-
-
-class Net_URL
-{
-    var $options = array('encode_query_keys' => false);
-    /**
-    * Full url
-    * @var string
-    */
-    var $url;
-
-    /**
-    * Protocol
-    * @var string
-    */
-    var $protocol;
-
-    /**
-    * Username
-    * @var string
-    */
-    var $username;
-
-    /**
-    * Password
-    * @var string
-    */
-    var $password;
-
-    /**
-    * Host
-    * @var string
-    */
-    var $host;
-
-    /**
-    * Port
-    * @var integer
-    */
-    var $port;
-
-    /**
-    * Path
-    * @var string
-    */
-    var $path;
-
-    /**
-    * Query string
-    * @var array
-    */
-    var $querystring;
-
-    /**
-    * Anchor
-    * @var string
-    */
-    var $anchor;
-
-    /**
-    * Whether to use []
-    * @var bool
-    */
-    var $useBrackets;
-
-    /**
-    * PHP4 Constructor
-    *
-    * @see __construct()
-    */
-    function Net_URL($url = null, $useBrackets = true)
-    {
-        $this->__construct($url, $useBrackets);
-    }
-
-    /**
-    * PHP5 Constructor
-    *
-    * Parses the given url and stores the various parts
-    * Defaults are used in certain cases
-    *
-    * @param string $url         Optional URL
-    * @param bool   $useBrackets Whether to use square brackets when
-    *                            multiple querystrings with the same name
-    *                            exist
-    */
-    function __construct($url = null, $useBrackets = true)
-    {
-        $this->url = $url;
-        $this->useBrackets = $useBrackets;
-
-        $this->initialize();
-    }
-
-    function initialize()
-    {
-        $HTTP_SERVER_VARS  = !empty($_SERVER) ? $_SERVER : $GLOBALS['HTTP_SERVER_VARS'];
-
-        $this->user        = '';
-        $this->pass        = '';
-        $this->host        = '';
-        $this->port        = 80;
-        $this->path        = '';
-        $this->querystring = array();
-        $this->anchor      = '';
-
-        // Only use defaults if not an absolute URL given
-        if (!preg_match('/^[a-z0-9]+:\/\//i', $this->url)) {
-            $this->protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on' ? 'https' : 'http');
-
-            /**
-            * Figure out host/port
-            */
-            if (!empty($HTTP_SERVER_VARS['HTTP_HOST']) && 
-                preg_match('/^(.*)(:([0-9]+))?$/U', $HTTP_SERVER_VARS['HTTP_HOST'], $matches)) 
-            {
-                $host = $matches[1];
-                if (!empty($matches[3])) {
-                    $port = $matches[3];
-                } else {
-                    $port = $this->getStandardPort($this->protocol);
-                }
-            }
-
-            $this->user        = '';
-            $this->pass        = '';
-            $this->host        = !empty($host) ? $host : (isset($HTTP_SERVER_VARS['SERVER_NAME']) ? $HTTP_SERVER_VARS['SERVER_NAME'] : 'localhost');
-            $this->port        = !empty($port) ? $port : (isset($HTTP_SERVER_VARS['SERVER_PORT']) ? $HTTP_SERVER_VARS['SERVER_PORT'] : $this->getStandardPort($this->protocol));
-            $this->path        = !empty($HTTP_SERVER_VARS['PHP_SELF']) ? $HTTP_SERVER_VARS['PHP_SELF'] : '/';
-            $this->querystring = isset($HTTP_SERVER_VARS['QUERY_STRING']) ? $this->_parseRawQuerystring($HTTP_SERVER_VARS['QUERY_STRING']) : null;
-            $this->anchor      = '';
-        }
-
-        // Parse the url and store the various parts
-        if (!empty($this->url)) {
-            $urlinfo = parse_url($this->url);
-
-            // Default querystring
-            $this->querystring = array();
-
-            foreach ($urlinfo as $key => $value) {
-                switch ($key) {
-                    case 'scheme':
-                        $this->protocol = $value;
-                        $this->port     = $this->getStandardPort($value);
-                        break;
-
-                    case 'user':
-                    case 'pass':
-                    case 'host':
-                    case 'port':
-                        $this->$key = $value;
-                        break;
-
-                    case 'path':
-                        if ($value{0} == '/') {
-                            $this->path = $value;
-                        } else {
-                            $path = dirname($this->path) == DIRECTORY_SEPARATOR ? '' : dirname($this->path);
-                            $this->path = sprintf('%s/%s', $path, $value);
-                        }
-                        break;
-
-                    case 'query':
-                        $this->querystring = $this->_parseRawQueryString($value);
-                        break;
-
-                    case 'fragment':
-                        $this->anchor = $value;
-                        break;
-                }
-            }
-        }
-    }
-    /**
-    * Returns full url
-    *
-    * @return string Full url
-    * @access public
-    */
-    function getURL()
-    {
-        $querystring = $this->getQueryString();
-
-        $this->url = $this->protocol . '://'
-                   . $this->user . (!empty($this->pass) ? ':' : '')
-                   . $this->pass . (!empty($this->user) ? '@' : '')
-                   . $this->host . ($this->port == $this->getStandardPort($this->protocol) ? '' : ':' . $this->port)
-                   . $this->path
-                   . (!empty($querystring) ? '?' . $querystring : '')
-                   . (!empty($this->anchor) ? '#' . $this->anchor : '');
-
-        return $this->url;
-    }
-
-    /**
-    * Adds or updates a querystring item (URL parameter).
-    * Automatically encodes parameters with rawurlencode() if $preencoded
-    *  is false.
-    * You can pass an array to $value, it gets mapped via [] in the URL if
-    * $this->useBrackets is activated.
-    *
-    * @param  string $name       Name of item
-    * @param  string $value      Value of item
-    * @param  bool   $preencoded Whether value is urlencoded or not, default = not
-    * @access public
-    */
-    function addQueryString($name, $value, $preencoded = false)
-    {
-        if ($this->getOption('encode_query_keys')) {
-            $name = rawurlencode($name);
-        }
-
-        if ($preencoded) {
-            $this->querystring[$name] = $value;
-        } else {
-            $this->querystring[$name] = is_array($value) ? array_map('rawurlencode', $value): rawurlencode($value);
-        }
-    }
-
-    /**
-    * Removes a querystring item
-    *
-    * @param  string $name Name of item
-    * @access public
-    */
-    function removeQueryString($name)
-    {
-        if ($this->getOption('encode_query_keys')) {
-            $name = rawurlencode($name);
-        }
-
-        if (isset($this->querystring[$name])) {
-            unset($this->querystring[$name]);
-        }
-    }
-
-    /**
-    * Sets the querystring to literally what you supply
-    *
-    * @param  string $querystring The querystring data. Should be of the format foo=bar&x=y etc
-    * @access public
-    */
-    function addRawQueryString($querystring)
-    {
-        $this->querystring = $this->_parseRawQueryString($querystring);
-    }
-
-    /**
-    * Returns flat querystring
-    *
-    * @return string Querystring
-    * @access public
-    */
-    function getQueryString()
-    {
-        if (!empty($this->querystring)) {
-            foreach ($this->querystring as $name => $value) {
-                // Encode var name
-                $name = rawurlencode($name);
-
-                if (is_array($value)) {
-                    foreach ($value as $k => $v) {
-                        $querystring[] = $this->useBrackets ? sprintf('%s[%s]=%s', $name, $k, $v) : ($name . '=' . $v);
-                    }
-                } elseif (!is_null($value)) {
-                    $querystring[] = $name . '=' . $value;
-                } else {
-                    $querystring[] = $name;
-                }
-            }
-            $querystring = implode(ini_get('arg_separator.output'), $querystring);
-        } else {
-            $querystring = '';
-        }
-
-        return $querystring;
-    }
-
-    /**
-    * Parses raw querystring and returns an array of it
-    *
-    * @param  string  $querystring The querystring to parse
-    * @return array                An array of the querystring data
-    * @access private
-    */
-    function _parseRawQuerystring($querystring)
-    {
-        $parts  = preg_split('/[' . preg_quote(ini_get('arg_separator.input'), '/') . ']/', $querystring, -1, PREG_SPLIT_NO_EMPTY);
-        $return = array();
-
-        foreach ($parts as $part) {
-            if (strpos($part, '=') !== false) {
-                $value = substr($part, strpos($part, '=') + 1);
-                $key   = substr($part, 0, strpos($part, '='));
-            } else {
-                $value = null;
-                $key   = $part;
-            }
-
-            if (!$this->getOption('encode_query_keys')) {
-                $key = rawurldecode($key);
-            }
-
-            if (preg_match('#^(.*)\[([0-9a-z_-]*)\]#i', $key, $matches)) {
-                $key = $matches[1];
-                $idx = $matches[2];
-
-                // Ensure is an array
-                if (empty($return[$key]) || !is_array($return[$key])) {
-                    $return[$key] = array();
-                }
-
-                // Add data
-                if ($idx === '') {
-                    $return[$key][] = $value;
-                } else {
-                    $return[$key][$idx] = $value;
-                }
-            } elseif (!$this->useBrackets AND !empty($return[$key])) {
-                $return[$key]   = (array)$return[$key];
-                $return[$key][] = $value;
-            } else {
-                $return[$key] = $value;
-            }
-        }
-
-        return $return;
-    }
-
-    /**
-    * Resolves //, ../ and ./ from a path and returns
-    * the result. Eg:
-    *
-    * /foo/bar/../boo.php    => /foo/boo.php
-    * /foo/bar/../../boo.php => /boo.php
-    * /foo/bar/.././/boo.php => /foo/boo.php
-    *
-    * This method can also be called statically.
-    *
-    * @param  string $path URL path to resolve
-    * @return string      The result
-    */
-    function resolvePath($path)
-    {
-        $path = explode('/', str_replace('//', '/', $path));
-
-        for ($i=0; $i<count($path); $i++) {
-            if ($path[$i] == '.') {
-                unset($path[$i]);
-                $path = array_values($path);
-                $i--;
-
-            } elseif ($path[$i] == '..' AND ($i > 1 OR ($i == 1 AND $path[0] != '') ) ) {
-                unset($path[$i]);
-                unset($path[$i-1]);
-                $path = array_values($path);
-                $i -= 2;
-
-            } elseif ($path[$i] == '..' AND $i == 1 AND $path[0] == '') {
-                unset($path[$i]);
-                $path = array_values($path);
-                $i--;
-
-            } else {
-                continue;
-            }
-        }
-
-        return implode('/', $path);
-    }
-
-    /**
-    * Returns the standard port number for a protocol
-    *
-    * @param  string  $scheme The protocol to lookup
-    * @return integer         Port number or NULL if no scheme matches
-    *
-    * @author Philippe Jausions <Philippe.Jausions@11abacus.com>
-    */
-    function getStandardPort($scheme)
-    {
-        switch (strtolower($scheme)) {
-            case 'http':    return 80;
-            case 'https':   return 443;
-            case 'ftp':     return 21;
-            case 'imap':    return 143;
-            case 'imaps':   return 993;
-            case 'pop3':    return 110;
-            case 'pop3s':   return 995;
-            default:        return null;
-       }
-    }
-
-    /**
-    * Forces the URL to a particular protocol
-    *
-    * @param string  $protocol Protocol to force the URL to
-    * @param integer $port     Optional port (standard port is used by default)
-    */
-    function setProtocol($protocol, $port = null)
-    {
-        $this->protocol = $protocol;
-        $this->port     = is_null($port) ? $this->getStandardPort($protocol) : $port;
-    }
-
-    /**
-     * Set an option
-     *
-     * This function set an option
-     * to be used thorough the script.
-     *
-     * @access public
-     * @param  string $optionName  The optionname to set
-     * @param  string $value       The value of this option.
-     */
-    function setOption($optionName, $value)
-    {
-        if (!array_key_exists($optionName, $this->options)) {
-            return false;
-        }
-
-        $this->options[$optionName] = $value;
-        $this->initialize();
-    }
-
-    /**
-     * Get an option
-     *
-     * This function gets an option
-     * from the $this->options array
-     * and return it's value.
-     *
-     * @access public
-     * @param  string $opionName  The name of the option to retrieve
-     * @see    $this->options
-     */
-    function getOption($optionName)
-    {
-        if (!isset($this->options[$optionName])) {
-            return false;
-        }
-
-        return $this->options[$optionName];
-    }
-
-}
-?>
old mode 100644 (file)
new mode 100755 (executable)
index f7fbcd9..9989404
@@ -18,9 +18,9 @@
  *   * Redistributions in binary form must reproduce the above copyright
  *     notice, this list of conditions and the following disclaimer in
  *     the documentation and/or other materials provided with the distribution.
- *   * Neither the name of the PHP_LexerGenerator nor the names of its
- *     contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
+ *   * Neither the name of the Net_URL2 nor the names of its contributors may
+ *     be used to endorse or promote products derived from this software
+ *     without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  *
  * @category  Networking
  * @package   Net_URL2
- * @author    Christian Schmidt <chsc@peytz.dk>
- * @copyright 2007-2008 Peytz & Co. A/S
+ * @author    Christian Schmidt <schmidt@php.net>
+ * @copyright 2007-2009 Peytz & Co. A/S
  * @license   http://www.opensource.org/licenses/bsd-license.php New BSD License
- * @version   CVS: $Id: URL2.php 286661 2009-08-02 12:50:54Z schmidt $
+ * @version   CVS: $Id: URL2.php 309223 2011-03-14 14:26:32Z till $
  * @link      http://www.rfc-editor.org/rfc/rfc3986.txt
  */
 
@@ -48,8 +48,8 @@
  *
  * @category  Networking
  * @package   Net_URL2
- * @author    Christian Schmidt <chsc@peytz.dk>
- * @copyright 2007-2008 Peytz & Co. ApS
+ * @author    Christian Schmidt <schmidt@php.net>
+ * @copyright 2007-2009 Peytz & Co. A/S
  * @license   http://www.opensource.org/licenses/bsd-license.php New BSD License
  * @version   Release: @package_version@
  * @link      http://pear.php.net/package/Net_URL2
@@ -74,15 +74,13 @@ class Net_URL2
 
     /**
      * Query variable separators when parsing the query string. Every character
-     * is considered a separator. Default is specified by the
-     * arg_separator.input php.ini setting (this defaults to "&").
+     * is considered a separator. Default is "&".
      */
     const OPTION_SEPARATOR_INPUT = 'input_separator';
 
     /**
      * Query variable separator used when generating the query string. Default
-     * is specified by the arg_separator.output php.ini setting (this defaults
-     * to "&").
+     * is "&".
      */
     const OPTION_SEPARATOR_OUTPUT = 'output_separator';
 
@@ -93,8 +91,8 @@ class Net_URL2
         self::OPTION_STRICT           => true,
         self::OPTION_USE_BRACKETS     => true,
         self::OPTION_ENCODE_KEYS      => true,
-        self::OPTION_SEPARATOR_INPUT  => 'x&',
-        self::OPTION_SEPARATOR_OUTPUT => 'x&',
+        self::OPTION_SEPARATOR_INPUT  => '&',
+        self::OPTION_SEPARATOR_OUTPUT => '&',
         );
 
     /**
@@ -113,7 +111,7 @@ class Net_URL2
     private $_host = false;
 
     /**
-     * @var  int|bool
+     * @var  string|bool
      */
     private $_port = false;
 
@@ -137,41 +135,19 @@ class Net_URL2
      *
      * @param string $url     an absolute or relative URL
      * @param array  $options an array of OPTION_xxx constants
+     *
+     * @return $this
+     * @uses   self::parseUrl()
      */
-    public function __construct($url, $options = null)
+    public function __construct($url, array $options = array())
     {
-        $this->setOption(self::OPTION_SEPARATOR_INPUT,
-                         ini_get('arg_separator.input'));
-        $this->setOption(self::OPTION_SEPARATOR_OUTPUT,
-                         ini_get('arg_separator.output'));
-        if (is_array($options)) {
-            foreach ($options as $optionName => $value) {
-                $this->setOption($optionName, $value);
+        foreach ($options as $optionName => $value) {
+            if (array_key_exists($optionName, $this->_options)) {
+                $this->_options[$optionName] = $value;
             }
         }
 
-        if (preg_match('@^([a-z][a-z0-9.+-]*):@i', $url, $reg)) {
-            $this->_scheme = $reg[1];
-            $url = substr($url, strlen($reg[0]));
-        }
-
-        if (preg_match('@^//([^/#?]+)@', $url, $reg)) {
-            $this->setAuthority($reg[1]);
-            $url = substr($url, strlen($reg[0]));
-        }
-
-        $i = strcspn($url, '?#');
-        $this->_path = substr($url, 0, $i);
-        $url = substr($url, $i);
-
-        if (preg_match('@^\?([^#]*)@', $url, $reg)) {
-            $this->_query = $reg[1];
-            $url = substr($url, strlen($reg[0]));
-        }
-
-        if ($url) {
-            $this->_fragment = substr($url, 1);
-        }
+        $this->parseUrl($url);
     }
 
     /**
@@ -191,13 +167,13 @@ class Net_URL2
             $this->$method($arg);
         }
     }
-    
+
     /**
      * Magic Getter.
      *
-     * This is the magic get method to retrieve the private variable 
+     * This is the magic get method to retrieve the private variable
      * that was set by either __set() or it's setter...
-     * 
+     *
      * @param  string $var         The property name to retrieve.
      * @return mixed  $this->$var  Either a boolean false if the
      *                             property is not set or the value
@@ -209,10 +185,10 @@ class Net_URL2
         if (method_exists($this, $method)) {
             return $this->$method();
         }
-        
+
         return false;
     }
-    
+
     /**
      * Returns the scheme, e.g. "http" or "urn", or false if there is no
      * scheme specified, i.e. if this is a relative URL.
@@ -232,12 +208,13 @@ class Net_URL2
      *                            scheme specified, i.e. if this is a relative
      *                            URL
      *
-     * @return void
+     * @return $this
      * @see    getScheme()
      */
     public function setScheme($scheme)
     {
         $this->_scheme = $scheme;
+        return $this;
     }
 
     /**
@@ -286,7 +263,7 @@ class Net_URL2
      * @param string|bool $userinfo userinfo or username
      * @param string|bool $password optional password, or false
      *
-     * @return void
+     * @return $this
      */
     public function setUserinfo($userinfo, $password = false)
     {
@@ -294,6 +271,7 @@ class Net_URL2
         if ($password !== false) {
             $this->_userinfo .= ':' . $password;
         }
+        return $this;
     }
 
     /**
@@ -313,18 +291,19 @@ class Net_URL2
      *
      * @param string|bool $host a hostname, an IP address, or false
      *
-     * @return void
+     * @return $this
      */
     public function setHost($host)
     {
         $this->_host = $host;
+        return $this;
     }
 
     /**
      * Returns the port number, or false if there is no port number specified,
      * i.e. if the default port is to be used.
      *
-     * @return  int|bool
+     * @return  string|bool
      */
     public function getPort()
     {
@@ -335,13 +314,14 @@ class Net_URL2
      * Sets the port number. Specify false if there is no port number specified,
      * i.e. if the default port is to be used.
      *
-     * @param int|bool $port a port number, or false
+     * @param string|bool $port a port number, or false
      *
-     * @return void
+     * @return $this
      */
     public function setPort($port)
     {
-        $this->_port = intval($port);
+        $this->_port = $port;
+        return $this;
     }
 
     /**
@@ -379,7 +359,7 @@ class Net_URL2
      *                                with userinfo prefixed and port number
      *                                appended, e.g. "foo:bar@example.org:81".
      *
-     * @return void
+     * @return $this
      */
     public function setAuthority($authority)
     {
@@ -393,9 +373,10 @@ class Net_URL2
 
             $this->_host = $reg[3];
             if (isset($reg[5])) {
-                $this->_port = intval($reg[5]);
+                $this->_port = $reg[5];
             }
         }
+        return $this;
     }
 
     /**
@@ -413,11 +394,12 @@ class Net_URL2
      *
      * @param string $path a path
      *
-     * @return void
+     * @return $this
      */
     public function setPath($path)
     {
         $this->_path = $path;
+        return $this;
     }
 
     /**
@@ -438,12 +420,13 @@ class Net_URL2
      *
      * @param string|bool $query a query string, e.g. "foo=1&bar=2"
      *
-     * @return void
-     * @see   self::setQueryVariables()
+     * @return $this
+     * @see    self::setQueryVariables()
      */
     public function setQuery($query)
     {
         $this->_query = $query;
+        return $this;
     }
 
     /**
@@ -462,11 +445,12 @@ class Net_URL2
      * @param string|bool $fragment a fragment excluding the leading "#", or
      *                              false
      *
-     * @return void
+     * @return $this
      */
     public function setFragment($fragment)
     {
         $this->_fragment = $fragment;
+        return $this;
     }
 
     /**
@@ -532,33 +516,19 @@ class Net_URL2
      *
      * @param array $array (name => value) array
      *
-     * @return void
+     * @return $this
      */
     public function setQueryVariables(array $array)
     {
         if (!$array) {
             $this->_query = false;
         } else {
-            foreach ($array as $name => $value) {
-                if ($this->getOption(self::OPTION_ENCODE_KEYS)) {
-                    $name = self::urlencode($name);
-                }
-
-                if (is_array($value)) {
-                    foreach ($value as $k => $v) {
-                        $parts[] = $this->getOption(self::OPTION_USE_BRACKETS)
-                            ? sprintf('%s[%s]=%s', $name, $k, $v)
-                            : ($name . '=' . $v);
-                    }
-                } elseif (!is_null($value)) {
-                    $parts[] = $name . '=' . self::urlencode($value);
-                } else {
-                    $parts[] = $name;
-                }
-            }
-            $this->_query = implode($this->getOption(self::OPTION_SEPARATOR_OUTPUT),
-                                    $parts);
+            $this->_query = $this->buildQuery(
+                $array,
+                $this->getOption(self::OPTION_SEPARATOR_OUTPUT)
+            );
         }
+        return $this;
     }
 
     /**
@@ -567,13 +537,14 @@ class Net_URL2
      * @param string $name  variable name
      * @param mixed  $value variable value
      *
-     * @return  array
+     * @return $this
      */
     public function setQueryVariable($name, $value)
     {
         $array = $this->getQueryVariables();
         $array[$name] = $value;
         $this->setQueryVariables($array);
+        return $this;
     }
 
     /**
@@ -785,7 +756,7 @@ class Net_URL2
 
         // Make sure not to be trapped in an infinite loop due to a bug in this
         // method
-        $j = 0; 
+        $j = 0;
         while ($path && $j++ < 100) {
             if (substr($path, 0, 2) == './') {
                 // Step 2.A
@@ -832,15 +803,16 @@ class Net_URL2
     public static function urlencode($string)
     {
        $encoded = rawurlencode($string);
-       // This is only necessary in PHP < 5.3.
-       $encoded = str_replace('%7E', '~', $encoded);
-       return $encoded;
+
+        // This is only necessary in PHP < 5.3.
+        $encoded = str_replace('%7E', '~', $encoded);
+        return $encoded;
     }
 
     /**
      * Returns a Net_URL2 instance representing the canonical URL of the
      * currently executing PHP script.
-     * 
+     *
      * @return  string
      */
     public static function getCanonical()
@@ -854,7 +826,7 @@ class Net_URL2
         $url = new self($_SERVER['PHP_SELF']);
         $url->_scheme = isset($_SERVER['HTTPS']) ? 'https' : 'http';
         $url->_host   = $_SERVER['SERVER_NAME'];
-        $port = intval($_SERVER['SERVER_PORT']);
+        $port = $_SERVER['SERVER_PORT'];
         if ($url->_scheme == 'http' && $port != 80 ||
             $url->_scheme == 'https' && $port != 443) {
 
@@ -895,34 +867,76 @@ class Net_URL2
     }
 
     /**
-     * Sets the specified option.
+     * Returns the value of the specified option.
      *
-     * @param string $optionName a self::OPTION_ constant
-     * @param mixed  $value      option value  
+     * @param string $optionName The name of the option to retrieve
      *
-     * @return void
-     * @see  self::OPTION_STRICT
-     * @see  self::OPTION_USE_BRACKETS
-     * @see  self::OPTION_ENCODE_KEYS
+     * @return  mixed
      */
-    function setOption($optionName, $value)
+    public function getOption($optionName)
     {
-        if (!array_key_exists($optionName, $this->_options)) {
-            return false;
-        }
-        $this->_options[$optionName] = $value;
+        return isset($this->_options[$optionName])
+            ? $this->_options[$optionName] : false;
     }
 
     /**
-     * Returns the value of the specified option.
+     * A simple version of http_build_query in userland. The encoded string is
+     * percentage encoded according to RFC 3986.
      *
-     * @param string $optionName The name of the option to retrieve
+     * @param array  $data      An array, which has to be converted into
+     *                          QUERY_STRING. Anything is possible.
+     * @param string $seperator See {@link self::OPTION_SEPARATOR_OUTPUT}
+     * @param string $key       For stacked values (arrays in an array).
      *
-     * @return  mixed
+     * @return string
      */
-    function getOption($optionName)
+    protected function buildQuery(array $data, $separator, $key = null)
     {
-        return isset($this->_options[$optionName])
-            ? $this->_options[$optionName] : false;
+        $query = array();
+        foreach ($data as $name => $value) {
+            if ($this->getOption(self::OPTION_ENCODE_KEYS) === true) {
+                $name = rawurlencode($name);
+            }
+            if ($key !== null) {
+                if ($this->getOption(self::OPTION_USE_BRACKETS) === true) {
+                    $name = $key . '[' . $name . ']';
+                } else {
+                    $name = $key;
+                }
+            }
+            if (is_array($value)) {
+                $query[] = $this->buildQuery($value, $separator, $name);
+            } else {
+                $query[] = $name . '=' . rawurlencode($value);
+            }
+        }
+        return implode($separator, $query);
+    }
+
+    /**
+     * This method uses a funky regex to parse the url into the designated parts.
+     *
+     * @param string $url
+     *
+     * @return void
+     * @uses   self::$_scheme, self::setAuthority(), self::$_path, self::$_query,
+     *         self::$_fragment
+     * @see    self::__construct()
+     */
+    protected function parseUrl($url)
+    {
+        // The regular expression is copied verbatim from RFC 3986, appendix B.
+        // The expression does not validate the URL but matches any string.
+        preg_match('!^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?!',
+                   $url,
+                   $matches);
+
+        // "path" is always present (possibly as an empty string); the rest
+        // are optional.
+        $this->_scheme   = !empty($matches[1]) ? $matches[2] : false;
+        $this->setAuthority(!empty($matches[3]) ? $matches[4] : false);
+        $this->_path     = $matches[5];
+        $this->_query    = !empty($matches[6]) ? $matches[7] : false;
+        $this->_fragment = !empty($matches[8]) ? $matches[9] : false;
     }
 }
diff --git a/extlib/data/generate-list.php b/extlib/data/generate-list.php
new file mode 100644 (file)
index 0000000..839266b
--- /dev/null
@@ -0,0 +1,98 @@
+<?php\r
+/**\r
+ * Helper file for downloading Public Suffix List and converting it to PHP array\r
+ *\r
+ * You can run this script to update PSL to the current version instead of\r
+ * waiting for a new release of HTTP_Request2.\r
+ *\r
+ * @version SVN: $Id: generate-list.php 308480 2011-02-19 11:27:13Z avb $\r
+ */\r
+\r
+/** URL to download Public Suffix List from */\r
+define('LIST_URL',    'http://mxr.mozilla.org/mozilla-central/source/netwerk/dns/effective_tld_names.dat?raw=1');\r
+/** Name of PHP file to write */\r
+define('OUTPUT_FILE', dirname(__FILE__) . '/public-suffix-list.php');\r
+\r
+require_once 'HTTP/Request2.php';\r
+\r
+function buildSubdomain(&$node, $tldParts)\r
+{\r
+    $part = trim(array_pop($tldParts));\r
+\r
+    if (!array_key_exists($part, $node)) {\r
+        $node[$part] = array();\r
+    }\r
+\r
+    if (0 < count($tldParts)) {\r
+        buildSubdomain($node[$part], $tldParts);\r
+    }\r
+}\r
+\r
+function writeNode($fp, $valueTree, $key = null, $indent = 0)\r
+{\r
+    if (is_null($key)) {\r
+        fwrite($fp, "return ");\r
+\r
+    } else {\r
+        fwrite($fp, str_repeat(' ', $indent) . "'$key' => ");\r
+    }\r
+\r
+    if (0 == ($count = count($valueTree))) {\r
+        fwrite($fp, 'true');\r
+    } else {\r
+        fwrite($fp, "array(\n");\r
+        for ($keys = array_keys($valueTree), $i = 0; $i < $count; $i++) {\r
+            writeNode($fp, $valueTree[$keys[$i]], $keys[$i], $indent + 1);\r
+            if ($i + 1 != $count) {\r
+                fwrite($fp, ",\n");\r
+            } else {\r
+                fwrite($fp, "\n");\r
+            }\r
+        }\r
+        fwrite($fp, str_repeat(' ', $indent) . ")");\r
+    }\r
+}\r
+\r
+\r
+try {\r
+    $request  = new HTTP_Request2(LIST_URL);\r
+    $response = $request->send();\r
+    if (200 != $response->getStatus()) {\r
+        throw new Exception("List download URL returned status: " .\r
+                            $response->getStatus() . ' ' . $response->getReasonPhrase());\r
+    }\r
+    $list     = $response->getBody();\r
+    if (false === strpos($list, 'The Original Code is the Public Suffix List.')) {\r
+        throw new Exception("List download URL does not contain expected phrase");\r
+    }\r
+    if (!($fp = @fopen(OUTPUT_FILE, 'wt'))) {\r
+        throw new Exception("Unable to open " . OUTPUT_FILE);\r
+    }\r
+\r
+} catch (Exception $e) {\r
+    die($e->getMessage());\r
+}\r
+\r
+$tldTree = array();\r
+$license = true;\r
+\r
+fwrite($fp, "<?php\n");\r
+\r
+foreach (array_filter(array_map('trim', explode("\n", $list))) as $line) {\r
+    if ('//' != substr($line, 0, 2)) {\r
+        buildSubdomain($tldTree, explode('.', $line));\r
+\r
+    } elseif ($license) {\r
+        fwrite($fp, $line . "\n");\r
+\r
+        if (0 === strpos($line, "// ***** END LICENSE BLOCK")) {\r
+            $license = false;\r
+            fwrite($fp, "\n");\r
+        }\r
+    }\r
+}\r
+\r
+writeNode($fp, $tldTree);\r
+fwrite($fp, ";\n?>");\r
+fclose($fp);\r
+?>
\ No newline at end of file
diff --git a/extlib/data/public-suffix-list.php b/extlib/data/public-suffix-list.php
new file mode 100644 (file)
index 0000000..77d9fd0
--- /dev/null
@@ -0,0 +1,4831 @@
+<?php\r
+// ***** BEGIN LICENSE BLOCK *****\r
+// Version: MPL 1.1/GPL 2.0/LGPL 2.1\r
+//\r
+// The contents of this file are subject to the Mozilla Public License Version\r
+// 1.1 (the "License"); you may not use this file except in compliance with\r
+// the License. You may obtain a copy of the License at\r
+// http://www.mozilla.org/MPL/\r
+//\r
+// Software distributed under the License is distributed on an "AS IS" basis,\r
+// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License\r
+// for the specific language governing rights and limitations under the\r
+// License.\r
+//\r
+// The Original Code is the Public Suffix List.\r
+//\r
+// The Initial Developer of the Original Code is\r
+// Jo Hermans <jo.hermans@gmail.com>.\r
+// Portions created by the Initial Developer are Copyright (C) 2007\r
+// the Initial Developer. All Rights Reserved.\r
+//\r
+// Contributor(s):\r
+//   Ruben Arakelyan <ruben@rubenarakelyan.com>\r
+//   Gervase Markham <gerv@gerv.net>\r
+//   Pamela Greene <pamg.bugs@gmail.com>\r
+//   David Triendl <david@triendl.name>\r
+//   Jothan Frakes <jothan@gmail.com>\r
+//   The kind representatives of many TLD registries\r
+//\r
+// Alternatively, the contents of this file may be used under the terms of\r
+// either the GNU General Public License Version 2 or later (the "GPL"), or\r
+// the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),\r
+// in which case the provisions of the GPL or the LGPL are applicable instead\r
+// of those above. If you wish to allow use of your version of this file only\r
+// under the terms of either the GPL or the LGPL, and not to allow others to\r
+// use your version of this file under the terms of the MPL, indicate your\r
+// decision by deleting the provisions above and replace them with the notice\r
+// and other provisions required by the GPL or the LGPL. If you do not delete\r
+// the provisions above, a recipient may use your version of this file under\r
+// the terms of any one of the MPL, the GPL or the LGPL.\r
+//\r
+// ***** END LICENSE BLOCK *****\r
+\r
+return array(\r
+ 'ac' => array(\r
+  'com' => true,\r
+  'edu' => true,\r
+  'gov' => true,\r
+  'net' => true,\r
+  'mil' => true,\r
+  'org' => true\r
+ ),\r
+ 'ad' => array(\r
+  'nom' => true\r
+ ),\r
+ 'ae' => array(\r
+  'co' => true,\r
+  'net' => true,\r
+  'org' => true,\r
+  'sch' => true,\r
+  'ac' => true,\r
+  'gov' => true,\r
+  'mil' => true\r
+ ),\r
+ 'aero' => array(\r
+  'accident-investigation' => true,\r
+  'accident-prevention' => true,\r
+  'aerobatic' => true,\r
+  'aeroclub' => true,\r
+  'aerodrome' => true,\r
+  'agents' => true,\r
+  'aircraft' => true,\r
+  'airline' => true,\r
+  'airport' => true,\r
+  'air-surveillance' => true,\r
+  'airtraffic' => true,\r
+  'air-traffic-control' => true,\r
+  'ambulance' => true,\r
+  'amusement' => true,\r
+  'association' => true,\r
+  'author' => true,\r
+  'ballooning' => true,\r
+  'broker' => true,\r
+  'caa' => true,\r
+  'cargo' => true,\r
+  'catering' => true,\r
+  'certification' => true,\r
+  'championship' => true,\r
+  'charter' => true,\r
+  'civilaviation' => true,\r
+  'club' => true,\r
+  'conference' => true,\r
+  'consultant' => true,\r
+  'consulting' => true,\r
+  'control' => true,\r
+  'council' => true,\r
+  'crew' => true,\r
+  'design' => true,\r
+  'dgca' => true,\r
+  'educator' => true,\r
+  'emergency' => true,\r
+  'engine' => true,\r
+  'engineer' => true,\r
+  'entertainment' => true,\r
+  'equipment' => true,\r
+  'exchange' => true,\r
+  'express' => true,\r
+  'federation' => true,\r
+  'flight' => true,\r
+  'freight' => true,\r
+  'fuel' => true,\r
+  'gliding' => true,\r
+  'government' => true,\r
+  'groundhandling' => true,\r
+  'group' => true,\r
+  'hanggliding' => true,\r
+  'homebuilt' => true,\r
+  'insurance' => true,\r
+  'journal' => true,\r
+  'journalist' => true,\r
+  'leasing' => true,\r
+  'logistics' => true,\r
+  'magazine' => true,\r
+  'maintenance' => true,\r
+  'marketplace' => true,\r
+  'media' => true,\r
+  'microlight' => true,\r
+  'modelling' => true,\r
+  'navigation' => true,\r
+  'parachuting' => true,\r
+  'paragliding' => true,\r
+  'passenger-association' => true,\r
+  'pilot' => true,\r
+  'press' => true,\r
+  'production' => true,\r
+  'recreation' => true,\r
+  'repbody' => true,\r
+  'res' => true,\r
+  'research' => true,\r
+  'rotorcraft' => true,\r
+  'safety' => true,\r
+  'scientist' => true,\r
+  'services' => true,\r
+  'show' => true,\r
+  'skydiving' => true,\r
+  'software' => true,\r
+  'student' => true,\r
+  'taxi' => true,\r
+  'trader' => true,\r
+  'trading' => true,\r
+  'trainer' => true,\r
+  'union' => true,\r
+  'workinggroup' => true,\r
+  'works' => true\r
+ ),\r
+ 'af' => array(\r
+  'gov' => true,\r
+  'com' => true,\r
+  'org' => true,\r
+  'net' => true,\r
+  'edu' => true\r
+ ),\r
+ 'ag' => array(\r
+  'com' => true,\r
+  'org' => true,\r
+  'net' => true,\r
+  'co' => true,\r
+  'nom' => true\r
+ ),\r
+ 'ai' => array(\r
+  'off' => true,\r
+  'com' => true,\r
+  'net' => true,\r
+  'org' => true\r
+ ),\r
+ 'al' => array(\r
+  'com' => true,\r
+  'edu' => true,\r
+  'gov' => true,\r
+  'mil' => true,\r
+  'net' => true,\r
+  'org' => true\r
+ ),\r
+ 'am' => true,\r
+ 'an' => array(\r
+  'com' => true,\r
+  'net' => true,\r
+  'org' => true,\r
+  'edu' => true\r
+ ),\r
+ 'ao' => array(\r
+  'ed' => true,\r
+  'gv' => true,\r
+  'og' => true,\r
+  'co' => true,\r
+  'pb' => true,\r
+  'it' => true\r
+ ),\r
+ 'aq' => true,\r
+ 'ar' => array(\r
+  '*' => true,\r
+  '!congresodelalengua3' => true,\r
+  '!educ' => true,\r
+  '!gobiernoelectronico' => true,\r
+  '!mecon' => true,\r
+  '!nacion' => true,\r
+  '!nic' => true,\r
+  '!promocion' => true,\r
+  '!retina' => true,\r
+  '!uba' => true\r
+ ),\r
+ 'arpa' => array(\r
+  'e164' => true,\r
+  'in-addr' => true,\r
+  'ip6' => true,\r
+  'iris' => true,\r
+  'uri' => true,\r
+  'urn' => true\r
+ ),\r
+ 'as' => array(\r
+  'gov' => true\r
+ ),\r
+ 'asia' => true,\r
+ 'at' => array(\r
+  'ac' => true,\r
+  'co' => true,\r
+  'gv' => true,\r
+  'or' => true,\r
+  'biz' => true,\r
+  'info' => true,\r
+  'priv' => true\r
+ ),\r
+ 'au' => array(\r
+  'com' => true,\r
+  'net' => true,\r
+  'org' => true,\r
+  'edu' => array(\r
+   'act' => true,\r
+   'nsw' => true,\r
+   'nt' => true,\r
+   'qld' => true,\r
+   'sa' => true,\r
+   'tas' => true,\r
+   'vic' => true,\r
+   'wa' => true\r
+  ),\r
+  'gov' => array(\r
+   'act' => true,\r
+   'nt' => true,\r
+   'qld' => true,\r
+   'sa' => true,\r
+   'tas' => true,\r
+   'vic' => true,\r
+   'wa' => true\r
+  ),\r
+  'csiro' => true,\r
+  'asn' => true,\r
+  'id' => true,\r
+  'info' => true,\r
+  'conf' => true,\r
+  'oz' => true,\r
+  'act' => true,\r
+  'nsw' => true,\r
+  'nt' => true,\r
+  'qld' => true,\r
+  'sa' => true,\r
+  'tas' => true,\r
+  'vic' => true,\r
+  'wa' => true\r
+ ),\r
+ 'aw' => array(\r
+  'com' => true\r
+ ),\r
+ 'ax' => true,\r
+ 'az' => array(\r
+  'com' => true,\r
+  'net' => true,\r
+  'int' => true,\r
+  'gov' => true,\r
+  'org' => true,\r
+  'edu' => true,\r
+  'info' => true,\r
+  'pp' => true,\r
+  'mil' => true,\r
+  'name' => true,\r
+  'pro' => true,\r
+  'biz' => true\r
+ ),\r
+ 'ba' => array(\r
+  'org' => true,\r
+  'net' => true,\r
+  'edu' => true,\r
+  'gov' => true,\r
+  'mil' => true,\r
+  'unsa' => true,\r
+  'unbi' => true,\r
+  'co' => true,\r
+  'com' => true,\r
+  'rs' => true\r
+ ),\r
+ 'bb' => array(\r
+  'biz' => true,\r
+  'com' => true,\r
+  'edu' => true,\r
+  'gov' => true,\r
+  'info' => true,\r
+  'net' => true,\r
+  'org' => true,\r
+  'store' => true\r
+ ),\r
+ 'bd' => array(\r
+  '*' => true\r
+ ),\r
+ 'be' => array(\r
+  'ac' => true\r
+ ),\r
+ 'bf' => array(\r
+  'gov' => true\r
+ ),\r
+ 'bg' => array(\r
+  'a' => true,\r
+  'b' => true,\r
+  'c' => true,\r
+  'd' => true,\r
+  'e' => true,\r
+  'f' => true,\r
+  'g' => true,\r
+  'h' => true,\r
+  'i' => true,\r
+  'j' => true,\r
+  'k' => true,\r
+  'l' => true,\r
+  'm' => true,\r
+  'n' => true,\r
+  'o' => true,\r
+  'p' => true,\r
+  'q' => true,\r
+  'r' => true,\r
+  's' => true,\r
+  't' => true,\r
+  'u' => true,\r
+  'v' => true,\r
+  'w' => true,\r
+  'x' => true,\r
+  'y' => true,\r
+  'z' => true,\r
+  '0' => true,\r
+  '1' => true,\r
+  '2' => true,\r
+  '3' => true,\r
+  '4' => true,\r
+  '5' => true,\r
+  '6' => true,\r
+  '7' => true,\r
+  '8' => true,\r
+  '9' => true\r
+ ),\r
+ 'bh' => array(\r
+  'com' => true,\r
+  'edu' => true,\r
+  'net' => true,\r
+  'org' => true,\r
+  'gov' => true\r
+ ),\r
+ 'bi' => array(\r
+  'co' => true,\r
+  'com' => true,\r
+  'edu' => true,\r
+  'or' => true,\r
+  'org' => true\r
+ ),\r
+ 'biz' => array(\r
+  'dyndns' => true,\r
+  'for-better' => true,\r
+  'for-more' => true,\r
+  'for-some' => true,\r
+  'for-the' => true,\r
+  'selfip' => true,\r
+  'webhop' => true\r
+ ),\r
+ 'bj' => array(\r
+  'asso' => true,\r
+  'barreau' => true,\r
+  'gouv' => true\r
+ ),\r
+ 'bm' => array(\r
+  'com' => true,\r
+  'edu' => true,\r
+  'gov' => true,\r
+  'net' => true,\r
+  'org' => true\r
+ ),\r
+ 'bn' => array(\r
+  '*' => true\r
+ ),\r
+ 'bo' => array(\r
+  'com' => true,\r
+  'edu' => true,\r
+  'gov' => true,\r
+  'gob' => true,\r
+  'int' => true,\r
+  'org' => true,\r
+  'net' => true,\r
+  'mil' => true,\r
+  'tv' => true\r
+ ),\r
+ 'br' => array(\r
+  'adm' => true,\r
+  'adv' => true,\r
+  'agr' => true,\r
+  'am' => true,\r
+  'arq' => true,\r
+  'art' => true,\r
+  'ato' => true,\r
+  'b' => true,\r
+  'bio' => true,\r
+  'blog' => true,\r
+  'bmd' => true,\r
+  'can' => true,\r
+  'cim' => true,\r
+  'cng' => true,\r
+  'cnt' => true,\r
+  'com' => true,\r
+  'coop' => true,\r
+  'ecn' => true,\r
+  'edu' => true,\r
+  'emp' => true,\r
+  'eng' => true,\r
+  'esp' => true,\r
+  'etc' => true,\r
+  'eti' => true,\r
+  'far' => true,\r
+  'flog' => true,\r
+  'fm' => true,\r
+  'fnd' => true,\r
+  'fot' => true,\r
+  'fst' => true,\r
+  'g12' => true,\r
+  'ggf' => true,\r
+  'gov' => true,\r
+  'imb' => true,\r
+  'ind' => true,\r
+  'inf' => true,\r
+  'jor' => true,\r
+  'jus' => true,\r
+  'lel' => true,\r
+  'mat' => true,\r
+  'med' => true,\r
+  'mil' => true,\r
+  'mus' => true,\r
+  'net' => true,\r
+  'nom' => true,\r
+  'not' => true,\r
+  'ntr' => true,\r
+  'odo' => true,\r
+  'org' => true,\r
+  'ppg' => true,\r
+  'pro' => true,\r
+  'psc' => true,\r
+  'psi' => true,\r
+  'qsl' => true,\r
+  'radio' => true,\r
+  'rec' => true,\r
+  'slg' => true,\r
+  'srv' => true,\r
+  'taxi' => true,\r
+  'teo' => true,\r
+  'tmp' => true,\r
+  'trd' => true,\r
+  'tur' => true,\r
+  'tv' => true,\r
+  'vet' => true,\r
+  'vlog' => true,\r
+  'wiki' => true,\r
+  'zlg' => true\r
+ ),\r
+ 'bs' => array(\r
+  'com' => true,\r
+  'net' => true,\r
+  'org' => true,\r
+  'edu' => true,\r
+  'gov' => true\r
+ ),\r
+ 'bt' => array(\r
+  'com' => true,\r
+  'edu' => true,\r
+  'gov' => true,\r
+  'net' => true,\r
+  'org' => true\r
+ ),\r
+ 'bw' => array(\r
+  'co' => true,\r
+  'org' => true\r
+ ),\r
+ 'by' => array(\r
+  'gov' => true,\r
+  'mil' => true,\r
+  'com' => true,\r
+  'of' => true\r
+ ),\r
+ 'bz' => array(\r
+  'com' => true,\r
+  'net' => true,\r
+  'org' => true,\r
+  'edu' => true,\r
+  'gov' => true\r
+ ),\r
+ 'ca' => array(\r
+  'ab' => true,\r
+  'bc' => true,\r
+  'mb' => true,\r
+  'nb' => true,\r
+  'nf' => true,\r
+  'nl' => true,\r
+  'ns' => true,\r
+  'nt' => true,\r
+  'nu' => true,\r
+  'on' => true,\r
+  'pe' => true,\r
+  'qc' => true,\r
+  'sk' => true,\r
+  'yk' => true,\r
+  'gc' => true,\r
+  'co' => true\r
+ ),\r
+ 'cat' => true,\r
+ 'cc' => array(\r
+  'ftpaccess' => true,\r
+  'game-server' => true,\r
+  'myphotos' => true,\r
+  'scrapping' => true\r
+ ),\r
+ 'cd' => array(\r
+  'gov' => true\r
+ ),\r
+ 'cf' => true,\r
+ 'cg' => true,\r
+ 'ch' => true,\r
+ 'ci' => array(\r
+  'org' => true,\r
+  'or' => true,\r
+  'com' => true,\r
+  'co' => true,\r
+  'edu' => true,\r
+  'ed' => true,\r
+  'ac' => true,\r
+  'net' => true,\r
+  'go' => true,\r
+  'asso' => true,\r
+  'aéroport' => true,\r
+  'int' => true,\r
+  'presse' => true,\r
+  'md' => true,\r
+  'gouv' => true\r
+ ),\r
+ 'ck' => array(\r
+  '*' => true,\r
+  '!www' => true\r
+ ),\r
+ 'cl' => array(\r
+  'gov' => true,\r
+  'gob' => true,\r
+  'co' => true,\r
+  'mil' => true\r
+ ),\r
+ 'cm' => array(\r
+  'gov' => true\r
+ ),\r
+ 'cn' => array(\r
+  'ac' => true,\r
+  'com' => true,\r
+  'edu' => true,\r
+  'gov' => true,\r
+  'net' => true,\r
+  'org' => true,\r
+  'mil' => true,\r
+  '公司' => true,\r
+  '网络' => true,\r
+  '網絡' => true,\r
+  'ah' => true,\r
+  'bj' => true,\r
+  'cq' => true,\r
+  'fj' => true,\r
+  'gd' => true,\r
+  'gs' => true,\r
+  'gz' => true,\r
+  'gx' => true,\r
+  'ha' => true,\r
+  'hb' => true,\r
+  'he' => true,\r
+  'hi' => true,\r
+  'hl' => true,\r
+  'hn' => true,\r
+  'jl' => true,\r
+  'js' => true,\r
+  'jx' => true,\r
+  'ln' => true,\r
+  'nm' => true,\r
+  'nx' => true,\r
+  'qh' => true,\r
+  'sc' => true,\r
+  'sd' => true,\r
+  'sh' => true,\r
+  'sn' => true,\r
+  'sx' => true,\r
+  'tj' => true,\r
+  'xj' => true,\r
+  'xz' => true,\r
+  'yn' => true,\r
+  'zj' => true,\r
+  'hk' => true,\r
+  'mo' => true,\r
+  'tw' => true\r
+ ),\r
+ 'co' => array(\r
+  'arts' => true,\r
+  'com' => true,\r
+  'edu' => true,\r
+  'firm' => true,\r
+  'gov' => true,\r
+  'info' => true,\r
+  'int' => true,\r
+  'mil' => true,\r
+  'net' => true,\r
+  'nom' => true,\r
+  'org' => true,\r
+  'rec' => true,\r
+  'web' => true\r
+ ),\r
+ 'com' => array(\r
+  'ar' => true,\r
+  'br' => true,\r
+  'cn' => true,\r
+  'de' => true,\r
+  'eu' => true,\r
+  'gb' => true,\r
+  'gr' => true,\r
+  'hu' => true,\r
+  'jpn' => true,\r
+  'kr' => true,\r
+  'no' => true,\r
+  'qc' => true,\r
+  'ru' => true,\r
+  'sa' => true,\r
+  'se' => true,\r
+  'uk' => true,\r
+  'us' => true,\r
+  'uy' => true,\r
+  'za' => true,\r
+  'operaunite' => true,\r
+  'appspot' => true,\r
+  'dyndns-at-home' => true,\r
+  'dyndns-at-work' => true,\r
+  'dyndns-blog' => true,\r
+  'dyndns-free' => true,\r
+  'dyndns-home' => true,\r
+  'dyndns-ip' => true,\r
+  'dyndns-mail' => true,\r
+  'dyndns-office' => true,\r
+  'dyndns-pics' => true,\r
+  'dyndns-remote' => true,\r
+  'dyndns-server' => true,\r
+  'dyndns-web' => true,\r
+  'dyndns-wiki' => true,\r
+  'dyndns-work' => true,\r
+  'blogdns' => true,\r
+  'cechire' => true,\r
+  'dnsalias' => true,\r
+  'dnsdojo' => true,\r
+  'doesntexist' => true,\r
+  'dontexist' => true,\r
+  'doomdns' => true,\r
+  'dyn-o-saur' => true,\r
+  'dynalias' => true,\r
+  'est-a-la-maison' => true,\r
+  'est-a-la-masion' => true,\r
+  'est-le-patron' => true,\r
+  'est-mon-blogueur' => true,\r
+  'from-ak' => true,\r
+  'from-al' => true,\r
+  'from-ar' => true,\r
+  'from-ca' => true,\r
+  'from-ct' => true,\r
+  'from-dc' => true,\r
+  'from-de' => true,\r
+  'from-fl' => true,\r
+  'from-ga' => true,\r
+  'from-hi' => true,\r
+  'from-ia' => true,\r
+  'from-id' => true,\r
+  'from-il' => true,\r
+  'from-in' => true,\r
+  'from-ks' => true,\r
+  'from-ky' => true,\r
+  'from-ma' => true,\r
+  'from-md' => true,\r
+  'from-mi' => true,\r
+  'from-mn' => true,\r
+  'from-mo' => true,\r
+  'from-ms' => true,\r
+  'from-mt' => true,\r
+  'from-nc' => true,\r
+  'from-nd' => true,\r
+  'from-ne' => true,\r
+  'from-nh' => true,\r
+  'from-nj' => true,\r
+  'from-nm' => true,\r
+  'from-nv' => true,\r
+  'from-oh' => true,\r
+  'from-ok' => true,\r
+  'from-or' => true,\r
+  'from-pa' => true,\r
+  'from-pr' => true,\r
+  'from-ri' => true,\r
+  'from-sc' => true,\r
+  'from-sd' => true,\r
+  'from-tn' => true,\r
+  'from-tx' => true,\r
+  'from-ut' => true,\r
+  'from-va' => true,\r
+  'from-vt' => true,\r
+  'from-wa' => true,\r
+  'from-wi' => true,\r
+  'from-wv' => true,\r
+  'from-wy' => true,\r
+  'getmyip' => true,\r
+  'gotdns' => true,\r
+  'hobby-site' => true,\r
+  'homelinux' => true,\r
+  'homeunix' => true,\r
+  'iamallama' => true,\r
+  'is-a-anarchist' => true,\r
+  'is-a-blogger' => true,\r
+  'is-a-bookkeeper' => true,\r
+  'is-a-bulls-fan' => true,\r
+  'is-a-caterer' => true,\r
+  'is-a-chef' => true,\r
+  'is-a-conservative' => true,\r
+  'is-a-cpa' => true,\r
+  'is-a-cubicle-slave' => true,\r
+  'is-a-democrat' => true,\r
+  'is-a-designer' => true,\r
+  'is-a-doctor' => true,\r
+  'is-a-financialadvisor' => true,\r
+  'is-a-geek' => true,\r
+  'is-a-green' => true,\r
+  'is-a-guru' => true,\r
+  'is-a-hard-worker' => true,\r
+  'is-a-hunter' => true,\r
+  'is-a-landscaper' => true,\r
+  'is-a-lawyer' => true,\r
+  'is-a-liberal' => true,\r
+  'is-a-libertarian' => true,\r
+  'is-a-llama' => true,\r
+  'is-a-musician' => true,\r
+  'is-a-nascarfan' => true,\r
+  'is-a-nurse' => true,\r
+  'is-a-painter' => true,\r
+  'is-a-personaltrainer' => true,\r
+  'is-a-photographer' => true,\r
+  'is-a-player' => true,\r
+  'is-a-republican' => true,\r
+  'is-a-rockstar' => true,\r
+  'is-a-socialist' => true,\r
+  'is-a-student' => true,\r
+  'is-a-teacher' => true,\r
+  'is-a-techie' => true,\r
+  'is-a-therapist' => true,\r
+  'is-an-accountant' => true,\r
+  'is-an-actor' => true,\r
+  'is-an-actress' => true,\r
+  'is-an-anarchist' => true,\r
+  'is-an-artist' => true,\r
+  'is-an-engineer' => true,\r
+  'is-an-entertainer' => true,\r
+  'is-certified' => true,\r
+  'is-gone' => true,\r
+  'is-into-anime' => true,\r
+  'is-into-cars' => true,\r
+  'is-into-cartoons' => true,\r
+  'is-into-games' => true,\r
+  'is-leet' => true,\r
+  'is-not-certified' => true,\r
+  'is-slick' => true,\r
+  'is-uberleet' => true,\r
+  'is-with-theband' => true,\r
+  'isa-geek' => true,\r
+  'isa-hockeynut' => true,\r
+  'issmarterthanyou' => true,\r
+  'likes-pie' => true,\r
+  'likescandy' => true,\r
+  'neat-url' => true,\r
+  'saves-the-whales' => true,\r
+  'selfip' => true,\r
+  'sells-for-less' => true,\r
+  'sells-for-u' => true,\r
+  'servebbs' => true,\r
+  'simple-url' => true,\r
+  'space-to-rent' => true,\r
+  'teaches-yoga' => true,\r
+  'writesthisblog' => true\r
+ ),\r
+ 'coop' => true,\r
+ 'cr' => array(\r
+  'ac' => true,\r
+  'co' => true,\r
+  'ed' => true,\r
+  'fi' => true,\r
+  'go' => true,\r
+  'or' => true,\r
+  'sa' => true\r
+ ),\r
+ 'cu' => array(\r
+  'com' => true,\r
+  'edu' => true,\r
+  'org' => true,\r
+  'net' => true,\r
+  'gov' => true,\r
+  'inf' => true\r
+ ),\r
+ 'cv' => true,\r
+ 'cx' => array(\r
+  'gov' => true,\r
+  'ath' => true\r
+ ),\r
+ 'cy' => array(\r
+  '*' => true\r
+ ),\r
+ 'cz' => true,\r
+ 'de' => array(\r
+  'com' => true,\r
+  'fuettertdasnetz' => true,\r
+  'isteingeek' => true,\r
+  'istmein' => true,\r
+  'lebtimnetz' => true,\r
+  'leitungsen' => true,\r
+  'traeumtgerade' => true\r
+ ),\r
+ 'dj' => true,\r
+ 'dk' => true,\r
+ 'dm' => array(\r
+  'com' => true,\r
+  'net' => true,\r
+  'org' => true,\r
+  'edu' => true,\r
+  'gov' => true\r
+ ),\r
+ 'do' => array(\r
+  'art' => true,\r
+  'com' => true,\r
+  'edu' => true,\r
+  'gob' => true,\r
+  'gov' => true,\r
+  'mil' => true,\r
+  'net' => true,\r
+  'org' => true,\r
+  'sld' => true,\r
+  'web' => true\r
+ ),\r
+ 'dz' => array(\r
+  'com' => true,\r
+  'org' => true,\r
+  'net' => true,\r
+  'gov' => true,\r
+  'edu' => true,\r
+  'asso' => true,\r
+  'pol' => true,\r
+  'art' => true\r
+ ),\r
+ 'ec' => array(\r
+  'com' => true,\r
+  'info' => true,\r
+  'net' => true,\r
+  'fin' => true,\r
+  'k12' => true,\r
+  'med' => true,\r
+  'pro' => true,\r
+  'org' => true,\r
+  'edu' => true,\r
+  'gov' => true,\r
+  'gob' => true,\r
+  'mil' => true\r
+ ),\r
+ 'edu' => true,\r
+ 'ee' => array(\r
+  'edu' => true,\r
+  'gov' => true,\r
+  'riik' => true,\r
+  'lib' => true,\r
+  'med' => true,\r
+  'com' => true,\r
+  'pri' => true,\r
+  'aip' => true,\r
+  'org' => true,\r
+  'fie' => true\r
+ ),\r
+ 'eg' => array(\r
+  'com' => true,\r
+  'edu' => true,\r
+  'eun' => true,\r
+  'gov' => true,\r
+  'mil' => true,\r
+  'name' => true,\r
+  'net' => true,\r
+  'org' => true,\r
+  'sci' => true\r
+ ),\r
+ 'er' => array(\r
+  '*' => true\r
+ ),\r
+ 'es' => array(\r
+  'com' => true,\r
+  'nom' => true,\r
+  'org' => true,\r
+  'gob' => true,\r
+  'edu' => true\r
+ ),\r
+ 'et' => array(\r
+  '*' => true\r
+ ),\r
+ 'eu' => true,\r
+ 'fi' => array(\r
+  'aland' => true,\r
+  'iki' => true\r
+ ),\r
+ 'fj' => array(\r
+  '*' => true\r
+ ),\r
+ 'fk' => array(\r
+  '*' => true\r
+ ),\r
+ 'fm' => true,\r
+ 'fo' => true,\r
+ 'fr' => array(\r
+  'com' => true,\r
+  'asso' => true,\r
+  'nom' => true,\r
+  'prd' => true,\r
+  'presse' => true,\r
+  'tm' => true,\r
+  'aeroport' => true,\r
+  'assedic' => true,\r
+  'avocat' => true,\r
+  'avoues' => true,\r
+  'cci' => true,\r
+  'chambagri' => true,\r
+  'chirurgiens-dentistes' => true,\r
+  'experts-comptables' => true,\r
+  'geometre-expert' => true,\r
+  'gouv' => true,\r
+  'greta' => true,\r
+  'huissier-justice' => true,\r
+  'medecin' => true,\r
+  'notaires' => true,\r
+  'pharmacien' => true,\r
+  'port' => true,\r
+  'veterinaire' => true\r
+ ),\r
+ 'ga' => true,\r
+ 'gd' => true,\r
+ 'ge' => array(\r
+  'com' => true,\r
+  'edu' => true,\r
+  'gov' => true,\r
+  'org' => true,\r
+  'mil' => true,\r
+  'net' => true,\r
+  'pvt' => true\r
+ ),\r
+ 'gf' => true,\r
+ 'gg' => array(\r
+  'co' => true,\r
+  'org' => true,\r
+  'net' => true,\r
+  'sch' => true,\r
+  'gov' => true\r
+ ),\r
+ 'gh' => array(\r
+  'com' => true,\r
+  'edu' => true,\r
+  'gov' => true,\r
+  'org' => true,\r
+  'mil' => true\r
+ ),\r
+ 'gi' => array(\r
+  'com' => true,\r
+  'ltd' => true,\r
+  'gov' => true,\r
+  'mod' => true,\r
+  'edu' => true,\r
+  'org' => true\r
+ ),\r
+ 'gl' => true,\r
+ 'gm' => true,\r
+ 'gn' => array(\r
+  'ac' => true,\r
+  'com' => true,\r
+  'edu' => true,\r
+  'gov' => true,\r
+  'org' => true,\r
+  'net' => true\r
+ ),\r
+ 'gov' => true,\r
+ 'gp' => array(\r
+  'com' => true,\r
+  'net' => true,\r
+  'mobi' => true,\r
+  'edu' => true,\r
+  'org' => true,\r
+  'asso' => true\r
+ ),\r
+ 'gq' => true,\r
+ 'gr' => array(\r
+  'com' => true,\r
+  'edu' => true,\r
+  'net' => true,\r
+  'org' => true,\r
+  'gov' => true\r
+ ),\r
+ 'gs' => true,\r
+ 'gt' => array(\r
+  '*' => true,\r
+  '!www' => true\r
+ ),\r
+ 'gu' => array(\r
+  '*' => true\r
+ ),\r
+ 'gw' => true,\r
+ 'gy' => array(\r
+  'co' => true,\r
+  'com' => true,\r
+  'net' => true\r
+ ),\r
+ 'hk' => array(\r
+  'com' => true,\r
+  'edu' => true,\r
+  'gov' => true,\r
+  'idv' => true,\r
+  'net' => true,\r
+  'org' => true,\r
+  '公司' => true,\r
+  '教育' => true,\r
+  '敎育' => true,\r
+  '政府' => true,\r
+  '個人' => true,\r
+  '个人' => true,\r
+  '箇人' => true,\r
+  '網络' => true,\r
+  '网络' => true,\r
+  '组織' => true,\r
+  '網絡' => true,\r
+  '网絡' => true,\r
+  '组织' => true,\r
+  '組織' => true,\r
+  '組织' => true\r
+ ),\r
+ 'hm' => true,\r
+ 'hn' => array(\r
+  'com' => true,\r
+  'edu' => true,\r
+  'org' => true,\r
+  'net' => true,\r
+  'mil' => true,\r
+  'gob' => true\r
+ ),\r
+ 'hr' => array(\r
+  'iz' => true,\r
+  'from' => true,\r
+  'name' => true,\r
+  'com' => true\r
+ ),\r
+ 'ht' => array(\r
+  'com' => true,\r
+  'shop' => true,\r
+  'firm' => true,\r
+  'info' => true,\r
+  'adult' => true,\r
+  'net' => true,\r
+  'pro' => true,\r
+  'org' => true,\r
+  'med' => true,\r
+  'art' => true,\r
+  'coop' => true,\r
+  'pol' => true,\r
+  'asso' => true,\r
+  'edu' => true,\r
+  'rel' => true,\r
+  'gouv' => true,\r
+  'perso' => true\r
+ ),\r
+ 'hu' => array(\r
+  'co' => true,\r
+  'info' => true,\r
+  'org' => true,\r
+  'priv' => true,\r
+  'sport' => true,\r
+  'tm' => true,\r
+  '2000' => true,\r
+  'agrar' => true,\r
+  'bolt' => true,\r
+  'casino' => true,\r
+  'city' => true,\r
+  'erotica' => true,\r
+  'erotika' => true,\r
+  'film' => true,\r
+  'forum' => true,\r
+  'games' => true,\r
+  'hotel' => true,\r
+  'ingatlan' => true,\r
+  'jogasz' => true,\r
+  'konyvelo' => true,\r
+  'lakas' => true,\r
+  'media' => true,\r
+  'news' => true,\r
+  'reklam' => true,\r
+  'sex' => true,\r
+  'shop' => true,\r
+  'suli' => true,\r
+  'szex' => true,\r
+  'tozsde' => true,\r
+  'utazas' => true,\r
+  'video' => true\r
+ ),\r
+ 'id' => array(\r
+  'ac' => true,\r
+  'co' => true,\r
+  'go' => true,\r
+  'mil' => true,\r
+  'net' => true,\r
+  'or' => true,\r
+  'sch' => true,\r
+  'web' => true\r
+ ),\r
+ 'ie' => array(\r
+  'gov' => true\r
+ ),\r
+ 'il' => array(\r
+  '*' => true\r
+ ),\r
+ 'im' => array(\r
+  'co' => array(\r
+   'ltd' => true,\r
+   'plc' => true\r
+  ),\r
+  'net' => true,\r
+  'gov' => true,\r
+  'org' => true,\r
+  'nic' => true,\r
+  'ac' => true\r
+ ),\r
+ 'in' => array(\r
+  'co' => true,\r
+  'firm' => true,\r
+  'net' => true,\r
+  'org' => true,\r
+  'gen' => true,\r
+  'ind' => true,\r
+  'nic' => true,\r
+  'ac' => true,\r
+  'edu' => true,\r
+  'res' => true,\r
+  'gov' => true,\r
+  'mil' => true\r
+ ),\r
+ 'info' => array(\r
+  'dyndns' => true,\r
+  'barrel-of-knowledge' => true,\r
+  'barrell-of-knowledge' => true,\r
+  'for-our' => true,\r
+  'groks-the' => true,\r
+  'groks-this' => true,\r
+  'here-for-more' => true,\r
+  'knowsitall' => true,\r
+  'selfip' => true,\r
+  'webhop' => true\r
+ ),\r
+ 'int' => array(\r
+  'eu' => true\r
+ ),\r
+ 'io' => array(\r
+  'com' => true\r
+ ),\r
+ 'iq' => array(\r
+  'gov' => true,\r
+  'edu' => true,\r
+  'mil' => true,\r
+  'com' => true,\r
+  'org' => true,\r
+  'net' => true\r
+ ),\r
+ 'ir' => array(\r
+  'ac' => true,\r
+  'co' => true,\r
+  'gov' => true,\r
+  'id' => true,\r
+  'net' => true,\r
+  'org' => true,\r
+  'sch' => true,\r
+  'ایران' => true,\r
+  'ايران' => true\r
+ ),\r
+ 'is' => array(\r
+  'net' => true,\r
+  'com' => true,\r
+  'edu' => true,\r
+  'gov' => true,\r
+  'org' => true,\r
+  'int' => true\r
+ ),\r
+ 'it' => array(\r
+  'gov' => true,\r
+  'edu' => true,\r
+  'agrigento' => true,\r
+  'ag' => true,\r
+  'alessandria' => true,\r
+  'al' => true,\r
+  'ancona' => true,\r
+  'an' => true,\r
+  'aosta' => true,\r
+  'aoste' => true,\r
+  'ao' => true,\r
+  'arezzo' => true,\r
+  'ar' => true,\r
+  'ascoli-piceno' => true,\r
+  'ascolipiceno' => true,\r
+  'ap' => true,\r
+  'asti' => true,\r
+  'at' => true,\r
+  'avellino' => true,\r
+  'av' => true,\r
+  'bari' => true,\r
+  'ba' => true,\r
+  'andria-barletta-trani' => true,\r
+  'andriabarlettatrani' => true,\r
+  'trani-barletta-andria' => true,\r
+  'tranibarlettaandria' => true,\r
+  'barletta-trani-andria' => true,\r
+  'barlettatraniandria' => true,\r
+  'andria-trani-barletta' => true,\r
+  'andriatranibarletta' => true,\r
+  'trani-andria-barletta' => true,\r
+  'traniandriabarletta' => true,\r
+  'bt' => true,\r
+  'belluno' => true,\r
+  'bl' => true,\r
+  'benevento' => true,\r
+  'bn' => true,\r
+  'bergamo' => true,\r
+  'bg' => true,\r
+  'biella' => true,\r
+  'bi' => true,\r
+  'bologna' => true,\r
+  'bo' => true,\r
+  'bolzano' => true,\r
+  'bozen' => true,\r
+  'balsan' => true,\r
+  'alto-adige' => true,\r
+  'altoadige' => true,\r
+  'suedtirol' => true,\r
+  'bz' => true,\r
+  'brescia' => true,\r
+  'bs' => true,\r
+  'brindisi' => true,\r
+  'br' => true,\r
+  'cagliari' => true,\r
+  'ca' => true,\r
+  'caltanissetta' => true,\r
+  'cl' => true,\r
+  'campobasso' => true,\r
+  'cb' => true,\r
+  'carboniaiglesias' => true,\r
+  'carbonia-iglesias' => true,\r
+  'iglesias-carbonia' => true,\r
+  'iglesiascarbonia' => true,\r
+  'ci' => true,\r
+  'caserta' => true,\r
+  'ce' => true,\r
+  'catania' => true,\r
+  'ct' => true,\r
+  'catanzaro' => true,\r
+  'cz' => true,\r
+  'chieti' => true,\r
+  'ch' => true,\r
+  'como' => true,\r
+  'co' => true,\r
+  'cosenza' => true,\r
+  'cs' => true,\r
+  'cremona' => true,\r
+  'cr' => true,\r
+  'crotone' => true,\r
+  'kr' => true,\r
+  'cuneo' => true,\r
+  'cn' => true,\r
+  'dell-ogliastra' => true,\r
+  'dellogliastra' => true,\r
+  'ogliastra' => true,\r
+  'og' => true,\r
+  'enna' => true,\r
+  'en' => true,\r
+  'ferrara' => true,\r
+  'fe' => true,\r
+  'fermo' => true,\r
+  'fm' => true,\r
+  'firenze' => true,\r
+  'florence' => true,\r
+  'fi' => true,\r
+  'foggia' => true,\r
+  'fg' => true,\r
+  'forli-cesena' => true,\r
+  'forlicesena' => true,\r
+  'cesena-forli' => true,\r
+  'cesenaforli' => true,\r
+  'fc' => true,\r
+  'frosinone' => true,\r
+  'fr' => true,\r
+  'genova' => true,\r
+  'genoa' => true,\r
+  'ge' => true,\r
+  'gorizia' => true,\r
+  'go' => true,\r
+  'grosseto' => true,\r
+  'gr' => true,\r
+  'imperia' => true,\r
+  'im' => true,\r
+  'isernia' => true,\r
+  'is' => true,\r
+  'laquila' => true,\r
+  'aquila' => true,\r
+  'aq' => true,\r
+  'la-spezia' => true,\r
+  'laspezia' => true,\r
+  'sp' => true,\r
+  'latina' => true,\r
+  'lt' => true,\r
+  'lecce' => true,\r
+  'le' => true,\r
+  'lecco' => true,\r
+  'lc' => true,\r
+  'livorno' => true,\r
+  'li' => true,\r
+  'lodi' => true,\r
+  'lo' => true,\r
+  'lucca' => true,\r
+  'lu' => true,\r
+  'macerata' => true,\r
+  'mc' => true,\r
+  'mantova' => true,\r
+  'mn' => true,\r
+  'massa-carrara' => true,\r
+  'massacarrara' => true,\r
+  'carrara-massa' => true,\r
+  'carraramassa' => true,\r
+  'ms' => true,\r
+  'matera' => true,\r
+  'mt' => true,\r
+  'medio-campidano' => true,\r
+  'mediocampidano' => true,\r
+  'campidano-medio' => true,\r
+  'campidanomedio' => true,\r
+  'vs' => true,\r
+  'messina' => true,\r
+  'me' => true,\r
+  'milano' => true,\r
+  'milan' => true,\r
+  'mi' => true,\r
+  'modena' => true,\r
+  'mo' => true,\r
+  'monza' => true,\r
+  'monza-brianza' => true,\r
+  'monzabrianza' => true,\r
+  'monzaebrianza' => true,\r
+  'monzaedellabrianza' => true,\r
+  'monza-e-della-brianza' => true,\r
+  'mb' => true,\r
+  'napoli' => true,\r
+  'naples' => true,\r
+  'na' => true,\r
+  'novara' => true,\r
+  'no' => true,\r
+  'nuoro' => true,\r
+  'nu' => true,\r
+  'oristano' => true,\r
+  'or' => true,\r
+  'padova' => true,\r
+  'padua' => true,\r
+  'pd' => true,\r
+  'palermo' => true,\r
+  'pa' => true,\r
+  'parma' => true,\r
+  'pr' => true,\r
+  'pavia' => true,\r
+  'pv' => true,\r
+  'perugia' => true,\r
+  'pg' => true,\r
+  'pescara' => true,\r
+  'pe' => true,\r
+  'pesaro-urbino' => true,\r
+  'pesarourbino' => true,\r
+  'urbino-pesaro' => true,\r
+  'urbinopesaro' => true,\r
+  'pu' => true,\r
+  'piacenza' => true,\r
+  'pc' => true,\r
+  'pisa' => true,\r
+  'pi' => true,\r
+  'pistoia' => true,\r
+  'pt' => true,\r
+  'pordenone' => true,\r
+  'pn' => true,\r
+  'potenza' => true,\r
+  'pz' => true,\r
+  'prato' => true,\r
+  'po' => true,\r
+  'ragusa' => true,\r
+  'rg' => true,\r
+  'ravenna' => true,\r
+  'ra' => true,\r
+  'reggio-calabria' => true,\r
+  'reggiocalabria' => true,\r
+  'rc' => true,\r
+  'reggio-emilia' => true,\r
+  'reggioemilia' => true,\r
+  're' => true,\r
+  'rieti' => true,\r
+  'ri' => true,\r
+  'rimini' => true,\r
+  'rn' => true,\r
+  'roma' => true,\r
+  'rome' => true,\r
+  'rm' => true,\r
+  'rovigo' => true,\r
+  'ro' => true,\r
+  'salerno' => true,\r
+  'sa' => true,\r
+  'sassari' => true,\r
+  'ss' => true,\r
+  'savona' => true,\r
+  'sv' => true,\r
+  'siena' => true,\r
+  'si' => true,\r
+  'siracusa' => true,\r
+  'sr' => true,\r
+  'sondrio' => true,\r
+  'so' => true,\r
+  'taranto' => true,\r
+  'ta' => true,\r
+  'tempio-olbia' => true,\r
+  'tempioolbia' => true,\r
+  'olbia-tempio' => true,\r
+  'olbiatempio' => true,\r
+  'ot' => true,\r
+  'teramo' => true,\r
+  'te' => true,\r
+  'terni' => true,\r
+  'tr' => true,\r
+  'torino' => true,\r
+  'turin' => true,\r
+  'to' => true,\r
+  'trapani' => true,\r
+  'tp' => true,\r
+  'trento' => true,\r
+  'trentino' => true,\r
+  'tn' => true,\r
+  'treviso' => true,\r
+  'tv' => true,\r
+  'trieste' => true,\r
+  'ts' => true,\r
+  'udine' => true,\r
+  'ud' => true,\r
+  'varese' => true,\r
+  'va' => true,\r
+  'venezia' => true,\r
+  'venice' => true,\r
+  've' => true,\r
+  'verbania' => true,\r
+  'vb' => true,\r
+  'vercelli' => true,\r
+  'vc' => true,\r
+  'verona' => true,\r
+  'vr' => true,\r
+  'vibo-valentia' => true,\r
+  'vibovalentia' => true,\r
+  'vv' => true,\r
+  'vicenza' => true,\r
+  'vi' => true,\r
+  'viterbo' => true,\r
+  'vt' => true\r
+ ),\r
+ 'je' => array(\r
+  'co' => true,\r
+  'org' => true,\r
+  'net' => true,\r
+  'sch' => true,\r
+  'gov' => true\r
+ ),\r
+ 'jm' => array(\r
+  '*' => true\r
+ ),\r
+ 'jo' => array(\r
+  'com' => true,\r
+  'org' => true,\r
+  'net' => true,\r
+  'edu' => true,\r
+  'sch' => true,\r
+  'gov' => true,\r
+  'mil' => true,\r
+  'name' => true\r
+ ),\r
+ 'jobs' => true,\r
+ 'jp' => array(\r
+  'ac' => true,\r
+  'ad' => true,\r
+  'co' => true,\r
+  'ed' => true,\r
+  'go' => true,\r
+  'gr' => true,\r
+  'lg' => true,\r
+  'ne' => true,\r
+  'or' => true,\r
+  'aichi' => array(\r
+   '*' => true,\r
+   '!pref' => true\r
+  ),\r
+  'akita' => array(\r
+   '*' => true,\r
+   '!pref' => true\r
+  ),\r
+  'aomori' => array(\r
+   '*' => true,\r
+   '!pref' => true\r
+  ),\r
+  'chiba' => array(\r
+   '*' => true,\r
+   '!pref' => true,\r
+   '!city' => true\r
+  ),\r
+  'ehime' => array(\r
+   '*' => true,\r
+   '!pref' => true\r
+  ),\r
+  'fukui' => array(\r
+   '*' => true,\r
+   '!pref' => true\r
+  ),\r
+  'fukuoka' => array(\r
+   '*' => true,\r
+   '!pref' => true,\r
+   '!city' => true\r
+  ),\r
+  'fukushima' => array(\r
+   '*' => true,\r
+   '!pref' => true\r
+  ),\r
+  'gifu' => array(\r
+   '*' => true,\r
+   '!pref' => true\r
+  ),\r
+  'gunma' => array(\r
+   '*' => true,\r
+   '!pref' => true\r
+  ),\r
+  'hiroshima' => array(\r
+   '*' => true,\r
+   '!pref' => true,\r
+   '!city' => true\r
+  ),\r
+  'hokkaido' => array(\r
+   '*' => true,\r
+   '!pref' => true\r
+  ),\r
+  'hyogo' => array(\r
+   '*' => true,\r
+   '!pref' => true\r
+  ),\r
+  'ibaraki' => array(\r
+   '*' => true,\r
+   '!pref' => true\r
+  ),\r
+  'ishikawa' => array(\r
+   '*' => true,\r
+   '!pref' => true\r
+  ),\r
+  'iwate' => array(\r
+   '*' => true,\r
+   '!pref' => true\r
+  ),\r
+  'kagawa' => array(\r
+   '*' => true,\r
+   '!pref' => true\r
+  ),\r
+  'kagoshima' => array(\r
+   '*' => true,\r
+   '!pref' => true\r
+  ),\r
+  'kanagawa' => array(\r
+   '*' => true,\r
+   '!pref' => true\r
+  ),\r
+  'kawasaki' => array(\r
+   '*' => true,\r
+   '!city' => true\r
+  ),\r
+  'kitakyushu' => array(\r
+   '*' => true,\r
+   '!city' => true\r
+  ),\r
+  'kobe' => array(\r
+   '*' => true,\r
+   '!city' => true\r
+  ),\r
+  'kochi' => array(\r
+   '*' => true,\r
+   '!pref' => true\r
+  ),\r
+  'kumamoto' => array(\r
+   '*' => true,\r
+   '!pref' => true\r
+  ),\r
+  'kyoto' => array(\r
+   '*' => true,\r
+   '!pref' => true,\r
+   '!city' => true\r
+  ),\r
+  'mie' => array(\r
+   '*' => true,\r
+   '!pref' => true\r
+  ),\r
+  'miyagi' => array(\r
+   '*' => true,\r
+   '!pref' => true\r
+  ),\r
+  'miyazaki' => array(\r
+   '*' => true,\r
+   '!pref' => true\r
+  ),\r
+  'nagano' => array(\r
+   '*' => true,\r
+   '!pref' => true\r
+  ),\r
+  'nagasaki' => array(\r
+   '*' => true,\r
+   '!pref' => true\r
+  ),\r
+  'nagoya' => array(\r
+   '*' => true,\r
+   '!city' => true\r
+  ),\r
+  'nara' => array(\r
+   '*' => true,\r
+   '!pref' => true\r
+  ),\r
+  'niigata' => array(\r
+   '*' => true,\r
+   '!pref' => true,\r
+   '!city' => true\r
+  ),\r
+  'oita' => array(\r
+   '*' => true,\r
+   '!pref' => true\r
+  ),\r
+  'okayama' => array(\r
+   '*' => true,\r
+   '!pref' => true,\r
+   '!city' => true\r
+  ),\r
+  'okinawa' => array(\r
+   '*' => true,\r
+   '!pref' => true\r
+  ),\r
+  'osaka' => array(\r
+   '*' => true,\r
+   '!pref' => true,\r
+   '!city' => true\r
+  ),\r
+  'saga' => array(\r
+   '*' => true,\r
+   '!pref' => true\r
+  ),\r
+  'saitama' => array(\r
+   '*' => true,\r
+   '!pref' => true,\r
+   '!city' => true\r
+  ),\r
+  'sapporo' => array(\r
+   '*' => true,\r
+   '!city' => true\r
+  ),\r
+  'sendai' => array(\r
+   '*' => true,\r
+   '!city' => true\r
+  ),\r
+  'shiga' => array(\r
+   '*' => true,\r
+   '!pref' => true\r
+  ),\r
+  'shimane' => array(\r
+   '*' => true,\r
+   '!pref' => true\r
+  ),\r
+  'shizuoka' => array(\r
+   '*' => true,\r
+   '!pref' => true,\r
+   '!city' => true\r
+  ),\r
+  'tochigi' => array(\r
+   '*' => true,\r
+   '!pref' => true\r
+  ),\r
+  'tokushima' => array(\r
+   '*' => true,\r
+   '!pref' => true\r
+  ),\r
+  'tokyo' => array(\r
+   '*' => true,\r
+   '!metro' => true\r
+  ),\r
+  'tottori' => array(\r
+   '*' => true,\r
+   '!pref' => true\r
+  ),\r
+  'toyama' => array(\r
+   '*' => true,\r
+   '!pref' => true\r
+  ),\r
+  'wakayama' => array(\r
+   '*' => true,\r
+   '!pref' => true\r
+  ),\r
+  'yamagata' => array(\r
+   '*' => true,\r
+   '!pref' => true\r
+  ),\r
+  'yamaguchi' => array(\r
+   '*' => true,\r
+   '!pref' => true\r
+  ),\r
+  'yamanashi' => array(\r
+   '*' => true,\r
+   '!pref' => true\r
+  ),\r
+  'yokohama' => array(\r
+   '*' => true,\r
+   '!city' => true\r
+  )\r
+ ),\r
+ 'ke' => array(\r
+  '*' => true\r
+ ),\r
+ 'kg' => array(\r
+  'org' => true,\r
+  'net' => true,\r
+  'com' => true,\r
+  'edu' => true,\r
+  'gov' => true,\r
+  'mil' => true\r
+ ),\r
+ 'kh' => array(\r
+  '*' => true\r
+ ),\r
+ 'ki' => array(\r
+  'edu' => true,\r
+  'biz' => true,\r
+  'net' => true,\r
+  'org' => true,\r
+  'gov' => true,\r
+  'info' => true,\r
+  'com' => true\r
+ ),\r
+ 'km' => array(\r
+  'org' => true,\r
+  'nom' => true,\r
+  'gov' => true,\r
+  'prd' => true,\r
+  'tm' => true,\r
+  'edu' => true,\r
+  'mil' => true,\r
+  'ass' => true,\r
+  'com' => true,\r
+  'coop' => true,\r
+  'asso' => true,\r
+  'presse' => true,\r
+  'medecin' => true,\r
+  'notaires' => true,\r
+  'pharmaciens' => true,\r
+  'veterinaire' => true,\r
+  'gouv' => true\r
+ ),\r
+ 'kn' => array(\r
+  'net' => true,\r
+  'org' => true,\r
+  'edu' => true,\r
+  'gov' => true\r
+ ),\r
+ 'kp' => array(\r
+  'com' => true,\r
+  'edu' => true,\r
+  'gov' => true,\r
+  'org' => true,\r
+  'rep' => true,\r
+  'tra' => true\r
+ ),\r
+ 'kr' => array(\r
+  'ac' => true,\r
+  'co' => true,\r
+  'es' => true,\r
+  'go' => true,\r
+  'hs' => true,\r
+  'kg' => true,\r
+  'mil' => true,\r
+  'ms' => true,\r
+  'ne' => true,\r
+  'or' => true,\r
+  'pe' => true,\r
+  're' => true,\r
+  'sc' => true,\r
+  'busan' => true,\r
+  'chungbuk' => true,\r
+  'chungnam' => true,\r
+  'daegu' => true,\r
+  'daejeon' => true,\r
+  'gangwon' => true,\r
+  'gwangju' => true,\r
+  'gyeongbuk' => true,\r
+  'gyeonggi' => true,\r
+  'gyeongnam' => true,\r
+  'incheon' => true,\r
+  'jeju' => true,\r
+  'jeonbuk' => true,\r
+  'jeonnam' => true,\r
+  'seoul' => true,\r
+  'ulsan' => true\r
+ ),\r
+ 'kw' => array(\r
+  '*' => true\r
+ ),\r
+ 'ky' => array(\r
+  'edu' => true,\r
+  'gov' => true,\r
+  'com' => true,\r
+  'org' => true,\r
+  'net' => true\r
+ ),\r
+ 'kz' => array(\r
+  'org' => true,\r
+  'edu' => true,\r
+  'net' => true,\r
+  'gov' => true,\r
+  'mil' => true,\r
+  'com' => true\r
+ ),\r
+ 'la' => array(\r
+  'int' => true,\r
+  'net' => true,\r
+  'info' => true,\r
+  'edu' => true,\r
+  'gov' => true,\r
+  'per' => true,\r
+  'com' => true,\r
+  'org' => true,\r
+  'c' => true\r
+ ),\r
+ 'lb' => array(\r
+  'com' => true,\r
+  'edu' => true,\r
+  'gov' => true,\r
+  'net' => true,\r
+  'org' => true\r
+ ),\r
+ 'lc' => array(\r
+  'com' => true,\r
+  'net' => true,\r
+  'co' => true,\r
+  'org' => true,\r
+  'edu' => true,\r
+  'gov' => true\r
+ ),\r
+ 'li' => true,\r
+ 'lk' => array(\r
+  'gov' => true,\r
+  'sch' => true,\r
+  'net' => true,\r
+  'int' => true,\r
+  'com' => true,\r
+  'org' => true,\r
+  'edu' => true,\r
+  'ngo' => true,\r
+  'soc' => true,\r
+  'web' => true,\r
+  'ltd' => true,\r
+  'assn' => true,\r
+  'grp' => true,\r
+  'hotel' => true\r
+ ),\r
+ 'lr' => array(\r
+  'com' => true,\r
+  'edu' => true,\r
+  'gov' => true,\r
+  'org' => true,\r
+  'net' => true\r
+ ),\r
+ 'ls' => array(\r
+  'co' => true,\r
+  'org' => true\r
+ ),\r
+ 'lt' => array(\r
+  'gov' => true\r
+ ),\r
+ 'lu' => true,\r
+ 'lv' => array(\r
+  'com' => true,\r
+  'edu' => true,\r
+  'gov' => true,\r
+  'org' => true,\r
+  'mil' => true,\r
+  'id' => true,\r
+  'net' => true,\r
+  'asn' => true,\r
+  'conf' => true\r
+ ),\r
+ 'ly' => array(\r
+  'com' => true,\r
+  'net' => true,\r
+  'gov' => true,\r
+  'plc' => true,\r
+  'edu' => true,\r
+  'sch' => true,\r
+  'med' => true,\r
+  'org' => true,\r
+  'id' => true\r
+ ),\r
+ 'ma' => array(\r
+  'co' => true,\r
+  'net' => true,\r
+  'gov' => true,\r
+  'org' => true,\r
+  'ac' => true,\r
+  'press' => true\r
+ ),\r
+ 'mc' => array(\r
+  'tm' => true,\r
+  'asso' => true\r
+ ),\r
+ 'md' => true,\r
+ 'me' => array(\r
+  'co' => true,\r
+  'net' => true,\r
+  'org' => true,\r
+  'edu' => true,\r
+  'ac' => true,\r
+  'gov' => true,\r
+  'its' => true,\r
+  'priv' => true\r
+ ),\r
+ 'mg' => array(\r
+  'org' => true,\r
+  'nom' => true,\r
+  'gov' => true,\r
+  'prd' => true,\r
+  'tm' => true,\r
+  'edu' => true,\r
+  'mil' => true,\r
+  'com' => true\r
+ ),\r
+ 'mh' => true,\r
+ 'mil' => true,\r
+ 'mk' => array(\r
+  'com' => true,\r
+  'org' => true,\r
+  'net' => true,\r
+  'edu' => true,\r
+  'gov' => true,\r
+  'inf' => true,\r
+  'name' => true\r
+ ),\r
+ 'ml' => array(\r
+  'com' => true,\r
+  'edu' => true,\r
+  'gouv' => true,\r
+  'gov' => true,\r
+  'net' => true,\r
+  'org' => true,\r
+  'presse' => true\r
+ ),\r
+ 'mm' => array(\r
+  '*' => true\r
+ ),\r
+ 'mn' => array(\r
+  'gov' => true,\r
+  'edu' => true,\r
+  'org' => true\r
+ ),\r
+ 'mo' => array(\r
+  'com' => true,\r
+  'net' => true,\r
+  'org' => true,\r
+  'edu' => true,\r
+  'gov' => true\r
+ ),\r
+ 'mobi' => true,\r
+ 'mp' => true,\r
+ 'mq' => true,\r
+ 'mr' => array(\r
+  'gov' => true\r
+ ),\r
+ 'ms' => true,\r
+ 'mt' => array(\r
+  '*' => true\r
+ ),\r
+ 'mu' => array(\r
+  'com' => true,\r
+  'net' => true,\r
+  'org' => true,\r
+  'gov' => true,\r
+  'ac' => true,\r
+  'co' => true,\r
+  'or' => true\r
+ ),\r
+ 'museum' => array(\r
+  'academy' => true,\r
+  'agriculture' => true,\r
+  'air' => true,\r
+  'airguard' => true,\r
+  'alabama' => true,\r
+  'alaska' => true,\r
+  'amber' => true,\r
+  'ambulance' => true,\r
+  'american' => true,\r
+  'americana' => true,\r
+  'americanantiques' => true,\r
+  'americanart' => true,\r
+  'amsterdam' => true,\r
+  'and' => true,\r
+  'annefrank' => true,\r
+  'anthro' => true,\r
+  'anthropology' => true,\r
+  'antiques' => true,\r
+  'aquarium' => true,\r
+  'arboretum' => true,\r
+  'archaeological' => true,\r
+  'archaeology' => true,\r
+  'architecture' => true,\r
+  'art' => true,\r
+  'artanddesign' => true,\r
+  'artcenter' => true,\r
+  'artdeco' => true,\r
+  'arteducation' => true,\r
+  'artgallery' => true,\r
+  'arts' => true,\r
+  'artsandcrafts' => true,\r
+  'asmatart' => true,\r
+  'assassination' => true,\r
+  'assisi' => true,\r
+  'association' => true,\r
+  'astronomy' => true,\r
+  'atlanta' => true,\r
+  'austin' => true,\r
+  'australia' => true,\r
+  'automotive' => true,\r
+  'aviation' => true,\r
+  'axis' => true,\r
+  'badajoz' => true,\r
+  'baghdad' => true,\r
+  'bahn' => true,\r
+  'bale' => true,\r
+  'baltimore' => true,\r
+  'barcelona' => true,\r
+  'baseball' => true,\r
+  'basel' => true,\r
+  'baths' => true,\r
+  'bauern' => true,\r
+  'beauxarts' => true,\r
+  'beeldengeluid' => true,\r
+  'bellevue' => true,\r
+  'bergbau' => true,\r
+  'berkeley' => true,\r
+  'berlin' => true,\r
+  'bern' => true,\r
+  'bible' => true,\r
+  'bilbao' => true,\r
+  'bill' => true,\r
+  'birdart' => true,\r
+  'birthplace' => true,\r
+  'bonn' => true,\r
+  'boston' => true,\r
+  'botanical' => true,\r
+  'botanicalgarden' => true,\r
+  'botanicgarden' => true,\r
+  'botany' => true,\r
+  'brandywinevalley' => true,\r
+  'brasil' => true,\r
+  'bristol' => true,\r
+  'british' => true,\r
+  'britishcolumbia' => true,\r
+  'broadcast' => true,\r
+  'brunel' => true,\r
+  'brussel' => true,\r
+  'brussels' => true,\r
+  'bruxelles' => true,\r
+  'building' => true,\r
+  'burghof' => true,\r
+  'bus' => true,\r
+  'bushey' => true,\r
+  'cadaques' => true,\r
+  'california' => true,\r
+  'cambridge' => true,\r
+  'can' => true,\r
+  'canada' => true,\r
+  'capebreton' => true,\r
+  'carrier' => true,\r
+  'cartoonart' => true,\r
+  'casadelamoneda' => true,\r
+  'castle' => true,\r
+  'castres' => true,\r
+  'celtic' => true,\r
+  'center' => true,\r
+  'chattanooga' => true,\r
+  'cheltenham' => true,\r
+  'chesapeakebay' => true,\r
+  'chicago' => true,\r
+  'children' => true,\r
+  'childrens' => true,\r
+  'childrensgarden' => true,\r
+  'chiropractic' => true,\r
+  'chocolate' => true,\r
+  'christiansburg' => true,\r
+  'cincinnati' => true,\r
+  'cinema' => true,\r
+  'circus' => true,\r
+  'civilisation' => true,\r
+  'civilization' => true,\r
+  'civilwar' => true,\r
+  'clinton' => true,\r
+  'clock' => true,\r
+  'coal' => true,\r
+  'coastaldefence' => true,\r
+  'cody' => true,\r
+  'coldwar' => true,\r
+  'collection' => true,\r
+  'colonialwilliamsburg' => true,\r
+  'coloradoplateau' => true,\r
+  'columbia' => true,\r
+  'columbus' => true,\r
+  'communication' => true,\r
+  'communications' => true,\r
+  'community' => true,\r
+  'computer' => true,\r
+  'computerhistory' => true,\r
+  'comunicações' => true,\r
+  'contemporary' => true,\r
+  'contemporaryart' => true,\r
+  'convent' => true,\r
+  'copenhagen' => true,\r
+  'corporation' => true,\r
+  'correios-e-telecomunicações' => true,\r
+  'corvette' => true,\r
+  'costume' => true,\r
+  'countryestate' => true,\r
+  'county' => true,\r
+  'crafts' => true,\r
+  'cranbrook' => true,\r
+  'creation' => true,\r
+  'cultural' => true,\r
+  'culturalcenter' => true,\r
+  'culture' => true,\r
+  'cyber' => true,\r
+  'cymru' => true,\r
+  'dali' => true,\r
+  'dallas' => true,\r
+  'database' => true,\r
+  'ddr' => true,\r
+  'decorativearts' => true,\r
+  'delaware' => true,\r
+  'delmenhorst' => true,\r
+  'denmark' => true,\r
+  'depot' => true,\r
+  'design' => true,\r
+  'detroit' => true,\r
+  'dinosaur' => true,\r
+  'discovery' => true,\r
+  'dolls' => true,\r
+  'donostia' => true,\r
+  'durham' => true,\r
+  'eastafrica' => true,\r
+  'eastcoast' => true,\r
+  'education' => true,\r
+  'educational' => true,\r
+  'egyptian' => true,\r
+  'eisenbahn' => true,\r
+  'elburg' => true,\r
+  'elvendrell' => true,\r
+  'embroidery' => true,\r
+  'encyclopedic' => true,\r
+  'england' => true,\r
+  'entomology' => true,\r
+  'environment' => true,\r
+  'environmentalconservation' => true,\r
+  'epilepsy' => true,\r
+  'essex' => true,\r
+  'estate' => true,\r
+  'ethnology' => true,\r
+  'exeter' => true,\r
+  'exhibition' => true,\r
+  'family' => true,\r
+  'farm' => true,\r
+  'farmequipment' => true,\r
+  'farmers' => true,\r
+  'farmstead' => true,\r
+  'field' => true,\r
+  'figueres' => true,\r
+  'filatelia' => true,\r
+  'film' => true,\r
+  'fineart' => true,\r
+  'finearts' => true,\r
+  'finland' => true,\r
+  'flanders' => true,\r
+  'florida' => true,\r
+  'force' => true,\r
+  'fortmissoula' => true,\r
+  'fortworth' => true,\r
+  'foundation' => true,\r
+  'francaise' => true,\r
+  'frankfurt' => true,\r
+  'franziskaner' => true,\r
+  'freemasonry' => true,\r
+  'freiburg' => true,\r
+  'fribourg' => true,\r
+  'frog' => true,\r
+  'fundacio' => true,\r
+  'furniture' => true,\r
+  'gallery' => true,\r
+  'garden' => true,\r
+  'gateway' => true,\r
+  'geelvinck' => true,\r
+  'gemological' => true,\r
+  'geology' => true,\r
+  'georgia' => true,\r
+  'giessen' => true,\r
+  'glas' => true,\r
+  'glass' => true,\r
+  'gorge' => true,\r
+  'grandrapids' => true,\r
+  'graz' => true,\r
+  'guernsey' => true,\r
+  'halloffame' => true,\r
+  'hamburg' => true,\r
+  'handson' => true,\r
+  'harvestcelebration' => true,\r
+  'hawaii' => true,\r
+  'health' => true,\r
+  'heimatunduhren' => true,\r
+  'hellas' => true,\r
+  'helsinki' => true,\r
+  'hembygdsforbund' => true,\r
+  'heritage' => true,\r
+  'histoire' => true,\r
+  'historical' => true,\r
+  'historicalsociety' => true,\r
+  'historichouses' => true,\r
+  'historisch' => true,\r
+  'historisches' => true,\r
+  'history' => true,\r
+  'historyofscience' => true,\r
+  'horology' => true,\r
+  'house' => true,\r
+  'humanities' => true,\r
+  'illustration' => true,\r
+  'imageandsound' => true,\r
+  'indian' => true,\r
+  'indiana' => true,\r
+  'indianapolis' => true,\r
+  'indianmarket' => true,\r
+  'intelligence' => true,\r
+  'interactive' => true,\r
+  'iraq' => true,\r
+  'iron' => true,\r
+  'isleofman' => true,\r
+  'jamison' => true,\r
+  'jefferson' => true,\r
+  'jerusalem' => true,\r
+  'jewelry' => true,\r
+  'jewish' => true,\r
+  'jewishart' => true,\r
+  'jfk' => true,\r
+  'journalism' => true,\r
+  'judaica' => true,\r
+  'judygarland' => true,\r
+  'juedisches' => true,\r
+  'juif' => true,\r
+  'karate' => true,\r
+  'karikatur' => true,\r
+  'kids' => true,\r
+  'koebenhavn' => true,\r
+  'koeln' => true,\r
+  'kunst' => true,\r
+  'kunstsammlung' => true,\r
+  'kunstunddesign' => true,\r
+  'labor' => true,\r
+  'labour' => true,\r
+  'lajolla' => true,\r
+  'lancashire' => true,\r
+  'landes' => true,\r
+  'lans' => true,\r
+  'läns' => true,\r
+  'larsson' => true,\r
+  'lewismiller' => true,\r
+  'lincoln' => true,\r
+  'linz' => true,\r
+  'living' => true,\r
+  'livinghistory' => true,\r
+  'localhistory' => true,\r
+  'london' => true,\r
+  'losangeles' => true,\r
+  'louvre' => true,\r
+  'loyalist' => true,\r
+  'lucerne' => true,\r
+  'luxembourg' => true,\r
+  'luzern' => true,\r
+  'mad' => true,\r
+  'madrid' => true,\r
+  'mallorca' => true,\r
+  'manchester' => true,\r
+  'mansion' => true,\r
+  'mansions' => true,\r
+  'manx' => true,\r
+  'marburg' => true,\r
+  'maritime' => true,\r
+  'maritimo' => true,\r
+  'maryland' => true,\r
+  'marylhurst' => true,\r
+  'media' => true,\r
+  'medical' => true,\r
+  'medizinhistorisches' => true,\r
+  'meeres' => true,\r
+  'memorial' => true,\r
+  'mesaverde' => true,\r
+  'michigan' => true,\r
+  'midatlantic' => true,\r
+  'military' => true,\r
+  'mill' => true,\r
+  'miners' => true,\r
+  'mining' => true,\r
+  'minnesota' => true,\r
+  'missile' => true,\r
+  'missoula' => true,\r
+  'modern' => true,\r
+  'moma' => true,\r
+  'money' => true,\r
+  'monmouth' => true,\r
+  'monticello' => true,\r
+  'montreal' => true,\r
+  'moscow' => true,\r
+  'motorcycle' => true,\r
+  'muenchen' => true,\r
+  'muenster' => true,\r
+  'mulhouse' => true,\r
+  'muncie' => true,\r
+  'museet' => true,\r
+  'museumcenter' => true,\r
+  'museumvereniging' => true,\r
+  'music' => true,\r
+  'national' => true,\r
+  'nationalfirearms' => true,\r
+  'nationalheritage' => true,\r
+  'nativeamerican' => true,\r
+  'naturalhistory' => true,\r
+  'naturalhistorymuseum' => true,\r
+  'naturalsciences' => true,\r
+  'nature' => true,\r
+  'naturhistorisches' => true,\r
+  'natuurwetenschappen' => true,\r
+  'naumburg' => true,\r
+  'naval' => true,\r
+  'nebraska' => true,\r
+  'neues' => true,\r
+  'newhampshire' => true,\r
+  'newjersey' => true,\r
+  'newmexico' => true,\r
+  'newport' => true,\r
+  'newspaper' => true,\r
+  'newyork' => true,\r
+  'niepce' => true,\r
+  'norfolk' => true,\r
+  'north' => true,\r
+  'nrw' => true,\r
+  'nuernberg' => true,\r
+  'nuremberg' => true,\r
+  'nyc' => true,\r
+  'nyny' => true,\r
+  'oceanographic' => true,\r
+  'oceanographique' => true,\r
+  'omaha' => true,\r
+  'online' => true,\r
+  'ontario' => true,\r
+  'openair' => true,\r
+  'oregon' => true,\r
+  'oregontrail' => true,\r
+  'otago' => true,\r
+  'oxford' => true,\r
+  'pacific' => true,\r
+  'paderborn' => true,\r
+  'palace' => true,\r
+  'paleo' => true,\r
+  'palmsprings' => true,\r
+  'panama' => true,\r
+  'paris' => true,\r
+  'pasadena' => true,\r
+  'pharmacy' => true,\r
+  'philadelphia' => true,\r
+  'philadelphiaarea' => true,\r
+  'philately' => true,\r
+  'phoenix' => true,\r
+  'photography' => true,\r
+  'pilots' => true,\r
+  'pittsburgh' => true,\r
+  'planetarium' => true,\r
+  'plantation' => true,\r
+  'plants' => true,\r
+  'plaza' => true,\r
+  'portal' => true,\r
+  'portland' => true,\r
+  'portlligat' => true,\r
+  'posts-and-telecommunications' => true,\r
+  'preservation' => true,\r
+  'presidio' => true,\r
+  'press' => true,\r
+  'project' => true,\r
+  'public' => true,\r
+  'pubol' => true,\r
+  'quebec' => true,\r
+  'railroad' => true,\r
+  'railway' => true,\r
+  'research' => true,\r
+  'resistance' => true,\r
+  'riodejaneiro' => true,\r
+  'rochester' => true,\r
+  'rockart' => true,\r
+  'roma' => true,\r
+  'russia' => true,\r
+  'saintlouis' => true,\r
+  'salem' => true,\r
+  'salvadordali' => true,\r
+  'salzburg' => true,\r
+  'sandiego' => true,\r
+  'sanfrancisco' => true,\r
+  'santabarbara' => true,\r
+  'santacruz' => true,\r
+  'santafe' => true,\r
+  'saskatchewan' => true,\r
+  'satx' => true,\r
+  'savannahga' => true,\r
+  'schlesisches' => true,\r
+  'schoenbrunn' => true,\r
+  'schokoladen' => true,\r
+  'school' => true,\r
+  'schweiz' => true,\r
+  'science' => true,\r
+  'scienceandhistory' => true,\r
+  'scienceandindustry' => true,\r
+  'sciencecenter' => true,\r
+  'sciencecenters' => true,\r
+  'science-fiction' => true,\r
+  'sciencehistory' => true,\r
+  'sciences' => true,\r
+  'sciencesnaturelles' => true,\r
+  'scotland' => true,\r
+  'seaport' => true,\r
+  'settlement' => true,\r
+  'settlers' => true,\r
+  'shell' => true,\r
+  'sherbrooke' => true,\r
+  'sibenik' => true,\r
+  'silk' => true,\r
+  'ski' => true,\r
+  'skole' => true,\r
+  'society' => true,\r
+  'sologne' => true,\r
+  'soundandvision' => true,\r
+  'southcarolina' => true,\r
+  'southwest' => true,\r
+  'space' => true,\r
+  'spy' => true,\r
+  'square' => true,\r
+  'stadt' => true,\r
+  'stalbans' => true,\r
+  'starnberg' => true,\r
+  'state' => true,\r
+  'stateofdelaware' => true,\r
+  'station' => true,\r
+  'steam' => true,\r
+  'steiermark' => true,\r
+  'stjohn' => true,\r
+  'stockholm' => true,\r
+  'stpetersburg' => true,\r
+  'stuttgart' => true,\r
+  'suisse' => true,\r
+  'surgeonshall' => true,\r
+  'surrey' => true,\r
+  'svizzera' => true,\r
+  'sweden' => true,\r
+  'sydney' => true,\r
+  'tank' => true,\r
+  'tcm' => true,\r
+  'technology' => true,\r
+  'telekommunikation' => true,\r
+  'television' => true,\r
+  'texas' => true,\r
+  'textile' => true,\r
+  'theater' => true,\r
+  'time' => true,\r
+  'timekeeping' => true,\r
+  'topology' => true,\r
+  'torino' => true,\r
+  'touch' => true,\r
+  'town' => true,\r
+  'transport' => true,\r
+  'tree' => true,\r
+  'trolley' => true,\r
+  'trust' => true,\r
+  'trustee' => true,\r
+  'uhren' => true,\r
+  'ulm' => true,\r
+  'undersea' => true,\r
+  'university' => true,\r
+  'usa' => true,\r
+  'usantiques' => true,\r
+  'usarts' => true,\r
+  'uscountryestate' => true,\r
+  'usculture' => true,\r
+  'usdecorativearts' => true,\r
+  'usgarden' => true,\r
+  'ushistory' => true,\r
+  'ushuaia' => true,\r
+  'uslivinghistory' => true,\r
+  'utah' => true,\r
+  'uvic' => true,\r
+  'valley' => true,\r
+  'vantaa' => true,\r
+  'versailles' => true,\r
+  'viking' => true,\r
+  'village' => true,\r
+  'virginia' => true,\r
+  'virtual' => true,\r
+  'virtuel' => true,\r
+  'vlaanderen' => true,\r
+  'volkenkunde' => true,\r
+  'wales' => true,\r
+  'wallonie' => true,\r
+  'war' => true,\r
+  'washingtondc' => true,\r
+  'watchandclock' => true,\r
+  'watch-and-clock' => true,\r
+  'western' => true,\r
+  'westfalen' => true,\r
+  'whaling' => true,\r
+  'wildlife' => true,\r
+  'williamsburg' => true,\r
+  'windmill' => true,\r
+  'workshop' => true,\r
+  'york' => true,\r
+  'yorkshire' => true,\r
+  'yosemite' => true,\r
+  'youth' => true,\r
+  'zoological' => true,\r
+  'zoology' => true,\r
+  'ירושלים' => true,\r
+  'иком' => true\r
+ ),\r
+ 'mv' => array(\r
+  'aero' => true,\r
+  'biz' => true,\r
+  'com' => true,\r
+  'coop' => true,\r
+  'edu' => true,\r
+  'gov' => true,\r
+  'info' => true,\r
+  'int' => true,\r
+  'mil' => true,\r
+  'museum' => true,\r
+  'name' => true,\r
+  'net' => true,\r
+  'org' => true,\r
+  'pro' => true\r
+ ),\r
+ 'mw' => array(\r
+  'ac' => true,\r
+  'biz' => true,\r
+  'co' => true,\r
+  'com' => true,\r
+  'coop' => true,\r
+  'edu' => true,\r
+  'gov' => true,\r
+  'int' => true,\r
+  'museum' => true,\r
+  'net' => true,\r
+  'org' => true\r
+ ),\r
+ 'mx' => array(\r
+  'com' => true,\r
+  'org' => true,\r
+  'gob' => true,\r
+  'edu' => true,\r
+  'net' => true\r
+ ),\r
+ 'my' => array(\r
+  'com' => true,\r
+  'net' => true,\r
+  'org' => true,\r
+  'gov' => true,\r
+  'edu' => true,\r
+  'mil' => true,\r
+  'name' => true\r
+ ),\r
+ 'mz' => array(\r
+  '*' => true\r
+ ),\r
+ 'na' => array(\r
+  'info' => true,\r
+  'pro' => true,\r
+  'name' => true,\r
+  'school' => true,\r
+  'or' => true,\r
+  'dr' => true,\r
+  'us' => true,\r
+  'mx' => true,\r
+  'ca' => true,\r
+  'in' => true,\r
+  'cc' => true,\r
+  'tv' => true,\r
+  'ws' => true,\r
+  'mobi' => true,\r
+  'co' => true,\r
+  'com' => true,\r
+  'org' => true\r
+ ),\r
+ 'name' => array(\r
+  'her' => array(\r
+   'forgot' => true\r
+  ),\r
+  'his' => array(\r
+   'forgot' => true\r
+  )\r
+ ),\r
+ 'nc' => array(\r
+  'asso' => true\r
+ ),\r
+ 'ne' => true,\r
+ 'net' => array(\r
+  'gb' => true,\r
+  'jp' => true,\r
+  'se' => true,\r
+  'uk' => true,\r
+  'za' => true,\r
+  'at-band-camp' => true,\r
+  'blogdns' => true,\r
+  'broke-it' => true,\r
+  'buyshouses' => true,\r
+  'dnsalias' => true,\r
+  'dnsdojo' => true,\r
+  'does-it' => true,\r
+  'dontexist' => true,\r
+  'dynalias' => true,\r
+  'dynathome' => true,\r
+  'endofinternet' => true,\r
+  'from-az' => true,\r
+  'from-co' => true,\r
+  'from-la' => true,\r
+  'from-ny' => true,\r
+  'gets-it' => true,\r
+  'ham-radio-op' => true,\r
+  'homeftp' => true,\r
+  'homeip' => true,\r
+  'homelinux' => true,\r
+  'homeunix' => true,\r
+  'in-the-band' => true,\r
+  'is-a-chef' => true,\r
+  'is-a-geek' => true,\r
+  'isa-geek' => true,\r
+  'kicks-ass' => true,\r
+  'office-on-the' => true,\r
+  'podzone' => true,\r
+  'scrapper-site' => true,\r
+  'selfip' => true,\r
+  'sells-it' => true,\r
+  'servebbs' => true,\r
+  'serveftp' => true,\r
+  'thruhere' => true,\r
+  'webhop' => true\r
+ ),\r
+ 'nf' => array(\r
+  'com' => true,\r
+  'net' => true,\r
+  'per' => true,\r
+  'rec' => true,\r
+  'web' => true,\r
+  'arts' => true,\r
+  'firm' => true,\r
+  'info' => true,\r
+  'other' => true,\r
+  'store' => true\r
+ ),\r
+ 'ng' => array(\r
+  'ac' => true,\r
+  'com' => true,\r
+  'edu' => true,\r
+  'gov' => true,\r
+  'net' => true,\r
+  'org' => true\r
+ ),\r
+ 'ni' => array(\r
+  '*' => true\r
+ ),\r
+ 'nl' => array(\r
+  'bv' => true,\r
+  'co' => true\r
+ ),\r
+ 'no' => array(\r
+  'fhs' => true,\r
+  'vgs' => true,\r
+  'fylkesbibl' => true,\r
+  'folkebibl' => true,\r
+  'museum' => true,\r
+  'idrett' => true,\r
+  'priv' => true,\r
+  'mil' => true,\r
+  'stat' => true,\r
+  'dep' => true,\r
+  'kommune' => true,\r
+  'herad' => true,\r
+  'aa' => array(\r
+   'gs' => true\r
+  ),\r
+  'ah' => array(\r
+   'gs' => true\r
+  ),\r
+  'bu' => array(\r
+   'gs' => true\r
+  ),\r
+  'fm' => array(\r
+   'gs' => true\r
+  ),\r
+  'hl' => array(\r
+   'gs' => true\r
+  ),\r
+  'hm' => array(\r
+   'gs' => true\r
+  ),\r
+  'jan-mayen' => array(\r
+   'gs' => true\r
+  ),\r
+  'mr' => array(\r
+   'gs' => true\r
+  ),\r
+  'nl' => array(\r
+   'gs' => true\r
+  ),\r
+  'nt' => array(\r
+   'gs' => true\r
+  ),\r
+  'of' => array(\r
+   'gs' => true\r
+  ),\r
+  'ol' => array(\r
+   'gs' => true\r
+  ),\r
+  'oslo' => array(\r
+   'gs' => true\r
+  ),\r
+  'rl' => array(\r
+   'gs' => true\r
+  ),\r
+  'sf' => array(\r
+   'gs' => true\r
+  ),\r
+  'st' => array(\r
+   'gs' => true\r
+  ),\r
+  'svalbard' => array(\r
+   'gs' => true\r
+  ),\r
+  'tm' => array(\r
+   'gs' => true\r
+  ),\r
+  'tr' => array(\r
+   'gs' => true\r
+  ),\r
+  'va' => array(\r
+   'gs' => true\r
+  ),\r
+  'vf' => array(\r
+   'gs' => true\r
+  ),\r
+  'akrehamn' => true,\r
+  'åkrehamn' => true,\r
+  'algard' => true,\r
+  'ålgård' => true,\r
+  'arna' => true,\r
+  'brumunddal' => true,\r
+  'bryne' => true,\r
+  'bronnoysund' => true,\r
+  'brønnøysund' => true,\r
+  'drobak' => true,\r
+  'drøbak' => true,\r
+  'egersund' => true,\r
+  'fetsund' => true,\r
+  'floro' => true,\r
+  'florø' => true,\r
+  'fredrikstad' => true,\r
+  'hokksund' => true,\r
+  'honefoss' => true,\r
+  'hønefoss' => true,\r
+  'jessheim' => true,\r
+  'jorpeland' => true,\r
+  'jørpeland' => true,\r
+  'kirkenes' => true,\r
+  'kopervik' => true,\r
+  'krokstadelva' => true,\r
+  'langevag' => true,\r
+  'langevåg' => true,\r
+  'leirvik' => true,\r
+  'mjondalen' => true,\r
+  'mjøndalen' => true,\r
+  'mo-i-rana' => true,\r
+  'mosjoen' => true,\r
+  'mosjøen' => true,\r
+  'nesoddtangen' => true,\r
+  'orkanger' => true,\r
+  'osoyro' => true,\r
+  'osøyro' => true,\r
+  'raholt' => true,\r
+  'råholt' => true,\r
+  'sandnessjoen' => true,\r
+  'sandnessjøen' => true,\r
+  'skedsmokorset' => true,\r
+  'slattum' => true,\r
+  'spjelkavik' => true,\r
+  'stathelle' => true,\r
+  'stavern' => true,\r
+  'stjordalshalsen' => true,\r
+  'stjørdalshalsen' => true,\r
+  'tananger' => true,\r
+  'tranby' => true,\r
+  'vossevangen' => true,\r
+  'afjord' => true,\r
+  'åfjord' => true,\r
+  'agdenes' => true,\r
+  'al' => true,\r
+  'ål' => true,\r
+  'alesund' => true,\r
+  'ålesund' => true,\r
+  'alstahaug' => true,\r
+  'alta' => true,\r
+  'áltá' => true,\r
+  'alaheadju' => true,\r
+  'álaheadju' => true,\r
+  'alvdal' => true,\r
+  'amli' => true,\r
+  'åmli' => true,\r
+  'amot' => true,\r
+  'åmot' => true,\r
+  'andebu' => true,\r
+  'andoy' => true,\r
+  'andøy' => true,\r
+  'andasuolo' => true,\r
+  'ardal' => true,\r
+  'årdal' => true,\r
+  'aremark' => true,\r
+  'arendal' => true,\r
+  'ås' => true,\r
+  'aseral' => true,\r
+  'åseral' => true,\r
+  'asker' => true,\r
+  'askim' => true,\r
+  'askvoll' => true,\r
+  'askoy' => true,\r
+  'askøy' => true,\r
+  'asnes' => true,\r
+  'åsnes' => true,\r
+  'audnedaln' => true,\r
+  'aukra' => true,\r
+  'aure' => true,\r
+  'aurland' => true,\r
+  'aurskog-holand' => true,\r
+  'aurskog-høland' => true,\r
+  'austevoll' => true,\r
+  'austrheim' => true,\r
+  'averoy' => true,\r
+  'averøy' => true,\r
+  'balestrand' => true,\r
+  'ballangen' => true,\r
+  'balat' => true,\r
+  'bálát' => true,\r
+  'balsfjord' => true,\r
+  'bahccavuotna' => true,\r
+  'báhccavuotna' => true,\r
+  'bamble' => true,\r
+  'bardu' => true,\r
+  'beardu' => true,\r
+  'beiarn' => true,\r
+  'bajddar' => true,\r
+  'bájddar' => true,\r
+  'baidar' => true,\r
+  'báidár' => true,\r
+  'berg' => true,\r
+  'bergen' => true,\r
+  'berlevag' => true,\r
+  'berlevåg' => true,\r
+  'bearalvahki' => true,\r
+  'bearalváhki' => true,\r
+  'bindal' => true,\r
+  'birkenes' => true,\r
+  'bjarkoy' => true,\r
+  'bjarkøy' => true,\r
+  'bjerkreim' => true,\r
+  'bjugn' => true,\r
+  'bodo' => true,\r
+  'bodø' => true,\r
+  'badaddja' => true,\r
+  'bådåddjå' => true,\r
+  'budejju' => true,\r
+  'bokn' => true,\r
+  'bremanger' => true,\r
+  'bronnoy' => true,\r
+  'brønnøy' => true,\r
+  'bygland' => true,\r
+  'bykle' => true,\r
+  'barum' => true,\r
+  'bærum' => true,\r
+  'telemark' => array(\r
+   'bo' => true,\r
+   'bø' => true\r
+  ),\r
+  'nordland' => array(\r
+   'bo' => true,\r
+   'bø' => true,\r
+   'heroy' => true,\r
+   'herøy' => true\r
+  ),\r
+  'bievat' => true,\r
+  'bievát' => true,\r
+  'bomlo' => true,\r
+  'bømlo' => true,\r
+  'batsfjord' => true,\r
+  'båtsfjord' => true,\r
+  'bahcavuotna' => true,\r
+  'báhcavuotna' => true,\r
+  'dovre' => true,\r
+  'drammen' => true,\r
+  'drangedal' => true,\r
+  'dyroy' => true,\r
+  'dyrøy' => true,\r
+  'donna' => true,\r
+  'dønna' => true,\r
+  'eid' => true,\r
+  'eidfjord' => true,\r
+  'eidsberg' => true,\r
+  'eidskog' => true,\r
+  'eidsvoll' => true,\r
+  'eigersund' => true,\r
+  'elverum' => true,\r
+  'enebakk' => true,\r
+  'engerdal' => true,\r
+  'etne' => true,\r
+  'etnedal' => true,\r
+  'evenes' => true,\r
+  'evenassi' => true,\r
+  'evenášši' => true,\r
+  'evje-og-hornnes' => true,\r
+  'farsund' => true,\r
+  'fauske' => true,\r
+  'fuossko' => true,\r
+  'fuoisku' => true,\r
+  'fedje' => true,\r
+  'fet' => true,\r
+  'finnoy' => true,\r
+  'finnøy' => true,\r
+  'fitjar' => true,\r
+  'fjaler' => true,\r
+  'fjell' => true,\r
+  'flakstad' => true,\r
+  'flatanger' => true,\r
+  'flekkefjord' => true,\r
+  'flesberg' => true,\r
+  'flora' => true,\r
+  'fla' => true,\r
+  'flå' => true,\r
+  'folldal' => true,\r
+  'forsand' => true,\r
+  'fosnes' => true,\r
+  'frei' => true,\r
+  'frogn' => true,\r
+  'froland' => true,\r
+  'frosta' => true,\r
+  'frana' => true,\r
+  'fræna' => true,\r
+  'froya' => true,\r
+  'frøya' => true,\r
+  'fusa' => true,\r
+  'fyresdal' => true,\r
+  'forde' => true,\r
+  'førde' => true,\r
+  'gamvik' => true,\r
+  'gangaviika' => true,\r
+  'gáŋgaviika' => true,\r
+  'gaular' => true,\r
+  'gausdal' => true,\r
+  'gildeskal' => true,\r
+  'gildeskål' => true,\r
+  'giske' => true,\r
+  'gjemnes' => true,\r
+  'gjerdrum' => true,\r
+  'gjerstad' => true,\r
+  'gjesdal' => true,\r
+  'gjovik' => true,\r
+  'gjøvik' => true,\r
+  'gloppen' => true,\r
+  'gol' => true,\r
+  'gran' => true,\r
+  'grane' => true,\r
+  'granvin' => true,\r
+  'gratangen' => true,\r
+  'grimstad' => true,\r
+  'grong' => true,\r
+  'kraanghke' => true,\r
+  'kråanghke' => true,\r
+  'grue' => true,\r
+  'gulen' => true,\r
+  'hadsel' => true,\r
+  'halden' => true,\r
+  'halsa' => true,\r
+  'hamar' => true,\r
+  'hamaroy' => true,\r
+  'habmer' => true,\r
+  'hábmer' => true,\r
+  'hapmir' => true,\r
+  'hápmir' => true,\r
+  'hammerfest' => true,\r
+  'hammarfeasta' => true,\r
+  'hámmárfeasta' => true,\r
+  'haram' => true,\r
+  'hareid' => true,\r
+  'harstad' => true,\r
+  'hasvik' => true,\r
+  'aknoluokta' => true,\r
+  'ákŋoluokta' => true,\r
+  'hattfjelldal' => true,\r
+  'aarborte' => true,\r
+  'haugesund' => true,\r
+  'hemne' => true,\r
+  'hemnes' => true,\r
+  'hemsedal' => true,\r
+  'more-og-romsdal' => array(\r
+   'heroy' => true,\r
+   'sande' => true\r
+  ),\r
+  'møre-og-romsdal' => array(\r
+   'herøy' => true,\r
+   'sande' => true\r
+  ),\r
+  'hitra' => true,\r
+  'hjartdal' => true,\r
+  'hjelmeland' => true,\r
+  'hobol' => true,\r
+  'hobøl' => true,\r
+  'hof' => true,\r
+  'hol' => true,\r
+  'hole' => true,\r
+  'holmestrand' => true,\r
+  'holtalen' => true,\r
+  'holtålen' => true,\r
+  'hornindal' => true,\r
+  'horten' => true,\r
+  'hurdal' => true,\r
+  'hurum' => true,\r
+  'hvaler' => true,\r
+  'hyllestad' => true,\r
+  'hagebostad' => true,\r
+  'hægebostad' => true,\r
+  'hoyanger' => true,\r
+  'høyanger' => true,\r
+  'hoylandet' => true,\r
+  'høylandet' => true,\r
+  'ha' => true,\r
+  'hå' => true,\r
+  'ibestad' => true,\r
+  'inderoy' => true,\r
+  'inderøy' => true,\r
+  'iveland' => true,\r
+  'jevnaker' => true,\r
+  'jondal' => true,\r
+  'jolster' => true,\r
+  'jølster' => true,\r
+  'karasjok' => true,\r
+  'karasjohka' => true,\r
+  'kárášjohka' => true,\r
+  'karlsoy' => true,\r
+  'galsa' => true,\r
+  'gálsá' => true,\r
+  'karmoy' => true,\r
+  'karmøy' => true,\r
+  'kautokeino' => true,\r
+  'guovdageaidnu' => true,\r
+  'klepp' => true,\r
+  'klabu' => true,\r
+  'klæbu' => true,\r
+  'kongsberg' => true,\r
+  'kongsvinger' => true,\r
+  'kragero' => true,\r
+  'kragerø' => true,\r
+  'kristiansand' => true,\r
+  'kristiansund' => true,\r
+  'krodsherad' => true,\r
+  'krødsherad' => true,\r
+  'kvalsund' => true,\r
+  'rahkkeravju' => true,\r
+  'ráhkkerávju' => true,\r
+  'kvam' => true,\r
+  'kvinesdal' => true,\r
+  'kvinnherad' => true,\r
+  'kviteseid' => true,\r
+  'kvitsoy' => true,\r
+  'kvitsøy' => true,\r
+  'kvafjord' => true,\r
+  'kvæfjord' => true,\r
+  'giehtavuoatna' => true,\r
+  'kvanangen' => true,\r
+  'kvænangen' => true,\r
+  'navuotna' => true,\r
+  'návuotna' => true,\r
+  'kafjord' => true,\r
+  'kåfjord' => true,\r
+  'gaivuotna' => true,\r
+  'gáivuotna' => true,\r
+  'larvik' => true,\r
+  'lavangen' => true,\r
+  'lavagis' => true,\r
+  'loabat' => true,\r
+  'loabát' => true,\r
+  'lebesby' => true,\r
+  'davvesiida' => true,\r
+  'leikanger' => true,\r
+  'leirfjord' => true,\r
+  'leka' => true,\r
+  'leksvik' => true,\r
+  'lenvik' => true,\r
+  'leangaviika' => true,\r
+  'leaŋgaviika' => true,\r
+  'lesja' => true,\r
+  'levanger' => true,\r
+  'lier' => true,\r
+  'lierne' => true,\r
+  'lillehammer' => true,\r
+  'lillesand' => true,\r
+  'lindesnes' => true,\r
+  'lindas' => true,\r
+  'lindås' => true,\r
+  'lom' => true,\r
+  'loppa' => true,\r
+  'lahppi' => true,\r
+  'láhppi' => true,\r
+  'lund' => true,\r
+  'lunner' => true,\r
+  'luroy' => true,\r
+  'lurøy' => true,\r
+  'luster' => true,\r
+  'lyngdal' => true,\r
+  'lyngen' => true,\r
+  'ivgu' => true,\r
+  'lardal' => true,\r
+  'lerdal' => true,\r
+  'lærdal' => true,\r
+  'lodingen' => true,\r
+  'lødingen' => true,\r
+  'lorenskog' => true,\r
+  'lørenskog' => true,\r
+  'loten' => true,\r
+  'løten' => true,\r
+  'malvik' => true,\r
+  'masoy' => true,\r
+  'måsøy' => true,\r
+  'muosat' => true,\r
+  'muosát' => true,\r
+  'mandal' => true,\r
+  'marker' => true,\r
+  'marnardal' => true,\r
+  'masfjorden' => true,\r
+  'meland' => true,\r
+  'meldal' => true,\r
+  'melhus' => true,\r
+  'meloy' => true,\r
+  'meløy' => true,\r
+  'meraker' => true,\r
+  'meråker' => true,\r
+  'moareke' => true,\r
+  'moåreke' => true,\r
+  'midsund' => true,\r
+  'midtre-gauldal' => true,\r
+  'modalen' => true,\r
+  'modum' => true,\r
+  'molde' => true,\r
+  'moskenes' => true,\r
+  'moss' => true,\r
+  'mosvik' => true,\r
+  'malselv' => true,\r
+  'målselv' => true,\r
+  'malatvuopmi' => true,\r
+  'málatvuopmi' => true,\r
+  'namdalseid' => true,\r
+  'aejrie' => true,\r
+  'namsos' => true,\r
+  'namsskogan' => true,\r
+  'naamesjevuemie' => true,\r
+  'nååmesjevuemie' => true,\r
+  'laakesvuemie' => true,\r
+  'nannestad' => true,\r
+  'narvik' => true,\r
+  'narviika' => true,\r
+  'naustdal' => true,\r
+  'nedre-eiker' => true,\r
+  'akershus' => array(\r
+   'nes' => true\r
+  ),\r
+  'buskerud' => array(\r
+   'nes' => true\r
+  ),\r
+  'nesna' => true,\r
+  'nesodden' => true,\r
+  'nesseby' => true,\r
+  'unjarga' => true,\r
+  'unjárga' => true,\r
+  'nesset' => true,\r
+  'nissedal' => true,\r
+  'nittedal' => true,\r
+  'nord-aurdal' => true,\r
+  'nord-fron' => true,\r
+  'nord-odal' => true,\r
+  'norddal' => true,\r
+  'nordkapp' => true,\r
+  'davvenjarga' => true,\r
+  'davvenjárga' => true,\r
+  'nordre-land' => true,\r
+  'nordreisa' => true,\r
+  'raisa' => true,\r
+  'ráisa' => true,\r
+  'nore-og-uvdal' => true,\r
+  'notodden' => true,\r
+  'naroy' => true,\r
+  'nærøy' => true,\r
+  'notteroy' => true,\r
+  'nøtterøy' => true,\r
+  'odda' => true,\r
+  'oksnes' => true,\r
+  'øksnes' => true,\r
+  'oppdal' => true,\r
+  'oppegard' => true,\r
+  'oppegård' => true,\r
+  'orkdal' => true,\r
+  'orland' => true,\r
+  'ørland' => true,\r
+  'orskog' => true,\r
+  'ørskog' => true,\r
+  'orsta' => true,\r
+  'ørsta' => true,\r
+  'hedmark' => array(\r
+   'os' => true,\r
+   'valer' => true,\r
+   'våler' => true\r
+  ),\r
+  'hordaland' => array(\r
+   'os' => true\r
+  ),\r
+  'osen' => true,\r
+  'osteroy' => true,\r
+  'osterøy' => true,\r
+  'ostre-toten' => true,\r
+  'østre-toten' => true,\r
+  'overhalla' => true,\r
+  'ovre-eiker' => true,\r
+  'øvre-eiker' => true,\r
+  'oyer' => true,\r
+  'øyer' => true,\r
+  'oygarden' => true,\r
+  'øygarden' => true,\r
+  'oystre-slidre' => true,\r
+  'øystre-slidre' => true,\r
+  'porsanger' => true,\r
+  'porsangu' => true,\r
+  'porsáŋgu' => true,\r
+  'porsgrunn' => true,\r
+  'radoy' => true,\r
+  'radøy' => true,\r
+  'rakkestad' => true,\r
+  'rana' => true,\r
+  'ruovat' => true,\r
+  'randaberg' => true,\r
+  'rauma' => true,\r
+  'rendalen' => true,\r
+  'rennebu' => true,\r
+  'rennesoy' => true,\r
+  'rennesøy' => true,\r
+  'rindal' => true,\r
+  'ringebu' => true,\r
+  'ringerike' => true,\r
+  'ringsaker' => true,\r
+  'rissa' => true,\r
+  'risor' => true,\r
+  'risør' => true,\r
+  'roan' => true,\r
+  'rollag' => true,\r
+  'rygge' => true,\r
+  'ralingen' => true,\r
+  'rælingen' => true,\r
+  'rodoy' => true,\r
+  'rødøy' => true,\r
+  'romskog' => true,\r
+  'rømskog' => true,\r
+  'roros' => true,\r
+  'røros' => true,\r
+  'rost' => true,\r
+  'røst' => true,\r
+  'royken' => true,\r
+  'røyken' => true,\r
+  'royrvik' => true,\r
+  'røyrvik' => true,\r
+  'rade' => true,\r
+  'råde' => true,\r
+  'salangen' => true,\r
+  'siellak' => true,\r
+  'saltdal' => true,\r
+  'salat' => true,\r
+  'sálát' => true,\r
+  'sálat' => true,\r
+  'samnanger' => true,\r
+  'vestfold' => array(\r
+   'sande' => true\r
+  ),\r
+  'sandefjord' => true,\r
+  'sandnes' => true,\r
+  'sandoy' => true,\r
+  'sandøy' => true,\r
+  'sarpsborg' => true,\r
+  'sauda' => true,\r
+  'sauherad' => true,\r
+  'sel' => true,\r
+  'selbu' => true,\r
+  'selje' => true,\r
+  'seljord' => true,\r
+  'sigdal' => true,\r
+  'siljan' => true,\r
+  'sirdal' => true,\r
+  'skaun' => true,\r
+  'skedsmo' => true,\r
+  'ski' => true,\r
+  'skien' => true,\r
+  'skiptvet' => true,\r
+  'skjervoy' => true,\r
+  'skjervøy' => true,\r
+  'skierva' => true,\r
+  'skiervá' => true,\r
+  'skjak' => true,\r
+  'skjåk' => true,\r
+  'skodje' => true,\r
+  'skanland' => true,\r
+  'skånland' => true,\r
+  'skanit' => true,\r
+  'skánit' => true,\r
+  'smola' => true,\r
+  'smøla' => true,\r
+  'snillfjord' => true,\r
+  'snasa' => true,\r
+  'snåsa' => true,\r
+  'snoasa' => true,\r
+  'snaase' => true,\r
+  'snåase' => true,\r
+  'sogndal' => true,\r
+  'sokndal' => true,\r
+  'sola' => true,\r
+  'solund' => true,\r
+  'songdalen' => true,\r
+  'sortland' => true,\r
+  'spydeberg' => true,\r
+  'stange' => true,\r
+  'stavanger' => true,\r
+  'steigen' => true,\r
+  'steinkjer' => true,\r
+  'stjordal' => true,\r
+  'stjørdal' => true,\r
+  'stokke' => true,\r
+  'stor-elvdal' => true,\r
+  'stord' => true,\r
+  'stordal' => true,\r
+  'storfjord' => true,\r
+  'omasvuotna' => true,\r
+  'strand' => true,\r
+  'stranda' => true,\r
+  'stryn' => true,\r
+  'sula' => true,\r
+  'suldal' => true,\r
+  'sund' => true,\r
+  'sunndal' => true,\r
+  'surnadal' => true,\r
+  'sveio' => true,\r
+  'svelvik' => true,\r
+  'sykkylven' => true,\r
+  'sogne' => true,\r
+  'søgne' => true,\r
+  'somna' => true,\r
+  'sømna' => true,\r
+  'sondre-land' => true,\r
+  'søndre-land' => true,\r
+  'sor-aurdal' => true,\r
+  'sør-aurdal' => true,\r
+  'sor-fron' => true,\r
+  'sør-fron' => true,\r
+  'sor-odal' => true,\r
+  'sør-odal' => true,\r
+  'sor-varanger' => true,\r
+  'sør-varanger' => true,\r
+  'matta-varjjat' => true,\r
+  'mátta-várjjat' => true,\r
+  'sorfold' => true,\r
+  'sørfold' => true,\r
+  'sorreisa' => true,\r
+  'sørreisa' => true,\r
+  'sorum' => true,\r
+  'sørum' => true,\r
+  'tana' => true,\r
+  'deatnu' => true,\r
+  'time' => true,\r
+  'tingvoll' => true,\r
+  'tinn' => true,\r
+  'tjeldsund' => true,\r
+  'dielddanuorri' => true,\r
+  'tjome' => true,\r
+  'tjøme' => true,\r
+  'tokke' => true,\r
+  'tolga' => true,\r
+  'torsken' => true,\r
+  'tranoy' => true,\r
+  'tranøy' => true,\r
+  'tromso' => true,\r
+  'tromsø' => true,\r
+  'tromsa' => true,\r
+  'romsa' => true,\r
+  'trondheim' => true,\r
+  'troandin' => true,\r
+  'trysil' => true,\r
+  'trana' => true,\r
+  'træna' => true,\r
+  'trogstad' => true,\r
+  'trøgstad' => true,\r
+  'tvedestrand' => true,\r
+  'tydal' => true,\r
+  'tynset' => true,\r
+  'tysfjord' => true,\r
+  'divtasvuodna' => true,\r
+  'divttasvuotna' => true,\r
+  'tysnes' => true,\r
+  'tysvar' => true,\r
+  'tysvær' => true,\r
+  'tonsberg' => true,\r
+  'tønsberg' => true,\r
+  'ullensaker' => true,\r
+  'ullensvang' => true,\r
+  'ulvik' => true,\r
+  'utsira' => true,\r
+  'vadso' => true,\r
+  'vadsø' => true,\r
+  'cahcesuolo' => true,\r
+  'čáhcesuolo' => true,\r
+  'vaksdal' => true,\r
+  'valle' => true,\r
+  'vang' => true,\r
+  'vanylven' => true,\r
+  'vardo' => true,\r
+  'vardø' => true,\r
+  'varggat' => true,\r
+  'várggát' => true,\r
+  'vefsn' => true,\r
+  'vaapste' => true,\r
+  'vega' => true,\r
+  'vegarshei' => true,\r
+  'vegårshei' => true,\r
+  'vennesla' => true,\r
+  'verdal' => true,\r
+  'verran' => true,\r
+  'vestby' => true,\r
+  'vestnes' => true,\r
+  'vestre-slidre' => true,\r
+  'vestre-toten' => true,\r
+  'vestvagoy' => true,\r
+  'vestvågøy' => true,\r
+  'vevelstad' => true,\r
+  'vik' => true,\r
+  'vikna' => true,\r
+  'vindafjord' => true,\r
+  'volda' => true,\r
+  'voss' => true,\r
+  'varoy' => true,\r
+  'værøy' => true,\r
+  'vagan' => true,\r
+  'vågan' => true,\r
+  'voagat' => true,\r
+  'vagsoy' => true,\r
+  'vågsøy' => true,\r
+  'vaga' => true,\r
+  'vågå' => true,\r
+  'ostfold' => array(\r
+   'valer' => true\r
+  ),\r
+  'østfold' => array(\r
+   'våler' => true\r
+  ),\r
+  'co' => true\r
+ ),\r
+ 'np' => array(\r
+  '*' => true\r
+ ),\r
+ 'nr' => array(\r
+  'biz' => true,\r
+  'info' => true,\r
+  'gov' => true,\r
+  'edu' => true,\r
+  'org' => true,\r
+  'net' => true,\r
+  'com' => true\r
+ ),\r
+ 'nu' => array(\r
+  'merseine' => true,\r
+  'mine' => true,\r
+  'shacknet' => true\r
+ ),\r
+ 'nz' => array(\r
+  '*' => true\r
+ ),\r
+ 'om' => array(\r
+  '*' => true,\r
+  '!mediaphone' => true,\r
+  '!nawrastelecom' => true,\r
+  '!nawras' => true,\r
+  '!omanmobile' => true,\r
+  '!omanpost' => true,\r
+  '!omantel' => true,\r
+  '!rakpetroleum' => true,\r
+  '!siemens' => true,\r
+  '!songfest' => true,\r
+  '!statecouncil' => true\r
+ ),\r
+ 'org' => array(\r
+  'ae' => true,\r
+  'us' => true,\r
+  'za' => true,\r
+  'dyndns' => array(\r
+   'go' => true,\r
+   'home' => true\r
+  ),\r
+  'blogdns' => true,\r
+  'blogsite' => true,\r
+  'boldlygoingnowhere' => true,\r
+  'dnsalias' => true,\r
+  'dnsdojo' => true,\r
+  'doesntexist' => true,\r
+  'dontexist' => true,\r
+  'doomdns' => true,\r
+  'dvrdns' => true,\r
+  'dynalias' => true,\r
+  'endofinternet' => true,\r
+  'endoftheinternet' => true,\r
+  'from-me' => true,\r
+  'game-host' => true,\r
+  'gotdns' => true,\r
+  'hobby-site' => true,\r
+  'homedns' => true,\r
+  'homeftp' => true,\r
+  'homelinux' => true,\r
+  'homeunix' => true,\r
+  'is-a-bruinsfan' => true,\r
+  'is-a-candidate' => true,\r
+  'is-a-celticsfan' => true,\r
+  'is-a-chef' => true,\r
+  'is-a-geek' => true,\r
+  'is-a-knight' => true,\r
+  'is-a-linux-user' => true,\r
+  'is-a-patsfan' => true,\r
+  'is-a-soxfan' => true,\r
+  'is-found' => true,\r
+  'is-lost' => true,\r
+  'is-saved' => true,\r
+  'is-very-bad' => true,\r
+  'is-very-evil' => true,\r
+  'is-very-good' => true,\r
+  'is-very-nice' => true,\r
+  'is-very-sweet' => true,\r
+  'isa-geek' => true,\r
+  'kicks-ass' => true,\r
+  'misconfused' => true,\r
+  'podzone' => true,\r
+  'readmyblog' => true,\r
+  'selfip' => true,\r
+  'sellsyourhome' => true,\r
+  'servebbs' => true,\r
+  'serveftp' => true,\r
+  'servegame' => true,\r
+  'stuff-4-sale' => true,\r
+  'webhop' => true\r
+ ),\r
+ 'pa' => array(\r
+  'ac' => true,\r
+  'gob' => true,\r
+  'com' => true,\r
+  'org' => true,\r
+  'sld' => true,\r
+  'edu' => true,\r
+  'net' => true,\r
+  'ing' => true,\r
+  'abo' => true,\r
+  'med' => true,\r
+  'nom' => true\r
+ ),\r
+ 'pe' => array(\r
+  'edu' => true,\r
+  'gob' => true,\r
+  'nom' => true,\r
+  'mil' => true,\r
+  'org' => true,\r
+  'com' => true,\r
+  'net' => true\r
+ ),\r
+ 'pf' => array(\r
+  'com' => true,\r
+  'org' => true,\r
+  'edu' => true\r
+ ),\r
+ 'pg' => array(\r
+  '*' => true\r
+ ),\r
+ 'ph' => array(\r
+  'com' => true,\r
+  'net' => true,\r
+  'org' => true,\r
+  'gov' => true,\r
+  'edu' => true,\r
+  'ngo' => true,\r
+  'mil' => true,\r
+  'i' => true\r
+ ),\r
+ 'pk' => array(\r
+  'com' => true,\r
+  'net' => true,\r
+  'edu' => true,\r
+  'org' => true,\r
+  'fam' => true,\r
+  'biz' => true,\r
+  'web' => true,\r
+  'gov' => true,\r
+  'gob' => true,\r
+  'gok' => true,\r
+  'gon' => true,\r
+  'gop' => true,\r
+  'gos' => true,\r
+  'info' => true\r
+ ),\r
+ 'pl' => array(\r
+  'aid' => true,\r
+  'agro' => true,\r
+  'atm' => true,\r
+  'auto' => true,\r
+  'biz' => true,\r
+  'com' => true,\r
+  'edu' => true,\r
+  'gmina' => true,\r
+  'gsm' => true,\r
+  'info' => true,\r
+  'mail' => true,\r
+  'miasta' => true,\r
+  'media' => true,\r
+  'mil' => true,\r
+  'net' => true,\r
+  'nieruchomosci' => true,\r
+  'nom' => true,\r
+  'org' => true,\r
+  'pc' => true,\r
+  'powiat' => true,\r
+  'priv' => true,\r
+  'realestate' => true,\r
+  'rel' => true,\r
+  'sex' => true,\r
+  'shop' => true,\r
+  'sklep' => true,\r
+  'sos' => true,\r
+  'szkola' => true,\r
+  'targi' => true,\r
+  'tm' => true,\r
+  'tourism' => true,\r
+  'travel' => true,\r
+  'turystyka' => true,\r
+  '6bone' => true,\r
+  'art' => true,\r
+  'mbone' => true,\r
+  'gov' => array(\r
+   'uw' => true,\r
+   'um' => true,\r
+   'ug' => true,\r
+   'upow' => true,\r
+   'starostwo' => true,\r
+   'so' => true,\r
+   'sr' => true,\r
+   'po' => true,\r
+   'pa' => true\r
+  ),\r
+  'ngo' => true,\r
+  'irc' => true,\r
+  'usenet' => true,\r
+  'augustow' => true,\r
+  'babia-gora' => true,\r
+  'bedzin' => true,\r
+  'beskidy' => true,\r
+  'bialowieza' => true,\r
+  'bialystok' => true,\r
+  'bielawa' => true,\r
+  'bieszczady' => true,\r
+  'boleslawiec' => true,\r
+  'bydgoszcz' => true,\r
+  'bytom' => true,\r
+  'cieszyn' => true,\r
+  'czeladz' => true,\r
+  'czest' => true,\r
+  'dlugoleka' => true,\r
+  'elblag' => true,\r
+  'elk' => true,\r
+  'glogow' => true,\r
+  'gniezno' => true,\r
+  'gorlice' => true,\r
+  'grajewo' => true,\r
+  'ilawa' => true,\r
+  'jaworzno' => true,\r
+  'jelenia-gora' => true,\r
+  'jgora' => true,\r
+  'kalisz' => true,\r
+  'kazimierz-dolny' => true,\r
+  'karpacz' => true,\r
+  'kartuzy' => true,\r
+  'kaszuby' => true,\r
+  'katowice' => true,\r
+  'kepno' => true,\r
+  'ketrzyn' => true,\r
+  'klodzko' => true,\r
+  'kobierzyce' => true,\r
+  'kolobrzeg' => true,\r
+  'konin' => true,\r
+  'konskowola' => true,\r
+  'kutno' => true,\r
+  'lapy' => true,\r
+  'lebork' => true,\r
+  'legnica' => true,\r
+  'lezajsk' => true,\r
+  'limanowa' => true,\r
+  'lomza' => true,\r
+  'lowicz' => true,\r
+  'lubin' => true,\r
+  'lukow' => true,\r
+  'malbork' => true,\r
+  'malopolska' => true,\r
+  'mazowsze' => true,\r
+  'mazury' => true,\r
+  'mielec' => true,\r
+  'mielno' => true,\r
+  'mragowo' => true,\r
+  'naklo' => true,\r
+  'nowaruda' => true,\r
+  'nysa' => true,\r
+  'olawa' => true,\r
+  'olecko' => true,\r
+  'olkusz' => true,\r
+  'olsztyn' => true,\r
+  'opoczno' => true,\r
+  'opole' => true,\r
+  'ostroda' => true,\r
+  'ostroleka' => true,\r
+  'ostrowiec' => true,\r
+  'ostrowwlkp' => true,\r
+  'pila' => true,\r
+  'pisz' => true,\r
+  'podhale' => true,\r
+  'podlasie' => true,\r
+  'polkowice' => true,\r
+  'pomorze' => true,\r
+  'pomorskie' => true,\r
+  'prochowice' => true,\r
+  'pruszkow' => true,\r
+  'przeworsk' => true,\r
+  'pulawy' => true,\r
+  'radom' => true,\r
+  'rawa-maz' => true,\r
+  'rybnik' => true,\r
+  'rzeszow' => true,\r
+  'sanok' => true,\r
+  'sejny' => true,\r
+  'siedlce' => true,\r
+  'slask' => true,\r
+  'slupsk' => true,\r
+  'sosnowiec' => true,\r
+  'stalowa-wola' => true,\r
+  'skoczow' => true,\r
+  'starachowice' => true,\r
+  'stargard' => true,\r
+  'suwalki' => true,\r
+  'swidnica' => true,\r
+  'swiebodzin' => true,\r
+  'swinoujscie' => true,\r
+  'szczecin' => true,\r
+  'szczytno' => true,\r
+  'tarnobrzeg' => true,\r
+  'tgory' => true,\r
+  'turek' => true,\r
+  'tychy' => true,\r
+  'ustka' => true,\r
+  'walbrzych' => true,\r
+  'warmia' => true,\r
+  'warszawa' => true,\r
+  'waw' => true,\r
+  'wegrow' => true,\r
+  'wielun' => true,\r
+  'wlocl' => true,\r
+  'wloclawek' => true,\r
+  'wodzislaw' => true,\r
+  'wolomin' => true,\r
+  'wroclaw' => true,\r
+  'zachpomor' => true,\r
+  'zagan' => true,\r
+  'zarow' => true,\r
+  'zgora' => true,\r
+  'zgorzelec' => true,\r
+  'gda' => true,\r
+  'gdansk' => true,\r
+  'gdynia' => true,\r
+  'med' => true,\r
+  'sopot' => true,\r
+  'gliwice' => true,\r
+  'krakow' => true,\r
+  'poznan' => true,\r
+  'wroc' => true,\r
+  'zakopane' => true,\r
+  'co' => true\r
+ ),\r
+ 'pm' => true,\r
+ 'pn' => array(\r
+  'gov' => true,\r
+  'co' => true,\r
+  'org' => true,\r
+  'edu' => true,\r
+  'net' => true\r
+ ),\r
+ 'pr' => array(\r
+  'com' => true,\r
+  'net' => true,\r
+  'org' => true,\r
+  'gov' => true,\r
+  'edu' => true,\r
+  'isla' => true,\r
+  'pro' => true,\r
+  'biz' => true,\r
+  'info' => true,\r
+  'name' => true,\r
+  'est' => true,\r
+  'prof' => true,\r
+  'ac' => true\r
+ ),\r
+ 'pro' => array(\r
+  'aca' => true,\r
+  'bar' => true,\r
+  'cpa' => true,\r
+  'jur' => true,\r
+  'law' => true,\r
+  'med' => true,\r
+  'eng' => true\r
+ ),\r
+ 'ps' => array(\r
+  'edu' => true,\r
+  'gov' => true,\r
+  'sec' => true,\r
+  'plo' => true,\r
+  'com' => true,\r
+  'org' => true,\r
+  'net' => true\r
+ ),\r
+ 'pt' => array(\r
+  'net' => true,\r
+  'gov' => true,\r
+  'org' => true,\r
+  'edu' => true,\r
+  'int' => true,\r
+  'publ' => true,\r
+  'com' => true,\r
+  'nome' => true\r
+ ),\r
+ 'pw' => array(\r
+  'co' => true,\r
+  'ne' => true,\r
+  'or' => true,\r
+  'ed' => true,\r
+  'go' => true,\r
+  'belau' => true\r
+ ),\r
+ 'py' => array(\r
+  '*' => true\r
+ ),\r
+ 'qa' => array(\r
+  'com' => true,\r
+  'edu' => true,\r
+  'gov' => true,\r
+  'mil' => true,\r
+  'name' => true,\r
+  'net' => true,\r
+  'org' => true,\r
+  'sch' => true\r
+ ),\r
+ 're' => array(\r
+  'com' => true,\r
+  'asso' => true,\r
+  'nom' => true\r
+ ),\r
+ 'ro' => array(\r
+  'com' => true,\r
+  'org' => true,\r
+  'tm' => true,\r
+  'nt' => true,\r
+  'nom' => true,\r
+  'info' => true,\r
+  'rec' => true,\r
+  'arts' => true,\r
+  'firm' => true,\r
+  'store' => true,\r
+  'www' => true\r
+ ),\r
+ 'rs' => array(\r
+  'co' => true,\r
+  'org' => true,\r
+  'edu' => true,\r
+  'ac' => true,\r
+  'gov' => true,\r
+  'in' => true\r
+ ),\r
+ 'ru' => array(\r
+  'ac' => true,\r
+  'com' => true,\r
+  'edu' => true,\r
+  'int' => true,\r
+  'net' => true,\r
+  'org' => true,\r
+  'pp' => true,\r
+  'adygeya' => true,\r
+  'altai' => true,\r
+  'amur' => true,\r
+  'arkhangelsk' => true,\r
+  'astrakhan' => true,\r
+  'bashkiria' => true,\r
+  'belgorod' => true,\r
+  'bir' => true,\r
+  'bryansk' => true,\r
+  'buryatia' => true,\r
+  'cbg' => true,\r
+  'chel' => true,\r
+  'chelyabinsk' => true,\r
+  'chita' => true,\r
+  'chukotka' => true,\r
+  'chuvashia' => true,\r
+  'dagestan' => true,\r
+  'dudinka' => true,\r
+  'e-burg' => true,\r
+  'grozny' => true,\r
+  'irkutsk' => true,\r
+  'ivanovo' => true,\r
+  'izhevsk' => true,\r
+  'jar' => true,\r
+  'joshkar-ola' => true,\r
+  'kalmykia' => true,\r
+  'kaluga' => true,\r
+  'kamchatka' => true,\r
+  'karelia' => true,\r
+  'kazan' => true,\r
+  'kchr' => true,\r
+  'kemerovo' => true,\r
+  'khabarovsk' => true,\r
+  'khakassia' => true,\r
+  'khv' => true,\r
+  'kirov' => true,\r
+  'koenig' => true,\r
+  'komi' => true,\r
+  'kostroma' => true,\r
+  'krasnoyarsk' => true,\r
+  'kuban' => true,\r
+  'kurgan' => true,\r
+  'kursk' => true,\r
+  'lipetsk' => true,\r
+  'magadan' => true,\r
+  'mari' => true,\r
+  'mari-el' => true,\r
+  'marine' => true,\r
+  'mordovia' => true,\r
+  'mosreg' => true,\r
+  'msk' => true,\r
+  'murmansk' => true,\r
+  'nalchik' => true,\r
+  'nnov' => true,\r
+  'nov' => true,\r
+  'novosibirsk' => true,\r
+  'nsk' => true,\r
+  'omsk' => true,\r
+  'orenburg' => true,\r
+  'oryol' => true,\r
+  'palana' => true,\r
+  'penza' => true,\r
+  'perm' => true,\r
+  'pskov' => true,\r
+  'ptz' => true,\r
+  'rnd' => true,\r
+  'ryazan' => true,\r
+  'sakhalin' => true,\r
+  'samara' => true,\r
+  'saratov' => true,\r
+  'simbirsk' => true,\r
+  'smolensk' => true,\r
+  'spb' => true,\r
+  'stavropol' => true,\r
+  'stv' => true,\r
+  'surgut' => true,\r
+  'tambov' => true,\r
+  'tatarstan' => true,\r
+  'tom' => true,\r
+  'tomsk' => true,\r
+  'tsaritsyn' => true,\r
+  'tsk' => true,\r
+  'tula' => true,\r
+  'tuva' => true,\r
+  'tver' => true,\r
+  'tyumen' => true,\r
+  'udm' => true,\r
+  'udmurtia' => true,\r
+  'ulan-ude' => true,\r
+  'vladikavkaz' => true,\r
+  'vladimir' => true,\r
+  'vladivostok' => true,\r
+  'volgograd' => true,\r
+  'vologda' => true,\r
+  'voronezh' => true,\r
+  'vrn' => true,\r
+  'vyatka' => true,\r
+  'yakutia' => true,\r
+  'yamal' => true,\r
+  'yaroslavl' => true,\r
+  'yekaterinburg' => true,\r
+  'yuzhno-sakhalinsk' => true,\r
+  'amursk' => true,\r
+  'baikal' => true,\r
+  'cmw' => true,\r
+  'fareast' => true,\r
+  'jamal' => true,\r
+  'kms' => true,\r
+  'k-uralsk' => true,\r
+  'kustanai' => true,\r
+  'kuzbass' => true,\r
+  'magnitka' => true,\r
+  'mytis' => true,\r
+  'nakhodka' => true,\r
+  'nkz' => true,\r
+  'norilsk' => true,\r
+  'oskol' => true,\r
+  'pyatigorsk' => true,\r
+  'rubtsovsk' => true,\r
+  'snz' => true,\r
+  'syzran' => true,\r
+  'vdonsk' => true,\r
+  'zgrad' => true,\r
+  'gov' => true,\r
+  'mil' => true,\r
+  'test' => true\r
+ ),\r
+ 'rw' => array(\r
+  'gov' => true,\r
+  'net' => true,\r
+  'edu' => true,\r
+  'ac' => true,\r
+  'com' => true,\r
+  'co' => true,\r
+  'int' => true,\r
+  'mil' => true,\r
+  'gouv' => true\r
+ ),\r
+ 'sa' => array(\r
+  'com' => true,\r
+  'net' => true,\r
+  'org' => true,\r
+  'gov' => true,\r
+  'med' => true,\r
+  'pub' => true,\r
+  'edu' => true,\r
+  'sch' => true\r
+ ),\r
+ 'sb' => array(\r
+  'com' => true,\r
+  'edu' => true,\r
+  'gov' => true,\r
+  'net' => true,\r
+  'org' => true\r
+ ),\r
+ 'sc' => array(\r
+  'com' => true,\r
+  'gov' => true,\r
+  'net' => true,\r
+  'org' => true,\r
+  'edu' => true\r
+ ),\r
+ 'sd' => array(\r
+  'com' => true,\r
+  'net' => true,\r
+  'org' => true,\r
+  'edu' => true,\r
+  'med' => true,\r
+  'gov' => true,\r
+  'info' => true\r
+ ),\r
+ 'se' => array(\r
+  'a' => true,\r
+  'ac' => true,\r
+  'b' => true,\r
+  'bd' => true,\r
+  'brand' => true,\r
+  'c' => true,\r
+  'd' => true,\r
+  'e' => true,\r
+  'f' => true,\r
+  'fh' => true,\r
+  'fhsk' => true,\r
+  'fhv' => true,\r
+  'g' => true,\r
+  'h' => true,\r
+  'i' => true,\r
+  'k' => true,\r
+  'komforb' => true,\r
+  'kommunalforbund' => true,\r
+  'komvux' => true,\r
+  'l' => true,\r
+  'lanbib' => true,\r
+  'm' => true,\r
+  'n' => true,\r
+  'naturbruksgymn' => true,\r
+  'o' => true,\r
+  'org' => true,\r
+  'p' => true,\r
+  'parti' => true,\r
+  'pp' => true,\r
+  'press' => true,\r
+  'r' => true,\r
+  's' => true,\r
+  'sshn' => true,\r
+  't' => true,\r
+  'tm' => true,\r
+  'u' => true,\r
+  'w' => true,\r
+  'x' => true,\r
+  'y' => true,\r
+  'z' => true\r
+ ),\r
+ 'sg' => array(\r
+  'com' => true,\r
+  'net' => true,\r
+  'org' => true,\r
+  'gov' => true,\r
+  'edu' => true,\r
+  'per' => true\r
+ ),\r
+ 'sh' => true,\r
+ 'si' => true,\r
+ 'sk' => true,\r
+ 'sl' => array(\r
+  'com' => true,\r
+  'net' => true,\r
+  'edu' => true,\r
+  'gov' => true,\r
+  'org' => true\r
+ ),\r
+ 'sm' => true,\r
+ 'sn' => array(\r
+  'art' => true,\r
+  'com' => true,\r
+  'edu' => true,\r
+  'gouv' => true,\r
+  'org' => true,\r
+  'perso' => true,\r
+  'univ' => true\r
+ ),\r
+ 'so' => array(\r
+  'com' => true,\r
+  'net' => true,\r
+  'org' => true\r
+ ),\r
+ 'sr' => true,\r
+ 'st' => array(\r
+  'co' => true,\r
+  'com' => true,\r
+  'consulado' => true,\r
+  'edu' => true,\r
+  'embaixada' => true,\r
+  'gov' => true,\r
+  'mil' => true,\r
+  'net' => true,\r
+  'org' => true,\r
+  'principe' => true,\r
+  'saotome' => true,\r
+  'store' => true\r
+ ),\r
+ 'su' => true,\r
+ 'sv' => array(\r
+  '*' => true\r
+ ),\r
+ 'sy' => array(\r
+  'edu' => true,\r
+  'gov' => true,\r
+  'net' => true,\r
+  'mil' => true,\r
+  'com' => true,\r
+  'org' => true\r
+ ),\r
+ 'sz' => array(\r
+  'co' => true,\r
+  'ac' => true,\r
+  'org' => true\r
+ ),\r
+ 'tc' => true,\r
+ 'td' => true,\r
+ 'tel' => true,\r
+ 'tf' => true,\r
+ 'tg' => true,\r
+ 'th' => array(\r
+  'ac' => true,\r
+  'co' => true,\r
+  'go' => true,\r
+  'in' => true,\r
+  'mi' => true,\r
+  'net' => true,\r
+  'or' => true\r
+ ),\r
+ 'tj' => array(\r
+  'ac' => true,\r
+  'biz' => true,\r
+  'co' => true,\r
+  'com' => true,\r
+  'edu' => true,\r
+  'go' => true,\r
+  'gov' => true,\r
+  'int' => true,\r
+  'mil' => true,\r
+  'name' => true,\r
+  'net' => true,\r
+  'nic' => true,\r
+  'org' => true,\r
+  'test' => true,\r
+  'web' => true\r
+ ),\r
+ 'tk' => true,\r
+ 'tl' => array(\r
+  'gov' => true\r
+ ),\r
+ 'tm' => true,\r
+ 'tn' => array(\r
+  'com' => true,\r
+  'ens' => true,\r
+  'fin' => true,\r
+  'gov' => true,\r
+  'ind' => true,\r
+  'intl' => true,\r
+  'nat' => true,\r
+  'net' => true,\r
+  'org' => true,\r
+  'info' => true,\r
+  'perso' => true,\r
+  'tourism' => true,\r
+  'edunet' => true,\r
+  'rnrt' => true,\r
+  'rns' => true,\r
+  'rnu' => true,\r
+  'mincom' => true,\r
+  'agrinet' => true,\r
+  'defense' => true,\r
+  'turen' => true\r
+ ),\r
+ 'to' => array(\r
+  'com' => true,\r
+  'gov' => true,\r
+  'net' => true,\r
+  'org' => true,\r
+  'edu' => true,\r
+  'mil' => true\r
+ ),\r
+ 'tr' => array(\r
+  '*' => true,\r
+  '!nic' => true,\r
+  'nc' => array(\r
+   'gov' => true\r
+  )\r
+ ),\r
+ 'travel' => true,\r
+ 'tt' => array(\r
+  'co' => true,\r
+  'com' => true,\r
+  'org' => true,\r
+  'net' => true,\r
+  'biz' => true,\r
+  'info' => true,\r
+  'pro' => true,\r
+  'int' => true,\r
+  'coop' => true,\r
+  'jobs' => true,\r
+  'mobi' => true,\r
+  'travel' => true,\r
+  'museum' => true,\r
+  'aero' => true,\r
+  'name' => true,\r
+  'gov' => true,\r
+  'edu' => true\r
+ ),\r
+ 'tv' => array(\r
+  'dyndns' => true,\r
+  'better-than' => true,\r
+  'on-the-web' => true,\r
+  'worse-than' => true\r
+ ),\r
+ 'tw' => array(\r
+  'edu' => true,\r
+  'gov' => true,\r
+  'mil' => true,\r
+  'com' => true,\r
+  'net' => true,\r
+  'org' => true,\r
+  'idv' => true,\r
+  'game' => true,\r
+  'ebiz' => true,\r
+  'club' => true,\r
+  '網路' => true,\r
+  '組織' => true,\r
+  '商業' => true\r
+ ),\r
+ 'tz' => array(\r
+  'ac' => true,\r
+  'co' => true,\r
+  'go' => true,\r
+  'mil' => true,\r
+  'ne' => true,\r
+  'or' => true,\r
+  'sc' => true\r
+ ),\r
+ 'ua' => array(\r
+  'com' => true,\r
+  'edu' => true,\r
+  'gov' => true,\r
+  'in' => true,\r
+  'net' => true,\r
+  'org' => true,\r
+  'cherkassy' => true,\r
+  'chernigov' => true,\r
+  'chernovtsy' => true,\r
+  'ck' => true,\r
+  'cn' => true,\r
+  'crimea' => true,\r
+  'cv' => true,\r
+  'dn' => true,\r
+  'dnepropetrovsk' => true,\r
+  'donetsk' => true,\r
+  'dp' => true,\r
+  'if' => true,\r
+  'ivano-frankivsk' => true,\r
+  'kh' => true,\r
+  'kharkov' => true,\r
+  'kherson' => true,\r
+  'khmelnitskiy' => true,\r
+  'kiev' => true,\r
+  'kirovograd' => true,\r
+  'km' => true,\r
+  'kr' => true,\r
+  'ks' => true,\r
+  'kv' => true,\r
+  'lg' => true,\r
+  'lugansk' => true,\r
+  'lutsk' => true,\r
+  'lviv' => true,\r
+  'mk' => true,\r
+  'nikolaev' => true,\r
+  'od' => true,\r
+  'odessa' => true,\r
+  'pl' => true,\r
+  'poltava' => true,\r
+  'rovno' => true,\r
+  'rv' => true,\r
+  'sebastopol' => true,\r
+  'sumy' => true,\r
+  'te' => true,\r
+  'ternopil' => true,\r
+  'uzhgorod' => true,\r
+  'vinnica' => true,\r
+  'vn' => true,\r
+  'zaporizhzhe' => true,\r
+  'zp' => true,\r
+  'zhitomir' => true,\r
+  'zt' => true,\r
+  'co' => true,\r
+  'pp' => true\r
+ ),\r
+ 'ug' => array(\r
+  'co' => true,\r
+  'ac' => true,\r
+  'sc' => true,\r
+  'go' => true,\r
+  'ne' => true,\r
+  'or' => true\r
+ ),\r
+ 'uk' => array(\r
+  '*' => true,\r
+  'sch' => array(\r
+   '*' => true\r
+  ),\r
+  '!bl' => true,\r
+  '!british-library' => true,\r
+  '!icnet' => true,\r
+  '!jet' => true,\r
+  '!mod' => true,\r
+  '!nel' => true,\r
+  '!nhs' => true,\r
+  '!nic' => true,\r
+  '!nls' => true,\r
+  '!national-library-scotland' => true,\r
+  '!parliament' => true,\r
+  '!police' => true\r
+ ),\r
+ 'us' => array(\r
+  'dni' => true,\r
+  'fed' => true,\r
+  'isa' => true,\r
+  'kids' => true,\r
+  'nsn' => true,\r
+  'ak' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'al' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'ar' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'as' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'az' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'ca' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'co' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'ct' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'dc' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'de' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'fl' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'ga' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'gu' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'hi' => array(\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'ia' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'id' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'il' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'in' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'ks' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'ky' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'la' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'ma' => array(\r
+   'k12' => array(\r
+    'pvt' => true,\r
+    'chtr' => true,\r
+    'paroch' => true\r
+   ),\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'md' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'me' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'mi' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'mn' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'mo' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'ms' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'mt' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'nc' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'nd' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'ne' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'nh' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'nj' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'nm' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'nv' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'ny' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'oh' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'ok' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'or' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'pa' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'pr' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'ri' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'sc' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'sd' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'tn' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'tx' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'ut' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'vi' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'vt' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'va' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'wa' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'wi' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'wv' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'wy' => array(\r
+   'k12' => true,\r
+   'cc' => true,\r
+   'lib' => true\r
+  ),\r
+  'is-by' => true,\r
+  'land-4-sale' => true,\r
+  'stuff-4-sale' => true\r
+ ),\r
+ 'uy' => array(\r
+  '*' => true\r
+ ),\r
+ 'uz' => array(\r
+  'com' => true,\r
+  'co' => true\r
+ ),\r
+ 'va' => true,\r
+ 'vc' => array(\r
+  'com' => true,\r
+  'net' => true,\r
+  'org' => true,\r
+  'gov' => true,\r
+  'mil' => true,\r
+  'edu' => true\r
+ ),\r
+ 've' => array(\r
+  '*' => true\r
+ ),\r
+ 'vg' => true,\r
+ 'vi' => array(\r
+  'co' => true,\r
+  'com' => true,\r
+  'k12' => true,\r
+  'net' => true,\r
+  'org' => true\r
+ ),\r
+ 'vn' => array(\r
+  'com' => true,\r
+  'net' => true,\r
+  'org' => true,\r
+  'edu' => true,\r
+  'gov' => true,\r
+  'int' => true,\r
+  'ac' => true,\r
+  'biz' => true,\r
+  'info' => true,\r
+  'name' => true,\r
+  'pro' => true,\r
+  'health' => true\r
+ ),\r
+ 'vu' => true,\r
+ 'wf' => true,\r
+ 'ws' => array(\r
+  'com' => true,\r
+  'net' => true,\r
+  'org' => true,\r
+  'gov' => true,\r
+  'edu' => true,\r
+  'dyndns' => true,\r
+  'mypets' => true\r
+ ),\r
+ 'yt' => true,\r
+ 'امارات' => true,\r
+ 'বাংলা' => true,\r
+ '中国' => true,\r
+ '中國' => true,\r
+ 'الجزائر' => true,\r
+ 'مصر' => true,\r
+ 'გე' => true,\r
+ '香港' => true,\r
+ 'भारत' => true,\r
+ 'بھارت' => true,\r
+ 'భారత్' => true,\r
+ 'ભારત' => true,\r
+ 'ਭਾਰਤ' => true,\r
+ 'ভারত' => true,\r
+ 'இந்தியா' => true,\r
+ 'ایران' => true,\r
+ 'ايران' => true,\r
+ 'الاردن' => true,\r
+ '한국' => true,\r
+ 'ලංකා' => true,\r
+ 'இலங்கை' => true,\r
+ 'المغرب' => true,\r
+ 'عمان' => true,\r
+ 'فلسطين' => true,\r
+ 'срб' => true,\r
+ 'рф' => true,\r
+ 'قطر' => true,\r
+ 'السعودية' => true,\r
+ 'السعودیة' => true,\r
+ 'السعودیۃ' => true,\r
+ 'السعوديه' => true,\r
+ 'سورية' => true,\r
+ 'سوريا' => true,\r
+ '新加坡' => true,\r
+ 'சிங்கப்பூர்' => true,\r
+ 'ไทย' => true,\r
+ 'تونس' => true,\r
+ '台灣' => true,\r
+ '台湾' => true,\r
+ '臺灣' => true,\r
+ 'укр' => true,\r
+ 'اليمن' => true,\r
+ 'xxx' => true,\r
+ 'ye' => array(\r
+  '*' => true\r
+ ),\r
+ 'za' => array(\r
+  '*' => true\r
+ ),\r
+ 'zm' => array(\r
+  '*' => true\r
+ ),\r
+ 'zw' => array(\r
+  '*' => true\r
+ )\r
+);\r
+?>
\ No newline at end of file