wunderbar 1.3.4 → 1.4.0
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.
- 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>"
|