evercookie 0.0.6 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. checksums.yaml +7 -0
  2. data/README.rdoc +17 -7
  3. data/app/assets/javascripts/evercookie/evercookie.js.erb +1034 -644
  4. data/config/routes.rb +2 -0
  5. data/lib/evercookie.rb +5 -0
  6. data/lib/evercookie/controller.rb +19 -1
  7. data/lib/evercookie/version.rb +1 -1
  8. data/test/dummy/config/environments/production.rb +2 -2
  9. data/test/dummy/config/initializers/evercookie.rb +6 -6
  10. data/test/dummy/db/development.sqlite3 +0 -0
  11. data/test/dummy/db/production.sqlite3 +0 -0
  12. data/test/dummy/log/development.log +7509 -27817
  13. data/test/dummy/log/production.log +869 -0
  14. data/test/dummy/log/test.log +876 -936
  15. data/test/dummy/tmp/cache/assets/{D45/3C0/sprockets%2Fd45fb0f5f994f0c125db5e026ee65258 → CA6/C50/sprockets%2F1ff1b670b38042f5c89026631c36fa33} +0 -0
  16. data/test/dummy/tmp/cache/assets/CD8/370/sprockets%2F357970feca3ac29060c1e3861e2c0953 +0 -0
  17. data/test/dummy/tmp/cache/assets/CE7/B90/sprockets%2F09c6831dd77d079a5a778b0d0744ee16 +0 -0
  18. data/test/dummy/tmp/cache/assets/CEC/FA0/sprockets%2Fcee8c6b09c33d2b276753e959712724e +0 -0
  19. data/test/dummy/tmp/cache/assets/D04/370/sprockets%2F0bfdc3134b37668ae9a63c753ef05021 +0 -0
  20. data/test/dummy/tmp/cache/assets/D19/B00/sprockets%2F28c67ae04b83f4f76d461c789d1236ad +0 -0
  21. data/test/dummy/tmp/cache/assets/D32/A10/sprockets%2F13fe41fee1fe35b49d145bcc06610705 +0 -0
  22. data/test/dummy/tmp/cache/assets/D45/590/sprockets%2F3e0f6f496cd38bd4ea06614f7e10399a +0 -0
  23. data/test/dummy/tmp/cache/assets/D4E/1B0/sprockets%2Ff7cbd26ba1d28d48de824f0e94586655 +0 -0
  24. data/test/dummy/tmp/cache/assets/D58/BF0/sprockets%2Fd2d743676d256ff903f78df59b43c7ec +0 -0
  25. data/test/dummy/tmp/cache/assets/D5A/EA0/sprockets%2Fd771ace226fc8215a3572e0aa35bb0d6 +0 -0
  26. data/test/dummy/tmp/cache/assets/D70/2D0/sprockets%2F2c853768baf811357d81d41bdfd05dcf +0 -0
  27. data/test/dummy/tmp/cache/assets/D84/180/sprockets%2F71efedfb555fe6a74750e5d579d363d5 +0 -0
  28. data/test/dummy/tmp/cache/assets/D8C/A10/sprockets%2Ffc7201c6cbef32453aa4175c520c8eae +0 -0
  29. data/test/dummy/tmp/cache/assets/D93/360/sprockets%2Fdf600f50f002512c95d93bcfbab891ed +0 -0
  30. data/test/dummy/tmp/cache/assets/DB2/E70/sprockets%2Fa25c858be7f39b1ce6854eb93ba77ef5 +0 -0
  31. data/test/dummy/tmp/cache/assets/DDC/400/sprockets%2Fcffd775d018f68ce5dba1ee0d951a994 +0 -0
  32. data/test/dummy/tmp/cache/assets/{D70/D10/sprockets%2Fa0d37ff489ed0857f72233f5cb0b9c0b → DDF/EE0/sprockets%2F0b91ee26fcc3a08f74edf9ade38787e4} +0 -0
  33. data/test/dummy/tmp/cache/assets/E04/890/sprockets%2F2f5173deea6c795b8fdde723bb4b63af +0 -0
  34. data/test/dummy4/config/initializers/evercookie.rb +6 -6
  35. data/test/dummy4/db/development.sqlite3 +0 -0
  36. data/test/dummy4/log/development.log +773 -0
  37. data/test/dummy4/log/production.log +0 -0
  38. data/test/dummy4/tmp/cache/assets/development/sprockets/09c6831dd77d079a5a778b0d0744ee16 +0 -0
  39. data/test/dummy4/tmp/cache/assets/development/sprockets/0b91ee26fcc3a08f74edf9ade38787e4 +0 -0
  40. data/test/dummy4/tmp/cache/assets/development/sprockets/0bfdc3134b37668ae9a63c753ef05021 +0 -0
  41. data/test/dummy4/tmp/cache/assets/development/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
  42. data/test/dummy4/tmp/cache/assets/development/sprockets/1ff1b670b38042f5c89026631c36fa33 +0 -0
  43. data/test/dummy4/tmp/cache/assets/development/sprockets/28c67ae04b83f4f76d461c789d1236ad +0 -0
  44. data/test/dummy4/tmp/cache/assets/development/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
  45. data/test/dummy4/tmp/cache/assets/development/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
  46. data/test/dummy4/tmp/cache/assets/development/sprockets/3e0f6f496cd38bd4ea06614f7e10399a +0 -0
  47. data/test/dummy4/tmp/cache/assets/development/sprockets/4b02b6e6070ec4638e7c6a9f9ecff6fb +0 -0
  48. data/test/dummy4/tmp/cache/assets/development/sprockets/6a810a0412e578254a540397a7b70f08 +0 -0
  49. data/test/dummy4/tmp/cache/assets/development/sprockets/71efedfb555fe6a74750e5d579d363d5 +0 -0
  50. data/test/dummy4/tmp/cache/assets/development/sprockets/772e790ccea45e8e96ee6d22061276f6 +0 -0
  51. data/test/dummy4/tmp/cache/assets/development/sprockets/7a52bc6747db430cf502b4bed0fa298d +0 -0
  52. data/test/dummy4/tmp/cache/assets/development/sprockets/83b76c8a28ae96c73c3cdc3df9887735 +0 -0
  53. data/test/dummy4/tmp/cache/assets/development/sprockets/84c8f54298cdbbdd246e0f9bd5f26ebc +0 -0
  54. data/test/dummy4/tmp/cache/assets/development/sprockets/8926b7221463ce523a79e492b466d9e2 +0 -0
  55. data/test/dummy4/tmp/cache/assets/development/sprockets/9f45c7d10a3f607b80476e3f791501bd +0 -0
  56. data/test/dummy4/tmp/cache/assets/development/sprockets/a25c858be7f39b1ce6854eb93ba77ef5 +0 -0
  57. data/test/dummy4/tmp/cache/assets/development/sprockets/a2c2ae4f525146e108d2be380ca73570 +0 -0
  58. data/test/dummy4/tmp/cache/assets/development/sprockets/bb7f0179d91d1103a39cf20660a9f092 +0 -0
  59. data/test/dummy4/tmp/cache/assets/development/sprockets/cbec6d2b8af02ca399bf300772f22560 +0 -0
  60. data/test/dummy4/tmp/cache/assets/development/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
  61. data/test/dummy4/tmp/cache/assets/development/sprockets/d2d743676d256ff903f78df59b43c7ec +0 -0
  62. data/test/dummy4/tmp/cache/assets/development/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
  63. data/test/dummy4/tmp/cache/assets/development/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
  64. data/test/dummy4/tmp/cache/assets/production/sprockets/09c6831dd77d079a5a778b0d0744ee16 +0 -0
  65. data/test/dummy4/tmp/cache/assets/production/sprockets/0b91ee26fcc3a08f74edf9ade38787e4 +0 -0
  66. data/test/dummy4/tmp/cache/assets/production/sprockets/0bfdc3134b37668ae9a63c753ef05021 +0 -0
  67. data/test/dummy4/tmp/cache/assets/production/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
  68. data/test/dummy4/tmp/cache/assets/production/sprockets/1ff1b670b38042f5c89026631c36fa33 +0 -0
  69. data/test/dummy4/tmp/cache/assets/production/sprockets/28c67ae04b83f4f76d461c789d1236ad +0 -0
  70. data/test/dummy4/tmp/cache/assets/production/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
  71. data/test/dummy4/tmp/cache/assets/production/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
  72. data/test/dummy4/tmp/cache/assets/production/sprockets/3e0f6f496cd38bd4ea06614f7e10399a +0 -0
  73. data/test/dummy4/tmp/cache/assets/production/sprockets/71efedfb555fe6a74750e5d579d363d5 +0 -0
  74. data/test/dummy4/tmp/cache/assets/production/sprockets/7a52bc6747db430cf502b4bed0fa298d +0 -0
  75. data/test/dummy4/tmp/cache/assets/production/sprockets/83b76c8a28ae96c73c3cdc3df9887735 +0 -0
  76. data/test/dummy4/tmp/cache/assets/production/sprockets/84c8f54298cdbbdd246e0f9bd5f26ebc +0 -0
  77. data/test/dummy4/tmp/cache/assets/production/sprockets/9f45c7d10a3f607b80476e3f791501bd +0 -0
  78. data/test/dummy4/tmp/cache/assets/production/sprockets/a25c858be7f39b1ce6854eb93ba77ef5 +0 -0
  79. data/test/dummy4/tmp/cache/assets/production/sprockets/a2c2ae4f525146e108d2be380ca73570 +0 -0
  80. data/test/dummy4/tmp/cache/assets/production/sprockets/cbec6d2b8af02ca399bf300772f22560 +0 -0
  81. data/test/dummy4/tmp/cache/assets/production/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
  82. data/test/dummy4/tmp/cache/assets/production/sprockets/d2d743676d256ff903f78df59b43c7ec +0 -0
  83. data/test/dummy4/tmp/cache/assets/production/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
  84. data/test/dummy4/tmp/cache/assets/production/sprockets/d7d5b37686831d37c4dd75e645f5e016 +0 -0
  85. data/test/dummy4/tmp/cache/assets/production/sprockets/de2fd9fd11c04a582cdbbe3d84a35ae6 +0 -0
  86. data/test/dummy4/tmp/cache/assets/production/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
  87. metadata +291 -199
  88. data/test/dummy/tmp/cache/assets/D2F/760/sprockets%2F3b464ead21d28d0a1298357a3a7cbc18 +0 -0
  89. data/test/dummy/tmp/cache/assets/D45/C10/sprockets%2Fac34f7046872aba24b7375de608d8fe6 +0 -0
  90. data/test/dummy/tmp/cache/assets/D99/2F0/sprockets%2Fa2cf2651c63ecb32c21ea94fa84cd498 +0 -0
  91. data/test/dummy/tmp/cache/assets/DAA/C00/sprockets%2F9bddc9410e086be5f5efa982c5247c7b +0 -0
  92. data/test/dummy/tmp/cache/assets/DCF/EC0/sprockets%2Fe1f34cd8fd7ca6a9a01d26e47c923f1f +0 -0
  93. data/test/dummy/tmp/cache/assets/DEE/200/sprockets%2F2a3f3abddecb0467eb2d7d5cf5f52302 +0 -0
  94. data/test/dummy/tmp/cache/assets/DFF/960/sprockets%2Fe73aa53de71d957ef04bdfd2fba2e915 +0 -0
  95. data/test/dummy/tmp/cache/assets/E83/750/sprockets%2Fe0a4c2b9c4acf9bcfedbb42a8bd45e80 +0 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 235391144b34efd7ec9c96864bba5c491e5c265e
