1 $:.unshift File.join(File.dirname(__FILE__), 'lib')
9 require 'coquelicot/configure'
10 require 'haml_gettext'
15 @lockfile ||= Lockfile.new "#{File.expand_path(@path)}.lock", :timeout => 4
20 yield @initial_content
21 @initial_content = nil
22 until (buf = @file.read(BUFFER_LEN)).nil?
23 yield @cipher.update(buf)
44 (class << self; Application; end)
47 @depot = Depot.new(settings.depot_path) if @depot.nil? || settings.depot_path != @depot.path
52 class Application < Sinatra::Base
53 set :app_file, __FILE__
54 include Coquelicot::Configure
56 GetText::bindtextdomain('coquelicot')
58 GetText::set_current_locale(params[:lang] || request.env['HTTP_ACCEPT_LANGUAGE'] || 'en')
66 content_type 'text/css', :charset => 'utf-8'
75 "#{Coquelicot.gen_random_pass}"
78 get '/ready/:link' do |link|
79 not_found if link.nil?
81 link, pass = link.split '-' if link.include? '-'
83 file = Coquelicot.depot.get_file(link, nil)
84 rescue Errno::ENOENT => ex
87 @expire_at = file.expire_at
88 @base = request.url.gsub(/\/ready\/[^\/]*$/, '')
94 @url = "#{@base}/#{@name}"
98 post '/authenticate' do
99 pass unless request.xhr?
100 unless authenticate(params) then
101 error 403, "Forbidden"
107 # if JS is disabled upload_token might be nil
108 params['upload_token'] = JSON.parse(params['upload_token']) unless params['upload_token'].nil?
109 unless authenticate(params) then
110 error 403, "Forbidden"
112 if params[:file] then
113 tmpfile = params[:file][:tempfile]
114 name = params[:file][:filename]
116 if tmpfile.nil? || name.nil? then
117 @error = "No file selected"
120 if tmpfile.lstat.size == 0 then
121 @error = "#{name} is empty"
124 if params[:expire].nil? or params[:expire].to_i == 0 then
125 params[:expire] = settings.default_expire
126 elsif params[:expire].to_i > settings.maximum_expire then
129 expire_at = Time.now + 60 * params[:expire].to_i
130 one_time_only = params[:one_time] and params[:one_time] == 'true'
131 if params[:file_key].nil? or params[:file_key].empty?then
132 pass = Coquelicot.gen_random_pass
134 pass = params[:file_key]
136 src = params[:file][:tempfile]
137 link = Coquelicot.depot.add_file(
139 { "Expire-at" => expire_at.to_i,
140 "One-time-only" => one_time_only,
141 "Filename" => params[:file][:filename],
142 "Length" => src.stat.size,
143 "Content-Type" => params[:file][:type],
145 redirect "ready/#{link}-#{pass}" if params[:file_key].nil? or params[:file_key].empty?
146 redirect "ready/#{link}"
150 throw :halt, [410, haml(:expired)]
153 def send_stored_file(file)
154 last_modified file.created_at.httpdate
155 attachment file.meta['Filename']
156 response['Content-Length'] = "#{file.meta['Length']}"
157 response['Content-Type'] = file.meta['Content-Type'] || 'application/octet-stream'
158 throw :halt, [200, file]
161 def send_link(link, pass)
162 file = Coquelicot.depot.get_file(link, pass)
163 return false if file.nil?
164 return expired if file.expired?
166 if file.one_time_only?
168 # unlocking done in file.close
170 rescue Lockfile::TimeoutLockError
171 error 409, "Download currently in progress"
174 send_stored_file(file)
177 get '/:link-:pass' do |link, pass|
178 not_found if link.nil? || pass.nil?
180 link = Coquelicot.remap_base32_extra_characters(link)
181 pass = Coquelicot.remap_base32_extra_characters(pass)
182 not_found unless send_link(link, pass)
185 get '/:link' do |link|
186 not_found if link.nil?
188 link = Coquelicot.remap_base32_extra_characters(link)
189 not_found unless Coquelicot.depot.file_exists? link
194 post '/:link' do |link|
195 pass = params[:file_key]
196 return 403 if pass.nil? or pass.empty?
198 # send Forbidden even if file is not found
199 return 403 unless send_link(link, pass)
200 rescue Coquelicot::BadKey => ex
207 url = request.scheme + "://"
209 if request.scheme == "https" && request.port != 443 ||
210 request.scheme == "http" && request.port != 80
211 url << ":#{request.port}"
213 url << request.script_name
218 settings.respond_to?(:clone_url) ? settings.clone_url : "#{base_href}coquelicot.git"
222 Coquelicot.settings.auth_method
228 Coquelicot::Application.run! if __FILE__ == $0