omnifiles 0.1.0 → 0.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6168535895fcefcd6125d84d87fd2deba8161d36
4
- data.tar.gz: 435bc5685890875c42eeaaeb89a76b1f259da2c9
3
+ metadata.gz: 10d0e6b7d9a8c8ba27681ce9726d63baf309c22e
4
+ data.tar.gz: 33e13a6d786009124e6312d6a26cd9872fcb50e8
5
5
  SHA512:
6
- metadata.gz: 2d68c691076c59bc970367d9c8b325c15f38ce4f1b1f74bf757b0409bea74d6bce83089b6305e903a17b08e38b7f321b99c71b4f02d8c59591613b368fe3501c
7
- data.tar.gz: 20146b39ff0cff35866da53a4c35492a1b9abf5df4b642cc50c4d2e146eda110ed7b5d01f0efde14b437cd63807854035f77cf3de90b2c0541f58616385038d2
6
+ metadata.gz: cebc8b5441cbd3d053a7d0465e7867a20d96f5894b1d8090f7ad031123a6bc494388e44552e295cc0abc0f0e1323f90268c935e4f98085b64377308158d27d51
7
+ data.tar.gz: 41f1711c4d30660f493fcec462beca32fabacf7f6827defb1bedaeef147548572bc4ede0e15d8ff9fdc291b36dfb6e67ba36368a36b831e4c9069b9165214dbc
data/README.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # OmniFiles
2
2
 
