ewigkeks 1.0.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 (76) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +8 -0
  3. data/Gemfile +4 -0
  4. data/Gemfile.lock +124 -0
  5. data/LICENSE.txt +20 -0
  6. data/README.md +96 -0
  7. data/Rakefile +32 -0
  8. data/app/assets/images/ewigkeks/.keep +0 -0
  9. data/app/assets/javascripts/ewigkeks.js +2 -0
  10. data/app/assets/javascripts/ewigkeks/evercookie.js.erb +1146 -0
  11. data/app/assets/javascripts/ewigkeks/swfobject-2.2.min.js +4 -0
  12. data/app/assets/stylesheets/ewigkeks/application.css +15 -0
  13. data/app/assets/swf/ec.swf +0 -0
  14. data/app/controllers/ewigkeks/application_controller.rb +4 -0
  15. data/app/controllers/ewigkeks/cookies_controller.rb +59 -0
  16. data/app/helpers/ewigkeks/application_helper.rb +4 -0
  17. data/app/views/layouts/ewigkeks/application.html.erb +14 -0
  18. data/bin/rails +12 -0
  19. data/config/routes.rb +8 -0
  20. data/ewigkeks.gemspec +23 -0
  21. data/lib/ewigkeks.rb +52 -0
  22. data/lib/ewigkeks/engine.rb +11 -0
  23. data/lib/ewigkeks/version.rb +3 -0
  24. data/lib/generators/ewigkeks/install/USAGE +9 -0
  25. data/lib/generators/ewigkeks/install/install_generator.rb +26 -0
  26. data/lib/generators/ewigkeks/install/templates/initializer.rb +7 -0
  27. data/lib/tasks/ewigkeks_tasks.rake +4 -0
  28. data/test/dummy/README.rdoc +28 -0
  29. data/test/dummy/Rakefile +6 -0
  30. data/test/dummy/app/assets/images/.keep +0 -0
  31. data/test/dummy/app/assets/javascripts/application.js +14 -0
  32. data/test/dummy/app/assets/stylesheets/application.css +15 -0
  33. data/test/dummy/app/controllers/application_controller.rb +5 -0
  34. data/test/dummy/app/controllers/concerns/.keep +0 -0
  35. data/test/dummy/app/controllers/tests_controller.rb +9 -0
  36. data/test/dummy/app/helpers/application_helper.rb +2 -0
  37. data/test/dummy/app/mailers/.keep +0 -0
  38. data/test/dummy/app/models/.keep +0 -0
  39. data/test/dummy/app/models/concerns/.keep +0 -0
  40. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  41. data/test/dummy/app/views/tests/get.html.erb +13 -0
  42. data/test/dummy/app/views/tests/set.html.erb +8 -0
  43. data/test/dummy/bin/bundle +3 -0
  44. data/test/dummy/bin/rails +4 -0
  45. data/test/dummy/bin/rake +4 -0
  46. data/test/dummy/bin/setup +29 -0
  47. data/test/dummy/config.ru +4 -0
  48. data/test/dummy/config/application.rb +26 -0
  49. data/test/dummy/config/boot.rb +5 -0
  50. data/test/dummy/config/database.yml +25 -0
  51. data/test/dummy/config/environment.rb +5 -0
  52. data/test/dummy/config/environments/development.rb +41 -0
  53. data/test/dummy/config/environments/production.rb +79 -0
  54. data/test/dummy/config/environments/test.rb +42 -0
  55. data/test/dummy/config/initializers/assets.rb +11 -0
  56. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  57. data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
  58. data/test/dummy/config/initializers/ewigkeks.rb +4 -0
  59. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  60. data/test/dummy/config/initializers/inflections.rb +16 -0
  61. data/test/dummy/config/initializers/mime_types.rb +4 -0
  62. data/test/dummy/config/initializers/session_store.rb +3 -0
  63. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  64. data/test/dummy/config/locales/en.yml +23 -0
  65. data/test/dummy/config/routes.rb +8 -0
  66. data/test/dummy/config/secrets.yml +22 -0
  67. data/test/dummy/lib/assets/.keep +0 -0
  68. data/test/dummy/log/.keep +0 -0
  69. data/test/dummy/public/404.html +67 -0
  70. data/test/dummy/public/422.html +67 -0
  71. data/test/dummy/public/500.html +66 -0
  72. data/test/dummy/public/favicon.ico +0 -0
  73. data/test/ewigkeks_test.rb +7 -0
  74. data/test/integration/navigation_test.rb +10 -0
  75. data/test/test_helper.rb +19 -0
  76. metadata +206 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0b2b550041c3c5fa379ae18574734c86084bf353
