vidibus-xss 0.1.14 → 0.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/VERSION +1 -1
- data/lib/vidibus/xss/extensions/controller.rb +24 -13
- data/public/javascripts/vidibus.js +51 -0
- data/public/javascripts/vidibus.loader.js +75 -70
- data/public/javascripts/vidibus.xss.js +87 -105
- data/vidibus-xss.gemspec +52 -27
- metadata +147 -16
- data/.gitignore +0 -21
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.1.
|
|
1
|
+
0.1.15
|
|
@@ -8,7 +8,7 @@ module Vidibus
|
|
|
8
8
|
extend ActiveSupport::Concern
|
|
9
9
|
|
|
10
10
|
included do
|
|
11
|
-
helper_method :url_for, :xss_request?, :fullpath_url
|
|
11
|
+
helper_method :url_for, :xss_request?, :fullpath_url, :render_xss_string, :extract_xss
|
|
12
12
|
respond_to :html, :xss
|
|
13
13
|
rescue_from ActionController::RoutingError, :with => :rescue_404
|
|
14
14
|
end
|
|
@@ -140,13 +140,13 @@ module Vidibus
|
|
|
140
140
|
resources
|
|
141
141
|
end
|
|
142
142
|
|
|
143
|
-
#
|
|
143
|
+
# Extracts XSS hash of resources and content from given content string.
|
|
144
144
|
# If html content is given, the method tries to extract title,
|
|
145
145
|
# stylesheets and javascripts from head and content from body.
|
|
146
146
|
# TODO: Allow script blocks! Add them to body?
|
|
147
147
|
# TODO: Allow style blocks?
|
|
148
148
|
# TODO: Check for html content
|
|
149
|
-
def
|
|
149
|
+
def extract_xss(content)
|
|
150
150
|
dom = Nokogiri::HTML(content)
|
|
151
151
|
{
|
|
152
152
|
:resources => extract_xss_javascripts(dom) + extract_xss_stylesheets(dom),
|
|
@@ -183,9 +183,18 @@ module Vidibus
|
|
|
183
183
|
render_xss(:callback => data)
|
|
184
184
|
end
|
|
185
185
|
|
|
186
|
+
# Controller method for rendering xss content.
|
|
187
|
+
def render_xss(options = {})
|
|
188
|
+
xss = render_xss_string(options)
|
|
189
|
+
xss_access_control_headers
|
|
190
|
+
self.content_type = Mime::XSS
|
|
191
|
+
self.status = 200 # force success status
|
|
192
|
+
self.response_body = xss
|
|
193
|
+
end
|
|
194
|
+
|
|
186
195
|
# Main method for rendering XSS.
|
|
187
196
|
# Renders given XSS resources and content to string and sets it as response_body.
|
|
188
|
-
def
|
|
197
|
+
def render_xss_string(options = {})
|
|
189
198
|
resources = options.delete(:resources)
|
|
190
199
|
content = options.delete(:content)
|
|
191
200
|
path = options.delete(:get)
|
|
@@ -210,7 +219,7 @@ module Vidibus
|
|
|
210
219
|
|
|
211
220
|
# render load invocations of XSS resources
|
|
212
221
|
if resources and resources.any?
|
|
213
|
-
xss << %(
|
|
222
|
+
xss << %(xssLoader.load(#{resources.to_json},'#{params[:scope]}');)
|
|
214
223
|
defer = true
|
|
215
224
|
end
|
|
216
225
|
|
|
@@ -232,13 +241,9 @@ module Vidibus
|
|
|
232
241
|
# wait until resources have been loaded, before rendering XSS content
|
|
233
242
|
if defer
|
|
234
243
|
function_name = "rx#{xss_random_string}"
|
|
235
|
-
xss_content = %(var #{function_name}=function(){if(
|
|
244
|
+
xss_content = %(var #{function_name}=function(){if(xssLoader.complete){#{xss_content}}else{window.setTimeout('#{function_name}()',100);}};#{function_name}();)
|
|
236
245
|
end
|
|
237
246
|
xss << xss_content
|
|
238
|
-
xss_access_control_headers
|
|
239
|
-
self.content_type = Mime::XSS
|
|
240
|
-
self.status = 200 # force success status
|
|
241
|
-
self.response_body = xss
|
|
242
247
|
end
|
|
243
248
|
|
|
244
249
|
# Generates random string for current cycle.
|
|
@@ -305,15 +310,21 @@ module Vidibus
|
|
|
305
310
|
|
|
306
311
|
# embed xss.get
|
|
307
312
|
if path = options[:path]
|
|
308
|
-
|
|
309
|
-
|
|
313
|
+
template = options[:template]
|
|
314
|
+
if template === false
|
|
315
|
+
xss = {}
|
|
316
|
+
else
|
|
317
|
+
template ||= "layouts/#{get_layout(:xss)}"
|
|
318
|
+
content = render_to_string(:template => template)
|
|
319
|
+
xss = extract_xss(content)
|
|
320
|
+
end
|
|
310
321
|
xss[:get] = "/#{path}"
|
|
311
322
|
xss.delete(:content) # Ensure that not content will be embedded!
|
|
312
323
|
|
|
313
324
|
# embed xss content
|
|
314
325
|
else
|
|
315
326
|
content = render_to_string(*args, &block)
|
|
316
|
-
xss =
|
|
327
|
+
xss = extract_xss(content)
|
|
317
328
|
end
|
|
318
329
|
|
|
319
330
|
render_xss(xss)
|
|
@@ -29,3 +29,54 @@ jQuery(function ($) {
|
|
|
29
29
|
vidibus.csrf.data[vidibus.csrf.param] = encodeURIComponent(vidibus.csrf.token);
|
|
30
30
|
}
|
|
31
31
|
});
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Implement ajax handler.
|
|
36
|
+
* This is the default handler provided in rails.js with some extensions.
|
|
37
|
+
*/
|
|
38
|
+
$(function($) {
|
|
39
|
+
$.fn.extend({
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Handles execution of remote calls firing overridable events along the way.
|
|
43
|
+
*/
|
|
44
|
+
callAjax: function(url, method, data) {
|
|
45
|
+
var el = this,
|
|
46
|
+
method = method || el.attr('method') || el.attr('data-method') || 'GET',
|
|
47
|
+
dataType = el.attr('data-type') || 'script';
|
|
48
|
+
if (!url) url = el.attr('action') || el.attr('href') || el.attr('data-url');
|
|
49
|
+
if (url === undefined) {
|
|
50
|
+
throw "No URL specified for remote call (action or href must be present).";
|
|
51
|
+
} else {
|
|
52
|
+
if (el.triggerAndReturn('ajax:before')) {
|
|
53
|
+
data = data || el.is('form') ? el.serializeArray() : {};
|
|
54
|
+
if (method == 'delete') {
|
|
55
|
+
data['_method'] = method;
|
|
56
|
+
method = 'POST';
|
|
57
|
+
}
|
|
58
|
+
$.extend(data, vidibus.csrf.data());
|
|
59
|
+
$.ajax({
|
|
60
|
+
url: url,
|
|
61
|
+
data: data,
|
|
62
|
+
dataType: dataType,
|
|
63
|
+
type: method.toUpperCase(),
|
|
64
|
+
beforeSend: function(xhr) {
|
|
65
|
+
el.trigger('ajax:loading', xhr);
|
|
66
|
+
},
|
|
67
|
+
success: function(data, status, xhr) {
|
|
68
|
+
el.trigger('ajax:success', [data, status, xhr]);
|
|
69
|
+
},
|
|
70
|
+
complete: function(xhr) {
|
|
71
|
+
el.trigger('ajax:complete', xhr);
|
|
72
|
+
},
|
|
73
|
+
error: function(xhr, status, error) {
|
|
74
|
+
el.trigger('ajax:failure', [xhr, status, error]);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
el.trigger('ajax:after');
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
});
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
// Basic loader for stylesheets and javascripts.
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
var xssLoader = {
|
|
3
|
+
|
|
4
4
|
complete: true, // indicates that loading has been finished
|
|
5
5
|
queue: [], // holds resources that are queued to load
|
|
6
6
|
loading: undefined, // holds resource that is currently being loaded
|
|
7
7
|
preloaded: undefined, // holds resources that are included in consumer base file
|
|
8
8
|
loaded: {}, // holds resources that are currently loaded
|
|
9
9
|
unused: {}, // holds resources that are loaded, but not required anymore
|
|
10
|
-
|
|
10
|
+
|
|
11
11
|
/**
|
|
12
12
|
* Load resources.
|
|
13
13
|
*/
|
|
@@ -19,98 +19,98 @@ vidibus.loader = {
|
|
|
19
19
|
$(resources).each(function() {
|
|
20
20
|
var resource = this,
|
|
21
21
|
src = resource.src,
|
|
22
|
-
name =
|
|
23
|
-
|
|
22
|
+
name = xssLoader.resourceName(src);
|
|
23
|
+
|
|
24
24
|
resource.name = name;
|
|
25
|
-
resource.scopes = {}
|
|
25
|
+
resource.scopes = {};
|
|
26
26
|
resource.scopes[scope] = true;
|
|
27
|
-
|
|
27
|
+
|
|
28
28
|
// remove current file, because it is used
|
|
29
|
-
delete
|
|
29
|
+
delete xssLoader.unused[name];
|
|
30
30
|
|
|
31
31
|
// skip files that have already been loaded
|
|
32
|
-
if (
|
|
33
|
-
|
|
32
|
+
if (xssLoader.loaded[name]) {
|
|
33
|
+
xssLoader.loaded[name].scopes[scope] = true; // add current scope
|
|
34
34
|
return; // continue
|
|
35
|
-
} else if (
|
|
35
|
+
} else if (xssLoader.preloaded[name]) {
|
|
36
36
|
return; // continue
|
|
37
37
|
}
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
|
|
39
|
+
xssLoader.loaded[name] = resource;
|
|
40
40
|
switch (resource.type) {
|
|
41
|
-
|
|
41
|
+
|
|
42
42
|
// load css file directly
|
|
43
43
|
case 'text/css':
|
|
44
|
-
var element = document.createElement("link");
|
|
45
|
-
element.rel = 'stylesheet';
|
|
46
|
-
element.href = src;
|
|
44
|
+
var element = document.createElement("link");
|
|
45
|
+
element.rel = 'stylesheet';
|
|
46
|
+
element.href = src;
|
|
47
47
|
element.media = resource.media || 'all';
|
|
48
48
|
element.type = 'text/css';
|
|
49
|
-
|
|
49
|
+
xssLoader.appendToHead(element);
|
|
50
50
|
break;
|
|
51
|
-
|
|
51
|
+
|
|
52
52
|
// push script file to loading queue
|
|
53
53
|
case 'text/javascript':
|
|
54
|
-
|
|
54
|
+
xssLoader.queue.push(resource);
|
|
55
55
|
break;
|
|
56
|
-
|
|
57
|
-
default: console.log('
|
|
56
|
+
|
|
57
|
+
default: console.log('xssLoader.load: unsupported resource type: '+resource.type);
|
|
58
58
|
}
|
|
59
59
|
});
|
|
60
|
-
|
|
60
|
+
|
|
61
61
|
this.loadQueue(true);
|
|
62
62
|
this.unloadUnused(scope);
|
|
63
63
|
},
|
|
64
|
-
|
|
64
|
+
|
|
65
65
|
/**
|
|
66
66
|
* Returns file name of resource.
|
|
67
67
|
*/
|
|
68
68
|
resourceName: function(url) {
|
|
69
69
|
return url.match(/\/([^\/\?]+)(\?.*)*$/)[1];
|
|
70
70
|
},
|
|
71
|
-
|
|
71
|
+
|
|
72
72
|
/**
|
|
73
73
|
* Returns list of static resources.
|
|
74
74
|
*/
|
|
75
75
|
initStaticResources: function() {
|
|
76
|
-
if (
|
|
77
|
-
|
|
76
|
+
if (xssLoader.preloaded === undefined) {
|
|
77
|
+
xssLoader.preloaded = {};
|
|
78
78
|
var $resource, src, name;
|
|
79
79
|
$('script[src],link[href]',$('head')).each(function() {
|
|
80
80
|
$resource = $(this);
|
|
81
81
|
src = $resource.attr('src') || $resource.attr('href');
|
|
82
|
-
name =
|
|
83
|
-
|
|
82
|
+
name = xssLoader.resourceName(src);
|
|
83
|
+
xssLoader.preloaded[name] = src;
|
|
84
84
|
});
|
|
85
85
|
}
|
|
86
86
|
},
|
|
87
|
-
|
|
87
|
+
|
|
88
88
|
/**
|
|
89
89
|
* Loads resources in queue.
|
|
90
90
|
*/
|
|
91
91
|
loadQueue: function(start) {
|
|
92
|
-
|
|
92
|
+
|
|
93
93
|
// Reduce queue if this method is called as callback.
|
|
94
|
-
if(start
|
|
95
|
-
|
|
94
|
+
if(start !== true) {
|
|
95
|
+
xssLoader.queue.shift();
|
|
96
96
|
}
|
|
97
|
-
|
|
98
|
-
var resource =
|
|
99
|
-
|
|
97
|
+
|
|
98
|
+
var resource = xssLoader.queue[0];
|
|
99
|
+
|
|
100
100
|
// return if file is currently loading
|
|
101
101
|
if (resource) {
|
|
102
|
-
if (resource
|
|
102
|
+
if (resource === xssLoader.loading) {
|
|
103
103
|
// console.log('CURRENTLY LOADING: '+resource.src);
|
|
104
104
|
return;
|
|
105
105
|
}
|
|
106
|
-
|
|
107
|
-
|
|
106
|
+
xssLoader.loading = resource;
|
|
107
|
+
xssLoader.loadScript(resource.src, xssLoader.loadQueue);
|
|
108
108
|
} else {
|
|
109
|
-
|
|
110
|
-
|
|
109
|
+
xssLoader.loading = undefined;
|
|
110
|
+
xssLoader.complete = true;
|
|
111
111
|
}
|
|
112
112
|
},
|
|
113
|
-
|
|
113
|
+
|
|
114
114
|
/**
|
|
115
115
|
* Loads script src.
|
|
116
116
|
*/
|
|
@@ -121,66 +121,71 @@ vidibus.loader = {
|
|
|
121
121
|
} else {
|
|
122
122
|
// IE
|
|
123
123
|
element.onreadystatechange = function() {
|
|
124
|
-
if (this.readyState
|
|
125
|
-
|
|
124
|
+
if (this.readyState === 'loaded') {
|
|
125
|
+
callback.call(this);
|
|
126
|
+
}
|
|
127
|
+
};
|
|
126
128
|
}
|
|
127
129
|
element.type = 'text/javascript';
|
|
128
130
|
element.src = src;
|
|
129
|
-
|
|
131
|
+
xssLoader.appendToHead(element);
|
|
130
132
|
element = null;
|
|
131
133
|
},
|
|
132
|
-
|
|
134
|
+
|
|
133
135
|
/**
|
|
134
136
|
* Detects unused resources and removes them.
|
|
135
137
|
*/
|
|
136
138
|
unloadUnused: function(scope) {
|
|
137
139
|
var name, resources = [];
|
|
138
|
-
for(name in
|
|
140
|
+
for(name in xssLoader.unused) {
|
|
141
|
+
if (xssLoader.unused.hasOwnProperty(name)) {
|
|
142
|
+
// Remove dependency for given scope.
|
|
143
|
+
if (xssLoader.unused[name].scopes[scope]) {
|
|
144
|
+
delete xssLoader.unused[name].scopes[scope];
|
|
145
|
+
}
|
|
139
146
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
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]);
|
|
147
|
+
// Unload resource if it has no dependencies left.
|
|
148
|
+
if ($.isEmptyObject(xssLoader.unused[name].scopes)) {
|
|
149
|
+
resources.push(xssLoader.unused[name]);
|
|
150
|
+
}
|
|
148
151
|
}
|
|
149
152
|
}
|
|
150
|
-
|
|
151
|
-
|
|
153
|
+
xssLoader.unload(resources);
|
|
154
|
+
xssLoader.unused = {};
|
|
152
155
|
},
|
|
153
|
-
|
|
156
|
+
|
|
154
157
|
/**
|
|
155
158
|
* Removes resources given in list.
|
|
156
159
|
*/
|
|
157
160
|
unload: function(resources) {
|
|
158
|
-
var src,
|
|
161
|
+
var src, resource;
|
|
159
162
|
$(resources).each(function() {
|
|
160
163
|
resource = this;
|
|
161
164
|
src = resource.src;
|
|
162
|
-
|
|
163
|
-
// console.log('REMOVE UNUSED RESOURCE: '+src);
|
|
164
|
-
|
|
165
165
|
switch (resource.type) {
|
|
166
|
-
case "text/css":
|
|
166
|
+
case "text/css":
|
|
167
167
|
$('link[href="'+src+'"]').remove();
|
|
168
168
|
break;
|
|
169
|
-
|
|
170
|
-
case "text/javascript":
|
|
169
|
+
|
|
170
|
+
case "text/javascript":
|
|
171
171
|
$('script[src="'+src+'"]').remove();
|
|
172
172
|
break;
|
|
173
|
-
|
|
174
|
-
default: console.log('
|
|
173
|
+
|
|
174
|
+
default: console.log('xssLoader.unload: unsupported resource type: '+resource.type);
|
|
175
175
|
}
|
|
176
|
-
delete
|
|
176
|
+
delete xssLoader.loaded[resource.name];
|
|
177
177
|
});
|
|
178
178
|
},
|
|
179
|
-
|
|
179
|
+
|
|
180
180
|
/**
|
|
181
181
|
* Appends given element to document head.
|
|
182
182
|
*/
|
|
183
183
|
appendToHead: function(element) {
|
|
184
|
-
|
|
184
|
+
$("head")[0].appendChild(element);
|
|
185
185
|
}
|
|
186
186
|
};
|
|
187
|
+
|
|
188
|
+
// Maintain compatibility
|
|
189
|
+
if (typeof vidibus !== "undefined") {
|
|
190
|
+
vidibus.loader = xssLoader;
|
|
191
|
+
}
|
|
@@ -18,9 +18,14 @@ vidibus.xss = {
|
|
|
18
18
|
initialized: {}, // holds true for every scope that has been initialized
|
|
19
19
|
fileExtension: 'xss', // use 'xss' as file extension
|
|
20
20
|
loadedUrls: {}, // store urls currently loaded in each scope
|
|
21
|
+
pathPrefix: '', // set a fixed prefix for all paths
|
|
22
|
+
|
|
23
|
+
ready: function() {
|
|
24
|
+
// TODO: implement real event handler
|
|
25
|
+
},
|
|
21
26
|
|
|
22
27
|
/**
|
|
23
|
-
* Detects scope of script block to be executed.
|
|
28
|
+
* Detects scope of script block to be executed.
|
|
24
29
|
* Must be called from embedding page.
|
|
25
30
|
*/
|
|
26
31
|
detectScope: function() {
|
|
@@ -30,50 +35,60 @@ vidibus.xss = {
|
|
|
30
35
|
$detector.remove();
|
|
31
36
|
return $scope;
|
|
32
37
|
},
|
|
33
|
-
|
|
38
|
+
|
|
34
39
|
/**
|
|
35
40
|
* Usage:
|
|
36
|
-
* vidibus.xss.embed('<div>Some HTML</div>', $('#scope'),
|
|
41
|
+
* vidibus.xss.embed('<div>Some HTML</div>', $('#scope') [, ".some element"]);
|
|
37
42
|
*/
|
|
38
|
-
embed: function(html, $scope,
|
|
43
|
+
embed: function(html, $scope, selector) {
|
|
39
44
|
html = this.transformPaths(html, $scope); // Transform local paths before embedding html into page!
|
|
40
|
-
|
|
45
|
+
if (selector) {
|
|
46
|
+
$(selector, $scope).html(html);
|
|
47
|
+
} else {
|
|
48
|
+
$scope.html(html);
|
|
49
|
+
}
|
|
41
50
|
this.setUrls($scope);
|
|
42
51
|
this.setActions($scope);
|
|
52
|
+
this.ready();
|
|
43
53
|
},
|
|
44
|
-
|
|
54
|
+
|
|
45
55
|
/**
|
|
46
56
|
* Calls given path for given scope. If a third parameter is set to true,
|
|
47
57
|
* the location will be loaded, even if it is currently loaded.
|
|
48
|
-
*
|
|
58
|
+
*
|
|
49
59
|
* Usage:
|
|
50
60
|
* vidibus.xss.get('path', $('#scope') [, true]);
|
|
51
|
-
*
|
|
61
|
+
*
|
|
52
62
|
* If no host is provided, host of scope will be used.
|
|
53
63
|
*/
|
|
54
64
|
get: function(path, $scope, reload) {
|
|
55
|
-
//
|
|
65
|
+
// escape query parts
|
|
56
66
|
path = path.replace("?", "%3F").replace("&", "%26").replace("=", "%3D");
|
|
57
67
|
|
|
68
|
+
// remove path prefix
|
|
69
|
+
if (typeof xssPathPrefix !== "undefined" && xssPathPrefix) {
|
|
70
|
+
path = path.replace(xssPathPrefix,'');
|
|
71
|
+
}
|
|
72
|
+
|
|
58
73
|
var scopeId = $scope[0].id,
|
|
59
74
|
params = scopeId+'='+this.getPath(path),
|
|
60
75
|
keepCurrentLocation = this.initialized[scopeId] ? 0 : 1,
|
|
61
76
|
location = $.param.fragment(String(document.location), params, keepCurrentLocation),
|
|
62
77
|
reloadScope = {};
|
|
63
|
-
|
|
78
|
+
|
|
64
79
|
this.initialized[scopeId] = true;
|
|
65
80
|
window.location.href = location; // write history
|
|
66
81
|
reloadScope[scopeId] = reload;
|
|
67
82
|
this.loadUrl(location, reloadScope);
|
|
68
83
|
},
|
|
69
|
-
|
|
84
|
+
|
|
70
85
|
/**
|
|
71
86
|
* Redirect to given path while forcing reloading.
|
|
72
87
|
*/
|
|
73
88
|
redirect: function(path, $scope) {
|
|
74
|
-
this.get(path, $scope, true)
|
|
89
|
+
this.get(path, $scope, true);
|
|
75
90
|
},
|
|
76
|
-
|
|
91
|
+
|
|
77
92
|
/**
|
|
78
93
|
* Handles callback action.
|
|
79
94
|
*
|
|
@@ -83,41 +98,41 @@ vidibus.xss = {
|
|
|
83
98
|
* Accepts actions depending on status:
|
|
84
99
|
* (redirect) to: Performs redirect to location.
|
|
85
100
|
*/
|
|
86
|
-
callback: function(data, $scope) {
|
|
87
|
-
if (data.status
|
|
101
|
+
callback: function(data, $scope) {
|
|
102
|
+
if (data.status === "redirect") {
|
|
88
103
|
this.redirect(data.to, $scope);
|
|
89
104
|
}
|
|
90
105
|
},
|
|
91
|
-
|
|
106
|
+
|
|
92
107
|
/**
|
|
93
108
|
* Sets host for given scope.
|
|
94
109
|
*/
|
|
95
110
|
setHost: function(host, $scope) {
|
|
96
111
|
$scope.attr('data-host', host);
|
|
97
112
|
},
|
|
98
|
-
|
|
113
|
+
|
|
99
114
|
/**
|
|
100
115
|
* Returns host for given scope.
|
|
101
116
|
*/
|
|
102
117
|
getHost: function($scope) {
|
|
103
118
|
return $scope.attr('data-host');
|
|
104
119
|
},
|
|
105
|
-
|
|
120
|
+
|
|
106
121
|
/**
|
|
107
122
|
* Turns given path into an absolute url.
|
|
108
123
|
*/
|
|
109
124
|
getUrl: function(path, host) {
|
|
110
|
-
if (path.match(/https?:\/\//)) { return path }
|
|
125
|
+
if (path.match(/https?:\/\//)) { return path; }
|
|
111
126
|
return host + path;
|
|
112
127
|
},
|
|
113
|
-
|
|
128
|
+
|
|
114
129
|
/**
|
|
115
130
|
* Returns relative path from url.
|
|
116
131
|
*/
|
|
117
132
|
getPath: function(url) {
|
|
118
|
-
return url.replace(/https?:\/\/[^\/]+/,'')
|
|
133
|
+
return url.replace(/https?:\/\/[^\/]+/,'');
|
|
119
134
|
},
|
|
120
|
-
|
|
135
|
+
|
|
121
136
|
/**
|
|
122
137
|
* Rewrites links to absolute urls.
|
|
123
138
|
*/
|
|
@@ -129,20 +144,20 @@ vidibus.xss = {
|
|
|
129
144
|
var href = $(this).attr('href');
|
|
130
145
|
$(this).attr('href', vidibus.xss.getUrl(href, host));
|
|
131
146
|
});
|
|
132
|
-
|
|
147
|
+
|
|
133
148
|
// Rewrite forms
|
|
134
149
|
$('form[action]', $scope).each(function(e) {
|
|
135
150
|
var action = $(this).attr('action');
|
|
136
151
|
$(this).attr('href', vidibus.xss.getUrl(action, host));
|
|
137
152
|
});
|
|
138
153
|
},
|
|
139
|
-
|
|
154
|
+
|
|
140
155
|
/**
|
|
141
156
|
* Set xss actions for interactive elements.
|
|
142
157
|
*/
|
|
143
158
|
setActions: function($scope) {
|
|
144
159
|
var host = this.getHost($scope);
|
|
145
|
-
|
|
160
|
+
|
|
146
161
|
// Set action for GET links
|
|
147
162
|
// TODO: Allow links to be flagged as "external"
|
|
148
163
|
$('a[href^='+host+']:not([data-method],[data-remote])', $scope).bind('click.xss', function(e) {
|
|
@@ -150,7 +165,7 @@ vidibus.xss = {
|
|
|
150
165
|
vidibus.xss.get(href, $scope);
|
|
151
166
|
e.preventDefault();
|
|
152
167
|
});
|
|
153
|
-
|
|
168
|
+
|
|
154
169
|
// Set action non-GET links
|
|
155
170
|
// TODO: Remove bindings from links that match current host only: a[data-method][href^='+host+']:not([data-remote])
|
|
156
171
|
$('a[data-method]:not([data-remote])').die('click').unbind('click'); // remove bindings
|
|
@@ -161,9 +176,9 @@ vidibus.xss = {
|
|
|
161
176
|
$(this).callAjax(url);
|
|
162
177
|
e.preventDefault();
|
|
163
178
|
});
|
|
164
|
-
|
|
179
|
+
|
|
165
180
|
// Set form action
|
|
166
|
-
$('form[action]').die('submit').unbind('submit') // remove bindings
|
|
181
|
+
$('form[action]').die('submit').unbind('submit'); // remove bindings
|
|
167
182
|
$('form[action][href^='+host+']', $scope).submit(function(e) {
|
|
168
183
|
var $form = $(this),
|
|
169
184
|
path = $form.attr('action');
|
|
@@ -172,7 +187,7 @@ vidibus.xss = {
|
|
|
172
187
|
return false;
|
|
173
188
|
});
|
|
174
189
|
},
|
|
175
|
-
|
|
190
|
+
|
|
176
191
|
/**
|
|
177
192
|
* Modifies paths within given html string.
|
|
178
193
|
* This method must be called before embedding html snippet into the page
|
|
@@ -180,13 +195,17 @@ vidibus.xss = {
|
|
|
180
195
|
*/
|
|
181
196
|
transformPaths: function(html, $scope) {
|
|
182
197
|
var match, url;
|
|
183
|
-
while (
|
|
198
|
+
while (true) {
|
|
199
|
+
match = html.match(/src="((?!http)[^"]+)"/);
|
|
200
|
+
if (!match) {
|
|
201
|
+
break;
|
|
202
|
+
}
|
|
184
203
|
url = vidibus.xss.buildUrl(match[1], $scope);
|
|
185
|
-
html = html.replace(match[0], 'src="'+url+'"')
|
|
204
|
+
html = html.replace(match[0], 'src="'+url+'"');
|
|
186
205
|
}
|
|
187
206
|
return html;
|
|
188
207
|
},
|
|
189
|
-
|
|
208
|
+
|
|
190
209
|
/**
|
|
191
210
|
* Load XSS sources from given url.
|
|
192
211
|
* If url is empty, the current location will be used.
|
|
@@ -194,24 +213,26 @@ vidibus.xss = {
|
|
|
194
213
|
loadUrl: function(url, reload) {
|
|
195
214
|
var scope, $scope, path, loaded, params = $.deparam.fragment();
|
|
196
215
|
for(scope in params) {
|
|
197
|
-
|
|
216
|
+
if (params.hasOwnProperty(scope)) {
|
|
217
|
+
path = params[scope];
|
|
198
218
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
219
|
+
// don't reload locations that have already been loaded
|
|
220
|
+
loaded = this.loadedUrls[scope];
|
|
221
|
+
if((!reload || !reload[scope]) && loaded && loaded === path) {
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
204
224
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
225
|
+
$scope = $('#'+scope);
|
|
226
|
+
if($scope[0] === undefined) {
|
|
227
|
+
console.log('Scope not found: '+scope);
|
|
228
|
+
} else {
|
|
229
|
+
this.loadedUrls[scope] = path;
|
|
230
|
+
this.loadData(path, $scope);
|
|
231
|
+
}
|
|
211
232
|
}
|
|
212
233
|
}
|
|
213
234
|
},
|
|
214
|
-
|
|
235
|
+
|
|
215
236
|
/**
|
|
216
237
|
* Load relative path into given scope.
|
|
217
238
|
* Transforms scope host and path into a XSS location.
|
|
@@ -225,7 +246,7 @@ vidibus.xss = {
|
|
|
225
246
|
type: 'GET'
|
|
226
247
|
});
|
|
227
248
|
},
|
|
228
|
-
|
|
249
|
+
|
|
229
250
|
/**
|
|
230
251
|
* Tranforms local paths to absolute ones.
|
|
231
252
|
*/
|
|
@@ -236,27 +257,32 @@ vidibus.xss = {
|
|
|
236
257
|
if(params) {
|
|
237
258
|
params = params.split("&");
|
|
238
259
|
} else {
|
|
239
|
-
params = []
|
|
260
|
+
params = [];
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// prepend path prefix
|
|
264
|
+
if (typeof xssPathPrefix !== "undefined" && xssPathPrefix && !path.match(xssPathPrefix)) {
|
|
265
|
+
path = xssPathPrefix + path;
|
|
240
266
|
}
|
|
241
267
|
|
|
242
268
|
var host = this.getHost($scope),
|
|
243
269
|
scope = $scope.attr('id'),
|
|
244
|
-
url = this.getUrl(path, host)
|
|
270
|
+
url = this.getUrl(path, host);
|
|
245
271
|
|
|
246
|
-
if (!url.match(/\.[a-z]+((\?|\#).*)?$/)) url += '.xss';
|
|
247
|
-
if (url.indexOf('.xss') > -1 && params.toString().indexOf('scope='+scope)
|
|
272
|
+
if (!url.match(/\.[a-z]+((\?|\#).*)?$/)) { url += '.xss'; }
|
|
273
|
+
if (url.indexOf('.xss') > -1 && params.toString().indexOf('scope='+scope) === -1) {
|
|
248
274
|
params.push('scope='+scope);
|
|
249
275
|
}
|
|
250
|
-
|
|
276
|
+
|
|
251
277
|
// add cache buster
|
|
252
278
|
if (uncached) {
|
|
253
279
|
var d = new Date();
|
|
254
280
|
params.push(d.getTime());
|
|
255
281
|
}
|
|
256
|
-
|
|
282
|
+
|
|
257
283
|
// append params
|
|
258
284
|
if (params.length) {
|
|
259
|
-
if (url.indexOf('?')
|
|
285
|
+
if (url.indexOf('?') === -1) { url += '?'; }
|
|
260
286
|
url += params.join('&');
|
|
261
287
|
}
|
|
262
288
|
|
|
@@ -266,13 +292,13 @@ vidibus.xss = {
|
|
|
266
292
|
|
|
267
293
|
/**
|
|
268
294
|
* Detect changes to document's location.
|
|
269
|
-
*
|
|
295
|
+
*
|
|
270
296
|
*/
|
|
271
297
|
$(function($){
|
|
272
|
-
|
|
298
|
+
|
|
273
299
|
// Detect changes of document.location and trigger loading.
|
|
274
300
|
$(window).bind('hashchange', function(e) {
|
|
275
|
-
if (
|
|
301
|
+
if (xssLoader.complete) {
|
|
276
302
|
vidibus.xss.loadUrl();
|
|
277
303
|
}
|
|
278
304
|
return false;
|
|
@@ -285,54 +311,10 @@ $(function($){
|
|
|
285
311
|
});
|
|
286
312
|
|
|
287
313
|
/**
|
|
288
|
-
*
|
|
289
|
-
* This is the default handler provided in rails.js extended to accept delete method.
|
|
314
|
+
* Extend XHR
|
|
290
315
|
*/
|
|
291
316
|
$(function($) {
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
/**
|
|
295
|
-
* Handles execution of remote calls firing overridable events along the way.
|
|
296
|
-
*/
|
|
297
|
-
callAjax: function(url) {
|
|
298
|
-
var el = this,
|
|
299
|
-
method = el.attr('method') || el.attr('data-method') || 'GET',
|
|
300
|
-
dataType = el.attr('data-type') || 'script';
|
|
301
|
-
if (!url) url = el.attr('action') || el.attr('href');
|
|
302
|
-
if (url === undefined) {
|
|
303
|
-
throw "No URL specified for remote call (action or href must be present).";
|
|
304
|
-
} else {
|
|
305
|
-
if (el.triggerAndReturn('ajax:before')) {
|
|
306
|
-
var data = el.is('form') ? el.serializeArray() : {};
|
|
307
|
-
if (method == 'delete') {
|
|
308
|
-
data['_method'] = method;
|
|
309
|
-
method = 'POST';
|
|
310
|
-
}
|
|
311
|
-
$.extend(data, vidibus.csrf.data());
|
|
312
|
-
$.ajax({
|
|
313
|
-
url: url,
|
|
314
|
-
data: data,
|
|
315
|
-
dataType: dataType,
|
|
316
|
-
type: method.toUpperCase(),
|
|
317
|
-
beforeSend: function(xhr) {
|
|
318
|
-
el.trigger('ajax:loading', xhr);
|
|
319
|
-
},
|
|
320
|
-
success: function(data, status, xhr) {
|
|
321
|
-
el.trigger('ajax:success', [data, status, xhr]);
|
|
322
|
-
},
|
|
323
|
-
complete: function(xhr) {
|
|
324
|
-
el.trigger('ajax:complete', xhr);
|
|
325
|
-
},
|
|
326
|
-
error: function(xhr, status, error) {
|
|
327
|
-
el.trigger('ajax:failure', [xhr, status, error]);
|
|
328
|
-
}
|
|
329
|
-
});
|
|
330
|
-
}
|
|
331
|
-
el.trigger('ajax:after');
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
});
|
|
335
|
-
|
|
317
|
+
|
|
336
318
|
/**
|
|
337
319
|
* Extend xhr object to send credentials and force XMLHttpRequest.
|
|
338
320
|
*/
|
|
@@ -341,17 +323,17 @@ $(function($) {
|
|
|
341
323
|
try {
|
|
342
324
|
xhr.withCredentials = "true";
|
|
343
325
|
} catch(e) {
|
|
344
|
-
alert('Cannot set xhr with credentials:\n'+e)
|
|
326
|
+
alert('Cannot set xhr with credentials:\n'+e);
|
|
345
327
|
}
|
|
346
328
|
};
|
|
347
|
-
|
|
329
|
+
|
|
348
330
|
/**
|
|
349
331
|
* Extends xhr on beforeSend by binding to Rails' ajax:loading event.
|
|
350
332
|
*/
|
|
351
333
|
$("body").bind('ajax:loading', function(e, xhr) {
|
|
352
334
|
extendXhr(xhr);
|
|
353
335
|
});
|
|
354
|
-
|
|
336
|
+
|
|
355
337
|
/**
|
|
356
338
|
* Try to send xhr request withCredentials.
|
|
357
339
|
* Unfortunately, this has to be set after the connection has been opened.
|
data/vidibus-xss.gemspec
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
# Generated by jeweler
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run
|
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
|
4
4
|
# -*- encoding: utf-8 -*-
|
|
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.15"
|
|
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{
|
|
12
|
+
s.date = %q{2011-01-11}
|
|
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 = [
|
|
@@ -17,32 +17,30 @@ Gem::Specification.new do |s|
|
|
|
17
17
|
]
|
|
18
18
|
s.files = [
|
|
19
19
|
".bundle/config",
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
"vidibus-xss.gemspec"
|
|
20
|
+
".rspec",
|
|
21
|
+
"Gemfile",
|
|
22
|
+
"Gemfile.lock",
|
|
23
|
+
"MIT-LICENSE",
|
|
24
|
+
"README.rdoc",
|
|
25
|
+
"Rakefile",
|
|
26
|
+
"VERSION",
|
|
27
|
+
"app/controllers/xss_controller.rb",
|
|
28
|
+
"config/routes.rb",
|
|
29
|
+
"lib/vidibus-xss.rb",
|
|
30
|
+
"lib/vidibus/xss.rb",
|
|
31
|
+
"lib/vidibus/xss/extensions.rb",
|
|
32
|
+
"lib/vidibus/xss/extensions/controller.rb",
|
|
33
|
+
"lib/vidibus/xss/extensions/string.rb",
|
|
34
|
+
"lib/vidibus/xss/extensions/view.rb",
|
|
35
|
+
"lib/vidibus/xss/mime_type.rb",
|
|
36
|
+
"public/javascripts/jquery.ba-bbq.js",
|
|
37
|
+
"public/javascripts/vidibus.js",
|
|
38
|
+
"public/javascripts/vidibus.loader.js",
|
|
39
|
+
"public/javascripts/vidibus.xss.js",
|
|
40
|
+
"spec/spec_helper.rb",
|
|
41
|
+
"vidibus-xss.gemspec"
|
|
43
42
|
]
|
|
44
43
|
s.homepage = %q{http://github.com/vidibus/vidibus-xss}
|
|
45
|
-
s.rdoc_options = ["--charset=UTF-8"]
|
|
46
44
|
s.require_paths = ["lib"]
|
|
47
45
|
s.rubygems_version = %q{1.3.7}
|
|
48
46
|
s.summary = %q{Drop-in XSS support for remote applications.}
|
|
@@ -58,15 +56,42 @@ Gem::Specification.new do |s|
|
|
|
58
56
|
s.add_runtime_dependency(%q<rails>, ["~> 3.0.0"])
|
|
59
57
|
s.add_runtime_dependency(%q<nokogiri>, [">= 0"])
|
|
60
58
|
s.add_runtime_dependency(%q<vidibus-routing_error>, [">= 0"])
|
|
59
|
+
s.add_runtime_dependency(%q<vidibus-uuid>, [">= 0"])
|
|
60
|
+
s.add_runtime_dependency(%q<jeweler>, [">= 0"])
|
|
61
|
+
s.add_runtime_dependency(%q<rake>, [">= 0"])
|
|
62
|
+
s.add_runtime_dependency(%q<rspec>, ["~> 2.0.0.beta.20"])
|
|
63
|
+
s.add_runtime_dependency(%q<rr>, [">= 0"])
|
|
64
|
+
s.add_runtime_dependency(%q<relevance-rcov>, [">= 0"])
|
|
65
|
+
s.add_runtime_dependency(%q<rails>, ["~> 3.0.0"])
|
|
66
|
+
s.add_runtime_dependency(%q<nokogiri>, [">= 0"])
|
|
67
|
+
s.add_runtime_dependency(%q<vidibus-routing_error>, [">= 0"])
|
|
61
68
|
else
|
|
62
69
|
s.add_dependency(%q<rails>, ["~> 3.0.0"])
|
|
63
70
|
s.add_dependency(%q<nokogiri>, [">= 0"])
|
|
64
71
|
s.add_dependency(%q<vidibus-routing_error>, [">= 0"])
|
|
72
|
+
s.add_dependency(%q<vidibus-uuid>, [">= 0"])
|
|
73
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
|
74
|
+
s.add_dependency(%q<rake>, [">= 0"])
|
|
75
|
+
s.add_dependency(%q<rspec>, ["~> 2.0.0.beta.20"])
|
|
76
|
+
s.add_dependency(%q<rr>, [">= 0"])
|
|
77
|
+
s.add_dependency(%q<relevance-rcov>, [">= 0"])
|
|
78
|
+
s.add_dependency(%q<rails>, ["~> 3.0.0"])
|
|
79
|
+
s.add_dependency(%q<nokogiri>, [">= 0"])
|
|
80
|
+
s.add_dependency(%q<vidibus-routing_error>, [">= 0"])
|
|
65
81
|
end
|
|
66
82
|
else
|
|
67
83
|
s.add_dependency(%q<rails>, ["~> 3.0.0"])
|
|
68
84
|
s.add_dependency(%q<nokogiri>, [">= 0"])
|
|
69
85
|
s.add_dependency(%q<vidibus-routing_error>, [">= 0"])
|
|
86
|
+
s.add_dependency(%q<vidibus-uuid>, [">= 0"])
|
|
87
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
|
88
|
+
s.add_dependency(%q<rake>, [">= 0"])
|
|
89
|
+
s.add_dependency(%q<rspec>, ["~> 2.0.0.beta.20"])
|
|
90
|
+
s.add_dependency(%q<rr>, [">= 0"])
|
|
91
|
+
s.add_dependency(%q<relevance-rcov>, [">= 0"])
|
|
92
|
+
s.add_dependency(%q<rails>, ["~> 3.0.0"])
|
|
93
|
+
s.add_dependency(%q<nokogiri>, [">= 0"])
|
|
94
|
+
s.add_dependency(%q<vidibus-routing_error>, [">= 0"])
|
|
70
95
|
end
|
|
71
96
|
end
|
|
72
97
|
|
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: 5
|
|
5
5
|
prerelease: false
|
|
6
6
|
segments:
|
|
7
7
|
- 0
|
|
8
8
|
- 1
|
|
9
|
-
-
|
|
10
|
-
version: 0.1.
|
|
9
|
+
- 15
|
|
10
|
+
version: 0.1.15
|
|
11
11
|
platform: ruby
|
|
12
12
|
authors:
|
|
13
13
|
- Andre Pankratz
|
|
@@ -15,13 +15,14 @@ autorequire:
|
|
|
15
15
|
bindir: bin
|
|
16
16
|
cert_chain: []
|
|
17
17
|
|
|
18
|
-
date:
|
|
18
|
+
date: 2011-01-11 00:00:00 +01:00
|
|
19
19
|
default_executable:
|
|
20
20
|
dependencies:
|
|
21
21
|
- !ruby/object:Gem::Dependency
|
|
22
|
-
|
|
22
|
+
type: :runtime
|
|
23
23
|
prerelease: false
|
|
24
|
-
|
|
24
|
+
name: rails
|
|
25
|
+
version_requirements: &id001 !ruby/object:Gem::Requirement
|
|
25
26
|
none: false
|
|
26
27
|
requirements:
|
|
27
28
|
- - ~>
|
|
@@ -32,12 +33,26 @@ dependencies:
|
|
|
32
33
|
- 0
|
|
33
34
|
- 0
|
|
34
35
|
version: 3.0.0
|
|
35
|
-
|
|
36
|
-
version_requirements: *id001
|
|
36
|
+
requirement: *id001
|
|
37
37
|
- !ruby/object:Gem::Dependency
|
|
38
|
+
type: :runtime
|
|
39
|
+
prerelease: false
|
|
38
40
|
name: nokogiri
|
|
41
|
+
version_requirements: &id002 !ruby/object:Gem::Requirement
|
|
42
|
+
none: false
|
|
43
|
+
requirements:
|
|
44
|
+
- - ">="
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
hash: 3
|
|
47
|
+
segments:
|
|
48
|
+
- 0
|
|
49
|
+
version: "0"
|
|
50
|
+
requirement: *id002
|
|
51
|
+
- !ruby/object:Gem::Dependency
|
|
52
|
+
type: :runtime
|
|
39
53
|
prerelease: false
|
|
40
|
-
|
|
54
|
+
name: vidibus-routing_error
|
|
55
|
+
version_requirements: &id003 !ruby/object:Gem::Requirement
|
|
41
56
|
none: false
|
|
42
57
|
requirements:
|
|
43
58
|
- - ">="
|
|
@@ -46,12 +61,86 @@ dependencies:
|
|
|
46
61
|
segments:
|
|
47
62
|
- 0
|
|
48
63
|
version: "0"
|
|
64
|
+
requirement: *id003
|
|
65
|
+
- !ruby/object:Gem::Dependency
|
|
49
66
|
type: :runtime
|
|
50
|
-
|
|
67
|
+
prerelease: false
|
|
68
|
+
name: vidibus-uuid
|
|
69
|
+
version_requirements: &id004 !ruby/object:Gem::Requirement
|
|
70
|
+
none: false
|
|
71
|
+
requirements:
|
|
72
|
+
- - ">="
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
hash: 3
|
|
75
|
+
segments:
|
|
76
|
+
- 0
|
|
77
|
+
version: "0"
|
|
78
|
+
requirement: *id004
|
|
51
79
|
- !ruby/object:Gem::Dependency
|
|
52
|
-
|
|
80
|
+
type: :runtime
|
|
81
|
+
prerelease: false
|
|
82
|
+
name: jeweler
|
|
83
|
+
version_requirements: &id005 !ruby/object:Gem::Requirement
|
|
84
|
+
none: false
|
|
85
|
+
requirements:
|
|
86
|
+
- - ">="
|
|
87
|
+
- !ruby/object:Gem::Version
|
|
88
|
+
hash: 3
|
|
89
|
+
segments:
|
|
90
|
+
- 0
|
|
91
|
+
version: "0"
|
|
92
|
+
requirement: *id005
|
|
93
|
+
- !ruby/object:Gem::Dependency
|
|
94
|
+
type: :runtime
|
|
95
|
+
prerelease: false
|
|
96
|
+
name: rake
|
|
97
|
+
version_requirements: &id006 !ruby/object:Gem::Requirement
|
|
98
|
+
none: false
|
|
99
|
+
requirements:
|
|
100
|
+
- - ">="
|
|
101
|
+
- !ruby/object:Gem::Version
|
|
102
|
+
hash: 3
|
|
103
|
+
segments:
|
|
104
|
+
- 0
|
|
105
|
+
version: "0"
|
|
106
|
+
requirement: *id006
|
|
107
|
+
- !ruby/object:Gem::Dependency
|
|
108
|
+
type: :runtime
|
|
109
|
+
prerelease: false
|
|
110
|
+
name: rspec
|
|
111
|
+
version_requirements: &id007 !ruby/object:Gem::Requirement
|
|
112
|
+
none: false
|
|
113
|
+
requirements:
|
|
114
|
+
- - ~>
|
|
115
|
+
- !ruby/object:Gem::Version
|
|
116
|
+
hash: 62196427
|
|
117
|
+
segments:
|
|
118
|
+
- 2
|
|
119
|
+
- 0
|
|
120
|
+
- 0
|
|
121
|
+
- beta
|
|
122
|
+
- 20
|
|
123
|
+
version: 2.0.0.beta.20
|
|
124
|
+
requirement: *id007
|
|
125
|
+
- !ruby/object:Gem::Dependency
|
|
126
|
+
type: :runtime
|
|
127
|
+
prerelease: false
|
|
128
|
+
name: rr
|
|
129
|
+
version_requirements: &id008 !ruby/object:Gem::Requirement
|
|
130
|
+
none: false
|
|
131
|
+
requirements:
|
|
132
|
+
- - ">="
|
|
133
|
+
- !ruby/object:Gem::Version
|
|
134
|
+
hash: 3
|
|
135
|
+
segments:
|
|
136
|
+
- 0
|
|
137
|
+
version: "0"
|
|
138
|
+
requirement: *id008
|
|
139
|
+
- !ruby/object:Gem::Dependency
|
|
140
|
+
type: :runtime
|
|
53
141
|
prerelease: false
|
|
54
|
-
|
|
142
|
+
name: relevance-rcov
|
|
143
|
+
version_requirements: &id009 !ruby/object:Gem::Requirement
|
|
55
144
|
none: false
|
|
56
145
|
requirements:
|
|
57
146
|
- - ">="
|
|
@@ -60,8 +149,51 @@ dependencies:
|
|
|
60
149
|
segments:
|
|
61
150
|
- 0
|
|
62
151
|
version: "0"
|
|
152
|
+
requirement: *id009
|
|
153
|
+
- !ruby/object:Gem::Dependency
|
|
63
154
|
type: :runtime
|
|
64
|
-
|
|
155
|
+
prerelease: false
|
|
156
|
+
name: rails
|
|
157
|
+
version_requirements: &id010 !ruby/object:Gem::Requirement
|
|
158
|
+
none: false
|
|
159
|
+
requirements:
|
|
160
|
+
- - ~>
|
|
161
|
+
- !ruby/object:Gem::Version
|
|
162
|
+
hash: 7
|
|
163
|
+
segments:
|
|
164
|
+
- 3
|
|
165
|
+
- 0
|
|
166
|
+
- 0
|
|
167
|
+
version: 3.0.0
|
|
168
|
+
requirement: *id010
|
|
169
|
+
- !ruby/object:Gem::Dependency
|
|
170
|
+
type: :runtime
|
|
171
|
+
prerelease: false
|
|
172
|
+
name: nokogiri
|
|
173
|
+
version_requirements: &id011 !ruby/object:Gem::Requirement
|
|
174
|
+
none: false
|
|
175
|
+
requirements:
|
|
176
|
+
- - ">="
|
|
177
|
+
- !ruby/object:Gem::Version
|
|
178
|
+
hash: 3
|
|
179
|
+
segments:
|
|
180
|
+
- 0
|
|
181
|
+
version: "0"
|
|
182
|
+
requirement: *id011
|
|
183
|
+
- !ruby/object:Gem::Dependency
|
|
184
|
+
type: :runtime
|
|
185
|
+
prerelease: false
|
|
186
|
+
name: vidibus-routing_error
|
|
187
|
+
version_requirements: &id012 !ruby/object:Gem::Requirement
|
|
188
|
+
none: false
|
|
189
|
+
requirements:
|
|
190
|
+
- - ">="
|
|
191
|
+
- !ruby/object:Gem::Version
|
|
192
|
+
hash: 3
|
|
193
|
+
segments:
|
|
194
|
+
- 0
|
|
195
|
+
version: "0"
|
|
196
|
+
requirement: *id012
|
|
65
197
|
description: Drop-in XSS support for remote applications.
|
|
66
198
|
email: andre@vidibus.com
|
|
67
199
|
executables: []
|
|
@@ -72,7 +204,6 @@ extra_rdoc_files:
|
|
|
72
204
|
- README.rdoc
|
|
73
205
|
files:
|
|
74
206
|
- .bundle/config
|
|
75
|
-
- .gitignore
|
|
76
207
|
- .rspec
|
|
77
208
|
- Gemfile
|
|
78
209
|
- Gemfile.lock
|
|
@@ -100,8 +231,8 @@ homepage: http://github.com/vidibus/vidibus-xss
|
|
|
100
231
|
licenses: []
|
|
101
232
|
|
|
102
233
|
post_install_message:
|
|
103
|
-
rdoc_options:
|
|
104
|
-
|
|
234
|
+
rdoc_options: []
|
|
235
|
+
|
|
105
236
|
require_paths:
|
|
106
237
|
- lib
|
|
107
238
|
required_ruby_version: !ruby/object:Gem::Requirement
|