ewigkeks 1.0.0

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