asciidoctor 1.5.6.2 → 1.5.7
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.
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
         |