evercookie 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README.rdoc +127 -0
- data/Rakefile +38 -0
- data/app/assets/images/ec.swf +0 -0
- data/app/assets/javascripts/ec.js +2 -0
- data/app/assets/javascripts/evercookie/evercookie.js.erb +704 -0
- data/app/assets/javascripts/evercookie/swfobject-2.2.min.js +4 -0
- data/app/views/evercookie/evercookie/get.js.erb +2 -0
- data/app/views/evercookie/evercookie/set.js.erb +2 -0
- data/config/routes.rb +20 -0
- data/lib/evercookie.rb +85 -0
- data/lib/evercookie/controller.rb +122 -0
- data/lib/evercookie/engine.rb +17 -0
- data/lib/evercookie/version.rb +4 -0
- data/lib/evercookie/view.rb +25 -0
- data/lib/tasks/evercookie_tasks.rake +4 -0
- data/test/dummy/README.rdoc +261 -0
- data/test/dummy/Rakefile +7 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/javascripts/index.js +2 -0
- data/test/dummy/app/assets/stylesheets/application.css +13 -0
- data/test/dummy/app/assets/stylesheets/index.css +4 -0
- data/test/dummy/app/controllers/application_controller.rb +3 -0
- data/test/dummy/app/controllers/index_controller.rb +24 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/helpers/index_helper.rb +2 -0
- data/test/dummy/app/views/index/get.html.erb +5 -0
- data/test/dummy/app/views/index/get_detailed.html.erb +26 -0
- data/test/dummy/app/views/index/index.html.erb +36 -0
- data/test/dummy/app/views/index/set.html.erb +3 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +59 -0
- data/test/dummy/config/boot.rb +10 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +37 -0
- data/test/dummy/config/environments/production.rb +67 -0
- data/test/dummy/config/environments/test.rb +37 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/evercookie.rb +8 -0
- data/test/dummy/config/initializers/inflections.rb +15 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/secret_token.rb +7 -0
- data/test/dummy/config/initializers/session_store.rb +8 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +5 -0
- data/test/dummy/config/routes.rb +10 -0
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/log/development.log +30554 -0
- data/test/dummy/log/test.log +1516 -0
- data/test/dummy/public/404.html +26 -0
- data/test/dummy/public/422.html +26 -0
- data/test/dummy/public/500.html +25 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/script/rails +6 -0
- data/test/dummy/test/functional/index_controller_test.rb +7 -0
- data/test/dummy/test/unit/helpers/index_helper_test.rb +4 -0
- data/test/dummy/tmp/cache/assets/CD8/370/sprockets%2F357970feca3ac29060c1e3861e2c0953 +0 -0
- data/test/dummy/tmp/cache/assets/CEC/FA0/sprockets%2Fcee8c6b09c33d2b276753e959712724e +0 -0
- data/test/dummy/tmp/cache/assets/D2F/760/sprockets%2F3b464ead21d28d0a1298357a3a7cbc18 +0 -0
- data/test/dummy/tmp/cache/assets/D32/A10/sprockets%2F13fe41fee1fe35b49d145bcc06610705 +0 -0
- data/test/dummy/tmp/cache/assets/D45/3C0/sprockets%2Fd45fb0f5f994f0c125db5e026ee65258 +0 -0
- data/test/dummy/tmp/cache/assets/D45/C10/sprockets%2Fac34f7046872aba24b7375de608d8fe6 +0 -0
- data/test/dummy/tmp/cache/assets/D4E/1B0/sprockets%2Ff7cbd26ba1d28d48de824f0e94586655 +0 -0
- data/test/dummy/tmp/cache/assets/D5A/EA0/sprockets%2Fd771ace226fc8215a3572e0aa35bb0d6 +0 -0
- data/test/dummy/tmp/cache/assets/D70/2D0/sprockets%2F2c853768baf811357d81d41bdfd05dcf +0 -0
- data/test/dummy/tmp/cache/assets/D70/D10/sprockets%2Fa0d37ff489ed0857f72233f5cb0b9c0b +0 -0
- data/test/dummy/tmp/cache/assets/D8C/A10/sprockets%2Ffc7201c6cbef32453aa4175c520c8eae +0 -0
- data/test/dummy/tmp/cache/assets/D93/360/sprockets%2Fdf600f50f002512c95d93bcfbab891ed +0 -0
- data/test/dummy/tmp/cache/assets/D99/2F0/sprockets%2Fa2cf2651c63ecb32c21ea94fa84cd498 +0 -0
- data/test/dummy/tmp/cache/assets/DAA/C00/sprockets%2F9bddc9410e086be5f5efa982c5247c7b +0 -0
- data/test/dummy/tmp/cache/assets/DCF/EC0/sprockets%2Fe1f34cd8fd7ca6a9a01d26e47c923f1f +0 -0
- data/test/dummy/tmp/cache/assets/DDC/400/sprockets%2Fcffd775d018f68ce5dba1ee0d951a994 +0 -0
- data/test/dummy/tmp/cache/assets/DEE/200/sprockets%2F2a3f3abddecb0467eb2d7d5cf5f52302 +0 -0
- data/test/dummy/tmp/cache/assets/DFF/960/sprockets%2Fe73aa53de71d957ef04bdfd2fba2e915 +0 -0
- data/test/dummy/tmp/cache/assets/E04/890/sprockets%2F2f5173deea6c795b8fdde723bb4b63af +0 -0
- data/test/dummy/tmp/cache/assets/E83/750/sprockets%2Fe0a4c2b9c4acf9bcfedbb42a8bd45e80 +0 -0
- data/test/evercookie_test.rb +7 -0
- data/test/test_helper.rb +15 -0
- data/test/unit/controllers/evercookie_controller_test.rb +86 -0
- data/test/unit/helpers/evercookie_controller_helper_test.rb +11 -0
- data/test/unit/helpers/evercookie_view_helper_test.rb +28 -0
- metadata +236 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2012 YOURNAME
|
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.rdoc
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
## Evercookie
|
2
|
+
|
3
|
+
Evercookie is a gem allowing you to use very persistent cookies on your rails project to track existing users on your system.
|
4
|
+
It's javascript is based on https://github.com/samyk/evercookie javascript.
|
5
|
+
Please note, that evercookie can't be fully reliable for detecting previous visiting of your site/application. For people who know the job it's simple enough to override it.
|
6
|
+
|
7
|
+
As written on original javascript site (http://samy.pl/evercookie/), when creating a new cookie, it uses the following storage mechanisms when available:
|
8
|
+
* Standard [HTTP Cookies](http://en.wikipedia.org/wiki/HTTP_cookie)
|
9
|
+
* [Local Shared Objects](http://en.wikipedia.org/wiki/Local_Shared_Object) (Flash Cookies)
|
10
|
+
* [Isolated Storage](http://www.silverlight.net/learn/quickstarts/isolatedstorage/) Silverlight (removed in gem)
|
11
|
+
* Storing cookies in RGB values of auto-generated, force-cached PNGs using HTML5 Canvas tag to read pixels (cookies) back out
|
12
|
+
* Storing cookies in and reading out [Web History](http://samy.pl/csshack/) (removed in gem)
|
13
|
+
* Storing cookies in HTTP [ETags](http://en.wikipedia.org/wiki/HTTP_ETag)
|
14
|
+
* Storing cookies in [Web cache](http://en.wikipedia.org/wiki/Web_cache)
|
15
|
+
* [window.name](http://en.wikipedia.org/wiki/HTTP_cookie#window.name) caching
|
16
|
+
* Internet Explorer [userData](http://msdn.microsoft.com/en-us/library/ms531424(VS.85).aspx) storage
|
17
|
+
* HTML5 [Session Storage](http://dev.w3.org/html5/webstorage/#the-sessionstorage-attribute)
|
18
|
+
* HTML5 [Local Storage](http://dev.w3.org/html5/webstorage/#dom-localstorage)
|
19
|
+
* HTML5 [Global Storage](https://developer.mozilla.org/en/dom/storage#globalStorage)
|
20
|
+
* HTML5 [Database Storage](http://dev.w3.org/html5/webdatabase) via SQLite
|
21
|
+
|
22
|
+
## Information
|
23
|
+
|
24
|
+
### RDoc
|
25
|
+
|
26
|
+
RDoc documentation can be found here
|
27
|
+
http://rubydoc.info/github/daddyz/evercookie/master/frames
|
28
|
+
|
29
|
+
### Bug reports
|
30
|
+
|
31
|
+
If you discover a problem with Evercookie gem, let us know about it.
|
32
|
+
https://github.com/daddyz/evercookie/issues
|
33
|
+
|
34
|
+
### Example application
|
35
|
+
|
36
|
+
You can see an example of evercookie working in test/dummy application of this gem
|
37
|
+
|
38
|
+
## Getting started
|
39
|
+
|
40
|
+
Evercookie works was written and tested on Rails 3.2. You can add in to your Gemfile with:
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
gem 'evercookie'
|
44
|
+
```
|
45
|
+
|
46
|
+
Run the bundle command to install it.
|
47
|
+
|
48
|
+
### View helpers
|
49
|
+
|
50
|
+
View helper that adds javascript for setting the evercookie for client:
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
set_evercookie(:key, :value)
|
54
|
+
```
|
55
|
+
|
56
|
+
View helper that checks whether the cookie was set on client side and resets if some of cookies were deleted:
|
57
|
+
|
58
|
+
```ruby
|
59
|
+
check_evercookie(:key)
|
60
|
+
```
|
61
|
+
|
62
|
+
### Controller helpers
|
63
|
+
|
64
|
+
Controller helper that gets the value of evercookie by key:
|
65
|
+
|
66
|
+
```ruby
|
67
|
+
evercookie_get_value(:key)
|
68
|
+
```
|
69
|
+
|
70
|
+
Controller helper that checks if specific evercookie was set:
|
71
|
+
|
72
|
+
```ruby
|
73
|
+
evercookie_is_set?(:key)
|
74
|
+
evercookie_is_set?(:key, :value)
|
75
|
+
```
|
76
|
+
|
77
|
+
### How it works
|
78
|
+
|
79
|
+
When you are calling:
|
80
|
+
* `set_evercookie` helper it adds javascript to set evercookie values in all available storage mechanisms.
|
81
|
+
* `check_evercookie` helper it adds javascript to get evercookie values from all storage mechanisms where it possible and resets their values where it was removed (like if user removed individual cookies it sets them back) and after that it calls it's controller action to save evercookie value in rails session
|
82
|
+
* `evercookie_get_value` helper in controller it checks evercookie's session for provided 'key' value and returns it if exists
|
83
|
+
* `evercookie_is_set?` helper in controller it checks if there is a provided 'key' in evercookie's session
|
84
|
+
|
85
|
+
### How this gem should be used
|
86
|
+
|
87
|
+
The main idea of this gem is to set somewhere in application an evercookie to track that this client already visited your application.
|
88
|
+
I used it to track multiple registrations in such scenario:
|
89
|
+
* After user was registered he was passed to specific view where I called set_evercookie helper:
|
90
|
+
```ruby
|
91
|
+
set_evercookie(:uid, user_unique_id)
|
92
|
+
```
|
93
|
+
* In user sign up page view I called check_evercookie helper:
|
94
|
+
```ruby
|
95
|
+
check_evercookie(:uid)
|
96
|
+
```
|
97
|
+
* In controller that was handling new user creation process I was running evercookie_get_value helper to check if previously I got evercookie value from user, and if I got it I was showing an error:
|
98
|
+
```ruby
|
99
|
+
evercookie_get_value(:uid)
|
100
|
+
```
|
101
|
+
|
102
|
+
### Configuring the gem
|
103
|
+
|
104
|
+
You can create the initializer for evercookie gem in your Rails application initializers folder:
|
105
|
+
|
106
|
+
```ruby
|
107
|
+
Evercookie.setup do |config|
|
108
|
+
# path for evercookie controller
|
109
|
+
config.namespace = :evercookie
|
110
|
+
|
111
|
+
# name of javascript class to be used for evercookie
|
112
|
+
config.js_class = :evercookie
|
113
|
+
|
114
|
+
# hash name base for session storage variables
|
115
|
+
config.hash_name = :evercookie
|
116
|
+
|
117
|
+
# cookie name for cache storage
|
118
|
+
config.cookie_cache = :evercookie_cache
|
119
|
+
|
120
|
+
# cookie name for png storage
|
121
|
+
config.cookie_png = :evercookie_png
|
122
|
+
|
123
|
+
# cookie name for etag storage
|
124
|
+
config.cookie_etag = :evercookie_etag
|
125
|
+
end
|
126
|
+
```
|
127
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
begin
|
3
|
+
require 'bundler/setup'
|
4
|
+
rescue LoadError
|
5
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
6
|
+
end
|
7
|
+
begin
|
8
|
+
require 'rdoc/task'
|
9
|
+
rescue LoadError
|
10
|
+
require 'rdoc/rdoc'
|
11
|
+
require 'rake/rdoctask'
|
12
|
+
RDoc::Task = Rake::RDocTask
|
13
|
+
end
|
14
|
+
|
15
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
16
|
+
rdoc.rdoc_dir = 'rdoc'
|
17
|
+
rdoc.title = 'Evercookie'
|
18
|
+
rdoc.options << '--line-numbers'
|
19
|
+
rdoc.rdoc_files.include('README.rdoc')
|
20
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
|
26
|
+
Bundler::GemHelper.install_tasks
|
27
|
+
|
28
|
+
require 'rake/testtask'
|
29
|
+
|
30
|
+
Rake::TestTask.new(:test) do |t|
|
31
|
+
t.libs << 'lib'
|
32
|
+
t.libs << 'test'
|
33
|
+
t.pattern = 'test/**/*_test.rb'
|
34
|
+
t.verbose = false
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
task :default => :test
|
Binary file
|
@@ -0,0 +1,704 @@
|
|
1
|
+
/*
|
2
|
+
* USAGE:
|
3
|
+
|
4
|
+
var ec = new <%= Evercookie.js_class %>();
|
5
|
+
ec.set("id", "12345");
|
6
|
+
ec.get("id", function(value) { alert("value is " + value) });
|
7
|
+
*/
|
8
|
+
var _ec_tests = 10; //1000
|
9
|
+
function _ec_replace(str, key, value) {
|
10
|
+
if (str.indexOf("&" + key + "=") > -1 || str.indexOf(key + "=") === 0) {
|
11
|
+
// find start
|
12
|
+
var idx = str.indexOf("&" + key + "="),
|
13
|
+
end, newstr;
|
14
|
+
if (idx === -1) {
|
15
|
+
idx = str.indexOf(key + "=");
|
16
|
+
}
|
17
|
+
// find end
|
18
|
+
end = str.indexOf("&", idx + 1);
|
19
|
+
if (end !== -1) {
|
20
|
+
newstr = str.substr(0, idx) + str.substr(end + (idx ? 0 : 1)) + "&" + key + "=" + value;
|
21
|
+
} else {
|
22
|
+
newstr = str.substr(0, idx) + "&" + key + "=" + value;
|
23
|
+
}
|
24
|
+
return newstr;
|
25
|
+
} else {
|
26
|
+
return str + "&" + key + "=" + value;
|
27
|
+
}
|
28
|
+
}
|
29
|
+
|
30
|
+
|
31
|
+
// necessary for flash to communicate with js...
|
32
|
+
// please implement a better way
|
33
|
+
var _global_lso;
|
34
|
+
function _evercookie_flash_var(cookie) {
|
35
|
+
_global_lso = cookie;
|
36
|
+
|
37
|
+
// remove the flash object now
|
38
|
+
var swf = document.getElementById("myswf");
|
39
|
+
if (swf && swf.parentNode) {
|
40
|
+
swf.parentNode.removeChild(swf);
|
41
|
+
}
|
42
|
+
}
|
43
|
+
|
44
|
+
var <%= Evercookie.js_class %> = (function (window) {
|
45
|
+
var document = window.document,
|
46
|
+
Image = window.Image,
|
47
|
+
localStorage = window.localStorage,
|
48
|
+
globalStorage = window.globalStorage,
|
49
|
+
swfobject = window.swfobject;
|
50
|
+
try {
|
51
|
+
var sessionStorage = window.sessionStorage;
|
52
|
+
} catch (e) { }
|
53
|
+
|
54
|
+
this._class = function () {
|
55
|
+
// private property
|
56
|
+
var self = this,
|
57
|
+
_baseKeyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
|
58
|
+
no_color = -1;
|
59
|
+
this._ec = {};
|
60
|
+
|
61
|
+
this.get = function (name, cb, dont_reset) {
|
62
|
+
self._<%= Evercookie.js_class %>(name, cb, undefined, undefined, dont_reset);
|
63
|
+
};
|
64
|
+
|
65
|
+
this.set = function (name, value) {
|
66
|
+
self._<%= Evercookie.js_class %>(name, function () {}, value);
|
67
|
+
};
|
68
|
+
|
69
|
+
this._<%= Evercookie.js_class %> = function (name, cb, value, i, dont_reset) {
|
70
|
+
if (self._<%= Evercookie.js_class %> === undefined) {
|
71
|
+
self = this;
|
72
|
+
}
|
73
|
+
if (i === undefined) {
|
74
|
+
i = 0;
|
75
|
+
}
|
76
|
+
// first run
|
77
|
+
if (i === 0) {
|
78
|
+
self.<%= Evercookie.js_class %>_database_storage(name, value);
|
79
|
+
self.<%= Evercookie.js_class %>_png(name, value);
|
80
|
+
self.<%= Evercookie.js_class %>_etag(name, value);
|
81
|
+
self.<%= Evercookie.js_class %>_cache(name, value);
|
82
|
+
self.<%= Evercookie.js_class %>_lso(name, value);
|
83
|
+
|
84
|
+
self._ec.userData = self.<%= Evercookie.js_class %>_userdata(name, value);
|
85
|
+
self._ec.cookieData = self.<%= Evercookie.js_class %>_cookie(name, value);
|
86
|
+
self._ec.localData = self.<%= Evercookie.js_class %>_local_storage(name, value);
|
87
|
+
self._ec.globalData = self.<%= Evercookie.js_class %>_global_storage(name, value);
|
88
|
+
self._ec.sessionData = self.<%= Evercookie.js_class %>_session_storage(name, value);
|
89
|
+
self._ec.windowData = self.<%= Evercookie.js_class %>_window(name, value);
|
90
|
+
}
|
91
|
+
|
92
|
+
// when writing data, we need to make sure lso object is there
|
93
|
+
if (value !== undefined) {
|
94
|
+
if ((typeof _global_lso === "undefined") && i++ < _ec_tests) {
|
95
|
+
setTimeout(function () {
|
96
|
+
self._<%= Evercookie.js_class %>(name, cb, value, i, dont_reset);
|
97
|
+
}, 100);
|
98
|
+
}
|
99
|
+
}
|
100
|
+
|
101
|
+
// when reading data, we need to wait for swf, db and png
|
102
|
+
else
|
103
|
+
{
|
104
|
+
if (
|
105
|
+
(
|
106
|
+
// we support local db and haven't read data in yet
|
107
|
+
(window.openDatabase && typeof self._ec.dbData === "undefined") ||
|
108
|
+
(typeof _global_lso === "undefined") ||
|
109
|
+
(typeof self._ec.etagData === "undefined") ||
|
110
|
+
(typeof self._ec.cacheData === "undefined") ||
|
111
|
+
(document.createElement("canvas").getContext && (typeof self._ec.pngData === "undefined" || self._ec.pngData === ""))
|
112
|
+
) &&
|
113
|
+
i++ < _ec_tests
|
114
|
+
)
|
115
|
+
{
|
116
|
+
setTimeout(function () {
|
117
|
+
self._<%= Evercookie.js_class %>(name, cb, value, i, dont_reset);
|
118
|
+
}, 300);
|
119
|
+
}
|
120
|
+
|
121
|
+
// we hit our max wait time or got all our data
|
122
|
+
else
|
123
|
+
{
|
124
|
+
// get just the piece of data we need from swf
|
125
|
+
self._ec.lsoData = self.getFromStr(name, _global_lso);
|
126
|
+
_global_lso = undefined;
|
127
|
+
|
128
|
+
var tmpec = self._ec,
|
129
|
+
candidates = [],
|
130
|
+
bestnum = 0,
|
131
|
+
candidate,
|
132
|
+
item;
|
133
|
+
self._ec = {};
|
134
|
+
|
135
|
+
// figure out which is the best candidate
|
136
|
+
for (item in tmpec) {
|
137
|
+
if (tmpec[item] && tmpec[item] !== "null" && tmpec[item] !== "undefined") {
|
138
|
+
candidates[tmpec[item]] = candidates[tmpec[item]] === undefined ? 1 : candidates[tmpec[item]] + 1;
|
139
|
+
}
|
140
|
+
}
|
141
|
+
|
142
|
+
for (item in candidates) {
|
143
|
+
if (candidates[item] > bestnum) {
|
144
|
+
bestnum = candidates[item];
|
145
|
+
candidate = item;
|
146
|
+
}
|
147
|
+
}
|
148
|
+
|
149
|
+
// reset cookie everywhere
|
150
|
+
if (dont_reset === undefined || dont_reset !== 1) {
|
151
|
+
self.set(name, candidate);
|
152
|
+
}
|
153
|
+
if (typeof cb === "function") {
|
154
|
+
cb(candidate, tmpec);
|
155
|
+
}
|
156
|
+
|
157
|
+
self.ajax({
|
158
|
+
url: "<%= Evercookie.get_save_path %>?name=" + name,
|
159
|
+
success: function (data) { }
|
160
|
+
});
|
161
|
+
}
|
162
|
+
}
|
163
|
+
};
|
164
|
+
|
165
|
+
this.<%= Evercookie.js_class %>_window = function (name, value) {
|
166
|
+
try {
|
167
|
+
if (value !== undefined) {
|
168
|
+
window.name = _ec_replace(window.name, name, value);
|
169
|
+
} else {
|
170
|
+
return this.getFromStr(name, window.name);
|
171
|
+
}
|
172
|
+
} catch (e) { }
|
173
|
+
};
|
174
|
+
|
175
|
+
this.<%= Evercookie.js_class %>_userdata = function (name, value) {
|
176
|
+
try {
|
177
|
+
var elm = this.createElem("div", "userdata_el", 1);
|
178
|
+
elm.style.behavior = "url(#default#userData)";
|
179
|
+
|
180
|
+
if (value !== undefined) {
|
181
|
+
elm.setAttribute(name, value);
|
182
|
+
elm.save(name);
|
183
|
+
} else {
|
184
|
+
elm.load(name);
|
185
|
+
return elm.getAttribute(name);
|
186
|
+
}
|
187
|
+
} catch (e) {}
|
188
|
+
};
|
189
|
+
|
190
|
+
function newImage(src) {
|
191
|
+
var img = new Image();
|
192
|
+
img.style.visibility = "hidden";
|
193
|
+
img.style.position = "absolute";
|
194
|
+
img.src = src;
|
195
|
+
}
|
196
|
+
|
197
|
+
this.ajax = function (settings) {
|
198
|
+
var headers, name, transports, transport, i, length;
|
199
|
+
|
200
|
+
headers = {
|
201
|
+
'X-Requested-With': 'XMLHttpRequest',
|
202
|
+
'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
|
203
|
+
};
|
204
|
+
|
205
|
+
transports = [
|
206
|
+
function () { return new XMLHttpRequest(); },
|
207
|
+
function () { return new ActiveXObject('Msxml2.XMLHTTP'); },
|
208
|
+
function () { return new ActiveXObject('Microsoft.XMLHTTP'); }
|
209
|
+
];
|
210
|
+
|
211
|
+
for (i = 0, length = transports.length; i < length; i++) {
|
212
|
+
transport = transports[i];
|
213
|
+
try {
|
214
|
+
transport = transport();
|
215
|
+
break;
|
216
|
+
} catch (e) {
|
217
|
+
}
|
218
|
+
}
|
219
|
+
|
220
|
+
transport.onreadystatechange = function () {
|
221
|
+
if (transport.readyState !== 4) {
|
222
|
+
return;
|
223
|
+
}
|
224
|
+
settings.success(transport.responseText);
|
225
|
+
};
|
226
|
+
transport.open('get', settings.url, true);
|
227
|
+
for (name in headers) {
|
228
|
+
transport.setRequestHeader(name, headers[name]);
|
229
|
+
}
|
230
|
+
transport.send();
|
231
|
+
};
|
232
|
+
|
233
|
+
this.<%= Evercookie.js_class %>_cache = function (name, value) {
|
234
|
+
if (value !== undefined) {
|
235
|
+
// make sure we have <%= Evercookie.js_class %> session defined first
|
236
|
+
document.cookie = "<%= Evercookie.cookie_cache %>=" + value + "; path=<%= Evercookie.get_cookie_path %>";
|
237
|
+
// <%= Evercookie.get_cache_path %> handles caching
|
238
|
+
newImage("<%= Evercookie.get_cache_path %>?name=" + name);
|
239
|
+
} else {
|
240
|
+
// interestingly enough, we want to erase our evercookie
|
241
|
+
// http cookie so will force a cached response
|
242
|
+
var origvalue = this.getFromStr("<%= Evercookie.cookie_cache %>", document.cookie);
|
243
|
+
self._ec.cacheData = undefined;
|
244
|
+
document.cookie = "<%= Evercookie.cookie_cache %>=; expires=Mon, 20 Sep 2010 00:00:00 UTC; path=<%= Evercookie.get_cookie_path %>";
|
245
|
+
|
246
|
+
self.ajax({
|
247
|
+
url: "<%= Evercookie.get_cache_path %>?name=" + name,
|
248
|
+
success: function (data) {
|
249
|
+
// put our cookie back
|
250
|
+
document.cookie = "<%= Evercookie.cookie_cache %>=" + origvalue + "; expires=Tue, 31 Dec 2030 00:00:00 UTC; path=<%= Evercookie.get_cookie_path %>";
|
251
|
+
|
252
|
+
self._ec.cacheData = data;
|
253
|
+
}
|
254
|
+
});
|
255
|
+
}
|
256
|
+
};
|
257
|
+
|
258
|
+
this.<%= Evercookie.js_class %>_etag = function (name, value) {
|
259
|
+
if (value !== undefined) {
|
260
|
+
// make sure we have <%= Evercookie.js_class %> session defined first
|
261
|
+
document.cookie = "<%= Evercookie.cookie_etag %>=" + value + "; path=<%= Evercookie.get_cookie_path %>";
|
262
|
+
// <%= Evercookie.get_etag_path %> handles etagging
|
263
|
+
newImage("<%= Evercookie.get_etag_path %>?name=" + name);
|
264
|
+
} else {
|
265
|
+
// interestingly enough, we want to erase our <%= Evercookie.js_class %>
|
266
|
+
// http cookie so will force a cached response
|
267
|
+
var origvalue = this.getFromStr("<%= Evercookie.cookie_etag %>", document.cookie);
|
268
|
+
self._ec.etagData = undefined;
|
269
|
+
document.cookie = "<%= Evercookie.cookie_etag %>=; expires=Mon, 20 Sep 2010 00:00:00 UTC; path=<%= Evercookie.get_cookie_path %>";
|
270
|
+
|
271
|
+
self.ajax({
|
272
|
+
url: "<%= Evercookie.get_etag_path %>?name=" + name,
|
273
|
+
success: function (data) {
|
274
|
+
// put our cookie back
|
275
|
+
document.cookie = "<%= Evercookie.cookie_etag %>=" + origvalue + "; expires=Tue, 31 Dec 2030 00:00:00 UTC; path=<%= Evercookie.get_cookie_path %>";
|
276
|
+
|
277
|
+
self._ec.etagData = data;
|
278
|
+
}
|
279
|
+
});
|
280
|
+
}
|
281
|
+
};
|
282
|
+
|
283
|
+
this.<%= Evercookie.js_class %>_lso = function (name, value) {
|
284
|
+
var div = document.getElementById("swfcontainer"),
|
285
|
+
flashvars = {},
|
286
|
+
params = {},
|
287
|
+
attributes = {};
|
288
|
+
if (div===null || div === undefined || !div.length) {
|
289
|
+
div = document.createElement("div");
|
290
|
+
div.setAttribute("id", "swfcontainer");
|
291
|
+
document.body.appendChild(div);
|
292
|
+
}
|
293
|
+
|
294
|
+
if (value !== undefined) {
|
295
|
+
flashvars.everdata = name + "=" + value;
|
296
|
+
}
|
297
|
+
params.swliveconnect = "true";
|
298
|
+
attributes.id = "myswf";
|
299
|
+
attributes.name = "myswf";
|
300
|
+
swfobject.embedSWF("<%= asset_path('ec.swf') %>", "swfcontainer", "1", "1", "9.0.0", false, flashvars, params, attributes);
|
301
|
+
};
|
302
|
+
|
303
|
+
this.<%= Evercookie.js_class %>_png = function (name, value) {
|
304
|
+
var canvas = document.createElement("canvas"),
|
305
|
+
img, ctx, origvalue;
|
306
|
+
canvas.style.visibility = "hidden";
|
307
|
+
canvas.style.position = "absolute";
|
308
|
+
canvas.width = 200;
|
309
|
+
canvas.height = 1;
|
310
|
+
if (canvas && canvas.getContext) {
|
311
|
+
// <%= Evercookie.get_png_path %> handles the hard part of generating the image
|
312
|
+
// based off of the http cookie and returning it cached
|
313
|
+
img = new Image();
|
314
|
+
img.style.visibility = "hidden";
|
315
|
+
img.style.position = "absolute";
|
316
|
+
if (value !== undefined) {
|
317
|
+
// make sure we have <%= Evercookie.js_class %> session defined first
|
318
|
+
document.cookie = "<%= Evercookie.cookie_png %>=" + value + "; path=<%= Evercookie.get_cookie_path %>";
|
319
|
+
} else {
|
320
|
+
self._ec.pngData = undefined;
|
321
|
+
ctx = canvas.getContext("2d");
|
322
|
+
|
323
|
+
// interestingly enough, we want to erase our <%= Evercookie.js_class %>
|
324
|
+
// http cookie so will force a cached response
|
325
|
+
origvalue = this.getFromStr("<%= Evercookie.cookie_png %>", document.cookie);
|
326
|
+
document.cookie = "<%= Evercookie.cookie_png %>=; expires=Mon, 20 Sep 2010 00:00:00 UTC; path=<%= Evercookie.get_cookie_path %>";
|
327
|
+
|
328
|
+
img.onload = function () {
|
329
|
+
// put our cookie back
|
330
|
+
document.cookie = "<%= Evercookie.cookie_png %>=" + origvalue + "; expires=Tue, 31 Dec 2030 00:00:00 UTC; path=<%= Evercookie.get_cookie_path %>";
|
331
|
+
|
332
|
+
self._ec.pngData = "";
|
333
|
+
ctx.drawImage(img, 0, 0);
|
334
|
+
|
335
|
+
// get CanvasPixelArray from given coordinates and dimensions
|
336
|
+
var imgd = ctx.getImageData(0, 0, 200, 1),
|
337
|
+
pix = imgd.data, i, n;
|
338
|
+
|
339
|
+
// loop over each pixel to get the "RGB" values (ignore alpha)
|
340
|
+
for (i = 0, n = pix.length; i < n; i += 4) {
|
341
|
+
if (pix[i] === 0) {
|
342
|
+
break;
|
343
|
+
}
|
344
|
+
self._ec.pngData += String.fromCharCode(pix[i]);
|
345
|
+
if (pix[i + 1] === 0) {
|
346
|
+
break;
|
347
|
+
}
|
348
|
+
self._ec.pngData += String.fromCharCode(pix[i + 1]);
|
349
|
+
if (pix[i + 2] === 0) {
|
350
|
+
break;
|
351
|
+
}
|
352
|
+
self._ec.pngData += String.fromCharCode(pix[i + 2]);
|
353
|
+
}
|
354
|
+
};
|
355
|
+
}
|
356
|
+
img.src = "<%= Evercookie.get_png_path %>?name=" + name;
|
357
|
+
}
|
358
|
+
};
|
359
|
+
|
360
|
+
this.<%= Evercookie.js_class %>_local_storage = function (name, value) {
|
361
|
+
try {
|
362
|
+
if (localStorage) {
|
363
|
+
if (value !== undefined) {
|
364
|
+
localStorage.setItem(name, value);
|
365
|
+
} else {
|
366
|
+
return localStorage.getItem(name);
|
367
|
+
}
|
368
|
+
}
|
369
|
+
} catch (e) { }
|
370
|
+
};
|
371
|
+
|
372
|
+
this.<%= Evercookie.js_class %>_database_storage = function (name, value) {
|
373
|
+
try {
|
374
|
+
if (window.openDatabase) {
|
375
|
+
var database = window.openDatabase("sqlite_<%= Evercookie.js_class %>", "", "<%= Evercookie.js_class %>", 1024 * 1024);
|
376
|
+
|
377
|
+
if (value !== undefined) {
|
378
|
+
database.transaction(function (tx) {
|
379
|
+
tx.executeSql("CREATE TABLE IF NOT EXISTS cache(" +
|
380
|
+
"id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, " +
|
381
|
+
"name TEXT NOT NULL, " +
|
382
|
+
"value TEXT NOT NULL, " +
|
383
|
+
"UNIQUE (name)" +
|
384
|
+
")", [], function (tx, rs) {}, function (tx, err) {});
|
385
|
+
tx.executeSql("INSERT OR REPLACE INTO cache(name, value) " +
|
386
|
+
"VALUES(?, ?)",
|
387
|
+
[name, value], function (tx, rs) {}, function (tx, err) {});
|
388
|
+
});
|
389
|
+
} else {
|
390
|
+
database.transaction(function (tx) {
|
391
|
+
tx.executeSql("SELECT value FROM cache WHERE name=?", [name],
|
392
|
+
function (tx, result1) {
|
393
|
+
if (result1.rows.length >= 1) {
|
394
|
+
self._ec.dbData = result1.rows.item(0).value;
|
395
|
+
} else {
|
396
|
+
self._ec.dbData = "";
|
397
|
+
}
|
398
|
+
}, function (tx, err) {});
|
399
|
+
});
|
400
|
+
}
|
401
|
+
}
|
402
|
+
} catch (e) { }
|
403
|
+
};
|
404
|
+
|
405
|
+
this.<%= Evercookie.js_class %>_session_storage = function (name, value) {
|
406
|
+
try {
|
407
|
+
if (sessionStorage) {
|
408
|
+
if (value !== undefined) {
|
409
|
+
sessionStorage.setItem(name, value);
|
410
|
+
} else {
|
411
|
+
return sessionStorage.getItem(name);
|
412
|
+
}
|
413
|
+
}
|
414
|
+
} catch (e) { }
|
415
|
+
};
|
416
|
+
|
417
|
+
this.<%= Evercookie.js_class %>_global_storage = function (name, value) {
|
418
|
+
if (globalStorage) {
|
419
|
+
var host = this.getHost();
|
420
|
+
try {
|
421
|
+
if (value !== undefined) {
|
422
|
+
globalStorage[host][name] = value;
|
423
|
+
} else {
|
424
|
+
return globalStorage[host][name];
|
425
|
+
}
|
426
|
+
} catch (e) { }
|
427
|
+
}
|
428
|
+
};
|
429
|
+
|
430
|
+
// public method for encoding
|
431
|
+
this.encode = function (input) {
|
432
|
+
var output = "",
|
433
|
+
chr1, chr2, chr3, enc1, enc2, enc3, enc4,
|
434
|
+
i = 0;
|
435
|
+
|
436
|
+
input = this._utf8_encode(input);
|
437
|
+
|
438
|
+
while (i < input.length) {
|
439
|
+
|
440
|
+
chr1 = input.charCodeAt(i++);
|
441
|
+
chr2 = input.charCodeAt(i++);
|
442
|
+
chr3 = input.charCodeAt(i++);
|
443
|
+
|
444
|
+
enc1 = chr1 >> 2;
|
445
|
+
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
|
446
|
+
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
|
447
|
+
enc4 = chr3 & 63;
|
448
|
+
|
449
|
+
if (isNaN(chr2)) {
|
450
|
+
enc3 = enc4 = 64;
|
451
|
+
} else if (isNaN(chr3)) {
|
452
|
+
enc4 = 64;
|
453
|
+
}
|
454
|
+
|
455
|
+
output = output +
|
456
|
+
_baseKeyStr.charAt(enc1) + _baseKeyStr.charAt(enc2) +
|
457
|
+
_baseKeyStr.charAt(enc3) + _baseKeyStr.charAt(enc4);
|
458
|
+
|
459
|
+
}
|
460
|
+
|
461
|
+
return output;
|
462
|
+
};
|
463
|
+
|
464
|
+
// public method for decoding
|
465
|
+
this.decode = function (input) {
|
466
|
+
var output = "",
|
467
|
+
chr1, chr2, chr3,
|
468
|
+
enc1, enc2, enc3, enc4,
|
469
|
+
i = 0;
|
470
|
+
|
471
|
+
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
|
472
|
+
|
473
|
+
while (i < input.length) {
|
474
|
+
enc1 = _baseKeyStr.indexOf(input.charAt(i++));
|
475
|
+
enc2 = _baseKeyStr.indexOf(input.charAt(i++));
|
476
|
+
enc3 = _baseKeyStr.indexOf(input.charAt(i++));
|
477
|
+
enc4 = _baseKeyStr.indexOf(input.charAt(i++));
|
478
|
+
|
479
|
+
chr1 = (enc1 << 2) | (enc2 >> 4);
|
480
|
+
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
|
481
|
+
chr3 = ((enc3 & 3) << 6) | enc4;
|
482
|
+
|
483
|
+
output = output + String.fromCharCode(chr1);
|
484
|
+
|
485
|
+
if (enc3 !== 64) {
|
486
|
+
output = output + String.fromCharCode(chr2);
|
487
|
+
}
|
488
|
+
if (enc4 !== 64) {
|
489
|
+
output = output + String.fromCharCode(chr3);
|
490
|
+
}
|
491
|
+
}
|
492
|
+
output = this._utf8_decode(output);
|
493
|
+
return output;
|
494
|
+
};
|
495
|
+
|
496
|
+
// private method for UTF-8 encoding
|
497
|
+
this._utf8_encode = function (str) {
|
498
|
+
str = str.replace(/\r\n/g, "\n");
|
499
|
+
var utftext = "", i = 0, n = str.length, c;
|
500
|
+
for (; i < n; i++) {
|
501
|
+
c = str.charCodeAt(i);
|
502
|
+
if (c < 128) {
|
503
|
+
utftext += String.fromCharCode(c);
|
504
|
+
} else if ((c > 127) && (c < 2048)) {
|
505
|
+
utftext += String.fromCharCode((c >> 6) | 192);
|
506
|
+
utftext += String.fromCharCode((c & 63) | 128);
|
507
|
+
} else {
|
508
|
+
utftext += String.fromCharCode((c >> 12) | 224);
|
509
|
+
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
|
510
|
+
utftext += String.fromCharCode((c & 63) | 128);
|
511
|
+
}
|
512
|
+
}
|
513
|
+
return utftext;
|
514
|
+
};
|
515
|
+
|
516
|
+
// private method for UTF-8 decoding
|
517
|
+
this._utf8_decode = function (utftext) {
|
518
|
+
var str = "",
|
519
|
+
i = 0, n = utftext.length,
|
520
|
+
c = 0, c1 = 0, c2 = 0, c3 = 0;
|
521
|
+
while (i < n) {
|
522
|
+
c = utftext.charCodeAt(i);
|
523
|
+
if (c < 128) {
|
524
|
+
str += String.fromCharCode(c);
|
525
|
+
i += 1;
|
526
|
+
} else if ((c > 191) && (c < 224)) {
|
527
|
+
c2 = utftext.charCodeAt(i + 1);
|
528
|
+
str += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
|
529
|
+
i += 2;
|
530
|
+
} else {
|
531
|
+
c2 = utftext.charCodeAt(i + 1);
|
532
|
+
c3 = utftext.charCodeAt(i + 2);
|
533
|
+
str += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
|
534
|
+
i += 3;
|
535
|
+
}
|
536
|
+
}
|
537
|
+
return str;
|
538
|
+
};
|
539
|
+
|
540
|
+
this.createElem = function (type, name, append) {
|
541
|
+
var el;
|
542
|
+
if (name !== undefined && document.getElementById(name)) {
|
543
|
+
el = document.getElementById(name);
|
544
|
+
} else {
|
545
|
+
el = document.createElement(type);
|
546
|
+
}
|
547
|
+
el.style.visibility = "hidden";
|
548
|
+
el.style.position = "absolute";
|
549
|
+
|
550
|
+
if (name) {
|
551
|
+
el.setAttribute("id", name);
|
552
|
+
}
|
553
|
+
|
554
|
+
if (append) {
|
555
|
+
document.body.appendChild(el);
|
556
|
+
}
|
557
|
+
return el;
|
558
|
+
};
|
559
|
+
|
560
|
+
this.createIframe = function (url, name) {
|
561
|
+
var el = this.createElem("iframe", name, 1);
|
562
|
+
el.setAttribute("src", url);
|
563
|
+
return el;
|
564
|
+
};
|
565
|
+
|
566
|
+
// wait for our swfobject to appear (swfobject.js to load)
|
567
|
+
var waitForSwf = this.waitForSwf = function (i) {
|
568
|
+
if (i === undefined) {
|
569
|
+
i = 0;
|
570
|
+
} else {
|
571
|
+
i++;
|
572
|
+
}
|
573
|
+
|
574
|
+
// wait for ~2 seconds for swfobject to appear
|
575
|
+
if (i < _ec_tests && typeof swfobject === "undefined") {
|
576
|
+
setTimeout(function () {
|
577
|
+
waitForSwf(i);
|
578
|
+
}, 300);
|
579
|
+
}
|
580
|
+
};
|
581
|
+
|
582
|
+
this.<%= Evercookie.js_class %>_cookie = function (name, value) {
|
583
|
+
if (value !== undefined) {
|
584
|
+
// expire the cookie first
|
585
|
+
document.cookie = name + "=; expires=Mon, 20 Sep 2010 00:00:00 UTC; path=<%= Evercookie.get_cookie_path %>";
|
586
|
+
document.cookie = name + "=" + value + "; expires=Tue, 31 Dec 2030 00:00:00 UTC; path=<%= Evercookie.get_cookie_path %>";
|
587
|
+
} else {
|
588
|
+
return this.getFromStr(name, document.cookie);
|
589
|
+
}
|
590
|
+
};
|
591
|
+
|
592
|
+
// get value from param-like string (eg, "x=y&name=VALUE")
|
593
|
+
this.getFromStr = function (name, text) {
|
594
|
+
if (typeof text !== "string") {
|
595
|
+
return;
|
596
|
+
}
|
597
|
+
var nameEQ = name + "=",
|
598
|
+
ca = text.split(/[;&]/),
|
599
|
+
i, c;
|
600
|
+
for (i = 0; i < ca.length; i++) {
|
601
|
+
c = ca[i];
|
602
|
+
while (c.charAt(0) === " ") {
|
603
|
+
c = c.substring(1, c.length);
|
604
|
+
}
|
605
|
+
if (c.indexOf(nameEQ) === 0) {
|
606
|
+
return c.substring(nameEQ.length, c.length);
|
607
|
+
}
|
608
|
+
}
|
609
|
+
};
|
610
|
+
|
611
|
+
this.getHost = function () {
|
612
|
+
return window.location.host.replace(/:\d+/, '');
|
613
|
+
};
|
614
|
+
|
615
|
+
this.toHex = function (str) {
|
616
|
+
var r = "",
|
617
|
+
e = str.length,
|
618
|
+
c = 0,
|
619
|
+
h;
|
620
|
+
while (c < e) {
|
621
|
+
h = str.charCodeAt(c++).toString(16);
|
622
|
+
while (h.length < 2) {
|
623
|
+
h = "0" + h;
|
624
|
+
}
|
625
|
+
r += h;
|
626
|
+
}
|
627
|
+
return r;
|
628
|
+
};
|
629
|
+
|
630
|
+
this.fromHex = function (str) {
|
631
|
+
var r = "",
|
632
|
+
e = str.length,
|
633
|
+
s;
|
634
|
+
while (e >= 0) {
|
635
|
+
s = e - 2;
|
636
|
+
r = String.fromCharCode("0x" + str.substring(s, e)) + r;
|
637
|
+
e = s;
|
638
|
+
}
|
639
|
+
return r;
|
640
|
+
};
|
641
|
+
|
642
|
+
/* create our anchor tag */
|
643
|
+
var _link = this.createElem("a", "_ec_rgb_link"),
|
644
|
+
/* for monitoring */
|
645
|
+
created_style,
|
646
|
+
/* create a custom style tag for the specific link. Set the CSS visited selector to a known value */
|
647
|
+
_cssText = "#_ec_rgb_link:visited{display:none;color:#FF0000}",
|
648
|
+
style;
|
649
|
+
|
650
|
+
/* Methods for IE6, IE7, FF, Opera, and Safari */
|
651
|
+
try {
|
652
|
+
created_style = 1;
|
653
|
+
style = document.createElement("style");
|
654
|
+
if (style.styleSheet) {
|
655
|
+
style.styleSheet.innerHTML = _cssText;
|
656
|
+
} else if (style.innerHTML) {
|
657
|
+
style.innerHTML = _cssText;
|
658
|
+
} else {
|
659
|
+
style.appendChild(document.createTextNode(_cssText));
|
660
|
+
}
|
661
|
+
} catch (e) {
|
662
|
+
created_style = 0;
|
663
|
+
}
|
664
|
+
|
665
|
+
/* if test_color, return -1 if we can't set a style */
|
666
|
+
this._getRGB = function (u, test_color) {
|
667
|
+
if (test_color && created_style === 0) {
|
668
|
+
return -1;
|
669
|
+
}
|
670
|
+
|
671
|
+
/* create the new anchor tag with the appropriate URL information */
|
672
|
+
_link.href = u;
|
673
|
+
_link.innerHTML = u;
|
674
|
+
// not sure why, but the next two appendChilds always have to happen vs just once
|
675
|
+
document.body.appendChild(style);
|
676
|
+
document.body.appendChild(_link);
|
677
|
+
|
678
|
+
/* add the link to the DOM and save the visible computed color */
|
679
|
+
var color;
|
680
|
+
if (document.defaultView) {
|
681
|
+
color = document.defaultView.getComputedStyle(_link, null).getPropertyValue("color");
|
682
|
+
} else {
|
683
|
+
color = _link.currentStyle.color;
|
684
|
+
}
|
685
|
+
return color;
|
686
|
+
};
|
687
|
+
|
688
|
+
this._testURL = function (url, no_color) {
|
689
|
+
var color = this._getRGB(url);
|
690
|
+
|
691
|
+
/* check to see if the link has been visited if the computed color is red */
|
692
|
+
if (color === "rgb(255, 0, 0)" || color === "#ff0000") {
|
693
|
+
return 1;
|
694
|
+
} else if (no_color && color !== no_color) {
|
695
|
+
/* if our style trick didn't work, just compare default style colors */
|
696
|
+
return 1;
|
697
|
+
}
|
698
|
+
/* not found */
|
699
|
+
return 0;
|
700
|
+
};
|
701
|
+
|
702
|
+
};
|
703
|
+
return this._class;
|
704
|
+
}(window));
|