asciidoctor 1.5.6.2 → 1.5.7
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of asciidoctor might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.adoc +330 -143
- data/README-fr.adoc +441 -0
- data/README-jp.adoc +418 -0
- data/README-zh_CN.adoc +430 -0
- data/README.adoc +454 -0
- data/Rakefile +57 -0
- data/asciidoctor.gemspec +7 -1
- data/data/locale/attributes-ar.adoc +22 -0
- data/data/locale/attributes-bg.adoc +22 -0
- data/data/locale/attributes-ca.adoc +22 -0
- data/data/locale/attributes-cs.adoc +22 -0
- data/data/locale/attributes-da.adoc +22 -0
- data/data/locale/attributes-de.adoc +22 -0
- data/data/locale/attributes-en.adoc +23 -0
- data/data/locale/attributes-es.adoc +22 -0
- data/data/locale/attributes-fa.adoc +22 -0
- data/data/locale/attributes-fi.adoc +22 -0
- data/data/locale/attributes-fr.adoc +22 -0
- data/data/locale/attributes-hu.adoc +22 -0
- data/data/locale/attributes-id.adoc +22 -0
- data/data/locale/attributes-it.adoc +22 -0
- data/data/locale/attributes-ja.adoc +22 -0
- data/data/locale/attributes-kr.adoc +22 -0
- data/data/locale/attributes-nb.adoc +22 -0
- data/data/locale/attributes-nl.adoc +22 -0
- data/data/locale/attributes-nn.adoc +22 -0
- data/data/locale/attributes-pl.adoc +22 -0
- data/data/locale/attributes-pt.adoc +22 -0
- data/data/locale/attributes-pt_BR.adoc +22 -0
- data/data/locale/attributes-ro.adoc +22 -0
- data/data/locale/attributes-ru.adoc +22 -0
- data/data/locale/attributes-sr.adoc +22 -0
- data/data/locale/attributes-sr_Latn.adoc +22 -0
- data/data/locale/attributes-tr.adoc +22 -0
- data/data/locale/attributes-uk.adoc +22 -0
- data/data/locale/attributes-zh_CN.adoc +22 -0
- data/data/locale/attributes-zh_TW.adoc +22 -0
- data/data/locale/attributes.adoc +8 -649
- data/data/stylesheets/asciidoctor-default.css +77 -72
- data/features/xref.feature +366 -7
- data/lib/asciidoctor.rb +107 -93
- data/lib/asciidoctor/abstract_block.rb +247 -239
- data/lib/asciidoctor/abstract_node.rb +56 -58
- data/lib/asciidoctor/block.rb +3 -3
- data/lib/asciidoctor/callouts.rb +1 -1
- data/lib/asciidoctor/cli/invoker.rb +36 -9
- data/lib/asciidoctor/cli/options.rb +63 -25
- data/lib/asciidoctor/converter.rb +23 -13
- data/lib/asciidoctor/converter/base.rb +4 -0
- data/lib/asciidoctor/converter/docbook45.rb +16 -9
- data/lib/asciidoctor/converter/docbook5.rb +115 -97
- data/lib/asciidoctor/converter/factory.rb +29 -31
- data/lib/asciidoctor/converter/html5.rb +229 -192
- data/lib/asciidoctor/converter/manpage.rb +72 -50
- data/lib/asciidoctor/converter/template.rb +12 -12
- data/lib/asciidoctor/core_ext.rb +5 -1
- data/lib/asciidoctor/core_ext/1.8.7/base64/strict_encode64.rb +6 -0
- data/lib/asciidoctor/document.rb +168 -77
- data/lib/asciidoctor/extensions.rb +79 -47
- data/lib/asciidoctor/helpers.rb +33 -11
- data/lib/asciidoctor/inline.rb +3 -2
- data/lib/asciidoctor/list.rb +2 -1
- data/lib/asciidoctor/logging.rb +122 -0
- data/lib/asciidoctor/parser.rb +406 -382
- data/lib/asciidoctor/path_resolver.rb +169 -162
- data/lib/asciidoctor/reader.rb +166 -121
- data/lib/asciidoctor/section.rb +45 -28
- data/lib/asciidoctor/stylesheets.rb +13 -5
- data/lib/asciidoctor/substitutors.rb +328 -254
- data/lib/asciidoctor/table.rb +105 -48
- data/lib/asciidoctor/timings.rb +34 -6
- data/lib/asciidoctor/version.rb +1 -1
- data/man/asciidoctor.1 +41 -23
- data/man/asciidoctor.adoc +14 -8
- data/test/api_test.rb +1004 -0
- data/test/attributes_test.rb +241 -50
- data/test/blocks_test.rb +549 -124
- data/test/converter_test.rb +170 -78
- data/test/document_test.rb +208 -767
- data/test/extensions_test.rb +188 -53
- data/test/fixtures/custom-backends/slim/html5/block_paragraph.html.slim +1 -1
- data/test/fixtures/custom-backends/slim/html5/block_sidebar.html.slim +1 -1
- data/test/fixtures/file-with-missing-include.adoc +1 -0
- data/test/fixtures/include-file.jsx +8 -0
- data/test/fixtures/lists.adoc +96 -0
- data/test/fixtures/other-chapters.adoc +11 -0
- data/test/fixtures/outer-include.adoc +5 -0
- data/test/fixtures/sample.asciidoc +5 -1
- data/test/fixtures/subdir/index.adoc +3 -0
- data/test/fixtures/subdir/inner-include.adoc +3 -0
- data/test/fixtures/subdir/middle-include.adoc +5 -0
- data/test/fixtures/tagged-class-enclosed.rb +0 -1
- data/test/fixtures/unclosed-tag.adoc +3 -0
- data/test/fixtures/unexpected-end-tag.adoc +4 -0
- data/test/invoker_test.rb +101 -40
- data/test/links_test.rb +266 -72
- data/test/lists_test.rb +243 -45
- data/test/logger_test.rb +211 -0
- data/test/manpage_test.rb +124 -6
- data/test/options_test.rb +46 -1
- data/test/paragraphs_test.rb +23 -10
- data/test/parser_test.rb +30 -1
- data/test/paths_test.rb +115 -33
- data/test/preamble_test.rb +1 -1
- data/test/reader_test.rb +337 -81
- data/test/sections_test.rb +656 -72
- data/test/substitutions_test.rb +182 -57
- data/test/tables_test.rb +324 -57
- data/test/test_helper.rb +77 -32
- data/test/text_test.rb +7 -7
- metadata +67 -3
@@ -7,7 +7,7 @@ module Asciidoctor
|
|
7
7
|
# The main emphasis of the class is on creating clean and secure paths. Clean
|
8
8
|
# paths are void of duplicate parent and current directory references in the
|
9
9
|
# path name. Secure paths are paths which are restricted from accessing
|
10
|
-
# directories outside of a jail
|
10
|
+
# directories outside of a jail path, if specified.
|
11
11
|
#
|
12
12
|
# Since joining two paths can result in an insecure path, this class also
|
13
13
|
# handles the task of joining a parent (start) and child (target) path.
|
@@ -94,13 +94,15 @@ module Asciidoctor
|
|
94
94
|
# => '/path/to/docs/images'
|
95
95
|
#
|
96
96
|
# begin
|
97
|
-
# resolver.system_path('images', '/etc', '/path/to/docs')
|
97
|
+
# resolver.system_path('images', '/etc', '/path/to/docs', recover: false)
|
98
98
|
# rescue SecurityError => e
|
99
99
|
# puts e.message
|
100
100
|
# end
|
101
|
-
# =>
|
101
|
+
# => start path /etc is outside of jail: /path/to/docs'
|
102
102
|
#
|
103
103
|
class PathResolver
|
104
|
+
include Logging
|
105
|
+
|
104
106
|
DOT = '.'
|
105
107
|
DOT_DOT = '..'
|
106
108
|
DOT_SLASH = './'
|
@@ -118,17 +120,14 @@ class PathResolver
|
|
118
120
|
# expanded to an absolute path inside the constructor.
|
119
121
|
#
|
120
122
|
# file_separator - the String file separator to use for path operations
|
121
|
-
# (optional, default: File::SEPARATOR)
|
123
|
+
# (optional, default: File::ALT_SEPARATOR or File::SEPARATOR)
|
122
124
|
# working_dir - the String working directory (optional, default: Dir.pwd)
|
123
125
|
#
|
124
126
|
def initialize file_separator = nil, working_dir = nil
|
125
|
-
@file_separator = file_separator
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
@working_dir = ::File.expand_path ::Dir.pwd
|
130
|
-
end
|
131
|
-
@_partition_path_sys, @_partition_path_web = {}, {}
|
127
|
+
@file_separator = file_separator || ::File::ALT_SEPARATOR || ::File::SEPARATOR
|
128
|
+
@working_dir = working_dir ? ((root? working_dir) ? (posixify working_dir) : (::File.expand_path working_dir)) : ::Dir.pwd
|
129
|
+
@_partition_path_sys = {}
|
130
|
+
@_partition_path_web = {}
|
132
131
|
end
|
133
132
|
|
134
133
|
# Public: Check whether the specified path is an absolute path.
|
@@ -196,7 +195,26 @@ class PathResolver
|
|
196
195
|
#
|
197
196
|
# returns If path descends from base, return the offset, otherwise false.
|
198
197
|
def descends_from? path, base
|
199
|
-
base == path
|
198
|
+
if base == path
|
199
|
+
0
|
200
|
+
elsif base == SLASH
|
201
|
+
(path.start_with? SLASH) && 1
|
202
|
+
else
|
203
|
+
(path.start_with? base + SLASH) && (base.length + 1)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
# Public: Calculate the relative path to this absolute path from the specified base directory
|
208
|
+
#
|
209
|
+
# If neither path or base are absolute paths, or the path is not contained
|
210
|
+
# within the base directory, no work is done.
|
211
|
+
#
|
212
|
+
# path - [String] an absolute filename.
|
213
|
+
# base - [String] an absolute base directory.
|
214
|
+
#
|
215
|
+
# Return the [String] relative path of the specified path calculated from the base directory.
|
216
|
+
def relative_path path, base
|
217
|
+
(root? path) && (offset = descends_from? path, base) ? (path.slice offset, path.length) : path
|
200
218
|
end
|
201
219
|
|
202
220
|
# Public: Normalize path by converting any backslashes to forward slashes
|
@@ -205,45 +223,46 @@ class PathResolver
|
|
205
223
|
#
|
206
224
|
# returns a String path with any backslashes replaced with forward slashes
|
207
225
|
def posixify path
|
208
|
-
if path
|
209
|
-
|
210
|
-
elsif path.include? BACKSLASH
|
211
|
-
path.tr BACKSLASH, SLASH
|
226
|
+
if path
|
227
|
+
@file_separator == BACKSLASH && (path.include? BACKSLASH) ? (path.tr BACKSLASH, SLASH) : path
|
212
228
|
else
|
213
|
-
|
229
|
+
''
|
214
230
|
end
|
215
231
|
end
|
216
232
|
alias posixfy posixify
|
217
233
|
|
218
|
-
# Public: Expand the path by
|
219
|
-
# and
|
220
|
-
#
|
221
|
-
# The result will be relative if the path is relative and
|
222
|
-
# absolute if the path is absolute. The file separator used
|
223
|
-
# in the expanded path is the one specified when the class
|
224
|
-
# was constructed.
|
234
|
+
# Public: Expand the specified path by converting the path to a posix path, resolving parent
|
235
|
+
# references (..), and removing self references (.).
|
225
236
|
#
|
226
237
|
# path - the String path to expand
|
227
238
|
#
|
228
|
-
# returns a String path with
|
239
|
+
# returns a String path as a posix path with parent references resolved and self references removed.
|
240
|
+
# The result will be relative if the path is relative and absolute if the path is absolute.
|
229
241
|
def expand_path path
|
230
|
-
path_segments, path_root
|
231
|
-
|
242
|
+
path_segments, path_root = partition_path path
|
243
|
+
if path.include? DOT_DOT
|
244
|
+
resolved_segments = []
|
245
|
+
path_segments.each do |segment|
|
246
|
+
segment == DOT_DOT ? resolved_segments.pop : resolved_segments << segment
|
247
|
+
end
|
248
|
+
join_path resolved_segments, path_root
|
249
|
+
else
|
250
|
+
join_path path_segments, path_root
|
251
|
+
end
|
232
252
|
end
|
233
253
|
|
234
|
-
# Public: Partition the path into path segments and remove
|
235
|
-
#
|
236
|
-
#
|
254
|
+
# Public: Partition the path into path segments and remove self references (.) and the trailing
|
255
|
+
# slash, if present. Prior to being partitioned, the path is converted to a posix path.
|
256
|
+
#
|
257
|
+
# Parent references are not resolved by this method since the consumer often needs to handle this
|
258
|
+
# resolution in a certain context (checking for the breach of a jail, for instance).
|
237
259
|
#
|
238
260
|
# path - the String path to partition
|
239
261
|
# web - a Boolean indicating whether the path should be handled
|
240
262
|
# as a web path (optional, default: false)
|
241
263
|
#
|
242
|
-
# Returns a
|
243
|
-
# path root (e.g., '/', './', 'c:/')
|
244
|
-
# version of the path.
|
245
|
-
#--
|
246
|
-
# QUESTION is it worth it to normalize slashes? it doubles the time elapsed
|
264
|
+
# Returns a 2-item Array containing the Array of String path segments and the
|
265
|
+
# path root (e.g., '/', './', 'c:/', or '//'), which is nil unless the path is absolute.
|
247
266
|
def partition_path path, web = nil
|
248
267
|
if (result = (cache = web ? @_partition_path_web : @_partition_path_sys)[path])
|
249
268
|
return result
|
@@ -251,56 +270,36 @@ class PathResolver
|
|
251
270
|
|
252
271
|
posix_path = posixify path
|
253
272
|
|
254
|
-
|
273
|
+
if web
|
255
274
|
# ex. /sample/path
|
256
275
|
if web_root? posix_path
|
257
|
-
SLASH
|
276
|
+
root = SLASH
|
258
277
|
# ex. ./sample/path
|
259
278
|
elsif posix_path.start_with? DOT_SLASH
|
260
|
-
DOT_SLASH
|
261
|
-
# ex. sample/path
|
262
|
-
else
|
263
|
-
nil
|
279
|
+
root = DOT_SLASH
|
280
|
+
# else ex. sample/path
|
264
281
|
end
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
# ex. C:/sample/path (or file:///sample/path in browser environment)
|
274
|
-
else
|
275
|
-
posix_path.slice 0, (posix_path.index SLASH) + 1
|
276
|
-
end
|
277
|
-
# ex. ./sample/path
|
278
|
-
elsif posix_path.start_with? DOT_SLASH
|
279
|
-
DOT_SLASH
|
280
|
-
# ex. sample/path
|
282
|
+
elsif root? posix_path
|
283
|
+
# ex. //sample/path
|
284
|
+
if unc? posix_path
|
285
|
+
root = DOUBLE_SLASH
|
286
|
+
# ex. /sample/path
|
287
|
+
elsif posix_path.start_with? SLASH
|
288
|
+
root = SLASH
|
289
|
+
# ex. C:/sample/path (or file:///sample/path in browser environment)
|
281
290
|
else
|
282
|
-
|
291
|
+
root = posix_path.slice 0, (posix_path.index SLASH) + 1
|
283
292
|
end
|
293
|
+
# ex. ./sample/path
|
294
|
+
elsif posix_path.start_with? DOT_SLASH
|
295
|
+
root = DOT_SLASH
|
296
|
+
# else ex. sample/path
|
284
297
|
end
|
285
298
|
|
286
|
-
path_segments = posix_path.split SLASH
|
287
|
-
# shift twice for a UNC path
|
288
|
-
if root == DOUBLE_SLASH
|
289
|
-
path_segments = path_segments[2..-1]
|
290
|
-
# shift twice for a file:/// path and adjust root
|
291
|
-
# NOTE technically file:/// paths work without this adjustment
|
292
|
-
#elsif ::RUBY_ENGINE_OPAL && ::JAVASCRIPT_IO_MODULE == 'xmlhttprequest' && root == 'file:/'
|
293
|
-
# root = 'file://'
|
294
|
-
# path_segments = path_segments[2..-1]
|
295
|
-
# shift once for any other root
|
296
|
-
elsif root
|
297
|
-
path_segments.shift
|
298
|
-
end
|
299
|
+
path_segments = (root ? (posix_path.slice root.length, posix_path.length) : posix_path).split SLASH
|
299
300
|
# strip out all dot entries
|
300
301
|
path_segments.delete DOT
|
301
|
-
|
302
|
-
#posix_path = posix_path.chop if posix_path.end_with? SLASH
|
303
|
-
cache[path] = [path_segments, root, posix_path]
|
302
|
+
cache[path] = [path_segments, root]
|
304
303
|
end
|
305
304
|
|
306
305
|
# Public: Join the segments using the posix file separator (since Ruby knows
|
@@ -317,110 +316,135 @@ class PathResolver
|
|
317
316
|
root ? %(#{root}#{segments * SLASH}) : segments * SLASH
|
318
317
|
end
|
319
318
|
|
320
|
-
# Public:
|
321
|
-
#
|
322
|
-
#
|
323
|
-
#
|
324
|
-
#
|
325
|
-
#
|
319
|
+
# Public: Securely resolve a system path
|
320
|
+
#
|
321
|
+
# Resolve a system path from the target relative to the start path, jail path, or working
|
322
|
+
# directory (specified in the constructor), in that order. If a jail path is specified, enforce
|
323
|
+
# that the resolved path descends from the jail path. If a jail path is not provided, the resolved
|
324
|
+
# path may be any location on the system. If the resolved path is absolute, use it as is (unless
|
325
|
+
# it breaches the jail path). Expand all parent and self references in the resolved path.
|
326
326
|
#
|
327
327
|
# target - the String target path
|
328
|
-
# start - the String start
|
329
|
-
#
|
328
|
+
# start - the String start path from which to resolve a relative target; falls back to jail, if
|
329
|
+
# specified, or the working directory specified in the constructor (default: nil)
|
330
|
+
# jail - the String jail path to which to confine the resolved path, if specified; must be an
|
331
|
+
# absolute path (default: nil)
|
330
332
|
# opts - an optional Hash of options to control processing (default: {}):
|
331
|
-
# * :recover is used to control whether the processor should
|
332
|
-
#
|
333
|
+
# * :recover is used to control whether the processor should
|
334
|
+
# automatically recover when an illegal path is encountered
|
333
335
|
# * :target_name is used in messages to refer to the path being resolved
|
334
336
|
#
|
335
|
-
# returns a String path
|
336
|
-
#
|
337
|
-
# that the resolved path be contained within the jail, if provided
|
337
|
+
# returns a String path relative to the start path, if specified, and confined to the jail path,
|
338
|
+
# if specified. The path is posixified and all parent and self references in the path are expanded.
|
338
339
|
def system_path target, start = nil, jail = nil, opts = {}
|
339
340
|
if jail
|
340
|
-
unless root? jail
|
341
|
-
|
342
|
-
end
|
341
|
+
raise ::SecurityError, %(Jail is not an absolute path: #{jail}) unless root? jail
|
342
|
+
#raise ::SecurityError, %(Jail is not a canonical path: #{jail}) if jail.include? DOT_DOT
|
343
343
|
jail = posixify jail
|
344
344
|
end
|
345
345
|
|
346
|
-
if target
|
347
|
-
|
346
|
+
if target
|
347
|
+
if root? target
|
348
|
+
target_path = expand_path target
|
349
|
+
if jail && !(descends_from? target_path, jail)
|
350
|
+
if opts.fetch :recover, true
|
351
|
+
logger.warn %(#{opts[:target_name] || 'path'} is outside of jail; recovering automatically)
|
352
|
+
target_segments, _ = partition_path target_path
|
353
|
+
jail_segments, jail_root = partition_path jail
|
354
|
+
return join_path jail_segments + target_segments, jail_root
|
355
|
+
else
|
356
|
+
raise ::SecurityError, %(#{opts[:target_name] || 'path'} #{target} is outside of jail: #{jail} (disallowed in safe mode))
|
357
|
+
end
|
358
|
+
end
|
359
|
+
return target_path
|
360
|
+
else
|
361
|
+
target_segments, _ = partition_path target
|
362
|
+
end
|
348
363
|
else
|
349
|
-
target_segments
|
364
|
+
target_segments = []
|
350
365
|
end
|
351
366
|
|
352
367
|
if target_segments.empty?
|
353
368
|
if start.nil_or_empty?
|
354
|
-
return jail
|
369
|
+
return jail || @working_dir
|
355
370
|
elsif root? start
|
356
|
-
|
371
|
+
if jail
|
372
|
+
start = posixify start
|
373
|
+
else
|
357
374
|
return expand_path start
|
358
375
|
end
|
359
376
|
else
|
360
|
-
|
377
|
+
target_segments, _ = partition_path start
|
378
|
+
start = jail || @working_dir
|
361
379
|
end
|
362
|
-
|
363
|
-
|
364
|
-
if target_root && target_root != DOT_SLASH
|
365
|
-
resolved_target = join_path target_segments, target_root
|
366
|
-
# if target is absolute and a sub-directory of jail, or
|
367
|
-
# a jail is not in place, let it slide
|
368
|
-
if !jail || (resolved_target.start_with? jail)
|
369
|
-
return resolved_target
|
370
|
-
end
|
371
|
-
end
|
372
|
-
|
373
|
-
if start.nil_or_empty?
|
374
|
-
start = jail ? jail : @working_dir
|
380
|
+
elsif start.nil_or_empty?
|
381
|
+
start = jail || @working_dir
|
375
382
|
elsif root? start
|
376
|
-
start = posixify start
|
383
|
+
start = posixify start if jail
|
377
384
|
else
|
378
|
-
start = system_path start, jail, jail, opts
|
385
|
+
#start = system_path start, jail, jail, opts
|
386
|
+
start = %(#{(jail || @working_dir).chomp '/'}/#{start})
|
379
387
|
end
|
380
388
|
|
381
|
-
# both jail and start have been
|
382
|
-
if jail ==
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
389
|
+
# both jail and start have been posixified at this point if jail is set
|
390
|
+
if jail && (recheck = !(descends_from? start, jail)) && @file_separator == BACKSLASH
|
391
|
+
start_segments, start_root = partition_path start
|
392
|
+
jail_segments, jail_root = partition_path jail
|
393
|
+
if start_root != jail_root
|
394
|
+
if opts.fetch :recover, true
|
395
|
+
logger.warn %(start path for #{opts[:target_name] || 'path'} is outside of jail root; recovering automatically)
|
396
|
+
start_segments = jail_segments
|
397
|
+
recheck = false
|
398
|
+
else
|
399
|
+
raise ::SecurityError, %(start path for #{opts[:target_name] || 'path'} #{start} refers to location outside jail root: #{jail} (disallowed in safe mode))
|
400
|
+
end
|
388
401
|
end
|
389
|
-
|
390
|
-
start_segments, start_root, _ = partition_path start
|
391
|
-
jail_segments, jail_root, _ = partition_path jail
|
392
|
-
|
393
|
-
# Already checked for this condition
|
394
|
-
#if start_root != jail_root
|
395
|
-
# raise ::SecurityError, %(Jail root #{jail_root} does not match root of #{opts[:target_name] || 'start path'}: #{start_root})
|
396
|
-
#end
|
397
402
|
else
|
398
|
-
start_segments,
|
399
|
-
jail_root = start_root
|
403
|
+
start_segments, jail_root = partition_path start
|
400
404
|
end
|
401
405
|
|
402
|
-
resolved_segments = start_segments.
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
406
|
+
if (resolved_segments = start_segments + target_segments).include? DOT_DOT
|
407
|
+
unresolved_segments, resolved_segments = resolved_segments, []
|
408
|
+
if jail
|
409
|
+
jail_segments, _ = partition_path jail unless jail_segments
|
410
|
+
warned = false
|
411
|
+
unresolved_segments.each do |segment|
|
412
|
+
if segment == DOT_DOT
|
413
|
+
if resolved_segments.size > jail_segments.size
|
414
|
+
resolved_segments.pop
|
415
|
+
elsif opts.fetch :recover, true
|
416
|
+
unless warned
|
417
|
+
logger.warn %(#{opts[:target_name] || 'path'} has illegal reference to ancestor of jail; recovering automatically)
|
418
|
+
warned = true
|
419
|
+
end
|
420
|
+
else
|
421
|
+
raise ::SecurityError, %(#{opts[:target_name] || 'path'} #{target} refers to location outside jail: #{jail} (disallowed in safe mode))
|
422
|
+
end
|
423
|
+
else
|
424
|
+
resolved_segments << segment
|
414
425
|
end
|
415
|
-
else
|
416
|
-
resolved_segments.pop
|
417
426
|
end
|
418
427
|
else
|
419
|
-
|
428
|
+
unresolved_segments.each do |segment|
|
429
|
+
segment == DOT_DOT ? resolved_segments.pop : resolved_segments << segment
|
430
|
+
end
|
420
431
|
end
|
421
432
|
end
|
422
433
|
|
423
|
-
|
434
|
+
if recheck
|
435
|
+
target_path = join_path resolved_segments, jail_root
|
436
|
+
if descends_from? target_path, jail
|
437
|
+
target_path
|
438
|
+
elsif opts.fetch :recover, true
|
439
|
+
logger.warn %(#{opts[:target_name] || 'path'} is outside of jail; recovering automatically)
|
440
|
+
jail_segments, _ = partition_path jail unless jail_segments
|
441
|
+
join_path jail_segments + target_segments, jail_root
|
442
|
+
else
|
443
|
+
raise ::SecurityError, %(#{opts[:target_name] || 'path'} #{target} is outside of jail: #{jail} (disallowed in safe mode))
|
444
|
+
end
|
445
|
+
else
|
446
|
+
join_path resolved_segments, jail_root
|
447
|
+
end
|
424
448
|
end
|
425
449
|
|
426
450
|
# Public: Resolve a web path from the target and start paths.
|
@@ -460,7 +484,7 @@ class PathResolver
|
|
460
484
|
# end
|
461
485
|
#end
|
462
486
|
|
463
|
-
target_segments, target_root
|
487
|
+
target_segments, target_root = partition_path target, true
|
464
488
|
resolved_segments = []
|
465
489
|
target_segments.each do |segment|
|
466
490
|
if segment == DOT_DOT
|
@@ -484,22 +508,5 @@ class PathResolver
|
|
484
508
|
|
485
509
|
uri_prefix ? %(#{uri_prefix}#{resolved_path}) : resolved_path
|
486
510
|
end
|
487
|
-
|
488
|
-
# Public: Calculate the relative path to this absolute filename from the specified base directory
|
489
|
-
#
|
490
|
-
# If either the filename or the base_directory are not absolute paths, or the
|
491
|
-
# filename is not contained within the base directory, no work is done.
|
492
|
-
#
|
493
|
-
# filename - [String] an absolute filename.
|
494
|
-
# base_directory - [String] an absolute base directory.
|
495
|
-
#
|
496
|
-
# Return the [String] relative path of the filename calculated from the base directory.
|
497
|
-
def relative_path filename, base_directory
|
498
|
-
if (root? filename) && (filename.start_with? base_directory)
|
499
|
-
filename.slice base_directory.length + 1, filename.length
|
500
|
-
else
|
501
|
-
filename
|
502
|
-
end
|
503
|
-
end
|
504
511
|
end
|
505
512
|
end
|