/usr/lib/ruby/vendor_ruby/upr/input_wrapper.rb is in ruby-upr 0.3.0-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | # -*- encoding: binary -*-
module Upr
# the underlying middlware for for wrapping env["rack.input"],
# this should typically be installed before other middlewares
# that may wrap env["rack.input"] in the middleware chain.
class InputWrapper < Struct.new(:app, :path_info, :frequency, :backend,
:input, :pos, :seen, :content_length,
:upload_id, :mtime)
include Params
def initialize(app, options = {})
super(app,
Array(options[:path_info] || nil),
options[:frequency] || 1,
options[:backend])
# support :drb for compatibility with mongrel_upload_progress
if options[:drb]
backend and raise ArgumentError, ":backend and :drb are incompatible"
require 'drb'
DRb.start_service
self.backend = DRbObject.new(nil, options[:drb])
elsif String === backend
# allow people to use strings in case their backend gets
# lazy-loaded (like an ActiveRecord model)
self.backend = eval(backend)
else
self.backend ||= Upr::Monitor.new
end
end
def call(env)
if path_info.empty? || path_info.include?(env["PATH_INFO"])
# benefit curl users...
/\A100-continue\z/i =~ env['HTTP_EXPECT'] and return [ 100, {}, [] ]
length = env["CONTENT_LENGTH"] and length = length.to_i
chunked = env["TRANSFER_ENCODING"] =~ %r{\Achunked\z}i and length = nil
if chunked || (length && length > 0)
if uid = extract_upload_id(env)
return dup._call(env, uid, length)
end
end
end
app.call(env)
end
def _call(env, uid, length)
self.upload_id = uid
self.mtime = self.pos = self.seen = 0
self.input = env["rack.input"]
env["rack.input"] = self
self.content_length = length
backend.start(upload_id, length)
app.call(env)
end
def _incr(nr)
self.pos += nr
_finish if content_length && pos >= content_length
if (nr = pos - seen) > 0 && mtime <= (Time.now.to_i - frequency)
backend.incr(upload_id, nr)
self.seen = pos
self.mtime = Time.now.to_i
end
end
def _finish
self.seen = backend.finish(upload_id).seen
self.content_length ||= self.seen
end
def size
rv = input.size
# we had an unknown length and just had to read in everything to get it
if content_length.nil?
_incr(rv - seen)
_finish
end
rv
end
def rewind
self.pos = 0
input.rewind
end
def gets
rv = input.gets
rv.nil? ? _finish : _incr(rv.size)
rv
end
def read(*args)
rv = input.read(*args)
rv.nil? || rv.size == 0 ? _finish : _incr(rv.size)
rv
end
def each(&block)
input.each do |chunk| # usually just a line
_incr(chunk.size)
yield chunk
end
_finish
end
end
end
|