evercookie 0.0.6 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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){}