change StoredFile.create interface
[coquelicot.git] / lib / coquelicot / app.rb
index d876fff..961c5b4 100644 (file)
@@ -1,9 +1,28 @@
+# Coquelicot: "one-click" file sharing with a focus on users' privacy.
+# Copyright © 2010-2012 potager.org <jardiniers@potager.org>
+#           © 2011 mh / immerda.ch <mh+coquelicot@immerda.ch>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+require 'lockfile'
 require 'sinatra/base'
+require 'sinatra/config_file'
 require 'haml'
+require 'haml/magic_translations'
 require 'sass'
 require 'digest/sha1'
-require 'gettext'
-require 'haml_gettext'
+require 'fast_gettext'
 
 module Coquelicot
   class << self
@@ -17,12 +36,29 @@ module Coquelicot
   end
 
   class Application < Sinatra::Base
-    set :root, Proc.new { app_file && File.expand_path('../../..', app_file) }
-    include Coquelicot::Configure
+    register Sinatra::ConfigFile
+    register Coquelicot::Auth::Extension
 
-    GetText::bindtextdomain('coquelicot')
+    set :root, Proc.new { app_file && File.expand_path('../../..', app_file) }
+    set :depot_path, Proc.new { File.join(root, 'files') }
+    set :default_expire, 60
+    set :maximum_expire, 60 * 24 * 30 # 1 month
+    set :gone_period, 60 * 24 * 7 # 1 week
+    set :filename_length, 20
+    set :random_pass_length, 16
+    set :about_text, ''
+    set :additional_css, ''
+    set :authentication_method, :name => :simplepass,
+                                :upload_password => 'a94a8fe5ccb19ba61c4c0873d391e987982fbbd3'
+
+    config_file File.expand_path('../../../conf/settings.yml', __FILE__)
+
+    FastGettext.add_text_domain 'coquelicot', :path => 'po', :type => 'po'
+    FastGettext.available_locales = [ 'en', 'fr', 'de' ]
+    Haml::MagicTranslations.enable(:fast_gettext)
     before do
-      GetText::set_current_locale(params[:lang] || request.env['HTTP_ACCEPT_LANGUAGE'] || 'en')
+      FastGettext.text_domain = 'coquelicot'
+      FastGettext.locale = params[:lang] || request.env['HTTP_ACCEPT_LANGUAGE'] || 'en'
     end
 
     not_found do
@@ -52,30 +88,36 @@ module Coquelicot
         not_found
       end
       @expire_at = file.expire_at
-      @base = request.url.gsub(/\/ready\/[^\/]*$/, '')
       @name = "#{link}"
       unless pass.nil?
         @name << "-#{pass}"
         @unprotected = true
       end
-      @url = "#{@base}/#{@name}"
+      @url = uri(@name)
       haml :ready
     end
 
     post '/authenticate' do
       pass unless request.xhr?
-      unless authenticate(params) then
-        error 403, "Forbidden"
+      begin
+        unless authenticate(params)
+          error 403, "Forbidden"
+        end
+        'OK'
+      rescue Coquelicot::Auth::Error => ex
+        error 503, ex.message
       end
-      'OK'
     end
 
     post '/upload' do
-      # if JS is disabled upload_token might be nil
-      params['upload_token'] = JSON.parse(params['upload_token']) unless params['upload_token'].nil?
-      unless authenticate(params) then
-        error 403, "Forbidden"
+      begin
+        unless authenticate(params)
+          error 403, "Forbidden"
+        end
+      rescue Coquelicot::Auth::Error => ex
+        error 503, ex.message
       end
+
       if params[:file] then
         tmpfile = params[:file][:tempfile]
         name = params[:file][:filename]
@@ -101,16 +143,17 @@ module Coquelicot
         pass = params[:file_key]
       end
       src = params[:file][:tempfile]
+      src.rewind
       link = Coquelicot.depot.add_file(
-         src, pass,
+         pass,
          { "Expire-at" => expire_at.to_i,
            "One-time-only" => one_time_only,
            "Filename" => params[:file][:filename],
            "Length" => src.stat.size,
            "Content-Type" => params[:file][:type],
-         })
-      redirect "ready/#{link}-#{pass}" if params[:file_key].nil? or params[:file_key].empty?
-      redirect "ready/#{link}"
+         }) { src.eof? ? nil : src.read }
+      redirect to("/ready/#{link}-#{pass}") if params[:file_key].nil? or params[:file_key].empty?
+      redirect to("/ready/#{link}")
     end
 
     def expired
@@ -170,19 +213,8 @@ module Coquelicot
     end
 
     helpers do
-      def base_href
-        url = request.scheme + "://"
-        url << request.host
-        if request.scheme == "https" && request.port != 443 ||
-            request.scheme == "http" && request.port != 80
-          url << ":#{request.port}"
-        end
-        url << request.script_name
-        "#{url}/"
-      end
-
       def clone_url
-        settings.respond_to?(:clone_url) ? settings.clone_url : "#{base_href}coquelicot.git"
+        settings.respond_to?(:clone_url) ? settings.clone_url : uri('coquelicot.git')
       end
 
       def authenticate(params)