UpdraftPlus WordPress Backup Plugin - Version 1.8.1

Version Description

  • 2013/12/10 =

  • FEATURE: New "Reporting" add-on - more sophisticated/flexible backup reports (http://updraftplus.com/shop/reporting/)

  • FEATURE: New enhanced add-on for Rackspace Cloud Files users, allowing them to create a new sub-user with exclusive access to the backup container (http://updraftplus.com/shop/cloudfiles-enhanced/) (PHP 5.3.3+ required for this feature)

  • FEATURE: Add region-selection (Dallas/Chicago/Northern Virginia/Sydney/Hong Kong) to Rackspace Cloud Files (PHP 5.3.3+ required for this feature)

  • FEATURE: Add option to 'Backup Now' dialog to not despatch this backup to the cloud

  • FIX: Fix bug in restore of wpcore (Premium) with certain options when backup set was from a previously restored backup with the same certain options

  • FIX: After restoring a site, only delete the backup set from local storage if it was also stored in the cloud (prevents the user having to upload the backup set twice if they want to re-run the restore)

  • FIX: Improve detection of extremely long-running/slow jobs

  • FIX: Fix issue with Rackspace Cloudfiles on WPMU installs

  • TWEAK: Mark as tested up to WordPress 3.8

  • TWEAK: Restore operations are now logged

  • TWEAK: Detect the database connection dropping and recover (seen on a very slow site where PHP ran continuously for 30 mins)

  • TWEAK: Change how permalinks are flushed post-restore. This spares the user from having to manually visit the permalinks page if they had plugins that altered their permalink structure (e.g. WooCommerce).

  • TWEAK: Require fewer file permissions when restoring/migrating

  • TWEAK: Remove various spurious PHP notices caught by the post-1.7.41 extra logging

  • TWEAK: Compress the log file before emailing it, if it is over 6Mb

  • TWEAK: Make sure some potential error messages from Dropbox are displayed properly

  • TWEAK: Work around sites with site/home URL settings in the WP DB that erroneously have a trailing slash

  • TWEAK: Log PHP notices for all job types

Download this release

Release Info

Developer DavidAnderson
Plugin Icon 128x128 UpdraftPlus WordPress Backup Plugin
Version 1.8.1
Comparing to
See all releases

Code changes from version 1.7.41 to 1.8.1

Files changed (294) hide show
  1. admin.php +171 -85
  2. backup.php +109 -39
  3. images/rackspacecloud-logo.png +0 -0
  4. includes/Dropbox/OAuth/Consumer/ConsumerAbstract.php +11 -9
  5. includes/Dropbox/OAuth/Consumer/Curl.php +10 -5
  6. includes/php-opencloud/autoload.php +7 -0
  7. includes/php-opencloud/composer/ClassLoader.php +246 -0
  8. includes/php-opencloud/composer/autoload_classmap.php +9 -0
  9. includes/php-opencloud/composer/autoload_namespaces.php +15 -0
  10. includes/php-opencloud/composer/autoload_real.php +43 -0
  11. includes/php-opencloud/composer/installed.json +321 -0
  12. includes/php-opencloud/guzzle/common/Guzzle/Common/AbstractHasDispatcher.php +49 -0
  13. includes/php-opencloud/guzzle/common/Guzzle/Common/Collection.php +403 -0
  14. includes/php-opencloud/guzzle/common/Guzzle/Common/Event.php +52 -0
  15. includes/php-opencloud/guzzle/common/Guzzle/Common/Exception/BadMethodCallException.php +5 -0
  16. includes/php-opencloud/guzzle/common/Guzzle/Common/Exception/ExceptionCollection.php +85 -0
  17. includes/php-opencloud/guzzle/common/Guzzle/Common/Exception/GuzzleException.php +8 -0
  18. includes/php-opencloud/guzzle/common/Guzzle/Common/Exception/InvalidArgumentException.php +5 -0
  19. includes/php-opencloud/guzzle/common/Guzzle/Common/Exception/RuntimeException.php +5 -0
  20. includes/php-opencloud/guzzle/common/Guzzle/Common/Exception/UnexpectedValueException.php +5 -0
  21. includes/php-opencloud/guzzle/common/Guzzle/Common/FromConfigInterface.php +18 -0
  22. includes/php-opencloud/guzzle/common/Guzzle/Common/HasDispatcherInterface.php +54 -0
  23. includes/php-opencloud/guzzle/common/Guzzle/Common/ToArrayInterface.php +16 -0
  24. includes/php-opencloud/guzzle/common/Guzzle/Common/Version.php +29 -0
  25. includes/php-opencloud/guzzle/common/Guzzle/Common/composer.json +20 -0
  26. includes/php-opencloud/guzzle/http/Guzzle/Http/AbstractEntityBodyDecorator.php +221 -0
  27. includes/php-opencloud/guzzle/http/Guzzle/Http/CachingEntityBody.php +229 -0
  28. includes/php-opencloud/guzzle/http/Guzzle/Http/Client.php +506 -0
  29. includes/php-opencloud/guzzle/http/Guzzle/Http/ClientInterface.php +223 -0
  30. includes/php-opencloud/guzzle/http/Guzzle/Http/Curl/CurlHandle.php +451 -0
  31. includes/php-opencloud/guzzle/http/Guzzle/Http/Curl/CurlMulti.php +363 -0
  32. includes/php-opencloud/guzzle/http/Guzzle/Http/Curl/CurlMultiInterface.php +58 -0
  33. includes/php-opencloud/guzzle/http/Guzzle/Http/Curl/CurlMultiProxy.php +147 -0
  34. includes/php-opencloud/guzzle/http/Guzzle/Http/Curl/CurlVersion.php +66 -0
  35. includes/php-opencloud/guzzle/http/Guzzle/Http/Curl/RequestMediator.php +147 -0
  36. includes/php-opencloud/guzzle/http/Guzzle/Http/EntityBody.php +201 -0
  37. includes/php-opencloud/guzzle/http/Guzzle/Http/EntityBodyInterface.php +73 -0
  38. includes/php-opencloud/guzzle/http/Guzzle/Http/Exception/BadResponseException.php +70 -0
  39. includes/php-opencloud/guzzle/http/Guzzle/Http/Exception/ClientErrorResponseException.php +8 -0
  40. includes/php-opencloud/guzzle/http/Guzzle/Http/Exception/CouldNotRewindStreamException.php +7 -0
  41. includes/php-opencloud/guzzle/http/Guzzle/Http/Exception/CurlException.php +101 -0
  42. includes/php-opencloud/guzzle/http/Guzzle/Http/Exception/HttpException.php +10 -0
  43. includes/php-opencloud/guzzle/http/Guzzle/Http/Exception/MultiTransferException.php +145 -0
  44. includes/php-opencloud/guzzle/http/Guzzle/Http/Exception/RequestException.php +39 -0
  45. includes/php-opencloud/guzzle/http/Guzzle/Http/Exception/ServerErrorResponseException.php +8 -0
  46. includes/php-opencloud/guzzle/http/Guzzle/Http/Exception/TooManyRedirectsException.php +5 -0
  47. includes/php-opencloud/guzzle/http/Guzzle/Http/IoEmittingEntityBody.php +83 -0
  48. includes/php-opencloud/guzzle/http/Guzzle/Http/Message/AbstractMessage.php +220 -0
  49. includes/php-opencloud/guzzle/http/Guzzle/Http/Message/EntityEnclosingRequest.php +248 -0
  50. includes/php-opencloud/guzzle/http/Guzzle/Http/Message/EntityEnclosingRequestInterface.php +136 -0
  51. includes/php-opencloud/guzzle/http/Guzzle/Http/Message/Header.php +178 -0
  52. includes/php-opencloud/guzzle/http/Guzzle/Http/Message/Header/CacheControl.php +121 -0
  53. includes/php-opencloud/guzzle/http/Guzzle/Http/Message/Header/HeaderCollection.php +109 -0
  54. includes/php-opencloud/guzzle/http/Guzzle/Http/Message/Header/HeaderFactory.php +26 -0
  55. includes/php-opencloud/guzzle/http/Guzzle/Http/Message/Header/HeaderFactoryInterface.php +19 -0
  56. includes/php-opencloud/guzzle/http/Guzzle/Http/Message/Header/HeaderInterface.php +83 -0
  57. includes/php-opencloud/guzzle/http/Guzzle/Http/Message/Header/Link.php +93 -0
  58. includes/php-opencloud/guzzle/http/Guzzle/Http/Message/MessageInterface.php +102 -0
  59. includes/php-opencloud/guzzle/http/Guzzle/Http/Message/PostFile.php +109 -0
  60. includes/php-opencloud/guzzle/http/Guzzle/Http/Message/PostFileInterface.php +67 -0
  61. includes/php-opencloud/guzzle/http/Guzzle/Http/Message/Request.php +638 -0
  62. includes/php-opencloud/guzzle/http/Guzzle/Http/Message/RequestFactory.php +356 -0
  63. includes/php-opencloud/guzzle/http/Guzzle/Http/Message/RequestFactoryInterface.php +105 -0
  64. includes/php-opencloud/guzzle/http/Guzzle/Http/Message/RequestInterface.php +318 -0
  65. includes/php-opencloud/guzzle/http/Guzzle/Http/Message/Response.php +957 -0
  66. includes/php-opencloud/guzzle/http/Guzzle/Http/Mimetypes.php +962 -0
  67. includes/php-opencloud/guzzle/http/Guzzle/Http/QueryAggregator/CommaAggregator.php +20 -0
  68. includes/php-opencloud/guzzle/http/Guzzle/Http/QueryAggregator/DuplicateAggregator.php +22 -0
  69. includes/php-opencloud/guzzle/http/Guzzle/Http/QueryAggregator/PhpAggregator.php +27 -0
  70. includes/php-opencloud/guzzle/http/Guzzle/Http/QueryAggregator/QueryAggregatorInterface.php +22 -0
  71. includes/php-opencloud/guzzle/http/Guzzle/Http/QueryString.php +276 -0
  72. includes/php-opencloud/guzzle/http/Guzzle/Http/ReadLimitEntityBody.php +105 -0
  73. includes/php-opencloud/guzzle/http/Guzzle/Http/RedirectPlugin.php +250 -0
  74. includes/php-opencloud/guzzle/http/Guzzle/Http/Resources/cacert.pem +3554 -0
  75. includes/php-opencloud/guzzle/http/Guzzle/Http/Resources/cacert.pem.md5 +1 -0
  76. includes/php-opencloud/guzzle/http/Guzzle/Http/StaticClient.php +157 -0
  77. includes/php-opencloud/guzzle/http/Guzzle/Http/Url.php +531 -0
  78. includes/php-opencloud/guzzle/http/Guzzle/Http/composer.json +32 -0
  79. includes/php-opencloud/guzzle/parser/Guzzle/Parser/Cookie/CookieParser.php +86 -0
  80. includes/php-opencloud/guzzle/parser/Guzzle/Parser/Cookie/CookieParserInterface.php +33 -0
  81. includes/php-opencloud/guzzle/parser/Guzzle/Parser/Message/AbstractMessageParser.php +58 -0
  82. includes/php-opencloud/guzzle/parser/Guzzle/Parser/Message/MessageParser.php +110 -0
  83. includes/php-opencloud/guzzle/parser/Guzzle/Parser/Message/MessageParserInterface.php +27 -0
  84. includes/php-opencloud/guzzle/parser/Guzzle/Parser/Message/PeclHttpMessageParser.php +48 -0
  85. includes/php-opencloud/guzzle/parser/Guzzle/Parser/ParserRegistry.php +75 -0
  86. includes/php-opencloud/guzzle/parser/Guzzle/Parser/UriTemplate/PeclUriTemplate.php +26 -0
  87. includes/php-opencloud/guzzle/parser/Guzzle/Parser/UriTemplate/UriTemplate.php +243 -0
  88. includes/php-opencloud/guzzle/parser/Guzzle/Parser/UriTemplate/UriTemplateInterface.php +21 -0
  89. includes/php-opencloud/guzzle/parser/Guzzle/Parser/Url/UrlParser.php +48 -0
  90. includes/php-opencloud/guzzle/parser/Guzzle/Parser/Url/UrlParserInterface.php +19 -0
  91. includes/php-opencloud/guzzle/parser/Guzzle/Parser/composer.json +19 -0
  92. includes/php-opencloud/guzzle/stream/Guzzle/Stream/PhpStreamRequestFactory.php +270 -0
  93. includes/php-opencloud/guzzle/stream/Guzzle/Stream/Stream.php +289 -0
  94. includes/php-opencloud/guzzle/stream/Guzzle/Stream/StreamInterface.php +218 -0
  95. includes/php-opencloud/guzzle/stream/Guzzle/Stream/StreamRequestFactoryInterface.php +24 -0
  96. includes/php-opencloud/guzzle/stream/Guzzle/Stream/composer.json +30 -0
  97. includes/php-opencloud/rackspace/php-opencloud/.gitignore +13 -0
  98. includes/php-opencloud/rackspace/php-opencloud/.travis.yml +18 -0
  99. includes/php-opencloud/rackspace/php-opencloud/CONTRIBUTING.md +36 -0
  100. includes/php-opencloud/rackspace/php-opencloud/LICENSE +16 -0
  101. includes/php-opencloud/rackspace/php-opencloud/README.md +70 -0
  102. includes/php-opencloud/rackspace/php-opencloud/composer.json +30 -0
  103. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Autoscale/Resource/AbstractResource.php +89 -0
  104. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Autoscale/Resource/Group.php +194 -0
  105. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Autoscale/Resource/GroupConfiguration.php +52 -0
  106. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Autoscale/Resource/LaunchConfiguration.php +62 -0
  107. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Autoscale/Resource/ScalingPolicy.php +61 -0
  108. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Autoscale/Resource/Webhook.php +43 -0
  109. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Autoscale/Service.php +58 -0
  110. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/CloudMonitoring/Exception/AgentException.php +15 -0
  111. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/CloudMonitoring/Exception/AlarmException.php +15 -0
  112. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/CloudMonitoring/Exception/CheckException.php +15 -0
  113. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/CloudMonitoring/Exception/CloudMonitoringException.php +17 -0
  114. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/CloudMonitoring/Exception/EntityException.php +15 -0
  115. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/CloudMonitoring/Exception/MetricException.php +15 -0
  116. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/CloudMonitoring/Exception/NotificationHistoryException.php +15 -0
  117. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/CloudMonitoring/Exception/NotificationPlanException.php +15 -0
  118. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/CloudMonitoring/Exception/ServiceException.php +15 -0
  119. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/CloudMonitoring/Exception/TestException.php +15 -0
  120. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/CloudMonitoring/Exception/ZoneException.php +15 -0
  121. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/CloudMonitoring/Resource/AbstractResource.php +106 -0
  122. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/CloudMonitoring/Resource/Agent.php +75 -0
  123. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/CloudMonitoring/Resource/AgentConnection.php +30 -0
  124. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/CloudMonitoring/Resource/AgentHost.php +51 -0
  125. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/CloudMonitoring/Resource/AgentHostInfo.php +15 -0
  126. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/CloudMonitoring/Resource/AgentTarget.php +61 -0
  127. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/CloudMonitoring/Resource/AgentToken.php +32 -0
  128. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/CloudMonitoring/Resource/Alarm.php +138 -0
  129. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/CloudMonitoring/Resource/Changelog.php +30 -0
  130. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/CloudMonitoring/Resource/Check.php +208 -0
  131. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/CloudMonitoring/Resource/CheckType.php +45 -0
  132. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/CloudMonitoring/Resource/Entity.php +93 -0
  133. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/CloudMonitoring/Resource/Metric.php +21 -0
  134. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/CloudMonitoring/Resource/Notification.php +74 -0
  135. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/CloudMonitoring/Resource/NotificationHistory.php +56 -0
  136. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/CloudMonitoring/Resource/NotificationPlan.php +55 -0
  137. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/CloudMonitoring/Resource/NotificationType.php +26 -0
  138. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/CloudMonitoring/Resource/ReadOnlyResource.php +36 -0
  139. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/CloudMonitoring/Resource/View.php +47 -0
  140. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/CloudMonitoring/Resource/Zone.php +70 -0
  141. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/CloudMonitoring/Service.php +279 -0
  142. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Base.php +426 -0
  143. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Collection.php +408 -0
  144. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Collection/ArrayCollection.php +118 -0
  145. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Collection/PaginatedIterator.php +293 -0
  146. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Collection/ResourceIterator.php +217 -0
  147. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Constants/Datetime.php +35 -0
  148. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Constants/Header.php +65 -0
  149. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Constants/Mime.php +17 -0
  150. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Constants/Service.php +19 -0
  151. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Constants/Size.php +20 -0
  152. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Constants/State.php +21 -0
  153. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/AsyncError.php +5 -0
  154. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/AsyncHttpError.php +5 -0
  155. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/AsyncTimeoutError.php +5 -0
  156. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/AttributeError.php +5 -0
  157. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/AuthenticationError.php +5 -0
  158. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/BaseException.php +7 -0
  159. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/CdnError.php +5 -0
  160. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/CdnHttpError.php +5 -0
  161. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/CdnNotAvailableError.php +5 -0
  162. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/CdnTtlError.php +5 -0
  163. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/CollectionException.php +5 -0
  164. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/ContainerCreateError.php +5 -0
  165. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/ContainerDeleteError.php +5 -0
  166. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/ContainerError.php +5 -0
  167. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/ContainerNameError.php +5 -0
  168. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/ContainerNotEmptyError.php +5 -0
  169. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/ContainerNotFoundError.php +5 -0
  170. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/CreateError.php +5 -0
  171. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/CreateUpdateError.php +5 -0
  172. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/CredentialError.php +5 -0
  173. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/DatabaseCreateError.php +5 -0
  174. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/DatabaseDeleteError.php +5 -0
  175. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/DatabaseListError.php +5 -0
  176. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/DatabaseNameError.php +5 -0
  177. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/DatabaseUpdateError.php +5 -0
  178. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/DeleteError.php +5 -0
  179. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/DocumentError.php +5 -0
  180. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/DomainError.php +5 -0
  181. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/EmptyResponseError.php +5 -0
  182. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/EndpointError.php +5 -0
  183. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/FlavorError.php +5 -0
  184. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/HttpError.php +5 -0
  185. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/HttpForbiddenError.php +5 -0
  186. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/HttpOverLimitError.php +5 -0
  187. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/HttpRetryError.php +5 -0
  188. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/HttpTimeoutError.php +5 -0
  189. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/HttpUnauthorizedError.php +5 -0
  190. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/HttpUrlError.php +5 -0
  191. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/IOError.php +5 -0
  192. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/IdRequiredError.php +5 -0
  193. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/ImageError.php +5 -0
  194. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/InstanceCreateError.php +5 -0
  195. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/InstanceDeleteError.php +5 -0
  196. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/InstanceError.php +5 -0
  197. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/InstanceFlavorError.php +5 -0
  198. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/InstanceNotFound.php +5 -0
  199. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/InstanceUpdateError.php +5 -0
  200. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/InvalidArgumentError.php +5 -0
  201. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/InvalidIdTypeError.php +5 -0
  202. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/InvalidIpTypeError.php +5 -0
  203. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/InvalidParameterError.php +5 -0
  204. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/InvalidRequestError.php +5 -0
  205. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/JsonError.php +5 -0
  206. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/LoggingException.php +16 -0
  207. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/MetadataCreateError.php +5 -0
  208. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/MetadataDeleteError.php +5 -0
  209. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/MetadataError.php +5 -0
  210. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/MetadataJsonError.php +5 -0
  211. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/MetadataKeyError.php +5 -0
  212. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/MetadataPrefixError.php +5 -0
  213. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/MetadataUpdateError.php +5 -0
  214. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/MisMatchedChecksumError.php +5 -0
  215. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/MissingValueError.php +5 -0
  216. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/NameError.php +5 -0
  217. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/NetworkCreateError.php +5 -0
  218. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/NetworkDeleteError.php +5 -0
  219. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/NetworkError.php +5 -0
  220. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/NetworkUpdateError.php +5 -0
  221. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/NetworkUrlError.php +5 -0
  222. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/NoContentTypeError.php +5 -0
  223. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/NoNameError.php +5 -0
  224. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/ObjFetchError.php +5 -0
  225. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/ObjectCopyError.php +5 -0
  226. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/ObjectError.php +5 -0
  227. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/RebuildError.php +5 -0
  228. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/RecordTypeError.php +5 -0
  229. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/ResourceBucketException.php +16 -0
  230. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/RuntimeException.php +5 -0
  231. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/ServerActionError.php +5 -0
  232. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/ServerCreateError.php +5 -0
  233. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/ServerDeleteError.php +5 -0
  234. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/ServerImageScheduleError.php +5 -0
  235. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/ServerIpsError.php +5 -0
  236. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/ServerJsonError.php +5 -0
  237. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/ServerUpdateError.php +5 -0
  238. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/ServerUrlError.php +5 -0
  239. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/ServiceException.php +5 -0
  240. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/SnapshotError.php +5 -0
  241. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/TempUrlMethodError.php +5 -0
  242. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/UnknownError.php +5 -0
  243. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/UnknownParameterError.php +5 -0
  244. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/UnrecognizedServiceError.php +5 -0
  245. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/UnsupportedExtensionError.php +5 -0
  246. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/UnsupportedFeatureExtension.php +5 -0
  247. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/UnsupportedVersionError.php +5 -0
  248. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/UpdateError.php +5 -0
  249. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/UrlError.php +5 -0
  250. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/UserCreateError.php +5 -0
  251. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/UserDeleteError.php +5 -0
  252. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/UserListError.php +5 -0
  253. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/UserNameError.php +5 -0
  254. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/UserUpdateError.php +5 -0
  255. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/VolumeError.php +5 -0
  256. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Exceptions/VolumeTypeError.php +5 -0
  257. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Http/Client.php +52 -0
  258. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Http/Message/Formatter.php +44 -0
  259. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Http/Message/RequestSubscriber.php +69 -0
  260. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Identity/Role.php +15 -0
  261. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Identity/Tenant.php +15 -0
  262. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Identity/User.php +15 -0
  263. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Lang.php +29 -0
  264. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Log/AbstractLogger.php +140 -0
  265. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Log/LogLevel.php +38 -0
  266. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Log/Logger.php +235 -0
  267. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Log/LoggerInterface.php +134 -0
  268. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Metadata.php +110 -0
  269. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/PersistentObject.php +726 -0
  270. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Service/AbstractService.php +417 -0
  271. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Service/Catalog.php +60 -0
  272. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Service/CatalogItem.php +146 -0
  273. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Service/Endpoint.php +112 -0
  274. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Service/NovaService.php +66 -0
  275. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Common/Service/ServiceBuilder.php +39 -0
  276. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Compute/Constants/Network.php +26 -0
  277. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Compute/Constants/ServerState.php +98 -0
  278. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Compute/Exception/KeyPairException.php +13 -0
  279. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Compute/Resource/Flavor.php +51 -0
  280. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Compute/Resource/Image.php +59 -0
  281. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Compute/Resource/KeyPair.php +124 -0
  282. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Compute/Resource/Network.php +116 -0
  283. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Compute/Resource/Server.php +661 -0
  284. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Compute/Resource/ServerMetadata.php +187 -0
  285. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Compute/Resource/VolumeAttachment.php +76 -0
  286. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Compute/Service.php +179 -0
  287. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/DNS/Resource/AsyncResponse.php +98 -0
  288. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/DNS/Resource/Domain.php +241 -0
  289. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/DNS/Resource/Object.php +134 -0
  290. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/DNS/Resource/PtrRecord.php +125 -0
  291. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/DNS/Resource/Record.php +56 -0
  292. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/DNS/Resource/Subdomain.php +26 -0
  293. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/DNS/Service.php +159 -0
  294. includes/php-opencloud/rackspace/php-opencloud/lib/OpenCloud/Database/Resource/Database.php +6 -0
admin.php CHANGED
@@ -74,16 +74,20 @@ class UpdraftPlus_Admin {
74
 
75
  if (version_compare($wp_version, '3.2', '<')) add_action('all_admin_notices', array($this, 'show_admin_warning_wordpressversion'));
76
 
77
- wp_enqueue_script('updraftplus-admin-ui', UPDRAFTPLUS_URL.'/includes/updraft-admin-ui.js', array('jquery', 'jquery-ui-dialog', 'plupload-all'), '29');
78
 
79
  wp_localize_script( 'updraftplus-admin-ui', 'updraftlion', array(
80
  'sendonlyonwarnings' => __('Send a report only when there are warnings/errors', 'updraftplus'),
81
- 'wholebackup' => __('Send entire backup to this address', 'updraftplus'),
 
82
  'rescanning' => __('Rescanning (looking for backups that you have uploaded manually into the internal backup store)...','updraftplus'),
 
83
  'excludedeverything' => __('If you exclude both the database and the files, then you have excluded everything!', 'updraftplus'),
84
  'restoreproceeding' => __('The restore operation has begun. Do not press stop or close your browser until it reports itself as having finished.', 'updraftplus'),
85
  'unexpectedresponse' => __('Unexpected response:','updraftplus'),
86
  'servererrorcode' => __('The web server returned an error code (try again, or check your web server logs)', 'updraftplus'),
 
 
87
  'calculating' => __('calculating...','updraftplus'),
88
  'begunlooking' => __('Begun looking for this entity','updraftplus'),
89
  'stilldownloading' => __('Some files are still downloading or being processed - please wait.', 'updraftplus'),
@@ -101,6 +105,7 @@ class UpdraftPlus_Admin {
101
  'notunderstood' => __('Download error: the server sent us a response which we did not understand.', 'updraftplus'),
102
  'requeststart' => __('Requesting start of backup...', 'updraftplus'),
103
  'phpinfo' => __('PHP information', 'updraftplus'),
 
104
  'raw' => __('Raw backup history', 'updraftplus'),
105
  'notarchive' => __('This file does not appear to be an UpdraftPlus backup archive (such files are .zip or .gz files which have a name like: backup_(time)_(site name)_(code)_(type).(zip|gz)). However, UpdraftPlus archives are standard zip/SQL files - so if you are sure that your file has the right format, then you can rename it to match that pattern.','updraftplus'),
106
  'makesure' => __('(make sure that you were trying to upload a zip file previously created by UpdraftPlus)','updraftplus'),
@@ -115,6 +120,7 @@ class UpdraftPlus_Admin {
115
  'backupnow' => __('Backup Now', 'updraftplus'),
116
  'cancel' => __('Cancel', 'updraftplus'),
117
  'deletebutton' => __('Delete', 'updraftplus'),
 
118
  'close' => __('Close', 'updraftplus'),
119
  'restore' => __('Restore', 'updraftplus'),
120
  ) );
@@ -123,7 +129,7 @@ class UpdraftPlus_Admin {
123
 
124
  function core_upgrade_preamble() {
125
  if (!class_exists('UpdraftPlus_Addon_Autobackup')) {
126
- if (defined('UPDRAFTPLUS_NOADS3')) return;
127
  # TODO: Remove legacy/wrong use of transient any time from 1 Jun 2014
128
  if (true == get_transient('updraftplus_dismissedautobackup')) return;
129
  $dismissed_until = UpdraftPlus_Options::get_updraft_option('updraftplus_dismissedautobackup', 0);
@@ -190,6 +196,9 @@ class UpdraftPlus_Admin {
190
  var updraft_downloader_nonce = '<?php wp_create_nonce("updraftplus_download"); ?>'
191
  </script>
192
  <style type="text/css">
 
 
 
193
  .updraftplus-remove a {
194
  color: red;
195
  }
@@ -260,7 +269,7 @@ class UpdraftPlus_Admin {
260
 
261
  function admin_action_upgrade_pluginortheme() {
262
 
263
- if (isset($_GET['action']) && ($_GET['action'] == 'upgrade-plugin' || $_GET['action'] == 'upgrade-theme') && !class_exists('UpdraftPlus_Addon_Autobackup') && !defined('UPDRAFTPLUS_NOADS3')) {
264
 
265
  # TODO: Remove legacy/erroneous use of transient any time after 1 Jun 2014
266
  $dismissed = get_transient('updraftplus_dismissedautobackup');
@@ -364,7 +373,7 @@ class UpdraftPlus_Admin {
364
  if ($_REQUEST['type'] == $type) $type_match = true;
365
  }
366
 
367
- if (!$type_match && $_REQUEST['type'] != 'db') exit;
368
 
369
  // Get the information on what is wanted
370
  $type = $_REQUEST['type'];
@@ -406,6 +415,8 @@ class UpdraftPlus_Admin {
406
  // Note that log() assumes that the data is in _POST, not _GET
407
  if ($debug_mode) $updraftplus->logfile_open($updraftplus->nonce);
408
 
 
 
409
  $updraftplus->log("Requested to obtain file: timestamp=$timestamp, type=$type, index=$findex");
410
 
411
  $itext = (empty($findex)) ? '' : $findex;
@@ -414,7 +425,7 @@ class UpdraftPlus_Admin {
414
  $services = (isset($backup_history[$timestamp]['service'])) ? $backup_history[$timestamp]['service'] : false;
415
  if (is_string($services)) $services = array($services);
416
 
417
- $updraftplus->jobdata_set('service', $service);
418
 
419
  // Fetch it from the cloud, if we have not already got it
420
 
@@ -447,12 +458,14 @@ class UpdraftPlus_Admin {
447
  $is_downloaded = false;
448
  foreach ($services as $service) {
449
  if ($is_downloaded) continue;
450
- $this->download_file($file, $service);
451
- if (is_readable($fullpath)) {
452
  clearstatcache();
453
  $updraftplus->log('Remote fetch was successful (file size: '.round(filesize($fullpath)/1024,1).' Kb)');
454
  $is_downloaded = true;
455
  } else {
 
 
456
  $updraftplus->log('Remote fetch failed');
457
  }
458
  }
@@ -470,8 +483,10 @@ class UpdraftPlus_Admin {
470
  $updraftplus->log('Remote fetch failed. File '.$fullpath.' did not exist or was unreadable. If you delete local backups then remote retrieval may have failed.');
471
  }
472
 
 
 
473
  @fclose($updraftplus->logfile_handle);
474
- if (!$debug_mode) @unlink($updraftplus->logfile_name);
475
 
476
  exit;
477
 
@@ -492,10 +507,11 @@ class UpdraftPlus_Admin {
492
  $objname = "UpdraftPlus_BackupModule_${service}";
493
  if (method_exists($objname, "download")) {
494
  $remote_obj = new $objname;
495
- $remote_obj->download($file);
496
  } else {
497
  $updraftplus->log("Automatic backup restoration is not available with the method: $service.");
498
  $updraftplus->log("$file: ".sprintf(__("The backup archive for this file could not be found. The remote storage method in use (%s) does not allow us to retrieve files. To perform any restoration using UpdraftPlus, you will need to obtain a copy of this file and place it inside UpdraftPlus's working folder", 'updraftplus'), $service)." (".$this->prune_updraft_dir_prefix($updraftplus->backups_dir_location()).")", 'error');
 
499
  }
500
 
501
  }
@@ -635,7 +651,10 @@ class UpdraftPlus_Admin {
635
  $updraftplus->jobdata_set('job_type', 'delete');
636
  $updraftplus->jobdata_set('job_time_ms', $updraftplus->job_time_ms);
637
 
638
- if (UpdraftPlus_Options::get_updraft_option('updraft_debug_mode')) $updraftplus->logfile_open($updraftplus->nonce);
 
 
 
639
 
640
  $updraft_dir = $updraftplus->backups_dir_location();
641
  $backupable_entities = $updraftplus->get_backupable_file_entities(true, true);
@@ -715,6 +734,11 @@ class UpdraftPlus_Admin {
715
 
716
  print json_encode(array('result' => 'success', 'message' => $message));
717
 
 
 
 
 
 
718
  } elseif ('rawbackuphistory' == $_REQUEST['subaction']) {
719
  echo '<h3>'.__('Known backups (raw)', 'updraftplus').'</h3><pre>';
720
  var_dump($updraftplus->get_backup_history());
@@ -761,12 +785,17 @@ class UpdraftPlus_Admin {
761
  } elseif ('ping' == $_REQUEST['subaction']) {
762
  // The purpose of this is to detect brokenness caused by extra line feeds in plugins/themes - before it breaks other AJAX operations and leads to support requests
763
  echo 'pong';
 
 
764
  } elseif ('phpinfo' == $_REQUEST['subaction']) {
765
  phpinfo(INFO_ALL ^ (INFO_CREDITS | INFO_LICENSE));
 
 
766
  } elseif ('backupnow' == $_REQUEST['subaction']) {
767
  echo '<strong>',__('Schedule backup','updraftplus').':</strong> ';
 
768
  $event = (!empty($_REQUEST['backupnow_nofiles'])) ? 'updraft_backupnow_backup_database' : ((!empty($_REQUEST['backupnow_nodb'])) ? 'updraft_backupnow_backup' : 'updraft_backupnow_backup_all');
769
- if (wp_schedule_single_event(time()+5, $event) === false) {
770
  $updraftplus->log("A backup run failed to schedule");
771
  echo __("Failed.",'updraftplus')."</div>";
772
  } else {
@@ -895,7 +924,7 @@ class UpdraftPlus_Admin {
895
 
896
  $db_file = (is_string($backup['db'])) ? $updraft_dir.'/'.$backup['db'] : $updraft_dir.'/'.$backup['db'][0];
897
 
898
- if (!is_readable($db_file)) return;
899
 
900
  // Encrypted - decrypt it
901
  if ($updraftplus->is_db_encrypted($db_file)) {
@@ -952,24 +981,26 @@ class UpdraftPlus_Admin {
952
 
953
  $migration_warning = false;
954
 
 
 
 
955
  while (!gzeof($dbhandle) && ($line<100 || count($wanted_tables)>0)) {
956
  $line++;
957
  // Up to 1Mb
958
  $buffer = rtrim(gzgets($dbhandle, 1048576));
959
  // Comments are what we are interested in
960
  if (substr($buffer, 0, 1) == '#') {
961
-
962
  if ('' == $old_siteurl && preg_match('/^\# Backup of: (http(.*))$/', $buffer, $matches)) {
963
- $old_siteurl = $matches[1];
964
  $mess[] = __('Backup of:', 'updraftplus').' '.htmlspecialchars($old_siteurl).((!empty($old_wp_version)) ? ' '.sprintf(__('(version: %s)', 'updraftplus'), $old_wp_version) : '');
965
  // Check for should-be migration
966
- if (!$migration_warning && $old_siteurl != site_url()) {
967
  $migration_warning = true;
968
  $powarn = apply_filters('updraftplus_dbscan_urlchange', sprintf(__('Warning: %s', 'updraftplus'), '<a href="http://updraftplus.com/shop/migrator/">'.__('This backup set is from a different site - this is not a restoration, but a migration. You need the Migrator add-on in order to make this work.', 'updraftplus').'</a>'), $old_siteurl, $res);
969
  if (!empty($powarn)) $warn[] = $powarn;
970
  }
971
  } elseif ('' == $old_home && preg_match('/^\# Home URL: (http(.*))$/', $buffer, $matches)) {
972
- $old_home = $matches[1];
973
  // Check for should-be migration
974
  if (!$migration_warning && $old_home != home_url()) {
975
  $migration_warning = true;
@@ -1265,10 +1296,13 @@ CREATE TABLE $wpdb->signups (
1265
  // If we restored the database, then that will have out-of-date information which may confuse the user - so automatically re-scan for them.
1266
  $this->rebuild_backup_history();
1267
  echo '<p><strong>'.__('Restore successful!','updraftplus').'</strong></p>';
 
1268
  echo '<b>'.__('Actions','updraftplus').':</b> <a href="'.UpdraftPlus_Options::admin_page_url().'?page=updraftplus&updraft_restore_success=true">'.__('Return to UpdraftPlus Configuration','updraftplus').'</a>';
1269
  return;
1270
  } elseif (is_wp_error($backup_success)) {
1271
  echo '<p>Restore failed...</p>';
 
 
1272
  $updraftplus->list_errors();
1273
  echo '<b>Actions:</b> <a href="'.UpdraftPlus_Options::admin_page_url().'?page=updraftplus">'.__('Return to UpdraftPlus Configuration','updraftplus').'</a>';
1274
  return;
@@ -1277,21 +1311,11 @@ CREATE TABLE $wpdb->signups (
1277
  return;
1278
  }
1279
  }
1280
- $deleted_old_dirs = false;
1281
- if(isset($_REQUEST['action']) && $_REQUEST['action'] == 'updraft_delete_old_dirs') {
1282
-
1283
- echo '<h1>UpdraftPlus - '.__('Remove old directories','updraftplus').'</h1>';
1284
 
 
1285
  $nonce = (empty($_REQUEST['_wpnonce'])) ? "" : $_REQUEST['_wpnonce'];
1286
- if (!wp_verify_nonce($nonce, 'updraft_delete_old_dirs')) die('Security check');
1287
-
1288
- if($this->delete_old_dirs()) {
1289
- echo '<p>'.__('Old directories successfully removed.','updraftplus').'</p><br/>';
1290
- $deleted_old_dirs = true;
1291
- } else {
1292
- echo '<p>',__('Old directory removal failed for some reason. You may want to do this manually.','updraftplus').'</p><br/>';
1293
- }
1294
- echo '<b>'.__('Actions','updraftplus').':</b> <a href="'.UpdraftPlus_Options::admin_page_url().'?page=updraftplus">'.__('Return to UpdraftPlus Configuration','updraftplus').'</a>';
1295
  return;
1296
  }
1297
 
@@ -1314,6 +1338,8 @@ CREATE TABLE $wpdb->signups (
1314
  return;
1315
  }
1316
 
 
 
1317
  echo '<div id="updraft_backup_started" class="updated fade" style="display:none; max-width: 800px; font-size:140%; line-height: 140%; padding:14px; clear:left;"></div>';
1318
 
1319
  // updraft_file_ids is not deleted
@@ -1335,10 +1361,10 @@ CREATE TABLE $wpdb->signups (
1335
  }
1336
 
1337
  ?>
1338
- <div class="wrap">
1339
  <h1><?php echo $updraftplus->plugin_title; ?></h1>
1340
 
1341
- <?php _e('By UpdraftPlus.Com','updraftplus')?> ( <a href="http://updraftplus.com">UpdraftPlus.Com</a> | <a href="http://updraftplus.com/news/"><?php _e('News','updraftplus');?></a> | <?php if (!defined('UPDRAFTPLUS_NOADS3')) { ?><a href="http://updraftplus.com/shop/"><?php _e("Premium",'updraftplus');?></a> | <?php } ?><a href="http://updraftplus.com/support/"><?php _e("Support",'updraftplus');?></a> | <a href="http://david.dw-perspective.org.uk"><?php _e("Lead developer's homepage",'updraftplus');?></a> | <?php if (1==0 && !defined('UPDRAFTPLUS_NOADS3')) { ?><a href="http://wordshell.net">WordShell - WordPress command line</a> | <a href="http://david.dw-perspective.org.uk/donate"><?php _e('Donate','updraftplus');?></a> | <?php } ?><a href="http://updraftplus.com/support/frequently-asked-questions/">FAQs</a> | <a href="http://profiles.wordpress.org/davidanderson/"><?php _e('More plugins','updraftplus');?></a> ) <?php _e('Version','updraftplus');?>: <?php echo $updraftplus->version; ?>
1342
  <br>
1343
 
1344
  <div id="updraft-hidethis">
@@ -1348,24 +1374,23 @@ CREATE TABLE $wpdb->signups (
1348
 
1349
  <?php
1350
  if(isset($_GET['updraft_restore_success'])) {
 
1351
  echo "<div class=\"updated fade\" style=\"padding:8px;\"><strong>".__('Your backup has been restored.','updraftplus').'</strong> '.__('If your restore included files, then your old (themes, uploads, plugins, whatever) directories have been retained with "-old" appended to their name. Remove them when you are satisfied that the backup worked properly.')."</div>";
1352
  }
1353
 
1354
  $ws_advert = $updraftplus->wordshell_random_advert(1);
1355
  if ($ws_advert) { echo '<div class="updated fade" style="max-width: 800px; font-size:140%; line-height: 140%; padding:14px; clear:left;">'.$ws_advert.'</div>'; }
1356
 
1357
- if($deleted_old_dirs) echo '<div style="color:blue" class=\"updated fade\">'.__('Old directories successfully deleted.','updraftplus').'</div>';
1358
-
1359
  if(!$updraftplus->memory_check(64)) {?>
1360
- <div class="updated fade" style="padding:8px;"><?php _e("Your PHP memory limit (set by your web hosting company) is very low. UpdraftPlus attempted to raise it but was unsuccessful. This plugin may struggle with a memory limit of less than 64 Mb - especially if you have very large files uploaded (though on the other hand, many sites will be successful with a 32Mb limit - your experience may vary).",'updraftplus');?> <?php _e('Current limit is:','updraftplus');?> <?php echo $updraftplus->memory_check_current(); ?> Mb</div>
1361
  <?php
1362
  }
1363
  if($this->scan_old_dirs()) {?>
1364
- <div class="updated fade" style="padding:8px;"><?php _e('Your WordPress install has old directories from its state before you restored/migrated (technical information: these are suffixed with -old). Use this button to delete them (if you have verified that the restoration worked).','updraftplus');?>
1365
- <form method="post" action="<?php echo remove_query_arg(array('updraft_restore_success','action')) ?>">
1366
- <?php wp_nonce_field('updraft_delete_old_dirs'); ?>
1367
  <input type="hidden" name="action" value="updraft_delete_old_dirs" />
1368
- <input type="submit" class="button-primary" value="<?php _e('Delete Old Directories','updraftplus');?>" />
1369
  </form>
1370
  </div>
1371
  <?php
@@ -1443,7 +1468,7 @@ CREATE TABLE $wpdb->signups (
1443
 
1444
  <div style="float:left; width:200px; margin-top: <?php echo (class_exists('UpdraftPlus_Addons_Migrator')) ? "20" : "0" ?>px;">
1445
  <div style="margin-bottom: 10px;">
1446
- <button type="button" <?php echo $backup_disabled ?> class="button-primary updraft-bigbutton" style="padding-top:2px;padding-bottom:2px;font-size:22px !important; min-height: 32px; min-width: 180px;" onclick="jQuery('#updraft-backupnow-modal').dialog('open');"><?php _e('Backup Now','updraftplus');?></button>
1447
  </div>
1448
  <div style="margin-bottom: 10px;">
1449
  <?php
@@ -1535,6 +1560,11 @@ CREATE TABLE $wpdb->signups (
1535
  </tr>
1536
  </table>
1537
 
 
 
 
 
 
1538
  <div id="updraft-delete-modal" title="<?php _e('Delete backup set', 'updraftplus');?>">
1539
  <form id="updraft_delete_form" method="post">
1540
  <p style="margin-top:3px; padding-top:0">
@@ -1641,7 +1671,8 @@ CREATE TABLE $wpdb->signups (
1641
 
1642
  <p>
1643
  <input type="checkbox" id="backupnow_nodb"> <label for="backupnow_nodb"><?php _e("Don't include the database in the backup", 'updraftplus'); ?></label><br>
1644
- <input type="checkbox" id="backupnow_nofiles"> <label for="backupnow_nofiles"><?php _e("Don't include any files in the backup", 'updraftplus'); ?></label>
 
1645
  </p>
1646
 
1647
  <p><?php _e('Does nothing happen when you attempt backups?','updraftplus');?> <a href="http://updraftplus.com/faqs/my-scheduled-backups-and-pressing-backup-now-does-nothing-however-pressing-debug-backup-does-produce-a-backup/"><?php _e('Go here for help.', 'updraftplus');?></a></p>
@@ -1909,18 +1940,37 @@ CREATE TABLE $wpdb->signups (
1909
 
1910
  }
1911
 
 
 
 
 
 
 
 
 
 
 
 
1912
  //deletes the -old directories that are created when a backup is restored.
1913
  function delete_old_dirs() {
1914
- global $wp_filesystem;
1915
- $credentials = request_filesystem_credentials(wp_nonce_url(UpdraftPlus_Options::admin_page_url()."?page=updraftplus&action=updraft_delete_old_dirs", 'updraft_delete_old_dirs'));
1916
  WP_Filesystem($credentials);
1917
- if ( $wp_filesystem->errors->get_error_code() ) {
1918
- foreach ( $wp_filesystem->errors->get_error_messages() as $message )
1919
  show_message($message);
1920
  exit;
1921
  }
1922
  // From WP_CONTENT_DIR - which contains 'themes'
1923
  $ret = $this->delete_old_dirs_dir($wp_filesystem->wp_content_dir());
 
 
 
 
 
 
 
 
1924
  // $ret2 = $this->delete_old_dirs_dir($wp_filesystem->abspath());
1925
  $plugs = untrailingslashit($wp_filesystem->wp_plugins_dir());
1926
  if ($wp_filesystem->is_dir($plugs.'-old')) {
@@ -1936,25 +1986,43 @@ CREATE TABLE $wpdb->signups (
1936
  $ret3 = true;
1937
  }
1938
 
1939
- return ($ret && $ret3) ? true : false;
1940
  }
1941
 
1942
- function delete_old_dirs_dir($dir) {
1943
 
1944
- global $wp_filesystem;
1945
- $list = $wp_filesystem->dirlist($dir);
 
 
 
 
 
 
 
1946
  if (!is_array($list)) return false;
1947
 
1948
  $ret = true;
1949
  foreach ($list as $item) {
1950
- if (substr($item['name'], -4, 4) == "-old") {
 
1951
  //recursively delete
1952
- print "<strong>".__('Delete','updraftplus').": </strong>".htmlspecialchars($item['name']).": ";
1953
- if(!$wp_filesystem->delete($dir.$item['name'], true)) {
1954
- $ret = false;
1955
- print "<strong>".__('Failed', 'updraftplus')."</strong><br>";
 
 
 
 
 
1956
  } else {
1957
- print "<strong>".__('OK', 'updraftplus')."</strong><br>";
 
 
 
 
 
1958
  }
1959
  }
1960
  }
@@ -2017,13 +2085,14 @@ CREATE TABLE $wpdb->signups (
2017
 
2018
  //scans the content dir to see if any -old dirs are present
2019
  function scan_old_dirs() {
2020
- $dirArr = scandir(untrailingslashit(WP_CONTENT_DIR));
2021
- foreach($dirArr as $dir) {
2022
- if (preg_match('/-old$/', $dir)) return true;
2023
- }
 
 
2024
  # No need to scan ABSPATH - we don't backup there
2025
- $plugdir = untrailingslashit(WP_PLUGIN_DIR);
2026
- if (is_dir($plugdir.'-old')) return true;
2027
  return false;
2028
  }
2029
 
@@ -2097,7 +2166,7 @@ CREATE TABLE $wpdb->signups (
2097
  echo __('and retain this many backups', 'updraftplus').': ';
2098
  $updraft_retain = (int)UpdraftPlus_Options::get_updraft_option('updraft_retain', 2);
2099
  $updraft_retain = ($updraft_retain > 0) ? $updraft_retain : 1;
2100
- ?> <input type="text" name="updraft_retain" value="<?php echo $updraft_retain ?>" style="width:40px;" />
2101
  </td>
2102
  </tr>
2103
  <tr>
@@ -2115,7 +2184,7 @@ CREATE TABLE $wpdb->signups (
2115
  echo __('and retain this many backups', 'updraftplus').': ';
2116
  $updraft_retain_db = (int)UpdraftPlus_Options::get_updraft_option('updraft_retain_db', $updraft_retain);
2117
  $updraft_retain_db = ($updraft_retain_db > 0) ? $updraft_retain_db : 1;
2118
- ?> <input type="text" name="updraft_retain_db" value="<?php echo $updraft_retain_db ?>" style="width:40px" />
2119
  </td>
2120
  </tr>
2121
  <tr class="backup-interval-description">
@@ -2217,23 +2286,14 @@ CREATE TABLE $wpdb->signups (
2217
  ?>
2218
 
2219
  <tr>
2220
- <th><?php _e('Email','updraftplus'); ?>:</th>
2221
  <td>
2222
  <?php
2223
  $updraft_email = UpdraftPlus_Options::get_updraft_option('updraft_email');
2224
  ?>
2225
- <input type="text" title="<?php _e('To send to more than one address, separate each address with a comma.', 'updraftplus'); ?>" style="width:260px" name="updraft_email" value="<?php esc_attr_e($updraft_email); ?>" /> <br><?php _e('Enter an address here to have a report sent (and the whole backup, if you choose) to it.','updraftplus'); ?>
2226
  <?php
2227
- $admin_email= get_bloginfo('admin_email');
2228
- if ($updraftplus->have_addons <10) {
2229
- if ($updraft_email && $updraft_email != $admin_email) {
2230
- echo '<strong>';
2231
- }
2232
- echo ' '.apply_filters('updraft_reportingemailnotice', sprintf(__("With the next release of UpdraftPlus, you will need an add-on to use a different email address to the site owner's (%s).", 'updraftplus'), $admin_email));
2233
- if ($updraft_email && $updraft_email != $admin_email) {
2234
- echo '</strong>';
2235
- }
2236
- }
2237
  ?>
2238
  </td>
2239
  </tr>
@@ -2283,7 +2343,7 @@ CREATE TABLE $wpdb->signups (
2283
  foreach ($updraftplus->backup_methods as $method => $description) {
2284
  do_action('updraftplus_config_print_before_storage', $method);
2285
  require_once(UPDRAFTPLUS_DIR.'/methods/'.$method.'.php');
2286
- $call_method = "UpdraftPlus_BackupModule_$method";
2287
  call_user_func(array($call_method, 'config_print'));
2288
  do_action('updraftplus_config_print_after_storage', $method);
2289
  }
@@ -2730,7 +2790,7 @@ ENDHERE;
2730
  $backup_history = UpdraftPlus_Options::get_updraft_option('updraft_backup_history');
2731
  if(!is_array($backup_history[$timestamp])) {
2732
  echo '<p>'.__('This backup does not exist in the backup history - restoration aborted. Timestamp:','updraftplus')." $timestamp</p><br/>";
2733
- return new WP_Error('does_not_exist', 'Backup does not exist in the backup history');
2734
  }
2735
 
2736
  // request_filesystem_credentials passes on fields just via hidden name/value pairs.
@@ -2759,6 +2819,7 @@ ENDHERE;
2759
  $updraftplus->jobdata_set('job_type', 'restore');
2760
  $updraftplus->jobdata_set('job_time_ms', $updraftplus->job_time_ms);
2761
  $updraftplus->logfile_open($updraftplus->nonce);
 
2762
  # TODO: Provide download link for the log file
2763
  # TODO: Automatic purging of old log files
2764
  # TODO: Provide option to auto-email the log file
@@ -2790,12 +2851,14 @@ ENDHERE;
2790
 
2791
  $updraftplus->log("Restore job started. Entities to restore: $entities_log");
2792
 
2793
- if (count($_POST['updraft_restore']) == 0) {
2794
  echo '<p>'.__('ABORT: Could not find the information on which entities to restore.', 'updraftplus').'</p>';
2795
  echo '<p>'.__('If making a request for support, please include this information:','updraftplus').' '.count($_POST).' : '.htmlspecialchars(serialize($_POST)).'</p>';
2796
  return new WP_Error('missing_info', 'Backup information not found');
2797
  }
2798
 
 
 
2799
  /*
2800
  $_POST['updraft_restore'] is typically something like: array( 0=>'db', 1=>'plugins', 2=>'themes'), etc.
2801
  i.e. array ( 'db', 'plugins', themes')
@@ -2810,7 +2873,7 @@ ENDHERE;
2810
  require_once(UPDRAFTPLUS_DIR.'/restorer.php');
2811
 
2812
  global $updraftplus_restorer;
2813
- $updraftplus_restorer = new Updraft_Restorer();
2814
 
2815
  $second_loop = array();
2816
 
@@ -2872,6 +2935,7 @@ ENDHERE;
2872
  echo __('Could not find one of the files for restoration', 'updraftplus')." ($file)<br>";
2873
  $updraftplus->log("$file: ".__('Could not find one of the files for restoration', 'updraftplus'), 'error');
2874
  echo '</div>';
 
2875
  return false;
2876
  }
2877
  }
@@ -2880,13 +2944,16 @@ ENDHERE;
2880
 
2881
  $val = $updraftplus_restorer->pre_restore_backup($files, $type, $info);
2882
  if (is_wp_error($val)) {
 
2883
  foreach ($val->get_error_messages() as $msg) {
2884
  echo '<strong>'.__('Error:', 'updraftplus').'</strong> '.htmlspecialchars($msg).'<br>';
2885
  }
2886
  echo '</div>'; //close the updraft_restore_progress div even if we error
 
2887
  return $val;
2888
  } elseif (false === $val) {
2889
  echo '</div>'; //close the updraft_restore_progress div even if we error
 
2890
  return false;
2891
  }
2892
 
@@ -2894,7 +2961,7 @@ ENDHERE;
2894
  }
2895
  $updraftplus_restorer->delete = (UpdraftPlus_Options::get_updraft_option('updraft_delete_local')) ? true : false;
2896
  if ('none' === $service || empty($service) || (is_array($service) && 1 == count($service) && (in_array('none', $service) || in_array('', $service)))) {
2897
- if ($updraftplus_restorer->delete) _e('Will not delete any archives after unpacking them, because there was no cloud storage for this backup','updraftplus').'<br>';
2898
  $updraftplus_restorer->delete = false;
2899
  }
2900
 
@@ -2905,40 +2972,59 @@ ENDHERE;
2905
  $info = (isset($backupable_entities[$type])) ? $backupable_entities[$type] : array();
2906
 
2907
  echo ('db' == $type) ? "<h2>".__('Database','updraftplus')."</h2>" : "<h2>".$info['description']."</h2>";
2908
-
2909
 
2910
  if (is_string($files)) $files = array($files);
2911
  foreach ($files as $file) {
2912
  $val = $updraftplus_restorer->restore_backup($file, $type, $info);
2913
 
2914
  if(is_wp_error($val)) {
 
2915
  foreach ($val->get_error_messages() as $msg) {
2916
  echo '<strong>'.__('Error message', 'updraftplus').':</strong> '.htmlspecialchars($msg).'<br>';
2917
  }
 
 
 
 
 
 
 
 
 
2918
  echo '</div>'; //close the updraft_restore_progress div even if we error
 
2919
  return $val;
2920
  } elseif (false === $val) {
2921
  echo '</div>'; //close the updraft_restore_progress div even if we error
 
2922
  return false;
2923
  }
2924
  }
2925
  }
2926
 
2927
  echo '</div>'; //close the updraft_restore_progress div
 
 
2928
  return true;
2929
  }
2930
 
2931
  function sort_restoration_entities($a, $b) {
2932
  if ($a == $b) return 0;
2933
  # Put the database first
2934
- if ($a == 'db') return -1;
2935
- if ($b == 'db') return 1;
2936
  return strcmp($a, $b);
2937
  }
2938
 
 
 
 
 
 
2939
  function get_settings_keys() {
2940
- return array('updraft_autobackup_default', 'updraftplus_tmp_googledrive_access_token', 'updraftplus_dismissedautobackup', 'updraft_interval', 'updraft_interval_database', 'updraft_retain', 'updraft_retain_db', 'updraft_encryptionphrase', 'updraft_service', 'updraft_dropbox_appkey', 'updraft_dropbox_secret', 'updraft_googledrive_clientid', 'updraft_googledrive_secret', 'updraft_googledrive_remotepath', 'updraft_ftp_login', 'updraft_ftp_pass', 'updraft_ftp_remote_path', 'updraft_server_address', 'updraft_dir', 'updraft_email', 'updraft_delete_local', 'updraft_debug_mode', 'updraft_include_plugins', 'updraft_include_themes', 'updraft_include_uploads', 'updraft_include_others', 'updraft_include_wpcore', 'updraft_include_wpcore_exclude', 'updraft_include_more',
2941
- 'updraft_include_blogs', 'updraft_include_mu-plugins', 'updraft_include_others_exclude', 'updraft_lastmessage', 'updraft_googledrive_token', 'updraft_dropboxtk_request_token', 'updraft_dropboxtk_access_token', 'updraft_dropbox_folder', 'updraft_last_backup', 'updraft_starttime_files', 'updraft_starttime_db', 'updraft_startday_db', 'updraft_startday_files', 'updraft_sftp_settings', 'updraft_s3generic_login', 'updraft_s3generic_pass', 'updraft_s3generic_remote_path', 'updraft_s3generic_endpoint', 'updraft_webdav_settings', 'updraft_disable_ping', 'updraft_cloudfiles_user', 'updraft_cloudfiles_apikey', 'updraft_cloudfiles_path', 'updraft_cloudfiles_authurl', 'updraft_ssl_useservercerts', 'updraft_ssl_disableverify', 'updraft_s3_login', 'updraft_s3_pass', 'updraft_s3_remote_path', 'updraft_dreamobjects_login', 'updraft_dreamobjects_pass', 'updraft_dreamobjects_remote_path');
2942
  }
2943
 
2944
  }
74
 
75
  if (version_compare($wp_version, '3.2', '<')) add_action('all_admin_notices', array($this, 'show_admin_warning_wordpressversion'));
76
 
77
+ wp_enqueue_script('updraftplus-admin-ui', UPDRAFTPLUS_URL.'/includes/updraft-admin-ui.js', array('jquery', 'jquery-ui-dialog', 'plupload-all'), '30');
78
 
79
  wp_localize_script( 'updraftplus-admin-ui', 'updraftlion', array(
80
  'sendonlyonwarnings' => __('Send a report only when there are warnings/errors', 'updraftplus'),
81
+ 'wholebackup' => __('When the Email storage method is enabled, also send the entire backup', 'updraftplus'),
82
+ 'emailsizelimits' => esc_attr(sprintf(__('Be aware that mail servers tend to have size limits; typically around %s Mb; backups larger than any limits will likely not arrive.','updraftplus'), '10-20')),
83
  'rescanning' => __('Rescanning (looking for backups that you have uploaded manually into the internal backup store)...','updraftplus'),
84
+ 'enteremailhere' => esc_attr(__('To send to more than one address, separate each address with a comma.', 'updraftplus')),
85
  'excludedeverything' => __('If you exclude both the database and the files, then you have excluded everything!', 'updraftplus'),
86
  'restoreproceeding' => __('The restore operation has begun. Do not press stop or close your browser until it reports itself as having finished.', 'updraftplus'),
87
  'unexpectedresponse' => __('Unexpected response:','updraftplus'),
88
  'servererrorcode' => __('The web server returned an error code (try again, or check your web server logs)', 'updraftplus'),
89
+ 'newuserpass' => __("The new user's RackSpace console password is (this will not be shown again):", 'updraftplus'),
90
+ 'trying' => __('Trying...', 'updraftplus'),
91
  'calculating' => __('calculating...','updraftplus'),
92
  'begunlooking' => __('Begun looking for this entity','updraftplus'),
93
  'stilldownloading' => __('Some files are still downloading or being processed - please wait.', 'updraftplus'),
105
  'notunderstood' => __('Download error: the server sent us a response which we did not understand.', 'updraftplus'),
106
  'requeststart' => __('Requesting start of backup...', 'updraftplus'),
107
  'phpinfo' => __('PHP information', 'updraftplus'),
108
+ 'delete_old_dirs' => __('Delete Old Directories', 'updraftplus'),
109
  'raw' => __('Raw backup history', 'updraftplus'),
110
  'notarchive' => __('This file does not appear to be an UpdraftPlus backup archive (such files are .zip or .gz files which have a name like: backup_(time)_(site name)_(code)_(type).(zip|gz)). However, UpdraftPlus archives are standard zip/SQL files - so if you are sure that your file has the right format, then you can rename it to match that pattern.','updraftplus'),
111
  'makesure' => __('(make sure that you were trying to upload a zip file previously created by UpdraftPlus)','updraftplus'),
120
  'backupnow' => __('Backup Now', 'updraftplus'),
121
  'cancel' => __('Cancel', 'updraftplus'),
122
  'deletebutton' => __('Delete', 'updraftplus'),
123
+ 'createbutton' => __('Create', 'updraftplus'),
124
  'close' => __('Close', 'updraftplus'),
125
  'restore' => __('Restore', 'updraftplus'),
126
  ) );
129
 
130
  function core_upgrade_preamble() {
131
  if (!class_exists('UpdraftPlus_Addon_Autobackup')) {
132
+ if (defined('UPDRAFTPLUS_NOADS_A')) return;
133
  # TODO: Remove legacy/wrong use of transient any time from 1 Jun 2014
134
  if (true == get_transient('updraftplus_dismissedautobackup')) return;
135
  $dismissed_until = UpdraftPlus_Options::get_updraft_option('updraftplus_dismissedautobackup', 0);
196
  var updraft_downloader_nonce = '<?php wp_create_nonce("updraftplus_download"); ?>'
197
  </script>
198
  <style type="text/css">
199
+ #updraft-wrap .form-table th {
200
+ width: 230px;
201
+ }
202
  .updraftplus-remove a {
203
  color: red;
204
  }
269
 
270
  function admin_action_upgrade_pluginortheme() {
271
 
272
+ if (isset($_GET['action']) && ($_GET['action'] == 'upgrade-plugin' || $_GET['action'] == 'upgrade-theme') && !class_exists('UpdraftPlus_Addon_Autobackup') && !defined('UPDRAFTPLUS_NOADS_A')) {
273
 
274
  # TODO: Remove legacy/erroneous use of transient any time after 1 Jun 2014
275
  $dismissed = get_transient('updraftplus_dismissedautobackup');
373
  if ($_REQUEST['type'] == $type) $type_match = true;
374
  }
375
 
376
+ if (!$type_match && 'db' != $_REQUEST['type']) exit;
377
 
378
  // Get the information on what is wanted
379
  $type = $_REQUEST['type'];
415
  // Note that log() assumes that the data is in _POST, not _GET
416
  if ($debug_mode) $updraftplus->logfile_open($updraftplus->nonce);
417
 
418
+ set_error_handler(array($updraftplus, 'php_error'), E_ALL & ~E_STRICT);
419
+
420
  $updraftplus->log("Requested to obtain file: timestamp=$timestamp, type=$type, index=$findex");
421
 
422
  $itext = (empty($findex)) ? '' : $findex;
425
  $services = (isset($backup_history[$timestamp]['service'])) ? $backup_history[$timestamp]['service'] : false;
426
  if (is_string($services)) $services = array($services);
427
 
428
+ $updraftplus->jobdata_set('service', $services);
429
 
430
  // Fetch it from the cloud, if we have not already got it
431
 
458
  $is_downloaded = false;
459
  foreach ($services as $service) {
460
  if ($is_downloaded) continue;
461
+ $download = $this->download_file($file, $service);
462
+ if (is_readable($fullpath) && $download !== false) {
463
  clearstatcache();
464
  $updraftplus->log('Remote fetch was successful (file size: '.round(filesize($fullpath)/1024,1).' Kb)');
465
  $is_downloaded = true;
466
  } else {
467
+ clearstatcache();
468
+ if (0 === @filesize($fullpath)) @unlink($fullpath);
469
  $updraftplus->log('Remote fetch failed');
470
  }
471
  }
483
  $updraftplus->log('Remote fetch failed. File '.$fullpath.' did not exist or was unreadable. If you delete local backups then remote retrieval may have failed.');
484
  }
485
 
486
+ restore_error_handler();
487
+
488
  @fclose($updraftplus->logfile_handle);
489
+ if (!$debug_mode) @unlink($updraftplus->logfile_name);
490
 
491
  exit;
492
 
507
  $objname = "UpdraftPlus_BackupModule_${service}";
508
  if (method_exists($objname, "download")) {
509
  $remote_obj = new $objname;
510
+ return $remote_obj->download($file);
511
  } else {
512
  $updraftplus->log("Automatic backup restoration is not available with the method: $service.");
513
  $updraftplus->log("$file: ".sprintf(__("The backup archive for this file could not be found. The remote storage method in use (%s) does not allow us to retrieve files. To perform any restoration using UpdraftPlus, you will need to obtain a copy of this file and place it inside UpdraftPlus's working folder", 'updraftplus'), $service)." (".$this->prune_updraft_dir_prefix($updraftplus->backups_dir_location()).")", 'error');
514
+ return false;
515
  }
516
 
517
  }
651
  $updraftplus->jobdata_set('job_type', 'delete');
652
  $updraftplus->jobdata_set('job_time_ms', $updraftplus->job_time_ms);
653
 
654
+ if (UpdraftPlus_Options::get_updraft_option('updraft_debug_mode')) {
655
+ $updraftplus->logfile_open($updraftplus->nonce);
656
+ set_error_handler(array($updraftplus, 'php_error'), E_ALL & ~E_STRICT);
657
+ }
658
 
659
  $updraft_dir = $updraftplus->backups_dir_location();
660
  $backupable_entities = $updraftplus->get_backupable_file_entities(true, true);
734
 
735
  print json_encode(array('result' => 'success', 'message' => $message));
736
 
737
+ if (UpdraftPlus_Options::get_updraft_option('updraft_debug_mode')) {
738
+ restore_error_handler();
739
+ }
740
+
741
+
742
  } elseif ('rawbackuphistory' == $_REQUEST['subaction']) {
743
  echo '<h3>'.__('Known backups (raw)', 'updraftplus').'</h3><pre>';
744
  var_dump($updraftplus->get_backup_history());
785
  } elseif ('ping' == $_REQUEST['subaction']) {
786
  // The purpose of this is to detect brokenness caused by extra line feeds in plugins/themes - before it breaks other AJAX operations and leads to support requests
787
  echo 'pong';
788
+ } elseif ('delete_old_dirs' == $_REQUEST['subaction']) {
789
+ $this->delete_old_dirs_go(false);
790
  } elseif ('phpinfo' == $_REQUEST['subaction']) {
791
  phpinfo(INFO_ALL ^ (INFO_CREDITS | INFO_LICENSE));
792
+ } elseif ('doaction' == $_REQUEST['subaction'] && !empty($_REQUEST['subsubaction']) && 'updraft_' == substr($_REQUEST['subsubaction'], 0, 8)) {
793
+ do_action($_REQUEST['subsubaction']);
794
  } elseif ('backupnow' == $_REQUEST['subaction']) {
795
  echo '<strong>',__('Schedule backup','updraftplus').':</strong> ';
796
+ $backupnow_nocloud = (empty($_REQUEST['backupnow_nocloud'])) ? false : true;
797
  $event = (!empty($_REQUEST['backupnow_nofiles'])) ? 'updraft_backupnow_backup_database' : ((!empty($_REQUEST['backupnow_nodb'])) ? 'updraft_backupnow_backup' : 'updraft_backupnow_backup_all');
798
+ if (wp_schedule_single_event(time()+5, $event, array($backupnow_nocloud)) === false) {
799
  $updraftplus->log("A backup run failed to schedule");
800
  echo __("Failed.",'updraftplus')."</div>";
801
  } else {
924
 
925
  $db_file = (is_string($backup['db'])) ? $updraft_dir.'/'.$backup['db'] : $updraft_dir.'/'.$backup['db'][0];
926
 
927
+ if (!is_readable($db_file)) return array($mess, $warn, $err);
928
 
929
  // Encrypted - decrypt it
930
  if ($updraftplus->is_db_encrypted($db_file)) {
981
 
982
  $migration_warning = false;
983
 
984
+ # Don't set too high - we want a timely response returned to the browser
985
+ @set_time_limit(90);
986
+
987
  while (!gzeof($dbhandle) && ($line<100 || count($wanted_tables)>0)) {
988
  $line++;
989
  // Up to 1Mb
990
  $buffer = rtrim(gzgets($dbhandle, 1048576));
991
  // Comments are what we are interested in
992
  if (substr($buffer, 0, 1) == '#') {
 
993
  if ('' == $old_siteurl && preg_match('/^\# Backup of: (http(.*))$/', $buffer, $matches)) {
994
+ $old_siteurl = untrailingslashit($matches[1]);
995
  $mess[] = __('Backup of:', 'updraftplus').' '.htmlspecialchars($old_siteurl).((!empty($old_wp_version)) ? ' '.sprintf(__('(version: %s)', 'updraftplus'), $old_wp_version) : '');
996
  // Check for should-be migration
997
+ if (!$migration_warning && $old_siteurl != untrailingslashit(site_url())) {
998
  $migration_warning = true;
999
  $powarn = apply_filters('updraftplus_dbscan_urlchange', sprintf(__('Warning: %s', 'updraftplus'), '<a href="http://updraftplus.com/shop/migrator/">'.__('This backup set is from a different site - this is not a restoration, but a migration. You need the Migrator add-on in order to make this work.', 'updraftplus').'</a>'), $old_siteurl, $res);
1000
  if (!empty($powarn)) $warn[] = $powarn;
1001
  }
1002
  } elseif ('' == $old_home && preg_match('/^\# Home URL: (http(.*))$/', $buffer, $matches)) {
1003
+ $old_home = untrailingslashit($matches[1]);
1004
  // Check for should-be migration
1005
  if (!$migration_warning && $old_home != home_url()) {
1006
  $migration_warning = true;
1296
  // If we restored the database, then that will have out-of-date information which may confuse the user - so automatically re-scan for them.
1297
  $this->rebuild_backup_history();
1298
  echo '<p><strong>'.__('Restore successful!','updraftplus').'</strong></p>';
1299
+ $updraftplus->log("Restore successful");
1300
  echo '<b>'.__('Actions','updraftplus').':</b> <a href="'.UpdraftPlus_Options::admin_page_url().'?page=updraftplus&updraft_restore_success=true">'.__('Return to UpdraftPlus Configuration','updraftplus').'</a>';
1301
  return;
1302
  } elseif (is_wp_error($backup_success)) {
1303
  echo '<p>Restore failed...</p>';
1304
+ $updraftplus->log_wp_error($backup_success);
1305
+ $updraftplus->log("Restore failed");
1306
  $updraftplus->list_errors();
1307
  echo '<b>Actions:</b> <a href="'.UpdraftPlus_Options::admin_page_url().'?page=updraftplus">'.__('Return to UpdraftPlus Configuration','updraftplus').'</a>';
1308
  return;
1311
  return;
1312
  }
1313
  }
 
 
 
 
1314
 
1315
+ if(isset($_REQUEST['action']) && 'updraft_delete_old_dirs' == $_REQUEST['action']) {
1316
  $nonce = (empty($_REQUEST['_wpnonce'])) ? "" : $_REQUEST['_wpnonce'];
1317
+ if (!wp_verify_nonce($nonce, 'updraftplus-credentialtest-nonce')) die('Security check');
1318
+ $this->delete_old_dirs_go();
 
 
 
 
 
 
 
1319
  return;
1320
  }
1321
 
1338
  return;
1339
  }
1340
 
1341
+ do_action('updraftplus_settings_page_init');
1342
+
1343
  echo '<div id="updraft_backup_started" class="updated fade" style="display:none; max-width: 800px; font-size:140%; line-height: 140%; padding:14px; clear:left;"></div>';
1344
 
1345
  // updraft_file_ids is not deleted
1361
  }
1362
 
1363
  ?>
1364
+ <div class="wrap" id="updraft-wrap">
1365
  <h1><?php echo $updraftplus->plugin_title; ?></h1>
1366
 
1367
+ <?php _e('By UpdraftPlus.Com','updraftplus')?> ( <a href="http://updraftplus.com">UpdraftPlus.Com</a> | <a href="http://updraftplus.com/news/"><?php _e('News','updraftplus');?></a> | <?php if (!defined('UPDRAFTPLUS_NOADS_A')) { ?><a href="http://updraftplus.com/shop/"><?php _e("Premium",'updraftplus');?></a> | <?php } ?><a href="http://updraftplus.com/support/"><?php _e("Support",'updraftplus');?></a> | <a href="http://david.dw-perspective.org.uk"><?php _e("Lead developer's homepage",'updraftplus');?></a> | <?php if (1==0 && !defined('UPDRAFTPLUS_NOADS_A')) { ?><a href="http://wordshell.net">WordShell - WordPress command line</a> | <a href="http://david.dw-perspective.org.uk/donate"><?php _e('Donate','updraftplus');?></a> | <?php } ?><a href="http://updraftplus.com/support/frequently-asked-questions/">FAQs</a> | <a href="http://profiles.wordpress.org/davidanderson/"><?php _e('More plugins','updraftplus');?></a> ) <?php _e('Version','updraftplus');?>: <?php echo $updraftplus->version; ?>
1368
  <br>
1369
 
1370
  <div id="updraft-hidethis">
1374
 
1375
  <?php
1376
  if(isset($_GET['updraft_restore_success'])) {
1377
+
1378
  echo "<div class=\"updated fade\" style=\"padding:8px;\"><strong>".__('Your backup has been restored.','updraftplus').'</strong> '.__('If your restore included files, then your old (themes, uploads, plugins, whatever) directories have been retained with "-old" appended to their name. Remove them when you are satisfied that the backup worked properly.')."</div>";
1379
  }
1380
 
1381
  $ws_advert = $updraftplus->wordshell_random_advert(1);
1382
  if ($ws_advert) { echo '<div class="updated fade" style="max-width: 800px; font-size:140%; line-height: 140%; padding:14px; clear:left;">'.$ws_advert.'</div>'; }
1383
 
 
 
1384
  if(!$updraftplus->memory_check(64)) {?>
1385
+ <div class="updated" style="padding:8px;"><?php _e("Your PHP memory limit (set by your web hosting company) is very low. UpdraftPlus attempted to raise it but was unsuccessful. This plugin may struggle with a memory limit of less than 64 Mb - especially if you have very large files uploaded (though on the other hand, many sites will be successful with a 32Mb limit - your experience may vary).",'updraftplus');?> <?php _e('Current limit is:','updraftplus');?> <?php echo $updraftplus->memory_check_current(); ?> Mb</div>
1386
  <?php
1387
  }
1388
  if($this->scan_old_dirs()) {?>
1389
+ <div id="updraft_delete_old_dirs_pagediv" class="updated" style="padding:8px;"><p><?php _e('Your WordPress install has old directories from its state before you restored/migrated (technical information: these are suffixed with -old). You should press this button to delete them as soon as you have verified that the restoration worked.','updraftplus');?></p>
1390
+ <form method="post" onsubmit="return updraft_delete_old_dirs();" action="<?php echo remove_query_arg(array('updraft_restore_success','action')) ?>">
1391
+ <?php wp_nonce_field('updraftplus-credentialtest-nonce'); ?>
1392
  <input type="hidden" name="action" value="updraft_delete_old_dirs" />
1393
+ <input type="submit" class="button-primary" value="<?php echo esc_attr(__('Delete Old Directories', 'updraftplus'));?>" />
1394
  </form>
1395
  </div>
1396
  <?php
1468
 
1469
  <div style="float:left; width:200px; margin-top: <?php echo (class_exists('UpdraftPlus_Addons_Migrator')) ? "20" : "0" ?>px;">
1470
  <div style="margin-bottom: 10px;">
1471
+ <button type="button" <?php echo $backup_disabled ?> class="button-primary updraft-bigbutton" style="padding-top:2px;padding-bottom:2px;font-size:22px !important; min-height: 32px; min-width: 180px;" <?php if ($backup_disabled) echo 'title="'.esc_attr(__('This button is disabled because your backup directory is not writable (see the setting futher down the page).', 'updraftplus')).'" ';?> onclick="jQuery('#updraft-backupnow-modal').dialog('open');"><?php _e('Backup Now', 'updraftplus');?></button>
1472
  </div>
1473
  <div style="margin-bottom: 10px;">
1474
  <?php
1560
  </tr>
1561
  </table>
1562
 
1563
+ <div id="updraft-message-modal" title="UpdraftPlus">
1564
+ <div id="updraft-message-modal-innards" style="font-size:115%; padding: 4px;">
1565
+ </div>
1566
+ </div>
1567
+
1568
  <div id="updraft-delete-modal" title="<?php _e('Delete backup set', 'updraftplus');?>">
1569
  <form id="updraft_delete_form" method="post">
1570
  <p style="margin-top:3px; padding-top:0">
1671
 
1672
  <p>
1673
  <input type="checkbox" id="backupnow_nodb"> <label for="backupnow_nodb"><?php _e("Don't include the database in the backup", 'updraftplus'); ?></label><br>
1674
+ <input type="checkbox" id="backupnow_nofiles"> <label for="backupnow_nofiles"><?php _e("Don't include any files in the backup", 'updraftplus'); ?></label><br>
1675
+ <input type="checkbox" id="backupnow_nocloud"> <label for="backupnow_nocloud"><?php _e("Don't send this backup to cloud storage", 'updraftplus'); ?></label>
1676
  </p>
1677
 
1678
  <p><?php _e('Does nothing happen when you attempt backups?','updraftplus');?> <a href="http://updraftplus.com/faqs/my-scheduled-backups-and-pressing-backup-now-does-nothing-however-pressing-debug-backup-does-produce-a-backup/"><?php _e('Go here for help.', 'updraftplus');?></a></p>
1940
 
1941
  }
1942
 
1943
+ function delete_old_dirs_go($show_return = true) {
1944
+ echo ($show_return) ? '<h1>UpdraftPlus - '.__('Remove old directories', 'updraftplus').'</h1>' : '<h2>'.__('Remove old directories', 'updraftplus').'</h2>';
1945
+
1946
+ if($this->delete_old_dirs()) {
1947
+ echo '<p>'.__('Old directories successfully removed.','updraftplus').'</p><br/>';
1948
+ } else {
1949
+ echo '<p>',__('Old directory removal failed for some reason. You may want to do this manually.','updraftplus').'</p><br/>';
1950
+ }
1951
+ if ($show_return) echo '<b>'.__('Actions','updraftplus').':</b> <a href="'.UpdraftPlus_Options::admin_page_url().'?page=updraftplus">'.__('Return to UpdraftPlus Configuration','updraftplus').'</a>';
1952
+ }
1953
+
1954
  //deletes the -old directories that are created when a backup is restored.
1955
  function delete_old_dirs() {
1956
+ global $wp_filesystem, $updraftplus;
1957
+ $credentials = request_filesystem_credentials(wp_nonce_url(UpdraftPlus_Options::admin_page_url()."?page=updraftplus&action=updraft_delete_old_dirs", 'updraftplus-credentialtest-nonce'));
1958
  WP_Filesystem($credentials);
1959
+ if ($wp_filesystem->errors->get_error_code()) {
1960
+ foreach ($wp_filesystem->errors->get_error_messages() as $message)
1961
  show_message($message);
1962
  exit;
1963
  }
1964
  // From WP_CONTENT_DIR - which contains 'themes'
1965
  $ret = $this->delete_old_dirs_dir($wp_filesystem->wp_content_dir());
1966
+
1967
+ $updraft_dir = $updraftplus->backups_dir_location();
1968
+ if ($updraft_dir) {
1969
+ $ret4 = ($updraft_dir) ? $this->delete_old_dirs_dir($updraft_dir, false) : true;
1970
+ } else {
1971
+ $ret4 = true;
1972
+ }
1973
+
1974
  // $ret2 = $this->delete_old_dirs_dir($wp_filesystem->abspath());
1975
  $plugs = untrailingslashit($wp_filesystem->wp_plugins_dir());
1976
  if ($wp_filesystem->is_dir($plugs.'-old')) {
1986
  $ret3 = true;
1987
  }
1988
 
1989
+ return $ret && $ret3 && $ret4;
1990
  }
1991
 
1992
+ function delete_old_dirs_dir($dir, $wpfs = true) {
1993
 
1994
+ $dir = trailingslashit($dir);
1995
+
1996
+ global $wp_filesystem, $updraftplus;
1997
+
1998
+ if ($wpfs) {
1999
+ $list = $wp_filesystem->dirlist($dir);
2000
+ } else {
2001
+ $list = scandir($dir);
2002
+ }
2003
  if (!is_array($list)) return false;
2004
 
2005
  $ret = true;
2006
  foreach ($list as $item) {
2007
+ $name = (is_array($item)) ? $item['name'] : $item;
2008
+ if ("-old" == substr($name, -4, 4)) {
2009
  //recursively delete
2010
+ print "<strong>".__('Delete','updraftplus').": </strong>".htmlspecialchars($name).": ";
2011
+
2012
+ if ($wpfs) {
2013
+ if(!$wp_filesystem->delete($dir.$name, true)) {
2014
+ $ret = false;
2015
+ echo "<strong>".__('Failed', 'updraftplus')."</strong><br>";
2016
+ } else {
2017
+ echo "<strong>".__('OK', 'updraftplus')."</strong><br>";
2018
+ }
2019
  } else {
2020
+ if ($updraftplus->remove_local_directory($dir.$name)) {
2021
+ echo "<strong>".__('OK', 'updraftplus')."</strong><br>";
2022
+ } else {
2023
+ $ret = false;
2024
+ echo "<strong>".__('Failed', 'updraftplus')."</strong><br>";
2025
+ }
2026
  }
2027
  }
2028
  }
2085
 
2086
  //scans the content dir to see if any -old dirs are present
2087
  function scan_old_dirs() {
2088
+ global $updraftplus;
2089
+ $dirs = scandir(untrailingslashit(WP_CONTENT_DIR));
2090
+ if (!is_array($dirs)) $dirs = array();
2091
+ $dirs_u = scandir($updraftplus->backups_dir_location());
2092
+ if (!is_array($dirs_u)) $dirs_u = array();
2093
+ foreach (array_merge($dirs, $dirs_u) as $dir) { if (preg_match('/-old$/', $dir)) return true; }
2094
  # No need to scan ABSPATH - we don't backup there
2095
+ if (is_dir(untrailingslashit(WP_PLUGIN_DIR).'-old')) return true;
 
2096
  return false;
2097
  }
2098
 
2166
  echo __('and retain this many backups', 'updraftplus').': ';
2167
  $updraft_retain = (int)UpdraftPlus_Options::get_updraft_option('updraft_retain', 2);
2168
  $updraft_retain = ($updraft_retain > 0) ? $updraft_retain : 1;
2169
+ ?> <input type="number" min="1" step="1" name="updraft_retain" value="<?php echo $updraft_retain ?>" style="width:40px;" />
2170
  </td>
2171
  </tr>
2172
  <tr>
2184
  echo __('and retain this many backups', 'updraftplus').': ';
2185
  $updraft_retain_db = (int)UpdraftPlus_Options::get_updraft_option('updraft_retain_db', $updraft_retain);
2186
  $updraft_retain_db = ($updraft_retain_db > 0) ? $updraft_retain_db : 1;
2187
+ ?> <input type="number" min="1" step="1" name="updraft_retain_db" value="<?php echo $updraft_retain_db ?>" style="width:40px" />
2188
  </td>
2189
  </tr>
2190
  <tr class="backup-interval-description">
2286
  ?>
2287
 
2288
  <tr>
2289
+ <th><?php _e('Email', 'updraftplus'); ?>:</th>
2290
  <td>
2291
  <?php
2292
  $updraft_email = UpdraftPlus_Options::get_updraft_option('updraft_email');
2293
  ?>
2294
+ <input type="checkbox" name="updraft_email" value="<?php esc_attr_e(get_bloginfo('admin_email')); ?>"<?php if (!empty($updraft_email)) echo ' checked="checked"';?> > <br><?php echo sprintf(__("Check this box to have a basic report sent to your site's admin address (%s).",'updraftplus'), htmlspecialchars(get_bloginfo('admin_email'))); ?>
2295
  <?php
2296
+ if (!class_exists('UpdraftPlus_Addon_Reporting')) echo '<a href="http://updraftplus.com/shop/reporting/">'.__('For more reporting features, use the Reporting add-on.', 'updraftplus').'</a>';
 
 
 
 
 
 
 
 
 
2297
  ?>
2298
  </td>
2299
  </tr>
2343
  foreach ($updraftplus->backup_methods as $method => $description) {
2344
  do_action('updraftplus_config_print_before_storage', $method);
2345
  require_once(UPDRAFTPLUS_DIR.'/methods/'.$method.'.php');
2346
+ $call_method = 'UpdraftPlus_BackupModule_'.$method;
2347
  call_user_func(array($call_method, 'config_print'));
2348
  do_action('updraftplus_config_print_after_storage', $method);
2349
  }
2790
  $backup_history = UpdraftPlus_Options::get_updraft_option('updraft_backup_history');
2791
  if(!is_array($backup_history[$timestamp])) {
2792
  echo '<p>'.__('This backup does not exist in the backup history - restoration aborted. Timestamp:','updraftplus')." $timestamp</p><br/>";
2793
+ return new WP_Error('does_not_exist', __('Backup does not exist in the backup history', 'updraftplus'));
2794
  }
2795
 
2796
  // request_filesystem_credentials passes on fields just via hidden name/value pairs.
2819
  $updraftplus->jobdata_set('job_type', 'restore');
2820
  $updraftplus->jobdata_set('job_time_ms', $updraftplus->job_time_ms);
2821
  $updraftplus->logfile_open($updraftplus->nonce);
2822
+
2823
  # TODO: Provide download link for the log file
2824
  # TODO: Automatic purging of old log files
2825
  # TODO: Provide option to auto-email the log file
2851
 
2852
  $updraftplus->log("Restore job started. Entities to restore: $entities_log");
2853
 
2854
+ if (0 == count($_POST['updraft_restore'])) {
2855
  echo '<p>'.__('ABORT: Could not find the information on which entities to restore.', 'updraftplus').'</p>';
2856
  echo '<p>'.__('If making a request for support, please include this information:','updraftplus').' '.count($_POST).' : '.htmlspecialchars(serialize($_POST)).'</p>';
2857
  return new WP_Error('missing_info', 'Backup information not found');
2858
  }
2859
 
2860
+ set_error_handler(array($updraftplus, 'php_error'), E_ALL & ~E_STRICT);
2861
+
2862
  /*
2863
  $_POST['updraft_restore'] is typically something like: array( 0=>'db', 1=>'plugins', 2=>'themes'), etc.
2864
  i.e. array ( 'db', 'plugins', themes')
2873
  require_once(UPDRAFTPLUS_DIR.'/restorer.php');
2874
 
2875
  global $updraftplus_restorer;
2876
+ $updraftplus_restorer = new Updraft_Restorer(new Updraft_Restorer_Skin);
2877
 
2878
  $second_loop = array();
2879
 
2935
  echo __('Could not find one of the files for restoration', 'updraftplus')." ($file)<br>";
2936
  $updraftplus->log("$file: ".__('Could not find one of the files for restoration', 'updraftplus'), 'error');
2937
  echo '</div>';
2938
+ restore_error_handler();
2939
  return false;
2940
  }
2941
  }
2944
 
2945
  $val = $updraftplus_restorer->pre_restore_backup($files, $type, $info);
2946
  if (is_wp_error($val)) {
2947
+ $updraftplus->log_wp_error($val);
2948
  foreach ($val->get_error_messages() as $msg) {
2949
  echo '<strong>'.__('Error:', 'updraftplus').'</strong> '.htmlspecialchars($msg).'<br>';
2950
  }
2951
  echo '</div>'; //close the updraft_restore_progress div even if we error
2952
+ restore_error_handler();
2953
  return $val;
2954
  } elseif (false === $val) {
2955
  echo '</div>'; //close the updraft_restore_progress div even if we error
2956
+ restore_error_handler();
2957
  return false;
2958
  }
2959
 
2961
  }
2962
  $updraftplus_restorer->delete = (UpdraftPlus_Options::get_updraft_option('updraft_delete_local')) ? true : false;
2963
  if ('none' === $service || empty($service) || (is_array($service) && 1 == count($service) && (in_array('none', $service) || in_array('', $service)))) {
2964
+ if ($updraftplus_restorer->delete) $updraftplus->log_e('Will not delete any archives after unpacking them, because there was no cloud storage for this backup');
2965
  $updraftplus_restorer->delete = false;
2966
  }
2967
 
2972
  $info = (isset($backupable_entities[$type])) ? $backupable_entities[$type] : array();
2973
 
2974
  echo ('db' == $type) ? "<h2>".__('Database','updraftplus')."</h2>" : "<h2>".$info['description']."</h2>";
2975
+ $updraftplus->log("Entity: ".$type);
2976
 
2977
  if (is_string($files)) $files = array($files);
2978
  foreach ($files as $file) {
2979
  $val = $updraftplus_restorer->restore_backup($file, $type, $info);
2980
 
2981
  if(is_wp_error($val)) {
2982
+ $updraftplus->log_e($val);
2983
  foreach ($val->get_error_messages() as $msg) {
2984
  echo '<strong>'.__('Error message', 'updraftplus').':</strong> '.htmlspecialchars($msg).'<br>';
2985
  }
2986
+ $codes = $val->get_error_codes();
2987
+ if (is_array($codes)) {
2988
+ foreach ($codes as $code) {
2989
+ $data = $val->get_error_data($code);
2990
+ if (!empty($data)) {
2991
+ echo '<strong>'.__('Error data:', 'updraftplus').'</strong> '.htmlspecialchars(serialize($data)).'<br>';
2992
+ }
2993
+ }
2994
+ }
2995
  echo '</div>'; //close the updraft_restore_progress div even if we error
2996
+ restore_error_handler();
2997
  return $val;
2998
  } elseif (false === $val) {
2999
  echo '</div>'; //close the updraft_restore_progress div even if we error
3000
+ restore_error_handler();
3001
  return false;
3002
  }
3003
  }
3004
  }
3005
 
3006
  echo '</div>'; //close the updraft_restore_progress div
3007
+
3008
+ restore_error_handler();
3009
  return true;
3010
  }
3011
 
3012
  function sort_restoration_entities($a, $b) {
3013
  if ($a == $b) return 0;
3014
  # Put the database first
3015
+ if ('db' == $a) return -1;
3016
+ if ('db' == $b) return 1;
3017
  return strcmp($a, $b);
3018
  }
3019
 
3020
+ function return_array($input) {
3021
+ if (!is_array($input)) $input = array();
3022
+ return $input;
3023
+ }
3024
+
3025
  function get_settings_keys() {
3026
+ return array('updraft_autobackup_default', 'updraftplus_tmp_googledrive_access_token', 'updraftplus_dismissedautobackup', 'updraft_interval', 'updraft_interval_database', 'updraft_retain', 'updraft_retain_db', 'updraft_encryptionphrase', 'updraft_service', 'updraft_dropbox_appkey', 'updraft_dropbox_secret', 'updraft_googledrive_clientid', 'updraft_googledrive_secret', 'updraft_googledrive_remotepath', 'updraft_ftp_login', 'updraft_ftp_pass', 'updraft_ftp_remote_path', 'updraft_server_address', 'updraft_dir', 'updraft_email', 'updraft_delete_local', 'updraft_debug_mode', 'updraft_include_plugins', 'updraft_include_themes', 'updraft_include_uploads', 'updraft_include_others', 'updraft_include_wpcore', 'updraft_include_wpcore_exclude', 'updraft_include_more', 'updraft_include_blogs', 'updraft_include_mu-plugins', 'updraft_include_others_exclude', 'updraft_lastmessage', 'updraft_googledrive_token', 'updraft_dropboxtk_request_token', 'updraft_dropboxtk_access_token', 'updraft_dropbox_folder',
3027
+ 'updraft_last_backup', 'updraft_starttime_files', 'updraft_starttime_db', 'updraft_startday_db', 'updraft_startday_files', 'updraft_sftp_settings', 'updraft_s3generic_login', 'updraft_s3generic_pass', 'updraft_s3generic_remote_path', 'updraft_s3generic_endpoint', 'updraft_webdav_settings', 'updraft_disable_ping', 'updraft_cloudfiles', 'updraft_cloudfiles_user', 'updraft_cloudfiles_apikey', 'updraft_cloudfiles_path', 'updraft_cloudfiles_authurl', 'updraft_ssl_useservercerts', 'updraft_ssl_disableverify', 'updraft_s3_login', 'updraft_s3_pass', 'updraft_s3_remote_path', 'updraft_dreamobjects_login', 'updraft_dreamobjects_pass', 'updraft_dreamobjects_remote_path', 'updraft_report_warningsonly', 'updraft_report_wholebackup');
3028
  }
3029
 
3030
  }
backup.php CHANGED
@@ -1,14 +1,10 @@
1
  <?php
2
 
3
- if (!defined ('ABSPATH')) die('No direct access allowed');
4
-
5
  if (!class_exists('UpdraftPlus_PclZip')) require(UPDRAFTPLUS_DIR.'/class-zip.php');
6
 
7
  // This file contains functions that are only needed/loaded when a backup is running (reduces memory usage on other site pages)
8
 
9
- global $updraftplus_backup;
10
- $updraftplus_backup = new UpdraftPlus_Backup();
11
-
12
  class UpdraftPlus_Backup {
13
 
14
  public $index = 0;
@@ -34,7 +30,7 @@ class UpdraftPlus_Backup {
34
  private $updraft_dir;
35
  private $job_file_entities = array();
36
 
37
- public function __construct() {
38
 
39
  global $updraftplus;
40
 
@@ -43,6 +39,11 @@ class UpdraftPlus_Backup {
43
  $this->debug = UpdraftPlus_Options::get_updraft_option('updraft_debug_mode');
44
  $this->updraft_dir = $updraftplus->backups_dir_location();
45
 
 
 
 
 
 
46
  // false means 'tried + failed'; whereas 0 means 'not yet tried'
47
  // Disallow binzip on OpenVZ when we're not sure there's plenty of memory
48
  if ($this->binzip === 0 && (!defined('UPDRAFTPLUS_PREFERPCLZIP') || UPDRAFTPLUS_PREFERPCLZIP != true) && (!defined('UPDRAFTPLUS_NO_BINZIP') || !UPDRAFTPLUS_NO_BINZIP) && $updraftplus->current_resumption <9) {
@@ -152,7 +153,7 @@ class UpdraftPlus_Backup {
152
  if ('.' == $e || '..' == $e || !is_file($this->updraft_dir.'/'.$e)) continue;
153
  $ziparchive_match = preg_match("/$match([0-9]+)?\.zip\.tmp\.([A-Za-z0-9]){6}?$/i", $e);
154
  $binzip_match = preg_match("/^zi([A-Za-z0-9]){6}$/", $e);
155
- if ($time_now-filemtime($this->updraft_dir.'/'.$e) < 30 && ($ziparchive_match || $binzip_match)) {
156
  $updraftplus->terminate_due_to_activity($this->updraft_dir.'/'.$e, $time_now, filemtime($this->updraft_dir.'/'.$e));
157
  }
158
  }
@@ -241,12 +242,14 @@ class UpdraftPlus_Backup {
241
  if (1 == ($updraftplus->current_resumption % 2) && count($services)>2) array_push($services, array_shift($services));
242
  }
243
 
 
 
244
  foreach ($services as $ind => $service) {
245
 
246
  # Used for logging by record_upload_chunk()
247
  $this->current_service = $service;
248
  # Used when deciding whether to delete the local file
249
- $this->last_service = ($ind+1 >= count($services)) ? true : false;
250
 
251
  $updraftplus->log("Cloud backup selection: ".$service);
252
  @set_time_limit(900);
@@ -440,33 +443,27 @@ class UpdraftPlus_Backup {
440
 
441
  $debug_mode = UpdraftPlus_Options::get_updraft_option('updraft_debug_mode');
442
 
443
- $sendmail_to = UpdraftPlus_Options::get_updraft_option('updraft_email');
444
- if (is_array($sendmail_to)) $sendmail_to = implode(',', $sendmail_to);
445
-
446
- $admin_email= get_bloginfo('admin_email');
447
- foreach (explode(',', $sendmail_to) as $sendmail_addr) {
448
- if ($updraftplus->have_addons < 10 && $sendmail_addr != $admin_email) {
449
- $updraftplus->log(sprintf(__("With the next release of UpdraftPlus, you will need an add-on to use a different email address to the site owner's (%s). See: %s", 'updraftplus'), $admin_email, 'http://updraftplus.com/next-updraftplus-release-ready-testing/'), 'warning', 'needpremiumforemail');
450
- }
451
- }
452
 
453
  $backup_files = $updraftplus->jobdata_get('backup_files');
454
  $backup_db = $updraftplus->jobdata_get('backup_database');
455
 
456
- if ($backup_files == 'finished' && ( $backup_db == 'finished' || $backup_db == 'encrypted' ) ) {
457
- $backup_contains = "Files and database";
458
- } elseif ($backup_files == 'finished') {
459
- $backup_contains = ($backup_db == "begun") ? "Files (database backup has not completed)" : "Files only (database was not part of this particular schedule)";
460
  } elseif ($backup_db == 'finished' || $backup_db == 'encrypted') {
461
- $backup_contains = ($backup_files == "begun") ? "Database (files backup has not completed)" : "Database only (files were not part of this particular schedule)";
462
  } else {
463
- $backup_contains = "Unknown/unexpected error - please raise a support request";
464
  }
465
 
466
- $updraftplus->log("Sending email ('$backup_contains') report to: ".substr($sendmail_to, 0, 5)."...");
467
-
468
  $append_log = '';
469
  $attachments = array();
 
 
 
470
  if ($updraftplus->error_count() > 0) {
471
  $append_log .= __('Errors encountered:', 'updraftplus')."\r\n";
472
  $attachments[0] = $updraftplus->logfile_name;
@@ -480,8 +477,9 @@ class UpdraftPlus_Backup {
480
  } elseif (is_string($err)) {
481
  $append_log .= "* ".rtrim($err)."\r\n";
482
  }
 
483
  }
484
- $append_log.="\n";
485
  }
486
  $warnings = $updraftplus->jobdata_get('warnings');
487
  if (is_array($warnings) && count($warnings) >0) {
@@ -490,20 +488,66 @@ class UpdraftPlus_Backup {
490
  foreach ($warnings as $err) {
491
  $append_log .= "* ".rtrim($err)."\r\n";
492
  }
493
- $append_log.="\n";
494
  }
495
 
496
- $append_log .= ($debug_mode && $updraftplus->logfile_name != "") ? "\r\nLog contents:\r\n".file_get_contents($updraftplus->logfile_name) : "" ;
 
 
 
497
 
498
  // We have to use the action in order to set the MIME type on the attachment - by default, WordPress just puts application/octet-stream
499
- if (count($attachments)>0) add_action('phpmailer_init', array($this, 'phpmailer_init'));
500
 
501
- foreach (explode(',', $sendmail_to) as $sendmail_addr) {
 
 
 
 
 
 
502
 
503
- wp_mail(trim($sendmail_addr), __('Backed up', 'updraftplus').': '.get_bloginfo('name').' (UpdraftPlus '.$updraftplus->version.') '.get_date_from_gmt(gmdate('Y-m-d H:i:s', time()), 'Y-m-d H:i'),'Site: '.site_url()."\r\nUpdraftPlus: ".__('WordPress backup is complete','updraftplus').".\r\n".__('Backup contains','updraftplus').': '.$backup_contains."\r\n".__('Latest status', 'updraftplus').": $final_message\r\n\r\n".$updraftplus->wordshell_random_advert(0)."\r\n".$append_log);
504
- if (count($attachments)>0) remove_action('phpmailer_init', array($this, 'phpmailer_init'));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
505
  }
506
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
507
  }
508
 
509
  // The purpose of this function is to make sure that the options table is put in the database first, then the users table, then the usermeta table; and after that the core WP tables - so that when restoring we restore the core tables first
@@ -699,7 +743,6 @@ class UpdraftPlus_Backup {
699
  if (!is_array($files)) $files=array($files);
700
  foreach ($files as $file) $updraftplus->check_recent_modification($this->updraft_dir.'/'.$file);
701
  }
702
-
703
  } elseif ('begun' == $bfiles_status) {
704
  if ($resumption_no>0) {
705
  $updraftplus->log("Creation of backups of directories: had begun; will resume");
@@ -794,6 +837,8 @@ class UpdraftPlus_Backup {
794
 
795
  $how_many_tables = count($all_tables);
796
 
 
 
797
  foreach ($all_tables as $table) {
798
 
799
  $manyrows_warning = false;
@@ -803,6 +848,9 @@ class UpdraftPlus_Backup {
803
  @set_time_limit(900);
804
  // The table file may already exist if we have produced it on a previous run
805
  $table_file_prefix = $file_base.'-db-table-'.$table.'.table';
 
 
 
806
  if (file_exists($this->updraft_dir.'/'.$table_file_prefix.'.gz')) {
807
  $updraftplus->log("Table $table: corresponding file already exists; moving on");
808
  $stitch_files[] = $table_file_prefix;
@@ -854,12 +902,28 @@ class UpdraftPlus_Backup {
854
  $stitch_files[] = $table_file_prefix;
855
 
856
  } else {
 
857
  $updraftplus->log("Skipping table (lacks our prefix): $table");
858
  }
859
 
860
  }
861
  }
862
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
863
  // Race detection - with zip files now being resumable, these can more easily occur, with two running side-by-side
864
  $backup_final_file_name = $backup_file_base.'-db.gz';
865
  $time_now = time();
@@ -878,8 +942,9 @@ class UpdraftPlus_Backup {
878
  // We delay the unlinking because if two runs go concurrently and fail to detect each other (should not happen, but there's no harm in assuming the detection failed) then that leads to files missing from the db dump
879
  $unlink_files = array();
880
 
 
881
  foreach ($stitch_files as $table_file) {
882
- $updraftplus->log("{$table_file}.gz: adding to final database dump");
883
  if (!$handle = gzopen($this->updraft_dir.'/'.$table_file.'.gz', "r")) {
884
  $updraftplus->log("Error: Failed to open database file for reading: ${table_file}.gz");
885
  $updraftplus->log("Failed to open database file for reading: ${table_file}.gz", 'error');
@@ -889,6 +954,7 @@ class UpdraftPlus_Backup {
889
  gzclose($handle);
890
  $unlink_files[] = $this->updraft_dir.'/'.$table_file.'.gz';
891
  }
 
892
  }
893
 
894
  if (defined("DB_CHARSET")) {
@@ -1183,9 +1249,9 @@ class UpdraftPlus_Backup {
1183
  $this->stow("# WordPress MySQL database backup\n");
1184
  $this->stow("# Created by UpdraftPlus version ".$updraftplus->version." (http://updraftplus.com)\n");
1185
  $this->stow("# WordPress Version: $wp_version, running on PHP ".phpversion()." (".$_SERVER["SERVER_SOFTWARE"]."), MySQL $mysql_version\n");
1186
- $this->stow("# Backup of: ".site_url()."\n");
1187
- $this->stow("# Home URL: ".home_url()."\n");
1188
- $this->stow("# Content URL: ".content_url()."\n");
1189
  $this->stow("# Table prefix: ".$this->table_prefix_raw."\n");
1190
  $this->stow("# Site info: multisite=".(is_multisite() ? '1' : '0')."\n");
1191
  $this->stow("# Site info: end\n");
@@ -1207,7 +1273,11 @@ class UpdraftPlus_Backup {
1207
 
1208
  public function phpmailer_init($phpmailer) {
1209
  global $updraftplus;
1210
- $phpmailer->AddAttachment($updraftplus->logfile_name, '', 'base64', 'text/plain');
 
 
 
 
1211
  }
1212
 
1213
  // This function recursively packs the zip, dereferencing symlinks but packing into a single-parent tree for universal unpacking
@@ -1268,7 +1338,7 @@ class UpdraftPlus_Backup {
1268
  #@touch($zipfile);
1269
  } else {
1270
  $updraftplus->log("$fullpath/$e: unreadable file");
1271
- $updraftplus->log(sprintf(__("%s: unreadable file - could not be backed up", 'updraftplus'), $use_path_when_storing.'/'.$e), 'warning');
1272
  }
1273
  } elseif (is_dir($fullpath.'/'.$e)) {
1274
  // no need to addEmptyDir here, as it gets done when we recurse
1
  <?php
2
 
3
+ if (!defined('UPDRAFTPLUS_DIR')) die('No direct access allowed');
 
4
  if (!class_exists('UpdraftPlus_PclZip')) require(UPDRAFTPLUS_DIR.'/class-zip.php');
5
 
6
  // This file contains functions that are only needed/loaded when a backup is running (reduces memory usage on other site pages)
7
 
 
 
 
8
  class UpdraftPlus_Backup {
9
 
10
  public $index = 0;
30
  private $updraft_dir;
31
  private $job_file_entities = array();
32
 
33
+ public function __construct($backup_files) {
34
 
35
  global $updraftplus;
36
 
39
  $this->debug = UpdraftPlus_Options::get_updraft_option('updraft_debug_mode');
40
  $this->updraft_dir = $updraftplus->backups_dir_location();
41
 
42
+ if ('no' === $backup_files) {
43
+ $this->use_zip_object = 'UpdraftPlus_PclZip';
44
+ return;
45
+ }
46
+
47
  // false means 'tried + failed'; whereas 0 means 'not yet tried'
48
  // Disallow binzip on OpenVZ when we're not sure there's plenty of memory
49
  if ($this->binzip === 0 && (!defined('UPDRAFTPLUS_PREFERPCLZIP') || UPDRAFTPLUS_PREFERPCLZIP != true) && (!defined('UPDRAFTPLUS_NO_BINZIP') || !UPDRAFTPLUS_NO_BINZIP) && $updraftplus->current_resumption <9) {
153
  if ('.' == $e || '..' == $e || !is_file($this->updraft_dir.'/'.$e)) continue;
154
  $ziparchive_match = preg_match("/$match([0-9]+)?\.zip\.tmp\.([A-Za-z0-9]){6}?$/i", $e);
155
  $binzip_match = preg_match("/^zi([A-Za-z0-9]){6}$/", $e);
156
+ if ($time_now-filemtime($this->updraft_dir.'/'.$e) < 30 && ($ziparchive_match || (0 != $updraftplus->current_resumption && $binzip_match))) {
157
  $updraftplus->terminate_due_to_activity($this->updraft_dir.'/'.$e, $time_now, filemtime($this->updraft_dir.'/'.$e));
158
  }
159
  }
242
  if (1 == ($updraftplus->current_resumption % 2) && count($services)>2) array_push($services, array_shift($services));
243
  }
244
 
245
+ $errors_before_uploads = $updraftplus->error_count();
246
+
247
  foreach ($services as $ind => $service) {
248
 
249
  # Used for logging by record_upload_chunk()
250
  $this->current_service = $service;
251
  # Used when deciding whether to delete the local file
252
+ $this->last_service = ($ind+1 >= count($services) && $errors_before_uploads == $updraftplus->error_count()) ? true : false;
253
 
254
  $updraftplus->log("Cloud backup selection: ".$service);
255
  @set_time_limit(900);
443
 
444
  $debug_mode = UpdraftPlus_Options::get_updraft_option('updraft_debug_mode');
445
 
446
+ $sendmail_to = $updraftplus->just_one_email(UpdraftPlus_Options::get_updraft_option('updraft_email'));
447
+ if (is_string($sendmail_to)) $sendmail_to = array($sendmail_to);
 
 
 
 
 
 
 
448
 
449
  $backup_files = $updraftplus->jobdata_get('backup_files');
450
  $backup_db = $updraftplus->jobdata_get('backup_database');
451
 
452
+ if ('finished' == $backup_files && ('finished' == $backup_db || 'encrypted' == $backup_db)) {
453
+ $backup_contains = __("Files and database", 'updraftplus');
454
+ } elseif ('finished' == $backup_files) {
455
+ $backup_contains = ($backup_db == "begun") ? __("Files (database backup has not completed)", 'updraftplus') : __("Files only (database was not part of this particular schedule)", 'updraftplus');
456
  } elseif ($backup_db == 'finished' || $backup_db == 'encrypted') {
457
+ $backup_contains = ($backup_files == "begun") ? __("Database (files backup has not completed)", 'updraftplus') : __("Database only (files were not part of this particular schedule)", 'updraftplus');
458
  } else {
459
+ $backup_contains = __("Unknown/unexpected error - please raise a support request", 'updraftplus');
460
  }
461
 
 
 
462
  $append_log = '';
463
  $attachments = array();
464
+
465
+ $error_count = 0;
466
+
467
  if ($updraftplus->error_count() > 0) {
468
  $append_log .= __('Errors encountered:', 'updraftplus')."\r\n";
469
  $attachments[0] = $updraftplus->logfile_name;
477
  } elseif (is_string($err)) {
478
  $append_log .= "* ".rtrim($err)."\r\n";
479
  }
480
+ $error_count++;
481
  }
482
+ $append_log.="\r\n";
483
  }
484
  $warnings = $updraftplus->jobdata_get('warnings');
485
  if (is_array($warnings) && count($warnings) >0) {
488
  foreach ($warnings as $err) {
489
  $append_log .= "* ".rtrim($err)."\r\n";
490
  }
491
+ $append_log.="\r\n";
492
  }
493
 
494
+ if ($debug_mode && '' != $updraftplus->logfile_name && !in_array($updraftplus->logfile_name, $attachments)) {
495
+ $append_log .= "\r\n".__('The log file has been attached to this email.', 'updraftplus');
496
+ $attachments[0] = $updraftplus->logfile_name;
497
+ }
498
 
499
  // We have to use the action in order to set the MIME type on the attachment - by default, WordPress just puts application/octet-stream
 
500
 
501
+ $subject = apply_filters('updraft_report_subject', sprintf(__('Backed up: %s', 'updraftplus'), get_bloginfo('name')).' (UpdraftPlus '.$updraftplus->version.') '.get_date_from_gmt(gmdate('Y-m-d H:i:s', time()), 'Y-m-d H:i'), $error_count, count($warnings));
502
+
503
+ $body = apply_filters('updraft_report_body', __('Backup of:').' '.site_url()."\r\nUpdraftPlus ".__('WordPress backup is complete','updraftplus').".\r\n".__('Backup contains:','updraftplus').' '.$backup_contains."\r\n".__('Latest status:', 'updraftplus').' '.$final_message."\r\n\r\n".$updraftplus->wordshell_random_advert(0)."\r\n".$append_log, $final_message, $backup_contains, $updraftplus->errors, $warnings);
504
+
505
+ $this->attachments = apply_filters('updraft_report_attachments', $attachments);
506
+
507
+ if (count($this->attachments)>0) add_action('phpmailer_init', array($this, 'phpmailer_init'));
508
 
509
+ $attach_size = 0;
510
+ $unlink_files = array();
511
+
512
+ foreach ($this->attachments as $ind => $attach) {
513
+ if ($attach == $updraftplus->logfile_name && filesize($attach) > 6*1048576) {
514
+
515
+ $updraftplus->log("Log file is large (".round(filesize($attach)/1024, 1)." Kb): will compress before e-mailing");
516
+
517
+ if (!$handle = fopen($attach, "r")) {
518
+ $updraftplus->log("Error: Failed to open log file for reading: ".$attach);
519
+ } else {
520
+ if (!$whandle = gzopen($attach.'.gz', 'w')) {
521
+ $updraftplus->log("Error: Failed to open log file for reading: ".$attach.".gz");
522
+ } else {
523
+ while (false !== ($line = @stream_get_line($handle, 2048, "\n"))) {
524
+ @gzwrite($whandle, $line."\n");
525
+ }
526
+ fclose($handle);
527
+ gzclose($whandle);
528
+ $this->attachments[$ind] = $attach.'.gz';
529
+ $unlink_files[] = $attach.'.gz';
530
+ }
531
+ }
532
+ }
533
+ $attach_size += filesize($this->attachments[$ind]);
534
  }
535
 
536
+ foreach ($sendmail_to as $ind => $mailto) {
537
+
538
+ if (false === apply_filters('updraft_report_sendto', true, $mailto, $error_count, count($warnings), $ind)) continue;
539
+
540
+ foreach (explode(',', $mailto) as $sendmail_addr) {
541
+ $updraftplus->log("Sending email ('$backup_contains') report (attachments: ".count($attachments).", size: ".round($attach_size/1024, 1)." Kb) to: ".substr($sendmail_addr, 0, 5)."...");
542
+ wp_mail(trim($sendmail_addr), $subject, $body);
543
+ }
544
+ }
545
+
546
+ foreach ($unlink_files as $file) @unlink($file);
547
+
548
+ do_action('updraft_report_finished');
549
+ if (count($this->attachments)>0) remove_action('phpmailer_init', array($this, 'phpmailer_init'));
550
+
551
  }
552
 
553
  // The purpose of this function is to make sure that the options table is put in the database first, then the users table, then the usermeta table; and after that the core WP tables - so that when restoring we restore the core tables first
743
  if (!is_array($files)) $files=array($files);
744
  foreach ($files as $file) $updraftplus->check_recent_modification($this->updraft_dir.'/'.$file);
745
  }
 
746
  } elseif ('begun' == $bfiles_status) {
747
  if ($resumption_no>0) {
748
  $updraftplus->log("Creation of backups of directories: had begun; will resume");
837
 
838
  $how_many_tables = count($all_tables);
839
 
840
+ $found_options_table = false;
841
+
842
  foreach ($all_tables as $table) {
843
 
844
  $manyrows_warning = false;
848
  @set_time_limit(900);
849
  // The table file may already exist if we have produced it on a previous run
850
  $table_file_prefix = $file_base.'-db-table-'.$table.'.table';
851
+
852
+ if ($this->table_prefix.'options' == $table) $found_options_table = true;
853
+
854
  if (file_exists($this->updraft_dir.'/'.$table_file_prefix.'.gz')) {
855
  $updraftplus->log("Table $table: corresponding file already exists; moving on");
856
  $stitch_files[] = $table_file_prefix;
902
  $stitch_files[] = $table_file_prefix;
903
 
904
  } else {
905
+ $total_tables--;
906
  $updraftplus->log("Skipping table (lacks our prefix): $table");
907
  }
908
 
909
  }
910
  }
911
 
912
+ if (!$found_options_table) {
913
+ $updraftplus->log(__('The database backup appears to have failed - the options table was not found', 'updraftplus'), 'warning', 'optstablenotfound');
914
+ $time_this_run = time()-$updraftplus->opened_log_time;
915
+ if ($time_this_run > 2000) {
916
+ # Have seen this happen; not sure how, but it was apparently deterministic; if the current process had been running for a long time, then apparently all database commands silently failed.
917
+ # If we have been running that long, then the resumption may be far off; bring it closer
918
+ $updraftplus->reschedule(60);
919
+ $updraftplus->log("Have been running very long, and it seems the database went away; terminating");
920
+ $updraftplus->record_still_alive();
921
+ die;
922
+ }
923
+ } else {
924
+ $updraftplus->log_removewarning('optstablenotfound');
925
+ }
926
+
927
  // Race detection - with zip files now being resumable, these can more easily occur, with two running side-by-side
928
  $backup_final_file_name = $backup_file_base.'-db.gz';
929
  $time_now = time();
942
  // We delay the unlinking because if two runs go concurrently and fail to detect each other (should not happen, but there's no harm in assuming the detection failed) then that leads to files missing from the db dump
943
  $unlink_files = array();
944
 
945
+ $sind = 1;
946
  foreach ($stitch_files as $table_file) {
947
+ $updraftplus->log("{$table_file}.gz ($sind/$how_many_tables): adding to final database dump");
948
  if (!$handle = gzopen($this->updraft_dir.'/'.$table_file.'.gz', "r")) {
949
  $updraftplus->log("Error: Failed to open database file for reading: ${table_file}.gz");
950
  $updraftplus->log("Failed to open database file for reading: ${table_file}.gz", 'error');
954
  gzclose($handle);
955
  $unlink_files[] = $this->updraft_dir.'/'.$table_file.'.gz';
956
  }
957
+ $sind++;
958
  }
959
 
960
  if (defined("DB_CHARSET")) {
1249
  $this->stow("# WordPress MySQL database backup\n");
1250
  $this->stow("# Created by UpdraftPlus version ".$updraftplus->version." (http://updraftplus.com)\n");
1251
  $this->stow("# WordPress Version: $wp_version, running on PHP ".phpversion()." (".$_SERVER["SERVER_SOFTWARE"]."), MySQL $mysql_version\n");
1252
+ $this->stow("# Backup of: ".untrailingslashit(site_url())."\n");
1253
+ $this->stow("# Home URL: ".untrailingslashit(home_url())."\n");
1254
+ $this->stow("# Content URL: ".untrailingslashit(content_url())."\n");
1255
  $this->stow("# Table prefix: ".$this->table_prefix_raw."\n");
1256
  $this->stow("# Site info: multisite=".(is_multisite() ? '1' : '0')."\n");
1257
  $this->stow("# Site info: end\n");
1273
 
1274
  public function phpmailer_init($phpmailer) {
1275
  global $updraftplus;
1276
+ if (empty($this->attachments) || !is_array($this->attachments)) return;
1277
+ foreach ($this->attachments as $attach) {
1278
+ $mime_type = (preg_match('/\.gz$/', $attach)) ? 'application/x-gzip' : 'text/plain';
1279
+ $phpmailer->AddAttachment($attach, '', 'base64', $mime_type);
1280
+ }
1281
  }
1282
 
1283
  // This function recursively packs the zip, dereferencing symlinks but packing into a single-parent tree for universal unpacking
1338
  #@touch($zipfile);
1339
  } else {
1340
  $updraftplus->log("$fullpath/$e: unreadable file");
1341
+ $updraftplus->log(sprintf(__("%s: unreadable file - could not be backed up", 'updraftplus'), $use_path_when_storing.'/'.$e), 'warning', "unrfile-$e");
1342
  }
1343
  } elseif (is_dir($fullpath.'/'.$e)) {
1344
  // no need to addEmptyDir here, as it gets done when we recurse
images/rackspacecloud-logo.png CHANGED
Binary file
includes/Dropbox/OAuth/Consumer/ConsumerAbstract.php CHANGED
@@ -49,7 +49,7 @@ abstract class Dropbox_ConsumerAbstract
49
  $this->getAccessToken();
50
  } catch(Dropbox_Exception $e) {
51
  global $updraftplus;
52
- $updraftplus->log($e->getMessage().' - need to reauthenticate this site with Dropbox (if this fails, then you can also try wiping your settings from the Expert Settings section');
53
  $this->getRequestToken();
54
  $this->authorise();
55
  }
@@ -80,22 +80,23 @@ abstract class Dropbox_ConsumerAbstract
80
  private function authorise()
81
  {
82
  // Only redirect if not using CLI
83
- if (PHP_SAPI !== 'cli' && (!defined('DOING_CRON') || !DOING_CRON)) {
84
  $url = $this->getAuthoriseUrl();
85
  if (!headers_sent()) {
86
  header('Location: ' . $url);
 
87
  } else {
88
  throw new Dropbox_Exception(sprintf(__('The %s authentication could not go ahead, because something else on your site is breaking it. Try disabling your other plugins and switching to a default theme. (Specifically, you are looking for the component that sends output (most likely PHP warnings/errors) before the page begins. Turning off any debugging settings may also help).', ''), 'Dropbox'));
89
  }
90
- exit;
91
  ?><?php
92
- return;
93
  }
94
  global $updraftplus;
95
- $updraftplus->log('Dropbox reauthorisation needed; but we are running from cron or the CLI, so this is not possible');
96
- UpdraftPlus_Options::update_updraft_option("updraft_dropboxtk_request_token",'');
97
- $updraftplus->log(sprintf(__('You need to re-authenticate with %s, as your existing credentials are not working.', 'updraftplus'), 'Dropbox'), 'error');
98
- exit;
 
99
  }
100
 
101
  /**
@@ -193,7 +194,8 @@ abstract class Dropbox_ConsumerAbstract
193
  // If the value is a file upload (prefixed with @), replace it with
194
  // the destination filename, the file path will be sent in POSTFIELDS
195
  if (isset($value[0]) && $value[0] === '@') $value = $params['filename'];
196
- $encoded[] = $this->encode($param) . '=' . $this->encode($value);
 
197
  } else {
198
  unset($params[$param]);
199
  }
49
  $this->getAccessToken();
50
  } catch(Dropbox_Exception $e) {
51
  global $updraftplus;
52
+ $updraftplus->log($e->getMessage().' - need to reauthenticate this site with Dropbox (if this fails, then you can also try wiping your settings from the Expert Settings section)');
53
  $this->getRequestToken();
54
  $this->authorise();
55
  }
80
  private function authorise()
81
  {
82
  // Only redirect if not using CLI
83
+ if (PHP_SAPI !== 'cli' && (!defined('DOING_CRON') || !DOING_CRON) && (!defined('DOING_AJAX') || !DOING_AJAX)) {
84
  $url = $this->getAuthoriseUrl();
85
  if (!headers_sent()) {
86
  header('Location: ' . $url);
87
+ exit;
88
  } else {
89
  throw new Dropbox_Exception(sprintf(__('The %s authentication could not go ahead, because something else on your site is breaking it. Try disabling your other plugins and switching to a default theme. (Specifically, you are looking for the component that sends output (most likely PHP warnings/errors) before the page begins. Turning off any debugging settings may also help).', ''), 'Dropbox'));
90
  }
 
91
  ?><?php
92
+ return false;
93
  }
94
  global $updraftplus;
95
+ $updraftplus->log('Dropbox reauthorisation needed; but we are running from cron, AJAX or the CLI, so this is not possible');
96
+ UpdraftPlus_Options::update_updraft_option("updraft_dropboxtk_request_token", '');
97
+ throw new Dropbox_Exception(sprintf(__('You need to re-authenticate with %s, as your existing credentials are not working.', 'updraftplus'), 'Dropbox'));
98
+ #$updraftplus->log(sprintf(__('You need to re-authenticate with %s, as your existing credentials are not working.', 'updraftplus'), 'Dropbox'), 'error');
99
+ return false;
100
  }
101
 
102
  /**
194
  // If the value is a file upload (prefixed with @), replace it with
195
  // the destination filename, the file path will be sent in POSTFIELDS
196
  if (isset($value[0]) && $value[0] === '@') $value = $params['filename'];
197
+ # Prevent spurious PHP warning by only doing non-arrays
198
+ if (!is_array($value)) $encoded[] = $this->encode($param) . '=' . $this->encode($value);
199
  } else {
200
  unset($params[$param]);
201
  }
includes/Dropbox/OAuth/Consumer/Curl.php CHANGED
@@ -84,6 +84,7 @@ class Dropbox_Curl extends Dropbox_ConsumerAbstract
84
  $options[CURLOPT_HEADER] = false;
85
  $options[CURLOPT_FILE] = $this->outFile;
86
  $options[CURLOPT_BINARYTRANSFER] = true;
 
87
  if (isset($additional['headers'])) $options[CURLOPT_HTTPHEADER] = $additional['headers'];
88
  $this->outFile = null;
89
  } elseif ($method == 'POST') { // POST
@@ -97,13 +98,15 @@ class Dropbox_Curl extends Dropbox_ConsumerAbstract
97
  fseek($this->inFile, 0);
98
  $this->inFile = null;
99
  }
100
-
101
  // Set the cURL options at once
102
  curl_setopt_array($handle, $options);
103
 
104
  // Execute, get any error and close
105
  $response = curl_exec($handle);
106
  $error = curl_error($handle);
 
 
107
  curl_close($handle);
108
 
109
  //Check if a cURL error has occured
@@ -117,10 +120,12 @@ class Dropbox_Curl extends Dropbox_ConsumerAbstract
117
 
118
  // Set the last response
119
  $this->lastResponse = $response;
 
 
120
 
121
  // The API doesn't return an error message for the 304 status code...
122
  // 304's are only returned when the path supplied during metadata calls has not been modified
123
- if ($response['code'] == 304) {
124
  $response['body'] = new stdClass;
125
  $response['body']->error = 'The folder contents have not changed';
126
  }
@@ -128,7 +133,7 @@ class Dropbox_Curl extends Dropbox_ConsumerAbstract
128
  // Check if an error occurred and throw an Exception
129
  if (!empty($response['body']->error)) {
130
  // Dropbox returns error messages inconsistently...
131
- if ($response['body']->error instanceof \stdClass) {
132
  $array = array_values((array) $response['body']->error);
133
  $message = $array[0];
134
  } else {
@@ -136,7 +141,7 @@ class Dropbox_Curl extends Dropbox_ConsumerAbstract
136
  }
137
 
138
  // Throw an Exception with the appropriate with the appropriate message and code
139
- switch ($response['code']) {
140
  case 304:
141
  throw new Dropbox_NotModifiedException($message, 304);
142
  case 400:
@@ -148,7 +153,7 @@ class Dropbox_Curl extends Dropbox_ConsumerAbstract
148
  case 415:
149
  throw new Dropbox_UnsupportedMediaTypeException($message, 415);
150
  default:
151
- throw new Dropbox_Exception($message, $response['code']);
152
  }
153
  }
154
 
84
  $options[CURLOPT_HEADER] = false;
85
  $options[CURLOPT_FILE] = $this->outFile;
86
  $options[CURLOPT_BINARYTRANSFER] = true;
87
+ $options[CURLOPT_FAILONERROR] = true;
88
  if (isset($additional['headers'])) $options[CURLOPT_HTTPHEADER] = $additional['headers'];
89
  $this->outFile = null;
90
  } elseif ($method == 'POST') { // POST
98
  fseek($this->inFile, 0);
99
  $this->inFile = null;
100
  }
101
+
102
  // Set the cURL options at once
103
  curl_setopt_array($handle, $options);
104
 
105
  // Execute, get any error and close
106
  $response = curl_exec($handle);
107
  $error = curl_error($handle);
108
+ $getinfo = curl_getinfo($handle);
109
+
110
  curl_close($handle);
111
 
112
  //Check if a cURL error has occured
120
 
121
  // Set the last response
122
  $this->lastResponse = $response;
123
+
124
+ $code = (!empty($response['code'])) ? $response['code'] : $getinfo['http_code'];
125
 
126
  // The API doesn't return an error message for the 304 status code...
127
  // 304's are only returned when the path supplied during metadata calls has not been modified
128
+ if ($code == 304) {
129
  $response['body'] = new stdClass;
130
  $response['body']->error = 'The folder contents have not changed';
131
  }
133
  // Check if an error occurred and throw an Exception
134
  if (!empty($response['body']->error)) {
135
  // Dropbox returns error messages inconsistently...
136
+ if ($response['body']->error instanceof stdClass) {
137
  $array = array_values((array) $response['body']->error);
138
  $message = $array[0];
139
  } else {
141
  }
142
 
143
  // Throw an Exception with the appropriate with the appropriate message and code
144
+ switch ($code) {
145
  case 304:
146
  throw new Dropbox_NotModifiedException($message, 304);
147
  case 400:
153
  case 415:
154
  throw new Dropbox_UnsupportedMediaTypeException($message, 415);
155
  default:
156
+ throw new Dropbox_Exception($message, $code);
157
  }
158
  }
159
 
includes/php-opencloud/autoload.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload.php @generated by Composer
4
+
5
+ require_once __DIR__ . '/composer' . '/autoload_real.php';
6
+
7
+ return ComposerAutoloaderInit3357fec9f50023e8458d16284bb22ab5::getLoader();
includes/php-opencloud/composer/ClassLoader.php ADDED
@@ -0,0 +1,246 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * This file is part of Composer.
5
+ *
6
+ * (c) Nils Adermann <naderman@naderman.de>
7
+ * Jordi Boggiano <j.boggiano@seld.be>
8
+ *
9
+ * For the full copyright and license information, please view the LICENSE
10
+ * file that was distributed with this source code.
11
+ */
12
+
13
+ namespace Composer\Autoload;
14
+
15
+ /**
16
+ * ClassLoader implements a PSR-0 class loader
17
+ *
18
+ * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md
19
+ *
20
+ * $loader = new \Composer\Autoload\ClassLoader();
21
+ *
22
+ * // register classes with namespaces
23
+ * $loader->add('Symfony\Component', __DIR__.'/component');
24
+ * $loader->add('Symfony', __DIR__.'/framework');
25
+ *
26
+ * // activate the autoloader
27
+ * $loader->register();
28
+ *
29
+ * // to enable searching the include path (eg. for PEAR packages)
30
+ * $loader->setUseIncludePath(true);
31
+ *
32
+ * In this example, if you try to use a class in the Symfony\Component
33
+ * namespace or one of its children (Symfony\Component\Console for instance),
34
+ * the autoloader will first look for the class under the component/
35
+ * directory, and it will then fallback to the framework/ directory if not
36
+ * found before giving up.
37
+ *
38
+ * This class is loosely based on the Symfony UniversalClassLoader.
39
+ *
40
+ * @author Fabien Potencier <fabien@symfony.com>
41
+ * @author Jordi Boggiano <j.boggiano@seld.be>
42
+ */
43
+ class ClassLoader
44
+ {
45
+ private $prefixes = array();
46
+ private $fallbackDirs = array();
47
+ private $useIncludePath = false;
48
+ private $classMap = array();
49
+
50
+ public function getPrefixes()
51
+ {
52
+ return call_user_func_array('array_merge', $this->prefixes);
53
+ }
54
+
55
+ public function getFallbackDirs()
56
+ {
57
+ return $this->fallbackDirs;
58
+ }
59
+
60
+ public function getClassMap()
61
+ {
62
+ return $this->classMap;
63
+ }
64
+
65
+ /**
66
+ * @param array $classMap Class to filename map
67
+ */
68
+ public function addClassMap(array $classMap)
69
+ {
70
+ if ($this->classMap) {
71
+ $this->classMap = array_merge($this->classMap, $classMap);
72
+ } else {
73
+ $this->classMap = $classMap;
74
+ }
75
+ }
76
+
77
+ /**
78
+ * Registers a set of classes, merging with any others previously set.
79
+ *
80
+ * @param string $prefix The classes prefix
81
+ * @param array|string $paths The location(s) of the classes
82
+ * @param bool $prepend Prepend the location(s)
83
+ */
84
+ public function add($prefix, $paths, $prepend = false)
85
+ {
86
+ if (!$prefix) {
87
+ if ($prepend) {
88
+ $this->fallbackDirs = array_merge(
89
+ (array) $paths,
90
+ $this->fallbackDirs
91
+ );
92
+ } else {
93
+ $this->fallbackDirs = array_merge(
94
+ $this->fallbackDirs,
95
+ (array) $paths
96
+ );
97
+ }
98
+
99
+ return;
100
+ }
101
+
102
+ $first = $prefix[0];
103
+ if (!isset($this->prefixes[$first][$prefix])) {
104
+ $this->prefixes[$first][$prefix] = (array) $paths;
105
+
106
+ return;
107
+ }
108
+ if ($prepend) {
109
+ $this->prefixes[$first][$prefix] = array_merge(
110
+ (array) $paths,
111
+ $this->prefixes[$first][$prefix]
112
+ );
113
+ } else {
114
+ $this->prefixes[$first][$prefix] = array_merge(
115
+ $this->prefixes[$first][$prefix],
116
+ (array) $paths
117
+ );
118
+ }
119
+ }
120
+
121
+ /**
122
+ * Registers a set of classes, replacing any others previously set.
123
+ *
124
+ * @param string $prefix The classes prefix
125
+ * @param array|string $paths The location(s) of the classes
126
+ */
127
+ public function set($prefix, $paths)
128
+ {
129
+ if (!$prefix) {
130
+ $this->fallbackDirs = (array) $paths;
131
+
132
+ return;
133
+ }
134
+ $this->prefixes[substr($prefix, 0, 1)][$prefix] = (array) $paths;
135
+ }
136
+
137
+ /**
138
+ * Turns on searching the include path for class files.
139
+ *
140
+ * @param bool $useIncludePath
141
+ */
142
+ public function setUseIncludePath($useIncludePath)
143
+ {
144
+ $this->useIncludePath = $useIncludePath;
145
+ }
146
+
147
+ /**
148
+ * Can be used to check if the autoloader uses the include path to check
149
+ * for classes.
150
+ *
151
+ * @return bool
152
+ */
153
+ public function getUseIncludePath()
154
+ {
155
+ return $this->useIncludePath;
156
+ }
157
+
158
+ /**
159
+ * Registers this instance as an autoloader.
160
+ *
161
+ * @param bool $prepend Whether to prepend the autoloader or not
162
+ */
163
+ public function register($prepend = false)
164
+ {
165
+ spl_autoload_register(array($this, 'loadClass'), true, $prepend);
166
+ }
167
+
168
+ /**
169
+ * Unregisters this instance as an autoloader.
170
+ */
171
+ public function unregister()
172
+ {
173
+ spl_autoload_unregister(array($this, 'loadClass'));
174
+ }
175
+
176
+ /**
177
+ * Loads the given class or interface.
178
+ *
179
+ * @param string $class The name of the class
180
+ * @return bool|null True if loaded, null otherwise
181
+ */
182
+ public function loadClass($class)
183
+ {
184
+ if ($file = $this->findFile($class)) {
185
+ include $file;
186
+
187
+ return true;
188
+ }
189
+ }
190
+
191
+ /**
192
+ * Finds the path to the file where the class is defined.
193
+ *
194
+ * @param string $class The name of the class
195
+ *
196
+ * @return string|false The path if found, false otherwise
197
+ */
198
+ public function findFile($class)
199
+ {
200
+ // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731
201
+ if ('\\' == $class[0]) {
202
+ $class = substr($class, 1);
203
+ }
204
+
205
+ if (isset($this->classMap[$class])) {
206
+ return $this->classMap[$class];
207
+ }
208
+
209
+ if (false !== $pos = strrpos($class, '\\')) {
210
+ // namespaced class name
211
+ $classPath = strtr(substr($class, 0, $pos), '\\', DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
212
+ $className = substr($class, $pos + 1);
213
+ } else {
214
+ // PEAR-like class name
215
+ $classPath = null;
216
+ $className = $class;
217
+ }
218
+
219
+ $classPath .= strtr($className, '_', DIRECTORY_SEPARATOR) . '.php';
220
+
221
+ $first = $class[0];
222
+ if (isset($this->prefixes[$first])) {
223
+ foreach ($this->prefixes[$first] as $prefix => $dirs) {
224
+ if (0 === strpos($class, $prefix)) {
225
+ foreach ($dirs as $dir) {
226
+ if (file_exists($dir . DIRECTORY_SEPARATOR . $classPath)) {
227
+ return $dir . DIRECTORY_SEPARATOR . $classPath;
228
+ }
229
+ }
230
+ }
231
+ }
232
+ }
233
+
234
+ foreach ($this->fallbackDirs as $dir) {
235
+ if (file_exists($dir . DIRECTORY_SEPARATOR . $classPath)) {
236
+ return $dir . DIRECTORY_SEPARATOR . $classPath;
237
+ }
238
+ }
239
+
240
+ if ($this->useIncludePath && $file = stream_resolve_include_path($classPath)) {
241
+ return $file;
242
+ }
243
+
244
+ return $this->classMap[$class] = false;
245
+ }
246
+ }
includes/php-opencloud/composer/autoload_classmap.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_classmap.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname($vendorDir);
7
+
8
+ return array(
9
+ );
includes/php-opencloud/composer/autoload_namespaces.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_namespaces.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname($vendorDir);
7
+
8
+ return array(
9
+ 'Symfony\\Component\\EventDispatcher\\' => array($vendorDir . '/symfony/event-dispatcher'),
10
+ 'OpenCloud' => array($vendorDir . '/rackspace/php-opencloud/lib', $vendorDir . '/rackspace/php-opencloud/tests'),
11
+ 'Guzzle\\Stream' => array($vendorDir . '/guzzle/stream'),
12
+ 'Guzzle\\Parser' => array($vendorDir . '/guzzle/parser'),
13
+ 'Guzzle\\Http' => array($vendorDir . '/guzzle/http'),
14
+ 'Guzzle\\Common' => array($vendorDir . '/guzzle/common'),
15
+ );
includes/php-opencloud/composer/autoload_real.php ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_real.php @generated by Composer
4
+
5
+ class ComposerAutoloaderInit3357fec9f50023e8458d16284bb22ab5
6
+ {
7
+ private static $loader;
8
+
9
+ public static function loadClassLoader($class)
10
+ {
11
+ if ('Composer\Autoload\ClassLoader' === $class) {
12
+ require __DIR__ . '/ClassLoader.php';
13
+ }
14
+ }
15
+
16
+ public static function getLoader()
17
+ {
18
+ if (null !== self::$loader) {
19
+ return self::$loader;
20
+ }
21
+
22
+ spl_autoload_register(array('ComposerAutoloaderInit3357fec9f50023e8458d16284bb22ab5', 'loadClassLoader'), true, true);
23
+ self::$loader = $loader = new \Composer\Autoload\ClassLoader();
24
+ spl_autoload_unregister(array('ComposerAutoloaderInit3357fec9f50023e8458d16284bb22ab5', 'loadClassLoader'));
25
+
26
+ $vendorDir = dirname(__DIR__);
27
+ $baseDir = dirname($vendorDir);
28
+
29
+ $map = require __DIR__ . '/autoload_namespaces.php';
30
+ foreach ($map as $namespace => $path) {
31
+ $loader->set($namespace, $path);
32
+ }
33
+
34
+ $classMap = require __DIR__ . '/autoload_classmap.php';
35
+ if ($classMap) {
36
+ $loader->addClassMap($classMap);
37
+ }
38
+
39
+ $loader->register(true);
40
+
41
+ return $loader;
42
+ }
43
+ }
includes/php-opencloud/composer/installed.json ADDED
@@ -0,0 +1,321 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ {
3
+ "name": "symfony/event-dispatcher",
4
+ "version": "v2.3.7",
5
+ "version_normalized": "2.3.7.0",
6
+ "target-dir": "Symfony/Component/EventDispatcher",
7
+ "source": {
8
+ "type": "git",
9
+ "url": "https://github.com/symfony/EventDispatcher.git",
10
+ "reference": "2d8ece3c610726a73d0c95c885134efea182610e"
11
+ },
12
+ "dist": {
13
+ "type": "zip",
14
+ "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/2d8ece3c610726a73d0c95c885134efea182610e",
15
+ "reference": "2d8ece3c610726a73d0c95c885134efea182610e",
16
+ "shasum": ""
17
+ },
18
+ "require": {
19
+ "php": ">=5.3.3"
20
+ },
21
+ "require-dev": {
22
+ "symfony/dependency-injection": "~2.0"
23
+ },
24
+ "suggest": {
25
+ "symfony/dependency-injection": "",
26
+ "symfony/http-kernel": ""
27
+ },
28
+ "time": "2013-10-13 06:32:10",
29
+ "type": "library",
30
+ "extra": {
31
+ "branch-alias": {
32
+ "dev-master": "2.3-dev"
33
+ }
34
+ },
35
+ "installation-source": "dist",
36
+ "autoload": {
37
+ "psr-0": {
38
+ "Symfony\\Component\\EventDispatcher\\": ""
39
+ }
40
+ },
41
+ "notification-url": "https://packagist.org/downloads/",
42
+ "license": [
43
+ "MIT"
44
+ ],
45
+ "authors": [
46
+ {
47
+ "name": "Fabien Potencier",
48
+ "email": "fabien@symfony.com"
49
+ },
50
+ {
51
+ "name": "Symfony Community",
52
+ "homepage": "http://symfony.com/contributors"
53
+ }
54
+ ],
55
+ "description": "Symfony EventDispatcher Component",
56
+ "homepage": "http://symfony.com"
57
+ },
58
+ {
59
+ "name": "guzzle/common",
60
+ "version": "v3.7.4",
61
+ "version_normalized": "3.7.4.0",
62
+ "target-dir": "Guzzle/Common",
63
+ "source": {
64
+ "type": "git",
65
+ "url": "https://github.com/guzzle/common.git",
66
+ "reference": "5126e268446c7e7df961b89128d71878e0652432"
67
+ },
68
+ "dist": {
69
+ "type": "zip",
70
+ "url": "https://api.github.com/repos/guzzle/common/zipball/5126e268446c7e7df961b89128d71878e0652432",
71
+ "reference": "5126e268446c7e7df961b89128d71878e0652432",
72
+ "shasum": ""
73
+ },
74
+ "require": {
75
+ "php": ">=5.3.2",
76
+ "symfony/event-dispatcher": ">=2.1"
77
+ },
78
+ "time": "2013-10-02 20:47:00",
79
+ "type": "library",
80
+ "extra": {
81
+ "branch-alias": {
82
+ "dev-master": "3.7-dev"
83
+ }
84
+ },
85
+ "installation-source": "dist",
86
+ "autoload": {
87
+ "psr-0": {
88
+ "Guzzle\\Common": ""
89
+ }
90
+ },
91
+ "notification-url": "https://packagist.org/downloads/",
92
+ "license": [
93
+ "MIT"
94
+ ],
95
+ "description": "Common libraries used by Guzzle",
96
+ "homepage": "http://guzzlephp.org/",
97
+ "keywords": [
98
+ "collection",
99
+ "common",
100
+ "event",
101
+ "exception"
102
+ ]
103
+ },
104
+ {
105
+ "name": "guzzle/stream",
106
+ "version": "v3.7.4",
107
+ "version_normalized": "3.7.4.0",
108
+ "target-dir": "Guzzle/Stream",
109
+ "source": {
110
+ "type": "git",
111
+ "url": "https://github.com/guzzle/stream.git",
112
+ "reference": "a86111d9ac7db31d65a053c825869409fe8fc83f"
113
+ },
114
+ "dist": {
115
+ "type": "zip",
116
+ "url": "https://api.github.com/repos/guzzle/stream/zipball/a86111d9ac7db31d65a053c825869409fe8fc83f",
117
+ "reference": "a86111d9ac7db31d65a053c825869409fe8fc83f",
118
+ "shasum": ""
119
+ },
120
+ "require": {
121
+ "guzzle/common": "self.version",
122
+ "php": ">=5.3.2"
123
+ },
124
+ "suggest": {
125
+ "guzzle/http": "To convert Guzzle request objects to PHP streams"
126
+ },
127
+ "time": "2013-07-30 22:07:23",
128
+ "type": "library",
129
+ "extra": {
130
+ "branch-alias": {
131
+ "dev-master": "3.7-dev"
132
+ }
133
+ },
134
+ "installation-source": "dist",
135
+ "autoload": {
136
+ "psr-0": {
137
+ "Guzzle\\Stream": ""
138
+ }
139
+ },
140
+ "notification-url": "https://packagist.org/downloads/",
141
+ "license": [
142
+ "MIT"
143
+ ],
144
+ "authors": [
145
+ {
146
+ "name": "Michael Dowling",
147
+ "email": "mtdowling@gmail.com",
148
+ "homepage": "https://github.com/mtdowling"
149
+ }
150
+ ],
151
+ "description": "Guzzle stream wrapper component",
152
+ "homepage": "http://guzzlephp.org/",
153
+ "keywords": [
154
+ "Guzzle",
155
+ "component",
156
+ "stream"
157
+ ]
158
+ },
159
+ {
160
+ "name": "guzzle/parser",
161
+ "version": "v3.7.4",
162
+ "version_normalized": "3.7.4.0",
163
+ "target-dir": "Guzzle/Parser",
164
+ "source": {
165
+ "type": "git",
166
+ "url": "https://github.com/guzzle/parser.git",
167
+ "reference": "a25c2ddda1c52fb69a4ee56eb530b13ddd9573c2"
168
+ },
169
+ "dist": {
170
+ "type": "zip",
171
+ "url": "https://api.github.com/repos/guzzle/parser/zipball/a25c2ddda1c52fb69a4ee56eb530b13ddd9573c2",
172
+ "reference": "a25c2ddda1c52fb69a4ee56eb530b13ddd9573c2",
173
+ "shasum": ""
174
+ },
175
+ "require": {
176
+ "php": ">=5.3.2"
177
+ },
178
+ "time": "2013-07-11 22:46:03",
179
+ "type": "library",
180
+ "extra": {
181
+ "branch-alias": {
182
+ "dev-master": "3.7-dev"
183
+ }
184
+ },
185
+ "installation-source": "dist",
186
+ "autoload": {
187
+ "psr-0": {
188
+ "Guzzle\\Parser": ""
189
+ }
190
+ },
191
+ "notification-url": "https://packagist.org/downloads/",
192
+ "license": [
193
+ "MIT"
194
+ ],
195
+ "description": "Interchangeable parsers used by Guzzle",
196
+ "homepage": "http://guzzlephp.org/",
197
+ "keywords": [
198
+ "URI Template",
199
+ "cookie",
200
+ "http",
201
+ "message",
202
+ "url"
203
+ ]
204
+ },
205
+ {
206
+ "name": "guzzle/http",
207
+ "version": "v3.7.4",
208
+ "version_normalized": "3.7.4.0",
209
+ "target-dir": "Guzzle/Http",
210
+ "source": {
211
+ "type": "git",
212
+ "url": "https://github.com/guzzle/http.git",
213
+ "reference": "3420035adcf312d62a2e64f3e6b3e3e590121786"
214
+ },
215
+ "dist": {
216
+ "type": "zip",
217
+ "url": "https://api.github.com/repos/guzzle/http/zipball/3420035adcf312d62a2e64f3e6b3e3e590121786",
218
+ "reference": "3420035adcf312d62a2e64f3e6b3e3e590121786",
219
+ "shasum": ""
220
+ },
221
+ "require": {
222
+ "guzzle/common": "self.version",
223
+ "guzzle/parser": "self.version",
224
+ "guzzle/stream": "self.version",
225
+ "php": ">=5.3.2"
226
+ },
227
+ "suggest": {
228
+ "ext-curl": "*"
229
+ },
230
+ "time": "2013-09-20 22:05:53",
231
+ "type": "library",
232
+ "extra": {
233
+ "branch-alias": {
234
+ "dev-master": "3.7-dev"
235
+ }
236
+ },
237
+ "installation-source": "dist",
238
+ "autoload": {
239
+ "psr-0": {
240
+ "Guzzle\\Http": ""
241
+ }
242
+ },
243
+ "notification-url": "https://packagist.org/downloads/",
244
+ "license": [
245
+ "MIT"
246
+ ],
247
+ "authors": [
248
+ {
249
+ "name": "Michael Dowling",
250
+ "email": "mtdowling@gmail.com",
251
+ "homepage": "https://github.com/mtdowling"
252
+ }
253
+ ],
254
+ "description": "HTTP libraries used by Guzzle",
255
+ "homepage": "http://guzzlephp.org/",
256
+ "keywords": [
257
+ "Guzzle",
258
+ "client",
259
+ "curl",
260
+ "http",
261
+ "http client"
262
+ ]
263
+ },
264
+ {
265
+ "name": "rackspace/php-opencloud",
266
+ "version": "dev-master",
267
+ "version_normalized": "9999999-dev",
268
+ "source": {
269
+ "type": "git",
270
+ "url": "https://github.com/rackspace/php-opencloud.git",
271
+ "reference": "bc80ef6bf81e2a5d02851a5b1e2cae2da8ec904e"
272
+ },
273
+ "dist": {
274
+ "type": "zip",
275
+ "url": "https://api.github.com/repos/rackspace/php-opencloud/zipball/bc80ef6bf81e2a5d02851a5b1e2cae2da8ec904e",
276
+ "reference": "bc80ef6bf81e2a5d02851a5b1e2cae2da8ec904e",
277
+ "shasum": ""
278
+ },
279
+ "require": {
280
+ "guzzle/http": "3.7.*@dev",
281
+ "php": ">=5.3.3"
282
+ },
283
+ "require-dev": {
284
+ "guzzle/plugin-mock": "3.7.*@dev"
285
+ },
286
+ "time": "2013-11-29 19:57:37",
287
+ "type": "library",
288
+ "installation-source": "source",
289
+ "autoload": {
290
+ "psr-0": {
291
+ "OpenCloud": [
292
+ "lib/",
293
+ "tests/"
294
+ ]
295
+ }
296
+ },
297
+ "notification-url": "https://packagist.org/downloads/",
298
+ "license": [
299
+ "MIT"
300
+ ],
301
+ "authors": [
302
+ {
303
+ "name": "Glen Campbell",
304
+ "email": "glen.campbell@rackspace.com"
305
+ },
306
+ {
307
+ "name": "Jamie Hannaford",
308
+ "email": "jamie.hannaford@rackspace.com",
309
+ "homepage": "https://github.com/jamiehannaford"
310
+ }
311
+ ],
312
+ "description": "PHP SDK for Rackspace/OpenStack APIs",
313
+ "keywords": [
314
+ "Openstack",
315
+ "nova",
316
+ "opencloud",
317
+ "rackspace",
318
+ "swift"
319
+ ]
320
+ }
321
+ ]
includes/php-opencloud/guzzle/common/Guzzle/Common/AbstractHasDispatcher.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Guzzle\Common;
4
+
5
+ use Symfony\Component\EventDispatcher\EventDispatcher;
6
+ use Symfony\Component\EventDispatcher\EventDispatcherInterface;
7
+ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
8
+
9
+ /**
10
+ * Class that holds an event dispatcher
11
+ */
12
+ class AbstractHasDispatcher implements HasDispatcherInterface
13
+ {
14
+ /** @var EventDispatcherInterface */
15
+ protected $eventDispatcher;
16
+
17
+ public static function getAllEvents()
18
+ {
19
+ return array();
20
+ }
21
+
22
+ public function setEventDispatcher(EventDispatcherInterface $eventDispatcher)
23
+ {
24
+ $this->eventDispatcher = $eventDispatcher;
25
+
26
+ return $this;
27
+ }
28
+
29
+ public function getEventDispatcher()
30
+ {
31
+ if (!$this->eventDispatcher) {
32
+ $this->eventDispatcher = new EventDispatcher();
33
+ }
34
+
35
+ return $this->eventDispatcher;
36
+ }
37
+
38
+ public function dispatch($eventName, array $context = array())
39
+ {
40
+ return $this->getEventDispatcher()->dispatch($eventName, new Event($context));
41
+ }
42
+
43
+ public function addSubscriber(EventSubscriberInterface $subscriber)
44
+ {
45
+ $this->getEventDispatcher()->addSubscriber($subscriber);
46
+
47
+ return $this;
48
+ }
49
+ }
includes/php-opencloud/guzzle/common/Guzzle/Common/Collection.php ADDED
@@ -0,0 +1,403 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Guzzle\Common;
4
+
5
+ use Guzzle\Common\Exception\InvalidArgumentException;
6
+ use Guzzle\Common\Exception\RuntimeException;
7
+
8
+ /**
9
+ * Key value pair collection object
10
+ */
11
+ class Collection implements \ArrayAccess, \IteratorAggregate, \Countable, ToArrayInterface
12
+ {
13
+ /** @var array Data associated with the object. */
14
+ protected $data;
15
+
16
+ /**
17
+ * @param array $data Associative array of data to set
18
+ */
19
+ public function __construct(array $data = array())
20
+ {
21
+ $this->data = $data;
22
+ }
23
+
24
+ /**
25
+ * Create a new collection from an array, validate the keys, and add default values where missing
26
+ *
27
+ * @param array $config Configuration values to apply.
28
+ * @param array $defaults Default parameters
29
+ * @param array $required Required parameter names
30
+ *
31
+ * @return self
32
+ * @throws InvalidArgumentException if a parameter is missing
33
+ */
34
+ public static function fromConfig(array $config = array(), array $defaults = array(), array $required = array())
35
+ {
36
+ $data = $config + $defaults;
37
+
38
+ if ($missing = array_diff($required, array_keys($data))) {
39
+ throw new InvalidArgumentException('Config is missing the following keys: ' . implode(', ', $missing));
40
+ }
41
+
42
+ return new self($data);
43
+ }
44
+
45
+ public function count()
46
+ {
47
+ return count($this->data);
48
+ }
49
+
50
+ public function getIterator()
51
+ {
52
+ return new \ArrayIterator($this->data);
53
+ }
54
+
55
+ public function toArray()
56
+ {
57
+ return $this->data;
58
+ }
59
+
60
+ /**
61
+ * Removes all key value pairs
62
+ *
63
+ * @return Collection
64
+ */
65
+ public function clear()
66
+ {
67
+ $this->data = array();
68
+
69
+ return $this;
70
+ }
71
+
72
+ /**
73
+ * Get all or a subset of matching key value pairs
74
+ *
75
+ * @param array $keys Pass an array of keys to retrieve only a subset of key value pairs
76
+ *
77
+ * @return array Returns an array of all matching key value pairs
78
+ */
79
+ public function getAll(array $keys = null)
80
+ {
81
+ return $keys ? array_intersect_key($this->data, array_flip($keys)) : $this->data;
82
+ }
83
+
84
+ /**
85
+ * Get a specific key value.
86
+ *
87
+ * @param string $key Key to retrieve.
88
+ *
89
+ * @return mixed|null Value of the key or NULL
90
+ */
91
+ public function get($key)
92
+ {
93
+ return isset($this->data[$key]) ? $this->data[$key] : null;
94
+ }
95
+
96
+ /**
97
+ * Set a key value pair
98
+ *
99
+ * @param string $key Key to set
100
+ * @param mixed $value Value to set
101
+ *
102
+ * @return Collection Returns a reference to the object
103
+ */
104
+ public function set($key, $value)
105
+ {
106
+ $this->data[$key] = $value;
107
+
108
+ return $this;
109
+ }
110
+
111
+ /**
112
+ * Add a value to a key. If a key of the same name has already been added, the key value will be converted into an
113
+ * array and the new value will be pushed to the end of the array.
114
+ *
115
+ * @param string $key Key to add
116
+ * @param mixed $value Value to add to the key
117
+ *
118
+ * @return Collection Returns a reference to the object.
119
+ */
120
+ public function add($key, $value)
121
+ {
122
+ if (!array_key_exists($key, $this->data)) {
123
+ $this->data[$key] = $value;
124
+ } elseif (is_array($this->data[$key])) {
125
+ $this->data[$key][] = $value;
126
+ } else {
127
+ $this->data[$key] = array($this->data[$key], $value);
128
+ }
129
+
130
+ return $this;
131
+ }
132
+
133
+ /**
134
+ * Remove a specific key value pair
135
+ *
136
+ * @param string $key A key to remove
137
+ *
138
+ * @return Collection
139
+ */
140
+ public function remove($key)
141
+ {
142
+ unset($this->data[$key]);
143
+
144
+ return $this;
145
+ }
146
+
147
+ /**
148
+ * Get all keys in the collection
149
+ *
150
+ * @return array
151
+ */
152
+ public function getKeys()
153
+ {
154
+ return array_keys($this->data);
155
+ }
156
+
157
+ /**
158
+ * Returns whether or not the specified key is present.
159
+ *
160
+ * @param string $key The key for which to check the existence.
161
+ *
162
+ * @return bool
163
+ */
164
+ public function hasKey($key)
165
+ {
166
+ return array_key_exists($key, $this->data);
167
+ }
168
+
169
+ /**
170
+ * Case insensitive search the keys in the collection
171
+ *
172
+ * @param string $key Key to search for
173
+ *
174
+ * @return bool|string Returns false if not found, otherwise returns the key
175
+ */
176
+ public function keySearch($key)
177
+ {
178
+ foreach (array_keys($this->data) as $k) {
179
+ if (!strcasecmp($k, $key)) {
180
+ return $k;
181
+ }
182
+ }
183
+
184
+ return false;
185
+ }
186
+
187
+ /**
188
+ * Checks if any keys contains a certain value
189
+ *
190
+ * @param string $value Value to search for
191
+ *
192
+ * @return mixed Returns the key if the value was found FALSE if the value was not found.
193
+ */
194
+ public function hasValue($value)
195
+ {
196
+ return array_search($value, $this->data);
197
+ }
198
+
199
+ /**
200
+ * Replace the data of the object with the value of an array
201
+ *
202
+ * @param array $data Associative array of data
203
+ *
204
+ * @return Collection Returns a reference to the object
205
+ */
206
+ public function replace(array $data)
207
+ {
208
+ $this->data = $data;
209
+
210
+ return $this;
211
+ }
212
+
213
+ /**
214
+ * Add and merge in a Collection or array of key value pair data.
215
+ *
216
+ * @param Collection|array $data Associative array of key value pair data
217
+ *
218
+ * @return Collection Returns a reference to the object.
219
+ */
220
+ public function merge($data)
221
+ {
222
+ foreach ($data as $key => $value) {
223
+ $this->add($key, $value);
224
+ }
225
+
226
+ return $this;
227
+ }
228
+
229
+ /**
230
+ * Over write key value pairs in this collection with all of the data from an array or collection.
231
+ *
232
+ * @param array|\Traversable $data Values to override over this config
233
+ *
234
+ * @return self
235
+ */
236
+ public function overwriteWith($data)
237
+ {
238
+ if (is_array($data)) {
239
+ $this->data = $data + $this->data;
240
+ } elseif ($data instanceof Collection) {
241
+ $this->data = $data->toArray() + $this->data;
242
+ } else {
243
+ foreach ($data as $key => $value) {
244
+ $this->data[$key] = $value;
245
+ }
246
+ }
247
+
248
+ return $this;
249
+ }
250
+
251
+ /**
252
+ * Returns a Collection containing all the elements of the collection after applying the callback function to each
253
+ * one. The Closure should accept three parameters: (string) $key, (string) $value, (array) $context and return a
254
+ * modified value
255
+ *
256
+ * @param \Closure $closure Closure to apply
257
+ * @param array $context Context to pass to the closure
258
+ * @param bool $static Set to TRUE to use the same class as the return rather than returning a Collection
259
+ *
260
+ * @return Collection
261
+ */
262
+ public function map(\Closure $closure, array $context = array(), $static = true)
263
+ {
264
+ $collection = $static ? new static() : new self();
265
+ foreach ($this as $key => $value) {
266
+ $collection->add($key, $closure($key, $value, $context));
267
+ }
268
+
269
+ return $collection;
270
+ }
271
+
272
+ /**
273
+ * Iterates over each key value pair in the collection passing them to the Closure. If the Closure function returns
274
+ * true, the current value from input is returned into the result Collection. The Closure must accept three
275
+ * parameters: (string) $key, (string) $value and return Boolean TRUE or FALSE for each value.
276
+ *
277
+ * @param \Closure $closure Closure evaluation function
278
+ * @param bool $static Set to TRUE to use the same class as the return rather than returning a Collection
279
+ *
280
+ * @return Collection
281
+ */
282
+ public function filter(\Closure $closure, $static = true)
283
+ {
284
+ $collection = ($static) ? new static() : new self();
285
+ foreach ($this->data as $key => $value) {
286
+ if ($closure($key, $value)) {
287
+ $collection->add($key, $value);
288
+ }
289
+ }
290
+
291
+ return $collection;
292
+ }
293
+
294
+ public function offsetExists($offset)
295
+ {
296
+ return isset($this->data[$offset]);
297
+ }
298
+
299
+ public function offsetGet($offset)
300
+ {
301
+ return isset($this->data[$offset]) ? $this->data[$offset] : null;
302
+ }
303
+
304
+ public function offsetSet($offset, $value)
305
+ {
306
+ $this->data[$offset] = $value;
307
+ }
308
+
309
+ public function offsetUnset($offset)
310
+ {
311
+ unset($this->data[$offset]);
312
+ }
313
+
314
+ /**
315
+ * Set a value into a nested array key. Keys will be created as needed to set the value.
316
+ *
317
+ * @param string $path Path to set
318
+ * @param mixed $value Value to set at the key
319
+ *
320
+ * @return self
321
+ * @throws RuntimeException when trying to setPath using a nested path that travels through a scalar value
322
+ */
323
+ public function setPath($path, $value)
324
+ {
325
+ $current =& $this->data;
326
+ $queue = explode('/', $path);
327
+ while (null !== ($key = array_shift($queue))) {
328
+ if (!is_array($current)) {
329
+ throw new RuntimeException("Trying to setPath {$path}, but {$key} is set and is not an array");
330
+ } elseif (!$queue) {
331
+ $current[$key] = $value;
332
+ } elseif (isset($current[$key])) {
333
+ $current =& $current[$key];
334
+ } else {
335
+ $current[$key] = array();
336
+ $current =& $current[$key];
337
+ }
338
+ }
339
+
340
+ return $this;
341
+ }
342
+
343
+ /**
344
+ * Gets a value from the collection using an array path (e.g. foo/baz/bar would retrieve bar from two nested arrays)
345
+ * Allows for wildcard searches which recursively combine matches up to the level at which the wildcard occurs. This
346
+ * can be useful for accepting any key of a sub-array and combining matching keys from each diverging path.
347
+ *
348
+ * @param string $path Path to traverse and retrieve a value from
349
+ * @param string $separator Character used to add depth to the search
350
+ * @param mixed $data Optional data to descend into (used when wildcards are encountered)
351
+ *
352
+ * @return mixed|null
353
+ */
354
+ public function getPath($path, $separator = '/', $data = null)
355
+ {
356
+ if ($data === null) {
357
+ $data =& $this->data;
358
+ }
359
+
360
+ $path = is_array($path) ? $path : explode($separator, $path);
361
+ while (null !== ($part = array_shift($path))) {
362
+ if (!is_array($data)) {
363
+ return null;
364
+ } elseif (isset($data[$part])) {
365
+ $data =& $data[$part];
366
+ } elseif ($part != '*') {
367
+ return null;
368
+ } else {
369
+ // Perform a wildcard search by diverging and merging paths
370
+ $result = array();
371
+ foreach ($data as $value) {
372
+ if (!$path) {
373
+ $result = array_merge_recursive($result, (array) $value);
374
+ } elseif (null !== ($test = $this->getPath($path, $separator, $value))) {
375
+ $result = array_merge_recursive($result, (array) $test);
376
+ }
377
+ }
378
+ return $result;
379
+ }
380
+ }
381
+
382
+ return $data;
383
+ }
384
+
385
+ /**
386
+ * Inject configuration settings into an input string
387
+ *
388
+ * @param string $input Input to inject
389
+ *
390
+ * @return string
391
+ * @deprecated
392
+ */
393
+ public function inject($input)
394
+ {
395
+ Version::warn(__METHOD__ . ' is deprecated');
396
+ $replace = array();
397
+ foreach ($this->data as $key => $val) {
398
+ $replace['{' . $key . '}'] = $val;
399
+ }
400
+
401
+ return strtr($input, $replace);
402
+ }
403
+ }
includes/php-opencloud/guzzle/common/Guzzle/Common/Event.php ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Guzzle\Common;
4
+
5
+ use Symfony\Component\EventDispatcher\Event as SymfonyEvent;
6
+
7
+ /**
8
+ * Default event for Guzzle notifications
9
+ */
10
+ class Event extends SymfonyEvent implements ToArrayInterface, \ArrayAccess, \IteratorAggregate
11
+ {
12
+ /** @var array */
13
+ private $context;
14
+
15
+ /**
16
+ * @param array $context Contextual information
17
+ */
18
+ public function __construct(array $context = array())
19
+ {
20
+ $this->context = $context;
21
+ }
22
+
23
+ public function getIterator()
24
+ {
25
+ return new \ArrayIterator($this->context);
26
+ }
27
+
28
+ public function offsetGet($offset)
29
+ {
30
+ return isset($this->context[$offset]) ? $this->context[$offset] : null;
31
+ }
32
+
33
+ public function offsetSet($offset, $value)
34
+ {
35
+ $this->context[$offset] = $value;
36
+ }
37
+
38
+ public function offsetExists($offset)
39
+ {
40
+ return isset($this->context[$offset]);
41
+ }
42
+
43
+ public function offsetUnset($offset)
44
+ {
45
+ unset($this->context[$offset]);
46
+ }
47
+
48
+ public function toArray()
49
+ {
50
+ return $this->context;
51
+ }
52
+ }
includes/php-opencloud/guzzle/common/Guzzle/Common/Exception/BadMethodCallException.php ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Guzzle\Common\Exception;
4
+
5
+ class BadMethodCallException extends \BadMethodCallException implements GuzzleException {}
includes/php-opencloud/guzzle/common/Guzzle/Common/Exception/ExceptionCollection.php ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Guzzle\Common\Exception;
4
+
5
+ /**
6
+ * Collection of exceptions
7
+ */
8
+ class ExceptionCollection extends \Exception implements GuzzleException, \IteratorAggregate, \Countable
9
+ {
10
+ /** @var array Array of Exceptions */
11
+ protected $exceptions = array();
12
+
13
+ /**
14
+ * Set all of the exceptions
15
+ *
16
+ * @param array $exceptions Array of exceptions
17
+ *
18
+ * @return self
19
+ */
20
+ public function setExceptions(array $exceptions)
21
+ {
22
+ $this->exceptions = array();
23
+ foreach ($exceptions as $exception) {
24
+ $this->add($exception);
25
+ }
26
+
27
+ return $this;
28
+ }
29
+
30
+ /**
31
+ * Add exceptions to the collection
32
+ *
33
+ * @param ExceptionCollection|\Exception $e Exception to add
34
+ *
35
+ * @return ExceptionCollection;
36
+ */
37
+ public function add($e)
38
+ {
39
+ if ($this->message) {
40
+ $this->message .= "\n";
41
+ }
42
+
43
+ if ($e instanceof self) {
44
+ $this->message .= '(' . get_class($e) . ")";
45
+ foreach (explode("\n", $e->getMessage()) as $message) {
46
+ $this->message .= "\n {$message}";
47
+ }
48
+ } elseif ($e instanceof \Exception) {
49
+ $this->exceptions[] = $e;
50
+ $this->message .= '(' . get_class($e) . ') ' . $e->getMessage();
51
+ }
52
+
53
+ return $this;
54
+ }
55
+
56
+ /**
57
+ * Get the total number of request exceptions
58
+ *
59
+ * @return int
60
+ */
61
+ public function count()
62
+ {
63
+ return count($this->exceptions);
64
+ }
65
+
66
+ /**
67
+ * Allows array-like iteration over the request exceptions
68
+ *
69
+ * @return \ArrayIterator
70
+ */
71
+ public function getIterator()
72
+ {
73
+ return new \ArrayIterator($this->exceptions);
74
+ }
75
+
76
+ /**
77
+ * Get the first exception in the collection
78
+ *
79
+ * @return \Exception
80
+ */
81
+ public function getFirst()
82
+ {
83
+ return $this->exceptions ? $this->exceptions[0] : null;
84
+ }
85
+ }
includes/php-opencloud/guzzle/common/Guzzle/Common/Exception/GuzzleException.php ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Guzzle\Common\Exception;
4
+
5
+ /**
6
+ * Guzzle exception
7
+ */
8
+ interface GuzzleException {}
includes/php-opencloud/guzzle/common/Guzzle/Common/Exception/InvalidArgumentException.php ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Guzzle\Common\Exception;
4
+
5
+ class InvalidArgumentException extends \InvalidArgumentException implements GuzzleException {}
includes/php-opencloud/guzzle/common/Guzzle/Common/Exception/RuntimeException.php ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Guzzle\Common\Exception;
4
+
5
+ class RuntimeException extends \RuntimeException implements GuzzleException {}
includes/php-opencloud/guzzle/common/Guzzle/Common/Exception/UnexpectedValueException.php ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Guzzle\Common\Exception;
4
+
5
+ class UnexpectedValueException extends \UnexpectedValueException implements GuzzleException {}
includes/php-opencloud/guzzle/common/Guzzle/Common/FromConfigInterface.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Guzzle\Common;
4
+
5
+ /**
6
+ * Interfaces that adds a factory method which is used to instantiate a class from an array of configuration options.
7
+ */
8
+ interface FromConfigInterface
9
+ {
10
+ /**
11
+ * Static factory method used to turn an array or collection of configuration data into an instantiated object.
12
+ *
13
+ * @param array|Collection $config Configuration data
14
+ *
15
+ * @return FromConfigInterface
16
+ */
17
+ public static function factory($config = array());
18
+ }
includes/php-opencloud/guzzle/common/Guzzle/Common/HasDispatcherInterface.php ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Guzzle\Common;
4
+
5
+ use Symfony\Component\EventDispatcher\EventDispatcherInterface;
6
+ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
7
+
8
+ /**
9
+ * Holds an event dispatcher
10
+ */
11
+ interface HasDispatcherInterface
12
+ {
13
+ /**
14
+ * Get a list of all of the events emitted from the class
15
+ *
16
+ * @return array
17
+ */
18
+ public static function getAllEvents();
19
+
20
+ /**
21
+ * Set the EventDispatcher of the request
22
+ *
23
+ * @param EventDispatcherInterface $eventDispatcher
24
+ *
25
+ * @return self
26
+ */
27
+ public function setEventDispatcher(EventDispatcherInterface $eventDispatcher);
28
+
29
+ /**
30
+ * Get the EventDispatcher of the request
31
+ *
32
+ * @return EventDispatcherInterface
33
+ */
34
+ public function getEventDispatcher();
35
+
36
+ /**
37
+ * Helper to dispatch Guzzle events and set the event name on the event
38
+ *
39
+ * @param string $eventName Name of the event to dispatch
40
+ * @param array $context Context of the event
41
+ *
42
+ * @return Event Returns the created event object
43
+ */
44
+ public function dispatch($eventName, array $context = array());
45
+
46
+ /**
47
+ * Add an event subscriber to the dispatcher
48
+ *
49
+ * @param EventSubscriberInterface $subscriber Event subscriber
50
+ *
51
+ * @return self
52
+ */
53
+ public function addSubscriber(EventSubscriberInterface $subscriber);
54
+ }
includes/php-opencloud/guzzle/common/Guzzle/Common/ToArrayInterface.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Guzzle\Common;
4
+
5
+ /**
6
+ * An object that can be represented as an array
7
+ */
8
+ interface ToArrayInterface
9
+ {
10
+ /**
11
+ * Get the array representation of an object
12
+ *
13
+ * @return array
14
+ */
15
+ public function toArray();
16
+ }
includes/php-opencloud/guzzle/common/Guzzle/Common/Version.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Guzzle\Common;
4
+
5
+ /**
6
+ * Guzzle version information
7
+ */
8
+ class Version
9
+ {
10
+ const VERSION = '3.7.4';
11
+
12
+ /**
13
+ * @var bool Set this value to true to enable warnings for deprecated functionality use. This should be on in your
14
+ * unit tests, but probably not in production.
15
+ */
16
+ public static $emitWarnings = false;
17
+
18
+ /**
19
+ * Emit a deprecation warning
20
+ *
21
+ * @param string $message Warning message
22
+ */
23
+ public static function warn($message)
24
+ {
25
+ if (self::$emitWarnings) {
26
+ trigger_error('Deprecation warning: ' . $message, E_USER_DEPRECATED);
27
+ }
28
+ }
29
+ }
includes/php-opencloud/guzzle/common/Guzzle/Common/composer.json ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "guzzle/common",
3
+ "homepage": "http://guzzlephp.org/",
4
+ "description": "Common libraries used by Guzzle",
5
+ "keywords": ["common", "event", "exception", "collection"],
6
+ "license": "MIT",
7
+ "require": {
8
+ "php": ">=5.3.2",
9
+ "symfony/event-dispatcher": ">=2.1"
10
+ },
11
+ "autoload": {
12
+ "psr-0": { "Guzzle\\Common": "" }
13
+ },
14
+ "target-dir": "Guzzle/Common",
15
+ "extra": {
16
+ "branch-alias": {
17
+ "dev-master": "3.7-dev"
18
+ }
19
+ }
20
+ }
includes/php-opencloud/guzzle/http/Guzzle/Http/AbstractEntityBodyDecorator.php ADDED
@@ -0,0 +1,221 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Guzzle\Http;
4
+
5
+ use Guzzle\Stream\Stream;
6
+
7
+ /**
8
+ * Abstract decorator used to wrap entity bodies
9
+ */
10
+ class AbstractEntityBodyDecorator implements EntityBodyInterface
11
+ {
12
+ /** @var EntityBodyInterface Decorated entity body */
13
+ protected $body;
14
+
15
+ /**
16
+ * @param EntityBodyInterface $body Entity body to decorate
17
+ */
18
+ public function __construct(EntityBodyInterface $body)
19
+ {
20
+ $this->body = $body;
21
+ }
22
+
23
+ public function __toString()
24
+ {
25
+ return (string) $this->body;
26
+ }
27
+
28
+ /**
29
+ * Allow decorators to implement custom methods
30
+ *
31
+ * @param string $method Missing method name
32
+ * @param array $args Method arguments
33
+ *
34
+ * @return mixed
35
+ */
36
+ public function __call($method, array $args)
37
+ {
38
+ return call_user_func_array(array($this->body, $method), $args);
39
+ }
40
+
41
+ public function close()
42
+ {
43
+ return $this->body->close();
44
+ }
45
+
46
+ public function setRewindFunction($callable)
47
+ {
48
+ $this->body->setRewindFunction($callable);
49
+
50
+ return $this;
51
+ }
52
+
53
+ public function rewind()
54
+ {
55
+ return $this->body->rewind();
56
+ }
57
+
58
+ public function compress($filter = 'zlib.deflate')
59
+ {
60
+ return $this->body->compress($filter);
61
+ }
62
+
63
+ public function uncompress($filter = 'zlib.inflate')
64
+ {
65
+ return $this->body->uncompress($filter);
66
+ }
67
+
68
+ public function getContentLength()
69
+ {
70
+ return $this->getSize();
71
+ }
72
+
73
+ public function getContentType()
74
+ {
75
+ return $this->body->getContentType();
76
+ }
77
+
78
+ public function getContentMd5($rawOutput = false, $base64Encode = false)
79
+ {
80
+ $hash = Stream::getHash($this, 'md5', $rawOutput);
81
+
82
+ return $hash && $base64Encode ? base64_encode($hash) : $hash;
83
+ }
84
+
85
+ public function getContentEncoding()
86
+ {
87
+ return $this->body->getContentEncoding();
88
+ }
89
+
90
+ public function getMetaData($key = null)
91
+ {
92
+ return $this->body->getMetaData($key);
93
+ }
94
+
95
+ public function getStream()
96
+ {
97
+ return $this->body->getStream();
98
+ }
99
+
100
+ public function setStream($stream, $size = 0)
101
+ {
102
+ $this->body->setStream($stream, $size);
103
+
104
+ return $this;
105
+ }
106
+
107
+ public function detachStream()
108
+ {
109
+ $this->body->detachStream();
110
+
111
+ return $this;
112
+ }
113
+
114
+ public function getWrapper()
115
+ {
116
+ return $this->body->getWrapper();
117
+ }
118
+
119
+ public function getWrapperData()
120
+ {
121
+ return $this->body->getWrapperData();
122
+ }
123
+
124
+ public function getStreamType()
125
+ {
126
+ return $this->body->getStreamType();
127
+ }
128
+
129
+ public function getUri()
130
+ {
131
+ return $this->body->getUri();
132
+ }
133
+
134
+ public function getSize()
135
+ {
136
+ return $this->body->getSize();
137
+ }
138
+
139
+ public function isReadable()
140
+ {
141
+ return $this->body->isReadable();
142
+ }
143
+
144
+ public function isRepeatable()
145
+ {
146
+ return $this->isSeekable() && $this->isReadable();
147
+ }
148
+
149
+ public function isWritable()
150
+ {
151
+ return $this->body->isWritable();
152
+ }
153
+
154
+ public function isConsumed()
155
+ {
156
+ return $this->body->isConsumed();
157
+ }
158
+
159
+ /**
160
+ * Alias of isConsumed()
161
+ * {@inheritdoc}
162
+ */
163
+ public function feof()
164
+ {
165
+ return $this->isConsumed();
166
+ }
167
+
168
+ public function isLocal()
169
+ {
170
+ return $this->body->isLocal();
171
+ }
172
+
173
+ public function isSeekable()
174
+ {
175
+ return $this->body->isSeekable();
176
+ }
177
+
178
+ public function setSize($size)
179
+ {
180
+ $this->body->setSize($size);
181
+
182
+ return $this;
183
+ }
184
+
185
+ public function seek($offset, $whence = SEEK_SET)
186
+ {
187
+ return $this->body->seek($offset, $whence);
188
+ }
189
+
190
+ public function read($length)
191
+ {
192
+ return $this->body->read($length);
193
+ }
194
+
195
+ public function write($string)
196
+ {
197
+ return $this->body->write($string);
198
+ }
199
+
200
+ public function readLine($maxLength = null)
201
+ {
202
+ return $this->body->readLine($maxLength);
203
+ }
204
+
205
+ public function ftell()
206
+ {
207
+ return $this->body->ftell();
208
+ }
209
+
210
+ public function getCustomData($key)
211
+ {
212
+ return $this->body->getCustomData($key);
213
+ }
214
+
215
+ public function setCustomData($key, $value)
216
+ {
217
+ $this->body->setCustomData($key, $value);
218
+
219
+ return $this;
220
+ }
221
+ }
includes/php-opencloud/guzzle/http/Guzzle/Http/CachingEntityBody.php ADDED
@@ -0,0 +1,229 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Guzzle\Http;
4
+
5
+ use Guzzle\Common\Exception\RuntimeException;
6
+
7
+ /**
8
+ * EntityBody decorator that can cache previously read bytes from a sequentially read tstream
9
+ */
10
+ class CachingEntityBody extends AbstractEntityBodyDecorator
11
+ {
12
+ /** @var EntityBody Remote stream used to actually pull data onto the buffer */
13
+ protected $remoteStream;
14
+
15
+ /** @var int The number of bytes to skip reading due to a write on the temporary buffer */
16
+ protected $skipReadBytes = 0;
17
+
18
+ /**
19
+ * We will treat the buffer object as the body of the entity body
20
+ * {@inheritdoc}
21
+ */
22
+ public function __construct(EntityBodyInterface $body)
23
+ {
24
+ $this->remoteStream = $body;
25
+ $this->body = new EntityBody(fopen('php://temp', 'r+'));
26
+ }
27
+
28
+ /**
29
+ * Will give the contents of the buffer followed by the exhausted remote stream.
30
+ *
31
+ * Warning: Loads the entire stream into memory
32
+ *
33
+ * @return string
34
+ */
35
+ public function __toString()
36
+ {
37
+ $pos = $this->ftell();
38
+ $this->rewind();
39
+
40
+ $str = '';
41
+ while (!$this->isConsumed()) {
42
+ $str .= $this->read(16384);
43
+ }
44
+
45
+ $this->seek($pos);
46
+
47
+ return $str;
48
+ }
49
+
50
+ public function getSize()
51
+ {
52
+ return max($this->body->getSize(), $this->remoteStream->getSize());
53
+ }
54
+
55
+ /**
56
+ * {@inheritdoc}
57
+ * @throws RuntimeException When seeking with SEEK_END or when seeking past the total size of the buffer stream
58
+ */
59
+ public function seek($offset, $whence = SEEK_SET)
60
+ {
61
+ if ($whence == SEEK_SET) {
62
+ $byte = $offset;
63
+ } elseif ($whence == SEEK_CUR) {
64
+ $byte = $offset + $this->ftell();
65
+ } else {
66
+ throw new RuntimeException(__CLASS__ . ' supports only SEEK_SET and SEEK_CUR seek operations');
67
+ }
68
+
69
+ // You cannot skip ahead past where you've read from the remote stream
70
+ if ($byte > $this->body->getSize()) {
71
+ throw new RuntimeException(
72
+ "Cannot seek to byte {$byte} when the buffered stream only contains {$this->body->getSize()} bytes"
73
+ );
74
+ }
75
+
76
+ return $this->body->seek($byte);
77
+ }
78
+
79
+ public function rewind()
80
+ {
81
+ return $this->seek(0);
82
+ }
83
+
84
+ /**
85
+ * Does not support custom rewind functions
86
+ *
87
+ * @throws RuntimeException
88
+ */
89
+ public function setRewindFunction($callable)
90
+ {
91
+ throw new RuntimeException(__CLASS__ . ' does not support custom stream rewind functions');
92
+ }
93
+
94
+ public function read($length)
95
+ {
96
+ // Perform a regular read on any previously read data from the buffer
97
+ $data = $this->body->read($length);
98
+ $remaining = $length - strlen($data);
99
+
100
+ // More data was requested so read from the remote stream
101
+ if ($remaining) {
102
+ // If data was written to the buffer in a position that would have been filled from the remote stream,
103
+ // then we must skip bytes on the remote stream to emulate overwriting bytes from that position. This
104
+ // mimics the behavior of other PHP stream wrappers.
105
+ $remoteData = $this->remoteStream->read($remaining + $this->skipReadBytes);
106
+
107
+ if ($this->skipReadBytes) {
108
+ $len = strlen($remoteData);
109
+ $remoteData = substr($remoteData, $this->skipReadBytes);
110
+ $this->skipReadBytes = max(0, $this->skipReadBytes - $len);
111
+ }
112
+
113
+ $data .= $remoteData;
114
+ $this->body->write($remoteData);
115
+ }
116
+
117
+ return $data;
118
+ }
119
+
120
+ public function write($string)
121
+ {
122
+ // When appending to the end of the currently read stream, you'll want to skip bytes from being read from
123
+ // the remote stream to emulate other stream wrappers. Basically replacing bytes of data of a fixed length.
124
+ $overflow = (strlen($string) + $this->ftell()) - $this->remoteStream->ftell();
125
+ if ($overflow > 0) {
126
+ $this->skipReadBytes += $overflow;
127
+ }
128
+
129
+ return $this->body->write($string);
130
+ }
131
+
132
+ /**
133
+ * {@inheritdoc}
134
+ * @link http://php.net/manual/en/function.fgets.php
135
+ */
136
+ public function readLine($maxLength = null)
137
+ {
138
+ $buffer = '';
139
+ $size = 0;
140
+ while (!$this->isConsumed()) {
141
+ $byte = $this->read(1);
142
+ $buffer .= $byte;
143
+ // Break when a new line is found or the max length - 1 is reached
144
+ if ($byte == PHP_EOL || ++$size == $maxLength - 1) {
145
+ break;
146
+ }
147
+ }
148
+
149
+ return $buffer;
150
+ }
151
+
152
+ public function isConsumed()
153
+ {
154
+ return $this->body->isConsumed() && $this->remoteStream->isConsumed();
155
+ }
156
+
157
+ /**
158
+ * Close both the remote stream and buffer stream
159
+ */
160
+ public function close()
161
+ {
162
+ return $this->remoteStream->close() && $this->body->close();
163
+ }
164
+
165
+ public function setStream($stream, $size = 0)
166
+ {
167
+ $this->remoteStream->setStream($stream, $size);
168
+ }
169
+
170
+ public function getContentType()
171
+ {
172
+ return $this->remoteStream->getContentType();
173
+ }
174
+
175
+ public function getContentEncoding()
176
+ {
177
+ return $this->remoteStream->getContentEncoding();
178
+ }
179
+
180
+ public function getMetaData($key = null)
181
+ {
182
+ return $this->remoteStream->getMetaData($key);
183
+ }
184
+
185
+ public function getStream()
186
+ {
187
+ return $this->remoteStream->getStream();
188
+ }
189
+
190
+ public function getWrapper()
191
+ {
192
+ return $this->remoteStream->getWrapper();
193
+ }
194
+
195
+ public function getWrapperData()
196
+ {
197
+ return $this->remoteStream->getWrapperData();
198
+ }
199
+
200
+ public function getStreamType()
201
+ {
202
+ return $this->remoteStream->getStreamType();
203
+ }
204
+
205
+ public function getUri()
206
+ {
207
+ return $this->remoteStream->getUri();
208
+ }
209
+
210
+ /**
211
+ * Always retrieve custom data from the remote stream
212
+ * {@inheritdoc}
213
+ */
214
+ public function getCustomData($key)
215
+ {
216
+ return $this->remoteStream->getCustomData($key);
217
+ }
218
+
219
+ /**
220
+ * Always set custom data on the remote stream
221
+ * {@inheritdoc}
222
+ */
223
+ public function setCustomData($key, $value)
224
+ {
225
+ $this->remoteStream->setCustomData($key, $value);
226
+
227
+ return $this;
228
+ }
229
+ }
includes/php-opencloud/guzzle/http/Guzzle/Http/Client.php ADDED
@@ -0,0 +1,506 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Guzzle\Http;
4
+
5
+ use Guzzle\Common\Collection;
6
+ use Guzzle\Common\AbstractHasDispatcher;
7
+ use Guzzle\Common\Exception\ExceptionCollection;
8
+ use Guzzle\Common\Exception\InvalidArgumentException;
9
+ use Guzzle\Common\Exception\RuntimeException;
10
+ use Guzzle\Common\Version;
11
+ use Guzzle\Parser\ParserRegistry;
12
+ use Guzzle\Parser\UriTemplate\UriTemplateInterface;
13
+ use Guzzle\Http\Message\RequestInterface;
14
+ use Guzzle\Http\Message\RequestFactory;
15
+ use Guzzle\Http\Message\RequestFactoryInterface;
16
+ use Guzzle\Http\Curl\CurlMultiInterface;
17
+ use Guzzle\Http\Curl\CurlMultiProxy;
18
+ use Guzzle\Http\Curl\CurlHandle;
19
+ use Guzzle\Http\Curl\CurlVersion;
20
+
21
+ /**
22
+ * HTTP client
23
+ */
24
+ class Client extends AbstractHasDispatcher implements ClientInterface
25
+ {
26
+ /** @deprecated Use [request.options][params] */
27
+ const REQUEST_PARAMS = 'request.params';
28
+
29
+ const REQUEST_OPTIONS = 'request.options';
30
+ const CURL_OPTIONS = 'curl.options';
31
+ const SSL_CERT_AUTHORITY = 'ssl.certificate_authority';
32
+ const DISABLE_REDIRECTS = RedirectPlugin::DISABLE;
33
+
34
+ /** @var Collection Default HTTP headers to set on each request */
35
+ protected $defaultHeaders;
36
+
37
+ /** @var string The user agent string to set on each request */
38
+ protected $userAgent;
39
+
40
+ /** @var Collection Parameter object holding configuration data */
41
+ private $config;
42
+
43
+ /** @var Url Base URL of the client */
44
+ private $baseUrl;
45
+
46
+ /** @var CurlMultiInterface CurlMulti object used internally */
47
+ private $curlMulti;
48
+
49
+ /** @var UriTemplateInterface URI template owned by the client */
50
+ private $uriTemplate;
51
+
52
+ /** @var RequestFactoryInterface Request factory used by the client */
53
+ protected $requestFactory;
54
+
55
+ public static function getAllEvents()
56
+ {
57
+ return array(self::CREATE_REQUEST);
58
+ }
59
+
60
+ /**
61
+ * @param string $baseUrl Base URL of the web service
62
+ * @param array|Collection $config Configuration settings
63
+ *
64
+ * @throws RuntimeException if cURL is not installed
65
+ */
66
+ public function __construct($baseUrl = '', $config = null)
67
+ {
68
+ if (!extension_loaded('curl')) {
69
+ // @codeCoverageIgnoreStart
70
+ throw new RuntimeException('The PHP cURL extension must be installed to use Guzzle.');
71
+ // @codeCoverageIgnoreEnd
72
+ }
73
+ $this->setConfig($config ?: new Collection());
74
+ $this->initSsl();
75
+ $this->setBaseUrl($baseUrl);
76
+ $this->defaultHeaders = new Collection();
77
+ $this->setRequestFactory(RequestFactory::getInstance());
78
+ $this->userAgent = $this->getDefaultUserAgent();
79
+ if (!$this->config[self::DISABLE_REDIRECTS]) {
80
+ $this->addSubscriber(new RedirectPlugin());
81
+ }
82
+ }
83
+
84
+ final public function setConfig($config)
85
+ {
86
+ if ($config instanceof Collection) {
87
+ $this->config = $config;
88
+ } elseif (is_array($config)) {
89
+ $this->config = new Collection($config);
90
+ } else {
91
+ throw new InvalidArgumentException('Config must be an array or Collection');
92
+ }
93
+
94
+ return $this;
95
+ }
96
+
97
+ final public function getConfig($key = false)
98
+ {
99
+ return $key ? $this->config[$key] : $this->config;
100
+ }
101
+
102
+ /**
103
+ * Set a default request option on the client that will be used as a default for each request
104
+ *
105
+ * @param string $keyOrPath request.options key (e.g. allow_redirects) or path to a nested key (e.g. headers/foo)
106
+ * @param mixed $value Value to set
107
+ *
108
+ * @return $this
109
+ */
110
+ public function setDefaultOption($keyOrPath, $value)
111
+ {
112
+ $keyOrPath = self::REQUEST_OPTIONS . '/' . $keyOrPath;
113
+ $this->config->setPath($keyOrPath, $value);
114
+
115
+ return $this;
116
+ }
117
+
118
+ /**
119
+ * Retrieve a default request option from the client
120
+ *
121
+ * @param string $keyOrPath request.options key (e.g. allow_redirects) or path to a nested key (e.g. headers/foo)
122
+ *
123
+ * @return mixed|null
124
+ */
125
+ public function getDefaultOption($keyOrPath)
126
+ {
127
+ $keyOrPath = self::REQUEST_OPTIONS . '/' . $keyOrPath;
128
+
129
+ return $this->config->getPath($keyOrPath);
130
+ }
131
+
132
+ final public function setSslVerification($certificateAuthority = true, $verifyPeer = true, $verifyHost = 2)
133
+ {
134
+ $opts = $this->config[self::CURL_OPTIONS] ?: array();
135
+
136
+ if ($certificateAuthority === true) {
137
+ // use bundled CA bundle, set secure defaults
138
+ $opts[CURLOPT_CAINFO] = __DIR__ . '/Resources/cacert.pem';
139
+ $opts[CURLOPT_SSL_VERIFYPEER] = true;
140
+ $opts[CURLOPT_SSL_VERIFYHOST] = 2;
141
+ } elseif ($certificateAuthority === false) {
142
+ unset($opts[CURLOPT_CAINFO]);
143
+ $opts[CURLOPT_SSL_VERIFYPEER] = false;
144
+ $opts[CURLOPT_SSL_VERIFYHOST] = 2;
145
+ } elseif ($verifyPeer !== true && $verifyPeer !== false && $verifyPeer !== 1 && $verifyPeer !== 0) {
146
+ throw new InvalidArgumentException('verifyPeer must be 1, 0 or boolean');
147
+ } elseif ($verifyHost !== 0 && $verifyHost !== 1 && $verifyHost !== 2) {
148
+ throw new InvalidArgumentException('verifyHost must be 0, 1 or 2');
149
+ } else {
150
+ $opts[CURLOPT_SSL_VERIFYPEER] = $verifyPeer;
151
+ $opts[CURLOPT_SSL_VERIFYHOST] = $verifyHost;
152
+ if (is_file($certificateAuthority)) {
153
+ unset($opts[CURLOPT_CAPATH]);
154
+ $opts[CURLOPT_CAINFO] = $certificateAuthority;
155
+ } elseif (is_dir($certificateAuthority)) {
156
+ unset($opts[CURLOPT_CAINFO]);
157
+ $opts[CURLOPT_CAPATH] = $certificateAuthority;
158
+ } else {
159
+ throw new RuntimeException(
160
+ 'Invalid option passed to ' . self::SSL_CERT_AUTHORITY . ': ' . $certificateAuthority
161
+ );
162
+ }
163
+ }
164
+
165
+ $this->config->set(self::CURL_OPTIONS, $opts);
166
+
167
+ return $this;
168
+ }
169
+
170
+ public function createRequest($method = 'GET', $uri = null, $headers = null, $body = null, array $options = array())
171
+ {
172
+ if (!$uri) {
173
+ $url = $this->getBaseUrl();
174
+ } else {
175
+ if (!is_array($uri)) {
176
+ $templateVars = null;
177
+ } else {
178
+ list($uri, $templateVars) = $uri;
179
+ }
180
+ if (substr($uri, 0, 4) === 'http') {
181
+ // Use absolute URLs as-is
182
+ $url = $this->expandTemplate($uri, $templateVars);
183
+ } else {
184
+ $url = Url::factory($this->getBaseUrl())->combine($this->expandTemplate($uri, $templateVars));
185
+ }
186
+ }
187
+
188
+ // If default headers are provided, then merge them under any explicitly provided headers for the request
189
+ if (count($this->defaultHeaders)) {
190
+ if (!$headers) {
191
+ $headers = $this->defaultHeaders->toArray();
192
+ } elseif (is_array($headers)) {
193
+ $headers += $this->defaultHeaders->toArray();
194
+ } elseif ($headers instanceof Collection) {
195
+ $headers = $headers->toArray() + $this->defaultHeaders->toArray();
196
+ }
197
+ }
198
+
199
+ return $this->prepareRequest($this->requestFactory->create($method, (string) $url, $headers, $body), $options);
200
+ }
201
+
202
+ public function getBaseUrl($expand = true)
203
+ {
204
+ return $expand ? $this->expandTemplate($this->baseUrl) : $this->baseUrl;
205
+ }
206
+
207
+ public function setBaseUrl($url)
208
+ {
209
+ $this->baseUrl = $url;
210
+
211
+ return $this;
212
+ }
213
+
214
+ public function setUserAgent($userAgent, $includeDefault = false)
215
+ {
216
+ if ($includeDefault) {
217
+ $userAgent .= ' ' . $this->getDefaultUserAgent();
218
+ }
219
+ $this->userAgent = $userAgent;
220
+
221
+ return $this;
222
+ }
223
+
224
+ /**
225
+ * Get the default User-Agent string to use with Guzzle
226
+ *
227
+ * @return string
228
+ */
229
+ public function getDefaultUserAgent()
230
+ {
231
+ return 'Guzzle/' . Version::VERSION
232
+ . ' curl/' . CurlVersion::getInstance()->get('version')
233
+ . ' PHP/' . PHP_VERSION;
234
+ }
235
+
236
+ public function get($uri = null, $headers = null, $options = array())
237
+ {
238
+ // BC compat: $options can be a string, resource, etc to specify where the response body is downloaded
239
+ return is_array($options)
240
+ ? $this->createRequest('GET', $uri, $headers, null, $options)
241
+ : $this->createRequest('GET', $uri, $headers, $options);
242
+ }
243
+
244
+ public function head($uri = null, $headers = null, array $options = array())
245
+ {
246
+ return $this->createRequest('HEAD', $uri, $headers, null, $options);
247
+ }
248
+
249
+ public function delete($uri = null, $headers = null, $body = null, array $options = array())
250
+ {
251
+ return $this->createRequest('DELETE', $uri, $headers, $body, $options);
252
+ }
253
+
254
+ public function put($uri = null, $headers = null, $body = null, array $options = array())
255
+ {
256
+ return $this->createRequest('PUT', $uri, $headers, $body, $options);
257
+ }
258
+
259
+ public function patch($uri = null, $headers = null, $body = null, array $options = array())
260
+ {
261
+ return $this->createRequest('PATCH', $uri, $headers, $body, $options);
262
+ }
263
+
264
+ public function post($uri = null, $headers = null, $postBody = null, array $options = array())
265
+ {
266
+ return $this->createRequest('POST', $uri, $headers, $postBody, $options);
267
+ }
268
+
269
+ public function options($uri = null, array $options = array())
270
+ {
271
+ return $this->createRequest('OPTIONS', $uri, $options);
272
+ }
273
+
274
+ public function send($requests)
275
+ {
276
+ if (!($requests instanceof RequestInterface)) {
277
+ return $this->sendMultiple($requests);
278
+ }
279
+
280
+ try {
281
+ /** @var $requests RequestInterface */
282
+ $this->getCurlMulti()->add($requests)->send();
283
+ return $requests->getResponse();
284
+ } catch (ExceptionCollection $e) {
285
+ throw $e->getFirst();
286
+ }
287
+ }
288
+
289
+ /**
290
+ * Set a curl multi object to be used internally by the client for transferring requests.
291
+ *
292
+ * @param CurlMultiInterface $curlMulti Multi object
293
+ *
294
+ * @return self
295
+ */
296
+ public function setCurlMulti(CurlMultiInterface $curlMulti)
297
+ {
298
+ $this->curlMulti = $curlMulti;
299
+
300
+ return $this;
301
+ }
302
+
303
+ /**
304
+ * @return CurlMultiInterface|CurlMultiProxy
305
+ */
306
+ public function getCurlMulti()
307
+ {
308
+ if (!$this->curlMulti) {
309
+ $this->curlMulti = new CurlMultiProxy();
310
+ }
311
+
312
+ return $this->curlMulti;
313
+ }
314
+
315
+ public function setRequestFactory(RequestFactoryInterface $factory)
316
+ {
317
+ $this->requestFactory = $factory;
318
+
319
+ return $this;
320
+ }
321
+
322
+ /**
323
+ * Set the URI template expander to use with the client
324
+ *
325
+ * @param UriTemplateInterface $uriTemplate URI template expander
326
+ *
327
+ * @return self
328
+ */
329
+ public function setUriTemplate(UriTemplateInterface $uriTemplate)
330
+ {
331
+ $this->uriTemplate = $uriTemplate;
332
+
333
+ return $this;
334
+ }
335
+
336
+ /**
337
+ * Copy the cacert.pem file from the phar if it is not in the temp folder and validate the MD5 checksum
338
+ *
339
+ * @param bool $md5Check Set to false to not perform the MD5 validation
340
+ *
341
+ * @return string Returns the path to the extracted cacert
342
+ * @throws RuntimeException if the file cannot be copied or there is a MD5 mismatch
343
+ */
344
+ public function preparePharCacert($md5Check = true)
345
+ {
346
+ $from = __DIR__ . '/Resources/cacert.pem';
347
+ $certFile = sys_get_temp_dir() . '/guzzle-cacert.pem';
348
+ if (!file_exists($certFile) && !copy($from, $certFile)) {
349
+ throw new RuntimeException("Could not copy {$from} to {$certFile}: " . var_export(error_get_last(), true));
350
+ } elseif ($md5Check) {
351
+ $actualMd5 = md5_file($certFile);
352
+ $expectedMd5 = trim(file_get_contents("{$from}.md5"));
353
+ if ($actualMd5 != $expectedMd5) {
354
+ throw new RuntimeException("{$certFile} MD5 mismatch: expected {$expectedMd5} but got {$actualMd5}");
355
+ }
356
+ }
357
+
358
+ return $certFile;
359
+ }
360
+
361
+ /**
362
+ * Expand a URI template while merging client config settings into the template variables
363
+ *
364
+ * @param string $template Template to expand
365
+ * @param array $variables Variables to inject
366
+ *
367
+ * @return string
368
+ */
369
+ protected function expandTemplate($template, array $variables = null)
370
+ {
371
+ $expansionVars = $this->getConfig()->toArray();
372
+ if ($variables) {
373
+ $expansionVars = $variables + $expansionVars;
374
+ }
375
+
376
+ return $this->getUriTemplate()->expand($template, $expansionVars);
377
+ }
378
+
379
+ /**
380
+ * Get the URI template expander used by the client
381
+ *
382
+ * @return UriTemplateInterface
383
+ */
384
+ protected function getUriTemplate()
385
+ {
386
+ if (!$this->uriTemplate) {
387
+ $this->uriTemplate = ParserRegistry::getInstance()->getParser('uri_template');
388
+ }
389
+
390
+ return $this->uriTemplate;
391
+ }
392
+
393
+ /**
394
+ * Send multiple requests in parallel
395
+ *
396
+ * @param array $requests Array of RequestInterface objects
397
+ *
398
+ * @return array Returns an array of Response objects
399
+ */
400
+ protected function sendMultiple(array $requests)
401
+ {
402
+ $curlMulti = $this->getCurlMulti();
403
+ foreach ($requests as $request) {
404
+ $curlMulti->add($request);
405
+ }
406
+ $curlMulti->send();
407
+
408
+ /** @var $request RequestInterface */
409
+ $result = array();
410
+ foreach ($requests as $request) {
411
+ $result[] = $request->getResponse();
412
+ }
413
+
414
+ return $result;
415
+ }
416
+
417
+ /**
418
+ * Prepare a request to be sent from the Client by adding client specific behaviors and properties to the request.
419
+ *
420
+ * @param RequestInterface $request Request to prepare for the client
421
+ * @param array $options Options to apply to the request
422
+ *
423
+ * @return RequestInterface
424
+ */
425
+ protected function prepareRequest(RequestInterface $request, array $options = array())
426
+ {
427
+ $request->setClient($this)->setEventDispatcher(clone $this->getEventDispatcher());
428
+
429
+ if ($curl = $this->config[self::CURL_OPTIONS]) {
430
+ $request->getCurlOptions()->overwriteWith(CurlHandle::parseCurlConfig($curl));
431
+ }
432
+
433
+ if ($params = $this->config[self::REQUEST_PARAMS]) {
434
+ Version::warn('request.params is deprecated. Use request.options to add default request options.');
435
+ $request->getParams()->overwriteWith($params);
436
+ }
437
+
438
+ if ($this->userAgent && !$request->hasHeader('User-Agent')) {
439
+ $request->setHeader('User-Agent', $this->userAgent);
440
+ }
441
+
442
+ if ($defaults = $this->config[self::REQUEST_OPTIONS]) {
443
+ $this->requestFactory->applyOptions($request, $defaults, RequestFactoryInterface::OPTIONS_AS_DEFAULTS);
444
+ }
445
+
446
+ if ($options) {
447
+ $this->requestFactory->applyOptions($request, $options);
448
+ }
449
+
450
+ $this->dispatch('client.create_request', array('client' => $this, 'request' => $request));
451
+
452
+ return $request;
453
+ }
454
+
455
+ /**
456
+ * Initializes SSL settings
457
+ */
458
+ protected function initSsl()
459
+ {
460
+ if ('system' == ($authority = $this->config[self::SSL_CERT_AUTHORITY])) {
461
+ return;
462
+ }
463
+
464
+ if ($authority === null) {
465
+ $authority = true;
466
+ }
467
+
468
+ if ($authority === true && substr(__FILE__, 0, 7) == 'phar://') {
469
+ $authority = $this->preparePharCacert();
470
+ $that = $this;
471
+ $this->getEventDispatcher()->addListener('request.before_send', function ($event) use ($authority, $that) {
472
+ if ($authority == $event['request']->getCurlOptions()->get(CURLOPT_CAINFO)) {
473
+ $that->preparePharCacert(false);
474
+ }
475
+ });
476
+ }
477
+
478
+ $this->setSslVerification($authority);
479
+ }
480
+
481
+ /**
482
+ * @deprecated
483
+ */
484
+ public function getDefaultHeaders()
485
+ {
486
+ Version::warn(__METHOD__ . ' is deprecated. Use the request.options array to retrieve default request options');
487
+ return $this->defaultHeaders;
488
+ }
489
+
490
+ /**
491
+ * @deprecated
492
+ */
493
+ public function setDefaultHeaders($headers)
494
+ {
495
+ Version::warn(__METHOD__ . ' is deprecated. Use the request.options array to specify default request options');
496
+ if ($headers instanceof Collection) {
497
+ $this->defaultHeaders = $headers;
498
+ } elseif (is_array($headers)) {
499
+ $this->defaultHeaders = new Collection($headers);
500
+ } else {
501
+ throw new InvalidArgumentException('Headers must be an array or Collection');
502
+ }
503
+
504
+ return $this;
505
+ }
506
+ }
includes/php-opencloud/guzzle/http/Guzzle/Http/ClientInterface.php ADDED
@@ -0,0 +1,223 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Guzzle\Http;
4
+
5
+ use Guzzle\Common\HasDispatcherInterface;
6
+ use Guzzle\Common\Collection;
7
+ use Guzzle\Common\Exception\InvalidArgumentException;
8
+ use Guzzle\Http\Message\EntityEnclosingRequestInterface;
9
+ use Guzzle\Http\Message\RequestInterface;
10
+
11
+ /**
12
+ * Client interface for send HTTP requests
13
+ */
14
+ interface ClientInterface extends HasDispatcherInterface
15
+ {
16
+ const CREATE_REQUEST = 'client.create_request';
17
+
18
+ /** @var string RFC 1123 HTTP-Date */
19
+ const HTTP_DATE = 'D, d M Y H:i:s \G\M\T';
20
+
21
+ /**
22
+ * Set the configuration object to use with the client
23
+ *
24
+ * @param array|Collection $config Parameters that define how the client behaves
25
+ *
26
+ * @return self
27
+ */
28
+ public function setConfig($config);
29
+
30
+ /**
31
+ * Get a configuration setting or all of the configuration settings. The Collection result of this method can be
32
+ * modified to change the configuration settings of a client.
33
+ *
34
+ * A client should honor the following special values:
35
+ *
36
+ * - request.options: Associative array of default RequestFactory options to apply to each request
37
+ * - request.params: Associative array of request parameters (data values) to apply to each request
38
+ * - curl.options: Associative array of cURL configuration settings to apply to each request
39
+ * - ssl.certificate_authority: Path a CAINFO, CAPATH, true to use strict defaults, or false to disable verification
40
+ * - redirect.disable: Set to true to disable redirects
41
+ *
42
+ * @param bool|string $key Configuration value to retrieve. Set to FALSE to retrieve all values of the client.
43
+ * The object return can be modified, and modifications will affect the client's config.
44
+ * @return mixed|Collection
45
+ * @see \Guzzle\Http\Message\RequestFactoryInterface::applyOptions for a full list of request.options options
46
+ */
47
+ public function getConfig($key = false);
48
+
49
+ /**
50
+ * Create and return a new {@see RequestInterface} configured for the client.
51
+ *
52
+ * Use an absolute path to override the base path of the client, or a relative path to append to the base path of
53
+ * the client. The URI can contain the query string as well. Use an array to provide a URI template and additional
54
+ * variables to use in the URI template expansion.
55
+ *
56
+ * @param string $method HTTP method. Defaults to GET
57
+ * @param string|array $uri Resource URI.
58
+ * @param array|Collection $headers HTTP headers
59
+ * @param string|resource|array|EntityBodyInterface $body Entity body of request (POST/PUT) or response (GET)
60
+ * @param array $options Array of options to apply to the request
61
+ *
62
+ * @return RequestInterface
63
+ * @throws InvalidArgumentException if a URI array is passed that does not contain exactly two elements: the URI
64
+ * followed by template variables
65
+ */
66
+ public function createRequest(
67
+ $method = RequestInterface::GET,
68
+ $uri = null,
69
+ $headers = null,
70
+ $body = null,
71
+ array $options = array()
72
+ );
73
+
74
+ /**
75
+ * Create a GET request for the client
76
+ *
77
+ * @param string|array $uri Resource URI
78
+ * @param array|Collection $headers HTTP headers
79
+ * @param array $options Options to apply to the request. For BC compatibility, you can also pass a
80
+ * string to tell Guzzle to download the body of the response to a particular
81
+ * location. Use the 'body' option instead for forward compatibility.
82
+ * @return RequestInterface
83
+ * @see Guzzle\Http\ClientInterface::createRequest()
84
+ */
85
+ public function get($uri = null, $headers = null, $options = array());
86
+
87
+ /**
88
+ * Create a HEAD request for the client
89
+ *
90
+ * @param string|array $uri Resource URI
91
+ * @param array|Collection $headers HTTP headers
92
+ * @param array $options Options to apply to the request
93
+ *
94
+ * @return RequestInterface
95
+ * @see Guzzle\Http\ClientInterface::createRequest()
96
+ */
97
+ public function head($uri = null, $headers = null, array $options = array());
98
+
99
+ /**
100
+ * Create a DELETE request for the client
101
+ *
102
+ * @param string|array $uri Resource URI
103
+ * @param array|Collection $headers HTTP headers
104
+ * @param string|resource|EntityBodyInterface $body Body to send in the request
105
+ * @param array $options Options to apply to the request
106
+ *
107
+ * @return EntityEnclosingRequestInterface
108
+ * @see Guzzle\Http\ClientInterface::createRequest()
109
+ */
110
+ public function delete($uri = null, $headers = null, $body = null, array $options = array());
111
+
112
+ /**
113
+ * Create a PUT request for the client
114
+ *
115
+ * @param string|array $uri Resource URI
116
+ * @param array|Collection $headers HTTP headers
117
+ * @param string|resource|EntityBodyInterface $body Body to send in the request
118
+ * @param array $options Options to apply to the request
119
+ *
120
+ * @return EntityEnclosingRequestInterface
121
+ * @see Guzzle\Http\ClientInterface::createRequest()
122
+ */
123
+ public function put($uri = null, $headers = null, $body = null, array $options = array());
124
+
125
+ /**
126
+ * Create a PATCH request for the client
127
+ *
128
+ * @param string|array $uri Resource URI
129
+ * @param array|Collection $headers HTTP headers
130
+ * @param string|resource|EntityBodyInterface $body Body to send in the request
131
+ * @param array $options Options to apply to the request
132
+ *
133
+ * @return EntityEnclosingRequestInterface
134
+ * @see Guzzle\Http\ClientInterface::createRequest()
135
+ */
136
+ public function patch($uri = null, $headers = null, $body = null, array $options = array());
137
+
138
+ /**
139
+ * Create a POST request for the client
140
+ *
141
+ * @param string|array $uri Resource URI
142
+ * @param array|Collection $headers HTTP headers
143
+ * @param array|Collection|string|EntityBodyInterface $postBody POST body. Can be a string, EntityBody, or
144
+ * associative array of POST fields to send in the body of the
145
+ * request. Prefix a value in the array with the @ symbol to
146
+ * reference a file.
147
+ * @param array $options Options to apply to the request
148
+ *
149
+ * @return EntityEnclosingRequestInterface
150
+ * @see Guzzle\Http\ClientInterface::createRequest()
151
+ */
152
+ public function post($uri = null, $headers = null, $postBody = null, array $options = array());
153
+
154
+ /**
155
+ * Create an OPTIONS request for the client
156
+ *
157
+ * @param string|array $uri Resource URI
158
+ * @param array $options Options to apply to the request
159
+ *
160
+ * @return RequestInterface
161
+ * @see Guzzle\Http\ClientInterface::createRequest()
162
+ */
163
+ public function options($uri = null, array $options = array());
164
+
165
+ /**
166
+ * Sends a single request or an array of requests in parallel
167
+ *
168
+ * @param array|RequestInterface $requests One or more RequestInterface objects to send
169
+ *
170
+ * @return \Guzzle\Http\Message\Response|array Returns a single Response or an array of Response objects
171
+ */
172
+ public function send($requests);
173
+
174
+ /**
175
+ * Get the client's base URL as either an expanded or raw URI template
176
+ *
177
+ * @param bool $expand Set to FALSE to get the raw base URL without URI template expansion
178
+ *
179
+ * @return string|null
180
+ */
181
+ public function getBaseUrl($expand = true);
182
+
183
+ /**
184
+ * Set the base URL of the client
185
+ *
186
+ * @param string $url The base service endpoint URL of the webservice
187
+ *
188
+ * @return self
189
+ */
190
+ public function setBaseUrl($url);
191
+
192
+ /**
193
+ * Set the User-Agent header to be used on all requests from the client
194
+ *
195
+ * @param string $userAgent User agent string
196
+ * @param bool $includeDefault Set to true to prepend the value to Guzzle's default user agent string
197
+ *
198
+ * @return self
199
+ */
200
+ public function setUserAgent($userAgent, $includeDefault = false);
201
+
202
+ /**
203
+ * Set SSL verification options.
204
+ *
205
+ * Setting $certificateAuthority to TRUE will result in the bundled cacert.pem being used to verify against the
206
+ * remote host.
207
+ *
208
+ * Alternate certificates to verify against can be specified with the $certificateAuthority option set to the full
209
+ * path to a certificate file, or the path to a directory containing certificates.
210
+ *
211
+ * Setting $certificateAuthority to FALSE will turn off peer verification, unset the bundled cacert.pem, and
212
+ * disable host verification. Please don't do this unless you really know what you're doing, and why you're doing
213
+ * it.
214
+ *
215
+ * @param string|bool $certificateAuthority bool, file path, or directory path
216
+ * @param bool $verifyPeer FALSE to stop from verifying the peer's certificate.
217
+ * @param int $verifyHost Set to 1 to check the existence of a common name in the SSL peer
218
+ * certificate. 2 to check the existence of a common name and also verify
219
+ * that it matches the hostname provided.
220
+ * @return self
221
+ */
222
+ public function setSslVerification($certificateAuthority = true, $verifyPeer = true, $verifyHost = 2);
223
+ }
includes/php-opencloud/guzzle/http/Guzzle/Http/Curl/CurlHandle.php ADDED
@@ -0,0 +1,451 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Guzzle\Http\Curl;
4
+
5
+ use Guzzle\Common\Exception\InvalidArgumentException;
6
+ use Guzzle\Common\Exception\RuntimeException;
7
+ use Guzzle\Common\Collection;
8
+ use Guzzle\Http\Message\EntityEnclosingRequest;
9
+ use Guzzle\Http\Message\RequestInterface;
10
+ use Guzzle\Parser\ParserRegistry;
11
+ use Guzzle\Http\Url;
12
+
13
+ /**
14
+ * Immutable wrapper for a cURL handle
15
+ */
16
+ class CurlHandle
17
+ {
18
+ const BODY_AS_STRING = 'body_as_string';
19
+ const PROGRESS = 'progress';
20
+ const DEBUG = 'debug';
21
+
22
+ /** @var Collection Curl options */
23
+ protected $options;
24
+
25
+ /** @var resource Curl resource handle */
26
+ protected $handle;
27
+
28
+ /** @var int CURLE_* error */
29
+ protected $errorNo = CURLE_OK;
30
+
31
+ /**
32
+ * Factory method to create a new curl handle based on an HTTP request.
33
+ *
34
+ * There are some helpful options you can set to enable specific behavior:
35
+ * - debug: Set to true to enable cURL debug functionality to track the actual headers sent over the wire.
36
+ * - progress: Set to true to enable progress function callbacks.
37
+ *
38
+ * @param RequestInterface $request Request
39
+ *
40
+ * @return CurlHandle
41
+ * @throws RuntimeException
42
+ */
43
+ public static function factory(RequestInterface $request)
44
+ {
45
+ $requestCurlOptions = $request->getCurlOptions();
46
+ $mediator = new RequestMediator($request, $requestCurlOptions->get('emit_io'));
47
+ $tempContentLength = null;
48
+ $method = $request->getMethod();
49
+ $bodyAsString = $requestCurlOptions->get(self::BODY_AS_STRING);
50
+
51
+ // Array of default cURL options.
52
+ $curlOptions = array(
53
+ CURLOPT_URL => $request->getUrl(),
54
+ CURLOPT_CONNECTTIMEOUT => 150,
55
+ CURLOPT_RETURNTRANSFER => false,
56
+ CURLOPT_HEADER => false,
57
+ CURLOPT_PORT => $request->getPort(),
58
+ CURLOPT_HTTPHEADER => array(),
59
+ CURLOPT_WRITEFUNCTION => array($mediator, 'writeResponseBody'),
60
+ CURLOPT_HEADERFUNCTION => array($mediator, 'receiveResponseHeader'),
61
+ CURLOPT_HTTP_VERSION => $request->getProtocolVersion() === '1.0'
62
+ ? CURL_HTTP_VERSION_1_0 : CURL_HTTP_VERSION_1_1,
63
+ // Verifies the authenticity of the peer's certificate
64
+ CURLOPT_SSL_VERIFYPEER => 1,
65
+ // Certificate must indicate that the server is the server to which you meant to connect
66
+ CURLOPT_SSL_VERIFYHOST => 2
67
+ );
68
+
69
+ if (defined('CURLOPT_PROTOCOLS')) {
70
+ // Allow only HTTP and HTTPS protocols
71
+ $curlOptions[CURLOPT_PROTOCOLS] = CURLPROTO_HTTP | CURLPROTO_HTTPS;
72
+ }
73
+
74
+ // Add CURLOPT_ENCODING if Accept-Encoding header is provided
75
+ if ($acceptEncodingHeader = $request->getHeader('Accept-Encoding')) {
76
+ $curlOptions[CURLOPT_ENCODING] = (string) $acceptEncodingHeader;
77
+ // Let cURL set the Accept-Encoding header, prevents duplicate values
78
+ $request->removeHeader('Accept-Encoding');
79
+ }
80
+
81
+ // Enable curl debug information if the 'debug' param was set
82
+ if ($requestCurlOptions->get('debug')) {
83
+ $curlOptions[CURLOPT_STDERR] = fopen('php://temp', 'r+');
84
+ // @codeCoverageIgnoreStart
85
+ if (false === $curlOptions[CURLOPT_STDERR]) {
86
+ throw new RuntimeException('Unable to create a stream for CURLOPT_STDERR');
87
+ }
88
+ // @codeCoverageIgnoreEnd
89
+ $curlOptions[CURLOPT_VERBOSE] = true;
90
+ }
91
+
92
+ // Specify settings according to the HTTP method
93
+ if ($method == 'GET') {
94
+ $curlOptions[CURLOPT_HTTPGET] = true;
95
+ } elseif ($method == 'HEAD') {
96
+ $curlOptions[CURLOPT_NOBODY] = true;
97
+ // HEAD requests do not use a write function
98
+ unset($curlOptions[CURLOPT_WRITEFUNCTION]);
99
+ } elseif (!($request instanceof EntityEnclosingRequest)) {
100
+ $curlOptions[CURLOPT_CUSTOMREQUEST] = $method;
101
+ } else {
102
+
103
+ $curlOptions[CURLOPT_CUSTOMREQUEST] = $method;
104
+
105
+ // Handle sending raw bodies in a request
106
+ if ($request->getBody()) {
107
+ // You can send the body as a string using curl's CURLOPT_POSTFIELDS
108
+ if ($bodyAsString) {
109
+ $curlOptions[CURLOPT_POSTFIELDS] = (string) $request->getBody();
110
+ // Allow curl to add the Content-Length for us to account for the times when
111
+ // POST redirects are followed by GET requests
112
+ if ($tempContentLength = $request->getHeader('Content-Length')) {
113
+ $tempContentLength = (int) (string) $tempContentLength;
114
+ }
115
+ // Remove the curl generated Content-Type header if none was set manually
116
+ if (!$request->hasHeader('Content-Type')) {
117
+ $curlOptions[CURLOPT_HTTPHEADER][] = 'Content-Type:';
118
+ }
119
+ } else {
120
+ $curlOptions[CURLOPT_UPLOAD] = true;
121
+ // Let cURL handle setting the Content-Length header
122
+ if ($tempContentLength = $request->getHeader('Content-Length')) {
123
+ $tempContentLength = (int) (string) $tempContentLength;
124
+ $curlOptions[CURLOPT_INFILESIZE] = $tempContentLength;
125
+ }
126
+ // Add a callback for curl to read data to send with the request only if a body was specified
127
+ $curlOptions[CURLOPT_READFUNCTION] = array($mediator, 'readRequestBody');
128
+ // Attempt to seek to the start of the stream
129
+ $request->getBody()->seek(0);
130
+ }
131
+
132
+ } else {
133
+
134
+ // Special handling for POST specific fields and files
135
+ $postFields = false;
136
+ if (count($request->getPostFiles())) {
137
+ $postFields = $request->getPostFields()->useUrlEncoding(false)->urlEncode();
138
+ foreach ($request->getPostFiles() as $key => $data) {
139
+ $prefixKeys = count($data) > 1;
140
+ foreach ($data as $index => $file) {
141
+ // Allow multiple files in the same key
142
+ $fieldKey = $prefixKeys ? "{$key}[{$index}]" : $key;
143
+ $postFields[$fieldKey] = $file->getCurlValue();
144
+ }
145
+ }
146
+ } elseif (count($request->getPostFields())) {
147
+ $postFields = (string) $request->getPostFields()->useUrlEncoding(true);
148
+ }
149
+
150
+ if ($postFields !== false) {
151
+ if ($method == 'POST') {
152
+ unset($curlOptions[CURLOPT_CUSTOMREQUEST]);
153
+ $curlOptions[CURLOPT_POST] = true;
154
+ }
155
+ $curlOptions[CURLOPT_POSTFIELDS] = $postFields;
156
+ $request->removeHeader('Content-Length');
157
+ }
158
+ }
159
+
160
+ // If the Expect header is not present, prevent curl from adding it
161
+ if (!$request->hasHeader('Expect')) {
162
+ $curlOptions[CURLOPT_HTTPHEADER][] = 'Expect:';
163
+ }
164
+ }
165
+
166
+ // If a Content-Length header was specified but we want to allow curl to set one for us
167
+ if (null !== $tempContentLength) {
168
+ $request->removeHeader('Content-Length');
169
+ }
170
+
171
+ // Set custom cURL options
172
+ foreach ($requestCurlOptions->toArray() as $key => $value) {
173
+ if (is_numeric($key)) {
174
+ $curlOptions[$key] = $value;
175
+ }
176
+ }
177
+
178
+ // Do not set an Accept header by default
179
+ if (!isset($curlOptions[CURLOPT_ENCODING])) {
180
+ $curlOptions[CURLOPT_HTTPHEADER][] = 'Accept:';
181
+ }
182
+
183
+ // Add any custom headers to the request. Empty headers will cause curl to not send the header at all.
184
+ foreach ($request->getHeaderLines() as $line) {
185
+ $curlOptions[CURLOPT_HTTPHEADER][] = $line;
186
+ }
187
+
188
+ // Add the content-length header back if it was temporarily removed
189
+ if ($tempContentLength) {
190
+ $request->setHeader('Content-Length', $tempContentLength);
191
+ }
192
+
193
+ // Apply the options to a new cURL handle.
194
+ $handle = curl_init();
195
+
196
+ // Enable the progress function if the 'progress' param was set
197
+ if ($requestCurlOptions->get('progress')) {
198
+ // Wrap the function in a function that provides the curl handle to the mediator's progress function
199
+ // Using this rather than injecting the handle into the mediator prevents a circular reference
200
+ $curlOptions[CURLOPT_PROGRESSFUNCTION] = function () use ($mediator, $handle) {
201
+ $args = func_get_args();
202
+ $args[] = $handle;
203
+ call_user_func_array(array($mediator, 'progress'), $args);
204
+ };
205
+ $curlOptions[CURLOPT_NOPROGRESS] = false;
206
+ }
207
+
208
+ curl_setopt_array($handle, $curlOptions);
209
+
210
+ return new static($handle, $curlOptions);
211
+ }
212
+
213
+ /**
214
+ * Construct a new CurlHandle object that wraps a cURL handle
215
+ *
216
+ * @param resource $handle Configured cURL handle resource
217
+ * @param Collection|array $options Curl options to use with the handle
218
+ *
219
+ * @throws InvalidArgumentException
220
+ */
221
+ public function __construct($handle, $options)
222
+ {
223
+ if (!is_resource($handle)) {
224
+ throw new InvalidArgumentException('Invalid handle provided');
225
+ }
226
+ if (is_array($options)) {
227
+ $this->options = new Collection($options);
228
+ } elseif ($options instanceof Collection) {
229
+ $this->options = $options;
230
+ } else {
231
+ throw new InvalidArgumentException('Expected array or Collection');
232
+ }
233
+ $this->handle = $handle;
234
+ }
235
+
236
+ /**
237
+ * Destructor
238
+ */
239
+ public function __destruct()
240
+ {
241
+ $this->close();
242
+ }
243
+
244
+ /**
245
+ * Close the curl handle
246
+ */
247
+ public function close()
248
+ {
249
+ if (is_resource($this->handle)) {
250
+ curl_close($this->handle);
251
+ }
252
+ $this->handle = null;
253
+ }
254
+
255
+ /**
256
+ * Check if the handle is available and still OK
257
+ *
258
+ * @return bool
259
+ */
260
+ public function isAvailable()
261
+ {
262
+ return is_resource($this->handle);
263
+ }
264
+
265
+ /**
266
+ * Get the last error that occurred on the cURL handle
267
+ *
268
+ * @return string
269
+ */
270
+ public function getError()
271
+ {
272
+ return $this->isAvailable() ? curl_error($this->handle) : '';
273
+ }
274
+
275
+ /**
276
+ * Get the last error number that occurred on the cURL handle
277
+ *
278
+ * @return int
279
+ */
280
+ public function getErrorNo()
281
+ {
282
+ if ($this->errorNo) {
283
+ return $this->errorNo;
284
+ }
285
+
286
+ return $this->isAvailable() ? curl_errno($this->handle) : CURLE_OK;
287
+ }
288
+
289
+ /**
290
+ * Set the curl error number
291
+ *
292
+ * @param int $error Error number to set
293
+ *
294
+ * @return CurlHandle
295
+ */
296
+ public function setErrorNo($error)
297
+ {
298
+ $this->errorNo = $error;
299
+
300
+ return $this;
301
+ }
302
+
303
+ /**
304
+ * Get cURL curl_getinfo data
305
+ *
306
+ * @param int $option Option to retrieve. Pass null to retrieve all data as an array.
307
+ *
308
+ * @return array|mixed
309
+ */
310
+ public function getInfo($option = null)
311
+ {
312
+ if (!is_resource($this->handle)) {
313
+ return null;
314
+ }
315
+
316
+ if (null !== $option) {
317
+ return curl_getinfo($this->handle, $option) ?: null;
318
+ }
319
+
320
+ return curl_getinfo($this->handle) ?: array();
321
+ }
322
+
323
+ /**
324
+ * Get the stderr output
325
+ *
326
+ * @param bool $asResource Set to TRUE to get an fopen resource
327
+ *
328
+ * @return string|resource|null
329
+ */
330
+ public function getStderr($asResource = false)
331
+ {
332
+ $stderr = $this->getOptions()->get(CURLOPT_STDERR);
333
+ if (!$stderr) {
334
+ return null;
335
+ }
336
+
337
+ if ($asResource) {
338
+ return $stderr;
339
+ }
340
+
341
+ fseek($stderr, 0);
342
+ $e = stream_get_contents($stderr);
343
+ fseek($stderr, 0, SEEK_END);
344
+
345
+ return $e;
346
+ }
347
+
348
+ /**
349
+ * Get the URL that this handle is connecting to
350
+ *
351
+ * @return Url
352
+ */
353
+ public function getUrl()
354
+ {
355
+ return Url::factory($this->options->get(CURLOPT_URL));
356
+ }
357
+
358
+ /**
359
+ * Get the wrapped curl handle
360
+ *
361
+ * @return resource|null Returns the cURL handle or null if it was closed
362
+ */
363
+ public function getHandle()
364
+ {
365
+ return $this->isAvailable() ? $this->handle : null;
366
+ }
367
+
368
+ /**
369
+ * Get the cURL setopt options of the handle. Changing values in the return object will have no effect on the curl
370
+ * handle after it is created.
371
+ *
372
+ * @return Collection
373
+ */
374
+ public function getOptions()
375
+ {
376
+ return $this->options;
377
+ }
378
+
379
+ /**
380
+ * Update a request based on the log messages of the CurlHandle
381
+ *
382
+ * @param RequestInterface $request Request to update
383
+ */
384
+ public function updateRequestFromTransfer(RequestInterface $request)
385
+ {
386
+ if (!$request->getResponse()) {
387
+ return;
388
+ }
389
+
390
+ // Update the transfer stats of the response
391
+ $request->getResponse()->setInfo($this->getInfo());
392
+
393
+ if (!$log = $this->getStderr(true)) {
394
+ return;
395
+ }
396
+
397
+ // Parse the cURL stderr output for outgoing requests
398
+ $headers = '';
399
+ fseek($log, 0);
400
+ while (($line = fgets($log)) !== false) {
401
+ if ($line && $line[0] == '>') {
402
+ $headers = substr(trim($line), 2) . "\r\n";
403
+ while (($line = fgets($log)) !== false) {
404
+ if ($line[0] == '*' || $line[0] == '<') {
405
+ break;
406
+ } else {
407
+ $headers .= trim($line) . "\r\n";
408
+ }
409
+ }
410
+ }
411
+ }
412
+
413
+ // Add request headers to the request exactly as they were sent
414
+ if ($headers) {
415
+ $parsed = ParserRegistry::getInstance()->getParser('message')->parseRequest($headers);
416
+ if (!empty($parsed['headers'])) {
417
+ $request->setHeaders(array());
418
+ foreach ($parsed['headers'] as $name => $value) {
419
+ $request->setHeader($name, $value);
420
+ }
421
+ }
422
+ if (!empty($parsed['version'])) {
423
+ $request->setProtocolVersion($parsed['version']);
424
+ }
425
+ }
426
+ }
427
+
428
+ /**
429
+ * Parse the config and replace curl.* configurators into the constant based values so it can be used elsewhere
430
+ *
431
+ * @param array|Collection $config The configuration we want to parse
432
+ *
433
+ * @return array
434
+ */
435
+ public static function parseCurlConfig($config)
436
+ {
437
+ $curlOptions = array();
438
+ foreach ($config as $key => $value) {
439
+ if (is_string($key) && defined($key)) {
440
+ // Convert constants represented as string to constant int values
441
+ $key = constant($key);
442
+ }
443
+ if (is_string($value) && defined($value)) {
444
+ $value = constant($value);
445
+ }
446
+ $curlOptions[$key] = $value;
447
+ }
448
+
449
+ return $curlOptions;
450
+ }
451
+ }
includes/php-opencloud/guzzle/http/Guzzle/Http/Curl/CurlMulti.php ADDED
@@ -0,0 +1,363 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Guzzle\Http\Curl;
4
+
5
+ use Guzzle\Common\AbstractHasDispatcher;
6
+ use Guzzle\Common\Event;
7
+ use Guzzle\Http\Exception\MultiTransferException;
8
+ use Guzzle\Http\Exception\CurlException;
9
+ use Guzzle\Http\Message\RequestInterface;
10
+
11
+ /**
12
+ * Send {@see RequestInterface} objects in parallel using curl_multi
13
+ */
14
+ class CurlMulti extends AbstractHasDispatcher implements CurlMultiInterface
15
+ {
16
+ /** @var resource cURL multi handle. */
17
+ protected $multiHandle;
18
+
19
+ /** @var array Attached {@see RequestInterface} objects. */
20
+ protected $requests;
21
+
22
+ /** @var \SplObjectStorage RequestInterface to CurlHandle hash */
23
+ protected $handles;
24
+
25
+ /** @var array Hash mapping curl handle resource IDs to request objects */
26
+ protected $resourceHash;
27
+
28
+ /** @var array Queued exceptions */
29
+ protected $exceptions = array();
30
+
31
+ /** @var array Requests that succeeded */
32
+ protected $successful = array();
33
+
34
+ /** @var array cURL multi error values and codes */
35
+ protected $multiErrors = array(
36
+ CURLM_BAD_HANDLE => array('CURLM_BAD_HANDLE', 'The passed-in handle is not a valid CURLM handle.'),
37
+ CURLM_BAD_EASY_HANDLE => array('CURLM_BAD_EASY_HANDLE', "An easy handle was not good/valid. It could mean that it isn't an easy handle at all, or possibly that the handle already is in used by this or another multi handle."),
38
+ CURLM_OUT_OF_MEMORY => array('CURLM_OUT_OF_MEMORY', 'You are doomed.'),
39
+ CURLM_INTERNAL_ERROR => array('CURLM_INTERNAL_ERROR', 'This can only be returned if libcurl bugs. Please report it to us!')
40
+ );
41
+
42
+ public function __construct()
43
+ {
44
+ $this->multiHandle = curl_multi_init();
45
+ // @codeCoverageIgnoreStart
46
+ if ($this->multiHandle === false) {
47
+ throw new CurlException('Unable to create multi handle');
48
+ }
49
+ // @codeCoverageIgnoreEnd
50
+ $this->reset();
51
+ }
52
+
53
+ public function __destruct()
54
+ {
55
+ if (is_resource($this->multiHandle)) {
56
+ curl_multi_close($this->multiHandle);
57
+ }
58
+ }
59
+
60
+ public function add(RequestInterface $request)
61
+ {
62
+ $this->requests[] = $request;
63
+ // If requests are currently transferring and this is async, then the
64
+ // request must be prepared now as the send() method is not called.
65
+ $this->beforeSend($request);
66
+ $this->dispatch(self::ADD_REQUEST, array('request' => $request));
67
+
68
+ return $this;
69
+ }
70
+
71
+ public function all()
72
+ {
73
+ return $this->requests;
74
+ }
75
+
76
+ public function remove(RequestInterface $request)
77
+ {
78
+ $this->removeHandle($request);
79
+ if (($index = array_search($request, $this->requests, true)) !== false) {
80
+ $request = $this->requests[$index];
81
+ unset($this->requests[$index]);
82
+ $this->requests = array_values($this->requests);
83
+ $this->dispatch(self::REMOVE_REQUEST, array('request' => $request));
84
+ return true;
85
+ }
86
+
87
+ return false;
88
+ }
89
+
90
+ public function reset($hard = false)
91
+ {
92
+ // Remove each request
93
+ if ($this->requests) {
94
+ foreach ($this->requests as $request) {
95
+ $this->remove($request);
96
+ }
97
+ }
98
+
99
+ $this->handles = new \SplObjectStorage();
100
+ $this->requests = $this->resourceHash = $this->exceptions = $this->successful = array();
101
+ }
102
+
103
+ public function send()
104
+ {
105
+ $this->perform();
106
+ $exceptions = $this->exceptions;
107
+ $successful = $this->successful;
108
+ $this->reset();
109
+
110
+ if ($exceptions) {
111
+ $this->throwMultiException($exceptions, $successful);
112
+ }
113
+ }
114
+
115
+ public function count()
116
+ {
117
+ return count($this->requests);
118
+ }
119
+
120
+ /**
121
+ * Build and throw a MultiTransferException
122
+ *
123
+ * @param array $exceptions Exceptions encountered
124
+ * @param array $successful Successful requests
125
+ * @throws MultiTransferException
126
+ */
127
+ protected function throwMultiException(array $exceptions, array $successful)
128
+ {
129
+ $multiException = new MultiTransferException('Errors during multi transfer');
130
+
131
+ while ($e = array_shift($exceptions)) {
132
+ $multiException->addFailedRequestWithException($e['request'], $e['exception']);
133
+ }
134
+
135
+ // Add successful requests
136
+ foreach ($successful as $request) {
137
+ if (!$multiException->containsRequest($request)) {
138
+ $multiException->addSuccessfulRequest($request);
139
+ }
140
+ }
141
+
142
+ throw $multiException;
143
+ }
144
+
145
+ /**
146
+ * Prepare for sending
147
+ *
148
+ * @param RequestInterface $request Request to prepare
149
+ * @throws \Exception on error preparing the request
150
+ */
151
+ protected function beforeSend(RequestInterface $request)
152
+ {
153
+ try {
154
+ $state = $request->setState(RequestInterface::STATE_TRANSFER);
155
+ if ($state == RequestInterface::STATE_TRANSFER) {
156
+ // Add the request curl handle to the multi handle
157
+ $handle = $this->createCurlHandle($request)->getHandle();
158
+ $this->checkCurlResult(curl_multi_add_handle($this->multiHandle, $handle));
159
+ } else {
160
+ // Requests might decide they don't need to be sent just before transfer (e.g. CachePlugin)
161
+ $this->remove($request);
162
+ if ($state == RequestInterface::STATE_COMPLETE) {
163
+ $this->successful[] = $request;
164
+ }
165
+ }
166
+ } catch (\Exception $e) {
167
+ // Queue the exception to be thrown when sent
168
+ $this->removeErroredRequest($request, $e);
169
+ }
170
+ }
171
+
172
+ /**
173
+ * Create a curl handle for a request
174
+ *
175
+ * @param RequestInterface $request Request
176
+ *
177
+ * @return CurlHandle
178
+ */
179
+ protected function createCurlHandle(RequestInterface $request)
180
+ {
181
+ $wrapper = CurlHandle::factory($request);
182
+ $this->handles[$request] = $wrapper;
183
+ $this->resourceHash[(int) $wrapper->getHandle()] = $request;
184
+
185
+ return $wrapper;
186
+ }
187
+
188
+ /**
189
+ * Get the data from the multi handle
190
+ */
191
+ protected function perform()
192
+ {
193
+ $event = new Event(array('curl_multi' => $this));
194
+
195
+ while ($this->requests) {
196
+ // Notify each request as polling
197
+ $blocking = $total = 0;
198
+ foreach ($this->requests as $request) {
199
+ ++$total;
200
+ $event['request'] = $request;
201
+ $request->getEventDispatcher()->dispatch(self::POLLING_REQUEST, $event);
202
+ // The blocking variable just has to be non-falsey to block the loop
203
+ if ($request->getParams()->hasKey(self::BLOCKING)) {
204
+ ++$blocking;
205
+ }
206
+ }
207
+ if ($blocking == $total) {
208
+ // Sleep to prevent eating CPU because no requests are actually pending a select call
209
+ usleep(500);
210
+ } else {
211
+ $this->executeHandles();
212
+ }
213
+ }
214
+ }
215
+
216
+ /**
217
+ * Execute and select curl handles
218
+ */
219
+ private function executeHandles()
220
+ {
221
+ // The first curl_multi_select often times out no matter what, but is usually required for fast transfers
222
+ $selectTimeout = 0.001;
223
+ $active = false;
224
+ do {
225
+ while (($mrc = curl_multi_exec($this->multiHandle, $active)) == CURLM_CALL_MULTI_PERFORM);
226
+ $this->checkCurlResult($mrc);
227
+ $this->processMessages();
228
+ if ($active && curl_multi_select($this->multiHandle, $selectTimeout) === -1) {
229
+ // Perform a usleep if a select returns -1: https://bugs.php.net/bug.php?id=61141
230
+ usleep(150);
231
+ }
232
+ $selectTimeout = 1;
233
+ } while ($active);
234
+ }
235
+
236
+ /**
237
+ * Process any received curl multi messages
238
+ */
239
+ private function processMessages()
240
+ {
241
+ while ($done = curl_multi_info_read($this->multiHandle)) {
242
+ $request = $this->resourceHash[(int) $done['handle']];
243
+ try {
244
+ $this->processResponse($request, $this->handles[$request], $done);
245
+ $this->successful[] = $request;
246
+ } catch (\Exception $e) {
247
+ $this->removeErroredRequest($request, $e);
248
+ }
249
+ }
250
+ }
251
+
252
+ /**
253
+ * Remove a request that encountered an exception
254
+ *
255
+ * @param RequestInterface $request Request to remove
256
+ * @param \Exception $e Exception encountered
257
+ */
258
+ protected function removeErroredRequest(RequestInterface $request, \Exception $e = null)
259
+ {
260
+ $this->exceptions[] = array('request' => $request, 'exception' => $e);
261
+ $this->remove($request);
262
+ $this->dispatch(self::MULTI_EXCEPTION, array('exception' => $e, 'all_exceptions' => $this->exceptions));
263
+ }
264
+
265
+ /**
266
+ * Check for errors and fix headers of a request based on a curl response
267
+ *
268
+ * @param RequestInterface $request Request to process
269
+ * @param CurlHandle $handle Curl handle object
270
+ * @param array $curl Array returned from curl_multi_info_read
271
+ *
272
+ * @throws CurlException on Curl error
273
+ */
274
+ protected function processResponse(RequestInterface $request, CurlHandle $handle, array $curl)
275
+ {
276
+ // Set the transfer stats on the response
277
+ $handle->updateRequestFromTransfer($request);
278
+ // Check if a cURL exception occurred, and if so, notify things
279
+ $curlException = $this->isCurlException($request, $handle, $curl);
280
+
281
+ // Always remove completed curl handles. They can be added back again
282
+ // via events if needed (e.g. ExponentialBackoffPlugin)
283
+ $this->removeHandle($request);
284
+
285
+ if (!$curlException) {
286
+ $state = $request->setState(RequestInterface::STATE_COMPLETE, array('handle' => $handle));
287
+ // Only remove the request if it wasn't resent as a result of the state change
288
+ if ($state != RequestInterface::STATE_TRANSFER) {
289
+ $this->remove($request);
290
+ }
291
+ } else {
292
+ // Set the state of the request to an error
293
+ $state = $request->setState(RequestInterface::STATE_ERROR, array('exception' => $curlException));
294
+ // Allow things to ignore the error if possible
295
+ if ($state != RequestInterface::STATE_TRANSFER) {
296
+ $this->remove($request);
297
+ }
298
+ // The error was not handled, so fail
299
+ if ($state == RequestInterface::STATE_ERROR) {
300
+ /** @var CurlException $curlException */
301
+ throw $curlException;
302
+ }
303
+ }
304
+ }
305
+
306
+ /**
307
+ * Remove a curl handle from the curl multi object
308
+ *
309
+ * @param RequestInterface $request Request that owns the handle
310
+ */
311
+ protected function removeHandle(RequestInterface $request)
312
+ {
313
+ if (isset($this->handles[$request])) {
314
+ $handle = $this->handles[$request];
315
+ curl_multi_remove_handle($this->multiHandle, $handle->getHandle());
316
+ unset($this->handles[$request]);
317
+ unset($this->resourceHash[(int) $handle->getHandle()]);
318
+ $handle->close();
319
+ }
320
+ }
321
+
322
+ /**
323
+ * Check if a cURL transfer resulted in what should be an exception
324
+ *
325
+ * @param RequestInterface $request Request to check
326
+ * @param CurlHandle $handle Curl handle object
327
+ * @param array $curl Array returned from curl_multi_info_read
328
+ *
329
+ * @return CurlException|bool
330
+ */
331
+ private function isCurlException(RequestInterface $request, CurlHandle $handle, array $curl)
332
+ {
333
+ if (CURLM_OK == $curl['result'] || CURLM_CALL_MULTI_PERFORM == $curl['result']) {
334
+ return false;
335
+ }
336
+
337
+ $handle->setErrorNo($curl['result']);
338
+ $e = new CurlException(sprintf('[curl] %s: %s [url] %s',
339
+ $handle->getErrorNo(), $handle->getError(), $handle->getUrl()));
340
+ $e->setCurlHandle($handle)
341
+ ->setRequest($request)
342
+ ->setCurlInfo($handle->getInfo())
343
+ ->setError($handle->getError(), $handle->getErrorNo());
344
+
345
+ return $e;
346
+ }
347
+
348
+ /**
349
+ * Throw an exception for a cURL multi response if needed
350
+ *
351
+ * @param int $code Curl response code
352
+ * @throws CurlException
353
+ */
354
+ private function checkCurlResult($code)
355
+ {
356
+ if ($code != CURLM_OK && $code != CURLM_CALL_MULTI_PERFORM) {
357
+ throw new CurlException(isset($this->multiErrors[$code])
358
+ ? "cURL error: {$code} ({$this->multiErrors[$code][0]}): cURL message: {$this->multiErrors[$code][1]}"
359
+ : 'Unexpected cURL error: ' . $code
360
+ );
361
+ }
362
+ }
363
+ }
includes/php-opencloud/guzzle/http/Guzzle/Http/Curl/CurlMultiInterface.php ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Guzzle\Http\Curl;
4
+
5
+ use Guzzle\Common\HasDispatcherInterface;
6
+ use Guzzle\Common\Exception\ExceptionCollection;
7
+ use Guzzle\Http\Message\RequestInterface;
8
+
9
+ /**
10
+ * Interface for sending a pool of {@see RequestInterface} objects in parallel
11
+ */
12
+ interface CurlMultiInterface extends \Countable, HasDispatcherInterface
13
+ {
14
+ const POLLING_REQUEST = 'curl_multi.polling_request';
15
+ const ADD_REQUEST = 'curl_multi.add_request';
16
+ const REMOVE_REQUEST = 'curl_multi.remove_request';
17
+ const MULTI_EXCEPTION = 'curl_multi.exception';
18
+ const BLOCKING = 'curl_multi.blocking';
19
+
20
+ /**
21
+ * Add a request to the pool.
22
+ *
23
+ * @param RequestInterface $request Request to add
24
+ *
25
+ * @return CurlMultiInterface
26
+ */
27
+ public function add(RequestInterface $request);
28
+
29
+ /**
30
+ * Get an array of attached {@see RequestInterface} objects
31
+ *
32
+ * @return array
33
+ */
34
+ public function all();
35
+
36
+ /**
37
+ * Remove a request from the pool.
38
+ *
39
+ * @param RequestInterface $request Request to remove
40
+ *
41
+ * @return bool Returns true on success or false on failure
42
+ */
43
+ public function remove(RequestInterface $request);
44
+
45
+ /**
46
+ * Reset the state and remove any attached RequestInterface objects
47
+ *
48
+ * @param bool $hard Set to true to close and reopen any open multi handles
49
+ */
50
+ public function reset($hard = false);
51
+
52
+ /**
53
+ * Send a pool of {@see RequestInterface} requests.
54
+ *
55
+ * @throws ExceptionCollection if any requests threw exceptions during the transfer.
56
+ */
57
+ public function send();
58
+ }
includes/php-opencloud/guzzle/http/Guzzle/Http/Curl/CurlMultiProxy.php ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Guzzle\Http\Curl;
4
+
5
+ use Guzzle\Common\AbstractHasDispatcher;
6
+ use Guzzle\Http\Message\RequestInterface;
7
+
8
+ /**
9
+ * Proxies requests and connections to a pool of internal curl_multi handles. Each recursive call will add requests
10
+ * to the next available CurlMulti handle.
11
+ */
12
+ class CurlMultiProxy extends AbstractHasDispatcher implements CurlMultiInterface
13
+ {
14
+ protected $handles = array();
15
+ protected $groups = array();
16
+ protected $queued = array();
17
+ protected $maxHandles;
18
+
19
+ /**
20
+ * @param int $maxHandles The maximum number of idle CurlMulti handles to allow to remain open
21
+ */
22
+ public function __construct($maxHandles = 3)
23
+ {
24
+ $this->maxHandles = $maxHandles;
25
+ // You can get some weird "Too many open files" errors when sending a large amount of requests in parallel.
26
+ // These two statements autoload classes before a system runs out of file descriptors so that you can get back
27
+ // valuable error messages if you run out.
28
+ class_exists('Guzzle\Http\Message\Response');
29
+ class_exists('Guzzle\Http\Exception\CurlException');
30
+ }
31
+
32
+ public function add(RequestInterface $request)
33
+ {
34
+ $this->queued[] = $request;
35
+
36
+ return $this;
37
+ }
38
+
39
+ public function all()
40
+ {
41
+ $requests = $this->queued;
42
+ foreach ($this->handles as $handle) {
43
+ $requests = array_merge($requests, $handle->all());
44
+ }
45
+
46
+ return $requests;
47
+ }
48
+
49
+ public function remove(RequestInterface $request)
50
+ {
51
+ foreach ($this->queued as $i => $r) {
52
+ if ($request === $r) {
53
+ unset($this->queued[$i]);
54
+ return true;
55
+ }
56
+ }
57
+
58
+ foreach ($this->handles as $handle) {
59
+ if ($handle->remove($request)) {
60
+ return true;
61
+ }
62
+ }
63
+
64
+ return false;
65
+ }
66
+
67
+ public function reset($hard = false)
68
+ {
69
+ $this->queued = array();
70
+ $this->groups = array();
71
+ foreach ($this->handles as $handle) {
72
+ $handle->reset();
73
+ }
74
+ if ($hard) {
75
+ $this->handles = array();
76
+ }
77
+
78
+ return $this;
79
+ }
80
+
81
+ public function send()
82
+ {
83
+ if ($this->queued) {
84
+ $group = $this->getAvailableHandle();
85
+ // Add this handle to a list of handles than is claimed
86
+ $this->groups[] = $group;
87
+ while ($request = array_shift($this->queued)) {
88
+ $group->add($request);
89
+ }
90
+ try {
91
+ $group->send();
92
+ array_pop($this->groups);
93
+ $this->cleanupHandles();
94
+ } catch (\Exception $e) {
95
+ // Remove the group and cleanup if an exception was encountered and no more requests in group
96
+ if (!$group->count()) {
97
+ array_pop($this->groups);
98
+ $this->cleanupHandles();
99
+ }
100
+ throw $e;
101
+ }
102
+ }
103
+ }
104
+
105
+ public function count()
106
+ {
107
+ return count($this->all());
108
+ }
109
+
110
+ /**
111
+ * Get an existing available CurlMulti handle or create a new one
112
+ *
113
+ * @return CurlMulti
114
+ */
115
+ protected function getAvailableHandle()
116
+ {
117
+ // Grab a handle that is not claimed
118
+ foreach ($this->handles as $h) {
119
+ if (!in_array($h, $this->groups, true)) {
120
+ return $h;
121
+ }
122
+ }
123
+
124
+ // All are claimed, so create one
125
+ $handle = new CurlMulti();
126
+ $handle->setEventDispatcher($this->getEventDispatcher());
127
+ $this->handles[] = $handle;
128
+
129
+ return $handle;
130
+ }
131
+
132
+ /**
133
+ * Trims down unused CurlMulti handles to limit the number of open connections
134
+ */
135
+ protected function cleanupHandles()
136
+ {
137
+ if ($diff = max(0, count($this->handles) - $this->maxHandles)) {
138
+ for ($i = count($this->handles) - 1; $i > 0 && $diff > 0; $i--) {
139
+ if (!count($this->handles[$i])) {
140
+ unset($this->handles[$i]);
141
+ $diff--;
142
+ }
143
+ }
144
+ $this->handles = array_values($this->handles);
145
+ }
146
+ }
147
+ }
includes/php-opencloud/guzzle/http/Guzzle/Http/Curl/CurlVersion.php ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Guzzle\Http\Curl;
4
+
5
+ /**
6
+ * Class used for querying curl_version data
7
+ */
8
+ class CurlVersion
9
+ {
10
+ /** @var array curl_version() information */
11
+ protected $version;
12
+
13
+ /** @var CurlVersion */
14
+ protected static $instance;
15
+
16
+ /** @var string Default user agent */
17
+ protected $userAgent;
18
+
19
+ /**
20
+ * @return CurlVersion
21
+ */
22
+ public static function getInstance()
23
+ {
24
+ if (!self::$instance) {
25
+ self::$instance = new self();
26
+ }
27
+
28
+ return self::$instance;
29
+ }
30
+
31
+ /**
32
+ * Get all of the curl_version() data
33
+ *
34
+ * @return array
35
+ */
36
+ public function getAll()
37
+ {
38
+ if (!$this->version) {
39
+ $this->version = curl_version();
40
+ }
41
+
42
+ return $this->version;
43
+ }
44
+
45
+ /**
46
+ * Get a specific type of curl information
47
+ *
48
+ * @param string $type Version information to retrieve. This value is one of:
49
+ * - version_number: cURL 24 bit version number
50
+ * - version: cURL version number, as a string
51
+ * - ssl_version_number: OpenSSL 24 bit version number
52
+ * - ssl_version: OpenSSL version number, as a string
53
+ * - libz_version: zlib version number, as a string
54
+ * - host: Information about the host where cURL was built
55
+ * - features: A bitmask of the CURL_VERSION_XXX constants
56
+ * - protocols: An array of protocols names supported by cURL
57
+ *
58
+ * @return string|float|bool if the $type is found, and false if not found
59
+ */
60
+ public function get($type)
61
+ {
62
+ $version = $this->getAll();
63
+
64
+ return isset($version[$type]) ? $version[$type] : false;
65
+ }
66
+ }
includes/php-opencloud/guzzle/http/Guzzle/Http/Curl/RequestMediator.php ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Guzzle\Http\Curl;
4
+
5
+ use Guzzle\Http\Message\RequestInterface;
6
+ use Guzzle\Http\EntityBody;
7
+ use Guzzle\Http\Message\Response;
8
+
9
+ /**
10
+ * Mediator between curl handles and request objects
11
+ */
12
+ class RequestMediator
13
+ {
14
+ /** @var RequestInterface */
15
+ protected $request;
16
+
17
+ /** @var bool Whether or not to emit read/write events */
18
+ protected $emitIo;
19
+
20
+ /**
21
+ * @param RequestInterface $request Request to mediate
22
+ * @param bool $emitIo Set to true to dispatch events on input and output
23
+ */
24
+ public function __construct(RequestInterface $request, $emitIo = false)
25
+ {
26
+ $this->request = $request;
27
+ $this->emitIo = $emitIo;
28
+ }
29
+
30
+ /**
31
+ * Receive a response header from curl
32
+ *
33
+ * @param resource $curl Curl handle
34
+ * @param string $header Received header
35
+ *
36
+ * @return int
37
+ */
38
+ public function receiveResponseHeader($curl, $header)
39
+ {
40
+ static $normalize = array("\r", "\n");
41
+ $length = strlen($header);
42
+ $header = str_replace($normalize, '', $header);
43
+
44
+ if (strpos($header, 'HTTP/') === 0) {
45
+
46
+ $startLine = explode(' ', $header, 3);
47
+ $code = $startLine[1];
48
+ $status = isset($startLine[2]) ? $startLine[2] : '';
49
+
50
+ // Only download the body of the response to the specified response
51
+ // body when a successful response is received.
52
+ if ($code >= 200 && $code < 300) {
53
+ $body = $this->request->getResponseBody();
54
+ } else {
55
+ $body = EntityBody::factory();
56
+ }
57
+
58
+ $response = new Response($code, null, $body);
59
+ $response->setStatus($code, $status);
60
+ $this->request->startResponse($response);
61
+
62
+ $this->request->dispatch('request.receive.status_line', array(
63
+ 'request' => $this,
64
+ 'line' => $header,
65
+ 'status_code' => $code,
66
+ 'reason_phrase' => $status
67
+ ));
68
+
69
+ } elseif ($pos = strpos($header, ':')) {
70
+ $this->request->getResponse()->addHeader(
71
+ trim(substr($header, 0, $pos)),
72
+ trim(substr($header, $pos + 1))
73
+ );
74
+ }
75
+
76
+ return $length;
77
+ }
78
+
79
+ /**
80
+ * Received a progress notification
81
+ *
82
+ * @param int $downloadSize Total download size
83
+ * @param int $downloaded Amount of bytes downloaded
84
+ * @param int $uploadSize Total upload size
85
+ * @param int $uploaded Amount of bytes uploaded
86
+ * @param resource $handle CurlHandle object
87
+ */
88
+ public function progress($downloadSize, $downloaded, $uploadSize, $uploaded, $handle = null)
89
+ {
90
+ $this->request->dispatch('curl.callback.progress', array(
91
+ 'request' => $this->request,
92
+ 'handle' => $handle,
93
+ 'download_size' => $downloadSize,
94
+ 'downloaded' => $downloaded,
95
+ 'upload_size' => $uploadSize,
96
+ 'uploaded' => $uploaded
97
+ ));
98
+ }
99
+
100
+ /**
101
+ * Write data to the response body of a request
102
+ *
103
+ * @param resource $curl Curl handle
104
+ * @param string $write Data that was received
105
+ *
106
+ * @return int
107
+ */
108
+ public function writeResponseBody($curl, $write)
109
+ {
110
+ if ($this->emitIo) {
111
+ $this->request->dispatch('curl.callback.write', array(
112
+ 'request' => $this->request,
113
+ 'write' => $write
114
+ ));
115
+ }
116
+
117
+ if ($response = $this->request->getResponse()) {
118
+ return $response->getBody()->write($write);
119
+ } else {
120
+ // Unexpected data received before response headers - abort transfer
121
+ return 0;
122
+ }
123
+ }
124
+
125
+ /**
126
+ * Read data from the request body and send it to curl
127
+ *
128
+ * @param resource $ch Curl handle
129
+ * @param resource $fd File descriptor
130
+ * @param int $length Amount of data to read
131
+ *
132
+ * @return string
133
+ */
134
+ public function readRequestBody($ch, $fd, $length)
135
+ {
136
+ if (!($body = $this->request->getBody())) {
137
+ return '';
138
+ }
139
+
140
+ $read = (string) $body->read($length);
141
+ if ($this->emitIo) {
142
+ $this->request->dispatch('curl.callback.read', array('request' => $this->request, 'read' => $read));
143
+ }
144
+
145
+ return $read;
146
+ }
147
+ }
includes/php-opencloud/guzzle/http/Guzzle/Http/EntityBody.php ADDED
@@ -0,0 +1,201 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Guzzle\Http;
4
+
5
+ use Guzzle\Common\Version;
6
+ use Guzzle\Stream\Stream;
7
+ use Guzzle\Common\Exception\InvalidArgumentException;
8
+ use Guzzle\Http\Mimetypes;
9
+
10
+ /**
11
+ * Entity body used with an HTTP request or response
12
+ */
13
+ class EntityBody extends Stream implements EntityBodyInterface
14
+ {
15
+ /** @var bool Content-Encoding of the entity body if known */
16
+ protected $contentEncoding = false;
17
+
18
+ /** @var callable Method to invoke for rewinding a stream */
19
+ protected $rewindFunction;
20
+
21
+ /**
22
+ * Create a new EntityBody based on the input type
23
+ *
24
+ * @param resource|string|EntityBody $resource Entity body data
25
+ * @param int $size Size of the data contained in the resource
26
+ *
27
+ * @return EntityBody
28
+ * @throws InvalidArgumentException if the $resource arg is not a resource or string
29
+ */
30
+ public static function factory($resource = '', $size = null)
31
+ {
32
+ if ($resource instanceof EntityBodyInterface) {
33
+ return $resource;
34
+ }
35
+
36
+ switch (gettype($resource)) {
37
+ case 'string':
38
+ return self::fromString($resource);
39
+ case 'resource':
40
+ return new static($resource, $size);
41
+ case 'object':
42
+ if (method_exists($resource, '__toString')) {
43
+ return self::fromString((string) $resource);
44
+ }
45
+ break;
46
+ case 'array':
47
+ return self::fromString(http_build_query($resource));
48
+ }
49
+
50
+ throw new InvalidArgumentException('Invalid resource type');
51
+ }
52
+
53
+ public function setRewindFunction($callable)
54
+ {
55
+ if (!is_callable($callable)) {
56
+ throw new InvalidArgumentException('Must specify a callable');
57
+ }
58
+
59
+ $this->rewindFunction = $callable;
60
+
61
+ return $this;
62
+ }
63
+
64
+ public function rewind()
65
+ {
66
+ return $this->rewindFunction ? call_user_func($this->rewindFunction, $this) : parent::rewind();
67
+ }
68
+
69
+ /**
70
+ * Create a new EntityBody from a string
71
+ *
72
+ * @param string $string String of data
73
+ *
74
+ * @return EntityBody
75
+ */
76
+ public static function fromString($string)
77
+ {
78
+ $stream = fopen('php://temp', 'r+');
79
+ if ($string !== '') {
80
+ fwrite($stream, $string);
81
+ rewind($stream);
82
+ }
83
+
84
+ return new static($stream);
85
+ }
86
+
87
+ public function compress($filter = 'zlib.deflate')
88
+ {
89
+ $result = $this->handleCompression($filter);
90
+ $this->contentEncoding = $result ? $filter : false;
91
+
92
+ return $result;
93
+ }
94
+
95
+ public function uncompress($filter = 'zlib.inflate')
96
+ {
97
+ $offsetStart = 0;
98
+
99
+ // When inflating gzipped data, the first 10 bytes must be stripped
100
+ // if a gzip header is present
101
+ if ($filter == 'zlib.inflate') {
102
+ // @codeCoverageIgnoreStart
103
+ if (!$this->isReadable() || ($this->isConsumed() && !$this->isSeekable())) {
104
+ return false;
105
+ }
106
+ // @codeCoverageIgnoreEnd
107
+ if (stream_get_contents($this->stream, 3, 0) === "\x1f\x8b\x08") {
108
+ $offsetStart = 10;
109
+ }
110
+ }
111
+
112
+ $this->contentEncoding = false;
113
+
114
+ return $this->handleCompression($filter, $offsetStart);
115
+ }
116
+
117
+ public function getContentLength()
118
+ {
119
+ return $this->getSize();
120
+ }
121
+
122
+ public function getContentType()
123
+ {
124
+ return $this->getUri() ? Mimetypes::getInstance()->fromFilename($this->getUri()) : null;
125
+ }
126
+
127
+ public function getContentMd5($rawOutput = false, $base64Encode = false)
128
+ {
129
+ if ($hash = self::getHash($this, 'md5', $rawOutput)) {
130
+ return $hash && $base64Encode ? base64_encode($hash) : $hash;
131
+ } else {
132
+ return false;
133
+ }
134
+ }
135
+
136
+ /**
137
+ * Calculate the MD5 hash of an entity body
138
+ *
139
+ * @param EntityBodyInterface $body Entity body to calculate the hash for
140
+ * @param bool $rawOutput Whether or not to use raw output
141
+ * @param bool $base64Encode Whether or not to base64 encode raw output (only if raw output is true)
142
+ *
143
+ * @return bool|string Returns an MD5 string on success or FALSE on failure
144
+ * @deprecated This will be deprecated soon
145
+ * @codeCoverageIgnore
146
+ */
147
+ public static function calculateMd5(EntityBodyInterface $body, $rawOutput = false, $base64Encode = false)
148
+ {
149
+ Version::warn(__CLASS__ . ' is deprecated. Use getContentMd5()');
150
+ return $body->getContentMd5($rawOutput, $base64Encode);
151
+ }
152
+
153
+ public function setStreamFilterContentEncoding($streamFilterContentEncoding)
154
+ {
155
+ $this->contentEncoding = $streamFilterContentEncoding;
156
+
157
+ return $this;
158
+ }
159
+
160
+ public function getContentEncoding()
161
+ {
162
+ return strtr($this->contentEncoding, array(
163
+ 'zlib.deflate' => 'gzip',
164
+ 'bzip2.compress' => 'compress'
165
+ )) ?: false;
166
+ }
167
+
168
+ protected function handleCompression($filter, $offsetStart = 0)
169
+ {
170
+ // @codeCoverageIgnoreStart
171
+ if (!$this->isReadable() || ($this->isConsumed() && !$this->isSeekable())) {
172
+ return false;
173
+ }
174
+ // @codeCoverageIgnoreEnd
175
+
176
+ $handle = fopen('php://temp', 'r+');
177
+ $filter = @stream_filter_append($handle, $filter, STREAM_FILTER_WRITE);
178
+ if (!$filter) {
179
+ return false;
180
+ }
181
+
182
+ // Seek to the offset start if possible
183
+ $this->seek($offsetStart);
184
+ while ($data = fread($this->stream, 8096)) {
185
+ fwrite($handle, $data);
186
+ }
187
+
188
+ fclose($this->stream);
189
+ $this->stream = $handle;
190
+ stream_filter_remove($filter);
191
+ $stat = fstat($this->stream);
192
+ $this->size = $stat['size'];
193
+ $this->rebuildCache();
194
+ $this->seek(0);
195
+
196
+ // Remove any existing rewind function as the underlying stream has been replaced
197
+ $this->rewindFunction = null;
198
+
199
+ return true;
200
+ }
201
+ }
includes/php-opencloud/guzzle/http/Guzzle/Http/EntityBodyInterface.php ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Guzzle\Http;
4
+
5
+ use Guzzle\Stream\StreamInterface;
6
+
7
+ /**
8
+ * Entity body used with an HTTP request or response
9
+ */
10
+ interface EntityBodyInterface extends StreamInterface
11
+ {
12
+ /**
13
+ * Specify a custom callback used to rewind a non-seekable stream. This can be useful entity enclosing requests
14
+ * that are redirected.
15
+ *
16
+ * @param mixed $callable Callable to invoke to rewind a non-seekable stream. The callback must accept an
17
+ * EntityBodyInterface object, perform the rewind if possible, and return a boolean
18
+ * representing whether or not the rewind was successful.
19
+ * @return self
20
+ */
21
+ public function setRewindFunction($callable);
22
+
23
+ /**
24
+ * If the stream is readable, compress the data in the stream using deflate compression. The uncompressed stream is
25
+ * then closed, and the compressed stream then becomes the wrapped stream.
26
+ *
27
+ * @param string $filter Compression filter
28
+ *
29
+ * @return bool Returns TRUE on success or FALSE on failure
30
+ */
31
+ public function compress($filter = 'zlib.deflate');
32
+
33
+ /**
34
+ * Decompress a deflated string. Once uncompressed, the uncompressed string is then used as the wrapped stream.
35
+ *
36
+ * @param string $filter De-compression filter
37
+ *
38
+ * @return bool Returns TRUE on success or FALSE on failure
39
+ */
40
+ public function uncompress($filter = 'zlib.inflate');
41
+
42
+ /**
43
+ * Get the Content-Length of the entity body if possible (alias of getSize)
44
+ *
45
+ * @return int|bool Returns the Content-Length or false on failure
46
+ */
47
+ public function getContentLength();
48
+
49
+ /**
50
+ * Guess the Content-Type of a local stream
51
+ *
52
+ * @return string|null
53
+ * @see http://www.php.net/manual/en/function.finfo-open.php
54
+ */
55
+ public function getContentType();
56
+
57
+ /**
58
+ * Get an MD5 checksum of the stream's contents
59
+ *
60
+ * @param bool $rawOutput Whether or not to use raw output
61
+ * @param bool $base64Encode Whether or not to base64 encode raw output (only if raw output is true)
62
+ *
63
+ * @return bool|string Returns an MD5 string on success or FALSE on failure
64
+ */
65
+ public function getContentMd5($rawOutput = false, $base64Encode = false);
66
+
67
+ /**
68
+ * Get the Content-Encoding of the EntityBody
69
+ *
70
+ * @return bool|string
71
+ */
72
+ public function getContentEncoding();
73
+ }
includes/php-opencloud/guzzle/http/Guzzle/Http/Exception/BadResponseException.php ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Guzzle\Http\Exception;
4
+
5
+ use Guzzle\Http\Message\RequestInterface;
6
+ use Guzzle\Http\Message\Response;
7
+
8
+ /**
9
+ * Http request exception thrown when a bad response is received
10
+ */
11
+ class BadResponseException extends RequestException
12
+ {
13
+ /** @var Response */
14
+ private $response;
15
+
16
+ /**
17
+ * Factory method to create a new response exception based on the response code.
18
+ *
19
+ * @param RequestInterface $request Request
20
+ * @param Response $response Response received
21
+ *
22
+ * @return BadResponseException
23
+ */
24
+ public static function factory(RequestInterface $request, Response $response)
25
+ {
26
+ if ($response->isClientError()) {
27
+ $label = 'Client error response';
28
+ $class = __NAMESPACE__ . '\\ClientErrorResponseException';
29
+ } elseif ($response->isServerError()) {
30
+ $label = 'Server error response';
31
+ $class = __NAMESPACE__ . '\\ServerErrorResponseException';
32
+ } else {
33
+ $label = 'Unsuccessful response';
34
+ $class = __CLASS__;
35
+ $e = new self();
36
+ }
37
+
38
+ $message = $label . PHP_EOL . implode(PHP_EOL, array(
39
+ '[status code] ' . $response->getStatusCode(),
40
+ '[reason phrase] ' . $response->getReasonPhrase(),
41
+ '[url] ' . $request->getUrl(),
42
+ ));
43
+
44
+ $e = new $class($message);
45
+ $e->setResponse($response);
46
+ $e->setRequest($request);
47
+
48
+ return $e;
49
+ }
50
+
51
+ /**
52
+ * Set the response that caused the exception
53
+ *
54
+ * @param Response $response Response to set
55
+ */
56
+ public function setResponse(Response $response)
57
+ {
58
+ $this->response = $response;
59
+ }
60
+
61
+ /**
62
+ * Get the response that caused the exception
63
+ *
64
+ * @return Response
65
+ */
66
+ public function getResponse()
67
+ {
68
+ return $this->response;
69
+ }
70
+ }
includes/php-opencloud/guzzle/http/Guzzle/Http/Exception/ClientErrorResponseException.php ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Guzzle\Http\Exception;
4
+
5
+ /**
6
+ * Exception when a client error is encountered (4xx codes)
7
+ */
8
+ class ClientErrorResponseException extends BadResponseException {}
includes/php-opencloud/guzzle/http/Guzzle/Http/Exception/CouldNotRewindStreamException.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Guzzle\Http\Exception;
4
+
5
+ use Guzzle\Common\Exception\RuntimeException;
6
+
7
+ class CouldNotRewindStreamException extends RuntimeException implements HttpException {}
includes/php-opencloud/guzzle/http/Guzzle/Http/Exception/CurlException.php ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Guzzle\Http\Exception;
4
+
5
+ use Guzzle\Http\Curl\CurlHandle;
6
+
7
+ /**
8
+ * cURL request exception
9
+ */
10
+ class CurlException extends RequestException
11
+ {
12
+ private $curlError;
13
+ private $curlErrorNo;
14
+ private $handle;
15
+ private $curlInfo = array();
16
+
17
+ /**
18
+ * Set the cURL error message
19
+ *
20
+ * @param string $error Curl error
21
+ * @param int $number Curl error number
22
+ *
23
+ * @return self
24
+ */
25
+ public function setError($error, $number)
26
+ {
27
+ $this->curlError = $error;
28
+ $this->curlErrorNo = $number;
29
+
30
+ return $this;
31
+ }
32
+
33
+ /**
34
+ * Set the associated curl handle
35
+ *
36
+ * @param CurlHandle $handle Curl handle
37
+ *
38
+ * @return self
39
+ */
40
+ public function setCurlHandle(CurlHandle $handle)
41
+ {
42
+ $this->handle = $handle;
43
+
44
+ return $this;
45
+ }
46
+
47
+ /**
48
+ * Get the associated cURL handle
49
+ *
50
+ * @return CurlHandle|null
51
+ */
52
+ public function getCurlHandle()
53
+ {
54
+ return $this->handle;
55
+ }
56
+
57
+ /**
58
+ * Get the associated cURL error message
59
+ *
60
+ * @return string|null
61
+ */
62
+ public function getError()
63
+ {
64
+ return $this->curlError;
65
+ }
66
+
67
+ /**
68
+ * Get the associated cURL error number
69
+ *
70
+ * @return int|null
71
+ */
72
+ public function getErrorNo()
73
+ {
74
+ return $this->curlErrorNo;
75
+ }
76
+
77
+ /**
78
+ * Returns curl information about the transfer
79
+ *
80
+ * @return array
81
+ */
82
+ public function getCurlInfo()
83
+ {
84
+ return $this->curlInfo;
85
+ }
86
+
87
+ /**
88
+ * Set curl transfer information
89
+ *
90
+ * @param array $info Array of curl transfer information
91
+ *
92
+ * @return self
93
+ * @link http://php.net/manual/en/function.curl-getinfo.php
94
+ */
95
+ public function setCurlInfo(array $info)
96
+ {
97
+ $this->curlInfo = $info;
98
+
99
+ return $this;
100
+ }
101
+ }
includes/php-opencloud/guzzle/http/Guzzle/Http/Exception/HttpException.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Guzzle\Http\Exception;
4
+
5
+ use Guzzle\Common\Exception\GuzzleException;
6
+
7
+ /**
8
+ * Http exception interface
9
+ */
10
+ interface HttpException extends GuzzleException {}
includes/php-opencloud/guzzle/http/Guzzle/Http/Exception/MultiTransferException.php ADDED
@@ -0,0 +1,145 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Guzzle\Http\Exception;
4
+
5
+ use Guzzle\Common\Exception\ExceptionCollection;
6
+ use Guzzle\Http\Message\RequestInterface;
7
+
8
+ /**
9
+ * Exception encountered during a multi transfer
10
+ */
11
+ class MultiTransferException extends ExceptionCollection
12
+ {
13
+ protected $successfulRequests = array();
14
+ protected $failedRequests = array();
15
+ protected $exceptionForRequest = array();
16
+
17
+ /**
18
+ * Get all of the requests in the transfer
19
+ *
20
+ * @return array
21
+ */
22
+ public function getAllRequests()
23
+ {
24
+ return array_merge($this->successfulRequests, $this->failedRequests);
25
+ }
26
+
27
+ /**
28
+ * Add to the array of successful requests
29
+ *
30
+ * @param RequestInterface $request Successful request
31
+ *
32
+ * @return self
33
+ */
34
+ public function addSuccessfulRequest(RequestInterface $request)
35
+ {
36
+ $this->successfulRequests[] = $request;
37
+
38
+ return $this;
39
+ }
40
+
41
+ /**
42
+ * Add to the array of failed requests
43
+ *
44
+ * @param RequestInterface $request Failed request
45
+ *
46
+ * @return self
47
+ */
48
+ public function addFailedRequest(RequestInterface $request)
49
+ {
50
+ $this->failedRequests[] = $request;
51
+
52
+ return $this;
53
+ }
54
+
55
+ /**
56
+ * Add to the array of failed requests and associate with exceptions
57
+ *
58
+ * @param RequestInterface $request Failed request
59
+ * @param \Exception $exception Exception to add and associate with
60
+ *
61
+ * @return self
62
+ */
63
+ public function addFailedRequestWithException(RequestInterface $request, \Exception $exception)
64
+ {
65
+ $this->add($exception)
66
+ ->addFailedRequest($request)
67
+ ->exceptionForRequest[spl_object_hash($request)] = $exception;
68
+
69
+ return $this;
70
+ }
71
+
72
+ /**
73
+ * Get the Exception that caused the given $request to fail
74
+ *
75
+ * @param RequestInterface $request Failed command
76
+ *
77
+ * @return \Exception|null
78
+ */
79
+ public function getExceptionForFailedRequest(RequestInterface $request)
80
+ {
81
+ $oid = spl_object_hash($request);
82
+
83
+ return isset($this->exceptionForRequest[$oid]) ? $this->exceptionForRequest[$oid] : null;
84
+ }
85
+
86
+ /**
87
+ * Set all of the successful requests
88
+ *
89
+ * @param array Array of requests
90
+ *
91
+ * @return self
92
+ */
93
+ public function setSuccessfulRequests(array $requests)
94
+ {
95
+ $this->successfulRequests = $requests;
96
+
97
+ return $this;
98
+ }
99
+
100
+ /**
101
+ * Set all of the failed requests
102
+ *
103
+ * @param array Array of requests
104
+ *
105
+ * @return self
106
+ */
107
+ public function setFailedRequests(array $requests)
108
+ {
109
+ $this->failedRequests = $requests;
110
+
111
+ return $this;
112
+ }
113
+
114
+ /**
115
+ * Get an array of successful requests sent in the multi transfer
116
+ *
117
+ * @return array
118
+ */
119
+ public function getSuccessfulRequests()
120
+ {
121
+ return $this->successfulRequests;
122
+ }
123
+
124
+ /**
125
+ * Get an array of failed requests sent in the multi transfer
126
+ *
127
+ * @return array
128
+ */
129
+ public function getFailedRequests()
130
+ {
131
+ return $this->failedRequests;
132
+ }
133
+
134
+ /**
135
+ * Check if the exception object contains a request
136
+ *
137
+ * @param RequestInterface $request Request to check
138
+ *
139
+ * @return bool
140
+ */
141
+ public function containsRequest(RequestInterface $request)
142
+ {
143
+ return in_array($request, $this->failedRequests, true) || in_array($request, $this->successfulRequests, true);
144
+ }
145
+ }
includes/php-opencloud/guzzle/http/Guzzle/Http/Exception/RequestException.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Guzzle\Http\Exception;
4
+
5
+ use Guzzle\Common\Exception\RuntimeException;
6
+ use Guzzle\Http\Message\RequestInterface;
7
+
8
+ /**
9
+ * Http request exception
10
+ */
11
+ class RequestException extends RuntimeException implements HttpException
12
+ {
13
+ /** @var RequestInterface */
14
+ protected $request;
15
+
16
+ /**
17
+ * Set the request that caused the exception
18
+ *
19
+ * @param RequestInterface $request Request to set
20
+ *
21
+ * @return RequestException
22
+ */
23
+ public function setRequest(RequestInterface $request)
24
+ {
25
+ $this->request = $request;
26
+
27
+ return $this;
28
+ }
29
+
30
+ /**
31
+ * Get the request that caused the exception
32
+ *
33
+ * @return RequestInterface
34
+ */
35
+ public function getRequest()
36
+ {
37
+ return $this->request;
38
+ }
39
+ }
includes/php-opencloud/guzzle/http/Guzzle/Http/Exception/ServerErrorResponseException.php ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Guzzle\Http\Exception;
4
+
5
+ /**
6
+ * Exception when a server error is encountered (5xx codes)
7
+ */
8
+ class ServerErrorResponseException extends BadResponseException {}
includes/php-opencloud/guzzle/http/Guzzle/Http/Exception/TooManyRedirectsException.php ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Guzzle\Http\Exception;
4
+
5
+ class TooManyRedirectsException extends BadResponseException {}
includes/php-opencloud/guzzle/http/Guzzle/Http/IoEmittingEntityBody.php ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Guzzle\Http;
4
+
5
+ use Guzzle\Common\Event;
6
+ use Guzzle\Common\HasDispatcherInterface;
7
+ use Symfony\Component\EventDispatcher\EventDispatcher;
8
+ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
9
+ use Symfony\Component\EventDispatcher\EventDispatcherInterface;
10
+
11
+ /**
12
+ * EntityBody decorator that emits events for read and write methods
13
+ */
14
+ class IoEmittingEntityBody extends AbstractEntityBodyDecorator implements HasDispatcherInterface
15
+ {
16
+ /** @var EventDispatcherInterface */
17
+ protected $eventDispatcher;
18
+
19
+ public static function getAllEvents()
20
+ {
21
+ return array('body.read', 'body.write');
22
+ }
23
+
24
+ /**
25
+ * {@inheritdoc}
26
+ * @codeCoverageIgnore
27
+ */
28
+ public function setEventDispatcher(EventDispatcherInterface $eventDispatcher)
29
+ {
30
+ $this->eventDispatcher = $eventDispatcher;
31
+
32
+ return $this;
33
+ }
34
+
35
+ public function getEventDispatcher()
36
+ {
37
+ if (!$this->eventDispatcher) {
38
+ $this->eventDispatcher = new EventDispatcher();
39
+ }
40
+
41
+ return $this->eventDispatcher;
42
+ }
43
+
44
+ public function dispatch($eventName, array $context = array())
45
+ {
46
+ return $this->getEventDispatcher()->dispatch($eventName, new Event($context));
47
+ }
48
+
49
+ /**
50
+ * {@inheritdoc}
51
+ * @codeCoverageIgnore
52
+ */
53
+ public function addSubscriber(EventSubscriberInterface $subscriber)
54
+ {
55
+ $this->getEventDispatcher()->addSubscriber($subscriber);
56
+
57
+ return $this;
58
+ }
59
+
60
+ public function read($length)
61
+ {
62
+ $event = array(
63
+ 'body' => $this,
64
+ 'length' => $length,
65
+ 'read' => $this->body->read($length)
66
+ );
67
+ $this->dispatch('body.read', $event);
68
+
69
+ return $event['read'];
70
+ }
71
+
72
+ public function write($string)
73
+ {
74
+ $event = array(
75
+ 'body' => $this,
76
+ 'write' => $string,
77
+ 'result' => $this->body->write($string)
78
+ );
79
+ $this->dispatch('body.write', $event);
80
+
81
+ return $event['result'];
82
+ }
83
+ }
includes/php-opencloud/guzzle/http/Guzzle/Http/Message/AbstractMessage.php ADDED
@@ -0,0 +1,220 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Guzzle\Http\Message;
4
+
5
+ use Guzzle\Common\Version;
6
+ use Guzzle\Common\Collection;
7
+ use Guzzle\Http\Message\Header\HeaderCollection;
8
+ use Guzzle\Http\Message\Header\HeaderFactory;
9
+ use Guzzle\Http\Message\Header\HeaderFactoryInterface;
10
+ use Guzzle\Http\Message\Header\HeaderInterface;
11
+
12
+ /**
13
+ * Abstract HTTP request/response message
14
+ */
15
+ abstract class AbstractMessage implements MessageInterface
16
+ {
17
+ /** @var array HTTP header collection */
18
+ protected $headers;
19
+
20
+ /** @var HeaderFactoryInterface $headerFactory */
21
+ protected $headerFactory;
22
+
23
+ /** @var Collection Custom message parameters that are extendable by plugins */
24
+ protected $params;
25
+
26
+ /** @var string Message protocol */
27
+ protected $protocol = 'HTTP';
28
+
29
+ /** @var string HTTP protocol version of the message */
30
+ protected $protocolVersion = '1.1';
31
+
32
+ public function __construct()
33
+ {
34
+ $this->params = new Collection();
35
+ $this->headerFactory = new HeaderFactory();
36
+ $this->headers = new HeaderCollection();
37
+ }
38
+
39
+ /**
40
+ * Set the header factory to use to create headers
41
+ *
42
+ * @param HeaderFactoryInterface $factory
43
+ *
44
+ * @return self
45
+ */
46
+ public function setHeaderFactory(HeaderFactoryInterface $factory)
47
+ {
48
+ $this->headerFactory = $factory;
49
+
50
+ return $this;
51
+ }
52
+
53
+ public function getParams()
54
+ {
55
+ return $this->params;
56
+ }
57
+
58
+ public function addHeader($header, $value)
59
+ {
60
+ if (isset($this->headers[$header])) {
61
+ $this->headers[$header]->add($value);
62
+ } elseif ($value instanceof HeaderInterface) {
63
+ $this->headers[$header] = $value;
64
+ } else {
65
+ $this->headers[$header] = $this->headerFactory->createHeader($header, $value);
66
+ }
67
+
68
+ return $this;
69
+ }
70
+
71
+ public function addHeaders(array $headers)
72
+ {
73
+ foreach ($headers as $key => $value) {
74
+ $this->addHeader($key, $value);
75
+ }
76
+
77
+ return $this;
78
+ }
79
+
80
+ public function getHeader($header)
81
+ {
82
+ return $this->headers[$header];
83
+ }
84
+
85
+ public function getHeaders()
86
+ {
87
+ return $this->headers;
88
+ }
89
+
90
+ public function getHeaderLines()
91
+ {
92
+ $headers = array();
93
+ foreach ($this->headers as $value) {
94
+ $headers[] = $value->getName() . ': ' . $value;
95
+ }
96
+
97
+ return $headers;
98
+ }
99
+
100
+ public function setHeader($header, $value)
101
+ {
102
+ unset($this->headers[$header]);
103
+ $this->addHeader($header, $value);
104
+
105
+ return $this;
106
+ }
107
+
108
+ public function setHeaders(array $headers)
109
+ {
110
+ $this->headers->clear();
111
+ foreach ($headers as $key => $value) {
112
+ $this->addHeader($key, $value);
113
+ }
114
+
115
+ return $this;
116
+ }
117
+
118
+ public function hasHeader($header)
119
+ {
120
+ return isset($this->headers[$header]);
121
+ }
122
+
123
+ public function removeHeader($header)
124
+ {
125
+ unset($this->headers[$header]);
126
+
127
+ return $this;
128
+ }
129
+
130
+ /**
131
+ * @deprecated Use $message->getHeader()->parseParams()
132
+ * @codeCoverageIgnore
133
+ */
134
+ public function getTokenizedHeader($header, $token = ';')
135
+ {
136
+ Version::warn(__METHOD__ . ' is deprecated. Use $message->getHeader()->parseParams()');
137
+ if ($this->hasHeader($header)) {
138
+ $data = new Collection();
139
+ foreach ($this->getHeader($header)->parseParams() as $values) {
140
+ foreach ($values as $key => $value) {
141
+ if ($value === '') {
142
+ $data->set($data->count(), $key);
143
+ } else {
144
+ $data->add($key, $value);
145
+ }
146
+ }
147
+ }
148
+ return $data;
149
+ }
150
+ }
151
+
152
+ /**
153
+ * @deprecated
154
+ * @codeCoverageIgnore
155
+ */
156
+ public function setTokenizedHeader($header, $data, $token = ';')
157
+ {
158
+ Version::warn(__METHOD__ . ' is deprecated.');
159
+ return $this;
160
+ }
161
+
162
+ /**
163
+ * @deprecated
164
+ * @codeCoverageIgnore
165
+ */
166
+ public function getCacheControlDirective($directive)
167
+ {
168
+ Version::warn(__METHOD__ . ' is deprecated. Use $message->getHeader(\'Cache-Control\')->getDirective()');
169
+ if (!($header = $this->getHeader('Cache-Control'))) {
170
+ return null;
171
+ }
172
+
173
+ return $header->getDirective($directive);
174
+ }
175
+
176
+ /**
177
+ * @deprecated
178
+ * @codeCoverageIgnore
179
+ */
180
+ public function hasCacheControlDirective($directive)
181
+ {
182
+ Version::warn(__METHOD__ . ' is deprecated. Use $message->getHeader(\'Cache-Control\')->hasDirective()');
183
+ if ($header = $this->getHeader('Cache-Control')) {
184
+ return $header->hasDirective($directive);
185
+ } else {
186
+ return false;
187
+ }
188
+ }
189
+
190
+ /**
191
+ * @deprecated
192
+ * @codeCoverageIgnore
193
+ */
194
+ public function addCacheControlDirective($directive, $value = true)
195
+ {
196
+ Version::warn(__METHOD__ . ' is deprecated. Use $message->getHeader(\'Cache-Control\')->addDirective()');
197
+ if (!($header = $this->getHeader('Cache-Control'))) {
198
+ $this->addHeader('Cache-Control', '');
199
+ $header = $this->getHeader('Cache-Control');
200
+ }
201
+
202
+ $header->addDirective($directive, $value);
203
+
204
+ return $this;
205
+ }
206
+
207
+ /**
208
+ * @deprecated
209
+ * @codeCoverageIgnore
210
+ */
211
+ public function removeCacheControlDirective($directive)
212
+ {
213
+ Version::warn(__METHOD__ . ' is deprecated. Use $message->getHeader(\'Cache-Control\')->removeDirective()');
214
+ if ($header = $this->getHeader('Cache-Control')) {
215
+ $header->removeDirective($directive);
216
+ }
217
+
218
+ return $this;
219
+ }
220
+ }
includes/php-opencloud/guzzle/http/Guzzle/Http/Message/EntityEnclosingRequest.php ADDED
@@ -0,0 +1,248 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Guzzle\Http\Message;
4
+
5
+ use Guzzle\Http\EntityBody;
6
+ use Guzzle\Http\EntityBodyInterface;
7
+ use Guzzle\Http\QueryString;
8
+ use Guzzle\Http\RedirectPlugin;
9
+ use Guzzle\Http\Exception\RequestException;
10
+ use Guzzle\Http\Mimetypes;
11
+
12
+ /**
13
+ * HTTP request that sends an entity-body in the request message (POST, PUT, PATCH, DELETE)
14
+ */
15
+ class EntityEnclosingRequest extends Request implements EntityEnclosingRequestInterface
16
+ {
17
+ /** @var int When the size of the body is greater than 1MB, then send Expect: 100-Continue */
18
+ protected $expectCutoff = 1048576;
19
+
20
+ /** @var EntityBodyInterface $body Body of the request */
21
+ protected $body;
22
+
23
+ /** @var QueryString POST fields to use in the EntityBody */
24
+ protected $postFields;
25
+
26
+ /** @var array POST files to send with the request */
27
+ protected $postFiles = array();
28
+
29
+ public function __construct($method, $url, $headers = array())
30
+ {
31
+ $this->postFields = new QueryString();
32
+ parent::__construct($method, $url, $headers);
33
+ }
34
+
35
+ /**
36
+ * @return string
37
+ */
38
+ public function __toString()
39
+ {
40
+ // Only attempt to include the POST data if it's only fields
41
+ if (count($this->postFields) && empty($this->postFiles)) {
42
+ return parent::__toString() . (string) $this->postFields;
43
+ }
44
+
45
+ return parent::__toString() . $this->body;
46
+ }
47
+
48
+ public function setState($state, array $context = array())
49
+ {
50
+ parent::setState($state, $context);
51
+ if ($state == self::STATE_TRANSFER && !$this->body && !count($this->postFields) && !count($this->postFiles)) {
52
+ $this->setHeader('Content-Length', 0)->removeHeader('Transfer-Encoding');
53
+ }
54
+
55
+ return $this->state;
56
+ }
57
+
58
+ public function setBody($body, $contentType = null)
59
+ {
60
+ $this->body = EntityBody::factory($body);
61
+
62
+ // Auto detect the Content-Type from the path of the request if possible
63
+ if ($contentType === null && !$this->hasHeader('Content-Type')) {
64
+ $contentType = $this->body->getContentType();
65
+ }
66
+
67
+ if ($contentType) {
68
+ $this->setHeader('Content-Type', $contentType);
69
+ }
70
+
71
+ // Always add the Expect 100-Continue header if the body cannot be rewound. This helps with redirects.
72
+ if (!$this->body->isSeekable() && $this->expectCutoff !== false) {
73
+ $this->setHeader('Expect', '100-Continue');
74
+ }
75
+
76
+ // Set the Content-Length header if it can be determined
77
+ $size = $this->body->getContentLength();
78
+ if ($size !== null && $size !== false) {
79
+ $this->setHeader('Content-Length', $size);
80
+ if ($size > $this->expectCutoff) {
81
+ $this->setHeader('Expect', '100-Continue');
82
+ }
83
+ } elseif (!$this->hasHeader('Content-Length')) {
84
+ if ('1.1' == $this->protocolVersion) {
85
+ $this->setHeader('Transfer-Encoding', 'chunked');
86
+ } else {
87
+ throw new RequestException(
88
+ 'Cannot determine Content-Length and cannot use chunked Transfer-Encoding when using HTTP/1.0'
89
+ );
90
+ }
91
+ }
92
+
93
+ return $this;
94
+ }
95
+
96
+ public function getBody()
97
+ {
98
+ return $this->body;
99
+ }
100
+
101
+ /**
102
+ * Set the size that the entity body of the request must exceed before adding the Expect: 100-Continue header.
103
+ *
104
+ * @param int|bool $size Cutoff in bytes. Set to false to never send the expect header (even with non-seekable data)
105
+ *
106
+ * @return self
107
+ */
108
+ public function setExpectHeaderCutoff($size)
109
+ {
110
+ $this->expectCutoff = $size;
111
+ if ($size === false || !$this->body) {
112
+ $this->removeHeader('Expect');
113
+ } elseif ($this->body && $this->body->getSize() && $this->body->getSize() > $size) {
114
+ $this->setHeader('Expect', '100-Continue');
115
+ }
116
+
117
+ return $this;
118
+ }
119
+
120
+ public function configureRedirects($strict = false, $maxRedirects = 5)
121
+ {
122
+ $this->getParams()->set(RedirectPlugin::STRICT_REDIRECTS, $strict);
123
+ if ($maxRedirects == 0) {
124
+ $this->getParams()->set(RedirectPlugin::DISABLE, true);
125
+ } else {
126
+ $this->getParams()->set(RedirectPlugin::MAX_REDIRECTS, $maxRedirects);
127
+ }
128
+
129
+ return $this;
130
+ }
131
+
132
+ public function getPostField($field)
133
+ {
134
+ return $this->postFields->get($field);
135
+ }
136
+
137
+ public function getPostFields()
138
+ {
139
+ return $this->postFields;
140
+ }
141
+
142
+ public function setPostField($key, $value)
143
+ {
144
+ $this->postFields->set($key, $value);
145
+ $this->processPostFields();
146
+
147
+ return $this;
148
+ }
149
+
150
+ public function addPostFields($fields)
151
+ {
152
+ $this->postFields->merge($fields);
153
+ $this->processPostFields();
154
+
155
+ return $this;
156
+ }
157
+
158
+ public function removePostField($field)
159
+ {
160
+ $this->postFields->remove($field);
161
+ $this->processPostFields();
162
+
163
+ return $this;
164
+ }
165
+
166
+ public function getPostFiles()
167
+ {
168
+ return $this->postFiles;
169
+ }
170
+
171
+ public function getPostFile($fieldName)
172
+ {
173
+ return isset($this->postFiles[$fieldName]) ? $this->postFiles[$fieldName] : null;
174
+ }
175
+
176
+ public function removePostFile($fieldName)
177
+ {
178
+ unset($this->postFiles[$fieldName]);
179
+ $this->processPostFields();
180
+
181
+ return $this;
182
+ }
183
+
184
+ public function addPostFile($field, $filename = null, $contentType = null)
185
+ {
186
+ $data = null;
187
+
188
+ if ($field instanceof PostFileInterface) {
189
+ $data = $field;
190
+ } elseif (is_array($filename)) {
191
+ // Allow multiple values to be set in a single key
192
+ foreach ($filename as $file) {
193
+ $this->addPostFile($field, $file, $contentType);
194
+ }
195
+ return $this;
196
+ } elseif (!is_string($filename)) {
197
+ throw new RequestException('The path to a file must be a string');
198
+ } elseif (!empty($filename)) {
199
+ // Adding an empty file will cause cURL to error out
200
+ $data = new PostFile($field, $filename, $contentType);
201
+ }
202
+
203
+ if ($data) {
204
+ if (!isset($this->postFiles[$data->getFieldName()])) {
205
+ $this->postFiles[$data->getFieldName()] = array($data);
206
+ } else {
207
+ $this->postFiles[$data->getFieldName()][] = $data;
208
+ }
209
+ $this->processPostFields();
210
+ }
211
+
212
+ return $this;
213
+ }
214
+
215
+ public function addPostFiles(array $files)
216
+ {
217
+ foreach ($files as $key => $file) {
218
+ if ($file instanceof PostFileInterface) {
219
+ $this->addPostFile($file, null, null, false);
220
+ } elseif (is_string($file)) {
221
+ // Convert non-associative array keys into 'file'
222
+ if (is_numeric($key)) {
223
+ $key = 'file';
224
+ }
225
+ $this->addPostFile($key, $file, null, false);
226
+ } else {
227
+ throw new RequestException('File must be a string or instance of PostFileInterface');
228
+ }
229
+ }
230
+
231
+ return $this;
232
+ }
233
+
234
+ /**
235
+ * Determine what type of request should be sent based on post fields
236
+ */
237
+ protected function processPostFields()
238
+ {
239
+ if (!$this->postFiles) {
240
+ $this->removeHeader('Expect')->setHeader('Content-Type', self::URL_ENCODED);
241
+ } else {
242
+ $this->setHeader('Content-Type', self::MULTIPART);
243
+ if ($this->expectCutoff !== false) {
244
+ $this->setHeader('Expect', '100-Continue');
245
+ }
246
+ }
247
+ }
248
+ }
includes/php-opencloud/guzzle/http/Guzzle/Http/Message/EntityEnclosingRequestInterface.php ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Guzzle\Http\Message;
4
+
5
+ use Guzzle\Http\Exception\RequestException;
6
+ use Guzzle\Http\EntityBodyInterface;
7
+ use Guzzle\Http\QueryString;
8
+
9
+ /**
10
+ * HTTP request that sends an entity-body in the request message (POST, PUT)
11
+ */
12
+ interface EntityEnclosingRequestInterface extends RequestInterface
13
+ {
14
+ const URL_ENCODED = 'application/x-www-form-urlencoded; charset=utf-8';
15
+ const MULTIPART = 'multipart/form-data';
16
+
17
+ /**
18
+ * Set the body of the request
19
+ *
20
+ * @param string|resource|EntityBodyInterface $body Body to use in the entity body of the request
21
+ * @param string $contentType Content-Type to set. Leave null to use an existing
22
+ * Content-Type or to guess the Content-Type
23
+ * @return self
24
+ * @throws RequestException if the protocol is < 1.1 and Content-Length can not be determined
25
+ */
26
+ public function setBody($body, $contentType = null);
27
+
28
+ /**
29
+ * Get the body of the request if set
30
+ *
31
+ * @return EntityBodyInterface|null
32
+ */
33
+ public function getBody();
34
+
35
+ /**
36
+ * Get a POST field from the request
37
+ *
38
+ * @param string $field Field to retrieve
39
+ *
40
+ * @return mixed|null
41
+ */
42
+ public function getPostField($field);
43
+
44
+ /**
45
+ * Get the post fields that will be used in the request
46
+ *
47
+ * @return QueryString
48
+ */
49
+ public function getPostFields();
50
+
51
+ /**
52
+ * Set a POST field value
53
+ *
54
+ * @param string $key Key to set
55
+ * @param string $value Value to set
56
+ *
57
+ * @return self
58
+ */
59
+ public function setPostField($key, $value);
60
+
61
+ /**
62
+ * Add POST fields to use in the request
63
+ *
64
+ * @param QueryString|array $fields POST fields
65
+ *
66
+ * @return self
67
+ */
68
+ public function addPostFields($fields);
69
+
70
+ /**
71
+ * Remove a POST field or file by name
72
+ *
73
+ * @param string $field Name of the POST field or file to remove
74
+ *
75
+ * @return self
76
+ */
77
+ public function removePostField($field);
78
+
79
+ /**
80
+ * Returns an associative array of POST field names to PostFileInterface objects
81
+ *
82
+ * @return array
83
+ */
84
+ public function getPostFiles();
85
+
86
+ /**
87
+ * Get a POST file from the request
88
+ *
89
+ * @param string $fieldName POST fields to retrieve
90
+ *
91
+ * @return array|null Returns an array wrapping an array of PostFileInterface objects
92
+ */
93
+ public function getPostFile($fieldName);
94
+
95
+ /**
96
+ * Remove a POST file from the request
97
+ *
98
+ * @param string $fieldName POST file field name to remove
99
+ *
100
+ * @return self
101
+ */
102
+ public function removePostFile($fieldName);
103
+
104
+ /**
105
+ * Add a POST file to the upload
106
+ *
107
+ * @param string $field POST field to use (e.g. file). Used to reference content from the server.
108
+ * @param string $filename Full path to the file. Do not include the @ symbol.
109
+ * @param string $contentType Optional Content-Type to add to the Content-Disposition.
110
+ * Default behavior is to guess. Set to false to not specify.
111
+ * @return self
112
+ */
113
+ public function addPostFile($field, $filename = null, $contentType = null);
114
+
115
+ /**
116
+ * Add POST files to use in the upload
117
+ *
118
+ * @param array $files An array of POST fields => filenames where filename can be a string or PostFileInterface
119
+ *
120
+ * @return self
121
+ */
122
+ public function addPostFiles(array $files);
123
+
124
+ /**
125
+ * Configure how redirects are handled for the request
126
+ *
127
+ * @param bool $strict Set to true to follow strict RFC compliance when redirecting POST requests. Most
128
+ * browsers with follow a 301-302 redirect for a POST request with a GET request. This is
129
+ * the default behavior of Guzzle. Enable strict redirects to redirect these responses
130
+ * with a POST rather than a GET request.
131
+ * @param int $maxRedirects Specify the maximum number of allowed redirects. Set to 0 to disable redirects.
132
+ *
133
+ * @return self
134
+ */
135
+ public function configureRedirects($strict = false, $maxRedirects = 5);
136
+ }
includes/php-opencloud/guzzle/http/Guzzle/Http/Message/Header.php ADDED
@@ -0,0 +1,178 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Guzzle\Http\Message;
4
+
5
+ use Guzzle\Common\Version;
6
+ use Guzzle\Http\Message\Header\HeaderInterface;
7
+
8
+ /**
9
+ * Represents a header and all of the values stored by that header
10
+ */
11
+ class Header implements HeaderInterface
12
+ {
13
+ protected $values = array();
14
+ protected $header;
15
+ protected $glue;
16
+
17
+ /**
18
+ * @param string $header Name of the header
19
+ * @param array|string $values Values of the header as an array or a scalar
20
+ * @param string $glue Glue used to combine multiple values into a string
21
+ */
22
+ public function __construct($header, $values = array(), $glue = ',')
23
+ {
24
+ $this->header = trim($header);
25
+ $this->glue = $glue;
26
+
27
+ foreach ((array) $values as $value) {
28
+ foreach ((array) $value as $v) {
29
+ $this->values[] = $v;
30
+ }
31
+ }
32
+ }
33
+
34
+ public function __toString()
35
+ {
36
+ return implode($this->glue . ' ', $this->toArray());
37
+ }
38
+
39
+ public function add($value)
40
+ {
41
+ $this->values[] = $value;
42
+
43
+ return $this;
44
+ }
45
+
46
+ public function getName()
47
+ {
48
+ return $this->header;
49
+ }
50
+
51
+ public function setName($name)
52
+ {
53
+ $this->header = $name;
54
+
55
+ return $this;
56
+ }
57
+
58
+ public function setGlue($glue)
59
+ {
60
+ $this->glue = $glue;
61
+
62
+ return $this;
63
+ }
64
+
65
+ public function getGlue()
66
+ {
67
+ return $this->glue;
68
+ }
69
+
70
+ /**
71
+ * Normalize the header to be a single header with an array of values.
72
+ *
73
+ * If any values of the header contains the glue string value (e.g. ","), then the value will be exploded into
74
+ * multiple entries in the header.
75
+ *
76
+ * @return self
77
+ */
78
+ public function normalize()
79
+ {
80
+ $values = $this->toArray();
81
+
82
+ for ($i = 0, $total = count($values); $i < $total; $i++) {
83
+ if (strpos($values[$i], $this->glue) !== false) {
84
+ // Explode on glue when the glue is not inside of a comma
85
+ foreach (preg_split('/' . preg_quote($this->glue) . '(?=([^"]*"[^"]*")*[^"]*$)/', $values[$i]) as $v) {
86
+ $values[] = trim($v);
87
+ }
88
+ unset($values[$i]);
89
+ }
90
+ }
91
+
92
+ $this->values = array_values($values);
93
+
94
+ return $this;
95
+ }
96
+
97
+ public function hasValue($searchValue)
98
+ {
99
+ return in_array($searchValue, $this->toArray());
100
+ }
101
+
102
+ public function removeValue($searchValue)
103
+ {
104
+ $this->values = array_values(array_filter($this->values, function ($value) use ($searchValue) {
105
+ return $value != $searchValue;
106
+ }));
107
+
108
+ return $this;
109
+ }
110
+
111
+ public function toArray()
112
+ {
113
+ return $this->values;
114
+ }
115
+
116
+ public function count()
117
+ {
118
+ return count($this->toArray());
119
+ }
120
+
121
+ public function getIterator()
122
+ {
123
+ return new \ArrayIterator($this->toArray());
124
+ }
125
+
126
+ public function parseParams()
127
+ {
128
+ $params = $matches = array();
129
+ $callback = array($this, 'trimHeader');
130
+
131
+ // Normalize the header into a single array and iterate over all values
132
+ foreach ($this->normalize()->toArray() as $val) {
133
+ $part = array();
134
+ foreach (preg_split('/;(?=([^"]*"[^"]*")*[^"]*$)/', $val) as $kvp) {
135
+ preg_match_all('/<[^>]+>|[^=]+/', $kvp, $matches);
136
+ $pieces = array_map($callback, $matches[0]);
137
+ $part[$pieces[0]] = isset($pieces[1]) ? $pieces[1] : '';
138
+ }
139
+ $params[] = $part;
140
+ }
141
+
142
+ return $params;
143
+ }
144
+
145
+ /**
146
+ * @deprecated
147
+ * @codeCoverageIgnore
148
+ */
149
+ public function hasExactHeader($header)
150
+ {
151
+ Version::warn(__METHOD__ . ' is deprecated');
152
+ return $this->header == $header;
153
+ }
154
+
155
+ /**
156
+ * @deprecated
157
+ * @codeCoverageIgnore
158
+ */
159
+ public function raw()
160
+ {
161
+ Version::warn(__METHOD__ . ' is deprecated. Use toArray()');
162
+ return $this->toArray();
163
+ }
164
+
165
+ /**
166
+ * Trim a header by removing excess spaces and wrapping quotes
167
+ *
168
+ * @param $str
169
+ *
170
+ * @return string
171
+ */
172
+ protected function trimHeader($str)
173
+ {
174
+ static $trimmed = "\"' \n\t";
175
+
176
+ return trim($str, $trimmed);
177
+ }
178
+ }
includes/php-opencloud/guzzle/http/Guzzle/Http/Message/Header/CacheControl.php ADDED
@@ -0,0 +1,121 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Guzzle\Http\Message\Header;
4
+
5
+ use Guzzle\Http\Message\Header;
6
+
7
+ /**
8
+ * Provides helpful functionality for Cache-Control headers
9
+ */
10
+ class CacheControl extends Header
11
+ {
12
+ /** @var array */
13
+ protected $directives;
14
+
15
+ public function add($value)
16
+ {
17
+ parent::add($value);
18
+ $this->directives = null;
19
+ }
20
+
21
+ public function removeValue($searchValue)
22
+ {
23
+ parent::removeValue($searchValue);
24
+ $this->directives = null;
25
+ }
26
+
27
+ /**
28
+ * Check if a specific cache control directive exists
29
+ *
30
+ * @param string $param Directive to retrieve
31
+ *
32
+ * @return bool
33
+ */
34
+ public function hasDirective($param)
35
+ {
36
+ $directives = $this->getDirectives();
37
+
38
+ return isset($directives[$param]);
39
+ }
40
+
41
+ /**
42
+ * Get a specific cache control directive
43
+ *
44
+ * @param string $param Directive to retrieve
45
+ *
46
+ * @return string|bool|null
47
+ */
48
+ public function getDirective($param)
49
+ {
50
+ $directives = $this->getDirectives();
51
+
52
+ return isset($directives[$param]) ? $directives[$param] : null;
53
+ }
54
+
55
+ /**
56
+ * Add a cache control directive
57
+ *
58
+ * @param string $param Directive to add
59
+ * @param string $value Value to set
60
+ *
61
+ * @return self
62
+ */
63
+ public function addDirective($param, $value)
64
+ {
65
+ $directives = $this->getDirectives();
66
+ $directives[$param] = $value;
67
+ $this->updateFromDirectives($directives);
68
+
69
+ return $this;
70
+ }
71
+
72
+ /**
73
+ * Remove a cache control directive by name
74
+ *
75
+ * @param string $param Directive to remove
76
+ *
77
+ * @return self
78
+ */
79
+ public function removeDirective($param)
80
+ {
81
+ $directives = $this->getDirectives();
82
+ unset($directives[$param]);
83
+ $this->updateFromDirectives($directives);
84
+
85
+ return $this;
86
+ }
87
+
88
+ /**
89
+ * Get an associative array of cache control directives
90
+ *
91
+ * @return array
92
+ */
93
+ public function getDirectives()
94
+ {
95
+ if ($this->directives === null) {
96
+ $this->directives = array();
97
+ foreach ($this->parseParams() as $collection) {
98
+ foreach ($collection as $key => $value) {
99
+ $this->directives[$key] = $value === '' ? true : $value;
100
+ }
101
+ }
102
+ }
103
+
104
+ return $this->directives;
105
+ }
106
+
107
+ /**
108
+ * Updates the header value based on the parsed directives
109
+ *
110
+ * @param array $directives Array of cache control directives
111
+ */
112
+ protected function updateFromDirectives(array $directives)
113
+ {
114
+ $this->directives = $directives;
115
+ $this->values = array();
116
+
117
+ foreach ($directives as $key => $value) {
118
+ $this->values[] = $value === true ? $key : "{$key}={$value}";
119
+ }
120
+ }
121
+ }
includes/php-opencloud/guzzle/http/Guzzle/Http/Message/Header/HeaderCollection.php ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Guzzle\Http\Message\Header;
4
+
5
+ use Guzzle\Common\Collection;
6
+ use Guzzle\Common\ToArrayInterface;
7
+
8
+ /**
9
+ * Provides a case-insensitive collection of headers
10
+ */
11
+ class HeaderCollection implements \IteratorAggregate, \Countable, \ArrayAccess, ToArrayInterface
12
+ {
13
+ /** @var array */
14
+ protected $headers;
15
+
16
+ public function __construct($headers = array())
17
+ {
18
+ $this->headers = $headers;
19
+ }
20
+
21
+ public function __clone()
22
+ {
23
+ foreach ($this->headers as &$header) {
24
+ $header = clone $header;
25
+ }
26
+ }
27
+
28
+ /**
29
+ * Clears the header collection
30
+ */
31
+ public function clear()
32
+ {
33
+ $this->headers = array();
34
+ }
35
+
36
+ /**
37
+ * Set a header on the collection
38
+ *
39
+ * @param HeaderInterface $header Header to add
40
+ *
41
+ * @return self
42
+ */
43
+ public function add(HeaderInterface $header)
44
+ {
45
+ $this->headers[strtolower($header->getName())] = $header;
46
+
47
+ return $this;
48
+ }
49
+
50
+ /**
51
+ * Get an array of header objects
52
+ *
53
+ * @return array
54
+ */
55
+ public function getAll()
56
+ {
57
+ return $this->headers;
58
+ }
59
+
60
+ /**
61
+ * Alias of offsetGet
62
+ */
63
+ public function get($key)
64
+ {
65
+ return $this->offsetGet($key);
66
+ }
67
+
68
+ public function count()
69
+ {
70
+ return count($this->headers);
71
+ }
72
+
73
+ public function offsetExists($offset)
74
+ {
75
+ return isset($this->headers[strtolower($offset)]);
76
+ }
77
+
78
+ public function offsetGet($offset)
79
+ {
80
+ $l = strtolower($offset);
81
+
82
+ return isset($this->headers[$l]) ? $this->headers[$l] : null;
83
+ }
84
+
85
+ public function offsetSet($offset, $value)
86
+ {
87
+ $this->add($value);
88
+ }
89
+
90
+ public function offsetUnset($offset)
91
+ {
92
+ unset($this->headers[strtolower($offset)]);
93
+ }
94
+
95
+ public function getIterator()
96
+ {
97
+ return new \ArrayIterator($this->headers);
98
+ }
99
+
100
+ public function toArray()
101
+ {
102
+ $result = array();
103
+ foreach ($this->headers as $header) {
104
+ $result[$header->getName()] = $header->toArray();
105
+ }
106
+
107
+ return $result;
108
+ }
109
+ }
includes/php-opencloud/guzzle/http/Guzzle/Http/Message/Header/HeaderFactory.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Guzzle\Http\Message\Header;
4
+
5
+ use Guzzle\Http\Message\Header;
6
+
7
+ /**
8
+ * Default header factory implementation
9
+ */
10
+ class HeaderFactory implements HeaderFactoryInterface
11
+ {
12
+ /** @var array */
13
+ protected $mapping = array(
14
+ 'cache-control' => 'Guzzle\Http\Message\Header\CacheControl',
15
+ 'link' => 'Guzzle\Http\Message\Header\Link',
16
+ );
17
+
18
+ public function createHeader($header, $value = null)
19
+ {
20
+ $lowercase = strtolower($header);
21
+
22
+ return isset($this->mapping[$lowercase])
23
+ ? new $this->mapping[$lowercase]($header, $value)
24
+ : new Header($header, $value);
25
+ }
26
+ }
includes/php-opencloud/guzzle/http/Guzzle/Http/Message/Header/HeaderFactoryInterface.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Guzzle\Http\Message\Header;
4
+
5
+ /**
6
+ * Interface for creating headers
7
+ */
8
+ interface HeaderFactoryInterface
9
+ {
10
+ /**
11
+ * Create a header from a header name and a single value
12
+ *
13
+ * @param string $header Name of the header to create
14
+ * @param string $value Value to set on the header
15
+ *
16
+ * @return HeaderInterface
17
+ */
18
+ public function createHeader($header, $value = null);
19
+ }
includes/php-opencloud/guzzle/http/Guzzle/Http/Message/Header/HeaderInterface.php ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Guzzle\Http\Message\Header;
4
+
5
+ use Guzzle\Common\ToArrayInterface;
6
+
7
+ interface HeaderInterface extends ToArrayInterface, \Countable, \IteratorAggregate
8
+ {
9
+ /**
10
+ * Convert the header to a string
11
+ *
12
+ * @return string
13
+ */
14
+ public function __toString();
15
+
16
+ /**
17
+ * Add a value to the list of header values
18
+ *
19
+ * @param string $value Value to add to the header
20
+ *
21
+ * @return self
22
+ */
23
+ public function add($value);
24
+
25
+ /**
26
+ * Get the name of the header
27
+ *
28
+ * @return string
29
+ */
30
+ public function getName();
31
+
32
+ /**
33
+ * Change the name of the header
34
+ *
35
+ * @param string $name Name to change to
36
+ *
37
+ * @return self
38
+ */
39
+ public function setName($name);
40
+
41
+ /**
42
+ * Change the glue used to implode the values
43
+ *
44
+ * @param string $glue Glue used to implode multiple values
45
+ *
46
+ * @return self
47
+ */
48
+ public function setGlue($glue);
49
+
50
+ /**
51
+ * Get the glue used to implode multiple values into a string
52
+ *
53
+ * @return string
54
+ */
55
+ public function getGlue();
56
+
57
+ /**
58
+ * Check if the collection of headers has a particular value
59
+ *
60
+ * @param string $searchValue Value to search for
61
+ *
62
+ * @return bool
63
+ */
64
+ public function hasValue($searchValue);
65
+
66
+ /**
67
+ * Remove a specific value from the header
68
+ *
69
+ * @param string $searchValue Value to remove
70
+ *
71
+ * @return self
72
+ */
73
+ public function removeValue($searchValue);
74
+
75
+ /**
76
+ * Parse a header containing ";" separated data into an array of associative arrays representing the header
77
+ * key value pair data of the header. When a parameter does not contain a value, but just contains a key, this
78
+ * function will inject a key with a '' string value.
79
+ *
80
+ * @return array
81
+ */
82
+ public function parseParams();
83
+ }
includes/php-opencloud/guzzle/http/Guzzle/Http/Message/Header/Link.php ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Guzzle\Http\Message\Header;
4
+
5
+ use Guzzle\Http\Message\Header;
6
+
7
+ /**
8
+ * Provides helpful functionality for link headers
9
+ */
10
+ class Link extends Header
11
+ {
12
+ /**
13
+ * Add a link to the header
14
+ *
15
+ * @param string $url Link URL
16
+ * @param string $rel Link rel
17
+ * @param array $params Other link parameters
18
+ *
19
+ * @return self
20
+ */
21
+ public function addLink($url, $rel, array $params = array())
22
+ {
23
+ $values = array("<{$url}>", "rel=\"{$rel}\"");
24
+
25
+ foreach ($params as $k => $v) {
26
+ $values[] = "{$k}=\"{$v}\"";
27
+ }
28
+
29
+ return $this->add(implode('; ', $values));
30
+ }
31
+
32
+ /**
33
+ * Check if a specific link exists for a given rel attribute
34
+ *
35
+ * @param string $rel rel value
36
+ *
37
+ * @return bool
38
+ */
39
+ public function hasLink($rel)
40
+ {
41
+ return $this->getLink($rel) !== null;
42
+ }
43
+
44
+ /**
45
+ * Get a specific link for a given rel attribute
46
+ *
47
+ * @param string $rel Rel value
48
+ *
49
+ * @return array|null
50
+ */
51
+ public function getLink($rel)
52
+ {
53
+ foreach ($this->getLinks() as $link) {
54
+ if (isset($link['rel']) && $link['rel'] == $rel) {
55
+ return $link;
56
+ }
57
+ }
58
+
59
+ return null;
60
+ }
61
+
62
+ /**
63
+ * Get an associative array of links
64
+ *
65
+ * For example:
66
+ * Link: <http:/.../front.jpeg>; rel=front; type="image/jpeg", <http://.../back.jpeg>; rel=back; type="image/jpeg"
67
+ *
68
+ * <code>
69
+ * var_export($response->getLinks());
70
+ * array(
71
+ * array(
72
+ * 'url' => 'http:/.../front.jpeg',
73
+ * 'rel' => 'back',
74
+ * 'type' => 'image/jpeg',
75
+ * )
76
+ * )
77
+ * </code>
78
+ *
79
+ * @return array
80
+ */
81
+ public function getLinks()
82
+ {
83
+ $links = $this->parseParams();
84
+
85
+ foreach ($links as &$link) {
86
+ $key = key($link);
87
+ unset($link[$key]);
88
+ $link['url'] = trim($key, '<> ');
89
+ }
90
+
91
+ return $links;
92
+ }
93
+ }
includes/php-opencloud/guzzle/http/Guzzle/Http/Message/MessageInterface.php ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Guzzle\Http\Message;
4
+
5
+ /**
6
+ * Request and response message interface
7
+ */
8
+ interface MessageInterface
9
+ {
10
+ /**
11
+ * Get application and plugin specific parameters set on the message.
12
+ *
13
+ * @return \Guzzle\Common\Collection
14
+ */
15
+ public function getParams();
16
+
17
+ /**
18
+ * Add a header to an existing collection of headers.
19
+ *
20
+ * @param string $header Header name to add
21
+ * @param string $value Value of the header
22
+ *
23
+ * @return self
24
+ */
25
+ public function addHeader($header, $value);
26
+
27
+ /**
28
+ * Add and merge in an array of HTTP headers.
29
+ *
30
+ * @param array $headers Associative array of header data.
31
+ *
32
+ * @return self
33
+ */
34
+ public function addHeaders(array $headers);
35
+
36
+ /**
37
+ * Retrieve an HTTP header by name. Performs a case-insensitive search of all headers.
38
+ *
39
+ * @param string $header Header to retrieve.
40
+ *
41
+ * @return Header|null
42
+ */
43
+ public function getHeader($header);
44
+
45
+ /**
46
+ * Get all headers as a collection
47
+ *
48
+ * @return \Guzzle\Http\Message\Header\HeaderCollection
49
+ */
50
+ public function getHeaders();
51
+
52
+ /**
53
+ * Check if the specified header is present.
54
+ *
55
+ * @param string $header The header to check.
56
+ *
57
+ * @return bool
58
+ */
59
+ public function hasHeader($header);
60
+
61
+ /**
62
+ * Remove a specific HTTP header.
63
+ *
64
+ * @param string $header HTTP header to remove.
65
+ *
66
+ * @return self
67
+ */
68
+ public function removeHeader($header);
69
+
70
+ /**
71
+ * Set an HTTP header and overwrite any existing value for the header
72
+ *
73
+ * @param string $header Name of the header to set.
74
+ * @param mixed $value Value to set.
75
+ *
76
+ * @return self
77
+ */
78
+ public function setHeader($header, $value);
79
+
80
+ /**
81
+ * Overwrite all HTTP headers with the supplied array of headers
82
+ *
83
+ * @param array $headers Associative array of header data.
84
+ *
85
+ * @return self
86
+ */
87
+ public function setHeaders(array $headers);
88
+
89
+ /**
90
+ * Get an array of message header lines (e.g. ["Host: example.com", ...])
91
+ *
92
+ * @return array
93
+ */
94
+ public function getHeaderLines();
95
+
96
+ /**
97
+ * Get the raw message headers as a string
98
+ *
99
+ * @return string
100
+ */
101
+ public function getRawHeaders();
102
+ }
includes/php-opencloud/guzzle/http/Guzzle/Http/Message/PostFile.php ADDED
@@ -0,0 +1,109 @@