wunderbar 1.3.4 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -21
- data/lib/wunderbar/asset.rb +5 -5
- data/lib/wunderbar/builder.rb +2 -2
- data/lib/wunderbar/cgi-methods.rb +1 -1
- data/lib/wunderbar/coderay.rb +0 -9
- data/lib/wunderbar/environment.rb +0 -34
- data/lib/wunderbar/html-methods.rb +5 -16
- data/lib/wunderbar/job-control.rb +1 -1
- data/lib/wunderbar/rack.rb +0 -2
- data/lib/wunderbar/react.rb +0 -14
- data/lib/wunderbar/render.rb +5 -7
- data/lib/wunderbar/sinatra.rb +6 -15
- data/lib/wunderbar/version.rb +2 -2
- data/lib/wunderbar/vue.rb +2 -2
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 01faf4f44e9f567cf1ab080f8f4a54879c0eb6b5d07e0ad6d265ede2cbd4b86f
|
4
|
+
data.tar.gz: a0db8a63944a68305a337a1eb5cef8114f5f88034e7a9c451cd37228ad97bc40
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d104318bd2e0e2ee9cd721c3b49790ede15b4459dbe253bc58b9108b6fc91fcb077e932a399b9194417a5dc31c62500684db424db534b4b72c1c709e2defedc1
|
7
|
+
data.tar.gz: e2d9ca6b2bec1fdb12a253e1ca9df2f73296388c60ee2b165c63305216a353fc0fe37e3ede10c48b6524b7391e060230ca53fa8f393b4d24b957f225da3363a2
|
data/README.md
CHANGED
@@ -366,26 +366,7 @@ Secure by default
|
|
366
366
|
|
367
367
|
Wunderbar will properly escape all HTML and JSON output, eliminating problems
|
368
368
|
of HTML or JavaScript injection. This includes calls to `_` to insert text
|
369
|
-
directly.
|
370
|
-
dependencies](#optional-dependencies) below), calls to insert markup
|
371
|
-
(`_{...}`) will escape the markup if the input is `tainted` and not explicitly
|
372
|
-
marked as `html-safe?` (when using Rails).
|
373
|
-
|
374
|
-
For Ruby version < 2.6.0:
|
375
|
-
|
376
|
-
> For all environments other than Rails, unless you call `Wunderbar.unsafe!` at
|
377
|
-
> the top of your script, Wunderbar will also set
|
378
|
-
> [`$SAFE=1`](http://www.ruby-doc.org/docs/ProgrammingRuby/html/taint.html)
|
379
|
-
> before processing requests. This means that you will need to
|
380
|
-
> [`untaint`](ruby-doc.org/core/Object.html#method-i-untaint) all inputs
|
381
|
-
> received from external sources before you make system calls or access the file
|
382
|
-
> system.
|
383
|
-
|
384
|
-
A special feature that effectively is only available in the Rails environment:
|
385
|
-
if the first argument to call that creates an element is `html_safe?`, then
|
386
|
-
that argument will be treated as a markup instead of as text. This allows one
|
387
|
-
to make calls like `_td link_to...` without placing the call to `link_to` in a
|
388
|
-
block.
|
369
|
+
directly.
|
389
370
|
|
390
371
|
Globals provided
|
391
372
|
---
|
@@ -454,7 +435,6 @@ The following gems, if installed, will produce cleaner and prettier output:
|
|
454
435
|
* `nokogumbo` also cleans up HTML fragments inserted via `<<` and `_{}`. If
|
455
436
|
this gem is available, it will be preferred over direct usage of `nokogiri`.
|
456
437
|
* `escape` prettier quoting of `system` commands
|
457
|
-
* `sanitize` will remove unsafe markup from tainted input
|
458
438
|
|
459
439
|
Related efforts
|
460
440
|
---
|
data/lib/wunderbar/asset.rb
CHANGED
@@ -30,14 +30,14 @@ module Wunderbar
|
|
30
30
|
return @path if @path or @contents
|
31
31
|
|
32
32
|
if @options[:name]
|
33
|
-
source =
|
33
|
+
source = @options[:file] || __FILE__
|
34
34
|
@mtime = File.mtime(source)
|
35
35
|
@path = @options[:name]
|
36
36
|
|
37
37
|
# look for asset in site
|
38
38
|
if ENV['DOCUMENT_ROOT']
|
39
|
-
root = File.join(ENV['DOCUMENT_ROOT'], 'assets')
|
40
|
-
dest = File.expand_path(@path, root)
|
39
|
+
root = File.join(ENV['DOCUMENT_ROOT'], 'assets')
|
40
|
+
dest = File.expand_path(@path, root)
|
41
41
|
if File.exist?(dest) and File.size(dest) == File.size(source)
|
42
42
|
@path = "/assets/#{@path}"
|
43
43
|
return @path
|
@@ -45,7 +45,7 @@ module Wunderbar
|
|
45
45
|
end
|
46
46
|
|
47
47
|
# look for asset in app
|
48
|
-
dest = File.expand_path(@path, Asset.root)
|
48
|
+
dest = File.expand_path(@path, Asset.root)
|
49
49
|
if File.exist?(dest) and File.size(dest) == File.size(source)
|
50
50
|
return @path
|
51
51
|
end
|
@@ -103,7 +103,7 @@ module Wunderbar
|
|
103
103
|
@path = '../' * env['PATH_INFO'].to_s.count('/') + 'assets'
|
104
104
|
@root ||= nil
|
105
105
|
@root = File.dirname(env['SCRIPT_FILENAME']) if env['SCRIPT_FILENAME']
|
106
|
-
@root = File.expand_path((@root || Dir.pwd) + "/assets")
|
106
|
+
@root = File.expand_path((@root || Dir.pwd) + "/assets")
|
107
107
|
|
108
108
|
# Options: typically :name plus either :file or :contents
|
109
109
|
# :name => name to be used for the asset
|
data/lib/wunderbar/builder.rb
CHANGED
@@ -51,14 +51,14 @@ module Wunderbar
|
|
51
51
|
secret = command - flat
|
52
52
|
begin
|
53
53
|
# if available, use escape as it does prettier quoting
|
54
|
-
raise LoadError if
|
54
|
+
raise LoadError if not defined? Escape
|
55
55
|
require 'escape'
|
56
56
|
echo = Escape.shell_command(command.compact - secret)
|
57
57
|
rescue LoadError
|
58
58
|
# std-lib function that gets the job done
|
59
59
|
echo = Shellwords.join(command.compact - secret)
|
60
60
|
end
|
61
|
-
command = flat.compact
|
61
|
+
command = flat.compact
|
62
62
|
else
|
63
63
|
echo = command
|
64
64
|
command = [command]
|
@@ -120,7 +120,7 @@ module Wunderbar
|
|
120
120
|
# asset support for Rack
|
121
121
|
request = (scope.respond_to? :request) ? scope.request : nil
|
122
122
|
if request and request.path =~ %r{/assets/\w[-.\w]+}
|
123
|
-
path =
|
123
|
+
path = '.' + scope.request.path
|
124
124
|
headers = {'type' => 'text/plain'}
|
125
125
|
headers['type'] = 'application/javascript' if path =~ /\.js$/
|
126
126
|
out?(scope, headers) { File.read path if File.exist? path }
|
data/lib/wunderbar/coderay.rb
CHANGED
@@ -2,15 +2,6 @@ require 'wunderbar'
|
|
2
2
|
require 'coderay'
|
3
3
|
require 'nokogiri'
|
4
4
|
|
5
|
-
# workaround for https://github.com/rubychan/coderay/pull/159
|
6
|
-
module CodeRay::PluginHost
|
7
|
-
alias_method :old_plugin_path, :plugin_path
|
8
|
-
def plugin_path *args
|
9
|
-
args.first.untaint if args.first == CodeRay::CODERAY_PATH
|
10
|
-
old_plugin_path(*args)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
5
|
module Wunderbar
|
15
6
|
class HtmlMarkup
|
16
7
|
def _coderay(*args)
|
@@ -5,40 +5,6 @@ module Wunderbar
|
|
5
5
|
TEXT = ARGV.delete('--text')
|
6
6
|
end
|
7
7
|
|
8
|
-
# Ruby 2.6.0 gets rid of $SAFE > 1; unfortunately in the process it
|
9
|
-
# treats $SAFE = 1 as a higher level; @FAFE = 1 no longer is limited
|
10
|
-
# to taintness checks, it not treats all File operations as unsafe
|
11
|
-
@@unsafe = (RUBY_VERSION.split('.').map(&:to_i) <=> [2, 6, 0]) == 1
|
12
|
-
|
13
|
-
def self.unsafe!(mode=true)
|
14
|
-
@@unsafe=mode
|
15
|
-
end
|
16
|
-
|
17
|
-
def self.safe?
|
18
|
-
if not @@unsafe and $SAFE == 0
|
19
|
-
# some gems (e.g. em-websocket-0.3.6) insert unsafe entries into the
|
20
|
-
# path, and that prevents requires from succeeding. If it looks like
|
21
|
-
# we are about to make a transition to $SAFE=1, clean up that mess
|
22
|
-
# before proceeding.
|
23
|
-
#
|
24
|
-
# the goal of $SAFE is not to protect us against software which was
|
25
|
-
# installed by the owner of the site, but from injection attacks
|
26
|
-
# contained within data provided by users of the site.
|
27
|
-
$:.each_with_index do |path, index|
|
28
|
-
if path.tainted?
|
29
|
-
$:[index] = File.expand_path(path.dup.untaint).untaint
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
# avoid: "Insecure PATH - (SecurityError)" when using Bundler
|
34
|
-
if defined? Bundler
|
35
|
-
ENV['PATH'] = ENV['PATH'].dup.untaint
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
not @@unsafe
|
40
|
-
end
|
41
|
-
|
42
8
|
class Scope
|
43
9
|
attr_accessor :env
|
44
10
|
def initialize(env)
|
@@ -133,7 +133,7 @@ module Wunderbar
|
|
133
133
|
# * Proxied Rack server. Document base may be relate to the
|
134
134
|
# HTTP_X_WUNDERBAR_BASE
|
135
135
|
#
|
136
|
-
cwd = File.realpath(Dir.pwd
|
136
|
+
cwd = File.realpath(Dir.pwd)
|
137
137
|
base = @_scope.env['DOCUMENT_ROOT'] if @_scope.env.respond_to? :[]
|
138
138
|
base ||= cwd
|
139
139
|
href = (head.children[1].attrs[:href] || '')
|
@@ -189,8 +189,8 @@ module Wunderbar
|
|
189
189
|
name = name.to_s.gsub('_', '-')
|
190
190
|
|
191
191
|
if flag != '!'
|
192
|
-
if String === args.first
|
193
|
-
if
|
192
|
+
if String === args.first
|
193
|
+
if not block and args.first =~ /[>&]/
|
194
194
|
markup = args.shift
|
195
195
|
block = Proc.new {_ {markup}}
|
196
196
|
end
|
@@ -362,11 +362,7 @@ module Wunderbar
|
|
362
362
|
def _(text=nil, &block)
|
363
363
|
unless block
|
364
364
|
if text
|
365
|
-
|
366
|
-
_ {text}
|
367
|
-
else
|
368
|
-
@_x.indented_text! text.to_s
|
369
|
-
end
|
365
|
+
_ {text}
|
370
366
|
end
|
371
367
|
return @_x
|
372
368
|
end
|
@@ -374,20 +370,13 @@ module Wunderbar
|
|
374
370
|
children = instance_eval(&block)
|
375
371
|
|
376
372
|
if String === children
|
377
|
-
|
378
|
-
safe ||= children.html_safe? if children.respond_to? :html_safe?
|
379
|
-
safe &&= defined? Nokogiri
|
380
|
-
ok = safe || defined? Sanitize
|
381
|
-
safe = true
|
382
|
-
|
383
|
-
if ok and (children.include? '<' or children.include? '&')
|
373
|
+
if children.include? '<' or children.include? '&'
|
384
374
|
if defined? Nokogiri::HTML5.fragment
|
385
375
|
doc = Nokogiri::HTML5.fragment(children.to_s)
|
386
376
|
else
|
387
377
|
doc = Nokogiri::HTML.fragment(children.to_s)
|
388
378
|
end
|
389
379
|
|
390
|
-
Sanitize.new.clean_node! doc.dup.untaint if not safe
|
391
380
|
children = doc.children.to_a
|
392
381
|
|
393
382
|
# ignore leading whitespace
|
@@ -25,7 +25,7 @@ module Wunderbar
|
|
25
25
|
# clear environment of cgi cruft
|
26
26
|
require 'cgi'
|
27
27
|
ENV.keys.select {|key| key =~ /^HTTP_/}.each do |key|
|
28
|
-
ENV.delete key
|
28
|
+
ENV.delete key
|
29
29
|
end
|
30
30
|
::CGI::QueryExtension.public_instance_methods.each do |method|
|
31
31
|
ENV.delete method.to_s.upcase
|
data/lib/wunderbar/rack.rb
CHANGED
@@ -17,8 +17,6 @@ module Wunderbar
|
|
17
17
|
Rack::Mime::MIME_TYPES[File.extname(env['PATH_INFO'])]
|
18
18
|
@_response.set_header('Content-Type', mime) if mime
|
19
19
|
@_response.write(file[:content] || file[:source].call)
|
20
|
-
elsif Wunderbar.safe? and $SAFE==0
|
21
|
-
Proc.new { $SAFE=1; Wunderbar::CGI.call(self) }.call
|
22
20
|
else
|
23
21
|
Wunderbar::CGI.call(self)
|
24
22
|
end
|
data/lib/wunderbar/react.rb
CHANGED
@@ -35,17 +35,3 @@ class Wunderbar::Render
|
|
35
35
|
"</pre>"
|
36
36
|
end
|
37
37
|
end
|
38
|
-
|
39
|
-
# Monkeypatch to address https://github.com/sstephenson/execjs/pull/180
|
40
|
-
require 'execjs'
|
41
|
-
class ExecJS::ExternalRuntime::Context
|
42
|
-
alias_method :w_write_to_tempfile, :write_to_tempfile
|
43
|
-
def write_to_tempfile(*args)
|
44
|
-
tmpfile = w_write_to_tempfile(*args).path.untaint
|
45
|
-
tmpfile = Struct.new(:path, :to_str).new(tmpfile, tmpfile)
|
46
|
-
def tmpfile.unlink
|
47
|
-
File.unlink path
|
48
|
-
end
|
49
|
-
tmpfile
|
50
|
-
end
|
51
|
-
end
|
data/lib/wunderbar/render.rb
CHANGED
@@ -82,14 +82,12 @@ class Wunderbar::XmlMarkup
|
|
82
82
|
|
83
83
|
src = File.join(base, src) if not base.empty?
|
84
84
|
src = src.sub(/\?.*$/, '') # strip queries (typically mtimes)
|
85
|
-
src.untaint
|
86
85
|
|
87
|
-
name = File.expand_path(src, @_scope.settings.public_folder
|
88
|
-
name.untaint unless src.tainted?
|
86
|
+
name = File.expand_path(src, @_scope.settings.public_folder)
|
89
87
|
if File.exist? name
|
90
88
|
result = File.read(name)
|
91
89
|
else
|
92
|
-
file = File.expand_path(src+'.rb', @_scope.settings.views
|
90
|
+
file = File.expand_path(src+'.rb', @_scope.settings.views)
|
93
91
|
result = Wunderbar::Asset.convert(file)
|
94
92
|
end
|
95
93
|
else
|
@@ -113,11 +111,11 @@ class Wunderbar::XmlMarkup
|
|
113
111
|
scripts.unshift script.contents
|
114
112
|
elsif script.path
|
115
113
|
if script.path.start_with? '/'
|
116
|
-
path =
|
114
|
+
path = ENV['DOCUMENT_ROOT'] + script.path
|
117
115
|
else
|
118
|
-
path = File.expand_path(script.path, Wunderbar::Asset.root)
|
116
|
+
path = File.expand_path(script.path, Wunderbar::Asset.root)
|
119
117
|
end
|
120
|
-
setup << File.read(script.options[:server]
|
118
|
+
setup << File.read(script.options[:server] || path)
|
121
119
|
end
|
122
120
|
end
|
123
121
|
|
data/lib/wunderbar/sinatra.rb
CHANGED
@@ -82,22 +82,14 @@ module Wunderbar
|
|
82
82
|
builder.set_variables_from_params(locals)
|
83
83
|
|
84
84
|
if not block
|
85
|
-
builder.instance_eval(data
|
85
|
+
builder.instance_eval(data, eval_file)
|
86
86
|
elsif not data
|
87
87
|
builder.instance_eval(&block)
|
88
88
|
else
|
89
89
|
context = builder.get_binding do
|
90
90
|
builder.instance_eval {_(&block)}
|
91
91
|
end
|
92
|
-
context.eval(data
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
def _evaluate_safely(*args, &block)
|
97
|
-
if Wunderbar.safe? and $SAFE==0
|
98
|
-
Proc.new { $SAFE=1; _evaluate(*args, &block) }.call
|
99
|
-
else
|
100
|
-
_evaluate(*args, &block)
|
92
|
+
context.eval(data, eval_file)
|
101
93
|
end
|
102
94
|
end
|
103
95
|
end
|
@@ -108,7 +100,7 @@ module Wunderbar
|
|
108
100
|
def evaluate(scope, locals, &block)
|
109
101
|
builder = HtmlMarkup.new(scope)
|
110
102
|
begin
|
111
|
-
|
103
|
+
_evaluate(builder, scope, locals, &block)
|
112
104
|
rescue Exception => exception
|
113
105
|
scope.response.status = Wunderbar::ServerError.status
|
114
106
|
builder.clear!
|
@@ -132,7 +124,7 @@ module Wunderbar
|
|
132
124
|
def evaluate(scope, locals, &block)
|
133
125
|
builder = JsonBuilder.new(scope)
|
134
126
|
begin
|
135
|
-
result =
|
127
|
+
result = _evaluate(builder, scope, locals, &block)
|
136
128
|
|
137
129
|
# if no output was produced, use the result
|
138
130
|
builder._! result if builder.target? == {} and result
|
@@ -154,7 +146,7 @@ module Wunderbar
|
|
154
146
|
def evaluate(scope, locals, &block)
|
155
147
|
builder = TextBuilder.new(scope)
|
156
148
|
begin
|
157
|
-
result =
|
149
|
+
result = _evaluate(builder, scope, locals, &block)
|
158
150
|
|
159
151
|
# if no output was produced, use the result
|
160
152
|
builder._ result.to_s if builder.target!.empty? and result
|
@@ -240,13 +232,12 @@ Tilt.register 'xhtml.rb', Wunderbar::Template::Xhtml
|
|
240
232
|
helpers Wunderbar::SinatraHelpers
|
241
233
|
|
242
234
|
if Dir.exist? settings.public_folder
|
243
|
-
Wunderbar::Asset.root = File.join(settings.public_folder, 'assets')
|
235
|
+
Wunderbar::Asset.root = File.join(settings.public_folder, 'assets')
|
244
236
|
end
|
245
237
|
|
246
238
|
Wunderbar::Asset.virtual = true
|
247
239
|
|
248
240
|
get "/#{Wunderbar::Asset.path}/:name" do |name|
|
249
|
-
name.untaint if name =~ /^([-\w]\.?)+$/
|
250
241
|
file = "#{Wunderbar::Asset.root}/#{name}"
|
251
242
|
_text do
|
252
243
|
if File.exist? file
|
data/lib/wunderbar/version.rb
CHANGED
data/lib/wunderbar/vue.rb
CHANGED
@@ -14,7 +14,7 @@ class Wunderbar::Render
|
|
14
14
|
path = `which nodejs`.chomp
|
15
15
|
path = `which node`.chomp if path.empty?
|
16
16
|
raise RuntimeError.new('Unable to locate nodejs') if path.empty?
|
17
|
-
@nodejs = path
|
17
|
+
@nodejs = path
|
18
18
|
end
|
19
19
|
|
20
20
|
def self.server(common)
|
@@ -50,7 +50,7 @@ class Wunderbar::Render
|
|
50
50
|
stdout += "\n<pre>#{CGI.escapeHTML(stderr)}</pre>"
|
51
51
|
end
|
52
52
|
|
53
|
-
stdout
|
53
|
+
stdout
|
54
54
|
rescue => e
|
55
55
|
Wunderbar.error e
|
56
56
|
"<pre>#{CGI.escapeHTML(e.message)}</pre>"
|