Commits

Anonymous committed f31e881

Upgraded phpFlickr libraries to version 2.3.1

Comments (0)

Files changed (14)

site/libraries/phpFlickr/.phpFlickr.php.swp

Binary file removed.

site/libraries/phpFlickr/PEAR/DB.php

File contents unchanged.

site/libraries/phpFlickr/PEAR/DB/common.php

File contents unchanged.

site/libraries/phpFlickr/PEAR/DB/mysql.php

File contents unchanged.

site/libraries/phpFlickr/PEAR/DB/pgsql.php

File contents unchanged.

site/libraries/phpFlickr/PEAR/DB/storage.php

File contents unchanged.

site/libraries/phpFlickr/PEAR/HTTP/Request.php

 <?php
-// +-----------------------------------------------------------------------+
-// | Copyright (c) 2002-2003, 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@phpguru.org>                           |
-// +-----------------------------------------------------------------------+
-//
-// $Id: Request.php 32 2005-08-01 06:21:02Z dancoulter $
-//
-// HTTP_Request Class
-//
-// Simple example, (Fetches yahoo.com and displays it):
-//
-// $a = &new HTTP_Request('http://www.yahoo.com/');
-// $a->sendRequest();
-// echo $a->getResponseBody();
-//
+/**
+ * Class for performing HTTP requests
+ *
+ * PHP versions 4 and 5
+ * 
+ * LICENSE:
+ *
+ * Copyright (c) 2002-2007, 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.
+ *
+ * @category    HTTP
+ * @package     HTTP_Request
+ * @author      Richard Heyes <richard@phpguru.org>
+ * @author      Alexey Borzov <avb@php.net>
+ * @copyright   2002-2007 Richard Heyes
+ * @license     http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version     CVS: $Id: Request.php 127 2008-01-17 20:21:37Z dcoulter $
+ * @link        http://pear.php.net/package/HTTP_Request/ 
+ */
 
+/**
+ * PEAR and PEAR_Error classes (for error handling)
+ */
 require_once 'PEAR.php';
+/**
+ * Socket class
+ */
 require_once 'Net/Socket.php';
+/**
+ * URL handling class
+ */ 
 require_once 'Net/URL.php';
 
+/**#@+
+ * Constants for HTTP request methods
+ */ 
 define('HTTP_REQUEST_METHOD_GET',     'GET',     true);
 define('HTTP_REQUEST_METHOD_HEAD',    'HEAD',    true);
 define('HTTP_REQUEST_METHOD_POST',    'POST',    true);
 define('HTTP_REQUEST_METHOD_DELETE',  'DELETE',  true);
 define('HTTP_REQUEST_METHOD_OPTIONS', 'OPTIONS', true);
 define('HTTP_REQUEST_METHOD_TRACE',   'TRACE',   true);
+/**#@-*/
 
+/**#@+
+ * Constants for HTTP request error codes
+ */ 
+define('HTTP_REQUEST_ERROR_FILE',             1);
+define('HTTP_REQUEST_ERROR_URL',              2);
+define('HTTP_REQUEST_ERROR_PROXY',            4);
+define('HTTP_REQUEST_ERROR_REDIRECTS',        8);
+define('HTTP_REQUEST_ERROR_RESPONSE',        16);  
+define('HTTP_REQUEST_ERROR_GZIP_METHOD',     32);
+define('HTTP_REQUEST_ERROR_GZIP_READ',       64);
+define('HTTP_REQUEST_ERROR_GZIP_DATA',      128);
+define('HTTP_REQUEST_ERROR_GZIP_CRC',       256);
+/**#@-*/
+
+/**#@+
+ * Constants for HTTP protocol versions
+ */
 define('HTTP_REQUEST_HTTP_VER_1_0', '1.0', true);
 define('HTTP_REQUEST_HTTP_VER_1_1', '1.1', true);
+/**#@-*/
 
