vidibus-xss 0.1.6 → 0.1.7
Sign up to get free protection for your applications and to get access to all the features.
- data/.bundle/config +2 -0
- data/.rspec +2 -0
- data/Gemfile +13 -0
- data/Gemfile.lock +107 -0
- data/Rakefile +6 -18
- data/VERSION +1 -1
- data/lib/vidibus/xss/extensions/controller.rb +70 -58
- data/public/javascripts/vidibus.js +16 -178
- data/public/javascripts/vidibus.loader.js +186 -0
- data/public/javascripts/vidibus.xss.js +16 -2
- data/vidibus-xss.gemspec +8 -13
- metadata +15 -55
- data/spec/spec.opts +0 -2
data/.bundle/config
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
abstract (1.0.0)
|
5
|
+
actionmailer (3.0.0)
|
6
|
+
actionpack (= 3.0.0)
|
7
|
+
mail (~> 2.2.5)
|
8
|
+
actionpack (3.0.0)
|
9
|
+
activemodel (= 3.0.0)
|
10
|
+
activesupport (= 3.0.0)
|
11
|
+
builder (~> 2.1.2)
|
12
|
+
erubis (~> 2.6.6)
|
13
|
+
i18n (~> 0.4.1)
|
14
|
+
rack (~> 1.2.1)
|
15
|
+
rack-mount (~> 0.6.12)
|
16
|
+
rack-test (~> 0.5.4)
|
17
|
+
tzinfo (~> 0.3.23)
|
18
|
+
activemodel (3.0.0)
|
19
|
+
activesupport (= 3.0.0)
|
20
|
+
builder (~> 2.1.2)
|
21
|
+
i18n (~> 0.4.1)
|
22
|
+
activerecord (3.0.0)
|
23
|
+
activemodel (= 3.0.0)
|
24
|
+
activesupport (= 3.0.0)
|
25
|
+
arel (~> 1.0.0)
|
26
|
+
tzinfo (~> 0.3.23)
|
27
|
+
activeresource (3.0.0)
|
28
|
+
activemodel (= 3.0.0)
|
29
|
+
activesupport (= 3.0.0)
|
30
|
+
activesupport (3.0.0)
|
31
|
+
arel (1.0.1)
|
32
|
+
activesupport (~> 3.0.0)
|
33
|
+
builder (2.1.2)
|
34
|
+
diff-lcs (1.1.2)
|
35
|
+
erubis (2.6.6)
|
36
|
+
abstract (>= 1.0.0)
|
37
|
+
gemcutter (0.6.1)
|
38
|
+
git (1.2.5)
|
39
|
+
i18n (0.4.1)
|
40
|
+
jeweler (1.4.0)
|
41
|
+
gemcutter (>= 0.1.0)
|
42
|
+
git (>= 1.2.5)
|
43
|
+
rubyforge (>= 2.0.0)
|
44
|
+
json_pure (1.4.6)
|
45
|
+
macaddr (1.0.0)
|
46
|
+
mail (2.2.5)
|
47
|
+
activesupport (>= 2.3.6)
|
48
|
+
mime-types
|
49
|
+
treetop (>= 1.4.5)
|
50
|
+
mime-types (1.16)
|
51
|
+
nokogiri (1.4.3.1)
|
52
|
+
polyglot (0.3.1)
|
53
|
+
rack (1.2.1)
|
54
|
+
rack-mount (0.6.13)
|
55
|
+
rack (>= 1.0.0)
|
56
|
+
rack-test (0.5.4)
|
57
|
+
rack (>= 1.0)
|
58
|
+
rails (3.0.0)
|
59
|
+
actionmailer (= 3.0.0)
|
60
|
+
actionpack (= 3.0.0)
|
61
|
+
activerecord (= 3.0.0)
|
62
|
+
activeresource (= 3.0.0)
|
63
|
+
activesupport (= 3.0.0)
|
64
|
+
bundler (~> 1.0.0)
|
65
|
+
railties (= 3.0.0)
|
66
|
+
railties (3.0.0)
|
67
|
+
actionpack (= 3.0.0)
|
68
|
+
activesupport (= 3.0.0)
|
69
|
+
rake (>= 0.8.4)
|
70
|
+
thor (~> 0.14.0)
|
71
|
+
rake (0.8.7)
|
72
|
+
relevance-rcov (0.9.2.1)
|
73
|
+
rr (1.0.0)
|
74
|
+
rspec (2.0.0.beta.20)
|
75
|
+
rspec-core (= 2.0.0.beta.20)
|
76
|
+
rspec-expectations (= 2.0.0.beta.20)
|
77
|
+
rspec-mocks (= 2.0.0.beta.20)
|
78
|
+
rspec-core (2.0.0.beta.20)
|
79
|
+
rspec-expectations (2.0.0.beta.20)
|
80
|
+
diff-lcs (>= 1.1.2)
|
81
|
+
rspec-mocks (2.0.0.beta.20)
|
82
|
+
rubyforge (2.0.4)
|
83
|
+
json_pure (>= 1.1.7)
|
84
|
+
thor (0.14.0)
|
85
|
+
treetop (1.4.8)
|
86
|
+
polyglot (>= 0.3.1)
|
87
|
+
tzinfo (0.3.23)
|
88
|
+
uuid (2.3.1)
|
89
|
+
macaddr (~> 1.0)
|
90
|
+
vidibus-routing_error (0.1.4)
|
91
|
+
rails (>= 3.0.0.rc)
|
92
|
+
vidibus-uuid (0.3.6)
|
93
|
+
uuid
|
94
|
+
|
95
|
+
PLATFORMS
|
96
|
+
ruby
|
97
|
+
|
98
|
+
DEPENDENCIES
|
99
|
+
jeweler
|
100
|
+
nokogiri
|
101
|
+
rails (~> 3.0.0)
|
102
|
+
rake
|
103
|
+
relevance-rcov
|
104
|
+
rr
|
105
|
+
rspec (~> 2.0.0.beta.20)
|
106
|
+
vidibus-routing_error
|
107
|
+
vidibus-uuid
|
data/Rakefile
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
require "rubygems"
|
2
2
|
require "rake"
|
3
|
+
require "rake/rdoctask"
|
4
|
+
require "rspec"
|
5
|
+
require "rspec/core/rake_task"
|
3
6
|
|
4
7
|
begin
|
5
8
|
require "jeweler"
|
@@ -10,40 +13,25 @@ begin
|
|
10
13
|
gem.email = "andre@vidibus.com"
|
11
14
|
gem.homepage = "http://github.com/vidibus/vidibus-xss"
|
12
15
|
gem.authors = ["Andre Pankratz"]
|
13
|
-
gem.add_development_dependency "rspec", ">= 1.2.9"
|
14
|
-
gem.add_development_dependency "relevance-rcov"
|
15
|
-
gem.add_development_dependency "rr"
|
16
16
|
gem.add_dependency "rails", ">= 3.0.0.rc"
|
17
17
|
gem.add_dependency "nokogiri"
|
18
18
|
gem.add_dependency "vidibus-routing_error"
|
19
|
-
|
20
|
-
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
21
19
|
end
|
22
20
|
Jeweler::GemcutterTasks.new
|
23
21
|
rescue LoadError
|
24
22
|
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
25
23
|
end
|
26
24
|
|
27
|
-
|
28
|
-
|
29
|
-
spec.libs << "lib" << "spec"
|
30
|
-
spec.spec_files = FileList["spec/**/*_spec.rb"]
|
31
|
-
end
|
32
|
-
|
33
|
-
Spec::Rake::SpecTask.new(:rcov) do |t|
|
34
|
-
t.spec_files = FileList["spec/vidibus/**/*_spec.rb"]
|
25
|
+
Rspec::Core::RakeTask.new(:rcov) do |t|
|
26
|
+
t.pattern = "spec/**/*_spec.rb"
|
35
27
|
t.rcov = true
|
36
28
|
t.rcov_opts = ["--exclude", "^spec,/gems/"]
|
37
29
|
end
|
38
30
|
|
39
|
-
task :spec => :check_dependencies
|
40
|
-
task :default => :spec
|
41
|
-
|
42
|
-
require "rake/rdoctask"
|
43
31
|
Rake::RDocTask.new do |rdoc|
|
44
32
|
version = File.exist?("VERSION") ? File.read("VERSION") : ""
|
45
33
|
rdoc.rdoc_dir = "rdoc"
|
46
|
-
rdoc.title = "vidibus-
|
34
|
+
rdoc.title = "vidibus-inheritance #{version}"
|
47
35
|
rdoc.rdoc_files.include("README*")
|
48
36
|
rdoc.rdoc_files.include("lib/**/*.rb")
|
49
37
|
rdoc.options << "--charset=utf-8"
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.7
|
@@ -4,52 +4,53 @@ module Vidibus
|
|
4
4
|
module Xss
|
5
5
|
module Extensions
|
6
6
|
module Controller
|
7
|
+
|
7
8
|
extend ActiveSupport::Concern
|
8
9
|
|
9
10
|
included do
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
11
|
+
helper_method :url_for, :xss_request?, :fullpath_url
|
12
|
+
respond_to :html, :xss
|
13
|
+
rescue_from ActionController::RoutingError, :with => :rescue_404
|
14
|
+
end
|
15
|
+
|
16
|
+
# Set hostname of clients that are allowed to access this resource.
|
17
|
+
def xss_clients
|
18
|
+
raise %(Define #xss_clients in your ApplicationController that returns all hosts that are allowed to access your service.\nExample: %w[http://myconsumer.local])
|
19
|
+
end
|
20
|
+
|
21
|
+
protected
|
22
|
+
|
23
|
+
# Returns layout for current request format.
|
24
|
+
def get_layout(format = nil)
|
25
|
+
(xss_request? or format == :xss) ? 'xss.haml' : 'application'
|
26
|
+
end
|
27
|
+
|
28
|
+
# IMPORTANT: restart server to apply modifications.
|
29
|
+
def rescue_404
|
30
|
+
return if respond_to_options_request
|
31
|
+
super
|
32
|
+
end
|
32
33
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
34
|
+
# Responds to OPTIONS request.
|
35
|
+
# When sending data to foreign domain by AJAX, Firefox will send an OPTIONS request first.
|
36
|
+
#
|
37
|
+
# == Usage:
|
38
|
+
#
|
39
|
+
# Set up a catch-all route for handling 404s like this, if you haven't done it already:
|
40
|
+
#
|
41
|
+
# match "*path" => "application#rescue_404"
|
42
|
+
#
|
43
|
+
# In ApplicationController, define a method that will be called by this catch-all route:
|
44
|
+
#
|
45
|
+
# def rescue_404
|
46
|
+
# respond_to_options_request
|
47
|
+
# end
|
48
|
+
#
|
49
|
+
def respond_to_options_request
|
50
|
+
return unless options_request?
|
51
|
+
xss_access_control_headers
|
52
|
+
render(:text => "OK", :status => 200) and return true
|
53
|
+
end
|
53
54
|
|
54
55
|
# Returns true if current request is in XSS format.
|
55
56
|
def xss_request?
|
@@ -72,9 +73,11 @@ module Vidibus
|
|
72
73
|
# Set access control headers to allow cross-domain XMLHttpRequest calls.
|
73
74
|
# For more information, see: https://developer.mozilla.org/En/HTTP_access_control
|
74
75
|
def xss_access_control_headers
|
75
|
-
headers["Access-Control-Allow-Origin"] = "
|
76
|
-
headers["Access-Control-Allow-Methods"] = "GET,
|
77
|
-
headers["Access-Control-Allow-Headers"] = "Content-Type"
|
76
|
+
headers["Access-Control-Allow-Origin"] = xss_clients.join(",")
|
77
|
+
headers["Access-Control-Allow-Methods"] = "GET,PUT,POST,OPTIONS"
|
78
|
+
headers["Access-Control-Allow-Headers"] = "Content-Type,Depth,User-Agent,X-File-Size,X-Requested-With,If-Modified-Since,X-File-Name,Cache-Control"
|
79
|
+
headers["Access-Control-Allow-Credentials"] = "true"
|
80
|
+
headers["Access-Control-Max-Age"] = "1728000" # Cache this response for 20 days.
|
78
81
|
end
|
79
82
|
|
80
83
|
def extract_xss_html(dom)
|
@@ -167,12 +170,12 @@ module Vidibus
|
|
167
170
|
path = options.delete(:get)
|
168
171
|
redirect = options.delete(:redirect)
|
169
172
|
callback = options.delete(:callback)
|
170
|
-
|
173
|
+
|
171
174
|
raise "Please provide :content, :get, :redirect or :callback." unless content or path or redirect or callback
|
172
175
|
raise "Please provide either :content to render or :get location to load. Not both." if content and path
|
173
|
-
|
176
|
+
|
174
177
|
xss = ""
|
175
|
-
|
178
|
+
|
176
179
|
# determine scope
|
177
180
|
if !(scope = params[:scope]).blank?
|
178
181
|
scope = "$('##{scope}')"
|
@@ -180,7 +183,7 @@ module Vidibus
|
|
180
183
|
scope = "$s#{xss_random_string}"
|
181
184
|
xss << %(var #{scope}=vidibus.xss.detectScope();)
|
182
185
|
end
|
183
|
-
|
186
|
+
|
184
187
|
# set host for current scope
|
185
188
|
xss << %(vidibus.xss.setHost('#{request.protocol}#{request.host_with_port}',#{scope});)
|
186
189
|
|
@@ -202,7 +205,9 @@ module Vidibus
|
|
202
205
|
%(vidibus.xss.callback(#{callback.to_json},#{scope});)
|
203
206
|
end
|
204
207
|
end
|
205
|
-
|
208
|
+
|
209
|
+
xss_content << xss_csrf_vars
|
210
|
+
|
206
211
|
# wait until resources have been loaded, before rendering XSS content
|
207
212
|
if defer
|
208
213
|
function_name = "rx#{xss_random_string}"
|
@@ -222,16 +227,19 @@ module Vidibus
|
|
222
227
|
random
|
223
228
|
end
|
224
229
|
end
|
225
|
-
|
226
230
|
|
227
|
-
|
231
|
+
# Sets vars for CSRF protection.
|
232
|
+
def xss_csrf_vars
|
233
|
+
%(vidibus.csrf.param='#{request_forgery_protection_token}', vidibus.csrf.token='#{form_authenticity_token}';)
|
234
|
+
end
|
228
235
|
|
236
|
+
### Override core extensions
|
229
237
|
|
230
|
-
# Bypasses authenticity verification for XSS requests.
|
231
|
-
# TODO: Verify authenticity in other ways (Single Sign-on).
|
232
|
-
def verify_authenticity_token
|
233
|
-
|
234
|
-
end
|
238
|
+
# # Bypasses authenticity verification for XSS requests.
|
239
|
+
# # TODO: Verify authenticity in other ways (Single Sign-on).
|
240
|
+
# def verify_authenticity_token
|
241
|
+
# xss_request? || super
|
242
|
+
# end
|
235
243
|
|
236
244
|
# Extension of url_for:
|
237
245
|
# Transform given relative paths into absolute urls.
|
@@ -267,7 +275,8 @@ module Vidibus
|
|
267
275
|
end
|
268
276
|
|
269
277
|
# Extensions of render method:
|
270
|
-
# Renders XSS response if requested
|
278
|
+
# Renders XSS response if requested.
|
279
|
+
# If Origin is withing allowed xss_clients, xss heades will be sent to allow authorization.
|
271
280
|
def render(*args, &block)
|
272
281
|
args << options = args.extract_options!
|
273
282
|
if xss_request? or options[:format] == :xss
|
@@ -287,6 +296,9 @@ module Vidibus
|
|
287
296
|
|
288
297
|
render_xss(xss)
|
289
298
|
else
|
299
|
+
if xss_clients.include?(request.headers["Origin"])
|
300
|
+
xss_access_control_headers
|
301
|
+
end
|
290
302
|
super(*args, &block)
|
291
303
|
end
|
292
304
|
end
|
@@ -5,189 +5,27 @@
|
|
5
5
|
|
6
6
|
var vidibus = {};
|
7
7
|
|
8
|
-
|
9
|
-
vidibus.loader = {
|
10
|
-
|
11
|
-
complete: true, // indicates that loading has been finished
|
12
|
-
queue: [], // holds resources that are queued to load
|
13
|
-
loading: undefined, // holds resource that is currently being loaded
|
14
|
-
preloaded: undefined, // holds resources that are included in consumer base file
|
15
|
-
loaded: {}, // holds resources that are currently loaded
|
16
|
-
unused: {}, // holds resources that are loaded, but not required anymore
|
17
|
-
|
18
|
-
/**
|
19
|
-
* Load resources.
|
20
|
-
*/
|
21
|
-
load: function(resources, scope) {
|
22
|
-
this.initStaticResources();
|
23
|
-
this.complete = false;
|
24
|
-
this.unused = jQuery.extend({}, this.loaded); // clone
|
25
|
-
|
26
|
-
$(resources).each(function() {
|
27
|
-
var resource = this,
|
28
|
-
src = resource.src,
|
29
|
-
name = vidibus.loader.resourceName(src);
|
30
|
-
|
31
|
-
resource.name = name;
|
32
|
-
resource.scopes = {}
|
33
|
-
resource.scopes[scope] = true;
|
34
|
-
|
35
|
-
// remove current file, because it is used
|
36
|
-
delete vidibus.loader.unused[name];
|
37
|
-
|
38
|
-
// skip files that have already been loaded
|
39
|
-
if (vidibus.loader.loaded[name]) {
|
40
|
-
vidibus.loader.loaded[name].scopes[scope] = true; // add current scope
|
41
|
-
return; // continue
|
42
|
-
} else if (vidibus.loader.preloaded[name]) {
|
43
|
-
return; // continue
|
44
|
-
}
|
45
|
-
|
46
|
-
vidibus.loader.loaded[name] = resource;
|
47
|
-
switch (resource.type) {
|
48
|
-
|
49
|
-
// load css file directly
|
50
|
-
case 'text/css':
|
51
|
-
var element = document.createElement("link");
|
52
|
-
element.rel = 'stylesheet';
|
53
|
-
element.href = src;
|
54
|
-
element.media = resource.media || 'all';
|
55
|
-
element.type = 'text/css';
|
56
|
-
vidibus.loader.appendToHead(element);
|
57
|
-
break;
|
58
|
-
|
59
|
-
// push script file to loading queue
|
60
|
-
case 'text/javascript':
|
61
|
-
vidibus.loader.queue.push(resource);
|
62
|
-
break;
|
63
|
-
|
64
|
-
default: console.log('vidibus.loader.load: unsupported resource type: '+resource.type);
|
65
|
-
}
|
66
|
-
});
|
67
|
-
|
68
|
-
this.loadQueue(true);
|
69
|
-
this.unloadUnused(scope);
|
70
|
-
},
|
8
|
+
jQuery(function ($) {
|
71
9
|
|
72
10
|
/**
|
73
|
-
*
|
11
|
+
* Assign global cross-site request forgery protection variables.
|
12
|
+
* To use vidibus.csrf, simply append it to your options object:
|
13
|
+
* jQuery.extend(yourSettings, vidibus.csrf.data)
|
74
14
|
*/
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
/**
|
80
|
-
* Returns list of static resources.
|
81
|
-
*/
|
82
|
-
initStaticResources: function() {
|
83
|
-
if (vidibus.loader.preloaded == undefined) {
|
84
|
-
vidibus.loader.preloaded = {};
|
85
|
-
var $resource, src, name;
|
86
|
-
$('script[src],link[href]',$('head')).each(function() {
|
87
|
-
$resource = $(this);
|
88
|
-
src = $resource.attr('src') || $resource.attr('href');
|
89
|
-
name = vidibus.loader.resourceName(src);
|
90
|
-
vidibus.loader.preloaded[name] = src;
|
91
|
-
});
|
92
|
-
}
|
93
|
-
},
|
94
|
-
|
95
|
-
/**
|
96
|
-
* Loads resources in queue.
|
97
|
-
*/
|
98
|
-
loadQueue: function(start) {
|
99
|
-
|
100
|
-
// Reduce queue if this method is called as callback.
|
101
|
-
if(start != true) {
|
102
|
-
vidibus.loader.queue.shift();
|
103
|
-
}
|
104
|
-
|
105
|
-
var resource = vidibus.loader.queue[0];
|
15
|
+
vidibus.csrf = {
|
16
|
+
param: $('meta[name=csrf-param]').attr('content'),
|
17
|
+
token: $('meta[name=csrf-token]').attr('content'),
|
106
18
|
|
107
|
-
|
108
|
-
|
109
|
-
if
|
110
|
-
|
111
|
-
return;
|
19
|
+
data: function() {
|
20
|
+
obj = {};
|
21
|
+
if(this.param && this.token) {
|
22
|
+
obj[this.param] = this.token;
|
112
23
|
}
|
113
|
-
|
114
|
-
vidibus.loader.loadScript(resource.src, vidibus.loader.loadQueue);
|
115
|
-
} else {
|
116
|
-
vidibus.loader.loading = undefined;
|
117
|
-
vidibus.loader.complete = true;
|
24
|
+
return obj;
|
118
25
|
}
|
119
|
-
}
|
26
|
+
};
|
120
27
|
|
121
|
-
|
122
|
-
|
123
|
-
*/
|
124
|
-
loadScript: function(src, callback) {
|
125
|
-
var element = document.createElement("script");
|
126
|
-
if (element.addEventListener) {
|
127
|
-
element.addEventListener("load", callback, false);
|
128
|
-
} else {
|
129
|
-
// IE
|
130
|
-
element.onreadystatechange = function() {
|
131
|
-
if (this.readyState == 'loaded') callback.call(this);
|
132
|
-
}
|
133
|
-
}
|
134
|
-
element.type = 'text/javascript';
|
135
|
-
element.src = src;
|
136
|
-
vidibus.loader.appendToHead(element);
|
137
|
-
element = null;
|
138
|
-
},
|
139
|
-
|
140
|
-
/**
|
141
|
-
* Detects unused resources and removes them.
|
142
|
-
*/
|
143
|
-
unloadUnused: function(scope) {
|
144
|
-
var name, resources = [];
|
145
|
-
for(name in vidibus.loader.unused) {
|
146
|
-
|
147
|
-
// Remove dependency for given scope.
|
148
|
-
if (vidibus.loader.unused[name].scopes[scope]) {
|
149
|
-
delete vidibus.loader.unused[name].scopes[scope];
|
150
|
-
}
|
151
|
-
|
152
|
-
// Unload resource if it has no dependencies left.
|
153
|
-
if ($.isEmptyObject(vidibus.loader.unused[name].scopes)) {
|
154
|
-
resources.push(vidibus.loader.unused[name]);
|
155
|
-
}
|
156
|
-
}
|
157
|
-
vidibus.loader.unload(resources);
|
158
|
-
vidibus.loader.unused = {}
|
159
|
-
},
|
160
|
-
|
161
|
-
/**
|
162
|
-
* Removes resources given in list.
|
163
|
-
*/
|
164
|
-
unload: function(resources) {
|
165
|
-
var src, data, resource;
|
166
|
-
$(resources).each(function() {
|
167
|
-
resource = this;
|
168
|
-
src = resource.src;
|
169
|
-
|
170
|
-
// console.log('REMOVE UNUSED RESOURCE: '+src);
|
171
|
-
|
172
|
-
switch (resource.type) {
|
173
|
-
case "text/css":
|
174
|
-
$('link[href="'+src+'"]').remove();
|
175
|
-
break;
|
176
|
-
|
177
|
-
case "text/javascript":
|
178
|
-
$('script[src="'+src+'"]').remove();
|
179
|
-
break;
|
180
|
-
|
181
|
-
default: console.log('vidibus.loader.unload: unsupported resource type: '+resource.type);
|
182
|
-
}
|
183
|
-
delete vidibus.loader.loaded[resource.name];
|
184
|
-
});
|
185
|
-
},
|
186
|
-
|
187
|
-
/**
|
188
|
-
* Appends given element to document head.
|
189
|
-
*/
|
190
|
-
appendToHead: function(element) {
|
191
|
-
document.getElementsByTagName("head")[0].appendChild(element);
|
28
|
+
if(vidibus.csrf.param && vidibus.csrf.token) {
|
29
|
+
vidibus.csrf.data[vidibus.csrf.param] = encodeURIComponent(vidibus.csrf.token);
|
192
30
|
}
|
193
|
-
};
|
31
|
+
});
|
@@ -0,0 +1,186 @@
|
|
1
|
+
// Basic loader for stylesheets and javascripts.
|
2
|
+
vidibus.loader = {
|
3
|
+
|
4
|
+
complete: true, // indicates that loading has been finished
|
5
|
+
queue: [], // holds resources that are queued to load
|
6
|
+
loading: undefined, // holds resource that is currently being loaded
|
7
|
+
preloaded: undefined, // holds resources that are included in consumer base file
|
8
|
+
loaded: {}, // holds resources that are currently loaded
|
9
|
+
unused: {}, // holds resources that are loaded, but not required anymore
|
10
|
+
|
11
|
+
/**
|
12
|
+
* Load resources.
|
13
|
+
*/
|
14
|
+
load: function(resources, scope) {
|
15
|
+
this.initStaticResources();
|
16
|
+
this.complete = false;
|
17
|
+
this.unused = jQuery.extend({}, this.loaded); // clone
|
18
|
+
|
19
|
+
$(resources).each(function() {
|
20
|
+
var resource = this,
|
21
|
+
src = resource.src,
|
22
|
+
name = vidibus.loader.resourceName(src);
|
23
|
+
|
24
|
+
resource.name = name;
|
25
|
+
resource.scopes = {}
|
26
|
+
resource.scopes[scope] = true;
|
27
|
+
|
28
|
+
// remove current file, because it is used
|
29
|
+
delete vidibus.loader.unused[name];
|
30
|
+
|
31
|
+
// skip files that have already been loaded
|
32
|
+
if (vidibus.loader.loaded[name]) {
|
33
|
+
vidibus.loader.loaded[name].scopes[scope] = true; // add current scope
|
34
|
+
return; // continue
|
35
|
+
} else if (vidibus.loader.preloaded[name]) {
|
36
|
+
return; // continue
|
37
|
+
}
|
38
|
+
|
39
|
+
vidibus.loader.loaded[name] = resource;
|
40
|
+
switch (resource.type) {
|
41
|
+
|
42
|
+
// load css file directly
|
43
|
+
case 'text/css':
|
44
|
+
var element = document.createElement("link");
|
45
|
+
element.rel = 'stylesheet';
|
46
|
+
element.href = src;
|
47
|
+
element.media = resource.media || 'all';
|
48
|
+
element.type = 'text/css';
|
49
|
+
vidibus.loader.appendToHead(element);
|
50
|
+
break;
|
51
|
+
|
52
|
+
// push script file to loading queue
|
53
|
+
case 'text/javascript':
|
54
|
+
vidibus.loader.queue.push(resource);
|
55
|
+
break;
|
56
|
+
|
57
|
+
default: console.log('vidibus.loader.load: unsupported resource type: '+resource.type);
|
58
|
+
}
|
59
|
+
});
|
60
|
+
|
61
|
+
this.loadQueue(true);
|
62
|
+
this.unloadUnused(scope);
|
63
|
+
},
|
64
|
+
|
65
|
+
/**
|
66
|
+
* Returns file name of resource.
|
67
|
+
*/
|
68
|
+
resourceName: function(url) {
|
69
|
+
return url.match(/\/([^\/\?]+)(\?.*)*$/)[1];
|
70
|
+
},
|
71
|
+
|
72
|
+
/**
|
73
|
+
* Returns list of static resources.
|
74
|
+
*/
|
75
|
+
initStaticResources: function() {
|
76
|
+
if (vidibus.loader.preloaded == undefined) {
|
77
|
+
vidibus.loader.preloaded = {};
|
78
|
+
var $resource, src, name;
|
79
|
+
$('script[src],link[href]',$('head')).each(function() {
|
80
|
+
$resource = $(this);
|
81
|
+
src = $resource.attr('src') || $resource.attr('href');
|
82
|
+
name = vidibus.loader.resourceName(src);
|
83
|
+
vidibus.loader.preloaded[name] = src;
|
84
|
+
});
|
85
|
+
}
|
86
|
+
},
|
87
|
+
|
88
|
+
/**
|
89
|
+
* Loads resources in queue.
|
90
|
+
*/
|
91
|
+
loadQueue: function(start) {
|
92
|
+
|
93
|
+
// Reduce queue if this method is called as callback.
|
94
|
+
if(start != true) {
|
95
|
+
vidibus.loader.queue.shift();
|
96
|
+
}
|
97
|
+
|
98
|
+
var resource = vidibus.loader.queue[0];
|
99
|
+
|
100
|
+
// return if file is currently loading
|
101
|
+
if (resource) {
|
102
|
+
if (resource == vidibus.loader.loading) {
|
103
|
+
// console.log('CURRENTLY LOADING: '+resource.src);
|
104
|
+
return;
|
105
|
+
}
|
106
|
+
vidibus.loader.loading = resource;
|
107
|
+
vidibus.loader.loadScript(resource.src, vidibus.loader.loadQueue);
|
108
|
+
} else {
|
109
|
+
vidibus.loader.loading = undefined;
|
110
|
+
vidibus.loader.complete = true;
|
111
|
+
}
|
112
|
+
},
|
113
|
+
|
114
|
+
/**
|
115
|
+
* Loads script src.
|
116
|
+
*/
|
117
|
+
loadScript: function(src, callback) {
|
118
|
+
var element = document.createElement("script");
|
119
|
+
if (element.addEventListener) {
|
120
|
+
element.addEventListener("load", callback, false);
|
121
|
+
} else {
|
122
|
+
// IE
|
123
|
+
element.onreadystatechange = function() {
|
124
|
+
if (this.readyState == 'loaded') callback.call(this);
|
125
|
+
}
|
126
|
+
}
|
127
|
+
element.type = 'text/javascript';
|
128
|
+
element.src = src;
|
129
|
+
vidibus.loader.appendToHead(element);
|
130
|
+
element = null;
|
131
|
+
},
|
132
|
+
|
133
|
+
/**
|
134
|
+
* Detects unused resources and removes them.
|
135
|
+
*/
|
136
|
+
unloadUnused: function(scope) {
|
137
|
+
var name, resources = [];
|
138
|
+
for(name in vidibus.loader.unused) {
|
139
|
+
|
140
|
+
// Remove dependency for given scope.
|
141
|
+
if (vidibus.loader.unused[name].scopes[scope]) {
|
142
|
+
delete vidibus.loader.unused[name].scopes[scope];
|
143
|
+
}
|
144
|
+
|
145
|
+
// Unload resource if it has no dependencies left.
|
146
|
+
if ($.isEmptyObject(vidibus.loader.unused[name].scopes)) {
|
147
|
+
resources.push(vidibus.loader.unused[name]);
|
148
|
+
}
|
149
|
+
}
|
150
|
+
vidibus.loader.unload(resources);
|
151
|
+
vidibus.loader.unused = {}
|
152
|
+
},
|
153
|
+
|
154
|
+
/**
|
155
|
+
* Removes resources given in list.
|
156
|
+
*/
|
157
|
+
unload: function(resources) {
|
158
|
+
var src, data, resource;
|
159
|
+
$(resources).each(function() {
|
160
|
+
resource = this;
|
161
|
+
src = resource.src;
|
162
|
+
|
163
|
+
// console.log('REMOVE UNUSED RESOURCE: '+src);
|
164
|
+
|
165
|
+
switch (resource.type) {
|
166
|
+
case "text/css":
|
167
|
+
$('link[href="'+src+'"]').remove();
|
168
|
+
break;
|
169
|
+
|
170
|
+
case "text/javascript":
|
171
|
+
$('script[src="'+src+'"]').remove();
|
172
|
+
break;
|
173
|
+
|
174
|
+
default: console.log('vidibus.loader.unload: unsupported resource type: '+resource.type);
|
175
|
+
}
|
176
|
+
delete vidibus.loader.loaded[resource.name];
|
177
|
+
});
|
178
|
+
},
|
179
|
+
|
180
|
+
/**
|
181
|
+
* Appends given element to document head.
|
182
|
+
*/
|
183
|
+
appendToHead: function(element) {
|
184
|
+
document.getElementsByTagName("head")[0].appendChild(element);
|
185
|
+
}
|
186
|
+
};
|
@@ -14,7 +14,6 @@
|
|
14
14
|
// $.ajax({...});
|
15
15
|
// }
|
16
16
|
|
17
|
-
|
18
17
|
vidibus.xss = {
|
19
18
|
initialized: {}, // holds true for every scope that has been initialized
|
20
19
|
fileExtension: 'xss', // use 'xss' as file extension
|
@@ -309,6 +308,7 @@ $(function($) {
|
|
309
308
|
data['_method'] = method;
|
310
309
|
method = 'POST';
|
311
310
|
}
|
311
|
+
$.extend(data, vidibus.csrf.data());
|
312
312
|
$.ajax({
|
313
313
|
url: url,
|
314
314
|
data: data,
|
@@ -316,6 +316,7 @@ $(function($) {
|
|
316
316
|
type: method.toUpperCase(),
|
317
317
|
beforeSend: function(xhr) {
|
318
318
|
el.trigger('ajax:loading', xhr);
|
319
|
+
xhr.withCredentials = "true";
|
319
320
|
},
|
320
321
|
success: function(data, status, xhr) {
|
321
322
|
el.trigger('ajax:success', [data, status, xhr]);
|
@@ -332,4 +333,17 @@ $(function($) {
|
|
332
333
|
}
|
333
334
|
}
|
334
335
|
});
|
335
|
-
});
|
336
|
+
});
|
337
|
+
|
338
|
+
/**
|
339
|
+
* Try to send xhr request withCredentials.
|
340
|
+
* Unfortunately, this has to be set after the connection has been opened.
|
341
|
+
* If you set a beforeSend handler yourself, you have to set withCredentials by yourself.
|
342
|
+
*/
|
343
|
+
$.ajaxSettings.beforeSend = function(xhr) {
|
344
|
+
try {
|
345
|
+
xhr.withCredentials = "true";
|
346
|
+
} catch(e) {
|
347
|
+
alert('Cannot set xhr with credentials:\n'+e)
|
348
|
+
}
|
349
|
+
};
|
data/vidibus-xss.gemspec
CHANGED
@@ -5,18 +5,22 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{vidibus-xss}
|
8
|
-
s.version = "0.1.
|
8
|
+
s.version = "0.1.7"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Andre Pankratz"]
|
12
|
-
s.date = %q{2010-
|
12
|
+
s.date = %q{2010-09-03}
|
13
13
|
s.description = %q{Drop-in XSS support for remote applications.}
|
14
14
|
s.email = %q{andre@vidibus.com}
|
15
15
|
s.extra_rdoc_files = [
|
16
16
|
"README.rdoc"
|
17
17
|
]
|
18
18
|
s.files = [
|
19
|
-
".
|
19
|
+
".bundle/config",
|
20
|
+
".gitignore",
|
21
|
+
".rspec",
|
22
|
+
"Gemfile",
|
23
|
+
"Gemfile.lock",
|
20
24
|
"MIT-LICENSE",
|
21
25
|
"README.rdoc",
|
22
26
|
"Rakefile",
|
@@ -32,8 +36,8 @@ Gem::Specification.new do |s|
|
|
32
36
|
"lib/vidibus/xss/mime_type.rb",
|
33
37
|
"public/javascripts/jquery.ba-bbq.js",
|
34
38
|
"public/javascripts/vidibus.js",
|
39
|
+
"public/javascripts/vidibus.loader.js",
|
35
40
|
"public/javascripts/vidibus.xss.js",
|
36
|
-
"spec/spec.opts",
|
37
41
|
"spec/spec_helper.rb",
|
38
42
|
"vidibus-xss.gemspec"
|
39
43
|
]
|
@@ -51,24 +55,15 @@ Gem::Specification.new do |s|
|
|
51
55
|
s.specification_version = 3
|
52
56
|
|
53
57
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
54
|
-
s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
|
55
|
-
s.add_development_dependency(%q<relevance-rcov>, [">= 0"])
|
56
|
-
s.add_development_dependency(%q<rr>, [">= 0"])
|
57
58
|
s.add_runtime_dependency(%q<rails>, [">= 3.0.0.rc"])
|
58
59
|
s.add_runtime_dependency(%q<nokogiri>, [">= 0"])
|
59
60
|
s.add_runtime_dependency(%q<vidibus-routing_error>, [">= 0"])
|
60
61
|
else
|
61
|
-
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
62
|
-
s.add_dependency(%q<relevance-rcov>, [">= 0"])
|
63
|
-
s.add_dependency(%q<rr>, [">= 0"])
|
64
62
|
s.add_dependency(%q<rails>, [">= 3.0.0.rc"])
|
65
63
|
s.add_dependency(%q<nokogiri>, [">= 0"])
|
66
64
|
s.add_dependency(%q<vidibus-routing_error>, [">= 0"])
|
67
65
|
end
|
68
66
|
else
|
69
|
-
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
70
|
-
s.add_dependency(%q<relevance-rcov>, [">= 0"])
|
71
|
-
s.add_dependency(%q<rr>, [">= 0"])
|
72
67
|
s.add_dependency(%q<rails>, [">= 3.0.0.rc"])
|
73
68
|
s.add_dependency(%q<nokogiri>, [">= 0"])
|
74
69
|
s.add_dependency(%q<vidibus-routing_error>, [">= 0"])
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vidibus-xss
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 21
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 7
|
10
|
+
version: 0.1.7
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Andre Pankratz
|
@@ -15,57 +15,13 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-
|
18
|
+
date: 2010-09-03 00:00:00 +02:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
|
-
- !ruby/object:Gem::Dependency
|
22
|
-
name: rspec
|
23
|
-
prerelease: false
|
24
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
|
-
requirements:
|
27
|
-
- - ">="
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
hash: 13
|
30
|
-
segments:
|
31
|
-
- 1
|
32
|
-
- 2
|
33
|
-
- 9
|
34
|
-
version: 1.2.9
|
35
|
-
type: :development
|
36
|
-
version_requirements: *id001
|
37
|
-
- !ruby/object:Gem::Dependency
|
38
|
-
name: relevance-rcov
|
39
|
-
prerelease: false
|
40
|
-
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
|
-
requirements:
|
43
|
-
- - ">="
|
44
|
-
- !ruby/object:Gem::Version
|
45
|
-
hash: 3
|
46
|
-
segments:
|
47
|
-
- 0
|
48
|
-
version: "0"
|
49
|
-
type: :development
|
50
|
-
version_requirements: *id002
|
51
|
-
- !ruby/object:Gem::Dependency
|
52
|
-
name: rr
|
53
|
-
prerelease: false
|
54
|
-
requirement: &id003 !ruby/object:Gem::Requirement
|
55
|
-
none: false
|
56
|
-
requirements:
|
57
|
-
- - ">="
|
58
|
-
- !ruby/object:Gem::Version
|
59
|
-
hash: 3
|
60
|
-
segments:
|
61
|
-
- 0
|
62
|
-
version: "0"
|
63
|
-
type: :development
|
64
|
-
version_requirements: *id003
|
65
21
|
- !ruby/object:Gem::Dependency
|
66
22
|
name: rails
|
67
23
|
prerelease: false
|
68
|
-
requirement: &
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
69
25
|
none: false
|
70
26
|
requirements:
|
71
27
|
- - ">="
|
@@ -78,11 +34,11 @@ dependencies:
|
|
78
34
|
- rc
|
79
35
|
version: 3.0.0.rc
|
80
36
|
type: :runtime
|
81
|
-
version_requirements: *
|
37
|
+
version_requirements: *id001
|
82
38
|
- !ruby/object:Gem::Dependency
|
83
39
|
name: nokogiri
|
84
40
|
prerelease: false
|
85
|
-
requirement: &
|
41
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
86
42
|
none: false
|
87
43
|
requirements:
|
88
44
|
- - ">="
|
@@ -92,11 +48,11 @@ dependencies:
|
|
92
48
|
- 0
|
93
49
|
version: "0"
|
94
50
|
type: :runtime
|
95
|
-
version_requirements: *
|
51
|
+
version_requirements: *id002
|
96
52
|
- !ruby/object:Gem::Dependency
|
97
53
|
name: vidibus-routing_error
|
98
54
|
prerelease: false
|
99
|
-
requirement: &
|
55
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
100
56
|
none: false
|
101
57
|
requirements:
|
102
58
|
- - ">="
|
@@ -106,7 +62,7 @@ dependencies:
|
|
106
62
|
- 0
|
107
63
|
version: "0"
|
108
64
|
type: :runtime
|
109
|
-
version_requirements: *
|
65
|
+
version_requirements: *id003
|
110
66
|
description: Drop-in XSS support for remote applications.
|
111
67
|
email: andre@vidibus.com
|
112
68
|
executables: []
|
@@ -116,7 +72,11 @@ extensions: []
|
|
116
72
|
extra_rdoc_files:
|
117
73
|
- README.rdoc
|
118
74
|
files:
|
75
|
+
- .bundle/config
|
119
76
|
- .gitignore
|
77
|
+
- .rspec
|
78
|
+
- Gemfile
|
79
|
+
- Gemfile.lock
|
120
80
|
- MIT-LICENSE
|
121
81
|
- README.rdoc
|
122
82
|
- Rakefile
|
@@ -132,8 +92,8 @@ files:
|
|
132
92
|
- lib/vidibus/xss/mime_type.rb
|
133
93
|
- public/javascripts/jquery.ba-bbq.js
|
134
94
|
- public/javascripts/vidibus.js
|
95
|
+
- public/javascripts/vidibus.loader.js
|
135
96
|
- public/javascripts/vidibus.xss.js
|
136
|
-
- spec/spec.opts
|
137
97
|
- spec/spec_helper.rb
|
138
98
|
- vidibus-xss.gemspec
|
139
99
|
has_rdoc: true
|
data/spec/spec.opts
DELETED