You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

181 lines
5.7 KiB

  1. /*!
  2. * Copyright (c) 2015, Salesforce.com, Inc.
  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. * 1. Redistributions of source code must retain the above copyright notice,
  9. * this list of conditions and the following disclaimer.
  10. *
  11. * 2. Redistributions in binary form must reproduce the above copyright notice,
  12. * this list of conditions and the following disclaimer in the documentation
  13. * and/or other materials provided with the distribution.
  14. *
  15. * 3. Neither the name of Salesforce.com nor the names of its contributors may
  16. * be used to endorse or promote products derived from this software without
  17. * specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  20. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  21. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  22. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
  23. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  24. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  25. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  26. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  27. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  28. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  29. * POSSIBILITY OF SUCH DAMAGE.
  30. */
  31. 'use strict';
  32. var Store = require('./store').Store;
  33. var permuteDomain = require('./permuteDomain').permuteDomain;
  34. var pathMatch = require('./pathMatch').pathMatch;
  35. var util = require('util');
  36. function MemoryCookieStore() {
  37. Store.call(this);
  38. this.idx = {};
  39. }
  40. util.inherits(MemoryCookieStore, Store);
  41. exports.MemoryCookieStore = MemoryCookieStore;
  42. MemoryCookieStore.prototype.idx = null;
  43. // Since it's just a struct in RAM, this Store is synchronous
  44. MemoryCookieStore.prototype.synchronous = true;
  45. // force a default depth:
  46. MemoryCookieStore.prototype.inspect = function() {
  47. return "{ idx: "+util.inspect(this.idx, false, 2)+' }';
  48. };
  49. // Use the new custom inspection symbol to add the custom inspect function if
  50. // available.
  51. if (util.inspect.custom) {
  52. MemoryCookieStore.prototype[util.inspect.custom] = MemoryCookieStore.prototype.inspect;
  53. }
  54. MemoryCookieStore.prototype.findCookie = function(domain, path, key, cb) {
  55. if (!this.idx[domain]) {
  56. return cb(null,undefined);
  57. }
  58. if (!this.idx[domain][path]) {
  59. return cb(null,undefined);
  60. }
  61. return cb(null,this.idx[domain][path][key]||null);
  62. };
  63. MemoryCookieStore.prototype.findCookies = function(domain, path, cb) {
  64. var results = [];
  65. if (!domain) {
  66. return cb(null,[]);
  67. }
  68. var pathMatcher;
  69. if (!path) {
  70. // null means "all paths"
  71. pathMatcher = function matchAll(domainIndex) {
  72. for (var curPath in domainIndex) {
  73. var pathIndex = domainIndex[curPath];
  74. for (var key in pathIndex) {
  75. results.push(pathIndex[key]);
  76. }
  77. }
  78. };
  79. } else {
  80. pathMatcher = function matchRFC(domainIndex) {
  81. //NOTE: we should use path-match algorithm from S5.1.4 here
  82. //(see : https://github.com/ChromiumWebApps/chromium/blob/b3d3b4da8bb94c1b2e061600df106d590fda3620/net/cookies/canonical_cookie.cc#L299)
  83. Object.keys(domainIndex).forEach(function (cookiePath) {
  84. if (pathMatch(path, cookiePath)) {
  85. var pathIndex = domainIndex[cookiePath];
  86. for (var key in pathIndex) {
  87. results.push(pathIndex[key]);
  88. }
  89. }
  90. });
  91. };
  92. }
  93. var domains = permuteDomain(domain) || [domain];
  94. var idx = this.idx;
  95. domains.forEach(function(curDomain) {
  96. var domainIndex = idx[curDomain];
  97. if (!domainIndex) {
  98. return;
  99. }
  100. pathMatcher(domainIndex);
  101. });
  102. cb(null,results);
  103. };
  104. MemoryCookieStore.prototype.putCookie = function(cookie, cb) {
  105. if (!this.idx[cookie.domain]) {
  106. this.idx[cookie.domain] = {};
  107. }
  108. if (!this.idx[cookie.domain][cookie.path]) {
  109. this.idx[cookie.domain][cookie.path] = {};
  110. }
  111. this.idx[cookie.domain][cookie.path][cookie.key] = cookie;
  112. cb(null);
  113. };
  114. MemoryCookieStore.prototype.updateCookie = function(oldCookie, newCookie, cb) {
  115. // updateCookie() may avoid updating cookies that are identical. For example,
  116. // lastAccessed may not be important to some stores and an equality
  117. // comparison could exclude that field.
  118. this.putCookie(newCookie,cb);
  119. };
  120. MemoryCookieStore.prototype.removeCookie = function(domain, path, key, cb) {
  121. if (this.idx[domain] && this.idx[domain][path] && this.idx[domain][path][key]) {
  122. delete this.idx[domain][path][key];
  123. }
  124. cb(null);
  125. };
  126. MemoryCookieStore.prototype.removeCookies = function(domain, path, cb) {
  127. if (this.idx[domain]) {
  128. if (path) {
  129. delete this.idx[domain][path];
  130. } else {
  131. delete this.idx[domain];
  132. }
  133. }
  134. return cb(null);
  135. };
  136. MemoryCookieStore.prototype.removeAllCookies = function(cb) {
  137. this.idx = {};
  138. return cb(null);
  139. }
  140. MemoryCookieStore.prototype.getAllCookies = function(cb) {
  141. var cookies = [];
  142. var idx = this.idx;
  143. var domains = Object.keys(idx);
  144. domains.forEach(function(domain) {
  145. var paths = Object.keys(idx[domain]);
  146. paths.forEach(function(path) {
  147. var keys = Object.keys(idx[domain][path]);
  148. keys.forEach(function(key) {
  149. if (key !== null) {
  150. cookies.push(idx[domain][path][key]);
  151. }
  152. });
  153. });
  154. });
  155. // Sort by creationIndex so deserializing retains the creation order.
  156. // When implementing your own store, this SHOULD retain the order too
  157. cookies.sort(function(a,b) {
  158. return (a.creationIndex||0) - (b.creationIndex||0);
  159. });
  160. cb(null, cookies);
  161. };