PageRenderTime 27ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/api/vendor/guzzlehttp/guzzle/src/Cookie/CookieJar.php

https://gitlab.com/x33n/respond
PHP | 248 lines | 177 code | 28 blank | 43 comment | 25 complexity | 2981ed1414b29b66426eece64865c3ab MD5 | raw file
  1. <?php
  2. namespace GuzzleHttp\Cookie;
  3. use GuzzleHttp\Message\RequestInterface;
  4. use GuzzleHttp\Message\ResponseInterface;
  5. use GuzzleHttp\ToArrayInterface;
  6. /**
  7. * Cookie jar that stores cookies an an array
  8. */
  9. class CookieJar implements CookieJarInterface, ToArrayInterface
  10. {
  11. /** @var SetCookie[] Loaded cookie data */
  12. private $cookies = [];
  13. /** @var bool */
  14. private $strictMode;
  15. /**
  16. * @param bool $strictMode Set to true to throw exceptions when invalid
  17. * cookies are added to the cookie jar.
  18. * @param array $cookieArray Array of SetCookie objects or a hash of arrays
  19. * that can be used with the SetCookie constructor
  20. */
  21. public function __construct($strictMode = false, $cookieArray = [])
  22. {
  23. $this->strictMode = $strictMode;
  24. foreach ($cookieArray as $cookie) {
  25. if (!($cookie instanceof SetCookie)) {
  26. $cookie = new SetCookie($cookie);
  27. }
  28. $this->setCookie($cookie);
  29. }
  30. }
  31. /**
  32. * Create a new Cookie jar from an associative array and domain.
  33. *
  34. * @param array $cookies Cookies to create the jar from
  35. * @param string $domain Domain to set the cookies to
  36. *
  37. * @return self
  38. */
  39. public static function fromArray(array $cookies, $domain)
  40. {
  41. $cookieJar = new self();
  42. foreach ($cookies as $name => $value) {
  43. $cookieJar->setCookie(new SetCookie([
  44. 'Domain' => $domain,
  45. 'Name' => $name,
  46. 'Value' => $value,
  47. 'Discard' => true
  48. ]));
  49. }
  50. return $cookieJar;
  51. }
  52. /**
  53. * Quote the cookie value if it is not already quoted and it contains
  54. * problematic characters.
  55. *
  56. * @param string $value Value that may or may not need to be quoted
  57. *
  58. * @return string
  59. */
  60. public static function getCookieValue($value)
  61. {
  62. if (substr($value, 0, 1) !== '"' &&
  63. substr($value, -1, 1) !== '"' &&
  64. strpbrk($value, ';,')
  65. ) {
  66. $value = '"' . $value . '"';
  67. }
  68. return $value;
  69. }
  70. public function toArray()
  71. {
  72. return array_map(function (SetCookie $cookie) {
  73. return $cookie->toArray();
  74. }, $this->getIterator()->getArrayCopy());
  75. }
  76. public function clear($domain = null, $path = null, $name = null)
  77. {
  78. if (!$domain) {
  79. $this->cookies = [];
  80. return;
  81. } elseif (!$path) {
  82. $this->cookies = array_filter(
  83. $this->cookies,
  84. function (SetCookie $cookie) use ($path, $domain) {
  85. return !$cookie->matchesDomain($domain);
  86. }
  87. );
  88. } elseif (!$name) {
  89. $this->cookies = array_filter(
  90. $this->cookies,
  91. function (SetCookie $cookie) use ($path, $domain) {
  92. return !($cookie->matchesPath($path) &&
  93. $cookie->matchesDomain($domain));
  94. }
  95. );
  96. } else {
  97. $this->cookies = array_filter(
  98. $this->cookies,
  99. function (SetCookie $cookie) use ($path, $domain, $name) {
  100. return !($cookie->getName() == $name &&
  101. $cookie->matchesPath($path) &&
  102. $cookie->matchesDomain($domain));
  103. }
  104. );
  105. }
  106. }
  107. public function clearSessionCookies()
  108. {
  109. $this->cookies = array_filter(
  110. $this->cookies,
  111. function (SetCookie $cookie) {
  112. return !$cookie->getDiscard() && $cookie->getExpires();
  113. }
  114. );
  115. }
  116. public function setCookie(SetCookie $cookie)
  117. {
  118. // Only allow cookies with set and valid domain, name, value
  119. $result = $cookie->validate();
  120. if ($result !== true) {
  121. if ($this->strictMode) {
  122. throw new \RuntimeException('Invalid cookie: ' . $result);
  123. } else {
  124. $this->removeCookieIfEmpty($cookie);
  125. return false;
  126. }
  127. }
  128. // Resolve conflicts with previously set cookies
  129. foreach ($this->cookies as $i => $c) {
  130. // Two cookies are identical, when their path, and domain are
  131. // identical.
  132. if ($c->getPath() != $cookie->getPath() ||
  133. $c->getDomain() != $cookie->getDomain() ||
  134. $c->getName() != $cookie->getName()
  135. ) {
  136. continue;
  137. }
  138. // The previously set cookie is a discard cookie and this one is
  139. // not so allow the new cookie to be set
  140. if (!$cookie->getDiscard() && $c->getDiscard()) {
  141. unset($this->cookies[$i]);
  142. continue;
  143. }
  144. // If the new cookie's expiration is further into the future, then
  145. // replace the old cookie
  146. if ($cookie->getExpires() > $c->getExpires()) {
  147. unset($this->cookies[$i]);
  148. continue;
  149. }
  150. // If the value has changed, we better change it
  151. if ($cookie->getValue() !== $c->getValue()) {
  152. unset($this->cookies[$i]);
  153. continue;
  154. }
  155. // The cookie exists, so no need to continue
  156. return false;
  157. }
  158. $this->cookies[] = $cookie;
  159. return true;
  160. }
  161. public function count()
  162. {
  163. return count($this->cookies);
  164. }
  165. public function getIterator()
  166. {
  167. return new \ArrayIterator(array_values($this->cookies));
  168. }
  169. public function extractCookies(
  170. RequestInterface $request,
  171. ResponseInterface $response
  172. ) {
  173. if ($cookieHeader = $response->getHeaderAsArray('Set-Cookie')) {
  174. foreach ($cookieHeader as $cookie) {
  175. $sc = SetCookie::fromString($cookie);
  176. if (!$sc->getDomain()) {
  177. $sc->setDomain($request->getHost());
  178. }
  179. $this->setCookie($sc);
  180. }
  181. }
  182. }
  183. public function addCookieHeader(RequestInterface $request)
  184. {
  185. $values = [];
  186. $scheme = $request->getScheme();
  187. $host = $request->getHost();
  188. $path = $request->getPath();
  189. foreach ($this->cookies as $cookie) {
  190. if ($cookie->matchesPath($path) &&
  191. $cookie->matchesDomain($host) &&
  192. !$cookie->isExpired() &&
  193. (!$cookie->getSecure() || $scheme == 'https')
  194. ) {
  195. $values[] = $cookie->getName() . '='
  196. . self::getCookieValue($cookie->getValue());
  197. }
  198. }
  199. if ($values) {
  200. $request->setHeader('Cookie', implode('; ', $values));
  201. }
  202. }
  203. /**
  204. * If a cookie already exists and the server asks to set it again with a
  205. * null value, the cookie must be deleted.
  206. *
  207. * @param SetCookie $cookie
  208. */
  209. private function removeCookieIfEmpty(SetCookie $cookie)
  210. {
  211. $cookieValue = $cookie->getValue();
  212. if ($cookieValue === null || $cookieValue === '') {
  213. $this->clear(
  214. $cookie->getDomain(),
  215. $cookie->getPath(),
  216. $cookie->getName()
  217. );
  218. }
  219. }
  220. }