update Zend and twitter oauth end point V02.17
authorYves-Marie Haussonne <1218002+ymph@users.noreply.github.com>
Thu, 21 Mar 2013 19:52:38 +0100
changeset 808 6b6c2214f778
parent 807 877f952ae2bd
child 809 5b7391b75db2
update Zend and twitter oauth end point
web/lib/Zend/Cache/Backend/WinCache.php
web/lib/Zend/Cloud/Infrastructure/Adapter.php
web/lib/Zend/Cloud/Infrastructure/Adapter/AbstractAdapter.php
web/lib/Zend/Cloud/Infrastructure/Adapter/Ec2.php
web/lib/Zend/Cloud/Infrastructure/Adapter/Rackspace.php
web/lib/Zend/Cloud/Infrastructure/Exception.php
web/lib/Zend/Cloud/Infrastructure/Factory.php
web/lib/Zend/Cloud/Infrastructure/Image.php
web/lib/Zend/Cloud/Infrastructure/ImageList.php
web/lib/Zend/Cloud/Infrastructure/Instance.php
web/lib/Zend/Cloud/Infrastructure/InstanceList.php
web/lib/Zend/Cloud/StorageService/Adapter/Rackspace.php
web/lib/Zend/EventManager/Event.php
web/lib/Zend/EventManager/EventCollection.php
web/lib/Zend/EventManager/EventDescription.php
web/lib/Zend/EventManager/EventManager.php
web/lib/Zend/EventManager/EventManagerAware.php
web/lib/Zend/EventManager/Exception.php
web/lib/Zend/EventManager/Exception/InvalidArgumentException.php
web/lib/Zend/EventManager/Filter.php
web/lib/Zend/EventManager/Filter/FilterIterator.php
web/lib/Zend/EventManager/FilterChain.php
web/lib/Zend/EventManager/GlobalEventManager.php
web/lib/Zend/EventManager/ListenerAggregate.php
web/lib/Zend/EventManager/ResponseCollection.php
web/lib/Zend/EventManager/SharedEventCollection.php
web/lib/Zend/EventManager/SharedEventCollectionAware.php
web/lib/Zend/EventManager/SharedEventManager.php
web/lib/Zend/EventManager/StaticEventManager.php
web/lib/Zend/File/ClassFileLocator.php
web/lib/Zend/Form/Decorator/Captcha/ReCaptcha.php
web/lib/Zend/Form/Element/Note.php
web/lib/Zend/Gdata/Analytics.php
web/lib/Zend/Gdata/Analytics/AccountEntry.php
web/lib/Zend/Gdata/Analytics/AccountFeed.php
web/lib/Zend/Gdata/Analytics/AccountQuery.php
web/lib/Zend/Gdata/Analytics/DataEntry.php
web/lib/Zend/Gdata/Analytics/DataFeed.php
web/lib/Zend/Gdata/Analytics/DataQuery.php
web/lib/Zend/Gdata/Analytics/Extension/Dimension.php
web/lib/Zend/Gdata/Analytics/Extension/Goal.php
web/lib/Zend/Gdata/Analytics/Extension/Metric.php
web/lib/Zend/Gdata/Analytics/Extension/Property.php
web/lib/Zend/Gdata/Analytics/Extension/TableId.php
web/lib/Zend/Http/Header/Exception/InvalidArgumentException.php
web/lib/Zend/Http/Header/Exception/RuntimeException.php
web/lib/Zend/Http/Header/SetCookie.php
web/lib/Zend/Http/UserAgent/Features/Adapter/Browscap.php
web/lib/Zend/Loader/AutoloaderFactory.php
web/lib/Zend/Loader/ClassMapAutoloader.php
web/lib/Zend/Loader/Exception/InvalidArgumentException.php
web/lib/Zend/Loader/SplAutoloader.php
web/lib/Zend/Loader/StandardAutoloader.php
web/lib/Zend/Log/Formatter/Abstract.php
web/lib/Zend/Mobile/Exception.php
web/lib/Zend/Mobile/Push/Abstract.php
web/lib/Zend/Mobile/Push/Apns.php
web/lib/Zend/Mobile/Push/Exception.php
web/lib/Zend/Mobile/Push/Exception/DeviceQuotaExceeded.php
web/lib/Zend/Mobile/Push/Exception/InvalidAuthToken.php
web/lib/Zend/Mobile/Push/Exception/InvalidPayload.php
web/lib/Zend/Mobile/Push/Exception/InvalidRegistration.php
web/lib/Zend/Mobile/Push/Exception/InvalidToken.php
web/lib/Zend/Mobile/Push/Exception/InvalidTopic.php
web/lib/Zend/Mobile/Push/Exception/QuotaExceeded.php
web/lib/Zend/Mobile/Push/Exception/ServerUnavailable.php
web/lib/Zend/Mobile/Push/Gcm.php
web/lib/Zend/Mobile/Push/Interface.php
web/lib/Zend/Mobile/Push/Message/Abstract.php
web/lib/Zend/Mobile/Push/Message/Apns.php
web/lib/Zend/Mobile/Push/Message/Exception.php
web/lib/Zend/Mobile/Push/Message/Gcm.php
web/lib/Zend/Mobile/Push/Message/Interface.php
web/lib/Zend/Mobile/Push/Message/Mpns.php
web/lib/Zend/Mobile/Push/Message/Mpns/Raw.php
web/lib/Zend/Mobile/Push/Message/Mpns/Tile.php
web/lib/Zend/Mobile/Push/Message/Mpns/Toast.php
web/lib/Zend/Mobile/Push/Mpns.php
web/lib/Zend/Mobile/Push/Response/Gcm.php
web/lib/Zend/Mobile/Push/Test/ApnsProxy.php
web/lib/Zend/Search/Lucene/Interface/MultiSearcher.php
web/lib/Zend/Service/Rackspace/Abstract.php
web/lib/Zend/Service/Rackspace/Exception.php
web/lib/Zend/Service/Rackspace/Files.php
web/lib/Zend/Service/Rackspace/Files/Container.php
web/lib/Zend/Service/Rackspace/Files/ContainerList.php
web/lib/Zend/Service/Rackspace/Files/Exception.php
web/lib/Zend/Service/Rackspace/Files/Object.php
web/lib/Zend/Service/Rackspace/Files/ObjectList.php
web/lib/Zend/Service/Rackspace/Servers.php
web/lib/Zend/Service/Rackspace/Servers/Exception.php
web/lib/Zend/Service/Rackspace/Servers/Image.php
web/lib/Zend/Service/Rackspace/Servers/ImageList.php
web/lib/Zend/Service/Rackspace/Servers/Server.php
web/lib/Zend/Service/Rackspace/Servers/ServerList.php
web/lib/Zend/Service/Rackspace/Servers/SharedIpGroup.php
web/lib/Zend/Service/Rackspace/Servers/SharedIpGroupList.php
web/lib/Zend/Service/ShortUrl/BitLy.php
web/lib/Zend/Service/SqlAzure/Exception.php
web/lib/Zend/Service/SqlAzure/Management/Client.php
web/lib/Zend/Service/SqlAzure/Management/Exception.php
web/lib/Zend/Service/SqlAzure/Management/FirewallRuleInstance.php
web/lib/Zend/Service/SqlAzure/Management/ServerInstance.php
web/lib/Zend/Service/SqlAzure/Management/ServiceEntityAbstract.php
web/lib/Zend/Service/Twitter/Response.php
web/lib/Zend/Service/WindowsAzure/CommandLine/Certificate.php
web/lib/Zend/Service/WindowsAzure/CommandLine/Deployment.php
web/lib/Zend/Service/WindowsAzure/CommandLine/GetAsynchronousOperation.php
web/lib/Zend/Service/WindowsAzure/CommandLine/Package.php
web/lib/Zend/Service/WindowsAzure/CommandLine/PackageScaffolder/PackageScaffolderAbstract.php
web/lib/Zend/Service/WindowsAzure/CommandLine/Scaffolders/DefaultScaffolder.phar
web/lib/Zend/Service/WindowsAzure/CommandLine/Scaffolders/DefaultScaffolder/build.bat
web/lib/Zend/Service/WindowsAzure/CommandLine/Scaffolders/DefaultScaffolder/index.php
web/lib/Zend/Service/WindowsAzure/CommandLine/Scaffolders/DefaultScaffolder/resources/PhpOnAzure.Web/Web.config
web/lib/Zend/Service/WindowsAzure/CommandLine/Scaffolders/DefaultScaffolder/resources/PhpOnAzure.Web/bin/add-environment-variables.cmd
web/lib/Zend/Service/WindowsAzure/CommandLine/Scaffolders/DefaultScaffolder/resources/PhpOnAzure.Web/bin/add-environment-variables.ps1
web/lib/Zend/Service/WindowsAzure/CommandLine/Scaffolders/DefaultScaffolder/resources/PhpOnAzure.Web/bin/install-php.cmd
web/lib/Zend/Service/WindowsAzure/CommandLine/Scaffolders/DefaultScaffolder/resources/PhpOnAzure.Web/diagnostics.wadcfg
web/lib/Zend/Service/WindowsAzure/CommandLine/Scaffolders/DefaultScaffolder/resources/PhpOnAzure.Web/resources/WebPICmdLine/Microsoft.Web.Deployment.dll
web/lib/Zend/Service/WindowsAzure/CommandLine/Scaffolders/DefaultScaffolder/resources/PhpOnAzure.Web/resources/WebPICmdLine/Microsoft.Web.PlatformInstaller.UI.dll
web/lib/Zend/Service/WindowsAzure/CommandLine/Scaffolders/DefaultScaffolder/resources/PhpOnAzure.Web/resources/WebPICmdLine/Microsoft.Web.PlatformInstaller.dll
web/lib/Zend/Service/WindowsAzure/CommandLine/Scaffolders/DefaultScaffolder/resources/PhpOnAzure.Web/resources/WebPICmdLine/WebpiCmdLine.exe
web/lib/Zend/Service/WindowsAzure/CommandLine/Scaffolders/DefaultScaffolder/resources/PhpOnAzure.Web/resources/WebPICmdLine/license.rtf
web/lib/Zend/Service/WindowsAzure/CommandLine/Scaffolders/DefaultScaffolder/resources/ServiceConfiguration.cscfg
web/lib/Zend/Service/WindowsAzure/CommandLine/Scaffolders/DefaultScaffolder/resources/ServiceDefinition.csdef
web/lib/Zend/Service/WindowsAzure/CommandLine/Service.php
web/lib/Zend/Service/WindowsAzure/CommandLine/Storage.php
web/lib/Zend/Service/WindowsAzure/Log/Exception.php
web/lib/Zend/Service/WindowsAzure/Log/Formatter/WindowsAzure.php
web/lib/Zend/Service/WindowsAzure/Log/Writer/WindowsAzure.php
web/lib/Zend/Service/WindowsAzure/Management/AffinityGroupInstance.php
web/lib/Zend/Service/WindowsAzure/Management/CertificateInstance.php
web/lib/Zend/Service/WindowsAzure/Management/Client.php
web/lib/Zend/Service/WindowsAzure/Management/DeploymentInstance.php
web/lib/Zend/Service/WindowsAzure/Management/Exception.php
web/lib/Zend/Service/WindowsAzure/Management/HostedServiceInstance.php
web/lib/Zend/Service/WindowsAzure/Management/LocationInstance.php
web/lib/Zend/Service/WindowsAzure/Management/OperatingSystemFamilyInstance.php
web/lib/Zend/Service/WindowsAzure/Management/OperatingSystemInstance.php
web/lib/Zend/Service/WindowsAzure/Management/OperationStatusInstance.php
web/lib/Zend/Service/WindowsAzure/Management/ServiceEntityAbstract.php
web/lib/Zend/Service/WindowsAzure/Management/StorageServiceInstance.php
web/lib/Zend/Service/WindowsAzure/Management/SubscriptionOperationInstance.php
web/lib/Zend/Soap/Server/Proxy.php
web/lib/Zend/Stdlib/CallbackHandler.php
web/lib/Zend/Stdlib/Exception.php
web/lib/Zend/Stdlib/Exception/InvalidCallbackException.php
web/lib/Zend/Stdlib/PriorityQueue.php
web/lib/Zend/Stdlib/SplPriorityQueue.php
web/lib/Zend/Tool/Framework/Manifest/ActionMetadata.php
web/lib/Zend/Tool/Framework/Manifest/Metadata.php
web/lib/Zend/Tool/Framework/Manifest/ProviderMetadata.php
web/lib/Zend/Tool/Project/Context/Zf/ServicesDirectory.php
web/lib/Zend/Tool/Project/Context/Zf/TestApplicationActionMethod.php
web/lib/Zend/Tool/Project/Context/Zf/TestApplicationModuleDirectory.php
web/lib/Zend/Tool/Project/Context/Zf/TestApplicationModulesDirectory.php
web/lib/Zend/Tool/Project/Context/Zf/TestPHPUnitBootstrapFile.php
web/lib/Zend/Validate/Ldap/Dn.php
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Cache/Backend/WinCache.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,349 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Cache
+ * @subpackage Zend_Cache_Backend
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+
+/**
+ * @see Zend_Cache_Backend_Interface
+ */
+require_once 'Zend/Cache/Backend/ExtendedInterface.php';
+
+/**
+ * @see Zend_Cache_Backend
+ */
+require_once 'Zend/Cache/Backend.php';
+
+
+/**
+ * @package    Zend_Cache
+ * @subpackage Zend_Cache_Backend
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Cache_Backend_WinCache extends Zend_Cache_Backend implements Zend_Cache_Backend_ExtendedInterface
+{
+    /**
+     * Log message
+     */
+    const TAGS_UNSUPPORTED_BY_CLEAN_OF_WINCACHE_BACKEND = 'Zend_Cache_Backend_WinCache::clean() : tags are unsupported by the WinCache backend';
+    const TAGS_UNSUPPORTED_BY_SAVE_OF_WINCACHE_BACKEND =  'Zend_Cache_Backend_WinCache::save() : tags are unsupported by the WinCache backend';
+
+    /**
+     * Constructor
+     *
+     * @param  array $options associative array of options
+     * @throws Zend_Cache_Exception
+     * @return void
+     */
+    public function __construct(array $options = array())
+    {
+        if (!extension_loaded('wincache')) {
+            Zend_Cache::throwException('The wincache extension must be loaded for using this backend !');
+        }
+        parent::__construct($options);
+    }
+
+    /**
+     * Test if a cache is available for the given id and (if yes) return it (false else)
+     *
+     * WARNING $doNotTestCacheValidity=true is unsupported by the WinCache backend
+     *
+     * @param  string  $id                     cache id
+     * @param  boolean $doNotTestCacheValidity if set to true, the cache validity won't be tested
+     * @return string cached datas (or false)
+     */
+    public function load($id, $doNotTestCacheValidity = false)
+    {
+        $tmp = wincache_ucache_get($id);
+        if (is_array($tmp)) {
+            return $tmp[0];
+        }
+        return false;
+    }
+
+    /**
+     * Test if a cache is available or not (for the given id)
+     *
+     * @param  string $id cache id
+     * @return mixed false (a cache is not available) or "last modified" timestamp (int) of the available cache record
+     */
+    public function test($id)
+    {
+        $tmp = wincache_ucache_get($id);
+        if (is_array($tmp)) {
+            return $tmp[1];
+        }
+        return false;
+    }
+
+    /**
+     * Save some string datas into a cache record
+     *
+     * Note : $data is always "string" (serialization is done by the
+     * core not by the backend)
+     *
+     * @param string $data datas to cache
+     * @param string $id cache id
+     * @param array $tags array of strings, the cache record will be tagged by each string entry
+     * @param int $specificLifetime if != false, set a specific lifetime for this cache record (null => infinite lifetime)
+     * @return boolean true if no problem
+     */
+    public function save($data, $id, $tags = array(), $specificLifetime = false)
+    {
+        $lifetime = $this->getLifetime($specificLifetime);
+        $result = wincache_ucache_set($id, array($data, time(), $lifetime), $lifetime);
+        if (count($tags) > 0) {
+            $this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_WINCACHE_BACKEND);
+        }
+        return $result;
+    }
+
+    /**
+     * Remove a cache record
+     *
+     * @param  string $id cache id
+     * @return boolean true if no problem
+     */
+    public function remove($id)
+    {
+        return wincache_ucache_delete($id);
+    }
+
+    /**
+     * Clean some cache records
+     *
+     * Available modes are :
+     * 'all' (default)  => remove all cache entries ($tags is not used)
+     * 'old'            => unsupported
+     * 'matchingTag'    => unsupported
+     * 'notMatchingTag' => unsupported
+     * 'matchingAnyTag' => unsupported
+     *
+     * @param  string $mode clean mode
+     * @param  array  $tags array of tags
+     * @throws Zend_Cache_Exception
+     * @return boolean true if no problem
+     */
+    public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array())
+    {
+        switch ($mode) {
+            case Zend_Cache::CLEANING_MODE_ALL:
+                return wincache_ucache_clear();
+                break;
+            case Zend_Cache::CLEANING_MODE_OLD:
+                $this->_log("Zend_Cache_Backend_WinCache::clean() : CLEANING_MODE_OLD is unsupported by the WinCache backend");
+                break;
+            case Zend_Cache::CLEANING_MODE_MATCHING_TAG:
+            case Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG:
+            case Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG:
+                $this->_log(self::TAGS_UNSUPPORTED_BY_CLEAN_OF_WINCACHE_BACKEND);
+                break;
+            default:
+                Zend_Cache::throwException('Invalid mode for clean() method');
+                break;
+        }
+    }
+
+    /**
+     * Return true if the automatic cleaning is available for the backend
+     *
+     * DEPRECATED : use getCapabilities() instead
+     *
+     * @deprecated
+     * @return boolean
+     */
+    public function isAutomaticCleaningAvailable()
+    {
+        return false;
+    }
+
+    /**
+     * Return the filling percentage of the backend storage
+     *
+     * @throws Zend_Cache_Exception
+     * @return int integer between 0 and 100
+     */
+    public function getFillingPercentage()
+    {
+        $mem = wincache_ucache_meminfo();
+        $memSize = $mem['memory_total'];
+        $memUsed = $memSize - $mem['memory_free'];
+        if ($memSize == 0) {
+            Zend_Cache::throwException('can\'t get WinCache memory size');
+        }
+        if ($memUsed > $memSize) {
+            return 100;
+        }
+        return ((int) (100. * ($memUsed / $memSize)));
+    }
+
+    /**
+     * Return an array of stored tags
+     *
+     * @return array array of stored tags (string)
+     */
+    public function getTags()
+    {
+        $this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_WINCACHE_BACKEND);
+        return array();
+    }
+
+    /**
+     * Return an array of stored cache ids which match given tags
+     *
+     * In case of multiple tags, a logical AND is made between tags
+     *
+     * @param array $tags array of tags
+     * @return array array of matching cache ids (string)
+     */
+    public function getIdsMatchingTags($tags = array())
+    {
+        $this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_WINCACHE_BACKEND);
+        return array();
+    }
+
+    /**
+     * Return an array of stored cache ids which don't match given tags
+     *
+     * In case of multiple tags, a logical OR is made between tags
+     *
+     * @param array $tags array of tags
+     * @return array array of not matching cache ids (string)
+     */
+    public function getIdsNotMatchingTags($tags = array())
+    {
+        $this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_WINCACHE_BACKEND);
+        return array();
+    }
+
+    /**
+     * Return an array of stored cache ids which match any given tags
+     *
+     * In case of multiple tags, a logical AND is made between tags
+     *
+     * @param array $tags array of tags
+     * @return array array of any matching cache ids (string)
+     */
+    public function getIdsMatchingAnyTags($tags = array())
+    {
+        $this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_WINCACHE_BACKEND);
+        return array();
+    }
+
+    /**
+     * Return an array of stored cache ids
+     *
+     * @return array array of stored cache ids (string)
+     */
+    public function getIds()
+    {
+        $res = array();
+        $array = wincache_ucache_info();
+        $records = $array['ucache_entries'];
+        foreach ($records as $record) {
+            $res[] = $record['key_name'];
+        }
+        return $res;
+    }
+
+    /**
+     * Return an array of metadatas for the given cache id
+     *
+     * The array must include these keys :
+     * - expire : the expire timestamp
+     * - tags : a string array of tags
+     * - mtime : timestamp of last modification time
+     *
+     * @param string $id cache id
+     * @return array array of metadatas (false if the cache id is not found)
+     */
+    public function getMetadatas($id)
+    {
+        $tmp = wincache_ucache_get($id);
+        if (is_array($tmp)) {
+            $data = $tmp[0];
+            $mtime = $tmp[1];
+            if (!isset($tmp[2])) {
+                return false;
+            }
+            $lifetime = $tmp[2];
+            return array(
+                'expire' => $mtime + $lifetime,
+                'tags' => array(),
+                'mtime' => $mtime
+            );
+        }
+        return false;
+    }
+
+    /**
+     * Give (if possible) an extra lifetime to the given cache id
+     *
+     * @param string $id cache id
+     * @param int $extraLifetime
+     * @return boolean true if ok
+     */
+    public function touch($id, $extraLifetime)
+    {
+        $tmp = wincache_ucache_get($id);
+        if (is_array($tmp)) {
+            $data = $tmp[0];
+            $mtime = $tmp[1];
+            if (!isset($tmp[2])) {
+                return false;
+            }
+            $lifetime = $tmp[2];
+            $newLifetime = $lifetime - (time() - $mtime) + $extraLifetime;
+            if ($newLifetime <=0) {
+                return false;
+            }
+            return wincache_ucache_set($id, array($data, time(), $newLifetime), $newLifetime);
+        }
+        return false;
+    }
+
+    /**
+     * Return an associative array of capabilities (booleans) of the backend
+     *
+     * The array must include these keys :
+     * - automatic_cleaning (is automating cleaning necessary)
+     * - tags (are tags supported)
+     * - expired_read (is it possible to read expired cache records
+     *                 (for doNotTestCacheValidity option for example))
+     * - priority does the backend deal with priority when saving
+     * - infinite_lifetime (is infinite lifetime can work with this backend)
+     * - get_list (is it possible to get the list of cache ids and the complete list of tags)
+     *
+     * @return array associative of with capabilities
+     */
+    public function getCapabilities()
+    {
+        return array(
+            'automatic_cleaning' => false,
+            'tags' => false,
+            'expired_read' => false,
+            'priority' => false,
+            'infinite_lifetime' => false,
+            'get_list' => true
+        );
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Cloud/Infrastructure/Adapter.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,167 @@
+<?php
+/**
+ * @category   Zend
+ * @package    Zend_Cloud
+ * @subpackage Infrastructure
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+/**
+ * Adapter interface for infrastructure service
+ * 
+ * @package    Zend_Cloud
+ * @subpackage Infrastructure
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+interface Zend_Cloud_Infrastructure_Adapter 
+{ 
+    const HTTP_ADAPTER = 'http_adapter'; 
+
+    /**
+     * The max. amount of time, in seconds, to wait for a status change
+     */
+    const TIMEOUT_STATUS_CHANGE = 30;
+
+    /**
+     * The time step, in seconds, for the status change
+     */
+    const TIME_STEP_STATUS_CHANGE = 5;
+
+    /**
+     * Return a list of the available instances
+     *
+     * @return InstanceList
+     */ 
+    public function listInstances(); 
+ 
+    /**
+     * Return the status of an instance
+     *
+     * @param  string $id
+     * @return string
+     */ 
+    public function statusInstance($id); 
+
+    /**
+     * Wait for status $status with a timeout of $timeout seconds
+     * 
+     * @param  string $id
+     * @param  string $status
+     * @param  integer $timeout 
+     * @return boolean
+     */
+    public function waitStatusInstance($id, $status, $timeout = self::TIMEOUT_STATUS_CHANGE);
+    
+    /**
+     * Return the public DNS name of the instance
+     * 
+     * @param  string $id
+     * @return string|boolean 
+     */
+    public function publicDnsInstance($id);
+    
+    /**
+     * Reboot an instance
+     *
+     * @param string $id
+     * @return boolean
+     */ 
+    public function rebootInstance($id); 
+ 
+    /**
+     * Create a new instance
+     *
+     * @param  string $name
+     * @param  array $options
+     * @return boolean
+     */ 
+    public function createInstance($name, $options); 
+ 
+    /**
+     * Stop the execution of an instance
+     *
+     * @param  string $id
+     * @return boolean
+     */ 
+    public function stopInstance($id); 
+ 
+    /**
+     * Start the execution of an instance
+     *
+     * @param  string $id
+     * @return boolean
+     */ 
+    public function startInstance($id); 
+ 
+    /**
+     * Destroy an instance
+     *
+     * @param  string $id
+     * @return boolean
+     */ 
+    public function destroyInstance($id); 
+ 
+    /**
+     * Return all the available instances images
+     *
+     * @return ImageList
+     */ 
+    public function imagesInstance(); 
+    
+    /**
+     * Return all the available zones
+     * 
+     * @return array
+     */
+    public function zonesInstance();
+    
+    /**
+     * Return the system informations about the $metric of an instance
+     *
+     * @param  string $id
+     * @param  string $metric
+     * @param  array $options
+     * @return array
+     */ 
+    public function monitorInstance($id, $metric, $options = null); 
+ 
+    /**
+     * Run arbitrary shell script on an instance
+     *
+     * @param  string $id
+     * @param  array $param
+     * @param  string|array $cmd
+     * @return string|array
+     */ 
+    public function deployInstance($id, $param, $cmd);
+            
+    /**
+     * Get the adapter instance
+     * 
+     * @return object
+     */
+    public function getAdapter();
+    
+    /**
+     * Get the adapter result
+     * 
+     * @return array
+     */
+    public function getAdapterResult();
+    
+    /**
+     * Get the last HTTP response
+     * 
+     * @return Zend_Http_Response
+     */
+    public function getLastHttpResponse();
+    
+    /**
+     * Get the last HTTP request
+     * 
+     * @return string
+     */
+    public function getLastHttpRequest();
+} 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Cloud/Infrastructure/Adapter/AbstractAdapter.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,175 @@
+<?php
+/**
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Cloud
+ * @subpackage DocumentService
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+require_once 'Zend/Cloud/Infrastructure/Adapter.php';
+require_once 'Zend/Cloud/Infrastructure/Instance.php';
+
+/**
+ * Abstract infrastructure service adapter
+ *
+ * @category   Zend
+ * @package    Zend_Cloud_Infrastructure
+ * @subpackage Adapter
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+abstract class Zend_Cloud_Infrastructure_Adapter_AbstractAdapter implements Zend_Cloud_Infrastructure_Adapter
+{
+    /**
+     * Store the last response from the adpter
+     * 
+     * @var array
+     */
+    protected $adapterResult;
+    
+    /**
+     * Valid metrics for monitor
+     * 
+     * @var array
+     */
+    protected $validMetrics = array(
+        Zend_Cloud_Infrastructure_Instance::MONITOR_CPU,
+        Zend_Cloud_Infrastructure_Instance::MONITOR_RAM,
+        Zend_Cloud_Infrastructure_Instance::MONITOR_DISK,
+        Zend_Cloud_Infrastructure_Instance::MONITOR_DISK_READ,
+        Zend_Cloud_Infrastructure_Instance::MONITOR_DISK_WRITE,
+        Zend_Cloud_Infrastructure_Instance::MONITOR_NETWORK_IN,
+        Zend_Cloud_Infrastructure_Instance::MONITOR_NETWORK_OUT,
+    );
+
+    /**
+     * Get the last result of the adapter
+     *
+     * @return array
+     */
+    public function getAdapterResult()
+    {
+        return $this->adapterResult;
+    }
+
+    /**
+     * Wait for status $status with a timeout of $timeout seconds
+     * 
+     * @param  string $id
+     * @param  string $status
+     * @param  integer $timeout 
+     * @return boolean
+     */
+    public function waitStatusInstance($id, $status, $timeout = self::TIMEOUT_STATUS_CHANGE)
+    {
+        if (empty($id) || empty($status)) {
+            return false;
+        }
+
+        $num = 0;
+        while (($num<$timeout) && ($this->statusInstance($id) != $status)) {
+            sleep(self::TIME_STEP_STATUS_CHANGE);
+            $num += self::TIME_STEP_STATUS_CHANGE;
+        }
+        return ($num < $timeout);
+    }
+
+    /**
+     * Run arbitrary shell script on an instance
+     *
+     * @param  string $id
+     * @param  array $param
+     * @param  string|array $cmd
+     * @return string|array
+     */ 
+    public function deployInstance($id, $params, $cmd)
+    {
+        if (!function_exists("ssh2_connect")) {
+            require_once 'Zend/Cloud/Infrastructure/Exception.php';
+            throw new Zend_Cloud_Infrastructure_Exception('Deployment requires the PHP "SSH" extension (ext/ssh2)');
+        }
+
+        if (empty($id)) {
+            require_once 'Zend/Cloud/Infrastructure/Exception.php';
+            throw new Zend_Cloud_Infrastructure_Exception('You must specify the instance where to deploy');
+        }
+
+        if (empty($cmd)) {
+            require_once 'Zend/Cloud/Infrastructure/Exception.php';
+            throw new Zend_Cloud_Infrastructure_Exception('You must specify the shell commands to run on the instance');
+        }
+
+        if (empty($params) 
+            || empty($params[Zend_Cloud_Infrastructure_Instance::SSH_USERNAME]) 
+            || (empty($params[Zend_Cloud_Infrastructure_Instance::SSH_PASSWORD]) 
+                && empty($params[Zend_Cloud_Infrastructure_Instance::SSH_KEY]))
+        ) {
+            require_once 'Zend/Cloud/Infrastructure/Exception.php';
+            throw new Zend_Cloud_Infrastructure_Exception('You must specify the params for the SSH connection');
+        }
+
+        $host = $this->publicDnsInstance($id);
+        if (empty($host)) {
+            require_once 'Zend/Cloud/Infrastructure/Exception.php';
+            throw new Zend_Cloud_Infrastructure_Exception(sprintf(
+                'The instance identified by "%s" does not exist', 
+                $id
+            ));
+        }
+
+        $conn = ssh2_connect($host);
+        if (!ssh2_auth_password($conn, $params[Zend_Cloud_Infrastructure_Instance::SSH_USERNAME], 
+                $params[Zend_Cloud_Infrastructure_Instance::SSH_PASSWORD])) {
+            require_once 'Zend/Cloud/Infrastructure/Exception.php';
+            throw new Zend_Cloud_Infrastructure_Exception('SSH authentication failed');
+        }
+
+        if (is_array($cmd)) {
+            $result = array();
+            foreach ($cmd as $command) {
+                $stream      = ssh2_exec($conn, $command);
+                $errorStream = ssh2_fetch_stream($stream, SSH2_STREAM_STDERR);
+
+                stream_set_blocking($errorStream, true);
+                stream_set_blocking($stream, true); 
+
+                $output = stream_get_contents($stream);
+                $error  = stream_get_contents($errorStream);
+                
+                if (empty($error)) {
+                    $result[$command] = $output;
+                } else {
+                    $result[$command] = $error;
+                }
+            }
+        } else {
+            $stream      = ssh2_exec($conn, $cmd);
+            $result      = stream_set_blocking($stream, true);
+            $errorStream = ssh2_fetch_stream($stream, SSH2_STREAM_STDERR);
+
+            stream_set_blocking($errorStream, true);
+            stream_set_blocking($stream, true); 
+
+            $output = stream_get_contents($stream);
+            $error  = stream_get_contents($errorStream);
+            
+            if (empty($error)) {
+                $result = $output;
+            } else {
+                $result = $error;
+            }
+        }    
+        return $result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Cloud/Infrastructure/Adapter/Ec2.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,496 @@
+<?php
+/**
+ * @category   Zend
+ * @package    Zend_Cloud_Infrastructure
+ * @subpackage Adapter
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+require_once 'Zend/Service/Amazon/Ec2/Instance.php';
+require_once 'Zend/Service/Amazon/Ec2/Image.php';
+require_once 'Zend/Service/Amazon/Ec2/Availabilityzones.php';
+require_once 'Zend/Service/Amazon/Ec2/CloudWatch.php';
+require_once 'Zend/Cloud/Infrastructure/Instance.php';
+require_once 'Zend/Cloud/Infrastructure/InstanceList.php';
+require_once 'Zend/Cloud/Infrastructure/Image.php';
+require_once 'Zend/Cloud/Infrastructure/ImageList.php';
+require_once 'Zend/Cloud/Infrastructure/Adapter/AbstractAdapter.php';
+
+/**
+ * Amazon EC2 adapter for infrastructure service
+ *
+ * @package    Zend_Cloud_Infrastructure
+ * @subpackage Adapter
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Cloud_Infrastructure_Adapter_Ec2 extends Zend_Cloud_Infrastructure_Adapter_AbstractAdapter
+{
+    /**
+     * AWS constants
+     */
+    const AWS_ACCESS_KEY     = 'aws_accesskey';
+    const AWS_SECRET_KEY     = 'aws_secretkey';
+    const AWS_REGION         = 'aws_region';
+    const AWS_SECURITY_GROUP = 'securityGroup';
+
+    /**
+     * Ec2 Instance 
+     * 
+     * @var Ec2Instance
+     */
+    protected $ec2;
+
+    /**
+     * Ec2 Image
+     * 
+     * @var Ec2Image
+     */
+    protected $ec2Image;
+
+    /**
+     * Ec2 Zone
+     * 
+     * @var Ec2Zone
+     */
+    protected $ec2Zone;
+
+    /**
+     * Ec2 Monitor 
+     * 
+     * @var Ec2Monitor
+     */
+    protected $ec2Monitor;
+
+    /**
+     * AWS Access Key
+     * 
+     * @var string 
+     */
+    protected $accessKey;
+
+    /**
+     * AWS Access Secret
+     * 
+     * @var string 
+     */
+    protected $accessSecret;
+
+    /**
+     * Region zone 
+     * 
+     * @var string 
+     */
+    protected $region;
+
+    /**
+     * Map array between EC2 and Infrastructure status
+     * 
+     * @var array 
+     */
+    protected $mapStatus = array (
+        'running'       => Zend_Cloud_Infrastructure_Instance::STATUS_RUNNING,
+        'terminated'    => Zend_Cloud_Infrastructure_Instance::STATUS_TERMINATED,
+        'pending'       => Zend_Cloud_Infrastructure_Instance::STATUS_PENDING,
+        'shutting-down' => Zend_Cloud_Infrastructure_Instance::STATUS_SHUTTING_DOWN,
+        'stopping'      => Zend_Cloud_Infrastructure_Instance::STATUS_PENDING,
+        'stopped'       => Zend_Cloud_Infrastructure_Instance::STATUS_STOPPED,
+        'rebooting'     => Zend_Cloud_Infrastructure_Instance::STATUS_REBOOTING,
+    );
+
+    /**
+     * Map monitor metrics between Infrastructure and EC2
+     * 
+     * @var array 
+     */
+    protected $mapMetrics= array (
+        Zend_Cloud_Infrastructure_Instance::MONITOR_CPU         => 'CPUUtilization',
+        Zend_Cloud_Infrastructure_Instance::MONITOR_DISK_READ   => 'DiskReadBytes',
+        Zend_Cloud_Infrastructure_Instance::MONITOR_DISK_WRITE  => 'DiskWriteBytes',
+        Zend_Cloud_Infrastructure_Instance::MONITOR_NETWORK_IN  => 'NetworkIn',
+        Zend_Cloud_Infrastructure_Instance::MONITOR_NETWORK_OUT => 'NetworkOut',
+    );
+
+    /**
+     * Constructor
+     *
+     * @param  array|Zend_Config $options
+     * @return void
+     */
+    public function __construct($options = array())
+    {
+        if (is_object($options)) {
+            if (method_exists($options, 'toArray')) {
+                $options= $options->toArray();
+            } elseif ($options instanceof Traversable) {
+                $options = iterator_to_array($options);
+            }
+        }
+        
+        if (empty($options) || !is_array($options)) {
+            require_once 'Zend/Cloud/Infrastructure/Exception.php';
+            throw new Zend_Cloud_Infrastructure_Exception('Invalid options provided');
+        }
+        
+        if (!isset($options[self::AWS_ACCESS_KEY]) 
+            || !isset($options[self::AWS_SECRET_KEY])
+        ) {
+            require_once 'Zend/Cloud/Infrastructure/Exception.php';
+            throw new Zend_Cloud_Infrastructure_Exception('AWS keys not specified!');
+        }
+
+        $this->accessKey    = $options[self::AWS_ACCESS_KEY];
+        $this->accessSecret = $options[self::AWS_SECRET_KEY];
+        $this->region       = '';
+
+        if (isset($options[self::AWS_REGION])) {
+            $this->region= $options[self::AWS_REGION];
+        }
+
+        try {
+            $this->ec2 = new Zend_Service_Amazon_Ec2_Instance($options[self::AWS_ACCESS_KEY], $options[self::AWS_SECRET_KEY], $this->region);
+        } catch (Exception  $e) {
+            require_once 'Zend/Cloud/Infrastructure/Exception.php';
+            throw new Zend_Cloud_Infrastructure_Exception('Error on create: ' . $e->getMessage(), $e->getCode(), $e);
+        }
+
+        if (isset($options[self::HTTP_ADAPTER])) {
+            $this->ec2->getHttpClient()->setAdapter($options[self::HTTP_ADAPTER]);
+        }
+    }
+
+    /**
+     * Convert the attributes of EC2 into attributes of Infrastructure
+     * 
+     * @param  array $attr
+     * @return array|boolean 
+     */
+    private function convertAttributes($attr)
+    {
+        $result = array();       
+        if (!empty($attr) && is_array($attr)) {
+            $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_ID]         = $attr['instanceId'];
+            $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_STATUS]     = $this->mapStatus[$attr['instanceState']['name']];
+            $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_IMAGEID]    = $attr['imageId'];
+            $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_ZONE]       = $attr['availabilityZone'];
+            $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_LAUNCHTIME] = $attr['launchTime'];
+
+            switch ($attr['instanceType']) {
+                case Zend_Service_Amazon_Ec2_Instance::MICRO:
+                    $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_CPU]     = '1 virtual core';
+                    $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_RAM]     = '613MB';
+                    $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_STORAGE] = '0GB';
+                    break;
+                case Zend_Service_Amazon_Ec2_Instance::SMALL:
+                    $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_CPU]     = '1 virtual core';
+                    $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_RAM]     = '1.7GB';
+                    $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_STORAGE] = '160GB';
+                    break;
+                case Zend_Service_Amazon_Ec2_Instance::LARGE:
+                    $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_CPU]     = '2 virtual core';
+                    $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_RAM]     = '7.5GB';
+                    $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_STORAGE] = '850GB';
+                    break;
+                case Zend_Service_Amazon_Ec2_Instance::XLARGE:
+                    $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_CPU]     = '4 virtual core';
+                    $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_RAM]     = '15GB';
+                    $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_STORAGE] = '1690GB';
+                    break;
+                case Zend_Service_Amazon_Ec2_Instance::HCPU_MEDIUM:
+                    $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_CPU]     = '2 virtual core';
+                    $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_RAM]     = '1.7GB';
+                    $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_STORAGE] = '350GB';
+                    break;
+                case Zend_Service_Amazon_Ec2_Instance::HCPU_XLARGE:
+                    $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_CPU]     = '8 virtual core';
+                    $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_RAM]     = '7GB';
+                    $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_STORAGE] = '1690GB';
+                    break;
+            }
+        }
+        return $result;
+    }
+
+    /**
+     * Return a list of the available instancies
+     *
+     * @return Zend_Cloud_Infrastructure_InstanceList
+     */ 
+    public function listInstances() 
+    {
+        $this->adapterResult = $this->ec2->describe();
+
+        $result = array();
+        foreach ($this->adapterResult['instances'] as $instance) {
+            $result[]= $this->convertAttributes($instance);
+        }
+        return new Zend_Cloud_Infrastructure_InstanceList($this, $result);
+    }
+
+    /**
+     * Return the status of an instance
+     *
+     * @param  string
+     * @return string|boolean
+     */ 
+    public function statusInstance($id)
+    {
+        $this->adapterResult = $this->ec2->describe($id);
+        if (empty($this->adapterResult['instances'])) {
+            return false;
+        }    
+        $result = $this->adapterResult['instances'][0];
+        return $this->mapStatus[$result['instanceState']['name']];
+    }
+
+    /**
+     * Return the public DNS name of the instance
+     * 
+     * @param  string $id
+     * @return string|boolean 
+     */
+    public function publicDnsInstance($id) 
+    {
+        $this->adapterResult = $this->ec2->describe($id);
+        if (empty($this->adapterResult['instances'])) {
+            return false;
+        }    
+        $result = $this->adapterResult['instances'][0];
+        return $result['dnsName'];
+    }
+
+    /**
+     * Reboot an instance
+     *
+     * @param string $id
+     * @return boolean
+     */ 
+    public function rebootInstance($id)
+    {
+        $this->adapterResult= $this->ec2->reboot($id);
+        return $this->adapterResult;
+    }
+
+    /**
+     * Create a new instance
+     *
+     * @param string $name
+     * @param array $options
+     * @return Instance|boolean
+     */ 
+    public function createInstance($name, $options)
+    {
+        // @todo instance's name management?
+        $this->adapterResult = $this->ec2->run($options);
+        if (empty($this->adapterResult['instances'])) {
+            return false;
+        }
+        $this->error= false;
+        return new Zend_Cloud_Infrastructure_Instance($this, $this->convertAttributes($this->adapterResult['instances'][0]));
+    }
+
+    /**
+     * Stop an instance
+     *
+     * @param  string $id
+     * @return boolean
+     */ 
+    public function stopInstance($id)
+    {
+        require_once 'Zend/Cloud/Infrastructure/Exception.php';
+        throw new Zend_Cloud_Infrastructure_Exception('The stopInstance method is not implemented in the adapter');
+    }
+ 
+    /**
+     * Start an instance
+     *
+     * @param  string $id
+     * @return boolean
+     */ 
+    public function startInstance($id)
+    {
+        require_once 'Zend/Cloud/Infrastructure/Exception.php';
+        throw new Zend_Cloud_Infrastructure_Exception('The startInstance method is not implemented in the adapter');
+    }
+ 
+    /**
+     * Destroy an instance
+     *
+     * @param  string $id
+     * @return boolean
+     */ 
+    public function destroyInstance($id)
+    {
+        $this->adapterResult = $this->ec2->terminate($id);
+        return (!empty($this->adapterResult));
+    }
+ 
+    /**
+     * Return a list of all the available instance images
+     *
+     * @return ImageList
+     */ 
+    public function imagesInstance()
+    {
+        if (!isset($this->ec2Image)) {
+            $this->ec2Image = new Zend_Service_Amazon_Ec2_Image($this->accessKey, $this->accessSecret, $this->region);
+        }
+
+        $this->adapterResult = $this->ec2Image->describe();
+                
+        $images = array();
+
+        foreach ($this->adapterResult as $result) {
+            switch (strtolower($result['platform'])) {
+                case 'windows' :
+                    $platform = Zend_Cloud_Infrastructure_Image::IMAGE_WINDOWS;
+                    break;
+                default:
+                    $platform = Zend_Cloud_Infrastructure_Image::IMAGE_LINUX;
+                    break;
+            }
+
+            $images[]= array (
+                Zend_Cloud_Infrastructure_Image::IMAGE_ID           => $result['imageId'],
+                Zend_Cloud_Infrastructure_Image::IMAGE_NAME         => '',
+                Zend_Cloud_Infrastructure_Image::IMAGE_DESCRIPTION  => $result['imageLocation'],
+                Zend_Cloud_Infrastructure_Image::IMAGE_OWNERID      => $result['imageOwnerId'],
+                Zend_Cloud_Infrastructure_Image::IMAGE_ARCHITECTURE => $result['architecture'],
+                Zend_Cloud_Infrastructure_Image::IMAGE_PLATFORM     => $platform,
+            );
+        }
+        return new Zend_Cloud_Infrastructure_ImageList($images,$this->ec2Image);
+    }
+
+    /**
+     * Return all the available zones
+     * 
+     * @return array
+     */
+    public function zonesInstance()
+    {
+        if (!isset($this->ec2Zone)) {
+            $this->ec2Zone = new Zend_Service_Amazon_Ec2_AvailabilityZones($this->accessKey,$this->accessSecret,$this->region);
+        }
+        $this->adapterResult = $this->ec2Zone->describe();
+
+        $zones = array();
+        foreach ($this->adapterResult as $zone) {
+            if (strtolower($zone['zoneState']) === 'available') {
+                $zones[] = array (
+                    Zend_Cloud_Infrastructure_Instance::INSTANCE_ZONE => $zone['zoneName'],
+                );
+            }
+        }
+        return $zones;
+    }
+
+    /**
+     * Return the system information about the $metric of an instance
+     * 
+     * @param  string $id
+     * @param  string $metric
+     * @param  null|array $options
+     * @return array
+     */ 
+    public function monitorInstance($id, $metric, $options = null)
+    {
+        if (empty($id) || empty($metric)) {
+            return false;
+        }
+
+        if (!in_array($metric,$this->validMetrics)) {
+            require_once 'Zend/Cloud/Infrastructure/Exception.php';
+            throw new Zend_Cloud_Infrastructure_Exception(sprintf(
+                'The metric "%s" is not valid', 
+                $metric
+            ));
+        }
+
+        if (!empty($options) && !is_array($options)) {
+            require_once 'Zend/Cloud/Infrastructure/Exception.php';
+            throw new Zend_Cloud_Infrastructure_Exception('The options must be an array');
+        }
+
+        if (!empty($options) 
+            && (empty($options[Zend_Cloud_Infrastructure_Instance::MONITOR_START_TIME]) 
+                || empty($options[Zend_Cloud_Infrastructure_Instance::MONITOR_END_TIME]))
+        ) {
+            require_once 'Zend/Cloud/Infrastructure/Exception.php';
+            throw new Zend_Cloud_Infrastructure_Exception(sprintf(
+                'The options array must contain: "%s" and "%s"',
+                $options[Zend_Cloud_Infrastructure_Instance::MONITOR_START_TIME],
+                $options[Zend_Cloud_Infrastructure_Instance::MONITOR_END_TIME]
+            ));
+        }      
+
+        if (!isset($this->ec2Monitor)) {
+            $this->ec2Monitor = new Zend_Service_Amazon_Ec2_CloudWatch($this->accessKey, $this->accessSecret, $this->region);
+        }
+
+        $param = array(
+            'MeasureName' => $this->mapMetrics[$metric],
+            'Statistics'  => array('Average'),
+            'Dimensions'  => array('InstanceId' => $id),
+        );
+
+        if (!empty($options)) {
+            $param['StartTime'] = $options[Zend_Cloud_Infrastructure_Instance::MONITOR_START_TIME];
+            $param['EndTime']   = $options[Zend_Cloud_Infrastructure_Instance::MONITOR_END_TIME];
+        }
+
+        $this->adapterResult = $this->ec2Monitor->getMetricStatistics($param);
+
+        $monitor             = array();
+        $num                 = 0;
+        $average             = 0;
+
+        if (!empty($this->adapterResult['datapoints'])) {
+            foreach ($this->adapterResult['datapoints'] as $result) {
+                $monitor['series'][] = array (
+                    'timestamp' => $result['Timestamp'],
+                    'value'     => $result['Average'],
+                );
+                $average += $result['Average'];
+                $num++;
+            }
+        }
+
+        if ($num > 0) {
+            $monitor['average'] = $average / $num;
+        }
+
+        return $monitor;
+    }
+
+    /**
+     * Get the adapter 
+     * 
+     * @return Zend_Service_Amazon_Ec2_Instance
+     */
+    public function getAdapter()
+    {
+        return $this->ec2;
+    }
+
+    /**
+     * Get last HTTP request
+     * 
+     * @return string 
+     */
+    public function getLastHttpRequest()
+    {
+        return $this->ec2->getHttpClient()->getLastRequest();
+    }
+
+    /**
+     * Get the last HTTP response
+     * 
+     * @return Zend_Http_Response 
+     */
+    public function getLastHttpResponse()
+    {
+        return $this->ec2->getHttpClient()->getLastResponse();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Cloud/Infrastructure/Adapter/Rackspace.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,483 @@
+<?php
+/**
+ * @category   Zend
+ * @package    Zend_Cloud_Infrastructure
+ * @subpackage Adapter
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+require_once 'Zend/Service/Rackspace/Servers.php';
+require_once 'Zend/Cloud/Infrastructure/Instance.php';
+require_once 'Zend/Cloud/Infrastructure/InstanceList.php';
+require_once 'Zend/Cloud/Infrastructure/Image.php';
+require_once 'Zend/Cloud/Infrastructure/ImageList.php';
+require_once 'Zend/Cloud/Infrastructure/Adapter/AbstractAdapter.php';
+
+/**
+ * Rackspace servers adapter for infrastructure service
+ *
+ * @package    Zend_Cloud_Infrastructure
+ * @subpackage Adapter
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Cloud_Infrastructure_Adapter_Rackspace extends Zend_Cloud_Infrastructure_Adapter_AbstractAdapter
+{
+    /**
+     * RACKSPACE constants
+     */
+    const RACKSPACE_USER      = 'rackspace_user';
+    const RACKSPACE_KEY       = 'rackspace_key';
+    const RACKSPACE_REGION    = 'rackspace_region';
+    const RACKSPACE_ZONE_USA  = 'USA';
+    const RACKSPACE_ZONE_UK   = 'UK';
+    const MONITOR_CPU_SAMPLES = 3;
+    /**
+     * Rackspace Servers Instance 
+     * 
+     * @var Zend_Service_Rackspace_Servers
+     */
+    protected $rackspace;
+    /**
+     * Rackspace access user
+     * 
+     * @var string 
+     */
+    protected $accessUser;
+
+    /**
+     * Rackspace access key
+     * 
+     * @var string 
+     */
+    protected $accessKey;
+    /**
+     * Rackspace Region
+     * 
+     * @var string 
+     */
+    protected $region;
+    /**
+     * Flavors
+     * 
+     * @var array 
+     */
+    protected $flavors;
+    /**
+     * Map array between Rackspace and Infrastructure status
+     * 
+     * @var array 
+     */
+    protected $mapStatus = array (
+        'ACTIVE'             => Zend_Cloud_Infrastructure_Instance::STATUS_RUNNING,
+        'SUSPENDED'          => Zend_Cloud_Infrastructure_Instance::STATUS_STOPPED,
+        'BUILD'              => Zend_Cloud_Infrastructure_Instance::STATUS_REBUILD,
+        'REBUILD'            => Zend_Cloud_Infrastructure_Instance::STATUS_REBUILD,
+        'QUEUE_RESIZE'       => Zend_Cloud_Infrastructure_Instance::STATUS_PENDING,
+        'PREP_RESIZE'        => Zend_Cloud_Infrastructure_Instance::STATUS_PENDING,
+        'RESIZE'             => Zend_Cloud_Infrastructure_Instance::STATUS_REBUILD,
+        'VERIFY_RESIZE'      => Zend_Cloud_Infrastructure_Instance::STATUS_REBUILD,
+        'PASSWORD'           => Zend_Cloud_Infrastructure_Instance::STATUS_PENDING,
+        'RESCUE'             => Zend_Cloud_Infrastructure_Instance::STATUS_PENDING,
+        'REBOOT'             => Zend_Cloud_Infrastructure_Instance::STATUS_REBOOTING,
+        'HARD_REBOOT'        => Zend_Cloud_Infrastructure_Instance::STATUS_REBOOTING,
+        'SHARE_IP'           => Zend_Cloud_Infrastructure_Instance::STATUS_PENDING,
+        'SHARE_IP_NO_CONFIG' => Zend_Cloud_Infrastructure_Instance::STATUS_PENDING,
+        'DELETE_IP'          => Zend_Cloud_Infrastructure_Instance::STATUS_PENDING,
+        'UNKNOWN'            => Zend_Cloud_Infrastructure_Instance::STATUS_PENDING
+    );
+    /**
+     * Constructor
+     *
+     * @param  array|Zend_Config $options
+     * @return void
+     */
+    public function __construct($options = array())
+    {
+        if (is_object($options)) {
+            if (method_exists($options, 'toArray')) {
+                $options= $options->toArray();
+            } elseif ($options instanceof Traversable) {
+                $options = iterator_to_array($options);
+            }
+        }
+        
+        if (empty($options) || !is_array($options)) {
+            require_once 'Zend/Cloud/Infrastructure/Exception.php';
+            throw new Zend_Cloud_Infrastructure_Exception('Invalid options provided');
+        }
+        
+        if (!isset($options[self::RACKSPACE_USER])) {
+            require_once 'Zend/Cloud/Infrastructure/Exception.php';
+            throw new Zend_Cloud_Infrastructure_Exception('Rackspace access user not specified!');
+        }
+
+        if (!isset($options[self::RACKSPACE_KEY])) {
+            require_once 'Zend/Cloud/Infrastructure/Exception.php';
+            throw new Zend_Cloud_Infrastructure_Exception('Rackspace access key not specified!');
+        }
+        
+        $this->accessUser = $options[self::RACKSPACE_USER];
+        $this->accessKey  = $options[self::RACKSPACE_KEY];
+        
+        if (isset($options[self::RACKSPACE_REGION])) {
+            switch ($options[self::RACKSPACE_REGION]) {
+                case self::RACKSPACE_ZONE_UK:
+                    $this->region= Zend_Service_Rackspace_Servers::UK_AUTH_URL;
+                    break;
+                case self::RACKSPACE_ZONE_USA:
+                    $this->region = Zend_Service_Rackspace_Servers::US_AUTH_URL;
+                    break;
+                default:
+                    require_once 'Zend/Cloud/Infrastructure/Exception.php';
+                    throw new Zend_Cloud_Infrastructure_Exception('The region is not valid');
+            }
+        } else {
+            $this->region = Zend_Service_Rackspace_Servers::US_AUTH_URL;
+        }
+
+        try {
+            $this->rackspace = new Zend_Service_Rackspace_Servers($this->accessUser,$this->accessKey, $this->region);
+        } catch (Exception  $e) {
+            require_once 'Zend/Cloud/Infrastructure/Exception.php';
+            throw new Zend_Cloud_Infrastructure_Exception('Error on create: ' . $e->getMessage(), $e->getCode(), $e);
+        }
+
+        if (isset($options[self::HTTP_ADAPTER])) {
+            $this->rackspace->getHttpClient()->setAdapter($options[self::HTTP_ADAPTER]);
+        }
+        
+    }
+    /**
+     * Convert the attributes of Rackspace server into attributes of Infrastructure
+     * 
+     * @param  array $attr
+     * @return array|boolean 
+     */
+    protected function convertAttributes($attr)
+    {
+        $result = array();       
+        if (!empty($attr) && is_array($attr)) {
+            $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_ID]      = $attr['id'];
+            $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_NAME]    = $attr['name'];
+            $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_STATUS]  = $this->mapStatus[$attr['status']];
+            $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_IMAGEID] = $attr['imageId'];
+            if ($this->region==Zend_Service_Rackspace_Servers::US_AUTH_URL) {
+                $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_ZONE] = self::RACKSPACE_ZONE_USA;
+            } else {
+                $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_ZONE] = self::RACKSPACE_ZONE_UK;
+            }
+            $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_RAM]     = $this->flavors[$attr['flavorId']]['ram'];
+            $result[Zend_Cloud_Infrastructure_Instance::INSTANCE_STORAGE] = $this->flavors[$attr['flavorId']]['disk'];
+        }
+        return $result;
+    }
+    /**
+     * Return a list of the available instancies
+     *
+     * @return InstanceList|boolean
+     */ 
+    public function listInstances() 
+    {
+        $this->adapterResult = $this->rackspace->listServers(true);
+        if ($this->adapterResult===false) {
+            return false;
+        }
+        $array= $this->adapterResult->toArray();
+        $result = array();
+        foreach ($array as $instance) {
+            $result[]= $this->convertAttributes($instance);
+        }
+        return new Zend_Cloud_Infrastructure_InstanceList($this, $result);
+    }
+    /**
+     * Return the status of an instance
+     *
+     * @param  string
+     * @return string|boolean
+     */ 
+    public function statusInstance($id)
+    {
+        $this->adapterResult = $this->rackspace->getServer($id);
+        if ($this->adapterResult===false) {
+            return false;
+        }
+        $array= $this->adapterResult->toArray();
+        return $this->mapStatus[$array['status']];
+    }
+    /**
+     * Return the public DNS name/Ip address of the instance
+     * 
+     * @param  string $id
+     * @return string|boolean 
+     */
+    public function publicDnsInstance($id) 
+    {
+        $this->adapterResult = $this->rackspace->getServerPublicIp($id);
+        if (empty($this->adapterResult)) {
+            return false;
+        }    
+        return $this->adapterResult[0];
+    }
+    /**
+     * Reboot an instance
+     *
+     * @param string $id
+     * @return boolean
+     */ 
+    public function rebootInstance($id)
+    {
+        return $this->rackspace->rebootServer($id,true);
+    }
+    /**
+     * Create a new instance
+     *
+     * @param string $name
+     * @param array $options
+     * @return Instance|boolean
+     */ 
+    public function createInstance($name, $options)
+    {
+        if (empty($name)) {
+            require_once 'Zend/Cloud/Infrastructure/Exception.php';
+            throw new Zend_Cloud_Infrastructure_Exception('You must specify the name of the instance');
+        }
+        if (empty($options) || !is_array($options)) {
+            require_once 'Zend/Cloud/Infrastructure/Exception.php';
+            throw new Zend_Cloud_Infrastructure_Exception('The options must be an array');
+        }
+        // @todo create an generic abstract definition for an instance?
+        $metadata= array();
+        if (isset($options['metadata'])) {
+            $metadata= $options['metadata'];
+            unset($options['metadata']);
+        }
+        $files= array();
+        if (isset($options['files'])) {
+            $files= $options['files'];
+            unset($options['files']);
+        }
+        $options['name']= $name;
+        $this->adapterResult = $this->rackspace->createServer($options,$metadata,$files);
+        if ($this->adapterResult===false) {
+            return false;
+        }
+        return new Zend_Cloud_Infrastructure_Instance($this, $this->convertAttributes($this->adapterResult->toArray()));
+    }
+    /**
+     * Stop an instance
+     *
+     * @param  string $id
+     * @return boolean
+     */ 
+    public function stopInstance($id)
+    {
+        require_once 'Zend/Cloud/Infrastructure/Exception.php';
+        throw new Zend_Cloud_Infrastructure_Exception('The stopInstance method is not implemented in the adapter');
+    }
+ 
+    /**
+     * Start an instance
+     *
+     * @param  string $id
+     * @return boolean
+     */ 
+    public function startInstance($id)
+    {
+        require_once 'Zend/Cloud/Infrastructure/Exception.php';
+        throw new Zend_Cloud_Infrastructure_Exception('The startInstance method is not implemented in the adapter');
+    }
+ 
+    /**
+     * Destroy an instance
+     *
+     * @param  string $id
+     * @return boolean
+     */ 
+    public function destroyInstance($id)
+    {
+        $this->adapterResult= $this->rackspace->deleteServer($id);
+        return $this->adapterResult;
+    }
+    /**
+     * Return a list of all the available instance images
+     *
+     * @return ImageList|boolean
+     */ 
+    public function imagesInstance()
+    {
+        $this->adapterResult = $this->rackspace->listImages(true);
+        if ($this->adapterResult===false) {
+            return false;
+        }
+        
+        $images= $this->adapterResult->toArray();
+        $result= array();
+        
+        foreach ($images as $image) {
+            if (strtolower($image['status'])==='active') {
+                if (strpos($image['name'],'Windows')!==false) {
+                    $platform = Zend_Cloud_Infrastructure_Image::IMAGE_WINDOWS;
+                } else {
+                    $platform = Zend_Cloud_Infrastructure_Image::IMAGE_LINUX;
+                }
+                if (strpos($image['name'],'x64')!==false) {
+                    $arch = Zend_Cloud_Infrastructure_Image::ARCH_64BIT;
+                } else {
+                    $arch = Zend_Cloud_Infrastructure_Image::ARCH_32BIT;
+                }
+                $result[]= array (
+                    Zend_Cloud_Infrastructure_Image::IMAGE_ID           => $image['id'],
+                    Zend_Cloud_Infrastructure_Image::IMAGE_NAME         => $image['name'],
+                    Zend_Cloud_Infrastructure_Image::IMAGE_DESCRIPTION  => $image['name'],
+                    Zend_Cloud_Infrastructure_Image::IMAGE_ARCHITECTURE => $arch,
+                    Zend_Cloud_Infrastructure_Image::IMAGE_PLATFORM     => $platform,
+                );
+            }
+        }
+        return new Zend_Cloud_Infrastructure_ImageList($result,$this->adapterResult);
+    }
+    /**
+     * Return all the available zones
+     * 
+     * @return array
+     */
+    public function zonesInstance()
+    {
+        return array(self::RACKSPACE_ZONE_USA,self::RACKSPACE_ZONE_UK);
+    }
+    /**
+     * Return the system information about the $metric of an instance
+     * NOTE: it works only for Linux servers
+     * 
+     * @param  string $id
+     * @param  string $metric
+     * @param  null|array $options
+     * @return array|boolean
+     */ 
+    public function monitorInstance($id, $metric, $options = null)
+    {
+        if (!function_exists("ssh2_connect")) {
+            require_once 'Zend/Cloud/Infrastructure/Exception.php';
+            throw new Zend_Cloud_Infrastructure_Exception('Monitor requires the PHP "SSH" extension (ext/ssh2)');
+        }
+        if (empty($id)) {
+            require_once 'Zend/Cloud/Infrastructure/Exception.php';
+            throw new Zend_Cloud_Infrastructure_Exception('You must specify the id of the instance to monitor');
+        }
+        if (empty($metric)) {
+            require_once 'Zend/Cloud/Infrastructure/Exception.php';
+            throw new Zend_Cloud_Infrastructure_Exception('You must specify the metric to monitor');
+        }
+        if (!in_array($metric,$this->validMetrics)) {
+            require_once 'Zend/Cloud/Infrastructure/Exception.php';
+            throw new Zend_Cloud_Infrastructure_Exception(sprintf('The metric "%s" is not valid', $metric));
+        }
+        if (!empty($options) && !is_array($options)) {
+            require_once 'Zend/Cloud/Infrastructure/Exception.php';
+            throw new Zend_Cloud_Infrastructure_Exception('The options must be an array');
+        }
+        
+        switch ($metric) {
+            case Zend_Cloud_Infrastructure_Instance::MONITOR_CPU:
+                $cmd= 'top -b -n '.self::MONITOR_CPU_SAMPLES.' | grep \'Cpu\'';
+                break;
+            case Zend_Cloud_Infrastructure_Instance::MONITOR_RAM:
+                $cmd= 'top -b -n 1 | grep \'Mem\'';
+                break;
+            case Zend_Cloud_Infrastructure_Instance::MONITOR_DISK:
+                $cmd= 'df --total | grep total';
+                break;
+        }
+        if (empty($cmd)) {
+            require_once 'Zend/Cloud/Infrastructure/Exception.php';
+            throw new Zend_Cloud_Infrastructure_Exception('The metric specified is not supported by the adapter');
+        }
+        
+        $params= array(
+            Zend_Cloud_Infrastructure_Instance::SSH_USERNAME => $options['username'],
+            Zend_Cloud_Infrastructure_Instance::SSH_PASSWORD => $options['password']
+        );
+        $exec_time= time();
+        $result= $this->deployInstance($id,$params,$cmd);
+        
+        if (empty($result)) {
+            return false;
+        }
+
+        $monitor = array();
+        $num     = 0;
+        $average = 0;
+
+        $outputs= explode("\n",$result);
+        foreach ($outputs as $output) {
+            if (!empty($output)) {
+                switch ($metric) {
+                    case Zend_Cloud_Infrastructure_Instance::MONITOR_CPU:
+                        if (preg_match('/(\d+\.\d)%us/', $output,$match)) {
+                            $usage = (float) $match[1];
+                        }
+                        break;
+                    case Zend_Cloud_Infrastructure_Instance::MONITOR_RAM:
+                        if (preg_match('/(\d+)k total/', $output,$match)) {
+                            $total = (integer) $match[1];
+                        }
+                        if (preg_match('/(\d+)k used/', $output,$match)) {
+                            $used = (integer) $match[1];
+                        }
+                        if ($total>0) {
+                            $usage= (float) $used/$total;
+                        }    
+                        break;
+                    case Zend_Cloud_Infrastructure_Instance::MONITOR_DISK:
+                        if (preg_match('/(\d+)%/', $output,$match)) {
+                            $usage = (float) $match[1];
+                        }
+                        break;
+                }
+                
+                $monitor['series'][] = array (
+                    'timestamp' => $exec_time,
+                    'value'     => number_format($usage,2).'%'
+                );
+                
+                $average += $usage;
+                $exec_time+= 60; // seconds
+                $num++;
+            }
+        }
+        
+        if ($num>0) {
+            $monitor['average'] = number_format($average/$num,2).'%';
+        }
+        return $monitor;
+    }
+    /**
+     * Get the adapter 
+     * 
+     * @return Zend_Service_Rackspace_Servers
+     */
+    public function getAdapter()
+    {
+        return $this->rackspace;
+    }
+    /**
+     * Get last HTTP request
+     * 
+     * @return string 
+     */
+    public function getLastHttpRequest()
+    {
+        return $this->rackspace->getHttpClient()->getLastRequest();
+    }
+    /**
+     * Get the last HTTP response
+     * 
+     * @return Zend_Http_Response 
+     */
+    public function getLastHttpResponse()
+    {
+        return $this->rackspace->getHttpClient()->getLastResponse();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Cloud/Infrastructure/Exception.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,25 @@
+<?php
+/**
+ * Exception
+ * 
+ * @category   Zend
+ * @package    Zend_Cloud
+ * @subpackage Infrastructure
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+/**
+ * Zend_Cloud_Exception
+ */
+require_once 'Zend/Cloud/Exception.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Cloud
+ * @subpackage Infrastructure
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Cloud_Infrastructure_Exception extends Zend_Cloud_Exception
+{}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Cloud/Infrastructure/Factory.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,65 @@
+<?php
+/**
+ * @category   Zend
+ * @package    Zend_Cloud
+ * @subpackage Infrastructure
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+require_once 'Zend/Cloud/AbstractFactory.php';
+
+
+/**
+ * Factory for infrastructure adapters
+ * 
+ * @package    Zend_Cloud
+ * @subpackage Infrastructure
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Cloud_Infrastructure_Factory extends Zend_Cloud_AbstractFactory
+{
+    const INFRASTRUCTURE_ADAPTER_KEY = 'infrastructure_adapter';
+
+    /**
+     * @var string Interface which adapter must implement to be considered valid
+     */
+    protected static $_adapterInterface = 'Zend_Cloud_Infrastructure_Adapter';
+
+    /**
+     * Constructor
+     *
+     * Private ctor - should not be used
+     *
+     * @return void
+     */
+    private function __construct()
+    {
+    }
+
+    /**
+     * Retrieve an adapter instance
+     *
+     * @param  array $options
+     * @return void
+     */
+    public static function getAdapter($options = array())
+    {
+        $adapter = parent::_getAdapter(self::INFRASTRUCTURE_ADAPTER_KEY, $options);
+
+        if (!$adapter) {
+            require_once 'Zend/Cloud/Infrastructure/Exception.php';
+            throw new Zend_Cloud_Infrastructure_Exception(sprintf(
+                'Class must be specified using the "%s" key',
+                self::INFRASTRUCTURE_ADAPTER_KEY
+            ));
+        } elseif (!$adapter instanceof self::$_adapterInterface) {
+            require_once 'Zend/Cloud/Infrastructure/Exception.php';
+            throw new Zend_Cloud_Infrastructure_Exception(sprintf(
+                'Adapter must implement "%s"', self::$_adapterInterface
+            ));
+        }
+        return $adapter;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Cloud/Infrastructure/Image.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,176 @@
+<?php
+/**
+ * @category   Zend
+ * @package    Zend_Cloud
+ * @subpackage Infrastructure
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+/**
+ * Instance of an infrastructure service
+ * 
+ * @package    Zend_Cloud
+ * @subpackage Infrastructure
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Cloud_Infrastructure_Image 
+{
+    const IMAGE_ID           = 'imageId';
+    const IMAGE_OWNERID      = 'ownerId';
+    const IMAGE_NAME         = 'name';
+    const IMAGE_DESCRIPTION  = 'description';
+    const IMAGE_PLATFORM     = 'platform';
+    const IMAGE_ARCHITECTURE = 'architecture';
+    const ARCH_32BIT         = 'i386';
+    const ARCH_64BIT         = 'x86_64';
+    const IMAGE_WINDOWS      = 'windows';
+    const IMAGE_LINUX        = 'linux';
+
+    /**
+     * Image's attributes
+     * 
+     * @var array
+     */
+    protected $attributes = array();
+
+    /**
+     * The Image adapter (if exists)
+     * 
+     * @var object
+     */
+    protected $adapter;
+
+    /**
+     * Required attributes
+     * 
+     * @var array
+     */
+    protected $attributeRequired = array(
+        self::IMAGE_ID, 
+        self::IMAGE_DESCRIPTION, 
+        self::IMAGE_PLATFORM, 
+        self::IMAGE_ARCHITECTURE,
+    );
+
+    /**
+     * Constructor
+     * 
+     * @param array $data
+     * @param object $adapter 
+     */
+    public function __construct($data, $adapter = null) 
+    {
+        if (is_object($data)) {
+            if (method_exists($data, 'toArray')) {
+                $data= $data->toArray();
+            } elseif ($data instanceof Traversable) {
+                $data = iterator_to_array($data);
+            }
+        }
+        
+        if (empty($data) || !is_array($data)) {
+            require_once 'Zend/Cloud/Infrastructure/Exception.php';
+            throw new Zend_Cloud_Infrastructure_Exception('You must pass an array of parameters');
+        }
+
+        foreach ($this->attributeRequired as $key) {
+            if (empty($data[$key])) {
+                require_once 'Zend/Cloud/Infrastructure/Exception.php';
+                throw new Zend_Cloud_Infrastructure_Exception(sprintf(
+                    'The param "%s" is a required parameter for class %s',
+                    $key,
+                    __CLASS__
+                ));
+            }
+        }
+
+        $this->attributes = $data;
+        $this->adapter    = $adapter;
+    }
+
+    /**
+     * Get Attribute with a specific key
+     *
+     * @param array $data
+     * @return misc|boolean
+     */
+    public function getAttribute($key) 
+    {
+        if (!empty($this->attributes[$key])) {
+            return $this->attributes[$key];
+        }
+        return false;
+    }
+
+    /**
+     * Get all the attributes
+     * 
+     * @return array
+     */
+    public function getAttributes()
+    {
+        return $this->attributes;
+    }
+
+    /**
+     * Get the image ID
+     * 
+     * @return string
+     */
+    public function getId()
+    {
+        return $this->attributes[self::IMAGE_ID];
+    }
+
+    /**
+     * Get the Owner ID
+     * 
+     * @return string
+     */
+    public function getOwnerId()
+    {
+        return $this->attributes[self::IMAGE_OWNERID];
+    }
+
+    /**
+     * Get the name
+     * 
+     * @return string 
+     */
+    public function getName()
+    {
+        return $this->attributes[self::IMAGE_NAME];
+    }
+
+    /**
+     * Get the description
+     * 
+     * @return string 
+     */
+    public function getDescription()
+    {
+        return $this->attributes[self::IMAGE_DESCRIPTION];
+    }
+
+    /**
+     * Get the platform
+     * 
+     * @return string 
+     */
+    public function getPlatform()
+    {
+        return $this->attributes[self::IMAGE_PLATFORM];
+    }
+
+    /**
+     * Get the architecture
+     * 
+     * @return string 
+     */
+    public function getArchitecture()
+    {
+        return $this->attributes[self::IMAGE_ARCHITECTURE];
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Cloud/Infrastructure/ImageList.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,218 @@
+<?php
+/**
+ * @category   Zend
+ * @package    Zend_Cloud
+ * @subpackage Infrastructure
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+
+require_once 'Zend/Cloud/Infrastructure/Image.php';
+
+/**
+ * List of images
+ *
+ * @package    Zend_Cloud
+ * @subpackage Infrastructure
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Cloud_Infrastructure_ImageList implements Countable, Iterator, ArrayAccess
+{
+    /**
+     * @var array Array of Zend_Cloud_Infrastructure_Image
+     */
+    protected $images = array();
+
+    /**
+     * @var int Iterator key
+     */
+    protected $iteratorKey = 0;
+
+    /**
+     * The Image adapter (if exists)
+     * 
+     * @var object
+     */
+    protected $adapter;
+
+    /**
+     * Constructor
+     *
+     * @param  array $list
+     * @param  null|object $adapter
+     * @return boolean
+     */
+    public function __construct($images, $adapter = null)
+    {
+        if (empty($images) || !is_array($images)) {
+            require_once 'Zend/Cloud/Infrastructure/Exception.php';
+            throw new Zend_Cloud_Infrastructure_Exception(__CLASS__ . ' expects an array of images');
+        }
+
+        $this->adapter = $adapter;
+        $this->constructFromArray($images);
+    }
+
+    /**
+     * Transforms the Array to array of Instances
+     *
+     * @param  array $list
+     * @return void
+     */
+    protected function constructFromArray(array $list)
+    {
+        foreach ($list as $image) {
+            $this->addImage(new Zend_Cloud_Infrastructure_Image($image, $this->adapter));
+        }
+    }
+
+    /**
+     * Add an image
+     *
+     * @param  Image
+     * @return ImageList
+     */
+    protected function addImage(Zend_Cloud_Infrastructure_Image $image)
+    {
+        $this->images[] = $image;
+        return $this;
+    }
+
+    /**
+     * Return number of images
+     *
+     * Implement Countable::count()
+     *
+     * @return int
+     */
+    public function count()
+    {
+        return count($this->images);
+    }
+
+    /**
+     * Return the current element
+     *
+     * Implement Iterator::current()
+     *
+     * @return Image
+     */
+    public function current()
+    {
+        return $this->images[$this->iteratorKey];
+    }
+
+    /**
+     * Return the key of the current element
+     *
+     * Implement Iterator::key()
+     *
+     * @return int
+     */
+    public function key()
+    {
+        return $this->iteratorKey;
+    }
+
+    /**
+     * Move forward to next element
+     *
+     * Implement Iterator::next()
+     *
+     * @return void
+     */
+    public function next()
+    {
+        $this->iteratorKey++;
+    }
+
+    /**
+     * Rewind the Iterator to the first element
+     *
+     * Implement Iterator::rewind()
+     *
+     * @return void
+     */
+    public function rewind()
+    {
+        $this->iteratorKey = 0;
+    }
+
+    /**
+     * Check if there is a current element after calls to rewind() or next()
+     *
+     * Implement Iterator::valid()
+     *
+     * @return bool
+     */
+    public function valid()
+    {
+        $numItems = $this->count();
+        if ($numItems > 0 && $this->iteratorKey < $numItems) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Whether the offset exists
+     *
+     * Implement ArrayAccess::offsetExists()
+     *
+     * @param   int     $offset
+     * @return  bool
+     */
+    public function offsetExists($offset)
+    {
+        return ($offset < $this->count());
+    }
+
+    /**
+     * Return value at given offset
+     *
+     * Implement ArrayAccess::offsetGet()
+     *
+     * @param   int     $offset
+     * @throws  Zend_Cloud_Infrastructure_Exception
+     * @return  Image
+     */
+    public function offsetGet($offset)
+    {
+        if (!$this->offsetExists($offset)) {
+            require_once 'Zend/Cloud/Infrastructure/Exception.php';
+            throw new Zend_Cloud_Infrastructure_Exception('Illegal index');
+        }
+        return $this->images[$offset];
+    }
+
+    /**
+     * Throws exception because all values are read-only
+     *
+     * Implement ArrayAccess::offsetSet()
+     *
+     * @param   int     $offset
+     * @param   string  $value
+     * @throws  Zend_Cloud_Infrastructure_Exception
+     */
+    public function offsetSet($offset, $value)
+    {
+        require_once 'Zend/Cloud/Infrastructure/Exception.php';
+        throw new Zend_Cloud_Infrastructure_Exception('You are trying to set read-only property');
+    }
+
+    /**
+     * Throws exception because all values are read-only
+     *
+     * Implement ArrayAccess::offsetUnset()
+     *
+     * @param   int     $offset
+     * @throws  Zend_Cloud_Infrastructure_Exception
+     */
+    public function offsetUnset($offset)
+    {
+        require_once 'Zend/Cloud/Infrastructure/Exception.php';
+        throw new Zend_Cloud_Infrastructure_Exception('You are trying to unset read-only property');
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Cloud/Infrastructure/Instance.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,320 @@
+<?php
+/**
+ * @category   Zend
+ * @package    Zend_Cloud
+ * @subpackage Infrastructure
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+/**
+ * Instance of an infrastructure service
+ *
+ * @package    Zend_Cloud
+ * @subpackage Infrastructure
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Cloud_Infrastructure_Instance 
+{
+    const STATUS_RUNNING       = 'running';
+    const STATUS_STOPPED       = 'stopped';
+    const STATUS_SHUTTING_DOWN = 'shutting-down';
+    const STATUS_REBOOTING     = 'rebooting';
+    const STATUS_TERMINATED    = 'terminated';
+    const STATUS_PENDING       = 'pending';
+    const STATUS_REBUILD       = 'rebuild';
+    const INSTANCE_ID          = 'id';
+    const INSTANCE_IMAGEID     = 'imageId';
+    const INSTANCE_NAME        = 'name';
+    const INSTANCE_STATUS      = 'status';
+    const INSTANCE_PUBLICDNS   = 'publicDns';
+    const INSTANCE_CPU         = 'cpu';
+    const INSTANCE_RAM         = 'ram';
+    const INSTANCE_STORAGE     = 'storageSize';
+    const INSTANCE_ZONE        = 'zone';
+    const INSTANCE_LAUNCHTIME  = 'launchTime';
+    const MONITOR_CPU          = 'CpuUsage';
+    const MONITOR_RAM          = 'RamUsage';
+    const MONITOR_NETWORK_IN   = 'NetworkIn';
+    const MONITOR_NETWORK_OUT  = 'NetworkOut';
+    const MONITOR_DISK         = 'DiskUsage';
+    const MONITOR_DISK_WRITE   = 'DiskWrite';
+    const MONITOR_DISK_READ    = 'DiskRead';
+    const MONITOR_START_TIME   = 'StartTime';
+    const MONITOR_END_TIME     = 'EndTime';
+    const SSH_USERNAME         = 'username';
+    const SSH_PASSWORD         = 'password';
+    const SSH_PRIVATE_KEY      = 'privateKey';
+    const SSH_PUBLIC_KEY       = 'publicKey';
+    const SSH_PASSPHRASE       = 'passphrase';
+
+    /**
+     * @var Zend_Cloud_Infrastructure_Adapter
+     */
+    protected $adapter;
+
+    /**
+     * Instance's attribute
+     * 
+     * @var array 
+     */
+    protected $attributes;
+
+    /**
+     * Attributes required for an instance
+     * 
+     * @var array 
+     */
+    protected $attributeRequired = array(
+        self::INSTANCE_ID,
+        self::INSTANCE_STATUS,
+        self::INSTANCE_IMAGEID,
+        self::INSTANCE_ZONE
+    );
+
+    /**
+     * Constructor
+     * 
+     * @param  Adapter $adapter
+     * @param  array $data 
+     * @return void
+     */
+    public function __construct($adapter, $data = null)
+    {
+        if (!($adapter instanceof Zend_Cloud_Infrastructure_Adapter)) {
+            require_once 'Zend/Cloud/Infrastructure/Exception.php';
+            throw new Zend_Cloud_Infrastructure_Exception("You must pass a Zend_Cloud_Infrastructure_Adapter instance");
+        }
+
+        if (is_object($data)) {
+            if (method_exists($data, 'toArray')) {
+                $data= $data->toArray();
+            } elseif ($data instanceof Traversable) {
+                $data = iterator_to_array($data);
+            }
+        }
+        
+        if (empty($data) || !is_array($data)) {
+            require_once 'Zend/Cloud/Infrastructure/Exception.php';
+            throw new Zend_Cloud_Infrastructure_Exception("You must pass an array of parameters");
+        }
+
+        foreach ($this->attributeRequired as $key) {
+            if (empty($data[$key])) {
+                require_once 'Zend/Cloud/Infrastructure/Exception.php';
+                throw new Zend_Cloud_Infrastructure_Exception(sprintf(
+                    'The param "%s" is a required param for %s', 
+                    $key,
+                    __CLASS__
+                ));
+            }
+        }
+
+        $this->adapter    = $adapter;
+        $this->attributes = $data;
+    }
+
+    /**
+     * Get Attribute with a specific key
+     *
+     * @param array $data
+     * @return misc|false
+     */
+    public function getAttribute($key) 
+    {
+        if (!empty($this->attributes[$key])) {
+            return $this->attributes[$key];
+        }
+        return false;
+    }
+
+    /**
+     * Get all the attributes
+     * 
+     * @return array
+     */
+    public function getAttributes()
+    {
+        return $this->attributes;
+    }
+
+    /**
+     * Get the instance's id
+     * 
+     * @return string 
+     */
+    public function getId()
+    {
+        return $this->attributes[self::INSTANCE_ID];
+    }
+
+    /**
+     * Get the instance's image id
+     * 
+     * @return string 
+     */
+    public function getImageId()
+    {
+        return $this->attributes[self::INSTANCE_IMAGEID];
+    }
+
+    /**
+     * Get the instance's name
+     * 
+     * @return string 
+     */
+    public function getName()
+    {
+        return $this->attributes[self::INSTANCE_NAME];
+    }
+
+    /**
+     * Get the status of the instance
+     * 
+     * @return string|boolean 
+     */
+    public function getStatus()
+    {
+        return $this->adapter->statusInstance($this->attributes[self::INSTANCE_ID]);
+    }
+
+    /**
+     * Wait for status $status with a timeout of $timeout seconds
+     * 
+     * @param  string $status
+     * @param  integer $timeout 
+     * @return boolean
+     */
+    public function waitStatus($status, $timeout = Adapter::TIMEOUT_STATUS_CHANGE)
+    {
+        return $this->adapter->waitStatusInstance($this->attributes[self::INSTANCE_ID], $status, $timeout);
+    }
+
+    /**
+     * Get the public DNS of the instance
+     * 
+     * @return string 
+     */
+    public function getPublicDns()
+    {
+        if (!isset($this->attributes[self::INSTANCE_PUBLICDNS])) {
+            $this->attributes[self::INSTANCE_PUBLICDNS] =  $this->adapter->publicDnsInstance($this->attributes[self::INSTANCE_ID]);
+        }
+        return $this->attributes[self::INSTANCE_PUBLICDNS];
+    }
+
+    /**
+     * Get the instance's CPU
+     * 
+     * @return string
+     */
+    public function getCpu()
+    {
+        return $this->attributes[self::INSTANCE_CPU];
+    }
+
+    /**
+     * Get the instance's RAM size
+     * 
+     * @return string
+     */
+    public function getRamSize()
+    {
+        return $this->attributes[self::INSTANCE_RAM];
+    }
+
+    /**
+     * Get the instance's storage size
+     * 
+     * @return string
+     */
+    public function getStorageSize()
+    {
+        return $this->attributes[self::INSTANCE_STORAGE];
+    }
+
+    /**
+     * Get the instance's zone
+     * 
+     * @return string 
+     */
+    public function getZone()
+    {
+        return $this->attributes[self::INSTANCE_ZONE];
+    }
+
+    /**
+     * Get the instance's launch time
+     * 
+     * @return string
+     */
+    public function getLaunchTime()
+    {
+        return $this->attributes[self::INSTANCE_LAUNCHTIME];
+    }
+
+    /**
+     * Reboot the instance
+     * 
+     * @return boolean 
+     */
+    public function reboot()
+    {
+        return $this->adapter->rebootInstance($this->attributes[self::INSTANCE_ID]);
+    }
+
+    /**
+     * Stop the instance
+     * 
+     * @return boolean 
+     */
+    public function stop()
+    {
+        return $this->adapter->stopInstance($this->attributes[self::INSTANCE_ID]);
+    }
+
+    /**
+     * Start the instance
+     * 
+     * @return boolean 
+     */
+    public function start()
+    {
+        return $this->adapter->startInstance($this->attributes[self::INSTANCE_ID]);
+    }
+
+    /**
+     * Destroy the instance
+     * 
+     * @return boolean 
+     */
+    public function destroy()
+    {
+        return $this->adapter->destroyInstance($this->attributes[self::INSTANCE_ID]);
+    }
+
+    /**
+     * Return the system informations about the $metric of an instance
+     * 
+     * @param  string $metric
+     * @param  null|array $options
+     * @return array|boolean
+     */ 
+    public function monitor($metric, $options = null)
+    {
+        return $this->adapter->monitorInstance($this->attributes[self::INSTANCE_ID], $metric, $options);
+    }
+
+    /**
+     * Run arbitrary shell script on the instance
+     *
+     * @param  array $param
+     * @param  string|array $cmd
+     * @return string|array
+     */
+    public function deploy($params, $cmd)
+    {
+        return $this->adapter->deployInstance($this->attributes[self::INSTANCE_ID], $params, $cmd);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Cloud/Infrastructure/InstanceList.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,219 @@
+<?php
+/**
+ * @category   Zend
+ * @package    Zend_Cloud
+ * @subpackage Infrastructure
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+require_once 'Zend/Cloud/Infrastructure/Instance.php';
+
+/**
+ * List of instances
+ *
+ * @package    Zend_Cloud
+ * @subpackage Infrastructure
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Cloud_Infrastructure_InstanceList implements Countable, Iterator, ArrayAccess
+{
+    /**
+     * @var array Array of Zend_Cloud_Infrastructure_Instance
+     */
+    protected $instances = array();
+
+    /**
+     * @var int Iterator key
+     */
+    protected $iteratorKey = 0;
+
+    /**
+     * @var Zend_Cloud_Infrastructure_Adapter
+     */
+    protected $adapter;
+
+    /**
+     * Constructor
+     *
+     * @param  Adapter $adapter
+     * @param  array $instances
+     * @return void
+     */
+    public function __construct($adapter, array $instances = null)
+    {
+        if (!($adapter instanceof Zend_Cloud_Infrastructure_Adapter)) {
+            require_once 'Zend/Cloud/Infrastructure/Exception.php';
+            throw new Zend_Cloud_Infrastructure_Exception('You must pass a Zend_Cloud_Infrastructure_Adapter');
+        }
+        if (empty($instances)) {
+            require_once 'Zend/Cloud/Infrastructure/Exception.php';
+            throw new Zend_Cloud_Infrastructure_Exception('You must pass an array of Instances');
+        }
+
+        $this->adapter = $adapter;
+        $this->constructFromArray($instances);
+    }
+
+    /**
+     * Transforms the Array to array of Instances
+     *
+     * @param  array $list
+     * @return void
+     */
+    protected function constructFromArray(array $list)
+    {
+        foreach ($list as $instance) {
+            $this->addInstance(new Zend_Cloud_Infrastructure_Instance($this->adapter,$instance));
+        }
+    }
+
+    /**
+     * Add an instance
+     *
+     * @param  Instance
+     * @return InstanceList
+     */
+    protected function addInstance(Zend_Cloud_Infrastructure_Instance $instance)
+    {
+        $this->instances[] = $instance;
+        return $this;
+    }
+
+    /**
+     * Return number of instances
+     *
+     * Implement Countable::count()
+     *
+     * @return int
+     */
+    public function count()
+    {
+        return count($this->instances);
+    }
+
+    /**
+     * Return the current element
+     *
+     * Implement Iterator::current()
+     *
+     * @return Instance
+     */
+    public function current()
+    {
+        return $this->instances[$this->iteratorKey];
+    }
+
+    /**
+     * Return the key of the current element
+     *
+     * Implement Iterator::key()
+     *
+     * @return int
+     */
+    public function key()
+    {
+        return $this->iteratorKey;
+    }
+
+    /**
+     * Move forward to next element
+     *
+     * Implement Iterator::next()
+     *
+     * @return void
+     */
+    public function next()
+    {
+        $this->iteratorKey++;
+    }
+
+    /**
+     * Rewind the Iterator to the first element
+     *
+     * Implement Iterator::rewind()
+     *
+     * @return void
+     */
+    public function rewind()
+    {
+        $this->iteratorKey = 0;
+    }
+
+    /**
+     * Check if there is a current element after calls to rewind() or next()
+     *
+     * Implement Iterator::valid()
+     *
+     * @return bool
+     */
+    public function valid()
+    {
+        $numItems = $this->count();
+        if ($numItems > 0 && $this->iteratorKey < $numItems) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Whether the offset exists
+     *
+     * Implement ArrayAccess::offsetExists()
+     *
+     * @param  int $offset
+     * @return bool
+     */
+    public function offsetExists($offset)
+    {
+        return ($offset < $this->count());
+    }
+
+    /**
+     * Return value at given offset
+     *
+     * Implement ArrayAccess::offsetGet()
+     *
+     * @param  int $offset
+     * @return Instance
+     * @throws Zend_Cloud_Infrastructure_Exception
+     */
+    public function offsetGet($offset)
+    {
+        if (!$this->offsetExists($offset)) {
+            require_once 'Zend/Cloud/Infrastructure/Exception.php';
+            throw new Zend_Cloud_Infrastructure_Exception('Illegal index');
+        }
+        return $this->instances[$offset];
+    }
+
+    /**
+     * Throws exception because all values are read-only
+     *
+     * Implement ArrayAccess::offsetSet()
+     *
+     * @param   int     $offset
+     * @param   string  $value
+     * @throws  Zend_Cloud_Infrastructure_Exception
+     */
+    public function offsetSet($offset, $value)
+    {
+        require_once 'Zend/Cloud/Infrastructure/Exception.php';
+        throw new Zend_Cloud_Infrastructure_Exception('You are trying to set read-only property');
+    }
+
+    /**
+     * Throws exception because all values are read-only
+     *
+     * Implement ArrayAccess::offsetUnset()
+     *
+     * @param   int     $offset
+     * @throws  Zend_Cloud_Infrastructure_Exception
+     */
+    public function offsetUnset($offset)
+    {
+        require_once 'Zend/Cloud/Infrastructure/Exception.php';
+        throw new Zend_Cloud_Infrastructure_Exception('You are trying to unset read-only property');
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Cloud/StorageService/Adapter/Rackspace.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,332 @@
+<?php
+/**
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Cloud_StorageService
+ * @subpackage Adapter
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+require_once 'Zend/Cloud/StorageService/Adapter.php';
+require_once 'Zend/Cloud/StorageService/Exception.php';
+require_once 'Zend/Service/Rackspace/Files.php';
+require_once 'Zend/Service/Rackspace/Exception.php';
+
+/**
+ * Adapter for Rackspace cloud storage
+ *
+ * @category   Zend
+ * @package    Zend_Cloud_StorageService
+ * @subpackage Adapter
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Cloud_StorageService_Adapter_Rackspace
+    implements Zend_Cloud_StorageService_Adapter
+{
+    const USER                = 'user';
+    const API_KEY             = 'key';
+    const REMOTE_CONTAINER    = 'container';
+    const DELETE_METADATA_KEY = 'ZF_metadata_deleted';
+    
+    /**
+     * The Rackspace adapter
+     * @var Zend_Service_Rackspace_Files
+     */
+    protected $_rackspace;
+
+    /**
+     * Container in which files are stored
+     * @var string
+     */
+    protected $_container = 'default';
+    
+    /**
+     * Constructor
+     *
+     * @param  array|Traversable $options
+     * @return void
+     */
+    function __construct($options = array())
+    {
+        if ($options instanceof Zend_Config) {
+            $options = $options->toArray();
+        }
+
+        if (!is_array($options) || empty($options)) {
+            throw new Zend_Cloud_StorageService_Exception('Invalid options provided');
+        }
+
+        try {
+            $this->_rackspace = new Zend_Service_Rackspace_Files($options[self::USER], $options[self::API_KEY]);
+        } catch (Zend_Service_Rackspace_Exception $e) {
+            throw new Zend_Cloud_StorageService_Exception('Error on create: '.$e->getMessage(), $e->getCode(), $e);
+        }
+        
+        if (isset($options[self::HTTP_ADAPTER])) {
+            $this->_rackspace->getHttpClient()->setAdapter($options[self::HTTP_ADAPTER]);
+        }
+        if (!empty($options[self::REMOTE_CONTAINER])) {
+            $this->_container = $options[self::REMOTE_CONTAINER];
+        }    
+    }
+
+     /**
+     * Get an item from the storage service.
+     *
+     * @param  string $path
+     * @param  array $options
+     * @return mixed
+     */
+    public function fetchItem($path, $options = null)
+    {
+        $item = $this->_rackspace->getObject($this->_container,$path, $options);
+        if (!$this->_rackspace->isSuccessful() && ($this->_rackspace->getErrorCode()!='404')) {
+            throw new Zend_Cloud_StorageService_Exception('Error on fetch: '.$this->_rackspace->getErrorMsg());
+        }
+        if (!empty($item)) {
+            return $item->getContent();
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Store an item in the storage service.
+     * 
+     * @param  string $destinationPath
+     * @param  mixed $data
+     * @param  array $options
+     * @return void
+     */
+    public function storeItem($destinationPath, $data, $options = null)
+    {
+        $this->_rackspace->storeObject($this->_container,$destinationPath,$data,$options);
+        if (!$this->_rackspace->isSuccessful()) {
+            throw new Zend_Cloud_StorageService_Exception('Error on store: '.$this->_rackspace->getErrorMsg());
+        }
+    }
+
+    /**
+     * Delete an item in the storage service.
+     *
+     * @param  string $path
+     * @param  array $options
+     * @return void
+     */
+    public function deleteItem($path, $options = null)
+    {
+        $this->_rackspace->deleteObject($this->_container,$path);
+        if (!$this->_rackspace->isSuccessful()) {
+            throw new Zend_Cloud_StorageService_Exception('Error on delete: '.$this->_rackspace->getErrorMsg());
+        }
+    }
+
+    /**
+     * Copy an item in the storage service to a given path.
+     *
+     * @param  string $sourcePath
+     * @param  string $destination path
+     * @param  array $options
+     * @return void
+     */
+    public function copyItem($sourcePath, $destinationPath, $options = null)
+    {
+        $this->_rackspace->copyObject($this->_container,$sourcePath,$this->_container,$destinationPath,$options);
+        if (!$this->_rackspace->isSuccessful()) {
+            throw new Zend_Cloud_StorageService_Exception('Error on copy: '.$this->_rackspace->getErrorMsg());
+        }
+    }
+
+    /**
+     * Move an item in the storage service to a given path.
+     * WARNING: This operation is *very* expensive for services that do not
+     * support moving an item natively.
+     *
+     * @param  string $sourcePath
+     * @param  string $destination path
+     * @param  array $options
+     * @return void
+     */
+    public function moveItem($sourcePath, $destinationPath, $options = null)
+    {
+        try {
+            $this->copyItem($sourcePath, $destinationPath, $options);
+        } catch (Zend_Service_Rackspace_Exception $e) {
+            throw new Zend_Cloud_StorageService_Exception('Error on move: '.$e->getMessage());
+        }    
+        try {
+            $this->deleteItem($sourcePath);
+        } catch (Zend_Service_Rackspace_Exception $e) {
+            $this->deleteItem($destinationPath);
+            throw new Zend_Cloud_StorageService_Exception('Error on move: '.$e->getMessage());
+        }    
+    }
+
+    /**
+     * Rename an item in the storage service to a given name.
+     * 
+     * @param  string $path
+     * @param  string $name
+     * @param  array $options
+     * @return void
+     */
+    public function renameItem($path, $name, $options = null)
+    {
+        require_once 'Zend/Cloud/OperationNotAvailableException.php';
+        throw new Zend_Cloud_OperationNotAvailableException('Renaming not implemented');
+    }
+
+    /**
+     * Get a key/value array of metadata for the given path.
+     *
+     * @param  string $path
+     * @param  array $options
+     * @return array An associative array of key/value pairs specifying the metadata for this object.
+     *                  If no metadata exists, an empty array is returned.
+     */
+    public function fetchMetadata($path, $options = null)
+    {
+        $result = $this->_rackspace->getMetadataObject($this->_container,$path);
+        if (!$this->_rackspace->isSuccessful()) {
+            throw new Zend_Cloud_StorageService_Exception('Error on fetch metadata: '.$this->_rackspace->getErrorMsg());
+        }
+        $metadata = array();
+        if (isset($result['metadata'])) {
+            $metadata =  $result['metadata'];
+        }
+        // delete the self::DELETE_METADATA_KEY - this is a trick to remove all
+        // the metadata information of an object (see deleteMetadata). 
+        // Rackspace doesn't have an API to remove the metadata of an object
+        unset($metadata[self::DELETE_METADATA_KEY]);
+        return $metadata;
+    }
+
+    /**
+     * Store a key/value array of metadata at the given path.
+     * WARNING: This operation overwrites any metadata that is located at
+     * $destinationPath.
+     *
+     * @param  string $destinationPath
+     * @param  array  $metadata        associative array specifying the key/value pairs for the metadata.
+     * @param  array  $options
+     * @return void
+     */
+    public function storeMetadata($destinationPath, $metadata, $options = null)
+    {
+        $this->_rackspace->setMetadataObject($this->_container, $destinationPath, $metadata);
+        if (!$this->_rackspace->isSuccessful()) {
+            throw new Zend_Cloud_StorageService_Exception('Error on store metadata: '.$this->_rackspace->getErrorMsg());
+        }
+     }
+
+    /**
+     * Delete a key/value array of metadata at the given path.
+     *
+     * @param  string $path
+     * @param  array $metadata - An associative array specifying the key/value pairs for the metadata
+     *                           to be deleted.  If null, all metadata associated with the object will
+     *                           be deleted.
+     * @param  array $options
+     * @return void
+     */
+    public function deleteMetadata($path, $metadata = null, $options = null)
+    {
+        if (empty($metadata)) {
+            $newMetadata = array(self::DELETE_METADATA_KEY => true);
+            try {
+                $this->storeMetadata($path, $newMetadata);
+            } catch (Zend_Service_Rackspace_Exception $e) {
+                throw new Zend_Cloud_StorageService_Exception('Error on delete metadata: '.$e->getMessage());
+            }
+        } else {
+            try {
+                $oldMetadata = $this->fetchMetadata($path);
+            } catch (Zend_Service_Rackspace_Exception $e) {
+                throw new Zend_Cloud_StorageService_Exception('Error on delete metadata: '.$e->getMessage());
+            }
+            $newMetadata = array_diff_assoc($oldMetadata, $metadata);
+            try {
+                $this->storeMetadata($path, $newMetadata);
+            } catch (Zend_Service_Rackspace_Exception $e) {
+                throw new Zend_Cloud_StorageService_Exception('Error on delete metadata: '.$e->getMessage());
+            }
+        }
+    }
+
+    /*
+     * Recursively traverse all the folders and build an array that contains
+     * the path names for each folder.
+     *
+     * @param  string $path        folder path to get the list of folders from.
+     * @param  array& $resultArray reference to the array that contains the path names
+     *                             for each folder.
+     * @return void
+     */
+    private function getAllFolders($path, &$resultArray)
+    {
+        if (!empty($path)) {
+            $options = array (
+                'prefix'    => $path
+            );
+        }    
+        $files = $this->_rackspace->getObjects($this->_container,$options);
+        if (!$this->_rackspace->isSuccessful()) {
+            throw new Zend_Cloud_StorageService_Exception('Error on get all folders: '.$this->_rackspace->getErrorMsg());
+        }
+        $resultArray = array();
+        foreach ($files as $file) {
+            $resultArray[dirname($file->getName())] = true;
+        }
+        $resultArray = array_keys($resultArray);
+    }
+
+    /**
+     * Return an array of the items contained in the given path.  The items
+     * returned are the files or objects that in the specified path.
+     *
+     * @param  string $path
+     * @param  array  $options
+     * @return array
+     */
+    public function listItems($path, $options = null)
+    {
+        if (!empty($path)) {
+            $options = array (
+                'prefix'    => $path
+            );
+        }   
+        
+        $files = $this->_rackspace->getObjects($this->_container,$options);
+        if (!$this->_rackspace->isSuccessful()) {
+            throw new Zend_Cloud_StorageService_Exception('Error on list items: '.$this->_rackspace->getErrorMsg());
+        }
+        $resultArray = array();
+        if (!empty($files)) {
+            foreach ($files as $file) {
+                $resultArray[] = $file->getName();
+            }
+        }    
+        return $resultArray;
+    }
+
+    /**
+     * Get the concrete client.
+     *
+     * @return Zend_Service_Rackspace_File
+     */
+    public function getClient()
+    {
+         return $this->_rackspace;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/EventManager/Event.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,225 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_EventManager
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+require_once 'Zend/EventManager/EventDescription.php';
+
+/**
+ * Representation of an event
+ *
+ * Encapsulates the target context and parameters passed, and provides some 
+ * behavior for interacting with the event manager.
+ *
+ * @category   Zend
+ * @package    Zend_EventManager
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_EventManager_Event implements Zend_EventManager_EventDescription
+{
+    /**
+     * @var string Event name
+     */
+    protected $name;
+
+    /**
+     * @var string|object The event target
+     */
+    protected $target;
+
+    /**
+     * @var array|ArrayAccess|object The event parameters
+     */
+    protected $params = array();
+
+    /**
+     * @var bool Whether or not to stop propagation
+     */
+    protected $stopPropagation = false;
+
+    /**
+     * Constructor
+     *
+     * Accept a target and its parameters.
+     * 
+     * @param  string $name Event name
+     * @param  string|object $target 
+     * @param  array|ArrayAccess $params 
+     * @return void
+     */
+    public function __construct($name = null, $target = null, $params = null)
+    {
+        if (null !== $name) {
+            $this->setName($name);
+        }
+
+        if (null !== $target) {
+            $this->setTarget($target);
+        }
+
+        if (null !== $params) {
+            $this->setParams($params);
+        }
+    }
+
+    /**
+     * Get event name
+     * 
+     * @return string
+     */
+    public function getName()
+    {
+        return $this->name;
+    }
+
+    /**
+     * Get the event target
+     *
+     * This may be either an object, or the name of a static method.
+     * 
+     * @return string|object
+     */
+    public function getTarget()
+    {
+        return $this->target;
+    }
+
+    /**
+     * Set parameters
+     *
+     * Overwrites parameters
+     * 
+     * @param  array|ArrayAccess|object $params 
+     * @return Event
+     */
+    public function setParams($params)
+    {
+        if (!is_array($params) && !is_object($params)) {
+            require_once 'Zend/EventManager/Exception/InvalidArgumentException.php';
+            throw new Zend_EventManager_Exception_InvalidArgumentException(sprintf(
+                'Event parameters must be an array or object; received "%s"',
+                (is_object($params) ? get_class($params) : gettype($params))
+            ));
+        }
+
+        $this->params = $params;
+        return $this;
+    }
+
+    /**
+     * Get all parameters
+     * 
+     * @return array|object|ArrayAccess
+     */
+    public function getParams()
+    {
+        return $this->params;
+    }
+
+    /**
+     * Get an individual parameter
+     *
+     * If the parameter does not exist, the $default value will be returned.
+     * 
+     * @param  string|int $name 
+     * @param  mixed $default 
+     * @return mixed
+     */
+    public function getParam($name, $default = null)
+    {
+        // Check in params that are arrays or implement array access
+        if (is_array($this->params) || $this->params instanceof ArrayAccess) {
+            if (!isset($this->params[$name])) {
+                return $default;
+            }
+
+            return $this->params[$name];
+        }
+
+        // Check in normal objects
+        if (!isset($this->params->{$name})) {
+            return $default;
+        }
+        return $this->params->{$name};
+    }
+
+    /**
+     * Set the event name
+     * 
+     * @param  string $name 
+     * @return Zend_EventManager_Event
+     */
+    public function setName($name)
+    {
+        $this->name = (string) $name;
+        return $this;
+    }
+
+    /**
+     * Set the event target/context
+     * 
+     * @param  null|string|object $target 
+     * @return Zend_EventManager_Event
+     */
+    public function setTarget($target)
+    {
+        $this->target = $target;
+        return $this;
+    }
+
+    /**
+     * Set an individual parameter to a value
+     * 
+     * @param  string|int $name 
+     * @param  mixed $value 
+     * @return Zend_EventManager_Event
+     */
+    public function setParam($name, $value)
+    {
+        if (is_array($this->params) || $this->params instanceof ArrayAccess) {
+            // Arrays or objects implementing array access
+            $this->params[$name] = $value;
+        } else {
+            // Objects
+            $this->params->{$name} = $value;
+        }
+        return $this;
+    }
+
+    /**
+     * Stop further event propagation
+     * 
+     * @param  bool $flag 
+     * @return void
+     */
+    public function stopPropagation($flag = true)
+    {
+        $this->stopPropagation = (bool) $flag;
+    }
+
+    /**
+     * Is propagation stopped?
+     * 
+     * @return bool
+     */
+    public function propagationIsStopped()
+    {
+        return $this->stopPropagation;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/EventManager/EventCollection.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,109 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_EventManager
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+require_once 'Zend/Stdlib/CallbackHandler.php';
+
+/**
+ * Interface for messengers
+ *
+ * @category   Zend
+ * @package    Zend_EventManager
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+interface Zend_EventManager_EventCollection
+{
+    /**
+     * Trigger an event
+     *
+     * Should allow handling the following scenarios:
+     * - Passing Event object only
+     * - Passing event name and Event object only
+     * - Passing event name, target, and Event object
+     * - Passing event name, target, and array|ArrayAccess of arguments
+     *
+     * Can emulate triggerUntil() if the last argument provided is a callback.
+     * 
+     * @param  string $event 
+     * @param  object|string $target 
+     * @param  array|object $argv 
+     * @param  null|callback $callback 
+     * @return Zend_EventManager_ResponseCollection
+     */
+    public function trigger($event, $target = null, $argv = array(), $callback = null);
+
+    /**
+     * Trigger an event until the given callback returns a boolean false
+     *
+     * Should allow handling the following scenarios:
+     * - Passing Event object and callback only
+     * - Passing event name, Event object, and callback only
+     * - Passing event name, target, Event object, and callback
+     * - Passing event name, target, array|ArrayAccess of arguments, and callback
+     * 
+     * @param  string $event 
+     * @param  object|string $target 
+     * @param  array|object $argv 
+     * @param  callback $callback 
+     * @return Zend_EventManager_ResponseCollection
+     */
+    public function triggerUntil($event, $target, $argv = null, $callback = null);
+
+    /**
+     * Attach a listener to an event
+     * 
+     * @param  string $event 
+     * @param  callback $callback
+     * @param  int $priority Priority at which to register listener
+     * @return Zend_Stdlib_CallbackHandler
+     */
+    public function attach($event, $callback = null, $priority = 1);
+
+    /**
+     * Detach an event listener
+     * 
+     * @param  Zend_Stdlib_CallbackHandler|Zend_EventManager_ListenerAggregate $listener 
+     * @return void
+     */
+    public function detach($listener);
+
+    /**
+     * Get a list of events for which this collection has listeners
+     * 
+     * @return array
+     */
+    public function getEvents();
+
+    /**
+     * Retrieve a list of listeners registered to a given event
+     * 
+     * @param  string $event 
+     * @return array|object
+     */
+    public function getListeners($event);
+
+    /**
+     * Clear all listeners for a given event
+     * 
+     * @param  string $event 
+     * @return void
+     */
+    public function clearListeners($event);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/EventManager/EventDescription.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,108 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_EventManager
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+/**
+ * Representation of an event
+ *
+ * @category   Zend
+ * @package    Zend_EventManager
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+interface Zend_EventManager_EventDescription
+{
+    /**
+     * Get event name
+     * 
+     * @return string
+     */
+    public function getName();
+
+    /**
+     * Get target/context from which event was triggered
+     * 
+     * @return null|string|object
+     */
+    public function getTarget();
+
+    /**
+     * Get parameters passed to the event
+     * 
+     * @return array|ArrayAccess
+     */
+    public function getParams();
+
+    /**
+     * Get a single parameter by name
+     * 
+     * @param  string $name 
+     * @param  mixed $default Default value to return if parameter does not exist
+     * @return mixed
+     */
+    public function getParam($name, $default = null);
+
+    /**
+     * Set the event name
+     * 
+     * @param  string $name 
+     * @return void
+     */
+    public function setName($name);
+
+    /**
+     * Set the event target/context
+     * 
+     * @param  null|string|object $target 
+     * @return void
+     */
+    public function setTarget($target);
+
+    /**
+     * Set event parameters
+     * 
+     * @param  string $params 
+     * @return void
+     */
+    public function setParams($params);
+
+    /**
+     * Set a single parameter by key
+     * 
+     * @param  string $name 
+     * @param  mixed $value 
+     * @return void
+     */
+    public function setParam($name, $value);
+
+    /**
+     * Indicate whether or not the parent EventCollection should stop propagating events
+     * 
+     * @param  bool $flag 
+     * @return void
+     */
+    public function stopPropagation($flag = true);
+
+    /**
+     * Has this event indicated event propagation should stop?
+     * 
+     * @return bool
+     */
+    public function propagationIsStopped();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/EventManager/EventManager.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,551 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_EventManager
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+require_once 'Zend/EventManager/Event.php';
+require_once 'Zend/EventManager/EventCollection.php';
+require_once 'Zend/EventManager/ResponseCollection.php';
+require_once 'Zend/EventManager/SharedEventCollectionAware.php';
+require_once 'Zend/EventManager/StaticEventManager.php';
+require_once 'Zend/Stdlib/CallbackHandler.php';
+require_once 'Zend/Stdlib/PriorityQueue.php';
+
+/**
+ * Event manager: notification system
+ *
+ * Use the EventManager when you want to create a per-instance notification
+ * system for your objects.
+ *
+ * @category   Zend
+ * @package    Zend_EventManager
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_EventManager_EventManager implements Zend_EventManager_EventCollection, Zend_EventManager_SharedEventCollectionAware
+{
+    /**
+     * Subscribed events and their listeners
+     * @var array Array of Zend_Stdlib_PriorityQueue objects
+     */
+    protected $events = array();
+
+    /**
+     * @var string Class representing the event being emitted
+     */
+    protected $eventClass = 'Zend_EventManager_Event';
+
+    /**
+     * Identifiers, used to pull static signals from StaticEventManager
+     * @var array
+     */
+    protected $identifiers = array();
+
+    /**
+     * Static collections
+     * @var false|null|Zend_EventManager_StaticEventCollection
+     */
+    protected $sharedCollections = null;
+
+    /**
+     * Constructor
+     *
+     * Allows optionally specifying identifier(s) to use to pull signals from a
+     * StaticEventManager.
+     *
+     * @param  null|string|int|array|Traversable $identifiers
+     * @return void
+     */
+    public function __construct($identifiers = null)
+    {
+        $this->setIdentifiers($identifiers);
+    }
+
+    /**
+     * Set the event class to utilize
+     *
+     * @param  string $class
+     * @return Zend_EventManager_EventManager
+     */
+    public function setEventClass($class)
+    {
+        $this->eventClass = $class;
+        return $this;
+    }
+
+    /**
+     * Set static collections container
+     *
+     * @param  Zend_EventManager_StaticEventCollection $collections
+     * @return void
+     */
+    public function setSharedCollections(Zend_EventManager_SharedEventCollection $collections)
+    {
+        $this->sharedCollections = $collections;
+        return $this;
+    }
+
+    /**
+     * Remove any shared collections
+     *
+     * Sets {@link $sharedCollections} to boolean false to disable ability
+     * to lazy-load static event manager instance.
+     * 
+     * @return void
+     */
+    public function unsetSharedCollections()
+    {
+        $this->sharedCollections = false;
+    }
+
+    /**
+     * Get static collections container
+     *
+     * @return false|Zend_EventManager_SharedEventCollection
+     */
+    public function getSharedCollections()
+    {
+        if (null === $this->sharedCollections) {
+            $this->setSharedCollections(Zend_EventManager_StaticEventManager::getInstance());
+        }
+        return $this->sharedCollections;
+    }
+
+    /**
+     * Get the identifier(s) for this Zend_EventManager_EventManager
+     *
+     * @return array
+     */
+    public function getIdentifiers()
+    {
+        return $this->identifiers;
+    }
+
+    /**
+     * Set the identifiers (overrides any currently set identifiers)
+     *
+     * @param string|int|array|Traversable $identifiers
+     * @return Zend_EventManager_EventManager
+     */
+    public function setIdentifiers($identifiers)
+    {
+        if (is_array($identifiers) || $identifiers instanceof Traversable) {
+            $this->identifiers = array_unique((array) $identifiers);
+        } elseif ($identifiers !== null) {
+            $this->identifiers = array($identifiers);
+        }
+        return $this;
+    }
+
+    /**
+     * Add some identifier(s) (appends to any currently set identifiers)
+     *
+     * @param string|int|array|Traversable $identifiers
+     * @return Zend_EventManager_EventManager
+     */
+    public function addIdentifiers($identifiers)
+    {
+        if (is_array($identifiers) || $identifiers instanceof Traversable) {
+            $this->identifiers = array_unique($this->identifiers + (array) $identifiers);
+        } elseif ($identifiers !== null) {
+            $this->identifiers = array_unique(array_merge($this->identifiers, array($identifiers)));
+        }
+        return $this;
+    }
+
+    /**
+     * Trigger all listeners for a given event
+     *
+     * Can emulate triggerUntil() if the last argument provided is a callback.
+     *
+     * @param  string $event
+     * @param  string|object $target Object calling emit, or symbol describing target (such as static method name)
+     * @param  array|ArrayAccess $argv Array of arguments; typically, should be associative
+     * @param  null|callback $callback
+     * @return Zend_EventManager_ResponseCollection All listener return values
+     */
+    public function trigger($event, $target = null, $argv = array(), $callback = null)
+    {
+        if ($event instanceof Zend_EventManager_EventDescription) {
+            $e        = $event;
+            $event    = $e->getName();
+            $callback = $target;
+        } elseif ($target instanceof Zend_EventManager_EventDescription) {
+            $e = $target;
+            $e->setName($event);
+            $callback = $argv;
+        } elseif ($argv instanceof Zend_EventManager_EventDescription) {
+            $e = $argv;
+            $e->setName($event);
+            $e->setTarget($target);
+        } else {
+            $e = new $this->eventClass();
+            $e->setName($event);
+            $e->setTarget($target);
+            $e->setParams($argv);
+        }
+
+        if ($callback && !is_callable($callback)) {
+            require_once 'Zend/Stdlib/Exception/InvalidCallbackException.php';
+            throw new Zend_Stdlib_Exception_InvalidCallbackException('Invalid callback provided');
+        }
+
+        return $this->triggerListeners($event, $e, $callback);
+    }
+
+    /**
+     * Trigger listeners until return value of one causes a callback to
+     * evaluate to true
+     *
+     * Triggers listeners until the provided callback evaluates the return
+     * value of one as true, or until all listeners have been executed.
+     *
+     * @param  string $event
+     * @param  string|object $target Object calling emit, or symbol describing target (such as static method name)
+     * @param  array|ArrayAccess $argv Array of arguments; typically, should be associative
+     * @param  Callable $callback
+     * @throws Zend_Stdlib_Exception_InvalidCallbackException if invalid callback provided
+     */
+    public function triggerUntil($event, $target, $argv = null, $callback = null)
+    {
+        if ($event instanceof Zend_EventManager_EventDescription) {
+            $e        = $event;
+            $event    = $e->getName();
+            $callback = $target;
+        } elseif ($target instanceof Zend_EventManager_EventDescription) {
+            $e = $target;
+            $e->setName($event);
+            $callback = $argv;
+        } elseif ($argv instanceof Zend_EventManager_EventDescription) {
+            $e = $argv;
+            $e->setName($event);
+            $e->setTarget($target);
+        } else {
+            $e = new $this->eventClass();
+            $e->setName($event);
+            $e->setTarget($target);
+            $e->setParams($argv);
+        }
+
+        if (!is_callable($callback)) {
+            require_once 'Zend/Stdlib/Exception/InvalidCallbackException.php';
+            throw new Zend_Stdlib_Exception_InvalidCallbackException('Invalid callback provided');
+        }
+
+        return $this->triggerListeners($event, $e, $callback);
+    }
+
+    /**
+     * Attach a listener to an event
+     *
+     * The first argument is the event, and the next argument describes a
+     * callback that will respond to that event. A CallbackHandler instance
+     * describing the event listener combination will be returned.
+     *
+     * The last argument indicates a priority at which the event should be
+     * executed. By default, this value is 1; however, you may set it for any
+     * integer value. Higher values have higher priority (i.e., execute first).
+     *
+     * You can specify "*" for the event name. In such cases, the listener will 
+     * be triggered for every event.
+     *
+     * @param  string|array|Zend_EventManager_ListenerAggregate $event An event or array of event names. If a ListenerAggregate, proxies to {@link attachAggregate()}.
+     * @param  callback|int $callback If string $event provided, expects PHP callback; for a ListenerAggregate $event, this will be the priority
+     * @param  int $priority If provided, the priority at which to register the callback
+     * @return Zend_Stdlib_CallbackHandler|mixed CallbackHandler if attaching callback (to allow later unsubscribe); mixed if attaching aggregate
+     */
+    public function attach($event, $callback = null, $priority = 1)
+    {
+        // Proxy ListenerAggregate arguments to attachAggregate()
+        if ($event instanceof Zend_EventManager_ListenerAggregate) {
+            return $this->attachAggregate($event, $callback);
+        }
+
+        // Null callback is invalid
+        if (null === $callback) {
+            require_once 'Zend/EventManager/Exception/InvalidArgumentException.php';
+            throw new Zend_EventManager_Exception_InvalidArgumentException(sprintf(
+                '%s: expects a callback; none provided',
+                __METHOD__
+            ));
+        }
+
+        // Array of events should be registered individually, and return an array of all listeners
+        if (is_array($event)) {
+            $listeners = array();
+            foreach ($event as $name) {
+                $listeners[] = $this->attach($name, $callback, $priority);
+            }
+            return $listeners;
+        }
+
+        // If we don't have a priority queue for the event yet, create one
+        if (empty($this->events[$event])) {
+            $this->events[$event] = new Zend_Stdlib_PriorityQueue();
+        }
+
+        // Create a callback handler, setting the event and priority in its metadata
+        $listener = new Zend_Stdlib_CallbackHandler($callback, array('event' => $event, 'priority' => $priority));
+
+        // Inject the callback handler into the queue
+        $this->events[$event]->insert($listener, $priority);
+        return $listener;
+    }
+
+    /**
+     * Attach a listener aggregate
+     *
+     * Listener aggregates accept an EventCollection instance, and call attach()
+     * one or more times, typically to attach to multiple events using local
+     * methods.
+     *
+     * @param  Zend_EventManager_ListenerAggregate $aggregate
+     * @param  int $priority If provided, a suggested priority for the aggregate to use
+     * @return mixed return value of {@link Zend_EventManager_ListenerAggregate::attach()}
+     */
+    public function attachAggregate(Zend_EventManager_ListenerAggregate $aggregate, $priority = 1)
+    {
+        return $aggregate->attach($this, $priority);
+    }
+
+    /**
+     * Unsubscribe a listener from an event
+     *
+     * @param  Zend_Stdlib_CallbackHandler|Zend_EventManager_ListenerAggregate $listener
+     * @return bool Returns true if event and listener found, and unsubscribed; returns false if either event or listener not found
+     * @throws Zend_EventManager_Exception_InvalidArgumentException if invalid listener provided
+     */
+    public function detach($listener)
+    {
+        if ($listener instanceof Zend_EventManager_ListenerAggregate) {
+            return $this->detachAggregate($listener);
+        }
+
+        if (!$listener instanceof Zend_Stdlib_CallbackHandler) {
+            require_once 'Zend/EventManager/Exception/InvalidArgumentException.php';
+            throw new Zend_EventManager_Exception_InvalidArgumentException(sprintf(
+                '%s: expected a Zend_EventManager_ListenerAggregate or Zend_Stdlib_CallbackHandler; received "%s"',
+                __METHOD__,
+                (is_object($listener) ? get_class($listener) : gettype($listener))
+            ));
+        }
+
+        $event = $listener->getMetadatum('event');
+        if (!$event || empty($this->events[$event])) {
+            return false;
+        }
+        $return = $this->events[$event]->remove($listener);
+        if (!$return) {
+            return false;
+        }
+        if (!count($this->events[$event])) {
+            unset($this->events[$event]);
+        }
+        return true;
+    }
+
+    /**
+     * Detach a listener aggregate
+     *
+     * Listener aggregates accept an EventCollection instance, and call detach()
+     * of all previously attached listeners.
+     *
+     * @param  Zend_EventManager_ListenerAggregate $aggregate
+     * @return mixed return value of {@link Zend_EventManager_ListenerAggregate::detach()}
+     */
+    public function detachAggregate(Zend_EventManager_ListenerAggregate $aggregate)
+    {
+        return $aggregate->detach($this);
+    }
+
+    /**
+     * Retrieve all registered events
+     *
+     * @return array
+     */
+    public function getEvents()
+    {
+        return array_keys($this->events);
+    }
+
+    /**
+     * Retrieve all listeners for a given event
+     *
+     * @param  string $event
+     * @return Zend_Stdlib_PriorityQueue
+     */
+    public function getListeners($event)
+    {
+        if (!array_key_exists($event, $this->events)) {
+            return new Zend_Stdlib_PriorityQueue();
+        }
+        return $this->events[$event];
+    }
+
+    /**
+     * Clear all listeners for a given event
+     *
+     * @param  string $event
+     * @return void
+     */
+    public function clearListeners($event)
+    {
+        if (!empty($this->events[$event])) {
+            unset($this->events[$event]);
+        }
+    }
+
+    /**
+     * Prepare arguments
+     *
+     * Use this method if you want to be able to modify arguments from within a
+     * listener. It returns an ArrayObject of the arguments, which may then be
+     * passed to trigger() or triggerUntil().
+     *
+     * @param  array $args
+     * @return ArrayObject
+     */
+    public function prepareArgs(array $args)
+    {
+        return new ArrayObject($args);
+    }
+
+    /**
+     * Trigger listeners
+     *
+     * Actual functionality for triggering listeners, to which both trigger() and triggerUntil()
+     * delegate.
+     *
+     * @param  string           $event Event name
+     * @param  EventDescription $e
+     * @param  null|callback    $callback
+     * @return ResponseCollection
+     */
+    protected function triggerListeners($event, Zend_EventManager_EventDescription $e, $callback = null)
+    {
+        $responses = new Zend_EventManager_ResponseCollection;
+        $listeners = $this->getListeners($event);
+
+        // Add shared/wildcard listeners to the list of listeners,
+        // but don't modify the listeners object
+        $sharedListeners         = $this->getSharedListeners($event);
+        $sharedWildcardListeners = $this->getSharedListeners('*');
+        $wildcardListeners       = $this->getListeners('*');
+        if (count($sharedListeners) || count($sharedWildcardListeners) || count($wildcardListeners)) {
+            $listeners = clone $listeners;
+        }
+
+        // Shared listeners on this specific event
+        $this->insertListeners($listeners, $sharedListeners);
+
+        // Shared wildcard listeners
+        $this->insertListeners($listeners, $sharedWildcardListeners);
+
+        // Add wildcard listeners
+        $this->insertListeners($listeners, $wildcardListeners);
+
+        if ($listeners->isEmpty()) {
+            return $responses;
+        }
+
+        foreach ($listeners as $listener) {
+            // Trigger the listener's callback, and push its result onto the
+            // response collection
+            $responses->push(call_user_func($listener->getCallback(), $e));
+
+            // If the event was asked to stop propagating, do so
+            if ($e->propagationIsStopped()) {
+                $responses->setStopped(true);
+                break;
+            }
+
+            // If the result causes our validation callback to return true,
+            // stop propagation
+            if ($callback && call_user_func($callback, $responses->last())) {
+                $responses->setStopped(true);
+                break;
+            }
+        }
+
+        return $responses;
+    }
+
+    /**
+     * Get list of all listeners attached to the shared collection for
+     * identifiers registered by this instance
+     *
+     * @param  string $event
+     * @return array
+     */
+    protected function getSharedListeners($event)
+    {
+        if (!$sharedCollections = $this->getSharedCollections()) {
+            return array();
+        }
+
+        $identifiers     = $this->getIdentifiers();
+        $sharedListeners = array();
+
+        foreach ($identifiers as $id) {
+            if (!$listeners = $sharedCollections->getListeners($id, $event)) {
+                continue;
+            }
+
+            if (!is_array($listeners) && !($listeners instanceof Traversable)) {
+                continue;
+            }
+
+            foreach ($listeners as $listener) {
+                if (!$listener instanceof Zend_Stdlib_CallbackHandler) {
+                    continue;
+                }
+                $sharedListeners[] = $listener;
+            }
+        }
+
+        return $sharedListeners;
+    }
+
+    /**
+     * Add listeners to the master queue of listeners
+     *
+     * Used to inject shared listeners and wildcard listeners.
+     * 
+     * @param  Zend_Stdlib_PriorityQueue $masterListeners 
+     * @param  Zend_Stdlib_PriorityQueue $listeners 
+     * @return void
+     */
+    protected function insertListeners($masterListeners, $listeners)
+    {
+        if (!count($listeners)) {
+            return;
+        }
+
+        foreach ($listeners as $listener) {
+            $priority = $listener->getMetadatum('priority');
+            if (null === $priority) {
+                $priority = 1;
+            } elseif (is_array($priority)) {
+                // If we have an array, likely using PriorityQueue. Grab first
+                // element of the array, as that's the actual priority.
+                $priority = array_shift($priority);
+            }
+            $masterListeners->insert($listener, $priority);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/EventManager/EventManagerAware.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,40 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_EventManager
+ * @subpackage UnitTest
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+/**
+ * Interface to automate setter injection for an EventManager instance
+ *
+ * @category   Zend
+ * @package    Zend_EventManager
+ * @subpackage UnitTest
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+interface Zend_EventManager_EventManagerAware
+{
+    /**
+     * Inject an EventManager instance
+     * 
+     * @param  Zend_EventManager_EventCollection $eventManager 
+     * @return void
+     */
+    public function setEventManager(Zend_EventManager_EventCollection $eventManager);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/EventManager/Exception.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,31 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_EventManager
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+/**
+ * Base exception interface
+ *
+ * @category   Zend
+ * @package    Zend_EventManager
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+interface Zend_EventManager_Exception
+{
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/EventManager/Exception/InvalidArgumentException.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,42 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_EventManager
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+/**
+ * @see Zend_Exception
+ */
+require_once 'Zend/Exception.php';
+
+/**
+ * @see Zend_EventManager_Exception
+ */
+require_once 'Zend/EventManager/Exception.php';
+
+/**
+ * Invalid argument exception
+ *
+ * @category   Zend
+ * @package    Zend_EventManager
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_EventManager_Exception_InvalidArgumentException
+    extends Zend_Exception implements Zend_EventManager_Exception
+{
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/EventManager/Filter.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,78 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_EventManager
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+require_once 'Zend/Stdlib/CallbackHandler.php';
+
+/**
+ * Interface for intercepting filter chains
+ *
+ * @category   Zend
+ * @package    Zend_EventManager
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+interface Zend_EventManager_Filter
+{
+    /**
+     * Execute the filter chain
+     * 
+     * @param  string|object $context 
+     * @param  array $params 
+     * @return mixed
+     */
+    public function run($context, array $params = array());
+
+    /**
+     * Attach an intercepting filter
+     * 
+     * @param  callback $callback 
+     * @return Zend_Stdlib_CallbackHandler
+     */
+    public function attach($callback);
+
+    /**
+     * Detach an intercepting filter
+     * 
+     * @param  Zend_Stdlib_CallbackHandler $filter 
+     * @return bool
+     */
+    public function detach(Zend_Stdlib_CallbackHandler $filter);
+
+    /**
+     * Get all intercepting filters
+     * 
+     * @return array
+     */
+    public function getFilters();
+
+    /**
+     * Clear all filters
+     * 
+     * @return void
+     */
+    public function clearFilters();
+
+    /**
+     * Get all filter responses
+     * 
+     * @return Zend_EventManager_ResponseCollection
+     */
+    public function getResponses();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/EventManager/Filter/FilterIterator.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,113 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_EventManager
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+require_once 'Zend/Stdlib/CallbackHandler.php';
+require_once 'Zend/Stdlib/SplPriorityQueue.php';
+
+/**
+ * Specialized priority queue implementation for use with an intercepting 
+ * filter chain.
+ *
+ * Allows removal
+ *
+ * @category   Zend
+ * @package    Zend_EventManager
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_EventManager_Filter_FilterIterator extends Zend_Stdlib_SplPriorityQueue
+{
+    /**
+     * Does the queue contain a given value?
+     * 
+     * @param  mixed $datum 
+     * @return bool
+     */
+    public function contains($datum)
+    {
+        $chain = clone $this;
+        foreach ($chain as $item) {
+            if ($item === $datum) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Remove a value from the queue
+     *
+     * This is an expensive operation. It must first iterate through all values,
+     * and then re-populate itself. Use only if absolutely necessary.
+     * 
+     * @param  mixed $datum 
+     * @return bool
+     */
+    public function remove($datum)
+    {
+        $this->setExtractFlags(self::EXTR_BOTH);
+
+        // Iterate and remove any matches
+        $removed = false;
+        $items   = array();
+        $this->rewind();
+        while (!$this->isEmpty()) {
+            $item = $this->extract();
+            if ($item['data'] === $datum) {
+                $removed = true;
+                continue;
+            }
+            $items[] = $item;
+        }
+
+        // Repopulate
+        foreach ($items as $item) {
+            $this->insert($item['data'], $item['priority']);
+        }
+
+        $this->setExtractFlags(self::EXTR_DATA);
+        return $removed;
+    }
+
+    /**
+     * Iterate the next filter in the chain
+     *
+     * Iterates and calls the next filter in the chain.
+     * 
+     * @param  mixed $context 
+     * @param  array $params 
+     * @param  Zend_EventManager_Filter_FilterIterator $chain 
+     * @return void
+     */
+    public function next($context = null, array $params = array(), $chain = null)
+    {
+        if (empty($context) || $chain->isEmpty()) {
+            return;
+        }
+
+        $next = $this->extract();
+        if (!$next instanceof Zend_Stdlib_CallbackHandler) {
+            return;
+        }
+
+        $return = call_user_func($next->getCallback(), $context, $params, $chain);
+        return $return;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/EventManager/FilterChain.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,138 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_EventManager
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+require_once 'Zend/EventManager/Filter.php';
+require_once 'Zend/EventManager/Filter/FilterIterator.php';
+require_once 'Zend/Stdlib/CallbackHandler.php';
+
+/**
+ * FilterChain: intercepting filter manager
+ *
+ * @category   Zend
+ * @package    Zend_EventManager
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_EventManager_FilterChain implements Zend_EventManager_Filter
+{
+    /**
+     * @var Zend_EventManager_Filter_FilterIterator All filters
+     */
+    protected $filters;
+
+    /**
+     * Constructor
+     *
+     * Initializes Zend_EventManager_Filter_FilterIterator in which filters will be aggregated
+     * 
+     * @return void
+     */
+    public function __construct()
+    {
+        $this->filters = new Zend_EventManager_Filter_FilterIterator();
+    }
+
+    /**
+     * Apply the filters
+     *
+     * Begins iteration of the filters.
+     * 
+     * @param  mixed $context Object under observation
+     * @param  mixed $argv Associative array of arguments
+     * @return mixed
+     */
+    public function run($context, array $argv = array())
+    {
+        $chain = clone $this->getFilters();
+
+        if ($chain->isEmpty()) {
+            return;
+        }
+
+        $next = $chain->extract();
+        if (!$next instanceof Zend_Stdlib_CallbackHandler) {
+            return;
+        }
+
+        return call_user_func($next->getCallback(), $context, $argv, $chain);
+    }
+
+    /**
+     * Connect a filter to the chain
+     * 
+     * @param  callback $callback PHP Callback
+     * @param  int $priority Priority in the queue at which to execute; defaults to 1 (higher numbers == higher priority)
+     * @return Zend_Stdlib_CallbackHandler (to allow later unsubscribe)
+     */
+    public function attach($callback, $priority = 1)
+    {
+        if (empty($callback)) {
+            require_once 'Zend/Stdlib/Exception/InvalidCallbackException.php';
+            throw new Zend_Stdlib_Exception_InvalidCallbackException('No callback provided');
+        }
+        $filter = new Zend_Stdlib_CallbackHandler($callback, array('priority' => $priority));
+        $this->filters->insert($filter, $priority);
+        return $filter;
+    }
+
+    /**
+     * Detach a filter from the chain
+     * 
+     * @param  Zend_Stdlib_CallbackHandler $filter 
+     * @return bool Returns true if filter found and unsubscribed; returns false otherwise
+     */
+    public function detach(Zend_Stdlib_CallbackHandler $filter)
+    {
+        return $this->filters->remove($filter);
+    }
+
+    /**
+     * Retrieve all filters
+     * 
+     * @return Zend_EventManager_Filter_FilterIterator
+     */
+    public function getFilters()
+    {
+        return $this->filters;
+    }
+
+    /**
+     * Clear all filters
+     * 
+     * @return void
+     */
+    public function clearFilters()
+    {
+        $this->filters = new Zend_EventManager_Filter_FilterIterator();
+    }
+
+    /**
+     * Return current responses
+     *
+     * Only available while the chain is still being iterated. Returns the 
+     * current ResponseCollection.
+     * 
+     * @return null|Zend_EventManager_ResponseCollection
+     */
+    public function getResponses()
+    {
+        return $this->responses;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/EventManager/GlobalEventManager.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,149 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_EventManager
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+require_once 'Zend/Stdlib/CallbackHandler.php';
+require_once 'Zend/Stdlib/PriorityQueue.php';
+
+/**
+ * Event manager: notification system
+ *
+ * Use the EventManager when you want to create a per-instance notification 
+ * system for your objects.
+ *
+ * @category   Zend
+ * @package    Zend_EventManager
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_EventManager_GlobalEventManager
+{
+    /**
+     * @var Zend_EventManager_EventCollection
+     */
+    protected static $events;
+
+    /**
+     * Set the event collection on which this will operate
+     * 
+     * @param  null|Zend_EventManager_EventCollection $events 
+     * @return void
+     */
+    public static function setEventCollection(Zend_EventManager_EventCollection $events = null)
+    {
+        self::$events = $events;
+    }
+
+    /**
+     * Get event collection on which this operates
+     * 
+     * @return void
+     */
+    public static function getEventCollection()
+    {
+        if (null === self::$events) {
+            self::setEventCollection(new Zend_EventManager_EventManager());
+        }
+        return self::$events;
+    }
+
+    /**
+     * Trigger an event
+     * 
+     * @param  string $event 
+     * @param  object|string $context 
+     * @param  array|object $argv 
+     * @return Zend_EventManager_ResponseCollection
+     */
+    public static function trigger($event, $context, $argv = array())
+    {
+        return self::getEventCollection()->trigger($event, $context, $argv);
+    }
+
+    /**
+     * Trigger listeenrs until return value of one causes a callback to evaluate 
+     * to true.
+     * 
+     * @param  string $event 
+     * @param  string|object $context 
+     * @param  array|object $argv 
+     * @param  callback $callback 
+     * @return Zend_EventManager_ResponseCollection
+     */
+    public static function triggerUntil($event, $context, $argv, $callback)
+    {
+        return self::getEventCollection()->triggerUntil($event, $context, $argv, $callback);
+    }
+
+    /**
+     * Attach a listener to an event
+     * 
+     * @param  string $event 
+     * @param  callback $callback 
+     * @param  int $priority 
+     * @return Zend_Stdlib_CallbackHandler
+     */
+    public static function attach($event, $callback, $priority = 1)
+    {
+        return self::getEventCollection()->attach($event, $callback, $priority);
+    }
+
+    /**
+     * Detach a callback from a listener
+     * 
+     * @param  Zend_Stdlib_CallbackHandler $listener 
+     * @return bool
+     */
+    public static function detach(Zend_Stdlib_CallbackHandler $listener)
+    {
+        return self::getEventCollection()->detach($listener);
+    }
+
+    /**
+     * Retrieve list of events this object manages
+     * 
+     * @return array
+     */
+    public static function getEvents()
+    {
+        return self::getEventCollection()->getEvents();
+    }
+
+    /**
+     * Retrieve all listeners for a given event
+     * 
+     * @param  string $event 
+     * @return Zend_Stdlib_PriorityQueue|array
+     */
+    public static function getListeners($event)
+    {
+        return self::getEventCollection()->getListeners($event);
+    }
+
+    /**
+     * Clear all listeners for a given event
+     * 
+     * @param  string $event 
+     * @return void
+     */
+    public static function clearListeners($event)
+    {
+        return self::getEventCollection()->clearListeners($event);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/EventManager/ListenerAggregate.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,53 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_EventManager
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+/**
+ * Interface for self-registering event listeners.
+ *
+ * Classes implementing this interface may be registered by name or instance
+ * with an EventManager, without an event name. The {@link attach()} method will
+ * then be called with the current EventManager instance, allowing the class to
+ * wire up one or more listeners.
+ *
+ * @category   Zend
+ * @package    Zend_EventManager
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+interface Zend_EventManager_ListenerAggregate
+{
+    /**
+     * Attach one or more listeners
+     *
+     * Implementors may add an optional $priority argument; the EventManager
+     * implementation will pass this to the aggregate.
+     *
+     * @param Zend_EventManager_EventCollection $events
+     * @param null|int $priority Optional priority "hint" to use when attaching listeners
+     */
+    public function attach(Zend_EventManager_EventCollection $events);
+
+    /**
+     * Detach all previously attached listeners
+     *
+     * @param Zend_EventManager_EventCollection $events
+     */
+    public function detach(Zend_EventManager_EventCollection $events);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/EventManager/ResponseCollection.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,424 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_EventManager
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+if (version_compare(PHP_VERSION, '5.3.0', '<')) {
+    class SplStack implements Iterator, ArrayAccess, Countable
+    {
+        /**
+         * Delete items during iteration
+         */
+        const IT_MODE_DELETE = 1;
+
+        /**
+         * Keep items during iteration
+         */
+        const IT_MODE_KEEP = 0;
+
+        /**
+         * Mode used when iterating
+         * @var int
+         */
+        protected $mode = self::IT_MODE_KEEP;
+
+        /**
+         * Count of elements in the stack 
+         * 
+         * @var int
+         */
+        protected $count = 0;
+
+        /**
+         * Data represented by this stack
+         * 
+         * @var array
+         */
+        protected $data = array();
+
+        /**
+         * Sorted stack of values
+         * 
+         * @var false|array
+         */
+        protected $stack = false;
+
+        /**
+         * Set the iterator mode
+         *
+         * Must be set to one of IT_MODE_DELETE or IT_MODE_KEEP
+         * 
+         * @todo   Currently, IteratorMode is ignored, as we use the default (keep); should this be implemented?
+         * @param  int $mode 
+         * @return void
+         * @throws InvalidArgumentException
+         */
+        public function setIteratorMode($mode)
+        {
+            $expected = array(
+                self::IT_MODE_DELETE => true,
+                self::IT_MODE_KEEP => true,
+            );
+
+            if (!isset($expected[$mode])) {
+                throw new InvalidArgumentException(sprintf('Invalid iterator mode specified ("%s")', $mode));
+            }
+
+            $this->mode = $mode;
+        }
+
+        /**
+         * Return last element in the stack
+         * 
+         * @return mixed
+         */
+        public function bottom()
+        {
+            $this->rewind();
+            $value = array_pop($this->stack);
+            array_push($this->stack, $value);
+            return $value;
+        }
+
+        /**
+         * Countable: return count of items in the stack
+         * 
+         * @return int
+         */
+        public function count()
+        {
+            return $this->count;
+        }
+
+        /**
+         * Iterator: return current item in the stack
+         * 
+         * @return mixed
+         */
+        public function current()
+        {
+            if (!$this->stack) {
+                $this->rewind();
+            }
+            return current($this->stack);
+        }
+
+        /**
+         * Get iteration mode
+         * 
+         * @return int
+         */
+        public function getIteratorMode()
+        {
+            return $this->mode;
+        }
+
+        /**
+         * Is the stack empty?
+         *
+         * @return bool
+         */
+        public function isEmpty()
+        {
+            return ($this->count === 0);
+        }
+
+        /**
+         * Iterator: return key of current item in the stack
+         *
+         * @return mixed
+         */
+        public function key()
+        {
+            if (!$this->stack) {
+                $this->rewind();
+            }
+            return key($this->stack);
+        }
+
+        /**
+         * Iterator: advance pointer to next item in the stack
+         * 
+         * @return void
+         */
+        public function next()
+        {
+            if (!$this->stack) {
+                $this->rewind();
+            }
+            return next($this->stack);
+        }
+
+        /**
+         * ArrayAccess: does an item exist at the specified offset?
+         * 
+         * @param  mixed $index 
+         * @return bool
+         */
+        public function offsetExists($index)
+        {
+            return array_key_exists($index, $this->data);
+        }
+
+        /**
+         * ArrayAccess: get the item at the specified offset
+         * 
+         * @param  mixed $index 
+         * @return mixed
+         * @throws OutOfRangeException
+         */
+        public function offsetGet($index)
+        {
+            if (!$this->offsetExists($index)) {
+                throw OutOfRangeException(sprintf('Invalid index ("%s") specified', $index));
+            }
+            return $this->data[$index];
+        }
+
+        /**
+         * ArrayAccess: add an item at the specified offset
+         * 
+         * @param  mixed $index 
+         * @param  mixed $newval 
+         * @return void
+         */
+        public function offsetSet($index, $newval)
+        {
+            $this->data[$index] = $newval;
+            $this->stack = false;
+            $this->count++;
+        }
+
+        /**
+         * ArrayAccess: unset the item at the specified offset
+         * 
+         * @param  mixed $index 
+         * @return void
+         * @throws OutOfRangeException
+         */
+        public function offsetUnset($index)
+        {
+            if (!$this->offsetExists($index)) {
+                throw OutOfRangeException(sprintf('Invalid index ("%s") specified', $index));
+            }
+            unset($this->data[$index]);
+            $this->stack = false;
+            $this->count--;
+        }
+
+        /**
+         * Pop a node from the end of the stack
+         *
+         * @return mixed
+         * @throws RuntimeException
+         */
+        public function pop()
+        {
+            $val         = array_pop($this->data);
+            $this->stack = false;
+            $this->count--;
+            return $val;
+        }
+
+        /**
+         * Move the iterator to the previous node
+         *
+         * @todo   Does this need to be implemented?
+         * @return void
+         */
+        public function prev()
+        {
+        }
+
+        /**
+         * Push an element to the list
+         * 
+         * @param  mixed $value 
+         * @return void
+         */
+        public function push($value)
+        {
+            array_push($this->data, $value);
+            $this->count++;
+            $this->stack  = false;
+        }
+
+        /**
+         * Iterator: rewind to beginning of stack
+         * 
+         * @return void
+         */
+        public function rewind()
+        {
+            if (is_array($this->stack)) {
+                return reset($this->stack);
+            }
+            $this->stack = array_reverse($this->data, true);
+        }
+
+        /**
+         * Serialize the storage
+         *
+         * @return string
+         */
+        public function serialize()
+        {
+            return serialize($this->data);
+        }
+
+        /**
+         * Shifts a node from the beginning of the list
+         *
+         * @return mixed
+         * @throws RuntimeException
+         */
+        public function shift()
+        {
+            $val         = array_shift($this->data);
+            $this->stack = false;
+            $this->count--;
+            return $val;
+        }
+
+        /**
+         * Peek at the top node of the stack
+         * 
+         * @return mixed
+         */
+        public function top()
+        {
+            $this->rewind();
+            $value = array_shift($this->stack);
+            array_unshift($this->stack, $value);
+            return $value;
+        }
+
+        /**
+         * Unserialize the storage
+         *
+         * @param  string
+         * @return void
+         */
+        public function unserialize($serialized)
+        {
+            $this->data  = unserialize($serialized);
+            $this->stack = false;
+        }
+
+        /**
+         * Unshift a node onto the beginning of the list
+         *
+         * @param  mixed $value
+         * @return void
+         */
+        public function unshift($value)
+        {
+            array_unshift($this->data, $value);
+            $this->count++;
+            $this->stack  = false;
+        }
+        
+        /**
+         * Iterator: is the current pointer valid?
+         *
+         * @return bool
+         */
+        public function valid()
+        {
+            $key = key($this->stack);
+            $var = ($key !== null && $key !== false);
+            return $var;
+        }
+    }
+}
+
+/**
+ * Collection of signal handler return values
+ *
+ * @category   Zend
+ * @package    Zend_EventManager
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_EventManager_ResponseCollection extends SplStack 
+{
+    protected $stopped = false;
+
+    /**
+     * Did the last response provided trigger a short circuit of the stack?
+     * 
+     * @return bool
+     */
+    public function stopped()
+    {
+        return $this->stopped;
+    }
+
+    /**
+     * Mark the collection as stopped (or its opposite)
+     * 
+     * @param  bool $flag 
+     * @return Zend_EventManager_ResponseCollection
+     */
+    public function setStopped($flag)
+    {
+        $this->stopped = (bool) $flag;
+        return $this;
+    }
+
+    /**
+     * Convenient access to the first handler return value.
+     *
+     * @return mixed The first handler return value
+     */
+    public function first()
+    {
+        return parent::bottom();
+    }
+
+    /**
+     * Convenient access to the last handler return value.
+     *
+     * If the collection is empty, returns null. Otherwise, returns value
+     * returned by last handler.
+     *
+     * @return mixed The last handler return value
+     */
+    public function last()
+    {
+        if (count($this) === 0) {
+            return null;
+        }
+        return parent::top();
+    }
+
+    /**
+     * Check if any of the responses match the given value.
+     *
+     * @param  mixed $value The value to look for among responses
+     */
+    public function contains($value)
+    {
+        foreach ($this as $response) {
+            if ($response === $value) {
+                return true;
+            }
+        }
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/EventManager/SharedEventCollection.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,32 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_EventManager
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+/**
+ * Interface for shared event listener collections
+ *
+ * @category   Zend
+ * @package    Zend_EventManager
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+interface Zend_EventManager_SharedEventCollection
+{
+    public function getListeners($id, $event);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/EventManager/SharedEventCollectionAware.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,42 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_EventManager
+ * @subpackage UnitTest
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+require_once 'Zend/EventManager/SharedEventCollection.php';
+
+/**
+ * Interface to automate setter injection for a SharedEventCollection instance
+ *
+ * @category   Zend
+ * @package    Zend_EventManager
+ * @subpackage UnitTest
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+interface Zend_EventManager_SharedEventCollectionAware
+{
+    /**
+     * Inject an EventManager instance
+     * 
+     * @param  Zend_EventManager_SharedEventCollection $sharedEventCollection 
+     * @return Zend_EventManager_SharedEventCollectionAware
+     */
+    public function setSharedCollections(Zend_EventManager_SharedEventCollection $sharedEventCollection);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/EventManager/SharedEventManager.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,148 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_EventManager
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+require_once 'Zend/EventManager/EventManager.php';
+require_once 'Zend/EventManager/SharedEventCollection.php';
+
+/**
+ * Shared/contextual EventManager
+ *
+ * Allows attaching to EMs composed by other classes without having an instance first.
+ * The assumption is that the SharedEventManager will be injected into EventManager 
+ * instances, and then queried for additional listeners when triggering an event.
+ *
+ * @category   Zend
+ * @package    Zend_EventManager
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_EventManager_SharedEventManager implements Zend_EventManager_SharedEventCollection
+{
+    /**
+     * Identifiers with event connections
+     * @var array
+     */
+    protected $identifiers = array();
+
+    /**
+     * Attach a listener to an event
+     *
+     * Allows attaching a callback to an event offerred by one or more 
+     * identifying components. As an example, the following connects to the 
+     * "getAll" event of both an AbstractResource and EntityResource:
+     *
+     * <code>
+     * SharedEventManager::getInstance()->connect(
+     *     array('My\Resource\AbstractResource', 'My\Resource\EntityResource'),
+     *     'getOne',
+     *     function ($e) use ($cache) {
+     *         if (!$id = $e->getParam('id', false)) {
+     *             return;
+     *         }
+     *         if (!$data = $cache->load(get_class($resource) . '::getOne::' . $id )) {
+     *             return;
+     *         }
+     *         return $data;
+     *     }
+     * );
+     * </code>
+     * 
+     * @param  string|array $id Identifier(s) for event emitting component(s)
+     * @param  string $event 
+     * @param  callback $callback PHP Callback
+     * @param  int $priority Priority at which listener should execute
+     * @return void
+     */
+    public function attach($id, $event, $callback, $priority = 1)
+    {
+        $ids = (array) $id;
+        foreach ($ids as $id) {
+            if (!array_key_exists($id, $this->identifiers)) {
+                $this->identifiers[$id] = new Zend_EventManager_EventManager();
+            }
+            $this->identifiers[$id]->attach($event, $callback, $priority);
+        }
+    }
+
+    /**
+     * Detach a listener from an event offered by a given resource
+     * 
+     * @param  string|int $id
+     * @param  Zend_Stdlib_CallbackHandler $listener 
+     * @return bool Returns true if event and listener found, and unsubscribed; returns false if either event or listener not found
+     */
+    public function detach($id, Zend_Stdlib_CallbackHandler $listener)
+    {
+        if (!array_key_exists($id, $this->identifiers)) {
+            return false;
+        }
+        return $this->identifiers[$id]->detach($listener);
+    }
+
+    /**
+     * Retrieve all registered events for a given resource
+     * 
+     * @param  string|int $id
+     * @return array
+     */
+    public function getEvents($id)
+    {
+        if (!array_key_exists($id, $this->identifiers)) {
+            return false;
+        }
+        return $this->identifiers[$id]->getEvents();
+    }
+
+    /**
+     * Retrieve all listeners for a given identifier and event
+     * 
+     * @param  string|int $id
+     * @param  string|int $event 
+     * @return false|Zend_Stdlib_PriorityQueue
+     */
+    public function getListeners($id, $event)
+    {
+        if (!array_key_exists($id, $this->identifiers)) {
+            return false;
+        }
+        return $this->identifiers[$id]->getListeners($event);
+    }
+
+    /**
+     * Clear all listeners for a given identifier, optionally for a specific event
+     * 
+     * @param  string|int $id 
+     * @param  null|string $event 
+     * @return bool
+     */
+    public function clearListeners($id, $event = null)
+    {
+        if (!array_key_exists($id, $this->identifiers)) {
+            return false;
+        }
+
+        if (null === $event) {
+            unset($this->identifiers[$id]);
+            return true;
+        }
+
+        return $this->identifiers[$id]->clearListeners($event);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/EventManager/StaticEventManager.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,80 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_EventManager
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+require_once 'Zend/EventManager/EventManager.php';
+require_once 'Zend/EventManager/SharedEventManager.php';
+require_once 'Zend/Stdlib/CallbackHandler.php';
+
+/**
+ * Static version of EventManager
+ *
+ * @category   Zend
+ * @package    Zend_EventManager
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_EventManager_StaticEventManager extends Zend_EventManager_SharedEventManager
+{
+    /**
+     * @var Zend_EventManager_StaticEventManager
+     */
+    protected static $instance;
+
+    /**
+     * Singleton
+     * 
+     * @return void
+     */
+    protected function __construct()
+    {
+    }
+
+    /**
+     * Singleton
+     *
+     * @return void
+     */
+    private function __clone()
+    {
+    }
+
+    /**
+     * Retrieve instance
+     * 
+     * @return Zend_EventManager_StaticEventManager
+     */
+    public static function getInstance()
+    {
+        if (null === self::$instance) {
+            self::$instance = new self();
+        }
+        return self::$instance;
+    }
+
+    /**
+     * Reset the singleton instance
+     * 
+     * @return void
+     */
+    public static function resetInstance()
+    {
+        self::$instance = null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/File/ClassFileLocator.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,173 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_File
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+/**
+ * Locate files containing PHP classes, interfaces, or abstracts
+ * 
+ * @package    Zend_File
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    New BSD {@link http://framework.zend.com/license/new-bsd}
+ */
+class Zend_File_ClassFileLocator extends FilterIterator
+{
+    /**
+     * Create an instance of the locator iterator
+     * 
+     * Expects either a directory, or a DirectoryIterator (or its recursive variant) 
+     * instance.
+     * 
+     * @param  string|DirectoryIterator $dirOrIterator 
+     * @return void
+     */
+    public function __construct($dirOrIterator = '.')
+    {
+        if (is_string($dirOrIterator)) {
+            if (!is_dir($dirOrIterator)) {
+                throw new InvalidArgumentException('Expected a valid directory name');
+            }
+
+            $dirOrIterator = new RecursiveDirectoryIterator($dirOrIterator);
+        }
+        if (!$dirOrIterator instanceof DirectoryIterator) {
+            throw new InvalidArgumentException('Expected a DirectoryIterator');
+        }
+
+        if ($dirOrIterator instanceof RecursiveIterator) {
+            $iterator = new RecursiveIteratorIterator($dirOrIterator);
+        } else {
+            $iterator = $dirOrIterator;
+        }
+
+        parent::__construct($iterator);
+
+        // Forward-compat with PHP 5.3
+        if (version_compare(PHP_VERSION, '5.3.0', '<')) {
+            if (!defined('T_NAMESPACE')) {
+                define('T_NAMESPACE', 'namespace');
+            }
+            if (!defined('T_NS_SEPARATOR')) {
+                define('T_NS_SEPARATOR', '\\');
+            }
+        }
+    }
+
+    /**
+     * Filter for files containing PHP classes, interfaces, or abstracts
+     * 
+     * @return bool
+     */
+    public function accept()
+    {
+        $file = $this->getInnerIterator()->current();
+
+        // If we somehow have something other than an SplFileInfo object, just 
+        // return false
+        if (!$file instanceof SplFileInfo) {
+            return false;
+        }
+
+        // If we have a directory, it's not a file, so return false
+        if (!$file->isFile()) {
+            return false;
+        }
+
+        // If not a PHP file, skip
+        if ($file->getBasename('.php') == $file->getBasename()) {
+            return false;
+        }
+
+        $contents = file_get_contents($file->getRealPath());
+        $tokens   = token_get_all($contents);
+        $count    = count($tokens);
+        $i        = 0;
+        while ($i < $count) {
+            $token = $tokens[$i];
+
+            if (!is_array($token)) {
+                // single character token found; skip
+                $i++;
+                continue;
+            }
+
+            list($id, $content, $line) = $token;
+
+            switch ($id) {
+                case T_NAMESPACE:
+                    // Namespace found; grab it for later
+                    $namespace = '';
+                    $done      = false;
+                    do {
+                        ++$i;
+                        $token = $tokens[$i];
+                        if (is_string($token)) {
+                            if (';' === $token) {
+                                $done = true;
+                            }
+                            continue;
+                        }
+                        list($type, $content, $line) = $token;
+                        switch ($type) {
+                            case T_STRING:
+                            case T_NS_SEPARATOR:
+                                $namespace .= $content;
+                                break;
+                        }
+                    } while (!$done && $i < $count);
+
+                    // Set the namespace of this file in the object
+                    $file->namespace = $namespace;
+                    break;
+                case T_CLASS:
+                case T_INTERFACE:
+                    // Abstract class, class, or interface found
+
+                    // Get the classname
+                    $class = '';
+                    do {
+                        ++$i;
+                        $token = $tokens[$i];
+                        if (is_string($token)) {
+                            continue;
+                        }
+                        list($type, $content, $line) = $token;
+                        switch ($type) {
+                            case T_STRING:
+                                $class = $content;
+                                break;
+                        }
+                    } while (empty($class) && $i < $count);
+
+                    // If a classname was found, set it in the object, and 
+                    // return boolean true (found)
+                    if (!empty($class)) {
+                        $file->classname = $class;
+                        return true;
+                    }
+                    break;
+                default:
+                    break;
+            }
+            ++$i;
+        }
+
+        // No class-type tokens found; return false
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Form/Decorator/Captcha/ReCaptcha.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,128 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Form
+ * @subpackage Decorator
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+/** @see Zend_Form_Decorator_Abstract */
+require_once 'Zend/Form/Decorator/Abstract.php';
+
+/**
+ * ReCaptcha-based captcha decorator
+ *
+ * Adds hidden fields for challenge and response input, and JS for populating 
+ * from known recaptcha IDs
+ *
+ * @category   Zend
+ * @package    Zend_Form
+ * @subpackage Element
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Form_Decorator_Captcha_ReCaptcha extends Zend_Form_Decorator_Abstract
+{
+    /**
+     * Render captcha
+     *
+     * @param  string $content
+     * @return string
+     */
+    public function render($content)
+    {
+        $element = $this->getElement();
+        if (!$element instanceof Zend_Form_Element_Captcha) {
+            return $content;
+        }
+
+        $view    = $element->getView();
+        if (null === $view) {
+            return $content;
+        }
+
+        $id            = $element->getId();
+        $name          = $element->getBelongsTo();
+        $placement     = $this->getPlacement();
+        $separator     = $this->getSeparator();
+        $challengeName = empty($name) ? 'recaptcha_challenge_field' : $name . '[recaptcha_challenge_field]';
+        $responseName  = empty($name) ? 'recaptcha_response_field'  : $name . '[recaptcha_response_field]';
+        $challengeId   = $id . '-challenge';
+        $responseId    = $id . '-response';
+        $captcha       = $element->getCaptcha();
+        $markup        = $captcha->render($view, $element);
+
+        // Create hidden fields for holding the final recaptcha values
+        // Placing "id" in "attribs" to ensure it is not overwritten with the name
+        $hidden = $view->formHidden(array(
+            'name'    => $challengeName,
+            'attribs' => array('id' => $challengeId),
+        ));
+        $hidden .= $view->formHidden(array(
+            'name'    => $responseName,
+            'attribs' => array('id'   => $responseId),
+        ));
+
+        // Create a window.onload event so that we can bind to the form.
+        // Once bound, add an onsubmit event that will replace the hidden field 
+        // values with those produced by ReCaptcha
+        // zendBindEvent mediates between Mozilla's addEventListener and
+        // IE's sole support for addEvent.
+        $js =<<<EOJ
+<script type="text/javascript" language="JavaScript">
+function windowOnLoad(fn) {
+    var old = window.onload;
+    window.onload = function() {
+        if (old) {
+            old();
+        }
+        fn();
+    };
+}
+function zendBindEvent(el, eventName, eventHandler) {
+    if (el.addEventListener){
+        el.addEventListener(eventName, eventHandler, false); 
+    } else if (el.attachEvent){
+        el.attachEvent('on'+eventName, eventHandler);
+    }
+}
+windowOnLoad(function(){
+    zendBindEvent(
+        document.getElementById("$challengeId").form,
+        'submit',
+        function(e) {
+            document.getElementById("$challengeId").value = document.getElementById("recaptcha_challenge_field").value;
+            document.getElementById("$responseId").value = document.getElementById("recaptcha_response_field").value;
+        }    
+    );
+});
+</script>
+EOJ;
+
+        // Always place the hidden fields before the captcha markup, and follow 
+        // with the JS from above
+        switch ($placement) {
+            case 'PREPEND':
+                $content = $hidden . $markup . $js . $separator . $content;
+                break;
+            case 'APPEND':
+            default:
+                $content = $content . $separator . $hidden . $markup . $js;
+        }
+        return $content;
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Form/Element/Note.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,64 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Form
+ * @subpackage Element
+ * @copyright  Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+/** Zend_Form_Element_Xhtml */
+require_once 'Zend/Form/Element/Xhtml.php';
+
+/**
+ * Element to show an HTML note
+ *
+ * @category   Zend
+ * @package    Zend_Form
+ * @subpackage Element
+ * @copyright  Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+class Zend_Form_Element_Note extends Zend_Form_Element_Xhtml
+{
+    /**
+     * Default form view helper to use for rendering
+     *
+     * @var string
+     */
+    public $helper = 'formNote';
+    
+    /**
+     * Ignore flag (used when retrieving values at form level)
+     *
+     * @var bool
+     */
+    protected $_ignore = true;
+    
+    /**
+     * Validate element value (pseudo)
+     *
+     * There is no need to reset the value
+     *
+     * @param  mixed $value Is always ignored
+     * @param  mixed $context Is always ignored
+     * @return boolean Returns always TRUE
+     */
+    public function isValid($value, $context = null)
+    {
+        return true;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Gdata/Analytics.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,137 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Gdata
+ * @subpackage Analytics
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/**
+ * @see Zend_Gdata
+ */
+require_once 'Zend/Gdata.php';
+
+/**
+ * @see Zend_Gdata_Analytics_AccountEntry
+ */
+require_once 'Zend/Gdata/Analytics/AccountEntry.php';
+
+/**
+ * @see Zend_Gdata_Analytics_AccountFeed
+ */
+require_once 'Zend/Gdata/Analytics/AccountFeed.php';
+
+/**
+ * @see Zend_Gdata_Analytics_DataEntry
+ */
+require_once 'Zend/Gdata/Analytics/DataEntry.php';
+
+/**
+ * @see Zend_Gdata_Analytics_DataFeed
+ */
+require_once 'Zend/Gdata/Analytics/DataFeed.php';
+
+/**
+ * @see Zend_Gdata_Analytics_DataQuery
+ */
+require_once 'Zend/Gdata/Analytics/DataQuery.php';
+
+/**
+ * @see Zend_Gdata_Analytics_AccountQuery
+ */
+require_once 'Zend/Gdata/Analytics/AccountQuery.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Gdata
+ * @subpackage Analytics
+ */
+class Zend_Gdata_Analytics extends Zend_Gdata
+{
+
+    const AUTH_SERVICE_NAME = 'analytics';
+    const ANALYTICS_FEED_URI = 'https://www.googleapis.com/analytics/v2.4/data';
+    const ANALYTICS_ACCOUNT_FEED_URI = 'https://www.googleapis.com/analytics/v2.4/management/accounts';
+
+    public static $namespaces = array(
+        array('analytics', 'http://schemas.google.com/analytics/2009', 1, 0),
+        array('ga', 'http://schemas.google.com/ga/2009', 1, 0)
+     );
+
+    /**
+     * Create Gdata object
+     *
+     * @param Zend_Http_Client $client
+     * @param string $applicationId The identity of the app in the form of
+     *          Company-AppName-Version
+     */
+    public function __construct($client = null, $applicationId = 'MyCompany-MyApp-1.0')
+    {
+        $this->registerPackage('Zend_Gdata_Analytics');
+        $this->registerPackage('Zend_Gdata_Analytics_Extension');
+        parent::__construct($client, $applicationId);
+        $this->_httpClient->setParameterPost('service', self::AUTH_SERVICE_NAME);
+    }
+
+    /**
+     * Retrieve account feed object
+     * 
+     * @param string|Zend_Uri_Uri $uri
+     * @return Zend_Gdata_Analytics_AccountFeed
+     */
+    public function getAccountFeed($uri = self::ANALYTICS_ACCOUNT_FEED_URI)
+    {
+        if ($uri instanceof Query) {
+            $uri = $uri->getQueryUrl();
+        }
+        return parent::getFeed($uri, 'Zend_Gdata_Analytics_AccountFeed');
+    }
+
+    /**
+     * Retrieve data feed object
+     * 
+     * @param string|Zend_Uri_Uri $uri
+     * @return Zend_Gdata_Analytics_DataFeed
+     */
+    public function getDataFeed($uri = self::ANALYTICS_FEED_URI)
+    {
+        if ($uri instanceof Query) {
+            $uri = $uri->getQueryUrl();
+        }
+        return parent::getFeed($uri, 'Zend_Gdata_Analytics_DataFeed');
+    }
+
+    /**
+     * Returns a new DataQuery object.
+     * 
+     * @return Zend_Gdata_Analytics_DataQuery
+     */
+    public function newDataQuery()
+    {
+        return new Zend_Gdata_Analytics_DataQuery();
+    }
+    
+    /**
+     * Returns a new AccountQuery object.
+     *
+     * @return Zend_Gdata_Analytics_AccountQuery
+     */
+    public function newAccountQuery()
+    {
+        return new Zend_Gdata_Analytics_AccountQuery();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Gdata/Analytics/AccountEntry.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,102 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Gdata
+ * @subpackage Analytics
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/**
+ * @see Zend_Gdata_Entry
+ */
+require_once 'Zend/Gdata/Entry.php';
+
+/**
+ * @see Zend_Gdata_Analytics_Extension_Dimension
+ */
+require_once 'Zend/Gdata/Analytics/Extension/Dimension.php';
+
+/**
+ * @see Zend_Gdata_Analytics_Extension_Metric
+ */
+require_once 'Zend/Gdata/Analytics/Extension/Metric.php';
+
+/**
+ * @see Zend_Gdata_Analytics_Extension_Property
+ */
+require_once 'Zend/Gdata/Analytics/Extension/Property.php';
+
+/**
+ * @see Zend_Gdata_Analytics_Extension_TableId
+ */
+require_once 'Zend/Gdata/Analytics/Extension/TableId.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Gdata
+ * @subpackage Analytics
+ */
+class Zend_Gdata_Analytics_AccountEntry extends Zend_Gdata_Entry
+{
+    protected $_accountId;
+    protected $_accountName;
+    protected $_profileId;
+    protected $_webPropertyId;
+    protected $_currency;
+    protected $_timezone;
+    protected $_tableId;
+    protected $_profileName;
+    protected $_goal;
+
+    /**
+     * @see Zend_Gdata_Entry::__construct()
+     */
+    public function __construct($element = null)
+    {
+        $this->registerAllNamespaces(Zend_Gdata_Analytics::$namespaces);
+        parent::__construct($element);
+    }
+
+    /**
+     * @param DOMElement $child
+     * @return void
+     */
+    protected function takeChildFromDOM($child)
+    {
+        $absoluteNodeName = $child->namespaceURI . ':' . $child->localName;
+        switch ($absoluteNodeName){
+            case $this->lookupNamespace('analytics') . ':' . 'property';
+                $property = new Zend_Gdata_Analytics_Extension_Property();
+                $property->transferFromDOM($child);
+                $this->{$property->getName()} = $property;
+                break;
+            case $this->lookupNamespace('analytics') . ':' . 'tableId';
+                $tableId = new Zend_Gdata_Analytics_Extension_TableId();
+                $tableId->transferFromDOM($child);
+                $this->_tableId = $tableId;
+                break;
+            case $this->lookupNamespace('ga') . ':' . 'goal';
+                $goal = new Zend_Gdata_Analytics_Extension_Goal();
+                $goal->transferFromDOM($child);
+                $this->_goal = $goal;
+                break;
+            default:
+                parent::takeChildFromDOM($child);
+                break;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Gdata/Analytics/AccountFeed.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,57 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Gdata
+ * @subpackage Analytics
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/**
+ * @see Zend_Gdata_Feed
+ */
+require_once 'Zend/Gdata/Feed.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Gdata
+ * @subpackage Analytics
+ */
+class Zend_Gdata_Analytics_AccountFeed extends Zend_Gdata_Feed
+{
+    /**
+     * The classname for individual feed elements.
+     *
+     * @var string
+     */
+    protected $_entryClassName = 'Zend_Gdata_Analytics_AccountEntry';
+
+    /**
+     * The classname for the feed.
+     *
+     * @var string
+     */
+    protected $_feedClassName = 'Zend_Gdata_Analytics_AccountFeed';
+
+    /**
+     * @see Zend_GData_Feed::__construct()
+     */
+    public function __construct($element = null)
+    {
+        $this->registerAllNamespaces(Zend_Gdata_Analytics::$namespaces);
+        parent::__construct($element);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Gdata/Analytics/AccountQuery.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,190 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Gdata
+ * @subpackage Analytics
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/**
+ * @see Zend_Gdata_Query
+ */
+require_once 'Zend/Gdata/Query.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Gdata
+ * @subpackage Analytics
+ */
+class Zend_Gdata_Analytics_AccountQuery extends Zend_Gdata_Query
+{
+    const ANALYTICS_FEED_URI = 'https://www.googleapis.com/analytics/v2.4/management/accounts';
+
+    /**
+     * The default URI used for feeds.
+     */
+    protected $_defaultFeedUri = self::ANALYTICS_FEED_URI;
+    
+    /**
+     * @var string
+     */
+    protected $_accountId = '~all';
+    /**
+     * @var string
+     */
+    protected $_webpropertyId = '~all';
+    /**
+     * @var string
+     */
+    protected $_profileId = '~all';
+   
+    /**
+     * @var bool
+     */ 
+    protected $_webproperties = false;
+    /**
+     * @var bool
+     */
+    protected $_profiles = false;
+    /**
+     * @var bool
+     */
+    protected $_goals = false;
+    
+    /**
+     * @param string $accountId
+     * @return Zend_Gdata_Analytics_AccountQuery
+     */
+    public function setAccountId($accountId)
+    {
+        $this->_accountId = $accountId;
+        return $this;
+    }
+    
+    /**
+     * @return string
+     */
+    public function getAccountId()
+    {
+        return $this->_accountId;
+    }
+
+    /**
+     * @param string $webpropertyId
+     * @return Zend_Gdata_Analytics_AccountQuery
+     */
+    public function setWebpropertyId($webpropertyId)
+    {
+        $this->_webpropertyId = $webpropertyId;
+        return $this;
+    }
+    
+    /**
+     * @return string
+     */
+    public function getWebpropertyId()
+    {
+        return $this->_webpropertyId;
+    }
+    
+    /**
+     * @param string $profileId
+     * @return Zend_Gdata_Analytics_AccountQuery
+     */
+    public function setProfileId($profileId)
+    {
+        $this->_profileId = $profileId;
+        return $this;
+    }
+
+    /**
+     * @return string
+     */
+    public function getProfileId()
+    {
+        return $this->_profileId;
+    }
+    
+    /**
+     * @param string $accountId
+     * @return Zend_Gdata_Analytics_AccountQuery
+     */
+    public function webproperties($accountId = '~all')
+    {
+        $this->_webproperties = true;
+        $this->setAccountId($accountId);    
+        return $this;
+    }
+    
+    /**
+     * @param string $webpropertyId
+     * @param string $accountId
+     * @return Zend_Gdata_Analytics_AccountQuery
+     */
+    public function profiles($webpropertyId = '~all', $accountId = '~all')
+    {
+        $this->_profiles = true;
+        if (null !== $accountId) {
+            $this->setAccountId($accountId);    
+        }
+        $this->setWebpropertyId($webpropertyId);
+        return $this;
+    }
+    
+    /**
+     * @param string $webpropertyId
+     * @param string $accountId
+     * @param string $accountId
+     * @return Zend_Gdata_Analytics_AccountQuery
+     */
+    public function goals($profileId = '~all', $webpropertyId = '~all', $accountId = '~all')
+    {
+        $this->_goals = true;
+        if (null !== $accountId) {
+            $this->setAccountId($accountId);    
+        }
+        if (null !== $webpropertyId) {
+            $this->setWebpropertyId($webpropertyId);    
+        }
+        $this->setProfileId($profileId);
+        return $this;
+    }
+    
+    /**
+     * @return string url
+     */
+    public function getQueryUrl()
+    {
+        $url = $this->_defaultFeedUri;
+        
+        // add account id
+        if ($this->_webproperties or $this->_profiles or $this->_goals) {
+            $url .= '/' . $this->_accountId . '/webproperties';
+        }
+        
+        if ($this->_profiles or $this->_goals) {
+            $url .= '/' . $this->_webpropertyId . '/profiles';
+        }
+        
+        if ($this->_goals) {
+            $url .= '/' . $this->_profileId . '/goals';
+        }
+
+        $url .= $this->getQueryString();
+        return $url;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Gdata/Analytics/DataEntry.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,116 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Gdata
+ * @subpackage Analytics
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/**
+ * @see Zend_Gdata_Entry
+ */
+require_once 'Zend/Gdata/Entry.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Gdata
+ * @subpackage Analytics
+ */
+class Zend_Gdata_Analytics_DataEntry extends Zend_Gdata_Entry
+{
+    /**
+     * @var array
+     */
+    protected $_dimensions = array();
+    /**
+     * @var array
+     */
+    protected $_metrics = array();
+
+    /**
+     * @param DOMElement $element
+     */
+    public function __construct($element = null)
+    {
+        $this->registerAllNamespaces(Zend_Gdata_Analytics::$namespaces);
+        parent::__construct($element);
+    }
+
+    /**
+     * @param DOMElement $child
+     * @return void
+     */
+    protected function takeChildFromDOM($child)
+    {
+        $absoluteNodeName = $child->namespaceURI . ':' . $child->localName;
+        switch ($absoluteNodeName) {
+            case $this->lookupNamespace('analytics') . ':' . 'dimension';
+                $dimension = new Zend_Gdata_Analytics_Extension_Dimension();
+                $dimension->transferFromDOM($child);
+                $this->_dimensions[] = $dimension;
+                break;
+            case $this->lookupNamespace('analytics') . ':' . 'metric';
+                $metric = new Zend_Gdata_Analytics_Extension_Metric();
+                $metric->transferFromDOM($child);
+                $this->_metrics[] = $metric;
+                break;
+            default:
+                parent::takeChildFromDOM($child);
+                break;
+        }
+    }
+
+    /**
+     * @param string $name 
+     * @return mixed
+     */
+    public function getDimension($name)
+    {
+        foreach ($this->_dimensions as $dimension) {
+            if ($dimension->getName() == $name) {
+                return $dimension;
+            }
+        }
+        return null;
+    }
+    
+    /** 
+     * @param string $name 
+     * @return mixed
+     */
+    public function getMetric($name)
+    {
+        foreach ($this->_metrics as $metric) {
+            if ($metric->getName() == $name) {
+                return $metric;
+            }
+        }
+        return null;
+    }
+    
+    /**
+     * @param string $name 
+     * @return mixed
+     */
+    public function getValue($name)
+    {
+        if (null !== ($metric = $this->getMetric($name))) {
+            return $metric;
+        }
+        return $this->getDimension($name);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Gdata/Analytics/DataFeed.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,64 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Gdata
+ * @subpackage Analytics
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/**
+ * @see Zend_Gdata_Feed
+ */
+require_once 'Zend/Gdata/Feed.php';
+
+/**
+ * @see Zend_Gdata_Analytics
+ */
+require_once 'Zend/Gdata/Analytics.php';
+
+/**
+ * @see Zend_Gdata_Geo_Entry
+ */
+require_once 'Zend/Gdata/Analytics/DataEntry.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Gdata
+ * @subpackage Analytics
+ */
+class Zend_Gdata_Analytics_DataFeed extends Zend_Gdata_Feed
+{
+
+    /**
+     * The classname for individual feed elements.
+     *
+     * @var string
+     */
+    protected $_entryClassName = 'Zend_Gdata_Analytics_DataEntry';
+    /**
+     * The classname for the feed.
+     *
+     * @var string
+     */
+    protected $_feedClassName = 'Zend_Gdata_Analytics_DataFeed';
+
+    public function __construct($element = null)
+    {
+        $this->registerAllNamespaces(Zend_Gdata_Analytics::$namespaces);
+        parent::__construct($element);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Gdata/Analytics/DataQuery.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,403 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Gdata
+ * @subpackage Analytics
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/**
+ * @see Zend_Gdata_Query
+ */
+require_once 'Zend/Gdata/Query.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Gdata
+ * @subpackage Analytics
+ */
+class Zend_Gdata_Analytics_DataQuery extends Zend_Gdata_Query
+{
+    const ANALYTICS_FEED_URI = 'https://www.googleapis.com/analytics/v2.4/data';
+
+    /**
+     * The default URI used for feeds.
+     */
+    protected $_defaultFeedUri = self::ANALYTICS_FEED_URI;
+
+    // D1. Visitor
+    const DIMENSION_BROWSER = 'ga:browser';
+    const DIMENSION_BROWSER_VERSION = 'ga:browserVersion';
+    const DIMENSION_CITY = 'ga:city';
+    const DIMENSION_CONNECTIONSPEED = 'ga:connectionSpeed';
+    const DIMENSION_CONTINENT = 'ga:continent';
+    const DIMENSION_COUNTRY = 'ga:country';
+    const DIMENSION_DATE = 'ga:date';
+    const DIMENSION_DAY = 'ga:day';
+    const DIMENSION_DAYS_SINCE_LAST_VISIT= 'ga:daysSinceLastVisit';
+    const DIMENSION_FLASH_VERSION = 'ga:flashVersion';
+    const DIMENSION_HOSTNAME = 'ga:hostname';
+    const DIMENSION_HOUR = 'ga:hour';
+    const DIMENSION_JAVA_ENABLED= 'ga:javaEnabled';
+    const DIMENSION_LANGUAGE= 'ga:language';
+    const DIMENSION_LATITUDE = 'ga:latitude';
+    const DIMENSION_LONGITUDE = 'ga:longitude';
+    const DIMENSION_MONTH = 'ga:month';
+    const DIMENSION_NETWORK_DOMAIN = 'ga:networkDomain';
+    const DIMENSION_NETWORK_LOCATION = 'ga:networkLocation';
+    const DIMENSION_OPERATING_SYSTEM = 'ga:operatingSystem';
+    const DIMENSION_OPERATING_SYSTEM_VERSION = 'ga:operatingSystemVersion';
+    const DIMENSION_PAGE_DEPTH = 'ga:pageDepth';
+    const DIMENSION_REGION = 'ga:region';
+    const DIMENSION_SCREEN_COLORS= 'ga:screenColors';
+    const DIMENSION_SCREEN_RESOLUTION = 'ga:screenResolution';
+    const DIMENSION_SUB_CONTINENT = 'ga:subContinent';
+    const DIMENSION_USER_DEFINED_VALUE = 'ga:userDefinedValue';
+    const DIMENSION_VISIT_COUNT = 'ga:visitCount';
+    const DIMENSION_VISIT_LENGTH = 'ga:visitLength';
+    const DIMENSION_VISITOR_TYPE = 'ga:visitorType';
+    const DIMENSION_WEEK = 'ga:week';
+    const DIMENSION_YEAR = 'ga:year';
+
+    // D2. Campaign
+    const DIMENSION_AD_CONTENT = 'ga:adContent';
+    const DIMENSION_AD_GROUP = 'ga:adGroup';
+    const DIMENSION_AD_SLOT = 'ga:adSlot';
+    const DIMENSION_AD_SLOT_POSITION = 'ga:adSlotPosition';
+    const DIMENSION_CAMPAIGN = 'ga:campaign';
+    const DIMENSION_KEYWORD = 'ga:keyword';
+    const DIMENSION_MEDIUM = 'ga:medium';
+    const DIMENSION_REFERRAL_PATH = 'ga:referralPath';
+    const DIMENSION_SOURCE = 'ga:source';
+
+    // D3. Content
+    const DIMENSION_EXIT_PAGE_PATH = 'ga:exitPagePath';
+    const DIMENSION_LANDING_PAGE_PATH = 'ga:landingPagePath';
+    const DIMENSION_PAGE_PATH = 'ga:pagePath';
+    const DIMENSION_PAGE_TITLE = 'ga:pageTitle';
+    const DIMENSION_SECOND_PAGE_PATH = 'ga:secondPagePath';
+
+    // D4. Ecommerce
+    const DIMENSION_AFFILIATION = 'ga:affiliation';
+    const DIMENSION_DAYS_TO_TRANSACTION = 'ga:daysToTransaction';
+    const DIMENSION_PRODUCT_CATEGORY = 'ga:productCategory';
+    const DIMENSION_PRODUCT_NAME = 'ga:productName';
+    const DIMENSION_PRODUCT_SKU = 'ga:productSku';
+    const DIMENSION_TRANSACTION_ID = 'ga:transactionId';
+    const DIMENSION_VISITS_TO_TRANSACTION = 'ga:visitsToTransaction';
+
+    // D5. Internal Search
+    const DIMENSION_SEARCH_CATEGORY = 'ga:searchCategory';
+    const DIMENSION_SEARCH_DESTINATION_PAGE = 'ga:searchDestinationPage';
+    const DIMENSION_SEARCH_KEYWORD = 'ga:searchKeyword';
+    const DIMENSION_SEARCH_KEYWORD_REFINEMENT = 'ga:searchKeywordRefinement';
+    const DIMENSION_SEARCH_START_PAGE = 'ga:searchStartPage';
+    const DIMENSION_SEARCH_USED = 'ga:searchUsed';
+
+    // D6. Navigation
+    const DIMENSION_NEXT_PAGE_PATH = 'ga:nextPagePath';
+    const DIMENSION_PREV_PAGE_PATH= 'ga:previousPagePath';
+
+    // D7. Events
+    const DIMENSION_EVENT_CATEGORY = 'ga:eventCategory';
+    const DIMENSION_EVENT_ACTION = 'ga:eventAction';
+    const DIMENSION_EVENT_LABEL = 'ga:eventLabel';
+
+    // D8. Custon Variables
+    const DIMENSION_CUSTOM_VAR_NAME_1 = 'ga:customVarName1';
+    const DIMENSION_CUSTOM_VAR_NAME_2 = 'ga:customVarName2';
+    const DIMENSION_CUSTOM_VAR_NAME_3 = 'ga:customVarName3';
+    const DIMENSION_CUSTOM_VAR_NAME_4 = 'ga:customVarName4';
+    const DIMENSION_CUSTOM_VAR_NAME_5 = 'ga:customVarName5';
+    const DIMENSION_CUSTOM_VAR_VALUE_1 = 'ga:customVarValue1';
+    const DIMENSION_CUSTOM_VAR_VALUE_2 = 'ga:customVarValue2';
+    const DIMENSION_CUSTOM_VAR_VALUE_3 = 'ga:customVarValue3';
+    const DIMENSION_CUSTOM_VAR_VALUE_4 = 'ga:customVarValue4';
+    const DIMENSION_CUSTOM_VAR_VALUE_5 = 'ga:customVarValue5';
+
+    // M1. Visitor
+    const METRIC_BOUNCES = 'ga:bounces';
+    const METRIC_ENTRANCES = 'ga:entrances';
+    const METRIC_EXITS = 'ga:exits';
+    const METRIC_NEW_VISITS = 'ga:newVisits';
+    const METRIC_PAGEVIEWS = 'ga:pageviews';
+    const METRIC_TIME_ON_PAGE = 'ga:timeOnPage';
+    const METRIC_TIME_ON_SITE = 'ga:timeOnSite';
+    const METRIC_VISITORS = 'ga:visitors';
+    const METRIC_VISITS = 'ga:visits';
+
+    // M2. Campaign
+    const METRIC_AD_CLICKS = 'ga:adClicks';
+    const METRIC_AD_COST = 'ga:adCost';
+    const METRIC_CPC = 'ga:CPC';
+    const METRIC_CPM = 'ga:CPM';
+    const METRIC_CTR = 'ga:CTR';
+    const METRIC_IMPRESSIONS = 'ga:impressions';
+
+    // M3. Content
+    const METRIC_UNIQUE_PAGEVIEWS = 'ga:uniquePageviews';
+
+    // M4. Ecommerce
+    const METRIC_ITEM_REVENUE = 'ga:itemRevenue';
+    const METRIC_ITEM_QUANTITY = 'ga:itemQuantity';
+    const METRIC_TRANSACTIONS = 'ga:transactions';
+    const METRIC_TRANSACTION_REVENUE = 'ga:transactionRevenue';
+    const METRIC_TRANSACTION_SHIPPING = 'ga:transactionShipping';
+    const METRIC_TRANSACTION_TAX = 'ga:transactionTax';
+    const METRIC_UNIQUE_PURCHASES = 'ga:uniquePurchases';
+
+    // M5. Internal Search
+    const METRIC_SEARCH_DEPTH = 'ga:searchDepth';
+    const METRIC_SEARCH_DURATION = 'ga:searchDuration';
+    const METRIC_SEARCH_EXITS = 'ga:searchExits';
+    const METRIC_SEARCH_REFINEMENTS = 'ga:searchRefinements';
+    const METRIC_SEARCH_UNIQUES = 'ga:searchUniques';
+    const METRIC_SEARCH_VISIT = 'ga:searchVisits';
+
+    // M6. Goals
+    const METRIC_GOAL_COMPLETIONS_ALL = 'ga:goalCompletionsAll';
+    const METRIC_GOAL_STARTS_ALL = 'ga:goalStartsAll';
+    const METRIC_GOAL_VALUE_ALL = 'ga:goalValueAll';
+    // TODO goals 1-20
+    const METRIC_GOAL_1_COMPLETION = 'ga:goal1Completions';
+    const METRIC_GOAL_1_STARTS = 'ga:goal1Starts';
+    const METRIC_GOAL_1_VALUE = 'ga:goal1Value';
+
+    // M7. Events
+    const METRIC_TOTAL_EVENTS = 'ga:totalEvents';
+    const METRIC_UNIQUE_EVENTS = 'ga:uniqueEvents';
+    const METRIC_EVENT_VALUE = 'ga:eventValue';
+    
+    // suported filter operators
+    const EQUALS = "==";
+    const EQUALS_NOT = "!=";
+    const GREATER = ">";
+    const LESS = ">";
+    const GREATER_EQUAL = ">=";
+    const LESS_EQUAL = "<=";
+    const CONTAINS = "=@";
+    const CONTAINS_NOT ="!@";
+    const REGULAR ="=~";
+    const REGULAR_NOT ="!~";
+    
+    /**
+     * @var string
+     */
+    protected $_profileId;
+    /**
+     * @var array
+     */
+    protected $_dimensions = array();
+    /**
+     * @var array
+     */
+    protected $_metrics = array();
+    /**
+     * @var array
+     */
+    protected $_sort = array();
+    /**
+     * @var array
+     */
+    protected $_filters = array();
+    
+    /**
+     * @param string $id
+     * @return Zend_Gdata_Analytics_DataQuery
+     */
+    public function setProfileId($id)
+    {
+        $this->_profileId = $id;
+        return $this;
+    }
+
+    /**
+     * @return string
+     */
+    public function getProfileId()
+    {
+        return $this->_profileId;
+    }
+
+    /**
+     * @param string $dimension
+     * @return Zend_Gdata_Analytics_DataQuery
+     */
+    public function addDimension($dimension)
+    {
+        $this->_dimensions[$dimension] = true;        
+        return $this;
+    }
+
+    /**
+     * @param string $metric
+     * @return Zend_Gdata_Analytics_DataQuery
+     */
+    public function addMetric($metric)
+    {
+        $this->_metrics[$metric] = true;
+        return $this;
+    }
+
+    /**
+     * @return array
+     */
+    public function getDimensions()
+    {
+        return $this->_dimensions;
+    }
+
+    /**
+     * @return array
+     */
+    public function getMetrics()
+    {
+        return $this->_metrics;
+    }
+
+    /**
+     * @param string $dimension
+     * @return Zend_Gdata_Analytics_DataQuery
+     */
+    public function removeDimension($dimension)
+    {
+        unset($this->_dimensions[$dimension]);
+        return $this;
+    }
+    /**
+     * @param string $metric
+     * @return Zend_Gdata_Analytics_DataQuery
+     */
+    public function removeMetric($metric)
+    {
+        unset($this->_metrics[$metric]);
+        return $this;
+    }
+    /**
+     * @param string $value
+     * @return Zend_Gdata_Analytics_DataQuery
+     */
+    public function setStartDate($date)
+    {
+        $this->setParam("start-date", $date);
+        return $this;
+    }
+    /**
+     * @param string $value
+     * @return Zend_Gdata_Analytics_DataQuery
+     */
+    public function setEndDate($date)
+    {
+        $this->setParam("end-date", $date);
+        return $this;
+    }
+    
+    /**
+     * @param string $filter
+     * @return Zend_Gdata_Analytics_DataQuery
+     */
+    public function addFilter($filter)
+    {
+        $this->_filters[] = array($filter, true);
+        return $this;
+    }
+    
+    /**
+     * @param string $filter
+     * @return Zend_Gdata_Analytics_DataQuery
+     */
+    public function addOrFilter($filter)
+    {
+        $this->_filters[] = array($filter, false);
+        return $this;
+    }
+    
+    /**
+     * @param string $sort
+     * @param boolean[optional] $descending
+     * @return Zend_Gdata_Analytics_DataQuery
+     */
+    public function addSort($sort, $descending=false)
+    {
+        // add to sort storage
+        $this->_sort[] = ($descending?'-':'').$sort;
+        return $this;
+    }
+    
+    /**
+     * @return Zend_Gdata_Analytics_DataQuery
+     */
+    public function clearSort()
+    {
+        $this->_sort = array();
+        return $this;
+    }
+    
+    /**
+     * @param string $segment
+     * @return Zend_Gdata_Analytics_DataQuery
+     */
+    public function setSegment($segment)
+    {
+        $this->setParam('segment', $segment);
+        return $this;
+    }
+
+    /**
+     * @return string url
+     */
+    public function getQueryUrl()
+    {
+        $uri = $this->_defaultFeedUri;
+        if (isset($this->_url)) {
+            $uri = $this->_url;
+        }
+        
+        $dimensions = $this->getDimensions();
+        if (!empty($dimensions)) {
+            $this->setParam('dimensions', implode(",", array_keys($dimensions)));
+        }
+        
+        $metrics = $this->getMetrics();
+        if (!empty($metrics)) {
+            $this->setParam('metrics', implode(",", array_keys($metrics)));
+        }
+        
+        // profile id (ga:tableId)
+        if ($this->getProfileId() != null) {
+            $this->setParam('ids', 'ga:'.ltrim($this->getProfileId(), "ga:"));
+        }
+                
+        // sorting
+        if ($this->_sort) {
+            $this->setParam('sort', implode(",", $this->_sort));
+        }
+        
+        // filtering
+        $filters = "";
+        foreach ($this->_filters as $filter) {
+            $filters.=($filter[1]===true?';':',').$filter[0];
+        }
+        
+        if ($filters!="") {
+            $this->setParam('filters', ltrim($filters, ",;"));
+        }
+        
+        $uri .= $this->getQueryString();
+        return $uri;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Gdata/Analytics/Extension/Dimension.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,40 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Gdata
+ * @subpackage Analytics
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/**
+ * @see Zend_Gdata_Extension_Metric
+ */
+require_once 'Zend/Gdata/Analytics/Extension/Metric.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Gdata
+ * @subpackage Analytics
+ */
+class Zend_Gdata_Analytics_Extension_Dimension 
+    extends Zend_Gdata_Analytics_Extension_Metric
+{
+    protected $_rootNamespace = 'ga';
+    protected $_rootElement = 'dimension';
+    protected $_value = null;
+    protected $_name = null;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Gdata/Analytics/Extension/Goal.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,52 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Gdata
+ * @subpackage Analytics
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/**
+ * @see Zend_Gdata_Extension
+ */
+require_once 'Zend/Gdata/Extension.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Gdata
+ * @subpackage Analytics
+ */
+class Zend_Gdata_Analytics_Goal extends Zend_Gdata_Extension
+{
+    protected $_rootNamespace = 'ga';
+    protected $_rootElement = 'goal';
+
+    public function __construct()
+    {
+        $this->registerAllNamespaces(Zend_Gdata_Analytics::$namespaces);
+        parent::__construct();
+    }
+    
+    /**
+     * @return string
+     */
+    public function __toString()
+    {
+        $attribs = $this->getExtensionAttributes();
+        return $attribs['name']['value'];
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Gdata/Analytics/Extension/Metric.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,54 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Gdata
+ * @subpackage Analytics
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/**
+ * @see Zend_Gdata_Extension_Property
+ */
+require_once 'Zend/Gdata/Analytics/Extension/Property.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Gdata
+ * @subpackage Analytics
+ */
+class Zend_Gdata_Analytics_Extension_Metric 
+    extends Zend_Gdata_Analytics_Extension_Property
+{
+    protected $_rootNamespace = 'ga';
+    protected $_rootElement = 'metric';
+    protected $_value = null;
+    protected $_name = null;
+
+    protected function takeAttributeFromDOM($attribute)
+    {
+        switch ($attribute->localName) {
+            case 'name':
+                $this->_name = $attribute->nodeValue;
+                break;
+            case 'value':
+                $this->_value = $attribute->nodeValue;
+                break;
+            default:
+                parent::takeAttributeFromDOM($attribute);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Gdata/Analytics/Extension/Property.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,122 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Gdata
+ * @subpackage Analytics
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/**
+ * @see Zend_Gdata_Extension
+ */
+require_once 'Zend/Gdata/Extension.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Gdata
+ * @subpackage Analytics
+ */
+class Zend_Gdata_Analytics_Extension_Property extends Zend_Gdata_Extension
+{
+    protected $_rootNamespace = 'ga';
+    protected $_rootElement = 'property';
+    protected $_value = null;
+    protected $_name = null;
+
+    /**
+     * Constructs a new Zend_Gdata_Calendar_Extension_Timezone object.
+     * @param string $value (optional) The text content of the element.
+     */
+    public function __construct($value = null, $name = null)
+    {
+        $this->registerAllNamespaces(Zend_Gdata_Analytics::$namespaces);
+        parent::__construct();
+        $this->_value = $value;
+        $this->_name = $name;
+    }
+
+    /**
+     * Given a DOMNode representing an attribute, tries to map the data into
+     * instance members.  If no mapping is defined, the name and value are
+     * stored in an array.
+     *
+     * @param DOMNode $attribute The DOMNode attribute needed to be handled
+     */
+    protected function takeAttributeFromDOM($attribute)
+    {
+        switch ($attribute->localName) {
+            case 'name':
+                $name = explode(':', $attribute->nodeValue);
+                $this->_name = end($name);
+                break;
+            case 'value':
+                $this->_value = $attribute->nodeValue;
+                break;
+            default:
+                parent::takeAttributeFromDOM($attribute);
+        }
+    }
+
+    /**
+     * Get the value for this element's value attribute.
+     *
+     * @return string The value associated with this attribute.
+     */
+    public function getValue()
+    {
+        return $this->_value;
+    }
+
+    /**
+     * Set the value for this element's value attribute.
+     *
+     * @param string $value The desired value for this attribute.
+     * @return Zend_Gdata_Analytics_Extension_Property The element being modified.
+     */
+    public function setValue($value)
+    {
+        $this->_value = $value;
+        return $this;
+    }
+
+    /**
+     * @param string $name
+     * @return Zend_Gdata_Analytics_Extension_Property
+     */
+    public function setName($name)
+    {
+        $this->_name = $name;
+        return $this;
+    }
+
+    /**
+     * @return string
+     */
+    public function getName()
+    {
+        return $this->_name;
+    }
+
+    /**
+     * Magic toString method allows using this directly via echo
+     * Works best in PHP >= 4.2.0
+     */
+    public function __toString()
+    {
+        return $this->getValue();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Gdata/Analytics/Extension/TableId.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,112 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Gdata
+ * @subpackage Analytics
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/**
+ * @see Zend_Gdata_Extension
+ */
+require_once 'Zend/Gdata/Extension.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Gdata
+ * @subpackage Analytics
+ */
+class Zend_Gdata_Analytics_Extension_TableId extends Zend_Gdata_Extension
+{
+
+    protected $_rootNamespace = 'ga';
+    protected $_rootElement = 'tableId';
+    protected $_value = null;
+
+    /**
+     * Constructs a new Zend_Gdata_Calendar_Extension_Timezone object.
+     * @param string $value (optional) The text content of the element.
+     */
+    public function __construct($value = null)
+    {
+        $this->registerAllNamespaces(Zend_Gdata_Analytics::$namespaces);
+        parent::__construct();
+        $this->_value = $value;
+    }
+
+    /**
+     * Retrieves a DOMElement which corresponds to this element and all
+     * child properties.  This is used to build an entry back into a DOM
+     * and eventually XML text for sending to the server upon updates, or
+     * for application storage/persistence.
+     *
+     * @param DOMDocument $doc The DOMDocument used to construct DOMElements
+     * @return DOMElement The DOMElement representing this element and all
+     * child properties.
+     */
+    public function getDOM($doc = null, $majorVersion = 1, $minorVersion = null)
+    {
+        $element = parent::getDOM($doc, $majorVersion, $minorVersion);
+        if ($this->_value != null) {
+            $element->setAttribute('value', $this->_value);
+        }
+        return $element;
+    }
+
+    /**
+     * Given a DOMNode representing an attribute, tries to map the data into
+     * instance members.  If no mapping is defined, the name and value are
+     * stored in an array.
+     *
+     * @param DOMNode $attribute The DOMNode attribute needed to be handled
+     */
+    protected function takeChildFromDOM($child)
+    {
+       $this->_value = $child->nodeValue;
+    }
+
+    /**
+     * Get the value for this element's value attribute.
+     *
+     * @return string The value associated with this attribute.
+     */
+    public function getValue()
+    {
+        return $this->_value;
+    }
+
+    /**
+     * Set the value for this element's value attribute.
+     *
+     * @param string $value The desired value for this attribute.
+     * @return Zend_Gdata_Calendar_Extension_Timezone The element being modified.
+     */
+    public function setValue($value)
+    {
+        $this->_value = $value;
+        return $this;
+    }
+
+    /**
+     * Magic toString method allows using this directly via echo
+     * Works best in PHP >= 4.2.0
+     */
+    public function __toString()
+    {
+        return $this->getValue();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Http/Header/Exception/InvalidArgumentException.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,36 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Http
+ * @subpackage Header_Exception
+ * @version    $Id$
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+/**
+ * @see Zend_Http_Exception
+ */
+require_once 'Zend/Http/Exception.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Http
+ * @subpackage Header_Exception
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Http_Header_Exception_InvalidArgumentException extends Zend_Http_Exception
+{}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Http/Header/Exception/RuntimeException.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,36 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Http
+ * @subpackage Header_Exception
+ * @version    $Id$
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+/**
+ * @see Zend_Http_Exception
+ */
+require_once 'Zend/Http/Exception.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Http
+ * @subpackage Header_Exception
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Http_Header_Exception_RuntimeException extends Zend_Http_Exception
+{}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Http/Header/SetCookie.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,546 @@
+<?php
+
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Http
+ * @subpackage Header
+ * @version    $Id$
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+/**
+ * @see Zend_Http_Header_Exception_InvalidArgumentException
+ */
+require_once "Zend/Http/Header/Exception/InvalidArgumentException.php";
+
+/**
+ * @see Zend_Http_Header_Exception_RuntimeException
+ */
+require_once "Zend/Http/Header/Exception/RuntimeException.php";
+
+/**
+ * Zend_Http_Client is an implementation of an HTTP client in PHP. The client
+ * supports basic features like sending different HTTP requests and handling
+ * redirections, as well as more advanced features like proxy settings, HTTP
+ * authentication and cookie persistence (using a Zend_Http_CookieJar object)
+ *
+ * @todo Implement proxy settings
+ * @category   Zend
+ * @package    Zend_Http
+ * @subpackage Header
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Http_Header_SetCookie
+{
+
+    /**
+     * Cookie name
+     *
+     * @var string
+     */
+    protected $name = null;
+
+    /**
+     * Cookie value
+     *
+     * @var string
+     */
+    protected $value = null;
+
+    /**
+     * Version
+     * 
+     * @var integer
+     */
+    protected $version = null;
+    
+    /**
+     * Max Age
+     * 
+     * @var integer
+     */
+    protected $maxAge = null;
+    
+    /**
+     * Cookie expiry date
+     *
+     * @var int
+     */
+    protected $expires = null;
+
+    /**
+     * Cookie domain
+     *
+     * @var string
+     */
+    protected $domain = null;
+
+    /**
+     * Cookie path
+     *
+     * @var string
+     */
+    protected $path = null;
+
+    /**
+     * Whether the cookie is secure or not
+     *
+     * @var boolean
+     */
+    protected $secure = null;
+
+    /**
+     * @var true
+     */
+    protected $httponly = null;
+
+    /**
+     * Generate a new Cookie object from a cookie string
+     * (for example the value of the Set-Cookie HTTP header)
+     *
+     * @static
+     * @throws Zend_Http_Header_Exception_InvalidArgumentException
+     * @param  $headerLine
+     * @param  bool $bypassHeaderFieldName
+     * @return array|SetCookie
+     */
+    public static function fromString($headerLine, $bypassHeaderFieldName = false)
+    {
+        list($name, $value) = explode(': ', $headerLine, 2);
+
+        // check to ensure proper header type for this factory
+        if (strtolower($name) !== 'set-cookie') {
+            throw new Zend_Http_Header_Exception_InvalidArgumentException('Invalid header line for Set-Cookie string: "' . $name . '"');
+        }
+
+        $multipleHeaders = preg_split('#(?<!Sun|Mon|Tue|Wed|Thu|Fri|Sat),\s*#', $value);
+        $headers = array();
+        foreach ($multipleHeaders as $headerLine) {
+            $header = new self();
+            $keyValuePairs = preg_split('#;\s*#', $headerLine);
+            foreach ($keyValuePairs as $keyValue) {
+                if (strpos($keyValue, '=')) {
+                    list($headerKey, $headerValue) = preg_split('#=\s*#', $keyValue, 2);
+                } else {
+                    $headerKey = $keyValue;
+                    $headerValue = null;
+                }
+                
+                // First K=V pair is always the cookie name and value
+                if ($header->getName() === NULL) {
+                    $header->setName($headerKey);
+                    $header->setValue($headerValue);
+                    continue;
+                }
+
+                // Process the remanining elements
+                switch (str_replace(array('-', '_'), '', strtolower($headerKey))) {
+                    case 'expires' : $header->setExpires($headerValue); break;
+                    case 'domain'  : $header->setDomain($headerValue); break;
+                    case 'path'    : $header->setPath($headerValue); break;
+                    case 'secure'  : $header->setSecure(true); break;
+                    case 'httponly': $header->setHttponly(true); break;
+                    case 'version' : $header->setVersion((int) $headerValue); break;
+                    case 'maxage'  : $header->setMaxAge((int) $headerValue); break;
+                    default:
+                        // Intentionally omitted
+                }
+            }
+            $headers[] = $header;
+        }
+        return count($headers) == 1 ? array_pop($headers) : $headers;
+    }
+
+    /**
+     * Cookie object constructor
+     *
+     * @todo Add validation of each one of the parameters (legal domain, etc.)
+     *
+     * @param string $name
+     * @param string $value
+     * @param int $expires
+     * @param string $path
+     * @param string $domain
+     * @param bool $secure
+     * @param bool $httponly
+     * @param string $maxAge
+     * @param int $version
+     * @return SetCookie
+     */
+    public function __construct($name = null, $value = null, $expires = null, $path = null, $domain = null, $secure = false, $httponly = false, $maxAge = null, $version = null)
+    {
+        $this->type = 'Cookie';
+
+        if ($name) {
+            $this->setName($name);
+        }
+
+        if ($value) {
+            $this->setValue($value); // in parent
+        }
+
+        if ($version) {
+            $this->setVersion($version);
+        }
+
+        if ($maxAge) {
+            $this->setMaxAge($maxAge);
+        }
+
+        if ($domain) {
+            $this->setDomain($domain);
+        }
+
+        if ($expires) {
+            $this->setExpires($expires);
+        }
+
+        if ($path) {
+            $this->setPath($path);
+        }
+
+        if ($secure) {
+            $this->setSecure($secure);
+        }
+        
+        if ($httponly) {
+            $this->setHttponly($httponly);
+        }
+    }
+
+    /**
+     * @return string 'Set-Cookie'
+     */
+    public function getFieldName()
+    {
+        return 'Set-Cookie';
+    }
+
+    /**
+     * @throws Zend_Http_Header_Exception_RuntimeException
+     * @return string
+     */
+    public function getFieldValue()
+    {
+        if ($this->getName() == '') {
+            throw new Zend_Http_Header_Exception_RuntimeException('A cookie name is required to generate a field value for this cookie');
+        }
+        
+        $value = $this->getValue();
+        if (strpos($value,'"')!==false) {
+            $value = '"'.urlencode(str_replace('"', '', $value)).'"';
+        } else {
+            $value = urlencode($value);
+        }
+        $fieldValue = $this->getName() . '=' . $value;
+
+        $version = $this->getVersion();
+        if ($version!==null) {
+            $fieldValue .= '; Version=' . $version;
+        }
+        
+        $maxAge = $this->getMaxAge();
+        if ($maxAge!==null) {
+            $fieldValue .= '; Max-Age=' . $maxAge;
+        }
+        
+        $expires = $this->getExpires();
+        if ($expires) {
+            $fieldValue .= '; Expires=' . $expires;
+        }
+
+        $domain = $this->getDomain();
+        if ($domain) {
+            $fieldValue .= '; Domain=' . $domain;
+        }
+
+        $path = $this->getPath();
+        if ($path) {
+            $fieldValue .= '; Path=' . $path;
+        }
+
+        if ($this->isSecure()) {
+            $fieldValue .= '; Secure';
+        }
+
+        if ($this->isHttponly()) {
+            $fieldValue .= '; HttpOnly';
+        }
+
+        return $fieldValue;
+    }
+
+    /**
+     * @param string $name
+     * @return SetCookie
+     */
+    public function setName($name)
+    {
+        if (preg_match("/[=,; \t\r\n\013\014]/", $name)) {
+            throw new Zend_Http_Header_Exception_InvalidArgumentException("Cookie name cannot contain these characters: =,; \\t\\r\\n\\013\\014 ({$name})");
+        }
+
+        $this->name = $name;
+        return $this;
+    }
+
+    /**
+     * @return string
+     */
+    public function getName()
+    {
+        return $this->name;
+    }
+
+    /**
+     * @param string $value
+     */
+    public function setValue($value)
+    {
+        $this->value = $value;
+        return $this;
+    }
+
+    /**
+     * @return string
+     */
+    public function getValue()
+    {
+        return $this->value;
+    }
+
+    /**
+     * Set version
+     * 
+     * @param integer $version
+     */
+    public function setVersion($version)
+    {
+        if (!is_int($version)) {
+            throw new Zend_Http_Header_Exception_InvalidArgumentException('Invalid Version number specified');
+        }
+        $this->version = $version;
+    }
+    
+    /**
+     * Get version
+     * 
+     * @return integer
+     */
+    public function getVersion()
+    {
+        return $this->version;
+    }
+    
+    /**
+     * Set Max-Age
+     * 
+     * @param integer $maxAge
+     */
+    public function setMaxAge($maxAge)
+    {
+        if (!is_int($maxAge) || ($maxAge<0)) {
+            throw new Zend_Http_Header_Exception_InvalidArgumentException('Invalid Max-Age number specified');
+        }
+        $this->maxAge = $maxAge;
+    }
+    
+    /**
+     * Get Max-Age
+     * 
+     * @return integer
+     */
+    public function getMaxAge()
+    {
+        return $this->maxAge;
+    }
+
+    /**
+     * @param int $expires
+     * @return SetCookie
+     */
+    public function setExpires($expires)
+    {
+        if (!empty($expires)) {
+            if (is_string($expires)) {
+                $expires = strtotime($expires);
+            } elseif (!is_int($expires)) {
+                throw new Zend_Http_Header_Exception_InvalidArgumentException('Invalid expires time specified');
+            }
+            $this->expires = (int) $expires;
+        }
+        return $this;
+    }
+
+    /**
+     * @return int
+     */
+    public function getExpires($inSeconds = false)
+    {
+        if ($this->expires == null) {
+            return;
+        }
+        if ($inSeconds) {
+            return $this->expires;
+        }
+        return gmdate('D, d-M-Y H:i:s', $this->expires) . ' GMT';
+    }
+
+    /**
+     * @param string $domain
+     */
+    public function setDomain($domain)
+    {
+        $this->domain = $domain;
+        return $this;
+    }
+
+    /**
+     * @return string
+     */
+    public function getDomain()
+    {
+        return $this->domain;
+    }
+
+    /**
+     * @param string $path
+     */
+    public function setPath($path)
+    {
+        $this->path = $path;
+        return $this;
+    }
+
+    /**
+     * @return string
+     */
+    public function getPath()
+    {
+        return $this->path;
+    }
+
+    /**
+     * @param boolean $secure
+     */
+    public function setSecure($secure)
+    {
+        $this->secure = $secure;
+        return $this;
+    }
+
+    /**
+     * @return boolean
+     */
+    public function isSecure()
+    {
+        return $this->secure;
+    }
+
+    /**
+     * @param bool $httponly
+     */
+    public function setHttponly($httponly)
+    {
+        $this->httponly = $httponly;
+        return $this;
+    }
+
+    /**
+     * @return bool
+     */
+    public function isHttponly()
+    {
+        return $this->httponly;
+    }
+
+    /**
+     * Check whether the cookie has expired
+     *
+     * Always returns false if the cookie is a session cookie (has no expiry time)
+     *
+     * @param int $now Timestamp to consider as "now"
+     * @return boolean
+     */
+    public function isExpired($now = null)
+    {
+        if ($now === null) {
+            $now = time();
+        }
+
+        if (is_int($this->expires) && $this->expires < $now) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Check whether the cookie is a session cookie (has no expiry time set)
+     *
+     * @return boolean
+     */
+    public function isSessionCookie()
+    {
+        return ($this->expires === null);
+    }
+
+    public function isValidForRequest($requestDomain, $path, $isSecure = false)
+    {
+        if ($this->getDomain() && (strrpos($requestDomain, $this->getDomain()) !== false)) {
+            return false;
+        }
+        
+        if ($this->getPath() && (strpos($path, $this->getPath()) !== 0)) {
+            return false;
+        }
+        
+        if ($this->secure && $this->isSecure()!==$isSecure) {
+            return false;
+        }
+        
+        return true;
+
+    }
+
+    public function toString()
+    {
+        return $this->getFieldName() . ': ' . $this->getFieldValue();
+    }
+    
+    public function __toString()
+    {
+        return $this->toString();
+    }
+
+    public function toStringMultipleHeaders(array $headers)
+    {
+        $headerLine = $this->toString();
+        /* @var $header SetCookie */
+        foreach ($headers as $header) {
+            if (!$header instanceof Zend_Http_Header_SetCookie) {
+                throw new Zend_Http_Header_Exception_RuntimeException(
+                    'The SetCookie multiple header implementation can only accept an array of SetCookie headers'
+                );
+            }
+            $headerLine .= ', ' . $header->getFieldValue();
+        }
+        return $headerLine;
+    }
+
+    
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Http/UserAgent/Features/Adapter/Browscap.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,90 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Http
+ * @subpackage UserAgent
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+/**
+ * Zend_Http_UserAgent_Features_Adapter_Interface
+ */
+require_once 'Zend/Http/UserAgent/Features/Adapter.php';
+
+/**
+ * Features adapter utilizing PHP's native browscap support
+ *
+ * Requires that you have a PHP-compatible version of the browscap.ini, per the
+ * instructions at http://php.net/get_browser
+ *
+ * @package    Zend_Http
+ * @subpackage UserAgent
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Http_UserAgent_Features_Adapter_Browscap implements Zend_Http_UserAgent_Features_Adapter
+{
+    /**
+     * Constructor
+     *
+     * Validate that we have browscap support available.
+     * 
+     * @return void
+     * @throws Zend_Http_UserAgent_Features_Exception
+     */
+    public function __construct()
+    {
+        $browscap = ini_get('browscap');
+        if (empty($browscap) || !file_exists($browscap)) {
+            require_once 'Zend/Http/UserAgent/Features/Exception.php';
+            throw new Zend_Http_UserAgent_Features_Exception(sprintf(
+                '%s requires a browscap entry in php.ini pointing to a valid browscap.ini; none present',
+                __CLASS__
+            ));
+        }
+    }
+
+    /**
+     * Get features from request
+     *
+     * @param  array $request $_SERVER variable
+     * @param  array $config ignored; included only to satisfy parent class
+     * @return array
+     */
+    public static function getFromRequest($request, array $config)
+    {
+        $browscap = get_browser($request['http_user_agent'], true);
+        $features = array();
+        foreach ($browscap as $key => $value) {
+            // For a few keys, we need to munge a bit for the device object
+            switch ($key) {
+                case 'browser':
+                    $features['mobile_browser'] = $value;
+                    break;
+                case 'version':
+                    $features['mobile_browser_version'] = $value;
+                    break;
+                case 'platform':
+                    $features['device_os'] = $value;
+                    break;
+                default:
+                    $features[$key] = $value;
+                    break;
+            }
+        }
+        return $features;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Loader/AutoloaderFactory.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,211 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Loader
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+require_once dirname(__FILE__) . '/SplAutoloader.php';
+
+if (class_exists('Zend_Loader_AutoloaderFactory')) return;
+
+/**
+ * @package    Zend_Loader
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+abstract class Zend_Loader_AutoloaderFactory
+{
+    const STANDARD_AUTOLOADER = 'Zend_Loader_StandardAutoloader';
+
+    /**
+     * @var array All autoloaders registered using the factory
+     */
+    protected static $loaders = array();
+
+    /**
+     * @var Zend_Loader_StandardAutoloader StandardAutoloader instance for resolving 
+     * autoloader classes via the include_path
+     */
+    protected static $standardAutoloader;
+
+    /**
+     * Factory for autoloaders
+     *
+     * Options should be an array or Traversable object of the following structure:
+     * <code>
+     * array(
+     *     '<autoloader class name>' => $autoloaderOptions,
+     * )
+     * </code>
+     *
+     * The factory will then loop through and instantiate each autoloader with
+     * the specified options, and register each with the spl_autoloader.
+     *
+     * You may retrieve the concrete autoloader instances later using
+     * {@link getRegisteredAutoloaders()}.
+     *
+     * Note that the class names must be resolvable on the include_path or via
+     * the Zend library, using PSR-0 rules (unless the class has already been
+     * loaded).
+     *
+     * @param  array|Traversable $options (optional) options to use. Defaults to Zend_Loader_StandardAutoloader
+     * @return void
+     * @throws Zend_Loader_Exception_InvalidArgumentException for invalid options
+     * @throws Zend_Loader_Exception_InvalidArgumentException for unloadable autoloader classes
+     */
+    public static function factory($options = null)
+    {
+        if (null === $options) {
+            if (!isset(self::$loaders[self::STANDARD_AUTOLOADER])) {
+                $autoloader = self::getStandardAutoloader();
+                $autoloader->register();
+                self::$loaders[self::STANDARD_AUTOLOADER] = $autoloader;
+            }
+
+            // Return so we don't hit the next check's exception (we're done here anyway)
+            return;
+        }
+
+        if (!is_array($options) && !($options instanceof Traversable)) {
+            require_once 'Exception/InvalidArgumentException.php';
+            throw new Zend_Loader_Exception_InvalidArgumentException(
+                'Options provided must be an array or Traversable'
+            );
+        }
+
+        foreach ($options as $class => $options) {
+            if (!isset(self::$loaders[$class])) {
+                $autoloader = self::getStandardAutoloader();
+                if (!class_exists($class) && !$autoloader->autoload($class)) {
+                    require_once 'Exception/InvalidArgumentException.php';
+                    throw new Zend_Loader_Exception_InvalidArgumentException(sprintf(
+                        'Autoloader class "%s" not loaded', 
+                        $class
+                    ));
+                }
+
+                // unfortunately is_subclass_of is broken on some 5.3 versions
+                // additionally instanceof is also broken for this use case
+                if (version_compare(PHP_VERSION, '5.3.7', '>=')) {
+                        if (!is_subclass_of($class, 'Zend_Loader_SplAutoloader')) {
+                        require_once 'Exception/InvalidArgumentException.php';
+                        throw new Zend_Loader_Exception_InvalidArgumentException(sprintf(
+                            'Autoloader class %s must implement Zend\\Loader\\SplAutoloader', 
+                            $class
+                        ));
+                    }
+                }
+
+                if ($class === self::STANDARD_AUTOLOADER) {
+                    $autoloader->setOptions($options);
+                } else {
+                    $autoloader = new $class($options);
+                }
+                $autoloader->register();
+                self::$loaders[$class] = $autoloader;
+            } else {
+                self::$loaders[$class]->setOptions($options);
+            }
+        }
+    }
+
+    /**
+     * Get an list of all autoloaders registered with the factory
+     *
+     * Returns an array of autoloader instances.
+     *
+     * @return array
+     */
+    public static function getRegisteredAutoloaders()
+    {
+        return self::$loaders;
+    }
+
+    /**
+     * Retrieves an autoloader by class name
+     *
+     * @param string $class
+     * @return Zend_Loader_SplAutoloader
+     * @throws Zend_Loader_Exception_InvalidArgumentException for non-registered class
+     */
+    public static function getRegisteredAutoloader($class)
+    {
+        if (!isset(self::$loaders[$class])) {
+            require_once 'Exception/InvalidArgumentException.php';
+            throw new Zend_Loader_Exception_InvalidArgumentException(sprintf('Autoloader class "%s" not loaded', $class));
+        }
+        return self::$loaders[$class];
+    }
+
+    /**
+     * Unregisters all autoloaders that have been registered via the factory.
+     * This will NOT unregister autoloaders registered outside of the fctory.
+     *
+     * @return void
+     */
+    public static function unregisterAutoloaders()
+    {
+        foreach (self::getRegisteredAutoloaders() as $class => $autoloader) {
+            spl_autoload_unregister(array($autoloader, 'autoload'));
+            unset(self::$loaders[$class]);
+        }
+    }
+
+    /**
+     * Unregister a single autoloader by class name
+     *
+     * @param  string $autoloaderClass
+     * @return bool
+     */
+    public static function unregisterAutoloader($autoloaderClass)
+    {
+        if (!isset(self::$loaders[$autoloaderClass])) {
+            return false;
+        }
+
+        $autoloader = self::$loaders[$autoloaderClass];
+        spl_autoload_unregister(array($autoloader, 'autoload'));
+        unset(self::$loaders[$autoloaderClass]);
+        return true;
+    }
+
+    /**
+     * Get an instance of the standard autoloader
+     *
+     * Used to attempt to resolve autoloader classes, using the 
+     * StandardAutoloader. The instance is marked as a fallback autoloader, to 
+     * allow resolving autoloaders not under the "Zend" or "Zend" namespaces.
+     * 
+     * @return Zend_Loader_SplAutoloader
+     */
+    protected static function getStandardAutoloader()
+    {
+        if (null !== self::$standardAutoloader) {
+            return self::$standardAutoloader;
+        }
+
+        // Extract the filename from the classname
+        $stdAutoloader = substr(strrchr(self::STANDARD_AUTOLOADER, '_'), 1);
+
+        if (!class_exists(self::STANDARD_AUTOLOADER)) {
+            require_once dirname(__FILE__) . "/$stdAutoloader.php";
+        }
+        $loader = new Zend_Loader_StandardAutoloader();
+        self::$standardAutoloader = $loader;
+        return self::$standardAutoloader;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Loader/ClassMapAutoloader.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,248 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Loader
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+// Grab SplAutoloader interface
+require_once dirname(__FILE__) . '/SplAutoloader.php';
+
+/**
+ * Class-map autoloader
+ *
+ * Utilizes class-map files to lookup classfile locations.
+ * 
+ * @package    Zend_Loader
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    New BSD {@link http://framework.zend.com/license/new-bsd}
+ */
+class Zend_Loader_ClassMapAutoloader implements Zend_Loader_SplAutoloader
+{
+    /**
+     * Registry of map files that have already been loaded
+     * @var array
+     */
+    protected $mapsLoaded = array();
+
+    /**
+     * Class name/filename map
+     * @var array
+     */
+    protected $map = array();
+
+    /**
+     * Constructor
+     *
+     * Create a new instance, and optionally configure the autoloader.
+     * 
+     * @param  null|array|Traversable $options 
+     * @return void
+     */
+    public function __construct($options = null)
+    {
+        if (null !== $options) {
+            $this->setOptions($options);
+        }
+    }
+
+    /**
+     * Configure the autoloader
+     *
+     * Proxies to {@link registerAutoloadMaps()}.
+     * 
+     * @param  array|Traversable $options 
+     * @return Zend_Loader_ClassMapAutoloader
+     */
+    public function setOptions($options)
+    {
+        $this->registerAutoloadMaps($options);
+        return $this;
+    }
+
+    /**
+     * Register an autoload map
+     *
+     * An autoload map may be either an associative array, or a file returning
+     * an associative array.
+     *
+     * An autoload map should be an associative array containing 
+     * classname/file pairs.
+     * 
+     * @param  string|array $location 
+     * @return Zend_Loader_ClassMapAutoloader
+     */
+    public function registerAutoloadMap($map)
+    {
+        if (is_string($map)) {
+            $location = $map;
+            if ($this === ($map = $this->loadMapFromFile($location))) {
+                return $this;
+            }
+        }
+
+        if (!is_array($map)) {
+            require_once dirname(__FILE__) . '/Exception/InvalidArgumentException.php';
+            throw new Zend_Loader_Exception_InvalidArgumentException('Map file provided does not return a map');
+        }
+
+        $this->map = array_merge($this->map, $map);
+
+        if (isset($location)) {
+            $this->mapsLoaded[] = $location;
+        }
+
+        return $this;
+    }
+
+    /**
+     * Register many autoload maps at once
+     * 
+     * @param  array $locations 
+     * @return Zend_Loader_ClassMapAutoloader
+     */
+    public function registerAutoloadMaps($locations)
+    {
+        if (!is_array($locations) && !($locations instanceof Traversable)) {
+            require_once dirname(__FILE__) . '/Exception/InvalidArgumentException.php';
+            throw new Zend_Loader_Exception_InvalidArgumentException('Map list must be an array or implement Traversable');
+        }
+        foreach ($locations as $location) {
+            $this->registerAutoloadMap($location);
+        }
+        return $this;
+    }
+
+    /**
+     * Retrieve current autoload map
+     * 
+     * @return array
+     */
+    public function getAutoloadMap()
+    {
+        return $this->map;
+    }
+
+    /**
+     * Defined by Autoloadable
+     * 
+     * @param  string $class 
+     * @return void
+     */
+    public function autoload($class)
+    {
+        if (isset($this->map[$class])) {
+            require_once $this->map[$class];
+        }
+    }
+
+    /**
+     * Register the autoloader with spl_autoload registry
+     * 
+     * @return void
+     */
+    public function register()
+    {
+        if (version_compare(PHP_VERSION, '5.3.0', '>=')) {
+            spl_autoload_register(array($this, 'autoload'), true, true);
+        } else {
+            spl_autoload_register(array($this, 'autoload'), true);
+        }
+    }
+
+    /**
+     * Load a map from a file
+     *
+     * If the map has been previously loaded, returns the current instance;
+     * otherwise, returns whatever was returned by calling include() on the
+     * location.
+     * 
+     * @param  string $location 
+     * @return Zend_Loader_ClassMapAutoloader|mixed
+     * @throws Zend_Loader_Exception_InvalidArgumentException for nonexistent locations
+     */
+    protected function loadMapFromFile($location)
+    {
+        if (!file_exists($location)) {
+            require_once dirname(__FILE__) . '/Exception/InvalidArgumentException.php';
+            throw new Zend_Loader_Exception_InvalidArgumentException('Map file provided does not exist');
+        }
+
+        if (!$path = self::realPharPath($location)) {
+            $path = realpath($location);
+        }
+
+        if (in_array($path, $this->mapsLoaded)) {
+            // Already loaded this map
+            return $this;
+        }
+
+        $map = include $path;
+
+        return $map;
+    }
+
+    /**
+     * Resolve the real_path() to a file within a phar.
+     *
+     * @see    https://bugs.php.net/bug.php?id=52769 
+     * @param  string $path 
+     * @return string
+     */
+    public static function realPharPath($path)
+    {
+        if (strpos($path, 'phar:///') !== 0) {
+            return;
+        }
+        
+        $parts = explode('/', str_replace(array('/','\\'), '/', substr($path, 8)));
+        $parts = array_values(array_filter($parts, array(__CLASS__, 'concatPharParts')));
+
+        array_walk($parts, array(__CLASS__, 'resolvePharParentPath'), $parts);
+
+        if (file_exists($realPath = 'phar:///' . implode('/', $parts))) {
+            return $realPath;
+        }
+    }
+
+    /**
+     * Helper callback for filtering phar paths
+     * 
+     * @param  string $part 
+     * @return bool
+     */
+    public static function concatPharParts($part)
+    {
+        return ($part !== '' && $part !== '.');
+    }
+
+    /**
+     * Helper callback to resolve a parent path in a Phar archive
+     * 
+     * @param  string $value 
+     * @param  int $key 
+     * @param  array $parts 
+     * @return void
+     */
+    public static function resolvePharParentPath($value, $key, &$parts)
+    {
+        if ($value !== '...') {
+            return;
+        }
+        unset($parts[$key], $parts[$key-1]);
+        $parts = array_values($parts);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Loader/Exception/InvalidArgumentException.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,34 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Loader
+ * @subpackage Exception
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+require_once dirname(__FILE__) . '/../Exception.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Loader
+ * @subpackage Exception
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Loader_Exception_InvalidArgumentException
+    extends Zend_Loader_Exception
+{
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Loader/SplAutoloader.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,75 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Loader
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+if (interface_exists('Zend_Loader_SplAutoloader')) return;
+
+/**
+ * Defines an interface for classes that may register with the spl_autoload 
+ * registry
+ *
+ * @package    Zend_Loader
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+interface Zend_Loader_SplAutoloader
+{
+    /**
+     * Constructor
+     *
+     * Allow configuration of the autoloader via the constructor.
+     * 
+     * @param  null|array|Traversable $options 
+     * @return void
+     */
+    public function __construct($options = null);
+
+    /**
+     * Configure the autoloader
+     *
+     * In most cases, $options should be either an associative array or 
+     * Traversable object.
+     * 
+     * @param  array|Traversable $options 
+     * @return SplAutoloader
+     */
+    public function setOptions($options);
+
+    /**
+     * Autoload a class
+     *
+     * @param   $class
+     * @return  mixed
+     *          False [if unable to load $class]
+     *          get_class($class) [if $class is successfully loaded]
+     */
+    public function autoload($class);
+
+    /**
+     * Register the autoloader with spl_autoload registry
+     *
+     * Typically, the body of this will simply be:
+     * <code>
+     * spl_autoload_register(array($this, 'autoload'));
+     * </code>
+     * 
+     * @return void
+     */
+    public function register();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Loader/StandardAutoloader.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,368 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Loader
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+// Grab SplAutoloader interface
+require_once dirname(__FILE__) . '/SplAutoloader.php';
+
+/**
+ * PSR-0 compliant autoloader
+ *
+ * Allows autoloading both namespaced and vendor-prefixed classes. Class
+ * lookups are performed on the filesystem. If a class file for the referenced
+ * class is not found, a PHP warning will be raised by include().
+ *
+ * @package    Zend_Loader
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    New BSD {@link http://framework.zend.com/license/new-bsd}
+ */
+class Zend_Loader_StandardAutoloader implements Zend_Loader_SplAutoloader
+{
+    const NS_SEPARATOR     = '\\';
+    const PREFIX_SEPARATOR = '_';
+    const LOAD_NS          = 'namespaces';
+    const LOAD_PREFIX      = 'prefixes';
+    const ACT_AS_FALLBACK  = 'fallback_autoloader';
+    const AUTOREGISTER_ZF  = 'autoregister_zf';
+
+    /**
+     * @var array Namespace/directory pairs to search; ZF library added by default
+     */
+    protected $namespaces = array();
+
+    /**
+     * @var array Prefix/directory pairs to search
+     */
+    protected $prefixes = array();
+
+    /**
+     * @var bool Whether or not the autoloader should also act as a fallback autoloader
+     */
+    protected $fallbackAutoloaderFlag = false;
+
+    /**
+     * @var bool
+     */
+    protected $error;
+
+    /**
+     * Constructor
+     *
+     * @param  null|array|Traversable $options
+     * @return void
+     */
+    public function __construct($options = null)
+    {
+        if (null !== $options) {
+            $this->setOptions($options);
+        }
+    }
+
+    /**
+     * Configure autoloader
+     *
+     * Allows specifying both "namespace" and "prefix" pairs, using the
+     * following structure:
+     * <code>
+     * array(
+     *     'namespaces' => array(
+     *         'Zend'     => '/path/to/Zend/library',
+     *         'Doctrine' => '/path/to/Doctrine/library',
+     *     ),
+     *     'prefixes' => array(
+     *         'Phly_'     => '/path/to/Phly/library',
+     *     ),
+     *     'fallback_autoloader' => true,
+     * )
+     * </code>
+     *
+     * @param  array|Traversable $options
+     * @return Zend_Loader_StandardAutoloader
+     */
+    public function setOptions($options)
+    {
+        if (!is_array($options) && !($options instanceof Traversable)) {
+            require_once dirname(__FILE__) . '/Exception/InvalidArgumentException.php';
+            throw new Zend_Loader_Exception_InvalidArgumentException('Options must be either an array or Traversable');
+        }
+
+        foreach ($options as $type => $pairs) {
+            switch ($type) {
+                case self::AUTOREGISTER_ZF:
+                    if ($pairs) {
+                        $this->registerPrefix('Zend', dirname(dirname(__FILE__)));
+                    }
+                    break;
+                case self::LOAD_NS:
+                    if (is_array($pairs) || $pairs instanceof Traversable) {
+                        $this->registerNamespaces($pairs);
+                    }
+                    break;
+                case self::LOAD_PREFIX:
+                    if (is_array($pairs) || $pairs instanceof Traversable) {
+                        $this->registerPrefixes($pairs);
+                    }
+                    break;
+                case self::ACT_AS_FALLBACK:
+                    $this->setFallbackAutoloader($pairs);
+                    break;
+                default:
+                    // ignore
+            }
+        }
+        return $this;
+    }
+
+    /**
+     * Set flag indicating fallback autoloader status
+     *
+     * @param  bool $flag
+     * @return Zend_Loader_StandardAutoloader
+     */
+    public function setFallbackAutoloader($flag)
+    {
+        $this->fallbackAutoloaderFlag = (bool) $flag;
+        return $this;
+    }
+
+    /**
+     * Is this autoloader acting as a fallback autoloader?
+     *
+     * @return bool
+     */
+    public function isFallbackAutoloader()
+    {
+        return $this->fallbackAutoloaderFlag;
+    }
+
+    /**
+     * Register a namespace/directory pair
+     *
+     * @param  string $namespace
+     * @param  string $directory
+     * @return Zend_Loader_StandardAutoloader
+     */
+    public function registerNamespace($namespace, $directory)
+    {
+        $namespace = rtrim($namespace, self::NS_SEPARATOR). self::NS_SEPARATOR;
+        $this->namespaces[$namespace] = $this->normalizeDirectory($directory);
+        return $this;
+    }
+
+    /**
+     * Register many namespace/directory pairs at once
+     *
+     * @param  array $namespaces
+     * @return Zend_Loader_StandardAutoloader
+     */
+    public function registerNamespaces($namespaces)
+    {
+        if (!is_array($namespaces) && !$namespaces instanceof Traversable) {
+            require_once dirname(__FILE__) . '/Exception/InvalidArgumentException.php';
+            throw new Zend_Loader_Exception_InvalidArgumentException('Namespace pairs must be either an array or Traversable');
+        }
+
+        foreach ($namespaces as $namespace => $directory) {
+            $this->registerNamespace($namespace, $directory);
+        }
+        return $this;
+    }
+
+    /**
+     * Register a prefix/directory pair
+     *
+     * @param  string $prefix
+     * @param  string $directory
+     * @return Zend_Loader_StandardAutoloader
+     */
+    public function registerPrefix($prefix, $directory)
+    {
+        $prefix = rtrim($prefix, self::PREFIX_SEPARATOR). self::PREFIX_SEPARATOR;
+        $this->prefixes[$prefix] = $this->normalizeDirectory($directory);
+        return $this;
+    }
+
+    /**
+     * Register many namespace/directory pairs at once
+     *
+     * @param  array $prefixes
+     * @return Zend_Loader_StandardAutoloader
+     */
+    public function registerPrefixes($prefixes)
+    {
+        if (!is_array($prefixes) && !$prefixes instanceof Traversable) {
+            require_once dirname(__FILE__) . '/Exception/InvalidArgumentException.php';
+            throw new Zend_Loader_Exception_InvalidArgumentException('Prefix pairs must be either an array or Traversable');
+        }
+
+        foreach ($prefixes as $prefix => $directory) {
+            $this->registerPrefix($prefix, $directory);
+        }
+        return $this;
+    }
+
+    /**
+     * Defined by Autoloadable; autoload a class
+     *
+     * @param  string $class
+     * @return false|string
+     */
+    public function autoload($class)
+    {
+        $isFallback = $this->isFallbackAutoloader();
+        if (false !== strpos($class, self::NS_SEPARATOR)) {
+            if ($this->loadClass($class, self::LOAD_NS)) {
+                return $class;
+            } elseif ($isFallback) {
+                return $this->loadClass($class, self::ACT_AS_FALLBACK);
+            }
+            return false;
+        }
+        if (false !== strpos($class, self::PREFIX_SEPARATOR)) {
+            if ($this->loadClass($class, self::LOAD_PREFIX)) {
+                return $class;
+            } elseif ($isFallback) {
+                return $this->loadClass($class, self::ACT_AS_FALLBACK);
+            }
+            return false;
+        }
+        if ($isFallback) {
+            return $this->loadClass($class, self::ACT_AS_FALLBACK);
+        }
+        return false;
+    }
+
+    /**
+     * Register the autoloader with spl_autoload
+     *
+     * @return void
+     */
+    public function register()
+    {
+        spl_autoload_register(array($this, 'autoload'));
+    }
+
+    /**
+     * Error handler
+     *
+     * Used by {@link loadClass} during fallback autoloading in PHP versions
+     * prior to 5.3.0.
+     * 
+     * @param mixed $errno 
+     * @param mixed $errstr 
+     * @return void
+     */
+    public function handleError($errno, $errstr)
+    {
+        $this->error = true;
+    }
+
+    /**
+     * Transform the class name to a filename
+     *
+     * @param  string $class
+     * @param  string $directory
+     * @return string
+     */
+    protected function transformClassNameToFilename($class, $directory)
+    {
+        // $class may contain a namespace portion, in  which case we need
+        // to preserve any underscores in that portion.
+        $matches = array();
+        preg_match('/(?P<namespace>.+\\\)?(?P<class>[^\\\]+$)/', $class, $matches);
+
+        $class     = (isset($matches['class'])) ? $matches['class'] : '';
+        $namespace = (isset($matches['namespace'])) ? $matches['namespace'] : '';
+
+        return $directory
+             . str_replace(self::NS_SEPARATOR, '/', $namespace)
+             . str_replace(self::PREFIX_SEPARATOR, '/', $class)
+             . '.php';
+    }
+
+    /**
+     * Load a class, based on its type (namespaced or prefixed)
+     *
+     * @param  string $class
+     * @param  string $type
+     * @return void
+     */
+    protected function loadClass($class, $type)
+    {
+        if (!in_array($type, array(self::LOAD_NS, self::LOAD_PREFIX, self::ACT_AS_FALLBACK))) {
+            require_once dirname(__FILE__) . '/Exception/InvalidArgumentException.php';
+            throw new Zend_Loader_Exception_InvalidArgumentException();
+        }
+
+        // Fallback autoloading
+        if ($type === self::ACT_AS_FALLBACK) {
+            // create filename
+            $filename = $this->transformClassNameToFilename($class, '');
+            if (version_compare(PHP_VERSION, '5.3.2', '>=')) {
+                $resolvedName = stream_resolve_include_path($filename);
+                if ($resolvedName !== false) {
+                    return include $resolvedName;
+                }
+                return false;
+            }
+            $this->error = false;
+            set_error_handler(array($this, 'handleError'), E_WARNING);
+            include $filename;
+            restore_error_handler();
+            if ($this->error) {
+                return false;
+            }
+            return class_exists($class, false);
+        }
+
+        // Namespace and/or prefix autoloading
+        foreach ($this->$type as $leader => $path) {
+            if (0 === strpos($class, $leader)) {
+                // Trim off leader (namespace or prefix)
+                $trimmedClass = substr($class, strlen($leader));
+
+                // create filename
+                $filename = $this->transformClassNameToFilename($trimmedClass, $path);
+                if (file_exists($filename)) {
+                    return include $filename;
+                }
+                return false;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Normalize the directory to include a trailing directory separator
+     *
+     * @param  string $directory
+     * @return string
+     */
+    protected function normalizeDirectory($directory)
+    {
+        $last = $directory[strlen($directory) - 1];
+        if (in_array($last, array('/', '\\'))) {
+            $directory[strlen($directory) - 1] = DIRECTORY_SEPARATOR;
+            return $directory;
+        }
+        $directory .= DIRECTORY_SEPARATOR;
+        return $directory;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Log/Formatter/Abstract.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,40 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Log
+ * @subpackage Formatter
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: Abstract.php 24593 2012-01-05 20:35:02Z matthew $
+ */
+
+/** @see Zend_Log_Formatter_Interface */
+require_once 'Zend/Log/Formatter/Interface.php';
+
+/** @see Zend_Log_FactoryInterface */
+require_once 'Zend/Log/FactoryInterface.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Log
+ * @subpackage Formatter
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: Abstract.php 24593 2012-01-05 20:35:02Z matthew $
+ */
+abstract class Zend_Log_Formatter_Abstract
+    implements Zend_Log_Formatter_Interface, Zend_Log_FactoryInterface
+{
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Mobile/Exception.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,33 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/** Zend_Exception */
+require_once 'Zend/Exception.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+class Zend_Mobile_Exception extends Zend_Exception
+{}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Mobile/Push/Abstract.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,112 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/** Zend_Mobile_Push_Interface **/
+require_once 'Zend/Mobile/Push/Interface.php';
+
+/** Zend_Mobile_Push_Exception **/
+require_once 'Zend/Mobile/Push/Exception.php';
+
+/**
+ * Push Abstract
+ *
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+abstract class Zend_Mobile_Push_Abstract implements Zend_Mobile_Push_Interface
+{
+    /**
+     * Is Connected
+     *
+     * @var boolean
+     */
+    protected $_isConnected = false;
+
+    /**
+     * Connect to the Push Server
+     * 
+     * @return Zend_Mobile_Push_Abstract
+     */
+    public function connect()
+    {
+        $this->_isConnected = true;
+        return $this;
+    }
+
+    /**
+     * Send a Push Message
+     *
+     * @param Zend_Mobile_Push_Message_Abstract $message
+     * @return boolean
+     * @throws DomainException
+     */
+    public function send(Zend_Mobile_Push_Message_Abstract $message)
+    {
+        if (!$this->_isConnected) {
+            $this->connect();
+        }
+        return true;
+    }
+
+    /**
+     * Close the Connection to the Push Server
+     *
+     * @return void
+     */
+    public function close()
+    {
+        $this->_isConnected = false;
+    }
+
+    /**
+     * Is Connected
+     *
+     * @return boolean
+     */
+    public function isConnected()
+    {
+        return $this->_isConnected;
+    }
+
+    /**
+     * Set Options
+     *
+     * @param array $options
+     * @return Zend_Mobile_Push_Abstract
+     * @throws Zend_Mobile_Push_Exception
+     */
+    public function setOptions(array $options)
+    {
+        foreach ($options as $k => $v) {
+            $method = 'set' . ucwords($k);
+            if (!method_exists($this, $method)) {
+                throw new Zend_Mobile_Push_Exception('The method "' . $method . "' does not exist.");
+            }
+            $this->$method($v);
+        }
+        return $this;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Mobile/Push/Apns.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,391 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/** Zend_Mobile_Push_Abstract **/
+require_once 'Zend/Mobile/Push/Abstract.php';
+
+/** Zend_Mobile_Push_Message_Apns **/
+require_once 'Zend/Mobile/Push/Message/Apns.php';
+
+/**
+ * APNS Push
+ *
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+class Zend_Mobile_Push_Apns extends Zend_Mobile_Push_Abstract
+{
+
+    /**
+     * @const int apple server uri constants
+     */
+    const SERVER_SANDBOX_URI = 0;
+    const SERVER_PRODUCTION_URI = 1;
+    const SERVER_FEEDBACK_SANDBOX_URI = 2;
+    const SERVER_FEEDBACK_PRODUCTION_URI = 3;
+
+    /**
+     * Apple Server URI's
+     *
+     * @var array
+     */
+    protected $_serverUriList = array(
+        'ssl://gateway.sandbox.push.apple.com:2195',
+        'ssl://gateway.push.apple.com:2195',
+        'ssl://feedback.sandbox.push.apple.com:2196',
+        'ssl://feedback.push.apple.com:2196'
+    );
+
+    /**
+     * Current Environment
+     *
+     * @var int
+     */
+    protected $_currentEnv;
+
+    /**
+     * Socket
+     *
+     * @var resource
+     */
+    protected $_socket;
+
+    /**
+     * Certificate
+     *
+     * @var string
+     */
+    protected $_certificate;
+
+    /**
+     * Certificate Passphrase
+     *
+     * @var string
+     */
+    protected $_certificatePassphrase;
+
+    /**
+     * Get Certficiate
+     *
+     * @return string
+     */
+    public function getCertificate()
+    {
+        return $this->_certificate;
+    }
+
+    /**
+     * Set Certificate
+     *
+     * @param  string $cert
+     * @return Zend_Mobile_Push_Apns
+     * @throws Zend_Mobile_Push_Exception
+     */
+    public function setCertificate($cert)
+    {
+        if (!is_string($cert)) {
+            throw new Zend_Mobile_Push_Exception('$cert must be a string');
+        }
+        if (!file_exists($cert)) {
+            throw new Zend_Mobile_Push_Exception('$cert must be a valid path to the certificate');
+        }
+        $this->_certificate = $cert;
+        return $this;
+    }
+
+    /**
+     * Get Certificate Passphrase
+     *
+     * @return string
+     */
+    public function getCertificatePassphrase()
+    {
+        return $this->_certificatePassphrase;
+    }
+
+    /**
+     * Set Certificate Passphrase
+     *
+     * @param  string $passphrase
+     * @return Zend_Mobile_Push_Apns
+     * @throws Zend_Mobile_Push_Exception
+     */
+    public function setCertificatePassphrase($passphrase)
+    {
+        if (!is_string($passphrase)) {
+            throw new Zend_Mobile_Push_Exception('$passphrase must be a string');
+        }
+        $this->_certificatePassphrase = $passphrase;
+        return $this;
+    }
+
+    /**
+     * Connect to Socket
+     *
+     * @param  string $uri
+     * @return bool
+     * @throws Zend_Mobile_Push_Exception_ServerUnavailable
+     */
+    protected function _connect($uri)
+    {
+        $ssl = array(
+            'local_cert' => $this->_certificate,
+        );
+        if ($this->_certificatePassphrase) {
+            $ssl['passphrase'] = $this->_certificatePassphrase;
+        }
+
+        $this->_socket = stream_socket_client($uri,
+            $errno,
+            $errstr,
+            ini_get('default_socket_timeout'),
+            STREAM_CLIENT_CONNECT,
+            stream_context_create(array(
+                'ssl' => $ssl,
+            ))
+        );
+
+        if (!is_resource($this->_socket)) {
+            require_once 'Zend/Mobile/Push/Exception/ServerUnavailable.php';
+            throw new Zend_Mobile_Push_Exception_ServerUnavailable(sprintf('Unable to connect: %s: %d (%s)',
+                $uri,
+                $errno,
+                $errstr
+            ));
+        }
+
+        stream_set_blocking($this->_socket, 0);
+        stream_set_write_buffer($this->_socket, 0);
+        return true;
+    }
+
+    /**
+    * Read from the Socket Server
+    * 
+    * @param int $length
+    * @return string
+    */
+    protected function _read($length) {
+        $data = false;
+        if (!feof($this->_socket)) {
+            $data = fread($this->_socket, $length);
+        }
+        return $data;
+    }
+
+    /**
+    * Write to the Socket Server
+    * 
+    * @param string $payload
+    * @return int
+    */
+    protected function _write($payload) {
+        return @fwrite($this->_socket, $payload);
+    }
+
+    /**
+     * Connect to the Push Server
+     *
+     * @param string $env
+     * @return Zend_Mobile_Push_Abstract
+     * @throws Zend_Mobile_Push_Exception
+     * @throws Zend_Mobile_Push_Exception_ServerUnavailable
+     */
+    public function connect($env = self::SERVER_PRODUCTION_URI)
+    {
+        if ($this->_isConnected) {
+            if ($this->_currentEnv == self::SERVER_PRODUCTION_URI) {
+                return $this;
+            }
+            $this->close();
+        }
+
+        if (!isset($this->_serverUriList[$env])) {
+            throw new Zend_Mobile_Push_Exception('$env is not a valid environment');
+        }
+
+        if (!$this->_certificate) {
+            throw new Zend_Mobile_Push_Exception('A certificate must be set prior to calling ::connect');
+        }
+
+        $this->_connect($this->_serverUriList[$env]);
+
+        $this->_currentEnv = $env;
+        $this->_isConnected = true;
+        return $this;
+    }
+
+
+
+    /**
+     * Feedback
+     *
+     * @return array array w/ key = token and value = time
+     * @throws Zend_Mobile_Push_Exception
+     * @throws Zend_Mobile_Push_Exception_ServerUnavailable
+     */
+    public function feedback()
+    {
+        if (!$this->_isConnected ||
+            !in_array($this->_currentEnv,
+                array(self::SERVER_FEEDBACK_SANDBOX_URI, self::SERVER_FEEDBACK_PRODUCTION_URI))) {
+            $this->connect(self::SERVER_FEEDBACK_PRODUCTION_URI);
+        }
+
+        $tokens = array();
+        while ($token = $this->_read(38)) {
+            if (strlen($token) < 38) {
+                continue;
+            }
+            $token = unpack('Ntime/ntokenLength/H*token', $token);
+            if (!isset($tokens[$token['token']]) || $tokens[$token['token']] < $token['time']) {
+                $tokens[$token['token']] = $token['time'];
+            }
+        }
+        return $tokens;
+    }
+
+    /**
+     * Send Message
+     *
+     * @param Zend_Mobile_Push_Message_Apns $message
+     * @return boolean
+     * @throws Zend_Mobile_Push_Exception
+     * @throws Zend_Mobile_Push_Exception_ServerUnavailable
+     * @throws Zend_Mobile_Push_Exception_InvalidToken
+     * @throws Zend_Mobile_Push_Exception_InvalidTopic
+     * @throws Zend_Mobile_Push_Exception_InvalidPayload
+     */
+    public function send(Zend_Mobile_Push_Message_Abstract $message)
+    {
+        if (!$message->validate()) {
+            throw new Zend_Mobile_Push_Exception('The message is not valid.');
+        }
+
+        if (!$this->_isConnected || !in_array($this->_currentEnv, array(
+            self::SERVER_SANDBOX_URI,
+            self::SERVER_PRODUCTION_URI))) {
+            $this->connect(self::SERVER_PRODUCTION_URI);
+        }
+
+        $payload = array('aps' => array());
+
+        $alert = $message->getAlert();
+        foreach ($alert as $k => $v) {
+            if ($v == null) {
+                unset($alert[$k]);
+            }
+        }
+        if (!empty($alert)) {
+            $payload['aps']['alert'] = $alert;
+        }
+        if (!is_null($message->getBadge())) {
+            $payload['aps']['badge'] = $message->getBadge();
+        }
+        $payload['aps']['sound'] = $message->getSound();
+
+        foreach($message->getCustomData() as $k => $v) {
+            $payload[$k] = $v;
+        }
+        $payload = json_encode($payload);
+
+        $expire = $message->getExpire();
+        if ($expire > 0) {
+            $expire += time();
+        }
+        $id = $message->getId();
+        if (empty($id)) {
+            $id = time();
+        }
+
+        $payload = pack('CNNnH*', 1, $id, $expire, 32, $message->getToken())
+            . pack('n', strlen($payload))
+            . $payload;
+        $ret = $this->_write($payload);
+        if ($ret === false) {
+            require_once 'Zend/Mobile/Push/Exception/ServerUnavailable.php';
+            throw new Zend_Mobile_Push_Exception_ServerUnavailable('Unable to send message');
+        }
+        // check for errors from apple
+        $err = $this->_read(1024);
+        if (strlen($err) > 0) {
+            $err = unpack('Ccmd/Cerrno/Nid', $err);
+            switch ($err['errno']) {
+                case 0:
+                    return true;
+                    break;
+                case 1:
+                    throw new Zend_Mobile_Push_Exception('A processing error has occurred on the apple push notification server.');
+                    break;
+                case 2:
+                    require_once 'Zend/Mobile/Push/Exception/InvalidToken.php';
+                    throw new Zend_Mobile_Push_Exception_InvalidToken('Missing token; you must set a token for the message.');
+                    break;
+                case 3:
+                    require_once 'Zend/Mobile/Push/Exception/InvalidTopic.php';
+                    throw new Zend_Mobile_Push_Exception_InvalidTopic('Missing id; you must set an id for the message.');
+                    break;
+                case 4:
+                    require_once 'Zend/Mobile/Push/Exception/InvalidPayload.php';
+                    throw new Zend_Mobile_Push_Exception_InvalidPayload('Missing message; the message must always have some content.');
+                    break;
+                case 5:
+                    require_once 'Zend/Mobile/Push/Exception/InvalidToken.php';
+                    throw new Zend_Mobile_Push_Exception_InvalidToken('Bad token.  This token is too big and is not a regular apns token.');
+                    break;
+                case 6:
+                    require_once 'Zend/Mobile/Push/Exception/InvalidTopic.php';
+                    throw new Zend_Mobile_Push_Exception_InvalidTopic('The message id is too big; reduce the size of the id.');
+                    break;
+                case 7:
+                    require_once 'Zend/Mobile/Push/Exception/InvalidPayload.php';
+                    throw new Zend_Mobile_Push_Exception_InvalidPayload('The message is too big; reduce the size of the message.');
+                    break;
+                case 8:
+                    require_once 'Zend/Mobile/Push/Exception/InvalidToken.php';
+                    throw new Zend_Mobile_Push_Exception_InvalidToken('Bad token.  Remove this token from being sent to again.');
+                    break;
+                default:
+                    throw new Zend_Mobile_Push_Exception(sprintf('An unknown error occurred: %d', $err['errno']));
+                    break;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Close Connection
+     *
+     * @return void
+     */
+    public function close()
+    {
+        if ($this->_isConnected && is_resource($this->_socket)) {
+            fclose($this->_socket);
+        }
+        $this->_isConnected = false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Mobile/Push/Exception.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,35 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/** Zend_Mobile_Exception */
+require_once 'Zend/Mobile/Exception.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+class Zend_Mobile_Push_Exception extends Zend_Mobile_Exception
+{}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Mobile/Push/Exception/DeviceQuotaExceeded.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,35 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/** Zend_Mobile_Push_Exception */
+require_once 'Zend/Mobile/Push/Exception.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+class Zend_Mobile_Push_Exception_DeviceQuotaExceeded extends Zend_Mobile_Push_Exception
+{}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Mobile/Push/Exception/InvalidAuthToken.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,35 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/** Zend_Mobile_Push_Exception */
+require_once 'Zend/Mobile/Push/Exception.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+class Zend_Mobile_Push_Exception_InvalidAuthToken extends Zend_Mobile_Push_Exception
+{}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Mobile/Push/Exception/InvalidPayload.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,35 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/** Zend_Mobile_Push_Exception */
+require_once 'Zend/Mobile/Push/Exception.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+class Zend_Mobile_Push_Exception_InvalidPayload extends Zend_Mobile_Push_Exception
+{}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Mobile/Push/Exception/InvalidRegistration.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,35 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/** Zend_Mobile_Push_Exception */
+require_once 'Zend/Mobile/Push/Exception.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+class Zend_Mobile_Push_Exception_InvalidRegistration extends Zend_Mobile_Push_Exception
+{}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Mobile/Push/Exception/InvalidToken.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,35 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/** Zend_Mobile_Push_Exception */
+require_once 'Zend/Mobile/Push/Exception.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+class Zend_Mobile_Push_Exception_InvalidToken extends Zend_Mobile_Push_Exception
+{}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Mobile/Push/Exception/InvalidTopic.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,35 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/** Zend_Mobile_Push_Exception */
+require_once 'Zend/Mobile/Push/Exception.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+class Zend_Mobile_Push_Exception_InvalidTopic extends Zend_Mobile_Push_Exception
+{}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Mobile/Push/Exception/QuotaExceeded.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,35 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/** Zend_Mobile_Push_Exception */
+require_once 'Zend/Mobile/Push/Exception.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+class Zend_Mobile_Push_Exception_QuotaExceeded extends Zend_Mobile_Push_Exception
+{}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Mobile/Push/Exception/ServerUnavailable.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,35 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/** Zend_Mobile_Push_Exception */
+require_once 'Zend/Mobile/Push/Exception.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+class Zend_Mobile_Push_Exception_ServerUnavailable extends Zend_Mobile_Push_Exception
+{}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Mobile/Push/Gcm.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,172 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/** Zend_Http_Client **/
+require_once 'Zend/Http/Client.php';
+
+/** Zend_Mobile_Push_Abstract **/
+require_once 'Zend/Mobile/Push/Abstract.php';
+
+/** Zend_Mobile_Push_Message_Gcm **/
+require_once 'Zend/Mobile/Push/Message/Gcm.php';
+
+/** Zend_Mobile_Push_Response_Gcm **/
+require_once 'Zend/Mobile/Push/Response/Gcm.php';
+
+/**
+ * GCM Push
+ *
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+class Zend_Mobile_Push_Gcm extends Zend_Mobile_Push_Abstract
+{
+
+    /**
+     * @const string Server URI
+     */
+    const SERVER_URI = 'https://android.googleapis.com/gcm/send';
+
+    /**
+     * Http Client
+     *
+     * @var Client
+     */
+    protected $_httpClient;
+
+    /**
+     * API Key
+     *
+     * @var string
+     */
+    protected $_apiKey;
+
+    /**
+     * Get API Key
+     *
+     * @return string
+     */
+    public function getApiKey()
+    {
+        return $this->_apiKey;
+    }
+
+    /**
+     * Set API Key
+     *
+     * @param  string $key
+     * @return Zend_Mobile_Push_Gcm
+     * @throws Zend_Mobile_Push_Exception
+     */
+    public function setApiKey($key)
+    {
+        if (!is_string($key) || empty($key)) {
+            throw new Zend_Mobile_Push_Exception('The api key must be a string and not empty');
+        }
+        $this->_apiKey = $key;
+        return $this;
+    }
+
+    /**
+     * Get Http Client
+     *
+     * @return Zend_Http_Client
+     */
+    public function getHttpClient()
+    {
+        if (!$this->_httpClient) {
+            $this->_httpClient = new Zend_Http_Client();
+            $this->_httpClient->setConfig(array(
+                'strictredirects' => true,
+            ));
+        }
+        return $this->_httpClient;
+    }
+
+    /**
+     * Set Http Client
+     *
+     * @return Zend_Mobile_Push_Gcm
+     */
+    public function setHttpClient(Zend_Http_Client $client)
+    {
+        $this->_httpClient = $client;
+        return $this;
+    }
+
+    /**
+     * Send Message
+     *
+     * @param Zend_Mobile_Push_Message_Gcm $message
+     * @return Zend_Mobile_Push_Response_Gcm
+     * @throws Zend_Mobile_Push_Exception
+     */
+    public function send(Zend_Mobile_Push_Message_Abstract $message)
+    {
+        if (!$message->validate()) {
+            throw new Zend_Mobile_Push_Exception('The message is not valid.');
+        }
+
+        $this->connect();
+
+        $client = $this->getHttpClient();
+        $client->setUri(self::SERVER_URI);
+        $client->setHeaders('Authorization', 'key=' . $this->getApiKey());
+
+        $json = array('registration_ids' => $message->getToken());
+        if ($data = $message->getData()) {
+            $json['data'] = $data;
+        }
+        if ($id = $message->getId()) {
+            $json['id'] = $id;
+        }
+
+        $response = $client->setRawData($message->toJson(), 'application/json')
+                           ->request('POST');
+        $this->close();
+
+        switch ($response->getStatus())
+        {
+            case 500:
+                require_once 'Zend/Mobile/Push/Exception/ServerUnavailable.php';
+                throw new Zend_Mobile_Push_Exception_ServerUnavailable('The server encountered an internal error, try again');
+                break;
+            case 503:
+                require_once 'Zend/Mobile/Push/Exception/ServerUnavailable.php';
+                throw new Zend_Mobile_Push_Exception_ServerUnavailable('The server was unavailable, check Retry-After header');
+                break;
+            case 401:
+                require_once 'Zend/Mobile/Push/Exception/InvalidAuthToken.php';
+                throw new Zend_Mobile_Push_Exception_InvalidAuthToken('There was an error authenticating the sender account');
+                break;
+            case 400:
+                require_once 'Zend/Mobile/Push/Exception/InvalidPayload.php';
+                throw new Zend_Mobile_Push_Exception_InvalidPayload('The request could not be parsed as JSON or contains invalid fields');
+                break;
+        }
+        return new Zend_Mobile_Push_Response_Gcm($response->getBody(), $message);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Mobile/Push/Interface.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,64 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/**
+ * Push Interface
+ *
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+interface Zend_Mobile_Push_Interface
+{
+    /**
+     * Connect to the Push Server
+     *
+     * @return Push
+     */
+    public function connect();
+
+    /**
+     * Send a Push Message
+     *
+     * @param Zend_Mobile_Push_Message_Interface $message
+     * @return boolean
+     */
+    public function send(Zend_Mobile_Push_Message_Abstract $message);
+
+    /**
+     * Close the Connection to the Push Server
+     *
+     * @return void
+     */
+    public function close();
+
+    /**
+     * Set Options
+     *
+     * @param array $options
+     * @return Zend_Mobile_Push_Abstract
+     */
+    public function setOptions(array $options);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Mobile/Push/Message/Abstract.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,135 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/** Zend_Mobile_Push_Message_Interface **/
+require_once 'Zend/Mobile/Push/Message/Interface.php';
+
+/** Zend_Mobile_Push_Message_Exception **/
+require_once 'Zend/Mobile/Push/Message/Exception.php';
+
+/**
+ * Message Abstract
+ *
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push_Message
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+abstract class Zend_Mobile_Push_Message_Abstract implements Zend_Mobile_Push_Message_Interface
+{
+    /**
+     * Token
+     *
+     * @var string
+     */
+    protected $_token;
+
+    /**
+     * Id
+     *
+     * @var scalar
+     */
+    protected $_id;
+
+    /**
+     * Get Token
+     *
+     * @return string
+     */
+    public function getToken()
+    {
+        return $this->_token;
+    }
+
+    /**
+     * Set Token
+     *
+     * @param  string $token
+     * @return Zend_Mobile_Push_Message_Abstract
+     */
+    public function setToken($token)
+    {
+        if (!is_string($token)) {
+            throw new Zend_Mobile_Push_Message_Exception('$token must be a string');
+        }
+        $this->_token = $token;
+        return $this;
+    }
+
+    /**
+     * Get Message ID
+     * 
+     * @return scalar
+     */
+    public function getId()
+    {
+        return $this->_id;
+    }
+
+    /**
+     * Set Message ID
+     *
+     * @param scalar $id
+     * @return Zend_Mobile_Push_Message_Abstract
+     * @throws Exception
+     */
+    public function setId($id)
+    {
+        if (!is_scalar($id)) {
+            throw new Zend_Mobile_Push_Message_Exception('$id must be a scalar');
+        }
+        $this->_id = $id;
+        return $this;
+    }
+
+    /**
+     * Set Options
+     *
+     * @param array $options
+     * @return Zend_Mobile_Push_Message_Abstract
+     * @throws Zend_Mobile_Push_Message_Exception
+     */
+    public function setOptions(array $options)
+    {
+        foreach ($options as $k => $v) {
+            $method = 'set' . ucwords($k);
+            if (!method_exists($this, $method)) {
+                throw new Zend_Mobile_Push_Message_Exception('The method "' . $method . "' does not exist.");
+            }
+            $this->$method($v);
+        }
+        return $this;
+    }
+
+
+    /**
+     * Validate Message format
+     *
+     * @return boolean
+     */
+    public function validate()
+    {
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Mobile/Push/Message/Apns.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,284 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/** Zend_Mobile_Push_Message_Abstract **/
+require_once 'Zend/Mobile/Push/Message/Abstract.php';
+
+/**
+ * Apns Message
+ *
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+class Zend_Mobile_Push_Message_Apns extends Zend_Mobile_Push_Message_Abstract
+{
+    /**
+     * Badge Number
+     *
+     * @var int
+     */
+    protected $_badge;
+
+    /**
+     * Alert
+     *
+     * @var array
+     */
+    protected $_alert  = array();
+
+    /**
+     * Expiration
+     *
+     * @var int
+     */
+    protected $_expire;
+
+    /**
+     * Sound
+     *
+     * @var string
+     */
+    protected $_sound = 'default';
+
+    /**
+     * Custom Data
+     *
+     * @var array
+     */
+    protected $_custom = array();
+
+    /**
+     * Get Alert
+     *
+     * @return array
+     */
+    public function getAlert()
+    {
+        return $this->_alert;
+    }
+
+    /**
+     * Set Alert
+     *
+     * @param string $text
+     * @param string $actionLocKey
+     * @param string $locKey
+     * @param array $locArgs
+     * @param string $launchImage
+     * @return Zend_Mobile_Push_Message_Apns
+     */
+    public function setAlert($text, $actionLocKey=null, $locKey=null, $locArgs=null, $launchImage=null)
+    {
+        if ($text !== null && !is_string($text)) {
+            throw new Zend_Mobile_Push_Message_Exception('$text must be a string');
+        }
+
+        if ($actionLocKey !== null && !is_string($actionLocKey)) {
+            throw new Zend_Mobile_Push_Message_Exception('$actionLocKey must be a string');
+        }
+
+        if ($locKey !== null && !is_string($locKey)) {
+            throw new Zend_Mobile_Push_Message_Exception('$locKey must be a string');
+        }
+
+        if ($locArgs !== null) {
+            if (!is_array($locArgs)) {
+                throw new Zend_Mobile_Push_Message_Exception('$locArgs must be an array of strings');
+            } else {
+                foreach ($locArgs as $str) {
+                    if (!is_string($str)) {
+                        throw new Zend_Mobile_Push_Message_Exception('$locArgs contains an item that is not a string');
+                    }
+                }
+            }
+        }
+
+        if (null !== $launchImage && !is_string($launchImage)) {
+            throw new Zend_Mobile_Push_Message_Exception('$launchImage must be a string');
+        }
+
+        $this->_alert = array(
+            'body'           => $text,
+            'action-loc-key' => $actionLocKey,
+            'loc-key'        => $locKey,
+            'loc-args'       => $locArgs,
+            'launch-image'   => $launchImage,
+        );
+        return $this;
+    }
+
+    /**
+     * Get Badge
+     *
+     * @return int
+     */
+    public function getBadge()
+    {
+        return $this->_badge;
+    }
+
+    /**
+     * Set Badge
+     *
+     * @param int $badge
+     * @return Zend_Mobile_Push_Message_Apns
+     * @throws Zend_Mobile_Push_Message_Exception
+     */
+    public function setBadge($badge)
+    {
+        if (!is_null($badge) && !is_numeric($badge)) {
+            throw new Zend_Mobile_Push_Message_Exception('$badge must be an integer');
+        }
+        if (!is_null($badge) && $badge < 0) {
+            throw new Zend_Mobile_Push_Message_Exception('$badge must be greater or equal to 0');
+        }
+        $this->_badge = $badge;
+    }
+
+    /**
+     * Get Expire
+     *
+     * @return int
+     */
+    public function getExpire()
+    {
+        return $this->_expire;
+    }
+
+    /**
+     * Set Expire
+     *
+     * @param int $expire
+     * @return Zend_Mobile_Push_Message_Apns
+     * @throws Zend_Mobile_Push_Message_Exception
+     */
+    public function setExpire($expire)
+    {
+        if (!is_numeric($expire)) {
+            throw new Zend_Mobile_Push_Message_Exception('$expire must be an integer');
+        }
+        $this->_expire = (int) $expire;
+        return $this;
+    }
+
+    /**
+     * Get Sound
+     *
+     * @return string
+     */
+    public function getSound()
+    {
+        return $this->_sound;
+    }
+
+    /**
+     * Set Sound
+     *
+     * @param string $sound
+     * @return Zend_Mobile_Push_Message_Apns
+     * @throws Zend_Mobile_Push_Message_Exception
+     */
+    public function setSound($sound)
+    {
+        if (!is_string($sound)) {
+            throw new Zend_Mobile_Push_Message_Exception('$sound must be a string');
+        }
+        $this->_sound = $sound;
+        return $this;
+    }
+
+    /**
+     * Add Custom Data
+     *
+     * @param string $key
+     * @param mixed $value
+     * @return Zend_Mobile_Push_Message_Apns
+     * @throws Zend_Mobile_Push_Message_Exception
+     */
+    public function addCustomData($key, $value)
+    {
+        if (!is_string($key)) {
+            throw new Zend_Mobile_Push_Message_Exception('$key is not a string');
+        }
+        if ($key == 'aps') {
+            throw new Zend_Mobile_Push_Message_Exception('$key must not be aps as it is reserved by apple');
+        }
+        $this->_custom[$key] = $value;
+    }
+
+    /**
+     * Clear Custom Data
+     *
+     * @return throw new Zend_Mobile_Push_Message_Apns
+     */
+    public function clearCustomData()
+    {
+        $this->_custom = array();
+        return $this;
+    }
+
+    /**
+     * Set Custom Data
+     *
+     * @param array $data
+     * @return Zend_Mobile_Push_Message_Apns
+     * @throws Zend_Mobile_Push_Message_Exception
+     */
+    public function setCustomData($array)
+    {
+        $this->_custom = array();
+        foreach ($array as $k => $v) {
+            $this->addCustomData($k, $v);
+        }
+        return $this;
+    }
+
+    /**
+     * Get Custom Data
+     *
+     * @return array
+     */
+    public function getCustomData()
+    {
+        return $this->_custom;
+    }
+
+    /**
+     * Validate this is a proper Apns message
+     *
+     * @return boolean
+     */
+    public function validate()
+    {
+        if (!is_string($this->_token) || strlen($this->_token) === 0) {
+            return false;
+        }
+        if (null != $this->_id && !is_numeric($this->_id)) {
+            return false;
+        }
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Mobile/Push/Message/Exception.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,35 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/** Zend_Mobile_Push_Exception */
+require_once 'Zend/Mobile/Push/Exception.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+class Zend_Mobile_Push_Message_Exception extends Zend_Mobile_Exception
+{}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Mobile/Push/Message/Gcm.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,274 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/** Zend_Mobile_Push_Message_Abstract **/
+require_once 'Zend/Mobile/Push/Message/Abstract.php';
+
+/**
+ * Gcm Message
+ *
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ * @method     array getToken()
+ */
+class Zend_Mobile_Push_Message_Gcm extends Zend_Mobile_Push_Message_Abstract
+{
+
+    /**
+     * Tokens
+     *
+     * @var array
+     */
+    protected $_token = array();
+
+    /**
+     * Data key value pairs
+     * 
+     * @var array
+     */
+    protected $_data = array();
+
+    /**
+     * Delay while idle
+     *
+     * @var boolean
+     */
+    protected $_delay = false;
+
+    /**
+     * Time to live in seconds
+     * 
+     * @var int
+     */
+    protected $_ttl = 0;
+
+    /**
+     * Add a Token
+     *
+     * @param  string $token
+     * @return Zend_Mobile_Push_Message_Gcm
+     * @throws Zend_Mobile_Push_Message_Exception
+     */
+    public function addToken($token)
+    {
+        if (!is_string($token)) {
+            throw new Zend_Mobile_Push_Message_Exception('$token must be a string');
+        }
+        if (!in_array($token, $this->_token)) {
+           $this->_token[] = $token;
+        }
+        return $this;
+    }
+
+    /**
+     * Set Token
+     *
+     * @param  string|array $token
+     * @return Zend_Mobile_Push_Message_Gcm
+     * @throws Zend_Mobile_Push_Message_Exception
+     */
+    public function setToken($token)
+    {
+        $this->clearToken();
+        if (is_string($token)) {
+            $this->addToken($token);
+        } else if (is_array($token)) {
+            foreach ($token as $t) {
+                $this->addToken($t);
+            }
+        }
+        return $this;
+    }
+
+    /**
+     * Clear Tokens
+     *
+     * @return Zend_Mobile_Push_Message_Gcm
+     */
+    public function clearToken()
+    {
+        $this->_token = array();
+        return $this;
+    }
+
+
+    /**
+     * Add Data
+     *
+     * @param  string $key
+     * @param  string $value
+     * @return Zend_Mobile_Push_Message_Gcm
+     * @throws Zend_Mobile_Push_Message_Exception
+     */
+    public function addData($key, $value)
+    {
+        if (!is_string($key)) {
+            throw new Zend_Mobile_Push_Message_Exception('$key is not a string');
+        }
+        if (!is_scalar($value)) {
+            throw new Zend_Mobile_Push_Message_Exception('$value is not a string');
+        }
+        $this->_data[$key] = $value;
+        return $this;
+    }
+
+    /**
+     * Set Data
+     *
+     * @param array $data
+     * @return Zend_Mobile_Push_Message_Gcm
+     * @throws Zend_Mobile_Push_Message_Exception
+     */
+    public function setData(array $data)
+    {
+        $this->clearData();
+        foreach ($data as $k => $v) {
+            $this->addData($k, $v);
+        }
+        return $this;
+    }
+
+    /**
+     * Clear Data
+     *
+     * @return Zend_Mobile_Push_Message_Gcm
+     */
+    public function clearData()
+    {
+        $this->_data = array();
+        return $this;
+    }
+
+    /**
+     * Get Data
+     *
+     * @return array
+     */
+    public function getData()
+    {
+        return $this->_data;
+    }
+
+    /**
+     * Set Delay While Idle
+     *
+     * @param boolean $delay
+     * @return Zend_Mobile_Push_Message_Gcm
+     * @throws Zend_Mobile_Push_Message_Exception
+     */
+    public function setDelayWhileIdle($delay)
+    {
+        if (!is_bool($delay)) {
+            throw new Zend_Mobile_Push_Message_Exception('$delay must be boolean');
+        }
+        $this->_delay = $delay;
+        return $this;
+    }
+
+    /**
+     * Get Delay While Idle
+     *
+     * @return boolean
+     */
+    public function getDelayWhileIdle()
+    {
+        return $this->_delay;
+    }
+
+    /**
+     * Set time to live
+     * If $secs is set to 0 it will be handled as
+     * not being set.
+     *
+     * @param  int $secs
+     * @return Zend_Mobile_Push_Message_Gcm
+     */
+    public function setTtl($secs)
+    {
+        if (!is_numeric($secs)) {
+            throw new Zend_Mobile_Push_Message_Exception('$secs must be numeric');
+        }
+        $this->_ttl = (int) $secs;
+        return $this;
+    }
+
+    /**
+     * Get time to live
+     *
+     * @return int
+     */
+    public function getTtl()
+    {
+        return $this->_ttl;
+    }
+
+    /**
+     * Validate this is a proper Gcm message
+     * Does not validate size.
+     *
+     * @return boolean
+     */
+    public function validate()
+    {
+        if (!is_array($this->_token) || empty($this->_token)) {
+            return false;
+        }
+        if ($this->_ttl > 0 &&
+            (!is_scalar($this->_id) ||
+            strlen($this->_id) === 0)) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * To Json utility method
+     * Takes the data and properly assigns it to
+     * a json encoded array to match the Gcm format.
+     *
+     * @return string
+     */
+    public function toJson()
+    {
+        $json = array();
+        if ($this->_token) {
+            $json['registration_ids'] = $this->_token;
+        }
+        if ($this->_id) {
+            $json['collapse_key'] = (string) $this->_id;
+        }
+        if ($this->_data) {
+            $json['data'] = $this->_data;
+        }
+        if ($this->_delay) {
+            $json['delay_while_idle'] = $this->_delay;
+        }
+        if ($this->_ttl) {
+            $json['time_to_live'] = $this->_ttl;
+        }
+        return json_encode($json);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Mobile/Push/Message/Interface.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,79 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/**
+ * Push Message Interface
+ *
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+interface Zend_Mobile_Push_Message_Interface
+{
+    /**
+     * Get Token
+     *
+     * @return string
+     */
+    public function getToken();
+
+    /**
+     * Set Token
+     *
+     * @param string $token
+     * @return Zend_Mobile_Push_Message_Abstract
+     */
+    public function setToken($token);
+
+    /**
+     * Get Id
+     *
+     * @return scalar
+     */
+    public function getId();
+
+    /**
+     * Set Id
+     *
+     * @param scalar $id
+     * @return Zend_Mobile_Push_Message_Abstract
+     */
+    public function setId($id);
+
+    /**
+     * Set Options
+     *
+     * @param array $options
+     * @return Zend_Mobile_Push_Message_Abstract
+     */
+    public function setOptions(array $options);
+
+    /**
+     * Validate Message
+     *
+     * @return boolean
+     */
+    public function validate();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Mobile/Push/Message/Mpns.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,117 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+/** Zend_Mobile_Push_Message_Abstract **/
+require_once 'Zend/Mobile/Push/Message/Abstract.php';
+
+/** Zend_Uri **/
+require_once 'Zend/Uri.php';
+
+/**
+ * Mpns Message
+ *
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+abstract class Zend_Mobile_Push_Message_Mpns extends Zend_Mobile_Push_Message_Abstract
+{
+    /**
+     * Mpns types
+     *
+     * @var string
+     */
+    const TYPE_RAW = 'raw';
+    const TYPE_TILE = 'token';
+    const TYPE_TOAST = 'toast';
+
+    /**
+     * Delay
+     *
+     * @var int
+     */
+    protected $_delay;
+
+    /**
+     * Get Delay
+     *
+     * @return int
+     */
+    abstract public function getDelay();
+
+    /**
+     * Set Delay
+     *
+     * @param int $delay one of const DELAY_* of implementing classes
+     * @return Zend_Mobile_Push_Message_Mpns
+     */
+    abstract public function setDelay($delay);
+
+    /**
+     * Get Notification Type
+     *
+     * @return string
+     */
+    public static function getNotificationType()
+    {
+        return "";
+    }
+
+    /**
+     * Set Token
+     *
+     * @param string $token
+     * @return Zend_Mobile_Push_Message_Mpns
+     * @throws Zend_Mobile_Push_Message_Exception
+     */
+    public function setToken($token)
+    {
+        if (!is_string($token)) {
+            throw new Zend_Mobile_Push_Message_Exception('$token is not a string');
+        }
+        if (!Zend_Uri::check($token)) {
+            throw new Zend_Mobile_Push_Message_Exception('$token is not a valid URI');
+        }
+        return parent::setToken($token);
+    }
+
+    /**
+     * Get XML Payload
+     *
+     * @return string
+     */
+    abstract public function getXmlPayload();
+
+    /**
+     * Validate proper mpns message
+     *
+     * @return boolean
+     */
+    public function validate()
+    {
+        if (!isset($this->_token) || strlen($this->_token) === 0) {
+            return false;
+        }
+        return parent::validate();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Mobile/Push/Message/Mpns/Raw.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,149 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+/** Zend_Mobile_Push_Message_Mpns **/
+require_once 'Zend/Mobile/Push/Message/Mpns.php';
+
+/**
+ * Mpns Raw Message
+ *
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Mobile_Push_Message_Mpns_Raw extends Zend_Mobile_Push_Message_Mpns
+{
+    /**
+     * Mpns delays
+     *
+     * @var int
+     */
+    const DELAY_IMMEDIATE = 3;
+    const DELAY_450S = 13;
+    const DELAY_900S = 23;
+
+    /**
+     * Message
+     *
+     * @var string
+     */
+    protected $_msg;
+
+    /**
+     * Get Delay
+     *
+     * @return int
+     */
+    public function getDelay()
+    {
+        if (!$this->_delay) {
+            return self::DELAY_IMMEDIATE;
+        }
+        return $this->_delay;
+    }
+
+    /**
+     * Set Delay
+     *
+     * @param int $delay
+     * @return Zend_Mobile_Push_Message_Mpns_Raw
+     * @throws Zend_Mobile_Push_Message_Exception
+     */
+    public function setDelay($delay)
+    {
+        if (!in_array($delay, array(
+            self::DELAY_IMMEDIATE,
+            self::DELAY_450S,
+            self::DELAY_900S
+        ))) {
+            throw new Zend_Mobile_Push_Message_Exception('$delay must be one of the DELAY_* constants');
+        }
+        $this->_delay = $delay;
+        return $this;
+    }
+
+    /**
+     * Set Message
+     *
+     * @param string $msg XML string
+     * @return Zend_Mobile_Push_Message_Mpns_Raw
+     * @throws Zend_Mobile_Push_Message_Exception
+     */
+    public function setMessage($msg)
+    {
+        if (!is_string($msg)) {
+            throw new Zend_Mobile_Push_Message_Exception('$msg is not a string');
+        }
+        if (!simplexml_load_string($msg)) {
+            throw new Zend_Mobile_Push_Message_Exception('$msg is not valid xml');
+        }
+        $this->_msg = $msg;
+        return $this;
+    }
+
+    /**
+     * Get Message
+     *
+     * @return string
+     */
+    public function getMessage()
+    {
+        return $this->_msg;
+    }
+
+    /**
+     * Get Notification Type
+     *
+     * @return string
+     */
+    public static function getNotificationType()
+    {
+        return 'raw';
+    }
+
+    /**
+     * Get XML Payload
+     *
+     * @return string
+     */
+    public function getXmlPayload()
+    {
+        return $this->_msg;
+    }
+
+    /**
+     * Validate proper mpns message
+     *
+     * @return boolean
+     */
+    public function validate()
+    {
+        if (!isset($this->_token) || strlen($this->_token) === 0) {
+            return false;
+        }
+        if (empty($this->_msg)) {
+            return false;
+        }
+        return parent::validate();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Mobile/Push/Message/Mpns/Tile.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,365 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+/** Zend_Mobile_Push_Message_Mpns **/
+require_once 'Zend/Mobile/Push/Message/Mpns.php';
+
+/**
+ * Mpns Tile Message
+ *
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Mobile_Push_Message_Mpns_Tile extends Zend_Mobile_Push_Message_Mpns
+{
+    /**
+     * Mpns delays
+     *
+     * @var int
+     */
+    const DELAY_IMMEDIATE = 1;
+    const DELAY_450S = 11;
+    const DELAY_900S = 21;
+
+    /**
+     * Background Image
+     *
+     * @var string
+     */
+    protected $_backgroundImage;
+
+    /**
+     * Count
+     *
+     * @var int
+     */
+    protected $_count = 0;
+
+    /**
+     * Title
+     *
+     * @var string
+     */
+    protected $_title;
+
+    /**
+     * Back Background Image
+     *
+     * @var string
+     */
+    protected $_backBackgroundImage;
+
+    /**
+     * Back Title
+     *
+     * @var string
+     */
+    protected $_backTitle;
+
+    /**
+     * Back Content
+     *
+     * @var string
+     */
+    protected $_backContent;
+
+    /**
+     * Tile ID
+     *
+     * @var string
+     */
+    protected $_tileId;
+
+    /**
+     * Get Background Image
+     *
+     * @return string
+     */
+    public function getBackgroundImage()
+    {
+        return $this->_backgroundImage;
+    }
+
+    /**
+     * Set Background Image
+     *
+     * @param string $bgImg
+     * @return Zend_Mobile_Push_Message_Mpns_Tile
+     * @throws Zend_Mobile_Push_Message_Exception
+     */
+    public function setBackgroundImage($bgImg)
+    {
+        if (!is_string($bgImg)) {
+            throw new Zend_Mobile_Push_Message_Exception('$bgImg must be a string');
+        }
+        $this->_backgroundImage = $bgImg;
+        return $this;
+    }
+
+    /**
+     * Get Count
+     *
+     * @return int
+     */
+    public function getCount()
+    {
+        return $this->_count;
+    }
+
+    /**
+     * Set Count
+     *
+     * @param int $count
+     * @return Zend_Mobile_Push_Message_Mpns_Tile
+     * @throws Zend_Mobile_Push_Message_Exception
+     */
+    public function setCount($count)
+    {
+        if (!is_numeric($count)) {
+            throw new Zend_Mobile_Push_Message_Exception('$count is not numeric');
+        }
+        $this->_count = (int) $count;
+        return $this;
+    }
+
+    /**
+     * Get Title
+     *
+     * @return string
+     */
+    public function getTitle()
+    {
+        return $this->_title;
+    }
+
+    /**
+     * Set Title
+     *
+     * @param string $title
+     * @return Zend_Mobile_Push_Message_Mpns_Tile
+     * @throws Zend_Mobile_Push_Message_Exception
+     */
+    public function setTitle($title)
+    {
+        if (!is_string($title)) {
+            throw new Zend_Mobile_Push_Message_Exception('$title must be a string');
+        }
+        $this->_title = $title;
+        return $this;
+    }
+
+    /**
+     * Get Back Background Image
+     *
+     * @return string
+     */
+    public function getBackBackgroundImage()
+    {
+        return $this->_backBackgroundImage;
+    }
+
+    /**
+     * Set Back Background Image
+     *
+     * @param string $bgImg
+     * @return Zend_Mobile_Push_Message_Mpns_Tile
+     * @throws Zend_Mobile_Push_Message_Exception
+     */
+    public function setBackBackgroundImage($bgImg)
+    {
+        if (!is_string($bgImg)) {
+            throw new Zend_Mobile_Push_Message_Exception('$bgImg must be a string');
+        }
+        $this->_backBackgroundImage = $bgImg;
+        return $this;
+    }
+
+    /**
+     * Get Back Title
+     *
+     * @return string
+     */
+    public function getBackTitle()
+    {
+        return $this->_backTitle;
+    }
+
+    /**
+     * Set Back Title
+     *
+     * @param string $title
+     * @return Zend_Mobile_Push_Message_Mpns_Tile
+     * @throws Zend_Mobile_Push_Message_Exception
+     */
+    public function setBackTitle($title)
+    {
+        if (!is_string($title)) {
+            throw new Zend_Mobile_Push_Message_Exception('$title must be a string');
+        }
+        $this->_backTitle = $title;
+        return $this;
+    }
+
+    /**
+     * Get Back Content
+     *
+     * @return string
+     */
+    public function getBackContent()
+    {
+        return $this->_backContent;
+    }
+
+    /**
+     * Set Back Content
+     * 
+     * @param string $content
+     * @return Zend_Mobile_Push_Message_Mpns_Tile
+     * @throws Zend_Mobile_Push_Message_Exception
+     */
+    public function setBackContent($content)
+    {
+        if (!is_string($content)) {
+            throw new Zend_Mobile_Push_Message_Exception('$content must be a string');
+        }
+        $this->_backContent = $content;
+    }
+
+    /**
+     * Get Tile Id
+     *
+     * @return string
+     */
+    public function getTileId()
+    {
+        return $this->_tileId;
+    }
+
+    /**
+     * Set Tile Id
+     *
+     * @param string $tileId
+     * @return Zend_Mobile_Push_Message_Mpns_Tile
+     * @throws Zend_Mobile_Push_Message_Exception
+     */
+    public function setTileId($tileId)
+    {
+        if (!is_string($tileId)) {
+            throw new Zend_Mobile_Push_Message_Exception('$tileId is not a string');
+        }
+        $this->_tileId = $tileId;
+        return $this;
+    }
+
+    /**
+     * Get Delay
+     *
+     * @return int
+     */
+    public function getDelay()
+    {
+        if (!$this->_delay) {
+            return self::DELAY_IMMEDIATE;
+        }
+        return $this->_delay;
+    }
+
+    /**
+     * Set Delay
+     *
+     * @param int $delay
+     * @return Zend_Mobile_Push_Message_Mpns_Tile
+     * @throws Zend_Mobile_Push_Message_Exception
+     */
+    public function setDelay($delay)
+    {
+        if (!in_array($delay, array(
+            self::DELAY_IMMEDIATE,
+            self::DELAY_450S,
+            self::DELAY_900S
+        ))) {
+            throw new Zend_Mobile_Push_Message_Exception('$delay must be one of the DELAY_* constants');
+        }
+        $this->_delay = $delay;
+        return $this;
+    }
+
+    /**
+     * Get Notification Type
+     *
+     * @return string
+     */
+    public static function getNotificationType()
+    {
+        return 'token';
+    }
+
+    /**
+     * Get XML Payload
+     *
+     * @return string
+     */
+    public function getXmlPayload()
+    {
+        $ret = '<?xml version="1.0" encoding="utf-8"?>'
+            . '<wp:Notification xmlns:wp="WPNotification">'
+            . '<wp:Tile' . (($this->_tileId) ? ' Id="' . htmlspecialchars($this->_tileId) . '"' : '') . '>'
+            . '<wp:BackgroundImage>' . htmlspecialchars($this->_backgroundImage) . '</wp:BackgroundImage>'
+            . '<wp:Count>' . (int) $this->_count . '</wp:Count>'
+            . '<wp:Title>' . htmlspecialchars($this->_title) . '</wp:Title>';
+
+        if ($this->_backBackgroundImage) {
+            $ret .= '<wp:BackBackgroundImage>' . htmlspecialchars($this->_backBackgroundImage) . '</wp:BackBackgroundImage>';
+        }
+        if ($this->_backTitle) {
+            $ret .= '<wp:BackTitle>' . htmlspecialchars($this->_backTitle) . '</wp:BackTitle>';
+        }
+        if ($this->_backContent) {
+            $ret .= '<wp:BackContent>' . htmlspecialchars($this->_backContent) . '</wp:BackContent>';
+        }
+
+        $ret .= '</wp:Tile>'
+            . '</wp:Notification>';
+        return $ret;
+    }
+
+    /**
+     * Validate proper mpns message
+     *
+     * @return boolean
+     */
+    public function validate()
+    {
+        if (!isset($this->_token) || strlen($this->_token) === 0) {
+            return false;
+        }
+        if (empty($this->_backgroundImage)) {
+            return false;
+        }
+        if (empty($this->_title)) {
+            return false;
+        }
+        return parent::validate();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Mobile/Push/Message/Mpns/Toast.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,225 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+/** Zend_Mobile_Push_Message_Mpns **/
+require_once 'Zend/Mobile/Push/Message/Mpns.php';
+
+/**
+ * Mpns Toast Message
+ *
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Mobile_Push_Message_Mpns_Toast extends Zend_Mobile_Push_Message_Mpns
+{
+    /**
+     * Mpns delays
+     *
+     * @var int
+     */
+    const DELAY_IMMEDIATE = 2;
+    const DELAY_450S = 12;
+    const DELAY_900S = 22;
+
+    /**
+     * Title
+     *
+     * @var string
+     */
+    protected $_title;
+
+    /**
+     * Message
+     *
+     * @var string
+     */
+    protected $_msg;
+
+    /**
+     * Params
+     *
+     * @var string
+     */
+    protected $_params;
+
+    /**
+     * Get Title
+     *
+     * @return string
+     */
+    public function getTitle()
+    {
+        return $this->_title;
+    }
+
+    /**
+     * Set Title
+     *
+     * @param string $title
+     * @return Zend_Mobile_Push_Message_Mpns_Toast
+     * @throws Zend_Mobile_Push_Message_Exception
+     */
+    public function setTitle($title)
+    {
+        if (!is_string($title)) {
+            throw new Zend_Mobile_Push_Message_Exception('$title must be a string');
+        }
+        $this->_title = $title;
+        return $this;
+    }
+
+    /**
+     * Get Message
+     *
+     * @return string
+     */
+    public function getMessage()
+    {
+        return $this->_msg;
+    }
+
+    /**
+     * Set Message
+     *
+     * @param string $msg
+     * @return Zend_Mobile_Push_Message_Mpns_Toast
+     * @throws Zend_Mobile_Push_Message_Exception
+     */
+    public function setMessage($msg)
+    {
+        if (!is_string($msg)) {
+            throw new Zend_Mobile_Push_Message_Exception('$msg must be a string');
+        }
+        $this->_msg = $msg;
+        return $this;
+    }
+
+    /**
+     * Get Params
+     *
+     * @return string
+     */
+    public function getParams()
+    {
+        return $this->_params;
+    }
+
+    /**
+     * Set Params
+     *
+     * @param string $params
+     * @return Zend_Mobile_Push_Message_Mpns_Toast
+     * @throws Zend_Mobile_Push_Message_Exception
+     */
+    public function setParams($params)
+    {
+        if (!is_string($params)) {
+            throw new Zend_Mobile_Push_Message_Exception('$params must be a string');
+        }
+        $this->_params = $params;
+        return $this;
+    }
+
+    /**
+     * Get Delay
+     *
+     * @return int
+     */
+    public function getDelay()
+    {
+        if (!$this->_delay) {
+            return self::DELAY_IMMEDIATE;
+        }
+        return $this->_delay;
+    }
+
+    /**
+     * Set Delay
+     *
+     * @param int $delay
+     * @return Zend_Mobile_Push_Message_Mpns_Toast
+     * @throws Zend_Mobile_Push_Message_Exception
+     */
+    public function setDelay($delay)
+    {
+        if (!in_array($delay, array(
+            self::DELAY_IMMEDIATE,
+            self::DELAY_450S,
+            self::DELAY_900S
+        ))) {
+            throw new Zend_Mobile_Push_Message_Exception('$delay must be one of the DELAY_* constants');
+        }
+        $this->_delay = $delay;
+        return $this;
+    }
+
+    /**
+     * Get Notification Type
+     *
+     * @return string
+     */
+    public static function getNotificationType()
+    {
+        return 'toast';
+    }
+
+    /**
+     * Get XML Payload
+     *
+     * @return string
+     */
+    public function getXmlPayload()
+    {
+        $ret = '<?xml version="1.0" encoding="utf-8"?>'
+            . '<wp:Notification xmlns:wp="WPNotification">'
+            . '<wp:Toast>'
+            . '<wp:Text1>' . htmlspecialchars($this->_title) . '</wp:Text1>'
+            . '<wp:Text2>' . htmlspecialchars($this->_msg) . '</wp:Text2>';
+        if (!empty($this->_params)) {
+            $ret .= '<wp:Param>' . htmlspecialchars($this->_params) . '</wp:Param>';
+        }
+        $ret .= '</wp:Toast>'
+            . '</wp:Notification>';
+        return $ret;
+    }
+
+    /**
+     * Validate proper mpns message
+     *
+     * @return boolean
+     */
+    public function validate()
+    {
+        if (!isset($this->_token) || strlen($this->_token) === 0) {
+            return false;
+        }
+        if (empty($this->_title)) {
+            return false;
+        }
+        if (empty($this->_msg)) {
+            return false;
+        }
+        return parent::validate();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Mobile/Push/Mpns.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,152 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/** Zend_Http_Client **/
+require_once 'Zend/Http/Client.php';
+
+/** Zend_Mobile_Push_Abstract **/
+require_once 'Zend/Mobile/Push/Abstract.php';
+
+/** Zend_Mobile_Push_Message_Mpns **/
+require_once 'Zend/Mobile/Push/Message/Mpns.php';
+
+/**
+ * Mpns Push
+ *
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+class Zend_Mobile_Push_Mpns extends Zend_Mobile_Push_Abstract
+{
+    /**
+     * Http Client
+     *
+     * @var Client
+     */
+    protected $_httpClient;
+
+    /**
+     * Get Http Client
+     *
+     * @return Zend_Http_Client
+     */
+    public function getHttpClient()
+    {
+        if (!$this->_httpClient) {
+            $this->_httpClient = new Zend_Http_Client();
+            $this->_httpClient->setConfig(array(
+                'strictredirects' => true,
+            ));
+        }
+        return $this->_httpClient;
+    }
+
+    /**
+     * Set Http Client
+     *
+     * @return Zend_Mobile_Push_Mpns
+     */
+    public function setHttpClient(Zend_Http_Client $client)
+    {
+        $this->_httpClient = $client;
+        return $this;
+    }
+
+    /**
+     * Send Message
+     *
+     * @param Zend_Mobile_Push_Message_Mpns $message
+     * @return boolean
+     * @throws Zend_Mobile_Push_Exception
+     */
+    public function send(Zend_Mobile_Push_Message_Abstract $message)
+    {
+        if (!$message->validate()) {
+            throw new Zend_Mobile_Push_Exception('The message is not valid.');
+        }
+
+        $this->connect();
+
+        $client = $this->getHttpClient();
+        $client->setUri($message->getToken());
+        $client->setHeaders(array(
+            'Context-Type' => 'text/xml',
+            'Accept' => 'application/*',
+            'X-NotificationClass' => $message->getDelay()
+        ));
+        if ($message->getId()) {
+            $client->setHeaders('X-MessageID', $message->getId());
+        }
+        if ($message->getNotificationType() != Zend_Mobile_Push_Message_Mpns::TYPE_RAW) {
+            $client->setHeaders('X-WindowsPhone-Target', $message->getNotificationType());
+        }
+        $client->setRawData($message->getXmlPayload(), 'text/xml');
+        $response = $client->request('POST');
+        $this->close();
+
+
+        switch ($response->getStatus())
+        {
+            case 200:
+                // check headers for response?  need to test how this actually works to correctly handle different states.
+                if ($response->getHeader('NotificationStatus') == 'QueueFull') {
+                    require_once 'Zend/Mobile/Push/Exception/DeviceQuotaExceeded.php';
+                    throw new Zend_Mobile_Push_Exception_DeviceQuotaExceeded('The devices push notification queue is full, use exponential backoff');
+                }
+                break;
+            case 400:
+                require_once 'Zend/Mobile/Push/Exception/InvalidPayload.php';
+                throw new Zend_Mobile_Push_Exception_InvalidPayload('The message xml was invalid');
+                break;
+            case 401:
+                require_once 'Zend/Mobile/Push/Exception/InvalidToken.php';
+                throw new Zend_Mobile_Push_Exception_InvalidToken('The device token is not valid or there is a mismatch between certificates');
+                break;
+            case 404:
+                require_once 'Zend/Mobile/Push/Exception/InvalidToken.php';
+                throw new Zend_Mobile_Push_Exception_InvalidToken('The device subscription is invalid, stop sending notifications to this device');
+                break;
+            case 405:
+                throw new Zend_Mobile_Push_Exception('Invalid method, only POST is allowed'); // will never be hit unless overwritten
+                break;
+            case 406:
+                require_once 'Zend/Mobile/Push/Exception/QuotaExceeded.php';
+                throw new Zend_Mobile_Push_Exception_QuotaExceeded('The unauthenticated web service has reached the per-day throttling limit');
+                break;
+            case 412:
+                require_once 'Zend/Mobile/Push/Exception/InvalidToken.php';
+                throw new Zend_Mobile_Push_Exception_InvalidToken('The device is in an inactive state.  You may retry once per hour');
+                break;
+            case 503:
+                require_once 'Zend/Mobile/Push/Exception/ServerUnavailable.php';
+                throw new Zend_Mobile_Push_Exception_ServerUnavailable('The server was unavailable.');
+                break;
+            default:
+                break;
+        }
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Mobile/Push/Response/Gcm.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,242 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/**
+ * Gcm Response
+ *
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Zend_Mobile_Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+class Zend_Mobile_Push_Response_Gcm
+{
+
+    const RESULT_MESSAGE_ID = 'message_id';
+    const RESULT_ERROR = 'error';
+    const RESULT_CANONICAL = 'registration_id';
+
+    /**
+     * Multicast ID
+     * @var int
+     */
+    protected $_id;
+
+    /**
+     * Success Count
+     * @var int
+     */
+    protected $_successCnt;
+
+    /**
+     * Failure Count
+     * @var int
+     */
+    protected $_failureCnt;
+
+    /**
+     * Canonical registration id count
+     * @var int
+     */
+    protected $_canonicalCnt;
+
+    /**
+     * Message
+     * @var Zend_Mobile_Push_Message_Gcm
+     */
+    protected $_message;
+
+    /**
+     * Results
+     * @var array
+     */
+    protected $_results;
+
+    /**
+     * Raw Response
+     * @var array
+     */
+    protected $_response;
+
+    /**
+     * Constructor
+     *
+     * @param string $responseString JSON encoded response
+     * @param Zend_Mobile_Push_Message_Gcm $message
+     * @return Zend_Mobile_Push_Response_Gcm
+     * @throws Zend_Mobile_Push_Exception_ServerUnavailable
+     */
+    public function __construct($responseString = null, Zend_Mobile_Push_Message_Gcm $message = null)
+    {
+        if ($responseString) {
+            if (!$response = json_decode($responseString, true)) {
+                require_once 'Zend/Mobile/Push/Exception/ServerUnavailable.php';
+                throw new Zend_Mobile_Push_Exception_ServerUnavailable('The server gave us an invalid response, try again later');
+            }
+            $this->setResponse($response);
+        }
+
+        if ($message) {
+            $this->setMessage($message);
+        }
+
+    }
+
+    /**
+     * Get Message
+     *
+     * @return Zend_Mobile_Push_Message_Gcm
+     */
+    public function getMessage()
+    {
+        return $this->_message;
+    }
+
+    /**
+     * Set Message
+     *
+     * @param Zend_Mobile_Push_Message_Gcm $message
+     * @return Zend_Mobile_Push_Response_Gcm
+     */
+    public function setMessage(Zend_Mobile_Push_Message_Gcm $message)
+    {
+        $this->_message = $message;
+        return $this;
+    }
+
+    /**
+     * Get Response
+     *
+     * @return array
+     */
+    public function getResponse()
+    {
+        return $this->_response;
+    }
+
+    /**
+     * Set Response
+     *
+     * @param array $response
+     * @return Zend_Mobile_Push_Response_Gcm
+     */
+    public function setResponse(array $response)
+    {
+        if (!isset($response['results']) ||
+            !isset($response['success']) ||
+            !isset($response['failure']) ||
+            !isset($response['canonical_ids']) ||
+            !isset($response['multicast_id'])) {
+            throw new Zend_Mobile_Push_Exception('Response did not contain the proper fields');
+        }
+        $this->_response = $response;
+        $this->_results = $response['results'];
+        $this->_successCnt = (int) $response['success'];
+        $this->_failureCnt = (int) $response['failure'];
+        $this->_canonicalCnt = (int) $response['canonical_ids'];
+        $this->_id = (int) $response['multicast_id'];
+        return $this;
+    }
+
+    /**
+     * Get Success Count
+     *
+     * @return int
+     */
+    public function getSuccessCount()
+    {
+        return $this->_successCnt;
+    }
+
+    /**
+     * Get Failure Count
+     *
+     * @return int
+     */
+    public function getFailureCount()
+    {
+        return $this->_failureCnt;
+    }
+
+    /**
+     * Get Canonical Count
+     *
+     * @return int
+     */
+    public function getCanonicalCount()
+    {
+        return $this->_canonicalCnt;
+    }
+
+    /**
+     * Get Results
+     *
+     * @return array multi dimensional array of:
+     *         NOTE: key is registration_id if the message is passed.
+     *         'registration_id' => array( 
+     *             'message_id' => 'id',
+     *             'error' => 'error',
+     *             'registration_id' => 'id'
+     *          )
+     */
+    public function getResults()
+    {
+        return $this->_correlate();
+    }
+
+    /**
+     * Get Singular Result
+     *
+     * @param  int   $flag one of the RESULT_* flags
+     * @return array singular array with keys being registration id
+     *               value is the type of result
+     */
+    public function getResult($flag)
+    {
+        $ret = array();
+        foreach ($this->_correlate() as $k => $v) {
+            if (isset($v[$flag])) {
+                $ret[$k] = $v[$flag];
+            }
+        }
+        return $ret;
+    }
+
+    /**
+     * Correlate Message and Result
+     *
+     * @return array
+     */
+    protected function _correlate()
+    {
+        $results = $this->_results;
+        if ($this->_message && $results) {
+            $tokens = $this->_message->getToken();
+            while($token = array_shift($tokens)) {
+                $results[$token] = array_shift($results);
+            }
+        }
+        return $results;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Mobile/Push/Test/ApnsProxy.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,103 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Push
+ * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id $
+ */
+
+/** Zend_Mobile_Push_Apns **/
+require_once 'Zend/Mobile/Push/Apns.php';
+
+/**
+ * Apns Test Proxy
+ * This class is utilized for unit testing purposes
+ *
+ * @category   Zend
+ * @package    Zend_Mobile
+ * @subpackage Push
+ */
+class Zend_Mobile_Push_Test_ApnsProxy extends Zend_Mobile_Push_Apns 
+{
+    /**
+     * Read Response
+     *
+     * @var string
+     */
+    protected $_readResponse;
+
+    /**
+     * Write Response
+     *
+     * @var mixed
+     */
+    protected $_writeResponse;
+
+    /**
+     * Set the Response
+     *
+     * @param string $str
+     * @return Zend_Mobile_Push_ApnsProxy
+     */
+    public function setReadResponse($str) {
+        $this->_readResponse = $str;
+    }
+
+    /**
+     * Set the write response
+     *
+     * @param mixed $resp
+     * @return void
+     */
+    public function setWriteResponse($resp)
+    {
+        $this->_writeResponse = $resp;
+    }
+
+    /**
+     * Connect
+     *
+     * @return true
+     */
+    protected function _connect($uri) {
+        return true;
+    }
+
+    /**
+     * Return Response
+     *
+     * @param string $length
+     * @return string
+     */
+    protected function _read($length) {
+        $ret = substr($this->_readResponse, 0, $length);
+        $this->_readResponse = null;
+        return $ret;
+    }
+
+    /**
+     * Write and Return Length
+     *
+     * @param string $payload
+     * @return int
+     */
+    protected function _write($payload) {
+        $ret = $this->_writeResponse;
+        $this->_writeResponse = null;
+        return (null === $ret) ? strlen($payload) : $ret;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Search/Lucene/Interface/MultiSearcher.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,25 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Search_Lucene
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: MultiSearcher.php 24593 2012-01-05 20:35:02Z matthew $
+ */
+
+
+/** Zend_Search_Lucene_MultiSearcher */
+require_once 'Zend/Search/Lucene/MultiSearcher.php';
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/Rackspace/Abstract.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,387 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service
+ * @subpackage Rackspace
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+require_once 'Zend/Http/Client.php';
+
+abstract class Zend_Service_Rackspace_Abstract
+{
+    const VERSION                = 'v1.0';
+    const US_AUTH_URL            = 'https://auth.api.rackspacecloud.com';
+    const UK_AUTH_URL            = 'https://lon.auth.api.rackspacecloud.com';
+    const API_FORMAT             = 'json';
+    const USER_AGENT             = 'Zend_Service_Rackspace';
+    const STORAGE_URL            = "X-Storage-Url";
+    const AUTHTOKEN              = "X-Auth-Token";
+    const AUTHUSER_HEADER        = "X-Auth-User";
+    const AUTHKEY_HEADER         = "X-Auth-Key";
+    const AUTHUSER_HEADER_LEGACY = "X-Storage-User";
+    const AUTHKEY_HEADER_LEGACY  = "X-Storage-Pass";
+    const AUTHTOKEN_LEGACY       = "X-Storage-Token";
+    const CDNM_URL               = "X-CDN-Management-Url";
+    const MANAGEMENT_URL         = "X-Server-Management-Url";
+    /**
+     * Rackspace Key
+     *
+     * @var string
+     */
+    protected $key;
+    /**
+     * Rackspace account name
+     *
+     * @var string
+     */
+    protected $user;
+    /**
+     * Token of authentication
+     *
+     * @var string
+     */
+    protected $token;
+    /**
+     * Authentication URL
+     *
+     * @var string
+     */
+    protected $authUrl;
+    /**
+     * @var Zend_Http_Client
+     */
+    protected $httpClient;
+    /**
+     * Error Msg
+     *
+     * @var string
+     */
+    protected $errorMsg;
+    /**
+     * HTTP error code
+     *
+     * @var string
+     */
+    protected $errorCode;
+    /**
+     * Storage URL
+     *
+     * @var string
+     */
+    protected $storageUrl;
+    /**
+     * CDN URL
+     *
+     * @var string
+     */
+    protected $cdnUrl;
+    /**
+     * Server management URL
+     * 
+     * @var string 
+     */
+    protected $managementUrl;
+    /**
+     * Do we use ServiceNet?
+     * 
+     * @var boolean
+     */
+    protected $useServiceNet = false;
+    /**
+     * Constructor
+     *
+     * You must pass the account and the Rackspace authentication key.
+     * Optional: the authentication url (default is US)
+     *
+     * @param string $user
+     * @param string $key
+     * @param string $authUrl
+     */
+    public function __construct($user, $key, $authUrl=self::US_AUTH_URL)
+    {
+        if (!isset($user)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception("The user cannot be empty");
+        }
+        if (!isset($key)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception("The key cannot be empty");
+        }
+        if (!in_array($authUrl, array(self::US_AUTH_URL, self::UK_AUTH_URL))) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception("The authentication URL should be valid");
+        }
+        $this->setUser($user);
+        $this->setKey($key);
+        $this->setAuthUrl($authUrl);
+    }
+    /**
+     * Get User account
+     *
+     * @return string
+     */
+    public function getUser()
+    {
+        return $this->user;
+    }
+    /**
+     * Get user key
+     *
+     * @return string
+     */
+    public function getKey()
+    {
+        return $this->key;
+    }
+    /**
+     * Get authentication URL
+     *
+     * @return string
+     */
+    public function getAuthUrl()
+    {
+        return $this->authUrl;
+    }
+    /**
+     * Get the storage URL
+     *
+     * @return string|boolean
+     */
+    public function getStorageUrl() 
+    {
+        if (empty($this->storageUrl)) {
+            if (!$this->authenticate()) {
+                return false;
+            }
+        }
+        return $this->storageUrl;
+    }
+    /**
+     * Get the CDN URL
+     *
+     * @return string|boolean
+     */
+    public function getCdnUrl() 
+    {
+        if (empty($this->cdnUrl)) {
+            if (!$this->authenticate()) {
+                return false;
+            }
+        }
+        return $this->cdnUrl;
+    }
+    /**
+     * Get the management server URL
+     * 
+     * @return string|boolean
+     */     
+    public function getManagementUrl()
+    {
+        if (empty($this->managementUrl)) {
+            if (!$this->authenticate()) {
+                return false;
+            }
+        }
+        return $this->managementUrl;
+    }
+    /**
+     * Set the user account
+     *
+     * @param string $user
+     * @return void
+     */
+    public function setUser($user)
+    {
+        if (!empty($user)) {
+            $this->user = $user;
+        }
+    }
+    /**
+     * Set the authentication key
+     *
+     * @param string $key
+     * @return void
+     */
+    public function setKey($key)
+    {
+        if (!empty($key)) {
+            $this->key = $key;
+        }
+    }
+    /**
+     * Set the Authentication URL
+     *
+     * @param string $url
+     * @return void
+     */
+    public function setAuthUrl($url)
+    {
+        if (!empty($url) && in_array($url, array(self::US_AUTH_URL, self::UK_AUTH_URL))) {
+            $this->authUrl = $url;
+        } else {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception("The authentication URL is not valid");
+        }
+    }
+    
+    /**
+     * Sets whether to use ServiceNet
+     * 
+     * ServiceNet is Rackspace's internal network. Bandwidth on ServiceNet is
+     * not charged.
+     * 
+     * @param boolean $useServiceNet
+     */
+    public function setServiceNet($useServiceNet = true)
+    {
+        $this->useServiceNet = $useServiceNet;
+        return $this;
+    }
+
+    /**
+     * Get whether we're using ServiceNet
+     * 
+     * @return boolean
+     */
+    public function getServiceNet()
+    {
+        return $this->useServiceNet;
+    }
+
+    /**
+     * Get the authentication token
+     *
+     * @return string
+     */
+    public function getToken()
+    {
+        if (empty($this->token)) {
+            if (!$this->authenticate()) {
+                return false;
+            }
+        }
+        return $this->token;
+    }
+    /**
+     * Get the error msg of the last HTTP call
+     *
+     * @return string
+     */
+    public function getErrorMsg() 
+    {
+        return $this->errorMsg;
+    }
+    /**
+     * Get the error code of the last HTTP call
+     * 
+     * @return strig 
+     */
+    public function getErrorCode() 
+    {
+        return $this->errorCode;
+    }
+    /**
+     * get the HttpClient instance
+     *
+     * @return Zend_Http_Client
+     */
+    public function getHttpClient()
+    {
+        if (empty($this->httpClient)) {
+            $this->httpClient = new Zend_Http_Client();
+        }
+        return $this->httpClient;
+    }
+    /**
+     * Return true is the last call was successful
+     * 
+     * @return boolean 
+     */
+    public function isSuccessful()
+    {
+        return ($this->errorMsg=='');
+    }
+    /**
+     * HTTP call
+     *
+     * @param string $url
+     * @param string $method
+     * @param array $headers
+     * @param array $get
+     * @param string $body
+     * @return Zend_Http_Response
+     */
+    protected function httpCall($url,$method,$headers=array(),$data=array(),$body=null)
+    {
+        $client = $this->getHttpClient();
+        $client->resetParameters(true);
+        if (empty($headers[self::AUTHUSER_HEADER])) {
+            $headers[self::AUTHTOKEN]= $this->getToken();
+        } 
+        $client->setMethod($method);
+        if (empty($data['format'])) {
+            $data['format']= self::API_FORMAT;
+        }
+        $client->setParameterGet($data);    
+        if (!empty($body)) {
+            $client->setRawData($body);
+            if (!isset($headers['Content-Type'])) {
+                $headers['Content-Type']= 'application/json';
+            }
+        }
+        $client->setHeaders($headers);
+        $client->setUri($url);
+        $this->errorMsg='';
+        $this->errorCode='';
+        return $client->request();
+    }
+    /**
+     * Authentication
+     *
+     * @return boolean
+     */
+    public function authenticate()
+    {
+        if (empty($this->user)) {
+            /**
+             * @see Zend_Service_Rackspace_Exception
+             */
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception("User has not been set");
+        }
+
+        $headers = array (
+            self::AUTHUSER_HEADER => $this->user,
+            self::AUTHKEY_HEADER => $this->key
+        );
+        $result = $this->httpCall($this->authUrl.'/'.self::VERSION,'GET', $headers);
+        if ($result->getStatus()==204) {
+            $this->token = $result->getHeader(self::AUTHTOKEN);
+            $this->cdnUrl = $result->getHeader(self::CDNM_URL);
+            $this->managementUrl = $result->getHeader(self::MANAGEMENT_URL);
+            $storageUrl = $result->getHeader(self::STORAGE_URL);
+            if ($this->useServiceNet) {
+                $storageUrl = preg_replace('|(.*)://([^/]*)(.*)|', '$1://snet-$2$3', $storageUrl);
+            }
+            $this->storageUrl = $storageUrl;
+            return true;
+        }
+        $this->errorMsg = $result->getBody();
+        $this->errorCode = $result->getStatus();
+        return false;
+    } 
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/Rackspace/Exception.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,36 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service
+ * @subpackage Rackspace
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: Exception.php 24593 2012-01-05 20:35:02Z matthew $
+ */
+
+/**
+ * @see Zend_Service_Exception
+ */
+require_once 'Zend/Service/Exception.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Service
+ * @subpackage Rackspace
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Service_Rackspace_Exception extends Zend_Service_Exception
+{}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/Rackspace/Files.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,691 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service
+ * @subpackage Rackspace
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+require_once 'Zend/Service/Rackspace/Abstract.php';
+require_once 'Zend/Service/Rackspace/Files/ContainerList.php';
+require_once 'Zend/Service/Rackspace/Files/ObjectList.php';
+require_once 'Zend/Service/Rackspace/Files/Container.php';
+require_once 'Zend/Service/Rackspace/Files/Object.php';
+
+class Zend_Service_Rackspace_Files extends Zend_Service_Rackspace_Abstract
+{
+    const ERROR_CONTAINER_NOT_EMPTY            = 'The container is not empty, I cannot delete it.';
+    const ERROR_CONTAINER_NOT_FOUND            = 'The container was not found.';
+    const ERROR_OBJECT_NOT_FOUND               = 'The object was not found.';
+    const ERROR_OBJECT_MISSING_PARAM           = 'Missing Content-Length or Content-Type header in the request';
+    const ERROR_OBJECT_CHECKSUM                = 'Checksum of the file content failed';
+    const ERROR_CONTAINER_EXIST                = 'The container already exists';
+    const ERROR_PARAM_NO_NAME_CONTAINER        = 'You must specify the container name';
+    const ERROR_PARAM_NO_NAME_OBJECT           = 'You must specify the object name';
+    const ERROR_PARAM_NO_CONTENT               = 'You must specify the content of the object';
+    const ERROR_PARAM_NO_NAME_SOURCE_CONTAINER = 'You must specify the source container name';
+    const ERROR_PARAM_NO_NAME_SOURCE_OBJECT    = 'You must specify the source object name';
+    const ERROR_PARAM_NO_NAME_DEST_CONTAINER   = 'You must specify the destination container name';
+    const ERROR_PARAM_NO_NAME_DEST_OBJECT      = 'You must specify the destination object name';
+    const ERROR_PARAM_NO_METADATA              = 'You must specify the metadata array';
+    const ERROR_CDN_TTL_OUT_OF_RANGE           = 'TTL must be a number in seconds, min is 900 sec and maximum is 1577836800 (50 years)';
+    const ERROR_PARAM_UPDATE_CDN               = 'You must specify at least one the parameters: ttl, cdn_enabled or log_retention';
+    const HEADER_CONTENT_TYPE                  = 'Content-Type';
+    const HEADER_HASH                          = 'Etag';
+    const HEADER_LAST_MODIFIED                 = 'Last-Modified';
+    const HEADER_CONTENT_LENGTH                = 'Content-Length';
+    const HEADER_COPY_FROM                     = 'X-Copy-From';
+    const METADATA_OBJECT_HEADER               = "X-Object-Meta-";
+    const METADATA_CONTAINER_HEADER            = "X-Container-Meta-";
+    const CDN_URI                              = "X-CDN-URI";
+    const CDN_SSL_URI                          = "X-CDN-SSL-URI";
+    const CDN_ENABLED                          = "X-CDN-Enabled";
+    const CDN_LOG_RETENTION                    = "X-Log-Retention";
+    const CDN_ACL_USER_AGENT                   = "X-User-Agent-ACL";
+    const CDN_ACL_REFERRER                     = "X-Referrer-ACL";
+    const CDN_TTL                              = "X-TTL";
+    const CDN_TTL_MIN                          = 900;
+    const CDN_TTL_MAX                          = 1577836800;
+    const CDN_EMAIL                            = "X-Purge-Email";
+    const ACCOUNT_CONTAINER_COUNT              = "X-Account-Container-Count";
+    const ACCOUNT_BYTES_USED                   = "X-Account-Bytes-Used";
+    const ACCOUNT_OBJ_COUNT                    = "X-Account-Object-Count";
+    const CONTAINER_OBJ_COUNT                  = "X-Container-Object-Count";
+    const CONTAINER_BYTES_USE                  = "X-Container-Bytes-Used";
+    const MANIFEST_OBJECT_HEADER               = "X-Object-Manifest";
+
+    /**
+     * Return the total count of containers
+     *
+     * @return integer
+     */
+    public function getCountContainers()
+    {
+        $data= $this->getInfoAccount();
+        return $data['tot_containers'];
+    }
+    /**
+     * Return the size in bytes of all the containers
+     *
+     * @return integer
+     */
+    public function getSizeContainers()
+    {
+        $data= $this->getInfoAccount();
+        return $data['size_containers'];
+    }
+    /**
+     * Return the count of objects contained in all the containers
+     *
+     * @return integer
+     */
+    public function getCountObjects()
+    {
+        $data= $this->getInfoAccount();
+        return $data['tot_objects'];
+    }
+    /**
+     * Get all the containers
+     *
+     * @param array $options
+     * @return Zend_Service_Rackspace_Files_ContainerList|boolean
+     */
+    public function getContainers($options=array())
+    {
+        $result= $this->httpCall($this->getStorageUrl(),'GET',null,$options);
+        if ($result->isSuccessful()) {
+            return new Zend_Service_Rackspace_Files_ContainerList($this,json_decode($result->getBody(),true));
+        }
+        return false;
+    }
+    /**
+     * Get all the CDN containers
+     *
+     * @param array $options
+     * @return array|boolean
+     */
+    public function getCdnContainers($options=array())
+    {
+        $options['enabled_only']= true;
+        $result= $this->httpCall($this->getCdnUrl(),'GET',null,$options);
+        if ($result->isSuccessful()) {
+            return new Zend_Service_Rackspace_Files_ContainerList($this,json_decode($result->getBody(),true));
+        }
+        return false;
+    }
+    /**
+     * Get the metadata information of the accounts:
+     * - total count containers
+     * - size in bytes of all the containers
+     * - total objects in all the containers
+     * 
+     * @return array|boolean
+     */
+    public function getInfoAccount()
+    {
+        $result= $this->httpCall($this->getStorageUrl(),'HEAD');
+        if ($result->isSuccessful()) {
+            $output= array(
+                'tot_containers'  => $result->getHeader(self::ACCOUNT_CONTAINER_COUNT),
+                'size_containers' => $result->getHeader(self::ACCOUNT_BYTES_USED),
+                'tot_objects'     => $result->getHeader(self::ACCOUNT_OBJ_COUNT)
+            );
+            return $output;
+        }
+        return false;
+    }
+    /**
+     * Get all the objects of a container
+     *
+     * @param string $container
+     * @param array $options
+     * @return  Zend_Service_Rackspace_Files_ObjectList|boolean
+     */
+    public function getObjects($container,$options=array())
+    {
+        if (empty($container)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME_CONTAINER);
+        }
+        $result= $this->httpCall($this->getStorageUrl().'/'.rawurlencode($container),'GET',null,$options);
+        if ($result->isSuccessful()) {
+            return new Zend_Service_Rackspace_Files_ObjectList($this,json_decode($result->getBody(),true),$container);
+        }
+        return false;
+    }
+    /**
+     * Create a container
+     *
+     * @param string $container
+     * @param array $metadata
+     * @return Zend_Service_Rackspace_Files_Container|boolean
+     */
+    public function createContainer($container,$metadata=array())
+    {
+        if (empty($container)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME_CONTAINER);
+        }
+        $headers=array();
+        if (!empty($metadata)) {
+            foreach ($metadata as $key => $value) {
+                $headers[self::METADATA_CONTAINER_HEADER.rawurlencode(strtolower($key))]= rawurlencode($value);
+            }
+        }
+        $result= $this->httpCall($this->getStorageUrl().'/'.rawurlencode($container),'PUT',$headers);
+        $status= $result->getStatus();
+        switch ($status) {
+            case '201': // break intentionally omitted
+                $data= array(
+                    'name' => $container
+                );
+                return new Zend_Service_Rackspace_Files_Container($this,$data);
+            case '202':
+                $this->errorMsg= self::ERROR_CONTAINER_EXIST;
+                break;
+            default:
+                $this->errorMsg= $result->getBody();
+                break;
+        }
+        $this->errorCode= $status;
+        return false;
+    }
+    /**
+     * Delete a container (only if it's empty)
+     *
+     * @param sting $container
+     * @return boolean
+     */
+    public function deleteContainer($container)
+    {
+        if (empty($container)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME_CONTAINER);
+        }
+        $result= $this->httpCall($this->getStorageUrl().'/'.rawurlencode($container),'DELETE');
+        $status= $result->getStatus();
+        switch ($status) {
+            case '204': // break intentionally omitted
+                return true;
+            case '409':
+                $this->errorMsg= self::ERROR_CONTAINER_NOT_EMPTY;
+                break;
+            case '404':
+                $this->errorMsg= self::ERROR_CONTAINER_NOT_FOUND;
+                break;
+            default:
+                $this->errorMsg= $result->getBody();
+                break;
+        }
+        $this->errorCode= $status;
+        return false;
+    }
+    /**
+     * Get the metadata of a container
+     *
+     * @param string $container
+     * @return array|boolean
+     */
+    public function getMetadataContainer($container)
+    {
+        if (empty($container)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME_CONTAINER);
+        }
+        $result= $this->httpCall($this->getStorageUrl().'/'.rawurlencode($container),'HEAD');
+        $status= $result->getStatus();
+        switch ($status) {
+            case '204': // break intentionally omitted
+                $headers= $result->getHeaders();
+                $count= strlen(self::METADATA_CONTAINER_HEADER);
+                // Zend_Http_Response alters header name in array key, so match our header to what will be in the headers array
+                $headerName = ucwords(strtolower(self::METADATA_CONTAINER_HEADER)); 
+                $metadata= array();
+                foreach ($headers as $type => $value) {
+                    if (strpos($type,$headerName)!==false) {
+                        $metadata[strtolower(substr($type, $count))]= $value;
+                    }
+                }
+                $data= array (
+                    'name'     => $container,
+                    'count'    => $result->getHeader(self::CONTAINER_OBJ_COUNT),
+                    'bytes'    => $result->getHeader(self::CONTAINER_BYTES_USE),
+                    'metadata' => $metadata
+                );
+                return $data;
+            case '404':
+                $this->errorMsg= self::ERROR_CONTAINER_NOT_FOUND;
+                break;
+            default:
+                $this->errorMsg= $result->getBody();
+                break;
+        }
+        $this->errorCode= $status;
+        return false;
+    }
+    /**
+     * Get a container
+     * 
+     * @param string $container
+     * @return Container|boolean
+     */
+    public function getContainer($container) {
+        $result= $this->getMetadataContainer($container);
+        if (!empty($result)) {
+            return new Zend_Service_Rackspace_Files_Container($this,$result);
+        }
+        return false;
+    }
+    /**
+     * Get an object in a container
+     *
+     * @param string $container
+     * @param string $object
+     * @param array $headers
+     * @return Zend_Service_Rackspace_Files_Object|boolean
+     */
+    public function getObject($container,$object,$headers=array())
+    {
+        if (empty($container)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME_CONTAINER);
+        }
+        if (empty($object)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME_OBJECT);
+        }
+        $result= $this->httpCall($this->getStorageUrl().'/'.rawurlencode($container).'/'.rawurlencode($object),'GET',$headers);
+        $status= $result->getStatus();
+        switch ($status) {
+            case '200': // break intentionally omitted
+                $data= array(
+                    'name'          => $object,
+                    'container'     => $container,
+                    'hash'          => $result->getHeader(self::HEADER_HASH),
+                    'bytes'         => $result->getHeader(self::HEADER_CONTENT_LENGTH),
+                    'last_modified' => $result->getHeader(self::HEADER_LAST_MODIFIED),
+                    'content_type'  => $result->getHeader(self::HEADER_CONTENT_TYPE),
+                    'content'       => $result->getBody()
+                );
+                return new Zend_Service_Rackspace_Files_Object($this,$data);
+            case '404':
+                $this->errorMsg= self::ERROR_OBJECT_NOT_FOUND;
+                break;
+            default:
+                $this->errorMsg= $result->getBody();
+                break;
+        }
+        $this->errorCode= $status;
+        return false;
+    }
+    /**
+     * Store a file in a container
+     *
+     * @param string $container
+     * @param string $object
+     * @param string $content
+     * @param array $metadata
+     * @param string $content_type
+     *
+     * @return boolean
+     */
+    public function storeObject($container,$object,$content,$metadata=array(),$content_type=null) {
+        if (empty($container)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME_CONTAINER);
+        }
+        if (empty($object)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME_OBJECT);
+        }
+        if (empty($content)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_CONTENT);
+        }
+        if (!empty($content_type)) {
+           $headers[self::HEADER_CONTENT_TYPE]= $content_type;
+        }
+        if (!empty($metadata) && is_array($metadata)) {
+            foreach ($metadata as $key => $value) {
+                $headers[self::METADATA_OBJECT_HEADER.$key]= $value;
+            }
+        }
+        $headers[self::HEADER_HASH]= md5($content);
+        $headers[self::HEADER_CONTENT_LENGTH]= strlen($content);
+        $result= $this->httpCall($this->getStorageUrl().'/'.rawurlencode($container).'/'.rawurlencode($object),'PUT',$headers,null,$content);
+        $status= $result->getStatus();
+        switch ($status) {
+            case '201': // break intentionally omitted
+                return true;
+            case '412':
+                $this->errorMsg= self::ERROR_OBJECT_MISSING_PARAM;
+                break;
+            case '422':
+                $this->errorMsg= self::ERROR_OBJECT_CHECKSUM;
+                break;
+            default:
+                $this->errorMsg= $result->getBody();
+                break;
+        }
+        $this->errorCode= $status;
+        return false;
+    }
+    /**
+     * Delete an object in a container
+     *
+     * @param string $container
+     * @param string $object
+     * @return boolean
+     */
+    public function deleteObject($container,$object) {
+        if (empty($container)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME_CONTAINER);
+        }
+        if (empty($object)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME_OBJECT);
+        }
+        $result= $this->httpCall($this->getStorageUrl().'/'.rawurlencode($container).'/'.rawurlencode($object),'DELETE');
+        $status= $result->getStatus();
+        switch ($status) {
+            case '204': // break intentionally omitted
+                return true;
+            case '404':
+                $this->errorMsg= self::ERROR_OBJECT_NOT_FOUND;
+                break;
+            default:
+                $this->errorMsg= $result->getBody();
+                break;
+        }
+        $this->errorCode= $status;
+        return false;
+    }
+    /**
+     * Copy an object from a container to another
+     *
+     * @param string $container_source
+     * @param string $obj_source
+     * @param string $container_dest
+     * @param string $obj_dest
+     * @param array $metadata
+     * @param string $content_type
+     * @return boolean
+     */
+    public function copyObject($container_source,$obj_source,$container_dest,$obj_dest,$metadata=array(),$content_type=null) {
+        if (empty($container_source)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME_SOURCE_CONTAINER);
+        }
+        if (empty($obj_source)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME_SOURCE_OBJECT);
+        }
+        if (empty($container_dest)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME_DEST_CONTAINER);
+        }
+        if (empty($obj_dest)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME_DEST_OBJECT);
+        }
+        $headers= array(
+            self::HEADER_COPY_FROM => '/'.rawurlencode($container_source).'/'.rawurlencode($obj_source),
+            self::HEADER_CONTENT_LENGTH => 0
+        );
+        if (!empty($content_type)) {
+            $headers[self::HEADER_CONTENT_TYPE]= $content_type;
+        }
+        if (!empty($metadata) && is_array($metadata)) {
+            foreach ($metadata as $key => $value) {
+                $headers[self::METADATA_OBJECT_HEADER.$key]= $value;
+            }
+        }
+        $result= $this->httpCall($this->getStorageUrl().'/'.rawurlencode($container_dest).'/'.rawurlencode($obj_dest),'PUT',$headers);
+        $status= $result->getStatus();
+        switch ($status) {
+            case '201': // break intentionally omitted
+                return true;
+            default:
+                $this->errorMsg= $result->getBody();
+                break;
+        }
+        $this->errorCode= $status;
+        return false;
+    }
+    /**
+     * Get the metadata of an object
+     *
+     * @param string $container
+     * @param string $object
+     * @return array|boolean
+     */
+    public function getMetadataObject($container,$object) {
+        if (empty($container)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME_CONTAINER);
+        }
+        if (empty($object)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME_OBJECT);
+        }
+        $result= $this->httpCall($this->getStorageUrl().'/'.rawurlencode($container).'/'.rawurlencode($object),'HEAD');
+        $status= $result->getStatus();
+        switch ($status) {
+            case '200': // break intentionally omitted
+                $headers= $result->getHeaders();
+                $count= strlen(self::METADATA_OBJECT_HEADER);
+                // Zend_Http_Response alters header name in array key, so match our header to what will be in the headers array
+                $headerName = ucwords(strtolower(self::METADATA_OBJECT_HEADER)); 
+                $metadata= array();
+                foreach ($headers as $type => $value) {
+                    if (strpos($type,$headerName)!==false) {
+                        $metadata[strtolower(substr($type, $count))]= $value;
+                    }
+                }
+                $data= array (
+                    'name'          => $object,
+                    'container'     => $container,
+                    'hash'          => $result->getHeader(self::HEADER_HASH),
+                    'bytes'         => $result->getHeader(self::HEADER_CONTENT_LENGTH),
+                    'content_type'  => $result->getHeader(self::HEADER_CONTENT_TYPE),
+                    'last_modified' => $result->getHeader(self::HEADER_LAST_MODIFIED),
+                    'metadata'      => $metadata
+                );
+                return $data;
+            case '404':
+                $this->errorMsg= self::ERROR_OBJECT_NOT_FOUND;
+                break;
+            default:
+                $this->errorMsg= $result->getBody();
+                break;
+        }
+        $this->errorCode= $status;
+        return false;
+    }
+    /**
+     * Set the metadata of a object in a container
+     * The old metadata values are replaced with the new one
+     * 
+     * @param string $container
+     * @param string $object
+     * @param array $metadata
+     * @return boolean
+     */
+    public function setMetadataObject($container,$object,$metadata)
+    {
+        if (empty($container)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME_CONTAINER);
+        }
+        if (empty($object)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME_OBJECT);
+        }
+        if (empty($metadata) || !is_array($metadata)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME_OBJECT);
+        }
+        $headers=array();
+        foreach ($metadata as $key => $value) {
+            $headers[self::METADATA_OBJECT_HEADER.$key]= $value;
+        }
+        $result= $this->httpCall($this->getStorageUrl().'/'.rawurlencode($container).'/'.rawurlencode($object),'POST',$headers);
+        $status= $result->getStatus();
+        switch ($status) {
+            case '202': // break intentionally omitted
+                return true;
+            case '404':
+                $this->errorMsg= self::ERROR_OBJECT_NOT_FOUND;
+                break;
+            default:
+                $this->errorMsg= $result->getBody();
+                break;
+        }
+        $this->errorCode= $status;
+        return false;
+    }
+    /**
+     * Enable the CDN for a container
+     *
+     * @param  string $container
+     * @param  integer $ttl
+     * @return array|boolean
+     */
+    public function enableCdnContainer ($container,$ttl=self::CDN_TTL_MIN) {
+        if (empty($container)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME_CONTAINER);
+        }
+        $headers=array();
+        if (is_numeric($ttl) && ($ttl>=self::CDN_TTL_MIN) && ($ttl<=self::CDN_TTL_MAX)) {
+            $headers[self::CDN_TTL]= $ttl;
+        } else {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception(self::ERROR_CDN_TTL_OUT_OF_RANGE);
+        }
+        $result= $this->httpCall($this->getCdnUrl().'/'.rawurlencode($container),'PUT',$headers);
+        $status= $result->getStatus();
+        switch ($status) {
+            case '201':
+            case '202': // break intentionally omitted
+                $data= array (
+                    'cdn_uri'     => $result->getHeader(self::CDN_URI),
+                    'cdn_uri_ssl' => $result->getHeader(self::CDN_SSL_URI)
+                );
+                return $data;
+            case '404':
+                $this->errorMsg= self::ERROR_CONTAINER_NOT_FOUND;
+                break;
+            default:
+                $this->errorMsg= $result->getBody();
+                break;
+        }
+        $this->errorCode= $status;
+        return false;
+    }
+    /**
+     * Update the attribute of a CDN container
+     *
+     * @param  string $container
+     * @param  integer $ttl
+     * @param  boolean $cdn_enabled
+     * @param  boolean $log
+     * @return boolean
+     */
+    public function updateCdnContainer($container,$ttl=null,$cdn_enabled=null,$log=null)
+    {
+        if (empty($container)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME_CONTAINER);
+        }
+        if (empty($ttl) && (!isset($cdn_enabled)) && (!isset($log))) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_UPDATE_CDN);
+        }
+        $headers=array();
+        if (isset($ttl)) {
+            if (is_numeric($ttl) && ($ttl>=self::CDN_TTL_MIN) && ($ttl<=self::CDN_TTL_MAX)) {
+                $headers[self::CDN_TTL]= $ttl;
+            } else {
+                require_once 'Zend/Service/Rackspace/Exception.php';
+                throw new Zend_Service_Rackspace_Exception(self::ERROR_CDN_TTL_OUT_OF_RANGE);
+            }
+        }
+        if (isset($cdn_enabled)) {
+            if ($cdn_enabled===true) {
+                $headers[self::CDN_ENABLED]= 'true';
+            } else {
+                $headers[self::CDN_ENABLED]= 'false';
+            }
+        }
+        if (isset($log)) {
+            if ($log===true) {
+                $headers[self::CDN_LOG_RETENTION]= 'true';
+            } else  {
+                $headers[self::CDN_LOG_RETENTION]= 'false';
+            }
+        }
+        $result= $this->httpCall($this->getCdnUrl().'/'.rawurlencode($container),'POST',$headers);
+        $status= $result->getStatus();
+        switch ($status) {
+            case '200':
+            case '202': // break intentionally omitted
+                return true;
+            case '404':
+                $this->errorMsg= self::ERROR_CONTAINER_NOT_FOUND;
+                break;
+            default:
+                $this->errorMsg= $result->getBody();
+                break;
+        }
+        $this->errorCode= $status;
+        return false;
+    }
+    /**
+     * Get the information of a Cdn container
+     *
+     * @param string $container
+     * @return array|boolean
+     */
+    public function getInfoCdnContainer($container) {
+        if (empty($container)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME_CONTAINER);
+        }
+        $result= $this->httpCall($this->getCdnUrl().'/'.rawurlencode($container),'HEAD');
+        $status= $result->getStatus();
+        switch ($status) {
+            case '204': // break intentionally omitted
+                $data= array (
+                    'ttl'         => $result->getHeader(self::CDN_TTL),
+                    'cdn_uri'     => $result->getHeader(self::CDN_URI),
+                    'cdn_uri_ssl' => $result->getHeader(self::CDN_SSL_URI)
+                );
+                $data['cdn_enabled']= (strtolower($result->getHeader(self::CDN_ENABLED))!=='false');
+                $data['log_retention']= (strtolower($result->getHeader(self::CDN_LOG_RETENTION))!=='false');
+                return $data;
+            case '404':
+                $this->errorMsg= self::ERROR_CONTAINER_NOT_FOUND;
+                break;
+            default:
+                $this->errorMsg= $result->getBody();
+                break;
+        }
+        $this->errorCode= $status;
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/Rackspace/Files/Container.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,329 @@
+<?php
+
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service_Rackspace
+ * @subpackage Files
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+require_once 'Zend/Service/Rackspace/Files.php';
+
+class Zend_Service_Rackspace_Files_Container
+{
+    const ERROR_PARAM_FILE_CONSTRUCT  = 'The Zend_Service_Rackspace_Files passed in construction is not valid';
+    const ERROR_PARAM_ARRAY_CONSTRUCT = 'The array passed in construction is not valid';
+    const ERROR_PARAM_NO_NAME         = 'The container name is empty';
+    /**
+     * @var string
+     */
+    protected $name;
+    /**
+     * Construct
+     *
+     * @param Zend_Service_Rackspace_Files $service
+     * @param string $name
+     */
+    public function __construct($service, $data)
+    {
+        if (!($service instanceof Zend_Service_Rackspace_Files)) {
+            require_once 'Zend/Service/Rackspace/Files/Exception.php';
+            throw new Zend_Service_Rackspace_Files_Exception(self::ERROR_PARAM_FILE_CONSTRUCT);
+        }
+        if (!is_array($data)) {
+            require_once 'Zend/Service/Rackspace/Files/Exception.php';
+            throw new Zend_Service_Rackspace_Files_Exception(self::ERROR_PARAM_ARRAY_CONSTRUCT);
+        }
+        if (!array_key_exists('name', $data)) {
+            require_once 'Zend/Service/Rackspace/Files/Exception.php';
+            throw new Zend_Service_Rackspace_Files_Exception(self::ERROR_PARAM_NO_NAME);
+        }    
+        $this->service = $service;
+        $this->name = $data['name'];
+    }
+    /**
+     * Get the name of the container
+     *
+     * @return string
+     */
+    public function getName()
+    {
+        return $this->name;
+    }
+    /**
+     * Get the size in bytes of the container
+     *
+     * @return integer|boolean
+     */
+    public function getSize()
+    {
+        $data = $this->getInfo();
+        if (isset($data['bytes'])) {
+            return $data['bytes'];
+        }
+        return false;
+    }
+    /**
+     * Get the total count of objects in the container
+     *
+     * @return integer|boolean
+     */
+    public function getObjectCount()
+    {
+        $data = $this->getInfo();
+        if (isset($data['count'])) {
+            return $data['count'];
+        }
+        return false;
+    }
+    /**
+     * Return true if the container is CDN enabled
+     * 
+     * @return boolean
+     */
+    public function isCdnEnabled()
+    {
+        $data = $this->getCdnInfo();
+        if (isset($data['cdn_enabled'])) {
+            return $data['cdn_enabled'];
+        }
+        return false;
+    }
+    /**
+     * Get the TTL of the CDN
+     * 
+     * @return integer|boolean 
+     */
+    public function getCdnTtl() 
+    {
+        $data = $this->getCdnInfo();
+        if (!isset($data['ttl'])) {
+            return $data['ttl'];
+        }
+        return false;
+    }
+    /**
+     * Return true if the log retention is enabled for the CDN
+     *
+     * @return boolean
+     */
+    public function isCdnLogEnabled()
+    {
+        $data = $this->getCdnInfo();
+        if (!isset($data['log_retention'])) {
+            return $data['log_retention'];
+        }
+        return false;
+    }
+    /**
+     * Get the CDN URI
+     * 
+     * @return string|boolean
+     */
+    public function getCdnUri()
+    {
+        $data = $this->getCdnInfo();
+        if (!isset($data['cdn_uri'])) {
+            return $data['cdn_uri'];
+        }
+        return false;
+    }
+    /**
+     * Get the CDN URI SSL
+     *
+     * @return string|boolean
+     */
+    public function getCdnUriSsl()
+    {
+        $data = $this->getCdnInfo();
+        if (!isset($data['cdn_uri_ssl'])) {
+            return $data['cdn_uri_ssl'];
+        }
+        return false;
+    }
+    /**
+     * Get the metadata of the container
+     *
+     * If $key is empty return the array of metadata
+     *
+     * @param string $key
+     * @return array|string|boolean
+     */
+    public function getMetadata($key=null)
+    {
+        $result = $this->service->getMetadataContainer($this->getName());
+        if (!empty($result) && is_array($result)) {
+            if (empty($key)) {
+                return $result['metadata'];
+            } else {
+                if (isset ($result['metadata'][$key])) {
+                    return $result['metadata'][$key];
+                }
+            }    
+        }    
+        return false;
+    }
+    /**
+     * Get the information of the container (total of objects, total size)
+     * 
+     * @return array|boolean 
+     */
+    public function getInfo()
+    {
+        $result = $this->service->getMetadataContainer($this->getName());
+        if (!empty($result) && is_array($result)) {
+           return $result;
+        }
+        return false;
+    }
+    /**
+     * Get all the object of the container
+     *
+     * @return Zend_Service_Rackspace_Files_ObjectList
+     */
+    public function getObjects()
+    {
+        return $this->service->getObjects($this->getName());
+    }
+    /**
+     * Get an object of the container
+     * 
+     * @param string $name
+     * @param array $headers
+     * @return Zend_Service_Rackspace_Files_Object|boolean
+     */
+    public function getObject($name, $headers=array())
+    {
+        return $this->service->getObject($this->getName(), $name, $headers);
+    }
+    /**
+     * Add an object in the container
+     *
+     * @param string $name
+     * @param string $file the content of the object
+     * @param array $metadata
+     * @return boolen
+     */
+    public function addObject($name, $file, $metadata=array())
+    {
+        return $this->service->storeObject($this->getName(), $name, $file, $metadata);
+    }
+    /**
+     * Delete an object in the container
+     *
+     * @param string $obj
+     * @return boolean
+     */
+    public function deleteObject($obj)
+    {
+        return $this->service->deleteObject($this->getName(), $obj);
+    }
+    /**
+     * Copy an object to another container
+     *
+     * @param string $obj_source
+     * @param string $container_dest
+     * @param string $obj_dest
+     * @param array $metadata
+     * @param string $content_type
+     * @return boolean
+     */
+    public function copyObject($obj_source, $container_dest, $obj_dest, $metadata=array(), $content_type=null)
+    {
+        return $this->service->copyObject($this->getName(), $obj_source, $container_dest, $obj_dest, $metadata, $content_type);
+    }
+    /**
+     * Get the metadata of an object in the container
+     *
+     * @param string $object
+     * @return array
+     */
+    public function getMetadataObject($object)
+    {
+        return $this->service->getMetadataObject($this->getName(),$object);
+    }
+    /**
+     * Set the metadata of an object in the container
+     *
+     * @param string $object
+     * @param array $metadata
+     * @return boolean
+     */
+    public function setMetadataObject($object,$metadata=array()) 
+    {
+        return $this->service->setMetadataObject($this->getName(),$object,$metadata);
+    }
+    /**
+     * Enable the CDN for the container
+     *
+     * @param integer $ttl
+     * @return array|boolean
+     */
+    public function enableCdn($ttl=Zend_Service_Rackspace_Files::CDN_TTL_MIN) 
+    {
+        return $this->service->enableCdnContainer($this->getName(),$ttl);
+    }
+    /**
+     * Disable the CDN for the container
+     * 
+     * @return boolean
+     */
+    public function disableCdn() 
+    {
+        $result = $this->service->updateCdnContainer($this->getName(),null,false);
+        return ($result!==false);
+    }
+    /**
+     * Change the TTL for the CDN container
+     *
+     * @param integer $ttl
+     * @return boolean
+     */
+    public function changeTtlCdn($ttl) 
+    {
+        $result =  $this->service->updateCdnContainer($this->getName(),$ttl);
+        return ($result!==false);
+    }
+    /**
+     * Enable the log retention for the CDN
+     *
+     * @return boolean
+     */
+    public function enableLogCdn() 
+    {
+        $result =  $this->service->updateCdnContainer($this->getName(),null,null,true);
+        return ($result!==false);
+    }
+    /**
+     * Disable the log retention for the CDN
+     *
+     * @return boolean
+     */
+    public function disableLogCdn() 
+    {
+        $result =  $this->service->updateCdnContainer($this->getName(),null,null,false);
+        return ($result!==false);
+    }
+    /**
+     * Get the CDN information
+     *
+     * @return array|boolean
+     */
+    public function getCdnInfo() 
+    {
+        return $this->service->getInfoCdnContainer($this->getName());
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/Rackspace/Files/ContainerList.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,221 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service_Rackspace
+ * @subpackage Files
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+require_once 'Zend/Service/Rackspace/Files/Container.php';
+require_once 'Zend/Service/Rackspace/Files.php';
+
+/**
+ * List of servers retrived from the Rackspace web service
+ *
+ * @uses       ArrayAccess
+ * @uses       Countable
+ * @uses       Iterator
+ * @uses       OutOfBoundsException
+ * @uses       Zend_Service_Rackspace_Files_Container
+ * @category   Zend
+ * @package    Zend_Service_Rackspace
+ * @subpackage Files
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Service_Rackspace_Files_ContainerList implements Countable, Iterator, ArrayAccess
+{
+    /**
+     * @var array Array of Zend_Service_Rackspace_Files_Container
+     */
+    protected $objects = array();
+    /**
+     * @var int Iterator key
+     */
+    protected $iteratorKey = 0;
+    /**
+     * @var RackspaceFiles
+     */
+    protected $service;
+    /**
+     * Constructor
+     *
+     * @param  array $list
+     * @return boolean
+     */
+    public function __construct($service,$list = array())
+    {
+        if (!($service instanceof Zend_Service_Rackspace_Files ) || !is_array($list)) {
+            require_once 'Zend/Service/Rackspace/Files/Exception.php';
+            throw new Zend_Service_Rackspace_Files_Exception("You must pass a Zend_Service_Rackspace_Files_Exception object and an array");
+        }
+        $this->service= $service;
+        $this->_constructFromArray($list);
+    }
+    /**
+     * Transforms the Array to array of container
+     *
+     * @param  array $list
+     * @return void
+     */
+    private function _constructFromArray(array $list)
+    {
+        foreach ($list as $container) {
+            $this->_addObject(new Zend_Service_Rackspace_Files_Container($this->service,$container));
+        }
+    }
+    /**
+     * Add an object
+     *
+     * @param  Zend_Service_Rackspace_Files_Container $obj
+     * @return Zend_Service_Rackspace_Files_ContainerList
+     */
+    protected function _addObject (Zend_Service_Rackspace_Files_Container $obj)
+    {
+        $this->objects[] = $obj;
+        return $this;
+    }
+    /**
+     * Return number of servers
+     *
+     * Implement Countable::count()
+     *
+     * @return int
+     */
+    public function count()
+    {
+        return count($this->objects);
+    }
+    /**
+     * Return the current element
+     *
+     * Implement Iterator::current()
+     *
+     * @return Zend_Service_Rackspace_Files_Container
+     */
+    public function current()
+    {
+        return $this->objects[$this->iteratorKey];
+    }
+    /**
+     * Return the key of the current element
+     *
+     * Implement Iterator::key()
+     *
+     * @return int
+     */
+    public function key()
+    {
+        return $this->iteratorKey;
+    }
+    /**
+     * Move forward to next element
+     *
+     * Implement Iterator::next()
+     *
+     * @return void
+     */
+    public function next()
+    {
+        $this->iteratorKey += 1;
+    }
+    /**
+     * Rewind the Iterator to the first element
+     *
+     * Implement Iterator::rewind()
+     *
+     * @return void
+     */
+    public function rewind()
+    {
+        $this->iteratorKey = 0;
+    }
+    /**
+     * Check if there is a current element after calls to rewind() or next()
+     *
+     * Implement Iterator::valid()
+     *
+     * @return bool
+     */
+    public function valid()
+    {
+        $numItems = $this->count();
+        if ($numItems > 0 && $this->iteratorKey < $numItems) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+    /**
+     * Whether the offset exists
+     *
+     * Implement ArrayAccess::offsetExists()
+     *
+     * @param   int     $offset
+     * @return  bool
+     */
+    public function offsetExists($offset)
+    {
+        return ($offset < $this->count());
+    }
+    /**
+     * Return value at given offset
+     *
+     * Implement ArrayAccess::offsetGet()
+     *
+     * @param   int     $offset
+     * @throws  Zend_Service_Rackspace_Files_Exception
+     * @return  Zend_Service_Rackspace_Files_Container
+     */
+    public function offsetGet($offset)
+    {
+        if ($this->offsetExists($offset)) {
+            return $this->objects[$offset];
+        } else {
+            require_once 'Zend/Service/Rackspace/Files/Exception.php';
+            throw new Zend_Service_Rackspace_Files_Exception('Illegal index');
+        }
+    }
+
+    /**
+     * Throws exception because all values are read-only
+     *
+     * Implement ArrayAccess::offsetSet()
+     *
+     * @param   int     $offset
+     * @param   string  $value
+     * @throws  Zend_Service_Rackspace_Files_Exception
+     */
+    public function offsetSet($offset, $value)
+    {
+        require_once 'Zend/Service/Rackspace/Files/Exception.php';
+        throw new Zend_Service_Rackspace_Files_Exception('You are trying to set read-only property');
+    }
+
+    /**
+     * Throws exception because all values are read-only
+     *
+     * Implement ArrayAccess::offsetUnset()
+     *
+     * @param   int     $offset
+     * @throws  Zend_Service_Rackspace_Files_Exception
+     */
+    public function offsetUnset($offset)
+    {
+        require_once 'Zend/Service/Rackspace/Files/Exception.php';
+        throw new Zend_Service_Rackspace_Files_Exception('You are trying to unset read-only property');
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/Rackspace/Files/Exception.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,36 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service_Rackspace
+ * @subpackage Files
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: Exception.php 24593 2012-01-05 20:35:02Z matthew $
+ */
+
+/**
+ * @see Zend_Service_Rackspace_Exception
+ */
+require_once 'Zend/Service/Rackspace/Exception.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Service_Rackspace
+ * @subpackage Files
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Service_Rackspace_Files_Exception extends Zend_Service_Rackspace_Exception
+{}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/Rackspace/Files/Object.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,271 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service_Rackspace
+ * @subpackage Files
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+require_once 'Zend/Service/Rackspace/Files.php';
+
+class Zend_Service_Rackspace_Files_Object
+{
+    /**
+     * The service that has created the object
+     *
+     * @var Zend_Service_Rackspace_Files
+     */
+    protected $service;
+    /**
+     * Name of the object
+     *
+     * @var string
+     */
+    protected $name;
+    /**
+     * MD5 value of the object's content
+     *
+     * @var string
+     */
+    protected $hash;
+    /**
+     * Size in bytes of the object's content
+     *
+     * @var integer
+     */
+    protected $size;
+    /**
+     * Content type of the object's content
+     *
+     * @var string
+     */
+    protected $contentType;
+    /**
+     * Date of the last modified of the object
+     *
+     * @var string
+     */
+    protected $lastModified;
+    /**
+     * Object content
+     *
+     * @var string
+     */
+    protected $content;
+    /**
+     * Name of the container where the object is stored
+     *
+     * @var string
+     */
+    protected $container;
+    /**
+     * Constructor
+     * 
+     * You must pass the Zend_Service_Rackspace_Files object of the caller and an associative
+     * array with the keys "name", "container", "hash", "bytes", "content_type",
+     * "last_modified", "file" where:
+     * name= name of the object
+     * container= name of the container where the object is stored
+     * hash= the MD5 of the object's content
+     * bytes= size in bytes of the object's content
+     * content_type= content type of the object's content
+     * last_modified= date of the last modified of the object
+     * content= content of the object
+     * 
+     * @param Zend_Service_Rackspace_Files $service
+     * @param array $data 
+     */
+    public function __construct($service,$data)
+    {
+        if (!($service instanceof Zend_Service_Rackspace_Files) || !is_array($data)) {
+            require_once 'Zend/Service/Rackspace/Files/Exception.php';
+            throw new Zend_Service_Rackspace_Files_Exception("You must pass a RackspaceFiles and an array");
+        }
+        if (!array_key_exists('name', $data)) {
+            require_once 'Zend/Service/Rackspace/Files/Exception.php';
+            throw new Zend_Service_Rackspace_Files_Exception("You must pass the name of the object in the array (name)");
+        }
+        if (!array_key_exists('container', $data)) {
+            require_once 'Zend/Service/Rackspace/Files/Exception.php';
+            throw new Zend_Service_Rackspace_Files_Exception("You must pass the container of the object in the array (container)");
+        }
+        if (!array_key_exists('hash', $data)) {
+            require_once 'Zend/Service/Rackspace/Files/Exception.php';
+            throw new Zend_Service_Rackspace_Files_Exception("You must pass the hash of the object in the array (hash)");
+        }
+        if (!array_key_exists('bytes', $data)) {
+            require_once 'Zend/Service/Rackspace/Files/Exception.php';
+            throw new Zend_Service_Rackspace_Files_Exception("You must pass the byte size of the object in the array (bytes)");
+        }
+        if (!array_key_exists('content_type', $data)) {
+            require_once 'Zend/Service/Rackspace/Files/Exception.php';
+            throw new Zend_Service_Rackspace_Files_Exception("You must pass the content type of the object in the array (content_type)");
+        }
+        if (!array_key_exists('last_modified', $data)) {
+            require_once 'Zend/Service/Rackspace/Files/Exception.php';
+            throw new Zend_Service_Rackspace_Files_Exception("You must pass the last modified data of the object in the array (last_modified)");
+        }
+        $this->name= $data['name'];
+        $this->container= $data['container'];
+        $this->hash= $data['hash'];
+        $this->size= $data['bytes'];
+        $this->contentType= $data['content_type'];
+        $this->lastModified= $data['last_modified'];
+        if (!empty($data['content'])) {
+            $this->content= $data['content'];
+        }
+        $this->service= $service;
+    }
+    /**
+     * Get name
+     *
+     * @return string
+     */
+    public function getName() 
+    {
+        return $this->name;
+    }
+    /**
+     * Get the name of the container
+     *
+     * @return string
+     */
+    public function getContainer() 
+    {
+        return $this->container;
+    }
+    /**
+     * Get the MD5 of the object's content
+     *
+     * @return string|boolean
+     */
+    public function getHash() 
+    {
+        return $this->hash;
+    }
+    /**
+     * Get the size (in bytes) of the object's content
+     *
+     * @return integer|boolean
+     */
+    public function getSize() 
+    {
+        return $this->size;
+    }
+    /**
+     * Get the content type of the object's content
+     *
+     * @return string
+     */
+    public function getContentType() 
+    {
+        return $this->contentType;
+    }
+    /**
+     * Get the data of the last modified of the object
+     *
+     * @return string
+     */
+    public function getLastModified() 
+    {
+        return $this->lastModified;
+    }
+    /**
+     * Get the content of the object
+     *
+     * @return string
+     */
+    public function getContent() 
+    {
+        return $this->content;
+    }
+    /**
+     * Get the metadata of the object
+     * If you don't pass the $key it returns the entire array of metadata value
+     *
+     * @param  string $key
+     * @return string|array|boolean
+     */
+    public function getMetadata($key=null) 
+    {
+        $result= $this->service->getMetadataObject($this->container,$this->name);
+        if (!empty($result)) {
+            if (empty($key)) {
+                return $result['metadata'];
+            }
+            if (isset($result['metadata'][$key])) {
+                return $result['metadata'][$key];
+            }
+        }
+        return false;
+    }
+    /**
+     * Set the metadata value
+     * The old metadata values are replaced with the new one
+     * 
+     * @param array $metadata
+     * @return boolean
+     */
+    public function setMetadata($metadata) 
+    {
+        return $this->service->setMetadataObject($this->container,$this->name,$metadata);
+    }
+    /**
+     * Copy the object to another container
+     * You can add metadata information to the destination object, change the
+     * content_type and the name of the object
+     *
+     * @param  string $container_dest
+     * @param  string $name_dest
+     * @param  array $metadata
+     * @param  string $content_type
+     * @return boolean
+     */
+    public function copyTo($container_dest,$name_dest,$metadata=array(),$content_type=null) 
+    {
+        return $this->service->copyObject($this->container,$this->name,$container_dest,$name_dest,$metadata,$content_type);
+    }
+    /**
+     * Get the CDN URL of the object
+     *
+     * @return string
+     */
+    public function getCdnUrl() 
+    {
+        $result= $this->service->getInfoCdnContainer($this->container);
+        if ($result!==false) {
+            if ($result['cdn_enabled']) {
+                return $result['cdn_uri'].'/'.$this->name;
+            }
+        }
+        return false;
+    }
+    /**
+     * Get the CDN SSL URL of the object
+     *
+     * @return string
+     */
+    public function getCdnUrlSsl() 
+    {
+        $result= $this->service->getInfoCdnContainer($this->container);
+        if ($result!==false) {
+            if ($result['cdn_enabled']) {
+                return $result['cdn_uri_ssl'].'/'.$this->name;
+            }
+        }
+        return false;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/Rackspace/Files/ObjectList.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,237 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service_Rackspace
+ * @subpackage Files
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+require_once 'Zend/Service/Rackspace/Files/Object.php';
+require_once 'Zend/Service/Rackspace/Files.php';
+
+/**
+ * List of servers retrived from the GoGrid web service
+ *
+ * @uses       ArrayAccess
+ * @uses       Countable
+ * @uses       Iterator
+ * @uses       OutOfBoundsException
+ * @uses       Zend_Service_Rackspace_Files
+ * @category   Zend
+ * @package    Zend_Service_Rackspace
+ * @subpackage Files
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Service_Rackspace_Files_ObjectList implements Countable, Iterator, ArrayAccess
+{
+    /**
+     * @var array of Zend_Service_Rackspace_Files_Object
+     */
+    protected $objects = array();
+    /**
+     * @var int Iterator key
+     */
+    protected $iteratorKey = 0;
+    /**
+     * @var RackspaceFiles
+     */
+    protected $service;
+    /**
+     * The container name of the object list
+     * 
+     * @var string
+     */
+    protected $container;
+    /**
+     * Construct
+     *
+     * @param  array $list
+     * @return boolean
+     */
+    public function __construct($service,$list,$container)
+    {
+        if (!($service instanceof Zend_Service_Rackspace_Files)) {
+            require_once 'Zend/Service/Rackspace/Files/Exception.php';
+            throw new Zend_Service_Rackspace_Files_Exception("You must pass a Zend_Service_Rackspace_Files object");
+        }
+        if (!is_array($list)) {
+            require_once 'Zend/Service/Rackspace/Files/Exception.php';
+            throw new Zend_Service_Rackspace_Files_Exception("You must pass an array of data objects");
+        }
+        if (empty($container)) {
+            require_once 'Zend/Service/Rackspace/Files/Exception.php';
+            throw new Zend_Service_Rackspace_Files_Exception("You must pass the container of the object list");
+        }
+        $this->service= $service;
+        $this->container= $container;
+        $this->_constructFromArray($list);
+    }
+    /**
+     * Transforms the Array to array of container
+     *
+     * @param  array $list
+     * @return void
+     */
+    private function _constructFromArray(array $list)
+    {
+        foreach ($list as $obj) {
+            $obj['container']= $this->container;
+            $this->_addObject(new Zend_Service_Rackspace_Files_Object($this->service,$obj));
+        }
+    }
+    /**
+     * Add an object
+     *
+     * @param  Zend_Service_Rackspace_Files_Object $obj
+     * @return Zend_Service_Rackspace_Files_ObjectList
+     */
+    protected function _addObject (Zend_Service_Rackspace_Files_Object $obj)
+    {
+        $this->objects[] = $obj;
+        return $this;
+    }
+    /**
+     * Return number of servers
+     *
+     * Implement Countable::count()
+     *
+     * @return int
+     */
+    public function count()
+    {
+        return count($this->objects);
+    }
+    /**
+     * Return the current element
+     *
+     * Implement Iterator::current()
+     *
+     * @return Zend_Service_Rackspace_Files_Object
+     */
+    public function current()
+    {
+        return $this->objects[$this->iteratorKey];
+    }
+    /**
+     * Return the key of the current element
+     *
+     * Implement Iterator::key()
+     *
+     * @return int
+     */
+    public function key()
+    {
+        return $this->iteratorKey;
+    }
+    /**
+     * Move forward to next element
+     *
+     * Implement Iterator::next()
+     *
+     * @return void
+     */
+    public function next()
+    {
+        $this->iteratorKey += 1;
+    }
+    /**
+     * Rewind the Iterator to the first element
+     *
+     * Implement Iterator::rewind()
+     *
+     * @return void
+     */
+    public function rewind()
+    {
+        $this->iteratorKey = 0;
+    }
+    /**
+     * Check if there is a current element after calls to rewind() or next()
+     *
+     * Implement Iterator::valid()
+     *
+     * @return bool
+     */
+    public function valid()
+    {
+        $numItems = $this->count();
+        if ($numItems > 0 && $this->iteratorKey < $numItems) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+    /**
+     * Whether the offset exists
+     *
+     * Implement ArrayAccess::offsetExists()
+     *
+     * @param   int     $offset
+     * @return  bool
+     */
+    public function offsetExists($offset)
+    {
+        return ($offset < $this->count());
+    }
+    /**
+     * Return value at given offset
+     *
+     * Implement ArrayAccess::offsetGet()
+     *
+     * @param   int     $offset
+     * @throws  Zend_Service_Rackspace_Files_Exception
+     * @return  Zend_Service_Rackspace_Files_Object
+     */
+    public function offsetGet($offset)
+    {
+        if ($this->offsetExists($offset)) {
+            return $this->objects[$offset];
+        } else {
+            require_once 'Zend/Service/Rackspace/Files/Exception.php';
+            throw new Zend_Service_Rackspace_Files_Exception('Illegal index');
+        }
+    }
+
+    /**
+     * Throws exception because all values are read-only
+     *
+     * Implement ArrayAccess::offsetSet()
+     *
+     * @param   int     $offset
+     * @param   string  $value
+     * @throws  Zend_Service_Rackspace_Files_Exception
+     */
+    public function offsetSet($offset, $value)
+    {
+        require_once 'Zend/Service/Rackspace/Files/Exception.php';
+        throw new Zend_Service_Rackspace_Files_Exception('You are trying to set read-only property');
+    }
+
+    /**
+     * Throws exception because all values are read-only
+     *
+     * Implement ArrayAccess::offsetUnset()
+     *
+     * @param   int     $offset
+     * @throws  Zend_Service_Rackspace_Files_Exception
+     */
+    public function offsetUnset($offset)
+    {
+        require_once 'Zend/Service/Rackspace/Files/Exception.php';
+        throw new Zend_Service_Rackspace_Files_Exception('You are trying to unset read-only property');
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/Rackspace/Servers.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,1281 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service
+ * @subpackage Rackspace
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+require_once 'Zend/Service/Rackspace/Abstract.php';
+require_once 'Zend/Service/Rackspace/Servers/Server.php';
+require_once 'Zend/Service/Rackspace/Servers/ServerList.php';
+require_once 'Zend/Service/Rackspace/Servers/Image.php';
+require_once 'Zend/Service/Rackspace/Servers/ImageList.php';
+require_once 'Zend/Service/Rackspace/Servers/SharedIpGroup.php';
+require_once 'Zend/Service/Rackspace/Servers/SharedIpGroupList.php';
+require_once 'Zend/Validate/Ip.php';
+
+class Zend_Service_Rackspace_Servers extends Zend_Service_Rackspace_Abstract
+{
+    const LIMIT_FILE_SIZE           = 10240;
+    const LIMIT_NUM_FILE            = 5;
+    const ERROR_SERVICE_UNAVAILABLE = 'The service is unavailable';
+    const ERROR_UNAUTHORIZED        = 'Unauthorized';
+    const ERROR_OVERLIMIT           = 'You reached the limit of requests, please wait some time before retry';
+    const ERROR_PARAM_NO_ID         = 'You must specify the item\'s id';
+    const ERROR_PARAM_NO_NAME       = 'You must specify the name';
+    const ERROR_PARAM_NO_SERVERID   = 'You must specify the server Id';
+    const ERROR_PARAM_NO_IMAGEID    = 'You must specify the server\'s image ID';
+    const ERROR_PARAM_NO_FLAVORID   = 'You must specify the server\'s flavor ID';
+    const ERROR_PARAM_NO_ARRAY      = 'You must specify an array of parameters';
+    const ERROR_PARAM_NO_WEEKLY     = 'You must specify a weekly backup schedule';
+    const ERROR_PARAM_NO_DAILY      = 'You must specify a daily backup schedule';
+    const ERROR_ITEM_NOT_FOUND      = 'The item specified doesn\'t exist.';
+    const ERROR_NO_FILE_EXISTS      = 'The file specified doesn\'t exist';
+    const ERROR_LIMIT_FILE_SIZE     = 'You reached the size length of a file';
+    const ERROR_IN_PROGRESS         = 'The item specified is still in progress';
+    const ERROR_BUILD_IN_PROGRESS   = 'The build is still in progress';
+    const ERROR_RESIZE_NOT_ALLOWED  = 'The resize is not allowed';
+    /**
+     * Get the list of the servers
+     * If $details is true returns detail info
+     * 
+     * @param  boolean $details
+     * @return Zend_Service_Rackspace_Servers_ServerList|boolean
+     */
+    public function listServers($details=false)
+    {
+        $url= '/servers';
+        if ($details) {
+            $url.= '/detail';
+        } 
+        $result= $this->httpCall($this->getManagementUrl().$url,'GET');
+        $status= $result->getStatus();
+        switch ($status) {
+            case '200' : 
+            case '203' : // break intentionally omitted   
+                $servers= json_decode($result->getBody(),true);
+                return new Zend_Service_Rackspace_Servers_ServerList($this,$servers['servers']);
+            case '503' :
+                $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE;
+                break;
+            case '401' :
+                $this->errorMsg= self::ERROR_UNAUTHORIZED;
+                break;
+            case '413' :
+                $this->errorMsg= self::ERROR_OVERLIMIT;
+                break;
+            default:
+                $this->errorMsg= $result->getBody();
+                break;
+        }
+        $this->errorCode= $status;
+        return false;
+    }
+    /**
+     * Get the specified server
+     * 
+     * @param  string $id 
+     * @return Zend_Service_Rackspace_Servers_Server
+     */
+    public function getServer($id) 
+    {
+        if (empty($id)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_ID);
+        }
+        $result= $this->httpCall($this->getManagementUrl().'/servers/'.rawurlencode($id),'GET');
+        $status= $result->getStatus();
+        switch ($status) {
+            case '200' : 
+            case '203' : // break intentionally omitted   
+                $server = json_decode($result->getBody(),true);
+                return new Zend_Service_Rackspace_Servers_Server($this,$server['server']);
+            case '503' :
+                $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE;
+                break;
+            case '401' :
+                $this->errorMsg= self::ERROR_UNAUTHORIZED;
+                break;
+            case '404' :
+                $this->errorMsg= self::ERROR_ITEM_NOT_FOUND;
+                break;
+            case '413' :
+                $this->errorMsg= self::ERROR_OVERLIMIT;
+                break;
+            default:
+                $this->errorMsg= $result->getBody();
+                break;
+        }
+        $this->errorCode= $status;
+        return false;
+    }
+    /**
+     * Create a new server
+     * 
+     * The required parameters are specified in $data (name, imageId, falvorId)
+     * The $files is an associative array with 'serverPath' => 'localPath'
+     * 
+     * @param  array $data 
+     * @param  array $metadata
+     * @param  array $files
+     * @return Zend_Service_Rackspace_Servers_Server|boolean
+     */
+    public function createServer(array $data, $metadata=array(),$files=array())
+    {
+        if (empty($data) || !is_array($data) || !is_array($metadata) || !is_array($files)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_ARRAY);
+        }
+        if (!isset($data['name'])) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME);
+        }
+        if (!isset($data['flavorId'])) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_FLAVORID);
+        }
+        if (!isset($data['imageId'])) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_IMAGEID);
+        }
+        if (count($files)>self::LIMIT_NUM_FILE) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception('You can attach '.self::LIMIT_NUM_FILE.' files maximum');
+        }
+        if (!empty($metadata)) {
+            $data['metadata']= $metadata;
+        }
+        $data['flavorId']= (integer) $data['flavorId'];
+        $data['imageId']= (integer) $data['imageId'];
+        if (!empty($files)) {
+            foreach ($files as $serverPath => $filePath) {
+                if (!file_exists($filePath)) {
+                    require_once 'Zend/Service/Rackspace/Exception.php';
+                    throw new Zend_Service_Rackspace_Exception(
+                            sprintf("The file %s doesn't exist",$filePath));
+                }
+                $content= file_get_contents($filePath);
+                if (strlen($content) > self::LIMIT_FILE_SIZE) {
+                    require_once 'Zend/Service/Rackspace/Exception.php';
+                    throw new Zend_Service_Rackspace_Exception(
+                            sprintf("The size of the file %s is greater than the max size of %d bytes",
+                                    $filePath,self::LIMIT_FILE_SIZE));
+                }
+                $data['personality'][] = array (
+                    'path'     => $serverPath,
+                    'contents' => base64_encode(file_get_contents($filePath))
+                );
+            }
+        }
+        $result = $this->httpCall($this->getManagementUrl().'/servers','POST',
+                null,null,json_encode(array ('server' => $data)));
+        $status = $result->getStatus();
+        switch ($status) {
+            case '200' :
+            case '202' : // break intentionally omitted   
+                $server = json_decode($result->getBody(),true);
+                return new Zend_Service_Rackspace_Servers_Server($this,$server['server']);
+            case '503' :
+                $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE;
+                break;
+            case '401' :
+                $this->errorMsg= self::ERROR_UNAUTHORIZED;
+                break;
+            case '404' :
+                $this->errorMsg= self::ERROR_ITEM_NOT_FOUND;
+                break;
+            case '413' :
+                $this->errorMsg= self::ERROR_OVERLIMIT;
+                break;
+            default:
+                $this->errorMsg= $result->getBody();
+                break;
+        }
+        $this->errorCode= $status;
+        return false;
+    }
+    /**
+     * Change the name or the admin password for a server
+     * 
+     * @param  string $id
+     * @param  string $name
+     * @param  string $password
+     * @return boolean 
+     */
+    protected function updateServer($id,$name=null,$password=null)
+    {
+        if (empty($id)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception('You must specify the ID of the server');
+        }
+        if (empty($name) && empty($password)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception("You must specify the new name or password of server");
+        }
+        $data= array();
+        if (!empty($name)) {
+            $data['name']= $name;
+        }
+        if (!empty($password)) {
+            $data['adminPass']= $password;
+        }
+        $result = $this->httpCall($this->getManagementUrl().'/servers/'.rawurlencode($id),'PUT',
+                null,null,json_encode(array('server' => $data)));
+        $status = $result->getStatus();
+        switch ($status) {
+            case '204' : // break intentionally omitted   
+                return true;
+            case '503' :
+                $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE;
+                break;
+            case '401' :
+                $this->errorMsg= self::ERROR_UNAUTHORIZED;
+                break;
+            case '404' :
+                $this->errorMsg= self::ERROR_ITEM_NOT_FOUND;
+                break;
+            case '409' :
+                $this->errorMsg= self::ERROR_IN_PROGRESS;
+                break;
+            case '413' :
+                $this->errorMsg= self::ERROR_OVERLIMIT;
+                break;
+            default:
+                $this->errorMsg= $result->getBody();
+                break;
+        }
+        $this->errorCode= $status;
+        return false;
+    }
+    /**
+     * Change the server's name
+     * 
+     * @param  string $id
+     * @param  string $name
+     * @return boolean 
+     */
+    public function changeServerName($id,$name)
+    {
+        if (empty($id)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception('You must specify the ID of the server');
+        }
+        if (empty($name)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception("You must specify the new name of the server");
+        }
+        return $this->updateServer($id, $name);
+    }
+    /**
+     * Change the admin password of the server
+     * 
+     * @param  string $id
+     * @param  string $password
+     * @return boolean 
+     */
+    public function changeServerPassword($id,$password)
+    {
+        if (empty($id)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception('You must specify the ID of the server');
+        }
+        if (empty($password)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception("You must specify the new password of the server");
+        }
+        return $this->updateServer($id, null,$password);
+    }
+    /**
+     * Delete a server
+     * 
+     * @param  string $id
+     * @return boolean 
+     */
+    public function deleteServer($id)
+    {
+        if (empty($id)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception('You must specify the ID of the server');
+        }
+        $result = $this->httpCall($this->getManagementUrl().'/servers/'.rawurlencode($id),'DELETE');
+        $status = $result->getStatus();
+        switch ($status) {
+            case '202' : // break intentionally omitted   
+                return true;
+            case '503' :
+                $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE;
+                break;
+            case '401' :
+                $this->errorMsg= self::ERROR_UNAUTHORIZED;
+                break;
+            case '404' :
+                $this->errorMsg= self::ERROR_ITEM_NOT_FOUND;
+                break;
+            case '409' :
+                $this->errorMsg= self::ERROR_IN_PROGRESS;
+                break;
+            case '413' :
+                $this->errorMsg= self::ERROR_OVERLIMIT;
+                break;
+            default:
+                $this->errorMsg= $result->getBody();
+                break;
+        }
+        $this->errorCode= $status;
+        return false;
+    }
+    /**
+     * Get the server's IPs (public and private)
+     * 
+     * @param  string $id
+     * @return array|boolean 
+     */
+    public function getServerIp($id)
+    {
+        $result= $this->getServer($id);
+        if ($result===false) {
+            return false;
+        }
+        $result= $result->toArray();
+        return $result['addresses'];
+    }
+    /**
+     * Get the Public IPs of a server
+     * 
+     * @param  string $id
+     * @return array|boolean
+     */
+    public function getServerPublicIp($id)
+    {
+        $addresses= $this->getServerIp($id);
+        if ($addresses===false) {
+            return false;
+        }
+        return $addresses['public'];
+    }
+    /**
+     * Get the Private IPs of a server
+     * 
+     * @param  string $id
+     * @return array|boolean
+     */
+    public function getServerPrivateIp($id)
+    {
+        $addresses= $this->getServerIp($id);
+        if ($addresses===false) {
+            return false;
+        }
+        return $addresses['private'];
+    }
+    /**
+     * Share an ip address for a server (id)
+     * 
+     * @param  string $id server
+     * @param  string $ip 
+     * @param  string $groupId
+     * @return boolean
+     */
+    public function shareIpAddress($id,$ip,$groupId,$configure=true)
+    {
+        if (empty($id)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception('You didn\'t specified the ID of the server');
+        }
+        if (empty($ip)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception('You didn\'t specified the IP address to share');
+        }
+        $validator = new Zend_Validate_Ip();
+        if (!$validator->isValid($ip)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception("The parameter $ip specified is not a valid IP address");
+        }
+        if (empty($groupId)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception('You didn\'t specified the group id to use');
+        }
+        $data= array (
+            'sharedIpGroupId' => (integer) $groupId,
+            'configureServer' => $configure
+        );
+        $result = $this->httpCall($this->getManagementUrl().'/servers/'.rawurlencode($id).'/ips/public/'.rawurlencode($ip),'PUT',
+                null,null,json_encode(array('shareIp' => $data)));
+        $status = $result->getStatus();
+        switch ($status) {
+            case '202' : // break intentionally omitted   
+                return true;
+            case '503' :
+                $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE;
+                break;
+            case '401' :
+                $this->errorMsg= self::ERROR_UNAUTHORIZED;
+                break;
+            case '404' :
+                $this->errorMsg= self::ERROR_ITEM_NOT_FOUND;
+                break;
+            case '413' :
+                $this->errorMsg= self::ERROR_OVERLIMIT;
+                break;
+            default:
+                $this->errorMsg= $result->getBody();
+                break;
+        }
+        $this->errorCode= $status;
+        return false;
+    }
+    /**
+     * Unshare IP address for a server ($id)
+     * 
+     * @param  string $id
+     * @param  string $ip
+     * @return boolean 
+     */
+    public function unshareIpAddress($id,$ip)
+    {
+        if (empty($id)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception('You didn\'t specified the ID of the server');
+        }
+        if (empty($ip)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception('You didn\'t specified the IP address to share');
+        }
+        $validator = new Zend_Validate_Ip();
+        if (!$validator->isValid($ip)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception("The parameter $ip specified is not a valid IP address");
+        }
+        $result = $this->httpCall($this->getManagementUrl().'/servers/'.rawurlencode($id).'/ips/public/'.rawurlencode($ip),
+                'DELETE');
+        $status = $result->getStatus();
+        switch ($status) {
+            case '202' : // break intentionally omitted   
+                return true;
+            case '503' :
+                $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE;
+                break;
+            case '401' :
+                $this->errorMsg= self::ERROR_UNAUTHORIZED;
+                break;
+            case '404' :
+                $this->errorMsg= self::ERROR_ITEM_NOT_FOUND;
+                break;
+            case '413' :
+                $this->errorMsg= self::ERROR_OVERLIMIT;
+                break;
+            default:
+                $this->errorMsg= $result->getBody();
+                break;
+        }
+        $this->errorCode= $status;
+        return false;
+    }
+    /**
+     * Reboot a server
+     * 
+     * $hard true is the equivalent of power cycling the server
+     * $hard false is a graceful shutdown
+     * 
+     * @param  string $id
+     * @param  boolean $hard 
+     * @return boolean
+     */
+    public function rebootServer($id,$hard=false)
+    {
+        if (empty($id)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception('You didn\'t specified the ID of the server');
+        }
+        if (!$hard) {
+            $type= 'SOFT';
+        } else {
+            $type= 'HARD';
+        }
+        $data= array (
+            'reboot' => array (
+                'type' => $type
+            )
+        );
+        $result = $this->httpCall($this->getManagementUrl().'/servers/'.rawurlencode($id).'/action',
+                                  'POST', null, null, json_encode($data));
+        $status = $result->getStatus();
+        switch ($status) {
+            case '200' :
+            case '202' : // break intentionally omitted   
+                return true;
+            case '503' :
+                $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE;
+                break;
+            case '401' :
+                $this->errorMsg= self::ERROR_UNAUTHORIZED;
+                break;
+            case '404' :
+                $this->errorMsg= self::ERROR_ITEM_NOT_FOUND;
+                break;
+            case '409' :
+                $this->errorMsg= self::ERROR_BUILD_IN_PROGRESS;
+                break;
+            case '413' :
+                $this->errorMsg= self::ERROR_OVERLIMIT;
+                break;
+            default:
+                $this->errorMsg= $result->getBody();
+                break;
+        }
+        $this->errorCode= $status;
+        return false;
+    }
+    /**
+     * Rebuild a server
+     * 
+     * The rebuild function removes all data on the server and replaces it with the specified image,
+     * serverId and IP addresses will remain the same.
+     * 
+     * @param  string $id
+     * @param  string $imageId
+     * @return boolean
+     */
+    public function rebuildServer($id,$imageId)
+    {
+        if (empty($id)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception('You didn\'t specified the ID of the server');
+        }
+        if (empty($imageId)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception('You didn\'t specified the new imageId of the server');
+        }
+        $data= array (
+            'rebuild' => array (
+                'imageId' => (integer) $imageId
+            )
+        );
+        $result = $this->httpCall($this->getManagementUrl().'/servers/'.rawurlencode($id).'/action',
+                                  'POST', null, null, json_encode($data));
+        $status = $result->getStatus();
+        switch ($status) {
+            case '202' : // break intentionally omitted   
+                return true;
+            case '503' :
+                $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE;
+                break;
+            case '401' :
+                $this->errorMsg= self::ERROR_UNAUTHORIZED;
+                break;
+            case '404' :
+                $this->errorMsg= self::ERROR_ITEM_NOT_FOUND;
+                break;
+            case '409' :
+                $this->errorMsg= self::ERROR_BUILD_IN_PROGRESS;
+                break;
+            case '413' :
+                $this->errorMsg= self::ERROR_OVERLIMIT;
+                break;
+            default:
+                $this->errorMsg= $result->getBody();
+                break;
+        }
+        $this->errorCode= $status;
+        return false;
+    }
+    /**
+     * Resize a server
+     * 
+     * The resize function converts an existing server to a different flavor, in essence, scaling the
+     * server up or down. The original server is saved for a period of time to allow rollback if there
+     * is a problem. All resizes should be tested and explicitly confirmed, at which time the original
+     * server is removed. All resizes are automatically confirmed after 24 hours if they are not
+     * explicitly confirmed or reverted.
+     * 
+     * @param  string $id
+     * @param  string $flavorId
+     * @return boolean
+     */
+    public function resizeServer($id,$flavorId)
+    {
+        if (empty($id)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception('You didn\'t specified the ID of the server');
+        }
+        if (empty($flavorId)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception('You didn\'t specified the new flavorId of the server');
+        }
+        $data= array (
+            'resize' => array (
+                'flavorId' => (integer) $flavorId
+            )
+        );
+        $result = $this->httpCall($this->getManagementUrl().'/servers/'.rawurlencode($id).'/action',
+                                  'POST', null, null, json_encode($data));
+        $status = $result->getStatus();
+        switch ($status) {
+            case '202' : // break intentionally omitted   
+                return true;
+            case '503' :
+                $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE;
+                break;
+            case '401' :
+                $this->errorMsg= self::ERROR_UNAUTHORIZED;
+                break;
+            case '403' :
+                $this->errorMsg= self::ERROR_RESIZE_NOT_ALLOWED;
+                break;
+            case '404' :
+                $this->errorMsg= self::ERROR_ITEM_NOT_FOUND;
+                break;
+            case '409' :
+                $this->errorMsg= self::ERROR_BUILD_IN_PROGRESS;
+                break;
+            case '413' :
+                $this->errorMsg= self::ERROR_OVERLIMIT;
+                break;
+            default:
+                $this->errorMsg= $result->getBody();
+                break;
+        }
+        $this->errorCode= $status;
+        return false;
+    }
+    /**
+     * Confirm resize of a server
+     * 
+     * During a resize operation, the original server is saved for a period of time to allow roll
+     * back if there is a problem. Once the newly resized server is tested and has been confirmed
+     * to be functioning properly, use this operation to confirm the resize. After confirmation,
+     * the original server is removed and cannot be rolled back to. All resizes are automatically
+     * confirmed after 24 hours if they are not explicitly confirmed or reverted.
+     *
+     * @param  string $id
+     * @return boolean 
+     */
+    public function confirmResizeServer($id)
+    {
+        if (empty($id)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception('You didn\'t specified the ID of the server');
+        }
+        $data= array (
+            'confirmResize' => null
+        );
+        $result = $this->httpCall($this->getManagementUrl().'/servers/'.rawurlencode($id).'/action',
+                                  'POST', null, null, json_encode($data));
+        $status = $result->getStatus();
+        switch ($status) {
+            case '204' : // break intentionally omitted   
+                return true;
+            case '503' :
+                $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE;
+                break;
+            case '401' :
+                $this->errorMsg= self::ERROR_UNAUTHORIZED;
+                break;
+            case '403' :
+                $this->errorMsg= self::ERROR_RESIZE_NOT_ALLOWED;
+                break;
+            case '404' :
+                $this->errorMsg= self::ERROR_ITEM_NOT_FOUND;
+                break;
+            case '409' :
+                $this->errorMsg= self::ERROR_BUILD_IN_PROGRESS;
+                break;
+            case '413' :
+                $this->errorMsg= self::ERROR_OVERLIMIT;
+                break;
+            default:
+                $this->errorMsg= $result->getBody();
+                break;
+        }
+        $this->errorCode= $status;
+        return false;
+    }
+    /**
+     * Revert resize of a server
+     * 
+     * During a resize operation, the original server is saved for a period of time to allow for roll
+     * back if there is a problem. If you determine there is a problem with a newly resized server,
+     * use this operation to revert the resize and roll back to the original server. All resizes are
+     * automatically confirmed after 24 hours if they have not already been confirmed explicitly or
+     * reverted.
+     *
+     * @param  string $id
+     * @return boolean 
+     */
+    public function revertResizeServer($id)
+    {
+        if (empty($id)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception('You didn\'t specified the ID of the server');
+        }
+        $data= array (
+            'revertResize' => null
+        );
+        $result = $this->httpCall($this->getManagementUrl().'/servers/'.rawurlencode($id).'/action',
+                                  'POST', null, null, json_encode($data));
+        $status = $result->getStatus();
+        switch ($status) {
+            case '202' : // break intentionally omitted   
+                return true;
+            case '503' :
+                $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE;
+                break;
+            case '401' :
+                $this->errorMsg= self::ERROR_UNAUTHORIZED;
+                break;
+            case '403' :
+                $this->errorMsg= self::ERROR_RESIZE_NOT_ALLOWED;
+                break;
+            case '404' :
+                $this->errorMsg= self::ERROR_ITEM_NOT_FOUND;
+                break;
+            case '409' :
+                $this->errorMsg= self::ERROR_BUILD_IN_PROGRESS;
+                break;
+            case '413' :
+                $this->errorMsg= self::ERROR_OVERLIMIT;
+                break;
+            default:
+                $this->errorMsg= $result->getBody();
+                break;
+        }
+        $this->errorCode= $status;
+        return false;
+    }
+    /**
+     * Get the list of the flavors
+     * 
+     * If $details is true returns detail info
+     * 
+     * @param  boolean $details
+     * @return array|boolean
+     */
+    public function listFlavors($details=false)
+    {
+        $url= '/flavors';
+        if ($details) {
+            $url.= '/detail';
+        } 
+        $result= $this->httpCall($this->getManagementUrl().$url,'GET');
+        $status= $result->getStatus();
+        switch ($status) {
+            case '200' : 
+            case '203' : // break intentionally omitted   
+                $flavors= json_decode($result->getBody(),true);
+                return $flavors['flavors'];
+            case '503' :
+                $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE;
+                break;
+            case '401' :
+                $this->errorMsg= self::ERROR_UNAUTHORIZED;
+                break;
+            case '413' :
+                $this->errorMsg= self::ERROR_OVERLIMIT;
+                break;
+            default:
+                $this->errorMsg= $result->getBody();
+                break;
+        }
+        $this->errorCode= $status;
+        return false;
+    }
+    /**
+     * Get the detail of a flavor
+     * 
+     * @param  string $flavorId
+     * @return array|boolean
+     */
+    public function getFlavor($flavorId)
+    {
+        if (empty($flavorId)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception('You didn\'t specified the new flavorId of the server');
+        }
+        $result= $this->httpCall($this->getManagementUrl().'/flavors/'.rawurlencode($flavorId),'GET');
+        $status= $result->getStatus();
+        switch ($status) {
+            case '200' : 
+            case '203' : // break intentionally omitted   
+                $flavor= json_decode($result->getBody(),true);
+                return $flavor['flavor'];
+            case '503' :
+                $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE;
+                break;
+            case '401' :
+                $this->errorMsg= self::ERROR_UNAUTHORIZED;
+                break;
+            case '413' :
+                $this->errorMsg= self::ERROR_OVERLIMIT;
+                break;
+            default:
+                $this->errorMsg= $result->getBody();
+                break;
+        }
+        $this->errorCode= $status;
+        return false;
+    }
+    /**
+     * Get the list of the images
+     * 
+     * @param  boolean $details
+     * @return Zend_Service_Rackspace_Servers_ImageList|boolean 
+     */
+    public function listImages($details=false)
+    {
+        $url= '/images';
+        if ($details) {
+            $url.= '/detail';
+        } 
+        $result= $this->httpCall($this->getManagementUrl().$url,'GET');
+        $status= $result->getStatus();
+        switch ($status) {
+            case '200' : 
+            case '203' : // break intentionally omitted   
+                $images= json_decode($result->getBody(),true);
+                return new Zend_Service_Rackspace_Servers_ImageList($this,$images['images']);
+            case '503' :
+                $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE;
+                break;
+            case '401' :
+                $this->errorMsg= self::ERROR_UNAUTHORIZED;
+                break;
+            case '413' :
+                $this->errorMsg= self::ERROR_OVERLIMIT;
+                break;
+            default:
+                $this->errorMsg= $result->getBody();
+                break;
+        }
+        $this->errorCode= $status;
+        return false;
+    }
+    /**
+     * Get detail about an image
+     * 
+     * @param  string $id
+     * @return Zend_Service_Rackspace_Servers_Image|boolean
+     */
+    public function getImage($id)
+    {
+        $result= $this->httpCall($this->getManagementUrl().'/images/'.rawurlencode($id),'GET');
+        $status= $result->getStatus();
+        switch ($status) {
+            case '200' : 
+            case '203' : // break intentionally omitted   
+                $image= json_decode($result->getBody(),true);
+                return new Zend_Service_Rackspace_Servers_Image($this,$image['image']);
+            case '503' :
+                $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE;
+                break;
+            case '401' :
+                $this->errorMsg= self::ERROR_UNAUTHORIZED;
+                break;
+            case '404' :
+                 $this->errorMsg= self::ERROR_ITEM_NOT_FOUND;
+                break;
+            case '413' :
+                $this->errorMsg= self::ERROR_OVERLIMIT;
+                break;
+            default:
+                $this->errorMsg= $result->getBody();
+                break;
+        }
+        $this->errorCode= $status;
+        return false;
+    }
+    /**
+     * Create an image for a serverId
+     * 
+     * @param  string $serverId
+     * @param  string $name 
+     * @return Zend_Service_Rackspace_Servers_Image
+     */
+    public function createImage($serverId,$name)
+    {
+        if (empty($serverId)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_SERVERID);
+        }
+        if (empty($name)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME);
+        }
+        $data = array(
+            'image' => array (
+                'serverId' => (integer) $serverId,
+                'name'     => $name
+            )
+        );
+        $result = $this->httpCall($this->getManagementUrl().'/images', 'POST',
+                                  null, null, json_encode($data));
+        $status = $result->getStatus();
+        switch ($status) {
+            case '202' : // break intentionally omitted   
+                $image= json_decode($result->getBody(),true);
+                return new Zend_Service_Rackspace_Servers_Image($this,$image['image']);
+            case '503' :
+                $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE;
+                break;
+            case '401' :
+                $this->errorMsg= self::ERROR_UNAUTHORIZED;
+                break;
+            case '403' :
+                $this->errorMsg= self::ERROR_RESIZE_NOT_ALLOWED;
+                break;
+            case '404' :
+                $this->errorMsg= self::ERROR_ITEM_NOT_FOUND;
+                break;
+            case '409' :
+                $this->errorMsg= self::ERROR_BUILD_IN_PROGRESS;
+                break;
+            case '413' :
+                $this->errorMsg= self::ERROR_OVERLIMIT;
+                break;
+            default:
+                $this->errorMsg= $result->getBody();
+                break;
+        }
+        $this->errorCode= $status;
+        return false;
+    }
+    /**
+     * Delete an image
+     * 
+     * @param  string $id
+     * @return boolean 
+     */
+    public function deleteImage($id)
+    {
+        if (empty($id)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_ID);
+        }
+        $result = $this->httpCall($this->getManagementUrl().'/images/'.rawurlencode($id),'DELETE');
+        $status = $result->getStatus();
+        switch ($status) {
+            case '204' : // break intentionally omitted   
+                return true;
+            case '503' :
+                $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE;
+                break;
+            case '401' :
+                $this->errorMsg= self::ERROR_UNAUTHORIZED;
+                break;
+            case '404' :
+                $this->errorMsg= self::ERROR_ITEM_NOT_FOUND;
+                break;
+            case '413' :
+                $this->errorMsg= self::ERROR_OVERLIMIT;
+                break;
+            default:
+                $this->errorMsg= $result->getBody();
+                break;
+        }
+        $this->errorCode= $status;
+        return false;
+    }
+    /**
+     * Get the backup schedule of a server
+     * 
+     * @param  string $id server's Id
+     * @return array|boolean 
+     */
+    public function getBackupSchedule($id)
+    {
+        if (empty($id)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_ID);
+        }
+        $result= $this->httpCall($this->getManagementUrl().'/servers/'.rawurlencode($id).'/backup_schedule',
+                                 'GET');
+        $status= $result->getStatus();
+        switch ($status) {
+            case '200' : 
+            case '203' : // break intentionally omitted   
+                $backup = json_decode($result->getBody(),true);
+                return $backup['backupSchedule'];
+            case '503' :
+                $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE;
+                break;
+            case '401' :
+                $this->errorMsg= self::ERROR_UNAUTHORIZED;
+                break;
+            case '404' :
+                $this->errorMsg= self::ERROR_ITEM_NOT_FOUND;
+                break;
+            case '413' :
+                $this->errorMsg= self::ERROR_OVERLIMIT;
+                break;
+            default:
+                $this->errorMsg= $result->getBody();
+                break;
+        }
+        $this->errorCode= $status;
+        return false;
+    }
+    /**
+     * Change the backup schedule of a server
+     * 
+     * @param  string $id server's Id
+     * @param  string $weekly
+     * @param  string $daily
+     * @return boolean 
+     */
+    public function changeBackupSchedule($id,$weekly,$daily)
+    {
+        if (empty($id)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_ID);
+        }
+        if (empty($weekly)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_WEEKLY);
+        }
+        if (empty($daily)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_DAILY);
+        }
+        $data = array (
+            'backupSchedule' => array (
+                'enabled' => true,
+                'weekly'  => $weekly,
+                'daily'   => $daily
+            )
+        );
+        $result= $this->httpCall($this->getManagementUrl().'/servers/'.rawurlencode($id).'/backup_schedule',
+                                 'POST',null,null,json_encode($data));
+        $status= $result->getStatus();
+        switch ($status) {
+            case '204' : // break intentionally omitted   
+                return true;
+            case '503' :
+                $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE;
+                break;
+            case '401' :
+                $this->errorMsg= self::ERROR_UNAUTHORIZED;
+                break;
+            case '404' :
+                $this->errorMsg= self::ERROR_ITEM_NOT_FOUND;
+                break;
+            case '409' :
+                $this->errorMsg= self::ERROR_BUILD_IN_PROGRESS;
+                break;
+            case '413' :
+                $this->errorMsg= self::ERROR_OVERLIMIT;
+                break;
+            default:
+                $this->errorMsg= $result->getBody();
+                break;
+        }
+        $this->errorCode= $status;
+        return false;
+    }
+    /**
+     * Disable the backup schedule for a server
+     * 
+     * @param  string $id server's Id
+     * @return boolean
+     */
+    public function disableBackupSchedule($id)
+    {
+        if (empty($id)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_ID);
+        }
+        $result = $this->httpCall($this->getManagementUrl().'/servers/'.rawurlencode($id).'/backup_schedule',
+                                  'DELETE');
+        $status = $result->getStatus();
+        switch ($status) {
+            case '204' : // break intentionally omitted   
+                return true;
+            case '503' :
+                $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE;
+                break;
+            case '401' :
+                $this->errorMsg= self::ERROR_UNAUTHORIZED;
+                break;
+            case '404' :
+                $this->errorMsg= self::ERROR_ITEM_NOT_FOUND;
+                break;
+            case '409' :
+                $this->errorMsg= self::ERROR_BUILD_IN_PROGRESS;
+                break;
+            case '413' :
+                $this->errorMsg= self::ERROR_OVERLIMIT;
+                break;
+            default:
+                $this->errorMsg= $result->getBody();
+                break;
+        }
+        $this->errorCode= $status;
+        return false;
+    }
+    /**
+     * Get the list of shared IP groups
+     * 
+     * @param  boolean $details
+     * @return Zend_Service_Rackspace_Servers_SharedIpGroupList|boolean 
+     */
+    public function listSharedIpGroups($details=false)
+    {
+        $url= '/shared_ip_groups';
+        if ($details) {
+            $url.= '/detail';
+        } 
+        $result= $this->httpCall($this->getManagementUrl().$url,'GET');
+        $status= $result->getStatus();
+        switch ($status) {
+            case '200' : 
+            case '203' : // break intentionally omitted   
+                $groups= json_decode($result->getBody(),true);
+                return new Zend_Service_Rackspace_Servers_SharedIpGroupList($this,$groups['sharedIpGroups']);
+            case '503' :
+                $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE;
+                break;
+            case '401' :
+                $this->errorMsg= self::ERROR_UNAUTHORIZED;
+                break;
+            case '413' :
+                $this->errorMsg= self::ERROR_OVERLIMIT;
+                break;
+            default:
+                $this->errorMsg= $result->getBody();
+                break;
+        }
+        $this->errorCode= $status;
+        return false;
+    }
+    /**
+     * Get the shared IP group
+     * 
+     * @param  integer $id
+     * @return Zend_Service_Rackspace_Servers_SharedIpGroup|boolean 
+     */
+    public function getSharedIpGroup($id)
+    {
+        if (empty($id)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_ID);
+        }
+        $result= $this->httpCall($this->getManagementUrl().'/shared_ip_groups/'.rawurlencode($id),'GET');
+        $status= $result->getStatus();
+        switch ($status) {
+            case '200' : 
+            case '203' : // break intentionally omitted   
+                $group= json_decode($result->getBody(),true);
+                return new Zend_Service_Rackspace_Servers_SharedIpGroup($this,$group['sharedIpGroup']);
+            case '503' :
+                $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE;
+                break;
+            case '401' :
+                $this->errorMsg= self::ERROR_UNAUTHORIZED;
+                break;
+            case '404' :
+                $this->errorMsg= self::ERROR_ITEM_NOT_FOUND;
+                break;
+            case '413' :
+                $this->errorMsg= self::ERROR_OVERLIMIT;
+                break;
+            default:
+                $this->errorMsg= $result->getBody();
+                break;
+        }
+        $this->errorCode= $status;
+        return false;
+    }
+    /**
+     * Create a shared Ip group
+     * 
+     * @param  string $name
+     * @param  string $serverId
+     * @return array|boolean 
+     */
+    public function createSharedIpGroup($name,$serverId)
+    {
+        if (empty($name)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_NAME);
+        }
+        if (empty($serverId)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_ID);
+        }
+        $data = array (
+            'sharedIpGroup' => array (
+                'name'   => $name,
+                'server' => (integer) $serverId
+            )
+        );
+        $result= $this->httpCall($this->getManagementUrl().'/shared_ip_groups',
+                                 'POST',null,null,json_encode($data));
+        $status= $result->getStatus();
+        switch ($status) {
+            case '201' : // break intentionally omitted   
+                $group = json_decode($result->getBody(),true);
+                return new Zend_Service_Rackspace_Servers_SharedIpGroup($this,$group['sharedIpGroup']);
+            case '503' :
+                $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE;
+                break;
+            case '401' :
+                $this->errorMsg= self::ERROR_UNAUTHORIZED;
+                break;
+            case '413' :
+                $this->errorMsg= self::ERROR_OVERLIMIT;
+                break;
+            default:
+                $this->errorMsg= $result->getBody();
+                break;
+        }
+        $this->errorCode= $status;
+        return false;
+    }
+    /**
+     * Delete a Shared Ip Group
+     * 
+     * @param  integer $id 
+     * @return boolean
+     */
+    public function deleteSharedIpGroup($id)
+    {
+        if (empty($id)) {
+            require_once 'Zend/Service/Rackspace/Exception.php';
+            throw new Zend_Service_Rackspace_Exception(self::ERROR_PARAM_NO_ID);
+        }
+        $result= $this->httpCall($this->getManagementUrl().'/shared_ip_groups/'.rawurlencode($id),'DELETE');
+        $status= $result->getStatus();
+        switch ($status) {
+            case '204' : // break intentionally omitted   
+                return true;
+            case '503' :
+                $this->errorMsg= self::ERROR_SERVICE_UNAVAILABLE;
+                break;
+            case '401' :
+                $this->errorMsg= self::ERROR_UNAUTHORIZED;
+                break;
+            case '404' :
+                $this->errorMsg= self::ERROR_ITEM_NOT_FOUND;
+                break;
+            case '413' :
+                $this->errorMsg= self::ERROR_OVERLIMIT;
+                break;
+            default:
+                $this->errorMsg= $result->getBody();
+                break;
+        }
+        $this->errorCode= $status;
+        return false;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/Rackspace/Servers/Exception.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,36 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service_Rackspace
+ * @subpackage Files
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: Exception.php 24593 2012-01-05 20:35:02Z matthew $
+ */
+
+/**
+ * @see Zend_Service_Rackspace_Exception
+ */
+require_once 'Zend/Service/Rackspace/Exception.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Service_Rackspace
+ * @subpackage Files
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Service_Rackspace_Servers_Exception extends Zend_Service_Rackspace_Exception
+{}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/Rackspace/Servers/Image.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,209 @@
+<?php
+
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service_Rackspace
+ * @subpackage Servers
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+require_once 'Zend/Service/Rackspace/Servers.php';
+
+class Zend_Service_Rackspace_Servers_Image
+{
+    const ERROR_PARAM_CONSTRUCT = 'You must pass a Zend_Service_Rackspace_Servers object and an array';
+    const ERROR_PARAM_NO_NAME   = 'You must pass the image\'s name in the array (name)';
+    const ERROR_PARAM_NO_ID     = 'You must pass the image\'s id in the array (id)';
+    /**
+     * Name of the image
+     * 
+     * @var string 
+     */
+    protected $name;
+    /**
+     * Id of the image
+     * 
+     * @var string 
+     */
+    protected $id;
+    /**
+     * Server Id of the image
+     * 
+     * @var string 
+     */
+    protected $serverId;
+    /**
+     * Updated data
+     * 
+     * @var string 
+     */
+    protected $updated;
+    /**
+     * Created data
+     * 
+     * @var string 
+     */
+    protected $created;
+    /**
+     * Status
+     * 
+     * @var string 
+     */
+    protected $status;
+    /**
+     * Status progress
+     * 
+     * @var integer 
+     */
+    protected $progress;
+    /**
+     * The service that has created the image object
+     *
+     * @var Zend_Service_Rackspace_Servers
+     */
+    protected $service;
+    /**
+     * Construct
+     * 
+     * @param array $data
+     * @return void
+     */
+    public function __construct($service, $data)
+    {
+        if (!($service instanceof Zend_Service_Rackspace_Servers) || !is_array($data)) {
+            require_once 'Zend/Service/Rackspace/Servers/Exception.php';
+            throw new Zend_Service_Rackspace_Servers_Exception(self::ERROR_PARAM_CONSTRUCT);
+        }
+        if (!array_key_exists('name', $data)) {
+            require_once 'Zend/Service/Rackspace/Servers/Exception.php';
+            throw new Zend_Service_Rackspace_Servers_Exception(self::ERROR_PARAM_NO_NAME);
+        }
+        if (!array_key_exists('id', $data)) {
+            require_once 'Zend/Service/Rackspace/Servers/Exception.php';
+            throw new Zend_Service_Rackspace_Servers_Exception(self::ERROR_PARAM_NO_ID);
+        }
+        $this->service= $service;
+        $this->name = $data['name'];
+        $this->id = $data['id'];
+        if (isset($data['serverId'])) {
+            $this->serverId= $data['serverId'];
+        }
+        if (isset($data['updated'])) {
+            $this->updated= $data['updated'];
+        }
+        if (isset($data['created'])) {
+            $this->created= $data['created'];
+        }
+        if (isset($data['status'])) {
+            $this->status= $data['status'];
+        }
+        if (isset($data['progress'])) {
+            $this->progress= $data['progress'];
+        }
+    }
+    /**
+     * Get the name of the image
+     *
+     * @return string
+     */
+    public function getName()
+    {
+        return $this->name;
+    }
+    /**
+     * Get the image's id
+     * 
+     * @return string 
+     */
+    public function getId()
+    {
+        return $this->id;
+    }
+    /**
+     * Get the server's id of the image
+     * 
+     * @return string 
+     */
+    public function getServerId()
+    {
+        return $this->serverId;
+    }
+    /**
+     * Get the updated data
+     * 
+     * @return string 
+     */
+    public function getUpdated()
+    {
+        return $this->updated;
+    }
+    /**
+     * Get the created data
+     * 
+     * @return string 
+     */
+    public function getCreated()
+    {
+        return $this->created;
+    }
+    /**
+     * Get the image's status
+     * 
+     * @return string|boolean
+     */
+    public function getStatus()
+    {
+        $data= $this->service->getImage($this->id);
+        if ($data!==false) {
+            $data= $data->toArray();
+            $this->status= $data['status'];
+            return $this->status;
+        }
+        return false;
+    }
+    /**
+     * Get the progress's status
+     * 
+     * @return integer|boolean
+     */
+    public function getProgress()
+    {
+        $data= $this->service->getImage($this->id);
+        if ($data!==false) {
+            $data= $data->toArray();
+            $this->progress= $data['progress'];
+            return $this->progress;
+        }
+        return false;
+    }
+    /**
+     * To Array
+     * 
+     * @return array 
+     */
+    public function toArray()
+    {
+        return array (
+            'name'     => $this->name,
+            'id'       => $this->id,
+            'serverId' => $this->serverId,
+            'updated'  => $this->updated,
+            'created'  => $this->created,
+            'status'   => $this->status,
+            'progress' => $this->progress
+        );
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/Rackspace/Servers/ImageList.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,234 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service_Rackspace
+ * @subpackage Servers
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+require_once 'Zend/Service/Rackspace/Servers.php';
+require_once 'Zend/Service/Rackspace/Servers/Image.php';
+
+/**
+ * List of images of Rackspace
+ *
+ * @uses       ArrayAccess
+ * @uses       Countable
+ * @uses       Iterator
+ * @uses       Zend_Service_Rackspace_Servers
+ * @category   Zend
+ * @package    Zend_Service_Rackspace
+ * @subpackage Servers
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Service_Rackspace_Servers_ImageList implements Countable, Iterator, ArrayAccess
+{
+    /**
+     * @var array of Zend_Service_Rackspace_Servers_Image
+     */
+    protected $images = array();
+    /**
+     * @var int Iterator key
+     */
+    protected $iteratorKey = 0;
+    /**
+     * @var Zend_Service_Rackspace_Servers
+     */
+    protected $service;
+    /**
+     * Construct
+     *
+     * @param  RackspaceServers $service
+     * @param  array $list
+     * @return void
+     */
+    public function __construct($service,$list = array())
+    {
+        if (!($service instanceof Zend_Service_Rackspace_Servers) || !is_array($list)) {
+            require_once 'Zend/Service/Rackspace/Servers/Exception.php';
+            throw new Zend_Service_Rackspace_Servers_Exception("You must pass a Zend_Service_Rackspace_Servers object and an array");
+        }
+        $this->service= $service;
+        $this->constructFromArray($list);
+    }
+    /**
+     * Transforms the array to array of Server
+     *
+     * @param  array $list
+     * @return void
+     */
+    private function constructFromArray(array $list)
+    {
+        foreach ($list as $image) {
+            $this->addImage(new Zend_Service_Rackspace_Servers_Image($this->service,$image));
+        }
+    }
+    /**
+     * Add an image
+     *
+     * @param  Zend_Service_Rackspace_Servers_Image $image
+     * @return Zend_Service_Rackspace_Servers_ImageList
+     */
+    protected function addImage (Zend_Service_Rackspace_Servers_Image $image)
+    {
+        $this->images[] = $image;
+        return $this;
+    }
+    /**
+     * To Array
+     * 
+     * @return array 
+     */
+    public function toArray()
+    {
+        $array= array();
+        foreach ($this->images as $image) {
+            $array[]= $image->toArray();
+        }
+        return $array;
+    }
+    /**
+     * Return number of images
+     *
+     * Implement Countable::count()
+     *
+     * @return int
+     */
+    public function count()
+    {
+        return count($this->images);
+    }
+    /**
+     * Return the current element
+     *
+     * Implement Iterator::current()
+     *
+     * @return Zend_Service_Rackspace_Servers_Image
+     */
+    public function current()
+    {
+        return $this->images[$this->iteratorKey];
+    }
+    /**
+     * Return the key of the current element
+     *
+     * Implement Iterator::key()
+     *
+     * @return int
+     */
+    public function key()
+    {
+        return $this->iteratorKey;
+    }
+    /**
+     * Move forward to next element
+     *
+     * Implement Iterator::next()
+     *
+     * @return void
+     */
+    public function next()
+    {
+        $this->iteratorKey += 1;
+    }
+    /**
+     * Rewind the Iterator to the first element
+     *
+     * Implement Iterator::rewind()
+     *
+     * @return void
+     */
+    public function rewind()
+    {
+        $this->iteratorKey = 0;
+    }
+    /**
+     * Check if there is a current element after calls to rewind() or next()
+     *
+     * Implement Iterator::valid()
+     *
+     * @return bool
+     */
+    public function valid()
+    {
+        $numItems = $this->count();
+        if ($numItems > 0 && $this->iteratorKey < $numItems) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+    /**
+     * Whether the offset exists
+     *
+     * Implement ArrayAccess::offsetExists()
+     *
+     * @param   int     $offset
+     * @return  bool
+     */
+    public function offsetExists($offset)
+    {
+        return ($offset < $this->count());
+    }
+    /**
+     * Return value at given offset
+     *
+     * Implement ArrayAccess::offsetGet()
+     *
+     * @param   int     $offset
+     * @throws  Zend_Service_Rackspace_Servers_Exception
+     * @return  Zend_Service_Rackspace_Servers_Image
+     */
+    public function offsetGet($offset)
+    {
+        if ($this->offsetExists($offset)) {
+            return $this->images[$offset];
+        } else {
+            require_once 'Zend/Service/Rackspace/Servers/Exception.php';
+            throw new Zend_Service_Rackspace_Servers_Exception('Illegal index');
+        }
+    }
+
+    /**
+     * Throws exception because all values are read-only
+     *
+     * Implement ArrayAccess::offsetSet()
+     *
+     * @param   int     $offset
+     * @param   string  $value
+     * @throws  Zend_Service_Rackspace_Servers_Exception
+     */
+    public function offsetSet($offset, $value)
+    {
+        require_once 'Zend/Service/Rackspace/Servers/Exception.php';
+        throw new Zend_Service_Rackspace_Servers_Exception('You are trying to set read-only property');
+    }
+
+    /**
+     * Throws exception because all values are read-only
+     *
+     * Implement ArrayAccess::offsetUnset()
+     *
+     * @param   int     $offset
+     * @throws  Zend_Service_Rackspace_Servers_Exception
+     */
+    public function offsetUnset($offset)
+    {
+        require_once 'Zend/Service/Rackspace/Servers/Exception.php';
+        throw new Zend_Service_Rackspace_Servers_Exception('You are trying to unset read-only property');
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/Rackspace/Servers/Server.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,325 @@
+<?php
+
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service_Rackspace
+ * @subpackage Servers
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+require_once 'Zend/Service/Rackspace/Servers.php';
+
+class Zend_Service_Rackspace_Servers_Server
+{
+    const ERROR_PARAM_CONSTRUCT = 'You must pass a Zend_Service_Rackspace_Servers object and an array';
+    const ERROR_PARAM_NO_NAME   = 'You must pass the server\'s name in the array (name)';
+    const ERROR_PARAM_NO_ID     = 'You must pass the server\'s id in the array (id)';
+    /**
+     * Server's name
+     * 
+     * @var string
+     */
+    protected $name;
+    /**
+     * Server's id
+     *
+     * @var string
+     */
+    protected $id;
+    /**
+     * Image id of the server
+     *
+     * @var string
+     */
+    protected $imageId;
+    /**
+     * Flavor id of the server
+     * 
+     * @var string 
+     */
+    protected $flavorId;
+    /**
+     * Host id
+     * 
+     * @var string
+     */
+    protected $hostId;
+    /**
+     * Server's status
+     * 
+     * @var string 
+     */
+    protected $status;
+    /**
+     * Progress of the status
+     * 
+     * @var integer
+     */
+    protected $progress;
+    /**
+     * Admin password, generated on a new server
+     * 
+     * @var string 
+     */
+    protected $adminPass;
+    /**
+     * Public and private IP addresses
+     * 
+     * @var array 
+     */
+    protected $addresses = array();
+    /**
+     * @var array
+     */
+    protected $metadata = array();
+    /**
+     * The service that has created the server object
+     *
+     * @var Zend_Service_Rackspace_Servers
+     */
+    protected $service;
+    /**
+     * Constructor
+     *
+     * @param  Zend_Service_Rackspace_Servers $service
+     * @param  array $data
+     * @return void
+     */
+    public function __construct($service, $data)
+    {
+        if (!($service instanceof Zend_Service_Rackspace_Servers) || !is_array($data)) {
+            require_once 'Zend/Service/Rackspace/Servers/Exception.php';
+            throw new Zend_Service_Rackspace_Servers_Exception(self::ERROR_PARAM_CONSTRUCT);
+        }
+        if (!array_key_exists('name', $data)) {
+            require_once 'Zend/Service/Rackspace/Servers/Exception.php';
+            throw new Zend_Service_Rackspace_Servers_Exception(self::ERROR_PARAM_NO_NAME);
+        }
+        if (!array_key_exists('id', $data)) {
+            require_once 'Zend/Service/Rackspace/Servers/Exception.php';
+            throw new Zend_Service_Rackspace_Servers_Exception(self::ERROR_PARAM_NO_ID);
+        }
+        $this->service = $service;
+        $this->name = $data['name'];
+        $this->id = $data['id'];
+        if (isset($data['imageId'])) {
+            $this->imageId= $data['imageId'];
+        }
+        if (isset($data['flavorId'])) {
+            $this->flavorId= $data['flavorId'];
+        }
+        if (isset($data['hostId'])) {
+            $this->hostId= $data['hostId'];
+        }
+        if (isset($data['status'])) {
+            $this->status= $data['status'];
+        }
+        if (isset($data['progress'])) {
+            $this->progress= $data['progress'];
+        }
+        if (isset($data['adminPass'])) {
+            $this->adminPass= $data['adminPass'];
+        }
+        if (isset($data['addresses']) && is_array($data['addresses'])) {
+            $this->addresses= $data['addresses'];
+        }
+        if (isset($data['metadata']) && is_array($data['metadata'])) {
+            $this->metadata= $data['metadata'];
+        } 
+    }
+    /**
+     * Get the name of the server
+     *
+     * @return string
+     */
+    public function getName()
+    {
+        return $this->name;
+    }
+    /**
+     * Get the server's id
+     * 
+     * @return string 
+     */
+    public function getId()
+    {
+        return $this->id;
+    }
+    /**
+     * Get the server's image Id
+     * 
+     * @return string 
+     */
+    public function getImageId()
+    {
+        return $this->imageId;
+    }
+    /**
+     * Get the server's flavor Id
+     * 
+     * @return string 
+     */
+    public function getFlavorId()
+    {
+        return $this->flavorId;
+    }
+    /**
+     * Get the server's host Id
+     * 
+     * @return string 
+     */
+    public function getHostId()
+    {
+        return $this->hostId;
+    }
+    /**
+     * Ge the server's admin password
+     * 
+     * @return string 
+     */
+    public function getAdminPass()
+    {
+        return $this->adminPass;
+    }
+    /**
+     * Get the server's status
+     * 
+     * @return string|boolean
+     */
+    public function getStatus()
+    {
+        $data= $this->service->getServer($this->id);
+        if ($data!==false) {
+            $data= $data->toArray();
+            $this->status= $data['status'];
+            return $this->status;
+        }
+        return false;
+    }
+    /**
+     * Get the progress's status
+     * 
+     * @return integer|boolean
+     */
+    public function getProgress()
+    {
+        $data= $this->service->getServer($this->id);
+        if ($data!==false) {
+            $data= $data->toArray();
+            $this->progress= $data['progress'];
+            return $this->progress;
+        }
+        return false;
+    }
+    /**
+     * Get the private IPs
+     * 
+     * @return array|boolean
+     */
+    public function getPrivateIp()
+    {
+        if (isset($this->addresses['private'])) {
+            return $this->addresses['private'];
+        }
+        return false;
+    }
+    /**
+     * Get the public IPs
+     * 
+     * @return array|boolean
+     */
+    public function getPublicIp()
+    {
+        if (isset($this->addresses['public'])) {
+            return $this->addresses['public'];
+        }
+        return false;
+    }
+    /**
+     * Get the metadata of the container
+     *
+     * If $key is empty return the array of metadata
+     *
+     * @param string $key
+     * @return array|string
+     */
+    public function getMetadata($key=null)
+    {
+        if (!empty($key) && isset($this->metadata[$key])) {
+            return $this->metadata[$key];
+        }
+        return $this->metadata;
+    }
+    /**
+     * Change the name of the server
+     * 
+     * @param string $name
+     * @return boolean 
+     */
+    public function changeName($name) 
+    {
+        $result= $this->service->changeServerName($this->id, $name);
+        if ($result!==false) {
+            $this->name= $name;
+            return true;
+        }
+        return false;
+    }
+    /**
+     * Change the admin password of the server
+     * 
+     * @param string $password
+     * @return boolean 
+     */
+    public function changePassword($password)
+    {
+        $result=  $this->service->changeServerPassword($this->id, $password);
+        if ($result!==false) {
+            $this->adminPass= $password;
+            return true;
+        }
+        return false;
+    }
+    /**
+     * Reboot the server
+     * 
+     * @return boolean 
+     */
+    public function reboot($hard=false)
+    {
+        return $this->service->rebootServer($this->id,$hard);
+    }
+    /**
+     * To Array
+     * 
+     * @return array 
+     */
+    public function toArray()
+    {
+        return array (
+            'name'      => $this->name,
+            'id'        => $this->id,
+            'imageId'   => $this->imageId,
+            'flavorId'  => $this->flavorId,
+            'hostId'    => $this->hostId,
+            'status'    => $this->status,
+            'progress'  => $this->progress,
+            'adminPass' => $this->adminPass,
+            'addresses' => $this->addresses,
+            'metadata'  => $this->metadata
+        );
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/Rackspace/Servers/ServerList.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,235 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service_Rackspace
+ * @subpackage Servers
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+require_once 'Zend/Service/Rackspace/Servers.php';
+require_once 'Zend/Service/Rackspace/Servers/Server.php';
+
+/**
+ * List of servers of Rackspace
+ *
+ * @uses       ArrayAccess
+ * @uses       Countable
+ * @uses       Iterator
+ * @uses       OutOfBoundsException
+ * @uses       Zend_Service_Rackspace_Servers
+ * @category   Zend
+ * @package    Zend_Service_Rackspace
+ * @subpackage Servers
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Service_Rackspace_Servers_ServerList implements Countable, Iterator, ArrayAccess
+{
+    /**
+     * @var array of Zend_Service_Rackspace_Servers_Server
+     */
+    protected $servers = array();
+    /**
+     * @var int Iterator key
+     */
+    protected $iteratorKey = 0;
+    /**
+     * @var Zend_Service_Rackspace_Servers
+     */
+    protected $service;
+    /**
+     * Construct
+     *
+     * @param  Zend_Service_Rackspace_Servers $service
+     * @param  array $list
+     * @return void
+     */
+    public function __construct($service,$list = array())
+    {
+        if (!($service instanceof Zend_Service_Rackspace_Servers) || !is_array($list)) {
+            require_once 'Zend/Service/Rackspace/Servers/Exception.php';
+            throw new Zend_Service_Rackspace_Servers_Exception("You must pass a Zend_Service_Rackspace_Servers object and an array");
+        }
+        $this->service= $service;
+        $this->constructFromArray($list);
+    }
+    /**
+     * Transforms the array to array of Server
+     *
+     * @param  array $list
+     * @return void
+     */
+    private function constructFromArray(array $list)
+    {
+        foreach ($list as $server) {
+            $this->addServer(new Zend_Service_Rackspace_Servers_Server($this->service,$server));
+        }
+    }
+    /**
+     * Add a server
+     *
+     * @param  Zend_Service_Rackspace_Servers_Server $server
+     * @return Zend_Service_Rackspace_Servers_ServerList
+     */
+    protected function addServer (Zend_Service_Rackspace_Servers_Server $server)
+    {
+        $this->servers[] = $server;
+        return $this;
+    }
+    /**
+     * To Array
+     * 
+     * @return array 
+     */
+    public function toArray()
+    {
+        $array= array();
+        foreach ($this->servers as $server) {
+            $array[]= $server->toArray();
+        }
+        return $array;
+    }
+    /**
+     * Return number of servers
+     *
+     * Implement Countable::count()
+     *
+     * @return int
+     */
+    public function count()
+    {
+        return count($this->servers);
+    }
+    /**
+     * Return the current element
+     *
+     * Implement Iterator::current()
+     *
+     * @return Zend_Service_Rackspace_Servers_Server
+     */
+    public function current()
+    {
+        return $this->servers[$this->iteratorKey];
+    }
+    /**
+     * Return the key of the current element
+     *
+     * Implement Iterator::key()
+     *
+     * @return int
+     */
+    public function key()
+    {
+        return $this->iteratorKey;
+    }
+    /**
+     * Move forward to next element
+     *
+     * Implement Iterator::next()
+     *
+     * @return void
+     */
+    public function next()
+    {
+        $this->iteratorKey += 1;
+    }
+    /**
+     * Rewind the Iterator to the first element
+     *
+     * Implement Iterator::rewind()
+     *
+     * @return void
+     */
+    public function rewind()
+    {
+        $this->iteratorKey = 0;
+    }
+    /**
+     * Check if there is a current element after calls to rewind() or next()
+     *
+     * Implement Iterator::valid()
+     *
+     * @return bool
+     */
+    public function valid()
+    {
+        $numItems = $this->count();
+        if ($numItems > 0 && $this->iteratorKey < $numItems) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+    /**
+     * Whether the offset exists
+     *
+     * Implement ArrayAccess::offsetExists()
+     *
+     * @param   int     $offset
+     * @return  bool
+     */
+    public function offsetExists($offset)
+    {
+        return ($offset < $this->count());
+    }
+    /**
+     * Return value at given offset
+     *
+     * Implement ArrayAccess::offsetGet()
+     *
+     * @param   int     $offset
+     * @throws  Zend_Service_Rackspace_Servers_Exception
+     * @return  Zend_Service_Rackspace_Servers_Server
+     */
+    public function offsetGet($offset)
+    {
+        if ($this->offsetExists($offset)) {
+            return $this->servers[$offset];
+        } else {
+            require_once 'Zend/Service/Rackspace/Servers/Exception.php';
+            throw new Zend_Service_Rackspace_Servers_Exception('Illegal index');
+        }
+    }
+
+    /**
+     * Throws exception because all values are read-only
+     *
+     * Implement ArrayAccess::offsetSet()
+     *
+     * @param   int     $offset
+     * @param   string  $value
+     * @throws  Zend_Service_Rackspace_Servers_Exception
+     */
+    public function offsetSet($offset, $value)
+    {
+        require_once 'Zend/Service/Rackspace/Servers/Exception.php';
+        throw new Zend_Service_Rackspace_Servers_Exception('You are trying to set read-only property');
+    }
+
+    /**
+     * Throws exception because all values are read-only
+     *
+     * Implement ArrayAccess::offsetUnset()
+     *
+     * @param   int     $offset
+     * @throws  Zend_Service_Rackspace_Servers_Exception
+     */
+    public function offsetUnset($offset)
+    {
+        require_once 'Zend/Service/Rackspace/Servers/Exception.php';
+        throw new Zend_Service_Rackspace_Servers_Exception('You are trying to unset read-only property');
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/Rackspace/Servers/SharedIpGroup.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,165 @@
+<?php
+
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service_Rackspace
+ * @subpackage Servers
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+require_once 'Zend/Service/Rackspace/Servers.php';
+
+class Zend_Service_Rackspace_Servers_SharedIpGroup
+{
+    const ERROR_PARAM_CONSTRUCT  = 'You must pass a Zend_Service_Rackspace_Servers object and an array';
+    const ERROR_PARAM_NO_NAME    = 'You must pass the image\'s name in the array (name)';
+    const ERROR_PARAM_NO_ID      = 'You must pass the image\'s id in the array (id)';
+    const ERROR_PARAM_NO_SERVERS = 'The servers parameter must be an array of Ids';
+    /**
+     * Name of the shared IP group
+     * 
+     * @var string 
+     */
+    protected $name;
+    /**
+     * Id of the shared IP group
+     * 
+     * @var string 
+     */
+    protected $id;
+    /**
+     * Array of servers of the shared IP group
+     * 
+     * @var array 
+     */
+    protected $serversId = array();
+    /**
+     * The service that has created the image object
+     *
+     * @var Zend_Service_Rackspace_Servers
+     */
+    protected $service;
+    /**
+     * Construct
+     * 
+     * @param  Zend_Service_Rackspace_Servers $service
+     * @param  array $data
+     * @return void
+     */
+    public function __construct($service, $data)
+    {
+        if (!($service instanceof Zend_Service_Rackspace_Servers) || !is_array($data)) {
+            require_once 'Zend/Service/Rackspace/Servers/Exception.php';
+            throw new Zend_Service_Rackspace_Servers_Exception(self::ERROR_PARAM_CONSTRUCT);
+        }
+        if (!array_key_exists('name', $data)) {
+            require_once 'Zend/Service/Rackspace/Servers/Exception.php';
+            throw new Zend_Service_Rackspace_Servers_Exception(self::ERROR_PARAM_NO_NAME);
+        }
+        if (!array_key_exists('id', $data)) {
+            require_once 'Zend/Service/Rackspace/Servers/Exception.php';
+            throw new Zend_Service_Rackspace_Servers_Exception(self::ERROR_PARAM_NO_ID);
+        }
+        if (isset($data['servers']) && !is_array($data['servers'])) {
+            require_once 'Zend/Service/Rackspace/Servers/Exception.php';
+            throw new Zend_Service_Rackspace_Servers_Exception(self::ERROR_PARAM_NO_SERVERS);
+        } 
+        $this->service= $service;
+        $this->name = $data['name'];
+        $this->id = $data['id'];
+        if (isset($data['servers'])) {
+            $this->serversId= $data['servers'];
+        }    
+    }
+    /**
+     * Get the name of the shared IP group
+     *
+     * @return string
+     */
+    public function getName()
+    {
+        return $this->name;
+    }
+    /**
+     * Get the id of the shared IP group
+     * 
+     * @return string 
+     */
+    public function getId()
+    {
+        return $this->id;
+    }
+    /**
+     * Get the server's array of the shared IP group
+     * 
+     * @return string 
+     */
+    public function getServersId()
+    {
+        if (empty($this->serversId)) {
+            $info= $this->service->getSharedIpGroup($this->id);
+            if (($info!==false)) {
+                $info= $info->toArray();
+                if (isset($info['servers'])) {
+                    $this->serversId= $info['servers'];
+                }
+            }    
+        }
+        return $this->serversId;
+    }
+    /**
+     * Get the server 
+     * 
+     * @param integer $id
+     * @return Zend_Service_Rackspace_Servers_Server|boolean
+     */
+    public function getServer($id)
+    {
+        if (empty($this->serversId)) {
+            $this->getServersId();
+        }
+        if (in_array($id,$this->serversId)) {
+            return $this->service->getServer($id);
+        }
+        return false;
+    }
+    /**
+     * Create a server in the shared Ip Group
+     * 
+     * @param  array $data
+     * @param  array $metadata
+     * @param  array $files 
+     * @return Zend_Service_Rackspace_Servers_Server|boolean
+     */
+    public function createServer(array $data, $metadata=array(),$files=array()) 
+    {
+        $data['sharedIpGroupId']= (integer) $this->id;
+        return $this->service->createServer($data,$metadata,$files);
+    }
+    /**
+     * To Array
+     * 
+     * @return array 
+     */
+    public function toArray()
+    {
+        return array (
+            'name'    => $this->name,
+            'id'      => $this->id,
+            'servers' => $this->serversId
+        );
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/Rackspace/Servers/SharedIpGroupList.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,234 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service_Rackspace
+ * @subpackage Servers
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+require_once 'Zend/Service/Rackspace/Servers.php';
+require_once 'Zend/Service/Rackspace/Servers/SharedIpGroup.php';
+
+/**
+ * List of shared Ip group of Rackspace
+ *
+ * @uses       ArrayAccess
+ * @uses       Countable
+ * @uses       Iterator
+ * @uses       Zend_Service_Rackspace_Servers
+ * @category   Zend
+ * @package    Zend_Service_Rackspace
+ * @subpackage Servers
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Service_Rackspace_Servers_SharedIpGroupList implements Countable, Iterator, ArrayAccess
+{
+    /**
+     * @var array of Zend_Service_Rackspace_Servers_SharedIpGroup
+     */
+    protected $shared = array();
+    /**
+     * @var int Iterator key
+     */
+    protected $iteratorKey = 0;
+    /**
+     * @var Zend_Service_Rackspace_Servers
+     */
+    protected $service;
+    /**
+     * Construct
+     *
+     * @param  Zend_Service_Rackspace_Servers $service
+     * @param  array $list
+     * @return void
+     */
+    public function __construct($service,$list = array())
+    {
+        if (!($service instanceof Zend_Service_Rackspace_Servers) || !is_array($list)) {
+            require_once 'Zend/Service/Rackspace/Servers/Exception.php';
+            throw new Zend_Service_Rackspace_Servers_Exception("You must pass a Zend_Service_Rackspace_Servers object and an array");
+        }
+        $this->service= $service;
+        $this->constructFromArray($list);
+    }
+    /**
+     * Transforms the array to array of Shared Ip Group
+     *
+     * @param  array $list
+     * @return void
+     */
+    private function constructFromArray(array $list)
+    {
+        foreach ($list as $share) {
+            $this->addSharedIpGroup(new Zend_Service_Rackspace_Servers_SharedIpGroup($this->service,$share));
+        }
+    }
+    /**
+     * Add a shared Ip group
+     *
+     * @param  Zend_Service_Rackspace_Servers_SharedIpGroup $shared
+     * @return Zend_Service_Rackspace_Servers_SharedIpGroupList
+     */
+    protected function addSharedIpGroup (Zend_Service_Rackspace_Servers_SharedIpGroup $share)
+    {
+        $this->shared[] = $share;
+        return $this;
+    }
+    /**
+     * To Array
+     * 
+     * @return array 
+     */
+    public function toArray()
+    {
+        $array= array();
+        foreach ($this->shared as $share) {
+            $array[]= $share->toArray();
+        }
+        return $array;
+    }
+    /**
+     * Return number of shared Ip Groups
+     *
+     * Implement Countable::count()
+     *
+     * @return int
+     */
+    public function count()
+    {
+        return count($this->shared);
+    }
+    /**
+     * Return the current element
+     *
+     * Implement Iterator::current()
+     *
+     * @return Zend_Service_Rackspace_Servers_SharedIpGroup
+     */
+    public function current()
+    {
+        return $this->shared[$this->iteratorKey];
+    }
+    /**
+     * Return the key of the current element
+     *
+     * Implement Iterator::key()
+     *
+     * @return int
+     */
+    public function key()
+    {
+        return $this->iteratorKey;
+    }
+    /**
+     * Move forward to next element
+     *
+     * Implement Iterator::next()
+     *
+     * @return void
+     */
+    public function next()
+    {
+        $this->iteratorKey += 1;
+    }
+    /**
+     * Rewind the Iterator to the first element
+     *
+     * Implement Iterator::rewind()
+     *
+     * @return void
+     */
+    public function rewind()
+    {
+        $this->iteratorKey = 0;
+    }
+    /**
+     * Check if there is a current element after calls to rewind() or next()
+     *
+     * Implement Iterator::valid()
+     *
+     * @return boolean
+     */
+    public function valid()
+    {
+        $numItems = $this->count();
+        if ($numItems > 0 && $this->iteratorKey < $numItems) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+    /**
+     * Whether the offset exists
+     *
+     * Implement ArrayAccess::offsetExists()
+     *
+     * @param   int     $offset
+     * @return  boolean
+     */
+    public function offsetExists($offset)
+    {
+        return ($offset < $this->count());
+    }
+    /**
+     * Return value at given offset
+     *
+     * Implement ArrayAccess::offsetGet()
+     *
+     * @param   int  $offset
+     * @throws  Zend_Service_Rackspace_Servers_Exception
+     * @return  Zend_Service_Rackspace_Servers_SharedIpGroup
+     */
+    public function offsetGet($offset)
+    {
+        if ($this->offsetExists($offset)) {
+            return $this->shared[$offset];
+        } else {
+            require_once 'Zend/Service/Rackspace/Servers/Exception.php';
+            throw new Zend_Service_Rackspace_Servers_Exception('Illegal index');
+        }
+    }
+
+    /**
+     * Throws exception because all values are read-only
+     *
+     * Implement ArrayAccess::offsetSet()
+     *
+     * @param   int     $offset
+     * @param   string  $value
+     * @throws  Zend_Service_Rackspace_Servers_Exception
+     */
+    public function offsetSet($offset, $value)
+    {
+        require_once 'Zend/Service/Rackspace/Servers/Exception.php';
+        throw new Zend_Service_Rackspace_Servers_Exception('You are trying to set read-only property');
+    }
+
+    /**
+     * Throws exception because all values are read-only
+     *
+     * Implement ArrayAccess::offsetUnset()
+     *
+     * @param  int $offset
+     * @throws Zend_Service_Rackspace_Servers_Exception
+     */
+    public function offsetUnset($offset)
+    {
+        require_once 'Zend/Service/Rackspace/Servers/Exception.php';
+        throw new Zend_Service_Rackspace_Servers_Exception('You are trying to unset read-only property');
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/ShortUrl/BitLy.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,167 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service_ShortUrl
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/**
+ * @see Zend_Service_ShortUrl_AbstractShortener
+ */
+require_once 'Zend/Service/ShortUrl/AbstractShortener.php';
+
+/**
+ * Bit.ly API implementation
+ *
+ * @category   Zend
+ * @package    Zend_Service_ShortUrl
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Service_ShortUrl_BitLy extends Zend_Service_ShortUrl_AbstractShortener
+{
+
+    /**
+     * Base URI of the service
+     *
+     * @var string
+     */
+    protected $_apiUri = 'http://api.bitly.com';
+
+    /**
+     * user login name
+     *
+     * @var string
+     */
+    protected $_loginName;
+
+    /**
+     * user API key or application access token
+     *
+     * @var string
+     */
+    protected $_apiKey;
+
+    /**
+     * @param string $login user login name or application access token
+     * @param null|string $apiKey user API key
+     */
+    public function __construct($login, $apiKey = null)
+    {
+        if(null === $apiKey) {
+            $this->setOAuthAccessToken($login);
+        } else {
+            $this->setApiLogin($login, $apiKey);
+        }
+    }
+
+    /**
+     * set OAuth credentials
+     *
+     * @param $accessToken
+     * @return Zend_Service_ShortUrl_BitLy
+     */
+    public function setOAuthAccessToken($accessToken)
+    {
+        $this->_apiKey = $accessToken;
+        $this->_loginName = null;
+        return $this;
+    }
+
+    /**
+     * set login credentials
+     *
+     * @param $login
+     * @param $apiKey
+     * @return Zend_Service_ShortUrl_BitLy
+     */
+    public function setApiLogin($login, $apiKey)
+    {
+        $this->_apiKey = $apiKey;
+        $this->_loginName = $login;
+        return $this;
+    }
+
+    /**
+     * prepare http client
+     * @return void
+     */
+    protected function _setAccessParameter()
+    {
+        if(null === $this->_loginName) {
+            //OAuth login
+            $this->getHttpClient()->setParameterGet('access_token', $this->_apiKey);
+        } else {
+            //login/APIKey authentication
+            $this->getHttpClient()->setParameterGet('login',$this->_loginName);
+            $this->getHttpClient()->setParameterGet('apiKey',$this->_apiKey);
+        }
+    }
+
+    /**
+     * handle bit.ly response
+     *
+     * @return string
+     * @throws Zend_Service_ShortUrl_Exception
+     */
+    protected function _processRequest()
+    {
+        $response = $this->getHttpClient()->request();
+        if(500 == $response->getStatus()) {
+            throw new Zend_Service_ShortUrl_Exception('Bit.ly :: '.$response->getBody());
+        }
+        return $response->getBody();
+    }
+
+    /**
+     * This function shortens long url
+     *
+     * @param  string $url URL to Shorten
+     * @throws Zend_Service_ShortUrl_Exception if bit.ly reports an error
+     * @return string Shortened Url
+     */
+    public function shorten($url)
+    {
+        $this->_validateUri($url);
+        $this->_setAccessParameter();
+
+        $this->getHttpClient()->setUri($this->_apiUri.'/v3/shorten');
+        $this->getHttpClient()->setParameterGet('longUrl',$url);
+        $this->getHttpClient()->setParameterGet('format','txt');
+
+        return $this->_processRequest();
+    }
+
+    /**
+     * Reveals target for short URL
+     *
+     * @param  string $shortenedUrl URL to reveal target of
+     * @throws Zend_Service_ShortUrl_Exception if bit.ly reports an error
+     * @return string Unshortened Url
+     */
+    public function unshorten($shortenedUrl)
+    {
+        $this->_validateUri($shortenedUrl);
+        $this->_setAccessParameter();
+
+        $this->getHttpClient()->setUri($this->_apiUri.'/v3/expand');
+        $this->getHttpClient()->setParameterGet('shortUrl',$shortenedUrl);
+        $this->getHttpClient()->setParameterGet('format','txt');
+
+        return $this->_processRequest();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/SqlAzure/Exception.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,35 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure
+ * @subpackage Exception
+ * @version    $Id$
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+/**
+ * @see Zend_Service_Exception
+ */
+require_once 'Zend/Service/Exception.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Service_SqlAzure
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Service_SqlAzure_Exception extends Zend_Service_Exception
+{}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/SqlAzure/Management/Client.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,609 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure
+ * @subpackage Management
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/**
+ * @see Zend_Http_Client
+ */
+ require_once 'Zend/Http/Client.php';
+ 
+ /**
+ * @see Zend_Service_WindowsAzure_RetryPolicy_RetryPolicyAbstract
+ */
+ require_once 'Zend/Service/WindowsAzure/RetryPolicy/RetryPolicyAbstract.php';
+ 
+ /**
+ * @see Zend_Service_SqlAzure_Management_ServerInstance
+ */
+ require_once 'Zend/Service/SqlAzure/Management/ServerInstance.php';
+ 
+ /**
+ * @see Zend_Service_SqlAzure_Management_FirewallRuleInstance
+ */
+ require_once 'Zend/Service/SqlAzure/Management/FirewallRuleInstance.php';
+ 
+/**
+ * @category   Zend
+ * @package    Zend_Service_SqlAzure
+ * @subpackage Management
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Service_SqlAzure_Management_Client
+{
+	/**
+	 * Management service URL
+	 */
+	const URL_MANAGEMENT        = "https://management.database.windows.net:8443";
+	
+	/**
+	 * Operations
+	 */
+	const OP_OPERATIONS                = "operations";
+	const OP_SERVERS                   = "servers";
+	const OP_FIREWALLRULES             = "firewallrules";
+
+	/**
+	 * Current API version
+	 * 
+	 * @var string
+	 */
+	protected $_apiVersion = '1.0';
+	
+	/**
+	 * Subscription ID
+	 *
+	 * @var string
+	 */
+	protected $_subscriptionId = '';
+	
+	/**
+	 * Management certificate path (.PEM)
+	 *
+	 * @var string
+	 */
+	protected $_certificatePath = '';
+	
+	/**
+	 * Management certificate passphrase
+	 *
+	 * @var string
+	 */
+	protected $_certificatePassphrase = '';
+	
+	/**
+	 * Zend_Http_Client channel used for communication with REST services
+	 * 
+	 * @var Zend_Http_Client
+	 */
+	protected $_httpClientChannel = null;	
+
+	/**
+	 * Zend_Service_WindowsAzure_RetryPolicy_RetryPolicyAbstract instance
+	 * 
+	 * @var Zend_Service_WindowsAzure_RetryPolicy_RetryPolicyAbstract
+	 */
+	protected $_retryPolicy = null;
+	
+	/**
+	 * Returns the last request ID
+	 * 
+	 * @var string
+	 */
+	protected $_lastRequestId = null;
+	
+	/**
+	 * Creates a new Zend_Service_SqlAzure_Management instance
+	 * 
+	 * @param string $subscriptionId Subscription ID
+	 * @param string $certificatePath Management certificate path (.PEM)
+	 * @param string $certificatePassphrase Management certificate passphrase
+     * @param Zend_Service_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy Retry policy to use when making requests
+	 */
+	public function __construct(
+		$subscriptionId,
+		$certificatePath,
+		$certificatePassphrase,
+		Zend_Service_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy = null
+	) {
+		$this->_subscriptionId = $subscriptionId;
+		$this->_certificatePath = $certificatePath;
+		$this->_certificatePassphrase = $certificatePassphrase;
+		
+		$this->_retryPolicy = $retryPolicy;
+		if (is_null($this->_retryPolicy)) {
+		    $this->_retryPolicy = Zend_Service_WindowsAzure_RetryPolicy_RetryPolicyAbstract::noRetry();
+		}
+		
+		// Setup default Zend_Http_Client channel
+		$options = array(
+		    'adapter'       => 'Zend_Http_Client_Adapter_Socket',
+		    'ssltransport'  => 'ssl',
+			'sslcert'       => $this->_certificatePath,
+			'sslpassphrase' => $this->_certificatePassphrase,
+			'sslusecontext' => true,
+		);
+		if (function_exists('curl_init')) {
+			// Set cURL options if cURL is used afterwards
+			$options['curloptions'] = array(
+					CURLOPT_FOLLOWLOCATION => true,
+					CURLOPT_TIMEOUT => 120,
+			);
+		}
+		$this->_httpClientChannel = new Zend_Http_Client(null, $options);
+	}
+	
+	/**
+	 * Set the HTTP client channel to use
+	 * 
+	 * @param Zend_Http_Client_Adapter_Interface|string $adapterInstance Adapter instance or adapter class name.
+	 */
+	public function setHttpClientChannel($adapterInstance = 'Zend_Http_Client_Adapter_Socket')
+	{
+		$this->_httpClientChannel->setAdapter($adapterInstance);
+	}
+	
+    /**
+     * Retrieve HTTP client channel
+     * 
+     * @return Zend_Http_Client_Adapter_Interface
+     */
+    public function getHttpClientChannel()
+    {
+        return $this->_httpClientChannel;
+    }
+	
+	/**
+	 * Returns the Windows Azure subscription ID
+	 * 
+	 * @return string
+	 */
+	public function getSubscriptionId()
+	{
+		return $this->_subscriptionId;
+	}
+	
+	/**
+	 * Returns the last request ID.
+	 * 
+	 * @return string
+	 */
+	public function getLastRequestId()
+	{
+		return $this->_lastRequestId;
+	}
+	
+	/**
+	 * Get base URL for creating requests
+	 *
+	 * @return string
+	 */
+	public function getBaseUrl()
+	{
+		return self::URL_MANAGEMENT . '/' . $this->_subscriptionId;
+	}
+	
+	/**
+	 * Perform request using Zend_Http_Client channel
+	 *
+	 * @param string $path Path
+	 * @param string $queryString Query string
+	 * @param string $httpVerb HTTP verb the request will use
+	 * @param array $headers x-ms headers to add
+	 * @param mixed $rawData Optional RAW HTTP data to be sent over the wire
+	 * @return Zend_Http_Response
+	 */
+	protected function _performRequest(
+		$path = '/',
+		$queryString = '',
+		$httpVerb = Zend_Http_Client::GET,
+		$headers = array(),
+		$rawData = null
+	) {
+	    // Clean path
+		if (strpos($path, '/') !== 0) {
+			$path = '/' . $path;
+		}
+			
+		// Clean headers
+		if (is_null($headers)) {
+		    $headers = array();
+		}
+		
+		// Ensure cUrl will also work correctly:
+		//  - disable Content-Type if required
+		//  - disable Expect: 100 Continue
+		if (!isset($headers["Content-Type"])) {
+			$headers["Content-Type"] = '';
+		}
+		//$headers["Expect"] = '';
+
+		// Add version header
+		$headers['x-ms-version'] = $this->_apiVersion;
+		    
+		// URL encoding
+		$path           = self::urlencode($path);
+		$queryString    = self::urlencode($queryString);
+
+		// Generate URL and sign request
+		$requestUrl     = $this->getBaseUrl() . $path . $queryString;
+		$requestHeaders = $headers;
+
+		// Prepare request 
+		$this->_httpClientChannel->resetParameters(true);
+		$this->_httpClientChannel->setUri($requestUrl);
+		$this->_httpClientChannel->setHeaders($requestHeaders);
+		$this->_httpClientChannel->setRawData($rawData);
+
+		// Execute request
+		$response = $this->_retryPolicy->execute(
+		    array($this->_httpClientChannel, 'request'),
+		    array($httpVerb)
+		);
+		
+		// Store request id
+		$this->_lastRequestId = $response->getHeader('x-ms-request-id');
+		
+		return $response;
+	}
+	
+	/** 
+	 * Parse result from Zend_Http_Response
+	 *
+	 * @param Zend_Http_Response $response Response from HTTP call
+	 * @return object
+	 * @throws Zend_Service_WindowsAzure_Exception
+	 */
+	protected function _parseResponse(Zend_Http_Response $response = null)
+	{
+		if (is_null($response)) {
+			require_once 'Zend/Service/SqlAzure/Exception.php';
+			throw new Zend_Service_SqlAzure_Exception('Response should not be null.');
+		}
+		
+        $xml = @simplexml_load_string($response->getBody());
+        
+        if ($xml !== false) {
+            // Fetch all namespaces 
+            $namespaces = array_merge($xml->getNamespaces(true), $xml->getDocNamespaces(true)); 
+            
+            // Register all namespace prefixes
+            foreach ($namespaces as $prefix => $ns) { 
+                if ($prefix != '') {
+                    $xml->registerXPathNamespace($prefix, $ns);
+                } 
+            } 
+        }
+        
+        return $xml;
+	}
+	
+	/**
+	 * URL encode function
+	 * 
+	 * @param  string $value Value to encode
+	 * @return string        Encoded value
+	 */
+	public static function urlencode($value)
+	{
+	    return str_replace(' ', '%20', $value);
+	}
+	
+    /**
+     * Builds a query string from an array of elements
+     * 
+     * @param array     Array of elements
+     * @return string   Assembled query string
+     */
+    public static function createQueryStringFromArray($queryString)
+    {
+    	return count($queryString) > 0 ? '?' . implode('&', $queryString) : '';
+    }
+    
+	/**
+	 * Get error message from Zend_Http_Response
+	 *
+	 * @param Zend_Http_Response $response Repsonse
+	 * @param string $alternativeError Alternative error message
+	 * @return string
+	 */
+	protected function _getErrorMessage(Zend_Http_Response $response, $alternativeError = 'Unknown error.')
+	{
+		$response = $this->_parseResponse($response);
+		if ($response && $response->Message) {
+			return (string)$response->Message;
+		} else {
+			return $alternativeError;
+		}
+	}
+	
+	/**
+	 * The Create Server operation adds a new SQL Azure server to a subscription.
+	 * 
+	 * @param string $administratorLogin Administrator login.
+	 * @param string $administratorPassword Administrator password.
+	 * @param string $location Location of the server.
+	 * @return Zend_Service_SqlAzure_Management_ServerInstance Server information.
+	 * @throws Zend_Service_SqlAzure_Management_Exception
+	 */
+	public function createServer($administratorLogin, $administratorPassword, $location)
+	{
+		if ($administratorLogin == '' || is_null($administratorLogin)) {
+                    require_once 'Zend/Service/SqlAzure/Management/Exception.php';
+                    throw new Zend_Service_SqlAzure_Management_Exception('Administrator login should be specified.');
+                }
+		if ($administratorPassword == '' || is_null($administratorPassword)) {
+                    require_once 'Zend/Service/SqlAzure/Management/Exception.php';
+                    throw new Zend_Service_SqlAzure_Management_Exception('Administrator password should be specified.');
+                }
+                if (is_null($location) && is_null($affinityGroup)) {
+                    require_once 'Zend/Service/SqlAzure/Management/Exception.php';
+                    throw new Zend_Service_SqlAzure_Management_Exception('Please specify a location for the server.');
+                }
+    	
+                $response = $this->_performRequest(self::OP_SERVERS, '',
+    		Zend_Http_Client::POST,
+    		array('Content-Type' => 'application/xml; charset=utf-8'),
+    		'<Server xmlns="http://schemas.microsoft.com/sqlazure/2010/12/"><AdministratorLogin>' . $administratorLogin . '</AdministratorLogin><AdministratorLoginPassword>' . $administratorPassword . '</AdministratorLoginPassword><Location>' . $location . '</Location></Server>');
+ 	
+                if ($response->isSuccessful()) {
+			$xml = $this->_parseResponse($response);
+			
+			return new Zend_Service_SqlAzure_Management_ServerInstance(
+				(string)$xml,
+				$administratorLogin,
+				$location
+			);
+                } else {
+			require_once 'Zend/Service/SqlAzure/Management/Exception.php';
+			throw new Zend_Service_SqlAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
+		}	
+	}
+	
+	/**
+	 * The Get Servers operation enumerates SQL Azure servers that are provisioned for a subscription.
+	 * 
+	 * @return array An array of Zend_Service_SqlAzure_Management_ServerInstance.
+	 * @throws Zend_Service_SqlAzure_Management_Exception
+	 */
+	public function listServers()
+	{
+            $response = $this->_performRequest(self::OP_SERVERS);
+ 	
+            if ($response->isSuccessful()) {
+		$xml = $this->_parseResponse($response);
+		$xmlServices = null;
+			
+                if (!$xml->Server) {
+                    return array();
+		}
+		if (count($xml->Server) > 1) {
+    		    $xmlServices = $xml->Server;
+    		} else {
+    		    $xmlServices = array($xml->Server);
+    		}
+    		
+		$services = array();
+		if (!is_null($xmlServices)) {				
+				
+                    for ($i = 0; $i < count($xmlServices); $i++) {
+                        $services[] = new Zend_Service_SqlAzure_Management_ServerInstance(
+                                	    (string)$xmlServices[$i]->Name,
+					    (string)$xmlServices[$i]->AdministratorLogin,
+					    (string)$xmlServices[$i]->Location
+					);
+                    }
+		}
+		return $services;
+            } else {
+		require_once 'Zend/Service/SqlAzure/Management/Exception.php';
+		throw new Zend_Service_SqlAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
+            }
+	}
+	
+	/**
+	 * The Drop Server operation drops a SQL Azure server from a subscription.
+	 * 
+	 * @param string $serverName Server to drop.
+	 * @throws Zend_Service_SqlAzure_Management_Exception
+	 */
+	public function dropServer($serverName)
+	{
+            if ($serverName == '' || is_null($serverName)) {
+                require_once 'Zend/Service/SqlAzure/Management/Exception.php';
+                throw new Zend_Service_SqlAzure_Management_Exception('Server name should be specified.');
+            }
+    	
+            $response = $this->_performRequest(self::OP_SERVERS . '/' . $serverName, '', Zend_Http_Client::DELETE);
+
+            if (!$response->isSuccessful()) {
+		require_once 'Zend/Service/SqlAzure/Management/Exception.php';
+		throw new Zend_Service_SqlAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
+            }	
+	}
+	
+	/**
+	 * The Set Server Administrator Password operation sets the administrative password of a SQL Azure server for a subscription.
+	 * 
+	 * @param string $serverName Server to set password for.
+	 * @param string $administratorPassword Administrator password.
+	 * @throws Zend_Service_SqlAzure_Management_Exception
+	 */
+	public function setAdministratorPassword($serverName, $administratorPassword)
+	{
+            if ($serverName == '' || is_null($serverName)) {
+		require_once 'Zend/Service/SqlAzure/Management/Exception.php';
+    		throw new Zend_Service_SqlAzure_Management_Exception('Server name should be specified.');
+            }
+            if ($administratorPassword == '' || is_null($administratorPassword)) {
+                require_once 'Zend/Service/SqlAzure/Management/Exception.php';
+    		throw new Zend_Service_SqlAzure_Management_Exception('Administrator password should be specified.');
+            }
+    	
+            $response = $this->_performRequest(self::OP_SERVERS . '/' . $serverName, '?op=ResetPassword',
+    		Zend_Http_Client::POST,
+    		array('Content-Type' => 'application/xml; charset=utf-8'),
+    		'<AdministratorLoginPassword xmlns="http://schemas.microsoft.com/sqlazure/2010/12/">' . $administratorPassword . '</AdministratorLoginPassword>');
+    		
+            if (!$response->isSuccessful()) {
+		require_once 'Zend/Service/SqlAzure/Management/Exception.php';
+		throw new Zend_Service_SqlAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
+            }	
+	}
+	
+	/**
+	 * The Set Server Firewall Rule operation updates an existing firewall rule or adds a new firewall rule for a SQL Azure server that belongs to a subscription.
+	 * 
+	 * @param string $serverName Server name.
+	 * @param string $ruleName Firewall rule name.
+	 * @param string $startIpAddress Start IP address.
+	 * @param string $endIpAddress End IP address.
+	 * @return Zend_Service_SqlAzure_Management_FirewallRuleInstance
+	 * @throws Zend_Service_SqlAzure_Management_Exception
+	 */
+	public function createFirewallRule($serverName, $ruleName, $startIpAddress, $endIpAddress)
+	{
+            if ($serverName == '' || is_null($serverName)) {
+                require_once 'Zend/Service/SqlAzure/Management/Exception.php';
+                throw new Zend_Service_SqlAzure_Management_Exception('Server name should be specified.');
+            }
+            if ($ruleName == '' || is_null($ruleName)) {
+                require_once 'Zend/Service/SqlAzure/Management/Exception.php';
+                throw new Zend_Service_SqlAzure_Management_Exception('Rule name should be specified.');
+            }
+            if ($startIpAddress == '' || is_null($startIpAddress) || !filter_var($startIpAddress, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
+                require_once 'Zend/Service/SqlAzure/Management/Exception.php';
+                throw new Zend_Service_SqlAzure_Management_Exception('Start IP address should be specified.');
+            }
+            if ($endIpAddress == '' || is_null($endIpAddress) || !filter_var($endIpAddress, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
+                require_once 'Zend/Service/SqlAzure/Management/Exception.php';
+                throw new Zend_Service_SqlAzure_Management_Exception('End IP address should be specified.');
+            }
+    	
+            $response = $this->_performRequest(self::OP_SERVERS . '/' . $serverName . '/' . self::OP_FIREWALLRULES . '/' . $ruleName, '',
+    		Zend_Http_Client::PUT,
+    		array('Content-Type' => 'application/xml; charset=utf-8'),
+    		'<FirewallRule xmlns="http://schemas.microsoft.com/sqlazure/2010/12/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://schemas.microsoft.com/sqlazure/2010/12/ FirewallRule.xsd"><StartIpAddress>' . $startIpAddress . '</StartIpAddress><EndIpAddress>' . $endIpAddress . '</EndIpAddress></FirewallRule>');
+
+            if ($response->isSuccessful()) {
+		
+    		return new Zend_Service_SqlAzure_Management_FirewallRuleInstance(
+    			$ruleName,
+    			$startIpAddress,
+    			$endIpAddress
+    		);
+            } else {
+		require_once 'Zend/Service/SqlAzure/Management/Exception.php';
+		throw new Zend_Service_SqlAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
+            }
+	}
+	
+	/**
+	 * The Get Server Firewall Rules operation retrieves a list of all the firewall rules for a SQL Azure server that belongs to a subscription.
+	 * 
+	 * @param string $serverName Server name.
+	 * @return Array of Zend_Service_SqlAzure_Management_FirewallRuleInstance.
+	 * @throws Zend_Service_SqlAzure_Management_Exception
+	 */
+	public function listFirewallRules($serverName)
+	{
+            if ($serverName == '' || is_null($serverName)) {
+		require_once 'Zend/Service/SqlAzure/Management/Exception.php';
+                throw new Zend_Service_SqlAzure_Management_Exception('Server name should be specified.');
+            }
+    	
+	    $response = $this->_performRequest(self::OP_SERVERS . '/' . $serverName . '/' . self::OP_FIREWALLRULES);
+ 	
+            if ($response->isSuccessful()) {
+		$xml = $this->_parseResponse($response);
+		$xmlServices = null;
+			
+    		if (!$xml->FirewallRule) {
+                    return array();
+		}
+		if (count($xml->FirewallRule) > 1) {
+    		    $xmlServices = $xml->FirewallRule;
+    		} else {
+    		    $xmlServices = array($xml->FirewallRule);
+    		}
+    		
+		$services = array();
+		if (!is_null($xmlServices)) {				
+                    
+                    for ($i = 0; $i < count($xmlServices); $i++) {
+                        $services[] = new Zend_Service_SqlAzure_Management_FirewallRuleInstance(
+					    (string)$xmlServices[$i]->Name,
+					    (string)$xmlServices[$i]->StartIpAddress,
+					    (string)$xmlServices[$i]->EndIpAddress
+					);
+                    }
+		}
+		return $services;
+            } else {
+		require_once 'Zend/Service/SqlAzure/Management/Exception.php';
+		throw new Zend_Service_SqlAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
+            }		
+	}
+	
+	/**
+	 * The Delete Server Firewall Rule operation deletes a firewall rule from a SQL Azure server that belongs to a subscription.
+	 * 
+	 * @param string $serverName Server name.
+	 * @param string $ruleName Rule name.
+	 * @throws Zend_Service_SqlAzure_Management_Exception
+	 */
+	public function deleteFirewallRule($serverName, $ruleName)
+	{
+		if ($serverName == '' || is_null($serverName)) {
+			require_once 'Zend/Service/SqlAzure/Management/Exception.php';
+    		throw new Zend_Service_SqlAzure_Management_Exception('Server name should be specified.');
+    	}
+		if ($ruleName == '' || is_null($ruleName)) {
+			require_once 'Zend/Service/SqlAzure/Management/Exception.php';
+    		throw new Zend_Service_SqlAzure_Management_Exception('Rule name should be specified.');
+    	}
+    	
+        $response = $this->_performRequest(self::OP_SERVERS . '/' . $serverName . '/' . self::OP_FIREWALLRULES . '/' . $ruleName, '',
+    		Zend_Http_Client::DELETE);
+
+    	if (!$response->isSuccessful()) {
+			require_once 'Zend/Service/SqlAzure/Management/Exception.php';
+			throw new Zend_Service_SqlAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
+		}
+	}
+	
+	/**
+	 * Creates a firewall rule for Microsoft Services. This is required if access to SQL Azure is required from other services like Windows Azure.
+	 * 
+	 * @param string $serverName Server name.
+	 * @param boolean $allowAccess Allow access from other Microsoft Services?
+	 * @throws Zend_Service_SqlAzure_Management_Exception
+	 */
+	public function createFirewallRuleForMicrosoftServices($serverName, $allowAccess)
+	{
+		if ($allowAccess) {
+			$this->createFirewallRule($serverName, 'MicrosoftServices', '0.0.0.0', '0.0.0.0');
+		} else {
+			$this->deleteFirewallRule($serverName, 'MicrosoftServices');
+		}
+	}
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/SqlAzure/Management/Exception.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,35 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure
+ * @subpackage Management
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+ require_once 'Zend/Service/SqlAzure/Exception.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Service_SqlAzure
+ * @subpackage Management
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Service_SqlAzure_Management_Exception
+	extends Zend_Service_SqlAzure_Exception
+{
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/SqlAzure/Management/FirewallRuleInstance.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,57 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure
+ * @subpackage Management
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/**
+ * @see Zend_Service_SqlAzure_Management_ServiceEntityAbstract
+ */
+require_once 'Zend/Service/SqlAzure/Management/ServiceEntityAbstract.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Service_SqlAzure
+ * @subpackage Management
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * 
+ * @property string $Name               The name of the firewall rule.
+ * @property string $StartIpAddress     The start IP address.
+ * @property string $EndIpAddress       The end IP address.
+ */
+class Zend_Service_SqlAzure_Management_FirewallRuleInstance
+	extends Zend_Service_SqlAzure_Management_ServiceEntityAbstract
+{    
+    /**
+     * Constructor
+     * 
+     * @param string $name               The name of the firewall rule.
+     * @param string $startIpAddress     The start IP address.
+     * @param string $endIpAddress       The end IP address.
+	 */
+    public function __construct($name, $startIpAddress, $endIpAddress) 
+    {	        
+        $this->_data = array(
+            'name'               => $name,
+            'startipaddress'     => $startIpAddress,
+            'endipaddress'       => $endIpAddress       
+        );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/SqlAzure/Management/ServerInstance.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,59 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure
+ * @subpackage Management
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/**
+ * @see Zend_Service_SqlAzure_Management_ServiceEntityAbstract
+ */
+require_once 'Zend/Service/SqlAzure/Management/ServiceEntityAbstract.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Service_SqlAzure
+ * @subpackage Management
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * 
+ * @property string $Name               The name of the server.
+ * @property string $DnsName            The DNS name of the server.
+ * @property string $AdministratorLogin The administrator login.
+ * @property string $Location           The location of the server in Windows Azure.
+ */
+class Zend_Service_SqlAzure_Management_ServerInstance
+	extends Zend_Service_SqlAzure_Management_ServiceEntityAbstract
+{    
+    /**
+     * Constructor
+     * 
+     * @param string $name               The name of the server.
+     * @param string $administratorLogin The administrator login.
+     * @param string $location           The location of the server in Windows Azure.
+	 */
+    public function __construct($name, $administratorLogin, $location) 
+    {	        
+        $this->_data = array(
+            'name'               => $name,
+            'dnsname'            => $name . '.database.windows.net',
+            'administratorlogin' => $administratorLogin,
+            'location'           => $location       
+        );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/SqlAzure/Management/ServiceEntityAbstract.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,67 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure
+ * @subpackage Management
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+
+/**
+ * @category   Zend
+ * @package    Zend_Service_SqlAzure
+ * @subpackage Management
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+abstract class Zend_Service_SqlAzure_Management_ServiceEntityAbstract
+{
+    /**
+     * Data
+     * 
+     * @var array
+     */
+    protected $_data = null;
+    
+    /**
+     * Magic overload for setting properties
+     * 
+     * @param string $name     Name of the property
+     * @param string $value    Value to set
+     */
+    public function __set($name, $value) {
+        if (array_key_exists(strtolower($name), $this->_data)) {
+            $this->_data[strtolower($name)] = $value;
+            return;
+        }
+	require_once 'Zend/Service/SqlAzure/Management/Exception.php';
+        throw new Zend_Service_SqlAzure_Management_Exception("Unknown property: " . $name);
+    }
+
+    /**
+     * Magic overload for getting properties
+     * 
+     * @param string $name     Name of the property
+     */
+    public function __get($name) {
+        if (array_key_exists(strtolower($name), $this->_data)) {
+            return $this->_data[strtolower($name)];
+        }
+	require_once 'Zend/Service/SqlAzure/Management/Exception.php';
+        throw new Zend_Service_SqlAzure_Management_Exception("Unknown property: " . $name);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/Twitter/Response.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,179 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service
+ * @subpackage Twitter
+ * @copyright  Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/**
+ * @see Zend_Http_Response
+ */
+require_once 'Zend/Http/Response.php';
+
+/**
+ * @see Zend_Json
+ */
+require_once 'Zend/Json.php';
+
+/**
+ * Representation of a response from Twitter.
+ *
+ * Provides:
+ *
+ * - method for testing if we have a successful call
+ * - method for retrieving errors, if any
+ * - method for retrieving the raw JSON
+ * - method for retrieving the decoded response
+ * - proxying to elements of the decoded response via property overloading
+ *
+ * @category   Zend
+ * @package    Zend_Service
+ * @subpackage Twitter
+ * @copyright  Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Service_Twitter_Response
+{
+    /**
+     * @var Zend_Http_Response
+     */
+    protected $httpResponse;
+
+    /**
+     * @var array|stdClass
+     */
+    protected $jsonBody;
+
+    /**
+     * @var string
+     */
+    protected $rawBody;
+
+    /**
+     * Constructor
+     *
+     * Assigns the HTTP response to a property, as well as the body
+     * representation. It then attempts to decode the body as JSON.
+     *
+     * @param  Zend_Http_Response $httpResponse
+     * @throws Zend_Service_Twitter_Exception if unable to decode JSON response
+     */
+    public function __construct(Zend_Http_Response $httpResponse)
+    {
+        $this->httpResponse = $httpResponse;
+        $this->rawBody      = $httpResponse->getBody();
+        try {
+            $jsonBody = Zend_Json::decode($this->rawBody, Zend_Json::TYPE_OBJECT);
+            $this->jsonBody = $jsonBody;
+        } catch (Zend_Json_Exception $e) {
+            require_once 'Zend/Service/Twitter/Exception.php';
+            throw new Zend_Service_Twitter_Exception(sprintf(
+                'Unable to decode response from twitter: %s',
+                $e->getMessage()
+            ), 0, $e);
+        }
+    }
+
+    /**
+     * Property overloading to JSON elements
+     *
+     * If a named property exists within the JSON response returned,
+     * proxies to it. Otherwise, returns null.
+     *
+     * @param  string $name
+     * @return mixed
+     */
+    public function __get($name)
+    {
+        if (null === $this->jsonBody) {
+            return null;
+        }
+        if (!isset($this->jsonBody->{$name})) {
+            return null;
+        }
+        return $this->jsonBody->{$name};
+    }
+
+    /**
+     * Was the request successful?
+     *
+     * @return bool
+     */
+    public function isSuccess()
+    {
+        return $this->httpResponse->isSuccessful();
+    }
+
+    /**
+     * Did an error occur in the request?
+     *
+     * @return bool
+     */
+    public function isError()
+    {
+        return !$this->httpResponse->isSuccessful();
+    }
+
+    /**
+     * Retrieve the errors.
+     *
+     * Twitter _should_ return a standard error object, which contains an
+     * "errors" property pointing to an array of errors. This method will
+     * return that array if present, and raise an exception if not detected.
+     *
+     * If the response was successful, an empty array is returned.
+     *
+     * @return array
+     * @throws Exception\DomainException if unable to detect structure of error response
+     */
+    public function getErrors()
+    {
+        if (!$this->isError()) {
+            return array();
+        }
+        if (null === $this->jsonBody
+            || !isset($this->jsonBody->errors)
+        ) {
+            require_once 'Zend/Service/Twitter/Exception.php';
+            throw new Zend_Service_Twitter_Exception(
+                'Either no JSON response received, or JSON error response is malformed; cannot return errors'
+            );
+        }
+        return $this->jsonBody->errors;
+    }
+
+    /**
+     * Retrieve the raw response body
+     *
+     * @return string
+     */
+    public function getRawResponse()
+    {
+        return $this->rawBody;
+    }
+
+    /**
+     * Retun the decoded response body
+     *
+     * @return array|stdClass
+     */
+    public function toValue()
+    {
+        return $this->jsonBody;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/WindowsAzure/CommandLine/Certificate.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,170 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service_Console
+ * @subpackage Exception
+ * @version    $Id$
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+
+/**
+ * Certificate commands
+ * 
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure_CommandLine
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * 
+ * @command-handler certificate
+ * @command-handler-description Windows Azure Certificate commands
+ * @command-handler-header Windows Azure SDK for PHP
+ * @command-handler-header Copyright (c) 2009 - 2011, RealDolmen (http://www.realdolmen.com)
+ * @command-handler-footer Note: Parameters that are common across all commands can be stored 
+ * @command-handler-footer in two dedicated environment variables.
+ * @command-handler-footer - SubscriptionId: The Windows Azure Subscription Id to operate on.
+ * @command-handler-footer - Certificate The Windows Azure .cer Management Certificate.
+ * @command-handler-footer 
+ * @command-handler-footer All commands support the --ConfigurationFile or -F parameter.
+ * @command-handler-footer The parameter file is a simple INI file carrying one parameter
+ * @command-handler-footer value per line. It accepts the same parameters as one can
+ * @command-handler-footer use from the command line command.
+ */
+class Zend_Service_WindowsAzure_CommandLine_Certificate
+	extends Zend_Service_Console_Command
+{	
+	/**
+	 * List certificates for a specified hosted service in a specified subscription.
+	 * 
+	 * @command-name List
+	 * @command-description List certificates for a specified hosted service in a specified subscription.
+	 * @command-parameter-for $subscriptionId Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --SubscriptionId|-sid Required. This is the Windows Azure Subscription Id to operate on.
+	 * @command-parameter-for $certificate Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Certificate|-cert Required. This is the .pem certificate that user has uploaded to Windows Azure subscription as Management Certificate.
+	 * @command-parameter-for $certificatePassphrase Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Prompt --Passphrase|-p Required. The certificate passphrase. If not specified, a prompt will be displayed.
+	 * @command-parameter-for $serviceName Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --ServiceName|-sn Required. The name of the hosted service.
+	 * @command-example List certificates for service name "phptest":
+	 * @command-example List -sid:"<your_subscription_id>" -cert:"mycert.pem" -sn:"phptest"
+	 */
+	public function listCertificatesCommand($subscriptionId, $certificate, $certificatePassphrase, $serviceName)
+	{
+		$client = new Zend_Service_WindowsAzure_Management_Client($subscriptionId, $certificate, $certificatePassphrase);
+		$result = $client->listCertificates($serviceName);
+
+		if (count($result) == 0) {
+			echo 'No data to display.';
+		}
+		foreach ($result as $object) {
+			$this->_displayObjectInformation($object, array('Thumbprint', 'CertificateUrl', 'ThumbprintAlgorithm'));
+		}
+	}
+	
+	/**
+	 * Add a certificate for a specified hosted service in a specified subscription.
+	 * 
+	 * @command-name Add
+	 * @command-description Add a certificate for a specified hosted service in a specified subscription.
+	 * @command-parameter-for $subscriptionId Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --SubscriptionId|-sid Required. This is the Windows Azure Subscription Id to operate on.
+	 * @command-parameter-for $certificate Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Certificate|-cert Required. This is the .pem certificate that user has uploaded to Windows Azure subscription as Management Certificate.
+	 * @command-parameter-for $certificatePassphrase Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Prompt --Passphrase|-p Required. The certificate passphrase. If not specified, a prompt will be displayed.
+	 * @command-parameter-for $serviceName Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --ServiceName|-sn Required. The name of the hosted service.
+	 * @command-parameter-for $certificateLocation Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --CertificateLocation Required. Path to the .pfx certificate to be added.
+	 * @command-parameter-for $certificatePassword Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Prompt --CertificatePassword Required. The password for the certificate that will be added.
+	 * @command-parameter-for $waitForOperation Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --WaitFor|-w Optional. Wait for the operation to complete?
+	 * @command-example Add certificates for service name "phptest":
+	 * @command-example Add -sid:"<your_subscription_id>" -cert:"mycert.pem" -sn:"phptest" --CertificateLocation:"cert.pfx" --CertificatePassword:"certpassword"
+	 */
+	public function addCertificateCommand($subscriptionId, $certificate, $certificatePassphrase, $serviceName, $certificateLocation, $certificatePassword, $waitForOperation = false)
+	{
+		$client = new Zend_Service_WindowsAzure_Management_Client($subscriptionId, $certificate, $certificatePassphrase);
+		$client->addCertificate($serviceName, $certificateLocation, $certificatePassword, 'pfx');
+		if ($waitForOperation) {
+			$client->waitForOperation();
+		}
+		echo $client->getLastRequestId();
+	}
+	
+	/**
+	 * Gets a certificate from a specified hosted service in a specified subscription.
+	 * 
+	 * @command-name Get
+	 * @command-description Gets a certificate from a specified hosted service in a specified subscription.
+	 * @command-parameter-for $subscriptionId Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --SubscriptionId|-sid Required. This is the Windows Azure Subscription Id to operate on.
+	 * @command-parameter-for $certificate Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Certificate|-cert Required. This is the .pem certificate that user has uploaded to Windows Azure subscription as Management Certificate.
+	 * @command-parameter-for $certificatePassphrase Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Prompt --Passphrase|-p Required. The certificate passphrase. If not specified, a prompt will be displayed.
+	 * @command-parameter-for $serviceName Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --ServiceName|-sn Required. The name of the hosted service.
+	 * @command-parameter-for $thumbprint Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --CertificateThumbprint Required. The certificate thumbprint for which to retrieve the certificate.
+	 * @command-parameter-for $algorithm Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --CertificateAlgorithm Required. The certificate's algorithm.
+	 * @command-example Get certificate for service name "phptest":
+	 * @command-example Get -sid:"<your_subscription_id>" -cert:"mycert.pem" -sn:"phptest" --CertificateThumbprint:"<thumbprint>" --CertificateAlgorithm:"sha1"
+	 */
+	public function getCertificateCommand($subscriptionId, $certificate, $certificatePassphrase, $serviceName, $thumbprint, $algorithm = "sha1")
+	{
+		$client = new Zend_Service_WindowsAzure_Management_Client($subscriptionId, $certificate, $certificatePassphrase);
+		$result = $client->getCertificate($serviceName, $algorithm, $thumbprint);
+
+		$this->_displayObjectInformation($result, array('Thumbprint', 'CertificateUrl', 'ThumbprintAlgorithm'));
+	}
+	
+	/**
+	 * Gets a certificate property from a specified hosted service in a specified subscription.
+	 * 
+	 * @command-name GetProperty
+	 * @command-description Gets a certificate property from a specified hosted service in a specified subscription.
+	 * @command-parameter-for $subscriptionId Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --SubscriptionId|-sid Required. This is the Windows Azure Subscription Id to operate on.
+	 * @command-parameter-for $certificate Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Certificate|-cert Required. This is the .pem certificate that user has uploaded to Windows Azure subscription as Management Certificate.
+	 * @command-parameter-for $certificatePassphrase Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Prompt --Passphrase|-p Required. The certificate passphrase. If not specified, a prompt will be displayed.
+	 * @command-parameter-for $serviceName Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --ServiceName|-sn Required. The name of the hosted service.
+	 * @command-parameter-for $thumbprint Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --CertificateThumbprint Required. The certificate thumbprint for which to retrieve the certificate.
+	 * @command-parameter-for $algorithm Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --CertificateAlgorithm Required. The certificate's algorithm.
+	 * @command-parameter-for $property Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --Property|-prop Required. The property to retrieve for the certificate.
+	 * @command-example Get certificate for service name "phptest":
+	 * @command-example Get -sid:"<your_subscription_id>" -cert:"mycert.pem" -sn:"phptest" --CertificateThumbprint:"<thumbprint>" --CertificateAlgorithm:"sha1"
+	 */
+	public function getCertificatePropertyCommand($subscriptionId, $certificate, $certificatePassphrase, $serviceName, $thumbprint, $algorithm = "sha1", $property)
+	{
+		$client = new Zend_Service_WindowsAzure_Management_Client($subscriptionId, $certificate, $certificatePassphrase);
+		$result = $client->getCertificate($serviceName, $algorithm, $thumbprint);
+
+		printf("%s\r\n", $result->$property);
+	}
+	
+	/**
+	 * Deletes a certificate from a specified hosted service in a specified subscription.
+	 * 
+	 * @command-name Delete
+	 * @command-description Deletes a certificate from a specified hosted service in a specified subscription.
+	 * @command-parameter-for $subscriptionId Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --SubscriptionId|-sid Required. This is the Windows Azure Subscription Id to operate on.
+	 * @command-parameter-for $certificate Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Certificate|-cert Required. This is the .pem certificate that user has uploaded to Windows Azure subscription as Management Certificate.
+	 * @command-parameter-for $certificatePassphrase Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Prompt --Passphrase|-p Required. The certificate passphrase. If not specified, a prompt will be displayed.
+	 * @command-parameter-for $serviceName Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --ServiceName|-sn Required. The name of the hosted service.
+	 * @command-parameter-for $thumbprint Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --CertificateThumbprint Required. The certificate thumbprint for which to retrieve the certificate.
+	 * @command-parameter-for $algorithm Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --CertificateAlgorithm Required. The certificate's algorithm.
+	 * @command-parameter-for $waitForOperation Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --WaitFor|-w Optional. Wait for the operation to complete?
+	 * @command-example Get certificate for service name "phptest":
+	 * @command-example Get -sid:"<your_subscription_id>" -cert:"mycert.pem" -sn:"phptest" --CertificateThumbprint:"<thumbprint>" --CertificateAlgorithm:"sha1"
+	 */
+	public function deleteCertificateCommand($subscriptionId, $certificate, $certificatePassphrase, $serviceName, $thumbprint, $algorithm = "sha1", $waitForOperation = false)
+	{
+		$client = new Zend_Service_WindowsAzure_Management_Client($subscriptionId, $certificate, $certificatePassphrase);
+		$client->deleteCertificate($serviceName, $algorithm, $thumbprint);
+		if ($waitForOperation) {
+			$client->waitForOperation();
+		}
+		echo $client->getLastRequestId();
+	}
+}
+
+Zend_Service_Console_Command::bootstrap($_SERVER['argv']);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/WindowsAzure/CommandLine/Deployment.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,580 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service_Console
+ * @subpackage Exception
+ * @version    $Id$
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+/**
+ * @see Zend_Service_Console_Command
+ */
+require_once 'Zend/Service/Console/Command.php';
+
+/**
+ * Deployment commands
+ * 
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure_CommandLine
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * 
+ * @command-handler deployment
+ * @command-handler-description Windows Azure Deployment commands
+ * @command-handler-header Windows Azure SDK for PHP
+ * @command-handler-header Copyright (c) 2009 - 2011, RealDolmen (http://www.realdolmen.com)
+ * @command-handler-footer Note: Parameters that are common across all commands can be stored 
+ * @command-handler-footer in two dedicated environment variables.
+ * @command-handler-footer - SubscriptionId: The Windows Azure Subscription Id to operate on.
+ * @command-handler-footer - Certificate The Windows Azure .cer Management Certificate.
+ * @command-handler-footer 
+ * @command-handler-footer All commands support the --ConfigurationFile or -F parameter.
+ * @command-handler-footer The parameter file is a simple INI file carrying one parameter
+ * @command-handler-footer value per line. It accepts the same parameters as one can
+ * @command-handler-footer use from the command line command.
+ */
+class Zend_Service_WindowsAzure_CommandLine_Deployment
+	extends Zend_Service_Console_Command
+{	
+	/**
+	 * Creates a deployment from a remote package file and service configuration.
+	 * 
+	 * @command-name CreateFromStorage
+	 * @command-description Creates a deployment from a remote package file and service configuration.
+	 * @command-parameter-for $subscriptionId Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --SubscriptionId|-sid Required. This is the Windows Azure Subscription Id to operate on.
+	 * @command-parameter-for $certificate Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Certificate|-cert Required. This is the .pem certificate that user has uploaded to Windows Azure subscription as Management Certificate.
+	 * @command-parameter-for $certificatePassphrase Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Prompt --Passphrase|-p Required. The certificate passphrase. If not specified, a prompt will be displayed.
+	 * @command-parameter-for $serviceName Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Name Required. The hosted service account name to operate on.
+	 * @command-parameter-for $deploymentName Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --DeploymentName Required. The name for the deployment.
+	 * @command-parameter-for $label Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --Label Required. The label for the deployment.
+	 * @command-parameter-for $staging Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --Staging Host the service in the staging slot.
+	 * @command-parameter-for $production Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --Production Host the service in the staging slot.
+	 * @command-parameter-for $packageUrl Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --PackageUrl Required. The remote location of the .cspkg file.
+	 * @command-parameter-for $serviceConfigurationLocation Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --ServiceConfigLocation Required. The location of the .cspkg file.
+	 * @command-parameter-for $startImmediately Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --StartImmediately Optional. Start the deployment after creation.
+	 * @command-parameter-for $warningsAsErrors Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --WarningsAsErrors Optional. Treat warnings as errors.
+	 * @command-parameter-for $waitForOperation Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --WaitFor|-w Optional. Wait for the operation to complete?
+	 * @command-example Create a deployment from a remote .cspkg:
+	 * @command-example CreateFromStorage -sid:"<your_subscription_id>" -cert:"mycert.pem" --Name:"hostedservicename" --DeploymentName:"deploymentname"
+	 * @command-example --Label:"deploymentlabel" --Production
+	 * @command-example --PackageUrl:"http://acct.blob.core.windows.net/pkgs/service.cspkg"
+	 * @command-example --ServiceConfigLocation:".\ServiceConfiguration.cscfg" --StartImmediately --WaitFor
+	 */
+	public function createFromStorageCommand($subscriptionId, $certificate, $certificatePassphrase, $serviceName, $deploymentName, $label, $staging = false, $production = false, $packageUrl, $serviceConfigurationLocation, $startImmediately = true, $warningsAsErrors = false, $waitForOperation = false)
+	{
+		$deploymentSlot = 'staging';
+		if (!$staging && !$production) {
+			require_once 'Zend/Service/Console/Exception.php';
+			throw new Zend_Service_Console_Exception('Either --Staging or --Production should be specified.');
+		}
+		if ($production) {
+			$deploymentSlot = 'production';
+		}
+
+		$client->createDeployment($serviceName, $deploymentSlot, $deploymentName, $label, $packageUrl, $serviceConfigurationLocation, $startImmediately, $warningsAsErrors);
+
+		if ($waitForOperation) {
+			$client->waitForOperation();
+		}
+		echo $client->getLastRequestId();
+	}
+	
+	/**
+	 * Creates a deployment from a local package file and service configuration.
+	 * 
+	 * @command-name CreateFromLocal
+	 * @command-description Creates a deployment from a local package file and service configuration.
+	 * @command-parameter-for $subscriptionId Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --SubscriptionId|-sid Required. This is the Windows Azure Subscription Id to operate on.
+	 * @command-parameter-for $certificate Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Certificate|-cert Required. This is the .pem certificate that user has uploaded to Windows Azure subscription as Management Certificate.
+	 * @command-parameter-for $certificatePassphrase Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Prompt --Passphrase|-p Required. The certificate passphrase. If not specified, a prompt will be displayed.
+	 * @command-parameter-for $serviceName Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Name Required. The hosted service account name to operate on.
+	 * @command-parameter-for $deploymentName Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --DeploymentName Required. The name for the deployment.
+	 * @command-parameter-for $label Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --Label Required. The label for the deployment.
+	 * @command-parameter-for $staging Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --Staging Host the service in the staging slot.
+	 * @command-parameter-for $production Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --Production Host the service in the staging slot.
+	 * @command-parameter-for $packageLocation Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --PackageLocation Required. The location of the .cspkg file.
+	 * @command-parameter-for $serviceConfigurationLocation Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --ServiceConfigLocation Required. The location of the .cspkg file.
+	 * @command-parameter-for $storageAccount Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --StorageAccount Required. Storage account to use when creating the deployment.
+	 * @command-parameter-for $startImmediately Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --StartImmediately Optional. Start the deployment after creation.
+	 * @command-parameter-for $warningsAsErrors Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --WarningsAsErrors Optional. Treat warnings as errors.
+	 * @command-parameter-for $waitForOperation Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --WaitFor|-w Optional. Wait for the operation to complete?
+	 * @command-example Create a deployment from a local .cspkg:
+	 * @command-example CreateFromLocal -sid:"<your_subscription_id>" -cert:"mycert.pem" --Name:"hostedservicename" --DeploymentName:"deploymentname"
+	 * @command-example --Label:"deploymentlabel" --Production --PackageLocation:".\service.cspkg"
+	 * @command-example --ServiceConfigLocation:".\ServiceConfiguration.cscfg" --StorageAccount:"mystorage"
+	 * @command-example --StartImmediately --WaitFor
+	 */
+	public function createFromLocalCommand($subscriptionId, $certificate, $certificatePassphrase, $serviceName, $deploymentName, $label, $staging = false, $production = false, $packageLocation, $serviceConfigurationLocation, $storageAccount, $startImmediately = true, $warningsAsErrors = false, $waitForOperation = false)
+	{
+		$deploymentSlot = 'staging';
+		if (!$staging && !$production) {
+			require_once 'Zend/Service/Console/Exception.php';
+			throw new Zend_Service_Console_Exception('Either --Staging or --Production should be specified.');
+		}
+		if ($production) {
+			$deploymentSlot = 'production';
+		}
+
+		$client = new Zend_Service_WindowsAzure_Management_Client($subscriptionId, $certificate, $certificatePassphrase);
+		$blobClient = $client->createBlobClientForService($storageAccount);
+		$blobClient->createContainerIfNotExists('phpazuredeployments');
+		$blobClient->putBlob('phpazuredeployments', basename($packageLocation), $packageLocation);
+		$package = $blobClient->getBlobInstance('phpazuredeployments', basename($packageLocation));
+		
+		$client->createDeployment($serviceName, $deploymentSlot, $deploymentName, $label, $package->Url, $serviceConfigurationLocation, $startImmediately, $warningsAsErrors);
+
+		$client->waitForOperation();
+		$blobClient->deleteBlob('phpazuredeployments', basename($packageLocation));
+		
+		if ($waitForOperation) {
+			$client->waitForOperation();
+		}
+		echo $client->getLastRequestId();
+	}
+	
+	/**
+	 * Get deployment properties.
+	 * 
+	 * @command-name GetProperties
+	 * @command-description Get deployment properties.
+	 * @command-parameter-for $subscriptionId Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --SubscriptionId|-sid Required. This is the Windows Azure Subscription Id to operate on.
+	 * @command-parameter-for $certificate Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Certificate|-cert Required. This is the .pem certificate that user has uploaded to Windows Azure subscription as Management Certificate.
+	 * @command-parameter-for $certificatePassphrase Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Prompt --Passphrase|-p Required. The certificate passphrase. If not specified, a prompt will be displayed.
+	 * @command-parameter-for $serviceName Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Name Required. The hosted service account name to operate on.
+	 * @command-parameter-for $deploymentSlot Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --BySlot Required if deployment name is omitted. The slot to retrieve property information for.
+	 * @command-parameter-for $deploymentName Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --ByName Required if deployment slot is omitted. The deployment name to retrieve property information for.
+	 * @command-example Get deployment properties for service "phptest" (production slot):
+	 * @command-example GetProperties -sid:"<your_subscription_id>" -cert:"mycert.pem" --Name:"servicename" --BySlot:"production"
+	 */
+	public function getPropertiesCommand($subscriptionId, $certificate, $certificatePassphrase, $serviceName, $deploymentSlot, $deploymentName)
+	{
+		$client = new Zend_Service_WindowsAzure_Management_Client($subscriptionId, $certificate, $certificatePassphrase);
+		
+		$result = null;
+		
+		if (!is_null($deploymentSlot) && $deploymentSlot != '') {
+			$deploymentSlot = strtolower($deploymentSlot);
+			
+			$result = $client->getDeploymentBySlot($serviceName, $deploymentSlot);
+		} else {
+			$result = $client->getDeploymentByDeploymentId($serviceName, $deploymentName);
+		}
+
+		$this->_displayObjectInformation($result, array('Name', 'DeploymentSlot', 'Label', 'Url', 'Status'));
+	}
+	
+	/**
+	 * Get hosted service account property.
+	 * 
+	 * @command-name GetProperty
+	 * @command-description Get deployment property.
+	 * @command-parameter-for $subscriptionId Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --SubscriptionId|-sid Required. This is the Windows Azure Subscription Id to operate on.
+	 * @command-parameter-for $certificate Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Certificate|-cert Required. This is the .pem certificate that user has uploaded to Windows Azure subscription as Management Certificate.
+	 * @command-parameter-for $certificatePassphrase Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Prompt --Passphrase|-p Required. The certificate passphrase. If not specified, a prompt will be displayed.
+	 * @command-parameter-for $serviceName Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Name Required. The hosted service account name to operate on.
+	 * @command-parameter-for $deploymentSlot Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --BySlot Required if deployment name is omitted. The slot to retrieve property information for.
+	 * @command-parameter-for $deploymentName Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --ByName Required if deployment slot is omitted. The deployment name to retrieve property information for.
+	 * @command-parameter-for $property Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --Property|-prop Required. The property to retrieve for the hosted service account.
+	 * @command-example Get deployment property "Name" for service "phptest" (production slot):
+	 * @command-example GetProperties -sid:"<your_subscription_id>" -cert:"mycert.pem"
+	 * @command-example --Name:"servicename" --BySlot:"production" --Property:"Name"
+	 */
+	public function getPropertyCommand($subscriptionId, $certificate, $certificatePassphrase, $serviceName, $deploymentSlot, $deploymentName, $property)
+	{
+		$client = new Zend_Service_WindowsAzure_Management_Client($subscriptionId, $certificate, $certificatePassphrase);
+		
+		$result = null;
+		
+		if (!is_null($deploymentSlot) && $deploymentSlot != '') {
+			$deploymentSlot = strtolower($deploymentSlot);
+			
+			$result = $client->getDeploymentBySlot($serviceName, $deploymentSlot);
+		} else {
+			$result = $client->getDeploymentByDeploymentId($serviceName, $deploymentName);
+		}
+
+		printf("%s\r\n", $result->$property);
+	}
+	
+	/**
+	 * Swap deployment slots (perform VIP swap).
+	 * 
+	 * @command-name Swap
+	 * @command-description Swap deployment slots (perform VIP swap).
+	 * @command-parameter-for $subscriptionId Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --SubscriptionId|-sid Required. This is the Windows Azure Subscription Id to operate on.
+	 * @command-parameter-for $certificate Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Certificate|-cert Required. This is the .pem certificate that user has uploaded to Windows Azure subscription as Management Certificate.
+	 * @command-parameter-for $certificatePassphrase Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Prompt --Passphrase|-p Required. The certificate passphrase. If not specified, a prompt will be displayed.
+	 * @command-parameter-for $serviceName Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Name Required. The hosted service account name to operate on.
+	 * @command-parameter-for $waitForOperation Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --WaitFor|-w Optional. Wait for the operation to complete?
+	 * @command-example Swap deployment slots:
+	 * @command-example Swap -sid:"<your_subscription_id>" -cert:"mycert.pem" --Name:"servicename"
+	 */
+	public function swapCommand($subscriptionId, $certificate, $certificatePassphrase, $serviceName, $waitForOperation = false)
+	{
+		$client = new Zend_Service_WindowsAzure_Management_Client($subscriptionId, $certificate, $certificatePassphrase);
+		
+		$productionDeploymentName = null;
+		try { $productionDeploymentName = $client->getDeploymentBySlot($serviceName, 'production')->Name; } catch (Exception $ex) {}
+		
+		$stagingDeploymentName = null;
+		try { $stagingDeploymentName = $client->getDeploymentBySlot($serviceName, 'staging')->Name; } catch (Exception $ex) {}
+		
+		if (is_null($productionDeploymentName)) {
+			$productionDeploymentName = $stagingDeploymentName;
+		}
+		if (is_null($stagingDeploymentName)) {
+			require_once 'Zend/Service/Console/Exception.php';
+			throw new Zend_Service_Console_Exception('Swapping deployment slots is only possible when both slots have an active deployment or when production slot is empty.');
+		}
+
+		$client->swapDeployment($serviceName, $productionDeploymentName, $stagingDeploymentName);
+		
+		if ($waitForOperation) {
+			$client->waitForOperation();
+		}
+		echo $client->getLastRequestId();
+	}
+	
+	/**
+	 * Deletes a deployment.
+	 * 
+	 * @command-name Delete
+	 * @command-description Deletes a deployment.
+	 * @command-parameter-for $subscriptionId Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --SubscriptionId|-sid Required. This is the Windows Azure Subscription Id to operate on.
+	 * @command-parameter-for $certificate Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Certificate|-cert Required. This is the .pem certificate that user has uploaded to Windows Azure subscription as Management Certificate.
+	 * @command-parameter-for $certificatePassphrase Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Prompt --Passphrase|-p Required. The certificate passphrase. If not specified, a prompt will be displayed.
+	 * @command-parameter-for $serviceName Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Name Required. The hosted service account name to operate on.
+	 * @command-parameter-for $deploymentSlot Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --BySlot Required if deployment name is omitted. The slot to retrieve property information for.
+	 * @command-parameter-for $deploymentName Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --ByName Required if deployment slot is omitted. The deployment name to retrieve property information for.
+	 * @command-parameter-for $waitForOperation Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --WaitFor|-w Optional. Wait for the operation to complete?
+	 * @command-example Delete a deployment:
+	 * @command-example Delete -sid:"<your_subscription_id>" -cert:"mycert.pem" --Name:"hostedservicename" --DeploymentName:"deploymentname"
+	 */
+	public function deleteCommand($subscriptionId, $certificate, $certificatePassphrase, $serviceName, $deploymentSlot, $deploymentName, $waitForOperation = false)
+	{
+		$client = new Zend_Service_WindowsAzure_Management_Client($subscriptionId, $certificate, $certificatePassphrase);
+
+		if (!is_null($deploymentSlot) && $deploymentSlot != '') {
+			$deploymentSlot = strtolower($deploymentSlot);
+			
+			$client->deleteDeploymentBySlot($serviceName, $deploymentSlot);
+		} else {
+			$client->deleteDeploymentByDeploymentId($serviceName, $deploymentName);
+		}
+		
+		if ($waitForOperation) {
+			$client->waitForOperation();
+		}
+		echo $client->getLastRequestId();
+	}
+	
+	/**
+	 * Updates a deployment's configuration.
+	 * 
+	 * @command-name UpdateConfig
+	 * @command-description Updates a deployment's configuration.
+	 * @command-parameter-for $subscriptionId Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --SubscriptionId|-sid Required. This is the Windows Azure Subscription Id to operate on.
+	 * @command-parameter-for $certificate Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Certificate|-cert Required. This is the .pem certificate that user has uploaded to Windows Azure subscription as Management Certificate.
+	 * @command-parameter-for $certificatePassphrase Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Prompt --Passphrase|-p Required. The certificate passphrase. If not specified, a prompt will be displayed.
+	 * @command-parameter-for $serviceName Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Name Required. The hosted service account name to operate on.
+	 * @command-parameter-for $deploymentSlot Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --BySlot Required if deployment name is omitted. The slot to retrieve property information for.
+	 * @command-parameter-for $deploymentName Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --ByName Required if deployment slot is omitted. The deployment name to retrieve property information for.
+	 * @command-parameter-for $serviceConfigurationLocation Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --ServiceConfigLocation Required. The location of the .cspkg file.
+	 * @command-parameter-for $waitForOperation Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --WaitFor|-w Optional. Wait for the operation to complete?
+	 * @command-example Update configuration:
+	 * @command-example UpdateConfig -sid:"<your_subscription_id>" -cert:"mycert.pem"
+	 * @command-example --Name:"hostedservicename" --ByName:"deploymentname"
+	 * @command-example --ServiceConfigLocation:".\ServiceConfiguration.cscfg"
+	 */
+	public function updateConfigurationCommand($subscriptionId, $certificate, $certificatePassphrase, $serviceName, $deploymentSlot, $deploymentName, $serviceConfigurationLocation, $waitForOperation = false)
+	{
+		$client = new Zend_Service_WindowsAzure_Management_Client($subscriptionId, $certificate, $certificatePassphrase);
+
+		if (!is_null($deploymentSlot) && $deploymentSlot != '') {
+			$deploymentSlot = strtolower($deploymentSlot);
+			
+			$client->configureDeploymentBySlot($serviceName, $deploymentSlot, $serviceConfigurationLocation);
+		} else {
+			$client->configureDeploymentByDeploymentId($serviceName, $deploymentName, $serviceConfigurationLocation);
+		}
+		
+		if ($waitForOperation) {
+			$client->waitForOperation();
+		}
+		echo $client->getLastRequestId();
+	}
+	
+	/**
+	 * Updates a deployment's status.
+	 * 
+	 * @command-name UpdateStatus
+	 * @command-description Updates a deployment's status.
+	 * @command-parameter-for $subscriptionId Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --SubscriptionId|-sid Required. This is the Windows Azure Subscription Id to operate on.
+	 * @command-parameter-for $certificate Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Certificate|-cert Required. This is the .pem certificate that user has uploaded to Windows Azure subscription as Management Certificate.
+	 * @command-parameter-for $certificatePassphrase Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Prompt --Passphrase|-p Required. The certificate passphrase. If not specified, a prompt will be displayed.
+	 * @command-parameter-for $serviceName Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Name Required. The hosted service account name to operate on.
+	 * @command-parameter-for $deploymentSlot Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --BySlot Required if deployment name is omitted. The slot to retrieve property information for.
+	 * @command-parameter-for $deploymentName Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --ByName Required if deployment slot is omitted. The deployment name to retrieve property information for.
+	 * @command-parameter-for $newStatus Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --Status Required. New status (Suspended|Running)
+	 * @command-parameter-for $waitForOperation Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --WaitFor|-w Optional. Wait for the operation to complete?
+	 * @command-example Suspend a deployment:
+	 * @command-example UpdateStatus -sid:"<your_subscription_id>" -cert:"mycert.pem"
+	 * @command-example --Name:"hostedservicename" --ByName:"deploymentname"
+	 * @command-example --Status:"Suspended"
+	 */
+	public function updateStatusCommand($subscriptionId, $certificate, $certificatePassphrase, $serviceName, $deploymentSlot, $deploymentName, $newStatus, $waitForOperation = false)
+	{
+		$client = new Zend_Service_WindowsAzure_Management_Client($subscriptionId, $certificate, $certificatePassphrase);
+
+		if (!is_null($deploymentSlot) && $deploymentSlot != '') {
+			$deploymentSlot = strtolower($deploymentSlot);
+			
+			$client->updateDeploymentStatusBySlot($serviceName, $deploymentSlot, $newStatus);
+		} else {
+			$client->updateDeploymentStatusByDeploymentId($serviceName, $deploymentName, $newStatus);
+		}
+		
+		if ($waitForOperation) {
+			$client->waitForOperation();
+		}
+		echo $client->getLastRequestId();
+	}
+	
+	/**
+	 * Updates the number of instances.
+	 * 
+	 * @command-name EditInstanceNumber
+	 * @command-description Updates the number of instances.
+	 * @command-parameter-for $subscriptionId Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --SubscriptionId|-sid Required. This is the Windows Azure Subscription Id to operate on.
+	 * @command-parameter-for $certificate Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Certificate|-cert Required. This is the .pem certificate that user has uploaded to Windows Azure subscription as Management Certificate.
+	 * @command-parameter-for $certificatePassphrase Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Prompt --Passphrase|-p Required. The certificate passphrase. If not specified, a prompt will be displayed.
+	 * @command-parameter-for $serviceName Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Name Required. The hosted service account name to operate on.
+	 * @command-parameter-for $deploymentSlot Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --BySlot Required if deployment name is omitted. The slot to retrieve property information for.
+	 * @command-parameter-for $deploymentName Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --ByName Required if deployment slot is omitted. The deployment name to retrieve property information for.
+	 * @command-parameter-for $roleName Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --RoleName|-r Required. Role name to update the number of instances for.
+	 * @command-parameter-for $newInstanceNumber Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --NewInstanceNumber|-i Required. New number of instances.
+	 * @command-parameter-for $waitForOperation Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --WaitFor|-w Optional. Wait for the operation to complete?
+	 * @command-example Suspend a deployment:
+	 * @command-example EditInstanceNumber -sid:"<your_subscription_id>" -cert:"mycert.pem"
+	 * @command-example --Name:"hostedservicename" --ByName:"deploymentname"
+	 * @command-example --NewInstanceNumber:"4"
+	 */
+	public function editInstanceNumberCommand($subscriptionId, $certificate, $certificatePassphrase, $serviceName, $deploymentSlot, $deploymentName, $roleName, $newInstanceNumber = 1, $waitForOperation = false)
+	{
+		$client = new Zend_Service_WindowsAzure_Management_Client($subscriptionId, $certificate, $certificatePassphrase);
+
+		if (!is_null($deploymentSlot) && $deploymentSlot != '') {
+			$deploymentSlot = strtolower($deploymentSlot);
+			
+			$client->setInstanceCountBySlot($serviceName, $deploymentSlot, $roleName, $newInstanceNumber);
+		} else {
+			$client->setInstanceCountByDeploymentId($serviceName, $deploymentName, $roleName, $newInstanceNumber);
+		}
+		
+		if ($waitForOperation) {
+			$client->waitForOperation();
+		}
+		echo $client->getLastRequestId();
+	}
+	
+	/**
+	 * Reboots a role instance.
+	 * 
+	 * @command-name RebootInstance
+	 * @command-description Reboots a role instance.
+	 * @command-parameter-for $subscriptionId Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --SubscriptionId|-sid Required. This is the Windows Azure Subscription Id to operate on.
+	 * @command-parameter-for $certificate Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Certificate|-cert Required. This is the .pem certificate that user has uploaded to Windows Azure subscription as Management Certificate.
+	 * @command-parameter-for $certificatePassphrase Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Prompt --Passphrase|-p Required. The certificate passphrase. If not specified, a prompt will be displayed.
+	 * @command-parameter-for $serviceName Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Name Required. The hosted service account name to operate on.
+	 * @command-parameter-for $deploymentSlot Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --BySlot Required if deployment name is omitted. The slot to retrieve property information for.
+	 * @command-parameter-for $deploymentName Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --ByName Required if deployment slot is omitted. The deployment name to retrieve property information for.
+	 * @command-parameter-for $instanceName Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --RoleInstanceName Required. The name of the role instance to work with.
+	 * @command-parameter-for $waitForOperation Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --WaitFor|-w Optional. Wait for the operation to complete?
+	 * @command-example Reboot a role instance:
+	 * @command-example RebootInstance -sid:"<your_subscription_id>" -cert:"mycert.pem"
+	 * @command-example --Name:"hostedservicename" --ByName:"deploymentname"
+	 * @command-example --RoleInstanceName:"PhpOnAzure.Web_IN_0"
+	 */
+	public function rebootInstanceCommand($subscriptionId, $certificate, $certificatePassphrase, $serviceName, $deploymentSlot, $deploymentName, $instanceName, $waitForOperation = false)
+	{
+		$client = new Zend_Service_WindowsAzure_Management_Client($subscriptionId, $certificate, $certificatePassphrase);
+
+		if (!is_null($deploymentSlot) && $deploymentSlot != '') {
+			$deploymentSlot = strtolower($deploymentSlot);
+			
+			$client->rebootRoleInstanceBySlot($serviceName, $deploymentSlot, $instanceName);
+		} else {
+			$client->rebootRoleInstanceByDeploymentId($serviceName, $deploymentName, $instanceName);
+		}
+		
+		if ($waitForOperation) {
+			$client->waitForOperation();
+		}
+		echo $client->getLastRequestId();
+	}
+	
+	/**
+	 * Reimages a role instance.
+	 * 
+	 * @command-name ReimageInstance
+	 * @command-description Reimages a role instance.
+	 * @command-parameter-for $subscriptionId Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --SubscriptionId|-sid Required. This is the Windows Azure Subscription Id to operate on.
+	 * @command-parameter-for $certificate Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Certificate|-cert Required. This is the .pem certificate that user has uploaded to Windows Azure subscription as Management Certificate.
+	 * @command-parameter-for $certificatePassphrase Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Prompt --Passphrase|-p Required. The certificate passphrase. If not specified, a prompt will be displayed.
+	 * @command-parameter-for $serviceName Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Name Required. The hosted service account name to operate on.
+	 * @command-parameter-for $deploymentSlot Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --BySlot Required if deployment name is omitted. The slot to retrieve property information for.
+	 * @command-parameter-for $deploymentName Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --ByName Required if deployment slot is omitted. The deployment name to retrieve property information for.
+	 * @command-parameter-for $instanceName Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --RoleInstanceName Required. The name of the role instance to work with.
+	 * @command-parameter-for $waitForOperation Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --WaitFor|-w Optional. Wait for the operation to complete?
+	 * @command-example Reimage a role instance:
+	 * @command-example ReimageInstance -sid:"<your_subscription_id>" -cert:"mycert.pem"
+	 * @command-example --Name:"hostedservicename" --ByName:"deploymentname"
+	 * @command-example --RoleInstanceName:"PhpOnAzure.Web_IN_0"
+	 */
+	public function reimageInstanceCommand($subscriptionId, $certificate, $certificatePassphrase, $serviceName, $deploymentSlot, $deploymentName, $instanceName, $waitForOperation = false)
+	{
+		$client = new Zend_Service_WindowsAzure_Management_Client($subscriptionId, $certificate, $certificatePassphrase);
+
+		if (!is_null($deploymentSlot) && $deploymentSlot != '') {
+			$deploymentSlot = strtolower($deploymentSlot);
+			
+			$client->reimageRoleInstanceBySlot($serviceName, $deploymentSlot, $instanceName);
+		} else {
+			$client->reimageRoleInstanceByDeploymentId($serviceName, $deploymentName, $instanceName);
+		}
+		
+		if ($waitForOperation) {
+			$client->waitForOperation();
+		}
+		echo $client->getLastRequestId();
+	}
+	
+	/**
+	 * Upgrades a deployment from a remote package file and service configuration.
+	 * 
+	 * @command-name UpgradeFromStorage
+	 * @command-description Upgrades a deployment from a remote package file and service configuration.
+	 * @command-parameter-for $subscriptionId Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --SubscriptionId|-sid Required. This is the Windows Azure Subscription Id to operate on.
+	 * @command-parameter-for $certificate Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Certificate|-cert Required. This is the .pem certificate that user has uploaded to Windows Azure subscription as Management Certificate.
+	 * @command-parameter-for $certificatePassphrase Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Prompt --Passphrase|-p Required. The certificate passphrase. If not specified, a prompt will be displayed.
+	 * @command-parameter-for $serviceName Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Name Required. The hosted service account name to operate on.
+	 * @command-parameter-for $deploymentSlot Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --BySlot Required if deployment name is omitted. The slot to retrieve property information for.
+	 * @command-parameter-for $deploymentName Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --ByName Required if deployment slot is omitted. The deployment name to retrieve property information for.
+	 * @command-parameter-for $label Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --Label Required. The label for the deployment.
+	 * @command-parameter-for $packageUrl Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --PackageUrl Required. The remote location of the .cspkg file.
+	 * @command-parameter-for $serviceConfigurationLocation Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --ServiceConfigLocation Required. The location of the .cspkg file.
+	 * @command-parameter-for $mode Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --Mode Required. Set to auto|manual.
+	 * @command-parameter-for $roleName Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --RoleName Optional. Role name to upgrade.
+	 * @command-parameter-for $waitForOperation Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --WaitFor|-w Optional. Wait for the operation to complete?
+	 */
+	public function upgradeFromStorageCommand($subscriptionId, $certificate, $certificatePassphrase, $serviceName, $deploymentSlot, $deploymentName, $label, $packageUrl, $serviceConfigurationLocation, $mode = 'auto', $roleName = null, $waitForOperation = false)
+	{		
+		$client = new Zend_Service_WindowsAzure_Management_Client($subscriptionId, $certificate, $certificatePassphrase);
+
+		if (!is_null($deploymentSlot) && $deploymentSlot != '') {
+			$deploymentSlot = strtolower($deploymentSlot);
+			
+			$client->upgradeDeploymentBySlot($serviceName, $deploymentSlot, $label, $packageUrl, $serviceConfigurationLocation, $mode, $roleName);
+		} else {
+			$client->upgradeDeploymentByDeploymentId($serviceName, $deploymentName, $label, $packageUrl, $serviceConfigurationLocation, $mode, $roleName);
+		}
+		
+		if ($waitForOperation) {
+			$client->waitForOperation();
+		}
+		echo $client->getLastRequestId();
+	}
+	
+	/**
+	 * Upgrades a deployment from a local package file and service configuration.
+	 * 
+	 * @command-name UpgradeFromLocal
+	 * @command-description Upgrades a deployment from a local package file and service configuration.
+	 * @command-parameter-for $subscriptionId Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --SubscriptionId|-sid Required. This is the Windows Azure Subscription Id to operate on.
+	 * @command-parameter-for $certificate Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Certificate|-cert Required. This is the .pem certificate that user has uploaded to Windows Azure subscription as Management Certificate.
+	 * @command-parameter-for $certificatePassphrase Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Prompt --Passphrase|-p Required. The certificate passphrase. If not specified, a prompt will be displayed.
+	 * @command-parameter-for $serviceName Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Name Required. The hosted service account name to operate on.
+	 * @command-parameter-for $deploymentSlot Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --BySlot Required if deployment name is omitted. The slot to retrieve property information for.
+	 * @command-parameter-for $deploymentName Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --ByName Required if deployment slot is omitted. The deployment name to retrieve property information for.
+	 * @command-parameter-for $label Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --Label Required. The label for the deployment.
+	 * @command-parameter-for $packageLocation Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --PackageLocation Required. The location of the .cspkg file.
+	 * @command-parameter-for $serviceConfigurationLocation Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --ServiceConfigLocation Required. The location of the .cspkg file.
+	 * @command-parameter-for $storageAccount Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --StorageAccount Required. Storage account to use when creating the deployment.
+	 * @command-parameter-for $mode Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --Mode Required. Set to auto|manual.
+	 * @command-parameter-for $roleName Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --RoleName Optional. Role name to upgrade.
+	 * @command-parameter-for $waitForOperation Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --WaitFor|-w Optional. Wait for the operation to complete?
+	 */
+	public function upgradeFromLocalCommand($subscriptionId, $certificate, $certificatePassphrase, $serviceName, $deploymentSlot, $deploymentName, $label, $packageLocation, $serviceConfigurationLocation, $storageAccount, $mode = 'auto', $roleName = null, $waitForOperation = false)
+	{
+		$client = new Zend_Service_WindowsAzure_Management_Client($subscriptionId, $certificate, $certificatePassphrase);
+		
+		$blobClient = $client->createBlobClientForService($storageAccount);
+		$blobClient->createContainerIfNotExists('phpazuredeployments');
+		$blobClient->putBlob('phpazuredeployments', basename($packageLocation), $packageLocation);
+		$package = $blobClient->getBlobInstance('phpazuredeployments', basename($packageLocation));
+		
+		if (!is_null($deploymentSlot) && $deploymentSlot != '') {
+			$deploymentSlot = strtolower($deploymentSlot);
+			
+			$client->upgradeDeploymentBySlot($serviceName, $deploymentSlot, $label, $package->Url, $serviceConfigurationLocation, $mode, $roleName);
+		} else {
+			$client->upgradeDeploymentByDeploymentId($serviceName, $deploymentName, $label, $package->Url, $serviceConfigurationLocation, $mode, $roleName);
+		}
+		
+		$client->waitForOperation();
+		$blobClient->deleteBlob('phpazuredeployments', basename($packageLocation));
+		
+		if ($waitForOperation) {
+			$client->waitForOperation();
+		}
+		echo $client->getLastRequestId();
+	}
+	
+	/**
+	 * Walks upgrade domains.
+	 * 
+	 * @command-name WalkUpgradeDomains
+	 * @command-description Walks upgrade domains.
+	 * @command-parameter-for $subscriptionId Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --SubscriptionId|-sid Required. This is the Windows Azure Subscription Id to operate on.
+	 * @command-parameter-for $certificate Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Certificate|-cert Required. This is the .pem certificate that user has uploaded to Windows Azure subscription as Management Certificate.
+	 * @command-parameter-for $certificatePassphrase Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Prompt --Passphrase|-p Required. The certificate passphrase. If not specified, a prompt will be displayed.
+	 * @command-parameter-for $serviceName Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Name Required. The hosted service account name to operate on.
+	 * @command-parameter-for $deploymentSlot Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --BySlot Required if deployment name is omitted. The slot to retrieve property information for.
+	 * @command-parameter-for $deploymentName Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --ByName Required if deployment slot is omitted. The deployment name to retrieve property information for.
+	 * @command-parameter-for $upgradeDomain Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --UpgradeDomain Required. The upgrade domain index.
+	 * @command-parameter-for $waitForOperation Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --WaitFor|-w Optional. Wait for the operation to complete?
+	 */
+	public function walkUpgradeDomainsCommand($subscriptionId, $certificate, $certificatePassphrase, $serviceName, $deploymentSlot, $deploymentName, $upgradeDomain, $waitForOperation = false)
+	{
+		$client = new Zend_Service_WindowsAzure_Management_Client($subscriptionId, $certificate, $certificatePassphrase);
+		
+		if (!is_null($deploymentSlot) && $deploymentSlot != '') {
+			$deploymentSlot = strtolower($deploymentSlot);
+			
+			$client->walkUpgradeDomainBySlot($serviceName, $deploymentSlot, $upgradeDomain);
+		} else {
+			$client->walkUpgradeDomainByDeploymentId($serviceName, $deploymentName, $upgradeDomain);
+		}
+		
+		if ($waitForOperation) {
+			$client->waitForOperation();
+		}
+		echo $client->getLastRequestId();
+	}
+}
+
+Zend_Service_Console_Command::bootstrap($_SERVER['argv']);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/WindowsAzure/CommandLine/GetAsynchronousOperation.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,88 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service_Console
+ * @subpackage Exception
+ * @version    $Id$
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+/**
+ * Asynchronous Operation commands
+ * 
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure_CommandLine
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * 
+ * @command-handler getasynchronousoperation
+ * @command-handler-description Windows Azure Asynchronous Operation commands
+ * @command-handler-header Windows Azure SDK for PHP
+ * @command-handler-header Copyright (c) 2009 - 2011, RealDolmen (http://www.realdolmen.com)
+ * @command-handler-footer Note: Parameters that are common across all commands can be stored 
+ * @command-handler-footer in two dedicated environment variables.
+ * @command-handler-footer - SubscriptionId: The Windows Azure Subscription Id to operate on.
+ * @command-handler-footer - Certificate The Windows Azure .cer Management Certificate.
+ * @command-handler-footer 
+ * @command-handler-footer All commands support the --ConfigurationFile or -F parameter.
+ * @command-handler-footer The parameter file is a simple INI file carrying one parameter
+ * @command-handler-footer value per line. It accepts the same parameters as one can
+ * @command-handler-footer use from the command line command.
+ */
+class Zend_Service_WindowsAzure_CommandLine_GetAsynchronousOperation
+	extends Zend_Service_Console_Command
+{	
+	/**
+	 * Get information for a specific asynchronous request.
+	 * 
+	 * @command-name GetInfo
+	 * @command-description Get information for a specific asynchronous request.
+	 * @command-parameter-for $subscriptionId Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --SubscriptionId|-sid Required. This is the Windows Azure Subscription Id to operate on.
+	 * @command-parameter-for $certificate Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Certificate|-cert Required. This is the .pem certificate that user has uploaded to Windows Azure subscription as Management Certificate.
+	 * @command-parameter-for $certificatePassphrase Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Prompt --Passphrase|-p Required. The certificate passphrase. If not specified, a prompt will be displayed.
+	 * @command-parameter-for $requestId Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --RequestId|-r Required. The value returned by a call that starts an asynchronous operation to monitor.
+	 * @command-example Get information for a specific asynchronous operation:
+	 * @command-example GetInfo -sid:"<your_subscription_id>" -cert:"mycert.pem" -r:"dab87a4b70e94a36805f5af2d20fc593"
+	 */
+	public function getInfoCommand($subscriptionId, $certificate, $certificatePassphrase, $requestId)
+	{
+		$client = new Zend_Service_WindowsAzure_Management_Client($subscriptionId, $certificate, $certificatePassphrase);
+		$result = $client->getOperationStatus($requestId);
+
+		$this->_displayObjectInformation($result, array('ID', 'Status', 'ErrorMessage'));
+	}
+	
+	/**
+	 * Wait for a specific asynchronous request to complete.
+	 * 
+	 * @command-name WaitFor
+	 * @command-description Wait for a specific asynchronous request to complete.
+	 * @command-parameter-for $subscriptionId Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --SubscriptionId|-sid Required. This is the Windows Azure Subscription Id to operate on.
+	 * @command-parameter-for $certificate Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Certificate|-cert Required. This is the .pem certificate that user has uploaded to Windows Azure subscription as Management Certificate.
+	 * @command-parameter-for $certificatePassphrase Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Prompt --Passphrase|-p Required. The certificate passphrase. If not specified, a prompt will be displayed.
+	 * @command-parameter-for $requestId Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --RequestId|-r Required. The value returned by a call that starts an asynchronous operation to monitor.
+	 * @command-parameter-for $interval Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --Interval|-i Optional. The interval between two status checks (in milliseconds).
+	 * @command-example Wait for a specific asynchronous operation:
+	 * @command-example WaitFor -sid:"<your_subscription_id>" -cert:"mycert.pem" -r:"dab87a4b70e94a36805f5af2d20fc593"
+	 */
+	public function waitForCommand($subscriptionId, $certificate, $certificatePassphrase, $requestId, $interval = 250)
+	{
+		$client = new Zend_Service_WindowsAzure_Management_Client($subscriptionId, $certificate, $certificatePassphrase);
+		$client->waitForOperation($requestId, $interval);
+	}
+}
+
+Zend_Service_Console_Command::bootstrap($_SERVER['argv']);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/WindowsAzure/CommandLine/Package.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,198 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service_Console
+ * @subpackage Exception
+ * @version    $Id$
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+
+/**
+ * Package commands
+ * 
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure_CommandLine
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * 
+ * @command-handler package
+ * @command-handler-description Windows Azure Package commands
+ * @command-handler-header Windows Azure SDK for PHP
+ * @command-handler-header Copyright (c) 2009 - 2011, RealDolmen (http://www.realdolmen.com)
+ * @command-handler-footer 
+ * @command-handler-footer All commands support the --ConfigurationFile or -F parameter.
+ * @command-handler-footer The parameter file is a simple INI file carrying one parameter
+ * @command-handler-footer value per line. It accepts the same parameters as one can
+ * @command-handler-footer use from the command line command.
+ */
+class Zend_Service_WindowsAzure_CommandLine_Package
+	extends Zend_Service_Console_Command
+{	
+	/**
+	 * Scaffolds a Windows Azure project structure which can be customized before packaging.
+	 * 
+	 * @command-name Scaffold
+	 * @command-description Scaffolds a Windows Azure project structure which can be customized before packaging.
+	 * 
+	 * @command-parameter-for $path Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --Path|-p Required. The path to create the Windows Azure project structure.
+	 * @command-parameter-for $scaffolder Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Scaffolder|-s Optional. The path to the scaffolder to use. Defaults to Scaffolders/DefaultScaffolder.phar 
+	 */
+	public function scaffoldCommand($path, $scaffolder, $argv)
+	{
+		// Default parameter value
+		if ($scaffolder == '') {
+			$scaffolder = dirname(__FILE__) . '/Scaffolders/DefaultScaffolder.phar';
+		}
+		$scaffolder = realpath($scaffolder);
+		
+		// Verify scaffolder
+		if (!is_file($scaffolder)) {
+			require_once 'Zend/Service/Console/Exception.php';
+			throw new Zend_Service_Console_Exception('Could not locate the given scaffolder: ' . $scaffolder);
+		}
+		
+		// Include scaffolder
+		$archive = new Phar($scaffolder);
+		include $scaffolder;
+		if (!class_exists('Scaffolder')) {
+			require_once 'Zend/Service/Console/Exception.php';
+			throw new Zend_Service_Console_Exception('Could not locate a class named Scaffolder in the given scaffolder: ' . $scaffolder . '. Make sure the scaffolder package contains a file named index.php and contains a class named Scaffolder.');
+		}
+		
+		// Cleanup $argv
+		$options = array();
+		foreach ($argv as $arg) {
+			list($key, $value) = explode(':', $arg, 2);
+			while (substr($key, 0, 1) == '-') {
+				$key = substr($key, 1);
+			}
+			$options[$key] = $value;
+		}
+		
+		// Run scaffolder
+		$scaffolderInstance = new Scaffolder();
+		$scaffolderInstance->invoke($archive, $path, $options);
+	}
+	
+
+	/**
+	 * Packages a Windows Azure project structure.
+	 * 
+	 * @command-name Create
+	 * @command-description Packages a Windows Azure project structure.
+	 * 
+	 * @command-parameter-for $path Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --Path|-p Required. The path to package.
+	 * @command-parameter-for $runDevFabric Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --RunDevFabric|-dev Required. Switch. Run and deploy to the Windows Azure development fabric.
+	 * @command-parameter-for $outputPath Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --OutputPath|-out Optional. The output path for the resulting package. 
+	 */
+	public function createPackageCommand($path, $runDevFabric, $outputPath)
+	{
+		// Create output paths
+		if ($outputPath == '') {
+			$outputPath = realpath($path . '/../');
+		}
+		$packageOut = $outputPath . '/' . basename($path) . '.cspkg';
+
+		// Find Windows Azure SDK bin folder
+		$windowsAzureSdkFolderCandidates = array_merge(
+			isset($_SERVER['ProgramFiles']) ? glob($_SERVER['ProgramFiles'] . '\Windows Azure SDK\*\bin', GLOB_NOSORT) : array(),
+			isset($_SERVER['ProgramFiles']) ? glob($_SERVER['ProgramFiles(x86)'] . '\Windows Azure SDK\*\bin', GLOB_NOSORT) : array(),
+			isset($_SERVER['ProgramFiles']) ? glob($_SERVER['ProgramW6432'] . '\Windows Azure SDK\*\bin', GLOB_NOSORT) : array()
+		);
+		if (count($windowsAzureSdkFolderCandidates) == 0) {
+			throw new Zend_Service_Console_Exception('Could not locate Windows Azure SDK for PHP.');
+		}
+		$cspack = '"' . $windowsAzureSdkFolderCandidates[0] . '\cspack.exe' . '"';
+		$csrun = '"' . $windowsAzureSdkFolderCandidates[0] . '\csrun.exe' . '"';
+		
+		// Open the ServiceDefinition.csdef file and check for role paths
+		$serviceDefinitionFile = $path . '/ServiceDefinition.csdef';
+		if (!file_exists($serviceDefinitionFile)) {
+			require_once 'Zend/Service/Console/Exception.php';
+			throw new Zend_Service_Console_Exception('Could not locate ServiceDefinition.csdef at ' . $serviceDefinitionFile . '.');
+		}
+		$serviceDefinition = simplexml_load_file($serviceDefinitionFile);
+		$xmlRoles = array();
+		if ($serviceDefinition->WebRole) {
+			if (count($serviceDefinition->WebRole) > 1) {
+	    		$xmlRoles = array_merge($xmlRoles, $serviceDefinition->WebRole);
+			} else {
+	    		$xmlRoles = array_merge($xmlRoles, array($serviceDefinition->WebRole));
+	    	}
+		}
+		if ($serviceDefinition->WorkerRole) {
+			if (count($serviceDefinition->WorkerRole) > 1) {
+	    		$xmlRoles = array_merge($xmlRoles, $serviceDefinition->WorkerRole);
+			} else {
+	    		$xmlRoles = array_merge($xmlRoles, array($serviceDefinition->WorkerRole));
+	    	}
+		}
+    		
+		// Build '/role:' command parameter
+		$roleArgs = array();
+		foreach ($xmlRoles as $xmlRole) {
+			if ($xmlRole["name"]) {
+				$roleArgs[] = '/role:' . $xmlRole["name"] . ';' . realpath($path . '/' . $xmlRole["name"]);
+			}
+		}
+		
+		// Build command
+		$command = $cspack;
+		$args = array(
+			$path . '\ServiceDefinition.csdef',
+			implode(' ', $roleArgs),
+			'/out:' . $packageOut
+		);
+		if ($runDevFabric) {
+			$args[] = '/copyOnly';
+		}
+		passthru($command . ' ' . implode(' ', $args));
+		
+		// Can we copy a configuration file?
+		$serviceConfigurationFile = $path . '/ServiceConfiguration.cscfg';
+		$serviceConfigurationFileOut = $outputPath . '/ServiceConfiguration.cscfg';
+		if (file_exists($serviceConfigurationFile) && !file_exists($serviceConfigurationFileOut)) {
+			copy($serviceConfigurationFile, $serviceConfigurationFileOut);
+		}
+		
+		// Do we have to start the development fabric?
+		if ($runDevFabric) {
+			passthru($csrun . ' /devstore:start /devfabric:start');
+			passthru($csrun . ' /removeAll');
+			passthru($csrun . ' /run:"' . $packageOut . ';' . $serviceConfigurationFileOut . '" /launchBrowser');
+		}
+	}
+	
+	/**
+	 * Creates a scaffolder from a given path.
+	 * 
+	 * @command-name CreateScaffolder
+	 * @command-description Creates a scaffolder from a given path.
+	 * 
+	 * @command-parameter-for $rootPath Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --Path|-p Required. The path to package into a scaffolder.
+	 * @command-parameter-for $scaffolderFile Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --OutFile|-out Required. The filename of the scaffolder.
+	 */
+	public function createScaffolderCommand($rootPath, $scaffolderFile)
+	{
+		$archive = new Phar($scaffolderFile);
+		$archive->buildFromIterator(
+			new RecursiveIteratorIterator(
+				new RecursiveDirectoryIterator(realpath($rootPath))),
+		realpath($rootPath));
+	}
+}
+Zend_Service_Console_Command::bootstrap($_SERVER['argv']);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/WindowsAzure/CommandLine/PackageScaffolder/PackageScaffolderAbstract.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,249 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/**
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure_CommandLine
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */ 
+abstract class Zend_Service_WindowsAzure_CommandLine_PackageScaffolder_PackageScaffolderAbstract
+{
+	/**
+	 * Invokes the scaffolder.
+	 *
+	 * @param Phar $phar Phar archive containing the current scaffolder.
+	 * @param string $root Path Root path.
+	 * @param array $options Options array (key/value).
+	 */
+	abstract public function invoke(Phar $phar, $rootPath, $options = array());
+	
+	/**
+	 * Writes output to STDERR, followed by a newline (optional)
+	 * 
+	 * @param string $message
+	 * @param string $newLine
+	 */
+	protected function log($message, $newLine = true)
+	{
+		if (error_reporting() === 0) {
+			return;
+		}
+		file_put_contents('php://stderr', $message . ($newLine ? "\r\n" : ''));
+	}
+	
+	/**
+	 * Extract resources to a file system path
+	 * 
+	 * @param Phar $phar Phar archive.
+	 * @param string $path Output path root.
+	 */
+	protected function extractResources(Phar $phar, $path)
+	{
+		$this->deleteDirectory($path);
+		$phar->extractTo($path);
+		@unlink($path . '/index.php');
+		@unlink($path . '/build.bat');
+		$this->copyDirectory($path . '/resources', $path, false);
+		$this->deleteDirectory($path . '/resources');
+	}
+	
+	/**
+	 * Apply file transforms.
+	 * 
+	 * @param string $rootPath Root path.
+	 * @param array $values Key/value array.
+	 */
+	protected function applyTransforms($rootPath, $values)
+	{
+        if (is_null($rootPath) || !is_string($rootPath) || empty($rootPath)) {
+            throw new InvalidArgumentException("Undefined \"rootPath\"");
+        }
+                        
+        if (is_dir($rootPath)) {
+            $d = dir($rootPath);
+            while ( false !== ( $entry = $d->read() ) ) {
+                if ( $entry == '.' || $entry == '..' ) {
+                    continue;
+                }
+                $entry = $rootPath . '/' . $entry; 
+                
+                $this->applyTransforms($entry, $values);
+            }
+            $d->close();
+        } else {
+        	$contents = file_get_contents($rootPath);
+        	foreach ($values as $key => $value) {
+        		$contents = str_replace('$' . $key . '$', $value, $contents);
+        	}
+            file_put_contents($rootPath, $contents);
+        }
+        
+        return true;
+	}
+	
+	/**
+     * Create directory
+     * 
+     * @param string  $path           Path of directory to create.
+     * @param boolean $abortIfExists  Abort if directory exists.
+     * @param boolean $recursive      Create parent directories if not exist.
+     * 
+     * @return boolean
+     */
+    protected function createDirectory($path, $abortIfExists = true, $recursive = true) {
+        if (is_null($path) || !is_string($path) || empty($path)) {
+            throw new InvalidArgumentException ("Undefined \"path\"" );        
+        }
+                
+        if (is_dir($path) && $abortIfExists) {
+            return false;       
+        }
+        
+        if (is_dir($path) ) {
+            @chmod($path, '0777');
+            if (!self::deleteDirectory($path) ) {
+                throw new RuntimeException("Failed to delete \"{$path}\".");
+            }
+        }
+            
+        if (!mkdir($path, '0777', $recursive) || !is_dir($path)) {
+            throw new RuntimeException( "Failed to create directory \"{$path}\"." );
+        }
+
+        return true;
+    }
+    
+    /**
+     * Fully copy a source directory to a target directory.
+     * 
+     * @param string  $sourcePath   Source directory
+     * @param string  $destinationPath   Target directory
+     * @param boolean $abortIfExists Query re-creating target directory if exists
+     * @param octal   $mode           Changes access mode
+     * 
+     * @return boolean
+     */
+    protected function copyDirectory($sourcePath, $destinationPath, $abortIfExists = true, $mode = '0777') {
+        if (is_null($sourcePath) || !is_string($sourcePath) || empty($sourcePath)) {
+            throw new InvalidArgumentException("Undefined \"sourcePath\"");
+        }
+        
+        if (is_null($destinationPath) || !is_string($destinationPath) || empty($destinationPath)) {
+        	throw new InvalidArgumentException("Undefined \"destinationPath\"");
+        }
+                    
+        if (is_dir($destinationPath) && $abortIfExists) {
+            return false;
+        }
+                        
+        if (is_dir($sourcePath)) {
+            if (!is_dir($destinationPath) && !mkdir($destinationPath, $mode)) {
+                throw new RuntimeException("Failed to create target directory \"{$destinationPath}\"" );
+            }
+            $d = dir($sourcePath);
+            while ( false !== ( $entry = $d->read() ) ) {
+                if ( $entry == '.' || $entry == '..' ) {
+                    continue;
+                }
+                $strSourceEntry = $sourcePath . '/' . $entry; 
+                $strTargetEntry = $destinationPath . '/' . $entry;
+                if (is_dir($strSourceEntry) ) {
+                    $this->copyDirectory(
+                    	$strSourceEntry, 
+                    	$strTargetEntry, 
+                    	false, 
+                    	$mode
+                    );
+                    continue;
+                }
+                if (!copy($strSourceEntry, $strTargetEntry) ) {
+                    throw new RuntimeException (
+                        "Failed to copy"
+                        . " file \"{$strSourceEntry}\""
+                        . " to \"{$strTargetEntry}\"" 
+                    );
+                }
+            }
+            $d->close();
+        } else {
+            if (!copy($sourcePath, $destinationPath)) {
+                throw new RuntimeException (
+                    "Failed to copy"
+                    . " file \"{$sourcePath}\""
+                    . " to \"{$destinationPath}\"" 
+                    
+                );
+            }
+        }
+        
+        return true;
+    }
+    
+    /**
+     * Delete directory and all of its contents;
+     * 
+     * @param string $path Directory path
+     * @return boolean
+     */
+    protected function deleteDirectory($path) 
+    {
+        if (is_null($path) || !is_string($path) || empty($path)) {
+            throw new InvalidArgumentException( "Undefined \"path\"" );        
+        }
+        
+        $handleDir = false;
+        if (is_dir($path) ) {    
+            $handleDir = @opendir($path);
+        }
+        if (!$handleDir) {
+            return false;
+        }
+        @chmod($path, 0777);
+        while ($file = readdir($handleDir)) {
+            if ($file == '.' || $file == '..') {
+                continue;
+            }
+            
+            $fsEntity = $path . "/" . $file;
+            
+            if (is_dir($fsEntity)) {
+                $this->deleteDirectory($fsEntity);
+                continue;
+            }
+            
+            if (is_file($fsEntity)) {
+                @unlink($fsEntity);
+                continue;
+            }
+            
+            throw new LogicException (
+                "Unexpected file type: \"{$fsEntity}\"" 
+            );
+        }
+        
+        @chmod($path, 0777);        
+        closedir($handleDir);
+        @rmdir($path);
+                     
+        return true;
+    }
+}
Binary file web/lib/Zend/Service/WindowsAzure/CommandLine/Scaffolders/DefaultScaffolder.phar has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/WindowsAzure/CommandLine/Scaffolders/DefaultScaffolder/build.bat	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,1 @@
+php ..\..\Package.php CreateScaffolder -p:"./" -out:"..\DefaultScaffolder.phar"
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/WindowsAzure/CommandLine/Scaffolders/DefaultScaffolder/index.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,63 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+
+/**
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure_CommandLine
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */ 
+class Scaffolder
+	extends Zend_Service_WindowsAzure_CommandLine_PackageScaffolder_PackageScaffolderAbstract
+{
+	/**
+	 * Invokes the scaffolder.
+	 *
+	 * @param Phar $phar Phar archive containing the current scaffolder.
+	 * @param string $root Path Root path.
+	 * @param array $options Options array (key/value).
+	 */
+	public function invoke(Phar $phar, $rootPath, $options = array())
+	{
+		// Check required parameters
+		if (empty($options['DiagnosticsConnectionString'])) {
+			require_once 'Zend/Service/Console/Exception.php';
+			throw new Zend_Service_Console_Exception('Missing argument for scaffolder: DiagnosticsConnectionString');
+		}
+		
+		// Extract to disk
+		$this->log('Extracting resources...');
+		$this->createDirectory($rootPath);
+		$this->extractResources($phar, $rootPath);
+		$this->log('Extracted resources.');
+		
+		// Apply transforms
+		$this->log('Applying transforms...');
+		$this->applyTransforms($rootPath, $options);
+		$this->log('Applied transforms.');
+		
+		// Show "to do" message
+		$contentRoot = realpath($rootPath . '/PhpOnAzure.Web');
+		echo "\r\n";
+		echo "Note: before packaging your application, please copy your application code to $contentRoot";
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/WindowsAzure/CommandLine/Scaffolders/DefaultScaffolder/resources/PhpOnAzure.Web/Web.config	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<configuration>
+  <system.diagnostics>
+   <trace>
+      <listeners>
+        <add type="zend.service.windowsazure.Diagnostics.DiagnosticMonitorTraceListener, zend.service.windowsazure.Diagnostics, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" name="AzureDiagnostics">
+          <filter type="" />
+        </add>
+      </listeners>
+    </trace>
+  </system.diagnostics>
+  <system.webServer>
+    <defaultDocument>
+      <files>
+        <clear />
+        <add value="index.php" />
+      </files>
+    </defaultDocument>
+  </system.webServer>
+</configuration>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/WindowsAzure/CommandLine/Scaffolders/DefaultScaffolder/resources/PhpOnAzure.Web/bin/add-environment-variables.cmd	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,7 @@
+@echo off
+ECHO "Adding extra environment variables..." >> ..\startup-tasks-log.txt
+
+powershell.exe Set-ExecutionPolicy Unrestricted
+powershell.exe .\add-environment-variables.ps1 >> ..\startup-tasks-log.txt 2>>..\startup-tasks-error-log.txt
+
+ECHO "Added extra environment variables." >> ..\startup-tasks-log.txt
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/WindowsAzure/CommandLine/Scaffolders/DefaultScaffolder/resources/PhpOnAzure.Web/bin/add-environment-variables.ps1	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,15 @@
+[Reflection.Assembly]::LoadWithPartialName("zend.service.windowsazure.ServiceRuntime")
+
+$rdRoleId = [Environment]::GetEnvironmentVariable("RdRoleId", "Machine")
+
+[Environment]::SetEnvironmentVariable("RdRoleId", [zend.service.windowsazure.ServiceRuntime.RoleEnvironment]::CurrentRoleInstance.Id, "Machine")
+[Environment]::SetEnvironmentVariable("RoleName", [zend.service.windowsazure.ServiceRuntime.RoleEnvironment]::CurrentRoleInstance.Role.Name, "Machine")
+[Environment]::SetEnvironmentVariable("RoleInstanceID", [zend.service.windowsazure.ServiceRuntime.RoleEnvironment]::CurrentRoleInstance.Id, "Machine")
+[Environment]::SetEnvironmentVariable("RoleDeploymentID", [zend.service.windowsazure.ServiceRuntime.RoleEnvironment]::DeploymentId, "Machine")
+
+
+if ($rdRoleId -ne [zend.service.windowsazure.ServiceRuntime.RoleEnvironment]::CurrentRoleInstance.Id) {
+    Restart-Computer
+}
+
+[Environment]::SetEnvironmentVariable('Path', $env:RoleRoot + '\base\x86;' + [Environment]::GetEnvironmentVariable('Path', 'Machine'), 'Machine')
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/WindowsAzure/CommandLine/Scaffolders/DefaultScaffolder/resources/PhpOnAzure.Web/bin/install-php.cmd	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,12 @@
+@echo off
+ECHO "Starting PHP installation..." >> ..\startup-tasks-log.txt
+
+md "%~dp0appdata"
+cd "%~dp0appdata"
+cd ..
+
+reg add "hku\.default\software\microsoft\windows\currentversion\explorer\user shell folders" /v "Local AppData" /t REG_EXPAND_SZ /d "%~dp0appdata" /f
+"..\resources\WebPICmdLine\webpicmdline" /Products:PHP53,SQLDriverPHP53IIS /AcceptEula  >> ..\startup-tasks-log.txt 2>>..\startup-tasks-error-log.txt
+reg add "hku\.default\software\microsoft\windows\currentversion\explorer\user shell folders" /v "Local AppData" /t REG_EXPAND_SZ /d %%USERPROFILE%%\AppData\Local /f
+
+ECHO "Completed PHP installation." >> ..\startup-tasks-log.txt
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/WindowsAzure/CommandLine/Scaffolders/DefaultScaffolder/resources/PhpOnAzure.Web/diagnostics.wadcfg	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,35 @@
+<DiagnosticMonitorConfiguration xmlns="http://schemas.microsoft.com/ServiceHosting/2010/10/DiagnosticsConfiguration" configurationChangePollInterval="PT1M" overallQuotaInMB="4096">
+   <DiagnosticInfrastructureLogs bufferQuotaInMB="10"
+      scheduledTransferLogLevelFilter="Error"
+      scheduledTransferPeriod="PT1M" />
+
+   <Logs bufferQuotaInMB="0"
+      scheduledTransferLogLevelFilter="Verbose"
+      scheduledTransferPeriod="PT1M" />
+
+   <Directories bufferQuotaInMB="0" 
+      scheduledTransferPeriod="PT5M">
+   
+      <!-- These three elements specify the special directories 
+           that are set up for the log types -->
+      <CrashDumps container="wad-crash-dumps" directoryQuotaInMB="256" />
+      <FailedRequestLogs container="wad-frq" directoryQuotaInMB="256" />
+      <IISLogs container="wad-iis" directoryQuotaInMB="256" />
+   </Directories>
+
+   <PerformanceCounters bufferQuotaInMB="0" scheduledTransferPeriod="PT1M">
+      <!-- The counter specifier is in the same format as the imperative 
+           diagnostics configuration API -->
+      <PerformanceCounterConfiguration 
+         counterSpecifier="\Processor(_Total)\% Processor Time" sampleRate="PT5M" />
+      <PerformanceCounterConfiguration 
+         counterSpecifier="\Memory\Available Mbytes" sampleRate="PT5M" />
+   </PerformanceCounters>
+   <WindowsEventLog bufferQuotaInMB="0"
+      scheduledTransferLogLevelFilter="Verbose"
+      scheduledTransferPeriod="PT5M">
+      <!-- The event log name is in the same format as the imperative 
+           diagnostics configuration API -->
+      <DataSource name="System!*" />
+   </WindowsEventLog>
+</DiagnosticMonitorConfiguration>
Binary file web/lib/Zend/Service/WindowsAzure/CommandLine/Scaffolders/DefaultScaffolder/resources/PhpOnAzure.Web/resources/WebPICmdLine/Microsoft.Web.Deployment.dll has changed
Binary file web/lib/Zend/Service/WindowsAzure/CommandLine/Scaffolders/DefaultScaffolder/resources/PhpOnAzure.Web/resources/WebPICmdLine/Microsoft.Web.PlatformInstaller.UI.dll has changed
Binary file web/lib/Zend/Service/WindowsAzure/CommandLine/Scaffolders/DefaultScaffolder/resources/PhpOnAzure.Web/resources/WebPICmdLine/Microsoft.Web.PlatformInstaller.dll has changed
Binary file web/lib/Zend/Service/WindowsAzure/CommandLine/Scaffolders/DefaultScaffolder/resources/PhpOnAzure.Web/resources/WebPICmdLine/WebpiCmdLine.exe has changed
Binary file web/lib/Zend/Service/WindowsAzure/CommandLine/Scaffolders/DefaultScaffolder/resources/PhpOnAzure.Web/resources/WebPICmdLine/license.rtf has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/WindowsAzure/CommandLine/Scaffolders/DefaultScaffolder/resources/ServiceConfiguration.cscfg	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ServiceConfiguration serviceName="PhpOnAzure" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration" osFamily="2" osVersion="*">
+  <Role name="PhpOnAzure.Web">
+    <Instances count="1" />
+    <ConfigurationSettings>
+      <Setting name="zend.service.windowsazure.Plugins.Diagnostics.ConnectionString" value="$DiagnosticsConnectionString$"/>
+    </ConfigurationSettings>
+  </Role>
+</ServiceConfiguration>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/WindowsAzure/CommandLine/Scaffolders/DefaultScaffolder/resources/ServiceDefinition.csdef	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ServiceDefinition name="PhpOnAzure" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
+  <WebRole name="PhpOnAzure.Web" enableNativeCodeExecution="true">
+    <Sites>
+      <Site name="Web" physicalDirectory="./PhpOnAzure.Web">
+        <Bindings>
+          <Binding name="Endpoint1" endpointName="HttpEndpoint" />
+        </Bindings>
+      </Site>
+    </Sites>
+    <Startup>
+      <Task commandLine="add-environment-variables.cmd" executionContext="elevated" taskType="simple" />
+      <Task commandLine="install-php.cmd" executionContext="elevated" taskType="simple" />
+    </Startup>
+    <Endpoints>
+      <InputEndpoint name="HttpEndpoint" protocol="http" port="80" />
+    </Endpoints>
+    <Imports>
+      <Import moduleName="Diagnostics"/>
+    </Imports>
+    <ConfigurationSettings>
+    </ConfigurationSettings>
+  </WebRole>
+</ServiceDefinition>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/WindowsAzure/CommandLine/Service.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,192 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service_Console
+ * @subpackage Exception
+ * @version    $Id$
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+
+/**
+ * Service commands
+ * 
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure_CommandLine
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * 
+ * @command-handler service
+ * @command-handler-description Windows Azure Service commands
+ * @command-handler-header Windows Azure SDK for PHP
+ * @command-handler-header Copyright (c) 2009 - 2011, RealDolmen (http://www.realdolmen.com)
+ * @command-handler-footer Note: Parameters that are common across all commands can be stored 
+ * @command-handler-footer in two dedicated environment variables.
+ * @command-handler-footer - SubscriptionId: The Windows Azure Subscription Id to operate on.
+ * @command-handler-footer - Certificate The Windows Azure .cer Management Certificate.
+ * @command-handler-footer 
+ * @command-handler-footer All commands support the --ConfigurationFile or -F parameter.
+ * @command-handler-footer The parameter file is a simple INI file carrying one parameter
+ * @command-handler-footer value per line. It accepts the same parameters as one can
+ * @command-handler-footer use from the command line command.
+ */
+class Zend_Service_WindowsAzure_CommandLine_Service
+	extends Zend_Service_Console_Command
+{	
+	/**
+	 * List hosted service accounts for a specified subscription.
+	 * 
+	 * @command-name List
+	 * @command-description List hosted service accounts for a specified subscription.
+	 * @command-parameter-for $subscriptionId Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --SubscriptionId|-sid Required. This is the Windows Azure Subscription Id to operate on.
+	 * @command-parameter-for $certificate Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Certificate|-cert Required. This is the .pem certificate that user has uploaded to Windows Azure subscription as Management Certificate.
+	 * @command-parameter-for $certificatePassphrase Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Prompt --Passphrase|-p Required. The certificate passphrase. If not specified, a prompt will be displayed.
+	 * @command-example List hosted service accounts for subscription:
+	 * @command-example List -sid:"<your_subscription_id>" -cert:"mycert.pem"
+	 */
+	public function listCommand($subscriptionId, $certificate, $certificatePassphrase)
+	{
+		$client = new Zend_Service_WindowsAzure_Management_Client($subscriptionId, $certificate, $certificatePassphrase);
+		$result = $client->listHostedServices();
+
+		if (count($result) == 0) {
+			echo 'No data to display.';
+		}
+		foreach ($result as $object) {
+			$this->_displayObjectInformation($object, array('ServiceName', 'Url'));
+		}
+	}
+	
+	/**
+	 * Get hosted service account properties.
+	 * 
+	 * @command-name GetProperties
+	 * @command-description Get hosted service account properties.
+	 * @command-parameter-for $subscriptionId Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --SubscriptionId|-sid Required. This is the Windows Azure Subscription Id to operate on.
+	 * @command-parameter-for $certificate Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Certificate|-cert Required. This is the .pem certificate that user has uploaded to Windows Azure subscription as Management Certificate.
+	 * @command-parameter-for $certificatePassphrase Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Prompt --Passphrase|-p Required. The certificate passphrase. If not specified, a prompt will be displayed.
+	 * @command-parameter-for $serviceName Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Name Required. The hosted service account name to operate on.
+	 * @command-example Get hosted service account properties for service "phptest":
+	 * @command-example GetProperties -sid:"<your_subscription_id>" -cert:"mycert.pem"
+	 * @command-example --Name:"phptest"
+	 */
+	public function getPropertiesCommand($subscriptionId, $certificate, $certificatePassphrase, $serviceName)
+	{
+		$client = new Zend_Service_WindowsAzure_Management_Client($subscriptionId, $certificate, $certificatePassphrase);
+		$result = $client->getHostedServiceProperties($serviceName);
+		
+		$this->_displayObjectInformation($result, array('ServiceName', 'Label', 'AffinityGroup', 'Location'));
+	}
+	
+	/**
+	 * Get hosted service account property.
+	 * 
+	 * @command-name GetProperty
+	 * @command-description Get storage account property.
+	 * @command-parameter-for $subscriptionId Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --SubscriptionId|-sid Required. This is the Windows Azure Subscription Id to operate on.
+	 * @command-parameter-for $certificate Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Certificate|-cert Required. This is the .pem certificate that user has uploaded to Windows Azure subscription as Management Certificate.
+	 * @command-parameter-for $certificatePassphrase Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Prompt --Passphrase|-p Required. The certificate passphrase. If not specified, a prompt will be displayed.
+	 * @command-parameter-for $serviceName Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Name Required. The hosted service account name to operate on.
+	 * @command-parameter-for $property Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --Property|-prop Required. The property to retrieve for the hosted service account.
+	 * @command-example Get hosted service account property "Url" for service "phptest":
+	 * @command-example GetProperty -sid:"<your_subscription_id>" -cert:"mycert.pem"
+	 * @command-example --Name:"phptest" --Property:Url
+	 */
+	public function getPropertyCommand($subscriptionId, $certificate, $certificatePassphrase, $serviceName, $property)
+	{
+		$client = new Zend_Service_WindowsAzure_Management_Client($subscriptionId, $certificate, $certificatePassphrase);
+		$result = $client->getHostedServiceProperties($serviceName);
+		
+		printf("%s\r\n", $result->$property);
+	}
+	
+	/**
+	 * Create hosted service account.
+	 * 
+	 * @command-name Create
+	 * @command-description Create hosted service account.
+	 * @command-parameter-for $subscriptionId Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --SubscriptionId|-sid Required. This is the Windows Azure Subscription Id to operate on.
+	 * @command-parameter-for $certificate Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Certificate|-cert Required. This is the .pem certificate that user has uploaded to Windows Azure subscription as Management Certificate.
+	 * @command-parameter-for $certificatePassphrase Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Prompt --Passphrase|-p Required. The certificate passphrase. If not specified, a prompt will be displayed.
+	 * @command-parameter-for $serviceName Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --Name Required. The hosted service account name.
+	 * @command-parameter-for $label Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --Label Required. A label for the hosted service.
+	 * @command-parameter-for $description Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --Description Optional. A description for the hosted service.
+	 * @command-parameter-for $location Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --Location Required if AffinityGroup is not specified. The location where the hosted service will be created.
+	 * @command-parameter-for $affinityGroup Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --AffinityGroup Required if Location is not specified. The name of an existing affinity group associated with this subscription.
+	 * @command-parameter-for $waitForOperation Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --WaitFor|-w Optional. Wait for the operation to complete?
+	 * @command-example Create hosted service account in West Europe
+	 * @command-example Create -p:"phpazure" --Name:"phptestsdk2" --Label:"phptestsdk2" --Location:"West Europe"
+	 */
+	public function createCommand($subscriptionId, $certificate, $certificatePassphrase, $serviceName, $label, $description, $location, $affinityGroup, $waitForOperation = false)
+	{
+		$client = new Zend_Service_WindowsAzure_Management_Client($subscriptionId, $certificate, $certificatePassphrase);
+		$client->createHostedService($serviceName, $label, $description, $location, $affinityGroup);
+		if ($waitForOperation) {
+			$client->waitForOperation();
+		}
+		echo $client->getLastRequestId();
+	}
+	
+	/**
+	 * Update hosted service account.
+	 * 
+	 * @command-name Update
+	 * @command-description Update hosted service account.
+	 * @command-parameter-for $subscriptionId Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --SubscriptionId|-sid Required. This is the Windows Azure Subscription Id to operate on.
+	 * @command-parameter-for $certificate Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Certificate|-cert Required. This is the .pem certificate that user has uploaded to Windows Azure subscription as Management Certificate.
+	 * @command-parameter-for $certificatePassphrase Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Prompt --Passphrase|-p Required. The certificate passphrase. If not specified, a prompt will be displayed.
+	 * @command-parameter-for $serviceName Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --Name Required. The hosted service account name.
+	 * @command-parameter-for $label Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --Label Required. A label for the hosted service.
+	 * @command-parameter-for $description Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --Description Optional. A description for the hosted service.
+	 * @command-parameter-for $waitForOperation Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --WaitFor|-w Optional. Wait for the operation to complete?
+	 * @command-example Update hosted service
+	 * @command-example Update -p:"phpazure" --Name:"phptestsdk2" --Label:"New label" --Description:"Some description"
+	 */
+	public function updateCommand($subscriptionId, $certificate, $certificatePassphrase, $serviceName, $label, $description, $waitForOperation = false)
+	{
+		$client = new Zend_Service_WindowsAzure_Management_Client($subscriptionId, $certificate, $certificatePassphrase);
+		$client->updateHostedService($serviceName, $label, $description);
+		if ($waitForOperation) {
+			$client->waitForOperation();
+		}
+		echo $client->getLastRequestId();
+	}
+	
+	/**
+	 * Delete hosted service account.
+	 * 
+	 * @command-name Delete
+	 * @command-description Delete hosted service account.
+	 * @command-parameter-for $subscriptionId Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --SubscriptionId|-sid Required. This is the Windows Azure Subscription Id to operate on.
+	 * @command-parameter-for $certificate Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Certificate|-cert Required. This is the .pem certificate that user has uploaded to Windows Azure subscription as Management Certificate.
+	 * @command-parameter-for $certificatePassphrase Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Prompt --Passphrase|-p Required. The certificate passphrase. If not specified, a prompt will be displayed.
+	 * @command-parameter-for $serviceName Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --Name Required. The hosted service account name.
+	 * @command-parameter-for $waitForOperation Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --WaitFor|-w Optional. Wait for the operation to complete?
+	 * @command-example Delete hosted service
+	 * @command-example Delete -p:"phpazure" --Name:"phptestsdk2"
+	 */
+	public function deleteCommand($subscriptionId, $certificate, $certificatePassphrase, $serviceName, $waitForOperation = false)
+	{
+		$client = new Zend_Service_WindowsAzure_Management_Client($subscriptionId, $certificate, $certificatePassphrase);
+		$client->deleteHostedService($serviceName);
+		if ($waitForOperation) {
+			$client->waitForOperation();
+		}
+		echo $client->getLastRequestId();
+	}
+}
+
+Zend_Service_Console_Command::bootstrap($_SERVER['argv']);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/WindowsAzure/CommandLine/Storage.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,189 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service_Console
+ * @subpackage Exception
+ * @version    $Id$
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+
+/**
+ * Storage commands
+ * 
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure_CommandLine
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * 
+ * @command-handler storage
+ * @command-handler-description Windows Azure Storage commands
+ * @command-handler-header Windows Azure SDK for PHP
+ * @command-handler-header Copyright (c) 2009 - 2011, RealDolmen (http://www.realdolmen.com)
+ * @command-handler-footer Note: Parameters that are common across all commands can be stored 
+ * @command-handler-footer in two dedicated environment variables.
+ * @command-handler-footer - SubscriptionId: The Windows Azure Subscription Id to operate on.
+ * @command-handler-footer - Certificate The Windows Azure .cer Management Certificate.
+ * @command-handler-footer 
+ * @command-handler-footer All commands support the --ConfigurationFile or -F parameter.
+ * @command-handler-footer The parameter file is a simple INI file carrying one parameter
+ * @command-handler-footer value per line. It accepts the same parameters as one can
+ * @command-handler-footer use from the command line command.
+ */
+class Zend_Service_WindowsAzure_CommandLine_Storage
+	extends Zend_Service_Console_Command
+{	
+	/**
+	 * List storage accounts for a specified subscription.
+	 * 
+	 * @command-name ListAccounts
+	 * @command-description List storage accounts for a specified subscription.
+	 * @command-parameter-for $subscriptionId Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --SubscriptionId|-sid Required. This is the Windows Azure Subscription Id to operate on.
+	 * @command-parameter-for $certificate Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Certificate|-cert Required. This is the .pem certificate that user has uploaded to Windows Azure subscription as Management Certificate.
+	 * @command-parameter-for $certificatePassphrase Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Prompt --Passphrase|-p Required. The certificate passphrase. If not specified, a prompt will be displayed.
+	 * @command-example List storage accounts for subscription:
+	 * @command-example ListAccounts -sid:"<your_subscription_id>" -cert:"mycert.pem"
+	 */
+	public function listAccountsCommand($subscriptionId, $certificate, $certificatePassphrase)
+	{
+		$client = new Zend_Service_WindowsAzure_Management_Client($subscriptionId, $certificate, $certificatePassphrase);
+		$result = $client->listStorageAccounts();
+
+		if (count($result) == 0) {
+			echo 'No data to display.';
+		}
+		foreach ($result as $object) {
+			$this->_displayObjectInformation($object, array('ServiceName', 'Url'));
+		}
+	}
+	
+	/**
+	 * Get storage account properties.
+	 * 
+	 * @command-name GetProperties
+	 * @command-description Get storage account properties.
+	 * @command-parameter-for $subscriptionId Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --SubscriptionId|-sid Required. This is the Windows Azure Subscription Id to operate on.
+	 * @command-parameter-for $certificate Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Certificate|-cert Required. This is the .pem certificate that user has uploaded to Windows Azure subscription as Management Certificate.
+	 * @command-parameter-for $certificatePassphrase Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Prompt --Passphrase|-p Required. The certificate passphrase. If not specified, a prompt will be displayed.
+	 * @command-parameter-for $accountName Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --AccountName Required. The storage account name to operate on.
+	 * @command-example Get storage account properties for account "phptest":
+	 * @command-example GetProperties -sid:"<your_subscription_id>" -cert:"mycert.pem"
+	 * @command-example --AccountName:"phptest"
+	 */
+	public function getPropertiesCommand($subscriptionId, $certificate, $certificatePassphrase, $accountName)
+	{
+		$client = new Zend_Service_WindowsAzure_Management_Client($subscriptionId, $certificate, $certificatePassphrase);
+		$result = $client->getStorageAccountProperties($accountName);
+		
+		$this->_displayObjectInformation($result, array('ServiceName', 'Label', 'AffinityGroup', 'Location'));
+	}
+	
+	/**
+	 * Get storage account property.
+	 * 
+	 * @command-name GetProperty
+	 * @command-description Get storage account property.
+	 * @command-parameter-for $subscriptionId Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --SubscriptionId|-sid Required. This is the Windows Azure Subscription Id to operate on.
+	 * @command-parameter-for $certificate Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Certificate|-cert Required. This is the .pem certificate that user has uploaded to Windows Azure subscription as Management Certificate.
+	 * @command-parameter-for $certificatePassphrase Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Prompt --Passphrase|-p Required. The certificate passphrase. If not specified, a prompt will be displayed.
+	 * @command-parameter-for $accountName Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --AccountName Required. The storage account name to operate on.
+	 * @command-parameter-for $property Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --Property|-prop Required. The property to retrieve for the storage account.
+	 * @command-example Get storage account property "Url" for account "phptest":
+	 * @command-example GetProperty -sid:"<your_subscription_id>" -cert:"mycert.pem"
+	 * @command-example --AccountName:"phptest" --Property:Url
+	 */
+	public function getPropertyCommand($subscriptionId, $certificate, $certificatePassphrase, $accountName, $property)
+	{
+		$client = new Zend_Service_WindowsAzure_Management_Client($subscriptionId, $certificate, $certificatePassphrase);
+		$result = $client->getStorageAccountProperties($accountName);
+		
+		printf("%s\r\n", $result->$property);
+	}
+	
+	/**
+	 * Get storage account keys.
+	 * 
+	 * @command-name GetKeys
+	 * @command-description Get storage account keys.
+	 * @command-parameter-for $subscriptionId Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --SubscriptionId|-sid Required. This is the Windows Azure Subscription Id to operate on.
+	 * @command-parameter-for $certificate Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Certificate|-cert Required. This is the .pem certificate that user has uploaded to Windows Azure subscription as Management Certificate.
+	 * @command-parameter-for $certificatePassphrase Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Prompt --Passphrase|-p Required. The certificate passphrase. If not specified, a prompt will be displayed.
+	 * @command-parameter-for $accountName Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --AccountName Required. The storage account name to operate on.
+	 * @command-example Get storage account keys for account "phptest":
+	 * @command-example GetKeys -sid:"<your_subscription_id>" -cert:"mycert.pem"
+	 * @command-example --AccountName:"phptest"
+	 */
+	public function getKeysCommand($subscriptionId, $certificate, $certificatePassphrase, $accountName)
+	{
+		$client = new Zend_Service_WindowsAzure_Management_Client($subscriptionId, $certificate, $certificatePassphrase);
+		$result = $client->getStorageAccountKeys($accountName);
+		
+		$this->_displayObjectInformation((object)array('Key' => 'primary', 'Value' => $result[0]), array('Key', 'Value'));
+		$this->_displayObjectInformation((object)array('Key' => 'secondary', 'Value' => $result[1]), array('Key', 'Value'));
+	}
+	
+	/**
+	 * Get storage account key.
+	 * 
+	 * @command-name GetKey
+	 * @command-description Get storage account key.
+	 * @command-parameter-for $subscriptionId Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --SubscriptionId|-sid Required. This is the Windows Azure Subscription Id to operate on.
+	 * @command-parameter-for $certificate Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Certificate|-cert Required. This is the .pem certificate that user has uploaded to Windows Azure subscription as Management Certificate.
+	 * @command-parameter-for $certificatePassphrase Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Prompt --Passphrase|-p Required. The certificate passphrase. If not specified, a prompt will be displayed.
+	 * @command-parameter-for $accountName Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --AccountName Required. The storage account name to operate on.
+	 * @command-parameter-for $key Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --Key|-k Optional. Specifies the key to regenerate (primary|secondary). If omitted, primary key is used as the default.
+	 * @command-example Get primary storage account key for account "phptest":
+	 * @command-example GetKey -sid:"<your_subscription_id>" -cert:"mycert.pem"
+	 * @command-example --AccountName:"phptest" -Key:primary
+	 */
+	public function getKeyCommand($subscriptionId, $certificate, $certificatePassphrase, $accountName, $key = 'primary')
+	{
+		$client = new Zend_Service_WindowsAzure_Management_Client($subscriptionId, $certificate, $certificatePassphrase);
+		$result = $client->getStorageAccountKeys($accountName);
+		
+		if (strtolower($key) == 'secondary') {
+			printf("%s\r\n", $result[1]);
+		}
+		printf("%s\r\n", $result[0]);
+	}
+	
+	/**
+	 * Regenerate storage account keys.
+	 * 
+	 * @command-name RegenerateKeys
+	 * @command-description Regenerate storage account keys.
+	 * @command-parameter-for $subscriptionId Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --SubscriptionId|-sid Required. This is the Windows Azure Subscription Id to operate on.
+	 * @command-parameter-for $certificate Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --Certificate|-cert Required. This is the .pem certificate that user has uploaded to Windows Azure subscription as Management Certificate.
+	 * @command-parameter-for $certificatePassphrase Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Prompt --Passphrase|-p Required. The certificate passphrase. If not specified, a prompt will be displayed.
+	 * @command-parameter-for $accountName Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile|Zend_Service_Console_Command_ParameterSource_Env --AccountName Required. The storage account name to operate on.
+	 * @command-parameter-for $key Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --Key|-k Optional. Specifies the key to regenerate (primary|secondary). If omitted, primary key is used as the default.
+	 * @command-parameter-for $waitForOperation Zend_Service_Console_Command_ParameterSource_Argv|Zend_Service_Console_Command_ParameterSource_ConfigFile --WaitFor|-w Optional. Wait for the operation to complete?
+	 * @command-example Regenerate secondary key for account "phptest":
+	 * @command-example RegenerateKeys -sid:"<your_subscription_id>" -cert:"mycert.pem"
+	 * @command-example --AccountName:"phptest" -Key:secondary
+	 */
+	public function regenerateKeysCommand($subscriptionId, $certificate, $certificatePassphrase, $accountName, $key = 'primary', $waitForOperation = false)
+	{
+		$client = new Zend_Service_WindowsAzure_Management_Client($subscriptionId, $certificate, $certificatePassphrase);
+		$client->regenerateStorageAccountKey($accountName, $key);
+		if ($waitForOperation) {
+			$client->waitForOperation();
+		}
+		echo $client->getLastRequestId();
+	}
+}
+
+Zend_Service_Console_Command::bootstrap($_SERVER['argv']);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/WindowsAzure/Log/Exception.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,38 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure
+ * @subpackage Exception
+ * @version    $Id: Exception.php 25285 2013-03-09 10:30:20Z frosch $
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+/**
+ * @see Zend_Service_WindowsAzure_Exception
+ */
+require_once 'Zend/Service/WindowsAzure/Exception.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure
+ * @subpackage Log
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Service_WindowsAzure_Log_Exception
+    extends Zend_Service_WindowsAzure_Exception
+{
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/WindowsAzure/Log/Formatter/WindowsAzure.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,73 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure
+ * @subpackage Storage
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/**
+ * @see Zend_Log_Formatter_Interface
+ */
+require_once 'Zend/Log/Formatter/Interface.php';
+
+/**
+ * @see Zend_Service_WindowsAzure_Storage_DynamicTableEntity
+ */
+require_once 'Zend/Service/WindowsAzure/Storage/DynamicTableEntity.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure
+ * @subpackage Log
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Service_WindowsAzure_Log_Formatter_WindowsAzure
+    implements Zend_Log_Formatter_Interface
+{
+    /**
+     * Write a message to the table storage
+     *
+     * @param  array $event
+     *
+     * @return Zend_Service_WindowsAzure_Storage_DynamicTableEntity
+     */
+    public function format($event)
+    {
+        // partition key is the current date, represented as YYYYMMDD
+        // row key will always be the current timestamp. These values MUST be hardcoded.
+        $logEntity = new Zend_Service_WindowsAzure_Storage_DynamicTableEntity(
+            date('Ymd'), microtime(true)
+        );
+        // Windows Azure automatically adds the timestamp, but the timezone is most of the time
+        // different compared to the origin server's timezone, so add this timestamp aswell.
+        $event['server_timestamp'] = $event['timestamp'];
+        unset($event['timestamp']);
+
+        foreach ($event as $key => $value) {
+            if ((is_object($value) && !method_exists($value, '__toString'))
+                || is_array($value)
+            ) {
+                $value = gettype($value);
+            }
+            $logEntity->{$key} = $value;
+        }
+
+        return $logEntity;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/WindowsAzure/Log/Writer/WindowsAzure.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,196 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure
+ * @subpackage Storage
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/**
+ * @see Zend_Log_Writer_Abstract
+ */
+require_once 'Zend/Log/Writer/Abstract.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure
+ * @subpackage Log
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Service_WindowsAzure_Log_Writer_WindowsAzure
+    extends Zend_Log_Writer_Abstract
+{
+    /**
+     * @var Zend_Service_Log_Formatter_Interface
+     */
+    protected $_formatter;
+
+    /**
+     * Connection to a windows Azure
+     *
+     * @var Zend_Service_Service_WindowsAzure_Storage_Table
+     */
+    protected $_tableStorageConnection = null;
+
+    /**
+     * Name of the table to use for logging purposes
+     *
+     * @var string
+     */
+    protected $_tableName = null;
+
+    /**
+     * Whether to keep all messages to be logged in an external buffer until the script ends and
+     * only then to send the messages in batch to the logging component.
+     *
+     * @var bool
+     */
+    protected $_bufferMessages = false;
+
+    /**
+     * If message buffering is activated, it will store all the messages in this buffer and only
+     * write them to table storage (in a batch transaction) when the script ends.
+     *
+     * @var array
+     */
+    protected $_messageBuffer = array();
+
+    /**
+     * @param Zend_Service_Service_WindowsAzure_Storage_Table|Zend_Service_WindowsAzure_Storage_Table $tableStorageConnection
+     * @param string                                                                                  $tableName
+     * @param bool                                                                                    $createTable create the Windows Azure table for logging if it does not exist
+     * @param bool                                                                                    $bufferMessages
+     * @throws Zend_Service_Log_Exception
+     */
+    public function __construct(
+        Zend_Service_WindowsAzure_Storage_Table $tableStorageConnection,
+        $tableName, $createTable = true, $bufferMessages = true
+    )
+    {
+        if ($tableStorageConnection == null) {
+            require_once 'Zend/Service/Log/Exception.php';
+            throw new Zend_Service_Log_Exception(
+                'No connection to the Windows Azure tables provided.'
+            );
+        }
+
+        if (!is_string($tableName)) {
+            require_once 'Zend/Service/Log/Exception.php';
+            throw new Zend_Service_Log_Exception(
+                'Provided Windows Azure table name must be a string.'
+            );
+        }
+
+        $this->_tableStorageConnection = $tableStorageConnection;
+        $this->_tableName              = $tableName;
+
+        // create the logging table if it does not exist. It will add some overhead, so it's optional
+        if ($createTable) {
+            $this->_tableStorageConnection->createTableIfNotExists(
+                $this->_tableName
+            );
+        }
+
+        // keep messages to be logged in an internal buffer and only send them over the wire when
+        // the script execution ends
+        if ($bufferMessages) {
+            $this->_bufferMessages = $bufferMessages;
+        }
+
+        $this->_formatter =
+            new Zend_Service_WindowsAzure_Log_Formatter_WindowsAzure();
+    }
+
+    /**
+     * If the log messages have been stored in the internal buffer, just send them
+     * to table storage.
+     */
+    public function shutdown()
+    {
+        parent::shutdown();
+        if ($this->_bufferMessages) {
+            $this->_tableStorageConnection->startBatch();
+            foreach ($this->_messageBuffer as $logEntity) {
+                $this->_tableStorageConnection->insertEntity(
+                    $this->_tableName, $logEntity
+                );
+            }
+            $this->_tableStorageConnection->commit();
+        }
+    }
+
+    /**
+     * Create a new instance of Zend_Service_Log_Writer_WindowsAzure
+     *
+     * @param  array $config
+     * @return Zend_Service_Log_Writer_WindowsAzure
+     * @throws Zend_Service_Log_Exception
+     */
+    static public function factory($config)
+    {
+        $config = self::_parseConfig($config);
+        $config = array_merge(
+            array(
+                 'connection' => null,
+                 'tableName' => null,
+                 'createTable' => true,
+            ), $config
+        );
+
+        return new self(
+            $config['connection'],
+            $config['tableName'],
+            $config['createTable']
+        );
+    }
+
+    /**
+     * The only formatter accepted is already  loaded in the constructor
+     *
+     * @todo enable custom formatters using the WindowsAzure_Storage_DynamicTableEntity class
+     */
+    public function setFormatter(
+        Zend_Service_Log_Formatter_Interface $formatter
+    )
+    {
+        require_once 'Zend/Service/Log/Exception.php';
+        throw new Zend_Service_Log_Exception(
+            get_class($this) . ' does not support formatting');
+    }
+
+    /**
+     * Write a message to the table storage. If buffering is activated, then messages will just be
+     * added to an internal buffer.
+     *
+     * @param  array $event
+     * @return void
+     * @todo   format the event using a formatted, not in this method
+     */
+    protected function _write($event)
+    {
+        $logEntity = $this->_formatter->format($event);
+
+        if ($this->_bufferMessages) {
+            $this->_messageBuffer[] = $logEntity;
+        } else {
+            $this->_tableStorageConnection->insertEntity(
+                $this->_tableName, $logEntity
+            );
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/WindowsAzure/Management/AffinityGroupInstance.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,66 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure
+ * @subpackage Management
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/**
+ * @see Zend_Service_WindowsAzure_Management_ServiceEntityAbstract
+ */
+require_once 'Zend/Service/WindowsAzure/Management/ServiceEntityAbstract.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure
+ * @subpackage Management
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * 
+ * @property string $Name              The affinity group name. 
+ * @property string $Label             A label for the affinity group.
+ * @property string $Description       A description for the affinity group.
+ * @property string $Location          The location of the affinity group.
+ * @property array  $HostedServices    A list of hosted services in this affinity gtoup.
+ * @property array  $StorageServices   A list of storage services in this affinity gtoup.
+ */
+class Zend_Service_WindowsAzure_Management_AffinityGroupInstance
+	extends Zend_Service_WindowsAzure_Management_ServiceEntityAbstract
+{    
+    /**
+     * Constructor
+     * 
+     * @property string $name              The affinity group name. 
+     * @property string $label             A label for the affinity group.
+     * @property string $description       A description for the affinity group.
+     * @property string $location          The location of the affinity group.
+     * @property array  $hostedServices    A list of hosted services in this affinity gtoup.
+     * @property array  $storageServices   A list of storage services in this affinity gtoup.
+	 */
+    public function __construct($name, $label, $description, $location, $hostedServices = array(), $storageServices = array()) 
+    {	        
+        $this->_data = array(
+            'name'              => $name,
+            'label'             => base64_decode($label),
+            'description'       => $description,
+            'location'          => $location,
+            'hostedservices'    => $hostedServices,
+            'storageservices'   => $storageServices
+        );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/WindowsAzure/Management/CertificateInstance.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,60 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure
+ * @subpackage Management
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/**
+ * @see Zend_Service_WindowsAzure_Management_ServiceEntityAbstract
+ */
+require_once 'Zend/Service/WindowsAzure/Management/ServiceEntityAbstract.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure
+ * @subpackage Management
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * 
+ * @property string $CertificateUrl          Certificate thumbprint address.
+ * @property string $Thumbprint              Certificate thumbprint.
+ * @property string $ThumbprintAlgorithm	 Certificate thumbprint algorithm.
+ * @property string $Data                    Certificate data.
+ */
+class Zend_Service_WindowsAzure_Management_CertificateInstance
+	extends Zend_Service_WindowsAzure_Management_ServiceEntityAbstract
+{    
+    /**
+     * Constructor
+     * 
+     * @param string $certificateUrl          Certificate thumbprint address.
+     * @param string $thumbprint              Certificate thumbprint.
+     * @param string $thumbprintAlgorithm	 Certificate thumbprint algorithm.
+     * @param string $data                    Certificate data.
+	 */
+    public function __construct($certificateUrl, $thumbprint, $thumbprintAlgorithm, $data) 
+    {	        
+        $this->_data = array(
+            'certificateurl'       => $certificateUrl,
+            'thumbprint'           => $thumbprint,
+            'thumbprintalgorithm'  => $thumbprintAlgorithm,
+            'data'                 => base64_decode($data)        
+        );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/WindowsAzure/Management/Client.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,2423 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure
+ * @subpackage Management
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/**
+ * @see Zend_Service_WindowsAzure_Management_OperationStatusInstance
+ */
+require_once 'Zend/Service/WindowsAzure/Management/OperationStatusInstance.php';
+
+/**
+ * @see Zend_Service_WindowsAzure_Management_SubscriptionOperationInstance
+ */
+require_once 'Zend/Service/WindowsAzure/Management/SubscriptionOperationInstance.php';
+
+/**
+ * @see Zend_Service_WindowsAzure_Management_DeploymentInstance
+ */
+require_once 'Zend/Service/WindowsAzure/Management/DeploymentInstance.php';
+
+/**
+ * @see Zend_Service_WindowsAzure_Storage_Blob
+ */
+require_once 'Zend/Service/WindowsAzure/Storage/Blob.php';
+
+/**
+ * @see Zend_Service_WindowsAzure_Storage_Table
+ */
+require_once 'Zend/Service/WindowsAzure/Storage/Table.php';
+
+/**
+ * @see Zend_Service_WindowsAzure_Management_HostedServiceInstance
+ */
+require_once 'Zend/Service/WindowsAzure/Management/HostedServiceInstance.php';
+
+/**
+ * @see Zend_Service_WindowsAzure_Management_CertificateInstance
+ */
+require_once 'Zend/Service/WindowsAzure/Management/CertificateInstance.php';
+
+/**
+ * @see Zend_Service_WindowsAzure_Management_AffinityGroupInstance
+ */
+require_once 'Zend/Service/WindowsAzure/Management/AffinityGroupInstance.php';
+
+/**
+ * @see Zend_Service_WindowsAzure_Management_LocationInstance
+ */
+require_once 'Zend/Service/WindowsAzure/Management/LocationInstance.php';
+
+/**
+ * @see Zend_Service_WindowsAzure_Management_OperatingSystemInstance
+ */
+require_once 'Zend/Service/WindowsAzure/Management/OperatingSystemInstance.php';
+
+/**
+ * @see Zend_Service_WindowsAzure_Management_OperatingSystemFamilyInstance
+ */
+require_once 'Zend/Service/WindowsAzure/Management/OperatingSystemFamilyInstance.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure
+ * @subpackage Management
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Service_WindowsAzure_Management_Client
+{
+	/**
+	 * Management service URL
+	 */
+	const URL_MANAGEMENT        = "https://management.core.windows.net";
+	
+	/**
+	 * Operations
+	 */
+	const OP_OPERATIONS                = "operations";
+	const OP_STORAGE_ACCOUNTS          = "services/storageservices";
+	const OP_HOSTED_SERVICES           = "services/hostedservices";
+	const OP_AFFINITYGROUPS            = "affinitygroups";
+	const OP_LOCATIONS                 = "locations";
+	const OP_OPERATINGSYSTEMS          = "operatingsystems";
+	const OP_OPERATINGSYSTEMFAMILIES   = "operatingsystemfamilies";
+
+	/**
+	 * Current API version
+	 * 
+	 * @var string
+	 */
+	protected $_apiVersion = '2011-02-25';
+	
+	/**
+	 * Subscription ID
+	 *
+	 * @var string
+	 */
+	protected $_subscriptionId = '';
+	
+	/**
+	 * Management certificate path (.PEM)
+	 *
+	 * @var string
+	 */
+	protected $_certificatePath = '';
+	
+	/**
+	 * Management certificate passphrase
+	 *
+	 * @var string
+	 */
+	protected $_certificatePassphrase = '';
+	
+	/**
+	 * Zend_Http_Client channel used for communication with REST services
+	 * 
+	 * @var Zend_Http_Client
+	 */
+	protected $_httpClientChannel = null;	
+
+	/**
+	 * Zend_Service_WindowsAzure_RetryPolicy_RetryPolicyAbstract instance
+	 * 
+	 * @var Zend_Service_WindowsAzure_RetryPolicy_RetryPolicyAbstract
+	 */
+	protected $_retryPolicy = null;
+	
+	/**
+	 * Returns the last request ID
+	 * 
+	 * @var string
+	 */
+	protected $_lastRequestId = null;
+	
+	/**
+	 * Creates a new Zend_Service_WindowsAzure_Management instance
+	 * 
+	 * @param string $subscriptionId Subscription ID
+	 * @param string $certificatePath Management certificate path (.PEM)
+	 * @param string $certificatePassphrase Management certificate passphrase
+     * @param Zend_Service_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy Retry policy to use when making requests
+	 */
+	public function __construct(
+		$subscriptionId,
+		$certificatePath,
+		$certificatePassphrase,
+		Zend_Service_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy = null
+	) {
+		$this->_subscriptionId = $subscriptionId;
+		$this->_certificatePath = $certificatePath;
+		$this->_certificatePassphrase = $certificatePassphrase;
+		
+		$this->_retryPolicy = $retryPolicy;
+		if (is_null($this->_retryPolicy)) {
+		    $this->_retryPolicy = Zend_Service_WindowsAzure_RetryPolicy_RetryPolicyAbstract::noRetry();
+		}
+		
+		// Setup default Zend_Http_Client channel
+		$options = array(
+		    'adapter'       => 'Zend_Http_Client_Adapter_Socket',
+		    'ssltransport'  => 'ssl',
+			'sslcert'       => $this->_certificatePath,
+			'sslpassphrase' => $this->_certificatePassphrase,
+			'sslusecontext' => true,
+		);
+		if (function_exists('curl_init')) {
+			// Set cURL options if cURL is used afterwards
+			$options['curloptions'] = array(
+					CURLOPT_FOLLOWLOCATION => true,
+					CURLOPT_TIMEOUT => 120,
+			);
+		}
+		$this->_httpClientChannel = new Zend_Http_Client(null, $options);
+	}
+	
+	/**
+	 * Set the HTTP client channel to use
+	 * 
+	 * @param Zend_Http_Client_Adapter_Interface|string $adapterInstance Adapter instance or adapter class name.
+	 */
+	public function setHttpClientChannel($adapterInstance = 'Zend_Http_Client_Adapter_Socket')
+	{
+		$this->_httpClientChannel->setAdapter($adapterInstance);
+	}
+	
+    /**
+     * Retrieve HTTP client channel
+     * 
+     * @return Zend_Http_Client_Adapter_Interface
+     */
+    public function getHttpClientChannel()
+    {
+        return $this->_httpClientChannel;
+    }
+	
+	/**
+	 * Returns the Windows Azure subscription ID
+	 * 
+	 * @return string
+	 */
+	public function getSubscriptionId()
+	{
+		return $this->_subscriptionId;
+	}
+	
+	/**
+	 * Returns the last request ID.
+	 * 
+	 * @return string
+	 */
+	public function getLastRequestId()
+	{
+		return $this->_lastRequestId;
+	}
+	
+	/**
+	 * Get base URL for creating requests
+	 *
+	 * @return string
+	 */
+	public function getBaseUrl()
+	{
+		return self::URL_MANAGEMENT . '/' . $this->_subscriptionId;
+	}
+	
+	/**
+	 * Perform request using Zend_Http_Client channel
+	 *
+	 * @param string $path Path
+	 * @param string $queryString Query string
+	 * @param string $httpVerb HTTP verb the request will use
+	 * @param array $headers x-ms headers to add
+	 * @param mixed $rawData Optional RAW HTTP data to be sent over the wire
+	 * @return Zend_Http_Response
+	 */
+	protected function _performRequest(
+		$path = '/',
+		$queryString = '',
+		$httpVerb = Zend_Http_Client::GET,
+		$headers = array(),
+		$rawData = null
+	) {
+	    // Clean path
+		if (strpos($path, '/') !== 0) {
+			$path = '/' . $path;
+		}
+			
+		// Clean headers
+		if (is_null($headers)) {
+		    $headers = array();
+		}
+		
+		// Ensure cUrl will also work correctly:
+		//  - disable Content-Type if required
+		//  - disable Expect: 100 Continue
+		if (!isset($headers["Content-Type"])) {
+			$headers["Content-Type"] = '';
+		}
+		//$headers["Expect"] = '';
+
+		// Add version header
+		$headers['x-ms-version'] = $this->_apiVersion;
+		    
+		// URL encoding
+		$path           = self::urlencode($path);
+		$queryString    = self::urlencode($queryString);
+
+		// Generate URL and sign request
+		$requestUrl     = $this->getBaseUrl() . $path . $queryString;
+		$requestHeaders = $headers;
+
+		// Prepare request 
+		$this->_httpClientChannel->resetParameters(true);
+		$this->_httpClientChannel->setUri($requestUrl);
+		$this->_httpClientChannel->setHeaders($requestHeaders);
+		$this->_httpClientChannel->setRawData($rawData);
+
+		// Execute request
+		$response = $this->_retryPolicy->execute(
+		    array($this->_httpClientChannel, 'request'),
+		    array($httpVerb)
+		);
+		
+		// Store request id
+		$this->_lastRequestId = $response->getHeader('x-ms-request-id');
+		
+		return $response;
+	}
+	
+	/** 
+	 * Parse result from Zend_Http_Response
+	 *
+	 * @param Zend_Http_Response $response Response from HTTP call
+	 * @return object
+	 * @throws Zend_Service_WindowsAzure_Exception
+	 */
+	protected function _parseResponse(Zend_Http_Response $response = null)
+	{
+		if (is_null($response)) {
+			require_once 'Zend/Service/WindowsAzure/Exception.php';
+			throw new Zend_Service_WindowsAzure_Exception('Response should not be null.');
+		}
+		
+        $xml = @simplexml_load_string($response->getBody());
+        
+        if ($xml !== false) {
+            // Fetch all namespaces 
+            $namespaces = array_merge($xml->getNamespaces(true), $xml->getDocNamespaces(true)); 
+            
+            // Register all namespace prefixes
+            foreach ($namespaces as $prefix => $ns) { 
+                if ($prefix != '') {
+                    $xml->registerXPathNamespace($prefix, $ns);
+                } 
+            } 
+        }
+        
+        return $xml;
+	}
+	
+	/**
+	 * URL encode function
+	 * 
+	 * @param  string $value Value to encode
+	 * @return string        Encoded value
+	 */
+	public static function urlencode($value)
+	{
+	    return str_replace(' ', '%20', $value);
+	}
+	
+    /**
+     * Builds a query string from an array of elements
+     * 
+     * @param array     Array of elements
+     * @return string   Assembled query string
+     */
+    public static function createQueryStringFromArray($queryString)
+    {
+    	return count($queryString) > 0 ? '?' . implode('&', $queryString) : '';
+    }
+    
+	/**
+	 * Get error message from Zend_Http_Response
+	 *
+	 * @param Zend_Http_Response $response Repsonse
+	 * @param string $alternativeError Alternative error message
+	 * @return string
+	 */
+	protected function _getErrorMessage(Zend_Http_Response $response, $alternativeError = 'Unknown error.')
+	{
+		$response = $this->_parseResponse($response);
+		if ($response && $response->Message) {
+			return (string)$response->Message;
+		} else {
+			return $alternativeError;
+		}
+	}
+    
+    /**
+     * The Get Operation Status operation returns the status of the specified operation.
+     * After calling an asynchronous operation, you can call Get Operation Status to
+     * determine whether the operation has succeed, failed, or is still in progress.
+     *
+     * @param string $requestId The request ID. If omitted, the last request ID will be used.
+     * @return Zend_Service_WindowsAzure_Management_OperationStatusInstance
+     * @throws Zend_Service_WindowsAzure_Management_Exception
+     */
+    public function getOperationStatus($requestId = '')
+    {
+    	if ($requestId == '') {
+    		$requestId = $this->getLastRequestId();
+    	}
+    	
+    	$response = $this->_performRequest(self::OP_OPERATIONS . '/' . $requestId);
+
+    	if ($response->isSuccessful()) {
+			$result = $this->_parseResponse($response);
+
+			if (!is_null($result)) {
+				return new Zend_Service_WindowsAzure_Management_OperationStatusInstance(
+					(string)$result->ID,
+					(string)$result->Status,
+					($result->Error ? (string)$result->Error->Code : ''),
+					($result->Error ? (string)$result->Error->Message : '')
+				);
+			}
+			return null;
+		} else {
+			require_once 'Zend/Service/Management/Exception.php';
+			throw new Zend_Service_WindowsAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
+		}
+    }
+    
+
+    
+    /**
+     * The List Subscription Operations operation returns a list of create, update,
+     * and delete operations that were performed on a subscription during the specified timeframe.
+     * Documentation on the parameters can be found at http://msdn.microsoft.com/en-us/library/gg715318.aspx.
+     *
+     * @param string $startTime The start of the timeframe to begin listing subscription operations in UTC format. This parameter and the $endTime parameter indicate the timeframe to retrieve subscription operations. This parameter cannot indicate a start date of more than 90 days in the past.
+     * @param string $endTime The end of the timeframe to begin listing subscription operations in UTC format. This parameter and the $startTime parameter indicate the timeframe to retrieve subscription operations. 
+     * @param string $objectIdFilter Returns subscription operations only for the specified object type and object ID. 
+     * @param string $operationResultFilter Returns subscription operations only for the specified result status, either Succeeded, Failed, or InProgress.
+     * @param string $continuationToken Internal usage.
+     * @return array Array of Zend_Service_WindowsAzure_Management_SubscriptionOperationInstance
+     * @throws Zend_Service_WindowsAzure_Management_Exception
+     */
+    public function listSubscriptionOperations($startTime, $endTime, $objectIdFilter = null, $operationResultFilter = null, $continuationToken = null)
+    {
+    	if ($startTime == '' || is_null($startTime)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Start time should be specified.');
+    	}
+    	if ($endTime == '' || is_null($endTime)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('End time should be specified.');
+    	}
+    	if ($operationResultFilter != '' && !is_null($operationResultFilter)) {
+	        $operationResultFilter = strtolower($operationResultFilter);
+	    	if ($operationResultFilter != 'succeeded' && $operationResultFilter != 'failed' && $operationResultFilter != 'inprogress') {
+				require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+	    		throw new Zend_Service_WindowsAzure_Management_Exception('OperationResultFilter should be succeeded|failed|inprogress.');
+	    	}
+    	}
+    	
+    	$parameters = array();
+    	$parameters[] = 'StartTime=' . $startTime;
+    	$parameters[] = 'EndTime=' . $endTime;
+    	if ($objectIdFilter != '' && !is_null($objectIdFilter)) {
+    		$parameters[] = 'ObjectIdFilter=' . $objectIdFilter;
+    	}
+    	if ($operationResultFilter != '' && !is_null($operationResultFilter)) {
+    		$parameters[] = 'OperationResultFilter=' . ucfirst($operationResultFilter);
+    	}
+    	if ($continuationToken != '' && !is_null($continuationToken)) {
+    		$parameters[] = 'ContinuationToken=' . $continuationToken;
+    	}
+    	
+    	$response = $this->_performRequest(self::OP_OPERATIONS, '?' . implode('&', $parameters));
+
+    	if ($response->isSuccessful()) {
+			$result = $this->_parseResponse($response);
+			$namespaces = $result->getDocNamespaces(); 
+    		$result->registerXPathNamespace('__empty_ns', $namespaces['']);
+ 
+			$xmlOperations = $result->xpath('//__empty_ns:SubscriptionOperation');
+			
+		    // Create return value
+		    $returnValue = array();		    
+		    foreach ($xmlOperations as $xmlOperation) {
+		    	// Create operation instance
+		    	$operation = new Zend_Service_WindowsAzure_Management_SubscriptionOperationInstance(
+		    		$xmlOperation->OperationId,
+		    		$xmlOperation->OperationObjectId,
+		    		$xmlOperation->OperationName,
+		    		array(),
+		    		(array)$xmlOperation->OperationCaller,
+		    		(array)$xmlOperation->OperationStatus
+		    	);
+		    	
+		    	// Parse parameters
+		    	$xmlOperation->registerXPathNamespace('__empty_ns', $namespaces['']); 
+		    	$xmlParameters = $xmlOperation->xpath('.//__empty_ns:OperationParameter');
+		    	foreach ($xmlParameters as $xmlParameter) {
+		    		$xmlParameterDetails = $xmlParameter->children('http://schemas.datacontract.org/2004/07/Microsoft.Samples.WindowsAzure.ServiceManagement');
+		    		$operation->addOperationParameter((string)$xmlParameterDetails->Name, (string)$xmlParameterDetails->Value);
+		    	}
+		    	
+    		    // Add to result
+    		    $returnValue[] = $operation;
+		    }
+		    
+			// More data?
+		    if (!is_null($result->ContinuationToken) && $result->ContinuationToken != '') {
+		    	$returnValue = array_merge($returnValue, $this->listSubscriptionOperations($startTime, $endTime, $objectIdFilter, $operationResultFilter, (string)$result->ContinuationToken));
+		    }
+		    
+		    // Return
+		    return $returnValue;
+		} else {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+			throw new Zend_Service_WindowsAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
+		}
+    }
+    
+    /**
+     * Wait for an operation to complete
+     * 
+     * @param string $requestId The request ID. If omitted, the last request ID will be used.
+     * @param int $sleepInterval Sleep interval in milliseconds.
+     * @return Zend_Service_WindowsAzure_Management_OperationStatusInstance
+     * @throws Zend_Service_WindowsAzure_Management_Exception
+     */
+    public function waitForOperation($requestId = '', $sleepInterval = 250)
+    {
+    	if ($requestId == '') {
+    		$requestId = $this->getLastRequestId();
+    	}
+    	if ($requestId == '' || is_null($requestId)) {
+    		return null;
+    	}
+
+		$status = $this->getOperationStatus($requestId);
+		while ($status->Status == 'InProgress') {
+		  $status = $this->getOperationStatus($requestId);
+		  usleep($sleepInterval);
+		}
+		
+		return $status;
+    }
+    
+	/**
+	 * Creates a new Zend_Service_WindowsAzure_Storage_Blob instance for the current account
+	 *
+	 * @param string $serviceName the service name to create a storage client for.
+	 * @param Zend_Service_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy Retry policy to use when making requests
+	 * @return Zend_Service_WindowsAzure_Storage_Blob
+	 */
+	public function createBlobClientForService($serviceName, Zend_Service_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy = null)
+	{
+		if ($serviceName == '' || is_null($serviceName)) {
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Service name should be specified.');
+    	}
+    	
+    	$storageKeys = $this->getStorageAccountKeys($serviceName);
+    	
+		
+		
+		return new Zend_Service_WindowsAzure_Storage_Blob(
+			Zend_Service_WindowsAzure_Storage::URL_CLOUD_BLOB,
+			$serviceName,
+			$storageKeys[0],
+			false,
+			$retryPolicy
+		);
+	}
+	
+	/**
+	 * Creates a new Zend_Service_WindowsAzure_Storage_Table instance for the current account
+	 *
+	 * @param string $serviceName the service name to create a storage client for.
+	 * @param Zend_Service_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy Retry policy to use when making requests
+	 * @return Zend_Service_WindowsAzure_Storage_Table
+	 */
+	public function createTableClientForService($serviceName, Zend_Service_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy = null)
+	{
+		if ($serviceName == '' || is_null($serviceName)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Service name should be specified.');
+    	}
+    	
+    	$storageKeys = $this->getStorageAccountKeys($serviceName);
+		
+		return new Zend_Service_WindowsAzure_Storage_Table(
+			Zend_Service_WindowsAzure_Storage::URL_CLOUD_TABLE,
+			$serviceName,
+			$storageKeys[0],
+			false,
+			$retryPolicy
+		);
+	}
+	
+	/**
+	 * Creates a new Zend_Service_WindowsAzure_Storage_Queue instance for the current account
+	 *
+	 * @param string $serviceName the service name to create a storage client for.
+	 * @param Zend_Service_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy Retry policy to use when making requests
+	 * @return Zend_Service_WindowsAzure_Storage_Queue
+	 */
+	public function createQueueClientForService($serviceName, Zend_Service_WindowsAzure_RetryPolicy_RetryPolicyAbstract $retryPolicy = null)
+	{
+		if ($serviceName == '' || is_null($serviceName)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Service name should be specified.');
+    	}
+    	
+    	$storageKeys = $this->getStorageAccountKeys($serviceName);
+    	
+		require_once 'Zend/Service/WindowsAzure/Storage/Queue.php';
+		
+		return new Zend_Service_WindowsAzure_Storage_Queue(
+			Zend_Service_WindowsAzure_Storage::URL_CLOUD_QUEUE,
+			$serviceName,
+			$storageKeys[0],
+			false,
+			$retryPolicy
+		);
+	}
+    
+    /**
+     * The List Storage Accounts operation lists the storage accounts available under
+     * the current subscription.
+     *
+     * @return array An array of Zend_Service_WindowsAzure_Management_StorageServiceInstance
+     */
+    public function listStorageAccounts()
+    {
+    	$response = $this->_performRequest(self::OP_STORAGE_ACCOUNTS);
+
+    	if ($response->isSuccessful()) {
+			$result = $this->_parseResponse($response);
+			
+    		if (!$result->StorageService) {
+				return array();
+			}
+		    if (count($result->StorageService) > 1) {
+    		    $xmlServices = $result->StorageService;
+    		} else {
+    		    $xmlServices = array($result->StorageService);
+    		}
+    		
+			$services = array();
+			if (!is_null($xmlServices)) {				
+				for ($i = 0; $i < count($xmlServices); $i++) {
+					$services[] = new Zend_Service_WindowsAzure_Management_StorageServiceInstance(
+					    (string)$xmlServices[$i]->Url,
+					    (string)$xmlServices[$i]->ServiceName
+					);
+				}
+			}
+			return $services;
+		} else {
+			throw new Zend_Service_WindowsAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
+		}
+    }
+    
+    /**
+     * The Get Storage Account Properties operation returns the system properties for the
+     * specified storage account. These properties include: the address, description, and 
+     * label of the storage account; and the name of the affinity group to which the service
+     * belongs, or its geo-location if it is not part of an affinity group.
+     *
+     * @param string $serviceName The name of your service.
+     * @return Zend_Service_WindowsAzure_Management_StorageServiceInstance
+     * @throws Zend_Service_WindowsAzure_Management_Exception
+     */
+    public function getStorageAccountProperties($serviceName)
+    {
+    	if ($serviceName == '' || is_null($serviceName)) {
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Service name should be specified.');
+    	}
+    	
+    	$response = $this->_performRequest(self::OP_STORAGE_ACCOUNTS . '/' . $serviceName);
+
+    	if ($response->isSuccessful()) {
+			$xmlService = $this->_parseResponse($response);
+
+			if (!is_null($xmlService)) {
+				require_once 'Zend/Service/WindowsAzure/Management/StorageServiceInstance.php';
+				
+				return new Zend_Service_WindowsAzure_Management_StorageServiceInstance(
+					(string)$xmlService->Url,
+					(string)$xmlService->ServiceName,
+					(string)$xmlService->StorageServiceProperties->Description,
+					(string)$xmlService->StorageServiceProperties->AffinityGroup,
+					(string)$xmlService->StorageServiceProperties->Location,
+					(string)$xmlService->StorageServiceProperties->Label
+				);
+			}
+			return null;
+		} else {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+			throw new Zend_Service_WindowsAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
+		}
+    }
+    
+    /**
+     * The Get Storage Keys operation returns the primary
+     * and secondary access keys for the specified storage account.
+     *
+     * @param string $serviceName The name of your service.
+     * @return array An array of strings
+     * @throws Zend_Service_WindowsAzure_Management_Exception
+     */
+    public function getStorageAccountKeys($serviceName)
+    {
+    	if ($serviceName == '' || is_null($serviceName)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Service name should be specified.');
+    	}
+    	
+    	$response = $this->_performRequest(self::OP_STORAGE_ACCOUNTS . '/' . $serviceName . '/keys');
+
+    	if ($response->isSuccessful()) {
+			$xmlService = $this->_parseResponse($response);
+
+			if (!is_null($xmlService)) {
+				return array(
+					(string)$xmlService->StorageServiceKeys->Primary,
+					(string)$xmlService->StorageServiceKeys->Secondary
+				);
+			}
+			return array();
+		} else {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+			throw new Zend_Service_WindowsAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
+		}
+    }
+    
+    /**
+     * The Regenerate Keys operation regenerates the primary
+     * or secondary access key for the specified storage account.
+     *
+     * @param string $serviceName The name of your service.
+     * @param string $key		  The key to regenerate (primary or secondary)
+     * @return array An array of strings
+     * @throws Zend_Service_WindowsAzure_Management_Exception
+     */
+    public function regenerateStorageAccountKey($serviceName, $key = 'primary')
+    {
+    	if ($serviceName == '' || is_null($serviceName)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Service name should be specified.');
+    	}
+    	$key = strtolower($key);
+    	if ($key != 'primary' && $key != 'secondary') {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Key identifier should be primary|secondary.');
+    	}
+    	
+    	$response = $this->_performRequest(
+    		self::OP_STORAGE_ACCOUNTS . '/' . $serviceName . '/keys', '?action=regenerate',
+    		Zend_Http_Client::POST,
+    		array('Content-Type' => 'application/xml'),
+    		'<?xml version="1.0" encoding="utf-8"?>
+             <RegenerateKeys xmlns="http://schemas.microsoft.com/windowsazure">
+               <KeyType>' . ucfirst($key) . '</KeyType>
+             </RegenerateKeys>');
+
+    	if ($response->isSuccessful()) {
+			$xmlService = $this->_parseResponse($response);
+
+			if (!is_null($xmlService)) {
+				return array(
+					(string)$xmlService->StorageServiceKeys->Primary,
+					(string)$xmlService->StorageServiceKeys->Secondary
+				);
+			}
+			return array();
+		} else {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+			throw new Zend_Service_WindowsAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
+		}
+    }
+    
+    /**
+     * The List Hosted Services operation lists the hosted services available
+     * under the current subscription.
+     *
+     * @return array An array of Zend_Service_WindowsAzure_Management_HostedServiceInstance
+     * @throws Zend_Service_WindowsAzure_Management_Exception
+     */
+    public function listHostedServices()
+    {
+    	$response = $this->_performRequest(self::OP_HOSTED_SERVICES);
+
+    	if ($response->isSuccessful()) {
+			$result = $this->_parseResponse($response);
+			
+    		if (!$result->HostedService) {
+				return array();
+			}
+		    if (count($result->HostedService) > 1) {
+    		    $xmlServices = $result->HostedService;
+    		} else {
+    		    $xmlServices = array($result->HostedService);
+    		}
+    		
+			$services = array();
+			if (!is_null($xmlServices)) {	
+				
+				for ($i = 0; $i < count($xmlServices); $i++) {
+					$services[] = new Zend_Service_WindowsAzure_Management_HostedServiceInstance(
+					    (string)$xmlServices[$i]->Url,
+					    (string)$xmlServices[$i]->ServiceName
+					);
+				}
+			}
+			return $services;
+		} else {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+			throw new Zend_Service_WindowsAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
+		}
+    }
+    
+    /**
+     * The Create Hosted Service operation creates a new hosted service in Windows Azure.
+     * 
+     * @param string $serviceName A name for the hosted service that is unique to the subscription.
+     * @param string $label A label for the hosted service. The label may be up to 100 characters in length.
+     * @param string $description A description for the hosted service. The description may be up to 1024 characters in length.
+     * @param string $location Required if AffinityGroup is not specified. The location where the hosted service will be created. 
+     * @param string $affinityGroup Required if Location is not specified. The name of an existing affinity group associated with this subscription.
+     */
+    public function createHostedService($serviceName, $label, $description = '', $location = null, $affinityGroup = null)
+    {
+    	if ($serviceName == '' || is_null($serviceName)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Service name should be specified.');
+    	}
+    	if ($label == '' || is_null($label)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Label should be specified.');
+    	}
+        if (strlen($label) > 100) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Label is too long. The maximum length is 100 characters.');
+    	}
+        if (strlen($description) > 1024) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Description is too long. The maximum length is 1024 characters.');
+    	}
+    	if ( (is_null($location) && is_null($affinityGroup)) || (!is_null($location) && !is_null($affinityGroup)) ) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Please specify a location -or- an affinity group for the service.');
+    	}
+    	
+    	$locationOrAffinityGroup = is_null($location)
+    		? '<AffinityGroup>' . $affinityGroup . '</AffinityGroup>'
+    		: '<Location>' . $location . '</Location>';
+    	
+        $response = $this->_performRequest(self::OP_HOSTED_SERVICES, '',
+    		Zend_Http_Client::POST,
+    		array('Content-Type' => 'application/xml; charset=utf-8'),
+    		'<CreateHostedService xmlns="http://schemas.microsoft.com/windowsazure"><ServiceName>' . $serviceName . '</ServiceName><Label>' . base64_encode($label) . '</Label><Description>' . $description . '</Description>' . $locationOrAffinityGroup . '</CreateHostedService>');
+ 	
+    	if (!$response->isSuccessful()) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+			throw new Zend_Service_WindowsAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
+		}
+    }
+    
+    /**
+     * The Update Hosted Service operation updates the label and/or the description for a hosted service in Windows Azure.
+     * 
+     * @param string $serviceName A name for the hosted service that is unique to the subscription.
+     * @param string $label A label for the hosted service. The label may be up to 100 characters in length.
+     * @param string $description A description for the hosted service. The description may be up to 1024 characters in length.
+     */
+    public function updateHostedService($serviceName, $label, $description = '')
+    {
+    	if ($serviceName == '' || is_null($serviceName)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Service name should be specified.');
+    	}
+    	if ($label == '' || is_null($label)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Label should be specified.');
+    	}
+        if (strlen($label) > 100) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Label is too long. The maximum length is 100 characters.');
+    	}
+    	
+        $response = $this->_performRequest(self::OP_HOSTED_SERVICES . '/' . $serviceName, '',
+    		Zend_Http_Client::PUT,
+    		array('Content-Type' => 'application/xml; charset=utf-8'),
+    		'<UpdateHostedService xmlns="http://schemas.microsoft.com/windowsazure"><Label>' . base64_encode($label) . '</Label><Description>' . $description . '</Description></UpdateHostedService>');
+ 	
+    	if (!$response->isSuccessful()) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+			throw new Zend_Service_WindowsAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
+		}
+    }
+    
+    /**
+     * The Delete Hosted Service operation deletes the specified hosted service in Windows Azure.
+     * 
+     * @param string $serviceName A name for the hosted service that is unique to the subscription.
+     */
+    public function deleteHostedService($serviceName)
+    {
+    	if ($serviceName == '' || is_null($serviceName)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Service name should be specified.');
+    	}
+    	
+        $response = $this->_performRequest(self::OP_HOSTED_SERVICES . '/' . $serviceName, '', Zend_Http_Client::DELETE);
+ 	
+    	if (!$response->isSuccessful()) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+			throw new Zend_Service_WindowsAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
+		}
+    }
+    
+    /**
+     * The Get Hosted Service Properties operation retrieves system properties
+     * for the specified hosted service. These properties include the service
+     * name and service type; the name of the affinity group to which the service
+     * belongs, or its location if it is not part of an affinity group; and
+     * optionally, information on the service's deployments.
+     *
+     * @param string $serviceName The name of your service.
+     * @return Zend_Service_WindowsAzure_Management_HostedServiceInstance
+     * @throws Zend_Service_WindowsAzure_Management_Exception
+     */
+    public function getHostedServiceProperties($serviceName)
+    {
+    	if ($serviceName == '' || is_null($serviceName)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Service name should be specified.');
+    	}
+    	
+    	$response = $this->_performRequest(self::OP_HOSTED_SERVICES . '/' . $serviceName, '?embed-detail=true');
+
+    	if ($response->isSuccessful()) {
+			$xmlService = $this->_parseResponse($response);
+
+			if (!is_null($xmlService)) {
+				
+				$returnValue = new Zend_Service_WindowsAzure_Management_HostedServiceInstance(
+					(string)$xmlService->Url,
+					(string)$xmlService->ServiceName,
+					(string)$xmlService->HostedServiceProperties->Description,
+					(string)$xmlService->HostedServiceProperties->AffinityGroup,
+					(string)$xmlService->HostedServiceProperties->Location,
+					(string)$xmlService->HostedServiceProperties->Label
+				);
+				
+				// Deployments
+		    	if (count($xmlService->Deployments->Deployment) > 1) {
+    		    	$xmlServices = $xmlService->Deployments->Deployment;
+    			} else {
+    		    	$xmlServices = array($xmlService->Deployments->Deployment);
+    			}
+    			
+    			$deployments = array();
+    			foreach ($xmlServices as $xmlDeployment) {
+					$deployments[] = $this->_convertXmlElementToDeploymentInstance($xmlDeployment);
+    			}
+				$returnValue->Deployments = $deployments;
+				
+				return $returnValue;
+			}
+			return null;
+		} else {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+			throw new Zend_Service_WindowsAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
+		}
+    }
+
+    /**
+     * The Create Deployment operation uploads a new service package
+     * and creates a new deployment on staging or production.
+     * 
+     * @param string $serviceName		The service name
+     * @param string $deploymentSlot	The deployment slot (production or staging)
+	 * @param string $name              The name for the deployment. The deployment ID as listed on the Windows Azure management portal must be unique among other deployments for the hosted service.
+	 * @param string $label             A URL that refers to the location of the service package in the Blob service. The service package must be located in a storage account beneath the same subscription.
+	 * @param string $packageUrl        The service configuration file for the deployment.
+	 * @param string $configuration     A label for this deployment, up to 100 characters in length.
+	 * @param boolean $startDeployment  Indicates whether to start the deployment immediately after it is created.
+	 * @param boolean $treatWarningsAsErrors Indicates whether to treat package validation warnings as errors.
+     * @throws Zend_Service_WindowsAzure_Management_Exception
+     */
+    public function createDeployment($serviceName, $deploymentSlot, $name, $label, $packageUrl, $configuration, $startDeployment = false, $treatWarningsAsErrors = false)
+    {
+        if ($serviceName == '' || is_null($serviceName)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Service name should be specified.');
+    	}
+    	$deploymentSlot = strtolower($deploymentSlot);
+    	if ($deploymentSlot != 'production' && $deploymentSlot != 'staging') {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Deployment slot should be production|staging.');
+    	}
+    	if ($name == '' || is_null($name)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Name should be specified.');
+    	}
+    	if ($label == '' || is_null($label)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Label should be specified.');
+    	}
+        if (strlen($label) > 100) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Label is too long. The maximum length is 100 characters.');
+    	}
+    	if ($packageUrl == '' || is_null($packageUrl)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Package URL should be specified.');
+    	}
+    	if ($configuration == '' || is_null($configuration)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Configuration should be specified.');
+    	}
+    	
+    	if (@file_exists($configuration)) {
+    		$configuration = utf8_decode(file_get_contents($configuration));
+    	}
+    	
+    	// Clean up the configuration
+    	$conformingConfiguration = $this->_cleanConfiguration($configuration);
+    	
+    	$operationUrl = self::OP_HOSTED_SERVICES . '/' . $serviceName . '/deploymentslots/' . $deploymentSlot;
+        $response = $this->_performRequest($operationUrl, '',
+    		Zend_Http_Client::POST,
+    		array('Content-Type' => 'application/xml; charset=utf-8'),
+    		'<CreateDeployment xmlns="http://schemas.microsoft.com/windowsazure"><Name>' . $name . '</Name><PackageUrl>' . $packageUrl . '</PackageUrl><Label>' . base64_encode($label) . '</Label><Configuration>' . base64_encode($conformingConfiguration) . '</Configuration><StartDeployment>' . ($startDeployment ? 'true' : 'false') . '</StartDeployment><TreatWarningsAsError>' . ($treatWarningsAsErrors ? 'true' : 'false') . '</TreatWarningsAsError></CreateDeployment>');
+ 	
+    	if (!$response->isSuccessful()) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+			throw new Zend_Service_WindowsAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
+		}    	
+    }
+    
+    /**
+     * The Get Deployment operation returns configuration information, status,
+     * and system properties for the specified deployment.
+     * 
+     * @param string $serviceName		The service name
+     * @param string $deploymentSlot	The deployment slot (production or staging)
+     * @return Zend_Service_WindowsAzure_Management_DeploymentInstance
+     * @throws Zend_Service_WindowsAzure_Management_Exception
+     */
+    public function getDeploymentBySlot($serviceName, $deploymentSlot)
+    {
+        if ($serviceName == '' || is_null($serviceName)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Service name should be specified.');
+    	}
+    	$deploymentSlot = strtolower($deploymentSlot);
+    	if ($deploymentSlot != 'production' && $deploymentSlot != 'staging') {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Deployment slot should be production|staging.');
+    	}
+    	
+    	$operationUrl = self::OP_HOSTED_SERVICES . '/' . $serviceName . '/deploymentslots/' . $deploymentSlot;
+    	return $this->_getDeployment($operationUrl);
+    }
+    
+    /**
+     * The Get Deployment operation returns configuration information, status,
+     * and system properties for the specified deployment.
+     * 
+     * @param string $serviceName		The service name
+     * @param string $deploymentId	The deployment ID as listed on the Windows Azure management portal
+     * @return Zend_Service_WindowsAzure_Management_DeploymentInstance
+     * @throws Zend_Service_WindowsAzure_Management_Exception
+     */
+    public function getDeploymentByDeploymentId($serviceName, $deploymentId)
+    {
+        if ($serviceName == '' || is_null($serviceName)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Service name should be specified.');
+    	}
+        if ($deploymentId == '' || is_null($deploymentId)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Deployment ID should be specified.');
+    	}
+    	
+    	$operationUrl = self::OP_HOSTED_SERVICES . '/' . $serviceName . '/deployments/' . $deploymentId;
+    	return $this->_getDeployment($operationUrl);
+    }
+    
+    /**
+     * The Get Deployment operation returns configuration information, status,
+     * and system properties for the specified deployment.
+     * 
+     * @param string $operationUrl		The operation url
+     * @return Zend_Service_WindowsAzure_Management_DeploymentInstance
+     * @throws Zend_Service_WindowsAzure_Management_Exception
+     */
+    protected function _getDeployment($operationUrl)
+    {
+        $response = $this->_performRequest($operationUrl);
+
+    	if ($response->isSuccessful()) {
+			$xmlService = $this->_parseResponse($response);
+			
+			return $this->_convertXmlElementToDeploymentInstance($xmlService);
+		} else {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+			throw new Zend_Service_WindowsAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
+		}
+    }
+    
+    /**
+     * The Swap Deployment operation initiates a virtual IP swap between
+     * the staging and production deployment environments for a service.
+     * If the service is currently running in the staging environment,
+     * it will be swapped to the production environment. If it is running
+     * in the production environment, it will be swapped to staging.
+     * 
+     * @param string $serviceName The service name.
+     * @param string $productionDeploymentName The name of the production deployment.
+     * @param string $sourceDeploymentName The name of the source deployment.
+     * @throws Zend_Service_WindowsAzure_Management_Exception
+     */
+    public function swapDeployment($serviceName, $productionDeploymentName, $sourceDeploymentName)
+    {
+    	if ($serviceName == '' || is_null($serviceName)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Service name should be specified.');
+    	}
+    	if ($productionDeploymentName == '' || is_null($productionDeploymentName)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Production Deployment ID should be specified.');
+    	}
+    	if ($sourceDeploymentName == '' || is_null($sourceDeploymentName)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Source Deployment ID should be specified.');
+    	}
+    	
+    	$operationUrl = self::OP_HOSTED_SERVICES . '/' . $serviceName;
+        $response = $this->_performRequest($operationUrl, '',
+    		Zend_Http_Client::POST,
+    		array('Content-Type' => 'application/xml; charset=utf-8'),
+    		'<Swap xmlns="http://schemas.microsoft.com/windowsazure"><Production>' . $productionDeploymentName . '</Production><SourceDeployment>' . $sourceDeploymentName . '</SourceDeployment></Swap>');
+    		
+    	if (!$response->isSuccessful()) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+			throw new Zend_Service_WindowsAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
+		}    	
+    }
+    
+    /**
+     * The Delete Deployment operation deletes the specified deployment.
+     * 
+     * @param string $serviceName		The service name
+     * @param string $deploymentSlot	The deployment slot (production or staging)
+     * @throws Zend_Service_WindowsAzure_Management_Exception
+     */
+    public function deleteDeploymentBySlot($serviceName, $deploymentSlot)
+    {
+        if ($serviceName == '' || is_null($serviceName)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Service name should be specified.');
+    	}
+    	$deploymentSlot = strtolower($deploymentSlot);
+    	if ($deploymentSlot != 'production' && $deploymentSlot != 'staging') {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Deployment slot should be production|staging.');
+    	}
+    	
+    	$operationUrl = self::OP_HOSTED_SERVICES . '/' . $serviceName . '/deploymentslots/' . $deploymentSlot;
+    	return $this->_deleteDeployment($operationUrl);
+    }
+    
+    /**
+     * The Delete Deployment operation deletes the specified deployment.
+     * 
+     * @param string $serviceName		The service name
+     * @param string $deploymentId	The deployment ID as listed on the Windows Azure management portal
+     * @throws Zend_Service_WindowsAzure_Management_Exception
+     */
+    public function deleteDeploymentByDeploymentId($serviceName, $deploymentId)
+    {
+        if ($serviceName == '' || is_null($serviceName)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Service name should be specified.');
+    	}
+    	if ($deploymentId == '' || is_null($deploymentId)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Deployment ID should be specified.');
+    	}
+    	
+    	$operationUrl = self::OP_HOSTED_SERVICES . '/' . $serviceName . '/deployments/' . $deploymentId;
+    	return $this->_deleteDeployment($operationUrl);
+    }
+    
+    /**
+     * The Delete Deployment operation deletes the specified deployment.
+     * 
+     * @param string $operationUrl		The operation url
+     * @throws Zend_Service_WindowsAzure_Management_Exception
+     */
+    protected function _deleteDeployment($operationUrl)
+    {
+        $response = $this->_performRequest($operationUrl, '', Zend_Http_Client::DELETE);
+			 
+    	if (!$response->isSuccessful()) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+			throw new Zend_Service_WindowsAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
+		}
+    }
+    
+    /**
+     * The Update Deployment Status operation initiates a change in deployment status.
+     * 
+     * @param string $serviceName		The service name
+     * @param string $deploymentSlot	The deployment slot (production or staging)
+     * @param string $status            The deployment status (running|suspended)
+     * @throws Zend_Service_WindowsAzure_Management_Exception
+     */
+    public function updateDeploymentStatusBySlot($serviceName, $deploymentSlot, $status = 'running')
+    {
+        if ($serviceName == '' || is_null($serviceName)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Service name should be specified.');
+    	}
+    	$deploymentSlot = strtolower($deploymentSlot);
+    	if ($deploymentSlot != 'production' && $deploymentSlot != 'staging') {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Deployment slot should be production|staging.');
+    	}
+    	$status = strtolower($status);
+    	if ($status != 'running' && $status != 'suspended') {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Status should be running|suspended.');
+    	}
+    	
+    	$operationUrl = self::OP_HOSTED_SERVICES . '/' . $serviceName . '/deploymentslots/' . $deploymentSlot;
+    	return $this->_updateDeploymentStatus($operationUrl, $status);
+    }
+    
+    /**
+     * The Update Deployment Status operation initiates a change in deployment status.
+     * 
+     * @param string $serviceName		The service name
+     * @param string $deploymentId	The deployment ID as listed on the Windows Azure management portal
+     * @param string $status            The deployment status (running|suspended)
+     * @throws Zend_Service_WindowsAzure_Management_Exception
+     */
+    public function updateDeploymentStatusByDeploymentId($serviceName, $deploymentId, $status = 'running')
+    {
+        if ($serviceName == '' || is_null($serviceName)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Service name should be specified.');
+    	}
+    	if ($deploymentId == '' || is_null($deploymentId)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Deployment ID should be specified.');
+    	}
+        $status = strtolower($status);
+    	if ($status != 'running' && $status != 'suspended') {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Status should be running|suspended.');
+    	}
+    	
+    	$operationUrl = self::OP_HOSTED_SERVICES . '/' . $serviceName . '/deployments/' . $deploymentId;
+    	return $this->_updateDeploymentStatus($operationUrl, $status);
+    }
+    
+    /**
+     * The Update Deployment Status operation initiates a change in deployment status.
+     * 
+     * @param string $operationUrl		The operation url
+     * @param string $status            The deployment status (running|suspended)
+     * @throws Zend_Service_WindowsAzure_Management_Exception
+     */
+    protected function _updateDeploymentStatus($operationUrl, $status = 'running')
+    {
+        $response = $this->_performRequest($operationUrl . '/', '?comp=status',
+    		Zend_Http_Client::POST,
+    		array('Content-Type' => 'application/xml; charset=utf-8'),
+    		'<UpdateDeploymentStatus xmlns="http://schemas.microsoft.com/windowsazure"><Status>' . ucfirst($status) . '</Status></UpdateDeploymentStatus>');
+    		
+    	if (!$response->isSuccessful()) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+			throw new Zend_Service_WindowsAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
+		}
+    }
+    
+    /**
+     * Converts an XmlElement into a Zend_Service_WindowsAzure_Management_DeploymentInstance
+     * 
+     * @param object $xmlService The XML Element
+     * @return Zend_Service_WindowsAzure_Management_DeploymentInstance
+     * @throws Zend_Service_WindowsAzure_Management_Exception
+     */
+    protected function _convertXmlElementToDeploymentInstance($xmlService)
+    {
+		if (!is_null($xmlService)) {
+			
+			$returnValue = new Zend_Service_WindowsAzure_Management_DeploymentInstance(
+				(string)$xmlService->Name,
+				(string)$xmlService->DeploymentSlot,
+				(string)$xmlService->PrivateID,
+				(string)$xmlService->Label,
+				(string)$xmlService->Url,
+				(string)$xmlService->Configuration,
+				(string)$xmlService->Status,
+				(string)$xmlService->UpgradeStatus,
+				(string)$xmlService->UpgradeType,
+				(string)$xmlService->CurrentUpgradeDomainState,
+				(string)$xmlService->CurrentUpgradeDomain,
+				(string)$xmlService->UpgradeDomainCount
+			);
+				
+			// Append role instances
+			if ($xmlService->RoleInstanceList && $xmlService->RoleInstanceList->RoleInstance) {
+				$xmlRoleInstances = $xmlService->RoleInstanceList->RoleInstance;
+				if (count($xmlService->RoleInstanceList->RoleInstance) == 1) {
+		    	    $xmlRoleInstances = array($xmlService->RoleInstanceList->RoleInstance);
+		    	}
+		    		
+				$roleInstances = array();
+				if (!is_null($xmlRoleInstances)) {				
+					for ($i = 0; $i < count($xmlRoleInstances); $i++) {
+						$roleInstances[] = array(
+						    'rolename' => (string)$xmlRoleInstances[$i]->RoleName,
+						    'instancename' => (string)$xmlRoleInstances[$i]->InstanceName,
+						    'instancestatus' => (string)$xmlRoleInstances[$i]->InstanceStatus
+						);
+					}
+				}
+				
+				$returnValue->RoleInstanceList = $roleInstances;
+			}
+			
+			// Append roles
+			if ($xmlService->RoleList && $xmlService->RoleList->Role) {
+				$xmlRoles = $xmlService->RoleList->Role;
+				if (count($xmlService->RoleList->Role) == 1) {
+		    	    $xmlRoles = array($xmlService->RoleList->Role);
+		    	}
+	    		
+				$roles = array();
+				if (!is_null($xmlRoles)) {				
+					for ($i = 0; $i < count($xmlRoles); $i++) {
+						$roles[] = array(
+						    'rolename' => (string)$xmlRoles[$i]->RoleName,
+						    'osversion' => (!is_null($xmlRoles[$i]->OsVersion) ? (string)$xmlRoles[$i]->OsVersion : (string)$xmlRoles[$i]->OperatingSystemVersion)					
+						);
+					}
+				}
+				$returnValue->RoleList = $roles;
+			}
+				
+			return $returnValue;
+		}
+		return null;
+    }
+    
+    /**
+     * Updates a deployment's role instance count.
+     * 
+     * @param string $serviceName		The service name
+     * @param string $deploymentSlot	The deployment slot (production or staging)
+     * @param string|array $roleName	The role name
+     * @param string|array $instanceCount The instance count
+     * @throws Zend_Service_WindowsAzure_Management_Exception
+     */
+	public function setInstanceCountBySlot($serviceName, $deploymentSlot, $roleName, $instanceCount) {
+	    if ($serviceName == '' || is_null($serviceName)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Service name should be specified.');
+    	}
+    	$deploymentSlot = strtolower($deploymentSlot);
+    	if ($deploymentSlot != 'production' && $deploymentSlot != 'staging') {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Deployment slot should be production|staging.');
+    	}
+    	if ($roleName == '' || is_null($roleName)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Role name name should be specified.');
+    	}
+    	
+		// Get configuration
+		$deployment = $this->getDeploymentBySlot($serviceName, $deploymentSlot);
+		$configuration = $deployment->Configuration;
+		$configuration = $this->_updateInstanceCountInConfiguration($roleName, $instanceCount, $configuration);
+		
+		// Update configuration
+		$this->configureDeploymentBySlot($serviceName, $deploymentSlot, $configuration);		
+	}
+	
+    /**
+     * Updates a deployment's role instance count.
+     * 
+     * @param string $serviceName		The service name
+     * @param string $deploymentSlot	The deployment slot (production or staging)
+     * @param string|array $roleName	The role name
+     * @param string|array $instanceCount The instance count
+     * @throws Zend_Service_WindowsAzure_Management_Exception
+     */
+    public function setInstanceCountByDeploymentId($serviceName, $deploymentId, $roleName, $instanceCount)
+    {
+	    if ($serviceName == '' || is_null($serviceName)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Service name should be specified.');
+    	}
+        if ($deploymentId == '' || is_null($deploymentId)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Deployment ID should be specified.');
+    	}
+    	if ($roleName == '' || is_null($roleName)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Role name name should be specified.');
+    	}
+    	
+		// Get configuration
+		$deployment = $this->getDeploymentByDeploymentId($serviceName, $deploymentId);
+		$configuration = $deployment->Configuration;
+		$configuration = $this->_updateInstanceCountInConfiguration($roleName, $instanceCount, $configuration);
+		
+		// Update configuration
+		$this->configureDeploymentByDeploymentId($serviceName, $deploymentId, $configuration);
+    }
+	
+    /**
+     * Updates instance count in configuration XML.
+     * 
+     * @param string|array $roleName			The role name
+     * @param string|array $instanceCount		The instance count
+     * @param string $configuration             XML configuration represented as a string
+     * @throws Zend_Service_WindowsAzure_Management_Exception
+     */
+	protected function _updateInstanceCountInConfiguration($roleName, $instanceCount, $configuration) {
+    	// Change variables
+		if (!is_array($roleName)) {
+			$roleName = array($roleName);
+		}
+		if (!is_array($instanceCount)) {
+			$instanceCount = array($instanceCount);
+		}
+
+		$configuration = preg_replace('/(<\?xml[^?]+?)utf-16/i', '$1utf-8', $configuration);
+		//$configuration = '<?xml version="1.0">' . substr($configuration, strpos($configuration, '>') + 2);
+
+		$xml = simplexml_load_string($configuration); 
+		
+		// http://www.php.net/manual/en/simplexmlelement.xpath.php#97818
+		$namespaces = $xml->getDocNamespaces();
+	    $xml->registerXPathNamespace('__empty_ns', $namespaces['']); 
+	
+		for ($i = 0; $i < count($roleName); $i++) {
+			$elements = $xml->xpath('//__empty_ns:Role[@name="' . $roleName[$i] . '"]/__empty_ns:Instances');
+	
+			if (count($elements) == 1) {
+				$element = $elements[0];
+				$element['count'] = $instanceCount[$i];
+			} 
+		}
+		
+		$configuration = $xml->asXML();
+		//$configuration = preg_replace('/(<\?xml[^?]+?)utf-8/i', '$1utf-16', $configuration);
+
+		return $configuration;
+	}
+    
+    /**
+     * The Change Deployment Configuration request may be specified as follows.
+     * Note that you can change a deployment's configuration either by specifying the deployment
+     * environment (staging or production), or by specifying the deployment's unique name. 
+     * 
+     * @param string $serviceName		The service name
+     * @param string $deploymentSlot	The deployment slot (production or staging)
+     * @param string $configuration     XML configuration represented as a string
+     * @throws Zend_Service_WindowsAzure_Management_Exception
+     */
+    public function configureDeploymentBySlot($serviceName, $deploymentSlot, $configuration)
+    {
+        if ($serviceName == '' || is_null($serviceName)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Service name should be specified.');
+    	}
+    	$deploymentSlot = strtolower($deploymentSlot);
+    	if ($deploymentSlot != 'production' && $deploymentSlot != 'staging') {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Deployment slot should be production|staging.');
+    	}
+    	if ($configuration == '' || is_null($configuration)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Configuration name should be specified.');
+    	}
+    	
+        if (@file_exists($configuration)) {
+    		$configuration = utf8_decode(file_get_contents($configuration));
+    	}
+    	
+    	$operationUrl = self::OP_HOSTED_SERVICES . '/' . $serviceName . '/deploymentslots/' . $deploymentSlot;
+    	return $this->_configureDeployment($operationUrl, $configuration);
+    }
+    
+    /**
+     * The Change Deployment Configuration request may be specified as follows.
+     * Note that you can change a deployment's configuration either by specifying the deployment
+     * environment (staging or production), or by specifying the deployment's unique name. 
+     * 
+     * @param string $serviceName		The service name
+     * @param string $deploymentId	The deployment ID as listed on the Windows Azure management portal
+     * @param string $configuration     XML configuration represented as a string
+     * @throws Zend_Service_WindowsAzure_Management_Exception
+     */
+    public function configureDeploymentByDeploymentId($serviceName, $deploymentId, $configuration)
+    {
+        if ($serviceName == '' || is_null($serviceName)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Service name should be specified.');
+    	}
+    	if ($deploymentId == '' || is_null($deploymentId)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Deployment ID should be specified.');
+    	}
+    	if ($configuration == '' || is_null($configuration)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Configuration name should be specified.');
+    	}
+    	
+        if (@file_exists($configuration)) {
+    		$configuration = utf8_decode(file_get_contents($configuration));
+    	}
+    	
+    	$operationUrl = self::OP_HOSTED_SERVICES . '/' . $serviceName . '/deployments/' . $deploymentId;
+    	return $this->_configureDeployment($operationUrl, $configuration);
+    }
+    
+    /**
+     * The Change Deployment Configuration request may be specified as follows.
+     * Note that you can change a deployment's configuration either by specifying the deployment
+     * environment (staging or production), or by specifying the deployment's unique name. 
+     * 
+     * @param string $operationUrl		The operation url
+     * @param string $configuration     XML configuration represented as a string
+     * @throws Zend_Service_WindowsAzure_Management_Exception
+     */
+    protected function _configureDeployment($operationUrl, $configuration)
+    {
+    	// Clean up the configuration
+    	$conformingConfiguration = $this->_cleanConfiguration($configuration);
+
+        $response = $this->_performRequest($operationUrl . '/', '?comp=config',
+    		Zend_Http_Client::POST,
+    		array('Content-Type' => 'application/xml; charset=utf-8'),
+    		'<ChangeConfiguration xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><Configuration>' . base64_encode($conformingConfiguration) . '</Configuration></ChangeConfiguration>');
+			 
+    	if (!$response->isSuccessful()) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+			throw new Zend_Service_WindowsAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
+		}
+    }
+    
+    /**
+     * The Upgrade Deployment operation initiates an upgrade.
+     * 
+     * @param string $serviceName		The service name
+     * @param string $deploymentSlot	The deployment slot (production or staging)
+	 * @param string $label             A URL that refers to the location of the service package in the Blob service. The service package must be located in a storage account beneath the same subscription.
+	 * @param string $packageUrl        The service configuration file for the deployment.
+	 * @param string $configuration     A label for this deployment, up to 100 characters in length.
+     * @param string $mode              The type of upgrade to initiate. Possible values are Auto or Manual.
+     * @param string $roleToUpgrade     The name of the specific role to upgrade.
+     * @throws Zend_Service_WindowsAzure_Management_Exception
+     */
+    public function upgradeDeploymentBySlot($serviceName, $deploymentSlot, $label, $packageUrl, $configuration, $mode = 'auto', $roleToUpgrade = null)
+    {
+        if ($serviceName == '' || is_null($serviceName)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Service name should be specified.');
+    	}
+    	$deploymentSlot = strtolower($deploymentSlot);
+    	if ($deploymentSlot != 'production' && $deploymentSlot != 'staging') {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Deployment slot should be production|staging.');
+    	}
+    	if ($label == '' || is_null($label)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Label should be specified.');
+    	}
+        if (strlen($label) > 100) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Label is too long. The maximum length is 100 characters.');
+    	}
+    	if ($packageUrl == '' || is_null($packageUrl)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Package URL should be specified.');
+    	}
+    	if ($configuration == '' || is_null($configuration)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Configuration should be specified.');
+    	}
+    	$mode = strtolower($mode);
+    	if ($mode != 'auto' && $mode != 'manual') {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Mode should be auto|manual.');
+    	}
+    	
+    	if (@file_exists($configuration)) {
+    		$configuration = utf8_decode(file_get_contents($configuration));
+    	}
+    	
+		$operationUrl = self::OP_HOSTED_SERVICES . '/' . $serviceName . '/deploymentslots/' . $deploymentSlot;
+    	return $this->_upgradeDeployment($operationUrl, $label, $packageUrl, $configuration, $mode, $roleToUpgrade);  	
+    }
+    
+    /**
+     * The Upgrade Deployment operation initiates an upgrade.
+     * 
+     * @param string $serviceName		The service name
+     * @param string $deploymentId	The deployment ID as listed on the Windows Azure management portal
+	 * @param string $label             A URL that refers to the location of the service package in the Blob service. The service package must be located in a storage account beneath the same subscription.
+	 * @param string $packageUrl        The service configuration file for the deployment.
+	 * @param string $configuration     A label for this deployment, up to 100 characters in length.
+     * @param string $mode              The type of upgrade to initiate. Possible values are Auto or Manual.
+     * @param string $roleToUpgrade     The name of the specific role to upgrade.
+     * @throws Zend_Service_WindowsAzure_Management_Exception
+     */
+    public function upgradeDeploymentByDeploymentId($serviceName, $deploymentId, $label, $packageUrl, $configuration, $mode = 'auto', $roleToUpgrade = null)
+    {
+        if ($serviceName == '' || is_null($serviceName)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Service name should be specified.');
+    	}
+    	if ($deploymentId == '' || is_null($deploymentId)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Deployment ID should be specified.');
+    	}
+    	if ($label == '' || is_null($label)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Label should be specified.');
+    	}
+        if (strlen($label) > 100) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Label is too long. The maximum length is 100 characters.');
+    	}
+    	if ($packageUrl == '' || is_null($packageUrl)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Package URL should be specified.');
+    	}
+    	if ($configuration == '' || is_null($configuration)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Configuration should be specified.');
+    	}
+    	$mode = strtolower($mode);
+    	if ($mode != 'auto' && $mode != 'manual') {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Mode should be auto|manual.');
+    	}
+    	
+    	if (@file_exists($configuration)) {
+    		$configuration = utf8_decode(file_get_contents($configuration));
+    	}
+    	
+		$operationUrl = self::OP_HOSTED_SERVICES . '/' . $serviceName . '/deployments/' . $deploymentId;
+    	return $this->_upgradeDeployment($operationUrl, $label, $packageUrl, $configuration, $mode, $roleToUpgrade);  	
+    }
+    
+    
+    /**
+     * The Upgrade Deployment operation initiates an upgrade.
+     * 
+     * @param string $operationUrl		The operation url
+	 * @param string $label             A URL that refers to the location of the service package in the Blob service. The service package must be located in a storage account beneath the same subscription.
+	 * @param string $packageUrl        The service configuration file for the deployment.
+	 * @param string $configuration     A label for this deployment, up to 100 characters in length.
+     * @param string $mode              The type of upgrade to initiate. Possible values are Auto or Manual.
+     * @param string $roleToUpgrade     The name of the specific role to upgrade.
+     * @throws Zend_Service_WindowsAzure_Management_Exception
+     */
+    protected function _upgradeDeployment($operationUrl, $label, $packageUrl, $configuration, $mode, $roleToUpgrade)
+    {
+    	// Clean up the configuration
+    	$conformingConfiguration = $this->_cleanConfiguration($configuration);
+    	
+        $response = $this->_performRequest($operationUrl . '/', '?comp=upgrade',
+    		Zend_Http_Client::POST,
+    		array('Content-Type' => 'application/xml; charset=utf-8'),
+    		'<UpgradeDeployment xmlns="http://schemas.microsoft.com/windowsazure"><Mode>' . ucfirst($mode) . '</Mode><PackageUrl>' . $packageUrl . '</PackageUrl><Configuration>' . base64_encode($conformingConfiguration) . '</Configuration><Label>' . base64_encode($label) . '</Label>' . (!is_null($roleToUpgrade) ? '<RoleToUpgrade>' . $roleToUpgrade . '</RoleToUpgrade>' : '') . '</UpgradeDeployment>');		
+    		
+    	if (!$response->isSuccessful()) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+			throw new Zend_Service_WindowsAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
+		}
+    }
+    
+    /**
+     * The Walk Upgrade Domain operation specifies the next upgrade domain to be walked during an in-place upgrade.
+     * 
+     * @param string $serviceName		The service name
+     * @param string $deploymentSlot	The deployment slot (production or staging)
+	 * @param int $upgradeDomain     An integer value that identifies the upgrade domain to walk. Upgrade domains are identified with a zero-based index: the first upgrade domain has an ID of 0, the second has an ID of 1, and so on.
+     * @throws Zend_Service_WindowsAzure_Management_Exception
+     */
+    public function walkUpgradeDomainBySlot($serviceName, $deploymentSlot, $upgradeDomain = 0)
+    {
+        if ($serviceName == '' || is_null($serviceName)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Service name should be specified.');
+    	}
+    	$deploymentSlot = strtolower($deploymentSlot);
+    	if ($deploymentSlot != 'production' && $deploymentSlot != 'staging') {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Deployment slot should be production|staging.');
+    	}
+    	
+		$operationUrl = self::OP_HOSTED_SERVICES . '/' . $serviceName . '/deploymentslots/' . $deploymentSlot;
+    	return $this->_walkUpgradeDomain($operationUrl, $upgradeDomain);  	
+    }
+    
+    /**
+     * The Walk Upgrade Domain operation specifies the next upgrade domain to be walked during an in-place upgrade.
+     * 
+     * @param string $serviceName		The service name
+     * @param string $deploymentId	The deployment ID as listed on the Windows Azure management portal
+	 * @param int $upgradeDomain     An integer value that identifies the upgrade domain to walk. Upgrade domains are identified with a zero-based index: the first upgrade domain has an ID of 0, the second has an ID of 1, and so on.
+     * @throws Zend_Service_WindowsAzure_Management_Exception
+     */
+    public function walkUpgradeDomainByDeploymentId($serviceName, $deploymentId, $upgradeDomain = 0)
+    {
+        if ($serviceName == '' || is_null($serviceName)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Service name should be specified.');
+    	}
+    	if ($deploymentId == '' || is_null($deploymentId)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Deployment ID should be specified.');
+    	}
+    	
+		$operationUrl = self::OP_HOSTED_SERVICES . '/' . $serviceName . '/deployments/' . $deploymentId;
+    	return $this->_walkUpgradeDomain($operationUrl, $upgradeDomain);  	
+    }
+    
+    
+    /**
+     * The Walk Upgrade Domain operation specifies the next upgrade domain to be walked during an in-place upgrade.
+     * 
+     * @param string $operationUrl   The operation url
+	 * @param int $upgradeDomain     An integer value that identifies the upgrade domain to walk. Upgrade domains are identified with a zero-based index: the first upgrade domain has an ID of 0, the second has an ID of 1, and so on.
+     * @throws Zend_Service_WindowsAzure_Management_Exception
+     */
+    protected function _walkUpgradeDomain($operationUrl, $upgradeDomain = 0)
+    {
+        $response = $this->_performRequest($operationUrl . '/', '?comp=walkupgradedomain',
+    		Zend_Http_Client::POST,
+    		array('Content-Type' => 'application/xml; charset=utf-8'),
+    		'<WalkUpgradeDomain xmlns="http://schemas.microsoft.com/windowsazure"><UpgradeDomain>' . $upgradeDomain . '</UpgradeDomain></WalkUpgradeDomain>');		
+
+    	if (!$response->isSuccessful()) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+			throw new Zend_Service_WindowsAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
+		}
+    }
+    
+    /**
+     * The Reboot Role Instance operation requests a reboot of a role instance
+     * that is running in a deployment.
+     * 
+     * @param string $serviceName		The service name
+     * @param string $deploymentSlot	The deployment slot (production or staging)
+     * @param string $roleInstanceName  The role instance name
+     * @throws Zend_Service_WindowsAzure_Management_Exception
+     */
+    public function rebootRoleInstanceBySlot($serviceName, $deploymentSlot, $roleInstanceName)
+    {
+        if ($serviceName == '' || is_null($serviceName)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Service name should be specified.');
+    	}
+    	$deploymentSlot = strtolower($deploymentSlot);
+    	if ($deploymentSlot != 'production' && $deploymentSlot != 'staging') {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Deployment slot should be production|staging.');
+    	}
+        if ($roleInstanceName == '' || is_null($roleInstanceName)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Role instance name should be specified.');
+    	}
+    	
+    	$operationUrl = self::OP_HOSTED_SERVICES . '/' . $serviceName . '/deploymentslots/' . $deploymentSlot . '/roleinstances/' . $roleInstanceName;
+    	return $this->_rebootOrReimageRoleInstance($operationUrl, 'reboot');
+    }
+    
+    /**
+     * The Reboot Role Instance operation requests a reboot of a role instance
+     * that is running in a deployment.
+     * 
+     * @param string $serviceName		The service name
+     * @param string $deploymentId	The deployment ID as listed on the Windows Azure management portal
+     * @param string $roleInstanceName  The role instance name
+     * @throws Zend_Service_WindowsAzure_Management_Exception
+     */
+    public function rebootRoleInstanceByDeploymentId($serviceName, $deploymentId, $roleInstanceName)
+    {
+        if ($serviceName == '' || is_null($serviceName)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Service name should be specified.');
+    	}
+    	if ($deploymentId == '' || is_null($deploymentId)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Deployment ID should be specified.');
+    	}
+        if ($roleInstanceName == '' || is_null($roleInstanceName)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Role instance name should be specified.');
+    	}
+    	
+    	$operationUrl = self::OP_HOSTED_SERVICES . '/' . $serviceName . '/deployments/' . $deploymentId . '/roleinstances/' . $roleInstanceName;
+    	return $this->_rebootOrReimageRoleInstance($operationUrl, 'reboot');
+    }
+
+    /**
+     * The Reimage Role Instance operation requests a reimage of a role instance
+     * that is running in a deployment.
+     * 
+     * @param string $serviceName		The service name
+     * @param string $deploymentSlot	The deployment slot (production or staging)
+     * @param string $roleInstanceName  The role instance name
+     * @throws Zend_Service_WindowsAzure_Management_Exception
+     */
+    public function reimageRoleInstanceBySlot($serviceName, $deploymentSlot, $roleInstanceName)
+    {
+        if ($serviceName == '' || is_null($serviceName)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Service name should be specified.');
+    	}
+    	$deploymentSlot = strtolower($deploymentSlot);
+    	if ($deploymentSlot != 'production' && $deploymentSlot != 'staging') {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Deployment slot should be production|staging.');
+    	}
+        if ($roleInstanceName == '' || is_null($roleInstanceName)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Role instance name should be specified.');
+    	}
+    	
+    	$operationUrl = self::OP_HOSTED_SERVICES . '/' . $serviceName . '/deploymentslots/' . $deploymentSlot . '/roleinstances/' . $roleInstanceName;
+    	return $this->_rebootOrReimageRoleInstance($operationUrl, 'reimage');
+    }
+    
+    /**
+     * The Reimage Role Instance operation requests a reimage of a role instance
+     * that is running in a deployment.
+     * 
+     * @param string $serviceName		The service name
+     * @param string $deploymentId	    The deployment ID as listed on the Windows Azure management portal
+     * @param string $roleInstanceName  The role instance name
+     * @throws Zend_Service_WindowsAzure_Management_Exception
+     */
+    public function reimageRoleInstanceByDeploymentId($serviceName, $deploymentId, $roleInstanceName)
+    {
+        if ($serviceName == '' || is_null($serviceName)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Service name should be specified.');
+    	}
+    	if ($deploymentId == '' || is_null($deploymentId)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Deployment ID should be specified.');
+    	}
+        if ($roleInstanceName == '' || is_null($roleInstanceName)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Role instance name should be specified.');
+    	}
+    	
+    	$operationUrl = self::OP_HOSTED_SERVICES . '/' . $serviceName . '/deployments/' . $deploymentId . '/roleinstances/' . $roleInstanceName;
+    	return $this->_rebootOrReimageRoleInstance($operationUrl, 'reimage');
+    }
+    
+    /**
+     * Reboots or reimages a role instance.
+     * 
+     * @param string $operationUrl		The operation url
+     * @param string $operation The operation (reboot|reimage)
+     * @throws Zend_Service_WindowsAzure_Management_Exception
+     */
+    protected function _rebootOrReimageRoleInstance($operationUrl, $operation = 'reboot')
+    {
+        $response = $this->_performRequest($operationUrl, '?comp=' . $operation, Zend_Http_Client::POST);
+    		
+    	if (!$response->isSuccessful()) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+			throw new Zend_Service_WindowsAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
+		}
+    }
+    
+    /**
+     * The List Certificates operation lists all certificates associated with
+     * the specified hosted service.
+     * 
+     * @param string $serviceName		The service name
+     * @return array Array of Zend_Service_WindowsAzure_Management_CertificateInstance
+     * @throws Zend_Service_WindowsAzure_Management_Exception
+     */
+    public function listCertificates($serviceName)
+    {
+        if ($serviceName == '' || is_null($serviceName)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Service name should be specified.');
+    	}
+    	
+    	$operationUrl = self::OP_HOSTED_SERVICES . '/' . $serviceName . '/certificates';
+        $response = $this->_performRequest($operationUrl);
+
+    	if ($response->isSuccessful()) {
+			$result = $this->_parseResponse($response);
+
+			if (!$result->Certificate) {
+				return array();
+			}
+		    if (count($result->Certificate) > 1) {
+    		    $xmlServices = $result->Certificate;
+    		} else {
+    		    $xmlServices = array($result->Certificate);
+    		}
+
+			$services = array();
+			if (!is_null($xmlServices)) {				
+				
+				for ($i = 0; $i < count($xmlServices); $i++) {
+					$services[] = new Zend_Service_WindowsAzure_Management_CertificateInstance(
+					    (string)$xmlServices[$i]->CertificateUrl,
+					    (string)$xmlServices[$i]->Thumbprint,
+					    (string)$xmlServices[$i]->ThumbprintAlgorithm,
+					    (string)$xmlServices[$i]->Data
+					);
+				}
+			}
+			return $services;
+		} else {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+			throw new Zend_Service_WindowsAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
+		}
+    }
+    
+    /**
+     * The Get Certificate operation returns the public data for the specified certificate.
+     * 
+     * @param string $serviceName|$certificateUrl	The service name -or- the certificate URL
+     * @param string $algorithm         			Algorithm
+     * @param string $thumbprint        			Thumbprint
+     * @return Zend_Service_WindowsAzure_Management_CertificateInstance
+     * @throws Zend_Service_WindowsAzure_Management_Exception
+     */
+    public function getCertificate($serviceName, $algorithm = '', $thumbprint = '')
+    {
+        if ($serviceName == '' || is_null($serviceName)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Service name or certificate URL should be specified.');
+    	}
+    	if (strpos($serviceName, 'https') === false && ($algorithm == '' || is_null($algorithm)) && ($thumbprint == '' || is_null($thumbprint))) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Algorithm and thumbprint should be specified.');
+    	}
+    	
+    	$operationUrl = str_replace($this->getBaseUrl(), '', $serviceName);
+    	if (strpos($serviceName, 'https') === false) {
+    		$operationUrl = self::OP_HOSTED_SERVICES . '/' . $serviceName . '/certificates/' . $algorithm . '-' . strtoupper($thumbprint);
+    	}
+    	
+        $response = $this->_performRequest($operationUrl);
+
+    	if ($response->isSuccessful()) {
+			$result = $this->_parseResponse($response);
+			
+			return new Zend_Service_WindowsAzure_Management_CertificateInstance(
+				$this->getBaseUrl() . $operationUrl,
+				$algorithm,
+				$thumbprint,
+				(string)$result->Data
+			);
+		} else {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+			throw new Zend_Service_WindowsAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
+		}
+    }
+    
+    /**
+     * The Add Certificate operation adds a certificate to the subscription.
+     * 
+     * @param string $serviceName         The service name
+     * @param string $certificateData     Certificate data
+     * @param string $certificatePassword The certificate password
+     * @param string $certificateFormat   The certificate format. Currently, only 'pfx' is supported.
+     * @throws Zend_Service_WindowsAzure_Management_Exception
+     */
+    public function addCertificate($serviceName, $certificateData, $certificatePassword, $certificateFormat = 'pfx')
+    {
+    	if ($serviceName == '' || is_null($serviceName)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Service name should be specified.');
+    	}
+    	if ($certificateData == '' || is_null($certificateData)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Certificate data should be specified.');
+    	}
+    	if ($certificatePassword == '' || is_null($certificatePassword)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Certificate password should be specified.');
+    	}
+    	if ($certificateFormat != 'pfx') {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Certificate format should be "pfx".');
+    	}
+    	
+    	if (@file_exists($certificateData)) {
+    		$certificateData = file_get_contents($certificateData);
+    	}
+    	
+    	$operationUrl = self::OP_HOSTED_SERVICES . '/' . $serviceName . '/certificates';
+        $response = $this->_performRequest($operationUrl, '',
+    		Zend_Http_Client::POST,
+    		array('Content-Type' => 'application/xml; charset=utf-8'),
+    		'<CertificateFile xmlns="http://schemas.microsoft.com/windowsazure"><Data>' . base64_encode($certificateData) . '</Data><CertificateFormat>' . $certificateFormat . '</CertificateFormat><Password>' . $certificatePassword . '</Password></CertificateFile>');
+
+    	if (!$response->isSuccessful()) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+			throw new Zend_Service_WindowsAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
+		}
+    }
+    
+    /**
+     * The Delete Certificate operation deletes a certificate from the subscription's certificate store.
+     * 
+     * @param string $serviceName|$certificateUrl	The service name -or- the certificate URL
+     * @param string $algorithm         			Algorithm
+     * @param string $thumbprint        			Thumbprint
+     * @throws Zend_Service_WindowsAzure_Management_Exception
+     */
+    public function deleteCertificate($serviceName, $algorithm = '', $thumbprint = '')
+    {
+        if ($serviceName == '' || is_null($serviceName)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Service name or certificate URL should be specified.');
+    	}
+    	if (strpos($serviceName, 'https') === false && ($algorithm == '' || is_null($algorithm)) && ($thumbprint == '' || is_null($thumbprint))) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Algorithm and thumbprint should be specified.');
+    	}
+    	
+    	$operationUrl = str_replace($this->getBaseUrl(), '', $serviceName);
+    	if (strpos($serviceName, 'https') === false) {
+    		$operationUrl = self::OP_HOSTED_SERVICES . '/' . $serviceName . '/certificates/' . $algorithm . '-' . strtoupper($thumbprint);
+    	}
+    	
+        $response = $this->_performRequest($operationUrl, '', Zend_Http_Client::DELETE);
+
+    	if (!$response->isSuccessful()) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+			throw new Zend_Service_WindowsAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
+		}
+    }
+    
+    /**
+     * The List Affinity Groups operation lists the affinity groups associated with
+     * the specified subscription.
+     * 
+     * @return array Array of Zend_Service_WindowsAzure_Management_AffinityGroupInstance
+     * @throws Zend_Service_WindowsAzure_Management_Exception
+     */
+    public function listAffinityGroups()
+    {
+        $response = $this->_performRequest(self::OP_AFFINITYGROUPS);
+
+    	if ($response->isSuccessful()) {
+			$result = $this->_parseResponse($response);
+			
+    		if (!$result->AffinityGroup) {
+				return array();
+			}
+		    if (count($result->AffinityGroup) > 1) {
+    		    $xmlServices = $result->AffinityGroup;
+    		} else {
+    		    $xmlServices = array($result->AffinityGroup);
+    		}
+    		
+			$services = array();
+			if (!is_null($xmlServices)) {				
+				
+				for ($i = 0; $i < count($xmlServices); $i++) {
+					$services[] = new Zend_Service_WindowsAzure_Management_AffinityGroupInstance(
+					    (string)$xmlServices[$i]->Name,
+					    (string)$xmlServices[$i]->Label,
+					    (string)$xmlServices[$i]->Description,
+					    (string)$xmlServices[$i]->Location
+					);
+				}
+			}
+			return $services;
+		} else {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+			throw new Zend_Service_WindowsAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
+		}
+    }
+    
+    /**
+     * The Create Affinity Group operation creates a new affinity group for the specified subscription.
+     * 
+     * @param string $name A name for the affinity group that is unique to the subscription.
+     * @param string $label A label for the affinity group. The label may be up to 100 characters in length.
+     * @param string $description A description for the affinity group. The description may be up to 1024 characters in length.
+     * @param string $location The location where the affinity group will be created. To list available locations, use the List Locations operation. 
+     */
+    public function createAffinityGroup($name, $label, $description = '', $location = '')
+    {
+    	if ($name == '' || is_null($name)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Affinity group name should be specified.');
+    	}
+    	if ($label == '' || is_null($label)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Label should be specified.');
+    	}
+        if (strlen($label) > 100) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Label is too long. The maximum length is 100 characters.');
+    	}
+        if (strlen($description) > 1024) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Description is too long. The maximum length is 1024 characters.');
+    	}
+    	if ($location == '' || is_null($location)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Location should be specified.');
+    	}
+    	
+        $response = $this->_performRequest(self::OP_AFFINITYGROUPS, '',
+    		Zend_Http_Client::POST,
+    		array('Content-Type' => 'application/xml; charset=utf-8'),
+    		'<CreateAffinityGroup xmlns="http://schemas.microsoft.com/windowsazure"><Name>' . $name . '</Name><Label>' . base64_encode($label) . '</Label><Description>' . $description . '</Description><Location>' . $location . '</Location></CreateAffinityGroup>');	
+    		
+    	if (!$response->isSuccessful()) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+			throw new Zend_Service_WindowsAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
+		}
+    }
+    
+    /**
+     * The Update Affinity Group operation updates the label and/or the description for an affinity group for the specified subscription.
+     * 
+     * @param string $name The name for the affinity group that should be updated.
+     * @param string $label A label for the affinity group. The label may be up to 100 characters in length.
+     * @param string $description A description for the affinity group. The description may be up to 1024 characters in length. 
+     */
+    public function updateAffinityGroup($name, $label, $description = '')
+    {
+    	if ($name == '' || is_null($name)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Affinity group name should be specified.');
+    	}
+    	if ($label == '' || is_null($label)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Label should be specified.');
+    	}
+        if (strlen($label) > 100) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Label is too long. The maximum length is 100 characters.');
+    	}
+        if (strlen($description) > 1024) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Description is too long. The maximum length is 1024 characters.');
+    	}
+    	
+        $response = $this->_performRequest(self::OP_AFFINITYGROUPS . '/' . $name, '',
+    		Zend_Http_Client::PUT,
+    		array('Content-Type' => 'application/xml; charset=utf-8'),
+    		'<UpdateAffinityGroup xmlns="http://schemas.microsoft.com/windowsazure"><Label>' . base64_encode($label) . '</Label><Description>' . $description . '</Description></UpdateAffinityGroup>');	
+    		
+    	if (!$response->isSuccessful()) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+			throw new Zend_Service_WindowsAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
+		}
+    }
+    
+    /**
+     * The Delete Affinity Group operation deletes an affinity group in the specified subscription.
+     * 
+     * @param string $name The name for the affinity group that should be deleted.
+     */
+    public function deleteAffinityGroup($name)
+    {
+    	if ($name == '' || is_null($name)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Affinity group name should be specified.');
+    	}
+    	
+        $response = $this->_performRequest(self::OP_AFFINITYGROUPS . '/' . $name, '',
+    		Zend_Http_Client::DELETE);
+    		
+    	if (!$response->isSuccessful()) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+			throw new Zend_Service_WindowsAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
+		}
+    }
+    
+    /**
+     * The Get Affinity Group Properties operation returns the
+     * system properties associated with the specified affinity group.
+     * 
+     * @param string $affinityGroupName The affinity group name.
+     * @return Zend_Service_WindowsAzure_Management_AffinityGroupInstance
+     * @throws Zend_Service_WindowsAzure_Management_Exception
+     */
+    public function getAffinityGroupProperties($affinityGroupName)
+    {
+        if ($affinityGroupName == '' || is_null($affinityGroupName)) {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+    		throw new Zend_Service_WindowsAzure_Management_Exception('Affinity group name should be specified.');
+    	}
+    	
+        $response = $this->_performRequest(self::OP_AFFINITYGROUPS . '/' . $affinityGroupName);
+
+    	if ($response->isSuccessful()) {
+			$result = $this->_parseResponse($response);
+			
+			$affinityGroup = new Zend_Service_WindowsAzure_Management_AffinityGroupInstance(
+				$affinityGroupName,
+				(string)$result->Label,
+				(string)$result->Description,
+				(string)$result->Location
+			);
+
+			// Hosted services
+			if (count($result->HostedServices->HostedService) > 1) {
+		    	$xmlService = $result->HostedServices->HostedService;
+		    } else {
+		    	$xmlService = array($result->HostedServices->HostedService);
+		    }
+		    		
+			$services = array();
+			if (!is_null($xmlService)) {				
+				for ($i = 0; $i < count($xmlService); $i++) {
+					$services[] = array(
+						'url' => (string)$xmlService[$i]->Url,
+						'name' => (string)$xmlService[$i]->ServiceName
+					);
+				}
+			}
+			$affinityGroup->HostedServices = $services;
+			
+			// Storage services
+			if (count($result->StorageServices->StorageService) > 1) {
+		    	$xmlService = $result->StorageServices->StorageService;
+		    } else {
+		    	$xmlService = array($result->StorageServices->StorageService);
+		    }
+		    		
+			$services = array();
+			if (!is_null($xmlService)) {				
+				for ($i = 0; $i < count($xmlService); $i++) {
+					$services[] = array(
+						'url' => (string)$xmlService[$i]->Url,
+						'name' => (string)$xmlService[$i]->ServiceName
+					);
+				}
+			}
+			$affinityGroup->StorageServices = $services;	
+			
+			return $affinityGroup;
+		} else {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+			throw new Zend_Service_WindowsAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
+		}
+    }
+    
+    /**
+     * The List Locations operation lists all of the data center locations
+     * that are valid for your subscription.
+     * 
+     * @return array Array of Zend_Service_WindowsAzure_Management_LocationInstance
+     * @throws Zend_Service_WindowsAzure_Management_Exception
+     */
+    public function listLocations()
+    {
+        $response = $this->_performRequest(self::OP_LOCATIONS);
+
+    	if ($response->isSuccessful()) {
+			$result = $this->_parseResponse($response);
+			
+    		if (!$result->Location) {
+				return array();
+			}
+		    if (count($result->Location) > 1) {
+    		    $xmlServices = $result->Location;
+    		} else {
+    		    $xmlServices = array($result->Location);
+    		}
+    		
+			$services = array();
+			if (!is_null($xmlServices)) {				
+				
+				for ($i = 0; $i < count($xmlServices); $i++) {
+					$services[] = new Zend_Service_WindowsAzure_Management_LocationInstance(
+					    (string)$xmlServices[$i]->Name
+					);
+				}
+			}
+			return $services;
+		} else {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+			throw new Zend_Service_WindowsAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
+		}
+    }
+    
+    /**
+     * The List Operating Systems operation lists the versions of the guest operating system
+     * that are currently available in Windows Azure. The 2010-10-28 version of List Operating
+     * Systems also indicates what family an operating system version belongs to.
+     * Currently Windows Azure supports two operating system families: the Windows Azure guest
+     * operating system that is substantially compatible with Windows Server 2008 SP2,
+     * and the Windows Azure guest operating system that is substantially compatible with
+     * Windows Server 2008 R2.
+     * 
+     * @return array Array of Zend_Service_WindowsAzure_Management_OperatingSystemInstance
+     * @throws Zend_Service_WindowsAzure_Management_Exception
+     */
+    public function listOperatingSystems()
+    {
+        $response = $this->_performRequest(self::OP_OPERATINGSYSTEMS);
+
+    	if ($response->isSuccessful()) {
+			$result = $this->_parseResponse($response);
+			
+    		if (!$result->OperatingSystem) {
+				return array();
+			}
+		    if (count($result->OperatingSystem) > 1) {
+    		    $xmlServices = $result->OperatingSystem;
+    		} else {
+    		    $xmlServices = array($result->OperatingSystem);
+    		}
+    		
+			$services = array();
+			if (!is_null($xmlServices)) {				
+				
+				for ($i = 0; $i < count($xmlServices); $i++) {
+					$services[] = new Zend_Service_WindowsAzure_Management_OperatingSystemInstance(
+					    (string)$xmlServices[$i]->Version,
+					    (string)$xmlServices[$i]->Label,
+					    ((string)$xmlServices[$i]->IsDefault == 'true'),
+					    ((string)$xmlServices[$i]->IsActive == 'true'),
+					    (string)$xmlServices[$i]->Family,
+					    (string)$xmlServices[$i]->FamilyLabel
+					);
+				}
+			}
+			return $services;
+		} else {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+			throw new Zend_Service_WindowsAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
+		}
+    }
+    
+    /**
+     * The List OS Families operation lists the guest operating system families
+     * available in Windows Azure, and also lists the operating system versions
+     * available for each family. Currently Windows Azure supports two operating
+     * system families: the Windows Azure guest operating system that is
+     * substantially compatible with Windows Server 2008 SP2, and the Windows
+     * Azure guest operating system that is substantially compatible with
+     * Windows Server 2008 R2.
+     * 
+     * @return array Array of Zend_Service_WindowsAzure_Management_OperatingSystemFamilyInstance
+     * @throws Zend_Service_WindowsAzure_Management_Exception
+     */
+    public function listOperatingSystemFamilies()
+    {
+        $response = $this->_performRequest(self::OP_OPERATINGSYSTEMFAMILIES);
+
+    	if ($response->isSuccessful()) {
+			$result = $this->_parseResponse($response);
+			
+    		if (!$result->OperatingSystemFamily) {
+				return array();
+			}
+		    if (count($result->OperatingSystemFamily) > 1) {
+    		    $xmlServices = $result->OperatingSystemFamily;
+    		} else {
+    		    $xmlServices = array($result->OperatingSystemFamily);
+    		}
+    		
+			$services = array();
+			if (!is_null($xmlServices)) {				
+				
+				for ($i = 0; $i < count($xmlServices); $i++) {
+					$services[] = new Zend_Service_WindowsAzure_Management_OperatingSystemFamilyInstance(
+					    (string)$xmlServices[$i]->Name,
+					    (string)$xmlServices[$i]->Label
+					);
+								
+					if (count($xmlServices[$i]->OperatingSystems->OperatingSystem) > 1) {
+		    		    $xmlOperatingSystems = $xmlServices[$i]->OperatingSystems->OperatingSystem;
+		    		} else {
+		    		    $xmlOperatingSystems = array($xmlServices[$i]->OperatingSystems->OperatingSystem);
+		    		}
+		    		
+					$operatingSystems = array();
+					if (!is_null($xmlOperatingSystems)) {				
+						require_once 'Zend/Service/WindowsAzure/Management/OperatingSystemInstance.php';
+						for ($i = 0; $i < count($xmlOperatingSystems); $i++) {
+							$operatingSystems[] = new Zend_Service_WindowsAzure_Management_OperatingSystemInstance(
+							    (string)$xmlOperatingSystems[$i]->Version,
+							    (string)$xmlOperatingSystems[$i]->Label,
+							    ((string)$xmlOperatingSystems[$i]->IsDefault == 'true'),
+							    ((string)$xmlOperatingSystems[$i]->IsActive == 'true'),
+							    (string)$xmlServices[$i]->Name,
+							    (string)$xmlServices[$i]->Label
+							);
+						}
+					}
+					$services[ count($services) - 1 ]->OperatingSystems = $operatingSystems;
+				}
+			}
+			return $services;
+		} else {
+			require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+			throw new Zend_Service_WindowsAzure_Management_Exception($this->_getErrorMessage($response, 'Resource could not be accessed.'));
+		}
+    }
+    
+    /**
+     * Clean configuration
+     * 
+     * @param string $configuration Configuration to clean.
+     * @return string
+     */
+    public function _cleanConfiguration($configuration) {
+    	$configuration = str_replace('?<?', '<?', $configuration);
+		$configuration = str_replace("\r", "", $configuration);
+		$configuration = str_replace("\n", "", $configuration);
+		
+		return $configuration;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/WindowsAzure/Management/DeploymentInstance.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,90 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure
+ * @subpackage Management
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/**
+ * @see Zend_Service_WindowsAzure_Management_ServiceEntityAbstract
+ */
+require_once 'Zend/Service/WindowsAzure/Management/ServiceEntityAbstract.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure
+ * @subpackage Management
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * 
+ * @property string $Name            The name for the deployment. This name must be unique among other deployments for the specified hosted service.
+ * @property string $DeploymentSlot  The environment to which the hosted service is deployed, either staging or production.
+ * @property string $PrivateID       The unique identifier for this deployment.
+ * @property string $Label           The label for the deployment.
+ * @property string $Url             The URL for the deployment.
+ * @property string $Configuration   The configuration file (XML, represented as string).
+ * @property string $Status          The status of the deployment. Running, Suspended, RunningTransitioning, SuspendedTransitioning, Starting, Suspending, Deploying, Deleting.
+ * @property string $UpgradeStatus   Parent node for elements describing an upgrade that is currently underway.
+ * @property string $UpgradeType     The upgrade type designated for this deployment. Possible values are Auto and Manual.
+ * @property string $CurrentUpgradeDomainState  The state of the current upgrade domain. Possible values are Before and During.
+ * @property string $CurrentUpgradeDomain       An integer value that identifies the current upgrade domain. Upgrade domains are identified with a zero-based index: the first upgrade domain has an ID of 0, the second has an ID of 1, and so on.
+ * @property string $UpgradeDomainCount         An integer value that indicates the number of upgrade domains in the deployment.
+ * @property array  $RoleInstanceList           The list of role instances.
+ * @property array  $RoleList                   The list of roles.
+ */
+class Zend_Service_WindowsAzure_Management_DeploymentInstance
+	extends Zend_Service_WindowsAzure_Management_ServiceEntityAbstract
+{    
+    /**
+     * Constructor
+     * 
+     * @param string $name            The name for the deployment. This name must be unique among other deployments for the specified hosted service.
+     * @param string $deploymentSlot  The environment to which the hosted service is deployed, either staging or production.
+     * @param string $privateID       The unique identifier for this deployment.
+     * @param string $label           The label for the deployment.
+     * @param string $url             The URL for the deployment.
+     * @param string $configuration   The configuration file (XML, represented as string).
+     * @param string $status          The status of the deployment. Running, Suspended, RunningTransitioning, SuspendedTransitioning, Starting, Suspending, Deploying, Deleting.
+     * @param string $upgradeStatus   Parent node for elements describing an upgrade that is currently underway.
+     * @param string $upgradeType     The upgrade type designated for this deployment. Possible values are Auto and Manual.
+     * @param string $currentUpgradeDomainState  The state of the current upgrade domain. Possible values are Before and During.
+     * @param string $currentUpgradeDomain       An integer value that identifies the current upgrade domain. Upgrade domains are identified with a zero-based index: the first upgrade domain has an ID of 0, the second has an ID of 1, and so on.
+     * @param string $upgradeDomainCount         An integer value that indicates the number of upgrade domains in the deployment.
+     * @param array  $roleInstanceList           The list of role instances.
+     * @param array  $roleList                   The list of roles.
+	 */
+    public function __construct($name, $deploymentSlot, $privateID, $label, $url, $configuration, $status, $upgradeStatus, $upgradeType, $currentUpgradeDomainState, $currentUpgradeDomain, $upgradeDomainCount, $roleInstanceList = array(), $roleList = array()) 
+    {	        
+        $this->_data = array(
+            'name'                        => $name,
+            'deploymentslot'              => $deploymentSlot,
+            'privateid'                   => $privateID,
+            'label'                       => base64_decode($label),
+            'url'                         => $url,
+            'configuration'               => base64_decode($configuration),
+            'status'                      => $status,
+            'upgradestatus'               => $upgradeStatus,
+            'upgradetype'                 => $upgradeType,
+            'currentupgradedomainstate'   => $currentUpgradeDomainState,
+            'currentupgradedomain'        => $currentUpgradeDomain,
+            'upgradedomaincount'          => $upgradeDomainCount,
+            'roleinstancelist'            => $roleInstanceList,
+            'rolelist'                    => $roleList    
+        );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/WindowsAzure/Management/Exception.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,38 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure
+ * @subpackage Management
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/**
+ * @see Zend_Service_WindowsAzure_Exception
+ */
+require_once 'Zend/Service/WindowsAzure/Exception.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure
+ * @subpackage Management
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Service_WindowsAzure_Management_Exception
+    extends Zend_Service_WindowsAzure_Exception
+{
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/WindowsAzure/Management/HostedServiceInstance.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,69 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure
+ * @subpackage Management
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/**
+ * @see Zend_Service_WindowsAzure_Management_ServiceEntityAbstract
+ */
+require_once 'Zend/Service/WindowsAzure/Management/ServiceEntityAbstract.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure
+ * @subpackage Management
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * 
+ * @property string $Url             The address of the hosted service.
+ * @property string $ServiceName     The name of the hosted service.
+ * @property string $Description	 A description of the hosted service.
+ * @property string $AffinityGroup   The affinity group with which this hosted service is associated.
+ * @property string $Location        The geo-location of the hosted service in Windows Azure, if your hosted service is not associated with an affinity group.
+ * @property string $Label           The label for the hosted service.
+ * @property array  $Deployments     Deployments for the hosted service.
+ */
+class Zend_Service_WindowsAzure_Management_HostedServiceInstance
+	extends Zend_Service_WindowsAzure_Management_ServiceEntityAbstract
+{    
+    /**
+     * Constructor
+     * 
+     * @param string $url             The address of the hosted service.
+     * @param string $serviceName     The name of the hosted service.
+	 * @param string $description	  A description of the storage account.
+	 * @param string $affinityGroup   The affinity group with which this hosted service is associated.
+	 * @param string $location        The geo-location of the hosted service in Windows Azure, if your hosted service is not associated with an affinity group.
+	 * @param string $label           The label for the hosted service.
+	 * @param array  $deployments     Deployments for the hosted service.
+	 */
+    public function __construct($url, $serviceName, $description = '', $affinityGroup = '', $location = '', $label = '', $deployments = array()) 
+    {	        
+        $this->_data = array(
+            'url'              => $url,
+            'servicename'      => $serviceName,
+            'description'      => $description,
+            'affinitygroup'    => $affinityGroup,
+            'location'         => $location,
+            'label'            => base64_decode($label),
+            'deployments'      => $deployments
+        );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/WindowsAzure/Management/LocationInstance.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,51 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure
+ * @subpackage Management
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/**
+ * @see Zend_Service_WindowsAzure_Management_ServiceEntityAbstract
+ */
+require_once 'Zend/Service/WindowsAzure/Management/ServiceEntityAbstract.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure
+ * @subpackage Management
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * 
+ * @property string $Name         The location name.
+ */
+class Zend_Service_WindowsAzure_Management_LocationInstance
+	extends Zend_Service_WindowsAzure_Management_ServiceEntityAbstract
+{    
+    /**
+     * Constructor
+     * 
+     * @param string $name         The location name. 
+	 */
+    public function __construct($name) 
+    {	        
+        $this->_data = array(
+            'name'        => $name    
+        );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/WindowsAzure/Management/OperatingSystemFamilyInstance.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,57 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure
+ * @subpackage Management
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/**
+ * @see Zend_Service_WindowsAzure_Management_ServiceEntityAbstract
+ */
+require_once 'Zend/Service/WindowsAzure/Management/ServiceEntityAbstract.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure
+ * @subpackage Management
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * 
+ * @property string $Name              Indicates which operating system family this version belongs to. A value of 1 corresponds to the Windows Azure guest operating system that is substantially compatible with Windows Server 2008 SP2. A value of 2 corresponds to the Windows Azure guest operating system that is substantially compatible with Windows Server 2008 R2. 
+ * @property string $Label             A label for the operating system version.
+ * @property array  $OperatingSystems  A list of operating systems available under this operating system family.
+ */
+class Zend_Service_WindowsAzure_Management_OperatingSystemFamilyInstance
+	extends Zend_Service_WindowsAzure_Management_ServiceEntityAbstract
+{    
+    /**
+     * Constructor
+     * 
+     * @param string $name              Indicates which operating system family this version belongs to. A value of 1 corresponds to the Windows Azure guest operating system that is substantially compatible with Windows Server 2008 SP2. A value of 2 corresponds to the Windows Azure guest operating system that is substantially compatible with Windows Server 2008 R2. 
+     * @param string $label             A label for the operating system version.
+     * @param array  $operatingSystems  A list of operating systems available under this operating system family.
+	 */
+    public function __construct($name, $label, $operatingSystems = array()) 
+    {	        
+        $this->_data = array(
+            'name'              => $name,
+            'label'             => base64_decode($label),
+            'operatingsystems'  => $operatingSystems
+        );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/WindowsAzure/Management/OperatingSystemInstance.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,66 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure
+ * @subpackage Management
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/**
+ * @see Zend_Service_WindowsAzure_Management_ServiceEntityAbstract
+ */
+require_once 'Zend/Service/WindowsAzure/Management/ServiceEntityAbstract.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure
+ * @subpackage Management
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * 
+ * @property string $Version         The operating system version. This value corresponds to the configuration value for specifying that your service is to run on a particular version of the Windows Azure guest operating system. 
+ * @property string $Label           A label for the operating system version.
+ * @property string $IsDefault    	 Indicates whether this operating system version is the default version for a service that has not otherwise specified a particular version. The default operating system version is applied to services that are configured for auto-upgrade. An operating system family has exactly one default operating system version at any given time, for which the IsDefault element is set to true; for all other versions, IsDefault is set to false.
+ * @property string $IsActive        Indicates whether this operating system version is currently active for running a service. If an operating system version is active, you can manually configure your service to run on that version.
+ * @property string $Family          Indicates which operating system family this version belongs to. A value of 1 corresponds to the Windows Azure guest operating system that is substantially compatible with Windows Server 2008 SP2. A value of 2 corresponds to the Windows Azure guest operating system that is substantially compatible with Windows Server 2008 R2.
+ * @property string $FamilyLabel     A label for the operating system family.
+ */
+class Zend_Service_WindowsAzure_Management_OperatingSystemInstance
+	extends Zend_Service_WindowsAzure_Management_ServiceEntityAbstract
+{    
+    /**
+     * Constructor
+     * 
+     * @param string $version         The operating system version. This value corresponds to the configuration value for specifying that your service is to run on a particular version of the Windows Azure guest operating system. 
+     * @param string $label           A label for the operating system version.
+     * @param string $isDefault    	  Indicates whether this operating system version is the default version for a service that has not otherwise specified a particular version. The default operating system version is applied to services that are configured for auto-upgrade. An operating system family has exactly one default operating system version at any given time, for which the IsDefault element is set to true; for all other versions, IsDefault is set to false.
+     * @param string $isActive        Indicates whether this operating system version is currently active for running a service. If an operating system version is active, you can manually configure your service to run on that version.
+     * @param string $family          Indicates which operating system family this version belongs to. A value of 1 corresponds to the Windows Azure guest operating system that is substantially compatible with Windows Server 2008 SP2. A value of 2 corresponds to the Windows Azure guest operating system that is substantially compatible with Windows Server 2008 R2.
+     * @param string $familyLabel     A label for the operating system family.
+	 */
+    public function __construct($version, $label, $isDefault, $isActive, $family, $familyLabel) 
+    {	        
+        $this->_data = array(
+            'version'        => $version,
+            'label'          => base64_decode($label),
+            'isdefault'      => $isDefault,
+            'isactive'       => $isActive,
+            'family'         => $family,
+            'familylabel'    => base64_decode($familyLabel)        
+        );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/WindowsAzure/Management/OperationStatusInstance.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,60 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure
+ * @subpackage Management
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/**
+ * @see Zend_Service_WindowsAzure_Management_ServiceEntityAbstract
+ */
+require_once 'Zend/Service/WindowsAzure/Management/ServiceEntityAbstract.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure
+ * @subpackage Management
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * 
+ * @property string $Id              The request ID of the asynchronous request.
+ * @property string $Status          The status of the asynchronous request. Possible values include InProgress, Succeeded, or Failed.
+ * @property string $ErrorCode	     The management service error code returned if the asynchronous request failed. 
+ * @property string $ErrorMessage    The management service error message returned if the asynchronous request failed. 
+ */
+class Zend_Service_WindowsAzure_Management_OperationStatusInstance
+	extends Zend_Service_WindowsAzure_Management_ServiceEntityAbstract
+{    
+    /**
+     * Constructor
+     * 
+     * @param string $id              The request ID of the asynchronous request.
+     * @param string $status          The status of the asynchronous request. Possible values include InProgress, Succeeded, or Failed.
+     * @param string $errorCode	      The management service error code returned if the asynchronous request failed. 
+     * @param string $errorMessage    The management service error message returned if the asynchronous request failed.
+	 */
+    public function __construct($id, $status, $errorCode, $errorMessage) 
+    {	        
+        $this->_data = array(
+            'id'              => $id,
+            'status'          => $status,
+            'errorcode'       => $errorCode,
+            'errormessage'    => $errorMessage     
+        );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/WindowsAzure/Management/ServiceEntityAbstract.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,67 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure
+ * @subpackage Management
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+
+/**
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure
+ * @subpackage Management
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+abstract class Zend_Service_WindowsAzure_Management_ServiceEntityAbstract
+{
+    /**
+     * Data
+     * 
+     * @var array
+     */
+    protected $_data = null;
+    
+    /**
+     * Magic overload for setting properties
+     * 
+     * @param string $name     Name of the property
+     * @param string $value    Value to set
+     */
+    public function __set($name, $value) {
+        if (array_key_exists(strtolower($name), $this->_data)) {
+            $this->_data[strtolower($name)] = $value;
+            return;
+        }
+	require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+        throw new Zend_Service_WindowsAzure_Management_Exception("Unknown property: " . $name);
+    }
+
+    /**
+     * Magic overload for getting properties
+     * 
+     * @param string $name     Name of the property
+     */
+    public function __get($name) {
+        if (array_key_exists(strtolower($name), $this->_data)) {
+            return $this->_data[strtolower($name)];
+        }
+	require_once 'Zend/Service/WindowsAzure/Management/Exception.php';
+        throw new Zend_Service_WindowsAzure_Management_Exception("Unknown property: " . $name);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/WindowsAzure/Management/StorageServiceInstance.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,66 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure
+ * @subpackage Management
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/**
+ * @see Zend_Service_WindowsAzure_Management_ServiceEntityAbstract
+ */
+require_once 'Zend/Service/WindowsAzure/Management/ServiceEntityAbstract.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure
+ * @subpackage Management
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * 
+ * @property string $Url             The address of the storage account.
+ * @property string $ServiceName     The name of the storage account.
+ * @property string $Description	 A description of the storage account.
+ * @property string $AffinityGroup   The affinity group with which this storage account is associated.
+ * @property string $Location        The geo-location of the storage account in Windows Azure, if your storage account is not associated with an affinity group.
+ * @property string $Label           The label for the storage account.
+ */
+class Zend_Service_WindowsAzure_Management_StorageServiceInstance
+	extends Zend_Service_WindowsAzure_Management_ServiceEntityAbstract
+{    
+    /**
+     * Constructor
+     * 
+     * @param string $url             The address of the storage account.
+     * @param string $serviceName     The name of the storage account.
+	 * @param string $description	  A description of the storage account.
+	 * @param string $affinityGroup   The affinity group with which this storage account is associated.
+	 * @param string $location        The geo-location of the storage account in Windows Azure, if your storage account is not associated with an affinity group.
+	 * @param string $label           The label for the storage account.
+	 */
+    public function __construct($url, $serviceName, $description = '', $affinityGroup = '', $location = '', $label = '') 
+    {	        
+        $this->_data = array(
+            'url'              => $url,
+            'servicename'      => $serviceName,
+            'description'      => $description,
+            'affinitygroup'    => $affinityGroup,
+            'location'         => $location,
+            'label'            => base64_decode($label)        
+        );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Service/WindowsAzure/Management/SubscriptionOperationInstance.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,77 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure
+ * @subpackage Management
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id$
+ */
+
+/**
+ * @see Zend_Service_WindowsAzure_Management_ServiceEntityAbstract
+ */
+require_once 'Zend/Service/WindowsAzure/Management/ServiceEntityAbstract.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Service_WindowsAzure
+ * @subpackage Management
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * 
+ * @property string $operationId The globally unique identifier (GUID) of the operation.
+ * @property string $operationObjectId The target object for the operation. 
+ * @property string $operationName The name of the performed operation.
+ * @property array  $operationParameters The collection of parameters for the performed operation.
+ * @property array  $operationCaller A collection of attributes that identifies the source of the operation.
+ * @property array  $operationStatus The current status of the operation.
+ */
+class Zend_Service_WindowsAzure_Management_SubscriptionOperationInstance
+	extends Zend_Service_WindowsAzure_Management_ServiceEntityAbstract
+{    
+    /**
+     * Constructor
+     * 
+     * @param string $operationId The globally unique identifier (GUID) of the operation.
+     * @param string $operationObjectId The target object for the operation. 
+     * @param string $operationName The name of the performed operation.
+     * @param array  $operationParameters The collection of parameters for the performed operation.
+     * @param array  $operationCaller A collection of attributes that identifies the source of the operation.
+     * @param array  $operationStatus The current status of the operation.
+     */
+    public function __construct($operationId, $operationObjectId, $operationName, $operationParameters = array(), $operationCaller = array(), $operationStatus = array()) 
+    {	        
+        $this->_data = array(
+            'operationid'          => $operationId,
+	        'operationobjectid'    => $operationObjectId,
+	        'operationname'        => $operationName,
+	        'operationparameters'  => $operationParameters,
+	        'operationcaller'      => $operationCaller,
+	        'operationstatus'      => $operationStatus
+        );
+    }
+    
+	/**
+	 * Add operation parameter
+	 * 
+ 	 * @param	string	$name	Name
+ 	 * @param	string	$value  Value
+	 */
+    public function addOperationParameter($name, $value)
+    {
+    	$this->_data['operationparameters'][$name] = $value;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Soap/Server/Proxy.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,75 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Soap
+ * @subpackage AutoDiscover
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id:$
+ */
+
+class Zend_Soap_Server_Proxy
+{
+    /**
+     * @var object
+     */
+    protected $_classInstance;
+    /**
+     * @var string
+     */
+    protected $_className;
+    /**
+     * Constructor
+     * 
+     * @param object $service 
+     */
+    public function  __construct($className, $classArgs = array())
+    {
+        $class = new ReflectionClass($className);
+        $constructor = $class->getConstructor();
+	if ($constructor === null) {
+            $this->_classInstance = $class->newInstance();
+	} else {
+            $this->_classInstance = $class->newInstanceArgs($classArgs);
+	}
+	$this->_className = $className;
+    }
+    /**
+     * Proxy for the WS-I compliant call
+     * 
+     * @param  string $name
+     * @param  string $arguments
+     * @return array 
+     */
+    public function __call($name, $arguments)
+    {
+        $result = call_user_func_array(array($this->_classInstance, $name), $this->_preProcessArguments($arguments));
+        return array("{$name}Result"=>$result);
+    }
+    /**
+     *  Pre process arguments
+     * 
+     * @param  mixed $arguments
+     * @return array 
+     */
+    protected function _preProcessArguments($arguments)
+    {
+        if (count($arguments) == 1 && is_object($arguments[0])) {
+            return get_object_vars($arguments[0]);
+	} else {
+            return $arguments;
+	}
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Stdlib/CallbackHandler.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,301 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Stdlib
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+/**
+ * CallbackHandler
+ *
+ * A handler for a event, event, filterchain, etc. Abstracts PHP callbacks,
+ * primarily to allow for lazy-loading and ensuring availability of default
+ * arguments (currying).
+ *
+ * @category   Zend
+ * @package    Zend_Stdlib
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Stdlib_CallbackHandler
+{
+    /**
+     * @var string|array PHP callback to invoke
+     */
+    protected $callback;
+
+    /**
+     * Did an error occur when testing the validity of the callback?
+     * @var bool
+     */
+    protected $error = false;
+
+    /**
+     * Callback metadata, if any
+     * @var array
+     */
+    protected $metadata;
+
+    /**
+     * Constructor
+     * 
+     * @param  string $event Event to which slot is subscribed
+     * @param  string|array|object $callback PHP callback 
+     * @param  array $options Options used by the callback handler (e.g., priority)
+     * @return void
+     */
+    public function __construct($callback, array $metadata = array())
+    {
+        $this->metadata  = $metadata;
+        $this->registerCallback($callback);
+    }
+
+    /**
+     * Error handler
+     *
+     * Used by registerCallback() when calling is_callable() to capture engine warnings.
+     * 
+     * @param  int $errno 
+     * @param  string $errstr 
+     * @return void
+     */
+    public function errorHandler($errno, $errstr)
+    {
+        $this->error = true;
+    }
+
+    /**
+     * Registers the callback provided in the constructor
+     *
+     * If you have pecl/weakref {@see http://pecl.php.net/weakref} installed, 
+     * this method provides additional behavior.
+     *
+     * If a callback is a functor, or an array callback composing an object 
+     * instance, this method will pass the object to a WeakRef instance prior
+     * to registering the callback.
+     * 
+     * @param  Callable $callback 
+     * @return void
+     */
+    protected function registerCallback($callback)
+    {
+        set_error_handler(array($this, 'errorHandler'), E_STRICT);
+        $callable = is_callable($callback);
+        restore_error_handler();
+        if (!$callable || $this->error) {
+            require_once 'Zend/Stdlib/Exception/InvalidCallbackException.php';
+            throw new Zend_Stdlib_Exception_InvalidCallbackException('Invalid callback provided; not callable');
+        }
+
+        // If pecl/weakref is not installed, simply store the callback and return
+        if (!class_exists('WeakRef')) {
+            $this->callback = $callback;
+            return;
+        }
+
+        // If WeakRef exists, we want to use it.
+
+        // If we have a non-closure object, pass it to WeakRef, and then
+        // register it.
+        if (is_object($callback) && !$callback instanceof Closure) {
+            $this->callback = new WeakRef($callback);
+            return;
+        }
+
+        // If we have a string or closure, register as-is
+        if (!is_array($callback)) {
+            $this->callback = $callback;
+            return;
+        }
+
+        list($target, $method) = $callback;
+
+        // If we have an array callback, and the first argument is not an 
+        // object, register as-is
+        if (!is_object($target)) {
+            $this->callback = $callback;
+            return;
+        }
+
+        // We have an array callback with an object as the first argument;
+        // pass it to WeakRef, and then register the new callback
+        $target = new WeakRef($target);
+        $this->callback = array($target, $method);
+    }
+
+    /**
+     * Retrieve registered callback
+     * 
+     * @return Callable
+     */
+    public function getCallback()
+    {
+        $callback = $this->callback;
+
+        // String callbacks -- simply return
+        if (is_string($callback)) {
+            return $callback;
+        }
+
+        // WeakRef callbacks -- pull it out of the object and return it
+        if ($callback instanceof WeakRef) {
+            return $callback->get();
+        }
+
+        // Non-WeakRef object callback -- return it
+        if (is_object($callback)) {
+            return $callback;
+        }
+
+        // Array callback with WeakRef object -- retrieve the object first, and 
+        // then return
+        list($target, $method) = $callback;
+        if ($target instanceof WeakRef) {
+            return array($target->get(), $method);
+        }
+
+        // Otherwise, return it
+        return $callback;
+    }
+
+    /**
+     * Invoke handler
+     * 
+     * @param  array $args Arguments to pass to callback
+     * @return mixed
+     */
+    public function call(array $args = array())
+    {
+        $callback = $this->getCallback();
+
+        $isPhp54 = version_compare(PHP_VERSION, '5.4.0rc1', '>=');
+
+        if ($isPhp54 && is_string($callback)) {
+            $this->validateStringCallbackFor54($callback);
+        }
+
+        // Minor performance tweak; use call_user_func() until > 3 arguments 
+        // reached
+        switch (count($args)) {
+            case 0:
+                if ($isPhp54) {
+                    return $callback();
+                }
+                return call_user_func($callback);
+            case 1:
+                if ($isPhp54) {
+                    return $callback(array_shift($args));
+                }
+                return call_user_func($callback, array_shift($args));
+            case 2:
+                $arg1 = array_shift($args);
+                $arg2 = array_shift($args);
+                if ($isPhp54) {
+                    return $callback($arg1, $arg2);
+                }
+                return call_user_func($callback, $arg1, $arg2);
+            case 3:
+                $arg1 = array_shift($args);
+                $arg2 = array_shift($args);
+                $arg3 = array_shift($args);
+                if ($isPhp54) {
+                    return $callback($arg1, $arg2, $arg3);
+                }
+                return call_user_func($callback, $arg1, $arg2, $arg3);
+            default:
+                return call_user_func_array($callback, $args);
+        }
+    }
+
+    /**
+     * Invoke as functor
+     * 
+     * @return mixed
+     */
+    public function __invoke()
+    {
+        return $this->call(func_get_args());
+    }
+
+    /**
+     * Get all callback metadata
+     * 
+     * @return array
+     */
+    public function getMetadata()
+    {
+        return $this->metadata;
+    }
+
+    /**
+     * Retrieve a single metadatum
+     * 
+     * @param  string $name 
+     * @return mixed
+     */
+    public function getMetadatum($name)
+    {
+        if (array_key_exists($name, $this->metadata)) {
+            return $this->metadata[$name];
+        }
+        return null;
+    }
+
+    /**
+     * Validate a static method call
+     *
+     * Validates that a static method call in PHP 5.4 will actually work
+     * 
+     * @param  string $callback 
+     * @return true
+     * @throws Zend_Stdlib_Exception_InvalidCallbackException if invalid
+     */
+    protected function validateStringCallbackFor54($callback)
+    {
+        if (!strstr($callback, '::')) {
+            return true;
+        }
+
+        list($class, $method) = explode('::', $callback, 2);
+
+        if (!class_exists($class)) {
+            require_once 'Zend/Stdlib/Exception/InvalidCallbackException.php';
+            throw new Zend_Stdlib_Exception_InvalidCallbackException(sprintf(
+                'Static method call "%s" refers to a class that does not exist',
+                $callback
+            ));
+        }
+
+        $r = new ReflectionClass($class);
+        if (!$r->hasMethod($method)) {
+            require_once 'Zend/Stdlib/Exception/InvalidCallbackException.php';
+            throw new Zend_Stdlib_Exception_InvalidCallbackException(sprintf(
+                'Static method call "%s" refers to a method that does not exist',
+                $callback
+            ));
+        }
+        $m = $r->getMethod($method);
+        if (!$m->isStatic()) {
+            require_once 'Zend/Stdlib/Exception/InvalidCallbackException.php';
+            throw new Zend_Stdlib_Exception_InvalidCallbackException(sprintf(
+                'Static method call "%s" refers to a method that is not static',
+                $callback
+            ));
+        }
+
+        return true;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Stdlib/Exception.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,31 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Stdlib
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+/**
+ * Marker interface for Stdlib exceptions
+ *
+ * @category   Zend
+ * @package    Zend_Stdlib
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+interface Zend_Stdlib_Exception
+{
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Stdlib/Exception/InvalidCallbackException.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,35 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Stdlib
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+require_once 'Zend/Stdlib/Exception.php';
+
+/**
+ * Invalid callback exception
+ *
+ * @category   Zend
+ * @package    Zend_Stdlib
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Stdlib_Exception_InvalidCallbackException
+    extends DomainException
+    implements Zend_Stdlib_Exception
+{
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Stdlib/PriorityQueue.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,319 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Stdlib
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+require_once 'Zend/Stdlib/SplPriorityQueue.php';
+
+/**
+ * Re-usable, serializable priority queue implementation
+ *
+ * SplPriorityQueue acts as a heap; on iteration, each item is removed from the
+ * queue. If you wish to re-use such a queue, you need to clone it first. This 
+ * makes for some interesting issues if you wish to delete items from the queue,
+ * or, as already stated, iterate over it multiple times.
+ *
+ * This class aggregates items for the queue itself, but also composes an 
+ * "inner" iterator in the form of an SplPriorityQueue object for performing
+ * the actual iteration.
+ *
+ * @category   Zend
+ * @package    Zend_Stdlib
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Stdlib_PriorityQueue implements Countable, IteratorAggregate, Serializable
+{
+    const EXTR_DATA     = 0x00000001;
+    const EXTR_PRIORITY = 0x00000002;
+    const EXTR_BOTH     = 0x00000003;
+
+    /**
+     * Inner queue class to use for iteration
+     * @var string
+     */
+    protected $queueClass = 'Zend_Stdlib_SplPriorityQueue';
+
+    /**
+     * Actual items aggregated in the priority queue. Each item is an array
+     * with keys "data" and "priority".
+     * @var array
+     */
+    protected $items      = array();
+
+    /**
+     * Inner queue object
+     * @var SplPriorityQueue
+     */
+    protected $queue;
+
+    /**
+     * Insert an item into the queue
+     *
+     * Priority defaults to 1 (low priority) if none provided.
+     * 
+     * @param  mixed $data 
+     * @param  int $priority 
+     * @return Zend_Stdlib_PriorityQueue
+     */
+    public function insert($data, $priority = 1)
+    {
+        $priority = (int) $priority;
+        $this->items[] = array(
+            'data'     => $data,
+            'priority' => $priority,
+        );
+        $this->getQueue()->insert($data, $priority);
+        return $this;
+    }
+
+    /**
+     * Remove an item from the queue
+     *
+     * This is different than {@link extract()}; its purpose is to dequeue an
+     * item.
+     *
+     * This operation is potentially expensive, as it requires 
+     * re-initialization and re-population of the inner queue.
+     * 
+     * Note: this removes the first item matching the provided item found. If
+     * the same item has been added multiple times, it will not remove other 
+     * instances.
+     *
+     * @param  mixed $datum
+     * @return boolean False if the item was not found, true otherwise.
+     */
+    public function remove($datum)
+    {
+        $found = false;
+        foreach ($this->items as $key => $item) {
+            if ($item['data'] === $datum) {
+                $found = true;
+                break;
+            }
+        }
+        if ($found) {
+            unset($this->items[$key]);
+            $this->queue = null;
+            $queue = $this->getQueue();
+            foreach ($this->items as $item) {
+                $queue->insert($item['data'], $item['priority']);
+            }
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Is the queue empty?
+     * 
+     * @return bool
+     */
+    public function isEmpty()
+    {
+        return (0 === $this->count());
+    }
+
+    /**
+     * How many items are in the queue?
+     * 
+     * @return int
+     */
+    public function count()
+    {
+        return count($this->items);
+    }
+
+    /**
+     * Peek at the top node in the queue, based on priority.
+     * 
+     * @return mixed
+     */
+    public function top()
+    {
+        return $this->getIterator()->top();
+    }
+
+    /**
+     * Extract a node from the inner queue and sift up 
+     * 
+     * @return mixed
+     */
+    public function extract()
+    {
+        return $this->getQueue()->extract();
+    }
+
+    /**
+     * Retrieve the inner iterator
+     *
+     * SplPriorityQueue acts as a heap, which typically implies that as items
+     * are iterated, they are also removed. This does not work for situations
+     * where the queue may be iterated multiple times. As such, this class 
+     * aggregates the values, and also injects an SplPriorityQueue. This method 
+     * retrieves the inner queue object, and clones it for purposes of 
+     * iteration.
+     * 
+     * @return SplPriorityQueue
+     */
+    public function getIterator()
+    {
+        $queue = $this->getQueue();
+        return clone $queue;
+    }
+
+    /**
+     * Serialize the data structure
+     * 
+     * @return string
+     */
+    public function serialize()
+    {
+        return serialize($this->items);
+    }
+
+    /**
+     * Unserialize a string into a Zend_Stdlib_PriorityQueue object
+     *
+     * Serialization format is compatible with {@link Zend_Stdlib_SplPriorityQueue}
+     * 
+     * @param  string $data 
+     * @return void
+     */
+    public function unserialize($data)
+    {
+        foreach (unserialize($data) as $item) {
+            $this->insert($item['data'], $item['priority']);
+        }
+    }
+
+    /**
+     * Serialize to an array
+     *
+     * By default, returns only the item data, and in the order registered (not
+     * sorted). You may provide one of the EXTR_* flags as an argument, allowing
+     * the ability to return priorities or both data and priority.
+     * 
+     * @param  int $flag 
+     * @return array
+     */
+    public function toArray($flag = self::EXTR_DATA)
+    {
+        switch ($flag) {
+            case self::EXTR_BOTH:
+                return $this->items;
+            case self::EXTR_PRIORITY:
+                return array_map(array($this, 'returnPriority'), $this->items);
+            case self::EXTR_DATA:
+            default:
+                return array_map(array($this, 'returnData'), $this->items);
+        }
+    }
+
+    /**
+     * Specify the internal queue class
+     *
+     * Please see {@link getIterator()} for details on the necessity of an
+     * internal queue class. The class provided should extend SplPriorityQueue.
+     * 
+     * @param  string $class 
+     * @return Zend_Stdlib_PriorityQueue
+     */
+    public function setInternalQueueClass($class)
+    {
+        $this->queueClass = (string) $class;
+        return $this;
+    }
+
+    /**
+     * Does the queue contain the given datum?
+     * 
+     * @param  mixed $datum 
+     * @return bool
+     */
+    public function contains($datum)
+    {
+        foreach ($this->items as $item) {
+            if ($item['data'] === $datum) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Does the queue have an item with the given priority?
+     * 
+     * @param  int $priority 
+     * @return bool
+     */
+    public function hasPriority($priority)
+    {
+        foreach ($this->items as $item) {
+            if ($item['priority'] === $priority) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Get the inner priority queue instance
+     * 
+     * @return Zend_Stdlib_SplPriorityQueue
+     */
+    protected function getQueue()
+    {
+        if (null === $this->queue) {
+            $this->queue = new $this->queueClass();
+            if (!$this->queue instanceof SplPriorityQueue) {
+                throw new DomainException(sprintf(
+                    'Zend_Stdlib_PriorityQueue expects an internal queue of type SplPriorityQueue; received "%s"',
+                    get_class($this->queue)
+                ));
+            }
+        }
+        return $this->queue;
+    }
+
+    /**
+     * Return priority from an internal item
+     *
+     * Used as a lambda in toArray().
+     * 
+     * @param  array $item 
+     * @return mixed
+     */
+    public function returnPriority($item)
+    {
+        return $item['priority'];
+    }
+
+    /**
+     * Return data from an internal item
+     *
+     * Used as a lambda in toArray().
+     * 
+     * @param  array $item 
+     * @return mixed
+     */
+    public function returnData($item)
+    {
+        return $item['data'];
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Stdlib/SplPriorityQueue.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,499 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Stdlib
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+
+if (version_compare(PHP_VERSION, '5.3.0', '<')) {
+    /**
+     * SplPriorityQueue 
+     *
+     * PHP 5.2.X userland implementation of PHP's SplPriorityQueue
+     */
+    class SplPriorityQueue implements Iterator , Countable 
+    {
+        /**
+         * Extract data only
+         */
+        const EXTR_DATA = 0x00000001;
+
+        /**
+         * Extract priority only
+         */
+        const EXTR_PRIORITY = 0x00000002;
+
+        /**
+         * Extract an array of ('data' => $value, 'priority' => $priority)
+         */
+        const EXTR_BOTH = 0x00000003;
+
+        /**
+         * Count of items in the queue
+         * @var int
+         */
+        protected $count = 0;
+
+        /**
+         * Flag indicating what should be returned when iterating or extracting
+         * @var int
+         */
+        protected $extractFlags = self::EXTR_DATA;
+
+        /**
+         * @var bool|array
+         */
+        protected $preparedQueue = false;
+
+        /**
+         * All items in the queue
+         * @var array
+         */
+        protected $queue = array();
+
+        /**
+         * Constructor
+         * 
+         * Creates a new, empty queue
+         * 
+         * @return void
+         */
+        public function __construct()
+        {
+        }
+
+        /**
+         * Compare two priorities
+         *
+         * Returns positive integer if $priority1 is greater than $priority2, 0 
+         * if equal, negative otherwise.
+         *
+         * Unused internally, and only included in order to retain the same 
+         * interface as PHP's SplPriorityQueue.
+         *
+         * @param  mixed $priority1
+         * @param  mixed $priority2
+         * @return int
+         */
+        public function compare($priority1, $priority2)
+        {
+            if ($priority1 > $priority2) {
+                return 1;
+            }
+            if ($priority1 == $priority2) {
+                return 0;
+            }
+
+            return -1;
+        }
+
+        /**
+         * Countable: return number of items composed in the queue
+         * 
+         * @return int
+         */
+        public function count()
+        {
+            return $this->count;
+        }
+
+        /**
+         * Iterator: return current item
+         *
+         * @return mixed
+         */
+        public function current()
+        {
+            if (!$this->preparedQueue) {
+                $this->rewind();
+            }
+            if (!$this->count) {
+                throw new OutOfBoundsException('Cannot iterate SplPriorityQueue; no elements present');
+            }
+
+if (!is_array($this->preparedQueue)) {
+    throw new DomainException(sprintf(
+        "Queue was prepared, but is empty?\n    PreparedQueue: %s\n    Internal Queue: %s\n",
+        var_export($this->preparedQueue, 1),
+        var_export($this->queue, 1)
+    ));
+}
+
+            $return      = array_shift($this->preparedQueue);
+            $priority    = $return['priority'];
+            $priorityKey = $return['priorityKey'];
+            $key         = $return['key'];
+            unset($return['key']);
+            unset($return['priorityKey']);
+            unset($this->queue[$priorityKey][$key]);
+
+            switch ($this->extractFlags) {
+                case self::EXTR_DATA:
+                    return $return['data'];
+                case self::EXTR_PRIORITY:
+                    return $return['priority'];
+                case self::EXTR_BOTH:
+                default:
+                    return $return;
+            };
+        }
+
+        /**
+         * Extract a node from top of the heap and sift up
+         *
+         * Returns either the value, the priority, or both, depending on the extract flag.
+         *
+         * @return mixed;
+         */
+        public function extract()
+        {
+            if (!$this->count) {
+                return null;
+            }
+
+            if (!$this->preparedQueue) {
+                $this->prepareQueue();
+            }
+
+            if (empty($this->preparedQueue)) {
+                return null;
+            }
+
+            $return      = array_shift($this->preparedQueue);
+            $priority    = $return['priority'];
+            $priorityKey = $return['priorityKey'];
+            $key         = $return['key'];
+            unset($return['key']);
+            unset($return['priorityKey']);
+            unset($this->queue[$priorityKey][$key]);
+            $this->count--;
+
+            switch ($this->extractFlags) {
+                case self::EXTR_DATA:
+                    return $return['data'];
+                case self::EXTR_PRIORITY:
+                    return $return['priority'];
+                case self::EXTR_BOTH:
+                default:
+                    return $return;
+            };
+        }
+
+        /**
+         * Insert a value into the heap, at the specified priority
+         *
+         * @param  mixed $value
+         * @param  mixed $priority
+         * @return void
+         */
+        public function insert($value, $priority)
+        {
+            if (!is_scalar($priority)) {
+                $priority = serialize($priority);
+            }
+            if (!isset($this->queue[$priority])) {
+                $this->queue[$priority] = array();
+            }
+            $this->queue[$priority][] = $value;
+            $this->count++;
+            $this->preparedQueue = false;
+        }
+
+        /**
+         * Is the queue currently empty?
+         *
+         * @return bool
+         */
+        public function isEmpty()
+        {
+            return (0 == $this->count);
+        }
+
+        /**
+         * Iterator: return current key
+         *
+         * @return mixed Usually an int or string
+         */
+        public function key()
+        {
+            return $this->count;
+        }
+
+        /**
+         * Iterator: Move pointer forward
+         *
+         * @return void
+         */
+        public function next()
+        {
+            $this->count--;
+        }
+
+        /**
+         * Recover from corrupted state and allow further actions on the queue
+         *
+         * Unimplemented, and only included in order to retain the same interface as PHP's 
+         * SplPriorityQueue.
+         *
+         * @return void
+         */
+        public function recoverFromCorruption()
+        {
+        }
+
+        /**
+         * Iterator: Move pointer to first item
+         *
+         * @return void
+         */
+        public function rewind()
+        {
+            if (!$this->preparedQueue) {
+                $this->prepareQueue();
+            }
+        }
+
+        /**
+         * Set the extract flags
+         * 
+         * Defines what is extracted by SplPriorityQueue::current(), 
+         * SplPriorityQueue::top() and SplPriorityQueue::extract().
+         * 
+         * - SplPriorityQueue::EXTR_DATA (0x00000001): Extract the data
+         * - SplPriorityQueue::EXTR_PRIORITY (0x00000002): Extract the priority
+         * - SplPriorityQueue::EXTR_BOTH (0x00000003): Extract an array containing both
+         *
+         * The default mode is SplPriorityQueue::EXTR_DATA.
+         *
+         * @param  int $flags
+         * @return void
+         */
+        public function setExtractFlags($flags)
+        {
+            $expected = array(
+                self::EXTR_DATA => true,
+                self::EXTR_PRIORITY => true,
+                self::EXTR_BOTH => true,
+            );
+            if (!isset($expected[$flags])) {
+                throw new InvalidArgumentException(sprintf('Expected an EXTR_* flag; received %s', $flags));
+            }
+            $this->extractFlags = $flags;
+        }
+
+        /**
+         * Return the value or priority (or both) of the top node, depending on 
+         * the extract flag
+         *
+         * @return mixed
+         */
+        public function top()
+        {
+            $this->sort();
+            $keys = array_keys($this->queue);
+            $key  = array_shift($keys);
+            if (preg_match('/^(a|O):/', $key)) {
+                $key = unserialize($key);
+            }
+
+            if ($this->extractFlags == self::EXTR_PRIORITY) {
+                return $key;
+            }
+
+            if ($this->extractFlags == self::EXTR_DATA) {
+                return $this->queue[$key][0];
+            }
+
+            return array(
+                'data'     => $this->queue[$key][0],
+                'priority' => $key,
+            );
+        }
+
+        /**
+         * Iterator: is the current position valid for the queue
+         *
+         * @return bool
+         */
+        public function valid()
+        {
+            return (bool) $this->count;
+        }
+
+        /**
+         * Sort the queue
+         * 
+         * @return void
+         */
+        protected function sort()
+        {
+            krsort($this->queue);
+        }
+
+        /**
+         * Prepare the queue for iteration and/or extraction
+         * 
+         * @return void
+         */
+        protected function prepareQueue()
+        {
+            $this->sort();
+            $count = $this->count;
+            $queue = array();
+            foreach ($this->queue as $priority => $values) {
+                $priorityKey = $priority;
+                if (preg_match('/^(a|O):/', $priority)) {
+                    $priority = unserialize($priority);
+                }
+                foreach ($values as $key => $value) {
+                    $queue[$count] = array(
+                        'data'        => $value,
+                        'priority'    => $priority,
+                        'priorityKey' => $priorityKey,
+                        'key'         => $key,
+                    );
+                    $count--;
+                }
+            }
+            $this->preparedQueue = $queue;
+        }
+    }
+}
+
+/**
+ * Serializable version of SplPriorityQueue
+ *
+ * Also, provides predictable heap order for datums added with the same priority
+ * (i.e., they will be emitted in the same order they are enqueued).
+ *
+ * @category   Zend
+ * @package    Zend_Stdlib
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Stdlib_SplPriorityQueue extends SplPriorityQueue implements Serializable
+{
+    /**
+     * @var int Seed used to ensure queue order for items of the same priority
+     */
+    protected $serial = PHP_INT_MAX;
+
+    /**
+     * @var bool
+     */
+    protected $isPhp53;
+
+    /**
+     * Constructor
+     * 
+     * @return void
+     */
+    public function __construct()
+    {
+        $this->isPhp53 = version_compare(PHP_VERSION, '5.3', '>=');
+    }
+
+    /**
+     * Insert a value with a given priority
+     *
+     * Utilizes {@var $serial} to ensure that values of equal priority are 
+     * emitted in the same order in which they are inserted.
+     * 
+     * @param  mixed $datum 
+     * @param  mixed $priority 
+     * @return void
+     */
+    public function insert($datum, $priority)
+    {
+        // If using the native PHP SplPriorityQueue implementation, we need to
+        // hack around it to ensure that items registered at the same priority
+        // return in the order registered. In the userland version, this is not
+        // necessary.
+        if ($this->isPhp53) {
+            if (!is_array($priority)) {
+                $priority = array($priority, $this->serial--);
+            }
+        }
+        parent::insert($datum, $priority);
+    }
+
+    /**
+     * Serialize to an array
+     *
+     * Array will be priority => data pairs
+     * 
+     * @return array
+     */
+    public function toArray()
+    {
+        $this->setExtractFlags(self::EXTR_BOTH);
+        $array = array();
+        while ($this->valid()) {
+            $array[] = $this->current();
+            $this->next();
+        }
+        $this->setExtractFlags(self::EXTR_DATA);
+
+        // Iterating through a priority queue removes items
+        foreach ($array as $item) {
+            $this->insert($item['data'], $item['priority']);
+        }
+
+        // Return only the data
+        $return = array();
+        foreach ($array as $item) {
+            $return[] = $item['data'];
+        }
+
+        return $return;
+    }
+
+    /**
+     * Serialize
+     * 
+     * @return string
+     */
+    public function serialize()
+    {
+        $data = array();
+        $this->setExtractFlags(self::EXTR_BOTH);
+        while ($this->valid()) {
+            $data[] = $this->current();
+            $this->next();
+        }
+        $this->setExtractFlags(self::EXTR_DATA);
+
+        // Iterating through a priority queue removes items
+        foreach ($data as $item) {
+            $this->insert($item['data'], $item['priority']);
+        }
+
+        return serialize($data);
+    }
+
+    /**
+     * Deserialize
+     * 
+     * @param  string $data
+     * @return void
+     */
+    public function unserialize($data)
+    {
+        foreach (unserialize($data) as $item) {
+            $this->insert($item['data'], $item['priority']);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Tool/Framework/Manifest/ActionMetadata.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,31 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Tool
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: ActionMetadata.php 24593 2012-01-05 20:35:02Z matthew $
+ */
+
+/**
+ * @category   Zend
+ * @package    Zend_Tool
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Tool_Framework_Manifest_ActionMetadata
+{
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Tool/Framework/Manifest/Metadata.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,31 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Tool
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: Metadata.php 24593 2012-01-05 20:35:02Z matthew $
+ */
+
+/**
+ * @category   Zend
+ * @package    Zend_Tool
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Tool_Framework_Manifest_Metadata
+{
+    
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Tool/Framework/Manifest/ProviderMetadata.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,31 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Tool
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: ProviderMetadata.php 24593 2012-01-05 20:35:02Z matthew $
+ */
+
+/**
+ * @category   Zend
+ * @package    Zend_Tool
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Tool_Framework_Manifest_ProviderMetadata
+{
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Tool/Project/Context/Zf/ServicesDirectory.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,55 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Tool
+ * @subpackage Framework
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: ServicesDirectory.php 24593 2012-01-05 20:35:02Z matthew $
+ */
+
+/**
+ * @see Zend_Tool_Project_Context_Filesystem_Directory
+ */
+require_once 'Zend/Tool/Project/Context/Filesystem/Directory.php';
+
+/**
+ * This class is the front most class for utilizing Zend_Tool_Project
+ *
+ * A profile is a hierarchical set of resources that keep track of
+ * items within a specific project.
+ *
+ * @category   Zend
+ * @package    Zend_Tool
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Tool_Project_Context_Zf_ServicesDirectory extends Zend_Tool_Project_Context_Filesystem_Directory
+{
+    /**
+     * @var string
+     */
+    protected $_filesystemName = 'services';
+
+    /**
+     * Defined by Zend_Tool_Project_Context_Interface
+     *
+     * @return string
+     */
+    public function getName()
+    {
+        return 'ServicesDirectory';
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Tool/Project/Context/Zf/TestApplicationActionMethod.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,229 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Tool
+ * @subpackage Framework
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: ActionMethod.php 20096 2010-01-06 02:05:09Z bkarwin $
+ */
+
+/**
+ * @see Zend_Tool_Project_Context_Interface
+ */
+require_once 'Zend/Tool/Project/Context/Interface.php';
+
+/**
+ * @see Zend_Reflection_File
+ */
+require_once 'Zend/Reflection/File.php';
+
+/**
+ * This class is the front most class for utilizing Zend_Tool_Project
+ *
+ * A profile is a hierarchical set of resources that keep track of
+ * items within a specific project.
+ *
+ * @category   Zend
+ * @package    Zend_Tool
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Tool_Project_Context_Zf_TestApplicationActionMethod implements Zend_Tool_Project_Context_Interface
+{
+
+    /**
+     * @var Zend_Tool_Project_Profile_Resource
+     */
+    protected $_resource = null;
+
+    /**
+     * @var Zend_Tool_Project_Profile_Resource
+     */
+    protected $_testApplicationControllerResource = null;
+
+    /**
+     * @var string
+     */
+    protected $_testApplicationControllerPath = '';
+
+    /**
+     * @var string
+     */
+    protected $_forActionName = null;
+
+    /**
+     * init()
+     *
+     * @return Zend_Tool_Project_Context_Zf_ActionMethod
+     */
+    public function init()
+    {
+        $this->_forActionName = $this->_resource->getAttribute('forActionName');
+
+        $this->_resource->setAppendable(false);
+        $this->_testApplicationControllerResource = $this->_resource->getParentResource();
+        if (!$this->_testApplicationControllerResource->getContext() instanceof Zend_Tool_Project_Context_Zf_TestApplicationControllerFile) {
+            require_once 'Zend/Tool/Project/Context/Exception.php';
+            throw new Zend_Tool_Project_Context_Exception('ActionMethod must be a sub resource of a TestApplicationControllerFile');
+        }
+        // make the ControllerFile node appendable so we can tack on the actionMethod.
+        $this->_resource->getParentResource()->setAppendable(true);
+
+        $this->_testApplicationControllerPath = $this->_testApplicationControllerResource->getContext()->getPath();
+
+        return $this;
+    }
+
+    /**
+     * getPersistentAttributes
+     *
+     * @return array
+     */
+    public function getPersistentAttributes()
+    {
+        return array(
+            'forActionName' => $this->getForActionName()
+            );
+    }
+
+    /**
+     * getName()
+     *
+     * @return string
+     */
+    public function getName()
+    {
+        return 'TestApplicationActionMethod';
+    }
+
+    /**
+     * setResource()
+     *
+     * @param Zend_Tool_Project_Profile_Resource $resource
+     * @return Zend_Tool_Project_Context_Zf_ActionMethod
+     */
+    public function setResource(Zend_Tool_Project_Profile_Resource $resource)
+    {
+        $this->_resource = $resource;
+        return $this;
+    }
+
+    /**
+     * getActionName()
+     *
+     * @return string
+     */
+    public function getForActionName()
+    {
+        return $this->_forActionName;
+    }
+
+    /**
+     * create()
+     *
+     * @return Zend_Tool_Project_Context_Zf_ActionMethod
+     */
+    public function create()
+    {
+        $file = $this->_testApplicationControllerPath;
+        
+        if (!file_exists($file)) {
+            require_once 'Zend/Tool/Project/Context/Exception.php';
+            throw new Zend_Tool_Project_Context_Exception(
+                'Could not create action within test controller ' . $file
+                . ' with action name ' . $this->_forActionName
+                );
+        }
+        
+        $actionParam = $this->getForActionName();
+        $controllerParam = $this->_resource->getParentResource()->getForControllerName();
+        //$moduleParam = null;//
+        
+        /* @var $controllerDirectoryResource Zend_Tool_Project_Profile_Resource */
+        $controllerDirectoryResource = $this->_resource->getParentResource()->getParentResource();
+        if ($controllerDirectoryResource->getParentResource()->getName() == 'TestApplicationModuleDirectory') {
+            $moduleParam = $controllerDirectoryResource->getParentResource()->getForModuleName();
+        } else {
+            $moduleParam = 'default';
+        }
+        
+        
+
+        if ($actionParam == 'index' && $controllerParam == 'Index' && $moduleParam == 'default') {
+            $assert = '$this->assertQueryContentContains("div#welcome h3", "This is your project\'s main page");';
+        } else {
+            $assert = <<<EOS
+\$this->assertQueryContentContains(
+    'div#view-content p',
+    'View script for controller <b>' . \$params['controller'] . '</b> and script/action name <b>' . \$params['action'] . '</b>'
+    );
+EOS;
+        }
+        
+        $codeGenFile = Zend_CodeGenerator_Php_File::fromReflectedFileName($file, true, true);
+        $codeGenFile->getClass()->setMethod(array(
+            'name' => 'test' . ucfirst($actionParam) . 'Action',
+            'body' => <<<EOS
+\$params = array('action' => '$actionParam', 'controller' => '$controllerParam', 'module' => '$moduleParam');
+\$urlParams = \$this->urlizeOptions(\$params);
+\$url = \$this->url(\$urlParams);
+\$this->dispatch(\$url);
+
+// assertions
+\$this->assertModule(\$urlParams['module']);
+\$this->assertController(\$urlParams['controller']);
+\$this->assertAction(\$urlParams['action']);
+$assert
+
+EOS
+            ));
+
+        file_put_contents($file, $codeGenFile->generate());
+        
+        return $this;
+    }
+
+    /**
+     * delete()
+     *
+     * @return Zend_Tool_Project_Context_Zf_ActionMethod
+     */
+    public function delete()
+    {
+        // @todo do this
+        return $this;
+    }
+
+    /**
+     * hasActionMethod()
+     *
+     * @param string $controllerPath
+     * @param string $actionName
+     * @return bool
+     */
+    /*
+    public static function hasActionMethod($controllerPath, $actionName)
+    {
+        if (!file_exists($controllerPath)) {
+            return false;
+        }
+
+        $controllerCodeGenFile = Zend_CodeGenerator_Php_File::fromReflectedFileName($controllerPath, true, true);
+        return $controllerCodeGenFile->getClass()->hasMethod('test' . $actionName . 'Action');
+    }
+    */
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Tool/Project/Context/Zf/TestApplicationModuleDirectory.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,98 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Tool
+ * @subpackage Framework
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: TestApplicationControllerDirectory.php 20096 2010-01-06 02:05:09Z bkarwin $
+ */
+
+/**
+ * @see Zend_Tool_Project_Context_Filesystem_Directory
+ */
+require_once 'Zend/Tool/Project/Context/Filesystem/Directory.php';
+
+/**
+ * This class is the front most class for utilizing Zend_Tool_Project
+ *
+ * A profile is a hierarchical set of resources that keep track of
+ * items within a specific project.
+ *
+ * @category   Zend
+ * @package    Zend_Tool
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Tool_Project_Context_Zf_TestApplicationModuleDirectory extends Zend_Tool_Project_Context_Filesystem_Directory
+{
+
+
+    /**
+     * @var string
+     */
+    protected $_forModuleName = null;
+
+    /**
+     * @var string
+     */
+    protected $_filesystemName = 'moduleDirectory';
+
+    /**
+     * init()
+     *
+     * @return Zend_Tool_Project_Context_Zf_ControllerFile
+     */
+    public function init()
+    {
+        $this->_filesystemName = $this->_forModuleName = $this->_resource->getAttribute('forModuleName');
+        parent::init();
+        return $this;
+    }
+
+    /**
+     * getName()
+     *
+     * @return string
+     */
+    public function getName()
+    {
+        return 'TestApplicationModuleDirectory';
+    }
+
+    /**
+     * getPersistentAttributes
+     *
+     * @return array
+     */
+    public function getPersistentAttributes()
+    {
+        return array(
+            'forModuleName' => $this->getForModuleName()
+            );
+    }
+
+    /**
+     * getModuleName()
+     *
+     * @return string
+     */
+    public function getForModuleName()
+    {
+        return $this->_forModuleName;
+    }
+    
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Tool/Project/Context/Zf/TestApplicationModulesDirectory.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,57 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Tool
+ * @subpackage Framework
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: TestApplicationControllerDirectory.php 20096 2010-01-06 02:05:09Z bkarwin $
+ */
+
+/**
+ * @see Zend_Tool_Project_Context_Filesystem_Directory
+ */
+require_once 'Zend/Tool/Project/Context/Filesystem/Directory.php';
+
+/**
+ * This class is the front most class for utilizing Zend_Tool_Project
+ *
+ * A profile is a hierarchical set of resources that keep track of
+ * items within a specific project.
+ *
+ * @category   Zend
+ * @package    Zend_Tool
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Tool_Project_Context_Zf_TestApplicationModulesDirectory extends Zend_Tool_Project_Context_Filesystem_Directory
+{
+
+    /**
+     * @var string
+     */
+    protected $_filesystemName = 'modules';
+
+    /**
+     * getName()
+     *
+     * @return string
+     */
+    public function getName()
+    {
+        return 'TestApplicationModulesDirectory';
+    }
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Tool/Project/Context/Zf/TestPHPUnitBootstrapFile.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,88 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Tool
+ * @subpackage Framework
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: TestApplicationBootstrapFile.php 20096 2010-01-06 02:05:09Z bkarwin $
+ */
+
+/**
+ * @see Zend_Tool_Project_Context_Filesystem_File
+ */
+require_once 'Zend/Tool/Project/Context/Filesystem/File.php';
+
+/**
+ * This class is the front most class for utilizing Zend_Tool_Project
+ *
+ * A profile is a hierarchical set of resources that keep track of
+ * items within a specific project.
+ *
+ * @category   Zend
+ * @package    Zend_Tool
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Tool_Project_Context_Zf_TestPHPUnitBootstrapFile extends Zend_Tool_Project_Context_Filesystem_File
+{
+
+    /**
+     * @var string
+     */
+    protected $_filesystemName = 'bootstrap.php';
+
+    /**
+     * getName()
+     *
+     * @return string
+     */
+    public function getName()
+    {
+        return 'TestPHPUnitBootstrapFile';
+    }
+    
+    /**
+     * getContents()
+     *
+     * @return string
+     */
+    public function getContents()
+    {
+        $codeGenerator = new Zend_CodeGenerator_Php_File(array(
+            'body' => <<<EOS
+// Define path to application directory
+defined('APPLICATION_PATH')
+    || define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application'));
+
+// Define application environment
+defined('APPLICATION_ENV')
+    || define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'testing'));
+
+// Ensure library/ is on include_path
+set_include_path(implode(PATH_SEPARATOR, array(
+    realpath(APPLICATION_PATH . '/../library'),
+    get_include_path(),
+)));
+
+require_once 'Zend/Loader/Autoloader.php';
+Zend_Loader_Autoloader::getInstance();
+
+EOS
+            ));
+        return $codeGenerator->generate();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/lib/Zend/Validate/Ldap/Dn.php	Thu Mar 21 19:52:38 2013 +0100
@@ -0,0 +1,65 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category   Zend
+ * @package    Zend_Validate
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ * @version    $Id: Abstract.php 24807 2012-05-15 12:10:42Z adamlundrigan $
+ */
+
+/**
+ * @see Zend_Validate_Interface
+ */
+require_once 'Zend/Validate/Abstract.php';
+
+/**
+ * @category   Zend
+ * @package    Zend_Validate
+ * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license    http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Validate_Ldap_Dn extends Zend_Validate_Abstract
+{
+
+    const MALFORMED = 'malformed';
+    
+    /**
+     * Validation failure message template definitions.
+     *
+     * @var array
+     */
+    protected $_messageTemplates = array(
+        self::MALFORMED => 'DN is malformed',
+    );
+    
+    /**
+     * Defined by Zend_Validate_Interface.
+     *
+     * Returns true if and only if $value is a valid DN.
+     *
+     * @param string $value The value to be validated.
+     * 
+     * @return boolean
+     */
+    public function isValid($value) 
+    {
+        $valid = Zend_Ldap_Dn::checkDn($value);
+        if ($valid === false) {
+            $this->_error(self::MALFORMED);
+            return false;
+        }
+        return true;
+    }
+}
\ No newline at end of file