3
+ [![Gem Version](https://img.shields.io/gem/v/omnifiles.svg)](https://rubygems.org/gems/omnifiles)
4
+ [![Code Climate](https://codeclimate.com/github/theirix/omnifiles/badges/gpa.svg)](https://codeclimate.com/github/theirix/omnifiles)
5
+ [![Dependency Status](https://gemnasium.com/theirix/omnifiles.svg)](https://gemnasium.com/theirix/omnifiles)
6
+
3
7
  File storage and shortener server.
4
8
 
5
9
  OmniFiles is built with Sinatra and Rack and uses an sqlite database to store shortened
@@ -15,15 +19,14 @@ OmniFiles is a Rack application and can be used as a gem or as a server in local
15
19
 
16
20
  gem install omnifiles
17
21
 
18
- 2. Create a settings file `/path/to/settings.yaml` by copying `config/settings.yaml.example`.
19
- Location of file must be specified in env variable `OMNIFILES_SETTINGS`.
22
+ 2. Point an env variable `OMNIFILES_SETTINGS` to location of a settings file `/path/to/settings.yaml` (see Configurarion).
20
23
 
21
24
  3. Start an app as a Thin server
22
25
 
23
26
  OMNIFILES_SETTINGS=/path/to/settings.yaml omnifiles
24
27
  Of course, you can provide any additional Thin options:
25
28
 
26
- OMNIFILES_SETTINGS=/path/to/settings.yaml omnifiles -l /var/log/omnifiles.log -P /var/run/omnifiles.pid -d
29
+ OMNIFILES_SETTINGS=/path/to/settings.yaml omnifiles -p 3000
27
30
 
28
31
  ## As a rack app
29
32
 
@@ -35,20 +38,36 @@ OmniFiles can be started using `config.ru` with you favourite Rack server.
35
38
 
36
39
  bundle install
37
40
 
38
- 3. Create a settings file `/path/to/settings.yaml` by copying `config/settings.yaml.example`.
39
- Location of file must be specified in env variable `OMNIFILES_SETTINGS`.
41
+ 3. Point an env variable `OMNIFILES_SETTINGS` to location of a settings file `/path/to/settings.yaml` (see Configurarion).
40
42
 
41
43
  4. Start Rack app
42
44
 
43
45
  rackup
44
46
 
47
+ ## Configuration
48
+
49
+ Settings file template can be found at `config/settings.yaml.example`.
50
+
51
+ If you prefer production Rack environment, please use `production` instead of `development` section in the config.
52
+ Also specify `-E production` at `omnifiles` (actially Thin) command line.
53
+
54
+ If you prefer to run omnifiles as a daemon, don't forget to set log and pid location. Author prefer to follow XDG and place all the files at the `~/.local/share/omnifiles`, including the database. So one can use following command line:
55
+
56
+ OMNIFILES_SETTINGS=$HOME/.local/share/omnifiles/settings.yaml omnifiles -d -a 127.0.0.1 -p 3000 \
57
+ -l $HOME/.local/share/omnifiles/omnifiles.log \
58
+ -P $HOME/.local/share/omnifiles/omnifiles.pid
59
+
45
60
  ## Usage
46
61
 
47
62
  1. Storing files.
48
- OmniFiles can store files by issuing an authenticated POST request
63
+ OmniFiles can store files by issuing an authenticated POST form request:
49
64
 
50
65
  % curl --digest -u user:secret -F "file=@/path/to/file.jpg" 'http://localhost:3000/store'
51
66
  http://localhost:3000/f/e63A12
67
+ Or you can post a file just as a binary POST data:
68
+
69
+ % curl --digest -u user:secret -H "Content-Type: application/octet-stream" --data-binary "@/path/to/file.jpg" 'http://localhost:3000/store'
70
+ http://localhost:3000/f/e63A12
52
71
  OmniFiles returns a short url in response so you can just issue following command to save URL in clipboard
53
72
 
54
73
  % curl --digest -u user:secret -F "file=@/path/to/file.jpg" 'http://localhost:3000/store' | pbcopy
@@ -69,4 +88,4 @@ using web browser or curl
69
88
 
70
89
  ## License information
71
90
 
72
- Please consult with the LICENSE.txt for license information.
91
+ Please consult with the LICENSE.txt for license information. It is MIT by the way.
@@ -1,5 +1,5 @@
1
1
  development:
2
- storage_dir: /var/lib/omnifiles/storage
3
- db: /var/lib/omnifiles/omnifiles.sqlite3
2
+ storage_dir: storage
3
+ db: omnifiles.sqlite3
4
4
  auth_opaque: alongopaquekey
5
5
  auth_password: secret
@@ -3,6 +3,7 @@
3
3
  require 'sinatra'
4
4
  require 'filemagic'
5
5
  require 'uri'
6
+ require 'tempfile'
6
7
  require 'settingslogic'
7
8
  require 'haml'
8
9
  require 'rack'
@@ -42,7 +43,11 @@ module OmniFiles
42
43
  halt 404, "File not found" unless data
43
44
 
44
45
  @url = url('/f/'+name)
45
- @original_filename = URI.unescape data['original_filename']
46
+ if data['original_filename']
47
+ @original_filename = URI.unescape data['original_filename']
48
+ else
49
+ @original_filename = "<i>Not provided</i>"
50
+ end
46
51
  @access_count = data['accessed']
47
52
  @mime = data['mime']
48
53
  @shortened = name
@@ -50,33 +55,33 @@ module OmniFiles
50
55
  haml :stat
51
56
  end
52
57
 
58
+ # POST handler with form/body handling
53
59
  def store_file
54
60
  logger.info "Route POST store"
55
61
  begin
56
62
  req = Rack::Request.new(env)
57
- post_file = req.POST['file']
58
- original_filename = URI.escape(File.basename(post_file[:filename]))
59
-
60
- temp_file = post_file[:tempfile]
63
+ if !req.POST || req.POST == {}
64
+ logger.info "Saving POST body to temp file"
61
65
 
62
- # Determine file mime and desired url
63
- mime = FileMagic.mime.file temp_file.path
66
+ original_filename = nil
64
67
 
65
- # Short URL is composed from escaped filename from form, mime type and leading file bytes
66
- shortened = @storage.shorten_file temp_file.path, original_filename, mime
68
+ # Make a temp file with body content
69
+ temp_file = Tempfile.new("omnifiles-post-")
70
+ File.open(temp_file.path, 'wb') do |ftemp|
71
+ IO.copy_stream(req.body, ftemp)
72
+ end
73
+ else
74
+ logger.info "Using POST form"
67
75
 
68
- # Save file to storage
69
- target_path = File.join(Settings.storage_dir, shortened)
70
- raise "Not so unique id #{shortened}" if File.exists? target_path
71
- FileUtils.cp temp_file.path, target_path
76
+ # Use a Rack provided file with content
77
+ post_file = req.POST['file']
78
+ original_filename = URI.escape(File.basename(post_file[:filename]))
72
79
 
73
- # Put record to storage
74
- @storage.put_file shortened, original_filename, mime
75
- short_url = url('/f/'+shortened)
80
+ temp_file = post_file[:tempfile]
81
+ end
76
82
 
77
- logger.info "Stored file #{target_path} to shortened #{shortened}, magic '#{mime}'"
83
+ store_with_file temp_file.path, original_filename
78
84
 
79
- short_url
80
85
  ensure
81
86
  if temp_file
82
87
  temp_file.close
@@ -85,6 +90,31 @@ module OmniFiles
85
90
  end
86
91
  end
87
92
 
93
+ # Save temporary file to storage
94
+ def store_with_file path, original_filename
95
+ # Take a sample of file
96
+ sample = Digest::MD5.hexdigest(IO.binread(path, 0x100))
97
+
98
+ # Determine file mime and desired url
99
+ mime = FileMagic.mime.file path
100
+
101
+ # Short URL is composed from escaped filename from form, mime type and leading file bytes
102
+ shortened = @storage.shorten_file sample, original_filename, mime
103
+
104
+ # Save file to storage
105
+ target_path = File.join(Settings.storage_dir, shortened)
106
+ raise "Not so unique id #{shortened}" if File.exists? target_path
107
+ FileUtils.cp path, target_path
108
+
109
+ # Put record to storage
110
+ @storage.put_file shortened, original_filename, mime
111
+ short_url = url('/f/'+shortened)
112
+
113
+ logger.info "Stored file #{target_path} to shortened #{shortened}, magic '#{mime}'"
114
+
115
+ short_url
116
+ end
117
+
88
118
  end
89
119
 
90
120
  end
@@ -30,7 +30,9 @@ module OmniFiles
30
30
 
31
31
  logger.info "Data #{data}, file #{path}, was at #{filename}"
32
32
 
33
- headers 'X-Original-Filename' => filename
33
+ if filename && !filename.empty?
34
+ headers 'X-Original-Filename' => filename
35
+ end
34
36
  send_file path, :type => mime
35
37
  end
36
38
 
@@ -18,10 +18,11 @@ module OmniFiles
18
18
  end
19
19
 
20
20
  # returns shortened url
21
- def shorten_file path, filename, mime
21
+ def shorten_file sample, filename, mime
22
22
  counter = 0
23
23
  begin
24
- hashing = [filename, mime, Digest::MD5.hexdigest(IO.binread(path, 0x100)), counter.to_s].join '|'
24
+ # filename can be null
25
+ hashing = [filename.to_s, mime, sample, counter.to_s].join '|'
25
26
  @logger.info "Hashing value " + hashing
26
27
  shortened = @shortener.shorten hashing
27
28
  counter += 1
@@ -1,3 +1,3 @@
1
1
  module OmniFiles
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: omnifiles
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - theirix
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-05 00:00:00.000000000 Z
11
+ date: 2015-01-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler