pasu 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 3127e891fee1f5bce7a3f057fcd05a7914b16893
4
+ data.tar.gz: 362104b819db149f78599e57fabfd57c70e4cfd2
5
+ SHA512:
6
+ metadata.gz: 1e30bbb27b83d64c8756f2698ee9dc6299d60b2ff283f75e9e88227f8208784543912545b34a88e9ace25d71ae872ec4c040fc2ffb15a0a05187b3ce07c35ab5
7
+ data.tar.gz: 5070ba9accab64dd258e31901b563d5e9503e4d319a922c3de36075e7a1889dfd3895559982d5d32c24946b95bf857e7c577997c8c2fce5364d744377e47f073
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Tobias Bühlmann
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,42 @@
1
+ # Pasu
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/pasu.png)](http://badge.fury.io/rb/pasu) [![Dependency Status](https://gemnasium.com/tbuehlmann/pasu.png)](https://gemnasium.com/tbuehlmann/pasu)
4
+
5
+ Pasu is a simple HTTP Server for serving (and uploading) Files.
6
+
7
+ ## Requirements
8
+ - Ruby ~> 2.0
9
+
10
+ ## Installation
11
+
12
+ ```sh
13
+ $ gem install pasu
14
+ ```
15
+
16
+ ## Usage
17
+
18
+ ```sh
19
+ $ pasu
20
+ ```
21
+
22
+ ### Options
23
+
24
+ | Option | Description | Default |
25
+ | --- | --- | --- |
26
+ | -v, --version | Print version. | |
27
+ | -d, --directory DIRECTORY | Set the base directory for listing files. | pwd |
28
+ | --no-recursion | Don't recursively list directories. | false |
29
+ | -u, --upload | Allow uploading of files. | false |
30
+ | --basic-auth USER:PW | Only allowing requests with valid user/pw combination provided. | None |
31
+ | -b, --bind HOST | Bind the server to the given host. | 0.0.0.0 |
32
+ | -p, --port PORT | Bind the server to the given port. | 8080 |
33
+ | -s, --server RACK_HANDLER | Use your own rack handler. | Puma |
34
+ | -h, --help | Show help message. |
35
+
36
+ ## Contributing
37
+
38
+ 1. Fork it (https://github.com/tbuehlmann/pasu/fork)
39
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
40
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
41
+ 4. Push to the branch (`git push origin my-new-feature`)
42
+ 5. Create new Pull Request
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'pasu'
4
+
5
+ runner = Pasu::Runner.new
6
+ runner.run
@@ -0,0 +1,14 @@
1
+ require 'optparse'
2
+ require 'pathname'
3
+
4
+ require 'cuba'
5
+ require 'cuba/render'
6
+ require 'cuba/send_file'
7
+ require 'puma'
8
+ require 'slim'
9
+
10
+ module Pasu
11
+ require 'pasu/application'
12
+ require 'pasu/runner'
13
+ require 'pasu/version'
14
+ end
@@ -0,0 +1,171 @@
1
+ module Pasu
2
+ class Application < Cuba
3
+ plugin SendFile
4
+ plugin Cuba::Render
5
+
6
+ settings[:render][:template_engine] = 'slim'
7
+
8
+ class << self
9
+ def setup(options = {})
10
+ settings.merge!(default_settings)
11
+ settings.merge!(options)
12
+ setup_basic_auth
13
+ end
14
+
15
+ def default_settings
16
+ {
17
+ directory: Pathname.pwd,
18
+ recursive: true,
19
+ upload: false,
20
+ basic_auth: {},
21
+ host: '0.0.0.0',
22
+ port: 8080,
23
+ handler: 'Puma'
24
+ }
25
+ end
26
+
27
+ def run
28
+ rack_handler = Rack::Handler.get(settings[:handler])
29
+ rack_handler.run(
30
+ self,
31
+ Host: settings[:host],
32
+ Port: settings[:port],
33
+ Verbose: true
34
+ )
35
+ end
36
+
37
+ private
38
+
39
+ def setup_basic_auth
40
+ if settings[:basic_auth].any?
41
+ use Rack::Auth::Basic do |username, password|
42
+ settings[:basic_auth][username] == password
43
+ end
44
+ end
45
+ end
46
+ end
47
+
48
+ define do
49
+ on /(.*)/ do |escaped_path|
50
+ @path = unescape_path(escaped_path)
51
+
52
+ on get do
53
+ on file do
54
+ send_file(@path)
55
+ end
56
+
57
+ on directory do
58
+ @files = children(@path)
59
+ res.write view(:directory)
60
+ end
61
+
62
+ on file_not_found do
63
+ res.status = 404
64
+ res.write view(:file_not_found)
65
+ end
66
+ end
67
+
68
+ on post do
69
+ on upload_allowed do
70
+ on directory do
71
+ on param(:file) do |file|
72
+ save_file(@path, file)
73
+ res.redirect escape_path(@path.relative_path_from(settings[:directory]))
74
+ end
75
+
76
+ on no_file_attached do
77
+ res.status = 400
78
+ res.write view(:no_file_attached)
79
+ end
80
+ end
81
+
82
+ on directory_not_found do
83
+ res.status = 404
84
+ res.write view(:directory_not_found)
85
+ end
86
+ end
87
+
88
+ on upload_not_allowed do
89
+ res.status = 401
90
+ res.write view(:no_upload)
91
+ end
92
+ end
93
+ end
94
+ end
95
+
96
+ private
97
+
98
+ def escape_path(path)
99
+ file_names = path.each_filename.map do |file_name|
100
+ Rack::Utils.escape_path(file_name)
101
+ end.join('/')
102
+
103
+ file_names == '.' ? '/' : "/#{file_names}"
104
+ end
105
+
106
+ def unescape_path(escaped_path)
107
+ file_names = escaped_path.split('/').map do |file_name|
108
+ Rack::Utils.unescape(file_name)
109
+ end
110
+
111
+ settings[:directory].join(*file_names)
112
+ end
113
+
114
+ def children(path)
115
+ path.children.tap do |files|
116
+ files.select! { |file| (file.directory? || file.file?) && file.readable? }
117
+ files.sort_by! { |file| [file.ftype, file.basename] }
118
+
119
+ if settings[:recursive]
120
+ if path != settings[:directory]
121
+ files.unshift(path.parent)
122
+ end
123
+ else
124
+ files.select!(&:file?)
125
+ end
126
+ end
127
+ end
128
+
129
+ def directory
130
+ @path.directory? && @path.readable? && allowed_directory?(@path)
131
+ end
132
+
133
+ def file
134
+ @path.file? && @path.readable? && allowed_directory?(@path.parent)
135
+ end
136
+
137
+ def allowed_directory?(directory)
138
+ is_descendant = directory.ascend do |ascendant|
139
+ break(true) if ascendant == settings[:directory]
140
+ end
141
+
142
+ (settings[:recursive] || directory == settings[:directory]) && is_descendant
143
+ end
144
+
145
+ # TODO: wb correct?
146
+ def save_file(directory, file)
147
+ path = directory.join(file[:filename])
148
+ File.open(path, 'wb') { |f| f.write(file[:tempfile].read) }
149
+ end
150
+
151
+ def upload_allowed
152
+ settings[:upload]
153
+ end
154
+
155
+ def upload_not_allowed
156
+ true
157
+ end
158
+
159
+ def file_not_found
160
+ true
161
+ end
162
+
163
+ def directory_not_found
164
+ true
165
+ end
166
+
167
+ def no_file_attached
168
+ true
169
+ end
170
+ end
171
+ end
@@ -0,0 +1,73 @@
1
+ module Pasu
2
+ class Runner
3
+ def initialize
4
+ OptionParser.new do |p|
5
+ p.banner = 'Usage: pasu [options]'
6
+
7
+ p.separator ''
8
+ p.separator 'Options:'
9
+
10
+ p.on('-v', '--version', 'Print version.') do
11
+ puts "Pasu #{VERSION} (https://github.com/tbuehlmann/pasu)"
12
+ exit
13
+ end
14
+
15
+ p.on('-d', '--directory DIRECTORY', 'Set the base directory for listing files. (Default: pwd)') do |dir|
16
+ directory = Pathname.new(dir).expand_path
17
+
18
+ if directory.directory?
19
+ options[:directory] = directory
20
+ else
21
+ puts "Couldn't find directory #{dir}"
22
+ exit 1
23
+ end
24
+ end
25
+
26
+ p.on('--no-recursion', "Don't recursively list directories. (Default: false)") do
27
+ options[:recursive] = false
28
+ end
29
+
30
+ p.on('-u', '--upload', 'Allow uploading of files. (Default: false)') do
31
+ options[:upload] = true
32
+ end
33
+
34
+ p.on('--basic-auth USER:PW', 'Only allowing requests with valid user/pw combination provided. (Default: None)') do |access|
35
+ username, password = access.split(':')
36
+ options[:basic_auth] ||= {}
37
+ options[:basic_auth][username] = password
38
+ end
39
+
40
+ p.on('-b', '--bind HOST', 'Bind the server to the given host. (Default: 0.0.0.0)') do |host|
41
+ options[:host] = host
42
+ end
43
+
44
+ p.on('-p', '--port PORT', 'Bind the server to the given port. (Default: 8080)') do |port|
45
+ options[:port] = Integer(port)
46
+ end
47
+
48
+ p.on('-s', '--server RACK_HANDLER', 'Use your own rack handler. (Default: Puma)') do |handler|
49
+ options[:handler] = handler
50
+ end
51
+
52
+ p.on_tail('-h', '--help', 'Show this message.') do
53
+ puts p
54
+ exit
55
+ end
56
+ end.parse!
57
+ end
58
+
59
+ def options
60
+ @options ||= {}
61
+ end
62
+
63
+ def run
64
+ Pasu::Application.setup(options)
65
+
66
+ begin
67
+ Pasu::Application.run
68
+ rescue Errno::EADDRINUSE
69
+ puts "Port #{options[:port]} is already in use. Quitting."
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,3 @@
1
+ module Pasu
2
+ VERSION = Gem::Version.new('0.0.1')
3
+ end
@@ -0,0 +1,33 @@
1
+ # encoding: utf-8
2
+
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'pasu/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'pasu'
9
+ spec.version = Pasu::VERSION
10
+ spec.authors = ['Tobias Bühlmann']
11
+ spec.email = ['tobias.buehlmann@gmx.de']
12
+ spec.summary = 'Simple File Serving HTTP Server'
13
+ spec.description = 'Pasu is a simple HTTP Server for serving (and uploading) Files.'
14
+ spec.homepage = 'https://github.com/tbuehlmann/pasu'
15
+ spec.license = 'MIT'
16
+
17
+ spec.files = `git ls-files`.split("\n")
18
+ spec.executables = ['pasu']
19
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
+ spec.require_paths = ['lib']
21
+
22
+ spec.required_ruby_version = '~> 2.0'
23
+
24
+ spec.add_runtime_dependency 'cuba', '~> 3.1'
25
+ spec.add_runtime_dependency 'cuba-sendfile', '0.0.2'
26
+ spec.add_runtime_dependency 'slim', '~> 2.0'
27
+ spec.add_runtime_dependency 'tilt', '~> 2.0'
28
+ spec.add_runtime_dependency 'puma', '~> 2.7'
29
+
30
+ spec.add_development_dependency 'bundler', '~> 1.5'
31
+ spec.add_development_dependency 'rake', '~> 10.1'
32
+ spec.add_development_dependency 'pry', '0.9.12.6'
33
+ end
@@ -0,0 +1,12 @@
1
+ h1 Directory listing
2
+
3
+ - if settings[:upload]
4
+ form action=escape_path(@path.relative_path_from(settings[:directory])) method='POST' enctype="multipart/form-data"
5
+ input type='file' name='file'
6
+ input type='submit' value='Upload'
7
+
8
+ ul
9
+ - @files.each do |file|
10
+ li class=file.ftype
11
+ - text = file == @path.parent ? '..' : file.basename
12
+ a href=escape_path(file.relative_path_from(settings[:directory])) #{Rack::Utils.escape_html(text)}
@@ -0,0 +1 @@
1
+ h1 Directory not found
@@ -0,0 +1 @@
1
+ h1 File not found
@@ -0,0 +1,8 @@
1
+ doctype html
2
+ html
3
+ head
4
+ title Pasu
5
+ css:
6
+ body { font-family: Helvetica, Arial, sans-serif; }
7
+ body
8
+ == content
@@ -0,0 +1 @@
1
+ h1 No File attached
@@ -0,0 +1 @@
1
+ h1 Uploading files is not permitted
@@ -0,0 +1,4 @@
1
+ - if settings[:upload]
2
+ form action=escape(path.relative_path_from(settings[:directory])) method='POST'
3
+ input type='file' name='file'
4
+ input type='submit' value='Upload'
metadata ADDED
@@ -0,0 +1,174 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pasu
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Tobias Bühlmann
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-02-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: cuba
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: cuba-sendfile
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '='
32
+ - !ruby/object:Gem::Version
33
+ version: 0.0.2
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '='
39
+ - !ruby/object:Gem::Version
40
+ version: 0.0.2
41
+ - !ruby/object:Gem::Dependency
42
+ name: slim
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: tilt
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '2.0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '2.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: puma
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '2.7'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '2.7'
83
+ - !ruby/object:Gem::Dependency
84
+ name: bundler
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.5'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1.5'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rake
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '10.1'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '10.1'
111
+ - !ruby/object:Gem::Dependency
112
+ name: pry
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - '='
116
+ - !ruby/object:Gem::Version
117
+ version: 0.9.12.6
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - '='
123
+ - !ruby/object:Gem::Version
124
+ version: 0.9.12.6
125
+ description: Pasu is a simple HTTP Server for serving (and uploading) Files.
126
+ email:
127
+ - tobias.buehlmann@gmx.de
128
+ executables:
129
+ - pasu
130
+ extensions: []
131
+ extra_rdoc_files: []
132
+ files:
133
+ - ".gitignore"
134
+ - Gemfile
135
+ - LICENSE
136
+ - README.md
137
+ - bin/pasu
138
+ - lib/pasu.rb
139
+ - lib/pasu/application.rb
140
+ - lib/pasu/runner.rb
141
+ - lib/pasu/version.rb
142
+ - pasu.gemspec
143
+ - views/directory.slim
144
+ - views/directory_not_found.slim
145
+ - views/file_not_found.slim
146
+ - views/layout.slim
147
+ - views/no_file_attached.slim
148
+ - views/no_upload.slim
149
+ - views/upload.slim
150
+ homepage: https://github.com/tbuehlmann/pasu
151
+ licenses:
152
+ - MIT
153
+ metadata: {}
154
+ post_install_message:
155
+ rdoc_options: []
156
+ require_paths:
157
+ - lib
158
+ required_ruby_version: !ruby/object:Gem::Requirement
159
+ requirements:
160
+ - - "~>"
161
+ - !ruby/object:Gem::Version
162
+ version: '2.0'
163
+ required_rubygems_version: !ruby/object:Gem::Requirement
164
+ requirements:
165
+ - - ">="
166
+ - !ruby/object:Gem::Version
167
+ version: '0'
168
+ requirements: []
169
+ rubyforge_project:
170
+ rubygems_version: 2.2.0
171
+ signing_key:
172
+ specification_version: 4
173
+ summary: Simple File Serving HTTP Server
174
+ test_files: []