ultra-max-sys 0.0.1

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 ultra-max-sys might be problematic. Click here for more details.

Files changed (163) hide show
  1. checksums.yaml +7 -0
  2. data/roda-3.106.0/MIT-LICENSE +21 -0
  3. data/roda-3.106.0/lib/roda/cache.rb +42 -0
  4. data/roda-3.106.0/lib/roda/plugins/Integer_matcher_max.rb +55 -0
  5. data/roda-3.106.0/lib/roda/plugins/_after_hook.rb +11 -0
  6. data/roda-3.106.0/lib/roda/plugins/_base64.rb +34 -0
  7. data/roda-3.106.0/lib/roda/plugins/_before_hook.rb +41 -0
  8. data/roda-3.106.0/lib/roda/plugins/_optimized_matching.rb +227 -0
  9. data/roda-3.106.0/lib/roda/plugins/_symbol_class_matchers.rb +108 -0
  10. data/roda-3.106.0/lib/roda/plugins/_symbol_regexp_matchers.rb +24 -0
  11. data/roda-3.106.0/lib/roda/plugins/additional_render_engines.rb +61 -0
  12. data/roda-3.106.0/lib/roda/plugins/additional_view_directories.rb +66 -0
  13. data/roda-3.106.0/lib/roda/plugins/all_verbs.rb +50 -0
  14. data/roda-3.106.0/lib/roda/plugins/assets.rb +902 -0
  15. data/roda-3.106.0/lib/roda/plugins/assets_preloading.rb +89 -0
  16. data/roda-3.106.0/lib/roda/plugins/assume_ssl.rb +28 -0
  17. data/roda-3.106.0/lib/roda/plugins/autoload_hash_branches.rb +79 -0
  18. data/roda-3.106.0/lib/roda/plugins/autoload_named_routes.rb +65 -0
  19. data/roda-3.106.0/lib/roda/plugins/backtracking_array.rb +88 -0
  20. data/roda-3.106.0/lib/roda/plugins/bearer_token.rb +28 -0
  21. data/roda-3.106.0/lib/roda/plugins/branch_locals.rb +76 -0
  22. data/roda-3.106.0/lib/roda/plugins/break.rb +43 -0
  23. data/roda-3.106.0/lib/roda/plugins/caching.rb +206 -0
  24. data/roda-3.106.0/lib/roda/plugins/capture_erb.rb +94 -0
  25. data/roda-3.106.0/lib/roda/plugins/chunked.rb +333 -0
  26. data/roda-3.106.0/lib/roda/plugins/class_level_routing.rb +111 -0
  27. data/roda-3.106.0/lib/roda/plugins/class_matchers.rb +155 -0
  28. data/roda-3.106.0/lib/roda/plugins/common_logger.rb +82 -0
  29. data/roda-3.106.0/lib/roda/plugins/conditional_sessions.rb +67 -0
  30. data/roda-3.106.0/lib/roda/plugins/content_for.rb +105 -0
  31. data/roda-3.106.0/lib/roda/plugins/content_security_policy.rb +333 -0
  32. data/roda-3.106.0/lib/roda/plugins/cookie_flags.rb +157 -0
  33. data/roda-3.106.0/lib/roda/plugins/cookies.rb +51 -0
  34. data/roda-3.106.0/lib/roda/plugins/csrf.rb +81 -0
  35. data/roda-3.106.0/lib/roda/plugins/custom_block_results.rb +85 -0
  36. data/roda-3.106.0/lib/roda/plugins/custom_matchers.rb +89 -0
  37. data/roda-3.106.0/lib/roda/plugins/default_headers.rb +64 -0
  38. data/roda-3.106.0/lib/roda/plugins/default_status.rb +35 -0
  39. data/roda-3.106.0/lib/roda/plugins/delay_build.rb +18 -0
  40. data/roda-3.106.0/lib/roda/plugins/delegate.rb +77 -0
  41. data/roda-3.106.0/lib/roda/plugins/delete_empty_headers.rb +36 -0
  42. data/roda-3.106.0/lib/roda/plugins/direct_call.rb +38 -0
  43. data/roda-3.106.0/lib/roda/plugins/disallow_file_uploads.rb +38 -0
  44. data/roda-3.106.0/lib/roda/plugins/drop_body.rb +43 -0
  45. data/roda-3.106.0/lib/roda/plugins/each_part.rb +87 -0
  46. data/roda-3.106.0/lib/roda/plugins/early_hints.rb +25 -0
  47. data/roda-3.106.0/lib/roda/plugins/empty_root.rb +49 -0
  48. data/roda-3.106.0/lib/roda/plugins/environments.rb +79 -0
  49. data/roda-3.106.0/lib/roda/plugins/erb_h.rb +43 -0
  50. data/roda-3.106.0/lib/roda/plugins/error_email.rb +152 -0
  51. data/roda-3.106.0/lib/roda/plugins/error_handler.rb +133 -0
  52. data/roda-3.106.0/lib/roda/plugins/error_mail.rb +149 -0
  53. data/roda-3.106.0/lib/roda/plugins/exception_page.rb +445 -0
  54. data/roda-3.106.0/lib/roda/plugins/filter_common_logger.rb +46 -0
  55. data/roda-3.106.0/lib/roda/plugins/flash.rb +119 -0
  56. data/roda-3.106.0/lib/roda/plugins/h.rb +59 -0
  57. data/roda-3.106.0/lib/roda/plugins/halt.rb +108 -0
  58. data/roda-3.106.0/lib/roda/plugins/hash_branch_view_subdir.rb +76 -0
  59. data/roda-3.106.0/lib/roda/plugins/hash_branches.rb +145 -0
  60. data/roda-3.106.0/lib/roda/plugins/hash_matcher.rb +39 -0
  61. data/roda-3.106.0/lib/roda/plugins/hash_paths.rb +128 -0
  62. data/roda-3.106.0/lib/roda/plugins/hash_public.rb +125 -0
  63. data/roda-3.106.0/lib/roda/plugins/hash_public_cache.rb +91 -0
  64. data/roda-3.106.0/lib/roda/plugins/hash_routes.rb +304 -0
  65. data/roda-3.106.0/lib/roda/plugins/head.rb +99 -0
  66. data/roda-3.106.0/lib/roda/plugins/header_matchers.rb +88 -0
  67. data/roda-3.106.0/lib/roda/plugins/heartbeat.rb +41 -0
  68. data/roda-3.106.0/lib/roda/plugins/hmac_paths.rb +413 -0
  69. data/roda-3.106.0/lib/roda/plugins/hooks.rb +92 -0
  70. data/roda-3.106.0/lib/roda/plugins/host_authorization.rb +155 -0
  71. data/roda-3.106.0/lib/roda/plugins/host_routing.rb +194 -0
  72. data/roda-3.106.0/lib/roda/plugins/hsts.rb +35 -0
  73. data/roda-3.106.0/lib/roda/plugins/indifferent_params.rb +126 -0
  74. data/roda-3.106.0/lib/roda/plugins/inject_erb.rb +33 -0
  75. data/roda-3.106.0/lib/roda/plugins/invalid_request_body.rb +107 -0
  76. data/roda-3.106.0/lib/roda/plugins/ip_from_header.rb +34 -0
  77. data/roda-3.106.0/lib/roda/plugins/json.rb +119 -0
  78. data/roda-3.106.0/lib/roda/plugins/json_parser.rb +107 -0
  79. data/roda-3.106.0/lib/roda/plugins/link_to.rb +83 -0
  80. data/roda-3.106.0/lib/roda/plugins/mail_processor.rb +629 -0
  81. data/roda-3.106.0/lib/roda/plugins/mailer.rb +285 -0
  82. data/roda-3.106.0/lib/roda/plugins/map_matcher.rb +48 -0
  83. data/roda-3.106.0/lib/roda/plugins/match_affix.rb +64 -0
  84. data/roda-3.106.0/lib/roda/plugins/match_hook.rb +34 -0
  85. data/roda-3.106.0/lib/roda/plugins/match_hook_args.rb +93 -0
  86. data/roda-3.106.0/lib/roda/plugins/middleware.rb +225 -0
  87. data/roda-3.106.0/lib/roda/plugins/middleware_stack.rb +101 -0
  88. data/roda-3.106.0/lib/roda/plugins/module_include.rb +96 -0
  89. data/roda-3.106.0/lib/roda/plugins/multi_public.rb +95 -0
  90. data/roda-3.106.0/lib/roda/plugins/multi_route.rb +156 -0
  91. data/roda-3.106.0/lib/roda/plugins/multi_run.rb +144 -0
  92. data/roda-3.106.0/lib/roda/plugins/multi_view.rb +83 -0
  93. data/roda-3.106.0/lib/roda/plugins/multibyte_string_matcher.rb +57 -0
  94. data/roda-3.106.0/lib/roda/plugins/named_routes.rb +167 -0
  95. data/roda-3.106.0/lib/roda/plugins/named_templates.rb +102 -0
  96. data/roda-3.106.0/lib/roda/plugins/not_allowed.rb +151 -0
  97. data/roda-3.106.0/lib/roda/plugins/not_found.rb +55 -0
  98. data/roda-3.106.0/lib/roda/plugins/optimized_segment_matchers.rb +53 -0
  99. data/roda-3.106.0/lib/roda/plugins/optimized_string_matchers.rb +50 -0
  100. data/roda-3.106.0/lib/roda/plugins/padrino_render.rb +42 -0
  101. data/roda-3.106.0/lib/roda/plugins/param_matchers.rb +83 -0
  102. data/roda-3.106.0/lib/roda/plugins/params_capturing.rb +118 -0
  103. data/roda-3.106.0/lib/roda/plugins/part.rb +76 -0
  104. data/roda-3.106.0/lib/roda/plugins/partials.rb +74 -0
  105. data/roda-3.106.0/lib/roda/plugins/pass.rb +47 -0
  106. data/roda-3.106.0/lib/roda/plugins/path.rb +255 -0
  107. data/roda-3.106.0/lib/roda/plugins/path_matchers.rb +54 -0
  108. data/roda-3.106.0/lib/roda/plugins/path_rewriter.rb +111 -0
  109. data/roda-3.106.0/lib/roda/plugins/permissions_policy.rb +340 -0
  110. data/roda-3.106.0/lib/roda/plugins/placeholder_string_matchers.rb +48 -0
  111. data/roda-3.106.0/lib/roda/plugins/plain_hash_response_headers.rb +32 -0
  112. data/roda-3.106.0/lib/roda/plugins/precompile_templates.rb +156 -0
  113. data/roda-3.106.0/lib/roda/plugins/public.rb +182 -0
  114. data/roda-3.106.0/lib/roda/plugins/r.rb +35 -0
  115. data/roda-3.106.0/lib/roda/plugins/recheck_precompiled_assets.rb +107 -0
  116. data/roda-3.106.0/lib/roda/plugins/redirect_http_to_https.rb +99 -0
  117. data/roda-3.106.0/lib/roda/plugins/redirect_path.rb +59 -0
  118. data/roda-3.106.0/lib/roda/plugins/relative_path.rb +76 -0
  119. data/roda-3.106.0/lib/roda/plugins/render.rb +998 -0
  120. data/roda-3.106.0/lib/roda/plugins/render_coverage.rb +105 -0
  121. data/roda-3.106.0/lib/roda/plugins/render_each.rb +224 -0
  122. data/roda-3.106.0/lib/roda/plugins/render_locals.rb +102 -0
  123. data/roda-3.106.0/lib/roda/plugins/request_aref.rb +77 -0
  124. data/roda-3.106.0/lib/roda/plugins/request_headers.rb +83 -0
  125. data/roda-3.106.0/lib/roda/plugins/response_attachment.rb +94 -0
  126. data/roda-3.106.0/lib/roda/plugins/response_content_type.rb +79 -0
  127. data/roda-3.106.0/lib/roda/plugins/response_request.rb +36 -0
  128. data/roda-3.106.0/lib/roda/plugins/route_block_args.rb +50 -0
  129. data/roda-3.106.0/lib/roda/plugins/route_csrf.rb +388 -0
  130. data/roda-3.106.0/lib/roda/plugins/run_append_slash.rb +51 -0
  131. data/roda-3.106.0/lib/roda/plugins/run_handler.rb +51 -0
  132. data/roda-3.106.0/lib/roda/plugins/run_require_slash.rb +46 -0
  133. data/roda-3.106.0/lib/roda/plugins/sec_fetch_site_csrf.rb +131 -0
  134. data/roda-3.106.0/lib/roda/plugins/send_file.rb +127 -0
  135. data/roda-3.106.0/lib/roda/plugins/sessions.rb +537 -0
  136. data/roda-3.106.0/lib/roda/plugins/shape_friendly.rb +232 -0
  137. data/roda-3.106.0/lib/roda/plugins/shared_vars.rb +86 -0
  138. data/roda-3.106.0/lib/roda/plugins/sinatra_helpers.rb +444 -0
  139. data/roda-3.106.0/lib/roda/plugins/slash_path_empty.rb +26 -0
  140. data/roda-3.106.0/lib/roda/plugins/static.rb +42 -0
  141. data/roda-3.106.0/lib/roda/plugins/static_routing.rb +89 -0
  142. data/roda-3.106.0/lib/roda/plugins/status_303.rb +34 -0
  143. data/roda-3.106.0/lib/roda/plugins/status_handler.rb +86 -0
  144. data/roda-3.106.0/lib/roda/plugins/streaming.rb +170 -0
  145. data/roda-3.106.0/lib/roda/plugins/strip_path_prefix.rb +33 -0
  146. data/roda-3.106.0/lib/roda/plugins/symbol_matchers.rb +188 -0
  147. data/roda-3.106.0/lib/roda/plugins/symbol_status.rb +32 -0
  148. data/roda-3.106.0/lib/roda/plugins/symbol_views.rb +37 -0
  149. data/roda-3.106.0/lib/roda/plugins/timestamp_public.rb +78 -0
  150. data/roda-3.106.0/lib/roda/plugins/type_routing.rb +217 -0
  151. data/roda-3.106.0/lib/roda/plugins/typecast_params.rb +1185 -0
  152. data/roda-3.106.0/lib/roda/plugins/typecast_params_sized_integers.rb +108 -0
  153. data/roda-3.106.0/lib/roda/plugins/unescape_path.rb +41 -0
  154. data/roda-3.106.0/lib/roda/plugins/view_options.rb +203 -0
  155. data/roda-3.106.0/lib/roda/plugins/view_subdir_leading_slash.rb +49 -0
  156. data/roda-3.106.0/lib/roda/plugins.rb +68 -0
  157. data/roda-3.106.0/lib/roda/request.rb +722 -0
  158. data/roda-3.106.0/lib/roda/response.rb +221 -0
  159. data/roda-3.106.0/lib/roda/session_middleware.rb +184 -0
  160. data/roda-3.106.0/lib/roda/version.rb +18 -0
  161. data/roda-3.106.0/lib/roda.rb +741 -0
  162. data/ultra-max-sys.gemspec +12 -0
  163. metadata +202 -0
