]> git.immae.eu Git - github/wallabag/wallabag.git/blobdiff - inc/3rdparty/libraries/humble-http-agent/CookieJar.php
[change] we now use Full-Text RSS 3.1, thank you so much @fivefilters
[github/wallabag/wallabag.git] / inc / 3rdparty / libraries / humble-http-agent / CookieJar.php
similarity index 97%
rename from inc/3rdparty/humble-http-agent/CookieJar.php
rename to inc/3rdparty/libraries/humble-http-agent/CookieJar.php
index d91b711eda48211971e43037599e564256477410..83e94f14035c5dd9053bb4150592a6807fa77f39 100644 (file)
-<?php
-/**
- * Cookie Jar
- * 
- * PHP class for handling cookies, as defined by the Netscape spec: 
- * <http://curl.haxx.se/rfc/cookie_spec.html>
- *
- * This class should be used to handle cookies (storing cookies from HTTP response messages, and
- * sending out cookies in HTTP request messages). This has been adapted for FiveFilters.org 
- * from the original version used in HTTP Navigator. See http://www.keyvan.net/code/http-navigator/
- * 
- * This class is mainly based on Cookies.pm <http://search.cpan.org/author/GAAS/libwww-perl-5.65/
- * lib/HTTP/Cookies.pm> from the libwww-perl collection <http://www.linpro.no/lwp/>.
- * Unlike Cookies.pm, this class only supports the Netscape cookie spec, not RFC 2965.
- * 
- * @version 0.5
- * @date 2011-03-15
- * @see http://php.net/HttpRequestPool
- * @author Keyvan Minoukadeh
- * @copyright 2011 Keyvan Minoukadeh
- * @license http://www.gnu.org/licenses/agpl-3.0.html AGPL v3
- */
-
-class CookieJar
-{
-    /**
-    * Cookies - array containing all cookies.
-    *
-    * <pre>
-    * Cookies are stored like this:
-    *   [domain][path][name] = array
-    * where array is:
-    *   0 => value, 1 => secure, 2 => expires
-    * </pre>
-    * @var array
-    * @access private
-    */
-    public $cookies = array();
-       public $debug = false;
-
-    /**
-    * Constructor
-    */
-    function __construct() {
-    }
-
-       protected function debug($msg, $file=null, $line=null) {
-               if ($this->debug) {
-                       $mem = round(memory_get_usage()/1024, 2);
-                       $memPeak = round(memory_get_peak_usage()/1024, 2);
-                       echo '* ',$msg;
-                       if (isset($file, $line)) echo " ($file line $line)";
-                       echo ' - mem used: ',$mem," (peak: $memPeak)\n";        
-                       ob_flush();
-                       flush();
-               }
-       }       
-       
-    /**
-    * Get matching cookies
-    *
-    * Only use this method if you cannot use add_cookie_header(), for example, if you want to use
-    * this cookie jar class without using the request class.
-    *
-    * @param array $param associative array containing 'domain', 'path', 'secure' keys
-    * @return string
-    * @see add_cookie_header()
-    */
-    public function getMatchingCookies($url)
-    {
-               if (($parts = @parse_url($url)) && isset($parts['scheme'], $parts['host'], $parts['path'])) {
-                       $param['domain'] = $parts['host'];
-                       $param['path'] = $parts['path'];
-                       $param['secure'] = (strtolower($parts['scheme']) == 'https');
-                       unset($parts);
-               } else {
-                       return false;
-               }
-        // RFC 2965 notes:
-        //  If multiple cookies satisfy the criteria above, they are ordered in
-        //  the Cookie header such that those with more specific Path attributes
-        //  precede those with less specific.  Ordering with respect to other
-        //  attributes (e.g., Domain) is unspecified.
-        $domain = $param['domain'];
-        if (strpos($domain, '.') === false) $domain .= '.local';
-        $request_path = $param['path'];
-        if ($request_path == '') $request_path = '/';
-        $request_secure = $param['secure'];
-        $now = time();
-        $matched_cookies = array();
-        // domain - find matching domains
-        $this->debug('Finding matching domains for '.$domain, __FILE__, __LINE__);
-        while (strpos($domain, '.') !== false) {
-            if (isset($this->cookies[$domain])) {
-                $this->debug(' domain match found: '.$domain);
-                $cookies =& $this->cookies[$domain];
-            } else {
-                $domain = $this->_reduce_domain($domain);
-                continue;
-            }
-            // paths - find matching paths starting from most specific
-            $this->debug('  - Finding matching paths for '.$request_path);
-            $paths = array_keys($cookies);
-            usort($paths, array($this, '_cmp_length'));
-            foreach ($paths as $path) {
-                // continue to next cookie if request path does not path-match cookie path
-                if (!$this->_path_match($request_path, $path)) continue;
-                // loop through cookie names
-                $this->debug('     path match found: '.$path);
-                foreach ($cookies[$path] as $name => $values) {
-                    // if this cookie is secure but request isn't, continue to next cookie
-                    if ($values[1] && !$request_secure) continue;
-                    // if cookie is not a session cookie and has expired, continue to next cookie
-                    if (is_int($values[2]) && ($values[2] < $now)) continue;
-                    // cookie matches request
-                    $this->debug('      cookie match: '.$name.'='.$values[0]);
-                    $matched_cookies[] = $name.'='.$values[0];
-                }
-            }
-            $domain = $this->_reduce_domain($domain);
-        }
-        // return cookies
-        return implode('; ', $matched_cookies);
-    }
-
-    /**
-    * Parse Set-Cookie values.
-    *
-    * Only use this method if you cannot use extract_cookies(), for example, if you want to use
-    * this cookie jar class without using the response class.
-    *
-    * @param array $set_cookies array holding 1 or more "Set-Cookie" header values
-    * @param array $param associative array containing 'host', 'path' keys
-    * @return void
-    * @see extract_cookies()
-    */
-    public function storeCookies($url, $set_cookies)
-    {
-        if (count($set_cookies) == 0) return;
-               $param = @parse_url($url);
-               if (!is_array($param) || !isset($param['host'])) return;
-        $request_host = $param['host'];
-        if (strpos($request_host, '.') === false) $request_host .= '.local';
-        $request_path = @$param['path'];
-        if ($request_path == '') $request_path = '/';
-        //
-        // loop through set-cookie headers
-        //
-        foreach ($set_cookies as $set_cookie) {
-            $this->debug('Parsing: '.$set_cookie);
-            // temporary cookie store (before adding to jar)
-            $tmp_cookie = array();
-            $param = explode(';', $set_cookie);
-            // loop through params
-            for ($x=0; $x<count($param); $x++) {
-                $key_val = explode('=', $param[$x], 2);
-                if (count($key_val) != 2) {
-                    // if the first param isn't a name=value pair, continue to the next set-cookie
-                    // header
-                    if ($x == 0) continue 2;
-                    // check for secure flag
-                    if (strtolower(trim($key_val[0])) == 'secure') $tmp_cookie['secure'] = true;
-                    // continue to next param
-                    continue;
-                }
-                list($key, $val) = array_map('trim', $key_val);
-                // first name=value pair is the cookie name and value
-                // the name and value are stored under 'name' and 'value' to avoid conflicts
-                // with later parameters.
-                if ($x == 0) {
-                    $tmp_cookie = array('name'=>$key, 'value'=>$val);
-                    continue;
-                }
-                $key = strtolower($key);
-                if (in_array($key, array('expires', 'path', 'domain', 'secure'))) {
-                    $tmp_cookie[$key] = $val;
-                }
-            }
-            //
-            // set cookie
-            //
-            // check domain
-            if (isset($tmp_cookie['domain']) && ($tmp_cookie['domain'] != $request_host) &&
-                    ($tmp_cookie['domain'] != ".$request_host")) {
-                $domain = $tmp_cookie['domain'];
-                if ((strpos($domain, '.') === false) && ($domain != 'local')) {
-                    $this->debug(' - domain "'.$domain.'" has no dot and is not a local domain');
-                    continue;
-                }
-                if (preg_match('/\.[0-9]+$/', $domain)) {
-                    $this->debug(' - domain "'.$domain.'" appears to be an ip address');
-                    continue;
-                }
-                if (substr($domain, 0, 1) != '.') $domain = ".$domain";
-                if (!$this->_domain_match($request_host, $domain)) {
-                    $this->debug(' - request host "'.$request_host.'" does not domain-match "'.$domain.'"');
-                    continue;
-                }
-            } else {
-                // if domain is not specified in the set-cookie header, domain will default to
-                // the request host
-                $domain = $request_host;
-            }
-            // check path
-            if (isset($tmp_cookie['path']) && ($tmp_cookie['path'] != '')) {
-                $path = urldecode($tmp_cookie['path']);
-                if (!$this->_path_match($request_path, $path)) {
-                    $this->debug(' - request path "'.$request_path.'" does not path-match "'.$path.'"');
-                    continue;
-                }
-            } else {
-                $path = $request_path;
-                $path = substr($path, 0, strrpos($path, '/'));
-                if ($path == '') $path = '/';
-            }
-            // check if secure
-            $secure = (isset($tmp_cookie['secure'])) ? true : false;
-            // check expiry
-            if (isset($tmp_cookie['expires'])) {
-                if (($expires = strtotime($tmp_cookie['expires'])) < 0) {
-                    $expires = null;
-                }
-            } else {
-                $expires = null;
-            }
-            // set cookie
-            $this->set_cookie($domain, $path, $tmp_cookie['name'], $tmp_cookie['value'], $secure, $expires);
-        }
-    }
-       
-       // return array of set-cookie values extracted from HTTP response headers (string $h)
-       public function extractCookies($h) {
-        $x = 0;
-        $lines = 0;
-        $headers = array();
-        $last_match = false;
-               $h = explode("\n", $h);
-        foreach ($h as $line) {
-                       $line = rtrim($line);
-            $lines++;
-
-            $trimmed_line = trim($line);
-            if (isset($line_last)) {
-                // check if we have \r\n\r\n (indicating the end of headers)
-                // some servers will not use CRLF (\r\n), so we make CR (\r) optional.
-                // if (preg_match('/\015?\012\015?\012/', $line_last.$line)) {
-                //     break;
-                // }
-                // As an alternative, we can check if the current trimmed line is empty
-                if ($trimmed_line == '') {
-                    break;
-                }
-
-                // check for continuation line...
-                // RFC 2616 Section 2.2 "Basic Rules":
-                // HTTP/1.1 header field values can be folded onto multiple lines if the
-                // continuation line begins with a space or horizontal tab. All linear
-                // white space, including folding, has the same semantics as SP. A
-                // recipient MAY replace any linear white space with a single SP before
-                // interpreting the field value or forwarding the message downstream.
-                if ($last_match && preg_match('/^\s+(.*)/', $line, $match)) {
-                    // append to previous header value
-                    $headers[$x-1] .= ' '.rtrim($match[1]);
-                    continue;
-                }
-            }
-            $line_last = $line;
-
-            // split header name and value
-            if (preg_match('/^Set-Cookie\s*:\s*(.*)/i', $line, $match)) {
-                $headers[$x++] = rtrim($match[1]);
-                $last_match = true;
-            } else {
-                $last_match = false;
-            }
-        }
-        return $headers;
-       }
-
-    /**
-    * Set Cookie
-    * @param string $domain
-    * @param string $path
-    * @param string $name cookie name
-    * @param string $value cookie value
-    * @param bool $secure
-    * @param int $expires expiry time (null if session cookie, <= 0 will delete cookie)
-    * @return void
-    */
-    function set_cookie($domain, $path, $name, $value, $secure=false, $expires=null)
-    {
-        if ($domain == '') return;
-        if ($path == '') return;
-        if ($name == '') return;
-        // check if cookie needs to go
-        if (isset($expires) && ($expires <= 0)) {
-            if (isset($this->cookies[$domain][$path][$name])) unset($this->cookies[$domain][$path][$name]);
-            return;
-        }
-        if ($value == '') return;
-        $this->cookies[$domain][$path][$name] = array($value, $secure, $expires);
-        return;
-    }
-
-    /**
-    * Clear cookies - [domain [,path [,name]]] - call method with no arguments to clear all cookies.
-    * @param string $domain
-    * @param string $path
-    * @param string $name
-    * @return void
-    */
-    function clear($domain=null, $path=null, $name=null)
-    {
-        if (!isset($domain)) {
-            $this->cookies = array();
-        } elseif (!isset($path)) {
-            if (isset($this->cookies[$domain])) unset($this->cookies[$domain]);
-        } elseif (!isset($name)) {
-            if (isset($this->cookies[$domain][$path])) unset($this->cookies[$domain][$path]);
-        } elseif (isset($name)) {
-            if (isset($this->cookies[$domain][$path][$name])) unset($this->cookies[$domain][$path][$name]);
-        }
-    }
-
-    /**
-    * Compare string length - used for sorting
-    * @access private
-    * @return int
-    */
-    function _cmp_length($a, $b)
-    {
-        $la = strlen($a); $lb = strlen($b);
-        if ($la == $lb) return 0;
-        return ($la > $lb) ? -1 : 1;
-    }
-
-    /**
-    * Reduce domain
-    * @param string $domain
-    * @return string
-    * @access private
-    */
-    function _reduce_domain($domain)
-    {
-        if ($domain == '') return '';
-        if (substr($domain, 0, 1) == '.') return substr($domain, 1);
-        return substr($domain, strpos($domain, '.'));
-    }
-
-    /**
-    * Path match - check if path1 path-matches path2
-    *
-    * From RFC 2965: 
-    *   <i>For two strings that represent paths, P1 and P2, P1 path-matches P2
-    *   if P2 is a prefix of P1 (including the case where P1 and P2 string-
-    *   compare equal).  Thus, the string /tec/waldo path-matches /tec.</i>
-    * @param string $path1
-    * @param string $path2
-    * @return bool
-    * @access private
-    */
-    function _path_match($path1, $path2)
-    {
-        return (substr($path1, 0, strlen($path2)) == $path2);
-    }
-
-    /**
-    * Domain match - check if domain1 domain-matches domain2
-    *
-    * A few extracts from RFC 2965: 
-    *  -  A Set-Cookie2 from request-host y.x.foo.com for Domain=.foo.com
-    *     would be rejected, because H is y.x and contains a dot.
-    *
-    *  -  A Set-Cookie2 from request-host x.foo.com for Domain=.foo.com
-    *     would be accepted.
-    *
-    *  -  A Set-Cookie2 with Domain=.com or Domain=.com., will always be
-    *     rejected, because there is no embedded dot.
-    *
-    *  -  A Set-Cookie2 from request-host example for Domain=.local will
-    *     be accepted, because the effective host name for the request-
-    *     host is example.local, and example.local domain-matches .local.
-    *
-    * I'm ignoring the first point for now (must check to see how other browsers handle
-    * this rule for Set-Cookie headers)
-    *
-    * @param string $domain1
-    * @param string $domain2
-    * @return bool
-    * @access private
-    */
-    function _domain_match($domain1, $domain2)
-    {
-        $domain1 = strtolower($domain1);
-        $domain2 = strtolower($domain2);
-        while (strpos($domain1, '.') !== false) {
-            if ($domain1 == $domain2) return true;
-            $domain1 = $this->_reduce_domain($domain1);
-            continue;
-        }
-        return false;
-    }
-}
+<?php\r
+/**\r
+ * Cookie Jar\r
+ * \r
+ * PHP class for handling cookies, as defined by the Netscape spec: \r
+ * <http://curl.haxx.se/rfc/cookie_spec.html>\r
+ *\r
+ * This class should be used to handle cookies (storing cookies from HTTP response messages, and\r
+ * sending out cookies in HTTP request messages). This has been adapted for FiveFilters.org \r
+ * from the original version used in HTTP Navigator. See http://www.keyvan.net/code/http-navigator/\r
+ * \r
+ * This class is mainly based on Cookies.pm <http://search.cpan.org/author/GAAS/libwww-perl-5.65/\r
+ * lib/HTTP/Cookies.pm> from the libwww-perl collection <http://www.linpro.no/lwp/>.\r
+ * Unlike Cookies.pm, this class only supports the Netscape cookie spec, not RFC 2965.\r
+ * \r
+ * @version 0.5\r
+ * @date 2011-03-15\r
+ * @see http://php.net/HttpRequestPool\r
+ * @author Keyvan Minoukadeh\r
+ * @copyright 2011 Keyvan Minoukadeh\r
+ * @license http://www.gnu.org/licenses/agpl-3.0.html AGPL v3\r
+ */\r
+\r
+class CookieJar\r
+{\r
+    /**\r
+    * Cookies - array containing all cookies.\r
+    *\r
+    * <pre>\r
+    * Cookies are stored like this:\r
+    *   [domain][path][name] = array\r
+    * where array is:\r
+    *   0 => value, 1 => secure, 2 => expires\r
+    * </pre>\r
+    * @var array\r
+    * @access private\r
+    */\r
+    public $cookies = array();\r
+       public $debug = false;\r
+\r
+    /**\r
+    * Constructor\r
+    */\r
+    function __construct() {\r
+    }\r
+\r
+       protected function debug($msg, $file=null, $line=null) {\r
+               if ($this->debug) {\r
+                       $mem = round(memory_get_usage()/1024, 2);\r
+                       $memPeak = round(memory_get_peak_usage()/1024, 2);\r
+                       echo '* ',$msg;\r
+                       if (isset($file, $line)) echo " ($file line $line)";\r
+                       echo ' - mem used: ',$mem," (peak: $memPeak)\n";        \r
+                       ob_flush();\r
+                       flush();\r
+               }\r
+       }       \r
+       \r
+    /**\r
+    * Get matching cookies\r
+    *\r
+    * Only use this method if you cannot use add_cookie_header(), for example, if you want to use\r
+    * this cookie jar class without using the request class.\r
+    *\r
+    * @param array $param associative array containing 'domain', 'path', 'secure' keys\r
+    * @return string\r
+    * @see add_cookie_header()\r
+    */\r
+    public function getMatchingCookies($url)\r
+    {\r
+               if (($parts = @parse_url($url)) && isset($parts['scheme'], $parts['host'], $parts['path'])) {\r
+                       $param['domain'] = $parts['host'];\r
+                       $param['path'] = $parts['path'];\r
+                       $param['secure'] = (strtolower($parts['scheme']) == 'https');\r
+                       unset($parts);\r
+               } else {\r
+                       return false;\r
+               }\r
+        // RFC 2965 notes:\r
+        //  If multiple cookies satisfy the criteria above, they are ordered in\r
+        //  the Cookie header such that those with more specific Path attributes\r
+        //  precede those with less specific.  Ordering with respect to other\r
+        //  attributes (e.g., Domain) is unspecified.\r
+        $domain = $param['domain'];\r
+        if (strpos($domain, '.') === false) $domain .= '.local';\r
+        $request_path = $param['path'];\r
+        if ($request_path == '') $request_path = '/';\r
+        $request_secure = $param['secure'];\r
+        $now = time();\r
+        $matched_cookies = array();\r
+        // domain - find matching domains\r
+        $this->debug('Finding matching domains for '.$domain, __FILE__, __LINE__);\r
+        while (strpos($domain, '.') !== false) {\r
+            if (isset($this->cookies[$domain])) {\r
+                $this->debug(' domain match found: '.$domain);\r
+                $cookies =& $this->cookies[$domain];\r
+            } else {\r
+                $domain = $this->_reduce_domain($domain);\r
+                continue;\r
+            }\r
+            // paths - find matching paths starting from most specific\r
+            $this->debug('  - Finding matching paths for '.$request_path);\r
+            $paths = array_keys($cookies);\r
+            usort($paths, array($this, '_cmp_length'));\r
+            foreach ($paths as $path) {\r
+                // continue to next cookie if request path does not path-match cookie path\r
+                if (!$this->_path_match($request_path, $path)) continue;\r
+                // loop through cookie names\r
+                $this->debug('     path match found: '.$path);\r
+                foreach ($cookies[$path] as $name => $values) {\r
+                    // if this cookie is secure but request isn't, continue to next cookie\r
+                    if ($values[1] && !$request_secure) continue;\r
+                    // if cookie is not a session cookie and has expired, continue to next cookie\r
+                    if (is_int($values[2]) && ($values[2] < $now)) continue;\r
+                    // cookie matches request\r
+                    $this->debug('      cookie match: '.$name.'='.$values[0]);\r
+                    $matched_cookies[] = $name.'='.$values[0];\r
+                }\r
+            }\r
+            $domain = $this->_reduce_domain($domain);\r
+        }\r
+        // return cookies\r
+        return implode('; ', $matched_cookies);\r
+    }\r
+\r
+    /**\r
+    * Parse Set-Cookie values.\r
+    *\r
+    * Only use this method if you cannot use extract_cookies(), for example, if you want to use\r
+    * this cookie jar class without using the response class.\r
+    *\r
+    * @param array $set_cookies array holding 1 or more "Set-Cookie" header values\r
+    * @param array $param associative array containing 'host', 'path' keys\r
+    * @return void\r
+    * @see extract_cookies()\r
+    */\r
+    public function storeCookies($url, $set_cookies)\r
+    {\r
+        if (count($set_cookies) == 0) return;\r
+               $param = @parse_url($url);\r
+               if (!is_array($param) || !isset($param['host'])) return;\r
+        $request_host = $param['host'];\r
+        if (strpos($request_host, '.') === false) $request_host .= '.local';\r
+        $request_path = @$param['path'];\r
+        if ($request_path == '') $request_path = '/';\r
+        //\r
+        // loop through set-cookie headers\r
+        //\r
+        foreach ($set_cookies as $set_cookie) {\r
+            $this->debug('Parsing: '.$set_cookie);\r
+            // temporary cookie store (before adding to jar)\r
+            $tmp_cookie = array();\r
+            $param = explode(';', $set_cookie);\r
+            // loop through params\r
+            for ($x=0; $x<count($param); $x++) {\r
+                $key_val = explode('=', $param[$x], 2);\r
+                if (count($key_val) != 2) {\r
+                    // if the first param isn't a name=value pair, continue to the next set-cookie\r
+                    // header\r
+                    if ($x == 0) continue 2;\r
+                    // check for secure flag\r
+                    if (strtolower(trim($key_val[0])) == 'secure') $tmp_cookie['secure'] = true;\r
+                    // continue to next param\r
+                    continue;\r
+                }\r
+                list($key, $val) = array_map('trim', $key_val);\r
+                // first name=value pair is the cookie name and value\r
+                // the name and value are stored under 'name' and 'value' to avoid conflicts\r
+                // with later parameters.\r
+                if ($x == 0) {\r
+                    $tmp_cookie = array('name'=>$key, 'value'=>$val);\r
+                    continue;\r
+                }\r
+                $key = strtolower($key);\r
+                if (in_array($key, array('expires', 'path', 'domain', 'secure'))) {\r
+                    $tmp_cookie[$key] = $val;\r
+                }\r
+            }\r
+            //\r
+            // set cookie\r
+            //\r
+            // check domain\r
+            if (isset($tmp_cookie['domain']) && ($tmp_cookie['domain'] != $request_host) &&\r
+                    ($tmp_cookie['domain'] != ".$request_host")) {\r
+                $domain = $tmp_cookie['domain'];\r
+                if ((strpos($domain, '.') === false) && ($domain != 'local')) {\r
+                    $this->debug(' - domain "'.$domain.'" has no dot and is not a local domain');\r
+                    continue;\r
+                }\r
+                if (preg_match('/\.[0-9]+$/', $domain)) {\r
+                    $this->debug(' - domain "'.$domain.'" appears to be an ip address');\r
+                    continue;\r
+                }\r
+                if (substr($domain, 0, 1) != '.') $domain = ".$domain";\r
+                if (!$this->_domain_match($request_host, $domain)) {\r
+                    $this->debug(' - request host "'.$request_host.'" does not domain-match "'.$domain.'"');\r
+                    continue;\r
+                }\r
+            } else {\r
+                // if domain is not specified in the set-cookie header, domain will default to\r
+                // the request host\r
+                $domain = $request_host;\r
+            }\r
+            // check path\r
+            if (isset($tmp_cookie['path']) && ($tmp_cookie['path'] != '')) {\r
+                $path = urldecode($tmp_cookie['path']);\r
+                if (!$this->_path_match($request_path, $path)) {\r
+                    $this->debug(' - request path "'.$request_path.'" does not path-match "'.$path.'"');\r
+                    continue;\r
+                }\r
+            } else {\r
+                $path = $request_path;\r
+                $path = substr($path, 0, strrpos($path, '/'));\r
+                if ($path == '') $path = '/';\r
+            }\r
+            // check if secure\r
+            $secure = (isset($tmp_cookie['secure'])) ? true : false;\r
+            // check expiry\r
+            if (isset($tmp_cookie['expires'])) {\r
+                if (($expires = strtotime($tmp_cookie['expires'])) < 0) {\r
+                    $expires = null;\r
+                }\r
+            } else {\r
+                $expires = null;\r
+            }\r
+            // set cookie\r
+            $this->set_cookie($domain, $path, $tmp_cookie['name'], $tmp_cookie['value'], $secure, $expires);\r
+        }\r
+    }\r
+       \r
+       // return array of set-cookie values extracted from HTTP response headers (string $h)\r
+       public function extractCookies($h) {\r
+        $x = 0;\r
+        $lines = 0;\r
+        $headers = array();\r
+        $last_match = false;\r
+               $h = explode("\n", $h);\r
+        foreach ($h as $line) {\r
+                       $line = rtrim($line);\r
+            $lines++;\r
+\r
+            $trimmed_line = trim($line);\r
+            if (isset($line_last)) {\r
+                // check if we have \r\n\r\n (indicating the end of headers)\r
+                // some servers will not use CRLF (\r\n), so we make CR (\r) optional.\r
+                // if (preg_match('/\015?\012\015?\012/', $line_last.$line)) {\r
+                //     break;\r
+                // }\r
+                // As an alternative, we can check if the current trimmed line is empty\r
+                if ($trimmed_line == '') {\r
+                    break;\r
+                }\r
+\r
+                // check for continuation line...\r
+                // RFC 2616 Section 2.2 "Basic Rules":\r
+                // HTTP/1.1 header field values can be folded onto multiple lines if the\r
+                // continuation line begins with a space or horizontal tab. All linear\r
+                // white space, including folding, has the same semantics as SP. A\r
+                // recipient MAY replace any linear white space with a single SP before\r
+                // interpreting the field value or forwarding the message downstream.\r
+                if ($last_match && preg_match('/^\s+(.*)/', $line, $match)) {\r
+                    // append to previous header value\r
+                    $headers[$x-1] .= ' '.rtrim($match[1]);\r
+                    continue;\r
+                }\r
+            }\r
+            $line_last = $line;\r
+\r
+            // split header name and value\r
+            if (preg_match('/^Set-Cookie\s*:\s*(.*)/i', $line, $match)) {\r
+                $headers[$x++] = rtrim($match[1]);\r
+                $last_match = true;\r
+            } else {\r
+                $last_match = false;\r
+            }\r
+        }\r
+        return $headers;\r
+       }\r
+\r
+    /**\r
+    * Set Cookie\r
+    * @param string $domain\r
+    * @param string $path\r
+    * @param string $name cookie name\r
+    * @param string $value cookie value\r
+    * @param bool $secure\r
+    * @param int $expires expiry time (null if session cookie, <= 0 will delete cookie)\r
+    * @return void\r
+    */\r
+    function set_cookie($domain, $path, $name, $value, $secure=false, $expires=null)\r
+    {\r
+        if ($domain == '') return;\r
+        if ($path == '') return;\r
+        if ($name == '') return;\r
+        // check if cookie needs to go\r
+        if (isset($expires) && ($expires <= 0)) {\r
+            if (isset($this->cookies[$domain][$path][$name])) unset($this->cookies[$domain][$path][$name]);\r
+            return;\r
+        }\r
+        if ($value == '') return;\r
+        $this->cookies[$domain][$path][$name] = array($value, $secure, $expires);\r
+        return;\r
+    }\r
+\r
+    /**\r
+    * Clear cookies - [domain [,path [,name]]] - call method with no arguments to clear all cookies.\r
+    * @param string $domain\r
+    * @param string $path\r
+    * @param string $name\r
+    * @return void\r
+    */\r
+    function clear($domain=null, $path=null, $name=null)\r
+    {\r
+        if (!isset($domain)) {\r
+            $this->cookies = array();\r
+        } elseif (!isset($path)) {\r
+            if (isset($this->cookies[$domain])) unset($this->cookies[$domain]);\r
+        } elseif (!isset($name)) {\r
+            if (isset($this->cookies[$domain][$path])) unset($this->cookies[$domain][$path]);\r
+        } elseif (isset($name)) {\r
+            if (isset($this->cookies[$domain][$path][$name])) unset($this->cookies[$domain][$path][$name]);\r
+        }\r
+    }\r
+\r
+    /**\r
+    * Compare string length - used for sorting\r
+    * @access private\r
+    * @return int\r
+    */\r
+    function _cmp_length($a, $b)\r
+    {\r
+        $la = strlen($a); $lb = strlen($b);\r
+        if ($la == $lb) return 0;\r
+        return ($la > $lb) ? -1 : 1;\r
+    }\r
+\r
+    /**\r
+    * Reduce domain\r
+    * @param string $domain\r
+    * @return string\r
+    * @access private\r
+    */\r
+    function _reduce_domain($domain)\r
+    {\r
+        if ($domain == '') return '';\r
+        if (substr($domain, 0, 1) == '.') return substr($domain, 1);\r
+        return substr($domain, strpos($domain, '.'));\r
+    }\r
+\r
+    /**\r
+    * Path match - check if path1 path-matches path2\r
+    *\r
+    * From RFC 2965: \r
+    *   <i>For two strings that represent paths, P1 and P2, P1 path-matches P2\r
+    *   if P2 is a prefix of P1 (including the case where P1 and P2 string-\r
+    *   compare equal).  Thus, the string /tec/waldo path-matches /tec.</i>\r
+    * @param string $path1\r
+    * @param string $path2\r
+    * @return bool\r
+    * @access private\r
+    */\r
+    function _path_match($path1, $path2)\r
+    {\r
+        return (substr($path1, 0, strlen($path2)) == $path2);\r
+    }\r
+\r
+    /**\r
+    * Domain match - check if domain1 domain-matches domain2\r
+    *\r
+    * A few extracts from RFC 2965: \r
+    *  -  A Set-Cookie2 from request-host y.x.foo.com for Domain=.foo.com\r
+    *     would be rejected, because H is y.x and contains a dot.\r
+    *\r
+    *  -  A Set-Cookie2 from request-host x.foo.com for Domain=.foo.com\r
+    *     would be accepted.\r
+    *\r
+    *  -  A Set-Cookie2 with Domain=.com or Domain=.com., will always be\r
+    *     rejected, because there is no embedded dot.\r
+    *\r
+    *  -  A Set-Cookie2 from request-host example for Domain=.local will\r
+    *     be accepted, because the effective host name for the request-\r
+    *     host is example.local, and example.local domain-matches .local.\r
+    *\r
+    * I'm ignoring the first point for now (must check to see how other browsers handle\r
+    * this rule for Set-Cookie headers)\r
+    *\r
+    * @param string $domain1\r
+    * @param string $domain2\r
+    * @return bool\r
+    * @access private\r
+    */\r
+    function _domain_match($domain1, $domain2)\r
+    {\r
+        $domain1 = strtolower($domain1);\r
+        $domain2 = strtolower($domain2);\r
+        while (strpos($domain1, '.') !== false) {\r
+            if ($domain1 == $domain2) return true;\r
+            $domain1 = $this->_reduce_domain($domain1);\r
+            continue;\r
+        }\r
+        return false;\r
+    }\r
+}\r
 ?>
\ No newline at end of file