4
+ data.tar.gz: 223b0379958b31c9505ff9cb9a560f867baa2461
5
+ SHA512:
6
+ metadata.gz: 9e70c4012d64a96a99e95719da3203cb14a6af4007c78d41bcbd47143880abb0fb1dff6b4f36877b2b0e5ef078da91f21425657af45fe6bc6b8d6e8e330deed7
7
+ data.tar.gz: 21ed7bf6113b60018632efe7aa9e340df15df19c786896bb29ec68bf958cc9daee750916b9a19b4896a0e2c396ddc8a4927c0c24e8b58188bb8c560be57c25c3
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ .bundle/
2
+ log/*.log
3
+ pkg/
4
+ test/dummy/db/*.sqlite3
5
+ test/dummy/db/*.sqlite3-journal
6
+ test/dummy/log/*.log
7
+ test/dummy/tmp/
8
+ test/dummy/.sass-cache
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+ gem 'pry-rails'
data/Gemfile.lock ADDED
@@ -0,0 +1,124 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ ewigkeks (0.0.1)
5
+ chunky_png (~> 1.3)
6
+ rails (~> 4.2)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ actionmailer (4.2.0)
12
+ actionpack (= 4.2.0)
13
+ actionview (= 4.2.0)
14
+ activejob (= 4.2.0)
15
+ mail (~> 2.5, >= 2.5.4)
16
+ rails-dom-testing (~> 1.0, >= 1.0.5)
17
+ actionpack (4.2.0)
18
+ actionview (= 4.2.0)
19
+ activesupport (= 4.2.0)
20
+ rack (~> 1.6.0)
21
+ rack-test (~> 0.6.2)
22
+ rails-dom-testing (~> 1.0, >= 1.0.5)
23
+ rails-html-sanitizer (~> 1.0, >= 1.0.1)
24
+ actionview (4.2.0)
25
+ activesupport (= 4.2.0)
26
+ builder (~> 3.1)
27
+ erubis (~> 2.7.0)
28
+ rails-dom-testing (~> 1.0, >= 1.0.5)
29
+ rails-html-sanitizer (~> 1.0, >= 1.0.1)
30
+ activejob (4.2.0)
31
+ activesupport (= 4.2.0)
32
+ globalid (>= 0.3.0)
33
+ activemodel (4.2.0)
34
+ activesupport (= 4.2.0)
35
+ builder (~> 3.1)
36
+ activerecord (4.2.0)
37
+ activemodel (= 4.2.0)
38
+ activesupport (= 4.2.0)
39
+ arel (~> 6.0)
40
+ activesupport (4.2.0)
41
+ i18n (~> 0.7)
42
+ json (~> 1.7, >= 1.7.7)
43
+ minitest (~> 5.1)
44
+ thread_safe (~> 0.3, >= 0.3.4)
45
+ tzinfo (~> 1.1)
46
+ arel (6.0.0)
47
+ builder (3.2.2)
48
+ chunky_png (1.3.3)
49
+ coderay (1.1.0)
50
+ erubis (2.7.0)
51
+ globalid (0.3.2)
52
+ activesupport (>= 4.1.0)
53
+ hike (1.2.3)
54
+ i18n (0.7.0)
55
+ json (1.8.2)
56
+ loofah (2.0.1)
57
+ nokogiri (>= 1.5.9)
58
+ mail (2.6.3)
59
+ mime-types (>= 1.16, < 3)
60
+ method_source (0.8.2)
61
+ mime-types (2.4.3)
62
+ mini_portile (0.6.2)
63
+ minitest (5.5.1)
64
+ multi_json (1.10.1)
65
+ nokogiri (1.6.6.2)
66
+ mini_portile (~> 0.6.0)
67
+ pry (0.10.1)
68
+ coderay (~> 1.1.0)
69
+ method_source (~> 0.8.1)
70
+ slop (~> 3.4)
71
+ pry-rails (0.3.2)
72
+ pry (>= 0.9.10)
73
+ rack (1.6.0)
74
+ rack-test (0.6.3)
75
+ rack (>= 1.0)
76
+ rails (4.2.0)
77
+ actionmailer (= 4.2.0)
78
+ actionpack (= 4.2.0)
79
+ actionview (= 4.2.0)
80
+ activejob (= 4.2.0)
81
+ activemodel (= 4.2.0)
82
+ activerecord (= 4.2.0)
83
+ activesupport (= 4.2.0)
84
+ bundler (>= 1.3.0, < 2.0)
85
+ railties (= 4.2.0)
86
+ sprockets-rails
87
+ rails-deprecated_sanitizer (1.0.3)
88
+ activesupport (>= 4.2.0.alpha)
89
+ rails-dom-testing (1.0.5)
90
+ activesupport (>= 4.2.0.beta, < 5.0)
91
+ nokogiri (~> 1.6.0)
92
+ rails-deprecated_sanitizer (>= 1.0.1)
93
+ rails-html-sanitizer (1.0.1)
94
+ loofah (~> 2.0)
95
+ railties (4.2.0)
96
+ actionpack (= 4.2.0)
97
+ activesupport (= 4.2.0)
98
+ rake (>= 0.8.7)
99
+ thor (>= 0.18.1, < 2.0)
100
+ rake (10.4.2)
101
+ slop (3.6.0)
102
+ sprockets (2.12.3)
103
+ hike (~> 1.2)
104
+ multi_json (~> 1.0)
105
+ rack (~> 1.0)
106
+ tilt (~> 1.1, != 1.3.0)
107
+ sprockets-rails (2.2.4)
108
+ actionpack (>= 3.0)
109
+ activesupport (>= 3.0)
110
+ sprockets (>= 2.8, < 4.0)
111
+ sqlite3 (1.3.10)
112
+ thor (0.19.1)
113
+ thread_safe (0.3.4)
114
+ tilt (1.4.1)
115
+ tzinfo (1.2.2)
116
+ thread_safe (~> 0.1)
117
+
118
+ PLATFORMS
119
+ ruby
120
+
121
+ DEPENDENCIES
122
+ ewigkeks!
123
+ pry-rails
124
+ sqlite3
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2015 VersaCommerce
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,96 @@
1
+ # Ewigkeks
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/ewigkeks.svg)](http://badge.fury.io/rb/ewigkeks)
4
+
5
+ Ewigkeks is a library for integrating the [evercookie](http://samy.pl/evercookie/ "evercookie") JavaScript library into your Rails application. It saves and retrieves key-value-pairs in different client/browser storages.
6
+
7
+ ## Requirements
8
+
9
+ - Ruby ≥ 1.9.3
10
+ - Rails ~> 4.0
11
+
12
+ ## Installation
13
+
14
+ Add this line to your application's Gemfile:
15
+
16
+ ```ruby
17
+ gem 'ewigkeks'
18
+ ```
19
+
20
+ execute:
21
+
22
+ ```sh
23
+ $ bundle install
24
+ ```
25
+
26
+ and run:
27
+
28
+ ```sh
29
+ $ bin/rails generate ewigkeks:install
30
+ ```
31
+
32
+ ## Usage
33
+
34
+ In order to set an evercookie, call this JavaScript in your view:
35
+
36
+ ```erb
37
+ var evercookie = new <%= Ewigkeks.js_class %>();
38
+ evercookie.set('foo', 'bar');
39
+ ```
40
+
41
+ This evercookie is accessible later on by using the `get` function:
42
+
43
+ ```erb
44
+ var evercookie = new <%= Ewigkeks.js_class %>();
45
+
46
+ evercookie.get('foo', function(value) {
47
+ // do something with the value
48
+ });
49
+ ```
50
+
51
+ Per default, evercookie will repopulate missing key-value-pairs to the client/browser storages when calling the `get` function. If you explicitely do not want this behaviour, call `get` with an additional argument like this:
52
+
53
+ ```
54
+ var evercookie = new <%= Ewigkeks.js_class %>();
55
+
56
+ evercookie.get('foo', function(value) {
57
+ // do something with the value
58
+ }, 1);
59
+ ```
60
+
61
+ `1` tells evercookie to not repopulate, 0 tells it to repopulate (default).
62
+
63
+ ## Optional Configuration
64
+
65
+ When running the install generator, Ewigkeks will add an initializer to your Rails application with several configuration options:
66
+
67
+ | Option | Default | Meaning |
68
+ | :-----------------: | :-------------------: | ------------------------------------------------------------------ |
69
+ | `js_class` | `'evercookie'` | Changes the evercookie function name inside the JavaScript library |
70
+ | `scope` | `'ewigkeks'` | Changes the route under which the Ewigkeks controller gets called |
71
+ | `png_cookie_name` | `"#{js_class}_png"` | Changes the cookie name for the PNG storage |
72
+ | `cache_cookie_name` | `"#{js_class}_cache"` | Changes the cookie name for the Cache storage |
73
+ | `etag_cookie_name` | `"#{js_class}_etag"` | Changes the cookie name for the ETAG storage |
74
+
75
+ ## License
76
+
77
+ Copyright 2015 VersaCommerce
78
+
79
+ Permission is hereby granted, free of charge, to any person obtaining
80
+ a copy of this software and associated documentation files (the
81
+ "Software"), to deal in the Software without restriction, including
82
+ without limitation the rights to use, copy, modify, merge, publish,
83
+ distribute, sublicense, and/or sell copies of the Software, and to
84
+ permit persons to whom the Software is furnished to do so, subject to
85
+ the following conditions:
86
+
87
+ The above copyright notice and this permission notice shall be
88
+ included in all copies or substantial portions of the Software.
89
+
90
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
91
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
92
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
93
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
94
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
95
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
96
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,32 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'Ewigkeks'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.rdoc')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
18
+ load 'rails/tasks/engine.rake'
19
+ load 'rails/tasks/statistics.rake'
20
+
21
+ Bundler::GemHelper.install_tasks
22
+
23
+ require 'rake/testtask'
24
+
25
+ Rake::TestTask.new(:test) do |t|
26
+ t.libs << 'lib'
27
+ t.libs << 'test'
28
+ t.pattern = 'test/**/*_test.rb'
29
+ t.verbose = false
30
+ end
31
+
32
+ task default: :test
File without changes
@@ -0,0 +1,2 @@
1
+ //= require ewigkeks/swfobject-2.2.min
2
+ //= require ewigkeks/evercookie
@@ -0,0 +1,1146 @@
1
+ /*jslint browser: true, nomen: false, plusplus: false, bitwise: false, maxerr: 50, indent: 2 */
2
+ /**
3
+ * @depends swfobject-2.2.min.js
4
+ *
5
+ * evercookie 0.4 (10/13/2010) -- extremely persistent cookies
6
+ *
7
+ * by samy kamkar : code@samy.pl : http://samy.pl
8
+ *
9
+ * this api attempts to produce several types of persistent data
10
+ * to essentially make a cookie virtually irrevocable from a system
11
+ *
12
+ * specifically it uses:
13
+ * - standard http cookies
14
+ * - flash cookies (local shared objects)
15
+ * - silverlight isolated storage
16
+ * - png generation w/forced cache and html5 canvas pixel reading
17
+ * - http etags
18
+ * - http cache
19
+ * - window.name
20
+ * - IE userData
21
+ * - html5 session cookies
22
+ * - html5 local storage
23
+ * - html5 global storage
24
+ * - html5 database storage via sqlite
25
+ * - css history scanning
26
+ * - Java JNLP PersistenceService
27
+ * - Java exploit
28
+ *
29
+ * if any cookie is found, it's then reset to all the other locations
30
+ * for example, if someone deletes all but one type of cookie, once
31
+ * that cookie is re-discovered, all of the other cookie types get reset
32
+ *
33
+ * !!! SOME OF THESE ARE CROSS-DOMAIN COOKIES, THIS MEANS
34
+ * OTHER SITES WILL BE ABLE TO READ SOME OF THESE COOKIES !!!
35
+ *
36
+ * USAGE:
37
+
38
+ var ec = new evercookie();
39
+
40
+ // set a cookie "id" to "12345"
41
+ // usage: ec.set(key, value)
42
+ ec.set("id", "12345");
43
+
44
+ // retrieve a cookie called "id" (simply)
45
+ ec.get("id", function(value) { alert("Cookie value is " + value) });
46
+
47
+ // or use a more advanced callback function for getting our cookie
48
+ // the cookie value is the first param
49
+ // an object containing the different storage methods
50
+ // and returned cookie values is the second parameter
51
+ function getCookie(best_candidate, all_candidates)
52
+ {
53
+ alert("The retrieved cookie is: " + best_candidate + "\n" +
54
+ "You can see what each storage mechanism returned " +
55
+ "by looping through the all_candidates object.");
56
+
57
+ for (var item in all_candidates)
58
+ document.write("Storage mechanism " + item +
59
+ " returned " + all_candidates[item] + " votes<br>");
60
+ }
61
+ ec.get("id", getCookie);
62
+
63
+ // we look for "candidates" based off the number of "cookies" that
64
+ // come back matching since it's possible for mismatching cookies.
65
+ // the best candidate is very-very-likely the correct one
66
+
67
+ */
68
+ try{
69
+ (function (window) {
70
+ 'use strict';
71
+ var document = window.document,
72
+ Image = window.Image,
73
+ globalStorage = window.globalStorage,
74
+ swfobject = window.swfobject;
75
+
76
+ try{
77
+ var localStore = window.localStorage
78
+ }catch(ex){}
79
+
80
+ try {
81
+ var sessionStorage = window.sessionStorage;
82
+ } catch (e) { }
83
+
84
+ function newImage(src) {
85
+ var img = new Image();
86
+ img.style.visibility = "hidden";
87
+ img.style.position = "absolute";
88
+ img.src = src;
89
+ }
90
+ function _ec_replace(str, key, value) {
91
+ if (str.indexOf("&" + key + "=") > -1 || str.indexOf(key + "=") === 0) {
92
+ // find start
93
+ var idx = str.indexOf("&" + key + "="),
94
+ end, newstr;
95
+ if (idx === -1) {
96
+ idx = str.indexOf(key + "=");
97
+ }
98
+ // find end
99
+ end = str.indexOf("&", idx + 1);
100
+ if (end !== -1) {
101
+ newstr = str.substr(0, idx) + str.substr(end + (idx ? 0 : 1)) + "&" + key + "=" + value;
102
+ } else {
103
+ newstr = str.substr(0, idx) + "&" + key + "=" + value;
104
+ }
105
+ return newstr;
106
+ } else {
107
+ return str + "&" + key + "=" + value;
108
+ }
109
+ }
110
+
111
+ function idb() {
112
+ if ('indexedDB' in window) {
113
+ return true
114
+ } else if (window.indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB) {
115
+ return true
116
+ } else {
117
+ return false
118
+ }
119
+ }
120
+
121
+ // necessary for flash to communicate with js...
122
+ // please implement a better way
123
+ var _global_lso;
124
+ function _<%= Ewigkeks.js_class %>_flash_var(cookie) {
125
+ _global_lso = cookie;
126
+
127
+ // remove the flash object now
128
+ var swf = document.getElementById("myswf");
129
+ if (swf && swf.parentNode) {
130
+ swf.parentNode.removeChild(swf);
131
+ }
132
+ }
133
+
134
+ /*
135
+ * Again, ugly workaround....same problem as flash.
136
+ */
137
+ var _global_isolated;
138
+ function onSilverlightLoad(sender, args) {
139
+ var control = sender.getHost();
140
+ _global_isolated = control.Content.App.getIsolatedStorage();
141
+ }
142
+
143
+ function onSilverlightError(sender, args) {
144
+ _global_isolated = "";
145
+ }
146
+
147
+ var defaultOptionMap = {
148
+ history: false, // CSS history knocking or not .. can be network intensive
149
+ java: true, // Java applet on/off... may prompt users for permission to run.
150
+ tests: 10, // 1000 what is it, actually?
151
+ silverlight: true, // you might want to turn it off https://github.com/samyk/evercookie/issues/45
152
+ domain: '.' + window.location.host.replace(/:\d+/, ''), // Get current domain
153
+ baseurl: '', // base url for php, flash and silverlight assets
154
+ asseturi: '', // assets = .fla, .jar, etc
155
+ phpuri: '', // php file path or route
156
+ authPath: false, // set to false to disable Basic Authentication cache
157
+ pngCookieName: '<%= Ewigkeks.png_cookie_name %>',
158
+ pngPath: '<%= Ewigkeks.png_path %>',
159
+ etagCookieName: '<%= Ewigkeks.etag_cookie_name %>',
160
+ etagPath: '<%= Ewigkeks.etag_path %>',
161
+ cacheCookieName: '<%= Ewigkeks.cache_cookie_name %>',
162
+ cachePath: '<%= Ewigkeks.cache_path %>'
163
+ };
164
+
165
+ var _baseKeyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
166
+ /**
167
+ * @class Evercookie
168
+ * @param {Object} options
169
+ * @param {Boolean} options.history CSS history knocking or not .. can be network intensive
170
+ * @param {Boolean} options.java Java applet on/off... may prompt users for permission to run.
171
+ * @param {Number} options.tests
172
+ * @param {Boolean} options.silverlight you might want to turn it off https://github.com/samyk/evercookie/issues/45
173
+ * @param {String} options.domain (eg: www.sitename.com use .sitename.com)
174
+ * @param {String} options.baseurl base url (eg: www.sitename.com/demo use /demo)
175
+ * @param {String} options.asseturi asset path (eg: www.sitename.com/assets use /assets)
176
+ * @param {String} options.phpuri php path/route (eg: www.sitename.com/php use /php)
177
+ * @param {String|Function} options.domain as a string, domain for cookie, as a function, accept window object and return domain string
178
+ * @param {String} options.pngCookieName
179
+ * @param {String} options.pngPath
180
+ * @param {String} options.etagCookieName:
181
+ * @param {String} options.etagPath
182
+ * @param {String} options.cacheCookieName
183
+ * @param {String} options.cachePath
184
+ */
185
+ function <%= Ewigkeks.js_class %>(options) {
186
+ options = options || {};
187
+ var opts = {};
188
+ for (var key in defaultOptionMap) {
189
+ var optValue = options[key];
190
+ if(typeof optValue !== 'undefined') {
191
+ opts[key] = optValue
192
+ } else {
193
+ opts[key] = defaultOptionMap[key];
194
+ }
195
+ }
196
+ if(typeof opts.domain === 'function'){
197
+ opts.domain = opts.domain(window);
198
+ }
199
+ var _ec_history = opts.history,
200
+ _ec_java = opts.java,
201
+ _ec_tests = opts.tests,
202
+ _ec_baseurl = opts.baseurl,
203
+ _ec_asseturi = opts.asseturi,
204
+ _ec_phpuri = opts.phpuri,
205
+ _ec_domain = opts.domain;
206
+
207
+ // private property
208
+ var self = this;
209
+ this._ec = {};
210
+
211
+ this.get = function (name, cb, dont_reset) {
212
+ self._<%= Ewigkeks.js_class %>(name, cb, undefined, undefined, dont_reset);
213
+ };
214
+
215
+ this.set = function (name, value) {
216
+ self._<%= Ewigkeks.js_class %>(name, function () {}, value);
217
+ };
218
+
219
+ this._<%= Ewigkeks.js_class %> = function (name, cb, value, i, dont_reset) {
220
+ if (self._<%= Ewigkeks.js_class %> === undefined) {
221
+ self = this;
222
+ }
223
+ if (i === undefined) {
224
+ i = 0;
225
+ }
226
+ // first run
227
+ if (i === 0) {
228
+ self.<%= Ewigkeks.js_class %>_database_storage(name, value);
229
+ self.<%= Ewigkeks.js_class %>_indexdb_storage(name, value);
230
+ self.<%= Ewigkeks.js_class %>_png(name, value);
231
+ self.<%= Ewigkeks.js_class %>_etag(name, value);
232
+ self.<%= Ewigkeks.js_class %>_cache(name, value);
233
+ self.<%= Ewigkeks.js_class %>_lso(name, value);
234
+ if (opts.silverlight) {
235
+ self.<%= Ewigkeks.js_class %>_silverlight(name, value);
236
+ }
237
+ if (opts.authPath) {
238
+ self.<%= Ewigkeks.js_class %>_auth(name, value);
239
+ }
240
+ if (_ec_java) {
241
+ self.<%= Ewigkeks.js_class %>_java(name, value);
242
+ }
243
+
244
+ self._ec.userData = self.<%= Ewigkeks.js_class %>_userdata(name, value);
245
+ self._ec.cookieData = self.<%= Ewigkeks.js_class %>_cookie(name, value);
246
+ self._ec.localData = self.<%= Ewigkeks.js_class %>_local_storage(name, value);
247
+ self._ec.globalData = self.<%= Ewigkeks.js_class %>_global_storage(name, value);
248
+ self._ec.sessionData = self.<%= Ewigkeks.js_class %>_session_storage(name, value);
249
+ self._ec.windowData = self.<%= Ewigkeks.js_class %>_window(name, value);
250
+
251
+ if (_ec_history) {
252
+ self._ec.historyData = self.<%= Ewigkeks.js_class %>_history(name, value);
253
+ }
254
+ }
255
+
256
+ // when writing data, we need to make sure lso and silverlight object is there
257
+ if (value !== undefined) {
258
+ if ((typeof _global_lso === "undefined" ||
259
+ typeof _global_isolated === "undefined") &&
260
+ i++ < _ec_tests) {
261
+ setTimeout(function () {
262
+ self._<%= Ewigkeks.js_class %>(name, cb, value, i, dont_reset);
263
+ }, 300);
264
+ }
265
+ }
266
+
267
+ // when reading data, we need to wait for swf, db, silverlight, java and png
268
+ else
269
+ {
270
+ if (
271
+ (
272
+ // we support local db and haven't read data in yet
273
+ (window.openDatabase && typeof self._ec.dbData === "undefined") ||
274
+ (idb() && (typeof self._ec.idbData === "undefined" || self._ec.idbData === "")) ||
275
+ (typeof _global_lso === "undefined") ||
276
+ (typeof self._ec.etagData === "undefined") ||
277
+ (typeof self._ec.cacheData === "undefined") ||
278
+ (typeof self._ec.javaData === "undefined") ||
279
+ (document.createElement("canvas").getContext && (typeof self._ec.pngData === "undefined" || self._ec.pngData === "")) ||
280
+ (typeof _global_isolated === "undefined")
281
+ ) &&
282
+ i++ < _ec_tests
283
+ )
284
+ {
285
+ setTimeout(function () {
286
+ self._<%= Ewigkeks.js_class %>(name, cb, value, i, dont_reset);
287
+ }, 300);
288
+ }
289
+
290
+ // we hit our max wait time or got all our data
291
+ else
292
+ {
293
+ // get just the piece of data we need from swf
294
+ self._ec.lsoData = self.getFromStr(name, _global_lso);
295
+ _global_lso = undefined;
296
+
297
+ // get just the piece of data we need from silverlight
298
+ self._ec.slData = self.getFromStr(name, _global_isolated);
299
+ _global_isolated = undefined;
300
+
301
+ var tmpec = self._ec,
302
+ candidates = [],
303
+ bestnum = 0,
304
+ candidate,
305
+ item;
306
+ self._ec = {};
307
+
308
+ // figure out which is the best candidate
309
+ for (item in tmpec) {
310
+ if (tmpec[item] && tmpec[item] !== "null" && tmpec[item] !== "undefined") {
311
+ candidates[tmpec[item]] = candidates[tmpec[item]] === undefined ? 1 : candidates[tmpec[item]] + 1;
312
+ }
313
+ }
314
+
315
+ for (item in candidates) {
316
+ if (candidates[item] > bestnum) {
317
+ bestnum = candidates[item];
318
+ candidate = item;
319
+ }
320
+ }
321
+
322
+ // reset cookie everywhere
323
+ if (candidate !== undefined && (dont_reset === undefined || dont_reset !== 1)) {
324
+ self.set(name, candidate);
325
+ }
326
+ if (typeof cb === "function") {
327
+ cb(candidate, tmpec);
328
+ }
329
+ }
330
+ }
331
+ };
332
+
333
+ this.<%= Ewigkeks.js_class %>_window = function (name, value) {
334
+ try {
335
+ if (value !== undefined) {
336
+ window.name = _ec_replace(window.name, name, value);
337
+ } else {
338
+ return this.getFromStr(name, window.name);
339
+ }
340
+ } catch (e) { }
341
+ };
342
+
343
+ this.<%= Ewigkeks.js_class %>_userdata = function (name, value) {
344
+ try {
345
+ var elm = this.createElem("div", "userdata_el", 1);
346
+ elm.style.behavior = "url(#default#userData)";
347
+
348
+ if (value !== undefined) {
349
+ elm.setAttribute(name, value);
350
+ elm.save(name);
351
+ } else {
352
+ elm.load(name);
353
+ return elm.getAttribute(name);
354
+ }
355
+ } catch (e) {}
356
+ };
357
+
358
+ this.ajax = function (settings) {
359
+ var headers, name, transports, transport, i, length;
360
+
361
+ headers = {
362
+ 'X-Requested-With': 'XMLHttpRequest',
363
+ 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
364
+ };
365
+
366
+ transports = [
367
+ function () { return new XMLHttpRequest(); },
368
+ function () { return new ActiveXObject('Msxml2.XMLHTTP'); },
369
+ function () { return new ActiveXObject('Microsoft.XMLHTTP'); }
370
+ ];
371
+
372
+ for (i = 0, length = transports.length; i < length; i++) {
373
+ transport = transports[i];
374
+ try {
375
+ transport = transport();
376
+ break;
377
+ } catch (e) {
378
+ }
379
+ }
380
+
381
+ transport.onreadystatechange = function () {
382
+ if (transport.readyState !== 4) {
383
+ return;
384
+ }
385
+ settings.success(transport.responseText);
386
+ };
387
+ transport.open('get', settings.url, true);
388
+ for (name in headers) {
389
+ transport.setRequestHeader(name, headers[name]);
390
+ }
391
+ transport.send();
392
+ };
393
+
394
+ this.<%= Ewigkeks.js_class %>_cache = function (name, value) {
395
+ if (value !== undefined) {
396
+ // make sure we have evercookie session defined first
397
+ document.cookie = opts.cacheCookieName + "=" + value + "; path=/; domain=" + _ec_domain;
398
+ // {{ajax request to opts.cachePath}} handles caching
399
+ self.ajax({
400
+ url: _ec_baseurl + _ec_phpuri + opts.cachePath + "?name=" + name + "&cookie=" + opts.cacheCookieName,
401
+ success: function (data) {}
402
+ });
403
+ } else {
404
+ // interestingly enough, we want to erase our evercookie
405
+ // http cookie so the php will force a cached response
406
+ var origvalue = this.getFromStr(opts.cacheCookieName, document.cookie);
407
+ self._ec.cacheData = undefined;
408
+ document.cookie = opts.cacheCookieName + "=; expires=Mon, 20 Sep 2010 00:00:00 UTC; path=/; domain=" + _ec_domain;
409
+
410
+ self.ajax({
411
+ url: _ec_baseurl + _ec_phpuri + opts.cachePath + "?name=" + name + "&cookie=" + opts.cacheCookieName,
412
+ success: function (data) {
413
+ // put our cookie back
414
+ document.cookie = opts.cacheCookieName + "=" + origvalue + "; expires=Tue, 31 Dec 2030 00:00:00 UTC; path=/; domain=" + _ec_domain;
415
+
416
+ self._ec.cacheData = data;
417
+ }
418
+ });
419
+ }
420
+ };
421
+ this.<%= Ewigkeks.js_class %>_auth = function (name, value) {
422
+ if (value !== undefined) {
423
+ // {{opts.authPath}} handles Basic Access Authentication
424
+ newImage('//' + value + '@' + location.host + _ec_baseurl + _ec_phpuri + opts.authPath + "?name=" + name);
425
+ }
426
+ else {
427
+ self.ajax({
428
+ url: _ec_baseurl + _ec_phpuri + opts.authPath + "?name=" + name,
429
+ success: function (data) {
430
+ self._ec.authData = data;
431
+ }
432
+ });
433
+ }
434
+ };
435
+
436
+ this.<%= Ewigkeks.js_class %>_etag = function (name, value) {
437
+ if (value !== undefined) {
438
+ // make sure we have evercookie session defined first
439
+ document.cookie = opts.etagCookieName + "=" + value + "; path=/; domain=" + _ec_domain;
440
+ // {{ajax request to opts.etagPath}} handles etagging
441
+ self.ajax({
442
+ url: _ec_baseurl + _ec_phpuri + opts.etagPath + "?name=" + name + "&cookie=" + opts.etagCookieName,
443
+ success: function (data) {}
444
+ });
445
+ } else {
446
+ // interestingly enough, we want to erase our evercookie
447
+ // http cookie so the php will force a cached response
448
+ var origvalue = this.getFromStr(opts.etagCookieName, document.cookie);
449
+ self._ec.etagData = undefined;
450
+ document.cookie = opts.etagCookieName + "=; expires=Mon, 20 Sep 2010 00:00:00 UTC; path=/; domain=" + _ec_domain;
451
+
452
+ self.ajax({
453
+ url: _ec_baseurl + _ec_phpuri + opts.etagPath + "?name=" + name + "&cookie=" + opts.etagCookieName,
454
+ success: function (data) {
455
+ // put our cookie back
456
+ document.cookie = opts.etagCookieName + "=" + origvalue + "; expires=Tue, 31 Dec 2030 00:00:00 UTC; path=/; domain=" + _ec_domain;
457
+
458
+ self._ec.etagData = data;
459
+ }
460
+ });
461
+ }
462
+ };
463
+
464
+ this.<%= Ewigkeks.js_class %>_java = function (name, value) {
465
+ var div = document.getElementById("ecAppletContainer");
466
+
467
+ // Exit if dtjava.js was not included in the page header.
468
+ if (typeof dtjava === "undefined") {
469
+ return;
470
+ }
471
+
472
+ // Create the container div if none exists.
473
+ if (div===null || div === undefined || !div.length) {
474
+ div = document.createElement("div");
475
+ div.setAttribute("id", "ecAppletContainer");
476
+ div.style.position = "absolute";
477
+ div.style.top = "-3000px";
478
+ div.style.left = "-3000px";
479
+ div.style.width = "1px";
480
+ div.style.height = "1px";
481
+ document.body.appendChild(div);
482
+ }
483
+
484
+ // If the Java applet is not yet defined, embed it.
485
+ if (typeof ecApplet === "undefined") {
486
+ dtjava.embed({
487
+ id: "ecApplet",
488
+ url: _ec_baseurl + _ec_asseturi + "/evercookie.jnlp",
489
+ width: "1px",
490
+ height: "1px",
491
+ placeholder: "ecAppletContainer"
492
+ }, {},{ onJavascriptReady: doSetOrGet });
493
+ // When the applet is loaded we will continue in doSetOrGet()
494
+ }
495
+ else {
496
+ // applet already running... call doGetOrSet() directly.
497
+ doSetOrGet("ecApplet");
498
+ }
499
+
500
+ function doSetOrGet(appletId) {
501
+ var applet = document.getElementById(appletId);
502
+ if (value !== undefined) {
503
+ applet.set(name,value);
504
+ }
505
+ else {
506
+ self._ec.javaData = applet.get(name);
507
+ }
508
+ }
509
+
510
+ // The result of a get() is now in self._ec._javaData
511
+ };
512
+
513
+ this.<%= Ewigkeks.js_class %>_lso = function (name, value) {
514
+ var div = document.getElementById("swfcontainer"),
515
+ flashvars = {},
516
+ params = {},
517
+ attributes = {};
518
+ if (div===null || div === undefined || !div.length) {
519
+ div = document.createElement("div");
520
+ div.setAttribute("id", "swfcontainer");
521
+ document.body.appendChild(div);
522
+ }
523
+
524
+ if (value !== undefined) {
525
+ flashvars.everdata = name + "=" + value;
526
+ }
527
+ params.swliveconnect = "true";
528
+ attributes.id = "myswf";
529
+ attributes.name = "myswf";
530
+ swfobject.embedSWF("<%= asset_path('ec.swf') %>", "swfcontainer", "1", "1", "9.0.0", false, flashvars, params, attributes);
531
+ };
532
+
533
+ this.<%= Ewigkeks.js_class %>_png = function (name, value) {
534
+ var canvas = document.createElement("canvas"),
535
+ img, ctx, origvalue;
536
+ canvas.style.visibility = "hidden";
537
+ canvas.style.position = "absolute";
538
+ canvas.width = 200;
539
+ canvas.height = 1;
540
+ if (canvas && canvas.getContext) {
541
+ // {{opts.pngPath}} handles the hard part of generating the image
542
+ // based off of the http cookie and returning it cached
543
+ img = new Image();
544
+ img.style.visibility = "hidden";
545
+ img.style.position = "absolute";
546
+ if (value !== undefined) {
547
+ // make sure we have evercookie session defined first
548
+ document.cookie = opts.pngCookieName + "=" + value + "; path=/; domain=" + _ec_domain;
549
+ } else {
550
+ self._ec.pngData = undefined;
551
+ ctx = canvas.getContext("2d");
552
+
553
+ // interestingly enough, we want to erase our evercookie
554
+ // http cookie so the php will force a cached response
555
+ origvalue = this.getFromStr(opts.pngCookieName, document.cookie);
556
+ document.cookie = opts.pngCookieName + "=; expires=Mon, 20 Sep 2010 00:00:00 UTC; path=/; domain=" + _ec_domain;
557
+
558
+ img.onload = function () {
559
+ // put our cookie back
560
+ document.cookie = opts.pngCookieName + "=" + origvalue + "; expires=Tue, 31 Dec 2030 00:00:00 UTC; path=/; domain=" + _ec_domain;
561
+
562
+ self._ec.pngData = "";
563
+ ctx.drawImage(img, 0, 0);
564
+
565
+ // get CanvasPixelArray from given coordinates and dimensions
566
+ var imgd = ctx.getImageData(0, 0, 200, 1),
567
+ pix = imgd.data, i, n;
568
+
569
+ // loop over each pixel to get the "RGB" values (ignore alpha)
570
+ for (i = 0, n = pix.length; i < n; i += 4) {
571
+ if (pix[i] === 0) {
572
+ break;
573
+ }
574
+ self._ec.pngData += String.fromCharCode(pix[i]);
575
+ if (pix[i + 1] === 0) {
576
+ break;
577
+ }
578
+ self._ec.pngData += String.fromCharCode(pix[i + 1]);
579
+ if (pix[i + 2] === 0) {
580
+ break;
581
+ }
582
+ self._ec.pngData += String.fromCharCode(pix[i + 2]);
583
+ }
584
+ };
585
+ }
586
+ img.src = _ec_baseurl + _ec_phpuri + opts.pngPath + "?name=" + name + "&cookie=" + opts.pngCookieName;
587
+ }
588
+ };
589
+
590
+ this.<%= Ewigkeks.js_class %>_local_storage = function (name, value) {
591
+ try {
592
+ if (localStore) {
593
+ if (value !== undefined) {
594
+ localStore.setItem(name, value);
595
+ } else {
596
+ return localStore.getItem(name);
597
+ }
598
+ }
599
+ } catch (e) { }
600
+ };
601
+
602
+ this.<%= Ewigkeks.js_class %>_database_storage = function (name, value) {
603
+ try {
604
+ if (window.openDatabase) {
605
+ var database = window.openDatabase("sqlite_<%= Ewigkeks.js_class %>", "", "<%= Ewigkeks.js_class %>", 1024 * 1024);
606
+
607
+ if (value !== undefined) {
608
+ database.transaction(function (tx) {
609
+ tx.executeSql("CREATE TABLE IF NOT EXISTS cache(" +
610
+ "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, " +
611
+ "name TEXT NOT NULL, " +
612
+ "value TEXT NOT NULL, " +
613
+ "UNIQUE (name)" +
614
+ ")", [], function (tx, rs) {}, function (tx, err) {});
615
+ tx.executeSql("INSERT OR REPLACE INTO cache(name, value) " +
616
+ "VALUES(?, ?)",
617
+ [name, value], function (tx, rs) {}, function (tx, err) {});
618
+ });
619
+ } else {
620
+ database.transaction(function (tx) {
621
+ tx.executeSql("SELECT value FROM cache WHERE name=?", [name],
622
+ function (tx, result1) {
623
+ if (result1.rows.length >= 1) {
624
+ self._ec.dbData = result1.rows.item(0).value;
625
+ } else {
626
+ self._ec.dbData = "";
627
+ }
628
+ }, function (tx, err) {});
629
+ });
630
+ }
631
+ }
632
+ } catch (e) { }
633
+ };
634
+
635
+ this.<%= Ewigkeks.js_class %>_indexdb_storage = function(name, value) {
636
+ try {
637
+ if (!('indexedDB' in window)) {
638
+
639
+ indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
640
+ IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.msIDBTransaction;
641
+ IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.msIDBKeyRange;
642
+ }
643
+
644
+ if (indexedDB) {
645
+ var ver = 1;
646
+ //FF incognito mode restricts indexedb access
647
+ var request = indexedDB.open("idb_<%= Ewigkeks.js_class %>", ver);
648
+
649
+
650
+ request.onerror = function(e) { ;
651
+ }
652
+
653
+ request.onupgradeneeded = function(event) {
654
+ var db = event.target.result;
655
+
656
+ var store = db.createObjectStore("<%= Ewigkeks.js_class %>", {
657
+ keyPath: "name",
658
+ unique: false
659
+ })
660
+
661
+ }
662
+
663
+ if (value !== undefined) {
664
+
665
+
666
+ request.onsuccess = function(event) {
667
+ var idb = event.target.result;
668
+ if (idb.objectStoreNames.contains("<%= Ewigkeks.js_class %>")) {
669
+ var tx = idb.transaction(["<%= Ewigkeks.js_class %>"], "readwrite");
670
+ var objst = tx.objectStore("<%= Ewigkeks.js_class %>");
671
+ var qr = objst.put({
672
+ "name": name,
673
+ "value": value
674
+ })
675
+ } idb.close();
676
+ }
677
+
678
+ } else {
679
+
680
+ request.onsuccess = function(event) {
681
+
682
+ var idb = event.target.result;
683
+
684
+ if (!idb.objectStoreNames.contains("<%= Ewigkeks.js_class %>")) {
685
+
686
+ self._ec.idbData = undefined;
687
+ } else {
688
+ var tx = idb.transaction(["<%= Ewigkeks.js_class %>"]);
689
+ var objst = tx.objectStore("<%= Ewigkeks.js_class %>");
690
+ var qr = objst.get(name);
691
+
692
+ qr.onsuccess = function(event) {
693
+ if (qr.result === undefined) {
694
+ self._ec.idbData = undefined
695
+ } else {
696
+ self._ec.idbData = qr.result.value;
697
+ }
698
+ }
699
+ }
700
+ idb.close();
701
+ }
702
+ }
703
+ }
704
+ } catch (e) {}
705
+ };
706
+
707
+ this.<%= Ewigkeks.js_class %>_session_storage = function (name, value) {
708
+ try {
709
+ if (sessionStorage) {
710
+ if (value !== undefined) {
711
+ sessionStorage.setItem(name, value);
712
+ } else {
713
+ return sessionStorage.getItem(name);
714
+ }
715
+ }
716
+ } catch (e) { }
717
+ };
718
+
719
+ this.<%= Ewigkeks.js_class %>_global_storage = function (name, value) {
720
+ if (globalStorage) {
721
+ var host = this.getHost();
722
+ try {
723
+ if (value !== undefined) {
724
+ globalStorage[host][name] = value;
725
+ } else {
726
+ return globalStorage[host][name];
727
+ }
728
+ } catch (e) { }
729
+ }
730
+ };
731
+
732
+ this.<%= Ewigkeks.js_class %>_silverlight = function (name, value) {
733
+ /*
734
+ * Create silverlight embed
735
+ *
736
+ * Ok. so, I tried doing this the proper dom way, but IE chokes on appending anything in object tags (including params), so this
737
+ * is the best method I found. Someone really needs to find a less hack-ish way. I hate the look of this shit.
738
+ */
739
+ var source = _ec_baseurl + _ec_asseturi + "/<%= Ewigkeks.js_class %>.xap",
740
+ minver = "4.0.50401.0",
741
+ initParam = "",
742
+ html;
743
+ if (value !== undefined) {
744
+ initParam = '<param name="initParams" value="' + name + '=' + value + '" />';
745
+ }
746
+
747
+ html =
748
+ '<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">' +
749
+ initParam +
750
+ '<param name="source" value="' + source + '"/>' +
751
+ '<param name="onLoad" value="onSilverlightLoad"/>' +
752
+ '<param name="onError" value="onSilverlightError"/>' +
753
+ '<param name="background" value="Transparent"/>' +
754
+ '<param name="windowless" value="true"/>' +
755
+ '<param name="minRuntimeVersion" value="' + minver + '"/>' +
756
+ '<param name="autoUpgrade" value="false"/>' +
757
+ '<a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=' + minver + '" style="display:none">' +
758
+ 'Get Microsoft Silverlight' +
759
+ '</a>' +
760
+ '</object>';
761
+ try{
762
+ if (typeof jQuery === 'undefined') {
763
+ document.body.appendChild(html);
764
+ } else {
765
+ $('body').append(html);
766
+ }
767
+ }catch(ex){
768
+
769
+ }
770
+ };
771
+
772
+ // public method for encoding
773
+ this.encode = function (input) {
774
+ var output = "",
775
+ chr1, chr2, chr3, enc1, enc2, enc3, enc4,
776
+ i = 0;
777
+
778
+ input = this._utf8_encode(input);
779
+
780
+ while (i < input.length) {
781
+
782
+ chr1 = input.charCodeAt(i++);
783
+ chr2 = input.charCodeAt(i++);
784
+ chr3 = input.charCodeAt(i++);
785
+
786
+ enc1 = chr1 >> 2;
787
+ enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
788
+ enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
789
+ enc4 = chr3 & 63;
790
+
791
+ if (isNaN(chr2)) {
792
+ enc3 = enc4 = 64;
793
+ } else if (isNaN(chr3)) {
794
+ enc4 = 64;
795
+ }
796
+
797
+ output = output +
798
+ _baseKeyStr.charAt(enc1) + _baseKeyStr.charAt(enc2) +
799
+ _baseKeyStr.charAt(enc3) + _baseKeyStr.charAt(enc4);
800
+
801
+ }
802
+
803
+ return output;
804
+ };
805
+
806
+ // public method for decoding
807
+ this.decode = function (input) {
808
+ var output = "",
809
+ chr1, chr2, chr3,
810
+ enc1, enc2, enc3, enc4,
811
+ i = 0;
812
+
813
+ input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
814
+
815
+ while (i < input.length) {
816
+ enc1 = _baseKeyStr.indexOf(input.charAt(i++));
817
+ enc2 = _baseKeyStr.indexOf(input.charAt(i++));
818
+ enc3 = _baseKeyStr.indexOf(input.charAt(i++));
819
+ enc4 = _baseKeyStr.indexOf(input.charAt(i++));
820
+
821
+ chr1 = (enc1 << 2) | (enc2 >> 4);
822
+ chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
823
+ chr3 = ((enc3 & 3) << 6) | enc4;
824
+
825
+ output = output + String.fromCharCode(chr1);
826
+
827
+ if (enc3 !== 64) {
828
+ output = output + String.fromCharCode(chr2);
829
+ }
830
+ if (enc4 !== 64) {
831
+ output = output + String.fromCharCode(chr3);
832
+ }
833
+ }
834
+ output = this._utf8_decode(output);
835
+ return output;
836
+ };
837
+
838
+ // private method for UTF-8 encoding
839
+ this._utf8_encode = function (str) {
840
+ str = str.replace(/\r\n/g, "\n");
841
+ var utftext = "", i = 0, n = str.length, c;
842
+ for (; i < n; i++) {
843
+ c = str.charCodeAt(i);
844
+ if (c < 128) {
845
+ utftext += String.fromCharCode(c);
846
+ } else if ((c > 127) && (c < 2048)) {
847
+ utftext += String.fromCharCode((c >> 6) | 192);
848
+ utftext += String.fromCharCode((c & 63) | 128);
849
+ } else {
850
+ utftext += String.fromCharCode((c >> 12) | 224);
851
+ utftext += String.fromCharCode(((c >> 6) & 63) | 128);
852
+ utftext += String.fromCharCode((c & 63) | 128);
853
+ }
854
+ }
855
+ return utftext;
856
+ };
857
+
858
+ // private method for UTF-8 decoding
859
+ this._utf8_decode = function (utftext) {
860
+ var str = "",
861
+ i = 0, n = utftext.length,
862
+ c = 0, c1 = 0, c2 = 0, c3 = 0;
863
+ while (i < n) {
864
+ c = utftext.charCodeAt(i);
865
+ if (c < 128) {
866
+ str += String.fromCharCode(c);
867
+ i += 1;
868
+ } else if ((c > 191) && (c < 224)) {
869
+ c2 = utftext.charCodeAt(i + 1);
870
+ str += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
871
+ i += 2;
872
+ } else {
873
+ c2 = utftext.charCodeAt(i + 1);
874
+ c3 = utftext.charCodeAt(i + 2);
875
+ str += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
876
+ i += 3;
877
+ }
878
+ }
879
+ return str;
880
+ };
881
+
882
+ // this is crazy but it's 4am in dublin and i thought this would be hilarious
883
+ // blame the guinness
884
+ this.<%= Ewigkeks.js_class %>_history = function (name, value) {
885
+ // - is special
886
+ var baseElems = (_baseKeyStr + "-").split(""),
887
+ // sorry google.
888
+ url = "http://www.google.com/<%= Ewigkeks.js_class %>/cache/" + this.getHost() + "/" + name,
889
+ i, base,
890
+ letter = "",
891
+ val = "",
892
+ found = 1;
893
+
894
+ if (value !== undefined) {
895
+ // don't reset this if we already have it set once
896
+ // too much data and you can't clear previous values
897
+ if (this.hasVisited(url)) {
898
+ return;
899
+ }
900
+
901
+ this.createIframe(url, "if");
902
+ url = url + "/";
903
+
904
+ base = this.encode(value).split("");
905
+ for (i = 0; i < base.length; i++) {
906
+ url = url + base[i];
907
+ this.createIframe(url, "if" + i);
908
+ }
909
+
910
+ // - signifies the end of our data
911
+ url = url + "-";
912
+ this.createIframe(url, "if_");
913
+ } else {
914
+ // omg you got csspwn3d
915
+ if (this.hasVisited(url)) {
916
+ url = url + "/";
917
+
918
+ while (letter !== "-" && found === 1) {
919
+ found = 0;
920
+ for (i = 0; i < baseElems.length; i++) {
921
+ if (this.hasVisited(url + baseElems[i])) {
922
+ letter = baseElems[i];
923
+ if (letter !== "-") {
924
+ val = val + letter;
925
+ }
926
+ url = url + letter;
927
+ found = 1;
928
+ break;
929
+ }
930
+ }
931
+ }
932
+
933
+ // lolz
934
+ return this.decode(val);
935
+ }
936
+ }
937
+ };
938
+
939
+ this.createElem = function (type, name, append) {
940
+ var el;
941
+ if (name !== undefined && document.getElementById(name)) {
942
+ el = document.getElementById(name);
943
+ } else {
944
+ el = document.createElement(type);
945
+ }
946
+ el.style.visibility = "hidden";
947
+ el.style.position = "absolute";
948
+
949
+ if (name) {
950
+ el.setAttribute("id", name);
951
+ }
952
+
953
+ if (append) {
954
+ document.body.appendChild(el);
955
+ }
956
+ return el;
957
+ };
958
+
959
+ this.createIframe = function (url, name) {
960
+ var el = this.createElem("iframe", name, 1);
961
+ el.setAttribute("src", url);
962
+ return el;
963
+ };
964
+
965
+ // wait for our swfobject to appear (swfobject.js to load)
966
+ var waitForSwf = this.waitForSwf = function (i) {
967
+ if (i === undefined) {
968
+ i = 0;
969
+ } else {
970
+ i++;
971
+ }
972
+
973
+ // wait for ~2 seconds for swfobject to appear
974
+ if (i < _ec_tests && typeof swfobject === "undefined") {
975
+ setTimeout(function () {
976
+ waitForSwf(i);
977
+ }, 300);
978
+ }
979
+ };
980
+
981
+ this.<%= Ewigkeks.js_class %>_cookie = function (name, value) {
982
+ if (value !== undefined) {
983
+ // expire the cookie first
984
+ document.cookie = name + "=; expires=Mon, 20 Sep 2010 00:00:00 UTC; path=/; domain=" + _ec_domain;
985
+ document.cookie = name + "=" + value + "; expires=Tue, 31 Dec 2030 00:00:00 UTC; path=/; domain=" + _ec_domain;
986
+ } else {
987
+ return this.getFromStr(name, document.cookie);
988
+ }
989
+ };
990
+
991
+ // get value from param-like string (eg, "x=y&name=VALUE")
992
+ this.getFromStr = function (name, text) {
993
+ if (typeof text !== "string") {
994
+ return;
995
+ }
996
+ var nameEQ = name + "=",
997
+ ca = text.split(/[;&]/),
998
+ i, c;
999
+ for (i = 0; i < ca.length; i++) {
1000
+ c = ca[i];
1001
+ while (c.charAt(0) === " ") {
1002
+ c = c.substring(1, c.length);
1003
+ }
1004
+ if (c.indexOf(nameEQ) === 0) {
1005
+ return c.substring(nameEQ.length, c.length);
1006
+ }
1007
+ }
1008
+ };
1009
+
1010
+ this.getHost = function () {
1011
+ return window.location.host.replace(/:\d+/, '');
1012
+ };
1013
+
1014
+ this.toHex = function (str) {
1015
+ var r = "",
1016
+ e = str.length,
1017
+ c = 0,
1018
+ h;
1019
+ while (c < e) {
1020
+ h = str.charCodeAt(c++).toString(16);
1021
+ while (h.length < 2) {
1022
+ h = "0" + h;
1023
+ }
1024
+ r += h;
1025
+ }
1026
+ return r;
1027
+ };
1028
+
1029
+ this.fromHex = function (str) {
1030
+ var r = "",
1031
+ e = str.length,
1032
+ s;
1033
+ while (e >= 0) {
1034
+ s = e - 2;
1035
+ r = String.fromCharCode("0x" + str.substring(s, e)) + r;
1036
+ e = s;
1037
+ }
1038
+ return r;
1039
+ };
1040
+
1041
+ /**
1042
+ * css history knocker (determine what sites your visitors have been to)
1043
+ *
1044
+ * originally by Jeremiah Grossman
1045
+ * http://jeremiahgrossman.blogspot.com/2006/08/i-know-where-youve-been.html
1046
+ *
1047
+ * ported to additional browsers by Samy Kamkar
1048
+ *
1049
+ * compatible with ie6, ie7, ie8, ff1.5, ff2, ff3, opera, safari, chrome, flock
1050
+ *
1051
+ * - code@samy.pl
1052
+ */
1053
+ this.hasVisited = function (url) {
1054
+ if (this.no_color === -1) {
1055
+ var no_style = this._getRGB("http://samy-was-here-this-should-never-be-visited.com", -1);
1056
+ if (no_style === -1) {
1057
+ this.no_color = this._getRGB("http://samy-was-here-" + Math.floor(Math.random() * 9999999) + "rand.com");
1058
+ }
1059
+ }
1060
+
1061
+ // did we give full url?
1062
+ if (url.indexOf("https:") === 0 || url.indexOf("http:") === 0) {
1063
+ return this._testURL(url, this.no_color);
1064
+ }
1065
+
1066
+ // if not, just test a few diff types if (exact)
1067
+ return this._testURL("http://" + url, this.no_color) ||
1068
+ this._testURL("https://" + url, this.no_color) ||
1069
+ this._testURL("http://www." + url, this.no_color) ||
1070
+ this._testURL("https://www." + url, this.no_color);
1071
+ };
1072
+
1073
+ /* create our anchor tag */
1074
+ var _link = this.createElem("a", "_ec_rgb_link"),
1075
+ /* for monitoring */
1076
+ created_style,
1077
+ /* create a custom style tag for the specific link. Set the CSS visited selector to a known value */
1078
+ _cssText = "#_ec_rgb_link:visited{display:none;color:#FF0000}",
1079
+ style;
1080
+
1081
+ /* Methods for IE6, IE7, FF, Opera, and Safari */
1082
+ try {
1083
+ created_style = 1;
1084
+ style = document.createElement("style");
1085
+ if (style.styleSheet) {
1086
+ style.styleSheet.innerHTML = _cssText;
1087
+ } else if (style.innerHTML) {
1088
+ style.innerHTML = _cssText;
1089
+ } else {
1090
+ style.appendChild(document.createTextNode(_cssText));
1091
+ }
1092
+ } catch (e) {
1093
+ created_style = 0;
1094
+ }
1095
+
1096
+ /* if test_color, return -1 if we can't set a style */
1097
+ this._getRGB = function (u, test_color) {
1098
+ if (test_color && created_style === 0) {
1099
+ return -1;
1100
+ }
1101
+
1102
+ /* create the new anchor tag with the appropriate URL information */
1103
+ _link.href = u;
1104
+ _link.innerHTML = u;
1105
+ // not sure why, but the next two appendChilds always have to happen vs just once
1106
+ document.body.appendChild(style);
1107
+ document.body.appendChild(_link);
1108
+
1109
+ /* add the link to the DOM and save the visible computed color */
1110
+ var color;
1111
+ if (document.defaultView) {
1112
+ if (document.defaultView.getComputedStyle(_link, null) == null) {
1113
+ return -1; // getComputedStyle is unavailable in FF when running in IFRAME
1114
+ }
1115
+ color = document.defaultView.getComputedStyle(_link, null).getPropertyValue("color");
1116
+ } else {
1117
+ color = _link.currentStyle.color;
1118
+ }
1119
+ return color;
1120
+ };
1121
+
1122
+ this._testURL = function (url, no_color) {
1123
+ var color = this._getRGB(url);
1124
+
1125
+ /* check to see if the link has been visited if the computed color is red */
1126
+ if (color === "rgb(255, 0, 0)" || color === "#ff0000") {
1127
+ return 1;
1128
+ } else if (no_color && color !== no_color) {
1129
+ /* if our style trick didn't work, just compare default style colors */
1130
+ return 1;
1131
+ }
1132
+ /* not found */
1133
+ return 0;
1134
+ };
1135
+
1136
+ };
1137
+
1138
+ window._<%= Ewigkeks.js_class %>_flash_var = _<%= Ewigkeks.js_class %>_flash_var;
1139
+ /**
1140
+ * Because Evercookie is a class, it should has first letter in capital
1141
+ * Keep first letter in small for legacy purpose
1142
+ * @expose Evercookie
1143
+ */
1144
+ window.<%= Ewigkeks.js_class %> = <%= Ewigkeks.js_class %>;
1145
+ }(window));
1146
+ }catch(ex){}