@@ -0,0 +1,46 @@
1
+ # frozen-string-literal: true
2
+
3
+ #
4
+ class Roda
5
+ module RodaPlugins
6
+ # The run_require_slash plugin makes +r.run+ a no-op if the remaining
7
+ # path is not empty and does not start with +/+. The Rack SPEC requires that
8
+ # +PATH_INFO+ start with a slash if not empty, so this plugin prevents
9
+ # dispatching to the application with an environment that would violate the
10
+ # Rack SPEC.
11
+ #
12
+ # You are unlikely to want to use this plugin unless you are consuming partial
13
+ # segments of the request path, or using the match_affix plugin to change
14
+ # how routing is done:
15
+ #
16
+ # plugin :match_affix, "", /(\/|\z)/
17
+ # route do |r|
18
+ # r.on "/a" do
19
+ # r.on "b" do
20
+ # r.run App
21
+ # end
22
+ # end
23
+ # end
24
+ #
25
+ # # with run_require_slash:
26
+ # # GET /a/b/e => Not dispatched to application
27
+ # # GET /a/b => App gets "" as PATH_INFO
28
+ #
29
+ # # without run_require_slash:
30
+ # # GET /a/b/e => App gets "e" as PATH_INFO, violating rack SPEC
31
+ # # GET /a/b => App gets "" as PATH_INFO
32
+ module RunRequireSlash
33
+ module RequestMethods
34
+ # Calls the given rack app only if the remaining patch is empty or
35
+ # starts with a slash.
36
+ def run(*)
37
+ if @remaining_path.empty? || @remaining_path.start_with?('/')
38
+ super
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ register_plugin(:run_require_slash, RunRequireSlash)
45
+ end
46
+ end
@@ -0,0 +1,131 @@
1
+ # frozen-string-literal: true
2
+
3
+ class Roda
4
+ module RodaPlugins
5
+ # The sec_fetch_site_csrf plugin allows for CSRF protection using the
6
+ # Sec-Fetch-Site header added in modern browsers. It allows for CSRF
7
+ # protection without the use of CSRF tokens, which can simplify
8
+ # form creation.
9
+ #
10
+ # The protection offered by the sec_fetch_site_csrf plugin is weaker than
11
+ # the protection offered by the route_csrf plugin with default settings,
12
+ # since it doesn't support per-request tokens. Be aware you are trading
13
+ # security for simplicity when using the sec_fetch_site_csrf plugin instead
14
+ # of the route_csrf plugin. Other caveats in using the sec_fetch_site_csrf
15
+ # plugin:
16
+ #
17
+ # * Not all browsers set the Sec-Fetch-Site header. Some browsers
18
+ # didn't start setting the header until 2023. In these cases, you
19
+ # need to decide how to handle the request. The default is to deny
20
+ # the request, though you can use the :allow_missing option to allow
21
+ # it.
22
+ #
23
+ # * Sec-Fetch-Site headers are not set for http requests, only https
24
+ # requests, so this doesn't offer protection for http requests.
25
+ #
26
+ # * It isn't possible to share a CSRF secret between applications in
27
+ # different origins to allow cross-site requests between the
28
+ # applications.
29
+ #
30
+ # This plugin adds the +check_sec_fetch_site!+ method to the routing
31
+ # block scope. You should call this method at the appropriate place
32
+ # in the routing tree to enforce the CSRF protection. The method can
33
+ # accept a block to override the :csrf_failure plugin option behavior
34
+ # on a per-call basis.
35
+ #
36
+ # When loading the plugin with no options:
37
+ #
38
+ # plugin :sec_fetch_site_csrf
39
+ #
40
+ # Only same-origin requests are allowed by default.
41
+ #
42
+ # This plugin supports the following options:
43
+ #
44
+ # :allow_missing :: Whether to allow requests lacking the Sec-Fetch-Site
45
+ # header (false by default).
46
+ # :allow_none :: Whether to allow requests where Sec-Fetch-Value is none
47
+ # (false by default).
48
+ # :allow_same_site :: Whether to allow requests where Sec-Fetch-Value is
49
+ # same-site (false by default)
50
+ # :check_request_methods :: Which request methods require CSRF protection
51
+ # (default: <tt>['POST', 'DELETE', 'PATCH', 'PUT']</tt>)
52
+ # :csrf_failure :: The action to taken if a request does not have a valid header
53
+ # (default: :raise). Options:
54
+ # :raise :: raise a Roda::RodaPlugins::SecFetchSiteCsrf::CsrfFailure
55
+ # exception
56
+ # :empty_403 :: return a blank 403 page
57
+ # :clear_session :: clear the current session
58
+ #
59
+ # The plugin also supports a block, in which case failures will call the block
60
+ # as a routing block (the block should accept the request object).
61
+ module SecFetchSiteCsrf
62
+ DEFAULTS = {
63
+ :csrf_failure => :raise,
64
+ :check_request_methods => %w'POST DELETE PATCH PUT'.freeze.each(&:freeze)
65
+ }.freeze
66
+
67
+ # Exception class raised when :csrf_failure option is :raise and
68
+ # the Sec-Fetch-Site header is not considered valid.
69
+ class CsrfFailure < RodaError; end
70
+
71
+ def self.configure(app, opts=OPTS, &block)
72
+ options = app.opts[:sec_fetch_site_csrf] = (app.opts[:sec_fetch_site_csrf] || DEFAULTS).merge(opts)
73
+
74
+ allowed_values = options[:allowed_values] = ["same-origin"]
75
+ allowed_values << "same-site" if opts[:allow_same_site]
76
+ allowed_values << "none" if opts[:allow_none]
77
+ allowed_values << nil if opts[:allow_missing]
78
+ allowed_values.freeze
79
+
80
+ if block
81
+ options[:csrf_failure] = :method
82
+ app.define_roda_method(:_roda_sec_fetch_site_csrf_failure, 1, &app.send(:convert_route_block, block))
83
+ end
84
+
85
+ case options[:csrf_failure]
86
+ when :raise, :empty_403, :clear_session, :method
87
+ # nothing
88
+ else
89
+ raise RodaError, "Unsupported :csrf_failure plugin option: #{options[:csrf_failure].inspect}"
90
+ end
91
+
92
+ options.freeze
93
+ end
94
+
95
+ module InstanceMethods
96
+ # Check that the Sec-Fetch-Site header is valid, if the request requires it.
97
+ # If the header is valid or the request does not require the header, return nil.
98
+ # Otherwise, if a block is given, treat it as a routing block and yield to it, and
99
+ # if a block is not given, use the plugin :csrf_failure option to determine how to
100
+ # handle it.
101
+ def check_sec_fetch_site!(&block)
102
+ plugin_opts = self.class.opts[:sec_fetch_site_csrf]
103
+ return unless plugin_opts[:check_request_methods].include?(request.request_method)
104
+
105
+ sec_fetch_site = env["HTTP_SEC_FETCH_SITE"]
106
+ return if plugin_opts[:allowed_values].include?(sec_fetch_site)
107
+
108
+ @_request.on(&block) if block
109
+
110
+ case failure_action = plugin_opts[:csrf_failure]
111
+ when :raise
112
+ raise CsrfFailure, "potential cross-site request, Sec-Fetch-Site value: #{sec_fetch_site.inspect}"
113
+ when :empty_403
114
+ @_response.status = 403
115
+ headers = @_response.headers
116
+ headers.clear
117
+ headers[RodaResponseHeaders::CONTENT_TYPE] = 'text/html'
118
+ headers[RodaResponseHeaders::CONTENT_LENGTH] ='0'
119
+ throw :halt, @_response.finish_with_body([])
120
+ when :clear_session
121
+ session.clear
122
+ else # when :method
123
+ @_request.on{_roda_sec_fetch_site_csrf_failure(@_request)}
124
+ end
125
+ end
126
+ end
127
+ end
128
+
129
+ register_plugin(:sec_fetch_site_csrf, SecFetchSiteCsrf)
130
+ end
131
+ end
@@ -0,0 +1,127 @@
1
+ # frozen-string-literal: true
2
+
3
+ begin
4
+ require 'rack/files'
5
+ rescue LoadError
6
+ require 'rack/file'
7
+ end
8
+
9
+ #
10
+ class Roda
11
+ module RodaPlugins
12
+ # The send_file plugin adds a send_file method, used for
13
+ # returning the contents of a file as the body of a request.
14
+ # It also loads the response_attachment plugin to set the
15
+ # Content-Disposition and Content-Type based on the file's
16
+ # extension.
17
+ #
18
+ # senf_file will serve the file with the given path from the file system:
19
+ #
20
+ # send_file 'path/to/file.txt'
21
+ #
22
+ # Options:
23
+ #
24
+ # :disposition :: Set the Content-Disposition to the given disposition.
25
+ # :filename :: Set the Content-Disposition to attachment (unless :disposition is set),
26
+ # and set the filename parameter to the value.
27
+ # :last_modified :: Explicitly set the Last-Modified header to the given value, and
28
+ # return a not modified response if there has not been modified since
29
+ # the previous request. This option requires the caching plugin.
30
+ # :status :: Override the status for the response.
31
+ # :type :: Set the Content-Type to use for this response.
32
+ #
33
+ # == License
34
+ #
35
+ # The implementation was originally taken from Sinatra,
36
+ # which is also released under the MIT License:
37
+ #
38
+ # Copyright (c) 2007, 2008, 2009 Blake Mizerany
39
+ # Copyright (c) 2010, 2011, 2012, 2013, 2014 Konstantin Haase
40
+ #
41
+ # Permission is hereby granted, free of charge, to any person
42
+ # obtaining a copy of this software and associated documentation
43
+ # files (the "Software"), to deal in the Software without
44
+ # restriction, including without limitation the rights to use,
45
+ # copy, modify, merge, publish, distribute, sublicense, and/or sell
46
+ # copies of the Software, and to permit persons to whom the
47
+ # Software is furnished to do so, subject to the following
48
+ # conditions:
49
+ #
50
+ # The above copyright notice and this permission notice shall be
51
+ # included in all copies or substantial portions of the Software.
52
+ #
53
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
54
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
55
+ # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
56
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
57
+ # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
58
+ # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
59
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
60
+ # OTHER DEALINGS IN THE SOFTWARE.
61
+ module SendFile
62
+ RACK_FILES = defined?(Rack::Files) ? Rack::Files : Rack::File
63
+
64
+ # Depend on the status_303 plugin.
65
+ def self.load_dependencies(app)
66
+ app.plugin :response_attachment
67
+ end
68
+
69
+ module InstanceMethods
70
+ # Use the contents of the file at +path+ as the response body. See plugin documentation for options.
71
+ def send_file(path, opts = OPTS)
72
+ r = @_request
73
+ res = @_response
74
+ headers = res.headers
75
+ if (type = opts[:type]) || !headers[RodaResponseHeaders::CONTENT_TYPE]
76
+ type_str = type.to_s
77
+
78
+ if type_str.include?('/')
79
+ type = type_str
80
+ else
81
+ if type
82
+ type = ".#{type}" unless type_str.start_with?(".")
83
+ else
84
+ type = ::File.extname(path)
85
+ end
86
+
87
+ type &&= Rack::Mime.mime_type(type, nil)
88
+ type ||= 'application/octet-stream'
89
+ end
90
+
91
+ headers[RodaResponseHeaders::CONTENT_TYPE] = type
92
+ end
93
+
94
+ disposition = opts[:disposition]
95
+ filename = opts[:filename]
96
+ if disposition || filename
97
+ disposition ||= 'attachment'
98
+ filename = path if filename.nil?
99
+ res.attachment(filename, disposition)
100
+ end
101
+
102
+ if lm = opts[:last_modified]
103
+ r.last_modified(lm)
104
+ end
105
+
106
+ file = RACK_FILES.new nil
107
+ s, h, b = if Rack.release > '2'
108
+ file.serving(r, path)
109
+ else
110
+ file.path = path
111
+ file.serving(env)
112
+ end
113
+
114
+ res.status = opts[:status] || s
115
+ headers.delete(RodaResponseHeaders::CONTENT_LENGTH)
116
+ headers.replace(h.merge!(headers))
117
+ r.halt res.finish_with_body(b)
118
+ rescue Errno::ENOENT
119
+ response.status = 404
120
+ r.halt
121
+ end
122
+ end
123
+ end
124
+
125
+ register_plugin(:send_file, SendFile)
126
+ end
127
+ end