Instant Indexing for Google - Version 1.1.1

Version Description

Download this release

Release Info

Developer rankmath
Plugin Icon 128x128 Instant Indexing for Google
Version 1.1.1
Comparing to
See all releases

Version 1.1.1

Files changed (179) hide show
  1. assets/css/admin.css +1 -0
  2. assets/css/common.css +5 -0
  3. assets/css/dashboard.css +1 -0
  4. assets/css/settings.css +1 -0
  5. assets/fonts/Rank-Math.svg +80 -0
  6. assets/fonts/Rank-Math.ttf +0 -0
  7. assets/fonts/Rank-Math.woff +0 -0
  8. assets/img/icon.svg +107 -0
  9. assets/index.php +4 -0
  10. assets/js/console.js +108 -0
  11. assets/js/console.min.js +1 -0
  12. assets/js/dashboard.js +48 -0
  13. assets/js/dashboard.min.js +1 -0
  14. includes/class-instant-indexing-module.php +7 -0
  15. includes/class-instant-indexing.php +1047 -0
  16. includes/index.php +4 -0
  17. index.php +4 -0
  18. instant-indexing.php +44 -0
  19. languages/fast-indexing-api.pot +285 -0
  20. readme.txt +122 -0
  21. vendor/autoload.php +7 -0
  22. vendor/composer/ClassLoader.php +481 -0
  23. vendor/composer/InstalledVersions.php +337 -0
  24. vendor/composer/LICENSE +21 -0
  25. vendor/composer/autoload_classmap.php +32 -0
  26. vendor/composer/autoload_files.php +19 -0
  27. vendor/composer/autoload_namespaces.php +9 -0
  28. vendor/composer/autoload_psr4.php +25 -0
  29. vendor/composer/autoload_real.php +75 -0
  30. vendor/composer/autoload_static.php +161 -0
  31. vendor/composer/installed.json +1255 -0
  32. vendor/composer/installed.php +197 -0
  33. vendor/composer/platform_check.php +26 -0
  34. vendor/firebase/php-jwt/LICENSE +30 -0
  35. vendor/firebase/php-jwt/src/BeforeValidException.php +7 -0
  36. vendor/firebase/php-jwt/src/ExpiredException.php +7 -0
  37. vendor/firebase/php-jwt/src/JWK.php +172 -0
  38. vendor/firebase/php-jwt/src/JWT.php +544 -0
  39. vendor/firebase/php-jwt/src/SignatureInvalidException.php +7 -0
  40. vendor/google/apiclient-services/LICENSE +203 -0
  41. vendor/google/apiclient-services/autoload.php +36 -0
  42. vendor/google/apiclient-services/src/Indexing.php +86 -0
  43. vendor/google/apiclient-services/src/Indexing/PublishUrlNotificationResponse.php +42 -0
  44. vendor/google/apiclient-services/src/Indexing/Resource/UrlNotifications.php +67 -0
  45. vendor/google/apiclient-services/src/Indexing/UrlNotification.php +53 -0
  46. vendor/google/apiclient-services/src/Indexing/UrlNotificationMetadata.php +67 -0
  47. vendor/google/apiclient-services/synth.metadata +18 -0
  48. vendor/google/apiclient-services/synth.py +119 -0
  49. vendor/google/apiclient/LICENSE +203 -0
  50. vendor/google/apiclient/src/AccessToken/Revoke.php +81 -0
  51. vendor/google/apiclient/src/AccessToken/Verify.php +309 -0
  52. vendor/google/apiclient/src/AuthHandler/AuthHandlerFactory.php +52 -0
  53. vendor/google/apiclient/src/AuthHandler/Guzzle5AuthHandler.php +110 -0
  54. vendor/google/apiclient/src/AuthHandler/Guzzle6AuthHandler.php +117 -0
  55. vendor/google/apiclient/src/AuthHandler/Guzzle7AuthHandler.php +25 -0
  56. vendor/google/apiclient/src/Client.php +1274 -0
  57. vendor/google/apiclient/src/Collection.php +98 -0
  58. vendor/google/apiclient/src/Exception.php +24 -0
  59. vendor/google/apiclient/src/Http/Batch.php +258 -0
  60. vendor/google/apiclient/src/Http/MediaFileUpload.php +358 -0
  61. vendor/google/apiclient/src/Http/REST.php +192 -0
  62. vendor/google/apiclient/src/Model.php +324 -0
  63. vendor/google/apiclient/src/Service.php +71 -0
  64. vendor/google/apiclient/src/Service/Exception.php +71 -0
  65. vendor/google/apiclient/src/Service/Resource.php +308 -0
  66. vendor/google/apiclient/src/Task/Composer.php +115 -0
  67. vendor/google/apiclient/src/Task/Exception.php +24 -0
  68. vendor/google/apiclient/src/Task/Retryable.php +26 -0
  69. vendor/google/apiclient/src/Task/Runner.php +287 -0
  70. vendor/google/apiclient/src/Utils/UriTemplate.php +335 -0
  71. vendor/google/apiclient/src/aliases.php +65 -0
  72. vendor/google/auth/COPYING +202 -0
  73. vendor/google/auth/LICENSE +203 -0
  74. vendor/google/auth/autoload.php +34 -0
  75. vendor/google/auth/renovate.json +6 -0
  76. vendor/google/auth/src/AccessToken.php +479 -0
  77. vendor/google/auth/src/ApplicationDefaultCredentials.php +308 -0
  78. vendor/google/auth/src/Cache/InvalidArgumentException.php +24 -0
  79. vendor/google/auth/src/Cache/Item.php +190 -0
  80. vendor/google/auth/src/Cache/MemoryCacheItemPool.php +154 -0
  81. vendor/google/auth/src/Cache/SysVCacheItemPool.php +241 -0
  82. vendor/google/auth/src/CacheTrait.php +83 -0
  83. vendor/google/auth/src/Credentials/AppIdentityCredentials.php +230 -0
  84. vendor/google/auth/src/Credentials/GCECredentials.php +547 -0
  85. vendor/google/auth/src/Credentials/IAMCredentials.php +91 -0
  86. vendor/google/auth/src/Credentials/InsecureCredentials.php +70 -0
  87. vendor/google/auth/src/Credentials/ServiceAccountCredentials.php +333 -0
  88. vendor/google/auth/src/Credentials/ServiceAccountJwtAccessCredentials.php +205 -0
  89. vendor/google/auth/src/Credentials/UserRefreshCredentials.php +138 -0
  90. vendor/google/auth/src/CredentialsLoader.php +250 -0
  91. vendor/google/auth/src/FetchAuthTokenCache.php +278 -0
  92. vendor/google/auth/src/FetchAuthTokenInterface.php +54 -0
  93. vendor/google/auth/src/GCECache.php +92 -0
  94. vendor/google/auth/src/GetQuotaProjectInterface.php +33 -0
  95. vendor/google/auth/src/HttpHandler/Guzzle5HttpHandler.php +126 -0
  96. vendor/google/auth/src/HttpHandler/Guzzle6HttpHandler.php +62 -0
  97. vendor/google/auth/src/HttpHandler/Guzzle7HttpHandler.php +21 -0
  98. vendor/google/auth/src/HttpHandler/HttpClientCache.php +54 -0
  99. vendor/google/auth/src/HttpHandler/HttpHandlerFactory.php +53 -0
  100. vendor/google/auth/src/Iam.php +99 -0
  101. vendor/google/auth/src/Middleware/AuthTokenMiddleware.php +148 -0
  102. vendor/google/auth/src/Middleware/ScopedAccessTokenMiddleware.php +175 -0
  103. vendor/google/auth/src/Middleware/SimpleMiddleware.php +92 -0
  104. vendor/google/auth/src/OAuth2.php +1434 -0
  105. vendor/google/auth/src/ProjectIdProviderInterface.php +32 -0
  106. vendor/google/auth/src/ServiceAccountSignerTrait.php +57 -0
  107. vendor/google/auth/src/SignBlobInterface.php +44 -0
  108. vendor/google/auth/src/Subscriber/AuthTokenSubscriber.php +136 -0
  109. vendor/google/auth/src/Subscriber/ScopedAccessTokenSubscriber.php +180 -0
  110. vendor/google/auth/src/Subscriber/SimpleSubscriber.php +93 -0
  111. vendor/google/auth/src/UpdateMetadataInterface.php +41 -0
  112. vendor/guzzlehttp/guzzle/.php_cs +23 -0
  113. vendor/guzzlehttp/guzzle/Dockerfile +18 -0
  114. vendor/guzzlehttp/guzzle/LICENSE +19 -0
  115. vendor/guzzlehttp/guzzle/src/Client.php +501 -0
  116. vendor/guzzlehttp/guzzle/src/ClientInterface.php +87 -0
  117. vendor/guzzlehttp/guzzle/src/Cookie/CookieJar.php +316 -0
  118. vendor/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php +84 -0
  119. vendor/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php +91 -0
  120. vendor/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php +72 -0
  121. vendor/guzzlehttp/guzzle/src/Cookie/SetCookie.php +403 -0
  122. vendor/guzzlehttp/guzzle/src/Exception/BadResponseException.php +27 -0
  123. vendor/guzzlehttp/guzzle/src/Exception/ClientException.php +9 -0
  124. vendor/guzzlehttp/guzzle/src/Exception/ConnectException.php +37 -0
  125. vendor/guzzlehttp/guzzle/src/Exception/GuzzleException.php +23 -0
  126. vendor/guzzlehttp/guzzle/src/Exception/InvalidArgumentException.php +7 -0
  127. vendor/guzzlehttp/guzzle/src/Exception/RequestException.php +192 -0
  128. vendor/guzzlehttp/guzzle/src/Exception/SeekException.php +27 -0
  129. vendor/guzzlehttp/guzzle/src/Exception/ServerException.php +9 -0
  130. vendor/guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.php +6 -0
  131. vendor/guzzlehttp/guzzle/src/Exception/TransferException.php +6 -0
  132. vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php +585 -0
  133. vendor/guzzlehttp/guzzle/src/Handler/CurlFactoryInterface.php +27 -0
  134. vendor/guzzlehttp/guzzle/src/Handler/CurlHandler.php +45 -0
  135. vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php +219 -0
  136. vendor/guzzlehttp/guzzle/src/Handler/EasyHandle.php +92 -0
  137. vendor/guzzlehttp/guzzle/src/Handler/MockHandler.php +195 -0
  138. vendor/guzzlehttp/guzzle/src/Handler/Proxy.php +55 -0
  139. vendor/guzzlehttp/guzzle/src/Handler/StreamHandler.php +545 -0
  140. vendor/guzzlehttp/guzzle/src/HandlerStack.php +277 -0
  141. vendor/guzzlehttp/guzzle/src/MessageFormatter.php +185 -0
  142. vendor/guzzlehttp/guzzle/src/Middleware.php +254 -0
  143. vendor/guzzlehttp/guzzle/src/Pool.php +134 -0
  144. vendor/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php +111 -0
  145. vendor/guzzlehttp/guzzle/src/RedirectMiddleware.php +255 -0
  146. vendor/guzzlehttp/guzzle/src/RequestOptions.php +263 -0
  147. vendor/guzzlehttp/guzzle/src/RetryMiddleware.php +128 -0
  148. vendor/guzzlehttp/guzzle/src/TransferStats.php +126 -0
  149. vendor/guzzlehttp/guzzle/src/UriTemplate.php +237 -0
  150. vendor/guzzlehttp/guzzle/src/Utils.php +92 -0
  151. vendor/guzzlehttp/guzzle/src/functions.php +334 -0
  152. vendor/guzzlehttp/guzzle/src/functions_include.php +6 -0
  153. vendor/guzzlehttp/promises/LICENSE +19 -0
  154. vendor/guzzlehttp/promises/Makefile +13 -0
  155. vendor/guzzlehttp/promises/src/AggregateException.php +17 -0
  156. vendor/guzzlehttp/promises/src/CancellationException.php +10 -0
  157. vendor/guzzlehttp/promises/src/Coroutine.php +169 -0
  158. vendor/guzzlehttp/promises/src/Create.php +84 -0
  159. vendor/guzzlehttp/promises/src/Each.php +90 -0
  160. vendor/guzzlehttp/promises/src/EachPromise.php +254 -0
  161. vendor/guzzlehttp/promises/src/FulfilledPromise.php +84 -0
  162. vendor/guzzlehttp/promises/src/Is.php +46 -0
  163. vendor/guzzlehttp/promises/src/Promise.php +278 -0
  164. vendor/guzzlehttp/promises/src/PromiseInterface.php +97 -0
  165. vendor/guzzlehttp/promises/src/PromisorInterface.php +16 -0
  166. vendor/guzzlehttp/promises/src/RejectedPromise.php +91 -0
  167. vendor/guzzlehttp/promises/src/RejectionException.php +48 -0
  168. vendor/guzzlehttp/promises/src/TaskQueue.php +67 -0
  169. vendor/guzzlehttp/promises/src/TaskQueueInterface.php +24 -0
  170. vendor/guzzlehttp/promises/src/Utils.php +274 -0
  171. vendor/guzzlehttp/promises/src/functions.php +363 -0
  172. vendor/guzzlehttp/promises/src/functions_include.php +6 -0
  173. vendor/guzzlehttp/psr7/.php_cs.dist +56 -0
  174. vendor/guzzlehttp/psr7/LICENSE +19 -0
  175. vendor/guzzlehttp/psr7/src/AppendStream.php +246 -0
  176. vendor/guzzlehttp/psr7/src/BufferStream.php +142 -0
  177. vendor/guzzlehttp/psr7/src/CachingStream.php +141 -0
  178. vendor/guzzlehttp/psr7/src/DroppingStream.php +45 -0
  179. vendor/guzzlehttp/psr7/src/FnStream.php +32 -0
assets/css/admin.css ADDED
@@ -0,0 +1 @@
 
1
+ .rank-math-wrap{max-width:1080px}.instant-indexing-nav-tabs a .dashicons{line-height:1.2}#giapi-response-wrapper{display:none}#giapi-response-userfriendly{display:none}#giapi-response-userfriendly.ready{display:block}#instant-indexing textarea{width:600px;max-width:49%}.giapi-limits{width:420px;max-width:49%;float:right;padding:14px 20px 16px;border:1px solid #ccc;background:#fafafa}.giapi-limits p{margin:0}.response-box{background:#fff;padding:18px 20px;margin:20px 0;text-align:center}.response-box .response-status{font-size:24px;line-height:1.5;margin:0 0 10px}.response-box .response-message{margin:0}.response-box .response-status:before{font-family:dashicons;font-size:28px;position:relative;top:5px;margin-right:2px}#giapi-submit{margin-top:10px}.success .response-status:before{content:"\f147"}.fail .response-status:before{content:"\f158"}.success .response-status{color:#156115}.fail .response-status{color:#bb2b2b}@media screen and (max-width: 1110px){.giapi-limits{width:100%;max-width:100%;float:none;-webkit-box-sizing:border-box;box-sizing:border-box}#instant-indexing #giapi-url{width:100%;max-width:100%}}.form-table .description{font-weight:normal}.setup-guide-link-wrapper{display:inline-block;border:1px solid #ccc;background:#fafafa;padding:10px 10px 10px 6px;margin-top:8px}.setup-guide-link-wrapper a{text-decoration:none}.notice:not(.rank-math-notice){display:none}
assets/css/common.css ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ /*!
2
+ * Plugin: Rank Math
3
+ * URL: https://rankmath.com/wordpress/plugin/seo-suite/
4
+ * Name: common.css
5
+ */@font-face{font-family:'Rank-Math';src:url("../fonts/Rank-Math.ttf?v1.0.56") format("truetype"),url("../fonts/Rank-Math.woff?v1.0.56") format("woff"),url("../fonts/Rank-Math.svg?v1.0.56#Rank-Math") format("svg");font-weight:normal;font-style:normal;font-display:block}[class^="rm-icon-"],[class*=" rm-icon-"]{font-family:'Rank-Math' !important;speak:none;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.rm-icon-copy:before{content:"\e902"}.rm-icon-google:before{content:"\e901"}.rm-icon-rank-math:before{content:"\e900"}.rm-icon-mobile:before{content:"\ea2e"}.rm-icon-role-manager:before{content:"\ea3a"}.rm-icon-calendar:before{content:"\ea43"}.rm-icon-sitemap:before{content:"\ea4f"}.rm-icon-import:before{content:"\ea5a"}.rm-icon-export:before{content:"\ea5d"}.rm-icon-settings:before{content:"\ea60"}.rm-icon-desktop:before{content:"\ea67"}.rm-icon-htaccess:before{content:"\ea6f"}.rm-icon-robots:before{content:"\ea70"}.rm-icon-category:before{content:"\ea76"}.rm-icon-link:before{content:"\ea83"}.rm-icon-local-seo:before{content:"\ea87"}.rm-icon-misc:before{content:"\ea8f"}.rm-icon-software:before{content:"\ea9a"}.rm-icon-image:before{content:"\eaa0"}.rm-icon-analyzer:before{content:"\eaa9"}.rm-icon-search:before{content:"\eaab"}.rm-icon-star-filled:before{content:"\eab3"}.rm-icon-star:before{content:"\eab5"}.rm-icon-trash:before{content:"\eaba"}.rm-icon-users:before{content:"\eac4"}.rm-icon-images:before{content:"\eb6a"}.rm-icon-redirection:before{content:"\eb70"}.rm-icon-video:before{content:"\eb73"}.rm-icon-analytics:before{content:"\eb87"}.rm-icon-schema:before{content:"\eb97"}.rm-icon-adsense:before{content:"\eb99"}.rm-icon-tick:before{content:"\eb9d"}.rm-icon-circle-plus:before{content:"\eb9f"}.rm-icon-eye:before{content:"\eba4"}.rm-icon-heart-filled:before{content:"\ebac"}.rm-icon-info:before{content:"\ebb4"}.rm-icon-howto:before{content:"\ebbc"}.rm-icon-faq:before{content:"\ebbd"}.rm-icon-music:before{content:"\ebc8"}.rm-icon-plus:before{content:"\ebce"}.rm-icon-help:before{content:"\ebd2"}.rm-icon-404:before{content:"\ebe8"}.rm-icon-cross:before{content:"\ebea"}.rm-icon-recipe:before{content:"\ec3b"}.rm-icon-restaurant:before{content:"\ec56"}.rm-icon-post-format:before{content:"\ec64"}.rm-icon-service:before{content:"\ec66"}.rm-icon-course:before{content:"\ec70"}.rm-icon-book:before{content:"\ec73"}.rm-icon-social:before{content:"\ec76"}.rm-icon-edit:before{content:"\ec78"}.rm-icon-page:before{content:"\ec86"}.rm-icon-arrow-up:before{content:"\ecbe"}.rm-icon-caret-down:before{content:"\ecbf"}.rm-icon-arrow-down:before{content:"\ecc6"}.rm-icon-caret-up:before{content:"\ecc7"}.rm-icon-direction:before{content:"\ecc9"}.rm-icon-stories:before{content:"\ece7"}.rm-icon-acf:before{content:"\eceb"}.rm-icon-home:before{content:"\ed0d"}.rm-icon-toolbox:before{content:"\ed1f"}.rm-icon-comments:before{content:"\ed35"}.rm-icon-job:before{content:"\ed3a"}.rm-icon-post:before{content:"\ed4d"}.rm-icon-support:before{content:"\ed64"}.rm-icon-search-console:before{content:"\ed71"}.rm-icon-cart:before{content:"\ed73"}.rm-icon-attachment:before{content:"\ed83"}.rm-icon-tag:before{content:"\ed91"}.rm-icon-instant-indexing:before{content:"\ebe1"}.rank-math-header{display:-webkit-box;display:-ms-flexbox;display:flex;margin-bottom:20px;margin-left:-20px;padding:13px 15px;border-bottom:1px solid #b5bfc9;background:#fff;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row wrap;flex-flow:row wrap}.rank-math-header .rank-math-logo{position:relative;margin-right:15px;padding-right:15px}.rank-math-header .rank-math-logo:after{position:absolute;top:0;right:0;width:1px;height:66px;margin:-12px 0;content:'';background:#b5bfc9}.rank-math-header .rank-math-logo a{text-decoration:none}.rank-math-header .rank-math-logo a:focus{-webkit-box-shadow:none;box-shadow:none}.rank-math-header .rank-math-logo i{font-size:28px;line-height:48px;display:block;width:40px;height:40px;text-align:center;color:#fff;border-radius:5px;background:linear-gradient(-135deg, #ff4492, #434e8f);text-shadow:0 1px 3px rgba(0,0,0,0.1);position:relative}@supports (-moz-appearance: none){.rank-math-header .rank-math-logo i{line-height:40px}}.rank-math-header .rank-math-logo-text{font-size:22px;font-weight:500;margin:11px auto 0 0}.rank-math-header .rank-math-logo-text span{vertical-align:4px}.rank-math-header a.rank-math-help{font-size:18px;line-height:36px;display:-webkit-box;display:-ms-flexbox;display:flex;margin-left:5px;padding:0 10px;color:#858b90;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-flow:column wrap;flex-flow:column wrap;-ms-flex-pack:distribute;justify-content:space-around}.rank-math-header a.rank-math-help:focus,.rank-math-header a.rank-math-help:hover{color:#069de3;border-color:#069de3}.rank-math-header a.rank-math-help:focus{-webkit-box-shadow:0 0 0 1px #069de3;box-shadow:0 0 0 1px #069de3}.rank-math-header a.rank-math-help i{height:24px}.rank-math-header a.rank-math-help i:before{vertical-align:-3px}@supports (-moz-appearance: none){.rank-math-header a.rank-math-help i:before{vertical-align:initial}}.rank-math-search-options .search-field input{display:block;margin:0 5px 0 0;padding:10px 15px;border-color:#b5bfc9;border-radius:3px;height:40px;width:150px}.rank-math-search-options{position:relative}.rank-math-search-options .search-field{position:relative;float:left}.rank-math-search-options .search-field input{width:275px;padding-left:42px;color:#858b90}.rank-math-search-options .search-field input:hover{border-color:#069de3}.rank-math-search-options .search-field input:focus{border-color:#069de3;-webkit-box-shadow:0 0 0 1px #069de3;box-shadow:0 0 0 1px #069de3}.rank-math-search-options .search-field i{color:#858b90;font-weight:bold;-webkit-transform:translateY(-50%);transform:translateY(-50%);position:absolute;top:50%;left:13px}.rank-math-search-options .search-field em{right:8px;left:auto;display:none}.searching .rank-math-search-options .search-field em{display:block}.rank-math-search-options select{line-height:38px;padding:0 15px;color:#858b90;border:1px solid #b5bfc9;background:#f6f8f7}.rank-math-search-options select:hover{color:#069de3;border-color:#069de3}.rank-math-search-options select:focus{border-color:#069de3;-webkit-box-shadow:0 0 0 1px #069de3;box-shadow:0 0 0 1px #069de3}.rank-math-wrap-settings.search-no-results .rank-math-setting-search-empty{font-size:2em;font-weight:400;display:block;padding:25px 0;text-align:center}.rank-math-search-dropdown{z-index:10;display:none;overflow:auto;max-width:450px;border:1px solid #b5bfc9;border-radius:3px;background:#fff;height:260px;width:100%;position:absolute;top:48px;right:0}.rank-math-search-dropdown .cmb-row{padding:10px;cursor:pointer;border-bottom:1px solid #b5bfc9}.rank-math-search-dropdown .cmb-row .cmb2-metabox-description{font-size:12px}.rank-math-search-dropdown .cmb-row:hover{background:#f6f6f6}.rank-math-search-dropdown.empty:before{font-size:1.2em;font-style:italic;display:block;padding:20px;content:'Nothing found.'}.rank-math-page{overflow-x:hidden;background:#e1e1e1}.rank-math-page div.notice:not(.rank-math-notice):not(.settings-error):not(.cmb-type-notice),.rank-math-page .update-nag{display:none}.rank-math-page .rank-math-breadcrumbs{font-size:13px;font-weight:500;line-height:1;text-transform:uppercase;color:#7f868d}.rank-math-page .rank-math-breadcrumbs-wrap{display:-webkit-box;display:-ms-flexbox;display:flex;width:1020px;max-width:100%;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row wrap;flex-flow:row wrap;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.rank-math-page .rank-math-breadcrumbs .active{color:#242628}.rank-math-page .rank-math-breadcrumbs .divider{margin:0 5px}.rank-math-page .rank-math-mode-selector{font-size:14px;margin:5px 10px 0 0}.rank-math-page .rank-math-mode-selector a{display:inline-block;padding:5px 0 1px;text-decoration:none;color:#7f868d}.rank-math-page .rank-math-mode-selector a:hover,.rank-math-page .rank-math-mode-selector a.active{color:#242628;border-bottom:1px solid}.rank-math-page .rank-math-mode-selector a:first-child{margin-right:7px}.rank-math-page div.rank-math-tab-nav{position:relative;z-index:1;display:-webkit-box;display:-ms-flexbox;display:flex;overflow-x:auto;margin-bottom:-1px;white-space:nowrap;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row;flex-flow:row}@media screen and (min-width: 64rem){.rank-math-page div.rank-math-tab-nav{overflow-x:visible}}.rank-math-page .rank-math-tools-wrap div.rank-math-tab-nav{width:1020px}.rank-math-page .rank-math-tab:not(.rank-math-options-panel-content){font-size:15px;font-weight:500;line-height:39px;position:relative;margin:0;padding:0 15px;text-decoration:none;color:#5b646c;border:1px solid #b5bfc9;border-right:0;border-bottom:0;border-bottom:1px solid #b5bfc9;background:#f0f2f4}.rank-math-page .rank-math-tab:not(.rank-math-options-panel-content):hover,.rank-math-page .rank-math-tab:not(.rank-math-options-panel-content):focus,.rank-math-page .rank-math-tab:not(.rank-math-options-panel-content).is-active{color:#1a1e22;outline:none;background:#f8f9fa;-webkit-box-shadow:none;box-shadow:none}.rank-math-page .rank-math-tab:not(.rank-math-options-panel-content).is-active{border-bottom:1px solid #f8f9fa}.rank-math-page .rank-math-tab:not(.rank-math-options-panel-content):first-child{border-radius:4px 0 0 0}.rank-math-page .rank-math-tab:not(.rank-math-options-panel-content):last-of-type{border-right:1px solid #b5bfc9;border-radius:0 4px 0 0}.rank-math-page #wpwrap{overflow:hidden;background:#f0f2f4}.rank-math-page .dashboard-wrapper{position:relative;margin-bottom:.5rem;padding:30px 0;border-radius:0 6px 6px 6px;background:#f8f9fa}.rank-math-page .dashboard-wrapper:before{position:absolute;top:0;left:-180px;overflow:hidden;width:200vw;height:100%;padding-bottom:50px;content:'';border-top:1px solid #b5bfc9;border-bottom:1px solid #b5bfc9;background:#f8f9fa}.rank-math-page .dashboard-wrapper>div{position:relative}.rank-math-page .dashboard-wrapper>div>h2{margin-top:0;color:#242628}.rank-math-page .dashboard-wrapper>div>.description{font-size:1rem;margin-bottom:1.5rem}.rank-math-page.folded .dashboard-wrapper:before{left:-56px}.rank-math-page #wpfooter{padding:15px 20px;border-top:1px solid #b5bfc9;background:#fff}.rank-math-wrap{font-size:15px;position:relative;-webkit-box-sizing:border-box;box-sizing:border-box;margin:20px 10px 0 0;color:#242628}@media screen and (min-width: 48rem){.rank-math-wrap{margin:20px 40px 0 0}}.rank-math-wrap .container{width:1020px;max-width:100%}.rank-math-wrap p,.rank-math-wrap .description{font-size:14px;font-style:normal;line-height:1.5}.rank-math-wrap h1,.rank-math-wrap h2,.rank-math-wrap h3,.rank-math-wrap h4,.rank-math-wrap h5,.rank-math-wrap h6{color:#242628}.rank-math-wrap .page-title,.rank-math-wrap h1{font-size:2.8em;font-weight:400;line-height:1.2em;margin:.2em 200px 0 0;padding:0;color:#242628}.rank-math-wrap>h2{font-size:2.7em;font-weight:300;line-height:1.3;margin:40px 0 .6em;text-align:center}.rank-math-wrap .page-title{font-size:2em;font-weight:400;line-height:1;margin:35px 0 20px}.rank-math-wrap h3{font-size:1.375rem;line-height:1.5;margin:1.25em 0 .6em}.rank-math-wrap h3.health-check-accordion-heading{font-size:inherit;line-height:inherit;margin:0;background:#f8f9fa}.rank-math-wrap h3.health-check-accordion-heading>button{background:transparent}.rank-math-wrap ol li p{font-size:14px;font-weight:400}.rank-math-wrap .rank-math-text{font-size:19px;font-weight:400;line-height:1.6em;min-height:40px;margin:1.4em 200px 1em 0;color:#555d66}@media only screen and (max-width: 500px){.rank-math-wrap .rank-math-text,.rank-math-wrap h1{margin-right:0}.rank-math-wrap .rank-math-text{margin-bottom:.25em}}.two-col{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;-ms-flex-wrap:wrap;flex-wrap:wrap;justify-content:space-between}.two-col .col{max-width:100%;-webkit-box-flex:0;-ms-flex:0 0 100%;flex:0 0 100%}#error-log-wrapper .rank-math-code-box{color:#fff}@media screen and (min-width: 48rem){.two-col .col{-webkit-box-sizing:border-box;box-sizing:border-box;width:495px;max-width:48.53%}}.rank-math-box{position:relative;margin-bottom:1rem;background:#fff;border:1px solid #b5bfc9;border-radius:6px;padding:1.875rem}.rank-math-box.no-borders{border:0;padding:0;background:transparent}.rank-math-box.no-padding{padding:0}.rank-math-box.no-padding footer{margin:1.875rem 0 0}.rank-math-box.switch-at-top .rank-math-switch{position:absolute;top:-12px;right:0}.rank-math-box.switch-at-top header{padding:0 20px}.rank-math-box.switch-at-top header h3{padding-top:14px}.rank-math-box header{line-height:55px}.rank-math-box header h3{color:#242628;position:relative;z-index:1;margin:0 0 20px}.rank-math-box header p{color:#7f868d;margin-top:0;padding:0 10px}.rank-math-box-content form .frm-submit p{display:inline-block;margin-left:10px}.rank-math-box footer{background:#f8f9fa;padding:1.25rem 1.875rem;margin:1.875rem -1.875rem -1.875rem;border:0;border-top:1px solid #b5bfc9;border-radius:0 0 6px 6px}.rank-math-page .button,.rank-math-page .button-secondary,.rank-math-page .is-secondary{font-size:14px;line-height:38px;height:auto;min-height:30px;padding:0 20px;-webkit-transition:.25s all linear;transition:.25s all linear;color:#6b7278;border:1px solid #7f868d;border-radius:3px;background:#f8f9fa;-webkit-box-shadow:none;box-shadow:none}.rank-math-page .button.active,.rank-math-page .button-secondary.active,.rank-math-page .is-secondary.active{color:#61676d;border-color:#7f868d;background:#f8f9fa;-webkit-box-shadow:inset 0 2px 5px -3px #7f8292;box-shadow:inset 0 2px 5px -3px #7f8292}.rank-math-page .button:focus,.rank-math-page .button:hover,.rank-math-page .button-secondary:focus,.rank-math-page .button-secondary:hover,.rank-math-page .is-secondary:focus,.rank-math-page .is-secondary:hover{color:#61676d;border-color:#069de3;background:#f8f9fa}.rank-math-page .button:focus,.rank-math-page .button-secondary:focus,.rank-math-page .is-secondary:focus{border-color:#069de3;-webkit-box-shadow:0 0 0 1px #069de3;box-shadow:0 0 0 1px #069de3}.rank-math-page .button .dashicons,.rank-math-page .button-secondary .dashicons,.rank-math-page .is-secondary .dashicons{margin:0 3px 0 0}.rank-math-page .button.disabled,.rank-math-page .button-secondary.disabled,.rank-math-page .is-secondary.disabled{pointer-events:none}.rank-math-page .button-primary:not(.default),.rank-math-page .is-primary{color:#fff;border-color:#069de3;background:#069de3;text-shadow:none}.rank-math-page .button-primary:not(.default):focus,.rank-math-page .button-primary:not(.default):hover,.rank-math-page .is-primary:focus,.rank-math-page .is-primary:hover{color:#fff;border-color:#08a7f1;background:#08a7f1}.rank-math-page .button-primary:not(.default):focus,.rank-math-page .is-primary:focus{-webkit-box-shadow:0 0 0 1px #fff,0 0 0 3px #069de3;box-shadow:0 0 0 1px #fff,0 0 0 3px #069de3}.rank-math-page .button-primary:not(.default)[disabled],.rank-math-page .is-primary[disabled]{border-color:#069de3 !important;background:#069de3 !important}.rank-math-page .is-blue:not(.default){border-color:#4e8cde;background:#4e8cde}.rank-math-page .is-blue:not(.default):hover,.rank-math-page .is-blue:not(.default):focus{border-color:#397eda;background:#397eda}.rank-math-page .is-blue:not(.default):focus{-webkit-box-shadow:0 0 0 1px #fff,0 0 0 3px #397eda;box-shadow:0 0 0 1px #fff,0 0 0 3px #397eda}.rank-math-page .is-green:not(.default){border-color:#10AC84;background:#10AC84}.rank-math-page .is-green:not(.default):hover,.rank-math-page .is-green:not(.default):focus{border-color:#0f9e79;background:#0f9e79}.rank-math-page .is-green:not(.default):focus{-webkit-box-shadow:0 0 0 1px #fff,0 0 0 3px #0f9e79;box-shadow:0 0 0 1px #fff,0 0 0 3px #0f9e79}.rank-math-page .button-link-delete{color:#ee6a5e;border-color:#ee6a5e}.rank-math-page .button-link,.rank-math-page .is-link{border:0;background:transparent;-webkit-box-shadow:none;box-shadow:none}.rank-math-page .button-small,.rank-math-page .is-small{font-size:12px;line-height:24px;min-height:24px;padding:0 8px}.rank-math-page .button-xlarge,.rank-math-page .is-large{font-size:16px;line-height:44px;height:46px}.rank-math-page .button-animated{font-size:24px;line-height:82px;height:auto;min-height:30px;padding:0 40px;-webkit-transform:perspective(1px) translateZ(0);transform:perspective(1px) translateZ(0);text-align:center;border-radius:82px}.rank-math-page .button-animated i{line-height:85px}.rank-math-page .button-animated:before{content:'';-webkit-animation:hvr-ripple-out 1s linear infinite;animation:hvr-ripple-out 1s linear infinite;border:#bcdbea solid 6px;border-radius:55px;position:absolute;top:-6px;right:-6px;bottom:-6px;left:-6px}@-webkit-keyframes hvr-ripple-out{100%{opacity:0;top:-20px;right:-20px;bottom:-20px;left:-20px}}@-webkit-keyframes hvr-ripple-out{100%{opacity:0;top:-20px;right:-20px;bottom:-20px;left:-20px}}@keyframes hvr-ripple-out{100%{opacity:0;top:-20px;right:-20px;bottom:-20px;left:-20px}}.consent-box{background:#f6f7f9;padding:20px;border-radius:6px;margin-top:1rem}.consent-box input[type=checkbox]{float:left;margin-top:5px;margin-right:10px}.consent-box p{font-size:14px !important;line-height:1.7;margin:0;opacity:0.8;overflow:hidden}.rank-math-pro-badge{vertical-align:middle;color:#fff;background:#4CAF50;background:linear-gradient(100deg, #4CAF50 0%, #8baf4c 100%);font-size:11px;font-weight:normal;text-transform:uppercase;padding:4px 10px;border-radius:3px;margin-left:5px}.rank-math-pro-badge.business{background:#253142;color:#F7D070}.rank-math-pro-badge a{color:inherit;text-decoration:none}.rank-math-tabs>.cmb-row.tab-header{background:#f8f9fa;padding:30px;text-align:center;border:1px solid #b5bfc9;border-bottom:0;border-radius:6px 6px 0 0;display:block !important}.rank-math-tabs>.cmb-row.tab-header .rank-math-notice{margin:1rem 0 0}.rank-math-tabs-navigation:not(.rank-math-custom){float:left;width:200px;border-top:1px solid #b5bfc9}.rank-math-tabs-navigation:not(.rank-math-custom) a{font-size:15px;position:relative;display:block;-webkit-box-sizing:border-box;box-sizing:border-box;padding:11px 15px;text-decoration:none;color:#5b6065;outline:none;background:#f8f9fa;-webkit-box-shadow:none;box-shadow:none;-webkit-transition:0.2s all linear;transition:0.2s all linear}.rank-math-tabs-navigation:not(.rank-math-custom) a .rm-icon,.rank-math-tabs-navigation:not(.rank-math-custom) a .dashicons{font-size:14px;min-width:20px;margin-right:10px;vertical-align:-1px;text-align:center}.rank-math-tabs-navigation:not(.rank-math-custom) a.active,.rank-math-tabs-navigation:not(.rank-math-custom) a:focus,.rank-math-tabs-navigation:not(.rank-math-custom) a:hover{color:#069de3;background:#fff;border-left:3px solid}.rank-math-tabs-navigation:not(.rank-math-custom) a.active:after{position:absolute;top:0;right:-1px;width:1px;height:100%;content:'';background:#fff}.rank-math-tabs-navigation:not(.rank-math-custom) a:first-child,.rank-math-tabs-navigation:not(.rank-math-custom) a+a{border:solid #b5bfc9;border-width:0 0 1px 1px}.rank-math-tabs-navigation:not(.rank-math-custom) a:last-child{border-radius:0 0 0 6px}.rank-math-tabs-navigation:not(.rank-math-custom) .separator{font-weight:600;color:#5b6065;background:#e9ecef;display:block;padding:12px 15px 10px;border-left:1px solid #b5bfc9;border-bottom:1px solid #b5bfc9}.rank-math-tabs-navigation:not(.rank-math-custom) .separator+a{border-left:1px solid #b5bfc9;border-bottom:1px solid #b5bfc9}.rank-math-tabs-content:not(.rank-math-custom){overflow:hidden;-webkit-box-sizing:border-box;box-sizing:border-box;min-height:400px;margin-bottom:20px;padding:30px;border:1px solid #b5bfc9;border-radius:0;background:#fff}.rank-math-tabs-content:not(.rank-math-custom) .tab-header{display:none !important}.rank-math-tab h3:first-of-type{margin-top:0}.rank-math-tab .cmb-type-title:first-of-type{padding-top:0;text-align:center;border-top:0}.rank-math-tab .cmb2-checkbox-list li{display:inline-block;width:49%}.rank-math-tab .cmb2-checkbox-list li{display:inline-block;width:49%}.rank-math-tab .cmb-advanced-robots-list li{display:inline-block;-webkit-box-sizing:border-box;box-sizing:border-box;width:33%;padding:0 1% 0 0}.rank-math-tab .cmb-advanced-robots-list li:last-child{padding-right:0}.rank-math-tab .cmb-advanced-robots-list li label{display:inline-block;margin-bottom:5px}.rank-math-tab .cmb-advanced-robots-list li label input[type='checkbox']{margin-right:2px}.rank-math-tab .cmb-advanced-robots-list li .rank-math-tooltip{margin-left:3px}.form-footer:not(.rank-math-custom){border:1px solid #b5bfc9;border-top:0;border-radius:0 0 6px 6px}.rank-math-tooltip{position:relative;cursor:pointer;color:#b5bfc9;display:inline-block;line-height:20px;height:20px}.rank-math-tooltip em{line-height:20px}.rank-math-tooltip>span{font-size:11px;font-weight:400;line-height:1.5;white-space:normal;width:200px;padding:8px 10px;-webkit-transition:all .3s ease-in-out;transition:all .3s ease-in-out;-webkit-transform:translate3d(-50%, 0, 0);transform:translate3d(-50%, 0, 0);text-align:center;pointer-events:none;opacity:0;color:#fff;border-radius:3px;background:#555d66;position:absolute;bottom:100%;left:50%}.rank-math-tooltip>span:after{content:'';-webkit-transform:translate3d(-50%, 0, 0);transform:translate3d(-50%, 0, 0);position:absolute;top:100%;left:50%;border-style:solid;height:0;width:0;border-color:#555d66 transparent transparent;border-width:8px 7px 0}.rank-math-tooltip.bottom span{top:130%;bottom:auto;display:table}.rank-math-tooltip.bottom span:after{position:absolute;top:auto;bottom:100%;left:50%;-webkit-transform:rotate(180deg) translate3d(50%, 0, 0);transform:rotate(180deg) translate3d(50%, 0, 0)}.rank-math-tooltip:hover{color:#069de3}.rank-math-tooltip:hover span{bottom:130%;opacity:1;z-index:1}.import_export .no-borders{margin-top:2rem}.rank-math-import-export>div{margin-bottom:3rem}.rank-math-import-export>div>h2{font-size:1.375rem;margin-top:0;margin-bottom:0.825rem}.rank-math-import-export>div>p.description{font-size:1rem;margin-bottom:1.5rem}.rank-math-import-export .rank-math-box-content{padding:1.875rem}.rank-math-import-export .rank-math-box-content p:first-child{margin-top:0}.rank-math-import-export .rank-math-box-content input[type=checkbox]{margin-top:-1px}.rank-math-import-export .rank-math-box-content footer{margin:1.875rem -1.875rem -1.875rem}.rank-math-import-export .rank-math-export-form .form-table{margin-top:0}.rank-math-import-export .rank-math-export-form .form-table ul{margin:0}.rank-math-import-export .rank-math-export-form th,.rank-math-import-export .rank-math-export-form td{padding:0}.rank-math-import-export .rank-math-export-form .empty-notice{padding:0 1rem}.rank-math-import-export .rank-math-settings-backup-form .list-table{background:#fff}.rank-math-box-inner>*{display:none}.rank-math-box-inner>.active-tab{display:block}.rank-math-box-tabs{border-bottom:1px solid #b5bfc9;background:#f8f9fa;border-radius:6px 6px 0 0}.rank-math-box-tabs>a{color:#5b6065;font-size:0.825rem;font-weight:500;line-height:46px;position:relative;float:left;padding:0 15px;text-decoration:none;-webkit-box-shadow:none;box-shadow:none;border-right:1px solid #b5bfc9}.rank-math-box-tabs>a:first-child{border-radius:6px 0 0 0}.rank-math-box-tabs>a:hover{color:#069de3}.rank-math-box-tabs>a.active-tab{color:#069de3;background:#fff}.rank-math-box-tabs>a.active-tab:after{position:absolute;bottom:-1px;left:0;width:100%;height:1px;content:'';background:#fff}.rank-math-box-tabs>a .rm-icon{vertical-align:-1px;margin-right:3px}.invalid,.widefat.invalid,.wp-admin .invalid,.wp-admin .widefat.invalid{border-color:#dd2c00 !important;background:pink}.invalid ~ .validation-message,.widefat.invalid ~ .validation-message,.wp-admin .invalid ~ .validation-message,.wp-admin .widefat.invalid ~ .validation-message{display:inline-block}.validation-message{font-size:12px;font-style:italic;display:none;overflow:hidden;margin-top:5px;margin-left:2px;padding:4px 8px;-webkit-transition:.28s;transition:.28s;vertical-align:middle;color:#fff;border-radius:3px;background:#dd2c00}span.input-loading{background:url("../img/loader.svg") no-repeat center 4px;background-size:contain;display:inline-block;margin:0 0 0 16px;height:24px;width:16px}body .cmb2-wrap .cmb2-id-console-profile .regular-text,body .cmb2-wrap .cmb2-id-console-profile select,body .cmb2-wrap .cmb2-id-console-authorization-code .regular-text,body .cmb2-wrap .cmb2-id-console-authorization-code select{display:inline-block;max-width:60%;margin-right:10px}body .cmb2-wrap .cmb2-id-console-authorization-code .button-secondary{margin-top:5px}.wizard-share{margin-top:3px;vertical-align:3px}.wizard-share a{font-size:12px;font-weight:700;line-height:24px;display:inline-block;margin-left:5px;padding:0 15px 0 10px;text-decoration:none;color:#fff;border-radius:3px;background:#3b5998}.wizard-share a.share-twitter{background:#55acee}.wizard-share .dashicons{font-size:16px;height:auto;vertical-align:middle}#gsc-dp-info{font-weight:bold}textarea.rank-math-code-box,textarea.rank-math-code-box:focus,div.rank-math-code-box textarea,div.rank-math-code-box textarea:focus{color:#bbbec5;background:#32344b;border-color:#32344b;width:100%}textarea.rank-math-code-box:disabled,textarea.rank-math-code-box:focus:disabled,div.rank-math-code-box textarea:disabled,div.rank-math-code-box textarea:focus:disabled{color:#b3b6be}.rank-math-code-box div.cmb-td{width:100% !important}#new_post_type{width:1020px;max-width:100%;-webkit-box-sizing:border-box;box-sizing:border-box}.rank-math-notice{border-radius:4px}.rank-math-notice .rm-icon{font-size:18px;height:16px;vertical-align:-6px;margin-right:8px;opacity:0.8;display:inline-block}.rank-math-notice .notice-info,.rank-math-notice .notice-warning,.rank-math-notice .notice-error{border-radius:4px}.update-message p.rank-math-beta-update-notice{font-weight:bold}.update-message p.rank-math-beta-update-notice:before{content:"\f534"}.updating-message p.rank-math-beta-update-notice,.updated-message p.rank-math-beta-update-notice{display:none}.rank-math-mode-basic .rank-math-advanced-option{display:none !important}#footer-thankyou{font-style:normal}.text-center{text-align:center}.rank-math-gray-box{margin-top:2rem !important;padding:25px 35px;border-radius:5px;background:#f5f5f5}body.rtl .rank-math-header{margin-right:-20px;margin-left:0}body.rtl .rank-math-header .rank-math-logo{margin-right:0;padding-right:0;margin-left:15px;padding-left:15px}body.rtl .rank-math-header .rank-math-logo:after{right:auto;left:0}body.rtl .rank-math-header .rank-math-logo-text{margin-right:0;margin-left:auto}body.rtl .rank-math-search-options{float:left}body.rtl .rank-math-search-options .search-field{float:right}body.rtl .rank-math-search-options .search-field input{margin:0 0 0 5px}body.rtl .rank-math-wrap{margin-right:0;margin-left:40px}body.rtl .rank-math-wrap h1,body.rtl .rank-math-wrap .page-title{margin-right:0;margin-left:200px}body.rtl .rank-math-wrap .rank-math-text{margin-right:0;margin-left:200px}body.rtl.rank-math-page .dashboard-wrapper:before{right:-180px;left:auto}body.rtl.rank-math-page .nav-tab{border-right:1px solid #b5bfc9;border-left:0;margin-right:0}body.rtl.rank-math-page .nav-tab:first-child{border-radius:0 4px 0 0}body.rtl.rank-math-page .nav-tab:last-child{border-radius:4px 0 0 0;border-left:1px solid #b5bfc9}body.rtl.rank-math-page .rank-math-mode-selector a{margin-right:0;margin-left:7px}body.rtl .rank-math-tab .cmb-advanced-robots-list li{padding:0 0 0 1%}body.rtl .rank-math-tabs-navigation:not(.rank-math-custom){float:right;margin-right:0}body.rtl .rank-math-tabs-navigation:not(.rank-math-custom) a .rm-icon{margin-right:0;margin-left:10px}body.rtl .rank-math-wrap-settings .form-footer{margin-right:200px;margin-left:0}body.rtl .cmb2-wrap .cmb-type-textarea .button,body.rtl .cmb2-wrap .cmb-type-textarea-small .button{border-width:1px 1px 0 0}body.rtl .rank-math-ui .button .dashicons{margin:0 0 0 3px}.rank-math-variables-preview,.rank-math-preview-title{font-family:arial, sans-serif;max-width:600px;margin-top:15px;color:#1a0dab;border-radius:4px}.rank-math-variables-preview:empty,.rank-math-preview-title:empty{display:none}.rank-math-variables-preview:before,.rank-math-preview-title:before{font-size:10px;font-weight:600;display:block;margin:0 0 8px;content:attr(data-title);letter-spacing:.15em;text-transform:uppercase;color:#aaa}.rank-math-variables-wrap{position:relative}.rank-math-variables-wrap input,.rank-math-variables-wrap textarea{padding-right:50px !important}.cmb2-wrap .cmb-type-textarea .button.button-secondary,.cmb2-wrap .cmb-type-textarea-small .button.button-secondary{top:auto;right:1px;bottom:1px;border-width:1px 0 0 1px;border-radius:3px 0 3px 0}.cmb2-wrap .cmb-type-textarea .button.button-secondary+.rank-math-variables-dropdown,.cmb2-wrap .cmb-type-textarea-small .button.button-secondary+.rank-math-variables-dropdown{top:70px;right:0}.cmb2-wrap .cmb-type-textarea textarea,.cmb2-wrap .cmb-type-textarea-small textarea{display:block;resize:none}a.rank-math-variables-button.button-secondary{line-height:40px;height:auto;padding:0 10px;color:#858b90;border-width:0 0 0 1px;border-radius:0 3px 3px 0;-webkit-box-shadow:none;box-shadow:none;position:absolute;top:1px;right:0;bottom:1px}a.rank-math-variables-button.button-secondary .dashicons{font-size:20px;line-height:40px;height:auto;margin-right:0}a.rank-math-variables-button.button-secondary:hover{border-color:#b5bfc9;background:#f8f9fa}.rank-math-variables-dropdown{z-index:999;display:none;overflow:auto;max-width:450px;border:1px solid #b5bfc9;border-radius:6px;background:#fff;position:absolute;top:48px;right:0;height:220px;width:80%}.rank-math-variables-dropdown input[type='text']{margin:10px;border-color:#b5bfc9;background:#fff;height:34px;width:calc(100% - 20px)}.rank-math-variables-dropdown input[type='text']:focus{border-color:#069de3;-webkit-box-shadow:0 0 0 1px #069de3;box-shadow:0 0 0 1px #069de3}.rank-math-variables-dropdown ul{margin:0}.rank-math-variables-dropdown li{font-size:12px;position:relative;margin:0;padding:10px;cursor:pointer;border-bottom:1px solid #b5bfc9}.rank-math-variables-dropdown li:last-of-type{border-bottom:0}.rank-math-variables-dropdown li span{font-style:italic;display:block;padding-top:.2em;color:#888}.rank-math-variables-dropdown li:hover{background:#f8f9fa}.rank-math-variables-dropdown li:after{display:inline-block;margin-top:3px;padding:.25em .4em;content:attr(data-var);white-space:nowrap;border-radius:.25rem;background-color:#f0f2f4;position:absolute;top:4px;right:10px}.dropdown-up .rank-math-variables-dropdown{top:auto;bottom:100%}.rank-math-preview-title>div{display:inline-block;min-width:400px}.rank-math-preview-title h5{font-size:18px;font-weight:normal;line-height:22px;margin:0;color:#1a0dab}.rank-math-preview-title span{line-height:16px;height:17px;color:#006621}.list-table{border:1px solid #b5bfc9;border-radius:6px}.list-table+.notice{margin-top:10px}.list-table .empty-notice{font-weight:600;padding-left:15px}.list-table table{margin:0}.list-table th,.list-table td{padding:12px 15px;border-bottom:1px solid #b5bfc9}.list-table tr:last-child th,.list-table tr:last-child td{border:0}.list-table th strong{font-size:16px;display:block}.list-table .cmb2-checkbox-list li{display:inline-block;width:48%;margin:10px 0 0}.list-table .cmb2-checkbox-list label{font-weight:400}.list-table.with-action th{width:auto;vertical-align:middle}.list-table.with-action td:last-child{text-align:right}.list-table.with-action td:last-child .button+.button{margin-left:5px}.list-table.with-action.at-top td:last-child{vertical-align:top}.list-table.with-action .choices td{padding-top:0;text-align:left}.list-table.with-action .importer-header th,.list-table.with-action .importer-header td{border-bottom:none}@media screen and (max-width: 1020px){body .rank-math-wrap h1,body .rank-math-wrap .page-title{margin-right:0}}@media screen and (max-width: 782px){.form-table input.regular-text{height:36px}body .cmb2-wrap select{padding:0}body .rank-math-wrap .cmb-row.cmb-type-file .regular-text:not([type='hidden'])+.cmb2-upload-button{line-height:35px}body .rank-math-wrap .rank-math-search-options .search-field input{width:200px}body .rank-math-wrap .cmb2-id-console-profile select{max-width:100%}body .rank-math-wrap .cmb2-id-console-profile button{margin-top:5px}body .rank-math-wrap .rank-math-rss-variables thead th,body .rank-math-wrap .rank-math-rss-variables tbody td{margin-bottom:0}body .rank-math-wrap input[type=checkbox]:checked:before,body .rank-math-wrap .cmb2-wrap input[type=checkbox]:checked:before{font-size:30px}body #rank-math-redirection-popup .media-modal{left:0;height:100%}body .rank-math-wrap .module-listing .two-col .col{width:100%;min-width:100%;max-width:100%}body .rank-math-wrap .rank-math-systm-status td,body .rank-math-wrap .rank-math-systm-status th{border:0;border-bottom:1px solid #ededed}}@media only screen and (max-width: 768px){body .rank-math-wrap .rank-math-tabs-navigation:not(.rank-math-custom),body .rank-math-wrap.rank-math-wrap-settings .form-footer{width:100%;margin:0}}@media only screen and (max-width: 640px){body .rank-math-wrap .rank-math-tabs-content:not(.rank-math-custom){padding:15px}body .rank-math-wrap .rank-math-search-options{width:100%;margin-bottom:15px}body .cmb2-wrap .cmb-row{padding:15px 0}body .rank-math-wrap .cmb-row .cmb-th{max-width:100%;margin-bottom:5px}body .rank-math-wrap .rank-math-ui.settings-footer input{padding:0 25px}body .rank-math-wrap .rank-math-box-help.two-col .col{width:100%;min-width:100%;max-width:100%}body .rank-math-social-preview-item{padding:10px}}@media only screen and (max-width: 595px){body .rank-math-wrap h1,body .rank-math-wrap .page-title{font-size:30px}body .rank-math-wrap .cmb-group-text-only .cmb-field-list .cmb-field-list>.cmb-remove-field-row{padding-top:0}body .rank-math-wrap .cmb2-wrap .cmb-row.cmb-type-file .regular-text{width:100%;margin-top:5px;border-radius:3px}body .rank-math-metabox-wrap .rank-math-tab{padding:15px}body .rank-math-redirections-wrap .wp-heading-inline a{display:inline-block}body .rank-math-metabox-wrap .rank-math-tabs-navigation:not(.social-tabs-navigation) a .dashicons{font-size:18px;margin-right:0;padding-bottom:2px;padding-left:2px}body .rank-math-metabox-wrap .rank-math-tabs-navigation:not(.social-tabs-navigation) a .rank-math-tab-text{display:none}body .cmb2-wrap .cmb-row.cmb-row-33,body .cmb2-wrap .cmb-row.cmb-row-50{width:100%}body .cmb2-wrap .cmb-row.cmb-row-33 .cmb-th,body .cmb2-wrap .cmb-row.cmb-row-33 .cmb-td,body .cmb2-wrap .cmb-row.cmb-row-50 .cmb-th,body .cmb2-wrap .cmb-row.cmb-row-50 .cmb-td{padding:0}}.rank-math-validate-field label.invalid{font-size:12px;font-style:italic;margin-top:5px;margin-left:2px;padding:4px 8px;vertical-align:middle;color:#fff;border-radius:3px;background:#dd2c00;position:absolute;overflow:visible}.rank-math-validate-field label.invalid:after{content:"";width:0;height:0;border-style:solid;border-width:0 4px 6px 4px;border-color:transparent transparent #dd2c00 transparent;position:absolute;top:-6px;left:6px}
assets/css/dashboard.css ADDED
@@ -0,0 +1 @@
 
1
+ .rank-math-list-icon{margin:0 0 1.5rem}.rank-math-list-icon li{margin-bottom:18px;overflow:hidden}.rank-math-list-icon li a{text-decoration:none;color:#7f868d}.rank-math-list-icon li a:hover strong{color:#069de3}.rank-math-list-icon li a:focus{outline:none;-webkit-box-shadow:none;box-shadow:none}.rank-math-list-icon li strong{font-weight:600;display:block;margin:3px 0;color:#242628;-webkit-transition:0.25s linear all;transition:0.25s linear all}.rank-math-list-icon li p{margin:0}.rank-math-list-icon li i{float:left;margin-right:15px;text-align:center}.rank-math-list-icon li i.rm-icon-star-filled{color:#F7D070;background:#253142}.rank-math-list-icon li i.rm-icon-settings{color:#B8423F;background:rgba(184,66,63,0.1)}.rank-math-list-icon li i.rm-icon-import{color:#3494BE;background:rgba(52,148,190,0.1)}.rank-math-list-icon li i.rm-icon-post{color:#E3765C;background:rgba(227,118,92,0.1)}.rank-math-list-icon li i.rm-icon-help{color:#87a627;background:rgba(135,166,39,0.1)}.rank-math-list-icon li i.rm-icon-sitemap{color:#DBA240;background:rgba(219,162,64,0.1)}.rank-math-list-icon li i.rm-icon-support{color:#2940C9;background:rgba(41,64,201,0.1)}.rank-math-list-icon li>div{overflow:hidden}.rank-math-switch input[type=checkbox]{visibility:hidden;height:0;width:0}.rank-math-switch label{position:relative;display:block;cursor:pointer;text-indent:-9999px;border-radius:100px;background:#ddd;height:24px;width:44px}.rank-math-switch label:after{position:absolute;top:2px;left:2px;content:'';-webkit-transition:.4s;transition:.4s;border-radius:90px;background:#fff;height:20px;width:20px}.rank-math-switch input:checked+label{background:#528fcc}.rank-math-switch input:checked+label:after{-webkit-transform:translateX(100%);transform:translateX(100%)}.module-listing .grid{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row wrap;flex-flow:row wrap}.rank-math-list-icon li i,.module-listing .rank-math-box>i{font-size:20px;line-height:50px;display:inline-block;color:#ccc;border-radius:6px;background:#eee;height:50px;width:50px}.module-listing .grid{-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-flow:row wrap;flex-flow:row wrap}.module-listing .rank-math-box{-webkit-box-flex:0;-ms-flex:0 0 288px;flex:0 0 288px;padding:1.875rem 1.25rem 80px;margin:0 0.9375rem 0.9375rem 0;text-align:center;-webkit-box-sizing:border-box;box-sizing:border-box}.module-listing .rank-math-box>i.rm-icon-404{color:#FF521B;background:rgba(255,82,27,0.12)}.module-listing .rank-math-box>i.rm-icon-mobile{color:#3f8aca;background:rgba(63,138,202,0.12)}.module-listing .rank-math-box>i.rm-icon-acf{color:#03E6AA;background:rgba(3,230,170,0.12)}.module-listing .rank-math-box>i.rm-icon-users{color:#3494BE;background:rgba(52,148,190,0.1)}.module-listing .rank-math-box>i.rm-icon-comments{color:#B8423F;background:rgba(184,66,63,0.1)}.module-listing .rank-math-box>i.rm-icon-images{color:#649d66;background:rgba(100,157,102,0.1)}.module-listing .rank-math-box>i.rm-icon-link{color:#DBA240;background:rgba(219,162,64,0.1)}.module-listing .rank-math-box>i.rm-icon-local-seo{color:#2940C9;background:rgba(41,64,201,0.1)}.module-listing .rank-math-box>i.rm-icon-post{color:#679cf7;background:rgba(103,156,247,0.1)}.module-listing .rank-math-box>i.rm-icon-redirection{color:#F7B267;background:rgba(247,178,103,0.1)}.module-listing .rank-math-box>i.rm-icon-schema{color:#843224;background:rgba(132,50,36,0.1)}.module-listing .rank-math-box>i.rm-icon-role-manager{color:#87a627;background:rgba(135,166,39,0.1)}.module-listing .rank-math-box>i.rm-icon-search-console{color:#3C88D8;background:rgba(60,136,216,0.1)}.module-listing .rank-math-box>i.rm-icon-analyzer{color:#E3765C;background:rgba(227,118,92,0.1)}.module-listing .rank-math-box>i.rm-icon-sitemap{color:#049404;background:rgba(4,148,4,0.1)}.module-listing .rank-math-box>i.rm-icon-cart{color:#842474;background:rgba(132,36,116,0.1)}.module-listing .rank-math-box>i.rm-icon-video{color:#f76767;background:rgba(247,103,103,0.1)}.module-listing .rank-math-box>i.rm-icon-stories{color:#180ca4;background:rgba(24,12,164,0.1)}.module-listing .rank-math-box>i.rm-icon-instant-indexing{color:#a40fa4;background:rgba(164,15,164,0.1)}.module-listing .rank-math-box header{overflow:hidden}.module-listing .rank-math-box header h3{font-size:1.0625rem;margin:1.5rem 0 0.75rem}.module-listing .rank-math-box header h3 span{background:rgba(16,172,132,0.1);color:#019e76;font-weight:500}.module-listing .rank-math-box header p{margin-bottom:0;display:-webkit-box;-webkit-line-clamp:5;-webkit-box-orient:vertical;overflow:hidden}.module-listing .rank-math-box .module-settings{display:none;float:left;font-size:14px;line-height:30px;padding:0 12px;height:32px}.module-listing .rank-math-box .status{clear:both;background:#f8f9fa;-webkit-box-sizing:border-box;box-sizing:border-box;width:100%;height:60px;margin:0;padding:15px 20px;border-top:1px solid #b5bfc9;border-radius:0 0 6px 6px;position:absolute;bottom:0;left:0}.module-listing .rank-math-box .status label{color:#77797c}.module-listing .rank-math-box .status label.rank-math-tooltip span{text-indent:0;color:#fff}.module-listing .rank-math-box .status .cmb2-toggle{float:right;margin-top:3px}.module-listing .rank-math-box .status .cmb2-toggle .cmb2-slider{text-indent:-9999px;z-index:1}.module-listing .rank-math-box .status .cmb2-toggle .rank-math-tooltip span{top:50%;right:58px;bottom:auto;left:auto;width:110px;-webkit-transform:translate3d(-70%, -50%, 0);transform:translate3d(-70%, -50%, 0)}.module-listing .rank-math-box .status .cmb2-toggle .rank-math-tooltip span:after{top:50%;right:-8px;left:auto;width:0;height:0;content:'';-webkit-transform:translate3d(0, -50%, 0);transform:translate3d(0, -50%, 0);border-width:7px 0 7px 8px;border-style:solid;border-color:transparent transparent transparent #555d66}.module-listing .rank-math-box .status .cmb2-toggle .rank-math-tooltip:hover span{bottom:auto;-webkit-transform:translate3d(0, -50%, 0);transform:translate3d(0, -50%, 0);opacity:1}.module-listing .rank-math-box .status .cmb2-toggle .input-loading{display:none}.module-listing .rank-math-box.active .module-settings{display:inline-block}.module-listing .rank-math-box.saving .cmb2-toggle label{display:none}.module-listing .rank-math-box.saving .cmb2-toggle .input-loading{display:block;margin-top:0}.cmb2-toggle{position:relative;display:inline-block;width:50px;height:24px}.cmb2-toggle input{display:none}.cmb2-toggle input:checked+.cmb2-slider{background-color:#069de3;border-color:#069de3}.cmb2-toggle input:checked+.cmb2-slider:before{background:#fff;-webkit-transform:translateX(24px);transform:translateX(24px)}.cmb2-toggle input:checked+.cmb2-slider .toggle_off{display:none}.cmb2-toggle input:checked+.cmb2-slider .toggle_on{display:block}.cmb2-toggle input+.cmb2-slider:focus{-webkit-box-shadow:0 0 0 2px #fff, 0 0 0 3px #555d66;box-shadow:0 0 0 2px #fff, 0 0 0 3px #555d66}.cmb2-slider{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;border:2px solid #6c7781;border-radius:34px}.cmb2-slider:before{position:absolute;content:"";height:14px;width:14px;left:4px;bottom:3px;background-color:#6c7781;border-radius:50%}.cmb2-slider.disabled{opacity:0.6}.toggle_on,.toggle_off{position:absolute;top:6px;left:10px;-webkit-box-sizing:border-box;box-sizing:border-box}.toggle_on{display:none;outline:1px solid transparent;outline-offset:-1px;background:#fff;fill:#fff;border:1px solid #fff;border-radius:2px}.toggle_off{color:#6c7781;fill:currentColor;right:6px;left:auto}#side-sortables .cmb-row .cmb2-toggle+.cmb2-metabox-description{padding-bottom:0}.rank-math-welcome-text{padding:10px 30px;border:1px solid #d8d8d8;border-radius:3px;-webkit-box-shadow:4px 4px 20px rgba(0,0,0,0.12);box-shadow:4px 4px 20px rgba(0,0,0,0.12)}.rank-math-box{margin-bottom:1.875rem}.rank-math-box header .button{font-weight:500;position:absolute;top:1.875rem;right:1.875rem;color:#fff;border:0;border-radius:4px;-webkit-box-shadow:none;box-shadow:none}.rank-math-box header .button i{font-weight:600;margin-right:5px;font-size:10px;text-shadow:1px 0px 0px #fff}.rank-math-box.status-green header h3{color:#58bb58}.rank-math-box.status-green header .button{background:#58bb58}.rank-math-box.status-red header h3{color:#ee6a5e}.rank-math-box.status-red header .button{background:#ee6a5e}.rank-math-box .regular-text.fullwidth{width:100%;margin-top:5px;padding:12px;vertical-align:top;color:#777;border-color:#ddd;background:#e5e5e5;-webkit-box-shadow:none !important;box-shadow:none !important}.rank-math-box .regular-text.fullwidth:focus{background:#f5f5f5}.rank-math-box form p{font-size:1.125rem;margin-bottom:0}.rank-math-box form .button-xlarge{margin-top:25px}.rank-math-box form .button-animated{margin:25px auto 0;display:table}[id^='cmb2-metabox-rank'] input[type=checkbox]{margin:0 5px 0 0}[id^='cmb2-metabox-rank'] input[type=checkbox]:checked,[id^='cmb2-metabox-rank'] input[type=checkbox]:checked:focus{border-color:#069de3;background:#069de3;-webkit-box-shadow:none !important;box-shadow:none !important}[id^='cmb2-metabox-rank'] input[type=checkbox]:checked:before,[id^='cmb2-metabox-rank'] input[type=checkbox]:checked:focus:before{content:url("data:image/svg+xml; utf8,%3Csvg%20xmlns%3D%27http%3A//www.w3.org/2000/svg%27%20viewBox%3D%270%200%2020%2020%27%3E%3Cpath%20d%3D%27M14.83%204.89l1.34.94-5.81%208.38H9.02L5.78%209.67l1.34-1.25%202.57%202.4z%27%20fill%3D%27%23fff%27/%3E%3C/svg%3E%0A");font-size:20px;color:#fff;height:1.3125rem;width:1.3125rem}@media screen and (max-width: 782px){[id^='cmb2-metabox-rank'] input[type=checkbox]:checked:before,[id^='cmb2-metabox-rank'] input[type=checkbox]:checked:focus:before{width:1.875rem;height:1.875rem;margin:-.1875rem -.3125rem}}.rank-math-systm-status{border-collapse:collapse}.rank-math-systm-status td,.rank-math-systm-status th{border:1px solid #b5bfc9}.rank-math-systm-status td:first-child{width:33%}.rank-math-systm-status thead th{font-weight:700}.rank-math-systm-status .rank-math-tooltip{float:right}.rank-math-systm-status+.rank-math-systm-status{margin-top:40px}#debug-report{display:none}#debug-report textarea{font-family:monospace;font-size:12px;line-height:20px;margin:0;padding:20px;resize:none;border-radius:0;outline:0;height:300px;width:100%}body.rtl .module-listing .rank-math-box>.dashicons{float:right}body.rtl .module-listing .rank-math-box header{padding-right:20px;padding-left:0}body.rtl .module-listing .status .rank-math-switch{float:left}body.rtl .module-listing .status .rank-math-switch label{float:left}body.rtl .module-listing .status .rank-math-switch strong{float:right;margin-left:12px}body.rtl .rank-math-box header .button{right:auto;left:20px}body.rtl .rank-math-systm-status .rank-math-tooltip{float:left}/*! CSS Used from: http://local.local/wp-content/plugins/404-monitor/assets/admin/css/modal.css?ver=1.0.1 ; media=all */@media all{.rank-math-feedback-modal{z-index:11000;display:none;background:rgba(0,0,0,0.8);position:fixed;top:0;right:0;bottom:0;left:0}.rank-math-feedback-modal p{padding:15px 20px;color:#21262b}.rank-math-feedback-modal .button-close{cursor:pointer;position:absolute;right:5px;top:5px;z-index:10}.rank-math-feedback-content{width:500px;max-width:100%;margin:auto;-webkit-transform:translate(-50%, -50%);transform:translate(-50%, -50%);border-radius:4px;background:#fff;-webkit-box-shadow:10px 10px 40px rgba(0,0,0,0.3);box-shadow:10px 10px 40px rgba(0,0,0,0.3);position:absolute;top:50%;left:50%}.rank-math-feedback-content .plugin-card.plugin-card-seo-by-rank-math{width:100%;margin:0;border:0}.rank-math-feedback-content .column-compatibility{float:left;width:auto;margin-top:6px}.rank-math-feedback-content p{padding:0 20px}.rank-math-feedback-content h3{margin-bottom:5px}.rank-math-feedback-content h3 a{color:inherit;text-decoration:none;font-size:18px}.rank-math-feedback-content .name.column-name{margin-right:0}.rank-math-feedback-content .plugin-card .desc{margin-right:0}.rank-math-feedback-content .plugin-card .desc p{font-size:14px;padding-left:0;padding-right:0}.rank-math-feedback-content .button{float:right}.rank-math-feedback-content .vers.column-rating{max-width:100%;width:100%;margin-top:10px}.rank-math-feedback-content .vers.column-rating a{color:inherit;text-decoration:none}.rank-math-feedback-content .num-ratings{font-size:14px;font-weight:normal;vertical-align:3px;margin-left:5px}.rank-math-feedback-content .star-rating{display:inline-block;margin-top:0;letter-spacing:-1px}.rank-math-feedback-content .star-rating .star{vertical-align:0}.rank-math-feedback-content .plugin-icon{top:24px}}.indexing-api-label{pointer-events:none}
assets/css/settings.css ADDED
@@ -0,0 +1 @@
 
1
+ .form-table .description{font-weight:normal}.setup-guide-link-wrapper{display:inline-block;border:1px solid #ccc;background:#fafafa;padding:10px 10px 10px 6px;margin-top:8px}.setup-guide-link-wrapper a{text-decoration:none}.notice:not(.rank-math-notice){display:none}
assets/fonts/Rank-Math.svg ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" standalone="no"?>
2
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
3
+ <svg xmlns="http://www.w3.org/2000/svg">
4
+ <metadata>Generated by IcoMoon</metadata>
5
+ <defs>
6
+ <font id="rank-math" horiz-adv-x="1024">
7
+ <font-face units-per-em="1024" ascent="1170.2857142857142" descent="146.28571428571428" />
8
+ <missing-glyph horiz-adv-x="1024" />
9
+ <glyph unicode="&#x20;" horiz-adv-x="0" d="" />
10
+ <glyph unicode="&#xe900;" glyph-name="rank-math" d="M1023.934 677.523l-168.816-7.602 29.765-46.542-281.471-179.92-279.255 117.309-324.157-135.128 22.473-53.945 301.639 125.687 284.951-119.681 307.38 196.387 29.765-46.542zM119.902 504.784l204.299 85.128 9.951-4.189v120.966h-214.25zM587.321 1000.283v-520.943l16.090-6.649 198.204 126.44v401.151zM353.634 577.434l214.25-90.026v366.112h-214.25z" />
11
+ <glyph unicode="&#xe901;" glyph-name="google" horiz-adv-x="860" d="M438.857 735.143h414.286c4-22.286 6.857-44 6.857-73.143 0-250.286-168-428.571-421.143-428.571-242.857 0-438.857 196-438.857 438.857s196 438.857 438.857 438.857c118.286 0 217.714-43.429 294.286-114.857l-119.429-114.857c-32.571 31.429-89.714 68-174.857 68-149.714 0-272-124-272-277.143s122.286-277.143 272-277.143c173.714 0 238.857 124.571 249.143 189.143h-249.143v150.857z" />
12
+ <glyph unicode="&#xe902;" glyph-name="copy" d="M810 270v598h-468v-598h468zM810 952q34 0 60-25t26-59v-598q0-34-26-60t-60-26h-468q-34 0-60 26t-26 60v598q0 34 26 59t60 25h468zM682 1124v-86h-512v-598h-84v598q0 34 25 60t59 26h512z" />
13
+ <glyph unicode="&#xea2e;" glyph-name="mobile" horiz-adv-x="1317" d="M966.857 1198h-617.143c-59.657 0-106.971-47.314-106.971-106.971v-1102.629c0-59.657 47.314-106.971 106.971-106.971h617.143c59.657 0 106.971 47.314 106.971 106.971v1102.629c2.057 59.657-47.314 106.971-106.971 106.971zM1014.171-11.6c0-24.686-20.571-45.257-45.257-45.257h-619.2c-24.686 0-45.257 20.571-45.257 45.257v1102.629c-2.057 24.686 18.514 45.257 45.257 45.257h617.143c24.686 0 45.257-20.571 45.257-45.257v-1102.629zM658.286 210.571c-53.486 0-98.743-45.257-98.743-98.743s45.257-98.743 98.743-98.743c53.486 0 98.743 45.257 98.743 98.743s-45.257 98.743-98.743 98.743zM658.286 74.8c-20.571 0-37.029 16.457-37.029 37.029s16.457 37.029 37.029 37.029 37.029-16.457 37.029-37.029-16.457-37.029-37.029-37.029zM726.171 1025.2h-135.771c-16.457 0-30.857-14.4-30.857-30.857s14.4-30.857 30.857-30.857h135.771c16.457 0 30.857 14.4 30.857 30.857s-14.4 30.857-30.857 30.857z" />
14
+ <glyph unicode="&#xea3a;" glyph-name="role-manager" horiz-adv-x="1317" d="M580.114 648.743c156.343 0 283.886 123.429 283.886 273.6 0 152.229-127.543 275.657-283.886 275.657s-283.886-123.429-283.886-273.6c2.057-152.229 127.543-275.657 283.886-275.657zM580.114 1136.286c123.429 0 222.171-96.686 222.171-213.943s-98.743-211.886-222.171-211.886-222.171 94.629-222.171 211.886 100.8 213.943 222.171 213.943zM1238.4 157.086c0 152.229-123.429 275.657-275.657 275.657-26.743 0-53.486-4.114-78.171-12.343-86.4 65.829-193.371 102.857-304.457 102.857-277.714 0-504-226.286-504-504v-65.829c0-41.143 32.914-74.057 74.057-74.057h859.886c16.457 0 32.914 6.171 45.257 16.457 106.971 41.143 183.086 141.943 183.086 261.257zM1102.629 319.6l-310.629-288c-24.686 34.971-41.143 78.171-41.143 125.486 0 117.257 96.686 213.943 213.943 213.943 51.429 0 100.8-20.571 137.829-51.429zM150.171-56.857c-6.171 0-12.343 6.171-12.343 12.343v65.829c0 242.743 197.486 442.286 442.286 442.286 86.4 0 166.629-24.686 238.629-69.943-78.171-49.371-131.657-135.771-131.657-234.514 0-86.4 39.086-162.514 102.857-213.943h-639.771zM962.743-56.857c-49.371 0-92.571 16.457-129.6 43.2l308.571 285.943c22.629-32.914 34.971-74.057 34.971-115.2 0-117.257-94.629-213.943-213.943-213.943z" />
15
+ <glyph unicode="&#xea43;" glyph-name="calendar" horiz-adv-x="1317" d="M1221.943 986.114h-109.029v94.629c0 16.457-14.4 30.857-30.857 30.857s-30.857-14.4-30.857-30.857v-96.686h-785.829v96.686c0 16.457-14.4 30.857-30.857 30.857s-30.857-12.343-30.857-30.857v-96.686h-109.029c-51.429 0-92.571-41.143-92.571-92.571v-833.143c0-51.429 41.143-92.571 92.571-92.571h1127.314c51.429 0 92.571 41.143 92.571 92.571v835.2c0 49.371-41.143 92.571-92.571 92.571zM63.771 636.4h257.143v-261.257h-257.143v261.257zM380.571 636.4h246.857v-261.257h-246.857v261.257zM627.429 313.429v-285.943h-246.857v285.943h246.857zM689.143 313.429h246.857v-285.943h-246.857v285.943zM689.143 375.143v261.257h246.857v-261.257h-246.857zM997.714 636.4h257.143v-261.257h-257.143v261.257zM94.629 924.4h109.029v-94.629c0-16.457 14.4-30.857 30.857-30.857s30.857 14.4 30.857 30.857v94.629h787.886v-94.629c0-16.457 14.4-30.857 30.857-30.857s30.857 14.4 30.857 30.857v94.629h109.029c16.457 0 30.857-14.4 30.857-30.857v-195.429h-1191.086v195.429c0 16.457 12.343 30.857 30.857 30.857zM63.771 60.4v253.029h257.143v-285.943h-226.286c-18.514 2.057-30.857 14.4-30.857 32.914zM1221.943 29.543h-226.286v283.886h257.143v-255.086c0-16.457-12.343-28.8-30.857-28.8z" />
16
+ <glyph unicode="&#xea4f;" glyph-name="sitemap" horiz-adv-x="1317" d="M1114.971 284.629c-69.943 0-127.543-49.371-141.943-113.143h-55.543v279.771h102.857c131.657 0 236.571 100.8 236.571 226.286s-106.971 226.286-236.571 226.286c-24.686 0-49.371-4.114-74.057-12.343 2.057 10.286 2.057 18.514 2.057 28.8 0 154.286-129.6 277.714-290.057 277.714s-288-123.429-288-275.657c0-10.286 0-20.571 2.057-28.8-24.686 8.229-49.371 12.343-74.057 12.343-131.657 0-236.571-100.8-236.571-226.286s106.971-226.286 236.571-226.286h102.857v-279.771h-55.543c-14.4 65.829-72 113.143-141.943 113.143-80.229 0-144-65.829-144-144 0-80.229 65.829-144 144-144 69.943 0 127.543 49.371 141.943 113.143h86.4c16.457 0 30.857 14.4 30.857 30.857v308.571h166.629v-283.886c-67.886-14.4-115.2-72-115.2-141.943 0-80.229 65.829-144 144-144s144 65.829 144 144c0 69.943-49.371 127.543-113.143 141.943v283.886h166.629v-310.629c0-16.457 14.4-30.857 30.857-30.857h86.4c14.4-65.829 72-113.143 141.943-113.143 80.229 0 144 65.829 144 144 0 80.229-65.829 144-144 144zM201.6 56.286c-45.257 0-82.286 37.029-82.286 82.286s37.029 82.286 82.286 82.286 82.286-37.029 82.286-82.286c2.057-45.257-34.971-82.286-82.286-82.286zM740.571 25.429c0-45.257-37.029-82.286-82.286-82.286s-82.286 37.029-82.286 82.286 37.029 82.286 82.286 82.286 82.286-34.971 82.286-82.286zM689.143 512.971v82.286c0 16.457-14.4 30.857-30.857 30.857s-30.857-14.4-30.857-30.857v-82.286h-166.629v82.286c0 16.457-14.4 30.857-30.857 30.857s-30.857-14.4-30.857-30.857v-82.286h-102.857c-96.686 0-174.857 74.057-174.857 164.571s78.171 164.571 174.857 164.571c37.029 0 72-10.286 102.857-30.857 10.286-8.229 26.743-6.171 37.029 2.057s14.4 22.629 10.286 34.971c-8.229 22.629-14.4 49.371-14.4 74.057 0 117.257 100.8 213.943 226.286 213.943s228.343-96.686 228.343-213.943c0-24.686-4.114-49.371-14.4-74.057-4.114-12.343-2.057-26.743 10.286-34.971 10.286-8.229 24.686-8.229 37.029-2.057 30.857 20.571 65.829 30.857 102.857 30.857 96.686 0 174.857-74.057 174.857-164.571s-78.171-164.571-174.857-164.571h-102.857v82.286c0 16.457-14.4 30.857-30.857 30.857s-30.857-14.4-30.857-30.857v-82.286h-168.686zM1114.971 56.286c-45.257 0-82.286 37.029-82.286 82.286s37.029 82.286 82.286 82.286 82.286-37.029 82.286-82.286-37.029-82.286-82.286-82.286z" />
17
+ <glyph unicode="&#xea5a;" glyph-name="import" horiz-adv-x="1317" d="M754.971 463.6l-65.829-69.943v205.714c0 16.457-14.4 30.857-30.857 30.857s-30.857-14.4-30.857-30.857v-205.714l-65.829 69.943c-12.343 12.343-30.857 12.343-43.2 2.057s-12.343-30.857-2.057-43.2l106.971-113.143c8.229-10.286 22.629-14.4 34.971-14.4s24.686 6.171 34.971 14.4l106.971 113.143c12.343 12.343 10.286 32.914-2.057 43.2s-30.857 10.286-43.2-2.057zM1211.657 718.686c-59.657 63.771-141.943 109.029-230.4 121.371-47.314 78.171-117.257 135.771-199.543 164.571-37.029 14.4-78.171 20.571-123.429 20.571-207.771 0-376.457-166.629-380.571-372.343-154.286-10.286-277.714-141.943-277.714-300.343 0-164.571 133.714-298.286 298.286-298.286h623.314c218.057 0 394.971 176.914 394.971 394.971 0 98.743-37.029 195.429-104.914 269.486zM919.543 115.943h-621.257c-131.657 0-236.571 104.914-236.571 236.571s104.914 236.571 236.571 236.571h10.286c16.457 0 30.857 14.4 30.857 30.857v22.629c0 174.857 141.943 318.857 318.857 318.857 37.029 0 72-6.171 102.857-18.514 74.057-24.686 135.771-78.171 174.857-150.171 4.114-8.229 14.4-14.4 24.686-16.457 78.171-8.229 154.286-47.314 205.714-102.857 57.6-61.714 88.457-144 88.457-226.286 0-181.029-150.171-331.2-335.314-331.2z" />
18
+ <glyph unicode="&#xea5d;" glyph-name="export" horiz-adv-x="1317" d="M701.486 636.4c-8.229 10.286-22.629 14.4-34.971 14.4s-24.686-6.171-34.971-14.4l-106.971-113.143c-12.343-12.343-10.286-32.914 2.057-43.2 6.171-6.171 14.4-8.229 20.571-8.229 8.229 0 16.457 4.114 22.629 10.286l65.829 69.943v-228.343c0-16.457 14.4-30.857 30.857-30.857s30.857 14.4 30.857 30.857v228.343l65.829-69.943c12.343-12.343 30.857-12.343 43.2-2.057 12.343 12.343 12.343 30.857 2.057 43.2l-106.971 113.143zM1211.657 718.686c-59.657 63.771-141.943 109.029-230.4 121.371-47.314 78.171-117.257 135.771-199.543 164.571-37.029 14.4-78.171 20.571-123.429 20.571-207.771 0-376.457-166.629-380.571-372.343-154.286-10.286-277.714-141.943-277.714-298.286 0-164.571 133.714-298.286 298.286-298.286h623.314c218.057-2.057 394.971 174.857 394.971 392.914 0 98.743-37.029 195.429-104.914 269.486zM919.543 115.943h-621.257c-131.657 0-236.571 104.914-236.571 238.629s104.914 236.571 236.571 236.571h10.286c16.457 0 30.857 14.4 30.857 30.857v22.629c0 174.857 141.943 318.857 318.857 318.857 37.029 0 72-6.171 102.857-16.457 74.057-24.686 135.771-78.171 174.857-150.171 4.114-8.229 14.4-14.4 24.686-16.457 78.171-8.229 154.286-47.314 205.714-102.857 57.6-61.714 88.457-144 88.457-226.286 0-185.143-150.171-335.314-335.314-335.314z" />
19
+ <glyph unicode="&#xea60;" glyph-name="settings" horiz-adv-x="1317" d="M660.343 798.914c-141.943 0-259.2-115.2-259.2-259.2 0-141.943 115.2-259.2 259.2-259.2 141.943 0 257.143 115.2 257.143 259.2 0 141.943-115.2 259.2-257.143 259.2zM660.343 342.229c-109.029 0-197.486 88.457-197.486 197.486s88.457 197.486 197.486 197.486 197.486-88.457 197.486-197.486c-2.057-109.029-90.514-197.486-197.486-197.486zM1291.886 385.429l-133.714 72c-2.057 2.057-4.114 6.171-4.114 8.229 4.114 26.743 6.171 53.486 6.171 80.229 0 28.8-2.057 55.543-6.171 80.229 0 2.057 0 6.171 2.057 8.229l135.771 76.114c20.571 12.343 28.8 37.029 18.514 57.6l-127.543 218.057c-12.343 18.514-37.029 26.743-57.6 18.514l-141.943-78.171h-4.114c-10.286 8.229-18.514 16.457-26.743 22.629-24.686 20.571-45.257 39.086-78.171 55.543-8.229 4.114-14.4 14.4-14.4 22.629v82.286c0 49.371-39.086 88.457-88.457 88.457h-226.286c-49.371 0-88.457-39.086-88.457-88.457v-86.4c0-10.286-6.171-18.514-14.4-22.629-32.914-16.457-53.486-34.971-80.229-55.543-8.229-6.171-16.457-14.4-24.686-20.571h-4.114l-129.6 67.886c-37.029 20.571-61.714 6.171-72-12.343l-123.429-211.886c-6.171-10.286-8.229-22.629-4.114-34.971s10.286-22.629 22.629-28.8l133.714-74.057c4.114 0 4.114-4.114 4.114-6.171-4.114-24.686-6.171-49.371-6.171-80.229 0-26.743 2.057-53.486 4.114-78.171 0-2.057 0-6.171-4.114-8.229l-137.829-76.114c-20.571-12.343-28.8-37.029-18.514-57.6l127.543-218.057c14.4-18.514 37.029-26.743 59.657-18.514l141.943 78.171h4.114c10.286-8.229 18.514-14.4 26.743-22.629 24.686-20.571 47.314-41.143 80.229-55.543 8.229-4.114 14.4-14.4 14.4-22.629v-96.686c0-49.371 39.086-88.457 88.457-88.457h228.343c49.371 0 88.457 39.086 88.457 88.457v98.743c0 10.286 6.171 18.514 14.4 22.629 30.857 14.4 53.486 32.914 78.171 55.543 8.229 6.171 16.457 14.4 26.743 22.629h4.114l127.543-72c34.971-20.571 61.714-6.171 72 12.343l125.486 213.943c6.171 10.286 8.229 22.629 4.114 34.971s-12.343 22.629-22.629 28.8zM1137.6 155.029l-125.486 69.943c-22.629 12.343-51.429 10.286-72-6.171-10.286-8.229-18.514-16.457-28.8-22.629-22.629-18.514-41.143-34.971-63.771-47.314-30.857-14.4-49.371-45.257-49.371-78.171v-98.743c0-14.4-12.343-26.743-26.743-26.743h-226.286c-14.4 0-26.743 12.343-26.743 26.743v96.686c0 32.914-20.571 63.771-49.371 78.171-24.686 12.343-43.2 26.743-67.886 47.314-8.229 8.229-18.514 14.4-26.743 22.629-12.343 10.286-26.743 14.4-41.143 14.4-10.286 0-22.629-2.057-32.914-8.229l-125.486-69.943-109.029 185.143 121.371 67.886c24.686 14.4 37.029 41.143 34.971 69.943-2.057 22.629-4.114 45.257-4.114 69.943 0 26.743 2.057 49.371 6.171 69.943 4.114 28.8-8.229 59.657-34.971 74.057l-119.314 65.829 109.029 185.143 125.486-69.943c22.629-12.343 51.429-10.286 72 6.171 10.286 8.229 18.514 14.4 26.743 22.629 22.629 20.571 41.143 34.971 67.886 47.314 30.857 14.4 49.371 45.257 49.371 78.171v84.343c0 14.4 12.343 26.743 26.743 26.743h228.343c14.4 0 26.743-12.343 26.743-26.743v-84.343c0-32.914 20.571-63.771 49.371-78.171 24.686-12.343 41.143-26.743 63.771-45.257 8.229-8.229 18.514-16.457 28.8-24.686 20.571-16.457 49.371-18.514 72-6.171l125.486 69.943 109.029-185.143-121.371-67.886c-24.686-14.4-39.086-43.2-32.914-72 4.114-20.571 6.171-43.2 6.171-69.943 0-22.629-2.057-45.257-6.171-69.943-4.114-28.8 8.229-57.6 34.971-72l119.314-63.771-113.143-185.143z" />
20
+ <glyph unicode="&#xea67;" glyph-name="desktop" horiz-adv-x="1317" d="M1265.143 1140.4h-1213.714c-28.8 0-51.429-22.629-51.429-51.429v-814.629c0-28.8 22.629-51.429 51.429-51.429h446.4l-59.657-224.229h-121.371c-16.457 0-30.857-14.4-30.857-30.857s14.4-30.857 30.857-30.857h685.029c16.457 0 30.857 14.4 30.857 30.857s-14.4 30.857-30.857 30.857h-121.371l-59.657 224.229h446.4c28.8 0 51.429 22.629 51.429 51.429v814.629c-2.057 28.8-24.686 51.429-53.486 51.429zM816.686 0.743h-316.8l59.657 224.229h195.429l61.714-224.229zM1254.857 284.629h-1193.143v794.057h1193.143v-794.057z" />
21
+ <glyph unicode="&#xea6f;" glyph-name="htaccess" horiz-adv-x="1317" d="M1285.714 947.029h-613.029l-80.229 230.4c-4.114 12.343-16.457 20.571-28.8 20.571h-532.8c-16.457 0-30.857-14.4-30.857-30.857v-1254.857c0-16.457 14.4-30.857 30.857-30.857h1254.857c16.457 0 30.857 14.4 30.857 30.857v1003.886c0 16.457-14.4 30.857-30.857 30.857zM1254.857-56.857h-1193.143v1193.143h481.371l80.229-230.4c4.114-12.343 16.457-20.571 28.8-20.571h602.743v-942.171zM228.343 665.2c0-16.457 14.4-30.857 30.857-30.857h456.686c16.457 0 30.857 14.4 30.857 30.857s-14.4 30.857-30.857 30.857h-456.686c-16.457 0-30.857-14.4-30.857-30.857zM259.2 383.371h456.686c16.457 0 30.857 14.4 30.857 30.857s-14.4 30.857-30.857 30.857h-456.686c-16.457 0-30.857-14.4-30.857-30.857s14.4-30.857 30.857-30.857zM228.343 163.257c0-16.457 14.4-30.857 30.857-30.857h627.429c16.457 0 30.857 14.4 30.857 30.857s-14.4 30.857-30.857 30.857h-627.429c-16.457 0-30.857-14.4-30.857-30.857z" />
22
+ <glyph unicode="&#xea70;" glyph-name="robots" horiz-adv-x="1317" d="M1285.714 947.029h-613.029l-80.229 230.4c-4.114 12.343-16.457 20.571-28.8 20.571h-532.8c-16.457 0-30.857-14.4-30.857-30.857v-1254.857c0-16.457 14.4-30.857 30.857-30.857h1254.857c16.457 0 30.857 14.4 30.857 30.857v1003.886c0 16.457-14.4 30.857-30.857 30.857zM1254.857-56.857h-1193.143v1193.143h481.371l80.229-230.4c4.114-12.343 16.457-20.571 28.8-20.571h602.743v-942.171zM415.543 638.457c-10.286-6.171-16.457-16.457-16.457-26.743v-129.6c0-150.171 72-290.057 193.371-374.4l47.314-32.914c6.171-4.114 12.343-6.171 18.514-6.171s12.343 2.057 18.514 6.171l47.314 32.914c121.371 84.343 193.371 222.171 193.371 374.4v129.6c0 12.343-6.171 22.629-16.457 26.743l-228.343 117.257c-8.229 4.114-18.514 4.114-28.8 0l-228.343-117.257zM855.771 591.143v-111.086c0-129.6-61.714-250.971-166.629-322.971l-30.857-20.571-30.857 20.571c-104.914 72-166.629 193.371-166.629 322.971v111.086l197.486 102.857 197.486-102.857z" />
23
+ <glyph unicode="&#xea76;" glyph-name="category" horiz-adv-x="1317" d="M1291.886 805.086c0 2.057 2.057 6.171 2.057 8.229v109.029c0 47.314-39.086 86.4-86.4 86.4h-559.543c-4.114 0-8.229 0-12.343-2.057l-18.514 47.314c-8.229 20.571-28.8 34.971-51.429 34.971h-510.171c-30.857 0-55.543-24.686-55.543-55.543v-987.429c0-30.857 24.686-55.543 55.543-55.543h1207.543c30.857 0 55.543 24.686 55.543 55.543v713.829c-2.057 18.514-12.343 34.971-26.743 45.257zM1207.543 947.029c12.343 0 24.686-10.286 24.686-24.686v-109.029h-518.4l-53.486 133.714h547.2zM1254.857 52.171h-1193.143v975.086h499.886l94.629-234.514c10.286-22.629 32.914-39.086 57.6-39.086h541.029v-701.486z" />
24
+ <glyph unicode="&#xea83;" glyph-name="link" horiz-adv-x="1317" d="M1246.629 294.914l-181.029 181.029c-88.457 88.457-230.4 94.629-325.029 14.4l-131.657 131.657c34.971 43.2 55.543 94.629 55.543 152.229 0 65.829-24.686 125.486-69.943 172.8l-181.029 181.029c-94.629 94.629-246.857 94.629-341.486 0-47.314-47.314-72-106.971-72-172.8 0-63.771 24.686-125.486 69.943-170.743l178.971-181.029c47.314-47.314 109.029-69.943 170.743-69.943 49.371 0 98.743 16.457 141.943 45.257l135.771-135.771c-28.8-41.143-45.257-90.514-45.257-139.886 0-63.771 24.686-125.486 69.943-170.743l178.971-181.029c47.314-47.314 109.029-69.943 170.743-69.943s123.429 22.629 170.743 69.943c45.257 45.257 72 104.914 72 170.743 2.057 65.829-22.629 125.486-67.886 172.8zM294.171 648.743l-178.971 181.029c-34.971 32.914-53.486 78.171-53.486 125.486s18.514 92.571 53.486 127.543c34.971 34.971 80.229 53.486 127.543 53.486 45.257 0 92.571-18.514 127.543-53.486l181.029-181.029c31.842-33.494 51.43-78.9 51.43-128.881 0-0.253-0.001-0.505-0.002-0.758v0.039c0-39.086-14.4-78.171-37.029-109.029l-72 72c-12.343 12.343-30.857 12.343-43.2 0s-12.343-30.857 0-43.2l69.943-69.943c-72-43.2-164.571-34.971-226.286 26.743zM1201.371-3.371c-69.943-69.943-185.143-69.943-255.086 0l-178.971 181.029c-34.971 34.971-53.486 80.229-53.486 127.543 0 34.971 10.286 67.886 28.8 96.686l69.943-67.886c6.171-6.171 14.4-8.229 22.629-8.229s16.457 2.057 22.629 8.229c12.343 12.343 12.343 30.857 0 43.2l-69.943 69.943c32.914 24.686 72 37.029 111.086 37.029 45.257 0 92.571-18.514 127.543-53.486l181.029-181.029c32.914-34.971 51.429-80.229 51.429-127.543-4.114-47.314-22.629-92.571-57.6-125.486z" />
25
+ <glyph unicode="&#xea87;" glyph-name="local-seo" horiz-adv-x="1317" d="M658.286 1198c-292.114 0-530.743-230.4-530.743-514.286 0-246.857 380.571-666.514 497.829-787.886 8.229-10.286 20.571-14.4 34.971-14.4 12.343 0 24.686 6.171 34.971 14.4 117.257 123.429 497.829 541.029 497.829 787.886-4.114 283.886-242.743 514.286-534.857 514.286zM658.286-50.686c-220.114 232.457-469.029 559.543-469.029 734.4 0 250.971 209.829 452.571 469.029 452.571s469.029-201.6 469.029-452.571c0-174.857-248.914-501.943-469.029-734.4zM658.286 885.314c-123.429 0-224.229-96.686-224.229-216s100.8-216 224.229-216 224.229 96.686 224.229 216c0 117.257-100.8 216-224.229 216zM658.286 512.971c-88.457 0-162.514 69.943-162.514 154.286s72 154.286 162.514 154.286 162.514-69.943 162.514-154.286-74.057-154.286-162.514-154.286z" />
26
+ <glyph unicode="&#xea8f;" glyph-name="misc" horiz-adv-x="1317" d="M658.286 1198c-362.057 0-658.286-296.229-658.286-658.286s296.229-658.286 658.286-658.286 658.286 296.229 658.286 658.286-296.229 658.286-658.286 658.286zM658.286-56.857c-329.143 0-596.571 267.429-596.571 596.571s267.429 596.571 596.571 596.571 596.571-267.429 596.571-596.571-267.429-596.571-596.571-596.571zM884.571 831.829h-452.571c-16.457 0-30.857-14.4-30.857-30.857s14.4-30.857 30.857-30.857h452.571c16.457 0 30.857 14.4 30.857 30.857s-14.4 30.857-30.857 30.857zM884.571 570.571h-452.571c-16.457 0-30.857-14.4-30.857-30.857s14.4-30.857 30.857-30.857h452.571c16.457 0 30.857 14.4 30.857 30.857s-14.4 30.857-30.857 30.857zM884.571 309.314h-452.571c-16.457 0-30.857-14.4-30.857-30.857s14.4-30.857 30.857-30.857h452.571c16.457 0 30.857 14.4 30.857 30.857s-14.4 30.857-30.857 30.857z" />
27
+ <glyph unicode="&#xea9a;" glyph-name="software" horiz-adv-x="1317" d="M1312.457 772.171l-104.914 327.086c-14.4 43.2-55.543 72-100.8 72h-884.571c-45.257 0-84.343-26.743-98.743-67.886l-117.257-329.143c-4.114-10.286-6.171-22.629-6.171-34.971v-728.229c0-57.6 47.314-104.914 104.914-104.914h1106.743c57.6 0 104.914 47.314 104.914 104.914v730.286c0 10.286-2.057 20.571-4.114 30.857zM1147.886 1080.743l94.629-298.286h-553.371v327.086h417.6c18.514 0 34.971-10.286 41.143-28.8zM181.029 1082.8c6.171 16.457 22.629 28.8 41.143 28.8h405.257v-327.086h-553.371l106.971 298.286zM1211.657-30.114h-1106.743c-24.686 0-43.2 18.514-43.2 43.2v707.657h1193.143v-709.714c0-22.629-18.514-41.143-43.2-41.143z" />
28
+ <glyph unicode="&#xeaa0;" glyph-name="image" horiz-adv-x="1317" d="M1180.8 1198h-1045.029c-28.8 0-51.429-22.629-51.429-49.371v-1215.771c0-28.8 22.629-49.371 51.429-49.371h1045.029c26.743 0 49.371 22.629 49.371 49.371v1215.771c2.057 26.743-20.571 49.371-49.371 49.371zM1170.514 1136.286v-664.457c-18.514-10.286-37.029-22.629-53.486-34.971-30.857-20.571-61.714-47.314-90.514-72-82.286-72-160.457-141.943-267.429-102.857-20.571 8.229-43.2 24.686-63.771 43.2l-8.229 8.229c-51.429 41.143-106.971 86.4-176.914 106.971-115.2 34.971-220.114-30.857-312.686-90.514-18.514-12.343-34.971-22.629-53.486-32.914v839.314h1026.514zM146.057-56.857v281.829c2.057 2.057 4.114 4.114 6.171 4.114h2.057c26.743 14.4 53.486 30.857 78.171 47.314 84.343 53.486 172.8 109.029 261.257 82.286 57.6-16.457 106.971-57.6 154.286-96.686l8.229-6.171c22.629-20.571 49.371-43.2 82.286-53.486 28.8-10.286 57.6-16.457 82.286-16.457 98.743 0 176.914 67.886 246.857 129.6 28.8 24.686 55.543 49.371 84.343 67.886l18.514 12.343v-452.571h-1024.457zM829.029 566.457c96.686 0 172.8 78.171 172.8 172.8s-78.171 172.8-172.8 172.8-172.8-78.171-172.8-172.8 78.171-172.8 172.8-172.8zM829.029 850.343c61.714 0 111.086-49.371 111.086-111.086s-49.371-111.086-111.086-111.086-111.086 49.371-111.086 111.086 49.371 111.086 111.086 111.086z" />
29
+ <glyph unicode="&#xeaa9;" glyph-name="analyzer" horiz-adv-x="1317" d="M30.857 844.171c16.457 0 30.857 14.4 30.857 30.857v218.057h216c16.457 0 30.857 14.4 30.857 30.857s-14.4 30.857-30.857 30.857h-246.857c-16.457 0-30.857-14.4-30.857-30.857v-246.857c0-18.514 14.4-32.914 30.857-32.914zM1285.714 1154.8h-246.857c-16.457 0-30.857-14.4-30.857-30.857s14.4-30.857 30.857-30.857h216v-216c0-16.457 14.4-30.857 30.857-30.857s30.857 14.4 30.857 30.857v246.857c0 16.457-14.4 30.857-30.857 30.857zM1285.714 235.257c-16.457 0-30.857-14.4-30.857-30.857v-216h-216c-16.457 0-30.857-14.4-30.857-30.857s14.4-30.857 30.857-30.857h246.857c16.457 0 30.857 14.4 30.857 30.857v246.857c0 16.457-14.4 30.857-30.857 30.857zM277.714-11.6h-216v216c0 16.457-14.4 30.857-30.857 30.857s-30.857-14.4-30.857-30.857v-246.857c0-16.457 14.4-30.857 30.857-30.857h246.857c16.457 0 30.857 14.4 30.857 30.857s-14.4 30.857-30.857 30.857zM1084.114 519.143c10.286 12.343 10.286 28.8 0 41.143-8.229 8.229-193.371 218.057-425.829 218.057s-419.657-209.829-425.829-218.057c-10.286-12.343-10.286-28.8 0-41.143 8.229-8.229 193.371-218.057 425.829-218.057s419.657 209.829 425.829 218.057zM658.286 362.8c-166.629 0-310.629 125.486-360 176.914 51.429 49.371 195.429 176.914 360 176.914s310.629-125.486 360-176.914c-49.371-49.371-193.371-176.914-360-176.914zM573.943 539.714c0-47.314 39.086-86.4 84.343-86.4 47.314 0 84.343 39.086 84.343 86.4s-39.086 86.4-84.343 86.4c-47.314 0-84.343-39.086-84.343-86.4zM680.914 539.714c0-12.343-10.286-24.686-22.629-24.686s-22.629 10.286-22.629 24.686 10.286 24.686 22.629 24.686 22.629-12.343 22.629-24.686z" />
30
+ <glyph unicode="&#xeaab;" glyph-name="search" horiz-adv-x="1317" d="M1304.229-7.486l-384.686 312.686c72 90.514 111.086 201.6 111.086 318.857 0 137.829-53.486 267.429-150.171 364.114-201.6 201.6-528.686 201.6-730.286 0-96.686-96.686-150.171-224.229-150.171-362.057s53.486-267.429 150.171-364.114c100.8-100.8 232.457-150.171 364.114-150.171s263.314 49.371 364.114 150.171l386.743-314.743c6.171-4.114 12.343-6.171 18.514-6.171 8.229 0 18.514 4.114 24.686 12.343 12.343 10.286 10.286 28.8-4.114 39.086zM195.429 305.2c-86.4 84.343-133.714 199.543-133.714 320.914s47.314 234.514 133.714 320.914c88.457 88.457 205.714 133.714 320.914 133.714 117.257 0 232.457-45.257 320.914-133.714 86.4-86.4 133.714-199.543 133.714-320.914s-47.314-234.514-133.714-320.914c-176.914-176.914-464.914-176.914-641.829 0z" />
31
+ <glyph unicode="&#xeab3;" glyph-name="star-filled" horiz-adv-x="1317" d="M1285.714 722.8l-411.429 63.771-185.143 390.857c-14.4 26.743-51.429 26.743-63.771 0l-185.143-392.914-411.429-61.714c-28.8-4.114-41.143-43.2-18.514-63.771l298.286-306.514-69.943-429.943c-4.114-28.8 24.686-53.486 51.429-37.029l368.229 201.6 370.286-199.543c24.686-14.4 55.543 8.229 51.429 37.029l-72 427.886 296.229 306.514c22.629 20.571 12.343 59.657-18.514 63.771z" />
32
+ <glyph unicode="&#xeab5;" glyph-name="star" horiz-adv-x="1317" d="M1310.4 702.229c-10.286 28.8-34.971 49.371-63.771 55.543l-355.886 55.543-160.457 337.371c-12.343 28.8-41.143 47.314-72 47.314s-57.6-18.514-72-47.314l-160.457-339.429-355.886-57.6c-28.8-4.114-53.486-26.743-63.771-55.543-10.286-30.857-2.057-63.771 18.514-86.4l259.2-265.371-59.657-370.286c-6.171-32.914 8.229-63.771 32.914-82.286 14.4-10.286 28.8-14.4 45.257-14.4 12.343 0 26.743 4.114 37.029 10.286l318.857 174.857 318.857-172.8c26.743-14.4 57.6-12.343 82.286 4.114 26.743 18.514 39.086 49.371 32.914 82.286l-59.657 372.343 257.143 263.314c24.686 24.686 30.857 57.6 20.571 88.457zM1246.629 659.029l-261.257-267.429c-12.343-12.343-16.457-28.8-14.4-45.257l61.714-376.457c2.057-12.343-6.171-20.571-8.229-22.629-4.114-2.057-10.286-6.171-18.514-2.057l-325.029 174.857c-14.4 8.229-32.914 8.229-47.314 0l-322.971-176.914c-8.229-4.114-14.4-2.057-18.514 2.057-2.057 2.057-10.286 8.229-8.229 22.629l59.657 374.4c2.057 16.457-2.057 32.914-14.4 45.257l-261.257 267.429c-8.229 8.229-6.171 20.571-4.114 22.629 2.057 4.114 4.114 12.343 14.4 14.4l362.057 57.6c16.457 2.057 30.857 12.343 37.029 28.8l162.514 343.543c6.171 12.343 14.4 14.4 18.514 14.4s12.343-2.057 16.457-10.286l162.514-343.543c8.229-14.4 20.571-26.743 37.029-28.8l362.057-57.6c10.286-2.057 14.4-10.286 14.4-14.4 2.057-2.057 6.171-12.343-4.114-22.629z" />
33
+ <glyph unicode="&#xeaba;" glyph-name="trash" horiz-adv-x="1317" d="M1042.971 1039.6h-197.486v63.771c0 51.429-43.2 94.629-94.629 94.629h-183.086c-51.429 0-94.629-43.2-94.629-94.629v-63.771h-197.486c-51.429 0-92.571-41.143-92.571-92.571v-78.171c0-43.2 30.857-80.229 69.943-90.514l39.086-808.457c2.057-51.429 43.2-90.514 94.629-90.514h547.2c51.429 0 92.571 39.086 94.629 90.514l39.086 808.457c41.143 10.286 69.943 45.257 69.943 90.514v78.171c-2.057 51.429-45.257 92.571-94.629 92.571zM532.8 1103.371c0 18.514 14.4 32.914 32.914 32.914h183.086c18.514 0 32.914-14.4 32.914-32.914v-63.771h-248.914v63.771zM964.8-23.943c0-18.514-14.4-30.857-32.914-30.857h-547.2c-18.514 0-32.914 14.4-32.914 30.857l-39.086 802.286h689.143l-37.029-802.286zM1073.829 868.857c0-16.457-14.4-30.857-30.857-30.857h-769.371c-16.457 0-30.857 14.4-30.857 30.857v78.171c0 16.457 14.4 30.857 30.857 30.857h767.314c16.457 0 30.857-14.4 30.857-30.857v-78.171zM658.286 541.771c-16.457 0-30.857-14.4-30.857-30.857v-345.6c0-16.457 14.4-30.857 30.857-30.857s30.857 14.4 30.857 30.857v345.6c0 16.457-14.4 30.857-30.857 30.857zM866.057 496.514c-16.457 0-30.857-12.343-32.914-28.8l-14.4-257.143c0-16.457 12.343-30.857 28.8-32.914h2.057c16.457 0 30.857 12.343 30.857 28.8l14.4 259.2c0 16.457-12.343 30.857-28.8 30.857zM448.457 496.514c-16.457-2.057-30.857-16.457-28.8-32.914l16.457-259.2c0-16.457 14.4-28.8 30.857-28.8h2.057c16.457 2.057 30.857 16.457 28.8 32.914l-16.457 259.2c0 18.514-14.4 30.857-32.914 28.8z" />
34
+ <glyph unicode="&#xeac4;" glyph-name="users" horiz-adv-x="1317" d="M409.371 619.943c129.6 0 232.457 100.8 232.457 226.286s-104.914 226.286-232.457 226.286-232.457-100.8-232.457-226.286 104.914-226.286 232.457-226.286zM409.371 1010.8c94.629 0 170.743-74.057 170.743-164.571s-76.114-164.571-170.743-164.571c-94.629 0-170.743 74.057-170.743 164.571s76.114 164.571 170.743 164.571zM973.029 515.029c109.029 0 197.486 86.4 197.486 193.371s-88.457 193.371-197.486 193.371-197.486-86.4-197.486-193.371c-2.057-106.971 86.4-193.371 197.486-193.371zM973.029 838c76.114 0 135.771-59.657 135.771-131.657s-61.714-131.657-135.771-131.657-135.771 59.657-135.771 131.657c-2.057 72 59.657 131.657 135.771 131.657zM981.257 451.257h-20.571c-80.229 0-156.343-28.8-216-80.229-69.943 96.686-183.086 160.457-312.686 160.457h-47.314c-211.886 0-384.686-172.8-384.686-384.686v-78.171c0-34.971 28.8-63.771 63.771-63.771h1195.2c32.914 0 57.6 26.743 57.6 57.6v53.486c0 187.2-150.171 335.314-335.314 335.314zM61.714 68.629v78.171c0 178.971 146.057 325.029 325.029 325.029h47.314c178.971 0 325.029-146.057 325.029-325.029v-78.171s0-2.057-2.057-2.057h-12.343l-682.971 2.057zM1254.857 68.629h-436.114v80.229c0 61.714-14.4 119.314-41.143 170.743 49.371 45.257 115.2 72 185.143 72h20.571c148.114-2.057 271.543-123.429 271.543-273.6v-49.371z" />
35
+ <glyph unicode="&#xeb6a;" glyph-name="images" horiz-adv-x="1317" d="M458.743 338.114c63.771 0 117.257 51.429 117.257 117.257s-51.429 117.257-117.257 117.257-117.257-51.429-117.257-117.257 51.429-117.257 117.257-117.257zM458.743 508.857c30.857 0 55.543-24.686 55.543-55.543s-24.686-55.543-55.543-55.543-55.543 24.686-55.543 55.543 24.686 55.543 55.543 55.543zM1273.371 1198h-660.343c-24.686 0-43.2-18.514-43.2-43.2v-413.486h-526.629c-24.686 0-43.2-18.514-43.2-43.2v-773.486c0-24.686 18.514-43.2 43.2-43.2h660.343c22.629 0 43.2 18.514 43.2 43.2v413.486h526.629c24.686 0 43.2 18.514 43.2 43.2v773.486c0 24.686-18.514 43.2-43.2 43.2zM631.543 1136.286h623.314v-423.771c-20.571-10.286-41.143-20.571-49.371-26.743-20.571-14.4-39.086-30.857-57.6-47.314-59.657-51.429-100.8-82.286-158.4-61.714-10.286 4.114-22.629 12.343-32.914 22.629l-6.171 4.114c-32.914 26.743-69.943 57.6-115.2 69.943-28.8 8.229-55.543 8.229-86.4 2.057v22.629c0 24.686-18.514 43.2-43.2 43.2h-69.943v394.971zM685.029 679.6v-417.6c-10.286-6.171-26.743-18.514-49.371-32.914-20.571-14.4-39.086-30.857-57.6-47.314-59.657-51.429-100.8-82.286-158.4-61.714-12.343 4.114-24.686 14.4-37.029 24.686l-4.114 4.114c-32.914 26.743-69.943 55.543-115.2 67.886-76.114 22.629-141.943-16.457-201.6-53.486v514.286h623.314zM61.714-56.857v150.171c10.286 6.171 18.514 12.343 28.8 16.457 53.486 32.914 104.914 65.829 156.343 49.371 32.914-10.286 63.771-34.971 92.571-57.6l4.114-4.114c14.4-12.343 32.914-28.8 55.543-34.971 20.571-8.229 39.086-10.286 55.543-10.286 67.886 0 119.314 45.257 162.514 84.343 18.514 16.457 34.971 30.857 51.429 41.143 6.171 4.114 10.286 6.171 14.4 10.286v-244.8h-621.257zM746.743 399.829v211.886c24.686 8.229 47.314 10.286 69.943 4.114 34.971-10.286 65.829-34.971 94.629-59.657l6.171-4.114c14.4-12.343 30.857-26.743 53.486-32.914 20.571-8.229 39.086-10.286 55.543-10.286 65.829 0 119.314 45.257 162.514 84.343 18.514 16.457 34.971 30.857 53.486 43.2 2.057 2.057 8.229 4.114 14.4 8.229v-242.743h-510.171zM1028.571 794.8c63.771 0 117.257 51.429 117.257 117.257s-53.486 115.2-117.257 115.2-117.257-51.429-117.257-117.257 53.486-115.2 117.257-115.2zM1028.571 965.543c30.857 0 55.543-24.686 55.543-55.543s-24.686-55.543-55.543-55.543-55.543 24.686-55.543 55.543 24.686 55.543 55.543 55.543z" />
36
+ <glyph unicode="&#xeb70;" glyph-name="redirection" horiz-adv-x="1317" d="M1304.229 231.143l-181.029 185.143c-12.343 12.343-30.857 12.343-43.2 0s-12.343-30.857 0-43.2l152.229-156.343h-255.086l-248.914 312.686 248.914 310.629h232.457l-131.657-135.771c-12.343-12.343-12.343-30.857 0-43.2 6.171-6.171 14.4-8.229 20.571-8.229 8.229 0 16.457 4.114 22.629 10.286l181.029 187.2c16.457 18.514 16.457 47.314 0 65.829l-181.029 187.2c-12.343 12.343-30.857 12.343-43.2 0s-12.343-30.857 0-43.2l150.171-154.286h-265.371c-10.286 0-18.514-4.114-24.686-12.343l-248.914-314.743-248.914 312.686c-6.171 8.229-14.4 12.343-24.686 12.343h-384.686c-16.457-2.057-30.857-14.4-30.857-32.914s14.4-30.857 30.857-30.857h370.286l248.914-310.629-248.914-310.629h-370.286c-16.457 0-30.857-14.4-30.857-30.857s14.4-30.857 30.857-30.857h384.686c10.286 0 18.514 4.114 24.686 12.343l248.914 312.686 248.914-312.686c6.171-8.229 14.4-12.343 24.686-12.343h246.857l-129.6-133.714c-12.343-12.343-12.343-30.857 0-43.2 6.171-6.171 14.4-8.229 20.571-8.229 8.229 0 16.457 4.114 22.629 10.286l181.029 187.2c16.457 14.4 16.457 43.2 0 61.714z" />
37
+ <glyph unicode="&#xeb73;" glyph-name="video" horiz-adv-x="1317" d="M1162.286 1198h-1008c-84.343 0-154.286-69.943-154.286-154.286v-1005.943c0-86.4 69.943-156.343 154.286-156.343h1005.943c84.343 0 154.286 69.943 154.286 154.286v1008c2.057 84.343-67.886 154.286-152.229 154.286zM308.571 570.571h-246.857v257.143h246.857v-257.143zM61.714 508.857h246.857v-257.143h-246.857v257.143zM370.286 1136.286h576v-1193.143h-576v1193.143zM1254.857 570.571h-246.857v257.143h246.857v-257.143zM1008 508.857h246.857v-257.143h-246.857v257.143zM1254.857 1043.714v-154.286h-246.857v246.857h154.286c51.429 0 92.571-41.143 92.571-92.571zM154.286 1136.286h154.286v-246.857h-246.857v154.286c0 51.429 41.143 92.571 92.571 92.571zM61.714 35.714v154.286h246.857v-246.857h-154.286c-51.429 0-92.571 41.143-92.571 92.571zM1162.286-56.857h-154.286v246.857h246.857v-154.286c0-51.429-41.143-92.571-92.571-92.571zM826.971 566.457l-306.514 187.2c-10.286 6.171-20.571 6.171-30.857 0s-16.457-16.457-16.457-26.743v-372.343c0-10.286 6.171-20.571 16.457-26.743 4.114-2.057 10.286-4.114 14.4-4.114 6.171 0 10.286 2.057 16.457 4.114l306.514 187.2c10.286 4.114 16.457 14.4 16.457 24.686s-6.171 20.571-16.457 26.743zM534.857 408.057v263.314l218.057-131.657-218.057-131.657z" />
38
+ <glyph unicode="&#xeb87;" glyph-name="analytics" horiz-adv-x="1317" d="M1285.714-56.857h-189.257v752.914c0 16.457-14.4 30.857-30.857 30.857s-30.857-14.4-30.857-30.857v-752.914h-331.2v538.971c0 16.457-14.4 30.857-30.857 30.857s-30.857-14.4-30.857-30.857v-538.971h-316.8v327.086c0 16.457-14.4 30.857-30.857 30.857s-30.857-14.4-30.857-30.857v-327.086h-201.6v1224c0 16.457-14.4 30.857-30.857 30.857s-30.857-14.4-30.857-30.857v-1254.857c0-16.457 14.4-30.857 30.857-30.857h1254.857c16.457 0 30.857 14.4 30.857 30.857s-14.4 30.857-30.857 30.857zM294.171 383.371c59.657 0 106.971 47.314 106.971 106.971 0 10.286-2.057 18.514-4.114 26.743l203.657 127.543c18.514-16.457 45.257-28.8 72-28.8 59.657 0 106.971 47.314 106.971 106.971 0 10.286-2.057 20.571-6.171 30.857l207.771 90.514c20.571-24.686 49.371-41.143 84.343-41.143 59.657 0 106.971 47.314 106.971 106.971s-47.314 106.971-106.971 106.971-106.971-47.314-106.971-106.971v-8.229l-220.114-94.629c-18.514 14.4-41.143 24.686-65.829 24.686-59.657 0-106.971-47.314-106.971-106.971 0-8.229 2.057-18.514 4.114-26.743l-203.657-127.543c-18.514 16.457-43.2 26.743-69.943 26.743-59.657 0-106.971-47.314-106.971-106.971-2.057-59.657 45.257-106.971 104.914-106.971zM1065.6 959.371c24.686 0 45.257-20.571 45.257-45.257s-20.571-45.257-45.257-45.257-45.257 20.571-45.257 45.257 20.571 45.257 45.257 45.257zM672.686 770.114c24.686 0 45.257-20.571 45.257-45.257s-20.571-45.257-45.257-45.257c-24.686 0-45.257 20.571-45.257 45.257s20.571 45.257 45.257 45.257zM294.171 535.6c24.686 0 45.257-20.571 45.257-45.257s-20.571-45.257-45.257-45.257-45.257 20.571-45.257 45.257c0 24.686 20.571 45.257 45.257 45.257z" />
39
+ <glyph unicode="&#xeb97;" glyph-name="schema" horiz-adv-x="1317" d="M1285.714 1029.314h-1254.857c-16.457 0-30.857-14.4-30.857-30.857v-917.486c0-16.457 14.4-30.857 30.857-30.857h1254.857c16.457 0 30.857 14.4 30.857 30.857v917.486c0 16.457-14.4 30.857-30.857 30.857zM1254.857 967.6v-193.371h-1193.143v193.371h1193.143zM61.714 111.829v598.629h1193.143v-598.629h-1193.143zM742.629 866.8c0-23.859 19.341-43.2 43.2-43.2s43.2 19.341 43.2 43.2v0c0 23.859-19.341 43.2-43.2 43.2s-43.2-19.341-43.2-43.2v0M913.371 866.8c0-23.859 19.341-43.2 43.2-43.2s43.2 19.341 43.2 43.2v0c0 23.859-19.341 43.2-43.2 43.2s-43.2-19.341-43.2-43.2v0M1082.057 866.8c0-23.859 19.341-43.2 43.2-43.2s43.2 19.341 43.2 43.2v0c0 23.859-19.341 43.2-43.2 43.2s-43.2-19.341-43.2-43.2v0M829.029 480.057l-98.743 14.4-45.257 90.514c-4.114 10.286-14.4 16.457-26.743 16.457s-22.629-6.171-26.743-16.457l-45.257-90.514-98.743-14.4c-12.343-2.057-20.571-10.286-24.686-20.571s0-22.629 8.229-30.857l72-69.943-16.457-98.743c-2.057-12.343 2.057-22.629 12.343-30.857 6.171-4.114 12.343-6.171 18.514-6.171 4.114 0 10.286 2.057 14.4 4.114l86.4 45.257 88.457-47.314c10.286-6.171 22.629-4.114 32.914 2.057s14.4 18.514 12.343 30.857l-16.457 98.743 72 69.943c8.229 8.229 12.343 20.571 8.229 30.857-4.114 12.343-14.4 20.571-26.743 22.629zM720 389.543c-8.229-6.171-10.286-16.457-8.229-26.743l8.229-53.486-47.314 24.686c-8.229 4.114-20.571 4.114-28.8 0l-47.314-24.686 8.229 53.486c2.057 10.286-2.057 20.571-8.229 26.743l-39.086 37.029 53.486 8.229c10.286 2.057 18.514 8.229 22.629 16.457l24.686 49.371 24.686-49.371c4.114-8.229 12.343-16.457 22.629-16.457l53.486-8.229-39.086-37.029z" />
40
+ <glyph unicode="&#xeb99;" glyph-name="adsense" horiz-adv-x="1317" d="M1285.714 1113.657h-1254.857c-16.457 0-30.857-14.4-30.857-30.857v-660.343c0-16.457 14.4-30.857 30.857-30.857h170.743v-394.971c0-16.457 14.4-30.857 30.857-30.857s30.857 14.4 30.857 30.857v394.971h364.114v-394.971c0-16.457 14.4-30.857 30.857-30.857s30.857 14.4 30.857 30.857v394.971h364.114v-394.971c0-16.457 14.4-30.857 30.857-30.857s30.857 14.4 30.857 30.857v394.971h170.743c16.457 0 30.857 14.4 30.857 30.857v660.343c0 16.457-14.4 30.857-30.857 30.857zM1254.857 453.314h-1193.143v598.629h1193.143v-598.629zM306.514 584.971c14.4-8.229 32.914-2.057 41.143 14.4l39.086 78.171h168.686l37.029-78.171c6.171-10.286 16.457-16.457 26.743-16.457 4.114 0 8.229 0 14.4 4.114 14.4 8.229 22.629 26.743 14.4 41.143l-150.171 308.571c-6.171 10.286-16.457 16.457-26.743 16.457s-22.629-6.171-26.743-16.457l-150.171-308.571c-10.286-16.457-4.114-34.971 12.343-43.2zM469.029 852.4l55.543-113.143h-109.029l53.486 113.143zM792 578.8h51.429c100.8 0 183.086 82.286 183.086 183.086v10.286c0 100.8-82.286 183.086-183.086 183.086h-51.429c-16.457 0-30.857-14.4-30.857-30.857v-316.8c0-16.457 14.4-28.8 30.857-28.8zM822.857 895.6h20.571c67.886 0 121.371-55.543 121.371-121.371v-10.286c0-67.886-55.543-121.371-121.371-121.371h-20.571v253.029z" />
41
+ <glyph unicode="&#xeb9d;" glyph-name="tick" horiz-adv-x="1317" d="M458.743 115.943c-20.571 0-43.2 8.229-59.657 24.686l-390.857 382.629c-12.343 12.343-12.343 30.857 0 43.2s30.857 12.343 43.2 0l390.857-382.629c8.229-8.229 22.629-8.229 30.857 0l789.943 771.429c12.343 12.343 30.857 12.343 43.2 0s12.343-30.857 0-43.2l-787.886-771.429c-16.457-16.457-37.029-24.686-59.657-24.686z" />
42
+ <glyph unicode="&#xeb9f;" glyph-name="circle-plus" horiz-adv-x="1317" d="M886.629 572.629h-197.486v197.486c0 16.457-14.4 30.857-30.857 30.857s-30.857-14.4-30.857-30.857v-197.486h-197.486c-16.457 0-30.857-14.4-30.857-30.857s14.4-30.857 30.857-30.857h197.486v-197.486c0-16.457 14.4-30.857 30.857-30.857s30.857 14.4 30.857 30.857v197.486h197.486c16.457 0 30.857 14.4 30.857 30.857s-14.4 30.857-30.857 30.857zM658.286 1198c-362.057 0-658.286-296.229-658.286-658.286s296.229-658.286 658.286-658.286 658.286 296.229 658.286 658.286-296.229 658.286-658.286 658.286zM658.286-56.857c-329.143 0-596.571 267.429-596.571 596.571s267.429 596.571 596.571 596.571 596.571-267.429 596.571-596.571-267.429-596.571-596.571-596.571z" />
43
+ <glyph unicode="&#xeba4;" glyph-name="eye" horiz-adv-x="1317" d="M658.286 393.657c-80.229 0-144 65.829-144 146.057s65.829 146.057 144 146.057c80.229 0 144-65.829 144-146.057s-63.771-146.057-144-146.057zM658.286 624.057c-45.257 0-82.286-37.029-82.286-84.343s37.029-84.343 82.286-84.343 82.286 37.029 82.286 84.343-37.029 84.343-82.286 84.343zM658.286 163.257c-267.429 0-510.171 133.714-652.114 355.886-8.229 12.343-8.229 28.8 0 43.2 141.943 222.171 384.686 353.829 652.114 353.829s510.171-133.714 652.114-355.886c8.229-12.343 8.229-28.8 0-43.2-141.943-220.114-384.686-353.829-652.114-353.829zM65.829 539.714c131.657-197.486 351.771-314.743 592.457-314.743s460.8 117.257 592.457 314.743c-131.657 197.486-351.771 314.743-592.457 314.743s-460.8-117.257-592.457-314.743z" />
44
+ <glyph unicode="&#xebac;" glyph-name="heart-filled" horiz-adv-x="1317" d="M1215.771 1014.914c-133.714 133.714-353.829 133.714-487.543 0l-72-72-72 72c-67.886 65.829-154.286 98.743-242.743 98.743s-174.857-30.857-240.686-98.743c-133.714-133.714-133.714-355.886 0-489.6l557.486-561.6 557.486 563.657c67.886 67.886 100.8 154.286 100.8 242.743s-34.971 178.971-100.8 244.8z" />
45
+ <glyph unicode="&#xebb4;" glyph-name="info" horiz-adv-x="1317" d="M826.971-56.857h-137.829v975.086c0 47.314-39.086 86.4-86.4 86.4h-111.086c-16.457 0-30.857-14.4-30.857-30.857s14.4-30.857 30.857-30.857h111.086c14.4 0 24.686-10.286 24.686-24.686v-975.086h-137.829c-16.457 0-30.857-14.4-30.857-30.857s14.4-30.857 30.857-30.857h335.314c16.457 0 30.857 14.4 30.857 30.857s-12.343 30.857-28.8 30.857zM602.743 1142.457c0-30.675 24.867-55.543 55.543-55.543s55.543 24.867 55.543 55.543v0c0 30.675-24.867 55.543-55.543 55.543s-55.543-24.867-55.543-55.543v0" />
46
+ <glyph unicode="&#xebbc;" glyph-name="howto" horiz-adv-x="1317" d="M306.514 1045.771h-275.657c-16.457 0-30.857-14.4-30.857-30.857v-275.657c0-16.457 14.4-30.857 30.857-30.857h275.657c16.457 0 30.857 14.4 30.857 30.857v275.657c0 16.457-12.343 30.857-30.857 30.857zM275.657 768.057h-213.943v216h213.943v-216zM306.514 373.086h-275.657c-16.457 0-30.857-14.4-30.857-30.857v-275.657c0-16.457 14.4-30.857 30.857-30.857h275.657c16.457 0 30.857 14.4 30.857 30.857v275.657c0 16.457-12.343 30.857-30.857 30.857zM275.657 95.371h-213.943v216h213.943v-216zM584.229 940.857h701.486c16.457 0 30.857 14.4 30.857 30.857s-14.4 30.857-30.857 30.857h-701.486c-16.457 0-30.857-14.4-30.857-30.857s14.4-30.857 30.857-30.857zM1285.714 811.257h-701.486c-16.457 0-30.857-14.4-30.857-30.857s14.4-30.857 30.857-30.857h701.486c16.457 0 30.857 14.4 30.857 30.857s-14.4 30.857-30.857 30.857zM1285.714 329.886h-701.486c-16.457 0-30.857-14.4-30.857-30.857s14.4-30.857 30.857-30.857h701.486c16.457 0 30.857 14.4 30.857 30.857s-14.4 30.857-30.857 30.857zM1285.714 138.571h-701.486c-16.457 0-30.857-14.4-30.857-30.857s14.4-30.857 30.857-30.857h701.486c16.457 0 30.857 14.4 30.857 30.857s-14.4 30.857-30.857 30.857z" />
47
+ <glyph unicode="&#xebbd;" glyph-name="faq" horiz-adv-x="1317" d="M240.686 1158.914h-189.257c-26.743 0-51.429-24.686-51.429-51.429v-189.257c0-28.8 22.629-51.429 51.429-51.429h189.257c28.8 0 51.429 22.629 51.429 51.429v189.257c0 26.743-22.629 51.429-51.429 51.429zM230.4 926.457h-168.686v170.743h168.686v-170.743zM518.4 979.943h767.314c16.457 0 30.857 14.4 30.857 30.857s-14.4 30.857-30.857 30.857h-767.314c-16.457 0-30.857-14.4-30.857-30.857s12.343-30.857 30.857-30.857zM240.686 698.114h-189.257c-28.8 0-51.429-22.629-51.429-51.429v-189.257c0-28.8 22.629-51.429 51.429-51.429h189.257c28.8 0 51.429 22.629 51.429 51.429v189.257c0 28.8-22.629 51.429-51.429 51.429zM230.4 467.714h-168.686v168.686h168.686v-168.686zM1285.714 582.914h-767.314c-16.457 0-30.857-14.4-30.857-30.857s14.4-30.857 30.857-30.857h767.314c16.457 0 30.857 14.4 30.857 30.857s-14.4 30.857-30.857 30.857zM240.686 214.686h-189.257c-28.8 0-51.429-22.629-51.429-51.429v-189.257c0-28.8 22.629-51.429 51.429-51.429h189.257c28.8 0 51.429 22.629 51.429 51.429v189.257c0 28.8-22.629 51.429-51.429 51.429zM230.4-17.771h-168.686v168.686h168.686v-168.686zM1285.714 99.486h-767.314c-16.457 0-30.857-14.4-30.857-30.857s14.4-30.857 30.857-30.857h767.314c16.457 0 30.857 14.4 30.857 30.857s-14.4 30.857-30.857 30.857z" />
48
+ <glyph unicode="&#xebc8;" glyph-name="music" horiz-adv-x="1317" d="M1283.657 1056.057c-20.571 18.514-47.314 28.8-76.114 26.743l-771.429-59.657c-51.429-4.114-92.571-47.314-92.571-100.8v-676.8c-37.029 24.686-84.343 39.086-139.886 39.086-113.143 0-201.6-63.771-201.6-146.057s88.457-146.057 201.6-146.057c113.143 0 201.6 63.771 201.6 146.057v514.286l849.6 65.829v-415.543c-37.029 24.686-84.343 39.086-139.886 39.086-113.143 0-201.6-63.771-201.6-146.057s88.457-146.057 201.6-146.057 201.6 63.771 201.6 146.057v785.829c0 28.8-12.343 55.543-32.914 74.057zM201.6 58.343c-76.114 0-139.886 39.086-139.886 84.343s63.771 84.343 139.886 84.343 139.886-39.086 139.886-84.343-63.771-84.343-139.886-84.343zM1114.971 115.943c-76.114 0-139.886 39.086-139.886 84.343s63.771 84.343 139.886 84.343 139.886-39.086 139.886-84.343-63.771-84.343-139.886-84.343zM403.2 922.343c0 20.571 16.457 37.029 34.971 39.086l777.6 59.657c10.286 0 18.514-4.114 26.743-10.286 8.229-8.229 12.343-18.514 12.343-28.8v-201.6l-851.657-65.829v207.771z" />
49
+ <glyph unicode="&#xebce;" glyph-name="plus" horiz-adv-x="1317" d="M1285.714 570.571h-596.571v596.571c0 16.457-14.4 30.857-30.857 30.857s-30.857-14.4-30.857-30.857v-596.571h-596.571c-16.457 0-30.857-14.4-30.857-30.857s14.4-30.857 30.857-30.857h596.571v-596.571c0-16.457 14.4-30.857 30.857-30.857s30.857 14.4 30.857 30.857v596.571h596.571c16.457 0 30.857 14.4 30.857 30.857s-14.4 30.857-30.857 30.857z" />
50
+ <glyph unicode="&#xebd2;" glyph-name="help" horiz-adv-x="1317" d="M658.286 1198c-362.057 0-658.286-296.229-658.286-658.286s296.229-658.286 658.286-658.286 658.286 296.229 658.286 658.286-296.229 658.286-658.286 658.286zM658.286-56.857c-329.143 0-596.571 267.429-596.571 596.571s267.429 596.571 596.571 596.571 596.571-267.429 596.571-596.571-267.429-596.571-596.571-596.571zM695.314 967.6c-59.657 10.286-121.371-6.171-166.629-43.2-45.257-39.086-72-94.629-72-154.286 0-22.629 4.114-45.257 12.343-67.886 6.171-16.457 22.629-24.686 39.086-18.514s24.686 22.629 18.514 39.086c-6.171 14.4-8.229 30.857-8.229 47.314 0 41.143 18.514 80.229 49.371 106.971 32.914 26.743 74.057 37.029 115.2 30.857 55.543-10.286 102.857-55.543 113.143-113.143 12.343-65.829-22.629-129.6-84.343-156.343-51.429-20.571-84.343-72-84.343-131.657v-137.829c0-16.457 14.4-30.857 30.857-30.857s30.857 14.4 30.857 30.857v137.829c0 32.914 18.514 63.771 45.257 74.057 88.457 37.029 137.829 127.543 121.371 222.171-12.343 82.286-80.229 150.171-160.457 164.571zM658.286 253.771c-30.857 0-57.6-24.686-57.6-57.6 0-30.857 24.686-57.6 57.6-57.6 30.857 0 57.6 24.686 57.6 57.6s-26.743 57.6-57.6 57.6z" />
51
+ <glyph unicode="&#xebe1;" glyph-name="instant-indexing" horiz-adv-x="1317" d="M1059.429 647.086c-14.4 20.571-37.029 28.8-59.657 22.629l-203.657-51.429 67.886 501.943c4.114 26.743-10.286 49.371-34.971 59.657s-51.429 2.057-67.886-18.514l-501.943-699.429c-14.4-18.514-14.4-43.2-2.057-63.771s34.971-28.8 57.6-24.686l195.429 39.086-57.6-481.371c-2.057-26.743 10.286-49.371 34.971-59.657 6.171-2.057 14.4-4.114 20.571-4.114 18.514 0 34.971 8.229 45.257 22.629l501.943 691.2c16.457 20.571 16.457 45.257 4.114 65.829zM516.343-56.457l55.543 469.029c2.057 18.514-4.114 34.971-18.514 47.314-10.286 10.286-24.686 14.4-39.086 14.4-4.114 0-8.229 0-10.286-2.057l-189.257-37.029 485.486 672.686-65.829-487.543c-2.057-18.514 4.114-37.029 18.514-49.371s32.914-16.457 51.429-12.343l197.486 49.371-485.486-664.457z" />
52
+ <glyph unicode="&#xebe8;" glyph-name="404" horiz-adv-x="1317" d="M1310.4 130.343l-627.429 855.771c-12.343 16.457-39.086 16.457-49.371 0l-627.429-855.771c-6.171-10.286-8.229-22.629-2.057-32.914s16.457-16.457 26.743-16.457h1254.857c12.343 0 22.629 6.171 26.743 16.457 6.171 10.286 4.114 22.629-2.057 32.914zM92.571 142.686l565.714 773.486 565.714-771.429h-1131.429zM627.429 681.657v-228.343c0-16.457 14.4-30.857 30.857-30.857s30.857 14.4 30.857 30.857v228.343c0 16.457-14.4 30.857-30.857 30.857s-30.857-12.343-30.857-30.857zM617.143 282.571c0-22.723 18.42-41.143 41.143-41.143s41.143 18.42 41.143 41.143v0c0 22.723-18.42 41.143-41.143 41.143s-41.143-18.42-41.143-41.143v0" />
53
+ <glyph unicode="&#xebea;" glyph-name="cross" horiz-adv-x="1317" d="M701.486 539.714l606.857 604.8c12.343 12.343 12.343 30.857 0 43.2s-30.857 12.343-43.2 0l-606.857-604.8-604.8 606.857c-12.343 10.286-32.914 10.286-45.257 0-10.286-12.343-10.286-32.914 0-45.257l606.857-604.8-606.857-604.8c-12.343-12.343-12.343-30.857 0-43.2 6.171-8.229 14.4-10.286 22.629-10.286s16.457 2.057 22.629 8.229l604.8 606.857 604.8-604.8c6.171-6.171 14.4-8.229 22.629-8.229s16.457 2.057 22.629 8.229c12.343 12.343 12.343 30.857 0 43.2l-606.857 604.8z" />
54
+ <glyph unicode="&#xec3b;" glyph-name="recipe" horiz-adv-x="1317" d="M1059.429 899.714c-39.086 0-78.171-10.286-113.143-26.743-6.171 156.343-133.714 281.829-290.057 281.829s-283.886-123.429-290.057-279.771c-32.914 16.457-69.943 24.686-106.971 24.686-144 0-259.2-115.2-259.2-259.2 0-131.657 98.743-240.686 226.286-257.143v-429.943c0-8.229 4.114-18.514 10.286-22.629 6.171-6.171 16.457-8.229 24.686-6.171l185.143 28.8c139.886 22.629 283.886 22.629 423.771 0l185.143-28.8h4.114c8.229 0 14.4 2.057 20.571 8.229s10.286 14.4 10.286 22.629v427.886c127.543 14.4 226.286 125.486 226.286 257.143 0 144-115.2 259.2-257.143 259.2zM880.457 15.143c-148.114 22.629-296.229 22.629-444.343 0l-148.114-24.686v127.543l158.4 24.686c139.886 22.629 283.886 22.629 423.771 0l158.4-24.686v-127.543l-148.114 24.686zM1059.429 445.086c-16.457 0-30.857-14.4-30.857-30.857v-232.457l-148.114 22.629c-6.171 0-10.286 2.057-16.457 2.057v176.914c0 16.457-14.4 30.857-30.857 30.857s-30.857-14.4-30.857-30.857v-168.686c-96.686 10.286-193.371 10.286-290.057 0v168.686c0 16.457-14.4 30.857-30.857 30.857s-28.8-14.4-28.8-30.857v-176.914c-6.171 0-10.286-2.057-16.457-2.057l-148.114-24.686v234.514c0 16.457-14.4 30.857-30.857 30.857-106.971 0-195.429 88.457-195.429 197.486s88.457 197.486 195.429 197.486c45.257 0 86.4-14.4 123.429-43.2 10.286-8.229 24.686-8.229 34.971-2.057s16.457 18.514 14.4 32.914c-2.057 12.343-4.114 24.686-4.114 39.086 0 127.543 102.857 232.457 228.343 232.457s228.343-102.857 228.343-232.457c0-14.4-2.057-30.857-4.114-43.2s4.114-26.743 14.4-32.914c12.343-6.171 26.743-4.114 34.971 4.114 34.971 30.857 82.286 49.371 129.6 49.371 106.971 0 195.429-88.457 195.429-197.486 2.057-113.143-86.4-201.6-193.371-201.6z" />
55
+ <glyph unicode="&#xec56;" glyph-name="restaurant" horiz-adv-x="1317" d="M1254.857 835.943l-195.429 345.6c-6.171 10.286-16.457 16.457-26.743 16.457h-750.857c-10.286 0-20.571-6.171-26.743-16.457l-193.371-345.6c-2.057-4.114-4.114-10.286-4.114-14.4v-909.257c0-16.457 14.4-30.857 30.857-30.857h1139.657c16.457 0 30.857 14.4 30.857 30.857v909.257c0 6.171-2.057 10.286-4.114 14.4zM341.486 792.743c-2.057-59.657-51.429-109.029-111.086-109.029s-109.029 49.371-111.086 109.029h222.171zM911.314 792.743c-2.057-59.657-51.429-109.029-111.086-109.029s-109.029 49.371-111.086 109.029h222.171zM1197.257 792.743c-2.057-59.657-51.429-109.029-111.086-109.029s-109.029 49.371-111.086 109.029h222.171zM300.343 1136.286h713.829l158.4-281.829h-1030.629l158.4 281.829zM627.429 792.743c-2.057-59.657-51.429-109.029-111.086-109.029s-109.029 49.371-111.086 109.029h222.171zM347.657-56.857v394.971h166.629v-394.971h-166.629zM576-56.857v425.829c0 16.457-14.4 30.857-30.857 30.857h-228.343c-16.457 0-30.857-14.4-30.857-30.857v-425.829h-166.629v720c30.857-24.686 67.886-41.143 111.086-41.143 59.657 0 111.086 30.857 141.943 76.114 30.857-45.257 84.343-76.114 141.943-76.114 59.657 0 111.086 28.8 141.943 74.057 30.857-45.257 82.286-74.057 141.943-74.057s111.086 30.857 141.943 76.114c30.857-45.257 84.343-76.114 141.943-76.114 43.2 0 80.229 14.4 111.086 41.143v-720h-617.143zM1001.829 399.829h-170.743c-16.457 0-30.857-14.4-30.857-30.857v-170.743c0-16.457 14.4-30.857 30.857-30.857h170.743c16.457 0 30.857 14.4 30.857 30.857v170.743c0 16.457-14.4 30.857-30.857 30.857zM970.971 229.086h-109.029v109.029h109.029v-109.029z" />
56
+ <glyph unicode="&#xec64;" glyph-name="post-format" horiz-adv-x="1317" d="M1156.114 953.2l-275.657 236.571c-6.171 4.114-12.343 8.229-20.571 8.229h-678.857c-18.514 0-32.914-14.4-32.914-30.857v-1254.857c0-16.457 14.4-30.857 30.857-30.857h481.371c16.457 0 30.857 14.4 30.857 30.857s-12.343 30.857-28.8 30.857h-452.571v1193.143h637.714l257.143-220.114v-973.029h-26.743c-16.457 0-30.857-14.4-30.857-30.857s14.4-30.857 30.857-30.857h57.6c16.457 0 30.857 14.4 30.857 30.857v1018.286c2.057 8.229-2.057 16.457-10.286 22.629zM382.629 907.943h298.286c16.457 0 30.857 14.4 30.857 30.857s-14.4 30.857-30.857 30.857h-298.286c-16.457 0-30.857-14.4-30.857-30.857s14.4-30.857 30.857-30.857zM382.629 716.629h510.171c16.457 0 30.857 14.4 30.857 30.857s-14.4 30.857-30.857 30.857h-510.171c-16.457 0-30.857-14.4-30.857-30.857s14.4-30.857 30.857-30.857zM382.629 502.686h510.171c16.457 0 30.857 14.4 30.857 30.857s-14.4 30.857-30.857 30.857h-510.171c-16.457 0-30.857-14.4-30.857-30.857s14.4-30.857 30.857-30.857zM866.057 389.543c-76.114 0-137.829-61.714-137.829-137.829 0-32.914 12.343-63.771 32.914-88.457v-253.029c0-10.286 6.171-20.571 14.4-26.743 10.286-6.171 20.571-6.171 30.857 0l59.657 32.914 59.657-32.914c4.114-2.057 10.286-4.114 14.4-4.114 6.171 0 10.286 2.057 16.457 4.114 10.286 6.171 14.4 16.457 14.4 26.743v255.086c20.571 24.686 30.857 53.486 30.857 88.457 0 74.057-59.657 135.771-135.771 135.771zM866.057 327.829c41.143 0 76.114-32.914 76.114-76.114 0-41.143-32.914-76.114-76.114-76.114s-76.114 34.971-76.114 76.114c0 43.2 34.971 76.114 76.114 76.114zM880.457-17.771c-10.286 6.171-20.571 6.171-30.857 0l-26.743-16.457v156.343c14.4-4.114 28.8-8.229 43.2-8.229s30.857 2.057 43.2 8.229v-156.343l-28.8 16.457z" />
57
+ <glyph unicode="&#xec66;" glyph-name="service" horiz-adv-x="1317" d="M1285.714 1093.086h-1254.857c-16.457 0-30.857-14.4-30.857-30.857v-680.914c0-16.457 14.4-30.857 30.857-30.857h119.314c18.514-61.714 78.171-106.971 146.057-106.971s127.543 45.257 146.057 106.971h429.943c18.514-61.714 78.171-106.971 146.057-106.971 69.943 0 127.543 45.257 146.057 106.971h119.314c16.457 0 30.857 14.4 30.857 30.857v680.914c2.057 16.457-12.343 30.857-28.8 30.857zM296.229 305.2c-49.371 0-90.514 39.086-90.514 88.457s41.143 88.457 90.514 88.457 90.514-39.086 90.514-88.457-39.086-88.457-90.514-88.457zM1020.343 305.2c-49.371 0-90.514 39.086-90.514 88.457s41.143 88.457 90.514 88.457 90.514-39.086 90.514-88.457-41.143-88.457-90.514-88.457zM1254.857 412.171h-82.286c-10.286 74.057-74.057 129.6-152.229 129.6s-141.943-57.6-152.229-129.6h-419.657c-10.286 74.057-74.057 129.6-152.229 129.6s-141.943-57.6-152.229-129.6h-82.286v619.2h1193.143v-619.2zM296.229 194.114c-119.314 0-230.4-61.714-292.114-160.457-8.229-14.4-4.114-32.914 10.286-43.2 4.114-4.114 10.286-4.114 16.457-4.114 10.286 0 20.571 6.171 26.743 14.4 49.371 82.286 141.943 131.657 238.629 131.657 98.743 0 189.257-49.371 238.629-131.657 8.229-14.4 28.8-18.514 43.2-10.286s18.514 28.8 10.286 43.2c-61.714 100.8-170.743 160.457-292.114 160.457zM1020.343 194.114c-119.314 0-230.4-61.714-292.114-160.457-8.229-14.4-4.114-32.914 10.286-43.2 14.4-8.229 32.914-4.114 43.2 10.286 49.371 82.286 141.943 131.657 238.629 131.657 98.743 0 189.257-49.371 238.629-131.657 6.171-10.286 16.457-14.4 26.743-14.4 6.171 0 10.286 2.057 16.457 4.114 14.4 8.229 18.514 28.8 10.286 43.2-63.771 100.8-172.8 160.457-292.114 160.457z" />
58
+ <glyph unicode="&#xec70;" glyph-name="course" horiz-adv-x="1317" d="M1296 825.657l-625.371 226.286c-6.171 2.057-14.4 2.057-20.571 0l-629.486-226.286c-12.343-4.114-20.571-16.457-20.571-28.8s8.229-24.686 20.571-28.8l178.971-63.771v-403.2c0-12.343 8.229-24.686 20.571-28.8 185.143-61.714 325.029-88.457 452.571-88.457 67.886 0 131.657 8.229 197.486 20.571v-24.686c-41.143-12.343-72-51.429-72-96.686 0-55.543 45.257-102.857 102.857-102.857s102.857 45.257 102.857 102.857c0 45.257-30.857 84.343-72 96.686v39.086c53.486 14.4 106.971 32.914 166.629 53.486 12.343 4.114 20.571 16.457 20.571 28.8v403.2l176.914 63.771c12.343 4.114 20.571 16.457 20.571 28.8s-10.286 24.686-20.571 28.8zM901.029 39.829c-22.629 0-41.143 18.514-41.143 41.143s18.514 41.143 41.143 41.143 41.143-18.514 41.143-41.143-18.514-41.143-41.143-41.143zM261.257 323.714v357.943l386.743-139.886c4.114-2.057 6.171-2.057 10.286-2.057s6.171 0 10.286 2.057l201.6 72v-347.657c-178.971-39.086-347.657-28.8-608.914 57.6zM1055.314 321.657c-43.2-14.4-84.343-28.8-125.486-39.086v353.829l125.486 45.257v-360zM907.2 694l-164.571 61.714c-16.457 6.171-32.914-2.057-39.086-18.514s2.057-32.914 18.514-39.086l96.686-34.971-160.457-59.657-534.857 193.371 534.857 193.371 534.857-193.371-285.943-102.857z" />
59
+ <glyph unicode="&#xec73;" glyph-name="book" horiz-adv-x="1317" d="M1256.914 1027.257h-528.686c-28.8 0-53.486-10.286-69.943-28.8-18.514 18.514-43.2 28.8-69.943 28.8h-528.686c-32.914 0-59.657-26.743-59.657-59.657v-798.171c0-32.914 26.743-59.657 59.657-59.657h567.771v-26.743c0-16.457 14.4-30.857 30.857-30.857s30.857 14.4 30.857 30.857v26.743h567.771c32.914 0 59.657 26.743 59.657 59.657v798.171c0 32.914-26.743 59.657-59.657 59.657zM61.714 171.486v794.057h526.629c22.629 0 39.086-16.457 39.086-41.143v-752.914h-565.714zM1254.857 171.486h-565.714v752.914c0 22.629 16.457 41.143 39.086 41.143h526.629v-794.057zM429.943 798.914h-228.343c-16.457 0-30.857-14.4-30.857-30.857s14.4-30.857 30.857-30.857h228.343c16.457 0 30.857 14.4 30.857 30.857s-14.4 30.857-30.857 30.857zM886.629 737.2h228.343c16.457 0 30.857 14.4 30.857 30.857s-14.4 30.857-30.857 30.857h-228.343c-16.457 0-30.857-14.4-30.857-30.857s14.4-30.857 30.857-30.857zM886.629 566.457h228.343c16.457 0 30.857 14.4 30.857 30.857s-14.4 30.857-30.857 30.857h-228.343c-16.457 0-30.857-14.4-30.857-30.857s14.4-30.857 30.857-30.857zM429.943 628.171h-228.343c-16.457 0-30.857-14.4-30.857-30.857s14.4-30.857 30.857-30.857h228.343c16.457 0 30.857 14.4 30.857 30.857s-14.4 30.857-30.857 30.857zM429.943 457.429h-228.343c-16.457 0-30.857-14.4-30.857-30.857 0-18.514 14.4-30.857 30.857-30.857h228.343c16.457 0 30.857 14.4 30.857 30.857s-14.4 30.857-30.857 30.857zM886.629 395.714h228.343c16.457 0 30.857 14.4 30.857 30.857s-14.4 30.857-30.857 30.857h-228.343c-16.457 0-30.857-14.4-30.857-30.857 0-18.514 14.4-30.857 30.857-30.857z" />
60
+ <glyph unicode="&#xec76;" glyph-name="social" horiz-adv-x="1317" d="M1265.143 1056.057c-59.657 49.371-150.171 41.143-201.6-18.514-24.686-28.8-34.971-65.829-32.914-104.914 2.057-12.343 4.114-22.629 8.229-34.971l-226.286-131.657c-39.086 67.886-111.086 113.143-193.371 113.143-65.829 0-123.429-28.8-164.571-74.057l-193.371 174.857c14.4 22.629 22.629 47.314 22.629 76.114 0 78.171-63.771 141.943-141.943 141.943s-141.943-63.771-141.943-141.943 63.771-141.943 141.943-141.943c28.8 0 55.543 8.229 78.171 22.629l201.6-183.086c-14.4-28.8-22.629-61.714-22.629-96.686 0-123.429 98.743-222.171 222.171-222.171 8.229 0 16.457 0 24.686 2.057l53.486-195.429c-61.714-30.857-102.857-94.629-102.857-168.686 0-104.914 86.4-191.314 191.314-191.314s191.314 86.4 191.314 191.314-86.4 191.314-191.314 191.314c-10.286 0-18.514 0-28.8-2.057l-51.429 191.314c80.229 32.914 137.829 113.143 137.829 205.714 0 18.514-2.057 34.971-6.171 51.429l236.571 137.829 10.286-10.286c26.743-20.571 57.6-32.914 90.514-32.914h14.4c37.029 4.114 72 22.629 96.686 51.429 45.257 59.657 37.029 150.171-22.629 199.543zM141.943 973.771c-43.2 0-80.229 37.029-80.229 82.286s37.029 80.229 80.229 80.229 80.229-37.029 80.229-80.229-34.971-82.286-80.229-82.286zM915.429 72.743c0-69.943-57.6-129.6-129.6-129.6s-129.6 57.6-129.6 129.6c0 69.943 57.6 129.6 129.6 129.6s129.6-59.657 129.6-129.6zM621.257 496.514c-88.457 0-160.457 72-160.457 160.457s72 160.457 160.457 160.457 160.457-72 160.457-160.457-72-160.457-160.457-160.457zM1236.343 895.6c-14.4-16.457-32.914-26.743-55.543-28.8-20.571-2.057-43.2 4.114-59.657 18.514s-26.743 32.914-28.8 55.543c-2.057 20.571 4.114 43.2 18.514 59.657 16.457 18.514 39.086 28.8 61.714 28.8 18.514 0 37.029-6.171 51.429-18.514 34.971-30.857 41.143-82.286 12.343-115.2z" />
61
+ <glyph unicode="&#xec78;" glyph-name="edit" horiz-adv-x="1317" d="M1314.514 990.229c0 12.343-4.114 24.686-14.4 34.971-26.743 26.743-53.486 53.486-78.171 80.229-24.686 24.686-49.371 47.314-74.057 72-8.229 10.286-18.514 16.457-30.857 18.514-14.4 2.057-26.743-2.057-39.086-10.286l-156.343-156.343h-872.229c-26.743 0-49.371-22.629-49.371-49.371v-1051.2c0-26.743 22.629-49.371 49.371-49.371h1051.2c26.743 0 49.371 22.629 49.371 49.371v876.343l152.229 152.229c8.229 8.229 12.343 20.571 12.343 32.914zM685.029 430.686l-205.714-67.886 67.886 205.714 421.714 421.714 139.886-137.829-423.771-421.714zM1088.229-56.857h-1024.457v1024.457h796.114l-366.171-366.171-88.457-271.543c-4.114-10.286-2.057-22.629 4.114-30.857 4.114-6.171 12.343-14.4 28.8-14.4h4.114l275.657 90.514 368.229 368.229v-800.229zM1152 895.6l-139.886 137.829 98.743 96.686 67.886-67.886c22.629-22.629 45.257-47.314 69.943-69.943l-96.686-96.686z" />
62
+ <glyph unicode="&#xec86;" glyph-name="page" horiz-adv-x="1317" d="M1158.171 1039.6h-4.114c-22.629 0-43.2 0-65.829 2.057v102.857c0 30.857-22.629 53.486-53.486 53.486h-868.114c-30.857 0-53.486-22.629-53.486-53.486v-812.571c0-8.229 4.114-16.457 8.229-22.629l22.629-20.571 8.229-8.229 392.914-390.857c6.171-6.171 14.4-8.229 22.629-8.229h469.029c30.857 0 53.486 22.629 53.486 51.429v88.457l111.086 224.229c2.057 4.114 4.114 8.229 4.114 14.4l2.057 734.4c-4.114 24.686-24.686 45.257-49.371 45.257zM512.229 6.914l-273.6 273.6h273.6v-273.6zM1026.514-56.857h-452.571v353.829c0 24.686-20.571 45.257-45.257 45.257h-353.829v794.057h851.657v-94.629h-65.829c-26.743 0-49.371-20.571-49.371-45.257l-2.057-736.457c0-4.114 2.057-10.286 4.114-14.4l113.143-224.229v-78.171zM1141.714 266.114l-84.343-168.686-84.343 168.686v528.686h168.686v-528.686zM1141.714 856.514h-168.686v123.429c55.543 0 111.086 0 168.686-2.057v-121.371z" />
63
+ <glyph unicode="&#xecbe;" glyph-name="arrow-up" horiz-adv-x="1317" d="M905.143 1019.029l-187.2 158.4c-34.971 28.8-86.4 28.8-121.371 0l-185.143-158.4c-12.343-10.286-14.4-30.857-4.114-43.2s30.857-14.4 43.2-4.114l176.914 148.114v-1207.543c0-16.457 14.4-30.857 30.857-30.857s30.857 14.4 30.857 30.857v1207.543l176.914-148.114c6.171-4.114 12.343-8.229 20.571-8.229s18.514 4.114 22.629 10.286c12.343 14.4 10.286 34.971-4.114 45.257z" />
64
+ <glyph unicode="&#xecbf;" glyph-name="caret-down" horiz-adv-x="1317" d="M1308.343 848.286c-12.343 12.343-30.857 12.343-43.2 2.057l-592.457-561.6c-8.229-8.229-20.571-8.229-28.8 0l-592.457 561.6c-12.343 10.286-30.857 10.286-43.2-2.057s-10.286-32.914 2.057-43.2l592.457-561.6c16.457-14.4 37.029-22.629 57.6-22.629s41.143 8.229 57.6 22.629l592.457 561.6c8.229 10.286 10.286 30.857-2.057 43.2z" />
65
+ <glyph unicode="&#xecc6;" glyph-name="arrow-down" horiz-adv-x="1317" d="M909.257 103.6c-10.286 12.343-30.857 14.4-43.2 4.114l-176.914-148.114v1207.543c0 16.457-14.4 30.857-30.857 30.857s-30.857-14.4-30.857-30.857v-1207.543l-176.914 148.114c-12.343 10.286-32.914 10.286-43.2-4.114-10.286-12.343-10.286-32.914 4.114-43.2l187.2-156.343c16.457-14.4 39.086-22.629 59.657-22.629s43.2 8.229 59.657 22.629l187.2 156.343c14.4 10.286 16.457 30.857 4.114 43.2z" />
66
+ <glyph unicode="&#xecc7;" glyph-name="caret-up" horiz-adv-x="1317" d="M1306.286 274.343l-590.4 561.6c-30.857 28.8-82.286 28.8-113.143 0l-592.457-561.6c-12.343-12.343-12.343-30.857-2.057-43.2 6.171-6.171 14.4-10.286 22.629-10.286s14.4 2.057 20.571 8.229l592.457 561.6c8.229 8.229 20.571 8.229 28.8 0l592.457-561.6c12.343-12.343 32.914-10.286 43.2 2.057 12.343 12.343 10.286 32.914-2.057 43.2z" />
67
+ <glyph unicode="&#xecc9;" glyph-name="direction" horiz-adv-x="1317" d="M1252.8 815.371l-156.343 199.543c-6.171 8.229-14.4 12.343-24.686 12.343h-553.371v139.886c0 16.457-14.4 30.857-30.857 30.857s-30.857-14.4-30.857-30.857v-139.886h-370.286c-16.457 0-30.857-14.4-30.857-30.857v-399.086c0-16.457 14.4-30.857 30.857-30.857h368.229v-654.171c0-16.457 14.4-30.857 30.857-30.857s30.857 14.4 30.857 30.857v654.171h557.486c10.286 0 18.514 4.114 24.686 12.343l156.343 199.543c8.229 10.286 8.229 26.743-2.057 37.029zM1059.429 628.171h-942.171v337.371h940.114l131.657-168.686-129.6-168.686z" />
68
+ <glyph unicode="&#xece7;" glyph-name="stories" horiz-adv-x="1317" d="M1302.171 366.914l-127.543 80.229c-14.4 8.229-32.914 4.114-43.2-10.286s-4.114-32.914 10.286-43.2l86.4-53.486-569.829-355.886-569.829 357.943 86.4 53.486c14.4 8.229 18.514 28.8 10.286 43.2s-28.8 18.514-43.2 10.286l-127.543-80.229c-8.229-6.171-14.4-16.457-14.4-26.743s6.171-20.571 14.4-26.743l627.429-394.971c4.114-4.114 10.286-4.114 16.457-4.114s12.343 2.057 16.457 4.114l627.429 394.971c8.229 6.171 14.4 16.457 14.4 26.743s-6.171 20.571-14.4 24.686zM545.143 377.2l96.686-59.657c4.114-4.114 10.286-4.114 16.457-4.114s12.343 2.057 16.457 4.114l96.686 59.657c14.4 8.229 18.514 28.8 10.286 43.2s-28.8 18.514-43.2 10.286l-80.229-51.429-80.229 49.371c-14.4 8.229-32.914 4.114-43.2-10.286s-4.114-32.914 10.286-41.143zM250.971 562.343l154.286-96.686c4.114-4.114 10.286-4.114 16.457-4.114 10.286 0 20.571 4.114 26.743 14.4 8.229 14.4 4.114 32.914-10.286 43.2l-154.286 96.686c-14.4 8.229-32.914 4.114-43.2-10.286-8.229-14.4-4.114-32.914 10.286-43.2zM14.4 712.514l96.686-59.657c4.114-4.114 10.286-4.114 16.457-4.114 10.286 0 20.571 4.114 26.743 14.4 8.229 14.4 4.114 32.914-10.286 43.2l-53.486 34.971 53.486 34.971c14.4 8.229 18.514 28.8 10.286 43.2s-28.8 18.514-43.2 10.286l-96.686-59.657c-8.229-12.343-14.4-22.629-14.4-32.914s6.171-20.571 14.4-24.686zM267.429 856.514c6.171 0 10.286 2.057 16.457 4.114l154.286 96.686c14.4 8.229 18.514 28.8 10.286 43.2s-28.8 18.514-43.2 10.286l-154.286-96.686c-14.4-8.229-18.514-28.8-10.286-43.2 6.171-10.286 16.457-14.4 26.743-14.4zM578.057 1045.771l80.229 49.371 80.229-49.371c4.114-4.114 10.286-4.114 16.457-4.114 10.286 0 20.571 4.114 26.743 14.4 8.229 14.4 4.114 32.914-10.286 43.2l-96.686 59.657c-10.286 6.171-22.629 6.171-32.914 0l-96.686-59.657c-14.4-8.229-18.514-28.8-10.286-43.2 10.286-14.4 28.8-18.514 43.2-10.286zM878.4 957.314l154.286-96.686c4.114-4.114 10.286-4.114 16.457-4.114 10.286 0 20.571 4.114 26.743 14.4 8.229 14.4 4.114 32.914-10.286 43.2l-154.286 96.686c-14.4 8.229-32.914 4.114-43.2-10.286-8.229-14.4-4.114-32.914 10.286-43.2zM1164.343 661.086c6.171-10.286 16.457-14.4 26.743-14.4 6.171 0 10.286 2.057 16.457 4.114l96.686 59.657c8.229 6.171 14.4 16.457 14.4 26.743s-6.171 20.571-14.4 26.743l-96.686 59.657c-14.4 8.229-32.914 4.114-43.2-10.286-8.229-14.4-4.114-32.914 10.286-43.2l53.486-34.971-53.486-30.857c-16.457-10.286-20.571-28.8-10.286-43.2zM894.857 461.543c6.171 0 10.286 2.057 16.457 4.114l154.286 96.686c14.4 8.229 18.514 28.8 10.286 43.2s-28.8 18.514-43.2 10.286l-154.286-96.686c-14.4-8.229-18.514-28.8-10.286-43.2 6.171-10.286 16.457-14.4 26.743-14.4z" />
69
+ <glyph unicode="&#xeceb;" glyph-name="acf" horiz-adv-x="1317" d="M1285.714 1198h-1254.857c-16.457 0-30.857-14.4-30.857-30.857v-761.143c0-18.514 14.4-30.857 30.857-30.857h1254.857c16.457 0 30.857 14.4 30.857 30.857v761.143c0 16.457-14.4 30.857-30.857 30.857zM1254.857 436.857h-1193.143v699.429h1193.143v-699.429zM1164.343 177.657h-1012.114c-16.457 0-30.857-14.4-30.857-30.857s14.4-30.857 30.857-30.857h1012.114c16.457 0 30.857 14.4 30.857 30.857s-14.4 30.857-30.857 30.857zM1164.343-56.857h-1012.114c-16.457 0-30.857-14.4-30.857-30.857s14.4-30.857 30.857-30.857h1012.114c16.457 0 30.857 14.4 30.857 30.857s-14.4 30.857-30.857 30.857z" />
70
+ <glyph unicode="&#xed0d;" glyph-name="home" horiz-adv-x="1317" d="M1170.514 628.171c-16.457 0-30.857-14.4-30.857-30.857v-654.171h-337.371v483.429c0 16.457-14.4 30.857-30.857 30.857h-226.286c-16.457 0-30.857-14.4-30.857-30.857v-483.429h-337.371v654.171c0 16.457-14.4 30.857-30.857 30.857s-30.857-14.4-30.857-30.857v-685.029c0-16.457 14.4-30.857 30.857-30.857h1026.514c16.457 0 30.857 14.4 30.857 30.857v685.029c-2.057 16.457-16.457 30.857-32.914 30.857zM576-56.857v452.571h164.571v-452.571h-164.571zM1302.171 788.629l-627.429 405.257c-10.286 6.171-22.629 6.171-32.914 0l-627.429-405.257c-14.4-10.286-18.514-28.8-10.286-43.2s28.8-18.514 43.2-8.229l610.971 392.914 610.971-392.914c6.171-4.114 10.286-4.114 16.457-4.114 10.286 0 20.571 4.114 26.743 14.4 8.229 12.343 4.114 30.857-10.286 41.143z" />
71
+ <glyph unicode="&#xed1f;" glyph-name="toolbox" horiz-adv-x="1317" d="M1160.229 912.057h-242.743v82.286c0 80.229-65.829 144-144 144h-228.343c-80.229 0-144-65.829-144-144v-82.286h-244.8c-84.343 0-154.286-69.943-154.286-154.286v-218.057c0-16.457 14.4-30.857 30.857-30.857h26.743v-518.4c0-28.8 22.629-51.429 51.429-51.429h1096.457c28.8 0 51.429 22.629 51.429 51.429v518.4h26.743c16.457 0 30.857 14.4 30.857 30.857v218.057c-2.057 84.343-69.943 154.286-156.343 154.286zM460.8 994.343c0 45.257 37.029 82.286 82.286 82.286h228.343c45.257 0 82.286-37.029 82.286-82.286v-82.286h-392.914v82.286zM63.771 757.771c0 51.429 41.143 92.571 92.571 92.571h1005.943c51.429 0 92.571-41.143 92.571-92.571v-187.2h-1191.086v187.2zM1197.257 0.743h-1077.943v508.114h279.771v-139.886c0-16.457 14.4-30.857 30.857-30.857s30.857 14.4 30.857 30.857v139.886h392.914v-139.886c0-16.457 14.4-30.857 30.857-30.857s30.857 14.4 30.857 30.857v139.886h279.771v-508.114z" />
72
+ <glyph unicode="&#xed35;" glyph-name="comments" horiz-adv-x="1317" d="M1285.714 1082.8h-1254.857c-16.457 0-30.857-12.343-30.857-30.857v-1026.514c0-10.286 6.171-20.571 14.4-26.743 4.114-2.057 10.286-4.114 16.457-4.114s10.286 2.057 14.4 4.114l392.914 224.229h847.543c16.457 0 30.857 14.4 30.857 30.857v798.171c0 18.514-14.4 30.857-30.857 30.857zM1254.857 284.629h-824.914c-6.171 0-10.286-2.057-14.4-4.114l-353.829-201.6v942.171h1193.143v-736.457zM316.8 529.429c67.886 0 123.429 55.543 123.429 123.429s-55.543 123.429-123.429 123.429-123.429-55.543-123.429-123.429 55.543-123.429 123.429-123.429zM316.8 714.571c34.971 0 61.714-26.743 61.714-61.714s-26.743-61.714-61.714-61.714-61.714 26.743-61.714 61.714 26.743 61.714 61.714 61.714zM658.286 529.429c67.886 0 123.429 55.543 123.429 123.429s-55.543 123.429-123.429 123.429-123.429-55.543-123.429-123.429 55.543-123.429 123.429-123.429zM658.286 714.571c34.971 0 61.714-26.743 61.714-61.714s-26.743-61.714-61.714-61.714-61.714 26.743-61.714 61.714 26.743 61.714 61.714 61.714zM999.771 529.429c67.886 0 123.429 55.543 123.429 123.429s-55.543 123.429-123.429 123.429-123.429-55.543-123.429-123.429 55.543-123.429 123.429-123.429zM999.771 714.571c34.971 0 61.714-26.743 61.714-61.714s-26.743-61.714-61.714-61.714-61.714 26.743-61.714 61.714 28.8 61.714 61.714 61.714z" />
73
+ <glyph unicode="&#xed3a;" glyph-name="job" horiz-adv-x="1317" d="M1242.514 1163.029c-39.086 30.857-90.514 41.143-137.829 28.8l-767.314-187.2h-158.4c-90.514 0-164.571-74.057-164.571-164.571v-341.486c0-80.229 57.6-148.114 133.714-160.457l100.8-432c4.114-14.4 16.457-24.686 30.857-24.686h168.686c10.286 0 18.514 4.114 24.686 12.343s8.229 16.457 6.171 26.743l-94.629 405.257 720-176.914c12.343-4.114 26.743-4.114 39.086-4.114 34.971 0 69.943 12.343 98.743 34.971 39.086 30.857 59.657 74.057 59.657 123.429v740.571c0 45.257-22.629 90.514-59.657 119.314zM372.343 951.143l306.514 74.057v-709.714l-306.514 76.114v559.543zM76.114 498.571v343.543c0 55.543 45.257 102.857 102.857 102.857h133.714v-547.2h-133.714c-57.6 0-102.857 45.257-102.857 100.8zM304.457-56.857l-88.457 382.629h104.914l88.457-382.629h-104.914zM1240.457 301.086c0-28.8-12.343-55.543-37.029-74.057s-55.543-24.686-86.4-18.514l-376.457 92.571v740.571l378.514 92.571c30.857 8.229 61.714 0 86.4-18.514 22.629-18.514 37.029-45.257 37.029-74.057v-740.571z" />
74
+ <glyph unicode="&#xed4d;" glyph-name="post" horiz-adv-x="1317" d="M1168.457 1198h-1020.343c-16.457 0-30.857-14.4-30.857-30.857v-1254.857c0-16.457 14.4-30.857 30.857-30.857h1020.343c16.457 0 30.857 14.4 30.857 30.857v1254.857c0 16.457-14.4 30.857-30.857 30.857zM1137.6-56.857h-958.629v1193.143h958.629v-1193.143zM672.686 593.2h341.486c16.457 0 30.857 14.4 30.857 30.857v374.4c0 16.457-14.4 30.857-30.857 30.857h-341.486c-16.457 0-30.857-14.4-30.857-30.857v-374.4c0-16.457 12.343-30.857 30.857-30.857zM703.543 967.6h279.771v-312.686h-279.771v312.686zM306.514 967.6h195.429c16.457 0 30.857 14.4 30.857 30.857s-14.4 30.857-30.857 30.857h-195.429c-16.457 0-30.857-14.4-30.857-30.857s14.4-30.857 30.857-30.857zM306.514 780.4h195.429c16.457 0 30.857 14.4 30.857 30.857s-14.4 30.857-30.857 30.857h-195.429c-16.457 0-30.857-14.4-30.857-30.857s14.4-30.857 30.857-30.857zM306.514 593.2h195.429c16.457 0 30.857 14.4 30.857 30.857s-14.4 30.857-30.857 30.857h-195.429c-16.457 0-30.857-14.4-30.857-30.857s14.4-30.857 30.857-30.857zM306.514 406h705.6c16.457 0 30.857 14.4 30.857 30.857s-14.4 30.857-30.857 30.857h-705.6c-16.457 0-30.857-14.4-30.857-30.857s14.4-30.857 30.857-30.857zM306.514 218.8h705.6c16.457 0 30.857 14.4 30.857 30.857s-14.4 30.857-30.857 30.857h-705.6c-16.457 0-30.857-14.4-30.857-30.857s14.4-30.857 30.857-30.857zM306.514 31.6h705.6c16.457 0 30.857 14.4 30.857 30.857s-14.4 30.857-30.857 30.857h-705.6c-16.457 0-30.857-14.4-30.857-30.857s14.4-30.857 30.857-30.857z" />
75
+ <glyph unicode="&#xed64;" glyph-name="support" horiz-adv-x="1317" d="M64.152 1017.373c-11.386-2.566-27.267-10.749-35.285-18.185-29.865-27.689-28.867-11.818-28.867-459.566 0-369.509 0.859-413.537 8.337-428.307 18.273-36.082 42.567-51.475 79.935-50.631 21.759 0.489 39.95 9.345 159.809 77.791l135.252 77.241h420.079c271.646 0 428.904 1.893 445.042 5.354 28.255 6.058 50.415 23.945 60.974 49.217 10.569 25.293 10.569 672.994 0 698.287-10.558 25.272-32.719 43.159-60.974 49.217-31.521 6.763-1154.211 6.367-1184.302-0.417M1251.735 948.15c4.623-12.045 3.636-651.662-1.013-658.98-3.065-4.824-104.59-6.598-441.278-7.714l-437.297-1.455-136.918-78.429c-75.302-43.133-142.375-78.429-149.045-78.429s-14.904 2.777-18.298 6.171c-4.695 4.695-6.171 102.42-6.171 408.435 0 221.246 1.404 405.926 3.122 410.4 2.823 7.354 59.894 8.136 593.45 8.136s590.626-0.782 593.45-8.136M191.53 848.188c-6.387-2.607-14.235-10.502-17.445-17.542-8.043-17.65 5.148-37.389 27.73-41.508 9.216-1.682 117.766-2.366 241.221-1.522 212.328 1.445 225.051 2.057 235.286 11.325 13.814 12.507 13.814 29.613 0 42.12-10.27 9.298-22.701 9.849-243 10.836-132.696 0.591-237.158-0.993-243.792-3.708M953.789 841.564c-32.724-15.629-53.789-39.934-53.789-62.074 0-34.365 32.523-40.335 59.472-10.918 14.102 15.393 19.795 18 39.327 18 46.625 0 64.759-48.039 29.515-78.202-48.662-41.637-54.468-50.678-59.313-92.355-2.71-23.338-1.517-29.556 7.992-41.585 12.811-16.2 30.837-18.386 42.434-5.143 4.335 4.953 9.031 21.636 10.435 37.080 2.031 22.377 5.030 29.654 14.77 35.83 28.008 17.758 54.987 49.747 61.097 72.437 23.112 85.834-71.851 165.173-151.941 126.931M177.722 667.139c-11.479-16.385-9.931-27.453 5.544-39.621 12.831-10.095 19.934-10.661 133.946-10.661h120.399l12.945 12.945c9.437 9.437 12.019 16.051 9.53 24.429-6.953 23.421-12.513 24.341-147.060 24.341-125.717 0-127.399-0.144-135.303-11.433M180 498.571c-5.657-5.657-10.286-14.914-10.286-20.571s4.629-14.914 10.286-20.571c9.9-9.9 17.141-10.286 192.482-10.286h182.201l10.656 13.551c13.325 16.941 13.402 24.85 0.375 37.877-9.9 9.9-17.141 10.286-192.857 10.286s-182.957-0.386-192.857-10.286M968.673 468.095c-31.644-19.296-34.853-66.122-6.187-90.242 32.133-27.036 80.193-12.621 92.268 27.684 14.899 49.731-40.767 90.185-86.081 62.558" />
76
+ <glyph unicode="&#xed71;" glyph-name="search-console" horiz-adv-x="1317" d="M1285.714 1198h-1254.857c-16.457 0-30.857-14.4-30.857-30.857v-1254.857c0-16.457 14.4-30.857 30.857-30.857h1254.857c16.457 0 30.857 14.4 30.857 30.857v1254.857c0 16.457-14.4 30.857-30.857 30.857zM1254.857-56.857h-1193.143v448.457c6.171 0 12.343 2.057 16.457 8.229l183.086 162.514c18.514-14.4 43.2-22.629 67.886-22.629 39.086 0 72 18.514 94.629 47.314l115.2-67.886c-4.114-10.286-4.114-22.629-4.114-32.914 0-63.771 51.429-115.2 115.2-115.2s115.2 51.429 115.2 115.2v14.4l168.686 156.343c20.571-18.514 47.314-30.857 78.171-30.857 63.771 0 115.2 51.429 115.2 115.2s-51.429 115.2-115.2 115.2-115.2-51.429-115.2-115.2c0-12.343 2.057-22.629 4.114-32.914l-164.571-148.114c-20.571 26.743-53.486 43.2-88.457 43.2-30.857 0-57.6-12.343-78.171-30.857l-125.486 76.114v8.229c0 63.771-51.429 115.2-115.2 115.2s-115.2-51.429-115.2-115.2c0-16.457 4.114-32.914 10.286-45.257l-160.457-144v668.571h1193.143v-1193.143zM329.143 603.486c-30.857 0-53.486 24.686-53.486 53.486s24.686 53.486 53.486 53.486 53.486-24.686 53.486-53.486-24.686-53.486-53.486-53.486zM701.486 486.229c0-30.857-24.686-53.486-53.486-53.486s-53.486 24.686-53.486 53.486 24.686 53.486 53.486 53.486 53.486-22.629 53.486-53.486zM954.514 741.314c0 30.857 24.686 53.486 53.486 53.486s53.486-24.686 53.486-53.486-24.686-53.486-53.486-53.486-53.486 24.686-53.486 53.486z" />
77
+ <glyph unicode="&#xed73;" glyph-name="cart" horiz-adv-x="1317" d="M1201.371 469.771l115.2 512.229c2.057 8.229 0 18.514-6.171 26.743s-14.4 12.343-24.686 12.343h-987.429l-8.229 139.886c0 16.457-14.4 28.8-30.857 28.8h-228.343c-16.457-2.057-30.857-16.457-30.857-32.914s14.4-30.857 30.857-30.857h199.543l55.543-905.143c0-16.457 14.4-28.8 30.857-28.8h855.771c16.457 0 30.857 14.4 30.857 30.857s-14.4 30.857-30.857 30.857h-826.971l-12.343 193.371h839.314c14.4 0 26.743 10.286 28.8 22.629zM329.143 508.857l-26.743 448.457h944.229l-100.8-448.457h-816.686zM450.514 128.286c-65.829 0-119.314-53.486-119.314-119.314s53.486-119.314 119.314-119.314 119.314 53.486 119.314 119.314c-2.057 67.886-55.543 119.314-119.314 119.314zM450.514-46.571c-30.857 0-57.6 24.686-57.6 57.6 0 30.857 24.686 57.6 57.6 57.6s57.6-24.686 57.6-57.6c-2.057-30.857-26.743-57.6-57.6-57.6zM1028.571 128.286c-65.829 0-119.314-53.486-119.314-119.314s53.486-119.314 119.314-119.314c65.829 0 119.314 53.486 119.314 119.314 0 67.886-53.486 119.314-119.314 119.314zM1028.571-46.571c-30.857 0-57.6 24.686-57.6 57.6 0 30.857 24.686 57.6 57.6 57.6 30.857 0 57.6-24.686 57.6-57.6 0-30.857-24.686-57.6-57.6-57.6z" />
78
+ <glyph unicode="&#xed83;" glyph-name="attachment" horiz-adv-x="1317" d="M1001.829 800.971c-16.457 0-30.857-14.4-30.857-30.857v-541.029c2.057-76.114-28.8-146.057-86.4-203.657-57.6-55.543-135.771-86.4-216-82.286-86.4 0-176.914 32.914-230.4 86.4-57.6 53.486-90.514 127.543-90.514 201.6v693.257c0 69.943 32.914 131.657 94.629 170.743 59.657 41.143 133.714 51.429 203.657 26.743l8.229-2.057c8.229-2.057 16.457-4.114 22.629-10.286 78.171-39.086 121.371-109.029 121.371-189.257v-592.457c0-41.143-14.4-80.229-39.086-109.029-4.114-6.171-8.229-8.229-10.286-10.286-24.686-24.686-57.6-37.029-90.514-37.029-39.086 0-76.114 16.457-100.8 47.314-26.743 30.857-41.143 69.943-41.143 111.086v497.829c0 16.457-14.4 30.857-30.857 30.857s-30.857-14.4-30.857-30.857v-495.771c0-55.543 20.571-109.029 55.543-150.171 34.971-43.2 90.514-67.886 148.114-67.886 49.371 0 94.629 18.514 133.714 53.486l14.4 14.4c34.971 41.143 53.486 92.571 53.486 150.171v590.4c0 102.857-57.6 193.371-154.286 242.743-12.343 8.229-24.686 10.286-34.971 14.4l-6.171 2.057c-88.457 30.857-183.086 18.514-257.143-34.971-78.171-51.429-121.371-131.657-121.371-222.171v-693.257c0-90.514 39.086-178.971 109.029-244.8 65.829-61.714 172.8-102.857 271.543-102.857h10.286c92.571 0 181.029 37.029 248.914 100.8 69.943 67.886 106.971 156.343 104.914 248.914v536.914c2.057 16.457-12.343 30.857-28.8 30.857z" />
79
+ <glyph unicode="&#xed91;" glyph-name="tag" horiz-adv-x="1317" d="M1242.514 998.457c-6.171 6.171-16.457 10.286-26.743 8.229l-314.743-43.2c-82.286 123.429-234.514 265.371-481.371 228.343-16.457-2.057-28.8-18.514-26.743-34.971s18.514-28.8 34.971-26.743c201.6 30.857 329.143-72 405.257-174.857l-181.029-24.686c-6.171 0-12.343-4.114-16.457-8.229l-561.6-534.857c-6.171-6.171-10.286-14.4-10.286-22.629s4.114-16.457 10.286-22.629l479.314-452.571c6.171-6.171 14.4-8.229 20.571-8.229s14.4 2.057 20.571 8.229l563.657 532.8c4.114 4.114 8.229 10.286 10.286 18.514l82.286 530.743c2.057 10.286 0 20.571-8.229 26.743zM1110.857 461.543l-534.857-506.057-434.057 411.429 530.743 501.943 199.543 28.8c34.971-61.714 51.429-111.086 53.486-117.257 4.114-12.343 16.457-22.629 28.8-22.629 2.057 0 6.171 0 8.229 2.057 16.457 4.114 24.686 22.629 20.571 39.086 0 2.057-14.4 47.314-47.314 106.971l246.857 34.971-72-479.314z" />
80
+ </font></defs></svg>
assets/fonts/Rank-Math.ttf ADDED
Binary file
assets/fonts/Rank-Math.woff ADDED
Binary file
assets/img/icon.svg ADDED
@@ -0,0 +1,107 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <svg enable-background="new 0 0 400 400" height="400" viewBox="0 0 400 400" width="400" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><clipPath id="a"><path d="m-.062.001h400v399.998h-400z"/></clipPath><clipPath id="b"><path d="m242.496 283.599-.057-27.273-13.438 22.573h-3.387l-13.43-22.224v26.924h-7.25v-41.147h6.254l16.234 27.272 15.947-27.272h6.254l.057 41.147zm36.733 0v-3.818c-1.752 2.705-5.143 4.23-9.813 4.23-7.123 0-11.625-3.938-11.625-9.405 0-5.23 3.516-9.329 12.967-9.329h8.061v-.489c0-4.287-2.572-6.817-7.77-6.817-3.475 0-7.123 1.174-9.457 3.118l-2.863-5.35c3.328-2.587 8.178-3.882 13.203-3.882 8.992 0 14.189 4.329 14.189 13.344v18.398zm-.411-13.428h-7.533c-4.967 0-6.309 1.882-6.309 4.196 0 2.643 2.223 4.35 5.961 4.35 3.572-.057 6.658-1.7 7.881-4.93zm29.262 7.784c1.469.041 2.906-.415 4.086-1.295l2.043 5.231c-1.752 1.397-4.377 2.098-7.004 2.098-6.838 0-10.752-3.644-10.752-10.58v-15.083h-5.141v-5.881h5.141v-7.169h7.305v7.169h8.34v5.881h-8.34v14.929c0 3.057 1.513 4.7 4.322 4.7zm35.565 5.644v-17.042c0-5.595-2.779-8.295-7.414-8.295-5.199 0-8.707 3.177-8.707 9.47v15.867h-7.297v-43.614h7.297v15.872c2.398-2.587 6.08-4 10.424-4 7.443 0 13.002 4.329 13.002 13.755v17.987z"/></clipPath><clipPath id="c"><path d="m-.062.001h400v399.998h-400z"/></clipPath><clipPath id="d" clip-path="url(#c)"><path d="m75.436 270.08 9.435 13.519h-8.178l-8.338-12.029c-.525.049-1.051.071-1.578.063h-9.242v11.966h-7.594v-41.147h16.794c10.744 0 17.409 5.525 17.409 14.637-.001 6.229-3.158 10.816-8.708 12.991zm-9.028-21.16h-8.875v16.398h8.875c6.664 0 10.104-3.057 10.104-8.23 0-5.175-3.44-8.168-10.104-8.168zm44.446 34.679v-3.818c-1.751 2.705-5.142 4.23-9.811 4.23-7.124 0-11.627-3.938-11.627-9.405 0-5.23 3.511-9.344 12.967-9.344h8.062v-.475c0-4.287-2.573-6.817-7.769-6.817-3.475 0-7.124 1.174-9.458 3.118l-2.856-5.35c3.329-2.587 8.178-3.882 13.204-3.882 8.985 0 14.182 4.329 14.182 13.344v18.398h-6.894zm-.409-13.428h-7.535c-4.96 0-6.309 1.882-6.309 4.196 0 2.643 2.224 4.35 5.964 4.35 3.556-.057 6.656-1.7 7.88-4.93zm40.067 13.428v-17.042c0-5.595-2.746-8.295-7.422-8.295-5.198 0-8.7 3.177-8.7 9.47v15.867h-7.304v-31.386h6.949v4.057c2.398-2.88 6.198-4.413 10.751-4.413 7.477 0 13.029 4.329 13.029 13.755v17.987zm48.996 0h-8.873l-10.807-13.428-5.433 5.175v8.253h-7.303v-43.614h7.303v26.334l15.127-14.105h8.764l-13.031 13.169z"/></clipPath><clipPath id="e"><path d="m321.939 150.989-39.884 1.787 7.027 10.972-66.562 42.367-65.966-27.606-76.606 31.79 5.308 12.712 71.27-29.596 67.32 28.187 72.627-46.26 7.041 10.969z"/></clipPath><clipPath id="f"><path d="m-.062.001h400v399.998h-400z"/></clipPath><clipPath id="g" clip-path="url(#f)"><path d="m108.274 191.671 48.267-20.049 2.36.987v-28.491h-50.627zm110.439-116.684v122.671l3.807 1.599 46.824-29.829v-94.44h-50.631zm-55.219 99.555 50.571 21.184v-86.173h-50.571z"/></clipPath><image height="400" overflow="visible" transform="translate(-.0625)" width="400" xlink:href="data:image/jpeg;base64,/9j/4AAQSkZJRgABAgEASABIAAD/7AARRHVja3kAAQAEAAAAHgAA/+4AIUFkb2JlAGTAAAAAAQMA
2
+ EAMCAwYAAAM/AAADSwAAA2//2wCEABALCwsMCxAMDBAXDw0PFxsUEBAUGx8XFxcXFx8eFxoaGhoX
3
+ Hh4jJSclIx4vLzMzLy9AQEBAQEBAQEBAQEBAQEABEQ8PERMRFRISFRQRFBEUGhQWFhQaJhoaHBoa
4
+ JjAjHh4eHiMwKy4nJycuKzU1MDA1NUBAP0BAQEBAQEBAQEBAQP/CABEIAZABkAMBIgACEQEDEQH/
5
+ xABeAAEBAAAAAAAAAAAAAAAAAAAABwEBAAAAAAAAAAAAAAAAAAAAABABAQAAAAAAAAAAAAAAAAAA
6
+ kLARAQAAAAAAAAAAAAAAAAAAALASAQAAAAAAAAAAAAAAAAAAAJD/2gAMAwEAAhEDEQAAAKAAAAAA
7
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
8
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
9
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
10
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
11
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
12
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
13
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
14
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
15
+ AAAAAAAAAAAD/9oACAECAAEFABx//9oACAEDAAEFABx//9oACAEBAAEFAI4n/9oACAECAgY/ABx/
16
+ /9oACAEDAgY/ABx//9oACAEBAQY/ABxP/9k="/><g clip-path="url(#a)"><image height="400" overflow="visible" transform="translate(-.0625)" width="400" xlink:href="data:image/jpeg;base64,/9j/4AAQSkZJRgABAgEASABIAAD/7AARRHVja3kAAQAEAAAAHgAA/+4AIUFkb2JlAGTAAAAAAQMA
17
+ EAMCAwYAAAVgAAAFbAAABZD/2wCEABALCwsMCxAMDBAXDw0PFxsUEBAUGx8XFxcXFx8eFxoaGhoX
18
+ Hh4jJSclIx4vLzMzLy9AQEBAQEBAQEBAQEBAQEABEQ8PERMRFRISFRQRFBEUGhQWFhQaJhoaHBoa
19
+ JjAjHh4eHiMwKy4nJycuKzU1MDA1NUBAP0BAQEBAQEBAQEBAQP/CABEIAZABkAMBIgACEQEDEQH/
20
+ xABlAAEBAQEBAAAAAAAAAAAAAAABAAIGBQEBAQEBAQAAAAAAAAAAAAAAAQAEBQIQAQEAAAAAAAAA
21
+ AAAAAAAAAJCwEQEAAAAAAAAAAAAAAAAAAACwEgEAAAAAAAAAAAAAAAAAAACQ/9oADAMBAAIRAxEA
22
+ AADwUeh7UpUSXLKiKkSjKiK5RUaURYRUZUiURYZUSkZYSYZYSkaqpqqqq8BHbhkRUiUZUhUaUh1C
23
+ KiSlKiKiK5aURUhUaYRUpUSkZkSkqapqqqq8CHbhUiUZUhUSUpURUSYZURUh1DSiKkKjTUKiLDTU
24
+ LVTULVTVNVVVXPo7cLCSlKiSlKiKkSjKiK5RUaURYRUZUiURYZUSkZYSYZYSkaqpqq5+rbgUZkRU
25
+ iUZUhUaUh1CKiSlKiKiK5aURUhUaYRUpUSkZkSkqapqq55HbgYZUiUZUhUSUpURUSYZURUh1DSiK
26
+ kKjTUKiLDTULVTULVTVNVXPJbcCjLCSlKiSlKiKkSjKiK5RUaURYRUZUiURYZUSkZYSYZYSkaqp5
27
+ 6rdgaiUZkRUiUZUhUaUh1CKiSlKiKiK5aURUhUaYRUpUSkZkSkqap51HdgkSYZUiUZUhUSUpURUS
28
+ YZURUh1DSiKkKjTUKiLDTULVTULVTVPOpbsCkSjLCSlKiSlKiKkSjKiK5RUaURYRUZUiURYZUSkZ
29
+ YSYZYSkZ52rdz2qWolGZEVIlGVIVGlIdQiokpSoioiuWlEVIVGmEVKVEpGZEpKudR3YJGZEmGVIl
30
+ GVIVElKVEVEmGVEVIdQ0oipCo01Coiw01C1U1C1VzqW7ApSpEoywkpSokpSoipEoyoiuUVGlEWEV
31
+ GVIlEWGVEpGWEmGWEudq3YGqmqWolGZEVIlGVIVGlIdQiokpTqEVEVy0oipCo0wipSolIzIlziO/
32
+ BIlIzIkwypEoypCokpSoiokwyoioiw0oipCo01Coiw01C1U1DzqW/ApEpSpEoywkpSokpSoipFqG
33
+ VEVyio0oiwioypEoiwyolIywkwzztW7A1E1U1S1EozIipEoypCo0oiwiokpTqEVEVy0oipCo0wip
34
+ SolIzztW7BI1IlIzIkwypEoypCokpSoiokwyoioiw0oipCo01Coiw01C1Vz1W7DJUpEpSpEoywkp
35
+ SokpSoipFqGVEVyio0oiwioypEoiwyolIywlz1W7BVS1E1U1S1EozIipEoypCo0oiwiokpTqEVEV
36
+ y0oipCo0wipSolz1W7BVTI1IlIzIkwypEoypCokpSoiokwyoioiw0oipCo01Coiw01Dz9W7BVTJU
37
+ pEpSpEoywkpSokpSoipFqGVEVyio0oiwioypEoiwyolIzz9W3BVVVS1E1U1S1EozIipEoypCo0oi
38
+ wiokpTqEVEVy0oipCo0wipT4FW3BVVVTI1IlIzIkwypEoypCokpSoiokwyoioiw0oipCo01Coiw1
39
+ 4FW3DVVVTJUpEpSpEoywkpSokpSoipFqGVEVyio0oiwioypEoi1Sol//2gAIAQIAAQUAHH//2gAI
40
+ AQMAAQUAHH//2gAIAQEAAQUAjif/2gAIAQICBj8AHH//2gAIAQMCBj8AHH//2gAIAQEBBj8AHE//
41
+ 2Q=="/></g><g clip-path="url(#b)"><image height="400" overflow="visible" transform="translate(-.0625)" width="400" xlink:href="data:image/jpeg;base64,/9j/4AAQSkZJRgABAgEASABIAAD/7AARRHVja3kAAQAEAAAAHgAA/+4AIUFkb2JlAGTAAAAAAQMA
42
+ EAMCAwYAAAN/AAADiwAAA6//2wCEABALCwsMCxAMDBAXDw0PFxsUEBAUGx8XFxcXFx8eFxoaGhoX
43
+ Hh4jJSclIx4vLzMzLy9AQEBAQEBAQEBAQEBAQEABEQ8PERMRFRISFRQRFBEUGhQWFhQaJhoaHBoa
44
+ JjAjHh4eHiMwKy4nJycuKzU1MDA1NUBAP0BAQEBAQEBAQEBAQP/CABEIAZABkAMBIgACEQEDEQH/
45
+ xABfAAEBAQAAAAAAAAAAAAAAAAAACAcBAQAAAAAAAAAAAAAAAAAAAAAQAQEAAAAAAAAAAAAAAAAA
46
+ AJCwEQEAAAAAAAAAAAAAAAAAAACwEgEAAAAAAAAAAAAAAAAAAACQ/9oADAMBAAIRAxEAAADPwAAA
47
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
48
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
49
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
50
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
51
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFACf1ACf1ACf1ACf1ACf1A
52
+ Cf1ACf1ACf1ACf1ACf1AT+AAAAAAAAAAAAAAUAAAAAAAAAABP9AT+AAAAAAAAAAAAAAUAAAAAAAA
53
+ AABP9AT+AAAAAAAAAAAAAAUAAAAAAAAAABP9AT+AAAAAAAAAAAAAAUAn8UAn8UAn8UAn8UAn8UAn
54
+ 8UAn8UAn8UAn8UAn8UBP4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
55
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
56
+ AAAAAAAAAAAAAAAAAAAAAf/aAAgBAgABBQAcf//aAAgBAwABBQAcf//aAAgBAQABBQCOJ//aAAgB
57
+ AgIGPwAcf//aAAgBAwIGPwAcf//aAAgBAQEGPwAcT//Z"/></g><g clip-path="url(#d)"><image height="400" overflow="visible" transform="translate(-.0625)" width="400" xlink:href="data:image/jpeg;base64,/9j/4AAQSkZJRgABAgEASABIAAD/7AARRHVja3kAAQAEAAAAHgAA/+4AIUFkb2JlAGTAAAAAAQMA
58
+ EAMCAwYAAAO5AAADxgAAA+r/2wCEABALCwsMCxAMDBAXDw0PFxsUEBAUGx8XFxcXFx8eFxoaGhoX
59
+ Hh4jJSclIx4vLzMzLy9AQEBAQEBAQEBAQEBAQEABEQ8PERMRFRISFRQRFBEUGhQWFhQaJhoaHBoa
60
+ JjAjHh4eHiMwKy4nJycuKzU1MDA1NUBAP0BAQEBAQEBAQEBAQP/CABEIAZABkAMBIgACEQEDEQH/
61
+ xABqAAEBAQAAAAAAAAAAAAAAAAAABwEBAQEBAAAAAAAAAAAAAAAAAAABAhAAAwABBAMAAAAAAAAA
62
+ AAAAABESAUBwgAIwYLARAQAAAAAAAAAAAAAAAAAAALASAQAAAAAAAAAAAAAAAAAAAJD/2gAMAwEA
63
+ AhEDEQAAAJ+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
64
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
65
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
66
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
67
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWyomtqoktoiS2iJLa
68
+ IktukRW5LEVuERW7SILeIgt4iAkAAAAAAAAAAAAAWyJ2zTRQKAA3NAAANAEsQGcgAAAAAAAAAAAA
69
+ LZE7Zo3NoAFAA0AAGs0CWIDOQAAAAAAAAAAAAFsids0bjTRAKABrNAAG5oERAZgAAAAAAAAAAAAC
70
+ 2RNVsRNVtRIW1EhbUSFtRIW3YiLciKW3IiLciIt6IAJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
71
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
72
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//aAAgBAgABBQDjBjDJJJJJ
73
+ JEIQvP11PXU9dTjKKKKKKKKGMe0f/9oACAEDAAEFAOMyEIQvYWMY9o//2gAIAQEAAQUA+OJ//9oA
74
+ CAECAgY/ABx//9oACAEDAgY/ABx//9oACAEBAQY/ABxP/9k="/></g><g clip-path="url(#e)"><image height="400" overflow="visible" transform="translate(-.0625)" width="400" xlink:href="data:image/jpeg;base64,/9j/4AAQSkZJRgABAgEASABIAAD/7AARRHVja3kAAQAEAAAAHgAA/+4AIUFkb2JlAGTAAAAAAQMA
75
+ EAMCAwYAAAN9AAADiQAAA63/2wCEABALCwsMCxAMDBAXDw0PFxsUEBAUGx8XFxcXFx8eFxoaGhoX
76
+ Hh4jJSclIx4vLzMzLy9AQEBAQEBAQEBAQEBAQEABEQ8PERMRFRISFRQRFBEUGhQWFhQaJhoaHBoa
77
+ JjAjHh4eHiMwKy4nJycuKzU1MDA1NUBAP0BAQEBAQEBAQEBAQP/CABEIAZABkAMBIgACEQEDEQH/
78
+ xABfAAEBAQAAAAAAAAAAAAAAAAAACAcBAQAAAAAAAAAAAAAAAAAAAAAQAQEAAAAAAAAAAAAAAAAA
79
+ AJCwEQEAAAAAAAAAAAAAAAAAAACwEgEAAAAAAAAAAAAAAAAAAACQ/9oADAMBAAIRAxEAAADPwAAA
80
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
81
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
82
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAn
83
+ +gAAAAAAAAAAAAAAAACfwAAAAAAAKAn+gAAAAAAAAAAAAAAAACfwAAAAAAAKAn+gAAAAAAAAAAAA
84
+ AAAACfwAAAAAAAKAn+gAAAAAAAAAAAAAAAACfwAAAAAAAKAn+gAAAAAAAAAAAAAAAACfwAAAAAAA
85
+ KAn8UAn8UAn8UAn8UAn8UAn8UAn8UAn8UAn8UAn8UAn8UAn8UAn8UAn8UAn8UAn8UAn8AAAAAAAA
86
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
87
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
88
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
89
+ AAAAAAAAAAAAAAAAAAf/2gAIAQIAAQUAHH//2gAIAQMAAQUAHH//2gAIAQEAAQUAjif/2gAIAQIC
90
+ Bj8AHH//2gAIAQMCBj8AHH//2gAIAQEBBj8AHE//2Q=="/></g><g clip-path="url(#g)"><image height="400" overflow="visible" transform="translate(-.0625)" width="400" xlink:href="data:image/jpeg;base64,/9j/4AAQSkZJRgABAgEASABIAAD/7AARRHVja3kAAQAEAAAAHgAA/+4AIUFkb2JlAGTAAAAAAQMA
91
+ EAMCAwYAAAOqAAADtgAAA9r/2wCEABALCwsMCxAMDBAXDw0PFxsUEBAUGx8XFxcXFx8eFxoaGhoX
92
+ Hh4jJSclIx4vLzMzLy9AQEBAQEBAQEBAQEBAQEABEQ8PERMRFRISFRQRFBEUGhQWFhQaJhoaHBoa
93
+ JjAjHh4eHiMwKy4nJycuKzU1MDA1NUBAP0BAQEBAQEBAQEBAQP/CABEIAZABkAMBIgACEQEDEQH/
94
+ xABkAAEBAQAAAAAAAAAAAAAAAAAAAQcBAQEBAAAAAAAAAAAAAAAAAAABAhABAQEBAQAAAAAAAAAA
95
+ AAAAAUBggLARAQAAAAAAAAAAAAAAAAAAALASAQAAAAAAAAAAAAAAAAAAAJD/2gAMAwEAAhEDEQAA
96
+ AM/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
97
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABtw3VlAlAoAAFlAAlqUYbuWGshIAAAAAAAAAAABtw3Vl
98
+ AgFqUAAWCgBVlhhu5YayEgAAAAAAAAAAAG3DdAoAlWUAAAoAAluG7lhrISAAAAAAAAAAAAbcN0Cp
99
+ QJQKAABZQAJbhu44cyEgAAAAAAAAAAAG3DdAWUCAWpQABYKAFYduOHTISAAAAAAAAAAAAbcN0ACg
100
+ CVZQAACgAYduOHSBIAAAAAAAAAAABtw3QAKlAlAoAAFlAGHbjh0gSAAAAAAAAAAAAbcl3QAFlAgF
101
+ qUAAWCgYduOHSBIAAAAAAAAAAABttl3QAAKAJVlAAAKBh244dIEgAAAAAAAAAAAAAAAAAAAAAAAA
102
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
103
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
104
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
105
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH//2gAIAQIAAQUA2rS0tLS0
106
+ tLS0vGn/2gAIAQMAAQUA2rS0tLS0tLS0vGn/2gAIAQEAAQUA8cT/2gAIAQICBj8AHH//2gAIAQMC
107
+ Bj8AHH//2gAIAQEBBj8AHE//2Q=="/></g></svg>
assets/index.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Nothing to see here.
4
+ */
assets/js/console.js ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // minifyOnSave
2
+ jQuery(document).ready(function($) {
3
+ var $responseTextarea = $('#giapi-response');
4
+ var $submitButton = $('#giapi-submit');
5
+ var $urlField = $('#giapi-url');
6
+ var $actionRadio = $('.giapi-action');
7
+ var $ufResponse = $('#giapi-response-userfriendly');
8
+ var logResponse = function( info, url, api_action ) {
9
+ var d = new Date();
10
+ var n = d.toLocaleTimeString();
11
+ var urls = $urlField.val().split('\n').filter(Boolean);
12
+ var urls_str = urls[0];
13
+ var is_batch = false;
14
+ var action = $actionRadio.filter(':checked').val();
15
+ if ( urls.length > 1 ) {
16
+ urls_str = '(batch)';
17
+ is_batch = true;
18
+ }
19
+
20
+ $ufResponse.removeClass('not-ready fail success').addClass('ready').find('.response-id').html('<strong>' + action + '</strong>' + ' ' + urls_str);
21
+ if ( api_action !== 'bing_submit' ) {
22
+ if ( ! is_batch ) {
23
+ if ( typeof info.error !== 'undefined' ) {
24
+ $ufResponse.addClass('fail').find('.response-status').text(rm_giapi.l10n_error+' '+info.error.code).siblings('.response-message').text(info.error.message);
25
+ } else {
26
+ var base = info;
27
+ if ( typeof info.urlNotificationMetadata !== 'undefined' ) {
28
+ base = info.urlNotificationMetadata;
29
+ }
30
+ var d = new Date(base.latestUpdate.notifyTime);
31
+ $ufResponse.addClass('success').find('.response-status').text(rm_giapi.l10n_success+' ').siblings('.response-message').text(rm_giapi.l10n_last_updated+' ' + d.toString());
32
+ }
33
+ } else {
34
+ $ufResponse.addClass('success').find('.response-status').text(rm_giapi.l10n_success+' ').siblings('.response-message').text(rm_giapi.l10n_see_response);
35
+ if ( typeof info.error !== 'undefined' ) {
36
+ $ufResponse.addClass('fail').find('.response-status').text(rm_giapi.l10n_error+' '+info.error.code).siblings('.response-message').text(info.error.message);
37
+ } else {
38
+ $.each(info, function(index, val) {
39
+ if ( typeof val.error !== 'undefined' ) {
40
+ var error_code = '';
41
+ if ( typeof val.error.code !== 'undefined' ) {
42
+ error_code = val.error.code;
43
+ }
44
+ var error_message = '';
45
+ if ( typeof val.error.message !== 'undefined' ) {
46
+ error_message = val.error.message;
47
+ }
48
+ $ufResponse.addClass('fail').find('.response-status').text(rm_giapi.l10n_error+' '+error_code).siblings('.response-message').text(val.error.message);
49
+ }
50
+ });
51
+ }
52
+ }
53
+ } else {
54
+ // Bing URL submission API.
55
+ if ( typeof info.error !== 'undefined' ) {
56
+ $ufResponse.addClass('fail').find('.response-status').text(rm_giapi.l10n_error+' '+info.error.code).siblings('.response-message').text(info.error.message);
57
+ } else {
58
+ $ufResponse.addClass('success').find('.response-status').text(rm_giapi.l10n_success+' ').siblings('.response-message').text(rm_giapi.l10n_see_response);
59
+ }
60
+ }
61
+
62
+ var rawdata = n + " " + action + ": " + urls_str + "\n" + JSON.stringify(info, null, 2) + "\n" + "-".repeat(56);
63
+ var current = $responseTextarea.val();
64
+ $responseTextarea.val(rawdata + "\n" + current);
65
+ };
66
+
67
+ $('#giapi-response-trigger').click(function(e) {
68
+ e.preventDefault();
69
+ $(this).find('.dashicons').toggleClass('dashicons-arrow-down-alt2 dashicons-arrow-up-alt2')
70
+ $('#giapi-response-wrapper').toggle();
71
+ });
72
+
73
+ $('#instant-indexing').submit(function(event) {
74
+ event.preventDefault();
75
+ $submitButton.attr('disabled', 'disabled');
76
+ var input_url = $urlField.val();
77
+ var api_action = $actionRadio.filter(':checked').val();
78
+ var nonce = $('#_wpnonce').val();
79
+ $.ajax({
80
+ url: ajaxurl,
81
+ type: 'POST',
82
+ dataType: 'json',
83
+ data: { action: 'rm_giapi', url: input_url, api_action: api_action, _wpnonce: nonce },
84
+ }).always(function(data) {
85
+ logResponse( data, input_url, api_action );
86
+ $submitButton.removeAttr('disabled');
87
+ $.ajax({
88
+ url: ajaxurl,
89
+ type: 'POST',
90
+ dataType: 'json',
91
+ data: { action: 'rm_giapi_limits', _wpnonce: nonce },
92
+ })
93
+ .done(function( data ) {
94
+ $.each( data, function(index, val) {
95
+ $('#giapi-limit-'+index).text(val);
96
+ });
97
+ });
98
+ });
99
+ });
100
+
101
+ if ( rm_giapi.submit_onload ) {
102
+ $('#instant-indexing').submit();
103
+ }
104
+
105
+ $(window).on('load', function() {
106
+ $('#giapi-submit').prop('disabled', false);
107
+ });
108
+ });
assets/js/console.min.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(e){var r={};function s(t){if(r[t])return r[t].exports;var i=r[t]={i:t,l:!1,exports:{}};return e[t].call(i.exports,i,i.exports,s),i.l=!0,i.exports}s.m=e,s.c=r,s.d=function(e,r,t){s.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},s.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},s.t=function(e,r){if(1&r&&(e=s(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(s.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var i in e)s.d(t,i,function(r){return e[r]}.bind(null,i));return t},s.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return s.d(r,"a",r),r},s.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},s.p="",s(s.s=0)}([function(e,r){jQuery(document).ready((function(e){var r=e("#giapi-response"),s=e("#giapi-submit"),t=e("#giapi-url"),i=e(".giapi-action"),n=e("#giapi-response-userfriendly");e("#giapi-response-trigger").click((function(r){r.preventDefault(),e(this).find(".dashicons").toggleClass("dashicons-arrow-down-alt2 dashicons-arrow-up-alt2"),e("#giapi-response-wrapper").toggle()})),e("#instant-indexing").submit((function(a){a.preventDefault(),s.attr("disabled","disabled");var o=t.val(),l=i.filter(":checked").val(),d=e("#_wpnonce").val();e.ajax({url:ajaxurl,type:"POST",dataType:"json",data:{action:"rm_giapi",url:o,api_action:l,_wpnonce:d}}).always((function(a){!function(s,a,o){var l=(g=new Date).toLocaleTimeString(),d=t.val().split("\n").filter(Boolean),u=d[0],p=!1,c=i.filter(":checked").val();if(d.length>1&&(u="(batch)",p=!0),n.removeClass("not-ready fail success").addClass("ready").find(".response-id").html("<strong>"+c+"</strong> "+u),"bing_submit"!==o)if(p)n.addClass("success").find(".response-status").text(rm_giapi.l10n_success+" ").siblings(".response-message").text(rm_giapi.l10n_see_response),void 0!==s.error?n.addClass("fail").find(".response-status").text(rm_giapi.l10n_error+" "+s.error.code).siblings(".response-message").text(s.error.message):e.each(s,(function(e,r){if(void 0!==r.error){var s="";void 0!==r.error.code&&(s=r.error.code);void 0!==r.error.message&&r.error.message,n.addClass("fail").find(".response-status").text(rm_giapi.l10n_error+" "+s).siblings(".response-message").text(r.error.message)}}));else if(void 0!==s.error)n.addClass("fail").find(".response-status").text(rm_giapi.l10n_error+" "+s.error.code).siblings(".response-message").text(s.error.message);else{var f=s;void 0!==s.urlNotificationMetadata&&(f=s.urlNotificationMetadata);var g=new Date(f.latestUpdate.notifyTime);n.addClass("success").find(".response-status").text(rm_giapi.l10n_success+" ").siblings(".response-message").text(rm_giapi.l10n_last_updated+" "+g.toString())}else void 0!==s.error?n.addClass("fail").find(".response-status").text(rm_giapi.l10n_error+" "+s.error.code).siblings(".response-message").text(s.error.message):n.addClass("success").find(".response-status").text(rm_giapi.l10n_success+" ").siblings(".response-message").text(rm_giapi.l10n_see_response);var m=l+" "+c+": "+u+"\n"+JSON.stringify(s,null,2)+"\n"+"-".repeat(56),_=r.val();r.val(m+"\n"+_)}(a,0,l),s.removeAttr("disabled"),e.ajax({url:ajaxurl,type:"POST",dataType:"json",data:{action:"rm_giapi_limits",_wpnonce:d}}).done((function(r){e.each(r,(function(r,s){e("#giapi-limit-"+r).text(s)}))}))}))})),rm_giapi.submit_onload&&e("#instant-indexing").submit(),e(window).on("load",(function(){e("#giapi-submit").prop("disabled",!1)}))}))}]);
assets/js/dashboard.js ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // minifyOnSave
2
+ jQuery(document).ready(function($) {
3
+ var dialog = $( '#rank-math-feedback-form' )
4
+
5
+ dialog.on( 'click', '.button-close', function( event ) {
6
+ event.preventDefault()
7
+ dialog.fadeOut()
8
+ })
9
+
10
+ // Enable/Disable Modules
11
+ $( '.module-listing .rank-math-box:not(.active), a.rank-math-tab' ).on( 'click', function(e) {
12
+ e.preventDefault();
13
+
14
+ $( '#rank-math-feedback-form' ).fadeIn();
15
+
16
+ return false;
17
+ });
18
+
19
+ $( '#rank-math-feedback-form' ).on( 'click', function( e ) {
20
+ if ( 'rank-math-feedback-form' === e.target.id ) {
21
+ $( this ).find( '.button-close' ).trigger( 'click' );
22
+ }
23
+ });
24
+
25
+ $('a.nav-tab').not('.nav-tab-active').click(function(event) {
26
+ $( '#rank-math-feedback-form' ).fadeIn();
27
+ });
28
+
29
+ // Install & Activate Rank Math from modal.
30
+ var tryRankmathPanel = $( '.try-rankmath-panel' ),
31
+ installRankmathSuccess;
32
+
33
+ installRankmathSuccess = function( response ) {
34
+ response.activateUrl += '&from=schema-try-rankmath';
35
+ response.activateLabel = wp.updates.l10n.activatePluginLabel.replace( '%s', response.pluginName );
36
+ tryRankmathPanel.find('.install-now').text('Activating...');
37
+ window.location.href = response.activateUrl;
38
+ };
39
+
40
+ tryRankmathPanel.on( 'click', '.install-now', function( e ) {
41
+ e.preventDefault();
42
+ var args = {
43
+ slug: $( e.target ).data( 'slug' ),
44
+ success: installRankmathSuccess
45
+ };
46
+ wp.updates.installPlugin( args );
47
+ } );
48
+ });
assets/js/dashboard.min.js ADDED
@@ -0,0 +1 @@
 
1
+ !function(t){var e={};function n(a){if(e[a])return e[a].exports;var r=e[a]={i:a,l:!1,exports:{}};return t[a].call(r.exports,r,r.exports,n),r.l=!0,r.exports}n.m=t,n.c=e,n.d=function(t,e,a){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:a})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var a=Object.create(null);if(n.r(a),Object.defineProperty(a,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var r in t)n.d(a,r,function(e){return t[e]}.bind(null,r));return a},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s=1)}([,function(t,e){jQuery(document).ready((function(t){var e=t("#rank-math-feedback-form");e.on("click",".button-close",(function(t){t.preventDefault(),e.fadeOut()})),t(".module-listing .rank-math-box:not(.active), a.rank-math-tab").on("click",(function(e){return e.preventDefault(),t("#rank-math-feedback-form").fadeIn(),!1})),t("#rank-math-feedback-form").on("click",(function(e){"rank-math-feedback-form"===e.target.id&&t(this).find(".button-close").trigger("click")})),t("a.nav-tab").not(".nav-tab-active").click((function(e){t("#rank-math-feedback-form").fadeIn()}));var n,a=t(".try-rankmath-panel");n=function(t){t.activateUrl+="&from=schema-try-rankmath",t.activateLabel=wp.updates.l10n.activatePluginLabel.replace("%s",t.pluginName),a.find(".install-now").text("Activating..."),window.location.href=t.activateUrl},a.on("click",".install-now",(function(e){e.preventDefault();var a={slug:t(e.target).data("slug"),success:n};wp.updates.installPlugin(a)}))}))}]);
includes/class-instant-indexing-module.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /**
4
+ * Module class loaded by Rank Math. This plugin works independently of
5
+ * Rank Math, so this is just a placeholder.
6
+ */
7
+ class RM_GIAPI_Module {}
includes/class-instant-indexing.php ADDED
@@ -0,0 +1,1047 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Main plugin class.
4
+ *
5
+ * @package Instant Indexing
6
+ */
7
+ class RM_GIAPI {
8
+
9
+ /**
10
+ * Plugin version.
11
+ *
12
+ * @var string
13
+ */
14
+ public $version = '1.1.1';
15
+
16
+ /**
17
+ * Holds the admin menu hook suffix for the "dummy" dashboard.
18
+ *
19
+ * @var string
20
+ */
21
+ public $dashboard_menu_hook_suffix = '';
22
+
23
+ /**
24
+ * Holds the admin menu hook suffix for Rank Math > Instant Indexing
25
+ *
26
+ * @var string
27
+ */
28
+ public $menu_hook_suffix = '';
29
+
30
+ /**
31
+ * The default tab when visiting the admin page.
32
+ *
33
+ * @var string
34
+ */
35
+ public $default_nav_tab = '';
36
+
37
+ /**
38
+ * Holds the current admin tab.
39
+ *
40
+ * @var string
41
+ */
42
+ public $current_nav_tab = '';
43
+
44
+ /**
45
+ * Holds the admin tabs.
46
+ *
47
+ * @var array
48
+ */
49
+ public $nav_tabs = [];
50
+
51
+ /**
52
+ * Holds the admin notice messages.
53
+ *
54
+ * @var array
55
+ */
56
+ public $notices = [];
57
+
58
+ /**
59
+ * Holds the default settings.
60
+ *
61
+ * @var array
62
+ */
63
+ public $settings_defaults = [];
64
+
65
+ /**
66
+ * Debug mode. Enable with define( 'GIAPI_DEBUG', true );
67
+ *
68
+ * @var bool
69
+ */
70
+ public $debug = false;
71
+
72
+ /**
73
+ * Check if Rank Math SEO is installed.
74
+ *
75
+ * @var bool
76
+ */
77
+ public $is_rm_active = false;
78
+
79
+ /**
80
+ * Rank Math Instant Indexing API.
81
+ *
82
+ * @var bool
83
+ */
84
+ public $rmapi = null;
85
+
86
+ /**
87
+ * URL of the Google plugin setup guide on rankmath.com.
88
+ *
89
+ * @var string
90
+ */
91
+ public $google_guide_url = 'https://rankmath.com/blog/google-indexing-api/?utm_source=Instant+Indexing+Plugin&utm_medium=Setup+Guide+Button&utm_campaign=WP';
92
+
93
+ /**
94
+ * URL of the Bing plugin setup guide on rankmath.com.
95
+ *
96
+ * @var string
97
+ */
98
+ public $bing_guide_url = 'https://rankmath.com/blog/bing-indexing-api/?utm_source=Instant+Indexing+Plugin&utm_medium=Setup+Guide+Button&utm_campaign=WP';
99
+
100
+ /**
101
+ * Constructor method.
102
+ */
103
+ public function __construct() {
104
+ $this->debug = ( defined( 'GIAPI_DEBUG' ) && GIAPI_DEBUG );
105
+ $this->is_rm_active = function_exists( 'rank_math' );
106
+
107
+ $this->default_nav_tab = 'google_settings';
108
+ $this->settings_defaults = [
109
+ 'json_key' => '',
110
+ 'bing_api_key' => '',
111
+ 'post_types' => [],
112
+ 'bing_post_types' => [
113
+ 'post' => 'post',
114
+ 'page' => 'page',
115
+ ],
116
+ ];
117
+
118
+ $this->nav_tabs = [
119
+ 'google_settings' => __( 'Google API Settings', 'fast-indexing-api' ),
120
+ 'bing_settings' => __( 'Bing API Settings', 'fast-indexing-api' ),
121
+ 'console' => __( 'Console', 'fast-indexing-api' ),
122
+ ];
123
+
124
+ if ( $this->is_rm_active ) {
125
+ $this->rmapi = new RankMath\Instant_Indexing\Api();
126
+ add_action( 'admin_init', [ $this, 'remove_rm_admin_page' ] );
127
+ } else {
128
+ unset( $this->nav_tabs['bing_settings'] );
129
+ }
130
+
131
+ if ( $this->get_setting( 'json_key' ) ) {
132
+ $this->nav_tabs['google_settings'] = '<span class="dashicons dashicons-yes-alt"></span> ' . $this->nav_tabs['google_settings'];
133
+ unset( $this->nav_tabs['console'] );
134
+ $this->nav_tabs = [ 'console' => __( 'Console', 'fast-indexing-api' ) ] + $this->nav_tabs;
135
+ $this->default_nav_tab = 'console';
136
+ }
137
+
138
+ if ( $this->is_rm_active && $this->get_setting( 'bing_api_key' ) ) {
139
+ $this->nav_tabs['bing_settings'] = '<span class="dashicons dashicons-yes-alt"></span> ' . $this->nav_tabs['bing_settings'];
140
+ unset( $this->nav_tabs['console'] );
141
+ $this->nav_tabs = [ 'console' => __( 'Console', 'fast-indexing-api' ) ] + $this->nav_tabs;
142
+ $this->default_nav_tab = 'console';
143
+ }
144
+
145
+ $this->current_nav_tab = $this->default_nav_tab;
146
+ if ( isset( $_GET['tab'] ) && isset( $this->nav_tabs[ $_GET['tab'] ] ) ) {
147
+ $this->current_nav_tab = $_GET['tab']; //phpcs:ignore
148
+ }
149
+ add_action( 'admin_menu', [ $this, 'admin_menu' ], 20 );
150
+ add_action( 'admin_footer', [ $this, 'admin_footer' ], 20 );
151
+ add_action( 'admin_enqueue_scripts', [ $this, 'admin_enqueue_scripts' ] );
152
+ add_action( 'wp_ajax_rm_giapi', [ $this, 'ajax_rm_giapi' ] );
153
+ add_action( 'wp_ajax_rm_giapi_limits', [ $this, 'ajax_get_limits' ] );
154
+ add_action( 'admin_init', [ $this, 'rm_missing_admin_notice_error' ], 20, 1 );
155
+ add_action( 'admin_notices', [ $this, 'display_notices' ], 10, 1 );
156
+ add_action( 'load-rank-math_page_instant-indexing', [ $this, 'save_settings' ], 10, 1 );
157
+ add_filter( 'plugin_action_links_' . RM_GIAPI_FILE, [ $this, 'plugin_action_links' ] );
158
+
159
+ if ( $this->get_setting( 'json_key' ) ) {
160
+ $post_types = $this->get_setting( 'post_types', [] );
161
+ foreach ( $post_types as $key => $post_type ) {
162
+ if ( empty( $post_type ) ) {
163
+ continue;
164
+ }
165
+ add_action( 'save_post_' . $post_type, [ $this, 'publish_post' ], 10, 2 );
166
+ add_filter( 'bulk_actions-edit-' . $post_type, [ $this, 'register_bulk_actions' ] );
167
+ add_filter( 'handle_bulk_actions-edit-' . $post_type, [ $this, 'bulk_action_handler' ], 10, 3 );
168
+ }
169
+ add_action( 'trashed_post', [ $this, 'delete_post' ], 10, 1 );
170
+ }
171
+
172
+ if ( $this->is_rm_active && $this->get_setting( 'bing_api_key' ) ) {
173
+ $post_types = $this->get_setting( 'bing_post_types', [] );
174
+ foreach ( $post_types as $key => $post_type ) {
175
+ if ( empty( $post_type ) ) {
176
+ continue;
177
+ }
178
+ add_action( 'save_post_' . $post_type, [ $this, 'bing_publish_post' ], 10, 2 );
179
+ add_filter( 'bulk_actions-edit-' . $post_type, [ $this, 'bing_register_bulk_actions' ] );
180
+ add_filter( 'handle_bulk_actions-edit-' . $post_type, [ $this, 'bing_bulk_action_handler' ], 10, 3 );
181
+ }
182
+ }
183
+
184
+ if ( $this->get_setting( 'json_key' ) || $this->get_setting( 'bing_api_key' ) ) {
185
+ add_filter( 'post_row_actions', [ $this, 'send_to_api_link' ], 10, 2 );
186
+ add_filter( 'page_row_actions', [ $this, 'send_to_api_link' ], 10, 2 );
187
+ }
188
+
189
+ // Localization.
190
+ add_action( 'plugins_loaded', [ $this, 'giapi_load_textdomain' ] );
191
+
192
+ add_filter( 'rank_math/modules', [ $this, 'filter_modules' ], 25 );
193
+ }
194
+
195
+ public function remove_rm_admin_page() {
196
+ remove_submenu_page( 'rank-math', 'rank-math-options-instant-indexing' );
197
+ }
198
+
199
+ /**
200
+ * Register actions for the bulk edit dropdowns on the post listing screen.
201
+ *
202
+ * @param array $bulk_actions Actions.
203
+ * @return array $bulk_actions
204
+ */
205
+ public function register_bulk_actions( $bulk_actions ) {
206
+ $bulk_actions['giapi_update'] = __( 'Instant Indexing: Google Update', 'fast-indexing-api' );
207
+ $bulk_actions['giapi_getstatus'] = __( 'Instant Indexing: Google Get Status', 'fast-indexing-api' );
208
+
209
+ return $bulk_actions;
210
+ }
211
+
212
+ /**
213
+ * Register additional actions for the bulk edit dropdowns on the post listing screen.
214
+ *
215
+ * @param array $bulk_actions Actions.
216
+ * @return array $bulk_actions
217
+ */
218
+ public function bing_register_bulk_actions( $bulk_actions ) {
219
+ $bulk_actions['giapi_bing_submit'] = __( 'Instant Indexing: Bing Submit', 'fast-indexing-api' );
220
+
221
+ return $bulk_actions;
222
+ }
223
+
224
+ /**
225
+ * Handle custom bulk actions.
226
+ *
227
+ * @param string $redirect_to The redirect URL.
228
+ * @param string $doaction The action being taken.
229
+ * @param array $post_ids The items to take the action on.
230
+ *
231
+ * @return string $redirect_to The redirect URL.
232
+ */
233
+ public function bulk_action_handler( $redirect_to, $doaction, $post_ids ) {
234
+ if ( $doaction !== 'giapi_update' && $doaction !== 'giapi_getstatus' ) {
235
+ return $redirect_to;
236
+ }
237
+
238
+ $nonce = wp_create_nonce( 'giapi-action' );
239
+ $redirect_to = add_query_arg(
240
+ [
241
+ 'page' => 'instant-indexing',
242
+ 'tab' => 'console',
243
+ 'apiaction' => substr( $doaction, 6 ),
244
+ 'apipostid' => $post_ids,
245
+ '_wpnonce' => $nonce,
246
+
247
+ ],
248
+ admin_url( 'admin.php' )
249
+ );
250
+ return $redirect_to;
251
+ }
252
+
253
+ /**
254
+ * Handle custom bulk actions.
255
+ *
256
+ * @param string $redirect_to The redirect URL.
257
+ * @param string $doaction The action being taken.
258
+ * @param array $post_ids The items to take the action on.
259
+ *
260
+ * @return string $redirect_to The redirect URL.
261
+ */
262
+ public function bing_bulk_action_handler( $redirect_to, $doaction, $post_ids ) {
263
+ if ( $doaction !== 'bing_submit' ) {
264
+ return $redirect_to;
265
+ }
266
+
267
+ $nonce = wp_create_nonce( 'giapi-action' );
268
+ $redirect_to = add_query_arg(
269
+ [
270
+ 'page' => 'instant-indexing',
271
+ 'tab' => 'console',
272
+ 'apiaction' => substr( $doaction, 6 ),
273
+ 'apipostid' => $post_ids,
274
+ '_wpnonce' => $nonce,
275
+
276
+ ],
277
+ admin_url( 'admin.php' )
278
+ );
279
+ return $redirect_to;
280
+ }
281
+
282
+ /**
283
+ * Add new action links for the post listing screen.
284
+ *
285
+ * @param array $actions Current action links.
286
+ * @param object $post WP_Post object.
287
+ * @return array $actions New action links.
288
+ */
289
+ public function send_to_api_link( $actions, $post ) {
290
+ if ( ! current_user_can( apply_filters( 'rank_math/indexing_api/capability', 'manage_options' ) ) ) {
291
+ return $actions;
292
+ }
293
+
294
+ if ( $post->post_status !== 'publish' ) {
295
+ return $actions;
296
+ }
297
+
298
+ $post_types = $this->get_setting( 'post_types', [] );
299
+ $bing_post_types = $this->get_setting( 'bing_post_types', [] );
300
+ if ( ! in_array( $post->post_type, $post_types, true ) && ! in_array( $post->post_type, $bing_post_types, true ) ) {
301
+ return $actions;
302
+ }
303
+
304
+ $nonce = wp_create_nonce( 'giapi-action' );
305
+ if ( in_array( $post->post_type, $post_types, true ) ) {
306
+ $actions['rmgiapi_update'] = '<a href="' . admin_url( 'admin.php?page=instant-indexing&tab=console&apiaction=update&_wpnonce=' . $nonce . '&apiurl=' . rawurlencode( get_permalink( $post ) ) ) . '" class="rmgiapi-link rmgiapi_update">' . __( 'Instant Indexing: Google Update', 'fast-indexing-api' ) . '</a>';
307
+ $actions['rmgiapi_getstatus'] = '<a href="' . admin_url( 'admin.php?page=instant-indexing&tab=console&apiaction=getstatus&_wpnonce=' . $nonce . '&apiurl=' . rawurlencode( get_permalink( $post ) ) ) . '" class="rmgiapi-link rmgiapi_update">' . __( 'Instant Indexing: Google Get Status', 'fast-indexing-api' ) . '</a>';
308
+ }
309
+ if ( in_array( $post->post_type, $bing_post_types, true ) ) {
310
+ $actions['rmgiapi_bing_submit'] = '<a href="' . admin_url( 'admin.php?page=instant-indexing&tab=console&apiaction=bing_submit&_wpnonce=' . $nonce . '&apiurl=' . rawurlencode( get_permalink( $post ) ) ) . '" class="rmgiapi-link rmgiapi_update">' . __( 'Instant Indexing: Bing Submit', 'fast-indexing-api' ) . '</a>';
311
+ }
312
+
313
+ return $actions;
314
+ }
315
+
316
+ /**
317
+ * Load text-domain.
318
+ *
319
+ * @return void
320
+ */
321
+ public function giapi_load_textdomain() {
322
+ load_plugin_textdomain( 'fast-indexing-api', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
323
+ }
324
+
325
+ /**
326
+ * AJAX handler for the console.
327
+ *
328
+ * @return void
329
+ */
330
+ public function ajax_rm_giapi() {
331
+ check_ajax_referer( 'giapi-console' );
332
+
333
+ if ( ! current_user_can( apply_filters( 'rank_math/indexing_api/capability', 'manage_options' ) ) ) {
334
+ die( '0' );
335
+ }
336
+
337
+ $url_input = $this->get_input_urls();
338
+ $action = sanitize_title( wp_unslash( $_POST['api_action'] ) );
339
+ header( 'Content-type: application/json' );
340
+
341
+ $result = $this->send_to_api( $url_input, $action );
342
+ wp_send_json( $result );
343
+ exit();
344
+ }
345
+
346
+ /**
347
+ * Submit one or more URLs to Google's API using their API library.
348
+ *
349
+ * @param array $url_input URLs.
350
+ * @param string $action API action.
351
+ * @return array $data Result of the API call.
352
+ */
353
+ public function send_to_api( $url_input, $action ) {
354
+ $url_input = (array) $url_input;
355
+
356
+ if ( strpos( $action, 'bing' ) === false ) {
357
+ // This is NOT a Bing API request, so it's Google.
358
+ include_once RM_GIAPI_PATH . 'vendor/autoload.php';
359
+ $this->client = new Google_Client();
360
+ $this->client->setAuthConfig( json_decode( $this->get_setting( 'json_key' ), true ) );
361
+ $this->client->setConfig( 'base_path', 'https://indexing.googleapis.com' );
362
+ $this->client->addScope( 'https://www.googleapis.com/auth/indexing' );
363
+
364
+ // Batch request.
365
+ $this->client->setUseBatch( true );
366
+ // init google batch and set root URL.
367
+ $service = new Google_Service_Indexing( $this->client );
368
+ $batch = new Google_Http_Batch( $this->client, false, 'https://indexing.googleapis.com' );
369
+ foreach ( $url_input as $i => $url ) {
370
+ $post_body = new Google_Service_Indexing_UrlNotification();
371
+ if ( $action === 'getstatus' ) {
372
+ $request_part = $service->urlNotifications->getMetadata( [ 'url' => $url ] ); // phpcs:ignore
373
+ } else {
374
+ $post_body->setType( $action === 'update' ? 'URL_UPDATED' : 'URL_DELETED' );
375
+ $post_body->setUrl( $url );
376
+ $request_part = $service->urlNotifications->publish( $post_body ); // phpcs:ignore
377
+ }
378
+ $batch->add( $request_part, 'url-' . $i );
379
+ }
380
+
381
+ $results = $batch->execute();
382
+ $data = [];
383
+ $res_count = count( $results );
384
+ foreach ( $results as $id => $response ) {
385
+ // Change "response-url-1" to "url-1".
386
+ $local_id = substr( $id, 9 );
387
+ if ( is_a( $response, 'Google_Service_Exception' ) ) {
388
+ $data[ $local_id ] = json_decode( $response->getMessage() );
389
+ } else {
390
+ $data[ $local_id ] = (array) $response->toSimpleObject();
391
+ }
392
+ if ( $res_count === 1 ) {
393
+ $data = $data[ $local_id ];
394
+ }
395
+ }
396
+ } else {
397
+ // Bing submit URL API.
398
+ $request = $this->rmapi->batch_submit_urls( $url_input );
399
+ if ( 'ok' === $request['status'] ) {
400
+ $data = [
401
+ 'success' => true,
402
+ ];
403
+ } else {
404
+ $data = [
405
+ 'error' => [
406
+ 'code' => '',
407
+ 'message' => $request['message'],
408
+ ],
409
+ ];
410
+ }
411
+ }
412
+
413
+ $this->log_request( $action );
414
+
415
+ if ( $this->debug ) {
416
+ error_log( 'Rank Math Instant Index: ' . $action . ' ' . $url_input[0] . ( count( $url_input ) > 1 ? ' (+)' : '' ) . "\n" . print_r( $data, true ) ); // phpcs:ignore
417
+ }
418
+
419
+ return $data;
420
+ }
421
+
422
+ /**
423
+ * Log request type & timestamp to keep track of remaining quota.
424
+ *
425
+ * @param string $type API action.
426
+ * @return void
427
+ */
428
+ public function log_request( $type ) {
429
+ $requests_log = get_option(
430
+ 'giapi_requests',
431
+ [
432
+ 'update' => [],
433
+ 'delete' => [],
434
+ 'getstatus' => [],
435
+ 'bing_submit' => [],
436
+ ]
437
+ );
438
+ $requests_log[ $type ][] = time();
439
+ if ( count( $requests_log[ $type ] ) > 600 ) {
440
+ $requests_log[ $type ] = array_slice( $requests_log[ $type ], -600, 600, true );
441
+ }
442
+ update_option( 'giapi_requests', $requests_log );
443
+ }
444
+
445
+ /**
446
+ * Get current quota (limits minus usage).
447
+ *
448
+ * @return array Current quota.
449
+ */
450
+ public function get_limits() {
451
+ $current_limits = [
452
+ 'publishperday' => 0,
453
+ 'permin' => 0,
454
+ 'metapermin' => 0,
455
+
456
+ 'bing_submitperday' => 0,
457
+ ];
458
+
459
+ $limit_publishperday = apply_filters( 'rank_math/indexing_api/limit_publishperday', 200 );
460
+ $limit_permin = apply_filters( 'rank_math/indexing_api/limit_perminute', 600 );
461
+ $limit_metapermin = apply_filters( 'rank_math/indexing_api/limit_metaperminute', 180 );
462
+
463
+ $limit_bingsubmitperday = apply_filters( 'rank_math/indexing_api/limit_bing_submitperday', 10 );
464
+
465
+ $requests_log = get_option(
466
+ 'giapi_requests',
467
+ [
468
+ 'update' => [],
469
+ 'delete' => [],
470
+ 'getstatus' => [],
471
+ 'bing_submit' => [],
472
+ ]
473
+ );
474
+
475
+ $timestamp_1day_ago = strtotime( '-1 day' );
476
+ $timestamp_1min_ago = strtotime( '-1 minute' );
477
+
478
+ $publish_1day = 0;
479
+ $all_1min = 0;
480
+ $meta_1min = 0;
481
+
482
+ foreach ( $requests_log['update'] as $time ) {
483
+ if ( $time > $timestamp_1day_ago ) {
484
+ $publish_1day++;
485
+ }
486
+ if ( $time > $timestamp_1min_ago ) {
487
+ $all_1min++;
488
+ }
489
+ }
490
+ foreach ( $requests_log['delete'] as $time ) {
491
+ if ( $time > $timestamp_1min_ago ) {
492
+ $all_1min++;
493
+ }
494
+ }
495
+ foreach ( $requests_log['getstatus'] as $time ) {
496
+ if ( $time > $timestamp_1min_ago ) {
497
+ $all_1min++;
498
+ $meta_1min++;
499
+ }
500
+ }
501
+
502
+ $bing_submit_1day = 0;
503
+ if ( ! isset( $requests_log['bing_submit'] ) ) {
504
+ $requests_log['bing_submit'] = [];
505
+ }
506
+
507
+ foreach ( $requests_log['bing_submit'] as $time ) {
508
+ if ( $time > $timestamp_1day_ago ) {
509
+ $bing_submit_1day++;
510
+ }
511
+ }
512
+
513
+ $current_limits['publishperday'] = $limit_publishperday - $publish_1day;
514
+ $current_limits['permin'] = $limit_permin - $all_1min;
515
+ $current_limits['metapermin'] = $limit_metapermin - $meta_1min;
516
+
517
+ $current_limits['bing_submitperday'] = $limit_bingsubmitperday - $bing_submit_1day;
518
+
519
+ $current_limits['publishperday_max'] = $limit_publishperday;
520
+ $current_limits['permin_max'] = $limit_permin;
521
+ $current_limits['metapermin_max'] = $limit_metapermin;
522
+
523
+ $current_limits['bing_submitperday_max'] = $limit_bingsubmitperday;
524
+
525
+ return $current_limits;
526
+ }
527
+
528
+ /**
529
+ * AJAX handler to get current quota in JSON format.
530
+ *
531
+ * @return void
532
+ */
533
+ public function ajax_get_limits() {
534
+ check_ajax_referer( 'giapi-console' );
535
+
536
+ if ( ! current_user_can( apply_filters( 'rank_math/indexing_api/capability', 'manage_options' ) ) ) {
537
+ die( '0' );
538
+ }
539
+
540
+ wp_send_json( $this->get_limits() );
541
+ die();
542
+ }
543
+
544
+ /**
545
+ * Normalize input URLs.
546
+ *
547
+ * @return array Input URLs.
548
+ */
549
+ public function get_input_urls() {
550
+ return array_values( array_filter( array_map( 'trim', explode( "\n", sanitize_textarea_field( wp_unslash( $_POST['url'] ) ) ) ) ) );
551
+ }
552
+
553
+ /**
554
+ * Add admin menu items.
555
+ *
556
+ * @return void
557
+ */
558
+ public function admin_menu() {
559
+ if ( ! class_exists( 'RankMath' ) ) {
560
+ $this->dashboard_menu_hook_suffix = add_menu_page(
561
+ 'Rank Math',
562
+ 'Rank Math',
563
+ apply_filters( 'rank_math/indexing_api/capability', 'manage_options' ),
564
+ 'instant-indexing-dashboard',
565
+ null,
566
+ 'data:image/svg+xml;base64,' . \base64_encode( '<svg viewBox="0 0 462.03 462.03" xmlns="http://www.w3.org/2000/svg" width="20"><g fill="#fff"><path d="m462 234.84-76.17 3.43 13.43 21-127 81.18-126-52.93-146.26 60.97 10.14 24.34 136.1-56.71 128.57 54 138.69-88.61 13.43 21z"/><path d="m54.1 312.78 92.18-38.41 4.49 1.89v-54.58h-96.67zm210.9-223.57v235.05l7.26 3 89.43-57.05v-181zm-105.44 190.79 96.67 40.62v-165.19h-96.67z"/></g></svg>' ),
567
+ 76
568
+ );
569
+ $this->dashboard_menu_hook_suffix = add_submenu_page( 'instant-indexing-dashboard', 'Rank Math', __( 'Dashboard', 'fast-indexing-api' ), apply_filters( 'rank_math/indexing_api/capability', 'manage_options' ), 'instant-indexing-dashboard', array( $this, 'show_dashboard' ) );
570
+ $this->menu_hook_suffix = add_submenu_page( 'instant-indexing-dashboard', __( 'Instant Indexing', 'fast-indexing-api' ), __( 'Instant Indexing', 'fast-indexing-api' ), apply_filters( 'rank_math/indexing_api/capability', 'manage_options' ), 'instant-indexing', array( $this, 'show_admin_page' ) );
571
+
572
+ return;
573
+ }
574
+
575
+ $this->menu_hook_suffix = add_submenu_page( 'rank-math', __( 'Instant Indexing', 'fast-indexing-api' ), __( 'Instant Indexing', 'fast-indexing-api' ), apply_filters( 'rank_math/indexing_api/capability', 'manage_options' ), 'instant-indexing', [ $this, 'show_admin_page' ] );
576
+ }
577
+
578
+ /**
579
+ * Output Indexing API Console page contents.
580
+ *
581
+ * @return void
582
+ */
583
+ public function show_console() {
584
+ $limits = $this->get_limits();
585
+ $urls = home_url( '/' );
586
+ if ( isset( $_GET['apiurl'] ) ) {
587
+ $urls = esc_url_raw( wp_unslash( $_GET['apiurl'] ) );
588
+ } elseif ( isset( $_GET['apipostid'] ) ) {
589
+ $ids = (array) wp_unslash( $_GET['apipostid'] ); // phpcs:ignore
590
+ $ids = array_map( 'absint', $ids ); // We sanitize it here.
591
+ $urls = '';
592
+ foreach ( $ids as $id ) {
593
+ if ( get_post_status( $id ) === 'publish' ) {
594
+ $urls .= get_permalink( $id ) . "\n";
595
+ }
596
+ }
597
+ }
598
+ $selected_action = 'update';
599
+ if ( ! $this->get_setting( 'json_key' ) ) {
600
+ $selected_action = 'bing_submit';
601
+ }
602
+ if ( isset( $_GET['apiaction'] ) ) {
603
+ $selected_action = sanitize_title( wp_unslash( $_GET['apiaction'] ) );
604
+ }
605
+
606
+ include_once RM_GIAPI_PATH . 'views/console.php';
607
+ }
608
+
609
+ /**
610
+ * Admin page content.
611
+ *
612
+ * @return void
613
+ */
614
+ public function show_admin_page() {
615
+ $this->nav_tabs();
616
+
617
+ $method = 'show_' . $this->current_nav_tab;
618
+ if ( method_exists( $this, $method ) ) {
619
+ $this->$method();
620
+ }
621
+ }
622
+
623
+ /**
624
+ * Admin page tabs.
625
+ *
626
+ * @return void
627
+ */
628
+ public function nav_tabs() {
629
+ echo '<div class="nav-tab-wrapper instant-indexing-nav-tabs">';
630
+ foreach ( $this->nav_tabs as $tab => $label ) {
631
+ echo '<a href="' . esc_url( add_query_arg( 'tab', $tab ) ) . '" class="nav-tab ' . ( $this->current_nav_tab == $tab ? 'nav-tab-active' : '' ) . '">' . wp_kses_post( $label ) . '</a>';
632
+ }
633
+ echo '</div>';
634
+ }
635
+
636
+ /**
637
+ * Enqueue CSS & JS for the admin pages.
638
+ *
639
+ * @param string $hook_suffix Hook suffix of the current page.
640
+ * @return void
641
+ */
642
+ public function admin_enqueue_scripts( $hook_suffix ) {
643
+ $min = '.min';
644
+ if ( $this->debug ) {
645
+ $min = '';
646
+ }
647
+ if ( $hook_suffix === $this->dashboard_menu_hook_suffix ) {
648
+ wp_enqueue_script( 'instant-indexing-dashboard', RM_GIAPI_URL . "assets/js/dashboard{$min}.js", [ 'jquery', 'updates' ], $this->version, true );
649
+ wp_enqueue_style( 'instant-indexing-dashboard', RM_GIAPI_URL . 'assets/css/dashboard.css', [], $this->version );
650
+ wp_enqueue_style( 'instant-indexing-common', RM_GIAPI_URL . 'assets/css/common.css', [], $this->version );
651
+ } elseif ( $hook_suffix === $this->menu_hook_suffix ) {
652
+ wp_enqueue_script( 'instant-indexing-console', RM_GIAPI_URL . "assets/js/console{$min}.js", [ 'jquery' ], $this->version, true );
653
+ wp_enqueue_style( 'instant-indexing-admin', RM_GIAPI_URL . 'assets/css/admin.css', [], $this->version );
654
+
655
+ $submit_onload = false;
656
+ if ( ! empty( $_GET['apiaction'] ) && ( ! empty( $_GET['apiurl'] ) || ! empty( $_GET['apipostid'] ) ) && wp_verify_nonce( wp_unslash( $_GET['_wpnonce'] ), 'giapi-action' ) ) {
657
+ $submit_onload = true;
658
+ }
659
+ wp_localize_script(
660
+ 'instant-indexing-console',
661
+ 'rm_giapi',
662
+ [
663
+ 'submit_onload' => $submit_onload,
664
+ 'l10n_success' => __( 'Success', 'fast-indexing-api' ),
665
+ 'l10n_error' => __( 'Error', 'fast-indexing-api' ),
666
+ 'l10n_last_updated' => __( 'Last updated ', 'fast-indexing-api' ),
667
+ 'l10n_see_response' => __( 'See response for details.', 'fast-indexing-api' ),
668
+ ]
669
+ );
670
+ }
671
+ }
672
+
673
+ /**
674
+ * Output Indexing API Settings page contents.
675
+ *
676
+ * @return void
677
+ */
678
+ public function show_google_settings() {
679
+ include_once RM_GIAPI_PATH . "views/google-settings.php";
680
+ }
681
+
682
+ /**
683
+ * Output URL Submission API Settings page contents.
684
+ *
685
+ * @return void
686
+ */
687
+ public function show_bing_settings() {
688
+ include_once RM_GIAPI_PATH . "views/bing-settings.php";
689
+ }
690
+
691
+ /**
692
+ * Handle settings save.
693
+ *
694
+ * @return void
695
+ */
696
+ public function save_settings() {
697
+ if ( ! isset( $_POST['giapi_settings'] ) ) {
698
+ return;
699
+ }
700
+ if ( ! isset( $_POST['_wpnonce'] ) || ! wp_verify_nonce( sanitize_title( wp_unslash( $_POST['_wpnonce'] ) ), 'giapi-save' ) ) {
701
+ $this->add_notice( __( 'Settings could not be updated.', 'fast-indexing-api' ), 'notice-error' );
702
+ return;
703
+ }
704
+ if ( ! current_user_can( apply_filters( 'rank_math/indexing_api/capability', 'manage_options' ) ) ) {
705
+ $this->add_notice( __( 'Settings could not be updated.', 'fast-indexing-api' ), 'notice-error' );
706
+ return;
707
+ }
708
+
709
+ $settings = [];
710
+ if ( isset( $_POST['giapi_settings']['json_key'] ) ) {
711
+ $settings = $this->save_google_settings();
712
+ } elseif ( isset( $_POST['giapi_settings']['bing_key'] ) ) {
713
+ $settings = $this->save_bing_settings();
714
+ }
715
+
716
+ if ( empty( $settings ) ) {
717
+ $this->add_notice( __( 'Settings could not be updated.', 'fast-indexing-api' ), 'notice-error' );
718
+ return;
719
+ }
720
+
721
+ update_option( 'rank-math-options-instant-indexing', $settings );
722
+ $this->add_notice( __( 'Settings updated.', 'fast-indexing-api' ), 'notice-success' );
723
+ }
724
+
725
+ /**
726
+ * Save data from "Google API Settings" admin page.
727
+ *
728
+ * @return array
729
+ */
730
+ private function save_google_settings() {
731
+ $json = sanitize_textarea_field( wp_unslash( $_POST['giapi_settings']['json_key'] ) );
732
+ if ( isset( $_FILES['json_file'] ) && ! empty( $_FILES['json_file']['tmp_name'] ) && file_exists( $_FILES['json_file']['tmp_name'] ) ) {
733
+ $json = file_get_contents( $_FILES['json_file']['tmp_name'] ); // phpcs:ignore
734
+ }
735
+
736
+ $post_types = isset( $_POST['giapi_settings']['post_types'] ) ? (array) $_POST['giapi_settings']['post_types'] : []; // phpcs:ignore
737
+ $post_types = array_map( 'sanitize_title', $post_types );
738
+
739
+ $settings = $this->get_settings();
740
+
741
+ $new_settings = [
742
+ 'json_key' => $json,
743
+ 'post_types' => array_values( $post_types ),
744
+ ];
745
+
746
+ return array_merge( $settings, $new_settings );
747
+ }
748
+
749
+ private function get_settings() {
750
+ $settings = get_option( 'rank-math-options-instant-indexing', [] );
751
+ if ( empty( $settings ) ) {
752
+ $old_settings = get_option( 'giapi_settings' );
753
+ if ( ! empty( $old_settings ) ) {
754
+ $settings = $old_settings;
755
+ }
756
+ }
757
+ $settings = array_merge( $this->settings_defaults, $settings );
758
+
759
+ return $settings;
760
+ }
761
+
762
+ /**
763
+ * Save data from "Bing API Settings" admin page.
764
+ *
765
+ * @return array
766
+ */
767
+ private function save_bing_settings() {
768
+ $bing_key = sanitize_text_field( wp_unslash( $_POST['giapi_settings']['bing_key'] ) );
769
+
770
+ $bing_post_types = (array) $_POST['giapi_settings']['bing_post_types']; // phpcs:ignore
771
+ $bing_post_types = array_map( 'sanitize_title', $bing_post_types );
772
+
773
+ $settings = $this->get_settings();
774
+
775
+ $new_settings = [
776
+ 'bing_api_key' => $bing_key,
777
+ 'bing_post_types' => array_values( $bing_post_types ),
778
+ ];
779
+
780
+ return array_merge( $settings, $new_settings );
781
+ }
782
+
783
+ /**
784
+ * Add a notice message to internal list, to be displayed on the next page load.
785
+ *
786
+ * @param string $message Meaningful message.
787
+ * @param string $class Additional class for the notice element.
788
+ * @param array $show_on Admin page IDs where the notice should be displayed.
789
+ * @param boolean $persist Whether the notice should be stored in the database until it is displayed.
790
+ * @param string $id Custom notice ID.
791
+ * @return void
792
+ */
793
+ public function add_notice( $message, $class = '', $show_on = null, $persist = false, $id = '' ) {
794
+ $notice = [
795
+ 'message' => $message,
796
+ 'class' => $class . ' is-dismissible',
797
+ 'show_on' => $show_on,
798
+ ];
799
+
800
+ if ( ! $id ) {
801
+ $id = md5( serialize( $notice ) );
802
+ }
803
+
804
+ if ( $persist ) {
805
+ $notices = get_option( 'giapi_notices', [] );
806
+ $notices[ $id ] = $notice;
807
+ update_option( 'giapi_notices', $notices );
808
+ return;
809
+ }
810
+ $this->notices[ $id ] = $notice;
811
+ }
812
+
813
+ /**
814
+ * Output notices from internal list.
815
+ *
816
+ * @return void
817
+ */
818
+ public function display_notices() {
819
+ $screen = get_current_screen();
820
+ $stored = get_option( 'giapi_notices', [] );
821
+ $this->notices = array_merge( $stored, $this->notices );
822
+ delete_option( 'giapi_notices' );
823
+ foreach ( $this->notices as $notice ) {
824
+ if ( ! empty( $notice['show_on'] ) && is_array( $notice['show_on'] ) && ! in_array( $screen->id, $notice['show_on'], true ) ) {
825
+ return;
826
+ }
827
+ $class = 'notice instant-indexing-notice ' . $notice['class'];
828
+ printf( '<div class="%1$s"><p>%2$s</p></div>', esc_attr( $class ), wp_kses_post( $notice['message'] ) );
829
+ }
830
+ }
831
+
832
+ /**
833
+ * Output checkbox inputs for the registered post types.
834
+ *
835
+ * @param string $api API provider: "google" or "bing".
836
+ * @return void
837
+ */
838
+ public function post_types_checkboxes( $api = 'google' ) {
839
+ $api_prefix = $api . '_';
840
+ if ( $api === 'google' ) {
841
+ $api_prefix = '';
842
+ }
843
+
844
+ $settings = $this->get_setting( $api_prefix . 'post_types', [] );
845
+ $post_types = get_post_types( [ 'public' => true ], 'objects' );
846
+ foreach ( $post_types as $post_type ) {
847
+ ?>
848
+ <label><input type="checkbox" name="giapi_settings[<?php echo sanitize_html_class( $api_prefix ); ?>post_types][<?php echo esc_attr( $post_type->name ); ?>]" value="<?php echo esc_attr( $post_type->name ); ?>" <?php checked( in_array( $post_type->name, $settings, true ) ); ?>> <?php echo esc_html( $post_type->label ); ?></label><br>
849
+ <?php
850
+ }
851
+ }
852
+
853
+ /**
854
+ * Get a specific plugin setting.
855
+ *
856
+ * @param string $setting Setting name.
857
+ * @param string $default Default value if setting is not found.
858
+ * @return mixed Setting value or default.
859
+ */
860
+ public function get_setting( $setting, $default = null ) {
861
+ $settings = $this->get_settings();
862
+
863
+ if ( $setting === 'json_key' ) {
864
+ if ( file_exists( plugin_dir_path( __FILE__ ) . 'rank-math-835b6feb842b.json' ) ) {
865
+ return file_get_contents( plugin_dir_path( __FILE__ ) . 'rank-math-835b6feb842b.json' );
866
+ }
867
+ }
868
+
869
+ return ( isset( $settings[ $setting ] ) ? $settings[ $setting ] : $default );
870
+ }
871
+
872
+ /**
873
+ * Output Rank Math Dashboard page contents.
874
+ *
875
+ * @return void
876
+ */
877
+ public function show_dashboard() {
878
+ include_once RM_GIAPI_PATH . 'views/dashboard.php';
879
+ }
880
+
881
+ /**
882
+ * Add Rank Math module.
883
+ *
884
+ * @param array $modules Current modules.
885
+ * @return array $modules New modules.
886
+ */
887
+ public function filter_modules( $modules ) {
888
+ $modules['instant-indexing'] = [
889
+ 'title' => esc_html__( 'Instant Indexing', 'fast-indexing-api' ),
890
+ 'desc' => esc_html__( 'Directly notify search engines when pages are added, updated or removed.', 'fast-indexing-api' ),
891
+ 'class' => 'RM_GIAPI_Module',
892
+ 'icon' => 'instant-indexing',
893
+ 'settings' => add_query_arg( 'page', 'instant-indexing', admin_url( 'admin.php' ) ),
894
+ 'disabled' => true,
895
+ 'disabled_text' => esc_html__( 'You cannot deactivate this module because the Instant Indexing plugin is active on this site.', 'fast-indexing-api' ),
896
+ ];
897
+
898
+ return $modules;
899
+ }
900
+
901
+ /**
902
+ * Add Javascript to the Dashboard.
903
+ *
904
+ * @param string $hook_suffix Hook suffix of the current admin page.
905
+ * @return void
906
+ */
907
+ public function admin_footer( $hook_suffix ) {
908
+ $screen = get_current_screen();
909
+ if ( $screen->id !== 'toplevel_page_rank-math' ) {
910
+ return;
911
+ }
912
+ ?>
913
+ <style>
914
+ .cmb2-toggle input#module-instant-indexing+.cmb2-slider {
915
+ background-color: #069de3;
916
+ border-color: #069de3
917
+ }
918
+
919
+ .cmb2-toggle input#module-instant-indexing+.cmb2-slider:before {
920
+ background: #fff;
921
+ -webkit-transform: translateX(24px);
922
+ transform: translateX(24px)
923
+ }
924
+
925
+ .cmb2-toggle input#module-instant-indexing+.cmb2-slider .toggle_off {
926
+ display: none
927
+ }
928
+
929
+ .cmb2-toggle input#module-instant-indexing+.cmb2-slider .toggle_on {
930
+ display: block
931
+ }
932
+
933
+ </style>
934
+ <?php
935
+ }
936
+
937
+ /**
938
+ * Add admin notice about Rank Math if it's not installed.
939
+ *
940
+ * @return void
941
+ */
942
+ public function rm_missing_admin_notice_error() {
943
+ if ( class_exists( 'RankMath' ) ) {
944
+ return;
945
+ }
946
+
947
+ /* translators: %s is a link to Rank Math plugin page */
948
+ $message = sprintf( __( 'It is recommended to use %s along with the Instant Indexing plugin.', 'fast-indexing-api' ), '<a href="https://wordpress.org/plugins/seo-by-rank-math/" target="_blank">' . __( 'Rank Math SEO' ) . '</a>' );
949
+ $class = 'notice-error';
950
+ $show_on = [ 'rank-math_page_instant-indexing', 'rank-math_page_instant-indexing-dashboard' ];
951
+
952
+ $this->add_notice( $message, $class, $show_on );
953
+ }
954
+
955
+ /**
956
+ * When a post from a watched post type is published, submit its URL
957
+ * to the API and add notice about it.
958
+ *
959
+ * @param int $post_id Post ID.
960
+ * @return void
961
+ */
962
+ public function publish_post( $post_id ) {
963
+ $post = get_post( $post_id );
964
+
965
+ if ( $post->post_status !== 'publish' ) {
966
+ return;
967
+ }
968
+
969
+ if ( wp_is_post_revision( $post_id ) || wp_is_post_autosave( $post_id ) ) {
970
+ return;
971
+ }
972
+
973
+ $send_url = apply_filters( 'rank_math/indexing_api/publish_url', get_permalink( $post ), $post, 'google' );
974
+ // Early exit if filter is set to false.
975
+ if ( ! $send_url ) {
976
+ return;
977
+ }
978
+
979
+ $this->send_to_api( $send_url, 'update' );
980
+ $this->add_notice( __( 'A recently published post has been automatically submitted to the Instant Indexing for indexation.', 'fast-indexing-api' ), 'notice-info', null, true );
981
+ }
982
+
983
+ /**
984
+ * When a post from a watched post type is published, submit its URL
985
+ * to the API and add notice about it.
986
+ *
987
+ * @param int $post_id Post ID.
988
+ * @return void
989
+ */
990
+ public function bing_publish_post( $post_id ) {
991
+ $post = get_post( $post_id );
992
+
993
+ if ( $post->post_status !== 'publish' ) {
994
+ return;
995
+ }
996
+
997
+ if ( wp_is_post_revision( $post_id ) || wp_is_post_autosave( $post_id ) ) {
998
+ return;
999
+ }
1000
+
1001
+ $send_url = apply_filters( 'rank_math/indexing_api/publish_url', get_permalink( $post ), $post, 'bing' );
1002
+ // Early exit if filter is set to false.
1003
+ if ( ! $send_url ) {
1004
+ return;
1005
+ }
1006
+
1007
+ $this->send_to_api( $send_url, 'bing_submit' );
1008
+ $this->add_notice( __( 'A recently published post has been automatically submitted to the Instant Indexing for indexation.', 'fast-indexing-api' ), 'notice-info', null, true );
1009
+ }
1010
+
1011
+ /**
1012
+ * When a post is deleted, check its post type and submit its URL
1013
+ * to the API if appropriate, then add notice about it.
1014
+ *
1015
+ * @param int $post_id Post ID.
1016
+ * @return void
1017
+ */
1018
+ public function delete_post( $post_id ) {
1019
+ $post_types = $this->get_setting( 'post_types', [] );
1020
+
1021
+ $post = get_post( $post_id );
1022
+ if ( ! in_array( $post->post_type, $post_types, true ) ) {
1023
+ return;
1024
+ }
1025
+
1026
+ $send_url = apply_filters( 'rank_math/indexing_api/delete_url', get_permalink( $post ), $post );
1027
+ // Early exit if filter is set to false.
1028
+ if ( ! $send_url ) {
1029
+ return;
1030
+ }
1031
+
1032
+ $this->send_to_api( $send_url, 'delete' );
1033
+ $this->add_notice( __( 'A deleted post has been automatically submitted to the Instant Indexing for deletion.', 'fast-indexing-api' ), 'notice-info', null, true );
1034
+ }
1035
+
1036
+ /**
1037
+ * Add Settings to plugin action links.
1038
+ *
1039
+ * @param array $actions Original actions.
1040
+ * @return array $actions New actions.
1041
+ */
1042
+ public function plugin_action_links( $actions ) {
1043
+ $actions['settings'] = '<a href="' . admin_url( 'admin.php?page=instant-indexing' ) . '">' . __( 'Settings', 'fast-indexing-api' ) . '</a>';
1044
+ return $actions;
1045
+ }
1046
+
1047
+ }
includes/index.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Nothing to see here.
4
+ */
index.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Nothing to see here.
4
+ */
instant-indexing.php ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Plugin Name: Instant Indexing
4
+ * Plugin URI: https://rankmath.com/wordpress/plugin/instant-indexing/
5
+ * Description: Get your website crawled immediately by Google using their NEW Indexing APIs.
6
+ * Version: 1.1.1
7
+ * Author: Rank Math
8
+ * Author URI: https://s.rankmath.com/home
9
+ * License: GPL v3
10
+ * Text Domain: fast-indexing-api
11
+ * Domain Path: /languages
12
+ *
13
+ * @package Instant Indexing
14
+ */
15
+
16
+ defined( 'ABSPATH' ) || die;
17
+
18
+ define( 'RM_GIAPI_PATH', plugin_dir_path( __FILE__ ) );
19
+ define( 'RM_GIAPI_FILE', plugin_basename( __FILE__ ) );
20
+ define( 'RM_GIAPI_URL', plugin_dir_url( __FILE__ ) );
21
+
22
+ /**
23
+ * Require Rank Math module class.
24
+ */
25
+ require_once 'includes/class-instant-indexing-module.php';
26
+
27
+ /**
28
+ * Require plugin class.
29
+ */
30
+ require_once 'includes/class-instant-indexing.php';
31
+
32
+ /**
33
+ * Instantiate plugin.
34
+ */
35
+ add_action( 'plugins_loaded', 'rm_giapi_init', 9 );
36
+
37
+ /**
38
+ * Init plugin.
39
+ *
40
+ * @return void
41
+ */
42
+ function rm_giapi_init() {
43
+ $rm_giapi = new RM_GIAPI();
44
+ }
languages/fast-indexing-api.pot ADDED
@@ -0,0 +1,285 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (C) 2021 fast-indexing-api
2
+ # This file is distributed under the same license as the fast-indexing-api package.
3
+ msgid ""
4
+ msgstr ""
5
+ "Project-Id-Version: fast-indexing-api\n"
6
+ "MIME-Version: 1.0\n"
7
+ "Content-Type: text/plain; charset=UTF-8\n"
8
+ "Content-Transfer-Encoding: 8bit\n"
9
+ "Language-Team: Rank Math\n"
10
+ "Last-Translator: Rank Math\n"
11
+ "X-Poedit-Basepath: ..\n"
12
+ "X-Poedit-KeywordsList: __;_e;_ex:1,2c;_n:1,2;_n_noop:1,2;_nx:1,2,4c;_nx_noop:1,2,3c;_x:1,2c;esc_attr__;esc_attr_e;esc_attr_x:1,2c;esc_html__;esc_html_e;esc_html_x:1,2c\n"
13
+ "X-Poedit-SearchPath-0: .\n"
14
+ "X-Poedit-SearchPathExcluded-0: *.js\n"
15
+ "X-Poedit-SourceCharset: UTF-8\n"
16
+ "Plural-Forms: nplurals=2; plural=(n != 1);\n"
17
+
18
+ msgid "Google API Settings"
19
+ msgstr ""
20
+
21
+ msgid "Bing API Settings"
22
+ msgstr ""
23
+
24
+ msgid "Console"
25
+ msgstr ""
26
+
27
+ msgid "Instant Indexing: Google Update"
28
+ msgstr ""
29
+
30
+ msgid "Instant Indexing: Google Get Status"
31
+ msgstr ""
32
+
33
+ msgid "Instant Indexing: Bing Submit"
34
+ msgstr ""
35
+
36
+ msgid "Dashboard"
37
+ msgstr ""
38
+
39
+ msgid "Instant Indexing"
40
+ msgstr ""
41
+
42
+ msgid "Success"
43
+ msgstr ""
44
+
45
+ msgid "Error"
46
+ msgstr ""
47
+
48
+ msgid "Last updated "
49
+ msgstr ""
50
+
51
+ msgid "See response for details."
52
+ msgstr ""
53
+
54
+ msgid "Settings could not be updated."
55
+ msgstr ""
56
+
57
+ msgid "Settings updated."
58
+ msgstr ""
59
+
60
+ msgid "Directly notify search engines when pages are added, updated or removed."
61
+ msgstr ""
62
+
63
+ msgid "You cannot deactivate this module because the Instant Indexing plugin is active on this site."
64
+ msgstr ""
65
+
66
+ #. translators: %s is a link to Rank Math plugin page
67
+ msgid "It is recommended to use %s along with the Instant Indexing plugin."
68
+ msgstr ""
69
+
70
+ msgid "A recently published post has been automatically submitted to the Instant Indexing for indexation."
71
+ msgstr ""
72
+
73
+ msgid "A deleted post has been automatically submitted to the Instant Indexing for deletion."
74
+ msgstr ""
75
+
76
+ msgid "Settings"
77
+ msgstr ""
78
+
79
+ msgid "Bing URL Submission API Settings"
80
+ msgstr ""
81
+
82
+ msgid "Bing API Key:"
83
+ msgstr ""
84
+
85
+ msgid "Paste your Bing URL Submission API Key in this field."
86
+ msgstr ""
87
+
88
+ msgid "Read our setup guide"
89
+ msgstr ""
90
+
91
+ msgid "Submit Post Types to Bing:"
92
+ msgstr ""
93
+
94
+ msgid "Submit posts from these post types automatically to the Bing URL Submission API when a post is published or edited."
95
+ msgstr ""
96
+
97
+ #. translators: %s is a link to the plugin settings tab.
98
+ msgid "Please navigate to the %s tab to configure the plugin."
99
+ msgstr ""
100
+
101
+ msgid "Google API Remaining Quota:"
102
+ msgstr ""
103
+
104
+ msgid "PublishRequestsPerDayPerProject"
105
+ msgstr ""
106
+
107
+ msgid "RequestsPerMinutePerProject"
108
+ msgstr ""
109
+
110
+ msgid "MetadataRequestsPerMinutePerProject"
111
+ msgstr ""
112
+
113
+ msgid "Bing API Remaining Quota:"
114
+ msgstr ""
115
+
116
+ msgid "UrlSubmissionQuota (per day)"
117
+ msgstr ""
118
+
119
+ msgid "URLs (one per line, up to 100 for Google and 500 for Bing):"
120
+ msgstr ""
121
+
122
+ msgid "Action:"
123
+ msgstr ""
124
+
125
+ msgid "<strong>Google</strong>: Publish/update URL"
126
+ msgstr ""
127
+
128
+ msgid "<strong>Google</strong>: Remove URL"
129
+ msgstr ""
130
+
131
+ msgid "<strong>Google</strong>: Get URL status"
132
+ msgstr ""
133
+
134
+ msgid "<strong>Bing</strong>: Submit URL"
135
+ msgstr ""
136
+
137
+ msgid "Send to API"
138
+ msgstr ""
139
+
140
+ msgid "Show Raw Response"
141
+ msgstr ""
142
+
143
+ msgid "Response..."
144
+ msgstr ""
145
+
146
+ msgid "Rank Math Knowledge Base"
147
+ msgstr ""
148
+
149
+ msgid "Modules"
150
+ msgstr ""
151
+
152
+ msgid "Help"
153
+ msgstr ""
154
+
155
+ msgid "Setup Wizard"
156
+ msgstr ""
157
+
158
+ msgid "Import &amp; Export"
159
+ msgstr ""
160
+
161
+ msgid "404 Monitor"
162
+ msgstr ""
163
+
164
+ msgid "Records the URLs on which visitors &amp; search engines run into 404 Errors. You can also turn on Redirections to redirect the error causing URLs to other URLs."
165
+ msgstr ""
166
+
167
+ msgid "ACF"
168
+ msgstr ""
169
+
170
+ msgid "ACF support helps Rank Math SEO read and analyze content written in the Advanced Custom Fields. If your theme uses ACF, you should enable this option."
171
+ msgstr ""
172
+
173
+ msgid "AMP"
174
+ msgstr ""
175
+
176
+ msgid "Install an AMP plugin to make Rank Math work with Accelerated Mobile Pages. Rank Math automatically adds required meta tags in all the AMP pages."
177
+ msgstr ""
178
+
179
+ msgid "Analytics"
180
+ msgstr ""
181
+
182
+ msgid "Connect Rank Math with Google Search Console to see the most important information from Google directly in your WordPress dashboard."
183
+ msgstr ""
184
+
185
+ msgid "bbPress"
186
+ msgstr ""
187
+
188
+ msgid "Add proper Meta tags to your bbPress forum posts, categories, profiles, etc. Get more options to take control of what search engines see and how they see it."
189
+ msgstr ""
190
+
191
+ msgid "BuddyPress"
192
+ msgstr ""
193
+
194
+ msgid "Enable the BuddyPress module for Rank Math SEO to make your BuddyPress forum SEO friendly by adding proper meta tags to all forum pages."
195
+ msgstr ""
196
+
197
+ msgid "Image SEO"
198
+ msgstr ""
199
+
200
+ msgid "Advanced Image SEO options to supercharge your website. Automate the task of adding the ALT and Title tags to your images on the fly."
201
+ msgstr ""
202
+
203
+ msgid "Directly notify search engines(Bing) when pages are added, updated or removed."
204
+ msgstr ""
205
+
206
+ msgid "Link Counter"
207
+ msgstr ""
208
+
209
+ msgid "Counts the total number of internal, external links, to and from links inside your posts. You can also see the same count in the Posts List Page."
210
+ msgstr ""
211
+
212
+ msgid "Local SEO &amp; Knowledge Graph"
213
+ msgstr ""
214
+
215
+ msgid "Dominate the search results for the local audiences by optimizing your website for Local SEO and it also helps you to add code related to Knowledge Graph."
216
+ msgstr ""
217
+
218
+ msgid "Redirections"
219
+ msgstr ""
220
+
221
+ msgid "Redirect non-existent content easily with 301 and 302 status code. This can help improve your site ranking. Also supports many other response codes."
222
+ msgstr ""
223
+
224
+ msgid "Schema (Structured Data)"
225
+ msgstr ""
226
+
227
+ msgid "Enable support for the structured data, which adds Schema code in your website, resulting in rich search results, better CTR and more traffic."
228
+ msgstr ""
229
+
230
+ msgid "Role Manager"
231
+ msgstr ""
232
+
233
+ msgid "The Role Manager allows you to use WordPress roles to control which of your site users can have edit or view access to Rank Math's settings."
234
+ msgstr ""
235
+
236
+ msgid "SEO Analysis"
237
+ msgstr ""
238
+
239
+ msgid "Let Rank Math analyze your website and your website's content using 70+ different tests to provide tailor-made SEO Analysis to you."
240
+ msgstr ""
241
+
242
+ msgid "Sitemap"
243
+ msgstr ""
244
+
245
+ msgid "Enable Rank Math's sitemap feature, which helps search engines intelligently crawl your website's content. It also supports hreflang tag."
246
+ msgstr ""
247
+
248
+ msgid "Google Web Stories"
249
+ msgstr ""
250
+
251
+ msgid "Make any Story created with the Web Stories WordPress plugin SEO-Ready with automatic support for Schema and Meta tags."
252
+ msgstr ""
253
+
254
+ msgid "WooCommerce"
255
+ msgstr ""
256
+
257
+ msgid "Optimize WooCommerce Pages for Search Engines by adding required metadata and Product Schema which will make your site stand out in the SERPs."
258
+ msgstr ""
259
+
260
+ msgid "Install for Free"
261
+ msgstr ""
262
+
263
+ msgid "Activate Now"
264
+ msgstr ""
265
+
266
+ msgid "Google Instant Indexing API Settings"
267
+ msgstr ""
268
+
269
+ msgid "Google JSON Key:"
270
+ msgstr ""
271
+
272
+ msgid "Upload the Service Account JSON key file you obtained from Google API Console or paste its contents in the field."
273
+ msgstr ""
274
+
275
+ msgid "Or upload JSON file: "
276
+ msgstr ""
277
+
278
+ msgid "<code>rank-math-835b6feb842b.json</code> file found in the plugin folder. You cannot change the JSON key from here until you delete or remame this file."
279
+ msgstr ""
280
+
281
+ msgid "Submit Post Types to Google:"
282
+ msgstr ""
283
+
284
+ msgid "Submit posts from these post types automatically to the Google Instant Indexing API when a post is published, edited, or deleted."
285
+ msgstr ""
readme.txt ADDED
@@ -0,0 +1,122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ === Instant Indexing for Google ===
2
+ Contributors: rankmath
3
+ Plugin link: https://rankmath.com/wordpress/plugin/instant-indexing/
4
+ Tags: indexing api, crawling, live streaming, fast indexing, job posting
5
+ Tested up to: 5.8.1
6
+ Requires at least: 5.6
7
+ Requires PHP: 7.2
8
+ Stable tag: 1.1.1
9
+ License: GPL-2.0+
10
+ License URI: https://www.gnu.org/licenses/gpl-2.0.txt
11
+
12
+ A very efficient yet simple plugin to take care of your indexing woos and helps get your content crawled by search bots instantly.
13
+
14
+ == Description ==
15
+
16
+ ### Get your website's pages, and content crawled immediately! Use the Instant Indexing plugin to beat your competition and rank higher.
17
+
18
+ ★★★★★<br>
19
+
20
+ > **Note**: Google recommends that you use the Indexing API ONLY for Job Posting and Live Streaming websites. However, it works on any type of website and many of our users have seen great results already. Please proceed with caution.
21
+
22
+ Whether you are a novice blogger or a seasoned SEO - you know the importance of getting into the Google index. It is the very first step before your website can see any organic traffic coming from Google or any other search engine.
23
+
24
+ If your pages don't get indexed, your website is essentially invisible to Google and all the visitors - visitors that would otherwise "see" your website in the search engines.
25
+
26
+ So, it is pretty important that your new content gets crawled/indexed fast, and it is equally important for your already published content to get updated in Google as well.
27
+
28
+ How do you do one or the other? Or, how about doing them both?
29
+
30
+ **Enter the Instant Indexing plugin by Rank Math**
31
+
32
+ When you publish new content or update old content on your WordPress website, the Instant Indexing plugin sends a crawl request to Google using the Google Indexing API.
33
+
34
+ The result? **Almost immediate indexing of your content**. [Here is an example](https://rankmath.com/blog/google-indexing-api/#proof).
35
+
36
+ There are a lot of plus points of having your content instantly crawled and indexed by the search engines, but, here are a few major advantages of using the Instant Indexing plugin:
37
+
38
+ * **Rank faster** - Have that awesome content you know users will like? Get it in front of your audience faster.
39
+ * Increase your chances of ranking above your competition
40
+ * Keep search results up-to-date
41
+ * One-time Setup
42
+ * **Automatic Submissions**
43
+ * Manual Submissions
44
+ * Excludes Custom Post Types
45
+ * Send request to remove Post from Google SERPs
46
+ * Get Current Post Status
47
+ * Compatible with Any SEO WordPress Plugin
48
+ * Bulk Submissions (Up to 100 URLs)
49
+ * Completely FREE.
50
+
51
+ There is just no reason not to give it a try.
52
+
53
+ ## ABOUT THE DEVELOPER
54
+
55
+ The Instant Indexing plugin is created by the same brains that are behind the popular [Rank Math SEO](https://rankmath.com/wordpress/plugin/seo-suite/) plugin. We created the Instant Indexing plugin to get your SEO friendly content crawled quickly. This, in turn, helps you rank faster and higher than you would if you didn't use these plugins.
56
+
57
+ = Getting Started: =
58
+ **1. Setting up the Plugin:** Once you install and activate the Instant Indexing Plugin, head over to **Rank Math > Instant Indexing** and configure the settings.
59
+
60
+ **[2. Facebook Group:](https://s.rankmath.com/groupfb)** In this group, you will find the team of Rank Math SEO plugin fairly active and ready to answer your SEO related queries.
61
+
62
+ **[3. User Documentation:](https://rankmath.com/blog/google-indexing-api/)** Although Instant Indexing plugin is already easy to set up, we've put together tutorial to help you set up and get started.
63
+
64
+ **[4. Fixing Common Errors:](https://s.rankmath.com/wp-errors-fixes)** Sometimes avoidable or common issues can get you stuck. We've created a common guide where we discuss all the common issues and how to fix them.
65
+
66
+ **[5. Support Ticket Forum:](https://s.rankmath.com/support)** Our dedicated forum is where you can get support for any issues that you face with Instant Indexing. In the forum, we'll also try to answer some SEO queries. User experience is important to us, and our aim is to answer all the queries on the forum in a timely manner.
67
+
68
+ **[6. Frequently Asked Questions:](#faq-header)** Here we've answered the most commonly asked questions about Instant Indexing by Rank Math.
69
+
70
+ == Installation ==
71
+
72
+ 1. Visit 'Plugins > Add New'
73
+ 2. Search for 'Instant Indexing for Google'
74
+ 3. Install Instant Indexing once it appears
75
+ 4. Activate the plugin
76
+ 5. Go to "after activation" section below.
77
+
78
+ = Manually =
79
+
80
+ 1. Upload the `fast-indexing-api` folder to the `/wp-content/plugins/` directory
81
+ 2. Activate the Instant Indexing plugin through the 'Plugins' menu in WordPress
82
+ 3. Go to "after activation" section below.
83
+
84
+ = After activation =
85
+
86
+ 1. You should see the Rank Math menu in the dashboard sidebar.
87
+ 2. From there you can access the plugin settings.
88
+ 3. You're done!
89
+
90
+ == Frequently Asked Questions ==
91
+
92
+ = Can I use the plugin without Rank Math? =
93
+ Yes, you absolutely can. You can use the Instant Indexing plugin with any SEO plugin you like. But, we recommend using the Instant Indexing API plugin with [Rank Math SEO](https://wordpress.org/plugins/seo-by-rank-math/) for best results.
94
+
95
+ = Can I submit pages that do not have Job Posting or Livestream structured data? =
96
+ Although the Google Indexing API officially supports pages containing Job Posting and Livestream structured data - it is officially recommended to use only on such websites. But, it can be used with any website. But, do proceed with caution if you are not comfortable with this.
97
+
98
+ = Will my pages and posts get indexed instantly? =
99
+ Technically, yes. That's what the plugin is made to do. But, please note that we guarantee instant crawling using this plugin. Whether or not Google will index your content after crawling is and always will be in Google's control. They have the final say in what they want to appear in their SERPs and what they don't.
100
+
101
+ == Screenshots ==
102
+
103
+ 1. Plugin sends request to Google Crawler once the Post is Published or Updated
104
+ 2. Manual Submissions
105
+ 3. Plugin Settings
106
+
107
+ == Changelog ==
108
+
109
+ = v1.1.1 [Sep 10, 2021] =
110
+ * Improved: Apply settings from v1.0.0 if available
111
+
112
+ = v1.1.0 [Sep 8, 2021] =
113
+ * Improved: Compatibility with the [Rank Math SEO](https://rankmath.com/) plugin. Now, you can use Rank Math's [Bing Instant Indexing](https://rankmath.com/blog/bing-indexing-api/) feature from the same settings page
114
+ * Improved: Reduce clutter on the Settings page by hiding unrelated admin notices
115
+ * Improved: Updated the third-party libraries to their latest version
116
+ * Fixed: JSON file upload option was not working on the Settings page
117
+ * Fixed: PHP notice appearing after saving the Settings or updating the post on some installations
118
+ * Fixed: Wrong text domain in some `gettext` calls
119
+ * Removed: Some unused files
120
+
121
+ = v1.0.0 [Sep 24, 2019] =
122
+ * Official plugin release on wp.org
vendor/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 ComposerAutoloaderInit1cfac4bac5a1827f26c0b477558bd882::getLoader();
vendor/composer/ClassLoader.php ADDED
@@ -0,0 +1,481 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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, PSR-4 and classmap class loader.
17
+ *
18
+ * $loader = new \Composer\Autoload\ClassLoader();
19
+ *
20
+ * // register classes with namespaces
21
+ * $loader->add('Symfony\Component', __DIR__.'/component');
22
+ * $loader->add('Symfony', __DIR__.'/framework');
23
+ *
24
+ * // activate the autoloader
25
+ * $loader->register();
26
+ *
27
+ * // to enable searching the include path (eg. for PEAR packages)
28
+ * $loader->setUseIncludePath(true);
29
+ *
30
+ * In this example, if you try to use a class in the Symfony\Component
31
+ * namespace or one of its children (Symfony\Component\Console for instance),
32
+ * the autoloader will first look for the class under the component/
33
+ * directory, and it will then fallback to the framework/ directory if not
34
+ * found before giving up.
35
+ *
36
+ * This class is loosely based on the Symfony UniversalClassLoader.
37
+ *
38
+ * @author Fabien Potencier <fabien@symfony.com>
39
+ * @author Jordi Boggiano <j.boggiano@seld.be>
40
+ * @see https://www.php-fig.org/psr/psr-0/
41
+ * @see https://www.php-fig.org/psr/psr-4/
42
+ */
43
+ class ClassLoader
44
+ {
45
+ private $vendorDir;
46
+
47
+ // PSR-4
48
+ private $prefixLengthsPsr4 = array();
49
+ private $prefixDirsPsr4 = array();
50
+ private $fallbackDirsPsr4 = array();
51
+
52
+ // PSR-0
53
+ private $prefixesPsr0 = array();
54
+ private $fallbackDirsPsr0 = array();
55
+
56
+ private $useIncludePath = false;
57
+ private $classMap = array();
58
+ private $classMapAuthoritative = false;
59
+ private $missingClasses = array();
60
+ private $apcuPrefix;
61
+
62
+ private static $registeredLoaders = array();
63
+
64
+ public function __construct($vendorDir = null)
65
+ {
66
+ $this->vendorDir = $vendorDir;
67
+ }
68
+
69
+ public function getPrefixes()
70
+ {
71
+ if (!empty($this->prefixesPsr0)) {
72
+ return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
73
+ }
74
+
75
+ return array();
76
+ }
77
+
78
+ public function getPrefixesPsr4()
79
+ {
80
+ return $this->prefixDirsPsr4;
81
+ }
82
+
83
+ public function getFallbackDirs()
84
+ {
85
+ return $this->fallbackDirsPsr0;
86
+ }
87
+
88
+ public function getFallbackDirsPsr4()
89
+ {
90
+ return $this->fallbackDirsPsr4;
91
+ }
92
+
93
+ public function getClassMap()
94
+ {
95
+ return $this->classMap;
96
+ }
97
+
98
+ /**
99
+ * @param array $classMap Class to filename map
100
+ */
101
+ public function addClassMap(array $classMap)
102
+ {
103
+ if ($this->classMap) {
104
+ $this->classMap = array_merge($this->classMap, $classMap);
105
+ } else {
106
+ $this->classMap = $classMap;
107
+ }
108
+ }
109
+
110
+ /**
111
+ * Registers a set of PSR-0 directories for a given prefix, either
112
+ * appending or prepending to the ones previously set for this prefix.
113
+ *
114
+ * @param string $prefix The prefix
115
+ * @param array|string $paths The PSR-0 root directories
116
+ * @param bool $prepend Whether to prepend the directories
117
+ */
118
+ public function add($prefix, $paths, $prepend = false)
119
+ {
120
+ if (!$prefix) {
121
+ if ($prepend) {
122
+ $this->fallbackDirsPsr0 = array_merge(
123
+ (array) $paths,
124
+ $this->fallbackDirsPsr0
125
+ );
126
+ } else {
127
+ $this->fallbackDirsPsr0 = array_merge(
128
+ $this->fallbackDirsPsr0,
129
+ (array) $paths
130
+ );
131
+ }
132
+
133
+ return;
134
+ }
135
+
136
+ $first = $prefix[0];
137
+ if (!isset($this->prefixesPsr0[$first][$prefix])) {
138
+ $this->prefixesPsr0[$first][$prefix] = (array) $paths;
139
+
140
+ return;
141
+ }
142
+ if ($prepend) {
143
+ $this->prefixesPsr0[$first][$prefix] = array_merge(
144
+ (array) $paths,
145
+ $this->prefixesPsr0[$first][$prefix]
146
+ );
147
+ } else {
148
+ $this->prefixesPsr0[$first][$prefix] = array_merge(
149
+ $this->prefixesPsr0[$first][$prefix],
150
+ (array) $paths
151
+ );
152
+ }
153
+ }
154
+
155
+ /**
156
+ * Registers a set of PSR-4 directories for a given namespace, either
157
+ * appending or prepending to the ones previously set for this namespace.
158
+ *
159
+ * @param string $prefix The prefix/namespace, with trailing '\\'
160
+ * @param array|string $paths The PSR-4 base directories
161
+ * @param bool $prepend Whether to prepend the directories
162
+ *
163
+ * @throws \InvalidArgumentException
164
+ */
165
+ public function addPsr4($prefix, $paths, $prepend = false)
166
+ {
167
+ if (!$prefix) {
168
+ // Register directories for the root namespace.
169
+ if ($prepend) {
170
+ $this->fallbackDirsPsr4 = array_merge(
171
+ (array) $paths,
172
+ $this->fallbackDirsPsr4
173
+ );
174
+ } else {
175
+ $this->fallbackDirsPsr4 = array_merge(
176
+ $this->fallbackDirsPsr4,
177
+ (array) $paths
178
+ );
179
+ }
180
+ } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
181
+ // Register directories for a new namespace.
182
+ $length = strlen($prefix);
183
+ if ('\\' !== $prefix[$length - 1]) {
184
+ throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
185
+ }
186
+ $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
187
+ $this->prefixDirsPsr4[$prefix] = (array) $paths;
188
+ } elseif ($prepend) {
189
+ // Prepend directories for an already registered namespace.
190
+ $this->prefixDirsPsr4[$prefix] = array_merge(
191
+ (array) $paths,
192
+ $this->prefixDirsPsr4[$prefix]
193
+ );
194
+ } else {
195
+ // Append directories for an already registered namespace.
196
+ $this->prefixDirsPsr4[$prefix] = array_merge(
197
+ $this->prefixDirsPsr4[$prefix],
198
+ (array) $paths
199
+ );
200
+ }
201
+ }
202
+
203
+ /**
204
+ * Registers a set of PSR-0 directories for a given prefix,
205
+ * replacing any others previously set for this prefix.
206
+ *
207
+ * @param string $prefix The prefix
208
+ * @param array|string $paths The PSR-0 base directories
209
+ */
210
+ public function set($prefix, $paths)
211
+ {
212
+ if (!$prefix) {
213
+ $this->fallbackDirsPsr0 = (array) $paths;
214
+ } else {
215
+ $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
216
+ }
217
+ }
218
+
219
+ /**
220
+ * Registers a set of PSR-4 directories for a given namespace,
221
+ * replacing any others previously set for this namespace.
222
+ *
223
+ * @param string $prefix The prefix/namespace, with trailing '\\'
224
+ * @param array|string $paths The PSR-4 base directories
225
+ *
226
+ * @throws \InvalidArgumentException
227
+ */
228
+ public function setPsr4($prefix, $paths)
229
+ {
230
+ if (!$prefix) {
231
+ $this->fallbackDirsPsr4 = (array) $paths;
232
+ } else {
233
+ $length = strlen($prefix);
234
+ if ('\\' !== $prefix[$length - 1]) {
235
+ throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
236
+ }
237
+ $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
238
+ $this->prefixDirsPsr4[$prefix] = (array) $paths;
239
+ }
240
+ }
241
+
242
+ /**
243
+ * Turns on searching the include path for class files.
244
+ *
245
+ * @param bool $useIncludePath
246
+ */
247
+ public function setUseIncludePath($useIncludePath)
248
+ {
249
+ $this->useIncludePath = $useIncludePath;
250
+ }
251
+
252
+ /**
253
+ * Can be used to check if the autoloader uses the include path to check
254
+ * for classes.
255
+ *
256
+ * @return bool
257
+ */
258
+ public function getUseIncludePath()
259
+ {
260
+ return $this->useIncludePath;
261
+ }
262
+
263
+ /**
264
+ * Turns off searching the prefix and fallback directories for classes
265
+ * that have not been registered with the class map.
266
+ *
267
+ * @param bool $classMapAuthoritative
268
+ */
269
+ public function setClassMapAuthoritative($classMapAuthoritative)
270
+ {
271
+ $this->classMapAuthoritative = $classMapAuthoritative;
272
+ }
273
+
274
+ /**
275
+ * Should class lookup fail if not found in the current class map?
276
+ *
277
+ * @return bool
278
+ */
279
+ public function isClassMapAuthoritative()
280
+ {
281
+ return $this->classMapAuthoritative;
282
+ }
283
+
284
+ /**
285
+ * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
286
+ *
287
+ * @param string|null $apcuPrefix
288
+ */
289
+ public function setApcuPrefix($apcuPrefix)
290
+ {
291
+ $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
292
+ }
293
+
294
+ /**
295
+ * The APCu prefix in use, or null if APCu caching is not enabled.
296
+ *
297
+ * @return string|null
298
+ */
299
+ public function getApcuPrefix()
300
+ {
301
+ return $this->apcuPrefix;
302
+ }
303
+
304
+ /**
305
+ * Registers this instance as an autoloader.
306
+ *
307
+ * @param bool $prepend Whether to prepend the autoloader or not
308
+ */
309
+ public function register($prepend = false)
310
+ {
311
+ spl_autoload_register(array($this, 'loadClass'), true, $prepend);
312
+
313
+ if (null === $this->vendorDir) {
314
+ return;
315
+ }
316
+
317
+ if ($prepend) {
318
+ self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
319
+ } else {
320
+ unset(self::$registeredLoaders[$this->vendorDir]);
321
+ self::$registeredLoaders[$this->vendorDir] = $this;
322
+ }
323
+ }
324
+
325
+ /**
326
+ * Unregisters this instance as an autoloader.
327
+ */
328
+ public function unregister()
329
+ {
330
+ spl_autoload_unregister(array($this, 'loadClass'));
331
+
332
+ if (null !== $this->vendorDir) {
333
+ unset(self::$registeredLoaders[$this->vendorDir]);
334
+ }
335
+ }
336
+
337
+ /**
338
+ * Loads the given class or interface.
339
+ *
340
+ * @param string $class The name of the class
341
+ * @return true|null True if loaded, null otherwise
342
+ */
343
+ public function loadClass($class)
344
+ {
345
+ if ($file = $this->findFile($class)) {
346
+ includeFile($file);
347
+
348
+ return true;
349
+ }
350
+
351
+ return null;
352
+ }
353
+
354
+ /**
355
+ * Finds the path to the file where the class is defined.
356
+ *
357
+ * @param string $class The name of the class
358
+ *
359
+ * @return string|false The path if found, false otherwise
360
+ */
361
+ public function findFile($class)
362
+ {
363
+ // class map lookup
364
+ if (isset($this->classMap[$class])) {
365
+ return $this->classMap[$class];
366
+ }
367
+ if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
368
+ return false;
369
+ }
370
+ if (null !== $this->apcuPrefix) {
371
+ $file = apcu_fetch($this->apcuPrefix.$class, $hit);
372
+ if ($hit) {
373
+ return $file;
374
+ }
375
+ }
376
+
377
+ $file = $this->findFileWithExtension($class, '.php');
378
+
379
+ // Search for Hack files if we are running on HHVM
380
+ if (false === $file && defined('HHVM_VERSION')) {
381
+ $file = $this->findFileWithExtension($class, '.hh');
382
+ }
383
+
384
+ if (null !== $this->apcuPrefix) {
385
+ apcu_add($this->apcuPrefix.$class, $file);
386
+ }
387
+
388
+ if (false === $file) {
389
+ // Remember that this class does not exist.
390
+ $this->missingClasses[$class] = true;
391
+ }
392
+
393
+ return $file;
394
+ }
395
+
396
+ /**
397
+ * Returns the currently registered loaders indexed by their corresponding vendor directories.
398
+ *
399
+ * @return self[]
400
+ */
401
+ public static function getRegisteredLoaders()
402
+ {
403
+ return self::$registeredLoaders;
404
+ }
405
+
406
+ private function findFileWithExtension($class, $ext)
407
+ {
408
+ // PSR-4 lookup
409
+ $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
410
+
411
+ $first = $class[0];
412
+ if (isset($this->prefixLengthsPsr4[$first])) {
413
+ $subPath = $class;
414
+ while (false !== $lastPos = strrpos($subPath, '\\')) {
415
+ $subPath = substr($subPath, 0, $lastPos);
416
+ $search = $subPath . '\\';
417
+ if (isset($this->prefixDirsPsr4[$search])) {
418
+ $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
419
+ foreach ($this->prefixDirsPsr4[$search] as $dir) {
420
+ if (file_exists($file = $dir . $pathEnd)) {
421
+ return $file;
422
+ }
423
+ }
424
+ }
425
+ }
426
+ }
427
+
428
+ // PSR-4 fallback dirs
429
+ foreach ($this->fallbackDirsPsr4 as $dir) {
430
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
431
+ return $file;
432
+ }
433
+ }
434
+
435
+ // PSR-0 lookup
436
+ if (false !== $pos = strrpos($class, '\\')) {
437
+ // namespaced class name
438
+ $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
439
+ . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
440
+ } else {
441
+ // PEAR-like class name
442
+ $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
443
+ }
444
+
445
+ if (isset($this->prefixesPsr0[$first])) {
446
+ foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
447
+ if (0 === strpos($class, $prefix)) {
448
+ foreach ($dirs as $dir) {
449
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
450
+ return $file;
451
+ }
452
+ }
453
+ }
454
+ }
455
+ }
456
+
457
+ // PSR-0 fallback dirs
458
+ foreach ($this->fallbackDirsPsr0 as $dir) {
459
+ if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
460
+ return $file;
461
+ }
462
+ }
463
+
464
+ // PSR-0 include paths.
465
+ if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
466
+ return $file;
467
+ }
468
+
469
+ return false;
470
+ }
471
+ }
472
+
473
+ /**
474
+ * Scope isolated include.
475
+ *
476
+ * Prevents access to $this/self from included files.
477
+ */
478
+ function includeFile($file)
479
+ {
480
+ include $file;
481
+ }
vendor/composer/InstalledVersions.php ADDED
@@ -0,0 +1,337 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
14
+
15
+ use Composer\Autoload\ClassLoader;
16
+ use Composer\Semver\VersionParser;
17
+
18
+ /**
19
+ * This class is copied in every Composer installed project and available to all
20
+ *
21
+ * See also https://getcomposer.org/doc/07-runtime.md#installed-versions
22
+ *
23
+ * To require it's presence, you can require `composer-runtime-api ^2.0`
24
+ */
25
+ class InstalledVersions
26
+ {
27
+ private static $installed;
28
+ private static $canGetVendors;
29
+ private static $installedByVendor = array();
30
+
31
+ /**
32
+ * Returns a list of all package names which are present, either by being installed, replaced or provided
33
+ *
34
+ * @return string[]
35
+ * @psalm-return list<string>
36
+ */
37
+ public static function getInstalledPackages()
38
+ {
39
+ $packages = array();
40
+ foreach (self::getInstalled() as $installed) {
41
+ $packages[] = array_keys($installed['versions']);
42
+ }
43
+
44
+ if (1 === \count($packages)) {
45
+ return $packages[0];
46
+ }
47
+
48
+ return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
49
+ }
50
+
51
+ /**
52
+ * Returns a list of all package names with a specific type e.g. 'library'
53
+ *
54
+ * @param string $type
55
+ * @return string[]
56
+ * @psalm-return list<string>
57
+ */
58
+ public static function getInstalledPackagesByType($type)
59
+ {
60
+ $packagesByType = array();
61
+
62
+ foreach (self::getInstalled() as $installed) {
63
+ foreach ($installed['versions'] as $name => $package) {
64
+ if (isset($package['type']) && $package['type'] === $type) {
65
+ $packagesByType[] = $name;
66
+ }
67
+ }
68
+ }
69
+
70
+ return $packagesByType;
71
+ }
72
+
73
+ /**
74
+ * Checks whether the given package is installed
75
+ *
76
+ * This also returns true if the package name is provided or replaced by another package
77
+ *
78
+ * @param string $packageName
79
+ * @param bool $includeDevRequirements
80
+ * @return bool
81
+ */
82
+ public static function isInstalled($packageName, $includeDevRequirements = true)
83
+ {
84
+ foreach (self::getInstalled() as $installed) {
85
+ if (isset($installed['versions'][$packageName])) {
86
+ return $includeDevRequirements || empty($installed['versions'][$packageName]['dev_requirement']);
87
+ }
88
+ }
89
+
90
+ return false;
91
+ }
92
+
93
+ /**
94
+ * Checks whether the given package satisfies a version constraint
95
+ *
96
+ * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
97
+ *
98
+ * Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
99
+ *
100
+ * @param VersionParser $parser Install composer/semver to have access to this class and functionality
101
+ * @param string $packageName
102
+ * @param string|null $constraint A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
103
+ * @return bool
104
+ */
105
+ public static function satisfies(VersionParser $parser, $packageName, $constraint)
106
+ {
107
+ $constraint = $parser->parseConstraints($constraint);
108
+ $provided = $parser->parseConstraints(self::getVersionRanges($packageName));
109
+
110
+ return $provided->matches($constraint);
111
+ }
112
+
113
+ /**
114
+ * Returns a version constraint representing all the range(s) which are installed for a given package
115
+ *
116
+ * It is easier to use this via isInstalled() with the $constraint argument if you need to check
117
+ * whether a given version of a package is installed, and not just whether it exists
118
+ *
119
+ * @param string $packageName
120
+ * @return string Version constraint usable with composer/semver
121
+ */
122
+ public static function getVersionRanges($packageName)
123
+ {
124
+ foreach (self::getInstalled() as $installed) {
125
+ if (!isset($installed['versions'][$packageName])) {
126
+ continue;
127
+ }
128
+
129
+ $ranges = array();
130
+ if (isset($installed['versions'][$packageName]['pretty_version'])) {
131
+ $ranges[] = $installed['versions'][$packageName]['pretty_version'];
132
+ }
133
+ if (array_key_exists('aliases', $installed['versions'][$packageName])) {
134
+ $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
135
+ }
136
+ if (array_key_exists('replaced', $installed['versions'][$packageName])) {
137
+ $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
138
+ }
139
+ if (array_key_exists('provided', $installed['versions'][$packageName])) {
140
+ $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
141
+ }
142
+
143
+ return implode(' || ', $ranges);
144
+ }
145
+
146
+ throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
147
+ }
148
+
149
+ /**
150
+ * @param string $packageName
151
+ * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
152
+ */
153
+ public static function getVersion($packageName)
154
+ {
155
+ foreach (self::getInstalled() as $installed) {
156
+ if (!isset($installed['versions'][$packageName])) {
157
+ continue;
158
+ }
159
+
160
+ if (!isset($installed['versions'][$packageName]['version'])) {
161
+ return null;
162
+ }
163
+
164
+ return $installed['versions'][$packageName]['version'];
165
+ }
166
+
167
+ throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
168
+ }
169
+
170
+ /**
171
+ * @param string $packageName
172
+ * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
173
+ */
174
+ public static function getPrettyVersion($packageName)
175
+ {
176
+ foreach (self::getInstalled() as $installed) {
177
+ if (!isset($installed['versions'][$packageName])) {
178
+ continue;
179
+ }
180
+
181
+ if (!isset($installed['versions'][$packageName]['pretty_version'])) {
182
+ return null;
183
+ }
184
+
185
+ return $installed['versions'][$packageName]['pretty_version'];
186
+ }
187
+
188
+ throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
189
+ }
190
+
191
+ /**
192
+ * @param string $packageName
193
+ * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
194
+ */
195
+ public static function getReference($packageName)
196
+ {
197
+ foreach (self::getInstalled() as $installed) {
198
+ if (!isset($installed['versions'][$packageName])) {
199
+ continue;
200
+ }
201
+
202
+ if (!isset($installed['versions'][$packageName]['reference'])) {
203
+ return null;
204
+ }
205
+
206
+ return $installed['versions'][$packageName]['reference'];
207
+ }
208
+
209
+ throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
210
+ }
211
+
212
+ /**
213
+ * @param string $packageName
214
+ * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as install path. Packages of type metapackages also have a null install path.
215
+ */
216
+ public static function getInstallPath($packageName)
217
+ {
218
+ foreach (self::getInstalled() as $installed) {
219
+ if (!isset($installed['versions'][$packageName])) {
220
+ continue;
221
+ }
222
+
223
+ return isset($installed['versions'][$packageName]['install_path']) ? $installed['versions'][$packageName]['install_path'] : null;
224
+ }
225
+
226
+ throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
227
+ }
228
+
229
+ /**
230
+ * @return array
231
+ * @psalm-return array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string}
232
+ */
233
+ public static function getRootPackage()
234
+ {
235
+ $installed = self::getInstalled();
236
+
237
+ return $installed[0]['root'];
238
+ }
239
+
240
+ /**
241
+ * Returns the raw installed.php data for custom implementations
242
+ *
243
+ * @deprecated Use getAllRawData() instead which returns all datasets for all autoloaders present in the process. getRawData only returns the first dataset loaded, which may not be what you expect.
244
+ * @return array[]
245
+ * @psalm-return array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string}>}
246
+ */
247
+ public static function getRawData()
248
+ {
249
+ @trigger_error('getRawData only returns the first dataset loaded, which may not be what you expect. Use getAllRawData() instead which returns all datasets for all autoloaders present in the process.', E_USER_DEPRECATED);
250
+
251
+ if (null === self::$installed) {
252
+ // only require the installed.php file if this file is loaded from its dumped location,
253
+ // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
254
+ if (substr(__DIR__, -8, 1) !== 'C') {
255
+ self::$installed = include __DIR__ . '/installed.php';
256
+ } else {
257
+ self::$installed = array();
258
+ }
259
+ }
260
+
261
+ return self::$installed;
262
+ }
263
+
264
+ /**
265
+ * Returns the raw data of all installed.php which are currently loaded for custom implementations
266
+ *
267
+ * @return array[]
268
+ * @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string}>}>
269
+ */
270
+ public static function getAllRawData()
271
+ {
272
+ return self::getInstalled();
273
+ }
274
+
275
+ /**
276
+ * Lets you reload the static array from another file
277
+ *
278
+ * This is only useful for complex integrations in which a project needs to use
279
+ * this class but then also needs to execute another project's autoloader in process,
280
+ * and wants to ensure both projects have access to their version of installed.php.
281
+ *
282
+ * A typical case would be PHPUnit, where it would need to make sure it reads all
283
+ * the data it needs from this class, then call reload() with
284
+ * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
285
+ * the project in which it runs can then also use this class safely, without
286
+ * interference between PHPUnit's dependencies and the project's dependencies.
287
+ *
288
+ * @param array[] $data A vendor/composer/installed.php data set
289
+ * @return void
290
+ *
291
+ * @psalm-param array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string}>} $data
292
+ */
293
+ public static function reload($data)
294
+ {
295
+ self::$installed = $data;
296
+ self::$installedByVendor = array();
297
+ }
298
+
299
+ /**
300
+ * @return array[]
301
+ * @psalm-return list<array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[], dev: bool, install_path: string}, versions: array<string, array{dev_requirement: bool, pretty_version?: string, version?: string, aliases?: string[], reference?: string, replaced?: string[], provided?: string[], install_path?: string}>}>
302
+ */
303
+ private static function getInstalled()
304
+ {
305
+ if (null === self::$canGetVendors) {
306
+ self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
307
+ }
308
+
309
+ $installed = array();
310
+
311
+ if (self::$canGetVendors) {
312
+ foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
313
+ if (isset(self::$installedByVendor[$vendorDir])) {
314
+ $installed[] = self::$installedByVendor[$vendorDir];
315
+ } elseif (is_file($vendorDir.'/composer/installed.php')) {
316
+ $installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php';
317
+ if (null === self::$installed && strtr($vendorDir.'/composer', '\\', '/') === strtr(__DIR__, '\\', '/')) {
318
+ self::$installed = $installed[count($installed) - 1];
319
+ }
320
+ }
321
+ }
322
+ }
323
+
324
+ if (null === self::$installed) {
325
+ // only require the installed.php file if this file is loaded from its dumped location,
326
+ // and not from its source location in the composer/composer package, see https://github.com/composer/composer/issues/9937
327
+ if (substr(__DIR__, -8, 1) !== 'C') {
328
+ self::$installed = require __DIR__ . '/installed.php';
329
+ } else {
330
+ self::$installed = array();
331
+ }
332
+ }
333
+ $installed[] = self::$installed;
334
+
335
+ return $installed;
336
+ }
337
+ }
vendor/composer/LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ Copyright (c) Nils Adermann, Jordi Boggiano
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the "Software"), to deal
6
+ in the Software without restriction, including without limitation the rights
7
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is furnished
9
+ to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all
12
+ copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20
+ THE SOFTWARE.
21
+
vendor/composer/autoload_classmap.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ 'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
10
+ 'Google_AccessToken_Revoke' => $vendorDir . '/google/apiclient/src/aliases.php',
11
+ 'Google_AccessToken_Verify' => $vendorDir . '/google/apiclient/src/aliases.php',
12
+ 'Google_AuthHandler_AuthHandlerFactory' => $vendorDir . '/google/apiclient/src/aliases.php',
13
+ 'Google_AuthHandler_Guzzle5AuthHandler' => $vendorDir . '/google/apiclient/src/aliases.php',
14
+ 'Google_AuthHandler_Guzzle6AuthHandler' => $vendorDir . '/google/apiclient/src/aliases.php',
15
+ 'Google_AuthHandler_Guzzle7AuthHandler' => $vendorDir . '/google/apiclient/src/aliases.php',
16
+ 'Google_Client' => $vendorDir . '/google/apiclient/src/aliases.php',
17
+ 'Google_Collection' => $vendorDir . '/google/apiclient/src/aliases.php',
18
+ 'Google_Exception' => $vendorDir . '/google/apiclient/src/aliases.php',
19
+ 'Google_Http_Batch' => $vendorDir . '/google/apiclient/src/aliases.php',
20
+ 'Google_Http_MediaFileUpload' => $vendorDir . '/google/apiclient/src/aliases.php',
21
+ 'Google_Http_REST' => $vendorDir . '/google/apiclient/src/aliases.php',
22
+ 'Google_Model' => $vendorDir . '/google/apiclient/src/aliases.php',
23
+ 'Google_Service' => $vendorDir . '/google/apiclient/src/aliases.php',
24
+ 'Google_Service_Exception' => $vendorDir . '/google/apiclient/src/aliases.php',
25
+ 'Google_Service_Resource' => $vendorDir . '/google/apiclient/src/aliases.php',
26
+ 'Google_Task_Composer' => $vendorDir . '/google/apiclient/src/aliases.php',
27
+ 'Google_Task_Exception' => $vendorDir . '/google/apiclient/src/aliases.php',
28
+ 'Google_Task_Retryable' => $vendorDir . '/google/apiclient/src/aliases.php',
29
+ 'Google_Task_Runner' => $vendorDir . '/google/apiclient/src/aliases.php',
30
+ 'Google_Utils_UriTemplate' => $vendorDir . '/google/apiclient/src/aliases.php',
31
+ 'Normalizer' => $vendorDir . '/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php',
32
+ );
vendor/composer/autoload_files.php ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_files.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname($vendorDir);
7
+
8
+ return array(
9
+ '7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
10
+ 'a0edc8309cc5e1d60e3047b5df6b7052' => $vendorDir . '/guzzlehttp/psr7/src/functions_include.php',
11
+ 'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php',
12
+ '25072dd6e2470089de65ae7bf11d3109' => $vendorDir . '/symfony/polyfill-php72/bootstrap.php',
13
+ 'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php',
14
+ 'f598d06aa772fa33d905e87be6398fb1' => $vendorDir . '/symfony/polyfill-intl-idn/bootstrap.php',
15
+ '37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
16
+ 'decc78cc4436b1292c6c0d151b19445c' => $vendorDir . '/phpseclib/phpseclib/phpseclib/bootstrap.php',
17
+ '1f87db08236948d07391152dccb70f04' => $vendorDir . '/google/apiclient-services/autoload.php',
18
+ 'a8d3953fd9959404dd22d3dfcd0a79f0' => $vendorDir . '/google/apiclient/src/aliases.php',
19
+ );
vendor/composer/autoload_namespaces.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
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
+ );
vendor/composer/autoload_psr4.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_psr4.php @generated by Composer
4
+
5
+ $vendorDir = dirname(dirname(__FILE__));
6
+ $baseDir = dirname($vendorDir);
7
+
8
+ return array(
9
+ 'phpseclib3\\' => array($vendorDir . '/phpseclib/phpseclib/phpseclib'),
10
+ 'Symfony\\Polyfill\\Php72\\' => array($vendorDir . '/symfony/polyfill-php72'),
11
+ 'Symfony\\Polyfill\\Intl\\Normalizer\\' => array($vendorDir . '/symfony/polyfill-intl-normalizer'),
12
+ 'Symfony\\Polyfill\\Intl\\Idn\\' => array($vendorDir . '/symfony/polyfill-intl-idn'),
13
+ 'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
14
+ 'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src'),
15
+ 'Psr\\Cache\\' => array($vendorDir . '/psr/cache/src'),
16
+ 'ParagonIE\\ConstantTime\\' => array($vendorDir . '/paragonie/constant_time_encoding/src'),
17
+ 'Monolog\\' => array($vendorDir . '/monolog/monolog/src/Monolog'),
18
+ 'GuzzleHttp\\Psr7\\' => array($vendorDir . '/guzzlehttp/psr7/src'),
19
+ 'GuzzleHttp\\Promise\\' => array($vendorDir . '/guzzlehttp/promises/src'),
20
+ 'GuzzleHttp\\' => array($vendorDir . '/guzzlehttp/guzzle/src'),
21
+ 'Google\\Service\\' => array($vendorDir . '/google/apiclient-services/src'),
22
+ 'Google\\Auth\\' => array($vendorDir . '/google/auth/src'),
23
+ 'Google\\' => array($vendorDir . '/google/apiclient/src'),
24
+ 'Firebase\\JWT\\' => array($vendorDir . '/firebase/php-jwt/src'),
25
+ );
vendor/composer/autoload_real.php ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_real.php @generated by Composer
4
+
5
+ class ComposerAutoloaderInit1cfac4bac5a1827f26c0b477558bd882
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
+ /**
17
+ * @return \Composer\Autoload\ClassLoader
18
+ */
19
+ public static function getLoader()
20
+ {
21
+ if (null !== self::$loader) {
22
+ return self::$loader;
23
+ }
24
+
25
+ require __DIR__ . '/platform_check.php';
26
+
27
+ spl_autoload_register(array('ComposerAutoloaderInit1cfac4bac5a1827f26c0b477558bd882', 'loadClassLoader'), true, true);
28
+ self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
29
+ spl_autoload_unregister(array('ComposerAutoloaderInit1cfac4bac5a1827f26c0b477558bd882', 'loadClassLoader'));
30
+
31
+ $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
32
+ if ($useStaticLoader) {
33
+ require __DIR__ . '/autoload_static.php';
34
+
35
+ call_user_func(\Composer\Autoload\ComposerStaticInit1cfac4bac5a1827f26c0b477558bd882::getInitializer($loader));
36
+ } else {
37
+ $map = require __DIR__ . '/autoload_namespaces.php';
38
+ foreach ($map as $namespace => $path) {
39
+ $loader->set($namespace, $path);
40
+ }
41
+
42
+ $map = require __DIR__ . '/autoload_psr4.php';
43
+ foreach ($map as $namespace => $path) {
44
+ $loader->setPsr4($namespace, $path);
45
+ }
46
+
47
+ $classMap = require __DIR__ . '/autoload_classmap.php';
48
+ if ($classMap) {
49
+ $loader->addClassMap($classMap);
50
+ }
51
+ }
52
+
53
+ $loader->register(true);
54
+
55
+ if ($useStaticLoader) {
56
+ $includeFiles = Composer\Autoload\ComposerStaticInit1cfac4bac5a1827f26c0b477558bd882::$files;
57
+ } else {
58
+ $includeFiles = require __DIR__ . '/autoload_files.php';
59
+ }
60
+ foreach ($includeFiles as $fileIdentifier => $file) {
61
+ composerRequire1cfac4bac5a1827f26c0b477558bd882($fileIdentifier, $file);
62
+ }
63
+
64
+ return $loader;
65
+ }
66
+ }
67
+
68
+ function composerRequire1cfac4bac5a1827f26c0b477558bd882($fileIdentifier, $file)
69
+ {
70
+ if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
71
+ require $file;
72
+
73
+ $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
74
+ }
75
+ }
vendor/composer/autoload_static.php ADDED
@@ -0,0 +1,161 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // autoload_static.php @generated by Composer
4
+
5
+ namespace Composer\Autoload;
6
+
7
+ class ComposerStaticInit1cfac4bac5a1827f26c0b477558bd882
8
+ {
9
+ public static $files = array (
10
+ '7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
11
+ 'a0edc8309cc5e1d60e3047b5df6b7052' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/functions_include.php',
12
+ 'c964ee0ededf28c96ebd9db5099ef910' => __DIR__ . '/..' . '/guzzlehttp/promises/src/functions_include.php',
13
+ '25072dd6e2470089de65ae7bf11d3109' => __DIR__ . '/..' . '/symfony/polyfill-php72/bootstrap.php',
14
+ 'e69f7f6ee287b969198c3c9d6777bd38' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/bootstrap.php',
15
+ 'f598d06aa772fa33d905e87be6398fb1' => __DIR__ . '/..' . '/symfony/polyfill-intl-idn/bootstrap.php',
16
+ '37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php',
17
+ 'decc78cc4436b1292c6c0d151b19445c' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/bootstrap.php',
18
+ '1f87db08236948d07391152dccb70f04' => __DIR__ . '/..' . '/google/apiclient-services/autoload.php',
19
+ 'a8d3953fd9959404dd22d3dfcd0a79f0' => __DIR__ . '/..' . '/google/apiclient/src/aliases.php',
20
+ );
21
+
22
+ public static $prefixLengthsPsr4 = array (
23
+ 'p' =>
24
+ array (
25
+ 'phpseclib3\\' => 11,
26
+ ),
27
+ 'S' =>
28
+ array (
29
+ 'Symfony\\Polyfill\\Php72\\' => 23,
30
+ 'Symfony\\Polyfill\\Intl\\Normalizer\\' => 33,
31
+ 'Symfony\\Polyfill\\Intl\\Idn\\' => 26,
32
+ ),
33
+ 'P' =>
34
+ array (
35
+ 'Psr\\Log\\' => 8,
36
+ 'Psr\\Http\\Message\\' => 17,
37
+ 'Psr\\Cache\\' => 10,
38
+ 'ParagonIE\\ConstantTime\\' => 23,
39
+ ),
40
+ 'M' =>
41
+ array (
42
+ 'Monolog\\' => 8,
43
+ ),
44
+ 'G' =>
45
+ array (
46
+ 'GuzzleHttp\\Psr7\\' => 16,
47
+ 'GuzzleHttp\\Promise\\' => 19,
48
+ 'GuzzleHttp\\' => 11,
49
+ 'Google\\Service\\' => 15,
50
+ 'Google\\Auth\\' => 12,
51
+ 'Google\\' => 7,
52
+ ),
53
+ 'F' =>
54
+ array (
55
+ 'Firebase\\JWT\\' => 13,
56
+ ),
57
+ );
58
+
59
+ public static $prefixDirsPsr4 = array (
60
+ 'phpseclib3\\' =>
61
+ array (
62
+ 0 => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib',
63
+ ),
64
+ 'Symfony\\Polyfill\\Php72\\' =>
65
+ array (
66
+ 0 => __DIR__ . '/..' . '/symfony/polyfill-php72',
67
+ ),
68
+ 'Symfony\\Polyfill\\Intl\\Normalizer\\' =>
69
+ array (
70
+ 0 => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer',
71
+ ),
72
+ 'Symfony\\Polyfill\\Intl\\Idn\\' =>
73
+ array (
74
+ 0 => __DIR__ . '/..' . '/symfony/polyfill-intl-idn',
75
+ ),
76
+ 'Psr\\Log\\' =>
77
+ array (
78
+ 0 => __DIR__ . '/..' . '/psr/log/Psr/Log',
79
+ ),
80
+ 'Psr\\Http\\Message\\' =>
81
+ array (
82
+ 0 => __DIR__ . '/..' . '/psr/http-message/src',
83
+ ),
84
+ 'Psr\\Cache\\' =>
85
+ array (
86
+ 0 => __DIR__ . '/..' . '/psr/cache/src',
87
+ ),
88
+ 'ParagonIE\\ConstantTime\\' =>
89
+ array (
90
+ 0 => __DIR__ . '/..' . '/paragonie/constant_time_encoding/src',
91
+ ),
92
+ 'Monolog\\' =>
93
+ array (
94
+ 0 => __DIR__ . '/..' . '/monolog/monolog/src/Monolog',
95
+ ),
96
+ 'GuzzleHttp\\Psr7\\' =>
97
+ array (
98
+ 0 => __DIR__ . '/..' . '/guzzlehttp/psr7/src',
99
+ ),
100
+ 'GuzzleHttp\\Promise\\' =>
101
+ array (
102
+ 0 => __DIR__ . '/..' . '/guzzlehttp/promises/src',
103
+ ),
104
+ 'GuzzleHttp\\' =>
105
+ array (
106
+ 0 => __DIR__ . '/..' . '/guzzlehttp/guzzle/src',
107
+ ),
108
+ 'Google\\Service\\' =>
109
+ array (
110
+ 0 => __DIR__ . '/..' . '/google/apiclient-services/src',
111
+ ),
112
+ 'Google\\Auth\\' =>
113
+ array (
114
+ 0 => __DIR__ . '/..' . '/google/auth/src',
115
+ ),
116
+ 'Google\\' =>
117
+ array (
118
+ 0 => __DIR__ . '/..' . '/google/apiclient/src',
119
+ ),
120
+ 'Firebase\\JWT\\' =>
121
+ array (
122
+ 0 => __DIR__ . '/..' . '/firebase/php-jwt/src',
123
+ ),
124
+ );
125
+
126
+ public static $classMap = array (
127
+ 'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
128
+ 'Google_AccessToken_Revoke' => __DIR__ . '/..' . '/google/apiclient/src/aliases.php',
129
+ 'Google_AccessToken_Verify' => __DIR__ . '/..' . '/google/apiclient/src/aliases.php',
130
+ 'Google_AuthHandler_AuthHandlerFactory' => __DIR__ . '/..' . '/google/apiclient/src/aliases.php',
131
+ 'Google_AuthHandler_Guzzle5AuthHandler' => __DIR__ . '/..' . '/google/apiclient/src/aliases.php',
132
+ 'Google_AuthHandler_Guzzle6AuthHandler' => __DIR__ . '/..' . '/google/apiclient/src/aliases.php',
133
+ 'Google_AuthHandler_Guzzle7AuthHandler' => __DIR__ . '/..' . '/google/apiclient/src/aliases.php',
134
+ 'Google_Client' => __DIR__ . '/..' . '/google/apiclient/src/aliases.php',
135
+ 'Google_Collection' => __DIR__ . '/..' . '/google/apiclient/src/aliases.php',
136
+ 'Google_Exception' => __DIR__ . '/..' . '/google/apiclient/src/aliases.php',
137
+ 'Google_Http_Batch' => __DIR__ . '/..' . '/google/apiclient/src/aliases.php',
138
+ 'Google_Http_MediaFileUpload' => __DIR__ . '/..' . '/google/apiclient/src/aliases.php',
139
+ 'Google_Http_REST' => __DIR__ . '/..' . '/google/apiclient/src/aliases.php',
140
+ 'Google_Model' => __DIR__ . '/..' . '/google/apiclient/src/aliases.php',
141
+ 'Google_Service' => __DIR__ . '/..' . '/google/apiclient/src/aliases.php',
142
+ 'Google_Service_Exception' => __DIR__ . '/..' . '/google/apiclient/src/aliases.php',
143
+ 'Google_Service_Resource' => __DIR__ . '/..' . '/google/apiclient/src/aliases.php',
144
+ 'Google_Task_Composer' => __DIR__ . '/..' . '/google/apiclient/src/aliases.php',
145
+ 'Google_Task_Exception' => __DIR__ . '/..' . '/google/apiclient/src/aliases.php',
146
+ 'Google_Task_Retryable' => __DIR__ . '/..' . '/google/apiclient/src/aliases.php',
147
+ 'Google_Task_Runner' => __DIR__ . '/..' . '/google/apiclient/src/aliases.php',
148
+ 'Google_Utils_UriTemplate' => __DIR__ . '/..' . '/google/apiclient/src/aliases.php',
149
+ 'Normalizer' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php',
150
+ );
151
+
152
+ public static function getInitializer(ClassLoader $loader)
153
+ {
154
+ return \Closure::bind(function () use ($loader) {
155
+ $loader->prefixLengthsPsr4 = ComposerStaticInit1cfac4bac5a1827f26c0b477558bd882::$prefixLengthsPsr4;
156
+ $loader->prefixDirsPsr4 = ComposerStaticInit1cfac4bac5a1827f26c0b477558bd882::$prefixDirsPsr4;
157
+ $loader->classMap = ComposerStaticInit1cfac4bac5a1827f26c0b477558bd882::$classMap;
158
+
159
+ }, null, ClassLoader::class);
160
+ }
161
+ }
vendor/composer/installed.json ADDED
@@ -0,0 +1,1255 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "packages": [
3
+ {
4
+ "name": "firebase/php-jwt",
5
+ "version": "v5.4.0",
6
+ "version_normalized": "5.4.0.0",
7
+ "source": {
8
+ "type": "git",
9
+ "url": "https://github.com/firebase/php-jwt.git",
10
+ "reference": "d2113d9b2e0e349796e72d2a63cf9319100382d2"
11
+ },
12
+ "dist": {
13
+ "type": "zip",
14
+ "url": "https://api.github.com/repos/firebase/php-jwt/zipball/d2113d9b2e0e349796e72d2a63cf9319100382d2",
15
+ "reference": "d2113d9b2e0e349796e72d2a63cf9319100382d2",
16
+ "shasum": ""
17
+ },
18
+ "require": {
19
+ "php": ">=5.3.0"
20
+ },
21
+ "require-dev": {
22
+ "phpunit/phpunit": ">=4.8 <=9"
23
+ },
24
+ "suggest": {
25
+ "paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present"
26
+ },
27
+ "time": "2021-06-23T19:00:23+00:00",
28
+ "type": "library",
29
+ "installation-source": "dist",
30
+ "autoload": {
31
+ "psr-4": {
32
+ "Firebase\\JWT\\": "src"
33
+ }
34
+ },
35
+ "notification-url": "https://packagist.org/downloads/",
36
+ "license": [
37
+ "BSD-3-Clause"
38
+ ],
39
+ "authors": [
40
+ {
41
+ "name": "Neuman Vong",
42
+ "email": "neuman+pear@twilio.com",
43
+ "role": "Developer"
44
+ },
45
+ {
46
+ "name": "Anant Narayanan",
47
+ "email": "anant@php.net",
48
+ "role": "Developer"
49
+ }
50
+ ],
51
+ "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.",
52
+ "homepage": "https://github.com/firebase/php-jwt",
53
+ "keywords": [
54
+ "jwt",
55
+ "php"
56
+ ],
57
+ "support": {
58
+ "issues": "https://github.com/firebase/php-jwt/issues",
59
+ "source": "https://github.com/firebase/php-jwt/tree/v5.4.0"
60
+ },
61
+ "install-path": "../firebase/php-jwt"
62
+ },
63
+ {
64
+ "name": "google/apiclient",
65
+ "version": "v2.10.1",
66
+ "version_normalized": "2.10.1.0",
67
+ "source": {
68
+ "type": "git",
69
+ "url": "https://github.com/googleapis/google-api-php-client.git",
70
+ "reference": "11871e94006ce7a419bb6124d51b6f9ace3f679b"
71
+ },
72
+ "dist": {
73
+ "type": "zip",
74
+ "url": "https://api.github.com/repos/googleapis/google-api-php-client/zipball/11871e94006ce7a419bb6124d51b6f9ace3f679b",
75
+ "reference": "11871e94006ce7a419bb6124d51b6f9ace3f679b",
76
+ "shasum": ""
77
+ },
78
+ "require": {
79
+ "firebase/php-jwt": "~2.0||~3.0||~4.0||~5.0",
80
+ "google/apiclient-services": "~0.200",
81
+ "google/auth": "^1.10",
82
+ "guzzlehttp/guzzle": "~5.3.3||~6.0||~7.0",
83
+ "guzzlehttp/psr7": "^1.2",
84
+ "monolog/monolog": "^1.17|^2.0",
85
+ "php": "^5.6|^7.0|^8.0",
86
+ "phpseclib/phpseclib": "~2.0||^3.0.2"
87
+ },
88
+ "require-dev": {
89
+ "cache/filesystem-adapter": "^0.3.2|^1.1",
90
+ "composer/composer": "^1.10.22",
91
+ "dealerdirect/phpcodesniffer-composer-installer": "^0.7",
92
+ "phpcompatibility/php-compatibility": "^9.2",
93
+ "phpunit/phpunit": "^5.7||^8.5.13",
94
+ "squizlabs/php_codesniffer": "~2.3",
95
+ "symfony/css-selector": "~2.1",
96
+ "symfony/dom-crawler": "~2.1"
97
+ },
98
+ "suggest": {
99
+ "cache/filesystem-adapter": "For caching certs and tokens (using Google\\Client::setCache)"
100
+ },
101
+ "time": "2021-06-25T14:25:44+00:00",
102
+ "type": "library",
103
+ "extra": {
104
+ "branch-alias": {
105
+ "dev-master": "2.x-dev"
106
+ }
107
+ },
108
+ "installation-source": "dist",
109
+ "autoload": {
110
+ "psr-4": {
111
+ "Google\\": "src/"
112
+ },
113
+ "files": [
114
+ "src/aliases.php"
115
+ ],
116
+ "classmap": [
117
+ "src/aliases.php"
118
+ ]
119
+ },
120
+ "notification-url": "https://packagist.org/downloads/",
121
+ "license": [
122
+ "Apache-2.0"
123
+ ],
124
+ "description": "Client library for Google APIs",
125
+ "homepage": "http://developers.google.com/api-client-library/php",
126
+ "keywords": [
127
+ "google"
128
+ ],
129
+ "support": {
130
+ "issues": "https://github.com/googleapis/google-api-php-client/issues",
131
+ "source": "https://github.com/googleapis/google-api-php-client/tree/v2.10.1"
132
+ },
133
+ "install-path": "../google/apiclient"
134
+ },
135
+ {
136
+ "name": "google/apiclient-services",
137
+ "version": "v0.206.0",
138
+ "version_normalized": "0.206.0.0",
139
+ "source": {
140
+ "type": "git",
141
+ "url": "https://github.com/googleapis/google-api-php-client-services.git",
142
+ "reference": "8ac3f4a7c201bbf794801b215e63f75f15cd0208"
143
+ },
144
+ "dist": {
145
+ "type": "zip",
146
+ "url": "https://api.github.com/repos/googleapis/google-api-php-client-services/zipball/8ac3f4a7c201bbf794801b215e63f75f15cd0208",
147
+ "reference": "8ac3f4a7c201bbf794801b215e63f75f15cd0208",
148
+ "shasum": ""
149
+ },
150
+ "require": {
151
+ "php": ">=5.6"
152
+ },
153
+ "require-dev": {
154
+ "phpunit/phpunit": "^5.7||^8.5.13"
155
+ },
156
+ "time": "2021-07-31T11:20:25+00:00",
157
+ "type": "library",
158
+ "installation-source": "dist",
159
+ "autoload": {
160
+ "psr-4": {
161
+ "Google\\Service\\": "src"
162
+ },
163
+ "files": [
164
+ "autoload.php"
165
+ ]
166
+ },
167
+ "notification-url": "https://packagist.org/downloads/",
168
+ "license": [
169
+ "Apache-2.0"
170
+ ],
171
+ "description": "Client library for Google APIs",
172
+ "homepage": "http://developers.google.com/api-client-library/php",
173
+ "keywords": [
174
+ "google"
175
+ ],
176
+ "support": {
177
+ "issues": "https://github.com/googleapis/google-api-php-client-services/issues",
178
+ "source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.206.0"
179
+ },
180
+ "install-path": "../google/apiclient-services"
181
+ },
182
+ {
183
+ "name": "google/auth",
184
+ "version": "v1.16.0",
185
+ "version_normalized": "1.16.0.0",
186
+ "source": {
187
+ "type": "git",
188
+ "url": "https://github.com/googleapis/google-auth-library-php.git",
189
+ "reference": "c747738d2dd450f541f09f26510198fbedd1c8a0"
190
+ },
191
+ "dist": {
192
+ "type": "zip",
193
+ "url": "https://api.github.com/repos/googleapis/google-auth-library-php/zipball/c747738d2dd450f541f09f26510198fbedd1c8a0",
194
+ "reference": "c747738d2dd450f541f09f26510198fbedd1c8a0",
195
+ "shasum": ""
196
+ },
197
+ "require": {
198
+ "firebase/php-jwt": "~2.0|~3.0|~4.0|~5.0",
199
+ "guzzlehttp/guzzle": "^5.3.1|^6.2.1|^7.0",
200
+ "guzzlehttp/psr7": "^1.2",
201
+ "php": ">=5.4",
202
+ "psr/cache": "^1.0|^2.0",
203
+ "psr/http-message": "^1.0"
204
+ },
205
+ "require-dev": {
206
+ "guzzlehttp/promises": "0.1.1|^1.3",
207
+ "kelvinmo/simplejwt": "^0.2.5|^0.5.1",
208
+ "phpseclib/phpseclib": "^2.0.31",
209
+ "phpunit/phpunit": "^4.8.36|^5.7",
210
+ "sebastian/comparator": ">=1.2.3",
211
+ "squizlabs/php_codesniffer": "^3.5"
212
+ },
213
+ "suggest": {
214
+ "phpseclib/phpseclib": "May be used in place of OpenSSL for signing strings or for token management. Please require version ^2."
215
+ },
216
+ "time": "2021-06-22T18:06:03+00:00",
217
+ "type": "library",
218
+ "installation-source": "dist",
219
+ "autoload": {
220
+ "psr-4": {
221
+ "Google\\Auth\\": "src"
222
+ }
223
+ },
224
+ "notification-url": "https://packagist.org/downloads/",
225
+ "license": [
226
+ "Apache-2.0"
227
+ ],
228
+ "description": "Google Auth Library for PHP",
229
+ "homepage": "http://github.com/google/google-auth-library-php",
230
+ "keywords": [
231
+ "Authentication",
232
+ "google",
233
+ "oauth2"
234
+ ],
235
+ "support": {
236
+ "docs": "https://googleapis.github.io/google-auth-library-php/master/",
237
+ "issues": "https://github.com/googleapis/google-auth-library-php/issues",
238
+ "source": "https://github.com/googleapis/google-auth-library-php/tree/v1.16.0"
239
+ },
240
+ "install-path": "../google/auth"
241
+ },
242
+ {
243
+ "name": "guzzlehttp/guzzle",
244
+ "version": "6.5.5",
245
+ "version_normalized": "6.5.5.0",
246
+ "source": {
247
+ "type": "git",
248
+ "url": "https://github.com/guzzle/guzzle.git",
249
+ "reference": "9d4290de1cfd701f38099ef7e183b64b4b7b0c5e"
250
+ },
251
+ "dist": {
252
+ "type": "zip",
253
+ "url": "https://api.github.com/repos/guzzle/guzzle/zipball/9d4290de1cfd701f38099ef7e183b64b4b7b0c5e",
254
+ "reference": "9d4290de1cfd701f38099ef7e183b64b4b7b0c5e",
255
+ "shasum": ""
256
+ },
257
+ "require": {
258
+ "ext-json": "*",
259
+ "guzzlehttp/promises": "^1.0",
260
+ "guzzlehttp/psr7": "^1.6.1",
261
+ "php": ">=5.5",
262
+ "symfony/polyfill-intl-idn": "^1.17.0"
263
+ },
264
+ "require-dev": {
265
+ "ext-curl": "*",
266
+ "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0",
267
+ "psr/log": "^1.1"
268
+ },
269
+ "suggest": {
270
+ "psr/log": "Required for using the Log middleware"
271
+ },
272
+ "time": "2020-06-16T21:01:06+00:00",
273
+ "type": "library",
274
+ "extra": {
275
+ "branch-alias": {
276
+ "dev-master": "6.5-dev"
277
+ }
278
+ },
279
+ "installation-source": "dist",
280
+ "autoload": {
281
+ "psr-4": {
282
+ "GuzzleHttp\\": "src/"
283
+ },
284
+ "files": [
285
+ "src/functions_include.php"
286
+ ]
287
+ },
288
+ "notification-url": "https://packagist.org/downloads/",
289
+ "license": [
290
+ "MIT"
291
+ ],
292
+ "authors": [
293
+ {
294
+ "name": "Michael Dowling",
295
+ "email": "mtdowling@gmail.com",
296
+ "homepage": "https://github.com/mtdowling"
297
+ }
298
+ ],
299
+ "description": "Guzzle is a PHP HTTP client library",
300
+ "homepage": "http://guzzlephp.org/",
301
+ "keywords": [
302
+ "client",
303
+ "curl",
304
+ "framework",
305
+ "http",
306
+ "http client",
307
+ "rest",
308
+ "web service"
309
+ ],
310
+ "support": {
311
+ "issues": "https://github.com/guzzle/guzzle/issues",
312
+ "source": "https://github.com/guzzle/guzzle/tree/6.5"
313
+ },
314
+ "install-path": "../guzzlehttp/guzzle"
315
+ },
316
+ {
317
+ "name": "guzzlehttp/promises",
318
+ "version": "1.4.1",
319
+ "version_normalized": "1.4.1.0",
320
+ "source": {
321
+ "type": "git",
322
+ "url": "https://github.com/guzzle/promises.git",
323
+ "reference": "8e7d04f1f6450fef59366c399cfad4b9383aa30d"
324
+ },
325
+ "dist": {
326
+ "type": "zip",
327
+ "url": "https://api.github.com/repos/guzzle/promises/zipball/8e7d04f1f6450fef59366c399cfad4b9383aa30d",
328
+ "reference": "8e7d04f1f6450fef59366c399cfad4b9383aa30d",
329
+ "shasum": ""
330
+ },
331
+ "require": {
332
+ "php": ">=5.5"
333
+ },
334
+ "require-dev": {
335
+ "symfony/phpunit-bridge": "^4.4 || ^5.1"
336
+ },
337
+ "time": "2021-03-07T09:25:29+00:00",
338
+ "type": "library",
339
+ "extra": {
340
+ "branch-alias": {
341
+ "dev-master": "1.4-dev"
342
+ }
343
+ },
344
+ "installation-source": "dist",
345
+ "autoload": {
346
+ "psr-4": {
347
+ "GuzzleHttp\\Promise\\": "src/"
348
+ },
349
+ "files": [
350
+ "src/functions_include.php"
351
+ ]
352
+ },
353
+ "notification-url": "https://packagist.org/downloads/",
354
+ "license": [
355
+ "MIT"
356
+ ],
357
+ "authors": [
358
+ {
359
+ "name": "Michael Dowling",
360
+ "email": "mtdowling@gmail.com",
361
+ "homepage": "https://github.com/mtdowling"
362
+ }
363
+ ],
364
+ "description": "Guzzle promises library",
365
+ "keywords": [
366
+ "promise"
367
+ ],
368
+ "support": {
369
+ "issues": "https://github.com/guzzle/promises/issues",
370
+ "source": "https://github.com/guzzle/promises/tree/1.4.1"
371
+ },
372
+ "install-path": "../guzzlehttp/promises"
373
+ },
374
+ {
375
+ "name": "guzzlehttp/psr7",
376
+ "version": "1.8.2",
377
+ "version_normalized": "1.8.2.0",
378
+ "source": {
379
+ "type": "git",
380
+ "url": "https://github.com/guzzle/psr7.git",
381
+ "reference": "dc960a912984efb74d0a90222870c72c87f10c91"
382
+ },
383
+ "dist": {
384
+ "type": "zip",
385
+ "url": "https://api.github.com/repos/guzzle/psr7/zipball/dc960a912984efb74d0a90222870c72c87f10c91",
386
+ "reference": "dc960a912984efb74d0a90222870c72c87f10c91",
387
+ "shasum": ""
388
+ },
389
+ "require": {
390
+ "php": ">=5.4.0",
391
+ "psr/http-message": "~1.0",
392
+ "ralouphie/getallheaders": "^2.0.5 || ^3.0.0"
393
+ },
394
+ "provide": {
395
+ "psr/http-message-implementation": "1.0"
396
+ },
397
+ "require-dev": {
398
+ "ext-zlib": "*",
399
+ "phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.8 || ^9.3.10"
400
+ },
401
+ "suggest": {
402
+ "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses"
403
+ },
404
+ "time": "2021-04-26T09:17:50+00:00",
405
+ "type": "library",
406
+ "extra": {
407
+ "branch-alias": {
408
+ "dev-master": "1.7-dev"
409
+ }
410
+ },
411
+ "installation-source": "dist",
412
+ "autoload": {
413
+ "psr-4": {
414
+ "GuzzleHttp\\Psr7\\": "src/"
415
+ },
416
+ "files": [
417
+ "src/functions_include.php"
418
+ ]
419
+ },
420
+ "notification-url": "https://packagist.org/downloads/",
421
+ "license": [
422
+ "MIT"
423
+ ],
424
+ "authors": [
425
+ {
426
+ "name": "Michael Dowling",
427
+ "email": "mtdowling@gmail.com",
428
+ "homepage": "https://github.com/mtdowling"
429
+ },
430
+ {
431
+ "name": "Tobias Schultze",
432
+ "homepage": "https://github.com/Tobion"
433
+ }
434
+ ],
435
+ "description": "PSR-7 message implementation that also provides common utility methods",
436
+ "keywords": [
437
+ "http",
438
+ "message",
439
+ "psr-7",
440
+ "request",
441
+ "response",
442
+ "stream",
443
+ "uri",
444
+ "url"
445
+ ],
446
+ "support": {
447
+ "issues": "https://github.com/guzzle/psr7/issues",
448
+ "source": "https://github.com/guzzle/psr7/tree/1.8.2"
449
+ },
450
+ "install-path": "../guzzlehttp/psr7"
451
+ },
452
+ {
453
+ "name": "monolog/monolog",
454
+ "version": "2.3.2",
455
+ "version_normalized": "2.3.2.0",
456
+ "source": {
457
+ "type": "git",
458
+ "url": "https://github.com/Seldaek/monolog.git",
459
+ "reference": "71312564759a7db5b789296369c1a264efc43aad"
460
+ },
461
+ "dist": {
462
+ "type": "zip",
463
+ "url": "https://api.github.com/repos/Seldaek/monolog/zipball/71312564759a7db5b789296369c1a264efc43aad",
464
+ "reference": "71312564759a7db5b789296369c1a264efc43aad",
465
+ "shasum": ""
466
+ },
467
+ "require": {
468
+ "php": ">=7.2",
469
+ "psr/log": "^1.0.1"
470
+ },
471
+ "provide": {
472
+ "psr/log-implementation": "1.0.0"
473
+ },
474
+ "require-dev": {
475
+ "aws/aws-sdk-php": "^2.4.9 || ^3.0",
476
+ "doctrine/couchdb": "~1.0@dev",
477
+ "elasticsearch/elasticsearch": "^7",
478
+ "graylog2/gelf-php": "^1.4.2",
479
+ "mongodb/mongodb": "^1.8",
480
+ "php-amqplib/php-amqplib": "~2.4",
481
+ "php-console/php-console": "^3.1.3",
482
+ "phpspec/prophecy": "^1.6.1",
483
+ "phpstan/phpstan": "^0.12.91",
484
+ "phpunit/phpunit": "^8.5",
485
+ "predis/predis": "^1.1",
486
+ "rollbar/rollbar": "^1.3",
487
+ "ruflin/elastica": ">=0.90 <7.0.1",
488
+ "swiftmailer/swiftmailer": "^5.3|^6.0"
489
+ },
490
+ "suggest": {
491
+ "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB",
492
+ "doctrine/couchdb": "Allow sending log messages to a CouchDB server",
493
+ "elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client",
494
+ "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)",
495
+ "ext-mbstring": "Allow to work properly with unicode symbols",
496
+ "ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)",
497
+ "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server",
498
+ "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)",
499
+ "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib",
500
+ "php-console/php-console": "Allow sending log messages to Google Chrome",
501
+ "rollbar/rollbar": "Allow sending log messages to Rollbar",
502
+ "ruflin/elastica": "Allow sending log messages to an Elastic Search server"
503
+ },
504
+ "time": "2021-07-23T07:42:52+00:00",
505
+ "type": "library",
506
+ "extra": {
507
+ "branch-alias": {
508
+ "dev-main": "2.x-dev"
509
+ }
510
+ },
511
+ "installation-source": "dist",
512
+ "autoload": {
513
+ "psr-4": {
514
+ "Monolog\\": "src/Monolog"
515
+ }
516
+ },
517
+ "notification-url": "https://packagist.org/downloads/",
518
+ "license": [
519
+ "MIT"
520
+ ],
521
+ "authors": [
522
+ {
523
+ "name": "Jordi Boggiano",
524
+ "email": "j.boggiano@seld.be",
525
+ "homepage": "https://seld.be"
526
+ }
527
+ ],
528
+ "description": "Sends your logs to files, sockets, inboxes, databases and various web services",
529
+ "homepage": "https://github.com/Seldaek/monolog",
530
+ "keywords": [
531
+ "log",
532
+ "logging",
533
+ "psr-3"
534
+ ],
535
+ "support": {
536
+ "issues": "https://github.com/Seldaek/monolog/issues",
537
+ "source": "https://github.com/Seldaek/monolog/tree/2.3.2"
538
+ },
539
+ "funding": [
540
+ {
541
+ "url": "https://github.com/Seldaek",
542
+ "type": "github"
543
+ },
544
+ {
545
+ "url": "https://tidelift.com/funding/github/packagist/monolog/monolog",
546
+ "type": "tidelift"
547
+ }
548
+ ],
549
+ "install-path": "../monolog/monolog"
550
+ },
551
+ {
552
+ "name": "paragonie/constant_time_encoding",
553
+ "version": "v2.4.0",
554
+ "version_normalized": "2.4.0.0",
555
+ "source": {
556
+ "type": "git",
557
+ "url": "https://github.com/paragonie/constant_time_encoding.git",
558
+ "reference": "f34c2b11eb9d2c9318e13540a1dbc2a3afbd939c"
559
+ },
560
+ "dist": {
561
+ "type": "zip",
562
+ "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/f34c2b11eb9d2c9318e13540a1dbc2a3afbd939c",
563
+ "reference": "f34c2b11eb9d2c9318e13540a1dbc2a3afbd939c",
564
+ "shasum": ""
565
+ },
566
+ "require": {
567
+ "php": "^7|^8"
568
+ },
569
+ "require-dev": {
570
+ "phpunit/phpunit": "^6|^7|^8|^9",
571
+ "vimeo/psalm": "^1|^2|^3|^4"
572
+ },
573
+ "time": "2020-12-06T15:14:20+00:00",
574
+ "type": "library",
575
+ "installation-source": "dist",
576
+ "autoload": {
577
+ "psr-4": {
578
+ "ParagonIE\\ConstantTime\\": "src/"
579
+ }
580
+ },
581
+ "notification-url": "https://packagist.org/downloads/",
582
+ "license": [
583
+ "MIT"
584
+ ],
585
+ "authors": [
586
+ {
587
+ "name": "Paragon Initiative Enterprises",
588
+ "email": "security@paragonie.com",
589
+ "homepage": "https://paragonie.com",
590
+ "role": "Maintainer"
591
+ },
592
+ {
593
+ "name": "Steve 'Sc00bz' Thomas",
594
+ "email": "steve@tobtu.com",
595
+ "homepage": "https://www.tobtu.com",
596
+ "role": "Original Developer"
597
+ }
598
+ ],
599
+ "description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)",
600
+ "keywords": [
601
+ "base16",
602
+ "base32",
603
+ "base32_decode",
604
+ "base32_encode",
605
+ "base64",
606
+ "base64_decode",
607
+ "base64_encode",
608
+ "bin2hex",
609
+ "encoding",
610
+ "hex",
611
+ "hex2bin",
612
+ "rfc4648"
613
+ ],
614
+ "support": {
615
+ "email": "info@paragonie.com",
616
+ "issues": "https://github.com/paragonie/constant_time_encoding/issues",
617
+ "source": "https://github.com/paragonie/constant_time_encoding"
618
+ },
619
+ "install-path": "../paragonie/constant_time_encoding"
620
+ },
621
+ {
622
+ "name": "paragonie/random_compat",
623
+ "version": "v9.99.100",
624
+ "version_normalized": "9.99.100.0",
625
+ "source": {
626
+ "type": "git",
627
+ "url": "https://github.com/paragonie/random_compat.git",
628
+ "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a"
629
+ },
630
+ "dist": {
631
+ "type": "zip",
632
+ "url": "https://api.github.com/repos/paragonie/random_compat/zipball/996434e5492cb4c3edcb9168db6fbb1359ef965a",
633
+ "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a",
634
+ "shasum": ""
635
+ },
636
+ "require": {
637
+ "php": ">= 7"
638
+ },
639
+ "require-dev": {
640
+ "phpunit/phpunit": "4.*|5.*",
641
+ "vimeo/psalm": "^1"
642
+ },
643
+ "suggest": {
644
+ "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
645
+ },
646
+ "time": "2020-10-15T08:29:30+00:00",
647
+ "type": "library",
648
+ "installation-source": "dist",
649
+ "notification-url": "https://packagist.org/downloads/",
650
+ "license": [
651
+ "MIT"
652
+ ],
653
+ "authors": [
654
+ {
655
+ "name": "Paragon Initiative Enterprises",
656
+ "email": "security@paragonie.com",
657
+ "homepage": "https://paragonie.com"
658
+ }
659
+ ],
660
+ "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
661
+ "keywords": [
662
+ "csprng",
663
+ "polyfill",
664
+ "pseudorandom",
665
+ "random"
666
+ ],
667
+ "support": {
668
+ "email": "info@paragonie.com",
669
+ "issues": "https://github.com/paragonie/random_compat/issues",
670
+ "source": "https://github.com/paragonie/random_compat"
671
+ },
672
+ "install-path": "../paragonie/random_compat"
673
+ },
674
+ {
675
+ "name": "phpseclib/phpseclib",
676
+ "version": "3.0.9",
677
+ "version_normalized": "3.0.9.0",
678
+ "source": {
679
+ "type": "git",
680
+ "url": "https://github.com/phpseclib/phpseclib.git",
681
+ "reference": "a127a5133804ff2f47ae629dd529b129da616ad7"
682
+ },
683
+ "dist": {
684
+ "type": "zip",
685
+ "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/a127a5133804ff2f47ae629dd529b129da616ad7",
686
+ "reference": "a127a5133804ff2f47ae629dd529b129da616ad7",
687
+ "shasum": ""
688
+ },
689
+ "require": {
690
+ "paragonie/constant_time_encoding": "^1|^2",
691
+ "paragonie/random_compat": "^1.4|^2.0|^9.99.99",
692
+ "php": ">=5.6.1"
693
+ },
694
+ "require-dev": {
695
+ "phing/phing": "~2.7",
696
+ "phpunit/phpunit": "^5.7|^6.0|^9.4",
697
+ "squizlabs/php_codesniffer": "~2.0"
698
+ },
699
+ "suggest": {
700
+ "ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.",
701
+ "ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.",
702
+ "ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.",
703
+ "ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations."
704
+ },
705
+ "time": "2021-06-14T06:54:45+00:00",
706
+ "type": "library",
707
+ "installation-source": "dist",
708
+ "autoload": {
709
+ "files": [
710
+ "phpseclib/bootstrap.php"
711
+ ],
712
+ "psr-4": {
713
+ "phpseclib3\\": "phpseclib/"
714
+ }
715
+ },
716
+ "notification-url": "https://packagist.org/downloads/",
717
+ "license": [
718
+ "MIT"
719
+ ],
720
+ "authors": [
721
+ {
722
+ "name": "Jim Wigginton",
723
+ "email": "terrafrost@php.net",
724
+ "role": "Lead Developer"
725
+ },
726
+ {
727
+ "name": "Patrick Monnerat",
728
+ "email": "pm@datasphere.ch",
729
+ "role": "Developer"
730
+ },
731
+ {
732
+ "name": "Andreas Fischer",
733
+ "email": "bantu@phpbb.com",
734
+ "role": "Developer"
735
+ },
736
+ {
737
+ "name": "Hans-Jürgen Petrich",
738
+ "email": "petrich@tronic-media.com",
739
+ "role": "Developer"
740
+ },
741
+ {
742
+ "name": "Graham Campbell",
743
+ "email": "graham@alt-three.com",
744
+ "role": "Developer"
745
+ }
746
+ ],
747
+ "description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.",
748
+ "homepage": "http://phpseclib.sourceforge.net",
749
+ "keywords": [
750
+ "BigInteger",
751
+ "aes",
752
+ "asn.1",
753
+ "asn1",
754
+ "blowfish",
755
+ "crypto",
756
+ "cryptography",
757
+ "encryption",
758
+ "rsa",
759
+ "security",
760
+ "sftp",
761
+ "signature",
762
+ "signing",
763
+ "ssh",
764
+ "twofish",
765
+ "x.509",
766
+ "x509"
767
+ ],
768
+ "support": {
769
+ "issues": "https://github.com/phpseclib/phpseclib/issues",
770
+ "source": "https://github.com/phpseclib/phpseclib/tree/3.0.9"
771
+ },
772
+ "funding": [
773
+ {
774
+ "url": "https://github.com/terrafrost",
775
+ "type": "github"
776
+ },
777
+ {
778
+ "url": "https://www.patreon.com/phpseclib",
779
+ "type": "patreon"
780
+ },
781
+ {
782
+ "url": "https://tidelift.com/funding/github/packagist/phpseclib/phpseclib",
783
+ "type": "tidelift"
784
+ }
785
+ ],
786
+ "install-path": "../phpseclib/phpseclib"
787
+ },
788
+ {
789
+ "name": "psr/cache",
790
+ "version": "1.0.1",
791
+ "version_normalized": "1.0.1.0",
792
+ "source": {
793
+ "type": "git",
794
+ "url": "https://github.com/php-fig/cache.git",
795
+ "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8"
796
+ },
797
+ "dist": {
798
+ "type": "zip",
799
+ "url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8",
800
+ "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8",
801
+ "shasum": ""
802
+ },
803
+ "require": {
804
+ "php": ">=5.3.0"
805
+ },
806
+ "time": "2016-08-06T20:24:11+00:00",
807
+ "type": "library",
808
+ "extra": {
809
+ "branch-alias": {
810
+ "dev-master": "1.0.x-dev"
811
+ }
812
+ },
813
+ "installation-source": "dist",
814
+ "autoload": {
815
+ "psr-4": {
816
+ "Psr\\Cache\\": "src/"
817
+ }
818
+ },
819
+ "notification-url": "https://packagist.org/downloads/",
820
+ "license": [
821
+ "MIT"
822
+ ],
823
+ "authors": [
824
+ {
825
+ "name": "PHP-FIG",
826
+ "homepage": "http://www.php-fig.org/"
827
+ }
828
+ ],
829
+ "description": "Common interface for caching libraries",
830
+ "keywords": [
831
+ "cache",
832
+ "psr",
833
+ "psr-6"
834
+ ],
835
+ "support": {
836
+ "source": "https://github.com/php-fig/cache/tree/master"
837
+ },
838
+ "install-path": "../psr/cache"
839
+ },
840
+ {
841
+ "name": "psr/http-message",
842
+ "version": "1.0.1",
843
+ "version_normalized": "1.0.1.0",
844
+ "source": {
845
+ "type": "git",
846
+ "url": "https://github.com/php-fig/http-message.git",
847
+ "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
848
+ },
849
+ "dist": {
850
+ "type": "zip",
851
+ "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
852
+ "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
853
+ "shasum": ""
854
+ },
855
+ "require": {
856
+ "php": ">=5.3.0"
857
+ },
858
+ "time": "2016-08-06T14:39:51+00:00",
859
+ "type": "library",
860
+ "extra": {
861
+ "branch-alias": {
862
+ "dev-master": "1.0.x-dev"
863
+ }
864
+ },
865
+ "installation-source": "dist",
866
+ "autoload": {
867
+ "psr-4": {
868
+ "Psr\\Http\\Message\\": "src/"
869
+ }
870
+ },
871
+ "notification-url": "https://packagist.org/downloads/",
872
+ "license": [
873
+ "MIT"
874
+ ],
875
+ "authors": [
876
+ {
877
+ "name": "PHP-FIG",
878
+ "homepage": "http://www.php-fig.org/"
879
+ }
880
+ ],
881
+ "description": "Common interface for HTTP messages",
882
+ "homepage": "https://github.com/php-fig/http-message",
883
+ "keywords": [
884
+ "http",
885
+ "http-message",
886
+ "psr",
887
+ "psr-7",
888
+ "request",
889
+ "response"
890
+ ],
891
+ "support": {
892
+ "source": "https://github.com/php-fig/http-message/tree/master"
893
+ },
894
+ "install-path": "../psr/http-message"
895
+ },
896
+ {
897
+ "name": "psr/log",
898
+ "version": "1.1.4",
899
+ "version_normalized": "1.1.4.0",
900
+ "source": {
901
+ "type": "git",
902
+ "url": "https://github.com/php-fig/log.git",
903
+ "reference": "d49695b909c3b7628b6289db5479a1c204601f11"
904
+ },
905
+ "dist": {
906
+ "type": "zip",
907
+ "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11",
908
+ "reference": "d49695b909c3b7628b6289db5479a1c204601f11",
909
+ "shasum": ""
910
+ },
911
+ "require": {
912
+ "php": ">=5.3.0"
913
+ },
914
+ "time": "2021-05-03T11:20:27+00:00",
915
+ "type": "library",
916
+ "extra": {
917
+ "branch-alias": {
918
+ "dev-master": "1.1.x-dev"
919
+ }
920
+ },
921
+ "installation-source": "dist",
922
+ "autoload": {
923
+ "psr-4": {
924
+ "Psr\\Log\\": "Psr/Log/"
925
+ }
926
+ },
927
+ "notification-url": "https://packagist.org/downloads/",
928
+ "license": [
929
+ "MIT"
930
+ ],
931
+ "authors": [
932
+ {
933
+ "name": "PHP-FIG",
934
+ "homepage": "https://www.php-fig.org/"
935
+ }
936
+ ],
937
+ "description": "Common interface for logging libraries",
938
+ "homepage": "https://github.com/php-fig/log",
939
+ "keywords": [
940
+ "log",
941
+ "psr",
942
+ "psr-3"
943
+ ],
944
+ "support": {
945
+ "source": "https://github.com/php-fig/log/tree/1.1.4"
946
+ },
947
+ "install-path": "../psr/log"
948
+ },
949
+ {
950
+ "name": "ralouphie/getallheaders",
951
+ "version": "3.0.3",
952
+ "version_normalized": "3.0.3.0",
953
+ "source": {
954
+ "type": "git",
955
+ "url": "https://github.com/ralouphie/getallheaders.git",
956
+ "reference": "120b605dfeb996808c31b6477290a714d356e822"
957
+ },
958
+ "dist": {
959
+ "type": "zip",
960
+ "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822",
961
+ "reference": "120b605dfeb996808c31b6477290a714d356e822",
962
+ "shasum": ""
963
+ },
964
+ "require": {
965
+ "php": ">=5.6"
966
+ },
967
+ "require-dev": {
968
+ "php-coveralls/php-coveralls": "^2.1",
969
+ "phpunit/phpunit": "^5 || ^6.5"
970
+ },
971
+ "time": "2019-03-08T08:55:37+00:00",
972
+ "type": "library",
973
+ "installation-source": "dist",
974
+ "autoload": {
975
+ "files": [
976
+ "src/getallheaders.php"
977
+ ]
978
+ },
979
+ "notification-url": "https://packagist.org/downloads/",
980
+ "license": [
981
+ "MIT"
982
+ ],
983
+ "authors": [
984
+ {
985
+ "name": "Ralph Khattar",
986
+ "email": "ralph.khattar@gmail.com"
987
+ }
988
+ ],
989
+ "description": "A polyfill for getallheaders.",
990
+ "support": {
991
+ "issues": "https://github.com/ralouphie/getallheaders/issues",
992
+ "source": "https://github.com/ralouphie/getallheaders/tree/develop"
993
+ },
994
+ "install-path": "../ralouphie/getallheaders"
995
+ },
996
+ {
997
+ "name": "symfony/polyfill-intl-idn",
998
+ "version": "v1.23.0",
999
+ "version_normalized": "1.23.0.0",
1000
+ "source": {
1001
+ "type": "git",
1002
+ "url": "https://github.com/symfony/polyfill-intl-idn.git",
1003
+ "reference": "65bd267525e82759e7d8c4e8ceea44f398838e65"
1004
+ },
1005
+ "dist": {
1006
+ "type": "zip",
1007
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/65bd267525e82759e7d8c4e8ceea44f398838e65",
1008
+ "reference": "65bd267525e82759e7d8c4e8ceea44f398838e65",
1009
+ "shasum": ""
1010
+ },
1011
+ "require": {
1012
+ "php": ">=7.1",
1013
+ "symfony/polyfill-intl-normalizer": "^1.10",
1014
+ "symfony/polyfill-php72": "^1.10"
1015
+ },
1016
+ "suggest": {
1017
+ "ext-intl": "For best performance"
1018
+ },
1019
+ "time": "2021-05-27T09:27:20+00:00",
1020
+ "type": "library",
1021
+ "extra": {
1022
+ "branch-alias": {
1023
+ "dev-main": "1.23-dev"
1024
+ },
1025
+ "thanks": {
1026
+ "name": "symfony/polyfill",
1027
+ "url": "https://github.com/symfony/polyfill"
1028
+ }
1029
+ },
1030
+ "installation-source": "dist",
1031
+ "autoload": {
1032
+ "psr-4": {
1033
+ "Symfony\\Polyfill\\Intl\\Idn\\": ""
1034
+ },
1035
+ "files": [
1036
+ "bootstrap.php"
1037
+ ]
1038
+ },
1039
+ "notification-url": "https://packagist.org/downloads/",
1040
+ "license": [
1041
+ "MIT"
1042
+ ],
1043
+ "authors": [
1044
+ {
1045
+ "name": "Laurent Bassin",
1046
+ "email": "laurent@bassin.info"
1047
+ },
1048
+ {
1049
+ "name": "Trevor Rowbotham",
1050
+ "email": "trevor.rowbotham@pm.me"
1051
+ },
1052
+ {
1053
+ "name": "Symfony Community",
1054
+ "homepage": "https://symfony.com/contributors"
1055
+ }
1056
+ ],
1057
+ "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions",
1058
+ "homepage": "https://symfony.com",
1059
+ "keywords": [
1060
+ "compatibility",
1061
+ "idn",
1062
+ "intl",
1063
+ "polyfill",
1064
+ "portable",
1065
+ "shim"
1066
+ ],
1067
+ "support": {
1068
+ "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.23.0"
1069
+ },
1070
+ "funding": [
1071
+ {
1072
+ "url": "https://symfony.com/sponsor",
1073
+ "type": "custom"
1074
+ },
1075
+ {
1076
+ "url": "https://github.com/fabpot",
1077
+ "type": "github"
1078
+ },
1079
+ {
1080
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
1081
+ "type": "tidelift"
1082
+ }
1083
+ ],
1084
+ "install-path": "../symfony/polyfill-intl-idn"
1085
+ },
1086
+ {
1087
+ "name": "symfony/polyfill-intl-normalizer",
1088
+ "version": "v1.23.0",
1089
+ "version_normalized": "1.23.0.0",
1090
+ "source": {
1091
+ "type": "git",
1092
+ "url": "https://github.com/symfony/polyfill-intl-normalizer.git",
1093
+ "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8"
1094
+ },
1095
+ "dist": {
1096
+ "type": "zip",
1097
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8590a5f561694770bdcd3f9b5c69dde6945028e8",
1098
+ "reference": "8590a5f561694770bdcd3f9b5c69dde6945028e8",
1099
+ "shasum": ""
1100
+ },
1101
+ "require": {
1102
+ "php": ">=7.1"
1103
+ },
1104
+ "suggest": {
1105
+ "ext-intl": "For best performance"
1106
+ },
1107
+ "time": "2021-02-19T12:13:01+00:00",
1108
+ "type": "library",
1109
+ "extra": {
1110
+ "branch-alias": {
1111
+ "dev-main": "1.23-dev"
1112
+ },
1113
+ "thanks": {
1114
+ "name": "symfony/polyfill",
1115
+ "url": "https://github.com/symfony/polyfill"
1116
+ }
1117
+ },
1118
+ "installation-source": "dist",
1119
+ "autoload": {
1120
+ "psr-4": {
1121
+ "Symfony\\Polyfill\\Intl\\Normalizer\\": ""
1122
+ },
1123
+ "files": [
1124
+ "bootstrap.php"
1125
+ ],
1126
+ "classmap": [
1127
+ "Resources/stubs"
1128
+ ]
1129
+ },
1130
+ "notification-url": "https://packagist.org/downloads/",
1131
+ "license": [
1132
+ "MIT"
1133
+ ],
1134
+ "authors": [
1135
+ {
1136
+ "name": "Nicolas Grekas",
1137
+ "email": "p@tchwork.com"
1138
+ },
1139
+ {
1140
+ "name": "Symfony Community",
1141
+ "homepage": "https://symfony.com/contributors"
1142
+ }
1143
+ ],
1144
+ "description": "Symfony polyfill for intl's Normalizer class and related functions",
1145
+ "homepage": "https://symfony.com",
1146
+ "keywords": [
1147
+ "compatibility",
1148
+ "intl",
1149
+ "normalizer",
1150
+ "polyfill",
1151
+ "portable",
1152
+ "shim"
1153
+ ],
1154
+ "support": {
1155
+ "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.23.0"
1156
+ },
1157
+ "funding": [
1158
+ {
1159
+ "url": "https://symfony.com/sponsor",
1160
+ "type": "custom"
1161
+ },
1162
+ {
1163
+ "url": "https://github.com/fabpot",
1164
+ "type": "github"
1165
+ },
1166
+ {
1167
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
1168
+ "type": "tidelift"
1169
+ }
1170
+ ],
1171
+ "install-path": "../symfony/polyfill-intl-normalizer"
1172
+ },
1173
+ {
1174
+ "name": "symfony/polyfill-php72",
1175
+ "version": "v1.23.0",
1176
+ "version_normalized": "1.23.0.0",
1177
+ "source": {
1178
+ "type": "git",
1179
+ "url": "https://github.com/symfony/polyfill-php72.git",
1180
+ "reference": "9a142215a36a3888e30d0a9eeea9766764e96976"
1181
+ },
1182
+ "dist": {
1183
+ "type": "zip",
1184
+ "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/9a142215a36a3888e30d0a9eeea9766764e96976",
1185
+ "reference": "9a142215a36a3888e30d0a9eeea9766764e96976",
1186
+ "shasum": ""
1187
+ },
1188
+ "require": {
1189
+ "php": ">=7.1"
1190
+ },
1191
+ "time": "2021-05-27T09:17:38+00:00",
1192
+ "type": "library",
1193
+ "extra": {
1194
+ "branch-alias": {
1195
+ "dev-main": "1.23-dev"
1196
+ },
1197
+ "thanks": {
1198
+ "name": "symfony/polyfill",
1199
+ "url": "https://github.com/symfony/polyfill"
1200
+ }
1201
+ },
1202
+ "installation-source": "dist",
1203
+ "autoload": {
1204
+ "psr-4": {
1205
+ "Symfony\\Polyfill\\Php72\\": ""
1206
+ },
1207
+ "files": [
1208
+ "bootstrap.php"
1209
+ ]
1210
+ },
1211
+ "notification-url": "https://packagist.org/downloads/",
1212
+ "license": [
1213
+ "MIT"
1214
+ ],
1215
+ "authors": [
1216
+ {
1217
+ "name": "Nicolas Grekas",
1218
+ "email": "p@tchwork.com"
1219
+ },
1220
+ {
1221
+ "name": "Symfony Community",
1222
+ "homepage": "https://symfony.com/contributors"
1223
+ }
1224
+ ],
1225
+ "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions",
1226
+ "homepage": "https://symfony.com",
1227
+ "keywords": [
1228
+ "compatibility",
1229
+ "polyfill",
1230
+ "portable",
1231
+ "shim"
1232
+ ],
1233
+ "support": {
1234
+ "source": "https://github.com/symfony/polyfill-php72/tree/v1.23.0"
1235
+ },
1236
+ "funding": [
1237
+ {
1238
+ "url": "https://symfony.com/sponsor",
1239
+ "type": "custom"
1240
+ },
1241
+ {
1242
+ "url": "https://github.com/fabpot",
1243
+ "type": "github"
1244
+ },
1245
+ {
1246
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
1247
+ "type": "tidelift"
1248
+ }
1249
+ ],
1250
+ "install-path": "../symfony/polyfill-php72"
1251
+ }
1252
+ ],
1253
+ "dev": true,
1254
+ "dev-package-names": []
1255
+ }
vendor/composer/installed.php ADDED
@@ -0,0 +1,197 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php return array(
2
+ 'root' => array(
3
+ 'pretty_version' => 'dev-master',
4
+ 'version' => 'dev-master',
5
+ 'type' => 'library',
6
+ 'install_path' => __DIR__ . '/../../',
7
+ 'aliases' => array(),
8
+ 'reference' => '8a59076f3959d1cd0460111e53f32577b4718150',
9
+ 'name' => '__root__',
10
+ 'dev' => true,
11
+ ),
12
+ 'versions' => array(
13
+ '__root__' => array(
14
+ 'pretty_version' => 'dev-master',
15
+ 'version' => 'dev-master',
16
+ 'type' => 'library',
17
+ 'install_path' => __DIR__ . '/../../',
18
+ 'aliases' => array(),
19
+ 'reference' => '8a59076f3959d1cd0460111e53f32577b4718150',
20
+ 'dev_requirement' => false,
21
+ ),
22
+ 'firebase/php-jwt' => array(
23
+ 'pretty_version' => 'v5.4.0',
24
+ 'version' => '5.4.0.0',
25
+ 'type' => 'library',
26
+ 'install_path' => __DIR__ . '/../firebase/php-jwt',
27
+ 'aliases' => array(),
28
+ 'reference' => 'd2113d9b2e0e349796e72d2a63cf9319100382d2',
29
+ 'dev_requirement' => false,
30
+ ),
31
+ 'google/apiclient' => array(
32
+ 'pretty_version' => 'v2.10.1',
33
+ 'version' => '2.10.1.0',
34
+ 'type' => 'library',
35
+ 'install_path' => __DIR__ . '/../google/apiclient',
36
+ 'aliases' => array(),
37
+ 'reference' => '11871e94006ce7a419bb6124d51b6f9ace3f679b',
38
+ 'dev_requirement' => false,
39
+ ),
40
+ 'google/apiclient-services' => array(
41
+ 'pretty_version' => 'v0.206.0',
42
+ 'version' => '0.206.0.0',
43
+ 'type' => 'library',
44
+ 'install_path' => __DIR__ . '/../google/apiclient-services',
45
+ 'aliases' => array(),
46
+ 'reference' => '8ac3f4a7c201bbf794801b215e63f75f15cd0208',
47
+ 'dev_requirement' => false,
48
+ ),
49
+ 'google/auth' => array(
50
+ 'pretty_version' => 'v1.16.0',
51
+ 'version' => '1.16.0.0',
52
+ 'type' => 'library',
53
+ 'install_path' => __DIR__ . '/../google/auth',
54
+ 'aliases' => array(),
55
+ 'reference' => 'c747738d2dd450f541f09f26510198fbedd1c8a0',
56
+ 'dev_requirement' => false,
57
+ ),
58
+ 'guzzlehttp/guzzle' => array(
59
+ 'pretty_version' => '6.5.5',
60
+ 'version' => '6.5.5.0',
61
+ 'type' => 'library',
62
+ 'install_path' => __DIR__ . '/../guzzlehttp/guzzle',
63
+ 'aliases' => array(),
64
+ 'reference' => '9d4290de1cfd701f38099ef7e183b64b4b7b0c5e',
65
+ 'dev_requirement' => false,
66
+ ),
67
+ 'guzzlehttp/promises' => array(
68
+ 'pretty_version' => '1.4.1',
69
+ 'version' => '1.4.1.0',
70
+ 'type' => 'library',
71
+ 'install_path' => __DIR__ . '/../guzzlehttp/promises',
72
+ 'aliases' => array(),
73
+ 'reference' => '8e7d04f1f6450fef59366c399cfad4b9383aa30d',
74
+ 'dev_requirement' => false,
75
+ ),
76
+ 'guzzlehttp/psr7' => array(
77
+ 'pretty_version' => '1.8.2',
78
+ 'version' => '1.8.2.0',
79
+ 'type' => 'library',
80
+ 'install_path' => __DIR__ . '/../guzzlehttp/psr7',
81
+ 'aliases' => array(),
82
+ 'reference' => 'dc960a912984efb74d0a90222870c72c87f10c91',
83
+ 'dev_requirement' => false,
84
+ ),
85
+ 'monolog/monolog' => array(
86
+ 'pretty_version' => '2.3.2',
87
+ 'version' => '2.3.2.0',
88
+ 'type' => 'library',
89
+ 'install_path' => __DIR__ . '/../monolog/monolog',
90
+ 'aliases' => array(),
91
+ 'reference' => '71312564759a7db5b789296369c1a264efc43aad',
92
+ 'dev_requirement' => false,
93
+ ),
94
+ 'paragonie/constant_time_encoding' => array(
95
+ 'pretty_version' => 'v2.4.0',
96
+ 'version' => '2.4.0.0',
97
+ 'type' => 'library',
98
+ 'install_path' => __DIR__ . '/../paragonie/constant_time_encoding',
99
+ 'aliases' => array(),
100
+ 'reference' => 'f34c2b11eb9d2c9318e13540a1dbc2a3afbd939c',
101
+ 'dev_requirement' => false,
102
+ ),
103
+ 'paragonie/random_compat' => array(
104
+ 'pretty_version' => 'v9.99.100',
105
+ 'version' => '9.99.100.0',
106
+ 'type' => 'library',
107
+ 'install_path' => __DIR__ . '/../paragonie/random_compat',
108
+ 'aliases' => array(),
109
+ 'reference' => '996434e5492cb4c3edcb9168db6fbb1359ef965a',
110
+ 'dev_requirement' => false,
111
+ ),
112
+ 'phpseclib/phpseclib' => array(
113
+ 'pretty_version' => '3.0.9',
114
+ 'version' => '3.0.9.0',
115
+ 'type' => 'library',
116
+ 'install_path' => __DIR__ . '/../phpseclib/phpseclib',
117
+ 'aliases' => array(),
118
+ 'reference' => 'a127a5133804ff2f47ae629dd529b129da616ad7',
119
+ 'dev_requirement' => false,
120
+ ),
121
+ 'psr/cache' => array(
122
+ 'pretty_version' => '1.0.1',
123
+ 'version' => '1.0.1.0',
124
+ 'type' => 'library',
125
+ 'install_path' => __DIR__ . '/../psr/cache',
126
+ 'aliases' => array(),
127
+ 'reference' => 'd11b50ad223250cf17b86e38383413f5a6764bf8',
128
+ 'dev_requirement' => false,
129
+ ),
130
+ 'psr/http-message' => array(
131
+ 'pretty_version' => '1.0.1',
132
+ 'version' => '1.0.1.0',
133
+ 'type' => 'library',
134
+ 'install_path' => __DIR__ . '/../psr/http-message',
135
+ 'aliases' => array(),
136
+ 'reference' => 'f6561bf28d520154e4b0ec72be95418abe6d9363',
137
+ 'dev_requirement' => false,
138
+ ),
139
+ 'psr/http-message-implementation' => array(
140
+ 'dev_requirement' => false,
141
+ 'provided' => array(
142
+ 0 => '1.0',
143
+ ),
144
+ ),
145
+ 'psr/log' => array(
146
+ 'pretty_version' => '1.1.4',
147
+ 'version' => '1.1.4.0',
148
+ 'type' => 'library',
149
+ 'install_path' => __DIR__ . '/../psr/log',
150
+ 'aliases' => array(),
151
+ 'reference' => 'd49695b909c3b7628b6289db5479a1c204601f11',
152
+ 'dev_requirement' => false,
153
+ ),
154
+ 'psr/log-implementation' => array(
155
+ 'dev_requirement' => false,
156
+ 'provided' => array(
157
+ 0 => '1.0.0',
158
+ ),
159
+ ),
160
+ 'ralouphie/getallheaders' => array(
161
+ 'pretty_version' => '3.0.3',
162
+ 'version' => '3.0.3.0',
163
+ 'type' => 'library',
164
+ 'install_path' => __DIR__ . '/../ralouphie/getallheaders',
165
+ 'aliases' => array(),
166
+ 'reference' => '120b605dfeb996808c31b6477290a714d356e822',
167
+ 'dev_requirement' => false,
168
+ ),
169
+ 'symfony/polyfill-intl-idn' => array(
170
+ 'pretty_version' => 'v1.23.0',
171
+ 'version' => '1.23.0.0',
172
+ 'type' => 'library',
173
+ 'install_path' => __DIR__ . '/../symfony/polyfill-intl-idn',
174
+ 'aliases' => array(),
175
+ 'reference' => '65bd267525e82759e7d8c4e8ceea44f398838e65',
176
+ 'dev_requirement' => false,
177
+ ),
178
+ 'symfony/polyfill-intl-normalizer' => array(
179
+ 'pretty_version' => 'v1.23.0',
180
+ 'version' => '1.23.0.0',
181
+ 'type' => 'library',
182
+ 'install_path' => __DIR__ . '/../symfony/polyfill-intl-normalizer',
183
+ 'aliases' => array(),
184
+ 'reference' => '8590a5f561694770bdcd3f9b5c69dde6945028e8',
185
+ 'dev_requirement' => false,
186
+ ),
187
+ 'symfony/polyfill-php72' => array(
188
+ 'pretty_version' => 'v1.23.0',
189
+ 'version' => '1.23.0.0',
190
+ 'type' => 'library',
191
+ 'install_path' => __DIR__ . '/../symfony/polyfill-php72',
192
+ 'aliases' => array(),
193
+ 'reference' => '9a142215a36a3888e30d0a9eeea9766764e96976',
194
+ 'dev_requirement' => false,
195
+ ),
196
+ ),
197
+ );
vendor/composer/platform_check.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // platform_check.php @generated by Composer
4
+
5
+ $issues = array();
6
+
7
+ if (!(PHP_VERSION_ID >= 70200)) {
8
+ $issues[] = 'Your Composer dependencies require a PHP version ">= 7.2.0". You are running ' . PHP_VERSION . '.';
9
+ }
10
+
11
+ if ($issues) {
12
+ if (!headers_sent()) {
13
+ header('HTTP/1.1 500 Internal Server Error');
14
+ }
15
+ if (!ini_get('display_errors')) {
16
+ if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
17
+ fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL);
18
+ } elseif (!headers_sent()) {
19
+ echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;
20
+ }
21
+ }
22
+ trigger_error(
23
+ 'Composer detected issues in your platform: ' . implode(' ', $issues),
24
+ E_USER_ERROR
25
+ );
26
+ }
vendor/firebase/php-jwt/LICENSE ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Copyright (c) 2011, Neuman Vong
2
+
3
+ All rights reserved.
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ * Redistributions of source code must retain the above copyright
9
+ notice, this list of conditions and the following disclaimer.
10
+
11
+ * Redistributions in binary form must reproduce the above
12
+ copyright notice, this list of conditions and the following
13
+ disclaimer in the documentation and/or other materials provided
14
+ with the distribution.
15
+
16
+ * Neither the name of the copyright holder nor the names of other
17
+ contributors may be used to endorse or promote products derived
18
+ from this software without specific prior written permission.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
vendor/firebase/php-jwt/src/BeforeValidException.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Firebase\JWT;
4
+
5
+ class BeforeValidException extends \UnexpectedValueException
6
+ {
7
+ }
vendor/firebase/php-jwt/src/ExpiredException.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Firebase\JWT;
4
+
5
+ class ExpiredException extends \UnexpectedValueException
6
+ {
7
+ }
vendor/firebase/php-jwt/src/JWK.php ADDED
@@ -0,0 +1,172 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Firebase\JWT;
4
+
5
+ use DomainException;
6
+ use InvalidArgumentException;
7
+ use UnexpectedValueException;
8
+
9
+ /**
10
+ * JSON Web Key implementation, based on this spec:
11
+ * https://tools.ietf.org/html/draft-ietf-jose-json-web-key-41
12
+ *
13
+ * PHP version 5
14
+ *
15
+ * @category Authentication
16
+ * @package Authentication_JWT
17
+ * @author Bui Sy Nguyen <nguyenbs@gmail.com>
18
+ * @license http://opensource.org/licenses/BSD-3-Clause 3-clause BSD
19
+ * @link https://github.com/firebase/php-jwt
20
+ */
21
+ class JWK
22
+ {
23
+ /**
24
+ * Parse a set of JWK keys
25
+ *
26
+ * @param array $jwks The JSON Web Key Set as an associative array
27
+ *
28
+ * @return array An associative array that represents the set of keys
29
+ *
30
+ * @throws InvalidArgumentException Provided JWK Set is empty
31
+ * @throws UnexpectedValueException Provided JWK Set was invalid
32
+ * @throws DomainException OpenSSL failure
33
+ *
34
+ * @uses parseKey
35
+ */
36
+ public static function parseKeySet(array $jwks)
37
+ {
38
+ $keys = array();
39
+
40
+ if (!isset($jwks['keys'])) {
41
+ throw new UnexpectedValueException('"keys" member must exist in the JWK Set');
42
+ }
43
+ if (empty($jwks['keys'])) {
44
+ throw new InvalidArgumentException('JWK Set did not contain any keys');
45
+ }
46
+
47
+ foreach ($jwks['keys'] as $k => $v) {
48
+ $kid = isset($v['kid']) ? $v['kid'] : $k;
49
+ if ($key = self::parseKey($v)) {
50
+ $keys[$kid] = $key;
51
+ }
52
+ }
53
+
54
+ if (0 === \count($keys)) {
55
+ throw new UnexpectedValueException('No supported algorithms found in JWK Set');
56
+ }
57
+
58
+ return $keys;
59
+ }
60
+
61
+ /**
62
+ * Parse a JWK key
63
+ *
64
+ * @param array $jwk An individual JWK
65
+ *
66
+ * @return resource|array An associative array that represents the key
67
+ *
68
+ * @throws InvalidArgumentException Provided JWK is empty
69
+ * @throws UnexpectedValueException Provided JWK was invalid
70
+ * @throws DomainException OpenSSL failure
71
+ *
72
+ * @uses createPemFromModulusAndExponent
73
+ */
74
+ public static function parseKey(array $jwk)
75
+ {
76
+ if (empty($jwk)) {
77
+ throw new InvalidArgumentException('JWK must not be empty');
78
+ }
79
+ if (!isset($jwk['kty'])) {
80
+ throw new UnexpectedValueException('JWK must contain a "kty" parameter');
81
+ }
82
+
83
+ switch ($jwk['kty']) {
84
+ case 'RSA':
85
+ if (!empty($jwk['d'])) {
86
+ throw new UnexpectedValueException('RSA private keys are not supported');
87
+ }
88
+ if (!isset($jwk['n']) || !isset($jwk['e'])) {
89
+ throw new UnexpectedValueException('RSA keys must contain values for both "n" and "e"');
90
+ }
91
+
92
+ $pem = self::createPemFromModulusAndExponent($jwk['n'], $jwk['e']);
93
+ $publicKey = \openssl_pkey_get_public($pem);
94
+ if (false === $publicKey) {
95
+ throw new DomainException(
96
+ 'OpenSSL error: ' . \openssl_error_string()
97
+ );
98
+ }
99
+ return $publicKey;
100
+ default:
101
+ // Currently only RSA is supported
102
+ break;
103
+ }
104
+ }
105
+
106
+ /**
107
+ * Create a public key represented in PEM format from RSA modulus and exponent information
108
+ *
109
+ * @param string $n The RSA modulus encoded in Base64
110
+ * @param string $e The RSA exponent encoded in Base64
111
+ *
112
+ * @return string The RSA public key represented in PEM format
113
+ *
114
+ * @uses encodeLength
115
+ */
116
+ private static function createPemFromModulusAndExponent($n, $e)
117
+ {
118
+ $modulus = JWT::urlsafeB64Decode($n);
119
+ $publicExponent = JWT::urlsafeB64Decode($e);
120
+
121
+ $components = array(
122
+ 'modulus' => \pack('Ca*a*', 2, self::encodeLength(\strlen($modulus)), $modulus),
123
+ 'publicExponent' => \pack('Ca*a*', 2, self::encodeLength(\strlen($publicExponent)), $publicExponent)
124
+ );
125
+
126
+ $rsaPublicKey = \pack(
127
+ 'Ca*a*a*',
128
+ 48,
129
+ self::encodeLength(\strlen($components['modulus']) + \strlen($components['publicExponent'])),
130
+ $components['modulus'],
131
+ $components['publicExponent']
132
+ );
133
+
134
+ // sequence(oid(1.2.840.113549.1.1.1), null)) = rsaEncryption.
135
+ $rsaOID = \pack('H*', '300d06092a864886f70d0101010500'); // hex version of MA0GCSqGSIb3DQEBAQUA
136
+ $rsaPublicKey = \chr(0) . $rsaPublicKey;
137
+ $rsaPublicKey = \chr(3) . self::encodeLength(\strlen($rsaPublicKey)) . $rsaPublicKey;
138
+
139
+ $rsaPublicKey = \pack(
140
+ 'Ca*a*',
141
+ 48,
142
+ self::encodeLength(\strlen($rsaOID . $rsaPublicKey)),
143
+ $rsaOID . $rsaPublicKey
144
+ );
145
+
146
+ $rsaPublicKey = "-----BEGIN PUBLIC KEY-----\r\n" .
147
+ \chunk_split(\base64_encode($rsaPublicKey), 64) .
148
+ '-----END PUBLIC KEY-----';
149
+
150
+ return $rsaPublicKey;
151
+ }
152
+
153
+ /**
154
+ * DER-encode the length
155
+ *
156
+ * DER supports lengths up to (2**8)**127, however, we'll only support lengths up to (2**8)**4. See
157
+ * {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 paragraph 8.1.3} for more information.
158
+ *
159
+ * @param int $length
160
+ * @return string
161
+ */
162
+ private static function encodeLength($length)
163
+ {
164
+ if ($length <= 0x7F) {
165
+ return \chr($length);
166
+ }
167
+
168
+ $temp = \ltrim(\pack('N', $length), \chr(0));
169
+
170
+ return \pack('Ca*', 0x80 | \strlen($temp), $temp);
171
+ }
172
+ }
vendor/firebase/php-jwt/src/JWT.php ADDED
@@ -0,0 +1,544 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Firebase\JWT;
4
+
5
+ use DomainException;
6
+ use Exception;
7
+ use InvalidArgumentException;
8
+ use UnexpectedValueException;
9
+ use DateTime;
10
+
11
+ /**
12
+ * JSON Web Token implementation, based on this spec:
13
+ * https://tools.ietf.org/html/rfc7519
14
+ *
15
+ * PHP version 5
16
+ *
17
+ * @category Authentication
18
+ * @package Authentication_JWT
19
+ * @author Neuman Vong <neuman@twilio.com>
20
+ * @author Anant Narayanan <anant@php.net>
21
+ * @license http://opensource.org/licenses/BSD-3-Clause 3-clause BSD
22
+ * @link https://github.com/firebase/php-jwt
23
+ */
24
+ class JWT
25
+ {
26
+ const ASN1_INTEGER = 0x02;
27
+ const ASN1_SEQUENCE = 0x10;
28
+ const ASN1_BIT_STRING = 0x03;
29
+
30
+ /**
31
+ * When checking nbf, iat or expiration times,
32
+ * we want to provide some extra leeway time to
33
+ * account for clock skew.
34
+ */
35
+ public static $leeway = 0;
36
+
37
+ /**
38
+ * Allow the current timestamp to be specified.
39
+ * Useful for fixing a value within unit testing.
40
+ *
41
+ * Will default to PHP time() value if null.
42
+ */
43
+ public static $timestamp = null;
44
+
45
+ public static $supported_algs = array(
46
+ 'ES384' => array('openssl', 'SHA384'),
47
+ 'ES256' => array('openssl', 'SHA256'),
48
+ 'HS256' => array('hash_hmac', 'SHA256'),
49
+ 'HS384' => array('hash_hmac', 'SHA384'),
50
+ 'HS512' => array('hash_hmac', 'SHA512'),
51
+ 'RS256' => array('openssl', 'SHA256'),
52
+ 'RS384' => array('openssl', 'SHA384'),
53
+ 'RS512' => array('openssl', 'SHA512'),
54
+ 'EdDSA' => array('sodium_crypto', 'EdDSA'),
55
+ );
56
+
57
+ /**
58
+ * Decodes a JWT string into a PHP object.
59
+ *
60
+ * @param string $jwt The JWT
61
+ * @param string|array|resource $key The key, or map of keys.
62
+ * If the algorithm used is asymmetric, this is the public key
63
+ * @param array $allowed_algs List of supported verification algorithms
64
+ * Supported algorithms are 'ES384','ES256', 'HS256', 'HS384',
65
+ * 'HS512', 'RS256', 'RS384', and 'RS512'
66
+ *
67
+ * @return object The JWT's payload as a PHP object
68
+ *
69
+ * @throws InvalidArgumentException Provided JWT was empty
70
+ * @throws UnexpectedValueException Provided JWT was invalid
71
+ * @throws SignatureInvalidException Provided JWT was invalid because the signature verification failed
72
+ * @throws BeforeValidException Provided JWT is trying to be used before it's eligible as defined by 'nbf'
73
+ * @throws BeforeValidException Provided JWT is trying to be used before it's been created as defined by 'iat'
74
+ * @throws ExpiredException Provided JWT has since expired, as defined by the 'exp' claim
75
+ *
76
+ * @uses jsonDecode
77
+ * @uses urlsafeB64Decode
78
+ */
79
+ public static function decode($jwt, $key, array $allowed_algs = array())
80
+ {
81
+ $timestamp = \is_null(static::$timestamp) ? \time() : static::$timestamp;
82
+
83
+ if (empty($key)) {
84
+ throw new InvalidArgumentException('Key may not be empty');
85
+ }
86
+ $tks = \explode('.', $jwt);
87
+ if (\count($tks) != 3) {
88
+ throw new UnexpectedValueException('Wrong number of segments');
89
+ }
90
+ list($headb64, $bodyb64, $cryptob64) = $tks;
91
+ if (null === ($header = static::jsonDecode(static::urlsafeB64Decode($headb64)))) {
92
+ throw new UnexpectedValueException('Invalid header encoding');
93
+ }
94
+ if (null === $payload = static::jsonDecode(static::urlsafeB64Decode($bodyb64))) {
95
+ throw new UnexpectedValueException('Invalid claims encoding');
96
+ }
97
+ if (false === ($sig = static::urlsafeB64Decode($cryptob64))) {
98
+ throw new UnexpectedValueException('Invalid signature encoding');
99
+ }
100
+ if (empty($header->alg)) {
101
+ throw new UnexpectedValueException('Empty algorithm');
102
+ }
103
+ if (empty(static::$supported_algs[$header->alg])) {
104
+ throw new UnexpectedValueException('Algorithm not supported');
105
+ }
106
+ if (!\in_array($header->alg, $allowed_algs)) {
107
+ throw new UnexpectedValueException('Algorithm not allowed');
108
+ }
109
+ if ($header->alg === 'ES256' || $header->alg === 'ES384') {
110
+ // OpenSSL expects an ASN.1 DER sequence for ES256/ES384 signatures
111
+ $sig = self::signatureToDER($sig);
112
+ }
113
+
114
+ if (\is_array($key) || $key instanceof \ArrayAccess) {
115
+ if (isset($header->kid)) {
116
+ if (!isset($key[$header->kid])) {
117
+ throw new UnexpectedValueException('"kid" invalid, unable to lookup correct key');
118
+ }
119
+ $key = $key[$header->kid];
120
+ } else {
121
+ throw new UnexpectedValueException('"kid" empty, unable to lookup correct key');
122
+ }
123
+ }
124
+
125
+ // Check the signature
126
+ if (!static::verify("$headb64.$bodyb64", $sig, $key, $header->alg)) {
127
+ throw new SignatureInvalidException('Signature verification failed');
128
+ }
129
+
130
+ // Check the nbf if it is defined. This is the time that the
131
+ // token can actually be used. If it's not yet that time, abort.
132
+ if (isset($payload->nbf) && $payload->nbf > ($timestamp + static::$leeway)) {
133
+ throw new BeforeValidException(
134
+ 'Cannot handle token prior to ' . \date(DateTime::ISO8601, $payload->nbf)
135
+ );
136
+ }
137
+
138
+ // Check that this token has been created before 'now'. This prevents
139
+ // using tokens that have been created for later use (and haven't
140
+ // correctly used the nbf claim).
141
+ if (isset($payload->iat) && $payload->iat > ($timestamp + static::$leeway)) {
142
+ throw new BeforeValidException(
143
+ 'Cannot handle token prior to ' . \date(DateTime::ISO8601, $payload->iat)
144
+ );
145
+ }
146
+
147
+ // Check if this token has expired.
148
+ if (isset($payload->exp) && ($timestamp - static::$leeway) >= $payload->exp) {
149
+ throw new ExpiredException('Expired token');
150
+ }
151
+
152
+ return $payload;
153
+ }
154
+
155
+ /**
156
+ * Converts and signs a PHP object or array into a JWT string.
157
+ *
158
+ * @param object|array $payload PHP object or array
159
+ * @param string|resource $key The secret key.
160
+ * If the algorithm used is asymmetric, this is the private key
161
+ * @param string $alg The signing algorithm.
162
+ * Supported algorithms are 'ES384','ES256', 'HS256', 'HS384',
163
+ * 'HS512', 'RS256', 'RS384', and 'RS512'
164
+ * @param mixed $keyId
165
+ * @param array $head An array with header elements to attach
166
+ *
167
+ * @return string A signed JWT
168
+ *
169
+ * @uses jsonEncode
170
+ * @uses urlsafeB64Encode
171
+ */
172
+ public static function encode($payload, $key, $alg = 'HS256', $keyId = null, $head = null)
173
+ {
174
+ $header = array('typ' => 'JWT', 'alg' => $alg);
175
+ if ($keyId !== null) {
176
+ $header['kid'] = $keyId;
177
+ }
178
+ if (isset($head) && \is_array($head)) {
179
+ $header = \array_merge($head, $header);
180
+ }
181
+ $segments = array();
182
+ $segments[] = static::urlsafeB64Encode(static::jsonEncode($header));
183
+ $segments[] = static::urlsafeB64Encode(static::jsonEncode($payload));
184
+ $signing_input = \implode('.', $segments);
185
+
186
+ $signature = static::sign($signing_input, $key, $alg);
187
+ $segments[] = static::urlsafeB64Encode($signature);
188
+
189
+ return \implode('.', $segments);
190
+ }
191
+
192
+ /**
193
+ * Sign a string with a given key and algorithm.
194
+ *
195
+ * @param string $msg The message to sign
196
+ * @param string|resource $key The secret key
197
+ * @param string $alg The signing algorithm.
198
+ * Supported algorithms are 'ES384','ES256', 'HS256', 'HS384',
199
+ * 'HS512', 'RS256', 'RS384', and 'RS512'
200
+ *
201
+ * @return string An encrypted message
202
+ *
203
+ * @throws DomainException Unsupported algorithm or bad key was specified
204
+ */
205
+ public static function sign($msg, $key, $alg = 'HS256')
206
+ {
207
+ if (empty(static::$supported_algs[$alg])) {
208
+ throw new DomainException('Algorithm not supported');
209
+ }
210
+ list($function, $algorithm) = static::$supported_algs[$alg];
211
+ switch ($function) {
212
+ case 'hash_hmac':
213
+ return \hash_hmac($algorithm, $msg, $key, true);
214
+ case 'openssl':
215
+ $signature = '';
216
+ $success = \openssl_sign($msg, $signature, $key, $algorithm);
217
+ if (!$success) {
218
+ throw new DomainException("OpenSSL unable to sign data");
219
+ }
220
+ if ($alg === 'ES256') {
221
+ $signature = self::signatureFromDER($signature, 256);
222
+ } elseif ($alg === 'ES384') {
223
+ $signature = self::signatureFromDER($signature, 384);
224
+ }
225
+ return $signature;
226
+ case 'sodium_crypto':
227
+ if (!function_exists('sodium_crypto_sign_detached')) {
228
+ throw new DomainException('libsodium is not available');
229
+ }
230
+ try {
231
+ // The last non-empty line is used as the key.
232
+ $lines = array_filter(explode("\n", $key));
233
+ $key = base64_decode(end($lines));
234
+ return sodium_crypto_sign_detached($msg, $key);
235
+ } catch (Exception $e) {
236
+ throw new DomainException($e->getMessage(), 0, $e);
237
+ }
238
+ }
239
+ }
240
+
241
+ /**
242
+ * Verify a signature with the message, key and method. Not all methods
243
+ * are symmetric, so we must have a separate verify and sign method.
244
+ *
245
+ * @param string $msg The original message (header and body)
246
+ * @param string $signature The original signature
247
+ * @param string|resource $key For HS*, a string key works. for RS*, must be a resource of an openssl public key
248
+ * @param string $alg The algorithm
249
+ *
250
+ * @return bool
251
+ *
252
+ * @throws DomainException Invalid Algorithm, bad key, or OpenSSL failure
253
+ */
254
+ private static function verify($msg, $signature, $key, $alg)
255
+ {
256
+ if (empty(static::$supported_algs[$alg])) {
257
+ throw new DomainException('Algorithm not supported');
258
+ }
259
+
260
+ list($function, $algorithm) = static::$supported_algs[$alg];
261
+ switch ($function) {
262
+ case 'openssl':
263
+ $success = \openssl_verify($msg, $signature, $key, $algorithm);
264
+ if ($success === 1) {
265
+ return true;
266
+ } elseif ($success === 0) {
267
+ return false;
268
+ }
269
+ // returns 1 on success, 0 on failure, -1 on error.
270
+ throw new DomainException(
271
+ 'OpenSSL error: ' . \openssl_error_string()
272
+ );
273
+ case 'sodium_crypto':
274
+ if (!function_exists('sodium_crypto_sign_verify_detached')) {
275
+ throw new DomainException('libsodium is not available');
276
+ }
277
+ try {
278
+ // The last non-empty line is used as the key.
279
+ $lines = array_filter(explode("\n", $key));
280
+ $key = base64_decode(end($lines));
281
+ return sodium_crypto_sign_verify_detached($signature, $msg, $key);
282
+ } catch (Exception $e) {
283
+ throw new DomainException($e->getMessage(), 0, $e);
284
+ }
285
+ case 'hash_hmac':
286
+ default:
287
+ $hash = \hash_hmac($algorithm, $msg, $key, true);
288
+ if (\function_exists('hash_equals')) {
289
+ return \hash_equals($signature, $hash);
290
+ }
291
+ $len = \min(static::safeStrlen($signature), static::safeStrlen($hash));
292
+
293
+ $status = 0;
294
+ for ($i = 0; $i < $len; $i++) {
295
+ $status |= (\ord($signature[$i]) ^ \ord($hash[$i]));
296
+ }
297
+ $status |= (static::safeStrlen($signature) ^ static::safeStrlen($hash));
298
+
299
+ return ($status === 0);
300
+ }
301
+ }
302
+
303
+ /**
304
+ * Decode a JSON string into a PHP object.
305
+ *
306
+ * @param string $input JSON string
307
+ *
308
+ * @return object Object representation of JSON string
309
+ *
310
+ * @throws DomainException Provided string was invalid JSON
311
+ */
312
+ public static function jsonDecode($input)
313
+ {
314
+ if (\version_compare(PHP_VERSION, '5.4.0', '>=') && !(\defined('JSON_C_VERSION') && PHP_INT_SIZE > 4)) {
315
+ /** In PHP >=5.4.0, json_decode() accepts an options parameter, that allows you
316
+ * to specify that large ints (like Steam Transaction IDs) should be treated as
317
+ * strings, rather than the PHP default behaviour of converting them to floats.
318
+ */
319
+ $obj = \json_decode($input, false, 512, JSON_BIGINT_AS_STRING);
320
+ } else {
321
+ /** Not all servers will support that, however, so for older versions we must
322
+ * manually detect large ints in the JSON string and quote them (thus converting
323
+ *them to strings) before decoding, hence the preg_replace() call.
324
+ */
325
+ $max_int_length = \strlen((string) PHP_INT_MAX) - 1;
326
+ $json_without_bigints = \preg_replace('/:\s*(-?\d{'.$max_int_length.',})/', ': "$1"', $input);
327
+ $obj = \json_decode($json_without_bigints);
328
+ }
329
+
330
+ if ($errno = \json_last_error()) {
331
+ static::handleJsonError($errno);
332
+ } elseif ($obj === null && $input !== 'null') {
333
+ throw new DomainException('Null result with non-null input');
334
+ }
335
+ return $obj;
336
+ }
337
+
338
+ /**
339
+ * Encode a PHP object into a JSON string.
340
+ *
341
+ * @param object|array $input A PHP object or array
342
+ *
343
+ * @return string JSON representation of the PHP object or array
344
+ *
345
+ * @throws DomainException Provided object could not be encoded to valid JSON
346
+ */
347
+ public static function jsonEncode($input)
348
+ {
349
+ $json = \json_encode($input);
350
+ if ($errno = \json_last_error()) {
351
+ static::handleJsonError($errno);
352
+ } elseif ($json === 'null' && $input !== null) {
353
+ throw new DomainException('Null result with non-null input');
354
+ }
355
+ return $json;
356
+ }
357
+
358
+ /**
359
+ * Decode a string with URL-safe Base64.
360
+ *
361
+ * @param string $input A Base64 encoded string
362
+ *
363
+ * @return string A decoded string
364
+ */
365
+ public static function urlsafeB64Decode($input)
366
+ {
367
+ $remainder = \strlen($input) % 4;
368
+ if ($remainder) {
369
+ $padlen = 4 - $remainder;
370
+ $input .= \str_repeat('=', $padlen);
371
+ }
372
+ return \base64_decode(\strtr($input, '-_', '+/'));
373
+ }
374
+
375
+ /**
376
+ * Encode a string with URL-safe Base64.
377
+ *
378
+ * @param string $input The string you want encoded
379
+ *
380
+ * @return string The base64 encode of what you passed in
381
+ */
382
+ public static function urlsafeB64Encode($input)
383
+ {
384
+ return \str_replace('=', '', \strtr(\base64_encode($input), '+/', '-_'));
385
+ }
386
+
387
+ /**
388
+ * Helper method to create a JSON error.
389
+ *
390
+ * @param int $errno An error number from json_last_error()
391
+ *
392
+ * @return void
393
+ */
394
+ private static function handleJsonError($errno)
395
+ {
396
+ $messages = array(
397
+ JSON_ERROR_DEPTH => 'Maximum stack depth exceeded',
398
+ JSON_ERROR_STATE_MISMATCH => 'Invalid or malformed JSON',
399
+ JSON_ERROR_CTRL_CHAR => 'Unexpected control character found',
400
+ JSON_ERROR_SYNTAX => 'Syntax error, malformed JSON',
401
+ JSON_ERROR_UTF8 => 'Malformed UTF-8 characters' //PHP >= 5.3.3
402
+ );
403
+ throw new DomainException(
404
+ isset($messages[$errno])
405
+ ? $messages[$errno]
406
+ : 'Unknown JSON error: ' . $errno
407
+ );
408
+ }
409
+
410
+ /**
411
+ * Get the number of bytes in cryptographic strings.
412
+ *
413
+ * @param string $str
414
+ *
415
+ * @return int
416
+ */
417
+ private static function safeStrlen($str)
418
+ {
419
+ if (\function_exists('mb_strlen')) {
420
+ return \mb_strlen($str, '8bit');
421
+ }
422
+ return \strlen($str);
423
+ }
424
+
425
+ /**
426
+ * Convert an ECDSA signature to an ASN.1 DER sequence
427
+ *
428
+ * @param string $sig The ECDSA signature to convert
429
+ * @return string The encoded DER object
430
+ */
431
+ private static function signatureToDER($sig)
432
+ {
433
+ // Separate the signature into r-value and s-value
434
+ list($r, $s) = \str_split($sig, (int) (\strlen($sig) / 2));
435
+
436
+ // Trim leading zeros
437
+ $r = \ltrim($r, "\x00");
438
+ $s = \ltrim($s, "\x00");
439
+
440
+ // Convert r-value and s-value from unsigned big-endian integers to
441
+ // signed two's complement
442
+ if (\ord($r[0]) > 0x7f) {
443
+ $r = "\x00" . $r;
444
+ }
445
+ if (\ord($s[0]) > 0x7f) {
446
+ $s = "\x00" . $s;
447
+ }
448
+
449
+ return self::encodeDER(
450
+ self::ASN1_SEQUENCE,
451
+ self::encodeDER(self::ASN1_INTEGER, $r) .
452
+ self::encodeDER(self::ASN1_INTEGER, $s)
453
+ );
454
+ }
455
+
456
+ /**
457
+ * Encodes a value into a DER object.
458
+ *
459
+ * @param int $type DER tag
460
+ * @param string $value the value to encode
461
+ * @return string the encoded object
462
+ */
463
+ private static function encodeDER($type, $value)
464
+ {
465
+ $tag_header = 0;
466
+ if ($type === self::ASN1_SEQUENCE) {
467
+ $tag_header |= 0x20;
468
+ }
469
+
470
+ // Type
471
+ $der = \chr($tag_header | $type);
472
+
473
+ // Length
474
+ $der .= \chr(\strlen($value));
475
+
476
+ return $der . $value;
477
+ }
478
+
479
+ /**
480
+ * Encodes signature from a DER object.
481
+ *
482
+ * @param string $der binary signature in DER format
483
+ * @param int $keySize the number of bits in the key
484
+ * @return string the signature
485
+ */
486
+ private static function signatureFromDER($der, $keySize)
487
+ {
488
+ // OpenSSL returns the ECDSA signatures as a binary ASN.1 DER SEQUENCE
489
+ list($offset, $_) = self::readDER($der);
490
+ list($offset, $r) = self::readDER($der, $offset);
491
+ list($offset, $s) = self::readDER($der, $offset);
492
+
493
+ // Convert r-value and s-value from signed two's compliment to unsigned
494
+ // big-endian integers
495
+ $r = \ltrim($r, "\x00");
496
+ $s = \ltrim($s, "\x00");
497
+
498
+ // Pad out r and s so that they are $keySize bits long
499
+ $r = \str_pad($r, $keySize / 8, "\x00", STR_PAD_LEFT);
500
+ $s = \str_pad($s, $keySize / 8, "\x00", STR_PAD_LEFT);
501
+
502
+ return $r . $s;
503
+ }
504
+
505
+ /**
506
+ * Reads binary DER-encoded data and decodes into a single object
507
+ *
508
+ * @param string $der the binary data in DER format
509
+ * @param int $offset the offset of the data stream containing the object
510
+ * to decode
511
+ * @return array [$offset, $data] the new offset and the decoded object
512
+ */
513
+ private static function readDER($der, $offset = 0)
514
+ {
515
+ $pos = $offset;
516
+ $size = \strlen($der);
517
+ $constructed = (\ord($der[$pos]) >> 5) & 0x01;
518
+ $type = \ord($der[$pos++]) & 0x1f;
519
+
520
+ // Length
521
+ $len = \ord($der[$pos++]);
522
+ if ($len & 0x80) {
523
+ $n = $len & 0x1f;
524
+ $len = 0;
525
+ while ($n-- && $pos < $size) {
526
+ $len = ($len << 8) | \ord($der[$pos++]);
527
+ }
528
+ }
529
+
530
+ // Value
531
+ if ($type == self::ASN1_BIT_STRING) {
532
+ $pos++; // Skip the first contents octet (padding indicator)
533
+ $data = \substr($der, $pos, $len - 1);
534
+ $pos += $len - 1;
535
+ } elseif (!$constructed) {
536
+ $data = \substr($der, $pos, $len);
537
+ $pos += $len;
538
+ } else {
539
+ $data = null;
540
+ }
541
+
542
+ return array($pos, $data);
543
+ }
544
+ }
vendor/firebase/php-jwt/src/SignatureInvalidException.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Firebase\JWT;
4
+
5
+ class SignatureInvalidException extends \UnexpectedValueException
6
+ {
7
+ }
vendor/google/apiclient-services/LICENSE ADDED
@@ -0,0 +1,203 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright [yyyy] [name of copyright owner]
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
202
+
203
+
vendor/google/apiclient-services/autoload.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // For older (pre-2.7.2) verions of google/apiclient
4
+ if (
5
+ file_exists(__DIR__ . '/../apiclient/src/Google/Client.php')
6
+ && !class_exists('Google_Client', false)
7
+ ) {
8
+ require_once(__DIR__ . '/../apiclient/src/Google/Client.php');
9
+ if (
10
+ defined('Google_Client::LIBVER')
11
+ && version_compare(Google_Client::LIBVER, '2.7.2', '<=')
12
+ ) {
13
+ $servicesClassMap = [
14
+ 'Google\\Client' => 'Google_Client',
15
+ 'Google\\Service' => 'Google_Service',
16
+ 'Google\\Service\\Resource' => 'Google_Service_Resource',
17
+ 'Google\\Model' => 'Google_Model',
18
+ 'Google\\Collection' => 'Google_Collection',
19
+ ];
20
+ foreach ($servicesClassMap as $alias => $class) {
21
+ class_alias($class, $alias);
22
+ }
23
+ }
24
+ }
25
+ spl_autoload_register(function ($class) {
26
+ if (0 === strpos($class, 'Google_Service_')) {
27
+ // Autoload the new class, which will also create an alias for the
28
+ // old class by changing underscores to namespaces:
29
+ // Google_Service_Speech_Resource_Operations
30
+ // => Google\Service\Speech\Resource\Operations
31
+ $classExists = class_exists($newClass = str_replace('_', '\\', $class));
32
+ if ($classExists) {
33
+ return true;
34
+ }
35
+ }
36
+ }, true, true);
vendor/google/apiclient-services/src/Indexing.php ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ namespace Google\Service;
19
+
20
+ use Google\Client;
21
+
22
+ /**
23
+ * Service definition for Indexing (v3).
24
+ *
25
+ * <p>
26
+ * Notifies Google when your web pages change.</p>
27
+ *
28
+ * <p>
29
+ * For more information about this service, see the API
30
+ * <a href="https://developers.google.com/search/apis/indexing-api/" target="_blank">Documentation</a>
31
+ * </p>
32
+ *
33
+ * @author Google, Inc.
34
+ */
35
+ class Indexing extends \Google\Service
36
+ {
37
+ /** Submit data to Google for indexing. */
38
+ const INDEXING =
39
+ "https://www.googleapis.com/auth/indexing";
40
+
41
+ public $urlNotifications;
42
+
43
+ /**
44
+ * Constructs the internal representation of the Indexing service.
45
+ *
46
+ * @param Client|array $clientOrConfig The client used to deliver requests, or a
47
+ * config array to pass to a new Client instance.
48
+ * @param string $rootUrl The root URL used for requests to the service.
49
+ */
50
+ public function __construct($clientOrConfig = [], $rootUrl = null)
51
+ {
52
+ parent::__construct($clientOrConfig);
53
+ $this->rootUrl = $rootUrl ?: 'https://indexing.googleapis.com/';
54
+ $this->servicePath = '';
55
+ $this->batchPath = 'batch';
56
+ $this->version = 'v3';
57
+ $this->serviceName = 'indexing';
58
+
59
+ $this->urlNotifications = new Indexing\Resource\UrlNotifications(
60
+ $this,
61
+ $this->serviceName,
62
+ 'urlNotifications',
63
+ [
64
+ 'methods' => [
65
+ 'getMetadata' => [
66
+ 'path' => 'v3/urlNotifications/metadata',
67
+ 'httpMethod' => 'GET',
68
+ 'parameters' => [
69
+ 'url' => [
70
+ 'location' => 'query',
71
+ 'type' => 'string',
72
+ ],
73
+ ],
74
+ ],'publish' => [
75
+ 'path' => 'v3/urlNotifications:publish',
76
+ 'httpMethod' => 'POST',
77
+ 'parameters' => [],
78
+ ],
79
+ ]
80
+ ]
81
+ );
82
+ }
83
+ }
84
+
85
+ // Adding a class alias for backwards compatibility with the previous class name.
86
+ class_alias(Indexing::class, 'Google_Service_Indexing');
vendor/google/apiclient-services/src/Indexing/PublishUrlNotificationResponse.php ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ namespace Google\Service\Indexing;
19
+
20
+ class PublishUrlNotificationResponse extends \Google\Model
21
+ {
22
+ protected $urlNotificationMetadataType = UrlNotificationMetadata::class;
23
+ protected $urlNotificationMetadataDataType = '';
24
+
25
+ /**
26
+ * @param UrlNotificationMetadata
27
+ */
28
+ public function setUrlNotificationMetadata(UrlNotificationMetadata $urlNotificationMetadata)
29
+ {
30
+ $this->urlNotificationMetadata = $urlNotificationMetadata;
31
+ }
32
+ /**
33
+ * @return UrlNotificationMetadata
34
+ */
35
+ public function getUrlNotificationMetadata()
36
+ {
37
+ return $this->urlNotificationMetadata;
38
+ }
39
+ }
40
+
41
+ // Adding a class alias for backwards compatibility with the previous class name.
42
+ class_alias(PublishUrlNotificationResponse::class, 'Google_Service_Indexing_PublishUrlNotificationResponse');
vendor/google/apiclient-services/src/Indexing/Resource/UrlNotifications.php ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ namespace Google\Service\Indexing\Resource;
19
+
20
+ use Google\Service\Indexing\PublishUrlNotificationResponse;
21
+ use Google\Service\Indexing\UrlNotification;
22
+ use Google\Service\Indexing\UrlNotificationMetadata;
23
+
24
+ /**
25
+ * The "urlNotifications" collection of methods.
26
+ * Typical usage is:
27
+ * <code>
28
+ * $indexingService = new Google\Service\Indexing(...);
29
+ * $urlNotifications = $indexingService->urlNotifications;
30
+ * </code>
31
+ */
32
+ class UrlNotifications extends \Google\Service\Resource
33
+ {
34
+ /**
35
+ * Gets metadata about a Web Document. This method can _only_ be used to query
36
+ * URLs that were previously seen in successful Indexing API notifications.
37
+ * Includes the latest `UrlNotification` received via this API.
38
+ * (urlNotifications.getMetadata)
39
+ *
40
+ * @param array $optParams Optional parameters.
41
+ *
42
+ * @opt_param string url URL that is being queried.
43
+ * @return UrlNotificationMetadata
44
+ */
45
+ public function getMetadata($optParams = [])
46
+ {
47
+ $params = [];
48
+ $params = array_merge($params, $optParams);
49
+ return $this->call('getMetadata', [$params], UrlNotificationMetadata::class);
50
+ }
51
+ /**
52
+ * Notifies that a URL has been updated or deleted. (urlNotifications.publish)
53
+ *
54
+ * @param UrlNotification $postBody
55
+ * @param array $optParams Optional parameters.
56
+ * @return PublishUrlNotificationResponse
57
+ */
58
+ public function publish(UrlNotification $postBody, $optParams = [])
59
+ {
60
+ $params = ['postBody' => $postBody];
61
+ $params = array_merge($params, $optParams);
62
+ return $this->call('publish', [$params], PublishUrlNotificationResponse::class);
63
+ }
64
+ }
65
+
66
+ // Adding a class alias for backwards compatibility with the previous class name.
67
+ class_alias(UrlNotifications::class, 'Google_Service_Indexing_Resource_UrlNotifications');
vendor/google/apiclient-services/src/Indexing/UrlNotification.php ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ namespace Google\Service\Indexing;
19
+
20
+ class UrlNotification extends \Google\Model
21
+ {
22
+ public $notifyTime;
23
+ public $type;
24
+ public $url;
25
+
26
+ public function setNotifyTime($notifyTime)
27
+ {
28
+ $this->notifyTime = $notifyTime;
29
+ }
30
+ public function getNotifyTime()
31
+ {
32
+ return $this->notifyTime;
33
+ }
34
+ public function setType($type)
35
+ {
36
+ $this->type = $type;
37
+ }
38
+ public function getType()
39
+ {
40
+ return $this->type;
41
+ }
42
+ public function setUrl($url)
43
+ {
44
+ $this->url = $url;
45
+ }
46
+ public function getUrl()
47
+ {
48
+ return $this->url;
49
+ }
50
+ }
51
+
52
+ // Adding a class alias for backwards compatibility with the previous class name.
53
+ class_alias(UrlNotification::class, 'Google_Service_Indexing_UrlNotification');
vendor/google/apiclient-services/src/Indexing/UrlNotificationMetadata.php ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ namespace Google\Service\Indexing;
19
+
20
+ class UrlNotificationMetadata extends \Google\Model
21
+ {
22
+ protected $latestRemoveType = UrlNotification::class;
23
+ protected $latestRemoveDataType = '';
24
+ protected $latestUpdateType = UrlNotification::class;
25
+ protected $latestUpdateDataType = '';
26
+ public $url;
27
+
28
+ /**
29
+ * @param UrlNotification
30
+ */
31
+ public function setLatestRemove(UrlNotification $latestRemove)
32
+ {
33
+ $this->latestRemove = $latestRemove;
34
+ }
35
+ /**
36
+ * @return UrlNotification
37
+ */
38
+ public function getLatestRemove()
39
+ {
40
+ return $this->latestRemove;
41
+ }
42
+ /**
43
+ * @param UrlNotification
44
+ */
45
+ public function setLatestUpdate(UrlNotification $latestUpdate)
46
+ {
47
+ $this->latestUpdate = $latestUpdate;
48
+ }
49
+ /**
50
+ * @return UrlNotification
51
+ */
52
+ public function getLatestUpdate()
53
+ {
54
+ return $this->latestUpdate;
55
+ }
56
+ public function setUrl($url)
57
+ {
58
+ $this->url = $url;
59
+ }
60
+ public function getUrl()
61
+ {
62
+ return $this->url;
63
+ }
64
+ }
65
+
66
+ // Adding a class alias for backwards compatibility with the previous class name.
67
+ class_alias(UrlNotificationMetadata::class, 'Google_Service_Indexing_UrlNotificationMetadata');
vendor/google/apiclient-services/synth.metadata ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "sources": [
3
+ {
4
+ "git": {
5
+ "name": ".",
6
+ "remote": "https://github.com/googleapis/google-api-php-client-services.git",
7
+ "sha": "9c653d59ab16b2d6b970de862b406535ff0eb7ee"
8
+ }
9
+ },
10
+ {
11
+ "git": {
12
+ "name": "discovery-artifact-manager",
13
+ "remote": "https://github.com/googleapis/discovery-artifact-manager.git",
14
+ "sha": "c542af134eaf20b46c56e52b861065c2b120be16"
15
+ }
16
+ }
17
+ ]
18
+ }
vendor/google/apiclient-services/synth.py ADDED
@@ -0,0 +1,119 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2020 Google LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ """This script is used to synthesize generated parts of this library."""
16
+
17
+ import synthtool as s
18
+ from synthtool.__main__ import extra_args
19
+ from synthtool import log, shell
20
+ from synthtool.sources import git
21
+ import logging
22
+ from os import path, remove
23
+ from pathlib import Path
24
+ import glob
25
+ import json
26
+ import re
27
+ import sys
28
+ from packaging import version
29
+
30
+ logging.basicConfig(level=logging.DEBUG)
31
+
32
+ VERSION_REGEX = r"([^\.]*)\.(.+)\.json$"
33
+
34
+ TEMPLATE_VERSIONS = [
35
+ "default",
36
+ ]
37
+ discovery_url = "https://github.com/googleapis/discovery-artifact-manager.git"
38
+
39
+ repository = Path('.')
40
+
41
+ log.debug(f"Cloning {discovery_url}.")
42
+ discovery = git.clone(discovery_url)
43
+
44
+ log.debug("Cleaning output directory.")
45
+ shell.run("rm -rf .cache".split(), cwd=repository)
46
+
47
+ log.debug("Installing dependencies.")
48
+ shell.run(
49
+ "python2 -m pip install -e generator/ --user".split(),
50
+ cwd=repository
51
+ )
52
+
53
+ def generate_service(disco: str):
54
+ m = re.search(VERSION_REGEX, disco)
55
+ name = m.group(1)
56
+ version = m.group(2)
57
+ template = TEMPLATE_VERSIONS[-1] # Generate for latest version
58
+
59
+ log.info(f"Generating {name} {version} ({template}).")
60
+
61
+ output_dir = repository / ".cache" / name / version
62
+ input_file = discovery / "discoveries" / disco
63
+
64
+ command = (
65
+ f"python2 -m googleapis.codegen --output_dir={output_dir}" +
66
+ f" --input={input_file} --language=php --language_variant={template}" +
67
+ f" --package_path=api/services"
68
+ )
69
+
70
+ shell.run(f"mkdir -p {output_dir}".split(), cwd=repository / "generator")
71
+ shell.run(command.split(), cwd=repository, hide_output=False)
72
+
73
+ s.copy(output_dir, f"src")
74
+
75
+ def all_discoveries(skip=None, prefer=None):
76
+ """Returns a map of API IDs to Discovery document filenames.
77
+
78
+ Args:
79
+ skip (list, optional): a list of API IDs to skip.
80
+ prefer (list, optional): a list of API IDs to include.
81
+
82
+ Returns:
83
+ list(string): A list of Discovery document filenames.
84
+ """
85
+ discos = {}
86
+ for file in sorted(glob.glob(str(discovery / 'discoveries/*.*.json'))):
87
+ api_id = None
88
+ with open(file) as api_file:
89
+ api_id = json.load(api_file)['id']
90
+ # If an API has already been visited, skip it.
91
+ if api_id in discos:
92
+ continue
93
+ # Skip APIs explicitly listed in "skip" arg
94
+ if skip and api_id in skip:
95
+ continue
96
+ discos[api_id] = path.basename(file)
97
+
98
+ # Skip APIs not preferred in index.json and not listed in "prefer" arg
99
+ index = {}
100
+ with open(str(discovery / 'discoveries/index.json')) as file:
101
+ index = json.load(file)
102
+ for api in index['items']:
103
+ api_id = api['id']
104
+ if prefer and api_id in prefer:
105
+ continue
106
+ if api['preferred']:
107
+ continue
108
+ discos.pop(api_id, None)
109
+
110
+ return discos.values()
111
+
112
+ def generate_services(services):
113
+ for service in services:
114
+ generate_service(service)
115
+
116
+ skip = ['discovery:v1', 'websecurityscanner:v1']
117
+ prefer = ['admin:directory_v1', 'admin:datatransfer_v1']
118
+ discoveries = all_discoveries(skip, prefer)
119
+ generate_services(discoveries)
vendor/google/apiclient/LICENSE ADDED
@@ -0,0 +1,203 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright [yyyy] [name of copyright owner]
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
202
+
203
+
vendor/google/apiclient/src/AccessToken/Revoke.php ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * Copyright 2008 Google Inc.
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */
18
+
19
+ namespace Google\AccessToken;
20
+
21
+ use Google\Auth\HttpHandler\HttpHandlerFactory;
22
+ use Google\Client;
23
+ use GuzzleHttp\ClientInterface;
24
+ use GuzzleHttp\Psr7;
25
+ use GuzzleHttp\Psr7\Request;
26
+
27
+ /**
28
+ * Wrapper around Google Access Tokens which provides convenience functions
29
+ *
30
+ */
31
+ class Revoke
32
+ {
33
+ /**
34
+ * @var ClientInterface The http client
35
+ */
36
+ private $http;
37
+
38
+ /**
39
+ * Instantiates the class, but does not initiate the login flow, leaving it
40
+ * to the discretion of the caller.
41
+ */
42
+ public function __construct(ClientInterface $http = null)
43
+ {
44
+ $this->http = $http;
45
+ }
46
+
47
+ /**
48
+ * Revoke an OAuth2 access token or refresh token. This method will revoke the current access
49
+ * token, if a token isn't provided.
50
+ *
51
+ * @param string|array $token The token (access token or a refresh token) that should be revoked.
52
+ * @return boolean Returns True if the revocation was successful, otherwise False.
53
+ */
54
+ public function revokeToken($token)
55
+ {
56
+ if (is_array($token)) {
57
+ if (isset($token['refresh_token'])) {
58
+ $token = $token['refresh_token'];
59
+ } else {
60
+ $token = $token['access_token'];
61
+ }
62
+ }
63
+
64
+ $body = Psr7\stream_for(http_build_query(array('token' => $token)));
65
+ $request = new Request(
66
+ 'POST',
67
+ Client::OAUTH2_REVOKE_URI,
68
+ [
69
+ 'Cache-Control' => 'no-store',
70
+ 'Content-Type' => 'application/x-www-form-urlencoded',
71
+ ],
72
+ $body
73
+ );
74
+
75
+ $httpHandler = HttpHandlerFactory::build($this->http);
76
+
77
+ $response = $httpHandler($request);
78
+
79
+ return $response->getStatusCode() == 200;
80
+ }
81
+ }
vendor/google/apiclient/src/AccessToken/Verify.php ADDED
@@ -0,0 +1,309 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /*
4
+ * Copyright 2008 Google Inc.
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */
18
+
19
+ namespace Google\AccessToken;
20
+
21
+ use Firebase\JWT\ExpiredException as ExpiredExceptionV3;
22
+ use Firebase\JWT\SignatureInvalidException;
23
+ use GuzzleHttp\Client;
24
+ use GuzzleHttp\ClientInterface;
25
+ use phpseclib3\Crypt\PublicKeyLoader;
26
+ use phpseclib3\Crypt\RSA\PublicKey;
27
+ use Psr\Cache\CacheItemPoolInterface;
28
+ use Google\Auth\Cache\MemoryCacheItemPool;
29
+ use Google\Exception as GoogleException;
30
+ use Stash\Driver\FileSystem;
31
+ use Stash\Pool;
32
+ use DateTime;
33
+ use DomainException;
34
+ use Exception;
35
+ use ExpiredException; // Firebase v2
36
+ use LogicException;
37
+
38
+ /**
39
+ * Wrapper around Google Access Tokens which provides convenience functions
40
+ *
41
+ */
42
+ class Verify
43
+ {
44
+ const FEDERATED_SIGNON_CERT_URL = 'https://www.googleapis.com/oauth2/v3/certs';
45
+ const OAUTH2_ISSUER = 'accounts.google.com';
46
+ const OAUTH2_ISSUER_HTTPS = 'https://accounts.google.com';
47
+
48
+ /**
49
+ * @var ClientInterface The http client
50
+ */
51
+ private $http;
52
+
53
+ /**
54
+ * @var CacheItemPoolInterface cache class
55
+ */
56
+ private $cache;
57
+
58
+ /**
59
+ * Instantiates the class, but does not initiate the login flow, leaving it
60
+ * to the discretion of the caller.
61
+ */
62
+ public function __construct(
63
+ ClientInterface $http = null,
64
+ CacheItemPoolInterface $cache = null,
65
+ $jwt = null
66
+ ) {
67
+ if (null === $http) {
68
+ $http = new Client();
69
+ }
70
+
71
+ if (null === $cache) {
72
+ $cache = new MemoryCacheItemPool;
73
+ }
74
+
75
+ $this->http = $http;
76
+ $this->cache = $cache;
77
+ $this->jwt = $jwt ?: $this->getJwtService();
78
+ }
79
+
80
+ /**
81
+ * Verifies an id token and returns the authenticated apiLoginTicket.
82
+ * Throws an exception if the id token is not valid.
83
+ * The audience parameter can be used to control which id tokens are
84
+ * accepted. By default, the id token must have been issued to this OAuth2 client.
85
+ *
86
+ * @param string $idToken the ID token in JWT format
87
+ * @param string $audience Optional. The audience to verify against JWt "aud"
88
+ * @return array the token payload, if successful
89
+ */
90
+ public function verifyIdToken($idToken, $audience = null)
91
+ {
92
+ if (empty($idToken)) {
93
+ throw new LogicException('id_token cannot be null');
94
+ }
95
+
96
+ // set phpseclib constants if applicable
97
+ $this->setPhpsecConstants();
98
+
99
+ // Check signature
100
+ $certs = $this->getFederatedSignOnCerts();
101
+ foreach ($certs as $cert) {
102
+ try {
103
+ $payload = $this->jwt->decode(
104
+ $idToken,
105
+ $this->getPublicKey($cert),
106
+ array('RS256')
107
+ );
108
+
109
+ if (property_exists($payload, 'aud')) {
110
+ if ($audience && $payload->aud != $audience) {
111
+ return false;
112
+ }
113
+ }
114
+
115
+ // support HTTP and HTTPS issuers
116
+ // @see https://developers.google.com/identity/sign-in/web/backend-auth
117
+ $issuers = array(self::OAUTH2_ISSUER, self::OAUTH2_ISSUER_HTTPS);
118
+ if (!isset($payload->iss) || !in_array($payload->iss, $issuers)) {
119
+ return false;
120
+ }
121
+
122
+ return (array) $payload;
123
+ } catch (ExpiredException $e) {
124
+ return false;
125
+ } catch (ExpiredExceptionV3 $e) {
126
+ return false;
127
+ } catch (SignatureInvalidException $e) {
128
+ // continue
129
+ } catch (DomainException $e) {
130
+ // continue
131
+ }
132
+ }
133
+
134
+ return false;
135
+ }
136
+
137
+ private function getCache()
138
+ {
139
+ return $this->cache;
140
+ }
141
+
142
+ /**
143
+ * Retrieve and cache a certificates file.
144
+ *
145
+ * @param $url string location
146
+ * @throws \Google\Exception
147
+ * @return array certificates
148
+ */
149
+ private function retrieveCertsFromLocation($url)
150
+ {
151
+ // If we're retrieving a local file, just grab it.
152
+ if (0 !== strpos($url, 'http')) {
153
+ if (!$file = file_get_contents($url)) {
154
+ throw new GoogleException(
155
+ "Failed to retrieve verification certificates: '" .
156
+ $url . "'."
157
+ );
158
+ }
159
+
160
+ return json_decode($file, true);
161
+ }
162
+
163
+ $response = $this->http->get($url);
164
+
165
+ if ($response->getStatusCode() == 200) {
166
+ return json_decode((string) $response->getBody(), true);
167
+ }
168
+ throw new GoogleException(
169
+ sprintf(
170
+ 'Failed to retrieve verification certificates: "%s".',
171
+ $response->getBody()->getContents()
172
+ ),
173
+ $response->getStatusCode()
174
+ );
175
+ }
176
+
177
+ // Gets federated sign-on certificates to use for verifying identity tokens.
178
+ // Returns certs as array structure, where keys are key ids, and values
179
+ // are PEM encoded certificates.
180
+ private function getFederatedSignOnCerts()
181
+ {
182
+ $certs = null;
183
+ if ($cache = $this->getCache()) {
184
+ $cacheItem = $cache->getItem('federated_signon_certs_v3');
185
+ $certs = $cacheItem->get();
186
+ }
187
+
188
+
189
+ if (!$certs) {
190
+ $certs = $this->retrieveCertsFromLocation(
191
+ self::FEDERATED_SIGNON_CERT_URL
192
+ );
193
+
194
+ if ($cache) {
195
+ $cacheItem->expiresAt(new DateTime('+1 hour'));
196
+ $cacheItem->set($certs);
197
+ $cache->save($cacheItem);
198
+ }
199
+ }
200
+
201
+ if (!isset($certs['keys'])) {
202
+ throw new InvalidArgumentException(
203
+ 'federated sign-on certs expects "keys" to be set'
204
+ );
205
+ }
206
+
207
+ return $certs['keys'];
208
+ }
209
+
210
+ private function getJwtService()
211
+ {
212
+ $jwtClass = 'JWT';
213
+ if (class_exists('\Firebase\JWT\JWT')) {
214
+ $jwtClass = 'Firebase\JWT\JWT';
215
+ }
216
+
217
+ if (property_exists($jwtClass, 'leeway') && $jwtClass::$leeway < 1) {
218
+ // Ensures JWT leeway is at least 1
219
+ // @see https://github.com/google/google-api-php-client/issues/827
220
+ $jwtClass::$leeway = 1;
221
+ }
222
+
223
+ return new $jwtClass;
224
+ }
225
+
226
+ private function getPublicKey($cert)
227
+ {
228
+ $bigIntClass = $this->getBigIntClass();
229
+ $modulus = new $bigIntClass($this->jwt->urlsafeB64Decode($cert['n']), 256);
230
+ $exponent = new $bigIntClass($this->jwt->urlsafeB64Decode($cert['e']), 256);
231
+ $component = array('n' => $modulus, 'e' => $exponent);
232
+
233
+ if (class_exists('phpseclib3\Crypt\RSA\PublicKey')) {
234
+ /** @var PublicKey $loader */
235
+ $loader = PublicKeyLoader::load($component);
236
+
237
+ return $loader->toString('PKCS8');
238
+ }
239
+
240
+ $rsaClass = $this->getRsaClass();
241
+ $rsa = new $rsaClass();
242
+ $rsa->loadKey($component);
243
+
244
+ return $rsa->getPublicKey();
245
+ }
246
+
247
+ private function getRsaClass()
248
+ {
249
+ if (class_exists('phpseclib3\Crypt\RSA')) {
250
+ return 'phpseclib3\Crypt\RSA';
251
+ }
252
+
253
+ if (class_exists('phpseclib\Crypt\RSA')) {
254
+ return 'phpseclib\Crypt\RSA';
255
+ }
256
+
257
+ return 'Crypt_RSA';
258
+ }
259
+
260
+ private function getBigIntClass()
261
+ {
262
+ if (class_exists('phpseclib3\Math\BigInteger')) {
263
+ return 'phpseclib3\Math\BigInteger';
264
+ }
265
+
266
+ if (class_exists('phpseclib\Math\BigInteger')) {
267
+ return 'phpseclib\Math\BigInteger';
268
+ }
269
+
270
+ return 'Math_BigInteger';
271
+ }
272
+
273
+ private function getOpenSslConstant()
274
+ {
275
+ if (class_exists('phpseclib3\Crypt\AES')) {
276
+ return 'phpseclib3\Crypt\AES::ENGINE_OPENSSL';
277
+ }
278
+
279
+ if (class_exists('phpseclib\Crypt\RSA')) {
280
+ return 'phpseclib\Crypt\RSA::MODE_OPENSSL';
281
+ }
282
+
283
+ if (class_exists('Crypt_RSA')) {
284
+ return 'CRYPT_RSA_MODE_OPENSSL';
285
+ }
286
+
287
+ throw new Exception('Cannot find RSA class');
288
+ }
289
+
290
+ /**
291
+ * phpseclib calls "phpinfo" by default, which requires special
292
+ * whitelisting in the AppEngine VM environment. This function
293
+ * sets constants to bypass the need for phpseclib to check phpinfo
294
+ *
295
+ * @see phpseclib/Math/BigInteger
296
+ * @see https://github.com/GoogleCloudPlatform/getting-started-php/issues/85
297
+ */
298
+ private function setPhpsecConstants()
299
+ {
300
+ if (filter_var(getenv('GAE_VM'), FILTER_VALIDATE_BOOLEAN)) {
301
+ if (!defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) {
302
+ define('MATH_BIGINTEGER_OPENSSL_ENABLED', true);
303
+ }
304
+ if (!defined('CRYPT_RSA_MODE')) {
305
+ define('CRYPT_RSA_MODE', constant($this->getOpenSslConstant()));
306
+ }
307
+ }
308
+ }
309
+ }
vendor/google/apiclient/src/AuthHandler/AuthHandlerFactory.php ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2015 Google Inc. All Rights Reserved.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\AuthHandler;
19
+
20
+ use GuzzleHttp\Client;
21
+ use GuzzleHttp\ClientInterface;
22
+ use Exception;
23
+
24
+ class AuthHandlerFactory
25
+ {
26
+ /**
27
+ * Builds out a default http handler for the installed version of guzzle.
28
+ *
29
+ * @return Guzzle5AuthHandler|Guzzle6AuthHandler|Guzzle7AuthHandler
30
+ * @throws Exception
31
+ */
32
+ public static function build($cache = null, array $cacheConfig = [])
33
+ {
34
+ $guzzleVersion = null;
35
+ if (defined('\GuzzleHttp\ClientInterface::MAJOR_VERSION')) {
36
+ $guzzleVersion = ClientInterface::MAJOR_VERSION;
37
+ } elseif (defined('\GuzzleHttp\ClientInterface::VERSION')) {
38
+ $guzzleVersion = (int) substr(ClientInterface::VERSION, 0, 1);
39
+ }
40
+
41
+ switch ($guzzleVersion) {
42
+ case 5:
43
+ return new Guzzle5AuthHandler($cache, $cacheConfig);
44
+ case 6:
45
+ return new Guzzle6AuthHandler($cache, $cacheConfig);
46
+ case 7:
47
+ return new Guzzle7AuthHandler($cache, $cacheConfig);
48
+ default:
49
+ throw new Exception('Version not supported');
50
+ }
51
+ }
52
+ }
vendor/google/apiclient/src/AuthHandler/Guzzle5AuthHandler.php ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Google\AuthHandler;
4
+
5
+ use Google\Auth\CredentialsLoader;
6
+ use Google\Auth\HttpHandler\HttpHandlerFactory;
7
+ use Google\Auth\FetchAuthTokenCache;
8
+ use Google\Auth\Subscriber\AuthTokenSubscriber;
9
+ use Google\Auth\Subscriber\ScopedAccessTokenSubscriber;
10
+ use Google\Auth\Subscriber\SimpleSubscriber;
11
+ use GuzzleHttp\Client;
12
+ use GuzzleHttp\ClientInterface;
13
+ use Psr\Cache\CacheItemPoolInterface;
14
+
15
+ /**
16
+ *
17
+ */
18
+ class Guzzle5AuthHandler
19
+ {
20
+ protected $cache;
21
+ protected $cacheConfig;
22
+
23
+ public function __construct(CacheItemPoolInterface $cache = null, array $cacheConfig = [])
24
+ {
25
+ $this->cache = $cache;
26
+ $this->cacheConfig = $cacheConfig;
27
+ }
28
+
29
+ public function attachCredentials(
30
+ ClientInterface $http,
31
+ CredentialsLoader $credentials,
32
+ callable $tokenCallback = null
33
+ ) {
34
+ // use the provided cache
35
+ if ($this->cache) {
36
+ $credentials = new FetchAuthTokenCache(
37
+ $credentials,
38
+ $this->cacheConfig,
39
+ $this->cache
40
+ );
41
+ }
42
+
43
+ return $this->attachCredentialsCache($http, $credentials, $tokenCallback);
44
+ }
45
+
46
+ public function attachCredentialsCache(
47
+ ClientInterface $http,
48
+ FetchAuthTokenCache $credentials,
49
+ callable $tokenCallback = null
50
+ ) {
51
+ // if we end up needing to make an HTTP request to retrieve credentials, we
52
+ // can use our existing one, but we need to throw exceptions so the error
53
+ // bubbles up.
54
+ $authHttp = $this->createAuthHttp($http);
55
+ $authHttpHandler = HttpHandlerFactory::build($authHttp);
56
+ $subscriber = new AuthTokenSubscriber(
57
+ $credentials,
58
+ $authHttpHandler,
59
+ $tokenCallback
60
+ );
61
+
62
+ $http->setDefaultOption('auth', 'google_auth');
63
+ $http->getEmitter()->attach($subscriber);
64
+
65
+ return $http;
66
+ }
67
+
68
+ public function attachToken(ClientInterface $http, array $token, array $scopes)
69
+ {
70
+ $tokenFunc = function ($scopes) use ($token) {
71
+ return $token['access_token'];
72
+ };
73
+
74
+ $subscriber = new ScopedAccessTokenSubscriber(
75
+ $tokenFunc,
76
+ $scopes,
77
+ $this->cacheConfig,
78
+ $this->cache
79
+ );
80
+
81
+ $http->setDefaultOption('auth', 'scoped');
82
+ $http->getEmitter()->attach($subscriber);
83
+
84
+ return $http;
85
+ }
86
+
87
+ public function attachKey(ClientInterface $http, $key)
88
+ {
89
+ $subscriber = new SimpleSubscriber(['key' => $key]);
90
+
91
+ $http->setDefaultOption('auth', 'simple');
92
+ $http->getEmitter()->attach($subscriber);
93
+
94
+ return $http;
95
+ }
96
+
97
+ private function createAuthHttp(ClientInterface $http)
98
+ {
99
+ return new Client(
100
+ [
101
+ 'base_url' => $http->getBaseUrl(),
102
+ 'defaults' => [
103
+ 'exceptions' => true,
104
+ 'verify' => $http->getDefaultOption('verify'),
105
+ 'proxy' => $http->getDefaultOption('proxy'),
106
+ ]
107
+ ]
108
+ );
109
+ }
110
+ }
vendor/google/apiclient/src/AuthHandler/Guzzle6AuthHandler.php ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Google\AuthHandler;
4
+
5
+ use Google\Auth\CredentialsLoader;
6
+ use Google\Auth\HttpHandler\HttpHandlerFactory;
7
+ use Google\Auth\FetchAuthTokenCache;
8
+ use Google\Auth\Middleware\AuthTokenMiddleware;
9
+ use Google\Auth\Middleware\ScopedAccessTokenMiddleware;
10
+ use Google\Auth\Middleware\SimpleMiddleware;
11
+ use GuzzleHttp\Client;
12
+ use GuzzleHttp\ClientInterface;
13
+ use Psr\Cache\CacheItemPoolInterface;
14
+
15
+ /**
16
+ * This supports Guzzle 6
17
+ */
18
+ class Guzzle6AuthHandler
19
+ {
20
+ protected $cache;
21
+ protected $cacheConfig;
22
+
23
+ public function __construct(CacheItemPoolInterface $cache = null, array $cacheConfig = [])
24
+ {
25
+ $this->cache = $cache;
26
+ $this->cacheConfig = $cacheConfig;
27
+ }
28
+
29
+ public function attachCredentials(
30
+ ClientInterface $http,
31
+ CredentialsLoader $credentials,
32
+ callable $tokenCallback = null
33
+ ) {
34
+ // use the provided cache
35
+ if ($this->cache) {
36
+ $credentials = new FetchAuthTokenCache(
37
+ $credentials,
38
+ $this->cacheConfig,
39
+ $this->cache
40
+ );
41
+ }
42
+
43
+ return $this->attachCredentialsCache($http, $credentials, $tokenCallback);
44
+ }
45
+
46
+ public function attachCredentialsCache(
47
+ ClientInterface $http,
48
+ FetchAuthTokenCache $credentials,
49
+ callable $tokenCallback = null
50
+ ) {
51
+ // if we end up needing to make an HTTP request to retrieve credentials, we
52
+ // can use our existing one, but we need to throw exceptions so the error
53
+ // bubbles up.
54
+ $authHttp = $this->createAuthHttp($http);
55
+ $authHttpHandler = HttpHandlerFactory::build($authHttp);
56
+ $middleware = new AuthTokenMiddleware(
57
+ $credentials,
58
+ $authHttpHandler,
59
+ $tokenCallback
60
+ );
61
+
62
+ $config = $http->getConfig();
63
+ $config['handler']->remove('google_auth');
64
+ $config['handler']->push($middleware, 'google_auth');
65
+ $config['auth'] = 'google_auth';
66
+ $http = new Client($config);
67
+
68
+ return $http;
69
+ }
70
+
71
+ public function attachToken(ClientInterface $http, array $token, array $scopes)
72
+ {
73
+ $tokenFunc = function ($scopes) use ($token) {
74
+ return $token['access_token'];
75
+ };
76
+
77
+ $middleware = new ScopedAccessTokenMiddleware(
78
+ $tokenFunc,
79
+ $scopes,
80
+ $this->cacheConfig,
81
+ $this->cache
82
+ );
83
+
84
+ $config = $http->getConfig();
85
+ $config['handler']->remove('google_auth');
86
+ $config['handler']->push($middleware, 'google_auth');
87
+ $config['auth'] = 'scoped';
88
+ $http = new Client($config);
89
+
90
+ return $http;
91
+ }
92
+
93
+ public function attachKey(ClientInterface $http, $key)
94
+ {
95
+ $middleware = new SimpleMiddleware(['key' => $key]);
96
+
97
+ $config = $http->getConfig();
98
+ $config['handler']->remove('google_auth');
99
+ $config['handler']->push($middleware, 'google_auth');
100
+ $config['auth'] = 'simple';
101
+ $http = new Client($config);
102
+
103
+ return $http;
104
+ }
105
+
106
+ private function createAuthHttp(ClientInterface $http)
107
+ {
108
+ return new Client(
109
+ [
110
+ 'base_uri' => $http->getConfig('base_uri'),
111
+ 'http_errors' => true,
112
+ 'verify' => $http->getConfig('verify'),
113
+ 'proxy' => $http->getConfig('proxy'),
114
+ ]
115
+ );
116
+ }
117
+ }
vendor/google/apiclient/src/AuthHandler/Guzzle7AuthHandler.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2020 Google LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\AuthHandler;
19
+
20
+ /**
21
+ * This supports Guzzle 7
22
+ */
23
+ class Guzzle7AuthHandler extends Guzzle6AuthHandler
24
+ {
25
+ }
vendor/google/apiclient/src/Client.php ADDED
@@ -0,0 +1,1274 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2010 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google;
19
+
20
+ use Google\AccessToken\Revoke;
21
+ use Google\AccessToken\Verify;
22
+ use Google\Auth\ApplicationDefaultCredentials;
23
+ use Google\Auth\Cache\MemoryCacheItemPool;
24
+ use Google\Auth\CredentialsLoader;
25
+ use Google\Auth\FetchAuthTokenCache;
26
+ use Google\Auth\HttpHandler\HttpHandlerFactory;
27
+ use Google\Auth\OAuth2;
28
+ use Google\Auth\Credentials\ServiceAccountCredentials;
29
+ use Google\Auth\Credentials\UserRefreshCredentials;
30
+ use Google\AuthHandler\AuthHandlerFactory;
31
+ use Google\Http\REST;
32
+ use GuzzleHttp\Client as GuzzleClient;
33
+ use GuzzleHttp\ClientInterface;
34
+ use GuzzleHttp\Ring\Client\StreamHandler;
35
+ use Psr\Cache\CacheItemPoolInterface;
36
+ use Psr\Http\Message\RequestInterface;
37
+ use Psr\Log\LoggerInterface;
38
+ use Monolog\Logger;
39
+ use Monolog\Handler\StreamHandler as MonologStreamHandler;
40
+ use Monolog\Handler\SyslogHandler as MonologSyslogHandler;
41
+ use BadMethodCallException;
42
+ use DomainException;
43
+ use InvalidArgumentException;
44
+ use LogicException;
45
+
46
+ /**
47
+ * The Google API Client
48
+ * https://github.com/google/google-api-php-client
49
+ */
50
+ class Client
51
+ {
52
+ const LIBVER = "2.10.1";
53
+ const USER_AGENT_SUFFIX = "google-api-php-client/";
54
+ const OAUTH2_REVOKE_URI = 'https://oauth2.googleapis.com/revoke';
55
+ const OAUTH2_TOKEN_URI = 'https://oauth2.googleapis.com/token';
56
+ const OAUTH2_AUTH_URL = 'https://accounts.google.com/o/oauth2/auth';
57
+ const API_BASE_PATH = 'https://www.googleapis.com';
58
+
59
+ /**
60
+ * @var OAuth2 $auth
61
+ */
62
+ private $auth;
63
+
64
+ /**
65
+ * @var ClientInterface $http
66
+ */
67
+ private $http;
68
+
69
+ /**
70
+ * @var CacheItemPoolInterface $cache
71
+ */
72
+ private $cache;
73
+
74
+ /**
75
+ * @var array access token
76
+ */
77
+ private $token;
78
+
79
+ /**
80
+ * @var array $config
81
+ */
82
+ private $config;
83
+
84
+ /**
85
+ * @var LoggerInterface $logger
86
+ */
87
+ private $logger;
88
+
89
+ /**
90
+ * @var boolean $deferExecution
91
+ */
92
+ private $deferExecution = false;
93
+
94
+ /** @var array $scopes */
95
+ // Scopes requested by the client
96
+ protected $requestedScopes = [];
97
+
98
+ /**
99
+ * Construct the Google Client.
100
+ *
101
+ * @param array $config
102
+ */
103
+ public function __construct(array $config = array())
104
+ {
105
+ $this->config = array_merge(
106
+ [
107
+ 'application_name' => '',
108
+
109
+ // Don't change these unless you're working against a special development
110
+ // or testing environment.
111
+ 'base_path' => self::API_BASE_PATH,
112
+
113
+ // https://developers.google.com/console
114
+ 'client_id' => '',
115
+ 'client_secret' => '',
116
+
117
+ // Path to JSON credentials or an array representing those credentials
118
+ // @see Google\Client::setAuthConfig
119
+ 'credentials' => null,
120
+ // @see Google\Client::setScopes
121
+ 'scopes' => null,
122
+ // Sets X-Goog-User-Project, which specifies a user project to bill
123
+ // for access charges associated with the request
124
+ 'quota_project' => null,
125
+
126
+ 'redirect_uri' => null,
127
+ 'state' => null,
128
+
129
+ // Simple API access key, also from the API console. Ensure you get
130
+ // a Server key, and not a Browser key.
131
+ 'developer_key' => '',
132
+
133
+ // For use with Google Cloud Platform
134
+ // fetch the ApplicationDefaultCredentials, if applicable
135
+ // @see https://developers.google.com/identity/protocols/application-default-credentials
136
+ 'use_application_default_credentials' => false,
137
+ 'signing_key' => null,
138
+ 'signing_algorithm' => null,
139
+ 'subject' => null,
140
+
141
+ // Other OAuth2 parameters.
142
+ 'hd' => '',
143
+ 'prompt' => '',
144
+ 'openid.realm' => '',
145
+ 'include_granted_scopes' => null,
146
+ 'login_hint' => '',
147
+ 'request_visible_actions' => '',
148
+ 'access_type' => 'online',
149
+ 'approval_prompt' => 'auto',
150
+
151
+ // Task Runner retry configuration
152
+ // @see Google\Task\Runner
153
+ 'retry' => array(),
154
+ 'retry_map' => null,
155
+
156
+ // Cache class implementing Psr\Cache\CacheItemPoolInterface.
157
+ // Defaults to Google\Auth\Cache\MemoryCacheItemPool.
158
+ 'cache' => null,
159
+ // cache config for downstream auth caching
160
+ 'cache_config' => [],
161
+
162
+ // function to be called when an access token is fetched
163
+ // follows the signature function ($cacheKey, $accessToken)
164
+ 'token_callback' => null,
165
+
166
+ // Service class used in Google\Client::verifyIdToken.
167
+ // Explicitly pass this in to avoid setting JWT::$leeway
168
+ 'jwt' => null,
169
+
170
+ // Setting api_format_v2 will return more detailed error messages
171
+ // from certain APIs.
172
+ 'api_format_v2' => false
173
+ ],
174
+ $config
175
+ );
176
+
177
+ if (!is_null($this->config['credentials'])) {
178
+ $this->setAuthConfig($this->config['credentials']);
179
+ unset($this->config['credentials']);
180
+ }
181
+
182
+ if (!is_null($this->config['scopes'])) {
183
+ $this->setScopes($this->config['scopes']);
184
+ unset($this->config['scopes']);
185
+ }
186
+
187
+ // Set a default token callback to update the in-memory access token
188
+ if (is_null($this->config['token_callback'])) {
189
+ $this->config['token_callback'] = function ($cacheKey, $newAccessToken) {
190
+ $this->setAccessToken(
191
+ [
192
+ 'access_token' => $newAccessToken,
193
+ 'expires_in' => 3600, // Google default
194
+ 'created' => time(),
195
+ ]
196
+ );
197
+ };
198
+ }
199
+
200
+ if (!is_null($this->config['cache'])) {
201
+ $this->setCache($this->config['cache']);
202
+ unset($this->config['cache']);
203
+ }
204
+ }
205
+
206
+ /**
207
+ * Get a string containing the version of the library.
208
+ *
209
+ * @return string
210
+ */
211
+ public function getLibraryVersion()
212
+ {
213
+ return self::LIBVER;
214
+ }
215
+
216
+ /**
217
+ * For backwards compatibility
218
+ * alias for fetchAccessTokenWithAuthCode
219
+ *
220
+ * @param $code string code from accounts.google.com
221
+ * @return array access token
222
+ * @deprecated
223
+ */
224
+ public function authenticate($code)
225
+ {
226
+ return $this->fetchAccessTokenWithAuthCode($code);
227
+ }
228
+
229
+ /**
230
+ * Attempt to exchange a code for an valid authentication token.
231
+ * Helper wrapped around the OAuth 2.0 implementation.
232
+ *
233
+ * @param $code string code from accounts.google.com
234
+ * @return array access token
235
+ */
236
+ public function fetchAccessTokenWithAuthCode($code)
237
+ {
238
+ if (strlen($code) == 0) {
239
+ throw new InvalidArgumentException("Invalid code");
240
+ }
241
+
242
+ $auth = $this->getOAuth2Service();
243
+ $auth->setCode($code);
244
+ $auth->setRedirectUri($this->getRedirectUri());
245
+
246
+ $httpHandler = HttpHandlerFactory::build($this->getHttpClient());
247
+ $creds = $auth->fetchAuthToken($httpHandler);
248
+ if ($creds && isset($creds['access_token'])) {
249
+ $creds['created'] = time();
250
+ $this->setAccessToken($creds);
251
+ }
252
+
253
+ return $creds;
254
+ }
255
+
256
+ /**
257
+ * For backwards compatibility
258
+ * alias for fetchAccessTokenWithAssertion
259
+ *
260
+ * @return array access token
261
+ * @deprecated
262
+ */
263
+ public function refreshTokenWithAssertion()
264
+ {
265
+ return $this->fetchAccessTokenWithAssertion();
266
+ }
267
+
268
+ /**
269
+ * Fetches a fresh access token with a given assertion token.
270
+ * @param ClientInterface $authHttp optional.
271
+ * @return array access token
272
+ */
273
+ public function fetchAccessTokenWithAssertion(ClientInterface $authHttp = null)
274
+ {
275
+ if (!$this->isUsingApplicationDefaultCredentials()) {
276
+ throw new DomainException(
277
+ 'set the JSON service account credentials using'
278
+ . ' Google\Client::setAuthConfig or set the path to your JSON file'
279
+ . ' with the "GOOGLE_APPLICATION_CREDENTIALS" environment variable'
280
+ . ' and call Google\Client::useApplicationDefaultCredentials to'
281
+ . ' refresh a token with assertion.'
282
+ );
283
+ }
284
+
285
+ $this->getLogger()->log(
286
+ 'info',
287
+ 'OAuth2 access token refresh with Signed JWT assertion grants.'
288
+ );
289
+
290
+ $credentials = $this->createApplicationDefaultCredentials();
291
+
292
+ $httpHandler = HttpHandlerFactory::build($authHttp);
293
+ $creds = $credentials->fetchAuthToken($httpHandler);
294
+ if ($creds && isset($creds['access_token'])) {
295
+ $creds['created'] = time();
296
+ $this->setAccessToken($creds);
297
+ }
298
+
299
+ return $creds;
300
+ }
301
+
302
+ /**
303
+ * For backwards compatibility
304
+ * alias for fetchAccessTokenWithRefreshToken
305
+ *
306
+ * @param string $refreshToken
307
+ * @return array access token
308
+ */
309
+ public function refreshToken($refreshToken)
310
+ {
311
+ return $this->fetchAccessTokenWithRefreshToken($refreshToken);
312
+ }
313
+
314
+ /**
315
+ * Fetches a fresh OAuth 2.0 access token with the given refresh token.
316
+ * @param string $refreshToken
317
+ * @return array access token
318
+ */
319
+ public function fetchAccessTokenWithRefreshToken($refreshToken = null)
320
+ {
321
+ if (null === $refreshToken) {
322
+ if (!isset($this->token['refresh_token'])) {
323
+ throw new LogicException(
324
+ 'refresh token must be passed in or set as part of setAccessToken'
325
+ );
326
+ }
327
+ $refreshToken = $this->token['refresh_token'];
328
+ }
329
+ $this->getLogger()->info('OAuth2 access token refresh');
330
+ $auth = $this->getOAuth2Service();
331
+ $auth->setRefreshToken($refreshToken);
332
+
333
+ $httpHandler = HttpHandlerFactory::build($this->getHttpClient());
334
+ $creds = $auth->fetchAuthToken($httpHandler);
335
+ if ($creds && isset($creds['access_token'])) {
336
+ $creds['created'] = time();
337
+ if (!isset($creds['refresh_token'])) {
338
+ $creds['refresh_token'] = $refreshToken;
339
+ }
340
+ $this->setAccessToken($creds);
341
+ }
342
+
343
+ return $creds;
344
+ }
345
+
346
+ /**
347
+ * Create a URL to obtain user authorization.
348
+ * The authorization endpoint allows the user to first
349
+ * authenticate, and then grant/deny the access request.
350
+ * @param string|array $scope The scope is expressed as an array or list of space-delimited strings.
351
+ * @return string
352
+ */
353
+ public function createAuthUrl($scope = null)
354
+ {
355
+ if (empty($scope)) {
356
+ $scope = $this->prepareScopes();
357
+ }
358
+ if (is_array($scope)) {
359
+ $scope = implode(' ', $scope);
360
+ }
361
+
362
+ // only accept one of prompt or approval_prompt
363
+ $approvalPrompt = $this->config['prompt']
364
+ ? null
365
+ : $this->config['approval_prompt'];
366
+
367
+ // include_granted_scopes should be string "true", string "false", or null
368
+ $includeGrantedScopes = $this->config['include_granted_scopes'] === null
369
+ ? null
370
+ : var_export($this->config['include_granted_scopes'], true);
371
+
372
+ $params = array_filter(
373
+ [
374
+ 'access_type' => $this->config['access_type'],
375
+ 'approval_prompt' => $approvalPrompt,
376
+ 'hd' => $this->config['hd'],
377
+ 'include_granted_scopes' => $includeGrantedScopes,
378
+ 'login_hint' => $this->config['login_hint'],
379
+ 'openid.realm' => $this->config['openid.realm'],
380
+ 'prompt' => $this->config['prompt'],
381
+ 'response_type' => 'code',
382
+ 'scope' => $scope,
383
+ 'state' => $this->config['state'],
384
+ ]
385
+ );
386
+
387
+ // If the list of scopes contains plus.login, add request_visible_actions
388
+ // to auth URL.
389
+ $rva = $this->config['request_visible_actions'];
390
+ if (strlen($rva) > 0 && false !== strpos($scope, 'plus.login')) {
391
+ $params['request_visible_actions'] = $rva;
392
+ }
393
+
394
+ $auth = $this->getOAuth2Service();
395
+
396
+ return (string) $auth->buildFullAuthorizationUri($params);
397
+ }
398
+
399
+ /**
400
+ * Adds auth listeners to the HTTP client based on the credentials
401
+ * set in the Google API Client object
402
+ *
403
+ * @param ClientInterface $http the http client object.
404
+ * @return ClientInterface the http client object
405
+ */
406
+ public function authorize(ClientInterface $http = null)
407
+ {
408
+ $credentials = null;
409
+ $token = null;
410
+ $scopes = null;
411
+ $http = $http ?: $this->getHttpClient();
412
+ $authHandler = $this->getAuthHandler();
413
+
414
+ // These conditionals represent the decision tree for authentication
415
+ // 1. Check for Application Default Credentials
416
+ // 2. Check for API Key
417
+ // 3a. Check for an Access Token
418
+ // 3b. If access token exists but is expired, try to refresh it
419
+ if ($this->isUsingApplicationDefaultCredentials()) {
420
+ $credentials = $this->createApplicationDefaultCredentials();
421
+ $http = $authHandler->attachCredentialsCache(
422
+ $http,
423
+ $credentials,
424
+ $this->config['token_callback']
425
+ );
426
+ } elseif ($token = $this->getAccessToken()) {
427
+ $scopes = $this->prepareScopes();
428
+ // add refresh subscriber to request a new token
429
+ if (isset($token['refresh_token']) && $this->isAccessTokenExpired()) {
430
+ $credentials = $this->createUserRefreshCredentials(
431
+ $scopes,
432
+ $token['refresh_token']
433
+ );
434
+ $http = $authHandler->attachCredentials(
435
+ $http,
436
+ $credentials,
437
+ $this->config['token_callback']
438
+ );
439
+ } else {
440
+ $http = $authHandler->attachToken($http, $token, (array) $scopes);
441
+ }
442
+ } elseif ($key = $this->config['developer_key']) {
443
+ $http = $authHandler->attachKey($http, $key);
444
+ }
445
+
446
+ return $http;
447
+ }
448
+
449
+ /**
450
+ * Set the configuration to use application default credentials for
451
+ * authentication
452
+ *
453
+ * @see https://developers.google.com/identity/protocols/application-default-credentials
454
+ * @param boolean $useAppCreds
455
+ */
456
+ public function useApplicationDefaultCredentials($useAppCreds = true)
457
+ {
458
+ $this->config['use_application_default_credentials'] = $useAppCreds;
459
+ }
460
+
461
+ /**
462
+ * To prevent useApplicationDefaultCredentials from inappropriately being
463
+ * called in a conditional
464
+ *
465
+ * @see https://developers.google.com/identity/protocols/application-default-credentials
466
+ */
467
+ public function isUsingApplicationDefaultCredentials()
468
+ {
469
+ return $this->config['use_application_default_credentials'];
470
+ }
471
+
472
+ /**
473
+ * Set the access token used for requests.
474
+ *
475
+ * Note that at the time requests are sent, tokens are cached. A token will be
476
+ * cached for each combination of service and authentication scopes. If a
477
+ * cache pool is not provided, creating a new instance of the client will
478
+ * allow modification of access tokens. If a persistent cache pool is
479
+ * provided, in order to change the access token, you must clear the cached
480
+ * token by calling `$client->getCache()->clear()`. (Use caution in this case,
481
+ * as calling `clear()` will remove all cache items, including any items not
482
+ * related to Google API PHP Client.)
483
+ *
484
+ * @param string|array $token
485
+ * @throws InvalidArgumentException
486
+ */
487
+ public function setAccessToken($token)
488
+ {
489
+ if (is_string($token)) {
490
+ if ($json = json_decode($token, true)) {
491
+ $token = $json;
492
+ } else {
493
+ // assume $token is just the token string
494
+ $token = array(
495
+ 'access_token' => $token,
496
+ );
497
+ }
498
+ }
499
+ if ($token == null) {
500
+ throw new InvalidArgumentException('invalid json token');
501
+ }
502
+ if (!isset($token['access_token'])) {
503
+ throw new InvalidArgumentException("Invalid token format");
504
+ }
505
+ $this->token = $token;
506
+ }
507
+
508
+ public function getAccessToken()
509
+ {
510
+ return $this->token;
511
+ }
512
+
513
+ /**
514
+ * @return string|null
515
+ */
516
+ public function getRefreshToken()
517
+ {
518
+ if (isset($this->token['refresh_token'])) {
519
+ return $this->token['refresh_token'];
520
+ }
521
+
522
+ return null;
523
+ }
524
+
525
+ /**
526
+ * Returns if the access_token is expired.
527
+ * @return bool Returns True if the access_token is expired.
528
+ */
529
+ public function isAccessTokenExpired()
530
+ {
531
+ if (!$this->token) {
532
+ return true;
533
+ }
534
+
535
+ $created = 0;
536
+ if (isset($this->token['created'])) {
537
+ $created = $this->token['created'];
538
+ } elseif (isset($this->token['id_token'])) {
539
+ // check the ID token for "iat"
540
+ // signature verification is not required here, as we are just
541
+ // using this for convenience to save a round trip request
542
+ // to the Google API server
543
+ $idToken = $this->token['id_token'];
544
+ if (substr_count($idToken, '.') == 2) {
545
+ $parts = explode('.', $idToken);
546
+ $payload = json_decode(base64_decode($parts[1]), true);
547
+ if ($payload && isset($payload['iat'])) {
548
+ $created = $payload['iat'];
549
+ }
550
+ }
551
+ }
552
+
553
+ // If the token is set to expire in the next 30 seconds.
554
+ return ($created + ($this->token['expires_in'] - 30)) < time();
555
+ }
556
+
557
+ /**
558
+ * @deprecated See UPGRADING.md for more information
559
+ */
560
+ public function getAuth()
561
+ {
562
+ throw new BadMethodCallException(
563
+ 'This function no longer exists. See UPGRADING.md for more information'
564
+ );
565
+ }
566
+
567
+ /**
568
+ * @deprecated See UPGRADING.md for more information
569
+ */
570
+ public function setAuth($auth)
571
+ {
572
+ throw new BadMethodCallException(
573
+ 'This function no longer exists. See UPGRADING.md for more information'
574
+ );
575
+ }
576
+
577
+ /**
578
+ * Set the OAuth 2.0 Client ID.
579
+ * @param string $clientId
580
+ */
581
+ public function setClientId($clientId)
582
+ {
583
+ $this->config['client_id'] = $clientId;
584
+ }
585
+
586
+ public function getClientId()
587
+ {
588
+ return $this->config['client_id'];
589
+ }
590
+
591
+ /**
592
+ * Set the OAuth 2.0 Client Secret.
593
+ * @param string $clientSecret
594
+ */
595
+ public function setClientSecret($clientSecret)
596
+ {
597
+ $this->config['client_secret'] = $clientSecret;
598
+ }
599
+
600
+ public function getClientSecret()
601
+ {
602
+ return $this->config['client_secret'];
603
+ }
604
+
605
+ /**
606
+ * Set the OAuth 2.0 Redirect URI.
607
+ * @param string $redirectUri
608
+ */
609
+ public function setRedirectUri($redirectUri)
610
+ {
611
+ $this->config['redirect_uri'] = $redirectUri;
612
+ }
613
+
614
+ public function getRedirectUri()
615
+ {
616
+ return $this->config['redirect_uri'];
617
+ }
618
+
619
+ /**
620
+ * Set OAuth 2.0 "state" parameter to achieve per-request customization.
621
+ * @see http://tools.ietf.org/html/draft-ietf-oauth-v2-22#section-3.1.2.2
622
+ * @param string $state
623
+ */
624
+ public function setState($state)
625
+ {
626
+ $this->config['state'] = $state;
627
+ }
628
+
629
+ /**
630
+ * @param string $accessType Possible values for access_type include:
631
+ * {@code "offline"} to request offline access from the user.
632
+ * {@code "online"} to request online access from the user.
633
+ */
634
+ public function setAccessType($accessType)
635
+ {
636
+ $this->config['access_type'] = $accessType;
637
+ }
638
+
639
+ /**
640
+ * @param string $approvalPrompt Possible values for approval_prompt include:
641
+ * {@code "force"} to force the approval UI to appear.
642
+ * {@code "auto"} to request auto-approval when possible. (This is the default value)
643
+ */
644
+ public function setApprovalPrompt($approvalPrompt)
645
+ {
646
+ $this->config['approval_prompt'] = $approvalPrompt;
647
+ }
648
+
649
+ /**
650
+ * Set the login hint, email address or sub id.
651
+ * @param string $loginHint
652
+ */
653
+ public function setLoginHint($loginHint)
654
+ {
655
+ $this->config['login_hint'] = $loginHint;
656
+ }
657
+
658
+ /**
659
+ * Set the application name, this is included in the User-Agent HTTP header.
660
+ * @param string $applicationName
661
+ */
662
+ public function setApplicationName($applicationName)
663
+ {
664
+ $this->config['application_name'] = $applicationName;
665
+ }
666
+
667
+ /**
668
+ * If 'plus.login' is included in the list of requested scopes, you can use
669
+ * this method to define types of app activities that your app will write.
670
+ * You can find a list of available types here:
671
+ * @link https://developers.google.com/+/api/moment-types
672
+ *
673
+ * @param array $requestVisibleActions Array of app activity types
674
+ */
675
+ public function setRequestVisibleActions($requestVisibleActions)
676
+ {
677
+ if (is_array($requestVisibleActions)) {
678
+ $requestVisibleActions = implode(" ", $requestVisibleActions);
679
+ }
680
+ $this->config['request_visible_actions'] = $requestVisibleActions;
681
+ }
682
+
683
+ /**
684
+ * Set the developer key to use, these are obtained through the API Console.
685
+ * @see http://code.google.com/apis/console-help/#generatingdevkeys
686
+ * @param string $developerKey
687
+ */
688
+ public function setDeveloperKey($developerKey)
689
+ {
690
+ $this->config['developer_key'] = $developerKey;
691
+ }
692
+
693
+ /**
694
+ * Set the hd (hosted domain) parameter streamlines the login process for
695
+ * Google Apps hosted accounts. By including the domain of the user, you
696
+ * restrict sign-in to accounts at that domain.
697
+ * @param $hd string - the domain to use.
698
+ */
699
+ public function setHostedDomain($hd)
700
+ {
701
+ $this->config['hd'] = $hd;
702
+ }
703
+
704
+ /**
705
+ * Set the prompt hint. Valid values are none, consent and select_account.
706
+ * If no value is specified and the user has not previously authorized
707
+ * access, then the user is shown a consent screen.
708
+ * @param $prompt string
709
+ * {@code "none"} Do not display any authentication or consent screens. Must not be specified with other values.
710
+ * {@code "consent"} Prompt the user for consent.
711
+ * {@code "select_account"} Prompt the user to select an account.
712
+ */
713
+ public function setPrompt($prompt)
714
+ {
715
+ $this->config['prompt'] = $prompt;
716
+ }
717
+
718
+ /**
719
+ * openid.realm is a parameter from the OpenID 2.0 protocol, not from OAuth
720
+ * 2.0. It is used in OpenID 2.0 requests to signify the URL-space for which
721
+ * an authentication request is valid.
722
+ * @param $realm string - the URL-space to use.
723
+ */
724
+ public function setOpenidRealm($realm)
725
+ {
726
+ $this->config['openid.realm'] = $realm;
727
+ }
728
+
729
+ /**
730
+ * If this is provided with the value true, and the authorization request is
731
+ * granted, the authorization will include any previous authorizations
732
+ * granted to this user/application combination for other scopes.
733
+ * @param $include boolean - the URL-space to use.
734
+ */
735
+ public function setIncludeGrantedScopes($include)
736
+ {
737
+ $this->config['include_granted_scopes'] = $include;
738
+ }
739
+
740
+ /**
741
+ * sets function to be called when an access token is fetched
742
+ * @param callable $tokenCallback - function ($cacheKey, $accessToken)
743
+ */
744
+ public function setTokenCallback(callable $tokenCallback)
745
+ {
746
+ $this->config['token_callback'] = $tokenCallback;
747
+ }
748
+
749
+ /**
750
+ * Revoke an OAuth2 access token or refresh token. This method will revoke the current access
751
+ * token, if a token isn't provided.
752
+ *
753
+ * @param string|array|null $token The token (access token or a refresh token) that should be revoked.
754
+ * @return boolean Returns True if the revocation was successful, otherwise False.
755
+ */
756
+ public function revokeToken($token = null)
757
+ {
758
+ $tokenRevoker = new Revoke($this->getHttpClient());
759
+
760
+ return $tokenRevoker->revokeToken($token ?: $this->getAccessToken());
761
+ }
762
+
763
+ /**
764
+ * Verify an id_token. This method will verify the current id_token, if one
765
+ * isn't provided.
766
+ *
767
+ * @throws LogicException If no token was provided and no token was set using `setAccessToken`.
768
+ * @throws UnexpectedValueException If the token is not a valid JWT.
769
+ * @param string|null $idToken The token (id_token) that should be verified.
770
+ * @return array|false Returns the token payload as an array if the verification was
771
+ * successful, false otherwise.
772
+ */
773
+ public function verifyIdToken($idToken = null)
774
+ {
775
+ $tokenVerifier = new Verify(
776
+ $this->getHttpClient(),
777
+ $this->getCache(),
778
+ $this->config['jwt']
779
+ );
780
+
781
+ if (null === $idToken) {
782
+ $token = $this->getAccessToken();
783
+ if (!isset($token['id_token'])) {
784
+ throw new LogicException(
785
+ 'id_token must be passed in or set as part of setAccessToken'
786
+ );
787
+ }
788
+ $idToken = $token['id_token'];
789
+ }
790
+
791
+ return $tokenVerifier->verifyIdToken(
792
+ $idToken,
793
+ $this->getClientId()
794
+ );
795
+ }
796
+
797
+ /**
798
+ * Set the scopes to be requested. Must be called before createAuthUrl().
799
+ * Will remove any previously configured scopes.
800
+ * @param string|array $scope_or_scopes, ie:
801
+ * array(
802
+ * 'https://www.googleapis.com/auth/plus.login',
803
+ * 'https://www.googleapis.com/auth/moderator'
804
+ * );
805
+ */
806
+ public function setScopes($scope_or_scopes)
807
+ {
808
+ $this->requestedScopes = array();
809
+ $this->addScope($scope_or_scopes);
810
+ }
811
+
812
+ /**
813
+ * This functions adds a scope to be requested as part of the OAuth2.0 flow.
814
+ * Will append any scopes not previously requested to the scope parameter.
815
+ * A single string will be treated as a scope to request. An array of strings
816
+ * will each be appended.
817
+ * @param $scope_or_scopes string|array e.g. "profile"
818
+ */
819
+ public function addScope($scope_or_scopes)
820
+ {
821
+ if (is_string($scope_or_scopes) && !in_array($scope_or_scopes, $this->requestedScopes)) {
822
+ $this->requestedScopes[] = $scope_or_scopes;
823
+ } else if (is_array($scope_or_scopes)) {
824
+ foreach ($scope_or_scopes as $scope) {
825
+ $this->addScope($scope);
826
+ }
827
+ }
828
+ }
829
+
830
+ /**
831
+ * Returns the list of scopes requested by the client
832
+ * @return array the list of scopes
833
+ *
834
+ */
835
+ public function getScopes()
836
+ {
837
+ return $this->requestedScopes;
838
+ }
839
+
840
+ /**
841
+ * @return string|null
842
+ * @visible For Testing
843
+ */
844
+ public function prepareScopes()
845
+ {
846
+ if (empty($this->requestedScopes)) {
847
+ return null;
848
+ }
849
+
850
+ return implode(' ', $this->requestedScopes);
851
+ }
852
+
853
+ /**
854
+ * Helper method to execute deferred HTTP requests.
855
+ *
856
+ * @param $request RequestInterface|\Google\Http\Batch
857
+ * @param string $expectedClass
858
+ * @throws \Google\Exception
859
+ * @return object of the type of the expected class or Psr\Http\Message\ResponseInterface.
860
+ */
861
+ public function execute(RequestInterface $request, $expectedClass = null)
862
+ {
863
+ $request = $request
864
+ ->withHeader(
865
+ 'User-Agent',
866
+ sprintf(
867
+ '%s %s%s',
868
+ $this->config['application_name'],
869
+ self::USER_AGENT_SUFFIX,
870
+ $this->getLibraryVersion()
871
+ )
872
+ )
873
+ ->withHeader(
874
+ 'x-goog-api-client',
875
+ sprintf(
876
+ 'gl-php/%s gdcl/%s',
877
+ phpversion(),
878
+ $this->getLibraryVersion()
879
+ )
880
+ );
881
+
882
+ if ($this->config['api_format_v2']) {
883
+ $request = $request->withHeader(
884
+ 'X-GOOG-API-FORMAT-VERSION',
885
+ 2
886
+ );
887
+ }
888
+
889
+ // call the authorize method
890
+ // this is where most of the grunt work is done
891
+ $http = $this->authorize();
892
+
893
+ return REST::execute(
894
+ $http,
895
+ $request,
896
+ $expectedClass,
897
+ $this->config['retry'],
898
+ $this->config['retry_map']
899
+ );
900
+ }
901
+
902
+ /**
903
+ * Declare whether batch calls should be used. This may increase throughput
904
+ * by making multiple requests in one connection.
905
+ *
906
+ * @param boolean $useBatch True if the batch support should
907
+ * be enabled. Defaults to False.
908
+ */
909
+ public function setUseBatch($useBatch)
910
+ {
911
+ // This is actually an alias for setDefer.
912
+ $this->setDefer($useBatch);
913
+ }
914
+
915
+ /**
916
+ * Are we running in Google AppEngine?
917
+ * return bool
918
+ */
919
+ public function isAppEngine()
920
+ {
921
+ return (isset($_SERVER['SERVER_SOFTWARE']) &&
922
+ strpos($_SERVER['SERVER_SOFTWARE'], 'Google App Engine') !== false);
923
+ }
924
+
925
+ public function setConfig($name, $value)
926
+ {
927
+ $this->config[$name] = $value;
928
+ }
929
+
930
+ public function getConfig($name, $default = null)
931
+ {
932
+ return isset($this->config[$name]) ? $this->config[$name] : $default;
933
+ }
934
+
935
+ /**
936
+ * For backwards compatibility
937
+ * alias for setAuthConfig
938
+ *
939
+ * @param string $file the configuration file
940
+ * @throws \Google\Exception
941
+ * @deprecated
942
+ */
943
+ public function setAuthConfigFile($file)
944
+ {
945
+ $this->setAuthConfig($file);
946
+ }
947
+
948
+ /**
949
+ * Set the auth config from new or deprecated JSON config.
950
+ * This structure should match the file downloaded from
951
+ * the "Download JSON" button on in the Google Developer
952
+ * Console.
953
+ * @param string|array $config the configuration json
954
+ * @throws \Google\Exception
955
+ */
956
+ public function setAuthConfig($config)
957
+ {
958
+ if (is_string($config)) {
959
+ if (!file_exists($config)) {
960
+ throw new InvalidArgumentException(sprintf('file "%s" does not exist', $config));
961
+ }
962
+
963
+ $json = file_get_contents($config);
964
+
965
+ if (!$config = json_decode($json, true)) {
966
+ throw new LogicException('invalid json for auth config');
967
+ }
968
+ }
969
+
970
+ $key = isset($config['installed']) ? 'installed' : 'web';
971
+ if (isset($config['type']) && $config['type'] == 'service_account') {
972
+ // application default credentials
973
+ $this->useApplicationDefaultCredentials();
974
+
975
+ // set the information from the config
976
+ $this->setClientId($config['client_id']);
977
+ $this->config['client_email'] = $config['client_email'];
978
+ $this->config['signing_key'] = $config['private_key'];
979
+ $this->config['signing_algorithm'] = 'HS256';
980
+ } elseif (isset($config[$key])) {
981
+ // old-style
982
+ $this->setClientId($config[$key]['client_id']);
983
+ $this->setClientSecret($config[$key]['client_secret']);
984
+ if (isset($config[$key]['redirect_uris'])) {
985
+ $this->setRedirectUri($config[$key]['redirect_uris'][0]);
986
+ }
987
+ } else {
988
+ // new-style
989
+ $this->setClientId($config['client_id']);
990
+ $this->setClientSecret($config['client_secret']);
991
+ if (isset($config['redirect_uris'])) {
992
+ $this->setRedirectUri($config['redirect_uris'][0]);
993
+ }
994
+ }
995
+ }
996
+
997
+ /**
998
+ * Use when the service account has been delegated domain wide access.
999
+ *
1000
+ * @param string $subject an email address account to impersonate
1001
+ */
1002
+ public function setSubject($subject)
1003
+ {
1004
+ $this->config['subject'] = $subject;
1005
+ }
1006
+
1007
+ /**
1008
+ * Declare whether making API calls should make the call immediately, or
1009
+ * return a request which can be called with ->execute();
1010
+ *
1011
+ * @param boolean $defer True if calls should not be executed right away.
1012
+ */
1013
+ public function setDefer($defer)
1014
+ {
1015
+ $this->deferExecution = $defer;
1016
+ }
1017
+
1018
+ /**
1019
+ * Whether or not to return raw requests
1020
+ * @return boolean
1021
+ */
1022
+ public function shouldDefer()
1023
+ {
1024
+ return $this->deferExecution;
1025
+ }
1026
+
1027
+ /**
1028
+ * @return OAuth2 implementation
1029
+ */
1030
+ public function getOAuth2Service()
1031
+ {
1032
+ if (!isset($this->auth)) {
1033
+ $this->auth = $this->createOAuth2Service();
1034
+ }
1035
+
1036
+ return $this->auth;
1037
+ }
1038
+
1039
+ /**
1040
+ * create a default google auth object
1041
+ */
1042
+ protected function createOAuth2Service()
1043
+ {
1044
+ $auth = new OAuth2(
1045
+ [
1046
+ 'clientId' => $this->getClientId(),
1047
+ 'clientSecret' => $this->getClientSecret(),
1048
+ 'authorizationUri' => self::OAUTH2_AUTH_URL,
1049
+ 'tokenCredentialUri' => self::OAUTH2_TOKEN_URI,
1050
+ 'redirectUri' => $this->getRedirectUri(),
1051
+ 'issuer' => $this->config['client_id'],
1052
+ 'signingKey' => $this->config['signing_key'],
1053
+ 'signingAlgorithm' => $this->config['signing_algorithm'],
1054
+ ]
1055
+ );
1056
+
1057
+ return $auth;
1058
+ }
1059
+
1060
+ /**
1061
+ * Set the Cache object
1062
+ * @param CacheItemPoolInterface $cache
1063
+ */
1064
+ public function setCache(CacheItemPoolInterface $cache)
1065
+ {
1066
+ $this->cache = $cache;
1067
+ }
1068
+
1069
+ /**
1070
+ * @return CacheItemPoolInterface
1071
+ */
1072
+ public function getCache()
1073
+ {
1074
+ if (!$this->cache) {
1075
+ $this->cache = $this->createDefaultCache();
1076
+ }
1077
+
1078
+ return $this->cache;
1079
+ }
1080
+
1081
+ /**
1082
+ * @param array $cacheConfig
1083
+ */
1084
+ public function setCacheConfig(array $cacheConfig)
1085
+ {
1086
+ $this->config['cache_config'] = $cacheConfig;
1087
+ }
1088
+
1089
+ /**
1090
+ * Set the Logger object
1091
+ * @param LoggerInterface $logger
1092
+ */
1093
+ public function setLogger(LoggerInterface $logger)
1094
+ {
1095
+ $this->logger = $logger;
1096
+ }
1097
+
1098
+ /**
1099
+ * @return LoggerInterface
1100
+ */
1101
+ public function getLogger()
1102
+ {
1103
+ if (!isset($this->logger)) {
1104
+ $this->logger = $this->createDefaultLogger();
1105
+ }
1106
+
1107
+ return $this->logger;
1108
+ }
1109
+
1110
+ protected function createDefaultLogger()
1111
+ {
1112
+ $logger = new Logger('google-api-php-client');
1113
+ if ($this->isAppEngine()) {
1114
+ $handler = new MonologSyslogHandler('app', LOG_USER, Logger::NOTICE);
1115
+ } else {
1116
+ $handler = new MonologStreamHandler('php://stderr', Logger::NOTICE);
1117
+ }
1118
+ $logger->pushHandler($handler);
1119
+
1120
+ return $logger;
1121
+ }
1122
+
1123
+ protected function createDefaultCache()
1124
+ {
1125
+ return new MemoryCacheItemPool;
1126
+ }
1127
+
1128
+ /**
1129
+ * Set the Http Client object
1130
+ * @param ClientInterface $http
1131
+ */
1132
+ public function setHttpClient(ClientInterface $http)
1133
+ {
1134
+ $this->http = $http;
1135
+ }
1136
+
1137
+ /**
1138
+ * @return ClientInterface
1139
+ */
1140
+ public function getHttpClient()
1141
+ {
1142
+ if (null === $this->http) {
1143
+ $this->http = $this->createDefaultHttpClient();
1144
+ }
1145
+
1146
+ return $this->http;
1147
+ }
1148
+
1149
+ /**
1150
+ * Set the API format version.
1151
+ *
1152
+ * `true` will use V2, which may return more useful error messages.
1153
+ *
1154
+ * @param bool $value
1155
+ */
1156
+ public function setApiFormatV2($value)
1157
+ {
1158
+ $this->config['api_format_v2'] = (bool) $value;
1159
+ }
1160
+
1161
+ protected function createDefaultHttpClient()
1162
+ {
1163
+ $guzzleVersion = null;
1164
+ if (defined('\GuzzleHttp\ClientInterface::MAJOR_VERSION')) {
1165
+ $guzzleVersion = ClientInterface::MAJOR_VERSION;
1166
+ } elseif (defined('\GuzzleHttp\ClientInterface::VERSION')) {
1167
+ $guzzleVersion = (int)substr(ClientInterface::VERSION, 0, 1);
1168
+ }
1169
+
1170
+ if (5 === $guzzleVersion) {
1171
+ $options = [
1172
+ 'base_url' => $this->config['base_path'],
1173
+ 'defaults' => ['exceptions' => false],
1174
+ ];
1175
+ if ($this->isAppEngine()) {
1176
+ // set StreamHandler on AppEngine by default
1177
+ $options['handler'] = new StreamHandler();
1178
+ $options['defaults']['verify'] = '/etc/ca-certificates.crt';
1179
+ }
1180
+ } elseif (6 === $guzzleVersion || 7 === $guzzleVersion) {
1181
+ // guzzle 6 or 7
1182
+ $options = [
1183
+ 'base_uri' => $this->config['base_path'],
1184
+ 'http_errors' => false,
1185
+ ];
1186
+ } else {
1187
+ throw new LogicException('Could not find supported version of Guzzle.');
1188
+ }
1189
+
1190
+ return new GuzzleClient($options);
1191
+ }
1192
+
1193
+ /**
1194
+ * @return FetchAuthTokenCache
1195
+ */
1196
+ private function createApplicationDefaultCredentials()
1197
+ {
1198
+ $scopes = $this->prepareScopes();
1199
+ $sub = $this->config['subject'];
1200
+ $signingKey = $this->config['signing_key'];
1201
+
1202
+ // create credentials using values supplied in setAuthConfig
1203
+ if ($signingKey) {
1204
+ $serviceAccountCredentials = array(
1205
+ 'client_id' => $this->config['client_id'],
1206
+ 'client_email' => $this->config['client_email'],
1207
+ 'private_key' => $signingKey,
1208
+ 'type' => 'service_account',
1209
+ 'quota_project_id' => $this->config['quota_project'],
1210
+ );
1211
+ $credentials = CredentialsLoader::makeCredentials(
1212
+ $scopes,
1213
+ $serviceAccountCredentials
1214
+ );
1215
+ } else {
1216
+ // When $sub is provided, we cannot pass cache classes to ::getCredentials
1217
+ // because FetchAuthTokenCache::setSub does not exist.
1218
+ // The result is when $sub is provided, calls to ::onGce are not cached.
1219
+ $credentials = ApplicationDefaultCredentials::getCredentials(
1220
+ $scopes,
1221
+ null,
1222
+ $sub ? null : $this->config['cache_config'],
1223
+ $sub ? null : $this->getCache(),
1224
+ $this->config['quota_project']
1225
+ );
1226
+ }
1227
+
1228
+ // for service account domain-wide authority (impersonating a user)
1229
+ // @see https://developers.google.com/identity/protocols/OAuth2ServiceAccount
1230
+ if ($sub) {
1231
+ if (!$credentials instanceof ServiceAccountCredentials) {
1232
+ throw new DomainException('domain-wide authority requires service account credentials');
1233
+ }
1234
+
1235
+ $credentials->setSub($sub);
1236
+ }
1237
+
1238
+ // If we are not using FetchAuthTokenCache yet, create it now
1239
+ if (!$credentials instanceof FetchAuthTokenCache) {
1240
+ $credentials = new FetchAuthTokenCache(
1241
+ $credentials,
1242
+ $this->config['cache_config'],
1243
+ $this->getCache()
1244
+ );
1245
+ }
1246
+ return $credentials;
1247
+ }
1248
+
1249
+ protected function getAuthHandler()
1250
+ {
1251
+ // Be very careful using the cache, as the underlying auth library's cache
1252
+ // implementation is naive, and the cache keys do not account for user
1253
+ // sessions.
1254
+ //
1255
+ // @see https://github.com/google/google-api-php-client/issues/821
1256
+ return AuthHandlerFactory::build(
1257
+ $this->getCache(),
1258
+ $this->config['cache_config']
1259
+ );
1260
+ }
1261
+
1262
+ private function createUserRefreshCredentials($scope, $refreshToken)
1263
+ {
1264
+ $creds = array_filter(
1265
+ array(
1266
+ 'client_id' => $this->getClientId(),
1267
+ 'client_secret' => $this->getClientSecret(),
1268
+ 'refresh_token' => $refreshToken,
1269
+ )
1270
+ );
1271
+
1272
+ return new UserRefreshCredentials($scope, $creds);
1273
+ }
1274
+ }
vendor/google/apiclient/src/Collection.php ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace Google;
4
+
5
+ /**
6
+ * Extension to the regular Google\Model that automatically
7
+ * exposes the items array for iteration, so you can just
8
+ * iterate over the object rather than a reference inside.
9
+ */
10
+ class Collection extends Model implements \Iterator, \Countable
11
+ {
12
+ protected $collection_key = 'items';
13
+
14
+ public function rewind()
15
+ {
16
+ if (isset($this->{$this->collection_key})
17
+ && is_array($this->{$this->collection_key})) {
18
+ reset($this->{$this->collection_key});
19
+ }
20
+ }
21
+
22
+ public function current()
23
+ {
24
+ $this->coerceType($this->key());
25
+ if (is_array($this->{$this->collection_key})) {
26
+ return current($this->{$this->collection_key});
27
+ }
28
+ }
29
+
30
+ public function key()
31
+ {
32
+ if (isset($this->{$this->collection_key})
33
+ && is_array($this->{$this->collection_key})) {
34
+ return key($this->{$this->collection_key});
35
+ }
36
+ }
37
+
38
+ public function next()
39
+ {
40
+ return next($this->{$this->collection_key});
41
+ }
42
+
43
+ public function valid()
44
+ {
45
+ $key = $this->key();
46
+ return $key !== null && $key !== false;
47
+ }
48
+
49
+ public function count()
50
+ {
51
+ if (!isset($this->{$this->collection_key})) {
52
+ return 0;
53
+ }
54
+ return count($this->{$this->collection_key});
55
+ }
56
+
57
+ public function offsetExists($offset)
58
+ {
59
+ if (!is_numeric($offset)) {
60
+ return parent::offsetExists($offset);
61
+ }
62
+ return isset($this->{$this->collection_key}[$offset]);
63
+ }
64
+
65
+ public function offsetGet($offset)
66
+ {
67
+ if (!is_numeric($offset)) {
68
+ return parent::offsetGet($offset);
69
+ }
70
+ $this->coerceType($offset);
71
+ return $this->{$this->collection_key}[$offset];
72
+ }
73
+
74
+ public function offsetSet($offset, $value)
75
+ {
76
+ if (!is_numeric($offset)) {
77
+ return parent::offsetSet($offset, $value);
78
+ }
79
+ $this->{$this->collection_key}[$offset] = $value;
80
+ }
81
+
82
+ public function offsetUnset($offset)
83
+ {
84
+ if (!is_numeric($offset)) {
85
+ return parent::offsetUnset($offset);
86
+ }
87
+ unset($this->{$this->collection_key}[$offset]);
88
+ }
89
+
90
+ private function coerceType($offset)
91
+ {
92
+ $keyType = $this->keyType($this->collection_key);
93
+ if ($keyType && !is_object($this->{$this->collection_key}[$offset])) {
94
+ $this->{$this->collection_key}[$offset] =
95
+ new $keyType($this->{$this->collection_key}[$offset]);
96
+ }
97
+ }
98
+ }
vendor/google/apiclient/src/Exception.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2013 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google;
19
+
20
+ use Exception as BaseException;
21
+
22
+ class Exception extends BaseException
23
+ {
24
+ }
vendor/google/apiclient/src/Http/Batch.php ADDED
@@ -0,0 +1,258 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2012 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Http;
19
+
20
+ use Google\Client;
21
+ use Google\Http\REST;
22
+ use Google\Service\Exception as GoogleServiceException;
23
+ use GuzzleHttp\Psr7;
24
+ use GuzzleHttp\Psr7\Request;
25
+ use GuzzleHttp\Psr7\Response;
26
+ use Psr\Http\Message\RequestInterface;
27
+ use Psr\Http\Message\ResponseInterface;
28
+
29
+ /**
30
+ * Class to handle batched requests to the Google API service.
31
+ *
32
+ * Note that calls to `Google\Http\Batch::execute()` do not clear the queued
33
+ * requests. To start a new batch, be sure to create a new instance of this
34
+ * class.
35
+ */
36
+ class Batch
37
+ {
38
+ const BATCH_PATH = 'batch';
39
+
40
+ private static $CONNECTION_ESTABLISHED_HEADERS = array(
41
+ "HTTP/1.0 200 Connection established\r\n\r\n",
42
+ "HTTP/1.1 200 Connection established\r\n\r\n",
43
+ );
44
+
45
+ /** @var string Multipart Boundary. */
46
+ private $boundary;
47
+
48
+ /** @var array service requests to be executed. */
49
+ private $requests = array();
50
+
51
+ /** @var Client */
52
+ private $client;
53
+
54
+ private $rootUrl;
55
+
56
+ private $batchPath;
57
+
58
+ public function __construct(
59
+ Client $client,
60
+ $boundary = false,
61
+ $rootUrl = null,
62
+ $batchPath = null
63
+ ) {
64
+ $this->client = $client;
65
+ $this->boundary = $boundary ?: mt_rand();
66
+ $this->rootUrl = rtrim($rootUrl ?: $this->client->getConfig('base_path'), '/');
67
+ $this->batchPath = $batchPath ?: self::BATCH_PATH;
68
+ }
69
+
70
+ public function add(RequestInterface $request, $key = false)
71
+ {
72
+ if (false == $key) {
73
+ $key = mt_rand();
74
+ }
75
+
76
+ $this->requests[$key] = $request;
77
+ }
78
+
79
+ public function execute()
80
+ {
81
+ $body = '';
82
+ $classes = array();
83
+ $batchHttpTemplate = <<<EOF
84
+ --%s
85
+ Content-Type: application/http
86
+ Content-Transfer-Encoding: binary
87
+ MIME-Version: 1.0
88
+ Content-ID: %s
89
+
90
+ %s
91
+ %s%s
92
+
93
+
94
+ EOF;
95
+
96
+ /** @var RequestInterface $req */
97
+ foreach ($this->requests as $key => $request) {
98
+ $firstLine = sprintf(
99
+ '%s %s HTTP/%s',
100
+ $request->getMethod(),
101
+ $request->getRequestTarget(),
102
+ $request->getProtocolVersion()
103
+ );
104
+
105
+ $content = (string) $request->getBody();
106
+
107
+ $headers = '';
108
+ foreach ($request->getHeaders() as $name => $values) {
109
+ $headers .= sprintf("%s:%s\r\n", $name, implode(', ', $values));
110
+ }
111
+
112
+ $body .= sprintf(
113
+ $batchHttpTemplate,
114
+ $this->boundary,
115
+ $key,
116
+ $firstLine,
117
+ $headers,
118
+ $content ? "\n".$content : ''
119
+ );
120
+
121
+ $classes['response-' . $key] = $request->getHeaderLine('X-Php-Expected-Class');
122
+ }
123
+
124
+ $body .= "--{$this->boundary}--";
125
+ $body = trim($body);
126
+ $url = $this->rootUrl . '/' . $this->batchPath;
127
+ $headers = array(
128
+ 'Content-Type' => sprintf('multipart/mixed; boundary=%s', $this->boundary),
129
+ 'Content-Length' => strlen($body),
130
+ );
131
+
132
+ $request = new Request(
133
+ 'POST',
134
+ $url,
135
+ $headers,
136
+ $body
137
+ );
138
+
139
+ $response = $this->client->execute($request);
140
+
141
+ return $this->parseResponse($response, $classes);
142
+ }
143
+
144
+ public function parseResponse(ResponseInterface $response, $classes = array())
145
+ {
146
+ $contentType = $response->getHeaderLine('content-type');
147
+ $contentType = explode(';', $contentType);
148
+ $boundary = false;
149
+ foreach ($contentType as $part) {
150
+ $part = explode('=', $part, 2);
151
+ if (isset($part[0]) && 'boundary' == trim($part[0])) {
152
+ $boundary = $part[1];
153
+ }
154
+ }
155
+
156
+ $body = (string) $response->getBody();
157
+ if (!empty($body)) {
158
+ $body = str_replace("--$boundary--", "--$boundary", $body);
159
+ $parts = explode("--$boundary", $body);
160
+ $responses = array();
161
+ $requests = array_values($this->requests);
162
+
163
+ foreach ($parts as $i => $part) {
164
+ $part = trim($part);
165
+ if (!empty($part)) {
166
+ list($rawHeaders, $part) = explode("\r\n\r\n", $part, 2);
167
+ $headers = $this->parseRawHeaders($rawHeaders);
168
+
169
+ $status = substr($part, 0, strpos($part, "\n"));
170
+ $status = explode(" ", $status);
171
+ $status = $status[1];
172
+
173
+ list($partHeaders, $partBody) = $this->parseHttpResponse($part, false);
174
+ $response = new Response(
175
+ $status,
176
+ $partHeaders,
177
+ Psr7\stream_for($partBody)
178
+ );
179
+
180
+ // Need content id.
181
+ $key = $headers['content-id'];
182
+
183
+ try {
184
+ $response = REST::decodeHttpResponse($response, $requests[$i-1]);
185
+ } catch (GoogleServiceException $e) {
186
+ // Store the exception as the response, so successful responses
187
+ // can be processed.
188
+ $response = $e;
189
+ }
190
+
191
+ $responses[$key] = $response;
192
+ }
193
+ }
194
+
195
+ return $responses;
196
+ }
197
+
198
+ return null;
199
+ }
200
+
201
+ private function parseRawHeaders($rawHeaders)
202
+ {
203
+ $headers = array();
204
+ $responseHeaderLines = explode("\r\n", $rawHeaders);
205
+ foreach ($responseHeaderLines as $headerLine) {
206
+ if ($headerLine && strpos($headerLine, ':') !== false) {
207
+ list($header, $value) = explode(': ', $headerLine, 2);
208
+ $header = strtolower($header);
209
+ if (isset($headers[$header])) {
210
+ $headers[$header] .= "\n" . $value;
211
+ } else {
212
+ $headers[$header] = $value;
213
+ }
214
+ }
215
+ }
216
+ return $headers;
217
+ }
218
+
219
+ /**
220
+ * Used by the IO lib and also the batch processing.
221
+ *
222
+ * @param $respData
223
+ * @param $headerSize
224
+ * @return array
225
+ */
226
+ private function parseHttpResponse($respData, $headerSize)
227
+ {
228
+ // check proxy header
229
+ foreach (self::$CONNECTION_ESTABLISHED_HEADERS as $established_header) {
230
+ if (stripos($respData, $established_header) !== false) {
231
+ // existed, remove it
232
+ $respData = str_ireplace($established_header, '', $respData);
233
+ // Subtract the proxy header size unless the cURL bug prior to 7.30.0
234
+ // is present which prevented the proxy header size from being taken into
235
+ // account.
236
+ // @TODO look into this
237
+ // if (!$this->needsQuirk()) {
238
+ // $headerSize -= strlen($established_header);
239
+ // }
240
+ break;
241
+ }
242
+ }
243
+
244
+ if ($headerSize) {
245
+ $responseBody = substr($respData, $headerSize);
246
+ $responseHeaders = substr($respData, 0, $headerSize);
247
+ } else {
248
+ $responseSegments = explode("\r\n\r\n", $respData, 2);
249
+ $responseHeaders = $responseSegments[0];
250
+ $responseBody = isset($responseSegments[1]) ? $responseSegments[1] :
251
+ null;
252
+ }
253
+
254
+ $responseHeaders = $this->parseRawHeaders($responseHeaders);
255
+
256
+ return array($responseHeaders, $responseBody);
257
+ }
258
+ }
vendor/google/apiclient/src/Http/MediaFileUpload.php ADDED
@@ -0,0 +1,358 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2012 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Http;
19
+
20
+ use Google\Client;
21
+ use Google\Http\REST;
22
+ use Google\Exception as GoogleException;
23
+ use GuzzleHttp\Psr7;
24
+ use GuzzleHttp\Psr7\Request;
25
+ use GuzzleHttp\Psr7\Uri;
26
+ use Psr\Http\Message\RequestInterface;
27
+
28
+ /**
29
+ * Manage large file uploads, which may be media but can be any type
30
+ * of sizable data.
31
+ */
32
+ class MediaFileUpload
33
+ {
34
+ const UPLOAD_MEDIA_TYPE = 'media';
35
+ const UPLOAD_MULTIPART_TYPE = 'multipart';
36
+ const UPLOAD_RESUMABLE_TYPE = 'resumable';
37
+
38
+ /** @var string $mimeType */
39
+ private $mimeType;
40
+
41
+ /** @var string $data */
42
+ private $data;
43
+
44
+ /** @var bool $resumable */
45
+ private $resumable;
46
+
47
+ /** @var int $chunkSize */
48
+ private $chunkSize;
49
+
50
+ /** @var int $size */
51
+ private $size;
52
+
53
+ /** @var string $resumeUri */
54
+ private $resumeUri;
55
+
56
+ /** @var int $progress */
57
+ private $progress;
58
+
59
+ /** @var Client */
60
+ private $client;
61
+
62
+ /** @var RequestInterface */
63
+ private $request;
64
+
65
+ /** @var string */
66
+ private $boundary;
67
+
68
+ /**
69
+ * Result code from last HTTP call
70
+ * @var int
71
+ */
72
+ private $httpResultCode;
73
+
74
+ /**
75
+ * @param Client $client
76
+ * @param RequestInterface $request
77
+ * @param string $mimeType
78
+ * @param string $data The bytes you want to upload.
79
+ * @param bool $resumable
80
+ * @param bool $chunkSize File will be uploaded in chunks of this many bytes.
81
+ * only used if resumable=True
82
+ */
83
+ public function __construct(
84
+ Client $client,
85
+ RequestInterface $request,
86
+ $mimeType,
87
+ $data,
88
+ $resumable = false,
89
+ $chunkSize = false
90
+ ) {
91
+ $this->client = $client;
92
+ $this->request = $request;
93
+ $this->mimeType = $mimeType;
94
+ $this->data = $data;
95
+ $this->resumable = $resumable;
96
+ $this->chunkSize = $chunkSize;
97
+ $this->progress = 0;
98
+
99
+ $this->process();
100
+ }
101
+
102
+ /**
103
+ * Set the size of the file that is being uploaded.
104
+ * @param $size - int file size in bytes
105
+ */
106
+ public function setFileSize($size)
107
+ {
108
+ $this->size = $size;
109
+ }
110
+
111
+ /**
112
+ * Return the progress on the upload
113
+ * @return int progress in bytes uploaded.
114
+ */
115
+ public function getProgress()
116
+ {
117
+ return $this->progress;
118
+ }
119
+
120
+ /**
121
+ * Send the next part of the file to upload.
122
+ * @param string|bool $chunk Optional. The next set of bytes to send. If false will
123
+ * use $data passed at construct time.
124
+ */
125
+ public function nextChunk($chunk = false)
126
+ {
127
+ $resumeUri = $this->getResumeUri();
128
+
129
+ if (false == $chunk) {
130
+ $chunk = substr($this->data, $this->progress, $this->chunkSize);
131
+ }
132
+
133
+ $lastBytePos = $this->progress + strlen($chunk) - 1;
134
+ $headers = array(
135
+ 'content-range' => "bytes $this->progress-$lastBytePos/$this->size",
136
+ 'content-length' => strlen($chunk),
137
+ 'expect' => '',
138
+ );
139
+
140
+ $request = new Request(
141
+ 'PUT',
142
+ $resumeUri,
143
+ $headers,
144
+ Psr7\stream_for($chunk)
145
+ );
146
+
147
+ return $this->makePutRequest($request);
148
+ }
149
+
150
+ /**
151
+ * Return the HTTP result code from the last call made.
152
+ * @return int code
153
+ */
154
+ public function getHttpResultCode()
155
+ {
156
+ return $this->httpResultCode;
157
+ }
158
+
159
+ /**
160
+ * Sends a PUT-Request to google drive and parses the response,
161
+ * setting the appropiate variables from the response()
162
+ *
163
+ * @param RequestInterface $request the Request which will be send
164
+ *
165
+ * @return false|mixed false when the upload is unfinished or the decoded http response
166
+ *
167
+ */
168
+ private function makePutRequest(RequestInterface $request)
169
+ {
170
+ $response = $this->client->execute($request);
171
+ $this->httpResultCode = $response->getStatusCode();
172
+
173
+ if (308 == $this->httpResultCode) {
174
+ // Track the amount uploaded.
175
+ $range = $response->getHeaderLine('range');
176
+ if ($range) {
177
+ $range_array = explode('-', $range);
178
+ $this->progress = $range_array[1] + 1;
179
+ }
180
+
181
+ // Allow for changing upload URLs.
182
+ $location = $response->getHeaderLine('location');
183
+ if ($location) {
184
+ $this->resumeUri = $location;
185
+ }
186
+
187
+ // No problems, but upload not complete.
188
+ return false;
189
+ }
190
+
191
+ return REST::decodeHttpResponse($response, $this->request);
192
+ }
193
+
194
+ /**
195
+ * Resume a previously unfinished upload
196
+ * @param $resumeUri the resume-URI of the unfinished, resumable upload.
197
+ */
198
+ public function resume($resumeUri)
199
+ {
200
+ $this->resumeUri = $resumeUri;
201
+ $headers = array(
202
+ 'content-range' => "bytes */$this->size",
203
+ 'content-length' => 0,
204
+ );
205
+ $httpRequest = new Request(
206
+ 'PUT',
207
+ $this->resumeUri,
208
+ $headers
209
+ );
210
+
211
+ return $this->makePutRequest($httpRequest);
212
+ }
213
+
214
+ /**
215
+ * @return RequestInterface
216
+ * @visible for testing
217
+ */
218
+ private function process()
219
+ {
220
+ $this->transformToUploadUrl();
221
+ $request = $this->request;
222
+
223
+ $postBody = '';
224
+ $contentType = false;
225
+
226
+ $meta = (string) $request->getBody();
227
+ $meta = is_string($meta) ? json_decode($meta, true) : $meta;
228
+
229
+ $uploadType = $this->getUploadType($meta);
230
+ $request = $request->withUri(
231
+ Uri::withQueryValue($request->getUri(), 'uploadType', $uploadType)
232
+ );
233
+
234
+ $mimeType = $this->mimeType ?: $request->getHeaderLine('content-type');
235
+
236
+ if (self::UPLOAD_RESUMABLE_TYPE == $uploadType) {
237
+ $contentType = $mimeType;
238
+ $postBody = is_string($meta) ? $meta : json_encode($meta);
239
+ } else if (self::UPLOAD_MEDIA_TYPE == $uploadType) {
240
+ $contentType = $mimeType;
241
+ $postBody = $this->data;
242
+ } else if (self::UPLOAD_MULTIPART_TYPE == $uploadType) {
243
+ // This is a multipart/related upload.
244
+ $boundary = $this->boundary ?: mt_rand();
245
+ $boundary = str_replace('"', '', $boundary);
246
+ $contentType = 'multipart/related; boundary=' . $boundary;
247
+ $related = "--$boundary\r\n";
248
+ $related .= "Content-Type: application/json; charset=UTF-8\r\n";
249
+ $related .= "\r\n" . json_encode($meta) . "\r\n";
250
+ $related .= "--$boundary\r\n";
251
+ $related .= "Content-Type: $mimeType\r\n";
252
+ $related .= "Content-Transfer-Encoding: base64\r\n";
253
+ $related .= "\r\n" . base64_encode($this->data) . "\r\n";
254
+ $related .= "--$boundary--";
255
+ $postBody = $related;
256
+ }
257
+
258
+ $request = $request->withBody(Psr7\stream_for($postBody));
259
+
260
+ if (isset($contentType) && $contentType) {
261
+ $request = $request->withHeader('content-type', $contentType);
262
+ }
263
+
264
+ return $this->request = $request;
265
+ }
266
+
267
+ /**
268
+ * Valid upload types:
269
+ * - resumable (UPLOAD_RESUMABLE_TYPE)
270
+ * - media (UPLOAD_MEDIA_TYPE)
271
+ * - multipart (UPLOAD_MULTIPART_TYPE)
272
+ * @param $meta
273
+ * @return string
274
+ * @visible for testing
275
+ */
276
+ public function getUploadType($meta)
277
+ {
278
+ if ($this->resumable) {
279
+ return self::UPLOAD_RESUMABLE_TYPE;
280
+ }
281
+
282
+ if (false == $meta && $this->data) {
283
+ return self::UPLOAD_MEDIA_TYPE;
284
+ }
285
+
286
+ return self::UPLOAD_MULTIPART_TYPE;
287
+ }
288
+
289
+ public function getResumeUri()
290
+ {
291
+ if (null === $this->resumeUri) {
292
+ $this->resumeUri = $this->fetchResumeUri();
293
+ }
294
+
295
+ return $this->resumeUri;
296
+ }
297
+
298
+ private function fetchResumeUri()
299
+ {
300
+ $body = $this->request->getBody();
301
+ if ($body) {
302
+ $headers = array(
303
+ 'content-type' => 'application/json; charset=UTF-8',
304
+ 'content-length' => $body->getSize(),
305
+ 'x-upload-content-type' => $this->mimeType,
306
+ 'x-upload-content-length' => $this->size,
307
+ 'expect' => '',
308
+ );
309
+ foreach ($headers as $key => $value) {
310
+ $this->request = $this->request->withHeader($key, $value);
311
+ }
312
+ }
313
+
314
+ $response = $this->client->execute($this->request, false);
315
+ $location = $response->getHeaderLine('location');
316
+ $code = $response->getStatusCode();
317
+
318
+ if (200 == $code && true == $location) {
319
+ return $location;
320
+ }
321
+
322
+ $message = $code;
323
+ $body = json_decode((string) $this->request->getBody(), true);
324
+ if (isset($body['error']['errors'])) {
325
+ $message .= ': ';
326
+ foreach ($body['error']['errors'] as $error) {
327
+ $message .= "{$error['domain']}, {$error['message']};";
328
+ }
329
+ $message = rtrim($message, ';');
330
+ }
331
+
332
+ $error = "Failed to start the resumable upload (HTTP {$message})";
333
+ $this->client->getLogger()->error($error);
334
+
335
+ throw new GoogleException($error);
336
+ }
337
+
338
+ private function transformToUploadUrl()
339
+ {
340
+ $parts = parse_url((string) $this->request->getUri());
341
+ if (!isset($parts['path'])) {
342
+ $parts['path'] = '';
343
+ }
344
+ $parts['path'] = '/upload' . $parts['path'];
345
+ $uri = Uri::fromParts($parts);
346
+ $this->request = $this->request->withUri($uri);
347
+ }
348
+
349
+ public function setChunkSize($chunkSize)
350
+ {
351
+ $this->chunkSize = $chunkSize;
352
+ }
353
+
354
+ public function getRequest()
355
+ {
356
+ return $this->request;
357
+ }
358
+ }
vendor/google/apiclient/src/Http/REST.php ADDED
@@ -0,0 +1,192 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2010 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Http;
19
+
20
+ use Google\Auth\HttpHandler\HttpHandlerFactory;
21
+ use Google\Client;
22
+ use Google\Task\Runner;
23
+ use Google\Service\Exception as GoogleServiceException;
24
+ use GuzzleHttp\ClientInterface;
25
+ use GuzzleHttp\Exception\RequestException;
26
+ use GuzzleHttp\Psr7\Response;
27
+ use Psr\Http\Message\RequestInterface;
28
+ use Psr\Http\Message\ResponseInterface;
29
+
30
+ /**
31
+ * This class implements the RESTful transport of apiServiceRequest()'s
32
+ */
33
+ class REST
34
+ {
35
+ /**
36
+ * Executes a Psr\Http\Message\RequestInterface and (if applicable) automatically retries
37
+ * when errors occur.
38
+ *
39
+ * @param Client $client
40
+ * @param RequestInterface $req
41
+ * @param string $expectedClass
42
+ * @param array $config
43
+ * @param array $retryMap
44
+ * @return array decoded result
45
+ * @throws \Google\Service\Exception on server side error (ie: not authenticated,
46
+ * invalid or malformed post body, invalid url)
47
+ */
48
+ public static function execute(
49
+ ClientInterface $client,
50
+ RequestInterface $request,
51
+ $expectedClass = null,
52
+ $config = array(),
53
+ $retryMap = null
54
+ ) {
55
+ $runner = new Runner(
56
+ $config,
57
+ sprintf('%s %s', $request->getMethod(), (string) $request->getUri()),
58
+ array(get_class(), 'doExecute'),
59
+ array($client, $request, $expectedClass)
60
+ );
61
+
62
+ if (null !== $retryMap) {
63
+ $runner->setRetryMap($retryMap);
64
+ }
65
+
66
+ return $runner->run();
67
+ }
68
+
69
+ /**
70
+ * Executes a Psr\Http\Message\RequestInterface
71
+ *
72
+ * @param Client $client
73
+ * @param RequestInterface $request
74
+ * @param string $expectedClass
75
+ * @return array decoded result
76
+ * @throws \Google\Service\Exception on server side error (ie: not authenticated,
77
+ * invalid or malformed post body, invalid url)
78
+ */
79
+ public static function doExecute(ClientInterface $client, RequestInterface $request, $expectedClass = null)
80
+ {
81
+ try {
82
+ $httpHandler = HttpHandlerFactory::build($client);
83
+ $response = $httpHandler($request);
84
+ } catch (RequestException $e) {
85
+ // if Guzzle throws an exception, catch it and handle the response
86
+ if (!$e->hasResponse()) {
87
+ throw $e;
88
+ }
89
+
90
+ $response = $e->getResponse();
91
+ // specific checking for Guzzle 5: convert to PSR7 response
92
+ if ($response instanceof \GuzzleHttp\Message\ResponseInterface) {
93
+ $response = new Response(
94
+ $response->getStatusCode(),
95
+ $response->getHeaders() ?: [],
96
+ $response->getBody(),
97
+ $response->getProtocolVersion(),
98
+ $response->getReasonPhrase()
99
+ );
100
+ }
101
+ }
102
+
103
+ return self::decodeHttpResponse($response, $request, $expectedClass);
104
+ }
105
+
106
+ /**
107
+ * Decode an HTTP Response.
108
+ * @static
109
+ * @throws \Google\Service\Exception
110
+ * @param RequestInterface $response The http response to be decoded.
111
+ * @param ResponseInterface $response
112
+ * @param string $expectedClass
113
+ * @return mixed|null
114
+ */
115
+ public static function decodeHttpResponse(
116
+ ResponseInterface $response,
117
+ RequestInterface $request = null,
118
+ $expectedClass = null
119
+ ) {
120
+ $code = $response->getStatusCode();
121
+
122
+ // retry strategy
123
+ if (intVal($code) >= 400) {
124
+ // if we errored out, it should be safe to grab the response body
125
+ $body = (string) $response->getBody();
126
+
127
+ // Check if we received errors, and add those to the Exception for convenience
128
+ throw new GoogleServiceException($body, $code, null, self::getResponseErrors($body));
129
+ }
130
+
131
+ // Ensure we only pull the entire body into memory if the request is not
132
+ // of media type
133
+ $body = self::decodeBody($response, $request);
134
+
135
+ if ($expectedClass = self::determineExpectedClass($expectedClass, $request)) {
136
+ $json = json_decode($body, true);
137
+
138
+ return new $expectedClass($json);
139
+ }
140
+
141
+ return $response;
142
+ }
143
+
144
+ private static function decodeBody(ResponseInterface $response, RequestInterface $request = null)
145
+ {
146
+ if (self::isAltMedia($request)) {
147
+ // don't decode the body, it's probably a really long string
148
+ return '';
149
+ }
150
+
151
+ return (string) $response->getBody();
152
+ }
153
+
154
+ private static function determineExpectedClass($expectedClass, RequestInterface $request = null)
155
+ {
156
+ // "false" is used to explicitly prevent an expected class from being returned
157
+ if (false === $expectedClass) {
158
+ return null;
159
+ }
160
+
161
+ // if we don't have a request, we just use what's passed in
162
+ if (null === $request) {
163
+ return $expectedClass;
164
+ }
165
+
166
+ // return what we have in the request header if one was not supplied
167
+ return $expectedClass ?: $request->getHeaderLine('X-Php-Expected-Class');
168
+ }
169
+
170
+ private static function getResponseErrors($body)
171
+ {
172
+ $json = json_decode($body, true);
173
+
174
+ if (isset($json['error']['errors'])) {
175
+ return $json['error']['errors'];
176
+ }
177
+
178
+ return null;
179
+ }
180
+
181
+ private static function isAltMedia(RequestInterface $request = null)
182
+ {
183
+ if ($request && $qs = $request->getUri()->getQuery()) {
184
+ parse_str($qs, $query);
185
+ if (isset($query['alt']) && $query['alt'] == 'media') {
186
+ return true;
187
+ }
188
+ }
189
+
190
+ return false;
191
+ }
192
+ }
vendor/google/apiclient/src/Model.php ADDED
@@ -0,0 +1,324 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2011 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google;
19
+
20
+ use Google\Exception as GoogleException;
21
+ use ReflectionObject;
22
+ use ReflectionProperty;
23
+ use stdClass;
24
+
25
+ /**
26
+ * This class defines attributes, valid values, and usage which is generated
27
+ * from a given json schema.
28
+ * http://tools.ietf.org/html/draft-zyp-json-schema-03#section-5
29
+ *
30
+ */
31
+ class Model implements \ArrayAccess
32
+ {
33
+ /**
34
+ * If you need to specify a NULL JSON value, use Google\Model::NULL_VALUE
35
+ * instead - it will be replaced when converting to JSON with a real null.
36
+ */
37
+ const NULL_VALUE = "{}gapi-php-null";
38
+ protected $internal_gapi_mappings = array();
39
+ protected $modelData = array();
40
+ protected $processed = array();
41
+
42
+ /**
43
+ * Polymorphic - accepts a variable number of arguments dependent
44
+ * on the type of the model subclass.
45
+ */
46
+ final public function __construct()
47
+ {
48
+ if (func_num_args() == 1 && is_array(func_get_arg(0))) {
49
+ // Initialize the model with the array's contents.
50
+ $array = func_get_arg(0);
51
+ $this->mapTypes($array);
52
+ }
53
+ $this->gapiInit();
54
+ }
55
+
56
+ /**
57
+ * Getter that handles passthrough access to the data array, and lazy object creation.
58
+ * @param string $key Property name.
59
+ * @return mixed The value if any, or null.
60
+ */
61
+ public function __get($key)
62
+ {
63
+ $keyType = $this->keyType($key);
64
+ $keyDataType = $this->dataType($key);
65
+ if ($keyType && !isset($this->processed[$key])) {
66
+ if (isset($this->modelData[$key])) {
67
+ $val = $this->modelData[$key];
68
+ } elseif ($keyDataType == 'array' || $keyDataType == 'map') {
69
+ $val = array();
70
+ } else {
71
+ $val = null;
72
+ }
73
+
74
+ if ($this->isAssociativeArray($val)) {
75
+ if ($keyDataType && 'map' == $keyDataType) {
76
+ foreach ($val as $arrayKey => $arrayItem) {
77
+ $this->modelData[$key][$arrayKey] =
78
+ new $keyType($arrayItem);
79
+ }
80
+ } else {
81
+ $this->modelData[$key] = new $keyType($val);
82
+ }
83
+ } else if (is_array($val)) {
84
+ $arrayObject = array();
85
+ foreach ($val as $arrayIndex => $arrayItem) {
86
+ $arrayObject[$arrayIndex] = new $keyType($arrayItem);
87
+ }
88
+ $this->modelData[$key] = $arrayObject;
89
+ }
90
+ $this->processed[$key] = true;
91
+ }
92
+
93
+ return isset($this->modelData[$key]) ? $this->modelData[$key] : null;
94
+ }
95
+
96
+ /**
97
+ * Initialize this object's properties from an array.
98
+ *
99
+ * @param array $array Used to seed this object's properties.
100
+ * @return void
101
+ */
102
+ protected function mapTypes($array)
103
+ {
104
+ // Hard initialise simple types, lazy load more complex ones.
105
+ foreach ($array as $key => $val) {
106
+ if ($keyType = $this->keyType($key)) {
107
+ $dataType = $this->dataType($key);
108
+ if ($dataType == 'array' || $dataType == 'map') {
109
+ $this->$key = array();
110
+ foreach ($val as $itemKey => $itemVal) {
111
+ if ($itemVal instanceof $keyType) {
112
+ $this->{$key}[$itemKey] = $itemVal;
113
+ } else {
114
+ $this->{$key}[$itemKey] = new $keyType($itemVal);
115
+ }
116
+ }
117
+ } elseif ($val instanceof $keyType) {
118
+ $this->$key = $val;
119
+ } else {
120
+ $this->$key = new $keyType($val);
121
+ }
122
+ unset($array[$key]);
123
+ } elseif (property_exists($this, $key)) {
124
+ $this->$key = $val;
125
+ unset($array[$key]);
126
+ } elseif (property_exists($this, $camelKey = $this->camelCase($key))) {
127
+ // This checks if property exists as camelCase, leaving it in array as snake_case
128
+ // in case of backwards compatibility issues.
129
+ $this->$camelKey = $val;
130
+ }
131
+ }
132
+ $this->modelData = $array;
133
+ }
134
+
135
+ /**
136
+ * Blank initialiser to be used in subclasses to do post-construction initialisation - this
137
+ * avoids the need for subclasses to have to implement the variadics handling in their
138
+ * constructors.
139
+ */
140
+ protected function gapiInit()
141
+ {
142
+ return;
143
+ }
144
+
145
+ /**
146
+ * Create a simplified object suitable for straightforward
147
+ * conversion to JSON. This is relatively expensive
148
+ * due to the usage of reflection, but shouldn't be called
149
+ * a whole lot, and is the most straightforward way to filter.
150
+ */
151
+ public function toSimpleObject()
152
+ {
153
+ $object = new stdClass();
154
+
155
+ // Process all other data.
156
+ foreach ($this->modelData as $key => $val) {
157
+ $result = $this->getSimpleValue($val);
158
+ if ($result !== null) {
159
+ $object->$key = $this->nullPlaceholderCheck($result);
160
+ }
161
+ }
162
+
163
+ // Process all public properties.
164
+ $reflect = new ReflectionObject($this);
165
+ $props = $reflect->getProperties(ReflectionProperty::IS_PUBLIC);
166
+ foreach ($props as $member) {
167
+ $name = $member->getName();
168
+ $result = $this->getSimpleValue($this->$name);
169
+ if ($result !== null) {
170
+ $name = $this->getMappedName($name);
171
+ $object->$name = $this->nullPlaceholderCheck($result);
172
+ }
173
+ }
174
+
175
+ return $object;
176
+ }
177
+
178
+ /**
179
+ * Handle different types of values, primarily
180
+ * other objects and map and array data types.
181
+ */
182
+ private function getSimpleValue($value)
183
+ {
184
+ if ($value instanceof Model) {
185
+ return $value->toSimpleObject();
186
+ } else if (is_array($value)) {
187
+ $return = array();
188
+ foreach ($value as $key => $a_value) {
189
+ $a_value = $this->getSimpleValue($a_value);
190
+ if ($a_value !== null) {
191
+ $key = $this->getMappedName($key);
192
+ $return[$key] = $this->nullPlaceholderCheck($a_value);
193
+ }
194
+ }
195
+ return $return;
196
+ }
197
+ return $value;
198
+ }
199
+
200
+ /**
201
+ * Check whether the value is the null placeholder and return true null.
202
+ */
203
+ private function nullPlaceholderCheck($value)
204
+ {
205
+ if ($value === self::NULL_VALUE) {
206
+ return null;
207
+ }
208
+ return $value;
209
+ }
210
+
211
+ /**
212
+ * If there is an internal name mapping, use that.
213
+ */
214
+ private function getMappedName($key)
215
+ {
216
+ if (isset($this->internal_gapi_mappings, $this->internal_gapi_mappings[$key])) {
217
+ $key = $this->internal_gapi_mappings[$key];
218
+ }
219
+ return $key;
220
+ }
221
+
222
+ /**
223
+ * Returns true only if the array is associative.
224
+ * @param array $array
225
+ * @return bool True if the array is associative.
226
+ */
227
+ protected function isAssociativeArray($array)
228
+ {
229
+ if (!is_array($array)) {
230
+ return false;
231
+ }
232
+ $keys = array_keys($array);
233
+ foreach ($keys as $key) {
234
+ if (is_string($key)) {
235
+ return true;
236
+ }
237
+ }
238
+ return false;
239
+ }
240
+
241
+ /**
242
+ * Verify if $obj is an array.
243
+ * @throws \Google\Exception Thrown if $obj isn't an array.
244
+ * @param array $obj Items that should be validated.
245
+ * @param string $method Method expecting an array as an argument.
246
+ */
247
+ public function assertIsArray($obj, $method)
248
+ {
249
+ if ($obj && !is_array($obj)) {
250
+ throw new GoogleException(
251
+ "Incorrect parameter type passed to $method(). Expected an array."
252
+ );
253
+ }
254
+ }
255
+
256
+ public function offsetExists($offset)
257
+ {
258
+ return isset($this->$offset) || isset($this->modelData[$offset]);
259
+ }
260
+
261
+ public function offsetGet($offset)
262
+ {
263
+ return isset($this->$offset) ?
264
+ $this->$offset :
265
+ $this->__get($offset);
266
+ }
267
+
268
+ public function offsetSet($offset, $value)
269
+ {
270
+ if (property_exists($this, $offset)) {
271
+ $this->$offset = $value;
272
+ } else {
273
+ $this->modelData[$offset] = $value;
274
+ $this->processed[$offset] = true;
275
+ }
276
+ }
277
+
278
+ public function offsetUnset($offset)
279
+ {
280
+ unset($this->modelData[$offset]);
281
+ }
282
+
283
+ protected function keyType($key)
284
+ {
285
+ $keyType = $key . "Type";
286
+
287
+ // ensure keyType is a valid class
288
+ if (property_exists($this, $keyType) && class_exists($this->$keyType)) {
289
+ return $this->$keyType;
290
+ }
291
+ }
292
+
293
+ protected function dataType($key)
294
+ {
295
+ $dataType = $key . "DataType";
296
+
297
+ if (property_exists($this, $dataType)) {
298
+ return $this->$dataType;
299
+ }
300
+ }
301
+
302
+ public function __isset($key)
303
+ {
304
+ return isset($this->modelData[$key]);
305
+ }
306
+
307
+ public function __unset($key)
308
+ {
309
+ unset($this->modelData[$key]);
310
+ }
311
+
312
+ /**
313
+ * Convert a string to camelCase
314
+ * @param string $value
315
+ * @return string
316
+ */
317
+ private function camelCase($value)
318
+ {
319
+ $value = ucwords(str_replace(array('-', '_'), ' ', $value));
320
+ $value = str_replace(' ', '', $value);
321
+ $value[0] = strtolower($value[0]);
322
+ return $value;
323
+ }
324
+ }
vendor/google/apiclient/src/Service.php ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2010 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google;
19
+
20
+ use Google\Http\Batch;
21
+ use TypeError;
22
+
23
+ class Service
24
+ {
25
+ public $batchPath;
26
+ public $rootUrl;
27
+ public $version;
28
+ public $servicePath;
29
+ public $availableScopes;
30
+ public $resource;
31
+ private $client;
32
+
33
+ public function __construct($clientOrConfig = [])
34
+ {
35
+ if ($clientOrConfig instanceof Client) {
36
+ $this->client = $clientOrConfig;
37
+ } elseif (is_array($clientOrConfig)) {
38
+ $this->client = new Client($clientOrConfig ?: []);
39
+ } else {
40
+ $errorMessage = 'constructor must be array or instance of Google\Client';
41
+ if (class_exists('TypeError')) {
42
+ throw new TypeError($errorMessage);
43
+ }
44
+ trigger_error($errorMessage, E_USER_ERROR);
45
+ }
46
+ }
47
+
48
+ /**
49
+ * Return the associated Google\Client class.
50
+ * @return \Google\Client
51
+ */
52
+ public function getClient()
53
+ {
54
+ return $this->client;
55
+ }
56
+
57
+ /**
58
+ * Create a new HTTP Batch handler for this service
59
+ *
60
+ * @return Batch
61
+ */
62
+ public function createBatch()
63
+ {
64
+ return new Batch(
65
+ $this->client,
66
+ false,
67
+ $this->rootUrl,
68
+ $this->batchPath
69
+ );
70
+ }
71
+ }
vendor/google/apiclient/src/Service/Exception.php ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Service;
19
+
20
+ use Google\Exception as GoogleException;
21
+
22
+ class Exception extends GoogleException
23
+ {
24
+ /**
25
+ * Optional list of errors returned in a JSON body of an HTTP error response.
26
+ */
27
+ protected $errors = array();
28
+
29
+ /**
30
+ * Override default constructor to add the ability to set $errors and a retry
31
+ * map.
32
+ *
33
+ * @param string $message
34
+ * @param int $code
35
+ * @param \Exception|null $previous
36
+ * @param [{string, string}] errors List of errors returned in an HTTP
37
+ * response. Defaults to [].
38
+ */
39
+ public function __construct(
40
+ $message,
41
+ $code = 0,
42
+ Exception $previous = null,
43
+ $errors = array()
44
+ ) {
45
+ if (version_compare(PHP_VERSION, '5.3.0') >= 0) {
46
+ parent::__construct($message, $code, $previous);
47
+ } else {
48
+ parent::__construct($message, $code);
49
+ }
50
+
51
+ $this->errors = $errors;
52
+ }
53
+
54
+ /**
55
+ * An example of the possible errors returned.
56
+ *
57
+ * {
58
+ * "domain": "global",
59
+ * "reason": "authError",
60
+ * "message": "Invalid Credentials",
61
+ * "locationType": "header",
62
+ * "location": "Authorization",
63
+ * }
64
+ *
65
+ * @return [{string, string}] List of errors return in an HTTP response or [].
66
+ */
67
+ public function getErrors()
68
+ {
69
+ return $this->errors;
70
+ }
71
+ }
vendor/google/apiclient/src/Service/Resource.php ADDED
@@ -0,0 +1,308 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2010 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Service;
19
+
20
+ use Google\Model;
21
+ use Google\Http\MediaFileUpload;
22
+ use Google\Exception as GoogleException;
23
+ use Google\Utils\UriTemplate;
24
+ use GuzzleHttp\Psr7\Request;
25
+
26
+ /**
27
+ * Implements the actual methods/resources of the discovered Google API using magic function
28
+ * calling overloading (__call()), which on call will see if the method name (plus.activities.list)
29
+ * is available in this service, and if so construct an apiHttpRequest representing it.
30
+ *
31
+ */
32
+ class Resource
33
+ {
34
+ // Valid query parameters that work, but don't appear in discovery.
35
+ private $stackParameters = array(
36
+ 'alt' => array('type' => 'string', 'location' => 'query'),
37
+ 'fields' => array('type' => 'string', 'location' => 'query'),
38
+ 'trace' => array('type' => 'string', 'location' => 'query'),
39
+ 'userIp' => array('type' => 'string', 'location' => 'query'),
40
+ 'quotaUser' => array('type' => 'string', 'location' => 'query'),
41
+ 'data' => array('type' => 'string', 'location' => 'body'),
42
+ 'mimeType' => array('type' => 'string', 'location' => 'header'),
43
+ 'uploadType' => array('type' => 'string', 'location' => 'query'),
44
+ 'mediaUpload' => array('type' => 'complex', 'location' => 'query'),
45
+ 'prettyPrint' => array('type' => 'string', 'location' => 'query'),
46
+ );
47
+
48
+ /** @var string $rootUrl */
49
+ private $rootUrl;
50
+
51
+ /** @var \Google\Client $client */
52
+ private $client;
53
+
54
+ /** @var string $serviceName */
55
+ private $serviceName;
56
+
57
+ /** @var string $servicePath */
58
+ private $servicePath;
59
+
60
+ /** @var string $resourceName */
61
+ private $resourceName;
62
+
63
+ /** @var array $methods */
64
+ private $methods;
65
+
66
+ public function __construct($service, $serviceName, $resourceName, $resource)
67
+ {
68
+ $this->rootUrl = $service->rootUrl;
69
+ $this->client = $service->getClient();
70
+ $this->servicePath = $service->servicePath;
71
+ $this->serviceName = $serviceName;
72
+ $this->resourceName = $resourceName;
73
+ $this->methods = is_array($resource) && isset($resource['methods']) ?
74
+ $resource['methods'] :
75
+ array($resourceName => $resource);
76
+ }
77
+
78
+ /**
79
+ * TODO: This function needs simplifying.
80
+ * @param $name
81
+ * @param $arguments
82
+ * @param $expectedClass - optional, the expected class name
83
+ * @return Request|$expectedClass
84
+ * @throws \Google\Exception
85
+ */
86
+ public function call($name, $arguments, $expectedClass = null)
87
+ {
88
+ if (! isset($this->methods[$name])) {
89
+ $this->client->getLogger()->error(
90
+ 'Service method unknown',
91
+ array(
92
+ 'service' => $this->serviceName,
93
+ 'resource' => $this->resourceName,
94
+ 'method' => $name
95
+ )
96
+ );
97
+
98
+ throw new GoogleException(
99
+ "Unknown function: " .
100
+ "{$this->serviceName}->{$this->resourceName}->{$name}()"
101
+ );
102
+ }
103
+ $method = $this->methods[$name];
104
+ $parameters = $arguments[0];
105
+
106
+ // postBody is a special case since it's not defined in the discovery
107
+ // document as parameter, but we abuse the param entry for storing it.
108
+ $postBody = null;
109
+ if (isset($parameters['postBody'])) {
110
+ if ($parameters['postBody'] instanceof Model) {
111
+ // In the cases the post body is an existing object, we want
112
+ // to use the smart method to create a simple object for
113
+ // for JSONification.
114
+ $parameters['postBody'] = $parameters['postBody']->toSimpleObject();
115
+ } else if (is_object($parameters['postBody'])) {
116
+ // If the post body is another kind of object, we will try and
117
+ // wrangle it into a sensible format.
118
+ $parameters['postBody'] =
119
+ $this->convertToArrayAndStripNulls($parameters['postBody']);
120
+ }
121
+ $postBody = (array) $parameters['postBody'];
122
+ unset($parameters['postBody']);
123
+ }
124
+
125
+ // TODO: optParams here probably should have been
126
+ // handled already - this may well be redundant code.
127
+ if (isset($parameters['optParams'])) {
128
+ $optParams = $parameters['optParams'];
129
+ unset($parameters['optParams']);
130
+ $parameters = array_merge($parameters, $optParams);
131
+ }
132
+
133
+ if (!isset($method['parameters'])) {
134
+ $method['parameters'] = array();
135
+ }
136
+
137
+ $method['parameters'] = array_merge(
138
+ $this->stackParameters,
139
+ $method['parameters']
140
+ );
141
+
142
+ foreach ($parameters as $key => $val) {
143
+ if ($key != 'postBody' && ! isset($method['parameters'][$key])) {
144
+ $this->client->getLogger()->error(
145
+ 'Service parameter unknown',
146
+ array(
147
+ 'service' => $this->serviceName,
148
+ 'resource' => $this->resourceName,
149
+ 'method' => $name,
150
+ 'parameter' => $key
151
+ )
152
+ );
153
+ throw new GoogleException("($name) unknown parameter: '$key'");
154
+ }
155
+ }
156
+
157
+ foreach ($method['parameters'] as $paramName => $paramSpec) {
158
+ if (isset($paramSpec['required']) &&
159
+ $paramSpec['required'] &&
160
+ ! isset($parameters[$paramName])
161
+ ) {
162
+ $this->client->getLogger()->error(
163
+ 'Service parameter missing',
164
+ array(
165
+ 'service' => $this->serviceName,
166
+ 'resource' => $this->resourceName,
167
+ 'method' => $name,
168
+ 'parameter' => $paramName
169
+ )
170
+ );
171
+ throw new GoogleException("($name) missing required param: '$paramName'");
172
+ }
173
+ if (isset($parameters[$paramName])) {
174
+ $value = $parameters[$paramName];
175
+ $parameters[$paramName] = $paramSpec;
176
+ $parameters[$paramName]['value'] = $value;
177
+ unset($parameters[$paramName]['required']);
178
+ } else {
179
+ // Ensure we don't pass nulls.
180
+ unset($parameters[$paramName]);
181
+ }
182
+ }
183
+
184
+ $this->client->getLogger()->info(
185
+ 'Service Call',
186
+ array(
187
+ 'service' => $this->serviceName,
188
+ 'resource' => $this->resourceName,
189
+ 'method' => $name,
190
+ 'arguments' => $parameters,
191
+ )
192
+ );
193
+
194
+ // build the service uri
195
+ $url = $this->createRequestUri(
196
+ $method['path'],
197
+ $parameters
198
+ );
199
+
200
+ // NOTE: because we're creating the request by hand,
201
+ // and because the service has a rootUrl property
202
+ // the "base_uri" of the Http Client is not accounted for
203
+ $request = new Request(
204
+ $method['httpMethod'],
205
+ $url,
206
+ ['content-type' => 'application/json'],
207
+ $postBody ? json_encode($postBody) : ''
208
+ );
209
+
210
+ // support uploads
211
+ if (isset($parameters['data'])) {
212
+ $mimeType = isset($parameters['mimeType'])
213
+ ? $parameters['mimeType']['value']
214
+ : 'application/octet-stream';
215
+ $data = $parameters['data']['value'];
216
+ $upload = new MediaFileUpload($this->client, $request, $mimeType, $data);
217
+
218
+ // pull down the modified request
219
+ $request = $upload->getRequest();
220
+ }
221
+
222
+ // if this is a media type, we will return the raw response
223
+ // rather than using an expected class
224
+ if (isset($parameters['alt']) && $parameters['alt']['value'] == 'media') {
225
+ $expectedClass = null;
226
+ }
227
+
228
+ // if the client is marked for deferring, rather than
229
+ // execute the request, return the response
230
+ if ($this->client->shouldDefer()) {
231
+ // @TODO find a better way to do this
232
+ $request = $request
233
+ ->withHeader('X-Php-Expected-Class', $expectedClass);
234
+
235
+ return $request;
236
+ }
237
+
238
+ return $this->client->execute($request, $expectedClass);
239
+ }
240
+
241
+ protected function convertToArrayAndStripNulls($o)
242
+ {
243
+ $o = (array) $o;
244
+ foreach ($o as $k => $v) {
245
+ if ($v === null) {
246
+ unset($o[$k]);
247
+ } elseif (is_object($v) || is_array($v)) {
248
+ $o[$k] = $this->convertToArrayAndStripNulls($o[$k]);
249
+ }
250
+ }
251
+ return $o;
252
+ }
253
+
254
+ /**
255
+ * Parse/expand request parameters and create a fully qualified
256
+ * request uri.
257
+ * @static
258
+ * @param string $restPath
259
+ * @param array $params
260
+ * @return string $requestUrl
261
+ */
262
+ public function createRequestUri($restPath, $params)
263
+ {
264
+ // Override the default servicePath address if the $restPath use a /
265
+ if ('/' == substr($restPath, 0, 1)) {
266
+ $requestUrl = substr($restPath, 1);
267
+ } else {
268
+ $requestUrl = $this->servicePath . $restPath;
269
+ }
270
+
271
+ // code for leading slash
272
+ if ($this->rootUrl) {
273
+ if ('/' !== substr($this->rootUrl, -1) && '/' !== substr($requestUrl, 0, 1)) {
274
+ $requestUrl = '/' . $requestUrl;
275
+ }
276
+ $requestUrl = $this->rootUrl . $requestUrl;
277
+ }
278
+ $uriTemplateVars = array();
279
+ $queryVars = array();
280
+ foreach ($params as $paramName => $paramSpec) {
281
+ if ($paramSpec['type'] == 'boolean') {
282
+ $paramSpec['value'] = $paramSpec['value'] ? 'true' : 'false';
283
+ }
284
+ if ($paramSpec['location'] == 'path') {
285
+ $uriTemplateVars[$paramName] = $paramSpec['value'];
286
+ } else if ($paramSpec['location'] == 'query') {
287
+ if (is_array($paramSpec['value'])) {
288
+ foreach ($paramSpec['value'] as $value) {
289
+ $queryVars[] = $paramName . '=' . rawurlencode(rawurldecode($value));
290
+ }
291
+ } else {
292
+ $queryVars[] = $paramName . '=' . rawurlencode(rawurldecode($paramSpec['value']));
293
+ }
294
+ }
295
+ }
296
+
297
+ if (count($uriTemplateVars)) {
298
+ $uriTemplateParser = new UriTemplate();
299
+ $requestUrl = $uriTemplateParser->parse($requestUrl, $uriTemplateVars);
300
+ }
301
+
302
+ if (count($queryVars)) {
303
+ $requestUrl .= '?' . implode('&', $queryVars);
304
+ }
305
+
306
+ return $requestUrl;
307
+ }
308
+ }
vendor/google/apiclient/src/Task/Composer.php ADDED
@@ -0,0 +1,115 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2020 Google LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
6
+ * use this file except in compliance with the License. You may obtain a copy of
7
+ * the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ * License for the specific language governing permissions and limitations under
15
+ * the License.
16
+ */
17
+
18
+ namespace Google\Task;
19
+
20
+ use Composer\Script\Event;
21
+ use Symfony\Component\Filesystem\Filesystem;
22
+ use Symfony\Component\Finder\Finder;
23
+ use InvalidArgumentException;
24
+
25
+ class Composer
26
+ {
27
+ /**
28
+ * @param Event $event Composer event passed in for any script method
29
+ * @param Filesystem $filesystem Optional. Used for testing.
30
+ */
31
+ public static function cleanup(
32
+ Event $event,
33
+ Filesystem $filesystem = null
34
+ ) {
35
+ $composer = $event->getComposer();
36
+ $extra = $composer->getPackage()->getExtra();
37
+ $servicesToKeep = isset($extra['google/apiclient-services']) ?
38
+ $extra['google/apiclient-services'] : [];
39
+ if ($servicesToKeep) {
40
+ $vendorDir = $composer->getConfig()->get('vendor-dir');
41
+ $serviceDir = sprintf(
42
+ '%s/google/apiclient-services/src/Google/Service',
43
+ $vendorDir
44
+ );
45
+ if (!is_dir($serviceDir)) {
46
+ // path for google/apiclient-services >= 0.200.0
47
+ $serviceDir = sprintf(
48
+ '%s/google/apiclient-services/src',
49
+ $vendorDir
50
+ );
51
+ }
52
+ self::verifyServicesToKeep($serviceDir, $servicesToKeep);
53
+ $finder = self::getServicesToRemove($serviceDir, $servicesToKeep);
54
+ $filesystem = $filesystem ?: new Filesystem();
55
+ if (0 !== $count = count($finder)) {
56
+ $event->getIO()->write(
57
+ sprintf(
58
+ 'Removing %s google services',
59
+ $count
60
+ )
61
+ );
62
+ foreach ($finder as $file) {
63
+ $realpath = $file->getRealPath();
64
+ $filesystem->remove($realpath);
65
+ $filesystem->remove($realpath . '.php');
66
+ }
67
+ }
68
+ }
69
+ }
70
+
71
+ /**
72
+ * @throws InvalidArgumentException when the service doesn't exist
73
+ */
74
+ private static function verifyServicesToKeep(
75
+ $serviceDir,
76
+ array $servicesToKeep
77
+ ) {
78
+ $finder = (new Finder())
79
+ ->directories()
80
+ ->depth('== 0');
81
+
82
+ foreach ($servicesToKeep as $service) {
83
+ if (!preg_match('/^[a-zA-Z0-9]*$/', $service)) {
84
+ throw new InvalidArgumentException(
85
+ sprintf(
86
+ 'Invalid Google service name "%s"',
87
+ $service
88
+ )
89
+ );
90
+ }
91
+ try {
92
+ $finder->in($serviceDir . '/' . $service);
93
+ } catch (InvalidArgumentException $e) {
94
+ throw new InvalidArgumentException(
95
+ sprintf(
96
+ 'Google service "%s" does not exist or was removed previously',
97
+ $service
98
+ )
99
+ );
100
+ }
101
+ }
102
+ }
103
+
104
+ private static function getServicesToRemove(
105
+ $serviceDir,
106
+ array $servicesToKeep
107
+ ) {
108
+ // find all files in the current directory
109
+ return (new Finder())
110
+ ->directories()
111
+ ->depth('== 0')
112
+ ->in($serviceDir)
113
+ ->exclude($servicesToKeep);
114
+ }
115
+ }
vendor/google/apiclient/src/Task/Exception.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Task;
19
+
20
+ use Google\Exception as GoogleException;
21
+
22
+ class Exception extends GoogleException
23
+ {
24
+ }
vendor/google/apiclient/src/Task/Retryable.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Task;
19
+
20
+ /**
21
+ * Interface for checking how many times a given task can be retried following
22
+ * a failure.
23
+ */
24
+ interface Retryable
25
+ {
26
+ }
vendor/google/apiclient/src/Task/Runner.php ADDED
@@ -0,0 +1,287 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Task;
19
+
20
+ use Google\Service\Exception as GoogleServiceException;
21
+ use Google\Task\Exception as GoogleTaskException;
22
+
23
+ /**
24
+ * A task runner with exponential backoff support.
25
+ *
26
+ * @see https://developers.google.com/drive/web/handle-errors#implementing_exponential_backoff
27
+ */
28
+ class Runner
29
+ {
30
+ const TASK_RETRY_NEVER = 0;
31
+ const TASK_RETRY_ONCE = 1;
32
+ const TASK_RETRY_ALWAYS = -1;
33
+
34
+ /**
35
+ * @var integer $maxDelay The max time (in seconds) to wait before a retry.
36
+ */
37
+ private $maxDelay = 60;
38
+ /**
39
+ * @var integer $delay The previous delay from which the next is calculated.
40
+ */
41
+ private $delay = 1;
42
+
43
+ /**
44
+ * @var integer $factor The base number for the exponential back off.
45
+ */
46
+ private $factor = 2;
47
+ /**
48
+ * @var float $jitter A random number between -$jitter and $jitter will be
49
+ * added to $factor on each iteration to allow for a better distribution of
50
+ * retries.
51
+ */
52
+ private $jitter = 0.5;
53
+
54
+ /**
55
+ * @var integer $attempts The number of attempts that have been tried so far.
56
+ */
57
+ private $attempts = 0;
58
+ /**
59
+ * @var integer $maxAttempts The max number of attempts allowed.
60
+ */
61
+ private $maxAttempts = 1;
62
+
63
+ /**
64
+ * @var callable $action The task to run and possibly retry.
65
+ */
66
+ private $action;
67
+ /**
68
+ * @var array $arguments The task arguments.
69
+ */
70
+ private $arguments;
71
+
72
+ /**
73
+ * @var array $retryMap Map of errors with retry counts.
74
+ */
75
+ protected $retryMap = [
76
+ '500' => self::TASK_RETRY_ALWAYS,
77
+ '503' => self::TASK_RETRY_ALWAYS,
78
+ 'rateLimitExceeded' => self::TASK_RETRY_ALWAYS,
79
+ 'userRateLimitExceeded' => self::TASK_RETRY_ALWAYS,
80
+ 6 => self::TASK_RETRY_ALWAYS, // CURLE_COULDNT_RESOLVE_HOST
81
+ 7 => self::TASK_RETRY_ALWAYS, // CURLE_COULDNT_CONNECT
82
+ 28 => self::TASK_RETRY_ALWAYS, // CURLE_OPERATION_TIMEOUTED
83
+ 35 => self::TASK_RETRY_ALWAYS, // CURLE_SSL_CONNECT_ERROR
84
+ 52 => self::TASK_RETRY_ALWAYS, // CURLE_GOT_NOTHING
85
+ 'lighthouseError' => self::TASK_RETRY_NEVER
86
+ ];
87
+
88
+ /**
89
+ * Creates a new task runner with exponential backoff support.
90
+ *
91
+ * @param array $config The task runner config
92
+ * @param string $name The name of the current task (used for logging)
93
+ * @param callable $action The task to run and possibly retry
94
+ * @param array $arguments The task arguments
95
+ * @throws \Google\Task\Exception when misconfigured
96
+ */
97
+ public function __construct(
98
+ $config,
99
+ $name,
100
+ $action,
101
+ array $arguments = array()
102
+ ) {
103
+ if (isset($config['initial_delay'])) {
104
+ if ($config['initial_delay'] < 0) {
105
+ throw new GoogleTaskException(
106
+ 'Task configuration `initial_delay` must not be negative.'
107
+ );
108
+ }
109
+
110
+ $this->delay = $config['initial_delay'];
111
+ }
112
+
113
+ if (isset($config['max_delay'])) {
114
+ if ($config['max_delay'] <= 0) {
115
+ throw new GoogleTaskException(
116
+ 'Task configuration `max_delay` must be greater than 0.'
117
+ );
118
+ }
119
+
120
+ $this->maxDelay = $config['max_delay'];
121
+ }
122
+
123
+ if (isset($config['factor'])) {
124
+ if ($config['factor'] <= 0) {
125
+ throw new GoogleTaskException(
126
+ 'Task configuration `factor` must be greater than 0.'
127
+ );
128
+ }
129
+
130
+ $this->factor = $config['factor'];
131
+ }
132
+
133
+ if (isset($config['jitter'])) {
134
+ if ($config['jitter'] <= 0) {
135
+ throw new GoogleTaskException(
136
+ 'Task configuration `jitter` must be greater than 0.'
137
+ );
138
+ }
139
+
140
+ $this->jitter = $config['jitter'];
141
+ }
142
+
143
+ if (isset($config['retries'])) {
144
+ if ($config['retries'] < 0) {
145
+ throw new GoogleTaskException(
146
+ 'Task configuration `retries` must not be negative.'
147
+ );
148
+ }
149
+ $this->maxAttempts += $config['retries'];
150
+ }
151
+
152
+ if (!is_callable($action)) {
153
+ throw new GoogleTaskException(
154
+ 'Task argument `$action` must be a valid callable.'
155
+ );
156
+ }
157
+
158
+ $this->action = $action;
159
+ $this->arguments = $arguments;
160
+ }
161
+
162
+ /**
163
+ * Checks if a retry can be attempted.
164
+ *
165
+ * @return boolean
166
+ */
167
+ public function canAttempt()
168
+ {
169
+ return $this->attempts < $this->maxAttempts;
170
+ }
171
+
172
+ /**
173
+ * Runs the task and (if applicable) automatically retries when errors occur.
174
+ *
175
+ * @return mixed
176
+ * @throws \Google\Service\Exception on failure when no retries are available.
177
+ */
178
+ public function run()
179
+ {
180
+ while ($this->attempt()) {
181
+ try {
182
+ return call_user_func_array($this->action, $this->arguments);
183
+ } catch (GoogleServiceException $exception) {
184
+ $allowedRetries = $this->allowedRetries(
185
+ $exception->getCode(),
186
+ $exception->getErrors()
187
+ );
188
+
189
+ if (!$this->canAttempt() || !$allowedRetries) {
190
+ throw $exception;
191
+ }
192
+
193
+ if ($allowedRetries > 0) {
194
+ $this->maxAttempts = min(
195
+ $this->maxAttempts,
196
+ $this->attempts + $allowedRetries
197
+ );
198
+ }
199
+ }
200
+ }
201
+ }
202
+
203
+ /**
204
+ * Runs a task once, if possible. This is useful for bypassing the `run()`
205
+ * loop.
206
+ *
207
+ * NOTE: If this is not the first attempt, this function will sleep in
208
+ * accordance to the backoff configurations before running the task.
209
+ *
210
+ * @return boolean
211
+ */
212
+ public function attempt()
213
+ {
214
+ if (!$this->canAttempt()) {
215
+ return false;
216
+ }
217
+
218
+ if ($this->attempts > 0) {
219
+ $this->backOff();
220
+ }
221
+
222
+ $this->attempts++;
223
+ return true;
224
+ }
225
+
226
+ /**
227
+ * Sleeps in accordance to the backoff configurations.
228
+ */
229
+ private function backOff()
230
+ {
231
+ $delay = $this->getDelay();
232
+
233
+ usleep($delay * 1000000);
234
+ }
235
+
236
+ /**
237
+ * Gets the delay (in seconds) for the current backoff period.
238
+ *
239
+ * @return float
240
+ */
241
+ private function getDelay()
242
+ {
243
+ $jitter = $this->getJitter();
244
+ $factor = $this->attempts > 1 ? $this->factor + $jitter : 1 + abs($jitter);
245
+
246
+ return $this->delay = min($this->maxDelay, $this->delay * $factor);
247
+ }
248
+
249
+ /**
250
+ * Gets the current jitter (random number between -$this->jitter and
251
+ * $this->jitter).
252
+ *
253
+ * @return float
254
+ */
255
+ private function getJitter()
256
+ {
257
+ return $this->jitter * 2 * mt_rand() / mt_getrandmax() - $this->jitter;
258
+ }
259
+
260
+ /**
261
+ * Gets the number of times the associated task can be retried.
262
+ *
263
+ * NOTE: -1 is returned if the task can be retried indefinitely
264
+ *
265
+ * @return integer
266
+ */
267
+ public function allowedRetries($code, $errors = array())
268
+ {
269
+ if (isset($this->retryMap[$code])) {
270
+ return $this->retryMap[$code];
271
+ }
272
+
273
+ if (
274
+ !empty($errors) &&
275
+ isset($errors[0]['reason'], $this->retryMap[$errors[0]['reason']])
276
+ ) {
277
+ return $this->retryMap[$errors[0]['reason']];
278
+ }
279
+
280
+ return 0;
281
+ }
282
+
283
+ public function setRetryMap($retryMap)
284
+ {
285
+ $this->retryMap = $retryMap;
286
+ }
287
+ }
vendor/google/apiclient/src/Utils/UriTemplate.php ADDED
@@ -0,0 +1,335 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2013 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Utils;
19
+
20
+ /**
21
+ * Implementation of levels 1-3 of the URI Template spec.
22
+ * @see http://tools.ietf.org/html/rfc6570
23
+ */
24
+ class UriTemplate
25
+ {
26
+ const TYPE_MAP = "1";
27
+ const TYPE_LIST = "2";
28
+ const TYPE_SCALAR = "4";
29
+
30
+ /**
31
+ * @var $operators array
32
+ * These are valid at the start of a template block to
33
+ * modify the way in which the variables inside are
34
+ * processed.
35
+ */
36
+ private $operators = array(
37
+ "+" => "reserved",
38
+ "/" => "segments",
39
+ "." => "dotprefix",
40
+ "#" => "fragment",
41
+ ";" => "semicolon",
42
+ "?" => "form",
43
+ "&" => "continuation"
44
+ );
45
+
46
+ /**
47
+ * @var reserved array
48
+ * These are the characters which should not be URL encoded in reserved
49
+ * strings.
50
+ */
51
+ private $reserved = array(
52
+ "=", ",", "!", "@", "|", ":", "/", "?", "#",
53
+ "[", "]",'$', "&", "'", "(", ")", "*", "+", ";"
54
+ );
55
+ private $reservedEncoded = array(
56
+ "%3D", "%2C", "%21", "%40", "%7C", "%3A", "%2F", "%3F",
57
+ "%23", "%5B", "%5D", "%24", "%26", "%27", "%28", "%29",
58
+ "%2A", "%2B", "%3B"
59
+ );
60
+
61
+ public function parse($string, array $parameters)
62
+ {
63
+ return $this->resolveNextSection($string, $parameters);
64
+ }
65
+
66
+ /**
67
+ * This function finds the first matching {...} block and
68
+ * executes the replacement. It then calls itself to find
69
+ * subsequent blocks, if any.
70
+ */
71
+ private function resolveNextSection($string, $parameters)
72
+ {
73
+ $start = strpos($string, "{");
74
+ if ($start === false) {
75
+ return $string;
76
+ }
77
+ $end = strpos($string, "}");
78
+ if ($end === false) {
79
+ return $string;
80
+ }
81
+ $string = $this->replace($string, $start, $end, $parameters);
82
+ return $this->resolveNextSection($string, $parameters);
83
+ }
84
+
85
+ private function replace($string, $start, $end, $parameters)
86
+ {
87
+ // We know a data block will have {} round it, so we can strip that.
88
+ $data = substr($string, $start + 1, $end - $start - 1);
89
+
90
+ // If the first character is one of the reserved operators, it effects
91
+ // the processing of the stream.
92
+ if (isset($this->operators[$data[0]])) {
93
+ $op = $this->operators[$data[0]];
94
+ $data = substr($data, 1);
95
+ $prefix = "";
96
+ $prefix_on_missing = false;
97
+
98
+ switch ($op) {
99
+ case "reserved":
100
+ // Reserved means certain characters should not be URL encoded
101
+ $data = $this->replaceVars($data, $parameters, ",", null, true);
102
+ break;
103
+ case "fragment":
104
+ // Comma separated with fragment prefix. Bare values only.
105
+ $prefix = "#";
106
+ $prefix_on_missing = true;
107
+ $data = $this->replaceVars($data, $parameters, ",", null, true);
108
+ break;
109
+ case "segments":
110
+ // Slash separated data. Bare values only.
111
+ $prefix = "/";
112
+ $data =$this->replaceVars($data, $parameters, "/");
113
+ break;
114
+ case "dotprefix":
115
+ // Dot separated data. Bare values only.
116
+ $prefix = ".";
117
+ $prefix_on_missing = true;
118
+ $data = $this->replaceVars($data, $parameters, ".");
119
+ break;
120
+ case "semicolon":
121
+ // Semicolon prefixed and separated. Uses the key name
122
+ $prefix = ";";
123
+ $data = $this->replaceVars($data, $parameters, ";", "=", false, true, false);
124
+ break;
125
+ case "form":
126
+ // Standard URL format. Uses the key name
127
+ $prefix = "?";
128
+ $data = $this->replaceVars($data, $parameters, "&", "=");
129
+ break;
130
+ case "continuation":
131
+ // Standard URL, but with leading ampersand. Uses key name.
132
+ $prefix = "&";
133
+ $data = $this->replaceVars($data, $parameters, "&", "=");
134
+ break;
135
+ }
136
+
137
+ // Add the initial prefix character if data is valid.
138
+ if ($data || ($data !== false && $prefix_on_missing)) {
139
+ $data = $prefix . $data;
140
+ }
141
+
142
+ } else {
143
+ // If no operator we replace with the defaults.
144
+ $data = $this->replaceVars($data, $parameters);
145
+ }
146
+ // This is chops out the {...} and replaces with the new section.
147
+ return substr($string, 0, $start) . $data . substr($string, $end + 1);
148
+ }
149
+
150
+ private function replaceVars(
151
+ $section,
152
+ $parameters,
153
+ $sep = ",",
154
+ $combine = null,
155
+ $reserved = false,
156
+ $tag_empty = false,
157
+ $combine_on_empty = true
158
+ ) {
159
+ if (strpos($section, ",") === false) {
160
+ // If we only have a single value, we can immediately process.
161
+ return $this->combine(
162
+ $section,
163
+ $parameters,
164
+ $sep,
165
+ $combine,
166
+ $reserved,
167
+ $tag_empty,
168
+ $combine_on_empty
169
+ );
170
+ } else {
171
+ // If we have multiple values, we need to split and loop over them.
172
+ // Each is treated individually, then glued together with the
173
+ // separator character.
174
+ $vars = explode(",", $section);
175
+ return $this->combineList(
176
+ $vars,
177
+ $sep,
178
+ $parameters,
179
+ $combine,
180
+ $reserved,
181
+ false, // Never emit empty strings in multi-param replacements
182
+ $combine_on_empty
183
+ );
184
+ }
185
+ }
186
+
187
+ public function combine(
188
+ $key,
189
+ $parameters,
190
+ $sep,
191
+ $combine,
192
+ $reserved,
193
+ $tag_empty,
194
+ $combine_on_empty
195
+ ) {
196
+ $length = false;
197
+ $explode = false;
198
+ $skip_final_combine = false;
199
+ $value = false;
200
+
201
+ // Check for length restriction.
202
+ if (strpos($key, ":") !== false) {
203
+ list($key, $length) = explode(":", $key);
204
+ }
205
+
206
+ // Check for explode parameter.
207
+ if ($key[strlen($key) - 1] == "*") {
208
+ $explode = true;
209
+ $key = substr($key, 0, -1);
210
+ $skip_final_combine = true;
211
+ }
212
+
213
+ // Define the list separator.
214
+ $list_sep = $explode ? $sep : ",";
215
+
216
+ if (isset($parameters[$key])) {
217
+ $data_type = $this->getDataType($parameters[$key]);
218
+ switch ($data_type) {
219
+ case self::TYPE_SCALAR:
220
+ $value = $this->getValue($parameters[$key], $length);
221
+ break;
222
+ case self::TYPE_LIST:
223
+ $values = array();
224
+ foreach ($parameters[$key] as $pkey => $pvalue) {
225
+ $pvalue = $this->getValue($pvalue, $length);
226
+ if ($combine && $explode) {
227
+ $values[$pkey] = $key . $combine . $pvalue;
228
+ } else {
229
+ $values[$pkey] = $pvalue;
230
+ }
231
+ }
232
+ $value = implode($list_sep, $values);
233
+ if ($value == '') {
234
+ return '';
235
+ }
236
+ break;
237
+ case self::TYPE_MAP:
238
+ $values = array();
239
+ foreach ($parameters[$key] as $pkey => $pvalue) {
240
+ $pvalue = $this->getValue($pvalue, $length);
241
+ if ($explode) {
242
+ $pkey = $this->getValue($pkey, $length);
243
+ $values[] = $pkey . "=" . $pvalue; // Explode triggers = combine.
244
+ } else {
245
+ $values[] = $pkey;
246
+ $values[] = $pvalue;
247
+ }
248
+ }
249
+ $value = implode($list_sep, $values);
250
+ if ($value == '') {
251
+ return false;
252
+ }
253
+ break;
254
+ }
255
+ } else if ($tag_empty) {
256
+ // If we are just indicating empty values with their key name, return that.
257
+ return $key;
258
+ } else {
259
+ // Otherwise we can skip this variable due to not being defined.
260
+ return false;
261
+ }
262
+
263
+ if ($reserved) {
264
+ $value = str_replace($this->reservedEncoded, $this->reserved, $value);
265
+ }
266
+
267
+ // If we do not need to include the key name, we just return the raw
268
+ // value.
269
+ if (!$combine || $skip_final_combine) {
270
+ return $value;
271
+ }
272
+
273
+ // Else we combine the key name: foo=bar, if value is not the empty string.
274
+ return $key . ($value != '' || $combine_on_empty ? $combine . $value : '');
275
+ }
276
+
277
+ /**
278
+ * Return the type of a passed in value
279
+ */
280
+ private function getDataType($data)
281
+ {
282
+ if (is_array($data)) {
283
+ reset($data);
284
+ if (key($data) !== 0) {
285
+ return self::TYPE_MAP;
286
+ }
287
+ return self::TYPE_LIST;
288
+ }
289
+ return self::TYPE_SCALAR;
290
+ }
291
+
292
+ /**
293
+ * Utility function that merges multiple combine calls
294
+ * for multi-key templates.
295
+ */
296
+ private function combineList(
297
+ $vars,
298
+ $sep,
299
+ $parameters,
300
+ $combine,
301
+ $reserved,
302
+ $tag_empty,
303
+ $combine_on_empty
304
+ ) {
305
+ $ret = array();
306
+ foreach ($vars as $var) {
307
+ $response = $this->combine(
308
+ $var,
309
+ $parameters,
310
+ $sep,
311
+ $combine,
312
+ $reserved,
313
+ $tag_empty,
314
+ $combine_on_empty
315
+ );
316
+ if ($response === false) {
317
+ continue;
318
+ }
319
+ $ret[] = $response;
320
+ }
321
+ return implode($sep, $ret);
322
+ }
323
+
324
+ /**
325
+ * Utility function to encode and trim values
326
+ */
327
+ private function getValue($value, $length)
328
+ {
329
+ if ($length) {
330
+ $value = substr($value, 0, $length);
331
+ }
332
+ $value = rawurlencode($value);
333
+ return $value;
334
+ }
335
+ }
vendor/google/apiclient/src/aliases.php ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ if (class_exists('Google_Client', false)) {
4
+ // Prevent error with preloading in PHP 7.4
5
+ // @see https://github.com/googleapis/google-api-php-client/issues/1976
6
+ return;
7
+ }
8
+
9
+ $classMap = [
10
+ 'Google\\Client' => 'Google_Client',
11
+ 'Google\\Service' => 'Google_Service',
12
+ 'Google\\AccessToken\\Revoke' => 'Google_AccessToken_Revoke',
13
+ 'Google\\AccessToken\\Verify' => 'Google_AccessToken_Verify',
14
+ 'Google\\Model' => 'Google_Model',
15
+ 'Google\\Utils\\UriTemplate' => 'Google_Utils_UriTemplate',
16
+ 'Google\\AuthHandler\\Guzzle6AuthHandler' => 'Google_AuthHandler_Guzzle6AuthHandler',
17
+ 'Google\\AuthHandler\\Guzzle7AuthHandler' => 'Google_AuthHandler_Guzzle7AuthHandler',
18
+ 'Google\\AuthHandler\\Guzzle5AuthHandler' => 'Google_AuthHandler_Guzzle5AuthHandler',
19
+ 'Google\\AuthHandler\\AuthHandlerFactory' => 'Google_AuthHandler_AuthHandlerFactory',
20
+ 'Google\\Http\\Batch' => 'Google_Http_Batch',
21
+ 'Google\\Http\\MediaFileUpload' => 'Google_Http_MediaFileUpload',
22
+ 'Google\\Http\\REST' => 'Google_Http_REST',
23
+ 'Google\\Task\\Retryable' => 'Google_Task_Retryable',
24
+ 'Google\\Task\\Exception' => 'Google_Task_Exception',
25
+ 'Google\\Task\\Runner' => 'Google_Task_Runner',
26
+ 'Google\\Collection' => 'Google_Collection',
27
+ 'Google\\Service\\Exception' => 'Google_Service_Exception',
28
+ 'Google\\Service\\Resource' => 'Google_Service_Resource',
29
+ 'Google\\Exception' => 'Google_Exception',
30
+ ];
31
+
32
+ foreach ($classMap as $class => $alias) {
33
+ class_alias($class, $alias);
34
+ }
35
+
36
+ /**
37
+ * This class needs to be defined explicitly as scripts must be recognized by
38
+ * the autoloader.
39
+ */
40
+ class Google_Task_Composer extends \Google\Task\Composer
41
+ {
42
+ }
43
+
44
+ if (\false) {
45
+ class Google_AccessToken_Revoke extends \Google\AccessToken\Revoke {}
46
+ class Google_AccessToken_Verify extends \Google\AccessToken\Verify {}
47
+ class Google_AuthHandler_AuthHandlerFactory extends \Google\AuthHandler\AuthHandlerFactory {}
48
+ class Google_AuthHandler_Guzzle5AuthHandler extends \Google\AuthHandler\Guzzle5AuthHandler {}
49
+ class Google_AuthHandler_Guzzle6AuthHandler extends \Google\AuthHandler\Guzzle6AuthHandler {}
50
+ class Google_AuthHandler_Guzzle7AuthHandler extends \Google\AuthHandler\Guzzle7AuthHandler {}
51
+ class Google_Client extends \Google\Client {}
52
+ class Google_Collection extends \Google\Collection {}
53
+ class Google_Exception extends \Google\Exception {}
54
+ class Google_Http_Batch extends \Google\Http\Batch {}
55
+ class Google_Http_MediaFileUpload extends \Google\Http\MediaFileUpload {}
56
+ class Google_Http_REST extends \Google\Http\REST {}
57
+ class Google_Model extends \Google\Model {}
58
+ class Google_Service extends \Google\Service {}
59
+ class Google_Service_Exception extends \Google\Service\Exception {}
60
+ class Google_Service_Resource extends \Google\Service\Resource {}
61
+ class Google_Task_Exception extends \Google\Task\Exception {}
62
+ interface Google_Task_Retryable extends \Google\Task\Retryable {}
63
+ class Google_Task_Runner extends \Google\Task\Runner {}
64
+ class Google_Utils_UriTemplate extends \Google\Utils\UriTemplate {}
65
+ }
vendor/google/auth/COPYING ADDED
@@ -0,0 +1,202 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
5
+
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding those notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
176
+
177
+ END OF TERMS AND CONDITIONS
178
+
179
+ APPENDIX: How to apply the Apache License to your work.
180
+
181
+ To apply the Apache License to your work, attach the following
182
+ boilerplate notice, with the fields enclosed by brackets "[]"
183
+ replaced with your own identifying information. (Don't include
184
+ the brackets!) The text should be enclosed in the appropriate
185
+ comment syntax for the file format. We also recommend that a
186
+ file or class name and description of purpose be included on the
187
+ same "printed page" as the copyright notice for easier
188
+ identification within third-party archives.
189
+
190
+ Copyright 2015 Google Inc.
191
+
192
+ Licensed under the Apache License, Version 2.0 (the "License");
193
+ you may not use this file except in compliance with the License.
194
+ You may obtain a copy of the License at
195
+
196
+ http://www.apache.org/licenses/LICENSE-2.0
197
+
198
+ Unless required by applicable law or agreed to in writing, software
199
+ distributed under the License is distributed on an "AS IS" BASIS,
200
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
+ See the License for the specific language governing permissions and
202
+ limitations under the License.
vendor/google/auth/LICENSE ADDED
@@ -0,0 +1,203 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright [yyyy] [name of copyright owner]
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
202
+
203
+
vendor/google/auth/autoload.php ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2014 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ function oauth2client_php_autoload($className)
19
+ {
20
+ $classPath = explode('_', $className);
21
+ if ($classPath[0] != 'Google') {
22
+ return;
23
+ }
24
+ if (count($classPath) > 3) {
25
+ // Maximum class file path depth in this project is 3.
26
+ $classPath = array_slice($classPath, 0, 3);
27
+ }
28
+ $filePath = dirname(__FILE__) . '/src/' . implode('/', $classPath) . '.php';
29
+ if (file_exists($filePath)) {
30
+ require_once $filePath;
31
+ }
32
+ }
33
+
34
+ spl_autoload_register('oauth2client_php_autoload');
vendor/google/auth/renovate.json ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ {
2
+ "extends": [
3
+ "config:base",
4
+ ":preserveSemverRanges"
5
+ ]
6
+ }
vendor/google/auth/src/AccessToken.php ADDED
@@ -0,0 +1,479 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2019 Google LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth;
19
+
20
+ use DateTime;
21
+ use Exception;
22
+ use Firebase\JWT\ExpiredException;
23
+ use Firebase\JWT\JWT;
24
+ use Firebase\JWT\SignatureInvalidException;
25
+ use Google\Auth\Cache\MemoryCacheItemPool;
26
+ use Google\Auth\HttpHandler\HttpClientCache;
27
+ use Google\Auth\HttpHandler\HttpHandlerFactory;
28
+ use GuzzleHttp\Psr7;
29
+ use GuzzleHttp\Psr7\Request;
30
+ use InvalidArgumentException;
31
+ use phpseclib\Crypt\RSA;
32
+ use phpseclib\Math\BigInteger;
33
+ use Psr\Cache\CacheItemPoolInterface;
34
+ use RuntimeException;
35
+ use SimpleJWT\InvalidTokenException;
36
+ use SimpleJWT\JWT as SimpleJWT;
37
+ use SimpleJWT\Keys\KeyFactory;
38
+ use SimpleJWT\Keys\KeySet;
39
+ use UnexpectedValueException;
40
+
41
+ /**
42
+ * Wrapper around Google Access Tokens which provides convenience functions.
43
+ *
44
+ * @experimental
45
+ */
46
+ class AccessToken
47
+ {
48
+ const FEDERATED_SIGNON_CERT_URL = 'https://www.googleapis.com/oauth2/v3/certs';
49
+ const IAP_CERT_URL = 'https://www.gstatic.com/iap/verify/public_key-jwk';
50
+ const IAP_ISSUER = 'https://cloud.google.com/iap';
51
+ const OAUTH2_ISSUER = 'accounts.google.com';
52
+ const OAUTH2_ISSUER_HTTPS = 'https://accounts.google.com';
53
+ const OAUTH2_REVOKE_URI = 'https://oauth2.googleapis.com/revoke';
54
+
55
+ /**
56
+ * @var callable
57
+ */
58
+ private $httpHandler;
59
+
60
+ /**
61
+ * @var CacheItemPoolInterface
62
+ */
63
+ private $cache;
64
+
65
+ /**
66
+ * @param callable $httpHandler [optional] An HTTP Handler to deliver PSR-7 requests.
67
+ * @param CacheItemPoolInterface $cache [optional] A PSR-6 compatible cache implementation.
68
+ */
69
+ public function __construct(
70
+ callable $httpHandler = null,
71
+ CacheItemPoolInterface $cache = null
72
+ ) {
73
+ $this->httpHandler = $httpHandler
74
+ ?: HttpHandlerFactory::build(HttpClientCache::getHttpClient());
75
+ $this->cache = $cache ?: new MemoryCacheItemPool();
76
+ }
77
+
78
+ /**
79
+ * Verifies an id token and returns the authenticated apiLoginTicket.
80
+ * Throws an exception if the id token is not valid.
81
+ * The audience parameter can be used to control which id tokens are
82
+ * accepted. By default, the id token must have been issued to this OAuth2 client.
83
+ *
84
+ * @param string $token The JSON Web Token to be verified.
85
+ * @param array $options [optional] Configuration options.
86
+ * @param string $options.audience The indended recipient of the token.
87
+ * @param string $options.issuer The intended issuer of the token.
88
+ * @param string $options.cacheKey The cache key of the cached certs. Defaults to
89
+ * the sha1 of $certsLocation if provided, otherwise is set to
90
+ * "federated_signon_certs_v3".
91
+ * @param string $options.certsLocation The location (remote or local) from which
92
+ * to retrieve certificates, if not cached. This value should only be
93
+ * provided in limited circumstances in which you are sure of the
94
+ * behavior.
95
+ * @param bool $options.throwException Whether the function should throw an
96
+ * exception if the verification fails. This is useful for
97
+ * determining the reason verification failed.
98
+ * @return array|bool the token payload, if successful, or false if not.
99
+ * @throws InvalidArgumentException If certs could not be retrieved from a local file.
100
+ * @throws InvalidArgumentException If received certs are in an invalid format.
101
+ * @throws InvalidArgumentException If the cert alg is not supported.
102
+ * @throws RuntimeException If certs could not be retrieved from a remote location.
103
+ * @throws UnexpectedValueException If the token issuer does not match.
104
+ * @throws UnexpectedValueException If the token audience does not match.
105
+ */
106
+ public function verify($token, array $options = [])
107
+ {
108
+ $audience = isset($options['audience'])
109
+ ? $options['audience']
110
+ : null;
111
+ $issuer = isset($options['issuer'])
112
+ ? $options['issuer']
113
+ : null;
114
+ $certsLocation = isset($options['certsLocation'])
115
+ ? $options['certsLocation']
116
+ : self::FEDERATED_SIGNON_CERT_URL;
117
+ $cacheKey = isset($options['cacheKey'])
118
+ ? $options['cacheKey']
119
+ : $this->getCacheKeyFromCertLocation($certsLocation);
120
+ $throwException = isset($options['throwException'])
121
+ ? $options['throwException']
122
+ : false; // for backwards compatibility
123
+
124
+ // Check signature against each available cert.
125
+ $certs = $this->getCerts($certsLocation, $cacheKey, $options);
126
+ $alg = $this->determineAlg($certs);
127
+ if (!in_array($alg, ['RS256', 'ES256'])) {
128
+ throw new InvalidArgumentException(
129
+ 'unrecognized "alg" in certs, expected ES256 or RS256'
130
+ );
131
+ }
132
+ try {
133
+ if ($alg == 'RS256') {
134
+ return $this->verifyRs256($token, $certs, $audience, $issuer);
135
+ }
136
+ return $this->verifyEs256($token, $certs, $audience, $issuer);
137
+ } catch (ExpiredException $e) { // firebase/php-jwt 3+
138
+ } catch (\ExpiredException $e) { // firebase/php-jwt 2
139
+ } catch (SignatureInvalidException $e) { // firebase/php-jwt 3+
140
+ } catch (\SignatureInvalidException $e) { // firebase/php-jwt 2
141
+ } catch (InvalidTokenException $e) { // simplejwt
142
+ } catch (DomainException $e) {
143
+ } catch (InvalidArgumentException $e) {
144
+ } catch (UnexpectedValueException $e) {
145
+ }
146
+
147
+ if ($throwException) {
148
+ throw $e;
149
+ }
150
+
151
+ return false;
152
+ }
153
+
154
+ /**
155
+ * Identifies the expected algorithm to verify by looking at the "alg" key
156
+ * of the provided certs.
157
+ *
158
+ * @param array $certs Certificate array according to the JWK spec (see
159
+ * https://tools.ietf.org/html/rfc7517).
160
+ * @return string The expected algorithm, such as "ES256" or "RS256".
161
+ */
162
+ private function determineAlg(array $certs)
163
+ {
164
+ $alg = null;
165
+ foreach ($certs as $cert) {
166
+ if (empty($cert['alg'])) {
167
+ throw new InvalidArgumentException(
168
+ 'certs expects "alg" to be set'
169
+ );
170
+ }
171
+ $alg = $alg ?: $cert['alg'];
172
+
173
+ if ($alg != $cert['alg']) {
174
+ throw new InvalidArgumentException(
175
+ 'More than one alg detected in certs'
176
+ );
177
+ }
178
+ }
179
+ return $alg;
180
+ }
181
+
182
+ /**
183
+ * Verifies an ES256-signed JWT.
184
+ *
185
+ * @param string $token The JSON Web Token to be verified.
186
+ * @param array $certs Certificate array according to the JWK spec (see
187
+ * https://tools.ietf.org/html/rfc7517).
188
+ * @param string|null $audience If set, returns false if the provided
189
+ * audience does not match the "aud" claim on the JWT.
190
+ * @param string|null $issuer If set, returns false if the provided
191
+ * issuer does not match the "iss" claim on the JWT.
192
+ * @return array|bool the token payload, if successful, or false if not.
193
+ */
194
+ private function verifyEs256($token, array $certs, $audience = null, $issuer = null)
195
+ {
196
+ $this->checkSimpleJwt();
197
+
198
+ $jwkset = new KeySet();
199
+ foreach ($certs as $cert) {
200
+ $jwkset->add(KeyFactory::create($cert, 'php'));
201
+ }
202
+
203
+ // Validate the signature using the key set and ES256 algorithm.
204
+ $jwt = $this->callSimpleJwtDecode([$token, $jwkset, 'ES256']);
205
+ $payload = $jwt->getClaims();
206
+
207
+ if (isset($payload['aud'])) {
208
+ if ($audience && $payload['aud'] != $audience) {
209
+ throw new UnexpectedValueException('Audience does not match');
210
+ }
211
+ }
212
+
213
+ // @see https://cloud.google.com/iap/docs/signed-headers-howto#verifying_the_jwt_payload
214
+ $issuer = $issuer ?: self::IAP_ISSUER;
215
+ if (!isset($payload['iss']) || $payload['iss'] !== $issuer) {
216
+ throw new UnexpectedValueException('Issuer does not match');
217
+ }
218
+
219
+ return $payload;
220
+ }
221
+
222
+ /**
223
+ * Verifies an RS256-signed JWT.
224
+ *
225
+ * @param string $token The JSON Web Token to be verified.
226
+ * @param array $certs Certificate array according to the JWK spec (see
227
+ * https://tools.ietf.org/html/rfc7517).
228
+ * @param string|null $audience If set, returns false if the provided
229
+ * audience does not match the "aud" claim on the JWT.
230
+ * @param string|null $issuer If set, returns false if the provided
231
+ * issuer does not match the "iss" claim on the JWT.
232
+ * @return array|bool the token payload, if successful, or false if not.
233
+ */
234
+ private function verifyRs256($token, array $certs, $audience = null, $issuer = null)
235
+ {
236
+ $this->checkAndInitializePhpsec();
237
+ $keys = [];
238
+ foreach ($certs as $cert) {
239
+ if (empty($cert['kid'])) {
240
+ throw new InvalidArgumentException(
241
+ 'certs expects "kid" to be set'
242
+ );
243
+ }
244
+ if (empty($cert['n']) || empty($cert['e'])) {
245
+ throw new InvalidArgumentException(
246
+ 'RSA certs expects "n" and "e" to be set'
247
+ );
248
+ }
249
+ $rsa = new RSA();
250
+ $rsa->loadKey([
251
+ 'n' => new BigInteger($this->callJwtStatic('urlsafeB64Decode', [
252
+ $cert['n'],
253
+ ]), 256),
254
+ 'e' => new BigInteger($this->callJwtStatic('urlsafeB64Decode', [
255
+ $cert['e']
256
+ ]), 256),
257
+ ]);
258
+
259
+ // create an array of key IDs to certs for the JWT library
260
+ $keys[$cert['kid']] = $rsa->getPublicKey();
261
+ }
262
+
263
+ $payload = $this->callJwtStatic('decode', [
264
+ $token,
265
+ $keys,
266
+ ['RS256']
267
+ ]);
268
+
269
+ if (property_exists($payload, 'aud')) {
270
+ if ($audience && $payload->aud != $audience) {
271
+ throw new UnexpectedValueException('Audience does not match');
272
+ }
273
+ }
274
+
275
+ // support HTTP and HTTPS issuers
276
+ // @see https://developers.google.com/identity/sign-in/web/backend-auth
277
+ $issuers = $issuer ? [$issuer] : [self::OAUTH2_ISSUER, self::OAUTH2_ISSUER_HTTPS];
278
+ if (!isset($payload->iss) || !in_array($payload->iss, $issuers)) {
279
+ throw new UnexpectedValueException('Issuer does not match');
280
+ }
281
+
282
+ return (array) $payload;
283
+ }
284
+
285
+ /**
286
+ * Revoke an OAuth2 access token or refresh token. This method will revoke the current access
287
+ * token, if a token isn't provided.
288
+ *
289
+ * @param string|array $token The token (access token or a refresh token) that should be revoked.
290
+ * @param array $options [optional] Configuration options.
291
+ * @return bool Returns True if the revocation was successful, otherwise False.
292
+ */
293
+ public function revoke($token, array $options = [])
294
+ {
295
+ if (is_array($token)) {
296
+ if (isset($token['refresh_token'])) {
297
+ $token = $token['refresh_token'];
298
+ } else {
299
+ $token = $token['access_token'];
300
+ }
301
+ }
302
+
303
+ $body = Psr7\stream_for(http_build_query(['token' => $token]));
304
+ $request = new Request('POST', self::OAUTH2_REVOKE_URI, [
305
+ 'Cache-Control' => 'no-store',
306
+ 'Content-Type' => 'application/x-www-form-urlencoded',
307
+ ], $body);
308
+
309
+ $httpHandler = $this->httpHandler;
310
+
311
+ $response = $httpHandler($request, $options);
312
+
313
+ return $response->getStatusCode() == 200;
314
+ }
315
+
316
+ /**
317
+ * Gets federated sign-on certificates to use for verifying identity tokens.
318
+ * Returns certs as array structure, where keys are key ids, and values
319
+ * are PEM encoded certificates.
320
+ *
321
+ * @param string $location The location from which to retrieve certs.
322
+ * @param string $cacheKey The key under which to cache the retrieved certs.
323
+ * @param array $options [optional] Configuration options.
324
+ * @return array
325
+ * @throws InvalidArgumentException If received certs are in an invalid format.
326
+ */
327
+ private function getCerts($location, $cacheKey, array $options = [])
328
+ {
329
+ $cacheItem = $this->cache->getItem($cacheKey);
330
+ $certs = $cacheItem ? $cacheItem->get() : null;
331
+
332
+ $gotNewCerts = false;
333
+ if (!$certs) {
334
+ $certs = $this->retrieveCertsFromLocation($location, $options);
335
+
336
+ $gotNewCerts = true;
337
+ }
338
+
339
+ if (!isset($certs['keys'])) {
340
+ if ($location !== self::IAP_CERT_URL) {
341
+ throw new InvalidArgumentException(
342
+ 'federated sign-on certs expects "keys" to be set'
343
+ );
344
+ }
345
+ throw new InvalidArgumentException(
346
+ 'certs expects "keys" to be set'
347
+ );
348
+ }
349
+
350
+ // Push caching off until after verifying certs are in a valid format.
351
+ // Don't want to cache bad data.
352
+ if ($gotNewCerts) {
353
+ $cacheItem->expiresAt(new DateTime('+1 hour'));
354
+ $cacheItem->set($certs);
355
+ $this->cache->save($cacheItem);
356
+ }
357
+
358
+ return $certs['keys'];
359
+ }
360
+
361
+ /**
362
+ * Retrieve and cache a certificates file.
363
+ *
364
+ * @param $url string location
365
+ * @param array $options [optional] Configuration options.
366
+ * @return array certificates
367
+ * @throws InvalidArgumentException If certs could not be retrieved from a local file.
368
+ * @throws RuntimeException If certs could not be retrieved from a remote location.
369
+ */
370
+ private function retrieveCertsFromLocation($url, array $options = [])
371
+ {
372
+ // If we're retrieving a local file, just grab it.
373
+ if (strpos($url, 'http') !== 0) {
374
+ if (!file_exists($url)) {
375
+ throw new InvalidArgumentException(sprintf(
376
+ 'Failed to retrieve verification certificates from path: %s.',
377
+ $url
378
+ ));
379
+ }
380
+
381
+ return json_decode(file_get_contents($url), true);
382
+ }
383
+
384
+ $httpHandler = $this->httpHandler;
385
+ $response = $httpHandler(new Request('GET', $url), $options);
386
+
387
+ if ($response->getStatusCode() == 200) {
388
+ return json_decode((string) $response->getBody(), true);
389
+ }
390
+
391
+ throw new RuntimeException(sprintf(
392
+ 'Failed to retrieve verification certificates: "%s".',
393
+ $response->getBody()->getContents()
394
+ ), $response->getStatusCode());
395
+ }
396
+
397
+ private function checkAndInitializePhpsec()
398
+ {
399
+ // @codeCoverageIgnoreStart
400
+ if (!class_exists('phpseclib\Crypt\RSA')) {
401
+ throw new RuntimeException('Please require phpseclib/phpseclib v2 to use this utility.');
402
+ }
403
+ // @codeCoverageIgnoreEnd
404
+
405
+ $this->setPhpsecConstants();
406
+ }
407
+
408
+ private function checkSimpleJwt()
409
+ {
410
+ // @codeCoverageIgnoreStart
411
+ if (!class_exists('SimpleJWT\JWT')) {
412
+ throw new RuntimeException('Please require kelvinmo/simplejwt ^0.2 to use this utility.');
413
+ }
414
+ // @codeCoverageIgnoreEnd
415
+ }
416
+
417
+ /**
418
+ * phpseclib calls "phpinfo" by default, which requires special
419
+ * whitelisting in the AppEngine VM environment. This function
420
+ * sets constants to bypass the need for phpseclib to check phpinfo
421
+ *
422
+ * @see phpseclib/Math/BigInteger
423
+ * @see https://github.com/GoogleCloudPlatform/getting-started-php/issues/85
424
+ * @codeCoverageIgnore
425
+ */
426
+ private function setPhpsecConstants()
427
+ {
428
+ if (filter_var(getenv('GAE_VM'), FILTER_VALIDATE_BOOLEAN)) {
429
+ if (!defined('MATH_BIGINTEGER_OPENSSL_ENABLED')) {
430
+ define('MATH_BIGINTEGER_OPENSSL_ENABLED', true);
431
+ }
432
+ if (!defined('CRYPT_RSA_MODE')) {
433
+ define('CRYPT_RSA_MODE', RSA::MODE_OPENSSL);
434
+ }
435
+ }
436
+ }
437
+
438
+ /**
439
+ * Provide a hook to mock calls to the JWT static methods.
440
+ *
441
+ * @param string $method
442
+ * @param array $args
443
+ * @return mixed
444
+ */
445
+ protected function callJwtStatic($method, array $args = [])
446
+ {
447
+ $class = class_exists('Firebase\JWT\JWT')
448
+ ? 'Firebase\JWT\JWT'
449
+ : 'JWT';
450
+ return call_user_func_array([$class, $method], $args);
451
+ }
452
+
453
+ /**
454
+ * Provide a hook to mock calls to the JWT static methods.
455
+ *
456
+ * @param array $args
457
+ * @return mixed
458
+ */
459
+ protected function callSimpleJwtDecode(array $args = [])
460
+ {
461
+ return call_user_func_array(['SimpleJWT\JWT', 'decode'], $args);
462
+ }
463
+
464
+ /**
465
+ * Generate a cache key based on the cert location using sha1 with the
466
+ * exception of using "federated_signon_certs_v3" to preserve BC.
467
+ *
468
+ * @param string $certsLocation
469
+ * @return string
470
+ */
471
+ private function getCacheKeyFromCertLocation($certsLocation)
472
+ {
473
+ $key = $certsLocation === self::FEDERATED_SIGNON_CERT_URL
474
+ ? 'federated_signon_certs_v3'
475
+ : sha1($certsLocation);
476
+
477
+ return 'google_auth_certs_cache|' . $key;
478
+ }
479
+ }
vendor/google/auth/src/ApplicationDefaultCredentials.php ADDED
@@ -0,0 +1,308 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2015 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth;
19
+
20
+ use DomainException;
21
+ use Google\Auth\Credentials\AppIdentityCredentials;
22
+ use Google\Auth\Credentials\GCECredentials;
23
+ use Google\Auth\Credentials\ServiceAccountCredentials;
24
+ use Google\Auth\HttpHandler\HttpClientCache;
25
+ use Google\Auth\HttpHandler\HttpHandlerFactory;
26
+ use Google\Auth\Middleware\AuthTokenMiddleware;
27
+ use Google\Auth\Subscriber\AuthTokenSubscriber;
28
+ use GuzzleHttp\Client;
29
+ use InvalidArgumentException;
30
+ use Psr\Cache\CacheItemPoolInterface;
31
+
32
+ /**
33
+ * ApplicationDefaultCredentials obtains the default credentials for
34
+ * authorizing a request to a Google service.
35
+ *
36
+ * Application Default Credentials are described here:
37
+ * https://developers.google.com/accounts/docs/application-default-credentials
38
+ *
39
+ * This class implements the search for the application default credentials as
40
+ * described in the link.
41
+ *
42
+ * It provides three factory methods:
43
+ * - #get returns the computed credentials object
44
+ * - #getSubscriber returns an AuthTokenSubscriber built from the credentials object
45
+ * - #getMiddleware returns an AuthTokenMiddleware built from the credentials object
46
+ *
47
+ * This allows it to be used as follows with GuzzleHttp\Client:
48
+ *
49
+ * ```
50
+ * use Google\Auth\ApplicationDefaultCredentials;
51
+ * use GuzzleHttp\Client;
52
+ * use GuzzleHttp\HandlerStack;
53
+ *
54
+ * $middleware = ApplicationDefaultCredentials::getMiddleware(
55
+ * 'https://www.googleapis.com/auth/taskqueue'
56
+ * );
57
+ * $stack = HandlerStack::create();
58
+ * $stack->push($middleware);
59
+ *
60
+ * $client = new Client([
61
+ * 'handler' => $stack,
62
+ * 'base_uri' => 'https://www.googleapis.com/taskqueue/v1beta2/projects/',
63
+ * 'auth' => 'google_auth' // authorize all requests
64
+ * ]);
65
+ *
66
+ * $res = $client->get('myproject/taskqueues/myqueue');
67
+ * ```
68
+ */
69
+ class ApplicationDefaultCredentials
70
+ {
71
+ /**
72
+ * Obtains an AuthTokenSubscriber that uses the default FetchAuthTokenInterface
73
+ * implementation to use in this environment.
74
+ *
75
+ * If supplied, $scope is used to in creating the credentials instance if
76
+ * this does not fallback to the compute engine defaults.
77
+ *
78
+ * @param string|array scope the scope of the access request, expressed
79
+ * either as an Array or as a space-delimited String.
80
+ * @param callable $httpHandler callback which delivers psr7 request
81
+ * @param array $cacheConfig configuration for the cache when it's present
82
+ * @param CacheItemPoolInterface $cache A cache implementation, may be
83
+ * provided if you have one already available for use.
84
+ * @return AuthTokenSubscriber
85
+ * @throws DomainException if no implementation can be obtained.
86
+ */
87
+ public static function getSubscriber(
88
+ $scope = null,
89
+ callable $httpHandler = null,
90
+ array $cacheConfig = null,
91
+ CacheItemPoolInterface $cache = null
92
+ ) {
93
+ $creds = self::getCredentials($scope, $httpHandler, $cacheConfig, $cache);
94
+
95
+ return new AuthTokenSubscriber($creds, $httpHandler);
96
+ }
97
+
98
+ /**
99
+ * Obtains an AuthTokenMiddleware that uses the default FetchAuthTokenInterface
100
+ * implementation to use in this environment.
101
+ *
102
+ * If supplied, $scope is used to in creating the credentials instance if
103
+ * this does not fallback to the compute engine defaults.
104
+ *
105
+ * @param string|array scope the scope of the access request, expressed
106
+ * either as an Array or as a space-delimited String.
107
+ * @param callable $httpHandler callback which delivers psr7 request
108
+ * @param array $cacheConfig configuration for the cache when it's present
109
+ * @param CacheItemPoolInterface $cache A cache implementation, may be
110
+ * provided if you have one already available for use.
111
+ * @param string $quotaProject specifies a project to bill for access
112
+ * charges associated with the request.
113
+ * @return AuthTokenMiddleware
114
+ * @throws DomainException if no implementation can be obtained.
115
+ */
116
+ public static function getMiddleware(
117
+ $scope = null,
118
+ callable $httpHandler = null,
119
+ array $cacheConfig = null,
120
+ CacheItemPoolInterface $cache = null,
121
+ $quotaProject = null
122
+ ) {
123
+ $creds = self::getCredentials($scope, $httpHandler, $cacheConfig, $cache, $quotaProject);
124
+
125
+ return new AuthTokenMiddleware($creds, $httpHandler);
126
+ }
127
+
128
+ /**
129
+ * Obtains an AuthTokenMiddleware which will fetch an access token to use in
130
+ * the Authorization header. The middleware is configured with the default
131
+ * FetchAuthTokenInterface implementation to use in this environment.
132
+ *
133
+ * If supplied, $scope is used to in creating the credentials instance if
134
+ * this does not fallback to the Compute Engine defaults.
135
+ *
136
+ * @param string|array $scope the scope of the access request, expressed
137
+ * either as an Array or as a space-delimited String.
138
+ * @param callable $httpHandler callback which delivers psr7 request
139
+ * @param array $cacheConfig configuration for the cache when it's present
140
+ * @param CacheItemPoolInterface $cache A cache implementation, may be
141
+ * provided if you have one already available for use.
142
+ * @param string $quotaProject specifies a project to bill for access
143
+ * charges associated with the request.
144
+ * @param string|array $defaultScope The default scope to use if no
145
+ * user-defined scopes exist, expressed either as an Array or as a
146
+ * space-delimited string.
147
+ *
148
+ * @return CredentialsLoader
149
+ * @throws DomainException if no implementation can be obtained.
150
+ */
151
+ public static function getCredentials(
152
+ $scope = null,
153
+ callable $httpHandler = null,
154
+ array $cacheConfig = null,
155
+ CacheItemPoolInterface $cache = null,
156
+ $quotaProject = null,
157
+ $defaultScope = null
158
+ ) {
159
+ $creds = null;
160
+ $jsonKey = CredentialsLoader::fromEnv()
161
+ ?: CredentialsLoader::fromWellKnownFile();
162
+ $anyScope = $scope ?: $defaultScope;
163
+
164
+ if (!$httpHandler) {
165
+ if (!($client = HttpClientCache::getHttpClient())) {
166
+ $client = new Client();
167
+ HttpClientCache::setHttpClient($client);
168
+ }
169
+
170
+ $httpHandler = HttpHandlerFactory::build($client);
171
+ }
172
+
173
+ if (!is_null($jsonKey)) {
174
+ if ($quotaProject) {
175
+ $jsonKey['quota_project_id'] = $quotaProject;
176
+ }
177
+ $creds = CredentialsLoader::makeCredentials(
178
+ $scope,
179
+ $jsonKey,
180
+ $defaultScope
181
+ );
182
+ } elseif (AppIdentityCredentials::onAppEngine() && !GCECredentials::onAppEngineFlexible()) {
183
+ $creds = new AppIdentityCredentials($anyScope);
184
+ } elseif (self::onGce($httpHandler, $cacheConfig, $cache)) {
185
+ $creds = new GCECredentials(null, $anyScope, null, $quotaProject);
186
+ }
187
+
188
+ if (is_null($creds)) {
189
+ throw new DomainException(self::notFound());
190
+ }
191
+ if (!is_null($cache)) {
192
+ $creds = new FetchAuthTokenCache($creds, $cacheConfig, $cache);
193
+ }
194
+ return $creds;
195
+ }
196
+
197
+ /**
198
+ * Obtains an AuthTokenMiddleware which will fetch an ID token to use in the
199
+ * Authorization header. The middleware is configured with the default
200
+ * FetchAuthTokenInterface implementation to use in this environment.
201
+ *
202
+ * If supplied, $targetAudience is used to set the "aud" on the resulting
203
+ * ID token.
204
+ *
205
+ * @param string $targetAudience The audience for the ID token.
206
+ * @param callable $httpHandler callback which delivers psr7 request
207
+ * @param array $cacheConfig configuration for the cache when it's present
208
+ * @param CacheItemPoolInterface $cache A cache implementation, may be
209
+ * provided if you have one already available for use.
210
+ * @return AuthTokenMiddleware
211
+ * @throws DomainException if no implementation can be obtained.
212
+ */
213
+ public static function getIdTokenMiddleware(
214
+ $targetAudience,
215
+ callable $httpHandler = null,
216
+ array $cacheConfig = null,
217
+ CacheItemPoolInterface $cache = null
218
+ ) {
219
+ $creds = self::getIdTokenCredentials($targetAudience, $httpHandler, $cacheConfig, $cache);
220
+
221
+ return new AuthTokenMiddleware($creds, $httpHandler);
222
+ }
223
+
224
+ /**
225
+ * Obtains the default FetchAuthTokenInterface implementation to use
226
+ * in this environment, configured with a $targetAudience for fetching an ID
227
+ * token.
228
+ *
229
+ * @param string $targetAudience The audience for the ID token.
230
+ * @param callable $httpHandler callback which delivers psr7 request
231
+ * @param array $cacheConfig configuration for the cache when it's present
232
+ * @param CacheItemPoolInterface $cache A cache implementation, may be
233
+ * provided if you have one already available for use.
234
+ * @return CredentialsLoader
235
+ * @throws DomainException if no implementation can be obtained.
236
+ * @throws InvalidArgumentException if JSON "type" key is invalid
237
+ */
238
+ public static function getIdTokenCredentials(
239
+ $targetAudience,
240
+ callable $httpHandler = null,
241
+ array $cacheConfig = null,
242
+ CacheItemPoolInterface $cache = null
243
+ ) {
244
+ $creds = null;
245
+ $jsonKey = CredentialsLoader::fromEnv()
246
+ ?: CredentialsLoader::fromWellKnownFile();
247
+
248
+ if (!$httpHandler) {
249
+ if (!($client = HttpClientCache::getHttpClient())) {
250
+ $client = new Client();
251
+ HttpClientCache::setHttpClient($client);
252
+ }
253
+
254
+ $httpHandler = HttpHandlerFactory::build($client);
255
+ }
256
+
257
+ if (!is_null($jsonKey)) {
258
+ if (!array_key_exists('type', $jsonKey)) {
259
+ throw new \InvalidArgumentException('json key is missing the type field');
260
+ }
261
+
262
+ if ($jsonKey['type'] == 'authorized_user') {
263
+ throw new InvalidArgumentException('ID tokens are not supported for end user credentials');
264
+ }
265
+
266
+ if ($jsonKey['type'] != 'service_account') {
267
+ throw new InvalidArgumentException('invalid value in the type field');
268
+ }
269
+
270
+ $creds = new ServiceAccountCredentials(null, $jsonKey, null, $targetAudience);
271
+ } elseif (self::onGce($httpHandler, $cacheConfig, $cache)) {
272
+ $creds = new GCECredentials(null, null, $targetAudience);
273
+ }
274
+
275
+ if (is_null($creds)) {
276
+ throw new DomainException(self::notFound());
277
+ }
278
+ if (!is_null($cache)) {
279
+ $creds = new FetchAuthTokenCache($creds, $cacheConfig, $cache);
280
+ }
281
+ return $creds;
282
+ }
283
+
284
+ private static function notFound()
285
+ {
286
+ $msg = 'Could not load the default credentials. Browse to ';
287
+ $msg .= 'https://developers.google.com';
288
+ $msg .= '/accounts/docs/application-default-credentials';
289
+ $msg .= ' for more information';
290
+
291
+ return $msg;
292
+ }
293
+
294
+ private static function onGce(
295
+ callable $httpHandler = null,
296
+ array $cacheConfig = null,
297
+ CacheItemPoolInterface $cache = null
298
+ ) {
299
+ $gceCacheConfig = [];
300
+ foreach (['lifetime', 'prefix'] as $key) {
301
+ if (isset($cacheConfig['gce_' . $key])) {
302
+ $gceCacheConfig[$key] = $cacheConfig['gce_' . $key];
303
+ }
304
+ }
305
+
306
+ return (new GCECache($gceCacheConfig, $cache))->onGce($httpHandler);
307
+ }
308
+ }
vendor/google/auth/src/Cache/InvalidArgumentException.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2016 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth\Cache;
19
+
20
+ use Psr\Cache\InvalidArgumentException as PsrInvalidArgumentException;
21
+
22
+ class InvalidArgumentException extends \InvalidArgumentException implements PsrInvalidArgumentException
23
+ {
24
+ }
vendor/google/auth/src/Cache/Item.php ADDED
@@ -0,0 +1,190 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2016 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth\Cache;
19
+
20
+ use Psr\Cache\CacheItemInterface;
21
+
22
+ /**
23
+ * A cache item.
24
+ */
25
+ final class Item implements CacheItemInterface
26
+ {
27
+ /**
28
+ * @var string
29
+ */
30
+ private $key;
31
+
32
+ /**
33
+ * @var mixed
34
+ */
35
+ private $value;
36
+
37
+ /**
38
+ * @var \DateTime|null
39
+ */
40
+ private $expiration;
41
+
42
+ /**
43
+ * @var bool
44
+ */
45
+ private $isHit = false;
46
+
47
+ /**
48
+ * @param string $key
49
+ */
50
+ public function __construct($key)
51
+ {
52
+ $this->key = $key;
53
+ }
54
+
55
+ /**
56
+ * {@inheritdoc}
57
+ */
58
+ public function getKey()
59
+ {
60
+ return $this->key;
61
+ }
62
+
63
+ /**
64
+ * {@inheritdoc}
65
+ */
66
+ public function get()
67
+ {
68
+ return $this->isHit() ? $this->value : null;
69
+ }
70
+
71
+ /**
72
+ * {@inheritdoc}
73
+ */
74
+ public function isHit()
75
+ {
76
+ if (!$this->isHit) {
77
+ return false;
78
+ }
79
+
80
+ if ($this->expiration === null) {
81
+ return true;
82
+ }
83
+
84
+ return $this->currentTime()->getTimestamp() < $this->expiration->getTimestamp();
85
+ }
86
+
87
+ /**
88
+ * {@inheritdoc}
89
+ */
90
+ public function set($value)
91
+ {
92
+ $this->isHit = true;
93
+ $this->value = $value;
94
+
95
+ return $this;
96
+ }
97
+
98
+ /**
99
+ * {@inheritdoc}
100
+ */
101
+ public function expiresAt($expiration)
102
+ {
103
+ if ($this->isValidExpiration($expiration)) {
104
+ $this->expiration = $expiration;
105
+
106
+ return $this;
107
+ }
108
+
109
+ $implementationMessage = interface_exists('DateTimeInterface')
110
+ ? 'implement interface DateTimeInterface'
111
+ : 'be an instance of DateTime';
112
+
113
+ $error = sprintf(
114
+ 'Argument 1 passed to %s::expiresAt() must %s, %s given',
115
+ get_class($this),
116
+ $implementationMessage,
117
+ gettype($expiration)
118
+ );
119
+
120
+ $this->handleError($error);
121
+ }
122
+
123
+ /**
124
+ * {@inheritdoc}
125
+ */
126
+ public function expiresAfter($time)
127
+ {
128
+ if (is_int($time)) {
129
+ $this->expiration = $this->currentTime()->add(new \DateInterval("PT{$time}S"));
130
+ } elseif ($time instanceof \DateInterval) {
131
+ $this->expiration = $this->currentTime()->add($time);
132
+ } elseif ($time === null) {
133
+ $this->expiration = $time;
134
+ } else {
135
+ $message = 'Argument 1 passed to %s::expiresAfter() must be an ' .
136
+ 'instance of DateInterval or of the type integer, %s given';
137
+ $error = sprintf($message, get_class($this), gettype($time));
138
+
139
+ $this->handleError($error);
140
+ }
141
+
142
+ return $this;
143
+ }
144
+
145
+ /**
146
+ * Handles an error.
147
+ *
148
+ * @param string $error
149
+ * @throws \TypeError
150
+ */
151
+ private function handleError($error)
152
+ {
153
+ if (class_exists('TypeError')) {
154
+ throw new \TypeError($error);
155
+ }
156
+
157
+ trigger_error($error, E_USER_ERROR);
158
+ }
159
+
160
+ /**
161
+ * Determines if an expiration is valid based on the rules defined by PSR6.
162
+ *
163
+ * @param mixed $expiration
164
+ * @return bool
165
+ */
166
+ private function isValidExpiration($expiration)
167
+ {
168
+ if ($expiration === null) {
169
+ return true;
170
+ }
171
+
172
+ // We test for two types here due to the fact the DateTimeInterface
173
+ // was not introduced until PHP 5.5. Checking for the DateTime type as
174
+ // well allows us to support 5.4.
175
+ if ($expiration instanceof \DateTimeInterface) {
176
+ return true;
177
+ }
178
+
179
+ if ($expiration instanceof \DateTime) {
180
+ return true;
181
+ }
182
+
183
+ return false;
184
+ }
185
+
186
+ protected function currentTime()
187
+ {
188
+ return new \DateTime('now', new \DateTimeZone('UTC'));
189
+ }
190
+ }
vendor/google/auth/src/Cache/MemoryCacheItemPool.php ADDED
@@ -0,0 +1,154 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2016 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth\Cache;
19
+
20
+ use Psr\Cache\CacheItemInterface;
21
+ use Psr\Cache\CacheItemPoolInterface;
22
+
23
+ /**
24
+ * Simple in-memory cache implementation.
25
+ */
26
+ final class MemoryCacheItemPool implements CacheItemPoolInterface
27
+ {
28
+ /**
29
+ * @var CacheItemInterface[]
30
+ */
31
+ private $items;
32
+
33
+ /**
34
+ * @var CacheItemInterface[]
35
+ */
36
+ private $deferredItems;
37
+
38
+ /**
39
+ * {@inheritdoc}
40
+ */
41
+ public function getItem($key)
42
+ {
43
+ return current($this->getItems([$key]));
44
+ }
45
+
46
+ /**
47
+ * {@inheritdoc}
48
+ */
49
+ public function getItems(array $keys = [])
50
+ {
51
+ $items = [];
52
+
53
+ foreach ($keys as $key) {
54
+ $items[$key] = $this->hasItem($key) ? clone $this->items[$key] : new Item($key);
55
+ }
56
+
57
+ return $items;
58
+ }
59
+
60
+ /**
61
+ * {@inheritdoc}
62
+ */
63
+ public function hasItem($key)
64
+ {
65
+ $this->isValidKey($key);
66
+
67
+ return isset($this->items[$key]) && $this->items[$key]->isHit();
68
+ }
69
+
70
+ /**
71
+ * {@inheritdoc}
72
+ */
73
+ public function clear()
74
+ {
75
+ $this->items = [];
76
+ $this->deferredItems = [];
77
+
78
+ return true;
79
+ }
80
+
81
+ /**
82
+ * {@inheritdoc}
83
+ */
84
+ public function deleteItem($key)
85
+ {
86
+ return $this->deleteItems([$key]);
87
+ }
88
+
89
+ /**
90
+ * {@inheritdoc}
91
+ */
92
+ public function deleteItems(array $keys)
93
+ {
94
+ array_walk($keys, [$this, 'isValidKey']);
95
+
96
+ foreach ($keys as $key) {
97
+ unset($this->items[$key]);
98
+ }
99
+
100
+ return true;
101
+ }
102
+
103
+ /**
104
+ * {@inheritdoc}
105
+ */
106
+ public function save(CacheItemInterface $item)
107
+ {
108
+ $this->items[$item->getKey()] = $item;
109
+
110
+ return true;
111
+ }
112
+
113
+ /**
114
+ * {@inheritdoc}
115
+ */
116
+ public function saveDeferred(CacheItemInterface $item)
117
+ {
118
+ $this->deferredItems[$item->getKey()] = $item;
119
+
120
+ return true;
121
+ }
122
+
123
+ /**
124
+ * {@inheritdoc}
125
+ */
126
+ public function commit()
127
+ {
128
+ foreach ($this->deferredItems as $item) {
129
+ $this->save($item);
130
+ }
131
+
132
+ $this->deferredItems = [];
133
+
134
+ return true;
135
+ }
136
+
137
+ /**
138
+ * Determines if the provided key is valid.
139
+ *
140
+ * @param string $key
141
+ * @return bool
142
+ * @throws InvalidArgumentException
143
+ */
144
+ private function isValidKey($key)
145
+ {
146
+ $invalidCharacters = '{}()/\\\\@:';
147
+
148
+ if (!is_string($key) || preg_match("#[$invalidCharacters]#", $key)) {
149
+ throw new InvalidArgumentException('The provided key is not valid: ' . var_export($key, true));
150
+ }
151
+
152
+ return true;
153
+ }
154
+ }
vendor/google/auth/src/Cache/SysVCacheItemPool.php ADDED
@@ -0,0 +1,241 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2018 Google Inc. All Rights Reserved.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ namespace Google\Auth\Cache;
18
+
19
+ use Psr\Cache\CacheItemInterface;
20
+ use Psr\Cache\CacheItemPoolInterface;
21
+
22
+ /**
23
+ * SystemV shared memory based CacheItemPool implementation.
24
+ *
25
+ * This CacheItemPool implementation can be used among multiple processes, but
26
+ * it doesn't provide any locking mechanism. If multiple processes write to
27
+ * this ItemPool, you have to avoid race condition manually in your code.
28
+ */
29
+ class SysVCacheItemPool implements CacheItemPoolInterface
30
+ {
31
+ const VAR_KEY = 1;
32
+
33
+ const DEFAULT_PROJ = 'A';
34
+
35
+ const DEFAULT_MEMSIZE = 10000;
36
+
37
+ const DEFAULT_PERM = 0600;
38
+
39
+ /** @var int */
40
+ private $sysvKey;
41
+
42
+ /**
43
+ * @var CacheItemInterface[]
44
+ */
45
+ private $items;
46
+
47
+ /**
48
+ * @var CacheItemInterface[]
49
+ */
50
+ private $deferredItems;
51
+
52
+ /**
53
+ * @var array
54
+ */
55
+ private $options;
56
+
57
+ /*
58
+ * @var bool
59
+ */
60
+ private $hasLoadedItems = false;
61
+
62
+ /**
63
+ * Create a SystemV shared memory based CacheItemPool.
64
+ *
65
+ * @param array $options [optional] Configuration options.
66
+ * @param int $options.variableKey The variable key for getting the data from
67
+ * the shared memory. **Defaults to** 1.
68
+ * @param $options.proj string The project identifier for ftok. This needs to
69
+ * be a one character string. **Defaults to** 'A'.
70
+ * @param $options.memsize int The memory size in bytes for shm_attach.
71
+ * **Defaults to** 10000.
72
+ * @param $options.perm int The permission for shm_attach. **Defaults to**
73
+ * 0600.
74
+ */
75
+ public function __construct($options = [])
76
+ {
77
+ if (! extension_loaded('sysvshm')) {
78
+ throw new \RuntimeException(
79
+ 'sysvshm extension is required to use this ItemPool'
80
+ );
81
+ }
82
+ $this->options = $options + [
83
+ 'variableKey' => self::VAR_KEY,
84
+ 'proj' => self::DEFAULT_PROJ,
85
+ 'memsize' => self::DEFAULT_MEMSIZE,
86
+ 'perm' => self::DEFAULT_PERM
87
+ ];
88
+ $this->items = [];
89
+ $this->deferredItems = [];
90
+ $this->sysvKey = ftok(__FILE__, $this->options['proj']);
91
+ }
92
+
93
+ public function getItem($key)
94
+ {
95
+ $this->loadItems();
96
+ return current($this->getItems([$key]));
97
+ }
98
+
99
+ /**
100
+ * {@inheritdoc}
101
+ */
102
+ public function getItems(array $keys = [])
103
+ {
104
+ $this->loadItems();
105
+ $items = [];
106
+ foreach ($keys as $key) {
107
+ $items[$key] = $this->hasItem($key) ?
108
+ clone $this->items[$key] :
109
+ new Item($key);
110
+ }
111
+ return $items;
112
+ }
113
+
114
+ /**
115
+ * {@inheritdoc}
116
+ */
117
+ public function hasItem($key)
118
+ {
119
+ $this->loadItems();
120
+ return isset($this->items[$key]) && $this->items[$key]->isHit();
121
+ }
122
+
123
+ /**
124
+ * {@inheritdoc}
125
+ */
126
+ public function clear()
127
+ {
128
+ $this->items = [];
129
+ $this->deferredItems = [];
130
+ return $this->saveCurrentItems();
131
+ }
132
+
133
+ /**
134
+ * {@inheritdoc}
135
+ */
136
+ public function deleteItem($key)
137
+ {
138
+ return $this->deleteItems([$key]);
139
+ }
140
+
141
+ /**
142
+ * {@inheritdoc}
143
+ */
144
+ public function deleteItems(array $keys)
145
+ {
146
+ if (!$this->hasLoadedItems) {
147
+ $this->loadItems();
148
+ }
149
+
150
+ foreach ($keys as $key) {
151
+ unset($this->items[$key]);
152
+ }
153
+ return $this->saveCurrentItems();
154
+ }
155
+
156
+ /**
157
+ * {@inheritdoc}
158
+ */
159
+ public function save(CacheItemInterface $item)
160
+ {
161
+ if (!$this->hasLoadedItems) {
162
+ $this->loadItems();
163
+ }
164
+
165
+ $this->items[$item->getKey()] = $item;
166
+ return $this->saveCurrentItems();
167
+ }
168
+
169
+ /**
170
+ * {@inheritdoc}
171
+ */
172
+ public function saveDeferred(CacheItemInterface $item)
173
+ {
174
+ $this->deferredItems[$item->getKey()] = $item;
175
+ return true;
176
+ }
177
+
178
+ /**
179
+ * {@inheritdoc}
180
+ */
181
+ public function commit()
182
+ {
183
+ foreach ($this->deferredItems as $item) {
184
+ if ($this->save($item) === false) {
185
+ return false;
186
+ }
187
+ }
188
+ $this->deferredItems = [];
189
+ return true;
190
+ }
191
+
192
+ /**
193
+ * Save the current items.
194
+ *
195
+ * @return bool true when success, false upon failure
196
+ */
197
+ private function saveCurrentItems()
198
+ {
199
+ $shmid = shm_attach(
200
+ $this->sysvKey,
201
+ $this->options['memsize'],
202
+ $this->options['perm']
203
+ );
204
+ if ($shmid !== false) {
205
+ $ret = shm_put_var(
206
+ $shmid,
207
+ $this->options['variableKey'],
208
+ $this->items
209
+ );
210
+ shm_detach($shmid);
211
+ return $ret;
212
+ }
213
+ return false;
214
+ }
215
+
216
+ /**
217
+ * Load the items from the shared memory.
218
+ *
219
+ * @return bool true when success, false upon failure
220
+ */
221
+ private function loadItems()
222
+ {
223
+ $shmid = shm_attach(
224
+ $this->sysvKey,
225
+ $this->options['memsize'],
226
+ $this->options['perm']
227
+ );
228
+ if ($shmid !== false) {
229
+ $data = @shm_get_var($shmid, $this->options['variableKey']);
230
+ if (!empty($data)) {
231
+ $this->items = $data;
232
+ } else {
233
+ $this->items = [];
234
+ }
235
+ shm_detach($shmid);
236
+ $this->hasLoadedItems = true;
237
+ return true;
238
+ }
239
+ return false;
240
+ }
241
+ }
vendor/google/auth/src/CacheTrait.php ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2015 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth;
19
+
20
+ trait CacheTrait
21
+ {
22
+ private $maxKeyLength = 64;
23
+
24
+ /**
25
+ * Gets the cached value if it is present in the cache when that is
26
+ * available.
27
+ */
28
+ private function getCachedValue($k)
29
+ {
30
+ if (is_null($this->cache)) {
31
+ return;
32
+ }
33
+
34
+ $key = $this->getFullCacheKey($k);
35
+ if (is_null($key)) {
36
+ return;
37
+ }
38
+
39
+ $cacheItem = $this->cache->getItem($key);
40
+ if ($cacheItem->isHit()) {
41
+ return $cacheItem->get();
42
+ }
43
+ }
44
+
45
+ /**
46
+ * Saves the value in the cache when that is available.
47
+ */
48
+ private function setCachedValue($k, $v)
49
+ {
50
+ if (is_null($this->cache)) {
51
+ return;
52
+ }
53
+
54
+ $key = $this->getFullCacheKey($k);
55
+ if (is_null($key)) {
56
+ return;
57
+ }
58
+
59
+ $cacheItem = $this->cache->getItem($key);
60
+ $cacheItem->set($v);
61
+ $cacheItem->expiresAfter($this->cacheConfig['lifetime']);
62
+ return $this->cache->save($cacheItem);
63
+ }
64
+
65
+ private function getFullCacheKey($key)
66
+ {
67
+ if (is_null($key)) {
68
+ return;
69
+ }
70
+
71
+ $key = $this->cacheConfig['prefix'] . $key;
72
+
73
+ // ensure we do not have illegal characters
74
+ $key = preg_replace('|[^a-zA-Z0-9_\.!]|', '', $key);
75
+
76
+ // Hash keys if they exceed $maxKeyLength (defaults to 64)
77
+ if ($this->maxKeyLength && strlen($key) > $this->maxKeyLength) {
78
+ $key = substr(hash('sha256', $key), 0, $this->maxKeyLength);
79
+ }
80
+
81
+ return $key;
82
+ }
83
+ }
vendor/google/auth/src/Credentials/AppIdentityCredentials.php ADDED
@@ -0,0 +1,230 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2015 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth\Credentials;
19
+
20
+ /*
21
+ * The AppIdentityService class is automatically defined on App Engine,
22
+ * so including this dependency is not necessary, and will result in a
23
+ * PHP fatal error in the App Engine environment.
24
+ */
25
+ use google\appengine\api\app_identity\AppIdentityService;
26
+ use Google\Auth\CredentialsLoader;
27
+ use Google\Auth\ProjectIdProviderInterface;
28
+ use Google\Auth\SignBlobInterface;
29
+
30
+ /**
31
+ * AppIdentityCredentials supports authorization on Google App Engine.
32
+ *
33
+ * It can be used to authorize requests using the AuthTokenMiddleware or
34
+ * AuthTokenSubscriber, but will only succeed if being run on App Engine:
35
+ *
36
+ * Example:
37
+ * ```
38
+ * use Google\Auth\Credentials\AppIdentityCredentials;
39
+ * use Google\Auth\Middleware\AuthTokenMiddleware;
40
+ * use GuzzleHttp\Client;
41
+ * use GuzzleHttp\HandlerStack;
42
+ *
43
+ * $gae = new AppIdentityCredentials('https://www.googleapis.com/auth/books');
44
+ * $middleware = new AuthTokenMiddleware($gae);
45
+ * $stack = HandlerStack::create();
46
+ * $stack->push($middleware);
47
+ *
48
+ * $client = new Client([
49
+ * 'handler' => $stack,
50
+ * 'base_uri' => 'https://www.googleapis.com/books/v1',
51
+ * 'auth' => 'google_auth'
52
+ * ]);
53
+ *
54
+ * $res = $client->get('volumes?q=Henry+David+Thoreau&country=US');
55
+ * ```
56
+ */
57
+ class AppIdentityCredentials extends CredentialsLoader implements
58
+ SignBlobInterface,
59
+ ProjectIdProviderInterface
60
+ {
61
+ /**
62
+ * Result of fetchAuthToken.
63
+ *
64
+ * @var array
65
+ */
66
+ protected $lastReceivedToken;
67
+
68
+ /**
69
+ * Array of OAuth2 scopes to be requested.
70
+ *
71
+ * @var array
72
+ */
73
+ private $scope;
74
+
75
+ /**
76
+ * @var string
77
+ */
78
+ private $clientName;
79
+
80
+ /**
81
+ * @param array $scope One or more scopes.
82
+ */
83
+ public function __construct($scope = array())
84
+ {
85
+ $this->scope = $scope;
86
+ }
87
+
88
+ /**
89
+ * Determines if this an App Engine instance, by accessing the
90
+ * SERVER_SOFTWARE environment variable (prod) or the APPENGINE_RUNTIME
91
+ * environment variable (dev).
92
+ *
93
+ * @return bool true if this an App Engine Instance, false otherwise
94
+ */
95
+ public static function onAppEngine()
96
+ {
97
+ $appEngineProduction = isset($_SERVER['SERVER_SOFTWARE']) &&
98
+ 0 === strpos($_SERVER['SERVER_SOFTWARE'], 'Google App Engine');
99
+ if ($appEngineProduction) {
100
+ return true;
101
+ }
102
+ $appEngineDevAppServer = isset($_SERVER['APPENGINE_RUNTIME']) &&
103
+ $_SERVER['APPENGINE_RUNTIME'] == 'php';
104
+ if ($appEngineDevAppServer) {
105
+ return true;
106
+ }
107
+ return false;
108
+ }
109
+
110
+ /**
111
+ * Implements FetchAuthTokenInterface#fetchAuthToken.
112
+ *
113
+ * Fetches the auth tokens using the AppIdentityService if available.
114
+ * As the AppIdentityService uses protobufs to fetch the access token,
115
+ * the GuzzleHttp\ClientInterface instance passed in will not be used.
116
+ *
117
+ * @param callable $httpHandler callback which delivers psr7 request
118
+ * @return array A set of auth related metadata, containing the following
119
+ * keys:
120
+ * - access_token (string)
121
+ * - expiration_time (string)
122
+ */
123
+ public function fetchAuthToken(callable $httpHandler = null)
124
+ {
125
+ try {
126
+ $this->checkAppEngineContext();
127
+ } catch (\Exception $e) {
128
+ return [];
129
+ }
130
+
131
+ // AppIdentityService expects an array when multiple scopes are supplied
132
+ $scope = is_array($this->scope) ? $this->scope : explode(' ', $this->scope);
133
+
134
+ $token = AppIdentityService::getAccessToken($scope);
135
+ $this->lastReceivedToken = $token;
136
+
137
+ return $token;
138
+ }
139
+
140
+ /**
141
+ * Sign a string using AppIdentityService.
142
+ *
143
+ * @param string $stringToSign The string to sign.
144
+ * @param bool $forceOpenSsl [optional] Does not apply to this credentials
145
+ * type.
146
+ * @return string The signature, base64-encoded.
147
+ * @throws \Exception If AppEngine SDK or mock is not available.
148
+ */
149
+ public function signBlob($stringToSign, $forceOpenSsl = false)
150
+ {
151
+ $this->checkAppEngineContext();
152
+
153
+ return base64_encode(AppIdentityService::signForApp($stringToSign)['signature']);
154
+ }
155
+
156
+ /**
157
+ * Get the project ID from AppIdentityService.
158
+ *
159
+ * Returns null if AppIdentityService is unavailable.
160
+ *
161
+ * @param callable $httpHandler Not used by this type.
162
+ * @return string|null
163
+ */
164
+ public function getProjectId(callable $httpHander = null)
165
+ {
166
+ try {
167
+ $this->checkAppEngineContext();
168
+ } catch (\Exception $e) {
169
+ return null;
170
+ }
171
+
172
+ return AppIdentityService::getApplicationId();
173
+ }
174
+
175
+ /**
176
+ * Get the client name from AppIdentityService.
177
+ *
178
+ * Subsequent calls to this method will return a cached value.
179
+ *
180
+ * @param callable $httpHandler Not used in this implementation.
181
+ * @return string
182
+ * @throws \Exception If AppEngine SDK or mock is not available.
183
+ */
184
+ public function getClientName(callable $httpHandler = null)
185
+ {
186
+ $this->checkAppEngineContext();
187
+
188
+ if (!$this->clientName) {
189
+ $this->clientName = AppIdentityService::getServiceAccountName();
190
+ }
191
+
192
+ return $this->clientName;
193
+ }
194
+
195
+ /**
196
+ * @return array|null
197
+ */
198
+ public function getLastReceivedToken()
199
+ {
200
+ if ($this->lastReceivedToken) {
201
+ return [
202
+ 'access_token' => $this->lastReceivedToken['access_token'],
203
+ 'expires_at' => $this->lastReceivedToken['expiration_time'],
204
+ ];
205
+ }
206
+
207
+ return null;
208
+ }
209
+
210
+ /**
211
+ * Caching is handled by the underlying AppIdentityService, return empty string
212
+ * to prevent caching.
213
+ *
214
+ * @return string
215
+ */
216
+ public function getCacheKey()
217
+ {
218
+ return '';
219
+ }
220
+
221
+ private function checkAppEngineContext()
222
+ {
223
+ if (!self::onAppEngine() || !class_exists('google\appengine\api\app_identity\AppIdentityService')) {
224
+ throw new \Exception(
225
+ 'This class must be run in App Engine, or you must include the AppIdentityService '
226
+ . 'mock class defined in tests/mocks/AppIdentityService.php'
227
+ );
228
+ }
229
+ }
230
+ }
vendor/google/auth/src/Credentials/GCECredentials.php ADDED
@@ -0,0 +1,547 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2015 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth\Credentials;
19
+
20
+ use Google\Auth\CredentialsLoader;
21
+ use Google\Auth\GetQuotaProjectInterface;
22
+ use Google\Auth\HttpHandler\HttpClientCache;
23
+ use Google\Auth\HttpHandler\HttpHandlerFactory;
24
+ use Google\Auth\Iam;
25
+ use Google\Auth\ProjectIdProviderInterface;
26
+ use Google\Auth\SignBlobInterface;
27
+ use GuzzleHttp\Exception\ClientException;
28
+ use GuzzleHttp\Exception\ConnectException;
29
+ use GuzzleHttp\Exception\RequestException;
30
+ use GuzzleHttp\Exception\ServerException;
31
+ use GuzzleHttp\Psr7\Request;
32
+ use InvalidArgumentException;
33
+
34
+ /**
35
+ * GCECredentials supports authorization on Google Compute Engine.
36
+ *
37
+ * It can be used to authorize requests using the AuthTokenMiddleware, but will
38
+ * only succeed if being run on GCE:
39
+ *
40
+ * use Google\Auth\Credentials\GCECredentials;
41
+ * use Google\Auth\Middleware\AuthTokenMiddleware;
42
+ * use GuzzleHttp\Client;
43
+ * use GuzzleHttp\HandlerStack;
44
+ *
45
+ * $gce = new GCECredentials();
46
+ * $middleware = new AuthTokenMiddleware($gce);
47
+ * $stack = HandlerStack::create();
48
+ * $stack->push($middleware);
49
+ *
50
+ * $client = new Client([
51
+ * 'handler' => $stack,
52
+ * 'base_uri' => 'https://www.googleapis.com/taskqueue/v1beta2/projects/',
53
+ * 'auth' => 'google_auth'
54
+ * ]);
55
+ *
56
+ * $res = $client->get('myproject/taskqueues/myqueue');
57
+ */
58
+ class GCECredentials extends CredentialsLoader implements
59
+ SignBlobInterface,
60
+ ProjectIdProviderInterface,
61
+ GetQuotaProjectInterface
62
+ {
63
+ // phpcs:disable
64
+ const cacheKey = 'GOOGLE_AUTH_PHP_GCE';
65
+ // phpcs:enable
66
+
67
+ /**
68
+ * The metadata IP address on appengine instances.
69
+ *
70
+ * The IP is used instead of the domain 'metadata' to avoid slow responses
71
+ * when not on Compute Engine.
72
+ */
73
+ const METADATA_IP = '169.254.169.254';
74
+
75
+ /**
76
+ * The metadata path of the default token.
77
+ */
78
+ const TOKEN_URI_PATH = 'v1/instance/service-accounts/default/token';
79
+
80
+ /**
81
+ * The metadata path of the default id token.
82
+ */
83
+ const ID_TOKEN_URI_PATH = 'v1/instance/service-accounts/default/identity';
84
+
85
+ /**
86
+ * The metadata path of the client ID.
87
+ */
88
+ const CLIENT_ID_URI_PATH = 'v1/instance/service-accounts/default/email';
89
+
90
+ /**
91
+ * The metadata path of the project ID.
92
+ */
93
+ const PROJECT_ID_URI_PATH = 'v1/project/project-id';
94
+
95
+ /**
96
+ * The header whose presence indicates GCE presence.
97
+ */
98
+ const FLAVOR_HEADER = 'Metadata-Flavor';
99
+
100
+ /**
101
+ * Note: the explicit `timeout` and `tries` below is a workaround. The underlying
102
+ * issue is that resolving an unknown host on some networks will take
103
+ * 20-30 seconds; making this timeout short fixes the issue, but
104
+ * could lead to false negatives in the event that we are on GCE, but
105
+ * the metadata resolution was particularly slow. The latter case is
106
+ * "unlikely" since the expected 4-nines time is about 0.5 seconds.
107
+ * This allows us to limit the total ping maximum timeout to 1.5 seconds
108
+ * for developer desktop scenarios.
109
+ */
110
+ const MAX_COMPUTE_PING_TRIES = 3;
111
+ const COMPUTE_PING_CONNECTION_TIMEOUT_S = 0.5;
112
+
113
+ /**
114
+ * Flag used to ensure that the onGCE test is only done once;.
115
+ *
116
+ * @var bool
117
+ */
118
+ private $hasCheckedOnGce = false;
119
+
120
+ /**
121
+ * Flag that stores the value of the onGCE check.
122
+ *
123
+ * @var bool
124
+ */
125
+ private $isOnGce = false;
126
+
127
+ /**
128
+ * Result of fetchAuthToken.
129
+ */
130
+ protected $lastReceivedToken;
131
+
132
+ /**
133
+ * @var string|null
134
+ */
135
+ private $clientName;
136
+
137
+ /**
138
+ * @var string|null
139
+ */
140
+ private $projectId;
141
+
142
+ /**
143
+ * @var Iam|null
144
+ */
145
+ private $iam;
146
+
147
+ /**
148
+ * @var string
149
+ */
150
+ private $tokenUri;
151
+
152
+ /**
153
+ * @var string
154
+ */
155
+ private $targetAudience;
156
+
157
+ /**
158
+ * @var string|null
159
+ */
160
+ private $quotaProject;
161
+
162
+ /**
163
+ * @var string|null
164
+ */
165
+ private $serviceAccountIdentity;
166
+
167
+ /**
168
+ * @param Iam $iam [optional] An IAM instance.
169
+ * @param string|array $scope [optional] the scope of the access request,
170
+ * expressed either as an array or as a space-delimited string.
171
+ * @param string $targetAudience [optional] The audience for the ID token.
172
+ * @param string $quotaProject [optional] Specifies a project to bill for access
173
+ * charges associated with the request.
174
+ * @param string $serviceAccountIdentity [optional] Specify a service
175
+ * account identity name to use instead of "default".
176
+ */
177
+ public function __construct(
178
+ Iam $iam = null,
179
+ $scope = null,
180
+ $targetAudience = null,
181
+ $quotaProject = null,
182
+ $serviceAccountIdentity = null
183
+ ) {
184
+ $this->iam = $iam;
185
+
186
+ if ($scope && $targetAudience) {
187
+ throw new InvalidArgumentException(
188
+ 'Scope and targetAudience cannot both be supplied'
189
+ );
190
+ }
191
+
192
+ $tokenUri = self::getTokenUri($serviceAccountIdentity);
193
+ if ($scope) {
194
+ if (is_string($scope)) {
195
+ $scope = explode(' ', $scope);
196
+ }
197
+
198
+ $scope = implode(',', $scope);
199
+
200
+ $tokenUri = $tokenUri . '?scopes='. $scope;
201
+ } elseif ($targetAudience) {
202
+ $tokenUri = self::getIdTokenUri($serviceAccountIdentity);
203
+ $tokenUri = $tokenUri . '?audience='. $targetAudience;
204
+ $this->targetAudience = $targetAudience;
205
+ }
206
+
207
+ $this->tokenUri = $tokenUri;
208
+ $this->quotaProject = $quotaProject;
209
+ $this->serviceAccountIdentity = $serviceAccountIdentity;
210
+ }
211
+
212
+ /**
213
+ * The full uri for accessing the default token.
214
+ *
215
+ * @param string $serviceAccountIdentity [optional] Specify a service
216
+ * account identity name to use instead of "default".
217
+ * @return string
218
+ */
219
+ public static function getTokenUri($serviceAccountIdentity = null)
220
+ {
221
+ $base = 'http://' . self::METADATA_IP . '/computeMetadata/';
222
+ $base .= self::TOKEN_URI_PATH;
223
+
224
+ if ($serviceAccountIdentity) {
225
+ return str_replace(
226
+ '/default/',
227
+ '/' . $serviceAccountIdentity . '/',
228
+ $base
229
+ );
230
+ }
231
+ return $base;
232
+ }
233
+
234
+ /**
235
+ * The full uri for accessing the default service account.
236
+ *
237
+ * @param string $serviceAccountIdentity [optional] Specify a service
238
+ * account identity name to use instead of "default".
239
+ * @return string
240
+ */
241
+ public static function getClientNameUri($serviceAccountIdentity = null)
242
+ {
243
+ $base = 'http://' . self::METADATA_IP . '/computeMetadata/';
244
+ $base .= self::CLIENT_ID_URI_PATH;
245
+
246
+ if ($serviceAccountIdentity) {
247
+ return str_replace(
248
+ '/default/',
249
+ '/' . $serviceAccountIdentity . '/',
250
+ $base
251
+ );
252
+ }
253
+
254
+ return $base;
255
+ }
256
+
257
+ /**
258
+ * The full uri for accesesing the default identity token.
259
+ *
260
+ * @param string $serviceAccountIdentity [optional] Specify a service
261
+ * account identity name to use instead of "default".
262
+ * @return string
263
+ */
264
+ private static function getIdTokenUri($serviceAccountIdentity = null)
265
+ {
266
+ $base = 'http://' . self::METADATA_IP . '/computeMetadata/';
267
+ $base .= self::ID_TOKEN_URI_PATH;
268
+
269
+ if ($serviceAccountIdentity) {
270
+ return str_replace(
271
+ '/default/',
272
+ '/' . $serviceAccountIdentity . '/',
273
+ $base
274
+ );
275
+ }
276
+
277
+ return $base;
278
+ }
279
+
280
+ /**
281
+ * The full uri for accessing the default project ID.
282
+ *
283
+ * @return string
284
+ */
285
+ private static function getProjectIdUri()
286
+ {
287
+ $base = 'http://' . self::METADATA_IP . '/computeMetadata/';
288
+
289
+ return $base . self::PROJECT_ID_URI_PATH;
290
+ }
291
+
292
+ /**
293
+ * Determines if this an App Engine Flexible instance, by accessing the
294
+ * GAE_INSTANCE environment variable.
295
+ *
296
+ * @return bool true if this an App Engine Flexible Instance, false otherwise
297
+ */
298
+ public static function onAppEngineFlexible()
299
+ {
300
+ return substr(getenv('GAE_INSTANCE'), 0, 4) === 'aef-';
301
+ }
302
+
303
+ /**
304
+ * Determines if this a GCE instance, by accessing the expected metadata
305
+ * host.
306
+ * If $httpHandler is not specified a the default HttpHandler is used.
307
+ *
308
+ * @param callable $httpHandler callback which delivers psr7 request
309
+ * @return bool True if this a GCEInstance, false otherwise
310
+ */
311
+ public static function onGce(callable $httpHandler = null)
312
+ {
313
+ $httpHandler = $httpHandler
314
+ ?: HttpHandlerFactory::build(HttpClientCache::getHttpClient());
315
+
316
+ $checkUri = 'http://' . self::METADATA_IP;
317
+ for ($i = 1; $i <= self::MAX_COMPUTE_PING_TRIES; $i++) {
318
+ try {
319
+ // Comment from: oauth2client/client.py
320
+ //
321
+ // Note: the explicit `timeout` below is a workaround. The underlying
322
+ // issue is that resolving an unknown host on some networks will take
323
+ // 20-30 seconds; making this timeout short fixes the issue, but
324
+ // could lead to false negatives in the event that we are on GCE, but
325
+ // the metadata resolution was particularly slow. The latter case is
326
+ // "unlikely".
327
+ $resp = $httpHandler(
328
+ new Request(
329
+ 'GET',
330
+ $checkUri,
331
+ [self::FLAVOR_HEADER => 'Google']
332
+ ),
333
+ ['timeout' => self::COMPUTE_PING_CONNECTION_TIMEOUT_S]
334
+ );
335
+
336
+ return $resp->getHeaderLine(self::FLAVOR_HEADER) == 'Google';
337
+ } catch (ClientException $e) {
338
+ } catch (ServerException $e) {
339
+ } catch (RequestException $e) {
340
+ } catch (ConnectException $e) {
341
+ }
342
+ }
343
+ return false;
344
+ }
345
+
346
+ /**
347
+ * Implements FetchAuthTokenInterface#fetchAuthToken.
348
+ *
349
+ * Fetches the auth tokens from the GCE metadata host if it is available.
350
+ * If $httpHandler is not specified a the default HttpHandler is used.
351
+ *
352
+ * @param callable $httpHandler callback which delivers psr7 request
353
+ *
354
+ * @return array A set of auth related metadata, based on the token type.
355
+ *
356
+ * Access tokens have the following keys:
357
+ * - access_token (string)
358
+ * - expires_in (int)
359
+ * - token_type (string)
360
+ * ID tokens have the following keys:
361
+ * - id_token (string)
362
+ *
363
+ * @throws \Exception
364
+ */
365
+ public function fetchAuthToken(callable $httpHandler = null)
366
+ {
367
+ $httpHandler = $httpHandler
368
+ ?: HttpHandlerFactory::build(HttpClientCache::getHttpClient());
369
+
370
+ if (!$this->hasCheckedOnGce) {
371
+ $this->isOnGce = self::onGce($httpHandler);
372
+ $this->hasCheckedOnGce = true;
373
+ }
374
+ if (!$this->isOnGce) {
375
+ return array(); // return an empty array with no access token
376
+ }
377
+
378
+ $response = $this->getFromMetadata($httpHandler, $this->tokenUri);
379
+
380
+ if ($this->targetAudience) {
381
+ return ['id_token' => $response];
382
+ }
383
+
384
+ if (null === $json = json_decode($response, true)) {
385
+ throw new \Exception('Invalid JSON response');
386
+ }
387
+
388
+ $json['expires_at'] = time() + $json['expires_in'];
389
+
390
+ // store this so we can retrieve it later
391
+ $this->lastReceivedToken = $json;
392
+
393
+ return $json;
394
+ }
395
+
396
+ /**
397
+ * @return string
398
+ */
399
+ public function getCacheKey()
400
+ {
401
+ return self::cacheKey;
402
+ }
403
+
404
+ /**
405
+ * @return array|null
406
+ */
407
+ public function getLastReceivedToken()
408
+ {
409
+ if ($this->lastReceivedToken) {
410
+ return [
411
+ 'access_token' => $this->lastReceivedToken['access_token'],
412
+ 'expires_at' => $this->lastReceivedToken['expires_at'],
413
+ ];
414
+ }
415
+
416
+ return null;
417
+ }
418
+
419
+ /**
420
+ * Get the client name from GCE metadata.
421
+ *
422
+ * Subsequent calls will return a cached value.
423
+ *
424
+ * @param callable $httpHandler callback which delivers psr7 request
425
+ * @return string
426
+ */
427
+ public function getClientName(callable $httpHandler = null)
428
+ {
429
+ if ($this->clientName) {
430
+ return $this->clientName;
431
+ }
432
+
433
+ $httpHandler = $httpHandler
434
+ ?: HttpHandlerFactory::build(HttpClientCache::getHttpClient());
435
+
436
+ if (!$this->hasCheckedOnGce) {
437
+ $this->isOnGce = self::onGce($httpHandler);
438
+ $this->hasCheckedOnGce = true;
439
+ }
440
+
441
+ if (!$this->isOnGce) {
442
+ return '';
443
+ }
444
+
445
+ $this->clientName = $this->getFromMetadata(
446
+ $httpHandler,
447
+ self::getClientNameUri($this->serviceAccountIdentity)
448
+ );
449
+
450
+ return $this->clientName;
451
+ }
452
+
453
+ /**
454
+ * Sign a string using the default service account private key.
455
+ *
456
+ * This implementation uses IAM's signBlob API.
457
+ *
458
+ * @see https://cloud.google.com/iam/credentials/reference/rest/v1/projects.serviceAccounts/signBlob SignBlob
459
+ *
460
+ * @param string $stringToSign The string to sign.
461
+ * @param bool $forceOpenSsl [optional] Does not apply to this credentials
462
+ * type.
463
+ * @param string $accessToken The access token to use to sign the blob. If
464
+ * provided, saves a call to the metadata server for a new access
465
+ * token. **Defaults to** `null`.
466
+ * @return string
467
+ */
468
+ public function signBlob($stringToSign, $forceOpenSsl = false, $accessToken = null)
469
+ {
470
+ $httpHandler = HttpHandlerFactory::build(HttpClientCache::getHttpClient());
471
+
472
+ // Providing a signer is useful for testing, but it's undocumented
473
+ // because it's not something a user would generally need to do.
474
+ $signer = $this->iam ?: new Iam($httpHandler);
475
+
476
+ $email = $this->getClientName($httpHandler);
477
+
478
+ if (is_null($accessToken)) {
479
+ $previousToken = $this->getLastReceivedToken();
480
+ $accessToken = $previousToken
481
+ ? $previousToken['access_token']
482
+ : $this->fetchAuthToken($httpHandler)['access_token'];
483
+ }
484
+
485
+ return $signer->signBlob($email, $accessToken, $stringToSign);
486
+ }
487
+
488
+ /**
489
+ * Fetch the default Project ID from compute engine.
490
+ *
491
+ * Returns null if called outside GCE.
492
+ *
493
+ * @param callable $httpHandler Callback which delivers psr7 request
494
+ * @return string|null
495
+ */
496
+ public function getProjectId(callable $httpHandler = null)
497
+ {
498
+ if ($this->projectId) {
499
+ return $this->projectId;
500
+ }
501
+
502
+ $httpHandler = $httpHandler
503
+ ?: HttpHandlerFactory::build(HttpClientCache::getHttpClient());
504
+
505
+ if (!$this->hasCheckedOnGce) {
506
+ $this->isOnGce = self::onGce($httpHandler);
507
+ $this->hasCheckedOnGce = true;
508
+ }
509
+
510
+ if (!$this->isOnGce) {
511
+ return null;
512
+ }
513
+
514
+ $this->projectId = $this->getFromMetadata($httpHandler, self::getProjectIdUri());
515
+ return $this->projectId;
516
+ }
517
+
518
+ /**
519
+ * Fetch the value of a GCE metadata server URI.
520
+ *
521
+ * @param callable $httpHandler An HTTP Handler to deliver PSR7 requests.
522
+ * @param string $uri The metadata URI.
523
+ * @return string
524
+ */
525
+ private function getFromMetadata(callable $httpHandler, $uri)
526
+ {
527
+ $resp = $httpHandler(
528
+ new Request(
529
+ 'GET',
530
+ $uri,
531
+ [self::FLAVOR_HEADER => 'Google']
532
+ )
533
+ );
534
+
535
+ return (string) $resp->getBody();
536
+ }
537
+
538
+ /**
539
+ * Get the quota project used for this API request
540
+ *
541
+ * @return string|null
542
+ */
543
+ public function getQuotaProject()
544
+ {
545
+ return $this->quotaProject;
546
+ }
547
+ }
vendor/google/auth/src/Credentials/IAMCredentials.php ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2015 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth\Credentials;
19
+
20
+ /**
21
+ * Authenticates requests using IAM credentials.
22
+ */
23
+ class IAMCredentials
24
+ {
25
+ const SELECTOR_KEY = 'x-goog-iam-authority-selector';
26
+ const TOKEN_KEY = 'x-goog-iam-authorization-token';
27
+
28
+ /**
29
+ * @var string
30
+ */
31
+ private $selector;
32
+
33
+ /**
34
+ * @var string
35
+ */
36
+ private $token;
37
+
38
+ /**
39
+ * @param $selector string the IAM selector
40
+ * @param $token string the IAM token
41
+ */
42
+ public function __construct($selector, $token)
43
+ {
44
+ if (!is_string($selector)) {
45
+ throw new \InvalidArgumentException(
46
+ 'selector must be a string'
47
+ );
48
+ }
49
+ if (!is_string($token)) {
50
+ throw new \InvalidArgumentException(
51
+ 'token must be a string'
52
+ );
53
+ }
54
+
55
+ $this->selector = $selector;
56
+ $this->token = $token;
57
+ }
58
+
59
+ /**
60
+ * export a callback function which updates runtime metadata.
61
+ *
62
+ * @return array updateMetadata function
63
+ */
64
+ public function getUpdateMetadataFunc()
65
+ {
66
+ return array($this, 'updateMetadata');
67
+ }
68
+
69
+ /**
70
+ * Updates metadata with the appropriate header metadata.
71
+ *
72
+ * @param array $metadata metadata hashmap
73
+ * @param string $unusedAuthUri optional auth uri
74
+ * @param callable $httpHandler callback which delivers psr7 request
75
+ * Note: this param is unused here, only included here for
76
+ * consistency with other credentials class
77
+ *
78
+ * @return array updated metadata hashmap
79
+ */
80
+ public function updateMetadata(
81
+ $metadata,
82
+ $unusedAuthUri = null,
83
+ callable $httpHandler = null
84
+ ) {
85
+ $metadata_copy = $metadata;
86
+ $metadata_copy[self::SELECTOR_KEY] = $this->selector;
87
+ $metadata_copy[self::TOKEN_KEY] = $this->token;
88
+
89
+ return $metadata_copy;
90
+ }
91
+ }
vendor/google/auth/src/Credentials/InsecureCredentials.php ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2018 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth\Credentials;
19
+
20
+ use Google\Auth\FetchAuthTokenInterface;
21
+
22
+ /**
23
+ * Provides a set of credentials that will always return an empty access token.
24
+ * This is useful for APIs which do not require authentication, for local
25
+ * service emulators, and for testing.
26
+ */
27
+ class InsecureCredentials implements FetchAuthTokenInterface
28
+ {
29
+ /**
30
+ * @var array
31
+ */
32
+ private $token = [
33
+ 'access_token' => ''
34
+ ];
35
+
36
+ /**
37
+ * Fetches the auth token. In this case it returns an empty string.
38
+ *
39
+ * @param callable $httpHandler
40
+ * @return array A set of auth related metadata, containing the following
41
+ * keys:
42
+ * - access_token (string)
43
+ */
44
+ public function fetchAuthToken(callable $httpHandler = null)
45
+ {
46
+ return $this->token;
47
+ }
48
+
49
+ /**
50
+ * Returns the cache key. In this case it returns a null value, disabling
51
+ * caching.
52
+ *
53
+ * @return string|null
54
+ */
55
+ public function getCacheKey()
56
+ {
57
+ return null;
58
+ }
59
+
60
+ /**
61
+ * Fetches the last received token. In this case, it returns the same empty string
62
+ * auth token.
63
+ *
64
+ * @return array
65
+ */
66
+ public function getLastReceivedToken()
67
+ {
68
+ return $this->token;
69
+ }
70
+ }
vendor/google/auth/src/Credentials/ServiceAccountCredentials.php ADDED
@@ -0,0 +1,333 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2015 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth\Credentials;
19
+
20
+ use Google\Auth\CredentialsLoader;
21
+ use Google\Auth\GetQuotaProjectInterface;
22
+ use Google\Auth\OAuth2;
23
+ use Google\Auth\ProjectIdProviderInterface;
24
+ use Google\Auth\ServiceAccountSignerTrait;
25
+ use Google\Auth\SignBlobInterface;
26
+ use InvalidArgumentException;
27
+
28
+ /**
29
+ * ServiceAccountCredentials supports authorization using a Google service
30
+ * account.
31
+ *
32
+ * (cf https://developers.google.com/accounts/docs/OAuth2ServiceAccount)
33
+ *
34
+ * It's initialized using the json key file that's downloadable from developer
35
+ * console, which should contain a private_key and client_email fields that it
36
+ * uses.
37
+ *
38
+ * Use it with AuthTokenMiddleware to authorize http requests:
39
+ *
40
+ * use Google\Auth\Credentials\ServiceAccountCredentials;
41
+ * use Google\Auth\Middleware\AuthTokenMiddleware;
42
+ * use GuzzleHttp\Client;
43
+ * use GuzzleHttp\HandlerStack;
44
+ *
45
+ * $sa = new ServiceAccountCredentials(
46
+ * 'https://www.googleapis.com/auth/taskqueue',
47
+ * '/path/to/your/json/key_file.json'
48
+ * );
49
+ * $middleware = new AuthTokenMiddleware($sa);
50
+ * $stack = HandlerStack::create();
51
+ * $stack->push($middleware);
52
+ *
53
+ * $client = new Client([
54
+ * 'handler' => $stack,
55
+ * 'base_uri' => 'https://www.googleapis.com/taskqueue/v1beta2/projects/',
56
+ * 'auth' => 'google_auth' // authorize all requests
57
+ * ]);
58
+ *
59
+ * $res = $client->get('myproject/taskqueues/myqueue');
60
+ */
61
+ class ServiceAccountCredentials extends CredentialsLoader implements
62
+ GetQuotaProjectInterface,
63
+ SignBlobInterface,
64
+ ProjectIdProviderInterface
65
+ {
66
+ use ServiceAccountSignerTrait;
67
+
68
+ /**
69
+ * The OAuth2 instance used to conduct authorization.
70
+ *
71
+ * @var OAuth2
72
+ */
73
+ protected $auth;
74
+
75
+ /**
76
+ * The quota project associated with the JSON credentials
77
+ *
78
+ * @var string
79
+ */
80
+ protected $quotaProject;
81
+
82
+ /*
83
+ * @var string|null
84
+ */
85
+ protected $projectId;
86
+
87
+ /*
88
+ * @var array|null
89
+ */
90
+ private $lastReceivedJwtAccessToken;
91
+
92
+ /*
93
+ * @var bool
94
+ */
95
+ private $useJwtAccessWithScope = false;
96
+
97
+ /*
98
+ * @var ServiceAccountJwtAccessCredentials|null
99
+ */
100
+ private $jwtAccessCredentials;
101
+
102
+ /**
103
+ * Create a new ServiceAccountCredentials.
104
+ *
105
+ * @param string|array $scope the scope of the access request, expressed
106
+ * either as an Array or as a space-delimited String.
107
+ * @param string|array $jsonKey JSON credential file path or JSON credentials
108
+ * as an associative array
109
+ * @param string $sub an email address account to impersonate, in situations when
110
+ * the service account has been delegated domain wide access.
111
+ * @param string $targetAudience The audience for the ID token.
112
+ */
113
+ public function __construct(
114
+ $scope,
115
+ $jsonKey,
116
+ $sub = null,
117
+ $targetAudience = null
118
+ ) {
119
+ if (is_string($jsonKey)) {
120
+ if (!file_exists($jsonKey)) {
121
+ throw new \InvalidArgumentException('file does not exist');
122
+ }
123
+ $jsonKeyStream = file_get_contents($jsonKey);
124
+ if (!$jsonKey = json_decode($jsonKeyStream, true)) {
125
+ throw new \LogicException('invalid json for auth config');
126
+ }
127
+ }
128
+ if (!array_key_exists('client_email', $jsonKey)) {
129
+ throw new \InvalidArgumentException(
130
+ 'json key is missing the client_email field'
131
+ );
132
+ }
133
+ if (!array_key_exists('private_key', $jsonKey)) {
134
+ throw new \InvalidArgumentException(
135
+ 'json key is missing the private_key field'
136
+ );
137
+ }
138
+ if (array_key_exists('quota_project_id', $jsonKey)) {
139
+ $this->quotaProject = (string) $jsonKey['quota_project_id'];
140
+ }
141
+ if ($scope && $targetAudience) {
142
+ throw new InvalidArgumentException(
143
+ 'Scope and targetAudience cannot both be supplied'
144
+ );
145
+ }
146
+ $additionalClaims = [];
147
+ if ($targetAudience) {
148
+ $additionalClaims = ['target_audience' => $targetAudience];
149
+ }
150
+ $this->auth = new OAuth2([
151
+ 'audience' => self::TOKEN_CREDENTIAL_URI,
152
+ 'issuer' => $jsonKey['client_email'],
153
+ 'scope' => $scope,
154
+ 'signingAlgorithm' => 'RS256',
155
+ 'signingKey' => $jsonKey['private_key'],
156
+ 'sub' => $sub,
157
+ 'tokenCredentialUri' => self::TOKEN_CREDENTIAL_URI,
158
+ 'additionalClaims' => $additionalClaims,
159
+ ]);
160
+
161
+ $this->projectId = isset($jsonKey['project_id'])
162
+ ? $jsonKey['project_id']
163
+ : null;
164
+ }
165
+
166
+ /**
167
+ * When called, the ServiceAccountCredentials will use an instance of
168
+ * ServiceAccountJwtAccessCredentials to fetch (self-sign) an access token
169
+ * even when only scopes are supplied. Otherwise,
170
+ * ServiceAccountJwtAccessCredentials is only called when no scopes and an
171
+ * authUrl (audience) is suppled.
172
+ */
173
+ public function useJwtAccessWithScope()
174
+ {
175
+ $this->useJwtAccessWithScope = true;
176
+ }
177
+
178
+ /**
179
+ * @param callable $httpHandler
180
+ *
181
+ * @return array A set of auth related metadata, containing the following
182
+ * keys:
183
+ * - access_token (string)
184
+ * - expires_in (int)
185
+ * - token_type (string)
186
+ */
187
+ public function fetchAuthToken(callable $httpHandler = null)
188
+ {
189
+ if ($this->useJwtAccessWithScope) {
190
+ $jwtCreds = $this->createJwtAccessCredentials();
191
+
192
+ $accessToken = $jwtCreds->fetchAuthToken($httpHandler);
193
+
194
+ if ($lastReceivedToken = $jwtCreds->getLastReceivedToken()) {
195
+ // Keep self-signed JWTs in memory as the last received token
196
+ $this->lastReceivedJwtAccessToken = $lastReceivedToken;
197
+ }
198
+
199
+ return $accessToken;
200
+ }
201
+ return $this->auth->fetchAuthToken($httpHandler);
202
+ }
203
+
204
+ /**
205
+ * @return string
206
+ */
207
+ public function getCacheKey()
208
+ {
209
+ $key = $this->auth->getIssuer() . ':' . $this->auth->getCacheKey();
210
+ if ($sub = $this->auth->getSub()) {
211
+ $key .= ':' . $sub;
212
+ }
213
+
214
+ return $key;
215
+ }
216
+
217
+ /**
218
+ * @return array
219
+ */
220
+ public function getLastReceivedToken()
221
+ {
222
+ // If self-signed JWTs are being used, fetch the last received token
223
+ // from memory. Else, fetch it from OAuth2
224
+ return $this->useSelfSignedJwt()
225
+ ? $this->lastReceivedJwtAccessToken
226
+ : $this->auth->getLastReceivedToken();
227
+ }
228
+
229
+ /**
230
+ * Get the project ID from the service account keyfile.
231
+ *
232
+ * Returns null if the project ID does not exist in the keyfile.
233
+ *
234
+ * @param callable $httpHandler Not used by this credentials type.
235
+ * @return string|null
236
+ */
237
+ public function getProjectId(callable $httpHandler = null)
238
+ {
239
+ return $this->projectId;
240
+ }
241
+
242
+ /**
243
+ * Updates metadata with the authorization token.
244
+ *
245
+ * @param array $metadata metadata hashmap
246
+ * @param string $authUri optional auth uri
247
+ * @param callable $httpHandler callback which delivers psr7 request
248
+ * @return array updated metadata hashmap
249
+ */
250
+ public function updateMetadata(
251
+ $metadata,
252
+ $authUri = null,
253
+ callable $httpHandler = null
254
+ ) {
255
+ // scope exists. use oauth implementation
256
+ if (!$this->useSelfSignedJwt()) {
257
+ return parent::updateMetadata($metadata, $authUri, $httpHandler);
258
+ }
259
+
260
+ $jwtCreds = $this->createJwtAccessCredentials();
261
+ if ($this->auth->getScope()) {
262
+ // Prefer user-provided "scope" to "audience"
263
+ $updatedMetadata = $jwtCreds->updateMetadata($metadata, null, $httpHandler);
264
+ } else {
265
+ $updatedMetadata = $jwtCreds->updateMetadata($metadata, $authUri, $httpHandler);
266
+ }
267
+
268
+ if ($lastReceivedToken = $jwtCreds->getLastReceivedToken()) {
269
+ // Keep self-signed JWTs in memory as the last received token
270
+ $this->lastReceivedJwtAccessToken = $lastReceivedToken;
271
+ }
272
+
273
+ return $updatedMetadata;
274
+ }
275
+
276
+ private function createJwtAccessCredentials()
277
+ {
278
+ if (!$this->jwtAccessCredentials) {
279
+ // Create credentials for self-signing a JWT (JwtAccess)
280
+ $credJson = array(
281
+ 'private_key' => $this->auth->getSigningKey(),
282
+ 'client_email' => $this->auth->getIssuer(),
283
+ );
284
+ $this->jwtAccessCredentials = new ServiceAccountJwtAccessCredentials(
285
+ $credJson,
286
+ $this->auth->getScope()
287
+ );
288
+ }
289
+
290
+ return $this->jwtAccessCredentials;
291
+ }
292
+
293
+ /**
294
+ * @param string $sub an email address account to impersonate, in situations when
295
+ * the service account has been delegated domain wide access.
296
+ */
297
+ public function setSub($sub)
298
+ {
299
+ $this->auth->setSub($sub);
300
+ }
301
+
302
+ /**
303
+ * Get the client name from the keyfile.
304
+ *
305
+ * In this case, it returns the keyfile's client_email key.
306
+ *
307
+ * @param callable $httpHandler Not used by this credentials type.
308
+ * @return string
309
+ */
310
+ public function getClientName(callable $httpHandler = null)
311
+ {
312
+ return $this->auth->getIssuer();
313
+ }
314
+
315
+ /**
316
+ * Get the quota project used for this API request
317
+ *
318
+ * @return string|null
319
+ */
320
+ public function getQuotaProject()
321
+ {
322
+ return $this->quotaProject;
323
+ }
324
+
325
+ private function useSelfSignedJwt()
326
+ {
327
+ // When true, ServiceAccountCredentials will always use JwtAccess
328
+ if ($this->useJwtAccessWithScope) {
329
+ return true;
330
+ }
331
+ return is_null($this->auth->getScope());
332
+ }
333
+ }
vendor/google/auth/src/Credentials/ServiceAccountJwtAccessCredentials.php ADDED
@@ -0,0 +1,205 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2015 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth\Credentials;
19
+
20
+ use Google\Auth\CredentialsLoader;
21
+ use Google\Auth\GetQuotaProjectInterface;
22
+ use Google\Auth\OAuth2;
23
+ use Google\Auth\ProjectIdProviderInterface;
24
+ use Google\Auth\ServiceAccountSignerTrait;
25
+ use Google\Auth\SignBlobInterface;
26
+
27
+ /**
28
+ * Authenticates requests using Google's Service Account credentials via
29
+ * JWT Access.
30
+ *
31
+ * This class allows authorizing requests for service accounts directly
32
+ * from credentials from a json key file downloaded from the developer
33
+ * console (via 'Generate new Json Key'). It is not part of any OAuth2
34
+ * flow, rather it creates a JWT and sends that as a credential.
35
+ */
36
+ class ServiceAccountJwtAccessCredentials extends CredentialsLoader implements
37
+ GetQuotaProjectInterface,
38
+ SignBlobInterface,
39
+ ProjectIdProviderInterface
40
+ {
41
+ use ServiceAccountSignerTrait;
42
+
43
+ /**
44
+ * The OAuth2 instance used to conduct authorization.
45
+ *
46
+ * @var OAuth2
47
+ */
48
+ protected $auth;
49
+
50
+ /**
51
+ * The quota project associated with the JSON credentials
52
+ */
53
+ protected $quotaProject;
54
+
55
+ /**
56
+ * Create a new ServiceAccountJwtAccessCredentials.
57
+ *
58
+ * @param string|array $jsonKey JSON credential file path or JSON credentials
59
+ * as an associative array
60
+ * @param string|array $scope the scope of the access request, expressed
61
+ * either as an Array or as a space-delimited String.
62
+ */
63
+ public function __construct($jsonKey, $scope = null)
64
+ {
65
+ if (is_string($jsonKey)) {
66
+ if (!file_exists($jsonKey)) {
67
+ throw new \InvalidArgumentException('file does not exist');
68
+ }
69
+ $jsonKeyStream = file_get_contents($jsonKey);
70
+ if (!$jsonKey = json_decode($jsonKeyStream, true)) {
71
+ throw new \LogicException('invalid json for auth config');
72
+ }
73
+ }
74
+ if (!array_key_exists('client_email', $jsonKey)) {
75
+ throw new \InvalidArgumentException(
76
+ 'json key is missing the client_email field'
77
+ );
78
+ }
79
+ if (!array_key_exists('private_key', $jsonKey)) {
80
+ throw new \InvalidArgumentException(
81
+ 'json key is missing the private_key field'
82
+ );
83
+ }
84
+ if (array_key_exists('quota_project_id', $jsonKey)) {
85
+ $this->quotaProject = (string) $jsonKey['quota_project_id'];
86
+ }
87
+ $this->auth = new OAuth2([
88
+ 'issuer' => $jsonKey['client_email'],
89
+ 'sub' => $jsonKey['client_email'],
90
+ 'signingAlgorithm' => 'RS256',
91
+ 'signingKey' => $jsonKey['private_key'],
92
+ 'scope' => $scope,
93
+ ]);
94
+
95
+ $this->projectId = isset($jsonKey['project_id'])
96
+ ? $jsonKey['project_id']
97
+ : null;
98
+ }
99
+
100
+ /**
101
+ * Updates metadata with the authorization token.
102
+ *
103
+ * @param array $metadata metadata hashmap
104
+ * @param string $authUri optional auth uri
105
+ * @param callable $httpHandler callback which delivers psr7 request
106
+ * @return array updated metadata hashmap
107
+ */
108
+ public function updateMetadata(
109
+ $metadata,
110
+ $authUri = null,
111
+ callable $httpHandler = null
112
+ ) {
113
+ $scope = $this->auth->getScope();
114
+ if (empty($authUri) && empty($scope)) {
115
+ return $metadata;
116
+ }
117
+
118
+ $this->auth->setAudience($authUri);
119
+
120
+ return parent::updateMetadata($metadata, $authUri, $httpHandler);
121
+ }
122
+
123
+ /**
124
+ * Implements FetchAuthTokenInterface#fetchAuthToken.
125
+ *
126
+ * @param callable $httpHandler
127
+ *
128
+ * @return array|void A set of auth related metadata, containing the
129
+ * following keys:
130
+ * - access_token (string)
131
+ */
132
+ public function fetchAuthToken(callable $httpHandler = null)
133
+ {
134
+ $audience = $this->auth->getAudience();
135
+ $scope = $this->auth->getScope();
136
+ if (empty($audience) && empty($scope)) {
137
+ return null;
138
+ }
139
+
140
+ if (!empty($audience) && !empty($scope)) {
141
+ throw new \UnexpectedValueException(
142
+ 'Cannot sign both audience and scope in JwtAccess'
143
+ );
144
+ }
145
+
146
+ $access_token = $this->auth->toJwt();
147
+
148
+ // Set the self-signed access token in OAuth2 for getLastReceivedToken
149
+ $this->auth->setAccessToken($access_token);
150
+
151
+ return array('access_token' => $access_token);
152
+ }
153
+
154
+ /**
155
+ * @return string
156
+ */
157
+ public function getCacheKey()
158
+ {
159
+ return $this->auth->getCacheKey();
160
+ }
161
+
162
+ /**
163
+ * @return array
164
+ */
165
+ public function getLastReceivedToken()
166
+ {
167
+ return $this->auth->getLastReceivedToken();
168
+ }
169
+
170
+ /**
171
+ * Get the project ID from the service account keyfile.
172
+ *
173
+ * Returns null if the project ID does not exist in the keyfile.
174
+ *
175
+ * @param callable $httpHandler Not used by this credentials type.
176
+ * @return string|null
177
+ */
178
+ public function getProjectId(callable $httpHandler = null)
179
+ {
180
+ return $this->projectId;
181
+ }
182
+
183
+ /**
184
+ * Get the client name from the keyfile.
185
+ *
186
+ * In this case, it returns the keyfile's client_email key.
187
+ *
188
+ * @param callable $httpHandler Not used by this credentials type.
189
+ * @return string
190
+ */
191
+ public function getClientName(callable $httpHandler = null)
192
+ {
193
+ return $this->auth->getIssuer();
194
+ }
195
+
196
+ /**
197
+ * Get the quota project used for this API request
198
+ *
199
+ * @return string|null
200
+ */
201
+ public function getQuotaProject()
202
+ {
203
+ return $this->quotaProject;
204
+ }
205
+ }
vendor/google/auth/src/Credentials/UserRefreshCredentials.php ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2015 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth\Credentials;
19
+
20
+ use Google\Auth\CredentialsLoader;
21
+ use Google\Auth\GetQuotaProjectInterface;
22
+ use Google\Auth\OAuth2;
23
+
24
+ /**
25
+ * Authenticates requests using User Refresh credentials.
26
+ *
27
+ * This class allows authorizing requests from user refresh tokens.
28
+ *
29
+ * This the end of the result of a 3LO flow. E.g, the end result of
30
+ * 'gcloud auth login' saves a file with these contents in well known
31
+ * location
32
+ *
33
+ * @see [Application Default Credentials](http://goo.gl/mkAHpZ)
34
+ */
35
+ class UserRefreshCredentials extends CredentialsLoader implements GetQuotaProjectInterface
36
+ {
37
+ /**
38
+ * The OAuth2 instance used to conduct authorization.
39
+ *
40
+ * @var OAuth2
41
+ */
42
+ protected $auth;
43
+
44
+ /**
45
+ * The quota project associated with the JSON credentials
46
+ */
47
+ protected $quotaProject;
48
+
49
+ /**
50
+ * Create a new UserRefreshCredentials.
51
+ *
52
+ * @param string|array $scope the scope of the access request, expressed
53
+ * either as an Array or as a space-delimited String.
54
+ * @param string|array $jsonKey JSON credential file path or JSON credentials
55
+ * as an associative array
56
+ */
57
+ public function __construct(
58
+ $scope,
59
+ $jsonKey
60
+ ) {
61
+ if (is_string($jsonKey)) {
62
+ if (!file_exists($jsonKey)) {
63
+ throw new \InvalidArgumentException('file does not exist');
64
+ }
65
+ $jsonKeyStream = file_get_contents($jsonKey);
66
+ if (!$jsonKey = json_decode($jsonKeyStream, true)) {
67
+ throw new \LogicException('invalid json for auth config');
68
+ }
69
+ }
70
+ if (!array_key_exists('client_id', $jsonKey)) {
71
+ throw new \InvalidArgumentException(
72
+ 'json key is missing the client_id field'
73
+ );
74
+ }
75
+ if (!array_key_exists('client_secret', $jsonKey)) {
76
+ throw new \InvalidArgumentException(
77
+ 'json key is missing the client_secret field'
78
+ );
79
+ }
80
+ if (!array_key_exists('refresh_token', $jsonKey)) {
81
+ throw new \InvalidArgumentException(
82
+ 'json key is missing the refresh_token field'
83
+ );
84
+ }
85
+ $this->auth = new OAuth2([
86
+ 'clientId' => $jsonKey['client_id'],
87
+ 'clientSecret' => $jsonKey['client_secret'],
88
+ 'refresh_token' => $jsonKey['refresh_token'],
89
+ 'scope' => $scope,
90
+ 'tokenCredentialUri' => self::TOKEN_CREDENTIAL_URI,
91
+ ]);
92
+ if (array_key_exists('quota_project_id', $jsonKey)) {
93
+ $this->quotaProject = (string) $jsonKey['quota_project_id'];
94
+ }
95
+ }
96
+
97
+ /**
98
+ * @param callable $httpHandler
99
+ *
100
+ * @return array A set of auth related metadata, containing the following
101
+ * keys:
102
+ * - access_token (string)
103
+ * - expires_in (int)
104
+ * - scope (string)
105
+ * - token_type (string)
106
+ * - id_token (string)
107
+ */
108
+ public function fetchAuthToken(callable $httpHandler = null)
109
+ {
110
+ return $this->auth->fetchAuthToken($httpHandler);
111
+ }
112
+
113
+ /**
114
+ * @return string
115
+ */
116
+ public function getCacheKey()
117
+ {
118
+ return $this->auth->getClientId() . ':' . $this->auth->getCacheKey();
119
+ }
120
+
121
+ /**
122
+ * @return array
123
+ */
124
+ public function getLastReceivedToken()
125
+ {
126
+ return $this->auth->getLastReceivedToken();
127
+ }
128
+
129
+ /**
130
+ * Get the quota project used for this API request
131
+ *
132
+ * @return string|null
133
+ */
134
+ public function getQuotaProject()
135
+ {
136
+ return $this->quotaProject;
137
+ }
138
+ }
vendor/google/auth/src/CredentialsLoader.php ADDED
@@ -0,0 +1,250 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2015 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth;
19
+
20
+ use Google\Auth\Credentials\InsecureCredentials;
21
+ use Google\Auth\Credentials\ServiceAccountCredentials;
22
+ use Google\Auth\Credentials\UserRefreshCredentials;
23
+ use GuzzleHttp\ClientInterface;
24
+
25
+ /**
26
+ * CredentialsLoader contains the behaviour used to locate and find default
27
+ * credentials files on the file system.
28
+ */
29
+ abstract class CredentialsLoader implements
30
+ FetchAuthTokenInterface,
31
+ UpdateMetadataInterface
32
+ {
33
+ const TOKEN_CREDENTIAL_URI = 'https://oauth2.googleapis.com/token';
34
+ const ENV_VAR = 'GOOGLE_APPLICATION_CREDENTIALS';
35
+ const WELL_KNOWN_PATH = 'gcloud/application_default_credentials.json';
36
+ const NON_WINDOWS_WELL_KNOWN_PATH_BASE = '.config';
37
+
38
+ /**
39
+ * @param string $cause
40
+ * @return string
41
+ */
42
+ private static function unableToReadEnv($cause)
43
+ {
44
+ $msg = 'Unable to read the credential file specified by ';
45
+ $msg .= ' GOOGLE_APPLICATION_CREDENTIALS: ';
46
+ $msg .= $cause;
47
+
48
+ return $msg;
49
+ }
50
+
51
+ /**
52
+ * @return bool
53
+ */
54
+ private static function isOnWindows()
55
+ {
56
+ return strtoupper(substr(PHP_OS, 0, 3)) === 'WIN';
57
+ }
58
+
59
+ /**
60
+ * Returns the currently available major Guzzle version.
61
+ *
62
+ * @return int
63
+ */
64
+ private static function getGuzzleMajorVersion()
65
+ {
66
+ if (defined('GuzzleHttp\ClientInterface::MAJOR_VERSION')) {
67
+ return ClientInterface::MAJOR_VERSION;
68
+ }
69
+
70
+ if (defined('GuzzleHttp\ClientInterface::VERSION')) {
71
+ return (int) substr(ClientInterface::VERSION, 0, 1);
72
+ }
73
+
74
+ throw new \Exception('Version not supported');
75
+ }
76
+
77
+ /**
78
+ * Load a JSON key from the path specified in the environment.
79
+ *
80
+ * Load a JSON key from the path specified in the environment
81
+ * variable GOOGLE_APPLICATION_CREDENTIALS. Return null if
82
+ * GOOGLE_APPLICATION_CREDENTIALS is not specified.
83
+ *
84
+ * @return array|null JSON key | null
85
+ */
86
+ public static function fromEnv()
87
+ {
88
+ $path = getenv(self::ENV_VAR);
89
+ if (empty($path)) {
90
+ return;
91
+ }
92
+ if (!file_exists($path)) {
93
+ $cause = 'file ' . $path . ' does not exist';
94
+ throw new \DomainException(self::unableToReadEnv($cause));
95
+ }
96
+ $jsonKey = file_get_contents($path);
97
+ return json_decode($jsonKey, true);
98
+ }
99
+
100
+ /**
101
+ * Load a JSON key from a well known path.
102
+ *
103
+ * The well known path is OS dependent:
104
+ *
105
+ * * windows: %APPDATA%/gcloud/application_default_credentials.json
106
+ * * others: $HOME/.config/gcloud/application_default_credentials.json
107
+ *
108
+ * If the file does not exist, this returns null.
109
+ *
110
+ * @return array|null JSON key | null
111
+ */
112
+ public static function fromWellKnownFile()
113
+ {
114
+ $rootEnv = self::isOnWindows() ? 'APPDATA' : 'HOME';
115
+ $path = [getenv($rootEnv)];
116
+ if (!self::isOnWindows()) {
117
+ $path[] = self::NON_WINDOWS_WELL_KNOWN_PATH_BASE;
118
+ }
119
+ $path[] = self::WELL_KNOWN_PATH;
120
+ $path = implode(DIRECTORY_SEPARATOR, $path);
121
+ if (!file_exists($path)) {
122
+ return;
123
+ }
124
+ $jsonKey = file_get_contents($path);
125
+ return json_decode($jsonKey, true);
126
+ }
127
+
128
+ /**
129
+ * Create a new Credentials instance.
130
+ *
131
+ * @param string|array $scope the scope of the access request, expressed
132
+ * either as an Array or as a space-delimited String.
133
+ * @param array $jsonKey the JSON credentials.
134
+ * @param string|array $defaultScope The default scope to use if no
135
+ * user-defined scopes exist, expressed either as an Array or as a
136
+ * space-delimited string.
137
+ *
138
+ * @return ServiceAccountCredentials|UserRefreshCredentials
139
+ */
140
+ public static function makeCredentials(
141
+ $scope,
142
+ array $jsonKey,
143
+ $defaultScope = null
144
+ ) {
145
+ if (!array_key_exists('type', $jsonKey)) {
146
+ throw new \InvalidArgumentException('json key is missing the type field');
147
+ }
148
+
149
+ if ($jsonKey['type'] == 'service_account') {
150
+ // Do not pass $defaultScope to ServiceAccountCredentials
151
+ return new ServiceAccountCredentials($scope, $jsonKey);
152
+ }
153
+
154
+ if ($jsonKey['type'] == 'authorized_user') {
155
+ $anyScope = $scope ?: $defaultScope;
156
+ return new UserRefreshCredentials($anyScope, $jsonKey);
157
+ }
158
+
159
+ throw new \InvalidArgumentException('invalid value in the type field');
160
+ }
161
+
162
+ /**
163
+ * Create an authorized HTTP Client from an instance of FetchAuthTokenInterface.
164
+ *
165
+ * @param FetchAuthTokenInterface $fetcher is used to fetch the auth token
166
+ * @param array $httpClientOptions (optional) Array of request options to apply.
167
+ * @param callable $httpHandler (optional) http client to fetch the token.
168
+ * @param callable $tokenCallback (optional) function to be called when a new token is fetched.
169
+ * @return \GuzzleHttp\Client
170
+ */
171
+ public static function makeHttpClient(
172
+ FetchAuthTokenInterface $fetcher,
173
+ array $httpClientOptions = [],
174
+ callable $httpHandler = null,
175
+ callable $tokenCallback = null
176
+ ) {
177
+ if (self::getGuzzleMajorVersion() === 5) {
178
+ $client = new \GuzzleHttp\Client($httpClientOptions);
179
+ $client->setDefaultOption('auth', 'google_auth');
180
+ $subscriber = new Subscriber\AuthTokenSubscriber(
181
+ $fetcher,
182
+ $httpHandler,
183
+ $tokenCallback
184
+ );
185
+ $client->getEmitter()->attach($subscriber);
186
+ return $client;
187
+ }
188
+
189
+ $middleware = new Middleware\AuthTokenMiddleware(
190
+ $fetcher,
191
+ $httpHandler,
192
+ $tokenCallback
193
+ );
194
+ $stack = \GuzzleHttp\HandlerStack::create();
195
+ $stack->push($middleware);
196
+
197
+ return new \GuzzleHttp\Client([
198
+ 'handler' => $stack,
199
+ 'auth' => 'google_auth',
200
+ ] + $httpClientOptions);
201
+ }
202
+
203
+ /**
204
+ * Create a new instance of InsecureCredentials.
205
+ *
206
+ * @return InsecureCredentials
207
+ */
208
+ public static function makeInsecureCredentials()
209
+ {
210
+ return new InsecureCredentials();
211
+ }
212
+
213
+ /**
214
+ * export a callback function which updates runtime metadata.
215
+ *
216
+ * @return array updateMetadata function
217
+ * @deprecated
218
+ */
219
+ public function getUpdateMetadataFunc()
220
+ {
221
+ return array($this, 'updateMetadata');
222
+ }
223
+
224
+ /**
225
+ * Updates metadata with the authorization token.
226
+ *
227
+ * @param array $metadata metadata hashmap
228
+ * @param string $authUri optional auth uri
229
+ * @param callable $httpHandler callback which delivers psr7 request
230
+ * @return array updated metadata hashmap
231
+ */
232
+ public function updateMetadata(
233
+ $metadata,
234
+ $authUri = null,
235
+ callable $httpHandler = null
236
+ ) {
237
+ if (isset($metadata[self::AUTH_METADATA_KEY])) {
238
+ // Auth metadata has already been set
239
+ return $metadata;
240
+ }
241
+ $result = $this->fetchAuthToken($httpHandler);
242
+ if (!isset($result['access_token'])) {
243
+ return $metadata;
244
+ }
245
+ $metadata_copy = $metadata;
246
+ $metadata_copy[self::AUTH_METADATA_KEY] = array('Bearer ' . $result['access_token']);
247
+
248
+ return $metadata_copy;
249
+ }
250
+ }
vendor/google/auth/src/FetchAuthTokenCache.php ADDED
@@ -0,0 +1,278 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2010 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth;
19
+
20
+ use Psr\Cache\CacheItemPoolInterface;
21
+
22
+ /**
23
+ * A class to implement caching for any object implementing
24
+ * FetchAuthTokenInterface
25
+ */
26
+ class FetchAuthTokenCache implements
27
+ FetchAuthTokenInterface,
28
+ GetQuotaProjectInterface,
29
+ SignBlobInterface,
30
+ ProjectIdProviderInterface,
31
+ UpdateMetadataInterface
32
+ {
33
+ use CacheTrait;
34
+
35
+ /**
36
+ * @var FetchAuthTokenInterface
37
+ */
38
+ private $fetcher;
39
+
40
+ /**
41
+ * @var array
42
+ */
43
+ private $cacheConfig;
44
+
45
+ /**
46
+ * @var CacheItemPoolInterface
47
+ */
48
+ private $cache;
49
+
50
+ /**
51
+ * @param FetchAuthTokenInterface $fetcher A credentials fetcher
52
+ * @param array $cacheConfig Configuration for the cache
53
+ * @param CacheItemPoolInterface $cache
54
+ */
55
+ public function __construct(
56
+ FetchAuthTokenInterface $fetcher,
57
+ array $cacheConfig = null,
58
+ CacheItemPoolInterface $cache
59
+ ) {
60
+ $this->fetcher = $fetcher;
61
+ $this->cache = $cache;
62
+ $this->cacheConfig = array_merge([
63
+ 'lifetime' => 1500,
64
+ 'prefix' => '',
65
+ ], (array) $cacheConfig);
66
+ }
67
+
68
+ /**
69
+ * Implements FetchAuthTokenInterface#fetchAuthToken.
70
+ *
71
+ * Checks the cache for a valid auth token and fetches the auth tokens
72
+ * from the supplied fetcher.
73
+ *
74
+ * @param callable $httpHandler callback which delivers psr7 request
75
+ * @return array the response
76
+ * @throws \Exception
77
+ */
78
+ public function fetchAuthToken(callable $httpHandler = null)
79
+ {
80
+ if ($cached = $this->fetchAuthTokenFromCache()) {
81
+ return $cached;
82
+ }
83
+
84
+ $auth_token = $this->fetcher->fetchAuthToken($httpHandler);
85
+
86
+ $this->saveAuthTokenInCache($auth_token);
87
+
88
+ return $auth_token;
89
+ }
90
+
91
+ /**
92
+ * @return string
93
+ */
94
+ public function getCacheKey()
95
+ {
96
+ return $this->getFullCacheKey($this->fetcher->getCacheKey());
97
+ }
98
+
99
+ /**
100
+ * @return array|null
101
+ */
102
+ public function getLastReceivedToken()
103
+ {
104
+ return $this->fetcher->getLastReceivedToken();
105
+ }
106
+
107
+ /**
108
+ * Get the client name from the fetcher.
109
+ *
110
+ * @param callable $httpHandler An HTTP handler to deliver PSR7 requests.
111
+ * @return string
112
+ */
113
+ public function getClientName(callable $httpHandler = null)
114
+ {
115
+ if (!$this->fetcher instanceof SignBlobInterface) {
116
+ throw new \RuntimeException(
117
+ 'Credentials fetcher does not implement ' .
118
+ 'Google\Auth\SignBlobInterface'
119
+ );
120
+ }
121
+
122
+ return $this->fetcher->getClientName($httpHandler);
123
+ }
124
+
125
+ /**
126
+ * Sign a blob using the fetcher.
127
+ *
128
+ * @param string $stringToSign The string to sign.
129
+ * @param bool $forceOpenSsl Require use of OpenSSL for local signing. Does
130
+ * not apply to signing done using external services. **Defaults to**
131
+ * `false`.
132
+ * @return string The resulting signature.
133
+ * @throws \RuntimeException If the fetcher does not implement
134
+ * `Google\Auth\SignBlobInterface`.
135
+ */
136
+ public function signBlob($stringToSign, $forceOpenSsl = false)
137
+ {
138
+ if (!$this->fetcher instanceof SignBlobInterface) {
139
+ throw new \RuntimeException(
140
+ 'Credentials fetcher does not implement ' .
141
+ 'Google\Auth\SignBlobInterface'
142
+ );
143
+ }
144
+
145
+ // Pass the access token from cache to GCECredentials for signing a blob.
146
+ // This saves a call to the metadata server when a cached token exists.
147
+ if ($this->fetcher instanceof Credentials\GCECredentials) {
148
+ $cached = $this->fetchAuthTokenFromCache();
149
+ $accessToken = isset($cached['access_token']) ? $cached['access_token'] : null;
150
+ return $this->fetcher->signBlob($stringToSign, $forceOpenSsl, $accessToken);
151
+ }
152
+
153
+ return $this->fetcher->signBlob($stringToSign, $forceOpenSsl);
154
+ }
155
+
156
+ /**
157
+ * Get the quota project used for this API request from the credentials
158
+ * fetcher.
159
+ *
160
+ * @return string|null
161
+ */
162
+ public function getQuotaProject()
163
+ {
164
+ if ($this->fetcher instanceof GetQuotaProjectInterface) {
165
+ return $this->fetcher->getQuotaProject();
166
+ }
167
+ }
168
+
169
+ /*
170
+ * Get the Project ID from the fetcher.
171
+ *
172
+ * @param callable $httpHandler Callback which delivers psr7 request
173
+ * @return string|null
174
+ * @throws \RuntimeException If the fetcher does not implement
175
+ * `Google\Auth\ProvidesProjectIdInterface`.
176
+ */
177
+ public function getProjectId(callable $httpHandler = null)
178
+ {
179
+ if (!$this->fetcher instanceof ProjectIdProviderInterface) {
180
+ throw new \RuntimeException(
181
+ 'Credentials fetcher does not implement ' .
182
+ 'Google\Auth\ProvidesProjectIdInterface'
183
+ );
184
+ }
185
+
186
+ return $this->fetcher->getProjectId($httpHandler);
187
+ }
188
+
189
+ /**
190
+ * Updates metadata with the authorization token.
191
+ *
192
+ * @param array $metadata metadata hashmap
193
+ * @param string $authUri optional auth uri
194
+ * @param callable $httpHandler callback which delivers psr7 request
195
+ * @return array updated metadata hashmap
196
+ * @throws \RuntimeException If the fetcher does not implement
197
+ * `Google\Auth\UpdateMetadataInterface`.
198
+ */
199
+ public function updateMetadata(
200
+ $metadata,
201
+ $authUri = null,
202
+ callable $httpHandler = null
203
+ ) {
204
+ if (!$this->fetcher instanceof UpdateMetadataInterface) {
205
+ throw new \RuntimeException(
206
+ 'Credentials fetcher does not implement ' .
207
+ 'Google\Auth\UpdateMetadataInterface'
208
+ );
209
+ }
210
+
211
+ $cached = $this->fetchAuthTokenFromCache($authUri);
212
+ if ($cached) {
213
+ // Set the access token in the `Authorization` metadata header so
214
+ // the downstream call to updateMetadata know they don't need to
215
+ // fetch another token.
216
+ if (isset($cached['access_token'])) {
217
+ $metadata[self::AUTH_METADATA_KEY] = [
218
+ 'Bearer ' . $cached['access_token']
219
+ ];
220
+ }
221
+ }
222
+
223
+ $newMetadata = $this->fetcher->updateMetadata(
224
+ $metadata,
225
+ $authUri,
226
+ $httpHandler
227
+ );
228
+
229
+ if (!$cached && $token = $this->fetcher->getLastReceivedToken()) {
230
+ $this->saveAuthTokenInCache($token, $authUri);
231
+ }
232
+
233
+ return $newMetadata;
234
+ }
235
+
236
+ private function fetchAuthTokenFromCache($authUri = null)
237
+ {
238
+ // Use the cached value if its available.
239
+ //
240
+ // TODO: correct caching; update the call to setCachedValue to set the expiry
241
+ // to the value returned with the auth token.
242
+ //
243
+ // TODO: correct caching; enable the cache to be cleared.
244
+
245
+ // if $authUri is set, use it as the cache key
246
+ $cacheKey = $authUri
247
+ ? $this->getFullCacheKey($authUri)
248
+ : $this->fetcher->getCacheKey();
249
+
250
+ $cached = $this->getCachedValue($cacheKey);
251
+ if (is_array($cached)) {
252
+ if (empty($cached['expires_at'])) {
253
+ // If there is no expiration data, assume token is not expired.
254
+ // (for JwtAccess and ID tokens)
255
+ return $cached;
256
+ }
257
+ if (time() < $cached['expires_at']) {
258
+ // access token is not expired
259
+ return $cached;
260
+ }
261
+ }
262
+
263
+ return null;
264
+ }
265
+
266
+ private function saveAuthTokenInCache($authToken, $authUri = null)
267
+ {
268
+ if (isset($authToken['access_token']) ||
269
+ isset($authToken['id_token'])) {
270
+ // if $authUri is set, use it as the cache key
271
+ $cacheKey = $authUri
272
+ ? $this->getFullCacheKey($authUri)
273
+ : $this->fetcher->getCacheKey();
274
+
275
+ $this->setCachedValue($cacheKey, $authToken);
276
+ }
277
+ }
278
+ }
vendor/google/auth/src/FetchAuthTokenInterface.php ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2015 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth;
19
+
20
+ /**
21
+ * An interface implemented by objects that can fetch auth tokens.
22
+ */
23
+ interface FetchAuthTokenInterface
24
+ {
25
+ /**
26
+ * Fetches the auth tokens based on the current state.
27
+ *
28
+ * @param callable $httpHandler callback which delivers psr7 request
29
+ * @return array a hash of auth tokens
30
+ */
31
+ public function fetchAuthToken(callable $httpHandler = null);
32
+
33
+ /**
34
+ * Obtains a key that can used to cache the results of #fetchAuthToken.
35
+ *
36
+ * If the value is empty, the auth token is not cached.
37
+ *
38
+ * @return string a key that may be used to cache the auth token.
39
+ */
40
+ public function getCacheKey();
41
+
42
+ /**
43
+ * Returns an associative array with the token and
44
+ * expiration time.
45
+ *
46
+ * @return null|array {
47
+ * The last received access token.
48
+ *
49
+ * @var string $access_token The access token string.
50
+ * @var int $expires_at The time the token expires as a UNIX timestamp.
51
+ * }
52
+ */
53
+ public function getLastReceivedToken();
54
+ }
vendor/google/auth/src/GCECache.php ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2020 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth;
19
+
20
+ use Google\Auth\Credentials\GCECredentials;
21
+ use Psr\Cache\CacheItemPoolInterface;
22
+
23
+ /**
24
+ * A class to implement caching for calls to GCECredentials::onGce. This class
25
+ * is used automatically when you pass a `Psr\Cache\CacheItemPoolInterface`
26
+ * cache object to `ApplicationDefaultCredentials::getCredentials`.
27
+ *
28
+ * ```
29
+ * $sysvCache = new Google\Auth\SysvCacheItemPool();
30
+ * $creds = Google\Auth\ApplicationDefaultCredentials::getCredentials(
31
+ * $scope,
32
+ * null,
33
+ * null,
34
+ * $sysvCache
35
+ * );
36
+ * ```
37
+ */
38
+ class GCECache
39
+ {
40
+ const GCE_CACHE_KEY = 'google_auth_on_gce_cache';
41
+
42
+ use CacheTrait;
43
+
44
+ /**
45
+ * @var array
46
+ */
47
+ private $cacheConfig;
48
+
49
+ /**
50
+ * @var CacheItemPoolInterface
51
+ */
52
+ private $cache;
53
+
54
+ /**
55
+ * @param array $cacheConfig Configuration for the cache
56
+ * @param CacheItemPoolInterface $cache
57
+ */
58
+ public function __construct(
59
+ array $cacheConfig = null,
60
+ CacheItemPoolInterface $cache = null
61
+ ) {
62
+ $this->cache = $cache;
63
+ $this->cacheConfig = array_merge([
64
+ 'lifetime' => 1500,
65
+ 'prefix' => '',
66
+ ], (array) $cacheConfig);
67
+ }
68
+
69
+ /**
70
+ * Caches the result of onGce so the metadata server is not called multiple
71
+ * times.
72
+ *
73
+ * @param callable $httpHandler callback which delivers psr7 request
74
+ * @return bool True if this a GCEInstance, false otherwise
75
+ */
76
+ public function onGce(callable $httpHandler = null)
77
+ {
78
+ if (is_null($this->cache)) {
79
+ return GCECredentials::onGce($httpHandler);
80
+ }
81
+
82
+ $cacheKey = self::GCE_CACHE_KEY;
83
+ $onGce = $this->getCachedValue($cacheKey);
84
+
85
+ if (is_null($onGce)) {
86
+ $onGce = GCECredentials::onGce($httpHandler);
87
+ $this->setCachedValue($cacheKey, $onGce);
88
+ }
89
+
90
+ return $onGce;
91
+ }
92
+ }
vendor/google/auth/src/GetQuotaProjectInterface.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2019 Google LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth;
19
+
20
+ /**
21
+ * An interface implemented by objects that can get quota projects.
22
+ */
23
+ interface GetQuotaProjectInterface
24
+ {
25
+ const X_GOOG_USER_PROJECT_HEADER = 'X-Goog-User-Project';
26
+
27
+ /**
28
+ * Get the quota project used for this API request
29
+ *
30
+ * @return string|null
31
+ */
32
+ public function getQuotaProject();
33
+ }
vendor/google/auth/src/HttpHandler/Guzzle5HttpHandler.php ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2015 Google Inc. All Rights Reserved.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ namespace Google\Auth\HttpHandler;
18
+
19
+ use Exception;
20
+ use GuzzleHttp\ClientInterface;
21
+ use GuzzleHttp\Message\ResponseInterface as Guzzle5ResponseInterface;
22
+ use GuzzleHttp\Promise\Promise;
23
+ use GuzzleHttp\Promise\RejectedPromise;
24
+ use GuzzleHttp\Psr7\Response;
25
+ use Psr\Http\Message\RequestInterface;
26
+ use Psr\Http\Message\ResponseInterface;
27
+
28
+ class Guzzle5HttpHandler
29
+ {
30
+ /**
31
+ * @var ClientInterface
32
+ */
33
+ private $client;
34
+
35
+ /**
36
+ * @param ClientInterface $client
37
+ */
38
+ public function __construct(ClientInterface $client)
39
+ {
40
+ $this->client = $client;
41
+ }
42
+
43
+ /**
44
+ * Accepts a PSR-7 Request and an array of options and returns a PSR-7 response.
45
+ *
46
+ * @param RequestInterface $request
47
+ * @param array $options
48
+ * @return ResponseInterface
49
+ */
50
+ public function __invoke(RequestInterface $request, array $options = [])
51
+ {
52
+ $response = $this->client->send(
53
+ $this->createGuzzle5Request($request, $options)
54
+ );
55
+
56
+ return $this->createPsr7Response($response);
57
+ }
58
+
59
+ /**
60
+ * Accepts a PSR-7 request and an array of options and returns a PromiseInterface
61
+ *
62
+ * @param RequestInterface $request
63
+ * @param array $options
64
+ * @return Promise
65
+ */
66
+ public function async(RequestInterface $request, array $options = [])
67
+ {
68
+ if (!class_exists('GuzzleHttp\Promise\Promise')) {
69
+ throw new Exception('Install guzzlehttp/promises to use async with Guzzle 5');
70
+ }
71
+
72
+ $futureResponse = $this->client->send(
73
+ $this->createGuzzle5Request(
74
+ $request,
75
+ ['future' => true] + $options
76
+ )
77
+ );
78
+
79
+ $promise = new Promise(
80
+ function () use ($futureResponse) {
81
+ try {
82
+ $futureResponse->wait();
83
+ } catch (Exception $e) {
84
+ // The promise is already delivered when the exception is
85
+ // thrown, so don't rethrow it.
86
+ }
87
+ },
88
+ [$futureResponse, 'cancel']
89
+ );
90
+
91
+ $futureResponse->then([$promise, 'resolve'], [$promise, 'reject']);
92
+
93
+ return $promise->then(
94
+ function (Guzzle5ResponseInterface $response) {
95
+ // Adapt the Guzzle 5 Response to a PSR-7 Response.
96
+ return $this->createPsr7Response($response);
97
+ },
98
+ function (Exception $e) {
99
+ return new RejectedPromise($e);
100
+ }
101
+ );
102
+ }
103
+
104
+ private function createGuzzle5Request(RequestInterface $request, array $options)
105
+ {
106
+ return $this->client->createRequest(
107
+ $request->getMethod(),
108
+ $request->getUri(),
109
+ array_merge_recursive([
110
+ 'headers' => $request->getHeaders(),
111
+ 'body' => $request->getBody(),
112
+ ], $options)
113
+ );
114
+ }
115
+
116
+ private function createPsr7Response(Guzzle5ResponseInterface $response)
117
+ {
118
+ return new Response(
119
+ $response->getStatusCode(),
120
+ $response->getHeaders() ?: [],
121
+ $response->getBody(),
122
+ $response->getProtocolVersion(),
123
+ $response->getReasonPhrase()
124
+ );
125
+ }
126
+ }
vendor/google/auth/src/HttpHandler/Guzzle6HttpHandler.php ADDED
@@ -0,0 +1,62 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2015 Google Inc. All Rights Reserved.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ namespace Google\Auth\HttpHandler;
18
+
19
+ use GuzzleHttp\ClientInterface;
20
+ use Psr\Http\Message\RequestInterface;
21
+ use Psr\Http\Message\ResponseInterface;
22
+
23
+ class Guzzle6HttpHandler
24
+ {
25
+ /**
26
+ * @var ClientInterface
27
+ */
28
+ private $client;
29
+
30
+ /**
31
+ * @param ClientInterface $client
32
+ */
33
+ public function __construct(ClientInterface $client)
34
+ {
35
+ $this->client = $client;
36
+ }
37
+
38
+ /**
39
+ * Accepts a PSR-7 request and an array of options and returns a PSR-7 response.
40
+ *
41
+ * @param RequestInterface $request
42
+ * @param array $options
43
+ * @return ResponseInterface
44
+ */
45
+ public function __invoke(RequestInterface $request, array $options = [])
46
+ {
47
+ return $this->client->send($request, $options);
48
+ }
49
+
50
+ /**
51
+ * Accepts a PSR-7 request and an array of options and returns a PromiseInterface
52
+ *
53
+ * @param RequestInterface $request
54
+ * @param array $options
55
+ *
56
+ * @return \GuzzleHttp\Promise\PromiseInterface
57
+ */
58
+ public function async(RequestInterface $request, array $options = [])
59
+ {
60
+ return $this->client->sendAsync($request, $options);
61
+ }
62
+ }
vendor/google/auth/src/HttpHandler/Guzzle7HttpHandler.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2020 Google LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ namespace Google\Auth\HttpHandler;
18
+
19
+ class Guzzle7HttpHandler extends Guzzle6HttpHandler
20
+ {
21
+ }
vendor/google/auth/src/HttpHandler/HttpClientCache.php ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2019 Google LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth\HttpHandler;
19
+
20
+ use GuzzleHttp\ClientInterface;
21
+
22
+ /**
23
+ * Stores an HTTP Client in order to prevent multiple instantiations.
24
+ */
25
+ class HttpClientCache
26
+ {
27
+ /**
28
+ * @var ClientInterface|null
29
+ */
30
+ private static $httpClient;
31
+
32
+ /**
33
+ * Cache an HTTP Client for later calls.
34
+ *
35
+ * Passing null will unset the cached client.
36
+ *
37
+ * @param ClientInterface|null $client
38
+ * @return void
39
+ */
40
+ public static function setHttpClient(ClientInterface $client = null)
41
+ {
42
+ self::$httpClient = $client;
43
+ }
44
+
45
+ /**
46
+ * Get the stored HTTP Client, or null.
47
+ *
48
+ * @return ClientInterface|null
49
+ */
50
+ public static function getHttpClient()
51
+ {
52
+ return self::$httpClient;
53
+ }
54
+ }
vendor/google/auth/src/HttpHandler/HttpHandlerFactory.php ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Copyright 2015 Google Inc. All Rights Reserved.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ namespace Google\Auth\HttpHandler;
18
+
19
+ use GuzzleHttp\Client;
20
+ use GuzzleHttp\ClientInterface;
21
+
22
+ class HttpHandlerFactory
23
+ {
24
+ /**
25
+ * Builds out a default http handler for the installed version of guzzle.
26
+ *
27
+ * @param ClientInterface $client
28
+ * @return Guzzle5HttpHandler|Guzzle6HttpHandler|Guzzle7HttpHandler
29
+ * @throws \Exception
30
+ */
31
+ public static function build(ClientInterface $client = null)
32
+ {
33
+ $client = $client ?: new Client();
34
+
35
+ $version = null;
36
+ if (defined('GuzzleHttp\ClientInterface::MAJOR_VERSION')) {
37
+ $version = ClientInterface::MAJOR_VERSION;
38
+ } elseif (defined('GuzzleHttp\ClientInterface::VERSION')) {
39
+ $version = (int) substr(ClientInterface::VERSION, 0, 1);
40
+ }
41
+
42
+ switch ($version) {
43
+ case 5:
44
+ return new Guzzle5HttpHandler($client);
45
+ case 6:
46
+ return new Guzzle6HttpHandler($client);
47
+ case 7:
48
+ return new Guzzle7HttpHandler($client);
49
+ default:
50
+ throw new \Exception('Version not supported');
51
+ }
52
+ }
53
+ }
vendor/google/auth/src/Iam.php ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2019 Google LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth;
19
+
20
+ use Google\Auth\HttpHandler\HttpClientCache;
21
+ use Google\Auth\HttpHandler\HttpHandlerFactory;
22
+ use GuzzleHttp\Psr7;
23
+
24
+ /**
25
+ * Tools for using the IAM API.
26
+ *
27
+ * @see https://cloud.google.com/iam/docs IAM Documentation
28
+ */
29
+ class Iam
30
+ {
31
+ const IAM_API_ROOT = 'https://iamcredentials.googleapis.com/v1';
32
+ const SIGN_BLOB_PATH = '%s:signBlob?alt=json';
33
+ const SERVICE_ACCOUNT_NAME = 'projects/-/serviceAccounts/%s';
34
+
35
+ /**
36
+ * @var callable
37
+ */
38
+ private $httpHandler;
39
+
40
+ /**
41
+ * @param callable $httpHandler [optional] The HTTP Handler to send requests.
42
+ */
43
+ public function __construct(callable $httpHandler = null)
44
+ {
45
+ $this->httpHandler = $httpHandler
46
+ ?: HttpHandlerFactory::build(HttpClientCache::getHttpClient());
47
+ }
48
+
49
+ /**
50
+ * Sign a string using the IAM signBlob API.
51
+ *
52
+ * Note that signing using IAM requires your service account to have the
53
+ * `iam.serviceAccounts.signBlob` permission, part of the "Service Account
54
+ * Token Creator" IAM role.
55
+ *
56
+ * @param string $email The service account email.
57
+ * @param string $accessToken An access token from the service account.
58
+ * @param string $stringToSign The string to be signed.
59
+ * @param array $delegates [optional] A list of service account emails to
60
+ * add to the delegate chain. If omitted, the value of `$email` will
61
+ * be used.
62
+ * @return string The signed string, base64-encoded.
63
+ */
64
+ public function signBlob($email, $accessToken, $stringToSign, array $delegates = [])
65
+ {
66
+ $httpHandler = $this->httpHandler;
67
+ $name = sprintf(self::SERVICE_ACCOUNT_NAME, $email);
68
+ $uri = self::IAM_API_ROOT . '/' . sprintf(self::SIGN_BLOB_PATH, $name);
69
+
70
+ if ($delegates) {
71
+ foreach ($delegates as &$delegate) {
72
+ $delegate = sprintf(self::SERVICE_ACCOUNT_NAME, $delegate);
73
+ }
74
+ } else {
75
+ $delegates = [$name];
76
+ }
77
+
78
+ $body = [
79
+ 'delegates' => $delegates,
80
+ 'payload' => base64_encode($stringToSign),
81
+ ];
82
+
83
+ $headers = [
84
+ 'Authorization' => 'Bearer ' . $accessToken
85
+ ];
86
+
87
+ $request = new Psr7\Request(
88
+ 'POST',
89
+ $uri,
90
+ $headers,
91
+ Psr7\stream_for(json_encode($body))
92
+ );
93
+
94
+ $res = $httpHandler($request);
95
+ $body = json_decode((string) $res->getBody(), true);
96
+
97
+ return $body['signedBlob'];
98
+ }
99
+ }
vendor/google/auth/src/Middleware/AuthTokenMiddleware.php ADDED
@@ -0,0 +1,148 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2015 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth\Middleware;
19
+
20
+ use Google\Auth\FetchAuthTokenInterface;
21
+ use Google\Auth\GetQuotaProjectInterface;
22
+ use Psr\Http\Message\RequestInterface;
23
+
24
+ /**
25
+ * AuthTokenMiddleware is a Guzzle Middleware that adds an Authorization header
26
+ * provided by an object implementing FetchAuthTokenInterface.
27
+ *
28
+ * The FetchAuthTokenInterface#fetchAuthToken is used to obtain a hash; one of
29
+ * the values value in that hash is added as the authorization header.
30
+ *
31
+ * Requests will be accessed with the authorization header:
32
+ *
33
+ * 'authorization' 'Bearer <value of auth_token>'
34
+ */
35
+ class AuthTokenMiddleware
36
+ {
37
+ /**
38
+ * @var callback
39
+ */
40
+ private $httpHandler;
41
+
42
+ /**
43
+ * @var FetchAuthTokenInterface
44
+ */
45
+ private $fetcher;
46
+
47
+ /**
48
+ * @var callable
49
+ */
50
+ private $tokenCallback;
51
+
52
+ /**
53
+ * Creates a new AuthTokenMiddleware.
54
+ *
55
+ * @param FetchAuthTokenInterface $fetcher is used to fetch the auth token
56
+ * @param callable $httpHandler (optional) callback which delivers psr7 request
57
+ * @param callable $tokenCallback (optional) function to be called when a new token is fetched.
58
+ */
59
+ public function __construct(
60
+ FetchAuthTokenInterface $fetcher,
61
+ callable $httpHandler = null,
62
+ callable $tokenCallback = null
63
+ ) {
64
+ $this->fetcher = $fetcher;
65
+ $this->httpHandler = $httpHandler;
66
+ $this->tokenCallback = $tokenCallback;
67
+ }
68
+
69
+ /**
70
+ * Updates the request with an Authorization header when auth is 'google_auth'.
71
+ *
72
+ * use Google\Auth\Middleware\AuthTokenMiddleware;
73
+ * use Google\Auth\OAuth2;
74
+ * use GuzzleHttp\Client;
75
+ * use GuzzleHttp\HandlerStack;
76
+ *
77
+ * $config = [..<oauth config param>.];
78
+ * $oauth2 = new OAuth2($config)
79
+ * $middleware = new AuthTokenMiddleware($oauth2);
80
+ * $stack = HandlerStack::create();
81
+ * $stack->push($middleware);
82
+ *
83
+ * $client = new Client([
84
+ * 'handler' => $stack,
85
+ * 'base_uri' => 'https://www.googleapis.com/taskqueue/v1beta2/projects/',
86
+ * 'auth' => 'google_auth' // authorize all requests
87
+ * ]);
88
+ *
89
+ * $res = $client->get('myproject/taskqueues/myqueue');
90
+ *
91
+ * @param callable $handler
92
+ * @return \Closure
93
+ */
94
+ public function __invoke(callable $handler)
95
+ {
96
+ return function (RequestInterface $request, array $options) use ($handler) {
97
+ // Requests using "auth"="google_auth" will be authorized.
98
+ if (!isset($options['auth']) || $options['auth'] !== 'google_auth') {
99
+ return $handler($request, $options);
100
+ }
101
+
102
+ $request = $request->withHeader('authorization', 'Bearer ' . $this->fetchToken());
103
+
104
+ if ($quotaProject = $this->getQuotaProject()) {
105
+ $request = $request->withHeader(
106
+ GetQuotaProjectInterface::X_GOOG_USER_PROJECT_HEADER,
107
+ $quotaProject
108
+ );
109
+ }
110
+
111
+ return $handler($request, $options);
112
+ };
113
+ }
114
+
115
+ /**
116
+ * Call fetcher to fetch the token.
117
+ *
118
+ * @return string
119
+ */
120
+ private function fetchToken()
121
+ {
122
+ $auth_tokens = $this->fetcher->fetchAuthToken($this->httpHandler);
123
+
124
+ if (array_key_exists('access_token', $auth_tokens)) {
125
+ // notify the callback if applicable
126
+ if ($this->tokenCallback) {
127
+ call_user_func(
128
+ $this->tokenCallback,
129
+ $this->fetcher->getCacheKey(),
130
+ $auth_tokens['access_token']
131
+ );
132
+ }
133
+
134
+ return $auth_tokens['access_token'];
135
+ }
136
+
137
+ if (array_key_exists('id_token', $auth_tokens)) {
138
+ return $auth_tokens['id_token'];
139
+ }
140
+ }
141
+
142
+ private function getQuotaProject()
143
+ {
144
+ if ($this->fetcher instanceof GetQuotaProjectInterface) {
145
+ return $this->fetcher->getQuotaProject();
146
+ }
147
+ }
148
+ }
vendor/google/auth/src/Middleware/ScopedAccessTokenMiddleware.php ADDED
@@ -0,0 +1,175 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2015 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth\Middleware;
19
+
20
+ use Google\Auth\CacheTrait;
21
+ use Psr\Cache\CacheItemPoolInterface;
22
+ use Psr\Http\Message\RequestInterface;
23
+
24
+ /**
25
+ * ScopedAccessTokenMiddleware is a Guzzle Middleware that adds an Authorization
26
+ * header provided by a closure.
27
+ *
28
+ * The closure returns an access token, taking the scope, either a single
29
+ * string or an array of strings, as its value. If provided, a cache will be
30
+ * used to preserve the access token for a given lifetime.
31
+ *
32
+ * Requests will be accessed with the authorization header:
33
+ *
34
+ * 'authorization' 'Bearer <value of auth_token>'
35
+ */
36
+ class ScopedAccessTokenMiddleware
37
+ {
38
+ use CacheTrait;
39
+
40
+ const DEFAULT_CACHE_LIFETIME = 1500;
41
+
42
+ /**
43
+ * @var CacheItemPoolInterface
44
+ */
45
+ private $cache;
46
+
47
+ /**
48
+ * @var array configuration
49
+ */
50
+ private $cacheConfig;
51
+
52
+ /**
53
+ * @var callable
54
+ */
55
+ private $tokenFunc;
56
+
57
+ /**
58
+ * @var array|string
59
+ */
60
+ private $scopes;
61
+
62
+ /**
63
+ * Creates a new ScopedAccessTokenMiddleware.
64
+ *
65
+ * @param callable $tokenFunc a token generator function
66
+ * @param array|string $scopes the token authentication scopes
67
+ * @param array $cacheConfig configuration for the cache when it's present
68
+ * @param CacheItemPoolInterface $cache an implementation of CacheItemPoolInterface
69
+ */
70
+ public function __construct(
71
+ callable $tokenFunc,
72
+ $scopes,
73
+ array $cacheConfig = null,
74
+ CacheItemPoolInterface $cache = null
75
+ ) {
76
+ $this->tokenFunc = $tokenFunc;
77
+ if (!(is_string($scopes) || is_array($scopes))) {
78
+ throw new \InvalidArgumentException(
79
+ 'wants scope should be string or array'
80
+ );
81
+ }
82
+ $this->scopes = $scopes;
83
+
84
+ if (!is_null($cache)) {
85
+ $this->cache = $cache;
86
+ $this->cacheConfig = array_merge([
87
+ 'lifetime' => self::DEFAULT_CACHE_LIFETIME,
88
+ 'prefix' => '',
89
+ ], $cacheConfig);
90
+ }
91
+ }
92
+
93
+ /**
94
+ * Updates the request with an Authorization header when auth is 'scoped'.
95
+ *
96
+ * E.g this could be used to authenticate using the AppEngine
97
+ * AppIdentityService.
98
+ *
99
+ * use google\appengine\api\app_identity\AppIdentityService;
100
+ * use Google\Auth\Middleware\ScopedAccessTokenMiddleware;
101
+ * use GuzzleHttp\Client;
102
+ * use GuzzleHttp\HandlerStack;
103
+ *
104
+ * $scope = 'https://www.googleapis.com/auth/taskqueue'
105
+ * $middleware = new ScopedAccessTokenMiddleware(
106
+ * 'AppIdentityService::getAccessToken',
107
+ * $scope,
108
+ * [ 'prefix' => 'Google\Auth\ScopedAccessToken::' ],
109
+ * $cache = new Memcache()
110
+ * );
111
+ * $stack = HandlerStack::create();
112
+ * $stack->push($middleware);
113
+ *
114
+ * $client = new Client([
115
+ * 'handler' => $stack,
116
+ * 'base_url' => 'https://www.googleapis.com/taskqueue/v1beta2/projects/',
117
+ * 'auth' => 'scoped' // authorize all requests
118
+ * ]);
119
+ *
120
+ * $res = $client->get('myproject/taskqueues/myqueue');
121
+ *
122
+ * @param callable $handler
123
+ * @return \Closure
124
+ */
125
+ public function __invoke(callable $handler)
126
+ {
127
+ return function (RequestInterface $request, array $options) use ($handler) {
128
+ // Requests using "auth"="scoped" will be authorized.
129
+ if (!isset($options['auth']) || $options['auth'] !== 'scoped') {
130
+ return $handler($request, $options);
131
+ }
132
+
133
+ $request = $request->withHeader('authorization', 'Bearer ' . $this->fetchToken());
134
+
135
+ return $handler($request, $options);
136
+ };
137
+ }
138
+
139
+ /**
140
+ * @return string
141
+ */
142
+ private function getCacheKey()
143
+ {
144
+ $key = null;
145
+
146
+ if (is_string($this->scopes)) {
147
+ $key .= $this->scopes;
148
+ } elseif (is_array($this->scopes)) {
149
+ $key .= implode(':', $this->scopes);
150
+ }
151
+
152
+ return $key;
153
+ }
154
+
155
+ /**
156
+ * Determine if token is available in the cache, if not call tokenFunc to
157
+ * fetch it.
158
+ *
159
+ * @return string
160
+ */
161
+ private function fetchToken()
162
+ {
163
+ $cacheKey = $this->getCacheKey();
164
+ $cached = $this->getCachedValue($cacheKey);
165
+
166
+ if (!empty($cached)) {
167
+ return $cached;
168
+ }
169
+
170
+ $token = call_user_func($this->tokenFunc, $this->scopes);
171
+ $this->setCachedValue($cacheKey, $token);
172
+
173
+ return $token;
174
+ }
175
+ }
vendor/google/auth/src/Middleware/SimpleMiddleware.php ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2015 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth\Middleware;
19
+
20
+ use GuzzleHttp\Psr7;
21
+ use Psr\Http\Message\RequestInterface;
22
+
23
+ /**
24
+ * SimpleMiddleware is a Guzzle Middleware that implements Google's Simple API
25
+ * access.
26
+ *
27
+ * Requests are accessed using the Simple API access developer key.
28
+ */
29
+ class SimpleMiddleware
30
+ {
31
+ /**
32
+ * @var array
33
+ */
34
+ private $config;
35
+
36
+ /**
37
+ * Create a new Simple plugin.
38
+ *
39
+ * The configuration array expects one option
40
+ * - key: required, otherwise InvalidArgumentException is thrown
41
+ *
42
+ * @param array $config Configuration array
43
+ */
44
+ public function __construct(array $config)
45
+ {
46
+ if (!isset($config['key'])) {
47
+ throw new \InvalidArgumentException('requires a key to have been set');
48
+ }
49
+
50
+ $this->config = array_merge(['key' => null], $config);
51
+ }
52
+
53
+ /**
54
+ * Updates the request query with the developer key if auth is set to simple.
55
+ *
56
+ * use Google\Auth\Middleware\SimpleMiddleware;
57
+ * use GuzzleHttp\Client;
58
+ * use GuzzleHttp\HandlerStack;
59
+ *
60
+ * $my_key = 'is not the same as yours';
61
+ * $middleware = new SimpleMiddleware(['key' => $my_key]);
62
+ * $stack = HandlerStack::create();
63
+ * $stack->push($middleware);
64
+ *
65
+ * $client = new Client([
66
+ * 'handler' => $stack,
67
+ * 'base_uri' => 'https://www.googleapis.com/discovery/v1/',
68
+ * 'auth' => 'simple'
69
+ * ]);
70
+ *
71
+ * $res = $client->get('drive/v2/rest');
72
+ *
73
+ * @param callable $handler
74
+ * @return \Closure
75
+ */
76
+ public function __invoke(callable $handler)
77
+ {
78
+ return function (RequestInterface $request, array $options) use ($handler) {
79
+ // Requests using "auth"="scoped" will be authorized.
80
+ if (!isset($options['auth']) || $options['auth'] !== 'simple') {
81
+ return $handler($request, $options);
82
+ }
83
+
84
+ $query = Psr7\parse_query($request->getUri()->getQuery());
85
+ $params = array_merge($query, $this->config);
86
+ $uri = $request->getUri()->withQuery(Psr7\build_query($params));
87
+ $request = $request->withUri($uri);
88
+
89
+ return $handler($request, $options);
90
+ };
91
+ }
92
+ }
vendor/google/auth/src/OAuth2.php ADDED
@@ -0,0 +1,1434 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2015 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth;
19
+
20
+ use Google\Auth\HttpHandler\HttpClientCache;
21
+ use Google\Auth\HttpHandler\HttpHandlerFactory;
22
+ use GuzzleHttp\Psr7;
23
+ use GuzzleHttp\Psr7\Request;
24
+ use InvalidArgumentException;
25
+ use Psr\Http\Message\RequestInterface;
26
+ use Psr\Http\Message\ResponseInterface;
27
+ use Psr\Http\Message\UriInterface;
28
+
29
+ /**
30
+ * OAuth2 supports authentication by OAuth2 2-legged flows.
31
+ *
32
+ * It primary supports
33
+ * - service account authorization
34
+ * - authorization where a user already has an access token
35
+ */
36
+ class OAuth2 implements FetchAuthTokenInterface
37
+ {
38
+ const DEFAULT_EXPIRY_SECONDS = 3600; // 1 hour
39
+ const DEFAULT_SKEW_SECONDS = 60; // 1 minute
40
+ const JWT_URN = 'urn:ietf:params:oauth:grant-type:jwt-bearer';
41
+
42
+ /**
43
+ * TODO: determine known methods from the keys of JWT::methods.
44
+ */
45
+ public static $knownSigningAlgorithms = array(
46
+ 'HS256',
47
+ 'HS512',
48
+ 'HS384',
49
+ 'RS256',
50
+ );
51
+
52
+ /**
53
+ * The well known grant types.
54
+ *
55
+ * @var array
56
+ */
57
+ public static $knownGrantTypes = array(
58
+ 'authorization_code',
59
+ 'refresh_token',
60
+ 'password',
61
+ 'client_credentials',
62
+ );
63
+
64
+ /**
65
+ * - authorizationUri
66
+ * The authorization server's HTTP endpoint capable of
67
+ * authenticating the end-user and obtaining authorization.
68
+ *
69
+ * @var UriInterface
70
+ */
71
+ private $authorizationUri;
72
+
73
+ /**
74
+ * - tokenCredentialUri
75
+ * The authorization server's HTTP endpoint capable of issuing
76
+ * tokens and refreshing expired tokens.
77
+ *
78
+ * @var UriInterface
79
+ */
80
+ private $tokenCredentialUri;
81
+
82
+ /**
83
+ * The redirection URI used in the initial request.
84
+ *
85
+ * @var string
86
+ */
87
+ private $redirectUri;
88
+
89
+ /**
90
+ * A unique identifier issued to the client to identify itself to the
91
+ * authorization server.
92
+ *
93
+ * @var string
94
+ */
95
+ private $clientId;
96
+
97
+ /**
98
+ * A shared symmetric secret issued by the authorization server, which is
99
+ * used to authenticate the client.
100
+ *
101
+ * @var string
102
+ */
103
+ private $clientSecret;
104
+
105
+ /**
106
+ * The resource owner's username.
107
+ *
108
+ * @var string
109
+ */
110
+ private $username;
111
+
112
+ /**
113
+ * The resource owner's password.
114
+ *
115
+ * @var string
116
+ */
117
+ private $password;
118
+
119
+ /**
120
+ * The scope of the access request, expressed either as an Array or as a
121
+ * space-delimited string.
122
+ *
123
+ * @var array
124
+ */
125
+ private $scope;
126
+
127
+ /**
128
+ * An arbitrary string designed to allow the client to maintain state.
129
+ *
130
+ * @var string
131
+ */
132
+ private $state;
133
+
134
+ /**
135
+ * The authorization code issued to this client.
136
+ *
137
+ * Only used by the authorization code access grant type.
138
+ *
139
+ * @var string
140
+ */
141
+ private $code;
142
+
143
+ /**
144
+ * The issuer ID when using assertion profile.
145
+ *
146
+ * @var string
147
+ */
148
+ private $issuer;
149
+
150
+ /**
151
+ * The target audience for assertions.
152
+ *
153
+ * @var string
154
+ */
155
+ private $audience;
156
+
157
+ /**
158
+ * The target sub when issuing assertions.
159
+ *
160
+ * @var string
161
+ */
162
+ private $sub;
163
+
164
+ /**
165
+ * The number of seconds assertions are valid for.
166
+ *
167
+ * @var int
168
+ */
169
+ private $expiry;
170
+
171
+ /**
172
+ * The signing key when using assertion profile.
173
+ *
174
+ * @var string
175
+ */
176
+ private $signingKey;
177
+
178
+ /**
179
+ * The signing key id when using assertion profile. Param kid in jwt header
180
+ *
181
+ * @var string
182
+ */
183
+ private $signingKeyId;
184
+
185
+ /**
186
+ * The signing algorithm when using an assertion profile.
187
+ *
188
+ * @var string
189
+ */
190
+ private $signingAlgorithm;
191
+
192
+ /**
193
+ * The refresh token associated with the access token to be refreshed.
194
+ *
195
+ * @var string
196
+ */
197
+ private $refreshToken;
198
+
199
+ /**
200
+ * The current access token.
201
+ *
202
+ * @var string
203
+ */
204
+ private $accessToken;
205
+
206
+ /**
207
+ * The current ID token.
208
+ *
209
+ * @var string
210
+ */
211
+ private $idToken;
212
+
213
+ /**
214
+ * The lifetime in seconds of the current access token.
215
+ *
216
+ * @var int
217
+ */
218
+ private $expiresIn;
219
+
220
+ /**
221
+ * The expiration time of the access token as a number of seconds since the
222
+ * unix epoch.
223
+ *
224
+ * @var int
225
+ */
226
+ private $expiresAt;
227
+
228
+ /**
229
+ * The issue time of the access token as a number of seconds since the unix
230
+ * epoch.
231
+ *
232
+ * @var int
233
+ */
234
+ private $issuedAt;
235
+
236
+ /**
237
+ * The current grant type.
238
+ *
239
+ * @var string
240
+ */
241
+ private $grantType;
242
+
243
+ /**
244
+ * When using an extension grant type, this is the set of parameters used by
245
+ * that extension.
246
+ */
247
+ private $extensionParams;
248
+
249
+ /**
250
+ * When using the toJwt function, these claims will be added to the JWT
251
+ * payload.
252
+ */
253
+ private $additionalClaims;
254
+
255
+ /**
256
+ * Create a new OAuthCredentials.
257
+ *
258
+ * The configuration array accepts various options
259
+ *
260
+ * - authorizationUri
261
+ * The authorization server's HTTP endpoint capable of
262
+ * authenticating the end-user and obtaining authorization.
263
+ *
264
+ * - tokenCredentialUri
265
+ * The authorization server's HTTP endpoint capable of issuing
266
+ * tokens and refreshing expired tokens.
267
+ *
268
+ * - clientId
269
+ * A unique identifier issued to the client to identify itself to the
270
+ * authorization server.
271
+ *
272
+ * - clientSecret
273
+ * A shared symmetric secret issued by the authorization server,
274
+ * which is used to authenticate the client.
275
+ *
276
+ * - scope
277
+ * The scope of the access request, expressed either as an Array
278
+ * or as a space-delimited String.
279
+ *
280
+ * - state
281
+ * An arbitrary string designed to allow the client to maintain state.
282
+ *
283
+ * - redirectUri
284
+ * The redirection URI used in the initial request.
285
+ *
286
+ * - username
287
+ * The resource owner's username.
288
+ *
289
+ * - password
290
+ * The resource owner's password.
291
+ *
292
+ * - issuer
293
+ * Issuer ID when using assertion profile
294
+ *
295
+ * - audience
296
+ * Target audience for assertions
297
+ *
298
+ * - expiry
299
+ * Number of seconds assertions are valid for
300
+ *
301
+ * - signingKey
302
+ * Signing key when using assertion profile
303
+ *
304
+ * - signingKeyId
305
+ * Signing key id when using assertion profile
306
+ *
307
+ * - refreshToken
308
+ * The refresh token associated with the access token
309
+ * to be refreshed.
310
+ *
311
+ * - accessToken
312
+ * The current access token for this client.
313
+ *
314
+ * - idToken
315
+ * The current ID token for this client.
316
+ *
317
+ * - extensionParams
318
+ * When using an extension grant type, this is the set of parameters used
319
+ * by that extension.
320
+ *
321
+ * @param array $config Configuration array
322
+ */
323
+ public function __construct(array $config)
324
+ {
325
+ $opts = array_merge([
326
+ 'expiry' => self::DEFAULT_EXPIRY_SECONDS,
327
+ 'extensionParams' => [],
328
+ 'authorizationUri' => null,
329
+ 'redirectUri' => null,
330
+ 'tokenCredentialUri' => null,
331
+ 'state' => null,
332
+ 'username' => null,
333
+ 'password' => null,
334
+ 'clientId' => null,
335
+ 'clientSecret' => null,
336
+ 'issuer' => null,
337
+ 'sub' => null,
338
+ 'audience' => null,
339
+ 'signingKey' => null,
340
+ 'signingKeyId' => null,
341
+ 'signingAlgorithm' => null,
342
+ 'scope' => null,
343
+ 'additionalClaims' => [],
344
+ ], $config);
345
+
346
+ $this->setAuthorizationUri($opts['authorizationUri']);
347
+ $this->setRedirectUri($opts['redirectUri']);
348
+ $this->setTokenCredentialUri($opts['tokenCredentialUri']);
349
+ $this->setState($opts['state']);
350
+ $this->setUsername($opts['username']);
351
+ $this->setPassword($opts['password']);
352
+ $this->setClientId($opts['clientId']);
353
+ $this->setClientSecret($opts['clientSecret']);
354
+ $this->setIssuer($opts['issuer']);
355
+ $this->setSub($opts['sub']);
356
+ $this->setExpiry($opts['expiry']);
357
+ $this->setAudience($opts['audience']);
358
+ $this->setSigningKey($opts['signingKey']);
359
+ $this->setSigningKeyId($opts['signingKeyId']);
360
+ $this->setSigningAlgorithm($opts['signingAlgorithm']);
361
+ $this->setScope($opts['scope']);
362
+ $this->setExtensionParams($opts['extensionParams']);
363
+ $this->setAdditionalClaims($opts['additionalClaims']);
364
+ $this->updateToken($opts);
365
+ }
366
+
367
+ /**
368
+ * Verifies the idToken if present.
369
+ *
370
+ * - if none is present, return null
371
+ * - if present, but invalid, raises DomainException.
372
+ * - otherwise returns the payload in the idtoken as a PHP object.
373
+ *
374
+ * The behavior of this method varies depending on the version of
375
+ * `firebase/php-jwt` you are using. In versions lower than 3.0.0, if
376
+ * `$publicKey` is null, the key is decoded without being verified. In
377
+ * newer versions, if a public key is not given, this method will throw an
378
+ * `\InvalidArgumentException`.
379
+ *
380
+ * @param string $publicKey The public key to use to authenticate the token
381
+ * @param array $allowed_algs List of supported verification algorithms
382
+ * @throws \DomainException if the token is missing an audience.
383
+ * @throws \DomainException if the audience does not match the one set in
384
+ * the OAuth2 class instance.
385
+ * @throws \UnexpectedValueException If the token is invalid
386
+ * @throws SignatureInvalidException If the signature is invalid.
387
+ * @throws BeforeValidException If the token is not yet valid.
388
+ * @throws ExpiredException If the token has expired.
389
+ * @return null|object
390
+ */
391
+ public function verifyIdToken($publicKey = null, $allowed_algs = array())
392
+ {
393
+ $idToken = $this->getIdToken();
394
+ if (is_null($idToken)) {
395
+ return null;
396
+ }
397
+
398
+ $resp = $this->jwtDecode($idToken, $publicKey, $allowed_algs);
399
+ if (!property_exists($resp, 'aud')) {
400
+ throw new \DomainException('No audience found the id token');
401
+ }
402
+ if ($resp->aud != $this->getAudience()) {
403
+ throw new \DomainException('Wrong audience present in the id token');
404
+ }
405
+
406
+ return $resp;
407
+ }
408
+
409
+ /**
410
+ * Obtains the encoded jwt from the instance data.
411
+ *
412
+ * @param array $config array optional configuration parameters
413
+ * @return string
414
+ */
415
+ public function toJwt(array $config = [])
416
+ {
417
+ if (is_null($this->getSigningKey())) {
418
+ throw new \DomainException('No signing key available');
419
+ }
420
+ if (is_null($this->getSigningAlgorithm())) {
421
+ throw new \DomainException('No signing algorithm specified');
422
+ }
423
+ $now = time();
424
+
425
+ $opts = array_merge([
426
+ 'skew' => self::DEFAULT_SKEW_SECONDS,
427
+ ], $config);
428
+
429
+ $assertion = [
430
+ 'iss' => $this->getIssuer(),
431
+ 'exp' => ($now + $this->getExpiry()),
432
+ 'iat' => ($now - $opts['skew']),
433
+ ];
434
+ foreach ($assertion as $k => $v) {
435
+ if (is_null($v)) {
436
+ throw new \DomainException($k . ' should not be null');
437
+ }
438
+ }
439
+ if (!(is_null($this->getAudience()))) {
440
+ $assertion['aud'] = $this->getAudience();
441
+ }
442
+
443
+ if (!(is_null($this->getScope()))) {
444
+ $assertion['scope'] = $this->getScope();
445
+ }
446
+
447
+ if (empty($assertion['scope']) && empty($assertion['aud'])) {
448
+ throw new \DomainException('one of scope or aud should not be null');
449
+ }
450
+
451
+ if (!(is_null($this->getSub()))) {
452
+ $assertion['sub'] = $this->getSub();
453
+ }
454
+ $assertion += $this->getAdditionalClaims();
455
+
456
+ return $this->jwtEncode(
457
+ $assertion,
458
+ $this->getSigningKey(),
459
+ $this->getSigningAlgorithm(),
460
+ $this->getSigningKeyId()
461
+ );
462
+ }
463
+
464
+ /**
465
+ * Generates a request for token credentials.
466
+ *
467
+ * @return RequestInterface the authorization Url.
468
+ */
469
+ public function generateCredentialsRequest()
470
+ {
471
+ $uri = $this->getTokenCredentialUri();
472
+ if (is_null($uri)) {
473
+ throw new \DomainException('No token credential URI was set.');
474
+ }
475
+
476
+ $grantType = $this->getGrantType();
477
+ $params = array('grant_type' => $grantType);
478
+ switch ($grantType) {
479
+ case 'authorization_code':
480
+ $params['code'] = $this->getCode();
481
+ $params['redirect_uri'] = $this->getRedirectUri();
482
+ $this->addClientCredentials($params);
483
+ break;
484
+ case 'password':
485
+ $params['username'] = $this->getUsername();
486
+ $params['password'] = $this->getPassword();
487
+ $this->addClientCredentials($params);
488
+ break;
489
+ case 'refresh_token':
490
+ $params['refresh_token'] = $this->getRefreshToken();
491
+ $this->addClientCredentials($params);
492
+ break;
493
+ case self::JWT_URN:
494
+ $params['assertion'] = $this->toJwt();
495
+ break;
496
+ default:
497
+ if (!is_null($this->getRedirectUri())) {
498
+ # Grant type was supposed to be 'authorization_code', as there
499
+ # is a redirect URI.
500
+ throw new \DomainException('Missing authorization code');
501
+ }
502
+ unset($params['grant_type']);
503
+ if (!is_null($grantType)) {
504
+ $params['grant_type'] = $grantType;
505
+ }
506
+ $params = array_merge($params, $this->getExtensionParams());
507
+ }
508
+
509
+ $headers = [
510
+ 'Cache-Control' => 'no-store',
511
+ 'Content-Type' => 'application/x-www-form-urlencoded',
512
+ ];
513
+
514
+ return new Request(
515
+ 'POST',
516
+ $uri,
517
+ $headers,
518
+ Psr7\build_query($params)
519
+ );
520
+ }
521
+
522
+ /**
523
+ * Fetches the auth tokens based on the current state.
524
+ *
525
+ * @param callable $httpHandler callback which delivers psr7 request
526
+ * @return array the response
527
+ */
528
+ public function fetchAuthToken(callable $httpHandler = null)
529
+ {
530
+ if (is_null($httpHandler)) {
531
+ $httpHandler = HttpHandlerFactory::build(HttpClientCache::getHttpClient());
532
+ }
533
+
534
+ $response = $httpHandler($this->generateCredentialsRequest());
535
+ $credentials = $this->parseTokenResponse($response);
536
+ $this->updateToken($credentials);
537
+
538
+ return $credentials;
539
+ }
540
+
541
+ /**
542
+ * Obtains a key that can used to cache the results of #fetchAuthToken.
543
+ *
544
+ * The key is derived from the scopes.
545
+ *
546
+ * @return string a key that may be used to cache the auth token.
547
+ */
548
+ public function getCacheKey()
549
+ {
550
+ if (is_array($this->scope)) {
551
+ return implode(':', $this->scope);
552
+ }
553
+
554
+ if ($this->audience) {
555
+ return $this->audience;
556
+ }
557
+
558
+ // If scope has not set, return null to indicate no caching.
559
+ return null;
560
+ }
561
+
562
+ /**
563
+ * Parses the fetched tokens.
564
+ *
565
+ * @param ResponseInterface $resp the response.
566
+ * @return array the tokens parsed from the response body.
567
+ * @throws \Exception
568
+ */
569
+ public function parseTokenResponse(ResponseInterface $resp)
570
+ {
571
+ $body = (string)$resp->getBody();
572
+ if ($resp->hasHeader('Content-Type') &&
573
+ $resp->getHeaderLine('Content-Type') == 'application/x-www-form-urlencoded'
574
+ ) {
575
+ $res = array();
576
+ parse_str($body, $res);
577
+
578
+ return $res;
579
+ }
580
+
581
+ // Assume it's JSON; if it's not throw an exception
582
+ if (null === $res = json_decode($body, true)) {
583
+ throw new \Exception('Invalid JSON response');
584
+ }
585
+
586
+ return $res;
587
+ }
588
+
589
+ /**
590
+ * Updates an OAuth 2.0 client.
591
+ *
592
+ * Example:
593
+ * ```
594
+ * $oauth->updateToken([
595
+ * 'refresh_token' => 'n4E9O119d',
596
+ * 'access_token' => 'FJQbwq9',
597
+ * 'expires_in' => 3600
598
+ * ]);
599
+ * ```
600
+ *
601
+ * @param array $config
602
+ * The configuration parameters related to the token.
603
+ *
604
+ * - refresh_token
605
+ * The refresh token associated with the access token
606
+ * to be refreshed.
607
+ *
608
+ * - access_token
609
+ * The current access token for this client.
610
+ *
611
+ * - id_token
612
+ * The current ID token for this client.
613
+ *
614
+ * - expires_in
615
+ * The time in seconds until access token expiration.
616
+ *
617
+ * - expires_at
618
+ * The time as an integer number of seconds since the Epoch
619
+ *
620
+ * - issued_at
621
+ * The timestamp that the token was issued at.
622
+ */
623
+ public function updateToken(array $config)
624
+ {
625
+ $opts = array_merge([
626
+ 'extensionParams' => [],
627
+ 'access_token' => null,
628
+ 'id_token' => null,
629
+ 'expires_in' => null,
630
+ 'expires_at' => null,
631
+ 'issued_at' => null,
632
+ ], $config);
633
+
634
+ $this->setExpiresAt($opts['expires_at']);
635
+ $this->setExpiresIn($opts['expires_in']);
636
+ // By default, the token is issued at `Time.now` when `expiresIn` is set,
637
+ // but this can be used to supply a more precise time.
638
+ if (!is_null($opts['issued_at'])) {
639
+ $this->setIssuedAt($opts['issued_at']);
640
+ }
641
+
642
+ $this->setAccessToken($opts['access_token']);
643
+ $this->setIdToken($opts['id_token']);
644
+ // The refresh token should only be updated if a value is explicitly
645
+ // passed in, as some access token responses do not include a refresh
646
+ // token.
647
+ if (array_key_exists('refresh_token', $opts)) {
648
+ $this->setRefreshToken($opts['refresh_token']);
649
+ }
650
+ }
651
+
652
+ /**
653
+ * Builds the authorization Uri that the user should be redirected to.
654
+ *
655
+ * @param array $config configuration options that customize the return url
656
+ * @return UriInterface the authorization Url.
657
+ * @throws InvalidArgumentException
658
+ */
659
+ public function buildFullAuthorizationUri(array $config = [])
660
+ {
661
+ if (is_null($this->getAuthorizationUri())) {
662
+ throw new InvalidArgumentException(
663
+ 'requires an authorizationUri to have been set'
664
+ );
665
+ }
666
+
667
+ $params = array_merge([
668
+ 'response_type' => 'code',
669
+ 'access_type' => 'offline',
670
+ 'client_id' => $this->clientId,
671
+ 'redirect_uri' => $this->redirectUri,
672
+ 'state' => $this->state,
673
+ 'scope' => $this->getScope(),
674
+ ], $config);
675
+
676
+ // Validate the auth_params
677
+ if (is_null($params['client_id'])) {
678
+ throw new InvalidArgumentException(
679
+ 'missing the required client identifier'
680
+ );
681
+ }
682
+ if (is_null($params['redirect_uri'])) {
683
+ throw new InvalidArgumentException('missing the required redirect URI');
684
+ }
685
+ if (!empty($params['prompt']) && !empty($params['approval_prompt'])) {
686
+ throw new InvalidArgumentException(
687
+ 'prompt and approval_prompt are mutually exclusive'
688
+ );
689
+ }
690
+
691
+ // Construct the uri object; return it if it is valid.
692
+ $result = clone $this->authorizationUri;
693
+ $existingParams = Psr7\parse_query($result->getQuery());
694
+
695
+ $result = $result->withQuery(
696
+ Psr7\build_query(array_merge($existingParams, $params))
697
+ );
698
+
699
+ if ($result->getScheme() != 'https') {
700
+ throw new InvalidArgumentException(
701
+ 'Authorization endpoint must be protected by TLS'
702
+ );
703
+ }
704
+
705
+ return $result;
706
+ }
707
+
708
+ /**
709
+ * Sets the authorization server's HTTP endpoint capable of authenticating
710
+ * the end-user and obtaining authorization.
711
+ *
712
+ * @param string $uri
713
+ */
714
+ public function setAuthorizationUri($uri)
715
+ {
716
+ $this->authorizationUri = $this->coerceUri($uri);
717
+ }
718
+
719
+ /**
720
+ * Gets the authorization server's HTTP endpoint capable of authenticating
721
+ * the end-user and obtaining authorization.
722
+ *
723
+ * @return UriInterface
724
+ */
725
+ public function getAuthorizationUri()
726
+ {
727
+ return $this->authorizationUri;
728
+ }
729
+
730
+ /**
731
+ * Gets the authorization server's HTTP endpoint capable of issuing tokens
732
+ * and refreshing expired tokens.
733
+ *
734
+ * @return string
735
+ */
736
+ public function getTokenCredentialUri()
737
+ {
738
+ return $this->tokenCredentialUri;
739
+ }
740
+
741
+ /**
742
+ * Sets the authorization server's HTTP endpoint capable of issuing tokens
743
+ * and refreshing expired tokens.
744
+ *
745
+ * @param string $uri
746
+ */
747
+ public function setTokenCredentialUri($uri)
748
+ {
749
+ $this->tokenCredentialUri = $this->coerceUri($uri);
750
+ }
751
+
752
+ /**
753
+ * Gets the redirection URI used in the initial request.
754
+ *
755
+ * @return string
756
+ */
757
+ public function getRedirectUri()
758
+ {
759
+ return $this->redirectUri;
760
+ }
761
+
762
+ /**
763
+ * Sets the redirection URI used in the initial request.
764
+ *
765
+ * @param string $uri
766
+ */
767
+ public function setRedirectUri($uri)
768
+ {
769
+ if (is_null($uri)) {
770
+ $this->redirectUri = null;
771
+
772
+ return;
773
+ }
774
+ // redirect URI must be absolute
775
+ if (!$this->isAbsoluteUri($uri)) {
776
+ // "postmessage" is a reserved URI string in Google-land
777
+ // @see https://developers.google.com/identity/sign-in/web/server-side-flow
778
+ if ('postmessage' !== (string)$uri) {
779
+ throw new InvalidArgumentException(
780
+ 'Redirect URI must be absolute'
781
+ );
782
+ }
783
+ }
784
+ $this->redirectUri = (string)$uri;
785
+ }
786
+
787
+ /**
788
+ * Gets the scope of the access requests as a space-delimited String.
789
+ *
790
+ * @return string
791
+ */
792
+ public function getScope()
793
+ {
794
+ if (is_null($this->scope)) {
795
+ return $this->scope;
796
+ }
797
+
798
+ return implode(' ', $this->scope);
799
+ }
800
+
801
+ /**
802
+ * Sets the scope of the access request, expressed either as an Array or as
803
+ * a space-delimited String.
804
+ *
805
+ * @param string|array $scope
806
+ * @throws InvalidArgumentException
807
+ */
808
+ public function setScope($scope)
809
+ {
810
+ if (is_null($scope)) {
811
+ $this->scope = null;
812
+ } elseif (is_string($scope)) {
813
+ $this->scope = explode(' ', $scope);
814
+ } elseif (is_array($scope)) {
815
+ foreach ($scope as $s) {
816
+ $pos = strpos($s, ' ');
817
+ if ($pos !== false) {
818
+ throw new InvalidArgumentException(
819
+ 'array scope values should not contain spaces'
820
+ );
821
+ }
822
+ }
823
+ $this->scope = $scope;
824
+ } else {
825
+ throw new InvalidArgumentException(
826
+ 'scopes should be a string or array of strings'
827
+ );
828
+ }
829
+ }
830
+
831
+ /**
832
+ * Gets the current grant type.
833
+ *
834
+ * @return string
835
+ */
836
+ public function getGrantType()
837
+ {
838
+ if (!is_null($this->grantType)) {
839
+ return $this->grantType;
840
+ }
841
+
842
+ // Returns the inferred grant type, based on the current object instance
843
+ // state.
844
+ if (!is_null($this->code)) {
845
+ return 'authorization_code';
846
+ }
847
+
848
+ if (!is_null($this->refreshToken)) {
849
+ return 'refresh_token';
850
+ }
851
+
852
+ if (!is_null($this->username) && !is_null($this->password)) {
853
+ return 'password';
854
+ }
855
+
856
+ if (!is_null($this->issuer) && !is_null($this->signingKey)) {
857
+ return self::JWT_URN;
858
+ }
859
+
860
+ return null;
861
+ }
862
+
863
+ /**
864
+ * Sets the current grant type.
865
+ *
866
+ * @param $grantType
867
+ * @throws InvalidArgumentException
868
+ */
869
+ public function setGrantType($grantType)
870
+ {
871
+ if (in_array($grantType, self::$knownGrantTypes)) {
872
+ $this->grantType = $grantType;
873
+ } else {
874
+ // validate URI
875
+ if (!$this->isAbsoluteUri($grantType)) {
876
+ throw new InvalidArgumentException(
877
+ 'invalid grant type'
878
+ );
879
+ }
880
+ $this->grantType = (string)$grantType;
881
+ }
882
+ }
883
+
884
+ /**
885
+ * Gets an arbitrary string designed to allow the client to maintain state.
886
+ *
887
+ * @return string
888
+ */
889
+ public function getState()
890
+ {
891
+ return $this->state;
892
+ }
893
+
894
+ /**
895
+ * Sets an arbitrary string designed to allow the client to maintain state.
896
+ *
897
+ * @param string $state
898
+ */
899
+ public function setState($state)
900
+ {
901
+ $this->state = $state;
902
+ }
903
+
904
+ /**
905
+ * Gets the authorization code issued to this client.
906
+ */
907
+ public function getCode()
908
+ {
909
+ return $this->code;
910
+ }
911
+
912
+ /**
913
+ * Sets the authorization code issued to this client.
914
+ *
915
+ * @param string $code
916
+ */
917
+ public function setCode($code)
918
+ {
919
+ $this->code = $code;
920
+ }
921
+
922
+ /**
923
+ * Gets the resource owner's username.
924
+ */
925
+ public function getUsername()
926
+ {
927
+ return $this->username;
928
+ }
929
+
930
+ /**
931
+ * Sets the resource owner's username.
932
+ *
933
+ * @param string $username
934
+ */
935
+ public function setUsername($username)
936
+ {
937
+ $this->username = $username;
938
+ }
939
+
940
+ /**
941
+ * Gets the resource owner's password.
942
+ */
943
+ public function getPassword()
944
+ {
945
+ return $this->password;
946
+ }
947
+
948
+ /**
949
+ * Sets the resource owner's password.
950
+ *
951
+ * @param $password
952
+ */
953
+ public function setPassword($password)
954
+ {
955
+ $this->password = $password;
956
+ }
957
+
958
+ /**
959
+ * Sets a unique identifier issued to the client to identify itself to the
960
+ * authorization server.
961
+ */
962
+ public function getClientId()
963
+ {
964
+ return $this->clientId;
965
+ }
966
+
967
+ /**
968
+ * Sets a unique identifier issued to the client to identify itself to the
969
+ * authorization server.
970
+ *
971
+ * @param $clientId
972
+ */
973
+ public function setClientId($clientId)
974
+ {
975
+ $this->clientId = $clientId;
976
+ }
977
+
978
+ /**
979
+ * Gets a shared symmetric secret issued by the authorization server, which
980
+ * is used to authenticate the client.
981
+ */
982
+ public function getClientSecret()
983
+ {
984
+ return $this->clientSecret;
985
+ }
986
+
987
+ /**
988
+ * Sets a shared symmetric secret issued by the authorization server, which
989
+ * is used to authenticate the client.
990
+ *
991
+ * @param $clientSecret
992
+ */
993
+ public function setClientSecret($clientSecret)
994
+ {
995
+ $this->clientSecret = $clientSecret;
996
+ }
997
+
998
+ /**
999
+ * Gets the Issuer ID when using assertion profile.
1000
+ */
1001
+ public function getIssuer()
1002
+ {
1003
+ return $this->issuer;
1004
+ }
1005
+
1006
+ /**
1007
+ * Sets the Issuer ID when using assertion profile.
1008
+ *
1009
+ * @param string $issuer
1010
+ */
1011
+ public function setIssuer($issuer)
1012
+ {
1013
+ $this->issuer = $issuer;
1014
+ }
1015
+
1016
+ /**
1017
+ * Gets the target sub when issuing assertions.
1018
+ */
1019
+ public function getSub()
1020
+ {
1021
+ return $this->sub;
1022
+ }
1023
+
1024
+ /**
1025
+ * Sets the target sub when issuing assertions.
1026
+ *
1027
+ * @param string $sub
1028
+ */
1029
+ public function setSub($sub)
1030
+ {
1031
+ $this->sub = $sub;
1032
+ }
1033
+
1034
+ /**
1035
+ * Gets the target audience when issuing assertions.
1036
+ */
1037
+ public function getAudience()
1038
+ {
1039
+ return $this->audience;
1040
+ }
1041
+
1042
+ /**
1043
+ * Sets the target audience when issuing assertions.
1044
+ *
1045
+ * @param string $audience
1046
+ */
1047
+ public function setAudience($audience)
1048
+ {
1049
+ $this->audience = $audience;
1050
+ }
1051
+
1052
+ /**
1053
+ * Gets the signing key when using an assertion profile.
1054
+ */
1055
+ public function getSigningKey()
1056
+ {
1057
+ return $this->signingKey;
1058
+ }
1059
+
1060
+ /**
1061
+ * Sets the signing key when using an assertion profile.
1062
+ *
1063
+ * @param string $signingKey
1064
+ */
1065
+ public function setSigningKey($signingKey)
1066
+ {
1067
+ $this->signingKey = $signingKey;
1068
+ }
1069
+
1070
+ /**
1071
+ * Gets the signing key id when using an assertion profile.
1072
+ *
1073
+ * @return string
1074
+ */
1075
+ public function getSigningKeyId()
1076
+ {
1077
+ return $this->signingKeyId;
1078
+ }
1079
+
1080
+ /**
1081
+ * Sets the signing key id when using an assertion profile.
1082
+ *
1083
+ * @param string $signingKeyId
1084
+ */
1085
+ public function setSigningKeyId($signingKeyId)
1086
+ {
1087
+ $this->signingKeyId = $signingKeyId;
1088
+ }
1089
+
1090
+ /**
1091
+ * Gets the signing algorithm when using an assertion profile.
1092
+ *
1093
+ * @return string
1094
+ */
1095
+ public function getSigningAlgorithm()
1096
+ {
1097
+ return $this->signingAlgorithm;
1098
+ }
1099
+
1100
+ /**
1101
+ * Sets the signing algorithm when using an assertion profile.
1102
+ *
1103
+ * @param string $signingAlgorithm
1104
+ */
1105
+ public function setSigningAlgorithm($signingAlgorithm)
1106
+ {
1107
+ if (is_null($signingAlgorithm)) {
1108
+ $this->signingAlgorithm = null;
1109
+ } elseif (!in_array($signingAlgorithm, self::$knownSigningAlgorithms)) {
1110
+ throw new InvalidArgumentException('unknown signing algorithm');
1111
+ } else {
1112
+ $this->signingAlgorithm = $signingAlgorithm;
1113
+ }
1114
+ }
1115
+
1116
+ /**
1117
+ * Gets the set of parameters used by extension when using an extension
1118
+ * grant type.
1119
+ */
1120
+ public function getExtensionParams()
1121
+ {
1122
+ return $this->extensionParams;
1123
+ }
1124
+
1125
+ /**
1126
+ * Sets the set of parameters used by extension when using an extension
1127
+ * grant type.
1128
+ *
1129
+ * @param $extensionParams
1130
+ */
1131
+ public function setExtensionParams($extensionParams)
1132
+ {
1133
+ $this->extensionParams = $extensionParams;
1134
+ }
1135
+
1136
+ /**
1137
+ * Gets the number of seconds assertions are valid for.
1138
+ */
1139
+ public function getExpiry()
1140
+ {
1141
+ return $this->expiry;
1142
+ }
1143
+
1144
+ /**
1145
+ * Sets the number of seconds assertions are valid for.
1146
+ *
1147
+ * @param int $expiry
1148
+ */
1149
+ public function setExpiry($expiry)
1150
+ {
1151
+ $this->expiry = $expiry;
1152
+ }
1153
+
1154
+ /**
1155
+ * Gets the lifetime of the access token in seconds.
1156
+ */
1157
+ public function getExpiresIn()
1158
+ {
1159
+ return $this->expiresIn;
1160
+ }
1161
+
1162
+ /**
1163
+ * Sets the lifetime of the access token in seconds.
1164
+ *
1165
+ * @param int $expiresIn
1166
+ */
1167
+ public function setExpiresIn($expiresIn)
1168
+ {
1169
+ if (is_null($expiresIn)) {
1170
+ $this->expiresIn = null;
1171
+ $this->issuedAt = null;
1172
+ } else {
1173
+ $this->issuedAt = time();
1174
+ $this->expiresIn = (int)$expiresIn;
1175
+ }
1176
+ }
1177
+
1178
+ /**
1179
+ * Gets the time the current access token expires at.
1180
+ *
1181
+ * @return int
1182
+ */
1183
+ public function getExpiresAt()
1184
+ {
1185
+ if (!is_null($this->expiresAt)) {
1186
+ return $this->expiresAt;
1187
+ }
1188
+
1189
+ if (!is_null($this->issuedAt) && !is_null($this->expiresIn)) {
1190
+ return $this->issuedAt + $this->expiresIn;
1191
+ }
1192
+
1193
+ return null;
1194
+ }
1195
+
1196
+ /**
1197
+ * Returns true if the acccess token has expired.
1198
+ *
1199
+ * @return bool
1200
+ */
1201
+ public function isExpired()
1202
+ {
1203
+ $expiration = $this->getExpiresAt();
1204
+ $now = time();
1205
+
1206
+ return !is_null($expiration) && $now >= $expiration;
1207
+ }
1208
+
1209
+ /**
1210
+ * Sets the time the current access token expires at.
1211
+ *
1212
+ * @param int $expiresAt
1213
+ */
1214
+ public function setExpiresAt($expiresAt)
1215
+ {
1216
+ $this->expiresAt = $expiresAt;
1217
+ }
1218
+
1219
+ /**
1220
+ * Gets the time the current access token was issued at.
1221
+ */
1222
+ public function getIssuedAt()
1223
+ {
1224
+ return $this->issuedAt;
1225
+ }
1226
+
1227
+ /**
1228
+ * Sets the time the current access token was issued at.
1229
+ *
1230
+ * @param int $issuedAt
1231
+ */
1232
+ public function setIssuedAt($issuedAt)
1233
+ {
1234
+ $this->issuedAt = $issuedAt;
1235
+ }
1236
+
1237
+ /**
1238
+ * Gets the current access token.
1239
+ */
1240
+ public function getAccessToken()
1241
+ {
1242
+ return $this->accessToken;
1243
+ }
1244
+
1245
+ /**
1246
+ * Sets the current access token.
1247
+ *
1248
+ * @param string $accessToken
1249
+ */
1250
+ public function setAccessToken($accessToken)
1251
+ {
1252
+ $this->accessToken = $accessToken;
1253
+ }
1254
+
1255
+ /**
1256
+ * Gets the current ID token.
1257
+ */
1258
+ public function getIdToken()
1259
+ {
1260
+ return $this->idToken;
1261
+ }
1262
+
1263
+ /**
1264
+ * Sets the current ID token.
1265
+ *
1266
+ * @param $idToken
1267
+ */
1268
+ public function setIdToken($idToken)
1269
+ {
1270
+ $this->idToken = $idToken;
1271
+ }
1272
+
1273
+ /**
1274
+ * Gets the refresh token associated with the current access token.
1275
+ */
1276
+ public function getRefreshToken()
1277
+ {
1278
+ return $this->refreshToken;
1279
+ }
1280
+
1281
+ /**
1282
+ * Sets the refresh token associated with the current access token.
1283
+ *
1284
+ * @param $refreshToken
1285
+ */
1286
+ public function setRefreshToken($refreshToken)
1287
+ {
1288
+ $this->refreshToken = $refreshToken;
1289
+ }
1290
+
1291
+ /**
1292
+ * Sets additional claims to be included in the JWT token
1293
+ *
1294
+ * @param array $additionalClaims
1295
+ */
1296
+ public function setAdditionalClaims(array $additionalClaims)
1297
+ {
1298
+ $this->additionalClaims = $additionalClaims;
1299
+ }
1300
+
1301
+ /**
1302
+ * Gets the additional claims to be included in the JWT token.
1303
+ *
1304
+ * @return array
1305
+ */
1306
+ public function getAdditionalClaims()
1307
+ {
1308
+ return $this->additionalClaims;
1309
+ }
1310
+
1311
+ /**
1312
+ * The expiration of the last received token.
1313
+ *
1314
+ * @return array|null
1315
+ */
1316
+ public function getLastReceivedToken()
1317
+ {
1318
+ if ($token = $this->getAccessToken()) {
1319
+ // the bare necessity of an auth token
1320
+ $authToken = [
1321
+ 'access_token' => $token,
1322
+ 'expires_at' => $this->getExpiresAt(),
1323
+ ];
1324
+ } elseif ($idToken = $this->getIdToken()) {
1325
+ $authToken = [
1326
+ 'id_token' => $idToken,
1327
+ 'expires_at' => $this->getExpiresAt(),
1328
+ ];
1329
+ } else {
1330
+ return null;
1331
+ }
1332
+
1333
+ if ($expiresIn = $this->getExpiresIn()) {
1334
+ $authToken['expires_in'] = $expiresIn;
1335
+ }
1336
+ if ($issuedAt = $this->getIssuedAt()) {
1337
+ $authToken['issued_at'] = $issuedAt;
1338
+ }
1339
+ if ($refreshToken = $this->getRefreshToken()) {
1340
+ $authToken['refresh_token'] = $refreshToken;
1341
+ }
1342
+
1343
+ return $authToken;
1344
+ }
1345
+
1346
+ /**
1347
+ * Get the client ID.
1348
+ *
1349
+ * Alias of {@see Google\Auth\OAuth2::getClientId()}.
1350
+ *
1351
+ * @param callable $httpHandler
1352
+ * @return string
1353
+ * @access private
1354
+ */
1355
+ public function getClientName(callable $httpHandler = null)
1356
+ {
1357
+ return $this->getClientId();
1358
+ }
1359
+
1360
+ /**
1361
+ * @todo handle uri as array
1362
+ *
1363
+ * @param string $uri
1364
+ * @return null|UriInterface
1365
+ */
1366
+ private function coerceUri($uri)
1367
+ {
1368
+ if (is_null($uri)) {
1369
+ return;
1370
+ }
1371
+
1372
+ return Psr7\uri_for($uri);
1373
+ }
1374
+
1375
+ /**
1376
+ * @param string $idToken
1377
+ * @param string|array|null $publicKey
1378
+ * @param array $allowedAlgs
1379
+ * @return object
1380
+ */
1381
+ private function jwtDecode($idToken, $publicKey, $allowedAlgs)
1382
+ {
1383
+ if (class_exists('Firebase\JWT\JWT')) {
1384
+ return \Firebase\JWT\JWT::decode($idToken, $publicKey, $allowedAlgs);
1385
+ }
1386
+
1387
+ return \JWT::decode($idToken, $publicKey, $allowedAlgs);
1388
+ }
1389
+
1390
+ private function jwtEncode($assertion, $signingKey, $signingAlgorithm, $signingKeyId = null)
1391
+ {
1392
+ if (class_exists('Firebase\JWT\JWT')) {
1393
+ return \Firebase\JWT\JWT::encode(
1394
+ $assertion,
1395
+ $signingKey,
1396
+ $signingAlgorithm,
1397
+ $signingKeyId
1398
+ );
1399
+ }
1400
+
1401
+ return \JWT::encode($assertion, $signingKey, $signingAlgorithm, $signingKeyId);
1402
+ }
1403
+
1404
+ /**
1405
+ * Determines if the URI is absolute based on its scheme and host or path
1406
+ * (RFC 3986).
1407
+ *
1408
+ * @param string $uri
1409
+ * @return bool
1410
+ */
1411
+ private function isAbsoluteUri($uri)
1412
+ {
1413
+ $uri = $this->coerceUri($uri);
1414
+
1415
+ return $uri->getScheme() && ($uri->getHost() || $uri->getPath());
1416
+ }
1417
+
1418
+ /**
1419
+ * @param array $params
1420
+ * @return array
1421
+ */
1422
+ private function addClientCredentials(&$params)
1423
+ {
1424
+ $clientId = $this->getClientId();
1425
+ $clientSecret = $this->getClientSecret();
1426
+
1427
+ if ($clientId && $clientSecret) {
1428
+ $params['client_id'] = $clientId;
1429
+ $params['client_secret'] = $clientSecret;
1430
+ }
1431
+
1432
+ return $params;
1433
+ }
1434
+ }
vendor/google/auth/src/ProjectIdProviderInterface.php ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2020 Google LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth;
19
+
20
+ /**
21
+ * Describes a Credentials object which supports fetching the project ID.
22
+ */
23
+ interface ProjectIdProviderInterface
24
+ {
25
+ /**
26
+ * Get the project ID.
27
+ *
28
+ * @param callable $httpHandler Callback which delivers psr7 request
29
+ * @return string|null
30
+ */
31
+ public function getProjectId(callable $httpHandler = null);
32
+ }
vendor/google/auth/src/ServiceAccountSignerTrait.php ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2019 Google LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth;
19
+
20
+ use phpseclib\Crypt\RSA;
21
+
22
+ /**
23
+ * Sign a string using a Service Account private key.
24
+ */
25
+ trait ServiceAccountSignerTrait
26
+ {
27
+ /**
28
+ * Sign a string using the service account private key.
29
+ *
30
+ * @param string $stringToSign
31
+ * @param bool $forceOpenssl Whether to use OpenSSL regardless of
32
+ * whether phpseclib is installed. **Defaults to** `false`.
33
+ * @return string
34
+ */
35
+ public function signBlob($stringToSign, $forceOpenssl = false)
36
+ {
37
+ $privateKey = $this->auth->getSigningKey();
38
+
39
+ $signedString = '';
40
+ if (class_exists('\\phpseclib\\Crypt\\RSA') && !$forceOpenssl) {
41
+ $rsa = new RSA;
42
+ $rsa->loadKey($privateKey);
43
+ $rsa->setSignatureMode(RSA::SIGNATURE_PKCS1);
44
+ $rsa->setHash('sha256');
45
+
46
+ $signedString = $rsa->sign($stringToSign);
47
+ } elseif (extension_loaded('openssl')) {
48
+ openssl_sign($stringToSign, $signedString, $privateKey, 'sha256WithRSAEncryption');
49
+ } else {
50
+ // @codeCoverageIgnoreStart
51
+ throw new \RuntimeException('OpenSSL is not installed.');
52
+ }
53
+ // @codeCoverageIgnoreEnd
54
+
55
+ return base64_encode($signedString);
56
+ }
57
+ }
vendor/google/auth/src/SignBlobInterface.php ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2019 Google LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth;
19
+
20
+ /**
21
+ * Describes a class which supports signing arbitrary strings.
22
+ */
23
+ interface SignBlobInterface extends FetchAuthTokenInterface
24
+ {
25
+ /**
26
+ * Sign a string using the method which is best for a given credentials type.
27
+ *
28
+ * @param string $stringToSign The string to sign.
29
+ * @param bool $forceOpenssl Require use of OpenSSL for local signing. Does
30
+ * not apply to signing done using external services. **Defaults to**
31
+ * `false`.
32
+ * @return string The resulting signature. Value should be base64-encoded.
33
+ */
34
+ public function signBlob($stringToSign, $forceOpenssl = false);
35
+
36
+ /**
37
+ * Returns the current Client Name.
38
+ *
39
+ * @param callable $httpHandler callback which delivers psr7 request, if
40
+ * one is required to obtain a client name.
41
+ * @return string
42
+ */
43
+ public function getClientName(callable $httpHandler = null);
44
+ }
vendor/google/auth/src/Subscriber/AuthTokenSubscriber.php ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2015 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth\Subscriber;
19
+
20
+ use Google\Auth\FetchAuthTokenInterface;
21
+ use Google\Auth\GetQuotaProjectInterface;
22
+ use GuzzleHttp\Event\BeforeEvent;
23
+ use GuzzleHttp\Event\RequestEvents;
24
+ use GuzzleHttp\Event\SubscriberInterface;
25
+
26
+ /**
27
+ * AuthTokenSubscriber is a Guzzle Subscriber that adds an Authorization header
28
+ * provided by an object implementing FetchAuthTokenInterface.
29
+ *
30
+ * The FetchAuthTokenInterface#fetchAuthToken is used to obtain a hash; one of
31
+ * the values value in that hash is added as the authorization header.
32
+ *
33
+ * Requests will be accessed with the authorization header:
34
+ *
35
+ * 'authorization' 'Bearer <value of auth_token>'
36
+ */
37
+ class AuthTokenSubscriber implements SubscriberInterface
38
+ {
39
+ /**
40
+ * @var callable
41
+ */
42
+ private $httpHandler;
43
+
44
+ /**
45
+ * @var FetchAuthTokenInterface
46
+ */
47
+ private $fetcher;
48
+
49
+ /**
50
+ * @var callable
51
+ */
52
+ private $tokenCallback;
53
+
54
+ /**
55
+ * Creates a new AuthTokenSubscriber.
56
+ *
57
+ * @param FetchAuthTokenInterface $fetcher is used to fetch the auth token
58
+ * @param callable $httpHandler (optional) http client to fetch the token.
59
+ * @param callable $tokenCallback (optional) function to be called when a new token is fetched.
60
+ */
61
+ public function __construct(
62
+ FetchAuthTokenInterface $fetcher,
63
+ callable $httpHandler = null,
64
+ callable $tokenCallback = null
65
+ ) {
66
+ $this->fetcher = $fetcher;
67
+ $this->httpHandler = $httpHandler;
68
+ $this->tokenCallback = $tokenCallback;
69
+ }
70
+
71
+ /**
72
+ * @return array
73
+ */
74
+ public function getEvents()
75
+ {
76
+ return ['before' => ['onBefore', RequestEvents::SIGN_REQUEST]];
77
+ }
78
+
79
+ /**
80
+ * Updates the request with an Authorization header when auth is 'fetched_auth_token'.
81
+ *
82
+ * Example:
83
+ * ```
84
+ * use GuzzleHttp\Client;
85
+ * use Google\Auth\OAuth2;
86
+ * use Google\Auth\Subscriber\AuthTokenSubscriber;
87
+ *
88
+ * $config = [..<oauth config param>.];
89
+ * $oauth2 = new OAuth2($config)
90
+ * $subscriber = new AuthTokenSubscriber($oauth2);
91
+ *
92
+ * $client = new Client([
93
+ * 'base_url' => 'https://www.googleapis.com/taskqueue/v1beta2/projects/',
94
+ * 'defaults' => ['auth' => 'google_auth']
95
+ * ]);
96
+ * $client->getEmitter()->attach($subscriber);
97
+ *
98
+ * $res = $client->get('myproject/taskqueues/myqueue');
99
+ * ```
100
+ *
101
+ * @param BeforeEvent $event
102
+ */
103
+ public function onBefore(BeforeEvent $event)
104
+ {
105
+ // Requests using "auth"="google_auth" will be authorized.
106
+ $request = $event->getRequest();
107
+ if ($request->getConfig()['auth'] != 'google_auth') {
108
+ return;
109
+ }
110
+
111
+ // Fetch the auth token.
112
+ $auth_tokens = $this->fetcher->fetchAuthToken($this->httpHandler);
113
+ if (array_key_exists('access_token', $auth_tokens)) {
114
+ $request->setHeader('authorization', 'Bearer ' . $auth_tokens['access_token']);
115
+
116
+ // notify the callback if applicable
117
+ if ($this->tokenCallback) {
118
+ call_user_func($this->tokenCallback, $this->fetcher->getCacheKey(), $auth_tokens['access_token']);
119
+ }
120
+ }
121
+
122
+ if ($quotaProject = $this->getQuotaProject()) {
123
+ $request->setHeader(
124
+ GetQuotaProjectInterface::X_GOOG_USER_PROJECT_HEADER,
125
+ $quotaProject
126
+ );
127
+ }
128
+ }
129
+
130
+ private function getQuotaProject()
131
+ {
132
+ if ($this->fetcher instanceof GetQuotaProjectInterface) {
133
+ return $this->fetcher->getQuotaProject();
134
+ }
135
+ }
136
+ }
vendor/google/auth/src/Subscriber/ScopedAccessTokenSubscriber.php ADDED
@@ -0,0 +1,180 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2015 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth\Subscriber;
19
+
20
+ use Google\Auth\CacheTrait;
21
+ use GuzzleHttp\Event\BeforeEvent;
22
+ use GuzzleHttp\Event\RequestEvents;
23
+ use GuzzleHttp\Event\SubscriberInterface;
24
+ use Psr\Cache\CacheItemPoolInterface;
25
+
26
+ /**
27
+ * ScopedAccessTokenSubscriber is a Guzzle Subscriber that adds an Authorization
28
+ * header provided by a closure.
29
+ *
30
+ * The closure returns an access token, taking the scope, either a single
31
+ * string or an array of strings, as its value. If provided, a cache will be
32
+ * used to preserve the access token for a given lifetime.
33
+ *
34
+ * Requests will be accessed with the authorization header:
35
+ *
36
+ * 'authorization' 'Bearer <access token obtained from the closure>'
37
+ */
38
+ class ScopedAccessTokenSubscriber implements SubscriberInterface
39
+ {
40
+ use CacheTrait;
41
+
42
+ const DEFAULT_CACHE_LIFETIME = 1500;
43
+
44
+ /**
45
+ * @var CacheItemPoolInterface
46
+ */
47
+ private $cache;
48
+
49
+ /**
50
+ * @var callable The access token generator function
51
+ */
52
+ private $tokenFunc;
53
+
54
+ /**
55
+ * @var array|string The scopes used to generate the token
56
+ */
57
+ private $scopes;
58
+
59
+ /**
60
+ * @var array
61
+ */
62
+ private $cacheConfig;
63
+
64
+ /**
65
+ * Creates a new ScopedAccessTokenSubscriber.
66
+ *
67
+ * @param callable $tokenFunc a token generator function
68
+ * @param array|string $scopes the token authentication scopes
69
+ * @param array $cacheConfig configuration for the cache when it's present
70
+ * @param CacheItemPoolInterface $cache an implementation of CacheItemPoolInterface
71
+ */
72
+ public function __construct(
73
+ callable $tokenFunc,
74
+ $scopes,
75
+ array $cacheConfig = null,
76
+ CacheItemPoolInterface $cache = null
77
+ ) {
78
+ $this->tokenFunc = $tokenFunc;
79
+ if (!(is_string($scopes) || is_array($scopes))) {
80
+ throw new \InvalidArgumentException(
81
+ 'wants scope should be string or array'
82
+ );
83
+ }
84
+ $this->scopes = $scopes;
85
+
86
+ if (!is_null($cache)) {
87
+ $this->cache = $cache;
88
+ $this->cacheConfig = array_merge([
89
+ 'lifetime' => self::DEFAULT_CACHE_LIFETIME,
90
+ 'prefix' => '',
91
+ ], $cacheConfig);
92
+ }
93
+ }
94
+
95
+ /**
96
+ * @return array
97
+ */
98
+ public function getEvents()
99
+ {
100
+ return ['before' => ['onBefore', RequestEvents::SIGN_REQUEST]];
101
+ }
102
+
103
+ /**
104
+ * Updates the request with an Authorization header when auth is 'scoped'.
105
+ *
106
+ * E.g this could be used to authenticate using the AppEngine AppIdentityService.
107
+ *
108
+ * Example:
109
+ * ```
110
+ * use google\appengine\api\app_identity\AppIdentityService;
111
+ * use Google\Auth\Subscriber\ScopedAccessTokenSubscriber;
112
+ * use GuzzleHttp\Client;
113
+ *
114
+ * $scope = 'https://www.googleapis.com/auth/taskqueue'
115
+ * $subscriber = new ScopedAccessToken(
116
+ * 'AppIdentityService::getAccessToken',
117
+ * $scope,
118
+ * ['prefix' => 'Google\Auth\ScopedAccessToken::'],
119
+ * $cache = new Memcache()
120
+ * );
121
+ *
122
+ * $client = new Client([
123
+ * 'base_url' => 'https://www.googleapis.com/taskqueue/v1beta2/projects/',
124
+ * 'defaults' => ['auth' => 'scoped']
125
+ * ]);
126
+ * $client->getEmitter()->attach($subscriber);
127
+ *
128
+ * $res = $client->get('myproject/taskqueues/myqueue');
129
+ * ```
130
+ *
131
+ * @param BeforeEvent $event
132
+ */
133
+ public function onBefore(BeforeEvent $event)
134
+ {
135
+ // Requests using "auth"="scoped" will be authorized.
136
+ $request = $event->getRequest();
137
+ if ($request->getConfig()['auth'] != 'scoped') {
138
+ return;
139
+ }
140
+ $auth_header = 'Bearer ' . $this->fetchToken();
141
+ $request->setHeader('authorization', $auth_header);
142
+ }
143
+
144
+ /**
145
+ * @return string
146
+ */
147
+ private function getCacheKey()
148
+ {
149
+ $key = null;
150
+
151
+ if (is_string($this->scopes)) {
152
+ $key .= $this->scopes;
153
+ } elseif (is_array($this->scopes)) {
154
+ $key .= implode(':', $this->scopes);
155
+ }
156
+
157
+ return $key;
158
+ }
159
+
160
+ /**
161
+ * Determine if token is available in the cache, if not call tokenFunc to
162
+ * fetch it.
163
+ *
164
+ * @return string
165
+ */
166
+ private function fetchToken()
167
+ {
168
+ $cacheKey = $this->getCacheKey();
169
+ $cached = $this->getCachedValue($cacheKey);
170
+
171
+ if (!empty($cached)) {
172
+ return $cached;
173
+ }
174
+
175
+ $token = call_user_func($this->tokenFunc, $this->scopes);
176
+ $this->setCachedValue($cacheKey, $token);
177
+
178
+ return $token;
179
+ }
180
+ }
vendor/google/auth/src/Subscriber/SimpleSubscriber.php ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2015 Google Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth\Subscriber;
19
+
20
+ use GuzzleHttp\Event\BeforeEvent;
21
+ use GuzzleHttp\Event\RequestEvents;
22
+ use GuzzleHttp\Event\SubscriberInterface;
23
+
24
+ /**
25
+ * SimpleSubscriber is a Guzzle Subscriber that implements Google's Simple API
26
+ * access.
27
+ *
28
+ * Requests are accessed using the Simple API access developer key.
29
+ */
30
+ class SimpleSubscriber implements SubscriberInterface
31
+ {
32
+ /**
33
+ * @var array
34
+ */
35
+ private $config;
36
+
37
+ /**
38
+ * Create a new Simple plugin.
39
+ *
40
+ * The configuration array expects one option
41
+ * - key: required, otherwise InvalidArgumentException is thrown
42
+ *
43
+ * @param array $config Configuration array
44
+ */
45
+ public function __construct(array $config)
46
+ {
47
+ if (!isset($config['key'])) {
48
+ throw new \InvalidArgumentException('requires a key to have been set');
49
+ }
50
+
51
+ $this->config = array_merge([], $config);
52
+ }
53
+
54
+ /**
55
+ * @return array
56
+ */
57
+ public function getEvents()
58
+ {
59
+ return ['before' => ['onBefore', RequestEvents::SIGN_REQUEST]];
60
+ }
61
+
62
+ /**
63
+ * Updates the request query with the developer key if auth is set to simple.
64
+ *
65
+ * Example:
66
+ * ```
67
+ * use Google\Auth\Subscriber\SimpleSubscriber;
68
+ * use GuzzleHttp\Client;
69
+ *
70
+ * $my_key = 'is not the same as yours';
71
+ * $subscriber = new SimpleSubscriber(['key' => $my_key]);
72
+ *
73
+ * $client = new Client([
74
+ * 'base_url' => 'https://www.googleapis.com/discovery/v1/',
75
+ * 'defaults' => ['auth' => 'simple']
76
+ * ]);
77
+ * $client->getEmitter()->attach($subscriber);
78
+ *
79
+ * $res = $client->get('drive/v2/rest');
80
+ * ```
81
+ *
82
+ * @param BeforeEvent $event
83
+ */
84
+ public function onBefore(BeforeEvent $event)
85
+ {
86
+ // Requests using "auth"="simple" with the developer key.
87
+ $request = $event->getRequest();
88
+ if ($request->getConfig()['auth'] != 'simple') {
89
+ return;
90
+ }
91
+ $request->getQuery()->overwriteWith($this->config);
92
+ }
93
+ }
vendor/google/auth/src/UpdateMetadataInterface.php ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ * Copyright 2020 Google LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ namespace Google\Auth;
19
+
20
+ /**
21
+ * Describes a Credentials object which supports updating request metadata
22
+ * (request headers).
23
+ */
24
+ interface UpdateMetadataInterface
25
+ {
26
+ const AUTH_METADATA_KEY = 'authorization';
27
+
28
+ /**
29
+ * Updates metadata with the authorization token.
30
+ *
31
+ * @param array $metadata metadata hashmap
32
+ * @param string $authUri optional auth uri
33
+ * @param callable $httpHandler callback which delivers psr7 request
34
+ * @return array updated metadata hashmap
35
+ */
36
+ public function updateMetadata(
37
+ $metadata,
38
+ $authUri = null,
39
+ callable $httpHandler = null
40
+ );
41
+ }
vendor/guzzlehttp/guzzle/.php_cs ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ $config = PhpCsFixer\Config::create()
4
+ ->setRiskyAllowed(true)
5
+ ->setRules([
6
+ '@PSR2' => true,
7
+ 'array_syntax' => ['syntax' => 'short'],
8
+ 'declare_strict_types' => false,
9
+ 'concat_space' => ['spacing'=>'one'],
10
+ 'php_unit_test_case_static_method_calls' => ['call_type' => 'self'],
11
+ 'ordered_imports' => true,
12
+ // 'phpdoc_align' => ['align'=>'vertical'],
13
+ // 'native_function_invocation' => true,
14
+ ])
15
+ ->setFinder(
16
+ PhpCsFixer\Finder::create()
17
+ ->in(__DIR__.'/src')
18
+ ->in(__DIR__.'/tests')
19
+ ->name('*.php')
20
+ )
21
+ ;
22
+
23
+ return $config;
vendor/guzzlehttp/guzzle/Dockerfile ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM composer:latest as setup
2
+
3
+ RUN mkdir /guzzle
4
+
5
+ WORKDIR /guzzle
6
+
7
+ RUN set -xe \
8
+ && composer init --name=guzzlehttp/test --description="Simple project for testing Guzzle scripts" --author="Márk Sági-Kazár <mark.sagikazar@gmail.com>" --no-interaction \
9
+ && composer require guzzlehttp/guzzle
10
+
11
+
12
+ FROM php:7.3
13
+
14
+ RUN mkdir /guzzle
15
+
16
+ WORKDIR /guzzle
17
+
18
+ COPY --from=setup /guzzle /guzzle
vendor/guzzlehttp/guzzle/LICENSE ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Copyright (c) 2011-2018 Michael Dowling, https://github.com/mtdowling <mtdowling@gmail.com>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
vendor/guzzlehttp/guzzle/src/Client.php ADDED
@@ -0,0 +1,501 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp;
3
+
4
+ use GuzzleHttp\Cookie\CookieJar;
5
+ use GuzzleHttp\Exception\GuzzleException;
6
+ use GuzzleHttp\Promise;
7
+ use GuzzleHttp\Psr7;
8
+ use Psr\Http\Message\RequestInterface;
9
+ use Psr\Http\Message\ResponseInterface;
10
+ use Psr\Http\Message\UriInterface;
11
+
12
+ /**
13
+ * @method ResponseInterface get(string|UriInterface $uri, array $options = [])
14
+ * @method ResponseInterface head(string|UriInterface $uri, array $options = [])
15
+ * @method ResponseInterface put(string|UriInterface $uri, array $options = [])
16
+ * @method ResponseInterface post(string|UriInterface $uri, array $options = [])
17
+ * @method ResponseInterface patch(string|UriInterface $uri, array $options = [])
18
+ * @method ResponseInterface delete(string|UriInterface $uri, array $options = [])
19
+ * @method Promise\PromiseInterface getAsync(string|UriInterface $uri, array $options = [])
20
+ * @method Promise\PromiseInterface headAsync(string|UriInterface $uri, array $options = [])
21
+ * @method Promise\PromiseInterface putAsync(string|UriInterface $uri, array $options = [])
22
+ * @method Promise\PromiseInterface postAsync(string|UriInterface $uri, array $options = [])
23
+ * @method Promise\PromiseInterface patchAsync(string|UriInterface $uri, array $options = [])
24
+ * @method Promise\PromiseInterface deleteAsync(string|UriInterface $uri, array $options = [])
25
+ */
26
+ class Client implements ClientInterface
27
+ {
28
+ /** @var array Default request options */
29
+ private $config;
30
+
31
+ /**
32
+ * Clients accept an array of constructor parameters.
33
+ *
34
+ * Here's an example of creating a client using a base_uri and an array of
35
+ * default request options to apply to each request:
36
+ *
37
+ * $client = new Client([
38
+ * 'base_uri' => 'http://www.foo.com/1.0/',
39
+ * 'timeout' => 0,
40
+ * 'allow_redirects' => false,
41
+ * 'proxy' => '192.168.16.1:10'
42
+ * ]);
43
+ *
44
+ * Client configuration settings include the following options:
45
+ *
46
+ * - handler: (callable) Function that transfers HTTP requests over the
47
+ * wire. The function is called with a Psr7\Http\Message\RequestInterface
48
+ * and array of transfer options, and must return a
49
+ * GuzzleHttp\Promise\PromiseInterface that is fulfilled with a
50
+ * Psr7\Http\Message\ResponseInterface on success.
51
+ * If no handler is provided, a default handler will be created
52
+ * that enables all of the request options below by attaching all of the
53
+ * default middleware to the handler.
54
+ * - base_uri: (string|UriInterface) Base URI of the client that is merged
55
+ * into relative URIs. Can be a string or instance of UriInterface.
56
+ * - **: any request option
57
+ *
58
+ * @param array $config Client configuration settings.
59
+ *
60
+ * @see \GuzzleHttp\RequestOptions for a list of available request options.
61
+ */
62
+ public function __construct(array $config = [])
63
+ {
64
+ if (!isset($config['handler'])) {
65
+ $config['handler'] = HandlerStack::create();
66
+ } elseif (!is_callable($config['handler'])) {
67
+ throw new \InvalidArgumentException('handler must be a callable');
68
+ }
69
+
70
+ // Convert the base_uri to a UriInterface
71
+ if (isset($config['base_uri'])) {
72
+ $config['base_uri'] = Psr7\uri_for($config['base_uri']);
73
+ }
74
+
75
+ $this->configureDefaults($config);
76
+ }
77
+
78
+ /**
79
+ * @param string $method
80
+ * @param array $args
81
+ *
82
+ * @return Promise\PromiseInterface
83
+ */
84
+ public function __call($method, $args)
85
+ {
86
+ if (count($args) < 1) {
87
+ throw new \InvalidArgumentException('Magic request methods require a URI and optional options array');
88
+ }
89
+
90
+ $uri = $args[0];
91
+ $opts = isset($args[1]) ? $args[1] : [];
92
+
93
+ return substr($method, -5) === 'Async'
94
+ ? $this->requestAsync(substr($method, 0, -5), $uri, $opts)
95
+ : $this->request($method, $uri, $opts);
96
+ }
97
+
98
+ /**
99
+ * Asynchronously send an HTTP request.
100
+ *
101
+ * @param array $options Request options to apply to the given
102
+ * request and to the transfer. See \GuzzleHttp\RequestOptions.
103
+ *
104
+ * @return Promise\PromiseInterface
105
+ */
106
+ public function sendAsync(RequestInterface $request, array $options = [])
107
+ {
108
+ // Merge the base URI into the request URI if needed.
109
+ $options = $this->prepareDefaults($options);
110
+
111
+ return $this->transfer(
112
+ $request->withUri($this->buildUri($request->getUri(), $options), $request->hasHeader('Host')),
113
+ $options
114
+ );
115
+ }
116
+
117
+ /**
118
+ * Send an HTTP request.
119
+ *
120
+ * @param array $options Request options to apply to the given
121
+ * request and to the transfer. See \GuzzleHttp\RequestOptions.
122
+ *
123
+ * @return ResponseInterface
124
+ * @throws GuzzleException
125
+ */
126
+ public function send(RequestInterface $request, array $options = [])
127
+ {
128
+ $options[RequestOptions::SYNCHRONOUS] = true;
129
+ return $this->sendAsync($request, $options)->wait();
130
+ }
131
+
132
+ /**
133
+ * Create and send an asynchronous HTTP request.
134
+ *
135
+ * Use an absolute path to override the base path of the client, or a
136
+ * relative path to append to the base path of the client. The URL can
137
+ * contain the query string as well. Use an array to provide a URL
138
+ * template and additional variables to use in the URL template expansion.
139
+ *
140
+ * @param string $method HTTP method
141
+ * @param string|UriInterface $uri URI object or string.
142
+ * @param array $options Request options to apply. See \GuzzleHttp\RequestOptions.
143
+ *
144
+ * @return Promise\PromiseInterface
145
+ */
146
+ public function requestAsync($method, $uri = '', array $options = [])
147
+ {
148
+ $options = $this->prepareDefaults($options);
149
+ // Remove request modifying parameter because it can be done up-front.
150
+ $headers = isset($options['headers']) ? $options['headers'] : [];
151
+ $body = isset($options['body']) ? $options['body'] : null;
152
+ $version = isset($options['version']) ? $options['version'] : '1.1';
153
+ // Merge the URI into the base URI.
154
+ $uri = $this->buildUri($uri, $options);
155
+ if (is_array($body)) {
156
+ $this->invalidBody();
157
+ }
158
+ $request = new Psr7\Request($method, $uri, $headers, $body, $version);
159
+ // Remove the option so that they are not doubly-applied.
160
+ unset($options['headers'], $options['body'], $options['version']);
161
+
162
+ return $this->transfer($request, $options);
163
+ }
164
+
165
+ /**
166
+ * Create and send an HTTP request.
167
+ *
168
+ * Use an absolute path to override the base path of the client, or a
169
+ * relative path to append to the base path of the client. The URL can
170
+ * contain the query string as well.
171
+ *
172
+ * @param string $method HTTP method.
173
+ * @param string|UriInterface $uri URI object or string.
174
+ * @param array $options Request options to apply. See \GuzzleHttp\RequestOptions.
175
+ *
176
+ * @return ResponseInterface
177
+ * @throws GuzzleException
178
+ */
179
+ public function request($method, $uri = '', array $options = [])
180
+ {
181
+ $options[RequestOptions::SYNCHRONOUS] = true;
182
+ return $this->requestAsync($method, $uri, $options)->wait();
183
+ }
184
+
185
+ /**
186
+ * Get a client configuration option.
187
+ *
188
+ * These options include default request options of the client, a "handler"
189
+ * (if utilized by the concrete client), and a "base_uri" if utilized by
190
+ * the concrete client.
191
+ *
192
+ * @param string|null $option The config option to retrieve.
193
+ *
194
+ * @return mixed
195
+ */
196
+ public function getConfig($option = null)
197
+ {
198
+ return $option === null
199
+ ? $this->config
200
+ : (isset($this->config[$option]) ? $this->config[$option] : null);
201
+ }
202
+
203
+ /**
204
+ * @param string|null $uri
205
+ *
206
+ * @return UriInterface
207
+ */
208
+ private function buildUri($uri, array $config)
209
+ {
210
+ // for BC we accept null which would otherwise fail in uri_for
211
+ $uri = Psr7\uri_for($uri === null ? '' : $uri);
212
+
213
+ if (isset($config['base_uri'])) {
214
+ $uri = Psr7\UriResolver::resolve(Psr7\uri_for($config['base_uri']), $uri);
215
+ }
216
+
217
+ if (isset($config['idn_conversion']) && ($config['idn_conversion'] !== false)) {
218
+ $idnOptions = ($config['idn_conversion'] === true) ? IDNA_DEFAULT : $config['idn_conversion'];
219
+ $uri = Utils::idnUriConvert($uri, $idnOptions);
220
+ }
221
+
222
+ return $uri->getScheme() === '' && $uri->getHost() !== '' ? $uri->withScheme('http') : $uri;
223
+ }
224
+
225
+ /**
226
+ * Configures the default options for a client.
227
+ *
228
+ * @param array $config
229
+ * @return void
230
+ */
231
+ private function configureDefaults(array $config)
232
+ {
233
+ $defaults = [
234
+ 'allow_redirects' => RedirectMiddleware::$defaultSettings,
235
+ 'http_errors' => true,
236
+ 'decode_content' => true,
237
+ 'verify' => true,
238
+ 'cookies' => false,
239
+ 'idn_conversion' => true,
240
+ ];
241
+
242
+ // Use the standard Linux HTTP_PROXY and HTTPS_PROXY if set.
243
+
244
+ // We can only trust the HTTP_PROXY environment variable in a CLI
245
+ // process due to the fact that PHP has no reliable mechanism to
246
+ // get environment variables that start with "HTTP_".
247
+ if (php_sapi_name() === 'cli' && getenv('HTTP_PROXY')) {
248
+ $defaults['proxy']['http'] = getenv('HTTP_PROXY');
249
+ }
250
+
251
+ if ($proxy = getenv('HTTPS_PROXY')) {
252
+ $defaults['proxy']['https'] = $proxy;
253
+ }
254
+
255
+ if ($noProxy = getenv('NO_PROXY')) {
256
+ $cleanedNoProxy = str_replace(' ', '', $noProxy);
257
+ $defaults['proxy']['no'] = explode(',', $cleanedNoProxy);
258
+ }
259
+
260
+ $this->config = $config + $defaults;
261
+
262
+ if (!empty($config['cookies']) && $config['cookies'] === true) {
263
+ $this->config['cookies'] = new CookieJar();
264
+ }
265
+
266
+ // Add the default user-agent header.
267
+ if (!isset($this->config['headers'])) {
268
+ $this->config['headers'] = ['User-Agent' => default_user_agent()];
269
+ } else {
270
+ // Add the User-Agent header if one was not already set.
271
+ foreach (array_keys($this->config['headers']) as $name) {
272
+ if (strtolower($name) === 'user-agent') {
273
+ return;
274
+ }
275
+ }
276
+ $this->config['headers']['User-Agent'] = default_user_agent();
277
+ }
278
+ }
279
+
280
+ /**
281
+ * Merges default options into the array.
282
+ *
283
+ * @param array $options Options to modify by reference
284
+ *
285
+ * @return array
286
+ */
287
+ private function prepareDefaults(array $options)
288
+ {
289
+ $defaults = $this->config;
290
+
291
+ if (!empty($defaults['headers'])) {
292
+ // Default headers are only added if they are not present.
293
+ $defaults['_conditional'] = $defaults['headers'];
294
+ unset($defaults['headers']);
295
+ }
296
+
297
+ // Special handling for headers is required as they are added as
298
+ // conditional headers and as headers passed to a request ctor.
299
+ if (array_key_exists('headers', $options)) {
300
+ // Allows default headers to be unset.
301
+ if ($options['headers'] === null) {
302
+ $defaults['_conditional'] = [];
303
+ unset($options['headers']);
304
+ } elseif (!is_array($options['headers'])) {
305
+ throw new \InvalidArgumentException('headers must be an array');
306
+ }
307
+ }
308
+
309
+ // Shallow merge defaults underneath options.
310
+ $result = $options + $defaults;
311
+
312
+ // Remove null values.
313
+ foreach ($result as $k => $v) {
314
+ if ($v === null) {
315
+ unset($result[$k]);
316
+ }
317
+ }
318
+
319
+ return $result;
320
+ }
321
+
322
+ /**
323
+ * Transfers the given request and applies request options.
324
+ *
325
+ * The URI of the request is not modified and the request options are used
326
+ * as-is without merging in default options.
327
+ *
328
+ * @param array $options See \GuzzleHttp\RequestOptions.
329
+ *
330
+ * @return Promise\PromiseInterface
331
+ */
332
+ private function transfer(RequestInterface $request, array $options)
333
+ {
334
+ // save_to -> sink
335
+ if (isset($options['save_to'])) {
336
+ $options['sink'] = $options['save_to'];
337
+ unset($options['save_to']);
338
+ }
339
+
340
+ // exceptions -> http_errors
341
+ if (isset($options['exceptions'])) {
342
+ $options['http_errors'] = $options['exceptions'];
343
+ unset($options['exceptions']);
344
+ }
345
+
346
+ $request = $this->applyOptions($request, $options);
347
+ /** @var HandlerStack $handler */
348
+ $handler = $options['handler'];
349
+
350
+ try {
351
+ return Promise\promise_for($handler($request, $options));
352
+ } catch (\Exception $e) {
353
+ return Promise\rejection_for($e);
354
+ }
355
+ }
356
+
357
+ /**
358
+ * Applies the array of request options to a request.
359
+ *
360
+ * @param RequestInterface $request
361
+ * @param array $options
362
+ *
363
+ * @return RequestInterface
364
+ */
365
+ private function applyOptions(RequestInterface $request, array &$options)
366
+ {
367
+ $modify = [
368
+ 'set_headers' => [],
369
+ ];
370
+
371
+ if (isset($options['headers'])) {
372
+ $modify['set_headers'] = $options['headers'];
373
+ unset($options['headers']);
374
+ }
375
+
376
+ if (isset($options['form_params'])) {
377
+ if (isset($options['multipart'])) {
378
+ throw new \InvalidArgumentException('You cannot use '
379
+ . 'form_params and multipart at the same time. Use the '
380
+ . 'form_params option if you want to send application/'
381
+ . 'x-www-form-urlencoded requests, and the multipart '
382
+ . 'option to send multipart/form-data requests.');
383
+ }
384
+ $options['body'] = http_build_query($options['form_params'], '', '&');
385
+ unset($options['form_params']);
386
+ // Ensure that we don't have the header in different case and set the new value.
387
+ $options['_conditional'] = Psr7\_caseless_remove(['Content-Type'], $options['_conditional']);
388
+ $options['_conditional']['Content-Type'] = 'application/x-www-form-urlencoded';
389
+ }
390
+
391
+ if (isset($options['multipart'])) {
392
+ $options['body'] = new Psr7\MultipartStream($options['multipart']);
393
+ unset($options['multipart']);
394
+ }
395
+
396
+ if (isset($options['json'])) {
397
+ $options['body'] = \GuzzleHttp\json_encode($options['json']);
398
+ unset($options['json']);
399
+ // Ensure that we don't have the header in different case and set the new value.
400
+ $options['_conditional'] = Psr7\_caseless_remove(['Content-Type'], $options['_conditional']);
401
+ $options['_conditional']['Content-Type'] = 'application/json';
402
+ }
403
+
404
+ if (!empty($options['decode_content'])
405
+ && $options['decode_content'] !== true
406
+ ) {
407
+ // Ensure that we don't have the header in different case and set the new value.
408
+ $options['_conditional'] = Psr7\_caseless_remove(['Accept-Encoding'], $options['_conditional']);
409
+ $modify['set_headers']['Accept-Encoding'] = $options['decode_content'];
410
+ }
411
+
412
+ if (isset($options['body'])) {
413
+ if (is_array($options['body'])) {
414
+ $this->invalidBody();
415
+ }
416
+ $modify['body'] = Psr7\stream_for($options['body']);
417
+ unset($options['body']);
418
+ }
419
+
420
+ if (!empty($options['auth']) && is_array($options['auth'])) {
421
+ $value = $options['auth'];
422
+ $type = isset($value[2]) ? strtolower($value[2]) : 'basic';
423
+ switch ($type) {
424
+ case 'basic':
425
+ // Ensure that we don't have the header in different case and set the new value.
426
+ $modify['set_headers'] = Psr7\_caseless_remove(['Authorization'], $modify['set_headers']);
427
+ $modify['set_headers']['Authorization'] = 'Basic '
428
+ . base64_encode("$value[0]:$value[1]");
429
+ break;
430
+ case 'digest':
431
+ // @todo: Do not rely on curl
432
+ $options['curl'][CURLOPT_HTTPAUTH] = CURLAUTH_DIGEST;
433
+ $options['curl'][CURLOPT_USERPWD] = "$value[0]:$value[1]";
434
+ break;
435
+ case 'ntlm':
436
+ $options['curl'][CURLOPT_HTTPAUTH] = CURLAUTH_NTLM;
437
+ $options['curl'][CURLOPT_USERPWD] = "$value[0]:$value[1]";
438
+ break;
439
+ }
440
+ }
441
+
442
+ if (isset($options['query'])) {
443
+ $value = $options['query'];
444
+ if (is_array($value)) {
445
+ $value = http_build_query($value, null, '&', PHP_QUERY_RFC3986);
446
+ }
447
+ if (!is_string($value)) {
448
+ throw new \InvalidArgumentException('query must be a string or array');
449
+ }
450
+ $modify['query'] = $value;
451
+ unset($options['query']);
452
+ }
453
+
454
+ // Ensure that sink is not an invalid value.
455
+ if (isset($options['sink'])) {
456
+ // TODO: Add more sink validation?
457
+ if (is_bool($options['sink'])) {
458
+ throw new \InvalidArgumentException('sink must not be a boolean');
459
+ }
460
+ }
461
+
462
+ $request = Psr7\modify_request($request, $modify);
463
+ if ($request->getBody() instanceof Psr7\MultipartStream) {
464
+ // Use a multipart/form-data POST if a Content-Type is not set.
465
+ // Ensure that we don't have the header in different case and set the new value.
466
+ $options['_conditional'] = Psr7\_caseless_remove(['Content-Type'], $options['_conditional']);
467
+ $options['_conditional']['Content-Type'] = 'multipart/form-data; boundary='
468
+ . $request->getBody()->getBoundary();
469
+ }
470
+
471
+ // Merge in conditional headers if they are not present.
472
+ if (isset($options['_conditional'])) {
473
+ // Build up the changes so it's in a single clone of the message.
474
+ $modify = [];
475
+ foreach ($options['_conditional'] as $k => $v) {
476
+ if (!$request->hasHeader($k)) {
477
+ $modify['set_headers'][$k] = $v;
478
+ }
479
+ }
480
+ $request = Psr7\modify_request($request, $modify);
481
+ // Don't pass this internal value along to middleware/handlers.
482
+ unset($options['_conditional']);
483
+ }
484
+
485
+ return $request;
486
+ }
487
+
488
+ /**
489
+ * Throw Exception with pre-set message.
490
+ * @return void
491
+ * @throws \InvalidArgumentException Invalid body.
492
+ */
493
+ private function invalidBody()
494
+ {
495
+ throw new \InvalidArgumentException('Passing in the "body" request '
496
+ . 'option as an array to send a POST request has been deprecated. '
497
+ . 'Please use the "form_params" request option to send a '
498
+ . 'application/x-www-form-urlencoded request, or the "multipart" '
499
+ . 'request option to send a multipart/form-data request.');
500
+ }
501
+ }
vendor/guzzlehttp/guzzle/src/ClientInterface.php ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp;
3
+
4
+ use GuzzleHttp\Exception\GuzzleException;
5
+ use GuzzleHttp\Promise\PromiseInterface;
6
+ use Psr\Http\Message\RequestInterface;
7
+ use Psr\Http\Message\ResponseInterface;
8
+ use Psr\Http\Message\UriInterface;
9
+
10
+ /**
11
+ * Client interface for sending HTTP requests.
12
+ */
13
+ interface ClientInterface
14
+ {
15
+ /**
16
+ * @deprecated Will be removed in Guzzle 7.0.0
17
+ */
18
+ const VERSION = '6.5.5';
19
+
20
+ /**
21
+ * Send an HTTP request.
22
+ *
23
+ * @param RequestInterface $request Request to send
24
+ * @param array $options Request options to apply to the given
25
+ * request and to the transfer.
26
+ *
27
+ * @return ResponseInterface
28
+ * @throws GuzzleException
29
+ */
30
+ public function send(RequestInterface $request, array $options = []);
31
+
32
+ /**
33
+ * Asynchronously send an HTTP request.
34
+ *
35
+ * @param RequestInterface $request Request to send
36
+ * @param array $options Request options to apply to the given
37
+ * request and to the transfer.
38
+ *
39
+ * @return PromiseInterface
40
+ */
41
+ public function sendAsync(RequestInterface $request, array $options = []);
42
+
43
+ /**
44
+ * Create and send an HTTP request.
45
+ *
46
+ * Use an absolute path to override the base path of the client, or a
47
+ * relative path to append to the base path of the client. The URL can
48
+ * contain the query string as well.
49
+ *
50
+ * @param string $method HTTP method.
51
+ * @param string|UriInterface $uri URI object or string.
52
+ * @param array $options Request options to apply.
53
+ *
54
+ * @return ResponseInterface
55
+ * @throws GuzzleException
56
+ */
57
+ public function request($method, $uri, array $options = []);
58
+
59
+ /**
60
+ * Create and send an asynchronous HTTP request.
61
+ *
62
+ * Use an absolute path to override the base path of the client, or a
63
+ * relative path to append to the base path of the client. The URL can
64
+ * contain the query string as well. Use an array to provide a URL
65
+ * template and additional variables to use in the URL template expansion.
66
+ *
67
+ * @param string $method HTTP method
68
+ * @param string|UriInterface $uri URI object or string.
69
+ * @param array $options Request options to apply.
70
+ *
71
+ * @return PromiseInterface
72
+ */
73
+ public function requestAsync($method, $uri, array $options = []);
74
+
75
+ /**
76
+ * Get a client configuration option.
77
+ *
78
+ * These options include default request options of the client, a "handler"
79
+ * (if utilized by the concrete client), and a "base_uri" if utilized by
80
+ * the concrete client.
81
+ *
82
+ * @param string|null $option The config option to retrieve.
83
+ *
84
+ * @return mixed
85
+ */
86
+ public function getConfig($option = null);
87
+ }
vendor/guzzlehttp/guzzle/src/Cookie/CookieJar.php ADDED
@@ -0,0 +1,316 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Cookie;
3
+
4
+ use Psr\Http\Message\RequestInterface;
5
+ use Psr\Http\Message\ResponseInterface;
6
+
7
+ /**
8
+ * Cookie jar that stores cookies as an array
9
+ */
10
+ class CookieJar implements CookieJarInterface
11
+ {
12
+ /** @var SetCookie[] Loaded cookie data */
13
+ private $cookies = [];
14
+
15
+ /** @var bool */
16
+ private $strictMode;
17
+
18
+ /**
19
+ * @param bool $strictMode Set to true to throw exceptions when invalid
20
+ * cookies are added to the cookie jar.
21
+ * @param array $cookieArray Array of SetCookie objects or a hash of
22
+ * arrays that can be used with the SetCookie
23
+ * constructor
24
+ */
25
+ public function __construct($strictMode = false, $cookieArray = [])
26
+ {
27
+ $this->strictMode = $strictMode;
28
+
29
+ foreach ($cookieArray as $cookie) {
30
+ if (!($cookie instanceof SetCookie)) {
31
+ $cookie = new SetCookie($cookie);
32
+ }
33
+ $this->setCookie($cookie);
34
+ }
35
+ }
36
+
37
+ /**
38
+ * Create a new Cookie jar from an associative array and domain.
39
+ *
40
+ * @param array $cookies Cookies to create the jar from
41
+ * @param string $domain Domain to set the cookies to
42
+ *
43
+ * @return self
44
+ */
45
+ public static function fromArray(array $cookies, $domain)
46
+ {
47
+ $cookieJar = new self();
48
+ foreach ($cookies as $name => $value) {
49
+ $cookieJar->setCookie(new SetCookie([
50
+ 'Domain' => $domain,
51
+ 'Name' => $name,
52
+ 'Value' => $value,
53
+ 'Discard' => true
54
+ ]));
55
+ }
56
+
57
+ return $cookieJar;
58
+ }
59
+
60
+ /**
61
+ * @deprecated
62
+ */
63
+ public static function getCookieValue($value)
64
+ {
65
+ return $value;
66
+ }
67
+
68
+ /**
69
+ * Evaluate if this cookie should be persisted to storage
70
+ * that survives between requests.
71
+ *
72
+ * @param SetCookie $cookie Being evaluated.
73
+ * @param bool $allowSessionCookies If we should persist session cookies
74
+ * @return bool
75
+ */
76
+ public static function shouldPersist(
77
+ SetCookie $cookie,
78
+ $allowSessionCookies = false
79
+ ) {
80
+ if ($cookie->getExpires() || $allowSessionCookies) {
81
+ if (!$cookie->getDiscard()) {
82
+ return true;
83
+ }
84
+ }
85
+
86
+ return false;
87
+ }
88
+
89
+ /**
90
+ * Finds and returns the cookie based on the name
91
+ *
92
+ * @param string $name cookie name to search for
93
+ * @return SetCookie|null cookie that was found or null if not found
94
+ */
95
+ public function getCookieByName($name)
96
+ {
97
+ // don't allow a non string name
98
+ if ($name === null || !is_scalar($name)) {
99
+ return null;
100
+ }
101
+ foreach ($this->cookies as $cookie) {
102
+ if ($cookie->getName() !== null && strcasecmp($cookie->getName(), $name) === 0) {
103
+ return $cookie;
104
+ }
105
+ }
106
+
107
+ return null;
108
+ }
109
+
110
+ public function toArray()
111
+ {
112
+ return array_map(function (SetCookie $cookie) {
113
+ return $cookie->toArray();
114
+ }, $this->getIterator()->getArrayCopy());
115
+ }
116
+
117
+ public function clear($domain = null, $path = null, $name = null)
118
+ {
119
+ if (!$domain) {
120
+ $this->cookies = [];
121
+ return;
122
+ } elseif (!$path) {
123
+ $this->cookies = array_filter(
124
+ $this->cookies,
125
+ function (SetCookie $cookie) use ($domain) {
126
+ return !$cookie->matchesDomain($domain);
127
+ }
128
+ );
129
+ } elseif (!$name) {
130
+ $this->cookies = array_filter(
131
+ $this->cookies,
132
+ function (SetCookie $cookie) use ($path, $domain) {
133
+ return !($cookie->matchesPath($path) &&
134
+ $cookie->matchesDomain($domain));
135
+ }
136
+ );
137
+ } else {
138
+ $this->cookies = array_filter(
139
+ $this->cookies,
140
+ function (SetCookie $cookie) use ($path, $domain, $name) {
141
+ return !($cookie->getName() == $name &&
142
+ $cookie->matchesPath($path) &&
143
+ $cookie->matchesDomain($domain));
144
+ }
145
+ );
146
+ }
147
+ }
148
+
149
+ public function clearSessionCookies()
150
+ {
151
+ $this->cookies = array_filter(
152
+ $this->cookies,
153
+ function (SetCookie $cookie) {
154
+ return !$cookie->getDiscard() && $cookie->getExpires();
155
+ }
156
+ );
157
+ }
158
+
159
+ public function setCookie(SetCookie $cookie)
160
+ {
161
+ // If the name string is empty (but not 0), ignore the set-cookie
162
+ // string entirely.
163
+ $name = $cookie->getName();
164
+ if (!$name && $name !== '0') {
165
+ return false;
166
+ }
167
+
168
+ // Only allow cookies with set and valid domain, name, value
169
+ $result = $cookie->validate();
170
+ if ($result !== true) {
171
+ if ($this->strictMode) {
172
+ throw new \RuntimeException('Invalid cookie: ' . $result);
173
+ } else {
174
+ $this->removeCookieIfEmpty($cookie);
175
+ return false;
176
+ }
177
+ }
178
+
179
+ // Resolve conflicts with previously set cookies
180
+ foreach ($this->cookies as $i => $c) {
181
+
182
+ // Two cookies are identical, when their path, and domain are
183
+ // identical.
184
+ if ($c->getPath() != $cookie->getPath() ||
185
+ $c->getDomain() != $cookie->getDomain() ||
186
+ $c->getName() != $cookie->getName()
187
+ ) {
188
+ continue;
189
+ }
190
+
191
+ // The previously set cookie is a discard cookie and this one is
192
+ // not so allow the new cookie to be set
193
+ if (!$cookie->getDiscard() && $c->getDiscard()) {
194
+ unset($this->cookies[$i]);
195
+ continue;
196
+ }
197
+
198
+ // If the new cookie's expiration is further into the future, then
199
+ // replace the old cookie
200
+ if ($cookie->getExpires() > $c->getExpires()) {
201
+ unset($this->cookies[$i]);
202
+ continue;
203
+ }
204
+
205
+ // If the value has changed, we better change it
206
+ if ($cookie->getValue() !== $c->getValue()) {
207
+ unset($this->cookies[$i]);
208
+ continue;
209
+ }
210
+
211
+ // The cookie exists, so no need to continue
212
+ return false;
213
+ }
214
+
215
+ $this->cookies[] = $cookie;
216
+
217
+ return true;
218
+ }
219
+
220
+ public function count()
221
+ {
222
+ return count($this->cookies);
223
+ }
224
+
225
+ public function getIterator()
226
+ {
227
+ return new \ArrayIterator(array_values($this->cookies));
228
+ }
229
+
230
+ public function extractCookies(
231
+ RequestInterface $request,
232
+ ResponseInterface $response
233
+ ) {
234
+ if ($cookieHeader = $response->getHeader('Set-Cookie')) {
235
+ foreach ($cookieHeader as $cookie) {
236
+ $sc = SetCookie::fromString($cookie);
237
+ if (!$sc->getDomain()) {
238
+ $sc->setDomain($request->getUri()->getHost());
239
+ }
240
+ if (0 !== strpos($sc->getPath(), '/')) {
241
+ $sc->setPath($this->getCookiePathFromRequest($request));
242
+ }
243
+ $this->setCookie($sc);
244
+ }
245
+ }
246
+ }
247
+
248
+ /**
249
+ * Computes cookie path following RFC 6265 section 5.1.4
250
+ *
251
+ * @link https://tools.ietf.org/html/rfc6265#section-5.1.4
252
+ *
253
+ * @param RequestInterface $request
254
+ * @return string
255
+ */
256
+ private function getCookiePathFromRequest(RequestInterface $request)
257
+ {
258
+ $uriPath = $request->getUri()->getPath();
259
+ if ('' === $uriPath) {
260
+ return '/';
261
+ }
262
+ if (0 !== strpos($uriPath, '/')) {
263
+ return '/';
264
+ }
265
+ if ('/' === $uriPath) {
266
+ return '/';
267
+ }
268
+ if (0 === $lastSlashPos = strrpos($uriPath, '/')) {
269
+ return '/';
270
+ }
271
+
272
+ return substr($uriPath, 0, $lastSlashPos);
273
+ }
274
+
275
+ public function withCookieHeader(RequestInterface $request)
276
+ {
277
+ $values = [];
278
+ $uri = $request->getUri();
279
+ $scheme = $uri->getScheme();
280
+ $host = $uri->getHost();
281
+ $path = $uri->getPath() ?: '/';
282
+
283
+ foreach ($this->cookies as $cookie) {
284
+ if ($cookie->matchesPath($path) &&
285
+ $cookie->matchesDomain($host) &&
286
+ !$cookie->isExpired() &&
287
+ (!$cookie->getSecure() || $scheme === 'https')
288
+ ) {
289
+ $values[] = $cookie->getName() . '='
290
+ . $cookie->getValue();
291
+ }
292
+ }
293
+
294
+ return $values
295
+ ? $request->withHeader('Cookie', implode('; ', $values))
296
+ : $request;
297
+ }
298
+
299
+ /**
300
+ * If a cookie already exists and the server asks to set it again with a
301
+ * null value, the cookie must be deleted.
302
+ *
303
+ * @param SetCookie $cookie
304
+ */
305
+ private function removeCookieIfEmpty(SetCookie $cookie)
306
+ {
307
+ $cookieValue = $cookie->getValue();
308
+ if ($cookieValue === null || $cookieValue === '') {
309
+ $this->clear(
310
+ $cookie->getDomain(),
311
+ $cookie->getPath(),
312
+ $cookie->getName()
313
+ );
314
+ }
315
+ }
316
+ }
vendor/guzzlehttp/guzzle/src/Cookie/CookieJarInterface.php ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Cookie;
3
+
4
+ use Psr\Http\Message\RequestInterface;
5
+ use Psr\Http\Message\ResponseInterface;
6
+
7
+ /**
8
+ * Stores HTTP cookies.
9
+ *
10
+ * It extracts cookies from HTTP requests, and returns them in HTTP responses.
11
+ * CookieJarInterface instances automatically expire contained cookies when
12
+ * necessary. Subclasses are also responsible for storing and retrieving
13
+ * cookies from a file, database, etc.
14
+ *
15
+ * @link http://docs.python.org/2/library/cookielib.html Inspiration
16
+ */
17
+ interface CookieJarInterface extends \Countable, \IteratorAggregate
18
+ {
19
+ /**
20
+ * Create a request with added cookie headers.
21
+ *
22
+ * If no matching cookies are found in the cookie jar, then no Cookie
23
+ * header is added to the request and the same request is returned.
24
+ *
25
+ * @param RequestInterface $request Request object to modify.
26
+ *
27
+ * @return RequestInterface returns the modified request.
28
+ */
29
+ public function withCookieHeader(RequestInterface $request);
30
+
31
+ /**
32
+ * Extract cookies from an HTTP response and store them in the CookieJar.
33
+ *
34
+ * @param RequestInterface $request Request that was sent
35
+ * @param ResponseInterface $response Response that was received
36
+ */
37
+ public function extractCookies(
38
+ RequestInterface $request,
39
+ ResponseInterface $response
40
+ );
41
+
42
+ /**
43
+ * Sets a cookie in the cookie jar.
44
+ *
45
+ * @param SetCookie $cookie Cookie to set.
46
+ *
47
+ * @return bool Returns true on success or false on failure
48
+ */
49
+ public function setCookie(SetCookie $cookie);
50
+
51
+ /**
52
+ * Remove cookies currently held in the cookie jar.
53
+ *
54
+ * Invoking this method without arguments will empty the whole cookie jar.
55
+ * If given a $domain argument only cookies belonging to that domain will
56
+ * be removed. If given a $domain and $path argument, cookies belonging to
57
+ * the specified path within that domain are removed. If given all three
58
+ * arguments, then the cookie with the specified name, path and domain is
59
+ * removed.
60
+ *
61
+ * @param string|null $domain Clears cookies matching a domain
62
+ * @param string|null $path Clears cookies matching a domain and path
63
+ * @param string|null $name Clears cookies matching a domain, path, and name
64
+ *
65
+ * @return CookieJarInterface
66
+ */
67
+ public function clear($domain = null, $path = null, $name = null);
68
+
69
+ /**
70
+ * Discard all sessions cookies.
71
+ *
72
+ * Removes cookies that don't have an expire field or a have a discard
73
+ * field set to true. To be called when the user agent shuts down according
74
+ * to RFC 2965.
75
+ */
76
+ public function clearSessionCookies();
77
+
78
+ /**
79
+ * Converts the cookie jar to an array.
80
+ *
81
+ * @return array
82
+ */
83
+ public function toArray();
84
+ }
vendor/guzzlehttp/guzzle/src/Cookie/FileCookieJar.php ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Cookie;
3
+
4
+ /**
5
+ * Persists non-session cookies using a JSON formatted file
6
+ */
7
+ class FileCookieJar extends CookieJar
8
+ {
9
+ /** @var string filename */
10
+ private $filename;
11
+
12
+ /** @var bool Control whether to persist session cookies or not. */
13
+ private $storeSessionCookies;
14
+
15
+ /**
16
+ * Create a new FileCookieJar object
17
+ *
18
+ * @param string $cookieFile File to store the cookie data
19
+ * @param bool $storeSessionCookies Set to true to store session cookies
20
+ * in the cookie jar.
21
+ *
22
+ * @throws \RuntimeException if the file cannot be found or created
23
+ */
24
+ public function __construct($cookieFile, $storeSessionCookies = false)
25
+ {
26
+ parent::__construct();
27
+ $this->filename = $cookieFile;
28
+ $this->storeSessionCookies = $storeSessionCookies;
29
+
30
+ if (file_exists($cookieFile)) {
31
+ $this->load($cookieFile);
32
+ }
33
+ }
34
+
35
+ /**
36
+ * Saves the file when shutting down
37
+ */
38
+ public function __destruct()
39
+ {
40
+ $this->save($this->filename);
41
+ }
42
+
43
+ /**
44
+ * Saves the cookies to a file.
45
+ *
46
+ * @param string $filename File to save
47
+ * @throws \RuntimeException if the file cannot be found or created
48
+ */
49
+ public function save($filename)
50
+ {
51
+ $json = [];
52
+ foreach ($this as $cookie) {
53
+ /** @var SetCookie $cookie */
54
+ if (CookieJar::shouldPersist($cookie, $this->storeSessionCookies)) {
55
+ $json[] = $cookie->toArray();
56
+ }
57
+ }
58
+
59
+ $jsonStr = \GuzzleHttp\json_encode($json);
60
+ if (false === file_put_contents($filename, $jsonStr, LOCK_EX)) {
61
+ throw new \RuntimeException("Unable to save file {$filename}");
62
+ }
63
+ }
64
+
65
+ /**
66
+ * Load cookies from a JSON formatted file.
67
+ *
68
+ * Old cookies are kept unless overwritten by newly loaded ones.
69
+ *
70
+ * @param string $filename Cookie file to load.
71
+ * @throws \RuntimeException if the file cannot be loaded.
72
+ */
73
+ public function load($filename)
74
+ {
75
+ $json = file_get_contents($filename);
76
+ if (false === $json) {
77
+ throw new \RuntimeException("Unable to load file {$filename}");
78
+ } elseif ($json === '') {
79
+ return;
80
+ }
81
+
82
+ $data = \GuzzleHttp\json_decode($json, true);
83
+ if (is_array($data)) {
84
+ foreach (json_decode($json, true) as $cookie) {
85
+ $this->setCookie(new SetCookie($cookie));
86
+ }
87
+ } elseif (strlen($data)) {
88
+ throw new \RuntimeException("Invalid cookie file: {$filename}");
89
+ }
90
+ }
91
+ }
vendor/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Cookie;
3
+
4
+ /**
5
+ * Persists cookies in the client session
6
+ */
7
+ class SessionCookieJar extends CookieJar
8
+ {
9
+ /** @var string session key */
10
+ private $sessionKey;
11
+
12
+ /** @var bool Control whether to persist session cookies or not. */
13
+ private $storeSessionCookies;
14
+
15
+ /**
16
+ * Create a new SessionCookieJar object
17
+ *
18
+ * @param string $sessionKey Session key name to store the cookie
19
+ * data in session
20
+ * @param bool $storeSessionCookies Set to true to store session cookies
21
+ * in the cookie jar.
22
+ */
23
+ public function __construct($sessionKey, $storeSessionCookies = false)
24
+ {
25
+ parent::__construct();
26
+ $this->sessionKey = $sessionKey;
27
+ $this->storeSessionCookies = $storeSessionCookies;
28
+ $this->load();
29
+ }
30
+
31
+ /**
32
+ * Saves cookies to session when shutting down
33
+ */
34
+ public function __destruct()
35
+ {
36
+ $this->save();
37
+ }
38
+
39
+ /**
40
+ * Save cookies to the client session
41
+ */
42
+ public function save()
43
+ {
44
+ $json = [];
45
+ foreach ($this as $cookie) {
46
+ /** @var SetCookie $cookie */
47
+ if (CookieJar::shouldPersist($cookie, $this->storeSessionCookies)) {
48
+ $json[] = $cookie->toArray();
49
+ }
50
+ }
51
+
52
+ $_SESSION[$this->sessionKey] = json_encode($json);
53
+ }
54
+
55
+ /**
56
+ * Load the contents of the client session into the data array
57
+ */
58
+ protected function load()
59
+ {
60
+ if (!isset($_SESSION[$this->sessionKey])) {
61
+ return;
62
+ }
63
+ $data = json_decode($_SESSION[$this->sessionKey], true);
64
+ if (is_array($data)) {
65
+ foreach ($data as $cookie) {
66
+ $this->setCookie(new SetCookie($cookie));
67
+ }
68
+ } elseif (strlen($data)) {
69
+ throw new \RuntimeException("Invalid cookie data");
70
+ }
71
+ }
72
+ }
vendor/guzzlehttp/guzzle/src/Cookie/SetCookie.php ADDED
@@ -0,0 +1,403 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Cookie;
3
+
4
+ /**
5
+ * Set-Cookie object
6
+ */
7
+ class SetCookie
8
+ {
9
+ /** @var array */
10
+ private static $defaults = [
11
+ 'Name' => null,
12
+ 'Value' => null,
13
+ 'Domain' => null,
14
+ 'Path' => '/',
15
+ 'Max-Age' => null,
16
+ 'Expires' => null,
17
+ 'Secure' => false,
18
+ 'Discard' => false,
19
+ 'HttpOnly' => false
20
+ ];
21
+
22
+ /** @var array Cookie data */
23
+ private $data;
24
+
25
+ /**
26
+ * Create a new SetCookie object from a string
27
+ *
28
+ * @param string $cookie Set-Cookie header string
29
+ *
30
+ * @return self
31
+ */
32
+ public static function fromString($cookie)
33
+ {
34
+ // Create the default return array
35
+ $data = self::$defaults;
36
+ // Explode the cookie string using a series of semicolons
37
+ $pieces = array_filter(array_map('trim', explode(';', $cookie)));
38
+ // The name of the cookie (first kvp) must exist and include an equal sign.
39
+ if (empty($pieces[0]) || !strpos($pieces[0], '=')) {
40
+ return new self($data);
41
+ }
42
+
43
+ // Add the cookie pieces into the parsed data array
44
+ foreach ($pieces as $part) {
45
+ $cookieParts = explode('=', $part, 2);
46
+ $key = trim($cookieParts[0]);
47
+ $value = isset($cookieParts[1])
48
+ ? trim($cookieParts[1], " \n\r\t\0\x0B")
49
+ : true;
50
+
51
+ // Only check for non-cookies when cookies have been found
52
+ if (empty($data['Name'])) {
53
+ $data['Name'] = $key;
54
+ $data['Value'] = $value;
55
+ } else {
56
+ foreach (array_keys(self::$defaults) as $search) {
57
+ if (!strcasecmp($search, $key)) {
58
+ $data[$search] = $value;
59
+ continue 2;
60
+ }
61
+ }
62
+ $data[$key] = $value;
63
+ }
64
+ }
65
+
66
+ return new self($data);
67
+ }
68
+
69
+ /**
70
+ * @param array $data Array of cookie data provided by a Cookie parser
71
+ */
72
+ public function __construct(array $data = [])
73
+ {
74
+ $this->data = array_replace(self::$defaults, $data);
75
+ // Extract the Expires value and turn it into a UNIX timestamp if needed
76
+ if (!$this->getExpires() && $this->getMaxAge()) {
77
+ // Calculate the Expires date
78
+ $this->setExpires(time() + $this->getMaxAge());
79
+ } elseif ($this->getExpires() && !is_numeric($this->getExpires())) {
80
+ $this->setExpires($this->getExpires());
81
+ }
82
+ }
83
+
84
+ public function __toString()
85
+ {
86
+ $str = $this->data['Name'] . '=' . $this->data['Value'] . '; ';
87
+ foreach ($this->data as $k => $v) {
88
+ if ($k !== 'Name' && $k !== 'Value' && $v !== null && $v !== false) {
89
+ if ($k === 'Expires') {
90
+ $str .= 'Expires=' . gmdate('D, d M Y H:i:s \G\M\T', $v) . '; ';
91
+ } else {
92
+ $str .= ($v === true ? $k : "{$k}={$v}") . '; ';
93
+ }
94
+ }
95
+ }
96
+
97
+ return rtrim($str, '; ');
98
+ }
99
+
100
+ public function toArray()
101
+ {
102
+ return $this->data;
103
+ }
104
+
105
+ /**
106
+ * Get the cookie name
107
+ *
108
+ * @return string
109
+ */
110
+ public function getName()
111
+ {
112
+ return $this->data['Name'];
113
+ }
114
+
115
+ /**
116
+ * Set the cookie name
117
+ *
118
+ * @param string $name Cookie name
119
+ */
120
+ public function setName($name)
121
+ {
122
+ $this->data['Name'] = $name;
123
+ }
124
+
125
+ /**
126
+ * Get the cookie value
127
+ *
128
+ * @return string
129
+ */
130
+ public function getValue()
131
+ {
132
+ return $this->data['Value'];
133
+ }
134
+
135
+ /**
136
+ * Set the cookie value
137
+ *
138
+ * @param string $value Cookie value
139
+ */
140
+ public function setValue($value)
141
+ {
142
+ $this->data['Value'] = $value;
143
+ }
144
+
145
+ /**
146
+ * Get the domain
147
+ *
148
+ * @return string|null
149
+ */
150
+ public function getDomain()
151
+ {
152
+ return $this->data['Domain'];
153
+ }
154
+
155
+ /**
156
+ * Set the domain of the cookie
157
+ *
158
+ * @param string $domain
159
+ */
160
+ public function setDomain($domain)
161
+ {
162
+ $this->data['Domain'] = $domain;
163
+ }
164
+
165
+ /**
166
+ * Get the path
167
+ *
168
+ * @return string
169
+ */
170
+ public function getPath()
171
+ {
172
+ return $this->data['Path'];
173
+ }
174
+
175
+ /**
176
+ * Set the path of the cookie
177
+ *
178
+ * @param string $path Path of the cookie
179
+ */
180
+ public function setPath($path)
181
+ {
182
+ $this->data['Path'] = $path;
183
+ }
184
+
185
+ /**
186
+ * Maximum lifetime of the cookie in seconds
187
+ *
188
+ * @return int|null
189
+ */
190
+ public function getMaxAge()
191
+ {
192
+ return $this->data['Max-Age'];
193
+ }
194
+
195
+ /**
196
+ * Set the max-age of the cookie
197
+ *
198
+ * @param int $maxAge Max age of the cookie in seconds
199
+ */
200
+ public function setMaxAge($maxAge)
201
+ {
202
+ $this->data['Max-Age'] = $maxAge;
203
+ }
204
+
205
+ /**
206
+ * The UNIX timestamp when the cookie Expires
207
+ *
208
+ * @return mixed
209
+ */
210
+ public function getExpires()
211
+ {
212
+ return $this->data['Expires'];
213
+ }
214
+
215
+ /**
216
+ * Set the unix timestamp for which the cookie will expire
217
+ *
218
+ * @param int $timestamp Unix timestamp
219
+ */
220
+ public function setExpires($timestamp)
221
+ {
222
+ $this->data['Expires'] = is_numeric($timestamp)
223
+ ? (int) $timestamp
224
+ : strtotime($timestamp);
225
+ }
226
+
227
+ /**
228
+ * Get whether or not this is a secure cookie
229
+ *
230
+ * @return bool|null
231
+ */
232
+ public function getSecure()
233
+ {
234
+ return $this->data['Secure'];
235
+ }
236
+
237
+ /**
238
+ * Set whether or not the cookie is secure
239
+ *
240
+ * @param bool $secure Set to true or false if secure
241
+ */
242
+ public function setSecure($secure)
243
+ {
244
+ $this->data['Secure'] = $secure;
245
+ }
246
+
247
+ /**
248
+ * Get whether or not this is a session cookie
249
+ *
250
+ * @return bool|null
251
+ */
252
+ public function getDiscard()
253
+ {
254
+ return $this->data['Discard'];
255
+ }
256
+
257
+ /**
258
+ * Set whether or not this is a session cookie
259
+ *
260
+ * @param bool $discard Set to true or false if this is a session cookie
261
+ */
262
+ public function setDiscard($discard)
263
+ {
264
+ $this->data['Discard'] = $discard;
265
+ }
266
+
267
+ /**
268
+ * Get whether or not this is an HTTP only cookie
269
+ *
270
+ * @return bool
271
+ */
272
+ public function getHttpOnly()
273
+ {
274
+ return $this->data['HttpOnly'];
275
+ }
276
+
277
+ /**
278
+ * Set whether or not this is an HTTP only cookie
279
+ *
280
+ * @param bool $httpOnly Set to true or false if this is HTTP only
281
+ */
282
+ public function setHttpOnly($httpOnly)
283
+ {
284
+ $this->data['HttpOnly'] = $httpOnly;
285
+ }
286
+
287
+ /**
288
+ * Check if the cookie matches a path value.
289
+ *
290
+ * A request-path path-matches a given cookie-path if at least one of
291
+ * the following conditions holds:
292
+ *
293
+ * - The cookie-path and the request-path are identical.
294
+ * - The cookie-path is a prefix of the request-path, and the last
295
+ * character of the cookie-path is %x2F ("/").
296
+ * - The cookie-path is a prefix of the request-path, and the first
297
+ * character of the request-path that is not included in the cookie-
298
+ * path is a %x2F ("/") character.
299
+ *
300
+ * @param string $requestPath Path to check against
301
+ *
302
+ * @return bool
303
+ */
304
+ public function matchesPath($requestPath)
305
+ {
306
+ $cookiePath = $this->getPath();
307
+
308
+ // Match on exact matches or when path is the default empty "/"
309
+ if ($cookiePath === '/' || $cookiePath == $requestPath) {
310
+ return true;
311
+ }
312
+
313
+ // Ensure that the cookie-path is a prefix of the request path.
314
+ if (0 !== strpos($requestPath, $cookiePath)) {
315
+ return false;
316
+ }
317
+
318
+ // Match if the last character of the cookie-path is "/"
319
+ if (substr($cookiePath, -1, 1) === '/') {
320
+ return true;
321
+ }
322
+
323
+ // Match if the first character not included in cookie path is "/"
324
+ return substr($requestPath, strlen($cookiePath), 1) === '/';
325
+ }
326
+
327
+ /**
328
+ * Check if the cookie matches a domain value
329
+ *
330
+ * @param string $domain Domain to check against
331
+ *
332
+ * @return bool
333
+ */
334
+ public function matchesDomain($domain)
335
+ {
336
+ // Remove the leading '.' as per spec in RFC 6265.
337
+ // http://tools.ietf.org/html/rfc6265#section-5.2.3
338
+ $cookieDomain = ltrim($this->getDomain(), '.');
339
+
340
+ // Domain not set or exact match.
341
+ if (!$cookieDomain || !strcasecmp($domain, $cookieDomain)) {
342
+ return true;
343
+ }
344
+
345
+ // Matching the subdomain according to RFC 6265.
346
+ // http://tools.ietf.org/html/rfc6265#section-5.1.3
347
+ if (filter_var($domain, FILTER_VALIDATE_IP)) {
348
+ return false;
349
+ }
350
+
351
+ return (bool) preg_match('/\.' . preg_quote($cookieDomain, '/') . '$/', $domain);
352
+ }
353
+
354
+ /**
355
+ * Check if the cookie is expired
356
+ *
357
+ * @return bool
358
+ */
359
+ public function isExpired()
360
+ {
361
+ return $this->getExpires() !== null && time() > $this->getExpires();
362
+ }
363
+
364
+ /**
365
+ * Check if the cookie is valid according to RFC 6265
366
+ *
367
+ * @return bool|string Returns true if valid or an error message if invalid
368
+ */
369
+ public function validate()
370
+ {
371
+ // Names must not be empty, but can be 0
372
+ $name = $this->getName();
373
+ if (empty($name) && !is_numeric($name)) {
374
+ return 'The cookie name must not be empty';
375
+ }
376
+
377
+ // Check if any of the invalid characters are present in the cookie name
378
+ if (preg_match(
379
+ '/[\x00-\x20\x22\x28-\x29\x2c\x2f\x3a-\x40\x5c\x7b\x7d\x7f]/',
380
+ $name
381
+ )) {
382
+ return 'Cookie name must not contain invalid characters: ASCII '
383
+ . 'Control characters (0-31;127), space, tab and the '
384
+ . 'following characters: ()<>@,;:\"/?={}';
385
+ }
386
+
387
+ // Value must not be empty, but can be 0
388
+ $value = $this->getValue();
389
+ if (empty($value) && !is_numeric($value)) {
390
+ return 'The cookie value must not be empty';
391
+ }
392
+
393
+ // Domains must not be empty, but can be 0
394
+ // A "0" is not a valid internet domain, but may be used as server name
395
+ // in a private network.
396
+ $domain = $this->getDomain();
397
+ if (empty($domain) && !is_numeric($domain)) {
398
+ return 'The cookie domain must not be empty';
399
+ }
400
+
401
+ return true;
402
+ }
403
+ }
vendor/guzzlehttp/guzzle/src/Exception/BadResponseException.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Exception;
3
+
4
+ use Psr\Http\Message\RequestInterface;
5
+ use Psr\Http\Message\ResponseInterface;
6
+
7
+ /**
8
+ * Exception when an HTTP error occurs (4xx or 5xx error)
9
+ */
10
+ class BadResponseException extends RequestException
11
+ {
12
+ public function __construct(
13
+ $message,
14
+ RequestInterface $request,
15
+ ResponseInterface $response = null,
16
+ \Exception $previous = null,
17
+ array $handlerContext = []
18
+ ) {
19
+ if (null === $response) {
20
+ @trigger_error(
21
+ 'Instantiating the ' . __CLASS__ . ' class without a Response is deprecated since version 6.3 and will be removed in 7.0.',
22
+ E_USER_DEPRECATED
23
+ );
24
+ }
25
+ parent::__construct($message, $request, $response, $previous, $handlerContext);
26
+ }
27
+ }
vendor/guzzlehttp/guzzle/src/Exception/ClientException.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Exception;
3
+
4
+ /**
5
+ * Exception when a client error is encountered (4xx codes)
6
+ */
7
+ class ClientException extends BadResponseException
8
+ {
9
+ }
vendor/guzzlehttp/guzzle/src/Exception/ConnectException.php ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Exception;
3
+
4
+ use Psr\Http\Message\RequestInterface;
5
+
6
+ /**
7
+ * Exception thrown when a connection cannot be established.
8
+ *
9
+ * Note that no response is present for a ConnectException
10
+ */
11
+ class ConnectException extends RequestException
12
+ {
13
+ public function __construct(
14
+ $message,
15
+ RequestInterface $request,
16
+ \Exception $previous = null,
17
+ array $handlerContext = []
18
+ ) {
19
+ parent::__construct($message, $request, null, $previous, $handlerContext);
20
+ }
21
+
22
+ /**
23
+ * @return null
24
+ */
25
+ public function getResponse()
26
+ {
27
+ return null;
28
+ }
29
+
30
+ /**
31
+ * @return bool
32
+ */
33
+ public function hasResponse()
34
+ {
35
+ return false;
36
+ }
37
+ }
vendor/guzzlehttp/guzzle/src/Exception/GuzzleException.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Exception;
3
+
4
+ use Throwable;
5
+
6
+ if (interface_exists(Throwable::class)) {
7
+ interface GuzzleException extends Throwable
8
+ {
9
+ }
10
+ } else {
11
+ /**
12
+ * @method string getMessage()
13
+ * @method \Throwable|null getPrevious()
14
+ * @method mixed getCode()
15
+ * @method string getFile()
16
+ * @method int getLine()
17
+ * @method array getTrace()
18
+ * @method string getTraceAsString()
19
+ */
20
+ interface GuzzleException
21
+ {
22
+ }
23
+ }
vendor/guzzlehttp/guzzle/src/Exception/InvalidArgumentException.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace GuzzleHttp\Exception;
4
+
5
+ final class InvalidArgumentException extends \InvalidArgumentException implements GuzzleException
6
+ {
7
+ }
vendor/guzzlehttp/guzzle/src/Exception/RequestException.php ADDED
@@ -0,0 +1,192 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Exception;
3
+
4
+ use GuzzleHttp\Promise\PromiseInterface;
5
+ use Psr\Http\Message\RequestInterface;
6
+ use Psr\Http\Message\ResponseInterface;
7
+ use Psr\Http\Message\UriInterface;
8
+
9
+ /**
10
+ * HTTP Request exception
11
+ */
12
+ class RequestException extends TransferException
13
+ {
14
+ /** @var RequestInterface */
15
+ private $request;
16
+
17
+ /** @var ResponseInterface|null */
18
+ private $response;
19
+
20
+ /** @var array */
21
+ private $handlerContext;
22
+
23
+ public function __construct(
24
+ $message,
25
+ RequestInterface $request,
26
+ ResponseInterface $response = null,
27
+ \Exception $previous = null,
28
+ array $handlerContext = []
29
+ ) {
30
+ // Set the code of the exception if the response is set and not future.
31
+ $code = $response && !($response instanceof PromiseInterface)
32
+ ? $response->getStatusCode()
33
+ : 0;
34
+ parent::__construct($message, $code, $previous);
35
+ $this->request = $request;
36
+ $this->response = $response;
37
+ $this->handlerContext = $handlerContext;
38
+ }
39
+
40
+ /**
41
+ * Wrap non-RequestExceptions with a RequestException
42
+ *
43
+ * @param RequestInterface $request
44
+ * @param \Exception $e
45
+ *
46
+ * @return RequestException
47
+ */
48
+ public static function wrapException(RequestInterface $request, \Exception $e)
49
+ {
50
+ return $e instanceof RequestException
51
+ ? $e
52
+ : new RequestException($e->getMessage(), $request, null, $e);
53
+ }
54
+
55
+ /**
56
+ * Factory method to create a new exception with a normalized error message
57
+ *
58
+ * @param RequestInterface $request Request
59
+ * @param ResponseInterface $response Response received
60
+ * @param \Exception $previous Previous exception
61
+ * @param array $ctx Optional handler context.
62
+ *
63
+ * @return self
64
+ */
65
+ public static function create(
66
+ RequestInterface $request,
67
+ ResponseInterface $response = null,
68
+ \Exception $previous = null,
69
+ array $ctx = []
70
+ ) {
71
+ if (!$response) {
72
+ return new self(
73
+ 'Error completing request',
74
+ $request,
75
+ null,
76
+ $previous,
77
+ $ctx
78
+ );
79
+ }
80
+
81
+ $level = (int) floor($response->getStatusCode() / 100);
82
+ if ($level === 4) {
83
+ $label = 'Client error';
84
+ $className = ClientException::class;
85
+ } elseif ($level === 5) {
86
+ $label = 'Server error';
87
+ $className = ServerException::class;
88
+ } else {
89
+ $label = 'Unsuccessful request';
90
+ $className = __CLASS__;
91
+ }
92
+
93
+ $uri = $request->getUri();
94
+ $uri = static::obfuscateUri($uri);
95
+
96
+ // Client Error: `GET /` resulted in a `404 Not Found` response:
97
+ // <html> ... (truncated)
98
+ $message = sprintf(
99
+ '%s: `%s %s` resulted in a `%s %s` response',
100
+ $label,
101
+ $request->getMethod(),
102
+ $uri,
103
+ $response->getStatusCode(),
104
+ $response->getReasonPhrase()
105
+ );
106
+
107
+ $summary = static::getResponseBodySummary($response);
108
+
109
+ if ($summary !== null) {
110
+ $message .= ":\n{$summary}\n";
111
+ }
112
+
113
+ return new $className($message, $request, $response, $previous, $ctx);
114
+ }
115
+
116
+ /**
117
+ * Get a short summary of the response
118
+ *
119
+ * Will return `null` if the response is not printable.
120
+ *
121
+ * @param ResponseInterface $response
122
+ *
123
+ * @return string|null
124
+ */
125
+ public static function getResponseBodySummary(ResponseInterface $response)
126
+ {
127
+ return \GuzzleHttp\Psr7\get_message_body_summary($response);
128
+ }
129
+
130
+ /**
131
+ * Obfuscates URI if there is a username and a password present
132
+ *
133
+ * @param UriInterface $uri
134
+ *
135
+ * @return UriInterface
136
+ */
137
+ private static function obfuscateUri(UriInterface $uri)
138
+ {
139
+ $userInfo = $uri->getUserInfo();
140
+
141
+ if (false !== ($pos = strpos($userInfo, ':'))) {
142
+ return $uri->withUserInfo(substr($userInfo, 0, $pos), '***');
143
+ }
144
+
145
+ return $uri;
146
+ }
147
+
148
+ /**
149
+ * Get the request that caused the exception
150
+ *
151
+ * @return RequestInterface
152
+ */
153
+ public function getRequest()
154
+ {
155
+ return $this->request;
156
+ }
157
+
158
+ /**
159
+ * Get the associated response
160
+ *
161
+ * @return ResponseInterface|null
162
+ */
163
+ public function getResponse()
164
+ {
165
+ return $this->response;
166
+ }
167
+
168
+ /**
169
+ * Check if a response was received
170
+ *
171
+ * @return bool
172
+ */
173
+ public function hasResponse()
174
+ {
175
+ return $this->response !== null;
176
+ }
177
+
178
+ /**
179
+ * Get contextual information about the error from the underlying handler.
180
+ *
181
+ * The contents of this array will vary depending on which handler you are
182
+ * using. It may also be just an empty array. Relying on this data will
183
+ * couple you to a specific handler, but can give more debug information
184
+ * when needed.
185
+ *
186
+ * @return array
187
+ */
188
+ public function getHandlerContext()
189
+ {
190
+ return $this->handlerContext;
191
+ }
192
+ }
vendor/guzzlehttp/guzzle/src/Exception/SeekException.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Exception;
3
+
4
+ use Psr\Http\Message\StreamInterface;
5
+
6
+ /**
7
+ * Exception thrown when a seek fails on a stream.
8
+ */
9
+ class SeekException extends \RuntimeException implements GuzzleException
10
+ {
11
+ private $stream;
12
+
13
+ public function __construct(StreamInterface $stream, $pos = 0, $msg = '')
14
+ {
15
+ $this->stream = $stream;
16
+ $msg = $msg ?: 'Could not seek the stream to position ' . $pos;
17
+ parent::__construct($msg);
18
+ }
19
+
20
+ /**
21
+ * @return StreamInterface
22
+ */
23
+ public function getStream()
24
+ {
25
+ return $this->stream;
26
+ }
27
+ }
vendor/guzzlehttp/guzzle/src/Exception/ServerException.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Exception;
3
+
4
+ /**
5
+ * Exception when a server error is encountered (5xx codes)
6
+ */
7
+ class ServerException extends BadResponseException
8
+ {
9
+ }
vendor/guzzlehttp/guzzle/src/Exception/TooManyRedirectsException.php ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Exception;
3
+
4
+ class TooManyRedirectsException extends RequestException
5
+ {
6
+ }
vendor/guzzlehttp/guzzle/src/Exception/TransferException.php ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Exception;
3
+
4
+ class TransferException extends \RuntimeException implements GuzzleException
5
+ {
6
+ }
vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php ADDED
@@ -0,0 +1,585 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Handler;
3
+
4
+ use GuzzleHttp\Exception\ConnectException;
5
+ use GuzzleHttp\Exception\RequestException;
6
+ use GuzzleHttp\Promise\FulfilledPromise;
7
+ use GuzzleHttp\Psr7;
8
+ use GuzzleHttp\Psr7\LazyOpenStream;
9
+ use GuzzleHttp\TransferStats;
10
+ use Psr\Http\Message\RequestInterface;
11
+
12
+ /**
13
+ * Creates curl resources from a request
14
+ */
15
+ class CurlFactory implements CurlFactoryInterface
16
+ {
17
+ const CURL_VERSION_STR = 'curl_version';
18
+ const LOW_CURL_VERSION_NUMBER = '7.21.2';
19
+
20
+ /** @var array */
21
+ private $handles = [];
22
+
23
+ /** @var int Total number of idle handles to keep in cache */
24
+ private $maxHandles;
25
+
26
+ /**
27
+ * @param int $maxHandles Maximum number of idle handles.
28
+ */
29
+ public function __construct($maxHandles)
30
+ {
31
+ $this->maxHandles = $maxHandles;
32
+ }
33
+
34
+ public function create(RequestInterface $request, array $options)
35
+ {
36
+ if (isset($options['curl']['body_as_string'])) {
37
+ $options['_body_as_string'] = $options['curl']['body_as_string'];
38
+ unset($options['curl']['body_as_string']);
39
+ }
40
+
41
+ $easy = new EasyHandle;
42
+ $easy->request = $request;
43
+ $easy->options = $options;
44
+ $conf = $this->getDefaultConf($easy);
45
+ $this->applyMethod($easy, $conf);
46
+ $this->applyHandlerOptions($easy, $conf);
47
+ $this->applyHeaders($easy, $conf);
48
+ unset($conf['_headers']);
49
+
50
+ // Add handler options from the request configuration options
51
+ if (isset($options['curl'])) {
52
+ $conf = array_replace($conf, $options['curl']);
53
+ }
54
+
55
+ $conf[CURLOPT_HEADERFUNCTION] = $this->createHeaderFn($easy);
56
+ $easy->handle = $this->handles
57
+ ? array_pop($this->handles)
58
+ : curl_init();
59
+ curl_setopt_array($easy->handle, $conf);
60
+
61
+ return $easy;
62
+ }
63
+
64
+ public function release(EasyHandle $easy)
65
+ {
66
+ $resource = $easy->handle;
67
+ unset($easy->handle);
68
+
69
+ if (count($this->handles) >= $this->maxHandles) {
70
+ curl_close($resource);
71
+ } else {
72
+ // Remove all callback functions as they can hold onto references
73
+ // and are not cleaned up by curl_reset. Using curl_setopt_array
74
+ // does not work for some reason, so removing each one
75
+ // individually.
76
+ curl_setopt($resource, CURLOPT_HEADERFUNCTION, null);
77
+ curl_setopt($resource, CURLOPT_READFUNCTION, null);
78
+ curl_setopt($resource, CURLOPT_WRITEFUNCTION, null);
79
+ curl_setopt($resource, CURLOPT_PROGRESSFUNCTION, null);
80
+ curl_reset($resource);
81
+ $this->handles[] = $resource;
82
+ }
83
+ }
84
+
85
+ /**
86
+ * Completes a cURL transaction, either returning a response promise or a
87
+ * rejected promise.
88
+ *
89
+ * @param callable $handler
90
+ * @param EasyHandle $easy
91
+ * @param CurlFactoryInterface $factory Dictates how the handle is released
92
+ *
93
+ * @return \GuzzleHttp\Promise\PromiseInterface
94
+ */
95
+ public static function finish(
96
+ callable $handler,
97
+ EasyHandle $easy,
98
+ CurlFactoryInterface $factory
99
+ ) {
100
+ if (isset($easy->options['on_stats'])) {
101
+ self::invokeStats($easy);
102
+ }
103
+
104
+ if (!$easy->response || $easy->errno) {
105
+ return self::finishError($handler, $easy, $factory);
106
+ }
107
+
108
+ // Return the response if it is present and there is no error.
109
+ $factory->release($easy);
110
+
111
+ // Rewind the body of the response if possible.
112
+ $body = $easy->response->getBody();
113
+ if ($body->isSeekable()) {
114
+ $body->rewind();
115
+ }
116
+
117
+ return new FulfilledPromise($easy->response);
118
+ }
119
+
120
+ private static function invokeStats(EasyHandle $easy)
121
+ {
122
+ $curlStats = curl_getinfo($easy->handle);
123
+ $curlStats['appconnect_time'] = curl_getinfo($easy->handle, CURLINFO_APPCONNECT_TIME);
124
+ $stats = new TransferStats(
125
+ $easy->request,
126
+ $easy->response,
127
+ $curlStats['total_time'],
128
+ $easy->errno,
129
+ $curlStats
130
+ );
131
+ call_user_func($easy->options['on_stats'], $stats);
132
+ }
133
+
134
+ private static function finishError(
135
+ callable $handler,
136
+ EasyHandle $easy,
137
+ CurlFactoryInterface $factory
138
+ ) {
139
+ // Get error information and release the handle to the factory.
140
+ $ctx = [
141
+ 'errno' => $easy->errno,
142
+ 'error' => curl_error($easy->handle),
143
+ 'appconnect_time' => curl_getinfo($easy->handle, CURLINFO_APPCONNECT_TIME),
144
+ ] + curl_getinfo($easy->handle);
145
+ $ctx[self::CURL_VERSION_STR] = curl_version()['version'];
146
+ $factory->release($easy);
147
+
148
+ // Retry when nothing is present or when curl failed to rewind.
149
+ if (empty($easy->options['_err_message'])
150
+ && (!$easy->errno || $easy->errno == 65)
151
+ ) {
152
+ return self::retryFailedRewind($handler, $easy, $ctx);
153
+ }
154
+
155
+ return self::createRejection($easy, $ctx);
156
+ }
157
+
158
+ private static function createRejection(EasyHandle $easy, array $ctx)
159
+ {
160
+ static $connectionErrors = [
161
+ CURLE_OPERATION_TIMEOUTED => true,
162
+ CURLE_COULDNT_RESOLVE_HOST => true,
163
+ CURLE_COULDNT_CONNECT => true,
164
+ CURLE_SSL_CONNECT_ERROR => true,
165
+ CURLE_GOT_NOTHING => true,
166
+ ];
167
+
168
+ // If an exception was encountered during the onHeaders event, then
169
+ // return a rejected promise that wraps that exception.
170
+ if ($easy->onHeadersException) {
171
+ return \GuzzleHttp\Promise\rejection_for(
172
+ new RequestException(
173
+ 'An error was encountered during the on_headers event',
174
+ $easy->request,
175
+ $easy->response,
176
+ $easy->onHeadersException,
177
+ $ctx
178
+ )
179
+ );
180
+ }
181
+ if (version_compare($ctx[self::CURL_VERSION_STR], self::LOW_CURL_VERSION_NUMBER)) {
182
+ $message = sprintf(
183
+ 'cURL error %s: %s (%s)',
184
+ $ctx['errno'],
185
+ $ctx['error'],
186
+ 'see https://curl.haxx.se/libcurl/c/libcurl-errors.html'
187
+ );
188
+ } else {
189
+ $message = sprintf(
190
+ 'cURL error %s: %s (%s) for %s',
191
+ $ctx['errno'],
192
+ $ctx['error'],
193
+ 'see https://curl.haxx.se/libcurl/c/libcurl-errors.html',
194
+ $easy->request->getUri()
195
+ );
196
+ }
197
+
198
+ // Create a connection exception if it was a specific error code.
199
+ $error = isset($connectionErrors[$easy->errno])
200
+ ? new ConnectException($message, $easy->request, null, $ctx)
201
+ : new RequestException($message, $easy->request, $easy->response, null, $ctx);
202
+
203
+ return \GuzzleHttp\Promise\rejection_for($error);
204
+ }
205
+
206
+ private function getDefaultConf(EasyHandle $easy)
207
+ {
208
+ $conf = [
209
+ '_headers' => $easy->request->getHeaders(),
210
+ CURLOPT_CUSTOMREQUEST => $easy->request->getMethod(),
211
+ CURLOPT_URL => (string) $easy->request->getUri()->withFragment(''),
212
+ CURLOPT_RETURNTRANSFER => false,
213
+ CURLOPT_HEADER => false,
214
+ CURLOPT_CONNECTTIMEOUT => 150,
215
+ ];
216
+
217
+ if (defined('CURLOPT_PROTOCOLS')) {
218
+ $conf[CURLOPT_PROTOCOLS] = CURLPROTO_HTTP | CURLPROTO_HTTPS;
219
+ }
220
+
221
+ $version = $easy->request->getProtocolVersion();
222
+ if ($version == 1.1) {
223
+ $conf[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_1;
224
+ } elseif ($version == 2.0) {
225
+ $conf[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_2_0;
226
+ } else {
227
+ $conf[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_0;
228
+ }
229
+
230
+ return $conf;
231
+ }
232
+
233
+ private function applyMethod(EasyHandle $easy, array &$conf)
234
+ {
235
+ $body = $easy->request->getBody();
236
+ $size = $body->getSize();
237
+
238
+ if ($size === null || $size > 0) {
239
+ $this->applyBody($easy->request, $easy->options, $conf);
240
+ return;
241
+ }
242
+
243
+ $method = $easy->request->getMethod();
244
+ if ($method === 'PUT' || $method === 'POST') {
245
+ // See http://tools.ietf.org/html/rfc7230#section-3.3.2
246
+ if (!$easy->request->hasHeader('Content-Length')) {
247
+ $conf[CURLOPT_HTTPHEADER][] = 'Content-Length: 0';
248
+ }
249
+ } elseif ($method === 'HEAD') {
250
+ $conf[CURLOPT_NOBODY] = true;
251
+ unset(
252
+ $conf[CURLOPT_WRITEFUNCTION],
253
+ $conf[CURLOPT_READFUNCTION],
254
+ $conf[CURLOPT_FILE],
255
+ $conf[CURLOPT_INFILE]
256
+ );
257
+ }
258
+ }
259
+
260
+ private function applyBody(RequestInterface $request, array $options, array &$conf)
261
+ {
262
+ $size = $request->hasHeader('Content-Length')
263
+ ? (int) $request->getHeaderLine('Content-Length')
264
+ : null;
265
+
266
+ // Send the body as a string if the size is less than 1MB OR if the
267
+ // [curl][body_as_string] request value is set.
268
+ if (($size !== null && $size < 1000000) ||
269
+ !empty($options['_body_as_string'])
270
+ ) {
271
+ $conf[CURLOPT_POSTFIELDS] = (string) $request->getBody();
272
+ // Don't duplicate the Content-Length header
273
+ $this->removeHeader('Content-Length', $conf);
274
+ $this->removeHeader('Transfer-Encoding', $conf);
275
+ } else {
276
+ $conf[CURLOPT_UPLOAD] = true;
277
+ if ($size !== null) {
278
+ $conf[CURLOPT_INFILESIZE] = $size;
279
+ $this->removeHeader('Content-Length', $conf);
280
+ }
281
+ $body = $request->getBody();
282
+ if ($body->isSeekable()) {
283
+ $body->rewind();
284
+ }
285
+ $conf[CURLOPT_READFUNCTION] = function ($ch, $fd, $length) use ($body) {
286
+ return $body->read($length);
287
+ };
288
+ }
289
+
290
+ // If the Expect header is not present, prevent curl from adding it
291
+ if (!$request->hasHeader('Expect')) {
292
+ $conf[CURLOPT_HTTPHEADER][] = 'Expect:';
293
+ }
294
+
295
+ // cURL sometimes adds a content-type by default. Prevent this.
296
+ if (!$request->hasHeader('Content-Type')) {
297
+ $conf[CURLOPT_HTTPHEADER][] = 'Content-Type:';
298
+ }
299
+ }
300
+
301
+ private function applyHeaders(EasyHandle $easy, array &$conf)
302
+ {
303
+ foreach ($conf['_headers'] as $name => $values) {
304
+ foreach ($values as $value) {
305
+ $value = (string) $value;
306
+ if ($value === '') {
307
+ // cURL requires a special format for empty headers.
308
+ // See https://github.com/guzzle/guzzle/issues/1882 for more details.
309
+ $conf[CURLOPT_HTTPHEADER][] = "$name;";
310
+ } else {
311
+ $conf[CURLOPT_HTTPHEADER][] = "$name: $value";
312
+ }
313
+ }
314
+ }
315
+
316
+ // Remove the Accept header if one was not set
317
+ if (!$easy->request->hasHeader('Accept')) {
318
+ $conf[CURLOPT_HTTPHEADER][] = 'Accept:';
319
+ }
320
+ }
321
+
322
+ /**
323
+ * Remove a header from the options array.
324
+ *
325
+ * @param string $name Case-insensitive header to remove
326
+ * @param array $options Array of options to modify
327
+ */
328
+ private function removeHeader($name, array &$options)
329
+ {
330
+ foreach (array_keys($options['_headers']) as $key) {
331
+ if (!strcasecmp($key, $name)) {
332
+ unset($options['_headers'][$key]);
333
+ return;
334
+ }
335
+ }
336
+ }
337
+
338
+ private function applyHandlerOptions(EasyHandle $easy, array &$conf)
339
+ {
340
+ $options = $easy->options;
341
+ if (isset($options['verify'])) {
342
+ if ($options['verify'] === false) {
343
+ unset($conf[CURLOPT_CAINFO]);
344
+ $conf[CURLOPT_SSL_VERIFYHOST] = 0;
345
+ $conf[CURLOPT_SSL_VERIFYPEER] = false;
346
+ } else {
347
+ $conf[CURLOPT_SSL_VERIFYHOST] = 2;
348
+ $conf[CURLOPT_SSL_VERIFYPEER] = true;
349
+ if (is_string($options['verify'])) {
350
+ // Throw an error if the file/folder/link path is not valid or doesn't exist.
351
+ if (!file_exists($options['verify'])) {
352
+ throw new \InvalidArgumentException(
353
+ "SSL CA bundle not found: {$options['verify']}"
354
+ );
355
+ }
356
+ // If it's a directory or a link to a directory use CURLOPT_CAPATH.
357
+ // If not, it's probably a file, or a link to a file, so use CURLOPT_CAINFO.
358
+ if (is_dir($options['verify']) ||
359
+ (is_link($options['verify']) && is_dir(readlink($options['verify'])))) {
360
+ $conf[CURLOPT_CAPATH] = $options['verify'];
361
+ } else {
362
+ $conf[CURLOPT_CAINFO] = $options['verify'];
363
+ }
364
+ }
365
+ }
366
+ }
367
+
368
+ if (!empty($options['decode_content'])) {
369
+ $accept = $easy->request->getHeaderLine('Accept-Encoding');
370
+ if ($accept) {
371
+ $conf[CURLOPT_ENCODING] = $accept;
372
+ } else {
373
+ $conf[CURLOPT_ENCODING] = '';
374
+ // Don't let curl send the header over the wire
375
+ $conf[CURLOPT_HTTPHEADER][] = 'Accept-Encoding:';
376
+ }
377
+ }
378
+
379
+ if (isset($options['sink'])) {
380
+ $sink = $options['sink'];
381
+ if (!is_string($sink)) {
382
+ $sink = \GuzzleHttp\Psr7\stream_for($sink);
383
+ } elseif (!is_dir(dirname($sink))) {
384
+ // Ensure that the directory exists before failing in curl.
385
+ throw new \RuntimeException(sprintf(
386
+ 'Directory %s does not exist for sink value of %s',
387
+ dirname($sink),
388
+ $sink
389
+ ));
390
+ } else {
391
+ $sink = new LazyOpenStream($sink, 'w+');
392
+ }
393
+ $easy->sink = $sink;
394
+ $conf[CURLOPT_WRITEFUNCTION] = function ($ch, $write) use ($sink) {
395
+ return $sink->write($write);
396
+ };
397
+ } else {
398
+ // Use a default temp stream if no sink was set.
399
+ $conf[CURLOPT_FILE] = fopen('php://temp', 'w+');
400
+ $easy->sink = Psr7\stream_for($conf[CURLOPT_FILE]);
401
+ }
402
+ $timeoutRequiresNoSignal = false;
403
+ if (isset($options['timeout'])) {
404
+ $timeoutRequiresNoSignal |= $options['timeout'] < 1;
405
+ $conf[CURLOPT_TIMEOUT_MS] = $options['timeout'] * 1000;
406
+ }
407
+
408
+ // CURL default value is CURL_IPRESOLVE_WHATEVER
409
+ if (isset($options['force_ip_resolve'])) {
410
+ if ('v4' === $options['force_ip_resolve']) {
411
+ $conf[CURLOPT_IPRESOLVE] = CURL_IPRESOLVE_V4;
412
+ } elseif ('v6' === $options['force_ip_resolve']) {
413
+ $conf[CURLOPT_IPRESOLVE] = CURL_IPRESOLVE_V6;
414
+ }
415
+ }
416
+
417
+ if (isset($options['connect_timeout'])) {
418
+ $timeoutRequiresNoSignal |= $options['connect_timeout'] < 1;
419
+ $conf[CURLOPT_CONNECTTIMEOUT_MS] = $options['connect_timeout'] * 1000;
420
+ }
421
+
422
+ if ($timeoutRequiresNoSignal && strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN') {
423
+ $conf[CURLOPT_NOSIGNAL] = true;
424
+ }
425
+
426
+ if (isset($options['proxy'])) {
427
+ if (!is_array($options['proxy'])) {
428
+ $conf[CURLOPT_PROXY] = $options['proxy'];
429
+ } else {
430
+ $scheme = $easy->request->getUri()->getScheme();
431
+ if (isset($options['proxy'][$scheme])) {
432
+ $host = $easy->request->getUri()->getHost();
433
+ if (!isset($options['proxy']['no']) ||
434
+ !\GuzzleHttp\is_host_in_noproxy($host, $options['proxy']['no'])
435
+ ) {
436
+ $conf[CURLOPT_PROXY] = $options['proxy'][$scheme];
437
+ }
438
+ }
439
+ }
440
+ }
441
+
442
+ if (isset($options['cert'])) {
443
+ $cert = $options['cert'];
444
+ if (is_array($cert)) {
445
+ $conf[CURLOPT_SSLCERTPASSWD] = $cert[1];
446
+ $cert = $cert[0];
447
+ }
448
+ if (!file_exists($cert)) {
449
+ throw new \InvalidArgumentException(
450
+ "SSL certificate not found: {$cert}"
451
+ );
452
+ }
453
+ $conf[CURLOPT_SSLCERT] = $cert;
454
+ }
455
+
456
+ if (isset($options['ssl_key'])) {
457
+ if (is_array($options['ssl_key'])) {
458
+ if (count($options['ssl_key']) === 2) {
459
+ list($sslKey, $conf[CURLOPT_SSLKEYPASSWD]) = $options['ssl_key'];
460
+ } else {
461
+ list($sslKey) = $options['ssl_key'];
462
+ }
463
+ }
464
+
465
+ $sslKey = isset($sslKey) ? $sslKey: $options['ssl_key'];
466
+
467
+ if (!file_exists($sslKey)) {
468
+ throw new \InvalidArgumentException(
469
+ "SSL private key not found: {$sslKey}"
470
+ );
471
+ }
472
+ $conf[CURLOPT_SSLKEY] = $sslKey;
473
+ }
474
+
475
+ if (isset($options['progress'])) {
476
+ $progress = $options['progress'];
477
+ if (!is_callable($progress)) {
478
+ throw new \InvalidArgumentException(
479
+ 'progress client option must be callable'
480
+ );
481
+ }
482
+ $conf[CURLOPT_NOPROGRESS] = false;
483
+ $conf[CURLOPT_PROGRESSFUNCTION] = function () use ($progress) {
484
+ $args = func_get_args();
485
+ // PHP 5.5 pushed the handle onto the start of the args
486
+ if (is_resource($args[0])) {
487
+ array_shift($args);
488
+ }
489
+ call_user_func_array($progress, $args);
490
+ };
491
+ }
492
+
493
+ if (!empty($options['debug'])) {
494
+ $conf[CURLOPT_STDERR] = \GuzzleHttp\debug_resource($options['debug']);
495
+ $conf[CURLOPT_VERBOSE] = true;
496
+ }
497
+ }
498
+
499
+ /**
500
+ * This function ensures that a response was set on a transaction. If one
501
+ * was not set, then the request is retried if possible. This error
502
+ * typically means you are sending a payload, curl encountered a
503
+ * "Connection died, retrying a fresh connect" error, tried to rewind the
504
+ * stream, and then encountered a "necessary data rewind wasn't possible"
505
+ * error, causing the request to be sent through curl_multi_info_read()
506
+ * without an error status.
507
+ */
508
+ private static function retryFailedRewind(
509
+ callable $handler,
510
+ EasyHandle $easy,
511
+ array $ctx
512
+ ) {
513
+ try {
514
+ // Only rewind if the body has been read from.
515
+ $body = $easy->request->getBody();
516
+ if ($body->tell() > 0) {
517
+ $body->rewind();
518
+ }
519
+ } catch (\RuntimeException $e) {
520
+ $ctx['error'] = 'The connection unexpectedly failed without '
521
+ . 'providing an error. The request would have been retried, '
522
+ . 'but attempting to rewind the request body failed. '
523
+ . 'Exception: ' . $e;
524
+ return self::createRejection($easy, $ctx);
525
+ }
526
+
527
+ // Retry no more than 3 times before giving up.
528
+ if (!isset($easy->options['_curl_retries'])) {
529
+ $easy->options['_curl_retries'] = 1;
530
+ } elseif ($easy->options['_curl_retries'] == 2) {
531
+ $ctx['error'] = 'The cURL request was retried 3 times '
532
+ . 'and did not succeed. The most likely reason for the failure '
533
+ . 'is that cURL was unable to rewind the body of the request '
534
+ . 'and subsequent retries resulted in the same error. Turn on '
535
+ . 'the debug option to see what went wrong. See '
536
+ . 'https://bugs.php.net/bug.php?id=47204 for more information.';
537
+ return self::createRejection($easy, $ctx);
538
+ } else {
539
+ $easy->options['_curl_retries']++;
540
+ }
541
+
542
+ return $handler($easy->request, $easy->options);
543
+ }
544
+
545
+ private function createHeaderFn(EasyHandle $easy)
546
+ {
547
+ if (isset($easy->options['on_headers'])) {
548
+ $onHeaders = $easy->options['on_headers'];
549
+
550
+ if (!is_callable($onHeaders)) {
551
+ throw new \InvalidArgumentException('on_headers must be callable');
552
+ }
553
+ } else {
554
+ $onHeaders = null;
555
+ }
556
+
557
+ return function ($ch, $h) use (
558
+ $onHeaders,
559
+ $easy,
560
+ &$startingResponse
561
+ ) {
562
+ $value = trim($h);
563
+ if ($value === '') {
564
+ $startingResponse = true;
565
+ $easy->createResponse();
566
+ if ($onHeaders !== null) {
567
+ try {
568
+ $onHeaders($easy->response);
569
+ } catch (\Exception $e) {
570
+ // Associate the exception with the handle and trigger
571
+ // a curl header write error by returning 0.
572
+ $easy->onHeadersException = $e;
573
+ return -1;
574
+ }
575
+ }
576
+ } elseif ($startingResponse) {
577
+ $startingResponse = false;
578
+ $easy->headers = [$value];
579
+ } else {
580
+ $easy->headers[] = $value;
581
+ }
582
+ return strlen($h);
583
+ };
584
+ }
585
+ }
vendor/guzzlehttp/guzzle/src/Handler/CurlFactoryInterface.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Handler;
3
+
4
+ use Psr\Http\Message\RequestInterface;
5
+
6
+ interface CurlFactoryInterface
7
+ {
8
+ /**
9
+ * Creates a cURL handle resource.
10
+ *
11
+ * @param RequestInterface $request Request
12
+ * @param array $options Transfer options
13
+ *
14
+ * @return EasyHandle
15
+ * @throws \RuntimeException when an option cannot be applied
16
+ */
17
+ public function create(RequestInterface $request, array $options);
18
+
19
+ /**
20
+ * Release an easy handle, allowing it to be reused or closed.
21
+ *
22
+ * This function must call unset on the easy handle's "handle" property.
23
+ *
24
+ * @param EasyHandle $easy
25
+ */
26
+ public function release(EasyHandle $easy);
27
+ }
vendor/guzzlehttp/guzzle/src/Handler/CurlHandler.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Handler;
3
+
4
+ use GuzzleHttp\Psr7;
5
+ use Psr\Http\Message\RequestInterface;
6
+
7
+ /**
8
+ * HTTP handler that uses cURL easy handles as a transport layer.
9
+ *
10
+ * When using the CurlHandler, custom curl options can be specified as an
11
+ * associative array of curl option constants mapping to values in the
12
+ * **curl** key of the "client" key of the request.
13
+ */
14
+ class CurlHandler
15
+ {
16
+ /** @var CurlFactoryInterface */
17
+ private $factory;
18
+
19
+ /**
20
+ * Accepts an associative array of options:
21
+ *
22
+ * - factory: Optional curl factory used to create cURL handles.
23
+ *
24
+ * @param array $options Array of options to use with the handler
25
+ */
26
+ public function __construct(array $options = [])
27
+ {
28
+ $this->factory = isset($options['handle_factory'])
29
+ ? $options['handle_factory']
30
+ : new CurlFactory(3);
31
+ }
32
+
33
+ public function __invoke(RequestInterface $request, array $options)
34
+ {
35
+ if (isset($options['delay'])) {
36
+ usleep($options['delay'] * 1000);
37
+ }
38
+
39
+ $easy = $this->factory->create($request, $options);
40
+ curl_exec($easy->handle);
41
+ $easy->errno = curl_errno($easy->handle);
42
+
43
+ return CurlFactory::finish($this, $easy, $this->factory);
44
+ }
45
+ }
vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php ADDED
@@ -0,0 +1,219 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Handler;
3
+
4
+ use GuzzleHttp\Promise as P;
5
+ use GuzzleHttp\Promise\Promise;
6
+ use GuzzleHttp\Utils;
7
+ use Psr\Http\Message\RequestInterface;
8
+
9
+ /**
10
+ * Returns an asynchronous response using curl_multi_* functions.
11
+ *
12
+ * When using the CurlMultiHandler, custom curl options can be specified as an
13
+ * associative array of curl option constants mapping to values in the
14
+ * **curl** key of the provided request options.
15
+ *
16
+ * @property resource $_mh Internal use only. Lazy loaded multi-handle.
17
+ */
18
+ class CurlMultiHandler
19
+ {
20
+ /** @var CurlFactoryInterface */
21
+ private $factory;
22
+ private $selectTimeout;
23
+ private $active;
24
+ private $handles = [];
25
+ private $delays = [];
26
+ private $options = [];
27
+
28
+ /**
29
+ * This handler accepts the following options:
30
+ *
31
+ * - handle_factory: An optional factory used to create curl handles
32
+ * - select_timeout: Optional timeout (in seconds) to block before timing
33
+ * out while selecting curl handles. Defaults to 1 second.
34
+ * - options: An associative array of CURLMOPT_* options and
35
+ * corresponding values for curl_multi_setopt()
36
+ *
37
+ * @param array $options
38
+ */
39
+ public function __construct(array $options = [])
40
+ {
41
+ $this->factory = isset($options['handle_factory'])
42
+ ? $options['handle_factory'] : new CurlFactory(50);
43
+
44
+ if (isset($options['select_timeout'])) {
45
+ $this->selectTimeout = $options['select_timeout'];
46
+ } elseif ($selectTimeout = getenv('GUZZLE_CURL_SELECT_TIMEOUT')) {
47
+ $this->selectTimeout = $selectTimeout;
48
+ } else {
49
+ $this->selectTimeout = 1;
50
+ }
51
+
52
+ $this->options = isset($options['options']) ? $options['options'] : [];
53
+ }
54
+
55
+ public function __get($name)
56
+ {
57
+ if ($name === '_mh') {
58
+ $this->_mh = curl_multi_init();
59
+
60
+ foreach ($this->options as $option => $value) {
61
+ // A warning is raised in case of a wrong option.
62
+ curl_multi_setopt($this->_mh, $option, $value);
63
+ }
64
+
65
+ // Further calls to _mh will return the value directly, without entering the
66
+ // __get() method at all.
67
+ return $this->_mh;
68
+ }
69
+
70
+ throw new \BadMethodCallException();
71
+ }
72
+
73
+ public function __destruct()
74
+ {
75
+ if (isset($this->_mh)) {
76
+ curl_multi_close($this->_mh);
77
+ unset($this->_mh);
78
+ }
79
+ }
80
+
81
+ public function __invoke(RequestInterface $request, array $options)
82
+ {
83
+ $easy = $this->factory->create($request, $options);
84
+ $id = (int) $easy->handle;
85
+
86
+ $promise = new Promise(
87
+ [$this, 'execute'],
88
+ function () use ($id) {
89
+ return $this->cancel($id);
90
+ }
91
+ );
92
+
93
+ $this->addRequest(['easy' => $easy, 'deferred' => $promise]);
94
+
95
+ return $promise;
96
+ }
97
+
98
+ /**
99
+ * Ticks the curl event loop.
100
+ */
101
+ public function tick()
102
+ {
103
+ // Add any delayed handles if needed.
104
+ if ($this->delays) {
105
+ $currentTime = Utils::currentTime();
106
+ foreach ($this->delays as $id => $delay) {
107
+ if ($currentTime >= $delay) {
108
+ unset($this->delays[$id]);
109
+ curl_multi_add_handle(
110
+ $this->_mh,
111
+ $this->handles[$id]['easy']->handle
112
+ );
113
+ }
114
+ }
115
+ }
116
+
117
+ // Step through the task queue which may add additional requests.
118
+ P\queue()->run();
119
+
120
+ if ($this->active &&
121
+ curl_multi_select($this->_mh, $this->selectTimeout) === -1
122
+ ) {
123
+ // Perform a usleep if a select returns -1.
124
+ // See: https://bugs.php.net/bug.php?id=61141
125
+ usleep(250);
126
+ }
127
+
128
+ while (curl_multi_exec($this->_mh, $this->active) === CURLM_CALL_MULTI_PERFORM);
129
+
130
+ $this->processMessages();
131
+ }
132
+
133
+ /**
134
+ * Runs until all outstanding connections have completed.
135
+ */
136
+ public function execute()
137
+ {
138
+ $queue = P\queue();
139
+
140
+ while ($this->handles || !$queue->isEmpty()) {
141
+ // If there are no transfers, then sleep for the next delay
142
+ if (!$this->active && $this->delays) {
143
+ usleep($this->timeToNext());
144
+ }
145
+ $this->tick();
146
+ }
147
+ }
148
+
149
+ private function addRequest(array $entry)
150
+ {
151
+ $easy = $entry['easy'];
152
+ $id = (int) $easy->handle;
153
+ $this->handles[$id] = $entry;
154
+ if (empty($easy->options['delay'])) {
155
+ curl_multi_add_handle($this->_mh, $easy->handle);
156
+ } else {
157
+ $this->delays[$id] = Utils::currentTime() + ($easy->options['delay'] / 1000);
158
+ }
159
+ }
160
+
161
+ /**
162
+ * Cancels a handle from sending and removes references to it.
163
+ *
164
+ * @param int $id Handle ID to cancel and remove.
165
+ *
166
+ * @return bool True on success, false on failure.
167
+ */
168
+ private function cancel($id)
169
+ {
170
+ // Cannot cancel if it has been processed.
171
+ if (!isset($this->handles[$id])) {
172
+ return false;
173
+ }
174
+
175
+ $handle = $this->handles[$id]['easy']->handle;
176
+ unset($this->delays[$id], $this->handles[$id]);
177
+ curl_multi_remove_handle($this->_mh, $handle);
178
+ curl_close($handle);
179
+
180
+ return true;
181
+ }
182
+
183
+ private function processMessages()
184
+ {
185
+ while ($done = curl_multi_info_read($this->_mh)) {
186
+ $id = (int) $done['handle'];
187
+ curl_multi_remove_handle($this->_mh, $done['handle']);
188
+
189
+ if (!isset($this->handles[$id])) {
190
+ // Probably was cancelled.
191
+ continue;
192
+ }
193
+
194
+ $entry = $this->handles[$id];
195
+ unset($this->handles[$id], $this->delays[$id]);
196
+ $entry['easy']->errno = $done['result'];
197
+ $entry['deferred']->resolve(
198
+ CurlFactory::finish(
199
+ $this,
200
+ $entry['easy'],
201
+ $this->factory
202
+ )
203
+ );
204
+ }
205
+ }
206
+
207
+ private function timeToNext()
208
+ {
209
+ $currentTime = Utils::currentTime();
210
+ $nextTime = PHP_INT_MAX;
211
+ foreach ($this->delays as $time) {
212
+ if ($time < $nextTime) {
213
+ $nextTime = $time;
214
+ }
215
+ }
216
+
217
+ return max(0, $nextTime - $currentTime) * 1000000;
218
+ }
219
+ }
vendor/guzzlehttp/guzzle/src/Handler/EasyHandle.php ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Handler;
3
+
4
+ use GuzzleHttp\Psr7\Response;
5
+ use Psr\Http\Message\RequestInterface;
6
+ use Psr\Http\Message\ResponseInterface;
7
+ use Psr\Http\Message\StreamInterface;
8
+
9
+ /**
10
+ * Represents a cURL easy handle and the data it populates.
11
+ *
12
+ * @internal
13
+ */
14
+ final class EasyHandle
15
+ {
16
+ /** @var resource cURL resource */
17
+ public $handle;
18
+
19
+ /** @var StreamInterface Where data is being written */
20
+ public $sink;
21
+
22
+ /** @var array Received HTTP headers so far */
23
+ public $headers = [];
24
+
25
+ /** @var ResponseInterface Received response (if any) */
26
+ public $response;
27
+
28
+ /** @var RequestInterface Request being sent */
29
+ public $request;
30
+
31
+ /** @var array Request options */
32
+ public $options = [];
33
+
34
+ /** @var int cURL error number (if any) */
35
+ public $errno = 0;
36
+
37
+ /** @var \Exception Exception during on_headers (if any) */
38
+ public $onHeadersException;
39
+
40
+ /**
41
+ * Attach a response to the easy handle based on the received headers.
42
+ *
43
+ * @throws \RuntimeException if no headers have been received.
44
+ */
45
+ public function createResponse()
46
+ {
47
+ if (empty($this->headers)) {
48
+ throw new \RuntimeException('No headers have been received');
49
+ }
50
+
51
+ // HTTP-version SP status-code SP reason-phrase
52
+ $startLine = explode(' ', array_shift($this->headers), 3);
53
+ $headers = \GuzzleHttp\headers_from_lines($this->headers);
54
+ $normalizedKeys = \GuzzleHttp\normalize_header_keys($headers);
55
+
56
+ if (!empty($this->options['decode_content'])
57
+ && isset($normalizedKeys['content-encoding'])
58
+ ) {
59
+ $headers['x-encoded-content-encoding']
60
+ = $headers[$normalizedKeys['content-encoding']];
61
+ unset($headers[$normalizedKeys['content-encoding']]);
62
+ if (isset($normalizedKeys['content-length'])) {
63
+ $headers['x-encoded-content-length']
64
+ = $headers[$normalizedKeys['content-length']];
65
+
66
+ $bodyLength = (int) $this->sink->getSize();
67
+ if ($bodyLength) {
68
+ $headers[$normalizedKeys['content-length']] = $bodyLength;
69
+ } else {
70
+ unset($headers[$normalizedKeys['content-length']]);
71
+ }
72
+ }
73
+ }
74
+
75
+ // Attach a response to the easy handle with the parsed headers.
76
+ $this->response = new Response(
77
+ $startLine[1],
78
+ $headers,
79
+ $this->sink,
80
+ substr($startLine[0], 5),
81
+ isset($startLine[2]) ? (string) $startLine[2] : null
82
+ );
83
+ }
84
+
85
+ public function __get($name)
86
+ {
87
+ $msg = $name === 'handle'
88
+ ? 'The EasyHandle has been released'
89
+ : 'Invalid property: ' . $name;
90
+ throw new \BadMethodCallException($msg);
91
+ }
92
+ }
vendor/guzzlehttp/guzzle/src/Handler/MockHandler.php ADDED
@@ -0,0 +1,195 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Handler;
3
+
4
+ use GuzzleHttp\Exception\RequestException;
5
+ use GuzzleHttp\HandlerStack;
6
+ use GuzzleHttp\Promise\PromiseInterface;
7
+ use GuzzleHttp\Promise\RejectedPromise;
8
+ use GuzzleHttp\TransferStats;
9
+ use Psr\Http\Message\RequestInterface;
10
+ use Psr\Http\Message\ResponseInterface;
11
+
12
+ /**
13
+ * Handler that returns responses or throw exceptions from a queue.
14
+ */
15
+ class MockHandler implements \Countable
16
+ {
17
+ private $queue = [];
18
+ private $lastRequest;
19
+ private $lastOptions;
20
+ private $onFulfilled;
21
+ private $onRejected;
22
+
23
+ /**
24
+ * Creates a new MockHandler that uses the default handler stack list of
25
+ * middlewares.
26
+ *
27
+ * @param array $queue Array of responses, callables, or exceptions.
28
+ * @param callable $onFulfilled Callback to invoke when the return value is fulfilled.
29
+ * @param callable $onRejected Callback to invoke when the return value is rejected.
30
+ *
31
+ * @return HandlerStack
32
+ */
33
+ public static function createWithMiddleware(
34
+ array $queue = null,
35
+ callable $onFulfilled = null,
36
+ callable $onRejected = null
37
+ ) {
38
+ return HandlerStack::create(new self($queue, $onFulfilled, $onRejected));
39
+ }
40
+
41
+ /**
42
+ * The passed in value must be an array of
43
+ * {@see Psr7\Http\Message\ResponseInterface} objects, Exceptions,
44
+ * callables, or Promises.
45
+ *
46
+ * @param array $queue
47
+ * @param callable $onFulfilled Callback to invoke when the return value is fulfilled.
48
+ * @param callable $onRejected Callback to invoke when the return value is rejected.
49
+ */
50
+ public function __construct(
51
+ array $queue = null,
52
+ callable $onFulfilled = null,
53
+ callable $onRejected = null
54
+ ) {
55
+ $this->onFulfilled = $onFulfilled;
56
+ $this->onRejected = $onRejected;
57
+
58
+ if ($queue) {
59
+ call_user_func_array([$this, 'append'], $queue);
60
+ }
61
+ }
62
+
63
+ public function __invoke(RequestInterface $request, array $options)
64
+ {
65
+ if (!$this->queue) {
66
+ throw new \OutOfBoundsException('Mock queue is empty');
67
+ }
68
+
69
+ if (isset($options['delay']) && is_numeric($options['delay'])) {
70
+ usleep($options['delay'] * 1000);
71
+ }
72
+
73
+ $this->lastRequest = $request;
74
+ $this->lastOptions = $options;
75
+ $response = array_shift($this->queue);
76
+
77
+ if (isset($options['on_headers'])) {
78
+ if (!is_callable($options['on_headers'])) {
79
+ throw new \InvalidArgumentException('on_headers must be callable');
80
+ }
81
+ try {
82
+ $options['on_headers']($response);
83
+ } catch (\Exception $e) {
84
+ $msg = 'An error was encountered during the on_headers event';
85
+ $response = new RequestException($msg, $request, $response, $e);
86
+ }
87
+ }
88
+
89
+ if (is_callable($response)) {
90
+ $response = call_user_func($response, $request, $options);
91
+ }
92
+
93
+ $response = $response instanceof \Exception
94
+ ? \GuzzleHttp\Promise\rejection_for($response)
95
+ : \GuzzleHttp\Promise\promise_for($response);
96
+
97
+ return $response->then(
98
+ function ($value) use ($request, $options) {
99
+ $this->invokeStats($request, $options, $value);
100
+ if ($this->onFulfilled) {
101
+ call_user_func($this->onFulfilled, $value);
102
+ }
103
+ if (isset($options['sink'])) {
104
+ $contents = (string) $value->getBody();
105
+ $sink = $options['sink'];
106
+
107
+ if (is_resource($sink)) {
108
+ fwrite($sink, $contents);
109
+ } elseif (is_string($sink)) {
110
+ file_put_contents($sink, $contents);
111
+ } elseif ($sink instanceof \Psr\Http\Message\StreamInterface) {
112
+ $sink->write($contents);
113
+ }
114
+ }
115
+
116
+ return $value;
117
+ },
118
+ function ($reason) use ($request, $options) {
119
+ $this->invokeStats($request, $options, null, $reason);
120
+ if ($this->onRejected) {
121
+ call_user_func($this->onRejected, $reason);
122
+ }
123
+ return \GuzzleHttp\Promise\rejection_for($reason);
124
+ }
125
+ );
126
+ }
127
+
128
+ /**
129
+ * Adds one or more variadic requests, exceptions, callables, or promises
130
+ * to the queue.
131
+ */
132
+ public function append()
133
+ {
134
+ foreach (func_get_args() as $value) {
135
+ if ($value instanceof ResponseInterface
136
+ || $value instanceof \Exception
137
+ || $value instanceof PromiseInterface
138
+ || is_callable($value)
139
+ ) {
140
+ $this->queue[] = $value;
141
+ } else {
142
+ throw new \InvalidArgumentException('Expected a response or '
143
+ . 'exception. Found ' . \GuzzleHttp\describe_type($value));
144
+ }
145
+ }
146
+ }
147
+
148
+ /**
149
+ * Get the last received request.
150
+ *
151
+ * @return RequestInterface
152
+ */
153
+ public function getLastRequest()
154
+ {
155
+ return $this->lastRequest;
156
+ }
157
+
158
+ /**
159
+ * Get the last received request options.
160
+ *
161
+ * @return array
162
+ */
163
+ public function getLastOptions()
164
+ {
165
+ return $this->lastOptions;
166
+ }
167
+
168
+ /**
169
+ * Returns the number of remaining items in the queue.
170
+ *
171
+ * @return int
172
+ */
173
+ public function count()
174
+ {
175
+ return count($this->queue);
176
+ }
177
+
178
+ public function reset()
179
+ {
180
+ $this->queue = [];
181
+ }
182
+
183
+ private function invokeStats(
184
+ RequestInterface $request,
185
+ array $options,
186
+ ResponseInterface $response = null,
187
+ $reason = null
188
+ ) {
189
+ if (isset($options['on_stats'])) {
190
+ $transferTime = isset($options['transfer_time']) ? $options['transfer_time'] : 0;
191
+ $stats = new TransferStats($request, $response, $transferTime, $reason);
192
+ call_user_func($options['on_stats'], $stats);
193
+ }
194
+ }
195
+ }
vendor/guzzlehttp/guzzle/src/Handler/Proxy.php ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Handler;
3
+
4
+ use GuzzleHttp\RequestOptions;
5
+ use Psr\Http\Message\RequestInterface;
6
+
7
+ /**
8
+ * Provides basic proxies for handlers.
9
+ */
10
+ class Proxy
11
+ {
12
+ /**
13
+ * Sends synchronous requests to a specific handler while sending all other
14
+ * requests to another handler.
15
+ *
16
+ * @param callable $default Handler used for normal responses
17
+ * @param callable $sync Handler used for synchronous responses.
18
+ *
19
+ * @return callable Returns the composed handler.
20
+ */
21
+ public static function wrapSync(
22
+ callable $default,
23
+ callable $sync
24
+ ) {
25
+ return function (RequestInterface $request, array $options) use ($default, $sync) {
26
+ return empty($options[RequestOptions::SYNCHRONOUS])
27
+ ? $default($request, $options)
28
+ : $sync($request, $options);
29
+ };
30
+ }
31
+
32
+ /**
33
+ * Sends streaming requests to a streaming compatible handler while sending
34
+ * all other requests to a default handler.
35
+ *
36
+ * This, for example, could be useful for taking advantage of the
37
+ * performance benefits of curl while still supporting true streaming
38
+ * through the StreamHandler.
39
+ *
40
+ * @param callable $default Handler used for non-streaming responses
41
+ * @param callable $streaming Handler used for streaming responses
42
+ *
43
+ * @return callable Returns the composed handler.
44
+ */
45
+ public static function wrapStreaming(
46
+ callable $default,
47
+ callable $streaming
48
+ ) {
49
+ return function (RequestInterface $request, array $options) use ($default, $streaming) {
50
+ return empty($options['stream'])
51
+ ? $default($request, $options)
52
+ : $streaming($request, $options);
53
+ };
54
+ }
55
+ }
vendor/guzzlehttp/guzzle/src/Handler/StreamHandler.php ADDED
@@ -0,0 +1,545 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp\Handler;
3
+
4
+ use GuzzleHttp\Exception\ConnectException;
5
+ use GuzzleHttp\Exception\RequestException;
6
+ use GuzzleHttp\Promise\FulfilledPromise;
7
+ use GuzzleHttp\Promise\PromiseInterface;
8
+ use GuzzleHttp\Psr7;
9
+ use GuzzleHttp\TransferStats;
10
+ use GuzzleHttp\Utils;
11
+ use Psr\Http\Message\RequestInterface;
12
+ use Psr\Http\Message\ResponseInterface;
13
+ use Psr\Http\Message\StreamInterface;
14
+
15
+ /**
16
+ * HTTP handler that uses PHP's HTTP stream wrapper.
17
+ */
18
+ class StreamHandler
19
+ {
20
+ private $lastHeaders = [];
21
+
22
+ /**
23
+ * Sends an HTTP request.
24
+ *
25
+ * @param RequestInterface $request Request to send.
26
+ * @param array $options Request transfer options.
27
+ *
28
+ * @return PromiseInterface
29
+ */
30
+ public function __invoke(RequestInterface $request, array $options)
31
+ {
32
+ // Sleep if there is a delay specified.
33
+ if (isset($options['delay'])) {
34
+ usleep($options['delay'] * 1000);
35
+ }
36
+
37
+ $startTime = isset($options['on_stats']) ? Utils::currentTime() : null;
38
+
39
+ try {
40
+ // Does not support the expect header.
41
+ $request = $request->withoutHeader('Expect');
42
+
43
+ // Append a content-length header if body size is zero to match
44
+ // cURL's behavior.
45
+ if (0 === $request->getBody()->getSize()) {
46
+ $request = $request->withHeader('Content-Length', '0');
47
+ }
48
+
49
+ return $this->createResponse(
50
+ $request,
51
+ $options,
52
+ $this->createStream($request, $options),
53
+ $startTime
54
+ );
55
+ } catch (\InvalidArgumentException $e) {
56
+ throw $e;
57
+ } catch (\Exception $e) {
58
+ // Determine if the error was a networking error.
59
+ $message = $e->getMessage();
60
+ // This list can probably get more comprehensive.
61
+ if (strpos($message, 'getaddrinfo') // DNS lookup failed
62
+ || strpos($message, 'Connection refused')
63
+ || strpos($message, "couldn't connect to host") // error on HHVM
64
+ || strpos($message, "connection attempt failed")
65
+ ) {
66
+ $e = new ConnectException($e->getMessage(), $request, $e);
67
+ }
68
+ $e = RequestException::wrapException($request, $e);
69
+ $this->invokeStats($options, $request, $startTime, null, $e);
70
+
71
+ return \GuzzleHttp\Promise\rejection_for($e);
72
+ }
73
+ }
74
+
75
+ private function invokeStats(
76
+ array $options,
77
+ RequestInterface $request,
78
+ $startTime,
79
+ ResponseInterface $response = null,
80
+ $error = null
81
+ ) {
82
+ if (isset($options['on_stats'])) {
83
+ $stats = new TransferStats(
84
+ $request,
85
+ $response,
86
+ Utils::currentTime() - $startTime,
87
+ $error,
88
+ []
89
+ );
90
+ call_user_func($options['on_stats'], $stats);
91
+ }
92
+ }
93
+
94
+ private function createResponse(
95
+ RequestInterface $request,
96
+ array $options,
97
+ $stream,
98
+ $startTime
99
+ ) {
100
+ $hdrs = $this->lastHeaders;
101
+ $this->lastHeaders = [];
102
+ $parts = explode(' ', array_shift($hdrs), 3);
103
+ $ver = explode('/', $parts[0])[1];
104
+ $status = $parts[1];
105
+ $reason = isset($parts[2]) ? $parts[2] : null;
106
+ $headers = \GuzzleHttp\headers_from_lines($hdrs);
107
+ list($stream, $headers) = $this->checkDecode($options, $headers, $stream);
108
+ $stream = Psr7\stream_for($stream);
109
+ $sink = $stream;
110
+
111
+ if (strcasecmp('HEAD', $request->getMethod())) {
112
+ $sink = $this->createSink($stream, $options);
113
+ }
114
+
115
+ $response = new Psr7\Response($status, $headers, $sink, $ver, $reason);
116
+
117
+ if (isset($options['on_headers'])) {
118
+ try {
119
+ $options['on_headers']($response);
120
+ } catch (\Exception $e) {
121
+ $msg = 'An error was encountered during the on_headers event';
122
+ $ex = new RequestException($msg, $request, $response, $e);
123
+ return \GuzzleHttp\Promise\rejection_for($ex);
124
+ }
125
+ }
126
+
127
+ // Do not drain when the request is a HEAD request because they have
128
+ // no body.
129
+ if ($sink !== $stream) {
130
+ $this->drain(
131
+ $stream,
132
+ $sink,
133
+ $response->getHeaderLine('Content-Length')
134
+ );
135
+ }
136
+
137
+ $this->invokeStats($options, $request, $startTime, $response, null);
138
+
139
+ return new FulfilledPromise($response);
140
+ }
141
+
142
+ private function createSink(StreamInterface $stream, array $options)
143
+ {
144
+ if (!empty($options['stream'])) {
145
+ return $stream;
146
+ }
147
+
148
+ $sink = isset($options['sink'])
149
+ ? $options['sink']
150
+ : fopen('php://temp', 'r+');
151
+
152
+ return is_string($sink)
153
+ ? new Psr7\LazyOpenStream($sink, 'w+')
154
+ : Psr7\stream_for($sink);
155
+ }
156
+
157
+ private function checkDecode(array $options, array $headers, $stream)
158
+ {
159
+ // Automatically decode responses when instructed.
160
+ if (!empty($options['decode_content'])) {
161
+ $normalizedKeys = \GuzzleHttp\normalize_header_keys($headers);
162
+ if (isset($normalizedKeys['content-encoding'])) {
163
+ $encoding = $headers[$normalizedKeys['content-encoding']];
164
+ if ($encoding[0] === 'gzip' || $encoding[0] === 'deflate') {
165
+ $stream = new Psr7\InflateStream(
166
+ Psr7\stream_for($stream)
167
+ );
168
+ $headers['x-encoded-content-encoding']
169
+ = $headers[$normalizedKeys['content-encoding']];
170
+ // Remove content-encoding header
171
+ unset($headers[$normalizedKeys['content-encoding']]);
172
+ // Fix content-length header
173
+ if (isset($normalizedKeys['content-length'])) {
174
+ $headers['x-encoded-content-length']
175
+ = $headers[$normalizedKeys['content-length']];
176
+
177
+ $length = (int) $stream->getSize();
178
+ if ($length === 0) {
179
+ unset($headers[$normalizedKeys['content-length']]);
180
+ } else {
181
+ $headers[$normalizedKeys['content-length']] = [$length];
182
+ }
183
+ }
184
+ }
185
+ }
186
+ }
187
+
188
+ return [$stream, $headers];
189
+ }
190
+
191
+ /**
192
+ * Drains the source stream into the "sink" client option.
193
+ *
194
+ * @param StreamInterface $source
195
+ * @param StreamInterface $sink
196
+ * @param string $contentLength Header specifying the amount of
197
+ * data to read.
198
+ *
199
+ * @return StreamInterface
200
+ * @throws \RuntimeException when the sink option is invalid.
201
+ */
202
+ private function drain(
203
+ StreamInterface $source,
204
+ StreamInterface $sink,
205
+ $contentLength
206
+ ) {
207
+ // If a content-length header is provided, then stop reading once
208
+ // that number of bytes has been read. This can prevent infinitely
209
+ // reading from a stream when dealing with servers that do not honor
210
+ // Connection: Close headers.
211
+ Psr7\copy_to_stream(
212
+ $source,
213
+ $sink,
214
+ (strlen($contentLength) > 0 && (int) $contentLength > 0) ? (int) $contentLength : -1
215
+ );
216
+
217
+ $sink->seek(0);
218
+ $source->close();
219
+
220
+ return $sink;
221
+ }
222
+
223
+ /**
224
+ * Create a resource and check to ensure it was created successfully
225
+ *
226
+ * @param callable $callback Callable that returns stream resource
227
+ *
228
+ * @return resource
229
+ * @throws \RuntimeException on error
230
+ */
231
+ private function createResource(callable $callback)
232
+ {
233
+ $errors = null;
234
+ set_error_handler(function ($_, $msg, $file, $line) use (&$errors) {
235
+ $errors[] = [
236
+ 'message' => $msg,
237
+ 'file' => $file,
238
+ 'line' => $line
239
+ ];
240
+ return true;
241
+ });
242
+
243
+ $resource = $callback();
244
+ restore_error_handler();
245
+
246
+ if (!$resource) {
247
+ $message = 'Error creating resource: ';
248
+ foreach ($errors as $err) {
249
+ foreach ($err as $key => $value) {
250
+ $message .= "[$key] $value" . PHP_EOL;
251
+ }
252
+ }
253
+ throw new \RuntimeException(trim($message));
254
+ }
255
+
256
+ return $resource;
257
+ }
258
+
259
+ private function createStream(RequestInterface $request, array $options)
260
+ {
261
+ static $methods;
262
+ if (!$methods) {
263
+ $methods = array_flip(get_class_methods(__CLASS__));
264
+ }
265
+
266
+ // HTTP/1.1 streams using the PHP stream wrapper require a
267
+ // Connection: close header
268
+ if ($request->getProtocolVersion() == '1.1'
269
+ && !$request->hasHeader('Connection')
270
+ ) {
271
+ $request = $request->withHeader('Connection', 'close');
272
+ }
273
+
274
+ // Ensure SSL is verified by default
275
+ if (!isset($options['verify'])) {
276
+ $options['verify'] = true;
277
+ }
278
+
279
+ $params = [];
280
+ $context = $this->getDefaultContext($request);
281
+
282
+ if (isset($options['on_headers']) && !is_callable($options['on_headers'])) {
283
+ throw new \InvalidArgumentException('on_headers must be callable');
284
+ }
285
+
286
+ if (!empty($options)) {
287
+ foreach ($options as $key => $value) {
288
+ $method = "add_{$key}";
289
+ if (isset($methods[$method])) {
290
+ $this->{$method}($request, $context, $value, $params);
291
+ }
292
+ }
293
+ }
294
+
295
+ if (isset($options['stream_context'])) {
296
+ if (!is_array($options['stream_context'])) {
297
+ throw new \InvalidArgumentException('stream_context must be an array');
298
+ }
299
+ $context = array_replace_recursive(
300
+ $context,
301
+ $options['stream_context']
302
+ );
303
+ }
304
+
305
+ // Microsoft NTLM authentication only supported with curl handler
306
+ if (isset($options['auth'])
307
+ && is_array($options['auth'])
308
+ && isset($options['auth'][2])
309
+ && 'ntlm' == $options['auth'][2]
310
+ ) {
311
+ throw new \InvalidArgumentException('Microsoft NTLM authentication only supported with curl handler');
312
+ }
313
+
314
+ $uri = $this->resolveHost($request, $options);
315
+
316
+ $context = $this->createResource(
317
+ function () use ($context, $params) {
318
+ return stream_context_create($context, $params);
319
+ }
320
+ );
321
+
322
+ return $this->createResource(
323
+ function () use ($uri, &$http_response_header, $context, $options) {
324
+ $resource = fopen((string) $uri, 'r', null, $context);
325
+ $this->lastHeaders = $http_response_header;
326
+
327
+ if (isset($options['read_timeout'])) {
328
+ $readTimeout = $options['read_timeout'];
329
+ $sec = (int) $readTimeout;
330
+ $usec = ($readTimeout - $sec) * 100000;
331
+ stream_set_timeout($resource, $sec, $usec);
332
+ }
333
+
334
+ return $resource;
335
+ }
336
+ );
337
+ }
338
+
339
+ private function resolveHost(RequestInterface $request, array $options)
340
+ {
341
+ $uri = $request->getUri();
342
+
343
+ if (isset($options['force_ip_resolve']) && !filter_var($uri->getHost(), FILTER_VALIDATE_IP)) {
344
+ if ('v4' === $options['force_ip_resolve']) {
345
+ $records = dns_get_record($uri->getHost(), DNS_A);
346
+ if (!isset($records[0]['ip'])) {
347
+ throw new ConnectException(
348
+ sprintf(
349
+ "Could not resolve IPv4 address for host '%s'",
350
+ $uri->getHost()
351
+ ),
352
+ $request
353
+ );
354
+ }
355
+ $uri = $uri->withHost($records[0]['ip']);
356
+ } elseif ('v6' === $options['force_ip_resolve']) {
357
+ $records = dns_get_record($uri->getHost(), DNS_AAAA);
358
+ if (!isset($records[0]['ipv6'])) {
359
+ throw new ConnectException(
360
+ sprintf(
361
+ "Could not resolve IPv6 address for host '%s'",
362
+ $uri->getHost()
363
+ ),
364
+ $request
365
+ );
366
+ }
367
+ $uri = $uri->withHost('[' . $records[0]['ipv6'] . ']');
368
+ }
369
+ }
370
+
371
+ return $uri;
372
+ }
373
+
374
+ private function getDefaultContext(RequestInterface $request)
375
+ {
376
+ $headers = '';
377
+ foreach ($request->getHeaders() as $name => $value) {
378
+ foreach ($value as $val) {
379
+ $headers .= "$name: $val\r\n";
380
+ }
381
+ }
382
+
383
+ $context = [
384
+ 'http' => [
385
+ 'method' => $request->getMethod(),
386
+ 'header' => $headers,
387
+ 'protocol_version' => $request->getProtocolVersion(),
388
+ 'ignore_errors' => true,
389
+ 'follow_location' => 0,
390
+ ],
391
+ ];
392
+
393
+ $body = (string) $request->getBody();
394
+
395
+ if (!empty($body)) {
396
+ $context['http']['content'] = $body;
397
+ // Prevent the HTTP handler from adding a Content-Type header.
398
+ if (!$request->hasHeader('Content-Type')) {
399
+ $context['http']['header'] .= "Content-Type:\r\n";
400
+ }
401
+ }
402
+
403
+ $context['http']['header'] = rtrim($context['http']['header']);
404
+
405
+ return $context;
406
+ }
407
+
408
+ private function add_proxy(RequestInterface $request, &$options, $value, &$params)
409
+ {
410
+ if (!is_array($value)) {
411
+ $options['http']['proxy'] = $value;
412
+ } else {
413
+ $scheme = $request->getUri()->getScheme();
414
+ if (isset($value[$scheme])) {
415
+ if (!isset($value['no'])
416
+ || !\GuzzleHttp\is_host_in_noproxy(
417
+ $request->getUri()->getHost(),
418
+ $value['no']
419
+ )
420
+ ) {
421
+ $options['http']['proxy'] = $value[$scheme];
422
+ }
423
+ }
424
+ }
425
+ }
426
+
427
+ private function add_timeout(RequestInterface $request, &$options, $value, &$params)
428
+ {
429
+ if ($value > 0) {
430
+ $options['http']['timeout'] = $value;
431
+ }
432
+ }
433
+
434
+ private function add_verify(RequestInterface $request, &$options, $value, &$params)
435
+ {
436
+ if ($value === true) {
437
+ // PHP 5.6 or greater will find the system cert by default. When
438
+ // < 5.6, use the Guzzle bundled cacert.
439
+ if (PHP_VERSION_ID < 50600) {
440
+ $options['ssl']['cafile'] = \GuzzleHttp\default_ca_bundle();
441
+ }
442
+ } elseif (is_string($value)) {
443
+ $options['ssl']['cafile'] = $value;
444
+ if (!file_exists($value)) {
445
+ throw new \RuntimeException("SSL CA bundle not found: $value");
446
+ }
447
+ } elseif ($value === false) {
448
+ $options['ssl']['verify_peer'] = false;
449
+ $options['ssl']['verify_peer_name'] = false;
450
+ return;
451
+ } else {
452
+ throw new \InvalidArgumentException('Invalid verify request option');
453
+ }
454
+
455
+ $options['ssl']['verify_peer'] = true;
456
+ $options['ssl']['verify_peer_name'] = true;
457
+ $options['ssl']['allow_self_signed'] = false;
458
+ }
459
+
460
+ private function add_cert(RequestInterface $request, &$options, $value, &$params)
461
+ {
462
+ if (is_array($value)) {
463
+ $options['ssl']['passphrase'] = $value[1];
464
+ $value = $value[0];
465
+ }
466
+
467
+ if (!file_exists($value)) {
468
+ throw new \RuntimeException("SSL certificate not found: {$value}");
469
+ }
470
+
471
+ $options['ssl']['local_cert'] = $value;
472
+ }
473
+
474
+ private function add_progress(RequestInterface $request, &$options, $value, &$params)
475
+ {
476
+ $this->addNotification(
477
+ $params,
478
+ function ($code, $a, $b, $c, $transferred, $total) use ($value) {
479
+ if ($code == STREAM_NOTIFY_PROGRESS) {
480
+ $value($total, $transferred, null, null);
481
+ }
482
+ }
483
+ );
484
+ }
485
+
486
+ private function add_debug(RequestInterface $request, &$options, $value, &$params)
487
+ {
488
+ if ($value === false) {
489
+ return;
490
+ }
491
+
492
+ static $map = [
493
+ STREAM_NOTIFY_CONNECT => 'CONNECT',
494
+ STREAM_NOTIFY_AUTH_REQUIRED => 'AUTH_REQUIRED',
495
+ STREAM_NOTIFY_AUTH_RESULT => 'AUTH_RESULT',
496
+ STREAM_NOTIFY_MIME_TYPE_IS => 'MIME_TYPE_IS',
497
+ STREAM_NOTIFY_FILE_SIZE_IS => 'FILE_SIZE_IS',
498
+ STREAM_NOTIFY_REDIRECTED => 'REDIRECTED',
499
+ STREAM_NOTIFY_PROGRESS => 'PROGRESS',
500
+ STREAM_NOTIFY_FAILURE => 'FAILURE',
501
+ STREAM_NOTIFY_COMPLETED => 'COMPLETED',
502
+ STREAM_NOTIFY_RESOLVE => 'RESOLVE',
503
+ ];
504
+ static $args = ['severity', 'message', 'message_code',
505
+ 'bytes_transferred', 'bytes_max'];
506
+
507
+ $value = \GuzzleHttp\debug_resource($value);
508
+ $ident = $request->getMethod() . ' ' . $request->getUri()->withFragment('');
509
+ $this->addNotification(
510
+ $params,
511
+ function () use ($ident, $value, $map, $args) {
512
+ $passed = func_get_args();
513
+ $code = array_shift($passed);
514
+ fprintf($value, '<%s> [%s] ', $ident, $map[$code]);
515
+ foreach (array_filter($passed) as $i => $v) {
516
+ fwrite($value, $args[$i] . ': "' . $v . '" ');
517
+ }
518
+ fwrite($value, "\n");
519
+ }
520
+ );
521
+ }
522
+
523
+ private function addNotification(array &$params, callable $notify)
524
+ {
525
+ // Wrap the existing function if needed.
526
+ if (!isset($params['notification'])) {
527
+ $params['notification'] = $notify;
528
+ } else {
529
+ $params['notification'] = $this->callArray([
530
+ $params['notification'],
531
+ $notify
532
+ ]);
533
+ }
534
+ }
535
+
536
+ private function callArray(array $functions)
537
+ {
538
+ return function () use ($functions) {
539
+ $args = func_get_args();
540
+ foreach ($functions as $fn) {
541
+ call_user_func_array($fn, $args);
542
+ }
543
+ };
544
+ }
545
+ }
vendor/guzzlehttp/guzzle/src/HandlerStack.php ADDED
@@ -0,0 +1,277 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp;
3
+
4
+ use GuzzleHttp\Promise\PromiseInterface;
5
+ use Psr\Http\Message\RequestInterface;
6
+ use Psr\Http\Message\ResponseInterface;
7
+
8
+ /**
9
+ * Creates a composed Guzzle handler function by stacking middlewares on top of
10
+ * an HTTP handler function.
11
+ */
12
+ class HandlerStack
13
+ {
14
+ /** @var callable|null */
15
+ private $handler;
16
+
17
+ /** @var array */
18
+ private $stack = [];
19
+
20
+ /** @var callable|null */
21
+ private $cached;
22
+
23
+ /**
24
+ * Creates a default handler stack that can be used by clients.
25
+ *
26
+ * The returned handler will wrap the provided handler or use the most
27
+ * appropriate default handler for your system. The returned HandlerStack has
28
+ * support for cookies, redirects, HTTP error exceptions, and preparing a body
29
+ * before sending.
30
+ *
31
+ * The returned handler stack can be passed to a client in the "handler"
32
+ * option.
33
+ *
34
+ * @param callable $handler HTTP handler function to use with the stack. If no
35
+ * handler is provided, the best handler for your
36
+ * system will be utilized.
37
+ *
38
+ * @return HandlerStack
39
+ */
40
+ public static function create(callable $handler = null)
41
+ {
42
+ $stack = new self($handler ?: choose_handler());
43
+ $stack->push(Middleware::httpErrors(), 'http_errors');
44
+ $stack->push(Middleware::redirect(), 'allow_redirects');
45
+ $stack->push(Middleware::cookies(), 'cookies');
46
+ $stack->push(Middleware::prepareBody(), 'prepare_body');
47
+
48
+ return $stack;
49
+ }
50
+
51
+ /**
52
+ * @param callable $handler Underlying HTTP handler.
53
+ */
54
+ public function __construct(callable $handler = null)
55
+ {
56
+ $this->handler = $handler;
57
+ }
58
+
59
+ /**
60
+ * Invokes the handler stack as a composed handler
61
+ *
62
+ * @param RequestInterface $request
63
+ * @param array $options
64
+ *
65
+ * @return ResponseInterface|PromiseInterface
66
+ */
67
+ public function __invoke(RequestInterface $request, array $options)
68
+ {
69
+ $handler = $this->resolve();
70
+
71
+ return $handler($request, $options);
72
+ }
73
+
74
+ /**
75
+ * Dumps a string representation of the stack.
76
+ *
77
+ * @return string
78
+ */
79
+ public function __toString()
80
+ {
81
+ $depth = 0;
82
+ $stack = [];
83
+ if ($this->handler) {
84
+ $stack[] = "0) Handler: " . $this->debugCallable($this->handler);
85
+ }
86
+
87
+ $result = '';
88
+ foreach (array_reverse($this->stack) as $tuple) {
89
+ $depth++;
90
+ $str = "{$depth}) Name: '{$tuple[1]}', ";
91
+ $str .= "Function: " . $this->debugCallable($tuple[0]);
92
+ $result = "> {$str}\n{$result}";
93
+ $stack[] = $str;
94
+ }
95
+
96
+ foreach (array_keys($stack) as $k) {
97
+ $result .= "< {$stack[$k]}\n";
98
+ }
99
+
100
+ return $result;
101
+ }
102
+
103
+ /**
104
+ * Set the HTTP handler that actually returns a promise.
105
+ *
106
+ * @param callable $handler Accepts a request and array of options and
107
+ * returns a Promise.
108
+ */
109
+ public function setHandler(callable $handler)
110
+ {
111
+ $this->handler = $handler;
112
+ $this->cached = null;
113
+ }
114
+
115
+ /**
116
+ * Returns true if the builder has a handler.
117
+ *
118
+ * @return bool
119
+ */
120
+ public function hasHandler()
121
+ {
122
+ return (bool) $this->handler;
123
+ }
124
+
125
+ /**
126
+ * Unshift a middleware to the bottom of the stack.
127
+ *
128
+ * @param callable $middleware Middleware function
129
+ * @param string $name Name to register for this middleware.
130
+ */
131
+ public function unshift(callable $middleware, $name = null)
132
+ {
133
+ array_unshift($this->stack, [$middleware, $name]);
134
+ $this->cached = null;
135
+ }
136
+
137
+ /**
138
+ * Push a middleware to the top of the stack.
139
+ *
140
+ * @param callable $middleware Middleware function
141
+ * @param string $name Name to register for this middleware.
142
+ */
143
+ public function push(callable $middleware, $name = '')
144
+ {
145
+ $this->stack[] = [$middleware, $name];
146
+ $this->cached = null;
147
+ }
148
+
149
+ /**
150
+ * Add a middleware before another middleware by name.
151
+ *
152
+ * @param string $findName Middleware to find
153
+ * @param callable $middleware Middleware function
154
+ * @param string $withName Name to register for this middleware.
155
+ */
156
+ public function before($findName, callable $middleware, $withName = '')
157
+ {
158
+ $this->splice($findName, $withName, $middleware, true);
159
+ }
160
+
161
+ /**
162
+ * Add a middleware after another middleware by name.
163
+ *
164
+ * @param string $findName Middleware to find
165
+ * @param callable $middleware Middleware function
166
+ * @param string $withName Name to register for this middleware.
167
+ */
168
+ public function after($findName, callable $middleware, $withName = '')
169
+ {
170
+ $this->splice($findName, $withName, $middleware, false);
171
+ }
172
+
173
+ /**
174
+ * Remove a middleware by instance or name from the stack.
175
+ *
176
+ * @param callable|string $remove Middleware to remove by instance or name.
177
+ */
178
+ public function remove($remove)
179
+ {
180
+ $this->cached = null;
181
+ $idx = is_callable($remove) ? 0 : 1;
182
+ $this->stack = array_values(array_filter(
183
+ $this->stack,
184
+ function ($tuple) use ($idx, $remove) {
185
+ return $tuple[$idx] !== $remove;
186
+ }
187
+ ));
188
+ }
189
+
190
+ /**
191
+ * Compose the middleware and handler into a single callable function.
192
+ *
193
+ * @return callable
194
+ */
195
+ public function resolve()
196
+ {
197
+ if (!$this->cached) {
198
+ if (!($prev = $this->handler)) {
199
+ throw new \LogicException('No handler has been specified');
200
+ }
201
+
202
+ foreach (array_reverse($this->stack) as $fn) {
203
+ $prev = $fn[0]($prev);
204
+ }
205
+
206
+ $this->cached = $prev;
207
+ }
208
+
209
+ return $this->cached;
210
+ }
211
+
212
+ /**
213
+ * @param string $name
214
+ * @return int
215
+ */
216
+ private function findByName($name)
217
+ {
218
+ foreach ($this->stack as $k => $v) {
219
+ if ($v[1] === $name) {
220
+ return $k;
221
+ }
222
+ }
223
+
224
+ throw new \InvalidArgumentException("Middleware not found: $name");
225
+ }
226
+
227
+ /**
228
+ * Splices a function into the middleware list at a specific position.
229
+ *
230
+ * @param string $findName
231
+ * @param string $withName
232
+ * @param callable $middleware
233
+ * @param bool $before
234
+ */
235
+ private function splice($findName, $withName, callable $middleware, $before)
236
+ {
237
+ $this->cached = null;
238
+ $idx = $this->findByName($findName);
239
+ $tuple = [$middleware, $withName];
240
+
241
+ if ($before) {
242
+ if ($idx === 0) {
243
+ array_unshift($this->stack, $tuple);
244
+ } else {
245
+ $replacement = [$tuple, $this->stack[$idx]];
246
+ array_splice($this->stack, $idx, 1, $replacement);
247
+ }
248
+ } elseif ($idx === count($this->stack) - 1) {
249
+ $this->stack[] = $tuple;
250
+ } else {
251
+ $replacement = [$this->stack[$idx], $tuple];
252
+ array_splice($this->stack, $idx, 1, $replacement);
253
+ }
254
+ }
255
+
256
+ /**
257
+ * Provides a debug string for a given callable.
258
+ *
259
+ * @param array|callable $fn Function to write as a string.
260
+ *
261
+ * @return string
262
+ */
263
+ private function debugCallable($fn)
264
+ {
265
+ if (is_string($fn)) {
266
+ return "callable({$fn})";
267
+ }
268
+
269
+ if (is_array($fn)) {
270
+ return is_string($fn[0])
271
+ ? "callable({$fn[0]}::{$fn[1]})"
272
+ : "callable(['" . get_class($fn[0]) . "', '{$fn[1]}'])";
273
+ }
274
+
275
+ return 'callable(' . spl_object_hash($fn) . ')';
276
+ }
277
+ }
vendor/guzzlehttp/guzzle/src/MessageFormatter.php ADDED
@@ -0,0 +1,185 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp;
3
+
4
+ use Psr\Http\Message\MessageInterface;
5
+ use Psr\Http\Message\RequestInterface;
6
+ use Psr\Http\Message\ResponseInterface;
7
+
8
+ /**
9
+ * Formats log messages using variable substitutions for requests, responses,
10
+ * and other transactional data.
11
+ *
12
+ * The following variable substitutions are supported:
13
+ *
14
+ * - {request}: Full HTTP request message
15
+ * - {response}: Full HTTP response message
16
+ * - {ts}: ISO 8601 date in GMT
17
+ * - {date_iso_8601} ISO 8601 date in GMT
18
+ * - {date_common_log} Apache common log date using the configured timezone.
19
+ * - {host}: Host of the request
20
+ * - {method}: Method of the request
21
+ * - {uri}: URI of the request
22
+ * - {version}: Protocol version
23
+ * - {target}: Request target of the request (path + query + fragment)
24
+ * - {hostname}: Hostname of the machine that sent the request
25
+ * - {code}: Status code of the response (if available)
26
+ * - {phrase}: Reason phrase of the response (if available)
27
+ * - {error}: Any error messages (if available)
28
+ * - {req_header_*}: Replace `*` with the lowercased name of a request header to add to the message
29
+ * - {res_header_*}: Replace `*` with the lowercased name of a response header to add to the message
30
+ * - {req_headers}: Request headers
31
+ * - {res_headers}: Response headers
32
+ * - {req_body}: Request body
33
+ * - {res_body}: Response body
34
+ */
35
+ class MessageFormatter
36
+ {
37
+ /**
38
+ * Apache Common Log Format.
39
+ * @link http://httpd.apache.org/docs/2.4/logs.html#common
40
+ * @var string
41
+ */
42
+ const CLF = "{hostname} {req_header_User-Agent} - [{date_common_log}] \"{method} {target} HTTP/{version}\" {code} {res_header_Content-Length}";
43
+ const DEBUG = ">>>>>>>>\n{request}\n<<<<<<<<\n{response}\n--------\n{error}";
44
+ const SHORT = '[{ts}] "{method} {target} HTTP/{version}" {code}';
45
+
46
+ /** @var string Template used to format log messages */
47
+ private $template;
48
+
49
+ /**
50
+ * @param string $template Log message template
51
+ */
52
+ public function __construct($template = self::CLF)
53
+ {
54
+ $this->template = $template ?: self::CLF;
55
+ }
56
+
57
+ /**
58
+ * Returns a formatted message string.
59
+ *
60
+ * @param RequestInterface $request Request that was sent
61
+ * @param ResponseInterface $response Response that was received
62
+ * @param \Exception $error Exception that was received
63
+ *
64
+ * @return string
65
+ */
66
+ public function format(
67
+ RequestInterface $request,
68
+ ResponseInterface $response = null,
69
+ \Exception $error = null
70
+ ) {
71
+ $cache = [];
72
+
73
+ return preg_replace_callback(
74
+ '/{\s*([A-Za-z_\-\.0-9]+)\s*}/',
75
+ function (array $matches) use ($request, $response, $error, &$cache) {
76
+ if (isset($cache[$matches[1]])) {
77
+ return $cache[$matches[1]];
78
+ }
79
+
80
+ $result = '';
81
+ switch ($matches[1]) {
82
+ case 'request':
83
+ $result = Psr7\str($request);
84
+ break;
85
+ case 'response':
86
+ $result = $response ? Psr7\str($response) : '';
87
+ break;
88
+ case 'req_headers':
89
+ $result = trim($request->getMethod()
90
+ . ' ' . $request->getRequestTarget())
91
+ . ' HTTP/' . $request->getProtocolVersion() . "\r\n"
92
+ . $this->headers($request);
93
+ break;
94
+ case 'res_headers':
95
+ $result = $response ?
96
+ sprintf(
97
+ 'HTTP/%s %d %s',
98
+ $response->getProtocolVersion(),
99
+ $response->getStatusCode(),
100
+ $response->getReasonPhrase()
101
+ ) . "\r\n" . $this->headers($response)
102
+ : 'NULL';
103
+ break;
104
+ case 'req_body':
105
+ $result = $request->getBody();
106
+ break;
107
+ case 'res_body':
108
+ $result = $response ? $response->getBody() : 'NULL';
109
+ break;
110
+ case 'ts':
111
+ case 'date_iso_8601':
112
+ $result = gmdate('c');
113
+ break;
114
+ case 'date_common_log':
115
+ $result = date('d/M/Y:H:i:s O');
116
+ break;
117
+ case 'method':
118
+ $result = $request->getMethod();
119
+ break;
120
+ case 'version':
121
+ $result = $request->getProtocolVersion();
122
+ break;
123
+ case 'uri':
124
+ case 'url':
125
+ $result = $request->getUri();
126
+ break;
127
+ case 'target':
128
+ $result = $request->getRequestTarget();
129
+ break;
130
+ case 'req_version':
131
+ $result = $request->getProtocolVersion();
132
+ break;
133
+ case 'res_version':
134
+ $result = $response
135
+ ? $response->getProtocolVersion()
136
+ : 'NULL';
137
+ break;
138
+ case 'host':
139
+ $result = $request->getHeaderLine('Host');
140
+ break;
141
+ case 'hostname':
142
+ $result = gethostname();
143
+ break;
144
+ case 'code':
145
+ $result = $response ? $response->getStatusCode() : 'NULL';
146
+ break;
147
+ case 'phrase':
148
+ $result = $response ? $response->getReasonPhrase() : 'NULL';
149
+ break;
150
+ case 'error':
151
+ $result = $error ? $error->getMessage() : 'NULL';
152
+ break;
153
+ default:
154
+ // handle prefixed dynamic headers
155
+ if (strpos($matches[1], 'req_header_') === 0) {
156
+ $result = $request->getHeaderLine(substr($matches[1], 11));
157
+ } elseif (strpos($matches[1], 'res_header_') === 0) {
158
+ $result = $response
159
+ ? $response->getHeaderLine(substr($matches[1], 11))
160
+ : 'NULL';
161
+ }
162
+ }
163
+
164
+ $cache[$matches[1]] = $result;
165
+ return $result;
166
+ },
167
+ $this->template
168
+ );
169
+ }
170
+
171
+ /**
172
+ * Get headers from message as string
173
+ *
174
+ * @return string
175
+ */
176
+ private function headers(MessageInterface $message)
177
+ {
178
+ $result = '';
179
+ foreach ($message->getHeaders() as $name => $values) {
180
+ $result .= $name . ': ' . implode(', ', $values) . "\r\n";
181
+ }
182
+
183
+ return trim($result);
184
+ }
185
+ }
vendor/guzzlehttp/guzzle/src/Middleware.php ADDED
@@ -0,0 +1,254 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp;
3
+
4
+ use GuzzleHttp\Cookie\CookieJarInterface;
5
+ use GuzzleHttp\Exception\RequestException;
6
+ use GuzzleHttp\Promise\RejectedPromise;
7
+ use GuzzleHttp\Psr7;
8
+ use Psr\Http\Message\ResponseInterface;
9
+ use Psr\Log\LoggerInterface;
10
+
11
+ /**
12
+ * Functions used to create and wrap handlers with handler middleware.
13
+ */
14
+ final class Middleware
15
+ {
16
+ /**
17
+ * Middleware that adds cookies to requests.
18
+ *
19
+ * The options array must be set to a CookieJarInterface in order to use
20
+ * cookies. This is typically handled for you by a client.
21
+ *
22
+ * @return callable Returns a function that accepts the next handler.
23
+ */
24
+ public static function cookies()
25
+ {
26
+ return function (callable $handler) {
27
+ return function ($request, array $options) use ($handler) {
28
+ if (empty($options['cookies'])) {
29
+ return $handler($request, $options);
30
+ } elseif (!($options['cookies'] instanceof CookieJarInterface)) {
31
+ throw new \InvalidArgumentException('cookies must be an instance of GuzzleHttp\Cookie\CookieJarInterface');
32
+ }
33
+ $cookieJar = $options['cookies'];
34
+ $request = $cookieJar->withCookieHeader($request);
35
+ return $handler($request, $options)
36
+ ->then(
37
+ function ($response) use ($cookieJar, $request) {
38
+ $cookieJar->extractCookies($request, $response);
39
+ return $response;
40
+ }
41
+ );
42
+ };
43
+ };
44
+ }
45
+
46
+ /**
47
+ * Middleware that throws exceptions for 4xx or 5xx responses when the
48
+ * "http_error" request option is set to true.
49
+ *
50
+ * @return callable Returns a function that accepts the next handler.
51
+ */
52
+ public static function httpErrors()
53
+ {
54
+ return function (callable $handler) {
55
+ return function ($request, array $options) use ($handler) {
56
+ if (empty($options['http_errors'])) {
57
+ return $handler($request, $options);
58
+ }
59
+ return $handler($request, $options)->then(
60
+ function (ResponseInterface $response) use ($request) {
61
+ $code = $response->getStatusCode();
62
+ if ($code < 400) {
63
+ return $response;
64
+ }
65
+ throw RequestException::create($request, $response);
66
+ }
67
+ );
68
+ };
69
+ };
70
+ }
71
+
72
+ /**
73
+ * Middleware that pushes history data to an ArrayAccess container.
74
+ *
75
+ * @param array|\ArrayAccess $container Container to hold the history (by reference).
76
+ *
77
+ * @return callable Returns a function that accepts the next handler.
78
+ * @throws \InvalidArgumentException if container is not an array or ArrayAccess.
79
+ */
80
+ public static function history(&$container)
81
+ {
82
+ if (!is_array($container) && !$container instanceof \ArrayAccess) {
83
+ throw new \InvalidArgumentException('history container must be an array or object implementing ArrayAccess');
84
+ }
85
+
86
+ return function (callable $handler) use (&$container) {
87
+ return function ($request, array $options) use ($handler, &$container) {
88
+ return $handler($request, $options)->then(
89
+ function ($value) use ($request, &$container, $options) {
90
+ $container[] = [
91
+ 'request' => $request,
92
+ 'response' => $value,
93
+ 'error' => null,
94
+ 'options' => $options
95
+ ];
96
+ return $value;
97
+ },
98
+ function ($reason) use ($request, &$container, $options) {
99
+ $container[] = [
100
+ 'request' => $request,
101
+ 'response' => null,
102
+ 'error' => $reason,
103
+ 'options' => $options
104
+ ];
105
+ return \GuzzleHttp\Promise\rejection_for($reason);
106
+ }
107
+ );
108
+ };
109
+ };
110
+ }
111
+
112
+ /**
113
+ * Middleware that invokes a callback before and after sending a request.
114
+ *
115
+ * The provided listener cannot modify or alter the response. It simply
116
+ * "taps" into the chain to be notified before returning the promise. The
117
+ * before listener accepts a request and options array, and the after
118
+ * listener accepts a request, options array, and response promise.
119
+ *
120
+ * @param callable $before Function to invoke before forwarding the request.
121
+ * @param callable $after Function invoked after forwarding.
122
+ *
123
+ * @return callable Returns a function that accepts the next handler.
124
+ */
125
+ public static function tap(callable $before = null, callable $after = null)
126
+ {
127
+ return function (callable $handler) use ($before, $after) {
128
+ return function ($request, array $options) use ($handler, $before, $after) {
129
+ if ($before) {
130
+ $before($request, $options);
131
+ }
132
+ $response = $handler($request, $options);
133
+ if ($after) {
134
+ $after($request, $options, $response);
135
+ }
136
+ return $response;
137
+ };
138
+ };
139
+ }
140
+
141
+ /**
142
+ * Middleware that handles request redirects.
143
+ *
144
+ * @return callable Returns a function that accepts the next handler.
145
+ */
146
+ public static function redirect()
147
+ {
148
+ return function (callable $handler) {
149
+ return new RedirectMiddleware($handler);
150
+ };
151
+ }
152
+
153
+ /**
154
+ * Middleware that retries requests based on the boolean result of
155
+ * invoking the provided "decider" function.
156
+ *
157
+ * If no delay function is provided, a simple implementation of exponential
158
+ * backoff will be utilized.
159
+ *
160
+ * @param callable $decider Function that accepts the number of retries,
161
+ * a request, [response], and [exception] and
162
+ * returns true if the request is to be retried.
163
+ * @param callable $delay Function that accepts the number of retries and
164
+ * returns the number of milliseconds to delay.
165
+ *
166
+ * @return callable Returns a function that accepts the next handler.
167
+ */
168
+ public static function retry(callable $decider, callable $delay = null)
169
+ {
170
+ return function (callable $handler) use ($decider, $delay) {
171
+ return new RetryMiddleware($decider, $handler, $delay);
172
+ };
173
+ }
174
+
175
+ /**
176
+ * Middleware that logs requests, responses, and errors using a message
177
+ * formatter.
178
+ *
179
+ * @param LoggerInterface $logger Logs messages.
180
+ * @param MessageFormatter $formatter Formatter used to create message strings.
181
+ * @param string $logLevel Level at which to log requests.
182
+ *
183
+ * @return callable Returns a function that accepts the next handler.
184
+ */
185
+ public static function log(LoggerInterface $logger, MessageFormatter $formatter, $logLevel = 'info' /* \Psr\Log\LogLevel::INFO */)
186
+ {
187
+ return function (callable $handler) use ($logger, $formatter, $logLevel) {
188
+ return function ($request, array $options) use ($handler, $logger, $formatter, $logLevel) {
189
+ return $handler($request, $options)->then(
190
+ function ($response) use ($logger, $request, $formatter, $logLevel) {
191
+ $message = $formatter->format($request, $response);
192
+ $logger->log($logLevel, $message);
193
+ return $response;
194
+ },
195
+ function ($reason) use ($logger, $request, $formatter) {
196
+ $response = $reason instanceof RequestException
197
+ ? $reason->getResponse()
198
+ : null;
199
+ $message = $formatter->format($request, $response, $reason);
200
+ $logger->notice($message);
201
+ return \GuzzleHttp\Promise\rejection_for($reason);
202
+ }
203
+ );
204
+ };
205
+ };
206
+ }
207
+
208
+ /**
209
+ * This middleware adds a default content-type if possible, a default
210
+ * content-length or transfer-encoding header, and the expect header.
211
+ *
212
+ * @return callable
213
+ */
214
+ public static function prepareBody()
215
+ {
216
+ return function (callable $handler) {
217
+ return new PrepareBodyMiddleware($handler);
218
+ };
219
+ }
220
+
221
+ /**
222
+ * Middleware that applies a map function to the request before passing to
223
+ * the next handler.
224
+ *
225
+ * @param callable $fn Function that accepts a RequestInterface and returns
226
+ * a RequestInterface.
227
+ * @return callable
228
+ */
229
+ public static function mapRequest(callable $fn)
230
+ {
231
+ return function (callable $handler) use ($fn) {
232
+ return function ($request, array $options) use ($handler, $fn) {
233
+ return $handler($fn($request), $options);
234
+ };
235
+ };
236
+ }
237
+
238
+ /**
239
+ * Middleware that applies a map function to the resolved promise's
240
+ * response.
241
+ *
242
+ * @param callable $fn Function that accepts a ResponseInterface and
243
+ * returns a ResponseInterface.
244
+ * @return callable
245
+ */
246
+ public static function mapResponse(callable $fn)
247
+ {
248
+ return function (callable $handler) use ($fn) {
249
+ return function ($request, array $options) use ($handler, $fn) {
250
+ return $handler($request, $options)->then($fn);
251
+ };
252
+ };
253
+ }
254
+ }
vendor/guzzlehttp/guzzle/src/Pool.php ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp;
3
+
4
+ use GuzzleHttp\Promise\EachPromise;
5
+ use GuzzleHttp\Promise\PromiseInterface;
6
+ use GuzzleHttp\Promise\PromisorInterface;
7
+ use Psr\Http\Message\RequestInterface;
8
+
9
+ /**
10
+ * Sends an iterator of requests concurrently using a capped pool size.
11
+ *
12
+ * The pool will read from an iterator until it is cancelled or until the
13
+ * iterator is consumed. When a request is yielded, the request is sent after
14
+ * applying the "request_options" request options (if provided in the ctor).
15
+ *
16
+ * When a function is yielded by the iterator, the function is provided the
17
+ * "request_options" array that should be merged on top of any existing
18
+ * options, and the function MUST then return a wait-able promise.
19
+ */
20
+ class Pool implements PromisorInterface
21
+ {
22
+ /** @var EachPromise */
23
+ private $each;
24
+
25
+ /**
26
+ * @param ClientInterface $client Client used to send the requests.
27
+ * @param array|\Iterator $requests Requests or functions that return
28
+ * requests to send concurrently.
29
+ * @param array $config Associative array of options
30
+ * - concurrency: (int) Maximum number of requests to send concurrently
31
+ * - options: Array of request options to apply to each request.
32
+ * - fulfilled: (callable) Function to invoke when a request completes.
33
+ * - rejected: (callable) Function to invoke when a request is rejected.
34
+ */
35
+ public function __construct(
36
+ ClientInterface $client,
37
+ $requests,
38
+ array $config = []
39
+ ) {
40
+ // Backwards compatibility.
41
+ if (isset($config['pool_size'])) {
42
+ $config['concurrency'] = $config['pool_size'];
43
+ } elseif (!isset($config['concurrency'])) {
44
+ $config['concurrency'] = 25;
45
+ }
46
+
47
+ if (isset($config['options'])) {
48
+ $opts = $config['options'];
49
+ unset($config['options']);
50
+ } else {
51
+ $opts = [];
52
+ }
53
+
54
+ $iterable = \GuzzleHttp\Promise\iter_for($requests);
55
+ $requests = function () use ($iterable, $client, $opts) {
56
+ foreach ($iterable as $key => $rfn) {
57
+ if ($rfn instanceof RequestInterface) {
58
+ yield $key => $client->sendAsync($rfn, $opts);
59
+ } elseif (is_callable($rfn)) {
60
+ yield $key => $rfn($opts);
61
+ } else {
62
+ throw new \InvalidArgumentException('Each value yielded by '
63
+ . 'the iterator must be a Psr7\Http\Message\RequestInterface '
64
+ . 'or a callable that returns a promise that fulfills '
65
+ . 'with a Psr7\Message\Http\ResponseInterface object.');
66
+ }
67
+ }
68
+ };
69
+
70
+ $this->each = new EachPromise($requests(), $config);
71
+ }
72
+
73
+ /**
74
+ * Get promise
75
+ *
76
+ * @return PromiseInterface
77
+ */
78
+ public function promise()
79
+ {
80
+ return $this->each->promise();
81
+ }
82
+
83
+ /**
84
+ * Sends multiple requests concurrently and returns an array of responses
85
+ * and exceptions that uses the same ordering as the provided requests.
86
+ *
87
+ * IMPORTANT: This method keeps every request and response in memory, and
88
+ * as such, is NOT recommended when sending a large number or an
89
+ * indeterminate number of requests concurrently.
90
+ *
91
+ * @param ClientInterface $client Client used to send the requests
92
+ * @param array|\Iterator $requests Requests to send concurrently.
93
+ * @param array $options Passes through the options available in
94
+ * {@see GuzzleHttp\Pool::__construct}
95
+ *
96
+ * @return array Returns an array containing the response or an exception
97
+ * in the same order that the requests were sent.
98
+ * @throws \InvalidArgumentException if the event format is incorrect.
99
+ */
100
+ public static function batch(
101
+ ClientInterface $client,
102
+ $requests,
103
+ array $options = []
104
+ ) {
105
+ $res = [];
106
+ self::cmpCallback($options, 'fulfilled', $res);
107
+ self::cmpCallback($options, 'rejected', $res);
108
+ $pool = new static($client, $requests, $options);
109
+ $pool->promise()->wait();
110
+ ksort($res);
111
+
112
+ return $res;
113
+ }
114
+
115
+ /**
116
+ * Execute callback(s)
117
+ *
118
+ * @return void
119
+ */
120
+ private static function cmpCallback(array &$options, $name, array &$results)
121
+ {
122
+ if (!isset($options[$name])) {
123
+ $options[$name] = function ($v, $k) use (&$results) {
124
+ $results[$k] = $v;
125
+ };
126
+ } else {
127
+ $currentFn = $options[$name];
128
+ $options[$name] = function ($v, $k) use (&$results, $currentFn) {
129
+ $currentFn($v, $k);
130
+ $results[$k] = $v;
131
+ };
132
+ }
133
+ }
134
+ }
vendor/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php ADDED
@@ -0,0 +1,111 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp;
3
+
4
+ use GuzzleHttp\Promise\PromiseInterface;
5
+ use GuzzleHttp\Psr7;
6
+ use Psr\Http\Message\RequestInterface;
7
+
8
+ /**
9
+ * Prepares requests that contain a body, adding the Content-Length,
10
+ * Content-Type, and Expect headers.
11
+ */
12
+ class PrepareBodyMiddleware
13
+ {
14
+ /** @var callable */
15
+ private $nextHandler;
16
+
17
+ /**
18
+ * @param callable $nextHandler Next handler to invoke.
19
+ */
20
+ public function __construct(callable $nextHandler)
21
+ {
22
+ $this->nextHandler = $nextHandler;
23
+ }
24
+
25
+ /**
26
+ * @param RequestInterface $request
27
+ * @param array $options
28
+ *
29
+ * @return PromiseInterface
30
+ */
31
+ public function __invoke(RequestInterface $request, array $options)
32
+ {
33
+ $fn = $this->nextHandler;
34
+
35
+ // Don't do anything if the request has no body.
36
+ if ($request->getBody()->getSize() === 0) {
37
+ return $fn($request, $options);
38
+ }
39
+
40
+ $modify = [];
41
+
42
+ // Add a default content-type if possible.
43
+ if (!$request->hasHeader('Content-Type')) {
44
+ if ($uri = $request->getBody()->getMetadata('uri')) {
45
+ if ($type = Psr7\mimetype_from_filename($uri)) {
46
+ $modify['set_headers']['Content-Type'] = $type;
47
+ }
48
+ }
49
+ }
50
+
51
+ // Add a default content-length or transfer-encoding header.
52
+ if (!$request->hasHeader('Content-Length')
53
+ && !$request->hasHeader('Transfer-Encoding')
54
+ ) {
55
+ $size = $request->getBody()->getSize();
56
+ if ($size !== null) {
57
+ $modify['set_headers']['Content-Length'] = $size;
58
+ } else {
59
+ $modify['set_headers']['Transfer-Encoding'] = 'chunked';
60
+ }
61
+ }
62
+
63
+ // Add the expect header if needed.
64
+ $this->addExpectHeader($request, $options, $modify);
65
+
66
+ return $fn(Psr7\modify_request($request, $modify), $options);
67
+ }
68
+
69
+ /**
70
+ * Add expect header
71
+ *
72
+ * @return void
73
+ */
74
+ private function addExpectHeader(
75
+ RequestInterface $request,
76
+ array $options,
77
+ array &$modify
78
+ ) {
79
+ // Determine if the Expect header should be used
80
+ if ($request->hasHeader('Expect')) {
81
+ return;
82
+ }
83
+
84
+ $expect = isset($options['expect']) ? $options['expect'] : null;
85
+
86
+ // Return if disabled or if you're not using HTTP/1.1 or HTTP/2.0
87
+ if ($expect === false || $request->getProtocolVersion() < 1.1) {
88
+ return;
89
+ }
90
+
91
+ // The expect header is unconditionally enabled
92
+ if ($expect === true) {
93
+ $modify['set_headers']['Expect'] = '100-Continue';
94
+ return;
95
+ }
96
+
97
+ // By default, send the expect header when the payload is > 1mb
98
+ if ($expect === null) {
99
+ $expect = 1048576;
100
+ }
101
+
102
+ // Always add if the body cannot be rewound, the size cannot be
103
+ // determined, or the size is greater than the cutoff threshold
104
+ $body = $request->getBody();
105
+ $size = $body->getSize();
106
+
107
+ if ($size === null || $size >= (int) $expect || !$body->isSeekable()) {
108
+ $modify['set_headers']['Expect'] = '100-Continue';
109
+ }
110
+ }
111
+ }
vendor/guzzlehttp/guzzle/src/RedirectMiddleware.php ADDED
@@ -0,0 +1,255 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp;
3
+
4
+ use GuzzleHttp\Exception\BadResponseException;
5
+ use GuzzleHttp\Exception\TooManyRedirectsException;
6
+ use GuzzleHttp\Promise\PromiseInterface;
7
+ use GuzzleHttp\Psr7;
8
+ use Psr\Http\Message\RequestInterface;
9
+ use Psr\Http\Message\ResponseInterface;
10
+ use Psr\Http\Message\UriInterface;
11
+
12
+ /**
13
+ * Request redirect middleware.
14
+ *
15
+ * Apply this middleware like other middleware using
16
+ * {@see \GuzzleHttp\Middleware::redirect()}.
17
+ */
18
+ class RedirectMiddleware
19
+ {
20
+ const HISTORY_HEADER = 'X-Guzzle-Redirect-History';
21
+
22
+ const STATUS_HISTORY_HEADER = 'X-Guzzle-Redirect-Status-History';
23
+
24
+ public static $defaultSettings = [
25
+ 'max' => 5,
26
+ 'protocols' => ['http', 'https'],
27
+ 'strict' => false,
28
+ 'referer' => false,
29
+ 'track_redirects' => false,
30
+ ];
31
+
32
+ /** @var callable */
33
+ private $nextHandler;
34
+
35
+ /**
36
+ * @param callable $nextHandler Next handler to invoke.
37
+ */
38
+ public function __construct(callable $nextHandler)
39
+ {
40
+ $this->nextHandler = $nextHandler;
41
+ }
42
+
43
+ /**
44
+ * @param RequestInterface $request
45
+ * @param array $options
46
+ *
47
+ * @return PromiseInterface
48
+ */
49
+ public function __invoke(RequestInterface $request, array $options)
50
+ {
51
+ $fn = $this->nextHandler;
52
+
53
+ if (empty($options['allow_redirects'])) {
54
+ return $fn($request, $options);
55
+ }
56
+
57
+ if ($options['allow_redirects'] === true) {
58
+ $options['allow_redirects'] = self::$defaultSettings;
59
+ } elseif (!is_array($options['allow_redirects'])) {
60
+ throw new \InvalidArgumentException('allow_redirects must be true, false, or array');
61
+ } else {
62
+ // Merge the default settings with the provided settings
63
+ $options['allow_redirects'] += self::$defaultSettings;
64
+ }
65
+
66
+ if (empty($options['allow_redirects']['max'])) {
67
+ return $fn($request, $options);
68
+ }
69
+
70
+ return $fn($request, $options)
71
+ ->then(function (ResponseInterface $response) use ($request, $options) {
72
+ return $this->checkRedirect($request, $options, $response);
73
+ });
74
+ }
75
+
76
+ /**
77
+ * @param RequestInterface $request
78
+ * @param array $options
79
+ * @param ResponseInterface $response
80
+ *
81
+ * @return ResponseInterface|PromiseInterface
82
+ */
83
+ public function checkRedirect(
84
+ RequestInterface $request,
85
+ array $options,
86
+ ResponseInterface $response
87
+ ) {
88
+ if (substr($response->getStatusCode(), 0, 1) != '3'
89
+ || !$response->hasHeader('Location')
90
+ ) {
91
+ return $response;
92
+ }
93
+
94
+ $this->guardMax($request, $options);
95
+ $nextRequest = $this->modifyRequest($request, $options, $response);
96
+
97
+ if (isset($options['allow_redirects']['on_redirect'])) {
98
+ call_user_func(
99
+ $options['allow_redirects']['on_redirect'],
100
+ $request,
101
+ $response,
102
+ $nextRequest->getUri()
103
+ );
104
+ }
105
+
106
+ /** @var PromiseInterface|ResponseInterface $promise */
107
+ $promise = $this($nextRequest, $options);
108
+
109
+ // Add headers to be able to track history of redirects.
110
+ if (!empty($options['allow_redirects']['track_redirects'])) {
111
+ return $this->withTracking(
112
+ $promise,
113
+ (string) $nextRequest->getUri(),
114
+ $response->getStatusCode()
115
+ );
116
+ }
117
+
118
+ return $promise;
119
+ }
120
+
121
+ /**
122
+ * Enable tracking on promise.
123
+ *
124
+ * @return PromiseInterface
125
+ */
126
+ private function withTracking(PromiseInterface $promise, $uri, $statusCode)
127
+ {
128
+ return $promise->then(
129
+ function (ResponseInterface $response) use ($uri, $statusCode) {
130
+ // Note that we are pushing to the front of the list as this
131
+ // would be an earlier response than what is currently present
132
+ // in the history header.
133
+ $historyHeader = $response->getHeader(self::HISTORY_HEADER);
134
+ $statusHeader = $response->getHeader(self::STATUS_HISTORY_HEADER);
135
+ array_unshift($historyHeader, $uri);
136
+ array_unshift($statusHeader, $statusCode);
137
+ return $response->withHeader(self::HISTORY_HEADER, $historyHeader)
138
+ ->withHeader(self::STATUS_HISTORY_HEADER, $statusHeader);
139
+ }
140
+ );
141
+ }
142
+
143
+ /**
144
+ * Check for too many redirects
145
+ *
146
+ * @return void
147
+ *
148
+ * @throws TooManyRedirectsException Too many redirects.
149
+ */
150
+ private function guardMax(RequestInterface $request, array &$options)
151
+ {
152
+ $current = isset($options['__redirect_count'])
153
+ ? $options['__redirect_count']
154
+ : 0;
155
+ $options['__redirect_count'] = $current + 1;
156
+ $max = $options['allow_redirects']['max'];
157
+
158
+ if ($options['__redirect_count'] > $max) {
159
+ throw new TooManyRedirectsException(
160
+ "Will not follow more than {$max} redirects",
161
+ $request
162
+ );
163
+ }
164
+ }
165
+
166
+ /**
167
+ * @param RequestInterface $request
168
+ * @param array $options
169
+ * @param ResponseInterface $response
170
+ *
171
+ * @return RequestInterface
172
+ */
173
+ public function modifyRequest(
174
+ RequestInterface $request,
175
+ array $options,
176
+ ResponseInterface $response
177
+ ) {
178
+ // Request modifications to apply.
179
+ $modify = [];
180
+ $protocols = $options['allow_redirects']['protocols'];
181
+
182
+ // Use a GET request if this is an entity enclosing request and we are
183
+ // not forcing RFC compliance, but rather emulating what all browsers
184
+ // would do.
185
+ $statusCode = $response->getStatusCode();
186
+ if ($statusCode == 303 ||
187
+ ($statusCode <= 302 && !$options['allow_redirects']['strict'])
188
+ ) {
189
+ $modify['method'] = 'GET';
190
+ $modify['body'] = '';
191
+ }
192
+
193
+ $uri = $this->redirectUri($request, $response, $protocols);
194
+ if (isset($options['idn_conversion']) && ($options['idn_conversion'] !== false)) {
195
+ $idnOptions = ($options['idn_conversion'] === true) ? IDNA_DEFAULT : $options['idn_conversion'];
196
+ $uri = Utils::idnUriConvert($uri, $idnOptions);
197
+ }
198
+
199
+ $modify['uri'] = $uri;
200
+ Psr7\rewind_body($request);
201
+
202
+ // Add the Referer header if it is told to do so and only
203
+ // add the header if we are not redirecting from https to http.
204
+ if ($options['allow_redirects']['referer']
205
+ && $modify['uri']->getScheme() === $request->getUri()->getScheme()
206
+ ) {
207
+ $uri = $request->getUri()->withUserInfo('');
208
+ $modify['set_headers']['Referer'] = (string) $uri;
209
+ } else {
210
+ $modify['remove_headers'][] = 'Referer';
211
+ }
212
+
213
+ // Remove Authorization header if host is different.
214
+ if ($request->getUri()->getHost() !== $modify['uri']->getHost()) {
215
+ $modify['remove_headers'][] = 'Authorization';
216
+ }
217
+
218
+ return Psr7\modify_request($request, $modify);
219
+ }
220
+
221
+ /**
222
+ * Set the appropriate URL on the request based on the location header
223
+ *
224
+ * @param RequestInterface $request
225
+ * @param ResponseInterface $response
226
+ * @param array $protocols
227
+ *
228
+ * @return UriInterface
229
+ */
230
+ private function redirectUri(
231
+ RequestInterface $request,
232
+ ResponseInterface $response,
233
+ array $protocols
234
+ ) {
235
+ $location = Psr7\UriResolver::resolve(
236
+ $request->getUri(),
237
+ new Psr7\Uri($response->getHeaderLine('Location'))
238
+ );
239
+
240
+ // Ensure that the redirect URI is allowed based on the protocols.
241
+ if (!in_array($location->getScheme(), $protocols)) {
242
+ throw new BadResponseException(
243
+ sprintf(
244
+ 'Redirect URI, %s, does not use one of the allowed redirect protocols: %s',
245
+ $location,
246
+ implode(', ', $protocols)
247
+ ),
248
+ $request,
249
+ $response
250
+ );
251
+ }
252
+
253
+ return $location;
254
+ }
255
+ }
vendor/guzzlehttp/guzzle/src/RequestOptions.php ADDED
@@ -0,0 +1,263 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp;
3
+
4
+ /**
5
+ * This class contains a list of built-in Guzzle request options.
6
+ *
7
+ * More documentation for each option can be found at http://guzzlephp.org/.
8
+ *
9
+ * @link http://docs.guzzlephp.org/en/v6/request-options.html
10
+ */
11
+ final class RequestOptions
12
+ {
13
+ /**
14
+ * allow_redirects: (bool|array) Controls redirect behavior. Pass false
15
+ * to disable redirects, pass true to enable redirects, pass an
16
+ * associative to provide custom redirect settings. Defaults to "false".
17
+ * This option only works if your handler has the RedirectMiddleware. When
18
+ * passing an associative array, you can provide the following key value
19
+ * pairs:
20
+ *
21
+ * - max: (int, default=5) maximum number of allowed redirects.
22
+ * - strict: (bool, default=false) Set to true to use strict redirects
23
+ * meaning redirect POST requests with POST requests vs. doing what most
24
+ * browsers do which is redirect POST requests with GET requests
25
+ * - referer: (bool, default=false) Set to true to enable the Referer
26
+ * header.
27
+ * - protocols: (array, default=['http', 'https']) Allowed redirect
28
+ * protocols.
29
+ * - on_redirect: (callable) PHP callable that is invoked when a redirect
30
+ * is encountered. The callable is invoked with the request, the redirect
31
+ * response that was received, and the effective URI. Any return value
32
+ * from the on_redirect function is ignored.
33
+ */
34
+ const ALLOW_REDIRECTS = 'allow_redirects';
35
+
36
+ /**
37
+ * auth: (array) Pass an array of HTTP authentication parameters to use
38
+ * with the request. The array must contain the username in index [0],
39
+ * the password in index [1], and you can optionally provide a built-in
40
+ * authentication type in index [2]. Pass null to disable authentication
41
+ * for a request.
42
+ */
43
+ const AUTH = 'auth';
44
+
45
+ /**
46
+ * body: (resource|string|null|int|float|StreamInterface|callable|\Iterator)
47
+ * Body to send in the request.
48
+ */
49
+ const BODY = 'body';
50
+
51
+ /**
52
+ * cert: (string|array) Set to a string to specify the path to a file
53
+ * containing a PEM formatted SSL client side certificate. If a password
54
+ * is required, then set cert to an array containing the path to the PEM
55
+ * file in the first array element followed by the certificate password
56
+ * in the second array element.
57
+ */
58
+ const CERT = 'cert';
59
+
60
+ /**
61
+ * cookies: (bool|GuzzleHttp\Cookie\CookieJarInterface, default=false)
62
+ * Specifies whether or not cookies are used in a request or what cookie
63
+ * jar to use or what cookies to send. This option only works if your
64
+ * handler has the `cookie` middleware. Valid values are `false` and
65
+ * an instance of {@see GuzzleHttp\Cookie\CookieJarInterface}.
66
+ */
67
+ const COOKIES = 'cookies';
68
+
69
+ /**
70
+ * connect_timeout: (float, default=0) Float describing the number of
71
+ * seconds to wait while trying to connect to a server. Use 0 to wait
72
+ * indefinitely (the default behavior).
73
+ */
74
+ const CONNECT_TIMEOUT = 'connect_timeout';
75
+
76
+ /**
77
+ * debug: (bool|resource) Set to true or set to a PHP stream returned by
78
+ * fopen() enable debug output with the HTTP handler used to send a
79
+ * request.
80
+ */
81
+ const DEBUG = 'debug';
82
+
83
+ /**
84
+ * decode_content: (bool, default=true) Specify whether or not
85
+ * Content-Encoding responses (gzip, deflate, etc.) are automatically
86
+ * decoded.
87
+ */
88
+ const DECODE_CONTENT = 'decode_content';
89
+
90
+ /**
91
+ * delay: (int) The amount of time to delay before sending in milliseconds.
92
+ */
93
+ const DELAY = 'delay';
94
+
95
+ /**
96
+ * expect: (bool|integer) Controls the behavior of the
97
+ * "Expect: 100-Continue" header.
98
+ *
99
+ * Set to `true` to enable the "Expect: 100-Continue" header for all
100
+ * requests that sends a body. Set to `false` to disable the
101
+ * "Expect: 100-Continue" header for all requests. Set to a number so that
102
+ * the size of the payload must be greater than the number in order to send
103
+ * the Expect header. Setting to a number will send the Expect header for
104
+ * all requests in which the size of the payload cannot be determined or
105
+ * where the body is not rewindable.
106
+ *
107
+ * By default, Guzzle will add the "Expect: 100-Continue" header when the
108
+ * size of the body of a request is greater than 1 MB and a request is
109
+ * using HTTP/1.1.
110
+ */
111
+ const EXPECT = 'expect';
112
+
113
+ /**
114
+ * form_params: (array) Associative array of form field names to values
115
+ * where each value is a string or array of strings. Sets the Content-Type
116
+ * header to application/x-www-form-urlencoded when no Content-Type header
117
+ * is already present.
118
+ */
119
+ const FORM_PARAMS = 'form_params';
120
+
121
+ /**
122
+ * headers: (array) Associative array of HTTP headers. Each value MUST be
123
+ * a string or array of strings.
124
+ */
125
+ const HEADERS = 'headers';
126
+
127
+ /**
128
+ * http_errors: (bool, default=true) Set to false to disable exceptions
129
+ * when a non- successful HTTP response is received. By default,
130
+ * exceptions will be thrown for 4xx and 5xx responses. This option only
131
+ * works if your handler has the `httpErrors` middleware.
132
+ */
133
+ const HTTP_ERRORS = 'http_errors';
134
+
135
+ /**
136
+ * idn: (bool|int, default=true) A combination of IDNA_* constants for
137
+ * idn_to_ascii() PHP's function (see "options" parameter). Set to false to
138
+ * disable IDN support completely, or to true to use the default
139
+ * configuration (IDNA_DEFAULT constant).
140
+ */
141
+ const IDN_CONVERSION = 'idn_conversion';
142
+
143
+ /**
144
+ * json: (mixed) Adds JSON data to a request. The provided value is JSON
145
+ * encoded and a Content-Type header of application/json will be added to
146
+ * the request if no Content-Type header is already present.
147
+ */
148
+ const JSON = 'json';
149
+
150
+ /**
151
+ * multipart: (array) Array of associative arrays, each containing a
152
+ * required "name" key mapping to the form field, name, a required
153
+ * "contents" key mapping to a StreamInterface|resource|string, an
154
+ * optional "headers" associative array of custom headers, and an
155
+ * optional "filename" key mapping to a string to send as the filename in
156
+ * the part. If no "filename" key is present, then no "filename" attribute
157
+ * will be added to the part.
158
+ */
159
+ const MULTIPART = 'multipart';
160
+
161
+ /**
162
+ * on_headers: (callable) A callable that is invoked when the HTTP headers
163
+ * of the response have been received but the body has not yet begun to
164
+ * download.
165
+ */
166
+ const ON_HEADERS = 'on_headers';
167
+
168
+ /**
169
+ * on_stats: (callable) allows you to get access to transfer statistics of
170
+ * a request and access the lower level transfer details of the handler
171
+ * associated with your client. ``on_stats`` is a callable that is invoked
172
+ * when a handler has finished sending a request. The callback is invoked
173
+ * with transfer statistics about the request, the response received, or
174
+ * the error encountered. Included in the data is the total amount of time
175
+ * taken to send the request.
176
+ */
177
+ const ON_STATS = 'on_stats';
178
+
179
+ /**
180
+ * progress: (callable) Defines a function to invoke when transfer
181
+ * progress is made. The function accepts the following positional
182
+ * arguments: the total number of bytes expected to be downloaded, the
183
+ * number of bytes downloaded so far, the number of bytes expected to be
184
+ * uploaded, the number of bytes uploaded so far.
185
+ */
186
+ const PROGRESS = 'progress';
187
+
188
+ /**
189
+ * proxy: (string|array) Pass a string to specify an HTTP proxy, or an
190
+ * array to specify different proxies for different protocols (where the
191
+ * key is the protocol and the value is a proxy string).
192
+ */
193
+ const PROXY = 'proxy';
194
+
195
+ /**
196
+ * query: (array|string) Associative array of query string values to add
197
+ * to the request. This option uses PHP's http_build_query() to create
198
+ * the string representation. Pass a string value if you need more
199
+ * control than what this method provides
200
+ */
201
+ const QUERY = 'query';
202
+
203
+ /**
204
+ * sink: (resource|string|StreamInterface) Where the data of the
205
+ * response is written to. Defaults to a PHP temp stream. Providing a
206
+ * string will write data to a file by the given name.
207
+ */
208
+ const SINK = 'sink';
209
+
210
+ /**
211
+ * synchronous: (bool) Set to true to inform HTTP handlers that you intend
212
+ * on waiting on the response. This can be useful for optimizations. Note
213
+ * that a promise is still returned if you are using one of the async
214
+ * client methods.
215
+ */
216
+ const SYNCHRONOUS = 'synchronous';
217
+
218
+ /**
219
+ * ssl_key: (array|string) Specify the path to a file containing a private
220
+ * SSL key in PEM format. If a password is required, then set to an array
221
+ * containing the path to the SSL key in the first array element followed
222
+ * by the password required for the certificate in the second element.
223
+ */
224
+ const SSL_KEY = 'ssl_key';
225
+
226
+ /**
227
+ * stream: Set to true to attempt to stream a response rather than
228
+ * download it all up-front.
229
+ */
230
+ const STREAM = 'stream';
231
+
232
+ /**
233
+ * verify: (bool|string, default=true) Describes the SSL certificate
234
+ * verification behavior of a request. Set to true to enable SSL
235
+ * certificate verification using the system CA bundle when available
236
+ * (the default). Set to false to disable certificate verification (this
237
+ * is insecure!). Set to a string to provide the path to a CA bundle on
238
+ * disk to enable verification using a custom certificate.
239
+ */
240
+ const VERIFY = 'verify';
241
+
242
+ /**
243
+ * timeout: (float, default=0) Float describing the timeout of the
244
+ * request in seconds. Use 0 to wait indefinitely (the default behavior).
245
+ */
246
+ const TIMEOUT = 'timeout';
247
+
248
+ /**
249
+ * read_timeout: (float, default=default_socket_timeout ini setting) Float describing
250
+ * the body read timeout, for stream requests.
251
+ */
252
+ const READ_TIMEOUT = 'read_timeout';
253
+
254
+ /**
255
+ * version: (float) Specifies the HTTP protocol version to attempt to use.
256
+ */
257
+ const VERSION = 'version';
258
+
259
+ /**
260
+ * force_ip_resolve: (bool) Force client to use only ipv4 or ipv6 protocol
261
+ */
262
+ const FORCE_IP_RESOLVE = 'force_ip_resolve';
263
+ }
vendor/guzzlehttp/guzzle/src/RetryMiddleware.php ADDED
@@ -0,0 +1,128 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp;
3
+
4
+ use GuzzleHttp\Promise\PromiseInterface;
5
+ use GuzzleHttp\Promise\RejectedPromise;
6
+ use GuzzleHttp\Psr7;
7
+ use Psr\Http\Message\RequestInterface;
8
+ use Psr\Http\Message\ResponseInterface;
9
+
10
+ /**
11
+ * Middleware that retries requests based on the boolean result of
12
+ * invoking the provided "decider" function.
13
+ */
14
+ class RetryMiddleware
15
+ {
16
+ /** @var callable */
17
+ private $nextHandler;
18
+
19
+ /** @var callable */
20
+ private $decider;
21
+
22
+ /** @var callable */
23
+ private $delay;
24
+
25
+ /**
26
+ * @param callable $decider Function that accepts the number of retries,
27
+ * a request, [response], and [exception] and
28
+ * returns true if the request is to be
29
+ * retried.
30
+ * @param callable $nextHandler Next handler to invoke.
31
+ * @param callable $delay Function that accepts the number of retries
32
+ * and [response] and returns the number of
33
+ * milliseconds to delay.
34
+ */
35
+ public function __construct(
36
+ callable $decider,
37
+ callable $nextHandler,
38
+ callable $delay = null
39
+ ) {
40
+ $this->decider = $decider;
41
+ $this->nextHandler = $nextHandler;
42
+ $this->delay = $delay ?: __CLASS__ . '::exponentialDelay';
43
+ }
44
+
45
+ /**
46
+ * Default exponential backoff delay function.
47
+ *
48
+ * @param int $retries
49
+ *
50
+ * @return int milliseconds.
51
+ */
52
+ public static function exponentialDelay($retries)
53
+ {
54
+ return (int) pow(2, $retries - 1) * 1000;
55
+ }
56
+
57
+ /**
58
+ * @param RequestInterface $request
59
+ * @param array $options
60
+ *
61
+ * @return PromiseInterface
62
+ */
63
+ public function __invoke(RequestInterface $request, array $options)
64
+ {
65
+ if (!isset($options['retries'])) {
66
+ $options['retries'] = 0;
67
+ }
68
+
69
+ $fn = $this->nextHandler;
70
+ return $fn($request, $options)
71
+ ->then(
72
+ $this->onFulfilled($request, $options),
73
+ $this->onRejected($request, $options)
74
+ );
75
+ }
76
+
77
+ /**
78
+ * Execute fulfilled closure
79
+ *
80
+ * @return mixed
81
+ */
82
+ private function onFulfilled(RequestInterface $req, array $options)
83
+ {
84
+ return function ($value) use ($req, $options) {
85
+ if (!call_user_func(
86
+ $this->decider,
87
+ $options['retries'],
88
+ $req,
89
+ $value,
90
+ null
91
+ )) {
92
+ return $value;
93
+ }
94
+ return $this->doRetry($req, $options, $value);
95
+ };
96
+ }
97
+
98
+ /**
99
+ * Execute rejected closure
100
+ *
101
+ * @return callable
102
+ */
103
+ private function onRejected(RequestInterface $req, array $options)
104
+ {
105
+ return function ($reason) use ($req, $options) {
106
+ if (!call_user_func(
107
+ $this->decider,
108
+ $options['retries'],
109
+ $req,
110
+ null,
111
+ $reason
112
+ )) {
113
+ return \GuzzleHttp\Promise\rejection_for($reason);
114
+ }
115
+ return $this->doRetry($req, $options);
116
+ };
117
+ }
118
+
119
+ /**
120
+ * @return self
121
+ */
122
+ private function doRetry(RequestInterface $request, array $options, ResponseInterface $response = null)
123
+ {
124
+ $options['delay'] = call_user_func($this->delay, ++$options['retries'], $response);
125
+
126
+ return $this($request, $options);
127
+ }
128
+ }
vendor/guzzlehttp/guzzle/src/TransferStats.php ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp;
3
+
4
+ use Psr\Http\Message\RequestInterface;
5
+ use Psr\Http\Message\ResponseInterface;
6
+ use Psr\Http\Message\UriInterface;
7
+
8
+ /**
9
+ * Represents data at the point after it was transferred either successfully
10
+ * or after a network error.
11
+ */
12
+ final class TransferStats
13
+ {
14
+ private $request;
15
+ private $response;
16
+ private $transferTime;
17
+ private $handlerStats;
18
+ private $handlerErrorData;
19
+
20
+ /**
21
+ * @param RequestInterface $request Request that was sent.
22
+ * @param ResponseInterface|null $response Response received (if any)
23
+ * @param float|null $transferTime Total handler transfer time.
24
+ * @param mixed $handlerErrorData Handler error data.
25
+ * @param array $handlerStats Handler specific stats.
26
+ */
27
+ public function __construct(
28
+ RequestInterface $request,
29
+ ResponseInterface $response = null,
30
+ $transferTime = null,
31
+ $handlerErrorData = null,
32
+ $handlerStats = []
33
+ ) {
34
+ $this->request = $request;
35
+ $this->response = $response;
36
+ $this->transferTime = $transferTime;
37
+ $this->handlerErrorData = $handlerErrorData;
38
+ $this->handlerStats = $handlerStats;
39
+ }
40
+
41
+ /**
42
+ * @return RequestInterface
43
+ */
44
+ public function getRequest()
45
+ {
46
+ return $this->request;
47
+ }
48
+
49
+ /**
50
+ * Returns the response that was received (if any).
51
+ *
52
+ * @return ResponseInterface|null
53
+ */
54
+ public function getResponse()
55
+ {
56
+ return $this->response;
57
+ }
58
+
59
+ /**
60
+ * Returns true if a response was received.
61
+ *
62
+ * @return bool
63
+ */
64
+ public function hasResponse()
65
+ {
66
+ return $this->response !== null;
67
+ }
68
+
69
+ /**
70
+ * Gets handler specific error data.
71
+ *
72
+ * This might be an exception, a integer representing an error code, or
73
+ * anything else. Relying on this value assumes that you know what handler
74
+ * you are using.
75
+ *
76
+ * @return mixed
77
+ */
78
+ public function getHandlerErrorData()
79
+ {
80
+ return $this->handlerErrorData;
81
+ }
82
+
83
+ /**
84
+ * Get the effective URI the request was sent to.
85
+ *
86
+ * @return UriInterface
87
+ */
88
+ public function getEffectiveUri()
89
+ {
90
+ return $this->request->getUri();
91
+ }
92
+
93
+ /**
94
+ * Get the estimated time the request was being transferred by the handler.
95
+ *
96
+ * @return float|null Time in seconds.
97
+ */
98
+ public function getTransferTime()
99
+ {
100
+ return $this->transferTime;
101
+ }
102
+
103
+ /**
104
+ * Gets an array of all of the handler specific transfer data.
105
+ *
106
+ * @return array
107
+ */
108
+ public function getHandlerStats()
109
+ {
110
+ return $this->handlerStats;
111
+ }
112
+
113
+ /**
114
+ * Get a specific handler statistic from the handler by name.
115
+ *
116
+ * @param string $stat Handler specific transfer stat to retrieve.
117
+ *
118
+ * @return mixed|null
119
+ */
120
+ public function getHandlerStat($stat)
121
+ {
122
+ return isset($this->handlerStats[$stat])
123
+ ? $this->handlerStats[$stat]
124
+ : null;
125
+ }
126
+ }
vendor/guzzlehttp/guzzle/src/UriTemplate.php ADDED
@@ -0,0 +1,237 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp;
3
+
4
+ /**
5
+ * Expands URI templates. Userland implementation of PECL uri_template.
6
+ *
7
+ * @link http://tools.ietf.org/html/rfc6570
8
+ */
9
+ class UriTemplate
10
+ {
11
+ /** @var string URI template */
12
+ private $template;
13
+
14
+ /** @var array Variables to use in the template expansion */
15
+ private $variables;
16
+
17
+ /** @var array Hash for quick operator lookups */
18
+ private static $operatorHash = [
19
+ '' => ['prefix' => '', 'joiner' => ',', 'query' => false],
20
+ '+' => ['prefix' => '', 'joiner' => ',', 'query' => false],
21
+ '#' => ['prefix' => '#', 'joiner' => ',', 'query' => false],
22
+ '.' => ['prefix' => '.', 'joiner' => '.', 'query' => false],
23
+ '/' => ['prefix' => '/', 'joiner' => '/', 'query' => false],
24
+ ';' => ['prefix' => ';', 'joiner' => ';', 'query' => true],
25
+ '?' => ['prefix' => '?', 'joiner' => '&', 'query' => true],
26
+ '&' => ['prefix' => '&', 'joiner' => '&', 'query' => true]
27
+ ];
28
+
29
+ /** @var array Delimiters */
30
+ private static $delims = [':', '/', '?', '#', '[', ']', '@', '!', '$',
31
+ '&', '\'', '(', ')', '*', '+', ',', ';', '='];
32
+
33
+ /** @var array Percent encoded delimiters */
34
+ private static $delimsPct = ['%3A', '%2F', '%3F', '%23', '%5B', '%5D',
35
+ '%40', '%21', '%24', '%26', '%27', '%28', '%29', '%2A', '%2B', '%2C',
36
+ '%3B', '%3D'];
37
+
38
+ public function expand($template, array $variables)
39
+ {
40
+ if (false === strpos($template, '{')) {
41
+ return $template;
42
+ }
43
+
44
+ $this->template = $template;
45
+ $this->variables = $variables;
46
+
47
+ return preg_replace_callback(
48
+ '/\{([^\}]+)\}/',
49
+ [$this, 'expandMatch'],
50
+ $this->template
51
+ );
52
+ }
53
+
54
+ /**
55
+ * Parse an expression into parts
56
+ *
57
+ * @param string $expression Expression to parse
58
+ *
59
+ * @return array Returns an associative array of parts
60
+ */
61
+ private function parseExpression($expression)
62
+ {
63
+ $result = [];
64
+
65
+ if (isset(self::$operatorHash[$expression[0]])) {
66
+ $result['operator'] = $expression[0];
67
+ $expression = substr($expression, 1);
68
+ } else {
69
+ $result['operator'] = '';
70
+ }
71
+
72
+ foreach (explode(',', $expression) as $value) {
73
+ $value = trim($value);
74
+ $varspec = [];
75
+ if ($colonPos = strpos($value, ':')) {
76
+ $varspec['value'] = substr($value, 0, $colonPos);
77
+ $varspec['modifier'] = ':';
78
+ $varspec['position'] = (int) substr($value, $colonPos + 1);
79
+ } elseif (substr($value, -1) === '*') {
80
+ $varspec['modifier'] = '*';
81
+ $varspec['value'] = substr($value, 0, -1);
82
+ } else {
83
+ $varspec['value'] = (string) $value;
84
+ $varspec['modifier'] = '';
85
+ }
86
+ $result['values'][] = $varspec;
87
+ }
88
+
89
+ return $result;
90
+ }
91
+
92
+ /**
93
+ * Process an expansion
94
+ *
95
+ * @param array $matches Matches met in the preg_replace_callback
96
+ *
97
+ * @return string Returns the replacement string
98
+ */
99
+ private function expandMatch(array $matches)
100
+ {
101
+ static $rfc1738to3986 = ['+' => '%20', '%7e' => '~'];
102
+
103
+ $replacements = [];
104
+ $parsed = self::parseExpression($matches[1]);
105
+ $prefix = self::$operatorHash[$parsed['operator']]['prefix'];
106
+ $joiner = self::$operatorHash[$parsed['operator']]['joiner'];
107
+ $useQuery = self::$operatorHash[$parsed['operator']]['query'];
108
+
109
+ foreach ($parsed['values'] as $value) {
110
+ if (!isset($this->variables[$value['value']])) {
111
+ continue;
112
+ }
113
+
114
+ $variable = $this->variables[$value['value']];
115
+ $actuallyUseQuery = $useQuery;
116
+ $expanded = '';
117
+
118
+ if (is_array($variable)) {
119
+ $isAssoc = $this->isAssoc($variable);
120
+ $kvp = [];
121
+ foreach ($variable as $key => $var) {
122
+ if ($isAssoc) {
123
+ $key = rawurlencode($key);
124
+ $isNestedArray = is_array($var);
125
+ } else {
126
+ $isNestedArray = false;
127
+ }
128
+
129
+ if (!$isNestedArray) {
130
+ $var = rawurlencode($var);
131
+ if ($parsed['operator'] === '+' ||
132
+ $parsed['operator'] === '#'
133
+ ) {
134
+ $var = $this->decodeReserved($var);
135
+ }
136
+ }
137
+
138
+ if ($value['modifier'] === '*') {
139
+ if ($isAssoc) {
140
+ if ($isNestedArray) {
141
+ // Nested arrays must allow for deeply nested
142
+ // structures.
143
+ $var = strtr(
144
+ http_build_query([$key => $var]),
145
+ $rfc1738to3986
146
+ );
147
+ } else {
148
+ $var = $key . '=' . $var;
149
+ }
150
+ } elseif ($key > 0 && $actuallyUseQuery) {
151
+ $var = $value['value'] . '=' . $var;
152
+ }
153
+ }
154
+
155
+ $kvp[$key] = $var;
156
+ }
157
+
158
+ if (empty($variable)) {
159
+ $actuallyUseQuery = false;
160
+ } elseif ($value['modifier'] === '*') {
161
+ $expanded = implode($joiner, $kvp);
162
+ if ($isAssoc) {
163
+ // Don't prepend the value name when using the explode
164
+ // modifier with an associative array.
165
+ $actuallyUseQuery = false;
166
+ }
167
+ } else {
168
+ if ($isAssoc) {
169
+ // When an associative array is encountered and the
170
+ // explode modifier is not set, then the result must be
171
+ // a comma separated list of keys followed by their
172
+ // respective values.
173
+ foreach ($kvp as $k => &$v) {
174
+ $v = $k . ',' . $v;
175
+ }
176
+ }
177
+ $expanded = implode(',', $kvp);
178
+ }
179
+ } else {
180
+ if ($value['modifier'] === ':') {
181
+ $variable = substr($variable, 0, $value['position']);
182
+ }
183
+ $expanded = rawurlencode($variable);
184
+ if ($parsed['operator'] === '+' || $parsed['operator'] === '#') {
185
+ $expanded = $this->decodeReserved($expanded);
186
+ }
187
+ }
188
+
189
+ if ($actuallyUseQuery) {
190
+ if (!$expanded && $joiner !== '&') {
191
+ $expanded = $value['value'];
192
+ } else {
193
+ $expanded = $value['value'] . '=' . $expanded;
194
+ }
195
+ }
196
+
197
+ $replacements[] = $expanded;
198
+ }
199
+
200
+ $ret = implode($joiner, $replacements);
201
+ if ($ret && $prefix) {
202
+ return $prefix . $ret;
203
+ }
204
+
205
+ return $ret;
206
+ }
207
+
208
+ /**
209
+ * Determines if an array is associative.
210
+ *
211
+ * This makes the assumption that input arrays are sequences or hashes.
212
+ * This assumption is a tradeoff for accuracy in favor of speed, but it
213
+ * should work in almost every case where input is supplied for a URI
214
+ * template.
215
+ *
216
+ * @param array $array Array to check
217
+ *
218
+ * @return bool
219
+ */
220
+ private function isAssoc(array $array)
221
+ {
222
+ return $array && array_keys($array)[0] !== 0;
223
+ }
224
+
225
+ /**
226
+ * Removes percent encoding on reserved characters (used with + and #
227
+ * modifiers).
228
+ *
229
+ * @param string $string String to fix
230
+ *
231
+ * @return string
232
+ */
233
+ private function decodeReserved($string)
234
+ {
235
+ return str_replace(self::$delimsPct, self::$delims, $string);
236
+ }
237
+ }
vendor/guzzlehttp/guzzle/src/Utils.php ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp;
3
+
4
+ use GuzzleHttp\Exception\InvalidArgumentException;
5
+ use Psr\Http\Message\UriInterface;
6
+ use Symfony\Polyfill\Intl\Idn\Idn;
7
+
8
+ final class Utils
9
+ {
10
+ /**
11
+ * Wrapper for the hrtime() or microtime() functions
12
+ * (depending on the PHP version, one of the two is used)
13
+ *
14
+ * @return float|mixed UNIX timestamp
15
+ *
16
+ * @internal
17
+ */
18
+ public static function currentTime()
19
+ {
20
+ return function_exists('hrtime') ? hrtime(true) / 1e9 : microtime(true);
21
+ }
22
+
23
+ /**
24
+ * @param int $options
25
+ *
26
+ * @return UriInterface
27
+ * @throws InvalidArgumentException
28
+ *
29
+ * @internal
30
+ */
31
+ public static function idnUriConvert(UriInterface $uri, $options = 0)
32
+ {
33
+ if ($uri->getHost()) {
34
+ $asciiHost = self::idnToAsci($uri->getHost(), $options, $info);
35
+ if ($asciiHost === false) {
36
+ $errorBitSet = isset($info['errors']) ? $info['errors'] : 0;
37
+
38
+ $errorConstants = array_filter(array_keys(get_defined_constants()), function ($name) {
39
+ return substr($name, 0, 11) === 'IDNA_ERROR_';
40
+ });
41
+
42
+ $errors = [];
43
+ foreach ($errorConstants as $errorConstant) {
44
+ if ($errorBitSet & constant($errorConstant)) {
45
+ $errors[] = $errorConstant;
46
+ }
47
+ }
48
+
49
+ $errorMessage = 'IDN conversion failed';
50
+ if ($errors) {
51
+ $errorMessage .= ' (errors: ' . implode(', ', $errors) . ')';
52
+ }
53
+
54
+ throw new InvalidArgumentException($errorMessage);
55
+ } else {
56
+ if ($uri->getHost() !== $asciiHost) {
57
+ // Replace URI only if the ASCII version is different
58
+ $uri = $uri->withHost($asciiHost);
59
+ }
60
+ }
61
+ }
62
+
63
+ return $uri;
64
+ }
65
+
66
+ /**
67
+ * @param string $domain
68
+ * @param int $options
69
+ * @param array $info
70
+ *
71
+ * @return string|false
72
+ */
73
+ private static function idnToAsci($domain, $options, &$info = [])
74
+ {
75
+ if (\preg_match('%^[ -~]+$%', $domain) === 1) {
76
+ return $domain;
77
+ }
78
+
79
+ if (\extension_loaded('intl') && defined('INTL_IDNA_VARIANT_UTS46')) {
80
+ return \idn_to_ascii($domain, $options, INTL_IDNA_VARIANT_UTS46, $info);
81
+ }
82
+
83
+ /*
84
+ * The Idn class is marked as @internal. Verify that class and method exists.
85
+ */
86
+ if (method_exists(Idn::class, 'idn_to_ascii')) {
87
+ return Idn::idn_to_ascii($domain, $options, Idn::INTL_IDNA_VARIANT_UTS46, $info);
88
+ }
89
+
90
+ throw new \RuntimeException('ext-intl or symfony/polyfill-intl-idn not loaded or too old');
91
+ }
92
+ }
vendor/guzzlehttp/guzzle/src/functions.php ADDED
@@ -0,0 +1,334 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ namespace GuzzleHttp;
3
+
4
+ use GuzzleHttp\Handler\CurlHandler;
5
+ use GuzzleHttp\Handler\CurlMultiHandler;
6
+ use GuzzleHttp\Handler\Proxy;
7
+ use GuzzleHttp\Handler\StreamHandler;
8
+
9
+ /**
10
+ * Expands a URI template
11
+ *
12
+ * @param string $template URI template
13
+ * @param array $variables Template variables
14
+ *
15
+ * @return string
16
+ */
17
+ function uri_template($template, array $variables)
18
+ {
19
+ if (extension_loaded('uri_template')) {
20
+ // @codeCoverageIgnoreStart
21
+ return \uri_template($template, $variables);
22
+ // @codeCoverageIgnoreEnd
23
+ }
24
+
25
+ static $uriTemplate;
26
+ if (!$uriTemplate) {
27
+ $uriTemplate = new UriTemplate();
28
+ }
29
+
30
+ return $uriTemplate->expand($template, $variables);
31
+ }
32
+
33
+ /**
34
+ * Debug function used to describe the provided value type and class.
35
+ *
36
+ * @param mixed $input
37
+ *
38
+ * @return string Returns a string containing the type of the variable and
39
+ * if a class is provided, the class name.
40
+ */
41
+ function describe_type($input)
42
+ {
43
+ switch (gettype($input)) {
44
+ case 'object':
45
+ return 'object(' . get_class($input) . ')';
46
+ case 'array':
47
+ return 'array(' . count($input) . ')';
48
+ default:
49
+ ob_start();
50
+ var_dump($input);
51
+ // normalize float vs double
52
+ return str_replace('double(', 'float(', rtrim(ob_get_clean()));
53
+ }
54
+ }
55
+
56
+ /**
57
+ * Parses an array of header lines into an associative array of headers.
58
+ *
59
+ * @param iterable $lines Header lines array of strings in the following
60
+ * format: "Name: Value"
61
+ * @return array
62
+ */
63
+ function headers_from_lines($lines)
64
+ {
65
+ $headers = [];
66
+
67
+ foreach ($lines as $line) {
68
+ $parts = explode(':', $line, 2);
69
+ $headers[trim($parts[0])][] = isset($parts[1])
70
+ ? trim($parts[1])
71
+ : null;
72
+ }
73
+
74
+ return $headers;
75
+ }
76
+
77
+ /**
78
+ * Returns a debug stream based on the provided variable.
79
+ *
80
+ * @param mixed $value Optional value
81
+ *
82
+ * @return resource
83
+ */
84
+ function debug_resource($value = null)
85
+ {
86
+ if (is_resource($value)) {
87
+ return $value;
88
+ } elseif (defined('STDOUT')) {
89
+ return STDOUT;
90
+ }
91
+
92
+ return fopen('php://output', 'w');
93
+ }
94
+
95
+ /**
96
+ * Chooses and creates a default handler to use based on the environment.
97
+ *
98
+ * The returned handler is not wrapped by any default middlewares.
99
+ *
100
+ * @return callable Returns the best handler for the given system.
101
+ * @throws \RuntimeException if no viable Handler is available.
102
+ */
103
+ function choose_handler()
104
+ {
105
+ $handler = null;
106
+ if (function_exists('curl_multi_exec') && function_exists('curl_exec')) {
107
+ $handler = Proxy::wrapSync(new CurlMultiHandler(), new CurlHandler());
108
+ } elseif (function_exists('curl_exec')) {
109
+ $handler = new CurlHandler();
110
+ } elseif (function_exists('curl_multi_exec')) {
111
+ $handler = new CurlMultiHandler();
112
+ }
113
+
114
+ if (ini_get('allow_url_fopen')) {
115
+ $handler = $handler
116
+ ? Proxy::wrapStreaming($handler, new StreamHandler())
117
+ : new StreamHandler();
118
+ } elseif (!$handler) {
119
+ throw new \RuntimeException('GuzzleHttp requires cURL, the '
120
+ . 'allow_url_fopen ini setting, or a custom HTTP handler.');
121
+ }
122
+
123
+ return $handler;
124
+ }
125
+
126
+ /**
127
+ * Get the default User-Agent string to use with Guzzle
128
+ *
129
+ * @return string
130
+ */
131
+ function default_user_agent()
132
+ {
133
+ static $defaultAgent = '';
134
+
135
+ if (!$defaultAgent) {
136
+ $defaultAgent = 'GuzzleHttp/' . Client::VERSION;
137
+ if (extension_loaded('curl') && function_exists('curl_version')) {
138
+ $defaultAgent .= ' curl/' . \curl_version()['version'];
139
+ }
140
+ $defaultAgent .= ' PHP/' . PHP_VERSION;
141
+ }
142
+
143
+ return $defaultAgent;
144
+ }
145
+
146
+ /**
147
+ * Returns the default cacert bundle for the current system.
148
+ *
149
+ * First, the openssl.cafile and curl.cainfo php.ini settings are checked.
150
+ * If those settings are not configured, then the common locations for
151
+ * bundles found on Red Hat, CentOS, Fedora, Ubuntu, Debian, FreeBSD, OS X
152
+ * and Windows are checked. If any of these file locations are found on
153
+ * disk, they will be utilized.
154
+ *
155
+ * Note: the result of this function is cached for subsequent calls.
156
+ *
157
+ * @return string
158
+ * @throws \RuntimeException if no bundle can be found.
159
+ */
160
+ function default_ca_bundle()
161
+ {
162
+ static $cached = null;
163
+ static $cafiles = [
164
+ // Red Hat, CentOS, Fedora (provided by the ca-certificates package)
165
+ '/etc/pki/tls/certs/ca-bundle.crt',
166
+ // Ubuntu, Debian (provided by the ca-certificates package)
167
+ '/etc/ssl/certs/ca-certificates.crt',
168
+ // FreeBSD (provided by the ca_root_nss package)
169
+ '/usr/local/share/certs/ca-root-nss.crt',
170
+ // SLES 12 (provided by the ca-certificates package)
171
+ '/var/lib/ca-certificates/ca-bundle.pem',
172
+ // OS X provided by homebrew (using the default path)
173
+ '/usr/local/etc/openssl/cert.pem',
174
+ // Google app engine
175
+ '/etc/ca-certificates.crt',
176
+ // Windows?
177
+ 'C:\\windows\\system32\\curl-ca-bundle.crt',
178
+ 'C:\\windows\\curl-ca-bundle.crt',
179
+ ];
180
+
181
+ if ($cached) {
182
+ return $cached;
183
+ }
184
+
185
+ if ($ca = ini_get('openssl.cafile')) {
186
+ return $cached = $ca;
187
+ }
188
+
189
+ if ($ca = ini_get('curl.cainfo')) {
190
+ return $cached = $ca;
191
+ }
192
+
193
+ foreach ($cafiles as $filename) {
194
+ if (file_exists($filename)) {
195
+ return $cached = $filename;
196
+ }
197
+ }
198
+
199
+ throw new \RuntimeException(
200
+ <<< EOT
201
+ No system CA bundle could be found in any of the the common system locations.
202
+ PHP versions earlier than 5.6 are not properly configured to use the system's
203
+ CA bundle by default. In order to verify peer certificates, you will need to
204
+ supply the path on disk to a certificate bundle to the 'verify' request
205
+ option: http://docs.guzzlephp.org/en/latest/clients.html#verify. If you do not
206
+ need a specific certificate bundle, then Mozilla provides a commonly used CA
207
+ bundle which can be downloaded here (provided by the maintainer of cURL):
208
+ https://raw.githubusercontent.com/bagder/ca-bundle/master/ca-bundle.crt. Once
209
+ you have a CA bundle available on disk, you can set the 'openssl.cafile' PHP
210
+ ini setting to point to the path to the file, allowing you to omit the 'verify'
211
+ request option. See http://curl.haxx.se/docs/sslcerts.html for more
212
+ information.
213
+ EOT
214
+ );
215
+ }
216
+
217
+ /**
218
+ * Creates an associative array of lowercase header names to the actual
219
+ * header casing.
220
+ *
221
+ * @param array $headers
222
+ *
223
+ * @return array
224
+ */
225
+ function normalize_header_keys(array $headers)
226
+ {
227
+ $result = [];
228
+ foreach (array_keys($headers) as $key) {
229
+ $result[strtolower($key)] = $key;
230
+ }
231
+
232
+ return $result;
233
+ }
234
+
235
+ /**
236
+ * Returns true if the provided host matches any of the no proxy areas.
237
+ *
238
+ * This method will strip a port from the host if it is present. Each pattern
239
+ * can be matched with an exact match (e.g., "foo.com" == "foo.com") or a
240
+ * partial match: (e.g., "foo.com" == "baz.foo.com" and ".foo.com" ==
241
+ * "baz.foo.com", but ".foo.com" != "foo.com").
242
+ *
243
+ * Areas are matched in the following cases:
244
+ * 1. "*" (without quotes) always matches any hosts.
245
+ * 2. An exact match.
246
+ * 3. The area starts with "." and the area is the last part of the host. e.g.
247
+ * '.mit.edu' will match any host that ends with '.mit.edu'.
248
+ *
249
+ * @param string $host Host to check against the patterns.
250
+ * @param array $noProxyArray An array of host patterns.
251
+ *
252
+ * @return bool
253
+ */
254
+ function is_host_in_noproxy($host, array $noProxyArray)
255
+ {
256
+ if (strlen($host) === 0) {
257
+ throw new \InvalidArgumentException('Empty host provided');
258
+ }
259
+
260
+ // Strip port if present.
261
+ if (strpos($host, ':')) {
262
+ $host = explode($host, ':', 2)[0];
263
+ }
264
+
265
+ foreach ($noProxyArray as $area) {
266
+ // Always match on wildcards.
267
+ if ($area === '*') {
268
+ return true;
269
+ } elseif (empty($area)) {
270
+ // Don't match on empty values.
271
+ continue;
272
+ } elseif ($area === $host) {
273
+ // Exact matches.
274
+ return true;
275
+ } else {
276
+ // Special match if the area when prefixed with ".". Remove any
277
+ // existing leading "." and add a new leading ".".
278
+ $area = '.' . ltrim($area, '.');
279
+ if (substr($host, -(strlen($area))) === $area) {
280
+ return true;
281
+ }
282
+ }
283
+ }
284
+
285
+ return false;
286
+ }
287
+
288
+ /**
289
+ * Wrapper for json_decode that throws when an error occurs.
290
+ *
291
+ * @param string $json JSON data to parse
292
+ * @param bool $assoc When true, returned objects will be converted
293
+ * into associative arrays.
294
+ * @param int $depth User specified recursion depth.
295
+ * @param int $options Bitmask of JSON decode options.
296
+ *
297
+ * @return mixed
298
+ * @throws Exception\InvalidArgumentException if the JSON cannot be decoded.
299
+ * @link http://www.php.net/manual/en/function.json-decode.php
300
+ */
301
+ function json_decode($json, $assoc = false, $depth = 512, $options = 0)
302
+ {
303
+ $data = \json_decode($json, $assoc, $depth, $options);
304
+ if (JSON_ERROR_NONE !== json_last_error()) {
305
+ throw new Exception\InvalidArgumentException(
306
+ 'json_decode error: ' . json_last_error_msg()
307
+ );
308
+ }
309
+
310
+ return $data;
311
+ }
312
+
313
+ /**
314
+ * Wrapper for JSON encoding that throws when an error occurs.
315
+ *
316
+ * @param mixed $value The value being encoded
317
+ * @param int $options JSON encode option bitmask
318
+ * @param int $depth Set the maximum depth. Must be greater than zero.
319
+ *
320
+ * @return string
321
+ * @throws Exception\InvalidArgumentException if the JSON cannot be encoded.
322
+ * @link http://www.php.net/manual/en/function.json-encode.php
323
+ */
324
+ function json_encode($value, $options = 0, $depth = 512)
325
+ {
326
+ $json = \json_encode($value, $options, $depth);
327
+ if (JSON_ERROR_NONE !== json_last_error()) {
328
+ throw new Exception\InvalidArgumentException(
329
+ 'json_encode error: ' . json_last_error_msg()
330
+ );
331
+ }
332
+
333
+ return $json;
334
+ }
vendor/guzzlehttp/guzzle/src/functions_include.php ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Don't redefine the functions if included multiple times.
4
+ if (!function_exists('GuzzleHttp\uri_template')) {
5
+ require __DIR__ . '/functions.php';
6
+ }
vendor/guzzlehttp/promises/LICENSE ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Copyright (c) 2015-2016 Michael Dowling, https://github.com/mtdowling <mtdowling@gmail.com>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
vendor/guzzlehttp/promises/Makefile ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ all: clean test
2
+
3
+ test:
4
+ vendor/bin/phpunit
5
+
6
+ coverage:
7
+ vendor/bin/phpunit --coverage-html=artifacts/coverage
8
+
9
+ view-coverage:
10
+ open artifacts/coverage/index.html
11
+
12
+ clean:
13
+ rm -rf artifacts/*
vendor/guzzlehttp/promises/src/AggregateException.php ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace GuzzleHttp\Promise;
4
+
5
+ /**
6
+ * Exception thrown when too many errors occur in the some() or any() methods.
7
+ */
8
+ class AggregateException extends RejectionException
9
+ {
10
+ public function __construct($msg, array $reasons)
11
+ {
12
+ parent::__construct(
13
+ $reasons,
14
+ sprintf('%s; %d rejected promises', $msg, count($reasons))
15
+ );
16
+ }
17
+ }
vendor/guzzlehttp/promises/src/CancellationException.php ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace GuzzleHttp\Promise;
4
+
5
+ /**
6
+ * Exception that is set as the reason for a promise that has been cancelled.
7
+ */
8
+ class CancellationException extends RejectionException
9
+ {
10
+ }
vendor/guzzlehttp/promises/src/Coroutine.php ADDED
@@ -0,0 +1,169 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace GuzzleHttp\Promise;
4
+
5
+ use Exception;
6
+ use Generator;
7
+ use Throwable;
8
+
9
+ /**
10
+ * Creates a promise that is resolved using a generator that yields values or
11
+ * promises (somewhat similar to C#'s async keyword).
12
+ *
13
+ * When called, the Coroutine::of method will start an instance of the generator
14
+ * and returns a promise that is fulfilled with its final yielded value.
15
+ *
16
+ * Control is returned back to the generator when the yielded promise settles.
17
+ * This can lead to less verbose code when doing lots of sequential async calls
18
+ * with minimal processing in between.
19
+ *
20
+ * use GuzzleHttp\Promise;
21
+ *
22
+ * function createPromise($value) {
23
+ * return new Promise\FulfilledPromise($value);
24
+ * }
25
+ *
26
+ * $promise = Promise\Coroutine::of(function () {
27
+ * $value = (yield createPromise('a'));
28
+ * try {
29
+ * $value = (yield createPromise($value . 'b'));
30
+ * } catch (\Exception $e) {
31
+ * // The promise was rejected.
32
+ * }
33
+ * yield $value . 'c';
34
+ * });
35
+ *
36
+ * // Outputs "abc"
37
+ * $promise->then(function ($v) { echo $v; });
38
+ *
39
+ * @param callable $generatorFn Generator function to wrap into a promise.
40
+ *
41
+ * @return Promise
42
+ *
43
+ * @link https://github.com/petkaantonov/bluebird/blob/master/API.md#generators inspiration
44
+ */
45
+ final class Coroutine implements PromiseInterface
46
+ {
47
+ /**
48
+ * @var PromiseInterface|null
49
+ */
50
+ private $currentPromise;
51
+
52
+ /**
53
+ * @var Generator
54
+ */
55
+ private $generator;
56
+
57
+ /**
58
+ * @var Promise
59
+ */
60
+ private $result;
61
+
62
+ public function __construct(callable $generatorFn)
63
+ {
64
+ $this->generator = $generatorFn();
65
+ $this->result = new Promise(function () {
66
+ while (isset($this->currentPromise)) {
67
+ $this->currentPromise->wait();
68
+ }
69
+ });
70
+ try {
71
+ $this->nextCoroutine($this->generator->current());
72
+ } catch (\Exception $exception) {
73
+ $this->result->reject($exception);
74
+ } catch (Throwable $throwable) {
75
+ $this->result->reject($throwable);
76
+ }
77
+ }
78
+
79
+ /**
80
+ * Create a new coroutine.
81
+ *
82
+ * @return self
83
+ */
84
+ public static function of(callable $generatorFn)
85
+ {
86
+ return new self($generatorFn);
87
+ }
88
+
89
+ public function then(
90
+ callable $onFulfilled = null,
91
+ callable $onRejected = null
92
+ ) {
93
+ return $this->result->then($onFulfilled, $onRejected);
94
+ }
95
+
96
+ public function otherwise(callable $onRejected)
97
+ {
98
+ return $this->result->otherwise($onRejected);
99
+ }
100
+
101
+ public function wait($unwrap = true)
102
+ {
103
+ return $this->result->wait($unwrap);
104
+ }
105
+
106
+ public function getState()
107
+ {
108
+ return $this->result->getState();
109
+ }
110
+
111
+ public function resolve($value)
112
+ {
113
+ $this->result->resolve($value);
114
+ }
115
+
116
+ public function reject($reason)
117
+ {
118
+ $this->result->reject($reason);
119
+ }
120
+
121
+ public function cancel()
122
+ {
123
+ $this->currentPromise->cancel();
124
+ $this->result->cancel();
125
+ }
126
+
127
+ private function nextCoroutine($yielded)
128
+ {
129
+ $this->currentPromise = Create::promiseFor($yielded)
130
+ ->then([$this, '_handleSuccess'], [$this, '_handleFailure']);
131
+ }
132
+
133
+ /**
134
+ * @internal
135
+ */
136
+ public function _handleSuccess($value)
137
+ {
138
+ unset($this->currentPromise);
139
+ try {
140
+ $next = $this->generator->send($value);
141
+ if ($this->generator->valid()) {
142
+ $this->nextCoroutine($next);
143
+ } else {
144
+ $this->result->resolve($value);
145
+ }
146
+ } catch (Exception $exception) {
147
+ $this->result->reject($exception);
148
+ } catch (Throwable $throwable) {
149
+ $this->result->reject($throwable);
150
+ }
151
+ }
152
+
153
+ /**
154
+ * @internal
155
+ */
156
+ public function _handleFailure($reason)
157
+ {
158
+ unset($this->currentPromise);
159
+ try {
160
+ $nextYield = $this->generator->throw(Create::exceptionFor($reason));
161
+ // The throw was caught, so keep iterating on the coroutine
162
+ $this->nextCoroutine($nextYield);
163
+ } catch (Exception $exception) {
164
+ $this->result->reject($exception);
165
+ } catch (Throwable $throwable) {
166
+ $this->result->reject($throwable);
167
+ }
168
+ }
169
+ }
vendor/guzzlehttp/promises/src/Create.php ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace GuzzleHttp\Promise;
4
+
5
+ final class Create
6
+ {
7
+ /**
8
+ * Creates a promise for a value if the value is not a promise.
9
+ *
10
+ * @param mixed $value Promise or value.
11
+ *
12
+ * @return PromiseInterface
13
+ */
14
+ public static function promiseFor($value)
15
+ {
16
+ if ($value instanceof PromiseInterface) {
17
+ return $value;
18
+ }
19
+
20
+ // Return a Guzzle promise that shadows the given promise.
21
+ if (is_object($value) && method_exists($value, 'then')) {
22
+ $wfn = method_exists($value, 'wait') ? [$value, 'wait'] : null;
23
+ $cfn = method_exists($value, 'cancel') ? [$value, 'cancel'] : null;
24
+ $promise = new Promise($wfn, $cfn);
25
+ $value->then([$promise, 'resolve'], [$promise, 'reject']);
26
+ return $promise;
27
+ }
28
+
29
+ return new FulfilledPromise($value);
30
+ }
31
+
32
+ /**
33
+ * Creates a rejected promise for a reason if the reason is not a promise.
34
+ * If the provided reason is a promise, then it is returned as-is.
35
+ *
36
+ * @param mixed $reason Promise or reason.
37
+ *
38
+ * @return PromiseInterface
39
+ */
40
+ public static function rejectionFor($reason)
41
+ {
42
+ if ($reason instanceof PromiseInterface) {
43
+ return $reason;
44
+ }
45
+
46
+ return new RejectedPromise($reason);
47
+ }
48
+
49
+ /**
50
+ * Create an exception for a rejected promise value.
51
+ *
52
+ * @param mixed $reason
53
+ *
54
+ * @return \Exception|\Throwable
55
+ */
56
+ public static function exceptionFor($reason)
57
+ {
58
+ if ($reason instanceof \Exception || $reason instanceof \Throwable) {
59
+ return $reason;
60
+ }
61
+
62
+ return new RejectionException($reason);
63
+ }
64
+
65
+ /**
66
+ * Returns an iterator for the given value.
67
+ *
68
+ * @param mixed $value
69
+ *
70
+ * @return \Iterator
71
+ */
72
+ public static function iterFor($value)
73
+ {
74
+ if ($value instanceof \Iterator) {
75
+ return $value;
76
+ }
77
+
78
+ if (is_array($value)) {
79
+ return new \ArrayIterator($value);
80
+ }
81
+
82
+ return new \ArrayIterator([$value]);
83
+ }
84
+ }
vendor/guzzlehttp/promises/src/Each.php ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace GuzzleHttp\Promise;
4
+
5
+ final class Each
6
+ {
7
+ /**
8
+ * Given an iterator that yields promises or values, returns a promise that
9
+ * is fulfilled with a null value when the iterator has been consumed or
10
+ * the aggregate promise has been fulfilled or rejected.
11
+ *
12
+ * $onFulfilled is a function that accepts the fulfilled value, iterator
13
+ * index, and the aggregate promise. The callback can invoke any necessary
14
+ * side effects and choose to resolve or reject the aggregate if needed.
15
+ *
16
+ * $onRejected is a function that accepts the rejection reason, iterator
17
+ * index, and the aggregate promise. The callback can invoke any necessary
18
+ * side effects and choose to resolve or reject the aggregate if needed.
19
+ *
20
+ * @param mixed $iterable Iterator or array to iterate over.
21
+ * @param callable $onFulfilled
22
+ * @param callable $onRejected
23
+ *
24
+ * @return PromiseInterface
25
+ */
26
+ public static function of(
27
+ $iterable,
28
+ callable $onFulfilled = null,
29
+ callable $onRejected = null
30
+ ) {
31
+ return (new EachPromise($iterable, [
32
+ 'fulfilled' => $onFulfilled,
33
+ 'rejected' => $onRejected
34
+ ]))->promise();
35
+ }
36
+
37
+ /**
38
+ * Like of, but only allows a certain number of outstanding promises at any
39
+ * given time.
40
+ *
41
+ * $concurrency may be an integer or a function that accepts the number of
42
+ * pending promises and returns a numeric concurrency limit value to allow
43
+ * for dynamic a concurrency size.
44
+ *
45
+ * @param mixed $iterable
46
+ * @param int|callable $concurrency
47
+ * @param callable $onFulfilled
48
+ * @param callable $onRejected
49
+ *
50
+ * @return PromiseInterface
51
+ */
52
+ public static function ofLimit(
53
+ $iterable,
54
+ $concurrency,
55
+ callable $onFulfilled = null,
56
+ callable $onRejected = null
57
+ ) {
58
+ return (new EachPromise($iterable, [
59
+ 'fulfilled' => $onFulfilled,
60
+ 'rejected' => $onRejected,
61
+ 'concurrency' => $concurrency
62
+ ]))->promise();
63
+ }
64
+
65
+ /**
66
+ * Like limit, but ensures that no promise in the given $iterable argument
67
+ * is rejected. If any promise is rejected, then the aggregate promise is
68
+ * rejected with the encountered rejection.
69
+ *
70
+ * @param mixed $iterable
71
+ * @param int|callable $concurrency
72
+ * @param callable $onFulfilled
73
+ *
74
+ * @return PromiseInterface
75
+ */
76
+ public static function ofLimitAll(
77
+ $iterable,
78
+ $concurrency,
79
+ callable $onFulfilled = null
80
+ ) {
81
+ return each_limit(
82
+ $iterable,
83
+ $concurrency,
84
+ $onFulfilled,
85
+ function ($reason, $idx, PromiseInterface $aggregate) {
86
+ $aggregate->reject($reason);
87
+ }
88
+ );
89
+ }
90
+ }
vendor/guzzlehttp/promises/src/EachPromise.php ADDED
@@ -0,0 +1,254 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace GuzzleHttp\Promise;
4
+
5
+ /**
6
+ * Represents a promise that iterates over many promises and invokes
7
+ * side-effect functions in the process.
8
+ */
9
+ class EachPromise implements PromisorInterface
10
+ {
11
+ private $pending = [];
12
+
13
+ private $nextPendingIndex = 0;
14
+
15
+ /** @var \Iterator|null */
16
+ private $iterable;
17
+
18
+ /** @var callable|int|null */
19
+ private $concurrency;
20
+
21
+ /** @var callable|null */
22
+ private $onFulfilled;
23
+
24
+ /** @var callable|null */
25
+ private $onRejected;
26
+
27
+ /** @var Promise|null */
28
+ private $aggregate;
29
+
30
+ /** @var bool|null */
31
+ private $mutex;
32
+
33
+ /**
34
+ * Configuration hash can include the following key value pairs:
35
+ *
36
+ * - fulfilled: (callable) Invoked when a promise fulfills. The function
37
+ * is invoked with three arguments: the fulfillment value, the index
38
+ * position from the iterable list of the promise, and the aggregate
39
+ * promise that manages all of the promises. The aggregate promise may
40
+ * be resolved from within the callback to short-circuit the promise.
41
+ * - rejected: (callable) Invoked when a promise is rejected. The
42
+ * function is invoked with three arguments: the rejection reason, the
43
+ * index position from the iterable list of the promise, and the
44
+ * aggregate promise that manages all of the promises. The aggregate
45
+ * promise may be resolved from within the callback to short-circuit
46
+ * the promise.
47
+ * - concurrency: (integer) Pass this configuration option to limit the
48
+ * allowed number of outstanding concurrently executing promises,
49
+ * creating a capped pool of promises. There is no limit by default.
50
+ *
51
+ * @param mixed $iterable Promises or values to iterate.
52
+ * @param array $config Configuration options
53
+ */
54
+ public function __construct($iterable, array $config = [])
55
+ {
56
+ $this->iterable = Create::iterFor($iterable);
57
+
58
+ if (isset($config['concurrency'])) {
59
+ $this->concurrency = $config['concurrency'];
60
+ }
61
+
62
+ if (isset($config['fulfilled'])) {
63
+ $this->onFulfilled = $config['fulfilled'];
64
+ }
65
+
66
+ if (isset($config['rejected'])) {
67
+ $this->onRejected = $config['rejected'];
68
+ }
69
+ }
70
+
71
+ /** @psalm-suppress InvalidNullableReturnType */
72
+ public function promise()
73
+ {
74
+ if ($this->aggregate) {
75
+ return $this->aggregate;
76
+ }
77
+
78
+ try {
79
+ $this->createPromise();
80
+ /** @psalm-assert Promise $this->aggregate */
81
+ $this->iterable->rewind();
82
+ if (!$this->checkIfFinished()) {
83
+ $this->refillPending();
84
+ }
85
+ } catch (\Throwable $e) {
86
+ /**
87
+ * @psalm-suppress NullReference
88
+ * @phpstan-ignore-next-line
89
+ */
90
+ $this->aggregate->reject($e);
91
+ } catch (\Exception $e) {
92
+ /**
93
+ * @psalm-suppress NullReference
94
+ * @phpstan-ignore-next-line
95
+ */
96
+ $this->aggregate->reject($e);
97
+ }
98
+
99
+ /**
100
+ * @psalm-suppress NullableReturnStatement
101
+ * @phpstan-ignore-next-line
102
+ */
103
+ return $this->aggregate;
104
+ }
105
+
106
+ private function createPromise()
107
+ {
108
+ $this->mutex = false;
109
+ $this->aggregate = new Promise(function () {
110
+ reset($this->pending);
111
+ // Consume a potentially fluctuating list of promises while
112
+ // ensuring that indexes are maintained (precluding array_shift).
113
+ while ($promise = current($this->pending)) {
114
+ next($this->pending);
115
+ $promise->wait();
116
+ if (Is::settled($this->aggregate)) {
117
+ return;
118
+ }
119
+ }
120
+ });
121
+
122
+ // Clear the references when the promise is resolved.
123
+ $clearFn = function () {
124
+ $this->iterable = $this->concurrency = $this->pending = null;
125
+ $this->onFulfilled = $this->onRejected = null;
126
+ $this->nextPendingIndex = 0;
127
+ };
128
+
129
+ $this->aggregate->then($clearFn, $clearFn);
130
+ }
131
+
132
+ private function refillPending()
133
+ {
134
+ if (!$this->concurrency) {
135
+ // Add all pending promises.
136
+ while ($this->addPending() && $this->advanceIterator());
137
+ return;
138
+ }
139
+
140
+ // Add only up to N pending promises.
141
+ $concurrency = is_callable($this->concurrency)
142
+ ? call_user_func($this->concurrency, count($this->pending))
143
+ : $this->concurrency;
144
+ $concurrency = max($concurrency - count($this->pending), 0);
145
+ // Concurrency may be set to 0 to disallow new promises.
146
+ if (!$concurrency) {
147
+ return;
148
+ }
149
+ // Add the first pending promise.
150
+ $this->addPending();
151
+ // Note this is special handling for concurrency=1 so that we do
152
+ // not advance the iterator after adding the first promise. This
153
+ // helps work around issues with generators that might not have the
154
+ // next value to yield until promise callbacks are called.
155
+ while (--$concurrency
156
+ && $this->advanceIterator()
157
+ && $this->addPending());
158
+ }
159
+
160
+ private function addPending()
161
+ {
162
+ if (!$this->iterable || !$this->iterable->valid()) {
163
+ return false;
164
+ }
165
+
166
+ $promise = Create::promiseFor($this->iterable->current());
167
+ $key = $this->iterable->key();
168
+
169
+ // Iterable keys may not be unique, so we use a counter to
170
+ // guarantee uniqueness
171
+ $idx = $this->nextPendingIndex++;
172
+
173
+ $this->pending[$idx] = $promise->then(
174
+ function ($value) use ($idx, $key) {
175
+ if ($this->onFulfilled) {
176
+ call_user_func(
177
+ $this->onFulfilled,
178
+ $value,
179
+ $key,
180
+ $this->aggregate
181
+ );
182
+ }
183
+ $this->step($idx);
184
+ },
185
+ function ($reason) use ($idx, $key) {
186
+ if ($this->onRejected) {
187
+ call_user_func(
188
+ $this->onRejected,
189
+ $reason,
190
+ $key,
191
+ $this->aggregate
192
+ );
193
+ }
194
+ $this->step($idx);
195
+ }
196
+ );
197
+
198
+ return true;
199
+ }
200
+
201
+ private function advanceIterator()
202
+ {
203
+ // Place a lock on the iterator so that we ensure to not recurse,
204
+ // preventing fatal generator errors.
205
+ if ($this->mutex) {
206
+ return false;
207
+ }
208
+
209
+ $this->mutex = true;
210
+
211
+ try {
212
+ $this->iterable->next();
213
+ $this->mutex = false;
214
+ return true;
215
+ } catch (\Throwable $e) {
216
+ $this->aggregate->reject($e);
217
+ $this->mutex = false;
218
+ return false;
219
+ } catch (\Exception $e) {
220
+ $this->aggregate->reject($e);
221
+ $this->mutex = false;
222
+ return false;
223
+ }
224
+ }
225
+
226
+ private function step($idx)
227
+ {
228
+ // If the promise was already resolved, then ignore this step.
229
+ if (Is::settled($this->aggregate)) {
230
+ return;
231
+ }
232
+
233
+ unset($this->pending[$idx]);
234
+
235
+ // Only refill pending promises if we are not locked, preventing the
236
+ // EachPromise to recursively invoke the provided iterator, which
237
+ // cause a fatal error: "Cannot resume an already running generator"
238
+ if ($this->advanceIterator() && !$this->checkIfFinished()) {
239
+ // Add more pending promises if possible.
240
+ $this->refillPending();
241
+ }
242
+ }
243
+
244
+ private function checkIfFinished()
245
+ {
246
+ if (!$this->pending && !$this->iterable->valid()) {
247
+ // Resolve the promise if there's nothing left to do.
248
+ $this->aggregate->resolve(null);
249
+ return true;
250
+ }
251
+
252
+ return false;
253
+ }
254
+ }
vendor/guzzlehttp/promises/src/FulfilledPromise.php ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace GuzzleHttp\Promise;
4
+
5
+ /**
6
+ * A promise that has been fulfilled.
7
+ *
8
+ * Thenning off of this promise will invoke the onFulfilled callback
9
+ * immediately and ignore other callbacks.
10
+ */
11
+ class FulfilledPromise implements PromiseInterface
12
+ {
13
+ private $value;
14
+
15
+ public function __construct($value)
16
+ {
17
+ if (is_object($value) && method_exists($value, 'then')) {
18
+ throw new \InvalidArgumentException(
19
+ 'You cannot create a FulfilledPromise with a promise.'
20
+ );
21
+ }
22
+
23
+ $this->value = $value;
24
+ }
25
+
26
+ public function then(
27
+ callable $onFulfilled = null,
28
+ callable $onRejected = null
29
+ ) {
30
+ // Return itself if there is no onFulfilled function.
31
+ if (!$onFulfilled) {
32
+ return $this;
33
+ }
34
+
35
+ $queue = Utils::queue();
36
+ $p = new Promise([$queue, 'run']);
37
+ $value = $this->value;
38
+ $queue->add(static function () use ($p, $value, $onFulfilled) {
39
+ if (Is::pending($p)) {
40
+ try {
41
+ $p->resolve($onFulfilled($value));
42
+ } catch (\Throwable $e) {
43
+ $p->reject($e);
44
+ } catch (\Exception $e) {
45
+ $p->reject($e);
46
+ }
47
+ }
48
+ });
49
+
50
+ return $p;
51
+ }
52
+
53
+ public function otherwise(callable $onRejected)
54
+ {
55
+ return $this->then(null, $onRejected);
56
+ }
57
+
58
+ public function wait($unwrap = true, $defaultDelivery = null)
59
+ {
60
+ return $unwrap ? $this->value : null;
61
+ }
62
+
63
+ public function getState()
64
+ {
65
+ return self::FULFILLED;
66
+ }
67
+
68
+ public function resolve($value)
69
+ {
70
+ if ($value !== $this->value) {
71
+ throw new \LogicException("Cannot resolve a fulfilled promise");
72
+ }
73
+ }
74
+
75
+ public function reject($reason)
76
+ {
77
+ throw new \LogicException("Cannot reject a fulfilled promise");
78
+ }
79
+
80
+ public function cancel()
81
+ {
82
+ // pass
83
+ }
84
+ }
vendor/guzzlehttp/promises/src/Is.php ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace GuzzleHttp\Promise;
4
+
5
+ final class Is
6
+ {
7
+ /**
8
+ * Returns true if a promise is pending.
9
+ *
10
+ * @return bool
11
+ */
12
+ public static function pending(PromiseInterface $promise)
13
+ {
14
+ return $promise->getState() === PromiseInterface::PENDING;
15
+ }
16
+
17
+ /**
18
+ * Returns true if a promise is fulfilled or rejected.
19
+ *
20
+ * @return bool
21
+ */
22
+ public static function settled(PromiseInterface $promise)
23
+ {
24
+ return $promise->getState() !== PromiseInterface::PENDING;
25
+ }
26
+
27
+ /**
28
+ * Returns true if a promise is fulfilled.
29
+ *
30
+ * @return bool
31
+ */
32
+ public static function fulfilled(PromiseInterface $promise)
33
+ {
34
+ return $promise->getState() === PromiseInterface::FULFILLED;
35
+ }
36
+
37
+ /**
38
+ * Returns true if a promise is rejected.
39
+ *
40
+ * @return bool
41
+ */
42
+ public static function rejected(PromiseInterface $promise)
43
+ {
44
+ return $promise->getState() === PromiseInterface::REJECTED;
45
+ }
46
+ }
vendor/guzzlehttp/promises/src/Promise.php ADDED
@@ -0,0 +1,278 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace GuzzleHttp\Promise;
4
+
5
+ /**
6
+ * Promises/A+ implementation that avoids recursion when possible.
7
+ *
8
+ * @link https://promisesaplus.com/
9
+ */
10
+ class Promise implements PromiseInterface
11
+ {
12
+ private $state = self::PENDING;
13
+ private $result;
14
+ private $cancelFn;
15
+ private $waitFn;
16
+ private $waitList;
17
+ private $handlers = [];
18
+
19
+ /**
20
+ * @param callable $waitFn Fn that when invoked resolves the promise.
21
+ * @param callable $cancelFn Fn that when invoked cancels the promise.
22
+ */
23
+ public function __construct(
24
+ callable $waitFn = null,
25
+ callable $cancelFn = null
26
+ ) {
27
+ $this->waitFn = $waitFn;
28
+ $this->cancelFn = $cancelFn;
29
+ }
30
+
31
+ public function then(
32
+ callable $onFulfilled = null,
33
+ callable $onRejected = null
34
+ ) {
35
+ if ($this->state === self::PENDING) {
36
+ $p = new Promise(null, [$this, 'cancel']);
37
+ $this->handlers[] = [$p, $onFulfilled, $onRejected];
38
+ $p->waitList = $this->waitList;
39
+ $p->waitList[] = $this;
40
+ return $p;
41
+ }
42
+
43
+ // Return a fulfilled promise and immediately invoke any callbacks.
44
+ if ($this->state === self::FULFILLED) {
45
+ $promise = Create::promiseFor($this->result);
46
+ return $onFulfilled ? $promise->then($onFulfilled) : $promise;
47
+ }
48
+
49
+ // It's either cancelled or rejected, so return a rejected promise
50
+ // and immediately invoke any callbacks.
51
+ $rejection = Create::rejectionFor($this->result);
52
+ return $onRejected ? $rejection->then(null, $onRejected) : $rejection;
53
+ }
54
+
55
+ public function otherwise(callable $onRejected)
56
+ {
57
+ return $this->then(null, $onRejected);
58
+ }
59
+
60
+ public function wait($unwrap = true)
61
+ {
62
+ $this->waitIfPending();
63
+
64
+ if ($this->result instanceof PromiseInterface) {
65
+ return $this->result->wait($unwrap);
66
+ }
67
+ if ($unwrap) {
68
+ if ($this->state === self::FULFILLED) {
69
+ return $this->result;
70
+ }
71
+ // It's rejected so "unwrap" and throw an exception.
72
+ throw Create::exceptionFor($this->result);
73
+ }
74
+ }
75
+
76
+ public function getState()
77
+ {
78
+ return $this->state;
79
+ }
80
+
81
+ public function cancel()
82
+ {
83
+ if ($this->state !== self::PENDING) {
84
+ return;
85
+ }
86
+
87
+ $this->waitFn = $this->waitList = null;
88
+
89
+ if ($this->cancelFn) {
90
+ $fn = $this->cancelFn;
91
+ $this->cancelFn = null;
92
+ try {
93
+ $fn();
94
+ } catch (\Throwable $e) {
95
+ $this->reject($e);
96
+ } catch (\Exception $e) {
97
+ $this->reject($e);
98
+ }
99
+ }
100
+
101
+ // Reject the promise only if it wasn't rejected in a then callback.
102
+ /** @psalm-suppress RedundantCondition */
103
+ if ($this->state === self::PENDING) {
104
+ $this->reject(new CancellationException('Promise has been cancelled'));
105
+ }
106
+ }
107
+
108
+ public function resolve($value)
109
+ {
110
+ $this->settle(self::FULFILLED, $value);
111
+ }
112
+
113
+ public function reject($reason)
114
+ {
115
+ $this->settle(self::REJECTED, $reason);
116
+ }
117
+
118
+ private function settle($state, $value)
119
+ {
120
+ if ($this->state !== self::PENDING) {
121
+ // Ignore calls with the same resolution.
122
+ if ($state === $this->state && $value === $this->result) {
123
+ return;
124
+ }
125
+ throw $this->state === $state
126
+ ? new \LogicException("The promise is already {$state}.")
127
+ : new \LogicException("Cannot change a {$this->state} promise to {$state}");
128
+ }
129
+
130
+ if ($value === $this) {
131
+ throw new \LogicException('Cannot fulfill or reject a promise with itself');
132
+ }
133
+
134
+ // Clear out the state of the promise but stash the handlers.
135
+ $this->state = $state;
136
+ $this->result = $value;
137
+ $handlers = $this->handlers;
138
+ $this->handlers = null;
139
+ $this->waitList = $this->waitFn = null;
140
+ $this->cancelFn = null;
141
+
142
+ if (!$handlers) {
143
+ return;
144
+ }
145
+
146
+ // If the value was not a settled promise or a thenable, then resolve
147
+ // it in the task queue using the correct ID.
148
+ if (!is_object($value) || !method_exists($value, 'then')) {
149
+ $id = $state === self::FULFILLED ? 1 : 2;
150
+ // It's a success, so resolve the handlers in the queue.
151
+ Utils::queue()->add(static function () use ($id, $value, $handlers) {
152
+ foreach ($handlers as $handler) {
153
+ self::callHandler($id, $value, $handler);
154
+ }
155
+ });
156
+ } elseif ($value instanceof Promise && Is::pending($value)) {
157
+ // We can just merge our handlers onto the next promise.
158
+ $value->handlers = array_merge($value->handlers, $handlers);
159
+ } else {
160
+ // Resolve the handlers when the forwarded promise is resolved.
161
+ $value->then(
162
+ static function ($value) use ($handlers) {
163
+ foreach ($handlers as $handler) {
164
+ self::callHandler(1, $value, $handler);
165
+ }
166
+ },
167
+ static function ($reason) use ($handlers) {
168
+ foreach ($handlers as $handler) {
169
+ self::callHandler(2, $reason, $handler);
170
+ }
171
+ }
172
+ );
173
+ }
174
+ }
175
+
176
+ /**
177
+ * Call a stack of handlers using a specific callback index and value.
178
+ *
179
+ * @param int $index 1 (resolve) or 2 (reject).
180
+ * @param mixed $value Value to pass to the callback.
181
+ * @param array $handler Array of handler data (promise and callbacks).
182
+ */
183
+ private static function callHandler($index, $value, array $handler)
184
+ {
185
+ /** @var PromiseInterface $promise */
186
+ $promise = $handler[0];
187
+
188
+ // The promise may have been cancelled or resolved before placing
189
+ // this thunk in the queue.
190
+ if (Is::settled($promise)) {
191
+ return;
192
+ }
193
+
194
+ try {
195
+ if (isset($handler[$index])) {
196
+ /*
197
+ * If $f throws an exception, then $handler will be in the exception
198
+ * stack trace. Since $handler contains a reference to the callable
199
+ * itself we get a circular reference. We clear the $handler
200
+ * here to avoid that memory leak.
201
+ */
202
+ $f = $handler[$index];
203
+ unset($handler);
204
+ $promise->resolve($f($value));
205
+ } elseif ($index === 1) {
206
+ // Forward resolution values as-is.
207
+ $promise->resolve($value);
208
+ } else {
209
+ // Forward rejections down the chain.
210
+ $promise->reject($value);
211
+ }
212
+ } catch (\Throwable $reason) {
213
+ $promise->reject($reason);
214
+ } catch (\Exception $reason) {
215
+ $promise->reject($reason);
216
+ }
217
+ }
218
+
219
+ private function waitIfPending()
220
+ {
221
+ if ($this->state !== self::PENDING) {
222
+ return;
223
+ } elseif ($this->waitFn) {
224
+ $this->invokeWaitFn();
225
+ } elseif ($this->waitList) {
226
+ $this->invokeWaitList();
227
+ } else {
228
+ // If there's no wait function, then reject the promise.
229
+ $this->reject('Cannot wait on a promise that has '
230
+ . 'no internal wait function. You must provide a wait '
231
+ . 'function when constructing the promise to be able to '
232
+ . 'wait on a promise.');
233
+ }
234
+
235
+ Utils::queue()->run();
236
+
237
+ /** @psalm-suppress RedundantCondition */
238
+ if ($this->state === self::PENDING) {
239
+ $this->reject('Invoking the wait callback did not resolve the promise');
240
+ }
241
+ }
242
+
243
+ private function invokeWaitFn()
244
+ {
245
+ try {
246
+ $wfn = $this->waitFn;
247
+ $this->waitFn = null;
248
+ $wfn(true);
249
+ } catch (\Exception $reason) {
250
+ if ($this->state === self::PENDING) {
251
+ // The promise has not been resolved yet, so reject the promise
252
+ // with the exception.
253
+ $this->reject($reason);
254
+ } else {
255
+ // The promise was already resolved, so there's a problem in
256
+ // the application.
257
+ throw $reason;
258
+ }
259
+ }
260
+ }
261
+
262
+ private function invokeWaitList()
263
+ {
264
+ $waitList = $this->waitList;
265
+ $this->waitList = null;
266
+
267
+ foreach ($waitList as $result) {
268
+ do {
269
+ $result->waitIfPending();
270
+ $result = $result->result;
271
+ } while ($result instanceof Promise);
272
+
273
+ if ($result instanceof PromiseInterface) {
274
+ $result->wait(false);
275
+ }
276
+ }
277
+ }
278
+ }
vendor/guzzlehttp/promises/src/PromiseInterface.php ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace GuzzleHttp\Promise;
4
+
5
+ /**
6
+ * A promise represents the eventual result of an asynchronous operation.
7
+ *
8
+ * The primary way of interacting with a promise is through its then method,
9
+ * which registers callbacks to receive either a promise’s eventual value or
10
+ * the reason why the promise cannot be fulfilled.
11
+ *
12
+ * @link https://promisesaplus.com/
13
+ */
14
+ interface PromiseInterface
15
+ {
16
+ const PENDING = 'pending';
17
+ const FULFILLED = 'fulfilled';
18
+ const REJECTED = 'rejected';
19
+
20
+ /**
21
+ * Appends fulfillment and rejection handlers to the promise, and returns
22
+ * a new promise resolving to the return value of the called handler.
23
+ *
24
+ * @param callable $onFulfilled Invoked when the promise fulfills.
25
+ * @param callable $onRejected Invoked when the promise is rejected.
26
+ *
27
+ * @return PromiseInterface
28
+ */
29
+ public function then(
30
+ callable $onFulfilled = null,
31
+ callable $onRejected = null
32
+ );
33
+
34
+ /**
35
+ * Appends a rejection handler callback to the promise, and returns a new
36
+ * promise resolving to the return value of the callback if it is called,
37
+ * or to its original fulfillment value if the promise is instead
38
+ * fulfilled.
39
+ *
40
+ * @param callable $onRejected Invoked when the promise is rejected.
41
+ *
42
+ * @return PromiseInterface
43
+ */
44
+ public function otherwise(callable $onRejected);
45
+
46
+ /**
47
+ * Get the state of the promise ("pending", "rejected", or "fulfilled").
48
+ *
49
+ * The three states can be checked against the constants defined on
50
+ * PromiseInterface: PENDING, FULFILLED, and REJECTED.
51
+ *
52
+ * @return string
53
+ */
54
+ public function getState();
55
+
56
+ /**
57
+ * Resolve the promise with the given value.
58
+ *
59
+ * @param mixed $value
60
+ *
61
+ * @throws \RuntimeException if the promise is already resolved.
62
+ */
63
+ public function resolve($value);
64
+
65
+ /**
66
+ * Reject the promise with the given reason.
67
+ *
68
+ * @param mixed $reason
69
+ *
70
+ * @throws \RuntimeException if the promise is already resolved.
71
+ */
72
+ public function reject($reason);
73
+
74
+ /**
75
+ * Cancels the promise if possible.
76
+ *
77
+ * @link https://github.com/promises-aplus/cancellation-spec/issues/7
78
+ */
79
+ public function cancel();
80
+
81
+ /**
82
+ * Waits until the promise completes if possible.
83
+ *
84
+ * Pass $unwrap as true to unwrap the result of the promise, either
85
+ * returning the resolved value or throwing the rejected exception.
86
+ *
87
+ * If the promise cannot be waited on, then the promise will be rejected.
88
+ *
89
+ * @param bool $unwrap
90
+ *
91
+ * @return mixed
92
+ *
93
+ * @throws \LogicException if the promise has no wait function or if the
94
+ * promise does not settle after waiting.
95
+ */
96
+ public function wait($unwrap = true);
97
+ }
vendor/guzzlehttp/promises/src/PromisorInterface.php ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace GuzzleHttp\Promise;
4
+
5
+ /**
6
+ * Interface used with classes that return a promise.
7
+ */
8
+ interface PromisorInterface
9
+ {
10
+ /**
11
+ * Returns a promise.
12
+ *
13
+ * @return PromiseInterface
14
+ */
15
+ public function promise();
16
+ }
vendor/guzzlehttp/promises/src/RejectedPromise.php ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace GuzzleHttp\Promise;
4
+
5
+ /**
6
+ * A promise that has been rejected.
7
+ *
8
+ * Thenning off of this promise will invoke the onRejected callback
9
+ * immediately and ignore other callbacks.
10
+ */
11
+ class RejectedPromise implements PromiseInterface
12
+ {
13
+ private $reason;
14
+
15
+ public function __construct($reason)
16
+ {
17
+ if (is_object($reason) && method_exists($reason, 'then')) {
18
+ throw new \InvalidArgumentException(
19
+ 'You cannot create a RejectedPromise with a promise.'
20
+ );
21
+ }
22
+
23
+ $this->reason = $reason;
24
+ }
25
+
26
+ public function then(
27
+ callable $onFulfilled = null,
28
+ callable $onRejected = null
29
+ ) {
30
+ // If there's no onRejected callback then just return self.
31
+ if (!$onRejected) {
32
+ return $this;
33
+ }
34
+
35
+ $queue = Utils::queue();
36
+ $reason = $this->reason;
37
+ $p = new Promise([$queue, 'run']);
38
+ $queue->add(static function () use ($p, $reason, $onRejected) {
39
+ if (Is::pending($p)) {
40
+ try {
41
+ // Return a resolved promise if onRejected does not throw.
42
+ $p->resolve($onRejected($reason));
43
+ } catch (\Throwable $e) {
44
+ // onRejected threw, so return a rejected promise.
45
+ $p->reject($e);
46
+ } catch (\Exception $e) {
47
+ // onRejected threw, so return a rejected promise.
48
+ $p->reject($e);
49
+ }
50
+ }
51
+ });
52
+
53
+ return $p;
54
+ }
55
+
56
+ public function otherwise(callable $onRejected)
57
+ {
58
+ return $this->then(null, $onRejected);
59
+ }
60
+
61
+ public function wait($unwrap = true, $defaultDelivery = null)
62
+ {
63
+ if ($unwrap) {
64
+ throw Create::exceptionFor($this->reason);
65
+ }
66
+
67
+ return null;
68
+ }
69
+
70
+ public function getState()
71
+ {
72
+ return self::REJECTED;
73
+ }
74
+
75
+ public function resolve($value)
76
+ {
77
+ throw new \LogicException("Cannot resolve a rejected promise");
78
+ }
79
+
80
+ public function reject($reason)
81
+ {
82
+ if ($reason !== $this->reason) {
83
+ throw new \LogicException("Cannot reject a rejected promise");
84
+ }
85
+ }
86
+
87
+ public function cancel()
88
+ {
89
+ // pass
90
+ }
91
+ }
vendor/guzzlehttp/promises/src/RejectionException.php ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace GuzzleHttp\Promise;
4
+
5
+ /**
6
+ * A special exception that is thrown when waiting on a rejected promise.
7
+ *
8
+ * The reason value is available via the getReason() method.
9
+ */
10
+ class RejectionException extends \RuntimeException
11
+ {
12
+ /** @var mixed Rejection reason. */
13
+ private $reason;
14
+
15
+ /**
16
+ * @param mixed $reason Rejection reason.
17
+ * @param string $description Optional description
18
+ */
19
+ public function __construct($reason, $description = null)
20
+ {
21
+ $this->reason = $reason;
22
+
23
+ $message = 'The promise was rejected';
24
+
25
+ if ($description) {
26
+ $message .= ' with reason: ' . $description;
27
+ } elseif (is_string($reason)
28
+ || (is_object($reason) && method_exists($reason, '__toString'))
29
+ ) {
30
+ $message .= ' with reason: ' . $this->reason;
31
+ } elseif ($reason instanceof \JsonSerializable) {
32
+ $message .= ' with reason: '
33
+ . json_encode($this->reason, JSON_PRETTY_PRINT);
34
+ }
35
+
36
+ parent::__construct($message);
37
+ }
38
+
39
+ /**
40
+ * Returns the rejection reason.
41
+ *
42
+ * @return mixed
43
+ */
44
+ public function getReason()
45
+ {
46
+ return $this->reason;
47
+ }
48
+ }
vendor/guzzlehttp/promises/src/TaskQueue.php ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace GuzzleHttp\Promise;
4
+
5
+ /**
6
+ * A task queue that executes tasks in a FIFO order.
7
+ *
8
+ * This task queue class is used to settle promises asynchronously and
9
+ * maintains a constant stack size. You can use the task queue asynchronously
10
+ * by calling the `run()` function of the global task queue in an event loop.
11
+ *
12
+ * GuzzleHttp\Promise\Utils::queue()->run();
13
+ */
14
+ class TaskQueue implements TaskQueueInterface
15
+ {
16
+ private $enableShutdown = true;
17
+ private $queue = [];
18
+
19
+ public function __construct($withShutdown = true)
20
+ {
21
+ if ($withShutdown) {
22
+ register_shutdown_function(function () {
23
+ if ($this->enableShutdown) {
24
+ // Only run the tasks if an E_ERROR didn't occur.
25
+ $err = error_get_last();
26
+ if (!$err || ($err['type'] ^ E_ERROR)) {
27
+ $this->run();
28
+ }
29
+ }
30
+ });
31
+ }
32
+ }
33
+
34
+ public function isEmpty()
35
+ {
36
+ return !$this->queue;
37
+ }
38
+
39
+ public function add(callable $task)
40
+ {
41
+ $this->queue[] = $task;
42
+ }
43
+
44
+ public function run()
45
+ {
46
+ while ($task = array_shift($this->queue)) {
47
+ /** @var callable $task */
48
+ $task();
49
+ }
50
+ }
51
+
52
+ /**
53
+ * The task queue will be run and exhausted by default when the process
54
+ * exits IFF the exit is not the result of a PHP E_ERROR error.
55
+ *
56
+ * You can disable running the automatic shutdown of the queue by calling
57
+ * this function. If you disable the task queue shutdown process, then you
58
+ * MUST either run the task queue (as a result of running your event loop
59
+ * or manually using the run() method) or wait on each outstanding promise.
60
+ *
61
+ * Note: This shutdown will occur before any destructors are triggered.
62
+ */
63
+ public function disableShutdown()
64
+ {
65
+ $this->enableShutdown = false;
66
+ }
67
+ }
vendor/guzzlehttp/promises/src/TaskQueueInterface.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace GuzzleHttp\Promise;
4
+
5
+ interface TaskQueueInterface
6
+ {
7
+ /**
8
+ * Returns true if the queue is empty.
9
+ *
10
+ * @return bool
11
+ */
12
+ public function isEmpty();
13
+
14
+ /**
15
+ * Adds a task to the queue that will be executed the next time run is
16
+ * called.
17
+ */
18
+ public function add(callable $task);
19
+
20
+ /**
21
+ * Execute all of the pending task in the queue.
22
+ */
23
+ public function run();
24
+ }
vendor/guzzlehttp/promises/src/Utils.php ADDED
@@ -0,0 +1,274 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace GuzzleHttp\Promise;
4
+
5
+ final class Utils
6
+ {
7
+ /**
8
+ * Get the global task queue used for promise resolution.
9
+ *
10
+ * This task queue MUST be run in an event loop in order for promises to be
11
+ * settled asynchronously. It will be automatically run when synchronously
12
+ * waiting on a promise.
13
+ *
14
+ * <code>
15
+ * while ($eventLoop->isRunning()) {
16
+ * GuzzleHttp\Promise\Utils::queue()->run();
17
+ * }
18
+ * </code>
19
+ *
20
+ * @param TaskQueueInterface $assign Optionally specify a new queue instance.
21
+ *
22
+ * @return TaskQueueInterface
23
+ */
24
+ public static function queue(TaskQueueInterface $assign = null)
25
+ {
26
+ static $queue;
27
+
28
+ if ($assign) {
29
+ $queue = $assign;
30
+ } elseif (!$queue) {
31
+ $queue = new TaskQueue();
32
+ }
33
+
34
+ return $queue;
35
+ }
36
+
37
+ /**
38
+ * Adds a function to run in the task queue when it is next `run()` and
39
+ * returns a promise that is fulfilled or rejected with the result.
40
+ *
41
+ * @param callable $task Task function to run.
42
+ *
43
+ * @return PromiseInterface
44
+ */
45
+ public static function task(callable $task)
46
+ {
47
+ $queue = self::queue();
48
+ $promise = new Promise([$queue, 'run']);
49
+ $queue->add(function () use ($task, $promise) {
50
+ try {
51
+ $promise->resolve($task());
52
+ } catch (\Throwable $e) {
53
+ $promise->reject($e);
54
+ } catch (\Exception $e) {
55
+ $promise->reject($e);
56
+ }
57
+ });
58
+
59
+ return $promise;
60
+ }
61
+
62
+ /**
63
+ * Synchronously waits on a promise to resolve and returns an inspection
64
+ * state array.
65
+ *
66
+ * Returns a state associative array containing a "state" key mapping to a
67
+ * valid promise state. If the state of the promise is "fulfilled", the
68
+ * array will contain a "value" key mapping to the fulfilled value of the
69
+ * promise. If the promise is rejected, the array will contain a "reason"
70
+ * key mapping to the rejection reason of the promise.
71
+ *
72
+ * @param PromiseInterface $promise Promise or value.
73
+ *
74
+ * @return array
75
+ */
76
+ public static function inspect(PromiseInterface $promise)
77
+ {
78
+ try {
79
+ return [
80
+ 'state' => PromiseInterface::FULFILLED,
81
+ 'value' => $promise->wait()
82
+ ];
83
+ } catch (RejectionException $e) {
84
+ return ['state' => PromiseInterface::REJECTED, 'reason' => $e->getReason()];
85
+ } catch (\Throwable $e) {
86
+ return ['state' => PromiseInterface::REJECTED, 'reason' => $e];
87
+ } catch (\Exception $e) {
88
+ return ['state' => PromiseInterface::REJECTED, 'reason' => $e];
89
+ }
90
+ }
91
+
92
+ /**
93
+ * Waits on all of the provided promises, but does not unwrap rejected
94
+ * promises as thrown exception.
95
+ *
96
+ * Returns an array of inspection state arrays.
97
+ *
98
+ * @see inspect for the inspection state array format.
99
+ *
100
+ * @param PromiseInterface[] $promises Traversable of promises to wait upon.
101
+ *
102
+ * @return array
103
+ */
104
+ public static function inspectAll($promises)
105
+ {
106
+ $results = [];
107
+ foreach ($promises as $key => $promise) {
108
+ $results[$key] = inspect($promise);
109
+ }
110
+
111
+ return $results;
112
+ }
113
+
114
+ /**
115
+ * Waits on all of the provided promises and returns the fulfilled values.
116
+ *
117
+ * Returns an array that contains the value of each promise (in the same
118
+ * order the promises were provided). An exception is thrown if any of the
119
+ * promises are rejected.
120
+ *
121
+ * @param iterable<PromiseInterface> $promises Iterable of PromiseInterface objects to wait on.
122
+ *
123
+ * @return array
124
+ *
125
+ * @throws \Exception on error
126
+ * @throws \Throwable on error in PHP >=7
127
+ */
128
+ public static function unwrap($promises)
129
+ {
130
+ $results = [];
131
+ foreach ($promises as $key => $promise) {
132
+ $results[$key] = $promise->wait();
133
+ }
134
+
135
+ return $results;
136
+ }
137
+
138
+ /**
139
+ * Given an array of promises, return a promise that is fulfilled when all
140
+ * the items in the array are fulfilled.
141
+ *
142
+ * The promise's fulfillment value is an array with fulfillment values at
143
+ * respective positions to the original array. If any promise in the array
144
+ * rejects, the returned promise is rejected with the rejection reason.
145
+ *
146
+ * @param mixed $promises Promises or values.
147
+ * @param bool $recursive If true, resolves new promises that might have been added to the stack during its own resolution.
148
+ *
149
+ * @return PromiseInterface
150
+ */
151
+ public static function all($promises, $recursive = false)
152
+ {
153
+ $results = [];
154
+ $promise = Each::of(
155
+ $promises,
156
+ function ($value, $idx) use (&$results) {
157
+ $results[$idx] = $value;
158
+ },
159
+ function ($reason, $idx, Promise $aggregate) {
160
+ $aggregate->reject($reason);
161
+ }
162
+ )->then(function () use (&$results) {
163
+ ksort($results);
164
+ return $results;
165
+ });
166
+
167
+ if (true === $recursive) {
168
+ $promise = $promise->then(function ($results) use ($recursive, &$promises) {
169
+ foreach ($promises as $promise) {
170
+ if (Is::pending($promise)) {
171
+ return self::all($promises, $recursive);
172
+ }
173
+ }
174
+ return $results;
175
+ });
176
+ }
177
+
178
+ return $promise;
179
+ }
180
+
181
+ /**
182
+ * Initiate a competitive race between multiple promises or values (values
183
+ * will become immediately fulfilled promises).
184
+ *
185
+ * When count amount of promises have been fulfilled, the returned promise
186
+ * is fulfilled with an array that contains the fulfillment values of the
187
+ * winners in order of resolution.
188
+ *
189
+ * This promise is rejected with a {@see AggregateException} if the number
190
+ * of fulfilled promises is less than the desired $count.
191
+ *
192
+ * @param int $count Total number of promises.
193
+ * @param mixed $promises Promises or values.
194
+ *
195
+ * @return PromiseInterface
196
+ */
197
+ public static function some($count, $promises)
198
+ {
199
+ $results = [];
200
+ $rejections = [];
201
+
202
+ return Each::of(
203
+ $promises,
204
+ function ($value, $idx, PromiseInterface $p) use (&$results, $count) {
205
+ if (Is::settled($p)) {
206
+ return;
207
+ }
208
+ $results[$idx] = $value;
209
+ if (count($results) >= $count) {
210
+ $p->resolve(null);
211
+ }
212
+ },
213
+ function ($reason) use (&$rejections) {
214
+ $rejections[] = $reason;
215
+ }
216
+ )->then(
217
+ function () use (&$results, &$rejections, $count) {
218
+ if (count($results) !== $count) {
219
+ throw new AggregateException(
220
+ 'Not enough promises to fulfill count',
221
+ $rejections
222
+ );
223
+ }
224
+ ksort($results);
225
+ return array_values($results);
226
+ }
227
+ );
228
+ }
229
+
230
+ /**
231
+ * Like some(), with 1 as count. However, if the promise fulfills, the
232
+ * fulfillment value is not an array of 1 but the value directly.
233
+ *
234
+ * @param mixed $promises Promises or values.
235
+ *
236
+ * @return PromiseInterface
237
+ */
238
+ public static function any($promises)
239
+ {
240
+ return self::some(1, $promises)->then(function ($values) {
241
+ return $values[0];
242
+ });
243
+ }
244
+
245
+ /**
246
+ * Returns a promise that is fulfilled when all of the provided promises have
247
+ * been fulfilled or rejected.
248
+ *
249
+ * The returned promise is fulfilled with an array of inspection state arrays.
250
+ *
251
+ * @see inspect for the inspection state array format.
252
+ *
253
+ * @param mixed $promises Promises or values.
254
+ *
255
+ * @return PromiseInterface
256
+ */
257
+ public static function settle($promises)
258
+ {
259
+ $results = [];
260
+
261
+ return Each::of(
262
+ $promises,
263
+ function ($value, $idx) use (&$results) {
264
+ $results[$idx] = ['state' => PromiseInterface::FULFILLED, 'value' => $value];
265
+ },
266
+ function ($reason, $idx) use (&$results) {
267
+ $results[$idx] = ['state' => PromiseInterface::REJECTED, 'reason' => $reason];
268
+ }
269
+ )->then(function () use (&$results) {
270
+ ksort($results);
271
+ return $results;
272
+ });
273
+ }
274
+ }
vendor/guzzlehttp/promises/src/functions.php ADDED
@@ -0,0 +1,363 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace GuzzleHttp\Promise;
4
+
5
+ /**
6
+ * Get the global task queue used for promise resolution.
7
+ *
8
+ * This task queue MUST be run in an event loop in order for promises to be
9
+ * settled asynchronously. It will be automatically run when synchronously
10
+ * waiting on a promise.
11
+ *
12
+ * <code>
13
+ * while ($eventLoop->isRunning()) {
14
+ * GuzzleHttp\Promise\queue()->run();
15
+ * }
16
+ * </code>
17
+ *
18
+ * @param TaskQueueInterface $assign Optionally specify a new queue instance.
19
+ *
20
+ * @return TaskQueueInterface
21
+ *
22
+ * @deprecated queue will be removed in guzzlehttp/promises:2.0. Use Utils::queue instead.
23
+ */
24
+ function queue(TaskQueueInterface $assign = null)
25
+ {
26
+ return Utils::queue($assign);
27
+ }
28
+
29
+ /**
30
+ * Adds a function to run in the task queue when it is next `run()` and returns
31
+ * a promise that is fulfilled or rejected with the result.
32
+ *
33
+ * @param callable $task Task function to run.
34
+ *
35
+ * @return PromiseInterface
36
+ *
37
+ * @deprecated task will be removed in guzzlehttp/promises:2.0. Use Utils::task instead.
38
+ */
39
+ function task(callable $task)
40
+ {
41
+ return Utils::task($task);
42
+ }
43
+
44
+ /**
45
+ * Creates a promise for a value if the value is not a promise.
46
+ *
47
+ * @param mixed $value Promise or value.
48
+ *
49
+ * @return PromiseInterface
50
+ *
51
+ * @deprecated promise_for will be removed in guzzlehttp/promises:2.0. Use Create::promiseFor instead.
52
+ */
53
+ function promise_for($value)
54
+ {
55
+ return Create::promiseFor($value);
56
+ }
57
+
58
+ /**
59
+ * Creates a rejected promise for a reason if the reason is not a promise. If
60
+ * the provided reason is a promise, then it is returned as-is.
61
+ *
62
+ * @param mixed $reason Promise or reason.
63
+ *
64
+ * @return PromiseInterface
65
+ *
66
+ * @deprecated rejection_for will be removed in guzzlehttp/promises:2.0. Use Create::rejectionFor instead.
67
+ */
68
+ function rejection_for($reason)
69
+ {
70
+ return Create::rejectionFor($reason);
71
+ }
72
+
73
+ /**
74
+ * Create an exception for a rejected promise value.
75
+ *
76
+ * @param mixed $reason
77
+ *
78
+ * @return \Exception|\Throwable
79
+ *
80
+ * @deprecated exception_for will be removed in guzzlehttp/promises:2.0. Use Create::exceptionFor instead.
81
+ */
82
+ function exception_for($reason)
83
+ {
84
+ return Create::exceptionFor($reason);
85
+ }
86
+
87
+ /**
88
+ * Returns an iterator for the given value.
89
+ *
90
+ * @param mixed $value
91
+ *
92
+ * @return \Iterator
93
+ *
94
+ * @deprecated iter_for will be removed in guzzlehttp/promises:2.0. Use Create::iterFor instead.
95
+ */
96
+ function iter_for($value)
97
+ {
98
+ return Create::iterFor($value);
99
+ }
100
+
101
+ /**
102
+ * Synchronously waits on a promise to resolve and returns an inspection state
103
+ * array.
104
+ *
105
+ * Returns a state associative array containing a "state" key mapping to a
106
+ * valid promise state. If the state of the promise is "fulfilled", the array
107
+ * will contain a "value" key mapping to the fulfilled value of the promise. If
108
+ * the promise is rejected, the array will contain a "reason" key mapping to
109
+ * the rejection reason of the promise.
110
+ *
111
+ * @param PromiseInterface $promise Promise or value.
112
+ *
113
+ * @return array
114
+ *
115
+ * @deprecated inspect will be removed in guzzlehttp/promises:2.0. Use Utils::inspect instead.
116
+ */
117
+ function inspect(PromiseInterface $promise)
118
+ {
119
+ return Utils::inspect($promise);
120
+ }
121
+
122
+ /**
123
+ * Waits on all of the provided promises, but does not unwrap rejected promises
124
+ * as thrown exception.
125
+ *
126
+ * Returns an array of inspection state arrays.
127
+ *
128
+ * @see inspect for the inspection state array format.
129
+ *
130
+ * @param PromiseInterface[] $promises Traversable of promises to wait upon.
131
+ *
132
+ * @return array
133
+ *
134
+ * @deprecated inspect will be removed in guzzlehttp/promises:2.0. Use Utils::inspectAll instead.
135
+ */
136
+ function inspect_all($promises)
137
+ {
138
+ return Utils::inspectAll($promises);
139
+ }
140
+
141
+ /**
142
+ * Waits on all of the provided promises and returns the fulfilled values.
143
+ *
144
+ * Returns an array that contains the value of each promise (in the same order
145
+ * the promises were provided). An exception is thrown if any of the promises
146
+ * are rejected.
147
+ *
148
+ * @param iterable<PromiseInterface> $promises Iterable of PromiseInterface objects to wait on.
149
+ *
150
+ * @return array
151
+ *
152
+ * @throws \Exception on error
153
+ * @throws \Throwable on error in PHP >=7
154
+ *
155
+ * @deprecated unwrap will be removed in guzzlehttp/promises:2.0. Use Utils::unwrap instead.
156
+ */
157
+ function unwrap($promises)
158
+ {
159
+ return Utils::unwrap($promises);
160
+ }
161
+
162
+ /**
163
+ * Given an array of promises, return a promise that is fulfilled when all the
164
+ * items in the array are fulfilled.
165
+ *
166
+ * The promise's fulfillment value is an array with fulfillment values at
167
+ * respective positions to the original array. If any promise in the array
168
+ * rejects, the returned promise is rejected with the rejection reason.
169
+ *
170
+ * @param mixed $promises Promises or values.
171
+ * @param bool $recursive If true, resolves new promises that might have been added to the stack during its own resolution.
172
+ *
173
+ * @return PromiseInterface
174
+ *
175
+ * @deprecated all will be removed in guzzlehttp/promises:2.0. Use Utils::all instead.
176
+ */
177
+ function all($promises, $recursive = false)
178
+ {
179
+ return Utils::all($promises, $recursive);
180
+ }
181
+
182
+ /**
183
+ * Initiate a competitive race between multiple promises or values (values will
184
+ * become immediately fulfilled promises).
185
+ *
186
+ * When count amount of promises have been fulfilled, the returned promise is
187
+ * fulfilled with an array that contains the fulfillment values of the winners
188
+ * in order of resolution.
189
+ *
190
+ * This promise is rejected with a {@see AggregateException} if the number of
191
+ * fulfilled promises is less than the desired $count.
192
+ *
193
+ * @param int $count Total number of promises.
194
+ * @param mixed $promises Promises or values.
195
+ *
196
+ * @return PromiseInterface
197
+ *
198
+ * @deprecated some will be removed in guzzlehttp/promises:2.0. Use Utils::some instead.
199
+ */
200
+ function some($count, $promises)
201
+ {
202
+ return Utils::some($count, $promises);
203
+ }
204
+
205
+ /**
206
+ * Like some(), with 1 as count. However, if the promise fulfills, the
207
+ * fulfillment value is not an array of 1 but the value directly.
208
+ *
209
+ * @param mixed $promises Promises or values.
210
+ *
211
+ * @return PromiseInterface
212
+ *
213
+ * @deprecated any will be removed in guzzlehttp/promises:2.0. Use Utils::any instead.
214
+ */
215
+ function any($promises)
216
+ {
217
+ return Utils::any($promises);
218
+ }
219
+
220
+ /**
221
+ * Returns a promise that is fulfilled when all of the provided promises have
222
+ * been fulfilled or rejected.
223
+ *
224
+ * The returned promise is fulfilled with an array of inspection state arrays.
225
+ *
226
+ * @see inspect for the inspection state array format.
227
+ *
228
+ * @param mixed $promises Promises or values.
229
+ *
230
+ * @return PromiseInterface
231
+ *
232
+ * @deprecated settle will be removed in guzzlehttp/promises:2.0. Use Utils::settle instead.
233
+ */
234
+ function settle($promises)
235
+ {
236
+ return Utils::settle($promises);
237
+ }
238
+
239
+ /**
240
+ * Given an iterator that yields promises or values, returns a promise that is
241
+ * fulfilled with a null value when the iterator has been consumed or the
242
+ * aggregate promise has been fulfilled or rejected.
243
+ *
244
+ * $onFulfilled is a function that accepts the fulfilled value, iterator index,
245
+ * and the aggregate promise. The callback can invoke any necessary side
246
+ * effects and choose to resolve or reject the aggregate if needed.
247
+ *
248
+ * $onRejected is a function that accepts the rejection reason, iterator index,
249
+ * and the aggregate promise. The callback can invoke any necessary side
250
+ * effects and choose to resolve or reject the aggregate if needed.
251
+ *
252
+ * @param mixed $iterable Iterator or array to iterate over.
253
+ * @param callable $onFulfilled
254
+ * @param callable $onRejected
255
+ *
256
+ * @return PromiseInterface
257
+ *
258
+ * @deprecated each will be removed in guzzlehttp/promises:2.0. Use Each::of instead.
259
+ */
260
+ function each(
261
+ $iterable,
262
+ callable $onFulfilled = null,
263
+ callable $onRejected = null
264
+ ) {
265
+ return Each::of($iterable, $onFulfilled, $onRejected);
266
+ }
267
+
268
+ /**
269
+ * Like each, but only allows a certain number of outstanding promises at any
270
+ * given time.
271
+ *
272
+ * $concurrency may be an integer or a function that accepts the number of
273
+ * pending promises and returns a numeric concurrency limit value to allow for
274
+ * dynamic a concurrency size.
275
+ *
276
+ * @param mixed $iterable
277
+ * @param int|callable $concurrency
278
+ * @param callable $onFulfilled
279
+ * @param callable $onRejected
280
+ *
281
+ * @return PromiseInterface
282
+ *
283
+ * @deprecated each_limit will be removed in guzzlehttp/promises:2.0. Use Each::ofLimit instead.
284
+ */
285
+ function each_limit(
286
+ $iterable,
287
+ $concurrency,
288
+ callable $onFulfilled = null,
289
+ callable $onRejected = null
290
+ ) {
291
+ return Each::ofLimit($iterable, $concurrency, $onFulfilled, $onRejected);
292
+ }
293
+
294
+ /**
295
+ * Like each_limit, but ensures that no promise in the given $iterable argument
296
+ * is rejected. If any promise is rejected, then the aggregate promise is
297
+ * rejected with the encountered rejection.
298
+ *
299
+ * @param mixed $iterable
300
+ * @param int|callable $concurrency
301
+ * @param callable $onFulfilled
302
+ *
303
+ * @return PromiseInterface
304
+ *
305
+ * @deprecated each_limit_all will be removed in guzzlehttp/promises:2.0. Use Each::ofLimitAll instead.
306
+ */
307
+ function each_limit_all(
308
+ $iterable,
309
+ $concurrency,
310
+ callable $onFulfilled = null
311
+ ) {
312
+ return Each::ofLimitAll($iterable, $concurrency, $onFulfilled);
313
+ }
314
+
315
+ /**
316
+ * Returns true if a promise is fulfilled.
317
+ *
318
+ * @return bool
319
+ *
320
+ * @deprecated is_fulfilled will be removed in guzzlehttp/promises:2.0. Use Is::fulfilled instead.
321
+ */
322
+ function is_fulfilled(PromiseInterface $promise)
323
+ {
324
+ return Is::fulfilled($promise);
325
+ }
326
+
327
+ /**
328
+ * Returns true if a promise is rejected.
329
+ *
330
+ * @return bool
331
+ *
332
+ * @deprecated is_rejected will be removed in guzzlehttp/promises:2.0. Use Is::rejected instead.
333
+ */
334
+ function is_rejected(PromiseInterface $promise)
335
+ {
336
+ return Is::rejected($promise);
337
+ }
338
+
339
+ /**
340
+ * Returns true if a promise is fulfilled or rejected.
341
+ *
342
+ * @return bool
343
+ *
344
+ * @deprecated is_settled will be removed in guzzlehttp/promises:2.0. Use Is::settled instead.
345
+ */
346
+ function is_settled(PromiseInterface $promise)
347
+ {
348
+ return Is::settled($promise);
349
+ }
350
+
351
+ /**
352
+ * Create a new coroutine.
353
+ *
354
+ * @see Coroutine
355
+ *
356
+ * @return PromiseInterface
357
+ *
358
+ * @deprecated coroutine will be removed in guzzlehttp/promises:2.0. Use Coroutine::of instead.
359
+ */
360
+ function coroutine(callable $generatorFn)
361
+ {
362
+ return Coroutine::of($generatorFn);
363
+ }
vendor/guzzlehttp/promises/src/functions_include.php ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+ <?php
2
+
3
+ // Don't redefine the functions if included multiple times.
4
+ if (!function_exists('GuzzleHttp\Promise\promise_for')) {
5
+ require __DIR__ . '/functions.php';
6
+ }
vendor/guzzlehttp/psr7/.php_cs.dist ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ $config = PhpCsFixer\Config::create()
4
+ ->setRiskyAllowed(true)
5
+ ->setRules([
6
+ '@PSR2' => true,
7
+ 'array_syntax' => ['syntax' => 'short'],
8
+ 'concat_space' => ['spacing' => 'one'],
9
+ 'declare_strict_types' => false,
10
+ 'final_static_access' => true,
11
+ 'fully_qualified_strict_types' => true,
12
+ 'header_comment' => false,
13
+ 'is_null' => ['use_yoda_style' => true],
14
+ 'list_syntax' => ['syntax' => 'long'],
15
+ 'lowercase_cast' => true,
16
+ 'magic_method_casing' => true,
17
+ 'modernize_types_casting' => true,
18
+ 'multiline_comment_opening_closing' => true,
19
+ 'no_alias_functions' => true,
20
+ 'no_alternative_syntax' => true,
21
+ 'no_blank_lines_after_phpdoc' => true,
22
+ 'no_empty_comment' => true,
23
+ 'no_empty_phpdoc' => true,
24
+ 'no_empty_statement' => true,
25
+ 'no_extra_blank_lines' => true,
26
+ 'no_leading_import_slash' => true,
27
+ 'no_trailing_comma_in_singleline_array' => true,
28
+ 'no_unset_cast' => true,
29
+ 'no_unused_imports' => true,
30
+ 'no_whitespace_in_blank_line' => true,
31
+ 'ordered_imports' => true,
32
+ 'php_unit_ordered_covers' => true,
33
+ 'php_unit_test_annotation' => ['style' => 'prefix'],
34
+ 'php_unit_test_case_static_method_calls' => ['call_type' => 'self'],
35
+ 'phpdoc_align' => ['align' => 'vertical'],
36
+ 'phpdoc_no_useless_inheritdoc' => true,
37
+ 'phpdoc_scalar' => true,
38
+ 'phpdoc_separation' => true,
39
+ 'phpdoc_single_line_var_spacing' => true,
40
+ 'phpdoc_trim' => true,
41
+ 'phpdoc_trim_consecutive_blank_line_separation' => true,
42
+ 'phpdoc_types' => true,
43
+ 'phpdoc_types_order' => ['null_adjustment' => 'always_last', 'sort_algorithm' => 'none'],
44
+ 'phpdoc_var_without_name' => true,
45
+ 'single_trait_insert_per_statement' => true,
46
+ 'standardize_not_equals' => true,
47
+ ])
48
+ ->setFinder(
49
+ PhpCsFixer\Finder::create()
50
+ ->in(__DIR__.'/src')
51
+ ->in(__DIR__.'/tests')
52
+ ->name('*.php')
53
+ )
54
+ ;
55
+
56
+ return $config;
vendor/guzzlehttp/psr7/LICENSE ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Copyright (c) 2015 Michael Dowling, https://github.com/mtdowling <mtdowling@gmail.com>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
vendor/guzzlehttp/psr7/src/AppendStream.php ADDED
@@ -0,0 +1,246 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace GuzzleHttp\Psr7;
4
+
5
+ use Psr\Http\Message\StreamInterface;
6
+
7
+ /**
8
+ * Reads from multiple streams, one after the other.
9
+ *
10
+ * This is a read-only stream decorator.
11
+ *
12
+ * @final
13
+ */
14
+ class AppendStream implements StreamInterface
15
+ {
16
+ /** @var StreamInterface[] Streams being decorated */
17
+ private $streams = [];
18
+
19
+ private $seekable = true;
20
+ private $current = 0;
21
+ private $pos = 0;
22
+
23
+ /**
24
+ * @param StreamInterface[] $streams Streams to decorate. Each stream must
25
+ * be readable.
26
+ */
27
+ public function __construct(array $streams = [])
28
+ {
29
+ foreach ($streams as $stream) {
30
+ $this->addStream($stream);
31
+ }
32
+ }
33
+
34
+ public function __toString()
35
+ {
36
+ try {
37
+ $this->rewind();
38
+ return $this->getContents();
39
+ } catch (\Exception $e) {
40
+ return '';
41
+ }
42
+ }
43
+
44
+ /**
45
+ * Add a stream to the AppendStream
46
+ *
47
+ * @param StreamInterface $stream Stream to append. Must be readable.
48
+ *
49
+ * @throws \InvalidArgumentException if the stream is not readable
50
+ */
51
+ public function addStream(StreamInterface $stream)
52
+ {
53
+ if (!$stream->isReadable()) {
54
+ throw new \InvalidArgumentException('Each stream must be readable');
55
+ }
56
+
57
+ // The stream is only seekable if all streams are seekable
58
+ if (!$stream->isSeekable()) {
59
+ $this->seekable = false;
60
+ }
61
+
62
+ $this->streams[] = $stream;
63
+ }
64
+
65
+ public function getContents()
66
+ {
67
+ return Utils::copyToString($this);
68
+ }
69
+
70
+ /**
71
+ * Closes each attached stream.
72
+ *
73
+ * {@inheritdoc}
74
+ */
75
+ public function close()
76
+ {
77
+ $this->pos = $this->current = 0;
78
+ $this->seekable = true;
79
+
80
+ foreach ($this->streams as $stream) {
81
+ $stream->close();
82
+ }
83
+
84
+ $this->streams = [];
85
+ }
86
+
87
+ /**
88
+ * Detaches each attached stream.
89
+ *
90
+ * Returns null as it's not clear which underlying stream resource to return.
91
+ *
92
+ * {@inheritdoc}
93
+ */
94
+ public function detach()
95
+ {
96
+ $this->pos = $this->current = 0;
97
+ $this->seekable = true;
98
+
99
+ foreach ($this->streams as $stream) {
100
+ $stream->detach();
101
+ }
102
+
103
+ $this->streams = [];
104
+
105
+ return null;
106
+ }
107
+
108
+ public function tell()
109
+ {
110
+ return $this->pos;
111
+ }
112
+
113
+ /**
114
+ * Tries to calculate the size by adding the size of each stream.
115
+ *
116
+ * If any of the streams do not return a valid number, then the size of the
117
+ * append stream cannot be determined and null is returned.
118
+ *
119
+ * {@inheritdoc}
120
+ */
121
+ public function getSize()
122
+ {
123
+ $size = 0;
124
+
125
+ foreach ($this->streams as $stream) {
126
+ $s = $stream->getSize();
127
+ if ($s === null) {
128
+ return null;
129
+ }
130
+ $size += $s;
131
+ }
132
+
133
+ return $size;
134
+ }
135
+
136
+ public function eof()
137
+ {
138
+ return !$this->streams ||
139
+ ($this->current >= count($this->streams) - 1 &&
140
+ $this->streams[$this->current]->eof());
141
+ }
142
+
143
+ public function rewind()
144
+ {
145
+ $this->seek(0);
146
+ }
147
+
148
+ /**
149
+ * Attempts to seek to the given position. Only supports SEEK_SET.
150
+ *
151
+ * {@inheritdoc}
152
+ */
153
+ public function seek($offset, $whence = SEEK_SET)
154
+ {
155
+ if (!$this->seekable) {
156
+ throw new \RuntimeException('This AppendStream is not seekable');
157
+ } elseif ($whence !== SEEK_SET) {
158
+ throw new \RuntimeException('The AppendStream can only seek with SEEK_SET');
159
+ }
160
+
161
+ $this->pos = $this->current = 0;
162
+
163
+ // Rewind each stream
164
+ foreach ($this->streams as $i => $stream) {
165
+ try {
166
+ $stream->rewind();
167
+ } catch (\Exception $e) {
168
+ throw new \RuntimeException('Unable to seek stream '
169
+ . $i . ' of the AppendStream', 0, $e);
170
+ }
171
+ }
172
+
173
+ // Seek to the actual position by reading from each stream
174
+ while ($this->pos < $offset && !$this->eof()) {
175
+ $result = $this->read(min(8096, $offset - $this->pos));
176
+ if ($result === '') {
177
+ break;
178
+ }
179
+ }
180
+ }
181
+
182
+ /**
183
+ * Reads from all of the appended streams until the length is met or EOF.
184
+ *
185
+ * {@inheritdoc}
186
+ */
187
+ public function read($length)
188
+ {
189
+ $buffer = '';
190
+ $total = count($this->streams) - 1;
191
+ $remaining = $length;
192
+ $progressToNext = false;
193
+
194
+ while ($remaining > 0) {
195
+
196
+ // Progress to the next stream if needed.
197
+ if ($progressToNext || $this->streams[$this->current]->eof()) {
198
+ $progressToNext = false;
199
+ if ($this->current === $total) {
200
+ break;
201
+ }
202
+ $this->current++;
203
+ }
204
+
205
+ $result = $this->streams[$this->current]->read($remaining);
206
+
207
+ // Using a loose comparison here to match on '', false, and null
208
+ if ($result == null) {
209
+ $progressToNext = true;
210
+ continue;
211
+ }
212
+
213
+ $buffer .= $result;
214
+ $remaining = $length - strlen($buffer);
215
+ }
216
+
217
+ $this->pos += strlen($buffer);
218
+
219
+ return $buffer;
220
+ }
221
+
222
+ public function isReadable()
223
+ {
224
+ return true;
225
+ }
226
+
227
+ public function isWritable()
228
+ {
229
+ return false;
230
+ }
231
+
232
+ public function isSeekable()
233
+ {
234
+ return $this->seekable;
235
+ }
236
+
237
+ public function write($string)
238
+ {
239
+ throw new \RuntimeException('Cannot write to an AppendStream');
240
+ }
241
+
242
+ public function getMetadata($key = null)
243
+ {
244
+ return $key ? null : [];
245
+ }
246
+ }
vendor/guzzlehttp/psr7/src/BufferStream.php ADDED
@@ -0,0 +1,142 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace GuzzleHttp\Psr7;
4
+
5
+ use Psr\Http\Message\StreamInterface;
6
+
7
+ /**
8
+ * Provides a buffer stream that can be written to to fill a buffer, and read
9
+ * from to remove bytes from the buffer.
10
+ *
11
+ * This stream returns a "hwm" metadata value that tells upstream consumers
12
+ * what the configured high water mark of the stream is, or the maximum
13
+ * preferred size of the buffer.
14
+ *
15
+ * @final
16
+ */
17
+ class BufferStream implements StreamInterface
18
+ {
19
+ private $hwm;
20
+ private $buffer = '';
21
+
22
+ /**
23
+ * @param int $hwm High water mark, representing the preferred maximum
24
+ * buffer size. If the size of the buffer exceeds the high
25
+ * water mark, then calls to write will continue to succeed
26
+ * but will return false to inform writers to slow down
27
+ * until the buffer has been drained by reading from it.
28
+ */
29
+ public function __construct($hwm = 16384)
30
+ {
31
+ $this->hwm = $hwm;
32
+ }
33
+
34
+ public function __toString()
35
+ {
36
+ return $this->getContents();
37
+ }
38
+
39
+ public function getContents()
40
+ {
41
+ $buffer = $this->buffer;
42
+ $this->buffer = '';
43
+
44
+ return $buffer;
45
+ }
46
+
47
+ public function close()
48
+ {
49
+ $this->buffer = '';
50
+ }
51
+
52
+ public function detach()
53
+ {
54
+ $this->close();
55
+
56
+ return null;
57
+ }
58
+
59
+ public function getSize()
60
+ {
61
+ return strlen($this->buffer);
62
+ }
63
+
64
+ public function isReadable()
65
+ {
66
+ return true;
67
+ }
68
+
69
+ public function isWritable()
70
+ {
71
+ return true;
72
+ }
73
+
74
+ public function isSeekable()
75
+ {
76
+ return false;
77
+ }
78
+
79
+ public function rewind()
80
+ {
81
+ $this->seek(0);
82
+ }
83
+
84
+ public function seek($offset, $whence = SEEK_SET)
85
+ {
86
+ throw new \RuntimeException('Cannot seek a BufferStream');
87
+ }
88
+
89
+ public function eof()
90
+ {
91
+ return strlen($this->buffer) === 0;
92
+ }
93
+
94
+ public function tell()
95
+ {
96
+ throw new \RuntimeException('Cannot determine the position of a BufferStream');
97
+ }
98
+
99
+ /**
100
+ * Reads data from the buffer.
101
+ */
102
+ public function read($length)
103
+ {
104
+ $currentLength = strlen($this->buffer);
105
+
106
+ if ($length >= $currentLength) {
107
+ // No need to slice the buffer because we don't have enough data.
108
+ $result = $this->buffer;
109
+ $this->buffer = '';
110
+ } else {
111
+ // Slice up the result to provide a subset of the buffer.
112
+ $result = substr($this->buffer, 0, $length);
113
+ $this->buffer = substr($this->buffer, $length);
114
+ }
115
+
116
+ return $result;
117
+ }
118
+
119
+ /**
120
+ * Writes data to the buffer.
121
+ */
122
+ public function write($string)
123
+ {
124
+ $this->buffer .= $string;
125
+
126
+ // TODO: What should happen here?
127
+ if (strlen($this->buffer) >= $this->hwm) {
128
+ return false;
129
+ }
130
+
131
+ return strlen($string);
132
+ }
133
+
134
+ public function getMetadata($key = null)
135
+ {
136
+ if ($key == 'hwm') {
137
+ return $this->hwm;
138
+ }
139
+
140
+ return $key ? null : [];
141
+ }
142
+ }
vendor/guzzlehttp/psr7/src/CachingStream.php ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace GuzzleHttp\Psr7;
4
+
5
+ use Psr\Http\Message\StreamInterface;
6
+
7
+ /**
8
+ * Stream decorator that can cache previously read bytes from a sequentially
9
+ * read stream.
10
+ *
11
+ * @final
12
+ */
13
+ class CachingStream implements StreamInterface
14
+ {
15
+ use StreamDecoratorTrait;
16
+
17
+ /** @var StreamInterface Stream being wrapped */
18
+ private $remoteStream;
19
+
20
+ /** @var int Number of bytes to skip reading due to a write on the buffer */
21
+ private $skipReadBytes = 0;
22
+
23
+ /**
24
+ * We will treat the buffer object as the body of the stream
25
+ *
26
+ * @param StreamInterface $stream Stream to cache. The cursor is assumed to be at the beginning of the stream.
27
+ * @param StreamInterface $target Optionally specify where data is cached
28
+ */
29
+ public function __construct(
30
+ StreamInterface $stream,
31
+ StreamInterface $target = null
32
+ ) {
33
+ $this->remoteStream = $stream;
34
+ $this->stream = $target ?: new Stream(Utils::tryFopen('php://temp', 'r+'));
35
+ }
36
+
37
+ public function getSize()
38
+ {
39
+ return max($this->stream->getSize(), $this->remoteStream->getSize());
40
+ }
41
+
42
+ public function rewind()
43
+ {
44
+ $this->seek(0);
45
+ }
46
+
47
+ public function seek($offset, $whence = SEEK_SET)
48
+ {
49
+ if ($whence == SEEK_SET) {
50
+ $byte = $offset;
51
+ } elseif ($whence == SEEK_CUR) {
52
+ $byte = $offset + $this->tell();
53
+ } elseif ($whence == SEEK_END) {
54
+ $size = $this->remoteStream->getSize();
55
+ if ($size === null) {
56
+ $size = $this->cacheEntireStream();
57
+ }
58
+ $byte = $size + $offset;
59
+ } else {
60
+ throw new \InvalidArgumentException('Invalid whence');
61
+ }
62
+
63
+ $diff = $byte - $this->stream->getSize();
64
+
65
+ if ($diff > 0) {
66
+ // Read the remoteStream until we have read in at least the amount
67
+ // of bytes requested, or we reach the end of the file.
68
+ while ($diff > 0 && !$this->remoteStream->eof()) {
69
+ $this->read($diff);
70
+ $diff = $byte - $this->stream->getSize();
71
+ }
72
+ } else {
73
+ // We can just do a normal seek since we've already seen this byte.
74
+ $this->stream->seek($byte);
75
+ }
76
+ }
77
+
78
+ public function read($length)
79
+ {
80
+ // Perform a regular read on any previously read data from the buffer
81
+ $data = $this->stream->read($length);
82
+ $remaining = $length - strlen($data);
83
+
84
+ // More data was requested so read from the remote stream
85
+ if ($remaining) {
86
+ // If data was written to the buffer in a position that would have
87
+ // been filled from the remote stream, then we must skip bytes on
88
+ // the remote stream to emulate overwriting bytes from that
89
+ // position. This mimics the behavior of other PHP stream wrappers.
90
+ $remoteData = $this->remoteStream->read(
91
+ $remaining + $this->skipReadBytes
92
+ );
93
+
94
+ if ($this->skipReadBytes) {
95
+ $len = strlen($remoteData);
96
+ $remoteData = substr($remoteData, $this->skipReadBytes);
97
+ $this->skipReadBytes = max(0, $this->skipReadBytes - $len);
98
+ }
99
+
100
+ $data .= $remoteData;
101
+ $this->stream->write($remoteData);
102
+ }
103
+
104
+ return $data;
105
+ }
106
+
107
+ public function write($string)
108
+ {
109
+ // When appending to the end of the currently read stream, you'll want
110
+ // to skip bytes from being read from the remote stream to emulate
111
+ // other stream wrappers. Basically replacing bytes of data of a fixed
112
+ // length.
113
+ $overflow = (strlen($string) + $this->tell()) - $this->remoteStream->tell();
114
+ if ($overflow > 0) {
115
+ $this->skipReadBytes += $overflow;
116
+ }
117
+
118
+ return $this->stream->write($string);
119
+ }
120
+
121
+ public function eof()
122
+ {
123
+ return $this->stream->eof() && $this->remoteStream->eof();
124
+ }
125
+
126
+ /**
127
+ * Close both the remote stream and buffer stream
128
+ */
129
+ public function close()
130
+ {
131
+ $this->remoteStream->close() && $this->stream->close();
132
+ }
133
+
134
+ private function cacheEntireStream()
135
+ {
136
+ $target = new FnStream(['write' => 'strlen']);
137
+ Utils::copyToStream($this, $target);
138
+
139
+ return $this->tell();
140
+ }
141
+ }
vendor/guzzlehttp/psr7/src/DroppingStream.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace GuzzleHttp\Psr7;
4
+
5
+ use Psr\Http\Message\StreamInterface;
6
+
7
+ /**
8
+ * Stream decorator that begins dropping data once the size of the underlying
9
+ * stream becomes too full.
10
+ *
11
+ * @final
12
+ */
13
+ class DroppingStream implements StreamInterface
14
+ {
15
+ use StreamDecoratorTrait;
16
+
17
+ private $maxLength;
18
+
19
+ /**
20
+ * @param StreamInterface $stream Underlying stream to decorate.
21
+ * @param int $maxLength Maximum size before dropping data.
22
+ */
23
+ public function __construct(StreamInterface $stream, $maxLength)
24
+ {
25
+ $this->stream = $stream;
26
+ $this->maxLength = $maxLength;
27
+ }
28
+
29
+ public function write($string)
30
+ {
31
+ $diff = $this->maxLength - $this->stream->getSize();
32
+
33
+ // Begin returning 0 when the underlying stream is too large.
34
+ if ($diff <= 0) {
35
+ return 0;
36
+ }
37
+
38
+ // Write the stream or a subset of the stream if needed.
39
+ if (strlen($string) < $diff) {
40
+ return $this->stream->write($string);
41
+ }
42
+
43
+ return $this->stream->write(substr($string, 0, $diff));
44
+ }
45
+ }
vendor/guzzlehttp/psr7/src/FnStream.php ADDED
@@ -0,0 +1,163 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ namespace GuzzleHttp\Psr7;
4
+
5
+ use Psr\Http\Message\StreamInterface;
6
+
7
+ /**
8
+ * Compose stream implementations based on a hash of functions.
9
+ *
10
+ * Allows for easy testing and extension of a provided stream without needing
11
+ * to create a concrete class for a simple extension point.
12
+ *
13
+ * @final
14
+ */
15
+ class FnStream implements StreamInterface
16
+ {
17
+ /** @var array */
18
+ private $methods;
19
+
20
+ /** @var array Methods that must be implemented in the given array */
21
+ private static $slots = ['__toString', 'close', 'detach', 'rewind',
22
+ 'getSize', 'tell', 'eof', 'isSeekable', 'seek', 'isWritable', 'write',
23
+ 'isReadable', 'read', 'getContents', 'getMetadata'];
24
+
25
+ /**
26
+ * @param array $methods Hash of method name to a callable.
27
+ */
28
+ public function __construct(array $methods)
29
+ {
30
+ $this->methods = $methods;
31
+
32
+ // Create the fu