4
+ data.tar.gz: 29a256ede19d32ac91056b5cbbd54d6be69e70ba
5
+ SHA512:
6
+ metadata.gz: d323fbcb0ccc533ae2fca746ad6a7967b9e188456261170d7139a43c010275a12372bbb584cf58f59f0f5cb8025a45b9f6d252a9ed85e7a7171473a959b4ee4a
7
+ data.tar.gz: e3f9a4f3f40baafb4931116f9551daf12d346cb247c3c7f178cfd99d4ff46276e67d8758d10befba005b619fc6edbfb56da84915e571adf32dec3cc8cb92b4ef
data/README.rdoc CHANGED
@@ -10,18 +10,21 @@ Please note, that evercookie can't be fully reliable for detecting previous visi
10
10
 
11
11
  As written on original javascript {site}[http://samy.pl/evercookie/], when creating a new cookie, it uses the following storage mechanisms when available:
12
12
  * Standard {HTTP Cookies}[http://en.wikipedia.org/wiki/HTTP_cookie]
13
- * {Local Shared Objects}[http://en.wikipedia.org/wiki/Local_Shared_Object] (Flash Cookies)
14
- * {Isolated Storage}[http://www.silverlight.net/learn/quickstarts/isolatedstorage/] Silverlight (removed in gem)
15
- * Storing cookies in RGB values of auto-generated, force-cached PNGs using HTML5 Canvas tag to read pixels (cookies) back out
16
- * Storing cookies in and reading out {Web History}[http://samy.pl/csshack/] (removed in gem)
13
+ * Flash {Local Shared Objects}[http://en.wikipedia.org/wiki/Local_Shared_Object] (Flash Cookies)
14
+ * Silverlight {Isolated Storage}[http://www.silverlight.net/learn/quickstarts/isolatedstorage/] (disabled in gem, due to possible issues with different browsers)
15
+ * CSS {History Knocking}[http://samy.pl/csshack/] (turned off in gem due to network intensiveness)
17
16
  * Storing cookies in HTTP {ETags}[http://en.wikipedia.org/wiki/HTTP_ETag]
18
17
  * Storing cookies in {Web cache}[http://en.wikipedia.org/wiki/Web_cache]
19
18
  * {window.name}[http://en.wikipedia.org/wiki/HTTP_cookie=window.name] caching
20
- * Internet Explorer {userData}[http://msdn.microsoft.com/en-us/library/ms531424(VS.85).aspx] storage
19
+ * Internet Explorer {userData storage}[http://msdn.microsoft.com/en-us/library/ms531424(VS.85).aspx]
20
+ * HTML5 Canvas - Cookie values stored in RGB data of auto-generated, force-cached PNG images
21
21
  * HTML5 {Session Storage}[http://dev.w3.org/html5/webstorage/=the-sessionstorage-attribute]
22
22
  * HTML5 {Local Storage}[http://dev.w3.org/html5/webstorage/=dom-localstorage]
23
23
  * HTML5 {Global Storage}[https://developer.mozilla.org/en/dom/storage=globalStorage]
24
24
  * HTML5 {Database Storage}[http://dev.w3.org/html5/webdatabase] via SQLite
25
+ * HTML5 {IndexedDB}[http://www.w3.org/TR/IndexedDB/]
26
+ * Java {JNLP PersistenceService}[http://docs.oracle.com/javase/1.5.0/docs/guide/javaws/jnlp/index.html] (disabled in gem due to possible user permission request)
27
+ * Java exploit {CVE-2013-0422}[https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2013-0422] - Attempts to escape the applet sandbox and write cookie data directly to the user's hard drive. (disabled in gem due to possible user permission request)
25
28
 
26
29
  == Information
27
30
 
@@ -41,7 +44,7 @@ You can see an example of evercookie working in test/dummy application of this g
41
44
 
42
45
  == Getting started
43
46
 
44
- Evercookie works was written and tested on Rails 3.2. You can add in to your Gemfile with:
47
+ Evercookie works was written and tested on Rails 3.2/4. You can add in to your Gemfile with:
45
48
 
46
49
  gem 'evercookie'
47
50
 
@@ -114,4 +117,11 @@ You can create the initializer for evercookie gem in your Rails application init
114
117
 
115
118
  # cookie name for etag storage
116
119
  config.cookie_etag = :evercookie_etag
117
- end
120
+ end
121
+
122
+ === Hiding evercookie presence in your application
123
+
124
+ If you really want to hide that you are using evercookie you should do several things (as I see it):
125
+ * precompile assets with compression enabled, it will remove all comments and will change some variables of evercookie JS class
126
+ * configure the gem to use paths that don't have 'evercookie' name in them
127
+ * but remember, if someone wants to find presence of evercookie, he will
@@ -1,704 +1,1094 @@
1
+ /*jslint browser: true, nomen: false, plusplus: false, bitwise: false, maxerr: 50, indent: 2 */
1
2
  /*
2
- * USAGE:
3
-
4
- var ec = new <%= Evercookie.js_class %>();
5
- ec.set("id", "12345");
6
- ec.get("id", function(value) { alert("value is " + value) });
3
+ var ec = new <%= Evercookie.js_class %>();
4
+
5
+ // set a cookie "id" to "12345"
6
+ // usage: ec.set(key, value)
7
+ ec.set("id", "12345");
8
+
9
+ // retrieve a cookie called "id" (simply)
10
+ ec.get("id", function(value) { alert("Cookie value is " + value) });
11
+
12
+ // or use a more advanced callback function for getting our cookie
13
+ // the cookie value is the first param
14
+ // an object containing the different storage methods
15
+ // and returned cookie values is the second parameter
16
+ function getCookie(best_candidate, all_candidates)
17
+ {
18
+ alert("The retrieved cookie is: " + best_candidate + "\n" +
19
+ "You can see what each storage mechanism returned " +
20
+ "by looping through the all_candidates object.");
21
+
22
+ for (var item in all_candidates)
23
+ document.write("Storage mechanism " + item +
24
+ " returned " + all_candidates[item] + " votes<br>");
25
+ }
26
+ ec.get("id", getCookie);
7
27
  */
8
- var _ec_tests = 10; //1000
9
- function _ec_replace(str, key, value) {
28
+ try{
29
+ (function (window) {
30
+ 'use strict';
31
+ var document = window.document,
32
+ Image = window.Image,
33
+ globalStorage = window.globalStorage,
34
+ swfobject = window.swfobject;
35
+
36
+ try{
37
+ var localStore = window.localStorage
38
+ }catch(ex){}
39
+
40
+ try {
41
+ var sessionStorage = window.sessionStorage;
42
+ } catch (e) { }
43
+
44
+ function newImage(src) {
45
+ var img = new Image();
46
+ img.style.visibility = "hidden";
47
+ img.style.position = "absolute";
48
+ img.src = src;
49
+ }
50
+ function _ec_replace(str, key, value) {
10
51
  if (str.indexOf("&" + key + "=") > -1 || str.indexOf(key + "=") === 0) {
11
- // find start
12
- var idx = str.indexOf("&" + key + "="),
13
- end, newstr;
14
- if (idx === -1) {
15
- idx = str.indexOf(key + "=");
16
- }
17
- // find end
18
- end = str.indexOf("&", idx + 1);
19
- if (end !== -1) {
20
- newstr = str.substr(0, idx) + str.substr(end + (idx ? 0 : 1)) + "&" + key + "=" + value;
21
- } else {
22
- newstr = str.substr(0, idx) + "&" + key + "=" + value;
23
- }
24
- return newstr;
52
+ // find start
53
+ var idx = str.indexOf("&" + key + "="),
54
+ end, newstr;
55
+ if (idx === -1) {
56
+ idx = str.indexOf(key + "=");
57
+ }
58
+ // find end
59
+ end = str.indexOf("&", idx + 1);
60
+ if (end !== -1) {
61
+ newstr = str.substr(0, idx) + str.substr(end + (idx ? 0 : 1)) + "&" + key + "=" + value;
62
+ } else {
63
+ newstr = str.substr(0, idx) + "&" + key + "=" + value;
64
+ }
65
+ return newstr;
25
66
  } else {
26
- return str + "&" + key + "=" + value;
67
+ return str + "&" + key + "=" + value;
27
68
  }
28
- }
69
+ }
29
70
 
71
+ function idb() {
72
+ if ('indexedDB' in window) {
73
+ return true
74
+ } else if (window.indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB) {
75
+ return true
76
+ } else {
77
+ return false
78
+ }
79
+ }
30
80
 
31
- // necessary for flash to communicate with js...
32
- // please implement a better way
33
- var _global_lso;
34
- function _evercookie_flash_var(cookie) {
81
+ // necessary for flash to communicate with js...
82
+ // please implement a better way
83
+ var _global_lso;
84
+ function _<%= Evercookie.js_class %>_flash_var(cookie) {
35
85
  _global_lso = cookie;
36
86
 
37
87
  // remove the flash object now
38
88
  var swf = document.getElementById("myswf");
39
89
  if (swf && swf.parentNode) {
40
- swf.parentNode.removeChild(swf);
90
+ swf.parentNode.removeChild(swf);
41
91
  }
42
- }
43
-
44
- var <%= Evercookie.js_class %> = (function (window) {
45
- var document = window.document,
46
- Image = window.Image,
47
- localStorage = window.localStorage,
48
- globalStorage = window.globalStorage,
49
- swfobject = window.swfobject;
50
- try {
51
- var sessionStorage = window.sessionStorage;
52
- } catch (e) { }
53
-
54
- this._class = function () {
55
- // private property
56
- var self = this,
57
- _baseKeyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
58
- no_color = -1;
59
- this._ec = {};
60
-
61
- this.get = function (name, cb, dont_reset) {
62
- self._<%= Evercookie.js_class %>(name, cb, undefined, undefined, dont_reset);
63
- };
64
-
65
- this.set = function (name, value) {
66
- self._<%= Evercookie.js_class %>(name, function () {}, value);
67
- };
68
-
69
- this._<%= Evercookie.js_class %> = function (name, cb, value, i, dont_reset) {
70
- if (self._<%= Evercookie.js_class %> === undefined) {
71
- self = this;
72
- }
73
- if (i === undefined) {
74
- i = 0;
75
- }
76
- // first run
77
- if (i === 0) {
78
- self.<%= Evercookie.js_class %>_database_storage(name, value);
79
- self.<%= Evercookie.js_class %>_png(name, value);
80
- self.<%= Evercookie.js_class %>_etag(name, value);
81
- self.<%= Evercookie.js_class %>_cache(name, value);
82
- self.<%= Evercookie.js_class %>_lso(name, value);
83
-
84
- self._ec.userData = self.<%= Evercookie.js_class %>_userdata(name, value);
85
- self._ec.cookieData = self.<%= Evercookie.js_class %>_cookie(name, value);
86
- self._ec.localData = self.<%= Evercookie.js_class %>_local_storage(name, value);
87
- self._ec.globalData = self.<%= Evercookie.js_class %>_global_storage(name, value);
88
- self._ec.sessionData = self.<%= Evercookie.js_class %>_session_storage(name, value);
89
- self._ec.windowData = self.<%= Evercookie.js_class %>_window(name, value);
92
+ }
93
+
94
+ /*
95
+ * Again, ugly workaround....same problem as flash.
96
+ */
97
+ var _global_isolated;
98
+ function onSilverlightLoad(sender, args) {
99
+ var control = sender.getHost();
100
+ _global_isolated = control.Content.App.getIsolatedStorage();
101
+ }
102
+
103
+ function onSilverlightError(sender, args) {
104
+ _global_isolated = "";
105
+ }
106
+
107
+ var defaultOptionMap = {
108
+ history: false, // CSS history knocking or not .. can be network intensive
109
+ java: false, // Java applet on/off... may prompt users for permission to run.
110
+ tests: 3, //1000 what is it, actually?
111
+ baseurl: '', // base url for php, flash and silverlight assets
112
+ silverlight: false, // you might want to turn it off https://github.com/samyk/evercookie/issues/45
113
+ domain: '.' + window.location.host.replace(/:\d+/, ''), // Get current domain
114
+ authPath: '<%= Evercookie.get_auth_path %>', // set to false to disable Basic Authentication cache
115
+ pngCookieName: '<%= Evercookie.cookie_png %>',
116
+ pngPath: '<%= Evercookie.get_png_path %>',
117
+ etagCookieName: '<%= Evercookie.cookie_etag %>',
118
+ etagPath: '<%= Evercookie.get_etag_path %>',
119
+ cacheCookieName: '<%= Evercookie.cookie_cache %>',
120
+ cachePath: '<%= Evercookie.get_cache_path %>'
121
+ };
122
+ var _baseKeyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
123
+ /**
124
+ * @class Evercookie
125
+ * @param {Object} options
126
+ * @param {Boolean} options.history CSS history knocking or not .. can be network intensive
127
+ * @param {Boolean} options.java Java applet on/off... may prompt users for permission to run.
128
+ * @param {Boolean} options.silverlight you might want to turn it off https://github.com/samyk/evercookie/issues/45
129
+ * @param {Number} options.tests
130
+ * @param {String} options.baseurl base url for php, flash and silverlight assets
131
+ * @param {String|Function} options.domain as a string, domain for cookie, as a function, accept window object and return domain string
132
+ * @param {String} options.pngCookieName
133
+ * @param {String} options.pngPath
134
+ * @param {String} options.etagCookieName:
135
+ * @param {String} options.etagPath
136
+ * @param {String} options.cacheCookieName
137
+ * @param {String} options.cachePath
138
+ */
139
+ function <%= Evercookie.js_class %>(options) {
140
+ options = options || {};
141
+ var opts = {};
142
+ for (var key in defaultOptionMap) {
143
+ var optValue = options[key];
144
+ if(typeof optValue !== 'undefined') {
145
+ opts[key] = optValue
146
+ } else {
147
+ opts[key] = defaultOptionMap[key];
148
+ }
149
+ }
150
+ if(typeof opts.domain === 'function'){
151
+ opts.domain = opts.domain(window);
152
+ }
153
+ var _ec_history = opts.history,
154
+ _ec_java = opts.java,
155
+ _ec_tests = opts.tests,
156
+ _ec_baseurl = opts.baseurl,
157
+ _ec_domain = opts.domain;
158
+
159
+ // private property
160
+ var self = this;
161
+ this._ec = {};
162
+
163
+ this.get = function (name, cb, dont_reset) {
164
+ self._<%= Evercookie.js_class %>(name, cb, undefined, undefined, dont_reset);
165
+ };
166
+
167
+ this.set = function (name, value) {
168
+ self._<%= Evercookie.js_class %>(name, function () {}, value);
169
+ };
170
+
171
+ this._<%= Evercookie.js_class %> = function (name, cb, value, i, dont_reset) {
172
+ if (self._<%= Evercookie.js_class %> === undefined) {
173
+ self = this;
174
+ }
175
+ if (i === undefined) {
176
+ i = 0;
177
+ }
178
+ // first run
179
+ if (i === 0) {
180
+ self.<%= Evercookie.js_class %>_database_storage(name, value);
181
+ self.<%= Evercookie.js_class %>_png(name, value);
182
+ self.<%= Evercookie.js_class %>_etag(name, value);
183
+ self.<%= Evercookie.js_class %>_cache(name, value);
184
+ self.<%= Evercookie.js_class %>_lso(name, value);
185
+ if (opts.silverlight) {
186
+ self.<%= Evercookie.js_class %>_silverlight(name, value);
187
+ }
188
+ if (opts.authPath) {
189
+ self.<%= Evercookie.js_class %>_auth(name, value);
190
+ }
191
+ if (_ec_java) {
192
+ self.<%= Evercookie.js_class %>_java(name, value);
193
+ }
194
+
195
+ self._ec.userData = self.<%= Evercookie.js_class %>_userdata(name, value);
196
+ self._ec.cookieData = self.<%= Evercookie.js_class %>_cookie(name, value);
197
+ self._ec.localData = self.<%= Evercookie.js_class %>_local_storage(name, value);
198
+ self._ec.globalData = self.<%= Evercookie.js_class %>_global_storage(name, value);
199
+ self._ec.sessionData = self.<%= Evercookie.js_class %>_session_storage(name, value);
200
+ self._ec.windowData = self.<%= Evercookie.js_class %>_window(name, value);
201
+
202
+ if (_ec_history) {
203
+ self._ec.historyData = self.<%= Evercookie.js_class %>_history(name, value);
204
+ }
205
+ }
206
+
207
+ // when writing data, we need to make sure lso and silverlight object is there
208
+ if (value !== undefined) {
209
+ if ((typeof _global_lso === "undefined" ||
210
+ typeof _global_isolated === "undefined") &&
211
+ i++ < _ec_tests) {
212
+ setTimeout(function () {
213
+ self._<%= Evercookie.js_class %>(name, cb, value, i, dont_reset);
214
+ }, 200);
215
+ }
216
+ }
217
+
218
+ // when reading data, we need to wait for swf, db, silverlight, java and png
219
+ else
220
+ {
221
+ if (
222
+ (
223
+ // we support local db and haven't read data in yet
224
+ (window.openDatabase && typeof self._ec.dbData === "undefined") ||
225
+ (idb() && (typeof self._ec.idbData === "undefined" || self._ec.idbData === "")) ||
226
+ (typeof _global_lso === "undefined") ||
227
+ (typeof self._ec.etagData === "undefined") ||
228
+ (typeof self._ec.cacheData === "undefined") ||
229
+ (typeof self._ec.javaData === "undefined") ||
230
+ (document.createElement("canvas").getContext && (typeof self._ec.pngData === "undefined" || self._ec.pngData === "")) ||
231
+ (typeof _global_isolated === "undefined")
232
+ ) &&
233
+ i++ < _ec_tests
234
+ )
235
+ {
236
+ setTimeout(function () {
237
+ self._<%= Evercookie.js_class %>(name, cb, value, i, dont_reset);
238
+ }, 200);
239
+ }
240
+
241
+ // we hit our max wait time or got all our data
242
+ else
243
+ {
244
+ // get just the piece of data we need from swf
245
+ self._ec.lsoData = self.getFromStr(name, _global_lso);
246
+ _global_lso = undefined;
247
+
248
+ // get just the piece of data we need from silverlight
249
+ self._ec.slData = self.getFromStr(name, _global_isolated);
250
+ _global_isolated = undefined;
251
+
252
+ var tmpec = self._ec,
253
+ candidates = [],
254
+ bestnum = 0,
255
+ candidate,
256
+ item;
257
+ self._ec = {};
258
+
259
+ // figure out which is the best candidate
260
+ for (item in tmpec) {
261
+ if (tmpec[item] && tmpec[item] !== "null" && tmpec[item] !== "undefined") {
262
+ candidates[tmpec[item]] = candidates[tmpec[item]] === undefined ? 1 : candidates[tmpec[item]] + 1;
90
263
  }
264
+ }
91
265
 
92
- // when writing data, we need to make sure lso object is there
93
- if (value !== undefined) {
94
- if ((typeof _global_lso === "undefined") && i++ < _ec_tests) {
95
- setTimeout(function () {
96
- self._<%= Evercookie.js_class %>(name, cb, value, i, dont_reset);
97
- }, 100);
98
- }
266
+ for (item in candidates) {
267
+ if (candidates[item] > bestnum) {
268
+ bestnum = candidates[item];
269
+ candidate = item;
99
270
  }
271
+ }
272
+
273
+ // reset cookie everywhere
274
+ if (candidate !== undefined && (dont_reset === undefined || dont_reset !== 1)) {
275
+ self.set(name, candidate);
276
+ }
277
+ if (typeof cb === "function") {
278
+ cb(candidate, tmpec);
279
+ }
280
+
281
+ self.ajax({
282
+ url: "<%= Evercookie.get_save_path %>?name=" + name,
283
+ success: function (data) { }
284
+ });
285
+ }
286
+ }
287
+ };
100
288
 
101
- // when reading data, we need to wait for swf, db and png
102
- else
103
- {
104
- if (
105
- (
106
- // we support local db and haven't read data in yet
107
- (window.openDatabase && typeof self._ec.dbData === "undefined") ||
108
- (typeof _global_lso === "undefined") ||
109
- (typeof self._ec.etagData === "undefined") ||
110
- (typeof self._ec.cacheData === "undefined") ||
111
- (document.createElement("canvas").getContext && (typeof self._ec.pngData === "undefined" || self._ec.pngData === ""))
112
- ) &&
113
- i++ < _ec_tests
114
- )
115
- {
116
- setTimeout(function () {
117
- self._<%= Evercookie.js_class %>(name, cb, value, i, dont_reset);
118
- }, 300);
119
- }
289
+ this.<%= Evercookie.js_class %>_window = function (name, value) {
290
+ try {
291
+ if (value !== undefined) {
292
+ window.name = _ec_replace(window.name, name, value);
293
+ } else {
294
+ return this.getFromStr(name, window.name);
295
+ }
296
+ } catch (e) { }
297
+ };
120
298
 
121
- // we hit our max wait time or got all our data
122
- else
123
- {
124
- // get just the piece of data we need from swf
125
- self._ec.lsoData = self.getFromStr(name, _global_lso);
126
- _global_lso = undefined;
127
-
128
- var tmpec = self._ec,
129
- candidates = [],
130
- bestnum = 0,
131
- candidate,
132
- item;
133
- self._ec = {};
134
-
135
- // figure out which is the best candidate
136
- for (item in tmpec) {
137
- if (tmpec[item] && tmpec[item] !== "null" && tmpec[item] !== "undefined") {
138
- candidates[tmpec[item]] = candidates[tmpec[item]] === undefined ? 1 : candidates[tmpec[item]] + 1;
139
- }
140
- }
299
+ this.<%= Evercookie.js_class %>_userdata = function (name, value) {
300
+ try {
301
+ var elm = this.createElem("div", "userdata_el", 1);
302
+ elm.style.behavior = "url(#default#userData)";
141
303
 
142
- for (item in candidates) {
143
- if (candidates[item] > bestnum) {
144
- bestnum = candidates[item];
145
- candidate = item;
146
- }
147
- }
304
+ if (value !== undefined) {
305
+ elm.setAttribute(name, value);
306
+ elm.save(name);
307
+ } else {
308
+ elm.load(name);
309
+ return elm.getAttribute(name);
310
+ }
311
+ } catch (e) {}
312
+ };
148
313
 
149
- // reset cookie everywhere
150
- if ((dont_reset === undefined || dont_reset !== 1) && candidate !== undefined) {
151
- self.set(name, candidate);
152
- }
153
- if (typeof cb === "function") {
154
- cb(candidate, tmpec);
155
- }
314
+ this.ajax = function (settings) {
315
+ var headers, name, transports, transport, i, length;
156
316
 
157
- self.ajax({
158
- url: "<%= Evercookie.get_save_path %>?name=" + name,
159
- success: function (data) { }
160
- });
161
- }
162
- }
163
- };
317
+ headers = {
318
+ 'X-Requested-With': 'XMLHttpRequest',
319
+ 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
320
+ };
164
321
 
165
- this.<%= Evercookie.js_class %>_window = function (name, value) {
166
- try {
167
- if (value !== undefined) {
168
- window.name = _ec_replace(window.name, name, value);
169
- } else {
170
- return this.getFromStr(name, window.name);
171
- }
172
- } catch (e) { }
173
- };
322
+ transports = [
323
+ function () { return new XMLHttpRequest(); },
324
+ function () { return new ActiveXObject('Msxml2.XMLHTTP'); },
325
+ function () { return new ActiveXObject('Microsoft.XMLHTTP'); }
326
+ ];
174
327
 
175
- this.<%= Evercookie.js_class %>_userdata = function (name, value) {
176
- try {
177
- var elm = this.createElem("div", "userdata_el", 1);
178
- elm.style.behavior = "url(#default#userData)";
328
+ for (i = 0, length = transports.length; i < length; i++) {
329
+ transport = transports[i];
330
+ try {
331
+ transport = transport();
332
+ break;
333
+ } catch (e) {
334
+ }
335
+ }
179
336
 
180
- if (value !== undefined) {
181
- elm.setAttribute(name, value);
182
- elm.save(name);
183
- } else {
184
- elm.load(name);
185
- return elm.getAttribute(name);
186
- }
187
- } catch (e) {}
188
- };
189
-
190
- function newImage(src) {
191
- var img = new Image();
192
- img.style.visibility = "hidden";
193
- img.style.position = "absolute";
194
- img.src = src;
195
- }
196
-
197
- this.ajax = function (settings) {
198
- var headers, name, transports, transport, i, length;
199
-
200
- headers = {
201
- 'X-Requested-With': 'XMLHttpRequest',
202
- 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
203
- };
204
-
205
- transports = [
206
- function () { return new XMLHttpRequest(); },
207
- function () { return new ActiveXObject('Msxml2.XMLHTTP'); },
208
- function () { return new ActiveXObject('Microsoft.XMLHTTP'); }
209
- ];
210
-
211
- for (i = 0, length = transports.length; i < length; i++) {
212
- transport = transports[i];
213
- try {
214
- transport = transport();
215
- break;
216
- } catch (e) {
217
- }
218
- }
337
+ transport.onreadystatechange = function () {
338
+ if (transport.readyState !== 4) {
339
+ return;
340
+ }
341
+ settings.success(transport.responseText);
342
+ };
343
+ transport.open('get', settings.url, true);
344
+ for (name in headers) {
345
+ transport.setRequestHeader(name, headers[name]);
346
+ }
347
+ transport.send();
348
+ };
219
349
 
220
- transport.onreadystatechange = function () {
221
- if (transport.readyState !== 4) {
222
- return;
223
- }
224
- settings.success(transport.responseText);
225
- };
226
- transport.open('get', settings.url, true);
227
- for (name in headers) {
228
- transport.setRequestHeader(name, headers[name]);
229
- }
230
- transport.send();
231
- };
232
-
233
- this.<%= Evercookie.js_class %>_cache = function (name, value) {
234
- if (value !== undefined) {
235
- // make sure we have <%= Evercookie.js_class %> session defined first
236
- document.cookie = "<%= Evercookie.cookie_cache %>=" + value + "; path=<%= Evercookie.get_cookie_path %>";
237
- // <%= Evercookie.get_cache_path %> handles caching
238
- newImage("<%= Evercookie.get_cache_path %>?name=" + name);
239
- } else {
240
- // interestingly enough, we want to erase our evercookie
241
- // http cookie so will force a cached response
242
- var origvalue = this.getFromStr("<%= Evercookie.cookie_cache %>", document.cookie);
243
- self._ec.cacheData = undefined;
244
- document.cookie = "<%= Evercookie.cookie_cache %>=; expires=Mon, 20 Sep 2010 00:00:00 UTC; path=<%= Evercookie.get_cookie_path %>";
245
-
246
- self.ajax({
247
- url: "<%= Evercookie.get_cache_path %>?name=" + name,
248
- success: function (data) {
249
- // put our cookie back
250
- document.cookie = "<%= Evercookie.cookie_cache %>=" + origvalue + "; expires=Tue, 31 Dec 2030 00:00:00 UTC; path=<%= Evercookie.get_cookie_path %>";
251
-
252
- self._ec.cacheData = data;
253
- }
254
- });
255
- }
256
- };
257
-
258
- this.<%= Evercookie.js_class %>_etag = function (name, value) {
259
- if (value !== undefined) {
260
- // make sure we have <%= Evercookie.js_class %> session defined first
261
- document.cookie = "<%= Evercookie.cookie_etag %>=" + value + "; path=<%= Evercookie.get_cookie_path %>";
262
- // <%= Evercookie.get_etag_path %> handles etagging
263
- newImage("<%= Evercookie.get_etag_path %>?name=" + name);
264
- } else {
265
- // interestingly enough, we want to erase our <%= Evercookie.js_class %>
266
- // http cookie so will force a cached response
267
- var origvalue = this.getFromStr("<%= Evercookie.cookie_etag %>", document.cookie);
268
- self._ec.etagData = undefined;
269
- document.cookie = "<%= Evercookie.cookie_etag %>=; expires=Mon, 20 Sep 2010 00:00:00 UTC; path=<%= Evercookie.get_cookie_path %>";
270
-
271
- self.ajax({
272
- url: "<%= Evercookie.get_etag_path %>?name=" + name,
273
- success: function (data) {
274
- // put our cookie back
275
- document.cookie = "<%= Evercookie.cookie_etag %>=" + origvalue + "; expires=Tue, 31 Dec 2030 00:00:00 UTC; path=<%= Evercookie.get_cookie_path %>";
276
-
277
- self._ec.etagData = data;
278
- }
279
- });
280
- }
281
- };
282
-
283
- this.<%= Evercookie.js_class %>_lso = function (name, value) {
284
- var div = document.getElementById("swfcontainer"),
285
- flashvars = {},
286
- params = {},
287
- attributes = {};
288
- if (div===null || div === undefined || !div.length) {
289
- div = document.createElement("div");
290
- div.setAttribute("id", "swfcontainer");
291
- document.body.appendChild(div);
350
+ this.<%= Evercookie.js_class %>_cache = function (name, value) {
351
+ if (value !== undefined) {
352
+ // make sure we have evercookie session defined first
353
+ document.cookie = opts.cacheCookieName + "=" + value + "; path=/; domain=" + _ec_domain;
354
+ // {{ajax request to opts.cachePath}} handles caching
355
+ self.ajax({
356
+ url: _ec_baseurl + opts.cachePath + "?name=" + name,
357
+ success: function (data) {}
358
+ });
359
+ } else {
360
+ // interestingly enough, we want to erase our evercookie
361
+ // http cookie so the php will force a cached response
362
+ var origvalue = this.getFromStr(opts.cacheCookieName, document.cookie);
363
+ self._ec.cacheData = undefined;
364
+ document.cookie = opts.cacheCookieName + "=; expires=Mon, 20 Sep 2010 00:00:00 UTC; path=/; domain=" + _ec_domain;
365
+
366
+ self.ajax({
367
+ url: _ec_baseurl + opts.cachePath + "?name=" + name,
368
+ success: function (data) {
369
+ // put our cookie back
370
+ document.cookie = opts.cacheCookieName + "=" + origvalue + "; expires=Tue, 31 Dec 2030 00:00:00 UTC; path=/; domain=" + _ec_domain;
371
+
372
+ self._ec.cacheData = data;
373
+ }
374
+ });
375
+ }
376
+ };
377
+ this.<%= Evercookie.js_class %>_auth = function (name, value) {
378
+ if (value !== undefined) {
379
+ // {{opts.authPath}} handles Basic Access Authentication
380
+ newImage('//' + value + '@' + location.host + _ec_baseurl + opts.authPath + "?name=" + name);
381
+ }
382
+ else {
383
+ self.ajax({
384
+ url: _ec_baseurl + opts.authPath + "?name=" + name,
385
+ success: function (data) {
386
+ self._ec.authData = data;
387
+ }
388
+ });
389
+ }
390
+ };
391
+
392
+ this.<%= Evercookie.js_class %>_etag = function (name, value) {
393
+ if (value !== undefined) {
394
+ // make sure we have evercookie session defined first
395
+ document.cookie = opts.etagCookieName + "=" + value + "; path=/; domain=" + _ec_domain;
396
+ // {{ajax request to opts.etagPath}} handles etagging
397
+ self.ajax({
398
+ url: _ec_baseurl + opts.etagPath + "?name=" + name,
399
+ success: function (data) {}
400
+ });
401
+ } else {
402
+ // interestingly enough, we want to erase our evercookie
403
+ // http cookie so the php will force a cached response
404
+ var origvalue = this.getFromStr(opts.etagCookieName, document.cookie);
405
+ self._ec.etagData = undefined;
406
+ document.cookie = opts.etagCookieName + "=; expires=Mon, 20 Sep 2010 00:00:00 UTC; path=/; domain=" + _ec_domain;
407
+
408
+ self.ajax({
409
+ url: _ec_baseurl + opts.etagPath + "?name=" + name,
410
+ success: function (data) {
411
+ // put our cookie back
412
+ document.cookie = opts.etagCookieName + "=" + origvalue + "; expires=Tue, 31 Dec 2030 00:00:00 UTC; path=/; domain=" + _ec_domain;
413
+
414
+ self._ec.etagData = data;
415
+ }
416
+ });
417
+ }
418
+ };
419
+
420
+ this.<%= Evercookie.js_class %>_java = function (name, value) {
421
+ var div = document.getElementById("ecAppletContainer");
422
+
423
+ // Exit if dtjava.js was not included in the page header.
424
+ if (typeof dtjava === "undefined") {
425
+ return;
426
+ }
427
+
428
+ // Create the container div if none exists.
429
+ if (div===null || div === undefined || !div.length) {
430
+ div = document.createElement("div");
431
+ div.setAttribute("id", "ecAppletContainer");
432
+ div.style.position = "absolute";
433
+ div.style.top = "-3000px";
434
+ div.style.left = "-3000px";
435
+ div.style.width = "1px";
436
+ div.style.height = "1px";
437
+ document.body.appendChild(div);
438
+ }
439
+
440
+ // If the Java applet is not yet defined, embed it.
441
+ if (typeof ecApplet === "undefined") {
442
+ dtjava.embed({
443
+ id: "ecApplet",
444
+ url: _ec_baseurl + "<%= Evercookie.js_class %>.jnlp",
445
+ width: "1px",
446
+ height: "1px",
447
+ placeholder: "ecAppletContainer"
448
+ }, {},{ onJavascriptReady: doSetOrGet });
449
+ // When the applet is loaded we will continue in doSetOrGet()
450
+ }
451
+ else {
452
+ // applet already running... call doGetOrSet() directly.
453
+ doSetOrGet("ecApplet");
454
+ }
455
+
456
+ function doSetOrGet(appletId) {
457
+ var applet = document.getElementById(appletId);
458
+ if (value !== undefined) {
459
+ applet.set(name,value);
460
+ }
461
+ else {
462
+ self._ec.javaData = applet.get(name);
463
+ }
464
+ }
465
+
466
+ // The result of a get() is now in self._ec._javaData
467
+ };
468
+
469
+ this.<%= Evercookie.js_class %>_lso = function (name, value) {
470
+ var div = document.getElementById("swfcontainer"),
471
+ flashvars = {},
472
+ params = {},
473
+ attributes = {};
474
+ if (div===null || div === undefined || !div.length) {
475
+ div = document.createElement("div");
476
+ div.setAttribute("id", "swfcontainer");
477
+ document.body.appendChild(div);
478
+ }
479
+
480
+ if (value !== undefined) {
481
+ flashvars.everdata = name + "=" + value;
482
+ }
483
+ params.swliveconnect = "true";
484
+ attributes.id = "myswf";
485
+ attributes.name = "myswf";
486
+ swfobject.embedSWF(_ec_baseurl + "<%= asset_path('ec.swf') %>", "swfcontainer", "1", "1", "9.0.0", false, flashvars, params, attributes);
487
+ };
488
+
489
+ this.<%= Evercookie.js_class %>_png = function (name, value) {
490
+ var canvas = document.createElement("canvas"),
491
+ img, ctx, origvalue;
492
+ canvas.style.visibility = "hidden";
493
+ canvas.style.position = "absolute";
494
+ canvas.width = 200;
495
+ canvas.height = 1;
496
+ if (canvas && canvas.getContext) {
497
+ // {{opts.pngPath}} handles the hard part of generating the image
498
+ // based off of the http cookie and returning it cached
499
+ img = new Image();
500
+ img.style.position = "absolute";
501
+ if (value !== undefined) {
502
+ // make sure we have evercookie session defined first
503
+ document.cookie = opts.pngCookieName + "=" + value + "; path=/; domain=" + _ec_domain;
504
+ } else {
505
+ self._ec.pngData = undefined;
506
+ ctx = canvas.getContext("2d");
507
+
508
+ // interestingly enough, we want to erase our evercookie
509
+ // http cookie so the php will force a cached response
510
+ origvalue = this.getFromStr(opts.pngCookieName, document.cookie);
511
+ document.cookie = opts.pngCookieName + "=; expires=Mon, 20 Sep 2010 00:00:00 UTC; path=/; domain=" + _ec_domain;
512
+
513
+ img.onload = function () {
514
+ // put our cookie back
515
+ document.cookie = opts.pngCookieName + "=" + origvalue + "; expires=Tue, 31 Dec 2030 00:00:00 UTC; path=/; domain=" + _ec_domain;
516
+
517
+ self._ec.pngData = "";
518
+ ctx.drawImage(img, 0, 0);
519
+
520
+ // get CanvasPixelArray from given coordinates and dimensions
521
+ var imgd = ctx.getImageData(0, 0, 200, 1),
522
+ pix = imgd.data, i, n;
523
+ // loop over each pixel to get the "RGB" values (ignore alpha)
524
+ for (i = 0, n = pix.length; i < n; i += 4) {
525
+ if (pix[i] === 0) {
526
+ break;
527
+ }
528
+ self._ec.pngData += String.fromCharCode(pix[i]);
529
+ if (pix[i + 1] === 0) {
530
+ break;
531
+ }
532
+ self._ec.pngData += String.fromCharCode(pix[i + 1]);
533
+ if (pix[i + 2] === 0) {
534
+ break;
535
+ }
536
+ self._ec.pngData += String.fromCharCode(pix[i + 2]);
292
537
  }
538
+ };
539
+ }
540
+ img.src = _ec_baseurl + opts.pngPath + "?name=" + name;
541
+ img.style.visibility = "hidden";
542
+ }
543
+ };
544
+
545
+ this.<%= Evercookie.js_class %>_local_storage = function (name, value) {
546
+ try {
547
+ if (localStore) {
548
+ if (value !== undefined) {
549
+ localStore.setItem(name, value);
550
+ } else {
551
+ return localStore.getItem(name);
552
+ }
553
+ }
554
+ } catch (e) { }
555
+ };
556
+
557
+ this.<%= Evercookie.js_class %>_database_storage = function (name, value) {
558
+ try {
559
+ if (window.openDatabase) {
560
+ var database = window.openDatabase("sqlite_<%= Evercookie.js_class %>", "", "<%= Evercookie.js_class %>", 1024 * 1024);
561
+
562
+ if (value !== undefined) {
563
+ database.transaction(function (tx) {
564
+ tx.executeSql("CREATE TABLE IF NOT EXISTS cache(" +
565
+ "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, " +
566
+ "name TEXT NOT NULL, " +
567
+ "value TEXT NOT NULL, " +
568
+ "UNIQUE (name)" +
569
+ ")", [], function (tx, rs) {}, function (tx, err) {});
570
+ tx.executeSql("INSERT OR REPLACE INTO cache(name, value) " +
571
+ "VALUES(?, ?)",
572
+ [name, value], function (tx, rs) {}, function (tx, err) {});
573
+ });
574
+ } else {
575
+ database.transaction(function (tx) {
576
+ tx.executeSql("SELECT value FROM cache WHERE name=?", [name],
577
+ function (tx, result1) {
578
+ if (result1.rows.length >= 1) {
579
+ self._ec.dbData = result1.rows.item(0).value;
580
+ } else {
581
+ self._ec.dbData = "";
582
+ }
583
+ }, function (tx, err) {});
584
+ });
585
+ }
586
+ }
587
+ } catch (e) { }
588
+ };
589
+
590
+ this.<%= Evercookie.js_class %>_indexdb_storage = function(name, value) {
591
+ try {
592
+ if (!('indexedDB' in window)) {
593
+
594
+ indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
595
+ IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.msIDBTransaction;
596
+ IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.msIDBKeyRange;
597
+ }
293
598
 
294
- if (value !== undefined) {
295
- flashvars.everdata = name + "=" + value;
599
+ if (indexedDB) {
600
+ var ver = 1;
601
+ //FF incognito mode restricts indexedb access
602
+ var request = indexedDB.open("idb_<%= Evercookie.js_class %>", ver);
603
+
604
+
605
+ request.onerror = function(e) { ;
606
+ }
607
+
608
+ request.onupgradeneeded = function(event) {
609
+ var db = event.target.result;
610
+
611
+ var store = db.createObjectStore("<%= Evercookie.js_class %>", {
612
+ keyPath: "name",
613
+ unique: false
614
+ })
615
+
616
+ }
617
+
618
+ if (value !== undefined) {
619
+
620
+
621
+ request.onsuccess = function(event) {
622
+ var idb = event.target.result;
623
+ if (idb.objectStoreNames.contains("<%= Evercookie.js_class %>")) {
624
+ var tx = idb.transaction(["<%= Evercookie.js_class %>"], "readwrite");
625
+ var objst = tx.objectStore("<%= Evercookie.js_class %>");
626
+ var qr = objst.put({
627
+ "name": name,
628
+ "value": value
629
+ })
630
+ } idb.close();
296
631
  }
297
- params.swliveconnect = "true";
298
- attributes.id = "myswf";
299
- attributes.name = "myswf";
300
- swfobject.embedSWF("<%= asset_path('ec.swf') %>", "swfcontainer", "1", "1", "9.0.0", false, flashvars, params, attributes);
301
- };
302
-
303
- this.<%= Evercookie.js_class %>_png = function (name, value) {
304
- var canvas = document.createElement("canvas"),
305
- img, ctx, origvalue;
306
- canvas.style.visibility = "hidden";
307
- canvas.style.position = "absolute";
308
- canvas.width = 200;
309
- canvas.height = 1;
310
- if (canvas && canvas.getContext) {
311
- // <%= Evercookie.get_png_path %> handles the hard part of generating the image
312
- // based off of the http cookie and returning it cached
313
- img = new Image();
314
- img.style.visibility = "hidden";
315
- img.style.position = "absolute";
316
- if (value !== undefined) {
317
- // make sure we have <%= Evercookie.js_class %> session defined first
318
- document.cookie = "<%= Evercookie.cookie_png %>=" + value + "; path=<%= Evercookie.get_cookie_path %>";
632
+
633
+ } else {
634
+
635
+ request.onsuccess = function(event) {
636
+
637
+ var idb = event.target.result;
638
+
639
+ if (!idb.objectStoreNames.contains("<%= Evercookie.js_class %>")) {
640
+
641
+ self._ec.idbData = undefined;
319
642
  } else {
320
- self._ec.pngData = undefined;
321
- ctx = canvas.getContext("2d");
322
-
323
- // interestingly enough, we want to erase our <%= Evercookie.js_class %>
324
- // http cookie so will force a cached response
325
- origvalue = this.getFromStr("<%= Evercookie.cookie_png %>", document.cookie);
326
- document.cookie = "<%= Evercookie.cookie_png %>=; expires=Mon, 20 Sep 2010 00:00:00 UTC; path=<%= Evercookie.get_cookie_path %>";
327
-
328
- img.onload = function () {
329
- // put our cookie back
330
- document.cookie = "<%= Evercookie.cookie_png %>=" + origvalue + "; expires=Tue, 31 Dec 2030 00:00:00 UTC; path=<%= Evercookie.get_cookie_path %>";
331
-
332
- self._ec.pngData = "";
333
- ctx.drawImage(img, 0, 0);
334
-
335
- // get CanvasPixelArray from given coordinates and dimensions
336
- var imgd = ctx.getImageData(0, 0, 200, 1),
337
- pix = imgd.data, i, n;
338
-
339
- // loop over each pixel to get the "RGB" values (ignore alpha)
340
- for (i = 0, n = pix.length; i < n; i += 4) {
341
- if (pix[i] === 0) {
342
- break;
343
- }
344
- self._ec.pngData += String.fromCharCode(pix[i]);
345
- if (pix[i + 1] === 0) {
346
- break;
347
- }
348
- self._ec.pngData += String.fromCharCode(pix[i + 1]);
349
- if (pix[i + 2] === 0) {
350
- break;
351
- }
352
- self._ec.pngData += String.fromCharCode(pix[i + 2]);
643
+ var tx = idb.transaction(["<%= Evercookie.js_class %>"]);
644
+ var objst = tx.objectStore("<%= Evercookie.js_class %>");
645
+ var qr = objst.get(name);
646
+
647
+ qr.onsuccess = function(event) {
648
+ if (qr.result === undefined) {
649
+ self._ec.idbData = undefined
650
+ } else {
651
+ self._ec.idbData = qr.result.value;
353
652
  }
354
- };
355
- }
356
- img.src = "<%= Evercookie.get_png_path %>?name=" + name;
357
- }
358
- };
359
-
360
- this.<%= Evercookie.js_class %>_local_storage = function (name, value) {
361
- try {
362
- if (localStorage) {
363
- if (value !== undefined) {
364
- localStorage.setItem(name, value);
365
- } else {
366
- return localStorage.getItem(name);
367
- }
368
- }
369
- } catch (e) { }
370
- };
371
-
372
- this.<%= Evercookie.js_class %>_database_storage = function (name, value) {
373
- try {
374
- if (window.openDatabase) {
375
- var database = window.openDatabase("sqlite_<%= Evercookie.js_class %>", "", "<%= Evercookie.js_class %>", 1024 * 1024);
376
-
377
- if (value !== undefined) {
378
- database.transaction(function (tx) {
379
- tx.executeSql("CREATE TABLE IF NOT EXISTS cache(" +
380
- "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, " +
381
- "name TEXT NOT NULL, " +
382
- "value TEXT NOT NULL, " +
383
- "UNIQUE (name)" +
384
- ")", [], function (tx, rs) {}, function (tx, err) {});
385
- tx.executeSql("INSERT OR REPLACE INTO cache(name, value) " +
386
- "VALUES(?, ?)",
387
- [name, value], function (tx, rs) {}, function (tx, err) {});
388
- });
389
- } else {
390
- database.transaction(function (tx) {
391
- tx.executeSql("SELECT value FROM cache WHERE name=?", [name],
392
- function (tx, result1) {
393
- if (result1.rows.length >= 1) {
394
- self._ec.dbData = result1.rows.item(0).value;
395
- } else {
396
- self._ec.dbData = "";
397
- }
398
- }, function (tx, err) {});
399
- });
400
653
  }
401
654
  }
402
- } catch (e) { }
403
- };
404
-
405
- this.<%= Evercookie.js_class %>_session_storage = function (name, value) {
406
- try {
407
- if (sessionStorage) {
408
- if (value !== undefined) {
409
- sessionStorage.setItem(name, value);
410
- } else {
411
- return sessionStorage.getItem(name);
412
- }
413
- }
414
- } catch (e) { }
415
- };
416
-
417
- this.<%= Evercookie.js_class %>_global_storage = function (name, value) {
418
- if (globalStorage) {
419
- var host = this.getHost();
420
- try {
421
- if (value !== undefined) {
422
- globalStorage[host][name] = value;
423
- } else {
424
- return globalStorage[host][name];
425
- }
426
- } catch (e) { }
655
+ idb.close();
427
656
  }
428
- };
657
+ }
658
+ }
659
+ } catch (e) {}
660
+ };
661
+
662
+ this.<%= Evercookie.js_class %>_session_storage = function (name, value) {
663
+ try {
664
+ if (sessionStorage) {
665
+ if (value !== undefined) {
666
+ sessionStorage.setItem(name, value);
667
+ } else {
668
+ return sessionStorage.getItem(name);
669
+ }
670
+ }
671
+ } catch (e) { }
672
+ };
429
673
 
430
- // public method for encoding
431
- this.encode = function (input) {
432
- var output = "",
433
- chr1, chr2, chr3, enc1, enc2, enc3, enc4,
434
- i = 0;
674
+ this.<%= Evercookie.js_class %>_global_storage = function (name, value) {
675
+ if (globalStorage) {
676
+ var host = this.getHost();
677
+ try {
678
+ if (value !== undefined) {
679
+ globalStorage[host][name] = value;
680
+ } else {
681
+ return globalStorage[host][name];
682
+ }
683
+ } catch (e) { }
684
+ }
685
+ };
435
686
 
436
- input = this._utf8_encode(input);
687
+ this.<%= Evercookie.js_class %>_silverlight = function (name, value) {
688
+ /*
689
+ * Create silverlight embed
690
+ *
691
+ * Ok. so, I tried doing this the proper dom way, but IE chokes on appending anything in object tags (including params), so this
692
+ * is the best method I found. Someone really needs to find a less hack-ish way. I hate the look of this shit.
693
+ */
694
+ var source = _ec_baseurl + "<%= Evercookie.js_class %>.xap",
695
+ minver = "4.0.50401.0",
696
+ initParam = "",
697
+ html;
698
+ if (value !== undefined) {
699
+ initParam = '<param name="initParams" value="' + name + '=' + value + '" />';
700
+ }
701
+
702
+ html =
703
+ '<object style="position:absolute;left:-500px;top:-500px" data="data:application/x-silverlight-2," type="application/x-silverlight-2" id="mysilverlight" width="0" height="0">' +
704
+ initParam +
705
+ '<param name="source" value="' + source + '"/>' +
706
+ '<param name="onLoad" value="onSilverlightLoad"/>' +
707
+ '<param name="onError" value="onSilverlightError"/>' +
708
+ '<param name="background" value="Transparent"/>' +
709
+ '<param name="windowless" value="true"/>' +
710
+ '<param name="minRuntimeVersion" value="' + minver + '"/>' +
711
+ '<param name="autoUpgrade" value="false"/>' +
712
+ '<a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=' + minver + '" style="display:none">' +
713
+ 'Get Microsoft Silverlight' +
714
+ '</a>' +
715
+ '</object>';
716
+ try{
717
+ document.body.appendChild(html);
718
+ }catch(ex){
719
+
720
+ }
721
+ };
437
722
 
438
- while (i < input.length) {
723
+ // public method for encoding
724
+ this.encode = function (input) {
725
+ var output = "",
726
+ chr1, chr2, chr3, enc1, enc2, enc3, enc4,
727
+ i = 0;
439
728
 
440
- chr1 = input.charCodeAt(i++);
441
- chr2 = input.charCodeAt(i++);
442
- chr3 = input.charCodeAt(i++);
729
+ input = this._utf8_encode(input);
443
730
 
444
- enc1 = chr1 >> 2;
445
- enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
446
- enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
447
- enc4 = chr3 & 63;
731
+ while (i < input.length) {
448
732
 
449
- if (isNaN(chr2)) {
450
- enc3 = enc4 = 64;
451
- } else if (isNaN(chr3)) {
452
- enc4 = 64;
453
- }
733
+ chr1 = input.charCodeAt(i++);
734
+ chr2 = input.charCodeAt(i++);
735
+ chr3 = input.charCodeAt(i++);
454
736
 
455
- output = output +
456
- _baseKeyStr.charAt(enc1) + _baseKeyStr.charAt(enc2) +
457
- _baseKeyStr.charAt(enc3) + _baseKeyStr.charAt(enc4);
737
+ enc1 = chr1 >> 2;
738
+ enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
739
+ enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
740
+ enc4 = chr3 & 63;
458
741
 
459
- }
742
+ if (isNaN(chr2)) {
743
+ enc3 = enc4 = 64;
744
+ } else if (isNaN(chr3)) {
745
+ enc4 = 64;
746
+ }
460
747
 
461
- return output;
462
- };
748
+ output = output +
749
+ _baseKeyStr.charAt(enc1) + _baseKeyStr.charAt(enc2) +
750
+ _baseKeyStr.charAt(enc3) + _baseKeyStr.charAt(enc4);
463
751
 
464
- // public method for decoding
465
- this.decode = function (input) {
466
- var output = "",
467
- chr1, chr2, chr3,
468
- enc1, enc2, enc3, enc4,
469
- i = 0;
752
+ }
470
753
 
471
- input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
754
+ return output;
755
+ };
472
756
 
473
- while (i < input.length) {
474
- enc1 = _baseKeyStr.indexOf(input.charAt(i++));
475
- enc2 = _baseKeyStr.indexOf(input.charAt(i++));
476
- enc3 = _baseKeyStr.indexOf(input.charAt(i++));
477
- enc4 = _baseKeyStr.indexOf(input.charAt(i++));
757
+ // public method for decoding
758
+ this.decode = function (input) {
759
+ var output = "",
760
+ chr1, chr2, chr3,
761
+ enc1, enc2, enc3, enc4,
762
+ i = 0;
478
763
 
479
- chr1 = (enc1 << 2) | (enc2 >> 4);
480
- chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
481
- chr3 = ((enc3 & 3) << 6) | enc4;
764
+ input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
482
765
 
483
- output = output + String.fromCharCode(chr1);
766
+ while (i < input.length) {
767
+ enc1 = _baseKeyStr.indexOf(input.charAt(i++));
768
+ enc2 = _baseKeyStr.indexOf(input.charAt(i++));
769
+ enc3 = _baseKeyStr.indexOf(input.charAt(i++));
770
+ enc4 = _baseKeyStr.indexOf(input.charAt(i++));
484
771
 
485
- if (enc3 !== 64) {
486
- output = output + String.fromCharCode(chr2);
487
- }
488
- if (enc4 !== 64) {
489
- output = output + String.fromCharCode(chr3);
490
- }
491
- }
492
- output = this._utf8_decode(output);
493
- return output;
494
- };
495
-
496
- // private method for UTF-8 encoding
497
- this._utf8_encode = function (str) {
498
- str = str.replace(/\r\n/g, "\n");
499
- var utftext = "", i = 0, n = str.length, c;
500
- for (; i < n; i++) {
501
- c = str.charCodeAt(i);
502
- if (c < 128) {
503
- utftext += String.fromCharCode(c);
504
- } else if ((c > 127) && (c < 2048)) {
505
- utftext += String.fromCharCode((c >> 6) | 192);
506
- utftext += String.fromCharCode((c & 63) | 128);
507
- } else {
508
- utftext += String.fromCharCode((c >> 12) | 224);
509
- utftext += String.fromCharCode(((c >> 6) & 63) | 128);
510
- utftext += String.fromCharCode((c & 63) | 128);
511
- }
512
- }
513
- return utftext;
514
- };
515
-
516
- // private method for UTF-8 decoding
517
- this._utf8_decode = function (utftext) {
518
- var str = "",
519
- i = 0, n = utftext.length,
520
- c = 0, c1 = 0, c2 = 0, c3 = 0;
521
- while (i < n) {
522
- c = utftext.charCodeAt(i);
523
- if (c < 128) {
524
- str += String.fromCharCode(c);
525
- i += 1;
526
- } else if ((c > 191) && (c < 224)) {
527
- c2 = utftext.charCodeAt(i + 1);
528
- str += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
529
- i += 2;
530
- } else {
531
- c2 = utftext.charCodeAt(i + 1);
532
- c3 = utftext.charCodeAt(i + 2);
533
- str += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
534
- i += 3;
535
- }
536
- }
537
- return str;
538
- };
539
-
540
- this.createElem = function (type, name, append) {
541
- var el;
542
- if (name !== undefined && document.getElementById(name)) {
543
- el = document.getElementById(name);
544
- } else {
545
- el = document.createElement(type);
546
- }
547
- el.style.visibility = "hidden";
548
- el.style.position = "absolute";
772
+ chr1 = (enc1 << 2) | (enc2 >> 4);
773
+ chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
774
+ chr3 = ((enc3 & 3) << 6) | enc4;
549
775
 
550
- if (name) {
551
- el.setAttribute("id", name);
552
- }
776
+ output = output + String.fromCharCode(chr1);
553
777
 
554
- if (append) {
555
- document.body.appendChild(el);
556
- }
557
- return el;
558
- };
559
-
560
- this.createIframe = function (url, name) {
561
- var el = this.createElem("iframe", name, 1);
562
- el.setAttribute("src", url);
563
- return el;
564
- };
565
-
566
- // wait for our swfobject to appear (swfobject.js to load)
567
- var waitForSwf = this.waitForSwf = function (i) {
568
- if (i === undefined) {
569
- i = 0;
570
- } else {
571
- i++;
572
- }
778
+ if (enc3 !== 64) {
779
+ output = output + String.fromCharCode(chr2);
780
+ }
781
+ if (enc4 !== 64) {
782
+ output = output + String.fromCharCode(chr3);
783
+ }
784
+ }
785
+ output = this._utf8_decode(output);
786
+ return output;
787
+ };
573
788
 
574
- // wait for ~2 seconds for swfobject to appear
575
- if (i < _ec_tests && typeof swfobject === "undefined") {
576
- setTimeout(function () {
577
- waitForSwf(i);
578
- }, 300);
579
- }
580
- };
581
-
582
- this.<%= Evercookie.js_class %>_cookie = function (name, value) {
583
- if (value !== undefined) {
584
- // expire the cookie first
585
- document.cookie = name + "=; expires=Mon, 20 Sep 2010 00:00:00 UTC; path=<%= Evercookie.get_cookie_path %>";
586
- document.cookie = name + "=" + value + "; expires=Tue, 31 Dec 2030 00:00:00 UTC; path=<%= Evercookie.get_cookie_path %>";
587
- } else {
588
- return this.getFromStr(name, document.cookie);
589
- }
590
- };
789
+ // private method for UTF-8 encoding
790
+ this._utf8_encode = function (str) {
791
+ str = str.replace(/\r\n/g, "\n");
792
+ var utftext = "", i = 0, n = str.length, c;
793
+ for (; i < n; i++) {
794
+ c = str.charCodeAt(i);
795
+ if (c < 128) {
796
+ utftext += String.fromCharCode(c);
797
+ } else if ((c > 127) && (c < 2048)) {
798
+ utftext += String.fromCharCode((c >> 6) | 192);
799
+ utftext += String.fromCharCode((c & 63) | 128);
800
+ } else {
801
+ utftext += String.fromCharCode((c >> 12) | 224);
802
+ utftext += String.fromCharCode(((c >> 6) & 63) | 128);
803
+ utftext += String.fromCharCode((c & 63) | 128);
804
+ }
805
+ }
806
+ return utftext;
807
+ };
591
808
 
592
- // get value from param-like string (eg, "x=y&name=VALUE")
593
- this.getFromStr = function (name, text) {
594
- if (typeof text !== "string") {
595
- return;
596
- }
597
- var nameEQ = name + "=",
598
- ca = text.split(/[;&]/),
599
- i, c;
600
- for (i = 0; i < ca.length; i++) {
601
- c = ca[i];
602
- while (c.charAt(0) === " ") {
603
- c = c.substring(1, c.length);
604
- }
605
- if (c.indexOf(nameEQ) === 0) {
606
- return c.substring(nameEQ.length, c.length);
607
- }
608
- }
609
- };
610
-
611
- this.getHost = function () {
612
- return window.location.host.replace(/:\d+/, '');
613
- };
614
-
615
- this.toHex = function (str) {
616
- var r = "",
617
- e = str.length,
618
- c = 0,
619
- h;
620
- while (c < e) {
621
- h = str.charCodeAt(c++).toString(16);
622
- while (h.length < 2) {
623
- h = "0" + h;
809
+ // private method for UTF-8 decoding
810
+ this._utf8_decode = function (utftext) {
811
+ var str = "",
812
+ i = 0, n = utftext.length,
813
+ c = 0, c1 = 0, c2 = 0, c3 = 0;
814
+ while (i < n) {
815
+ c = utftext.charCodeAt(i);
816
+ if (c < 128) {
817
+ str += String.fromCharCode(c);
818
+ i += 1;
819
+ } else if ((c > 191) && (c < 224)) {
820
+ c2 = utftext.charCodeAt(i + 1);
821
+ str += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
822
+ i += 2;
823
+ } else {
824
+ c2 = utftext.charCodeAt(i + 1);
825
+ c3 = utftext.charCodeAt(i + 2);
826
+ str += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
827
+ i += 3;
828
+ }
829
+ }
830
+ return str;
831
+ };
832
+
833
+ // this is crazy but it's 4am in dublin and i thought this would be hilarious
834
+ // blame the guinness
835
+ this.<%= Evercookie.js_class %>_history = function (name, value) {
836
+ // - is special
837
+ var baseElems = (_baseKeyStr + "-").split(""),
838
+ // sorry google.
839
+ url = "http://www.google.com/<%= Evercookie.js_class %>/cache/" + this.getHost() + "/" + name,
840
+ i, base,
841
+ letter = "",
842
+ val = "",
843
+ found = 1;
844
+
845
+ if (value !== undefined) {
846
+ // don't reset this if we already have it set once
847
+ // too much data and you can't clear previous values
848
+ if (this.hasVisited(url)) {
849
+ return;
850
+ }
851
+
852
+ this.createIframe(url, "if");
853
+ url = url + "/";
854
+
855
+ base = this.encode(value).split("");
856
+ for (i = 0; i < base.length; i++) {
857
+ url = url + base[i];
858
+ this.createIframe(url, "if" + i);
859
+ }
860
+
861
+ // - signifies the end of our data
862
+ url = url + "-";
863
+ this.createIframe(url, "if_");
864
+ } else {
865
+ // omg you got csspwn3d
866
+ if (this.hasVisited(url)) {
867
+ url = url + "/";
868
+
869
+ while (letter !== "-" && found === 1) {
870
+ found = 0;
871
+ for (i = 0; i < baseElems.length; i++) {
872
+ if (this.hasVisited(url + baseElems[i])) {
873
+ letter = baseElems[i];
874
+ if (letter !== "-") {
875
+ val = val + letter;
624
876
  }
625
- r += h;
626
- }
627
- return r;
628
- };
629
-
630
- this.fromHex = function (str) {
631
- var r = "",
632
- e = str.length,
633
- s;
634
- while (e >= 0) {
635
- s = e - 2;
636
- r = String.fromCharCode("0x" + str.substring(s, e)) + r;
637
- e = s;
638
- }
639
- return r;
640
- };
641
-
642
- /* create our anchor tag */
643
- var _link = this.createElem("a", "_ec_rgb_link"),
644
- /* for monitoring */
645
- created_style,
646
- /* create a custom style tag for the specific link. Set the CSS visited selector to a known value */
647
- _cssText = "#_ec_rgb_link:visited{display:none;color:#FF0000}",
648
- style;
649
-
650
- /* Methods for IE6, IE7, FF, Opera, and Safari */
651
- try {
652
- created_style = 1;
653
- style = document.createElement("style");
654
- if (style.styleSheet) {
655
- style.styleSheet.innerHTML = _cssText;
656
- } else if (style.innerHTML) {
657
- style.innerHTML = _cssText;
658
- } else {
659
- style.appendChild(document.createTextNode(_cssText));
877
+ url = url + letter;
878
+ found = 1;
879
+ break;
880
+ }
660
881
  }
661
- } catch (e) {
662
- created_style = 0;
882
+ }
883
+
884
+ // lolz
885
+ return this.decode(val);
663
886
  }
887
+ }
888
+ };
664
889
 
665
- /* if test_color, return -1 if we can't set a style */
666
- this._getRGB = function (u, test_color) {
667
- if (test_color && created_style === 0) {
668
- return -1;
669
- }
890
+ this.createElem = function (type, name, append) {
891
+ var el;
892
+ if (name !== undefined && document.getElementById(name)) {
893
+ el = document.getElementById(name);
894
+ } else {
895
+ el = document.createElement(type);
896
+ }
897
+ el.style.visibility = "hidden";
898
+ el.style.position = "absolute";
899
+
900
+ if (name) {
901
+ el.setAttribute("id", name);
902
+ }
903
+
904
+ if (append) {
905
+ document.body.appendChild(el);
906
+ }
907
+ return el;
908
+ };
670
909
 
671
- /* create the new anchor tag with the appropriate URL information */
672
- _link.href = u;
673
- _link.innerHTML = u;
674
- // not sure why, but the next two appendChilds always have to happen vs just once
675
- document.body.appendChild(style);
676
- document.body.appendChild(_link);
677
-
678
- /* add the link to the DOM and save the visible computed color */
679
- var color;
680
- if (document.defaultView) {
681
- color = document.defaultView.getComputedStyle(_link, null).getPropertyValue("color");
682
- } else {
683
- color = _link.currentStyle.color;
684
- }
685
- return color;
686
- };
687
-
688
- this._testURL = function (url, no_color) {
689
- var color = this._getRGB(url);
690
-
691
- /* check to see if the link has been visited if the computed color is red */
692
- if (color === "rgb(255, 0, 0)" || color === "#ff0000") {
693
- return 1;
694
- } else if (no_color && color !== no_color) {
695
- /* if our style trick didn't work, just compare default style colors */
696
- return 1;
697
- }
698
- /* not found */
699
- return 0;
700
- };
910
+ this.createIframe = function (url, name) {
911
+ var el = this.createElem("iframe", name, 1);
912
+ el.setAttribute("src", url);
913
+ return el;
914
+ };
701
915
 
916
+ // wait for our swfobject to appear (swfobject.js to load)
917
+ var waitForSwf = this.waitForSwf = function (i) {
918
+ if (i === undefined) {
919
+ i = 0;
920
+ } else {
921
+ i++;
922
+ }
923
+
924
+ // wait for ~2 seconds for swfobject to appear
925
+ if (i < _ec_tests && typeof swfobject === "undefined") {
926
+ setTimeout(function () {
927
+ waitForSwf(i);
928
+ }, 200);
929
+ }
702
930
  };
703
- return this._class;
931
+
932
+ this.<%= Evercookie.js_class %>_cookie = function (name, value) {
933
+ if (value !== undefined) {
934
+ // expire the cookie first
935
+ document.cookie = name + "=; expires=Mon, 20 Sep 2010 00:00:00 UTC; path=/; domain=" + _ec_domain;
936
+ document.cookie = name + "=" + value + "; expires=Tue, 31 Dec 2030 00:00:00 UTC; path=/; domain=" + _ec_domain;
937
+ } else {
938
+ return this.getFromStr(name, document.cookie);
939
+ }
940
+ };
941
+
942
+ // get value from param-like string (eg, "x=y&name=VALUE")
943
+ this.getFromStr = function (name, text) {
944
+ if (typeof text !== "string") {
945
+ return;
946
+ }
947
+ var nameEQ = name + "=",
948
+ ca = text.split(/[;&]/),
949
+ i, c;
950
+ for (i = 0; i < ca.length; i++) {
951
+ c = ca[i];
952
+ while (c.charAt(0) === " ") {
953
+ c = c.substring(1, c.length);
954
+ }
955
+ if (c.indexOf(nameEQ) === 0) {
956
+ return c.substring(nameEQ.length, c.length);
957
+ }
958
+ }
959
+ };
960
+
961
+ this.getHost = function () {
962
+ return window.location.host.replace(/:\d+/, '');
963
+ };
964
+
965
+ this.toHex = function (str) {
966
+ var r = "",
967
+ e = str.length,
968
+ c = 0,
969
+ h;
970
+ while (c < e) {
971
+ h = str.charCodeAt(c++).toString(16);
972
+ while (h.length < 2) {
973
+ h = "0" + h;
974
+ }
975
+ r += h;
976
+ }
977
+ return r;
978
+ };
979
+
980
+ this.fromHex = function (str) {
981
+ var r = "",
982
+ e = str.length,
983
+ s;
984
+ while (e >= 0) {
985
+ s = e - 2;
986
+ r = String.fromCharCode("0x" + str.substring(s, e)) + r;
987
+ e = s;
988
+ }
989
+ return r;
990
+ };
991
+
992
+ /**
993
+ * css history knocker (determine what sites your visitors have been to)
994
+ *
995
+ * originally by Jeremiah Grossman
996
+ * http://jeremiahgrossman.blogspot.com/2006/08/i-know-where-youve-been.html
997
+ *
998
+ * ported to additional browsers by Samy Kamkar
999
+ *
1000
+ * compatible with ie6, ie7, ie8, ff1.5, ff2, ff3, opera, safari, chrome, flock
1001
+ *
1002
+ * - code@samy.pl
1003
+ */
1004
+ this.hasVisited = function (url) {
1005
+ if (this.no_color === -1) {
1006
+ var no_style = this._getRGB("http://never-visited.com", -1);
1007
+ if (no_style === -1) {
1008
+ this.no_color = this._getRGB("http://this-" + Math.floor(Math.random() * 9999999) + "rand.com");
1009
+ }
1010
+ }
1011
+
1012
+ // did we give full url?
1013
+ if (url.indexOf("https:") === 0 || url.indexOf("http:") === 0) {
1014
+ return this._testURL(url, this.no_color);
1015
+ }
1016
+
1017
+ // if not, just test a few diff types if (exact)
1018
+ return this._testURL("http://" + url, this.no_color) ||
1019
+ this._testURL("https://" + url, this.no_color) ||
1020
+ this._testURL("http://www." + url, this.no_color) ||
1021
+ this._testURL("https://www." + url, this.no_color);
1022
+ };
1023
+
1024
+ /* create our anchor tag */
1025
+ var _link = this.createElem("a", "_ec_rgb_link"),
1026
+ /* for monitoring */
1027
+ created_style,
1028
+ /* create a custom style tag for the specific link. Set the CSS visited selector to a known value */
1029
+ _cssText = "#_ec_rgb_link:visited{display:none;color:#FF0000}",
1030
+ style;
1031
+
1032
+ /* Methods for IE6, IE7, FF, Opera, and Safari */
1033
+ try {
1034
+ created_style = 1;
1035
+ style = document.createElement("style");
1036
+ if (style.styleSheet) {
1037
+ style.styleSheet.innerHTML = _cssText;
1038
+ } else if (style.innerHTML) {
1039
+ style.innerHTML = _cssText;
1040
+ } else {
1041
+ style.appendChild(document.createTextNode(_cssText));
1042
+ }
1043
+ } catch (e) {
1044
+ created_style = 0;
1045
+ }
1046
+
1047
+ /* if test_color, return -1 if we can't set a style */
1048
+ this._getRGB = function (u, test_color) {
1049
+ if (test_color && created_style === 0) {
1050
+ return -1;
1051
+ }
1052
+
1053
+ /* create the new anchor tag with the appropriate URL information */
1054
+ _link.href = u;
1055
+ _link.innerHTML = u;
1056
+ // not sure why, but the next two appendChilds always have to happen vs just once
1057
+ document.body.appendChild(style);
1058
+ document.body.appendChild(_link);
1059
+
1060
+ /* add the link to the DOM and save the visible computed color */
1061
+ var color;
1062
+ if (document.defaultView) {
1063
+ color = document.defaultView.getComputedStyle(_link, null).getPropertyValue("color");
1064
+ } else {
1065
+ color = _link.currentStyle.color;
1066
+ }
1067
+ return color;
1068
+ };
1069
+
1070
+ this._testURL = function (url, no_color) {
1071
+ var color = this._getRGB(url);
1072
+
1073
+ /* check to see if the link has been visited if the computed color is red */
1074
+ if (color === "rgb(255, 0, 0)" || color === "#ff0000") {
1075
+ return 1;
1076
+ } else if (no_color && color !== no_color) {
1077
+ /* if our style trick didn't work, just compare default style colors */
1078
+ return 1;
1079
+ }
1080
+ /* not found */
1081
+ return 0;
1082
+ };
1083
+
1084
+ };
1085
+
1086
+ window._<%= Evercookie.js_class %>_flash_var = _<%= Evercookie.js_class %>_flash_var;
1087
+ /**
1088
+ * Because Evercookie is a class, it should has first letter in capital
1089
+ * Keep first letter in small for legacy purpose
1090
+ * @expose Evercookie
1091
+ */
1092
+ window.<%= Evercookie.js_class %> = <%= Evercookie.js_class %>;
704
1093
  }(window));
1094
+ }catch(ex){}