-class HTTP_Request {
+if (extension_loaded('mbstring') && (2 & ini_get('mbstring.func_overload'))) {
+   /**
+    * Whether string functions are overloaded by their mbstring equivalents 
+    */
+    define('HTTP_REQUEST_MBSTRING', true);
+} else {
+   /**
+    * @ignore
+    */
+    define('HTTP_REQUEST_MBSTRING', false);
+}
 
+/**
+ * Class for performing HTTP requests
+ *
+ * Simple example (fetches yahoo.com and displays it):
+ * <code>
+ * $a = &new HTTP_Request('http://www.yahoo.com/');
+ * $a->sendRequest();
+ * echo $a->getResponseBody();
+ * </code>
+ *
+ * @category    HTTP
+ * @package     HTTP_Request
+ * @author      Richard Heyes <richard@phpguru.org>
+ * @author      Alexey Borzov <avb@php.net>
+ * @version     Release: 1.4.2
+ */
+class HTTP_Request
+{
+   /**#@+
+    * @access private
+    */
     /**
     * Instance of Net_URL
-    * @var object Net_URL
+    * @var Net_URL
     */
     var $_url;
 
 
     /**
     * Socket object
-    * @var object Net_Socket
+    * @var Net_Socket
     */
     var $_sock;
     
 
     /**
     * Post data
-    * @var mixed
+    * @var array
     */
     var $_postData;
 
    /**
+    * Request body  
+    * @var string
+    */
+    var $_body;
+
+   /**
+    * A list of methods that MUST NOT have a request body, per RFC 2616
+    * @var array
+    */
+    var $_bodyDisallowed = array('TRACE');
+
+   /**
     * Files to post 
     * @var array
     */
     
     /**
     * HTTP_Response object
-    * @var object HTTP_Response
+    * @var HTTP_Response
     */
     var $_response;
     
     * @var array
     */
     var $_socketOptions = null;
+   /**#@-*/
 
     /**
     * Constructor
     */
     function HTTP_Request($url = '', $params = array())
     {
-        $this->_sock           = &new Net_Socket();
         $this->_method         =  HTTP_REQUEST_METHOD_GET;
         $this->_http           =  HTTP_REQUEST_HTTP_VER_1_1;
         $this->_requestHeaders = array();
-        $this->_postData       = null;
+        $this->_postData       = array();
+        $this->_body           = null;
 
         $this->_user = null;
         $this->_pass = null;
         // Default useragent
         $this->addHeader('User-Agent', 'PEAR HTTP_Request class ( http://pear.php.net/ )');
 
-        // Make sure keepalives dont knobble us
+        // We don't do keep-alives by default
         $this->addHeader('Connection', 'close');
 
         // Basic authentication
         if (!empty($this->_user)) {
-            $this->_requestHeaders['Authorization'] = 'Basic ' . base64_encode($this->_user . ':' . $this->_pass);
+            $this->addHeader('Authorization', 'Basic ' . base64_encode($this->_user . ':' . $this->_pass));
+        }
+
+        // Proxy authentication (see bug #5913)
+        if (!empty($this->_proxy_user)) {
+            $this->addHeader('Proxy-Authorization', 'Basic ' . base64_encode($this->_proxy_user . ':' . $this->_proxy_pass));
         }
 
         // Use gzip encoding if possible
-        // Avoid gzip encoding if using multibyte functions (see #1781)
-        if (HTTP_REQUEST_HTTP_VER_1_1 == $this->_http && extension_loaded('zlib') &&
-            0 == (2 & ini_get('mbstring.func_overload'))) {
-
+        if (HTTP_REQUEST_HTTP_VER_1_1 == $this->_http && extension_loaded('zlib')) {
             $this->addHeader('Accept-Encoding', 'gzip');
         }
     }
         if (HTTP_REQUEST_HTTP_VER_1_1 == $this->_http) {
             $this->addHeader('Host', $this->_generateHostHeader());
         }
+
+        // set '/' instead of empty path rather than check later (see bug #8662)
+        if (empty($this->_url->path)) {
+            $this->_url->path = '/';
+        } 
     }
     
+   /**
+    * Returns the current request URL  
+    *
+    * @return   string  Current request URL
+    * @access   public
+    */
+    function getUrl()
+    {
+        return empty($this->_url)? '': $this->_url->getUrl();
+    }
+
     /**
     * Sets a proxy to be used
     *
     */
     function addHeader($name, $value)
     {
-        $this->_requestHeaders[$name] = $value;
+        $this->_requestHeaders[strtolower($name)] = $value;
     }
 
     /**
     */
     function removeHeader($name)
     {
-        if (isset($this->_requestHeaders[$name])) {
-            unset($this->_requestHeaders[$name]);
+        if (isset($this->_requestHeaders[strtolower($name)])) {
+            unset($this->_requestHeaders[strtolower($name)]);
         }
     }
 
     function addFile($inputName, $fileName, $contentType = 'application/octet-stream')
     {
         if (!is_array($fileName) && !is_readable($fileName)) {
-            return PEAR::raiseError("File '{$fileName}' is not readable");
+            return PEAR::raiseError("File '{$fileName}' is not readable", HTTP_REQUEST_ERROR_FILE);
         } elseif (is_array($fileName)) {
             foreach ($fileName as $name) {
                 if (!is_readable($name)) {
-                    return PEAR::raiseError("File '{$name}' is not readable");
+                    return PEAR::raiseError("File '{$name}' is not readable", HTTP_REQUEST_ERROR_FILE);
                 }
             }
         }
     }
 
     /**
-    * Adds raw postdata
+    * Adds raw postdata (DEPRECATED)
     *
     * @param string     The data
     * @param bool       Whether data is preencoded or not, default = already encoded
     * @access public
+    * @deprecated       deprecated since 1.3.0, method setBody() should be used instead
     */
     function addRawPostData($postdata, $preencoded = true)
     {
-        $this->_postData = $preencoded ? $postdata : urlencode($postdata);
+        $this->_body = $preencoded ? $postdata : urlencode($postdata);
+    }
+
+   /**
+    * Sets the request body (for POST, PUT and similar requests)
+    *
+    * @param    string  Request body
+    * @access   public
+    */
+    function setBody($body)
+    {
+        $this->_body = $body;
     }
 
     /**
     */
     function addCookie($name, $value)
     {
-        $cookies = isset($this->_requestHeaders['Cookie']) ? $this->_requestHeaders['Cookie']. '; ' : '';
+        $cookies = isset($this->_requestHeaders['cookie']) ? $this->_requestHeaders['cookie']. '; ' : '';
         $this->addHeader('Cookie', $cookies . $name . '=' . $value);
     }
     
     function sendRequest($saveBody = true)
     {
         if (!is_a($this->_url, 'Net_URL')) {
-            return PEAR::raiseError('No URL given.');
+            return PEAR::raiseError('No URL given', HTTP_REQUEST_ERROR_URL);
         }
 
         $host = isset($this->_proxy_host) ? $this->_proxy_host : $this->_url->host;
         // we running on at least 4.3.0
         if (strcasecmp($this->_url->protocol, 'https') == 0 AND function_exists('file_get_contents') AND extension_loaded('openssl')) {
             if (isset($this->_proxy_host)) {
-                return PEAR::raiseError('HTTPS proxies are not supported.');
+                return PEAR::raiseError('HTTPS proxies are not supported', HTTP_REQUEST_ERROR_PROXY);
             }
             $host = 'ssl://' . $host;
         }
 
-        // If this is a second request, we may get away without
-        // re-connecting if they're on the same server
-        if (PEAR::isError($err = $this->_sock->connect($host, $port, null, $this->_timeout, $this->_socketOptions)) ||
-            PEAR::isError($err = $this->_sock->write($this->_buildRequest()))) {
+        // magic quotes may fuck up file uploads and chunked response processing
+        $magicQuotes = ini_get('magic_quotes_runtime');
+        ini_set('magic_quotes_runtime', false);
 
-            return $err;
-        }
-        if (!empty($this->_readTimeout)) {
-            $this->_sock->setTimeout($this->_readTimeout[0], $this->_readTimeout[1]);
+        // RFC 2068, section 19.7.1: A client MUST NOT send the Keep-Alive 
+        // connection token to a proxy server...
+        if (isset($this->_proxy_host) && !empty($this->_requestHeaders['connection']) &&
+            'Keep-Alive' == $this->_requestHeaders['connection'])
+        {
+            $this->removeHeader('connection');
         }
 
-        $this->_notify('sentRequest');
+        $keepAlive = (HTTP_REQUEST_HTTP_VER_1_1 == $this->_http && empty($this->_requestHeaders['connection'])) ||
+                     (!empty($this->_requestHeaders['connection']) && 'Keep-Alive' == $this->_requestHeaders['connection']);
+        $sockets   = &PEAR::getStaticProperty('HTTP_Request', 'sockets');
+        $sockKey   = $host . ':' . $port;
+        unset($this->_sock);
 
-        // Read the response
-        $this->_response = &new HTTP_Response($this->_sock, $this->_listeners);
-        if (PEAR::isError($err = $this->_response->process($this->_saveBody && $saveBody)) ) {
+        // There is a connected socket in the "static" property?
+        if ($keepAlive && !empty($sockets[$sockKey]) &&
+            !empty($sockets[$sockKey]->fp)) 
+        {
+            $this->_sock =& $sockets[$sockKey];
+            $err = null;
+        } else {
+            $this->_notify('connect');
+            $this->_sock =& new Net_Socket();
+            $err = $this->_sock->connect($host, $port, null, $this->_timeout, $this->_socketOptions);
+        }
+        PEAR::isError($err) or $err = $this->_sock->write($this->_buildRequest());
+
+        if (!PEAR::isError($err)) {
+            if (!empty($this->_readTimeout)) {
+                $this->_sock->setTimeout($this->_readTimeout[0], $this->_readTimeout[1]);
+            }
+
+            $this->_notify('sentRequest');
+
+            // Read the response
+            $this->_response = &new HTTP_Response($this->_sock, $this->_listeners);
+            $err = $this->_response->process(
+                $this->_saveBody && $saveBody,
+                HTTP_REQUEST_METHOD_HEAD != $this->_method
+            );
+
+            if ($keepAlive) {
+                $keepAlive = (isset($this->_response->_headers['content-length'])
+                              || (isset($this->_response->_headers['transfer-encoding'])
+                                  && strtolower($this->_response->_headers['transfer-encoding']) == 'chunked'));
+                if ($keepAlive) {
+                    if (isset($this->_response->_headers['connection'])) {
+                        $keepAlive = strtolower($this->_response->_headers['connection']) == 'keep-alive';
+                    } else {
+                        $keepAlive = 'HTTP/'.HTTP_REQUEST_HTTP_VER_1_1 == $this->_response->_protocol;
+                    }
+                }
+            }
+        }
+
+        ini_set('magic_quotes_runtime', $magicQuotes);
+
+        if (PEAR::isError($err)) {
             return $err;
         }
 
+        if (!$keepAlive) {
+            $this->disconnect();
+        // Store the connected socket in "static" property
+        } elseif (empty($sockets[$sockKey]) || empty($sockets[$sockKey]->fp)) {
+            $sockets[$sockKey] =& $this->_sock;
+        }
+
         // Check for redirection
-        // Bugfix (PEAR) bug #18, 6 oct 2003 by Dave Mertens (headers are also stored lowercase, so we're gonna use them here)
-        // some non RFC2616 compliant servers (scripts) are returning lowercase headers ('location: xxx')
         if (    $this->_allowRedirects
             AND $this->_redirects <= $this->_maxRedirects
             AND $this->getResponseCode() > 300
 
         // Too many redirects
         } elseif ($this->_allowRedirects AND $this->_redirects > $this->_maxRedirects) {
-            return PEAR::raiseError('Too many redirects');
+            return PEAR::raiseError('Too many redirects', HTTP_REQUEST_ERROR_REDIRECTS);
         }
 
-        $this->_sock->disconnect();
+        return true;
+    }
 
-        return true;
+    /**
+     * Disconnect the socket, if connected. Only useful if using Keep-Alive.
+     *
+     * @access public
+     */
+    function disconnect()
+    {
+        if (!empty($this->_sock) && !empty($this->_sock->fp)) {
+            $this->_notify('disconnect');
+            $this->_sock->disconnect();
+        }
     }
 
     /**
         if (!isset($headername)) {
             return isset($this->_response->_headers)? $this->_response->_headers: array();
         } else {
+            $headername = strtolower($headername);
             return isset($this->_response->_headers[$headername]) ? $this->_response->_headers[$headername] : false;
         }
     }
 
         $host = isset($this->_proxy_host) ? $this->_url->protocol . '://' . $this->_url->host : '';
         $port = (isset($this->_proxy_host) AND $this->_url->port != 80) ? ':' . $this->_url->port : '';
-        $path = (empty($this->_url->path)? '/': $this->_url->path) . $querystring;
+        $path = $this->_url->path . $querystring;
         $url  = $host . $port . $path;
 
+        if (!strlen($url)) {
+            $url = '/';
+        }
+
         $request = $this->_method . ' ' . $url . ' HTTP/' . $this->_http . "\r\n";
 
-        if (HTTP_REQUEST_METHOD_POST != $this->_method && HTTP_REQUEST_METHOD_PUT != $this->_method) {
+        if (in_array($this->_method, $this->_bodyDisallowed) ||
+            (0 == strlen($this->_body) && (HTTP_REQUEST_METHOD_POST != $this->_method ||
+             (empty($this->_postData) && empty($this->_postFiles)))))
+        {
             $this->removeHeader('Content-Type');
         } else {
-            if (empty($this->_requestHeaders['Content-Type'])) {
+            if (empty($this->_requestHeaders['content-type'])) {
                 // Add default content-type
                 $this->addHeader('Content-Type', 'application/x-www-form-urlencoded');
-            } elseif ('multipart/form-data' == $this->_requestHeaders['Content-Type']) {
+            } elseif ('multipart/form-data' == $this->_requestHeaders['content-type']) {
                 $boundary = 'HTTP_Request_' . md5(uniqid('request') . microtime());
                 $this->addHeader('Content-Type', 'multipart/form-data; boundary=' . $boundary);
             }
         // Request Headers
         if (!empty($this->_requestHeaders)) {
             foreach ($this->_requestHeaders as $name => $value) {
-                $request .= $name . ': ' . $value . "\r\n";
+                $canonicalName = implode('-', array_map('ucfirst', explode('-', $name)));
+                $request      .= $canonicalName . ': ' . $value . "\r\n";
             }
         }
 
         // No post data or wrong method, so simply add a final CRLF
-        if ((HTTP_REQUEST_METHOD_POST != $this->_method && HTTP_REQUEST_METHOD_PUT != $this->_method) ||
-            (empty($this->_postData) && empty($this->_postFiles))) {
+        if (in_array($this->_method, $this->_bodyDisallowed) || 
+            (HTTP_REQUEST_METHOD_POST != $this->_method && 0 == strlen($this->_body))) {
 
             $request .= "\r\n";
+
         // Post data if it's an array
-        } elseif ((!empty($this->_postData) && is_array($this->_postData)) || !empty($this->_postFiles)) {
+        } elseif (HTTP_REQUEST_METHOD_POST == $this->_method && 
+                  (!empty($this->_postData) || !empty($this->_postFiles))) {
+
             // "normal" POST request
             if (!isset($boundary)) {
                 $postdata = implode('&', array_map(
                         $postdata .= "\r\n\r\n" . $data . "\r\n";
                     }
                 }
-                $postdata .= '--' . $boundary . "\r\n";
+                $postdata .= '--' . $boundary . "--\r\n";
             }
-            $request .= 'Content-Length: ' . strlen($postdata) . "\r\n\r\n";
+            $request .= 'Content-Length: ' .
+                        (HTTP_REQUEST_MBSTRING? mb_strlen($postdata, 'iso-8859-1'): strlen($postdata)) .
+                        "\r\n\r\n";
             $request .= $postdata;
 
-        // Post data if it's raw
-        } elseif(!empty($this->_postData)) {
-            $request .= 'Content-Length: ' . strlen($this->_postData) . "\r\n\r\n";
-            $request .= $this->_postData;
+        // Explicitly set request body
+        } elseif (0 < strlen($this->_body)) {
+
+            $request .= 'Content-Length: ' .
+                        (HTTP_REQUEST_MBSTRING? mb_strlen($this->_body, 'iso-8859-1'): strlen($this->_body)) .
+                        "\r\n\r\n";
+            $request .= $this->_body;
+
+        // Terminate headers with CRLF on POST request with no body, too
+        } else {
+
+            $request .= "\r\n";
         }
         
         return $request;
     * @param    string  name for item
     * @param    mixed   item's values
     * @return   array   array with the following items: array('item name', 'item value');
+    * @access   private
     */
     function _flattenArray($name, $values)
     {
     * Adds a Listener to the list of listeners that are notified of
     * the object's events
     * 
-    * @param    object   HTTP_Request_Listener instance to attach
-    * @return   boolean  whether the listener was successfully attached
+    * Events sent by HTTP_Request object
+    * - 'connect': on connection to server
+    * - 'sentRequest': after the request was sent
+    * - 'disconnect': on disconnection from server
+    *
+    * Events sent by HTTP_Response object
+    * - 'gotHeaders': after receiving response headers (headers are passed in $data)
+    * - 'tick': on receiving a part of response body (the part is passed in $data)
+    * - 'gzTick': on receiving a gzip-encoded part of response body (ditto)
+    * - 'gotBody': after receiving the response body (passes the decoded body in $data if it was gzipped)
+    *
+    * @param    HTTP_Request_Listener   listener to attach
+    * @return   boolean                 whether the listener was successfully attached
     * @access   public
     */
     function attach(&$listener)
    /**
     * Removes a Listener from the list of listeners 
     * 
-    * @param    object   HTTP_Request_Listener instance to detach
-    * @return   boolean  whether the listener was successfully detached
+    * @param    HTTP_Request_Listener   listener to detach
+    * @return   boolean                 whether the listener was successfully detached
     * @access   public
     */
     function detach(&$listener)
    /**
     * Notifies all registered listeners of an event.
     * 
-    * Events sent by HTTP_Request object
-    * 'sentRequest': after the request was sent
-    * Events sent by HTTP_Response object
-    * 'gotHeaders': after receiving response headers (headers are passed in $data)
-    * 'tick': on receiving a part of response body (the part is passed in $data)
-    * 'gzTick': on receiving a gzip-encoded part of response body (ditto)
-    * 'gotBody': after receiving the response body (passes the decoded body in $data if it was gzipped)
-    * 
     * @param    string  Event name
     * @param    mixed   Additional data
     * @access   private
+    * @see      HTTP_Request::attach()
     */
     function _notify($event, $data = null)
     {
 
 
 /**
-* Response class to complement the Request class
-*/
+ * Response class to complement the Request class
+ *
+ * @category    HTTP
+ * @package     HTTP_Request
+ * @author      Richard Heyes <richard@phpguru.org>
+ * @author      Alexey Borzov <avb@php.net>
+ * @version     Release: 1.4.2
+ */
 class HTTP_Response
 {
     /**
     * Socket object
-    * @var object
+    * @var Net_Socket
     */
     var $_sock;
 
     */
     var $_listeners = array();
 
+   /**
+    * Bytes left to read from message-body
+    * @var null|int
+    */
+    var $_toRead;
+
     /**
     * Constructor
     *
-    * @param  object Net_Socket     socket to read the response from
-    * @param  array                 listeners attached to request
-    * @return mixed PEAR Error on error, true otherwise
+    * @param  Net_Socket    socket to read the response from
+    * @param  array         listeners attached to request
     */
     function HTTP_Response(&$sock, &$listeners)
     {
     * @param  bool      Whether to store response body in object property, set
     *                   this to false if downloading a LARGE file and using a Listener.
     *                   This is assumed to be true if body is gzip-encoded.
+    * @param  bool      Whether the response can actually have a message-body.
+    *                   Will be set to false for HEAD requests.
     * @throws PEAR_Error
     * @return mixed     true on success, PEAR_Error in case of malformed response
     */
-    function process($saveBody = true)
+    function process($saveBody = true, $canHaveBody = true)
     {
         do {
             $line = $this->_sock->readLine();
             if (sscanf($line, 'HTTP/%s %s', $http_version, $returncode) != 2) {
-                return PEAR::raiseError('Malformed response.');
+                return PEAR::raiseError('Malformed response', HTTP_REQUEST_ERROR_RESPONSE);
             } else {
                 $this->_protocol = 'HTTP/' . $http_version;
                 $this->_code     = intval($returncode);
 
         $this->_notify('gotHeaders', $this->_headers);
 
+        // RFC 2616, section 4.4:
+        // 1. Any response message which "MUST NOT" include a message-body ... 
+        // is always terminated by the first empty line after the header fields 
+        // 3. ... If a message is received with both a
+        // Transfer-Encoding header field and a Content-Length header field,
+        // the latter MUST be ignored.
+        $canHaveBody = $canHaveBody && $this->_code >= 200 && 
+                       $this->_code != 204 && $this->_code != 304;
+
         // If response body is present, read it and decode
         $chunked = isset($this->_headers['transfer-encoding']) && ('chunked' == $this->_headers['transfer-encoding']);
         $gzipped = isset($this->_headers['content-encoding']) && ('gzip' == $this->_headers['content-encoding']);
         $hasBody = false;
-        while (!$this->_sock->eof()) {
-            if ($chunked) {
-                $data = $this->_readChunked();
+        if ($canHaveBody && ($chunked || !isset($this->_headers['content-length']) || 
+                0 != $this->_headers['content-length']))
+        {
+            if ($chunked || !isset($this->_headers['content-length'])) {
+                $this->_toRead = null;
             } else {
-                $data = $this->_sock->read(4096);
+                $this->_toRead = $this->_headers['content-length'];
             }
-            if ('' != $data) {
-                $hasBody = true;
-                if ($saveBody || $gzipped) {
-                    $this->_body .= $data;
+            while (!$this->_sock->eof() && (is_null($this->_toRead) || 0 < $this->_toRead)) {
+                if ($chunked) {
+                    $data = $this->_readChunked();
+                } elseif (is_null($this->_toRead)) {
+                    $data = $this->_sock->read(4096);
+                } else {
+                    $data = $this->_sock->read(min(4096, $this->_toRead));
+                    $this->_toRead -= HTTP_REQUEST_MBSTRING? mb_strlen($data, 'iso-8859-1'): strlen($data);
                 }
-                $this->_notify($gzipped? 'gzTick': 'tick', $data);
+                if ('' == $data) {
+                    break;
+                } else {
+                    $hasBody = true;
+                    if ($saveBody || $gzipped) {
+                        $this->_body .= $data;
+                    }
+                    $this->_notify($gzipped? 'gzTick': 'tick', $data);
+                }
             }
         }
+
         if ($hasBody) {
             // Uncompress the body if needed
             if ($gzipped) {
-                $this->_body = gzinflate(substr($this->_body, 10));
+                $body = $this->_decodeGzip($this->_body);
+                if (PEAR::isError($body)) {
+                    return $body;
+                }
+                $this->_body = $body;
                 $this->_notify('gotBody', $this->_body);
             } else {
                 $this->_notify('gotBody');
     */
     function _processHeader($header)
     {
+        if (false === strpos($header, ':')) {
+            return;
+        }
         list($headername, $headervalue) = explode(':', $header, 2);
-        $headername_i = strtolower($headername);
-        $headervalue  = ltrim($headervalue);
+        $headername  = strtolower($headername);
+        $headervalue = ltrim($headervalue);
         
-        if ('set-cookie' != $headername_i) {
-            $this->_headers[$headername]   = $headervalue;
-            $this->_headers[$headername_i] = $headervalue;
+        if ('set-cookie' != $headername) {
+            if (isset($this->_headers[$headername])) {
+                $this->_headers[$headername] .= ',' . $headervalue;
+            } else {
+                $this->_headers[$headername]  = $headervalue;
+            }
         } else {
             $this->_parseCookie($headervalue);
         }
                 $this->_chunkLength = hexdec($matches[1]); 
                 // Chunk with zero length indicates the end
                 if (0 == $this->_chunkLength) {
-                    $this->_sock->readAll(); // make this an eof()
+                    $this->_sock->readLine(); // make this an eof()
                     return '';
                 }
-            } elseif ($this->_sock->eof()) {
+            } else {
                 return '';
             }
         }
         $data = $this->_sock->read($this->_chunkLength);
-        $this->_chunkLength -= strlen($data);
+        $this->_chunkLength -= HTTP_REQUEST_MBSTRING? mb_strlen($data, 'iso-8859-1'): strlen($data);
         if (0 == $this->_chunkLength) {
             $this->_sock->readLine(); // Trailing CRLF
         }
             $this->_listeners[$id]->update($this, $event, $data);
         }
     }
+
+
+   /**
+    * Decodes the message-body encoded by gzip
+    *
+    * The real decoding work is done by gzinflate() built-in function, this
+    * method only parses the header and checks data for compliance with
+    * RFC 1952  
+    *
+    * @access   private
+    * @param    string  gzip-encoded data
+    * @return   string  decoded data
+    */
+    function _decodeGzip($data)
+    {
+        if (HTTP_REQUEST_MBSTRING) {
+            $oldEncoding = mb_internal_encoding();
+            mb_internal_encoding('iso-8859-1');
+        }
+        $length = strlen($data);
+        // If it doesn't look like gzip-encoded data, don't bother
+        if (18 > $length || strcmp(substr($data, 0, 2), "\x1f\x8b")) {
+            return $data;
+        }
+        $method = ord(substr($data, 2, 1));
+        if (8 != $method) {
+            return PEAR::raiseError('_decodeGzip(): unknown compression method', HTTP_REQUEST_ERROR_GZIP_METHOD);
+        }
+        $flags = ord(substr($data, 3, 1));
+        if ($flags & 224) {
+            return PEAR::raiseError('_decodeGzip(): reserved bits are set', HTTP_REQUEST_ERROR_GZIP_DATA);
+        }
+
+        // header is 10 bytes minimum. may be longer, though.
+        $headerLength = 10;
+        // extra fields, need to skip 'em
+        if ($flags & 4) {
+            if ($length - $headerLength - 2 < 8) {
+                return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA);
+            }
+            $extraLength = unpack('v', substr($data, 10, 2));
+            if ($length - $headerLength - 2 - $extraLength[1] < 8) {
+                return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA);
+            }
+            $headerLength += $extraLength[1] + 2;
+        }
+        // file name, need to skip that
+        if ($flags & 8) {
+            if ($length - $headerLength - 1 < 8) {
+                return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA);
+            }
+            $filenameLength = strpos(substr($data, $headerLength), chr(0));
+            if (false === $filenameLength || $length - $headerLength - $filenameLength - 1 < 8) {
+                return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA);
+            }
+            $headerLength += $filenameLength + 1;
+        }
+        // comment, need to skip that also
+        if ($flags & 16) {
+            if ($length - $headerLength - 1 < 8) {
+                return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA);
+            }
+            $commentLength = strpos(substr($data, $headerLength), chr(0));
+            if (false === $commentLength || $length - $headerLength - $commentLength - 1 < 8) {
+                return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA);
+            }
+            $headerLength += $commentLength + 1;
+        }
+        // have a CRC for header. let's check
+        if ($flags & 1) {
+            if ($length - $headerLength - 2 < 8) {
+                return PEAR::raiseError('_decodeGzip(): data too short', HTTP_REQUEST_ERROR_GZIP_DATA);
+            }
+            $crcReal   = 0xffff & crc32(substr($data, 0, $headerLength));
+            $crcStored = unpack('v', substr($data, $headerLength, 2));
+            if ($crcReal != $crcStored[1]) {
+                return PEAR::raiseError('_decodeGzip(): header CRC check failed', HTTP_REQUEST_ERROR_GZIP_CRC);
+            }
+            $headerLength += 2;
+        }
+        // unpacked data CRC and size at the end of encoded data
+        $tmp = unpack('V2', substr($data, -8));
+        $dataCrc  = $tmp[1];
+        $dataSize = $tmp[2];
+
+        // finally, call the gzinflate() function
+        $unpacked = @gzinflate(substr($data, $headerLength, -8), $dataSize);
+        if (false === $unpacked) {
+            return PEAR::raiseError('_decodeGzip(): gzinflate() call failed', HTTP_REQUEST_ERROR_GZIP_READ);
+        } elseif ($dataSize != strlen($unpacked)) {
+            return PEAR::raiseError('_decodeGzip(): data size check failed', HTTP_REQUEST_ERROR_GZIP_READ);
+        } elseif ((0xffffffff & $dataCrc) != (0xffffffff & crc32($unpacked))) {
+            return PEAR::raiseError('_decodeGzip(): data CRC check failed', HTTP_REQUEST_ERROR_GZIP_CRC);
+        }
+        if (HTTP_REQUEST_MBSTRING) {
+            mb_internal_encoding($oldEncoding);
+        }
+        return $unpacked;
+    }
 } // End class HTTP_Response
 ?>

site/libraries/phpFlickr/PEAR/HTTP/Request/Listener.php

 <?php
-// +-----------------------------------------------------------------------+
-// | Copyright (c) 2002-2003, 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: Alexey Borzov <avb@php.net>                                  |
-// +-----------------------------------------------------------------------+
-//
-// $Id: Listener.php 32 2005-08-01 06:21:02Z dancoulter $
-//
+/**
+ * Listener for HTTP_Request and HTTP_Response objects
+ *
+ * PHP versions 4 and 5
+ * 
+ * LICENSE:
+ *
+ * Copyright (c) 2002-2007, 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.
+ *
+ * @category    HTTP
+ * @package     HTTP_Request
+ * @author      Alexey Borzov <avb@php.net>
+ * @copyright   2002-2007 Richard Heyes
+ * @license     http://opensource.org/licenses/bsd-license.php New BSD License
+ * @version     CVS: $Id: Listener.php 127 2008-01-17 20:21:37Z dcoulter $
+ * @link        http://pear.php.net/package/HTTP_Request/ 
+ */
 
 /**
+ * Listener for HTTP_Request and HTTP_Response objects
+ *
  * This class implements the Observer part of a Subject-Observer
- * design pattern. It listens to the events sent by a 
- * HTTP_Request or HTTP_Response instance.
+ * design pattern.
  *
- * @package HTTP_Request
- * @author  Alexey Borzov <avb@php.net>
- * @version $Revision: 32 $
+ * @category    HTTP
+ * @package     HTTP_Request
+ * @author      Alexey Borzov <avb@php.net>
+ * @version     Release: 1.4.2
  */
 class HTTP_Request_Listener 
 {

site/libraries/phpFlickr/PEAR/Net/Socket.php

File contents unchanged.

site/libraries/phpFlickr/PEAR/Net/URL.php

File contents unchanged.

site/libraries/phpFlickr/PEAR/PEAR.php

  * @author     Stig Bakken <ssb@php.net>
  * @author     Tomas V.V.Cox <cox@idecnet.com>
  * @author     Greg Beaver <cellog@php.net>
- * @copyright  1997-2005 The PHP Group
+ * @copyright  1997-2006 The PHP Group
  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
- * @version    CVS: $Id: PEAR.php 32 2005-08-01 06:21:02Z dancoulter $
+ * @version    CVS: $Id: PEAR.php 127 2008-01-17 20:21:37Z dcoulter $
  * @link       http://pear.php.net/package/PEAR
  * @since      File available since Release 0.1
  */
  * @author     Stig Bakken <ssb@php.net>
  * @author     Tomas V.V. Cox <cox@idecnet.com>
  * @author     Greg Beaver <cellog@php.net>
- * @copyright  1997-2005 The PHP Group
+ * @copyright  1997-2006 The PHP Group
  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
- * @version    Release: 1.4.0a12
+ * @version    Release: 1.6.2
  * @link       http://pear.php.net/package/PEAR
  * @see        PEAR_Error
  * @since      Class available since PHP 4.0.2
     function &getStaticProperty($class, $var)
     {
         static $properties;
+        if (!isset($properties[$class])) {
+            $properties[$class] = array();
+        }
+        if (!array_key_exists($var, $properties[$class])) {
+            $properties[$class][$var] = null;
+        }
         return $properties[$class][$var];
     }
 
     */
     function registerShutdownFunc($func, $args = array())
     {
+        // if we are called statically, there is a potential
+        // that no shutdown func is registered.  Bug #6445
+        if (!isset($GLOBALS['_PEAR_SHUTDOWN_REGISTERED'])) {
+            register_shutdown_function("_PEAR_call_destructors");
+            $GLOBALS['_PEAR_SHUTDOWN_REGISTERED'] = true;
+        }
         $GLOBALS['_PEAR_shutdown_funcs'][] = array($func, $args);
     }
 
      * @see PEAR::setErrorHandling
      * @since PHP 4.0.5
      */
-    function raiseError($message = null,
+    function &raiseError($message = null,
                          $code = null,
                          $mode = null,
                          $options = null,
             $ec = 'PEAR_Error';
         }
         if ($skipmsg) {
-            return new $ec($code, $mode, $options, $userinfo);
+            $a = &new $ec($code, $mode, $options, $userinfo);
+            return $a;
         } else {
-            return new $ec($message, $code, $mode, $options, $userinfo);
+            $a = &new $ec($message, $code, $mode, $options, $userinfo);
+            return $a;
         }
     }
 
      * @param string $message
      *
      */
-    function throwError($message = null,
+    function &throwError($message = null,
                          $code = null,
                          $userinfo = null)
     {
         if (isset($this) && is_a($this, 'PEAR')) {
-            return $this->raiseError($message, $code, null, null, $userinfo);
+            $a = &$this->raiseError($message, $code, null, null, $userinfo);
+            return $a;
         } else {
-            return PEAR::raiseError($message, $code, null, null, $userinfo);
+            $a = &PEAR::raiseError($message, $code, null, null, $userinfo);
+            return $a;
         }
     }
 
         sizeof($_PEAR_destructor_object_list))
     {
         reset($_PEAR_destructor_object_list);
+        if (PEAR::getStaticProperty('PEAR', 'destructlifo')) {
+            $_PEAR_destructor_object_list = array_reverse($_PEAR_destructor_object_list);
+        }
         while (list($k, $objref) = each($_PEAR_destructor_object_list)) {
             $classname = get_class($objref);
             while ($classname) {
  * @author     Stig Bakken <ssb@php.net>
  * @author     Tomas V.V. Cox <cox@idecnet.com>
  * @author     Gregory Beaver <cellog@php.net>
- * @copyright  1997-2005 The PHP Group
+ * @copyright  1997-2006 The PHP Group
  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
- * @version    Release: 1.4.0a12
+ * @version    Release: 1.6.2
  * @link       http://pear.php.net/manual/en/core.pear.pear-error.php
  * @see        PEAR::raiseError(), PEAR::throwError()
  * @since      Class available since PHP 4.0.2
         $this->code      = $code;
         $this->mode      = $mode;
         $this->userinfo  = $userinfo;
-        if (function_exists("debug_backtrace") && !defined('PEAR_IGNORE_BACKTRACE')) {
+        if (!PEAR::getStaticProperty('PEAR_Error', 'skiptrace')) {
             $this->backtrace = debug_backtrace();
+            if (isset($this->backtrace[0]) && isset($this->backtrace[0]['object'])) {
+                unset($this->backtrace[0]['object']);
+            }
         }
         if ($mode & PEAR_ERROR_CALLBACK) {
             $this->level = E_USER_NOTICE;
             }
         }
         if ($this->mode & PEAR_ERROR_EXCEPTION) {
-            trigger_error("PEAR_ERROR_EXCEPTION is obsolete, use class PEAR_ErrorStack for exceptions", E_USER_WARNING);
+            trigger_error("PEAR_ERROR_EXCEPTION is obsolete, use class PEAR_Exception for exceptions", E_USER_WARNING);
             eval('$e = new Exception($this->message, $this->code);throw($e);');
         }
     }

site/libraries/phpFlickr/auth.php

-<?
+<?php
     /* Last updated with phpFlickr 1.3.1
      *
      * Edit these variables to reflect the values you need. $default_redirect 

site/libraries/phpFlickr/getToken.php

File contents unchanged.

site/libraries/phpFlickr/phpFlickr.php

 <?php
-/* phpFlickr Class 2.1.0
+/* phpFlickr Class 2.3.1
  * Written by Dan Coulter (dan@dancoulter.com)
- * Sourceforge Project Page: http://www.sourceforge.net/projects/phpflickr/
+ * Project Home Page: http://phpflickr.com/
  * Released under GNU Lesser General Public License (http://www.gnu.org/copyleft/lgpl.html)
  * For more information about the class and upcoming tools and toys using it,
- * visit http://www.phpflickr.com/ or http://phpflickr.sourceforge.net
+ * visit http://www.phpflickr.com/
  *
- *     For installation instructions, open the README.txt file packaged with this
- *     class. If you don't have a copy, you can see it at:
- *     http://www.phpflickr.com/README.txt
+ *	 For installation instructions, open the README.txt file packaged with this
+ *	 class. If you don't have a copy, you can see it at:
+ *	 http://www.phpflickr.com/README.txt
  *
- *     Please submit all problems or questions to the Help Forum on my project page:
- *         http://sourceforge.net/forum/forum.php?forum_id=469652
+ *	 Please submit all problems or questions to the Help Forum on my Google Code project page:
+ *		 http://code.google.com/p/phpflickr/issues/list
  *
- */
+ */ 
 if (session_id() == "") {
-    @session_start();
+	@session_start();
 }
 
 // Decides which include path delimiter to use.  Windows should be using a semi-colon
 // and everything else should be using a colon.  If this isn't working on your system,
 // comment out this if statement and manually set the correct value into $path_delimiter.
 if (strpos(__FILE__, ':') !== false) {
-    $path_delimiter = ';';
+	$path_delimiter = ';';
 } else {
-    $path_delimiter = ':';
+	$path_delimiter = ':';
 }
 
 // This will add the packaged PEAR files into the include path for PHP, allowing you
 // ini_set('include_path', dirname(__FILE__) . '/PEAR' . $path_delimiter . ini_get('include_path'));
 
 class phpFlickr {
-    var $api_key;
-    var $secret;
-    var $REST = 'http://api.flickr.com/services/rest/';
-    var $Upload = 'http://api.flickr.com/services/upload/';
-    var $Replace = 'http://api.flickr.com/services/replace/';
-    var $req;
-    var $response;
-    var $parsed_response;
-    var $cache = false;
-    var $cache_db = null;
-    var $cache_table = null;
-    var $cache_dir = null;
-    var $cache_expire = null;
-    var $die_on_error;
-    var $error_code;
-    Var $error_msg;
-    var $token;
-    var $php_version;
+	var $api_key;
+	var $secret;
+	var $REST = 'http://api.flickr.com/services/rest/';
+	var $Upload = 'http://api.flickr.com/services/upload/';
+	var $Replace = 'http://api.flickr.com/services/replace/';
+	var $req;
+	var $response;
+	var $parsed_response;
+	var $cache = false;
+	var $cache_db = null;
+	var $cache_table = null;
+	var $cache_dir = null;
+	var $cache_expire = null;
+	var $die_on_error;
+	var $error_code;
+	Var $error_msg;
+	var $token;
+	var $php_version;
 
-    /*
-     * When your database cache table hits this many rows, a cleanup
-     * will occur to get rid of all of the old rows and cleanup the
-     * garbage in the table.  For most personal apps, 1000 rows should
-     * be more than enough.  If your site gets hit by a lot of traffic
-     * or you have a lot of disk space to spare, bump this number up.
-     * You should try to set it high enough that the cleanup only
-     * happens every once in a while, so this will depend on the growth
-     * of your table.
-     */
-    var $max_cache_rows = 1000;
+	/*
+	 * When your database cache table hits this many rows, a cleanup
+	 * will occur to get rid of all of the old rows and cleanup the
+	 * garbage in the table.  For most personal apps, 1000 rows should
+	 * be more than enough.  If your site gets hit by a lot of traffic
+	 * or you have a lot of disk space to spare, bump this number up.
+	 * You should try to set it high enough that the cleanup only
+	 * happens every once in a while, so this will depend on the growth
+	 * of your table.
+	 */
+	var $max_cache_rows = 1000;
 
-    function phpFlickr ($api_key, $secret = NULL, $die_on_error = false)
-    {
-        //The API Key must be set before any calls can be made.  You can
-        //get your own at http://www.flickr.com/services/api/misc.api_keys.html
-        $this->api_key = $api_key;
-        $this->secret = $secret;
-        $this->die_on_error = $die_on_error;
-        $this->service = "flickr";
+	function phpFlickr ($api_key, $secret = NULL, $die_on_error = false) {
+		//The API Key must be set before any calls can be made.  You can
+		//get your own at http://www.flickr.com/services/api/misc.api_keys.html
+		$this->api_key = $api_key;
+		$this->secret = $secret;
+		$this->die_on_error = $die_on_error;
+		$this->service = "flickr";
 
-        //Find the PHP version and store it for future reference
-        $this->php_version = explode("-", phpversion());
-        $this->php_version = explode(".", $this->php_version[0]);
+		//Find the PHP version and store it for future reference
+		$this->php_version = explode("-", phpversion());
+		$this->php_version = explode(".", $this->php_version[0]);
 
-        //All calls to the API are done via the POST method using the PEAR::HTTP_Request package.
-        require_once 'HTTP/Request.php';
-        $this->req =& new HTTP_Request();
-        $this->req->setMethod(HTTP_REQUEST_METHOD_POST);
-    }
+		//All calls to the API are done via the POST method using the PEAR::HTTP_Request package.
+		require_once 'HTTP/Request.php';
+		$this->req =& new HTTP_Request();
+		$this->req->setMethod(HTTP_REQUEST_METHOD_POST);
+	}
 
-    function enableCache($type, $connection, $cache_expire = 600, $table = 'flickr_cache')
-    {
-        // Turns on caching.  $type must be either "db" (for database caching) or "fs" (for filesystem).
-        // When using db, $connection must be a PEAR::DB connection string. Example:
-        //      "mysql://user:password@server/database"
-        // If the $table, doesn't exist, it will attempt to create it.
-        // When using file system, caching, the $connection is the folder that the web server has write
-        // access to. Use absolute paths for best results.  Relative paths may have unexpected behavior
-        // when you include this.  They'll usually work, you'll just want to test them.
-        if ($type == 'db') {
-            require_once 'DB.php';
-            $db =& DB::connect($connection);
-            if (PEAR::isError($db)) {
-                die($db->getMessage());
-            }
+	function enableCache ($type, $connection, $cache_expire = 600, $table = 'flickr_cache') {
+		// Turns on caching.  $type must be either "db" (for database caching) or "fs" (for filesystem).
+		// When using db, $connection must be a PEAR::DB connection string. Example:
+		//	  "mysql://user:password@server/database"
+		// If the $table, doesn't exist, it will attempt to create it.
+		// When using file system, caching, the $connection is the folder that the web server has write
+		// access to. Use absolute paths for best results.  Relative paths may have unexpected behavior
+		// when you include this.  They'll usually work, you'll just want to test them.
+		if ($type == 'db') {
+			require_once 'DB.php';
+			$db =& DB::connect($connection);
+			if (PEAR::isError($db)) {
+				die($db->getMessage());
+			}
 
-            /*
-             * If high performance is crucial, you can easily comment
-             * out this query once you've created your database table.
-             */
+			/*
+			 * If high performance is crucial, you can easily comment
+			 * out this query once you've created your database table.
+			 */
 
-            $db->query("
-                CREATE TABLE IF NOT EXISTS `$table` (
-                    `request` CHAR( 35 ) NOT NULL ,
-                    `response` MEDIUMTEXT NOT NULL ,
-                    `expiration` DATETIME NOT NULL ,
-                    INDEX ( `request` )
-                ) TYPE = MYISAM");
+			$db->query("
+				CREATE TABLE IF NOT EXISTS `$table` (
+					`request` CHAR( 35 ) NOT NULL ,
+					`response` MEDIUMTEXT NOT NULL ,
+					`expiration` DATETIME NOT NULL ,
+					INDEX ( `request` )
+				) TYPE = MYISAM");
 
-            if ($db->getOne("SELECT COUNT(*) FROM $table") > $this->max_cache_rows) {
-                $db->query("DELETE FROM $table WHERE expiration < DATE_SUB(NOW(), INTERVAL $cache_expire second)");
-                $db->query('OPTIMIZE TABLE ' . $this->cache_table);
-            }
+			if ($db->getOne("SELECT COUNT(*) FROM $table") > $this->max_cache_rows) {
+				$db->query("DELETE FROM $table WHERE expiration < DATE_SUB(NOW(), INTERVAL $cache_expire second)");
+				$db->query('OPTIMIZE TABLE ' . $this->cache_table);
+			}
 
-            $this->cache = 'db';
-            $this->cache_db = $db;
-            $this->cache_table = $table;
-        } elseif ($type == 'fs') {
-            $this->cache = 'fs';
-            $connection = realpath($connection);
-            $this->cache_dir = $connection;
-            if ($dir = opendir($this->cache_dir)) {
-                while ($file = readdir($dir)) {
-                    if (substr($file, -6) == '.cache' && ((filemtime($this->cache_dir . '/' . $file) + $cache_expire) < time()) ) {
-                        unlink($this->cache_dir . '/' . $file);
-                    }
-                }
-            }
-        }
-        $this->cache_expire = $cache_expire;
-    }
+			$this->cache = 'db';
+			$this->cache_db = $db;
+			$this->cache_table = $table;
+		} elseif ($type == 'fs') {
+			$this->cache = 'fs';
+			$connection = realpath($connection);
+			$this->cache_dir = $connection;
+			if ($dir = opendir($this->cache_dir)) {
+				while ($file = readdir($dir)) {
+					if (substr($file, -6) == '.cache' && ((filemtime($this->cache_dir . '/' . $file) + $cache_expire) < time()) ) {
+						unlink($this->cache_dir . '/' . $file);
+					}
+				}
+			}
+		}
+		$this->cache_expire = $cache_expire;
+	}
 
-    function getCached ($request)
-    {
-        //Checks the database or filesystem for a cached result to the request.
-        //If there is no cache result, it returns a value of false. If it finds one,
-        //it returns the unparsed XML.
-        $reqhash = md5(serialize($request));
-        if ($this->cache == 'db') {
-            $result = $this->cache_db->getOne("SELECT response FROM " . $this->cache_table . " WHERE request = ? AND DATE_SUB(NOW(), INTERVAL " . (int) $this->cache_expire . " SECOND) < expiration", $reqhash);
-            if (!empty($result)) {
-                return $result;
-            }
-        } elseif ($this->cache == 'fs') {
-            $file = $this->cache_dir . '/' . $reqhash . '.cache';
-            if (file_exists($file)) {
+	function getCached ($request) {
+		//Checks the database or filesystem for a cached result to the request.
+		//If there is no cache result, it returns a value of false. If it finds one,
+		//it returns the unparsed XML.
+		$reqhash = md5(serialize($request));
+		if ($this->cache == 'db') {
+			$result = $this->cache_db->getOne("SELECT response FROM " . $this->cache_table . " WHERE request = ? AND DATE_SUB(NOW(), INTERVAL " . (int) $this->cache_expire . " SECOND) < expiration", $reqhash);
+			if (!empty($result)) {
+				return $result;
+			}
+		} elseif ($this->cache == 'fs') {
+			$file = $this->cache_dir . '/' . $reqhash . '.cache';
+			if (file_exists($file)) {
 				if ($this->php_version[0] > 4 || ($this->php_version[0] == 4 && $this->php_version[1] >= 3)) {
 					return file_get_contents($file);
 				} else {
 					return implode('', file($file));
 				}
-            }
-        }
-        return false;
-    }
+			}
+		}
+		return false;
+	}
 
-    function cache ($request, $response)
-    {
-        //Caches the unparsed XML of a request.
-        $reqhash = md5(serialize($request));
-        if ($this->cache == 'db') {
-            //$this->cache_db->query("DELETE FROM $this->cache_table WHERE request = '$reqhash'");
-            if ($this->cache_db->getOne("SELECT COUNT(*) FROM {$this->cache_table} WHERE request = '$reqhash'")) {
-                $sql = "UPDATE " . $this->cache_table . " SET response = ?, expiration = ? WHERE request = ?";
-                $this->cache_db->query($sql, array($response, strftime("%Y-%m-%d %H:%M:%S"), $reqhash));
-            } else {
-                $sql = "INSERT INTO " . $this->cache_table . " (request, response, expiration) VALUES ('$reqhash', '" . str_replace("'", "''", $response) . "', '" . strftime("%Y-%m-%d %H:%M:%S") . "')";
-                $this->cache_db->query($sql);
-            }
-        } elseif ($this->cache == "fs") {
-            $file = $this->cache_dir . "/" . $reqhash . ".cache";
-            $fstream = fopen($file, "w");
-            $result = fwrite($fstream,$response);
-            fclose($fstream);
-            return $result;
-        }
-        return false;
-    }
+	function cache ($request, $response) {
+		//Caches the unparsed XML of a request.
+		$reqhash = md5(serialize($request));
+		if ($this->cache == 'db') {
+			//$this->cache_db->query("DELETE FROM $this->cache_table WHERE request = '$reqhash'");
+			if ($this->cache_db->getOne("SELECT COUNT(*) FROM {$this->cache_table} WHERE request = '$reqhash'")) {
+				$sql = "UPDATE " . $this->cache_table . " SET response = ?, expiration = ? WHERE request = ?";
+				$this->cache_db->query($sql, array($response, strftime("%Y-%m-%d %H:%M:%S"), $reqhash));
+			} else {
+				$sql = "INSERT INTO " . $this->cache_table . " (request, response, expiration) VALUES ('$reqhash', '" . str_replace("'", "''", $response) . "', '" . strftime("%Y-%m-%d %H:%M:%S") . "')";
+				$this->cache_db->query($sql);
+			}
+		} elseif ($this->cache == "fs") {
+			$file = $this->cache_dir . "/" . $reqhash . ".cache";
+			$fstream = fopen($file, "w");
+			$result = fwrite($fstream,$response);
+			fclose($fstream);
+			return $result;
+		}
+		return false;
+	}
 
-    function request ($command, $args = array(), $nocache = false)
-    {
-        //Sends a request to Flickr's REST endpoint via POST.
-        $this->req->setURL($this->REST);
-        $this->req->clearPostData();
-        if (substr($command,0,7) != "flickr.") {
-            $command = "flickr." . $command;
-        }
+	function request ($command, $args = array(), $nocache = false) {
+		//Sends a request to Flickr's REST endpoint via POST.
+		$this->req->setURL($this->REST);
+		$this->req->clearPostData();
+		if (substr($command,0,7) != "flickr.") {
+			$command = "flickr." . $command;
+		}
 
-        //Process arguments, including method and login data.
-        $args = array_merge(array("method" => $command, "format" => "php_serial", "api_key" => $this->api_key), $args);
-        if (!empty($this->token)) {
-            $args = array_merge($args, array("auth_token" => $this->token));
-        } elseif (!empty($_SESSION['phpFlickr_auth_token'])) {
-            $args = array_merge($args, array("auth_token" => $_SESSION['phpFlickr_auth_token']));
-        }
-        ksort($args);
-        $auth_sig = "";
-        if (!($this->response = $this->getCached($args)) || $nocache) {
-            foreach ($args as $key => $data) {
-                $auth_sig .= $key . $data;
-                $this->req->addPostData($key, $data);
-            }
-            if (!empty($this->secret)) {
-                $api_sig = md5($this->secret . $auth_sig);
-                $this->req->addPostData("api_sig", $api_sig);
-            }
+		//Process arguments, including method and login data.
+		$args = array_merge(array("method" => $command, "format" => "php_serial", "api_key" => $this->api_key), $args);
+		if (!empty($this->token)) {
+			$args = array_merge($args, array("auth_token" => $this->token));
+		} elseif (!empty($_SESSION['phpFlickr_auth_token'])) {
+			$args = array_merge($args, array("auth_token" => $_SESSION['phpFlickr_auth_token']));
+		}
+		ksort($args);
+		$auth_sig = "";
+		if (!($this->response = $this->getCached($args)) || $nocache) {
+			foreach ($args as $key => $data) {
+				$auth_sig .= $key . $data;
+				$this->req->addPostData($key, $data);
+			}
+			if (!empty($this->secret)) {
+				$api_sig = md5($this->secret . $auth_sig);
+				$this->req->addPostData("api_sig", $api_sig);
+			}
 
-            //Send Requests
-            if ($this->req->sendRequest()) {
-                $this->response = $this->req->getResponseBody();
-                $this->cache($args, $this->response);
-            } else {
-                die("There has been a problem sending your command to the server.");
-            }
-        }
-        /*
-         * Uncomment this line (and comment out the next one) if you're doing large queries
-         * and you're concerned about time.  This will, however, change the structure of
-         * the result, so be sure that you look at the results.
-         */
-        //$this->parsed_response = unserialize($this->response);
-        $this->parsed_response = $this->clean_text_nodes(unserialize($this->response));
-        if ($this->parsed_response['stat'] == 'fail') {
-            if ($this->die_on_error) die("The Flickr API returned the following error: #{$this->parsed_response['code']} - {$this->parsed_response['message']}");
-            else {
-                $this->error_code = $this->parsed_response['code'];
-                $this->error_msg = $this->parsed_response['message'];
-                $this->parsed_response = false;
-            }
-        } else {
-            $this->error_code = false;
-            $this->error_msg = false;
-        }
-        return $this->response;
-    }
+			$this->req->addHeader("Connection", "Keep-Alive");
+			
+			//Send Requests
+			if ($this->req->sendRequest()) {
+				$this->response = $this->req->getResponseBody();
+				$this->cache($args, $this->response);
+			} else {
+				die("There has been a problem sending your command to the server.");
+			}
+		}
+		/*
+		 * Uncomment this line (and comment out the next one) if you're doing large queries
+		 * and you're concerned about time.  This will, however, change the structure of
+		 * the result, so be sure that you look at the results.
+		 */
+		//$this->parsed_response = unserialize($this->response);
+		$this->parsed_response = $this->clean_text_nodes(unserialize($this->response));
+		if ($this->parsed_response['stat'] == 'fail') {
+			if ($this->die_on_error) die("The Flickr API returned the following error: #{$this->parsed_response['code']} - {$this->parsed_response['message']}");
+			else {
+				$this->error_code = $this->parsed_response['code'];
+				$this->error_msg = $this->parsed_response['message'];
+				$this->parsed_response = false;
+			}
+		} else {
+			$this->error_code = false;
+			$this->error_msg = false;
+		}
+		return $this->response;
+	}
 
-    function clean_text_nodes($arr) {
-        if (!is_array($arr)) {
-            return $arr;
-        } elseif (count($arr) == 0) {
-            return $arr;
-        } elseif (count($arr) == 1 && array_key_exists('_content', $arr)) {
-            return $arr['_content'];
-        } else {
-            foreach ($arr as $key => $element) {
-                $arr[$key] = $this->clean_text_nodes($element);
-            }
-            return($arr);
-        }
-    }
+	function clean_text_nodes ($arr) {
+		if (!is_array($arr)) {
+			return $arr;
+		} elseif (count($arr) == 0) {
+			return $arr;
+		} elseif (count($arr) == 1 && array_key_exists('_content', $arr)) {
+			return $arr['_content'];
+		} else {
+			foreach ($arr as $key => $element) {
+				$arr[$key] = $this->clean_text_nodes($element);
+			}
+			return($arr);
+		}
+	}
 
-    function setToken($token)
-    {
-        // Sets an authentication token to use instead of the session variable
-        $this->token = $token;
-    }
+	function setToken ($token) {
+		// Sets an authentication token to use instead of the session variable
+		$this->token = $token;
+	}
 
-    function setProxy($server, $port)
-    {
-        // Sets the proxy for all phpFlickr calls.
-        $this->req->setProxy($server, $port);
-    }
+	function setProxy ($server, $port) {
+		// Sets the proxy for all phpFlickr calls.
+		$this->req->setProxy($server, $port);
+	}
 
-    function getErrorCode()
-    {
+	function getErrorCode () {
 		// Returns the error code of the last call.  If the last call did not
 		// return an error. This will return a false boolean.
 		return $this->error_code;
-    }
+	}
 
-    function getErrorMsg()
-    {
+	function getErrorMsg () {
 		// Returns the error message of the last call.  If the last call did not
 		// return an error. This will return a false boolean.
 		return $this->error_msg;
-    }
+	}
 
-    /* These functions are front ends for the flickr calls */
+	/* These functions are front ends for the flickr calls */
 
-    function buildPhotoURL ($photo, $size = "Medium")
-    {
-        //receives an array (can use the individual photo data returned
-        //from an API call) and returns a URL (doesn't mean that the
-        //file size exists)
-        $sizes = array(
-            "square" => "_s",
-            "thumbnail" => "_t",
-            "small" => "_m",
-            "medium" => "",
-            "large" => "_b",
-            "original" => "_o"
-        );
-        
-        $size = strtolower($size);
-        if (!array_key_exists($size, $sizes)) {
-            $size = "medium";
-        }
-        
-        if ($size == "original") {
-            $url = "http://farm" . $photo['farm'] . ".static.flickr.com/" . $photo['server'] . "/" . $photo['id'] . "_" . $photo['originalsecret'] . "_o" . "." . $photo['originalformat'];
-        } else {
-            $url = "http://farm" . $photo['farm'] . ".static.flickr.com/" . $photo['server'] . "/" . $photo['id'] . "_" . $photo['secret'] . $sizes[$size] . ".jpg";
-        }
-        return $url;
-    }
+	function buildPhotoURL ($photo, $size = "Medium") {
+		//receives an array (can use the individual photo data returned
+		//from an API call) and returns a URL (doesn't mean that the
+		//file size exists)
+		$sizes = array(
+			"square" => "_s",
+			"thumbnail" => "_t",
+			"small" => "_m",
+			"medium" => "",
+			"large" => "_b",
+			"original" => "_o"
+		);
+		
+		$size = strtolower($size);
+		if (!array_key_exists($size, $sizes)) {
+			$size = "medium";
+		}
+		
+		if ($size == "original") {
+			$url = "http://farm" . $photo['farm'] . ".static.flickr.com/" . $photo['server'] . "/" . $photo['id'] . "_" . $photo['originalsecret'] . "_o" . "." . $photo['originalformat'];
+		} else {
+			$url = "http://farm" . $photo['farm'] . ".static.flickr.com/" . $photo['server'] . "/" . $photo['id'] . "_" . $photo['secret'] . $sizes[$size] . ".jpg";
+		}
+		return $url;
+	}
 
-    function getFriendlyGeodata($lat, $lon) {
-        /* I've added this method to get the friendly geodata (i.e. 'in New York, NY') that the
-         * website provides, but isn't available in the API. I'm providing this service as long
-         * as it doesn't flood my server with requests and crash it all the time.
-         */
-        return unserialize(file_get_contents('http://phpflickr.com/geodata/?format=php&lat=' . $lat . '&lon=' . $lon));
-    }
+	function getFriendlyGeodata ($lat, $lon) {
+		/* I've added this method to get the friendly geodata (i.e. 'in New York, NY') that the
+		 * website provides, but isn't available in the API. I'm providing this service as long
+		 * as it doesn't flood my server with requests and crash it all the time.
+		 */
+		return unserialize(file_get_contents('http://phpflickr.com/geodata/?format=php&lat=' . $lat . '&lon=' . $lon));
+	}
 
-    function sync_upload ($photo, $title = null, $description = null, $tags = null, $is_public = null, $is_friend = null, $is_family = null) {
-        $upload_req =& new HTTP_Request();
-        $upload_req->setMethod(HTTP_REQUEST_METHOD_POST);
+	function sync_upload ($photo, $title = null, $description = null, $tags = null, $is_public = null, $is_friend = null, $is_family = null) {
+		$upload_req =& new HTTP_Request();
+		$upload_req->setMethod(HTTP_REQUEST_METHOD_POST);
 
 
-        $upload_req->setURL($this->Upload);
-        $upload_req->clearPostData();
+		$upload_req->setURL($this->Upload);
+		$upload_req->clearPostData();
 
-        //Process arguments, including method and login data.
-        $args = array("api_key" => $this->api_key, "title" => $title, "description" => $description, "tags" => $tags, "is_public" => $is_public, "is_friend" => $is_friend, "is_family" => $is_family);
-        if (!empty($this->email)) {
-            $args = array_merge($args, array("email" => $this->email));
-        }
-        if (!empty($this->password)) {
-            $args = array_merge($args, array("password" => $this->password));
-        }
-        if (!empty($this->token)) {
-            $args = array_merge($args, array("auth_token" => $this->token));
-        } elseif (!empty($_SESSION['phpFlickr_auth_token'])) {
-            $args = array_merge($args, array("auth_token" => $_SESSION['phpFlickr_auth_token']));
-        }
+		//Process arguments, including method and login data.
+		$args = array("api_key" => $this->api_key, "title" => $title, "description" => $description, "tags" => $tags, "is_public" => $is_public, "is_friend" => $is_friend, "is_family" => $is_family);
+		if (!empty($this->email)) {
+			$args = array_merge($args, array("email" => $this->email));
+		}
+		if (!empty($this->password)) {
+			$args = array_merge($args, array("password" => $this->password));
+		}
+		if (!empty($this->token)) {
+			$args = array_merge($args, array("auth_token" => $this->token));
+		} elseif (!empty($_SESSION['phpFlickr_auth_token'])) {
+			$args = array_merge($args, array("auth_token" => $_SESSION['phpFlickr_auth_token']));
+		}
 
-        ksort($args);
-        $auth_sig = "";
-        foreach ($args as $key => $data) {
-            if ($data !== null) {
-                $auth_sig .= $key . $data;
-                $upload_req->addPostData($key, $data);
-            }
-        }
-        if (!empty($this->secret)) {
-            $api_sig = md5($this->secret . $auth_sig);
-            $upload_req->addPostData("api_sig", $api_sig);
-        }
+		ksort($args);
+		$auth_sig = "";
+		foreach ($args as $key => $data) {
+			if ($data !== null) {
+				$auth_sig .= $key . $data;
+				$upload_req->addPostData($key, $data);
+			}
+		}
+		if (!empty($this->secret)) {
+			$api_sig = md5($this->secret . $auth_sig);
+			$upload_req->addPostData("api_sig", $api_sig);
+		}
 
-        $photo = realpath($photo);
+		$photo = realpath($photo);
 
-        $result = $upload_req->addFile("photo", $photo);
+		$result = $upload_req->addFile("photo", $photo);
 
-        if (PEAR::isError($result)) {
-            die($result->getMessage());
-        }
+		if (PEAR::isError($result)) {
+			die($result->getMessage());
+		}
 
-        //Send Requests
-        if ($upload_req->sendRequest()) {
-            $this->response = $upload_req->getResponseBody();
-        } else {
-            die("There has been a problem sending your command to the server.");
-        }
+		//Send Requests
+		if ($upload_req->sendRequest()) {
+			$this->response = $upload_req->getResponseBody();
+		} else {
+			die("There has been a problem sending your command to the server.");
+		}
 
-        $rsp = explode("\n", $this->response);
-        foreach ($rsp as $line) {
-            if (ereg('<err code="([0-9]+)" msg="(.*)"', $line, $match)) {
-                if ($this->die_on_error)
-                    die("The Flickr API returned the following error: #{$match[1]} - {$match[2]}");
-                else {
-                    $this->error_code = $match[1];
-                    $this->error_msg = $match[2];
-                    $this->parsed_response = false;
-                    return false;
-                }
-            } elseif (ereg("<photoid>(.*)</photoid>", $line, $match)) {
-                $this->error_code = false;
-                $this->error_msg = false;
-                return $match[1];
-            }
-        }
-    }
+		$rsp = explode("\n", $this->response);
+		foreach ($rsp as $line) {
+			if (ereg('<err code="([0-9]+)" msg="(.*)"', $line, $match)) {
+				if ($this->die_on_error)
+					die("The Flickr API returned the following error: #{$match[1]} - {$match[2]}");
+				else {
+					$this->error_code = $match[1];
+					$this->error_msg = $match[2];
+					$this->parsed_response = false;
+					return false;
+				}
+			} elseif (ereg("<photoid>(.*)</photoid>", $line, $match)) {
+				$this->error_code = false;
+				$this->error_msg = false;
+				return $match[1];
+			}
+		}
+	}