diff --git a/lib/thirdpartylibs.xml b/lib/thirdpartylibs.xml
index d560b630485..2eb34700c5c 100644
--- a/lib/thirdpartylibs.xml
+++ b/lib/thirdpartylibs.xml
@@ -200,7 +200,7 @@
zend
Zend Framework
BSD
- 1.10.6
+ 1.12.16
diff --git a/lib/zend/Zend/Acl.php b/lib/zend/Zend/Acl.php
new file mode 100644
index 00000000000..a5d169f56ac
--- /dev/null
+++ b/lib/zend/Zend/Acl.php
@@ -0,0 +1,1242 @@
+ array(
+ 'allRoles' => array(
+ 'allPrivileges' => array(
+ 'type' => self::TYPE_DENY,
+ 'assert' => null
+ ),
+ 'byPrivilegeId' => array()
+ ),
+ 'byRoleId' => array()
+ ),
+ 'byResourceId' => array()
+ );
+
+ /**
+ * Adds a Role having an identifier unique to the registry
+ *
+ * The $parents parameter may be a reference to, or the string identifier for,
+ * a Role existing in the registry, or $parents may be passed as an array of
+ * these - mixing string identifiers and objects is ok - to indicate the Roles
+ * from which the newly added Role will directly inherit.
+ *
+ * In order to resolve potential ambiguities with conflicting rules inherited
+ * from different parents, the most recently added parent takes precedence over
+ * parents that were previously added. In other words, the first parent added
+ * will have the least priority, and the last parent added will have the
+ * highest priority.
+ *
+ * @param Zend_Acl_Role_Interface|string $role
+ * @param Zend_Acl_Role_Interface|string|array $parents
+ * @uses Zend_Acl_Role_Registry::add()
+ * @return Zend_Acl Provides a fluent interface
+ */
+ public function addRole($role, $parents = null)
+ {
+ if (is_string($role)) {
+ $role = new Zend_Acl_Role($role);
+ }
+
+ if (!$role instanceof Zend_Acl_Role_Interface) {
+ require_once 'Zend/Acl/Exception.php';
+ throw new Zend_Acl_Exception('addRole() expects $role to be of type Zend_Acl_Role_Interface');
+ }
+
+
+ $this->_getRoleRegistry()->add($role, $parents);
+
+ return $this;
+ }
+
+ /**
+ * Returns the identified Role
+ *
+ * The $role parameter can either be a Role or Role identifier.
+ *
+ * @param Zend_Acl_Role_Interface|string $role
+ * @uses Zend_Acl_Role_Registry::get()
+ * @return Zend_Acl_Role_Interface
+ */
+ public function getRole($role)
+ {
+ return $this->_getRoleRegistry()->get($role);
+ }
+
+ /**
+ * Returns true if and only if the Role exists in the registry
+ *
+ * The $role parameter can either be a Role or a Role identifier.
+ *
+ * @param Zend_Acl_Role_Interface|string $role
+ * @uses Zend_Acl_Role_Registry::has()
+ * @return boolean
+ */
+ public function hasRole($role)
+ {
+ return $this->_getRoleRegistry()->has($role);
+ }
+
+ /**
+ * Returns true if and only if $role inherits from $inherit
+ *
+ * Both parameters may be either a Role or a Role identifier. If
+ * $onlyParents is true, then $role must inherit directly from
+ * $inherit in order to return true. By default, this method looks
+ * through the entire inheritance DAG to determine whether $role
+ * inherits from $inherit through its ancestor Roles.
+ *
+ * @param Zend_Acl_Role_Interface|string $role
+ * @param Zend_Acl_Role_Interface|string $inherit
+ * @param boolean $onlyParents
+ * @uses Zend_Acl_Role_Registry::inherits()
+ * @return boolean
+ */
+ public function inheritsRole($role, $inherit, $onlyParents = false)
+ {
+ return $this->_getRoleRegistry()->inherits($role, $inherit, $onlyParents);
+ }
+
+ /**
+ * Removes the Role from the registry
+ *
+ * The $role parameter can either be a Role or a Role identifier.
+ *
+ * @param Zend_Acl_Role_Interface|string $role
+ * @uses Zend_Acl_Role_Registry::remove()
+ * @return Zend_Acl Provides a fluent interface
+ */
+ public function removeRole($role)
+ {
+ $this->_getRoleRegistry()->remove($role);
+
+ if ($role instanceof Zend_Acl_Role_Interface) {
+ $roleId = $role->getRoleId();
+ } else {
+ $roleId = $role;
+ }
+
+ foreach ($this->_rules['allResources']['byRoleId'] as $roleIdCurrent => $rules) {
+ if ($roleId === $roleIdCurrent) {
+ unset($this->_rules['allResources']['byRoleId'][$roleIdCurrent]);
+ }
+ }
+ foreach ($this->_rules['byResourceId'] as $resourceIdCurrent => $visitor) {
+ if (array_key_exists('byRoleId', $visitor)) {
+ foreach ($visitor['byRoleId'] as $roleIdCurrent => $rules) {
+ if ($roleId === $roleIdCurrent) {
+ unset($this->_rules['byResourceId'][$resourceIdCurrent]['byRoleId'][$roleIdCurrent]);
+ }
+ }
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Removes all Roles from the registry
+ *
+ * @uses Zend_Acl_Role_Registry::removeAll()
+ * @return Zend_Acl Provides a fluent interface
+ */
+ public function removeRoleAll()
+ {
+ $this->_getRoleRegistry()->removeAll();
+
+ foreach ($this->_rules['allResources']['byRoleId'] as $roleIdCurrent => $rules) {
+ unset($this->_rules['allResources']['byRoleId'][$roleIdCurrent]);
+ }
+ foreach ($this->_rules['byResourceId'] as $resourceIdCurrent => $visitor) {
+ foreach ($visitor['byRoleId'] as $roleIdCurrent => $rules) {
+ unset($this->_rules['byResourceId'][$resourceIdCurrent]['byRoleId'][$roleIdCurrent]);
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Adds a Resource having an identifier unique to the ACL
+ *
+ * The $parent parameter may be a reference to, or the string identifier for,
+ * the existing Resource from which the newly added Resource will inherit.
+ *
+ * @param Zend_Acl_Resource_Interface|string $resource
+ * @param Zend_Acl_Resource_Interface|string $parent
+ * @throws Zend_Acl_Exception
+ * @return Zend_Acl Provides a fluent interface
+ */
+ public function addResource($resource, $parent = null)
+ {
+ if (is_string($resource)) {
+ $resource = new Zend_Acl_Resource($resource);
+ }
+
+ if (!$resource instanceof Zend_Acl_Resource_Interface) {
+ require_once 'Zend/Acl/Exception.php';
+ throw new Zend_Acl_Exception('addResource() expects $resource to be of type Zend_Acl_Resource_Interface');
+ }
+
+ $resourceId = $resource->getResourceId();
+
+ if ($this->has($resourceId)) {
+ require_once 'Zend/Acl/Exception.php';
+ throw new Zend_Acl_Exception("Resource id '$resourceId' already exists in the ACL");
+ }
+
+ $resourceParent = null;
+
+ if (null !== $parent) {
+ try {
+ if ($parent instanceof Zend_Acl_Resource_Interface) {
+ $resourceParentId = $parent->getResourceId();
+ } else {
+ $resourceParentId = $parent;
+ }
+ $resourceParent = $this->get($resourceParentId);
+ } catch (Zend_Acl_Exception $e) {
+ require_once 'Zend/Acl/Exception.php';
+ throw new Zend_Acl_Exception("Parent Resource id '$resourceParentId' does not exist", 0, $e);
+ }
+ $this->_resources[$resourceParentId]['children'][$resourceId] = $resource;
+ }
+
+ $this->_resources[$resourceId] = array(
+ 'instance' => $resource,
+ 'parent' => $resourceParent,
+ 'children' => array()
+ );
+
+ return $this;
+ }
+
+ /**
+ * Adds a Resource having an identifier unique to the ACL
+ *
+ * The $parent parameter may be a reference to, or the string identifier for,
+ * the existing Resource from which the newly added Resource will inherit.
+ *
+ * @deprecated in version 1.9.1 and will be available till 2.0. New code
+ * should use addResource() instead.
+ *
+ * @param Zend_Acl_Resource_Interface $resource
+ * @param Zend_Acl_Resource_Interface|string $parent
+ * @throws Zend_Acl_Exception
+ * @return Zend_Acl Provides a fluent interface
+ */
+ public function add(Zend_Acl_Resource_Interface $resource, $parent = null)
+ {
+ return $this->addResource($resource, $parent);
+ }
+
+ /**
+ * Returns the identified Resource
+ *
+ * The $resource parameter can either be a Resource or a Resource identifier.
+ *
+ * @param Zend_Acl_Resource_Interface|string $resource
+ * @throws Zend_Acl_Exception
+ * @return Zend_Acl_Resource_Interface
+ */
+ public function get($resource)
+ {
+ if ($resource instanceof Zend_Acl_Resource_Interface) {
+ $resourceId = $resource->getResourceId();
+ } else {
+ $resourceId = (string) $resource;
+ }
+
+ if (!$this->has($resource)) {
+ require_once 'Zend/Acl/Exception.php';
+ throw new Zend_Acl_Exception("Resource '$resourceId' not found");
+ }
+
+ return $this->_resources[$resourceId]['instance'];
+ }
+
+ /**
+ * Returns true if and only if the Resource exists in the ACL
+ *
+ * The $resource parameter can either be a Resource or a Resource identifier.
+ *
+ * @param Zend_Acl_Resource_Interface|string $resource
+ * @return boolean
+ */
+ public function has($resource)
+ {
+ if ($resource instanceof Zend_Acl_Resource_Interface) {
+ $resourceId = $resource->getResourceId();
+ } else {
+ $resourceId = (string) $resource;
+ }
+
+ return isset($this->_resources[$resourceId]);
+ }
+
+ /**
+ * Returns true if and only if $resource inherits from $inherit
+ *
+ * Both parameters may be either a Resource or a Resource identifier. If
+ * $onlyParent is true, then $resource must inherit directly from
+ * $inherit in order to return true. By default, this method looks
+ * through the entire inheritance tree to determine whether $resource
+ * inherits from $inherit through its ancestor Resources.
+ *
+ * @param Zend_Acl_Resource_Interface|string $resource
+ * @param Zend_Acl_Resource_Interface|string $inherit
+ * @param boolean $onlyParent
+ * @throws Zend_Acl_Resource_Registry_Exception
+ * @return boolean
+ */
+ public function inherits($resource, $inherit, $onlyParent = false)
+ {
+ try {
+ $resourceId = $this->get($resource)->getResourceId();
+ $inheritId = $this->get($inherit)->getResourceId();
+ } catch (Zend_Acl_Exception $e) {
+ require_once 'Zend/Acl/Exception.php';
+ throw new Zend_Acl_Exception($e->getMessage(), $e->getCode(), $e);
+ }
+
+ if (null !== $this->_resources[$resourceId]['parent']) {
+ $parentId = $this->_resources[$resourceId]['parent']->getResourceId();
+ if ($inheritId === $parentId) {
+ return true;
+ } else if ($onlyParent) {
+ return false;
+ }
+ } else {
+ return false;
+ }
+
+ while (null !== $this->_resources[$parentId]['parent']) {
+ $parentId = $this->_resources[$parentId]['parent']->getResourceId();
+ if ($inheritId === $parentId) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Removes a Resource and all of its children
+ *
+ * The $resource parameter can either be a Resource or a Resource identifier.
+ *
+ * @param Zend_Acl_Resource_Interface|string $resource
+ * @throws Zend_Acl_Exception
+ * @return Zend_Acl Provides a fluent interface
+ */
+ public function remove($resource)
+ {
+ try {
+ $resourceId = $this->get($resource)->getResourceId();
+ } catch (Zend_Acl_Exception $e) {
+ require_once 'Zend/Acl/Exception.php';
+ throw new Zend_Acl_Exception($e->getMessage(), $e->getCode(), $e);
+ }
+
+ $resourcesRemoved = array($resourceId);
+ if (null !== ($resourceParent = $this->_resources[$resourceId]['parent'])) {
+ unset($this->_resources[$resourceParent->getResourceId()]['children'][$resourceId]);
+ }
+ foreach ($this->_resources[$resourceId]['children'] as $childId => $child) {
+ $this->remove($childId);
+ $resourcesRemoved[] = $childId;
+ }
+
+ foreach ($resourcesRemoved as $resourceIdRemoved) {
+ foreach ($this->_rules['byResourceId'] as $resourceIdCurrent => $rules) {
+ if ($resourceIdRemoved === $resourceIdCurrent) {
+ unset($this->_rules['byResourceId'][$resourceIdCurrent]);
+ }
+ }
+ }
+
+ unset($this->_resources[$resourceId]);
+
+ return $this;
+ }
+
+ /**
+ * Removes all Resources
+ *
+ * @return Zend_Acl Provides a fluent interface
+ */
+ public function removeAll()
+ {
+ foreach ($this->_resources as $resourceId => $resource) {
+ foreach ($this->_rules['byResourceId'] as $resourceIdCurrent => $rules) {
+ if ($resourceId === $resourceIdCurrent) {
+ unset($this->_rules['byResourceId'][$resourceIdCurrent]);
+ }
+ }
+ }
+
+ $this->_resources = array();
+
+ return $this;
+ }
+
+ /**
+ * Adds an "allow" rule to the ACL
+ *
+ * @param Zend_Acl_Role_Interface|string|array $roles
+ * @param Zend_Acl_Resource_Interface|string|array $resources
+ * @param string|array $privileges
+ * @param Zend_Acl_Assert_Interface $assert
+ * @uses Zend_Acl::setRule()
+ * @return Zend_Acl Provides a fluent interface
+ */
+ public function allow($roles = null, $resources = null, $privileges = null, Zend_Acl_Assert_Interface $assert = null)
+ {
+ return $this->setRule(self::OP_ADD, self::TYPE_ALLOW, $roles, $resources, $privileges, $assert);
+ }
+
+ /**
+ * Adds a "deny" rule to the ACL
+ *
+ * @param Zend_Acl_Role_Interface|string|array $roles
+ * @param Zend_Acl_Resource_Interface|string|array $resources
+ * @param string|array $privileges
+ * @param Zend_Acl_Assert_Interface $assert
+ * @uses Zend_Acl::setRule()
+ * @return Zend_Acl Provides a fluent interface
+ */
+ public function deny($roles = null, $resources = null, $privileges = null, Zend_Acl_Assert_Interface $assert = null)
+ {
+ return $this->setRule(self::OP_ADD, self::TYPE_DENY, $roles, $resources, $privileges, $assert);
+ }
+
+ /**
+ * Removes "allow" permissions from the ACL
+ *
+ * @param Zend_Acl_Role_Interface|string|array $roles
+ * @param Zend_Acl_Resource_Interface|string|array $resources
+ * @param string|array $privileges
+ * @uses Zend_Acl::setRule()
+ * @return Zend_Acl Provides a fluent interface
+ */
+ public function removeAllow($roles = null, $resources = null, $privileges = null)
+ {
+ return $this->setRule(self::OP_REMOVE, self::TYPE_ALLOW, $roles, $resources, $privileges);
+ }
+
+ /**
+ * Removes "deny" restrictions from the ACL
+ *
+ * @param Zend_Acl_Role_Interface|string|array $roles
+ * @param Zend_Acl_Resource_Interface|string|array $resources
+ * @param string|array $privileges
+ * @uses Zend_Acl::setRule()
+ * @return Zend_Acl Provides a fluent interface
+ */
+ public function removeDeny($roles = null, $resources = null, $privileges = null)
+ {
+ return $this->setRule(self::OP_REMOVE, self::TYPE_DENY, $roles, $resources, $privileges);
+ }
+
+ /**
+ * Performs operations on ACL rules
+ *
+ * The $operation parameter may be either OP_ADD or OP_REMOVE, depending on whether the
+ * user wants to add or remove a rule, respectively:
+ *
+ * OP_ADD specifics:
+ *
+ * A rule is added that would allow one or more Roles access to [certain $privileges
+ * upon] the specified Resource(s).
+ *
+ * OP_REMOVE specifics:
+ *
+ * The rule is removed only in the context of the given Roles, Resources, and privileges.
+ * Existing rules to which the remove operation does not apply would remain in the
+ * ACL.
+ *
+ * The $type parameter may be either TYPE_ALLOW or TYPE_DENY, depending on whether the
+ * rule is intended to allow or deny permission, respectively.
+ *
+ * The $roles and $resources parameters may be references to, or the string identifiers for,
+ * existing Resources/Roles, or they may be passed as arrays of these - mixing string identifiers
+ * and objects is ok - to indicate the Resources and Roles to which the rule applies. If either
+ * $roles or $resources is null, then the rule applies to all Roles or all Resources, respectively.
+ * Both may be null in order to work with the default rule of the ACL.
+ *
+ * The $privileges parameter may be used to further specify that the rule applies only
+ * to certain privileges upon the Resource(s) in question. This may be specified to be a single
+ * privilege with a string, and multiple privileges may be specified as an array of strings.
+ *
+ * If $assert is provided, then its assert() method must return true in order for
+ * the rule to apply. If $assert is provided with $roles, $resources, and $privileges all
+ * equal to null, then a rule having a type of:
+ *
+ * TYPE_ALLOW will imply a type of TYPE_DENY, and
+ *
+ * TYPE_DENY will imply a type of TYPE_ALLOW
+ *
+ * when the rule's assertion fails. This is because the ACL needs to provide expected
+ * behavior when an assertion upon the default ACL rule fails.
+ *
+ * @param string $operation
+ * @param string $type
+ * @param Zend_Acl_Role_Interface|string|array $roles
+ * @param Zend_Acl_Resource_Interface|string|array $resources
+ * @param string|array $privileges
+ * @param Zend_Acl_Assert_Interface $assert
+ * @throws Zend_Acl_Exception
+ * @uses Zend_Acl_Role_Registry::get()
+ * @uses Zend_Acl::get()
+ * @return Zend_Acl Provides a fluent interface
+ */
+ public function setRule($operation, $type, $roles = null, $resources = null, $privileges = null,
+ Zend_Acl_Assert_Interface $assert = null)
+ {
+ // ensure that the rule type is valid; normalize input to uppercase
+ $type = strtoupper($type);
+ if (self::TYPE_ALLOW !== $type && self::TYPE_DENY !== $type) {
+ require_once 'Zend/Acl/Exception.php';
+ throw new Zend_Acl_Exception("Unsupported rule type; must be either '" . self::TYPE_ALLOW . "' or '"
+ . self::TYPE_DENY . "'");
+ }
+
+ // ensure that all specified Roles exist; normalize input to array of Role objects or null
+ if (!is_array($roles)) {
+ $roles = array($roles);
+ } else if (0 === count($roles)) {
+ $roles = array(null);
+ }
+ $rolesTemp = $roles;
+ $roles = array();
+ foreach ($rolesTemp as $role) {
+ if (null !== $role) {
+ $roles[] = $this->_getRoleRegistry()->get($role);
+ } else {
+ $roles[] = null;
+ }
+ }
+ unset($rolesTemp);
+
+ // ensure that all specified Resources exist; normalize input to array of Resource objects or null
+ if ($resources !== null) {
+ if (!is_array($resources)) {
+ $resources = array($resources);
+ } else if (0 === count($resources)) {
+ $resources = array(null);
+ }
+ $resourcesTemp = $resources;
+ $resources = array();
+ foreach ($resourcesTemp as $resource) {
+ if (null !== $resource) {
+ $resources[] = $this->get($resource);
+ } else {
+ $resources[] = null;
+ }
+ }
+ unset($resourcesTemp, $resource);
+ } else {
+ $allResources = array(); // this might be used later if resource iteration is required
+ foreach ($this->_resources as $rTarget) {
+ $allResources[] = $rTarget['instance'];
+ }
+ unset($rTarget);
+ }
+
+ // normalize privileges to array
+ if (null === $privileges) {
+ $privileges = array();
+ } else if (!is_array($privileges)) {
+ $privileges = array($privileges);
+ }
+
+ switch ($operation) {
+
+ // add to the rules
+ case self::OP_ADD:
+ if ($resources !== null) {
+ // this block will iterate the provided resources
+ foreach ($resources as $resource) {
+ foreach ($roles as $role) {
+ $rules =& $this->_getRules($resource, $role, true);
+ if (0 === count($privileges)) {
+ $rules['allPrivileges']['type'] = $type;
+ $rules['allPrivileges']['assert'] = $assert;
+ if (!isset($rules['byPrivilegeId'])) {
+ $rules['byPrivilegeId'] = array();
+ }
+ } else {
+ foreach ($privileges as $privilege) {
+ $rules['byPrivilegeId'][$privilege]['type'] = $type;
+ $rules['byPrivilegeId'][$privilege]['assert'] = $assert;
+ }
+ }
+ }
+ }
+ } else {
+ // this block will apply to all resources in a global rule
+ foreach ($roles as $role) {
+ $rules =& $this->_getRules(null, $role, true);
+ if (0 === count($privileges)) {
+ $rules['allPrivileges']['type'] = $type;
+ $rules['allPrivileges']['assert'] = $assert;
+ } else {
+ foreach ($privileges as $privilege) {
+ $rules['byPrivilegeId'][$privilege]['type'] = $type;
+ $rules['byPrivilegeId'][$privilege]['assert'] = $assert;
+ }
+ }
+ }
+ }
+ break;
+
+ // remove from the rules
+ case self::OP_REMOVE:
+ if ($resources !== null) {
+ // this block will iterate the provided resources
+ foreach ($resources as $resource) {
+ foreach ($roles as $role) {
+ $rules =& $this->_getRules($resource, $role);
+ if (null === $rules) {
+ continue;
+ }
+ if (0 === count($privileges)) {
+ if (null === $resource && null === $role) {
+ if ($type === $rules['allPrivileges']['type']) {
+ $rules = array(
+ 'allPrivileges' => array(
+ 'type' => self::TYPE_DENY,
+ 'assert' => null
+ ),
+ 'byPrivilegeId' => array()
+ );
+ }
+ continue;
+ }
+
+ if (isset($rules['allPrivileges']['type']) &&
+ $type === $rules['allPrivileges']['type'])
+ {
+ unset($rules['allPrivileges']);
+ }
+ } else {
+ foreach ($privileges as $privilege) {
+ if (isset($rules['byPrivilegeId'][$privilege]) &&
+ $type === $rules['byPrivilegeId'][$privilege]['type'])
+ {
+ unset($rules['byPrivilegeId'][$privilege]);
+ }
+ }
+ }
+ }
+ }
+ } else {
+ // this block will apply to all resources in a global rule
+ foreach ($roles as $role) {
+ /**
+ * since null (all resources) was passed to this setRule() call, we need
+ * clean up all the rules for the global allResources, as well as the indivually
+ * set resources (per privilege as well)
+ */
+ foreach (array_merge(array(null), $allResources) as $resource) {
+ $rules =& $this->_getRules($resource, $role, true);
+ if (null === $rules) {
+ continue;
+ }
+ if (0 === count($privileges)) {
+ if (null === $role) {
+ if ($type === $rules['allPrivileges']['type']) {
+ $rules = array(
+ 'allPrivileges' => array(
+ 'type' => self::TYPE_DENY,
+ 'assert' => null
+ ),
+ 'byPrivilegeId' => array()
+ );
+ }
+ continue;
+ }
+
+ if (isset($rules['allPrivileges']['type']) && $type === $rules['allPrivileges']['type']) {
+ unset($rules['allPrivileges']);
+ }
+ } else {
+ foreach ($privileges as $privilege) {
+ if (isset($rules['byPrivilegeId'][$privilege]) &&
+ $type === $rules['byPrivilegeId'][$privilege]['type'])
+ {
+ unset($rules['byPrivilegeId'][$privilege]);
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+
+ default:
+ require_once 'Zend/Acl/Exception.php';
+ throw new Zend_Acl_Exception("Unsupported operation; must be either '" . self::OP_ADD . "' or '"
+ . self::OP_REMOVE . "'");
+ }
+
+ return $this;
+ }
+
+ /**
+ * Returns true if and only if the Role has access to the Resource
+ *
+ * The $role and $resource parameters may be references to, or the string identifiers for,
+ * an existing Resource and Role combination.
+ *
+ * If either $role or $resource is null, then the query applies to all Roles or all Resources,
+ * respectively. Both may be null to query whether the ACL has a "blacklist" rule
+ * (allow everything to all). By default, Zend_Acl creates a "whitelist" rule (deny
+ * everything to all), and this method would return false unless this default has
+ * been overridden (i.e., by executing $acl->allow()).
+ *
+ * If a $privilege is not provided, then this method returns false if and only if the
+ * Role is denied access to at least one privilege upon the Resource. In other words, this
+ * method returns true if and only if the Role is allowed all privileges on the Resource.
+ *
+ * This method checks Role inheritance using a depth-first traversal of the Role registry.
+ * The highest priority parent (i.e., the parent most recently added) is checked first,
+ * and its respective parents are checked similarly before the lower-priority parents of
+ * the Role are checked.
+ *
+ * @param Zend_Acl_Role_Interface|string $role
+ * @param Zend_Acl_Resource_Interface|string $resource
+ * @param string $privilege
+ * @uses Zend_Acl::get()
+ * @uses Zend_Acl_Role_Registry::get()
+ * @return boolean
+ */
+ public function isAllowed($role = null, $resource = null, $privilege = null)
+ {
+ // reset role & resource to null
+ $this->_isAllowedRole = null;
+ $this->_isAllowedResource = null;
+ $this->_isAllowedPrivilege = null;
+
+ if (null !== $role) {
+ // keep track of originally called role
+ $this->_isAllowedRole = $role;
+ $role = $this->_getRoleRegistry()->get($role);
+ if (!$this->_isAllowedRole instanceof Zend_Acl_Role_Interface) {
+ $this->_isAllowedRole = $role;
+ }
+ }
+
+ if (null !== $resource) {
+ // keep track of originally called resource
+ $this->_isAllowedResource = $resource;
+ $resource = $this->get($resource);
+ if (!$this->_isAllowedResource instanceof Zend_Acl_Resource_Interface) {
+ $this->_isAllowedResource = $resource;
+ }
+ }
+
+ if (null === $privilege) {
+ // query on all privileges
+ do {
+ // depth-first search on $role if it is not 'allRoles' pseudo-parent
+ if (null !== $role && null !== ($result = $this->_roleDFSAllPrivileges($role, $resource, $privilege))) {
+ return $result;
+ }
+
+ // look for rule on 'allRoles' psuedo-parent
+ if (null !== ($rules = $this->_getRules($resource, null))) {
+ foreach ($rules['byPrivilegeId'] as $privilege => $rule) {
+ if (self::TYPE_DENY === ($ruleTypeOnePrivilege = $this->_getRuleType($resource, null, $privilege))) {
+ return false;
+ }
+ }
+ if (null !== ($ruleTypeAllPrivileges = $this->_getRuleType($resource, null, null))) {
+ return self::TYPE_ALLOW === $ruleTypeAllPrivileges;
+ }
+ }
+
+ // try next Resource
+ $resource = $this->_resources[$resource->getResourceId()]['parent'];
+
+ } while (true); // loop terminates at 'allResources' pseudo-parent
+ } else {
+ $this->_isAllowedPrivilege = $privilege;
+ // query on one privilege
+ do {
+ // depth-first search on $role if it is not 'allRoles' pseudo-parent
+ if (null !== $role && null !== ($result = $this->_roleDFSOnePrivilege($role, $resource, $privilege))) {
+ return $result;
+ }
+
+ // look for rule on 'allRoles' pseudo-parent
+ if (null !== ($ruleType = $this->_getRuleType($resource, null, $privilege))) {
+ return self::TYPE_ALLOW === $ruleType;
+ } else if (null !== ($ruleTypeAllPrivileges = $this->_getRuleType($resource, null, null))) {
+ return self::TYPE_ALLOW === $ruleTypeAllPrivileges;
+ }
+
+ // try next Resource
+ $resource = $this->_resources[$resource->getResourceId()]['parent'];
+
+ } while (true); // loop terminates at 'allResources' pseudo-parent
+ }
+ }
+
+ /**
+ * Returns the Role registry for this ACL
+ *
+ * If no Role registry has been created yet, a new default Role registry
+ * is created and returned.
+ *
+ * @return Zend_Acl_Role_Registry
+ */
+ protected function _getRoleRegistry()
+ {
+ if (null === $this->_roleRegistry) {
+ $this->_roleRegistry = new Zend_Acl_Role_Registry();
+ }
+ return $this->_roleRegistry;
+ }
+
+ /**
+ * Performs a depth-first search of the Role DAG, starting at $role, in order to find a rule
+ * allowing/denying $role access to all privileges upon $resource
+ *
+ * This method returns true if a rule is found and allows access. If a rule exists and denies access,
+ * then this method returns false. If no applicable rule is found, then this method returns null.
+ *
+ * @param Zend_Acl_Role_Interface $role
+ * @param Zend_Acl_Resource_Interface $resource
+ * @return boolean|null
+ */
+ protected function _roleDFSAllPrivileges(Zend_Acl_Role_Interface $role, Zend_Acl_Resource_Interface $resource = null)
+ {
+ $dfs = array(
+ 'visited' => array(),
+ 'stack' => array()
+ );
+
+ if (null !== ($result = $this->_roleDFSVisitAllPrivileges($role, $resource, $dfs))) {
+ return $result;
+ }
+
+ while (null !== ($role = array_pop($dfs['stack']))) {
+ if (!isset($dfs['visited'][$role->getRoleId()])) {
+ if (null !== ($result = $this->_roleDFSVisitAllPrivileges($role, $resource, $dfs))) {
+ return $result;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Visits an $role in order to look for a rule allowing/denying $role access to all privileges upon $resource
+ *
+ * This method returns true if a rule is found and allows access. If a rule exists and denies access,
+ * then this method returns false. If no applicable rule is found, then this method returns null.
+ *
+ * This method is used by the internal depth-first search algorithm and may modify the DFS data structure.
+ *
+ * @param Zend_Acl_Role_Interface $role
+ * @param Zend_Acl_Resource_Interface $resource
+ * @param array $dfs
+ * @return boolean|null
+ * @throws Zend_Acl_Exception
+ */
+ protected function _roleDFSVisitAllPrivileges(Zend_Acl_Role_Interface $role, Zend_Acl_Resource_Interface $resource = null,
+ &$dfs = null)
+ {
+ if (null === $dfs) {
+ /**
+ * @see Zend_Acl_Exception
+ */
+ require_once 'Zend/Acl/Exception.php';
+ throw new Zend_Acl_Exception('$dfs parameter may not be null');
+ }
+
+ if (null !== ($rules = $this->_getRules($resource, $role))) {
+ foreach ($rules['byPrivilegeId'] as $privilege => $rule) {
+ if (self::TYPE_DENY === ($ruleTypeOnePrivilege = $this->_getRuleType($resource, $role, $privilege))) {
+ return false;
+ }
+ }
+ if (null !== ($ruleTypeAllPrivileges = $this->_getRuleType($resource, $role, null))) {
+ return self::TYPE_ALLOW === $ruleTypeAllPrivileges;
+ }
+ }
+
+ $dfs['visited'][$role->getRoleId()] = true;
+ foreach ($this->_getRoleRegistry()->getParents($role) as $roleParentId => $roleParent) {
+ $dfs['stack'][] = $roleParent;
+ }
+
+ return null;
+ }
+
+ /**
+ * Performs a depth-first search of the Role DAG, starting at $role, in order to find a rule
+ * allowing/denying $role access to a $privilege upon $resource
+ *
+ * This method returns true if a rule is found and allows access. If a rule exists and denies access,
+ * then this method returns false. If no applicable rule is found, then this method returns null.
+ *
+ * @param Zend_Acl_Role_Interface $role
+ * @param Zend_Acl_Resource_Interface $resource
+ * @param string $privilege
+ * @return boolean|null
+ * @throws Zend_Acl_Exception
+ */
+ protected function _roleDFSOnePrivilege(Zend_Acl_Role_Interface $role, Zend_Acl_Resource_Interface $resource = null,
+ $privilege = null)
+ {
+ if (null === $privilege) {
+ /**
+ * @see Zend_Acl_Exception
+ */
+ require_once 'Zend/Acl/Exception.php';
+ throw new Zend_Acl_Exception('$privilege parameter may not be null');
+ }
+
+ $dfs = array(
+ 'visited' => array(),
+ 'stack' => array()
+ );
+
+ if (null !== ($result = $this->_roleDFSVisitOnePrivilege($role, $resource, $privilege, $dfs))) {
+ return $result;
+ }
+
+ while (null !== ($role = array_pop($dfs['stack']))) {
+ if (!isset($dfs['visited'][$role->getRoleId()])) {
+ if (null !== ($result = $this->_roleDFSVisitOnePrivilege($role, $resource, $privilege, $dfs))) {
+ return $result;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Visits an $role in order to look for a rule allowing/denying $role access to a $privilege upon $resource
+ *
+ * This method returns true if a rule is found and allows access. If a rule exists and denies access,
+ * then this method returns false. If no applicable rule is found, then this method returns null.
+ *
+ * This method is used by the internal depth-first search algorithm and may modify the DFS data structure.
+ *
+ * @param Zend_Acl_Role_Interface $role
+ * @param Zend_Acl_Resource_Interface $resource
+ * @param string $privilege
+ * @param array $dfs
+ * @return boolean|null
+ * @throws Zend_Acl_Exception
+ */
+ protected function _roleDFSVisitOnePrivilege(Zend_Acl_Role_Interface $role, Zend_Acl_Resource_Interface $resource = null,
+ $privilege = null, &$dfs = null)
+ {
+ if (null === $privilege) {
+ /**
+ * @see Zend_Acl_Exception
+ */
+ require_once 'Zend/Acl/Exception.php';
+ throw new Zend_Acl_Exception('$privilege parameter may not be null');
+ }
+
+ if (null === $dfs) {
+ /**
+ * @see Zend_Acl_Exception
+ */
+ require_once 'Zend/Acl/Exception.php';
+ throw new Zend_Acl_Exception('$dfs parameter may not be null');
+ }
+
+ if (null !== ($ruleTypeOnePrivilege = $this->_getRuleType($resource, $role, $privilege))) {
+ return self::TYPE_ALLOW === $ruleTypeOnePrivilege;
+ } else if (null !== ($ruleTypeAllPrivileges = $this->_getRuleType($resource, $role, null))) {
+ return self::TYPE_ALLOW === $ruleTypeAllPrivileges;
+ }
+
+ $dfs['visited'][$role->getRoleId()] = true;
+ foreach ($this->_getRoleRegistry()->getParents($role) as $roleParentId => $roleParent) {
+ $dfs['stack'][] = $roleParent;
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the rule type associated with the specified Resource, Role, and privilege
+ * combination.
+ *
+ * If a rule does not exist or its attached assertion fails, which means that
+ * the rule is not applicable, then this method returns null. Otherwise, the
+ * rule type applies and is returned as either TYPE_ALLOW or TYPE_DENY.
+ *
+ * If $resource or $role is null, then this means that the rule must apply to
+ * all Resources or Roles, respectively.
+ *
+ * If $privilege is null, then the rule must apply to all privileges.
+ *
+ * If all three parameters are null, then the default ACL rule type is returned,
+ * based on whether its assertion method passes.
+ *
+ * @param Zend_Acl_Resource_Interface $resource
+ * @param Zend_Acl_Role_Interface $role
+ * @param string $privilege
+ * @return string|null
+ */
+ protected function _getRuleType(Zend_Acl_Resource_Interface $resource = null, Zend_Acl_Role_Interface $role = null,
+ $privilege = null)
+ {
+ // get the rules for the $resource and $role
+ if (null === ($rules = $this->_getRules($resource, $role))) {
+ return null;
+ }
+
+ // follow $privilege
+ if (null === $privilege) {
+ if (isset($rules['allPrivileges'])) {
+ $rule = $rules['allPrivileges'];
+ } else {
+ return null;
+ }
+ } else if (!isset($rules['byPrivilegeId'][$privilege])) {
+ return null;
+ } else {
+ $rule = $rules['byPrivilegeId'][$privilege];
+ }
+
+ // check assertion first
+ if ($rule['assert']) {
+ $assertion = $rule['assert'];
+ $assertionValue = $assertion->assert(
+ $this,
+ ($this->_isAllowedRole instanceof Zend_Acl_Role_Interface) ? $this->_isAllowedRole : $role,
+ ($this->_isAllowedResource instanceof Zend_Acl_Resource_Interface) ? $this->_isAllowedResource : $resource,
+ $this->_isAllowedPrivilege
+ );
+ }
+
+ if (null === $rule['assert'] || $assertionValue) {
+ return $rule['type'];
+ } else if (null !== $resource || null !== $role || null !== $privilege) {
+ return null;
+ } else if (self::TYPE_ALLOW === $rule['type']) {
+ return self::TYPE_DENY;
+ } else {
+ return self::TYPE_ALLOW;
+ }
+ }
+
+ /**
+ * Returns the rules associated with a Resource and a Role, or null if no such rules exist
+ *
+ * If either $resource or $role is null, this means that the rules returned are for all Resources or all Roles,
+ * respectively. Both can be null to return the default rule set for all Resources and all Roles.
+ *
+ * If the $create parameter is true, then a rule set is first created and then returned to the caller.
+ *
+ * @param Zend_Acl_Resource_Interface $resource
+ * @param Zend_Acl_Role_Interface $role
+ * @param boolean $create
+ * @return array|null
+ */
+ protected function &_getRules(Zend_Acl_Resource_Interface $resource = null, Zend_Acl_Role_Interface $role = null,
+ $create = false)
+ {
+ // create a reference to null
+ $null = null;
+ $nullRef =& $null;
+
+ // follow $resource
+ do {
+ if (null === $resource) {
+ $visitor =& $this->_rules['allResources'];
+ break;
+ }
+ $resourceId = $resource->getResourceId();
+ if (!isset($this->_rules['byResourceId'][$resourceId])) {
+ if (!$create) {
+ return $nullRef;
+ }
+ $this->_rules['byResourceId'][$resourceId] = array();
+ }
+ $visitor =& $this->_rules['byResourceId'][$resourceId];
+ } while (false);
+
+
+ // follow $role
+ if (null === $role) {
+ if (!isset($visitor['allRoles'])) {
+ if (!$create) {
+ return $nullRef;
+ }
+ $visitor['allRoles']['byPrivilegeId'] = array();
+ }
+ return $visitor['allRoles'];
+ }
+ $roleId = $role->getRoleId();
+ if (!isset($visitor['byRoleId'][$roleId])) {
+ if (!$create) {
+ return $nullRef;
+ }
+ $visitor['byRoleId'][$roleId]['byPrivilegeId'] = array();
+ $visitor['byRoleId'][$roleId]['allPrivileges'] = array('type' => null, 'assert' => null);
+ }
+ return $visitor['byRoleId'][$roleId];
+ }
+
+
+ /**
+ * @return array of registered roles (Deprecated)
+ * @deprecated Deprecated since version 1.10 (December 2009)
+ */
+ public function getRegisteredRoles()
+ {
+ trigger_error('The method getRegisteredRoles() was deprecated as of '
+ . 'version 1.0, and may be removed. You\'re encouraged '
+ . 'to use getRoles() instead.');
+
+ return $this->_getRoleRegistry()->getRoles();
+ }
+
+ /**
+ * Returns an array of registered roles.
+ *
+ * Note that this method does not return instances of registered roles,
+ * but only the role identifiers.
+ *
+ * @return array of registered roles
+ */
+ public function getRoles()
+ {
+ return array_keys($this->_getRoleRegistry()->getRoles());
+ }
+
+ /**
+ * @return array of registered resources
+ */
+ public function getResources()
+ {
+ return array_keys($this->_resources);
+ }
+
+}
+
diff --git a/lib/zend/Zend/Acl/Assert/Interface.php b/lib/zend/Zend/Acl/Assert/Interface.php
new file mode 100644
index 00000000000..e3d02565fc6
--- /dev/null
+++ b/lib/zend/Zend/Acl/Assert/Interface.php
@@ -0,0 +1,64 @@
+countryCode;
+ $this->_resourceId = (string) $resourceId;
}
/**
+ * Defined by Zend_Acl_Resource_Interface; returns the Resource identifier
+ *
* @return string
*/
- public function getCityCode()
+ public function getResourceId()
{
- return $this->cityCode;
+ return $this->_resourceId;
}
/**
+ * Defined by Zend_Acl_Resource_Interface; returns the Resource identifier
+ * Proxies to getResourceId()
+ *
* @return string
*/
- public function getCityName()
+ public function __toString()
{
- return $this->cityName;
+ return $this->getResourceId();
}
}
diff --git a/lib/zend/Zend/Acl/Resource/Interface.php b/lib/zend/Zend/Acl/Resource/Interface.php
new file mode 100644
index 00000000000..dcf10586d51
--- /dev/null
+++ b/lib/zend/Zend/Acl/Resource/Interface.php
@@ -0,0 +1,37 @@
+return->sessionId)) {
- return $this->return->sessionId;
- }
- return null;
+ $this->_roleId = (string) $roleId;
}
/**
- * prints the session on casting to string
+ * Defined by Zend_Acl_Role_Interface; returns the Role identifier
+ *
+ * @return string
+ */
+ public function getRoleId()
+ {
+ return $this->_roleId;
+ }
+
+ /**
+ * Defined by Zend_Acl_Role_Interface; returns the Role identifier
+ * Proxies to getRoleId()
*
* @return string
*/
public function __toString()
{
- return $this->getSessionId();
+ return $this->getRoleId();
}
}
diff --git a/lib/zend/Zend/Acl/Role/Interface.php b/lib/zend/Zend/Acl/Role/Interface.php
new file mode 100644
index 00000000000..e2510003ce5
--- /dev/null
+++ b/lib/zend/Zend/Acl/Role/Interface.php
@@ -0,0 +1,37 @@
+getRoleId();
+
+ if ($this->has($roleId)) {
+ /**
+ * @see Zend_Acl_Role_Registry_Exception
+ */
+ require_once 'Zend/Acl/Role/Registry/Exception.php';
+ throw new Zend_Acl_Role_Registry_Exception("Role id '$roleId' already exists in the registry");
+ }
+
+ $roleParents = array();
+
+ if (null !== $parents) {
+ if (!is_array($parents)) {
+ $parents = array($parents);
+ }
+ /**
+ * @see Zend_Acl_Role_Registry_Exception
+ */
+ require_once 'Zend/Acl/Role/Registry/Exception.php';
+ foreach ($parents as $parent) {
+ try {
+ if ($parent instanceof Zend_Acl_Role_Interface) {
+ $roleParentId = $parent->getRoleId();
+ } else {
+ $roleParentId = $parent;
+ }
+ $roleParent = $this->get($roleParentId);
+ } catch (Zend_Acl_Role_Registry_Exception $e) {
+ throw new Zend_Acl_Role_Registry_Exception("Parent Role id '$roleParentId' does not exist", 0, $e);
+ }
+ $roleParents[$roleParentId] = $roleParent;
+ $this->_roles[$roleParentId]['children'][$roleId] = $role;
+ }
+ }
+
+ $this->_roles[$roleId] = array(
+ 'instance' => $role,
+ 'parents' => $roleParents,
+ 'children' => array()
+ );
+
+ return $this;
+ }
+
+ /**
+ * Returns the identified Role
+ *
+ * The $role parameter can either be a Role or a Role identifier.
+ *
+ * @param Zend_Acl_Role_Interface|string $role
+ * @throws Zend_Acl_Role_Registry_Exception
+ * @return Zend_Acl_Role_Interface
+ */
+ public function get($role)
+ {
+ if ($role instanceof Zend_Acl_Role_Interface) {
+ $roleId = $role->getRoleId();
+ } else {
+ $roleId = (string) $role;
+ }
+
+ if (!$this->has($role)) {
+ /**
+ * @see Zend_Acl_Role_Registry_Exception
+ */
+ require_once 'Zend/Acl/Role/Registry/Exception.php';
+ throw new Zend_Acl_Role_Registry_Exception("Role '$roleId' not found");
+ }
+
+ return $this->_roles[$roleId]['instance'];
+ }
+
+ /**
+ * Returns true if and only if the Role exists in the registry
+ *
+ * The $role parameter can either be a Role or a Role identifier.
+ *
+ * @param Zend_Acl_Role_Interface|string $role
+ * @return boolean
+ */
+ public function has($role)
+ {
+ if ($role instanceof Zend_Acl_Role_Interface) {
+ $roleId = $role->getRoleId();
+ } else {
+ $roleId = (string) $role;
+ }
+
+ return isset($this->_roles[$roleId]);
+ }
+
+ /**
+ * Returns an array of an existing Role's parents
+ *
+ * The array keys are the identifiers of the parent Roles, and the values are
+ * the parent Role instances. The parent Roles are ordered in this array by
+ * ascending priority. The highest priority parent Role, last in the array,
+ * corresponds with the parent Role most recently added.
+ *
+ * If the Role does not have any parents, then an empty array is returned.
+ *
+ * @param Zend_Acl_Role_Interface|string $role
+ * @uses Zend_Acl_Role_Registry::get()
+ * @return array
+ */
+ public function getParents($role)
+ {
+ $roleId = $this->get($role)->getRoleId();
+
+ return $this->_roles[$roleId]['parents'];
+ }
+
+ /**
+ * Returns true if and only if $role inherits from $inherit
+ *
+ * Both parameters may be either a Role or a Role identifier. If
+ * $onlyParents is true, then $role must inherit directly from
+ * $inherit in order to return true. By default, this method looks
+ * through the entire inheritance DAG to determine whether $role
+ * inherits from $inherit through its ancestor Roles.
+ *
+ * @param Zend_Acl_Role_Interface|string $role
+ * @param Zend_Acl_Role_Interface|string $inherit
+ * @param boolean $onlyParents
+ * @throws Zend_Acl_Role_Registry_Exception
+ * @return boolean
+ */
+ public function inherits($role, $inherit, $onlyParents = false)
+ {
+ /**
+ * @see Zend_Acl_Role_Registry_Exception
+ */
+ require_once 'Zend/Acl/Role/Registry/Exception.php';
+ try {
+ $roleId = $this->get($role)->getRoleId();
+ $inheritId = $this->get($inherit)->getRoleId();
+ } catch (Zend_Acl_Role_Registry_Exception $e) {
+ throw new Zend_Acl_Role_Registry_Exception($e->getMessage(), $e->getCode(), $e);
+ }
+
+ $inherits = isset($this->_roles[$roleId]['parents'][$inheritId]);
+
+ if ($inherits || $onlyParents) {
+ return $inherits;
+ }
+
+ foreach ($this->_roles[$roleId]['parents'] as $parentId => $parent) {
+ if ($this->inherits($parentId, $inheritId)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Removes the Role from the registry
+ *
+ * The $role parameter can either be a Role or a Role identifier.
+ *
+ * @param Zend_Acl_Role_Interface|string $role
+ * @throws Zend_Acl_Role_Registry_Exception
+ * @return Zend_Acl_Role_Registry Provides a fluent interface
+ */
+ public function remove($role)
+ {
+ /**
+ * @see Zend_Acl_Role_Registry_Exception
+ */
+ require_once 'Zend/Acl/Role/Registry/Exception.php';
+ try {
+ $roleId = $this->get($role)->getRoleId();
+ } catch (Zend_Acl_Role_Registry_Exception $e) {
+ throw new Zend_Acl_Role_Registry_Exception($e->getMessage(), $e->getCode(), $e);
+ }
+
+ foreach ($this->_roles[$roleId]['children'] as $childId => $child) {
+ unset($this->_roles[$childId]['parents'][$roleId]);
+ }
+ foreach ($this->_roles[$roleId]['parents'] as $parentId => $parent) {
+ unset($this->_roles[$parentId]['children'][$roleId]);
+ }
+
+ unset($this->_roles[$roleId]);
+
+ return $this;
+ }
+
+ /**
+ * Removes all Roles from the registry
+ *
+ * @return Zend_Acl_Role_Registry Provides a fluent interface
+ */
+ public function removeAll()
+ {
+ $this->_roles = array();
+
+ return $this;
+ }
+
+ public function getRoles()
+ {
+ return $this->_roles;
+ }
+
+}
diff --git a/lib/zend/Zend/Acl/Role/Registry/Exception.php b/lib/zend/Zend/Acl/Role/Registry/Exception.php
new file mode 100644
index 00000000000..a2e906a98a2
--- /dev/null
+++ b/lib/zend/Zend/Acl/Role/Registry/Exception.php
@@ -0,0 +1,36 @@
+_acl = new Zend_Acl();
- $xml = simplexml_load_file($rolefile);
+ $xml = Zend_Xml_Security::scanFile($rolefile);
/*
Roles file format:
diff --git a/lib/zend/Zend/Amf/Adobe/DbInspector.php b/lib/zend/Zend/Amf/Adobe/DbInspector.php
old mode 100644
new mode 100755
index d756787ad6f..a25c3a2b165
--- a/lib/zend/Zend/Amf/Adobe/DbInspector.php
+++ b/lib/zend/Zend/Amf/Adobe/DbInspector.php
@@ -14,7 +14,7 @@
*
* @category Zend
* @package Zend_Amf
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
@@ -24,7 +24,7 @@
*
* @package Zend_Amf
* @subpackage Adobe
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Adobe_DbInspector
diff --git a/lib/zend/Zend/Amf/Adobe/Introspector.php b/lib/zend/Zend/Amf/Adobe/Introspector.php
old mode 100644
new mode 100755
index f746e38f470..3eb76c490cc
--- a/lib/zend/Zend/Amf/Adobe/Introspector.php
+++ b/lib/zend/Zend/Amf/Adobe/Introspector.php
@@ -14,7 +14,7 @@
*
* @category Zend
* @package Zend_Amf
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
@@ -33,7 +33,7 @@ require_once 'Zend/Server/Reflection.php';
*
* @package Zend_Amf
* @subpackage Adobe
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Adobe_Introspector
@@ -283,7 +283,12 @@ class Zend_Amf_Adobe_Introspector
return 'Unknown';
}
- if (in_array($typename, array('int', 'integer', 'bool', 'boolean', 'float', 'string', 'object', 'Unknown', 'stdClass', 'array'))) {
+ // Arrays
+ if ('array' == $typename) {
+ return 'Unknown[]';
+ }
+
+ if (in_array($typename, array('int', 'integer', 'bool', 'boolean', 'float', 'string', 'object', 'Unknown', 'stdClass'))) {
return $typename;
}
diff --git a/lib/zend/Zend/Amf/Auth/Abstract.php b/lib/zend/Zend/Amf/Auth/Abstract.php
old mode 100644
new mode 100755
index 617d2b412c4..180568d3fcc
--- a/lib/zend/Zend/Amf/Auth/Abstract.php
+++ b/lib/zend/Zend/Amf/Auth/Abstract.php
@@ -14,7 +14,7 @@
*
* @category Zend
* @package Zend_Amf
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
@@ -27,7 +27,7 @@ require_once 'Zend/Auth/Adapter/Interface.php';
*
* @package Zend_Amf
* @subpackage Auth
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
abstract class Zend_Amf_Auth_Abstract implements Zend_Auth_Adapter_Interface
diff --git a/lib/zend/Zend/Amf/Constants.php b/lib/zend/Zend/Amf/Constants.php
index 4cf60025a1a..723d8ba4fd3 100644
--- a/lib/zend/Zend/Amf/Constants.php
+++ b/lib/zend/Zend/Amf/Constants.php
@@ -14,7 +14,7 @@
*
* @category Zend
* @package Zend_Amf
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
@@ -24,7 +24,7 @@
* deserialization to detect the AMF marker and encoding types.
*
* @package Zend_Amf
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
final class Zend_Amf_Constants
diff --git a/lib/zend/Zend/Amf/Exception.php b/lib/zend/Zend/Amf/Exception.php
index fa45da335d5..5738cdd95d3 100644
--- a/lib/zend/Zend/Amf/Exception.php
+++ b/lib/zend/Zend/Amf/Exception.php
@@ -14,7 +14,7 @@
*
* @category Zend
* @package Zend_Amf
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
@@ -26,7 +26,7 @@ require_once 'Zend/Exception.php';
/**
* @package Zend_Amf
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Exception extends Zend_Exception
diff --git a/lib/zend/Zend/Amf/Parse/Amf0/Deserializer.php b/lib/zend/Zend/Amf/Parse/Amf0/Deserializer.php
index e80492d6b16..6d8fa7f55d9 100644
--- a/lib/zend/Zend/Amf/Parse/Amf0/Deserializer.php
+++ b/lib/zend/Zend/Amf/Parse/Amf0/Deserializer.php
@@ -15,7 +15,7 @@
* @category Zend
* @package Zend_Amf
* @subpackage Parse_Amf0
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
@@ -23,6 +23,9 @@
/** Zend_Amf_Constants */
require_once 'Zend/Amf/Constants.php';
+/** Zend_Xml_Security */
+require_once 'Zend/Xml/Security.php';
+
/** @see Zend_Amf_Parse_Deserializer */
require_once 'Zend/Amf/Parse/Deserializer.php';
@@ -33,7 +36,7 @@ require_once 'Zend/Amf/Parse/Deserializer.php';
* @todo Class could be implemented as Factory Class with each data type it's own class
* @package Zend_Amf
* @subpackage Parse_Amf0
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Parse_Amf0_Deserializer extends Zend_Amf_Parse_Deserializer
@@ -248,7 +251,7 @@ class Zend_Amf_Parse_Amf0_Deserializer extends Zend_Amf_Parse_Deserializer
public function readXmlString()
{
$string = $this->_stream->readLongUTF();
- return simplexml_load_string($string);
+ return Zend_Xml_Security::scan($string); //simplexml_load_string($string);
}
/**
diff --git a/lib/zend/Zend/Amf/Parse/Amf0/Serializer.php b/lib/zend/Zend/Amf/Parse/Amf0/Serializer.php
index 9ecc352b8e5..0a578c12911 100644
--- a/lib/zend/Zend/Amf/Parse/Amf0/Serializer.php
+++ b/lib/zend/Zend/Amf/Parse/Amf0/Serializer.php
@@ -15,7 +15,7 @@
* @category Zend
* @package Zend_Amf
* @subpackage Parse_Amf0
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
@@ -32,7 +32,7 @@ require_once 'Zend/Amf/Parse/Serializer.php';
* @uses Zend_Amf_Parse_Serializer
* @package Zend_Amf
* @subpackage Parse_Amf0
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Parse_Amf0_Serializer extends Zend_Amf_Parse_Serializer
@@ -63,8 +63,8 @@ class Zend_Amf_Parse_Amf0_Serializer extends Zend_Amf_Parse_Serializer
*/
public function writeTypeMarker(&$data, $markerType = null, $dataByVal = false)
{
- // Workaround for PHP5 with E_STRICT enabled complaining about "Only
- // variables should be passed by reference"
+ // Workaround for PHP5 with E_STRICT enabled complaining about "Only
+ // variables should be passed by reference"
if ((null === $data) && ($dataByVal !== false)) {
$data = &$dataByVal;
}
@@ -127,7 +127,7 @@ class Zend_Amf_Parse_Amf0_Serializer extends Zend_Amf_Parse_Serializer
case (is_bool($data)):
$markerType = Zend_Amf_Constants::AMF0_BOOLEAN;
break;
- case (is_string($data) && (strlen($data) > 65536)):
+ case (is_string($data) && (($this->_mbStringFunctionsOverloaded ? mb_strlen($data, '8bit') : strlen($data)) > 65536)):
$markerType = Zend_Amf_Constants::AMF0_LONGSTRING;
break;
case (is_string($data)):
@@ -187,23 +187,23 @@ class Zend_Amf_Parse_Amf0_Serializer extends Zend_Amf_Parse_Serializer
* Check if the given object is in the reference table, write the reference if it exists,
* otherwise add the object to the reference table
*
- * @param mixed $object object reference to check for reference
- * @param $markerType AMF type of the object to write
- * @param mixed $objectByVal object to check for reference
+ * @param mixed $object object reference to check for reference
+ * @param string $markerType AMF type of the object to write
+ * @param mixed $objectByVal object to check for reference
* @return Boolean true, if the reference was written, false otherwise
*/
- protected function writeObjectReference(&$object, $markerType, $objectByVal = false)
+ protected function writeObjectReference(&$object, $markerType, $objectByVal = false)
{
- // Workaround for PHP5 with E_STRICT enabled complaining about "Only
+ // Workaround for PHP5 with E_STRICT enabled complaining about "Only
// variables should be passed by reference"
if ((null === $object) && ($objectByVal !== false)) {
$object = &$objectByVal;
}
- if ($markerType == Zend_Amf_Constants::AMF0_OBJECT
- || $markerType == Zend_Amf_Constants::AMF0_MIXEDARRAY
- || $markerType == Zend_Amf_Constants::AMF0_ARRAY
- || $markerType == Zend_Amf_Constants::AMF0_TYPEDOBJECT
+ if ($markerType == Zend_Amf_Constants::AMF0_OBJECT
+ || $markerType == Zend_Amf_Constants::AMF0_MIXEDARRAY
+ || $markerType == Zend_Amf_Constants::AMF0_ARRAY
+ || $markerType == Zend_Amf_Constants::AMF0_TYPEDOBJECT
) {
$ref = array_search($object, $this->_referenceObjects, true);
//handle object reference
diff --git a/lib/zend/Zend/Amf/Parse/Amf3/Deserializer.php b/lib/zend/Zend/Amf/Parse/Amf3/Deserializer.php
index 0144798eb80..9bcc272af30 100644
--- a/lib/zend/Zend/Amf/Parse/Amf3/Deserializer.php
+++ b/lib/zend/Zend/Amf/Parse/Amf3/Deserializer.php
@@ -15,7 +15,7 @@
* @category Zend
* @package Zend_Amf
* @subpackage Parse_Amf3
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
@@ -23,6 +23,9 @@
/** Zend_Amf_Parse_Deserializer */
require_once 'Zend/Amf/Parse/Deserializer.php';
+/** Zend_Xml_Security */
+require_once 'Zend/Xml/Security.php';
+
/** Zend_Amf_Parse_TypeLoader */
require_once 'Zend/Amf/Parse/TypeLoader.php';
@@ -34,7 +37,7 @@ require_once 'Zend/Amf/Parse/TypeLoader.php';
* @todo Class could be implemented as Factory Class with each data type it's own class.
* @package Zend_Amf
* @subpackage Parse_Amf3
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Parse_Amf3_Deserializer extends Zend_Amf_Parse_Deserializer
@@ -225,7 +228,7 @@ class Zend_Amf_Parse_Amf3_Deserializer extends Zend_Amf_Parse_Deserializer
$timestamp = floor($this->_stream->readDouble() / 1000);
require_once 'Zend/Date.php';
- $dateTime = new Zend_Date((int) $timestamp);
+ $dateTime = new Zend_Date($timestamp);
$this->_referenceObjects[] = $dateTime;
return $dateTime;
}
@@ -385,6 +388,7 @@ class Zend_Amf_Parse_Amf3_Deserializer extends Zend_Amf_Parse_Deserializer
}
// Add properties back to the return object.
+ if (!is_array($properties)) $properties = array();
foreach($properties as $key=>$value) {
if($key) {
$returnObject->$key = $value;
@@ -416,6 +420,6 @@ class Zend_Amf_Parse_Amf3_Deserializer extends Zend_Amf_Parse_Deserializer
$xmlReference = $this->readInteger();
$length = $xmlReference >> 1;
$string = $this->_stream->readBytes($length);
- return simplexml_load_string($string);
+ return Zend_Xml_Security::scan($string);
}
}
diff --git a/lib/zend/Zend/Amf/Parse/Amf3/Serializer.php b/lib/zend/Zend/Amf/Parse/Amf3/Serializer.php
index 80d191bf5aa..3ce47b7f7cb 100644
--- a/lib/zend/Zend/Amf/Parse/Amf3/Serializer.php
+++ b/lib/zend/Zend/Amf/Parse/Amf3/Serializer.php
@@ -15,7 +15,7 @@
* @category Zend
* @package Zend_Amf
* @subpackage Parse_Amf3
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
@@ -35,7 +35,7 @@ require_once 'Zend/Amf/Parse/TypeLoader.php';
*
* @package Zend_Amf
* @subpackage Parse_Amf3
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Parse_Amf3_Serializer extends Zend_Amf_Parse_Serializer
@@ -45,7 +45,7 @@ class Zend_Amf_Parse_Amf3_Serializer extends Zend_Amf_Parse_Serializer
* @var string
*/
protected $_strEmpty = '';
-
+
/**
* An array of reference objects per amf body
* @var array
@@ -78,7 +78,7 @@ class Zend_Amf_Parse_Amf3_Serializer extends Zend_Amf_Parse_Serializer
*/
public function writeTypeMarker(&$data, $markerType = null, $dataByVal = false)
{
- // Workaround for PHP5 with E_STRICT enabled complaining about "Only
+ // Workaround for PHP5 with E_STRICT enabled complaining about "Only
// variables should be passed by reference"
if ((null === $data) && ($dataByVal !== false)) {
$data = &$dataByVal;
@@ -215,7 +215,7 @@ class Zend_Amf_Parse_Amf3_Serializer extends Zend_Amf_Parse_Serializer
* @return Zend_Amf_Parse_Amf3_Serializer
*/
protected function writeBinaryString(&$string){
- $ref = strlen($string) << 1 | 0x01;
+ $ref = ($this->_mbStringFunctionsOverloaded ? mb_strlen($string, '8bit') : strlen($string)) << 1 | 0x01;
$this->writeInteger($ref);
$this->_stream->writeBytes($string);
@@ -230,15 +230,17 @@ class Zend_Amf_Parse_Amf3_Serializer extends Zend_Amf_Parse_Serializer
*/
public function writeString(&$string)
{
- $len = strlen($string);
+ $len = $this->_mbStringFunctionsOverloaded ? mb_strlen($string, '8bit') : strlen($string);
if(!$len){
$this->writeInteger(0x01);
return $this;
}
- $ref = array_search($string, $this->_referenceStrings, true);
- if($ref === false){
- $this->_referenceStrings[] = $string;
+ $ref = array_key_exists($string, $this->_referenceStrings)
+ ? $this->_referenceStrings[$string]
+ : false;
+ if ($ref === false){
+ $this->_referenceStrings[$string] = count($this->_referenceStrings);
$this->writeBinaryString($string);
} else {
$ref <<= 1;
@@ -380,13 +382,16 @@ class Zend_Amf_Parse_Amf3_Serializer extends Zend_Amf_Parse_Serializer
*/
protected function writeObjectReference(&$object, $objectByVal = false)
{
- // Workaround for PHP5 with E_STRICT enabled complaining about "Only
+ // Workaround for PHP5 with E_STRICT enabled complaining about "Only
// variables should be passed by reference"
if ((null === $object) && ($objectByVal !== false)) {
$object = &$objectByVal;
}
- $ref = array_search($object, $this->_referenceObjects,true);
+ $hash = spl_object_hash($object);
+ $ref = array_key_exists($hash, $this->_referenceObjects)
+ ? $this->_referenceObjects[$hash]
+ : false;
// quickly handle object references
if ($ref !== false){
@@ -394,7 +399,7 @@ class Zend_Amf_Parse_Amf3_Serializer extends Zend_Amf_Parse_Serializer
$this->writeInteger($ref);
return true;
}
- $this->_referenceObjects[] = $object;
+ $this->_referenceObjects[$hash] = count($this->_referenceObjects);
return false;
}
diff --git a/lib/zend/Zend/Amf/Parse/Deserializer.php b/lib/zend/Zend/Amf/Parse/Deserializer.php
index a72aa15ed2f..e6d4b1a853d 100644
--- a/lib/zend/Zend/Amf/Parse/Deserializer.php
+++ b/lib/zend/Zend/Amf/Parse/Deserializer.php
@@ -15,7 +15,7 @@
* @category Zend
* @package Zend_Amf
* @subpackage Parse
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
@@ -30,7 +30,7 @@
* @see http://opensource.adobe.com/svn/opensource/blazeds/trunk/modules/core/src/java/flex/messaging/io/amf/
* @package Zend_Amf
* @subpackage Parse
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
abstract class Zend_Amf_Parse_Deserializer
diff --git a/lib/zend/Zend/Amf/Parse/InputStream.php b/lib/zend/Zend/Amf/Parse/InputStream.php
index ec8c88a19a7..25929651549 100644
--- a/lib/zend/Zend/Amf/Parse/InputStream.php
+++ b/lib/zend/Zend/Amf/Parse/InputStream.php
@@ -15,7 +15,7 @@
* @category Zend
* @package Zend_Amf
* @subpackage Parse
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
@@ -31,7 +31,7 @@ require_once 'Zend/Amf/Util/BinaryStream.php';
*
* @package Zend_Amf
* @subpackage Parse
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Parse_InputStream extends Zend_Amf_Util_BinaryStream
diff --git a/lib/zend/Zend/Amf/Parse/OutputStream.php b/lib/zend/Zend/Amf/Parse/OutputStream.php
index d06e75076c1..c6979baadce 100644
--- a/lib/zend/Zend/Amf/Parse/OutputStream.php
+++ b/lib/zend/Zend/Amf/Parse/OutputStream.php
@@ -15,7 +15,7 @@
* @category Zend
* @package Zend_Amf
* @subpackage Parse
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
@@ -32,7 +32,7 @@ require_once 'Zend/Amf/Util/BinaryStream.php';
* @uses Zend_Amf_Util_BinaryStream
* @package Zend_Amf
* @subpackage Parse
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Parse_OutputStream extends Zend_Amf_Util_BinaryStream
diff --git a/lib/zend/Zend/Amf/Parse/Resource/MysqlResult.php b/lib/zend/Zend/Amf/Parse/Resource/MysqlResult.php
old mode 100644
new mode 100755
index b3e004662f1..aed35a9d3f8
--- a/lib/zend/Zend/Amf/Parse/Resource/MysqlResult.php
+++ b/lib/zend/Zend/Amf/Parse/Resource/MysqlResult.php
@@ -15,7 +15,7 @@
* @category Zend
* @package Zend_Amf
* @subpackage Parse
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
@@ -26,7 +26,7 @@
*
* @package Zend_Amf
* @subpackage Parse
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Parse_Resource_MysqlResult
diff --git a/lib/zend/Zend/Amf/Parse/Resource/MysqliResult.php b/lib/zend/Zend/Amf/Parse/Resource/MysqliResult.php
index fbb9caefed3..45f53d4b73d 100644
--- a/lib/zend/Zend/Amf/Parse/Resource/MysqliResult.php
+++ b/lib/zend/Zend/Amf/Parse/Resource/MysqliResult.php
@@ -15,7 +15,7 @@
* @category Zend
* @package Zend_Amf
* @subpackage Parse
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
@@ -26,7 +26,7 @@
*
* @package Zend_Amf
* @subpackage Parse
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Parse_Resource_MysqliResult
diff --git a/lib/zend/Zend/Amf/Parse/Resource/Stream.php b/lib/zend/Zend/Amf/Parse/Resource/Stream.php
old mode 100644
new mode 100755
index 3fcd560ef19..b8afa148ac2
--- a/lib/zend/Zend/Amf/Parse/Resource/Stream.php
+++ b/lib/zend/Zend/Amf/Parse/Resource/Stream.php
@@ -15,7 +15,7 @@
* @category Zend
* @package Zend_Amf
* @subpackage Parse
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
@@ -25,7 +25,7 @@
*
* @package Zend_Amf
* @subpackage Parse
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Parse_Resource_Stream
diff --git a/lib/zend/Zend/Amf/Parse/Serializer.php b/lib/zend/Zend/Amf/Parse/Serializer.php
index 2a0e4a9bf8c..7bf75f65bd1 100644
--- a/lib/zend/Zend/Amf/Parse/Serializer.php
+++ b/lib/zend/Zend/Amf/Parse/Serializer.php
@@ -15,7 +15,7 @@
* @category Zend
* @package Zend_Amf
* @subpackage Parse
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
@@ -25,7 +25,7 @@
*
* @package Zend_Amf
* @subpackage Parse
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
abstract class Zend_Amf_Parse_Serializer
@@ -37,6 +37,13 @@ abstract class Zend_Amf_Parse_Serializer
*/
protected $_stream;
+ /**
+ * str* functions overloaded using mbstring.func_overload
+ *
+ * @var bool
+ */
+ protected $mbStringFunctionsOverloaded;
+
/**
* Constructor
*
@@ -46,6 +53,7 @@ abstract class Zend_Amf_Parse_Serializer
public function __construct(Zend_Amf_Parse_OutputStream $stream)
{
$this->_stream = $stream;
+ $this->_mbStringFunctionsOverloaded = function_exists('mb_strlen') && (ini_get('mbstring.func_overload') !== '') && ((int)ini_get('mbstring.func_overload') & 2);
}
/**
diff --git a/lib/zend/Zend/Amf/Parse/TypeLoader.php b/lib/zend/Zend/Amf/Parse/TypeLoader.php
index 5eda3b0ec2d..05c8db42f92 100644
--- a/lib/zend/Zend/Amf/Parse/TypeLoader.php
+++ b/lib/zend/Zend/Amf/Parse/TypeLoader.php
@@ -15,7 +15,7 @@
* @category Zend
* @package Zend_Amf
* @subpackage Parse
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
@@ -47,7 +47,7 @@ require_once 'Zend/Amf/Value/Messaging/RemotingMessage.php';
* @todo PHP 5.3 can drastically change this class w/ namespace and the new call_user_func w/ namespace
* @package Zend_Amf
* @subpackage Parse
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
final class Zend_Amf_Parse_TypeLoader
diff --git a/lib/zend/Zend/Amf/Request.php b/lib/zend/Zend/Amf/Request.php
index 0fa7f3e8e70..c5da936ef05 100644
--- a/lib/zend/Zend/Amf/Request.php
+++ b/lib/zend/Zend/Amf/Request.php
@@ -14,7 +14,7 @@
*
* @category Zend
* @package Zend_Amf
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
@@ -40,7 +40,7 @@ require_once 'Zend/Amf/Value/MessageBody.php';
*
* @todo Currently not checking if the object needs to be Type Mapped to a server object.
* @package Zend_Amf
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Request
diff --git a/lib/zend/Zend/Amf/Request/Http.php b/lib/zend/Zend/Amf/Request/Http.php
index 30059f06045..e5675058e95 100644
--- a/lib/zend/Zend/Amf/Request/Http.php
+++ b/lib/zend/Zend/Amf/Request/Http.php
@@ -15,7 +15,7 @@
* @category Zend
* @package Zend_Amf
* @subpackage Request
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
@@ -32,7 +32,7 @@ require_once 'Zend/Amf/Request.php';
*
* @package Zend_Amf
* @subpackage Request
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Request_Http extends Zend_Amf_Request
diff --git a/lib/zend/Zend/Amf/Response.php b/lib/zend/Zend/Amf/Response.php
index d069ecf9cb3..00e75010566 100644
--- a/lib/zend/Zend/Amf/Response.php
+++ b/lib/zend/Zend/Amf/Response.php
@@ -14,7 +14,7 @@
*
* @category Zend
* @package Zend_Amf
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
@@ -32,7 +32,7 @@ require_once 'Zend/Amf/Parse/Amf0/Serializer.php';
* Handles converting the PHP object ready for response back into AMF
*
* @package Zend_Amf
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Response
@@ -95,7 +95,7 @@ class Zend_Amf_Response
$stream->writeByte($header->mustRead);
$stream->writeLong(Zend_Amf_Constants::UNKNOWN_CONTENT_LENGTH);
if (is_object($header->data)) {
- // Workaround for PHP5 with E_STRICT enabled complaining about
+ // Workaround for PHP5 with E_STRICT enabled complaining about
// "Only variables should be passed by reference"
$placeholder = null;
$serializer->writeTypeMarker($placeholder, null, $header->data);
@@ -115,7 +115,7 @@ class Zend_Amf_Response
$bodyData = $body->getData();
$markerType = ($this->_objectEncoding == Zend_Amf_Constants::AMF0_OBJECT_ENCODING) ? null : Zend_Amf_Constants::AMF0_AMF3;
if (is_object($bodyData)) {
- // Workaround for PHP5 with E_STRICT enabled complaining about
+ // Workaround for PHP5 with E_STRICT enabled complaining about
// "Only variables should be passed by reference"
$placeholder = null;
$serializer->writeTypeMarker($placeholder, $markerType, $bodyData);
diff --git a/lib/zend/Zend/Amf/Response/Http.php b/lib/zend/Zend/Amf/Response/Http.php
index 961ffdf84ae..4182f6aa8ad 100644
--- a/lib/zend/Zend/Amf/Response/Http.php
+++ b/lib/zend/Zend/Amf/Response/Http.php
@@ -15,7 +15,7 @@
* @category Zend
* @package Zend_Amf
* @subpackage Response
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
@@ -28,7 +28,7 @@ require_once 'Zend/Amf/Response.php';
*
* @package Zend_Amf
* @subpackage Response
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Response_Http extends Zend_Amf_Response
@@ -41,10 +41,33 @@ class Zend_Amf_Response_Http extends Zend_Amf_Response
public function getResponse()
{
if (!headers_sent()) {
- header('Cache-Control: cache, must-revalidate');
- header('Pragma: public');
+ if ($this->isIeOverSsl()) {
+ header('Cache-Control: cache, must-revalidate');
+ header('Pragma: public');
+ } else {
+ header('Cache-Control: no-cache, must-revalidate');
+ header('Pragma: no-cache');
+ }
+ header('Expires: Thu, 19 Nov 1981 08:52:00 GMT');
header('Content-Type: application/x-amf');
}
return parent::getResponse();
}
+
+ protected function isIeOverSsl()
+ {
+ $ssl = isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : false;
+ if (!$ssl || ($ssl == 'off')) {
+ // IIS reports "off", whereas other browsers simply don't populate
+ return false;
+ }
+
+ $ua = $_SERVER['HTTP_USER_AGENT'];
+ if (!preg_match('/; MSIE \d+\.\d+;/', $ua)) {
+ // Not MicroSoft Internet Explorer
+ return false;
+ }
+
+ return true;
+ }
}
diff --git a/lib/zend/Zend/Amf/Server.php b/lib/zend/Zend/Amf/Server.php
index 241041f3e17..0f87286031d 100644
--- a/lib/zend/Zend/Amf/Server.php
+++ b/lib/zend/Zend/Amf/Server.php
@@ -14,7 +14,7 @@
*
* @category Zend
* @package Zend_Amf
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
@@ -52,7 +52,7 @@ require_once 'Zend/Auth.php';
* @todo Make the reflection methods cache and autoload.
* @package Zend_Amf
* @subpackage Server
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Server implements Zend_Server_Interface
@@ -108,7 +108,7 @@ class Zend_Amf_Server implements Zend_Server_Interface
protected $_session = false;
/**
- * Namespace allows all AMF calls to not clobber other php session variables
+ * Namespace allows all AMF calls to not clobber other PHP session variables
* @var Zend_Session_NameSpace default session namespace zend_amf
*/
protected $_sesionNamespace = 'zend_amf';
@@ -142,12 +142,18 @@ class Zend_Amf_Server implements Zend_Server_Interface
/**
* Set authentication adapter
*
+ * If the authentication adapter implements a "getAcl()" method, populate
+ * the ACL of this instance with it (if none exists already).
+ *
* @param Zend_Amf_Auth_Abstract $auth
* @return Zend_Amf_Server
*/
public function setAuth(Zend_Amf_Auth_Abstract $auth)
{
$this->_auth = $auth;
+ if ((null === $this->getAcl()) && method_exists($auth, 'getAcl')) {
+ $this->setAcl($auth->getAcl());
+ }
return $this;
}
/**
@@ -300,12 +306,12 @@ class Zend_Amf_Server implements Zend_Server_Interface
$source = $mapped;
}
}
- $qualifiedName = empty($source) ? $method : $source.".".$method;
+ $qualifiedName = empty($source) ? $method : $source . '.' . $method;
if (!isset($this->_table[$qualifiedName])) {
// if source is null a method that was not defined was called.
if ($source) {
- $className = str_replace(".", "_", $source);
+ $className = str_replace('.', '_', $source);
if(class_exists($className, false) && !isset($this->_classAllowed[$className])) {
require_once 'Zend/Amf/Server/Exception.php';
throw new Zend_Amf_Server_Exception('Can not call "' . $className . '" - use setClass()');
@@ -317,8 +323,12 @@ class Zend_Amf_Server implements Zend_Server_Interface
throw new Zend_Amf_Server_Exception('Class "' . $className . '" does not exist: '.$e->getMessage(), 0, $e);
}
// Add the new loaded class to the server.
+ require_once 'Zend/Amf/Server/Exception.php';
$this->setClass($className, $source);
- } else {
+ }
+
+ if (!isset($this->_table[$qualifiedName])) {
+ // Source is null or doesn't contain specified method
require_once 'Zend/Amf/Server/Exception.php';
throw new Zend_Amf_Server_Exception('Method "' . $method . '" does not exist');
}
@@ -331,6 +341,8 @@ class Zend_Amf_Server implements Zend_Server_Interface
$params = array_merge($params, $argv);
}
+ $params = $this->_castParameters($info, $params);
+
if ($info instanceof Zend_Server_Reflection_Function) {
$func = $info->getName();
$this->_checkAcl(null, $func);
@@ -491,66 +503,60 @@ class Zend_Amf_Server implements Zend_Server_Interface
// set response encoding
$response->setObjectEncoding($objectEncoding);
- $responseBody = $request->getAmfBodies();
-
- $handleAuth = false;
- if ($this->_auth) {
- $headers = $request->getAmfHeaders();
- if (isset($headers[Zend_Amf_Constants::CREDENTIALS_HEADER]) &&
- isset($headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->userid)) {
- $handleAuth = true;
+ // Authenticate, if we have credential headers
+ $error = false;
+ $headers = $request->getAmfHeaders();
+ if (isset($headers[Zend_Amf_Constants::CREDENTIALS_HEADER])
+ && isset($headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->userid)
+ && isset($headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->password)
+ ) {
+ try {
+ if ($this->_handleAuth(
+ $headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->userid,
+ $headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->password
+ )) {
+ // use RequestPersistentHeader to clear credentials
+ $response->addAmfHeader(
+ new Zend_Amf_Value_MessageHeader(
+ Zend_Amf_Constants::PERSISTENT_HEADER,
+ false,
+ new Zend_Amf_Value_MessageHeader(
+ Zend_Amf_Constants::CREDENTIALS_HEADER,
+ false, null
+ )
+ )
+ );
+ }
+ } catch (Exception $e) {
+ // Error during authentication; report it
+ $error = $this->_errorMessage(
+ $objectEncoding,
+ '',
+ $e->getMessage(),
+ $e->getTraceAsString(),
+ $e->getCode(),
+ $e->getLine()
+ );
+ $responseType = Zend_AMF_Constants::STATUS_METHOD;
}
}
// Iterate through each of the service calls in the AMF request
- foreach($responseBody as $body)
+ foreach($request->getAmfBodies() as $body)
{
+ if ($error) {
+ // Error during authentication; just report it and be done
+ $responseURI = $body->getResponseURI() . $responseType;
+ $newBody = new Zend_Amf_Value_MessageBody($responseURI, null, $error);
+ $response->addAmfBody($newBody);
+ continue;
+ }
try {
- if ($handleAuth) {
- if ($this->_handleAuth(
- $headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->userid,
- $headers[Zend_Amf_Constants::CREDENTIALS_HEADER]->password)) {
- // use RequestPersistentHeader to clear credentials
- $response->addAmfHeader(
- new Zend_Amf_Value_MessageHeader(
- Zend_Amf_Constants::PERSISTENT_HEADER,
- false,
- new Zend_Amf_Value_MessageHeader(
- Zend_Amf_Constants::CREDENTIALS_HEADER,
- false, null)));
- $handleAuth = false;
- }
- }
-
- if ($objectEncoding == Zend_Amf_Constants::AMF0_OBJECT_ENCODING) {
- // AMF0 Object Encoding
- $targetURI = $body->getTargetURI();
- $message = '';
-
- // Split the target string into its values.
- $source = substr($targetURI, 0, strrpos($targetURI, '.'));
-
- if ($source) {
- // Break off method name from namespace into source
- $method = substr(strrchr($targetURI, '.'), 1);
- $return = $this->_dispatch($method, $body->getData(), $source);
- } else {
- // Just have a method name.
- $return = $this->_dispatch($targetURI, $body->getData());
- }
- } else {
- // AMF3 read message type
- $message = $body->getData();
- if ($message instanceof Zend_Amf_Value_Messaging_CommandMessage) {
- // async call with command message
- $return = $this->_loadCommandMessage($message);
- } elseif ($message instanceof Zend_Amf_Value_Messaging_RemotingMessage) {
- require_once 'Zend/Amf/Value/Messaging/AcknowledgeMessage.php';
- $return = new Zend_Amf_Value_Messaging_AcknowledgeMessage($message);
- $return->body = $this->_dispatch($message->operation, $message->body, $message->source);
- } else {
- // Amf3 message sent with netConnection
+ switch ($objectEncoding) {
+ case Zend_Amf_Constants::AMF0_OBJECT_ENCODING:
+ // AMF0 Object Encoding
$targetURI = $body->getTargetURI();
+ $message = '';
// Split the target string into its values.
$source = substr($targetURI, 0, strrpos($targetURI, '.'));
@@ -563,7 +569,35 @@ class Zend_Amf_Server implements Zend_Server_Interface
// Just have a method name.
$return = $this->_dispatch($targetURI, $body->getData());
}
- }
+ break;
+ case Zend_Amf_Constants::AMF3_OBJECT_ENCODING:
+ default:
+ // AMF3 read message type
+ $message = $body->getData();
+ if ($message instanceof Zend_Amf_Value_Messaging_CommandMessage) {
+ // async call with command message
+ $return = $this->_loadCommandMessage($message);
+ } elseif ($message instanceof Zend_Amf_Value_Messaging_RemotingMessage) {
+ require_once 'Zend/Amf/Value/Messaging/AcknowledgeMessage.php';
+ $return = new Zend_Amf_Value_Messaging_AcknowledgeMessage($message);
+ $return->body = $this->_dispatch($message->operation, $message->body, $message->source);
+ } else {
+ // Amf3 message sent with netConnection
+ $targetURI = $body->getTargetURI();
+
+ // Split the target string into its values.
+ $source = substr($targetURI, 0, strrpos($targetURI, '.'));
+
+ if ($source) {
+ // Break off method name from namespace into source
+ $method = substr(strrchr($targetURI, '.'), 1);
+ $return = $this->_dispatch($method, $body->getData(), $source);
+ } else {
+ // Just have a method name.
+ $return = $this->_dispatch($targetURI, $body->getData());
+ }
+ }
+ break;
}
$responseType = Zend_AMF_Constants::RESULT_METHOD;
} catch (Exception $e) {
@@ -607,7 +641,7 @@ class Zend_Amf_Server implements Zend_Server_Interface
public function handle($request = null)
{
// Check if request was passed otherwise get it from the server
- if (is_null($request) || !$request instanceof Zend_Amf_Request) {
+ if ($request === null || !$request instanceof Zend_Amf_Request) {
$request = $this->getRequest();
} else {
$this->setRequest($request);
@@ -733,9 +767,9 @@ class Zend_Amf_Server implements Zend_Server_Interface
throw new Zend_Amf_Server_Exception('Invalid method or class; must be a classname or object');
}
- $argv = null;
+ $args = null;
if (2 < func_num_args()) {
- $argv = array_slice(func_get_args(), 2);
+ $args = array_slice(func_get_args(), 2);
}
// Use the class name as the name space by default.
@@ -746,7 +780,7 @@ class Zend_Amf_Server implements Zend_Server_Interface
$this->_classAllowed[is_object($class) ? get_class($class) : $class] = true;
- $this->_methods[] = Zend_Server_Reflection::reflectClass($class, $argv, $namespace);
+ $this->_methods[] = Zend_Server_Reflection::reflectClass($class, $args, $namespace);
$this->_buildDispatchTable();
return $this;
@@ -930,4 +964,85 @@ class Zend_Amf_Server implements Zend_Server_Interface
{
return array_keys($this->_table);
}
+
+ /**
+ * Cast parameters
+ *
+ * Takes the provided parameters from the request, and attempts to cast them
+ * to objects, if the prototype defines any as explicit object types
+ *
+ * @param Reflection $reflectionMethod
+ * @param array $params
+ * @return array
+ */
+ protected function _castParameters($reflectionMethod, array $params)
+ {
+ $prototypes = $reflectionMethod->getPrototypes();
+ $nonObjectTypes = array(
+ 'null',
+ 'mixed',
+ 'void',
+ 'unknown',
+ 'bool',
+ 'boolean',
+ 'number',
+ 'int',
+ 'integer',
+ 'double',
+ 'float',
+ 'string',
+ 'array',
+ 'object',
+ 'stdclass',
+ );
+ $types = array();
+ foreach ($prototypes as $prototype) {
+ foreach ($prototype->getParameters() as $parameter) {
+ $type = $parameter->getType();
+ if (in_array(strtolower($type), $nonObjectTypes)) {
+ continue;
+ }
+ $position = $parameter->getPosition();
+ $types[$position] = $type;
+ }
+ }
+
+ if (empty($types)) {
+ return $params;
+ }
+
+ foreach ($params as $position => $value) {
+ if (!isset($types[$position])) {
+ // No specific type to cast to? done
+ continue;
+ }
+
+ $type = $types[$position];
+
+ if (!class_exists($type)) {
+ // Not a class, apparently. done
+ continue;
+ }
+
+ if ($value instanceof $type) {
+ // Already of the right type? done
+ continue;
+ }
+
+ if (!is_array($value) && !is_object($value)) {
+ // Can't cast scalars to objects easily; done
+ continue;
+ }
+
+ // Create instance, and loop through value to set
+ $object = new $type;
+ foreach ($value as $property => $defined) {
+ $object->{$property} = $defined;
+ }
+
+ $params[$position] = $object;
+ }
+
+ return $params;
+ }
}
diff --git a/lib/zend/Zend/Amf/Server/Exception.php b/lib/zend/Zend/Amf/Server/Exception.php
index 10fe6762857..d9532ac1123 100644
--- a/lib/zend/Zend/Amf/Server/Exception.php
+++ b/lib/zend/Zend/Amf/Server/Exception.php
@@ -15,7 +15,7 @@
* @category Zend
* @package Zend_Amf
* @subpackage Server
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
@@ -29,7 +29,7 @@ require_once 'Zend/Amf/Exception.php';
* @category Zend
* @package Zend_Amf
* @subpackage Server
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Server_Exception extends Zend_Amf_Exception
diff --git a/lib/zend/Zend/Amf/Util/BinaryStream.php b/lib/zend/Zend/Amf/Util/BinaryStream.php
index fefc271de99..b56820a62fa 100644
--- a/lib/zend/Zend/Amf/Util/BinaryStream.php
+++ b/lib/zend/Zend/Amf/Util/BinaryStream.php
@@ -15,7 +15,7 @@
* @category Zend
* @package Zend_Amf
* @subpackage Util
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
@@ -25,7 +25,7 @@
*
* @package Zend_Amf
* @subpackage Util
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Util_BinaryStream
@@ -50,6 +50,11 @@ class Zend_Amf_Util_BinaryStream
*/
protected $_needle;
+ /**
+ * @var bool str* functions overloaded using mbstring.func_overload?
+ */
+ protected $_mbStringFunctionsOverloaded;
+
/**
* Constructor
*
@@ -69,7 +74,8 @@ class Zend_Amf_Util_BinaryStream
$this->_stream = $stream;
$this->_needle = 0;
- $this->_streamLength = strlen($stream);
+ $this->_mbStringFunctionsOverloaded = function_exists('mb_strlen') && (ini_get('mbstring.func_overload') !== '') && ((int)ini_get('mbstring.func_overload') & 2);
+ $this->_streamLength = $this->_mbStringFunctionsOverloaded ? mb_strlen($stream, '8bit') : strlen($stream);
$this->_bigEndian = (pack('l', 1) === "\x00\x00\x00\x01");
}
@@ -97,7 +103,7 @@ class Zend_Amf_Util_BinaryStream
require_once 'Zend/Amf/Exception.php';
throw new Zend_Amf_Exception('Buffer underrun at needle position: ' . $this->_needle . ' while requesting length: ' . $length);
}
- $bytes = substr($this->_stream, $this->_needle, $length);
+ $bytes = $this->_mbStringFunctionsOverloaded ? mb_substr($this->_stream, $this->_needle, $length, '8bit') : substr($this->_stream, $this->_needle, $length);
$this->_needle+= $length;
return $bytes;
}
@@ -120,12 +126,18 @@ class Zend_Amf_Util_BinaryStream
* Reads a signed byte
*
* @return int Value is in the range of -128 to 127.
+ * @throws Zend_Amf_Exception
*/
public function readByte()
{
if (($this->_needle + 1) > $this->_streamLength) {
require_once 'Zend/Amf/Exception.php';
- throw new Zend_Amf_Exception('Buffer underrun at needle position: ' . $this->_needle . ' while requesting length: ' . $length);
+ throw new Zend_Amf_Exception(
+ 'Buffer underrun at needle position: '
+ . $this->_needle
+ . ' while requesting length: '
+ . $this->_streamLength
+ );
}
return ord($this->_stream{$this->_needle++});
@@ -184,7 +196,7 @@ class Zend_Amf_Util_BinaryStream
*/
public function writeUtf($stream)
{
- $this->writeInt(strlen($stream));
+ $this->writeInt($this->_mbStringFunctionsOverloaded ? mb_strlen($stream, '8bit') : strlen($stream));
$this->_stream.= $stream;
return $this;
}
@@ -209,7 +221,7 @@ class Zend_Amf_Util_BinaryStream
*/
public function writeLongUtf($stream)
{
- $this->writeLong(strlen($stream));
+ $this->writeLong($this->_mbStringFunctionsOverloaded ? mb_strlen($stream, '8bit') : strlen($stream));
$this->_stream.= $stream;
}
@@ -255,7 +267,7 @@ class Zend_Amf_Util_BinaryStream
*/
public function readDouble()
{
- $bytes = substr($this->_stream, $this->_needle, 8);
+ $bytes = $this->_mbStringFunctionsOverloaded ? mb_substr($this->_stream, $this->_needle, 8, '8bit') : substr($this->_stream, $this->_needle, 8);
$this->_needle+= 8;
if (!$this->_bigEndian) {
diff --git a/lib/zend/Zend/Amf/Value/ByteArray.php b/lib/zend/Zend/Amf/Value/ByteArray.php
index 3555f300f35..32ebf268b81 100644
--- a/lib/zend/Zend/Amf/Value/ByteArray.php
+++ b/lib/zend/Zend/Amf/Value/ByteArray.php
@@ -15,7 +15,7 @@
* @category Zend
* @package Zend_Amf
* @subpackage Value
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
@@ -25,7 +25,7 @@
*
* @package Zend_Amf
* @subpackage Value
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Value_ByteArray
diff --git a/lib/zend/Zend/Amf/Value/MessageBody.php b/lib/zend/Zend/Amf/Value/MessageBody.php
index 4d4e67ed300..59cacba52be 100644
--- a/lib/zend/Zend/Amf/Value/MessageBody.php
+++ b/lib/zend/Zend/Amf/Value/MessageBody.php
@@ -15,7 +15,7 @@
* @category Zend
* @package Zend_Amf
* @subpackage Value
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
@@ -33,7 +33,7 @@
*
* @package Zend_Amf
* @subpackage Value
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Value_MessageBody
diff --git a/lib/zend/Zend/Amf/Value/MessageHeader.php b/lib/zend/Zend/Amf/Value/MessageHeader.php
index 3058db1e0f4..bdbbba2a7db 100644
--- a/lib/zend/Zend/Amf/Value/MessageHeader.php
+++ b/lib/zend/Zend/Amf/Value/MessageHeader.php
@@ -15,7 +15,7 @@
* @category Zend
* @package Zend_Amf
* @subpackage Value
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
@@ -28,7 +28,7 @@
*
* @package Zend_Amf
* @subpackage Value
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Value_MessageHeader
diff --git a/lib/zend/Zend/Amf/Value/Messaging/AbstractMessage.php b/lib/zend/Zend/Amf/Value/Messaging/AbstractMessage.php
index fab2b9d6e5e..acb5a0c6c8e 100644
--- a/lib/zend/Zend/Amf/Value/Messaging/AbstractMessage.php
+++ b/lib/zend/Zend/Amf/Value/Messaging/AbstractMessage.php
@@ -15,7 +15,7 @@
* @category Zend
* @package Zend_Amf
* @subpackage Value
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
@@ -26,7 +26,7 @@
*
* @package Zend_Amf
* @subpackage Value
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Value_Messaging_AbstractMessage
diff --git a/lib/zend/Zend/Amf/Value/Messaging/AcknowledgeMessage.php b/lib/zend/Zend/Amf/Value/Messaging/AcknowledgeMessage.php
index 8f54c333077..eb081bd4e25 100644
--- a/lib/zend/Zend/Amf/Value/Messaging/AcknowledgeMessage.php
+++ b/lib/zend/Zend/Amf/Value/Messaging/AcknowledgeMessage.php
@@ -15,7 +15,7 @@
* @category Zend
* @package Zend_Amf
* @subpackage Value
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
@@ -32,7 +32,7 @@ require_once 'Zend/Amf/Value/Messaging/AsyncMessage.php';
*
* @package Zend_Amf
* @subpackage Value
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Value_Messaging_AcknowledgeMessage extends Zend_Amf_Value_Messaging_AsyncMessage
diff --git a/lib/zend/Zend/Amf/Value/Messaging/ArrayCollection.php b/lib/zend/Zend/Amf/Value/Messaging/ArrayCollection.php
old mode 100644
new mode 100755
index 0b1b9301a42..a759f58e53e
--- a/lib/zend/Zend/Amf/Value/Messaging/ArrayCollection.php
+++ b/lib/zend/Zend/Amf/Value/Messaging/ArrayCollection.php
@@ -15,7 +15,7 @@
* @category Zend
* @package Zend_Amf
* @subpackage Value
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
@@ -27,9 +27,9 @@
*
* @package Zend_Amf
* @subpackage Value
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
-class Zend_Amf_Value_Messaging_ArrayCollection
+class Zend_Amf_Value_Messaging_ArrayCollection extends ArrayObject
{
}
diff --git a/lib/zend/Zend/Amf/Value/Messaging/AsyncMessage.php b/lib/zend/Zend/Amf/Value/Messaging/AsyncMessage.php
index 8787e57ce03..d052cb60ac3 100644
--- a/lib/zend/Zend/Amf/Value/Messaging/AsyncMessage.php
+++ b/lib/zend/Zend/Amf/Value/Messaging/AsyncMessage.php
@@ -15,7 +15,7 @@
* @category Zend
* @package Zend_Amf
* @subpackage Value
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
@@ -30,7 +30,7 @@ require_once 'Zend/Amf/Value/Messaging/AbstractMessage.php';
*
* @package Zend_Amf
* @subpackage Value
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Value_Messaging_AsyncMessage extends Zend_Amf_Value_Messaging_AbstractMessage
diff --git a/lib/zend/Zend/Amf/Value/Messaging/CommandMessage.php b/lib/zend/Zend/Amf/Value/Messaging/CommandMessage.php
index 05f4534883e..f4500da18dc 100644
--- a/lib/zend/Zend/Amf/Value/Messaging/CommandMessage.php
+++ b/lib/zend/Zend/Amf/Value/Messaging/CommandMessage.php
@@ -15,7 +15,7 @@
* @category Zend
* @package Zend_Amf
* @subpackage Value
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
@@ -36,7 +36,7 @@ require_once 'Zend/Amf/Value/Messaging/AsyncMessage.php';
*
* @package Zend_Amf
* @subpackage Value
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Value_Messaging_CommandMessage extends Zend_Amf_Value_Messaging_AsyncMessage
diff --git a/lib/zend/Zend/Amf/Value/Messaging/ErrorMessage.php b/lib/zend/Zend/Amf/Value/Messaging/ErrorMessage.php
index d3f7f950e8b..a6eaf166fb4 100644
--- a/lib/zend/Zend/Amf/Value/Messaging/ErrorMessage.php
+++ b/lib/zend/Zend/Amf/Value/Messaging/ErrorMessage.php
@@ -15,7 +15,7 @@
* @category Zend
* @package Zend_Amf
* @subpackage Value
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
@@ -30,7 +30,7 @@ require_once 'Zend/Amf/Value/Messaging/AcknowledgeMessage.php';
*
* @package Zend_Amf
* @subpackage Value
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Value_Messaging_ErrorMessage extends Zend_Amf_Value_Messaging_AcknowledgeMessage
diff --git a/lib/zend/Zend/Amf/Value/Messaging/RemotingMessage.php b/lib/zend/Zend/Amf/Value/Messaging/RemotingMessage.php
index 075fe9ee125..43c1e1e889b 100644
--- a/lib/zend/Zend/Amf/Value/Messaging/RemotingMessage.php
+++ b/lib/zend/Zend/Amf/Value/Messaging/RemotingMessage.php
@@ -15,7 +15,7 @@
* @category Zend
* @package Zend_Amf
* @subpackage Value
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
@@ -31,7 +31,7 @@ require_once 'Zend/Amf/Value/Messaging/AbstractMessage.php';
*
* @package Zend_Amf
* @subpackage Value
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Value_Messaging_RemotingMessage extends Zend_Amf_Value_Messaging_AbstractMessage
diff --git a/lib/zend/Zend/Amf/Value/TraitsInfo.php b/lib/zend/Zend/Amf/Value/TraitsInfo.php
index c92ffc21d37..64d3c990ea0 100644
--- a/lib/zend/Zend/Amf/Value/TraitsInfo.php
+++ b/lib/zend/Zend/Amf/Value/TraitsInfo.php
@@ -15,7 +15,7 @@
* @category Zend
* @package Zend_Amf
* @subpackage Value
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
@@ -25,7 +25,7 @@
*
* @package Zend_Amf
* @subpackage Value
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Amf_Value_TraitsInfo
diff --git a/lib/zend/Zend/Auth.php b/lib/zend/Zend/Auth.php
index 39659507e82..0b4b00ffb44 100644
--- a/lib/zend/Zend/Auth.php
+++ b/lib/zend/Zend/Auth.php
@@ -14,7 +14,7 @@
*
* @category Zend
* @package Zend_Auth
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
@@ -23,7 +23,7 @@
/**
* @category Zend
* @package Zend_Auth
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Auth
diff --git a/lib/zend/Zend/Auth/Adapter/Digest.php b/lib/zend/Zend/Auth/Adapter/Digest.php
new file mode 100644
index 00000000000..f52b651e7a6
--- /dev/null
+++ b/lib/zend/Zend/Auth/Adapter/Digest.php
@@ -0,0 +1,251 @@
+$methodName($$option);
+ }
+ }
+ }
+
+ /**
+ * Returns the filename option value or null if it has not yet been set
+ *
+ * @return string|null
+ */
+ public function getFilename()
+ {
+ return $this->_filename;
+ }
+
+ /**
+ * Sets the filename option value
+ *
+ * @param mixed $filename
+ * @return Zend_Auth_Adapter_Digest Provides a fluent interface
+ */
+ public function setFilename($filename)
+ {
+ $this->_filename = (string) $filename;
+ return $this;
+ }
+
+ /**
+ * Returns the realm option value or null if it has not yet been set
+ *
+ * @return string|null
+ */
+ public function getRealm()
+ {
+ return $this->_realm;
+ }
+
+ /**
+ * Sets the realm option value
+ *
+ * @param mixed $realm
+ * @return Zend_Auth_Adapter_Digest Provides a fluent interface
+ */
+ public function setRealm($realm)
+ {
+ $this->_realm = (string) $realm;
+ return $this;
+ }
+
+ /**
+ * Returns the username option value or null if it has not yet been set
+ *
+ * @return string|null
+ */
+ public function getUsername()
+ {
+ return $this->_username;
+ }
+
+ /**
+ * Sets the username option value
+ *
+ * @param mixed $username
+ * @return Zend_Auth_Adapter_Digest Provides a fluent interface
+ */
+ public function setUsername($username)
+ {
+ $this->_username = (string) $username;
+ return $this;
+ }
+
+ /**
+ * Returns the password option value or null if it has not yet been set
+ *
+ * @return string|null
+ */
+ public function getPassword()
+ {
+ return $this->_password;
+ }
+
+ /**
+ * Sets the password option value
+ *
+ * @param mixed $password
+ * @return Zend_Auth_Adapter_Digest Provides a fluent interface
+ */
+ public function setPassword($password)
+ {
+ $this->_password = (string) $password;
+ return $this;
+ }
+
+ /**
+ * Defined by Zend_Auth_Adapter_Interface
+ *
+ * @throws Zend_Auth_Adapter_Exception
+ * @return Zend_Auth_Result
+ */
+ public function authenticate()
+ {
+ $optionsRequired = array('filename', 'realm', 'username', 'password');
+ foreach ($optionsRequired as $optionRequired) {
+ if (null === $this->{"_$optionRequired"}) {
+ /**
+ * @see Zend_Auth_Adapter_Exception
+ */
+ require_once 'Zend/Auth/Adapter/Exception.php';
+ throw new Zend_Auth_Adapter_Exception("Option '$optionRequired' must be set before authentication");
+ }
+ }
+
+ if (false === ($fileHandle = @fopen($this->_filename, 'r'))) {
+ /**
+ * @see Zend_Auth_Adapter_Exception
+ */
+ require_once 'Zend/Auth/Adapter/Exception.php';
+ throw new Zend_Auth_Adapter_Exception("Cannot open '$this->_filename' for reading");
+ }
+
+ $id = "$this->_username:$this->_realm";
+ $idLength = strlen($id);
+
+ $result = array(
+ 'code' => Zend_Auth_Result::FAILURE,
+ 'identity' => array(
+ 'realm' => $this->_realm,
+ 'username' => $this->_username,
+ ),
+ 'messages' => array()
+ );
+
+ while ($line = trim(fgets($fileHandle))) {
+ if (substr($line, 0, $idLength) === $id) {
+ if ($this->_secureStringCompare(substr($line, -32), md5("$this->_username:$this->_realm:$this->_password"))) {
+ $result['code'] = Zend_Auth_Result::SUCCESS;
+ } else {
+ $result['code'] = Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID;
+ $result['messages'][] = 'Password incorrect';
+ }
+ return new Zend_Auth_Result($result['code'], $result['identity'], $result['messages']);
+ }
+ }
+
+ $result['code'] = Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND;
+ $result['messages'][] = "Username '$this->_username' and realm '$this->_realm' combination not found";
+ return new Zend_Auth_Result($result['code'], $result['identity'], $result['messages']);
+ }
+
+ /**
+ * Securely compare two strings for equality while avoided C level memcmp()
+ * optimisations capable of leaking timing information useful to an attacker
+ * attempting to iteratively guess the unknown string (e.g. password) being
+ * compared against.
+ *
+ * @param string $a
+ * @param string $b
+ * @return bool
+ */
+ protected function _secureStringCompare($a, $b)
+ {
+ if (strlen($a) !== strlen($b)) {
+ return false;
+ }
+ $result = 0;
+ for ($i = 0; $i < strlen($a); $i++) {
+ $result |= ord($a[$i]) ^ ord($b[$i]);
+ }
+ return $result == 0;
+ }
+}
diff --git a/lib/zend/Zend/Auth/Adapter/Exception.php b/lib/zend/Zend/Auth/Adapter/Exception.php
new file mode 100644
index 00000000000..03216493065
--- /dev/null
+++ b/lib/zend/Zend/Auth/Adapter/Exception.php
@@ -0,0 +1,38 @@
+ 'basic'|'digest'|'basic digest'
+ * 'realm' =>
+ * 'digest_domains' => Space-delimited list of URIs
+ * 'nonce_timeout' =>
+ * 'use_opaque' => Whether to send the opaque value in the header
+ * 'alogrithm' => See $_supportedAlgos. Default: MD5
+ * 'proxy_auth' => Whether to do authentication as a Proxy
+ * @throws Zend_Auth_Adapter_Exception
+ */
+ public function __construct(array $config)
+ {
+ if (!extension_loaded('hash')) {
+ /**
+ * @see Zend_Auth_Adapter_Exception
+ */
+ require_once 'Zend/Auth/Adapter/Exception.php';
+ throw new Zend_Auth_Adapter_Exception(__CLASS__ . ' requires the \'hash\' extension');
+ }
+
+ $this->_request = null;
+ $this->_response = null;
+ $this->_ieNoOpaque = false;
+
+
+ if (empty($config['accept_schemes'])) {
+ /**
+ * @see Zend_Auth_Adapter_Exception
+ */
+ require_once 'Zend/Auth/Adapter/Exception.php';
+ throw new Zend_Auth_Adapter_Exception('Config key \'accept_schemes\' is required');
+ }
+
+ $schemes = explode(' ', $config['accept_schemes']);
+ $this->_acceptSchemes = array_intersect($schemes, $this->_supportedSchemes);
+ if (empty($this->_acceptSchemes)) {
+ /**
+ * @see Zend_Auth_Adapter_Exception
+ */
+ require_once 'Zend/Auth/Adapter/Exception.php';
+ throw new Zend_Auth_Adapter_Exception('No supported schemes given in \'accept_schemes\'. Valid values: '
+ . implode(', ', $this->_supportedSchemes));
+ }
+
+ // Double-quotes are used to delimit the realm string in the HTTP header,
+ // and colons are field delimiters in the password file.
+ if (empty($config['realm']) ||
+ !ctype_print($config['realm']) ||
+ strpos($config['realm'], ':') !== false ||
+ strpos($config['realm'], '"') !== false) {
+ /**
+ * @see Zend_Auth_Adapter_Exception
+ */
+ require_once 'Zend/Auth/Adapter/Exception.php';
+ throw new Zend_Auth_Adapter_Exception('Config key \'realm\' is required, and must contain only printable '
+ . 'characters, excluding quotation marks and colons');
+ } else {
+ $this->_realm = $config['realm'];
+ }
+
+ if (in_array('digest', $this->_acceptSchemes)) {
+ if (empty($config['digest_domains']) ||
+ !ctype_print($config['digest_domains']) ||
+ strpos($config['digest_domains'], '"') !== false) {
+ /**
+ * @see Zend_Auth_Adapter_Exception
+ */
+ require_once 'Zend/Auth/Adapter/Exception.php';
+ throw new Zend_Auth_Adapter_Exception('Config key \'digest_domains\' is required, and must contain '
+ . 'only printable characters, excluding quotation marks');
+ } else {
+ $this->_domains = $config['digest_domains'];
+ }
+
+ if (empty($config['nonce_timeout']) ||
+ !is_numeric($config['nonce_timeout'])) {
+ /**
+ * @see Zend_Auth_Adapter_Exception
+ */
+ require_once 'Zend/Auth/Adapter/Exception.php';
+ throw new Zend_Auth_Adapter_Exception('Config key \'nonce_timeout\' is required, and must be an '
+ . 'integer');
+ } else {
+ $this->_nonceTimeout = (int) $config['nonce_timeout'];
+ }
+
+ // We use the opaque value unless explicitly told not to
+ if (isset($config['use_opaque']) && false == (bool) $config['use_opaque']) {
+ $this->_useOpaque = false;
+ } else {
+ $this->_useOpaque = true;
+ }
+
+ if (isset($config['algorithm']) && in_array($config['algorithm'], $this->_supportedAlgos)) {
+ $this->_algo = $config['algorithm'];
+ } else {
+ $this->_algo = 'MD5';
+ }
+ }
+
+ // Don't be a proxy unless explicitly told to do so
+ if (isset($config['proxy_auth']) && true == (bool) $config['proxy_auth']) {
+ $this->_imaProxy = true; // I'm a Proxy
+ } else {
+ $this->_imaProxy = false;
+ }
+ }
+
+ /**
+ * Setter for the _basicResolver property
+ *
+ * @param Zend_Auth_Adapter_Http_Resolver_Interface $resolver
+ * @return Zend_Auth_Adapter_Http Provides a fluent interface
+ */
+ public function setBasicResolver(Zend_Auth_Adapter_Http_Resolver_Interface $resolver)
+ {
+ $this->_basicResolver = $resolver;
+
+ return $this;
+ }
+
+ /**
+ * Getter for the _basicResolver property
+ *
+ * @return Zend_Auth_Adapter_Http_Resolver_Interface
+ */
+ public function getBasicResolver()
+ {
+ return $this->_basicResolver;
+ }
+
+ /**
+ * Setter for the _digestResolver property
+ *
+ * @param Zend_Auth_Adapter_Http_Resolver_Interface $resolver
+ * @return Zend_Auth_Adapter_Http Provides a fluent interface
+ */
+ public function setDigestResolver(Zend_Auth_Adapter_Http_Resolver_Interface $resolver)
+ {
+ $this->_digestResolver = $resolver;
+
+ return $this;
+ }
+
+ /**
+ * Getter for the _digestResolver property
+ *
+ * @return Zend_Auth_Adapter_Http_Resolver_Interface
+ */
+ public function getDigestResolver()
+ {
+ return $this->_digestResolver;
+ }
+
+ /**
+ * Setter for the Request object
+ *
+ * @param Zend_Controller_Request_Http $request
+ * @return Zend_Auth_Adapter_Http Provides a fluent interface
+ */
+ public function setRequest(Zend_Controller_Request_Http $request)
+ {
+ $this->_request = $request;
+
+ return $this;
+ }
+
+ /**
+ * Getter for the Request object
+ *
+ * @return Zend_Controller_Request_Http
+ */
+ public function getRequest()
+ {
+ return $this->_request;
+ }
+
+ /**
+ * Setter for the Response object
+ *
+ * @param Zend_Controller_Response_Http $response
+ * @return Zend_Auth_Adapter_Http Provides a fluent interface
+ */
+ public function setResponse(Zend_Controller_Response_Http $response)
+ {
+ $this->_response = $response;
+
+ return $this;
+ }
+
+ /**
+ * Getter for the Response object
+ *
+ * @return Zend_Controller_Response_Http
+ */
+ public function getResponse()
+ {
+ return $this->_response;
+ }
+
+ /**
+ * Authenticate
+ *
+ * @throws Zend_Auth_Adapter_Exception
+ * @return Zend_Auth_Result
+ */
+ public function authenticate()
+ {
+ if (empty($this->_request) ||
+ empty($this->_response)) {
+ /**
+ * @see Zend_Auth_Adapter_Exception
+ */
+ require_once 'Zend/Auth/Adapter/Exception.php';
+ throw new Zend_Auth_Adapter_Exception('Request and Response objects must be set before calling '
+ . 'authenticate()');
+ }
+
+ if ($this->_imaProxy) {
+ $getHeader = 'Proxy-Authorization';
+ } else {
+ $getHeader = 'Authorization';
+ }
+
+ $authHeader = $this->_request->getHeader($getHeader);
+ if (!$authHeader) {
+ return $this->_challengeClient();
+ }
+
+ list($clientScheme) = explode(' ', $authHeader);
+ $clientScheme = strtolower($clientScheme);
+
+ // The server can issue multiple challenges, but the client should
+ // answer with only the selected auth scheme.
+ if (!in_array($clientScheme, $this->_supportedSchemes)) {
+ $this->_response->setHttpResponseCode(400);
+ return new Zend_Auth_Result(
+ Zend_Auth_Result::FAILURE_UNCATEGORIZED,
+ array(),
+ array('Client requested an incorrect or unsupported authentication scheme')
+ );
+ }
+
+ // client sent a scheme that is not the one required
+ if (!in_array($clientScheme, $this->_acceptSchemes)) {
+ // challenge again the client
+ return $this->_challengeClient();
+ }
+
+ switch ($clientScheme) {
+ case 'basic':
+ $result = $this->_basicAuth($authHeader);
+ break;
+ case 'digest':
+ $result = $this->_digestAuth($authHeader);
+ break;
+ default:
+ /**
+ * @see Zend_Auth_Adapter_Exception
+ */
+ require_once 'Zend/Auth/Adapter/Exception.php';
+ throw new Zend_Auth_Adapter_Exception('Unsupported authentication scheme');
+ }
+
+ return $result;
+ }
+
+ /**
+ * Challenge Client
+ *
+ * Sets a 401 or 407 Unauthorized response code, and creates the
+ * appropriate Authenticate header(s) to prompt for credentials.
+ *
+ * @return Zend_Auth_Result Always returns a non-identity Auth result
+ */
+ protected function _challengeClient()
+ {
+ if ($this->_imaProxy) {
+ $statusCode = 407;
+ $headerName = 'Proxy-Authenticate';
+ } else {
+ $statusCode = 401;
+ $headerName = 'WWW-Authenticate';
+ }
+
+ $this->_response->setHttpResponseCode($statusCode);
+
+ // Send a challenge in each acceptable authentication scheme
+ if (in_array('basic', $this->_acceptSchemes)) {
+ $this->_response->setHeader($headerName, $this->_basicHeader());
+ }
+ if (in_array('digest', $this->_acceptSchemes)) {
+ $this->_response->setHeader($headerName, $this->_digestHeader());
+ }
+ return new Zend_Auth_Result(
+ Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID,
+ array(),
+ array('Invalid or absent credentials; challenging client')
+ );
+ }
+
+ /**
+ * Basic Header
+ *
+ * Generates a Proxy- or WWW-Authenticate header value in the Basic
+ * authentication scheme.
+ *
+ * @return string Authenticate header value
+ */
+ protected function _basicHeader()
+ {
+ return 'Basic realm="' . $this->_realm . '"';
+ }
+
+ /**
+ * Digest Header
+ *
+ * Generates a Proxy- or WWW-Authenticate header value in the Digest
+ * authentication scheme.
+ *
+ * @return string Authenticate header value
+ */
+ protected function _digestHeader()
+ {
+ $wwwauth = 'Digest realm="' . $this->_realm . '", '
+ . 'domain="' . $this->_domains . '", '
+ . 'nonce="' . $this->_calcNonce() . '", '
+ . ($this->_useOpaque ? 'opaque="' . $this->_calcOpaque() . '", ' : '')
+ . 'algorithm="' . $this->_algo . '", '
+ . 'qop="' . implode(',', $this->_supportedQops) . '"';
+
+ return $wwwauth;
+ }
+
+ /**
+ * Basic Authentication
+ *
+ * @param string $header Client's Authorization header
+ * @throws Zend_Auth_Adapter_Exception
+ * @return Zend_Auth_Result
+ */
+ protected function _basicAuth($header)
+ {
+ if (empty($header)) {
+ /**
+ * @see Zend_Auth_Adapter_Exception
+ */
+ require_once 'Zend/Auth/Adapter/Exception.php';
+ throw new Zend_Auth_Adapter_Exception('The value of the client Authorization header is required');
+ }
+ if (empty($this->_basicResolver)) {
+ /**
+ * @see Zend_Auth_Adapter_Exception
+ */
+ require_once 'Zend/Auth/Adapter/Exception.php';
+ throw new Zend_Auth_Adapter_Exception('A basicResolver object must be set before doing Basic '
+ . 'authentication');
+ }
+
+ // Decode the Authorization header
+ $auth = substr($header, strlen('Basic '));
+ $auth = base64_decode($auth);
+ if (!$auth) {
+ /**
+ * @see Zend_Auth_Adapter_Exception
+ */
+ require_once 'Zend/Auth/Adapter/Exception.php';
+ throw new Zend_Auth_Adapter_Exception('Unable to base64_decode Authorization header value');
+ }
+
+ // See ZF-1253. Validate the credentials the same way the digest
+ // implementation does. If invalid credentials are detected,
+ // re-challenge the client.
+ if (!ctype_print($auth)) {
+ return $this->_challengeClient();
+ }
+ // Fix for ZF-1515: Now re-challenges on empty username or password
+ $creds = array_filter(explode(':', $auth));
+ if (count($creds) != 2) {
+ return $this->_challengeClient();
+ }
+
+ $password = $this->_basicResolver->resolve($creds[0], $this->_realm);
+ if ($password && $this->_secureStringCompare($password, $creds[1])) {
+ $identity = array('username'=>$creds[0], 'realm'=>$this->_realm);
+ return new Zend_Auth_Result(Zend_Auth_Result::SUCCESS, $identity);
+ } else {
+ return $this->_challengeClient();
+ }
+ }
+
+ /**
+ * Digest Authentication
+ *
+ * @param string $header Client's Authorization header
+ * @throws Zend_Auth_Adapter_Exception
+ * @return Zend_Auth_Result Valid auth result only on successful auth
+ */
+ protected function _digestAuth($header)
+ {
+ if (empty($header)) {
+ /**
+ * @see Zend_Auth_Adapter_Exception
+ */
+ require_once 'Zend/Auth/Adapter/Exception.php';
+ throw new Zend_Auth_Adapter_Exception('The value of the client Authorization header is required');
+ }
+ if (empty($this->_digestResolver)) {
+ /**
+ * @see Zend_Auth_Adapter_Exception
+ */
+ require_once 'Zend/Auth/Adapter/Exception.php';
+ throw new Zend_Auth_Adapter_Exception('A digestResolver object must be set before doing Digest authentication');
+ }
+
+ $data = $this->_parseDigestAuth($header);
+ if ($data === false) {
+ $this->_response->setHttpResponseCode(400);
+ return new Zend_Auth_Result(
+ Zend_Auth_Result::FAILURE_UNCATEGORIZED,
+ array(),
+ array('Invalid Authorization header format')
+ );
+ }
+
+ // See ZF-1052. This code was a bit too unforgiving of invalid
+ // usernames. Now, if the username is bad, we re-challenge the client.
+ if ('::invalid::' == $data['username']) {
+ return $this->_challengeClient();
+ }
+
+ // Verify that the client sent back the same nonce
+ if ($this->_calcNonce() != $data['nonce']) {
+ return $this->_challengeClient();
+ }
+ // The opaque value is also required to match, but of course IE doesn't
+ // play ball.
+ if (!$this->_ieNoOpaque && $this->_calcOpaque() != $data['opaque']) {
+ return $this->_challengeClient();
+ }
+
+ // Look up the user's password hash. If not found, deny access.
+ // This makes no assumptions about how the password hash was
+ // constructed beyond that it must have been built in such a way as
+ // to be recreatable with the current settings of this object.
+ $ha1 = $this->_digestResolver->resolve($data['username'], $data['realm']);
+ if ($ha1 === false) {
+ return $this->_challengeClient();
+ }
+
+ // If MD5-sess is used, a1 value is made of the user's password
+ // hash with the server and client nonce appended, separated by
+ // colons.
+ if ($this->_algo == 'MD5-sess') {
+ $ha1 = hash('md5', $ha1 . ':' . $data['nonce'] . ':' . $data['cnonce']);
+ }
+
+ // Calculate h(a2). The value of this hash depends on the qop
+ // option selected by the client and the supported hash functions
+ switch ($data['qop']) {
+ case 'auth':
+ $a2 = $this->_request->getMethod() . ':' . $data['uri'];
+ break;
+ case 'auth-int':
+ // Should be REQUEST_METHOD . ':' . uri . ':' . hash(entity-body),
+ // but this isn't supported yet, so fall through to default case
+ default:
+ /**
+ * @see Zend_Auth_Adapter_Exception
+ */
+ require_once 'Zend/Auth/Adapter/Exception.php';
+ throw new Zend_Auth_Adapter_Exception('Client requested an unsupported qop option');
+ }
+ // Using hash() should make parameterizing the hash algorithm
+ // easier
+ $ha2 = hash('md5', $a2);
+
+
+ // Calculate the server's version of the request-digest. This must
+ // match $data['response']. See RFC 2617, section 3.2.2.1
+ $message = $data['nonce'] . ':' . $data['nc'] . ':' . $data['cnonce'] . ':' . $data['qop'] . ':' . $ha2;
+ $digest = hash('md5', $ha1 . ':' . $message);
+
+ // If our digest matches the client's let them in, otherwise return
+ // a 401 code and exit to prevent access to the protected resource.
+ if ($this->_secureStringCompare($digest, $data['response'])) {
+ $identity = array('username'=>$data['username'], 'realm'=>$data['realm']);
+ return new Zend_Auth_Result(Zend_Auth_Result::SUCCESS, $identity);
+ } else {
+ return $this->_challengeClient();
+ }
+ }
+
+ /**
+ * Calculate Nonce
+ *
+ * @return string The nonce value
+ */
+ protected function _calcNonce()
+ {
+ // Once subtle consequence of this timeout calculation is that it
+ // actually divides all of time into _nonceTimeout-sized sections, such
+ // that the value of timeout is the point in time of the next
+ // approaching "boundary" of a section. This allows the server to
+ // consistently generate the same timeout (and hence the same nonce
+ // value) across requests, but only as long as one of those
+ // "boundaries" is not crossed between requests. If that happens, the
+ // nonce will change on its own, and effectively log the user out. This
+ // would be surprising if the user just logged in.
+ $timeout = ceil(time() / $this->_nonceTimeout) * $this->_nonceTimeout;
+
+ $nonce = hash('md5', $timeout . ':' . $this->_request->getServer('HTTP_USER_AGENT') . ':' . __CLASS__);
+ return $nonce;
+ }
+
+ /**
+ * Calculate Opaque
+ *
+ * The opaque string can be anything; the client must return it exactly as
+ * it was sent. It may be useful to store data in this string in some
+ * applications. Ideally, a new value for this would be generated each time
+ * a WWW-Authenticate header is sent (in order to reduce predictability),
+ * but we would have to be able to create the same exact value across at
+ * least two separate requests from the same client.
+ *
+ * @return string The opaque value
+ */
+ protected function _calcOpaque()
+ {
+ return hash('md5', 'Opaque Data:' . __CLASS__);
+ }
+
+ /**
+ * Parse Digest Authorization header
+ *
+ * @param string $header Client's Authorization: HTTP header
+ * @return array|false Data elements from header, or false if any part of
+ * the header is invalid
+ */
+ protected function _parseDigestAuth($header)
+ {
+ $temp = null;
+ $data = array();
+
+ // See ZF-1052. Detect invalid usernames instead of just returning a
+ // 400 code.
+ $ret = preg_match('/username="([^"]+)"/', $header, $temp);
+ if (!$ret || empty($temp[1])
+ || !ctype_print($temp[1])
+ || strpos($temp[1], ':') !== false) {
+ $data['username'] = '::invalid::';
+ } else {
+ $data['username'] = $temp[1];
+ }
+ $temp = null;
+
+ $ret = preg_match('/realm="([^"]+)"/', $header, $temp);
+ if (!$ret || empty($temp[1])) {
+ return false;
+ }
+ if (!ctype_print($temp[1]) || strpos($temp[1], ':') !== false) {
+ return false;
+ } else {
+ $data['realm'] = $temp[1];
+ }
+ $temp = null;
+
+ $ret = preg_match('/nonce="([^"]+)"/', $header, $temp);
+ if (!$ret || empty($temp[1])) {
+ return false;
+ }
+ if (!ctype_xdigit($temp[1])) {
+ return false;
+ } else {
+ $data['nonce'] = $temp[1];
+ }
+ $temp = null;
+
+ $ret = preg_match('/uri="([^"]+)"/', $header, $temp);
+ if (!$ret || empty($temp[1])) {
+ return false;
+ }
+ // Section 3.2.2.5 in RFC 2617 says the authenticating server must
+ // verify that the URI field in the Authorization header is for the
+ // same resource requested in the Request Line.
+ $rUri = @parse_url($this->_request->getRequestUri());
+ $cUri = @parse_url($temp[1]);
+ if (false === $rUri || false === $cUri) {
+ return false;
+ } else {
+ // Make sure the path portion of both URIs is the same
+ if ($rUri['path'] != $cUri['path']) {
+ return false;
+ }
+ // Section 3.2.2.5 seems to suggest that the value of the URI
+ // Authorization field should be made into an absolute URI if the
+ // Request URI is absolute, but it's vague, and that's a bunch of
+ // code I don't want to write right now.
+ $data['uri'] = $temp[1];
+ }
+ $temp = null;
+
+ $ret = preg_match('/response="([^"]+)"/', $header, $temp);
+ if (!$ret || empty($temp[1])) {
+ return false;
+ }
+ if (32 != strlen($temp[1]) || !ctype_xdigit($temp[1])) {
+ return false;
+ } else {
+ $data['response'] = $temp[1];
+ }
+ $temp = null;
+
+ // The spec says this should default to MD5 if omitted. OK, so how does
+ // that square with the algo we send out in the WWW-Authenticate header,
+ // if it can easily be overridden by the client?
+ $ret = preg_match('/algorithm="?(' . $this->_algo . ')"?/', $header, $temp);
+ if ($ret && !empty($temp[1])
+ && in_array($temp[1], $this->_supportedAlgos)) {
+ $data['algorithm'] = $temp[1];
+ } else {
+ $data['algorithm'] = 'MD5'; // = $this->_algo; ?
+ }
+ $temp = null;
+
+ // Not optional in this implementation
+ $ret = preg_match('/cnonce="([^"]+)"/', $header, $temp);
+ if (!$ret || empty($temp[1])) {
+ return false;
+ }
+ if (!ctype_print($temp[1])) {
+ return false;
+ } else {
+ $data['cnonce'] = $temp[1];
+ }
+ $temp = null;
+
+ // If the server sent an opaque value, the client must send it back
+ if ($this->_useOpaque) {
+ $ret = preg_match('/opaque="([^"]+)"/', $header, $temp);
+ if (!$ret || empty($temp[1])) {
+
+ // Big surprise: IE isn't RFC 2617-compliant.
+ if (false !== strpos($this->_request->getHeader('User-Agent'), 'MSIE')) {
+ $temp[1] = '';
+ $this->_ieNoOpaque = true;
+ } else {
+ return false;
+ }
+ }
+ // This implementation only sends MD5 hex strings in the opaque value
+ if (!$this->_ieNoOpaque &&
+ (32 != strlen($temp[1]) || !ctype_xdigit($temp[1]))) {
+ return false;
+ } else {
+ $data['opaque'] = $temp[1];
+ }
+ $temp = null;
+ }
+
+ // Not optional in this implementation, but must be one of the supported
+ // qop types
+ $ret = preg_match('/qop="?(' . implode('|', $this->_supportedQops) . ')"?/', $header, $temp);
+ if (!$ret || empty($temp[1])) {
+ return false;
+ }
+ if (!in_array($temp[1], $this->_supportedQops)) {
+ return false;
+ } else {
+ $data['qop'] = $temp[1];
+ }
+ $temp = null;
+
+ // Not optional in this implementation. The spec says this value
+ // shouldn't be a quoted string, but apparently some implementations
+ // quote it anyway. See ZF-1544.
+ $ret = preg_match('/nc="?([0-9A-Fa-f]{8})"?/', $header, $temp);
+ if (!$ret || empty($temp[1])) {
+ return false;
+ }
+ if (8 != strlen($temp[1]) || !ctype_xdigit($temp[1])) {
+ return false;
+ } else {
+ $data['nc'] = $temp[1];
+ }
+ $temp = null;
+
+ return $data;
+ }
+
+ /**
+ * Securely compare two strings for equality while avoided C level memcmp()
+ * optimisations capable of leaking timing information useful to an attacker
+ * attempting to iteratively guess the unknown string (e.g. password) being
+ * compared against.
+ *
+ * @param string $a
+ * @param string $b
+ * @return bool
+ */
+ protected function _secureStringCompare($a, $b)
+ {
+ if (strlen($a) !== strlen($b)) {
+ return false;
+ }
+ $result = 0;
+ for ($i = 0; $i < strlen($a); $i++) {
+ $result |= ord($a[$i]) ^ ord($b[$i]);
+ }
+ return $result == 0;
+ }
+}
diff --git a/lib/zend/Zend/Auth/Adapter/Http/Resolver/Exception.php b/lib/zend/Zend/Auth/Adapter/Http/Resolver/Exception.php
new file mode 100644
index 00000000000..e7e2a4e8262
--- /dev/null
+++ b/lib/zend/Zend/Auth/Adapter/Http/Resolver/Exception.php
@@ -0,0 +1,40 @@
+setFile($path);
+ }
+ }
+
+ /**
+ * Set the path to the credentials file
+ *
+ * @param string $path
+ * @throws Zend_Auth_Adapter_Http_Resolver_Exception
+ * @return Zend_Auth_Adapter_Http_Resolver_File Provides a fluent interface
+ */
+ public function setFile($path)
+ {
+ if (empty($path) || !is_readable($path)) {
+ /**
+ * @see Zend_Auth_Adapter_Http_Resolver_Exception
+ */
+ require_once 'Zend/Auth/Adapter/Http/Resolver/Exception.php';
+ throw new Zend_Auth_Adapter_Http_Resolver_Exception('Path not readable: ' . $path);
+ }
+ $this->_file = $path;
+
+ return $this;
+ }
+
+ /**
+ * Returns the path to the credentials file
+ *
+ * @return string
+ */
+ public function getFile()
+ {
+ return $this->_file;
+ }
+
+ /**
+ * Resolve credentials
+ *
+ * Only the first matching username/realm combination in the file is
+ * returned. If the file contains credentials for Digest authentication,
+ * the returned string is the password hash, or h(a1) from RFC 2617. The
+ * returned string is the plain-text password for Basic authentication.
+ *
+ * The expected format of the file is:
+ * username:realm:sharedSecret
+ *
+ * That is, each line consists of the user's username, the applicable
+ * authentication realm, and the password or hash, each delimited by
+ * colons.
+ *
+ * @param string $username Username
+ * @param string $realm Authentication Realm
+ * @throws Zend_Auth_Adapter_Http_Resolver_Exception
+ * @return string|false User's shared secret, if the user is found in the
+ * realm, false otherwise.
+ */
+ public function resolve($username, $realm)
+ {
+ if (empty($username)) {
+ /**
+ * @see Zend_Auth_Adapter_Http_Resolver_Exception
+ */
+ require_once 'Zend/Auth/Adapter/Http/Resolver/Exception.php';
+ throw new Zend_Auth_Adapter_Http_Resolver_Exception('Username is required');
+ } else if (!ctype_print($username) || strpos($username, ':') !== false) {
+ /**
+ * @see Zend_Auth_Adapter_Http_Resolver_Exception
+ */
+ require_once 'Zend/Auth/Adapter/Http/Resolver/Exception.php';
+ throw new Zend_Auth_Adapter_Http_Resolver_Exception('Username must consist only of printable characters, '
+ . 'excluding the colon');
+ }
+ if (empty($realm)) {
+ /**
+ * @see Zend_Auth_Adapter_Http_Resolver_Exception
+ */
+ require_once 'Zend/Auth/Adapter/Http/Resolver/Exception.php';
+ throw new Zend_Auth_Adapter_Http_Resolver_Exception('Realm is required');
+ } else if (!ctype_print($realm) || strpos($realm, ':') !== false) {
+ /**
+ * @see Zend_Auth_Adapter_Http_Resolver_Exception
+ */
+ require_once 'Zend/Auth/Adapter/Http/Resolver/Exception.php';
+ throw new Zend_Auth_Adapter_Http_Resolver_Exception('Realm must consist only of printable characters, '
+ . 'excluding the colon.');
+ }
+
+ // Open file, read through looking for matching credentials
+ $fp = @fopen($this->_file, 'r');
+ if (!$fp) {
+ /**
+ * @see Zend_Auth_Adapter_Http_Resolver_Exception
+ */
+ require_once 'Zend/Auth/Adapter/Http/Resolver/Exception.php';
+ throw new Zend_Auth_Adapter_Http_Resolver_Exception('Unable to open password file: ' . $this->_file);
+ }
+
+ // No real validation is done on the contents of the password file. The
+ // assumption is that we trust the administrators to keep it secure.
+ while (($line = fgetcsv($fp, 512, ':')) !== false) {
+ if ($line[0] == $username && $line[1] == $realm) {
+ $password = $line[2];
+ fclose($fp);
+ return $password;
+ }
+ }
+
+ fclose($fp);
+ return false;
+ }
+}
diff --git a/lib/zend/Zend/Auth/Adapter/Http/Resolver/Interface.php b/lib/zend/Zend/Auth/Adapter/Http/Resolver/Interface.php
new file mode 100644
index 00000000000..4326ee8202f
--- /dev/null
+++ b/lib/zend/Zend/Auth/Adapter/Http/Resolver/Interface.php
@@ -0,0 +1,47 @@
+ self::SUCCESS ) {
+ $code = 1;
+ }
+
+ $this->_code = $code;
+ $this->_identity = $identity;
+ $this->_messages = $messages;
+ }
+
+ /**
+ * Returns whether the result represents a successful authentication attempt
+ *
+ * @return boolean
+ */
+ public function isValid()
+ {
+ return ($this->_code > 0) ? true : false;
+ }
+
+ /**
+ * getCode() - Get the result code for this authentication attempt
+ *
+ * @return int
+ */
+ public function getCode()
+ {
+ return $this->_code;
+ }
+
+ /**
+ * Returns the identity used in the authentication attempt
+ *
+ * @return mixed
+ */
+ public function getIdentity()
+ {
+ return $this->_identity;
+ }
+
+ /**
+ * Returns an array of string reasons why the authentication attempt was unsuccessful
+ *
+ * If authentication was successful, this method returns an empty array.
+ *
+ * @return array
+ */
+ public function getMessages()
+ {
+ return $this->_messages;
+ }
+}
diff --git a/lib/zend/Zend/Auth/Storage/Exception.php b/lib/zend/Zend/Auth/Storage/Exception.php
new file mode 100644
index 00000000000..542b6708a79
--- /dev/null
+++ b/lib/zend/Zend/Auth/Storage/Exception.php
@@ -0,0 +1,38 @@
+_data);
+ }
+
+ /**
+ * Returns the contents of storage
+ * Behavior is undefined when storage is empty.
+ *
+ * @throws Zend_Auth_Storage_Exception If reading contents from storage is impossible
+ * @return mixed
+ */
+ public function read()
+ {
+ return $this->_data;
+ }
+
+ /**
+ * Writes $contents to storage
+ *
+ * @param mixed $contents
+ * @throws Zend_Auth_Storage_Exception If writing $contents to storage is impossible
+ * @return void
+ */
+ public function write($contents)
+ {
+ $this->_data = $contents;
+ }
+
+ /**
+ * Clears contents from storage
+ *
+ * @throws Zend_Auth_Storage_Exception If clearing contents from storage is impossible
+ * @return void
+ */
+ public function clear()
+ {
+ $this->_data = null;
+ }
+}
diff --git a/lib/zend/Zend/Auth/Storage/Session.php b/lib/zend/Zend/Auth/Storage/Session.php
new file mode 100644
index 00000000000..c3680f6faf7
--- /dev/null
+++ b/lib/zend/Zend/Auth/Storage/Session.php
@@ -0,0 +1,149 @@
+_namespace = $namespace;
+ $this->_member = $member;
+ $this->_session = new Zend_Session_Namespace($this->_namespace);
+ }
+
+ /**
+ * Returns the session namespace
+ *
+ * @return string
+ */
+ public function getNamespace()
+ {
+ return $this->_namespace;
+ }
+
+ /**
+ * Returns the name of the session object member
+ *
+ * @return string
+ */
+ public function getMember()
+ {
+ return $this->_member;
+ }
+
+ /**
+ * Defined by Zend_Auth_Storage_Interface
+ *
+ * @return boolean
+ */
+ public function isEmpty()
+ {
+ return !isset($this->_session->{$this->_member});
+ }
+
+ /**
+ * Defined by Zend_Auth_Storage_Interface
+ *
+ * @return mixed
+ */
+ public function read()
+ {
+ return $this->_session->{$this->_member};
+ }
+
+ /**
+ * Defined by Zend_Auth_Storage_Interface
+ *
+ * @param mixed $contents
+ * @return void
+ */
+ public function write($contents)
+ {
+ $this->_session->{$this->_member} = $contents;
+ }
+
+ /**
+ * Defined by Zend_Auth_Storage_Interface
+ *
+ * @return void
+ */
+ public function clear()
+ {
+ unset($this->_session->{$this->_member});
+ }
+}
diff --git a/lib/zend/Zend/Cache.php b/lib/zend/Zend/Cache.php
new file mode 100644
index 00000000000..dc818f30e57
--- /dev/null
+++ b/lib/zend/Zend/Cache.php
@@ -0,0 +1,250 @@
+setBackend($backendObject);
+ return $frontendObject;
+ }
+
+ /**
+ * Backend Constructor
+ *
+ * @param string $backend
+ * @param array $backendOptions
+ * @param boolean $customBackendNaming
+ * @param boolean $autoload
+ * @return Zend_Cache_Backend
+ */
+ public static function _makeBackend($backend, $backendOptions, $customBackendNaming = false, $autoload = false)
+ {
+ if (!$customBackendNaming) {
+ $backend = self::_normalizeName($backend);
+ }
+ if (in_array($backend, Zend_Cache::$standardBackends)) {
+ // we use a standard backend
+ $backendClass = 'Zend_Cache_Backend_' . $backend;
+ // security controls are explicit
+ require_once str_replace('_', DIRECTORY_SEPARATOR, $backendClass) . '.php';
+ } else {
+ // we use a custom backend
+ if (!preg_match('~^[\w\\\\]+$~D', $backend)) {
+ Zend_Cache::throwException("Invalid backend name [$backend]");
+ }
+ if (!$customBackendNaming) {
+ // we use this boolean to avoid an API break
+ $backendClass = 'Zend_Cache_Backend_' . $backend;
+ } else {
+ $backendClass = $backend;
+ }
+ if (!$autoload) {
+ $file = str_replace('_', DIRECTORY_SEPARATOR, $backendClass) . '.php';
+ if (!(self::_isReadable($file))) {
+ self::throwException("file $file not found in include_path");
+ }
+ require_once $file;
+ }
+ }
+ return new $backendClass($backendOptions);
+ }
+
+ /**
+ * Frontend Constructor
+ *
+ * @param string $frontend
+ * @param array $frontendOptions
+ * @param boolean $customFrontendNaming
+ * @param boolean $autoload
+ * @return Zend_Cache_Core|Zend_Cache_Frontend
+ */
+ public static function _makeFrontend($frontend, $frontendOptions = array(), $customFrontendNaming = false, $autoload = false)
+ {
+ if (!$customFrontendNaming) {
+ $frontend = self::_normalizeName($frontend);
+ }
+ if (in_array($frontend, self::$standardFrontends)) {
+ // we use a standard frontend
+ // For perfs reasons, with frontend == 'Core', we can interact with the Core itself
+ $frontendClass = 'Zend_Cache_' . ($frontend != 'Core' ? 'Frontend_' : '') . $frontend;
+ // security controls are explicit
+ require_once str_replace('_', DIRECTORY_SEPARATOR, $frontendClass) . '.php';
+ } else {
+ // we use a custom frontend
+ if (!preg_match('~^[\w\\\\]+$~D', $frontend)) {
+ Zend_Cache::throwException("Invalid frontend name [$frontend]");
+ }
+ if (!$customFrontendNaming) {
+ // we use this boolean to avoid an API break
+ $frontendClass = 'Zend_Cache_Frontend_' . $frontend;
+ } else {
+ $frontendClass = $frontend;
+ }
+ if (!$autoload) {
+ $file = str_replace('_', DIRECTORY_SEPARATOR, $frontendClass) . '.php';
+ if (!(self::_isReadable($file))) {
+ self::throwException("file $file not found in include_path");
+ }
+ require_once $file;
+ }
+ }
+ return new $frontendClass($frontendOptions);
+ }
+
+ /**
+ * Throw an exception
+ *
+ * Note : for perf reasons, the "load" of Zend/Cache/Exception is dynamic
+ * @param string $msg Message for the exception
+ * @throws Zend_Cache_Exception
+ */
+ public static function throwException($msg, Exception $e = null)
+ {
+ // For perfs reasons, we use this dynamic inclusion
+ require_once 'Zend/Cache/Exception.php';
+ throw new Zend_Cache_Exception($msg, 0, $e);
+ }
+
+ /**
+ * Normalize frontend and backend names to allow multiple words TitleCased
+ *
+ * @param string $name Name to normalize
+ * @return string
+ */
+ protected static function _normalizeName($name)
+ {
+ $name = ucfirst(strtolower($name));
+ $name = str_replace(array('-', '_', '.'), ' ', $name);
+ $name = ucwords($name);
+ $name = str_replace(' ', '', $name);
+ if (stripos($name, 'ZendServer') === 0) {
+ $name = 'ZendServer_' . substr($name, strlen('ZendServer'));
+ }
+
+ return $name;
+ }
+
+ /**
+ * Returns TRUE if the $filename is readable, or FALSE otherwise.
+ * This function uses the PHP include_path, where PHP's is_readable()
+ * does not.
+ *
+ * Note : this method comes from Zend_Loader (see #ZF-2891 for details)
+ *
+ * @param string $filename
+ * @return boolean
+ */
+ private static function _isReadable($filename)
+ {
+ if (!$fh = @fopen($filename, 'r', true)) {
+ return false;
+ }
+ @fclose($fh);
+ return true;
+ }
+
+}
diff --git a/lib/zend/Zend/Cache/Backend.php b/lib/zend/Zend/Cache/Backend.php
new file mode 100644
index 00000000000..83f1af5f121
--- /dev/null
+++ b/lib/zend/Zend/Cache/Backend.php
@@ -0,0 +1,288 @@
+ (int) lifetime :
+ * - Cache lifetime (in seconds)
+ * - If null, the cache is valid forever
+ *
+ * =====> (int) logging :
+ * - if set to true, a logging is activated throw Zend_Log
+ *
+ * @var array directives
+ */
+ protected $_directives = array(
+ 'lifetime' => 3600,
+ 'logging' => false,
+ 'logger' => null
+ );
+
+ /**
+ * Available options
+ *
+ * @var array available options
+ */
+ protected $_options = array();
+
+ /**
+ * Constructor
+ *
+ * @param array $options Associative array of options
+ */
+ public function __construct(array $options = array())
+ {
+ foreach ($options as $name => $value) {
+ $this->setOption($name, $value);
+ }
+ }
+
+ /**
+ * Set the frontend directives
+ *
+ * @param array $directives Assoc of directives
+ * @throws Zend_Cache_Exception
+ * @return void
+ */
+ public function setDirectives($directives)
+ {
+ if (!is_array($directives)) Zend_Cache::throwException('Directives parameter must be an array');
+ while (list($name, $value) = each($directives)) {
+ if (!is_string($name)) {
+ Zend_Cache::throwException("Incorrect option name : $name");
+ }
+ $name = strtolower($name);
+ if (array_key_exists($name, $this->_directives)) {
+ $this->_directives[$name] = $value;
+ }
+
+ }
+
+ $this->_loggerSanity();
+ }
+
+ /**
+ * Set an option
+ *
+ * @param string $name
+ * @param mixed $value
+ * @throws Zend_Cache_Exception
+ * @return void
+ */
+ public function setOption($name, $value)
+ {
+ if (!is_string($name)) {
+ Zend_Cache::throwException("Incorrect option name : $name");
+ }
+ $name = strtolower($name);
+ if (array_key_exists($name, $this->_options)) {
+ $this->_options[$name] = $value;
+ }
+ }
+
+ /**
+ * Returns an option
+ *
+ * @param string $name Optional, the options name to return
+ * @throws Zend_Cache_Exceptions
+ * @return mixed
+ */
+ public function getOption($name)
+ {
+ $name = strtolower($name);
+
+ if (array_key_exists($name, $this->_options)) {
+ return $this->_options[$name];
+ }
+
+ if (array_key_exists($name, $this->_directives)) {
+ return $this->_directives[$name];
+ }
+
+ Zend_Cache::throwException("Incorrect option name : {$name}");
+ }
+
+ /**
+ * Get the life time
+ *
+ * if $specificLifetime is not false, the given specific life time is used
+ * else, the global lifetime is used
+ *
+ * @param int $specificLifetime
+ * @return int Cache life time
+ */
+ public function getLifetime($specificLifetime)
+ {
+ if ($specificLifetime === false) {
+ return $this->_directives['lifetime'];
+ }
+ return $specificLifetime;
+ }
+
+ /**
+ * Return true if the automatic cleaning is available for the backend
+ *
+ * DEPRECATED : use getCapabilities() instead
+ *
+ * @deprecated
+ * @return boolean
+ */
+ public function isAutomaticCleaningAvailable()
+ {
+ return true;
+ }
+
+ /**
+ * Determine system TMP directory and detect if we have read access
+ *
+ * inspired from Zend_File_Transfer_Adapter_Abstract
+ *
+ * @return string
+ * @throws Zend_Cache_Exception if unable to determine directory
+ */
+ public function getTmpDir()
+ {
+ $tmpdir = array();
+ foreach (array($_ENV, $_SERVER) as $tab) {
+ foreach (array('TMPDIR', 'TEMP', 'TMP', 'windir', 'SystemRoot') as $key) {
+ if (isset($tab[$key]) && is_string($tab[$key])) {
+ if (($key == 'windir') or ($key == 'SystemRoot')) {
+ $dir = realpath($tab[$key] . '\\temp');
+ } else {
+ $dir = realpath($tab[$key]);
+ }
+ if ($this->_isGoodTmpDir($dir)) {
+ return $dir;
+ }
+ }
+ }
+ }
+ $upload = ini_get('upload_tmp_dir');
+ if ($upload) {
+ $dir = realpath($upload);
+ if ($this->_isGoodTmpDir($dir)) {
+ return $dir;
+ }
+ }
+ if (function_exists('sys_get_temp_dir')) {
+ $dir = sys_get_temp_dir();
+ if ($this->_isGoodTmpDir($dir)) {
+ return $dir;
+ }
+ }
+ // Attemp to detect by creating a temporary file
+ $tempFile = tempnam(md5(uniqid(rand(), TRUE)), '');
+ if ($tempFile) {
+ $dir = realpath(dirname($tempFile));
+ unlink($tempFile);
+ if ($this->_isGoodTmpDir($dir)) {
+ return $dir;
+ }
+ }
+ if ($this->_isGoodTmpDir('/tmp')) {
+ return '/tmp';
+ }
+ if ($this->_isGoodTmpDir('\\temp')) {
+ return '\\temp';
+ }
+ Zend_Cache::throwException('Could not determine temp directory, please specify a cache_dir manually');
+ }
+
+ /**
+ * Verify if the given temporary directory is readable and writable
+ *
+ * @param string $dir temporary directory
+ * @return boolean true if the directory is ok
+ */
+ protected function _isGoodTmpDir($dir)
+ {
+ if (is_readable($dir)) {
+ if (is_writable($dir)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Make sure if we enable logging that the Zend_Log class
+ * is available.
+ * Create a default log object if none is set.
+ *
+ * @throws Zend_Cache_Exception
+ * @return void
+ */
+ protected function _loggerSanity()
+ {
+ if (!isset($this->_directives['logging']) || !$this->_directives['logging']) {
+ return;
+ }
+
+ if (isset($this->_directives['logger'])) {
+ if ($this->_directives['logger'] instanceof Zend_Log) {
+ return;
+ }
+ Zend_Cache::throwException('Logger object is not an instance of Zend_Log class.');
+ }
+
+ // Create a default logger to the standard output stream
+ require_once 'Zend/Log.php';
+ require_once 'Zend/Log/Writer/Stream.php';
+ require_once 'Zend/Log/Filter/Priority.php';
+ $logger = new Zend_Log(new Zend_Log_Writer_Stream('php://output'));
+ $logger->addFilter(new Zend_Log_Filter_Priority(Zend_Log::WARN, '<='));
+ $this->_directives['logger'] = $logger;
+ }
+
+ /**
+ * Log a message at the WARN (4) priority.
+ *
+ * @param string $message
+ * @param int $priority
+ * @return void
+ */
+ protected function _log($message, $priority = 4)
+ {
+ if (!$this->_directives['logging']) {
+ return;
+ }
+
+ if (!isset($this->_directives['logger'])) {
+ Zend_Cache::throwException('Logging is enabled but logger is not set.');
+ }
+ $logger = $this->_directives['logger'];
+ if (!$logger instanceof Zend_Log) {
+ Zend_Cache::throwException('Logger object is not an instance of Zend_Log class.');
+ }
+ $logger->log($message, $priority);
+ }
+}
diff --git a/lib/zend/Zend/Cache/Backend/Apc.php b/lib/zend/Zend/Cache/Backend/Apc.php
new file mode 100644
index 00000000000..5a09becdcfd
--- /dev/null
+++ b/lib/zend/Zend/Cache/Backend/Apc.php
@@ -0,0 +1,355 @@
+ infinite lifetime)
+ * @return boolean true if no problem
+ */
+ public function save($data, $id, $tags = array(), $specificLifetime = false)
+ {
+ $lifetime = $this->getLifetime($specificLifetime);
+ $result = apc_store($id, array($data, time(), $lifetime), $lifetime);
+ if (count($tags) > 0) {
+ $this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_APC_BACKEND);
+ }
+ return $result;
+ }
+
+ /**
+ * Remove a cache record
+ *
+ * @param string $id cache id
+ * @return boolean true if no problem
+ */
+ public function remove($id)
+ {
+ return apc_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 apc_clear_cache('user');
+ break;
+ case Zend_Cache::CLEANING_MODE_OLD:
+ $this->_log("Zend_Cache_Backend_Apc::clean() : CLEANING_MODE_OLD is unsupported by the Apc 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_APC_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 = apc_sma_info(true);
+ $memSize = $mem['num_seg'] * $mem['seg_size'];
+ $memAvailable= $mem['avail_mem'];
+ $memUsed = $memSize - $memAvailable;
+ if ($memSize == 0) {
+ Zend_Cache::throwException('can\'t get apc 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_APC_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_APC_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_APC_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_APC_BACKEND);
+ return array();
+ }
+
+ /**
+ * Return an array of stored cache ids
+ *
+ * @return array array of stored cache ids (string)
+ */
+ public function getIds()
+ {
+ $ids = array();
+ $iterator = new APCIterator('user', null, APC_ITER_KEY);
+ foreach ($iterator as $item) {
+ $ids[] = $item['key'];
+ }
+
+ return $ids;
+ }
+
+ /**
+ * 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 = apc_fetch($id);
+ if (is_array($tmp)) {
+ $data = $tmp[0];
+ $mtime = $tmp[1];
+ if (!isset($tmp[2])) {
+ // because this record is only with 1.7 release
+ // if old cache records are still there...
+ 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 = apc_fetch($id);
+ if (is_array($tmp)) {
+ $data = $tmp[0];
+ $mtime = $tmp[1];
+ if (!isset($tmp[2])) {
+ // because this record is only with 1.7 release
+ // if old cache records are still there...
+ return false;
+ }
+ $lifetime = $tmp[2];
+ $newLifetime = $lifetime - (time() - $mtime) + $extraLifetime;
+ if ($newLifetime <=0) {
+ return false;
+ }
+ apc_store($id, array($data, time(), $newLifetime), $newLifetime);
+ return true;
+ }
+ 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
+ );
+ }
+
+}
diff --git a/lib/zend/Zend/Cache/Backend/BlackHole.php b/lib/zend/Zend/Cache/Backend/BlackHole.php
new file mode 100644
index 00000000000..0fe1c9d0525
--- /dev/null
+++ b/lib/zend/Zend/Cache/Backend/BlackHole.php
@@ -0,0 +1,250 @@
+ infinite lifetime)
+ * @return boolean true if no problem
+ */
+ public function save($data, $id, $tags = array(), $specificLifetime = false)
+ {
+ return true;
+ }
+
+ /**
+ * Remove a cache record
+ *
+ * @param string $id cache id
+ * @return boolean true if no problem
+ */
+ public function remove($id)
+ {
+ return true;
+ }
+
+ /**
+ * Clean some cache records
+ *
+ * Available modes are :
+ * 'all' (default) => remove all cache entries ($tags is not used)
+ * 'old' => remove too old cache entries ($tags is not used)
+ * 'matchingTag' => remove cache entries matching all given tags
+ * ($tags can be an array of strings or a single string)
+ * 'notMatchingTag' => remove cache entries not matching one of the given tags
+ * ($tags can be an array of strings or a single string)
+ * 'matchingAnyTag' => remove cache entries matching any given tags
+ * ($tags can be an array of strings or a single string)
+ *
+ * @param string $mode clean mode
+ * @param tags array $tags array of tags
+ * @return boolean true if no problem
+ */
+ public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array())
+ {
+ return true;
+ }
+
+ /**
+ * Return an array of stored cache ids
+ *
+ * @return array array of stored cache ids (string)
+ */
+ public function getIds()
+ {
+ return array();
+ }
+
+ /**
+ * Return an array of stored tags
+ *
+ * @return array array of stored tags (string)
+ */
+ public function getTags()
+ {
+ 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())
+ {
+ 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())
+ {
+ 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())
+ {
+ return array();
+ }
+
+ /**
+ * Return the filling percentage of the backend storage
+ *
+ * @return int integer between 0 and 100
+ * @throws Zend_Cache_Exception
+ */
+ public function getFillingPercentage()
+ {
+ return 0;
+ }
+
+ /**
+ * 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)
+ {
+ 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)
+ {
+ 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' => true,
+ 'tags' => true,
+ 'expired_read' => true,
+ 'priority' => true,
+ 'infinite_lifetime' => true,
+ 'get_list' => true,
+ );
+ }
+
+ /**
+ * PUBLIC METHOD FOR UNIT TESTING ONLY !
+ *
+ * Force a cache record to expire
+ *
+ * @param string $id cache id
+ */
+ public function ___expire($id)
+ {
+ }
+}
diff --git a/lib/zend/Zend/Cache/Backend/ExtendedInterface.php b/lib/zend/Zend/Cache/Backend/ExtendedInterface.php
new file mode 100644
index 00000000000..0dd8bdf414c
--- /dev/null
+++ b/lib/zend/Zend/Cache/Backend/ExtendedInterface.php
@@ -0,0 +1,126 @@
+ (string) cache_dir :
+ * - Directory where to put the cache files
+ *
+ * =====> (boolean) file_locking :
+ * - Enable / disable file_locking
+ * - Can avoid cache corruption under bad circumstances but it doesn't work on multithread
+ * webservers and on NFS filesystems for example
+ *
+ * =====> (boolean) read_control :
+ * - Enable / disable read control
+ * - If enabled, a control key is embeded in cache file and this key is compared with the one
+ * calculated after the reading.
+ *
+ * =====> (string) read_control_type :
+ * - Type of read control (only if read control is enabled). Available values are :
+ * 'md5' for a md5 hash control (best but slowest)
+ * 'crc32' for a crc32 hash control (lightly less safe but faster, better choice)
+ * 'adler32' for an adler32 hash control (excellent choice too, faster than crc32)
+ * 'strlen' for a length only test (fastest)
+ *
+ * =====> (int) hashed_directory_level :
+ * - Hashed directory level
+ * - Set the hashed directory structure level. 0 means "no hashed directory
+ * structure", 1 means "one level of directory", 2 means "two levels"...
+ * This option can speed up the cache only when you have many thousands of
+ * cache file. Only specific benchs can help you to choose the perfect value
+ * for you. Maybe, 1 or 2 is a good start.
+ *
+ * =====> (int) hashed_directory_umask :
+ * - deprecated
+ * - Permissions for hashed directory structure
+ *
+ * =====> (int) hashed_directory_perm :
+ * - Permissions for hashed directory structure
+ *
+ * =====> (string) file_name_prefix :
+ * - prefix for cache files
+ * - be really carefull with this option because a too generic value in a system cache dir
+ * (like /tmp) can cause disasters when cleaning the cache
+ *
+ * =====> (int) cache_file_umask :
+ * - deprecated
+ * - Permissions for cache files
+ *
+ * =====> (int) cache_file_perm :
+ * - Permissions for cache files
+ *
+ * =====> (int) metatadatas_array_max_size :
+ * - max size for the metadatas array (don't change this value unless you
+ * know what you are doing)
+ *
+ * @var array available options
+ */
+ protected $_options = array(
+ 'cache_dir' => null,
+ 'file_locking' => true,
+ 'read_control' => true,
+ 'read_control_type' => 'crc32',
+ 'hashed_directory_level' => 0,
+ 'hashed_directory_perm' => 0700,
+ 'file_name_prefix' => 'zend_cache',
+ 'cache_file_perm' => 0600,
+ 'metadatas_array_max_size' => 100
+ );
+
+ /**
+ * Array of metadatas (each item is an associative array)
+ *
+ * @var array
+ */
+ protected $_metadatasArray = array();
+
+
+ /**
+ * Constructor
+ *
+ * @param array $options associative array of options
+ * @throws Zend_Cache_Exception
+ */
+ public function __construct(array $options = array())
+ {
+ parent::__construct($options);
+ if ($this->_options['cache_dir'] !== null) { // particular case for this option
+ $this->setCacheDir($this->_options['cache_dir']);
+ } else {
+ $this->setCacheDir(self::getTmpDir() . DIRECTORY_SEPARATOR, false);
+ }
+ if (isset($this->_options['file_name_prefix'])) { // particular case for this option
+ if (!preg_match('~^[a-zA-Z0-9_]+$~D', $this->_options['file_name_prefix'])) {
+ Zend_Cache::throwException('Invalid file_name_prefix : must use only [a-zA-Z0-9_]');
+ }
+ }
+ if ($this->_options['metadatas_array_max_size'] < 10) {
+ Zend_Cache::throwException('Invalid metadatas_array_max_size, must be > 10');
+ }
+
+ if (isset($options['hashed_directory_umask'])) {
+ // See #ZF-12047
+ trigger_error("'hashed_directory_umask' is deprecated -> please use 'hashed_directory_perm' instead", E_USER_NOTICE);
+ if (!isset($options['hashed_directory_perm'])) {
+ $options['hashed_directory_perm'] = $options['hashed_directory_umask'];
+ }
+ }
+ if (isset($options['hashed_directory_perm']) && is_string($options['hashed_directory_perm'])) {
+ // See #ZF-4422
+ $this->_options['hashed_directory_perm'] = octdec($this->_options['hashed_directory_perm']);
+ }
+
+ if (isset($options['cache_file_umask'])) {
+ // See #ZF-12047
+ trigger_error("'cache_file_umask' is deprecated -> please use 'cache_file_perm' instead", E_USER_NOTICE);
+ if (!isset($options['cache_file_perm'])) {
+ $options['cache_file_perm'] = $options['cache_file_umask'];
+ }
+ }
+ if (isset($options['cache_file_perm']) && is_string($options['cache_file_perm'])) {
+ // See #ZF-4422
+ $this->_options['cache_file_perm'] = octdec($this->_options['cache_file_perm']);
+ }
+ }
+
+ /**
+ * Set the cache_dir (particular case of setOption() method)
+ *
+ * @param string $value
+ * @param boolean $trailingSeparator If true, add a trailing separator is necessary
+ * @throws Zend_Cache_Exception
+ * @return void
+ */
+ public function setCacheDir($value, $trailingSeparator = true)
+ {
+ if (!is_dir($value)) {
+ Zend_Cache::throwException(sprintf('cache_dir "%s" must be a directory', $value));
+ }
+ if (!is_writable($value)) {
+ Zend_Cache::throwException(sprintf('cache_dir "%s" is not writable', $value));
+ }
+ if ($trailingSeparator) {
+ // add a trailing DIRECTORY_SEPARATOR if necessary
+ $value = rtrim(realpath($value), '\\/') . DIRECTORY_SEPARATOR;
+ }
+ $this->_options['cache_dir'] = $value;
+ }
+
+ /**
+ * Test if a cache is available for the given id and (if yes) return it (false else)
+ *
+ * @param string $id cache id
+ * @param boolean $doNotTestCacheValidity if set to true, the cache validity won't be tested
+ * @return string|false cached datas
+ */
+ public function load($id, $doNotTestCacheValidity = false)
+ {
+ if (!($this->_test($id, $doNotTestCacheValidity))) {
+ // The cache is not hit !
+ return false;
+ }
+ $metadatas = $this->_getMetadatas($id);
+ $file = $this->_file($id);
+ $data = $this->_fileGetContents($file);
+ if ($this->_options['read_control']) {
+ $hashData = $this->_hash($data, $this->_options['read_control_type']);
+ $hashControl = $metadatas['hash'];
+ if ($hashData != $hashControl) {
+ // Problem detected by the read control !
+ $this->_log('Zend_Cache_Backend_File::load() / read_control : stored hash and computed hash do not match');
+ $this->remove($id);
+ return false;
+ }
+ }
+ return $data;
+ }
+
+ /**
+ * 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)
+ {
+ clearstatcache();
+ return $this->_test($id, 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 boolean|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)
+ {
+ clearstatcache();
+ $file = $this->_file($id);
+ $path = $this->_path($id);
+ if ($this->_options['hashed_directory_level'] > 0) {
+ if (!is_writable($path)) {
+ // maybe, we just have to build the directory structure
+ $this->_recursiveMkdirAndChmod($id);
+ }
+ if (!is_writable($path)) {
+ return false;
+ }
+ }
+ if ($this->_options['read_control']) {
+ $hash = $this->_hash($data, $this->_options['read_control_type']);
+ } else {
+ $hash = '';
+ }
+ $metadatas = array(
+ 'hash' => $hash,
+ 'mtime' => time(),
+ 'expire' => $this->_expireTime($this->getLifetime($specificLifetime)),
+ 'tags' => $tags
+ );
+ $res = $this->_setMetadatas($id, $metadatas);
+ if (!$res) {
+ $this->_log('Zend_Cache_Backend_File::save() / error on saving metadata');
+ return false;
+ }
+ $res = $this->_filePutContents($file, $data);
+ return $res;
+ }
+
+ /**
+ * Remove a cache record
+ *
+ * @param string $id cache id
+ * @return boolean true if no problem
+ */
+ public function remove($id)
+ {
+ $file = $this->_file($id);
+ $boolRemove = $this->_remove($file);
+ $boolMetadata = $this->_delMetadatas($id);
+ return $boolMetadata && $boolRemove;
+ }
+
+ /**
+ * Clean some cache records
+ *
+ * Available modes are :
+ *
+ * Zend_Cache::CLEANING_MODE_ALL (default) => remove all cache entries ($tags is not used)
+ * Zend_Cache::CLEANING_MODE_OLD => remove too old cache entries ($tags is not used)
+ * Zend_Cache::CLEANING_MODE_MATCHING_TAG => remove cache entries matching all given tags
+ * ($tags can be an array of strings or a single string)
+ * Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG => remove cache entries not {matching one of the given tags}
+ * ($tags can be an array of strings or a single string)
+ * Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG => remove cache entries matching any given tags
+ * ($tags can be an array of strings or a single string)
+ *
+ * @param string $mode clean mode
+ * @param array $tags array of tags
+ * @return boolean true if no problem
+ */
+ public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array())
+ {
+ // We use this protected method to hide the recursive stuff
+ clearstatcache();
+ return $this->_clean($this->_options['cache_dir'], $mode, $tags);
+ }
+
+ /**
+ * Return an array of stored cache ids
+ *
+ * @return array array of stored cache ids (string)
+ */
+ public function getIds()
+ {
+ return $this->_get($this->_options['cache_dir'], 'ids', array());
+ }
+
+ /**
+ * Return an array of stored tags
+ *
+ * @return array array of stored tags (string)
+ */
+ public function getTags()
+ {
+ return $this->_get($this->_options['cache_dir'], 'tags', 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())
+ {
+ return $this->_get($this->_options['cache_dir'], 'matching', $tags);
+ }
+
+ /**
+ * 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())
+ {
+ return $this->_get($this->_options['cache_dir'], 'notMatching', $tags);
+ }
+
+ /**
+ * 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())
+ {
+ return $this->_get($this->_options['cache_dir'], 'matchingAny', $tags);
+ }
+
+ /**
+ * Return the filling percentage of the backend storage
+ *
+ * @throws Zend_Cache_Exception
+ * @return int integer between 0 and 100
+ */
+ public function getFillingPercentage()
+ {
+ $free = disk_free_space($this->_options['cache_dir']);
+ $total = disk_total_space($this->_options['cache_dir']);
+ if ($total == 0) {
+ Zend_Cache::throwException('can\'t get disk_total_space');
+ } else {
+ if ($free >= $total) {
+ return 100;
+ }
+ return ((int) (100. * ($total - $free) / $total));
+ }
+ }
+
+ /**
+ * 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)
+ {
+ $metadatas = $this->_getMetadatas($id);
+ if (!$metadatas) {
+ return false;
+ }
+ if (time() > $metadatas['expire']) {
+ return false;
+ }
+ return array(
+ 'expire' => $metadatas['expire'],
+ 'tags' => $metadatas['tags'],
+ 'mtime' => $metadatas['mtime']
+ );
+ }
+
+ /**
+ * 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)
+ {
+ $metadatas = $this->_getMetadatas($id);
+ if (!$metadatas) {
+ return false;
+ }
+ if (time() > $metadatas['expire']) {
+ return false;
+ }
+ $newMetadatas = array(
+ 'hash' => $metadatas['hash'],
+ 'mtime' => time(),
+ 'expire' => $metadatas['expire'] + $extraLifetime,
+ 'tags' => $metadatas['tags']
+ );
+ $res = $this->_setMetadatas($id, $newMetadatas);
+ if (!$res) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * 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' => true,
+ 'tags' => true,
+ 'expired_read' => true,
+ 'priority' => false,
+ 'infinite_lifetime' => true,
+ 'get_list' => true
+ );
+ }
+
+ /**
+ * PUBLIC METHOD FOR UNIT TESTING ONLY !
+ *
+ * Force a cache record to expire
+ *
+ * @param string $id cache id
+ */
+ public function ___expire($id)
+ {
+ $metadatas = $this->_getMetadatas($id);
+ if ($metadatas) {
+ $metadatas['expire'] = 1;
+ $this->_setMetadatas($id, $metadatas);
+ }
+ }
+
+ /**
+ * Get a metadatas record
+ *
+ * @param string $id Cache id
+ * @return array|false Associative array of metadatas
+ */
+ protected function _getMetadatas($id)
+ {
+ if (isset($this->_metadatasArray[$id])) {
+ return $this->_metadatasArray[$id];
+ } else {
+ $metadatas = $this->_loadMetadatas($id);
+ if (!$metadatas) {
+ return false;
+ }
+ $this->_setMetadatas($id, $metadatas, false);
+ return $metadatas;
+ }
+ }
+
+ /**
+ * Set a metadatas record
+ *
+ * @param string $id Cache id
+ * @param array $metadatas Associative array of metadatas
+ * @param boolean $save optional pass false to disable saving to file
+ * @return boolean True if no problem
+ */
+ protected function _setMetadatas($id, $metadatas, $save = true)
+ {
+ if (count($this->_metadatasArray) >= $this->_options['metadatas_array_max_size']) {
+ $n = (int) ($this->_options['metadatas_array_max_size'] / 10);
+ $this->_metadatasArray = array_slice($this->_metadatasArray, $n);
+ }
+ if ($save) {
+ $result = $this->_saveMetadatas($id, $metadatas);
+ if (!$result) {
+ return false;
+ }
+ }
+ $this->_metadatasArray[$id] = $metadatas;
+ return true;
+ }
+
+ /**
+ * Drop a metadata record
+ *
+ * @param string $id Cache id
+ * @return boolean True if no problem
+ */
+ protected function _delMetadatas($id)
+ {
+ if (isset($this->_metadatasArray[$id])) {
+ unset($this->_metadatasArray[$id]);
+ }
+ $file = $this->_metadatasFile($id);
+ return $this->_remove($file);
+ }
+
+ /**
+ * Clear the metadatas array
+ *
+ * @return void
+ */
+ protected function _cleanMetadatas()
+ {
+ $this->_metadatasArray = array();
+ }
+
+ /**
+ * Load metadatas from disk
+ *
+ * @param string $id Cache id
+ * @return array|false Metadatas associative array
+ */
+ protected function _loadMetadatas($id)
+ {
+ $file = $this->_metadatasFile($id);
+ $result = $this->_fileGetContents($file);
+ if (!$result) {
+ return false;
+ }
+ $tmp = @unserialize($result);
+ return $tmp;
+ }
+
+ /**
+ * Save metadatas to disk
+ *
+ * @param string $id Cache id
+ * @param array $metadatas Associative array
+ * @return boolean True if no problem
+ */
+ protected function _saveMetadatas($id, $metadatas)
+ {
+ $file = $this->_metadatasFile($id);
+ $result = $this->_filePutContents($file, serialize($metadatas));
+ if (!$result) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Make and return a file name (with path) for metadatas
+ *
+ * @param string $id Cache id
+ * @return string Metadatas file name (with path)
+ */
+ protected function _metadatasFile($id)
+ {
+ $path = $this->_path($id);
+ $fileName = $this->_idToFileName('internal-metadatas---' . $id);
+ return $path . $fileName;
+ }
+
+ /**
+ * Check if the given filename is a metadatas one
+ *
+ * @param string $fileName File name
+ * @return boolean True if it's a metadatas one
+ */
+ protected function _isMetadatasFile($fileName)
+ {
+ $id = $this->_fileNameToId($fileName);
+ if (substr($id, 0, 21) == 'internal-metadatas---') {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Remove a file
+ *
+ * If we can't remove the file (because of locks or any problem), we will touch
+ * the file to invalidate it
+ *
+ * @param string $file Complete file path
+ * @return boolean True if ok
+ */
+ protected function _remove($file)
+ {
+ if (!is_file($file)) {
+ return false;
+ }
+ if (!@unlink($file)) {
+ # we can't remove the file (because of locks or any problem)
+ $this->_log("Zend_Cache_Backend_File::_remove() : we can't remove $file");
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Clean some cache records (protected method used for recursive stuff)
+ *
+ * Available modes are :
+ * Zend_Cache::CLEANING_MODE_ALL (default) => remove all cache entries ($tags is not used)
+ * Zend_Cache::CLEANING_MODE_OLD => remove too old cache entries ($tags is not used)
+ * Zend_Cache::CLEANING_MODE_MATCHING_TAG => remove cache entries matching all given tags
+ * ($tags can be an array of strings or a single string)
+ * Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG => remove cache entries not {matching one of the given tags}
+ * ($tags can be an array of strings or a single string)
+ * Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG => remove cache entries matching any given tags
+ * ($tags can be an array of strings or a single string)
+ *
+ * @param string $dir Directory to clean
+ * @param string $mode Clean mode
+ * @param array $tags Array of tags
+ * @throws Zend_Cache_Exception
+ * @return boolean True if no problem
+ */
+ protected function _clean($dir, $mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array())
+ {
+ if (!is_dir($dir)) {
+ return false;
+ }
+ $result = true;
+ $prefix = $this->_options['file_name_prefix'];
+ $glob = @glob($dir . $prefix . '--*');
+ if ($glob === false) {
+ // On some systems it is impossible to distinguish between empty match and an error.
+ return true;
+ }
+ $metadataFiles = array();
+ foreach ($glob as $file) {
+ if (is_file($file)) {
+ $fileName = basename($file);
+ if ($this->_isMetadatasFile($fileName)) {
+ // In CLEANING_MODE_ALL, we drop anything, even remainings old metadatas files.
+ // To do that, we need to save the list of the metadata files first.
+ if ($mode == Zend_Cache::CLEANING_MODE_ALL) {
+ $metadataFiles[] = $file;
+ }
+ continue;
+ }
+ $id = $this->_fileNameToId($fileName);
+ $metadatas = $this->_getMetadatas($id);
+ if ($metadatas === FALSE) {
+ $metadatas = array('expire' => 1, 'tags' => array());
+ }
+ switch ($mode) {
+ case Zend_Cache::CLEANING_MODE_ALL:
+ $result = $result && $this->remove($id);
+ break;
+ case Zend_Cache::CLEANING_MODE_OLD:
+ if (time() > $metadatas['expire']) {
+ $result = $this->remove($id) && $result;
+ }
+ break;
+ case Zend_Cache::CLEANING_MODE_MATCHING_TAG:
+ $matching = true;
+ foreach ($tags as $tag) {
+ if (!in_array($tag, $metadatas['tags'])) {
+ $matching = false;
+ break;
+ }
+ }
+ if ($matching) {
+ $result = $this->remove($id) && $result;
+ }
+ break;
+ case Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG:
+ $matching = false;
+ foreach ($tags as $tag) {
+ if (in_array($tag, $metadatas['tags'])) {
+ $matching = true;
+ break;
+ }
+ }
+ if (!$matching) {
+ $result = $this->remove($id) && $result;
+ }
+ break;
+ case Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG:
+ $matching = false;
+ foreach ($tags as $tag) {
+ if (in_array($tag, $metadatas['tags'])) {
+ $matching = true;
+ break;
+ }
+ }
+ if ($matching) {
+ $result = $this->remove($id) && $result;
+ }
+ break;
+ default:
+ Zend_Cache::throwException('Invalid mode for clean() method');
+ break;
+ }
+ }
+ if ((is_dir($file)) and ($this->_options['hashed_directory_level']>0)) {
+ // Recursive call
+ $result = $this->_clean($file . DIRECTORY_SEPARATOR, $mode, $tags) && $result;
+ if ($mode == Zend_Cache::CLEANING_MODE_ALL) {
+ // we try to drop the structure too
+ @rmdir($file);
+ }
+ }
+ }
+
+ // cycle through metadataFiles and delete orphaned ones
+ foreach ($metadataFiles as $file) {
+ if (file_exists($file)) {
+ $result = $this->_remove($file) && $result;
+ }
+ }
+
+ return $result;
+ }
+
+ protected function _get($dir, $mode, $tags = array())
+ {
+ if (!is_dir($dir)) {
+ return false;
+ }
+ $result = array();
+ $prefix = $this->_options['file_name_prefix'];
+ $glob = @glob($dir . $prefix . '--*');
+ if ($glob === false) {
+ // On some systems it is impossible to distinguish between empty match and an error.
+ return array();
+ }
+ foreach ($glob as $file) {
+ if (is_file($file)) {
+ $fileName = basename($file);
+ $id = $this->_fileNameToId($fileName);
+ $metadatas = $this->_getMetadatas($id);
+ if ($metadatas === FALSE) {
+ continue;
+ }
+ if (time() > $metadatas['expire']) {
+ continue;
+ }
+ switch ($mode) {
+ case 'ids':
+ $result[] = $id;
+ break;
+ case 'tags':
+ $result = array_unique(array_merge($result, $metadatas['tags']));
+ break;
+ case 'matching':
+ $matching = true;
+ foreach ($tags as $tag) {
+ if (!in_array($tag, $metadatas['tags'])) {
+ $matching = false;
+ break;
+ }
+ }
+ if ($matching) {
+ $result[] = $id;
+ }
+ break;
+ case 'notMatching':
+ $matching = false;
+ foreach ($tags as $tag) {
+ if (in_array($tag, $metadatas['tags'])) {
+ $matching = true;
+ break;
+ }
+ }
+ if (!$matching) {
+ $result[] = $id;
+ }
+ break;
+ case 'matchingAny':
+ $matching = false;
+ foreach ($tags as $tag) {
+ if (in_array($tag, $metadatas['tags'])) {
+ $matching = true;
+ break;
+ }
+ }
+ if ($matching) {
+ $result[] = $id;
+ }
+ break;
+ default:
+ Zend_Cache::throwException('Invalid mode for _get() method');
+ break;
+ }
+ }
+ if ((is_dir($file)) and ($this->_options['hashed_directory_level']>0)) {
+ // Recursive call
+ $recursiveRs = $this->_get($file . DIRECTORY_SEPARATOR, $mode, $tags);
+ if ($recursiveRs === false) {
+ $this->_log('Zend_Cache_Backend_File::_get() / recursive call : can\'t list entries of "'.$file.'"');
+ } else {
+ $result = array_unique(array_merge($result, $recursiveRs));
+ }
+ }
+ }
+ return array_unique($result);
+ }
+
+ /**
+ * Compute & return the expire time
+ *
+ * @param int $lifetime
+ * @return int expire time (unix timestamp)
+ */
+ protected function _expireTime($lifetime)
+ {
+ if ($lifetime === null) {
+ return 9999999999;
+ }
+ return time() + $lifetime;
+ }
+
+ /**
+ * Make a control key with the string containing datas
+ *
+ * @param string $data Data
+ * @param string $controlType Type of control 'md5', 'crc32' or 'strlen'
+ * @throws Zend_Cache_Exception
+ * @return string Control key
+ */
+ protected function _hash($data, $controlType)
+ {
+ switch ($controlType) {
+ case 'md5':
+ return md5($data);
+ case 'crc32':
+ return crc32($data);
+ case 'strlen':
+ return strlen($data);
+ case 'adler32':
+ return hash('adler32', $data);
+ default:
+ Zend_Cache::throwException("Incorrect hash function : $controlType");
+ }
+ }
+
+ /**
+ * Transform a cache id into a file name and return it
+ *
+ * @param string $id Cache id
+ * @return string File name
+ */
+ protected function _idToFileName($id)
+ {
+ $prefix = $this->_options['file_name_prefix'];
+ $result = $prefix . '---' . $id;
+ return $result;
+ }
+
+ /**
+ * Make and return a file name (with path)
+ *
+ * @param string $id Cache id
+ * @return string File name (with path)
+ */
+ protected function _file($id)
+ {
+ $path = $this->_path($id);
+ $fileName = $this->_idToFileName($id);
+ return $path . $fileName;
+ }
+
+ /**
+ * Return the complete directory path of a filename (including hashedDirectoryStructure)
+ *
+ * @param string $id Cache id
+ * @param boolean $parts if true, returns array of directory parts instead of single string
+ * @return string Complete directory path
+ */
+ protected function _path($id, $parts = false)
+ {
+ $partsArray = array();
+ $root = $this->_options['cache_dir'];
+ $prefix = $this->_options['file_name_prefix'];
+ if ($this->_options['hashed_directory_level']>0) {
+ $hash = hash('adler32', $id);
+ for ($i=0 ; $i < $this->_options['hashed_directory_level'] ; $i++) {
+ $root = $root . $prefix . '--' . substr($hash, 0, $i + 1) . DIRECTORY_SEPARATOR;
+ $partsArray[] = $root;
+ }
+ }
+ if ($parts) {
+ return $partsArray;
+ } else {
+ return $root;
+ }
+ }
+
+ /**
+ * Make the directory strucuture for the given id
+ *
+ * @param string $id cache id
+ * @return boolean true
+ */
+ protected function _recursiveMkdirAndChmod($id)
+ {
+ if ($this->_options['hashed_directory_level'] <=0) {
+ return true;
+ }
+ $partsArray = $this->_path($id, true);
+ foreach ($partsArray as $part) {
+ if (!is_dir($part)) {
+ @mkdir($part, $this->_options['hashed_directory_perm']);
+ @chmod($part, $this->_options['hashed_directory_perm']); // see #ZF-320 (this line is required in some configurations)
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Test if the given cache id is available (and still valid as a cache record)
+ *
+ * @param string $id Cache id
+ * @param boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested
+ * @return boolean|mixed false (a cache is not available) or "last modified" timestamp (int) of the available cache record
+ */
+ protected function _test($id, $doNotTestCacheValidity)
+ {
+ $metadatas = $this->_getMetadatas($id);
+ if (!$metadatas) {
+ return false;
+ }
+ if ($doNotTestCacheValidity || (time() <= $metadatas['expire'])) {
+ return $metadatas['mtime'];
+ }
+ return false;
+ }
+
+ /**
+ * Return the file content of the given file
+ *
+ * @param string $file File complete path
+ * @return string File content (or false if problem)
+ */
+ protected function _fileGetContents($file)
+ {
+ $result = false;
+ if (!is_file($file)) {
+ return false;
+ }
+ $f = @fopen($file, 'rb');
+ if ($f) {
+ if ($this->_options['file_locking']) @flock($f, LOCK_SH);
+ $result = stream_get_contents($f);
+ if ($this->_options['file_locking']) @flock($f, LOCK_UN);
+ @fclose($f);
+ }
+ return $result;
+ }
+
+ /**
+ * Put the given string into the given file
+ *
+ * @param string $file File complete path
+ * @param string $string String to put in file
+ * @return boolean true if no problem
+ */
+ protected function _filePutContents($file, $string)
+ {
+ $result = false;
+ $f = @fopen($file, 'ab+');
+ if ($f) {
+ if ($this->_options['file_locking']) @flock($f, LOCK_EX);
+ fseek($f, 0);
+ ftruncate($f, 0);
+ $tmp = @fwrite($f, $string);
+ if (!($tmp === FALSE)) {
+ $result = true;
+ }
+ @fclose($f);
+ }
+ @chmod($file, $this->_options['cache_file_perm']);
+ return $result;
+ }
+
+ /**
+ * Transform a file name into cache id and return it
+ *
+ * @param string $fileName File name
+ * @return string Cache id
+ */
+ protected function _fileNameToId($fileName)
+ {
+ $prefix = $this->_options['file_name_prefix'];
+ return preg_replace('~^' . $prefix . '---(.*)$~', '$1', $fileName);
+ }
+
+}
diff --git a/lib/zend/Zend/Cache/Backend/Interface.php b/lib/zend/Zend/Cache/Backend/Interface.php
new file mode 100644
index 00000000000..1bd72d8c163
--- /dev/null
+++ b/lib/zend/Zend/Cache/Backend/Interface.php
@@ -0,0 +1,99 @@
+ infinite lifetime)
+ * @return boolean true if no problem
+ */
+ public function save($data, $id, $tags = array(), $specificLifetime = false);
+
+ /**
+ * Remove a cache record
+ *
+ * @param string $id Cache id
+ * @return boolean True if no problem
+ */
+ public function remove($id);
+
+ /**
+ * Clean some cache records
+ *
+ * Available modes are :
+ * Zend_Cache::CLEANING_MODE_ALL (default) => remove all cache entries ($tags is not used)
+ * Zend_Cache::CLEANING_MODE_OLD => remove too old cache entries ($tags is not used)
+ * Zend_Cache::CLEANING_MODE_MATCHING_TAG => remove cache entries matching all given tags
+ * ($tags can be an array of strings or a single string)
+ * Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG => remove cache entries not {matching one of the given tags}
+ * ($tags can be an array of strings or a single string)
+ * Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG => remove cache entries matching any given tags
+ * ($tags can be an array of strings or a single string)
+ *
+ * @param string $mode Clean mode
+ * @param array $tags Array of tags
+ * @return boolean true if no problem
+ */
+ public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array());
+
+}
diff --git a/lib/zend/Zend/Cache/Backend/Libmemcached.php b/lib/zend/Zend/Cache/Backend/Libmemcached.php
new file mode 100644
index 00000000000..623e75776cc
--- /dev/null
+++ b/lib/zend/Zend/Cache/Backend/Libmemcached.php
@@ -0,0 +1,484 @@
+ (array) servers :
+ * an array of memcached server ; each memcached server is described by an associative array :
+ * 'host' => (string) : the name of the memcached server
+ * 'port' => (int) : the port of the memcached server
+ * 'weight' => (int) : number of buckets to create for this server which in turn control its
+ * probability of it being selected. The probability is relative to the total
+ * weight of all servers.
+ * =====> (array) client :
+ * an array of memcached client options ; the memcached client is described by an associative array :
+ * @see http://php.net/manual/memcached.constants.php
+ * - The option name can be the name of the constant without the prefix 'OPT_'
+ * or the integer value of this option constant
+ *
+ * @var array available options
+ */
+ protected $_options = array(
+ 'servers' => array(array(
+ 'host' => self::DEFAULT_HOST,
+ 'port' => self::DEFAULT_PORT,
+ 'weight' => self::DEFAULT_WEIGHT,
+ )),
+ 'client' => array()
+ );
+
+ /**
+ * Memcached object
+ *
+ * @var mixed memcached object
+ */
+ protected $_memcache = null;
+
+ /**
+ * Constructor
+ *
+ * @param array $options associative array of options
+ * @throws Zend_Cache_Exception
+ * @return void
+ */
+ public function __construct(array $options = array())
+ {
+ if (!extension_loaded('memcached')) {
+ Zend_Cache::throwException('The memcached extension must be loaded for using this backend !');
+ }
+
+ // override default client options
+ $this->_options['client'] = array(
+ Memcached::OPT_DISTRIBUTION => Memcached::DISTRIBUTION_CONSISTENT,
+ Memcached::OPT_HASH => Memcached::HASH_MD5,
+ Memcached::OPT_LIBKETAMA_COMPATIBLE => true,
+ );
+
+ parent::__construct($options);
+
+ if (isset($this->_options['servers'])) {
+ $value = $this->_options['servers'];
+ if (isset($value['host'])) {
+ // in this case, $value seems to be a simple associative array (one server only)
+ $value = array(0 => $value); // let's transform it into a classical array of associative arrays
+ }
+ $this->setOption('servers', $value);
+ }
+ $this->_memcache = new Memcached;
+
+ // setup memcached client options
+ foreach ($this->_options['client'] as $name => $value) {
+ $optId = null;
+ if (is_int($name)) {
+ $optId = $name;
+ } else {
+ $optConst = 'Memcached::OPT_' . strtoupper($name);
+ if (defined($optConst)) {
+ $optId = constant($optConst);
+ } else {
+ $this->_log("Unknown memcached client option '{$name}' ({$optConst})");
+ }
+ }
+ if (null !== $optId) {
+ if (!$this->_memcache->setOption($optId, $value)) {
+ $this->_log("Setting memcached client option '{$optId}' failed");
+ }
+ }
+ }
+
+ // setup memcached servers
+ $servers = array();
+ foreach ($this->_options['servers'] as $server) {
+ if (!array_key_exists('port', $server)) {
+ $server['port'] = self::DEFAULT_PORT;
+ }
+ if (!array_key_exists('weight', $server)) {
+ $server['weight'] = self::DEFAULT_WEIGHT;
+ }
+
+ $servers[] = array($server['host'], $server['port'], $server['weight']);
+ }
+ $this->_memcache->addServers($servers);
+ }
+
+ /**
+ * Test if a cache is available for the given id and (if yes) return it (false else)
+ *
+ * @param string $id Cache id
+ * @param boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested
+ * @return string|false cached datas
+ */
+ public function load($id, $doNotTestCacheValidity = false)
+ {
+ $tmp = $this->_memcache->get($id);
+ if (isset($tmp[0])) {
+ return $tmp[0];
+ }
+ return false;
+ }
+
+ /**
+ * Test if a cache is available or not (for the given id)
+ *
+ * @param string $id Cache id
+ * @return int|false (a cache is not available) or "last modified" timestamp (int) of the available cache record
+ */
+ public function test($id)
+ {
+ $tmp = $this->_memcache->get($id);
+ if (isset($tmp[0], $tmp[1])) {
+ return (int)$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);
+
+ // ZF-8856: using set because add needs a second request if item already exists
+ $result = @$this->_memcache->set($id, array($data, time(), $lifetime), $lifetime);
+ if ($result === false) {
+ $rsCode = $this->_memcache->getResultCode();
+ $rsMsg = $this->_memcache->getResultMessage();
+ $this->_log("Memcached::set() failed: [{$rsCode}] {$rsMsg}");
+ }
+
+ if (count($tags) > 0) {
+ $this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_LIBMEMCACHED_BACKEND);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Remove a cache record
+ *
+ * @param string $id Cache id
+ * @return boolean True if no problem
+ */
+ public function remove($id)
+ {
+ return $this->_memcache->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 $this->_memcache->flush();
+ break;
+ case Zend_Cache::CLEANING_MODE_OLD:
+ $this->_log("Zend_Cache_Backend_Libmemcached::clean() : CLEANING_MODE_OLD is unsupported by the Libmemcached 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_LIBMEMCACHED_BACKEND);
+ break;
+ default:
+ Zend_Cache::throwException('Invalid mode for clean() method');
+ break;
+ }
+ }
+
+ /**
+ * Return true if the automatic cleaning is available for the backend
+ *
+ * @return boolean
+ */
+ public function isAutomaticCleaningAvailable()
+ {
+ return false;
+ }
+
+ /**
+ * Set the frontend directives
+ *
+ * @param array $directives Assoc of directives
+ * @throws Zend_Cache_Exception
+ * @return void
+ */
+ public function setDirectives($directives)
+ {
+ parent::setDirectives($directives);
+ $lifetime = $this->getLifetime(false);
+ if ($lifetime > 2592000) {
+ // #ZF-3490 : For the memcached backend, there is a lifetime limit of 30 days (2592000 seconds)
+ $this->_log('memcached backend has a limit of 30 days (2592000 seconds) for the lifetime');
+ }
+ if ($lifetime === null) {
+ // #ZF-4614 : we tranform null to zero to get the maximal lifetime
+ parent::setDirectives(array('lifetime' => 0));
+ }
+ }
+
+ /**
+ * Return an array of stored cache ids
+ *
+ * @return array array of stored cache ids (string)
+ */
+ public function getIds()
+ {
+ $this->_log("Zend_Cache_Backend_Libmemcached::save() : getting the list of cache ids is unsupported by the Libmemcached backend");
+ return array();
+ }
+
+ /**
+ * Return an array of stored tags
+ *
+ * @return array array of stored tags (string)
+ */
+ public function getTags()
+ {
+ $this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_LIBMEMCACHED_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_LIBMEMCACHED_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_LIBMEMCACHED_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_LIBMEMCACHED_BACKEND);
+ return array();
+ }
+
+ /**
+ * Return the filling percentage of the backend storage
+ *
+ * @throws Zend_Cache_Exception
+ * @return int integer between 0 and 100
+ */
+ public function getFillingPercentage()
+ {
+ $mems = $this->_memcache->getStats();
+ if ($mems === false) {
+ return 0;
+ }
+
+ $memSize = null;
+ $memUsed = null;
+ foreach ($mems as $key => $mem) {
+ if ($mem === false) {
+ $this->_log('can\'t get stat from ' . $key);
+ continue;
+ }
+
+ $eachSize = $mem['limit_maxbytes'];
+ $eachUsed = $mem['bytes'];
+ if ($eachUsed > $eachSize) {
+ $eachUsed = $eachSize;
+ }
+
+ $memSize += $eachSize;
+ $memUsed += $eachUsed;
+ }
+
+ if ($memSize === null || $memUsed === null) {
+ Zend_Cache::throwException('Can\'t get filling percentage');
+ }
+
+ return ((int) (100. * ($memUsed / $memSize)));
+ }
+
+ /**
+ * 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 = $this->_memcache->get($id);
+ if (isset($tmp[0], $tmp[1], $tmp[2])) {
+ $data = $tmp[0];
+ $mtime = $tmp[1];
+ $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 = $this->_memcache->get($id);
+ if (isset($tmp[0], $tmp[1], $tmp[2])) {
+ $data = $tmp[0];
+ $mtime = $tmp[1];
+ $lifetime = $tmp[2];
+ $newLifetime = $lifetime - (time() - $mtime) + $extraLifetime;
+ if ($newLifetime <=0) {
+ return false;
+ }
+ // #ZF-5702 : we try replace() first becase set() seems to be slower
+ if (!($result = $this->_memcache->replace($id, array($data, time(), $newLifetime), $newLifetime))) {
+ $result = $this->_memcache->set($id, array($data, time(), $newLifetime), $newLifetime);
+ if ($result === false) {
+ $rsCode = $this->_memcache->getResultCode();
+ $rsMsg = $this->_memcache->getResultMessage();
+ $this->_log("Memcached::set() failed: [{$rsCode}] {$rsMsg}");
+ }
+ }
+ return $result;
+ }
+ 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' => false
+ );
+ }
+
+}
diff --git a/lib/zend/Zend/Cache/Backend/Memcached.php b/lib/zend/Zend/Cache/Backend/Memcached.php
new file mode 100644
index 00000000000..9cb9916dd87
--- /dev/null
+++ b/lib/zend/Zend/Cache/Backend/Memcached.php
@@ -0,0 +1,509 @@
+ (array) servers :
+ * an array of memcached server ; each memcached server is described by an associative array :
+ * 'host' => (string) : the name of the memcached server
+ * 'port' => (int) : the port of the memcached server
+ * 'persistent' => (bool) : use or not persistent connections to this memcached server
+ * 'weight' => (int) : number of buckets to create for this server which in turn control its
+ * probability of it being selected. The probability is relative to the total
+ * weight of all servers.
+ * 'timeout' => (int) : value in seconds which will be used for connecting to the daemon. Think twice
+ * before changing the default value of 1 second - you can lose all the
+ * advantages of caching if your connection is too slow.
+ * 'retry_interval' => (int) : controls how often a failed server will be retried, the default value
+ * is 15 seconds. Setting this parameter to -1 disables automatic retry.
+ * 'status' => (bool) : controls if the server should be flagged as online.
+ * 'failure_callback' => (callback) : Allows the user to specify a callback function to run upon
+ * encountering an error. The callback is run before failover
+ * is attempted. The function takes two parameters, the hostname
+ * and port of the failed server.
+ *
+ * =====> (boolean) compression :
+ * true if you want to use on-the-fly compression
+ *
+ * =====> (boolean) compatibility :
+ * true if you use old memcache server or extension
+ *
+ * @var array available options
+ */
+ protected $_options = array(
+ 'servers' => array(array(
+ 'host' => self::DEFAULT_HOST,
+ 'port' => self::DEFAULT_PORT,
+ 'persistent' => self::DEFAULT_PERSISTENT,
+ 'weight' => self::DEFAULT_WEIGHT,
+ 'timeout' => self::DEFAULT_TIMEOUT,
+ 'retry_interval' => self::DEFAULT_RETRY_INTERVAL,
+ 'status' => self::DEFAULT_STATUS,
+ 'failure_callback' => self::DEFAULT_FAILURE_CALLBACK
+ )),
+ 'compression' => false,
+ 'compatibility' => false,
+ );
+
+ /**
+ * Memcache object
+ *
+ * @var mixed memcache object
+ */
+ protected $_memcache = null;
+
+ /**
+ * Constructor
+ *
+ * @param array $options associative array of options
+ * @throws Zend_Cache_Exception
+ * @return void
+ */
+ public function __construct(array $options = array())
+ {
+ if (!extension_loaded('memcache')) {
+ Zend_Cache::throwException('The memcache extension must be loaded for using this backend !');
+ }
+ parent::__construct($options);
+ if (isset($this->_options['servers'])) {
+ $value= $this->_options['servers'];
+ if (isset($value['host'])) {
+ // in this case, $value seems to be a simple associative array (one server only)
+ $value = array(0 => $value); // let's transform it into a classical array of associative arrays
+ }
+ $this->setOption('servers', $value);
+ }
+ $this->_memcache = new Memcache;
+ foreach ($this->_options['servers'] as $server) {
+ if (!array_key_exists('port', $server)) {
+ $server['port'] = self::DEFAULT_PORT;
+ }
+ if (!array_key_exists('persistent', $server)) {
+ $server['persistent'] = self::DEFAULT_PERSISTENT;
+ }
+ if (!array_key_exists('weight', $server)) {
+ $server['weight'] = self::DEFAULT_WEIGHT;
+ }
+ if (!array_key_exists('timeout', $server)) {
+ $server['timeout'] = self::DEFAULT_TIMEOUT;
+ }
+ if (!array_key_exists('retry_interval', $server)) {
+ $server['retry_interval'] = self::DEFAULT_RETRY_INTERVAL;
+ }
+ if (!array_key_exists('status', $server)) {
+ $server['status'] = self::DEFAULT_STATUS;
+ }
+ if (!array_key_exists('failure_callback', $server)) {
+ $server['failure_callback'] = self::DEFAULT_FAILURE_CALLBACK;
+ }
+ if ($this->_options['compatibility']) {
+ // No status for compatibility mode (#ZF-5887)
+ $this->_memcache->addServer($server['host'], $server['port'], $server['persistent'],
+ $server['weight'], $server['timeout'],
+ $server['retry_interval']);
+ } else {
+ $this->_memcache->addServer($server['host'], $server['port'], $server['persistent'],
+ $server['weight'], $server['timeout'],
+ $server['retry_interval'],
+ $server['status'], $server['failure_callback']);
+ }
+ }
+ }
+
+ /**
+ * Test if a cache is available for the given id and (if yes) return it (false else)
+ *
+ * @param string $id Cache id
+ * @param boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested
+ * @return string|false cached datas
+ */
+ public function load($id, $doNotTestCacheValidity = false)
+ {
+ $tmp = $this->_memcache->get($id);
+ if (is_array($tmp) && isset($tmp[0])) {
+ 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 = $this->_memcache->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);
+ if ($this->_options['compression']) {
+ $flag = MEMCACHE_COMPRESSED;
+ } else {
+ $flag = 0;
+ }
+
+ // ZF-8856: using set because add needs a second request if item already exists
+ $result = @$this->_memcache->set($id, array($data, time(), $lifetime), $flag, $lifetime);
+
+ if (count($tags) > 0) {
+ $this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_MEMCACHED_BACKEND);
+ }
+
+ return $result;
+ }
+
+ /**
+ * Remove a cache record
+ *
+ * @param string $id Cache id
+ * @return boolean True if no problem
+ */
+ public function remove($id)
+ {
+ return $this->_memcache->delete($id, 0);
+ }
+
+ /**
+ * 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 $this->_memcache->flush();
+ break;
+ case Zend_Cache::CLEANING_MODE_OLD:
+ $this->_log("Zend_Cache_Backend_Memcached::clean() : CLEANING_MODE_OLD is unsupported by the Memcached 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_MEMCACHED_BACKEND);
+ break;
+ default:
+ Zend_Cache::throwException('Invalid mode for clean() method');
+ break;
+ }
+ }
+
+ /**
+ * Return true if the automatic cleaning is available for the backend
+ *
+ * @return boolean
+ */
+ public function isAutomaticCleaningAvailable()
+ {
+ return false;
+ }
+
+ /**
+ * Set the frontend directives
+ *
+ * @param array $directives Assoc of directives
+ * @throws Zend_Cache_Exception
+ * @return void
+ */
+ public function setDirectives($directives)
+ {
+ parent::setDirectives($directives);
+ $lifetime = $this->getLifetime(false);
+ if ($lifetime > 2592000) {
+ // #ZF-3490 : For the memcached backend, there is a lifetime limit of 30 days (2592000 seconds)
+ $this->_log('memcached backend has a limit of 30 days (2592000 seconds) for the lifetime');
+ }
+ if ($lifetime === null) {
+ // #ZF-4614 : we tranform null to zero to get the maximal lifetime
+ parent::setDirectives(array('lifetime' => 0));
+ }
+ }
+
+ /**
+ * Return an array of stored cache ids
+ *
+ * @return array array of stored cache ids (string)
+ */
+ public function getIds()
+ {
+ $this->_log("Zend_Cache_Backend_Memcached::save() : getting the list of cache ids is unsupported by the Memcache backend");
+ return array();
+ }
+
+ /**
+ * Return an array of stored tags
+ *
+ * @return array array of stored tags (string)
+ */
+ public function getTags()
+ {
+ $this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_MEMCACHED_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_MEMCACHED_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_MEMCACHED_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_MEMCACHED_BACKEND);
+ return array();
+ }
+
+ /**
+ * Return the filling percentage of the backend storage
+ *
+ * @throws Zend_Cache_Exception
+ * @return int integer between 0 and 100
+ */
+ public function getFillingPercentage()
+ {
+ $mems = $this->_memcache->getExtendedStats();
+
+ $memSize = null;
+ $memUsed = null;
+ foreach ($mems as $key => $mem) {
+ if ($mem === false) {
+ $this->_log('can\'t get stat from ' . $key);
+ continue;
+ }
+
+ $eachSize = $mem['limit_maxbytes'];
+
+ /**
+ * Couchbase 1.x uses 'mem_used' instead of 'bytes'
+ * @see https://www.couchbase.com/issues/browse/MB-3466
+ */
+ $eachUsed = isset($mem['bytes']) ? $mem['bytes'] : $mem['mem_used'];
+ if ($eachUsed > $eachSize) {
+ $eachUsed = $eachSize;
+ }
+
+ $memSize += $eachSize;
+ $memUsed += $eachUsed;
+ }
+
+ if ($memSize === null || $memUsed === null) {
+ Zend_Cache::throwException('Can\'t get filling percentage');
+ }
+
+ return ((int) (100. * ($memUsed / $memSize)));
+ }
+
+ /**
+ * 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 = $this->_memcache->get($id);
+ if (is_array($tmp)) {
+ $data = $tmp[0];
+ $mtime = $tmp[1];
+ if (!isset($tmp[2])) {
+ // because this record is only with 1.7 release
+ // if old cache records are still there...
+ 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)
+ {
+ if ($this->_options['compression']) {
+ $flag = MEMCACHE_COMPRESSED;
+ } else {
+ $flag = 0;
+ }
+ $tmp = $this->_memcache->get($id);
+ if (is_array($tmp)) {
+ $data = $tmp[0];
+ $mtime = $tmp[1];
+ if (!isset($tmp[2])) {
+ // because this record is only with 1.7 release
+ // if old cache records are still there...
+ return false;
+ }
+ $lifetime = $tmp[2];
+ $newLifetime = $lifetime - (time() - $mtime) + $extraLifetime;
+ if ($newLifetime <=0) {
+ return false;
+ }
+ // #ZF-5702 : we try replace() first becase set() seems to be slower
+ if (!($result = $this->_memcache->replace($id, array($data, time(), $newLifetime), $flag, $newLifetime))) {
+ $result = $this->_memcache->set($id, array($data, time(), $newLifetime), $flag, $newLifetime);
+ }
+ return $result;
+ }
+ 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' => false
+ );
+ }
+
+}
diff --git a/lib/zend/Zend/Cache/Backend/Sqlite.php b/lib/zend/Zend/Cache/Backend/Sqlite.php
new file mode 100644
index 00000000000..3e8ac8276b9
--- /dev/null
+++ b/lib/zend/Zend/Cache/Backend/Sqlite.php
@@ -0,0 +1,678 @@
+ (string) cache_db_complete_path :
+ * - the complete path (filename included) of the SQLITE database
+ *
+ * ====> (int) automatic_vacuum_factor :
+ * - Disable / Tune the automatic vacuum process
+ * - The automatic vacuum process defragment the database file (and make it smaller)
+ * when a clean() or delete() is called
+ * 0 => no automatic vacuum
+ * 1 => systematic vacuum (when delete() or clean() methods are called)
+ * x (integer) > 1 => automatic vacuum randomly 1 times on x clean() or delete()
+ *
+ * @var array Available options
+ */
+ protected $_options = array(
+ 'cache_db_complete_path' => null,
+ 'automatic_vacuum_factor' => 10
+ );
+
+ /**
+ * DB ressource
+ *
+ * @var mixed $_db
+ */
+ private $_db = null;
+
+ /**
+ * Boolean to store if the structure has benn checked or not
+ *
+ * @var boolean $_structureChecked
+ */
+ private $_structureChecked = false;
+
+ /**
+ * Constructor
+ *
+ * @param array $options Associative array of options
+ * @throws Zend_cache_Exception
+ * @return void
+ */
+ public function __construct(array $options = array())
+ {
+ parent::__construct($options);
+ if ($this->_options['cache_db_complete_path'] === null) {
+ Zend_Cache::throwException('cache_db_complete_path option has to set');
+ }
+ if (!extension_loaded('sqlite')) {
+ Zend_Cache::throwException("Cannot use SQLite storage because the 'sqlite' extension is not loaded in the current PHP environment");
+ }
+ $this->_getConnection();
+ }
+
+ /**
+ * Destructor
+ *
+ * @return void
+ */
+ public function __destruct()
+ {
+ @sqlite_close($this->_getConnection());
+ }
+
+ /**
+ * Test if a cache is available for the given id and (if yes) return it (false else)
+ *
+ * @param string $id Cache id
+ * @param boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested
+ * @return string|false Cached datas
+ */
+ public function load($id, $doNotTestCacheValidity = false)
+ {
+ $this->_checkAndBuildStructure();
+ $sql = "SELECT content FROM cache WHERE id='$id'";
+ if (!$doNotTestCacheValidity) {
+ $sql = $sql . " AND (expire=0 OR expire>" . time() . ')';
+ }
+ $result = $this->_query($sql);
+ $row = @sqlite_fetch_array($result);
+ if ($row) {
+ return $row['content'];
+ }
+ 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)
+ {
+ $this->_checkAndBuildStructure();
+ $sql = "SELECT lastModified FROM cache WHERE id='$id' AND (expire=0 OR expire>" . time() . ')';
+ $result = $this->_query($sql);
+ $row = @sqlite_fetch_array($result);
+ if ($row) {
+ return ((int) $row['lastModified']);
+ }
+ 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)
+ * @throws Zend_Cache_Exception
+ * @return boolean True if no problem
+ */
+ public function save($data, $id, $tags = array(), $specificLifetime = false)
+ {
+ $this->_checkAndBuildStructure();
+ $lifetime = $this->getLifetime($specificLifetime);
+ $data = @sqlite_escape_string($data);
+ $mktime = time();
+ if ($lifetime === null) {
+ $expire = 0;
+ } else {
+ $expire = $mktime + $lifetime;
+ }
+ $this->_query("DELETE FROM cache WHERE id='$id'");
+ $sql = "INSERT INTO cache (id, content, lastModified, expire) VALUES ('$id', '$data', $mktime, $expire)";
+ $res = $this->_query($sql);
+ if (!$res) {
+ $this->_log("Zend_Cache_Backend_Sqlite::save() : impossible to store the cache id=$id");
+ return false;
+ }
+ $res = true;
+ foreach ($tags as $tag) {
+ $res = $this->_registerTag($id, $tag) && $res;
+ }
+ return $res;
+ }
+
+ /**
+ * Remove a cache record
+ *
+ * @param string $id Cache id
+ * @return boolean True if no problem
+ */
+ public function remove($id)
+ {
+ $this->_checkAndBuildStructure();
+ $res = $this->_query("SELECT COUNT(*) AS nbr FROM cache WHERE id='$id'");
+ $result1 = @sqlite_fetch_single($res);
+ $result2 = $this->_query("DELETE FROM cache WHERE id='$id'");
+ $result3 = $this->_query("DELETE FROM tag WHERE id='$id'");
+ $this->_automaticVacuum();
+ return ($result1 && $result2 && $result3);
+ }
+
+ /**
+ * Clean some cache records
+ *
+ * Available modes are :
+ * Zend_Cache::CLEANING_MODE_ALL (default) => remove all cache entries ($tags is not used)
+ * Zend_Cache::CLEANING_MODE_OLD => remove too old cache entries ($tags is not used)
+ * Zend_Cache::CLEANING_MODE_MATCHING_TAG => remove cache entries matching all given tags
+ * ($tags can be an array of strings or a single string)
+ * Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG => remove cache entries not {matching one of the given tags}
+ * ($tags can be an array of strings or a single string)
+ * Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG => remove cache entries matching any given tags
+ * ($tags can be an array of strings or a single string)
+ *
+ * @param string $mode Clean mode
+ * @param array $tags Array of tags
+ * @return boolean True if no problem
+ */
+ public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array())
+ {
+ $this->_checkAndBuildStructure();
+ $return = $this->_clean($mode, $tags);
+ $this->_automaticVacuum();
+ return $return;
+ }
+
+ /**
+ * Return an array of stored cache ids
+ *
+ * @return array array of stored cache ids (string)
+ */
+ public function getIds()
+ {
+ $this->_checkAndBuildStructure();
+ $res = $this->_query("SELECT id FROM cache WHERE (expire=0 OR expire>" . time() . ")");
+ $result = array();
+ while ($id = @sqlite_fetch_single($res)) {
+ $result[] = $id;
+ }
+ return $result;
+ }
+
+ /**
+ * Return an array of stored tags
+ *
+ * @return array array of stored tags (string)
+ */
+ public function getTags()
+ {
+ $this->_checkAndBuildStructure();
+ $res = $this->_query("SELECT DISTINCT(name) AS name FROM tag");
+ $result = array();
+ while ($id = @sqlite_fetch_single($res)) {
+ $result[] = $id;
+ }
+ return $result;
+ }
+
+ /**
+ * 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())
+ {
+ $first = true;
+ $ids = array();
+ foreach ($tags as $tag) {
+ $res = $this->_query("SELECT DISTINCT(id) AS id FROM tag WHERE name='$tag'");
+ if (!$res) {
+ return array();
+ }
+ $rows = @sqlite_fetch_all($res, SQLITE_ASSOC);
+ $ids2 = array();
+ foreach ($rows as $row) {
+ $ids2[] = $row['id'];
+ }
+ if ($first) {
+ $ids = $ids2;
+ $first = false;
+ } else {
+ $ids = array_intersect($ids, $ids2);
+ }
+ }
+ $result = array();
+ foreach ($ids as $id) {
+ $result[] = $id;
+ }
+ return $result;
+ }
+
+ /**
+ * 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())
+ {
+ $res = $this->_query("SELECT id FROM cache");
+ $rows = @sqlite_fetch_all($res, SQLITE_ASSOC);
+ $result = array();
+ foreach ($rows as $row) {
+ $id = $row['id'];
+ $matching = false;
+ foreach ($tags as $tag) {
+ $res = $this->_query("SELECT COUNT(*) AS nbr FROM tag WHERE name='$tag' AND id='$id'");
+ if (!$res) {
+ return array();
+ }
+ $nbr = (int) @sqlite_fetch_single($res);
+ if ($nbr > 0) {
+ $matching = true;
+ }
+ }
+ if (!$matching) {
+ $result[] = $id;
+ }
+ }
+ return $result;
+ }
+
+ /**
+ * 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())
+ {
+ $first = true;
+ $ids = array();
+ foreach ($tags as $tag) {
+ $res = $this->_query("SELECT DISTINCT(id) AS id FROM tag WHERE name='$tag'");
+ if (!$res) {
+ return array();
+ }
+ $rows = @sqlite_fetch_all($res, SQLITE_ASSOC);
+ $ids2 = array();
+ foreach ($rows as $row) {
+ $ids2[] = $row['id'];
+ }
+ if ($first) {
+ $ids = $ids2;
+ $first = false;
+ } else {
+ $ids = array_merge($ids, $ids2);
+ }
+ }
+ $result = array();
+ foreach ($ids as $id) {
+ $result[] = $id;
+ }
+ return $result;
+ }
+
+ /**
+ * Return the filling percentage of the backend storage
+ *
+ * @throws Zend_Cache_Exception
+ * @return int integer between 0 and 100
+ */
+ public function getFillingPercentage()
+ {
+ $dir = dirname($this->_options['cache_db_complete_path']);
+ $free = disk_free_space($dir);
+ $total = disk_total_space($dir);
+ if ($total == 0) {
+ Zend_Cache::throwException('can\'t get disk_total_space');
+ } else {
+ if ($free >= $total) {
+ return 100;
+ }
+ return ((int) (100. * ($total - $free) / $total));
+ }
+ }
+
+ /**
+ * 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)
+ {
+ $tags = array();
+ $res = $this->_query("SELECT name FROM tag WHERE id='$id'");
+ if ($res) {
+ $rows = @sqlite_fetch_all($res, SQLITE_ASSOC);
+ foreach ($rows as $row) {
+ $tags[] = $row['name'];
+ }
+ }
+ $this->_query('CREATE TABLE cache (id TEXT PRIMARY KEY, content BLOB, lastModified INTEGER, expire INTEGER)');
+ $res = $this->_query("SELECT lastModified,expire FROM cache WHERE id='$id'");
+ if (!$res) {
+ return false;
+ }
+ $row = @sqlite_fetch_array($res, SQLITE_ASSOC);
+ return array(
+ 'tags' => $tags,
+ 'mtime' => $row['lastModified'],
+ 'expire' => $row['expire']
+ );
+ }
+
+ /**
+ * 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)
+ {
+ $sql = "SELECT expire FROM cache WHERE id='$id' AND (expire=0 OR expire>" . time() . ')';
+ $res = $this->_query($sql);
+ if (!$res) {
+ return false;
+ }
+ $expire = @sqlite_fetch_single($res);
+ $newExpire = $expire + $extraLifetime;
+ $res = $this->_query("UPDATE cache SET lastModified=" . time() . ", expire=$newExpire WHERE id='$id'");
+ if ($res) {
+ return true;
+ } else {
+ 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' => true,
+ 'tags' => true,
+ 'expired_read' => true,
+ 'priority' => false,
+ 'infinite_lifetime' => true,
+ 'get_list' => true
+ );
+ }
+
+ /**
+ * PUBLIC METHOD FOR UNIT TESTING ONLY !
+ *
+ * Force a cache record to expire
+ *
+ * @param string $id Cache id
+ */
+ public function ___expire($id)
+ {
+ $time = time() - 1;
+ $this->_query("UPDATE cache SET lastModified=$time, expire=$time WHERE id='$id'");
+ }
+
+ /**
+ * Return the connection resource
+ *
+ * If we are not connected, the connection is made
+ *
+ * @throws Zend_Cache_Exception
+ * @return resource Connection resource
+ */
+ private function _getConnection()
+ {
+ if (is_resource($this->_db)) {
+ return $this->_db;
+ } else {
+ $this->_db = @sqlite_open($this->_options['cache_db_complete_path']);
+ if (!(is_resource($this->_db))) {
+ Zend_Cache::throwException("Impossible to open " . $this->_options['cache_db_complete_path'] . " cache DB file");
+ }
+ return $this->_db;
+ }
+ }
+
+ /**
+ * Execute an SQL query silently
+ *
+ * @param string $query SQL query
+ * @return mixed|false query results
+ */
+ private function _query($query)
+ {
+ $db = $this->_getConnection();
+ if (is_resource($db)) {
+ $res = @sqlite_query($db, $query);
+ if ($res === false) {
+ return false;
+ } else {
+ return $res;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Deal with the automatic vacuum process
+ *
+ * @return void
+ */
+ private function _automaticVacuum()
+ {
+ if ($this->_options['automatic_vacuum_factor'] > 0) {
+ $rand = rand(1, $this->_options['automatic_vacuum_factor']);
+ if ($rand == 1) {
+ $this->_query('VACUUM');
+ }
+ }
+ }
+
+ /**
+ * Register a cache id with the given tag
+ *
+ * @param string $id Cache id
+ * @param string $tag Tag
+ * @return boolean True if no problem
+ */
+ private function _registerTag($id, $tag) {
+ $res = $this->_query("DELETE FROM TAG WHERE name='$tag' AND id='$id'");
+ $res = $this->_query("INSERT INTO tag (name, id) VALUES ('$tag', '$id')");
+ if (!$res) {
+ $this->_log("Zend_Cache_Backend_Sqlite::_registerTag() : impossible to register tag=$tag on id=$id");
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Build the database structure
+ *
+ * @return false
+ */
+ private function _buildStructure()
+ {
+ $this->_query('DROP INDEX tag_id_index');
+ $this->_query('DROP INDEX tag_name_index');
+ $this->_query('DROP INDEX cache_id_expire_index');
+ $this->_query('DROP TABLE version');
+ $this->_query('DROP TABLE cache');
+ $this->_query('DROP TABLE tag');
+ $this->_query('CREATE TABLE version (num INTEGER PRIMARY KEY)');
+ $this->_query('CREATE TABLE cache (id TEXT PRIMARY KEY, content BLOB, lastModified INTEGER, expire INTEGER)');
+ $this->_query('CREATE TABLE tag (name TEXT, id TEXT)');
+ $this->_query('CREATE INDEX tag_id_index ON tag(id)');
+ $this->_query('CREATE INDEX tag_name_index ON tag(name)');
+ $this->_query('CREATE INDEX cache_id_expire_index ON cache(id, expire)');
+ $this->_query('INSERT INTO version (num) VALUES (1)');
+ }
+
+ /**
+ * Check if the database structure is ok (with the good version)
+ *
+ * @return boolean True if ok
+ */
+ private function _checkStructureVersion()
+ {
+ $result = $this->_query("SELECT num FROM version");
+ if (!$result) return false;
+ $row = @sqlite_fetch_array($result);
+ if (!$row) {
+ return false;
+ }
+ if (((int) $row['num']) != 1) {
+ // old cache structure
+ $this->_log('Zend_Cache_Backend_Sqlite::_checkStructureVersion() : old cache structure version detected => the cache is going to be dropped');
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Clean some cache records
+ *
+ * Available modes are :
+ * Zend_Cache::CLEANING_MODE_ALL (default) => remove all cache entries ($tags is not used)
+ * Zend_Cache::CLEANING_MODE_OLD => remove too old cache entries ($tags is not used)
+ * Zend_Cache::CLEANING_MODE_MATCHING_TAG => remove cache entries matching all given tags
+ * ($tags can be an array of strings or a single string)
+ * Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG => remove cache entries not {matching one of the given tags}
+ * ($tags can be an array of strings or a single string)
+ * Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG => remove cache entries matching any given tags
+ * ($tags can be an array of strings or a single string)
+ *
+ * @param string $mode Clean mode
+ * @param array $tags Array of tags
+ * @return boolean True if no problem
+ */
+ private function _clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array())
+ {
+ switch ($mode) {
+ case Zend_Cache::CLEANING_MODE_ALL:
+ $res1 = $this->_query('DELETE FROM cache');
+ $res2 = $this->_query('DELETE FROM tag');
+ return $res1 && $res2;
+ break;
+ case Zend_Cache::CLEANING_MODE_OLD:
+ $mktime = time();
+ $res1 = $this->_query("DELETE FROM tag WHERE id IN (SELECT id FROM cache WHERE expire>0 AND expire<=$mktime)");
+ $res2 = $this->_query("DELETE FROM cache WHERE expire>0 AND expire<=$mktime");
+ return $res1 && $res2;
+ break;
+ case Zend_Cache::CLEANING_MODE_MATCHING_TAG:
+ $ids = $this->getIdsMatchingTags($tags);
+ $result = true;
+ foreach ($ids as $id) {
+ $result = $this->remove($id) && $result;
+ }
+ return $result;
+ break;
+ case Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG:
+ $ids = $this->getIdsNotMatchingTags($tags);
+ $result = true;
+ foreach ($ids as $id) {
+ $result = $this->remove($id) && $result;
+ }
+ return $result;
+ break;
+ case Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG:
+ $ids = $this->getIdsMatchingAnyTags($tags);
+ $result = true;
+ foreach ($ids as $id) {
+ $result = $this->remove($id) && $result;
+ }
+ return $result;
+ break;
+ default:
+ break;
+ }
+ return false;
+ }
+
+ /**
+ * Check if the database structure is ok (with the good version), if no : build it
+ *
+ * @throws Zend_Cache_Exception
+ * @return boolean True if ok
+ */
+ private function _checkAndBuildStructure()
+ {
+ if (!($this->_structureChecked)) {
+ if (!$this->_checkStructureVersion()) {
+ $this->_buildStructure();
+ if (!$this->_checkStructureVersion()) {
+ Zend_Cache::throwException("Impossible to build cache structure in " . $this->_options['cache_db_complete_path']);
+ }
+ }
+ $this->_structureChecked = true;
+ }
+ return true;
+ }
+
+}
diff --git a/lib/zend/Zend/Cache/Backend/Static.php b/lib/zend/Zend/Cache/Backend/Static.php
new file mode 100644
index 00000000000..9e3c99036fb
--- /dev/null
+++ b/lib/zend/Zend/Cache/Backend/Static.php
@@ -0,0 +1,579 @@
+ null,
+ 'sub_dir' => 'html',
+ 'file_extension' => '.html',
+ 'index_filename' => 'index',
+ 'file_locking' => true,
+ 'cache_file_perm' => 0600,
+ 'cache_directory_perm' => 0700,
+ 'debug_header' => false,
+ 'tag_cache' => null,
+ 'disable_caching' => false
+ );
+
+ /**
+ * Cache for handling tags
+ * @var Zend_Cache_Core
+ */
+ protected $_tagCache = null;
+
+ /**
+ * Tagged items
+ * @var array
+ */
+ protected $_tagged = null;
+
+ /**
+ * Interceptor child method to handle the case where an Inner
+ * Cache object is being set since it's not supported by the
+ * standard backend interface
+ *
+ * @param string $name
+ * @param mixed $value
+ * @return Zend_Cache_Backend_Static
+ */
+ public function setOption($name, $value)
+ {
+ if ($name == 'tag_cache') {
+ $this->setInnerCache($value);
+ } else {
+ // See #ZF-12047 and #GH-91
+ if ($name == 'cache_file_umask') {
+ trigger_error(
+ "'cache_file_umask' is deprecated -> please use 'cache_file_perm' instead",
+ E_USER_NOTICE
+ );
+
+ $name = 'cache_file_perm';
+ }
+ if ($name == 'cache_directory_umask') {
+ trigger_error(
+ "'cache_directory_umask' is deprecated -> please use 'cache_directory_perm' instead",
+ E_USER_NOTICE
+ );
+
+ $name = 'cache_directory_perm';
+ }
+
+ parent::setOption($name, $value);
+ }
+ return $this;
+ }
+
+ /**
+ * Retrieve any option via interception of the parent's statically held
+ * options including the local option for a tag cache.
+ *
+ * @param string $name
+ * @return mixed
+ */
+ public function getOption($name)
+ {
+ $name = strtolower($name);
+
+ if ($name == 'tag_cache') {
+ return $this->getInnerCache();
+ }
+
+ return parent::getOption($name);
+ }
+
+ /**
+ * Test if a cache is available for the given id and (if yes) return it (false else)
+ *
+ * Note : return value is always "string" (unserialization is done by the core not by the backend)
+ *
+ * @param string $id Cache id
+ * @param boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested
+ * @return string|false cached datas
+ */
+ public function load($id, $doNotTestCacheValidity = false)
+ {
+ if (($id = (string)$id) === '') {
+ $id = $this->_detectId();
+ } else {
+ $id = $this->_decodeId($id);
+ }
+ if (!$this->_verifyPath($id)) {
+ Zend_Cache::throwException('Invalid cache id: does not match expected public_dir path');
+ }
+ if ($doNotTestCacheValidity) {
+ $this->_log("Zend_Cache_Backend_Static::load() : \$doNotTestCacheValidity=true is unsupported by the Static backend");
+ }
+
+ $fileName = basename($id);
+ if ($fileName === '') {
+ $fileName = $this->_options['index_filename'];
+ }
+ $pathName = $this->_options['public_dir'] . dirname($id);
+ $file = rtrim($pathName, '/') . '/' . $fileName . $this->_options['file_extension'];
+ if (file_exists($file)) {
+ $content = file_get_contents($file);
+ return $content;
+ }
+
+ return false;
+ }
+
+ /**
+ * Test if a cache is available or not (for the given id)
+ *
+ * @param string $id cache id
+ * @return bool
+ */
+ public function test($id)
+ {
+ $id = $this->_decodeId($id);
+ if (!$this->_verifyPath($id)) {
+ Zend_Cache::throwException('Invalid cache id: does not match expected public_dir path');
+ }
+
+ $fileName = basename($id);
+ if ($fileName === '') {
+ $fileName = $this->_options['index_filename'];
+ }
+ if ($this->_tagged === null && $tagged = $this->getInnerCache()->load(self::INNER_CACHE_NAME)) {
+ $this->_tagged = $tagged;
+ } elseif (!$this->_tagged) {
+ return false;
+ }
+ $pathName = $this->_options['public_dir'] . dirname($id);
+
+ // Switch extension if needed
+ if (isset($this->_tagged[$id])) {
+ $extension = $this->_tagged[$id]['extension'];
+ } else {
+ $extension = $this->_options['file_extension'];
+ }
+ $file = $pathName . '/' . $fileName . $extension;
+ if (file_exists($file)) {
+ return true;
+ }
+ 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)
+ {
+ if ($this->_options['disable_caching']) {
+ return true;
+ }
+ $extension = null;
+ if ($this->_isSerialized($data)) {
+ $data = unserialize($data);
+ $extension = '.' . ltrim($data[1], '.');
+ $data = $data[0];
+ }
+
+ clearstatcache();
+ if (($id = (string)$id) === '') {
+ $id = $this->_detectId();
+ } else {
+ $id = $this->_decodeId($id);
+ }
+
+ $fileName = basename($id);
+ if ($fileName === '') {
+ $fileName = $this->_options['index_filename'];
+ }
+
+ $pathName = realpath($this->_options['public_dir']) . dirname($id);
+ $this->_createDirectoriesFor($pathName);
+
+ if ($id === null || strlen($id) == 0) {
+ $dataUnserialized = unserialize($data);
+ $data = $dataUnserialized['data'];
+ }
+ $ext = $this->_options['file_extension'];
+ if ($extension) $ext = $extension;
+ $file = rtrim($pathName, '/') . '/' . $fileName . $ext;
+ if ($this->_options['file_locking']) {
+ $result = file_put_contents($file, $data, LOCK_EX);
+ } else {
+ $result = file_put_contents($file, $data);
+ }
+ @chmod($file, $this->_octdec($this->_options['cache_file_perm']));
+
+ if ($this->_tagged === null && $tagged = $this->getInnerCache()->load(self::INNER_CACHE_NAME)) {
+ $this->_tagged = $tagged;
+ } elseif ($this->_tagged === null) {
+ $this->_tagged = array();
+ }
+ if (!isset($this->_tagged[$id])) {
+ $this->_tagged[$id] = array();
+ }
+ if (!isset($this->_tagged[$id]['tags'])) {
+ $this->_tagged[$id]['tags'] = array();
+ }
+ $this->_tagged[$id]['tags'] = array_unique(array_merge($this->_tagged[$id]['tags'], $tags));
+ $this->_tagged[$id]['extension'] = $ext;
+ $this->getInnerCache()->save($this->_tagged, self::INNER_CACHE_NAME);
+ return (bool) $result;
+ }
+
+ /**
+ * Recursively create the directories needed to write the static file
+ */
+ protected function _createDirectoriesFor($path)
+ {
+ if (!is_dir($path)) {
+ $oldUmask = umask(0);
+ if ( !@mkdir($path, $this->_octdec($this->_options['cache_directory_perm']), true)) {
+ $lastErr = error_get_last();
+ umask($oldUmask);
+ Zend_Cache::throwException("Can't create directory: {$lastErr['message']}");
+ }
+ umask($oldUmask);
+ }
+ }
+
+ /**
+ * Detect serialization of data (cannot predict since this is the only way
+ * to obey the interface yet pass in another parameter).
+ *
+ * In future, ZF 2.0, check if we can just avoid the interface restraints.
+ *
+ * This format is the only valid one possible for the class, so it's simple
+ * to just run a regular expression for the starting serialized format.
+ */
+ protected function _isSerialized($data)
+ {
+ return preg_match("/a:2:\{i:0;s:\d+:\"/", $data);
+ }
+
+ /**
+ * Remove a cache record
+ *
+ * @param string $id Cache id
+ * @return boolean True if no problem
+ */
+ public function remove($id)
+ {
+ if (!$this->_verifyPath($id)) {
+ Zend_Cache::throwException('Invalid cache id: does not match expected public_dir path');
+ }
+ $fileName = basename($id);
+ if ($this->_tagged === null && $tagged = $this->getInnerCache()->load(self::INNER_CACHE_NAME)) {
+ $this->_tagged = $tagged;
+ } elseif (!$this->_tagged) {
+ return false;
+ }
+ if (isset($this->_tagged[$id])) {
+ $extension = $this->_tagged[$id]['extension'];
+ } else {
+ $extension = $this->_options['file_extension'];
+ }
+ if ($fileName === '') {
+ $fileName = $this->_options['index_filename'];
+ }
+ $pathName = $this->_options['public_dir'] . dirname($id);
+ $file = realpath($pathName) . '/' . $fileName . $extension;
+ if (!file_exists($file)) {
+ return false;
+ }
+ return unlink($file);
+ }
+
+ /**
+ * Remove a cache record recursively for the given directory matching a
+ * REQUEST_URI based relative path (deletes the actual file matching this
+ * in addition to the matching directory)
+ *
+ * @param string $id Cache id
+ * @return boolean True if no problem
+ */
+ public function removeRecursively($id)
+ {
+ if (!$this->_verifyPath($id)) {
+ Zend_Cache::throwException('Invalid cache id: does not match expected public_dir path');
+ }
+ $fileName = basename($id);
+ if ($fileName === '') {
+ $fileName = $this->_options['index_filename'];
+ }
+ $pathName = $this->_options['public_dir'] . dirname($id);
+ $file = $pathName . '/' . $fileName . $this->_options['file_extension'];
+ $directory = $pathName . '/' . $fileName;
+ if (file_exists($directory)) {
+ if (!is_writable($directory)) {
+ return false;
+ }
+ if (is_dir($directory)) {
+ foreach (new DirectoryIterator($directory) as $file) {
+ if (true === $file->isFile()) {
+ if (false === unlink($file->getPathName())) {
+ return false;
+ }
+ }
+ }
+ }
+ rmdir($directory);
+ }
+ if (file_exists($file)) {
+ if (!is_writable($file)) {
+ return false;
+ }
+ return unlink($file);
+ }
+ return true;
+ }
+
+ /**
+ * Clean some cache records
+ *
+ * Available modes are :
+ * Zend_Cache::CLEANING_MODE_ALL (default) => remove all cache entries ($tags is not used)
+ * Zend_Cache::CLEANING_MODE_OLD => remove too old cache entries ($tags is not used)
+ * Zend_Cache::CLEANING_MODE_MATCHING_TAG => remove cache entries matching all given tags
+ * ($tags can be an array of strings or a single string)
+ * Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG => remove cache entries not {matching one of the given tags}
+ * ($tags can be an array of strings or a single string)
+ * Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG => remove cache entries matching any given tags
+ * ($tags can be an array of strings or a single string)
+ *
+ * @param string $mode Clean mode
+ * @param array $tags Array of tags
+ * @return boolean true if no problem
+ * @throws Zend_Exception
+ */
+ public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array())
+ {
+ $result = false;
+ switch ($mode) {
+ case Zend_Cache::CLEANING_MODE_MATCHING_TAG:
+ case Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG:
+ if (empty($tags)) {
+ throw new Zend_Exception('Cannot use tag matching modes as no tags were defined');
+ }
+ if ($this->_tagged === null && $tagged = $this->getInnerCache()->load(self::INNER_CACHE_NAME)) {
+ $this->_tagged = $tagged;
+ } elseif (!$this->_tagged) {
+ return true;
+ }
+ foreach ($tags as $tag) {
+ $urls = array_keys($this->_tagged);
+ foreach ($urls as $url) {
+ if (isset($this->_tagged[$url]['tags']) && in_array($tag, $this->_tagged[$url]['tags'])) {
+ $this->remove($url);
+ unset($this->_tagged[$url]);
+ }
+ }
+ }
+ $this->getInnerCache()->save($this->_tagged, self::INNER_CACHE_NAME);
+ $result = true;
+ break;
+ case Zend_Cache::CLEANING_MODE_ALL:
+ if ($this->_tagged === null) {
+ $tagged = $this->getInnerCache()->load(self::INNER_CACHE_NAME);
+ $this->_tagged = $tagged;
+ }
+ if ($this->_tagged === null || empty($this->_tagged)) {
+ return true;
+ }
+ $urls = array_keys($this->_tagged);
+ foreach ($urls as $url) {
+ $this->remove($url);
+ unset($this->_tagged[$url]);
+ }
+ $this->getInnerCache()->save($this->_tagged, self::INNER_CACHE_NAME);
+ $result = true;
+ break;
+ case Zend_Cache::CLEANING_MODE_OLD:
+ $this->_log("Zend_Cache_Backend_Static : Selected Cleaning Mode Currently Unsupported By This Backend");
+ break;
+ case Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG:
+ if (empty($tags)) {
+ throw new Zend_Exception('Cannot use tag matching modes as no tags were defined');
+ }
+ if ($this->_tagged === null) {
+ $tagged = $this->getInnerCache()->load(self::INNER_CACHE_NAME);
+ $this->_tagged = $tagged;
+ }
+ if ($this->_tagged === null || empty($this->_tagged)) {
+ return true;
+ }
+ $urls = array_keys($this->_tagged);
+ foreach ($urls as $url) {
+ $difference = array_diff($tags, $this->_tagged[$url]['tags']);
+ if (count($tags) == count($difference)) {
+ $this->remove($url);
+ unset($this->_tagged[$url]);
+ }
+ }
+ $this->getInnerCache()->save($this->_tagged, self::INNER_CACHE_NAME);
+ $result = true;
+ break;
+ default:
+ Zend_Cache::throwException('Invalid mode for clean() method');
+ break;
+ }
+ return $result;
+ }
+
+ /**
+ * Set an Inner Cache, used here primarily to store Tags associated
+ * with caches created by this backend. Note: If Tags are lost, the cache
+ * should be completely cleaned as the mapping of tags to caches will
+ * have been irrevocably lost.
+ *
+ * @param Zend_Cache_Core
+ * @return void
+ */
+ public function setInnerCache(Zend_Cache_Core $cache)
+ {
+ $this->_tagCache = $cache;
+ $this->_options['tag_cache'] = $cache;
+ }
+
+ /**
+ * Get the Inner Cache if set
+ *
+ * @return Zend_Cache_Core
+ */
+ public function getInnerCache()
+ {
+ if ($this->_tagCache === null) {
+ Zend_Cache::throwException('An Inner Cache has not been set; use setInnerCache()');
+ }
+ return $this->_tagCache;
+ }
+
+ /**
+ * Verify path exists and is non-empty
+ *
+ * @param string $path
+ * @return bool
+ */
+ protected function _verifyPath($path)
+ {
+ $path = realpath($path);
+ $base = realpath($this->_options['public_dir']);
+ return strncmp($path, $base, strlen($base)) !== 0;
+ }
+
+ /**
+ * Determine the page to save from the request
+ *
+ * @return string
+ */
+ protected function _detectId()
+ {
+ return $_SERVER['REQUEST_URI'];
+ }
+
+ /**
+ * Validate a cache id or a tag (security, reliable filenames, reserved prefixes...)
+ *
+ * Throw an exception if a problem is found
+ *
+ * @param string $string Cache id or tag
+ * @throws Zend_Cache_Exception
+ * @return void
+ * @deprecated Not usable until perhaps ZF 2.0
+ */
+ protected static function _validateIdOrTag($string)
+ {
+ if (!is_string($string)) {
+ Zend_Cache::throwException('Invalid id or tag : must be a string');
+ }
+
+ // Internal only checked in Frontend - not here!
+ if (substr($string, 0, 9) == 'internal-') {
+ return;
+ }
+
+ // Validation assumes no query string, fragments or scheme included - only the path
+ if (!preg_match(
+ '/^(?:\/(?:(?:%[[:xdigit:]]{2}|[A-Za-z0-9-_.!~*\'()\[\]:@&=+$,;])*)?)+$/',
+ $string
+ )
+ ) {
+ Zend_Cache::throwException("Invalid id or tag '$string' : must be a valid URL path");
+ }
+ }
+
+ /**
+ * Detect an octal string and return its octal value for file permission ops
+ * otherwise return the non-string (assumed octal or decimal int already)
+ *
+ * @param string $val The potential octal in need of conversion
+ * @return int
+ */
+ protected function _octdec($val)
+ {
+ if (is_string($val) && decoct(octdec($val)) == $val) {
+ return octdec($val);
+ }
+ return $val;
+ }
+
+ /**
+ * Decode a request URI from the provided ID
+ *
+ * @param string $id
+ * @return string
+ */
+ protected function _decodeId($id)
+ {
+ return pack('H*', $id);
+ }
+}
diff --git a/lib/zend/Zend/Cache/Backend/Test.php b/lib/zend/Zend/Cache/Backend/Test.php
new file mode 100644
index 00000000000..d94e9734410
--- /dev/null
+++ b/lib/zend/Zend/Cache/Backend/Test.php
@@ -0,0 +1,416 @@
+_addLog('construct', array($options));
+ }
+
+ /**
+ * Set the frontend directives
+ *
+ * @param array $directives assoc of directives
+ * @return void
+ */
+ public function setDirectives($directives)
+ {
+ $this->_addLog('setDirectives', array($directives));
+ }
+
+ /**
+ * Test if a cache is available for the given id and (if yes) return it (false else)
+ *
+ * For this test backend only, if $id == 'false', then the method will return false
+ * if $id == 'serialized', the method will return a serialized array
+ * ('foo' else)
+ *
+ * @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)
+ {
+ $this->_addLog('get', array($id, $doNotTestCacheValidity));
+
+ if ( $id == 'false'
+ || $id == 'd8523b3ee441006261eeffa5c3d3a0a7'
+ || $id == 'e83249ea22178277d5befc2c5e2e9ace'
+ || $id == '40f649b94977c0a6e76902e2a0b43587'
+ || $id == '88161989b73a4cbfd0b701c446115a99'
+ || $id == '205fc79cba24f0f0018eb92c7c8b3ba4'
+ || $id == '170720e35f38150b811f68a937fb042d')
+ {
+ return false;
+ }
+ if ($id=='serialized') {
+ return serialize(array('foo'));
+ }
+ if ($id=='serialized2') {
+ return serialize(array('headers' => array(), 'data' => 'foo'));
+ }
+ if ( $id == '71769f39054f75894288e397df04e445' || $id == '615d222619fb20b527168340cebd0578'
+ || $id == '8a02d218a5165c467e7a5747cc6bd4b6' || $id == '648aca1366211d17cbf48e65dc570bee'
+ || $id == '4a923ef02d7f997ca14d56dfeae25ea7') {
+ return serialize(array('foo', 'bar'));
+ }
+ if ( $id == 'f53c7d912cc523d9a65834c8286eceb9') {
+ return serialize(array('foobar'));
+ }
+ return 'foo';
+ }
+
+ /**
+ * Test if a cache is available or not (for the given id)
+ *
+ * For this test backend only, if $id == 'false', then the method will return false
+ * (123456 else)
+ *
+ * @param string $id Cache id
+ * @return mixed|false false (a cache is not available) or "last modified" timestamp (int) of the available cache record
+ */
+ public function test($id)
+ {
+ $this->_addLog('test', array($id));
+ if ($id=='false') {
+ return false;
+ }
+ if (($id=='3c439c922209e2cb0b54d6deffccd75a')) {
+ return false;
+ }
+ return 123456;
+ }
+
+ /**
+ * Save some string datas into a cache record
+ *
+ * For this test backend only, if $id == 'false', then the method will return false
+ * (true else)
+ *
+ * @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)
+ {
+ $this->_addLog('save', array($data, $id, $tags));
+ if (substr($id,-5)=='false') {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Remove a cache record
+ *
+ * For this test backend only, if $id == 'false', then the method will return false
+ * (true else)
+ *
+ * @param string $id Cache id
+ * @return boolean True if no problem
+ */
+ public function remove($id)
+ {
+ $this->_addLog('remove', array($id));
+ if (substr($id,-5)=='false') {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Clean some cache records
+ *
+ * For this test backend only, if $mode == 'false', then the method will return false
+ * (true else)
+ *
+ * Available modes are :
+ * Zend_Cache::CLEANING_MODE_ALL (default) => remove all cache entries ($tags is not used)
+ * Zend_Cache::CLEANING_MODE_OLD => remove too old cache entries ($tags is not used)
+ * Zend_Cache::CLEANING_MODE_MATCHING_TAG => remove cache entries matching all given tags
+ * ($tags can be an array of strings or a single string)
+ * Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG => remove cache entries not {matching one of the given tags}
+ * ($tags can be an array of strings or a single string)
+ *
+ * @param string $mode Clean mode
+ * @param array $tags Array of tags
+ * @return boolean True if no problem
+ */
+ public function clean($mode = Zend_Cache::CLEANING_MODE_ALL, $tags = array())
+ {
+ $this->_addLog('clean', array($mode, $tags));
+ if ($mode=='false') {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Get the last log
+ *
+ * @return string The last log
+ */
+ public function getLastLog()
+ {
+ return $this->_log[$this->_index - 1];
+ }
+
+ /**
+ * Get the log index
+ *
+ * @return int Log index
+ */
+ public function getLogIndex()
+ {
+ return $this->_index;
+ }
+
+ /**
+ * Get the complete log array
+ *
+ * @return array Complete log array
+ */
+ public function getAllLogs()
+ {
+ return $this->_log;
+ }
+
+ /**
+ * Return true if the automatic cleaning is available for the backend
+ *
+ * @return boolean
+ */
+ public function isAutomaticCleaningAvailable()
+ {
+ return true;
+ }
+
+ /**
+ * Return an array of stored cache ids
+ *
+ * @return array array of stored cache ids (string)
+ */
+ public function getIds()
+ {
+ return array(
+ 'prefix_id1', 'prefix_id2'
+ );
+ }
+
+ /**
+ * Return an array of stored tags
+ *
+ * @return array array of stored tags (string)
+ */
+ public function getTags()
+ {
+ return array(
+ 'tag1', 'tag2'
+ );
+ }
+
+ /**
+ * 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())
+ {
+ if ($tags == array('tag1', 'tag2')) {
+ return array('prefix_id1', 'prefix_id2');
+ }
+
+ 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())
+ {
+ if ($tags == array('tag3', 'tag4')) {
+ return array('prefix_id3', 'prefix_id4');
+ }
+
+ 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())
+ {
+ if ($tags == array('tag5', 'tag6')) {
+ return array('prefix_id5', 'prefix_id6');
+ }
+
+ return array();
+ }
+
+ /**
+ * Return the filling percentage of the backend storage
+ *
+ * @return int integer between 0 and 100
+ */
+ public function getFillingPercentage()
+ {
+ return 50;
+ }
+
+ /**
+ * 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)
+ {
+ 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)
+ {
+ return true;
+ }
+
+ /**
+ * 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' => true,
+ 'tags' => true,
+ 'expired_read' => false,
+ 'priority' => true,
+ 'infinite_lifetime' => true,
+ 'get_list' => true
+ );
+ }
+
+ /**
+ * Add an event to the log array
+ *
+ * @param string $methodName MethodName
+ * @param array $args Arguments
+ * @return void
+ */
+ private function _addLog($methodName, $args)
+ {
+ $this->_log[$this->_index] = array(
+ 'methodName' => $methodName,
+ 'args' => $args
+ );
+ $this->_index = $this->_index + 1;
+ }
+
+}
diff --git a/lib/zend/Zend/Cache/Backend/TwoLevels.php b/lib/zend/Zend/Cache/Backend/TwoLevels.php
new file mode 100644
index 00000000000..135ff6ad8de
--- /dev/null
+++ b/lib/zend/Zend/Cache/Backend/TwoLevels.php
@@ -0,0 +1,548 @@
+ (string) slow_backend :
+ * - Slow backend name
+ * - Must implement the Zend_Cache_Backend_ExtendedInterface
+ * - Should provide a big storage
+ *
+ * =====> (string) fast_backend :
+ * - Flow backend name
+ * - Must implement the Zend_Cache_Backend_ExtendedInterface
+ * - Must be much faster than slow_backend
+ *
+ * =====> (array) slow_backend_options :
+ * - Slow backend options (see corresponding backend)
+ *
+ * =====> (array) fast_backend_options :
+ * - Fast backend options (see corresponding backend)
+ *
+ * =====> (int) stats_update_factor :
+ * - Disable / Tune the computation of the fast backend filling percentage
+ * - When saving a record into cache :
+ * 1 => systematic computation of the fast backend filling percentage
+ * x (integer) > 1 => computation of the fast backend filling percentage randomly 1 times on x cache write
+ *
+ * =====> (boolean) slow_backend_custom_naming :
+ * =====> (boolean) fast_backend_custom_naming :
+ * =====> (boolean) slow_backend_autoload :
+ * =====> (boolean) fast_backend_autoload :
+ * - See Zend_Cache::factory() method
+ *
+ * =====> (boolean) auto_fill_fast_cache
+ * - If true, automatically fill the fast cache when a cache record was not found in fast cache, but did
+ * exist in slow cache. This can be usefull when a non-persistent cache like APC or Memcached got
+ * purged for whatever reason.
+ *
+ * =====> (boolean) auto_refresh_fast_cache
+ * - If true, auto refresh the fast cache when a cache record is hit
+ *
+ * @var array available options
+ */
+ protected $_options = array(
+ 'slow_backend' => 'File',
+ 'fast_backend' => 'Apc',
+ 'slow_backend_options' => array(),
+ 'fast_backend_options' => array(),
+ 'stats_update_factor' => 10,
+ 'slow_backend_custom_naming' => false,
+ 'fast_backend_custom_naming' => false,
+ 'slow_backend_autoload' => false,
+ 'fast_backend_autoload' => false,
+ 'auto_fill_fast_cache' => true,
+ 'auto_refresh_fast_cache' => true
+ );
+
+ /**
+ * Slow Backend
+ *
+ * @var Zend_Cache_Backend_ExtendedInterface
+ */
+ protected $_slowBackend;
+
+ /**
+ * Fast Backend
+ *
+ * @var Zend_Cache_Backend_ExtendedInterface
+ */
+ protected $_fastBackend;
+
+ /**
+ * Cache for the fast backend filling percentage
+ *
+ * @var int
+ */
+ protected $_fastBackendFillingPercentage = null;
+
+ /**
+ * Constructor
+ *
+ * @param array $options Associative array of options
+ * @throws Zend_Cache_Exception
+ * @return void
+ */
+ public function __construct(array $options = array())
+ {
+ parent::__construct($options);
+
+ if ($this->_options['slow_backend'] === null) {
+ Zend_Cache::throwException('slow_backend option has to set');
+ } elseif ($this->_options['slow_backend'] instanceof Zend_Cache_Backend_ExtendedInterface) {
+ $this->_slowBackend = $this->_options['slow_backend'];
+ } else {
+ $this->_slowBackend = Zend_Cache::_makeBackend(
+ $this->_options['slow_backend'],
+ $this->_options['slow_backend_options'],
+ $this->_options['slow_backend_custom_naming'],
+ $this->_options['slow_backend_autoload']
+ );
+ if (!in_array('Zend_Cache_Backend_ExtendedInterface', class_implements($this->_slowBackend))) {
+ Zend_Cache::throwException('slow_backend must implement the Zend_Cache_Backend_ExtendedInterface interface');
+ }
+ }
+
+ if ($this->_options['fast_backend'] === null) {
+ Zend_Cache::throwException('fast_backend option has to set');
+ } elseif ($this->_options['fast_backend'] instanceof Zend_Cache_Backend_ExtendedInterface) {
+ $this->_fastBackend = $this->_options['fast_backend'];
+ } else {
+ $this->_fastBackend = Zend_Cache::_makeBackend(
+ $this->_options['fast_backend'],
+ $this->_options['fast_backend_options'],
+ $this->_options['fast_backend_custom_naming'],
+ $this->_options['fast_backend_autoload']
+ );
+ if (!in_array('Zend_Cache_Backend_ExtendedInterface', class_implements($this->_fastBackend))) {
+ Zend_Cache::throwException('fast_backend must implement the Zend_Cache_Backend_ExtendedInterface interface');
+ }
+ }
+
+ $this->_slowBackend->setDirectives($this->_directives);
+ $this->_fastBackend->setDirectives($this->_directives);
+ }
+
+ /**
+ * 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)
+ {
+ $fastTest = $this->_fastBackend->test($id);
+ if ($fastTest) {
+ return $fastTest;
+ } else {
+ return $this->_slowBackend->test($id);
+ }
+ }
+
+ /**
+ * 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)
+ * @param int $priority integer between 0 (very low priority) and 10 (maximum priority) used by some particular backends
+ * @return boolean true if no problem
+ */
+ public function save($data, $id, $tags = array(), $specificLifetime = false, $priority = 8)
+ {
+ $usage = $this->_getFastFillingPercentage('saving');
+ $boolFast = true;
+ $lifetime = $this->getLifetime($specificLifetime);
+ $preparedData = $this->_prepareData($data, $lifetime, $priority);
+ if (($priority > 0) && (10 * $priority >= $usage)) {
+ $fastLifetime = $this->_getFastLifetime($lifetime, $priority);
+ $boolFast = $this->_fastBackend->save($preparedData, $id, array(), $fastLifetime);
+ $boolSlow = $this->_slowBackend->save($preparedData, $id, $tags, $lifetime);
+ } else {
+ $boolSlow = $this->_slowBackend->save($preparedData, $id, $tags, $lifetime);
+ if ($boolSlow === true) {
+ $boolFast = $this->_fastBackend->remove($id);
+ if (!$boolFast && !$this->_fastBackend->test($id)) {
+ // some backends return false on remove() even if the key never existed. (and it won't if fast is full)
+ // all we care about is that the key doesn't exist now
+ $boolFast = true;
+ }
+ }
+ }
+
+ return ($boolFast && $boolSlow);
+ }
+
+ /**
+ * Test if a cache is available for the given id and (if yes) return it (false else)
+ *
+ * Note : return value is always "string" (unserialization is done by the core not by the backend)
+ *
+ * @param string $id Cache id
+ * @param boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested
+ * @return string|false cached datas
+ */
+ public function load($id, $doNotTestCacheValidity = false)
+ {
+ $resultFast = $this->_fastBackend->load($id, $doNotTestCacheValidity);
+ if ($resultFast === false) {
+ $resultSlow = $this->_slowBackend->load($id, $doNotTestCacheValidity);
+ if ($resultSlow === false) {
+ // there is no cache at all for this id
+ return false;
+ }
+ }
+ $array = $resultFast !== false ? unserialize($resultFast) : unserialize($resultSlow);
+
+ //In case no cache entry was found in the FastCache and auto-filling is enabled, copy data to FastCache
+ if ($resultFast === false && $this->_options['auto_fill_fast_cache']) {
+ $preparedData = $this->_prepareData($array['data'], $array['lifetime'], $array['priority']);
+ $this->_fastBackend->save($preparedData, $id, array(), $array['lifetime']);
+ }
+ // maybe, we have to refresh the fast cache ?
+ elseif ($this->_options['auto_refresh_fast_cache']) {
+ if ($array['priority'] == 10) {
+ // no need to refresh the fast cache with priority = 10
+ return $array['data'];
+ }
+ $newFastLifetime = $this->_getFastLifetime($array['lifetime'], $array['priority'], time() - $array['expire']);
+ // we have the time to refresh the fast cache
+ $usage = $this->_getFastFillingPercentage('loading');
+ if (($array['priority'] > 0) && (10 * $array['priority'] >= $usage)) {
+ // we can refresh the fast cache
+ $preparedData = $this->_prepareData($array['data'], $array['lifetime'], $array['priority']);
+ $this->_fastBackend->save($preparedData, $id, array(), $newFastLifetime);
+ }
+ }
+ return $array['data'];
+ }
+
+ /**
+ * Remove a cache record
+ *
+ * @param string $id Cache id
+ * @return boolean True if no problem
+ */
+ public function remove($id)
+ {
+ $boolFast = $this->_fastBackend->remove($id);
+ $boolSlow = $this->_slowBackend->remove($id);
+ return $boolFast && $boolSlow;
+ }
+
+ /**
+ * Clean some cache records
+ *
+ * Available modes are :
+ * Zend_Cache::CLEANING_MODE_ALL (default) => remove all cache entries ($tags is not used)
+ * Zend_Cache::CLEANING_MODE_OLD => remove too old cache entries ($tags is not used)
+ * Zend_Cache::CLEANING_MODE_MATCHING_TAG => remove cache entries matching all given tags
+ * ($tags can be an array of strings or a single string)
+ * Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG => remove cache entries not {matching one of the given tags}
+ * ($tags can be an array of strings or a single string)
+ * Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG => remove cache entries matching any given tags
+ * ($tags can be an array of strings or a single string)
+ *
+ * @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:
+ $boolFast = $this->_fastBackend->clean(Zend_Cache::CLEANING_MODE_ALL);
+ $boolSlow = $this->_slowBackend->clean(Zend_Cache::CLEANING_MODE_ALL);
+ return $boolFast && $boolSlow;
+ break;
+ case Zend_Cache::CLEANING_MODE_OLD:
+ return $this->_slowBackend->clean(Zend_Cache::CLEANING_MODE_OLD);
+ case Zend_Cache::CLEANING_MODE_MATCHING_TAG:
+ $ids = $this->_slowBackend->getIdsMatchingTags($tags);
+ $res = true;
+ foreach ($ids as $id) {
+ $bool = $this->remove($id);
+ $res = $res && $bool;
+ }
+ return $res;
+ break;
+ case Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG:
+ $ids = $this->_slowBackend->getIdsNotMatchingTags($tags);
+ $res = true;
+ foreach ($ids as $id) {
+ $bool = $this->remove($id);
+ $res = $res && $bool;
+ }
+ return $res;
+ break;
+ case Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG:
+ $ids = $this->_slowBackend->getIdsMatchingAnyTags($tags);
+ $res = true;
+ foreach ($ids as $id) {
+ $bool = $this->remove($id);
+ $res = $res && $bool;
+ }
+ return $res;
+ break;
+ default:
+ Zend_Cache::throwException('Invalid mode for clean() method');
+ break;
+ }
+ }
+
+ /**
+ * Return an array of stored cache ids
+ *
+ * @return array array of stored cache ids (string)
+ */
+ public function getIds()
+ {
+ return $this->_slowBackend->getIds();
+ }
+
+ /**
+ * Return an array of stored tags
+ *
+ * @return array array of stored tags (string)
+ */
+ public function getTags()
+ {
+ return $this->_slowBackend->getTags();
+ }
+
+ /**
+ * 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())
+ {
+ return $this->_slowBackend->getIdsMatchingTags($tags);
+ }
+
+ /**
+ * 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())
+ {
+ return $this->_slowBackend->getIdsNotMatchingTags($tags);
+ }
+
+ /**
+ * 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())
+ {
+ return $this->_slowBackend->getIdsMatchingAnyTags($tags);
+ }
+
+ /**
+ * Return the filling percentage of the backend storage
+ *
+ * @return int integer between 0 and 100
+ */
+ public function getFillingPercentage()
+ {
+ return $this->_slowBackend->getFillingPercentage();
+ }
+
+ /**
+ * 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)
+ {
+ return $this->_slowBackend->getMetadatas($id);
+ }
+
+ /**
+ * 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)
+ {
+ return $this->_slowBackend->touch($id, $extraLifetime);
+ }
+
+ /**
+ * 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()
+ {
+ $slowBackendCapabilities = $this->_slowBackend->getCapabilities();
+ return array(
+ 'automatic_cleaning' => $slowBackendCapabilities['automatic_cleaning'],
+ 'tags' => $slowBackendCapabilities['tags'],
+ 'expired_read' => $slowBackendCapabilities['expired_read'],
+ 'priority' => $slowBackendCapabilities['priority'],
+ 'infinite_lifetime' => $slowBackendCapabilities['infinite_lifetime'],
+ 'get_list' => $slowBackendCapabilities['get_list']
+ );
+ }
+
+ /**
+ * Prepare a serialized array to store datas and metadatas informations
+ *
+ * @param string $data data to store
+ * @param int $lifetime original lifetime
+ * @param int $priority priority
+ * @return string serialize array to store into cache
+ */
+ private function _prepareData($data, $lifetime, $priority)
+ {
+ $lt = $lifetime;
+ if ($lt === null) {
+ $lt = 9999999999;
+ }
+ return serialize(array(
+ 'data' => $data,
+ 'lifetime' => $lifetime,
+ 'expire' => time() + $lt,
+ 'priority' => $priority
+ ));
+ }
+
+ /**
+ * Compute and return the lifetime for the fast backend
+ *
+ * @param int $lifetime original lifetime
+ * @param int $priority priority
+ * @param int $maxLifetime maximum lifetime
+ * @return int lifetime for the fast backend
+ */
+ private function _getFastLifetime($lifetime, $priority, $maxLifetime = null)
+ {
+ if ($lifetime <= 0) {
+ // if no lifetime, we have an infinite lifetime
+ // we need to use arbitrary lifetimes
+ $fastLifetime = (int) (2592000 / (11 - $priority));
+ } else {
+ // prevent computed infinite lifetime (0) by ceil
+ $fastLifetime = (int) ceil($lifetime / (11 - $priority));
+ }
+
+ if ($maxLifetime >= 0 && $fastLifetime > $maxLifetime) {
+ return $maxLifetime;
+ }
+
+ return $fastLifetime;
+ }
+
+ /**
+ * PUBLIC METHOD FOR UNIT TESTING ONLY !
+ *
+ * Force a cache record to expire
+ *
+ * @param string $id cache id
+ */
+ public function ___expire($id)
+ {
+ $this->_fastBackend->remove($id);
+ $this->_slowBackend->___expire($id);
+ }
+
+ private function _getFastFillingPercentage($mode)
+ {
+
+ if ($mode == 'saving') {
+ // mode saving
+ if ($this->_fastBackendFillingPercentage === null) {
+ $this->_fastBackendFillingPercentage = $this->_fastBackend->getFillingPercentage();
+ } else {
+ $rand = rand(1, $this->_options['stats_update_factor']);
+ if ($rand == 1) {
+ // we force a refresh
+ $this->_fastBackendFillingPercentage = $this->_fastBackend->getFillingPercentage();
+ }
+ }
+ } else {
+ // mode loading
+ // we compute the percentage only if it's not available in cache
+ if ($this->_fastBackendFillingPercentage === null) {
+ $this->_fastBackendFillingPercentage = $this->_fastBackend->getFillingPercentage();
+ }
+ }
+ return $this->_fastBackendFillingPercentage;
+ }
+
+}
diff --git a/lib/zend/Zend/Cache/Backend/WinCache.php b/lib/zend/Zend/Cache/Backend/WinCache.php
new file mode 100644
index 00000000000..06843fa39af
--- /dev/null
+++ b/lib/zend/Zend/Cache/Backend/WinCache.php
@@ -0,0 +1,349 @@
+ 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
+ );
+ }
+
+}
diff --git a/lib/zend/Zend/Cache/Backend/Xcache.php b/lib/zend/Zend/Cache/Backend/Xcache.php
new file mode 100644
index 00000000000..4bc077fc923
--- /dev/null
+++ b/lib/zend/Zend/Cache/Backend/Xcache.php
@@ -0,0 +1,221 @@
+ (string) user :
+ * xcache.admin.user (necessary for the clean() method)
+ *
+ * =====> (string) password :
+ * xcache.admin.pass (clear, not MD5) (necessary for the clean() method)
+ *
+ * @var array available options
+ */
+ protected $_options = array(
+ 'user' => null,
+ 'password' => null
+ );
+
+ /**
+ * Constructor
+ *
+ * @param array $options associative array of options
+ * @throws Zend_Cache_Exception
+ * @return void
+ */
+ public function __construct(array $options = array())
+ {
+ if (!extension_loaded('xcache')) {
+ Zend_Cache::throwException('The xcache 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 Xcache 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)
+ {
+ if ($doNotTestCacheValidity) {
+ $this->_log("Zend_Cache_Backend_Xcache::load() : \$doNotTestCacheValidity=true is unsupported by the Xcache backend");
+ }
+ $tmp = xcache_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)
+ {
+ if (xcache_isset($id)) {
+ $tmp = xcache_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 = xcache_set($id, array($data, time()), $lifetime);
+ if (count($tags) > 0) {
+ $this->_log(self::TAGS_UNSUPPORTED_BY_SAVE_OF_XCACHE_BACKEND);
+ }
+ return $result;
+ }
+
+ /**
+ * Remove a cache record
+ *
+ * @param string $id cache id
+ * @return boolean true if no problem
+ */
+ public function remove($id)
+ {
+ return xcache_unset($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:
+ // Necessary because xcache_clear_cache() need basic authentification
+ $backup = array();
+ if (isset($_SERVER['PHP_AUTH_USER'])) {
+ $backup['PHP_AUTH_USER'] = $_SERVER['PHP_AUTH_USER'];
+ }
+ if (isset($_SERVER['PHP_AUTH_PW'])) {
+ $backup['PHP_AUTH_PW'] = $_SERVER['PHP_AUTH_PW'];
+ }
+ if ($this->_options['user']) {
+ $_SERVER['PHP_AUTH_USER'] = $this->_options['user'];
+ }
+ if ($this->_options['password']) {
+ $_SERVER['PHP_AUTH_PW'] = $this->_options['password'];
+ }
+
+ $cnt = xcache_count(XC_TYPE_VAR);
+ for ($i=0; $i < $cnt; $i++) {
+ xcache_clear_cache(XC_TYPE_VAR, $i);
+ }
+
+ if (isset($backup['PHP_AUTH_USER'])) {
+ $_SERVER['PHP_AUTH_USER'] = $backup['PHP_AUTH_USER'];
+ $_SERVER['PHP_AUTH_PW'] = $backup['PHP_AUTH_PW'];
+ }
+ return true;
+ break;
+ case Zend_Cache::CLEANING_MODE_OLD:
+ $this->_log("Zend_Cache_Backend_Xcache::clean() : CLEANING_MODE_OLD is unsupported by the Xcache 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_XCACHE_BACKEND);
+ break;
+ default:
+ Zend_Cache::throwException('Invalid mode for clean() method');
+ break;
+ }
+ }
+
+ /**
+ * Return true if the automatic cleaning is available for the backend
+ *
+ * @return boolean
+ */
+ public function isAutomaticCleaningAvailable()
+ {
+ return false;
+ }
+
+}
diff --git a/lib/zend/Zend/Cache/Backend/ZendPlatform.php b/lib/zend/Zend/Cache/Backend/ZendPlatform.php
new file mode 100644
index 00000000000..31e9a7a22af
--- /dev/null
+++ b/lib/zend/Zend/Cache/Backend/ZendPlatform.php
@@ -0,0 +1,317 @@
+_directives['lifetime'];
+ }
+ $res = output_cache_get($id, $lifetime);
+ if($res) {
+ return $res[0];
+ } else {
+ return false;
+ }
+ }
+
+
+ /**
+ * Test if a cache is available or not (for the given id)
+ *
+ * @param string $id Cache id
+ * @return mixed|false false (a cache is not available) or "last modified" timestamp (int) of the available cache record
+ */
+ public function test($id)
+ {
+ $result = output_cache_get($id, $this->_directives['lifetime']);
+ if ($result) {
+ return $result[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 Data 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)
+ {
+ if (!($specificLifetime === false)) {
+ $this->_log("Zend_Cache_Backend_ZendPlatform::save() : non false specifc lifetime is unsuported for this backend");
+ }
+
+ $lifetime = $this->_directives['lifetime'];
+ $result1 = output_cache_put($id, array($data, time()));
+ $result2 = (count($tags) == 0);
+
+ foreach ($tags as $tag) {
+ $tagid = self::TAGS_PREFIX.$tag;
+ $old_tags = output_cache_get($tagid, $lifetime);
+ if ($old_tags === false) {
+ $old_tags = array();
+ }
+ $old_tags[$id] = $id;
+ output_cache_remove_key($tagid);
+ $result2 = output_cache_put($tagid, $old_tags);
+ }
+
+ return $result1 && $result2;
+ }
+
+
+ /**
+ * Remove a cache record
+ *
+ * @param string $id Cache id
+ * @return boolean True if no problem
+ */
+ public function remove($id)
+ {
+ return output_cache_remove_key($id);
+ }
+
+
+ /**
+ * Clean some cache records
+ *
+ * Available modes are :
+ * Zend_Cache::CLEANING_MODE_ALL (default) => remove all cache entries ($tags is not used)
+ * Zend_Cache::CLEANING_MODE_OLD => remove too old cache entries ($tags is not used)
+ * This mode is not supported in this backend
+ * Zend_Cache::CLEANING_MODE_MATCHING_TAG => remove cache entries matching all given tags
+ * ($tags can be an array of strings or a single string)
+ * Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG => unsupported
+ * Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG => remove cache entries matching any given tags
+ * ($tags can be an array of strings or a single string)
+ *
+ * @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:
+ case Zend_Cache::CLEANING_MODE_OLD:
+ $cache_dir = ini_get('zend_accelerator.output_cache_dir');
+ if (!$cache_dir) {
+ return false;
+ }
+ $cache_dir .= '/.php_cache_api/';
+ return $this->_clean($cache_dir, $mode);
+ break;
+ case Zend_Cache::CLEANING_MODE_MATCHING_TAG:
+ $idlist = null;
+ foreach ($tags as $tag) {
+ $next_idlist = output_cache_get(self::TAGS_PREFIX.$tag, $this->_directives['lifetime']);
+ if ($idlist) {
+ $idlist = array_intersect_assoc($idlist, $next_idlist);
+ } else {
+ $idlist = $next_idlist;
+ }
+ if (count($idlist) == 0) {
+ // if ID list is already empty - we may skip checking other IDs
+ $idlist = null;
+ break;
+ }
+ }
+ if ($idlist) {
+ foreach ($idlist as $id) {
+ output_cache_remove_key($id);
+ }
+ }
+ return true;
+ break;
+ case Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG:
+ $this->_log("Zend_Cache_Backend_ZendPlatform::clean() : CLEANING_MODE_NOT_MATCHING_TAG is not supported by the Zend Platform backend");
+ return false;
+ break;
+ case Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG:
+ $idlist = null;
+ foreach ($tags as $tag) {
+ $next_idlist = output_cache_get(self::TAGS_PREFIX.$tag, $this->_directives['lifetime']);
+ if ($idlist) {
+ $idlist = array_merge_recursive($idlist, $next_idlist);
+ } else {
+ $idlist = $next_idlist;
+ }
+ if (count($idlist) == 0) {
+ // if ID list is already empty - we may skip checking other IDs
+ $idlist = null;
+ break;
+ }
+ }
+ if ($idlist) {
+ foreach ($idlist as $id) {
+ output_cache_remove_key($id);
+ }
+ }
+ return true;
+ break;
+ default:
+ Zend_Cache::throwException('Invalid mode for clean() method');
+ break;
+ }
+ }
+
+ /**
+ * Clean a directory and recursivly go over it's subdirectories
+ *
+ * Remove all the cached files that need to be cleaned (according to mode and files mtime)
+ *
+ * @param string $dir Path of directory ot clean
+ * @param string $mode The same parameter as in Zend_Cache_Backend_ZendPlatform::clean()
+ * @return boolean True if ok
+ */
+ private function _clean($dir, $mode)
+ {
+ $d = @dir($dir);
+ if (!$d) {
+ return false;
+ }
+ $result = true;
+ while (false !== ($file = $d->read())) {
+ if ($file == '.' || $file == '..') {
+ continue;
+ }
+ $file = $d->path . $file;
+ if (is_dir($file)) {
+ $result = ($this->_clean($file .'/', $mode)) && ($result);
+ } else {
+ if ($mode == Zend_Cache::CLEANING_MODE_ALL) {
+ $result = ($this->_remove($file)) && ($result);
+ } else if ($mode == Zend_Cache::CLEANING_MODE_OLD) {
+ // Files older than lifetime get deleted from cache
+ if ($this->_directives['lifetime'] !== null) {
+ if ((time() - @filemtime($file)) > $this->_directives['lifetime']) {
+ $result = ($this->_remove($file)) && ($result);
+ }
+ }
+ }
+ }
+ }
+ $d->close();
+ return $result;
+ }
+
+ /**
+ * Remove a file
+ *
+ * If we can't remove the file (because of locks or any problem), we will touch
+ * the file to invalidate it
+ *
+ * @param string $file Complete file path
+ * @return boolean True if ok
+ */
+ private function _remove($file)
+ {
+ if (!@unlink($file)) {
+ # If we can't remove the file (because of locks or any problem), we will touch
+ # the file to invalidate it
+ $this->_log("Zend_Cache_Backend_ZendPlatform::_remove() : we can't remove $file => we are going to try to invalidate it");
+ if ($this->_directives['lifetime'] === null) {
+ return false;
+ }
+ if (!file_exists($file)) {
+ return false;
+ }
+ return @touch($file, time() - 2*abs($this->_directives['lifetime']));
+ }
+ return true;
+ }
+
+}
diff --git a/lib/zend/Zend/Cache/Backend/ZendServer.php b/lib/zend/Zend/Cache/Backend/ZendServer.php
new file mode 100755
index 00000000000..ededaf5a9bc
--- /dev/null
+++ b/lib/zend/Zend/Cache/Backend/ZendServer.php
@@ -0,0 +1,207 @@
+ (string) namespace :
+ * Namespace to be used for chaching operations
+ *
+ * @var array available options
+ */
+ protected $_options = array(
+ 'namespace' => 'zendframework'
+ );
+
+ /**
+ * Store data
+ *
+ * @param mixed $data Object to store
+ * @param string $id Cache id
+ * @param int $timeToLive Time to live in seconds
+ * @throws Zend_Cache_Exception
+ */
+ abstract protected function _store($data, $id, $timeToLive);
+
+ /**
+ * Fetch data
+ *
+ * @param string $id Cache id
+ * @throws Zend_Cache_Exception
+ */
+ abstract protected function _fetch($id);
+
+ /**
+ * Unset data
+ *
+ * @param string $id Cache id
+ */
+ abstract protected function _unset($id);
+
+ /**
+ * Clear cache
+ */
+ abstract protected function _clear();
+
+ /**
+ * Test if a cache is available for the given id and (if yes) return it (false else)
+ *
+ * @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 = $this->_fetch($id);
+ if ($tmp !== null) {
+ return $tmp;
+ }
+ 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
+ * @throws Zend_Cache_Exception
+ */
+ public function test($id)
+ {
+ $tmp = $this->_fetch('internal-metadatas---' . $id);
+ if ($tmp !== false) {
+ if (!is_array($tmp) || !isset($tmp['mtime'])) {
+ Zend_Cache::throwException('Cache metadata for \'' . $id . '\' id is corrupted' );
+ }
+ return $tmp['mtime'];
+ }
+ return false;
+ }
+
+ /**
+ * Compute & return the expire time
+ *
+ * @return int expire time (unix timestamp)
+ */
+ private function _expireTime($lifetime)
+ {
+ if ($lifetime === null) {
+ return 9999999999;
+ }
+ return time() + $lifetime;
+ }
+
+ /**
+ * 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);
+ $metadatas = array(
+ 'mtime' => time(),
+ 'expire' => $this->_expireTime($lifetime),
+ );
+
+ if (count($tags) > 0) {
+ $this->_log('Zend_Cache_Backend_ZendServer::save() : tags are unsupported by the ZendServer backends');
+ }
+
+ return $this->_store($data, $id, $lifetime) &&
+ $this->_store($metadatas, 'internal-metadatas---' . $id, $lifetime);
+ }
+
+ /**
+ * Remove a cache record
+ *
+ * @param string $id cache id
+ * @return boolean true if no problem
+ */
+ public function remove($id)
+ {
+ $result1 = $this->_unset($id);
+ $result2 = $this->_unset('internal-metadatas---' . $id);
+
+ return $result1 && $result2;
+ }
+
+ /**
+ * 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:
+ $this->_clear();
+ return true;
+ break;
+ case Zend_Cache::CLEANING_MODE_OLD:
+ $this->_log("Zend_Cache_Backend_ZendServer::clean() : CLEANING_MODE_OLD is unsupported by the Zend Server backends.");
+ 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->_clear();
+ $this->_log('Zend_Cache_Backend_ZendServer::clean() : tags are unsupported by the Zend Server backends.');
+ break;
+ default:
+ Zend_Cache::throwException('Invalid mode for clean() method');
+ break;
+ }
+ }
+}
diff --git a/lib/zend/Zend/Cache/Backend/ZendServer/Disk.php b/lib/zend/Zend/Cache/Backend/ZendServer/Disk.php
new file mode 100755
index 00000000000..54914fefff4
--- /dev/null
+++ b/lib/zend/Zend/Cache/Backend/ZendServer/Disk.php
@@ -0,0 +1,101 @@
+_options['namespace'] . '::' . $id,
+ $data,
+ $timeToLive) === false) {
+ $this->_log('Store operation failed.');
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Fetch data
+ *
+ * @param string $id Cache id
+ * @return mixed|null
+ */
+ protected function _fetch($id)
+ {
+ return zend_disk_cache_fetch($this->_options['namespace'] . '::' . $id);
+ }
+
+ /**
+ * Unset data
+ *
+ * @param string $id Cache id
+ * @return boolean true if no problem
+ */
+ protected function _unset($id)
+ {
+ return zend_disk_cache_delete($this->_options['namespace'] . '::' . $id);
+ }
+
+ /**
+ * Clear cache
+ */
+ protected function _clear()
+ {
+ zend_disk_cache_clear($this->_options['namespace']);
+ }
+}
diff --git a/lib/zend/Zend/Cache/Backend/ZendServer/ShMem.php b/lib/zend/Zend/Cache/Backend/ZendServer/ShMem.php
new file mode 100755
index 00000000000..83086dcd4ea
--- /dev/null
+++ b/lib/zend/Zend/Cache/Backend/ZendServer/ShMem.php
@@ -0,0 +1,101 @@
+_options['namespace'] . '::' . $id,
+ $data,
+ $timeToLive) === false) {
+ $this->_log('Store operation failed.');
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Fetch data
+ *
+ * @param string $id Cache id
+ * @return mixed|null
+ */
+ protected function _fetch($id)
+ {
+ return zend_shm_cache_fetch($this->_options['namespace'] . '::' . $id);
+ }
+
+ /**
+ * Unset data
+ *
+ * @param string $id Cache id
+ * @return boolean true if no problem
+ */
+ protected function _unset($id)
+ {
+ return zend_shm_cache_delete($this->_options['namespace'] . '::' . $id);
+ }
+
+ /**
+ * Clear cache
+ */
+ protected function _clear()
+ {
+ zend_shm_cache_clear($this->_options['namespace']);
+ }
+}
diff --git a/lib/zend/Zend/Cache/Core.php b/lib/zend/Zend/Cache/Core.php
new file mode 100644
index 00000000000..685d5d52b65
--- /dev/null
+++ b/lib/zend/Zend/Cache/Core.php
@@ -0,0 +1,765 @@
+ (boolean) write_control :
+ * - Enable / disable write control (the cache is read just after writing to detect corrupt entries)
+ * - Enable write control will lightly slow the cache writing but not the cache reading
+ * Write control can detect some corrupt cache files but maybe it's not a perfect control
+ *
+ * ====> (boolean) caching :
+ * - Enable / disable caching
+ * (can be very useful for the debug of cached scripts)
+ *
+ * =====> (string) cache_id_prefix :
+ * - prefix for cache ids (namespace)
+ *
+ * ====> (boolean) automatic_serialization :
+ * - Enable / disable automatic serialization
+ * - It can be used to save directly datas which aren't strings (but it's slower)
+ *
+ * ====> (int) automatic_cleaning_factor :
+ * - Disable / Tune the automatic cleaning process
+ * - The automatic cleaning process destroy too old (for the given life time)
+ * cache files when a new cache file is written :
+ * 0 => no automatic cache cleaning
+ * 1 => systematic cache cleaning
+ * x (integer) > 1 => automatic cleaning randomly 1 times on x cache write
+ *
+ * ====> (int) lifetime :
+ * - Cache lifetime (in seconds)
+ * - If null, the cache is valid forever.
+ *
+ * ====> (boolean) logging :
+ * - If set to true, logging is activated (but the system is slower)
+ *
+ * ====> (boolean) ignore_user_abort
+ * - If set to true, the core will set the ignore_user_abort PHP flag inside the
+ * save() method to avoid cache corruptions in some cases (default false)
+ *
+ * @var array $_options available options
+ */
+ protected $_options = array(
+ 'write_control' => true,
+ 'caching' => true,
+ 'cache_id_prefix' => null,
+ 'automatic_serialization' => false,
+ 'automatic_cleaning_factor' => 10,
+ 'lifetime' => 3600,
+ 'logging' => false,
+ 'logger' => null,
+ 'ignore_user_abort' => false
+ );
+
+ /**
+ * Array of options which have to be transfered to backend
+ *
+ * @var array $_directivesList
+ */
+ protected static $_directivesList = array('lifetime', 'logging', 'logger');
+
+ /**
+ * Not used for the core, just a sort a hint to get a common setOption() method (for the core and for frontends)
+ *
+ * @var array $_specificOptions
+ */
+ protected $_specificOptions = array();
+
+ /**
+ * Last used cache id
+ *
+ * @var string $_lastId
+ */
+ private $_lastId = null;
+
+ /**
+ * True if the backend implements Zend_Cache_Backend_ExtendedInterface
+ *
+ * @var boolean $_extendedBackend
+ */
+ protected $_extendedBackend = false;
+
+ /**
+ * Array of capabilities of the backend (only if it implements Zend_Cache_Backend_ExtendedInterface)
+ *
+ * @var array
+ */
+ protected $_backendCapabilities = array();
+
+ /**
+ * Constructor
+ *
+ * @param array|Zend_Config $options Associative array of options or Zend_Config instance
+ * @throws Zend_Cache_Exception
+ * @return void
+ */
+ public function __construct($options = array())
+ {
+ if ($options instanceof Zend_Config) {
+ $options = $options->toArray();
+ }
+ if (!is_array($options)) {
+ Zend_Cache::throwException("Options passed were not an array"
+ . " or Zend_Config instance.");
+ }
+ foreach ($options as $name => $value) {
+ $this->setOption($name, $value);
+ }
+ $this->_loggerSanity();
+ }
+
+ /**
+ * Set options using an instance of type Zend_Config
+ *
+ * @param Zend_Config $config
+ * @return Zend_Cache_Core
+ */
+ public function setConfig(Zend_Config $config)
+ {
+ $options = $config->toArray();
+ foreach ($options as $name => $value) {
+ $this->setOption($name, $value);
+ }
+ return $this;
+ }
+
+ /**
+ * Set the backend
+ *
+ * @param Zend_Cache_Backend $backendObject
+ * @throws Zend_Cache_Exception
+ * @return void
+ */
+ public function setBackend(Zend_Cache_Backend $backendObject)
+ {
+ $this->_backend= $backendObject;
+ // some options (listed in $_directivesList) have to be given
+ // to the backend too (even if they are not "backend specific")
+ $directives = array();
+ foreach (Zend_Cache_Core::$_directivesList as $directive) {
+ $directives[$directive] = $this->_options[$directive];
+ }
+ $this->_backend->setDirectives($directives);
+ if (in_array('Zend_Cache_Backend_ExtendedInterface', class_implements($this->_backend))) {
+ $this->_extendedBackend = true;
+ $this->_backendCapabilities = $this->_backend->getCapabilities();
+ }
+
+ }
+
+ /**
+ * Returns the backend
+ *
+ * @return Zend_Cache_Backend backend object
+ */
+ public function getBackend()
+ {
+ return $this->_backend;
+ }
+
+ /**
+ * Public frontend to set an option
+ *
+ * There is an additional validation (relatively to the protected _setOption method)
+ *
+ * @param string $name Name of the option
+ * @param mixed $value Value of the option
+ * @throws Zend_Cache_Exception
+ * @return void
+ */
+ public function setOption($name, $value)
+ {
+ if (!is_string($name)) {
+ Zend_Cache::throwException("Incorrect option name!");
+ }
+ $name = strtolower($name);
+ if (array_key_exists($name, $this->_options)) {
+ // This is a Core option
+ $this->_setOption($name, $value);
+ return;
+ }
+ if (array_key_exists($name, $this->_specificOptions)) {
+ // This a specic option of this frontend
+ $this->_specificOptions[$name] = $value;
+ return;
+ }
+ }
+
+ /**
+ * Public frontend to get an option value
+ *
+ * @param string $name Name of the option
+ * @throws Zend_Cache_Exception
+ * @return mixed option value
+ */
+ public function getOption($name)
+ {
+ $name = strtolower($name);
+
+ if (array_key_exists($name, $this->_options)) {
+ // This is a Core option
+ return $this->_options[$name];
+ }
+
+ if (array_key_exists($name, $this->_specificOptions)) {
+ // This a specic option of this frontend
+ return $this->_specificOptions[$name];
+ }
+
+ Zend_Cache::throwException("Incorrect option name : $name");
+ }
+
+ /**
+ * Set an option
+ *
+ * @param string $name Name of the option
+ * @param mixed $value Value of the option
+ * @throws Zend_Cache_Exception
+ * @return void
+ */
+ private function _setOption($name, $value)
+ {
+ if (!is_string($name) || !array_key_exists($name, $this->_options)) {
+ Zend_Cache::throwException("Incorrect option name : $name");
+ }
+ if ($name == 'lifetime' && empty($value)) {
+ $value = null;
+ }
+ $this->_options[$name] = $value;
+ }
+
+ /**
+ * Force a new lifetime
+ *
+ * The new value is set for the core/frontend but for the backend too (directive)
+ *
+ * @param int $newLifetime New lifetime (in seconds)
+ * @return void
+ */
+ public function setLifetime($newLifetime)
+ {
+ $this->_options['lifetime'] = $newLifetime;
+ $this->_backend->setDirectives(array(
+ 'lifetime' => $newLifetime
+ ));
+ }
+
+ /**
+ * Test if a cache is available for the given id and (if yes) return it (false else)
+ *
+ * @param string $id Cache id
+ * @param boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested
+ * @param boolean $doNotUnserialize Do not serialize (even if automatic_serialization is true) => for internal use
+ * @return mixed|false Cached datas
+ */
+ public function load($id, $doNotTestCacheValidity = false, $doNotUnserialize = false)
+ {
+ if (!$this->_options['caching']) {
+ return false;
+ }
+ $id = $this->_id($id); // cache id may need prefix
+ $this->_lastId = $id;
+ $this->_validateIdOrTag($id);
+
+ $this->_log("Zend_Cache_Core: load item '{$id}'", 7);
+ $data = $this->_backend->load($id, $doNotTestCacheValidity);
+ if ($data===false) {
+ // no cache available
+ return false;
+ }
+ if ((!$doNotUnserialize) && $this->_options['automatic_serialization']) {
+ // we need to unserialize before sending the result
+ return unserialize($data);
+ }
+ return $data;
+ }
+
+ /**
+ * Test if a cache is available for the given id
+ *
+ * @param string $id Cache id
+ * @return int|false Last modified time of cache entry if it is available, false otherwise
+ */
+ public function test($id)
+ {
+ if (!$this->_options['caching']) {
+ return false;
+ }
+ $id = $this->_id($id); // cache id may need prefix
+ $this->_validateIdOrTag($id);
+ $this->_lastId = $id;
+
+ $this->_log("Zend_Cache_Core: test item '{$id}'", 7);
+ return $this->_backend->test($id);
+ }
+
+ /**
+ * Save some data in a cache
+ *
+ * @param mixed $data Data to put in cache (can be another type than string if automatic_serialization is on)
+ * @param string $id Cache id (if not set, the last cache id will be used)
+ * @param array $tags Cache tags
+ * @param int $specificLifetime If != false, set a specific lifetime for this cache record (null => infinite lifetime)
+ * @param int $priority integer between 0 (very low priority) and 10 (maximum priority) used by some particular backends
+ * @throws Zend_Cache_Exception
+ * @return boolean True if no problem
+ */
+ public function save($data, $id = null, $tags = array(), $specificLifetime = false, $priority = 8)
+ {
+ if (!$this->_options['caching']) {
+ return true;
+ }
+ if ($id === null) {
+ $id = $this->_lastId;
+ } else {
+ $id = $this->_id($id);
+ }
+ $this->_validateIdOrTag($id);
+ $this->_validateTagsArray($tags);
+ if ($this->_options['automatic_serialization']) {
+ // we need to serialize datas before storing them
+ $data = serialize($data);
+ } else {
+ if (!is_string($data)) {
+ Zend_Cache::throwException("Datas must be string or set automatic_serialization = true");
+ }
+ }
+
+ // automatic cleaning
+ if ($this->_options['automatic_cleaning_factor'] > 0) {
+ $rand = rand(1, $this->_options['automatic_cleaning_factor']);
+ if ($rand==1) {
+ // new way || deprecated way
+ if ($this->_extendedBackend || method_exists($this->_backend, 'isAutomaticCleaningAvailable')) {
+ $this->_log("Zend_Cache_Core::save(): automatic cleaning running", 7);
+ $this->clean(Zend_Cache::CLEANING_MODE_OLD);
+ } else {
+ $this->_log("Zend_Cache_Core::save(): automatic cleaning is not available/necessary with current backend", 4);
+ }
+ }
+ }
+
+ $this->_log("Zend_Cache_Core: save item '{$id}'", 7);
+ if ($this->_options['ignore_user_abort']) {
+ $abort = ignore_user_abort(true);
+ }
+ if (($this->_extendedBackend) && ($this->_backendCapabilities['priority'])) {
+ $result = $this->_backend->save($data, $id, $tags, $specificLifetime, $priority);
+ } else {
+ $result = $this->_backend->save($data, $id, $tags, $specificLifetime);
+ }
+ if ($this->_options['ignore_user_abort']) {
+ ignore_user_abort($abort);
+ }
+
+ if (!$result) {
+ // maybe the cache is corrupted, so we remove it !
+ $this->_log("Zend_Cache_Core::save(): failed to save item '{$id}' -> removing it", 4);
+ $this->_backend->remove($id);
+ return false;
+ }
+
+ if ($this->_options['write_control']) {
+ $data2 = $this->_backend->load($id, true);
+ if ($data!=$data2) {
+ $this->_log("Zend_Cache_Core::save(): write control of item '{$id}' failed -> removing it", 4);
+ $this->_backend->remove($id);
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Remove a cache
+ *
+ * @param string $id Cache id to remove
+ * @return boolean True if ok
+ */
+ public function remove($id)
+ {
+ if (!$this->_options['caching']) {
+ return true;
+ }
+ $id = $this->_id($id); // cache id may need prefix
+ $this->_validateIdOrTag($id);
+
+ $this->_log("Zend_Cache_Core: remove item '{$id}'", 7);
+ return $this->_backend->remove($id);
+ }
+
+ /**
+ * Clean cache entries
+ *
+ * Available modes are :
+ * 'all' (default) => remove all cache entries ($tags is not used)
+ * 'old' => remove too old cache entries ($tags is not used)
+ * 'matchingTag' => remove cache entries matching all given tags
+ * ($tags can be an array of strings or a single string)
+ * 'notMatchingTag' => remove cache entries not matching one of the given tags
+ * ($tags can be an array of strings or a single string)
+ * 'matchingAnyTag' => remove cache entries matching any given tags
+ * ($tags can be an array of strings or a single string)
+ *
+ * @param string $mode
+ * @param array|string $tags
+ * @throws Zend_Cache_Exception
+ * @return boolean True if ok
+ */
+ public function clean($mode = 'all', $tags = array())
+ {
+ if (!$this->_options['caching']) {
+ return true;
+ }
+ if (!in_array($mode, array(Zend_Cache::CLEANING_MODE_ALL,
+ Zend_Cache::CLEANING_MODE_OLD,
+ Zend_Cache::CLEANING_MODE_MATCHING_TAG,
+ Zend_Cache::CLEANING_MODE_NOT_MATCHING_TAG,
+ Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG))) {
+ Zend_Cache::throwException('Invalid cleaning mode');
+ }
+ $this->_validateTagsArray($tags);
+
+ return $this->_backend->clean($mode, $tags);
+ }
+
+ /**
+ * 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())
+ {
+ if (!$this->_extendedBackend) {
+ Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);
+ }
+ if (!($this->_backendCapabilities['tags'])) {
+ Zend_Cache::throwException(self::BACKEND_NOT_SUPPORTS_TAG);
+ }
+
+ $ids = $this->_backend->getIdsMatchingTags($tags);
+
+ // we need to remove cache_id_prefix from ids (see #ZF-6178, #ZF-7600)
+ if (isset($this->_options['cache_id_prefix']) && $this->_options['cache_id_prefix'] !== '') {
+ $prefix = & $this->_options['cache_id_prefix'];
+ $prefixLen = strlen($prefix);
+ foreach ($ids as &$id) {
+ if (strpos($id, $prefix) === 0) {
+ $id = substr($id, $prefixLen);
+ }
+ }
+ }
+
+ return $ids;
+ }
+
+ /**
+ * 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())
+ {
+ if (!$this->_extendedBackend) {
+ Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);
+ }
+ if (!($this->_backendCapabilities['tags'])) {
+ Zend_Cache::throwException(self::BACKEND_NOT_SUPPORTS_TAG);
+ }
+
+ $ids = $this->_backend->getIdsNotMatchingTags($tags);
+
+ // we need to remove cache_id_prefix from ids (see #ZF-6178, #ZF-7600)
+ if (isset($this->_options['cache_id_prefix']) && $this->_options['cache_id_prefix'] !== '') {
+ $prefix = & $this->_options['cache_id_prefix'];
+ $prefixLen = strlen($prefix);
+ foreach ($ids as &$id) {
+ if (strpos($id, $prefix) === 0) {
+ $id = substr($id, $prefixLen);
+ }
+ }
+ }
+
+ return $ids;
+ }
+
+ /**
+ * Return an array of stored cache ids which match any given tags
+ *
+ * In case of multiple tags, a logical OR is made between tags
+ *
+ * @param array $tags array of tags
+ * @return array array of matching any cache ids (string)
+ */
+ public function getIdsMatchingAnyTags($tags = array())
+ {
+ if (!$this->_extendedBackend) {
+ Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);
+ }
+ if (!($this->_backendCapabilities['tags'])) {
+ Zend_Cache::throwException(self::BACKEND_NOT_SUPPORTS_TAG);
+ }
+
+ $ids = $this->_backend->getIdsMatchingAnyTags($tags);
+
+ // we need to remove cache_id_prefix from ids (see #ZF-6178, #ZF-7600)
+ if (isset($this->_options['cache_id_prefix']) && $this->_options['cache_id_prefix'] !== '') {
+ $prefix = & $this->_options['cache_id_prefix'];
+ $prefixLen = strlen($prefix);
+ foreach ($ids as &$id) {
+ if (strpos($id, $prefix) === 0) {
+ $id = substr($id, $prefixLen);
+ }
+ }
+ }
+
+ return $ids;
+ }
+
+ /**
+ * Return an array of stored cache ids
+ *
+ * @return array array of stored cache ids (string)
+ */
+ public function getIds()
+ {
+ if (!$this->_extendedBackend) {
+ Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);
+ }
+
+ $ids = $this->_backend->getIds();
+
+ // we need to remove cache_id_prefix from ids (see #ZF-6178, #ZF-7600)
+ if (isset($this->_options['cache_id_prefix']) && $this->_options['cache_id_prefix'] !== '') {
+ $prefix = & $this->_options['cache_id_prefix'];
+ $prefixLen = strlen($prefix);
+ foreach ($ids as &$id) {
+ if (strpos($id, $prefix) === 0) {
+ $id = substr($id, $prefixLen);
+ }
+ }
+ }
+
+ return $ids;
+ }
+
+ /**
+ * Return an array of stored tags
+ *
+ * @return array array of stored tags (string)
+ */
+ public function getTags()
+ {
+ if (!$this->_extendedBackend) {
+ Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);
+ }
+ if (!($this->_backendCapabilities['tags'])) {
+ Zend_Cache::throwException(self::BACKEND_NOT_SUPPORTS_TAG);
+ }
+ return $this->_backend->getTags();
+ }
+
+ /**
+ * Return the filling percentage of the backend storage
+ *
+ * @return int integer between 0 and 100
+ */
+ public function getFillingPercentage()
+ {
+ if (!$this->_extendedBackend) {
+ Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);
+ }
+ return $this->_backend->getFillingPercentage();
+ }
+
+ /**
+ * Return an array of metadatas for the given cache id
+ *
+ * The array will 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)
+ {
+ if (!$this->_extendedBackend) {
+ Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);
+ }
+ $id = $this->_id($id); // cache id may need prefix
+ return $this->_backend->getMetadatas($id);
+ }
+
+ /**
+ * 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)
+ {
+ if (!$this->_extendedBackend) {
+ Zend_Cache::throwException(self::BACKEND_NOT_IMPLEMENTS_EXTENDED_IF);
+ }
+ $id = $this->_id($id); // cache id may need prefix
+
+ $this->_log("Zend_Cache_Core: touch item '{$id}'", 7);
+ return $this->_backend->touch($id, $extraLifetime);
+ }
+
+ /**
+ * Validate a cache id or a tag (security, reliable filenames, reserved prefixes...)
+ *
+ * Throw an exception if a problem is found
+ *
+ * @param string $string Cache id or tag
+ * @throws Zend_Cache_Exception
+ * @return void
+ */
+ protected function _validateIdOrTag($string)
+ {
+ if (!is_string($string)) {
+ Zend_Cache::throwException('Invalid id or tag : must be a string');
+ }
+ if (substr($string, 0, 9) == 'internal-') {
+ Zend_Cache::throwException('"internal-*" ids or tags are reserved');
+ }
+ if (!preg_match('~^[a-zA-Z0-9_]+$~D', $string)) {
+ Zend_Cache::throwException("Invalid id or tag '$string' : must use only [a-zA-Z0-9_]");
+ }
+ }
+
+ /**
+ * Validate a tags array (security, reliable filenames, reserved prefixes...)
+ *
+ * Throw an exception if a problem is found
+ *
+ * @param array $tags Array of tags
+ * @throws Zend_Cache_Exception
+ * @return void
+ */
+ protected function _validateTagsArray($tags)
+ {
+ if (!is_array($tags)) {
+ Zend_Cache::throwException('Invalid tags array : must be an array');
+ }
+ foreach($tags as $tag) {
+ $this->_validateIdOrTag($tag);
+ }
+ reset($tags);
+ }
+
+ /**
+ * Make sure if we enable logging that the Zend_Log class
+ * is available.
+ * Create a default log object if none is set.
+ *
+ * @throws Zend_Cache_Exception
+ * @return void
+ */
+ protected function _loggerSanity()
+ {
+ if (!isset($this->_options['logging']) || !$this->_options['logging']) {
+ return;
+ }
+
+ if (isset($this->_options['logger']) && $this->_options['logger'] instanceof Zend_Log) {
+ return;
+ }
+
+ // Create a default logger to the standard output stream
+ require_once 'Zend/Log.php';
+ require_once 'Zend/Log/Writer/Stream.php';
+ require_once 'Zend/Log/Filter/Priority.php';
+ $logger = new Zend_Log(new Zend_Log_Writer_Stream('php://output'));
+ $logger->addFilter(new Zend_Log_Filter_Priority(Zend_Log::WARN, '<='));
+ $this->_options['logger'] = $logger;
+ }
+
+ /**
+ * Log a message at the WARN (4) priority.
+ *
+ * @param string $message
+ * @throws Zend_Cache_Exception
+ * @return void
+ */
+ protected function _log($message, $priority = 4)
+ {
+ if (!$this->_options['logging']) {
+ return;
+ }
+ if (!(isset($this->_options['logger']) || $this->_options['logger'] instanceof Zend_Log)) {
+ Zend_Cache::throwException('Logging is enabled but logger is not set');
+ }
+ $logger = $this->_options['logger'];
+ $logger->log($message, $priority);
+ }
+
+ /**
+ * Make and return a cache id
+ *
+ * Checks 'cache_id_prefix' and returns new id with prefix or simply the id if null
+ *
+ * @param string $id Cache id
+ * @return string Cache id (with or without prefix)
+ */
+ protected function _id($id)
+ {
+ if (($id !== null) && isset($this->_options['cache_id_prefix'])) {
+ return $this->_options['cache_id_prefix'] . $id; // return with prefix
+ }
+ return $id; // no prefix, just return the $id passed
+ }
+
+}
diff --git a/lib/zend/Zend/Cache/Exception.php b/lib/zend/Zend/Cache/Exception.php
new file mode 100644
index 00000000000..ee53b20671b
--- /dev/null
+++ b/lib/zend/Zend/Cache/Exception.php
@@ -0,0 +1,32 @@
+_tags = $tags;
+ $this->_extension = $extension;
+ ob_start(array($this, '_flush'));
+ ob_implicit_flush(false);
+ $this->_idStack[] = $id;
+ return false;
+ }
+
+ /**
+ * callback for output buffering
+ * (shouldn't really be called manually)
+ *
+ * @param string $data Buffered output
+ * @return string Data to send to browser
+ */
+ public function _flush($data)
+ {
+ $id = array_pop($this->_idStack);
+ if ($id === null) {
+ Zend_Cache::throwException('use of _flush() without a start()');
+ }
+ if ($this->_extension) {
+ $this->save(serialize(array($data, $this->_extension)), $id, $this->_tags);
+ } else {
+ $this->save($data, $id, $this->_tags);
+ }
+ return $data;
+ }
+}
diff --git a/lib/zend/Zend/Cache/Frontend/Class.php b/lib/zend/Zend/Cache/Frontend/Class.php
new file mode 100644
index 00000000000..4740402ac73
--- /dev/null
+++ b/lib/zend/Zend/Cache/Frontend/Class.php
@@ -0,0 +1,275 @@
+ (mixed) cached_entity :
+ * - if set to a class name, we will cache an abstract class and will use only static calls
+ * - if set to an object, we will cache this object methods
+ *
+ * ====> (boolean) cache_by_default :
+ * - if true, method calls will be cached by default
+ *
+ * ====> (array) cached_methods :
+ * - an array of method names which will be cached (even if cache_by_default = false)
+ *
+ * ====> (array) non_cached_methods :
+ * - an array of method names which won't be cached (even if cache_by_default = true)
+ *
+ * @var array available options
+ */
+ protected $_specificOptions = array(
+ 'cached_entity' => null,
+ 'cache_by_default' => true,
+ 'cached_methods' => array(),
+ 'non_cached_methods' => array()
+ );
+
+ /**
+ * Tags array
+ *
+ * @var array
+ */
+ protected $_tags = array();
+
+ /**
+ * SpecificLifetime value
+ *
+ * false => no specific life time
+ *
+ * @var bool|int
+ */
+ protected $_specificLifetime = false;
+
+ /**
+ * The cached object or the name of the cached abstract class
+ *
+ * @var mixed
+ */
+ protected $_cachedEntity = null;
+
+ /**
+ * The class name of the cached object or cached abstract class
+ *
+ * Used to differentiate between different classes with the same method calls.
+ *
+ * @var string
+ */
+ protected $_cachedEntityLabel = '';
+
+ /**
+ * Priority (used by some particular backends)
+ *
+ * @var int
+ */
+ protected $_priority = 8;
+
+ /**
+ * Constructor
+ *
+ * @param array $options Associative array of options
+ * @throws Zend_Cache_Exception
+ */
+ public function __construct(array $options = array())
+ {
+ foreach ($options as $name => $value) {
+ $this->setOption($name, $value);
+ }
+ if ($this->_specificOptions['cached_entity'] === null) {
+ Zend_Cache::throwException('cached_entity must be set !');
+ }
+ $this->setCachedEntity($this->_specificOptions['cached_entity']);
+ $this->setOption('automatic_serialization', true);
+ }
+
+ /**
+ * Set a specific life time
+ *
+ * @param bool|int $specificLifetime
+ * @return void
+ */
+ public function setSpecificLifetime($specificLifetime = false)
+ {
+ $this->_specificLifetime = $specificLifetime;
+ }
+
+ /**
+ * Set the priority (used by some particular backends)
+ *
+ * @param int $priority integer between 0 (very low priority) and 10 (maximum priority)
+ */
+ public function setPriority($priority)
+ {
+ $this->_priority = $priority;
+ }
+
+ /**
+ * Public frontend to set an option
+ *
+ * Just a wrapper to get a specific behaviour for cached_entity
+ *
+ * @param string $name Name of the option
+ * @param mixed $value Value of the option
+ * @throws Zend_Cache_Exception
+ * @return void
+ */
+ public function setOption($name, $value)
+ {
+ if ($name == 'cached_entity') {
+ $this->setCachedEntity($value);
+ } else {
+ parent::setOption($name, $value);
+ }
+ }
+
+ /**
+ * Specific method to set the cachedEntity
+ *
+ * if set to a class name, we will cache an abstract class and will use only static calls
+ * if set to an object, we will cache this object methods
+ *
+ * @param mixed $cachedEntity
+ */
+ public function setCachedEntity($cachedEntity)
+ {
+ if (!is_string($cachedEntity) && !is_object($cachedEntity)) {
+ Zend_Cache::throwException(
+ 'cached_entity must be an object or a class name'
+ );
+ }
+
+ $this->_cachedEntity = $cachedEntity;
+ $this->_specificOptions['cached_entity'] = $cachedEntity;
+
+ if (is_string($this->_cachedEntity)) {
+ $this->_cachedEntityLabel = $this->_cachedEntity;
+ } else {
+ $ro = new ReflectionObject($this->_cachedEntity);
+ $this->_cachedEntityLabel = $ro->getName();
+ }
+ }
+
+ /**
+ * Set the cache array
+ *
+ * @param array $tags
+ * @return void
+ */
+ public function setTagsArray($tags = array())
+ {
+ $this->_tags = $tags;
+ }
+
+ /**
+ * Main method : call the specified method or get the result from cache
+ *
+ * @param string $name Method name
+ * @param array $parameters Method parameters
+ * @return mixed Result
+ * @throws Exception
+ */
+ public function __call($name, $parameters)
+ {
+ $callback = array($this->_cachedEntity, $name);
+
+ if (!is_callable($callback, false)) {
+ Zend_Cache::throwException('Invalid callback');
+ }
+
+ $cacheBool1 = $this->_specificOptions['cache_by_default'];
+ $cacheBool2 = in_array($name, $this->_specificOptions['cached_methods']);
+ $cacheBool3 = in_array($name, $this->_specificOptions['non_cached_methods']);
+ $cache = (($cacheBool1 || $cacheBool2) && (!$cacheBool3));
+
+ if (!$cache) {
+ // We do not have not cache
+ return call_user_func_array($callback, $parameters);
+ }
+
+ $id = $this->makeId($name, $parameters);
+ if (($rs = $this->load($id)) && (array_key_exists(0, $rs))
+ && (array_key_exists(1, $rs))
+ ) {
+ // A cache is available
+ $output = $rs[0];
+ $return = $rs[1];
+ } else {
+ // A cache is not available (or not valid for this frontend)
+ ob_start();
+ ob_implicit_flush(false);
+
+ try {
+ $return = call_user_func_array($callback, $parameters);
+ $output = ob_get_clean();
+ $data = array($output, $return);
+
+ $this->save(
+ $data, $id, $this->_tags, $this->_specificLifetime,
+ $this->_priority
+ );
+ } catch (Exception $e) {
+ ob_end_clean();
+ throw $e;
+ }
+ }
+
+ echo $output;
+ return $return;
+ }
+
+ /**
+ * ZF-9970
+ *
+ * @deprecated
+ */
+ private function _makeId($name, $args)
+ {
+ return $this->makeId($name, $args);
+ }
+
+ /**
+ * Make a cache id from the method name and parameters
+ *
+ * @param string $name Method name
+ * @param array $args Method parameters
+ * @return string Cache id
+ */
+ public function makeId($name, array $args = array())
+ {
+ return md5($this->_cachedEntityLabel . '__' . $name . '__' . serialize($args));
+ }
+}
diff --git a/lib/zend/Zend/Cache/Frontend/File.php b/lib/zend/Zend/Cache/Frontend/File.php
new file mode 100644
index 00000000000..e5017c631ca
--- /dev/null
+++ b/lib/zend/Zend/Cache/Frontend/File.php
@@ -0,0 +1,222 @@
+ (string) master_file :
+ * - a complete path of the master file
+ * - deprecated (see master_files)
+ *
+ * ====> (array) master_files :
+ * - an array of complete path of master files
+ * - this option has to be set !
+ *
+ * ====> (string) master_files_mode :
+ * - Zend_Cache_Frontend_File::MODE_AND or Zend_Cache_Frontend_File::MODE_OR
+ * - if MODE_AND, then all master files have to be touched to get a cache invalidation
+ * - if MODE_OR (default), then a single touched master file is enough to get a cache invalidation
+ *
+ * ====> (boolean) ignore_missing_master_files
+ * - if set to true, missing master files are ignored silently
+ * - if set to false (default), an exception is thrown if there is a missing master file
+ * @var array available options
+ */
+ protected $_specificOptions = array(
+ 'master_file' => null,
+ 'master_files' => null,
+ 'master_files_mode' => 'OR',
+ 'ignore_missing_master_files' => false
+ );
+
+ /**
+ * Master file mtimes
+ *
+ * Array of int
+ *
+ * @var array
+ */
+ private $_masterFile_mtimes = null;
+
+ /**
+ * Constructor
+ *
+ * @param array $options Associative array of options
+ * @throws Zend_Cache_Exception
+ * @return void
+ */
+ public function __construct(array $options = array())
+ {
+ foreach ($options as $name => $value) {
+ $this->setOption($name, $value);
+ }
+ if (!isset($this->_specificOptions['master_files'])) {
+ Zend_Cache::throwException('master_files option must be set');
+ }
+ }
+
+ /**
+ * Change the master_files option
+ *
+ * @param array $masterFiles the complete paths and name of the master files
+ */
+ public function setMasterFiles(array $masterFiles)
+ {
+ $this->_specificOptions['master_file'] = null; // to keep a compatibility
+ $this->_specificOptions['master_files'] = null;
+ $this->_masterFile_mtimes = array();
+
+ clearstatcache();
+ $i = 0;
+ foreach ($masterFiles as $masterFile) {
+ if (file_exists($masterFile)) {
+ $mtime = filemtime($masterFile);
+ } else {
+ $mtime = false;
+ }
+
+ if (!$this->_specificOptions['ignore_missing_master_files'] && !$mtime) {
+ Zend_Cache::throwException('Unable to read master_file : ' . $masterFile);
+ }
+
+ $this->_masterFile_mtimes[$i] = $mtime;
+ $this->_specificOptions['master_files'][$i] = $masterFile;
+ if ($i === 0) { // to keep a compatibility
+ $this->_specificOptions['master_file'] = $masterFile;
+ }
+
+ $i++;
+ }
+ }
+
+ /**
+ * Change the master_file option
+ *
+ * To keep the compatibility
+ *
+ * @deprecated
+ * @param string $masterFile the complete path and name of the master file
+ */
+ public function setMasterFile($masterFile)
+ {
+ $this->setMasterFiles(array($masterFile));
+ }
+
+ /**
+ * Public frontend to set an option
+ *
+ * Just a wrapper to get a specific behaviour for master_file
+ *
+ * @param string $name Name of the option
+ * @param mixed $value Value of the option
+ * @throws Zend_Cache_Exception
+ * @return void
+ */
+ public function setOption($name, $value)
+ {
+ if ($name == 'master_file') {
+ $this->setMasterFile($value);
+ } else if ($name == 'master_files') {
+ $this->setMasterFiles($value);
+ } else {
+ parent::setOption($name, $value);
+ }
+ }
+
+ /**
+ * Test if a cache is available for the given id and (if yes) return it (false else)
+ *
+ * @param string $id Cache id
+ * @param boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested
+ * @param boolean $doNotUnserialize Do not serialize (even if automatic_serialization is true) => for internal use
+ * @return mixed|false Cached datas
+ */
+ public function load($id, $doNotTestCacheValidity = false, $doNotUnserialize = false)
+ {
+ if (!$doNotTestCacheValidity) {
+ if ($this->test($id)) {
+ return parent::load($id, true, $doNotUnserialize);
+ }
+ return false;
+ }
+ return parent::load($id, true, $doNotUnserialize);
+ }
+
+ /**
+ * Test if a cache is available for the given id
+ *
+ * @param string $id Cache id
+ * @return int|false Last modified time of cache entry if it is available, false otherwise
+ */
+ public function test($id)
+ {
+ $lastModified = parent::test($id);
+ if ($lastModified) {
+ if ($this->_specificOptions['master_files_mode'] == self::MODE_AND) {
+ // MODE_AND
+ foreach($this->_masterFile_mtimes as $masterFileMTime) {
+ if ($masterFileMTime) {
+ if ($lastModified > $masterFileMTime) {
+ return $lastModified;
+ }
+ }
+ }
+ } else {
+ // MODE_OR
+ $res = true;
+ foreach($this->_masterFile_mtimes as $masterFileMTime) {
+ if ($masterFileMTime) {
+ if ($lastModified <= $masterFileMTime) {
+ return false;
+ }
+ }
+ }
+ return $lastModified;
+ }
+ }
+ return false;
+ }
+
+}
+
diff --git a/lib/zend/Zend/Cache/Frontend/Function.php b/lib/zend/Zend/Cache/Frontend/Function.php
new file mode 100644
index 00000000000..8af521bda69
--- /dev/null
+++ b/lib/zend/Zend/Cache/Frontend/Function.php
@@ -0,0 +1,179 @@
+ (boolean) cache_by_default :
+ * - if true, function calls will be cached by default
+ *
+ * ====> (array) cached_functions :
+ * - an array of function names which will be cached (even if cache_by_default = false)
+ *
+ * ====> (array) non_cached_functions :
+ * - an array of function names which won't be cached (even if cache_by_default = true)
+ *
+ * @var array options
+ */
+ protected $_specificOptions = array(
+ 'cache_by_default' => true,
+ 'cached_functions' => array(),
+ 'non_cached_functions' => array()
+ );
+
+ /**
+ * Constructor
+ *
+ * @param array $options Associative array of options
+ * @return void
+ */
+ public function __construct(array $options = array())
+ {
+ foreach ($options as $name => $value) {
+ $this->setOption($name, $value);
+ }
+ $this->setOption('automatic_serialization', true);
+ }
+
+ /**
+ * Main method : call the specified function or get the result from cache
+ *
+ * @param callback $callback A valid callback
+ * @param array $parameters Function parameters
+ * @param array $tags Cache tags
+ * @param int $specificLifetime If != false, set a specific lifetime for this cache record (null => infinite lifetime)
+ * @param int $priority integer between 0 (very low priority) and 10 (maximum priority) used by some particular backends
+ * @return mixed Result
+ */
+ public function call($callback, array $parameters = array(), $tags = array(), $specificLifetime = false, $priority = 8)
+ {
+ if (!is_callable($callback, true, $name)) {
+ Zend_Cache::throwException('Invalid callback');
+ }
+
+ $cacheBool1 = $this->_specificOptions['cache_by_default'];
+ $cacheBool2 = in_array($name, $this->_specificOptions['cached_functions']);
+ $cacheBool3 = in_array($name, $this->_specificOptions['non_cached_functions']);
+ $cache = (($cacheBool1 || $cacheBool2) && (!$cacheBool3));
+ if (!$cache) {
+ // Caching of this callback is disabled
+ return call_user_func_array($callback, $parameters);
+ }
+
+ $id = $this->_makeId($callback, $parameters);
+ if ( ($rs = $this->load($id)) && isset($rs[0], $rs[1])) {
+ // A cache is available
+ $output = $rs[0];
+ $return = $rs[1];
+ } else {
+ // A cache is not available (or not valid for this frontend)
+ ob_start();
+ ob_implicit_flush(false);
+ $return = call_user_func_array($callback, $parameters);
+ $output = ob_get_clean();
+ $data = array($output, $return);
+ $this->save($data, $id, $tags, $specificLifetime, $priority);
+ }
+
+ echo $output;
+ return $return;
+ }
+
+ /**
+ * ZF-9970
+ *
+ * @deprecated
+ */
+ private function _makeId($callback, array $args)
+ {
+ return $this->makeId($callback, $args);
+ }
+
+ /**
+ * Make a cache id from the function name and parameters
+ *
+ * @param callback $callback A valid callback
+ * @param array $args Function parameters
+ * @throws Zend_Cache_Exception
+ * @return string Cache id
+ */
+ public function makeId($callback, array $args = array())
+ {
+ if (!is_callable($callback, true, $name)) {
+ Zend_Cache::throwException('Invalid callback');
+ }
+
+ // functions, methods and classnames are case-insensitive
+ $name = strtolower($name);
+
+ // generate a unique id for object callbacks
+ if (is_object($callback)) { // Closures & __invoke
+ $object = $callback;
+ } elseif (isset($callback[0])) { // array($object, 'method')
+ $object = $callback[0];
+ }
+ if (isset($object)) {
+ try {
+ $tmp = @serialize($callback);
+ } catch (Exception $e) {
+ Zend_Cache::throwException($e->getMessage());
+ }
+ if (!$tmp) {
+ $lastErr = error_get_last();
+ Zend_Cache::throwException("Can't serialize callback object to generate id: {$lastErr['message']}");
+ }
+ $name.= '__' . $tmp;
+ }
+
+ // generate a unique id for arguments
+ $argsStr = '';
+ if ($args) {
+ try {
+ $argsStr = @serialize(array_values($args));
+ } catch (Exception $e) {
+ Zend_Cache::throwException($e->getMessage());
+ }
+ if (!$argsStr) {
+ $lastErr = error_get_last();
+ throw Zend_Cache::throwException("Can't serialize arguments to generate id: {$lastErr['message']}");
+ }
+ }
+
+ return md5($name . $argsStr);
+ }
+
+}
diff --git a/lib/zend/Zend/Cache/Frontend/Output.php b/lib/zend/Zend/Cache/Frontend/Output.php
new file mode 100644
index 00000000000..99a8a64c9d8
--- /dev/null
+++ b/lib/zend/Zend/Cache/Frontend/Output.php
@@ -0,0 +1,105 @@
+_idStack = array();
+ }
+
+ /**
+ * Start the cache
+ *
+ * @param string $id Cache id
+ * @param boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested
+ * @param boolean $echoData If set to true, datas are sent to the browser if the cache is hit (simply returned else)
+ * @return mixed True if the cache is hit (false else) with $echoData=true (default) ; string else (datas)
+ */
+ public function start($id, $doNotTestCacheValidity = false, $echoData = true)
+ {
+ $data = $this->load($id, $doNotTestCacheValidity);
+ if ($data !== false) {
+ if ( $echoData ) {
+ echo($data);
+ return true;
+ } else {
+ return $data;
+ }
+ }
+ ob_start();
+ ob_implicit_flush(false);
+ $this->_idStack[] = $id;
+ return false;
+ }
+
+ /**
+ * Stop the cache
+ *
+ * @param array $tags Tags array
+ * @param int $specificLifetime If != false, set a specific lifetime for this cache record (null => infinite lifetime)
+ * @param string $forcedDatas If not null, force written datas with this
+ * @param boolean $echoData If set to true, datas are sent to the browser
+ * @param int $priority integer between 0 (very low priority) and 10 (maximum priority) used by some particular backends
+ * @return void
+ */
+ public function end($tags = array(), $specificLifetime = false, $forcedDatas = null, $echoData = true, $priority = 8)
+ {
+ if ($forcedDatas === null) {
+ $data = ob_get_clean();
+ } else {
+ $data =& $forcedDatas;
+ }
+ $id = array_pop($this->_idStack);
+ if ($id === null) {
+ Zend_Cache::throwException('use of end() without a start()');
+ }
+ $this->save($data, $id, $tags, $specificLifetime, $priority);
+ if ($echoData) {
+ echo($data);
+ }
+ }
+
+}
diff --git a/lib/zend/Zend/Cache/Frontend/Page.php b/lib/zend/Zend/Cache/Frontend/Page.php
new file mode 100644
index 00000000000..cc253d559c8
--- /dev/null
+++ b/lib/zend/Zend/Cache/Frontend/Page.php
@@ -0,0 +1,404 @@
+ (boolean) http_conditional :
+ * - if true, http conditional mode is on
+ * WARNING : http_conditional OPTION IS NOT IMPLEMENTED FOR THE MOMENT (TODO)
+ *
+ * ====> (boolean) debug_header :
+ * - if true, a debug text is added before each cached pages
+ *
+ * ====> (boolean) content_type_memorization :
+ * - deprecated => use memorize_headers instead
+ * - if the Content-Type header is sent after the cache was started, the
+ * corresponding value can be memorized and replayed when the cache is hit
+ * (if false (default), the frontend doesn't take care of Content-Type header)
+ *
+ * ====> (array) memorize_headers :
+ * - an array of strings corresponding to some HTTP headers name. Listed headers
+ * will be stored with cache datas and "replayed" when the cache is hit
+ *
+ * ====> (array) default_options :
+ * - an associative array of default options :
+ * - (boolean) cache : cache is on by default if true
+ * - (boolean) cacheWithXXXVariables (XXXX = 'Get', 'Post', 'Session', 'Files' or 'Cookie') :
+ * if true, cache is still on even if there are some variables in this superglobal array
+ * if false, cache is off if there are some variables in this superglobal array
+ * - (boolean) makeIdWithXXXVariables (XXXX = 'Get', 'Post', 'Session', 'Files' or 'Cookie') :
+ * if true, we have to use the content of this superglobal array to make a cache id
+ * if false, the cache id won't be dependent of the content of this superglobal array
+ * - (int) specific_lifetime : cache specific lifetime
+ * (false => global lifetime is used, null => infinite lifetime,
+ * integer => this lifetime is used), this "lifetime" is probably only
+ * usefull when used with "regexps" array
+ * - (array) tags : array of tags (strings)
+ * - (int) priority : integer between 0 (very low priority) and 10 (maximum priority) used by
+ * some particular backends
+ *
+ * ====> (array) regexps :
+ * - an associative array to set options only for some REQUEST_URI
+ * - keys are (pcre) regexps
+ * - values are associative array with specific options to set if the regexp matchs on $_SERVER['REQUEST_URI']
+ * (see default_options for the list of available options)
+ * - if several regexps match the $_SERVER['REQUEST_URI'], only the last one will be used
+ *
+ * @var array options
+ */
+ protected $_specificOptions = array(
+ 'http_conditional' => false,
+ 'debug_header' => false,
+ 'content_type_memorization' => false,
+ 'memorize_headers' => array(),
+ 'default_options' => array(
+ 'cache_with_get_variables' => false,
+ 'cache_with_post_variables' => false,
+ 'cache_with_session_variables' => false,
+ 'cache_with_files_variables' => false,
+ 'cache_with_cookie_variables' => false,
+ 'make_id_with_get_variables' => true,
+ 'make_id_with_post_variables' => true,
+ 'make_id_with_session_variables' => true,
+ 'make_id_with_files_variables' => true,
+ 'make_id_with_cookie_variables' => true,
+ 'cache' => true,
+ 'specific_lifetime' => false,
+ 'tags' => array(),
+ 'priority' => null
+ ),
+ 'regexps' => array()
+ );
+
+ /**
+ * Internal array to store some options
+ *
+ * @var array associative array of options
+ */
+ protected $_activeOptions = array();
+
+ /**
+ * If true, the page won't be cached
+ *
+ * @var boolean
+ */
+ protected $_cancel = false;
+
+ /**
+ * Constructor
+ *
+ * @param array $options Associative array of options
+ * @param boolean $doNotTestCacheValidity If set to true, the cache validity won't be tested
+ * @throws Zend_Cache_Exception
+ * @return void
+ */
+ public function __construct(array $options = array())
+ {
+ foreach ($options as $name => $value) {
+ $name = strtolower($name);
+ switch ($name) {
+ case 'regexps':
+ $this->_setRegexps($value);
+ break;
+ case 'default_options':
+ $this->_setDefaultOptions($value);
+ break;
+ case 'content_type_memorization':
+ $this->_setContentTypeMemorization($value);
+ break;
+ default:
+ $this->setOption($name, $value);
+ }
+ }
+ if (isset($this->_specificOptions['http_conditional'])) {
+ if ($this->_specificOptions['http_conditional']) {
+ Zend_Cache::throwException('http_conditional is not implemented for the moment !');
+ }
+ }
+ $this->setOption('automatic_serialization', true);
+ }
+
+ /**
+ * Specific setter for the 'default_options' option (with some additional tests)
+ *
+ * @param array $options Associative array
+ * @throws Zend_Cache_Exception
+ * @return void
+ */
+ protected function _setDefaultOptions($options)
+ {
+ if (!is_array($options)) {
+ Zend_Cache::throwException('default_options must be an array !');
+ }
+ foreach ($options as $key=>$value) {
+ if (!is_string($key)) {
+ Zend_Cache::throwException("invalid option [$key] !");
+ }
+ $key = strtolower($key);
+ if (isset($this->_specificOptions['default_options'][$key])) {
+ $this->_specificOptions['default_options'][$key] = $value;
+ }
+ }
+ }
+
+ /**
+ * Set the deprecated contentTypeMemorization option
+ *
+ * @param boolean $value value
+ * @return void
+ * @deprecated
+ */
+ protected function _setContentTypeMemorization($value)
+ {
+ $found = null;
+ foreach ($this->_specificOptions['memorize_headers'] as $key => $value) {
+ if (strtolower($value) == 'content-type') {
+ $found = $key;
+ }
+ }
+ if ($value) {
+ if (!$found) {
+ $this->_specificOptions['memorize_headers'][] = 'Content-Type';
+ }
+ } else {
+ if ($found) {
+ unset($this->_specificOptions['memorize_headers'][$found]);
+ }
+ }
+ }
+
+ /**
+ * Specific setter for the 'regexps' option (with some additional tests)
+ *
+ * @param array $options Associative array
+ * @throws Zend_Cache_Exception
+ * @return void
+ */
+ protected function _setRegexps($regexps)
+ {
+ if (!is_array($regexps)) {
+ Zend_Cache::throwException('regexps option must be an array !');
+ }
+ foreach ($regexps as $regexp=>$conf) {
+ if (!is_array($conf)) {
+ Zend_Cache::throwException('regexps option must be an array of arrays !');
+ }
+ $validKeys = array_keys($this->_specificOptions['default_options']);
+ foreach ($conf as $key=>$value) {
+ if (!is_string($key)) {
+ Zend_Cache::throwException("unknown option [$key] !");
+ }
+ $key = strtolower($key);
+ if (!in_array($key, $validKeys)) {
+ unset($regexps[$regexp][$key]);
+ }
+ }
+ }
+ $this->setOption('regexps', $regexps);
+ }
+
+ /**
+ * Start the cache
+ *
+ * @param string $id (optional) A cache id (if you set a value here, maybe you have to use Output frontend instead)
+ * @param boolean $doNotDie For unit testing only !
+ * @return boolean True if the cache is hit (false else)
+ */
+ public function start($id = false, $doNotDie = false)
+ {
+ $this->_cancel = false;
+ $lastMatchingRegexp = null;
+ if (isset($_SERVER['REQUEST_URI'])) {
+ foreach ($this->_specificOptions['regexps'] as $regexp => $conf) {
+ if (preg_match("`$regexp`", $_SERVER['REQUEST_URI'])) {
+ $lastMatchingRegexp = $regexp;
+ }
+ }
+ }
+ $this->_activeOptions = $this->_specificOptions['default_options'];
+ if ($lastMatchingRegexp !== null) {
+ $conf = $this->_specificOptions['regexps'][$lastMatchingRegexp];
+ foreach ($conf as $key=>$value) {
+ $this->_activeOptions[$key] = $value;
+ }
+ }
+ if (!($this->_activeOptions['cache'])) {
+ return false;
+ }
+ if (!$id) {
+ $id = $this->_makeId();
+ if (!$id) {
+ return false;
+ }
+ }
+ $array = $this->load($id);
+ if ($array !== false) {
+ $data = $array['data'];
+ $headers = $array['headers'];
+ if (!headers_sent()) {
+ foreach ($headers as $key=>$headerCouple) {
+ $name = $headerCouple[0];
+ $value = $headerCouple[1];
+ header("$name: $value");
+ }
+ }
+ if ($this->_specificOptions['debug_header']) {
+ echo 'DEBUG HEADER : This is a cached page !';
+ }
+ echo $data;
+ if ($doNotDie) {
+ return true;
+ }
+ die();
+ }
+ ob_start(array($this, '_flush'));
+ ob_implicit_flush(false);
+ return false;
+ }
+
+ /**
+ * Cancel the current caching process
+ */
+ public function cancel()
+ {
+ $this->_cancel = true;
+ }
+
+ /**
+ * callback for output buffering
+ * (shouldn't really be called manually)
+ *
+ * @param string $data Buffered output
+ * @return string Data to send to browser
+ */
+ public function _flush($data)
+ {
+ if ($this->_cancel) {
+ return $data;
+ }
+ $contentType = null;
+ $storedHeaders = array();
+ $headersList = headers_list();
+ foreach($this->_specificOptions['memorize_headers'] as $key=>$headerName) {
+ foreach ($headersList as $headerSent) {
+ $tmp = explode(':', $headerSent);
+ $headerSentName = trim(array_shift($tmp));
+ if (strtolower($headerName) == strtolower($headerSentName)) {
+ $headerSentValue = trim(implode(':', $tmp));
+ $storedHeaders[] = array($headerSentName, $headerSentValue);
+ }
+ }
+ }
+ $array = array(
+ 'data' => $data,
+ 'headers' => $storedHeaders
+ );
+ $this->save($array, null, $this->_activeOptions['tags'], $this->_activeOptions['specific_lifetime'], $this->_activeOptions['priority']);
+ return $data;
+ }
+
+ /**
+ * Make an id depending on REQUEST_URI and superglobal arrays (depending on options)
+ *
+ * @return mixed|false a cache id (string), false if the cache should have not to be used
+ */
+ protected function _makeId()
+ {
+ $tmp = $_SERVER['REQUEST_URI'];
+ $array = explode('?', $tmp, 2);
+ $tmp = $array[0];
+ foreach (array('Get', 'Post', 'Session', 'Files', 'Cookie') as $arrayName) {
+ $tmp2 = $this->_makePartialId($arrayName, $this->_activeOptions['cache_with_' . strtolower($arrayName) . '_variables'], $this->_activeOptions['make_id_with_' . strtolower($arrayName) . '_variables']);
+ if ($tmp2===false) {
+ return false;
+ }
+ $tmp = $tmp . $tmp2;
+ }
+ return md5($tmp);
+ }
+
+ /**
+ * Make a partial id depending on options
+ *
+ * @param string $arrayName Superglobal array name
+ * @param bool $bool1 If true, cache is still on even if there are some variables in the superglobal array
+ * @param bool $bool2 If true, we have to use the content of the superglobal array to make a partial id
+ * @return mixed|false Partial id (string) or false if the cache should have not to be used
+ */
+ protected function _makePartialId($arrayName, $bool1, $bool2)
+ {
+ switch ($arrayName) {
+ case 'Get':
+ $var = $_GET;
+ break;
+ case 'Post':
+ $var = $_POST;
+ break;
+ case 'Session':
+ if (isset($_SESSION)) {
+ $var = $_SESSION;
+ } else {
+ $var = null;
+ }
+ break;
+ case 'Cookie':
+ if (isset($_COOKIE)) {
+ $var = $_COOKIE;
+ } else {
+ $var = null;
+ }
+ break;
+ case 'Files':
+ $var = $_FILES;
+ break;
+ default:
+ return false;
+ }
+ if ($bool1) {
+ if ($bool2) {
+ return serialize($var);
+ }
+ return '';
+ }
+ if (count($var) > 0) {
+ return false;
+ }
+ return '';
+ }
+
+}
diff --git a/lib/zend/Zend/Cache/Manager.php b/lib/zend/Zend/Cache/Manager.php
new file mode 100644
index 00000000000..330ea954e85
--- /dev/null
+++ b/lib/zend/Zend/Cache/Manager.php
@@ -0,0 +1,308 @@
+ array(
+ 'frontend' => array(
+ 'name' => 'Core',
+ 'options' => array(
+ 'automatic_serialization' => true,
+ ),
+ ),
+ 'backend' => array(
+ 'name' => 'File',
+ 'options' => array(
+ // use system temp dir by default of file backend
+ // 'cache_dir' => '../cache',
+ ),
+ ),
+ ),
+
+ // Static Page HTML Cache
+ 'page' => array(
+ 'frontend' => array(
+ 'name' => 'Capture',
+ 'options' => array(
+ 'ignore_user_abort' => true,
+ ),
+ ),
+ 'backend' => array(
+ 'name' => 'Static',
+ 'options' => array(
+ 'public_dir' => '../public',
+ ),
+ ),
+ ),
+
+ // Tag Cache
+ 'pagetag' => array(
+ 'frontend' => array(
+ 'name' => 'Core',
+ 'options' => array(
+ 'automatic_serialization' => true,
+ 'lifetime' => null
+ ),
+ ),
+ 'backend' => array(
+ 'name' => 'File',
+ 'options' => array(
+ // use system temp dir by default of file backend
+ // 'cache_dir' => '../cache',
+ // use default umask of file backend
+ // 'cache_file_umask' => 0644
+ ),
+ ),
+ ),
+ );
+
+ /**
+ * Set a new cache for the Cache Manager to contain
+ *
+ * @param string $name
+ * @param Zend_Cache_Core $cache
+ * @return Zend_Cache_Manager
+ */
+ public function setCache($name, Zend_Cache_Core $cache)
+ {
+ $this->_caches[$name] = $cache;
+ return $this;
+ }
+
+ /**
+ * Check if the Cache Manager contains the named cache object, or a named
+ * configuration template to lazy load the cache object
+ *
+ * @param string $name
+ * @return bool
+ */
+ public function hasCache($name)
+ {
+ if (isset($this->_caches[$name])
+ || $this->hasCacheTemplate($name)
+ ) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Fetch the named cache object, or instantiate and return a cache object
+ * using a named configuration template
+ *
+ * @param string $name
+ * @return Zend_Cache_Core
+ */
+ public function getCache($name)
+ {
+ if (isset($this->_caches[$name])) {
+ return $this->_caches[$name];
+ }
+ if (isset($this->_optionTemplates[$name])) {
+ if ($name == self::PAGECACHE
+ && (!isset($this->_optionTemplates[$name]['backend']['options']['tag_cache'])
+ || !$this->_optionTemplates[$name]['backend']['options']['tag_cache'] instanceof Zend_Cache_Core)
+ ) {
+ $this->_optionTemplates[$name]['backend']['options']['tag_cache']
+ = $this->getCache(self::PAGETAGCACHE);
+ }
+
+ $this->_caches[$name] = Zend_Cache::factory(
+ $this->_optionTemplates[$name]['frontend']['name'],
+ $this->_optionTemplates[$name]['backend']['name'],
+ isset($this->_optionTemplates[$name]['frontend']['options']) ? $this->_optionTemplates[$name]['frontend']['options'] : array(),
+ isset($this->_optionTemplates[$name]['backend']['options']) ? $this->_optionTemplates[$name]['backend']['options'] : array(),
+ isset($this->_optionTemplates[$name]['frontend']['customFrontendNaming']) ? $this->_optionTemplates[$name]['frontend']['customFrontendNaming'] : false,
+ isset($this->_optionTemplates[$name]['backend']['customBackendNaming']) ? $this->_optionTemplates[$name]['backend']['customBackendNaming'] : false,
+ isset($this->_optionTemplates[$name]['frontendBackendAutoload']) ? $this->_optionTemplates[$name]['frontendBackendAutoload'] : false
+ );
+
+ return $this->_caches[$name];
+ }
+ }
+
+ /**
+ * Fetch all available caches
+ *
+ * @return array An array of all available caches with it's names as key
+ */
+ public function getCaches()
+ {
+ $caches = $this->_caches;
+ foreach ($this->_optionTemplates as $name => $tmp) {
+ if (!isset($caches[$name])) {
+ $caches[$name] = $this->getCache($name);
+ }
+ }
+ return $caches;
+ }
+
+ /**
+ * Set a named configuration template from which a cache object can later
+ * be lazy loaded
+ *
+ * @param string $name
+ * @param array $options
+ * @return Zend_Cache_Manager
+ * @throws Zend_Cache_Exception
+ */
+ public function setCacheTemplate($name, $options)
+ {
+ if ($options instanceof Zend_Config) {
+ $options = $options->toArray();
+ } elseif (!is_array($options)) {
+ require_once 'Zend/Cache/Exception.php';
+ throw new Zend_Cache_Exception('Options passed must be in'
+ . ' an associative array or instance of Zend_Config');
+ }
+ $this->_optionTemplates[$name] = $options;
+ return $this;
+ }
+
+ /**
+ * Check if the named configuration template
+ *
+ * @param string $name
+ * @return bool
+ */
+ public function hasCacheTemplate($name)
+ {
+ if (isset($this->_optionTemplates[$name])) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Get the named configuration template
+ *
+ * @param string $name
+ * @return array
+ */
+ public function getCacheTemplate($name)
+ {
+ if (isset($this->_optionTemplates[$name])) {
+ return $this->_optionTemplates[$name];
+ }
+ }
+
+ /**
+ * Pass an array containing changes to be applied to a named
+ * configuration
+ * template
+ *
+ * @param string $name
+ * @param array $options
+ * @return Zend_Cache_Manager
+ * @throws Zend_Cache_Exception for invalid options format or if option templates do not have $name
+ */
+ public function setTemplateOptions($name, $options)
+ {
+ if ($options instanceof Zend_Config) {
+ $options = $options->toArray();
+ } elseif (!is_array($options)) {
+ require_once 'Zend/Cache/Exception.php';
+ throw new Zend_Cache_Exception('Options passed must be in'
+ . ' an associative array or instance of Zend_Config');
+ }
+ if (!isset($this->_optionTemplates[$name])) {
+ throw new Zend_Cache_Exception('A cache configuration template'
+ . 'does not exist with the name "' . $name . '"');
+ }
+ $this->_optionTemplates[$name]
+ = $this->_mergeOptions($this->_optionTemplates[$name], $options);
+ return $this;
+ }
+
+ /**
+ * Simple method to merge two configuration arrays
+ *
+ * @param array $current
+ * @param array $options
+ * @return array
+ */
+ protected function _mergeOptions(array $current, array $options)
+ {
+ if (isset($options['frontend']['name'])) {
+ $current['frontend']['name'] = $options['frontend']['name'];
+ }
+ if (isset($options['backend']['name'])) {
+ $current['backend']['name'] = $options['backend']['name'];
+ }
+ if (isset($options['frontend']['options'])) {
+ foreach ($options['frontend']['options'] as $key => $value) {
+ $current['frontend']['options'][$key] = $value;
+ }
+ }
+ if (isset($options['backend']['options'])) {
+ foreach ($options['backend']['options'] as $key => $value) {
+ $current['backend']['options'][$key] = $value;
+ }
+ }
+ if (isset($options['frontend']['customFrontendNaming'])) {
+ $current['frontend']['customFrontendNaming'] = $options['frontend']['customFrontendNaming'];
+ }
+ if (isset($options['backend']['customBackendNaming'])) {
+ $current['backend']['customBackendNaming'] = $options['backend']['customBackendNaming'];
+ }
+ if (isset($options['frontendBackendAutoload'])) {
+ $current['frontendBackendAutoload'] = $options['frontendBackendAutoload'];
+ }
+ return $current;
+ }
+}
diff --git a/lib/zend/Zend/Config.php b/lib/zend/Zend/Config.php
new file mode 100644
index 00000000000..a39a1f22559
--- /dev/null
+++ b/lib/zend/Zend/Config.php
@@ -0,0 +1,484 @@
+_allowModifications = (boolean) $allowModifications;
+ $this->_loadedSection = null;
+ $this->_index = 0;
+ $this->_data = array();
+ foreach ($array as $key => $value) {
+ if (is_array($value)) {
+ $this->_data[$key] = new self($value, $this->_allowModifications);
+ } else {
+ $this->_data[$key] = $value;
+ }
+ }
+ $this->_count = count($this->_data);
+ }
+
+ /**
+ * Retrieve a value and return $default if there is no element set.
+ *
+ * @param string $name
+ * @param mixed $default
+ * @return mixed
+ */
+ public function get($name, $default = null)
+ {
+ $result = $default;
+ if (array_key_exists($name, $this->_data)) {
+ $result = $this->_data[$name];
+ }
+ return $result;
+ }
+
+ /**
+ * Magic function so that $obj->value will work.
+ *
+ * @param string $name
+ * @return mixed
+ */
+ public function __get($name)
+ {
+ return $this->get($name);
+ }
+
+ /**
+ * Only allow setting of a property if $allowModifications
+ * was set to true on construction. Otherwise, throw an exception.
+ *
+ * @param string $name
+ * @param mixed $value
+ * @throws Zend_Config_Exception
+ * @return void
+ */
+ public function __set($name, $value)
+ {
+ if ($this->_allowModifications) {
+ if (is_array($value)) {
+ $this->_data[$name] = new self($value, true);
+ } else {
+ $this->_data[$name] = $value;
+ }
+ $this->_count = count($this->_data);
+ } else {
+ /** @see Zend_Config_Exception */
+ require_once 'Zend/Config/Exception.php';
+ throw new Zend_Config_Exception('Zend_Config is read only');
+ }
+ }
+
+ /**
+ * Deep clone of this instance to ensure that nested Zend_Configs
+ * are also cloned.
+ *
+ * @return void
+ */
+ public function __clone()
+ {
+ $array = array();
+ foreach ($this->_data as $key => $value) {
+ if ($value instanceof Zend_Config) {
+ $array[$key] = clone $value;
+ } else {
+ $array[$key] = $value;
+ }
+ }
+ $this->_data = $array;
+ }
+
+ /**
+ * Return an associative array of the stored data.
+ *
+ * @return array
+ */
+ public function toArray()
+ {
+ $array = array();
+ $data = $this->_data;
+ foreach ($data as $key => $value) {
+ if ($value instanceof Zend_Config) {
+ $array[$key] = $value->toArray();
+ } else {
+ $array[$key] = $value;
+ }
+ }
+ return $array;
+ }
+
+ /**
+ * Support isset() overloading on PHP 5.1
+ *
+ * @param string $name
+ * @return boolean
+ */
+ public function __isset($name)
+ {
+ return isset($this->_data[$name]);
+ }
+
+ /**
+ * Support unset() overloading on PHP 5.1
+ *
+ * @param string $name
+ * @throws Zend_Config_Exception
+ * @return void
+ */
+ public function __unset($name)
+ {
+ if ($this->_allowModifications) {
+ unset($this->_data[$name]);
+ $this->_count = count($this->_data);
+ $this->_skipNextIteration = true;
+ } else {
+ /** @see Zend_Config_Exception */
+ require_once 'Zend/Config/Exception.php';
+ throw new Zend_Config_Exception('Zend_Config is read only');
+ }
+
+ }
+
+ /**
+ * Defined by Countable interface
+ *
+ * @return int
+ */
+ public function count()
+ {
+ return $this->_count;
+ }
+
+ /**
+ * Defined by Iterator interface
+ *
+ * @return mixed
+ */
+ public function current()
+ {
+ $this->_skipNextIteration = false;
+ return current($this->_data);
+ }
+
+ /**
+ * Defined by Iterator interface
+ *
+ * @return mixed
+ */
+ public function key()
+ {
+ return key($this->_data);
+ }
+
+ /**
+ * Defined by Iterator interface
+ *
+ */
+ public function next()
+ {
+ if ($this->_skipNextIteration) {
+ $this->_skipNextIteration = false;
+ return;
+ }
+ next($this->_data);
+ $this->_index++;
+ }
+
+ /**
+ * Defined by Iterator interface
+ *
+ */
+ public function rewind()
+ {
+ $this->_skipNextIteration = false;
+ reset($this->_data);
+ $this->_index = 0;
+ }
+
+ /**
+ * Defined by Iterator interface
+ *
+ * @return boolean
+ */
+ public function valid()
+ {
+ return $this->_index < $this->_count;
+ }
+
+ /**
+ * Returns the section name(s) loaded.
+ *
+ * @return mixed
+ */
+ public function getSectionName()
+ {
+ if(is_array($this->_loadedSection) && count($this->_loadedSection) == 1) {
+ $this->_loadedSection = $this->_loadedSection[0];
+ }
+ return $this->_loadedSection;
+ }
+
+ /**
+ * Returns true if all sections were loaded
+ *
+ * @return boolean
+ */
+ public function areAllSectionsLoaded()
+ {
+ return $this->_loadedSection === null;
+ }
+
+
+ /**
+ * Merge another Zend_Config with this one. The items
+ * in $merge will override the same named items in
+ * the current config.
+ *
+ * @param Zend_Config $merge
+ * @return Zend_Config
+ */
+ public function merge(Zend_Config $merge)
+ {
+ foreach($merge as $key => $item) {
+ if(array_key_exists($key, $this->_data)) {
+ if($item instanceof Zend_Config && $this->$key instanceof Zend_Config) {
+ $this->$key = $this->$key->merge(new Zend_Config($item->toArray(), !$this->readOnly()));
+ } else {
+ $this->$key = $item;
+ }
+ } else {
+ if($item instanceof Zend_Config) {
+ $this->$key = new Zend_Config($item->toArray(), !$this->readOnly());
+ } else {
+ $this->$key = $item;
+ }
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Prevent any more modifications being made to this instance. Useful
+ * after merge() has been used to merge multiple Zend_Config objects
+ * into one object which should then not be modified again.
+ *
+ */
+ public function setReadOnly()
+ {
+ $this->_allowModifications = false;
+ foreach ($this->_data as $key => $value) {
+ if ($value instanceof Zend_Config) {
+ $value->setReadOnly();
+ }
+ }
+ }
+
+ /**
+ * Returns if this Zend_Config object is read only or not.
+ *
+ * @return boolean
+ */
+ public function readOnly()
+ {
+ return !$this->_allowModifications;
+ }
+
+ /**
+ * Get the current extends
+ *
+ * @return array
+ */
+ public function getExtends()
+ {
+ return $this->_extends;
+ }
+
+ /**
+ * Set an extend for Zend_Config_Writer
+ *
+ * @param string $extendingSection
+ * @param string $extendedSection
+ * @return void
+ */
+ public function setExtend($extendingSection, $extendedSection = null)
+ {
+ if ($extendedSection === null && isset($this->_extends[$extendingSection])) {
+ unset($this->_extends[$extendingSection]);
+ } else if ($extendedSection !== null) {
+ $this->_extends[$extendingSection] = $extendedSection;
+ }
+ }
+
+ /**
+ * Throws an exception if $extendingSection may not extend $extendedSection,
+ * and tracks the section extension if it is valid.
+ *
+ * @param string $extendingSection
+ * @param string $extendedSection
+ * @throws Zend_Config_Exception
+ * @return void
+ */
+ protected function _assertValidExtend($extendingSection, $extendedSection)
+ {
+ // detect circular section inheritance
+ $extendedSectionCurrent = $extendedSection;
+ while (array_key_exists($extendedSectionCurrent, $this->_extends)) {
+ if ($this->_extends[$extendedSectionCurrent] == $extendingSection) {
+ /** @see Zend_Config_Exception */
+ require_once 'Zend/Config/Exception.php';
+ throw new Zend_Config_Exception('Illegal circular inheritance detected');
+ }
+ $extendedSectionCurrent = $this->_extends[$extendedSectionCurrent];
+ }
+ // remember that this section extends another section
+ $this->_extends[$extendingSection] = $extendedSection;
+ }
+
+ /**
+ * Handle any errors from simplexml_load_file or parse_ini_file
+ *
+ * @param integer $errno
+ * @param string $errstr
+ * @param string $errfile
+ * @param integer $errline
+ */
+ public function _loadFileErrorHandler($errno, $errstr, $errfile, $errline)
+ {
+ if ($this->_loadFileErrorStr === null) {
+ $this->_loadFileErrorStr = $errstr;
+ } else {
+ $this->_loadFileErrorStr .= (PHP_EOL . $errstr);
+ }
+ }
+
+ /**
+ * Merge two arrays recursively, overwriting keys of the same name
+ * in $firstArray with the value in $secondArray.
+ *
+ * @param mixed $firstArray First array
+ * @param mixed $secondArray Second array to merge into first array
+ * @return array
+ */
+ protected function _arrayMergeRecursive($firstArray, $secondArray)
+ {
+ if (is_array($firstArray) && is_array($secondArray)) {
+ foreach ($secondArray as $key => $value) {
+ if (isset($firstArray[$key])) {
+ $firstArray[$key] = $this->_arrayMergeRecursive($firstArray[$key], $value);
+ } else {
+ if($key === 0) {
+ $firstArray= array(0=>$this->_arrayMergeRecursive($firstArray, $value));
+ } else {
+ $firstArray[$key] = $value;
+ }
+ }
+ }
+ } else {
+ $firstArray = $secondArray;
+ }
+
+ return $firstArray;
+ }
+}
diff --git a/lib/zend/Zend/Config/Exception.php b/lib/zend/Zend/Config/Exception.php
new file mode 100644
index 00000000000..253b3346825
--- /dev/null
+++ b/lib/zend/Zend/Config/Exception.php
@@ -0,0 +1,33 @@
+hostname === "staging"
+ * $data->db->connection === "database"
+ *
+ * The $options parameter may be provided as either a boolean or an array.
+ * If provided as a boolean, this sets the $allowModifications option of
+ * Zend_Config. If provided as an array, there are three configuration
+ * directives that may be set. For example:
+ *
+ * $options = array(
+ * 'allowModifications' => false,
+ * 'nestSeparator' => ':',
+ * 'skipExtends' => false,
+ * );
+ *
+ * @param string $filename
+ * @param mixed $section
+ * @param boolean|array $options
+ * @throws Zend_Config_Exception
+ * @return void
+ */
+ public function __construct($filename, $section = null, $options = false)
+ {
+ if (empty($filename)) {
+ /**
+ * @see Zend_Config_Exception
+ */
+ require_once 'Zend/Config/Exception.php';
+ throw new Zend_Config_Exception('Filename is not set');
+ }
+
+ $allowModifications = false;
+ if (is_bool($options)) {
+ $allowModifications = $options;
+ } elseif (is_array($options)) {
+ if (isset($options['allowModifications'])) {
+ $allowModifications = (bool) $options['allowModifications'];
+ }
+ if (isset($options['nestSeparator'])) {
+ $this->_nestSeparator = (string) $options['nestSeparator'];
+ }
+ if (isset($options['skipExtends'])) {
+ $this->_skipExtends = (bool) $options['skipExtends'];
+ }
+ }
+
+ $iniArray = $this->_loadIniFile($filename);
+
+ if (null === $section) {
+ // Load entire file
+ $dataArray = array();
+ foreach ($iniArray as $sectionName => $sectionData) {
+ if(!is_array($sectionData)) {
+ $dataArray = $this->_arrayMergeRecursive($dataArray, $this->_processKey(array(), $sectionName, $sectionData));
+ } else {
+ $dataArray[$sectionName] = $this->_processSection($iniArray, $sectionName);
+ }
+ }
+ parent::__construct($dataArray, $allowModifications);
+ } else {
+ // Load one or more sections
+ if (!is_array($section)) {
+ $section = array($section);
+ }
+ $dataArray = array();
+ foreach ($section as $sectionName) {
+ if (!isset($iniArray[$sectionName])) {
+ /**
+ * @see Zend_Config_Exception
+ */
+ require_once 'Zend/Config/Exception.php';
+ throw new Zend_Config_Exception("Section '$sectionName' cannot be found in $filename");
+ }
+ $dataArray = $this->_arrayMergeRecursive($this->_processSection($iniArray, $sectionName), $dataArray);
+
+ }
+ parent::__construct($dataArray, $allowModifications);
+ }
+
+ $this->_loadedSection = $section;
+ }
+
+ /**
+ * Load the INI file from disk using parse_ini_file(). Use a private error
+ * handler to convert any loading errors into a Zend_Config_Exception
+ *
+ * @param string $filename
+ * @throws Zend_Config_Exception
+ * @return array
+ */
+ protected function _parseIniFile($filename)
+ {
+ set_error_handler(array($this, '_loadFileErrorHandler'));
+ $iniArray = parse_ini_file($filename, true); // Warnings and errors are suppressed
+ restore_error_handler();
+
+ // Check if there was a error while loading file
+ if ($this->_loadFileErrorStr !== null) {
+ /**
+ * @see Zend_Config_Exception
+ */
+ require_once 'Zend/Config/Exception.php';
+ throw new Zend_Config_Exception($this->_loadFileErrorStr);
+ }
+
+ return $iniArray;
+ }
+
+ /**
+ * Load the ini file and preprocess the section separator (':' in the
+ * section name (that is used for section extension) so that the resultant
+ * array has the correct section names and the extension information is
+ * stored in a sub-key called ';extends'. We use ';extends' as this can
+ * never be a valid key name in an INI file that has been loaded using
+ * parse_ini_file().
+ *
+ * @param string $filename
+ * @throws Zend_Config_Exception
+ * @return array
+ */
+ protected function _loadIniFile($filename)
+ {
+ $loaded = $this->_parseIniFile($filename);
+ $iniArray = array();
+ foreach ($loaded as $key => $data)
+ {
+ $pieces = explode($this->_sectionSeparator, $key);
+ $thisSection = trim($pieces[0]);
+ switch (count($pieces)) {
+ case 1:
+ $iniArray[$thisSection] = $data;
+ break;
+
+ case 2:
+ $extendedSection = trim($pieces[1]);
+ $iniArray[$thisSection] = array_merge(array(';extends'=>$extendedSection), $data);
+ break;
+
+ default:
+ /**
+ * @see Zend_Config_Exception
+ */
+ require_once 'Zend/Config/Exception.php';
+ throw new Zend_Config_Exception("Section '$thisSection' may not extend multiple sections in $filename");
+ }
+ }
+
+ return $iniArray;
+ }
+
+ /**
+ * Process each element in the section and handle the ";extends" inheritance
+ * key. Passes control to _processKey() to handle the nest separator
+ * sub-property syntax that may be used within the key name.
+ *
+ * @param array $iniArray
+ * @param string $section
+ * @param array $config
+ * @throws Zend_Config_Exception
+ * @return array
+ */
+ protected function _processSection($iniArray, $section, $config = array())
+ {
+ $thisSection = $iniArray[$section];
+
+ foreach ($thisSection as $key => $value) {
+ if (strtolower($key) == ';extends') {
+ if (isset($iniArray[$value])) {
+ $this->_assertValidExtend($section, $value);
+
+ if (!$this->_skipExtends) {
+ $config = $this->_processSection($iniArray, $value, $config);
+ }
+ } else {
+ /**
+ * @see Zend_Config_Exception
+ */
+ require_once 'Zend/Config/Exception.php';
+ throw new Zend_Config_Exception("Parent section '$section' cannot be found");
+ }
+ } else {
+ $config = $this->_processKey($config, $key, $value);
+ }
+ }
+ return $config;
+ }
+
+ /**
+ * Assign the key's value to the property list. Handles the
+ * nest separator for sub-properties.
+ *
+ * @param array $config
+ * @param string $key
+ * @param string $value
+ * @throws Zend_Config_Exception
+ * @return array
+ */
+ protected function _processKey($config, $key, $value)
+ {
+ if (strpos($key, $this->_nestSeparator) !== false) {
+ $pieces = explode($this->_nestSeparator, $key, 2);
+ if (strlen($pieces[0]) && strlen($pieces[1])) {
+ if (!isset($config[$pieces[0]])) {
+ if ($pieces[0] === '0' && !empty($config)) {
+ // convert the current values in $config into an array
+ $config = array($pieces[0] => $config);
+ } else {
+ $config[$pieces[0]] = array();
+ }
+ } elseif (!is_array($config[$pieces[0]])) {
+ /**
+ * @see Zend_Config_Exception
+ */
+ require_once 'Zend/Config/Exception.php';
+ throw new Zend_Config_Exception("Cannot create sub-key for '{$pieces[0]}' as key already exists");
+ }
+ $config[$pieces[0]] = $this->_processKey($config[$pieces[0]], $pieces[1], $value);
+ } else {
+ /**
+ * @see Zend_Config_Exception
+ */
+ require_once 'Zend/Config/Exception.php';
+ throw new Zend_Config_Exception("Invalid key '$key'");
+ }
+ } else {
+ $config[$key] = $value;
+ }
+ return $config;
+ }
+}
diff --git a/lib/zend/Zend/Config/Json.php b/lib/zend/Zend/Config/Json.php
new file mode 100755
index 00000000000..2c31fdc0140
--- /dev/null
+++ b/lib/zend/Zend/Config/Json.php
@@ -0,0 +1,242 @@
+ $value) {
+ switch (strtolower($key)) {
+ case 'allow_modifications':
+ case 'allowmodifications':
+ $allowModifications = (bool) $value;
+ break;
+ case 'skip_extends':
+ case 'skipextends':
+ $this->_skipExtends = (bool) $value;
+ break;
+ case 'ignore_constants':
+ case 'ignoreconstants':
+ $this->_ignoreConstants = (bool) $value;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ set_error_handler(array($this, '_loadFileErrorHandler')); // Warnings and errors are suppressed
+ if ($json[0] != '{') {
+ $json = file_get_contents($json);
+ }
+ restore_error_handler();
+
+ // Check if there was a error while loading file
+ if ($this->_loadFileErrorStr !== null) {
+ require_once 'Zend/Config/Exception.php';
+ throw new Zend_Config_Exception($this->_loadFileErrorStr);
+ }
+
+ // Replace constants
+ if (!$this->_ignoreConstants) {
+ $json = $this->_replaceConstants($json);
+ }
+
+ // Parse/decode
+ try {
+ $config = Zend_Json::decode($json);
+ } catch (Zend_Json_Exception $e) {
+ // decode failed
+ require_once 'Zend/Config/Exception.php';
+ throw new Zend_Config_Exception("Error parsing JSON data");
+ }
+
+ if ($section === null) {
+ $dataArray = array();
+ foreach ($config as $sectionName => $sectionData) {
+ $dataArray[$sectionName] = $this->_processExtends($config, $sectionName);
+ }
+
+ parent::__construct($dataArray, $allowModifications);
+ } elseif (is_array($section)) {
+ $dataArray = array();
+ foreach ($section as $sectionName) {
+ if (!isset($config[$sectionName])) {
+ require_once 'Zend/Config/Exception.php';
+ throw new Zend_Config_Exception(sprintf('Section "%s" cannot be found', $sectionName));
+ }
+
+ $dataArray = array_merge($this->_processExtends($config, $sectionName), $dataArray);
+ }
+
+ parent::__construct($dataArray, $allowModifications);
+ } else {
+ if (!isset($config[$section])) {
+ require_once 'Zend/Config/Exception.php';
+ throw new Zend_Config_Exception(sprintf('Section "%s" cannot be found', $section));
+ }
+
+ $dataArray = $this->_processExtends($config, $section);
+ if (!is_array($dataArray)) {
+ // Section in the JSON data contains just one top level string
+ $dataArray = array($section => $dataArray);
+ }
+
+ parent::__construct($dataArray, $allowModifications);
+ }
+
+ $this->_loadedSection = $section;
+ }
+
+ /**
+ * Helper function to process each element in the section and handle
+ * the "_extends" inheritance attribute.
+ *
+ * @param array $data Data array to process
+ * @param string $section Section to process
+ * @param array $config Configuration which was parsed yet
+ * @throws Zend_Config_Exception When $section cannot be found
+ * @return array
+ */
+ protected function _processExtends(array $data, $section, array $config = array())
+ {
+ if (!isset($data[$section])) {
+ require_once 'Zend/Config/Exception.php';
+ throw new Zend_Config_Exception(sprintf('Section "%s" cannot be found', $section));
+ }
+
+ $thisSection = $data[$section];
+
+ if (is_array($thisSection) && isset($thisSection[self::EXTENDS_NAME])) {
+ if (is_array($thisSection[self::EXTENDS_NAME])) {
+ require_once 'Zend/Config/Exception.php';
+ throw new Zend_Config_Exception('Invalid extends clause: must be a string; array received');
+ }
+ $this->_assertValidExtend($section, $thisSection[self::EXTENDS_NAME]);
+
+ if (!$this->_skipExtends) {
+ $config = $this->_processExtends($data, $thisSection[self::EXTENDS_NAME], $config);
+ }
+ unset($thisSection[self::EXTENDS_NAME]);
+ }
+
+ $config = $this->_arrayMergeRecursive($config, $thisSection);
+
+ return $config;
+ }
+
+ /**
+ * Replace any constants referenced in a string with their values
+ *
+ * @param string $value
+ * @return string
+ */
+ protected function _replaceConstants($value)
+ {
+ foreach ($this->_getConstants() as $constant) {
+ if (strstr($value, $constant)) {
+ // handle backslashes that may represent windows path names for instance
+ $replacement = str_replace('\\', '\\\\', constant($constant));
+ $value = str_replace($constant, $replacement, $value);
+ }
+ }
+ return $value;
+ }
+
+ /**
+ * Get (reverse) sorted list of defined constant names
+ *
+ * @return array
+ */
+ protected function _getConstants()
+ {
+ $constants = array_keys(get_defined_constants());
+ rsort($constants, SORT_STRING);
+ return $constants;
+ }
+}
diff --git a/lib/zend/Zend/Config/Writer.php b/lib/zend/Zend/Config/Writer.php
new file mode 100644
index 00000000000..8c255b3c847
--- /dev/null
+++ b/lib/zend/Zend/Config/Writer.php
@@ -0,0 +1,101 @@
+setOptions($options);
+ }
+ }
+
+ /**
+ * Set options via a Zend_Config instance
+ *
+ * @param Zend_Config $config
+ * @return Zend_Config_Writer
+ */
+ public function setConfig(Zend_Config $config)
+ {
+ $this->_config = $config;
+
+ return $this;
+ }
+
+ /**
+ * Set options via an array
+ *
+ * @param array $options
+ * @return Zend_Config_Writer
+ */
+ public function setOptions(array $options)
+ {
+ foreach ($options as $key => $value) {
+ if (in_array(strtolower($key), $this->_skipOptions)) {
+ continue;
+ }
+
+ $method = 'set' . ucfirst($key);
+ if (method_exists($this, $method)) {
+ $this->$method($value);
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Write a Zend_Config object to it's target
+ *
+ * @return void
+ */
+ abstract public function write();
+}
diff --git a/lib/zend/Zend/Service/DeveloperGarden/Response/VoiceButler/TearDownCallResponse.php b/lib/zend/Zend/Config/Writer/Array.php
similarity index 51%
rename from lib/zend/Zend/Service/DeveloperGarden/Response/VoiceButler/TearDownCallResponse.php
rename to lib/zend/Zend/Config/Writer/Array.php
index 6ea614a9d22..50c260e0cf0 100644
--- a/lib/zend/Zend/Service/DeveloperGarden/Response/VoiceButler/TearDownCallResponse.php
+++ b/lib/zend/Zend/Config/Writer/Array.php
@@ -13,38 +13,43 @@
* to license@zend.com so we can send you a copy immediately.
*
* @category Zend
- * @package Zend_Service
- * @subpackage DeveloperGarden
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @package Zend_Config
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
- * @see Zend_Service_DeveloperGarden_Response_VoiceButler_VoiceButlerAbstract
+ * @see Zend_Config_Writer
*/
-require_once 'Zend/Service/DeveloperGarden/Response/VoiceButler/VoiceButlerAbstract.php';
+require_once 'Zend/Config/Writer/FileAbstract.php';
/**
* @category Zend
- * @package Zend_Service
- * @subpackage DeveloperGarden
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
- * @author Marco Kaiser
+ * @package Zend_Config
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
-class Zend_Service_DeveloperGarden_Response_VoiceButler_TearDownCallResponse
- extends Zend_Service_DeveloperGarden_Response_VoiceButler_VoiceButlerAbstract
+class Zend_Config_Writer_Array extends Zend_Config_Writer_FileAbstract
{
/**
- * returns the session id
+ * Render a Zend_Config into a PHP Array config string.
+ *
+ * @since 1.10
* @return string
*/
- public function getSessionId()
+ public function render()
{
- if (isset($this->return->sessionId)) {
- return $this->return->sessionId;
+ $data = $this->_config->toArray();
+ $sectionName = $this->_config->getSectionName();
+
+ if (is_string($sectionName)) {
+ $data = array($sectionName => $data);
}
- return null;
+
+ $arrayString = "_filename = $filename;
+
+ return $this;
+ }
+
+ /**
+ * Set wether to exclusively lock the file or not
+ *
+ * @param boolean $exclusiveLock
+ * @return Zend_Config_Writer_Array
+ */
+ public function setExclusiveLock($exclusiveLock)
+ {
+ $this->_exclusiveLock = $exclusiveLock;
+
+ return $this;
+ }
+
+ /**
+ * Write configuration to file.
+ *
+ * @param string $filename
+ * @param Zend_Config $config
+ * @param bool $exclusiveLock
+ * @return void
+ */
+ public function write($filename = null, Zend_Config $config = null, $exclusiveLock = null)
+ {
+ if ($filename !== null) {
+ $this->setFilename($filename);
+ }
+
+ if ($config !== null) {
+ $this->setConfig($config);
+ }
+
+ if ($exclusiveLock !== null) {
+ $this->setExclusiveLock($exclusiveLock);
+ }
+
+ if ($this->_filename === null) {
+ require_once 'Zend/Config/Exception.php';
+ throw new Zend_Config_Exception('No filename was set');
+ }
+
+ if ($this->_config === null) {
+ require_once 'Zend/Config/Exception.php';
+ throw new Zend_Config_Exception('No config was set');
+ }
+
+ $configString = $this->render();
+
+ $flags = 0;
+
+ if ($this->_exclusiveLock) {
+ $flags |= LOCK_EX;
+ }
+
+ $result = @file_put_contents($this->_filename, $configString, $flags);
+
+ if ($result === false) {
+ require_once 'Zend/Config/Exception.php';
+ throw new Zend_Config_Exception('Could not write to file "' . $this->_filename . '"');
+ }
+ }
+
+ /**
+ * Render a Zend_Config into a config file string.
+ *
+ * @since 1.10
+ * @todo For 2.0 this should be redone into an abstract method.
+ * @return string
+ */
+ public function render()
+ {
+ return "";
+ }
+}
diff --git a/lib/zend/Zend/Config/Writer/Ini.php b/lib/zend/Zend/Config/Writer/Ini.php
new file mode 100644
index 00000000000..15344a5b740
--- /dev/null
+++ b/lib/zend/Zend/Config/Writer/Ini.php
@@ -0,0 +1,193 @@
+_nestSeparator = $separator;
+
+ return $this;
+ }
+
+ /**
+ * Set if rendering should occour without sections or not.
+ *
+ * If set to true, the INI file is rendered without sections completely
+ * into the global namespace of the INI file.
+ *
+ * @param bool $withoutSections
+ * @return Zend_Config_Writer_Ini
+ */
+ public function setRenderWithoutSections($withoutSections=true)
+ {
+ $this->_renderWithoutSections = (bool)$withoutSections;
+ return $this;
+ }
+
+ /**
+ * Render a Zend_Config into a INI config string.
+ *
+ * @since 1.10
+ * @return string
+ */
+ public function render()
+ {
+ $iniString = '';
+ $extends = $this->_config->getExtends();
+ $sectionName = $this->_config->getSectionName();
+
+ if($this->_renderWithoutSections == true) {
+ $iniString .= $this->_addBranch($this->_config);
+ } else if (is_string($sectionName)) {
+ $iniString .= '[' . $sectionName . ']' . "\n"
+ . $this->_addBranch($this->_config)
+ . "\n";
+ } else {
+ $config = $this->_sortRootElements($this->_config);
+ foreach ($config as $sectionName => $data) {
+ if (!($data instanceof Zend_Config)) {
+ $iniString .= $sectionName
+ . ' = '
+ . $this->_prepareValue($data)
+ . "\n";
+ } else {
+ if (isset($extends[$sectionName])) {
+ $sectionName .= ' : ' . $extends[$sectionName];
+ }
+
+ $iniString .= '[' . $sectionName . ']' . "\n"
+ . $this->_addBranch($data)
+ . "\n";
+ }
+ }
+ }
+
+ return $iniString;
+ }
+
+ /**
+ * Add a branch to an INI string recursively
+ *
+ * @param Zend_Config $config
+ * @return void
+ */
+ protected function _addBranch(Zend_Config $config, $parents = array())
+ {
+ $iniString = '';
+
+ foreach ($config as $key => $value) {
+ $group = array_merge($parents, array($key));
+
+ if ($value instanceof Zend_Config) {
+ $iniString .= $this->_addBranch($value, $group);
+ } else {
+ $iniString .= implode($this->_nestSeparator, $group)
+ . ' = '
+ . $this->_prepareValue($value)
+ . "\n";
+ }
+ }
+
+ return $iniString;
+ }
+
+ /**
+ * Prepare a value for INI
+ *
+ * @param mixed $value
+ * @return string
+ */
+ protected function _prepareValue($value)
+ {
+ if (is_integer($value) || is_float($value)) {
+ return $value;
+ } elseif (is_bool($value)) {
+ return ($value ? 'true' : 'false');
+ } elseif (strpos($value, '"') === false) {
+ return '"' . $value . '"';
+ } else {
+ /** @see Zend_Config_Exception */
+ require_once 'Zend/Config/Exception.php';
+ throw new Zend_Config_Exception('Value can not contain double quotes "');
+ }
+ }
+
+ /**
+ * Root elements that are not assigned to any section needs to be
+ * on the top of config.
+ *
+ * @see http://framework.zend.com/issues/browse/ZF-6289
+ * @param Zend_Config
+ * @return Zend_Config
+ */
+ protected function _sortRootElements(Zend_Config $config)
+ {
+ $configArray = $config->toArray();
+ $sections = array();
+
+ // remove sections from config array
+ foreach ($configArray as $key => $value) {
+ if (is_array($value)) {
+ $sections[$key] = $value;
+ unset($configArray[$key]);
+ }
+ }
+
+ // readd sections to the end
+ foreach ($sections as $key => $value) {
+ $configArray[$key] = $value;
+ }
+
+ return new Zend_Config($configArray);
+ }
+}
diff --git a/lib/zend/Zend/Config/Writer/Json.php b/lib/zend/Zend/Config/Writer/Json.php
new file mode 100755
index 00000000000..25da4a9038c
--- /dev/null
+++ b/lib/zend/Zend/Config/Writer/Json.php
@@ -0,0 +1,106 @@
+_prettyPrint;
+ }
+
+ /**
+ * Set prettyPrint flag
+ *
+ * @param bool $prettyPrint PrettyPrint flag
+ * @return Zend_Config_Writer_Json
+ */
+ public function setPrettyPrint($flag)
+ {
+ $this->_prettyPrint = (bool) $flag;
+ return $this;
+ }
+
+ /**
+ * Render a Zend_Config into a JSON config string.
+ *
+ * @since 1.10
+ * @return string
+ */
+ public function render()
+ {
+ $data = $this->_config->toArray();
+ $sectionName = $this->_config->getSectionName();
+ $extends = $this->_config->getExtends();
+
+ if (is_string($sectionName)) {
+ $data = array($sectionName => $data);
+ }
+
+ foreach ($extends as $section => $parentSection) {
+ $data[$section][Zend_Config_Json::EXTENDS_NAME] = $parentSection;
+ }
+
+ // Ensure that each "extends" section actually exists
+ foreach ($data as $section => $sectionData) {
+ if (is_array($sectionData) && isset($sectionData[Zend_Config_Json::EXTENDS_NAME])) {
+ $sectionExtends = $sectionData[Zend_Config_Json::EXTENDS_NAME];
+ if (!isset($data[$sectionExtends])) {
+ // Remove "extends" declaration if section does not exist
+ unset($data[$section][Zend_Config_Json::EXTENDS_NAME]);
+ }
+ }
+ }
+
+ $out = Zend_Json::encode($data);
+ if ($this->prettyPrint()) {
+ $out = Zend_Json::prettyPrint($out);
+ }
+ return $out;
+ }
+}
diff --git a/lib/zend/Zend/Config/Writer/Xml.php b/lib/zend/Zend/Config/Writer/Xml.php
new file mode 100644
index 00000000000..c73564b2190
--- /dev/null
+++ b/lib/zend/Zend/Config/Writer/Xml.php
@@ -0,0 +1,127 @@
+');
+ $extends = $this->_config->getExtends();
+ $sectionName = $this->_config->getSectionName();
+
+ if (is_string($sectionName)) {
+ $child = $xml->addChild($sectionName);
+
+ $this->_addBranch($this->_config, $child, $xml);
+ } else {
+ foreach ($this->_config as $sectionName => $data) {
+ if (!($data instanceof Zend_Config)) {
+ $xml->addChild($sectionName, (string) $data);
+ } else {
+ $child = $xml->addChild($sectionName);
+
+ if (isset($extends[$sectionName])) {
+ $child->addAttribute('zf:extends', $extends[$sectionName], Zend_Config_Xml::XML_NAMESPACE);
+ }
+
+ $this->_addBranch($data, $child, $xml);
+ }
+ }
+ }
+
+ $dom = dom_import_simplexml($xml)->ownerDocument;
+ $dom->formatOutput = true;
+
+ $xmlString = $dom->saveXML();
+
+ return $xmlString;
+ }
+
+ /**
+ * Add a branch to an XML object recursively
+ *
+ * @param Zend_Config $config
+ * @param SimpleXMLElement $xml
+ * @param SimpleXMLElement $parent
+ * @return void
+ */
+ protected function _addBranch(Zend_Config $config, SimpleXMLElement $xml, SimpleXMLElement $parent)
+ {
+ $branchType = null;
+
+ foreach ($config as $key => $value) {
+ if ($branchType === null) {
+ if (is_numeric($key)) {
+ $branchType = 'numeric';
+ $branchName = $xml->getName();
+ $xml = $parent;
+
+ unset($parent->{$branchName});
+ } else {
+ $branchType = 'string';
+ }
+ } else if ($branchType !== (is_numeric($key) ? 'numeric' : 'string')) {
+ require_once 'Zend/Config/Exception.php';
+ throw new Zend_Config_Exception('Mixing of string and numeric keys is not allowed');
+ }
+
+ if ($branchType === 'numeric') {
+ if ($value instanceof Zend_Config) {
+ $child = $parent->addChild($branchName);
+
+ $this->_addBranch($value, $child, $parent);
+ } else {
+ $parent->addChild($branchName, (string) $value);
+ }
+ } else {
+ if ($value instanceof Zend_Config) {
+ $child = $xml->addChild($key);
+
+ $this->_addBranch($value, $child, $xml);
+ } else {
+ $xml->addChild($key, (string) $value);
+ }
+ }
+ }
+ }
+}
diff --git a/lib/zend/Zend/Config/Writer/Yaml.php b/lib/zend/Zend/Config/Writer/Yaml.php
new file mode 100755
index 00000000000..4d2b1fed442
--- /dev/null
+++ b/lib/zend/Zend/Config/Writer/Yaml.php
@@ -0,0 +1,144 @@
+_yamlEncoder;
+ }
+
+ /**
+ * Set callback for decoding YAML
+ *
+ * @param callable $yamlEncoder the decoder to set
+ * @return Zend_Config_Yaml
+ */
+ public function setYamlEncoder($yamlEncoder)
+ {
+ if (!is_callable($yamlEncoder)) {
+ require_once 'Zend/Config/Exception.php';
+ throw new Zend_Config_Exception('Invalid parameter to setYamlEncoder - must be callable');
+ }
+
+ $this->_yamlEncoder = $yamlEncoder;
+ return $this;
+ }
+
+ /**
+ * Render a Zend_Config into a YAML config string.
+ *
+ * @since 1.10
+ * @return string
+ */
+ public function render()
+ {
+ $data = $this->_config->toArray();
+ $sectionName = $this->_config->getSectionName();
+ $extends = $this->_config->getExtends();
+
+ if (is_string($sectionName)) {
+ $data = array($sectionName => $data);
+ }
+
+ foreach ($extends as $section => $parentSection) {
+ $data[$section][Zend_Config_Yaml::EXTENDS_NAME] = $parentSection;
+ }
+
+ // Ensure that each "extends" section actually exists
+ foreach ($data as $section => $sectionData) {
+ if (is_array($sectionData) && isset($sectionData[Zend_Config_Yaml::EXTENDS_NAME])) {
+ $sectionExtends = $sectionData[Zend_Config_Yaml::EXTENDS_NAME];
+ if (!isset($data[$sectionExtends])) {
+ // Remove "extends" declaration if section does not exist
+ unset($data[$section][Zend_Config_Yaml::EXTENDS_NAME]);
+ }
+ }
+ }
+
+ return call_user_func($this->getYamlEncoder(), $data);
+ }
+
+ /**
+ * Very dumb YAML encoder
+ *
+ * Until we have Zend_Yaml...
+ *
+ * @param array $data YAML data
+ * @return string
+ */
+ public static function encode($data)
+ {
+ return self::_encodeYaml(0, $data);
+ }
+
+ /**
+ * Service function for encoding YAML
+ *
+ * @param int $indent Current indent level
+ * @param array $data Data to encode
+ * @return string
+ */
+ protected static function _encodeYaml($indent, $data)
+ {
+ reset($data);
+ $result = "";
+ $numeric = is_numeric(key($data));
+
+ foreach($data as $key => $value) {
+ if(is_array($value)) {
+ $encoded = "\n".self::_encodeYaml($indent+1, $value);
+ } else {
+ $encoded = (string)$value."\n";
+ }
+ $result .= str_repeat(" ", $indent).($numeric?"- ":"$key: ").$encoded;
+ }
+ return $result;
+ }
+}
diff --git a/lib/zend/Zend/Config/Xml.php b/lib/zend/Zend/Config/Xml.php
new file mode 100644
index 00000000000..4425a8b7059
--- /dev/null
+++ b/lib/zend/Zend/Config/Xml.php
@@ -0,0 +1,314 @@
+ false,
+ * 'skipExtends' => false
+ * );
+ *
+ * @param string $xml XML file or string to process
+ * @param mixed $section Section to process
+ * @param array|boolean $options
+ * @throws Zend_Config_Exception When xml is not set or cannot be loaded
+ * @throws Zend_Config_Exception When section $sectionName cannot be found in $xml
+ */
+ public function __construct($xml, $section = null, $options = false)
+ {
+ if (empty($xml)) {
+ require_once 'Zend/Config/Exception.php';
+ throw new Zend_Config_Exception('Filename is not set');
+ }
+
+ $allowModifications = false;
+ if (is_bool($options)) {
+ $allowModifications = $options;
+ } elseif (is_array($options)) {
+ if (isset($options['allowModifications'])) {
+ $allowModifications = (bool) $options['allowModifications'];
+ }
+ if (isset($options['skipExtends'])) {
+ $this->_skipExtends = (bool) $options['skipExtends'];
+ }
+ }
+
+ set_error_handler(array($this, '_loadFileErrorHandler')); // Warnings and errors are suppressed
+ if (strstr($xml, 'getMessage()
+ );
+ }
+ }
+
+ restore_error_handler();
+ // Check if there was a error while loading file
+ if ($this->_loadFileErrorStr !== null) {
+ require_once 'Zend/Config/Exception.php';
+ throw new Zend_Config_Exception($this->_loadFileErrorStr);
+ }
+
+ if ($section === null) {
+ $dataArray = array();
+ foreach ($config as $sectionName => $sectionData) {
+ $dataArray[$sectionName] = $this->_processExtends($config, $sectionName);
+ }
+
+ parent::__construct($dataArray, $allowModifications);
+ } else if (is_array($section)) {
+ $dataArray = array();
+ foreach ($section as $sectionName) {
+ if (!isset($config->$sectionName)) {
+ require_once 'Zend/Config/Exception.php';
+ throw new Zend_Config_Exception("Section '$sectionName' cannot be found in $xml");
+ }
+
+ $dataArray = array_merge($this->_processExtends($config, $sectionName), $dataArray);
+ }
+
+ parent::__construct($dataArray, $allowModifications);
+ } else {
+ if (!isset($config->$section)) {
+ require_once 'Zend/Config/Exception.php';
+ throw new Zend_Config_Exception("Section '$section' cannot be found in $xml");
+ }
+
+ $dataArray = $this->_processExtends($config, $section);
+ if (!is_array($dataArray)) {
+ // Section in the XML file contains just one top level string
+ $dataArray = array($section => $dataArray);
+ }
+
+ parent::__construct($dataArray, $allowModifications);
+ }
+
+ $this->_loadedSection = $section;
+ }
+
+ /**
+ * Helper function to process each element in the section and handle
+ * the "extends" inheritance attribute.
+ *
+ * @param SimpleXMLElement $element XML Element to process
+ * @param string $section Section to process
+ * @param array $config Configuration which was parsed yet
+ * @throws Zend_Config_Exception When $section cannot be found
+ * @return array
+ */
+ protected function _processExtends(SimpleXMLElement $element, $section, array $config = array())
+ {
+ if (!isset($element->$section)) {
+ require_once 'Zend/Config/Exception.php';
+ throw new Zend_Config_Exception("Section '$section' cannot be found");
+ }
+
+ $thisSection = $element->$section;
+ $nsAttributes = $thisSection->attributes(self::XML_NAMESPACE);
+
+ if (isset($thisSection['extends']) || isset($nsAttributes['extends'])) {
+ $extendedSection = (string) (isset($nsAttributes['extends']) ? $nsAttributes['extends'] : $thisSection['extends']);
+ $this->_assertValidExtend($section, $extendedSection);
+
+ if (!$this->_skipExtends) {
+ $config = $this->_processExtends($element, $extendedSection, $config);
+ }
+ }
+
+ $config = $this->_arrayMergeRecursive($config, $this->_toArray($thisSection));
+
+ return $config;
+ }
+
+ /**
+ * Returns a string or an associative and possibly multidimensional array from
+ * a SimpleXMLElement.
+ *
+ * @param SimpleXMLElement $xmlObject Convert a SimpleXMLElement into an array
+ * @return array|string
+ */
+ protected function _toArray(SimpleXMLElement $xmlObject)
+ {
+ $config = array();
+ $nsAttributes = $xmlObject->attributes(self::XML_NAMESPACE);
+
+ // Search for parent node values
+ if (count($xmlObject->attributes()) > 0) {
+ foreach ($xmlObject->attributes() as $key => $value) {
+ if ($key === 'extends') {
+ continue;
+ }
+
+ $value = (string) $value;
+
+ if (array_key_exists($key, $config)) {
+ if (!is_array($config[$key])) {
+ $config[$key] = array($config[$key]);
+ }
+
+ $config[$key][] = $value;
+ } else {
+ $config[$key] = $value;
+ }
+ }
+ }
+
+ // Search for local 'const' nodes and replace them
+ if (count($xmlObject->children(self::XML_NAMESPACE)) > 0) {
+ if (count($xmlObject->children()) > 0) {
+ require_once 'Zend/Config/Exception.php';
+ throw new Zend_Config_Exception("A node with a 'const' childnode may not have any other children");
+ }
+
+ $dom = dom_import_simplexml($xmlObject);
+ $namespaceChildNodes = array();
+
+ // We have to store them in an array, as replacing nodes will
+ // confuse the DOMNodeList later
+ foreach ($dom->childNodes as $node) {
+ if ($node instanceof DOMElement && $node->namespaceURI === self::XML_NAMESPACE) {
+ $namespaceChildNodes[] = $node;
+ }
+ }
+
+ foreach ($namespaceChildNodes as $node) {
+ switch ($node->localName) {
+ case 'const':
+ if (!$node->hasAttributeNS(self::XML_NAMESPACE, 'name')) {
+ require_once 'Zend/Config/Exception.php';
+ throw new Zend_Config_Exception("Misssing 'name' attribute in 'const' node");
+ }
+
+ $constantName = $node->getAttributeNS(self::XML_NAMESPACE, 'name');
+
+ if (!defined($constantName)) {
+ require_once 'Zend/Config/Exception.php';
+ throw new Zend_Config_Exception("Constant with name '$constantName' was not defined");
+ }
+
+ $constantValue = constant($constantName);
+
+ $dom->replaceChild($dom->ownerDocument->createTextNode($constantValue), $node);
+ break;
+
+ default:
+ require_once 'Zend/Config/Exception.php';
+ throw new Zend_Config_Exception("Unknown node with name '$node->localName' found");
+ }
+ }
+
+ return (string) simplexml_import_dom($dom);
+ }
+
+ // Search for children
+ if (count($xmlObject->children()) > 0) {
+ foreach ($xmlObject->children() as $key => $value) {
+ if (count($value->children()) > 0 || count($value->children(self::XML_NAMESPACE)) > 0) {
+ $value = $this->_toArray($value);
+ } else if (count($value->attributes()) > 0) {
+ $attributes = $value->attributes();
+ if (isset($attributes['value'])) {
+ $value = (string) $attributes['value'];
+ } else {
+ $value = $this->_toArray($value);
+ }
+ } else {
+ $value = (string) $value;
+ }
+
+ if (array_key_exists($key, $config)) {
+ if (!is_array($config[$key]) || !array_key_exists(0, $config[$key])) {
+ $config[$key] = array($config[$key]);
+ }
+
+ $config[$key][] = $value;
+ } else {
+ $config[$key] = $value;
+ }
+ }
+ } else if (!isset($xmlObject['extends']) && !isset($nsAttributes['extends']) && (count($config) === 0)) {
+ // Object has no children nor attributes and doesn't use the extends
+ // attribute: it's a string
+ $config = (string) $xmlObject;
+ }
+
+ return $config;
+ }
+}
diff --git a/lib/zend/Zend/Config/Yaml.php b/lib/zend/Zend/Config/Yaml.php
new file mode 100755
index 00000000000..0d107033eb8
--- /dev/null
+++ b/lib/zend/Zend/Config/Yaml.php
@@ -0,0 +1,415 @@
+_yamlDecoder;
+ }
+
+ /**
+ * Set callback for decoding YAML
+ *
+ * @param callable $yamlDecoder the decoder to set
+ * @return Zend_Config_Yaml
+ */
+ public function setYamlDecoder($yamlDecoder)
+ {
+ if (!is_callable($yamlDecoder)) {
+ require_once 'Zend/Config/Exception.php';
+ throw new Zend_Config_Exception('Invalid parameter to setYamlDecoder() - must be callable');
+ }
+
+ $this->_yamlDecoder = $yamlDecoder;
+ return $this;
+ }
+
+ /**
+ * Loads the section $section from the config file encoded as YAML
+ *
+ * Sections are defined as properties of the main object
+ *
+ * In order to extend another section, a section defines the "_extends"
+ * property having a value of the section name from which the extending
+ * section inherits values.
+ *
+ * Note that the keys in $section will override any keys of the same
+ * name in the sections that have been included via "_extends".
+ *
+ * Options may include:
+ * - allow_modifications: whether or not the config object is mutable
+ * - skip_extends: whether or not to skip processing of parent configuration
+ * - yaml_decoder: a callback to use to decode the Yaml source
+ *
+ * @param string $yaml YAML file to process
+ * @param mixed $section Section to process
+ * @param array|boolean $options
+ */
+ public function __construct($yaml, $section = null, $options = false)
+ {
+ if (empty($yaml)) {
+ require_once 'Zend/Config/Exception.php';
+ throw new Zend_Config_Exception('Filename is not set');
+ }
+
+ $ignoreConstants = $staticIgnoreConstants = self::ignoreConstants();
+ $allowModifications = false;
+ if (is_bool($options)) {
+ $allowModifications = $options;
+ } elseif (is_array($options)) {
+ foreach ($options as $key => $value) {
+ switch (strtolower($key)) {
+ case 'allow_modifications':
+ case 'allowmodifications':
+ $allowModifications = (bool) $value;
+ break;
+ case 'skip_extends':
+ case 'skipextends':
+ $this->_skipExtends = (bool) $value;
+ break;
+ case 'ignore_constants':
+ case 'ignoreconstants':
+ $ignoreConstants = (bool) $value;
+ break;
+ case 'yaml_decoder':
+ case 'yamldecoder':
+ $this->setYamlDecoder($value);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ // Suppress warnings and errors while loading file
+ set_error_handler(array($this, '_loadFileErrorHandler'));
+ $yaml = file_get_contents($yaml);
+ restore_error_handler();
+
+ // Check if there was a error while loading file
+ if ($this->_loadFileErrorStr !== null) {
+ require_once 'Zend/Config/Exception.php';
+ throw new Zend_Config_Exception($this->_loadFileErrorStr);
+ }
+
+ // Override static value for ignore_constants if provided in $options
+ self::setIgnoreConstants($ignoreConstants);
+
+ // Parse YAML
+ $config = call_user_func($this->getYamlDecoder(), $yaml);
+
+ // Reset original static state of ignore_constants
+ self::setIgnoreConstants($staticIgnoreConstants);
+
+ if (null === $config) {
+ // decode failed
+ require_once 'Zend/Config/Exception.php';
+ throw new Zend_Config_Exception("Error parsing YAML data");
+ }
+
+ if (null === $section) {
+ $dataArray = array();
+ foreach ($config as $sectionName => $sectionData) {
+ $dataArray[$sectionName] = $this->_processExtends($config, $sectionName);
+ }
+ parent::__construct($dataArray, $allowModifications);
+ } elseif (is_array($section)) {
+ $dataArray = array();
+ foreach ($section as $sectionName) {
+ if (!isset($config[$sectionName])) {
+ require_once 'Zend/Config/Exception.php';
+ throw new Zend_Config_Exception(sprintf(
+ 'Section "%s" cannot be found',
+ implode(' ', (array)$section)
+ ));
+ }
+
+ $dataArray = array_merge($this->_processExtends($config, $sectionName), $dataArray);
+ }
+ parent::__construct($dataArray, $allowModifications);
+ } else {
+ if (!isset($config[$section])) {
+ require_once 'Zend/Config/Exception.php';
+ throw new Zend_Config_Exception(sprintf(
+ 'Section "%s" cannot be found',
+ implode(' ', (array)$section)
+ ));
+ }
+
+ $dataArray = $this->_processExtends($config, $section);
+ if (!is_array($dataArray)) {
+ // Section in the yaml data contains just one top level string
+ $dataArray = array($section => $dataArray);
+ }
+ parent::__construct($dataArray, $allowModifications);
+ }
+
+ $this->_loadedSection = $section;
+ }
+
+ /**
+ * Helper function to process each element in the section and handle
+ * the "_extends" inheritance attribute.
+ *
+ * @param array $data Data array to process
+ * @param string $section Section to process
+ * @param array $config Configuration which was parsed yet
+ * @return array
+ * @throws Zend_Config_Exception When $section cannot be found
+ */
+ protected function _processExtends(array $data, $section, array $config = array())
+ {
+ if (!isset($data[$section])) {
+ require_once 'Zend/Config/Exception.php';
+ throw new Zend_Config_Exception(sprintf('Section "%s" cannot be found', $section));
+ }
+
+ $thisSection = $data[$section];
+
+ if (is_array($thisSection) && isset($thisSection[self::EXTENDS_NAME])) {
+ $this->_assertValidExtend($section, $thisSection[self::EXTENDS_NAME]);
+
+ if (!$this->_skipExtends) {
+ $config = $this->_processExtends($data, $thisSection[self::EXTENDS_NAME], $config);
+ }
+ unset($thisSection[self::EXTENDS_NAME]);
+ }
+
+ $config = $this->_arrayMergeRecursive($config, $thisSection);
+
+ return $config;
+ }
+
+ /**
+ * Very dumb YAML parser
+ *
+ * Until we have Zend_Yaml...
+ *
+ * @param string $yaml YAML source
+ * @return array Decoded data
+ */
+ public static function decode($yaml)
+ {
+ $lines = explode("\n", $yaml);
+ reset($lines);
+ return self::_decodeYaml(0, $lines);
+ }
+
+ /**
+ * Service function to decode YAML
+ *
+ * @param int $currentIndent Current indent level
+ * @param array $lines YAML lines
+ * @return array|string
+ */
+ protected static function _decodeYaml($currentIndent, &$lines)
+ {
+ $config = array();
+ $inIndent = false;
+ while (list($n, $line) = each($lines)) {
+ $lineno = $n + 1;
+
+ $line = rtrim(preg_replace("/#.*$/", "", $line));
+ if (strlen($line) == 0) {
+ continue;
+ }
+
+ $indent = strspn($line, " ");
+
+ // line without the spaces
+ $line = trim($line);
+ if (strlen($line) == 0) {
+ continue;
+ }
+
+ if ($indent < $currentIndent) {
+ // this level is done
+ prev($lines);
+ return $config;
+ }
+
+ if (!$inIndent) {
+ $currentIndent = $indent;
+ $inIndent = true;
+ }
+
+ if (preg_match("/(?!-)([\w\-]+):\s*(.*)/", $line, $m)) {
+ // key: value
+ if (strlen($m[2])) {
+ // simple key: value
+ $value = preg_replace("/#.*$/", "", $m[2]);
+ $value = self::_parseValue($value);
+ } else {
+ // key: and then values on new lines
+ $value = self::_decodeYaml($currentIndent + 1, $lines);
+ if (is_array($value) && !count($value)) {
+ $value = "";
+ }
+ }
+ $config[$m[1]] = $value;
+ } elseif ($line[0] == "-") {
+ // item in the list:
+ // - FOO
+ if (strlen($line) > 2) {
+ $value = substr($line, 2);
+
+ $config[] = self::_parseValue($value);
+ } else {
+ $config[] = self::_decodeYaml($currentIndent + 1, $lines);
+ }
+ } else {
+ require_once 'Zend/Config/Exception.php';
+ throw new Zend_Config_Exception(sprintf(
+ 'Error parsing YAML at line %d - unsupported syntax: "%s"',
+ $lineno, $line
+ ));
+ }
+ }
+ return $config;
+ }
+
+ /**
+ * Parse values
+ *
+ * @param string $value
+ * @return string
+ */
+ protected static function _parseValue($value)
+ {
+ $value = trim($value);
+
+ // remove quotes from string.
+ if ('"' == $value['0']) {
+ if ('"' == $value[count($value) -1]) {
+ $value = substr($value, 1, -1);
+ }
+ } elseif ('\'' == $value['0'] && '\'' == $value[count($value) -1]) {
+ $value = strtr($value, array("''" => "'", "'" => ''));
+ }
+
+ // Check for booleans and constants
+ if (preg_match('/^(t(rue)?|on|y(es)?)$/i', $value)) {
+ $value = true;
+ } elseif (preg_match('/^(f(alse)?|off|n(o)?)$/i', $value)) {
+ $value = false;
+ } elseif (strcasecmp($value, 'null') === 0) {
+ $value = null;
+ } elseif (!self::$_ignoreConstants) {
+ // test for constants
+ $value = self::_replaceConstants($value);
+ }
+
+ return $value;
+ }
+
+ /**
+ * Replace any constants referenced in a string with their values
+ *
+ * @param string $value
+ * @return string
+ */
+ protected static function _replaceConstants($value)
+ {
+ foreach (self::_getConstants() as $constant) {
+ if (strstr($value, $constant)) {
+ $value = str_replace($constant, constant($constant), $value);
+ }
+ }
+ return $value;
+ }
+
+ /**
+ * Get (reverse) sorted list of defined constant names
+ *
+ * @return array
+ */
+ protected static function _getConstants()
+ {
+ $constants = array_keys(get_defined_constants());
+ rsort($constants, SORT_STRING);
+ return $constants;
+ }
+}
diff --git a/lib/zend/Zend/Controller/Action.php b/lib/zend/Zend/Controller/Action.php
new file mode 100644
index 00000000000..9508e747119
--- /dev/null
+++ b/lib/zend/Zend/Controller/Action.php
@@ -0,0 +1,798 @@
+setRequest($request)
+ ->setResponse($response)
+ ->_setInvokeArgs($invokeArgs);
+ $this->_helper = new Zend_Controller_Action_HelperBroker($this);
+ $this->init();
+ }
+
+ /**
+ * Initialize object
+ *
+ * Called from {@link __construct()} as final step of object instantiation.
+ *
+ * @return void
+ */
+ public function init()
+ {
+ }
+
+ /**
+ * Initialize View object
+ *
+ * Initializes {@link $view} if not otherwise a Zend_View_Interface.
+ *
+ * If {@link $view} is not otherwise set, instantiates a new Zend_View
+ * object, using the 'views' subdirectory at the same level as the
+ * controller directory for the current module as the base directory.
+ * It uses this to set the following:
+ * - script path = views/scripts/
+ * - helper path = views/helpers/
+ * - filter path = views/filters/
+ *
+ * @return Zend_View_Interface
+ * @throws Zend_Controller_Exception if base view directory does not exist
+ */
+ public function initView()
+ {
+ if (!$this->getInvokeArg('noViewRenderer') && $this->_helper->hasHelper('viewRenderer')) {
+ return $this->view;
+ }
+
+ require_once 'Zend/View/Interface.php';
+ if (isset($this->view) && ($this->view instanceof Zend_View_Interface)) {
+ return $this->view;
+ }
+
+ $request = $this->getRequest();
+ $module = $request->getModuleName();
+ $dirs = $this->getFrontController()->getControllerDirectory();
+ if (empty($module) || !isset($dirs[$module])) {
+ $module = $this->getFrontController()->getDispatcher()->getDefaultModule();
+ }
+ $baseDir = dirname($dirs[$module]) . DIRECTORY_SEPARATOR . 'views';
+ if (!file_exists($baseDir) || !is_dir($baseDir)) {
+ require_once 'Zend/Controller/Exception.php';
+ throw new Zend_Controller_Exception('Missing base view directory ("' . $baseDir . '")');
+ }
+
+ require_once 'Zend/View.php';
+ $this->view = new Zend_View(array('basePath' => $baseDir));
+
+ return $this->view;
+ }
+
+ /**
+ * Render a view
+ *
+ * Renders a view. By default, views are found in the view script path as
+ * /.phtml. You may change the script suffix by
+ * resetting {@link $viewSuffix}. You may omit the controller directory
+ * prefix by specifying boolean true for $noController.
+ *
+ * By default, the rendered contents are appended to the response. You may
+ * specify the named body content segment to set by specifying a $name.
+ *
+ * @see Zend_Controller_Response_Abstract::appendBody()
+ * @param string|null $action Defaults to action registered in request object
+ * @param string|null $name Response object named path segment to use; defaults to null
+ * @param bool $noController Defaults to false; i.e. use controller name as subdir in which to search for view script
+ * @return void
+ */
+ public function render($action = null, $name = null, $noController = false)
+ {
+ if (!$this->getInvokeArg('noViewRenderer') && $this->_helper->hasHelper('viewRenderer')) {
+ return $this->_helper->viewRenderer->render($action, $name, $noController);
+ }
+
+ $view = $this->initView();
+ $script = $this->getViewScript($action, $noController);
+
+ $this->getResponse()->appendBody(
+ $view->render($script),
+ $name
+ );
+ }
+
+ /**
+ * Render a given view script
+ *
+ * Similar to {@link render()}, this method renders a view script. Unlike render(),
+ * however, it does not autodetermine the view script via {@link getViewScript()},
+ * but instead renders the script passed to it. Use this if you know the
+ * exact view script name and path you wish to use, or if using paths that do not
+ * conform to the spec defined with getViewScript().
+ *
+ * By default, the rendered contents are appended to the response. You may
+ * specify the named body content segment to set by specifying a $name.
+ *
+ * @param string $script
+ * @param string $name
+ * @return void
+ */
+ public function renderScript($script, $name = null)
+ {
+ if (!$this->getInvokeArg('noViewRenderer') && $this->_helper->hasHelper('viewRenderer')) {
+ return $this->_helper->viewRenderer->renderScript($script, $name);
+ }
+
+ $view = $this->initView();
+ $this->getResponse()->appendBody(
+ $view->render($script),
+ $name
+ );
+ }
+
+ /**
+ * Construct view script path
+ *
+ * Used by render() to determine the path to the view script.
+ *
+ * @param string $action Defaults to action registered in request object
+ * @param bool $noController Defaults to false; i.e. use controller name as subdir in which to search for view script
+ * @return string
+ * @throws Zend_Controller_Exception with bad $action
+ */
+ public function getViewScript($action = null, $noController = null)
+ {
+ if (!$this->getInvokeArg('noViewRenderer') && $this->_helper->hasHelper('viewRenderer')) {
+ $viewRenderer = $this->_helper->getHelper('viewRenderer');
+ if (null !== $noController) {
+ $viewRenderer->setNoController($noController);
+ }
+ return $viewRenderer->getViewScript($action);
+ }
+
+ $request = $this->getRequest();
+ if (null === $action) {
+ $action = $request->getActionName();
+ } elseif (!is_string($action)) {
+ require_once 'Zend/Controller/Exception.php';
+ throw new Zend_Controller_Exception('Invalid action specifier for view render');
+ }
+
+ if (null === $this->_delimiters) {
+ $dispatcher = Zend_Controller_Front::getInstance()->getDispatcher();
+ $wordDelimiters = $dispatcher->getWordDelimiter();
+ $pathDelimiters = $dispatcher->getPathDelimiter();
+ $this->_delimiters = array_unique(array_merge($wordDelimiters, (array) $pathDelimiters));
+ }
+
+ $action = str_replace($this->_delimiters, '-', $action);
+ $script = $action . '.' . $this->viewSuffix;
+
+ if (!$noController) {
+ $controller = $request->getControllerName();
+ $controller = str_replace($this->_delimiters, '-', $controller);
+ $script = $controller . DIRECTORY_SEPARATOR . $script;
+ }
+
+ return $script;
+ }
+
+ /**
+ * Return the Request object
+ *
+ * @return Zend_Controller_Request_Abstract
+ */
+ public function getRequest()
+ {
+ return $this->_request;
+ }
+
+ /**
+ * Set the Request object
+ *
+ * @param Zend_Controller_Request_Abstract $request
+ * @return Zend_Controller_Action
+ */
+ public function setRequest(Zend_Controller_Request_Abstract $request)
+ {
+ $this->_request = $request;
+ return $this;
+ }
+
+ /**
+ * Return the Response object
+ *
+ * @return Zend_Controller_Response_Abstract
+ */
+ public function getResponse()
+ {
+ return $this->_response;
+ }
+
+ /**
+ * Set the Response object
+ *
+ * @param Zend_Controller_Response_Abstract $response
+ * @return Zend_Controller_Action
+ */
+ public function setResponse(Zend_Controller_Response_Abstract $response)
+ {
+ $this->_response = $response;
+ return $this;
+ }
+
+ /**
+ * Set invocation arguments
+ *
+ * @param array $args
+ * @return Zend_Controller_Action
+ */
+ protected function _setInvokeArgs(array $args = array())
+ {
+ $this->_invokeArgs = $args;
+ return $this;
+ }
+
+ /**
+ * Return the array of constructor arguments (minus the Request object)
+ *
+ * @return array
+ */
+ public function getInvokeArgs()
+ {
+ return $this->_invokeArgs;
+ }
+
+ /**
+ * Return a single invocation argument
+ *
+ * @param string $key
+ * @return mixed
+ */
+ public function getInvokeArg($key)
+ {
+ if (isset($this->_invokeArgs[$key])) {
+ return $this->_invokeArgs[$key];
+ }
+
+ return null;
+ }
+
+ /**
+ * Get a helper by name
+ *
+ * @param string $helperName
+ * @return Zend_Controller_Action_Helper_Abstract
+ */
+ public function getHelper($helperName)
+ {
+ return $this->_helper->{$helperName};
+ }
+
+ /**
+ * Get a clone of a helper by name
+ *
+ * @param string $helperName
+ * @return Zend_Controller_Action_Helper_Abstract
+ */
+ public function getHelperCopy($helperName)
+ {
+ return clone $this->_helper->{$helperName};
+ }
+
+ /**
+ * Set the front controller instance
+ *
+ * @param Zend_Controller_Front $front
+ * @return Zend_Controller_Action
+ */
+ public function setFrontController(Zend_Controller_Front $front)
+ {
+ $this->_frontController = $front;
+ return $this;
+ }
+
+ /**
+ * Retrieve Front Controller
+ *
+ * @return Zend_Controller_Front
+ */
+ public function getFrontController()
+ {
+ // Used cache version if found
+ if (null !== $this->_frontController) {
+ return $this->_frontController;
+ }
+
+ // Grab singleton instance, if class has been loaded
+ if (class_exists('Zend_Controller_Front')) {
+ $this->_frontController = Zend_Controller_Front::getInstance();
+ return $this->_frontController;
+ }
+
+ // Throw exception in all other cases
+ require_once 'Zend/Controller/Exception.php';
+ throw new Zend_Controller_Exception('Front controller class has not been loaded');
+ }
+
+ /**
+ * Pre-dispatch routines
+ *
+ * Called before action method. If using class with
+ * {@link Zend_Controller_Front}, it may modify the
+ * {@link $_request Request object} and reset its dispatched flag in order
+ * to skip processing the current action.
+ *
+ * @return void
+ */
+ public function preDispatch()
+ {
+ }
+
+ /**
+ * Post-dispatch routines
+ *
+ * Called after action method execution. If using class with
+ * {@link Zend_Controller_Front}, it may modify the
+ * {@link $_request Request object} and reset its dispatched flag in order
+ * to process an additional action.
+ *
+ * Common usages for postDispatch() include rendering content in a sitewide
+ * template, link url correction, setting headers, etc.
+ *
+ * @return void
+ */
+ public function postDispatch()
+ {
+ }
+
+ /**
+ * Proxy for undefined methods. Default behavior is to throw an
+ * exception on undefined methods, however this function can be
+ * overridden to implement magic (dynamic) actions, or provide run-time
+ * dispatching.
+ *
+ * @param string $methodName
+ * @param array $args
+ * @return void
+ * @throws Zend_Controller_Action_Exception
+ */
+ public function __call($methodName, $args)
+ {
+ require_once 'Zend/Controller/Action/Exception.php';
+ if ('Action' == substr($methodName, -6)) {
+ $action = substr($methodName, 0, strlen($methodName) - 6);
+ throw new Zend_Controller_Action_Exception(sprintf('Action "%s" does not exist and was not trapped in __call()', $action), 404);
+ }
+
+ throw new Zend_Controller_Action_Exception(sprintf('Method "%s" does not exist and was not trapped in __call()', $methodName), 500);
+ }
+
+ /**
+ * Dispatch the requested action
+ *
+ * @param string $action Method name of action
+ * @return void
+ */
+ public function dispatch($action)
+ {
+ // Notify helpers of action preDispatch state
+ $this->_helper->notifyPreDispatch();
+
+ $this->preDispatch();
+ if ($this->getRequest()->isDispatched()) {
+ if (null === $this->_classMethods) {
+ $this->_classMethods = get_class_methods($this);
+ }
+
+ // If pre-dispatch hooks introduced a redirect then stop dispatch
+ // @see ZF-7496
+ if (!($this->getResponse()->isRedirect())) {
+ // preDispatch() didn't change the action, so we can continue
+ if ($this->getInvokeArg('useCaseSensitiveActions') || in_array($action, $this->_classMethods)) {
+ if ($this->getInvokeArg('useCaseSensitiveActions')) {
+ trigger_error('Using case sensitive actions without word separators is deprecated; please do not rely on this "feature"');
+ }
+ $this->$action();
+ } else {
+ $this->__call($action, array());
+ }
+ }
+ $this->postDispatch();
+ }
+
+ // whats actually important here is that this action controller is
+ // shutting down, regardless of dispatching; notify the helpers of this
+ // state
+ $this->_helper->notifyPostDispatch();
+ }
+
+ /**
+ * Call the action specified in the request object, and return a response
+ *
+ * Not used in the Action Controller implementation, but left for usage in
+ * Page Controller implementations. Dispatches a method based on the
+ * request.
+ *
+ * Returns a Zend_Controller_Response_Abstract object, instantiating one
+ * prior to execution if none exists in the controller.
+ *
+ * {@link preDispatch()} is called prior to the action,
+ * {@link postDispatch()} is called following it.
+ *
+ * @param null|Zend_Controller_Request_Abstract $request Optional request
+ * object to use
+ * @param null|Zend_Controller_Response_Abstract $response Optional response
+ * object to use
+ * @return Zend_Controller_Response_Abstract
+ */
+ public function run(Zend_Controller_Request_Abstract $request = null, Zend_Controller_Response_Abstract $response = null)
+ {
+ if (null !== $request) {
+ $this->setRequest($request);
+ } else {
+ $request = $this->getRequest();
+ }
+
+ if (null !== $response) {
+ $this->setResponse($response);
+ }
+
+ $action = $request->getActionName();
+ if (empty($action)) {
+ $action = 'index';
+ }
+ $action = $action . 'Action';
+
+ $request->setDispatched(true);
+ $this->dispatch($action);
+
+ return $this->getResponse();
+ }
+
+ /**
+ * Gets a parameter from the {@link $_request Request object}. If the
+ * parameter does not exist, NULL will be returned.
+ *
+ * If the parameter does not exist and $default is set, then
+ * $default will be returned instead of NULL.
+ *
+ * @param string $paramName
+ * @param mixed $default
+ * @return mixed
+ */
+ protected function _getParam($paramName, $default = null)
+ {
+ return $this->getParam($paramName, $default);
+ }
+
+ /**
+ * Gets a parameter from the {@link $_request Request object}. If the
+ * parameter does not exist, NULL will be returned.
+ *
+ * If the parameter does not exist and $default is set, then
+ * $default will be returned instead of NULL.
+ *
+ * @param string $paramName
+ * @param mixed $default
+ * @return mixed
+ */
+ public function getParam($paramName, $default = null)
+ {
+ $value = $this->getRequest()->getParam($paramName);
+ if ((null === $value || '' === $value) && (null !== $default)) {
+ $value = $default;
+ }
+
+ return $value;
+ }
+
+ /**
+ * Set a parameter in the {@link $_request Request object}.
+ *
+ * @param string $paramName
+ * @param mixed $value
+ * @return Zend_Controller_Action
+ * @deprecated Deprecated as of Zend Framework 1.7. Use
+ * setParam() instead.
+ */
+ protected function _setParam($paramName, $value)
+ {
+ return $this->setParam($paramName, $value);
+ }
+
+ /**
+ * Set a parameter in the {@link $_request Request object}.
+ *
+ * @param string $paramName
+ * @param mixed $value
+ * @return Zend_Controller_Action
+ */
+ public function setParam($paramName, $value)
+ {
+ $this->getRequest()->setParam($paramName, $value);
+
+ return $this;
+ }
+
+ /**
+ * Determine whether a given parameter exists in the
+ * {@link $_request Request object}.
+ *
+ * @param string $paramName
+ * @return boolean
+ * @deprecated Deprecated as of Zend Framework 1.7. Use
+ * hasParam() instead.
+ */
+ protected function _hasParam($paramName)
+ {
+ return $this->hasParam($paramName);
+ }
+
+ /**
+ * Determine whether a given parameter exists in the
+ * {@link $_request Request object}.
+ *
+ * @param string $paramName
+ * @return boolean
+ */
+ public function hasParam($paramName)
+ {
+ return null !== $this->getRequest()->getParam($paramName);
+ }
+
+ /**
+ * Return all parameters in the {@link $_request Request object}
+ * as an associative array.
+ *
+ * @return array
+ * @deprecated Deprecated as of Zend Framework 1.7. Use
+ * getAllParams() instead.
+ */
+ protected function _getAllParams()
+ {
+ return $this->getAllParams();
+ }
+
+ /**
+ * Return all parameters in the {@link $_request Request object}
+ * as an associative array.
+ *
+ * @return array
+ */
+ public function getAllParams()
+ {
+ return $this->getRequest()->getParams();
+ }
+
+
+ /**
+ * Forward to another controller/action.
+ *
+ * It is important to supply the unformatted names, i.e. "article"
+ * rather than "ArticleController". The dispatcher will do the
+ * appropriate formatting when the request is received.
+ *
+ * If only an action name is provided, forwards to that action in this
+ * controller.
+ *
+ * If an action and controller are specified, forwards to that action and
+ * controller in this module.
+ *
+ * Specifying an action, controller, and module is the most specific way to
+ * forward.
+ *
+ * A fourth argument, $params, will be used to set the request parameters.
+ * If either the controller or module are unnecessary for forwarding,
+ * simply pass null values for them before specifying the parameters.
+ *
+ * @param string $action
+ * @param string $controller
+ * @param string $module
+ * @param array $params
+ * @return void
+ * @deprecated Deprecated as of Zend Framework 1.7. Use
+ * forward() instead.
+ */
+ final protected function _forward($action, $controller = null, $module = null, array $params = null)
+ {
+ $this->forward($action, $controller, $module, $params);
+ }
+
+ /**
+ * Forward to another controller/action.
+ *
+ * It is important to supply the unformatted names, i.e. "article"
+ * rather than "ArticleController". The dispatcher will do the
+ * appropriate formatting when the request is received.
+ *
+ * If only an action name is provided, forwards to that action in this
+ * controller.
+ *
+ * If an action and controller are specified, forwards to that action and
+ * controller in this module.
+ *
+ * Specifying an action, controller, and module is the most specific way to
+ * forward.
+ *
+ * A fourth argument, $params, will be used to set the request parameters.
+ * If either the controller or module are unnecessary for forwarding,
+ * simply pass null values for them before specifying the parameters.
+ *
+ * @param string $action
+ * @param string $controller
+ * @param string $module
+ * @param array $params
+ * @return void
+ */
+ final public function forward($action, $controller = null, $module = null, array $params = null)
+ {
+ $request = $this->getRequest();
+
+ if (null !== $params) {
+ $request->setParams($params);
+ }
+
+ if (null !== $controller) {
+ $request->setControllerName($controller);
+
+ // Module should only be reset if controller has been specified
+ if (null !== $module) {
+ $request->setModuleName($module);
+ }
+ }
+
+ $request->setActionName($action)
+ ->setDispatched(false);
+ }
+
+ /**
+ * Redirect to another URL
+ *
+ * Proxies to {@link Zend_Controller_Action_Helper_Redirector::gotoUrl()}.
+ *
+ * @param string $url
+ * @param array $options Options to be used when redirecting
+ * @return void
+ * @deprecated Deprecated as of Zend Framework 1.7. Use
+ * redirect() instead.
+ */
+ protected function _redirect($url, array $options = array())
+ {
+ $this->redirect($url, $options);
+ }
+
+ /**
+ * Redirect to another URL
+ *
+ * Proxies to {@link Zend_Controller_Action_Helper_Redirector::gotoUrl()}.
+ *
+ * @param string $url
+ * @param array $options Options to be used when redirecting
+ * @return void
+ */
+ public function redirect($url, array $options = array())
+ {
+ $this->_helper->redirector->gotoUrl($url, $options);
+ }
+}
diff --git a/lib/zend/Zend/Controller/Action/Exception.php b/lib/zend/Zend/Controller/Action/Exception.php
new file mode 100644
index 00000000000..4cd9ce2a74b
--- /dev/null
+++ b/lib/zend/Zend/Controller/Action/Exception.php
@@ -0,0 +1,38 @@
+_actionController = $actionController;
+ return $this;
+ }
+
+ /**
+ * Retrieve current action controller
+ *
+ * @return Zend_Controller_Action
+ */
+ public function getActionController()
+ {
+ return $this->_actionController;
+ }
+
+ /**
+ * Retrieve front controller instance
+ *
+ * @return Zend_Controller_Front
+ */
+ public function getFrontController()
+ {
+ return Zend_Controller_Front::getInstance();
+ }
+
+ /**
+ * Hook into action controller initialization
+ *
+ * @return void
+ */
+ public function init()
+ {
+ }
+
+ /**
+ * Hook into action controller preDispatch() workflow
+ *
+ * @return void
+ */
+ public function preDispatch()
+ {
+ }
+
+ /**
+ * Hook into action controller postDispatch() workflow
+ *
+ * @return void
+ */
+ public function postDispatch()
+ {
+ }
+
+ /**
+ * getRequest() -
+ *
+ * @return Zend_Controller_Request_Abstract $request
+ */
+ public function getRequest()
+ {
+ $controller = $this->getActionController();
+ if (null === $controller) {
+ $controller = $this->getFrontController();
+ }
+
+ return $controller->getRequest();
+ }
+
+ /**
+ * getResponse() -
+ *
+ * @return Zend_Controller_Response_Abstract $response
+ */
+ public function getResponse()
+ {
+ $controller = $this->getActionController();
+ if (null === $controller) {
+ $controller = $this->getFrontController();
+ }
+
+ return $controller->getResponse();
+ }
+
+ /**
+ * getName()
+ *
+ * @return string
+ */
+ public function getName()
+ {
+ $fullClassName = get_class($this);
+ if (strpos($fullClassName, '_') !== false) {
+ $helperName = strrchr($fullClassName, '_');
+ return ltrim($helperName, '_');
+ } elseif (strpos($fullClassName, '\\') !== false) {
+ $helperName = strrchr($fullClassName, '\\');
+ return ltrim($helperName, '\\');
+ } else {
+ return $fullClassName;
+ }
+ }
+}
diff --git a/lib/zend/Zend/Controller/Action/Helper/ActionStack.php b/lib/zend/Zend/Controller/Action/Helper/ActionStack.php
new file mode 100644
index 00000000000..e22e8b8e7e4
--- /dev/null
+++ b/lib/zend/Zend/Controller/Action/Helper/ActionStack.php
@@ -0,0 +1,138 @@
+hasPlugin('Zend_Controller_Plugin_ActionStack')) {
+ /**
+ * @see Zend_Controller_Plugin_ActionStack
+ */
+ require_once 'Zend/Controller/Plugin/ActionStack.php';
+ $this->_actionStack = new Zend_Controller_Plugin_ActionStack();
+ $front->registerPlugin($this->_actionStack, 97);
+ } else {
+ $this->_actionStack = $front->getPlugin('Zend_Controller_Plugin_ActionStack');
+ }
+ }
+
+ /**
+ * Push onto the stack
+ *
+ * @param Zend_Controller_Request_Abstract $next
+ * @return Zend_Controller_Action_Helper_ActionStack Provides a fluent interface
+ */
+ public function pushStack(Zend_Controller_Request_Abstract $next)
+ {
+ $this->_actionStack->pushStack($next);
+ return $this;
+ }
+
+ /**
+ * Push a new action onto the stack
+ *
+ * @param string $action
+ * @param string $controller
+ * @param string $module
+ * @param array $params
+ * @throws Zend_Controller_Action_Exception
+ * @return Zend_Controller_Action_Helper_ActionStack
+ */
+ public function actionToStack($action, $controller = null, $module = null, array $params = array())
+ {
+ if ($action instanceof Zend_Controller_Request_Abstract) {
+ return $this->pushStack($action);
+ } elseif (!is_string($action)) {
+ /**
+ * @see Zend_Controller_Action_Exception
+ */
+ require_once 'Zend/Controller/Action/Exception.php';
+ throw new Zend_Controller_Action_Exception('ActionStack requires either a request object or minimally a string action');
+ }
+
+ $request = $this->getRequest();
+
+ if ($request instanceof Zend_Controller_Request_Abstract === false){
+ /**
+ * @see Zend_Controller_Action_Exception
+ */
+ require_once 'Zend/Controller/Action/Exception.php';
+ throw new Zend_Controller_Action_Exception('Request object not set yet');
+ }
+
+ $controller = (null === $controller) ? $request->getControllerName() : $controller;
+ $module = (null === $module) ? $request->getModuleName() : $module;
+
+ /**
+ * @see Zend_Controller_Request_Simple
+ */
+ require_once 'Zend/Controller/Request/Simple.php';
+ $newRequest = new Zend_Controller_Request_Simple($action, $controller, $module, $params);
+
+ return $this->pushStack($newRequest);
+ }
+
+ /**
+ * Perform helper when called as $this->_helper->actionStack() from an action controller
+ *
+ * Proxies to {@link simple()}
+ *
+ * @param string $action
+ * @param string $controller
+ * @param string $module
+ * @param array $params
+ * @return boolean
+ */
+ public function direct($action, $controller = null, $module = null, array $params = array())
+ {
+ return $this->actionToStack($action, $controller, $module, $params);
+ }
+}
diff --git a/lib/zend/Zend/Controller/Action/Helper/AjaxContext.php b/lib/zend/Zend/Controller/Action/Helper/AjaxContext.php
new file mode 100644
index 00000000000..dd4ca426d67
--- /dev/null
+++ b/lib/zend/Zend/Controller/Action/Helper/AjaxContext.php
@@ -0,0 +1,80 @@
+addContext('html', array('suffix' => 'ajax'));
+ }
+
+ /**
+ * Initialize AJAX context switching
+ *
+ * Checks for XHR requests; if detected, attempts to perform context switch.
+ *
+ * @param string $format
+ * @return void
+ */
+ public function initContext($format = null)
+ {
+ $this->_currentContext = null;
+
+ $request = $this->getRequest();
+ if (!method_exists($request, 'isXmlHttpRequest') ||
+ !$this->getRequest()->isXmlHttpRequest())
+ {
+ return;
+ }
+
+ return parent::initContext($format);
+ }
+}
diff --git a/lib/zend/Zend/Controller/Action/Helper/AutoComplete/Abstract.php b/lib/zend/Zend/Controller/Action/Helper/AutoComplete/Abstract.php
new file mode 100644
index 00000000000..707545434b2
--- /dev/null
+++ b/lib/zend/Zend/Controller/Action/Helper/AutoComplete/Abstract.php
@@ -0,0 +1,149 @@
+disableLayout();
+ }
+
+ Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer')->setNoRender(true);
+
+ return $this;
+ }
+
+ /**
+ * Encode data to JSON
+ *
+ * @param mixed $data
+ * @param bool $keepLayouts
+ * @throws Zend_Controller_Action_Exception
+ * @return string
+ */
+ public function encodeJson($data, $keepLayouts = false)
+ {
+ if ($this->validateData($data)) {
+ return Zend_Controller_Action_HelperBroker::getStaticHelper('Json')->encodeJson($data, $keepLayouts);
+ }
+
+ /**
+ * @see Zend_Controller_Action_Exception
+ */
+ require_once 'Zend/Controller/Action/Exception.php';
+ throw new Zend_Controller_Action_Exception('Invalid data passed for autocompletion');
+ }
+
+ /**
+ * Send autocompletion data
+ *
+ * Calls prepareAutoCompletion, populates response body with this
+ * information, and sends response.
+ *
+ * @param mixed $data
+ * @param bool $keepLayouts
+ * @return string|void
+ */
+ public function sendAutoCompletion($data, $keepLayouts = false)
+ {
+ $data = $this->prepareAutoCompletion($data, $keepLayouts);
+
+ $response = $this->getResponse();
+ $response->setBody($data);
+
+ if (!$this->suppressExit) {
+ $response->sendResponse();
+ exit;
+ }
+
+ return $data;
+ }
+
+ /**
+ * Strategy pattern: allow calling helper as broker method
+ *
+ * Prepares autocompletion data and, if $sendNow is true, immediately sends
+ * response.
+ *
+ * @param mixed $data
+ * @param bool $sendNow
+ * @param bool $keepLayouts
+ * @return string|void
+ */
+ public function direct($data, $sendNow = true, $keepLayouts = false)
+ {
+ if ($sendNow) {
+ return $this->sendAutoCompletion($data, $keepLayouts);
+ }
+
+ return $this->prepareAutoCompletion($data, $keepLayouts);
+ }
+}
diff --git a/lib/zend/Zend/Controller/Action/Helper/AutoCompleteDojo.php b/lib/zend/Zend/Controller/Action/Helper/AutoCompleteDojo.php
new file mode 100644
index 00000000000..9027f0f8e62
--- /dev/null
+++ b/lib/zend/Zend/Controller/Action/Helper/AutoCompleteDojo.php
@@ -0,0 +1,87 @@
+ $value) {
+ $items[] = array('label' => $value, 'name' => $value);
+ }
+ $data = new Zend_Dojo_Data('name', $items);
+ }
+
+ if (!$keepLayouts) {
+ require_once 'Zend/Controller/Action/HelperBroker.php';
+ Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer')->setNoRender(true);
+
+ require_once 'Zend/Layout.php';
+ $layout = Zend_Layout::getMvcInstance();
+ if ($layout instanceof Zend_Layout) {
+ $layout->disableLayout();
+ }
+ }
+
+ $response = Zend_Controller_Front::getInstance()->getResponse();
+ $response->setHeader('Content-Type', 'application/json');
+
+ return $data->toJson();
+ }
+}
diff --git a/lib/zend/Zend/Controller/Action/Helper/AutoCompleteScriptaculous.php b/lib/zend/Zend/Controller/Action/Helper/AutoCompleteScriptaculous.php
new file mode 100644
index 00000000000..098aed8b10c
--- /dev/null
+++ b/lib/zend/Zend/Controller/Action/Helper/AutoCompleteScriptaculous.php
@@ -0,0 +1,82 @@
+validateData($data)) {
+ /**
+ * @see Zend_Controller_Action_Exception
+ */
+ require_once 'Zend/Controller/Action/Exception.php';
+ throw new Zend_Controller_Action_Exception('Invalid data passed for autocompletion');
+ }
+
+ $data = (array) $data;
+ $data = '- ' . implode('
- ', $data) . '
';
+
+ if (!$keepLayouts) {
+ $this->disableLayouts();
+ }
+
+ return $data;
+ }
+}
diff --git a/lib/zend/Zend/Controller/Action/Helper/Cache.php b/lib/zend/Zend/Controller/Action/Helper/Cache.php
new file mode 100644
index 00000000000..61c089ff591
--- /dev/null
+++ b/lib/zend/Zend/Controller/Action/Helper/Cache.php
@@ -0,0 +1,289 @@
+getRequest()->getControllerName();
+ $actions = array_unique($actions);
+ if (!isset($this->_caching[$controller])) {
+ $this->_caching[$controller] = array();
+ }
+ if (!empty($tags)) {
+ $tags = array_unique($tags);
+ if (!isset($this->_tags[$controller])) {
+ $this->_tags[$controller] = array();
+ }
+ }
+ foreach ($actions as $action) {
+ $this->_caching[$controller][] = $action;
+ if (!empty($tags)) {
+ $this->_tags[$controller][$action] = array();
+ foreach ($tags as $tag) {
+ $this->_tags[$controller][$action][] = $tag;
+ }
+ }
+ }
+ if ($extension) {
+ if (!isset($this->_extensions[$controller])) {
+ $this->_extensions[$controller] = array();
+ }
+ foreach ($actions as $action) {
+ $this->_extensions[$controller][$action] = $extension;
+ }
+ }
+ }
+
+ /**
+ * Remove a specific page cache static file based on its
+ * relative URL from the application's public directory.
+ * The file extension is not required here; usually matches
+ * the original REQUEST_URI that was cached.
+ *
+ * @param string $relativeUrl
+ * @param bool $recursive
+ * @return mixed
+ */
+ public function removePage($relativeUrl, $recursive = false)
+ {
+ $cache = $this->getCache(Zend_Cache_Manager::PAGECACHE);
+ $encodedCacheId = $this->_encodeCacheId($relativeUrl);
+
+ if ($recursive) {
+ $backend = $cache->getBackend();
+ if (($backend instanceof Zend_Cache_Backend)
+ && method_exists($backend, 'removeRecursively')
+ ) {
+ $result = $backend->removeRecursively($encodedCacheId);
+ if (is_null($result) ) {
+ $result = $backend->removeRecursively($relativeUrl);
+ }
+ return $result;
+ }
+ }
+
+ $result = $cache->remove($encodedCacheId);
+ if (is_null($result) ) {
+ $result = $cache->remove($relativeUrl);
+ }
+ return $result;
+ }
+
+ /**
+ * Remove a specific page cache static file based on its
+ * relative URL from the application's public directory.
+ * The file extension is not required here; usually matches
+ * the original REQUEST_URI that was cached.
+ *
+ * @param array $tags
+ * @return mixed
+ */
+ public function removePagesTagged(array $tags)
+ {
+ return $this->getCache(Zend_Cache_Manager::PAGECACHE)
+ ->clean(Zend_Cache::CLEANING_MODE_MATCHING_ANY_TAG, $tags);
+ }
+
+ /**
+ * Commence page caching for any cacheable actions
+ *
+ * @return void
+ */
+ public function preDispatch()
+ {
+ $controller = $this->getRequest()->getControllerName();
+ $action = $this->getRequest()->getActionName();
+ $stats = ob_get_status(true);
+ foreach ($stats as $status) {
+ if ($status['name'] == 'Zend_Cache_Frontend_Page::_flush'
+ || $status['name'] == 'Zend_Cache_Frontend_Capture::_flush') {
+ $obStarted = true;
+ }
+ }
+ if (!isset($obStarted) && isset($this->_caching[$controller]) &&
+ in_array($action, $this->_caching[$controller])) {
+ $reqUri = $this->getRequest()->getRequestUri();
+ $tags = array();
+ if (isset($this->_tags[$controller][$action])
+ && !empty($this->_tags[$controller][$action])) {
+ $tags = array_unique($this->_tags[$controller][$action]);
+ }
+ $extension = null;
+ if (isset($this->_extensions[$controller][$action])) {
+ $extension = $this->_extensions[$controller][$action];
+ }
+ $this->getCache(Zend_Cache_Manager::PAGECACHE)
+ ->start($this->_encodeCacheId($reqUri), $tags, $extension);
+ }
+ }
+
+ /**
+ * Encode a Cache ID as hexadecimal. This is a workaround because Backend ID validation
+ * is trapped in the Frontend classes. Will try to get this reversed for ZF 2.0
+ * because it's a major annoyance to have IDs so restricted!
+ *
+ * @return string
+ * @param string $requestUri
+ */
+ protected function _encodeCacheId($requestUri)
+ {
+ return bin2hex($requestUri);
+ }
+
+ /**
+ * Set an instance of the Cache Manager for this helper
+ *
+ * @param Zend_Cache_Manager $manager
+ * @return void
+ */
+ public function setManager(Zend_Cache_Manager $manager)
+ {
+ $this->_manager = $manager;
+ return $this;
+ }
+
+ /**
+ * Get the Cache Manager instance or instantiate the object if not
+ * exists. Attempts to load from bootstrap if available.
+ *
+ * @return Zend_Cache_Manager
+ */
+ public function getManager()
+ {
+ if ($this->_manager !== null) {
+ return $this->_manager;
+ }
+ $front = Zend_Controller_Front::getInstance();
+ if ($front->getParam('bootstrap')
+ && $front->getParam('bootstrap')->getResource('CacheManager')) {
+ return $front->getParam('bootstrap')
+ ->getResource('CacheManager');
+ }
+ $this->_manager = new Zend_Cache_Manager;
+ return $this->_manager;
+ }
+
+ /**
+ * Return a list of actions for the current Controller marked for
+ * caching
+ *
+ * @return array
+ */
+ public function getCacheableActions()
+ {
+ return $this->_caching;
+ }
+
+ /**
+ * Return a list of tags set for all cacheable actions
+ *
+ * @return array
+ */
+ public function getCacheableTags()
+ {
+ return $this->_tags;
+ }
+
+ /**
+ * Proxy non-matched methods back to Zend_Cache_Manager where
+ * appropriate
+ *
+ * @param string $method
+ * @param array $args
+ * @return mixed
+ */
+ public function __call($method, $args)
+ {
+ if (method_exists($this->getManager(), $method)) {
+ return call_user_func_array(
+ array($this->getManager(), $method), $args
+ );
+ }
+ throw new Zend_Controller_Action_Exception('Method does not exist:'
+ . $method);
+ }
+
+}
diff --git a/lib/zend/Zend/Controller/Action/Helper/ContextSwitch.php b/lib/zend/Zend/Controller/Action/Helper/ContextSwitch.php
new file mode 100644
index 00000000000..fe9114bc6eb
--- /dev/null
+++ b/lib/zend/Zend/Controller/Action/Helper/ContextSwitch.php
@@ -0,0 +1,1394 @@
+setConfig($options);
+ } elseif (is_array($options)) {
+ $this->setOptions($options);
+ }
+
+ if (empty($this->_contexts)) {
+ $this->addContexts(array(
+ 'json' => array(
+ 'suffix' => 'json',
+ 'headers' => array('Content-Type' => 'application/json'),
+ 'callbacks' => array(
+ 'init' => 'initJsonContext',
+ 'post' => 'postJsonContext'
+ )
+ ),
+ 'xml' => array(
+ 'suffix' => 'xml',
+ 'headers' => array('Content-Type' => 'application/xml'),
+ )
+ ));
+ }
+
+ $this->init();
+ }
+
+ /**
+ * Initialize at start of action controller
+ *
+ * Reset the view script suffix to the original state, or store the
+ * original state.
+ *
+ * @return void
+ */
+ public function init()
+ {
+ if (null === $this->_viewSuffixOrig) {
+ $this->_viewSuffixOrig = $this->_getViewRenderer()->getViewSuffix();
+ } else {
+ $this->_getViewRenderer()->setViewSuffix($this->_viewSuffixOrig);
+ }
+ }
+
+ /**
+ * Configure object from array of options
+ *
+ * @param array $options
+ * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
+ */
+ public function setOptions(array $options)
+ {
+ if (isset($options['contexts'])) {
+ $this->setContexts($options['contexts']);
+ unset($options['contexts']);
+ }
+
+ foreach ($options as $key => $value) {
+ $method = 'set' . ucfirst($key);
+ if (in_array($method, $this->_unconfigurable)) {
+ continue;
+ }
+
+ if (in_array($method, $this->_specialConfig)) {
+ $method = '_' . $method;
+ }
+
+ if (method_exists($this, $method)) {
+ $this->$method($value);
+ }
+ }
+ return $this;
+ }
+
+ /**
+ * Set object state from config object
+ *
+ * @param Zend_Config $config
+ * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
+ */
+ public function setConfig(Zend_Config $config)
+ {
+ return $this->setOptions($config->toArray());
+ }
+
+ /**
+ * Strategy pattern: return object
+ *
+ * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
+ */
+ public function direct()
+ {
+ return $this;
+ }
+
+ /**
+ * Initialize context detection and switching
+ *
+ * @param mixed $format
+ * @throws Zend_Controller_Action_Exception
+ * @return void
+ */
+ public function initContext($format = null)
+ {
+ $this->_currentContext = null;
+
+ $controller = $this->getActionController();
+ $request = $this->getRequest();
+ $action = $request->getActionName();
+
+ // Return if no context switching enabled, or no context switching
+ // enabled for this action
+ $contexts = $this->getActionContexts($action);
+ if (empty($contexts)) {
+ return;
+ }
+
+ // Return if no context parameter provided
+ if (!$context = $request->getParam($this->getContextParam())) {
+ if ($format === null) {
+ return;
+ }
+ $context = $format;
+ $format = null;
+ }
+
+ // Check if context allowed by action controller
+ if (!$this->hasActionContext($action, $context)) {
+ return;
+ }
+
+ // Return if invalid context parameter provided and no format or invalid
+ // format provided
+ if (!$this->hasContext($context)) {
+ if (empty($format) || !$this->hasContext($format)) {
+
+ return;
+ }
+ }
+
+ // Use provided format if passed
+ if (!empty($format) && $this->hasContext($format)) {
+ $context = $format;
+ }
+
+ $suffix = $this->getSuffix($context);
+
+ $this->_getViewRenderer()->setViewSuffix($suffix);
+
+ $headers = $this->getHeaders($context);
+ if (!empty($headers)) {
+ $response = $this->getResponse();
+ foreach ($headers as $header => $content) {
+ $response->setHeader($header, $content);
+ }
+ }
+
+ if ($this->getAutoDisableLayout()) {
+ /**
+ * @see Zend_Layout
+ */
+ require_once 'Zend/Layout.php';
+ $layout = Zend_Layout::getMvcInstance();
+ if (null !== $layout) {
+ $layout->disableLayout();
+ }
+ }
+
+ if (null !== ($callback = $this->getCallback($context, self::TRIGGER_INIT))) {
+ if (is_string($callback) && method_exists($this, $callback)) {
+ $this->$callback();
+ } elseif (is_string($callback) && function_exists($callback)) {
+ $callback();
+ } elseif (is_array($callback)) {
+ call_user_func($callback);
+ } else {
+ /**
+ * @see Zend_Controller_Action_Exception
+ */
+ require_once 'Zend/Controller/Action/Exception.php';
+ throw new Zend_Controller_Action_Exception(sprintf('Invalid context callback registered for context "%s"', $context));
+ }
+ }
+
+ $this->_currentContext = $context;
+ }
+
+ /**
+ * JSON context extra initialization
+ *
+ * Turns off viewRenderer auto-rendering
+ *
+ * @return void
+ */
+ public function initJsonContext()
+ {
+ if (!$this->getAutoJsonSerialization()) {
+ return;
+ }
+
+ $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
+ $view = $viewRenderer->view;
+ if ($view instanceof Zend_View_Interface) {
+ $viewRenderer->setNoRender(true);
+ }
+ }
+
+ /**
+ * Should JSON contexts auto-serialize?
+ *
+ * @param boolean $flag
+ * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
+ */
+ public function setAutoJsonSerialization($flag)
+ {
+ $this->_autoJsonSerialization = (bool) $flag;
+ return $this;
+ }
+
+ /**
+ * Get JSON context auto-serialization flag
+ *
+ * @return boolean
+ */
+ public function getAutoJsonSerialization()
+ {
+ return $this->_autoJsonSerialization;
+ }
+
+ /**
+ * Set suffix from array
+ *
+ * @param array $spec
+ * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
+ */
+ protected function _setSuffix(array $spec)
+ {
+ foreach ($spec as $context => $suffixInfo) {
+ if (!is_string($context)) {
+ $context = null;
+ }
+
+ if (is_string($suffixInfo)) {
+ $this->setSuffix($context, $suffixInfo);
+ continue;
+ } elseif (is_array($suffixInfo)) {
+ if (isset($suffixInfo['suffix'])) {
+ $suffix = $suffixInfo['suffix'];
+ $prependViewRendererSuffix = true;
+
+ if ((null === $context) && isset($suffixInfo['context'])) {
+ $context = $suffixInfo['context'];
+ }
+
+ if (isset($suffixInfo['prependViewRendererSuffix'])) {
+ $prependViewRendererSuffix = $suffixInfo['prependViewRendererSuffix'];
+ }
+
+ $this->setSuffix($context, $suffix, $prependViewRendererSuffix);
+ continue;
+ }
+
+ $count = count($suffixInfo);
+ switch (true) {
+ case (($count < 2) && (null === $context)):
+ /**
+ * @see Zend_Controller_Action_Exception
+ */
+ require_once 'Zend/Controller/Action/Exception.php';
+ throw new Zend_Controller_Action_Exception('Invalid suffix information provided in config');
+ case ($count < 2):
+ $suffix = array_shift($suffixInfo);
+ $this->setSuffix($context, $suffix);
+ break;
+ case (($count < 3) && (null === $context)):
+ $context = array_shift($suffixInfo);
+ $suffix = array_shift($suffixInfo);
+ $this->setSuffix($context, $suffix);
+ break;
+ case (($count == 3) && (null === $context)):
+ $context = array_shift($suffixInfo);
+ $suffix = array_shift($suffixInfo);
+ $prependViewRendererSuffix = array_shift($suffixInfo);
+ $this->setSuffix($context, $suffix, $prependViewRendererSuffix);
+ break;
+ case ($count >= 2):
+ $suffix = array_shift($suffixInfo);
+ $prependViewRendererSuffix = array_shift($suffixInfo);
+ $this->setSuffix($context, $suffix, $prependViewRendererSuffix);
+ break;
+ }
+ }
+ }
+ return $this;
+ }
+
+ /**
+ * Customize view script suffix to use when switching context.
+ *
+ * Passing an empty suffix value to the setters disables the view script
+ * suffix change.
+ *
+ * @param string $context Context type for which to set suffix
+ * @param string $suffix Suffix to use
+ * @param boolean $prependViewRendererSuffix Whether or not to prepend the new suffix to the viewrenderer suffix
+ * @throws Zend_Controller_Action_Exception
+ * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
+ */
+ public function setSuffix($context, $suffix, $prependViewRendererSuffix = true)
+ {
+ if (!isset($this->_contexts[$context])) {
+ /**
+ * @see Zend_Controller_Action_Exception
+ */
+ require_once 'Zend/Controller/Action/Exception.php';
+ throw new Zend_Controller_Action_Exception(sprintf('Cannot set suffix; invalid context type "%s"', $context));
+ }
+
+ if (empty($suffix)) {
+ $suffix = '';
+ }
+
+ if (is_array($suffix)) {
+ if (isset($suffix['prependViewRendererSuffix'])) {
+ $prependViewRendererSuffix = $suffix['prependViewRendererSuffix'];
+ }
+ if (isset($suffix['suffix'])) {
+ $suffix = $suffix['suffix'];
+ } else {
+ $suffix = '';
+ }
+ }
+
+ $suffix = (string) $suffix;
+
+ if ($prependViewRendererSuffix) {
+ if (empty($suffix)) {
+ $suffix = $this->_getViewRenderer()->getViewSuffix();
+ } else {
+ $suffix .= '.' . $this->_getViewRenderer()->getViewSuffix();
+ }
+ }
+
+ $this->_contexts[$context]['suffix'] = $suffix;
+ return $this;
+ }
+
+ /**
+ * Retrieve suffix for given context type
+ *
+ * @param string $type Context type
+ * @throws Zend_Controller_Action_Exception
+ * @return string
+ */
+ public function getSuffix($type)
+ {
+ if (!isset($this->_contexts[$type])) {
+ /**
+ * @see Zend_Controller_Action_Exception
+ */
+ require_once 'Zend/Controller/Action/Exception.php';
+ throw new Zend_Controller_Action_Exception(sprintf('Cannot retrieve suffix; invalid context type "%s"', $type));
+ }
+
+ return $this->_contexts[$type]['suffix'];
+ }
+
+ /**
+ * Does the given context exist?
+ *
+ * @param string $context
+ * @param boolean $throwException
+ * @throws Zend_Controller_Action_Exception if context does not exist and throwException is true
+ * @return bool
+ */
+ public function hasContext($context, $throwException = false)
+ {
+ if (is_string($context)) {
+ if (isset($this->_contexts[$context])) {
+ return true;
+ }
+ } elseif (is_array($context)) {
+ $error = false;
+ foreach ($context as $test) {
+ if (!isset($this->_contexts[$test])) {
+ $error = (string) $test;
+ break;
+ }
+ }
+ if (false === $error) {
+ return true;
+ }
+ $context = $error;
+ } elseif (true === $context) {
+ return true;
+ }
+
+ if ($throwException) {
+ /**
+ * @see Zend_Controller_Action_Exception
+ */
+ require_once 'Zend/Controller/Action/Exception.php';
+ throw new Zend_Controller_Action_Exception(sprintf('Context "%s" does not exist', $context));
+ }
+
+ return false;
+ }
+
+ /**
+ * Add header to context
+ *
+ * @param string $context
+ * @param string $header
+ * @param string $content
+ * @throws Zend_Controller_Action_Exception
+ * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
+ */
+ public function addHeader($context, $header, $content)
+ {
+ $context = (string) $context;
+ $this->hasContext($context, true);
+
+ $header = (string) $header;
+ $content = (string) $content;
+
+ if (isset($this->_contexts[$context]['headers'][$header])) {
+ /**
+ * @see Zend_Controller_Action_Exception
+ */
+ require_once 'Zend/Controller/Action/Exception.php';
+ throw new Zend_Controller_Action_Exception(sprintf('Cannot add "%s" header to context "%s": already exists', $header, $context));
+ }
+
+ $this->_contexts[$context]['headers'][$header] = $content;
+ return $this;
+ }
+
+ /**
+ * Customize response header to use when switching context
+ *
+ * Passing an empty header value to the setters disables the response
+ * header.
+ *
+ * @param string $type Context type for which to set suffix
+ * @param string $header Header to set
+ * @param string $content Header content
+ * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
+ */
+ public function setHeader($context, $header, $content)
+ {
+ $this->hasContext($context, true);
+ $context = (string) $context;
+ $header = (string) $header;
+ $content = (string) $content;
+
+ $this->_contexts[$context]['headers'][$header] = $content;
+ return $this;
+ }
+
+ /**
+ * Add multiple headers at once for a given context
+ *
+ * @param string $context
+ * @param array $headers
+ * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
+ */
+ public function addHeaders($context, array $headers)
+ {
+ foreach ($headers as $header => $content) {
+ $this->addHeader($context, $header, $content);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Set headers from context => headers pairs
+ *
+ * @param array $options
+ * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
+ */
+ protected function _setHeaders(array $options)
+ {
+ foreach ($options as $context => $headers) {
+ if (!is_array($headers)) {
+ continue;
+ }
+ $this->setHeaders($context, $headers);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Set multiple headers at once for a given context
+ *
+ * @param string $context
+ * @param array $headers
+ * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
+ */
+ public function setHeaders($context, array $headers)
+ {
+ $this->clearHeaders($context);
+ foreach ($headers as $header => $content) {
+ $this->setHeader($context, $header, $content);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Retrieve context header
+ *
+ * Returns the value of a given header for a given context type
+ *
+ * @param string $context
+ * @param string $header
+ * @return string|null
+ */
+ public function getHeader($context, $header)
+ {
+ $this->hasContext($context, true);
+ $context = (string) $context;
+ $header = (string) $header;
+ if (isset($this->_contexts[$context]['headers'][$header])) {
+ return $this->_contexts[$context]['headers'][$header];
+ }
+
+ return null;
+ }
+
+ /**
+ * Retrieve context headers
+ *
+ * Returns all headers for a context as key/value pairs
+ *
+ * @param string $context
+ * @return array
+ */
+ public function getHeaders($context)
+ {
+ $this->hasContext($context, true);
+ $context = (string) $context;
+ return $this->_contexts[$context]['headers'];
+ }
+
+ /**
+ * Remove a single header from a context
+ *
+ * @param string $context
+ * @param string $header
+ * @return boolean
+ */
+ public function removeHeader($context, $header)
+ {
+ $this->hasContext($context, true);
+ $context = (string) $context;
+ $header = (string) $header;
+ if (isset($this->_contexts[$context]['headers'][$header])) {
+ unset($this->_contexts[$context]['headers'][$header]);
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Clear all headers for a given context
+ *
+ * @param string $context
+ * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
+ */
+ public function clearHeaders($context)
+ {
+ $this->hasContext($context, true);
+ $context = (string) $context;
+ $this->_contexts[$context]['headers'] = array();
+ return $this;
+ }
+
+ /**
+ * Validate trigger and return in normalized form
+ *
+ * @param string $trigger
+ * @throws Zend_Controller_Action_Exception
+ * @return string
+ */
+ protected function _validateTrigger($trigger)
+ {
+ $trigger = strtoupper($trigger);
+ if ('TRIGGER_' !== substr($trigger, 0, 8)) {
+ $trigger = 'TRIGGER_' . $trigger;
+ }
+
+ if (!in_array($trigger, array(self::TRIGGER_INIT, self::TRIGGER_POST))) {
+ /**
+ * @see Zend_Controller_Action_Exception
+ */
+ require_once 'Zend/Controller/Action/Exception.php';
+ throw new Zend_Controller_Action_Exception(sprintf('Invalid trigger "%s"', $trigger));
+ }
+
+ return $trigger;
+ }
+
+ /**
+ * Set a callback for a given context and trigger
+ *
+ * @param string $context
+ * @param string $trigger
+ * @param string|array $callback
+ * @throws Zend_Controller_Action_Exception
+ * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
+ */
+ public function setCallback($context, $trigger, $callback)
+ {
+ $this->hasContext($context, true);
+ $trigger = $this->_validateTrigger($trigger);
+
+ if (!is_string($callback)) {
+ if (!is_array($callback) || (2 != count($callback))) {
+ /**
+ * @see Zend_Controller_Action_Exception
+ */
+ require_once 'Zend/Controller/Action/Exception.php';
+ throw new Zend_Controller_Action_Exception('Invalid callback specified');
+ }
+ }
+
+ $this->_contexts[$context]['callbacks'][$trigger] = $callback;
+ return $this;
+ }
+
+ /**
+ * Set callbacks from array of context => callbacks pairs
+ *
+ * @param array $options
+ * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
+ */
+ protected function _setCallbacks(array $options)
+ {
+ foreach ($options as $context => $callbacks) {
+ if (!is_array($callbacks)) {
+ continue;
+ }
+
+ $this->setCallbacks($context, $callbacks);
+ }
+ return $this;
+ }
+
+ /**
+ * Set callbacks for a given context
+ *
+ * Callbacks should be in trigger/callback pairs.
+ *
+ * @param string $context
+ * @param array $callbacks
+ * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
+ */
+ public function setCallbacks($context, array $callbacks)
+ {
+ $this->hasContext($context, true);
+ $context = (string) $context;
+ if (!isset($this->_contexts[$context]['callbacks'])) {
+ $this->_contexts[$context]['callbacks'] = array();
+ }
+
+ foreach ($callbacks as $trigger => $callback) {
+ $this->setCallback($context, $trigger, $callback);
+ }
+ return $this;
+ }
+
+ /**
+ * Get a single callback for a given context and trigger
+ *
+ * @param string $context
+ * @param string $trigger
+ * @return string|array|null
+ */
+ public function getCallback($context, $trigger)
+ {
+ $this->hasContext($context, true);
+ $trigger = $this->_validateTrigger($trigger);
+ if (isset($this->_contexts[$context]['callbacks'][$trigger])) {
+ return $this->_contexts[$context]['callbacks'][$trigger];
+ }
+
+ return null;
+ }
+
+ /**
+ * Get all callbacks for a given context
+ *
+ * @param string $context
+ * @return array
+ */
+ public function getCallbacks($context)
+ {
+ $this->hasContext($context, true);
+ return $this->_contexts[$context]['callbacks'];
+ }
+
+ /**
+ * Clear a callback for a given context and trigger
+ *
+ * @param string $context
+ * @param string $trigger
+ * @return boolean
+ */
+ public function removeCallback($context, $trigger)
+ {
+ $this->hasContext($context, true);
+ $trigger = $this->_validateTrigger($trigger);
+ if (isset($this->_contexts[$context]['callbacks'][$trigger])) {
+ unset($this->_contexts[$context]['callbacks'][$trigger]);
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Clear all callbacks for a given context
+ *
+ * @param string $context
+ * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
+ */
+ public function clearCallbacks($context)
+ {
+ $this->hasContext($context, true);
+ $this->_contexts[$context]['callbacks'] = array();
+ return $this;
+ }
+
+ /**
+ * Set name of parameter to use when determining context format
+ *
+ * @param string $name
+ * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
+ */
+ public function setContextParam($name)
+ {
+ $this->_contextParam = (string) $name;
+ return $this;
+ }
+
+ /**
+ * Return context format request parameter name
+ *
+ * @return string
+ */
+ public function getContextParam()
+ {
+ return $this->_contextParam;
+ }
+
+ /**
+ * Indicate default context to use when no context format provided
+ *
+ * @param string $type
+ * @throws Zend_Controller_Action_Exception
+ * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
+ */
+ public function setDefaultContext($type)
+ {
+ if (!isset($this->_contexts[$type])) {
+ /**
+ * @see Zend_Controller_Action_Exception
+ */
+ require_once 'Zend/Controller/Action/Exception.php';
+ throw new Zend_Controller_Action_Exception(sprintf('Cannot set default context; invalid context type "%s"', $type));
+ }
+
+ $this->_defaultContext = $type;
+ return $this;
+ }
+
+ /**
+ * Return default context
+ *
+ * @return string
+ */
+ public function getDefaultContext()
+ {
+ return $this->_defaultContext;
+ }
+
+ /**
+ * Set flag indicating if layout should be disabled
+ *
+ * @param boolean $flag
+ * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
+ */
+ public function setAutoDisableLayout($flag)
+ {
+ $this->_disableLayout = ($flag) ? true : false;
+ return $this;
+ }
+
+ /**
+ * Retrieve auto layout disable flag
+ *
+ * @return boolean
+ */
+ public function getAutoDisableLayout()
+ {
+ return $this->_disableLayout;
+ }
+
+ /**
+ * Add new context
+ *
+ * @param string $context Context type
+ * @param array $spec Context specification
+ * @throws Zend_Controller_Action_Exception
+ * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
+ */
+ public function addContext($context, array $spec)
+ {
+ if ($this->hasContext($context)) {
+ /**
+ * @see Zend_Controller_Action_Exception
+ */
+ require_once 'Zend/Controller/Action/Exception.php';
+ throw new Zend_Controller_Action_Exception(sprintf('Cannot add context "%s"; already exists', $context));
+ }
+ $context = (string) $context;
+
+ $this->_contexts[$context] = array();
+
+ $this->setSuffix($context, (isset($spec['suffix']) ? $spec['suffix'] : ''))
+ ->setHeaders($context, (isset($spec['headers']) ? $spec['headers'] : array()))
+ ->setCallbacks($context, (isset($spec['callbacks']) ? $spec['callbacks'] : array()));
+ return $this;
+ }
+
+ /**
+ * Overwrite existing context
+ *
+ * @param string $context Context type
+ * @param array $spec Context specification
+ * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
+ */
+ public function setContext($context, array $spec)
+ {
+ $this->removeContext($context);
+ return $this->addContext($context, $spec);
+ }
+
+ /**
+ * Add multiple contexts
+ *
+ * @param array $contexts
+ * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
+ */
+ public function addContexts(array $contexts)
+ {
+ foreach ($contexts as $context => $spec) {
+ $this->addContext($context, $spec);
+ }
+ return $this;
+ }
+
+ /**
+ * Set multiple contexts, after first removing all
+ *
+ * @param array $contexts
+ * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
+ */
+ public function setContexts(array $contexts)
+ {
+ $this->clearContexts();
+ foreach ($contexts as $context => $spec) {
+ $this->addContext($context, $spec);
+ }
+ return $this;
+ }
+
+ /**
+ * Retrieve context specification
+ *
+ * @param string $context
+ * @return array|null
+ */
+ public function getContext($context)
+ {
+ if ($this->hasContext($context)) {
+ return $this->_contexts[(string) $context];
+ }
+ return null;
+ }
+
+ /**
+ * Retrieve context definitions
+ *
+ * @return array
+ */
+ public function getContexts()
+ {
+ return $this->_contexts;
+ }
+
+ /**
+ * Remove a context
+ *
+ * @param string $context
+ * @return boolean
+ */
+ public function removeContext($context)
+ {
+ if ($this->hasContext($context)) {
+ unset($this->_contexts[(string) $context]);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Remove all contexts
+ *
+ * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
+ */
+ public function clearContexts()
+ {
+ $this->_contexts = array();
+ return $this;
+ }
+
+ /**
+ * Return current context, if any
+ *
+ * @return null|string
+ */
+ public function getCurrentContext()
+ {
+ return $this->_currentContext;
+ }
+
+ /**
+ * Post dispatch processing
+ *
+ * Execute postDispatch callback for current context, if available
+ *
+ * @throws Zend_Controller_Action_Exception
+ * @return void
+ */
+ public function postDispatch()
+ {
+ $context = $this->getCurrentContext();
+ if (null !== $context) {
+ if (null !== ($callback = $this->getCallback($context, self::TRIGGER_POST))) {
+ if (is_string($callback) && method_exists($this, $callback)) {
+ $this->$callback();
+ } elseif (is_string($callback) && function_exists($callback)) {
+ $callback();
+ } elseif (is_array($callback)) {
+ call_user_func($callback);
+ } else {
+ /**
+ * @see Zend_Controller_Action_Exception
+ */
+ require_once 'Zend/Controller/Action/Exception.php';
+ throw new Zend_Controller_Action_Exception(sprintf('Invalid postDispatch context callback registered for context "%s"', $context));
+ }
+ }
+ }
+ }
+
+ /**
+ * JSON post processing
+ *
+ * JSON serialize view variables to response body
+ *
+ * @return void
+ */
+ public function postJsonContext()
+ {
+ if (!$this->getAutoJsonSerialization()) {
+ return;
+ }
+
+ $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
+ $view = $viewRenderer->view;
+ if ($view instanceof Zend_View_Interface) {
+ /**
+ * @see Zend_Json
+ */
+ if(method_exists($view, 'getVars')) {
+ require_once 'Zend/Json.php';
+ $vars = Zend_Json::encode($view->getVars());
+ $this->getResponse()->setBody($vars);
+ } else {
+ require_once 'Zend/Controller/Action/Exception.php';
+ throw new Zend_Controller_Action_Exception('View does not implement the getVars() method needed to encode the view into JSON');
+ }
+ }
+ }
+
+ /**
+ * Add one or more contexts to an action
+ *
+ * @param string $action
+ * @param string|array $context
+ * @return Zend_Controller_Action_Helper_ContextSwitch|void Provides a fluent interface
+ */
+ public function addActionContext($action, $context)
+ {
+ $this->hasContext($context, true);
+ $controller = $this->getActionController();
+ if (null === $controller) {
+ return;
+ }
+ $action = (string) $action;
+ $contextKey = $this->_contextKey;
+
+ if (!isset($controller->$contextKey)) {
+ $controller->$contextKey = array();
+ }
+
+ if (true === $context) {
+ $contexts = $this->getContexts();
+ $controller->{$contextKey}[$action] = array_keys($contexts);
+ return $this;
+ }
+
+ $context = (array) $context;
+ if (!isset($controller->{$contextKey}[$action])) {
+ $controller->{$contextKey}[$action] = $context;
+ } else {
+ $controller->{$contextKey}[$action] = array_merge(
+ $controller->{$contextKey}[$action],
+ $context
+ );
+ }
+
+ return $this;
+ }
+
+ /**
+ * Set a context as available for a given controller action
+ *
+ * @param string $action
+ * @param string|array $context
+ * @return Zend_Controller_Action_Helper_ContextSwitch|void Provides a fluent interface
+ */
+ public function setActionContext($action, $context)
+ {
+ $this->hasContext($context, true);
+ $controller = $this->getActionController();
+ if (null === $controller) {
+ return;
+ }
+ $action = (string) $action;
+ $contextKey = $this->_contextKey;
+
+ if (!isset($controller->$contextKey)) {
+ $controller->$contextKey = array();
+ }
+
+ if (true === $context) {
+ $contexts = $this->getContexts();
+ $controller->{$contextKey}[$action] = array_keys($contexts);
+ } else {
+ $controller->{$contextKey}[$action] = (array) $context;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Add multiple action/context pairs at once
+ *
+ * @param array $contexts
+ * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
+ */
+ public function addActionContexts(array $contexts)
+ {
+ foreach ($contexts as $action => $context) {
+ $this->addActionContext($action, $context);
+ }
+ return $this;
+ }
+
+ /**
+ * Overwrite and set multiple action contexts at once
+ *
+ * @param array $contexts
+ * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
+ */
+ public function setActionContexts(array $contexts)
+ {
+ foreach ($contexts as $action => $context) {
+ $this->setActionContext($action, $context);
+ }
+ return $this;
+ }
+
+ /**
+ * Does a particular controller action have the given context(s)?
+ *
+ * @param string $action
+ * @param string|array $context
+ * @throws Zend_Controller_Action_Exception
+ * @return boolean
+ */
+ public function hasActionContext($action, $context)
+ {
+ $this->hasContext($context, true);
+ $controller = $this->getActionController();
+ if (null === $controller) {
+ return false;
+ }
+ $action = (string) $action;
+ $contextKey = $this->_contextKey;
+
+ if (!isset($controller->{$contextKey})) {
+ return false;
+ }
+
+ $allContexts = $controller->{$contextKey};
+
+ if (!is_array($allContexts)) {
+ /**
+ * @see Zend_Controller_Action_Exception
+ */
+ require_once 'Zend/Controller/Action/Exception.php';
+ throw new Zend_Controller_Action_Exception("Invalid contexts found for controller");
+ }
+
+ if (!isset($allContexts[$action])) {
+ return false;
+ }
+
+ if (true === $allContexts[$action]) {
+ return true;
+ }
+
+ $contexts = $allContexts[$action];
+
+ if (!is_array($contexts)) {
+ /**
+ * @see Zend_Controller_Action_Exception
+ */
+ require_once 'Zend/Controller/Action/Exception.php';
+ throw new Zend_Controller_Action_Exception(sprintf("Invalid contexts found for action '%s'", $action));
+ }
+
+ if (is_string($context) && in_array($context, $contexts)) {
+ return true;
+ } elseif (is_array($context)) {
+ $found = true;
+ foreach ($context as $test) {
+ if (!in_array($test, $contexts)) {
+ $found = false;
+ break;
+ }
+ }
+ return $found;
+ }
+
+ return false;
+ }
+
+ /**
+ * Get contexts for a given action or all actions in the controller
+ *
+ * @param string $action
+ * @return array
+ */
+ public function getActionContexts($action = null)
+ {
+ $controller = $this->getActionController();
+ if (null === $controller) {
+ return array();
+ }
+ $contextKey = $this->_contextKey;
+
+ if (!isset($controller->$contextKey)) {
+ return array();
+ }
+
+ if (null !== $action) {
+ $action = (string) $action;
+ if (isset($controller->{$contextKey}[$action])) {
+ return $controller->{$contextKey}[$action];
+ } else {
+ return array();
+ }
+ }
+
+ return $controller->$contextKey;
+ }
+
+ /**
+ * Remove one or more contexts for a given controller action
+ *
+ * @param string $action
+ * @param string|array $context
+ * @return boolean
+ */
+ public function removeActionContext($action, $context)
+ {
+ if ($this->hasActionContext($action, $context)) {
+ $controller = $this->getActionController();
+ $contextKey = $this->_contextKey;
+ $action = (string) $action;
+ $contexts = $controller->$contextKey;
+ $actionContexts = $contexts[$action];
+ $contexts = (array) $context;
+ foreach ($contexts as $context) {
+ $index = array_search($context, $actionContexts);
+ if (false !== $index) {
+ unset($controller->{$contextKey}[$action][$index]);
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Clear all contexts for a given controller action or all actions
+ *
+ * @param string $action
+ * @return Zend_Controller_Action_Helper_ContextSwitch Provides a fluent interface
+ */
+ public function clearActionContexts($action = null)
+ {
+ $controller = $this->getActionController();
+ $contextKey = $this->_contextKey;
+
+ if (!isset($controller->$contextKey) || empty($controller->$contextKey)) {
+ return $this;
+ }
+
+ if (null === $action) {
+ $controller->$contextKey = array();
+ return $this;
+ }
+
+ $action = (string) $action;
+ if (isset($controller->{$contextKey}[$action])) {
+ unset($controller->{$contextKey}[$action]);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Retrieve ViewRenderer
+ *
+ * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface
+ */
+ protected function _getViewRenderer()
+ {
+ if (null === $this->_viewRenderer) {
+ $this->_viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
+ }
+
+ return $this->_viewRenderer;
+ }
+}
+
diff --git a/lib/zend/Zend/Controller/Action/Helper/FlashMessenger.php b/lib/zend/Zend/Controller/Action/Helper/FlashMessenger.php
new file mode 100644
index 00000000000..57fe9ecdeeb
--- /dev/null
+++ b/lib/zend/Zend/Controller/Action/Helper/FlashMessenger.php
@@ -0,0 +1,313 @@
+getName());
+ foreach (self::$_session as $namespace => $messages) {
+ self::$_messages[$namespace] = $messages;
+ unset(self::$_session->{$namespace});
+ }
+ }
+ }
+
+ /**
+ * postDispatch() - runs after action is dispatched, in this
+ * case, it is resetting the namespace in case we have forwarded to a different
+ * action, Flashmessage will be 'clean' (default namespace)
+ *
+ * @return Zend_Controller_Action_Helper_FlashMessenger Provides a fluent interface
+ */
+ public function postDispatch()
+ {
+ $this->resetNamespace();
+ return $this;
+ }
+
+ /**
+ * setNamespace() - change the namespace messages are added to, useful for
+ * per action controller messaging between requests
+ *
+ * @param string $namespace
+ * @return Zend_Controller_Action_Helper_FlashMessenger Provides a fluent interface
+ */
+ public function setNamespace($namespace = 'default')
+ {
+ $this->_namespace = $namespace;
+ return $this;
+ }
+
+ /**
+ * getNamespace() - return the current namepsace
+ *
+ * @return string
+ */
+ public function getNamespace()
+ {
+ return $this->_namespace;
+ }
+
+ /**
+ * resetNamespace() - reset the namespace to the default
+ *
+ * @return Zend_Controller_Action_Helper_FlashMessenger Provides a fluent interface
+ */
+ public function resetNamespace()
+ {
+ $this->setNamespace();
+ return $this;
+ }
+
+ /**
+ * addMessage() - Add a message to flash message
+ *
+ * @param string $message
+ * @return Zend_Controller_Action_Helper_FlashMessenger Provides a fluent interface
+ */
+ public function addMessage($message, $namespace = null)
+ {
+ if (!is_string($namespace) || $namespace == '') {
+ $namespace = $this->getNamespace();
+ }
+
+ if (self::$_messageAdded === false) {
+ self::$_session->setExpirationHops(1, null, true);
+ }
+
+ if (!is_array(self::$_session->{$namespace})) {
+ self::$_session->{$namespace} = array();
+ }
+
+ self::$_session->{$namespace}[] = $message;
+ self::$_messageAdded = true;
+
+ return $this;
+ }
+
+ /**
+ * hasMessages() - Wether a specific namespace has messages
+ *
+ * @return boolean
+ */
+ public function hasMessages($namespace = null)
+ {
+ if (!is_string($namespace) || $namespace == '') {
+ $namespace = $this->getNamespace();
+ }
+
+ return isset(self::$_messages[$namespace]);
+ }
+
+ /**
+ * getMessages() - Get messages from a specific namespace
+ *
+ * @return array
+ */
+ public function getMessages($namespace = null)
+ {
+ if (!is_string($namespace) || $namespace == '') {
+ $namespace = $this->getNamespace();
+ }
+
+ if ($this->hasMessages($namespace)) {
+ return self::$_messages[$namespace];
+ }
+
+ return array();
+ }
+
+ /**
+ * Clear all messages from the previous request & current namespace
+ *
+ * @return boolean True if messages were cleared, false if none existed
+ */
+ public function clearMessages($namespace = null)
+ {
+ if (!is_string($namespace) || $namespace == '') {
+ $namespace = $this->getNamespace();
+ }
+
+ if ($this->hasMessages($namespace)) {
+ unset(self::$_messages[$namespace]);
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * hasCurrentMessages() - check to see if messages have been added to current
+ * namespace within this request
+ *
+ * @return boolean
+ */
+ public function hasCurrentMessages($namespace = null)
+ {
+ if (!is_string($namespace) || $namespace == '') {
+ $namespace = $this->getNamespace();
+ }
+
+ return isset(self::$_session->{$namespace});
+ }
+
+ /**
+ * getCurrentMessages() - get messages that have been added to the current
+ * namespace within this request
+ *
+ * @return array
+ */
+ public function getCurrentMessages($namespace = null)
+ {
+ if (!is_string($namespace) || $namespace == '') {
+ $namespace = $this->getNamespace();
+ }
+
+ if ($this->hasCurrentMessages($namespace)) {
+ return self::$_session->{$namespace};
+ }
+
+ return array();
+ }
+
+ /**
+ * clear messages from the current request & current namespace
+ *
+ * @return boolean
+ */
+ public function clearCurrentMessages($namespace = null)
+ {
+ if (!is_string($namespace) || $namespace == '') {
+ $namespace = $this->getNamespace();
+ }
+
+ if ($this->hasCurrentMessages($namespace)) {
+ unset(self::$_session->{$namespace});
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * getIterator() - complete the IteratorAggregate interface, for iterating
+ *
+ * @return ArrayObject
+ */
+ public function getIterator($namespace = null)
+ {
+ if (!is_string($namespace) || $namespace == '') {
+ $namespace = $this->getNamespace();
+ }
+
+ if ($this->hasMessages($namespace)) {
+ return new ArrayObject($this->getMessages($namespace));
+ }
+
+ return new ArrayObject();
+ }
+
+ /**
+ * count() - Complete the countable interface
+ *
+ * @return int
+ */
+ public function count($namespace = null)
+ {
+ if (!is_string($namespace) || $namespace == '') {
+ $namespace = $this->getNamespace();
+ }
+
+ if ($this->hasMessages($namespace)) {
+ return count($this->getMessages($namespace));
+ }
+
+ return 0;
+ }
+
+ /**
+ * Strategy pattern: proxy to addMessage()
+ *
+ * @param string $message
+ * @return void
+ */
+ public function direct($message, $namespace=NULL)
+ {
+ return $this->addMessage($message, $namespace);
+ }
+}
diff --git a/lib/zend/Zend/Controller/Action/Helper/Json.php b/lib/zend/Zend/Controller/Action/Helper/Json.php
new file mode 100644
index 00000000000..86a8b113c17
--- /dev/null
+++ b/lib/zend/Zend/Controller/Action/Helper/Json.php
@@ -0,0 +1,133 @@
+true|false
+ * if $keepLayouts and parmas for Zend_Json::encode are required
+ * then, the array can contains a 'keepLayout'=>true|false and/or 'encodeData'=>true|false
+ * that will not be passed to Zend_Json::encode method but will be passed
+ * to Zend_View_Helper_Json
+ * @throws Zend_Controller_Action_Helper_Json
+ * @return string
+ */
+ public function encodeJson($data, $keepLayouts = false, $encodeData = true)
+ {
+ /**
+ * @see Zend_View_Helper_Json
+ */
+ require_once 'Zend/View/Helper/Json.php';
+ $jsonHelper = new Zend_View_Helper_Json();
+ $data = $jsonHelper->json($data, $keepLayouts, $encodeData);
+
+ if (!$keepLayouts) {
+ /**
+ * @see Zend_Controller_Action_HelperBroker
+ */
+ require_once 'Zend/Controller/Action/HelperBroker.php';
+ Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer')->setNoRender(true);
+ }
+
+ return $data;
+ }
+
+ /**
+ * Encode JSON response and immediately send
+ *
+ * @param mixed $data
+ * @param boolean|array $keepLayouts
+ * @param $encodeData Encode $data as JSON?
+ * NOTE: if boolean, establish $keepLayouts to true|false
+ * if array, admit params for Zend_Json::encode as enableJsonExprFinder=>true|false
+ * if $keepLayouts and parmas for Zend_Json::encode are required
+ * then, the array can contains a 'keepLayout'=>true|false and/or 'encodeData'=>true|false
+ * that will not be passed to Zend_Json::encode method but will be passed
+ * to Zend_View_Helper_Json
+ * @return string|void
+ */
+ public function sendJson($data, $keepLayouts = false, $encodeData = true)
+ {
+ $data = $this->encodeJson($data, $keepLayouts, $encodeData);
+ $response = $this->getResponse();
+ $response->setBody($data);
+
+ if (!$this->suppressExit) {
+ $response->sendResponse();
+ exit;
+ }
+
+ return $data;
+ }
+
+ /**
+ * Strategy pattern: call helper as helper broker method
+ *
+ * Allows encoding JSON. If $sendNow is true, immediately sends JSON
+ * response.
+ *
+ * @param mixed $data
+ * @param boolean $sendNow
+ * @param boolean $keepLayouts
+ * @param boolean $encodeData Encode $data as JSON?
+ * @return string|void
+ */
+ public function direct($data, $sendNow = true, $keepLayouts = false, $encodeData = true)
+ {
+ if ($sendNow) {
+ return $this->sendJson($data, $keepLayouts, $encodeData);
+ }
+ return $this->encodeJson($data, $keepLayouts, $encodeData);
+ }
+}
diff --git a/lib/zend/Zend/Controller/Action/Helper/Redirector.php b/lib/zend/Zend/Controller/Action/Helper/Redirector.php
new file mode 100644
index 00000000000..8c81646224d
--- /dev/null
+++ b/lib/zend/Zend/Controller/Action/Helper/Redirector.php
@@ -0,0 +1,534 @@
+_code;
+ }
+
+ /**
+ * Validate HTTP status redirect code
+ *
+ * @param int $code
+ * @throws Zend_Controller_Action_Exception on invalid HTTP status code
+ * @return true
+ */
+ protected function _checkCode($code)
+ {
+ $code = (int)$code;
+ if ((300 > $code) || (307 < $code) || (304 == $code) || (306 == $code)) {
+ require_once 'Zend/Controller/Action/Exception.php';
+ throw new Zend_Controller_Action_Exception('Invalid redirect HTTP status code (' . $code . ')');
+ }
+
+ return true;
+ }
+
+ /**
+ * Set HTTP status code for {@link _redirect()} behaviour
+ *
+ * @param int $code
+ * @return Zend_Controller_Action_Helper_Redirector Provides a fluent interface
+ */
+ public function setCode($code)
+ {
+ $this->_checkCode($code);
+ $this->_code = $code;
+ return $this;
+ }
+
+ /**
+ * Retrieve flag for whether or not {@link _redirect()} will exit when finished.
+ *
+ * @return boolean
+ */
+ public function getExit()
+ {
+ return $this->_exit;
+ }
+
+ /**
+ * Set exit flag for {@link _redirect()} behaviour
+ *
+ * @param boolean $flag
+ * @return Zend_Controller_Action_Helper_Redirector Provides a fluent interface
+ */
+ public function setExit($flag)
+ {
+ $this->_exit = ($flag) ? true : false;
+ return $this;
+ }
+
+ /**
+ * Retrieve flag for whether or not {@link _redirect()} will prepend the
+ * base URL on relative URLs
+ *
+ * @return boolean
+ */
+ public function getPrependBase()
+ {
+ return $this->_prependBase;
+ }
+
+ /**
+ * Set 'prepend base' flag for {@link _redirect()} behaviour
+ *
+ * @param boolean $flag
+ * @return Zend_Controller_Action_Helper_Redirector Provides a fluent interface
+ */
+ public function setPrependBase($flag)
+ {
+ $this->_prependBase = ($flag) ? true : false;
+ return $this;
+ }
+
+ /**
+ * Retrieve flag for whether or not {@link redirectAndExit()} shall close the session before
+ * exiting.
+ *
+ * @return boolean
+ */
+ public function getCloseSessionOnExit()
+ {
+ return $this->_closeSessionOnExit;
+ }
+
+ /**
+ * Set flag for whether or not {@link redirectAndExit()} shall close the session before exiting.
+ *
+ * @param boolean $flag
+ * @return Zend_Controller_Action_Helper_Redirector Provides a fluent interface
+ */
+ public function setCloseSessionOnExit($flag)
+ {
+ $this->_closeSessionOnExit = ($flag) ? true : false;
+ return $this;
+ }
+
+ /**
+ * Return use absolute URI flag
+ *
+ * @return boolean
+ */
+ public function getUseAbsoluteUri()
+ {
+ return $this->_useAbsoluteUri;
+ }
+
+ /**
+ * Set use absolute URI flag
+ *
+ * @param boolean $flag
+ * @return Zend_Controller_Action_Helper_Redirector Provides a fluent interface
+ */
+ public function setUseAbsoluteUri($flag = true)
+ {
+ $this->_useAbsoluteUri = ($flag) ? true : false;
+ return $this;
+ }
+
+ /**
+ * Set redirect in response object
+ *
+ * @return void
+ */
+ protected function _redirect($url)
+ {
+ if ($this->getUseAbsoluteUri() && !preg_match('#^(https?|ftp)://#', $url)) {
+ $host = (isset($_SERVER['HTTP_HOST'])?$_SERVER['HTTP_HOST']:'');
+ $proto = (isset($_SERVER['HTTPS'])&&$_SERVER['HTTPS']!=="off") ? 'https' : 'http';
+ $port = (isset($_SERVER['SERVER_PORT'])?$_SERVER['SERVER_PORT']:80);
+ $uri = $proto . '://' . $host;
+ if ((('http' == $proto) && (80 != $port)) || (('https' == $proto) && (443 != $port))) {
+ // do not append if HTTP_HOST already contains port
+ if (strrchr($host, ':') === false) {
+ $uri .= ':' . $port;
+ }
+ }
+ $url = $uri . '/' . ltrim($url, '/');
+ }
+ $this->_redirectUrl = $url;
+ $this->getResponse()->setRedirect($url, $this->getCode());
+ }
+
+ /**
+ * Retrieve currently set URL for redirect
+ *
+ * @return string
+ */
+ public function getRedirectUrl()
+ {
+ return $this->_redirectUrl;
+ }
+
+ /**
+ * Determine if the baseUrl should be prepended, and prepend if necessary
+ *
+ * @param string $url
+ * @return string
+ */
+ protected function _prependBase($url)
+ {
+ if ($this->getPrependBase()) {
+ $request = $this->getRequest();
+ if ($request instanceof Zend_Controller_Request_Http) {
+ $base = rtrim($request->getBaseUrl(), '/');
+ if (!empty($base) && ('/' != $base)) {
+ $url = $base . '/' . ltrim($url, '/');
+ } else {
+ $url = '/' . ltrim($url, '/');
+ }
+ }
+ }
+
+ return $url;
+ }
+
+ /**
+ * Set a redirect URL of the form /module/controller/action/params
+ *
+ * @param string $action
+ * @param string $controller
+ * @param string $module
+ * @param array $params
+ * @return void
+ */
+ public function setGotoSimple($action, $controller = null, $module = null, array $params = array())
+ {
+ $dispatcher = $this->getFrontController()->getDispatcher();
+ $request = $this->getRequest();
+ $curModule = $request->getModuleName();
+ $useDefaultController = false;
+
+ if (null === $controller && null !== $module) {
+ $useDefaultController = true;
+ }
+
+ if (null === $module) {
+ $module = $curModule;
+ }
+
+ if ($module == $dispatcher->getDefaultModule()) {
+ $module = '';
+ }
+
+ if (null === $controller && !$useDefaultController) {
+ $controller = $request->getControllerName();
+ if (empty($controller)) {
+ $controller = $dispatcher->getDefaultControllerName();
+ }
+ }
+
+ $params[$request->getModuleKey()] = $module;
+ $params[$request->getControllerKey()] = $controller;
+ $params[$request->getActionKey()] = $action;
+
+ $router = $this->getFrontController()->getRouter();
+ $url = $router->assemble($params, 'default', true);
+
+ $this->_redirect($url);
+ }
+
+ /**
+ * Build a URL based on a route
+ *
+ * @param array $urlOptions
+ * @param string $name Route name
+ * @param boolean $reset
+ * @param boolean $encode
+ * @return void
+ */
+ public function setGotoRoute(array $urlOptions = array(), $name = null, $reset = false, $encode = true)
+ {
+ $router = $this->getFrontController()->getRouter();
+ $url = $router->assemble($urlOptions, $name, $reset, $encode);
+
+ $this->_redirect($url);
+ }
+
+ /**
+ * Set a redirect URL string
+ *
+ * By default, emits a 302 HTTP status header, prepends base URL as defined
+ * in request object if url is relative, and halts script execution by
+ * calling exit().
+ *
+ * $options is an optional associative array that can be used to control
+ * redirect behaviour. The available option keys are:
+ * - exit: boolean flag indicating whether or not to halt script execution when done
+ * - prependBase: boolean flag indicating whether or not to prepend the base URL when a relative URL is provided
+ * - code: integer HTTP status code to use with redirect. Should be between 300 and 307.
+ *
+ * _redirect() sets the Location header in the response object. If you set
+ * the exit flag to false, you can override this header later in code
+ * execution.
+ *
+ * If the exit flag is true (true by default), _redirect() will write and
+ * close the current session, if any.
+ *
+ * @param string $url
+ * @param array $options
+ * @return void
+ */
+ public function setGotoUrl($url, array $options = array())
+ {
+ // prevent header injections
+ $url = str_replace(array("\n", "\r"), '', $url);
+
+ if (null !== $options) {
+ if (isset($options['exit'])) {
+ $this->setExit(($options['exit']) ? true : false);
+ }
+ if (isset($options['prependBase'])) {
+ $this->setPrependBase(($options['prependBase']) ? true : false);
+ }
+ if (isset($options['code'])) {
+ $this->setCode($options['code']);
+ }
+ }
+
+ // If relative URL, decide if we should prepend base URL
+ if (!preg_match('|^[a-z]+://|', $url)) {
+ $url = $this->_prependBase($url);
+ }
+
+ $this->_redirect($url);
+ }
+
+ /**
+ * Perform a redirect to an action/controller/module with params
+ *
+ * @param string $action
+ * @param string $controller
+ * @param string $module
+ * @param array $params
+ * @return void
+ */
+ public function gotoSimple($action, $controller = null, $module = null, array $params = array())
+ {
+ $this->setGotoSimple($action, $controller, $module, $params);
+
+ if ($this->getExit()) {
+ $this->redirectAndExit();
+ }
+ }
+
+ /**
+ * Perform a redirect to an action/controller/module with params, forcing an immdiate exit
+ *
+ * @param mixed $action
+ * @param mixed $controller
+ * @param mixed $module
+ * @param array $params
+ * @return void
+ */
+ public function gotoSimpleAndExit($action, $controller = null, $module = null, array $params = array())
+ {
+ $this->setGotoSimple($action, $controller, $module, $params);
+ $this->redirectAndExit();
+ }
+
+ /**
+ * Redirect to a route-based URL
+ *
+ * Uses route's assemble method to build the URL; route is specified by $name;
+ * default route is used if none provided.
+ *
+ * @param array $urlOptions Array of key/value pairs used to assemble URL
+ * @param string $name
+ * @param boolean $reset
+ * @param boolean $encode
+ * @return void
+ */
+ public function gotoRoute(array $urlOptions = array(), $name = null, $reset = false, $encode = true)
+ {
+ $this->setGotoRoute($urlOptions, $name, $reset, $encode);
+
+ if ($this->getExit()) {
+ $this->redirectAndExit();
+ }
+ }
+
+ /**
+ * Redirect to a route-based URL, and immediately exit
+ *
+ * Uses route's assemble method to build the URL; route is specified by $name;
+ * default route is used if none provided.
+ *
+ * @param array $urlOptions Array of key/value pairs used to assemble URL
+ * @param string $name
+ * @param boolean $reset
+ * @return void
+ */
+ public function gotoRouteAndExit(array $urlOptions = array(), $name = null, $reset = false)
+ {
+ $this->setGotoRoute($urlOptions, $name, $reset);
+ $this->redirectAndExit();
+ }
+
+ /**
+ * Perform a redirect to a url
+ *
+ * @param string $url
+ * @param array $options
+ * @return void
+ */
+ public function gotoUrl($url, array $options = array())
+ {
+ $this->setGotoUrl($url, $options);
+
+ if ($this->getExit()) {
+ $this->redirectAndExit();
+ }
+ }
+
+ /**
+ * Set a URL string for a redirect, perform redirect, and immediately exit
+ *
+ * @param string $url
+ * @param array $options
+ * @return void
+ */
+ public function gotoUrlAndExit($url, array $options = array())
+ {
+ $this->setGotoUrl($url, $options);
+ $this->redirectAndExit();
+ }
+
+ /**
+ * exit(): Perform exit for redirector
+ *
+ * @return void
+ */
+ public function redirectAndExit()
+ {
+ if ($this->getCloseSessionOnExit()) {
+ // Close session, if started
+ if (class_exists('Zend_Session', false) && Zend_Session::isStarted()) {
+ Zend_Session::writeClose();
+ } elseif (isset($_SESSION)) {
+ session_write_close();
+ }
+ }
+
+ $this->getResponse()->sendHeaders();
+ exit();
+ }
+
+ /**
+ * direct(): Perform helper when called as
+ * $this->_helper->redirector($action, $controller, $module, $params)
+ *
+ * @param string $action
+ * @param string $controller
+ * @param string $module
+ * @param array $params
+ * @return void
+ */
+ public function direct($action, $controller = null, $module = null, array $params = array())
+ {
+ $this->gotoSimple($action, $controller, $module, $params);
+ }
+
+ /**
+ * Overloading
+ *
+ * Overloading for old 'goto', 'setGoto', and 'gotoAndExit' methods
+ *
+ * @param string $method
+ * @param array $args
+ * @return mixed
+ * @throws Zend_Controller_Action_Exception for invalid methods
+ */
+ public function __call($method, $args)
+ {
+ $method = strtolower($method);
+ if ('goto' == $method) {
+ return call_user_func_array(array($this, 'gotoSimple'), $args);
+ }
+ if ('setgoto' == $method) {
+ return call_user_func_array(array($this, 'setGotoSimple'), $args);
+ }
+ if ('gotoandexit' == $method) {
+ return call_user_func_array(array($this, 'gotoSimpleAndExit'), $args);
+ }
+
+ require_once 'Zend/Controller/Action/Exception.php';
+ throw new Zend_Controller_Action_Exception(sprintf('Invalid method "%s" called on redirector', $method));
+ }
+}
diff --git a/lib/zend/Zend/Controller/Action/Helper/Url.php b/lib/zend/Zend/Controller/Action/Helper/Url.php
new file mode 100644
index 00000000000..7b8c69ac12a
--- /dev/null
+++ b/lib/zend/Zend/Controller/Action/Helper/Url.php
@@ -0,0 +1,117 @@
+getRequest();
+
+ if (null === $controller) {
+ $controller = $request->getControllerName();
+ }
+
+ if (null === $module) {
+ $module = $request->getModuleName();
+ }
+
+ $url = $controller . '/' . $action;
+ if ($module != $this->getFrontController()->getDispatcher()->getDefaultModule()) {
+ $url = $module . '/' . $url;
+ }
+
+ if ('' !== ($baseUrl = $this->getFrontController()->getBaseUrl())) {
+ $url = $baseUrl . '/' . $url;
+ }
+
+ if (null !== $params) {
+ $paramPairs = array();
+ foreach ($params as $key => $value) {
+ $paramPairs[] = urlencode($key) . '/' . urlencode($value);
+ }
+ $paramString = implode('/', $paramPairs);
+ $url .= '/' . $paramString;
+ }
+
+ $url = '/' . ltrim($url, '/');
+
+ return $url;
+ }
+
+ /**
+ * Assembles a URL based on a given route
+ *
+ * This method will typically be used for more complex operations, as it
+ * ties into the route objects registered with the router.
+ *
+ * @param array $urlOptions Options passed to the assemble method of the Route object.
+ * @param mixed $name The name of a Route to use. If null it will use the current Route
+ * @param boolean $reset
+ * @param boolean $encode
+ * @return string Url for the link href attribute.
+ */
+ public function url($urlOptions = array(), $name = null, $reset = false, $encode = true)
+ {
+ $router = $this->getFrontController()->getRouter();
+ return $router->assemble($urlOptions, $name, $reset, $encode);
+ }
+
+ /**
+ * Perform helper when called as $this->_helper->url() from an action controller
+ *
+ * Proxies to {@link simple()}
+ *
+ * @param string $action
+ * @param string $controller
+ * @param string $module
+ * @param array $params
+ * @return string
+ */
+ public function direct($action, $controller = null, $module = null, array $params = null)
+ {
+ return $this->simple($action, $controller, $module, $params);
+ }
+}
diff --git a/lib/zend/Zend/Controller/Action/Helper/ViewRenderer.php b/lib/zend/Zend/Controller/Action/Helper/ViewRenderer.php
new file mode 100644
index 00000000000..a66c12a4665
--- /dev/null
+++ b/lib/zend/Zend/Controller/Action/Helper/ViewRenderer.php
@@ -0,0 +1,1004 @@
+
+ * // In your bootstrap:
+ * Zend_Controller_Action_HelperBroker::addHelper(new Zend_Controller_Action_Helper_ViewRenderer());
+ *
+ * // In your action controller methods:
+ * $viewHelper = $this->_helper->getHelper('view');
+ *
+ * // Don't use controller subdirectories
+ * $viewHelper->setNoController(true);
+ *
+ * // Specify a different script to render:
+ * $this->_helper->viewRenderer('form');
+ *
+ *
+ *
+ * @uses Zend_Controller_Action_Helper_Abstract
+ * @package Zend_Controller
+ * @subpackage Zend_Controller_Action_Helper
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Controller_Action_Helper_ViewRenderer extends Zend_Controller_Action_Helper_Abstract
+{
+ /**
+ * @var Zend_View_Interface
+ */
+ public $view;
+
+ /**
+ * Word delimiters
+ * @var array
+ */
+ protected $_delimiters;
+
+ /**
+ * @var Zend_Filter_Inflector
+ */
+ protected $_inflector;
+
+ /**
+ * Inflector target
+ * @var string
+ */
+ protected $_inflectorTarget = '';
+
+ /**
+ * Current module directory
+ * @var string
+ */
+ protected $_moduleDir = '';
+
+ /**
+ * Whether or not to autorender using controller name as subdirectory;
+ * global setting (not reset at next invocation)
+ * @var boolean
+ */
+ protected $_neverController = false;
+
+ /**
+ * Whether or not to autorender postDispatch; global setting (not reset at
+ * next invocation)
+ * @var boolean
+ */
+ protected $_neverRender = false;
+
+ /**
+ * Whether or not to use a controller name as a subdirectory when rendering
+ * @var boolean
+ */
+ protected $_noController = false;
+
+ /**
+ * Whether or not to autorender postDispatch; per controller/action setting (reset
+ * at next invocation)
+ * @var boolean
+ */
+ protected $_noRender = false;
+
+ /**
+ * Characters representing path delimiters in the controller
+ * @var string|array
+ */
+ protected $_pathDelimiters;
+
+ /**
+ * Which named segment of the response to utilize
+ * @var string
+ */
+ protected $_responseSegment = null;
+
+ /**
+ * Which action view script to render
+ * @var string
+ */
+ protected $_scriptAction = null;
+
+ /**
+ * View object basePath
+ * @var string
+ */
+ protected $_viewBasePathSpec = ':moduleDir/views';
+
+ /**
+ * View script path specification string
+ * @var string
+ */
+ protected $_viewScriptPathSpec = ':controller/:action.:suffix';
+
+ /**
+ * View script path specification string, minus controller segment
+ * @var string
+ */
+ protected $_viewScriptPathNoControllerSpec = ':action.:suffix';
+
+ /**
+ * View script suffix
+ * @var string
+ */
+ protected $_viewSuffix = 'phtml';
+
+ /**
+ * Constructor
+ *
+ * Optionally set view object and options.
+ *
+ * @param Zend_View_Interface $view
+ * @param array $options
+ * @return void
+ */
+ public function __construct(Zend_View_Interface $view = null, array $options = array())
+ {
+ if (null !== $view) {
+ $this->setView($view);
+ }
+
+ if (!empty($options)) {
+ $this->_setOptions($options);
+ }
+ }
+
+ /**
+ * Clone - also make sure the view is cloned.
+ *
+ * @return void
+ */
+ public function __clone()
+ {
+ if (isset($this->view) && $this->view instanceof Zend_View_Interface) {
+ $this->view = clone $this->view;
+
+ }
+ }
+
+ /**
+ * Set the view object
+ *
+ * @param Zend_View_Interface $view
+ * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface
+ */
+ public function setView(Zend_View_Interface $view)
+ {
+ $this->view = $view;
+ return $this;
+ }
+
+ /**
+ * Get current module name
+ *
+ * @return string
+ */
+ public function getModule()
+ {
+ $request = $this->getRequest();
+ $module = $request->getModuleName();
+ if (null === $module) {
+ $module = $this->getFrontController()->getDispatcher()->getDefaultModule();
+ }
+
+ return $module;
+ }
+
+ /**
+ * Get module directory
+ *
+ * @throws Zend_Controller_Action_Exception
+ * @return string
+ */
+ public function getModuleDirectory()
+ {
+ $module = $this->getModule();
+ $moduleDir = $this->getFrontController()->getControllerDirectory($module);
+ if ((null === $moduleDir) || is_array($moduleDir)) {
+ /**
+ * @see Zend_Controller_Action_Exception
+ */
+ require_once 'Zend/Controller/Action/Exception.php';
+ throw new Zend_Controller_Action_Exception('ViewRenderer cannot locate module directory for module "' . $module . '"');
+ }
+ $this->_moduleDir = dirname($moduleDir);
+ return $this->_moduleDir;
+ }
+
+ /**
+ * Get inflector
+ *
+ * @return Zend_Filter_Inflector
+ */
+ public function getInflector()
+ {
+ if (null === $this->_inflector) {
+ /**
+ * @see Zend_Filter_Inflector
+ */
+ require_once 'Zend/Filter/Inflector.php';
+ /**
+ * @see Zend_Filter_PregReplace
+ */
+ require_once 'Zend/Filter/PregReplace.php';
+ /**
+ * @see Zend_Filter_Word_UnderscoreToSeparator
+ */
+ require_once 'Zend/Filter/Word/UnderscoreToSeparator.php';
+ $this->_inflector = new Zend_Filter_Inflector();
+ $this->_inflector->setStaticRuleReference('moduleDir', $this->_moduleDir) // moduleDir must be specified before the less specific 'module'
+ ->addRules(array(
+ ':module' => array('Word_CamelCaseToDash', 'StringToLower'),
+ ':controller' => array('Word_CamelCaseToDash', new Zend_Filter_Word_UnderscoreToSeparator('/'), 'StringToLower', new Zend_Filter_PregReplace('/\./', '-')),
+ ':action' => array('Word_CamelCaseToDash', new Zend_Filter_PregReplace('#[^a-z0-9' . preg_quote('/', '#') . ']+#i', '-'), 'StringToLower'),
+ ))
+ ->setStaticRuleReference('suffix', $this->_viewSuffix)
+ ->setTargetReference($this->_inflectorTarget);
+ }
+
+ // Ensure that module directory is current
+ $this->getModuleDirectory();
+
+ return $this->_inflector;
+ }
+
+ /**
+ * Set inflector
+ *
+ * @param Zend_Filter_Inflector $inflector
+ * @param boolean $reference Whether the moduleDir, target, and suffix should be set as references to ViewRenderer properties
+ * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface
+ */
+ public function setInflector(Zend_Filter_Inflector $inflector, $reference = false)
+ {
+ $this->_inflector = $inflector;
+ if ($reference) {
+ $this->_inflector->setStaticRuleReference('suffix', $this->_viewSuffix)
+ ->setStaticRuleReference('moduleDir', $this->_moduleDir)
+ ->setTargetReference($this->_inflectorTarget);
+ }
+ return $this;
+ }
+
+ /**
+ * Set inflector target
+ *
+ * @param string $target
+ * @return void
+ */
+ protected function _setInflectorTarget($target)
+ {
+ $this->_inflectorTarget = (string) $target;
+ }
+
+ /**
+ * Set internal module directory representation
+ *
+ * @param string $dir
+ * @return void
+ */
+ protected function _setModuleDir($dir)
+ {
+ $this->_moduleDir = (string) $dir;
+ }
+
+ /**
+ * Get internal module directory representation
+ *
+ * @return string
+ */
+ protected function _getModuleDir()
+ {
+ return $this->_moduleDir;
+ }
+
+ /**
+ * Generate a class prefix for helper and filter classes
+ *
+ * @return string
+ */
+ protected function _generateDefaultPrefix()
+ {
+ $default = 'Zend_View';
+ if (null === $this->_actionController) {
+ return $default;
+ }
+
+ $class = get_class($this->_actionController);
+
+ if (!strstr($class, '_')) {
+ return $default;
+ }
+
+ $module = $this->getModule();
+ if ('default' == $module) {
+ return $default;
+ }
+
+ $prefix = substr($class, 0, strpos($class, '_')) . '_View';
+
+ return $prefix;
+ }
+
+ /**
+ * Retrieve base path based on location of current action controller
+ *
+ * @return string
+ */
+ protected function _getBasePath()
+ {
+ if (null === $this->_actionController) {
+ return './views';
+ }
+
+ $inflector = $this->getInflector();
+ $this->_setInflectorTarget($this->getViewBasePathSpec());
+
+ $dispatcher = $this->getFrontController()->getDispatcher();
+ $request = $this->getRequest();
+
+ $parts = array(
+ 'module' => (($moduleName = $request->getModuleName()) != '') ? $dispatcher->formatModuleName($moduleName) : $moduleName,
+ 'controller' => $request->getControllerName(),
+ 'action' => $dispatcher->formatActionName($request->getActionName())
+ );
+
+ $path = $inflector->filter($parts);
+ return $path;
+ }
+
+ /**
+ * Set options
+ *
+ * @param array $options
+ * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface
+ */
+ protected function _setOptions(array $options)
+ {
+ foreach ($options as $key => $value)
+ {
+ switch ($key) {
+ case 'neverRender':
+ case 'neverController':
+ case 'noController':
+ case 'noRender':
+ $property = '_' . $key;
+ $this->{$property} = ($value) ? true : false;
+ break;
+ case 'responseSegment':
+ case 'scriptAction':
+ case 'viewBasePathSpec':
+ case 'viewScriptPathSpec':
+ case 'viewScriptPathNoControllerSpec':
+ case 'viewSuffix':
+ $property = '_' . $key;
+ $this->{$property} = (string) $value;
+ break;
+ default:
+ break;
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Initialize the view object
+ *
+ * $options may contain the following keys:
+ * - neverRender - flag dis/enabling postDispatch() autorender (affects all subsequent calls)
+ * - noController - flag indicating whether or not to look for view scripts in subdirectories named after the controller
+ * - noRender - flag indicating whether or not to autorender postDispatch()
+ * - responseSegment - which named response segment to render a view script to
+ * - scriptAction - what action script to render
+ * - viewBasePathSpec - specification to use for determining view base path
+ * - viewScriptPathSpec - specification to use for determining view script paths
+ * - viewScriptPathNoControllerSpec - specification to use for determining view script paths when noController flag is set
+ * - viewSuffix - what view script filename suffix to use
+ *
+ * @param string $path
+ * @param string $prefix
+ * @param array $options
+ * @throws Zend_Controller_Action_Exception
+ * @return void
+ */
+ public function initView($path = null, $prefix = null, array $options = array())
+ {
+ if (null === $this->view) {
+ $this->setView(new Zend_View());
+ }
+
+ // Reset some flags every time
+ $options['noController'] = (isset($options['noController'])) ? $options['noController'] : false;
+ $options['noRender'] = (isset($options['noRender'])) ? $options['noRender'] : false;
+ $this->_scriptAction = null;
+ $this->_responseSegment = null;
+
+ // Set options first; may be used to determine other initializations
+ $this->_setOptions($options);
+
+ // Get base view path
+ if (empty($path)) {
+ $path = $this->_getBasePath();
+ if (empty($path)) {
+ /**
+ * @see Zend_Controller_Action_Exception
+ */
+ require_once 'Zend/Controller/Action/Exception.php';
+ throw new Zend_Controller_Action_Exception('ViewRenderer initialization failed: retrieved view base path is empty');
+ }
+ }
+
+ if (null === $prefix) {
+ $prefix = $this->_generateDefaultPrefix();
+ }
+
+ // Determine if this path has already been registered
+ $currentPaths = $this->view->getScriptPaths();
+ $path = str_replace(array('/', '\\'), '/', $path);
+ $pathExists = false;
+ foreach ($currentPaths as $tmpPath) {
+ $tmpPath = str_replace(array('/', '\\'), '/', $tmpPath);
+ if (strstr($tmpPath, $path)) {
+ $pathExists = true;
+ break;
+ }
+ }
+ if (!$pathExists) {
+ $this->view->addBasePath($path, $prefix);
+ }
+
+ // Register view with action controller (unless already registered)
+ if ((null !== $this->_actionController) && (null === $this->_actionController->view)) {
+ $this->_actionController->view = $this->view;
+ $this->_actionController->viewSuffix = $this->_viewSuffix;
+ }
+ }
+
+ /**
+ * init - initialize view
+ *
+ * @return void
+ */
+ public function init()
+ {
+ if ($this->getFrontController()->getParam('noViewRenderer')) {
+ return;
+ }
+
+ $this->initView();
+ }
+
+ /**
+ * Set view basePath specification
+ *
+ * Specification can contain one or more of the following:
+ * - :moduleDir - current module directory
+ * - :controller - name of current controller in the request
+ * - :action - name of current action in the request
+ * - :module - name of current module in the request
+ *
+ * @param string $path
+ * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface
+ */
+ public function setViewBasePathSpec($path)
+ {
+ $this->_viewBasePathSpec = (string) $path;
+ return $this;
+ }
+
+ /**
+ * Retrieve the current view basePath specification string
+ *
+ * @return string
+ */
+ public function getViewBasePathSpec()
+ {
+ return $this->_viewBasePathSpec;
+ }
+
+ /**
+ * Set view script path specification
+ *
+ * Specification can contain one or more of the following:
+ * - :moduleDir - current module directory
+ * - :controller - name of current controller in the request
+ * - :action - name of current action in the request
+ * - :module - name of current module in the request
+ *
+ * @param string $path
+ * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface
+ */
+ public function setViewScriptPathSpec($path)
+ {
+ $this->_viewScriptPathSpec = (string) $path;
+ return $this;
+ }
+
+ /**
+ * Retrieve the current view script path specification string
+ *
+ * @return string
+ */
+ public function getViewScriptPathSpec()
+ {
+ return $this->_viewScriptPathSpec;
+ }
+
+ /**
+ * Set view script path specification (no controller variant)
+ *
+ * Specification can contain one or more of the following:
+ * - :moduleDir - current module directory
+ * - :controller - name of current controller in the request
+ * - :action - name of current action in the request
+ * - :module - name of current module in the request
+ *
+ * :controller will likely be ignored in this variant.
+ *
+ * @param string $path
+ * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface
+ */
+ public function setViewScriptPathNoControllerSpec($path)
+ {
+ $this->_viewScriptPathNoControllerSpec = (string) $path;
+ return $this;
+ }
+
+ /**
+ * Retrieve the current view script path specification string (no controller variant)
+ *
+ * @return string
+ */
+ public function getViewScriptPathNoControllerSpec()
+ {
+ return $this->_viewScriptPathNoControllerSpec;
+ }
+
+ /**
+ * Get a view script based on an action and/or other variables
+ *
+ * Uses values found in current request if no values passed in $vars.
+ *
+ * If {@link $_noController} is set, uses {@link $_viewScriptPathNoControllerSpec};
+ * otherwise, uses {@link $_viewScriptPathSpec}.
+ *
+ * @param string $action
+ * @param array $vars
+ * @return string
+ */
+ public function getViewScript($action = null, array $vars = array())
+ {
+ $request = $this->getRequest();
+ if ((null === $action) && (!isset($vars['action']))) {
+ $action = $this->getScriptAction();
+ if (null === $action) {
+ $action = $request->getActionName();
+ }
+ $vars['action'] = $action;
+ } elseif (null !== $action) {
+ $vars['action'] = $action;
+ }
+
+ $replacePattern = array('/[^a-z0-9]+$/i', '/^[^a-z0-9]+/i');
+ $vars['action'] = preg_replace($replacePattern, '', $vars['action']);
+
+ $inflector = $this->getInflector();
+ if ($this->getNoController() || $this->getNeverController()) {
+ $this->_setInflectorTarget($this->getViewScriptPathNoControllerSpec());
+ } else {
+ $this->_setInflectorTarget($this->getViewScriptPathSpec());
+ }
+ return $this->_translateSpec($vars);
+ }
+
+ /**
+ * Set the neverRender flag (i.e., globally dis/enable autorendering)
+ *
+ * @param boolean $flag
+ * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface
+ */
+ public function setNeverRender($flag = true)
+ {
+ $this->_neverRender = ($flag) ? true : false;
+ return $this;
+ }
+
+ /**
+ * Retrieve neverRender flag value
+ *
+ * @return boolean
+ */
+ public function getNeverRender()
+ {
+ return $this->_neverRender;
+ }
+
+ /**
+ * Set the noRender flag (i.e., whether or not to autorender)
+ *
+ * @param boolean $flag
+ * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface
+ */
+ public function setNoRender($flag = true)
+ {
+ $this->_noRender = ($flag) ? true : false;
+ return $this;
+ }
+
+ /**
+ * Retrieve noRender flag value
+ *
+ * @return boolean
+ */
+ public function getNoRender()
+ {
+ return $this->_noRender;
+ }
+
+ /**
+ * Set the view script to use
+ *
+ * @param string $name
+ * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface
+ */
+ public function setScriptAction($name)
+ {
+ $this->_scriptAction = (string) $name;
+ return $this;
+ }
+
+ /**
+ * Retrieve view script name
+ *
+ * @return string
+ */
+ public function getScriptAction()
+ {
+ return $this->_scriptAction;
+ }
+
+ /**
+ * Set the response segment name
+ *
+ * @param string $name
+ * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface
+ */
+ public function setResponseSegment($name)
+ {
+ if (null === $name) {
+ $this->_responseSegment = null;
+ } else {
+ $this->_responseSegment = (string) $name;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Retrieve named response segment name
+ *
+ * @return string
+ */
+ public function getResponseSegment()
+ {
+ return $this->_responseSegment;
+ }
+
+ /**
+ * Set the noController flag (i.e., whether or not to render into controller subdirectories)
+ *
+ * @param boolean $flag
+ * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface
+ */
+ public function setNoController($flag = true)
+ {
+ $this->_noController = ($flag) ? true : false;
+ return $this;
+ }
+
+ /**
+ * Retrieve noController flag value
+ *
+ * @return boolean
+ */
+ public function getNoController()
+ {
+ return $this->_noController;
+ }
+
+ /**
+ * Set the neverController flag (i.e., whether or not to render into controller subdirectories)
+ *
+ * @param boolean $flag
+ * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface
+ */
+ public function setNeverController($flag = true)
+ {
+ $this->_neverController = ($flag) ? true : false;
+ return $this;
+ }
+
+ /**
+ * Retrieve neverController flag value
+ *
+ * @return boolean
+ */
+ public function getNeverController()
+ {
+ return $this->_neverController;
+ }
+
+ /**
+ * Set view script suffix
+ *
+ * @param string $suffix
+ * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface
+ */
+ public function setViewSuffix($suffix)
+ {
+ $this->_viewSuffix = (string) $suffix;
+ return $this;
+ }
+
+ /**
+ * Get view script suffix
+ *
+ * @return string
+ */
+ public function getViewSuffix()
+ {
+ return $this->_viewSuffix;
+ }
+
+ /**
+ * Set options for rendering a view script
+ *
+ * @param string $action View script to render
+ * @param string $name Response named segment to render to
+ * @param boolean $noController Whether or not to render within a subdirectory named after the controller
+ * @return Zend_Controller_Action_Helper_ViewRenderer Provides a fluent interface
+ */
+ public function setRender($action = null, $name = null, $noController = null)
+ {
+ if (null !== $action) {
+ $this->setScriptAction($action);
+ }
+
+ if (null !== $name) {
+ $this->setResponseSegment($name);
+ }
+
+ if (null !== $noController) {
+ $this->setNoController($noController);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Inflect based on provided vars
+ *
+ * Allowed variables are:
+ * - :moduleDir - current module directory
+ * - :module - current module name
+ * - :controller - current controller name
+ * - :action - current action name
+ * - :suffix - view script file suffix
+ *
+ * @param array $vars
+ * @return string
+ */
+ protected function _translateSpec(array $vars = array())
+ {
+ $inflector = $this->getInflector();
+ $request = $this->getRequest();
+ $dispatcher = $this->getFrontController()->getDispatcher();
+
+ // Format module name
+ $module = $dispatcher->formatModuleName($request->getModuleName());
+
+ // Format controller name
+ require_once 'Zend/Filter/Word/CamelCaseToDash.php';
+ $filter = new Zend_Filter_Word_CamelCaseToDash();
+ $controller = $filter->filter($request->getControllerName());
+ $controller = $dispatcher->formatControllerName($controller);
+ if ('Controller' == substr($controller, -10)) {
+ $controller = substr($controller, 0, -10);
+ }
+
+ // Format action name
+ $action = $dispatcher->formatActionName($request->getActionName());
+
+ $params = compact('module', 'controller', 'action');
+ foreach ($vars as $key => $value) {
+ switch ($key) {
+ case 'module':
+ case 'controller':
+ case 'action':
+ case 'moduleDir':
+ case 'suffix':
+ $params[$key] = (string) $value;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (isset($params['suffix'])) {
+ $origSuffix = $this->getViewSuffix();
+ $this->setViewSuffix($params['suffix']);
+ }
+ if (isset($params['moduleDir'])) {
+ $origModuleDir = $this->_getModuleDir();
+ $this->_setModuleDir($params['moduleDir']);
+ }
+
+ $filtered = $inflector->filter($params);
+
+ if (isset($params['suffix'])) {
+ $this->setViewSuffix($origSuffix);
+ }
+ if (isset($params['moduleDir'])) {
+ $this->_setModuleDir($origModuleDir);
+ }
+
+ return $filtered;
+ }
+
+ /**
+ * Render a view script (optionally to a named response segment)
+ *
+ * Sets the noRender flag to true when called.
+ *
+ * @param string $script
+ * @param string $name
+ * @return void
+ */
+ public function renderScript($script, $name = null)
+ {
+ if (null === $name) {
+ $name = $this->getResponseSegment();
+ }
+
+ $this->getResponse()->appendBody(
+ $this->view->render($script),
+ $name
+ );
+
+ $this->setNoRender();
+ }
+
+ /**
+ * Render a view based on path specifications
+ *
+ * Renders a view based on the view script path specifications.
+ *
+ * @param string $action
+ * @param string $name
+ * @param boolean $noController
+ * @return void
+ */
+ public function render($action = null, $name = null, $noController = null)
+ {
+ $this->setRender($action, $name, $noController);
+ $path = $this->getViewScript();
+ $this->renderScript($path, $name);
+ }
+
+ /**
+ * Render a script based on specification variables
+ *
+ * Pass an action, and one or more specification variables (view script suffix)
+ * to determine the view script path, and render that script.
+ *
+ * @param string $action
+ * @param array $vars
+ * @param string $name
+ * @return void
+ */
+ public function renderBySpec($action = null, array $vars = array(), $name = null)
+ {
+ if (null !== $name) {
+ $this->setResponseSegment($name);
+ }
+
+ $path = $this->getViewScript($action, $vars);
+
+ $this->renderScript($path);
+ }
+
+ /**
+ * postDispatch - auto render a view
+ *
+ * Only autorenders if:
+ * - _noRender is false
+ * - action controller is present
+ * - request has not been re-dispatched (i.e., _forward() has not been called)
+ * - response is not a redirect
+ *
+ * @return void
+ */
+ public function postDispatch()
+ {
+ if ($this->_shouldRender()) {
+ $this->render();
+ }
+ }
+
+ /**
+ * Should the ViewRenderer render a view script?
+ *
+ * @return boolean
+ */
+ protected function _shouldRender()
+ {
+ return (!$this->getFrontController()->getParam('noViewRenderer')
+ && !$this->_neverRender
+ && !$this->_noRender
+ && (null !== $this->_actionController)
+ && $this->getRequest()->isDispatched()
+ && !$this->getResponse()->isRedirect()
+ );
+ }
+
+ /**
+ * Use this helper as a method; proxies to setRender()
+ *
+ * @param string $action
+ * @param string $name
+ * @param boolean $noController
+ * @return void
+ */
+ public function direct($action = null, $name = null, $noController = null)
+ {
+ $this->setRender($action, $name, $noController);
+ }
+}
diff --git a/lib/zend/Zend/Controller/Action/HelperBroker.php b/lib/zend/Zend/Controller/Action/HelperBroker.php
new file mode 100644
index 00000000000..f911c7035e6
--- /dev/null
+++ b/lib/zend/Zend/Controller/Action/HelperBroker.php
@@ -0,0 +1,381 @@
+ 'Zend/Controller/Action/Helper/',
+ ));
+ }
+ return self::$_pluginLoader;
+ }
+
+ /**
+ * addPrefix() - Add repository of helpers by prefix
+ *
+ * @param string $prefix
+ */
+ static public function addPrefix($prefix)
+ {
+ $prefix = rtrim($prefix, '_');
+ $path = str_replace('_', DIRECTORY_SEPARATOR, $prefix);
+ self::getPluginLoader()->addPrefixPath($prefix, $path);
+ }
+
+ /**
+ * addPath() - Add path to repositories where Action_Helpers could be found.
+ *
+ * @param string $path
+ * @param string $prefix Optional; defaults to 'Zend_Controller_Action_Helper'
+ * @return void
+ */
+ static public function addPath($path, $prefix = 'Zend_Controller_Action_Helper')
+ {
+ self::getPluginLoader()->addPrefixPath($prefix, $path);
+ }
+
+ /**
+ * addHelper() - Add helper objects
+ *
+ * @param Zend_Controller_Action_Helper_Abstract $helper
+ * @return void
+ */
+ static public function addHelper(Zend_Controller_Action_Helper_Abstract $helper)
+ {
+ self::getStack()->push($helper);
+ return;
+ }
+
+ /**
+ * resetHelpers()
+ *
+ * @return void
+ */
+ static public function resetHelpers()
+ {
+ self::$_stack = null;
+ return;
+ }
+
+ /**
+ * Retrieve or initialize a helper statically
+ *
+ * Retrieves a helper object statically, loading on-demand if the helper
+ * does not already exist in the stack. Always returns a helper, unless
+ * the helper class cannot be found.
+ *
+ * @param string $name
+ * @return Zend_Controller_Action_Helper_Abstract
+ */
+ public static function getStaticHelper($name)
+ {
+ $name = self::_normalizeHelperName($name);
+ $stack = self::getStack();
+
+ if (!isset($stack->{$name})) {
+ self::_loadHelper($name);
+ }
+
+ return $stack->{$name};
+ }
+
+ /**
+ * getExistingHelper() - get helper by name
+ *
+ * Static method to retrieve helper object. Only retrieves helpers already
+ * initialized with the broker (either via addHelper() or on-demand loading
+ * via getHelper()).
+ *
+ * Throws an exception if the referenced helper does not exist in the
+ * stack; use {@link hasHelper()} to check if the helper is registered
+ * prior to retrieving it.
+ *
+ * @param string $name
+ * @return Zend_Controller_Action_Helper_Abstract
+ * @throws Zend_Controller_Action_Exception
+ */
+ public static function getExistingHelper($name)
+ {
+ $name = self::_normalizeHelperName($name);
+ $stack = self::getStack();
+
+ if (!isset($stack->{$name})) {
+ require_once 'Zend/Controller/Action/Exception.php';
+ throw new Zend_Controller_Action_Exception('Action helper "' . $name . '" has not been registered with the helper broker');
+ }
+
+ return $stack->{$name};
+ }
+
+ /**
+ * Return all registered helpers as helper => object pairs
+ *
+ * @return array
+ */
+ public static function getExistingHelpers()
+ {
+ return self::getStack()->getHelpersByName();
+ }
+
+ /**
+ * Is a particular helper loaded in the broker?
+ *
+ * @param string $name
+ * @return boolean
+ */
+ public static function hasHelper($name)
+ {
+ $name = self::_normalizeHelperName($name);
+ return isset(self::getStack()->{$name});
+ }
+
+ /**
+ * Remove a particular helper from the broker
+ *
+ * @param string $name
+ * @return boolean
+ */
+ public static function removeHelper($name)
+ {
+ $name = self::_normalizeHelperName($name);
+ $stack = self::getStack();
+ if (isset($stack->{$name})) {
+ unset($stack->{$name});
+ }
+
+ return false;
+ }
+
+ /**
+ * Lazy load the priority stack and return it
+ *
+ * @return Zend_Controller_Action_HelperBroker_PriorityStack
+ */
+ public static function getStack()
+ {
+ if (self::$_stack == null) {
+ self::$_stack = new Zend_Controller_Action_HelperBroker_PriorityStack();
+ }
+
+ return self::$_stack;
+ }
+
+ /**
+ * Constructor
+ *
+ * @param Zend_Controller_Action $actionController
+ * @return void
+ */
+ public function __construct(Zend_Controller_Action $actionController)
+ {
+ $this->_actionController = $actionController;
+ foreach (self::getStack() as $helper) {
+ $helper->setActionController($actionController);
+ $helper->init();
+ }
+ }
+
+ /**
+ * notifyPreDispatch() - called by action controller dispatch method
+ *
+ * @return void
+ */
+ public function notifyPreDispatch()
+ {
+ foreach (self::getStack() as $helper) {
+ $helper->preDispatch();
+ }
+ }
+
+ /**
+ * notifyPostDispatch() - called by action controller dispatch method
+ *
+ * @return void
+ */
+ public function notifyPostDispatch()
+ {
+ foreach (self::getStack() as $helper) {
+ $helper->postDispatch();
+ }
+ }
+
+ /**
+ * getHelper() - get helper by name
+ *
+ * @param string $name
+ * @return Zend_Controller_Action_Helper_Abstract
+ */
+ public function getHelper($name)
+ {
+ $name = self::_normalizeHelperName($name);
+ $stack = self::getStack();
+
+ if (!isset($stack->{$name})) {
+ self::_loadHelper($name);
+ }
+
+ $helper = $stack->{$name};
+
+ $initialize = false;
+ if (null === ($actionController = $helper->getActionController())) {
+ $initialize = true;
+ } elseif ($actionController !== $this->_actionController) {
+ $initialize = true;
+ }
+
+ if ($initialize) {
+ $helper->setActionController($this->_actionController)
+ ->init();
+ }
+
+ return $helper;
+ }
+
+ /**
+ * Method overloading
+ *
+ * @param string $method
+ * @param array $args
+ * @return mixed
+ * @throws Zend_Controller_Action_Exception if helper does not have a direct() method
+ */
+ public function __call($method, $args)
+ {
+ $helper = $this->getHelper($method);
+ if (!method_exists($helper, 'direct')) {
+ require_once 'Zend/Controller/Action/Exception.php';
+ throw new Zend_Controller_Action_Exception('Helper "' . $method . '" does not support overloading via direct()');
+ }
+ return call_user_func_array(array($helper, 'direct'), $args);
+ }
+
+ /**
+ * Retrieve helper by name as object property
+ *
+ * @param string $name
+ * @return Zend_Controller_Action_Helper_Abstract
+ */
+ public function __get($name)
+ {
+ return $this->getHelper($name);
+ }
+
+ /**
+ * Normalize helper name for lookups
+ *
+ * @param string $name
+ * @return string
+ */
+ protected static function _normalizeHelperName($name)
+ {
+ if (strpos($name, '_') !== false) {
+ $name = str_replace(' ', '', ucwords(str_replace('_', ' ', $name)));
+ }
+
+ return ucfirst($name);
+ }
+
+ /**
+ * Load a helper
+ *
+ * @param string $name
+ * @return void
+ */
+ protected static function _loadHelper($name)
+ {
+ try {
+ $class = self::getPluginLoader()->load($name);
+ } catch (Zend_Loader_PluginLoader_Exception $e) {
+ require_once 'Zend/Controller/Action/Exception.php';
+ throw new Zend_Controller_Action_Exception('Action Helper by name ' . $name . ' not found', 0, $e);
+ }
+
+ $helper = new $class();
+
+ if (!$helper instanceof Zend_Controller_Action_Helper_Abstract) {
+ require_once 'Zend/Controller/Action/Exception.php';
+ throw new Zend_Controller_Action_Exception('Helper name ' . $name . ' -> class ' . $class . ' is not of type Zend_Controller_Action_Helper_Abstract');
+ }
+
+ self::getStack()->push($helper);
+ }
+}
diff --git a/lib/zend/Zend/Controller/Action/HelperBroker/PriorityStack.php b/lib/zend/Zend/Controller/Action/HelperBroker/PriorityStack.php
new file mode 100644
index 00000000000..d510b74ee58
--- /dev/null
+++ b/lib/zend/Zend/Controller/Action/HelperBroker/PriorityStack.php
@@ -0,0 +1,280 @@
+_helpersByNameRef)) {
+ return false;
+ }
+
+ return $this->_helpersByNameRef[$helperName];
+ }
+
+ /**
+ * Magic property overloading for returning if helper is set by name
+ *
+ * @param string $helperName The helper name
+ * @return Zend_Controller_Action_Helper_Abstract
+ */
+ public function __isset($helperName)
+ {
+ return array_key_exists($helperName, $this->_helpersByNameRef);
+ }
+
+ /**
+ * Magic property overloading for unsetting if helper is exists by name
+ *
+ * @param string $helperName The helper name
+ * @return Zend_Controller_Action_Helper_Abstract
+ */
+ public function __unset($helperName)
+ {
+ return $this->offsetUnset($helperName);
+ }
+
+ /**
+ * push helper onto the stack
+ *
+ * @param Zend_Controller_Action_Helper_Abstract $helper
+ * @return Zend_Controller_Action_HelperBroker_PriorityStack
+ */
+ public function push(Zend_Controller_Action_Helper_Abstract $helper)
+ {
+ $this->offsetSet($this->getNextFreeHigherPriority(), $helper);
+ return $this;
+ }
+
+ /**
+ * Return something iterable
+ *
+ * @return array
+ */
+ public function getIterator()
+ {
+ return new ArrayObject($this->_helpersByPriority);
+ }
+
+ /**
+ * offsetExists()
+ *
+ * @param int|string $priorityOrHelperName
+ * @return Zend_Controller_Action_HelperBroker_PriorityStack
+ */
+ public function offsetExists($priorityOrHelperName)
+ {
+ if (is_string($priorityOrHelperName)) {
+ return array_key_exists($priorityOrHelperName, $this->_helpersByNameRef);
+ } else {
+ return array_key_exists($priorityOrHelperName, $this->_helpersByPriority);
+ }
+ }
+
+ /**
+ * offsetGet()
+ *
+ * @param int|string $priorityOrHelperName
+ * @return Zend_Controller_Action_HelperBroker_PriorityStack
+ */
+ public function offsetGet($priorityOrHelperName)
+ {
+ if (!$this->offsetExists($priorityOrHelperName)) {
+ require_once 'Zend/Controller/Action/Exception.php';
+ throw new Zend_Controller_Action_Exception('A helper with priority ' . $priorityOrHelperName . ' does not exist.');
+ }
+
+ if (is_string($priorityOrHelperName)) {
+ return $this->_helpersByNameRef[$priorityOrHelperName];
+ } else {
+ return $this->_helpersByPriority[$priorityOrHelperName];
+ }
+ }
+
+ /**
+ * offsetSet()
+ *
+ * @param int $priority
+ * @param Zend_Controller_Action_Helper_Abstract $helper
+ * @return Zend_Controller_Action_HelperBroker_PriorityStack
+ */
+ public function offsetSet($priority, $helper)
+ {
+ $priority = (int) $priority;
+
+ if (!$helper instanceof Zend_Controller_Action_Helper_Abstract) {
+ require_once 'Zend/Controller/Action/Exception.php';
+ throw new Zend_Controller_Action_Exception('$helper must extend Zend_Controller_Action_Helper_Abstract.');
+ }
+
+ if (array_key_exists($helper->getName(), $this->_helpersByNameRef)) {
+ // remove any object with the same name to retain BC compailitbility
+ // @todo At ZF 2.0 time throw an exception here.
+ $this->offsetUnset($helper->getName());
+ }
+
+ if (array_key_exists($priority, $this->_helpersByPriority)) {
+ $priority = $this->getNextFreeHigherPriority($priority); // ensures LIFO
+ trigger_error("A helper with the same priority already exists, reassigning to $priority", E_USER_WARNING);
+ }
+
+ $this->_helpersByPriority[$priority] = $helper;
+ $this->_helpersByNameRef[$helper->getName()] = $helper;
+
+ if ($priority == ($nextFreeDefault = $this->getNextFreeHigherPriority($this->_nextDefaultPriority))) {
+ $this->_nextDefaultPriority = $nextFreeDefault;
+ }
+
+ krsort($this->_helpersByPriority); // always make sure priority and LIFO are both enforced
+ return $this;
+ }
+
+ /**
+ * offsetUnset()
+ *
+ * @param int|string $priorityOrHelperName Priority integer or the helper name
+ * @return Zend_Controller_Action_HelperBroker_PriorityStack
+ */
+ public function offsetUnset($priorityOrHelperName)
+ {
+ if (!$this->offsetExists($priorityOrHelperName)) {
+ require_once 'Zend/Controller/Action/Exception.php';
+ throw new Zend_Controller_Action_Exception('A helper with priority or name ' . $priorityOrHelperName . ' does not exist.');
+ }
+
+ if (is_string($priorityOrHelperName)) {
+ $helperName = $priorityOrHelperName;
+ $helper = $this->_helpersByNameRef[$helperName];
+ $priority = array_search($helper, $this->_helpersByPriority, true);
+ } else {
+ $priority = $priorityOrHelperName;
+ $helperName = $this->_helpersByPriority[$priorityOrHelperName]->getName();
+ }
+
+ unset($this->_helpersByNameRef[$helperName]);
+ unset($this->_helpersByPriority[$priority]);
+ return $this;
+ }
+
+ /**
+ * return the count of helpers
+ *
+ * @return int
+ */
+ public function count()
+ {
+ return count($this->_helpersByPriority);
+ }
+
+ /**
+ * Find the next free higher priority. If an index is given, it will
+ * find the next free highest priority after it.
+ *
+ * @param int $indexPriority OPTIONAL
+ * @return int
+ */
+ public function getNextFreeHigherPriority($indexPriority = null)
+ {
+ if ($indexPriority == null) {
+ $indexPriority = $this->_nextDefaultPriority;
+ }
+
+ $priorities = array_keys($this->_helpersByPriority);
+
+ while (in_array($indexPriority, $priorities)) {
+ $indexPriority++;
+ }
+
+ return $indexPriority;
+ }
+
+ /**
+ * Find the next free lower priority. If an index is given, it will
+ * find the next free lower priority before it.
+ *
+ * @param int $indexPriority
+ * @return int
+ */
+ public function getNextFreeLowerPriority($indexPriority = null)
+ {
+ if ($indexPriority == null) {
+ $indexPriority = $this->_nextDefaultPriority;
+ }
+
+ $priorities = array_keys($this->_helpersByPriority);
+
+ while (in_array($indexPriority, $priorities)) {
+ $indexPriority--;
+ }
+
+ return $indexPriority;
+ }
+
+ /**
+ * return the highest priority
+ *
+ * @return int
+ */
+ public function getHighestPriority()
+ {
+ return max(array_keys($this->_helpersByPriority));
+ }
+
+ /**
+ * return the lowest priority
+ *
+ * @return int
+ */
+ public function getLowestPriority()
+ {
+ return min(array_keys($this->_helpersByPriority));
+ }
+
+ /**
+ * return the helpers referenced by name
+ *
+ * @return array
+ */
+ public function getHelpersByName()
+ {
+ return $this->_helpersByNameRef;
+ }
+
+}
diff --git a/lib/zend/Zend/Controller/Action/Interface.php b/lib/zend/Zend/Controller/Action/Interface.php
new file mode 100644
index 00000000000..db354637a10
--- /dev/null
+++ b/lib/zend/Zend/Controller/Action/Interface.php
@@ -0,0 +1,69 @@
+setParams($params);
+ }
+
+ /**
+ * Formats a string into a controller name. This is used to take a raw
+ * controller name, such as one stored inside a Zend_Controller_Request_Abstract
+ * object, and reformat it to a proper class name that a class extending
+ * Zend_Controller_Action would use.
+ *
+ * @param string $unformatted
+ * @return string
+ */
+ public function formatControllerName($unformatted)
+ {
+ return ucfirst($this->_formatName($unformatted)) . 'Controller';
+ }
+
+ /**
+ * Formats a string into an action name. This is used to take a raw
+ * action name, such as one that would be stored inside a Zend_Controller_Request_Abstract
+ * object, and reformat into a proper method name that would be found
+ * inside a class extending Zend_Controller_Action.
+ *
+ * @param string $unformatted
+ * @return string
+ */
+ public function formatActionName($unformatted)
+ {
+ $formatted = $this->_formatName($unformatted, true);
+ return strtolower(substr($formatted, 0, 1)) . substr($formatted, 1) . 'Action';
+ }
+
+ /**
+ * Verify delimiter
+ *
+ * Verify a delimiter to use in controllers or actions. May be a single
+ * string or an array of strings.
+ *
+ * @param string|array $spec
+ * @return array
+ * @throws Zend_Controller_Dispatcher_Exception with invalid delimiters
+ */
+ public function _verifyDelimiter($spec)
+ {
+ if (is_string($spec)) {
+ return (array) $spec;
+ } elseif (is_array($spec)) {
+ $allStrings = true;
+ foreach ($spec as $delim) {
+ if (!is_string($delim)) {
+ $allStrings = false;
+ break;
+ }
+ }
+
+ if (!$allStrings) {
+ require_once 'Zend/Controller/Dispatcher/Exception.php';
+ throw new Zend_Controller_Dispatcher_Exception('Word delimiter array must contain only strings');
+ }
+
+ return $spec;
+ }
+
+ require_once 'Zend/Controller/Dispatcher/Exception.php';
+ throw new Zend_Controller_Dispatcher_Exception('Invalid word delimiter');
+ }
+
+ /**
+ * Retrieve the word delimiter character(s) used in
+ * controller or action names
+ *
+ * @return array
+ */
+ public function getWordDelimiter()
+ {
+ return $this->_wordDelimiter;
+ }
+
+ /**
+ * Set word delimiter
+ *
+ * Set the word delimiter to use in controllers and actions. May be a
+ * single string or an array of strings.
+ *
+ * @param string|array $spec
+ * @return Zend_Controller_Dispatcher_Abstract
+ */
+ public function setWordDelimiter($spec)
+ {
+ $spec = $this->_verifyDelimiter($spec);
+ $this->_wordDelimiter = $spec;
+
+ return $this;
+ }
+
+ /**
+ * Retrieve the path delimiter character(s) used in
+ * controller names
+ *
+ * @return array
+ */
+ public function getPathDelimiter()
+ {
+ return $this->_pathDelimiter;
+ }
+
+ /**
+ * Set path delimiter
+ *
+ * Set the path delimiter to use in controllers. May be a single string or
+ * an array of strings.
+ *
+ * @param string $spec
+ * @return Zend_Controller_Dispatcher_Abstract
+ */
+ public function setPathDelimiter($spec)
+ {
+ if (!is_string($spec)) {
+ require_once 'Zend/Controller/Dispatcher/Exception.php';
+ throw new Zend_Controller_Dispatcher_Exception('Invalid path delimiter');
+ }
+ $this->_pathDelimiter = $spec;
+
+ return $this;
+ }
+
+ /**
+ * Formats a string from a URI into a PHP-friendly name.
+ *
+ * By default, replaces words separated by the word separator character(s)
+ * with camelCaps. If $isAction is false, it also preserves replaces words
+ * separated by the path separation character with an underscore, making
+ * the following word Title cased. All non-alphanumeric characters are
+ * removed.
+ *
+ * @param string $unformatted
+ * @param boolean $isAction Defaults to false
+ * @return string
+ */
+ protected function _formatName($unformatted, $isAction = false)
+ {
+ // preserve directories
+ if (!$isAction) {
+ $segments = explode($this->getPathDelimiter(), $unformatted);
+ } else {
+ $segments = (array) $unformatted;
+ }
+
+ foreach ($segments as $key => $segment) {
+ $segment = str_replace($this->getWordDelimiter(), ' ', strtolower($segment));
+ $segment = preg_replace('/[^a-z0-9 ]/', '', $segment);
+ $segments[$key] = str_replace(' ', '', ucwords($segment));
+ }
+
+ return implode('_', $segments);
+ }
+
+ /**
+ * Retrieve front controller instance
+ *
+ * @return Zend_Controller_Front
+ */
+ public function getFrontController()
+ {
+ if (null === $this->_frontController) {
+ require_once 'Zend/Controller/Front.php';
+ $this->_frontController = Zend_Controller_Front::getInstance();
+ }
+
+ return $this->_frontController;
+ }
+
+ /**
+ * Set front controller instance
+ *
+ * @param Zend_Controller_Front $controller
+ * @return Zend_Controller_Dispatcher_Abstract
+ */
+ public function setFrontController(Zend_Controller_Front $controller)
+ {
+ $this->_frontController = $controller;
+ return $this;
+ }
+
+ /**
+ * Add or modify a parameter to use when instantiating an action controller
+ *
+ * @param string $name
+ * @param mixed $value
+ * @return Zend_Controller_Dispatcher_Abstract
+ */
+ public function setParam($name, $value)
+ {
+ $name = (string) $name;
+ $this->_invokeParams[$name] = $value;
+ return $this;
+ }
+
+ /**
+ * Set parameters to pass to action controller constructors
+ *
+ * @param array $params
+ * @return Zend_Controller_Dispatcher_Abstract
+ */
+ public function setParams(array $params)
+ {
+ $this->_invokeParams = array_merge($this->_invokeParams, $params);
+ return $this;
+ }
+
+ /**
+ * Retrieve a single parameter from the controller parameter stack
+ *
+ * @param string $name
+ * @return mixed
+ */
+ public function getParam($name)
+ {
+ if(isset($this->_invokeParams[$name])) {
+ return $this->_invokeParams[$name];
+ }
+
+ return null;
+ }
+
+ /**
+ * Retrieve action controller instantiation parameters
+ *
+ * @return array
+ */
+ public function getParams()
+ {
+ return $this->_invokeParams;
+ }
+
+ /**
+ * Clear the controller parameter stack
+ *
+ * By default, clears all parameters. If a parameter name is given, clears
+ * only that parameter; if an array of parameter names is provided, clears
+ * each.
+ *
+ * @param null|string|array single key or array of keys for params to clear
+ * @return Zend_Controller_Dispatcher_Abstract
+ */
+ public function clearParams($name = null)
+ {
+ if (null === $name) {
+ $this->_invokeParams = array();
+ } elseif (is_string($name) && isset($this->_invokeParams[$name])) {
+ unset($this->_invokeParams[$name]);
+ } elseif (is_array($name)) {
+ foreach ($name as $key) {
+ if (is_string($key) && isset($this->_invokeParams[$key])) {
+ unset($this->_invokeParams[$key]);
+ }
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Set response object to pass to action controllers
+ *
+ * @param Zend_Controller_Response_Abstract|null $response
+ * @return Zend_Controller_Dispatcher_Abstract
+ */
+ public function setResponse(Zend_Controller_Response_Abstract $response = null)
+ {
+ $this->_response = $response;
+ return $this;
+ }
+
+ /**
+ * Return the registered response object
+ *
+ * @return Zend_Controller_Response_Abstract|null
+ */
+ public function getResponse()
+ {
+ return $this->_response;
+ }
+
+ /**
+ * Set the default controller (minus any formatting)
+ *
+ * @param string $controller
+ * @return Zend_Controller_Dispatcher_Abstract
+ */
+ public function setDefaultControllerName($controller)
+ {
+ $this->_defaultController = (string) $controller;
+ return $this;
+ }
+
+ /**
+ * Retrieve the default controller name (minus formatting)
+ *
+ * @return string
+ */
+ public function getDefaultControllerName()
+ {
+ return $this->_defaultController;
+ }
+
+ /**
+ * Set the default action (minus any formatting)
+ *
+ * @param string $action
+ * @return Zend_Controller_Dispatcher_Abstract
+ */
+ public function setDefaultAction($action)
+ {
+ $this->_defaultAction = (string) $action;
+ return $this;
+ }
+
+ /**
+ * Retrieve the default action name (minus formatting)
+ *
+ * @return string
+ */
+ public function getDefaultAction()
+ {
+ return $this->_defaultAction;
+ }
+
+ /**
+ * Set the default module
+ *
+ * @param string $module
+ * @return Zend_Controller_Dispatcher_Abstract
+ */
+ public function setDefaultModule($module)
+ {
+ $this->_defaultModule = (string) $module;
+ return $this;
+ }
+
+ /**
+ * Retrieve the default module
+ *
+ * @return string
+ */
+ public function getDefaultModule()
+ {
+ return $this->_defaultModule;
+ }
+}
diff --git a/lib/zend/Zend/Controller/Dispatcher/Exception.php b/lib/zend/Zend/Controller/Dispatcher/Exception.php
new file mode 100644
index 00000000000..42404449663
--- /dev/null
+++ b/lib/zend/Zend/Controller/Dispatcher/Exception.php
@@ -0,0 +1,37 @@
+_curModule = $this->getDefaultModule();
+ }
+
+ /**
+ * Add a single path to the controller directory stack
+ *
+ * @param string $path
+ * @param string $module
+ * @return Zend_Controller_Dispatcher_Standard
+ */
+ public function addControllerDirectory($path, $module = null)
+ {
+ if (null === $module) {
+ $module = $this->_defaultModule;
+ }
+
+ $module = (string) $module;
+ $path = rtrim((string) $path, '/\\');
+
+ $this->_controllerDirectory[$module] = $path;
+ return $this;
+ }
+
+ /**
+ * Set controller directory
+ *
+ * @param array|string $directory
+ * @return Zend_Controller_Dispatcher_Standard
+ */
+ public function setControllerDirectory($directory, $module = null)
+ {
+ $this->_controllerDirectory = array();
+
+ if (is_string($directory)) {
+ $this->addControllerDirectory($directory, $module);
+ } elseif (is_array($directory)) {
+ foreach ((array) $directory as $module => $path) {
+ $this->addControllerDirectory($path, $module);
+ }
+ } else {
+ require_once 'Zend/Controller/Exception.php';
+ throw new Zend_Controller_Exception('Controller directory spec must be either a string or an array');
+ }
+
+ return $this;
+ }
+
+ /**
+ * Return the currently set directories for Zend_Controller_Action class
+ * lookup
+ *
+ * If a module is specified, returns just that directory.
+ *
+ * @param string $module Module name
+ * @return array|string Returns array of all directories by default, single
+ * module directory if module argument provided
+ */
+ public function getControllerDirectory($module = null)
+ {
+ if (null === $module) {
+ return $this->_controllerDirectory;
+ }
+
+ $module = (string) $module;
+ if (array_key_exists($module, $this->_controllerDirectory)) {
+ return $this->_controllerDirectory[$module];
+ }
+
+ return null;
+ }
+
+ /**
+ * Remove a controller directory by module name
+ *
+ * @param string $module
+ * @return bool
+ */
+ public function removeControllerDirectory($module)
+ {
+ $module = (string) $module;
+ if (array_key_exists($module, $this->_controllerDirectory)) {
+ unset($this->_controllerDirectory[$module]);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Format the module name.
+ *
+ * @param string $unformatted
+ * @return string
+ */
+ public function formatModuleName($unformatted)
+ {
+ if (($this->_defaultModule == $unformatted) && !$this->getParam('prefixDefaultModule')) {
+ return $unformatted;
+ }
+
+ return ucfirst($this->_formatName($unformatted));
+ }
+
+ /**
+ * Format action class name
+ *
+ * @param string $moduleName Name of the current module
+ * @param string $className Name of the action class
+ * @return string Formatted class name
+ */
+ public function formatClassName($moduleName, $className)
+ {
+ return $this->formatModuleName($moduleName) . '_' . $className;
+ }
+
+ /**
+ * Convert a class name to a filename
+ *
+ * @param string $class
+ * @return string
+ */
+ public function classToFilename($class)
+ {
+ return str_replace('_', DIRECTORY_SEPARATOR, $class) . '.php';
+ }
+
+ /**
+ * Returns TRUE if the Zend_Controller_Request_Abstract object can be
+ * dispatched to a controller.
+ *
+ * Use this method wisely. By default, the dispatcher will fall back to the
+ * default controller (either in the module specified or the global default)
+ * if a given controller does not exist. This method returning false does
+ * not necessarily indicate the dispatcher will not still dispatch the call.
+ *
+ * @param Zend_Controller_Request_Abstract $action
+ * @return boolean
+ */
+ public function isDispatchable(Zend_Controller_Request_Abstract $request)
+ {
+ $className = $this->getControllerClass($request);
+ if (!$className) {
+ return false;
+ }
+
+ $finalClass = $className;
+ if (($this->_defaultModule != $this->_curModule)
+ || $this->getParam('prefixDefaultModule'))
+ {
+ $finalClass = $this->formatClassName($this->_curModule, $className);
+ }
+ if (class_exists($finalClass, false)) {
+ return true;
+ }
+
+ $fileSpec = $this->classToFilename($className);
+ $dispatchDir = $this->getDispatchDirectory();
+ $test = $dispatchDir . DIRECTORY_SEPARATOR . $fileSpec;
+ return Zend_Loader::isReadable($test);
+ }
+
+ /**
+ * Dispatch to a controller/action
+ *
+ * By default, if a controller is not dispatchable, dispatch() will throw
+ * an exception. If you wish to use the default controller instead, set the
+ * param 'useDefaultControllerAlways' via {@link setParam()}.
+ *
+ * @param Zend_Controller_Request_Abstract $request
+ * @param Zend_Controller_Response_Abstract $response
+ * @return void
+ * @throws Zend_Controller_Dispatcher_Exception
+ */
+ public function dispatch(Zend_Controller_Request_Abstract $request, Zend_Controller_Response_Abstract $response)
+ {
+ $this->setResponse($response);
+
+ /**
+ * Get controller class
+ */
+ if (!$this->isDispatchable($request)) {
+ $controller = $request->getControllerName();
+ if (!$this->getParam('useDefaultControllerAlways') && !empty($controller)) {
+ require_once 'Zend/Controller/Dispatcher/Exception.php';
+ throw new Zend_Controller_Dispatcher_Exception('Invalid controller specified (' . $request->getControllerName() . ')');
+ }
+
+ $className = $this->getDefaultControllerClass($request);
+ } else {
+ $className = $this->getControllerClass($request);
+ if (!$className) {
+ $className = $this->getDefaultControllerClass($request);
+ }
+ }
+
+ /**
+ * If we're in a module or prefixDefaultModule is on, we must add the module name
+ * prefix to the contents of $className, as getControllerClass does not do that automatically.
+ * We must keep a separate variable because modules are not strictly PSR-0: We need the no-module-prefix
+ * class name to do the class->file mapping, but the full class name to insantiate the controller
+ */
+ $moduleClassName = $className;
+ if (($this->_defaultModule != $this->_curModule)
+ || $this->getParam('prefixDefaultModule'))
+ {
+ $moduleClassName = $this->formatClassName($this->_curModule, $className);
+ }
+
+ /**
+ * Load the controller class file
+ */
+ $className = $this->loadClass($className);
+
+ /**
+ * Instantiate controller with request, response, and invocation
+ * arguments; throw exception if it's not an action controller
+ */
+ $controller = new $moduleClassName($request, $this->getResponse(), $this->getParams());
+ if (!($controller instanceof Zend_Controller_Action_Interface) &&
+ !($controller instanceof Zend_Controller_Action)) {
+ require_once 'Zend/Controller/Dispatcher/Exception.php';
+ throw new Zend_Controller_Dispatcher_Exception(
+ 'Controller "' . $moduleClassName . '" is not an instance of Zend_Controller_Action_Interface'
+ );
+ }
+
+ /**
+ * Retrieve the action name
+ */
+ $action = $this->getActionMethod($request);
+
+ /**
+ * Dispatch the method call
+ */
+ $request->setDispatched(true);
+
+ // by default, buffer output
+ $disableOb = $this->getParam('disableOutputBuffering');
+ $obLevel = ob_get_level();
+ if (empty($disableOb)) {
+ ob_start();
+ }
+
+ try {
+ $controller->dispatch($action);
+ } catch (Exception $e) {
+ // Clean output buffer on error
+ $curObLevel = ob_get_level();
+ if ($curObLevel > $obLevel) {
+ do {
+ ob_get_clean();
+ $curObLevel = ob_get_level();
+ } while ($curObLevel > $obLevel);
+ }
+ throw $e;
+ }
+
+ if (empty($disableOb)) {
+ $content = ob_get_clean();
+ $response->appendBody($content);
+ }
+
+ // Destroy the page controller instance and reflection objects
+ $controller = null;
+ }
+
+ /**
+ * Load a controller class
+ *
+ * Attempts to load the controller class file from
+ * {@link getControllerDirectory()}. If the controller belongs to a
+ * module, looks for the module prefix to the controller class.
+ *
+ * @param string $className
+ * @return string Class name loaded
+ * @throws Zend_Controller_Dispatcher_Exception if class not loaded
+ */
+ public function loadClass($className)
+ {
+ $finalClass = $className;
+ if (($this->_defaultModule != $this->_curModule)
+ || $this->getParam('prefixDefaultModule'))
+ {
+ $finalClass = $this->formatClassName($this->_curModule, $className);
+ }
+ if (class_exists($finalClass, false)) {
+ return $finalClass;
+ }
+
+ $dispatchDir = $this->getDispatchDirectory();
+ $loadFile = $dispatchDir . DIRECTORY_SEPARATOR . $this->classToFilename($className);
+
+ if (Zend_Loader::isReadable($loadFile)) {
+ include_once $loadFile;
+ } else {
+ require_once 'Zend/Controller/Dispatcher/Exception.php';
+ throw new Zend_Controller_Dispatcher_Exception('Cannot load controller class "' . $className . '" from file "' . $loadFile . "'");
+ }
+
+ if (!class_exists($finalClass, false)) {
+ require_once 'Zend/Controller/Dispatcher/Exception.php';
+ throw new Zend_Controller_Dispatcher_Exception('Invalid controller class ("' . $finalClass . '")');
+ }
+
+ return $finalClass;
+ }
+
+ /**
+ * Get controller class name
+ *
+ * Try request first; if not found, try pulling from request parameter;
+ * if still not found, fallback to default
+ *
+ * @param Zend_Controller_Request_Abstract $request
+ * @return string|false Returns class name on success
+ */
+ public function getControllerClass(Zend_Controller_Request_Abstract $request)
+ {
+ $controllerName = $request->getControllerName();
+ if (empty($controllerName)) {
+ if (!$this->getParam('useDefaultControllerAlways')) {
+ return false;
+ }
+ $controllerName = $this->getDefaultControllerName();
+ $request->setControllerName($controllerName);
+ }
+
+ $className = $this->formatControllerName($controllerName);
+
+ $controllerDirs = $this->getControllerDirectory();
+ $module = $request->getModuleName();
+ if ($this->isValidModule($module)) {
+ $this->_curModule = $module;
+ $this->_curDirectory = $controllerDirs[$module];
+ } elseif ($this->isValidModule($this->_defaultModule)) {
+ $request->setModuleName($this->_defaultModule);
+ $this->_curModule = $this->_defaultModule;
+ $this->_curDirectory = $controllerDirs[$this->_defaultModule];
+ } else {
+ require_once 'Zend/Controller/Exception.php';
+ throw new Zend_Controller_Exception('No default module defined for this application');
+ }
+
+ return $className;
+ }
+
+ /**
+ * Determine if a given module is valid
+ *
+ * @param string $module
+ * @return bool
+ */
+ public function isValidModule($module)
+ {
+ if (!is_string($module)) {
+ return false;
+ }
+
+ $module = strtolower($module);
+ $controllerDir = $this->getControllerDirectory();
+ foreach (array_keys($controllerDir) as $moduleName) {
+ if ($module == strtolower($moduleName)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Retrieve default controller class
+ *
+ * Determines whether the default controller to use lies within the
+ * requested module, or if the global default should be used.
+ *
+ * By default, will only use the module default unless that controller does
+ * not exist; if this is the case, it falls back to the default controller
+ * in the default module.
+ *
+ * @param Zend_Controller_Request_Abstract $request
+ * @return string
+ */
+ public function getDefaultControllerClass(Zend_Controller_Request_Abstract $request)
+ {
+ $controller = $this->getDefaultControllerName();
+ $default = $this->formatControllerName($controller);
+ $request->setControllerName($controller)
+ ->setActionName(null);
+
+ $module = $request->getModuleName();
+ $controllerDirs = $this->getControllerDirectory();
+ $this->_curModule = $this->_defaultModule;
+ $this->_curDirectory = $controllerDirs[$this->_defaultModule];
+ if ($this->isValidModule($module)) {
+ $found = false;
+ if (class_exists($default, false)) {
+ $found = true;
+ } else {
+ $moduleDir = $controllerDirs[$module];
+ $fileSpec = $moduleDir . DIRECTORY_SEPARATOR . $this->classToFilename($default);
+ if (Zend_Loader::isReadable($fileSpec)) {
+ $found = true;
+ $this->_curDirectory = $moduleDir;
+ }
+ }
+ if ($found) {
+ $request->setModuleName($module);
+ $this->_curModule = $this->formatModuleName($module);
+ }
+ } else {
+ $request->setModuleName($this->_defaultModule);
+ }
+
+ return $default;
+ }
+
+ /**
+ * Return the value of the currently selected dispatch directory (as set by
+ * {@link getController()})
+ *
+ * @return string
+ */
+ public function getDispatchDirectory()
+ {
+ return $this->_curDirectory;
+ }
+
+ /**
+ * Determine the action name
+ *
+ * First attempt to retrieve from request; then from request params
+ * using action key; default to default action
+ *
+ * Returns formatted action name
+ *
+ * @param Zend_Controller_Request_Abstract $request
+ * @return string
+ */
+ public function getActionMethod(Zend_Controller_Request_Abstract $request)
+ {
+ $action = $request->getActionName();
+ if (empty($action)) {
+ $action = $this->getDefaultAction();
+ $request->setActionName($action);
+ }
+
+ return $this->formatActionName($action);
+ }
+}
diff --git a/lib/zend/Zend/Controller/Exception.php b/lib/zend/Zend/Controller/Exception.php
new file mode 100644
index 00000000000..b36853c425c
--- /dev/null
+++ b/lib/zend/Zend/Controller/Exception.php
@@ -0,0 +1,35 @@
+_plugins = new Zend_Controller_Plugin_Broker();
+ }
+
+ /**
+ * Enforce singleton; disallow cloning
+ *
+ * @return void
+ */
+ private function __clone()
+ {
+ }
+
+ /**
+ * Singleton instance
+ *
+ * @return Zend_Controller_Front
+ */
+ public static function getInstance()
+ {
+ if (null === self::$_instance) {
+ self::$_instance = new self();
+ }
+
+ return self::$_instance;
+ }
+
+ /**
+ * Resets all object properties of the singleton instance
+ *
+ * Primarily used for testing; could be used to chain front controllers.
+ *
+ * Also resets action helper broker, clearing all registered helpers.
+ *
+ * @return void
+ */
+ public function resetInstance()
+ {
+ $reflection = new ReflectionObject($this);
+ foreach ($reflection->getProperties() as $property) {
+ $name = $property->getName();
+ switch ($name) {
+ case '_instance':
+ break;
+ case '_controllerDir':
+ case '_invokeParams':
+ $this->{$name} = array();
+ break;
+ case '_plugins':
+ $this->{$name} = new Zend_Controller_Plugin_Broker();
+ break;
+ case '_throwExceptions':
+ case '_returnResponse':
+ $this->{$name} = false;
+ break;
+ case '_moduleControllerDirectoryName':
+ $this->{$name} = 'controllers';
+ break;
+ default:
+ $this->{$name} = null;
+ break;
+ }
+ }
+ Zend_Controller_Action_HelperBroker::resetHelpers();
+ }
+
+ /**
+ * Convenience feature, calls setControllerDirectory()->setRouter()->dispatch()
+ *
+ * In PHP 5.1.x, a call to a static method never populates $this -- so run()
+ * may actually be called after setting up your front controller.
+ *
+ * @param string|array $controllerDirectory Path to Zend_Controller_Action
+ * controller classes or array of such paths
+ * @return void
+ * @throws Zend_Controller_Exception if called from an object instance
+ */
+ public static function run($controllerDirectory)
+ {
+ self::getInstance()
+ ->setControllerDirectory($controllerDirectory)
+ ->dispatch();
+ }
+
+ /**
+ * Add a controller directory to the controller directory stack
+ *
+ * If $args is presented and is a string, uses it for the array key mapping
+ * to the directory specified.
+ *
+ * @param string $directory
+ * @param string $module Optional argument; module with which to associate directory. If none provided, assumes 'default'
+ * @return Zend_Controller_Front
+ * @throws Zend_Controller_Exception if directory not found or readable
+ */
+ public function addControllerDirectory($directory, $module = null)
+ {
+ $this->getDispatcher()->addControllerDirectory($directory, $module);
+ return $this;
+ }
+
+ /**
+ * Set controller directory
+ *
+ * Stores controller directory(ies) in dispatcher. May be an array of
+ * directories or a string containing a single directory.
+ *
+ * @param string|array $directory Path to Zend_Controller_Action controller
+ * classes or array of such paths
+ * @param string $module Optional module name to use with string $directory
+ * @return Zend_Controller_Front
+ */
+ public function setControllerDirectory($directory, $module = null)
+ {
+ $this->getDispatcher()->setControllerDirectory($directory, $module);
+ return $this;
+ }
+
+ /**
+ * Retrieve controller directory
+ *
+ * Retrieves:
+ * - Array of all controller directories if no $name passed
+ * - String path if $name passed and exists as a key in controller directory array
+ * - null if $name passed but does not exist in controller directory keys
+ *
+ * @param string $name Default null
+ * @return array|string|null
+ */
+ public function getControllerDirectory($name = null)
+ {
+ return $this->getDispatcher()->getControllerDirectory($name);
+ }
+
+ /**
+ * Remove a controller directory by module name
+ *
+ * @param string $module
+ * @return bool
+ */
+ public function removeControllerDirectory($module)
+ {
+ return $this->getDispatcher()->removeControllerDirectory($module);
+ }
+
+ /**
+ * Specify a directory as containing modules
+ *
+ * Iterates through the directory, adding any subdirectories as modules;
+ * the subdirectory within each module named after {@link $_moduleControllerDirectoryName}
+ * will be used as the controller directory path.
+ *
+ * @param string $path
+ * @return Zend_Controller_Front
+ */
+ public function addModuleDirectory($path)
+ {
+ try{
+ $dir = new DirectoryIterator($path);
+ } catch(Exception $e) {
+ require_once 'Zend/Controller/Exception.php';
+ throw new Zend_Controller_Exception("Directory $path not readable", 0, $e);
+ }
+ foreach ($dir as $file) {
+ if ($file->isDot() || !$file->isDir()) {
+ continue;
+ }
+
+ $module = $file->getFilename();
+
+ // Don't use SCCS directories as modules
+ if (preg_match('/^[^a-z]/i', $module) || ('CVS' == $module)) {
+ continue;
+ }
+
+ $moduleDir = $file->getPathname() . DIRECTORY_SEPARATOR . $this->getModuleControllerDirectoryName();
+ $this->addControllerDirectory($moduleDir, $module);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Return the path to a module directory (but not the controllers directory within)
+ *
+ * @param string $module
+ * @return string|null
+ */
+ public function getModuleDirectory($module = null)
+ {
+ if (null === $module) {
+ $request = $this->getRequest();
+ if (null !== $request) {
+ $module = $this->getRequest()->getModuleName();
+ }
+ if (empty($module)) {
+ $module = $this->getDispatcher()->getDefaultModule();
+ }
+ }
+
+ $controllerDir = $this->getControllerDirectory($module);
+
+ if ((null === $controllerDir) || !is_string($controllerDir)) {
+ return null;
+ }
+
+ return dirname($controllerDir);
+ }
+
+ /**
+ * Set the directory name within a module containing controllers
+ *
+ * @param string $name
+ * @return Zend_Controller_Front
+ */
+ public function setModuleControllerDirectoryName($name = 'controllers')
+ {
+ $this->_moduleControllerDirectoryName = (string) $name;
+
+ return $this;
+ }
+
+ /**
+ * Return the directory name within a module containing controllers
+ *
+ * @return string
+ */
+ public function getModuleControllerDirectoryName()
+ {
+ return $this->_moduleControllerDirectoryName;
+ }
+
+ /**
+ * Set the default controller (unformatted string)
+ *
+ * @param string $controller
+ * @return Zend_Controller_Front
+ */
+ public function setDefaultControllerName($controller)
+ {
+ $dispatcher = $this->getDispatcher();
+ $dispatcher->setDefaultControllerName($controller);
+ return $this;
+ }
+
+ /**
+ * Retrieve the default controller (unformatted string)
+ *
+ * @return string
+ */
+ public function getDefaultControllerName()
+ {
+ return $this->getDispatcher()->getDefaultControllerName();
+ }
+
+ /**
+ * Set the default action (unformatted string)
+ *
+ * @param string $action
+ * @return Zend_Controller_Front
+ */
+ public function setDefaultAction($action)
+ {
+ $dispatcher = $this->getDispatcher();
+ $dispatcher->setDefaultAction($action);
+ return $this;
+ }
+
+ /**
+ * Retrieve the default action (unformatted string)
+ *
+ * @return string
+ */
+ public function getDefaultAction()
+ {
+ return $this->getDispatcher()->getDefaultAction();
+ }
+
+ /**
+ * Set the default module name
+ *
+ * @param string $module
+ * @return Zend_Controller_Front
+ */
+ public function setDefaultModule($module)
+ {
+ $dispatcher = $this->getDispatcher();
+ $dispatcher->setDefaultModule($module);
+ return $this;
+ }
+
+ /**
+ * Retrieve the default module
+ *
+ * @return string
+ */
+ public function getDefaultModule()
+ {
+ return $this->getDispatcher()->getDefaultModule();
+ }
+
+ /**
+ * Set request class/object
+ *
+ * Set the request object. The request holds the request environment.
+ *
+ * If a class name is provided, it will instantiate it
+ *
+ * @param string|Zend_Controller_Request_Abstract $request
+ * @throws Zend_Controller_Exception if invalid request class
+ * @return Zend_Controller_Front
+ */
+ public function setRequest($request)
+ {
+ if (is_string($request)) {
+ if (!class_exists($request)) {
+ require_once 'Zend/Loader.php';
+ Zend_Loader::loadClass($request);
+ }
+ $request = new $request();
+ }
+ if (!$request instanceof Zend_Controller_Request_Abstract) {
+ require_once 'Zend/Controller/Exception.php';
+ throw new Zend_Controller_Exception('Invalid request class');
+ }
+
+ $this->_request = $request;
+
+ return $this;
+ }
+
+ /**
+ * Return the request object.
+ *
+ * @return null|Zend_Controller_Request_Abstract
+ */
+ public function getRequest()
+ {
+ return $this->_request;
+ }
+
+ /**
+ * Set router class/object
+ *
+ * Set the router object. The router is responsible for mapping
+ * the request to a controller and action.
+ *
+ * If a class name is provided, instantiates router with any parameters
+ * registered via {@link setParam()} or {@link setParams()}.
+ *
+ * @param string|Zend_Controller_Router_Interface $router
+ * @throws Zend_Controller_Exception if invalid router class
+ * @return Zend_Controller_Front
+ */
+ public function setRouter($router)
+ {
+ if (is_string($router)) {
+ if (!class_exists($router)) {
+ require_once 'Zend/Loader.php';
+ Zend_Loader::loadClass($router);
+ }
+ $router = new $router();
+ }
+
+ if (!$router instanceof Zend_Controller_Router_Interface) {
+ require_once 'Zend/Controller/Exception.php';
+ throw new Zend_Controller_Exception('Invalid router class');
+ }
+
+ $router->setFrontController($this);
+ $this->_router = $router;
+
+ return $this;
+ }
+
+ /**
+ * Return the router object.
+ *
+ * Instantiates a Zend_Controller_Router_Rewrite object if no router currently set.
+ *
+ * @return Zend_Controller_Router_Interface
+ */
+ public function getRouter()
+ {
+ if (null == $this->_router) {
+ require_once 'Zend/Controller/Router/Rewrite.php';
+ $this->setRouter(new Zend_Controller_Router_Rewrite());
+ }
+
+ return $this->_router;
+ }
+
+ /**
+ * Set the base URL used for requests
+ *
+ * Use to set the base URL segment of the REQUEST_URI to use when
+ * determining PATH_INFO, etc. Examples:
+ * - /admin
+ * - /myapp
+ * - /subdir/index.php
+ *
+ * Note that the URL should not include the full URI. Do not use:
+ * - http://example.com/admin
+ * - http://example.com/myapp
+ * - http://example.com/subdir/index.php
+ *
+ * If a null value is passed, this can be used as well for autodiscovery (default).
+ *
+ * @param string $base
+ * @return Zend_Controller_Front
+ * @throws Zend_Controller_Exception for non-string $base
+ */
+ public function setBaseUrl($base = null)
+ {
+ if (!is_string($base) && (null !== $base)) {
+ require_once 'Zend/Controller/Exception.php';
+ throw new Zend_Controller_Exception('Rewrite base must be a string');
+ }
+
+ $this->_baseUrl = $base;
+
+ if ((null !== ($request = $this->getRequest())) && (method_exists($request, 'setBaseUrl'))) {
+ $request->setBaseUrl($base);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Retrieve the currently set base URL
+ *
+ * @return string
+ */
+ public function getBaseUrl()
+ {
+ $request = $this->getRequest();
+ if ((null !== $request) && method_exists($request, 'getBaseUrl')) {
+ return $request->getBaseUrl();
+ }
+
+ return $this->_baseUrl;
+ }
+
+ /**
+ * Set the dispatcher object. The dispatcher is responsible for
+ * taking a Zend_Controller_Dispatcher_Token object, instantiating the controller, and
+ * call the action method of the controller.
+ *
+ * @param Zend_Controller_Dispatcher_Interface $dispatcher
+ * @return Zend_Controller_Front
+ */
+ public function setDispatcher(Zend_Controller_Dispatcher_Interface $dispatcher)
+ {
+ $this->_dispatcher = $dispatcher;
+ return $this;
+ }
+
+ /**
+ * Return the dispatcher object.
+ *
+ * @return Zend_Controller_Dispatcher_Interface
+ */
+ public function getDispatcher()
+ {
+ /**
+ * Instantiate the default dispatcher if one was not set.
+ */
+ if (!$this->_dispatcher instanceof Zend_Controller_Dispatcher_Interface) {
+ require_once 'Zend/Controller/Dispatcher/Standard.php';
+ $this->_dispatcher = new Zend_Controller_Dispatcher_Standard();
+ }
+ return $this->_dispatcher;
+ }
+
+ /**
+ * Set response class/object
+ *
+ * Set the response object. The response is a container for action
+ * responses and headers. Usage is optional.
+ *
+ * If a class name is provided, instantiates a response object.
+ *
+ * @param string|Zend_Controller_Response_Abstract $response
+ * @throws Zend_Controller_Exception if invalid response class
+ * @return Zend_Controller_Front
+ */
+ public function setResponse($response)
+ {
+ if (is_string($response)) {
+ if (!class_exists($response)) {
+ require_once 'Zend/Loader.php';
+ Zend_Loader::loadClass($response);
+ }
+ $response = new $response();
+ }
+ if (!$response instanceof Zend_Controller_Response_Abstract) {
+ require_once 'Zend/Controller/Exception.php';
+ throw new Zend_Controller_Exception('Invalid response class');
+ }
+
+ $this->_response = $response;
+
+ return $this;
+ }
+
+ /**
+ * Return the response object.
+ *
+ * @return null|Zend_Controller_Response_Abstract
+ */
+ public function getResponse()
+ {
+ return $this->_response;
+ }
+
+ /**
+ * Add or modify a parameter to use when instantiating an action controller
+ *
+ * @param string $name
+ * @param mixed $value
+ * @return Zend_Controller_Front
+ */
+ public function setParam($name, $value)
+ {
+ $name = (string) $name;
+ $this->_invokeParams[$name] = $value;
+ return $this;
+ }
+
+ /**
+ * Set parameters to pass to action controller constructors
+ *
+ * @param array $params
+ * @return Zend_Controller_Front
+ */
+ public function setParams(array $params)
+ {
+ $this->_invokeParams = array_merge($this->_invokeParams, $params);
+ return $this;
+ }
+
+ /**
+ * Retrieve a single parameter from the controller parameter stack
+ *
+ * @param string $name
+ * @return mixed
+ */
+ public function getParam($name)
+ {
+ if(isset($this->_invokeParams[$name])) {
+ return $this->_invokeParams[$name];
+ }
+
+ return null;
+ }
+
+ /**
+ * Retrieve action controller instantiation parameters
+ *
+ * @return array
+ */
+ public function getParams()
+ {
+ return $this->_invokeParams;
+ }
+
+ /**
+ * Clear the controller parameter stack
+ *
+ * By default, clears all parameters. If a parameter name is given, clears
+ * only that parameter; if an array of parameter names is provided, clears
+ * each.
+ *
+ * @param null|string|array single key or array of keys for params to clear
+ * @return Zend_Controller_Front
+ */
+ public function clearParams($name = null)
+ {
+ if (null === $name) {
+ $this->_invokeParams = array();
+ } elseif (is_string($name) && isset($this->_invokeParams[$name])) {
+ unset($this->_invokeParams[$name]);
+ } elseif (is_array($name)) {
+ foreach ($name as $key) {
+ if (is_string($key) && isset($this->_invokeParams[$key])) {
+ unset($this->_invokeParams[$key]);
+ }
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Register a plugin.
+ *
+ * @param Zend_Controller_Plugin_Abstract $plugin
+ * @param int $stackIndex Optional; stack index for plugin
+ * @return Zend_Controller_Front
+ */
+ public function registerPlugin(Zend_Controller_Plugin_Abstract $plugin, $stackIndex = null)
+ {
+ $this->_plugins->registerPlugin($plugin, $stackIndex);
+ return $this;
+ }
+
+ /**
+ * Unregister a plugin.
+ *
+ * @param string|Zend_Controller_Plugin_Abstract $plugin Plugin class or object to unregister
+ * @return Zend_Controller_Front
+ */
+ public function unregisterPlugin($plugin)
+ {
+ $this->_plugins->unregisterPlugin($plugin);
+ return $this;
+ }
+
+ /**
+ * Is a particular plugin registered?
+ *
+ * @param string $class
+ * @return bool
+ */
+ public function hasPlugin($class)
+ {
+ return $this->_plugins->hasPlugin($class);
+ }
+
+ /**
+ * Retrieve a plugin or plugins by class
+ *
+ * @param string $class
+ * @return false|Zend_Controller_Plugin_Abstract|array
+ */
+ public function getPlugin($class)
+ {
+ return $this->_plugins->getPlugin($class);
+ }
+
+ /**
+ * Retrieve all plugins
+ *
+ * @return array
+ */
+ public function getPlugins()
+ {
+ return $this->_plugins->getPlugins();
+ }
+
+ /**
+ * Set the throwExceptions flag and retrieve current status
+ *
+ * Set whether exceptions encounted in the dispatch loop should be thrown
+ * or caught and trapped in the response object.
+ *
+ * Default behaviour is to trap them in the response object; call this
+ * method to have them thrown.
+ *
+ * Passing no value will return the current value of the flag; passing a
+ * boolean true or false value will set the flag and return the current
+ * object instance.
+ *
+ * @param boolean $flag Defaults to null (return flag state)
+ * @return boolean|Zend_Controller_Front Used as a setter, returns object; as a getter, returns boolean
+ */
+ public function throwExceptions($flag = null)
+ {
+ if ($flag !== null) {
+ $this->_throwExceptions = (bool) $flag;
+ return $this;
+ }
+
+ return $this->_throwExceptions;
+ }
+
+ /**
+ * Set whether {@link dispatch()} should return the response without first
+ * rendering output. By default, output is rendered and dispatch() returns
+ * nothing.
+ *
+ * @param boolean $flag
+ * @return boolean|Zend_Controller_Front Used as a setter, returns object; as a getter, returns boolean
+ */
+ public function returnResponse($flag = null)
+ {
+ if (true === $flag) {
+ $this->_returnResponse = true;
+ return $this;
+ } elseif (false === $flag) {
+ $this->_returnResponse = false;
+ return $this;
+ }
+
+ return $this->_returnResponse;
+ }
+
+ /**
+ * Dispatch an HTTP request to a controller/action.
+ *
+ * @param Zend_Controller_Request_Abstract|null $request
+ * @param Zend_Controller_Response_Abstract|null $response
+ * @return void|Zend_Controller_Response_Abstract Returns response object if returnResponse() is true
+ */
+ public function dispatch(Zend_Controller_Request_Abstract $request = null, Zend_Controller_Response_Abstract $response = null)
+ {
+ if (!$this->getParam('noErrorHandler') && !$this->_plugins->hasPlugin('Zend_Controller_Plugin_ErrorHandler')) {
+ // Register with stack index of 100
+ require_once 'Zend/Controller/Plugin/ErrorHandler.php';
+ $this->_plugins->registerPlugin(new Zend_Controller_Plugin_ErrorHandler(), 100);
+ }
+
+ if (!$this->getParam('noViewRenderer') && !Zend_Controller_Action_HelperBroker::hasHelper('viewRenderer')) {
+ require_once 'Zend/Controller/Action/Helper/ViewRenderer.php';
+ Zend_Controller_Action_HelperBroker::getStack()->offsetSet(-80, new Zend_Controller_Action_Helper_ViewRenderer());
+ }
+
+ /**
+ * Instantiate default request object (HTTP version) if none provided
+ */
+ if (null !== $request) {
+ $this->setRequest($request);
+ } elseif ((null === $request) && (null === ($request = $this->getRequest()))) {
+ require_once 'Zend/Controller/Request/Http.php';
+ $request = new Zend_Controller_Request_Http();
+ $this->setRequest($request);
+ }
+
+ /**
+ * Set base URL of request object, if available
+ */
+ if (is_callable(array($this->_request, 'setBaseUrl'))) {
+ if (null !== $this->_baseUrl) {
+ $this->_request->setBaseUrl($this->_baseUrl);
+ }
+ }
+
+ /**
+ * Instantiate default response object (HTTP version) if none provided
+ */
+ if (null !== $response) {
+ $this->setResponse($response);
+ } elseif ((null === $this->_response) && (null === ($this->_response = $this->getResponse()))) {
+ require_once 'Zend/Controller/Response/Http.php';
+ $response = new Zend_Controller_Response_Http();
+ $this->setResponse($response);
+ }
+
+ /**
+ * Register request and response objects with plugin broker
+ */
+ $this->_plugins
+ ->setRequest($this->_request)
+ ->setResponse($this->_response);
+
+ /**
+ * Initialize router
+ */
+ $router = $this->getRouter();
+ $router->setParams($this->getParams());
+
+ /**
+ * Initialize dispatcher
+ */
+ $dispatcher = $this->getDispatcher();
+ $dispatcher->setParams($this->getParams())
+ ->setResponse($this->_response);
+
+ // Begin dispatch
+ try {
+ /**
+ * Route request to controller/action, if a router is provided
+ */
+
+ /**
+ * Notify plugins of router startup
+ */
+ $this->_plugins->routeStartup($this->_request);
+
+ try {
+ $router->route($this->_request);
+ } catch (Exception $e) {
+ if ($this->throwExceptions()) {
+ throw $e;
+ }
+
+ $this->_response->setException($e);
+ }
+
+ /**
+ * Notify plugins of router completion
+ */
+ $this->_plugins->routeShutdown($this->_request);
+
+ /**
+ * Notify plugins of dispatch loop startup
+ */
+ $this->_plugins->dispatchLoopStartup($this->_request);
+
+ /**
+ * Attempt to dispatch the controller/action. If the $this->_request
+ * indicates that it needs to be dispatched, move to the next
+ * action in the request.
+ */
+ do {
+ $this->_request->setDispatched(true);
+
+ /**
+ * Notify plugins of dispatch startup
+ */
+ $this->_plugins->preDispatch($this->_request);
+
+ /**
+ * Skip requested action if preDispatch() has reset it
+ */
+ if (!$this->_request->isDispatched()) {
+ continue;
+ }
+
+ /**
+ * Dispatch request
+ */
+ try {
+ $dispatcher->dispatch($this->_request, $this->_response);
+ } catch (Exception $e) {
+ if ($this->throwExceptions()) {
+ throw $e;
+ }
+ $this->_response->setException($e);
+ }
+
+ /**
+ * Notify plugins of dispatch completion
+ */
+ $this->_plugins->postDispatch($this->_request);
+ } while (!$this->_request->isDispatched());
+ } catch (Exception $e) {
+ if ($this->throwExceptions()) {
+ throw $e;
+ }
+
+ $this->_response->setException($e);
+ }
+
+ /**
+ * Notify plugins of dispatch loop completion
+ */
+ try {
+ $this->_plugins->dispatchLoopShutdown();
+ } catch (Exception $e) {
+ if ($this->throwExceptions()) {
+ throw $e;
+ }
+
+ $this->_response->setException($e);
+ }
+
+ if ($this->returnResponse()) {
+ return $this->_response;
+ }
+
+ $this->_response->sendResponse();
+ }
+}
diff --git a/lib/zend/Zend/Controller/Plugin/Abstract.php b/lib/zend/Zend/Controller/Plugin/Abstract.php
new file mode 100644
index 00000000000..7e590b7eef0
--- /dev/null
+++ b/lib/zend/Zend/Controller/Plugin/Abstract.php
@@ -0,0 +1,151 @@
+_request = $request;
+ return $this;
+ }
+
+ /**
+ * Get request object
+ *
+ * @return Zend_Controller_Request_Abstract $request
+ */
+ public function getRequest()
+ {
+ return $this->_request;
+ }
+
+ /**
+ * Set response object
+ *
+ * @param Zend_Controller_Response_Abstract $response
+ * @return Zend_Controller_Plugin_Abstract
+ */
+ public function setResponse(Zend_Controller_Response_Abstract $response)
+ {
+ $this->_response = $response;
+ return $this;
+ }
+
+ /**
+ * Get response object
+ *
+ * @return Zend_Controller_Response_Abstract $response
+ */
+ public function getResponse()
+ {
+ return $this->_response;
+ }
+
+ /**
+ * Called before Zend_Controller_Front begins evaluating the
+ * request against its routes.
+ *
+ * @param Zend_Controller_Request_Abstract $request
+ * @return void
+ */
+ public function routeStartup(Zend_Controller_Request_Abstract $request)
+ {}
+
+ /**
+ * Called after Zend_Controller_Router exits.
+ *
+ * Called after Zend_Controller_Front exits from the router.
+ *
+ * @param Zend_Controller_Request_Abstract $request
+ * @return void
+ */
+ public function routeShutdown(Zend_Controller_Request_Abstract $request)
+ {}
+
+ /**
+ * Called before Zend_Controller_Front enters its dispatch loop.
+ *
+ * @param Zend_Controller_Request_Abstract $request
+ * @return void
+ */
+ public function dispatchLoopStartup(Zend_Controller_Request_Abstract $request)
+ {}
+
+ /**
+ * Called before an action is dispatched by Zend_Controller_Dispatcher.
+ *
+ * This callback allows for proxy or filter behavior. By altering the
+ * request and resetting its dispatched flag (via
+ * {@link Zend_Controller_Request_Abstract::setDispatched() setDispatched(false)}),
+ * the current action may be skipped.
+ *
+ * @param Zend_Controller_Request_Abstract $request
+ * @return void
+ */
+ public function preDispatch(Zend_Controller_Request_Abstract $request)
+ {}
+
+ /**
+ * Called after an action is dispatched by Zend_Controller_Dispatcher.
+ *
+ * This callback allows for proxy or filter behavior. By altering the
+ * request and resetting its dispatched flag (via
+ * {@link Zend_Controller_Request_Abstract::setDispatched() setDispatched(false)}),
+ * a new action may be specified for dispatching.
+ *
+ * @param Zend_Controller_Request_Abstract $request
+ * @return void
+ */
+ public function postDispatch(Zend_Controller_Request_Abstract $request)
+ {}
+
+ /**
+ * Called before Zend_Controller_Front exits its dispatch loop.
+ *
+ * @return void
+ */
+ public function dispatchLoopShutdown()
+ {}
+}
diff --git a/lib/zend/Zend/Controller/Plugin/ActionStack.php b/lib/zend/Zend/Controller/Plugin/ActionStack.php
new file mode 100644
index 00000000000..12c62de1127
--- /dev/null
+++ b/lib/zend/Zend/Controller/Plugin/ActionStack.php
@@ -0,0 +1,280 @@
+setRegistry($registry);
+
+ if (null !== $key) {
+ $this->setRegistryKey($key);
+ } else {
+ $key = $this->getRegistryKey();
+ }
+
+ $registry[$key] = array();
+ }
+
+ /**
+ * Set registry object
+ *
+ * @param Zend_Registry $registry
+ * @return Zend_Controller_Plugin_ActionStack
+ */
+ public function setRegistry(Zend_Registry $registry)
+ {
+ $this->_registry = $registry;
+ return $this;
+ }
+
+ /**
+ * Retrieve registry object
+ *
+ * @return Zend_Registry
+ */
+ public function getRegistry()
+ {
+ return $this->_registry;
+ }
+
+ /**
+ * Retrieve registry key
+ *
+ * @return string
+ */
+ public function getRegistryKey()
+ {
+ return $this->_registryKey;
+ }
+
+ /**
+ * Set registry key
+ *
+ * @param string $key
+ * @return Zend_Controller_Plugin_ActionStack
+ */
+ public function setRegistryKey($key)
+ {
+ $this->_registryKey = (string) $key;
+ return $this;
+ }
+
+ /**
+ * Set clearRequestParams flag
+ *
+ * @param bool $clearRequestParams
+ * @return Zend_Controller_Plugin_ActionStack
+ */
+ public function setClearRequestParams($clearRequestParams)
+ {
+ $this->_clearRequestParams = (bool) $clearRequestParams;
+ return $this;
+ }
+
+ /**
+ * Retrieve clearRequestParams flag
+ *
+ * @return bool
+ */
+ public function getClearRequestParams()
+ {
+ return $this->_clearRequestParams;
+ }
+
+ /**
+ * Retrieve action stack
+ *
+ * @return array
+ */
+ public function getStack()
+ {
+ $registry = $this->getRegistry();
+ $stack = $registry[$this->getRegistryKey()];
+ return $stack;
+ }
+
+ /**
+ * Save stack to registry
+ *
+ * @param array $stack
+ * @return Zend_Controller_Plugin_ActionStack
+ */
+ protected function _saveStack(array $stack)
+ {
+ $registry = $this->getRegistry();
+ $registry[$this->getRegistryKey()] = $stack;
+ return $this;
+ }
+
+ /**
+ * Push an item onto the stack
+ *
+ * @param Zend_Controller_Request_Abstract $next
+ * @return Zend_Controller_Plugin_ActionStack
+ */
+ public function pushStack(Zend_Controller_Request_Abstract $next)
+ {
+ $stack = $this->getStack();
+ array_push($stack, $next);
+ return $this->_saveStack($stack);
+ }
+
+ /**
+ * Pop an item off the action stack
+ *
+ * @return false|Zend_Controller_Request_Abstract
+ */
+ public function popStack()
+ {
+ $stack = $this->getStack();
+ if (0 == count($stack)) {
+ return false;
+ }
+
+ $next = array_pop($stack);
+ $this->_saveStack($stack);
+
+ if (!$next instanceof Zend_Controller_Request_Abstract) {
+ require_once 'Zend/Controller/Exception.php';
+ throw new Zend_Controller_Exception('ArrayStack should only contain request objects');
+ }
+ $action = $next->getActionName();
+ if (empty($action)) {
+ return $this->popStack($stack);
+ }
+
+ $request = $this->getRequest();
+ $controller = $next->getControllerName();
+ if (empty($controller)) {
+ $next->setControllerName($request->getControllerName());
+ }
+
+ $module = $next->getModuleName();
+ if (empty($module)) {
+ $next->setModuleName($request->getModuleName());
+ }
+
+ return $next;
+ }
+
+ /**
+ * postDispatch() plugin hook -- check for actions in stack, and dispatch if any found
+ *
+ * @param Zend_Controller_Request_Abstract $request
+ * @return void
+ */
+ public function postDispatch(Zend_Controller_Request_Abstract $request)
+ {
+ // Don't move on to next request if this is already an attempt to
+ // forward
+ if (!$request->isDispatched()) {
+ return;
+ }
+
+ $this->setRequest($request);
+ $stack = $this->getStack();
+ if (empty($stack)) {
+ return;
+ }
+ $next = $this->popStack();
+ if (!$next) {
+ return;
+ }
+
+ $this->forward($next);
+ }
+
+ /**
+ * Forward request with next action
+ *
+ * @param array $next
+ * @return void
+ */
+ public function forward(Zend_Controller_Request_Abstract $next)
+ {
+ $request = $this->getRequest();
+ if ($this->getClearRequestParams()) {
+ $request->clearParams();
+ }
+
+ $request->setModuleName($next->getModuleName())
+ ->setControllerName($next->getControllerName())
+ ->setActionName($next->getActionName())
+ ->setParams($next->getParams())
+ ->setDispatched(false);
+ }
+}
diff --git a/lib/zend/Zend/Controller/Plugin/Broker.php b/lib/zend/Zend/Controller/Plugin/Broker.php
new file mode 100644
index 00000000000..1214583eb30
--- /dev/null
+++ b/lib/zend/Zend/Controller/Plugin/Broker.php
@@ -0,0 +1,365 @@
+_plugins, true)) {
+ require_once 'Zend/Controller/Exception.php';
+ throw new Zend_Controller_Exception('Plugin already registered');
+ }
+
+ $stackIndex = (int) $stackIndex;
+
+ if ($stackIndex) {
+ if (isset($this->_plugins[$stackIndex])) {
+ require_once 'Zend/Controller/Exception.php';
+ throw new Zend_Controller_Exception('Plugin with stackIndex "' . $stackIndex . '" already registered');
+ }
+ $this->_plugins[$stackIndex] = $plugin;
+ } else {
+ $stackIndex = count($this->_plugins);
+ while (isset($this->_plugins[$stackIndex])) {
+ ++$stackIndex;
+ }
+ $this->_plugins[$stackIndex] = $plugin;
+ }
+
+ $request = $this->getRequest();
+ if ($request) {
+ $this->_plugins[$stackIndex]->setRequest($request);
+ }
+ $response = $this->getResponse();
+ if ($response) {
+ $this->_plugins[$stackIndex]->setResponse($response);
+ }
+
+ ksort($this->_plugins);
+
+ return $this;
+ }
+
+ /**
+ * Unregister a plugin.
+ *
+ * @param string|Zend_Controller_Plugin_Abstract $plugin Plugin object or class name
+ * @return Zend_Controller_Plugin_Broker
+ */
+ public function unregisterPlugin($plugin)
+ {
+ if ($plugin instanceof Zend_Controller_Plugin_Abstract) {
+ // Given a plugin object, find it in the array
+ $key = array_search($plugin, $this->_plugins, true);
+ if (false === $key) {
+ require_once 'Zend/Controller/Exception.php';
+ throw new Zend_Controller_Exception('Plugin never registered.');
+ }
+ unset($this->_plugins[$key]);
+ } elseif (is_string($plugin)) {
+ // Given a plugin class, find all plugins of that class and unset them
+ foreach ($this->_plugins as $key => $_plugin) {
+ $type = get_class($_plugin);
+ if ($plugin == $type) {
+ unset($this->_plugins[$key]);
+ }
+ }
+ }
+ return $this;
+ }
+
+ /**
+ * Is a plugin of a particular class registered?
+ *
+ * @param string $class
+ * @return bool
+ */
+ public function hasPlugin($class)
+ {
+ foreach ($this->_plugins as $plugin) {
+ $type = get_class($plugin);
+ if ($class == $type) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Retrieve a plugin or plugins by class
+ *
+ * @param string $class Class name of plugin(s) desired
+ * @return false|Zend_Controller_Plugin_Abstract|array Returns false if none found, plugin if only one found, and array of plugins if multiple plugins of same class found
+ */
+ public function getPlugin($class)
+ {
+ $found = array();
+ foreach ($this->_plugins as $plugin) {
+ $type = get_class($plugin);
+ if ($class == $type) {
+ $found[] = $plugin;
+ }
+ }
+
+ switch (count($found)) {
+ case 0:
+ return false;
+ case 1:
+ return $found[0];
+ default:
+ return $found;
+ }
+ }
+
+ /**
+ * Retrieve all plugins
+ *
+ * @return array
+ */
+ public function getPlugins()
+ {
+ return $this->_plugins;
+ }
+
+ /**
+ * Set request object, and register with each plugin
+ *
+ * @param Zend_Controller_Request_Abstract $request
+ * @return Zend_Controller_Plugin_Broker
+ */
+ public function setRequest(Zend_Controller_Request_Abstract $request)
+ {
+ $this->_request = $request;
+
+ foreach ($this->_plugins as $plugin) {
+ $plugin->setRequest($request);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get request object
+ *
+ * @return Zend_Controller_Request_Abstract $request
+ */
+ public function getRequest()
+ {
+ return $this->_request;
+ }
+
+ /**
+ * Set response object
+ *
+ * @param Zend_Controller_Response_Abstract $response
+ * @return Zend_Controller_Plugin_Broker
+ */
+ public function setResponse(Zend_Controller_Response_Abstract $response)
+ {
+ $this->_response = $response;
+
+ foreach ($this->_plugins as $plugin) {
+ $plugin->setResponse($response);
+ }
+
+
+ return $this;
+ }
+
+ /**
+ * Get response object
+ *
+ * @return Zend_Controller_Response_Abstract $response
+ */
+ public function getResponse()
+ {
+ return $this->_response;
+ }
+
+
+ /**
+ * Called before Zend_Controller_Front begins evaluating the
+ * request against its routes.
+ *
+ * @param Zend_Controller_Request_Abstract $request
+ * @return void
+ */
+ public function routeStartup(Zend_Controller_Request_Abstract $request)
+ {
+ foreach ($this->_plugins as $plugin) {
+ try {
+ $plugin->routeStartup($request);
+ } catch (Exception $e) {
+ if (Zend_Controller_Front::getInstance()->throwExceptions()) {
+ throw new Zend_Controller_Exception($e->getMessage() . $e->getTraceAsString(), $e->getCode(), $e);
+ } else {
+ $this->getResponse()->setException($e);
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Called before Zend_Controller_Front exits its iterations over
+ * the route set.
+ *
+ * @param Zend_Controller_Request_Abstract $request
+ * @return void
+ */
+ public function routeShutdown(Zend_Controller_Request_Abstract $request)
+ {
+ foreach ($this->_plugins as $plugin) {
+ try {
+ $plugin->routeShutdown($request);
+ } catch (Exception $e) {
+ if (Zend_Controller_Front::getInstance()->throwExceptions()) {
+ throw new Zend_Controller_Exception($e->getMessage() . $e->getTraceAsString(), $e->getCode(), $e);
+ } else {
+ $this->getResponse()->setException($e);
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Called before Zend_Controller_Front enters its dispatch loop.
+ *
+ * During the dispatch loop, Zend_Controller_Front keeps a
+ * Zend_Controller_Request_Abstract object, and uses
+ * Zend_Controller_Dispatcher to dispatch the
+ * Zend_Controller_Request_Abstract object to controllers/actions.
+ *
+ * @param Zend_Controller_Request_Abstract $request
+ * @return void
+ */
+ public function dispatchLoopStartup(Zend_Controller_Request_Abstract $request)
+ {
+ foreach ($this->_plugins as $plugin) {
+ try {
+ $plugin->dispatchLoopStartup($request);
+ } catch (Exception $e) {
+ if (Zend_Controller_Front::getInstance()->throwExceptions()) {
+ throw new Zend_Controller_Exception($e->getMessage() . $e->getTraceAsString(), $e->getCode(), $e);
+ } else {
+ $this->getResponse()->setException($e);
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Called before an action is dispatched by Zend_Controller_Dispatcher.
+ *
+ * @param Zend_Controller_Request_Abstract $request
+ * @return void
+ */
+ public function preDispatch(Zend_Controller_Request_Abstract $request)
+ {
+ foreach ($this->_plugins as $plugin) {
+ try {
+ $plugin->preDispatch($request);
+ } catch (Exception $e) {
+ if (Zend_Controller_Front::getInstance()->throwExceptions()) {
+ throw new Zend_Controller_Exception($e->getMessage() . $e->getTraceAsString(), $e->getCode(), $e);
+ } else {
+ $this->getResponse()->setException($e);
+ // skip rendering of normal dispatch give the error handler a try
+ $this->getRequest()->setDispatched(false);
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Called after an action is dispatched by Zend_Controller_Dispatcher.
+ *
+ * @param Zend_Controller_Request_Abstract $request
+ * @return void
+ */
+ public function postDispatch(Zend_Controller_Request_Abstract $request)
+ {
+ foreach ($this->_plugins as $plugin) {
+ try {
+ $plugin->postDispatch($request);
+ } catch (Exception $e) {
+ if (Zend_Controller_Front::getInstance()->throwExceptions()) {
+ throw new Zend_Controller_Exception($e->getMessage() . $e->getTraceAsString(), $e->getCode(), $e);
+ } else {
+ $this->getResponse()->setException($e);
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Called before Zend_Controller_Front exits its dispatch loop.
+ *
+ * @param Zend_Controller_Request_Abstract $request
+ * @return void
+ */
+ public function dispatchLoopShutdown()
+ {
+ foreach ($this->_plugins as $plugin) {
+ try {
+ $plugin->dispatchLoopShutdown();
+ } catch (Exception $e) {
+ if (Zend_Controller_Front::getInstance()->throwExceptions()) {
+ throw new Zend_Controller_Exception($e->getMessage() . $e->getTraceAsString(), $e->getCode(), $e);
+ } else {
+ $this->getResponse()->setException($e);
+ }
+ }
+ }
+ }
+}
diff --git a/lib/zend/Zend/Controller/Plugin/ErrorHandler.php b/lib/zend/Zend/Controller/Plugin/ErrorHandler.php
new file mode 100644
index 00000000000..42da1633c64
--- /dev/null
+++ b/lib/zend/Zend/Controller/Plugin/ErrorHandler.php
@@ -0,0 +1,300 @@
+setErrorHandler($options);
+ }
+
+ /**
+ * setErrorHandler() - setup the error handling options
+ *
+ * @param array $options
+ * @return Zend_Controller_Plugin_ErrorHandler
+ */
+ public function setErrorHandler(Array $options = array())
+ {
+ if (isset($options['module'])) {
+ $this->setErrorHandlerModule($options['module']);
+ }
+ if (isset($options['controller'])) {
+ $this->setErrorHandlerController($options['controller']);
+ }
+ if (isset($options['action'])) {
+ $this->setErrorHandlerAction($options['action']);
+ }
+ return $this;
+ }
+
+ /**
+ * Set the module name for the error handler
+ *
+ * @param string $module
+ * @return Zend_Controller_Plugin_ErrorHandler
+ */
+ public function setErrorHandlerModule($module)
+ {
+ $this->_errorModule = (string) $module;
+ return $this;
+ }
+
+ /**
+ * Retrieve the current error handler module
+ *
+ * @return string
+ */
+ public function getErrorHandlerModule()
+ {
+ if (null === $this->_errorModule) {
+ $this->_errorModule = Zend_Controller_Front::getInstance()->getDispatcher()->getDefaultModule();
+ }
+ return $this->_errorModule;
+ }
+
+ /**
+ * Set the controller name for the error handler
+ *
+ * @param string $controller
+ * @return Zend_Controller_Plugin_ErrorHandler
+ */
+ public function setErrorHandlerController($controller)
+ {
+ $this->_errorController = (string) $controller;
+ return $this;
+ }
+
+ /**
+ * Retrieve the current error handler controller
+ *
+ * @return string
+ */
+ public function getErrorHandlerController()
+ {
+ return $this->_errorController;
+ }
+
+ /**
+ * Set the action name for the error handler
+ *
+ * @param string $action
+ * @return Zend_Controller_Plugin_ErrorHandler
+ */
+ public function setErrorHandlerAction($action)
+ {
+ $this->_errorAction = (string) $action;
+ return $this;
+ }
+
+ /**
+ * Retrieve the current error handler action
+ *
+ * @return string
+ */
+ public function getErrorHandlerAction()
+ {
+ return $this->_errorAction;
+ }
+
+ /**
+ * Route shutdown hook -- Ccheck for router exceptions
+ *
+ * @param Zend_Controller_Request_Abstract $request
+ */
+ public function routeShutdown(Zend_Controller_Request_Abstract $request)
+ {
+ $this->_handleError($request);
+ }
+
+ /**
+ * Pre dispatch hook -- check for exceptions and dispatch error handler if
+ * necessary
+ *
+ * @param Zend_Controller_Request_Abstract $request
+ */
+ public function preDispatch(Zend_Controller_Request_Abstract $request)
+ {
+ $this->_handleError($request);
+ }
+
+ /**
+ * Post dispatch hook -- check for exceptions and dispatch error handler if
+ * necessary
+ *
+ * @param Zend_Controller_Request_Abstract $request
+ */
+ public function postDispatch(Zend_Controller_Request_Abstract $request)
+ {
+ $this->_handleError($request);
+ }
+
+ /**
+ * Handle errors and exceptions
+ *
+ * If the 'noErrorHandler' front controller flag has been set,
+ * returns early.
+ *
+ * @param Zend_Controller_Request_Abstract $request
+ * @return void
+ */
+ protected function _handleError(Zend_Controller_Request_Abstract $request)
+ {
+ $frontController = Zend_Controller_Front::getInstance();
+ if ($frontController->getParam('noErrorHandler')) {
+ return;
+ }
+
+ $response = $this->getResponse();
+
+ if ($this->_isInsideErrorHandlerLoop) {
+ $exceptions = $response->getException();
+ if (count($exceptions) > $this->_exceptionCountAtFirstEncounter) {
+ // Exception thrown by error handler; tell the front controller to throw it
+ $frontController->throwExceptions(true);
+ throw array_pop($exceptions);
+ }
+ }
+
+ // check for an exception AND allow the error handler controller the option to forward
+ if (($response->isException()) && (!$this->_isInsideErrorHandlerLoop)) {
+ $this->_isInsideErrorHandlerLoop = true;
+
+ // Get exception information
+ $error = new ArrayObject(array(), ArrayObject::ARRAY_AS_PROPS);
+ $exceptions = $response->getException();
+ $exception = $exceptions[0];
+ $exceptionType = get_class($exception);
+ $error->exception = $exception;
+ switch ($exceptionType) {
+ case 'Zend_Controller_Router_Exception':
+ if (404 == $exception->getCode()) {
+ $error->type = self::EXCEPTION_NO_ROUTE;
+ } else {
+ $error->type = self::EXCEPTION_OTHER;
+ }
+ break;
+ case 'Zend_Controller_Dispatcher_Exception':
+ $error->type = self::EXCEPTION_NO_CONTROLLER;
+ break;
+ case 'Zend_Controller_Action_Exception':
+ if (404 == $exception->getCode()) {
+ $error->type = self::EXCEPTION_NO_ACTION;
+ } else {
+ $error->type = self::EXCEPTION_OTHER;
+ }
+ break;
+ default:
+ $error->type = self::EXCEPTION_OTHER;
+ break;
+ }
+
+ // Keep a copy of the original request
+ $error->request = clone $request;
+
+ // get a count of the number of exceptions encountered
+ $this->_exceptionCountAtFirstEncounter = count($exceptions);
+
+ // Forward to the error handler
+ $request->setParam('error_handler', $error)
+ ->setModuleName($this->getErrorHandlerModule())
+ ->setControllerName($this->getErrorHandlerController())
+ ->setActionName($this->getErrorHandlerAction())
+ ->setDispatched(false);
+ }
+ }
+}
diff --git a/lib/zend/Zend/Controller/Plugin/PutHandler.php b/lib/zend/Zend/Controller/Plugin/PutHandler.php
new file mode 100644
index 00000000000..3b5f57b9102
--- /dev/null
+++ b/lib/zend/Zend/Controller/Plugin/PutHandler.php
@@ -0,0 +1,60 @@
+_request->isPut()) {
+ $putParams = array();
+ parse_str($this->_request->getRawBody(), $putParams);
+ $request->setParams($putParams);
+ }
+ }
+}
diff --git a/lib/zend/Zend/Controller/Request/Abstract.php b/lib/zend/Zend/Controller/Request/Abstract.php
new file mode 100644
index 00000000000..d57238f46be
--- /dev/null
+++ b/lib/zend/Zend/Controller/Request/Abstract.php
@@ -0,0 +1,356 @@
+_module) {
+ $this->_module = $this->getParam($this->getModuleKey());
+ }
+
+ return $this->_module;
+ }
+
+ /**
+ * Set the module name to use
+ *
+ * @param string $value
+ * @return Zend_Controller_Request_Abstract
+ */
+ public function setModuleName($value)
+ {
+ $this->_module = $value;
+ return $this;
+ }
+
+ /**
+ * Retrieve the controller name
+ *
+ * @return string
+ */
+ public function getControllerName()
+ {
+ if (null === $this->_controller) {
+ $this->_controller = $this->getParam($this->getControllerKey());
+ }
+
+ return $this->_controller;
+ }
+
+ /**
+ * Set the controller name to use
+ *
+ * @param string $value
+ * @return Zend_Controller_Request_Abstract
+ */
+ public function setControllerName($value)
+ {
+ $this->_controller = $value;
+ return $this;
+ }
+
+ /**
+ * Retrieve the action name
+ *
+ * @return string
+ */
+ public function getActionName()
+ {
+ if (null === $this->_action) {
+ $this->_action = $this->getParam($this->getActionKey());
+ }
+
+ return $this->_action;
+ }
+
+ /**
+ * Set the action name
+ *
+ * @param string $value
+ * @return Zend_Controller_Request_Abstract
+ */
+ public function setActionName($value)
+ {
+ $this->_action = $value;
+ /**
+ * @see ZF-3465
+ */
+ if (null === $value) {
+ $this->setParam($this->getActionKey(), $value);
+ }
+ return $this;
+ }
+
+ /**
+ * Retrieve the module key
+ *
+ * @return string
+ */
+ public function getModuleKey()
+ {
+ return $this->_moduleKey;
+ }
+
+ /**
+ * Set the module key
+ *
+ * @param string $key
+ * @return Zend_Controller_Request_Abstract
+ */
+ public function setModuleKey($key)
+ {
+ $this->_moduleKey = (string) $key;
+ return $this;
+ }
+
+ /**
+ * Retrieve the controller key
+ *
+ * @return string
+ */
+ public function getControllerKey()
+ {
+ return $this->_controllerKey;
+ }
+
+ /**
+ * Set the controller key
+ *
+ * @param string $key
+ * @return Zend_Controller_Request_Abstract
+ */
+ public function setControllerKey($key)
+ {
+ $this->_controllerKey = (string) $key;
+ return $this;
+ }
+
+ /**
+ * Retrieve the action key
+ *
+ * @return string
+ */
+ public function getActionKey()
+ {
+ return $this->_actionKey;
+ }
+
+ /**
+ * Set the action key
+ *
+ * @param string $key
+ * @return Zend_Controller_Request_Abstract
+ */
+ public function setActionKey($key)
+ {
+ $this->_actionKey = (string) $key;
+ return $this;
+ }
+
+ /**
+ * Get an action parameter
+ *
+ * @param string $key
+ * @param mixed $default Default value to use if key not found
+ * @return mixed
+ */
+ public function getParam($key, $default = null)
+ {
+ $key = (string) $key;
+ if (isset($this->_params[$key])) {
+ return $this->_params[$key];
+ }
+
+ return $default;
+ }
+
+ /**
+ * Retrieve only user params (i.e, any param specific to the object and not the environment)
+ *
+ * @return array
+ */
+ public function getUserParams()
+ {
+ return $this->_params;
+ }
+
+ /**
+ * Retrieve a single user param (i.e, a param specific to the object and not the environment)
+ *
+ * @param string $key
+ * @param string $default Default value to use if key not found
+ * @return mixed
+ */
+ public function getUserParam($key, $default = null)
+ {
+ if (isset($this->_params[$key])) {
+ return $this->_params[$key];
+ }
+
+ return $default;
+ }
+
+ /**
+ * Set an action parameter
+ *
+ * A $value of null will unset the $key if it exists
+ *
+ * @param string $key
+ * @param mixed $value
+ * @return Zend_Controller_Request_Abstract
+ */
+ public function setParam($key, $value)
+ {
+ $key = (string) $key;
+
+ if ((null === $value) && isset($this->_params[$key])) {
+ unset($this->_params[$key]);
+ } elseif (null !== $value) {
+ $this->_params[$key] = $value;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get all action parameters
+ *
+ * @return array
+ */
+ public function getParams()
+ {
+ return $this->_params;
+ }
+
+ /**
+ * Set action parameters en masse; does not overwrite
+ *
+ * Null values will unset the associated key.
+ *
+ * @param array $array
+ * @return Zend_Controller_Request_Abstract
+ */
+ public function setParams(array $array)
+ {
+ $this->_params = $this->_params + (array) $array;
+
+ foreach ($array as $key => $value) {
+ if (null === $value) {
+ unset($this->_params[$key]);
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Unset all user parameters
+ *
+ * @return Zend_Controller_Request_Abstract
+ */
+ public function clearParams()
+ {
+ $this->_params = array();
+ return $this;
+ }
+
+ /**
+ * Set flag indicating whether or not request has been dispatched
+ *
+ * @param boolean $flag
+ * @return Zend_Controller_Request_Abstract
+ */
+ public function setDispatched($flag = true)
+ {
+ $this->_dispatched = $flag ? true : false;
+ return $this;
+ }
+
+ /**
+ * Determine if the request has been dispatched
+ *
+ * @return boolean
+ */
+ public function isDispatched()
+ {
+ return $this->_dispatched;
+ }
+}
diff --git a/lib/zend/Zend/Controller/Request/Apache404.php b/lib/zend/Zend/Controller/Request/Apache404.php
new file mode 100644
index 00000000000..3c4dd7ac487
--- /dev/null
+++ b/lib/zend/Zend/Controller/Request/Apache404.php
@@ -0,0 +1,82 @@
+_requestUri = $requestUri;
+ return $this;
+ }
+}
diff --git a/lib/zend/Zend/Controller/Request/Exception.php b/lib/zend/Zend/Controller/Request/Exception.php
new file mode 100644
index 00000000000..a7e3629fdab
--- /dev/null
+++ b/lib/zend/Zend/Controller/Request/Exception.php
@@ -0,0 +1,37 @@
+valid()) {
+ $path = $uri->getPath();
+ $query = $uri->getQuery();
+ if (!empty($query)) {
+ $path .= '?' . $query;
+ }
+
+ $this->setRequestUri($path);
+ } else {
+ require_once 'Zend/Controller/Request/Exception.php';
+ throw new Zend_Controller_Request_Exception('Invalid URI provided to constructor');
+ }
+ } else {
+ $this->setRequestUri();
+ }
+ }
+
+ /**
+ * Access values contained in the superglobals as public members
+ * Order of precedence: 1. GET, 2. POST, 3. COOKIE, 4. SERVER, 5. ENV
+ *
+ * @see http://msdn.microsoft.com/en-us/library/system.web.httprequest.item.aspx
+ * @param string $key
+ * @return mixed
+ */
+ public function __get($key)
+ {
+ switch (true) {
+ case isset($this->_params[$key]):
+ return $this->_params[$key];
+ case isset($_GET[$key]):
+ return $_GET[$key];
+ case isset($_POST[$key]):
+ return $_POST[$key];
+ case isset($_COOKIE[$key]):
+ return $_COOKIE[$key];
+ case ($key == 'REQUEST_URI'):
+ return $this->getRequestUri();
+ case ($key == 'PATH_INFO'):
+ return $this->getPathInfo();
+ case isset($_SERVER[$key]):
+ return $_SERVER[$key];
+ case isset($_ENV[$key]):
+ return $_ENV[$key];
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Alias to __get
+ *
+ * @param string $key
+ * @return mixed
+ */
+ public function get($key)
+ {
+ return $this->__get($key);
+ }
+
+ /**
+ * Set values
+ *
+ * In order to follow {@link __get()}, which operates on a number of
+ * superglobals, setting values through overloading is not allowed and will
+ * raise an exception. Use setParam() instead.
+ *
+ * @param string $key
+ * @param mixed $value
+ * @return void
+ * @throws Zend_Controller_Request_Exception
+ */
+ public function __set($key, $value)
+ {
+ require_once 'Zend/Controller/Request/Exception.php';
+ throw new Zend_Controller_Request_Exception('Setting values in superglobals not allowed; please use setParam()');
+ }
+
+ /**
+ * Alias to __set()
+ *
+ * @param string $key
+ * @param mixed $value
+ * @return void
+ */
+ public function set($key, $value)
+ {
+ return $this->__set($key, $value);
+ }
+
+ /**
+ * Check to see if a property is set
+ *
+ * @param string $key
+ * @return boolean
+ */
+ public function __isset($key)
+ {
+ switch (true) {
+ case isset($this->_params[$key]):
+ return true;
+ case isset($_GET[$key]):
+ return true;
+ case isset($_POST[$key]):
+ return true;
+ case isset($_COOKIE[$key]):
+ return true;
+ case isset($_SERVER[$key]):
+ return true;
+ case isset($_ENV[$key]):
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * Alias to __isset()
+ *
+ * @param string $key
+ * @return boolean
+ */
+ public function has($key)
+ {
+ return $this->__isset($key);
+ }
+
+ /**
+ * Set GET values
+ *
+ * @param string|array $spec
+ * @param null|mixed $value
+ * @return Zend_Controller_Request_Http
+ */
+ public function setQuery($spec, $value = null)
+ {
+ if ((null === $value) && !is_array($spec)) {
+ require_once 'Zend/Controller/Exception.php';
+ throw new Zend_Controller_Exception('Invalid value passed to setQuery(); must be either array of values or key/value pair');
+ }
+ if ((null === $value) && is_array($spec)) {
+ foreach ($spec as $key => $value) {
+ $this->setQuery($key, $value);
+ }
+ return $this;
+ }
+ $_GET[(string) $spec] = $value;
+ return $this;
+ }
+
+ /**
+ * Retrieve a member of the $_GET superglobal
+ *
+ * If no $key is passed, returns the entire $_GET array.
+ *
+ * @todo How to retrieve from nested arrays
+ * @param string $key
+ * @param mixed $default Default value to use if key not found
+ * @return mixed Returns null if key does not exist
+ */
+ public function getQuery($key = null, $default = null)
+ {
+ if (null === $key) {
+ return $_GET;
+ }
+
+ return (isset($_GET[$key])) ? $_GET[$key] : $default;
+ }
+
+ /**
+ * Set POST values
+ *
+ * @param string|array $spec
+ * @param null|mixed $value
+ * @return Zend_Controller_Request_Http
+ */
+ public function setPost($spec, $value = null)
+ {
+ if ((null === $value) && !is_array($spec)) {
+ require_once 'Zend/Controller/Exception.php';
+ throw new Zend_Controller_Exception('Invalid value passed to setPost(); must be either array of values or key/value pair');
+ }
+ if ((null === $value) && is_array($spec)) {
+ foreach ($spec as $key => $value) {
+ $this->setPost($key, $value);
+ }
+ return $this;
+ }
+ $_POST[(string) $spec] = $value;
+ return $this;
+ }
+
+ /**
+ * Retrieve a member of the $_POST superglobal
+ *
+ * If no $key is passed, returns the entire $_POST array.
+ *
+ * @todo How to retrieve from nested arrays
+ * @param string $key
+ * @param mixed $default Default value to use if key not found
+ * @return mixed Returns null if key does not exist
+ */
+ public function getPost($key = null, $default = null)
+ {
+ if (null === $key) {
+ return $_POST;
+ }
+
+ return (isset($_POST[$key])) ? $_POST[$key] : $default;
+ }
+
+ /**
+ * Retrieve a member of the $_COOKIE superglobal
+ *
+ * If no $key is passed, returns the entire $_COOKIE array.
+ *
+ * @todo How to retrieve from nested arrays
+ * @param string $key
+ * @param mixed $default Default value to use if key not found
+ * @return mixed Returns null if key does not exist
+ */
+ public function getCookie($key = null, $default = null)
+ {
+ if (null === $key) {
+ return $_COOKIE;
+ }
+
+ return (isset($_COOKIE[$key])) ? $_COOKIE[$key] : $default;
+ }
+
+ /**
+ * Retrieve a member of the $_SERVER superglobal
+ *
+ * If no $key is passed, returns the entire $_SERVER array.
+ *
+ * @param string $key
+ * @param mixed $default Default value to use if key not found
+ * @return mixed Returns null if key does not exist
+ */
+ public function getServer($key = null, $default = null)
+ {
+ if (null === $key) {
+ return $_SERVER;
+ }
+
+ return (isset($_SERVER[$key])) ? $_SERVER[$key] : $default;
+ }
+
+ /**
+ * Retrieve a member of the $_ENV superglobal
+ *
+ * If no $key is passed, returns the entire $_ENV array.
+ *
+ * @param string $key
+ * @param mixed $default Default value to use if key not found
+ * @return mixed Returns null if key does not exist
+ */
+ public function getEnv($key = null, $default = null)
+ {
+ if (null === $key) {
+ return $_ENV;
+ }
+
+ return (isset($_ENV[$key])) ? $_ENV[$key] : $default;
+ }
+
+ /**
+ * Set the REQUEST_URI on which the instance operates
+ *
+ * If no request URI is passed, uses the value in $_SERVER['REQUEST_URI'],
+ * $_SERVER['HTTP_X_REWRITE_URL'], or $_SERVER['ORIG_PATH_INFO'] + $_SERVER['QUERY_STRING'].
+ *
+ * @param string $requestUri
+ * @return Zend_Controller_Request_Http
+ */
+ public function setRequestUri($requestUri = null)
+ {
+ if ($requestUri === null) {
+ if (isset($_SERVER['HTTP_X_ORIGINAL_URL'])) {
+ // IIS with Microsoft Rewrite Module
+ $requestUri = $_SERVER['HTTP_X_ORIGINAL_URL'];
+ } elseif (isset($_SERVER['HTTP_X_REWRITE_URL'])) {
+ // IIS with ISAPI_Rewrite
+ $requestUri = $_SERVER['HTTP_X_REWRITE_URL'];
+ } elseif (
+ // IIS7 with URL Rewrite: make sure we get the unencoded url (double slash problem)
+ isset($_SERVER['IIS_WasUrlRewritten'])
+ && $_SERVER['IIS_WasUrlRewritten'] == '1'
+ && isset($_SERVER['UNENCODED_URL'])
+ && $_SERVER['UNENCODED_URL'] != ''
+ ) {
+ $requestUri = $_SERVER['UNENCODED_URL'];
+ } elseif (isset($_SERVER['REQUEST_URI'])) {
+ $requestUri = $_SERVER['REQUEST_URI'];
+ // Http proxy reqs setup request uri with scheme and host [and port] + the url path, only use url path
+ $schemeAndHttpHost = $this->getScheme() . '://' . $this->getHttpHost();
+ if (strpos($requestUri, $schemeAndHttpHost) === 0) {
+ $requestUri = substr($requestUri, strlen($schemeAndHttpHost));
+ }
+ } elseif (isset($_SERVER['ORIG_PATH_INFO'])) { // IIS 5.0, PHP as CGI
+ $requestUri = $_SERVER['ORIG_PATH_INFO'];
+ if (!empty($_SERVER['QUERY_STRING'])) {
+ $requestUri .= '?' . $_SERVER['QUERY_STRING'];
+ }
+ } else {
+ return $this;
+ }
+ } elseif (!is_string($requestUri)) {
+ return $this;
+ } else {
+ // Set GET items, if available
+ if (false !== ($pos = strpos($requestUri, '?'))) {
+ // Get key => value pairs and set $_GET
+ $query = substr($requestUri, $pos + 1);
+ parse_str($query, $vars);
+ $this->setQuery($vars);
+ }
+ }
+
+ $this->_requestUri = $requestUri;
+ return $this;
+ }
+
+ /**
+ * Returns the REQUEST_URI taking into account
+ * platform differences between Apache and IIS
+ *
+ * @return string
+ */
+ public function getRequestUri()
+ {
+ if (empty($this->_requestUri)) {
+ $this->setRequestUri();
+ }
+
+ return $this->_requestUri;
+ }
+
+ /**
+ * Set the base URL of the request; i.e., the segment leading to the script name
+ *
+ * E.g.:
+ * - /admin
+ * - /myapp
+ * - /subdir/index.php
+ *
+ * Do not use the full URI when providing the base. The following are
+ * examples of what not to use:
+ * - http://example.com/admin (should be just /admin)
+ * - http://example.com/subdir/index.php (should be just /subdir/index.php)
+ *
+ * If no $baseUrl is provided, attempts to determine the base URL from the
+ * environment, using SCRIPT_FILENAME, SCRIPT_NAME, PHP_SELF, and
+ * ORIG_SCRIPT_NAME in its determination.
+ *
+ * @param mixed $baseUrl
+ * @return Zend_Controller_Request_Http
+ */
+ public function setBaseUrl($baseUrl = null)
+ {
+ if ((null !== $baseUrl) && !is_string($baseUrl)) {
+ return $this;
+ }
+
+ if ($baseUrl === null) {
+ $filename = (isset($_SERVER['SCRIPT_FILENAME'])) ? basename($_SERVER['SCRIPT_FILENAME']) : '';
+
+ if (isset($_SERVER['SCRIPT_NAME']) && basename($_SERVER['SCRIPT_NAME']) === $filename) {
+ $baseUrl = $_SERVER['SCRIPT_NAME'];
+ } elseif (isset($_SERVER['PHP_SELF']) && basename($_SERVER['PHP_SELF']) === $filename) {
+ $baseUrl = $_SERVER['PHP_SELF'];
+ } elseif (isset($_SERVER['ORIG_SCRIPT_NAME']) && basename($_SERVER['ORIG_SCRIPT_NAME']) === $filename) {
+ $baseUrl = $_SERVER['ORIG_SCRIPT_NAME']; // 1and1 shared hosting compatibility
+ } else {
+ // Backtrack up the script_filename to find the portion matching
+ // php_self
+ $path = isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : '';
+ $file = isset($_SERVER['SCRIPT_FILENAME']) ? $_SERVER['SCRIPT_FILENAME'] : '';
+ $segs = explode('/', trim($file, '/'));
+ $segs = array_reverse($segs);
+ $index = 0;
+ $last = count($segs);
+ $baseUrl = '';
+ do {
+ $seg = $segs[$index];
+ $baseUrl = '/' . $seg . $baseUrl;
+ ++$index;
+ } while (($last > $index) && (false !== ($pos = strpos($path, $baseUrl))) && (0 != $pos));
+ }
+
+ // Does the baseUrl have anything in common with the request_uri?
+ $requestUri = $this->getRequestUri();
+
+ if (0 === strpos($requestUri, $baseUrl)) {
+ // full $baseUrl matches
+ $this->_baseUrl = $baseUrl;
+ return $this;
+ }
+
+ if (0 === strpos($requestUri, dirname($baseUrl))) {
+ // directory portion of $baseUrl matches
+ $this->_baseUrl = rtrim(dirname($baseUrl), '/');
+ return $this;
+ }
+
+ $truncatedRequestUri = $requestUri;
+ if (($pos = strpos($requestUri, '?')) !== false) {
+ $truncatedRequestUri = substr($requestUri, 0, $pos);
+ }
+
+ $basename = basename($baseUrl);
+ if (empty($basename) || !strpos($truncatedRequestUri, $basename)) {
+ // no match whatsoever; set it blank
+ $this->_baseUrl = '';
+ return $this;
+ }
+
+ // If using mod_rewrite or ISAPI_Rewrite strip the script filename
+ // out of baseUrl. $pos !== 0 makes sure it is not matching a value
+ // from PATH_INFO or QUERY_STRING
+ if ((strlen($requestUri) >= strlen($baseUrl))
+ && ((false !== ($pos = strpos($requestUri, $baseUrl))) && ($pos !== 0)))
+ {
+ $baseUrl = substr($requestUri, 0, $pos + strlen($baseUrl));
+ }
+ }
+
+ $this->_baseUrl = rtrim($baseUrl, '/');
+ return $this;
+ }
+
+ /**
+ * Everything in REQUEST_URI before PATH_INFO
+ *
+ *
+ * @return string
+ */
+ public function getBaseUrl($raw = false)
+ {
+ if (null === $this->_baseUrl) {
+ $this->setBaseUrl();
+ }
+
+ return (($raw == false) ? urldecode($this->_baseUrl) : $this->_baseUrl);
+ }
+
+ /**
+ * Set the base path for the URL
+ *
+ * @param string|null $basePath
+ * @return Zend_Controller_Request_Http
+ */
+ public function setBasePath($basePath = null)
+ {
+ if ($basePath === null) {
+ $filename = (isset($_SERVER['SCRIPT_FILENAME']))
+ ? basename($_SERVER['SCRIPT_FILENAME'])
+ : '';
+
+ $baseUrl = $this->getBaseUrl();
+ if (empty($baseUrl)) {
+ $this->_basePath = '';
+ return $this;
+ }
+
+ if (basename($baseUrl) === $filename) {
+ $basePath = dirname($baseUrl);
+ } else {
+ $basePath = $baseUrl;
+ }
+ }
+
+ if (substr(PHP_OS, 0, 3) === 'WIN') {
+ $basePath = str_replace('\\', '/', $basePath);
+ }
+
+ $this->_basePath = rtrim($basePath, '/');
+ return $this;
+ }
+
+ /**
+ * Everything in REQUEST_URI before PATH_INFO not including the filename
+ *
+ *
+ * @return string
+ */
+ public function getBasePath()
+ {
+ if (null === $this->_basePath) {
+ $this->setBasePath();
+ }
+
+ return $this->_basePath;
+ }
+
+ /**
+ * Set the PATH_INFO string
+ *
+ * @param string|null $pathInfo
+ * @return Zend_Controller_Request_Http
+ */
+ public function setPathInfo($pathInfo = null)
+ {
+ if ($pathInfo === null) {
+ $baseUrl = $this->getBaseUrl(); // this actually calls setBaseUrl() & setRequestUri()
+ $baseUrlRaw = $this->getBaseUrl(false);
+ $baseUrlEncoded = urlencode($baseUrlRaw);
+
+ if (null === ($requestUri = $this->getRequestUri())) {
+ return $this;
+ }
+
+ // Remove the query string from REQUEST_URI
+ if ($pos = strpos($requestUri, '?')) {
+ $requestUri = substr($requestUri, 0, $pos);
+ }
+
+ if (!empty($baseUrl) || !empty($baseUrlRaw)) {
+ if (strpos($requestUri, $baseUrl) === 0) {
+ $pathInfo = substr($requestUri, strlen($baseUrl));
+ } elseif (strpos($requestUri, $baseUrlRaw) === 0) {
+ $pathInfo = substr($requestUri, strlen($baseUrlRaw));
+ } elseif (strpos($requestUri, $baseUrlEncoded) === 0) {
+ $pathInfo = substr($requestUri, strlen($baseUrlEncoded));
+ } else {
+ $pathInfo = $requestUri;
+ }
+ } else {
+ $pathInfo = $requestUri;
+ }
+
+ }
+
+ $this->_pathInfo = (string) $pathInfo;
+ return $this;
+ }
+
+ /**
+ * Returns everything between the BaseUrl and QueryString.
+ * This value is calculated instead of reading PATH_INFO
+ * directly from $_SERVER due to cross-platform differences.
+ *
+ * @return string
+ */
+ public function getPathInfo()
+ {
+ if (empty($this->_pathInfo)) {
+ $this->setPathInfo();
+ }
+
+ return $this->_pathInfo;
+ }
+
+ /**
+ * Set allowed parameter sources
+ *
+ * Can be empty array, or contain one or more of '_GET' or '_POST'.
+ *
+ * @param array $paramSoures
+ * @return Zend_Controller_Request_Http
+ */
+ public function setParamSources(array $paramSources = array())
+ {
+ $this->_paramSources = $paramSources;
+ return $this;
+ }
+
+ /**
+ * Get list of allowed parameter sources
+ *
+ * @return array
+ */
+ public function getParamSources()
+ {
+ return $this->_paramSources;
+ }
+
+ /**
+ * Set a userland parameter
+ *
+ * Uses $key to set a userland parameter. If $key is an alias, the actual
+ * key will be retrieved and used to set the parameter.
+ *
+ * @param mixed $key
+ * @param mixed $value
+ * @return Zend_Controller_Request_Http
+ */
+ public function setParam($key, $value)
+ {
+ $key = (null !== ($alias = $this->getAlias($key))) ? $alias : $key;
+ parent::setParam($key, $value);
+ return $this;
+ }
+
+ /**
+ * Retrieve a parameter
+ *
+ * Retrieves a parameter from the instance. Priority is in the order of
+ * userland parameters (see {@link setParam()}), $_GET, $_POST. If a
+ * parameter matching the $key is not found, null is returned.
+ *
+ * If the $key is an alias, the actual key aliased will be used.
+ *
+ * @param mixed $key
+ * @param mixed $default Default value to use if key not found
+ * @return mixed
+ */
+ public function getParam($key, $default = null)
+ {
+ $keyName = (null !== ($alias = $this->getAlias($key))) ? $alias : $key;
+
+ $paramSources = $this->getParamSources();
+ if (isset($this->_params[$keyName])) {
+ return $this->_params[$keyName];
+ } elseif (in_array('_GET', $paramSources) && (isset($_GET[$keyName]))) {
+ return $_GET[$keyName];
+ } elseif (in_array('_POST', $paramSources) && (isset($_POST[$keyName]))) {
+ return $_POST[$keyName];
+ }
+
+ return $default;
+ }
+
+ /**
+ * Retrieve an array of parameters
+ *
+ * Retrieves a merged array of parameters, with precedence of userland
+ * params (see {@link setParam()}), $_GET, $_POST (i.e., values in the
+ * userland params will take precedence over all others).
+ *
+ * @return array
+ */
+ public function getParams()
+ {
+ $return = $this->_params;
+ $paramSources = $this->getParamSources();
+ if (in_array('_GET', $paramSources)
+ && isset($_GET)
+ && is_array($_GET)
+ ) {
+ $return += $_GET;
+ }
+ if (in_array('_POST', $paramSources)
+ && isset($_POST)
+ && is_array($_POST)
+ ) {
+ $return += $_POST;
+ }
+ return $return;
+ }
+
+ /**
+ * Set parameters
+ *
+ * Set one or more parameters. Parameters are set as userland parameters,
+ * using the keys specified in the array.
+ *
+ * @param array $params
+ * @return Zend_Controller_Request_Http
+ */
+ public function setParams(array $params)
+ {
+ foreach ($params as $key => $value) {
+ $this->setParam($key, $value);
+ }
+ return $this;
+ }
+
+ /**
+ * Set a key alias
+ *
+ * Set an alias used for key lookups. $name specifies the alias, $target
+ * specifies the actual key to use.
+ *
+ * @param string $name
+ * @param string $target
+ * @return Zend_Controller_Request_Http
+ */
+ public function setAlias($name, $target)
+ {
+ $this->_aliases[$name] = $target;
+ return $this;
+ }
+
+ /**
+ * Retrieve an alias
+ *
+ * Retrieve the actual key represented by the alias $name.
+ *
+ * @param string $name
+ * @return string|null Returns null when no alias exists
+ */
+ public function getAlias($name)
+ {
+ if (isset($this->_aliases[$name])) {
+ return $this->_aliases[$name];
+ }
+
+ return null;
+ }
+
+ /**
+ * Retrieve the list of all aliases
+ *
+ * @return array
+ */
+ public function getAliases()
+ {
+ return $this->_aliases;
+ }
+
+ /**
+ * Return the method by which the request was made
+ *
+ * @return string
+ */
+ public function getMethod()
+ {
+ return $this->getServer('REQUEST_METHOD');
+ }
+
+ /**
+ * Was the request made by POST?
+ *
+ * @return boolean
+ */
+ public function isPost()
+ {
+ if ('POST' == $this->getMethod()) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Was the request made by GET?
+ *
+ * @return boolean
+ */
+ public function isGet()
+ {
+ if ('GET' == $this->getMethod()) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Was the request made by PUT?
+ *
+ * @return boolean
+ */
+ public function isPut()
+ {
+ if ('PUT' == $this->getMethod()) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Was the request made by DELETE?
+ *
+ * @return boolean
+ */
+ public function isDelete()
+ {
+ if ('DELETE' == $this->getMethod()) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Was the request made by HEAD?
+ *
+ * @return boolean
+ */
+ public function isHead()
+ {
+ if ('HEAD' == $this->getMethod()) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Was the request made by OPTIONS?
+ *
+ * @return boolean
+ */
+ public function isOptions()
+ {
+ if ('OPTIONS' == $this->getMethod()) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Was the request made by PATCH?
+ *
+ * @return boolean
+ */
+ public function isPatch()
+ {
+ if ('PATCH' == $this->getMethod()) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Is the request a Javascript XMLHttpRequest?
+ *
+ * Should work with Prototype/Script.aculo.us, possibly others.
+ *
+ * @return boolean
+ */
+ public function isXmlHttpRequest()
+ {
+ return ($this->getHeader('X_REQUESTED_WITH') == 'XMLHttpRequest');
+ }
+
+ /**
+ * Is this a Flash request?
+ *
+ * @return boolean
+ */
+ public function isFlashRequest()
+ {
+ $header = strtolower($this->getHeader('USER_AGENT'));
+ return (strstr($header, ' flash')) ? true : false;
+ }
+
+ /**
+ * Is https secure request
+ *
+ * @return boolean
+ */
+ public function isSecure()
+ {
+ return ($this->getScheme() === self::SCHEME_HTTPS);
+ }
+
+ /**
+ * Return the raw body of the request, if present
+ *
+ * @return string|false Raw body, or false if not present
+ */
+ public function getRawBody()
+ {
+ if (null === $this->_rawBody) {
+ $body = file_get_contents('php://input');
+
+ if (strlen(trim($body)) > 0) {
+ $this->_rawBody = $body;
+ } else {
+ $this->_rawBody = false;
+ }
+ }
+ return $this->_rawBody;
+ }
+
+ /**
+ * Return the value of the given HTTP header. Pass the header name as the
+ * plain, HTTP-specified header name. Ex.: Ask for 'Accept' to get the
+ * Accept header, 'Accept-Encoding' to get the Accept-Encoding header.
+ *
+ * @param string $header HTTP header name
+ * @return string|false HTTP header value, or false if not found
+ * @throws Zend_Controller_Request_Exception
+ */
+ public function getHeader($header)
+ {
+ if (empty($header)) {
+ require_once 'Zend/Controller/Request/Exception.php';
+ throw new Zend_Controller_Request_Exception('An HTTP header name is required');
+ }
+
+ // Try to get it from the $_SERVER array first
+ $temp = strtoupper(str_replace('-', '_', $header));
+ if (isset($_SERVER['HTTP_' . $temp])) {
+ return $_SERVER['HTTP_' . $temp];
+ }
+
+ /*
+ * Try to get it from the $_SERVER array on POST request or CGI environment
+ * @see https://www.ietf.org/rfc/rfc3875 (4.1.2. and 4.1.3.)
+ */
+ if (isset($_SERVER[$temp])
+ && in_array($temp, array('CONTENT_TYPE', 'CONTENT_LENGTH'))
+ ) {
+ return $_SERVER[$temp];
+ }
+
+ // This seems to be the only way to get the Authorization header on
+ // Apache
+ if (function_exists('apache_request_headers')) {
+ $headers = apache_request_headers();
+ if (isset($headers[$header])) {
+ return $headers[$header];
+ }
+ $header = strtolower($header);
+ foreach ($headers as $key => $value) {
+ if (strtolower($key) == $header) {
+ return $value;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Get the request URI scheme
+ *
+ * @return string
+ */
+ public function getScheme()
+ {
+ return ($this->getServer('HTTPS') == 'on') ? self::SCHEME_HTTPS : self::SCHEME_HTTP;
+ }
+
+ /**
+ * Get the HTTP host.
+ *
+ * "Host" ":" host [ ":" port ] ; Section 3.2.2
+ * Note the HTTP Host header is not the same as the URI host.
+ * It includes the port while the URI host doesn't.
+ *
+ * @return string
+ */
+ public function getHttpHost()
+ {
+ $host = $this->getServer('HTTP_HOST');
+ if (!empty($host)) {
+ return $host;
+ }
+
+ $scheme = $this->getScheme();
+ $name = $this->getServer('SERVER_NAME');
+ $port = $this->getServer('SERVER_PORT');
+
+ if(null === $name) {
+ return '';
+ }
+ elseif (($scheme == self::SCHEME_HTTP && $port == 80) || ($scheme == self::SCHEME_HTTPS && $port == 443)) {
+ return $name;
+ } else {
+ return $name . ':' . $port;
+ }
+ }
+
+ /**
+ * Get the client's IP addres
+ *
+ * @param boolean $checkProxy
+ * @return string
+ */
+ public function getClientIp($checkProxy = true)
+ {
+ if ($checkProxy && $this->getServer('HTTP_CLIENT_IP') != null) {
+ $ip = $this->getServer('HTTP_CLIENT_IP');
+ } else if ($checkProxy && $this->getServer('HTTP_X_FORWARDED_FOR') != null) {
+ $ip = $this->getServer('HTTP_X_FORWARDED_FOR');
+ } else {
+ $ip = $this->getServer('REMOTE_ADDR');
+ }
+
+ return $ip;
+ }
+}
diff --git a/lib/zend/Zend/Controller/Request/HttpTestCase.php b/lib/zend/Zend/Controller/Request/HttpTestCase.php
new file mode 100644
index 00000000000..58b9bd3936a
--- /dev/null
+++ b/lib/zend/Zend/Controller/Request/HttpTestCase.php
@@ -0,0 +1,277 @@
+_rawBody = (string) $content;
+ return $this;
+ }
+
+ /**
+ * Get RAW POST body
+ *
+ * @return string|null
+ */
+ public function getRawBody()
+ {
+ return $this->_rawBody;
+ }
+
+ /**
+ * Clear raw POST body
+ *
+ * @return Zend_Controller_Request_HttpTestCase
+ */
+ public function clearRawBody()
+ {
+ $this->_rawBody = null;
+ return $this;
+ }
+
+ /**
+ * Set a cookie
+ *
+ * @param string $key
+ * @param mixed $value
+ * @return Zend_Controller_Request_HttpTestCase
+ */
+ public function setCookie($key, $value)
+ {
+ $_COOKIE[(string) $key] = $value;
+ return $this;
+ }
+
+ /**
+ * Set multiple cookies at once
+ *
+ * @param array $cookies
+ * @return void
+ */
+ public function setCookies(array $cookies)
+ {
+ foreach ($cookies as $key => $value) {
+ $_COOKIE[$key] = $value;
+ }
+ return $this;
+ }
+
+ /**
+ * Clear all cookies
+ *
+ * @return Zend_Controller_Request_HttpTestCase
+ */
+ public function clearCookies()
+ {
+ $_COOKIE = array();
+ return $this;
+ }
+
+ /**
+ * Set request method
+ *
+ * @param string $type
+ * @return Zend_Controller_Request_HttpTestCase
+ */
+ public function setMethod($type)
+ {
+ $type = strtoupper(trim((string) $type));
+ if (!in_array($type, $this->_validMethodTypes)) {
+ require_once 'Zend/Controller/Exception.php';
+ throw new Zend_Controller_Exception('Invalid request method specified');
+ }
+ $this->_method = $type;
+ return $this;
+ }
+
+ /**
+ * Get request method
+ *
+ * @return string|null
+ */
+ public function getMethod()
+ {
+ return $this->_method;
+ }
+
+ /**
+ * Set a request header
+ *
+ * @param string $key
+ * @param string $value
+ * @return Zend_Controller_Request_HttpTestCase
+ */
+ public function setHeader($key, $value)
+ {
+ $key = $this->_normalizeHeaderName($key);
+ $this->_headers[$key] = (string) $value;
+ return $this;
+ }
+
+ /**
+ * Set request headers
+ *
+ * @param array $headers
+ * @return Zend_Controller_Request_HttpTestCase
+ */
+ public function setHeaders(array $headers)
+ {
+ foreach ($headers as $key => $value) {
+ $this->setHeader($key, $value);
+ }
+ return $this;
+ }
+
+ /**
+ * Get request header
+ *
+ * @param string $header
+ * @param mixed $default
+ * @return string|null
+ */
+ public function getHeader($header, $default = null)
+ {
+ $header = $this->_normalizeHeaderName($header);
+ if (array_key_exists($header, $this->_headers)) {
+ return $this->_headers[$header];
+ }
+ return $default;
+ }
+
+ /**
+ * Get all request headers
+ *
+ * @return array
+ */
+ public function getHeaders()
+ {
+ return $this->_headers;
+ }
+
+ /**
+ * Clear request headers
+ *
+ * @return Zend_Controller_Request_HttpTestCase
+ */
+ public function clearHeaders()
+ {
+ $this->_headers = array();
+ return $this;
+ }
+
+ /**
+ * Get REQUEST_URI
+ *
+ * @return null|string
+ */
+ public function getRequestUri()
+ {
+ return $this->_requestUri;
+ }
+
+ /**
+ * Normalize a header name for setting and retrieval
+ *
+ * @param string $name
+ * @return string
+ */
+ protected function _normalizeHeaderName($name)
+ {
+ $name = strtoupper((string) $name);
+ $name = str_replace('-', '_', $name);
+ return $name;
+ }
+}
diff --git a/lib/zend/Zend/Controller/Request/Simple.php b/lib/zend/Zend/Controller/Request/Simple.php
new file mode 100644
index 00000000000..74e4b0c4a10
--- /dev/null
+++ b/lib/zend/Zend/Controller/Request/Simple.php
@@ -0,0 +1,55 @@
+setActionName($action);
+ }
+
+ if ($controller) {
+ $this->setControllerName($controller);
+ }
+
+ if ($module) {
+ $this->setModuleName($module);
+ }
+
+ if ($params) {
+ $this->setParams($params);
+ }
+ }
+
+}
diff --git a/lib/zend/Zend/Controller/Response/Abstract.php b/lib/zend/Zend/Controller/Response/Abstract.php
new file mode 100644
index 00000000000..9fcc22693e5
--- /dev/null
+++ b/lib/zend/Zend/Controller/Response/Abstract.php
@@ -0,0 +1,796 @@
+canSendHeaders(true);
+ $name = $this->_normalizeHeader($name);
+ $value = (string) $value;
+
+ if ($replace) {
+ foreach ($this->_headers as $key => $header) {
+ if ($name == $header['name']) {
+ unset($this->_headers[$key]);
+ }
+ }
+ }
+
+ $this->_headers[] = array(
+ 'name' => $name,
+ 'value' => $value,
+ 'replace' => $replace
+ );
+
+ return $this;
+ }
+
+ /**
+ * Set redirect URL
+ *
+ * Sets Location header and response code. Forces replacement of any prior
+ * redirects.
+ *
+ * @param string $url
+ * @param int $code
+ * @return Zend_Controller_Response_Abstract
+ */
+ public function setRedirect($url, $code = 302)
+ {
+ $this->canSendHeaders(true);
+ $this->setHeader('Location', $url, true)
+ ->setHttpResponseCode($code);
+
+ return $this;
+ }
+
+ /**
+ * Is this a redirect?
+ *
+ * @return boolean
+ */
+ public function isRedirect()
+ {
+ return $this->_isRedirect;
+ }
+
+ /**
+ * Return array of headers; see {@link $_headers} for format
+ *
+ * @return array
+ */
+ public function getHeaders()
+ {
+ return $this->_headers;
+ }
+
+ /**
+ * Clear headers
+ *
+ * @return Zend_Controller_Response_Abstract
+ */
+ public function clearHeaders()
+ {
+ $this->_headers = array();
+
+ return $this;
+ }
+
+ /**
+ * Clears the specified HTTP header
+ *
+ * @param string $name
+ * @return Zend_Controller_Response_Abstract
+ */
+ public function clearHeader($name)
+ {
+ if (! count($this->_headers)) {
+ return $this;
+ }
+
+ foreach ($this->_headers as $index => $header) {
+ if ($name == $header['name']) {
+ unset($this->_headers[$index]);
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Set raw HTTP header
+ *
+ * Allows setting non key => value headers, such as status codes
+ *
+ * @param string $value
+ * @return Zend_Controller_Response_Abstract
+ */
+ public function setRawHeader($value)
+ {
+ $this->canSendHeaders(true);
+ if ('Location' == substr($value, 0, 8)) {
+ $this->_isRedirect = true;
+ }
+ $this->_headersRaw[] = (string) $value;
+ return $this;
+ }
+
+ /**
+ * Retrieve all {@link setRawHeader() raw HTTP headers}
+ *
+ * @return array
+ */
+ public function getRawHeaders()
+ {
+ return $this->_headersRaw;
+ }
+
+ /**
+ * Clear all {@link setRawHeader() raw HTTP headers}
+ *
+ * @return Zend_Controller_Response_Abstract
+ */
+ public function clearRawHeaders()
+ {
+ $this->_headersRaw = array();
+ return $this;
+ }
+
+ /**
+ * Clears the specified raw HTTP header
+ *
+ * @param string $headerRaw
+ * @return Zend_Controller_Response_Abstract
+ */
+ public function clearRawHeader($headerRaw)
+ {
+ if (! count($this->_headersRaw)) {
+ return $this;
+ }
+
+ $key = array_search($headerRaw, $this->_headersRaw);
+ if ($key !== false) {
+ unset($this->_headersRaw[$key]);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Clear all headers, normal and raw
+ *
+ * @return Zend_Controller_Response_Abstract
+ */
+ public function clearAllHeaders()
+ {
+ return $this->clearHeaders()
+ ->clearRawHeaders();
+ }
+
+ /**
+ * Set HTTP response code to use with headers
+ *
+ * @param int $code
+ * @return Zend_Controller_Response_Abstract
+ */
+ public function setHttpResponseCode($code)
+ {
+ if (!is_int($code) || (100 > $code) || (599 < $code)) {
+ require_once 'Zend/Controller/Response/Exception.php';
+ throw new Zend_Controller_Response_Exception('Invalid HTTP response code');
+ }
+
+ if ((300 <= $code) && (307 >= $code)) {
+ $this->_isRedirect = true;
+ } else {
+ $this->_isRedirect = false;
+ }
+
+ $this->_httpResponseCode = $code;
+ return $this;
+ }
+
+ /**
+ * Retrieve HTTP response code
+ *
+ * @return int
+ */
+ public function getHttpResponseCode()
+ {
+ return $this->_httpResponseCode;
+ }
+
+ /**
+ * Can we send headers?
+ *
+ * @param boolean $throw Whether or not to throw an exception if headers have been sent; defaults to false
+ * @return boolean
+ * @throws Zend_Controller_Response_Exception
+ */
+ public function canSendHeaders($throw = false)
+ {
+ $ok = headers_sent($file, $line);
+ if ($ok && $throw && $this->headersSentThrowsException) {
+ require_once 'Zend/Controller/Response/Exception.php';
+ throw new Zend_Controller_Response_Exception('Cannot send headers; headers already sent in ' . $file . ', line ' . $line);
+ }
+
+ return !$ok;
+ }
+
+ /**
+ * Send all headers
+ *
+ * Sends any headers specified. If an {@link setHttpResponseCode() HTTP response code}
+ * has been specified, it is sent with the first header.
+ *
+ * @return Zend_Controller_Response_Abstract
+ */
+ public function sendHeaders()
+ {
+ // Only check if we can send headers if we have headers to send
+ if (count($this->_headersRaw) || count($this->_headers) || (200 != $this->_httpResponseCode)) {
+ $this->canSendHeaders(true);
+ } elseif (200 == $this->_httpResponseCode) {
+ // Haven't changed the response code, and we have no headers
+ return $this;
+ }
+
+ $httpCodeSent = false;
+
+ foreach ($this->_headersRaw as $header) {
+ if (!$httpCodeSent && $this->_httpResponseCode) {
+ header($header, true, $this->_httpResponseCode);
+ $httpCodeSent = true;
+ } else {
+ header($header);
+ }
+ }
+
+ foreach ($this->_headers as $header) {
+ if (!$httpCodeSent && $this->_httpResponseCode) {
+ header($header['name'] . ': ' . $header['value'], $header['replace'], $this->_httpResponseCode);
+ $httpCodeSent = true;
+ } else {
+ header($header['name'] . ': ' . $header['value'], $header['replace']);
+ }
+ }
+
+ if (!$httpCodeSent) {
+ header('HTTP/1.1 ' . $this->_httpResponseCode);
+ $httpCodeSent = true;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Set body content
+ *
+ * If $name is not passed, or is not a string, resets the entire body and
+ * sets the 'default' key to $content.
+ *
+ * If $name is a string, sets the named segment in the body array to
+ * $content.
+ *
+ * @param string $content
+ * @param null|string $name
+ * @return Zend_Controller_Response_Abstract
+ */
+ public function setBody($content, $name = null)
+ {
+ if ((null === $name) || !is_string($name)) {
+ $this->_body = array('default' => (string) $content);
+ } else {
+ $this->_body[$name] = (string) $content;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Append content to the body content
+ *
+ * @param string $content
+ * @param null|string $name
+ * @return Zend_Controller_Response_Abstract
+ */
+ public function appendBody($content, $name = null)
+ {
+ if ((null === $name) || !is_string($name)) {
+ if (isset($this->_body['default'])) {
+ $this->_body['default'] .= (string) $content;
+ } else {
+ return $this->append('default', $content);
+ }
+ } elseif (isset($this->_body[$name])) {
+ $this->_body[$name] .= (string) $content;
+ } else {
+ return $this->append($name, $content);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Clear body array
+ *
+ * With no arguments, clears the entire body array. Given a $name, clears
+ * just that named segment; if no segment matching $name exists, returns
+ * false to indicate an error.
+ *
+ * @param string $name Named segment to clear
+ * @return boolean
+ */
+ public function clearBody($name = null)
+ {
+ if (null !== $name) {
+ $name = (string) $name;
+ if (isset($this->_body[$name])) {
+ unset($this->_body[$name]);
+ return true;
+ }
+
+ return false;
+ }
+
+ $this->_body = array();
+ return true;
+ }
+
+ /**
+ * Return the body content
+ *
+ * If $spec is false, returns the concatenated values of the body content
+ * array. If $spec is boolean true, returns the body content array. If
+ * $spec is a string and matches a named segment, returns the contents of
+ * that segment; otherwise, returns null.
+ *
+ * @param boolean $spec
+ * @return string|array|null
+ */
+ public function getBody($spec = false)
+ {
+ if (false === $spec) {
+ ob_start();
+ $this->outputBody();
+ return ob_get_clean();
+ } elseif (true === $spec) {
+ return $this->_body;
+ } elseif (is_string($spec) && isset($this->_body[$spec])) {
+ return $this->_body[$spec];
+ }
+
+ return null;
+ }
+
+ /**
+ * Append a named body segment to the body content array
+ *
+ * If segment already exists, replaces with $content and places at end of
+ * array.
+ *
+ * @param string $name
+ * @param string $content
+ * @return Zend_Controller_Response_Abstract
+ */
+ public function append($name, $content)
+ {
+ if (!is_string($name)) {
+ require_once 'Zend/Controller/Response/Exception.php';
+ throw new Zend_Controller_Response_Exception('Invalid body segment key ("' . gettype($name) . '")');
+ }
+
+ if (isset($this->_body[$name])) {
+ unset($this->_body[$name]);
+ }
+ $this->_body[$name] = (string) $content;
+ return $this;
+ }
+
+ /**
+ * Prepend a named body segment to the body content array
+ *
+ * If segment already exists, replaces with $content and places at top of
+ * array.
+ *
+ * @param string $name
+ * @param string $content
+ * @return void
+ */
+ public function prepend($name, $content)
+ {
+ if (!is_string($name)) {
+ require_once 'Zend/Controller/Response/Exception.php';
+ throw new Zend_Controller_Response_Exception('Invalid body segment key ("' . gettype($name) . '")');
+ }
+
+ if (isset($this->_body[$name])) {
+ unset($this->_body[$name]);
+ }
+
+ $new = array($name => (string) $content);
+ $this->_body = $new + $this->_body;
+
+ return $this;
+ }
+
+ /**
+ * Insert a named segment into the body content array
+ *
+ * @param string $name
+ * @param string $content
+ * @param string $parent
+ * @param boolean $before Whether to insert the new segment before or
+ * after the parent. Defaults to false (after)
+ * @return Zend_Controller_Response_Abstract
+ */
+ public function insert($name, $content, $parent = null, $before = false)
+ {
+ if (!is_string($name)) {
+ require_once 'Zend/Controller/Response/Exception.php';
+ throw new Zend_Controller_Response_Exception('Invalid body segment key ("' . gettype($name) . '")');
+ }
+
+ if ((null !== $parent) && !is_string($parent)) {
+ require_once 'Zend/Controller/Response/Exception.php';
+ throw new Zend_Controller_Response_Exception('Invalid body segment parent key ("' . gettype($parent) . '")');
+ }
+
+ if (isset($this->_body[$name])) {
+ unset($this->_body[$name]);
+ }
+
+ if ((null === $parent) || !isset($this->_body[$parent])) {
+ return $this->append($name, $content);
+ }
+
+ $ins = array($name => (string) $content);
+ $keys = array_keys($this->_body);
+ $loc = array_search($parent, $keys);
+ if (!$before) {
+ // Increment location if not inserting before
+ ++$loc;
+ }
+
+ if (0 === $loc) {
+ // If location of key is 0, we're prepending
+ $this->_body = $ins + $this->_body;
+ } elseif ($loc >= (count($this->_body))) {
+ // If location of key is maximal, we're appending
+ $this->_body = $this->_body + $ins;
+ } else {
+ // Otherwise, insert at location specified
+ $pre = array_slice($this->_body, 0, $loc);
+ $post = array_slice($this->_body, $loc);
+ $this->_body = $pre + $ins + $post;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Echo the body segments
+ *
+ * @return void
+ */
+ public function outputBody()
+ {
+ $body = implode('', $this->_body);
+ echo $body;
+ }
+
+ /**
+ * Register an exception with the response
+ *
+ * @param Exception $e
+ * @return Zend_Controller_Response_Abstract
+ */
+ public function setException(Exception $e)
+ {
+ $this->_exceptions[] = $e;
+ return $this;
+ }
+
+ /**
+ * Retrieve the exception stack
+ *
+ * @return array
+ */
+ public function getException()
+ {
+ return $this->_exceptions;
+ }
+
+ /**
+ * Has an exception been registered with the response?
+ *
+ * @return boolean
+ */
+ public function isException()
+ {
+ return !empty($this->_exceptions);
+ }
+
+ /**
+ * Does the response object contain an exception of a given type?
+ *
+ * @param string $type
+ * @return boolean
+ */
+ public function hasExceptionOfType($type)
+ {
+ foreach ($this->_exceptions as $e) {
+ if ($e instanceof $type) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Does the response object contain an exception with a given message?
+ *
+ * @param string $message
+ * @return boolean
+ */
+ public function hasExceptionOfMessage($message)
+ {
+ foreach ($this->_exceptions as $e) {
+ if ($message == $e->getMessage()) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Does the response object contain an exception with a given code?
+ *
+ * @param int $code
+ * @return boolean
+ */
+ public function hasExceptionOfCode($code)
+ {
+ $code = (int) $code;
+ foreach ($this->_exceptions as $e) {
+ if ($code == $e->getCode()) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Retrieve all exceptions of a given type
+ *
+ * @param string $type
+ * @return false|array
+ */
+ public function getExceptionByType($type)
+ {
+ $exceptions = array();
+ foreach ($this->_exceptions as $e) {
+ if ($e instanceof $type) {
+ $exceptions[] = $e;
+ }
+ }
+
+ if (empty($exceptions)) {
+ $exceptions = false;
+ }
+
+ return $exceptions;
+ }
+
+ /**
+ * Retrieve all exceptions of a given message
+ *
+ * @param string $message
+ * @return false|array
+ */
+ public function getExceptionByMessage($message)
+ {
+ $exceptions = array();
+ foreach ($this->_exceptions as $e) {
+ if ($message == $e->getMessage()) {
+ $exceptions[] = $e;
+ }
+ }
+
+ if (empty($exceptions)) {
+ $exceptions = false;
+ }
+
+ return $exceptions;
+ }
+
+ /**
+ * Retrieve all exceptions of a given code
+ *
+ * @param mixed $code
+ * @return void
+ */
+ public function getExceptionByCode($code)
+ {
+ $code = (int) $code;
+ $exceptions = array();
+ foreach ($this->_exceptions as $e) {
+ if ($code == $e->getCode()) {
+ $exceptions[] = $e;
+ }
+ }
+
+ if (empty($exceptions)) {
+ $exceptions = false;
+ }
+
+ return $exceptions;
+ }
+
+ /**
+ * Whether or not to render exceptions (off by default)
+ *
+ * If called with no arguments or a null argument, returns the value of the
+ * flag; otherwise, sets it and returns the current value.
+ *
+ * @param boolean $flag Optional
+ * @return boolean
+ */
+ public function renderExceptions($flag = null)
+ {
+ if (null !== $flag) {
+ $this->_renderExceptions = $flag ? true : false;
+ }
+
+ return $this->_renderExceptions;
+ }
+
+ /**
+ * Send the response, including all headers, rendering exceptions if so
+ * requested.
+ *
+ * @return void
+ */
+ public function sendResponse()
+ {
+ $this->sendHeaders();
+
+ if ($this->isException() && $this->renderExceptions()) {
+ $exceptions = '';
+ foreach ($this->getException() as $e) {
+ $exceptions .= $e->__toString() . "\n";
+ }
+ echo $exceptions;
+ return;
+ }
+
+ $this->outputBody();
+ }
+
+ /**
+ * Magic __toString functionality
+ *
+ * Proxies to {@link sendResponse()} and returns response value as string
+ * using output buffering.
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ ob_start();
+ $this->sendResponse();
+ return ob_get_clean();
+ }
+}
diff --git a/lib/zend/Zend/Controller/Response/Cli.php b/lib/zend/Zend/Controller/Response/Cli.php
new file mode 100644
index 00000000000..ed141659fa8
--- /dev/null
+++ b/lib/zend/Zend/Controller/Response/Cli.php
@@ -0,0 +1,68 @@
+isException() && $this->renderExceptions()) {
+ $exceptions = '';
+ foreach ($this->getException() as $e) {
+ $exceptions .= $e->__toString() . "\n";
+ }
+ return $exceptions;
+ }
+
+ return $this->_body;
+ }
+}
diff --git a/lib/zend/Zend/Controller/Response/Exception.php b/lib/zend/Zend/Controller/Response/Exception.php
new file mode 100644
index 00000000000..9829fb66bc4
--- /dev/null
+++ b/lib/zend/Zend/Controller/Response/Exception.php
@@ -0,0 +1,36 @@
+_headersRaw as $header) {
+ $headers[] = $header;
+ }
+ foreach ($this->_headers as $header) {
+ $name = $header['name'];
+ $key = strtolower($name);
+ if (array_key_exists($name, $headers)) {
+ if ($header['replace']) {
+ $headers[$key] = $header['name'] . ': ' . $header['value'];
+ }
+ } else {
+ $headers[$key] = $header['name'] . ': ' . $header['value'];
+ }
+ }
+ return $headers;
+ }
+
+ /**
+ * Can we send headers?
+ *
+ * @param bool $throw
+ * @return void
+ */
+ public function canSendHeaders($throw = false)
+ {
+ return true;
+ }
+
+ /**
+ * Return the concatenated body segments
+ *
+ * @return string
+ */
+ public function outputBody()
+ {
+ $fullContent = '';
+ foreach ($this->_body as $content) {
+ $fullContent .= $content;
+ }
+ return $fullContent;
+ }
+
+ /**
+ * Get body and/or body segments
+ *
+ * @param bool|string $spec
+ * @return string|array|null
+ */
+ public function getBody($spec = false)
+ {
+ if (false === $spec) {
+ return $this->outputBody();
+ } elseif (true === $spec) {
+ return $this->_body;
+ } elseif (is_string($spec) && isset($this->_body[$spec])) {
+ return $this->_body[$spec];
+ }
+
+ return null;
+ }
+
+ /**
+ * "send" Response
+ *
+ * Concats all response headers, and then final body (separated by two
+ * newlines)
+ *
+ * @return string
+ */
+ public function sendResponse()
+ {
+ $headers = $this->sendHeaders();
+ $content = implode("\n", $headers) . "\n\n";
+
+ if ($this->isException() && $this->renderExceptions()) {
+ $exceptions = '';
+ foreach ($this->getException() as $e) {
+ $exceptions .= $e->__toString() . "\n";
+ }
+ $content .= $exceptions;
+ } else {
+ $content .= $this->outputBody();
+ }
+
+ return $content;
+ }
+}
diff --git a/lib/zend/Zend/Controller/Router/Abstract.php b/lib/zend/Zend/Controller/Router/Abstract.php
new file mode 100644
index 00000000000..71ed9473de5
--- /dev/null
+++ b/lib/zend/Zend/Controller/Router/Abstract.php
@@ -0,0 +1,178 @@
+setParams($params);
+ }
+
+ /**
+ * Add or modify a parameter to use when instantiating an action controller
+ *
+ * @param string $name
+ * @param mixed $value
+ * @return Zend_Controller_Router_Abstract
+ */
+ public function setParam($name, $value)
+ {
+ $name = (string)$name;
+ $this->_invokeParams[$name] = $value;
+
+ return $this;
+ }
+
+ /**
+ * Set parameters to pass to action controller constructors
+ *
+ * @param array $params
+ * @return Zend_Controller_Router_Abstract
+ */
+ public function setParams(array $params)
+ {
+ $this->_invokeParams = array_merge($this->_invokeParams, $params);
+
+ return $this;
+ }
+
+ /**
+ * Retrieve a single parameter from the controller parameter stack
+ *
+ * @param string $name
+ * @return mixed
+ */
+ public function getParam($name)
+ {
+ if (isset($this->_invokeParams[$name])) {
+ return $this->_invokeParams[$name];
+ }
+
+ return null;
+ }
+
+ /**
+ * Retrieve action controller instantiation parameters
+ *
+ * @return array
+ */
+ public function getParams()
+ {
+ return $this->_invokeParams;
+ }
+
+ /**
+ * Clear the controller parameter stack
+ *
+ * By default, clears all parameters. If a parameter name is given, clears
+ * only that parameter; if an array of parameter names is provided, clears
+ * each.
+ *
+ * @param null|string|array single key or array of keys for params to clear
+ * @return Zend_Controller_Router_Abstract
+ */
+ public function clearParams($name = null)
+ {
+ if (null === $name) {
+ $this->_invokeParams = array();
+ } elseif (is_string($name) && isset($this->_invokeParams[$name])) {
+ unset($this->_invokeParams[$name]);
+ } elseif (is_array($name)) {
+ foreach ($name as $key) {
+ if (is_string($key) && isset($this->_invokeParams[$key])) {
+ unset($this->_invokeParams[$key]);
+ }
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Retrieve Front Controller
+ *
+ * @return Zend_Controller_Front
+ */
+ public function getFrontController()
+ {
+ // Used cache version if found
+ if (null !== $this->_frontController) {
+ return $this->_frontController;
+ }
+
+ require_once 'Zend/Controller/Front.php';
+ $this->_frontController = Zend_Controller_Front::getInstance();
+
+ return $this->_frontController;
+ }
+
+ /**
+ * Set Front Controller
+ *
+ * @param Zend_Controller_Front $controller
+ * @return Zend_Controller_Router_Interface
+ */
+ public function setFrontController(Zend_Controller_Front $controller)
+ {
+ $this->_frontController = $controller;
+
+ return $this;
+ }
+}
diff --git a/lib/zend/Zend/Controller/Router/Exception.php b/lib/zend/Zend/Controller/Router/Exception.php
new file mode 100644
index 00000000000..2d036333060
--- /dev/null
+++ b/lib/zend/Zend/Controller/Router/Exception.php
@@ -0,0 +1,35 @@
+hasRoute('default')) {
+ $dispatcher = $this->getFrontController()->getDispatcher();
+ $request = $this->getFrontController()->getRequest();
+
+ require_once 'Zend/Controller/Router/Route/Module.php';
+ $compat = new Zend_Controller_Router_Route_Module(array(), $dispatcher, $request);
+
+ $this->_routes = array('default' => $compat) + $this->_routes;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Add route to the route chain
+ *
+ * If route contains method setRequest(), it is initialized with a request object
+ *
+ * @param string $name Name of the route
+ * @param Zend_Controller_Router_Route_Interface $route Instance of the route
+ * @return Zend_Controller_Router_Rewrite
+ */
+ public function addRoute($name, Zend_Controller_Router_Route_Interface $route)
+ {
+ if (method_exists($route, 'setRequest')) {
+ $route->setRequest($this->getFrontController()->getRequest());
+ }
+
+ $this->_routes[$name] = $route;
+
+ return $this;
+ }
+
+ /**
+ * Add routes to the route chain
+ *
+ * @param array $routes Array of routes with names as keys and routes as values
+ * @return Zend_Controller_Router_Rewrite
+ */
+ public function addRoutes($routes)
+ {
+ foreach ($routes as $name => $route) {
+ $this->addRoute($name, $route);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Create routes out of Zend_Config configuration
+ *
+ * Example INI:
+ * routes.archive.route = "archive/:year/*"
+ * routes.archive.defaults.controller = archive
+ * routes.archive.defaults.action = show
+ * routes.archive.defaults.year = 2000
+ * routes.archive.reqs.year = "\d+"
+ *
+ * routes.news.type = "Zend_Controller_Router_Route_Static"
+ * routes.news.route = "news"
+ * routes.news.defaults.controller = "news"
+ * routes.news.defaults.action = "list"
+ *
+ * And finally after you have created a Zend_Config with above ini:
+ * $router = new Zend_Controller_Router_Rewrite();
+ * $router->addConfig($config, 'routes');
+ *
+ * @param Zend_Config $config Configuration object
+ * @param string $section Name of the config section containing route's definitions
+ * @throws Zend_Controller_Router_Exception
+ * @return Zend_Controller_Router_Rewrite
+ */
+ public function addConfig(Zend_Config $config, $section = null)
+ {
+ if ($section !== null) {
+ if ($config->{$section} === null) {
+ require_once 'Zend/Controller/Router/Exception.php';
+ throw new Zend_Controller_Router_Exception("No route configuration in section '{$section}'");
+ }
+
+ $config = $config->{$section};
+ }
+
+ foreach ($config as $name => $info) {
+ $route = $this->_getRouteFromConfig($info);
+
+ if ($route instanceof Zend_Controller_Router_Route_Chain) {
+ if (!isset($info->chain)) {
+ require_once 'Zend/Controller/Router/Exception.php';
+ throw new Zend_Controller_Router_Exception("No chain defined");
+ }
+
+ if ($info->chain instanceof Zend_Config) {
+ $childRouteNames = $info->chain;
+ } else {
+ $childRouteNames = explode(',', $info->chain);
+ }
+
+ foreach ($childRouteNames as $childRouteName) {
+ $childRoute = $this->getRoute(trim($childRouteName));
+ $route->chain($childRoute);
+ }
+
+ $this->addRoute($name, $route);
+ } elseif (isset($info->chains) && $info->chains instanceof Zend_Config) {
+ $this->_addChainRoutesFromConfig($name, $route, $info->chains);
+ } else {
+ $this->addRoute($name, $route);
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get a route frm a config instance
+ *
+ * @param Zend_Config $info
+ * @return Zend_Controller_Router_Route_Interface
+ */
+ protected function _getRouteFromConfig(Zend_Config $info)
+ {
+ $class = (isset($info->type)) ? $info->type : 'Zend_Controller_Router_Route';
+ if (!class_exists($class)) {
+ require_once 'Zend/Loader.php';
+ Zend_Loader::loadClass($class);
+ }
+
+ $route = call_user_func(
+ array(
+ $class,
+ 'getInstance'
+ ), $info
+ );
+
+ if (isset($info->abstract) && $info->abstract && method_exists($route, 'isAbstract')) {
+ $route->isAbstract(true);
+ }
+
+ return $route;
+ }
+
+ /**
+ * Add chain routes from a config route
+ *
+ * @param string $name
+ * @param Zend_Controller_Router_Route_Interface $route
+ * @param Zend_Config $childRoutesInfo
+ * @return void
+ */
+ protected function _addChainRoutesFromConfig(
+ $name,
+ Zend_Controller_Router_Route_Interface $route,
+ Zend_Config $childRoutesInfo
+ )
+ {
+ foreach ($childRoutesInfo as $childRouteName => $childRouteInfo) {
+ if (is_string($childRouteInfo)) {
+ $childRouteName = $childRouteInfo;
+ $childRoute = $this->getRoute($childRouteName);
+ } else {
+ $childRoute = $this->_getRouteFromConfig($childRouteInfo);
+ }
+
+ if ($route instanceof Zend_Controller_Router_Route_Chain) {
+ $chainRoute = clone $route;
+ $chainRoute->chain($childRoute);
+ } else {
+ $chainRoute = $route->chain($childRoute);
+ }
+
+ $chainName = $name . $this->_chainNameSeparator . $childRouteName;
+
+ if (isset($childRouteInfo->chains)) {
+ $this->_addChainRoutesFromConfig($chainName, $chainRoute, $childRouteInfo->chains);
+ } else {
+ $this->addRoute($chainName, $chainRoute);
+ }
+ }
+ }
+
+ /**
+ * Remove a route from the route chain
+ *
+ * @param string $name Name of the route
+ * @throws Zend_Controller_Router_Exception
+ * @return Zend_Controller_Router_Rewrite
+ */
+ public function removeRoute($name)
+ {
+ if (!isset($this->_routes[$name])) {
+ require_once 'Zend/Controller/Router/Exception.php';
+ throw new Zend_Controller_Router_Exception("Route $name is not defined");
+ }
+
+ unset($this->_routes[$name]);
+
+ return $this;
+ }
+
+ /**
+ * Remove all standard default routes
+ *
+ * @return Zend_Controller_Router_Rewrite
+ */
+ public function removeDefaultRoutes()
+ {
+ $this->_useDefaultRoutes = false;
+
+ return $this;
+ }
+
+ /**
+ * Check if named route exists
+ *
+ * @param string $name Name of the route
+ * @return boolean
+ */
+ public function hasRoute($name)
+ {
+ return isset($this->_routes[$name]);
+ }
+
+ /**
+ * Retrieve a named route
+ *
+ * @param string $name Name of the route
+ * @throws Zend_Controller_Router_Exception
+ * @return Zend_Controller_Router_Route_Interface Route object
+ */
+ public function getRoute($name)
+ {
+ if (!isset($this->_routes[$name])) {
+ require_once 'Zend/Controller/Router/Exception.php';
+ throw new Zend_Controller_Router_Exception("Route $name is not defined");
+ }
+
+ return $this->_routes[$name];
+ }
+
+ /**
+ * Retrieve a currently matched route
+ *
+ * @throws Zend_Controller_Router_Exception
+ * @return Zend_Controller_Router_Route_Interface Route object
+ */
+ public function getCurrentRoute()
+ {
+ if (!isset($this->_currentRoute)) {
+ require_once 'Zend/Controller/Router/Exception.php';
+ throw new Zend_Controller_Router_Exception("Current route is not defined");
+ }
+
+ return $this->getRoute($this->_currentRoute);
+ }
+
+ /**
+ * Retrieve a name of currently matched route
+ *
+ * @throws Zend_Controller_Router_Exception
+ * @return string Route name
+ */
+ public function getCurrentRouteName()
+ {
+ if (!isset($this->_currentRoute)) {
+ require_once 'Zend/Controller/Router/Exception.php';
+ throw new Zend_Controller_Router_Exception("Current route is not defined");
+ }
+
+ return $this->_currentRoute;
+ }
+
+ /**
+ * Retrieve an array of routes added to the route chain
+ *
+ * @return array All of the defined routes
+ */
+ public function getRoutes()
+ {
+ return $this->_routes;
+ }
+
+ /**
+ * Find a matching route to the current PATH_INFO and inject
+ * returning values to the Request object.
+ *
+ * @param Zend_Controller_Request_Abstract $request
+ * @throws Zend_Controller_Router_Exception
+ * @return Zend_Controller_Request_Abstract Request object
+ */
+ public function route(Zend_Controller_Request_Abstract $request)
+ {
+ if (!$request instanceof Zend_Controller_Request_Http) {
+ require_once 'Zend/Controller/Router/Exception.php';
+ throw new Zend_Controller_Router_Exception(
+ 'Zend_Controller_Router_Rewrite requires a Zend_Controller_Request_Http-based request object'
+ );
+ }
+
+ if ($this->_useDefaultRoutes) {
+ $this->addDefaultRoutes();
+ }
+
+ // Find the matching route
+ $routeMatched = false;
+
+ foreach (array_reverse($this->_routes, true) as $name => $route) {
+ // TODO: Should be an interface method. Hack for 1.0 BC
+ if (method_exists($route, 'isAbstract') && $route->isAbstract()) {
+ continue;
+ }
+
+ // TODO: Should be an interface method. Hack for 1.0 BC
+ if (!method_exists($route, 'getVersion') || $route->getVersion() == 1) {
+ $match = $request->getPathInfo();
+ } else {
+ $match = $request;
+ }
+
+ if ($params = $route->match($match)) {
+ $this->_setRequestParams($request, $params);
+ $this->_currentRoute = $name;
+ $routeMatched = true;
+ break;
+ }
+ }
+
+ if (!$routeMatched) {
+ require_once 'Zend/Controller/Router/Exception.php';
+ throw new Zend_Controller_Router_Exception('No route matched the request', 404);
+ }
+
+ if ($this->_useCurrentParamsAsGlobal) {
+ $params = $request->getParams();
+ foreach ($params as $param => $value) {
+ $this->setGlobalParam($param, $value);
+ }
+ }
+
+ return $request;
+ }
+
+ /**
+ * Sets parameters for request object
+ *
+ * Module name, controller name and action name
+ *
+ * @param Zend_Controller_Request_Abstract $request
+ * @param array $params
+ */
+ protected function _setRequestParams($request, $params)
+ {
+ foreach ($params as $param => $value) {
+
+ $request->setParam($param, $value);
+
+ if ($param === $request->getModuleKey()) {
+ $request->setModuleName($value);
+ }
+ if ($param === $request->getControllerKey()) {
+ $request->setControllerName($value);
+ }
+ if ($param === $request->getActionKey()) {
+ $request->setActionName($value);
+ }
+ }
+ }
+
+ /**
+ * Generates a URL path that can be used in URL creation, redirection, etc.
+ *
+ * @param array $userParams Options passed by a user used to override parameters
+ * @param mixed $name The name of a Route to use
+ * @param bool $reset Whether to reset to the route defaults ignoring URL params
+ * @param bool $encode Tells to encode URL parts on output
+ * @throws Zend_Controller_Router_Exception
+ * @return string Resulting absolute URL path
+ */
+ public function assemble($userParams, $name = null, $reset = false, $encode = true)
+ {
+ if (!is_array($userParams)) {
+ require_once 'Zend/Controller/Router/Exception.php';
+ throw new Zend_Controller_Router_Exception('userParams must be an array');
+ }
+
+ if ($name == null) {
+ try {
+ $name = $this->getCurrentRouteName();
+ } catch (Zend_Controller_Router_Exception $e) {
+ $name = 'default';
+ }
+ }
+
+ // Use UNION (+) in order to preserve numeric keys
+ $params = $userParams + $this->_globalParams;
+
+ $route = $this->getRoute($name);
+ $url = $route->assemble($params, $reset, $encode);
+
+ if (!preg_match('|^[a-z]+://|', $url)) {
+ $url = rtrim($this->getFrontController()->getBaseUrl(), self::URI_DELIMITER) . self::URI_DELIMITER . $url;
+ }
+
+ return $url;
+ }
+
+ /**
+ * Set a global parameter
+ *
+ * @param string $name
+ * @param mixed $value
+ * @return Zend_Controller_Router_Rewrite
+ */
+ public function setGlobalParam($name, $value)
+ {
+ $this->_globalParams[$name] = $value;
+
+ return $this;
+ }
+
+ /**
+ * Set the separator to use with chain names
+ *
+ * @param string $separator The separator to use
+ * @return Zend_Controller_Router_Rewrite
+ */
+ public function setChainNameSeparator($separator)
+ {
+ $this->_chainNameSeparator = $separator;
+
+ return $this;
+ }
+
+ /**
+ * Get the separator to use for chain names
+ *
+ * @return string
+ */
+ public function getChainNameSeparator()
+ {
+ return $this->_chainNameSeparator;
+ }
+
+ /**
+ * Determines/returns whether to use the request parameters as global parameters.
+ *
+ * @param boolean|null $use
+ * Null/unset when you want to retrieve the current state.
+ * True when request parameters should be global, false otherwise
+ * @return boolean|Zend_Controller_Router_Rewrite
+ * Returns a boolean if first param isn't set, returns an
+ * instance of Zend_Controller_Router_Rewrite otherwise.
+ *
+ */
+ public function useRequestParametersAsGlobal($use = null)
+ {
+ if ($use === null) {
+ return $this->_useCurrentParamsAsGlobal;
+ }
+
+ $this->_useCurrentParamsAsGlobal = (bool)$use;
+
+ return $this;
+ }
+}
diff --git a/lib/zend/Zend/Controller/Router/Route.php b/lib/zend/Zend/Controller/Router/Route.php
new file mode 100644
index 00000000000..927b97b3d34
--- /dev/null
+++ b/lib/zend/Zend/Controller/Router/Route.php
@@ -0,0 +1,605 @@
+reqs instanceof Zend_Config) ? $config->reqs->toArray() : array();
+ $defs = ($config->defaults instanceof Zend_Config) ? $config->defaults->toArray() : array();
+
+ return new self($config->route, $defs, $reqs);
+ }
+
+ /**
+ * Prepares the route for mapping by splitting (exploding) it
+ * to a corresponding atomic parts. These parts are assigned
+ * a position which is later used for matching and preparing values.
+ *
+ * @param string $route Map used to match with later submitted URL path
+ * @param array $defaults Defaults for map variables with keys as variable names
+ * @param array $reqs Regular expression requirements for variables (keys as variable names)
+ * @param Zend_Translate $translator Translator to use for this instance
+ * @param mixed|null $locale
+ */
+ public function __construct(
+ $route, $defaults = array(), $reqs = array(), Zend_Translate $translator = null, $locale = null
+ )
+ {
+ $route = trim($route, $this->_urlDelimiter);
+ $this->_defaults = (array)$defaults;
+ $this->_requirements = (array)$reqs;
+ $this->_translator = $translator;
+ $this->_locale = $locale;
+
+ if ($route !== '') {
+ foreach (explode($this->_urlDelimiter, $route) as $pos => $part) {
+ if (substr($part, 0, 1) == $this->_urlVariable && substr($part, 1, 1) != $this->_urlVariable) {
+ $name = substr($part, 1);
+
+ if (substr($name, 0, 1) === '@' && substr($name, 1, 1) !== '@') {
+ $name = substr($name, 1);
+ $this->_translatable[] = $name;
+ $this->_isTranslated = true;
+ }
+
+ $this->_parts[$pos] = (isset($reqs[$name]) ? $reqs[$name] : $this->_defaultRegex);
+ $this->_variables[$pos] = $name;
+ } else {
+ if (substr($part, 0, 1) == $this->_urlVariable) {
+ $part = substr($part, 1);
+ }
+
+ if (substr($part, 0, 1) === '@' && substr($part, 1, 1) !== '@') {
+ $this->_isTranslated = true;
+ }
+
+ $this->_parts[$pos] = $part;
+
+ if ($part !== '*') {
+ $this->_staticCount++;
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Matches a user submitted path with parts defined by a map. Assigns and
+ * returns an array of variables on a successful match.
+ *
+ * @param string $path Path used to match against this routing map
+ * @param boolean $partial
+ * @throws Zend_Controller_Router_Exception
+ * @return array|false An array of assigned values or a false on a mismatch
+ */
+ public function match($path, $partial = false)
+ {
+ if ($this->_isTranslated) {
+ $translateMessages = $this->getTranslator()->getMessages();
+ }
+
+ $pathStaticCount = 0;
+ $values = array();
+ $matchedPath = '';
+
+ if (!$partial) {
+ $path = trim($path, $this->_urlDelimiter);
+ }
+
+ if ($path !== '') {
+ $path = explode($this->_urlDelimiter, $path);
+
+ foreach ($path as $pos => $pathPart) {
+ // Path is longer than a route, it's not a match
+ if (!array_key_exists($pos, $this->_parts)) {
+ if ($partial) {
+ break;
+ } else {
+ return false;
+ }
+ }
+
+ $matchedPath .= $pathPart . $this->_urlDelimiter;
+
+ // If it's a wildcard, get the rest of URL as wildcard data and stop matching
+ if ($this->_parts[$pos] == '*') {
+ $count = count($path);
+ for ($i = $pos; $i < $count; $i += 2) {
+ $var = urldecode($path[$i]);
+ if (!isset($this->_wildcardData[$var]) && !isset($this->_defaults[$var])
+ && !isset($values[$var])
+ ) {
+ $this->_wildcardData[$var] = (isset($path[$i + 1])) ? urldecode($path[$i + 1]) : null;
+ }
+ }
+
+ $matchedPath = implode($this->_urlDelimiter, $path);
+ break;
+ }
+
+ $name = isset($this->_variables[$pos]) ? $this->_variables[$pos] : null;
+ $pathPart = urldecode($pathPart);
+
+ // Translate value if required
+ $part = $this->_parts[$pos];
+ if ($this->_isTranslated
+ && (substr($part, 0, 1) === '@' && substr($part, 1, 1) !== '@'
+ && $name === null)
+ || $name !== null && in_array($name, $this->_translatable)
+ ) {
+ if (substr($part, 0, 1) === '@') {
+ $part = substr($part, 1);
+ }
+
+ if (($originalPathPart = array_search($pathPart, $translateMessages)) !== false) {
+ $pathPart = $originalPathPart;
+ }
+ }
+
+ if (substr($part, 0, 2) === '@@') {
+ $part = substr($part, 1);
+ }
+
+ // If it's a static part, match directly
+ if ($name === null && $part != $pathPart) {
+ return false;
+ }
+
+ // If it's a variable with requirement, match a regex. If not - everything matches
+ if ($part !== null
+ && !preg_match(
+ $this->_regexDelimiter . '^' . $part . '$' . $this->_regexDelimiter . 'iu', $pathPart
+ )
+ ) {
+ return false;
+ }
+
+ // If it's a variable store it's value for later
+ if ($name !== null) {
+ $values[$name] = $pathPart;
+ } else {
+ $pathStaticCount++;
+ }
+ }
+ }
+
+ // Check if all static mappings have been matched
+ if ($this->_staticCount != $pathStaticCount) {
+ return false;
+ }
+
+ $return = $values + $this->_wildcardData + $this->_defaults;
+
+ // Check if all map variables have been initialized
+ foreach ($this->_variables as $var) {
+ if (!array_key_exists($var, $return)) {
+ return false;
+ } elseif ($return[$var] == '' || $return[$var] === null) {
+ // Empty variable? Replace with the default value.
+ $return[$var] = $this->_defaults[$var];
+ }
+ }
+
+ $this->setMatchedPath(rtrim($matchedPath, $this->_urlDelimiter));
+
+ $this->_values = $values;
+
+ return $return;
+ }
+
+ /**
+ * Assembles user submitted parameters forming a URL path defined by this route
+ *
+ * @param array $data An array of variable and value pairs used as parameters
+ * @param boolean $reset Whether or not to set route defaults with those provided in $data
+ * @param boolean $encode
+ * @param boolean $partial
+ * @throws Zend_Controller_Router_Exception
+ * @return string Route path with user submitted parameters
+ */
+ public function assemble($data = array(), $reset = false, $encode = false, $partial = false)
+ {
+ if ($this->_isTranslated) {
+ $translator = $this->getTranslator();
+
+ if (isset($data['@locale'])) {
+ $locale = $data['@locale'];
+ unset($data['@locale']);
+ } else {
+ $locale = $this->getLocale();
+ }
+ }
+
+ $url = array();
+ $flag = false;
+
+ foreach ($this->_parts as $key => $part) {
+ $name = isset($this->_variables[$key]) ? $this->_variables[$key] : null;
+
+ $useDefault = false;
+ if (isset($name) && array_key_exists($name, $data) && $data[$name] === null) {
+ $useDefault = true;
+ }
+
+ if (isset($name)) {
+ if (isset($data[$name]) && !$useDefault) {
+ $value = $data[$name];
+ unset($data[$name]);
+ } elseif (!$reset && !$useDefault && isset($this->_values[$name])) {
+ $value = $this->_values[$name];
+ } elseif (!$reset && !$useDefault && isset($this->_wildcardData[$name])) {
+ $value = $this->_wildcardData[$name];
+ } elseif (array_key_exists($name, $this->_defaults)) {
+ $value = $this->_defaults[$name];
+ } else {
+ require_once 'Zend/Controller/Router/Exception.php';
+ throw new Zend_Controller_Router_Exception($name . ' is not specified');
+ }
+
+ if ($this->_isTranslated && in_array($name, $this->_translatable)) {
+ $url[$key] = $translator->translate($value, $locale);
+ } else {
+ $url[$key] = $value;
+ }
+ } elseif ($part != '*') {
+ if ($this->_isTranslated && substr($part, 0, 1) === '@') {
+ if (substr($part, 1, 1) !== '@') {
+ $url[$key] = $translator->translate(substr($part, 1), $locale);
+ } else {
+ $url[$key] = substr($part, 1);
+ }
+ } else {
+ if (substr($part, 0, 2) === '@@') {
+ $part = substr($part, 1);
+ }
+
+ $url[$key] = $part;
+ }
+ } else {
+ if (!$reset) {
+ $data += $this->_wildcardData;
+ }
+ $defaults = $this->getDefaults();
+ foreach ($data as $var => $value) {
+ if ($value !== null && (!isset($defaults[$var]) || $value != $defaults[$var])) {
+ $url[$key++] = $var;
+ $url[$key++] = $value;
+ $flag = true;
+ }
+ }
+ }
+ }
+
+ $return = '';
+
+ foreach (array_reverse($url, true) as $key => $value) {
+ $defaultValue = null;
+
+ if (isset($this->_variables[$key])) {
+ $defaultValue = $this->getDefault($this->_variables[$key]);
+
+ if ($this->_isTranslated && $defaultValue !== null
+ && isset($this->_translatable[$this->_variables[$key]])
+ ) {
+ $defaultValue = $translator->translate($defaultValue, $locale);
+ }
+ }
+
+ if ($flag || $value !== $defaultValue || $partial) {
+ if ($encode) {
+ $value = urlencode($value);
+ }
+ $return = $this->_urlDelimiter . $value . $return;
+ $flag = true;
+ }
+ }
+
+ return trim($return, $this->_urlDelimiter);
+ }
+
+ /**
+ * Return a single parameter of route's defaults
+ *
+ * @param string $name Array key of the parameter
+ * @return string Previously set default
+ */
+ public function getDefault($name)
+ {
+ if (isset($this->_defaults[$name])) {
+ return $this->_defaults[$name];
+ }
+
+ return null;
+ }
+
+ /**
+ * Return an array of defaults
+ *
+ * @return array Route defaults
+ */
+ public function getDefaults()
+ {
+ return $this->_defaults;
+ }
+
+ /**
+ * Get all variables which are used by the route
+ *
+ * @return array
+ */
+ public function getVariables()
+ {
+ return $this->_variables;
+ }
+
+ /**
+ * Set a default translator
+ *
+ * @param Zend_Translate $translator
+ * @return void
+ */
+ public static function setDefaultTranslator(Zend_Translate $translator = null)
+ {
+ self::$_defaultTranslator = $translator;
+ }
+
+ /**
+ * Get the default translator
+ *
+ * @return Zend_Translate
+ */
+ public static function getDefaultTranslator()
+ {
+ return self::$_defaultTranslator;
+ }
+
+ /**
+ * Set a translator
+ *
+ * @param Zend_Translate $translator
+ * @return void
+ */
+ public function setTranslator(Zend_Translate $translator)
+ {
+ $this->_translator = $translator;
+ }
+
+ /**
+ * Get the translator
+ *
+ * @throws Zend_Controller_Router_Exception When no translator can be found
+ * @return Zend_Translate
+ */
+ public function getTranslator()
+ {
+ if ($this->_translator !== null) {
+ return $this->_translator;
+ } else {
+ if (($translator = self::getDefaultTranslator()) !== null) {
+ return $translator;
+ } else {
+ try {
+ $translator = Zend_Registry::get('Zend_Translate');
+ } catch (Zend_Exception $e) {
+ $translator = null;
+ }
+
+ if ($translator instanceof Zend_Translate) {
+ return $translator;
+ }
+ }
+ }
+
+ require_once 'Zend/Controller/Router/Exception.php';
+ throw new Zend_Controller_Router_Exception('Could not find a translator');
+ }
+
+ /**
+ * Set a default locale
+ *
+ * @param mixed $locale
+ * @return void
+ */
+ public static function setDefaultLocale($locale = null)
+ {
+ self::$_defaultLocale = $locale;
+ }
+
+ /**
+ * Get the default locale
+ *
+ * @return mixed
+ */
+ public static function getDefaultLocale()
+ {
+ return self::$_defaultLocale;
+ }
+
+ /**
+ * Set a locale
+ *
+ * @param mixed $locale
+ * @return void
+ */
+ public function setLocale($locale)
+ {
+ $this->_locale = $locale;
+ }
+
+ /**
+ * Get the locale
+ *
+ * @return mixed
+ */
+ public function getLocale()
+ {
+ if ($this->_locale !== null) {
+ return $this->_locale;
+ } else {
+ if (($locale = self::getDefaultLocale()) !== null) {
+ return $locale;
+ } else {
+ try {
+ $locale = Zend_Registry::get('Zend_Locale');
+ } catch (Zend_Exception $e) {
+ $locale = null;
+ }
+
+ if ($locale !== null) {
+ return $locale;
+ }
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/lib/zend/Zend/Controller/Router/Route/Abstract.php b/lib/zend/Zend/Controller/Router/Route/Abstract.php
new file mode 100644
index 00000000000..2f6dc84807f
--- /dev/null
+++ b/lib/zend/Zend/Controller/Router/Route/Abstract.php
@@ -0,0 +1,121 @@
+_matchedPath = $path;
+ }
+
+ /**
+ * Get partially matched path
+ *
+ * @return string
+ */
+ public function getMatchedPath()
+ {
+ return $this->_matchedPath;
+ }
+
+ /**
+ * Check or set wether this is an abstract route or not
+ *
+ * @param boolean $flag
+ * @return boolean
+ */
+ public function isAbstract($flag = null)
+ {
+ if ($flag !== null) {
+ $this->_isAbstract = $flag;
+ }
+
+ return $this->_isAbstract;
+ }
+
+ /**
+ * Create a new chain
+ *
+ * @param Zend_Controller_Router_Route_Abstract $route
+ * @param string $separator
+ * @return Zend_Controller_Router_Route_Chain
+ */
+ public function chain(Zend_Controller_Router_Route_Abstract $route, $separator = '/')
+ {
+ require_once 'Zend/Controller/Router/Route/Chain.php';
+
+ $chain = new Zend_Controller_Router_Route_Chain();
+ $chain->chain($this)->chain($route, $separator);
+
+ return $chain;
+ }
+}
diff --git a/lib/zend/Zend/Controller/Router/Route/Chain.php b/lib/zend/Zend/Controller/Router/Route/Chain.php
new file mode 100644
index 00000000000..a474931ac51
--- /dev/null
+++ b/lib/zend/Zend/Controller/Router/Route/Chain.php
@@ -0,0 +1,229 @@
+defaults instanceof Zend_Config) ? $config->defaults->toArray() : array();
+
+ return new self($config->route, $defs);
+ }
+
+ /**
+ * Add a route to this chain
+ *
+ * @param Zend_Controller_Router_Route_Abstract $route
+ * @param string $separator
+ * @return Zend_Controller_Router_Route_Chain
+ */
+ public function chain(Zend_Controller_Router_Route_Abstract $route, $separator = self::URI_DELIMITER)
+ {
+ $this->_routes[] = $route;
+ $this->_separators[] = $separator;
+
+ return $this;
+ }
+
+ /**
+ * Matches a user submitted path with a previously defined route.
+ * Assigns and returns an array of defaults on a successful match.
+ *
+ * @param Zend_Controller_Request_Http $request Request to get the path info from
+ * @param null $partial
+ * @return array|false An array of assigned values or a false on a mismatch
+ */
+ public function match($request, $partial = null)
+ {
+ $rawPath = $request->getPathInfo();
+ $path = trim($request->getPathInfo(), self::URI_DELIMITER);
+ $subPath = $path;
+ $values = array();
+ $matchedPath = null;
+
+ foreach ($this->_routes as $key => $route) {
+ if ($key > 0
+ && $matchedPath !== null
+ && $subPath !== ''
+ && $subPath !== false
+ ) {
+ $separator = substr($subPath, 0, strlen($this->_separators[$key]));
+
+ if ($separator !== $this->_separators[$key]) {
+ $request->setPathInfo($rawPath);
+ return false;
+ }
+
+ $subPath = substr($subPath, strlen($separator));
+ }
+ // TODO: Should be an interface method. Hack for 1.0 BC
+ if (!method_exists($route, 'getVersion') || $route->getVersion() == 1) {
+ $match = $subPath;
+ } else {
+ $request->setPathInfo($subPath);
+ $match = $request;
+ }
+
+ $res = $route->match($match, true);
+
+ if ($res === false) {
+ $request->setPathInfo($rawPath);
+ return false;
+ }
+
+ $matchedPath = $route->getMatchedPath();
+
+ if ($matchedPath !== null) {
+ $subPath = substr($subPath, strlen($matchedPath));
+ }
+
+ $values = $res + $values;
+ }
+
+ $request->setPathInfo($path);
+
+ if ($subPath !== '' && $subPath !== false) {
+ return false;
+ }
+
+ return $values;
+ }
+
+ /**
+ * Assembles a URL path defined by this route
+ *
+ * @param array $data An array of variable and value pairs used as parameters
+ * @param bool $reset
+ * @param bool $encode
+ * @return string Route path with user submitted parameters
+ */
+ public function assemble($data = array(), $reset = false, $encode = false)
+ {
+ $value = '';
+ $numRoutes = count($this->_routes);
+
+ foreach ($this->_routes as $key => $route) {
+ if ($key > 0) {
+ $value .= $this->_separators[$key];
+ }
+
+ $value .= $route->assemble($data, $reset, $encode, (($numRoutes - 1) > $key));
+
+ if (method_exists($route, 'getVariables')) {
+ $variables = $route->getVariables();
+
+ foreach ($variables as $variable) {
+ $data[$variable] = null;
+ }
+ }
+ }
+
+ return $value;
+ }
+
+ /**
+ * Set the request object for this and the child routes
+ *
+ * @param Zend_Controller_Request_Abstract|null $request
+ * @return void
+ */
+ public function setRequest(Zend_Controller_Request_Abstract $request = null)
+ {
+ $this->_request = $request;
+
+ foreach ($this->_routes as $route) {
+ if (method_exists($route, 'setRequest')) {
+ $route->setRequest($request);
+ }
+ }
+ }
+
+ /**
+ * Return a single parameter of route's defaults
+ *
+ * @param string $name Array key of the parameter
+ * @return string Previously set default
+ */
+ public function getDefault($name)
+ {
+ $default = null;
+ foreach ($this->_routes as $route) {
+ if (method_exists($route, 'getDefault')) {
+ $current = $route->getDefault($name);
+ if (null !== $current) {
+ $default = $current;
+ }
+ }
+ }
+
+ return $default;
+ }
+
+ /**
+ * Return an array of defaults
+ *
+ * @return array Route defaults
+ */
+ public function getDefaults()
+ {
+ $defaults = array();
+ foreach ($this->_routes as $route) {
+ if (method_exists($route, 'getDefaults')) {
+ $defaults = array_merge($defaults, $route->getDefaults());
+ }
+ }
+
+ return $defaults;
+ }
+}
diff --git a/lib/zend/Zend/Controller/Router/Route/Hostname.php b/lib/zend/Zend/Controller/Router/Route/Hostname.php
new file mode 100644
index 00000000000..2d33c61811a
--- /dev/null
+++ b/lib/zend/Zend/Controller/Router/Route/Hostname.php
@@ -0,0 +1,380 @@
+_request = $request;
+ }
+
+ /**
+ * Get the request object
+ *
+ * @return Zend_Controller_Request_Abstract $request
+ */
+ public function getRequest()
+ {
+ if ($this->_request === null) {
+ require_once 'Zend/Controller/Front.php';
+ $this->_request = Zend_Controller_Front::getInstance()->getRequest();
+ }
+
+ return $this->_request;
+ }
+
+ /**
+ * Instantiates route based on passed Zend_Config structure
+ *
+ * @param Zend_Config $config Configuration object
+ * @return Zend_Controller_Router_Route_Hostname
+ */
+ public static function getInstance(Zend_Config $config)
+ {
+ $reqs = ($config->reqs instanceof Zend_Config) ? $config->reqs->toArray() : array();
+ $defs = ($config->defaults instanceof Zend_Config) ? $config->defaults->toArray() : array();
+ $scheme = (isset($config->scheme)) ? $config->scheme : null;
+
+ return new self($config->route, $defs, $reqs, $scheme);
+ }
+
+ /**
+ * Prepares the route for mapping by splitting (exploding) it
+ * to a corresponding atomic parts. These parts are assigned
+ * a position which is later used for matching and preparing values.
+ *
+ * @param string $route Map used to match with later submitted hostname
+ * @param array $defaults Defaults for map variables with keys as variable names
+ * @param array $reqs Regular expression requirements for variables (keys as variable names)
+ * @param string $scheme
+ */
+ public function __construct($route, $defaults = array(), $reqs = array(), $scheme = null)
+ {
+ $route = trim($route, '.');
+ $this->_defaults = (array) $defaults;
+ $this->_requirements = (array) $reqs;
+ $this->_scheme = $scheme;
+
+ if ($route != '') {
+ foreach (explode('.', $route) as $pos => $part) {
+ if (substr($part, 0, 1) == $this->_hostVariable) {
+ $name = substr($part, 1);
+ $this->_parts[$pos] = (isset($reqs[$name]) ? $reqs[$name] : $this->_defaultRegex);
+ $this->_variables[$pos] = $name;
+ } else {
+ $this->_parts[$pos] = $part;
+ $this->_staticCount++;
+ }
+ }
+ }
+ }
+
+ /**
+ * Matches a user submitted path with parts defined by a map. Assigns and
+ * returns an array of variables on a successful match.
+ *
+ * @param Zend_Controller_Request_Http $request Request to get the host from
+ * @return array|false An array of assigned values or a false on a mismatch
+ */
+ public function match($request)
+ {
+ // Check the scheme if required
+ if ($this->_scheme !== null) {
+ $scheme = $request->getScheme();
+
+ if ($scheme !== $this->_scheme) {
+ return false;
+ }
+ }
+
+ // Get the host and remove unnecessary port information
+ $host = $request->getHttpHost();
+ if (preg_match('#:\d+$#', $host, $result) === 1) {
+ $host = substr($host, 0, -strlen($result[0]));
+ }
+
+ $hostStaticCount = 0;
+ $values = array();
+
+ $host = trim($host, '.');
+
+ if ($host != '') {
+ $host = explode('.', $host);
+
+ foreach ($host as $pos => $hostPart) {
+ // Host is longer than a route, it's not a match
+ if (!array_key_exists($pos, $this->_parts)) {
+ return false;
+ }
+
+ $name = isset($this->_variables[$pos]) ? $this->_variables[$pos] : null;
+ $hostPart = urldecode($hostPart);
+
+ // If it's a static part, match directly
+ if ($name === null && $this->_parts[$pos] != $hostPart) {
+ return false;
+ }
+
+ // If it's a variable with requirement, match a regex. If not - everything matches
+ if ($this->_parts[$pos] !== null
+ && !preg_match(
+ $this->_regexDelimiter . '^' . $this->_parts[$pos] . '$' . $this->_regexDelimiter . 'iu',
+ $hostPart
+ )
+ ) {
+ return false;
+ }
+
+ // If it's a variable store it's value for later
+ if ($name !== null) {
+ $values[$name] = $hostPart;
+ } else {
+ $hostStaticCount++;
+ }
+ }
+ }
+
+ // Check if all static mappings have been matched
+ if ($this->_staticCount != $hostStaticCount) {
+ return false;
+ }
+
+ $return = $values + $this->_defaults;
+
+ // Check if all map variables have been initialized
+ foreach ($this->_variables as $var) {
+ if (!array_key_exists($var, $return)) {
+ return false;
+ }
+ }
+
+ $this->_values = $values;
+
+ return $return;
+ }
+
+ /**
+ * Assembles user submitted parameters forming a hostname defined by this route
+ *
+ * @param array $data An array of variable and value pairs used as parameters
+ * @param boolean $reset Whether or not to set route defaults with those provided in $data
+ * @param boolean $encode
+ * @param boolean $partial
+ * @throws Zend_Controller_Router_Exception
+ * @return string Route path with user submitted parameters
+ */
+ public function assemble($data = array(), $reset = false, $encode = false, $partial = false)
+ {
+ $host = array();
+ $flag = false;
+
+ foreach ($this->_parts as $key => $part) {
+ $name = isset($this->_variables[$key]) ? $this->_variables[$key] : null;
+
+ $useDefault = false;
+ if (isset($name) && array_key_exists($name, $data) && $data[$name] === null) {
+ $useDefault = true;
+ }
+
+ if (isset($name)) {
+ if (isset($data[$name]) && !$useDefault) {
+ $host[$key] = $data[$name];
+ unset($data[$name]);
+ } elseif (!$reset && !$useDefault && isset($this->_values[$name])) {
+ $host[$key] = $this->_values[$name];
+ } elseif (isset($this->_defaults[$name])) {
+ $host[$key] = $this->_defaults[$name];
+ } else {
+ require_once 'Zend/Controller/Router/Exception.php';
+ throw new Zend_Controller_Router_Exception($name . ' is not specified');
+ }
+ } else {
+ $host[$key] = $part;
+ }
+ }
+
+ $return = '';
+
+ foreach (array_reverse($host, true) as $key => $value) {
+ if ($flag || !isset($this->_variables[$key]) || $value !== $this->getDefault($this->_variables[$key])
+ || $partial
+ ) {
+ if ($encode) {
+ $value = urlencode($value);
+ }
+ $return = '.' . $value . $return;
+ $flag = true;
+ }
+ }
+
+ $url = trim($return, '.');
+
+ if ($this->_scheme !== null) {
+ $scheme = $this->_scheme;
+ } else {
+ $request = $this->getRequest();
+ if ($request instanceof Zend_Controller_Request_Http) {
+ $scheme = $request->getScheme();
+ } else {
+ $scheme = 'http';
+ }
+ }
+
+ $url = $scheme . '://' . $url;
+
+ return $url;
+ }
+
+ /**
+ * Return a single parameter of route's defaults
+ *
+ * @param string $name Array key of the parameter
+ * @return string Previously set default
+ */
+ public function getDefault($name)
+ {
+ if (isset($this->_defaults[$name])) {
+ return $this->_defaults[$name];
+ }
+
+ return null;
+ }
+
+ /**
+ * Return an array of defaults
+ *
+ * @return array Route defaults
+ */
+ public function getDefaults()
+ {
+ return $this->_defaults;
+ }
+
+ /**
+ * Get all variables which are used by the route
+ *
+ * @return array
+ */
+ public function getVariables()
+ {
+ return $this->_variables;
+ }
+}
diff --git a/lib/zend/Zend/Controller/Router/Route/Interface.php b/lib/zend/Zend/Controller/Router/Route/Interface.php
new file mode 100644
index 00000000000..6e82990f557
--- /dev/null
+++ b/lib/zend/Zend/Controller/Router/Route/Interface.php
@@ -0,0 +1,39 @@
+defaults instanceof Zend_Config) ? $config->defaults->toArray() : array();
+ $dispatcher = $frontController->getDispatcher();
+ $request = $frontController->getRequest();
+
+ return new self($defs, $dispatcher, $request);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param array $defaults Defaults for map variables with keys as variable names
+ * @param Zend_Controller_Dispatcher_Interface $dispatcher Dispatcher object
+ * @param Zend_Controller_Request_Abstract $request Request object
+ */
+ public function __construct(
+ array $defaults = array(),
+ Zend_Controller_Dispatcher_Interface $dispatcher = null,
+ Zend_Controller_Request_Abstract $request = null
+ )
+ {
+ $this->_defaults = $defaults;
+
+ if (isset($request)) {
+ $this->_request = $request;
+ }
+
+ if (isset($dispatcher)) {
+ $this->_dispatcher = $dispatcher;
+ }
+ }
+
+ /**
+ * Set request keys based on values in request object
+ *
+ * @return void
+ */
+ protected function _setRequestKeys()
+ {
+ if (null !== $this->_request) {
+ $this->_moduleKey = $this->_request->getModuleKey();
+ $this->_controllerKey = $this->_request->getControllerKey();
+ $this->_actionKey = $this->_request->getActionKey();
+ }
+
+ if (null !== $this->_dispatcher) {
+ $this->_defaults += array(
+ $this->_controllerKey => $this->_dispatcher->getDefaultControllerName(),
+ $this->_actionKey => $this->_dispatcher->getDefaultAction(),
+ $this->_moduleKey => $this->_dispatcher->getDefaultModule()
+ );
+ }
+
+ $this->_keysSet = true;
+ }
+
+ /**
+ * Matches a user submitted path. Assigns and returns an array of variables
+ * on a successful match.
+ *
+ * If a request object is registered, it uses its setModuleName(),
+ * setControllerName(), and setActionName() accessors to set those values.
+ * Always returns the values as an array.
+ *
+ * @param string $path Path used to match against this routing map
+ * @param boolean $partial
+ * @return array An array of assigned values or a false on a mismatch
+ */
+ public function match($path, $partial = false)
+ {
+ $this->_setRequestKeys();
+
+ $values = array();
+ $params = array();
+
+ if (!$partial) {
+ $path = trim($path, self::URI_DELIMITER);
+ } else {
+ $matchedPath = $path;
+ }
+
+ if ($path != '') {
+ $path = explode(self::URI_DELIMITER, $path);
+
+ if ($this->_dispatcher && $this->_dispatcher->isValidModule($path[0])) {
+ $values[$this->_moduleKey] = array_shift($path);
+ $this->_moduleValid = true;
+ }
+
+ if (count($path) && !empty($path[0])) {
+ $values[$this->_controllerKey] = array_shift($path);
+ }
+
+ if (count($path) && !empty($path[0])) {
+ $values[$this->_actionKey] = array_shift($path);
+ }
+
+ if ($numSegs = count($path)) {
+ for ($i = 0; $i < $numSegs; $i = $i + 2) {
+ $key = urldecode($path[$i]);
+ $val = isset($path[$i + 1]) ? urldecode($path[$i + 1]) : null;
+ $params[$key] = (isset($params[$key]) ? (array_merge((array)$params[$key], array($val))) : $val);
+ }
+ }
+ }
+
+ if ($partial) {
+ $this->setMatchedPath($matchedPath);
+ }
+
+ $this->_values = $values + $params;
+
+ return $this->_values + $this->_defaults;
+ }
+
+ /**
+ * Assembles user submitted parameters forming a URL path defined by this route
+ *
+ * @param array $data An array of variable and value pairs used as parameters
+ * @param boolean $reset Weither to reset the current params
+ * @param boolean $encode
+ * @param boolean $partial
+ * @return string Route path with user submitted parameters
+ */
+ public function assemble($data = array(), $reset = false, $encode = true, $partial = false)
+ {
+ if (!$this->_keysSet) {
+ $this->_setRequestKeys();
+ }
+
+ $params = (!$reset) ? $this->_values : array();
+
+ foreach ($data as $key => $value) {
+ if ($value !== null) {
+ $params[$key] = $value;
+ } elseif (isset($params[$key])) {
+ unset($params[$key]);
+ }
+ }
+
+ $params += $this->_defaults;
+
+ $url = '';
+
+ if ($this->_moduleValid || array_key_exists($this->_moduleKey, $data)) {
+ if ($params[$this->_moduleKey] != $this->_defaults[$this->_moduleKey]) {
+ $module = $params[$this->_moduleKey];
+ }
+ }
+ unset($params[$this->_moduleKey]);
+
+ $controller = $params[$this->_controllerKey];
+ unset($params[$this->_controllerKey]);
+
+ $action = $params[$this->_actionKey];
+ unset($params[$this->_actionKey]);
+
+ foreach ($params as $key => $value) {
+ $key = ($encode) ? urlencode($key) : $key;
+ if (is_array($value)) {
+ foreach ($value as $arrayValue) {
+ $arrayValue = ($encode) ? urlencode($arrayValue) : $arrayValue;
+ $url .= self::URI_DELIMITER . $key;
+ $url .= self::URI_DELIMITER . $arrayValue;
+ }
+ } else {
+ if ($encode) {
+ $value = urlencode($value);
+ }
+ $url .= self::URI_DELIMITER . $key;
+ $url .= self::URI_DELIMITER . $value;
+ }
+ }
+
+ if (!empty($url) || $action !== $this->_defaults[$this->_actionKey]) {
+ if ($encode) {
+ $action = urlencode($action);
+ }
+ $url = self::URI_DELIMITER . $action . $url;
+ }
+
+ if (!empty($url) || $controller !== $this->_defaults[$this->_controllerKey]) {
+ if ($encode) {
+ $controller = urlencode($controller);
+ }
+ $url = self::URI_DELIMITER . $controller . $url;
+ }
+
+ if (isset($module)) {
+ if ($encode) {
+ $module = urlencode($module);
+ }
+ $url = self::URI_DELIMITER . $module . $url;
+ }
+
+ return ltrim($url, self::URI_DELIMITER);
+ }
+
+ /**
+ * Return a single parameter of route's defaults
+ *
+ * @param string $name Array key of the parameter
+ * @return string Previously set default
+ */
+ public function getDefault($name)
+ {
+ if (isset($this->_defaults[$name])) {
+ return $this->_defaults[$name];
+ }
+ }
+
+ /**
+ * Return an array of defaults
+ *
+ * @return array Route defaults
+ */
+ public function getDefaults()
+ {
+ return $this->_defaults;
+ }
+}
diff --git a/lib/zend/Zend/Controller/Router/Route/Regex.php b/lib/zend/Zend/Controller/Router/Route/Regex.php
new file mode 100644
index 00000000000..e012357d7b3
--- /dev/null
+++ b/lib/zend/Zend/Controller/Router/Route/Regex.php
@@ -0,0 +1,319 @@
+defaults instanceof Zend_Config) ? $config->defaults->toArray() : array();
+ $map = ($config->map instanceof Zend_Config) ? $config->map->toArray() : array();
+ $reverse = (isset($config->reverse)) ? $config->reverse : null;
+
+ return new self($config->route, $defs, $map, $reverse);
+ }
+
+ /**
+ * Constructor
+ *
+ * @param $route
+ * @param array $defaults
+ * @param array $map
+ * @param null $reverse
+ */
+ public function __construct($route, $defaults = array(), $map = array(), $reverse = null)
+ {
+ $this->_regex = $route;
+ $this->_defaults = (array) $defaults;
+ $this->_map = (array) $map;
+ $this->_reverse = $reverse;
+ }
+
+ /**
+ * Get the version of the route
+ *
+ * @return int
+ */
+ public function getVersion()
+ {
+ return 1;
+ }
+
+ /**
+ * Matches a user submitted path with a previously defined route.
+ * Assigns and returns an array of defaults on a successful match.
+ *
+ * @param string $path Path used to match against this routing map
+ * @return array|false An array of assigned values or a false on a mismatch
+ */
+ public function match($path, $partial = false)
+ {
+ if (!$partial) {
+ $path = trim(urldecode($path), self::URI_DELIMITER);
+ $regex = '#^' . $this->_regex . '$#i';
+ } else {
+ $regex = '#^' . $this->_regex . '#i';
+ }
+
+ $res = preg_match($regex, $path, $values);
+
+ if ($res === 0) {
+ return false;
+ }
+
+ if ($partial) {
+ $this->setMatchedPath($values[0]);
+ }
+
+ // array_filter_key()? Why isn't this in a standard PHP function set yet? :)
+ foreach ($values as $i => $value) {
+ if (!is_int($i) || $i === 0) {
+ unset($values[$i]);
+ }
+ }
+
+ $this->_values = $values;
+
+ $values = $this->_getMappedValues($values);
+ $defaults = $this->_getMappedValues($this->_defaults, false, true);
+ $return = $values + $defaults;
+
+ return $return;
+ }
+
+ /**
+ * Maps numerically indexed array values to it's associative mapped counterpart.
+ * Or vice versa. Uses user provided map array which consists of index => name
+ * parameter mapping. If map is not found, it returns original array.
+ *
+ * Method strips destination type of keys form source array. Ie. if source array is
+ * indexed numerically then every associative key will be stripped. Vice versa if reversed
+ * is set to true.
+ *
+ * @param array $values Indexed or associative array of values to map
+ * @param boolean $reversed False means translation of index to association. True means reverse.
+ * @param boolean $preserve Should wrong type of keys be preserved or stripped.
+ * @return array An array of mapped values
+ */
+ protected function _getMappedValues($values, $reversed = false, $preserve = false)
+ {
+ if (count($this->_map) == 0) {
+ return $values;
+ }
+
+ $return = array();
+
+ foreach ($values as $key => $value) {
+ if (is_int($key) && !$reversed) {
+ if (array_key_exists($key, $this->_map)) {
+ $index = $this->_map[$key];
+ } elseif (false === ($index = array_search($key, $this->_map))) {
+ $index = $key;
+ }
+ $return[$index] = $values[$key];
+ } elseif ($reversed) {
+ $index = $key;
+ if (!is_int($key)) {
+ if (array_key_exists($key, $this->_map)) {
+ $index = $this->_map[$key];
+ } else {
+ $index = array_search($key, $this->_map, true);
+ }
+ }
+ if (false !== $index) {
+ $return[$index] = $values[$key];
+ }
+ } elseif ($preserve) {
+ $return[$key] = $value;
+ }
+ }
+
+ return $return;
+ }
+
+ /**
+ * Assembles a URL path defined by this route
+ *
+ * @param array $data An array of name (or index) and value pairs used as parameters
+ * @param boolean $reset
+ * @param boolean $encode
+ * @param boolean $partial
+ * @throws Zend_Controller_Router_Exception
+ * @return string Route path with user submitted parameters
+ */
+ public function assemble($data = array(), $reset = false, $encode = false, $partial = false)
+ {
+ if ($this->_reverse === null) {
+ require_once 'Zend/Controller/Router/Exception.php';
+ throw new Zend_Controller_Router_Exception('Cannot assemble. Reversed route is not specified.');
+ }
+
+ $defaultValuesMapped = $this->_getMappedValues($this->_defaults, true, false);
+ $matchedValuesMapped = $this->_getMappedValues($this->_values, true, false);
+ $dataValuesMapped = $this->_getMappedValues($data, true, false);
+
+ // handle resets, if so requested (By null value) to do so
+ if (($resetKeys = array_search(null, $dataValuesMapped, true)) !== false) {
+ foreach ((array)$resetKeys as $resetKey) {
+ if (isset($matchedValuesMapped[$resetKey])) {
+ unset($matchedValuesMapped[$resetKey]);
+ unset($dataValuesMapped[$resetKey]);
+ }
+ }
+ }
+
+ // merge all the data together, first defaults, then values matched, then supplied
+ $mergedData = $defaultValuesMapped;
+ $mergedData = $this->_arrayMergeNumericKeys($mergedData, $matchedValuesMapped);
+ $mergedData = $this->_arrayMergeNumericKeys($mergedData, $dataValuesMapped);
+
+ if ($encode) {
+ foreach ($mergedData as $key => &$value) {
+ $value = urlencode($value);
+ }
+ }
+
+ ksort($mergedData);
+
+ $return = @vsprintf($this->_reverse, $mergedData);
+
+ if ($return === false) {
+ require_once 'Zend/Controller/Router/Exception.php';
+ throw new Zend_Controller_Router_Exception('Cannot assemble. Too few arguments?');
+ }
+
+ return $return;
+ }
+
+ /**
+ * Return a single parameter of route's defaults
+ *
+ * @param string $name Array key of the parameter
+ * @return string Previously set default
+ */
+ public function getDefault($name)
+ {
+ if (isset($this->_defaults[$name])) {
+ return $this->_defaults[$name];
+ }
+ }
+
+ /**
+ * Return an array of defaults
+ *
+ * @return array Route defaults
+ */
+ public function getDefaults()
+ {
+ return $this->_defaults;
+ }
+
+ /**
+ * Get all variables which are used by the route
+ *
+ * @return array
+ */
+ public function getVariables()
+ {
+ $variables = array();
+
+ foreach ($this->_map as $key => $value) {
+ if (is_numeric($key)) {
+ $variables[] = $value;
+ } else {
+ $variables[] = $key;
+ }
+ }
+
+ return $variables;
+ }
+
+ /**
+ * _arrayMergeNumericKeys() - allows for a strict key (numeric's included) array_merge.
+ * php's array_merge() lacks the ability to merge with numeric keys.
+ *
+ * @param array $array1
+ * @param array $array2
+ * @return array
+ */
+ protected function _arrayMergeNumericKeys(Array $array1, Array $array2)
+ {
+ $returnArray = $array1;
+ foreach ($array2 as $array2Index => $array2Value) {
+ $returnArray[$array2Index] = $array2Value;
+ }
+
+ return $returnArray;
+ }
+}
diff --git a/lib/zend/Zend/Controller/Router/Route/Static.php b/lib/zend/Zend/Controller/Router/Route/Static.php
new file mode 100644
index 00000000000..4acd9f572ed
--- /dev/null
+++ b/lib/zend/Zend/Controller/Router/Route/Static.php
@@ -0,0 +1,149 @@
+defaults instanceof Zend_Config) ? $config->defaults->toArray() : array();
+
+ return new self($config->route, $defs);
+ }
+
+ /**
+ * Prepares the route for mapping.
+ *
+ * @param string $route Map used to match with later submitted URL path
+ * @param array $defaults Defaults for map variables with keys as variable names
+ */
+ public function __construct($route, $defaults = array())
+ {
+ $this->_route = trim($route, self::URI_DELIMITER);
+ $this->_defaults = (array) $defaults;
+ }
+
+ /**
+ * Matches a user submitted path with a previously defined route.
+ * Assigns and returns an array of defaults on a successful match.
+ *
+ * @param string $path Path used to match against this routing map
+ * @return array|false An array of assigned values or a false on a mismatch
+ */
+ public function match($path, $partial = false)
+ {
+ if ($partial) {
+ if ((empty($path) && empty($this->_route))
+ || (substr($path, 0, strlen($this->_route)) === $this->_route)
+ ) {
+ $this->setMatchedPath($this->_route);
+
+ return $this->_defaults;
+ }
+ } else {
+ if (trim($path, self::URI_DELIMITER) == $this->_route) {
+ return $this->_defaults;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Assembles a URL path defined by this route
+ *
+ * @param array $data An array of variable and value pairs used as parameters
+ * @return string Route path with user submitted parameters
+ */
+ public function assemble($data = array(), $reset = false, $encode = false, $partial = false)
+ {
+ return $this->_route;
+ }
+
+ /**
+ * Return a single parameter of route's defaults
+ *
+ * @param string $name Array key of the parameter
+ * @return string Previously set default
+ */
+ public function getDefault($name)
+ {
+ if (isset($this->_defaults[$name])) {
+ return $this->_defaults[$name];
+ }
+
+ return null;
+ }
+
+ /**
+ * Return an array of defaults
+ *
+ * @return array Route defaults
+ */
+ public function getDefaults()
+ {
+ return $this->_defaults;
+ }
+}
diff --git a/lib/zend/Zend/Crypt.php b/lib/zend/Zend/Crypt.php
new file mode 100644
index 00000000000..0ceeac71e33
--- /dev/null
+++ b/lib/zend/Zend/Crypt.php
@@ -0,0 +1,168 @@
+setPrime($prime);
+ $this->setGenerator($generator);
+ if ($privateKey !== null) {
+ $this->setPrivateKey($privateKey, $privateKeyType);
+ }
+ $this->setBigIntegerMath();
+ }
+
+ /**
+ * Generate own public key. If a private number has not already been
+ * set, one will be generated at this stage.
+ *
+ * @return Zend_Crypt_DiffieHellman
+ */
+ public function generateKeys()
+ {
+ if (function_exists('openssl_dh_compute_key') && self::$useOpenssl !== false) {
+ $details = array();
+ $details['p'] = $this->getPrime();
+ $details['g'] = $this->getGenerator();
+ if ($this->hasPrivateKey()) {
+ $details['priv_key'] = $this->getPrivateKey();
+ }
+ $opensslKeyResource = openssl_pkey_new( array('dh' => $details) );
+ $data = openssl_pkey_get_details($opensslKeyResource);
+ $this->setPrivateKey($data['dh']['priv_key'], self::BINARY);
+ $this->setPublicKey($data['dh']['pub_key'], self::BINARY);
+ } else {
+ // Private key is lazy generated in the absence of PHP 5.3's ext/openssl
+ $publicKey = $this->_math->powmod($this->getGenerator(), $this->getPrivateKey(), $this->getPrime());
+ $this->setPublicKey($publicKey);
+ }
+ return $this;
+ }
+
+ /**
+ * Setter for the value of the public number
+ *
+ * @param string $number
+ * @param string $type
+ * @throws Zend_Crypt_DiffieHellman_Exception
+ * @return Zend_Crypt_DiffieHellman
+ */
+ public function setPublicKey($number, $type = self::NUMBER)
+ {
+ if ($type == self::BINARY) {
+ $number = $this->_math->fromBinary($number);
+ }
+ if (!preg_match("/^\d+$/", $number)) {
+ require_once('Zend/Crypt/DiffieHellman/Exception.php');
+ throw new Zend_Crypt_DiffieHellman_Exception('invalid parameter; not a positive natural number');
+ }
+ $this->_publicKey = (string) $number;
+ return $this;
+ }
+
+ /**
+ * Returns own public key for communication to the second party to this
+ * transaction.
+ *
+ * @param string $type
+ * @throws Zend_Crypt_DiffieHellman_Exception
+ * @return string
+ */
+ public function getPublicKey($type = self::NUMBER)
+ {
+ if ($this->_publicKey === null) {
+ require_once 'Zend/Crypt/DiffieHellman/Exception.php';
+ throw new Zend_Crypt_DiffieHellman_Exception('A public key has not yet been generated using a prior call to generateKeys()');
+ }
+ if ($type == self::BINARY) {
+ return $this->_math->toBinary($this->_publicKey);
+ } elseif ($type == self::BTWOC) {
+ return $this->_math->btwoc($this->_math->toBinary($this->_publicKey));
+ }
+ return $this->_publicKey;
+ }
+
+ /**
+ * Compute the shared secret key based on the public key received from the
+ * the second party to this transaction. This should agree to the secret
+ * key the second party computes on our own public key.
+ * Once in agreement, the key is known to only to both parties.
+ * By default, the function expects the public key to be in binary form
+ * which is the typical format when being transmitted.
+ *
+ * If you need the binary form of the shared secret key, call
+ * getSharedSecretKey() with the optional parameter for Binary output.
+ *
+ * @param string $publicKey
+ * @param string $type
+ * @param string $output
+ * @throws Zend_Crypt_DiffieHellman_Exception
+ * @return mixed
+ */
+ public function computeSecretKey($publicKey, $type = self::NUMBER, $output = self::NUMBER)
+ {
+ if ($type == self::BINARY) {
+ $publicKey = $this->_math->fromBinary($publicKey);
+ }
+ if (!preg_match("/^\d+$/", $publicKey)) {
+ require_once('Zend/Crypt/DiffieHellman/Exception.php');
+ throw new Zend_Crypt_DiffieHellman_Exception('invalid parameter; not a positive natural number');
+ }
+ if (function_exists('openssl_dh_compute_key') && self::$useOpenssl !== false) {
+ $this->_secretKey = openssl_dh_compute_key($publicKey, $this->getPublicKey());
+ } else {
+ $this->_secretKey = $this->_math->powmod($publicKey, $this->getPrivateKey(), $this->getPrime());
+ }
+ return $this->getSharedSecretKey($output);
+ }
+
+ /**
+ * Return the computed shared secret key from the DiffieHellman transaction
+ *
+ * @param string $type
+ * @throws Zend_Crypt_DiffieHellman_Exception
+ * @return string
+ */
+ public function getSharedSecretKey($type = self::NUMBER)
+ {
+ if (!isset($this->_secretKey)) {
+ require_once('Zend/Crypt/DiffieHellman/Exception.php');
+ throw new Zend_Crypt_DiffieHellman_Exception('A secret key has not yet been computed; call computeSecretKey()');
+ }
+ if ($type == self::BINARY) {
+ return $this->_math->toBinary($this->_secretKey);
+ } elseif ($type == self::BTWOC) {
+ return $this->_math->btwoc($this->_math->toBinary($this->_secretKey));
+ }
+ return $this->_secretKey;
+ }
+
+ /**
+ * Setter for the value of the prime number
+ *
+ * @param string $number
+ * @throws Zend_Crypt_DiffieHellman_Exception
+ * @return Zend_Crypt_DiffieHellman
+ */
+ public function setPrime($number)
+ {
+ if (!preg_match("/^\d+$/", $number) || $number < 11) {
+ require_once('Zend/Crypt/DiffieHellman/Exception.php');
+ throw new Zend_Crypt_DiffieHellman_Exception('invalid parameter; not a positive natural number or too small: should be a large natural number prime');
+ }
+ $this->_prime = (string) $number;
+ return $this;
+ }
+
+ /**
+ * Getter for the value of the prime number
+ *
+ * @throws Zend_Crypt_DiffieHellman_Exception
+ * @return string
+ */
+ public function getPrime()
+ {
+ if (!isset($this->_prime)) {
+ require_once('Zend/Crypt/DiffieHellman/Exception.php');
+ throw new Zend_Crypt_DiffieHellman_Exception('No prime number has been set');
+ }
+ return $this->_prime;
+ }
+
+ /**
+ * Setter for the value of the generator number
+ *
+ * @param string $number
+ * @throws Zend_Crypt_DiffieHellman_Exception
+ * @return Zend_Crypt_DiffieHellman
+ */
+ public function setGenerator($number)
+ {
+ if (!preg_match("/^\d+$/", $number) || $number < 2) {
+ require_once('Zend/Crypt/DiffieHellman/Exception.php');
+ throw new Zend_Crypt_DiffieHellman_Exception('invalid parameter; not a positive natural number greater than 1');
+ }
+ $this->_generator = (string) $number;
+ return $this;
+ }
+
+ /**
+ * Getter for the value of the generator number
+ *
+ * @throws Zend_Crypt_DiffieHellman_Exception
+ * @return string
+ */
+ public function getGenerator()
+ {
+ if (!isset($this->_generator)) {
+ require_once('Zend/Crypt/DiffieHellman/Exception.php');
+ throw new Zend_Crypt_DiffieHellman_Exception('No generator number has been set');
+ }
+ return $this->_generator;
+ }
+
+ /**
+ * Setter for the value of the private number
+ *
+ * @param string $number
+ * @param string $type
+ * @throws Zend_Crypt_DiffieHellman_Exception
+ * @return Zend_Crypt_DiffieHellman
+ */
+ public function setPrivateKey($number, $type = self::NUMBER)
+ {
+ if ($type == self::BINARY) {
+ $number = $this->_math->fromBinary($number);
+ }
+ if (!preg_match("/^\d+$/", $number)) {
+ require_once('Zend/Crypt/DiffieHellman/Exception.php');
+ throw new Zend_Crypt_DiffieHellman_Exception('invalid parameter; not a positive natural number');
+ }
+ $this->_privateKey = (string) $number;
+ return $this;
+ }
+
+ /**
+ * Getter for the value of the private number
+ *
+ * @param string $type
+ * @return string
+ */
+ public function getPrivateKey($type = self::NUMBER)
+ {
+ if (!$this->hasPrivateKey()) {
+ $this->setPrivateKey($this->_generatePrivateKey(), self::BINARY);
+ }
+ if ($type == self::BINARY) {
+ return $this->_math->toBinary($this->_privateKey);
+ } elseif ($type == self::BTWOC) {
+ return $this->_math->btwoc($this->_math->toBinary($this->_privateKey));
+ }
+ return $this->_privateKey;
+ }
+
+ /**
+ * Check whether a private key currently exists.
+ *
+ * @return boolean
+ */
+ public function hasPrivateKey()
+ {
+ return isset($this->_privateKey);
+ }
+
+ /**
+ * Setter to pass an extension parameter which is used to create
+ * a specific BigInteger instance for a specific extension type.
+ * Allows manual setting of the class in case of an extension
+ * problem or bug.
+ *
+ * @param string $extension
+ * @return void
+ */
+ public function setBigIntegerMath($extension = null)
+ {
+ /**
+ * @see Zend_Crypt_Math
+ */
+ require_once 'Zend/Crypt/Math.php';
+ $this->_math = new Zend_Crypt_Math($extension);
+ }
+
+ /**
+ * In the event a private number/key has not been set by the user,
+ * or generated by ext/openssl, a best attempt will be made to
+ * generate a random key. Having a random number generator installed
+ * on linux/bsd is highly recommended! The alternative is not recommended
+ * for production unless without any other option.
+ *
+ * @return string
+ */
+ protected function _generatePrivateKey()
+ {
+ $rand = $this->_math->rand($this->getGenerator(), $this->getPrime());
+ return $rand;
+ }
+
+}
diff --git a/lib/zend/Zend/Crypt/DiffieHellman/Exception.php b/lib/zend/Zend/Crypt/DiffieHellman/Exception.php
new file mode 100644
index 00000000000..9afa43d6713
--- /dev/null
+++ b/lib/zend/Zend/Crypt/DiffieHellman/Exception.php
@@ -0,0 +1,36 @@
+80 using internal algo)
+ * @todo Check if mhash() is a required alternative (will be PECL-only soon)
+ * @category Zend
+ * @package Zend_Crypt
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license http://framework.zend.com/license/new-bsd New BSD License
+ */
+class Zend_Crypt_Hmac extends Zend_Crypt
+{
+
+ /**
+ * The key to use for the hash
+ *
+ * @var string
+ */
+ protected static $_key = null;
+
+ /**
+ * pack() format to be used for current hashing method
+ *
+ * @var string
+ */
+ protected static $_packFormat = null;
+
+ /**
+ * Hashing algorithm; can be the md5/sha1 functions or any algorithm name
+ * listed in the output of PHP 5.1.2+ hash_algos().
+ *
+ * @var string
+ */
+ protected static $_hashAlgorithm = 'md5';
+
+ /**
+ * List of algorithms supported my mhash()
+ *
+ * @var array
+ */
+ protected static $_supportedMhashAlgorithms = array('adler32',' crc32', 'crc32b', 'gost',
+ 'haval128', 'haval160', 'haval192', 'haval256', 'md4', 'md5', 'ripemd160',
+ 'sha1', 'sha256', 'tiger', 'tiger128', 'tiger160');
+
+ /**
+ * Constants representing the output mode of the hash algorithm
+ */
+ const STRING = 'string';
+ const BINARY = 'binary';
+
+ /**
+ * Performs a HMAC computation given relevant details such as Key, Hashing
+ * algorithm, the data to compute MAC of, and an output format of String,
+ * Binary notation or BTWOC.
+ *
+ * @param string $key
+ * @param string $hash
+ * @param string $data
+ * @param string $output
+ * @throws Zend_Crypt_Hmac_Exception
+ * @return string
+ */
+ public static function compute($key, $hash, $data, $output = self::STRING)
+ {
+ // set the key
+ if (!isset($key) || empty($key)) {
+ require_once 'Zend/Crypt/Hmac/Exception.php';
+ throw new Zend_Crypt_Hmac_Exception('provided key is null or empty');
+ }
+ self::$_key = $key;
+
+ // set the hash
+ self::_setHashAlgorithm($hash);
+
+ // perform hashing and return
+ return self::_hash($data, $output);
+ }
+
+ /**
+ * Setter for the hash method.
+ *
+ * @param string $hash
+ * @throws Zend_Crypt_Hmac_Exception
+ * @return Zend_Crypt_Hmac
+ */
+ protected static function _setHashAlgorithm($hash)
+ {
+ if (!isset($hash) || empty($hash)) {
+ require_once 'Zend/Crypt/Hmac/Exception.php';
+ throw new Zend_Crypt_Hmac_Exception('provided hash string is null or empty');
+ }
+
+ $hash = strtolower($hash);
+ $hashSupported = false;
+
+ if (function_exists('hash_algos') && in_array($hash, hash_algos())) {
+ $hashSupported = true;
+ }
+
+ if ($hashSupported === false && function_exists('mhash') && in_array($hash, self::$_supportedAlgosMhash)) {
+ $hashSupported = true;
+ }
+
+ if ($hashSupported === false) {
+ require_once 'Zend/Crypt/Hmac/Exception.php';
+ throw new Zend_Crypt_Hmac_Exception('hash algorithm provided is not supported on this PHP installation; please enable the hash or mhash extensions');
+ }
+ self::$_hashAlgorithm = $hash;
+ }
+
+ /**
+ * Perform HMAC and return the keyed data
+ *
+ * @param string $data
+ * @param string $output
+ * @param bool $internal Option to not use hash() functions for testing
+ * @return string
+ */
+ protected static function _hash($data, $output = self::STRING, $internal = false)
+ {
+ if (function_exists('hash_hmac')) {
+ if ($output == self::BINARY) {
+ return hash_hmac(self::$_hashAlgorithm, $data, self::$_key, true);
+ }
+ return hash_hmac(self::$_hashAlgorithm, $data, self::$_key);
+ }
+
+ if (function_exists('mhash')) {
+ if ($output == self::BINARY) {
+ return mhash(self::_getMhashDefinition(self::$_hashAlgorithm), $data, self::$_key);
+ }
+ $bin = mhash(self::_getMhashDefinition(self::$_hashAlgorithm), $data, self::$_key);
+ return bin2hex($bin);
+ }
+ }
+
+ /**
+ * Since MHASH accepts an integer constant representing the hash algorithm
+ * we need to make a small detour to get the correct integer matching our
+ * algorithm's name.
+ *
+ * @param string $hashAlgorithm
+ * @return integer
+ */
+ protected static function _getMhashDefinition($hashAlgorithm)
+ {
+ for ($i = 0; $i <= mhash_count(); $i++)
+ {
+ $types[mhash_get_hash_name($i)] = $i;
+ }
+ return $types[strtoupper($hashAlgorithm)];
+ }
+
+}
diff --git a/lib/zend/Zend/Crypt/Hmac/Exception.php b/lib/zend/Zend/Crypt/Hmac/Exception.php
new file mode 100644
index 00000000000..36acda37e76
--- /dev/null
+++ b/lib/zend/Zend/Crypt/Hmac/Exception.php
@@ -0,0 +1,36 @@
+ 127) {
+ return "\x00" . $long;
+ }
+ return $long;
+ }
+
+ /**
+ * Translate a binary form into a big integer string
+ *
+ * @param string $binary
+ * @return string
+ */
+ public function fromBinary($binary) {
+ return $this->_math->binaryToInteger($binary);
+ }
+
+ /**
+ * Translate a big integer string into a binary form
+ *
+ * @param string $integer
+ * @return string
+ */
+ public function toBinary($integer)
+ {
+ return $this->_math->integerToBinary($integer);
+ }
+
+}
diff --git a/lib/zend/Zend/Crypt/Math/BigInteger.php b/lib/zend/Zend/Crypt/Math/BigInteger.php
new file mode 100644
index 00000000000..e066f608513
--- /dev/null
+++ b/lib/zend/Zend/Crypt/Math/BigInteger.php
@@ -0,0 +1,118 @@
+_loadAdapter($extension);
+ }
+
+ /**
+ * Redirect all public method calls to the wrapped extension object.
+ *
+ * @param string $methodName
+ * @param array $args
+ * @return mixed
+ * @throws Zend_Crypt_Math_BigInteger_Exception
+ */
+ public function __call($methodName, $args)
+ {
+ if(!method_exists($this->_math, $methodName)) {
+ require_once 'Zend/Crypt/Math/BigInteger/Exception.php';
+ throw new Zend_Crypt_Math_BigInteger_Exception('invalid method call: ' . get_class($this->_math) . '::' . $methodName . '() does not exist');
+ }
+ return call_user_func_array(array($this->_math, $methodName), $args);
+ }
+
+ /**
+ * @param string $extension
+ * @throws Zend_Crypt_Math_BigInteger_Exception
+ */
+ protected function _loadAdapter($extension = null)
+ {
+ if ($extension === null) {
+ if (extension_loaded('gmp')) {
+ $extension = 'gmp';
+ //} elseif (extension_loaded('big_int')) {
+ // $extension = 'big_int';
+ } else {
+ $extension = 'bcmath';
+ }
+ }
+ if($extension == 'gmp' && extension_loaded('gmp')) {
+ require_once 'Zend/Crypt/Math/BigInteger/Gmp.php';
+ $this->_math = new Zend_Crypt_Math_BigInteger_Gmp();
+ //} elseif($extension == 'bigint' && extension_loaded('big_int')) {
+ // require_once 'Zend/Crypt_Math/BigInteger/Bigint.php';
+ // $this->_math = new Zend_Crypt_Math_BigInteger_Bigint();
+ } elseif ($extension == 'bcmath' && extension_loaded('bcmath')) {
+ require_once 'Zend/Crypt/Math/BigInteger/Bcmath.php';
+ $this->_math = new Zend_Crypt_Math_BigInteger_Bcmath();
+ } else {
+ require_once 'Zend/Crypt/Math/BigInteger/Exception.php';
+ throw new Zend_Crypt_Math_BigInteger_Exception($extension . ' big integer precision math support not detected');
+ }
+ }
+
+}
diff --git a/lib/zend/Zend/Crypt/Math/BigInteger/Bcmath.php b/lib/zend/Zend/Crypt/Math/BigInteger/Bcmath.php
new file mode 100644
index 00000000000..40154b6fbb0
--- /dev/null
+++ b/lib/zend/Zend/Crypt/Math/BigInteger/Bcmath.php
@@ -0,0 +1,227 @@
+ 0) {
+ $return = chr(bcmod($operand, 256)) . $return;
+ $operand = bcdiv($operand, 256);
+ }
+ if (ord($return[0]) > 127) {
+ $return = "\0" . $return;
+ }
+ return $return;
+ }
+
+ /**public function integerToBinary($operand)
+ {
+ $return = '';
+ while(bccomp($operand, '0')) {
+ $return .= chr(bcmod($operand, '256'));
+ $operand = bcdiv($operand, '256');
+ }
+ return $return;
+ }**/ // Prior version for referenced offset
+
+ /**
+ * @param string $operand
+ * @return string
+ */
+ public function hexToDecimal($operand)
+ {
+ $return = '0';
+ while(strlen($hex)) {
+ $hex = hexdec(substr($operand, 0, 4));
+ $dec = bcadd(bcmul($return, 65536), $hex);
+ $operand = substr($operand, 4);
+ }
+ return $return;
+ }
+}
diff --git a/lib/zend/Zend/Crypt/Math/BigInteger/Exception.php b/lib/zend/Zend/Crypt/Math/BigInteger/Exception.php
new file mode 100644
index 00000000000..d5ee2e6ddf0
--- /dev/null
+++ b/lib/zend/Zend/Crypt/Math/BigInteger/Exception.php
@@ -0,0 +1,36 @@
+ '7') {
+ $bigInt = '00' . $bigInt;
+ }
+ $return = pack("H*", $bigInt);
+ return $return;
+ }
+
+ /**
+ * @param string $operand
+ * @return string
+ */
+ public function hexToDecimal($operand)
+ {
+ $return = '0';
+ while(strlen($hex)) {
+ $hex = hexdec(substr($operand, 0, 4));
+ $dec = gmp_add(gmp_mul($return, 65536), $hex);
+ $operand = substr($operand, 4);
+ }
+ return $return;
+ }
+
+}
diff --git a/lib/zend/Zend/Crypt/Math/BigInteger/Interface.php b/lib/zend/Zend/Crypt/Math/BigInteger/Interface.php
new file mode 100644
index 00000000000..9fa92815e30
--- /dev/null
+++ b/lib/zend/Zend/Crypt/Math/BigInteger/Interface.php
@@ -0,0 +1,51 @@
+_hashAlgorithm = OPENSSL_ALGO_SHA1;
+
+ if (isset($options)) {
+ $this->setOptions($options);
+ }
+ }
+
+ public function setOptions(array $options)
+ {
+ if (isset($options['passPhrase'])) {
+ $this->_passPhrase = $options['passPhrase'];
+ }
+ foreach ($options as $option=>$value) {
+ switch ($option) {
+ case 'pemString':
+ $this->setPemString($value);
+ break;
+ case 'pemPath':
+ $this->setPemPath($value);
+ break;
+ case 'certificateString':
+ $this->setCertificateString($value);
+ break;
+ case 'certificatePath':
+ $this->setCertificatePath($value);
+ break;
+ case 'hashAlgorithm':
+ $this->setHashAlgorithm($value);
+ break;
+ }
+ }
+ }
+
+ public function getPrivateKey()
+ {
+ return $this->_privateKey;
+ }
+
+ public function getPublicKey()
+ {
+ return $this->_publicKey;
+ }
+
+ /**
+ * @param string $data
+ * @param Zend_Crypt_Rsa_Key_Private $privateKey
+ * @param string $format
+ * @return string
+ */
+ public function sign($data, Zend_Crypt_Rsa_Key_Private $privateKey = null, $format = null)
+ {
+ $signature = '';
+ if (isset($privateKey)) {
+ $opensslKeyResource = $privateKey->getOpensslKeyResource();
+ } else {
+ $opensslKeyResource = $this->_privateKey->getOpensslKeyResource();
+ }
+ $result = openssl_sign(
+ $data, $signature,
+ $opensslKeyResource,
+ $this->getHashAlgorithm()
+ );
+ if ($format == self::BASE64) {
+ return base64_encode($signature);
+ }
+ return $signature;
+ }
+
+ /**
+ * @param string $data
+ * @param string $signature
+ * @param string $format
+ * @return string
+ */
+ public function verifySignature($data, $signature, $format = null)
+ {
+ if ($format == self::BASE64) {
+ $signature = base64_decode($signature);
+ }
+ $result = openssl_verify($data, $signature,
+ $this->getPublicKey()->getOpensslKeyResource(),
+ $this->getHashAlgorithm());
+ return $result;
+ }
+
+ /**
+ * @param string $data
+ * @param Zend_Crypt_Rsa_Key $key
+ * @param string $format
+ * @return string
+ */
+ public function encrypt($data, Zend_Crypt_Rsa_Key $key, $format = null)
+ {
+ $encrypted = '';
+ $function = 'openssl_public_encrypt';
+ if ($key instanceof Zend_Crypt_Rsa_Key_Private) {
+ $function = 'openssl_private_encrypt';
+ }
+ $function($data, $encrypted, $key->getOpensslKeyResource());
+ if ($format == self::BASE64) {
+ return base64_encode($encrypted);
+ }
+ return $encrypted;
+ }
+
+ /**
+ * @param string $data
+ * @param Zend_Crypt_Rsa_Key $key
+ * @param string $format
+ * @return string
+ */
+ public function decrypt($data, Zend_Crypt_Rsa_Key $key, $format = null)
+ {
+ $decrypted = '';
+ if ($format == self::BASE64) {
+ $data = base64_decode($data);
+ }
+ $function = 'openssl_private_decrypt';
+ if ($key instanceof Zend_Crypt_Rsa_Key_Public) {
+ $function = 'openssl_public_decrypt';
+ }
+ $function($data, $decrypted, $key->getOpensslKeyResource());
+ return $decrypted;
+ }
+
+ /**
+ * @param array $configargs
+ *
+ * @throws Zend_Crypt_Rsa_Exception
+ *
+ * @return ArrayObject
+ */
+ public function generateKeys(array $configargs = null)
+ {
+ $config = null;
+ $passPhrase = null;
+ if ($configargs !== null) {
+ if (isset($configargs['passPhrase'])) {
+ $passPhrase = $configargs['passPhrase'];
+ unset($configargs['passPhrase']);
+ }
+ $config = $this->_parseConfigArgs($configargs);
+ }
+ $privateKey = null;
+ $publicKey = null;
+ $resource = openssl_pkey_new($config);
+ if (!$resource) {
+ require_once 'Zend/Crypt/Rsa/Exception.php';
+ throw new Zend_Crypt_Rsa_Exception('Failed to generate a new private key');
+ }
+ // above fails on PHP 5.3
+ openssl_pkey_export($resource, $private, $passPhrase);
+ $privateKey = new Zend_Crypt_Rsa_Key_Private($private, $passPhrase);
+ $details = openssl_pkey_get_details($resource);
+ $publicKey = new Zend_Crypt_Rsa_Key_Public($details['key']);
+ $return = new ArrayObject(array(
+ 'privateKey'=>$privateKey,
+ 'publicKey'=>$publicKey
+ ), ArrayObject::ARRAY_AS_PROPS);
+ return $return;
+ }
+
+ /**
+ * @param string $value
+ */
+ public function setPemString($value)
+ {
+ $this->_pemString = $value;
+ try {
+ $this->_privateKey = new Zend_Crypt_Rsa_Key_Private($this->_pemString, $this->_passPhrase);
+ $this->_publicKey = $this->_privateKey->getPublicKey();
+ } catch (Zend_Crypt_Exception $e) {
+ $this->_privateKey = null;
+ $this->_publicKey = new Zend_Crypt_Rsa_Key_Public($this->_pemString);
+ }
+ }
+
+ public function setPemPath($value)
+ {
+ $this->_pemPath = $value;
+ $this->setPemString(file_get_contents($this->_pemPath));
+ }
+
+ public function setCertificateString($value)
+ {
+ $this->_certificateString = $value;
+ $this->_publicKey = new Zend_Crypt_Rsa_Key_Public($this->_certificateString, $this->_passPhrase);
+ }
+
+ public function setCertificatePath($value)
+ {
+ $this->_certificatePath = $value;
+ $this->setCertificateString(file_get_contents($this->_certificatePath));
+ }
+
+ public function setHashAlgorithm($name)
+ {
+ switch (strtolower($name)) {
+ case 'md2':
+ $this->_hashAlgorithm = OPENSSL_ALGO_MD2;
+ break;
+ case 'md4':
+ $this->_hashAlgorithm = OPENSSL_ALGO_MD4;
+ break;
+ case 'md5':
+ $this->_hashAlgorithm = OPENSSL_ALGO_MD5;
+ break;
+ case 'sha1':
+ $this->_hashAlgorithm = OPENSSL_ALGO_SHA1;
+ break;
+ case 'dss1':
+ $this->_hashAlgorithm = OPENSSL_ALGO_DSS1;
+ break;
+ }
+ }
+
+ /**
+ * @return string
+ */
+ public function getPemString()
+ {
+ return $this->_pemString;
+ }
+
+ public function getPemPath()
+ {
+ return $this->_pemPath;
+ }
+
+ public function getCertificateString()
+ {
+ return $this->_certificateString;
+ }
+
+ public function getCertificatePath()
+ {
+ return $this->_certificatePath;
+ }
+
+ public function getHashAlgorithm()
+ {
+ return $this->_hashAlgorithm;
+ }
+
+ protected function _parseConfigArgs(array $config = null)
+ {
+ $configs = array();
+ if (isset($config['private_key_bits'])) {
+ $configs['private_key_bits'] = $config['private_key_bits'];
+ }
+ if (isset($config['privateKeyBits'])) {
+ $configs['private_key_bits'] = $config['privateKeyBits'];
+ }
+ if (!empty($configs)) {
+ return $configs;
+ }
+ return null;
+ }
+
+}
diff --git a/lib/zend/Zend/Crypt/Rsa/Exception.php b/lib/zend/Zend/Crypt/Rsa/Exception.php
new file mode 100644
index 00000000000..f1cf65e86ac
--- /dev/null
+++ b/lib/zend/Zend/Crypt/Rsa/Exception.php
@@ -0,0 +1,36 @@
+_opensslKeyResource;
+ }
+
+ /**
+ * @return string
+ * @throws Zend_Crypt_Exception
+ */
+ public function toString()
+ {
+ if (!empty($this->_pemString)) {
+ return $this->_pemString;
+ } elseif (!empty($this->_certificateString)) {
+ return $this->_certificateString;
+ }
+ /**
+ * @see Zend_Crypt_Exception
+ */
+ require_once 'Zend/Crypt/Exception.php';
+ throw new Zend_Crypt_Exception('No public key string representation is available');
+ }
+
+ /**
+ * @return string
+ */
+ public function __toString()
+ {
+ return $this->toString();
+ }
+
+ public function count()
+ {
+ return $this->_details['bits'];
+ }
+
+ public function getType()
+ {
+ return $this->_details['type'];
+ }
+}
diff --git a/lib/zend/Zend/Crypt/Rsa/Key/Private.php b/lib/zend/Zend/Crypt/Rsa/Key/Private.php
new file mode 100644
index 00000000000..98b2e026c24
--- /dev/null
+++ b/lib/zend/Zend/Crypt/Rsa/Key/Private.php
@@ -0,0 +1,75 @@
+_pemString = $pemString;
+ $this->_parse($passPhrase);
+ }
+
+ /**
+ * @param string $passPhrase
+ * @throws Zend_Crypt_Exception
+ */
+ protected function _parse($passPhrase)
+ {
+ $result = openssl_get_privatekey($this->_pemString, $passPhrase);
+ if (!$result) {
+ /**
+ * @see Zend_Crypt_Exception
+ */
+ require_once 'Zend/Crypt/Exception.php';
+ throw new Zend_Crypt_Exception('Unable to load private key');
+ }
+ $this->_opensslKeyResource = $result;
+ $this->_details = openssl_pkey_get_details($this->_opensslKeyResource);
+ }
+
+ public function getPublicKey()
+ {
+ if ($this->_publicKey === null) {
+ /**
+ * @see Zend_Crypt_Rsa_Key_Public
+ */
+ require_once 'Zend/Crypt/Rsa/Key/Public.php';
+ $this->_publicKey = new Zend_Crypt_Rsa_Key_Public($this->_details['key']);
+ }
+ return $this->_publicKey;
+ }
+
+}
diff --git a/lib/zend/Zend/Crypt/Rsa/Key/Public.php b/lib/zend/Zend/Crypt/Rsa/Key/Public.php
new file mode 100644
index 00000000000..9694342d17b
--- /dev/null
+++ b/lib/zend/Zend/Crypt/Rsa/Key/Public.php
@@ -0,0 +1,74 @@
+_parse($string);
+ }
+
+ /**
+ * @param string $string
+ * @throws Zend_Crypt_Exception
+ */
+ protected function _parse($string)
+ {
+ if (preg_match("/^-----BEGIN CERTIFICATE-----/", $string)) {
+ $this->_certificateString = $string;
+ } else {
+ $this->_pemString = $string;
+ }
+ $result = openssl_get_publickey($string);
+ if (!$result) {
+ /**
+ * @see Zend_Crypt_Exception
+ */
+ require_once 'Zend/Crypt/Exception.php';
+ throw new Zend_Crypt_Exception('Unable to load public key');
+ }
+ //openssl_pkey_export($result, $public);
+ //$this->_pemString = $public;
+ $this->_opensslKeyResource = $result;
+ $this->_details = openssl_pkey_get_details($this->_opensslKeyResource);
+ }
+
+ public function getCertificate()
+ {
+ return $this->_certificateString;
+ }
+
+}
diff --git a/lib/zend/Zend/Currency.php b/lib/zend/Zend/Currency.php
new file mode 100644
index 00000000000..9abc8b19989
--- /dev/null
+++ b/lib/zend/Zend/Currency.php
@@ -0,0 +1,902 @@
+ Position for the currency sign
+ * 'script' => Script for the output
+ * 'format' => Locale for numeric output
+ * 'display' => Currency detail to show
+ * 'precision' => Precision for the currency
+ * 'name' => Name for this currency
+ * 'currency' => 3 lettered international abbreviation
+ * 'symbol' => Currency symbol
+ * 'locale' => Locale for this currency
+ * 'value' => Money value
+ * 'service' => Exchange service to use
+ *
+ * @var array
+ * @see Zend_Locale
+ */
+ protected $_options = array(
+ 'position' => self::STANDARD,
+ 'script' => null,
+ 'format' => null,
+ 'display' => self::NO_SYMBOL,
+ 'precision' => 2,
+ 'name' => null,
+ 'currency' => null,
+ 'symbol' => null,
+ 'locale' => null,
+ 'value' => 0,
+ 'service' => null,
+ 'tag' => 'Zend_Locale'
+ );
+
+ /**
+ * Creates a currency instance. Every supressed parameter is used from the actual or the given locale.
+ *
+ * @param string|array $options OPTIONAL Options array or currency short name
+ * when string is given
+ * @param string|Zend_Locale $locale OPTIONAL locale name
+ * @throws Zend_Currency_Exception When currency is invalid
+ */
+ public function __construct($options = null, $locale = null)
+ {
+ $calloptions = $options;
+ if (is_array($options) && isset($options['display'])) {
+ $this->_options['display'] = $options['display'];
+ }
+
+ if (is_array($options)) {
+ $this->setLocale($locale);
+ $this->setFormat($options);
+ } else if (Zend_Locale::isLocale($options, false, false)) {
+ $this->setLocale($options);
+ $options = $locale;
+ } else {
+ $this->setLocale($locale);
+ }
+
+ // Get currency details
+ if (!isset($this->_options['currency']) || !is_array($options)) {
+ $this->_options['currency'] = self::getShortName($options, $this->_options['locale']);
+ }
+
+ if (!isset($this->_options['name']) || !is_array($options)) {
+ $this->_options['name'] = self::getName($options, $this->_options['locale']);
+ }
+
+ if (!isset($this->_options['symbol']) || !is_array($options)) {
+ $this->_options['symbol'] = self::getSymbol($options, $this->_options['locale']);
+ }
+
+ if (($this->_options['currency'] === null) and ($this->_options['name'] === null)) {
+ require_once 'Zend/Currency/Exception.php';
+ throw new Zend_Currency_Exception("Currency '$options' not found");
+ }
+
+ // Get the format
+ if ((is_array($calloptions) && !isset($calloptions['display']))
+ || (!is_array($calloptions) && $this->_options['display'] == self::NO_SYMBOL)) {
+ if (!empty($this->_options['symbol'])) {
+ $this->_options['display'] = self::USE_SYMBOL;
+ } else if (!empty($this->_options['currency'])) {
+ $this->_options['display'] = self::USE_SHORTNAME;
+ }
+ }
+ }
+
+ /**
+ * Returns a localized currency string
+ *
+ * @param integer|float $value OPTIONAL Currency value
+ * @param array $options OPTIONAL options to set temporary
+ * @throws Zend_Currency_Exception When the value is not a number
+ * @return string
+ */
+ public function toCurrency($value = null, array $options = array())
+ {
+ if ($value === null) {
+ if (is_array($options) && isset($options['value'])) {
+ $value = $options['value'];
+ } else {
+ $value = $this->_options['value'];
+ }
+ }
+
+ if (is_array($value)) {
+ $options += $value;
+ if (isset($options['value'])) {
+ $value = $options['value'];
+ }
+ }
+
+ // Validate the passed number
+ if (!(isset($value)) or (is_numeric($value) === false)) {
+ require_once 'Zend/Currency/Exception.php';
+ throw new Zend_Currency_Exception("Value '$value' has to be numeric");
+ }
+
+ if (isset($options['currency'])) {
+ if (!isset($options['locale'])) {
+ $options['locale'] = $this->_options['locale'];
+ }
+
+ $options['currency'] = self::getShortName($options['currency'], $options['locale']);
+ $options['name'] = self::getName($options['currency'], $options['locale']);
+ $options['symbol'] = self::getSymbol($options['currency'], $options['locale']);
+ }
+
+ $options = $this->_checkOptions($options) + $this->_options;
+
+ // Format the number
+ $format = $options['format'];
+ $locale = $options['locale'];
+ if (empty($format)) {
+ $format = Zend_Locale_Data::getContent($locale, 'currencynumber');
+ } else if (Zend_Locale::isLocale($format, true, false)) {
+ $locale = $format;
+ $format = Zend_Locale_Data::getContent($format, 'currencynumber');
+ }
+
+ $original = $value;
+ $value = Zend_Locale_Format::toNumber($value, array('locale' => $locale,
+ 'number_format' => $format,
+ 'precision' => $options['precision']));
+
+ if ($options['position'] !== self::STANDARD) {
+ $value = str_replace('¤', '', $value);
+ $space = '';
+ if (iconv_strpos($value, ' ') !== false) {
+ $value = str_replace(' ', '', $value);
+ $space = ' ';
+ }
+
+ if ($options['position'] == self::LEFT) {
+ $value = '¤' . $space . $value;
+ } else {
+ $value = $value . $space . '¤';
+ }
+ }
+
+ // Localize the number digits
+ if (empty($options['script']) === false) {
+ $value = Zend_Locale_Format::convertNumerals($value, 'Latn', $options['script']);
+ }
+
+ // Get the sign to be placed next to the number
+ if (is_numeric($options['display']) === false) {
+ $sign = $options['display'];
+ } else {
+ switch($options['display']) {
+ case self::USE_SYMBOL:
+ $sign = $this->_extractPattern($options['symbol'], $original);
+ break;
+
+ case self::USE_SHORTNAME:
+ $sign = $options['currency'];
+ break;
+
+ case self::USE_NAME:
+ $sign = $options['name'];
+ break;
+
+ default:
+ $sign = '';
+ $value = str_replace(' ', '', $value);
+ break;
+ }
+ }
+
+ $value = str_replace('¤', $sign, $value);
+ return $value;
+ }
+
+ /**
+ * Internal method to extract the currency pattern
+ * when a choice is given based on the given value
+ *
+ * @param string $pattern
+ * @param float|integer $value
+ * @return string
+ */
+ private function _extractPattern($pattern, $value)
+ {
+ if (strpos($pattern, '|') === false) {
+ return $pattern;
+ }
+
+ $patterns = explode('|', $pattern);
+ $token = $pattern;
+ $value = trim(str_replace('¤', '', $value));
+ krsort($patterns);
+ foreach($patterns as $content) {
+ if (strpos($content, '<') !== false) {
+ $check = iconv_substr($content, 0, iconv_strpos($content, '<'));
+ $token = iconv_substr($content, iconv_strpos($content, '<') + 1);
+ if ($check < $value) {
+ return $token;
+ }
+ } else {
+ $check = iconv_substr($content, 0, iconv_strpos($content, '≤'));
+ $token = iconv_substr($content, iconv_strpos($content, '≤') + 1);
+ if ($check <= $value) {
+ return $token;
+ }
+ }
+
+ }
+
+ return $token;
+ }
+
+ /**
+ * Sets the formating options of the localized currency string
+ * If no parameter is passed, the standard setting of the
+ * actual set locale will be used
+ *
+ * @param array $options (Optional) Options to set
+ * @return Zend_Currency
+ */
+ public function setFormat(array $options = array())
+ {
+ $this->_options = $this->_checkOptions($options) + $this->_options;
+ return $this;
+ }
+
+ /**
+ * Internal function for checking static given locale parameter
+ *
+ * @param string $currency (Optional) Currency name
+ * @param string|Zend_Locale $locale (Optional) Locale to display informations
+ * @throws Zend_Currency_Exception When locale contains no region
+ * @return string The extracted locale representation as string
+ */
+ private function _checkParams($currency = null, $locale = null)
+ {
+ // Manage the params
+ if ((empty($locale)) and (!empty($currency)) and
+ (Zend_Locale::isLocale($currency, true, false))) {
+ $locale = $currency;
+ $currency = null;
+ }
+
+ // Validate the locale and get the country short name
+ $country = null;
+ if ((Zend_Locale::isLocale($locale, true, false)) and (strlen($locale) > 4)) {
+ $country = substr($locale, (strpos($locale, '_') + 1));
+ } else {
+ require_once 'Zend/Currency/Exception.php';
+ throw new Zend_Currency_Exception("No region found within the locale '" . (string) $locale . "'");
+ }
+
+ // Get the available currencies for this country
+ $data = Zend_Locale_Data::getContent($locale, 'currencytoregion', $country);
+ if ((empty($currency) === false) and (empty($data) === false)) {
+ $abbreviation = $currency;
+ } else {
+ $abbreviation = $data;
+ }
+
+ return array('locale' => $locale, 'currency' => $currency, 'name' => $abbreviation, 'country' => $country);
+ }
+
+ /**
+ * Returns the actual or details of other currency symbols,
+ * when no symbol is available it returns the currency shortname (f.e. FIM for Finnian Mark)
+ *
+ * @param string $currency (Optional) Currency name
+ * @param string|Zend_Locale $locale (Optional) Locale to display informations
+ * @return string
+ */
+ public function getSymbol($currency = null, $locale = null)
+ {
+ if (($currency === null) and ($locale === null)) {
+ return $this->_options['symbol'];
+ }
+
+ $params = self::_checkParams($currency, $locale);
+
+ // Get the symbol
+ $symbol = Zend_Locale_Data::getContent($params['locale'], 'currencysymbol', $params['currency']);
+ if (empty($symbol) === true) {
+ $symbol = Zend_Locale_Data::getContent($params['locale'], 'currencysymbol', $params['name']);
+ }
+
+ if (empty($symbol) === true) {
+ return null;
+ }
+
+ return $symbol;
+ }
+
+ /**
+ * Returns the actual or details of other currency shortnames
+ *
+ * @param string $currency OPTIONAL Currency's name
+ * @param string|Zend_Locale $locale OPTIONAL The locale
+ * @return string
+ */
+ public function getShortName($currency = null, $locale = null)
+ {
+ if (($currency === null) and ($locale === null)) {
+ return $this->_options['currency'];
+ }
+
+ $params = self::_checkParams($currency, $locale);
+
+ // Get the shortname
+ if (empty($params['currency']) === true) {
+ return $params['name'];
+ }
+
+ $list = Zend_Locale_Data::getContent($params['locale'], 'currencytoname', $params['currency']);
+ if (empty($list) === true) {
+ $list = Zend_Locale_Data::getContent($params['locale'], 'nametocurrency', $params['currency']);
+ if (empty($list) === false) {
+ $list = $params['currency'];
+ }
+ }
+
+ if (empty($list) === true) {
+ return null;
+ }
+
+ return $list;
+ }
+
+ /**
+ * Returns the actual or details of other currency names
+ *
+ * @param string $currency (Optional) Currency's short name
+ * @param string|Zend_Locale $locale (Optional) The locale
+ * @return string
+ */
+ public function getName($currency = null, $locale = null)
+ {
+ if (($currency === null) and ($locale === null)) {
+ return $this->_options['name'];
+ }
+
+ $params = self::_checkParams($currency, $locale);
+
+ // Get the name
+ $name = Zend_Locale_Data::getContent($params['locale'], 'nametocurrency', $params['currency']);
+ if (empty($name) === true) {
+ $name = Zend_Locale_Data::getContent($params['locale'], 'nametocurrency', $params['name']);
+ }
+
+ if (empty($name) === true) {
+ return null;
+ }
+
+ return $name;
+ }
+
+ /**
+ * Returns a list of regions where this currency is or was known
+ *
+ * @param string $currency OPTIONAL Currency's short name
+ * @throws Zend_Currency_Exception When no currency was defined
+ * @return array List of regions
+ */
+ public function getRegionList($currency = null)
+ {
+ if ($currency === null) {
+ $currency = $this->_options['currency'];
+ }
+
+ if (empty($currency) === true) {
+ require_once 'Zend/Currency/Exception.php';
+ throw new Zend_Currency_Exception('No currency defined');
+ }
+
+ $data = Zend_Locale_Data::getContent($this->_options['locale'], 'regiontocurrency', $currency);
+
+ $result = explode(' ', $data);
+ return $result;
+ }
+
+ /**
+ * Returns a list of currencies which are used in this region
+ * a region name should be 2 charachters only (f.e. EG, DE, US)
+ * If no region is given, the actual region is used
+ *
+ * @param string $region OPTIONAL Region to return the currencies for
+ * @return array List of currencies
+ */
+ public function getCurrencyList($region = null)
+ {
+ if (empty($region) === true) {
+ if (strlen($this->_options['locale']) > 4) {
+ $region = substr($this->_options['locale'], (strpos($this->_options['locale'], '_') + 1));
+ }
+ }
+
+ $data = Zend_Locale_Data::getContent($this->_options['locale'], 'currencytoregion', $region);
+
+ $result = explode(' ', $data);
+ return $result;
+ }
+
+ /**
+ * Returns the actual currency name
+ *
+ * @return string
+ */
+ public function toString()
+ {
+ return $this->toCurrency();
+ }
+
+ /**
+ * Returns the currency name
+ *
+ * @return string
+ */
+ public function __toString()
+ {
+ return $this->toString();
+ }
+
+ /**
+ * Returns the set cache
+ *
+ * @return Zend_Cache_Core The set cache
+ */
+ public static function getCache()
+ {
+ return Zend_Locale_Data::getCache();
+ }
+
+ /**
+ * Sets a cache for Zend_Currency
+ *
+ * @param Zend_Cache_Core $cache Cache to set
+ * @return void
+ */
+ public static function setCache(Zend_Cache_Core $cache)
+ {
+ Zend_Locale_Data::setCache($cache);
+ }
+
+ /**
+ * Returns true when a cache is set
+ *
+ * @return boolean
+ */
+ public static function hasCache()
+ {
+ return Zend_Locale_Data::hasCache();
+ }
+
+ /**
+ * Removes any set cache
+ *
+ * @return void
+ */
+ public static function removeCache()
+ {
+ Zend_Locale_Data::removeCache();
+ }
+
+ /**
+ * Clears all set cache data
+ *
+ * @param string $tag Tag to clear when the default tag name is not used
+ * @return void
+ */
+ public static function clearCache($tag = null)
+ {
+ Zend_Locale_Data::clearCache($tag);
+ }
+
+ /**
+ * Sets a new locale for data retreivement
+ * Example: 'de_XX' will be set to 'de' because 'de_XX' does not exist
+ * 'xx_YY' will be set to 'root' because 'xx' does not exist
+ *
+ * @param string|Zend_Locale $locale (Optional) Locale for parsing input
+ * @throws Zend_Currency_Exception When the given locale does not exist
+ * @return Zend_Currency Provides fluent interface
+ */
+ public function setLocale($locale = null)
+ {
+ require_once 'Zend/Locale.php';
+ try {
+ $locale = Zend_Locale::findLocale($locale);
+ if (strlen($locale) > 4) {
+ $this->_options['locale'] = $locale;
+ } else {
+ require_once 'Zend/Currency/Exception.php';
+ throw new Zend_Currency_Exception("No region found within the locale '" . (string) $locale . "'");
+ }
+ } catch (Zend_Locale_Exception $e) {
+ require_once 'Zend/Currency/Exception.php';
+ throw new Zend_Currency_Exception($e->getMessage());
+ }
+
+ // Get currency details
+ $this->_options['currency'] = $this->getShortName(null, $this->_options['locale']);
+ $this->_options['name'] = $this->getName(null, $this->_options['locale']);
+ $this->_options['symbol'] = $this->getSymbol(null, $this->_options['locale']);
+
+ return $this;
+ }
+
+ /**
+ * Returns the actual set locale
+ *
+ * @return string
+ */
+ public function getLocale()
+ {
+ return $this->_options['locale'];
+ }
+
+ /**
+ * Returns the value
+ *
+ * @return float
+ */
+ public function getValue()
+ {
+ return $this->_options['value'];
+ }
+
+ /**
+ * Adds a currency
+ *
+ * @param float|integer|Zend_Currency $value Add this value to currency
+ * @param string|Zend_Currency $currency The currency to add
+ * @return Zend_Currency
+ */
+ public function setValue($value, $currency = null)
+ {
+ $this->_options['value'] = $this->_exchangeCurrency($value, $currency);
+ return $this;
+ }
+
+ /**
+ * Adds a currency
+ *
+ * @param float|integer|Zend_Currency $value Add this value to currency
+ * @param string|Zend_Currency $currency The currency to add
+ * @return Zend_Currency
+ */
+ public function add($value, $currency = null)
+ {
+ $value = $this->_exchangeCurrency($value, $currency);
+ $this->_options['value'] += (float) $value;
+ return $this;
+ }
+
+ /**
+ * Substracts a currency
+ *
+ * @param float|integer|Zend_Currency $value Substracts this value from currency
+ * @param string|Zend_Currency $currency The currency to substract
+ * @return Zend_Currency
+ */
+ public function sub($value, $currency = null)
+ {
+ $value = $this->_exchangeCurrency($value, $currency);
+ $this->_options['value'] -= (float) $value;
+ return $this;
+ }
+
+ /**
+ * Divides a currency
+ *
+ * @param float|integer|Zend_Currency $value Divides this value from currency
+ * @param string|Zend_Currency $currency The currency to divide
+ * @return Zend_Currency
+ */
+ public function div($value, $currency = null)
+ {
+ $value = $this->_exchangeCurrency($value, $currency);
+ $this->_options['value'] /= (float) $value;
+ return $this;
+ }
+
+ /**
+ * Multiplies a currency
+ *
+ * @param float|integer|Zend_Currency $value Multiplies this value from currency
+ * @param string|Zend_Currency $currency The currency to multiply
+ * @return Zend_Currency
+ */
+ public function mul($value, $currency = null)
+ {
+ $value = $this->_exchangeCurrency($value, $currency);
+ $this->_options['value'] *= (float) $value;
+ return $this;
+ }
+
+ /**
+ * Calculates the modulo from a currency
+ *
+ * @param float|integer|Zend_Currency $value Calculate modulo from this value
+ * @param string|Zend_Currency $currency The currency to calculate the modulo
+ * @return Zend_Currency
+ */
+ public function mod($value, $currency = null)
+ {
+ $value = $this->_exchangeCurrency($value, $currency);
+ $this->_options['value'] %= (float) $value;
+ return $this;
+ }
+
+ /**
+ * Compares two currencies
+ *
+ * @param float|integer|Zend_Currency $value Compares the currency with this value
+ * @param string|Zend_Currency $currency The currency to compare this value from
+ * @return Zend_Currency
+ */
+ public function compare($value, $currency = null)
+ {
+ $value = $this->_exchangeCurrency($value, $currency);
+ $value = $this->_options['value'] - $value;
+ if ($value < 0) {
+ return -1;
+ } else if ($value > 0) {
+ return 1;
+ }
+
+ return 0;
+ }
+
+ /**
+ * Returns true when the two currencies are equal
+ *
+ * @param float|integer|Zend_Currency $value Compares the currency with this value
+ * @param string|Zend_Currency $currency The currency to compare this value from
+ * @return boolean
+ */
+ public function equals($value, $currency = null)
+ {
+ $value = $this->_exchangeCurrency($value, $currency);
+ if ($this->_options['value'] == $value) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns true when the currency is more than the given value
+ *
+ * @param float|integer|Zend_Currency $value Compares the currency with this value
+ * @param string|Zend_Currency $currency The currency to compare this value from
+ * @return boolean
+ */
+ public function isMore($value, $currency = null)
+ {
+ $value = $this->_exchangeCurrency($value, $currency);
+ if ($this->_options['value'] > $value) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Returns true when the currency is less than the given value
+ *
+ * @param float|integer|Zend_Currency $value Compares the currency with this value
+ * @param string|Zend_Currency $currency The currency to compare this value from
+ * @return boolean
+ */
+ public function isLess($value, $currency = null)
+ {
+ $value = $this->_exchangeCurrency($value, $currency);
+ if ($this->_options['value'] < $value) {
+ return true;
+ }
+
+ return false;
+
+ }
+
+ /**
+ * Internal method which calculates the exchanges currency
+ *
+ * @param float|integer|Zend_Currency $value Compares the currency with this value
+ * @param string|Zend_Currency $currency The currency to compare this value from
+ * @return unknown
+ */
+ protected function _exchangeCurrency($value, $currency)
+ {
+ if ($value instanceof Zend_Currency) {
+ $currency = $value->getShortName();
+ $value = $value->getValue();
+ } else {
+ $currency = $this->getShortName($currency, $this->getLocale());
+ }
+
+ $rate = 1;
+ if ($currency !== $this->getShortName()) {
+ $service = $this->getService();
+ if (!($service instanceof Zend_Currency_CurrencyInterface)) {
+ require_once 'Zend/Currency/Exception.php';
+ throw new Zend_Currency_Exception('No exchange service applied');
+ }
+
+ $rate = $service->getRate($currency, $this->getShortName());
+ }
+
+ $value *= $rate;
+ return $value;
+ }
+
+ /**
+ * Returns the set service class
+ *
+ * @return Zend_Service
+ */
+ public function getService()
+ {
+ return $this->_options['service'];
+ }
+
+ /**
+ * Sets a new exchange service
+ *
+ * @param string|Zend_Currency_CurrencyInterface $service Service class
+ * @return Zend_Currency
+ */
+ public function setService($service)
+ {
+ if (is_string($service)) {
+ require_once 'Zend/Loader.php';
+ if (!class_exists($service)) {
+ $file = str_replace('_', DIRECTORY_SEPARATOR, $service) . '.php';
+ if (Zend_Loader::isReadable($file)) {
+ Zend_Loader::loadClass($service);
+ }
+ }
+
+ $service = new $service;
+ }
+
+ if (!($service instanceof Zend_Currency_CurrencyInterface)) {
+ require_once 'Zend/Currency/Exception.php';
+ throw new Zend_Currency_Exception('A currency service must implement Zend_Currency_CurrencyInterface');
+ }
+
+ $this->_options['service'] = $service;
+ return $this;
+ }
+
+ /**
+ * Internal method for checking the options array
+ *
+ * @param array $options Options to check
+ * @throws Zend_Currency_Exception On unknown position
+ * @throws Zend_Currency_Exception On unknown locale
+ * @throws Zend_Currency_Exception On unknown display
+ * @throws Zend_Currency_Exception On precision not between -1 and 30
+ * @throws Zend_Currency_Exception On problem with script conversion
+ * @throws Zend_Currency_Exception On unknown options
+ * @return array
+ */
+ protected function _checkOptions(array $options = array())
+ {
+ if (count($options) === 0) {
+ return $this->_options;
+ }
+
+ foreach ($options as $name => $value) {
+ $name = strtolower($name);
+ if ($name !== 'format') {
+ if (gettype($value) === 'string') {
+ $value = strtolower($value);
+ }
+ }
+
+ switch($name) {
+ case 'position':
+ if (($value !== self::STANDARD) and ($value !== self::RIGHT) and ($value !== self::LEFT)) {
+ require_once 'Zend/Currency/Exception.php';
+ throw new Zend_Currency_Exception("Unknown position '" . $value . "'");
+ }
+
+ break;
+
+ case 'format':
+ if ((empty($value) === false) and (Zend_Locale::isLocale($value, null, false) === false)) {
+ if (!is_string($value) || (strpos($value, '0') === false)) {
+ require_once 'Zend/Currency/Exception.php';
+ throw new Zend_Currency_Exception("'" .
+ ((gettype($value) === 'object') ? get_class($value) : $value)
+ . "' is no format token");
+ }
+ }
+ break;
+
+ case 'display':
+ if (is_numeric($value) and ($value !== self::NO_SYMBOL) and ($value !== self::USE_SYMBOL) and
+ ($value !== self::USE_SHORTNAME) and ($value !== self::USE_NAME)) {
+ require_once 'Zend/Currency/Exception.php';
+ throw new Zend_Currency_Exception("Unknown display '$value'");
+ }
+ break;
+
+ case 'precision':
+ if ($value === null) {
+ $value = -1;
+ }
+
+ if (($value < -1) or ($value > 30)) {
+ require_once 'Zend/Currency/Exception.php';
+ throw new Zend_Currency_Exception("'$value' precision has to be between -1 and 30.");
+ }
+ break;
+
+ case 'script':
+ try {
+ Zend_Locale_Format::convertNumerals(0, $options['script']);
+ } catch (Zend_Locale_Exception $e) {
+ require_once 'Zend/Currency/Exception.php';
+ throw new Zend_Currency_Exception($e->getMessage());
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return $options;
+ }
+}
diff --git a/lib/zend/Zend/Currency/CurrencyInterface.php b/lib/zend/Zend/Currency/CurrencyInterface.php
new file mode 100644
index 00000000000..8e828864b8c
--- /dev/null
+++ b/lib/zend/Zend/Currency/CurrencyInterface.php
@@ -0,0 +1,39 @@
+= -12)) {
+ if (!empty($match) and ($match[count($match) - 1] <= 14) and ($match[count($match) - 1] >= -12)) {
$zone = "Etc/GMT";
$zone .= ($match[count($match) - 1] < 0) ? "+" : "-";
$zone .= (int) abs($match[count($match) - 1]);
return $zone;
}
- preg_match('/([[:alpha:]\/]{3,30})(?!.*([[:alpha:]\/]{3,30}))/', $zone, $match);
+ preg_match('/([[:alpha:]\/_]{3,30})(?!.*([[:alpha:]\/]{3,30}))/', $zone, $match);
try {
if (!empty($match) and (!is_int($match[count($match) - 1]))) {
$oldzone = $this->getTimezone();
@@ -2066,9 +2067,18 @@ class Zend_Date extends Zend_Date_DateObject
}
// (T)hh:mm:ss
preg_match('/[T,\s]{0,1}(\d{2}):(\d{2}):(\d{2})/', $tmpdate, $timematch);
+ // (T)hhmmss
if (empty($timematch)) {
preg_match('/[T,\s]{0,1}(\d{2})(\d{2})(\d{2})/', $tmpdate, $timematch);
}
+ // (T)hh:mm
+ if (empty($timematch)) {
+ preg_match('/[T,\s]{0,1}(\d{2}):(\d{2})/', $tmpdate, $timematch);
+ }
+ // (T)hhmm
+ if (empty($timematch)) {
+ preg_match('/[T,\s]{0,1}(\d{2})(\d{2})/', $tmpdate, $timematch);
+ }
if (empty($datematch) and empty($timematch)) {
require_once 'Zend/Date/Exception.php';
throw new Zend_Date_Exception("unsupported ISO8601 format ($date)", 0, null, $date);
@@ -2092,6 +2102,9 @@ class Zend_Date extends Zend_Date_DateObject
$timematch[2] = 0;
$timematch[3] = 0;
}
+ if (!isset($timematch[3])) {
+ $timematch[3] = 0;
+ }
if (($calc == 'set') || ($calc == 'cmp')) {
--$datematch[2];
@@ -2106,7 +2119,10 @@ class Zend_Date extends Zend_Date_DateObject
break;
case self::RFC_2822:
- $result = preg_match('/^\w{3},\s(\d{1,2})\s(\w{3})\s(\d{4})\s(\d{2}):(\d{2}):{0,1}(\d{0,2})\s([+-]{1}\d{4})$/', $date, $match);
+ $result = preg_match('/^\w{3},\s(\d{1,2})\s(\w{3})\s(\d{4})\s'
+ . '(\d{2}):(\d{2}):{0,1}(\d{0,2})\s([+-]'
+ . '{1}\d{4}|\w{1,20})$/', $date, $match);
+
if (!$result) {
require_once 'Zend/Date/Exception.php';
throw new Zend_Date_Exception("no RFC 2822 format ($date)", 0, null, $date);
@@ -2640,10 +2656,8 @@ class Zend_Date extends Zend_Date_DateObject
$parsed['day'] = 0;
}
- if (isset($parsed['year'])) {
- $parsed['year'] -= 1970;
- } else {
- $parsed['year'] = 0;
+ if (!isset($parsed['year'])) {
+ $parsed['year'] = 1970;
}
}
@@ -2653,7 +2667,7 @@ class Zend_Date extends Zend_Date_DateObject
isset($parsed['second']) ? $parsed['second'] : 0,
isset($parsed['month']) ? (1 + $parsed['month']) : 1,
isset($parsed['day']) ? (1 + $parsed['day']) : 1,
- isset($parsed['year']) ? (1970 + $parsed['year']) : 1970,
+ $parsed['year'],
false), $this->getUnixTimestamp(), false);
} catch (Zend_Locale_Exception $e) {
if (!is_numeric($date)) {
@@ -2834,7 +2848,7 @@ class Zend_Date extends Zend_Date_DateObject
* @param string|integer|array|Zend_Date $time Time to set
* @param string $format OPTIONAL Timeformat for parsing input
* @param string|Zend_Locale $locale OPTIONAL Locale for parsing input
- * @return Zend_Date Provides fluid interface
+ * @return Zend_Date Provides a fluent interface
* @throws Zend_Date_Exception
*/
public function setTime($time, $format = null, $locale = null)
@@ -2852,7 +2866,7 @@ class Zend_Date extends Zend_Date_DateObject
* @param string|integer|array|Zend_Date $time Time to add
* @param string $format OPTIONAL Timeformat for parsing input
* @param string|Zend_Locale $locale OPTIONAL Locale for parsing input
- * @return Zend_Date Provides fluid interface
+ * @return Zend_Date Provides a fluent interface
* @throws Zend_Date_Exception
*/
public function addTime($time, $format = null, $locale = null)
@@ -2870,7 +2884,7 @@ class Zend_Date extends Zend_Date_DateObject
* @param string|integer|array|Zend_Date $time Time to sub
* @param string $format OPTIONAL Timeformat for parsing input
* @param string|Zend_Locale $locale OPTIONAL Locale for parsing input
- * @return Zend_Date Provides fluid inteface
+ * @return Zend_Date Provides a fluent inteface
* @throws Zend_Date_Exception
*/
public function subTime($time, $format = null, $locale = null)
@@ -2996,7 +3010,7 @@ class Zend_Date extends Zend_Date_DateObject
* @param string|integer|array|Zend_Date $date Date to set
* @param string $format OPTIONAL Date format for parsing
* @param string|Zend_Locale $locale OPTIONAL Locale for parsing input
- * @return Zend_Date Provides fluid interface
+ * @return Zend_Date Provides a fluent interface
* @throws Zend_Date_Exception
*/
public function setDate($date, $format = null, $locale = null)
@@ -3014,7 +3028,7 @@ class Zend_Date extends Zend_Date_DateObject
* @param string|integer|array|Zend_Date $date Date to add
* @param string $format OPTIONAL Date format for parsing input
* @param string|Zend_Locale $locale OPTIONAL Locale for parsing input
- * @return Zend_Date Provides fluid interface
+ * @return Zend_Date Provides a fluent interface
* @throws Zend_Date_Exception
*/
public function addDate($date, $format = null, $locale = null)
@@ -3033,7 +3047,7 @@ class Zend_Date extends Zend_Date_DateObject
* @param string|integer|array|Zend_Date $date Date to sub
* @param string $format OPTIONAL Date format for parsing input
* @param string|Zend_Locale $locale OPTIONAL Locale for parsing input
- * @return Zend_Date Provides fluid interface
+ * @return Zend_Date Provides a fluent interface
* @throws Zend_Date_Exception
*/
public function subDate($date, $format = null, $locale = null)
@@ -3084,7 +3098,7 @@ class Zend_Date extends Zend_Date_DateObject
*
* @param string|integer|Zend_Date $date ISO Date to set
* @param string|Zend_Locale $locale OPTIONAL Locale for parsing input
- * @return Zend_Date Provides fluid interface
+ * @return Zend_Date Provides a fluent interface
* @throws Zend_Date_Exception
*/
public function setIso($date, $locale = null)
@@ -3101,7 +3115,7 @@ class Zend_Date extends Zend_Date_DateObject
*
* @param string|integer|Zend_Date $date ISO Date to add
* @param string|Zend_Locale $locale OPTIONAL Locale for parsing input
- * @return Zend_Date Provides fluid interface
+ * @return Zend_Date Provides a fluent interface
* @throws Zend_Date_Exception
*/
public function addIso($date, $locale = null)
@@ -3118,7 +3132,7 @@ class Zend_Date extends Zend_Date_DateObject
*
* @param string|integer|Zend_Date $date ISO Date to sub
* @param string|Zend_Locale $locale OPTIONAL Locale for parsing input
- * @return Zend_Date Provides fluid interface
+ * @return Zend_Date Provides a fluent interface
* @throws Zend_Date_Exception
*/
public function subIso($date, $locale = null)
@@ -3171,7 +3185,7 @@ class Zend_Date extends Zend_Date_DateObject
*
* @param string|integer|Zend_Date $date RFC 822 to set
* @param string|Zend_Locale $locale OPTIONAL Locale for parsing input
- * @return Zend_Date Provides fluid interface
+ * @return Zend_Date Provides a fluent interface
* @throws Zend_Date_Exception
*/
public function setArpa($date, $locale = null)
@@ -3189,7 +3203,7 @@ class Zend_Date extends Zend_Date_DateObject
*
* @param string|integer|Zend_Date $date RFC 822 Date to add
* @param string|Zend_Locale $locale OPTIONAL Locale for parsing input
- * @return Zend_Date Provides fluid interface
+ * @return Zend_Date Provides a fluent interface
* @throws Zend_Date_Exception
*/
public function addArpa($date, $locale = null)
@@ -3207,7 +3221,7 @@ class Zend_Date extends Zend_Date_DateObject
*
* @param string|integer|Zend_Date $date RFC 822 Date to sub
* @param string|Zend_Locale $locale OPTIONAL Locale for parsing input
- * @return Zend_Date Provides fluid interface
+ * @return Zend_Date Provides a fluent interface
* @throws Zend_Date_Exception
*/
public function subArpa($date, $locale = null)
@@ -3233,12 +3247,12 @@ class Zend_Date extends Zend_Date_DateObject
return $this->_calcvalue('cmp', $date, 'arpa', self::RFC_822, $locale);
}
-
/**
* Check if location is supported
*
- * @param $location array - locations array
- * @return $horizon float
+ * @param array $location locations array
+ * @throws Zend_Date_Exception
+ * @return float $horizon float
*/
private function _checkLocation($location)
{
@@ -3280,7 +3294,7 @@ class Zend_Date extends Zend_Date_DateObject
* Returns the time of sunrise for this date and a given location as new date object
* For a list of cities and correct locations use the class Zend_Date_Cities
*
- * @param $location array - location of sunrise
+ * @param array $location location of sunrise
* ['horizon'] -> civil, nautic, astronomical, effective (default)
* ['longitude'] -> longitude of location
* ['latitude'] -> latitude of location
@@ -3300,7 +3314,7 @@ class Zend_Date extends Zend_Date_DateObject
* Returns the time of sunset for this date and a given location as new date object
* For a list of cities and correct locations use the class Zend_Date_Cities
*
- * @param $location array - location of sunset
+ * @param array $location location of sunset
* ['horizon'] -> civil, nautic, astronomical, effective (default)
* ['longitude'] -> longitude of location
* ['latitude'] -> latitude of location
@@ -3320,7 +3334,7 @@ class Zend_Date extends Zend_Date_DateObject
* Returns an array with the sunset and sunrise dates for all horizon types
* For a list of cities and correct locations use the class Zend_Date_Cities
*
- * @param $location array - location of suninfo
+ * @param array $location location of suninfo
* ['horizon'] -> civil, nautic, astronomical, effective (default)
* ['longitude'] -> longitude of location
* ['latitude'] -> latitude of location
@@ -3356,11 +3370,11 @@ class Zend_Date extends Zend_Date_DateObject
return $suninfo;
}
-
/**
* Check a given year for leap year.
*
- * @param integer|array|Zend_Date $year Year to check
+ * @param integer|array|Zend_Date $year Year to check
+ * @throws Zend_Date_Exception
* @return boolean
*/
public static function checkLeapYear($year)
@@ -3456,7 +3470,7 @@ class Zend_Date extends Zend_Date_DateObject
*
* @param string $calc Calculation to make
* @param string|integer|array|Zend_Date $date Date or Part to calculate
- * @param string $part Datepart for Calculation
+ * @param string $type Datepart for Calculation
* @param string|Zend_Locale $locale Locale for parsing input
* @return integer|string new date
* @throws Zend_Date_Exception
@@ -3494,11 +3508,13 @@ class Zend_Date extends Zend_Date_DateObject
/**
* Internal calculation, returns the requested date type
*
- * @param string $calc Calculation to make
- * @param string|integer|Zend_Date $value Datevalue to calculate with, if null the actual value is taken
- * @param string|Zend_Locale $locale Locale for parsing input
- * @return integer|Zend_Date new date
+ * @param string $calc Calculation to make
+ * @param string|integer|Zend_Date $value Datevalue to calculate with, if null the actual value is taken
+ * @param string $type
+ * @param string $parameter
+ * @param string|Zend_Locale $locale Locale for parsing input
* @throws Zend_Date_Exception
+ * @return integer|Zend_Date new date
*/
private function _calcvalue($calc, $value, $type, $parameter, $locale)
{
@@ -3554,9 +3570,9 @@ class Zend_Date extends Zend_Date_DateObject
* use set() instead.
* Returned is the new date object
*
- * @param string|integer|array|Zend_Date $date Year to set
+ * @param string|integer|array|Zend_Date $year Year to set
* @param string|Zend_Locale $locale OPTIONAL Locale for parsing input
- * @return Zend_Date Provides fluid interface
+ * @return Zend_Date Provides a fluent interface
* @throws Zend_Date_Exception
*/
public function setYear($year, $locale = null)
@@ -3573,9 +3589,9 @@ class Zend_Date extends Zend_Date_DateObject
* use add() instead.
* Returned is the new date object
*
- * @param string|integer|array|Zend_Date $date Year to add
+ * @param string|integer|array|Zend_Date $year Year to add
* @param string|Zend_Locale $locale OPTIONAL Locale for parsing input
- * @return Zend_Date Provides fluid interface
+ * @return Zend_Date Provides a fluent interface
* @throws Zend_Date_Exception
*/
public function addYear($year, $locale = null)
@@ -3592,9 +3608,9 @@ class Zend_Date extends Zend_Date_DateObject
* use sub() instead.
* Returned is the new date object
*
- * @param string|integer|array|Zend_Date $date Year to sub
+ * @param string|integer|array|Zend_Date $year Year to sub
* @param string|Zend_Locale $locale OPTIONAL Locale for parsing input
- * @return Zend_Date Provides fluid interface
+ * @return Zend_Date Provides a fluent interface
* @throws Zend_Date_Exception
*/
public function subYear($year, $locale = null)
@@ -3718,7 +3734,7 @@ class Zend_Date extends Zend_Date_DateObject
*
* @param string|integer|array|Zend_Date $month Month to set
* @param string|Zend_Locale $locale OPTIONAL Locale for parsing input
- * @return Zend_Date Provides fluid interface
+ * @return Zend_Date Provides a fluent interface
* @throws Zend_Date_Exception
*/
public function setMonth($month, $locale = null)
@@ -3737,7 +3753,7 @@ class Zend_Date extends Zend_Date_DateObject
*
* @param string|integer|array|Zend_Date $month Month to add
* @param string|Zend_Locale $locale OPTIONAL Locale for parsing input
- * @return Zend_Date Provides fluid interface
+ * @return Zend_Date Provides a fluent interface
* @throws Zend_Date_Exception
*/
public function addMonth($month, $locale = null)
@@ -3756,7 +3772,7 @@ class Zend_Date extends Zend_Date_DateObject
*
* @param string|integer|array|Zend_Date $month Month to sub
* @param string|Zend_Locale $locale OPTIONAL Locale for parsing input
- * @return Zend_Date Provides fluid interface
+ * @return Zend_Date Provides a fluent interface
* @throws Zend_Date_Exception
*/
public function subMonth($month, $locale = null)
@@ -3785,7 +3801,7 @@ class Zend_Date extends Zend_Date_DateObject
* Returns the day as new date object
* Example: 20.May.1986 -> 20.Jan.1970 00:00:00
*
- * @param $locale string|Zend_Locale OPTIONAL Locale for parsing input
+ * @param Zend_Locale $locale OPTIONAL Locale for parsing input
* @return Zend_Date
*/
public function getDay($locale = null)
@@ -3793,13 +3809,13 @@ class Zend_Date extends Zend_Date_DateObject
return $this->copyPart(self::DAY_SHORT, $locale);
}
-
/**
* Returns the calculated day
*
- * @param $calc string Type of calculation to make
- * @param $day string|integer|Zend_Date Day to calculate, when null the actual day is calculated
- * @param $locale string|Zend_Locale Locale for parsing input
+ * @param string $calc Type of calculation to make
+ * @param Zend_Date $day Day to calculate, when null the actual day is calculated
+ * @param Zend_Locale $locale Locale for parsing input
+ * @throws Zend_Date_Exception
* @return Zend_Date|integer
*/
private function _day($calc, $day, $locale)
@@ -3860,9 +3876,9 @@ class Zend_Date extends Zend_Date_DateObject
* Returned is the new date object
* Example: setDay('Montag', 'de_AT'); will set the monday of this week as day.
*
- * @param string|integer|array|Zend_Date $month Day to set
+ * @param string|integer|array|Zend_Date $day Day to set
* @param string|Zend_Locale $locale OPTIONAL Locale for parsing input
- * @return Zend_Date Provides fluid interface
+ * @return Zend_Date Provides a fluent interface
* @throws Zend_Date_Exception
*/
public function setDay($day, $locale = null)
@@ -3878,9 +3894,9 @@ class Zend_Date extends Zend_Date_DateObject
* If a localized dayname is given it will be parsed with the default locale or the optional
* set locale.
*
- * @param string|integer|array|Zend_Date $month Day to add
+ * @param string|integer|array|Zend_Date $day Day to add
* @param string|Zend_Locale $locale OPTIONAL Locale for parsing input
- * @return Zend_Date Provides fluid interface
+ * @return Zend_Date Provides a fluent interface
* @throws Zend_Date_Exception
*/
public function addDay($day, $locale = null)
@@ -3896,9 +3912,9 @@ class Zend_Date extends Zend_Date_DateObject
* If a localized dayname is given it will be parsed with the default locale or the optional
* set locale.
*
- * @param string|integer|array|Zend_Date $month Day to sub
+ * @param string|integer|array|Zend_Date $day Day to sub
* @param string|Zend_Locale $locale OPTIONAL Locale for parsing input
- * @return Zend_Date Provides fluid interface
+ * @return Zend_Date Provides a fluent interface
* @throws Zend_Date_Exception
*/
public function subDay($day, $locale = null)
@@ -3928,7 +3944,7 @@ class Zend_Date extends Zend_Date_DateObject
* Weekday is always from 1-7
* Example: 09-Jan-2007 -> 2 = Tuesday -> 02-Jan-1970 (when 02.01.1970 is also Tuesday)
*
- * @param $locale string|Zend_Locale OPTIONAL Locale for parsing input
+ * @param Zend_Locale $locale OPTIONAL Locale for parsing input
* @return Zend_Date
*/
public function getWeekday($locale = null)
@@ -3946,9 +3962,9 @@ class Zend_Date extends Zend_Date_DateObject
/**
* Returns the calculated weekday
*
- * @param $calc string Type of calculation to make
- * @param $weekday string|integer|array|Zend_Date Weekday to calculate, when null the actual weekday is calculated
- * @param $locale string|Zend_Locale Locale for parsing input
+ * @param string $calc Type of calculation to make
+ * @param Zend_Date $weekday Weekday to calculate, when null the actual weekday is calculated
+ * @param Zend_Locale $locale Locale for parsing input
* @return Zend_Date|integer
* @throws Zend_Date_Exception
*/
@@ -4008,9 +4024,9 @@ class Zend_Date extends Zend_Date_DateObject
* Returned is the new date object.
* Example: setWeekday(3); will set the wednesday of this week as day.
*
- * @param string|integer|array|Zend_Date $month Weekday to set
+ * @param string|integer|array|Zend_Date $weekday Weekday to set
* @param string|Zend_Locale $locale OPTIONAL Locale for parsing input
- * @return Zend_Date Provides fluid interface
+ * @return Zend_Date Provides a fluent interface
* @throws Zend_Date_Exception
*/
public function setWeekday($weekday, $locale = null)
@@ -4028,9 +4044,9 @@ class Zend_Date extends Zend_Date_DateObject
* Example: addWeekday(3); will add the difference of days from the begining of the month until
* wednesday.
*
- * @param string|integer|array|Zend_Date $month Weekday to add
+ * @param string|integer|array|Zend_Date $weekday Weekday to add
* @param string|Zend_Locale $locale OPTIONAL Locale for parsing input
- * @return Zend_Date Provides fluid interface
+ * @return Zend_Date Provides a fluent interface
* @throws Zend_Date_Exception
*/
public function addWeekday($weekday, $locale = null)
@@ -4048,9 +4064,9 @@ class Zend_Date extends Zend_Date_DateObject
* Example: subWeekday(3); will subtract the difference of days from the begining of the month until
* wednesday.
*
- * @param string|integer|array|Zend_Date $month Weekday to sub
+ * @param string|integer|array|Zend_Date $weekday Weekday to sub
* @param string|Zend_Locale $locale OPTIONAL Locale for parsing input
- * @return Zend_Date Provides fluid interface
+ * @return Zend_Date Provides a fluent interface
* @throws Zend_Date_Exception
*/
public function subWeekday($weekday, $locale = null)
@@ -4102,7 +4118,7 @@ class Zend_Date extends Zend_Date_DateObject
*
* @param string|integer|array|Zend_Date $day Day of Year to set
* @param string|Zend_Locale $locale OPTIONAL Locale for parsing input
- * @return Zend_Date Provides fluid interface
+ * @return Zend_Date Provides a fluent interface
* @throws Zend_Date_Exception
*/
public function setDayOfYear($day, $locale = null)
@@ -4119,7 +4135,7 @@ class Zend_Date extends Zend_Date_DateObject
*
* @param string|integer|array|Zend_Date $day Day of Year to add
* @param string|Zend_Locale $locale OPTIONAL Locale for parsing input
- * @return Zend_Date Provides fluid interface
+ * @return Zend_Date Provides a fluent interface
* @throws Zend_Date_Exception
*/
public function addDayOfYear($day, $locale = null)
@@ -4136,7 +4152,7 @@ class Zend_Date extends Zend_Date_DateObject
*
* @param string|integer|array|Zend_Date $day Day of Year to sub
* @param string|Zend_Locale $locale OPTIONAL Locale for parsing input
- * @return Zend_Date Provides fluid interface
+ * @return Zend_Date Provides a fluent interface
* @throws Zend_Date_Exception
*/
public function subDayOfYear($day, $locale = null)
@@ -4165,7 +4181,7 @@ class Zend_Date extends Zend_Date_DateObject
* Returns the hour as new date object
* Example: 02.Feb.1986 10:30:25 -> 01.Jan.1970 10:00:00
*
- * @param $locale string|Zend_Locale OPTIONAL Locale for parsing input
+ * @param Zend_Locale $locale OPTIONAL Locale for parsing input
* @return Zend_Date
*/
public function getHour($locale = null)
@@ -4182,7 +4198,7 @@ class Zend_Date extends Zend_Date_DateObject
*
* @param string|integer|array|Zend_Date $hour Hour to set
* @param string|Zend_Locale $locale OPTIONAL Locale for parsing input
- * @return Zend_Date Provides fluid interface
+ * @return Zend_Date Provides a fluent interface
* @throws Zend_Date_Exception
*/
public function setHour($hour, $locale = null)
@@ -4199,7 +4215,7 @@ class Zend_Date extends Zend_Date_DateObject
*
* @param string|integer|array|Zend_Date $hour Hour to add
* @param string|Zend_Locale $locale OPTIONAL Locale for parsing input
- * @return Zend_Date Provides fluid interface
+ * @return Zend_Date Provides a fluent interface
* @throws Zend_Date_Exception
*/
public function addHour($hour, $locale = null)
@@ -4216,7 +4232,7 @@ class Zend_Date extends Zend_Date_DateObject
*
* @param string|integer|array|Zend_Date $hour Hour to sub
* @param string|Zend_Locale $locale OPTIONAL Locale for parsing input
- * @return Zend_Date Provides fluid interface
+ * @return Zend_Date Provides a fluent interface
* @throws Zend_Date_Exception
*/
public function subHour($hour, $locale = null)
@@ -4268,7 +4284,7 @@ class Zend_Date extends Zend_Date_DateObject
*
* @param string|integer|array|Zend_Date $minute Minute to set
* @param string|Zend_Locale $locale OPTIONAL Locale for parsing input
- * @return Zend_Date Provides fluid interface
+ * @return Zend_Date Provides a fluent interface
* @throws Zend_Date_Exception
*/
public function setMinute($minute, $locale = null)
@@ -4285,7 +4301,7 @@ class Zend_Date extends Zend_Date_DateObject
*
* @param string|integer|array|Zend_Date $minute Minute to add
* @param string|Zend_Locale $locale OPTIONAL Locale for parsing input
- * @return Zend_Date Provides fluid interface
+ * @return Zend_Date Provides a fluent interface
* @throws Zend_Date_Exception
*/
public function addMinute($minute, $locale = null)
@@ -4302,7 +4318,7 @@ class Zend_Date extends Zend_Date_DateObject
*
* @param string|integer|array|Zend_Date $minute Minute to sub
* @param string|Zend_Locale $locale OPTIONAL Locale for parsing input
- * @return Zend_Date Provides fluid interface
+ * @return Zend_Date Provides a fluent interface
* @throws Zend_Date_Exception
*/
public function subMinute($minute, $locale = null)
@@ -4354,7 +4370,7 @@ class Zend_Date extends Zend_Date_DateObject
*
* @param string|integer|array|Zend_Date $second Second to set
* @param string|Zend_Locale $locale (Optional) Locale for parsing input
- * @return Zend_Date Provides fluid interface
+ * @return Zend_Date Provides a fluent interface
* @throws Zend_Date_Exception
*/
public function setSecond($second, $locale = null)
@@ -4371,7 +4387,7 @@ class Zend_Date extends Zend_Date_DateObject
*
* @param string|integer|array|Zend_Date $second Second to add
* @param string|Zend_Locale $locale (Optional) Locale for parsing input
- * @return Zend_Date Provides fluid interface
+ * @return Zend_Date Provides a fluent interface
* @throws Zend_Date_Exception
*/
public function addSecond($second, $locale = null)
@@ -4388,7 +4404,7 @@ class Zend_Date extends Zend_Date_DateObject
*
* @param string|integer|array|Zend_Date $second Second to sub
* @param string|Zend_Locale $locale (Optional) Locale for parsing input
- * @return Zend_Date Provides fluid interface
+ * @return Zend_Date Provides a fluent interface
* @throws Zend_Date_Exception
*/
public function subSecond($second, $locale = null)
@@ -4429,7 +4445,7 @@ class Zend_Date extends Zend_Date_DateObject
*
* @param integer $precision Precision for the fractional datepart 3 = milliseconds
* @throws Zend_Date_Exception
- * @return Zend_Date Provides fluid interface
+ * @return Zend_Date Provides a fluent interface
*/
public function setFractionalPrecision($precision)
{
@@ -4459,14 +4475,14 @@ class Zend_Date extends Zend_Date_DateObject
return $this->_fractional;
}
-
/**
* Sets new milliseconds for the date object
* Example: setMilliSecond(550, 2) -> equals +5 Sec +50 MilliSec
*
* @param integer|Zend_Date $milli (Optional) Millisecond to set, when null the actual millisecond is set
* @param integer $precision (Optional) Fraction precision of the given milliseconds
- * @return Zend_Date Provides fluid interface
+ * @throws Zend_Date_Exception
+ * @return Zend_Date Provides a fluent interface
*/
public function setMilliSecond($milli = null, $precision = null)
{
@@ -4493,13 +4509,13 @@ class Zend_Date extends Zend_Date_DateObject
return $this;
}
-
/**
* Adds milliseconds to the date object
*
* @param integer|Zend_Date $milli (Optional) Millisecond to add, when null the actual millisecond is added
* @param integer $precision (Optional) Fractional precision for the given milliseconds
- * @return Zend_Date Provides fluid interface
+ * @throws Zend_Date_Exception
+ * @return Zend_Date Provides a fluent interface
*/
public function addMilliSecond($milli = null, $precision = null)
{
@@ -4512,15 +4528,24 @@ class Zend_Date extends Zend_Date_DateObject
}
if ($precision === null) {
- $precision = strlen($milli);
- if ($milli < 0) {
- --$precision;
- }
+ // Use internal default precision
+ // Is not as logic as using the length of the input. But this would break tests and maybe other things
+ // as an input value of integer 10, which is used in tests, must be parsed as 10 milliseconds (real milliseconds, precision 3)
+ // but with auto-detect of precision, 100 milliseconds would be added.
+ $precision = $this->_precision;
}
if (!is_int($precision) || $precision < 1 || $precision > 9) {
require_once 'Zend/Date/Exception.php';
- throw new Zend_Date_Exception("precision ($precision) must be a positive integer less than 10", 0, null, $precision);
+ throw new Zend_Date_Exception(
+ "precision ($precision) must be a positive integer less than 10", 0, null, $precision
+ );
+ }
+
+ if ($this->_precision > $precision) {
+ $milli = $milli * pow(10, $this->_precision - $precision);
+ } elseif ($this->_precision < $precision) {
+ $milli = round($milli / pow(10, $precision - $this->_precision));
}
$this->_fractional += $milli;
@@ -4555,7 +4580,7 @@ class Zend_Date extends Zend_Date_DateObject
*
* @param integer|Zend_Date $milli (Optional) Millisecond to sub, when null the actual millisecond is subtracted
* @param integer $precision (Optional) Fractional precision for the given milliseconds
- * @return Zend_Date Provides fluid interface
+ * @return Zend_Date Provides a fluent interface
*/
public function subMilliSecond($milli = null, $precision = null)
{
@@ -4616,7 +4641,7 @@ class Zend_Date extends Zend_Date_DateObject
* Returns the week as new date object using monday as begining of the week
* Example: 12.Jan.2007 -> 08.Jan.1970 00:00:00
*
- * @param $locale string|Zend_Locale OPTIONAL Locale for parsing input
+ * @param Zend_Locale $locale OPTIONAL Locale for parsing input
* @return Zend_Date
*/
public function getWeek($locale = null)
@@ -4637,7 +4662,7 @@ class Zend_Date extends Zend_Date_DateObject
*
* @param string|integer|array|Zend_Date $week Week to set
* @param string|Zend_Locale $locale OPTIONAL Locale for parsing input
- * @return Zend_Date Provides fluid interface
+ * @return Zend_Date Provides a fluent interface
* @throws Zend_Date_Exception
*/
public function setWeek($week, $locale = null)
@@ -4652,7 +4677,7 @@ class Zend_Date extends Zend_Date_DateObject
*
* @param string|integer|array|Zend_Date $week Week to add
* @param string|Zend_Locale $locale OPTIONAL Locale for parsing input
- * @return Zend_Date Provides fluid interface
+ * @return Zend_Date Provides a fluent interface
* @throws Zend_Date_Exception
*/
public function addWeek($week, $locale = null)
@@ -4667,7 +4692,7 @@ class Zend_Date extends Zend_Date_DateObject
*
* @param string|integer|array|Zend_Date $week Week to sub
* @param string|Zend_Locale $locale OPTIONAL Locale for parsing input
- * @return Zend_Date Provides fluid interface
+ * @return Zend_Date Provides a fluent interface
* @throws Zend_Date_Exception
*/
public function subWeek($week, $locale = null)
diff --git a/lib/zend/Zend/Date/Cities.php b/lib/zend/Zend/Date/Cities.php
index 70bc0592dc0..6934d690e05 100644
--- a/lib/zend/Zend/Date/Cities.php
+++ b/lib/zend/Zend/Date/Cities.php
@@ -14,7 +14,7 @@
*
* @category Zend
* @package Zend_Date
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
@@ -28,7 +28,7 @@
* @category Zend
* @package Zend_Date
* @subpackage Zend_Date_Cities
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Date_Cities
diff --git a/lib/zend/Zend/Date/DateObject.php b/lib/zend/Zend/Date/DateObject.php
index 5435eb4a506..0ec9fce9fc2 100644
--- a/lib/zend/Zend/Date/DateObject.php
+++ b/lib/zend/Zend/Date/DateObject.php
@@ -14,7 +14,7 @@
*
* @category Zend
* @package Zend_Date
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @version $Id$
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
@@ -23,7 +23,7 @@
* @category Zend
* @package Zend_Date
* @subpackage Zend_Date_DateObject
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
abstract class Zend_Date_DateObject {
@@ -33,6 +33,7 @@ abstract class Zend_Date_DateObject {
*/
private $_unixTimestamp;
protected static $_cache = null;
+ protected static $_cacheTags = false;
protected static $_defaultOffset = 0;
/**
@@ -254,7 +255,11 @@ abstract class Zend_Date_DateObject {
}
if (isset(self::$_cache)) {
- self::$_cache->save( serialize($date), $id);
+ if (self::$_cacheTags) {
+ self::$_cache->save( serialize($date), $id, array('Zend_Date'));
+ } else {
+ self::$_cache->save( serialize($date), $id);
+ }
}
return $date;
@@ -307,6 +312,13 @@ abstract class Zend_Date_DateObject {
}
if (abs($timestamp) <= 0x7FFFFFFF) {
+ // See ZF-11992
+ // "o" will sometimes resolve to the previous year (see
+ // http://php.net/date ; it's part of the ISO 8601
+ // standard). However, this is not desired, so replacing
+ // all occurrences of "o" not preceded by a backslash
+ // with "Y"
+ $format = preg_replace('/(?save( serialize($timestamp), $idstamp);
+ if (self::$_cacheTags) {
+ self::$_cache->save( serialize($timestamp), $idstamp, array('Zend_Date'));
+ } else {
+ self::$_cache->save( serialize($timestamp), $idstamp);
+ }
}
}
@@ -828,7 +844,11 @@ abstract class Zend_Date_DateObject {
}
if (isset(self::$_cache)) {
- self::$_cache->save( serialize($array), $id);
+ if (self::$_cacheTags) {
+ self::$_cache->save( serialize($array), $id, array('Zend_Date'));
+ } else {
+ self::$_cache->save( serialize($array), $id);
+ }
}
return $array;
@@ -1055,4 +1075,22 @@ abstract class Zend_Date_DateObject {
return $offset;
}
+
+ /**
+ * Internal method to check if the given cache supports tags
+ *
+ * @param Zend_Cache $cache
+ */
+ protected static function _getTagSupportForCache()
+ {
+ $backend = self::$_cache->getBackend();
+ if ($backend instanceof Zend_Cache_Backend_ExtendedInterface) {
+ $cacheOptions = $backend->getCapabilities();
+ self::$_cacheTags = $cacheOptions['tags'];
+ } else {
+ self::$_cacheTags = false;
+ }
+
+ return self::$_cacheTags;
+ }
}
diff --git a/lib/zend/Zend/Date/Exception.php b/lib/zend/Zend/Date/Exception.php
index bcbfd20be52..f4573b38ce5 100644
--- a/lib/zend/Zend/Date/Exception.php
+++ b/lib/zend/Zend/Date/Exception.php
@@ -14,7 +14,7 @@
*
* @category Zend
* @package Zend_Date
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @version $Id$
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
@@ -29,7 +29,7 @@ require_once 'Zend/Exception.php';
/**
* @category Zend
* @package Zend_Date
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Date_Exception extends Zend_Exception
diff --git a/lib/zend/Zend/Exception.php b/lib/zend/Zend/Exception.php
index bbfb792e936..d97acb0f92c 100644
--- a/lib/zend/Zend/Exception.php
+++ b/lib/zend/Zend/Exception.php
@@ -14,14 +14,15 @@
*
* @category Zend
* @package Zend
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 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
-* @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Exception extends Exception
@@ -53,9 +54,9 @@ class Zend_Exception extends Exception
* Overloading
*
* For PHP < 5.3.0, provides access to the getPrevious() method.
- *
- * @param string $method
- * @param array $args
+ *
+ * @param string $method
+ * @param array $args
* @return mixed
*/
public function __call($method, array $args)
@@ -75,8 +76,8 @@ class Zend_Exception extends Exception
{
if (version_compare(PHP_VERSION, '5.3.0', '<')) {
if (null !== ($e = $this->getPrevious())) {
- return $e->__toString()
- . "\n\nNext "
+ return $e->__toString()
+ . "\n\nNext "
. parent::__toString();
}
}
diff --git a/lib/zend/Zend/Filter.php b/lib/zend/Zend/Filter.php
new file mode 100644
index 00000000000..1256ff9bd6b
--- /dev/null
+++ b/lib/zend/Zend/Filter.php
@@ -0,0 +1,239 @@
+_filters, $filter);
+ } else {
+ $this->_filters[] = $filter;
+ }
+ return $this;
+ }
+
+ /**
+ * Add a filter to the end of the chain
+ *
+ * @param Zend_Filter_Interface $filter
+ * @return Zend_Filter Provides a fluent interface
+ */
+ public function appendFilter(Zend_Filter_Interface $filter)
+ {
+ return $this->addFilter($filter, self::CHAIN_APPEND);
+ }
+
+ /**
+ * Add a filter to the start of the chain
+ *
+ * @param Zend_Filter_Interface $filter
+ * @return Zend_Filter Provides a fluent interface
+ */
+ public function prependFilter(Zend_Filter_Interface $filter)
+ {
+ return $this->addFilter($filter, self::CHAIN_PREPEND);
+ }
+
+ /**
+ * Get all the filters
+ *
+ * @return array
+ */
+ public function getFilters()
+ {
+ return $this->_filters;
+ }
+
+ /**
+ * Returns $value filtered through each filter in the chain
+ *
+ * Filters are run in the order in which they were added to the chain (FIFO)
+ *
+ * @param mixed $value
+ * @return mixed
+ */
+ public function filter($value)
+ {
+ $valueFiltered = $value;
+ foreach ($this->_filters as $filter) {
+ $valueFiltered = $filter->filter($valueFiltered);
+ }
+ return $valueFiltered;
+ }
+
+ /**
+ * Returns the set default namespaces
+ *
+ * @return array
+ */
+ public static function getDefaultNamespaces()
+ {
+ return self::$_defaultNamespaces;
+ }
+
+ /**
+ * Sets new default namespaces
+ *
+ * @param array|string $namespace
+ * @return null
+ */
+ public static function setDefaultNamespaces($namespace)
+ {
+ if (!is_array($namespace)) {
+ $namespace = array((string) $namespace);
+ }
+
+ self::$_defaultNamespaces = $namespace;
+ }
+
+ /**
+ * Adds a new default namespace
+ *
+ * @param array|string $namespace
+ * @return null
+ */
+ public static function addDefaultNamespaces($namespace)
+ {
+ if (!is_array($namespace)) {
+ $namespace = array((string) $namespace);
+ }
+
+ self::$_defaultNamespaces = array_unique(array_merge(self::$_defaultNamespaces, $namespace));
+ }
+
+ /**
+ * Returns true when defaultNamespaces are set
+ *
+ * @return boolean
+ */
+ public static function hasDefaultNamespaces()
+ {
+ return (!empty(self::$_defaultNamespaces));
+ }
+
+ /**
+ * @deprecated
+ * @see Zend_Filter::filterStatic()
+ *
+ * @param mixed $value
+ * @param string $classBaseName
+ * @param array $args OPTIONAL
+ * @param array|string $namespaces OPTIONAL
+ * @return mixed
+ * @throws Zend_Filter_Exception
+ */
+ public static function get($value, $classBaseName, array $args = array(), $namespaces = array())
+ {
+ trigger_error(
+ 'Zend_Filter::get() is deprecated as of 1.9.0; please update your code to utilize Zend_Filter::filterStatic()',
+ E_USER_NOTICE
+ );
+
+ return self::filterStatic($value, $classBaseName, $args, $namespaces);
+ }
+
+ /**
+ * Returns a value filtered through a specified filter class, without requiring separate
+ * instantiation of the filter object.
+ *
+ * The first argument of this method is a data input value, that you would have filtered.
+ * The second argument is a string, which corresponds to the basename of the filter class,
+ * relative to the Zend_Filter namespace. This method automatically loads the class,
+ * creates an instance, and applies the filter() method to the data input. You can also pass
+ * an array of constructor arguments, if they are needed for the filter class.
+ *
+ * @param mixed $value
+ * @param string $classBaseName
+ * @param array $args OPTIONAL
+ * @param array|string $namespaces OPTIONAL
+ * @return mixed
+ * @throws Zend_Filter_Exception
+ */
+ public static function filterStatic($value, $classBaseName, array $args = array(), $namespaces = array())
+ {
+ require_once 'Zend/Loader.php';
+ $namespaces = array_merge((array) $namespaces, self::$_defaultNamespaces, array('Zend_Filter'));
+ foreach ($namespaces as $namespace) {
+ $className = $namespace . '_' . ucfirst($classBaseName);
+ if (!class_exists($className, false)) {
+ try {
+ $file = str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';
+ if (Zend_Loader::isReadable($file)) {
+ Zend_Loader::loadClass($className);
+ } else {
+ continue;
+ }
+ } catch (Zend_Exception $ze) {
+ continue;
+ }
+ }
+
+ $class = new ReflectionClass($className);
+ if ($class->implementsInterface('Zend_Filter_Interface')) {
+ if ($class->hasMethod('__construct')) {
+ $object = $class->newInstanceArgs($args);
+ } else {
+ $object = $class->newInstance();
+ }
+ return $object->filter($value);
+ }
+ }
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception("Filter class not found from basename '$classBaseName'");
+ }
+}
diff --git a/lib/zend/Zend/Filter/Alnum.php b/lib/zend/Zend/Filter/Alnum.php
new file mode 100644
index 00000000000..7455dafe45c
--- /dev/null
+++ b/lib/zend/Zend/Filter/Alnum.php
@@ -0,0 +1,146 @@
+toArray();
+ } else if (is_array($allowWhiteSpace)) {
+ if (array_key_exists('allowwhitespace', $allowWhiteSpace)) {
+ $allowWhiteSpace = $allowWhiteSpace['allowwhitespace'];
+ } else {
+ $allowWhiteSpace = false;
+ }
+ }
+
+ $this->allowWhiteSpace = (boolean) $allowWhiteSpace;
+ if (null === self::$_unicodeEnabled) {
+ self::$_unicodeEnabled = (@preg_match('/\pL/u', 'a')) ? true : false;
+ }
+
+ if (null === self::$_meansEnglishAlphabet) {
+ $this->_locale = new Zend_Locale('auto');
+ self::$_meansEnglishAlphabet = in_array($this->_locale->getLanguage(),
+ array('ja', 'ko', 'zh')
+ );
+ }
+
+ }
+
+ /**
+ * Returns the allowWhiteSpace option
+ *
+ * @return boolean
+ */
+ public function getAllowWhiteSpace()
+ {
+ return $this->allowWhiteSpace;
+ }
+
+ /**
+ * Sets the allowWhiteSpace option
+ *
+ * @param boolean $allowWhiteSpace
+ * @return Zend_Filter_Alnum Provides a fluent interface
+ */
+ public function setAllowWhiteSpace($allowWhiteSpace)
+ {
+ $this->allowWhiteSpace = (boolean) $allowWhiteSpace;
+ return $this;
+ }
+
+ /**
+ * Defined by Zend_Filter_Interface
+ *
+ * Returns the string $value, removing all but alphabetic and digit characters
+ *
+ * @param string $value
+ * @return string
+ */
+ public function filter($value)
+ {
+ $whiteSpace = $this->allowWhiteSpace ? '\s' : '';
+ if (!self::$_unicodeEnabled) {
+ // POSIX named classes are not supported, use alternative a-zA-Z0-9 match
+ $pattern = '/[^a-zA-Z0-9' . $whiteSpace . ']/';
+ } else if (self::$_meansEnglishAlphabet) {
+ //The Alphabet means english alphabet.
+ $pattern = '/[^a-zA-Z0-9' . $whiteSpace . ']/u';
+ } else {
+ //The Alphabet means each language's alphabet.
+ $pattern = '/[^\p{L}\p{N}' . $whiteSpace . ']/u';
+ }
+
+ return preg_replace($pattern, '', (string) $value);
+ }
+}
diff --git a/lib/zend/Zend/Filter/Alpha.php b/lib/zend/Zend/Filter/Alpha.php
new file mode 100644
index 00000000000..7374da1665e
--- /dev/null
+++ b/lib/zend/Zend/Filter/Alpha.php
@@ -0,0 +1,146 @@
+toArray();
+ } else if (is_array($allowWhiteSpace)) {
+ if (array_key_exists('allowwhitespace', $allowWhiteSpace)) {
+ $allowWhiteSpace = $allowWhiteSpace['allowwhitespace'];
+ } else {
+ $allowWhiteSpace = false;
+ }
+ }
+
+ $this->allowWhiteSpace = (boolean) $allowWhiteSpace;
+ if (null === self::$_unicodeEnabled) {
+ self::$_unicodeEnabled = (@preg_match('/\pL/u', 'a')) ? true : false;
+ }
+
+ if (null === self::$_meansEnglishAlphabet) {
+ $this->_locale = new Zend_Locale('auto');
+ self::$_meansEnglishAlphabet = in_array($this->_locale->getLanguage(),
+ array('ja', 'ko', 'zh')
+ );
+ }
+
+ }
+
+ /**
+ * Returns the allowWhiteSpace option
+ *
+ * @return boolean
+ */
+ public function getAllowWhiteSpace()
+ {
+ return $this->allowWhiteSpace;
+ }
+
+ /**
+ * Sets the allowWhiteSpace option
+ *
+ * @param boolean $allowWhiteSpace
+ * @return Zend_Filter_Alpha Provides a fluent interface
+ */
+ public function setAllowWhiteSpace($allowWhiteSpace)
+ {
+ $this->allowWhiteSpace = (boolean) $allowWhiteSpace;
+ return $this;
+ }
+
+ /**
+ * Defined by Zend_Filter_Interface
+ *
+ * Returns the string $value, removing all but alphabetic characters
+ *
+ * @param string $value
+ * @return string
+ */
+ public function filter($value)
+ {
+ $whiteSpace = $this->allowWhiteSpace ? '\s' : '';
+ if (!self::$_unicodeEnabled) {
+ // POSIX named classes are not supported, use alternative a-zA-Z match
+ $pattern = '/[^a-zA-Z' . $whiteSpace . ']/';
+ } else if (self::$_meansEnglishAlphabet) {
+ //The Alphabet means english alphabet.
+ $pattern = '/[^a-zA-Z' . $whiteSpace . ']/u';
+ } else {
+ //The Alphabet means each language's alphabet.
+ $pattern = '/[^\p{L}' . $whiteSpace . ']/u';
+ }
+
+ return preg_replace($pattern, '', (string) $value);
+ }
+}
diff --git a/lib/zend/Zend/Service/DeveloperGarden/Request/VoiceButler/VoiceButlerAbstract.php b/lib/zend/Zend/Filter/BaseName.php
similarity index 57%
rename from lib/zend/Zend/Service/DeveloperGarden/Request/VoiceButler/VoiceButlerAbstract.php
rename to lib/zend/Zend/Filter/BaseName.php
index c907f4c96d6..8d6a6da5607 100644
--- a/lib/zend/Zend/Service/DeveloperGarden/Request/VoiceButler/VoiceButlerAbstract.php
+++ b/lib/zend/Zend/Filter/BaseName.php
@@ -1,4 +1,5 @@
'boolean',
+ self::INTEGER => 'integer',
+ self::FLOAT => 'float',
+ self::STRING => 'string',
+ self::ZERO => 'zero',
+ self::EMPTY_ARRAY => 'array',
+ self::NULL => 'null',
+ self::PHP => 'php',
+ self::FALSE_STRING => 'false',
+ self::YES => 'yes',
+ self::ALL => 'all',
+ );
+
+ /**
+ * Internal type to detect
+ *
+ * @var integer
+ */
+ protected $_type = self::PHP;
+
+ /**
+ * Internal locale
+ *
+ * @var array
+ */
+ protected $_locale = array('auto');
+
+ /**
+ * Internal mode
+ *
+ * @var boolean
+ */
+ protected $_casting = true;
+
+ /**
+ * Constructor
+ *
+ * @param string|array|Zend_Config $options OPTIONAL
+ */
+ public function __construct($options = null)
+ {
+ if ($options instanceof Zend_Config) {
+ $options = $options->toArray();
+ } elseif (!is_array($options)) {
+ $options = func_get_args();
+ $temp = array();
+ if (!empty($options)) {
+ $temp['type'] = array_shift($options);
+ }
+
+ if (!empty($options)) {
+ $temp['casting'] = array_shift($options);
+ }
+
+ if (!empty($options)) {
+ $temp['locale'] = array_shift($options);
+ }
+
+ $options = $temp;
+ }
+
+ if (array_key_exists('type', $options)) {
+ $this->setType($options['type']);
+ }
+
+ if (array_key_exists('casting', $options)) {
+ $this->setCasting($options['casting']);
+ }
+
+ if (array_key_exists('locale', $options)) {
+ $this->setLocale($options['locale']);
+ }
+ }
+
+ /**
+ * Returns the set null types
+ *
+ * @return int
+ */
+ public function getType()
+ {
+ return $this->_type;
+ }
+
+ /**
+ * Set the null types
+ *
+ * @param integer|array $type
+ * @throws Zend_Filter_Exception
+ * @return Zend_Filter_Boolean
+ */
+ public function setType($type = null)
+ {
+ if (is_array($type)) {
+ $detected = 0;
+ foreach($type as $value) {
+ if (is_int($value)) {
+ $detected += $value;
+ } elseif (in_array($value, $this->_constants)) {
+ $detected += array_search($value, $this->_constants);
+ }
+ }
+
+ $type = $detected;
+ } elseif (is_string($type) && in_array($type, $this->_constants)) {
+ $type = array_search($type, $this->_constants);
+ }
+
+ if (!is_int($type) || ($type < 0) || ($type > self::ALL)) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('Unknown type');
+ }
+
+ $this->_type = $type;
+ return $this;
+ }
+
+ /**
+ * Returns the set locale
+ *
+ * @return array
+ */
+ public function getLocale()
+ {
+ return $this->_locale;
+ }
+
+ /**
+ * Set the locales which are accepted
+ *
+ * @param string|array|Zend_Locale $locale
+ * @throws Zend_Filter_Exception
+ * @return Zend_Filter_Boolean
+ */
+ public function setLocale($locale = null)
+ {
+ if (is_string($locale)) {
+ $locale = array($locale);
+ } elseif ($locale instanceof Zend_Locale) {
+ $locale = array($locale->toString());
+ } elseif (!is_array($locale)) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('Locale has to be string, array or an instance of Zend_Locale');
+ }
+
+ require_once 'Zend/Locale.php';
+ foreach ($locale as $single) {
+ if (!Zend_Locale::isLocale($single)) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception("Unknown locale '$single'");
+ }
+ }
+
+ $this->_locale = $locale;
+ return $this;
+ }
+
+ /**
+ * Returns the casting option
+ *
+ * @return boolean
+ */
+ public function getCasting()
+ {
+ return $this->_casting;
+ }
+
+ /**
+ * Set the working mode
+ *
+ * @param boolean $locale When true this filter works like cast
+ * When false it recognises only true and false
+ * and all other values are returned as is
+ * @throws Zend_Filter_Exception
+ * @return Zend_Filter_Boolean
+ */
+ public function setCasting($casting = true)
+ {
+ $this->_casting = (boolean) $casting;
+ return $this;
+ }
+
+ /**
+ * Defined by Zend_Filter_Interface
+ *
+ * Returns a boolean representation of $value
+ *
+ * @param string $value
+ * @return string
+ */
+ public function filter($value)
+ {
+ $type = $this->getType();
+ $casting = $this->getCasting();
+
+ // STRING YES (Localized)
+ if ($type >= self::YES) {
+ $type -= self::YES;
+ if (is_string($value)) {
+ require_once 'Zend/Locale.php';
+ $locales = $this->getLocale();
+ foreach ($locales as $locale) {
+ if ($this->_getLocalizedQuestion($value, false, $locale) === false) {
+ return false;
+ }
+
+ if (!$casting && ($this->_getLocalizedQuestion($value, true, $locale) === true)) {
+ return true;
+ }
+ }
+ }
+ }
+
+ // STRING FALSE ('false')
+ if ($type >= self::FALSE_STRING) {
+ $type -= self::FALSE_STRING;
+ if (is_string($value) && (strtolower($value) == 'false')) {
+ return false;
+ }
+
+ if ((!$casting) && is_string($value) && (strtolower($value) == 'true')) {
+ return true;
+ }
+ }
+
+ // NULL (null)
+ if ($type >= self::NULL) {
+ $type -= self::NULL;
+ if ($value === null) {
+ return false;
+ }
+ }
+
+ // EMPTY_ARRAY (array())
+ if ($type >= self::EMPTY_ARRAY) {
+ $type -= self::EMPTY_ARRAY;
+ if (is_array($value) && ($value == array())) {
+ return false;
+ }
+ }
+
+ // ZERO ('0')
+ if ($type >= self::ZERO) {
+ $type -= self::ZERO;
+ if (is_string($value) && ($value == '0')) {
+ return false;
+ }
+
+ if ((!$casting) && (is_string($value)) && ($value == '1')) {
+ return true;
+ }
+ }
+
+ // STRING ('')
+ if ($type >= self::STRING) {
+ $type -= self::STRING;
+ if (is_string($value) && ($value == '')) {
+ return false;
+ }
+ }
+
+ // FLOAT (0.0)
+ if ($type >= self::FLOAT) {
+ $type -= self::FLOAT;
+ if (is_float($value) && ($value == 0.0)) {
+ return false;
+ }
+
+ if ((!$casting) && is_float($value) && ($value == 1.0)) {
+ return true;
+ }
+ }
+
+ // INTEGER (0)
+ if ($type >= self::INTEGER) {
+ $type -= self::INTEGER;
+ if (is_int($value) && ($value == 0)) {
+ return false;
+ }
+
+ if ((!$casting) && is_int($value) && ($value == 1)) {
+ return true;
+ }
+ }
+
+ // BOOLEAN (false)
+ if ($type >= self::BOOLEAN) {
+ $type -= self::BOOLEAN;
+ if (is_bool($value)) {
+ return $value;
+ }
+ }
+
+ if ($casting) {
+ return true;
+ }
+
+ return $value;
+ }
+
+ /**
+ * Determine the value of a localized string, and compare it to a given value
+ *
+ * @param string $value
+ * @param boolean $yes
+ * @param array $locale
+ * @return boolean
+ */
+ protected function _getLocalizedQuestion($value, $yes, $locale)
+ {
+ if ($yes == true) {
+ $question = 'yes';
+ $return = true;
+ } else {
+ $question = 'no';
+ $return = false;
+ }
+ $str = Zend_Locale::getTranslation($question, 'question', $locale);
+ $str = explode(':', $str);
+ if (!empty($str)) {
+ foreach($str as $no) {
+ if (($no == $value) || (strtolower($no) == strtolower($value))) {
+ return $return;
+ }
+ }
+ }
+ }
+}
diff --git a/lib/zend/Zend/Filter/Callback.php b/lib/zend/Zend/Filter/Callback.php
new file mode 100644
index 00000000000..f7961ea5110
--- /dev/null
+++ b/lib/zend/Zend/Filter/Callback.php
@@ -0,0 +1,152 @@
+toArray();
+ } else if (!is_array($options) || !array_key_exists('callback', $options)) {
+ $options = func_get_args();
+ $temp['callback'] = array_shift($options);
+ if (!empty($options)) {
+ $temp['options'] = array_shift($options);
+ }
+
+ $options = $temp;
+ }
+
+ if (!array_key_exists('callback', $options)) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('Missing callback to use');
+ }
+
+ $this->setCallback($options['callback']);
+ if (array_key_exists('options', $options)) {
+ $this->setOptions($options['options']);
+ }
+ }
+
+ /**
+ * Returns the set callback
+ *
+ * @return string|array Set callback
+ */
+ public function getCallback()
+ {
+ return $this->_callback;
+ }
+
+ /**
+ * Sets a new callback for this filter
+ *
+ * @param unknown_type $callback
+ * @return unknown
+ */
+ public function setCallback($callback, $options = null)
+ {
+ if (!is_callable($callback)) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('Callback can not be accessed');
+ }
+
+ $this->_callback = $callback;
+ $this->setOptions($options);
+ return $this;
+ }
+
+ /**
+ * Returns the set default options
+ *
+ * @return mixed
+ */
+ public function getOptions()
+ {
+ return $this->_options;
+ }
+
+ /**
+ * Sets new default options to the callback filter
+ *
+ * @param mixed $options Default options to set
+ * @return Zend_Filter_Callback
+ */
+ public function setOptions($options)
+ {
+ $this->_options = $options;
+ return $this;
+ }
+
+ /**
+ * Calls the filter per callback
+ *
+ * @param mixed $value Options for the set callback
+ * @return mixed Result from the filter which was callbacked
+ */
+ public function filter($value)
+ {
+ $options = array();
+
+ if ($this->_options !== null) {
+ if (!is_array($this->_options)) {
+ $options = array($this->_options);
+ } else {
+ $options = $this->_options;
+ }
+ }
+
+ array_unshift($options, $value);
+
+ return call_user_func_array($this->_callback, $options);
+ }
+}
diff --git a/lib/zend/Zend/Filter/Compress.php b/lib/zend/Zend/Filter/Compress.php
new file mode 100644
index 00000000000..e9361f7a437
--- /dev/null
+++ b/lib/zend/Zend/Filter/Compress.php
@@ -0,0 +1,197 @@
+toArray();
+ }
+ if (is_string($options)) {
+ $this->setAdapter($options);
+ } elseif ($options instanceof Zend_Filter_Compress_CompressInterface) {
+ $this->setAdapter($options);
+ } elseif (is_array($options)) {
+ $this->setOptions($options);
+ }
+ }
+
+ /**
+ * Set filter setate
+ *
+ * @param array $options
+ * @return Zend_Filter_Compress
+ */
+ public function setOptions(array $options)
+ {
+ foreach ($options as $key => $value) {
+ if ($key == 'options') {
+ $key = 'adapterOptions';
+ }
+ $method = 'set' . ucfirst($key);
+ if (method_exists($this, $method)) {
+ $this->$method($value);
+ }
+ }
+ return $this;
+ }
+
+ /**
+ * Returns the current adapter, instantiating it if necessary
+ *
+ * @return string
+ */
+ public function getAdapter()
+ {
+ if ($this->_adapter instanceof Zend_Filter_Compress_CompressInterface) {
+ return $this->_adapter;
+ }
+
+ $adapter = $this->_adapter;
+ $options = $this->getAdapterOptions();
+ if (!class_exists($adapter)) {
+ require_once 'Zend/Loader.php';
+ if (Zend_Loader::isReadable('Zend/Filter/Compress/' . ucfirst($adapter) . '.php')) {
+ $adapter = 'Zend_Filter_Compress_' . ucfirst($adapter);
+ }
+ Zend_Loader::loadClass($adapter);
+ }
+
+ $this->_adapter = new $adapter($options);
+ if (!$this->_adapter instanceof Zend_Filter_Compress_CompressInterface) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception("Compression adapter '" . $adapter . "' does not implement Zend_Filter_Compress_CompressInterface");
+ }
+ return $this->_adapter;
+ }
+
+ /**
+ * Retrieve adapter name
+ *
+ * @return string
+ */
+ public function getAdapterName()
+ {
+ return $this->getAdapter()->toString();
+ }
+
+ /**
+ * Sets compression adapter
+ *
+ * @param string|Zend_Filter_Compress_CompressInterface $adapter Adapter to use
+ * @return Zend_Filter_Compress
+ */
+ public function setAdapter($adapter)
+ {
+ if ($adapter instanceof Zend_Filter_Compress_CompressInterface) {
+ $this->_adapter = $adapter;
+ return $this;
+ }
+ if (!is_string($adapter)) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('Invalid adapter provided; must be string or instance of Zend_Filter_Compress_CompressInterface');
+ }
+ $this->_adapter = $adapter;
+
+ return $this;
+ }
+
+ /**
+ * Retrieve adapter options
+ *
+ * @return array
+ */
+ public function getAdapterOptions()
+ {
+ return $this->_adapterOptions;
+ }
+
+ /**
+ * Set adapter options
+ *
+ * @param array $options
+ * @return void
+ */
+ public function setAdapterOptions(array $options)
+ {
+ $this->_adapterOptions = $options;
+ return $this;
+ }
+
+ /**
+ * Calls adapter methods
+ *
+ * @param string $method Method to call
+ * @param string|array $options Options for this method
+ */
+ public function __call($method, $options)
+ {
+ $adapter = $this->getAdapter();
+ if (!method_exists($adapter, $method)) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception("Unknown method '{$method}'");
+ }
+
+ return call_user_func_array(array($adapter, $method), $options);
+ }
+
+ /**
+ * Defined by Zend_Filter_Interface
+ *
+ * Compresses the content $value with the defined settings
+ *
+ * @param string $value Content to compress
+ * @return string The compressed content
+ */
+ public function filter($value)
+ {
+ return $this->getAdapter()->compress($value);
+ }
+}
diff --git a/lib/zend/Zend/Filter/Compress/Bz2.php b/lib/zend/Zend/Filter/Compress/Bz2.php
new file mode 100644
index 00000000000..6bd4451f7bd
--- /dev/null
+++ b/lib/zend/Zend/Filter/Compress/Bz2.php
@@ -0,0 +1,188 @@
+ Blocksize to use from 0-9
+ * 'archive' => Archive to use
+ * )
+ *
+ * @var array
+ */
+ protected $_options = array(
+ 'blocksize' => 4,
+ 'archive' => null,
+ );
+
+ /**
+ * Class constructor
+ *
+ * @param array|Zend_Config $options (Optional) Options to set
+ */
+ public function __construct($options = null)
+ {
+ if (!extension_loaded('bz2')) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('This filter needs the bz2 extension');
+ }
+ parent::__construct($options);
+ }
+
+ /**
+ * Returns the set blocksize
+ *
+ * @return integer
+ */
+ public function getBlocksize()
+ {
+ return $this->_options['blocksize'];
+ }
+
+ /**
+ * Sets a new blocksize
+ *
+ * @param integer $level
+ * @return Zend_Filter_Compress_Bz2
+ */
+ public function setBlocksize($blocksize)
+ {
+ if (($blocksize < 0) || ($blocksize > 9)) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('Blocksize must be between 0 and 9');
+ }
+
+ $this->_options['blocksize'] = (int) $blocksize;
+ return $this;
+ }
+
+ /**
+ * Returns the set archive
+ *
+ * @return string
+ */
+ public function getArchive()
+ {
+ return $this->_options['archive'];
+ }
+
+ /**
+ * Sets the archive to use for de-/compression
+ *
+ * @param string $archive Archive to use
+ * @return Zend_Filter_Compress_Bz2
+ */
+ public function setArchive($archive)
+ {
+ $this->_options['archive'] = (string) $archive;
+ return $this;
+ }
+
+ /**
+ * Compresses the given content
+ *
+ * @param string $content
+ * @return string
+ */
+ public function compress($content)
+ {
+ $archive = $this->getArchive();
+ if (!empty($archive)) {
+ $file = bzopen($archive, 'w');
+ if (!$file) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception("Error opening the archive '" . $archive . "'");
+ }
+
+ bzwrite($file, $content);
+ bzclose($file);
+ $compressed = true;
+ } else {
+ $compressed = bzcompress($content, $this->getBlocksize());
+ }
+
+ if (is_int($compressed)) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('Error during compression');
+ }
+
+ return $compressed;
+ }
+
+ /**
+ * Decompresses the given content
+ *
+ * @param string $content
+ * @return string
+ */
+ public function decompress($content)
+ {
+ $archive = $this->getArchive();
+ if (@file_exists($content)) {
+ $archive = $content;
+ }
+
+ if (@file_exists($archive)) {
+ $file = bzopen($archive, 'r');
+ if (!$file) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception("Error opening the archive '" . $content . "'");
+ }
+
+ $compressed = bzread($file);
+ bzclose($file);
+ } else {
+ $compressed = bzdecompress($content);
+ }
+
+ if (is_int($compressed)) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('Error during decompression');
+ }
+
+ return $compressed;
+ }
+
+ /**
+ * Returns the adapter name
+ *
+ * @return string
+ */
+ public function toString()
+ {
+ return 'Bz2';
+ }
+}
diff --git a/lib/zend/Zend/Filter/Compress/CompressAbstract.php b/lib/zend/Zend/Filter/Compress/CompressAbstract.php
new file mode 100644
index 00000000000..2b20ac6f071
--- /dev/null
+++ b/lib/zend/Zend/Filter/Compress/CompressAbstract.php
@@ -0,0 +1,89 @@
+toArray();
+ }
+
+ if (is_array($options)) {
+ $this->setOptions($options);
+ }
+ }
+
+ /**
+ * Returns one or all set options
+ *
+ * @param string $option (Optional) Option to return
+ * @return mixed
+ */
+ public function getOptions($option = null)
+ {
+ if ($option === null) {
+ return $this->_options;
+ }
+
+ if (!array_key_exists($option, $this->_options)) {
+ return null;
+ }
+
+ return $this->_options[$option];
+ }
+
+ /**
+ * Sets all or one option
+ *
+ * @param array $options
+ * @return Zend_Filter_Compress_Bz2
+ */
+ public function setOptions(array $options)
+ {
+ foreach ($options as $key => $option) {
+ $method = 'set' . $key;
+ if (method_exists($this, $method)) {
+ $this->$method($option);
+ }
+ }
+
+ return $this;
+ }
+}
diff --git a/lib/zend/Zend/Service/DeveloperGarden/ConferenceCall/ConferenceAccount.php b/lib/zend/Zend/Filter/Compress/CompressInterface.php
similarity index 54%
rename from lib/zend/Zend/Service/DeveloperGarden/ConferenceCall/ConferenceAccount.php
rename to lib/zend/Zend/Filter/Compress/CompressInterface.php
index 37c609ba15e..75f0a4063bc 100644
--- a/lib/zend/Zend/Service/DeveloperGarden/ConferenceCall/ConferenceAccount.php
+++ b/lib/zend/Zend/Filter/Compress/CompressInterface.php
@@ -13,50 +13,42 @@
* to license@zend.com so we can send you a copy immediately.
*
* @category Zend
- * @package Zend_Service
- * @subpackage DeveloperGarden
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @package Zend_Filter
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
+ * Compression interface
+ *
* @category Zend
- * @package Zend_Service
- * @subpackage DeveloperGarden
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
- * @author Marco Kaiser
+ * @package Zend_Filter
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
-class Zend_Service_DeveloperGarden_ConferenceCall_ConferenceAccount
+interface Zend_Filter_Compress_CompressInterface
{
/**
- * type of billing
+ * Compresses $value with the defined settings
*
- * @var string
+ * @param string $value Data to compress
+ * @return string The compressed data
*/
- public $billingtype = null;
+ public function compress($value);
/**
- * account id
+ * Decompresses $value with the defined settings
*
- * @var integer
+ * @param string $value Data to decompress
+ * @return string The decompressed data
*/
- public $account = null;
-
- /**
- * @return integer
- */
- public function getAccount()
- {
- return $this->account;
- }
+ public function decompress($value);
/**
+ * Return the adapter name
+ *
* @return string
*/
- public function getBillingType()
- {
- return $this->billingtype;
- }
+ public function toString();
}
diff --git a/lib/zend/Zend/Filter/Compress/Gz.php b/lib/zend/Zend/Filter/Compress/Gz.php
new file mode 100644
index 00000000000..819795c5c97
--- /dev/null
+++ b/lib/zend/Zend/Filter/Compress/Gz.php
@@ -0,0 +1,228 @@
+ Compression level 0-9
+ * 'mode' => Compression mode, can be 'compress', 'deflate'
+ * 'archive' => Archive to use
+ * )
+ *
+ * @var array
+ */
+ protected $_options = array(
+ 'level' => 9,
+ 'mode' => 'compress',
+ 'archive' => null,
+ );
+
+ /**
+ * Class constructor
+ *
+ * @param array|Zend_Config|null $options (Optional) Options to set
+ */
+ public function __construct($options = null)
+ {
+ if (!extension_loaded('zlib')) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('This filter needs the zlib extension');
+ }
+ parent::__construct($options);
+ }
+
+ /**
+ * Returns the set compression level
+ *
+ * @return integer
+ */
+ public function getLevel()
+ {
+ return $this->_options['level'];
+ }
+
+ /**
+ * Sets a new compression level
+ *
+ * @param integer $level
+ * @return Zend_Filter_Compress_Gz
+ */
+ public function setLevel($level)
+ {
+ if (($level < 0) || ($level > 9)) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('Level must be between 0 and 9');
+ }
+
+ $this->_options['level'] = (int) $level;
+ return $this;
+ }
+
+ /**
+ * Returns the set compression mode
+ *
+ * @return string
+ */
+ public function getMode()
+ {
+ return $this->_options['mode'];
+ }
+
+ /**
+ * Sets a new compression mode
+ *
+ * @param string $mode Supported are 'compress', 'deflate' and 'file'
+ */
+ public function setMode($mode)
+ {
+ if (($mode != 'compress') && ($mode != 'deflate')) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('Given compression mode not supported');
+ }
+
+ $this->_options['mode'] = $mode;
+ return $this;
+ }
+
+ /**
+ * Returns the set archive
+ *
+ * @return string
+ */
+ public function getArchive()
+ {
+ return $this->_options['archive'];
+ }
+
+ /**
+ * Sets the archive to use for de-/compression
+ *
+ * @param string $archive Archive to use
+ * @return Zend_Filter_Compress_Gz
+ */
+ public function setArchive($archive)
+ {
+ $this->_options['archive'] = (string) $archive;
+ return $this;
+ }
+
+ /**
+ * Compresses the given content
+ *
+ * @param string $content
+ * @return string
+ */
+ public function compress($content)
+ {
+ $archive = $this->getArchive();
+ if (!empty($archive)) {
+ $file = gzopen($archive, 'w' . $this->getLevel());
+ if (!$file) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception("Error opening the archive '" . $this->_options['archive'] . "'");
+ }
+
+ gzwrite($file, $content);
+ gzclose($file);
+ $compressed = true;
+ } else if ($this->_options['mode'] == 'deflate') {
+ $compressed = gzdeflate($content, $this->getLevel());
+ } else {
+ $compressed = gzcompress($content, $this->getLevel());
+ }
+
+ if (!$compressed) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('Error during compression');
+ }
+
+ return $compressed;
+ }
+
+ /**
+ * Decompresses the given content
+ *
+ * @param string $content
+ * @return string
+ */
+ public function decompress($content)
+ {
+ $archive = $this->getArchive();
+ $mode = $this->getMode();
+ if (@file_exists($content)) {
+ $archive = $content;
+ }
+
+ if (@file_exists($archive)) {
+ $handler = fopen($archive, "rb");
+ if (!$handler) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception("Error opening the archive '" . $archive . "'");
+ }
+
+ fseek($handler, -4, SEEK_END);
+ $packet = fread($handler, 4);
+ $bytes = unpack("V", $packet);
+ $size = end($bytes);
+ fclose($handler);
+
+ $file = gzopen($archive, 'r');
+ $compressed = gzread($file, $size);
+ gzclose($file);
+ } else if ($mode == 'deflate') {
+ $compressed = gzinflate($content);
+ } else {
+ $compressed = gzuncompress($content);
+ }
+
+ if (!$compressed) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('Error during compression');
+ }
+
+ return $compressed;
+ }
+
+ /**
+ * Returns the adapter name
+ *
+ * @return string
+ */
+ public function toString()
+ {
+ return 'Gz';
+ }
+}
diff --git a/lib/zend/Zend/Filter/Compress/Lzf.php b/lib/zend/Zend/Filter/Compress/Lzf.php
new file mode 100644
index 00000000000..33115105a00
--- /dev/null
+++ b/lib/zend/Zend/Filter/Compress/Lzf.php
@@ -0,0 +1,91 @@
+ Callback for compression
+ * 'archive' => Archive to use
+ * 'password' => Password to use
+ * 'target' => Target to write the files to
+ * )
+ *
+ * @var array
+ */
+ protected $_options = array(
+ 'callback' => null,
+ 'archive' => null,
+ 'password' => null,
+ 'target' => '.',
+ );
+
+ /**
+ * Class constructor
+ *
+ * @param array $options (Optional) Options to set
+ */
+ public function __construct($options = null)
+ {
+ if (!extension_loaded('rar')) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('This filter needs the rar extension');
+ }
+ parent::__construct($options);
+ }
+
+ /**
+ * Returns the set callback for compression
+ *
+ * @return string
+ */
+ public function getCallback()
+ {
+ return $this->_options['callback'];
+ }
+
+ /**
+ * Sets the callback to use
+ *
+ * @param string $callback
+ * @return Zend_Filter_Compress_Rar
+ */
+ public function setCallback($callback)
+ {
+ if (!is_callable($callback)) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('Callback can not be accessed');
+ }
+
+ $this->_options['callback'] = $callback;
+ return $this;
+ }
+
+ /**
+ * Returns the set archive
+ *
+ * @return string
+ */
+ public function getArchive()
+ {
+ return $this->_options['archive'];
+ }
+
+ /**
+ * Sets the archive to use for de-/compression
+ *
+ * @param string $archive Archive to use
+ * @return Zend_Filter_Compress_Rar
+ */
+ public function setArchive($archive)
+ {
+ $archive = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $archive);
+ $this->_options['archive'] = (string) $archive;
+
+ return $this;
+ }
+
+ /**
+ * Returns the set password
+ *
+ * @return string
+ */
+ public function getPassword()
+ {
+ return $this->_options['password'];
+ }
+
+ /**
+ * Sets the password to use
+ *
+ * @param string $password
+ * @return Zend_Filter_Compress_Rar
+ */
+ public function setPassword($password)
+ {
+ $this->_options['password'] = (string) $password;
+ return $this;
+ }
+
+ /**
+ * Returns the set targetpath
+ *
+ * @return string
+ */
+ public function getTarget()
+ {
+ return $this->_options['target'];
+ }
+
+ /**
+ * Sets the targetpath to use
+ *
+ * @param string $target
+ * @return Zend_Filter_Compress_Rar
+ */
+ public function setTarget($target)
+ {
+ if (!file_exists(dirname($target))) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception("The directory '$target' does not exist");
+ }
+
+ $target = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $target);
+ $this->_options['target'] = (string) $target;
+ return $this;
+ }
+
+ /**
+ * Compresses the given content
+ *
+ * @param string|array $content
+ * @return string
+ */
+ public function compress($content)
+ {
+ $callback = $this->getCallback();
+ if ($callback === null) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('No compression callback available');
+ }
+
+ $options = $this->getOptions();
+ unset($options['callback']);
+
+ $result = call_user_func($callback, $options, $content);
+ if ($result !== true) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('Error compressing the RAR Archive');
+ }
+
+ return $this->getArchive();
+ }
+
+ /**
+ * Decompresses the given content
+ *
+ * @param string $content
+ * @return boolean
+ */
+ public function decompress($content)
+ {
+ $archive = $this->getArchive();
+ if (file_exists($content)) {
+ $archive = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, realpath($content));
+ } elseif (empty($archive) || !file_exists($archive)) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('RAR Archive not found');
+ }
+
+ $password = $this->getPassword();
+ if ($password !== null) {
+ $archive = rar_open($archive, $password);
+ } else {
+ $archive = rar_open($archive);
+ }
+
+ if (!$archive) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception("Error opening the RAR Archive");
+ }
+
+ $target = $this->getTarget();
+ if (!is_dir($target)) {
+ $target = dirname($target);
+ }
+
+ $filelist = rar_list($archive);
+ if (!$filelist) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception("Error reading the RAR Archive");
+ }
+
+ foreach($filelist as $file) {
+ $file->extract($target);
+ }
+
+ rar_close($archive);
+ return true;
+ }
+
+ /**
+ * Returns the adapter name
+ *
+ * @return string
+ */
+ public function toString()
+ {
+ return 'Rar';
+ }
+}
diff --git a/lib/zend/Zend/Filter/Compress/Tar.php b/lib/zend/Zend/Filter/Compress/Tar.php
new file mode 100644
index 00000000000..d2ce0d89a9b
--- /dev/null
+++ b/lib/zend/Zend/Filter/Compress/Tar.php
@@ -0,0 +1,245 @@
+ Archive to use
+ * 'target' => Target to write the files to
+ * )
+ *
+ * @var array
+ */
+ protected $_options = array(
+ 'archive' => null,
+ 'target' => '.',
+ 'mode' => null,
+ );
+
+ /**
+ * Class constructor
+ *
+ * @param array $options (Optional) Options to set
+ */
+ public function __construct($options = null)
+ {
+ if (!class_exists('Archive_Tar')) {
+ require_once 'Zend/Loader.php';
+ try {
+ Zend_Loader::loadClass('Archive_Tar');
+ } catch (Zend_Exception $e) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('This filter needs PEARs Archive_Tar', 0, $e);
+ }
+ }
+
+ parent::__construct($options);
+ }
+
+ /**
+ * Returns the set archive
+ *
+ * @return string
+ */
+ public function getArchive()
+ {
+ return $this->_options['archive'];
+ }
+
+ /**
+ * Sets the archive to use for de-/compression
+ *
+ * @param string $archive Archive to use
+ * @return Zend_Filter_Compress_Tar
+ */
+ public function setArchive($archive)
+ {
+ $archive = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $archive);
+ $this->_options['archive'] = (string) $archive;
+
+ return $this;
+ }
+
+ /**
+ * Returns the set targetpath
+ *
+ * @return string
+ */
+ public function getTarget()
+ {
+ return $this->_options['target'];
+ }
+
+ /**
+ * Sets the targetpath to use
+ *
+ * @param string $target
+ * @return Zend_Filter_Compress_Tar
+ */
+ public function setTarget($target)
+ {
+ if (!file_exists(dirname($target))) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception("The directory '$target' does not exist");
+ }
+
+ $target = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $target);
+ $this->_options['target'] = (string) $target;
+ return $this;
+ }
+
+ /**
+ * Returns the set compression mode
+ */
+ public function getMode()
+ {
+ return $this->_options['mode'];
+ }
+
+ /**
+ * Compression mode to use
+ * Eighter Gz or Bz2
+ *
+ * @param string $mode
+ */
+ public function setMode($mode)
+ {
+ $mode = ucfirst(strtolower($mode));
+ if (($mode != 'Bz2') && ($mode != 'Gz')) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception("The mode '$mode' is unknown");
+ }
+
+ if (($mode == 'Bz2') && (!extension_loaded('bz2'))) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('This mode needs the bz2 extension');
+ }
+
+ if (($mode == 'Gz') && (!extension_loaded('zlib'))) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('This mode needs the zlib extension');
+ }
+ }
+
+ /**
+ * Compresses the given content
+ *
+ * @param string $content
+ * @return string
+ */
+ public function compress($content)
+ {
+ $archive = new Archive_Tar($this->getArchive(), $this->getMode());
+ if (!file_exists($content)) {
+ $file = $this->getTarget();
+ if (is_dir($file)) {
+ $file .= DIRECTORY_SEPARATOR . "tar.tmp";
+ }
+
+ $result = file_put_contents($file, $content);
+ if ($result === false) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('Error creating the temporary file');
+ }
+
+ $content = $file;
+ }
+
+ if (is_dir($content)) {
+ // collect all file infos
+ foreach (new RecursiveIteratorIterator(
+ new RecursiveDirectoryIterator($content, RecursiveDirectoryIterator::KEY_AS_PATHNAME),
+ RecursiveIteratorIterator::SELF_FIRST
+ ) as $directory => $info
+ ) {
+ if ($info->isFile()) {
+ $file[] = $directory;
+ }
+ }
+
+ $content = $file;
+ }
+
+ $result = $archive->create($content);
+ if ($result === false) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('Error creating the Tar archive');
+ }
+
+ return $this->getArchive();
+ }
+
+ /**
+ * Decompresses the given content
+ *
+ * @param string $content
+ * @return boolean
+ */
+ public function decompress($content)
+ {
+ $archive = $this->getArchive();
+ if (file_exists($content)) {
+ $archive = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, realpath($content));
+ } elseif (empty($archive) || !file_exists($archive)) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('Tar Archive not found');
+ }
+
+ $archive = new Archive_Tar($archive, $this->getMode());
+ $target = $this->getTarget();
+ if (!is_dir($target)) {
+ $target = dirname($target);
+ }
+
+ $result = $archive->extract($target);
+ if ($result === false) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('Error while extracting the Tar archive');
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns the adapter name
+ *
+ * @return string
+ */
+ public function toString()
+ {
+ return 'Tar';
+ }
+}
diff --git a/lib/zend/Zend/Filter/Compress/Zip.php b/lib/zend/Zend/Filter/Compress/Zip.php
new file mode 100644
index 00000000000..9921fe9648a
--- /dev/null
+++ b/lib/zend/Zend/Filter/Compress/Zip.php
@@ -0,0 +1,355 @@
+ Archive to use
+ * 'password' => Password to use
+ * 'target' => Target to write the files to
+ * )
+ *
+ * @var array
+ */
+ protected $_options = array(
+ 'archive' => null,
+ 'target' => null,
+ );
+
+ /**
+ * Class constructor
+ *
+ * @param string|array $options (Optional) Options to set
+ */
+ public function __construct($options = null)
+ {
+ if (!extension_loaded('zip')) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('This filter needs the zip extension');
+ }
+ parent::__construct($options);
+ }
+
+ /**
+ * Returns the set archive
+ *
+ * @return string
+ */
+ public function getArchive()
+ {
+ return $this->_options['archive'];
+ }
+
+ /**
+ * Sets the archive to use for de-/compression
+ *
+ * @param string $archive Archive to use
+ * @return Zend_Filter_Compress_Rar
+ */
+ public function setArchive($archive)
+ {
+ $archive = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $archive);
+ $this->_options['archive'] = (string) $archive;
+
+ return $this;
+ }
+
+ /**
+ * Returns the set targetpath
+ *
+ * @return string
+ */
+ public function getTarget()
+ {
+ return $this->_options['target'];
+ }
+
+ /**
+ * Sets the target to use
+ *
+ * @param string $target
+ * @return Zend_Filter_Compress_Rar
+ */
+ public function setTarget($target)
+ {
+ if (!file_exists(dirname($target))) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception("The directory '$target' does not exist");
+ }
+
+ $target = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $target);
+ $this->_options['target'] = (string) $target;
+ return $this;
+ }
+
+ /**
+ * Compresses the given content
+ *
+ * @param string $content
+ * @return string Compressed archive
+ */
+ public function compress($content)
+ {
+ $zip = new ZipArchive();
+ $res = $zip->open($this->getArchive(), ZipArchive::CREATE | ZipArchive::OVERWRITE);
+
+ if ($res !== true) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception($this->_errorString($res));
+ }
+
+ if (file_exists($content)) {
+ $content = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, realpath($content));
+ $basename = substr($content, strrpos($content, DIRECTORY_SEPARATOR) + 1);
+ if (is_dir($content)) {
+ $index = strrpos($content, DIRECTORY_SEPARATOR) + 1;
+ $content .= DIRECTORY_SEPARATOR;
+ $stack = array($content);
+ while (!empty($stack)) {
+ $current = array_pop($stack);
+ $files = array();
+
+ $dir = dir($current);
+ while (false !== ($node = $dir->read())) {
+ if (($node == '.') || ($node == '..')) {
+ continue;
+ }
+
+ if (is_dir($current . $node)) {
+ array_push($stack, $current . $node . DIRECTORY_SEPARATOR);
+ }
+
+ if (is_file($current . $node)) {
+ $files[] = $node;
+ }
+ }
+
+ $local = substr($current, $index);
+ $zip->addEmptyDir(substr($local, 0, -1));
+
+ foreach ($files as $file) {
+ $zip->addFile($current . $file, $local . $file);
+ if ($res !== true) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception($this->_errorString($res));
+ }
+ }
+ }
+ } else {
+ $res = $zip->addFile($content, $basename);
+ if ($res !== true) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception($this->_errorString($res));
+ }
+ }
+ } else {
+ $file = $this->getTarget();
+ if (!is_dir($file)) {
+ $file = basename($file);
+ } else {
+ $file = "zip.tmp";
+ }
+
+ $res = $zip->addFromString($file, $content);
+ if ($res !== true) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception($this->_errorString($res));
+ }
+ }
+
+ $zip->close();
+ return $this->_options['archive'];
+ }
+
+ /**
+ * Decompresses the given content
+ *
+ * @param string $content
+ * @return string
+ */
+ public function decompress($content)
+ {
+ $archive = $this->getArchive();
+ if (file_exists($content)) {
+ $archive = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, realpath($content));
+ } elseif (empty($archive) || !file_exists($archive)) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('ZIP Archive not found');
+ }
+
+ $zip = new ZipArchive();
+ $res = $zip->open($archive);
+
+ $target = $this->getTarget();
+
+ if (!empty($target) && !is_dir($target)) {
+ $target = dirname($target);
+ }
+
+ if (!empty($target)) {
+ $target = rtrim($target, '/\\') . DIRECTORY_SEPARATOR;
+ }
+
+ if (empty($target) || !is_dir($target)) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('No target for ZIP decompression set');
+ }
+
+ if ($res !== true) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception($this->_errorString($res));
+ }
+
+ if (version_compare(PHP_VERSION, '5.2.8', '<')) {
+ for ($i = 0; $i < $zip->numFiles; $i++) {
+ $statIndex = $zip->statIndex($i);
+ $currName = $statIndex['name'];
+ if (($currName{0} == '/') ||
+ (substr($currName, 0, 2) == '..') ||
+ (substr($currName, 0, 4) == './..')
+ )
+ {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('Upward directory traversal was detected inside ' . $archive
+ . ' please use PHP 5.2.8 or greater to take advantage of path resolution features of '
+ . 'the zip extension in this decompress() method.'
+ );
+ }
+ }
+ }
+
+ $res = @$zip->extractTo($target);
+ if ($res !== true) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception($this->_errorString($res));
+ }
+
+ $zip->close();
+ return $target;
+ }
+
+ /**
+ * Returns the proper string based on the given error constant
+ *
+ * @param string $error
+ */
+ protected function _errorString($error)
+ {
+ switch($error) {
+ case ZipArchive::ER_MULTIDISK :
+ return 'Multidisk ZIP Archives not supported';
+
+ case ZipArchive::ER_RENAME :
+ return 'Failed to rename the temporary file for ZIP';
+
+ case ZipArchive::ER_CLOSE :
+ return 'Failed to close the ZIP Archive';
+
+ case ZipArchive::ER_SEEK :
+ return 'Failure while seeking the ZIP Archive';
+
+ case ZipArchive::ER_READ :
+ return 'Failure while reading the ZIP Archive';
+
+ case ZipArchive::ER_WRITE :
+ return 'Failure while writing the ZIP Archive';
+
+ case ZipArchive::ER_CRC :
+ return 'CRC failure within the ZIP Archive';
+
+ case ZipArchive::ER_ZIPCLOSED :
+ return 'ZIP Archive already closed';
+
+ case ZipArchive::ER_NOENT :
+ return 'No such file within the ZIP Archive';
+
+ case ZipArchive::ER_EXISTS :
+ return 'ZIP Archive already exists';
+
+ case ZipArchive::ER_OPEN :
+ return 'Can not open ZIP Archive';
+
+ case ZipArchive::ER_TMPOPEN :
+ return 'Failure creating temporary ZIP Archive';
+
+ case ZipArchive::ER_ZLIB :
+ return 'ZLib Problem';
+
+ case ZipArchive::ER_MEMORY :
+ return 'Memory allocation problem while working on a ZIP Archive';
+
+ case ZipArchive::ER_CHANGED :
+ return 'ZIP Entry has been changed';
+
+ case ZipArchive::ER_COMPNOTSUPP :
+ return 'Compression method not supported within ZLib';
+
+ case ZipArchive::ER_EOF :
+ return 'Premature EOF within ZIP Archive';
+
+ case ZipArchive::ER_INVAL :
+ return 'Invalid argument for ZLIB';
+
+ case ZipArchive::ER_NOZIP :
+ return 'Given file is no zip archive';
+
+ case ZipArchive::ER_INTERNAL :
+ return 'Internal error while working on a ZIP Archive';
+
+ case ZipArchive::ER_INCONS :
+ return 'Inconsistent ZIP archive';
+
+ case ZipArchive::ER_REMOVE :
+ return 'Can not remove ZIP Archive';
+
+ case ZipArchive::ER_DELETED :
+ return 'ZIP Entry has been deleted';
+
+ default :
+ return 'Unknown error within ZIP Archive';
+ }
+ }
+
+ /**
+ * Returns the adapter name
+ *
+ * @return string
+ */
+ public function toString()
+ {
+ return 'Zip';
+ }
+}
diff --git a/lib/zend/Zend/Service/DeveloperGarden/Request/SendSms/SendFlashSMS.php b/lib/zend/Zend/Filter/Decompress.php
similarity index 54%
rename from lib/zend/Zend/Service/DeveloperGarden/Request/SendSms/SendFlashSMS.php
rename to lib/zend/Zend/Filter/Decompress.php
index 0471d5f4c9b..02e9a8e5d4f 100644
--- a/lib/zend/Zend/Service/DeveloperGarden/Request/SendSms/SendFlashSMS.php
+++ b/lib/zend/Zend/Filter/Decompress.php
@@ -13,34 +13,37 @@
* to license@zend.com so we can send you a copy immediately.
*
* @category Zend
- * @package Zend_Service
- * @subpackage DeveloperGarden
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @package Zend_Filter
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
- * @see Zend_Service_DeveloperGarden_Request_SendSms_SendSmsAbstract
+ * @see Zend_Filter_Compress
*/
-require_once 'Zend/Service/DeveloperGarden/Request/SendSms/SendSmsAbstract.php';
+require_once 'Zend/Filter/Compress.php';
/**
+ * Decompresses a given string
+ *
* @category Zend
- * @package Zend_Service
- * @subpackage DeveloperGarden
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
- * @author Marco Kaiser
+ * @package Zend_Filter
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
-class Zend_Service_DeveloperGarden_Request_SendSms_SendFlashSMS
- extends Zend_Service_DeveloperGarden_Request_SendSms_SendSmsAbstract
+class Zend_Filter_Decompress extends Zend_Filter_Compress
{
/**
- * this is the sms type
- * 2 = FlashSMS
+ * Defined by Zend_Filter_Interface
*
- * @var integer
+ * Decompresses the content $value with the defined settings
+ *
+ * @param string $value Content to decompress
+ * @return string The decompressed content
*/
- protected $_smsType = 2;
+ public function filter($value)
+ {
+ return $this->getAdapter()->decompress($value);
+ }
}
diff --git a/lib/zend/Zend/Service/DeveloperGarden/Request/SendSms/SendSMS.php b/lib/zend/Zend/Filter/Decrypt.php
similarity index 54%
rename from lib/zend/Zend/Service/DeveloperGarden/Request/SendSms/SendSMS.php
rename to lib/zend/Zend/Filter/Decrypt.php
index 2ff7d145a75..844d95b86f7 100644
--- a/lib/zend/Zend/Service/DeveloperGarden/Request/SendSms/SendSMS.php
+++ b/lib/zend/Zend/Filter/Decrypt.php
@@ -13,34 +13,37 @@
* to license@zend.com so we can send you a copy immediately.
*
* @category Zend
- * @package Zend_Service
- * @subpackage DeveloperGarden
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @package Zend_Filter
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
- * @see Zend_Service_DeveloperGarden_Request_SendSms_SendSmsAbstract
+ * @see Zend_Filter_Encrypt
*/
-require_once 'Zend/Service/DeveloperGarden/Request/SendSms/SendSmsAbstract.php';
+require_once 'Zend/Filter/Encrypt.php';
/**
+ * Decrypts a given string
+ *
* @category Zend
- * @package Zend_Service
- * @subpackage DeveloperGarden
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
- * @author Marco Kaiser
+ * @package Zend_Filter
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
-class Zend_Service_DeveloperGarden_Request_SendSms_SendSMS
- extends Zend_Service_DeveloperGarden_Request_SendSms_SendSmsAbstract
+class Zend_Filter_Decrypt extends Zend_Filter_Encrypt
{
/**
- * this is the sms type
- * 1 = normal SMS
+ * Defined by Zend_Filter_Interface
*
- * @var integer
+ * Decrypts the content $value with the defined settings
+ *
+ * @param string $value Content to decrypt
+ * @return string The decrypted content
*/
- protected $_smsType = 1;
+ public function filter($value)
+ {
+ return $this->_adapter->decrypt($value);
+ }
}
diff --git a/lib/zend/Zend/Filter/Digits.php b/lib/zend/Zend/Filter/Digits.php
new file mode 100644
index 00000000000..01c3ed5a733
--- /dev/null
+++ b/lib/zend/Zend/Filter/Digits.php
@@ -0,0 +1,82 @@
+toArray();
+ }
+
+ $this->setAdapter($options);
+ }
+
+ /**
+ * Returns the name of the set adapter
+ *
+ * @return string
+ */
+ public function getAdapter()
+ {
+ return $this->_adapter->toString();
+ }
+
+ /**
+ * Sets new encryption options
+ *
+ * @param string|array $options (Optional) Encryption options
+ * @return Zend_Filter_Encrypt
+ */
+ public function setAdapter($options = null)
+ {
+ if (is_string($options)) {
+ $adapter = $options;
+ } else if (isset($options['adapter'])) {
+ $adapter = $options['adapter'];
+ unset($options['adapter']);
+ } else {
+ $adapter = 'Mcrypt';
+ }
+
+ if (!is_array($options)) {
+ $options = array();
+ }
+
+ if (Zend_Loader::isReadable('Zend/Filter/Encrypt/' . ucfirst($adapter). '.php')) {
+ $adapter = 'Zend_Filter_Encrypt_' . ucfirst($adapter);
+ }
+
+ if (!class_exists($adapter)) {
+ Zend_Loader::loadClass($adapter);
+ }
+
+ $this->_adapter = new $adapter($options);
+ if (!$this->_adapter instanceof Zend_Filter_Encrypt_Interface) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception("Encoding adapter '" . $adapter . "' does not implement Zend_Filter_Encrypt_Interface");
+ }
+
+ return $this;
+ }
+
+ /**
+ * Calls adapter methods
+ *
+ * @param string $method Method to call
+ * @param string|array $options Options for this method
+ */
+ public function __call($method, $options)
+ {
+ $part = substr($method, 0, 3);
+ if ((($part != 'get') and ($part != 'set')) or !method_exists($this->_adapter, $method)) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception("Unknown method '{$method}'");
+ }
+
+ return call_user_func_array(array($this->_adapter, $method), $options);
+ }
+
+ /**
+ * Defined by Zend_Filter_Interface
+ *
+ * Encrypts the content $value with the defined settings
+ *
+ * @param string $value Content to encrypt
+ * @return string The encrypted content
+ */
+ public function filter($value)
+ {
+ return $this->_adapter->encrypt($value);
+ }
+}
diff --git a/lib/zend/Zend/Filter/Encrypt/Interface.php b/lib/zend/Zend/Filter/Encrypt/Interface.php
new file mode 100644
index 00000000000..1510e7ff90f
--- /dev/null
+++ b/lib/zend/Zend/Filter/Encrypt/Interface.php
@@ -0,0 +1,47 @@
+ encryption key string
+ * 'algorithm' => algorithm to use
+ * 'algorithm_directory' => directory where to find the algorithm
+ * 'mode' => encryption mode to use
+ * 'modedirectory' => directory where to find the mode
+ * )
+ */
+ protected $_encryption = array(
+ 'key' => 'ZendFramework',
+ 'algorithm' => 'blowfish',
+ 'algorithm_directory' => '',
+ 'mode' => 'cbc',
+ 'mode_directory' => '',
+ 'vector' => null,
+ 'salt' => false
+ );
+
+ /**
+ * Internal compression
+ *
+ * @var array
+ */
+ protected $_compression;
+
+ protected static $_srandCalled = false;
+
+ /**
+ * Class constructor
+ *
+ * @param string|array|Zend_Config $options Cryption Options
+ */
+ public function __construct($options)
+ {
+ if (!extension_loaded('mcrypt')) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('This filter needs the mcrypt extension');
+ }
+
+ if ($options instanceof Zend_Config) {
+ $options = $options->toArray();
+ } elseif (is_string($options)) {
+ $options = array('key' => $options);
+ } elseif (!is_array($options)) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('Invalid options argument provided to filter');
+ }
+
+ if (array_key_exists('compression', $options)) {
+ $this->setCompression($options['compression']);
+ unset($options['compress']);
+ }
+
+ $this->setEncryption($options);
+ }
+
+ /**
+ * Returns the set encryption options
+ *
+ * @return array
+ */
+ public function getEncryption()
+ {
+ return $this->_encryption;
+ }
+
+ /**
+ * Sets new encryption options
+ *
+ * @param string|array $options Encryption options
+ * @return Zend_Filter_File_Encryption
+ */
+ public function setEncryption($options)
+ {
+ if (is_string($options)) {
+ $options = array('key' => $options);
+ }
+
+ if (!is_array($options)) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('Invalid options argument provided to filter');
+ }
+
+ $options = $options + $this->getEncryption();
+ $algorithms = mcrypt_list_algorithms($options['algorithm_directory']);
+ if (!in_array($options['algorithm'], $algorithms)) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception("The algorithm '{$options['algorithm']}' is not supported");
+ }
+
+ $modes = mcrypt_list_modes($options['mode_directory']);
+ if (!in_array($options['mode'], $modes)) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception("The mode '{$options['mode']}' is not supported");
+ }
+
+ if (!mcrypt_module_self_test($options['algorithm'], $options['algorithm_directory'])) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('The given algorithm can not be used due an internal mcrypt problem');
+ }
+
+ if (!isset($options['vector'])) {
+ $options['vector'] = null;
+ }
+
+ $this->_encryption = $options;
+ $this->setVector($options['vector']);
+
+ return $this;
+ }
+
+ /**
+ * Returns the set vector
+ *
+ * @return string
+ */
+ public function getVector()
+ {
+ return $this->_encryption['vector'];
+ }
+
+ /**
+ * Sets the initialization vector
+ *
+ * @param string $vector (Optional) Vector to set
+ * @return Zend_Filter_Encrypt_Mcrypt
+ */
+ public function setVector($vector = null)
+ {
+ $cipher = $this->_openCipher();
+ $size = mcrypt_enc_get_iv_size($cipher);
+ if (empty($vector)) {
+ $this->_srand();
+ if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' && version_compare(PHP_VERSION, '5.3.0', '<')) {
+ $method = MCRYPT_RAND;
+ } else {
+ if (file_exists('/dev/urandom') || (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN')) {
+ $method = MCRYPT_DEV_URANDOM;
+ } elseif (file_exists('/dev/random')) {
+ $method = MCRYPT_DEV_RANDOM;
+ } else {
+ $method = MCRYPT_RAND;
+ }
+ }
+ $vector = mcrypt_create_iv($size, $method);
+ } else if (strlen($vector) != $size) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('The given vector has a wrong size for the set algorithm');
+ }
+
+ $this->_encryption['vector'] = $vector;
+ $this->_closeCipher($cipher);
+
+ return $this;
+ }
+
+ /**
+ * Returns the compression
+ *
+ * @return array
+ */
+ public function getCompression()
+ {
+ return $this->_compression;
+ }
+
+ /**
+ * Sets a internal compression for values to encrypt
+ *
+ * @param string|array $compression
+ * @return Zend_Filter_Encrypt_Mcrypt
+ */
+ public function setCompression($compression)
+ {
+ if (is_string($this->_compression)) {
+ $compression = array('adapter' => $compression);
+ }
+
+ $this->_compression = $compression;
+ return $this;
+ }
+
+ /**
+ * Defined by Zend_Filter_Interface
+ *
+ * Encrypts $value with the defined settings
+ *
+ * @param string $value The content to encrypt
+ * @return string The encrypted content
+ */
+ public function encrypt($value)
+ {
+ // compress prior to encryption
+ if (!empty($this->_compression)) {
+ require_once 'Zend/Filter/Compress.php';
+ $compress = new Zend_Filter_Compress($this->_compression);
+ $value = $compress->filter($value);
+ }
+
+ $cipher = $this->_openCipher();
+ $this->_initCipher($cipher);
+ $encrypted = mcrypt_generic($cipher, $value);
+ mcrypt_generic_deinit($cipher);
+ $this->_closeCipher($cipher);
+
+ return $encrypted;
+ }
+
+ /**
+ * Defined by Zend_Filter_Interface
+ *
+ * Decrypts $value with the defined settings
+ *
+ * @param string $value Content to decrypt
+ * @return string The decrypted content
+ */
+ public function decrypt($value)
+ {
+ $cipher = $this->_openCipher();
+ $this->_initCipher($cipher);
+ $decrypted = mdecrypt_generic($cipher, $value);
+ mcrypt_generic_deinit($cipher);
+ $this->_closeCipher($cipher);
+
+ // decompress after decryption
+ if (!empty($this->_compression)) {
+ require_once 'Zend/Filter/Decompress.php';
+ $decompress = new Zend_Filter_Decompress($this->_compression);
+ $decrypted = $decompress->filter($decrypted);
+ }
+
+ return $decrypted;
+ }
+
+ /**
+ * Returns the adapter name
+ *
+ * @return string
+ */
+ public function toString()
+ {
+ return 'Mcrypt';
+ }
+
+ /**
+ * Open a cipher
+ *
+ * @throws Zend_Filter_Exception When the cipher can not be opened
+ * @return resource Returns the opened cipher
+ */
+ protected function _openCipher()
+ {
+ $cipher = mcrypt_module_open(
+ $this->_encryption['algorithm'],
+ $this->_encryption['algorithm_directory'],
+ $this->_encryption['mode'],
+ $this->_encryption['mode_directory']);
+
+ if ($cipher === false) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('Mcrypt can not be opened with your settings');
+ }
+
+ return $cipher;
+ }
+
+ /**
+ * Close a cipher
+ *
+ * @param resource $cipher Cipher to close
+ * @return Zend_Filter_Encrypt_Mcrypt
+ */
+ protected function _closeCipher($cipher)
+ {
+ mcrypt_module_close($cipher);
+
+ return $this;
+ }
+
+ /**
+ * Initialises the cipher with the set key
+ *
+ * @param resource $cipher
+ * @throws
+ * @return resource
+ */
+ protected function _initCipher($cipher)
+ {
+ $key = $this->_encryption['key'];
+
+ $keysizes = mcrypt_enc_get_supported_key_sizes($cipher);
+ if (empty($keysizes) || ($this->_encryption['salt'] == true)) {
+ $this->_srand();
+ $keysize = mcrypt_enc_get_key_size($cipher);
+ $key = substr(md5($key), 0, $keysize);
+ } else if (!in_array(strlen($key), $keysizes)) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('The given key has a wrong size for the set algorithm');
+ }
+
+ $result = mcrypt_generic_init($cipher, $key, $this->_encryption['vector']);
+ if ($result < 0) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('Mcrypt could not be initialize with the given setting');
+ }
+
+ return $this;
+ }
+
+ /**
+ * _srand() interception
+ *
+ * @see ZF-8742
+ */
+ protected function _srand()
+ {
+ if (version_compare(PHP_VERSION, '5.3.0', '>=')) {
+ return;
+ }
+
+ if (!self::$_srandCalled) {
+ srand((double) microtime() * 1000000);
+ self::$_srandCalled = true;
+ }
+ }
+}
diff --git a/lib/zend/Zend/Filter/Encrypt/Openssl.php b/lib/zend/Zend/Filter/Encrypt/Openssl.php
new file mode 100644
index 00000000000..7d1f70bd0ae
--- /dev/null
+++ b/lib/zend/Zend/Filter/Encrypt/Openssl.php
@@ -0,0 +1,492 @@
+ public keys
+ * 'private' => private keys
+ * 'envelope' => resulting envelope keys
+ * )
+ */
+ protected $_keys = array(
+ 'public' => array(),
+ 'private' => array(),
+ 'envelope' => array()
+ );
+
+ /**
+ * Internal passphrase
+ *
+ * @var string
+ */
+ protected $_passphrase;
+
+ /**
+ * Internal compression
+ *
+ * @var array
+ */
+ protected $_compression;
+
+ /**
+ * Internal create package
+ *
+ * @var boolean
+ */
+ protected $_package = false;
+
+ /**
+ * Class constructor
+ * Available options
+ * 'public' => public key
+ * 'private' => private key
+ * 'envelope' => envelope key
+ * 'passphrase' => passphrase
+ * 'compression' => compress value with this compression adapter
+ * 'package' => pack envelope keys into encrypted string, simplifies decryption
+ *
+ * @param string|array $options Options for this adapter
+ */
+ public function __construct($options = array())
+ {
+ if (!extension_loaded('openssl')) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('This filter needs the openssl extension');
+ }
+
+ if ($options instanceof Zend_Config) {
+ $options = $options->toArray();
+ }
+
+ if (!is_array($options)) {
+ $options = array('public' => $options);
+ }
+
+ if (array_key_exists('passphrase', $options)) {
+ $this->setPassphrase($options['passphrase']);
+ unset($options['passphrase']);
+ }
+
+ if (array_key_exists('compression', $options)) {
+ $this->setCompression($options['compression']);
+ unset($options['compress']);
+ }
+
+ if (array_key_exists('package', $options)) {
+ $this->setPackage($options['package']);
+ unset($options['package']);
+ }
+
+ $this->_setKeys($options);
+ }
+
+ /**
+ * Sets the encryption keys
+ *
+ * @param string|array $keys Key with type association
+ * @return Zend_Filter_Encrypt_Openssl
+ */
+ protected function _setKeys($keys)
+ {
+ if (!is_array($keys)) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('Invalid options argument provided to filter');
+ }
+
+ foreach ($keys as $type => $key) {
+ if (ctype_print($key) && is_file(realpath($key)) && is_readable($key)) {
+ $file = fopen($key, 'r');
+ $cert = fread($file, 8192);
+ fclose($file);
+ } else {
+ $cert = $key;
+ $key = count($this->_keys[$type]);
+ }
+
+ switch ($type) {
+ case 'public':
+ $test = openssl_pkey_get_public($cert);
+ if ($test === false) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception("Public key '{$cert}' not valid");
+ }
+
+ openssl_free_key($test);
+ $this->_keys['public'][$key] = $cert;
+ break;
+ case 'private':
+ $test = openssl_pkey_get_private($cert, $this->_passphrase);
+ if ($test === false) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception("Private key '{$cert}' not valid");
+ }
+
+ openssl_free_key($test);
+ $this->_keys['private'][$key] = $cert;
+ break;
+ case 'envelope':
+ $this->_keys['envelope'][$key] = $cert;
+ break;
+ default:
+ break;
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Returns all public keys
+ *
+ * @return array
+ */
+ public function getPublicKey()
+ {
+ $key = $this->_keys['public'];
+ return $key;
+ }
+
+ /**
+ * Sets public keys
+ *
+ * @param string|array $key Public keys
+ * @return Zend_Filter_Encrypt_Openssl
+ */
+ public function setPublicKey($key)
+ {
+ if (is_array($key)) {
+ foreach($key as $type => $option) {
+ if ($type !== 'public') {
+ $key['public'] = $option;
+ unset($key[$type]);
+ }
+ }
+ } else {
+ $key = array('public' => $key);
+ }
+
+ return $this->_setKeys($key);
+ }
+
+ /**
+ * Returns all private keys
+ *
+ * @return array
+ */
+ public function getPrivateKey()
+ {
+ $key = $this->_keys['private'];
+ return $key;
+ }
+
+ /**
+ * Sets private keys
+ *
+ * @param string $key Private key
+ * @param string $passphrase
+ * @return Zend_Filter_Encrypt_Openssl
+ */
+ public function setPrivateKey($key, $passphrase = null)
+ {
+ if (is_array($key)) {
+ foreach($key as $type => $option) {
+ if ($type !== 'private') {
+ $key['private'] = $option;
+ unset($key[$type]);
+ }
+ }
+ } else {
+ $key = array('private' => $key);
+ }
+
+ if ($passphrase !== null) {
+ $this->setPassphrase($passphrase);
+ }
+
+ return $this->_setKeys($key);
+ }
+
+ /**
+ * Returns all envelope keys
+ *
+ * @return array
+ */
+ public function getEnvelopeKey()
+ {
+ $key = $this->_keys['envelope'];
+ return $key;
+ }
+
+ /**
+ * Sets envelope keys
+ *
+ * @param string|array $options Envelope keys
+ * @return Zend_Filter_Encrypt_Openssl
+ */
+ public function setEnvelopeKey($key)
+ {
+ if (is_array($key)) {
+ foreach($key as $type => $option) {
+ if ($type !== 'envelope') {
+ $key['envelope'] = $option;
+ unset($key[$type]);
+ }
+ }
+ } else {
+ $key = array('envelope' => $key);
+ }
+
+ return $this->_setKeys($key);
+ }
+
+ /**
+ * Returns the passphrase
+ *
+ * @return string
+ */
+ public function getPassphrase()
+ {
+ return $this->_passphrase;
+ }
+
+ /**
+ * Sets a new passphrase
+ *
+ * @param string $passphrase
+ * @return Zend_Filter_Encrypt_Openssl
+ */
+ public function setPassphrase($passphrase)
+ {
+ $this->_passphrase = $passphrase;
+ return $this;
+ }
+
+ /**
+ * Returns the compression
+ *
+ * @return array
+ */
+ public function getCompression()
+ {
+ return $this->_compression;
+ }
+
+ /**
+ * Sets a internal compression for values to encrypt
+ *
+ * @param string|array $compression
+ * @return Zend_Filter_Encrypt_Openssl
+ */
+ public function setCompression($compression)
+ {
+ if (is_string($this->_compression)) {
+ $compression = array('adapter' => $compression);
+ }
+
+ $this->_compression = $compression;
+ return $this;
+ }
+
+ /**
+ * Returns if header should be packaged
+ *
+ * @return boolean
+ */
+ public function getPackage()
+ {
+ return $this->_package;
+ }
+
+ /**
+ * Sets if the envelope keys should be included in the encrypted value
+ *
+ * @param boolean $package
+ * @return Zend_Filter_Encrypt_Openssl
+ */
+ public function setPackage($package)
+ {
+ $this->_package = (boolean) $package;
+ return $this;
+ }
+
+ /**
+ * Encrypts $value with the defined settings
+ * Note that you also need the "encrypted" keys to be able to decrypt
+ *
+ * @param string $value Content to encrypt
+ * @return string The encrypted content
+ * @throws Zend_Filter_Exception
+ */
+ public function encrypt($value)
+ {
+ $encrypted = array();
+ $encryptedkeys = array();
+
+ if (count($this->_keys['public']) == 0) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('Openssl can not encrypt without public keys');
+ }
+
+ $keys = array();
+ $fingerprints = array();
+ $count = -1;
+ foreach($this->_keys['public'] as $key => $cert) {
+ $keys[$key] = openssl_pkey_get_public($cert);
+ if ($this->_package) {
+ $details = openssl_pkey_get_details($keys[$key]);
+ if ($details === false) {
+ $details = array('key' => 'ZendFramework');
+ }
+
+ ++$count;
+ $fingerprints[$count] = md5($details['key']);
+ }
+ }
+
+ // compress prior to encryption
+ if (!empty($this->_compression)) {
+ require_once 'Zend/Filter/Compress.php';
+ $compress = new Zend_Filter_Compress($this->_compression);
+ $value = $compress->filter($value);
+ }
+
+ $crypt = openssl_seal($value, $encrypted, $encryptedkeys, $keys);
+ foreach ($keys as $key) {
+ openssl_free_key($key);
+ }
+
+ if ($crypt === false) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('Openssl was not able to encrypt your content with the given options');
+ }
+
+ $this->_keys['envelope'] = $encryptedkeys;
+
+ // Pack data and envelope keys into single string
+ if ($this->_package) {
+ $header = pack('n', count($this->_keys['envelope']));
+ foreach($this->_keys['envelope'] as $key => $envKey) {
+ $header .= pack('H32n', $fingerprints[$key], strlen($envKey)) . $envKey;
+ }
+
+ $encrypted = $header . $encrypted;
+ }
+
+ return $encrypted;
+ }
+
+ /**
+ * Defined by Zend_Filter_Interface
+ *
+ * Decrypts $value with the defined settings
+ *
+ * @param string $value Content to decrypt
+ * @return string The decrypted content
+ * @throws Zend_Filter_Exception
+ */
+ public function decrypt($value)
+ {
+ $decrypted = "";
+ $envelope = current($this->getEnvelopeKey());
+
+ if (count($this->_keys['private']) !== 1) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('Please give a private key for decryption with Openssl');
+ }
+
+ if (!$this->_package && empty($envelope)) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('Please give a envelope key for decryption with Openssl');
+ }
+
+ foreach($this->_keys['private'] as $key => $cert) {
+ $keys = openssl_pkey_get_private($cert, $this->getPassphrase());
+ }
+
+ if ($this->_package) {
+ $details = openssl_pkey_get_details($keys);
+ if ($details !== false) {
+ $fingerprint = md5($details['key']);
+ } else {
+ $fingerprint = md5("ZendFramework");
+ }
+
+ $count = unpack('ncount', $value);
+ $count = $count['count'];
+ $length = 2;
+ for($i = $count; $i > 0; --$i) {
+ $header = unpack('H32print/nsize', substr($value, $length, 18));
+ $length += 18;
+ if ($header['print'] == $fingerprint) {
+ $envelope = substr($value, $length, $header['size']);
+ }
+
+ $length += $header['size'];
+ }
+
+ // remainder of string is the value to decrypt
+ $value = substr($value, $length);
+ }
+
+ $crypt = openssl_open($value, $decrypted, $envelope, $keys);
+ openssl_free_key($keys);
+
+ if ($crypt === false) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('Openssl was not able to decrypt you content with the given options');
+ }
+
+ // decompress after decryption
+ if (!empty($this->_compression)) {
+ require_once 'Zend/Filter/Decompress.php';
+ $decompress = new Zend_Filter_Decompress($this->_compression);
+ $decrypted = $decompress->filter($decrypted);
+ }
+
+ return $decrypted;
+ }
+
+ /**
+ * Returns the adapter name
+ *
+ * @return string
+ */
+ public function toString()
+ {
+ return 'Openssl';
+ }
+}
diff --git a/lib/zend/Zend/Filter/Exception.php b/lib/zend/Zend/Filter/Exception.php
new file mode 100644
index 00000000000..5763b2456ec
--- /dev/null
+++ b/lib/zend/Zend/Filter/Exception.php
@@ -0,0 +1,37 @@
+_filename;
+ }
+
+ /**
+ * Sets the new filename where the content will be stored
+ *
+ * @param string $filename (Optional) New filename to set
+ * @return Zend_Filter_File_Encryt
+ */
+ public function setFilename($filename = null)
+ {
+ $this->_filename = $filename;
+ return $this;
+ }
+
+ /**
+ * Defined by Zend_Filter_Interface
+ *
+ * Decrypts the file $value with the defined settings
+ *
+ * @param string $value Full path of file to change
+ * @return string The filename which has been set, or false when there were errors
+ */
+ public function filter($value)
+ {
+ if (!file_exists($value)) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception("File '$value' not found");
+ }
+
+ if (!isset($this->_filename)) {
+ $this->_filename = $value;
+ }
+
+ if (file_exists($this->_filename) and !is_writable($this->_filename)) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception("File '{$this->_filename}' is not writable");
+ }
+
+ $content = file_get_contents($value);
+ if (!$content) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception("Problem while reading file '$value'");
+ }
+
+ $decrypted = parent::filter($content);
+ $result = file_put_contents($this->_filename, $decrypted);
+
+ if (!$result) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception("Problem while writing file '{$this->_filename}'");
+ }
+
+ return $this->_filename;
+ }
+}
diff --git a/lib/zend/Zend/Filter/File/Encrypt.php b/lib/zend/Zend/Filter/File/Encrypt.php
new file mode 100644
index 00000000000..23c71b4b0aa
--- /dev/null
+++ b/lib/zend/Zend/Filter/File/Encrypt.php
@@ -0,0 +1,106 @@
+_filename;
+ }
+
+ /**
+ * Sets the new filename where the content will be stored
+ *
+ * @param string $filename (Optional) New filename to set
+ * @return Zend_Filter_File_Encryt
+ */
+ public function setFilename($filename = null)
+ {
+ $this->_filename = $filename;
+ return $this;
+ }
+
+ /**
+ * Defined by Zend_Filter_Interface
+ *
+ * Encrypts the file $value with the defined settings
+ *
+ * @param string $value Full path of file to change
+ * @return string The filename which has been set, or false when there were errors
+ */
+ public function filter($value)
+ {
+ if (!file_exists($value)) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception("File '$value' not found");
+ }
+
+ if (!isset($this->_filename)) {
+ $this->_filename = $value;
+ }
+
+ if (file_exists($this->_filename) and !is_writable($this->_filename)) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception("File '{$this->_filename}' is not writable");
+ }
+
+ $content = file_get_contents($value);
+ if (!$content) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception("Problem while reading file '$value'");
+ }
+
+ $encrypted = parent::filter($content);
+ $result = file_put_contents($this->_filename, $encrypted);
+
+ if (!$result) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception("Problem while writing file '{$this->_filename}'");
+ }
+
+ return $this->_filename;
+ }
+}
diff --git a/lib/zend/Zend/Filter/File/LowerCase.php b/lib/zend/Zend/Filter/File/LowerCase.php
new file mode 100644
index 00000000000..dd34321dea7
--- /dev/null
+++ b/lib/zend/Zend/Filter/File/LowerCase.php
@@ -0,0 +1,84 @@
+setEncoding($options);
+ }
+ }
+
+ /**
+ * Defined by Zend_Filter_Interface
+ *
+ * Does a lowercase on the content of the given file
+ *
+ * @param string $value Full path of file to change
+ * @return string The given $value
+ * @throws Zend_Filter_Exception
+ */
+ public function filter($value)
+ {
+ if (!file_exists($value)) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception("File '$value' not found");
+ }
+
+ if (!is_writable($value)) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception("File '$value' is not writable");
+ }
+
+ $content = file_get_contents($value);
+ if (!$content) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception("Problem while reading file '$value'");
+ }
+
+ $content = parent::filter($content);
+ $result = file_put_contents($value, $content);
+
+ if (!$result) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception("Problem while writing file '$value'");
+ }
+
+ return $value;
+ }
+}
diff --git a/lib/zend/Zend/Filter/File/Rename.php b/lib/zend/Zend/Filter/File/Rename.php
new file mode 100644
index 00000000000..b70acbe301f
--- /dev/null
+++ b/lib/zend/Zend/Filter/File/Rename.php
@@ -0,0 +1,309 @@
+ Source filename or directory which will be renamed
+ * 'target' => Target filename or directory, the new name of the sourcefile
+ * 'overwrite' => Shall existing files be overwritten ?
+ *
+ * @param string|array $options Target file or directory to be renamed
+ * @param string $target Source filename or directory (deprecated)
+ * @param bool $overwrite Should existing files be overwritten (deprecated)
+ * @return void
+ */
+ public function __construct($options)
+ {
+ if ($options instanceof Zend_Config) {
+ $options = $options->toArray();
+ } elseif (is_string($options)) {
+ $options = array('target' => $options);
+ } elseif (!is_array($options)) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('Invalid options argument provided to filter');
+ }
+
+ if (1 < func_num_args()) {
+ $argv = func_get_args();
+ array_shift($argv);
+ $source = array_shift($argv);
+ $overwrite = false;
+ if (!empty($argv)) {
+ $overwrite = array_shift($argv);
+ }
+ $options['source'] = $source;
+ $options['overwrite'] = $overwrite;
+ }
+
+ $this->setFile($options);
+ }
+
+ /**
+ * Returns the files to rename and their new name and location
+ *
+ * @return array
+ */
+ public function getFile()
+ {
+ return $this->_files;
+ }
+
+ /**
+ * Sets a new file or directory as target, deleting existing ones
+ *
+ * Array accepts the following keys:
+ * 'source' => Source filename or directory which will be renamed
+ * 'target' => Target filename or directory, the new name of the sourcefile
+ * 'overwrite' => Shall existing files be overwritten ?
+ *
+ * @param string|array $options Old file or directory to be rewritten
+ * @return Zend_Filter_File_Rename
+ */
+ public function setFile($options)
+ {
+ $this->_files = array();
+ $this->addFile($options);
+
+ return $this;
+ }
+
+ /**
+ * Adds a new file or directory as target to the existing ones
+ *
+ * Array accepts the following keys:
+ * 'source' => Source filename or directory which will be renamed
+ * 'target' => Target filename or directory, the new name of the sourcefile
+ * 'overwrite' => Shall existing files be overwritten ?
+ *
+ * @param string|array $options Old file or directory to be rewritten
+ * @return Zend_Filter_File_Rename
+ */
+ public function addFile($options)
+ {
+ if (is_string($options)) {
+ $options = array('target' => $options);
+ } elseif (!is_array($options)) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception ('Invalid options to rename filter provided');
+ }
+
+ $this->_convertOptions($options);
+
+ return $this;
+ }
+
+ /**
+ * Returns only the new filename without moving it
+ * But existing files will be erased when the overwrite option is true
+ *
+ * @param string $value Full path of file to change
+ * @param boolean $source Return internal informations
+ * @return string The new filename which has been set
+ */
+ public function getNewName($value, $source = false)
+ {
+ $file = $this->_getFileName($value);
+
+ if (!is_array($file) || !array_key_exists('source', $file) || !array_key_exists('target', $file)) {
+ return $value;
+ }
+
+ if ($file['source'] == $file['target']) {
+ return $value;
+ }
+
+ if (!file_exists($file['source'])) {
+ return $value;
+ }
+
+ if (($file['overwrite'] == true) && (file_exists($file['target']))) {
+ unlink($file['target']);
+ }
+
+ if (file_exists($file['target'])) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception(sprintf("File '%s' could not be renamed. It already exists.", $value));
+ }
+
+ if ($source) {
+ return $file;
+ }
+
+ return $file['target'];
+ }
+
+ /**
+ * Defined by Zend_Filter_Interface
+ *
+ * Renames the file $value to the new name set before
+ * Returns the file $value, removing all but digit characters
+ *
+ * @param string $value Full path of file to change
+ * @throws Zend_Filter_Exception
+ * @return string The new filename which has been set, or false when there were errors
+ */
+ public function filter($value)
+ {
+ $file = $this->getNewName($value, true);
+ if (is_string($file)) {
+ return $file;
+ }
+
+ $result = rename($file['source'], $file['target']);
+
+ if ($result === true) {
+ return $file['target'];
+ }
+
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception(sprintf("File '%s' could not be renamed. An error occured while processing the file.", $value));
+ }
+
+ /**
+ * Internal method for creating the file array
+ * Supports single and nested arrays
+ *
+ * @param array $options
+ * @return array
+ */
+ protected function _convertOptions($options) {
+ $files = array();
+ foreach ($options as $key => $value) {
+ if (is_array($value)) {
+ $this->_convertOptions($value);
+ continue;
+ }
+
+ switch ($key) {
+ case "source":
+ $files['source'] = (string) $value;
+ break;
+
+ case 'target' :
+ $files['target'] = (string) $value;
+ break;
+
+ case 'overwrite' :
+ $files['overwrite'] = (boolean) $value;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (empty($files)) {
+ return $this;
+ }
+
+ if (empty($files['source'])) {
+ $files['source'] = '*';
+ }
+
+ if (empty($files['target'])) {
+ $files['target'] = '*';
+ }
+
+ if (empty($files['overwrite'])) {
+ $files['overwrite'] = false;
+ }
+
+ $found = false;
+ foreach ($this->_files as $key => $value) {
+ if ($value['source'] == $files['source']) {
+ $this->_files[$key] = $files;
+ $found = true;
+ }
+ }
+
+ if (!$found) {
+ $count = count($this->_files);
+ $this->_files[$count] = $files;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Internal method to resolve the requested source
+ * and return all other related parameters
+ *
+ * @param string $file Filename to get the informations for
+ * @return array
+ */
+ protected function _getFileName($file)
+ {
+ $rename = array();
+ foreach ($this->_files as $value) {
+ if ($value['source'] == '*') {
+ if (!isset($rename['source'])) {
+ $rename = $value;
+ $rename['source'] = $file;
+ }
+ }
+
+ if ($value['source'] == $file) {
+ $rename = $value;
+ }
+ }
+
+ if (!isset($rename['source'])) {
+ return $file;
+ }
+
+ if (!isset($rename['target']) or ($rename['target'] == '*')) {
+ $rename['target'] = $rename['source'];
+ }
+
+ if (is_dir($rename['target'])) {
+ $name = basename($rename['source']);
+ $last = $rename['target'][strlen($rename['target']) - 1];
+ if (($last != '/') and ($last != '\\')) {
+ $rename['target'] .= DIRECTORY_SEPARATOR;
+ }
+
+ $rename['target'] .= $name;
+ }
+
+ return $rename;
+ }
+}
diff --git a/lib/zend/Zend/Filter/File/UpperCase.php b/lib/zend/Zend/Filter/File/UpperCase.php
new file mode 100644
index 00000000000..e65453e0fdb
--- /dev/null
+++ b/lib/zend/Zend/Filter/File/UpperCase.php
@@ -0,0 +1,84 @@
+setEncoding($options);
+ }
+ }
+
+ /**
+ * Defined by Zend_Filter_Interface
+ *
+ * Does a lowercase on the content of the given file
+ *
+ * @param string $value Full path of file to change
+ * @return string The given $value
+ * @throws Zend_Filter_Exception
+ */
+ public function filter($value)
+ {
+ if (!file_exists($value)) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception("File '$value' not found");
+ }
+
+ if (!is_writable($value)) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception("File '$value' is not writable");
+ }
+
+ $content = file_get_contents($value);
+ if (!$content) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception("Problem while reading file '$value'");
+ }
+
+ $content = parent::filter($content);
+ $result = file_put_contents($value, $content);
+
+ if (!$result) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception("Problem while writing file '$value'");
+ }
+
+ return $value;
+ }
+}
diff --git a/lib/zend/Zend/Filter/HtmlEntities.php b/lib/zend/Zend/Filter/HtmlEntities.php
new file mode 100644
index 00000000000..0c1dfecb956
--- /dev/null
+++ b/lib/zend/Zend/Filter/HtmlEntities.php
@@ -0,0 +1,216 @@
+toArray();
+ } else if (!is_array($options)) {
+ $options = func_get_args();
+ $temp['quotestyle'] = array_shift($options);
+ if (!empty($options)) {
+ $temp['charset'] = array_shift($options);
+ }
+
+ $options = $temp;
+ }
+
+ if (!isset($options['quotestyle'])) {
+ $options['quotestyle'] = ENT_COMPAT;
+ }
+
+ if (!isset($options['encoding'])) {
+ $options['encoding'] = 'UTF-8';
+ }
+ if (isset($options['charset'])) {
+ $options['encoding'] = $options['charset'];
+ }
+
+ if (!isset($options['doublequote'])) {
+ $options['doublequote'] = true;
+ }
+
+ $this->setQuoteStyle($options['quotestyle']);
+ $this->setEncoding($options['encoding']);
+ $this->setDoubleQuote($options['doublequote']);
+ }
+
+ /**
+ * Returns the quoteStyle option
+ *
+ * @return integer
+ */
+ public function getQuoteStyle()
+ {
+ return $this->_quoteStyle;
+ }
+
+ /**
+ * Sets the quoteStyle option
+ *
+ * @param integer $quoteStyle
+ * @return Zend_Filter_HtmlEntities Provides a fluent interface
+ */
+ public function setQuoteStyle($quoteStyle)
+ {
+ $this->_quoteStyle = $quoteStyle;
+ return $this;
+ }
+
+
+ /**
+ * Get encoding
+ *
+ * @return string
+ */
+ public function getEncoding()
+ {
+ return $this->_encoding;
+ }
+
+ /**
+ * Set encoding
+ *
+ * @param string $value
+ * @return Zend_Filter_HtmlEntities
+ */
+ public function setEncoding($value)
+ {
+ $this->_encoding = (string) $value;
+ return $this;
+ }
+
+ /**
+ * Returns the charSet option
+ *
+ * Proxies to {@link getEncoding()}
+ *
+ * @return string
+ */
+ public function getCharSet()
+ {
+ return $this->getEncoding();
+ }
+
+ /**
+ * Sets the charSet option
+ *
+ * Proxies to {@link setEncoding()}
+ *
+ * @param string $charSet
+ * @return Zend_Filter_HtmlEntities Provides a fluent interface
+ */
+ public function setCharSet($charSet)
+ {
+ return $this->setEncoding($charSet);
+ }
+
+ /**
+ * Returns the doubleQuote option
+ *
+ * @return boolean
+ */
+ public function getDoubleQuote()
+ {
+ return $this->_doubleQuote;
+ }
+
+ /**
+ * Sets the doubleQuote option
+ *
+ * @param boolean $doubleQuote
+ * @return Zend_Filter_HtmlEntities Provides a fluent interface
+ */
+ public function setDoubleQuote($doubleQuote)
+ {
+ $this->_doubleQuote = (boolean) $doubleQuote;
+ return $this;
+ }
+
+ /**
+ * Defined by Zend_Filter_Interface
+ *
+ * Returns the string $value, converting characters to their corresponding HTML entity
+ * equivalents where they exist
+ *
+ * @param string $value
+ * @return string
+ */
+ public function filter($value)
+ {
+ $filtered = htmlentities((string) $value, $this->getQuoteStyle(), $this->getEncoding(), $this->getDoubleQuote());
+ if (strlen((string) $value) && !strlen($filtered)) {
+ if (!function_exists('iconv')) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('Encoding mismatch has resulted in htmlentities errors');
+ }
+ $enc = $this->getEncoding();
+ $value = iconv('', $enc . '//IGNORE', (string) $value);
+ $filtered = htmlentities($value, $this->getQuoteStyle(), $enc, $this->getDoubleQuote());
+ if (!strlen($filtered)) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('Encoding mismatch has resulted in htmlentities errors');
+ }
+ }
+ return $filtered;
+ }
+}
diff --git a/lib/zend/Zend/Filter/Inflector.php b/lib/zend/Zend/Filter/Inflector.php
new file mode 100644
index 00000000000..00eea7d64b2
--- /dev/null
+++ b/lib/zend/Zend/Filter/Inflector.php
@@ -0,0 +1,527 @@
+toArray();
+ } else if (!is_array($options)) {
+ $options = func_get_args();
+ $temp = array();
+
+ if (!empty($options)) {
+ $temp['target'] = array_shift($options);
+ }
+
+ if (!empty($options)) {
+ $temp['rules'] = array_shift($options);
+ }
+
+ if (!empty($options)) {
+ $temp['throwTargetExceptionsOn'] = array_shift($options);
+ }
+
+ if (!empty($options)) {
+ $temp['targetReplacementIdentifier'] = array_shift($options);
+ }
+
+ $options = $temp;
+ }
+
+ $this->setOptions($options);
+ }
+
+ /**
+ * Retreive PluginLoader
+ *
+ * @return Zend_Loader_PluginLoader_Interface
+ */
+ public function getPluginLoader()
+ {
+ if (!$this->_pluginLoader instanceof Zend_Loader_PluginLoader_Interface) {
+ $this->_pluginLoader = new Zend_Loader_PluginLoader(array('Zend_Filter_' => 'Zend/Filter/'), __CLASS__);
+ }
+
+ return $this->_pluginLoader;
+ }
+
+ /**
+ * Set PluginLoader
+ *
+ * @param Zend_Loader_PluginLoader_Interface $pluginLoader
+ * @return Zend_Filter_Inflector
+ */
+ public function setPluginLoader(Zend_Loader_PluginLoader_Interface $pluginLoader)
+ {
+ $this->_pluginLoader = $pluginLoader;
+ return $this;
+ }
+
+ /**
+ * Use Zend_Config object to set object state
+ *
+ * @deprecated Use setOptions() instead
+ * @param Zend_Config $config
+ * @return Zend_Filter_Inflector
+ */
+ public function setConfig(Zend_Config $config)
+ {
+ return $this->setOptions($config);
+ }
+
+ /**
+ * Set options
+ *
+ * @param array $options
+ * @return Zend_Filter_Inflector
+ */
+ public function setOptions($options) {
+ if ($options instanceof Zend_Config) {
+ $options = $options->toArray();
+ }
+
+ // Set Präfix Path
+ if (array_key_exists('filterPrefixPath', $options)) {
+ if (!is_scalar($options['filterPrefixPath'])) {
+ foreach ($options['filterPrefixPath'] as $prefix => $path) {
+ $this->addFilterPrefixPath($prefix, $path);
+ }
+ }
+ }
+
+ if (array_key_exists('throwTargetExceptionsOn', $options)) {
+ $this->setThrowTargetExceptionsOn($options['throwTargetExceptionsOn']);
+ }
+
+ if (array_key_exists('targetReplacementIdentifier', $options)) {
+ $this->setTargetReplacementIdentifier($options['targetReplacementIdentifier']);
+ }
+
+ if (array_key_exists('target', $options)) {
+ $this->setTarget($options['target']);
+ }
+
+ if (array_key_exists('rules', $options)) {
+ $this->addRules($options['rules']);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Convienence method to add prefix and path to PluginLoader
+ *
+ * @param string $prefix
+ * @param string $path
+ * @return Zend_Filter_Inflector
+ */
+ public function addFilterPrefixPath($prefix, $path)
+ {
+ $this->getPluginLoader()->addPrefixPath($prefix, $path);
+ return $this;
+ }
+
+ /**
+ * Set Whether or not the inflector should throw an exception when a replacement
+ * identifier is still found within an inflected target.
+ *
+ * @param bool $throwTargetExceptions
+ * @return Zend_Filter_Inflector
+ */
+ public function setThrowTargetExceptionsOn($throwTargetExceptionsOn)
+ {
+ $this->_throwTargetExceptionsOn = ($throwTargetExceptionsOn == true) ? true : false;
+ return $this;
+ }
+
+ /**
+ * Will exceptions be thrown?
+ *
+ * @return bool
+ */
+ public function isThrowTargetExceptionsOn()
+ {
+ return $this->_throwTargetExceptionsOn;
+ }
+
+ /**
+ * Set the Target Replacement Identifier, by default ':'
+ *
+ * @param string $targetReplacementIdentifier
+ * @return Zend_Filter_Inflector
+ */
+ public function setTargetReplacementIdentifier($targetReplacementIdentifier)
+ {
+ if ($targetReplacementIdentifier) {
+ $this->_targetReplacementIdentifier = (string) $targetReplacementIdentifier;
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get Target Replacement Identifier
+ *
+ * @return string
+ */
+ public function getTargetReplacementIdentifier()
+ {
+ return $this->_targetReplacementIdentifier;
+ }
+
+ /**
+ * Set a Target
+ * ex: 'scripts/:controller/:action.:suffix'
+ *
+ * @param string
+ * @return Zend_Filter_Inflector
+ */
+ public function setTarget($target)
+ {
+ $this->_target = (string) $target;
+ return $this;
+ }
+
+ /**
+ * Retrieve target
+ *
+ * @return string
+ */
+ public function getTarget()
+ {
+ return $this->_target;
+ }
+
+ /**
+ * Set Target Reference
+ *
+ * @param reference $target
+ * @return Zend_Filter_Inflector
+ */
+ public function setTargetReference(&$target)
+ {
+ $this->_target =& $target;
+ return $this;
+ }
+
+ /**
+ * SetRules() is the same as calling addRules() with the exception that it
+ * clears the rules before adding them.
+ *
+ * @param array $rules
+ * @return Zend_Filter_Inflector
+ */
+ public function setRules(Array $rules)
+ {
+ $this->clearRules();
+ $this->addRules($rules);
+ return $this;
+ }
+
+ /**
+ * AddRules(): multi-call to setting filter rules.
+ *
+ * If prefixed with a ":" (colon), a filter rule will be added. If not
+ * prefixed, a static replacement will be added.
+ *
+ * ex:
+ * array(
+ * ':controller' => array('CamelCaseToUnderscore','StringToLower'),
+ * ':action' => array('CamelCaseToUnderscore','StringToLower'),
+ * 'suffix' => 'phtml'
+ * );
+ *
+ * @param array
+ * @return Zend_Filter_Inflector
+ */
+ public function addRules(Array $rules)
+ {
+ $keys = array_keys($rules);
+ foreach ($keys as $spec) {
+ if ($spec[0] == ':') {
+ $this->addFilterRule($spec, $rules[$spec]);
+ } else {
+ $this->setStaticRule($spec, $rules[$spec]);
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Get rules
+ *
+ * By default, returns all rules. If a $spec is provided, will return those
+ * rules if found, false otherwise.
+ *
+ * @param string $spec
+ * @return array|false
+ */
+ public function getRules($spec = null)
+ {
+ if (null !== $spec) {
+ $spec = $this->_normalizeSpec($spec);
+ if (isset($this->_rules[$spec])) {
+ return $this->_rules[$spec];
+ }
+ return false;
+ }
+
+ return $this->_rules;
+ }
+
+ /**
+ * getRule() returns a rule set by setFilterRule(), a numeric index must be provided
+ *
+ * @param string $spec
+ * @param int $index
+ * @return Zend_Filter_Interface|false
+ */
+ public function getRule($spec, $index)
+ {
+ $spec = $this->_normalizeSpec($spec);
+ if (isset($this->_rules[$spec]) && is_array($this->_rules[$spec])) {
+ if (isset($this->_rules[$spec][$index])) {
+ return $this->_rules[$spec][$index];
+ }
+ }
+ return false;
+ }
+
+ /**
+ * ClearRules() clears the rules currently in the inflector
+ *
+ * @return Zend_Filter_Inflector
+ */
+ public function clearRules()
+ {
+ $this->_rules = array();
+ return $this;
+ }
+
+ /**
+ * Set a filtering rule for a spec. $ruleSet can be a string, Filter object
+ * or an array of strings or filter objects.
+ *
+ * @param string $spec
+ * @param array|string|Zend_Filter_Interface $ruleSet
+ * @return Zend_Filter_Inflector
+ */
+ public function setFilterRule($spec, $ruleSet)
+ {
+ $spec = $this->_normalizeSpec($spec);
+ $this->_rules[$spec] = array();
+ return $this->addFilterRule($spec, $ruleSet);
+ }
+
+ /**
+ * Add a filter rule for a spec
+ *
+ * @param mixed $spec
+ * @param mixed $ruleSet
+ * @return void
+ */
+ public function addFilterRule($spec, $ruleSet)
+ {
+ $spec = $this->_normalizeSpec($spec);
+ if (!isset($this->_rules[$spec])) {
+ $this->_rules[$spec] = array();
+ }
+
+ if (!is_array($ruleSet)) {
+ $ruleSet = array($ruleSet);
+ }
+
+ if (is_string($this->_rules[$spec])) {
+ $temp = $this->_rules[$spec];
+ $this->_rules[$spec] = array();
+ $this->_rules[$spec][] = $temp;
+ }
+
+ foreach ($ruleSet as $rule) {
+ $this->_rules[$spec][] = $this->_getRule($rule);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Set a static rule for a spec. This is a single string value
+ *
+ * @param string $name
+ * @param string $value
+ * @return Zend_Filter_Inflector
+ */
+ public function setStaticRule($name, $value)
+ {
+ $name = $this->_normalizeSpec($name);
+ $this->_rules[$name] = (string) $value;
+ return $this;
+ }
+
+ /**
+ * Set Static Rule Reference.
+ *
+ * This allows a consuming class to pass a property or variable
+ * in to be referenced when its time to build the output string from the
+ * target.
+ *
+ * @param string $name
+ * @param mixed $reference
+ * @return Zend_Filter_Inflector
+ */
+ public function setStaticRuleReference($name, &$reference)
+ {
+ $name = $this->_normalizeSpec($name);
+ $this->_rules[$name] =& $reference;
+ return $this;
+ }
+
+ /**
+ * Inflect
+ *
+ * @param string|array $source
+ * @return string
+ */
+ public function filter($source)
+ {
+ // clean source
+ foreach ( (array) $source as $sourceName => $sourceValue) {
+ $source[ltrim($sourceName, ':')] = $sourceValue;
+ }
+
+ $pregQuotedTargetReplacementIdentifier = preg_quote($this->_targetReplacementIdentifier, '#');
+ $processedParts = array();
+
+ foreach ($this->_rules as $ruleName => $ruleValue) {
+ if (isset($source[$ruleName])) {
+ if (is_string($ruleValue)) {
+ // overriding the set rule
+ $processedParts['#'.$pregQuotedTargetReplacementIdentifier.$ruleName.'#'] = str_replace('\\', '\\\\', $source[$ruleName]);
+ } elseif (is_array($ruleValue)) {
+ $processedPart = $source[$ruleName];
+ foreach ($ruleValue as $ruleFilter) {
+ $processedPart = $ruleFilter->filter($processedPart);
+ }
+ $processedParts['#'.$pregQuotedTargetReplacementIdentifier.$ruleName.'#'] = str_replace('\\', '\\\\', $processedPart);
+ }
+ } elseif (is_string($ruleValue)) {
+ $processedParts['#'.$pregQuotedTargetReplacementIdentifier.$ruleName.'#'] = str_replace('\\', '\\\\', $ruleValue);
+ }
+ }
+
+ // all of the values of processedParts would have been str_replace('\\', '\\\\', ..)'d to disable preg_replace backreferences
+ $inflectedTarget = preg_replace(array_keys($processedParts), array_values($processedParts), $this->_target);
+
+ if ($this->_throwTargetExceptionsOn && (preg_match('#(?='.$pregQuotedTargetReplacementIdentifier.'[A-Za-z]{1})#', $inflectedTarget) == true)) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('A replacement identifier ' . $this->_targetReplacementIdentifier . ' was found inside the inflected target, perhaps a rule was not satisfied with a target source? Unsatisfied inflected target: ' . $inflectedTarget);
+ }
+
+ return $inflectedTarget;
+ }
+
+ /**
+ * Normalize spec string
+ *
+ * @param string $spec
+ * @return string
+ */
+ protected function _normalizeSpec($spec)
+ {
+ return ltrim((string) $spec, ':&');
+ }
+
+ /**
+ * Resolve named filters and convert them to filter objects.
+ *
+ * @param string $rule
+ * @return Zend_Filter_Interface
+ */
+ protected function _getRule($rule)
+ {
+ if ($rule instanceof Zend_Filter_Interface) {
+ return $rule;
+ }
+
+ $rule = (string) $rule;
+
+ $className = $this->getPluginLoader()->load($rule);
+ $ruleObject = new $className();
+ if (!$ruleObject instanceof Zend_Filter_Interface) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('No class named ' . $rule . ' implementing Zend_Filter_Interface could be found');
+ }
+
+ return $ruleObject;
+ }
+}
diff --git a/lib/zend/Zend/Filter/Input.php b/lib/zend/Zend/Filter/Input.php
new file mode 100644
index 00000000000..c3229fa6fb4
--- /dev/null
+++ b/lib/zend/Zend/Filter/Input.php
@@ -0,0 +1,1209 @@
+ false,
+ self::BREAK_CHAIN => false,
+ self::ESCAPE_FILTER => 'HtmlEntities',
+ self::MISSING_MESSAGE => "Field '%field%' is required by rule '%rule%', but the field is missing",
+ self::NOT_EMPTY_MESSAGE => "You must give a non-empty value for field '%field%'",
+ self::PRESENCE => self::PRESENCE_OPTIONAL
+ );
+
+ /**
+ * @var boolean Set to False initially, this is set to True after the
+ * input data have been processed. Reset to False in setData() method.
+ */
+ protected $_processed = false;
+
+ /**
+ * Translation object
+ * @var Zend_Translate
+ */
+ protected $_translator;
+
+ /**
+ * Is translation disabled?
+ * @var Boolean
+ */
+ protected $_translatorDisabled = false;
+
+ /**
+ * @param array $filterRules
+ * @param array $validatorRules
+ * @param array $data OPTIONAL
+ * @param array $options OPTIONAL
+ */
+ public function __construct($filterRules, $validatorRules, array $data = null, array $options = null)
+ {
+ if ($options) {
+ $this->setOptions($options);
+ }
+
+ $this->_filterRules = (array) $filterRules;
+ $this->_validatorRules = (array) $validatorRules;
+
+ if ($data) {
+ $this->setData($data);
+ }
+ }
+
+ /**
+ * @param mixed $namespaces
+ * @return Zend_Filter_Input
+ * @deprecated since 1.5.0RC1 - use addFilterPrefixPath() or addValidatorPrefixPath instead.
+ */
+ public function addNamespace($namespaces)
+ {
+ if (!is_array($namespaces)) {
+ $namespaces = array($namespaces);
+ }
+
+ foreach ($namespaces as $namespace) {
+ $prefix = $namespace;
+ $path = str_replace('_', DIRECTORY_SEPARATOR, $prefix);
+ $this->addFilterPrefixPath($prefix, $path);
+ $this->addValidatorPrefixPath($prefix, $path);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Add prefix path for all elements
+ *
+ * @param string $prefix
+ * @param string $path
+ * @return Zend_Filter_Input
+ */
+ public function addFilterPrefixPath($prefix, $path)
+ {
+ $this->getPluginLoader(self::FILTER)->addPrefixPath($prefix, $path);
+
+ return $this;
+ }
+
+ /**
+ * Add prefix path for all elements
+ *
+ * @param string $prefix
+ * @param string $path
+ * @return Zend_Filter_Input
+ */
+ public function addValidatorPrefixPath($prefix, $path)
+ {
+ $this->getPluginLoader(self::VALIDATE)->addPrefixPath($prefix, $path);
+
+ return $this;
+ }
+
+ /**
+ * Set plugin loaders for use with decorators and elements
+ *
+ * @param Zend_Loader_PluginLoader_Interface $loader
+ * @param string $type 'filter' or 'validate'
+ * @return Zend_Filter_Input
+ * @throws Zend_Filter_Exception on invalid type
+ */
+ public function setPluginLoader(Zend_Loader_PluginLoader_Interface $loader, $type)
+ {
+ $type = strtolower($type);
+ switch ($type) {
+ case self::FILTER:
+ case self::VALIDATE:
+ $this->_loaders[$type] = $loader;
+ return $this;
+ default:
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception(sprintf('Invalid type "%s" provided to setPluginLoader()', $type));
+ }
+
+ return $this;
+ }
+
+ /**
+ * Retrieve plugin loader for given type
+ *
+ * $type may be one of:
+ * - filter
+ * - validator
+ *
+ * If a plugin loader does not exist for the given type, defaults are
+ * created.
+ *
+ * @param string $type 'filter' or 'validate'
+ * @return Zend_Loader_PluginLoader_Interface
+ * @throws Zend_Filter_Exception on invalid type
+ */
+ public function getPluginLoader($type)
+ {
+ $type = strtolower($type);
+ if (!isset($this->_loaders[$type])) {
+ switch ($type) {
+ case self::FILTER:
+ $prefixSegment = 'Zend_Filter_';
+ $pathSegment = 'Zend/Filter/';
+ break;
+ case self::VALIDATE:
+ $prefixSegment = 'Zend_Validate_';
+ $pathSegment = 'Zend/Validate/';
+ break;
+ default:
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception(sprintf('Invalid type "%s" provided to getPluginLoader()', $type));
+ }
+
+ require_once 'Zend/Loader/PluginLoader.php';
+ $this->_loaders[$type] = new Zend_Loader_PluginLoader(
+ array($prefixSegment => $pathSegment)
+ );
+ }
+
+ return $this->_loaders[$type];
+ }
+
+ /**
+ * @return array
+ */
+ public function getMessages()
+ {
+ $this->_process();
+ return array_merge($this->_invalidMessages, $this->_missingFields);
+ }
+
+ /**
+ * @return array
+ */
+ public function getErrors()
+ {
+ $this->_process();
+ return $this->_invalidErrors;
+ }
+
+ /**
+ * @return array
+ */
+ public function getInvalid()
+ {
+ $this->_process();
+ return $this->_invalidMessages;
+ }
+
+ /**
+ * @return array
+ */
+ public function getMissing()
+ {
+ $this->_process();
+ return $this->_missingFields;
+ }
+
+ /**
+ * @return array
+ */
+ public function getUnknown()
+ {
+ $this->_process();
+ return $this->_unknownFields;
+ }
+
+ /**
+ * @param string $fieldName OPTIONAL
+ * @return mixed
+ */
+ public function getEscaped($fieldName = null)
+ {
+ $this->_process();
+ $this->_getDefaultEscapeFilter();
+
+ if ($fieldName === null) {
+ return $this->_escapeRecursive($this->_validFields);
+ }
+ if (array_key_exists($fieldName, $this->_validFields)) {
+ return $this->_escapeRecursive($this->_validFields[$fieldName]);
+ }
+ return null;
+ }
+
+ /**
+ * @param mixed $value
+ * @return mixed
+ */
+ protected function _escapeRecursive($data)
+ {
+ if($data === null) {
+ return $data;
+ }
+
+ if (!is_array($data)) {
+ return $this->_getDefaultEscapeFilter()->filter($data);
+ }
+ foreach ($data as &$element) {
+ $element = $this->_escapeRecursive($element);
+ }
+ return $data;
+ }
+
+ /**
+ * @param string $fieldName OPTIONAL
+ * @return mixed
+ */
+ public function getUnescaped($fieldName = null)
+ {
+ $this->_process();
+ if ($fieldName === null) {
+ return $this->_validFields;
+ }
+ if (array_key_exists($fieldName, $this->_validFields)) {
+ return $this->_validFields[$fieldName];
+ }
+ return null;
+ }
+
+ /**
+ * @param string $fieldName
+ * @return mixed
+ */
+ public function __get($fieldName)
+ {
+ return $this->getEscaped($fieldName);
+ }
+
+ /**
+ * @return boolean
+ */
+ public function hasInvalid()
+ {
+ $this->_process();
+ return !(empty($this->_invalidMessages));
+ }
+
+ /**
+ * @return boolean
+ */
+ public function hasMissing()
+ {
+ $this->_process();
+ return !(empty($this->_missingFields));
+ }
+
+ /**
+ * @return boolean
+ */
+ public function hasUnknown()
+ {
+ $this->_process();
+ return !(empty($this->_unknownFields));
+ }
+
+ /**
+ * @return boolean
+ */
+ public function hasValid()
+ {
+ $this->_process();
+ return !(empty($this->_validFields));
+ }
+
+ /**
+ * @param string $fieldName
+ * @return boolean
+ */
+ public function isValid($fieldName = null)
+ {
+ $this->_process();
+ if ($fieldName === null) {
+ return !($this->hasMissing() || $this->hasInvalid());
+ }
+ return array_key_exists($fieldName, $this->_validFields);
+ }
+
+ /**
+ * @param string $fieldName
+ * @return boolean
+ */
+ public function __isset($fieldName)
+ {
+ $this->_process();
+ return isset($this->_validFields[$fieldName]);
+ }
+
+ /**
+ * @return Zend_Filter_Input
+ * @throws Zend_Filter_Exception
+ */
+ public function process()
+ {
+ $this->_process();
+ if ($this->hasInvalid()) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception("Input has invalid fields");
+ }
+ if ($this->hasMissing()) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception("Input has missing fields");
+ }
+
+ return $this;
+ }
+
+ /**
+ * @param array $data
+ * @return Zend_Filter_Input
+ */
+ public function setData(array $data)
+ {
+ $this->_data = $data;
+
+ /**
+ * Reset to initial state
+ */
+ $this->_validFields = array();
+ $this->_invalidMessages = array();
+ $this->_invalidErrors = array();
+ $this->_missingFields = array();
+ $this->_unknownFields = array();
+
+ $this->_processed = false;
+
+ return $this;
+ }
+
+ /**
+ * @param mixed $escapeFilter
+ * @return Zend_Filter_Interface
+ */
+ public function setDefaultEscapeFilter($escapeFilter)
+ {
+ if (is_string($escapeFilter) || is_array($escapeFilter)) {
+ $escapeFilter = $this->_getFilter($escapeFilter);
+ }
+ if (!$escapeFilter instanceof Zend_Filter_Interface) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('Escape filter specified does not implement Zend_Filter_Interface');
+ }
+ $this->_defaultEscapeFilter = $escapeFilter;
+ return $escapeFilter;
+ }
+
+ /**
+ * @param array $options
+ * @return Zend_Filter_Input
+ * @throws Zend_Filter_Exception if an unknown option is given
+ */
+ public function setOptions(array $options)
+ {
+ foreach ($options as $option => $value) {
+ switch ($option) {
+ case self::ESCAPE_FILTER:
+ $this->setDefaultEscapeFilter($value);
+ break;
+ case self::INPUT_NAMESPACE:
+ $this->addNamespace($value);
+ break;
+ case self::VALIDATOR_NAMESPACE:
+ if(is_string($value)) {
+ $value = array($value);
+ }
+
+ foreach($value AS $prefix) {
+ $this->addValidatorPrefixPath(
+ $prefix,
+ str_replace('_', DIRECTORY_SEPARATOR, $prefix)
+ );
+ }
+ break;
+ case self::FILTER_NAMESPACE:
+ if(is_string($value)) {
+ $value = array($value);
+ }
+
+ foreach($value AS $prefix) {
+ $this->addFilterPrefixPath(
+ $prefix,
+ str_replace('_', DIRECTORY_SEPARATOR, $prefix)
+ );
+ }
+ break;
+ case self::ALLOW_EMPTY:
+ case self::BREAK_CHAIN:
+ case self::MISSING_MESSAGE:
+ case self::NOT_EMPTY_MESSAGE:
+ case self::PRESENCE:
+ $this->_defaults[$option] = $value;
+ break;
+ default:
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception("Unknown option '$option'");
+ break;
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Set translation object
+ *
+ * @param Zend_Translate|Zend_Translate_Adapter|null $translator
+ * @return Zend_Filter_Input
+ */
+ public function setTranslator($translator = null)
+ {
+ if ((null === $translator) || ($translator instanceof Zend_Translate_Adapter)) {
+ $this->_translator = $translator;
+ } elseif ($translator instanceof Zend_Translate) {
+ $this->_translator = $translator->getAdapter();
+ } else {
+ require_once 'Zend/Validate/Exception.php';
+ throw new Zend_Validate_Exception('Invalid translator specified');
+ }
+
+ return $this;
+ }
+
+ /**
+ * Return translation object
+ *
+ * @return Zend_Translate_Adapter|null
+ */
+ public function getTranslator()
+ {
+ if ($this->translatorIsDisabled()) {
+ return null;
+ }
+
+ if ($this->_translator === null) {
+ require_once 'Zend/Registry.php';
+ if (Zend_Registry::isRegistered('Zend_Translate')) {
+ $translator = Zend_Registry::get('Zend_Translate');
+ if ($translator instanceof Zend_Translate_Adapter) {
+ return $translator;
+ } elseif ($translator instanceof Zend_Translate) {
+ return $translator->getAdapter();
+ }
+ }
+ }
+
+ return $this->_translator;
+ }
+
+ /**
+ * Indicate whether or not translation should be disabled
+ *
+ * @param bool $flag
+ * @return Zend_Filter_Input
+ */
+ public function setDisableTranslator($flag)
+ {
+ $this->_translatorDisabled = (bool) $flag;
+ return $this;
+ }
+
+ /**
+ * Is translation disabled?
+ *
+ * @return bool
+ */
+ public function translatorIsDisabled()
+ {
+ return $this->_translatorDisabled;
+ }
+
+ /*
+ * Protected methods
+ */
+
+ /**
+ * @return void
+ */
+ protected function _filter()
+ {
+ foreach ($this->_filterRules as $ruleName => &$filterRule) {
+ /**
+ * Make sure we have an array representing this filter chain.
+ * Don't typecast to (array) because it might be a Zend_Filter object
+ */
+ if (!is_array($filterRule)) {
+ $filterRule = array($filterRule);
+ }
+
+ /**
+ * Filters are indexed by integer, metacommands are indexed by string.
+ * Pick out the filters.
+ */
+ $filterList = array();
+ foreach ($filterRule as $key => $value) {
+ if (is_int($key)) {
+ $filterList[] = $value;
+ }
+ }
+
+ /**
+ * Use defaults for filter metacommands.
+ */
+ $filterRule[self::RULE] = $ruleName;
+ if (!isset($filterRule[self::FIELDS])) {
+ $filterRule[self::FIELDS] = $ruleName;
+ }
+
+ /**
+ * Load all the filter classes and add them to the chain.
+ */
+ if (!isset($filterRule[self::FILTER_CHAIN])) {
+ $filterRule[self::FILTER_CHAIN] = new Zend_Filter();
+ foreach ($filterList as $filter) {
+ if (is_string($filter) || is_array($filter)) {
+ $filter = $this->_getFilter($filter);
+ }
+ $filterRule[self::FILTER_CHAIN]->addFilter($filter);
+ }
+ }
+
+ /**
+ * If the ruleName is the special wildcard rule,
+ * then apply the filter chain to all input data.
+ * Else just process the field named by the rule.
+ */
+ if ($ruleName == self::RULE_WILDCARD) {
+ foreach (array_keys($this->_data) as $field) {
+ $this->_filterRule(array_merge($filterRule, array(self::FIELDS => $field)));
+ }
+ } else {
+ $this->_filterRule($filterRule);
+ }
+ }
+ }
+
+ /**
+ * @param array $filterRule
+ * @return void
+ */
+ protected function _filterRule(array $filterRule)
+ {
+ $field = $filterRule[self::FIELDS];
+ if (!array_key_exists($field, $this->_data)) {
+ return;
+ }
+ if (is_array($this->_data[$field])) {
+ foreach ($this->_data[$field] as $key => $value) {
+ $this->_data[$field][$key] = $filterRule[self::FILTER_CHAIN]->filter($value);
+ }
+ } else {
+ $this->_data[$field] =
+ $filterRule[self::FILTER_CHAIN]->filter($this->_data[$field]);
+ }
+ }
+
+ /**
+ * @return Zend_Filter_Interface
+ */
+ protected function _getDefaultEscapeFilter()
+ {
+ if ($this->_defaultEscapeFilter !== null) {
+ return $this->_defaultEscapeFilter;
+ }
+ return $this->setDefaultEscapeFilter($this->_defaults[self::ESCAPE_FILTER]);
+ }
+
+ /**
+ * @param string $rule
+ * @param string $field
+ * @return string
+ */
+ protected function _getMissingMessage($rule, $field)
+ {
+ $message = $this->_defaults[self::MISSING_MESSAGE];
+
+ if (null !== ($translator = $this->getTranslator())) {
+ if ($translator->isTranslated(self::MISSING_MESSAGE)) {
+ $message = $translator->translate(self::MISSING_MESSAGE);
+ } else {
+ $message = $translator->translate($message);
+ }
+ }
+
+ $message = str_replace('%rule%', $rule, $message);
+ $message = str_replace('%field%', $field, $message);
+ return $message;
+ }
+
+ /**
+ * @return string
+ */
+ protected function _getNotEmptyMessage($rule, $field)
+ {
+ $message = $this->_defaults[self::NOT_EMPTY_MESSAGE];
+
+ if (null !== ($translator = $this->getTranslator())) {
+ if ($translator->isTranslated(self::NOT_EMPTY_MESSAGE)) {
+ $message = $translator->translate(self::NOT_EMPTY_MESSAGE);
+ } else {
+ $message = $translator->translate($message);
+ }
+ }
+
+ $message = str_replace('%rule%', $rule, $message);
+ $message = str_replace('%field%', $field, $message);
+ return $message;
+ }
+
+ /**
+ * @return void
+ */
+ protected function _process()
+ {
+ if ($this->_processed === false) {
+ $this->_filter();
+ $this->_validate();
+ $this->_processed = true;
+ }
+ }
+
+ /**
+ * @return void
+ */
+ protected function _validate()
+ {
+ /**
+ * Special case: if there are no validators, treat all fields as valid.
+ */
+ if (!$this->_validatorRules) {
+ $this->_validFields = $this->_data;
+ $this->_data = array();
+ return;
+ }
+
+ // remember the default not empty message in case we want to temporarily change it
+ $preserveDefaultNotEmptyMessage = $this->_defaults[self::NOT_EMPTY_MESSAGE];
+
+ foreach ($this->_validatorRules as $ruleName => &$validatorRule) {
+ /**
+ * Make sure we have an array representing this validator chain.
+ * Don't typecast to (array) because it might be a Zend_Validate object
+ */
+ if (!is_array($validatorRule)) {
+ $validatorRule = array($validatorRule);
+ }
+
+ /**
+ * Validators are indexed by integer, metacommands are indexed by string.
+ * Pick out the validators.
+ */
+ $validatorList = array();
+ foreach ($validatorRule as $key => $value) {
+ if (is_int($key)) {
+ $validatorList[$key] = $value;
+ }
+ }
+
+ /**
+ * Use defaults for validation metacommands.
+ */
+ $validatorRule[self::RULE] = $ruleName;
+ if (!isset($validatorRule[self::FIELDS])) {
+ $validatorRule[self::FIELDS] = $ruleName;
+ }
+ if (!isset($validatorRule[self::BREAK_CHAIN])) {
+ $validatorRule[self::BREAK_CHAIN] = $this->_defaults[self::BREAK_CHAIN];
+ }
+ if (!isset($validatorRule[self::PRESENCE])) {
+ $validatorRule[self::PRESENCE] = $this->_defaults[self::PRESENCE];
+ }
+ if (!isset($validatorRule[self::ALLOW_EMPTY])) {
+ $foundNotEmptyValidator = false;
+
+ foreach ($validatorRule as $rule) {
+ if ($rule === 'NotEmpty') {
+ $foundNotEmptyValidator = true;
+ // field may not be empty, we are ready
+ break 1;
+ }
+
+ if (is_array($rule)) {
+ $keys = array_keys($rule);
+ $classKey = array_shift($keys);
+ if (isset($rule[$classKey])) {
+ $ruleClass = $rule[$classKey];
+ if ($ruleClass === 'NotEmpty') {
+ $foundNotEmptyValidator = true;
+ // field may not be empty, we are ready
+ break 1;
+ }
+ }
+ }
+
+ // we must check if it is an object before using instanceof
+ if (!is_object($rule)) {
+ // it cannot be a NotEmpty validator, skip this one
+ continue;
+ }
+
+ if($rule instanceof Zend_Validate_NotEmpty) {
+ $foundNotEmptyValidator = true;
+ // field may not be empty, we are ready
+ break 1;
+ }
+ }
+
+ if (!$foundNotEmptyValidator) {
+ $validatorRule[self::ALLOW_EMPTY] = $this->_defaults[self::ALLOW_EMPTY];
+ } else {
+ $validatorRule[self::ALLOW_EMPTY] = false;
+ }
+ }
+
+ if (!isset($validatorRule[self::MESSAGES])) {
+ $validatorRule[self::MESSAGES] = array();
+ } else if (!is_array($validatorRule[self::MESSAGES])) {
+ $validatorRule[self::MESSAGES] = array($validatorRule[self::MESSAGES]);
+ } else if (array_intersect_key($validatorList, $validatorRule[self::MESSAGES])) {
+ // this seems pointless... it just re-adds what it already has...
+ // I can disable all this and not a single unit test fails...
+ // There are now corresponding numeric keys in the validation rule messages array
+ // Treat it as a named messages list for all rule validators
+ $unifiedMessages = $validatorRule[self::MESSAGES];
+ $validatorRule[self::MESSAGES] = array();
+
+ foreach ($validatorList as $key => $validator) {
+ if (array_key_exists($key, $unifiedMessages)) {
+ $validatorRule[self::MESSAGES][$key] = $unifiedMessages[$key];
+ }
+ }
+ }
+
+ /**
+ * Load all the validator classes and add them to the chain.
+ */
+ if (!isset($validatorRule[self::VALIDATOR_CHAIN])) {
+ $validatorRule[self::VALIDATOR_CHAIN] = new Zend_Validate();
+
+ foreach ($validatorList as $key => $validator) {
+ if (is_string($validator) || is_array($validator)) {
+ $validator = $this->_getValidator($validator);
+ }
+
+ if (isset($validatorRule[self::MESSAGES][$key])) {
+ $value = $validatorRule[self::MESSAGES][$key];
+ if (is_array($value)) {
+ $validator->setMessages($value);
+ } else {
+ $validator->setMessage($value);
+ }
+
+ if ($validator instanceof Zend_Validate_NotEmpty) {
+ /** we are changing the defaults here, this is alright if all subsequent validators are also a not empty
+ * validator, but it goes wrong if one of them is not AND is required!!!
+ * that is why we restore the default value at the end of this loop
+ */
+ if (is_array($value)) {
+ $temp = $value; // keep the original value
+ $this->_defaults[self::NOT_EMPTY_MESSAGE] = array_pop($temp);
+ unset($temp);
+ } else {
+ $this->_defaults[self::NOT_EMPTY_MESSAGE] = $value;
+ }
+ }
+ }
+
+ $validatorRule[self::VALIDATOR_CHAIN]->addValidator($validator, $validatorRule[self::BREAK_CHAIN]);
+ }
+ $validatorRule[self::VALIDATOR_CHAIN_COUNT] = count($validatorList);
+ }
+
+ /**
+ * If the ruleName is the special wildcard rule,
+ * then apply the validator chain to all input data.
+ * Else just process the field named by the rule.
+ */
+ if ($ruleName == self::RULE_WILDCARD) {
+ foreach (array_keys($this->_data) as $field) {
+ $this->_validateRule(array_merge($validatorRule, array(self::FIELDS => $field)));
+ }
+ } else {
+ $this->_validateRule($validatorRule);
+ }
+
+ // reset the default not empty message
+ $this->_defaults[self::NOT_EMPTY_MESSAGE] = $preserveDefaultNotEmptyMessage;
+ }
+
+
+
+ /**
+ * Unset fields in $_data that have been added to other arrays.
+ * We have to wait until all rules have been processed because
+ * a given field may be referenced by multiple rules.
+ */
+ foreach (array_merge(array_keys($this->_missingFields), array_keys($this->_invalidMessages)) as $rule) {
+ foreach ((array) $this->_validatorRules[$rule][self::FIELDS] as $field) {
+ unset($this->_data[$field]);
+ }
+ }
+ foreach ($this->_validFields as $field => $value) {
+ unset($this->_data[$field]);
+ }
+
+ /**
+ * Anything left over in $_data is an unknown field.
+ */
+ $this->_unknownFields = $this->_data;
+ }
+
+ /**
+ * @param array $validatorRule
+ * @return void
+ */
+ protected function _validateRule(array $validatorRule)
+ {
+ /**
+ * Get one or more data values from input, and check for missing fields.
+ * Apply defaults if fields are missing.
+ */
+ $data = array();
+ foreach ((array) $validatorRule[self::FIELDS] as $key => $field) {
+ if (array_key_exists($field, $this->_data)) {
+ $data[$field] = $this->_data[$field];
+ } else if (isset($validatorRule[self::DEFAULT_VALUE])) {
+ /** @todo according to this code default value can't be an array. It has to be reviewed */
+ if (!is_array($validatorRule[self::DEFAULT_VALUE])) {
+ // Default value is a scalar
+ $data[$field] = $validatorRule[self::DEFAULT_VALUE];
+ } else {
+ // Default value is an array. Search for corresponding key
+ if (isset($validatorRule[self::DEFAULT_VALUE][$key])) {
+ $data[$field] = $validatorRule[self::DEFAULT_VALUE][$key];
+ } else if ($validatorRule[self::PRESENCE] == self::PRESENCE_REQUIRED) {
+ // Default value array is provided, but it doesn't have an entry for current field
+ // and presence is required
+ $this->_missingFields[$validatorRule[self::RULE]][] =
+ $this->_getMissingMessage($validatorRule[self::RULE], $field);
+ }
+ }
+ } else if ($validatorRule[self::PRESENCE] == self::PRESENCE_REQUIRED) {
+ $this->_missingFields[$validatorRule[self::RULE]][] =
+ $this->_getMissingMessage($validatorRule[self::RULE], $field);
+ }
+ }
+
+ /**
+ * If any required fields are missing, break the loop.
+ */
+ if (isset($this->_missingFields[$validatorRule[self::RULE]]) && count($this->_missingFields[$validatorRule[self::RULE]]) > 0) {
+ return;
+ }
+
+ /**
+ * Evaluate the inputs against the validator chain.
+ */
+ if (count((array) $validatorRule[self::FIELDS]) > 1) {
+ if (!$validatorRule[self::ALLOW_EMPTY]) {
+ $emptyFieldsFound = false;
+ $errorsList = array();
+ $messages = array();
+
+ foreach ($data as $fieldKey => $field) {
+ // if there is no Zend_Validate_NotEmpty instance in the rules, we will use the default
+ if (!($notEmptyValidator = $this->_getNotEmptyValidatorInstance($validatorRule))) {
+ $notEmptyValidator = $this->_getValidator('NotEmpty');
+ $notEmptyValidator->setMessage($this->_getNotEmptyMessage($validatorRule[self::RULE], $fieldKey));
+ }
+
+ if (!$notEmptyValidator->isValid($field)) {
+ foreach ($notEmptyValidator->getMessages() as $messageKey => $message) {
+ if (!isset($messages[$messageKey])) {
+ $messages[$messageKey] = $message;
+ } else {
+ $messages[] = $message;
+ }
+ }
+ $errorsList[] = $notEmptyValidator->getErrors();
+ $emptyFieldsFound = true;
+ }
+ }
+
+ if ($emptyFieldsFound) {
+ $this->_invalidMessages[$validatorRule[self::RULE]] = $messages;
+ $this->_invalidErrors[$validatorRule[self::RULE]] = array_unique(call_user_func_array('array_merge', $errorsList));
+ return;
+ }
+ }
+
+ if (!$validatorRule[self::VALIDATOR_CHAIN]->isValid($data)) {
+ $this->_invalidMessages[$validatorRule[self::RULE]] = $validatorRule[self::VALIDATOR_CHAIN]->getMessages();
+ $this->_invalidErrors[$validatorRule[self::RULE]] = $validatorRule[self::VALIDATOR_CHAIN]->getErrors();
+ return;
+ }
+ } else if (count($data) > 0) {
+ // $data is actually a one element array
+ $fieldNames = array_keys($data);
+ $fieldName = reset($fieldNames);
+ $field = reset($data);
+
+ $failed = false;
+ if (!is_array($field)) {
+ $field = array($field);
+ }
+
+ // if there is no Zend_Validate_NotEmpty instance in the rules, we will use the default
+ if (!($notEmptyValidator = $this->_getNotEmptyValidatorInstance($validatorRule))) {
+ $notEmptyValidator = $this->_getValidator('NotEmpty');
+ $notEmptyValidator->setMessage($this->_getNotEmptyMessage($validatorRule[self::RULE], $fieldName));
+ }
+
+ if ($validatorRule[self::ALLOW_EMPTY]) {
+ $validatorChain = $validatorRule[self::VALIDATOR_CHAIN];
+ } else {
+ $validatorChain = new Zend_Validate();
+ $validatorChain->addValidator($notEmptyValidator, true /* Always break on failure */);
+ $validatorChain->addValidator($validatorRule[self::VALIDATOR_CHAIN]);
+ }
+
+ foreach ($field as $key => $value) {
+ if ($validatorRule[self::ALLOW_EMPTY] && !$notEmptyValidator->isValid($value)) {
+ // Field is empty AND it's allowed. Do nothing.
+ continue;
+ }
+
+ if (!$validatorChain->isValid($value)) {
+ if (isset($this->_invalidMessages[$validatorRule[self::RULE]])) {
+ $collectedMessages = $this->_invalidMessages[$validatorRule[self::RULE]];
+ } else {
+ $collectedMessages = array();
+ }
+
+ foreach ($validatorChain->getMessages() as $messageKey => $message) {
+ if (!isset($collectedMessages[$messageKey])) {
+ $collectedMessages[$messageKey] = $message;
+ } else {
+ $collectedMessages[] = $message;
+ }
+ }
+
+ $this->_invalidMessages[$validatorRule[self::RULE]] = $collectedMessages;
+ if (isset($this->_invalidErrors[$validatorRule[self::RULE]])) {
+ $this->_invalidErrors[$validatorRule[self::RULE]] = array_merge($this->_invalidErrors[$validatorRule[self::RULE]],
+ $validatorChain->getErrors());
+ } else {
+ $this->_invalidErrors[$validatorRule[self::RULE]] = $validatorChain->getErrors();
+ }
+ unset($this->_validFields[$fieldName]);
+ $failed = true;
+ if ($validatorRule[self::BREAK_CHAIN]) {
+ return;
+ }
+ }
+ }
+ if ($failed) {
+ return;
+ }
+ }
+
+ /**
+ * If we got this far, the inputs for this rule pass validation.
+ */
+ foreach ((array) $validatorRule[self::FIELDS] as $field) {
+ if (array_key_exists($field, $data)) {
+ $this->_validFields[$field] = $data[$field];
+ }
+ }
+ }
+
+ /**
+ * Check a validatorRule for the presence of a NotEmpty validator instance.
+ * The purpose is to preserve things like a custom message, that may have been
+ * set on the validator outside Zend_Filter_Input.
+ * @param array $validatorRule
+ * @return mixed false if none is found, Zend_Validate_NotEmpty instance if found
+ */
+ protected function _getNotEmptyValidatorInstance($validatorRule) {
+ foreach ($validatorRule as $rule => $value) {
+ if (is_object($value) and $value instanceof Zend_Validate_NotEmpty) {
+ return $value;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * @param mixed $classBaseName
+ * @return Zend_Filter_Interface
+ */
+ protected function _getFilter($classBaseName)
+ {
+ return $this->_getFilterOrValidator(self::FILTER, $classBaseName);
+ }
+
+ /**
+ * @param mixed $classBaseName
+ * @return Zend_Validate_Interface
+ */
+ protected function _getValidator($classBaseName)
+ {
+ return $this->_getFilterOrValidator(self::VALIDATE, $classBaseName);
+ }
+
+ /**
+ * @param string $type
+ * @param mixed $classBaseName
+ * @return Zend_Filter_Interface|Zend_Validate_Interface
+ * @throws Zend_Filter_Exception
+ */
+ protected function _getFilterOrValidator($type, $classBaseName)
+ {
+ $args = array();
+
+ if (is_array($classBaseName)) {
+ $args = $classBaseName;
+ $classBaseName = array_shift($args);
+ }
+
+ $interfaceName = 'Zend_' . ucfirst($type) . '_Interface';
+ $className = $this->getPluginLoader($type)->load(ucfirst($classBaseName));
+
+ $class = new ReflectionClass($className);
+
+ if (!$class->implementsInterface($interfaceName)) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception("Class '$className' based on basename '$classBaseName' must implement the '$interfaceName' interface");
+ }
+
+ if ($class->hasMethod('__construct')) {
+ $object = $class->newInstanceArgs($args);
+ } else {
+ $object = $class->newInstance();
+ }
+
+ return $object;
+ }
+
+}
diff --git a/lib/zend/Zend/Service/DeveloperGarden/Request/SmsValidation/GetValidatedNumbers.php b/lib/zend/Zend/Filter/Int.php
similarity index 57%
rename from lib/zend/Zend/Service/DeveloperGarden/Request/SmsValidation/GetValidatedNumbers.php
rename to lib/zend/Zend/Filter/Int.php
index b7fff44f88e..ee20702559e 100644
--- a/lib/zend/Zend/Service/DeveloperGarden/Request/SmsValidation/GetValidatedNumbers.php
+++ b/lib/zend/Zend/Filter/Int.php
@@ -1,4 +1,5 @@
null,
+ 'date_format' => null,
+ 'precision' => null
+ );
+
+ /**
+ * Class constructor
+ *
+ * @param string|Zend_Locale $locale (Optional) Locale to set
+ */
+ public function __construct($options = null)
+ {
+ if ($options instanceof Zend_Config) {
+ $options = $options->toArray();
+ }
+
+ if (null !== $options) {
+ $this->setOptions($options);
+ }
+ }
+
+ /**
+ * Returns the set options
+ *
+ * @return array
+ */
+ public function getOptions()
+ {
+ return $this->_options;
+ }
+
+ /**
+ * Sets options to use
+ *
+ * @param array $options (Optional) Options to use
+ * @return Zend_Filter_LocalizedToNormalized
+ */
+ public function setOptions(array $options = null)
+ {
+ $this->_options = $options + $this->_options;
+ return $this;
+ }
+
+ /**
+ * Defined by Zend_Filter_Interface
+ *
+ * Normalizes the given input
+ *
+ * @param string $value Value to normalized
+ * @return string|array The normalized value
+ */
+ public function filter($value)
+ {
+ if (Zend_Locale_Format::isNumber($value, $this->_options)) {
+ return Zend_Locale_Format::getNumber($value, $this->_options);
+ } else if (($this->_options['date_format'] === null) && (strpos($value, ':') !== false)) {
+ // Special case, no date format specified, detect time input
+ return Zend_Locale_Format::getTime($value, $this->_options);
+ } else if (Zend_Locale_Format::checkDateFormat($value, $this->_options)) {
+ // Detect date or time input
+ return Zend_Locale_Format::getDate($value, $this->_options);
+ }
+
+ return $value;
+ }
+}
diff --git a/lib/zend/Zend/Filter/NormalizedToLocalized.php b/lib/zend/Zend/Filter/NormalizedToLocalized.php
new file mode 100644
index 00000000000..60dbb9e0657
--- /dev/null
+++ b/lib/zend/Zend/Filter/NormalizedToLocalized.php
@@ -0,0 +1,111 @@
+ null,
+ 'date_format' => null,
+ 'precision' => null
+ );
+
+ /**
+ * Class constructor
+ *
+ * @param string|Zend_Locale $locale (Optional) Locale to set
+ */
+ public function __construct($options = null)
+ {
+ if ($options instanceof Zend_Config) {
+ $options = $options->toArray();
+ }
+
+ if (null !== $options) {
+ $this->setOptions($options);
+ }
+ }
+
+ /**
+ * Returns the set options
+ *
+ * @return array
+ */
+ public function getOptions()
+ {
+ return $this->_options;
+ }
+
+ /**
+ * Sets options to use
+ *
+ * @param array $options (Optional) Options to use
+ * @return Zend_Filter_LocalizedToNormalized
+ */
+ public function setOptions(array $options = null)
+ {
+ $this->_options = $options + $this->_options;
+ return $this;
+ }
+
+ /**
+ * Defined by Zend_Filter_Interface
+ *
+ * Normalizes the given input
+ *
+ * @param string $value Value to normalized
+ * @return string|array The normalized value
+ */
+ public function filter($value)
+ {
+ if (is_array($value)) {
+ require_once 'Zend/Date.php';
+ $date = new Zend_Date($value, $this->_options['locale']);
+ return $date->toString($this->_options['date_format']);
+ } else if ($this->_options['precision'] === 0) {
+ return Zend_Locale_Format::toInteger($value, $this->_options);
+ } else if ($this->_options['precision'] === null) {
+ return Zend_Locale_Format::toFloat($value, $this->_options);
+ }
+
+ return Zend_Locale_Format::toNumber($value, $this->_options);
+ }
+}
diff --git a/lib/zend/Zend/Filter/Null.php b/lib/zend/Zend/Filter/Null.php
new file mode 100644
index 00000000000..c7988004160
--- /dev/null
+++ b/lib/zend/Zend/Filter/Null.php
@@ -0,0 +1,183 @@
+ 'boolean',
+ self::INTEGER => 'integer',
+ self::EMPTY_ARRAY => 'array',
+ self::STRING => 'string',
+ self::ZERO => 'zero',
+ self::ALL => 'all'
+ );
+
+ /**
+ * Internal type to detect
+ *
+ * @var integer
+ */
+ protected $_type = self::ALL;
+
+ /**
+ * Constructor
+ *
+ * @param string|array|Zend_Config $options OPTIONAL
+ */
+ public function __construct($options = null)
+ {
+ if ($options instanceof Zend_Config) {
+ $options = $options->toArray();
+ } else if (!is_array($options)) {
+ $options = func_get_args();
+ $temp = array();
+ if (!empty($options)) {
+ $temp = array_shift($options);
+ }
+ $options = $temp;
+ } else if (is_array($options) && array_key_exists('type', $options)) {
+ $options = $options['type'];
+ }
+
+ if (!empty($options)) {
+ $this->setType($options);
+ }
+ }
+
+ /**
+ * Returns the set null types
+ *
+ * @return array
+ */
+ public function getType()
+ {
+ return $this->_type;
+ }
+
+ /**
+ * Set the null types
+ *
+ * @param integer|array $type
+ * @throws Zend_Filter_Exception
+ * @return Zend_Filter_Null
+ */
+ public function setType($type = null)
+ {
+ if (is_array($type)) {
+ $detected = 0;
+ foreach($type as $value) {
+ if (is_int($value)) {
+ $detected += $value;
+ } else if (in_array($value, $this->_constants)) {
+ $detected += array_search($value, $this->_constants);
+ }
+ }
+
+ $type = $detected;
+ } else if (is_string($type)) {
+ if (in_array($type, $this->_constants)) {
+ $type = array_search($type, $this->_constants);
+ }
+ }
+
+ if (!is_int($type) || ($type < 0) || ($type > self::ALL)) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('Unknown type');
+ }
+
+ $this->_type = $type;
+ return $this;
+ }
+
+ /**
+ * Defined by Zend_Filter_Interface
+ *
+ * Returns null representation of $value, if value is empty and matches
+ * types that should be considered null.
+ *
+ * @param string $value
+ * @return string
+ */
+ public function filter($value)
+ {
+ $type = $this->getType();
+
+ // STRING ZERO ('0')
+ if ($type >= self::ZERO) {
+ $type -= self::ZERO;
+ if (is_string($value) && ($value == '0')) {
+ return null;
+ }
+ }
+
+ // STRING ('')
+ if ($type >= self::STRING) {
+ $type -= self::STRING;
+ if (is_string($value) && ($value == '')) {
+ return null;
+ }
+ }
+
+ // EMPTY_ARRAY (array())
+ if ($type >= self::EMPTY_ARRAY) {
+ $type -= self::EMPTY_ARRAY;
+ if (is_array($value) && ($value == array())) {
+ return null;
+ }
+ }
+
+ // INTEGER (0)
+ if ($type >= self::INTEGER) {
+ $type -= self::INTEGER;
+ if (is_int($value) && ($value == 0)) {
+ return null;
+ }
+ }
+
+ // BOOLEAN (false)
+ if ($type >= self::BOOLEAN) {
+ $type -= self::BOOLEAN;
+ if (is_bool($value) && ($value == false)) {
+ return null;
+ }
+ }
+
+ return $value;
+ }
+}
diff --git a/lib/zend/Zend/Filter/PregReplace.php b/lib/zend/Zend/Filter/PregReplace.php
new file mode 100644
index 00000000000..7100c3717d8
--- /dev/null
+++ b/lib/zend/Zend/Filter/PregReplace.php
@@ -0,0 +1,174 @@
+ matching pattern
+ * 'replace' => replace with this
+ *
+ * @param string|array $options
+ * @return void
+ */
+ public function __construct($options = null)
+ {
+ if ($options instanceof Zend_Config) {
+ $options = $options->toArray();
+ } else if (!is_array($options)) {
+ $options = func_get_args();
+ $temp = array();
+ if (!empty($options)) {
+ $temp['match'] = array_shift($options);
+ }
+
+ if (!empty($options)) {
+ $temp['replace'] = array_shift($options);
+ }
+
+ $options = $temp;
+ }
+
+ if (array_key_exists('match', $options)) {
+ $this->setMatchPattern($options['match']);
+ }
+
+ if (array_key_exists('replace', $options)) {
+ $this->setReplacement($options['replace']);
+ }
+ }
+
+ /**
+ * Set the match pattern for the regex being called within filter()
+ *
+ * @param mixed $match - same as the first argument of preg_replace
+ * @return Zend_Filter_PregReplace
+ */
+ public function setMatchPattern($match)
+ {
+ $this->_matchPattern = $match;
+ return $this;
+ }
+
+ /**
+ * Get currently set match pattern
+ *
+ * @return string
+ */
+ public function getMatchPattern()
+ {
+ return $this->_matchPattern;
+ }
+
+ /**
+ * Set the Replacement pattern/string for the preg_replace called in filter
+ *
+ * @param mixed $replacement - same as the second argument of preg_replace
+ * @return Zend_Filter_PregReplace
+ */
+ public function setReplacement($replacement)
+ {
+ $this->_replacement = $replacement;
+ return $this;
+ }
+
+ /**
+ * Get currently set replacement value
+ *
+ * @return string
+ */
+ public function getReplacement()
+ {
+ return $this->_replacement;
+ }
+
+ /**
+ * Perform regexp replacement as filter
+ *
+ * @param string $value
+ * @return string
+ */
+ public function filter($value)
+ {
+ if ($this->_matchPattern == null) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception(get_class($this) . ' does not have a valid MatchPattern set.');
+ }
+
+ return preg_replace($this->_matchPattern, $this->_replacement, $value);
+ }
+
+}
diff --git a/lib/zend/Zend/Filter/RealPath.php b/lib/zend/Zend/Filter/RealPath.php
new file mode 100644
index 00000000000..00881de5f52
--- /dev/null
+++ b/lib/zend/Zend/Filter/RealPath.php
@@ -0,0 +1,134 @@
+setExists($options);
+ }
+
+ /**
+ * Returns true if the filtered path must exist
+ *
+ * @return boolean
+ */
+ public function getExists()
+ {
+ return $this->_exists;
+ }
+
+ /**
+ * Sets if the path has to exist
+ * TRUE when the path must exist
+ * FALSE when not existing paths can be given
+ *
+ * @param boolean|Zend_Config $exists Path must exist
+ * @return Zend_Filter_RealPath
+ */
+ public function setExists($exists)
+ {
+ if ($exists instanceof Zend_Config) {
+ $exists = $exists->toArray();
+ }
+
+ if (is_array($exists)) {
+ if (isset($exists['exists'])) {
+ $exists = (boolean) $exists['exists'];
+ }
+ }
+
+ $this->_exists = (boolean) $exists;
+ return $this;
+ }
+
+ /**
+ * Defined by Zend_Filter_Interface
+ *
+ * Returns realpath($value)
+ *
+ * @param string $value
+ * @return string
+ */
+ public function filter($value)
+ {
+ $path = (string) $value;
+ if ($this->_exists) {
+ return realpath($path);
+ }
+
+ $realpath = @realpath($path);
+ if ($realpath) {
+ return $realpath;
+ }
+
+ $drive = '';
+ if (substr(PHP_OS, 0, 3) == 'WIN') {
+ $path = preg_replace('/[\\\\\/]/', DIRECTORY_SEPARATOR, $path);
+ if (preg_match('/([a-zA-Z]\:)(.*)/', $path, $matches)) {
+ list($fullMatch, $drive, $path) = $matches;
+ } else {
+ $cwd = getcwd();
+ $drive = substr($cwd, 0, 2);
+ if (substr($path, 0, 1) != DIRECTORY_SEPARATOR) {
+ $path = substr($cwd, 3) . DIRECTORY_SEPARATOR . $path;
+ }
+ }
+ } elseif (substr($path, 0, 1) != DIRECTORY_SEPARATOR) {
+ $path = getcwd() . DIRECTORY_SEPARATOR . $path;
+ }
+
+ $stack = array();
+ $parts = explode(DIRECTORY_SEPARATOR, $path);
+ foreach ($parts as $dir) {
+ if (strlen($dir) && $dir !== '.') {
+ if ($dir == '..') {
+ array_pop($stack);
+ } else {
+ array_push($stack, $dir);
+ }
+ }
+ }
+
+ return $drive . DIRECTORY_SEPARATOR . implode(DIRECTORY_SEPARATOR, $stack);
+ }
+}
diff --git a/lib/zend/Zend/Filter/StringToLower.php b/lib/zend/Zend/Filter/StringToLower.php
new file mode 100644
index 00000000000..b208cfe77a1
--- /dev/null
+++ b/lib/zend/Zend/Filter/StringToLower.php
@@ -0,0 +1,121 @@
+toArray();
+ } else if (!is_array($options)) {
+ $options = func_get_args();
+ $temp = array();
+ if (!empty($options)) {
+ $temp['encoding'] = array_shift($options);
+ }
+ $options = $temp;
+ }
+
+ if (!array_key_exists('encoding', $options) && function_exists('mb_internal_encoding')) {
+ $options['encoding'] = mb_internal_encoding();
+ }
+
+ if (array_key_exists('encoding', $options)) {
+ $this->setEncoding($options['encoding']);
+ }
+ }
+
+ /**
+ * Returns the set encoding
+ *
+ * @return string
+ */
+ public function getEncoding()
+ {
+ return $this->_encoding;
+ }
+
+ /**
+ * Set the input encoding for the given string
+ *
+ * @param string $encoding
+ * @return Zend_Filter_StringToLower Provides a fluent interface
+ * @throws Zend_Filter_Exception
+ */
+ public function setEncoding($encoding = null)
+ {
+ if ($encoding !== null) {
+ if (!function_exists('mb_strtolower')) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('mbstring is required for this feature');
+ }
+
+ $encoding = (string) $encoding;
+ if (!in_array(strtolower($encoding), array_map('strtolower', mb_list_encodings()))) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception("The given encoding '$encoding' is not supported by mbstring");
+ }
+ }
+
+ $this->_encoding = $encoding;
+ return $this;
+ }
+
+ /**
+ * Defined by Zend_Filter_Interface
+ *
+ * Returns the string $value, converting characters to lowercase as necessary
+ *
+ * @param string $value
+ * @return string
+ */
+ public function filter($value)
+ {
+ if ($this->_encoding !== null) {
+ return mb_strtolower((string) $value, $this->_encoding);
+ }
+
+ return strtolower((string) $value);
+ }
+}
diff --git a/lib/zend/Zend/Filter/StringToUpper.php b/lib/zend/Zend/Filter/StringToUpper.php
new file mode 100644
index 00000000000..8fe362055f2
--- /dev/null
+++ b/lib/zend/Zend/Filter/StringToUpper.php
@@ -0,0 +1,121 @@
+toArray();
+ } else if (!is_array($options)) {
+ $options = func_get_args();
+ $temp = array();
+ if (!empty($options)) {
+ $temp['encoding'] = array_shift($options);
+ }
+ $options = $temp;
+ }
+
+ if (!array_key_exists('encoding', $options) && function_exists('mb_internal_encoding')) {
+ $options['encoding'] = mb_internal_encoding();
+ }
+
+ if (array_key_exists('encoding', $options)) {
+ $this->setEncoding($options['encoding']);
+ }
+ }
+
+ /**
+ * Returns the set encoding
+ *
+ * @return string
+ */
+ public function getEncoding()
+ {
+ return $this->_encoding;
+ }
+
+ /**
+ * Set the input encoding for the given string
+ *
+ * @param string $encoding
+ * @return Zend_Filter_StringToUpper Provides a fluent interface
+ * @throws Zend_Filter_Exception
+ */
+ public function setEncoding($encoding = null)
+ {
+ if ($encoding !== null) {
+ if (!function_exists('mb_strtoupper')) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception('mbstring is required for this feature');
+ }
+
+ $encoding = (string) $encoding;
+ if (!in_array(strtolower($encoding), array_map('strtolower', mb_list_encodings()))) {
+ require_once 'Zend/Filter/Exception.php';
+ throw new Zend_Filter_Exception("The given encoding '$encoding' is not supported by mbstring");
+ }
+ }
+
+ $this->_encoding = $encoding;
+ return $this;
+ }
+
+ /**
+ * Defined by Zend_Filter_Interface
+ *
+ * Returns the string $value, converting characters to uppercase as necessary
+ *
+ * @param string $value
+ * @return string
+ */
+ public function filter($value)
+ {
+ if ($this->_encoding) {
+ return mb_strtoupper((string) $value, $this->_encoding);
+ }
+
+ return strtoupper((string) $value);
+ }
+}
diff --git a/lib/zend/Zend/Filter/StringTrim.php b/lib/zend/Zend/Filter/StringTrim.php
new file mode 100644
index 00000000000..4f86d89e2c0
--- /dev/null
+++ b/lib/zend/Zend/Filter/StringTrim.php
@@ -0,0 +1,124 @@
+toArray();
+ } else if (!is_array($options)) {
+ $options = func_get_args();
+ $temp['charlist'] = array_shift($options);
+ $options = $temp;
+ }
+
+ if (array_key_exists('charlist', $options)) {
+ $this->setCharList($options['charlist']);
+ }
+ }
+
+ /**
+ * Returns the charList option
+ *
+ * @return string|null
+ */
+ public function getCharList()
+ {
+ return $this->_charList;
+ }
+
+ /**
+ * Sets the charList option
+ *
+ * @param string|null $charList
+ * @return Zend_Filter_StringTrim Provides a fluent interface
+ */
+ public function setCharList($charList)
+ {
+ $this->_charList = $charList;
+ return $this;
+ }
+
+ /**
+ * Defined by Zend_Filter_Interface
+ *
+ * Returns the string $value with characters stripped from the beginning and end
+ *
+ * @param string $value
+ * @return string
+ */
+ public function filter($value)
+ {
+ if (null === $this->_charList) {
+ return $this->_unicodeTrim((string) $value);
+ } else {
+ return $this->_unicodeTrim((string) $value, $this->_charList);
+ }
+ }
+
+ /**
+ * Unicode aware trim method
+ * Fixes a PHP problem
+ *
+ * @param string $value
+ * @param string $charlist
+ * @return string
+ */
+ protected function _unicodeTrim($value, $charlist = '\\\\s')
+ {
+ $chars = preg_replace(
+ array( '/[\^\-\]\\\]/S', '/\\\{4}/S', '/\//'),
+ array( '\\\\\\0', '\\', '\/' ),
+ $charlist
+ );
+
+ $pattern = '^[' . $chars . ']*|[' . $chars . ']*$';
+ return preg_replace("/$pattern/sSD", '', $value);
+ }
+}
diff --git a/lib/zend/Zend/Filter/StripNewlines.php b/lib/zend/Zend/Filter/StripNewlines.php
new file mode 100644
index 00000000000..667c6aae240
--- /dev/null
+++ b/lib/zend/Zend/Filter/StripNewlines.php
@@ -0,0 +1,48 @@
+ Tags which are allowed
+ * 'allowAttribs' => Attributes which are allowed
+ * 'allowComments' => Are comments allowed ?
+ *
+ * @param string|array|Zend_Config $options
+ * @return void
+ */
+ public function __construct($options = null)
+ {
+ if ($options instanceof Zend_Config) {
+ $options = $options->toArray();
+ } else if ((!is_array($options)) || (is_array($options) && !array_key_exists('allowTags', $options) &&
+ !array_key_exists('allowAttribs', $options) && !array_key_exists('allowComments', $options))) {
+ $options = func_get_args();
+ $temp['allowTags'] = array_shift($options);
+ if (!empty($options)) {
+ $temp['allowAttribs'] = array_shift($options);
+ }
+
+ if (!empty($options)) {
+ $temp['allowComments'] = array_shift($options);
+ }
+
+ $options = $temp;
+ }
+
+ if (array_key_exists('allowTags', $options)) {
+ $this->setTagsAllowed($options['allowTags']);
+ }
+
+ if (array_key_exists('allowAttribs', $options)) {
+ $this->setAttributesAllowed($options['allowAttribs']);
+ }
+
+ if (array_key_exists('allowComments', $options)) {
+ $this->setCommentsAllowed($options['allowComments']);
+ }
+ }
+
+ /**
+ * Returns the commentsAllowed option
+ *
+ * This setting is now deprecated and ignored internally.
+ *
+ * @deprecated
+ * @return bool
+ */
+ public function getCommentsAllowed()
+ {
+ return $this->commentsAllowed;
+ }
+
+ /**
+ * Sets the commentsAllowed option
+ *
+ * This setting is now deprecated and ignored internally.
+ *
+ * @deprecated
+ * @param boolean $commentsAllowed
+ * @return Zend_Filter_StripTags Provides a fluent interface
+ */
+ public function setCommentsAllowed($commentsAllowed)
+ {
+ $this->commentsAllowed = (boolean) $commentsAllowed;
+ return $this;
+ }
+
+ /**
+ * Returns the tagsAllowed option
+ *
+ * @return array
+ */
+ public function getTagsAllowed()
+ {
+ return $this->_tagsAllowed;
+ }
+
+ /**
+ * Sets the tagsAllowed option
+ *
+ * @param array|string $tagsAllowed
+ * @return Zend_Filter_StripTags Provides a fluent interface
+ */
+ public function setTagsAllowed($tagsAllowed)
+ {
+ if (!is_array($tagsAllowed)) {
+ $tagsAllowed = array($tagsAllowed);
+ }
+
+ foreach ($tagsAllowed as $index => $element) {
+ // If the tag was provided without attributes
+ if (is_int($index) && is_string($element)) {
+ // Canonicalize the tag name
+ $tagName = strtolower($element);
+ // Store the tag as allowed with no attributes
+ $this->_tagsAllowed[$tagName] = array();
+ }
+ // Otherwise, if a tag was provided with attributes
+ else if (is_string($index) && (is_array($element) || is_string($element))) {
+ // Canonicalize the tag name
+ $tagName = strtolower($index);
+ // Canonicalize the attributes
+ if (is_string($element)) {
+ $element = array($element);
+ }
+ // Store the tag as allowed with the provided attributes
+ $this->_tagsAllowed[$tagName] = array();
+ foreach ($element as $attribute) {
+ if (is_string($attribute)) {
+ // Canonicalize the attribute name
+ $attributeName = strtolower($attribute);
+ $this->_tagsAllowed[$tagName][$attributeName] = null;
+ }
+ }
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Returns the attributesAllowed option
+ *
+ * @return array
+ */
+ public function getAttributesAllowed()
+ {
+ return $this->_attributesAllowed;
+ }
+
+ /**
+ * Sets the attributesAllowed option
+ *
+ * @param array|string $attributesAllowed
+ * @return Zend_Filter_StripTags Provides a fluent interface
+ */
+ public function setAttributesAllowed($attributesAllowed)
+ {
+ if (!is_array($attributesAllowed)) {
+ $attributesAllowed = array($attributesAllowed);
+ }
+
+ // Store each attribute as allowed
+ foreach ($attributesAllowed as $attribute) {
+ if (is_string($attribute)) {
+ // Canonicalize the attribute name
+ $attributeName = strtolower($attribute);
+ $this->_attributesAllowed[$attributeName] = null;
+ }
+ }
+
+ return $this;
+ }
+
+ /**
+ * Defined by Zend_Filter_Interface
+ *
+ * @todo improve docblock descriptions
+ *
+ * @param string $value
+ * @return string
+ */
+ public function filter($value)
+ {
+ $value = (string) $value;
+
+ // Strip HTML comments first
+ while (strpos($value, '
-
diff --git a/lib/zend/Zend/Service/DeveloperGarden/Wsdl/SmsValidationUserService.wsdl b/lib/zend/Zend/Service/DeveloperGarden/Wsdl/SmsValidationUserService.wsdl
deleted file mode 100644
index 18c2c7cda7d..00000000000
--- a/lib/zend/Zend/Service/DeveloperGarden/Wsdl/SmsValidationUserService.wsdl
+++ /dev/null
@@ -1,169 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/zend/Zend/Service/DeveloperGarden/Wsdl/TokenService.wsdl b/lib/zend/Zend/Service/DeveloperGarden/Wsdl/TokenService.wsdl
deleted file mode 100644
index 04d03ee45e8..00000000000
--- a/lib/zend/Zend/Service/DeveloperGarden/Wsdl/TokenService.wsdl
+++ /dev/null
@@ -1,353 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Telekom specific format id, e.g. there will be multiple
- different token formats derived from SAML 2.0 Assertions
-
-
-
-
-
-
-
-
-
-
- Telekom specific encoding id - there can be different
- encoding formats for the same token format, e.g. SAML
- Assertions can be encoded as plain XML or in
- base64-encoding
-
-
-
-
-
-
-
-
-
-
-
-
-
- format of the token carried by the response,
- determines syntax and processing rules for token
-
-
-
-
-
-
-
- encoding of the token carried by the response,
- determines syntax and processing rules for token
-
-
-
-
-
-
-
- contains the string representation of the
- security token - no further token format identifier
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- valid SAM Session Id
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/zend/Zend/Service/DeveloperGarden/Wsdl/VoiceButlerService.wsdl b/lib/zend/Zend/Service/DeveloperGarden/Wsdl/VoiceButlerService.wsdl
deleted file mode 100644
index c17a50ffd8a..00000000000
--- a/lib/zend/Zend/Service/DeveloperGarden/Wsdl/VoiceButlerService.wsdl
+++ /dev/null
@@ -1,164 +0,0 @@
-
- VoiceButlerService
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/zend/Zend/Service/DeveloperGarden/Wsdl/VoiceButlerService.xsd b/lib/zend/Zend/Service/DeveloperGarden/Wsdl/VoiceButlerService.xsd
deleted file mode 100644
index ef724672dd9..00000000000
--- a/lib/zend/Zend/Service/DeveloperGarden/Wsdl/VoiceButlerService.xsd
+++ /dev/null
@@ -1,264 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/zend/Zend/Service/DeveloperGarden/Wsdl/ccsPort.wsdl b/lib/zend/Zend/Service/DeveloperGarden/Wsdl/ccsPort.wsdl
deleted file mode 100644
index 07d9ed9424a..00000000000
--- a/lib/zend/Zend/Service/DeveloperGarden/Wsdl/ccsPort.wsdl
+++ /dev/null
@@ -1,463 +0,0 @@
-
-
-
-CCS
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/zend/Zend/Service/DeveloperGarden/Wsdl/ccsPort.xsd b/lib/zend/Zend/Service/DeveloperGarden/Wsdl/ccsPort.xsd
deleted file mode 100644
index d9c30670da0..00000000000
--- a/lib/zend/Zend/Service/DeveloperGarden/Wsdl/ccsPort.xsd
+++ /dev/null
@@ -1,736 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/zend/Zend/Service/DeveloperGarden/Wsdl/localsearch.wsdl b/lib/zend/Zend/Service/DeveloperGarden/Wsdl/localsearch.wsdl
deleted file mode 100644
index 5258bfc7b5a..00000000000
--- a/lib/zend/Zend/Service/DeveloperGarden/Wsdl/localsearch.wsdl
+++ /dev/null
@@ -1,83 +0,0 @@
-
-
-
-Local Search
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/zend/Zend/Service/DeveloperGarden/Wsdl/localsearch.xsd b/lib/zend/Zend/Service/DeveloperGarden/Wsdl/localsearch.xsd
deleted file mode 100644
index 51684be499c..00000000000
--- a/lib/zend/Zend/Service/DeveloperGarden/Wsdl/localsearch.xsd
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/zend/Zend/Service/Ebay/Abstract.php b/lib/zend/Zend/Service/Ebay/Abstract.php
new file mode 100644
index 00000000000..640475b33a8
--- /dev/null
+++ b/lib/zend/Zend/Service/Ebay/Abstract.php
@@ -0,0 +1,309 @@
+setOption($options);
+ }
+
+ /**
+ * @param string|Zend_Config|array $name
+ * @param mixed $value
+ * @return Zend_Service_Ebay_Abstract Provides a fluent interface
+ */
+ public function setOption($name, $value = null)
+ {
+ if ($name instanceof Zend_Config) {
+ $name = $name->toArray();
+ }
+ if (is_array($name)) {
+ $this->_options = $name + $this->_options;
+ } else {
+ $this->_options[$name] = $value;
+ }
+ return $this;
+ }
+
+ /**
+ * @param string $name
+ * @return mixed
+ */
+ public function getOption($name = null)
+ {
+ if (null === $name) {
+ return $this->_options;
+ }
+ if ($this->hasOption($name)) {
+ return $this->_options[$name];
+ }
+ return null;
+ }
+
+ /**
+ * @param string $name
+ * @return boolean
+ */
+ public function hasOption($name)
+ {
+ return array_key_exists($name, $this->_options);
+ }
+
+ /**
+ * @param mixed $client
+ * @return Zend_Service_Ebay_Abstract Provides a fluent interface
+ */
+ abstract public function setClient($client);
+
+ /**
+ * @return mixed
+ */
+ abstract public function getClient();
+
+ /**
+ * @param Zend_Config|array $options
+ * @throws Zend_Service_Ebay_Finding_Exception When $options is not an array neither a Zend_Config object
+ * @return array
+ */
+ public static function optionsToArray($options)
+ {
+ if (null === $options) {
+ $options = array();
+ } else if ($options instanceof Zend_Config) {
+ $options = $options->toArray();
+ }
+
+ if (!is_array($options)) {
+ /**
+ * @see Zend_Service_Ebay_Exception
+ */
+ require_once 'Zend/Service/Ebay/Exception.php';
+ throw new Zend_Service_Ebay_Exception('Invalid options provided.');
+ }
+
+ return $options;
+ }
+
+ /**
+ * Implements Name-value Syntax translator.
+ *
+ * Example:
+ *
+ * array(
+ * 'paginationInput' => array(
+ * 'entriesPerPage' => 5,
+ * 'pageNumber' => 2
+ * ),
+ * 'itemFilter' => array(
+ * array(
+ * 'name' => 'MaxPrice',
+ * 'value' => 25,
+ * 'paramName' => 'Currency',
+ * 'paramValue' => 'USD'
+ * ),
+ * array(
+ * 'name' => 'FreeShippingOnly',
+ * 'value' => true
+ * ),
+ * array(
+ * 'name' => 'ListingType',
+ * 'value' => array(
+ * 'AuctionWithBIN',
+ * 'FixedPrice',
+ * 'StoreInventory'
+ * )
+ * )
+ * ),
+ * 'productId' => array(
+ * '' => 123,
+ * 'type' => 'UPC'
+ * )
+ * )
+ *
+ * this above is translated to
+ *
+ * array(
+ * 'paginationInput.entriesPerPage' => '5',
+ * 'paginationInput.pageNumber' => '2',
+ * 'itemFilter(0).name' => 'MaxPrice',
+ * 'itemFilter(0).value' => '25',
+ * 'itemFilter(0).paramName' => 'Currency',
+ * 'itemFilter(0).paramValue' => 'USD',
+ * 'itemFilter(1).name' => 'FreeShippingOnly',
+ * 'itemFilter(1).value' => '1',
+ * 'itemFilter(2).name' => 'ListingType',
+ * 'itemFilter(2).value(0)' => 'AuctionWithBIN',
+ * 'itemFilter(2).value(1)' => 'FixedPrice',
+ * 'itemFilter(2).value(2)' => 'StoreInventory',
+ * 'productId' => '123',
+ * 'productId.@type' => 'UPC'
+ * )
+ *
+ * @param Zend_Config|array $options
+ * @link http://developer.ebay.com/DevZone/finding/Concepts/MakingACall.html#nvsyntax
+ * @return array A simple array of strings
+ */
+ protected function _optionsToNameValueSyntax($options)
+ {
+ $options = self::optionsToArray($options);
+ ksort($options);
+ $new = array();
+ $runAgain = false;
+ foreach ($options as $name => $value) {
+ if (is_array($value)) {
+ // parse an array value, check if it is associative
+ $keyRaw = array_keys($value);
+ $keyNumber = range(0, count($value) - 1);
+ $isAssoc = count(array_diff($keyRaw, $keyNumber)) > 0;
+ // check for tag representation, like
+ // empty key refers to text value
+ // when there is a root tag, attributes receive flags
+ $hasAttribute = array_key_exists('', $value);
+ foreach ($value as $subName => $subValue) {
+ // generate new key name
+ if ($isAssoc) {
+ // named keys
+ $newName = $name;
+ if ($subName !== '') {
+ // when $subName is empty means that current value
+ // is the main value for the main key
+ $glue = $hasAttribute ? '.@' : '.';
+ $newName .= $glue . $subName;
+ }
+ } else {
+ // numeric keys
+ $newName = $name . '(' . $subName . ')';
+ }
+ // save value
+ if (is_array($subValue)) {
+ // it is necessary run this again, value is an array
+ $runAgain = true;
+ } else {
+ // parse basic type
+ $subValue = self::toEbayValue($subValue);
+ }
+ $new[$newName] = $subValue;
+ }
+ } else {
+ // parse basic type
+ $new[$name] = self::toEbayValue($value);
+ }
+ }
+ if ($runAgain) {
+ // this happens if any $subValue found is an array
+ $new = $this->_optionsToNameValueSyntax($new);
+ }
+ return $new;
+ }
+
+ /**
+ * Translate native PHP values format to ebay format for request.
+ *
+ * Boolean is translated to "0" or "1", date object generates ISO 8601,
+ * everything else is translated to string.
+ *
+ * @param mixed $value
+ * @return string
+ */
+ public static function toEbayValue($value)
+ {
+ if (is_bool($value)) {
+ $value = $value ? '1' : '0';
+ } else if ($value instanceof Zend_Date) {
+ $value = $value->getIso();
+ } else if ($value instanceof DateTime) {
+ $value = $value->format(DateTime::ISO8601);
+ } else {
+ $value = (string) $value;
+ }
+ return $value;
+ }
+
+ /**
+ * Translate an ebay value format to native PHP type.
+ *
+ * @param string $value
+ * @param string $type
+ * @see http://developer.ebay.com/DevZone/finding/CallRef/types/simpleTypes.html
+ * @throws Zend_Service_Ebay_Finding_Exception When $type is not valid
+ * @return mixed
+ */
+ public static function toPhpValue($value, $type)
+ {
+ switch ($type) {
+ // cast for: boolean
+ case 'boolean':
+ $value = (string) $value == 'true';
+ break;
+
+ // cast for: Amount, decimal, double, float, MeasureType
+ case 'float':
+ $value = floatval((string) $value);
+ break;
+
+ // cast for: int, long
+ // integer type generates a string value, because 32 bit systems
+ // have an integer range of -2147483648 to 2147483647
+ case 'integer':
+ // break intentionally omitted
+
+ // cast for: anyURI, base64Binary, dateTime, duration, string, token
+ case 'string':
+ $value = (string) $value;
+ break;
+
+ default:
+ /**
+ * @see Zend_Service_Ebay_Exception
+ */
+ require_once 'Zend/Service/Ebay/Exception.php';
+ throw new Zend_Service_Ebay_Exception("Invalid type '{$type}'.");
+ }
+ return $value;
+ }
+}
diff --git a/lib/zend/Zend/Service/Technorati/Exception.php b/lib/zend/Zend/Service/Ebay/Exception.php
similarity index 71%
rename from lib/zend/Zend/Service/Technorati/Exception.php
rename to lib/zend/Zend/Service/Ebay/Exception.php
index 88a34cd4db7..58577da8a5c 100644
--- a/lib/zend/Zend/Service/Technorati/Exception.php
+++ b/lib/zend/Zend/Service/Ebay/Exception.php
@@ -14,26 +14,24 @@
*
* @category Zend
* @package Zend_Service
- * @subpackage Technorati
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @subpackage Ebay
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id$
+ * @version $Id: Exception.php 20166 2010-01-09 19:00:17Z bkarwin $
*/
-
/**
* @see Zend_Service_Exception
*/
require_once 'Zend/Service/Exception.php';
-
/**
* @category Zend
* @package Zend_Service
- * @subpackage Technorati
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @subpackage Ebay
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
+ * @uses Zend_Service_Exception
*/
-class Zend_Service_Technorati_Exception extends Zend_Service_Exception
-{
-}
+class Zend_Service_Ebay_Exception extends Zend_Service_Exception
+{}
diff --git a/lib/zend/Zend/Service/Ebay/Finding.php b/lib/zend/Zend/Service/Ebay/Finding.php
new file mode 100644
index 00000000000..a5fd4ae64f5
--- /dev/null
+++ b/lib/zend/Zend/Service/Ebay/Finding.php
@@ -0,0 +1,424 @@
+ 'http://www.ebay.com/marketplace/search/v1/services',
+ self::XMLNS_MS => 'http://www.ebay.com/marketplace/services'
+ );
+
+ /**
+ *
+ * @var array
+ */
+ protected $_options = array(
+ self::OPTION_GLOBAL_ID => 'EBAY-US'
+ );
+
+ /**
+ * @return array
+ */
+ public static function getXmlNamespaces()
+ {
+ return self::$_xmlNamespaces;
+ }
+
+ /**
+ * @param Zend_Config|array|string $options Application Id or array of options
+ * @throws Zend_Service_Ebay_Finding_Exception When application id is missing
+ * @return void
+ */
+ public function __construct($options)
+ {
+ // prepare options
+ if (is_string($options)) {
+ // application id was given
+ $options = array(self::OPTION_APP_ID => $options);
+ } else {
+ // check application id
+ $options = parent::optionsToArray($options);
+ if (!array_key_exists(self::OPTION_APP_ID, $options)) {
+ /**
+ * @see Zend_Service_Ebay_Finding_Exception
+ */
+ require_once 'Zend/Service/Ebay/Finding/Exception.php';
+ throw new Zend_Service_Ebay_Finding_Exception(
+ 'Application Id is missing.');
+ }
+ }
+
+ // load options
+ parent::setOption($options);
+ }
+
+ /**
+ * @param Zend_Rest_Client $client
+ * @return Zend_Service_Ebay_Finding Provides a fluent interface
+ */
+ public function setClient($client)
+ {
+ if (!$client instanceof Zend_Rest_Client) {
+ /**
+ * @see Zend_Service_Ebay_Finding_Exception
+ */
+ require_once 'Zend/Service/Ebay/Finding/Exception.php';
+ throw new Zend_Service_Ebay_Finding_Exception(
+ 'Client object must extend Zend_Rest_Client.');
+ }
+ $this->_client = $client;
+
+ return $this;
+ }
+
+ /**
+ * @return Zend_Rest_Client
+ */
+ public function getClient()
+ {
+ if (!$this->_client instanceof Zend_Rest_Client) {
+ /**
+ * @see Zend_Rest_Client
+ */
+ require_once 'Zend/Rest/Client.php';
+ $this->_client = new Zend_Rest_Client();
+ }
+ return $this->_client;
+ }
+
+ /**
+ * Finds items by a keyword query and/or category and allows searching
+ * within item descriptions.
+ *
+ * @param string $keywords
+ * @param boolean $descriptionSearch
+ * @param integer $categoryId
+ * @param Zend_Config|array $options
+ * @link http://developer.ebay.com/DevZone/finding/CallRef/findItemsAdvanced.html
+ * @return Zend_Service_Ebay_Finding_Response_Items
+ */
+ public function findItemsAdvanced($keywords, $descriptionSearch = true, $categoryId = null, $options = null)
+ {
+ // prepare options
+ $options = parent::optionsToArray($options);
+ $options['keywords'] = $keywords;
+ $options['descriptionSearch'] = $descriptionSearch;
+ if (!empty($categoryId)) {
+ $options['categoryId'] = $categoryId;
+ }
+
+ // do request
+ return $this->_findItems($options, 'findItemsAdvanced');
+ }
+
+ /**
+ * Finds items in a specific category. Results can be filtered and sorted.
+ *
+ * @param integer $categoryId
+ * @param Zend_Config|array $options
+ * @link http://developer.ebay.com/DevZone/finding/CallRef/findItemsByCategory.html
+ * @return Zend_Service_Ebay_Finding_Response_Items
+ */
+ public function findItemsByCategory($categoryId, $options = null)
+ {
+ // prepare options
+ $options = parent::optionsToArray($options);
+ $options['categoryId'] = $categoryId;
+
+ // do request
+ return $this->_findItems($options, 'findItemsByCategory');
+ }
+
+ /**
+ * Finds items on eBay based upon a keyword query and returns details for
+ * matching items.
+ *
+ * @param string $keywords
+ * @param Zend_Config|array $options
+ * @link http://developer.ebay.com/DevZone/finding/CallRef/findItemsByKeywords.html
+ * @return Zend_Service_Ebay_Finding_Response_Items
+ */
+ public function findItemsByKeywords($keywords, $options = null)
+ {
+ // prepare options
+ $options = parent::optionsToArray($options);
+ $options['keywords'] = $keywords;
+
+ // do request
+ return $this->_findItems($options, 'findItemsByKeywords');
+ }
+
+ /**
+ * Finds items based upon a product ID, such as an ISBN, UPC, EAN, or ePID.
+ *
+ * @param integer $productId
+ * @param string $productIdType Default value is ReferenceID
+ * @param Zend_Config|array $options
+ * @link http://developer.ebay.com/DevZone/finding/CallRef/findItemsByProduct.html
+ * @return Zend_Service_Ebay_Finding_Response_Items
+ */
+ public function findItemsByProduct($productId, $productIdType = null, $options = null)
+ {
+ if (null == $productIdType) {
+ $productIdType = 'ReferenceID';
+ }
+
+ // prepare options
+ $options = parent::optionsToArray($options);
+ $options['productId'] = array('' => $productId,
+ 'type' => $productIdType);
+
+ // do request
+ return $this->_findItems($options, 'findItemsByProduct');
+ }
+
+ /**
+ * Finds items in eBay stores. Can search a specific store or can search all
+ * stores with a keyword query.
+ *
+ * @param string $storeName
+ * @param Zend_Config|array $options
+ * @link http://developer.ebay.com/DevZone/finding/CallRef/findItemsIneBayStores.html
+ * @return Zend_Service_Ebay_Finding_Response_Items
+ */
+ public function findItemsInEbayStores($storeName, $options = null)
+ {
+ // prepare options
+ $options = parent::optionsToArray($options);
+ $options['storeName'] = $storeName;
+
+ // do request
+ return $this->_findItems($options, 'findItemsIneBayStores');
+ }
+
+ /**
+ * @param array $options
+ * @param string $operation
+ * @return Zend_Service_Ebay_Finding_Response_Items
+ */
+ protected function _findItems(array $options, $operation)
+ {
+ // set default output selector value
+ if (!array_key_exists('outputSelector', $options)) {
+ $options['outputSelector'] = array('AspectHistogram',
+ 'CategoryHistogram',
+ 'SellerInfo',
+ 'StoreInfo');
+ }
+
+ // do request
+ $dom = $this->_request($operation, $options);
+
+ /**
+ * @see Zend_Service_Ebay_Finding_Response_Items
+ */
+ require_once 'Zend/Service/Ebay/Finding/Response/Items.php';
+ $response = new Zend_Service_Ebay_Finding_Response_Items($dom->firstChild);
+ return $response->setOperation($operation)
+ ->setOption($options);
+ }
+
+ /**
+ * Gets category and/or aspect metadata for the specified category.
+ *
+ * @param integer $categoryId
+ * @param Zend_Config|array $options
+ * @link http://developer.ebay.com/DevZone/finding/CallRef/getHistograms.html
+ * @return Zend_Service_Ebay_Finding_Response_Histograms
+ */
+ public function getHistograms($categoryId, $options = null)
+ {
+ // prepare options
+ $options = parent::optionsToArray($options);
+ $options['categoryId'] = $categoryId;
+
+ // do request
+ $operation = 'getHistograms';
+ $dom = $this->_request($operation, $options);
+
+ /**
+ * @see Zend_Service_Ebay_Finding_Response_Histograms
+ */
+ require_once 'Zend/Service/Ebay/Finding/Response/Histograms.php';
+ $response = new Zend_Service_Ebay_Finding_Response_Histograms($dom->firstChild);
+ return $response->setOperation($operation)
+ ->setOption($options);
+ }
+
+ /**
+ * Checks specified keywords and returns correctly spelled keywords for best
+ * search results.
+ *
+ * @param string $keywords
+ * @param Zend_Config|array $options
+ * @link http://developer.ebay.com/DevZone/finding/CallRef/getSearchKeywordsRecommendation.html
+ * @return Zend_Service_Ebay_Finding_Response_Keywords
+ */
+ public function getSearchKeywordsRecommendation($keywords, $options = null)
+ {
+ // prepare options
+ $options = parent::optionsToArray($options);
+ $options['keywords'] = $keywords;
+
+ // do request
+ $operation = 'getSearchKeywordsRecommendation';
+ $dom = $this->_request($operation, $options);
+
+ /**
+ * @see Zend_Service_Ebay_Finding_Response_Keywords
+ */
+ require_once 'Zend/Service/Ebay/Finding/Response/Keywords.php';
+ $response = new Zend_Service_Ebay_Finding_Response_Keywords($dom->firstChild);
+ return $response->setOperation($operation)
+ ->setOption($options);
+ }
+
+ /**
+ * @param string $operation
+ * @param array $options
+ * @link http://developer.ebay.com/DevZone/finding/Concepts/MakingACall.html#StandardURLParameters
+ * @return DOMDocument
+ */
+ protected function _request($operation, array $options = null)
+ {
+ // generate default options
+ // constructor load global-id and application-id values
+ $default = array('OPERATION-NAME' => $operation,
+ 'SERVICE-NAME' => self::SERVICE_NAME,
+ 'SERVICE-VERSION' => self::SERVICE_VERSION,
+ 'GLOBAL-ID' => $this->getOption(self::OPTION_GLOBAL_ID),
+ 'SECURITY-APPNAME' => $this->getOption(self::OPTION_APP_ID),
+ 'RESPONSE-DATA-FORMAT' => self::RESPONSE_DATA_FORMAT,
+ 'REST-PAYLOAD' => '');
+
+ // prepare options to ebay syntax
+ $options = $default + $this->_optionsToNameValueSyntax($options);
+
+ // do request
+ $client = $this->getClient();
+ $client->getHttpClient()->resetParameters();
+ $response = $client->setUri(self::ENDPOINT_URI)
+ ->restGet(self::ENDPOINT_PATH, $options);
+
+ return $this->_parseResponse($response);
+ }
+
+ /**
+ * Search for error from request.
+ *
+ * If any error is found a DOMDocument is returned, this object contains a
+ * DOMXPath object as "ebayFindingXPath" attribute.
+ *
+ * @param Zend_Http_Response $response
+ * @link http://developer.ebay.com/DevZone/finding/CallRef/types/ErrorSeverity.html
+ * @see Zend_Service_Ebay_Finding_Abstract::_initXPath()
+ * @throws Zend_Service_Ebay_Finding_Exception When any error occurrs during request
+ * @return DOMDocument
+ */
+ protected function _parseResponse(Zend_Http_Response $response)
+ {
+ // error message
+ $message = '';
+
+ // first trying, loading XML
+ $dom = new DOMDocument();
+ if (!$dom = @Zend_Xml_Security::scan($response->getBody(), $dom)) {
+ $message = 'It was not possible to load XML returned.';
+ }
+
+ // second trying, check request status
+ if ($response->isError()) {
+ $message = $response->getMessage()
+ . ' (HTTP status code #' . $response->getStatus() . ')';
+ }
+
+ // third trying, search for error message into XML response
+ // only first error that contains severiry=Error is read
+ $xpath = new DOMXPath($dom);
+ foreach (self::$_xmlNamespaces as $alias => $uri) {
+ $xpath->registerNamespace($alias, $uri);
+ }
+ $ns = self::XMLNS_FINDING;
+ $nsMs = self::XMLNS_MS;
+ $expression = "//$nsMs:errorMessage[1]/$ns:error/$ns:severity[.='Error']";
+ $severityNode = $xpath->query($expression)->item(0);
+ if ($severityNode) {
+ $errorNode = $severityNode->parentNode;
+ // ebay message
+ $messageNode = $xpath->query("//$ns:message[1]", $errorNode)->item(0);
+ if ($messageNode) {
+ $message = 'eBay error: ' . $messageNode->nodeValue;
+ } else {
+ $message = 'eBay error: unknown';
+ }
+ // ebay error id
+ $errorIdNode = $xpath->query("//$ns:errorId[1]", $errorNode)->item(0);
+ if ($errorIdNode) {
+ $message .= ' (#' . $errorIdNode->nodeValue . ')';
+ }
+ }
+
+ // throw exception when an error was detected
+ if (strlen($message) > 0) {
+ /**
+ * @see Zend_Service_Ebay_Finding_Exception
+ */
+ require_once 'Zend/Service/Ebay/Finding/Exception.php';
+ throw new Zend_Service_Ebay_Finding_Exception($message);
+ }
+
+ // add xpath to dom document
+ // it allows service_ebay_finding classes use this
+ $dom->ebayFindingXPath = $xpath;
+
+ return $dom;
+ }
+}
diff --git a/lib/zend/Zend/Service/Ebay/Finding/Abstract.php b/lib/zend/Zend/Service/Ebay/Finding/Abstract.php
new file mode 100644
index 00000000000..be025a817b8
--- /dev/null
+++ b/lib/zend/Zend/Service/Ebay/Finding/Abstract.php
@@ -0,0 +1,169 @@
+_dom = $dom;
+ $this->_initXPath();
+ $this->_init();
+ }
+
+ /**
+ * @param string $tag
+ * @param string $attribute
+ * @return mixed
+ */
+ public function attributes($tag, $attribute = null)
+ {
+ if (null === $attribute) {
+ // all attributes
+ if (array_key_exists($tag, $this->_attributes)) {
+ return $this->_attributes[$tag];
+ }
+ return array();
+ }
+
+ // a specific attribute
+ if (isset($this->_attributes[$tag][$attribute])) {
+ return $this->_attributes[$tag][$attribute];
+ }
+ return null;
+ }
+
+ /**
+ * Initialize object.
+ *
+ * Post construct logic, classes must read their members here. Called from
+ * {@link __construct()} as final step of object initialization.
+ *
+ * @return void
+ */
+ protected function _init()
+ {
+ }
+
+ /**
+ * Load DOMXPath for current DOM object.
+ *
+ * @see Zend_Service_Ebay_Finding::_parseResponse()
+ * @return void
+ */
+ protected function _initXPath()
+ {
+ $document = $this->_dom->ownerDocument;
+ if (!isset($document->ebayFindingXPath)) {
+ $xpath = new DOMXPath($document);
+ foreach (Zend_Service_Ebay_Finding::getXmlNamespaces() as $alias => $uri) {
+ $xpath->registerNamespace($alias, $uri);
+ }
+ $document->ebayFindingXPath = $xpath;
+ }
+ $this->_xPath = $document->ebayFindingXPath;
+ }
+
+ /**
+ * @return DOMElement
+ */
+ public function getDom()
+ {
+ return $this->_dom;
+ }
+
+ /**
+ * @return DOMXPath
+ */
+ public function getXPath()
+ {
+ return $this->_xPath;
+ }
+
+ /**
+ * @param string $path
+ * @param string $type
+ * @param string $array When true means it expects more than one node occurence
+ * @return mixed
+ */
+ protected function _query($path, $type, $array = false)
+ {
+ // find values
+ $values = array();
+ $nodes = $this->_xPath->query($path, $this->_dom);
+ foreach ($nodes as $node) {
+ $value = (string) $node->nodeValue;
+ $values[] = Zend_Service_Ebay_Abstract::toPhpValue($value, $type);
+ if (!$array) {
+ break;
+ }
+ }
+
+ // array
+ if ($array) {
+ return $values;
+ }
+
+ // single value
+ if (count($values)) {
+ return reset($values);
+ }
+
+ // no nodes fount
+ return null;
+ }
+}
diff --git a/lib/zend/Zend/Service/Ebay/Finding/Aspect.php b/lib/zend/Zend/Service/Ebay/Finding/Aspect.php
new file mode 100644
index 00000000000..df1b66bc0f0
--- /dev/null
+++ b/lib/zend/Zend/Service/Ebay/Finding/Aspect.php
@@ -0,0 +1,68 @@
+_attributes['valueHistogram'] = array(
+ 'valueName' => $this->_query(".//$ns:valueHistogram/@valueName", 'string', true)
+ );
+
+ $nodes = $this->_xPath->query(".//$ns:valueHistogram", $this->_dom);
+ if ($nodes->length > 0) {
+ /**
+ * @see Zend_Service_Ebay_Finding_Aspect_Histogram_Value_Set
+ */
+ require_once 'Zend/Service/Ebay/Finding/Aspect/Histogram/Value/Set.php';
+ $this->valueHistogram = new Zend_Service_Ebay_Finding_Aspect_Histogram_Value_Set($nodes);
+ }
+ }
+}
diff --git a/lib/zend/Zend/Service/Ebay/Finding/Aspect/Histogram/Container.php b/lib/zend/Zend/Service/Ebay/Finding/Aspect/Histogram/Container.php
new file mode 100644
index 00000000000..862e53430ef
--- /dev/null
+++ b/lib/zend/Zend/Service/Ebay/Finding/Aspect/Histogram/Container.php
@@ -0,0 +1,106 @@
+domainDisplayName = $this->_query(".//$ns:domainDisplayName[1]", 'string');
+ $this->domainName = $this->_query(".//$ns:domainName[1]", 'string');
+
+ $this->_attributes['aspect'] = array(
+ 'name' => $this->_query(".//$ns:aspect/@name", 'string', true)
+ );
+
+ $nodes = $this->_xPath->query(".//$ns:aspect", $this->_dom);
+ if ($nodes->length > 0) {
+ /**
+ * @see Zend_Service_Ebay_Finding_Aspect_Set
+ */
+ require_once 'Zend/Service/Ebay/Finding/Aspect/Set.php';
+ $this->aspect = new Zend_Service_Ebay_Finding_Aspect_Set($nodes);
+ }
+ }
+}
diff --git a/lib/zend/Zend/Service/DeveloperGarden/Response/ConferenceCall/AddConferenceTemplateParticipantResponseType.php b/lib/zend/Zend/Service/Ebay/Finding/Aspect/Histogram/Value.php
similarity index 50%
rename from lib/zend/Zend/Service/DeveloperGarden/Response/ConferenceCall/AddConferenceTemplateParticipantResponseType.php
rename to lib/zend/Zend/Service/Ebay/Finding/Aspect/Histogram/Value.php
index 5593ca9e630..8ca1ce35a08 100644
--- a/lib/zend/Zend/Service/DeveloperGarden/Response/ConferenceCall/AddConferenceTemplateParticipantResponseType.php
+++ b/lib/zend/Zend/Service/Ebay/Finding/Aspect/Histogram/Value.php
@@ -14,42 +14,43 @@
*
* @category Zend
* @package Zend_Service
- * @subpackage DeveloperGarden
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @subpackage Ebay
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id$
+ * @version $Id: Value.php 22791 2010-08-04 16:11:47Z renanbr $
*/
/**
- * @see Zend_Service_DeveloperGarden_Response_ConferenceCall_ConferenceCallAbstract
+ * @see Zend_Service_Ebay_Finding_Abstract
*/
-require_once 'Zend/Service/DeveloperGarden/Response/BaseType.php';
+require_once 'Zend/Service/Ebay/Finding/Abstract.php';
/**
* @category Zend
* @package Zend_Service
- * @subpackage DeveloperGarden
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
- * @author Marco Kaiser
+ * @subpackage Ebay
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
+ * @uses Zend_Service_Ebay_Finding_Abstract
*/
-class Zend_Service_DeveloperGarden_Response_ConferenceCall_AddConferenceTemplateParticipantResponseType
- extends Zend_Service_DeveloperGarden_Response_BaseType
+class Zend_Service_Ebay_Finding_Aspect_Histogram_Value extends Zend_Service_Ebay_Finding_Abstract
{
/**
- * the participant Id
+ * Number of items that share the characteristic the respective aspect
+ * value.
*
- * @var string
+ * @var integer
*/
- public $participantId = null;
+ public $count;
/**
- * return the participant id
- *
- * @return string
+ * @return void
*/
- public function getParticipantId()
+ protected function _init()
{
- return $this->participantId;
+ parent::_init();
+ $ns = Zend_Service_Ebay_Finding::XMLNS_FINDING;
+
+ $this->count = $this->_query(".//$ns:count[1]", 'integer');
}
}
diff --git a/lib/zend/Zend/Service/Ebay/Finding/Aspect/Histogram/Value/Set.php b/lib/zend/Zend/Service/Ebay/Finding/Aspect/Histogram/Value/Set.php
new file mode 100644
index 00000000000..7b236267cd6
--- /dev/null
+++ b/lib/zend/Zend/Service/Ebay/Finding/Aspect/Histogram/Value/Set.php
@@ -0,0 +1,57 @@
+_nodes->item($this->_key);
+ if (!$node) {
+ return null;
+ }
+
+ /**
+ * @see Zend_Service_Ebay_Finding_Aspect_Histogram_Value
+ */
+ require_once 'Zend/Service/Ebay/Finding/Aspect/Histogram/Value.php';
+ return new Zend_Service_Ebay_Finding_Aspect_Histogram_Value($node);
+ }
+}
diff --git a/lib/zend/Zend/Service/Ebay/Finding/Aspect/Set.php b/lib/zend/Zend/Service/Ebay/Finding/Aspect/Set.php
new file mode 100644
index 00000000000..1ba41bf70a1
--- /dev/null
+++ b/lib/zend/Zend/Service/Ebay/Finding/Aspect/Set.php
@@ -0,0 +1,57 @@
+_nodes->item($this->_key);
+ if (!$node) {
+ return null;
+ }
+
+ /**
+ * @see Zend_Service_Ebay_Finding_Aspect
+ */
+ require_once 'Zend/Service/Ebay/Finding/Aspect.php';
+ return new Zend_Service_Ebay_Finding_Aspect($node);
+ }
+}
diff --git a/lib/zend/Zend/Service/Ebay/Finding/Category.php b/lib/zend/Zend/Service/Ebay/Finding/Category.php
new file mode 100644
index 00000000000..f16e35a8c13
--- /dev/null
+++ b/lib/zend/Zend/Service/Ebay/Finding/Category.php
@@ -0,0 +1,73 @@
+categoryId = $this->_query(".//$ns:categoryId[1]", 'string');
+ $this->categoryName = $this->_query(".//$ns:categoryName[1]", 'string');
+ }
+
+ /**
+ * @param Zend_Service_Ebay_Finding $proxy
+ * @param Zend_Config|array $options
+ * @return Zend_Service_Ebay_Finding_Response_Items
+ */
+ public function findItems(Zend_Service_Ebay_Finding $proxy, $options = null)
+ {
+ return $proxy->findItemsByCategory($this->categoryId, $options);
+ }
+}
diff --git a/lib/zend/Zend/Service/Ebay/Finding/Category/Histogram.php b/lib/zend/Zend/Service/Ebay/Finding/Category/Histogram.php
new file mode 100644
index 00000000000..f126242bf46
--- /dev/null
+++ b/lib/zend/Zend/Service/Ebay/Finding/Category/Histogram.php
@@ -0,0 +1,77 @@
+count = $this->_query(".//$ns:count[1]", 'integer');
+
+ $nodes = $this->_xPath->query(".//$ns:childCategoryHistogram", $this->_dom);
+ if ($nodes->length > 0) {
+ /**
+ * @see Zend_Service_Ebay_Finding_Category_Histogram_Set
+ */
+ require_once 'Zend/Service/Ebay/Finding/Category/Histogram/Set.php';
+ $this->childCategoryHistogram = new Zend_Service_Ebay_Finding_Category_Histogram_Set($nodes);
+ }
+ }
+}
diff --git a/lib/zend/Zend/Service/Ebay/Finding/Category/Histogram/Container.php b/lib/zend/Zend/Service/Ebay/Finding/Category/Histogram/Container.php
new file mode 100644
index 00000000000..41a26bb1104
--- /dev/null
+++ b/lib/zend/Zend/Service/Ebay/Finding/Category/Histogram/Container.php
@@ -0,0 +1,66 @@
+_xPath->query(".//$ns:categoryHistogram", $this->_dom);
+ if ($nodes->length > 0) {
+ /**
+ * @see Zend_Service_Ebay_Finding_Category_Histogram_Set
+ */
+ require_once 'Zend/Service/Ebay/Finding/Category/Histogram/Set.php';
+ $this->categoryHistogram = new Zend_Service_Ebay_Finding_Category_Histogram_Set($nodes);
+ }
+ }
+}
diff --git a/lib/zend/Zend/Service/Ebay/Finding/Category/Histogram/Set.php b/lib/zend/Zend/Service/Ebay/Finding/Category/Histogram/Set.php
new file mode 100644
index 00000000000..1415bc3b91d
--- /dev/null
+++ b/lib/zend/Zend/Service/Ebay/Finding/Category/Histogram/Set.php
@@ -0,0 +1,57 @@
+_nodes->item($this->_key);
+ if (!$node) {
+ return null;
+ }
+
+ /**
+ * @see Zend_Service_Ebay_Finding_Category_Histogram
+ */
+ require_once 'Zend/Service/Ebay/Finding/Category/Histogram.php';
+ return new Zend_Service_Ebay_Finding_Category_Histogram($node);
+ }
+}
diff --git a/lib/zend/Zend/Service/Ebay/Finding/Error/Data.php b/lib/zend/Zend/Service/Ebay/Finding/Error/Data.php
new file mode 100644
index 00000000000..977d86afadb
--- /dev/null
+++ b/lib/zend/Zend/Service/Ebay/Finding/Error/Data.php
@@ -0,0 +1,158 @@
+category = $this->_query(".//$ns:category[1]", 'string');
+ $this->domain = $this->_query(".//$ns:domain[1]", 'string');
+ $this->errorId = $this->_query(".//$ns:errorId[1]", 'integer');
+ $this->exceptionId = $this->_query(".//$ns:exceptionId[1]", 'string');
+ $this->message = $this->_query(".//$ns:message[1]", 'string');
+ $this->parameter = $this->_query(".//$ns:parameter", 'string', true);
+ $this->severity = $this->_query(".//$ns:severity[1]", 'string');
+ $this->subdomain = $this->_query(".//$ns:subdomain[1]", 'string');
+
+ $this->_attributes['parameter'] = array(
+ 'name' => $this->_query(".//$ns:parameter/@name", 'string', true)
+ );
+ }
+}
diff --git a/lib/zend/Zend/Service/Ebay/Finding/Error/Data/Set.php b/lib/zend/Zend/Service/Ebay/Finding/Error/Data/Set.php
new file mode 100644
index 00000000000..5bafbf31585
--- /dev/null
+++ b/lib/zend/Zend/Service/Ebay/Finding/Error/Data/Set.php
@@ -0,0 +1,57 @@
+_nodes->item($this->_key);
+ if (!$node) {
+ return null;
+ }
+
+ /**
+ * @see Zend_Service_Ebay_Finding_Error_Data
+ */
+ require_once 'Zend/Service/Ebay/Finding/Error/Data.php';
+ return new Zend_Service_Ebay_Finding_Error_Data($node);
+ }
+}
diff --git a/lib/zend/Zend/Service/Ebay/Finding/Error/Message.php b/lib/zend/Zend/Service/Ebay/Finding/Error/Message.php
new file mode 100644
index 00000000000..24128ec7418
--- /dev/null
+++ b/lib/zend/Zend/Service/Ebay/Finding/Error/Message.php
@@ -0,0 +1,60 @@
+_xPath->query(".//$ns:error", $this->_dom);
+ if ($nodes->length > 0) {
+ /**
+ * @see Zend_Service_Ebay_Finding_Error_Data_Set
+ */
+ require_once 'Zend/Service/Ebay/Finding/Error/Data/Set.php';
+ $this->error = new Zend_Service_Ebay_Finding_Error_Data_Set($nodes);
+ }
+ }
+}
diff --git a/lib/zend/Zend/Service/DeveloperGarden/LocalSearch/Exception.php b/lib/zend/Zend/Service/Ebay/Finding/Exception.php
similarity index 63%
rename from lib/zend/Zend/Service/DeveloperGarden/LocalSearch/Exception.php
rename to lib/zend/Zend/Service/Ebay/Finding/Exception.php
index 6c667406dbf..403a9d38b96 100644
--- a/lib/zend/Zend/Service/DeveloperGarden/LocalSearch/Exception.php
+++ b/lib/zend/Zend/Service/Ebay/Finding/Exception.php
@@ -14,25 +14,24 @@
*
* @category Zend
* @package Zend_Service
- * @subpackage DeveloperGarden
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @subpackage Ebay
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @version $Id$
+ * @version $Id: Exception.php 20166 2010-01-09 19:00:17Z bkarwin $
*/
/**
- * Zend_Service_Exception
+ * @see Zend_Service_Exception
*/
-require_once 'Zend/Service/DeveloperGarden/Exception.php';
+require_once 'Zend/Service/Ebay/Exception.php';
/**
* @category Zend
* @package Zend_Service
- * @subpackage DeveloperGarden
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
- * @author Marco Kaiser
+ * @subpackage Ebay
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
+ * @uses Zend_Service_Ebay_Exception
*/
-class Zend_Service_DeveloperGarden_LocalSearch_Exception extends Zend_Service_DeveloperGarden_Exception
-{
-}
+class Zend_Service_Ebay_Finding_Exception extends Zend_Service_Ebay_Exception
+{}
diff --git a/lib/zend/Zend/Service/Ebay/Finding/ListingInfo.php b/lib/zend/Zend/Service/Ebay/Finding/ListingInfo.php
new file mode 100644
index 00000000000..c99dfff651c
--- /dev/null
+++ b/lib/zend/Zend/Service/Ebay/Finding/ListingInfo.php
@@ -0,0 +1,211 @@
+bestOfferEnabled = $this->_query(".//$ns:bestOfferEnabled[1]", 'boolean');
+ $this->buyItNowAvailable = $this->_query(".//$ns:buyItNowAvailable[1]", 'boolean');
+ $this->buyItNowPrice = $this->_query(".//$ns:buyItNowPrice[1]", 'float');
+ $this->convertedBuyItNowPrice = $this->_query(".//$ns:convertedBuyItNowPrice[1]", 'float');
+ $this->endTime = $this->_query(".//$ns:endTime[1]", 'string');
+ $this->gift = $this->_query(".//$ns:gift[1]", 'boolean');
+ $this->listingType = $this->_query(".//$ns:listingType[1]", 'string');
+ $this->startTime = $this->_query(".//$ns:startTime[1]", 'string');
+
+ $this->_attributes['buyItNowPrice'] = array(
+ 'currencyId' => $this->_query(".//$ns:buyItNowPrice[1]/@currencyId[1]", 'string')
+ );
+
+ $this->_attributes['convertedBuyItNowPrice'] = array(
+ 'currencyId' => $this->_query(".//$ns:convertedBuyItNowPrice[1]/@currencyId[1]", 'string')
+ );
+ }
+}
diff --git a/lib/zend/Zend/Service/Ebay/Finding/PaginationOutput.php b/lib/zend/Zend/Service/Ebay/Finding/PaginationOutput.php
new file mode 100644
index 00000000000..325474f04ef
--- /dev/null
+++ b/lib/zend/Zend/Service/Ebay/Finding/PaginationOutput.php
@@ -0,0 +1,115 @@
+entriesPerPage = $this->_query(".//$ns:entriesPerPage[1]", 'integer');
+ $this->pageNumber = $this->_query(".//$ns:pageNumber[1]", 'integer');
+ $this->totalEntries = $this->_query(".//$ns:totalEntries[1]", 'integer');
+ $this->totalPages = $this->_query(".//$ns:totalPages[1]", 'integer');
+ }
+}
diff --git a/lib/zend/Zend/Service/Ebay/Finding/Response/Abstract.php b/lib/zend/Zend/Service/Ebay/Finding/Response/Abstract.php
new file mode 100644
index 00000000000..bd7cb7c4896
--- /dev/null
+++ b/lib/zend/Zend/Service/Ebay/Finding/Response/Abstract.php
@@ -0,0 +1,185 @@
+ack = $this->_query(".//$ns:ack[1]", 'string');
+ $this->timestamp = $this->_query(".//$ns:timestamp[1]", 'string');
+ $this->version = $this->_query(".//$ns:version[1]", 'string');
+
+ $node = $this->_xPath->query(".//$ns:errorMessage[1]", $this->_dom)->item(0);
+ if ($node) {
+ /**
+ * @see Zend_Service_Ebay_Finding_Error_Message
+ */
+ require_once 'Zend/Service/Ebay/Finding/Error/Message.php';
+ $this->errorMessage = new Zend_Service_Ebay_Finding_Error_Message($node);
+ }
+ }
+
+ /**
+ * @param string $operation
+ * @return Zend_Service_Ebay_Finding_Response_Abstract Provides a fluent interface
+ */
+ public function setOperation($operation)
+ {
+ $this->_operation = (string) $operation;
+ return $this;
+ }
+
+ /**
+ * @return string
+ */
+ public function getOperation()
+ {
+ return $this->_operation;
+ }
+
+ /**
+ * @param string|Zend_Config|array $name
+ * @param mixed $value
+ * @return Zend_Service_Ebay_Finding_Response_Abstract Provides a fluent interface
+ */
+ public function setOption($name, $value = null)
+ {
+ if ($name instanceof Zend_Config) {
+ $name = $name->toArray();
+ }
+ if (is_array($name)) {
+ $this->_options = $name;
+ } else {
+ $this->_options[$name] = $value;
+ }
+ return $this;
+ }
+
+ /**
+ * @param string $name
+ * @return mixed
+ */
+ public function getOption($name = null)
+ {
+ if (null === $name) {
+ return $this->_options;
+ }
+ if (array_key_exists($name, $this->_options)) {
+ return $this->_options[$name];
+ }
+ return null;
+ }
+}
diff --git a/lib/zend/Zend/Service/Ebay/Finding/Response/Histograms.php b/lib/zend/Zend/Service/Ebay/Finding/Response/Histograms.php
new file mode 100644
index 00000000000..1e87b598916
--- /dev/null
+++ b/lib/zend/Zend/Service/Ebay/Finding/Response/Histograms.php
@@ -0,0 +1,86 @@
+_xPath->query(".//$ns:aspectHistogramContainer[1]", $this->_dom)->item(0);
+ if ($node) {
+ /**
+ * @see Zend_Service_Ebay_Finding_Aspect_Histogram_Container
+ */
+ require_once 'Zend/Service/Ebay/Finding/Aspect/Histogram/Container.php';
+ $this->aspectHistogramContainer = new Zend_Service_Ebay_Finding_Aspect_Histogram_Container($node);
+ }
+
+ $node = $this->_xPath->query(".//$ns:categoryHistogramContainer[1]", $this->_dom)->item(0);
+ if ($node) {
+ /**
+ * @see Zend_Service_Ebay_Finding_Category_Histogram_Container
+ */
+ require_once 'Zend/Service/Ebay/Finding/Category/Histogram/Container.php';
+ $this->categoryHistogramContainer = new Zend_Service_Ebay_Finding_Category_Histogram_Container($node);
+ }
+ }
+}
diff --git a/lib/zend/Zend/Service/Ebay/Finding/Response/Items.php b/lib/zend/Zend/Service/Ebay/Finding/Response/Items.php
new file mode 100644
index 00000000000..cb6108985b5
--- /dev/null
+++ b/lib/zend/Zend/Service/Ebay/Finding/Response/Items.php
@@ -0,0 +1,249 @@
+_attributes['searchResult'] = array(
+ 'count' => $this->_query(".//$ns:searchResult[1]/@count[1]", 'string')
+ );
+
+ $node = $this->_xPath->query(".//$ns:searchResult[1]", $this->_dom)->item(0);
+ if ($node) {
+ /**
+ * @see Zend_Service_Ebay_Finding_Search_Result
+ */
+ require_once 'Zend/Service/Ebay/Finding/Search/Result.php';
+ $this->searchResult = new Zend_Service_Ebay_Finding_Search_Result($node);
+ }
+
+ $node = $this->_xPath->query(".//$ns:paginationOutput[1]", $this->_dom)->item(0);
+ if ($node) {
+ /**
+ * @see Zend_Service_Ebay_Finding_PaginationOutput
+ */
+ require_once 'Zend/Service/Ebay/Finding/PaginationOutput.php';
+ $this->paginationOutput = new Zend_Service_Ebay_Finding_PaginationOutput($node);
+ }
+ }
+
+ /**
+ * @param Zend_Service_Ebay_Finding $proxy
+ * @param integer $number
+ * @throws Zend_Service_Ebay_Finding_Exception When $number is invalid
+ * @return Zend_Service_Ebay_Finding_Response_Items
+ */
+ public function page(Zend_Service_Ebay_Finding $proxy, $number)
+ {
+ // check page number
+ if ($number < 1 || $number > $this->paginationOutput->totalPages) {
+ /**
+ * @see Zend_Service_Ebay_Finding_Exception
+ */
+ require_once 'Zend/Service/Ebay/Finding/Exception.php';
+ throw new Zend_Service_Ebay_Finding_Exception(
+ "Page number '{$number}' is out of range.");
+ }
+
+ // prepare arguments
+ $arguments = array();
+ switch ($this->_operation) {
+ case 'findItemsAdvanced':
+ $arguments[] = $this->getOption('keywords');
+ $arguments[] = $this->getOption('descriptionSearch');
+ $arguments[] = $this->getOption('categoryId');
+ break;
+
+ case 'findItemsByCategory':
+ $arguments[] = $this->getOption('categoryId');
+ break;
+
+ case 'findItemsByKeywords':
+ $arguments[] = $this->getOption('keywords');
+ break;
+
+ case 'findItemsByProduct':
+ $productId = $this->getOption('productId');
+ if (!is_array($productId)) {
+ $productId = array('' => $productId);
+ }
+ $arguments[] = array_key_exists('', $productId)
+ ? $productId['']
+ : null;
+ $arguments[] = array_key_exists('type', $productId)
+ ? $productId['type']
+ : null;
+ break;
+
+ case 'findItemsIneBayStores':
+ $arguments[] = $this->getOption('storeName');
+ break;
+
+ default:
+ /**
+ * @see Zend_Service_Ebay_Finding_Exception
+ */
+ require_once 'Zend/Service/Ebay/Finding/Exception.php';
+ throw new Zend_Service_Ebay_Finding_Exception(
+ "Invalid operation '{$this->_operation}'.");
+ }
+
+ // prepare options
+ // remove every pagination entry from current option list
+ $options = $this->_options;
+ foreach (array_keys($options) as $optionName) {
+ if (substr($optionName, 0, 15) == 'paginationInput') {
+ unset($options[$optionName]);
+ }
+ }
+
+ // set new pagination values
+ // see more at http://developer.ebay.com/DevZone/finding/CallRef/types/PaginationInput.html
+ $entriesPerPage = $this->paginationOutput->entriesPerPage;
+ $options['paginationInput'] = array('entriesPerPage' => $entriesPerPage,
+ 'pageNumber' => $number);
+
+ // add current options as last argument
+ ksort($options);
+ $arguments[] = $options;
+
+ // verify cache
+ $id = serialize($arguments);
+ if (!array_key_exists($id, self::$_pageCache)) {
+ if ($number == $this->paginationOutput->pageNumber) {
+ // add itself to cache
+ $new = $this;
+ } else {
+ // request new page
+ $callback = array($proxy, $this->_operation);
+ $new = call_user_func_array($callback, $arguments);
+ }
+ self::$_pageCache[$id] = $new;
+ }
+
+ return self::$_pageCache[$id];
+ }
+
+ /**
+ * @param Zend_Service_Ebay_Finding $proxy
+ * @return Zend_Service_Ebay_Finding_Response_Items
+ */
+ public function pageFirst(Zend_Service_Ebay_Finding $proxy)
+ {
+ return $this->page($proxy, 1);
+ }
+
+ /**
+ * @param Zend_Service_Ebay_Finding $proxy
+ * @param integer $max
+ * @return Zend_Service_Ebay_Finding_Response_Items
+ */
+ public function pageLast(Zend_Service_Ebay_Finding $proxy, $max = self::PAGE_MAX_DEFAULT)
+ {
+ $last = $this->paginationOutput->totalPages;
+ if ($max > 0 && $last > $max) {
+ $last = $max;
+ }
+ return $this->page($proxy, $last);
+ }
+
+ /**
+ * @param Zend_Service_Ebay_Finding $proxy
+ * @param integer $max
+ * @return Zend_Service_Ebay_Finding_Response_Items
+ */
+ public function pageNext(Zend_Service_Ebay_Finding $proxy, $max = self::PAGE_MAX_DEFAULT)
+ {
+ $next = $this->paginationOutput->pageNumber + 1;
+ $last = $this->paginationOutput->totalPages;
+ if (($max > 0 && $next > $max) || $next > $last) {
+ return null;
+ }
+ return $this->page($proxy, $next);
+ }
+
+ /**
+ * @param Zend_Service_Ebay_Finding $proxy
+ * @return Zend_Service_Ebay_Finding_Response_Items
+ */
+ public function pagePrevious(Zend_Service_Ebay_Finding $proxy)
+ {
+ $previous = $this->paginationOutput->pageNumber - 1;
+ if ($previous < 1) {
+ return null;
+ }
+ return $this->page($proxy, $previous);
+ }
+}
diff --git a/lib/zend/Zend/Service/Ebay/Finding/Response/Keywords.php b/lib/zend/Zend/Service/Ebay/Finding/Response/Keywords.php
new file mode 100644
index 00000000000..7e992a50212
--- /dev/null
+++ b/lib/zend/Zend/Service/Ebay/Finding/Response/Keywords.php
@@ -0,0 +1,78 @@
+keywords = $this->_query(".//$ns:keywords[1]", 'string');
+ }
+
+ /**
+ * @param Zend_Service_Ebay_Finding $proxy
+ * @param Zend_Config|array $options
+ * @return Zend_Service_Ebay_Finding_Response_Items
+ */
+ public function findItems(Zend_Service_Ebay_Finding $proxy, $options = null)
+ {
+ // prepare options
+ $options = Zend_Service_Ebay_Abstract::optionsToArray($options);
+ $options = $options + $this->_options;
+
+ // find items
+ return $proxy->findItemsByKeywords($this->keywords, $options);
+ }
+}
diff --git a/lib/zend/Zend/Service/Ebay/Finding/Search/Item.php b/lib/zend/Zend/Service/Ebay/Finding/Search/Item.php
new file mode 100644
index 00000000000..55c62e2c8a6
--- /dev/null
+++ b/lib/zend/Zend/Service/Ebay/Finding/Search/Item.php
@@ -0,0 +1,394 @@
+autoPay = $this->_query(".//$ns:autoPay[1]", 'boolean');
+ $this->charityId = $this->_query(".//$ns:charityId[1]", 'integer');
+ $this->country = $this->_query(".//$ns:country[1]", 'string');
+ $this->distance = $this->_query(".//$ns:distance[1]", 'float');
+ $this->galleryPlusPictureURL = $this->_query(".//$ns:galleryPlusPictureURL", 'string', true);
+ $this->galleryURL = $this->_query(".//$ns:galleryURL[1]", 'string');
+ $this->globalId = $this->_query(".//$ns:globalId[1]", 'string');
+ $this->itemId = $this->_query(".//$ns:itemId[1]", 'string');
+ $this->location = $this->_query(".//$ns:location[1]", 'string');
+ $this->paymentMethod = $this->_query(".//$ns:paymentMethod", 'string', true);
+ $this->postalCode = $this->_query(".//$ns:postalCode[1]", 'string');
+ $this->productId = $this->_query(".//$ns:productId[1]", 'string');
+ $this->subtitle = $this->_query(".//$ns:subtitle[1]", 'string');
+ $this->title = $this->_query(".//$ns:title[1]", 'string');
+ $this->viewItemURL = $this->_query(".//$ns:viewItemURL[1]", 'string');
+
+ $this->_attributes['distance'] = array(
+ 'unit' => $this->_query(".//$ns:distance[1]/@unit[1]", 'string')
+ );
+ $this->_attributes['productId'] = array(
+ 'type' => $this->_query(".//$ns:productId[1]/@type[1]", 'string')
+ );
+
+ $node = $this->_xPath->query(".//$ns:listingInfo[1]", $this->_dom)->item(0);
+ if ($node) {
+ /**
+ * @see Zend_Service_Ebay_Finding_ListingInfo
+ */
+ require_once 'Zend/Service/Ebay/Finding/ListingInfo.php';
+ $this->listingInfo = new Zend_Service_Ebay_Finding_ListingInfo($node);
+ }
+
+ $node = $this->_xPath->query(".//$ns:primaryCategory[1]", $this->_dom)->item(0);
+ if ($node) {
+ /**
+ * @see Zend_Service_Ebay_Finding_Category
+ */
+ require_once 'Zend/Service/Ebay/Finding/Category.php';
+ $this->primaryCategory = new Zend_Service_Ebay_Finding_Category($node);
+ }
+
+ $node = $this->_xPath->query(".//$ns:secondaryCategory[1]", $this->_dom)->item(0);
+ if ($node) {
+ /**
+ * @see Zend_Service_Ebay_Finding_Category
+ */
+ require_once 'Zend/Service/Ebay/Finding/Category.php';
+ $this->secondaryCategory = new Zend_Service_Ebay_Finding_Category($node);
+ }
+
+ $node = $this->_xPath->query(".//$ns:sellerInfo[1]", $this->_dom)->item(0);
+ if ($node) {
+ /**
+ * @see Zend_Service_Ebay_Finding_SellerInfo
+ */
+ require_once 'Zend/Service/Ebay/Finding/SellerInfo.php';
+ $this->sellerInfo = new Zend_Service_Ebay_Finding_SellerInfo($node);
+ }
+
+ $node = $this->_xPath->query(".//$ns:sellingStatus[1]", $this->_dom)->item(0);
+ if ($node) {
+ /**
+ * @see Zend_Service_Ebay_Finding_SellingStatus
+ */
+ require_once 'Zend/Service/Ebay/Finding/SellingStatus.php';
+ $this->sellingStatus = new Zend_Service_Ebay_Finding_SellingStatus($node);
+ }
+
+ $node = $this->_xPath->query("./$ns:shippingInfo", $this->_dom)->item(0);
+ if ($node) {
+ /**
+ * @see Zend_Service_Ebay_Finding_ShippingInfo
+ */
+ require_once 'Zend/Service/Ebay/Finding/ShippingInfo.php';
+ $this->shippingInfo = new Zend_Service_Ebay_Finding_ShippingInfo($node);
+ }
+
+ $node = $this->_xPath->query(".//$ns:storeInfo[1]", $this->_dom)->item(0);
+ if ($node) {
+ /**
+ * @see Zend_Service_Ebay_Finding_Storefront
+ */
+ require_once 'Zend/Service/Ebay/Finding/Storefront.php';
+ $this->storeInfo = new Zend_Service_Ebay_Finding_Storefront($node);
+ }
+ }
+
+ /**
+ * @param Zend_Service_Ebay_Finding $proxy
+ * @param Zend_Config|array $options
+ * @return Zend_Service_Ebay_Finding_Response_Items
+ */
+ public function findItemsByProduct(Zend_Service_Ebay_Finding $proxy, $options = null)
+ {
+ $type = $this->attributes('productId', 'type');
+ return $proxy->findItemsByProduct($this->productId, $type, $options);
+ }
+}
diff --git a/lib/zend/Zend/Service/Ebay/Finding/Search/Item/Set.php b/lib/zend/Zend/Service/Ebay/Finding/Search/Item/Set.php
new file mode 100644
index 00000000000..57a3727fe52
--- /dev/null
+++ b/lib/zend/Zend/Service/Ebay/Finding/Search/Item/Set.php
@@ -0,0 +1,57 @@
+_nodes->item($this->_key);
+ if (!$node) {
+ return null;
+ }
+
+ /**
+ * @see Zend_Service_Ebay_Finding_Search_Item
+ */
+ require_once 'Zend/Service/Ebay/Finding/Search/Item.php';
+ return new Zend_Service_Ebay_Finding_Search_Item($node);
+ }
+}
diff --git a/lib/zend/Zend/Service/Ebay/Finding/Search/Result.php b/lib/zend/Zend/Service/Ebay/Finding/Search/Result.php
new file mode 100644
index 00000000000..9509b99625a
--- /dev/null
+++ b/lib/zend/Zend/Service/Ebay/Finding/Search/Result.php
@@ -0,0 +1,63 @@
+_xPath->query(".//$ns:item", $this->_dom);
+ if ($nodes) {
+ /**
+ * @see Zend_Service_Ebay_Finding_Search_Item_Set
+ */
+ require_once 'Zend/Service/Ebay/Finding/Search/Item/Set.php';
+ $this->item = new Zend_Service_Ebay_Finding_Search_Item_Set($nodes);
+ }
+ }
+}
diff --git a/lib/zend/Zend/Service/Ebay/Finding/SellerInfo.php b/lib/zend/Zend/Service/Ebay/Finding/SellerInfo.php
new file mode 100644
index 00000000000..4e7081ebdd5
--- /dev/null
+++ b/lib/zend/Zend/Service/Ebay/Finding/SellerInfo.php
@@ -0,0 +1,144 @@
+feedbackRatingStar = $this->_query(".//$ns:feedbackRatingStar[1]", 'string');
+ $this->feedbackScore = $this->_query(".//$ns:feedbackScore[1]", 'integer');
+ $this->positiveFeedbackPercent = $this->_query(".//$ns:positiveFeedbackPercent[1]", 'float');
+ $this->sellerUserName = $this->_query(".//$ns:sellerUserName[1]", 'string');
+ $this->topRatedSeller = $this->_query(".//$ns:topRatedSeller[1]", 'boolean');
+ }
+}
diff --git a/lib/zend/Zend/Service/Ebay/Finding/SellingStatus.php b/lib/zend/Zend/Service/Ebay/Finding/SellingStatus.php
new file mode 100644
index 00000000000..a6a3295607b
--- /dev/null
+++ b/lib/zend/Zend/Service/Ebay/Finding/SellingStatus.php
@@ -0,0 +1,130 @@
+bidCount = $this->_query(".//$ns:bidCount[1]", 'integer');
+ $this->convertedCurrentPrice = $this->_query(".//$ns:convertedCurrentPrice[1]", 'float');
+ $this->currentPrice = $this->_query(".//$ns:currentPrice[1]", 'float');
+ $this->sellingState = $this->_query(".//$ns:sellingState[1]", 'string');
+ $this->timeLeft = $this->_query(".//$ns:timeLeft[1]", 'string');
+
+ $this->_attributes['convertedCurrentPrice'] = array(
+ 'currencyId' => $this->_query(".//$ns:convertedCurrentPrice[1]/@currencyId[1]", 'string')
+ );
+
+ $this->_attributes['currentPrice'] = array(
+ 'currencyId' => $this->_query(".//$ns:currentPrice[1]/@currencyId[1]", 'string')
+ );
+ }
+}
diff --git a/lib/zend/Zend/Service/Ebay/Finding/Set/Abstract.php b/lib/zend/Zend/Service/Ebay/Finding/Set/Abstract.php
new file mode 100644
index 00000000000..08abf109f90
--- /dev/null
+++ b/lib/zend/Zend/Service/Ebay/Finding/Set/Abstract.php
@@ -0,0 +1,128 @@
+_nodes = $nodes;
+ $this->_init();
+ }
+
+ /**
+ * Initialize object.
+ *
+ * Called from {@link __construct()} as final step of object initialization.
+ *
+ * @return void
+ */
+ protected function _init()
+ {
+ }
+
+ /**
+ * Implement SeekableIterator::seek()
+ *
+ * @param integer $key
+ * @throws OutOfBoundsException When $key is not seekable
+ * @return void
+ */
+ public function seek($key)
+ {
+ if ($key < 0 || $key >= $this->count()) {
+ $message = "Position '{$key}' is not seekable.";
+ throw new OutOfBoundsException($message);
+ }
+ $this->_key = $key;
+ }
+
+ /**
+ * Implement Iterator::key()
+ *
+ * @return integer
+ */
+ public function key()
+ {
+ return $this->_key;
+ }
+
+ /**
+ * Implement Iterator::next()
+ *
+ * @return void
+ */
+ public function next()
+ {
+ $this->_key++;
+ }
+
+ /**
+ * Implement Iterator::rewind()
+ *
+ * @return void
+ */
+ public function rewind()
+ {
+ $this->_key = 0;
+ }
+
+ /**
+ * Implement Iterator::valid()
+ *
+ * @return boolean
+ */
+ public function valid()
+ {
+ return $this->_key >= 0 && $this->_key < $this->count();
+ }
+
+ /**
+ * Implement Countable::current()
+ *
+ * @return integer
+ */
+ public function count()
+ {
+ return $this->_nodes ? $this->_nodes->length : 0;
+ }
+}
diff --git a/lib/zend/Zend/Service/Ebay/Finding/ShippingInfo.php b/lib/zend/Zend/Service/Ebay/Finding/ShippingInfo.php
new file mode 100644
index 00000000000..a31257a0353
--- /dev/null
+++ b/lib/zend/Zend/Service/Ebay/Finding/ShippingInfo.php
@@ -0,0 +1,126 @@
+shippingServiceCost = $this->_query(".//$ns:shippingServiceCost[1]", 'float');
+ $this->shippingType = $this->_query(".//$ns:shippingType[1]", 'string');
+ $this->shipToLocations = $this->_query(".//$ns:shipToLocations", 'string', true);
+
+ $this->_attributes['shippingServiceCost'] = array(
+ 'currencyId' => $this->_query(".//$ns:shippingServiceCost[1]/@currencyId[1]", 'string')
+ );
+ }
+}
diff --git a/lib/zend/Zend/Service/Ebay/Finding/Storefront.php b/lib/zend/Zend/Service/Ebay/Finding/Storefront.php
new file mode 100644
index 00000000000..a32ffb9be83
--- /dev/null
+++ b/lib/zend/Zend/Service/Ebay/Finding/Storefront.php
@@ -0,0 +1,73 @@
+storeName = $this->_query(".//$ns:storeName[1]", 'string');
+ $this->storeURL = $this->_query(".//$ns:storeURL[1]", 'string');
+ }
+
+ /**
+ * @param Zend_Service_Ebay_Finding $proxy
+ * @param Zend_Config|array $options
+ * @return Zend_Service_Ebay_Finding_Response_Items
+ */
+ public function findItems(Zend_Service_Ebay_Finding $proxy, $options = null)
+ {
+ return $proxy->findItemsInEbayStores($this->storeName, $options);
+ }
+}
diff --git a/lib/zend/Zend/Service/Exception.php b/lib/zend/Zend/Service/Exception.php
index 6421b7b78f0..15beef5cc1c 100644
--- a/lib/zend/Zend/Service/Exception.php
+++ b/lib/zend/Zend/Service/Exception.php
@@ -14,7 +14,7 @@
*
* @category Zend
* @package Zend_Service
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
@@ -29,7 +29,7 @@ require_once 'Zend/Exception.php';
/**
* @category Zend
* @package Zend_Service
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Service_Exception extends Zend_Exception
diff --git a/lib/zend/Zend/Service/Flickr.php b/lib/zend/Zend/Service/Flickr.php
index af185f0ad18..a748ed4820a 100644
--- a/lib/zend/Zend/Service/Flickr.php
+++ b/lib/zend/Zend/Service/Flickr.php
@@ -16,17 +16,19 @@
* @category Zend
* @package Zend_Service
* @subpackage Flickr
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
+/** @see Zend_Xml_Security */
+require_once 'Zend/Xml/Security.php';
/**
* @category Zend
* @package Zend_Service
* @subpackage Flickr
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Service_Flickr
@@ -34,7 +36,7 @@ class Zend_Service_Flickr
/**
* Base URI for the REST client
*/
- const URI_BASE = 'http://www.flickr.com';
+ const URI_BASE = 'https://www.flickr.com';
/**
* Your Flickr API key
@@ -62,10 +64,6 @@ class Zend_Service_Flickr
*/
public function __construct($apiKey)
{
- iconv_set_encoding('output_encoding', 'UTF-8');
- iconv_set_encoding('input_encoding', 'UTF-8');
- iconv_set_encoding('internal_encoding', 'UTF-8');
-
$this->apiKey = (string) $apiKey;
}
@@ -118,8 +116,7 @@ class Zend_Service_Flickr
}
$dom = new DOMDocument();
- $dom->loadXML($response->getBody());
-
+ $dom = Zend_Xml_Security::scan($response->getBody(), $dom);
self::_checkErrors($dom);
/**
@@ -182,8 +179,7 @@ class Zend_Service_Flickr
}
$dom = new DOMDocument();
- $dom->loadXML($response->getBody());
-
+ $dom = Zend_Xml_Security::scan($response->getBody(), $dom);
self::_checkErrors($dom);
/**
@@ -237,8 +233,7 @@ class Zend_Service_Flickr
}
$dom = new DOMDocument();
- $dom->loadXML($response->getBody());
-
+ $dom = Zend_Xml_Security::scan($response->getBody(), $dom);
self::_checkErrors($dom);
/**
@@ -287,7 +282,7 @@ class Zend_Service_Flickr
}
$dom = new DOMDocument();
- $dom->loadXML($response->getBody());
+ $dom = Zend_Xml_Security::scan($response->getBody(), $dom);
self::_checkErrors($dom);
$xpath = new DOMXPath($dom);
return (string) $xpath->query('//user')->item(0)->getAttribute('id');
@@ -331,7 +326,7 @@ class Zend_Service_Flickr
}
$dom = new DOMDocument();
- $dom->loadXML($response->getBody());
+ $dom = Zend_Xml_Security::scan($response->getBody(), $dom);
self::_checkErrors($dom);
$xpath = new DOMXPath($dom);
return (string) $xpath->query('//user')->item(0)->getAttribute('id');
@@ -364,7 +359,7 @@ class Zend_Service_Flickr
$response = $restClient->restGet('/services/rest/', $options);
$dom = new DOMDocument();
- $dom->loadXML($response->getBody());
+ $dom = Zend_Xml_Security::scan($response->getBody(), $dom);
$xpath = new DOMXPath($dom);
self::_checkErrors($dom);
$retval = array();
diff --git a/lib/zend/Zend/Service/Flickr/Image.php b/lib/zend/Zend/Service/Flickr/Image.php
index fcf3063f8fc..197f9533990 100644
--- a/lib/zend/Zend/Service/Flickr/Image.php
+++ b/lib/zend/Zend/Service/Flickr/Image.php
@@ -16,7 +16,7 @@
* @category Zend
* @package Zend_Service
* @subpackage Flickr
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
@@ -26,7 +26,7 @@
* @category Zend
* @package Zend_Service
* @subpackage Flickr
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Service_Flickr_Image
diff --git a/lib/zend/Zend/Service/Flickr/Result.php b/lib/zend/Zend/Service/Flickr/Result.php
index 8fcea0812d4..8fad69a28a0 100644
--- a/lib/zend/Zend/Service/Flickr/Result.php
+++ b/lib/zend/Zend/Service/Flickr/Result.php
@@ -16,7 +16,7 @@
* @category Zend
* @package Zend_Service
* @subpackage Flickr
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
@@ -26,7 +26,7 @@
* @category Zend
* @package Zend_Service
* @subpackage Flickr
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Service_Flickr_Result
diff --git a/lib/zend/Zend/Service/Flickr/ResultSet.php b/lib/zend/Zend/Service/Flickr/ResultSet.php
index 2368627552e..31dd41050c5 100644
--- a/lib/zend/Zend/Service/Flickr/ResultSet.php
+++ b/lib/zend/Zend/Service/Flickr/ResultSet.php
@@ -16,7 +16,7 @@
* @category Zend
* @package Zend_Service
* @subpackage Flickr
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
@@ -32,7 +32,7 @@ require_once 'Zend/Service/Flickr/Result.php';
* @category Zend
* @package Zend_Service
* @subpackage Flickr
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
class Zend_Service_Flickr_ResultSet implements SeekableIterator
diff --git a/lib/zend/Zend/Service/LiveDocx.php b/lib/zend/Zend/Service/LiveDocx.php
index 02521327e89..7df6ebc44a1 100644
--- a/lib/zend/Zend/Service/LiveDocx.php
+++ b/lib/zend/Zend/Service/LiveDocx.php
@@ -15,7 +15,7 @@
* @category Zend
* @package Zend_Service
* @subpackage LiveDocx
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
@@ -24,7 +24,7 @@
* @category Zend
* @package Zend_Service
* @subpackage LiveDocx
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @since LiveDocx 1.0
*/
@@ -34,7 +34,7 @@ class Zend_Service_LiveDocx
* LiveDocx service version
* @since LiveDocx 1.0
*/
- const VERSION = '1.2';
+ const VERSION = '2.0';
/**
* SOAP client used to connect to LiveDocx service
@@ -42,37 +42,37 @@ class Zend_Service_LiveDocx
* @since LiveDocx 1.0
*/
protected $_soapClient;
-
+
/**
* WSDL of LiveDocx web service
* @var string
* @since LiveDocx 1.0
*/
protected $_wsdl;
-
+
/**
* Array of credentials (username and password) to log into backend server
* @var array
* @since LiveDocx 1.2
*/
protected $_credentials;
-
+
/**
* Set to true, when session is logged into backend server
* @var boolean
* @since LiveDocx 1.2
*/
protected $_loggedIn;
-
+
/**
* Constructor
*
* Optionally, pass an array of options (or Zend_Config object).
- *
- * If an option with the key 'soapClient' is provided, that value will be
+ *
+ * If an option with the key 'soapClient' is provided, that value will be
* used to set the internal SOAP client used to connect to the LiveDocx
* service.
- *
+ *
* Use 'soapClient' in the case that you have a dedicated or (locally
* installed) licensed LiveDocx server. For example:
*
@@ -85,7 +85,7 @@ class Zend_Service_LiveDocx
* )
* );
* {code}
- *
+ *
* Replace the URI of the WSDL in the constructor of Zend_Soap_Client with
* that of your dedicated or licensed LiveDocx server.
*
@@ -100,54 +100,54 @@ class Zend_Service_LiveDocx
* )
* );
* {code}
- *
+ *
* If you prefer to not pass the username and password through the
* constructor, you can also call the following methods:
- *
+ *
* {code}
* $phpLiveDocx = new Zend_Service_LiveDocx_MailMerge();
- *
+ *
* $phpLiveDocx->setUsername('myUsername')
* ->setPassword('myPassword');
* {/code}
- *
+ *
* Or, if you want to specify your own SoapClient:
- *
+ *
* {code}
* $phpLiveDocx = new Zend_Service_LiveDocx_MailMerge();
- *
+ *
* $phpLiveDocx->setUsername('myUsername')
* ->setPassword('myPassword');
- *
+ *
* $phpLiveDocx->setSoapClient(
* new Zend_Soap_Client('https://api.example.com/path/mailmerge.asmx?WSDL')
* );
- * {/code}
+ * {/code}
*
* @param array|Zend_Config $options
* @return void
* @throws Zend_Service_LiveDocx_Exception
* @since LiveDocx 1.0
- */
+ */
public function __construct($options = null)
{
$this->_credentials = array();
$this->_loggedIn = false;
-
+
if ($options instanceof Zend_Config) {
$options = $options->toArray();
}
-
+
if (is_array($options)) {
$this->setOptions($options);
}
}
-
+
/**
* Set options
* One or more of username, password, soapClient
- *
- * @param $options
+ *
+ * @param array $options
* @return Zend_Service_LiveDocx
* @since LiveDocx 1.2
*/
@@ -159,10 +159,10 @@ class Zend_Service_LiveDocx
$this->$method($value);
}
}
-
+
return $this;
}
-
+
/**
* Clean up and log out of LiveDocx service
*
@@ -173,7 +173,7 @@ class Zend_Service_LiveDocx
{
return $this->logOut();
}
-
+
/**
* Init Soap client - connect to SOAP service
*
@@ -187,13 +187,13 @@ class Zend_Service_LiveDocx
try {
require_once 'Zend/Soap/Client.php';
$this->_soapClient = new Zend_Soap_Client();
- $this->_soapClient->setWsdl($endpoint);
+ $this->_soapClient->setWsdl($endpoint);
} catch (Zend_Soap_Client_Exception $e) {
require_once 'Zend/Service/LiveDocx/Exception.php';
throw new Zend_Service_LiveDocx_Exception('Cannot connect to LiveDocx service at ' . $endpoint, 0, $e);
- }
+ }
}
-
+
/**
* Get SOAP client
*
@@ -204,7 +204,7 @@ class Zend_Service_LiveDocx
{
return $this->_soapClient;
}
-
+
/**
* Set SOAP client
*
@@ -237,18 +237,18 @@ class Zend_Service_LiveDocx
'Username has not been set. To set username specify the options array in the constructor or call setUsername($username) after instantiation'
);
}
-
+
if (null === $this->getPassword()) {
require_once 'Zend/Service/LiveDocx/Exception.php';
throw new Zend_Service_LiveDocx_Exception(
'Password has not been set. To set password specify the options array in the constructor or call setPassword($password) after instantiation'
);
}
-
+
if (null === $this->getSoapClient()) {
$this->_initSoapClient($this->_wsdl);
- }
-
+ }
+
try {
$this->getSoapClient()->LogIn(array(
'username' => $this->getUsername(),
@@ -260,9 +260,9 @@ class Zend_Service_LiveDocx
throw new Zend_Service_LiveDocx_Exception(
'Cannot login into LiveDocx service - username and/or password are invalid', 0, $e
);
- }
+ }
}
-
+
return $this->_loggedIn;
}
@@ -284,15 +284,15 @@ class Zend_Service_LiveDocx
throw new Zend_Service_LiveDocx_Exception(
'Cannot log out of LiveDocx service', 0, $e
);
- }
+ }
}
-
+
return $this->_loggedIn;
}
-
+
/**
* Return true, if session is currently logged into the backend server
- *
+ *
* @return boolean
* @since LiveDocx 1.2
*/
@@ -300,10 +300,10 @@ class Zend_Service_LiveDocx
{
return $this->_loggedIn;
}
-
+
/**
* Set username
- *
+ *
* @return Zend_Service_LiveDocx
* @since LiveDocx 1.0
*/
@@ -312,13 +312,13 @@ class Zend_Service_LiveDocx
$this->_credentials['username'] = $username;
return $this;
}
-
+
/**
* Set password
- *
+ *
* @return Zend_Service_LiveDocx
* @since LiveDocx 1.0
- */
+ */
public function setPassword($password)
{
$this->_credentials['password'] = $password;
@@ -327,19 +327,19 @@ class Zend_Service_LiveDocx
/**
* Set WSDL of LiveDocx web service
- *
+ *
* @return Zend_Service_LiveDocx
* @since LiveDocx 1.0
- */
- public function setWsdl($wsdl)
+ */
+ public function setWsdl($wsdl)
{
$this->_wsdl = $wsdl;
return $this;
}
-
+
/**
* Return current username
- *
+ *
* @return string|null
* @since LiveDocx 1.0
*/
@@ -348,35 +348,35 @@ class Zend_Service_LiveDocx
if (isset($this->_credentials['username'])) {
return $this->_credentials['username'];
}
-
+
return null;
}
-
+
/**
* Return current password
- *
+ *
* @return string|null
* @since LiveDocx 1.0
- */
+ */
public function getPassword()
{
if (isset($this->_credentials['password'])) {
return $this->_credentials['password'];
}
-
- return null;
+
+ return null;
}
-
+
/**
* Return WSDL of LiveDocx web service
- *
+ *
* @return Zend_Service_LiveDocx
* @since LiveDocx 1.0
- */
- public function getWsdl()
+ */
+ public function getWsdl()
{
return $this->_wsdl;
- }
+ }
/**
* Return the document format (extension) of a filename
@@ -389,7 +389,7 @@ class Zend_Service_LiveDocx
{
return strtolower(substr(strrchr($filename, '.'), 1));
}
-
+
/**
* Return the current API version
*
@@ -400,7 +400,7 @@ class Zend_Service_LiveDocx
{
return self::VERSION;
}
-
+
/**
* Compare the current API version with another version
*
@@ -412,4 +412,4 @@ class Zend_Service_LiveDocx
{
return version_compare($version, $this->getVersion());
}
-}
\ No newline at end of file
+}
diff --git a/lib/zend/Zend/Service/LiveDocx/Exception.php b/lib/zend/Zend/Service/LiveDocx/Exception.php
index a410e56bc25..53610c4afce 100644
--- a/lib/zend/Zend/Service/LiveDocx/Exception.php
+++ b/lib/zend/Zend/Service/LiveDocx/Exception.php
@@ -16,7 +16,7 @@
* @category Zend
* @package Zend_Service
* @subpackage LiveDocx
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
@@ -30,10 +30,10 @@ require_once 'Zend/Service/Exception.php';
* @category Zend
* @package Zend_Service
* @subpackage LiveDocx
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @since LiveDocx 1.0
*/
class Zend_Service_LiveDocx_Exception extends Zend_Service_Exception
{
-}
\ No newline at end of file
+}
diff --git a/lib/zend/Zend/Service/LiveDocx/MailMerge.php b/lib/zend/Zend/Service/LiveDocx/MailMerge.php
index 487730ef47c..0287e73f890 100644
--- a/lib/zend/Zend/Service/LiveDocx/MailMerge.php
+++ b/lib/zend/Zend/Service/LiveDocx/MailMerge.php
@@ -15,7 +15,7 @@
* @category Zend
* @package Zend_Service
* @subpackage LiveDocx
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
@@ -30,17 +30,18 @@ require_once 'Zend/Service/LiveDocx.php';
* @category Zend
* @package Zend_Service
* @subpackage LiveDocx
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
- * @since LiveDocx 1.0
+ * @since LiveDocx 1.0
*/
class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx
{
/**
* URI of LiveDocx.MailMerge WSDL
- * @since LiveDocx 1.0
+ * @since LiveDocx 1.0
*/
- const WSDL = 'https://api.livedocx.com/1.2/mailmerge.asmx?WSDL';
+ //const WSDL = 'https://api.livedocx.com/1.2/mailmerge.asmx?WSDL';
+ const WSDL = 'https://api.livedocx.com/2.0/mailmerge.asmx?WSDL';
/**
* Field values
@@ -70,7 +71,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx
$this->_wsdl = self::WSDL;
$this->_fieldValues = array();
$this->_blockFieldValues = array();
-
+
parent::__construct($options);
}
@@ -85,8 +86,14 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx
*/
public function setLocalTemplate($filename)
{
+ if (!is_readable($filename)) {
+ throw new Zend_Service_LiveDocx_Exception(
+ 'Cannot read local template from disk.'
+ );
+ }
+
$this->logIn();
-
+
try {
$this->getSoapClient()->SetLocalTemplate(array(
'template' => base64_encode(file_get_contents($filename)),
@@ -114,7 +121,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx
public function setRemoteTemplate($filename)
{
$this->logIn();
-
+
try {
$this->getSoapClient()->SetRemoteTemplate(array(
'filename' => $filename,
@@ -140,7 +147,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx
public function setFieldValues($values)
{
$this->logIn();
-
+
foreach ($values as $value) {
if (is_array($value)) {
$method = 'multiAssocArrayToArrayOfArrayOfString';
@@ -149,7 +156,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx
}
break;
}
-
+
try {
$this->getSoapClient()->SetFieldValues(array(
'fieldValues' => self::$method($values),
@@ -177,7 +184,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx
public function setFieldValue($field, $value)
{
$this->_fieldValues[$field] = $value;
-
+
return $this;
}
@@ -194,7 +201,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx
public function setBlockFieldValues($blockName, $blockFieldValues)
{
$this->logIn();
-
+
try {
$this->getSoapClient()->SetBlockFieldValues(array(
'blockName' => $blockName,
@@ -243,9 +250,9 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx
/**
* Set a password to open to document
- *
+ *
* This method can only be used for PDF documents
- *
+ *
* @param string $password
* @return Zend_Service_LiveDocx_MailMerge
* @throws Zend_Service_LiveDocx_Exception
@@ -254,7 +261,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx
public function setDocumentPassword($password)
{
$this->logIn();
-
+
try {
$this->getSoapClient()->SetDocumentPassword(array(
'password' => $password
@@ -265,18 +272,18 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx
'Cannot set document password. This method can be used on PDF files only.', 0, $e
);
}
-
- return $this;
+
+ return $this;
}
-
+
/**
* Set a master password for document and determine which security features
* are accessible without using the master password.
- *
+ *
* As default, nothing is allowed. To allow a security setting,
* explicatively set it using one of he DOCUMENT_ACCESS_PERMISSION_* class
- * constants.
- *
+ * constants.
+ *
* {code}
* $phpLiveDocx->setDocumentAccessPermissions(
* array (
@@ -286,10 +293,10 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx
* 'myDocumentAccessPassword'
* );
* {code}
- *
+ *
* This method can only be used for PDF documents
- *
- * @param array $permissions
+ *
+ * @param array $permissions
* @param string $password
* @return Zend_Service_LiveDocx_MailMerge
* @throws Zend_Service_LiveDocx_Exception
@@ -298,7 +305,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx
public function setDocumentAccessPermissions($permissions, $password)
{
$this->logIn();
-
+
try {
$this->getSoapClient()->SetDocumentAccessPermissions(array(
'permissions' => $permissions,
@@ -310,10 +317,10 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx
'Cannot set document access permissions', 0, $e
);
}
-
- return $this;
- }
-
+
+ return $this;
+ }
+
/**
* Merge assigned data with template to generate document
*
@@ -324,7 +331,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx
public function createDocument()
{
$this->logIn();
-
+
if (count($this->_fieldValues) > 0) {
$this->setFieldValues($this->_fieldValues);
}
@@ -354,9 +361,9 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx
public function retrieveDocument($format)
{
$this->logIn();
-
+
$format = strtolower($format);
-
+
try {
$result = $this->getSoapClient()->RetrieveDocument(array(
'format' => $format,
@@ -383,7 +390,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx
public function getMetafiles($fromPage, $toPage)
{
$this->logIn();
-
+
$ret = array();
$result = $this->getSoapClient()->GetMetafiles(array(
'fromPage' => (integer) $fromPage,
@@ -415,7 +422,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx
public function getAllMetafiles()
{
$this->logIn();
-
+
$ret = array();
$result = $this->getSoapClient()->GetAllMetafiles();
@@ -432,8 +439,8 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx
}
return $ret;
- }
-
+ }
+
/**
* Return graphical bitmap data for specified page range of created document
* Return array contains bitmap data (binary) - array key is page number
@@ -444,13 +451,13 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx
* @param string $format
* @return array
* @since LiveDocx 1.2
- */
+ */
public function getBitmaps($fromPage, $toPage, $zoomFactor, $format)
{
$this->logIn();
-
+
$ret = array();
-
+
$result = $this->getSoapClient()->GetBitmaps(array(
'fromPage' => (integer) $fromPage,
'toPage' => (integer) $toPage,
@@ -470,9 +477,9 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx
}
}
- return $ret;
+ return $ret;
}
-
+
/**
* Return graphical bitmap data for all pages of created document
* Return array contains bitmap data (binary) - array key is page number
@@ -481,11 +488,11 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx
* @param string $format
* @return array
* @since LiveDocx 1.2
- */
+ */
public function getAllBitmaps($zoomFactor, $format)
{
$this->logIn();
-
+
$ret = array();
$result = $this->getSoapClient()->GetAllBitmaps(array(
'zoomFactor' => (integer) $zoomFactor,
@@ -504,8 +511,8 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx
}
}
- return $ret;
- }
+ return $ret;
+ }
/**
* Return all the fields in the template
@@ -516,7 +523,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx
public function getFieldNames()
{
$this->logIn();
-
+
$ret = array();
$result = $this->getSoapClient()->GetFieldNames();
@@ -541,7 +548,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx
public function getBlockFieldNames($blockName)
{
$this->logIn();
-
+
$ret = array();
$result = $this->getSoapClient()->GetBlockFieldNames(array(
'blockName' => $blockName
@@ -567,7 +574,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx
public function getBlockNames()
{
$this->logIn();
-
+
$ret = array();
$result = $this->getSoapClient()->GetBlockNames();
@@ -593,7 +600,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx
public function uploadTemplate($filename)
{
$this->logIn();
-
+
try {
$this->getSoapClient()->UploadTemplate(array(
'template' => base64_encode(file_get_contents($filename)),
@@ -618,7 +625,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx
public function downloadTemplate($filename)
{
$this->logIn();
-
+
try {
$result = $this->getSoapClient()->DownloadTemplate(array(
'filename' => basename($filename),
@@ -644,7 +651,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx
public function deleteTemplate($filename)
{
$this->logIn();
-
+
$this->getSoapClient()->DeleteTemplate(array(
'filename' => basename($filename),
));
@@ -654,12 +661,12 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx
* List all templates stored on LiveDocx service
*
* @return array
- * @since LiveDocx 1.0
+ * @since LiveDocx 1.0
*/
public function listTemplates()
{
$this->logIn();
-
+
$ret = array();
$result = $this->getSoapClient()->ListTemplates();
@@ -680,7 +687,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx
public function templateExists($filename)
{
$this->logIn();
-
+
$result = $this->getSoapClient()->TemplateExists(array(
'filename' => basename($filename),
));
@@ -697,7 +704,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx
public function shareDocument()
{
$this->logIn();
-
+
$ret = null;
$result = $this->getSoapClient()->ShareDocument();
@@ -717,7 +724,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx
public function listSharedDocuments()
{
$this->logIn();
-
+
$ret = array();
$result = $this->getSoapClient()->ListSharedDocuments();
@@ -740,7 +747,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx
public function deleteSharedDocument($filename)
{
$this->logIn();
-
+
$this->getSoapClient()->DeleteSharedDocument(array(
'filename' => basename($filename),
));
@@ -757,7 +764,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx
public function downloadSharedDocument($filename)
{
$this->logIn();
-
+
try {
$result = $this->getSoapClient()->DownloadSharedDocument(array(
'filename' => basename($filename),
@@ -782,11 +789,11 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx
public function sharedDocumentExists($filename)
{
$this->logIn();
-
+
$ret = false;
$sharedDocuments = $this->listSharedDocuments();
foreach ($sharedDocuments as $shareDocument) {
- if (isset($shareDocument['filename'])
+ if (isset($shareDocument['filename'])
&& (basename($filename) === $shareDocument['filename'])
) {
$ret = true;
@@ -806,7 +813,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx
public function getTemplateFormats()
{
$this->logIn();
-
+
$ret = array();
$result = $this->getSoapClient()->GetTemplateFormats();
@@ -827,7 +834,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx
public function getDocumentFormats()
{
$this->logIn();
-
+
$ret = array();
$result = $this->getSoapClient()->GetDocumentFormats();
@@ -838,28 +845,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx
return $ret;
}
-
- /*
- * Return supported image formats (lowercase)
- *
- * @return array
- * @since LiveDocx 1.2
- */
- public function getImageFormats()
- {
- $this->logIn();
-
- $ret = array();
- $result = $this->getSoapClient()->GetImageFormats();
- if (isset($result->GetImageFormatsResult->string)) {
- $ret = $result->GetImageFormatsResult->string;
- $ret = array_map('strtolower', $ret);
- }
-
- return $ret;
- }
-
/**
* Return the names of all fonts that are installed on backend server
*
@@ -869,7 +855,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx
public function getFontNames()
{
$this->logIn();
-
+
$ret = array();
$result = $this->getSoapClient()->GetFontNames();
@@ -878,8 +864,8 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx
}
return $ret;
- }
-
+ }
+
/**
* Return supported document access options
*
@@ -889,7 +875,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx
public function getDocumentAccessOptions()
{
$this->logIn();
-
+
$ret = array();
$result = $this->getSoapClient()->GetDocumentAccessOptions();
@@ -898,19 +884,190 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx
}
return $ret;
- }
+ }
+
+ /**
+ * Return supported image formats from which can be imported (lowercase)
+ *
+ * @return array
+ * @since LiveDocx 2.0
+ */
+ public function getImageImportFormats()
+ {
+ $this->logIn();
+
+ $ret = array();
+ $result = $this->getSoapClient()->GetImageImportFormats();
+
+ if (isset($result->GetImageImportFormatsResult->string)) {
+ $ret = $result->GetImageImportFormatsResult->string;
+ $ret = array_map('strtolower', $ret);
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Return supported image formats to which can be exported (lowercase)
+ *
+ * @return array
+ * @since LiveDocx 2.0
+ */
+ public function getImageExportFormats()
+ {
+ $this->logIn();
+
+ $ret = array();
+ $result = $this->getSoapClient()->GetImageExportFormats();
+
+ if (isset($result->GetImageExportFormatsResult->string)) {
+ $ret = $result->GetImageExportFormatsResult->string;
+ $ret = array_map('strtolower', $ret);
+ }
+
+ return $ret;
+ }
+
+ /*
+ * Return supported image formats (lowercase)
+ *
+ * @return array
+ * @since LiveDocx 1.2
+ * @deprecated since LiveDocx 2.0
+ */
+ public function getImageFormats()
+ {
+ $replacement = 'getImageExportFormats';
+
+ /*
+ $errorMessage = sprintf(
+ "%s::%s is deprecated as of LiveDocx 2.0. "
+ . "It has been replaced by %s::%s() (drop in replacement)",
+ __CLASS__, __FUNCTION__, __CLASS__, $replacement);
+
+ trigger_error($errorMessage, E_USER_NOTICE);
+ */
+
+ return $this->$replacement();
+ }
+
+ /**
+ * Upload an image file to LiveDocx service
+ *
+ * @param string $filename
+ * @return void
+ * @throws Zend_Service_LiveDocx_Exception
+ * @since LiveDocx 2.0
+ */
+ public function uploadImage($filename)
+ {
+ $this->logIn();
+
+ try {
+ $this->getSoapClient()->UploadImage(array(
+ 'image' => base64_encode(file_get_contents($filename)),
+ 'filename' => basename($filename),
+ ));
+ } catch (Exception $e) {
+ require_once 'Zend/Service/LiveDocx/Exception.php';
+ throw new Zend_Service_LiveDocx_Exception(
+ 'Cannot upload image', 0, $e
+ );
+ }
+ }
+
+ /**
+ * Download an image file from LiveDocx service
+ *
+ * @param string $filename
+ * @return void
+ * @throws Zend_Service_LiveDocx_Exception
+ * @since LiveDocx 2.0
+ */
+ public function downloadImage($filename)
+ {
+ $this->logIn();
+
+ try {
+ $result = $this->getSoapClient()->DownloadImage(array(
+ 'filename' => basename($filename),
+ ));
+ } catch (Exception $e) {
+ require_once 'Zend/Service/LiveDocx/Exception.php';
+ throw new Zend_Service_LiveDocx_Exception(
+ 'Cannot download image', 0, $e
+ );
+ }
+
+ return base64_decode($result->DownloadImageResult);
+ }
+
+ /**
+ * List all images stored on LiveDocx service
+ *
+ * @return array
+ * @since LiveDocx 2.0
+ */
+ public function listImages()
+ {
+ $this->logIn();
+
+ $ret = array();
+ $result = $this->getSoapClient()->ListImages();
+
+ if (isset($result->ListImagesResult)) {
+ $ret = $this->_backendListArrayToMultiAssocArray($result->ListImagesResult);
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Delete an image file from LiveDocx service
+ *
+ * @param string $filename
+ * @return void
+ * @throws Zend_Service_LiveDocx_Exception
+ * @since LiveDocx 2.0
+ */
+ public function deleteImage($filename)
+ {
+ $this->logIn();
+
+ $this->getSoapClient()->DeleteImage(array(
+ 'filename' => basename($filename),
+ ));
+ }
+
+ /**
+ * Check whether an image file is available on LiveDocx service
+ *
+ * @param string $filename
+ * @return boolean
+ * @since LiveDocx 2.0
+ */
+ public function imageExists($filename)
+ {
+ $this->logIn();
+
+ $result = $this->getSoapClient()->ImageExists(array(
+ 'filename' => basename($filename),
+ ));
+
+ return (boolean) $result->ImageExistsResult;
+ }
/**
* Convert LiveDocx service return value from list methods to consistent PHP array
*
* @param array $list
* @return array
- * @since LiveDocx 1.0
+ * @since LiveDocx 1.0
*/
protected function _backendListArrayToMultiAssocArray($list)
{
$this->logIn();
-
+
$ret = array();
if (isset($list->ArrayOfString)) {
foreach ($list->ArrayOfString as $a) {
@@ -951,7 +1108,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx
{
$arrayKeys = array_keys($assoc);
$arrayValues = array_values($assoc);
-
+
return array($arrayKeys, $arrayValues);
}
@@ -975,4 +1132,7 @@ class Zend_Service_LiveDocx_MailMerge extends Zend_Service_LiveDocx
return array_merge($arrayKeys, $arrayValues);
}
-}
\ No newline at end of file
+
+ // -------------------------------------------------------------------------
+
+}
diff --git a/lib/zend/Zend/Service/Nirvanix.php b/lib/zend/Zend/Service/Nirvanix.php
deleted file mode 100644
index a63075d6999..00000000000
--- a/lib/zend/Zend/Service/Nirvanix.php
+++ /dev/null
@@ -1,107 +0,0 @@
- array(),
- 'httpClient' => new Zend_Http_Client(),
- 'host' => 'http://services.nirvanix.com');
- $this->_options = array_merge($defaultOptions, $options);
-
- // login and save sessionToken to default POST params
- $resp = $this->getService('Authentication')->login($authParams);
- $this->_options['defaults']['sessionToken'] = (string)$resp->SessionToken;
- }
-
- /**
- * Nirvanix divides its service into namespaces, with each namespace
- * providing different functionality. This is a factory method that
- * returns a preconfigured Zend_Service_Nirvanix_Namespace_Base proxy.
- *
- * @param string $namespace Name of the namespace
- * @return Zend_Service_Nirvanix_Namespace_Base
- */
- public function getService($namespace, $options = array())
- {
- switch ($namespace) {
- case 'IMFS':
- $class = 'Zend_Service_Nirvanix_Namespace_Imfs';
- break;
- default:
- $class = 'Zend_Service_Nirvanix_Namespace_Base';
- }
-
- $options['namespace'] = ucfirst($namespace);
- $options = array_merge($this->_options, $options);
-
- if (!class_exists($class)) {
- require_once 'Zend/Loader.php';
- Zend_Loader::loadClass($class);
- }
- return new $class($options);
- }
-
- /**
- * Get the configured options.
- *
- * @return array
- */
- public function getOptions()
- {
- return $this->_options;
- }
-
-}
diff --git a/lib/zend/Zend/Service/Nirvanix/Namespace/Base.php b/lib/zend/Zend/Service/Nirvanix/Namespace/Base.php
deleted file mode 100644
index a7bc1d0f98f..00000000000
--- a/lib/zend/Zend/Service/Nirvanix/Namespace/Base.php
+++ /dev/null
@@ -1,172 +0,0 @@
-_host = $options['baseUrl'];
- }
-
- if (isset($options['namespace'])) {
- $this->_namespace = $options['namespace'];
- }
-
- if (isset($options['defaults'])) {
- $this->_defaults = $options['defaults'];
- }
-
- if (! isset($options['httpClient'])) {
- $options['httpClient'] = new Zend_Http_Client();
- }
- $this->_httpClient = $options['httpClient'];
- }
-
- /**
- * When a method call is made against this proxy, convert it to
- * an HTTP request to make against the Nirvanix REST service.
- *
- * $imfs->DeleteFiles(array('filePath' => 'foo'));
- *
- * Assuming this object was proxying the IMFS namespace, the
- * method call above would call the DeleteFiles command. The
- * POST parameters would be filePath, merged with the
- * $this->_defaults (containing the sessionToken).
- *
- * @param string $methodName Name of the command to call
- * on this namespace.
- * @param array $args Only the first is used and it must be
- * an array. It contains the POST params.
- *
- * @return Zend_Service_Nirvanix_Response
- */
- public function __call($methodName, $args)
- {
- $uri = $this->_makeUri($methodName);
- $this->_httpClient->setUri($uri);
-
- if (!isset($args[0]) || !is_array($args[0])) {
- $args[0] = array();
- }
-
- $params = array_merge($this->_defaults, $args[0]);
- $this->_httpClient->resetParameters();
- $this->_httpClient->setParameterPost($params);
-
- $httpResponse = $this->_httpClient->request(Zend_Http_Client::POST);
- return $this->_wrapResponse($httpResponse);
- }
-
- /**
- * Return the HTTP client used for this namespace. This is useful
- * for inspecting the last request or directly interacting with the
- * HTTP client.
- *
- * @return Zend_Http_Client
- */
- public function getHttpClient()
- {
- return $this->_httpClient;
- }
-
- /**
- * Make a complete URI from an RPC method name. All Nirvanix REST
- * service URIs use the same format.
- *
- * @param string $methodName RPC method name
- * @return string
- */
- protected function _makeUri($methodName)
- {
- $methodName = ucfirst($methodName);
- return "{$this->_host}/ws/{$this->_namespace}/{$methodName}.ashx";
- }
-
- /**
- * All Nirvanix REST service calls return an XML payload. This method
- * makes a Zend_Service_Nirvanix_Response from that XML payload.
- *
- * @param Zend_Http_Response $httpResponse Raw response from Nirvanix
- * @return Zend_Service_Nirvanix_Response Wrapped response
- */
- protected function _wrapResponse($httpResponse)
- {
- return new Zend_Service_Nirvanix_Response($httpResponse->getBody());
- }
-}
diff --git a/lib/zend/Zend/Service/Nirvanix/Namespace/Imfs.php b/lib/zend/Zend/Service/Nirvanix/Namespace/Imfs.php
deleted file mode 100644
index 86907ad323f..00000000000
--- a/lib/zend/Zend/Service/Nirvanix/Namespace/Imfs.php
+++ /dev/null
@@ -1,105 +0,0 @@
- $filePath,
- 'expiration' => $expiration);
- $resp = $this->getOptimalUrls($params);
- $url = (string)$resp->Download->DownloadURL;
-
- // download the file
- $this->_httpClient->resetParameters();
- $this->_httpClient->setUri($url);
- $resp = $this->_httpClient->request(Zend_Http_Client::GET);
-
- return $resp->getBody();
- }
-
- /**
- * Convenience function to put the contents of a string into
- * the Nirvanix IMFS. Analog to PHP's file_put_contents().
- *
- * @param string $filePath Remote path and filename
- * @param integer $data Data to store in the file
- * @param string $mimeType Mime type of data
- * @return Zend_Service_Nirvanix_Response
- */
- public function putContents($filePath, $data, $mimeType = null)
- {
- // get storage node for upload
- $params = array('sizeBytes' => strlen($data));
- $resp = $this->getStorageNode($params);
- $host = (string)$resp->GetStorageNode->UploadHost;
- $uploadToken = (string)$resp->GetStorageNode->UploadToken;
-
- // http upload data into remote file
- $this->_httpClient->resetParameters();
- $this->_httpClient->setUri("http://{$host}/Upload.ashx");
- $this->_httpClient->setParameterPost('uploadToken', $uploadToken);
- $this->_httpClient->setParameterPost('destFolderPath', str_replace('\\', '/',dirname($filePath)));
- $this->_httpClient->setFileUpload(basename($filePath), 'uploadFile', $data, $mimeType);
- $response = $this->_httpClient->request(Zend_Http_Client::POST);
-
- return new Zend_Service_Nirvanix_Response($response->getBody());
- }
-
- /**
- * Convenience function to remove a file from the Nirvanix IMFS.
- * Analog to PHP's unlink().
- *
- * @param string $filePath Remove path and filename
- * @return Zend_Service_Nirvanix_Response
- */
- public function unlink($filePath)
- {
- $params = array('filePath' => $filePath);
- return $this->deleteFiles($params);
- }
-
-}
diff --git a/lib/zend/Zend/Service/Nirvanix/Response.php b/lib/zend/Zend/Service/Nirvanix/Response.php
deleted file mode 100644
index b1de6422f7a..00000000000
--- a/lib/zend/Zend/Service/Nirvanix/Response.php
+++ /dev/null
@@ -1,123 +0,0 @@
- contains an error.
- *
- * @category Zend
- * @package Zend_Service
- * @subpackage Nirvanix
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
- * @license http://framework.zend.com/license/new-bsd New BSD License
- */
-class Zend_Service_Nirvanix_Response
-{
- /**
- * SimpleXMLElement parsed from Nirvanix web service response.
- *
- * @var SimpleXMLElement
- */
- protected $_sxml;
-
- /**
- * Class constructor. Parse the XML response from a Nirvanix method
- * call into a decorated SimpleXMLElement element.
- *
- * @param string $xml XML response string from Nirvanix
- * @throws Zend_Service_Nirvanix_Exception
- */
- public function __construct($xml)
- {
- $this->_sxml = @simplexml_load_string($xml);
-
- if (! $this->_sxml instanceof SimpleXMLElement) {
- $this->_throwException("XML could not be parsed from response: $xml");
- }
-
- $name = $this->_sxml->getName();
- if ($name != 'Response') {
- $this->_throwException("Expected XML element Response, got $name");
- }
-
- $code = (int)$this->_sxml->ResponseCode;
- if ($code != 0) {
- $msg = (string)$this->_sxml->ErrorMessage;
- $this->_throwException($msg, $code);
- }
- }
-
- /**
- * Return the SimpleXMLElement representing this response
- * for direct access.
- *
- * @return SimpleXMLElement
- */
- public function getSxml()
- {
- return $this->_sxml;
- }
-
- /**
- * Delegate undefined properties to the decorated SimpleXMLElement.
- *
- * @param string $offset Undefined property name
- * @return mixed
- */
- public function __get($offset)
- {
- return $this->_sxml->$offset;
- }
-
- /**
- * Delegate undefined methods to the decorated SimpleXMLElement.
- *
- * @param string $offset Underfined method name
- * @param array $args Method arguments
- * @return mixed
- */
- public function __call($method, $args)
- {
- return call_user_func_array(array($this->_sxml, $method), $args);
- }
-
- /**
- * Throw an exception. This method exists to only contain the
- * lazy-require() of the exception class.
- *
- * @param string $message Error message
- * @param integer $code Error code
- * @throws Zend_Service_Nirvanix_Exception
- * @return void
- */
- protected function _throwException($message, $code = null)
- {
- /**
- * @see Zend_Service_Nirvanix_Exception
- */
- require_once 'Zend/Service/Nirvanix/Exception.php';
-
- throw new Zend_Service_Nirvanix_Exception($message, $code);
- }
-
-}
diff --git a/lib/zend/Zend/Service/Rackspace/Abstract.php b/lib/zend/Zend/Service/Rackspace/Abstract.php
new file mode 100644
index 00000000000..afec6a4e5db
--- /dev/null
+++ b/lib/zend/Zend/Service/Rackspace/Abstract.php
@@ -0,0 +1,392 @@
+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 ($method == 'PUT' && empty($body)) {
+ // if left at NULL a PUT request will always have
+ // Content-Type: x-url-form-encoded, which breaks copyObject()
+ $client->setEncType('');
+ }
+ 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;
+ }
+}
diff --git a/lib/zend/Zend/Service/Nirvanix/Exception.php b/lib/zend/Zend/Service/Rackspace/Exception.php
similarity index 78%
rename from lib/zend/Zend/Service/Nirvanix/Exception.php
rename to lib/zend/Zend/Service/Rackspace/Exception.php
index d81d4d13ba4..3074fff06af 100644
--- a/lib/zend/Zend/Service/Nirvanix/Exception.php
+++ b/lib/zend/Zend/Service/Rackspace/Exception.php
@@ -14,8 +14,8 @@
*
* @category Zend
* @package Zend_Service
- * @subpackage Nirvanix
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @subpackage Rackspace
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
@@ -28,9 +28,9 @@ require_once 'Zend/Service/Exception.php';
/**
* @category Zend
* @package Zend_Service
- * @subpackage Nirvanix
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @subpackage Rackspace
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
-class Zend_Service_Nirvanix_Exception extends Zend_Service_Exception
+class Zend_Service_Rackspace_Exception extends Zend_Service_Exception
{}
diff --git a/lib/zend/Zend/Service/Rackspace/Files.php b/lib/zend/Zend/Service/Rackspace/Files.php
new file mode 100644
index 00000000000..fd4bc6036a9
--- /dev/null
+++ b/lib/zend/Zend/Service/Rackspace/Files.php
@@ -0,0 +1,727 @@
+getInfoAccount();
+ return $data['tot_containers'];
+ }
+ /**
+ * Return the size in bytes of all the containers
+ *
+ * @return int
+ */
+ public function getSizeContainers()
+ {
+ $data= $this->getInfoAccount();
+ return $data['size_containers'];
+ }
+ /**
+ * Return the count of objects contained in all the containers
+ *
+ * @return int
+ */
+ public function getCountObjects()
+ {
+ $data= $this->getInfoAccount();
+ return $data['tot_objects'];
+ }
+ /**
+ * Get all the containers
+ *
+ * @param array $options
+ * @return Zend_Service_Rackspace_Files_ContainerList|bool
+ */
+ 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|bool
+ */
+ 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|bool
+ */
+ 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
+ *
+ * Returns a maximum of 10,000 object names.
+ *
+ * @param string $container
+ * @param array $options
+ * @return bool|Zend_Service_Rackspace_Files_ObjectList
+ * @throws Zend_Service_Rackspace_Exception
+ */
+ 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 bool|Zend_Service_Rackspace_Files_Container
+ * @throws Zend_Service_Rackspace_Exception
+ */
+ 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 string $container
+ * @return bool
+ * @throws Zend_Service_Rackspace_Exception
+ */
+ 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|bool
+ * @throws Zend_Service_Rackspace_Exception
+ */
+ 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 Zend_Service_Rackspace_Files_Container|bool
+ */
+ 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 bool|Zend_Service_Rackspace_Files_Object
+ * @throws Zend_Service_Rackspace_Exception
+ */
+ 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 bool
+ * @throws Zend_Service_Rackspace_Exception
+ */
+ 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 bool
+ * @throws Zend_Service_Rackspace_Exception
+ */
+ 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 bool
+ * @throws Zend_Service_Rackspace_Exception
+ */
+ 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|bool
+ * @throws Zend_Service_Rackspace_Exception
+ */
+ 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 bool
+ * @throws Zend_Service_Rackspace_Exception
+ */
+ 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 int $ttl
+ * @return array|bool
+ * @throws Zend_Service_Rackspace_Exception
+ */
+ 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 int $ttl
+ * @param bool $cdn_enabled
+ * @param bool $log
+ * @return bool
+ * @throws Zend_Service_Rackspace_Exception
+ */
+ 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|bool
+ * @throws Zend_Service_Rackspace_Exception
+ */
+ 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;
+ }
+}
diff --git a/lib/zend/Zend/Service/Rackspace/Files/Container.php b/lib/zend/Zend/Service/Rackspace/Files/Container.php
new file mode 100644
index 00000000000..da6b7046237
--- /dev/null
+++ b/lib/zend/Zend/Service/Rackspace/Files/Container.php
@@ -0,0 +1,405 @@
+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|bool
+ */
+ 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|bool
+ */
+ public function getObjectCount()
+ {
+ $data = $this->getInfo();
+ if (isset($data['count'])) {
+ return $data['count'];
+ }
+
+ return false;
+ }
+
+ /**
+ * Return true if the container is CDN enabled
+ *
+ * @return bool
+ */
+ 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|bool
+ */
+ 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 bool
+ */
+ public function isCdnLogEnabled()
+ {
+ $data = $this->getCdnInfo();
+ if (isset($data['log_retention'])) {
+ return $data['log_retention'];
+ }
+
+ return false;
+ }
+
+ /**
+ * Get the CDN URI
+ *
+ * @return string|bool
+ */
+ public function getCdnUri()
+ {
+ $data = $this->getCdnInfo();
+ if (isset($data['cdn_uri'])) {
+ return $data['cdn_uri'];
+ }
+
+ return false;
+ }
+
+ /**
+ * Get the CDN URI SSL
+ *
+ * @return string|bool
+ */
+ 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|bool
+ */
+ 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|bool
+ */
+ 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|bool
+ */
+ 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 bool
+ */
+ 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 bool
+ */
+ 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 bool
+ */
+ 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 bool
+ */
+ 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|bool
+ */
+ 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 bool
+ */
+ 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 bool
+ */
+ public function changeTtlCdn($ttl)
+ {
+ $result = $this->service->updateCdnContainer($this->getName(), $ttl);
+
+ return ($result !== false);
+ }
+
+ /**
+ * Enable the log retention for the CDN
+ *
+ * @return bool
+ */
+ public function enableLogCdn()
+ {
+ $result = $this->service->updateCdnContainer(
+ $this->getName(), null, null, true
+ );
+
+ return ($result !== false);
+ }
+
+ /**
+ * Disable the log retention for the CDN
+ *
+ * @return bool
+ */
+ public function disableLogCdn()
+ {
+ $result = $this->service->updateCdnContainer(
+ $this->getName(), null, null, false
+ );
+
+ return ($result !== false);
+ }
+
+ /**
+ * Get the CDN information
+ *
+ * @return array|bool
+ */
+ public function getCdnInfo()
+ {
+ return $this->service->getInfoCdnContainer($this->getName());
+ }
+}
diff --git a/lib/zend/Zend/Service/Rackspace/Files/ContainerList.php b/lib/zend/Zend/Service/Rackspace/Files/ContainerList.php
new file mode 100644
index 00000000000..f0650232fb8
--- /dev/null
+++ b/lib/zend/Zend/Service/Rackspace/Files/ContainerList.php
@@ -0,0 +1,221 @@
+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');
+ }
+}
diff --git a/lib/zend/Zend/Service/DeveloperGarden/Exception.php b/lib/zend/Zend/Service/Rackspace/Files/Exception.php
similarity index 63%
rename from lib/zend/Zend/Service/DeveloperGarden/Exception.php
rename to lib/zend/Zend/Service/Rackspace/Files/Exception.php
index 63a8a09e4fa..bd1c7ae72a7 100644
--- a/lib/zend/Zend/Service/DeveloperGarden/Exception.php
+++ b/lib/zend/Zend/Service/Rackspace/Files/Exception.php
@@ -13,26 +13,24 @@
* to license@zend.com so we can send you a copy immediately.
*
* @category Zend
- * @package Zend_Service
- * @subpackage DeveloperGarden
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @package Zend_Service_Rackspace
+ * @subpackage Files
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
/**
- * Zend_Service_Exception
+ * @see Zend_Service_Rackspace_Exception
*/
-require_once 'Zend/Service/Exception.php';
+require_once 'Zend/Service/Rackspace/Exception.php';
/**
* @category Zend
- * @package Zend_Service
- * @subpackage DeveloperGarden
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
- * @author Marco Kaiser
+ * @package Zend_Service_Rackspace
+ * @subpackage Files
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
-class Zend_Service_DeveloperGarden_Exception extends Zend_Service_Exception
-{
-}
+class Zend_Service_Rackspace_Files_Exception extends Zend_Service_Rackspace_Exception
+{}
diff --git a/lib/zend/Zend/Service/Rackspace/Files/Object.php b/lib/zend/Zend/Service/Rackspace/Files/Object.php
new file mode 100644
index 00000000000..4b2714ba279
--- /dev/null
+++ b/lib/zend/Zend/Service/Rackspace/Files/Object.php
@@ -0,0 +1,312 @@
+name = $data['name'];
+ $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'];
+ }
+ } elseif (array_key_exists('subdir', $data)) {
+ $this->name = $data['subdir'];
+ } else {
+ 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)'
+ );
+ }
+
+ $this->container = $data['container'];
+ $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;
+ }
+}
diff --git a/lib/zend/Zend/Service/Rackspace/Files/ObjectList.php b/lib/zend/Zend/Service/Rackspace/Files/ObjectList.php
new file mode 100644
index 00000000000..99abcb1c453
--- /dev/null
+++ b/lib/zend/Zend/Service/Rackspace/Files/ObjectList.php
@@ -0,0 +1,237 @@
+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');
+ }
+}
diff --git a/lib/zend/Zend/Service/Rackspace/Servers.php b/lib/zend/Zend/Service/Rackspace/Servers.php
new file mode 100644
index 00000000000..f76b7dde0e0
--- /dev/null
+++ b/lib/zend/Zend/Service/Rackspace/Servers.php
@@ -0,0 +1,1281 @@
+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;
+ }
+}
diff --git a/lib/zend/Zend/Service/Rackspace/Servers/Exception.php b/lib/zend/Zend/Service/Rackspace/Servers/Exception.php
new file mode 100644
index 00000000000..70de0889e5c
--- /dev/null
+++ b/lib/zend/Zend/Service/Rackspace/Servers/Exception.php
@@ -0,0 +1,36 @@
+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
+ );
+ }
+}
diff --git a/lib/zend/Zend/Service/Rackspace/Servers/ImageList.php b/lib/zend/Zend/Service/Rackspace/Servers/ImageList.php
new file mode 100644
index 00000000000..2d7848567b1
--- /dev/null
+++ b/lib/zend/Zend/Service/Rackspace/Servers/ImageList.php
@@ -0,0 +1,234 @@
+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');
+ }
+}
diff --git a/lib/zend/Zend/Service/Rackspace/Servers/Server.php b/lib/zend/Zend/Service/Rackspace/Servers/Server.php
new file mode 100644
index 00000000000..5249a9732e4
--- /dev/null
+++ b/lib/zend/Zend/Service/Rackspace/Servers/Server.php
@@ -0,0 +1,325 @@
+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
+ );
+ }
+}
diff --git a/lib/zend/Zend/Service/Rackspace/Servers/ServerList.php b/lib/zend/Zend/Service/Rackspace/Servers/ServerList.php
new file mode 100644
index 00000000000..9dda8684ec1
--- /dev/null
+++ b/lib/zend/Zend/Service/Rackspace/Servers/ServerList.php
@@ -0,0 +1,235 @@
+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');
+ }
+}
diff --git a/lib/zend/Zend/Service/Rackspace/Servers/SharedIpGroup.php b/lib/zend/Zend/Service/Rackspace/Servers/SharedIpGroup.php
new file mode 100644
index 00000000000..6367db299d2
--- /dev/null
+++ b/lib/zend/Zend/Service/Rackspace/Servers/SharedIpGroup.php
@@ -0,0 +1,165 @@
+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
+ );
+ }
+}
diff --git a/lib/zend/Zend/Service/Rackspace/Servers/SharedIpGroupList.php b/lib/zend/Zend/Service/Rackspace/Servers/SharedIpGroupList.php
new file mode 100644
index 00000000000..476f58a6a53
--- /dev/null
+++ b/lib/zend/Zend/Service/Rackspace/Servers/SharedIpGroupList.php
@@ -0,0 +1,234 @@
+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');
+ }
+}
diff --git a/lib/zend/Zend/Service/ReCaptcha.php b/lib/zend/Zend/Service/ReCaptcha.php
index 2421d9dc898..4993d201eac 100644
--- a/lib/zend/Zend/Service/ReCaptcha.php
+++ b/lib/zend/Zend/Service/ReCaptcha.php
@@ -15,7 +15,7 @@
* @category Zend
* @package Zend_Service
* @subpackage ReCaptcha
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
@@ -34,7 +34,7 @@ require_once 'Zend/Service/ReCaptcha/Response.php';
* @category Zend
* @package Zend_Service
* @subpackage ReCaptcha
- * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
* @version $Id$
*/
@@ -45,21 +45,21 @@ class Zend_Service_ReCaptcha extends Zend_Service_Abstract
*
* @var string
*/
- const API_SERVER = 'http://api.recaptcha.net';
+ const API_SERVER = 'http://www.google.com/recaptcha/api';
/**
* URI to the secure API
*
* @var string
*/
- const API_SECURE_SERVER = 'https://api-secure.recaptcha.net';
+ const API_SECURE_SERVER = 'https://www.google.com/recaptcha/api';
/**
* URI to the verify server
*
* @var string
*/
- const VERIFY_SERVER = 'http://api-verify.recaptcha.net/verify';
+ const VERIFY_SERVER = 'http://www.google.com/recaptcha/api/verify';
/**
* Public key used when displaying the captcha
@@ -103,8 +103,9 @@ class Zend_Service_ReCaptcha extends Zend_Service_Abstract
* @var array
*/
protected $_options = array(
- 'theme' => 'red',
- 'lang' => 'en',
+ 'theme' => 'red',
+ 'lang' => 'en',
+ 'custom_translations' => array(),
);
/**
@@ -373,10 +374,11 @@ class Zend_Service_ReCaptcha extends Zend_Service_Abstract
*
* This method uses the public key to fetch a recaptcha form.
*
+ * @param null|string $name Base name for recaptcha form elements
* @return string
* @throws Zend_Service_ReCaptcha_Exception
*/
- public function getHtml()
+ public function getHtml($name = null)
{
if ($this->_publicKey === null) {
/** @see Zend_Service_ReCaptcha_Exception */
@@ -415,6 +417,12 @@ class Zend_Service_ReCaptcha extends Zend_Service_Abstract
SCRIPT;
}
+ $challengeField = 'recaptcha_challenge_field';
+ $responseField = 'recaptcha_response_field';
+ if (!empty($name)) {
+ $challengeField = $name . '[' . $challengeField . ']';
+ $responseField = $name . '[' . $responseField . ']';
+ }
$return = $reCaptchaOptions;
$return .= <<
{$htmlBreak}
-