boxlet 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/boxlet +11 -8
- data/boxlet.gemspec +17 -9
- data/config.yml +29 -5
- data/lib/boxlet.rb +64 -24
- data/lib/boxlet/app.rb +133 -0
- data/lib/boxlet/app/controller.rb +168 -0
- data/lib/boxlet/app/router.rb +45 -0
- data/lib/boxlet/config.rb +119 -0
- data/lib/boxlet/db.rb +29 -0
- data/lib/boxlet/log.rb +1 -0
- data/lib/boxlet/runner.rb +37 -0
- data/lib/boxlet/version.rb +1 -1
- data/lib/handlers/thin.rb +34 -0
- data/lib/rack/boxlet_url_builder.rb +16 -0
- data/lib/rack/boxlet_url_map.rb +66 -0
- data/lib/rack/file_upload.rb +121 -0
- metadata +151 -27
- data/lib/boxlet/tcp_server.rb +0 -62
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6d5950f183d1274de5cd16237709c40ad58c65cf
|
4
|
+
data.tar.gz: 7ebc60f5a772512343f7d6778eb25ca227b2998f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 94c93357b399e5855256009dc8bd9edcd3c18d4537cca5fdb2927d773021570148292b2d081b4b0db34d02a261093fab7f43827d6b9387ec0d353dfdf9171b72
|
7
|
+
data.tar.gz: 0667cdd101c8ebaf9c0a34d2975d3ec573a3b0eff0a08fb24ebdff0714f765108927efbd233eeb3da861bb6093831161e94ada72394f63ae5f47c39758753857
|
data/bin/boxlet
CHANGED
@@ -1,12 +1,15 @@
|
|
1
|
-
|
1
|
+
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require
|
3
|
+
require 'boxlet'
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
argv = *ARGV
|
6
|
+
command = argv.count % 2 != 0 ? argv.shift : 'run'
|
7
|
+
argv_hash = Hash[*argv]
|
8
|
+
|
9
|
+
config = argv_hash["-c"] || argv_hash["--config"]
|
10
|
+
if !config
|
11
|
+
puts "WARNING: config file not specified, looking in current directory..."
|
12
|
+
config = 'config.yml'
|
9
13
|
end
|
10
14
|
|
11
|
-
|
12
|
-
server.run
|
15
|
+
Boxlet.run! argv_hash, command, config
|
data/boxlet.gemspec
CHANGED
@@ -6,22 +6,30 @@ require "boxlet/version"
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = "boxlet"
|
8
8
|
spec.version = Boxlet::VERSION
|
9
|
-
spec.authors = ["
|
9
|
+
spec.authors = ["arktisklada"]
|
10
10
|
spec.email = ["mail@enorganik.com"]
|
11
|
-
spec.
|
12
|
-
spec.
|
13
|
-
spec.homepage = "
|
11
|
+
spec.summary = %q{Upload pics from your phone}
|
12
|
+
spec.description = spec.summary
|
13
|
+
spec.homepage = "https://github.com/arktisklada/boxlet"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
16
|
-
# spec.files = `git ls-files`.split($/)
|
17
16
|
spec.files = %w[config.yml LICENSE.txt README.md Rakefile boxlet.gemspec]
|
18
17
|
spec.files += Dir.glob('lib/**/*.rb')
|
18
|
+
spec.files += Dir.glob('lib/boxlet/app/*.rb')
|
19
19
|
|
20
|
-
# spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
21
20
|
spec.executables = 'boxlet'
|
22
21
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
23
|
-
spec.require_paths =
|
22
|
+
spec.require_paths = ["lib"]
|
23
|
+
|
24
|
+
spec.add_dependency "rack", "~> 1.5"
|
25
|
+
spec.add_dependency "rack-contrib", "~> 1.1"
|
26
|
+
spec.add_dependency "thin", "~> 1.6"
|
27
|
+
|
28
|
+
spec.add_runtime_dependency 'multi_json', '~> 1.10', '>= 1.10.1'
|
29
|
+
spec.add_runtime_dependency 'mongo', '~> 1.10', '>= 1.10.2'
|
30
|
+
spec.add_runtime_dependency 'bson_ext', '~> 1.10', '>= 1.10.2'
|
31
|
+
spec.add_runtime_dependency 'sys-filesystem', '~> 1.1', '>= 1.1.2'
|
24
32
|
|
25
33
|
spec.add_development_dependency "bundler", "~> 1.3"
|
26
|
-
spec.add_development_dependency "rake"
|
27
|
-
end
|
34
|
+
spec.add_development_dependency "rake", "~> 10.3"
|
35
|
+
end
|
data/config.yml
CHANGED
@@ -1,8 +1,32 @@
|
|
1
1
|
# Boxlet configuration file
|
2
2
|
|
3
|
-
#
|
4
|
-
|
3
|
+
# Environment
|
4
|
+
environment: development
|
5
|
+
debug: true
|
5
6
|
|
6
|
-
#
|
7
|
-
|
8
|
-
|
7
|
+
# File system parameters
|
8
|
+
# path: ./
|
9
|
+
# upload_dir: ./uploads
|
10
|
+
# tmp_dir: /tmp
|
11
|
+
# file_system_root: /
|
12
|
+
|
13
|
+
# Capacity is either a percentage of available space on the drive or number in MB
|
14
|
+
capacity: 90%
|
15
|
+
|
16
|
+
# Server type and listen parameters
|
17
|
+
port: 8077
|
18
|
+
host: localhost
|
19
|
+
server_type: thin
|
20
|
+
daemonize: false
|
21
|
+
|
22
|
+
# Database config
|
23
|
+
db:
|
24
|
+
development:
|
25
|
+
host: localhost
|
26
|
+
db: boxlet_dev
|
27
|
+
production:
|
28
|
+
host: localhost
|
29
|
+
# port:
|
30
|
+
# user:
|
31
|
+
# pass:
|
32
|
+
db: boxlet
|
data/lib/boxlet.rb
CHANGED
@@ -1,33 +1,73 @@
|
|
1
|
-
require "fileutils"
|
2
1
|
require "yaml"
|
3
|
-
|
2
|
+
require "rack/contrib"
|
4
3
|
require "boxlet/version"
|
5
|
-
require "boxlet/
|
6
|
-
require "boxlet/
|
4
|
+
require "boxlet/app"
|
5
|
+
require "boxlet/config"
|
6
|
+
require "boxlet/runner"
|
7
|
+
require "pp" #unless ENV['RACK_ENV'] == 'production'
|
8
|
+
|
9
|
+
|
10
|
+
APP_ROOT = Dir.pwd
|
7
11
|
|
8
12
|
|
9
13
|
module Boxlet
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
end
|
19
|
-
|
20
|
-
@server = TcpServer.new
|
21
|
-
end
|
22
|
-
|
23
|
-
public
|
24
|
-
|
25
|
-
def self.config
|
26
|
-
return @@config
|
27
|
-
end
|
14
|
+
|
15
|
+
extend self
|
16
|
+
extend Boxlet::Config
|
17
|
+
|
18
|
+
attr_accessor :runner, :config, :raw_params, :raw_config
|
19
|
+
|
20
|
+
def run!(argv, command='run', config_file='config.yml', &blk)
|
21
|
+
populate_params!(argv, config_file)
|
28
22
|
|
29
|
-
|
30
|
-
|
23
|
+
app = Boxlet::App.new
|
24
|
+
|
25
|
+
case command
|
26
|
+
when 'run'
|
27
|
+
@runner = Boxlet::Runner.new
|
28
|
+
@runner.start(app.bind, &blk)
|
29
|
+
else
|
30
|
+
app.send(command, Boxlet.config)
|
31
31
|
end
|
32
|
+
|
33
|
+
app
|
34
|
+
end
|
35
|
+
|
36
|
+
def stop!
|
37
|
+
@runner.stop
|
38
|
+
app
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
def debug?
|
43
|
+
@config[:debug] == true ? true : false
|
44
|
+
end
|
45
|
+
|
46
|
+
def config
|
47
|
+
@config
|
48
|
+
end
|
49
|
+
|
50
|
+
def params
|
51
|
+
@params
|
32
52
|
end
|
53
|
+
|
33
54
|
end
|
55
|
+
|
56
|
+
|
57
|
+
# Configure our temporary folder
|
58
|
+
class Dir
|
59
|
+
def Dir::tmpdir
|
60
|
+
tmp = './tmp'
|
61
|
+
if $SAFE > 0
|
62
|
+
tmp = @@systmpdir
|
63
|
+
else
|
64
|
+
for dir in [ENV['TMPDIR'], ENV['TMP'], ENV['TEMP'], @@systmpdir, '/tmp']
|
65
|
+
if dir and stat = File.stat(dir) and stat.directory? and stat.writable?
|
66
|
+
tmp = dir
|
67
|
+
break
|
68
|
+
end rescue nil
|
69
|
+
end
|
70
|
+
File.expand_path(tmp)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/lib/boxlet/app.rb
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
require "sys/filesystem"
|
2
|
+
#require "rack/boxlet_url_builder"
|
3
|
+
require "rack/request"
|
4
|
+
require "rack/response"
|
5
|
+
require "rack/file_upload"
|
6
|
+
require "boxlet/db"
|
7
|
+
require "boxlet/app/router"
|
8
|
+
|
9
|
+
|
10
|
+
module Boxlet
|
11
|
+
class App
|
12
|
+
|
13
|
+
include Sys
|
14
|
+
|
15
|
+
def self.routes
|
16
|
+
routes = {
|
17
|
+
["/", :get] => :index,
|
18
|
+
# ["/auth"] => :auth,
|
19
|
+
# ["/register_device", :post] => :register_device,
|
20
|
+
# ["/notifications", :*] => :notifications,
|
21
|
+
["/stats", :post] => :stats,
|
22
|
+
["/push_files", :post] => :push_files,
|
23
|
+
["/file_list"] => :file_list,
|
24
|
+
["/file_info"] => :file_info
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize
|
29
|
+
usage = Boxlet::App.app_space_usage
|
30
|
+
capacity = Boxlet::App.app_space_capacity
|
31
|
+
puts "Space Utilization: #{usage}MB / #{capacity}MB (#{(usage.to_f / capacity).round(3)}%)"
|
32
|
+
end
|
33
|
+
|
34
|
+
def bind
|
35
|
+
Rack::Builder.new do
|
36
|
+
use Rack::Reloader
|
37
|
+
# use Rack::Static, :urls => ["/public"]
|
38
|
+
use Rack::FileUpload, :upload_dir => [Boxlet.config[:upload_dir] || APP_ROOT + '/uploads']
|
39
|
+
|
40
|
+
Boxlet::App.routes.each do |route, action|
|
41
|
+
map route[0] do
|
42
|
+
run Boxlet::Router.new(route[1] || :*, action)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end.to_app
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
def setup(config)
|
51
|
+
begin
|
52
|
+
# Check for free space
|
53
|
+
if Boxlet::App.free_space <= 50
|
54
|
+
raise "Not enough free space"
|
55
|
+
end
|
56
|
+
if Boxlet::App.app_space_usage / Boxlet::App.app_space_capacity >= 0.9
|
57
|
+
puts "App is over 90% full"
|
58
|
+
end
|
59
|
+
|
60
|
+
# Create upload and tmp directories
|
61
|
+
upload_dir = Boxlet.config[:upload_dir]
|
62
|
+
tmp_dir = Boxlet.config[:tmp_dir]
|
63
|
+
if !File.exists?(upload_dir) || !File.exists?(tmp_dir)
|
64
|
+
if !File.exists?(upload_dir)
|
65
|
+
puts "Upload directory (#{upload_dir}) does not exist. Create? [y/n]"
|
66
|
+
create = gets.chomp
|
67
|
+
if create =~ /y/i
|
68
|
+
Dir.mkdir(upload_dir)
|
69
|
+
puts "Upload directory created!"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
if !File.exists?(tmp_dir)
|
73
|
+
puts "Temp directory (#{tmp_dir}) does not exist. Create? [y/n]"
|
74
|
+
create = gets.chomp
|
75
|
+
if create =~ /y/i
|
76
|
+
Dir.mkdir(tmp_dir)
|
77
|
+
puts "Temp directory created!"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
if File.exists?(upload_dir) && File.exists?(tmp_dir)
|
81
|
+
puts "Done creating directories."
|
82
|
+
else
|
83
|
+
raise "Error creating directories. Please check your config and file permissions, and retry."
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
puts "\nBoxlet setup is done!"
|
88
|
+
rescue => e
|
89
|
+
puts "\nERROR: #{e}"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
|
94
|
+
# App disk space functions
|
95
|
+
|
96
|
+
def self.free_space
|
97
|
+
Boxlet::App.app_space_capacity - Boxlet::App.app_space_usage
|
98
|
+
end
|
99
|
+
|
100
|
+
def self.app_space_capacity
|
101
|
+
drive_free_space = Boxlet::App.drive_free_space
|
102
|
+
if Boxlet.config[:capacity].is_a? String
|
103
|
+
Boxlet::App.drive_free_space * Boxlet.config[:capacity].to_i / 100
|
104
|
+
else
|
105
|
+
Boxlet.config[:capacity]
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def self.app_space_usage
|
110
|
+
raise RuntimeError, "#{Boxlet.config[:upload_dir]} is not a directory" unless File.directory?(Boxlet.config[:upload_dir])
|
111
|
+
|
112
|
+
total_size = 0
|
113
|
+
Dir["#{Boxlet.config[:upload_dir]}/**/*"].each do |f|
|
114
|
+
total_size += File.size(f) if File.file?(f) && File.size?(f)
|
115
|
+
end
|
116
|
+
total_size / 1000000 # / 1048576 # to megabytes
|
117
|
+
end
|
118
|
+
|
119
|
+
# Drive disk space functions
|
120
|
+
|
121
|
+
def self.drive_free_space
|
122
|
+
stat = Filesystem.stat(Boxlet.config[:file_system_root])
|
123
|
+
(stat.block_size * stat.blocks_available).to_mb
|
124
|
+
end
|
125
|
+
|
126
|
+
def self.drive_capacity
|
127
|
+
stat = Filesystem.stat(Boxlet.config[:file_system_root])
|
128
|
+
(stat.block_size * stat.blocks).to_mb
|
129
|
+
end
|
130
|
+
|
131
|
+
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1,168 @@
|
|
1
|
+
require 'date'
|
2
|
+
|
3
|
+
# routes = {
|
4
|
+
# ["/", :get] => :index,
|
5
|
+
# ["/auth"] => :auth,
|
6
|
+
# ["/register_device", :post] => :register_device,
|
7
|
+
# ["/notifications", :post] => :notifications,
|
8
|
+
# ["/push_files", :post] => :push_files,
|
9
|
+
# ["/file_list"] => :file_list,
|
10
|
+
# ["/file_info"] => :file_info
|
11
|
+
# }
|
12
|
+
|
13
|
+
|
14
|
+
module Boxlet
|
15
|
+
class Controller
|
16
|
+
attr_accessor :request, :format, :params
|
17
|
+
|
18
|
+
def initialize(request)
|
19
|
+
@request = request
|
20
|
+
@params = Boxlet.symbolize_keys request.params
|
21
|
+
pp request.params
|
22
|
+
|
23
|
+
@format = :html
|
24
|
+
end
|
25
|
+
|
26
|
+
def action(action)
|
27
|
+
action_response = self.send(action)
|
28
|
+
set_user if action =~ /push_files|file_list|file_info/
|
29
|
+
|
30
|
+
{format: @format, content: action_response}
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
# actions
|
35
|
+
|
36
|
+
def index
|
37
|
+
'<html><body><form action="/push_files" method="post" enctype="multipart/form-data">UUID:<input type="text" name="uuid"><br><input type="file" name="file"><input type="submit"></form>'
|
38
|
+
end
|
39
|
+
|
40
|
+
# def auth
|
41
|
+
# @format = :json
|
42
|
+
# "auth"
|
43
|
+
# end
|
44
|
+
|
45
|
+
# def register_device
|
46
|
+
# @format = :json
|
47
|
+
|
48
|
+
# pp @params if Boxlet.config[:debug]
|
49
|
+
|
50
|
+
# uuid = @params[:uuid]
|
51
|
+
# # user = user_model.merge { uuid: uuid }
|
52
|
+
# if db.collection('users').insert(user)
|
53
|
+
# {response: true}
|
54
|
+
# else
|
55
|
+
# {response: false}
|
56
|
+
# end
|
57
|
+
# end
|
58
|
+
|
59
|
+
# def notifications
|
60
|
+
# @format = :json
|
61
|
+
|
62
|
+
# uuid = @params[:uuid]
|
63
|
+
# notifications = @params[:notifications]
|
64
|
+
# pp uuid
|
65
|
+
# # @user
|
66
|
+
# "notifications"
|
67
|
+
# end
|
68
|
+
|
69
|
+
def stats
|
70
|
+
@format = :json
|
71
|
+
|
72
|
+
{
|
73
|
+
capacity: Boxlet::App.app_space_capacity,
|
74
|
+
usage: Boxlet::App.app_space_usage,
|
75
|
+
free_space: free_space?
|
76
|
+
}
|
77
|
+
end
|
78
|
+
|
79
|
+
def push_files
|
80
|
+
@format = :json
|
81
|
+
|
82
|
+
upload_path = user_upload_dir || './uploads'
|
83
|
+
upload_file = @params[:file]
|
84
|
+
asset_path = @params[:asset_path]
|
85
|
+
asset_path_params = Rack::Utils.parse_nested_query(asset_path[asset_path.index('?') + 1..-1])
|
86
|
+
|
87
|
+
new_filename = "#{asset_path_params["id"]}.#{asset_path_params["ext"]}"
|
88
|
+
new_path = File.join(upload_path, new_filename)
|
89
|
+
FileUtils.mv(upload_file[:tempfile].path, new_path)
|
90
|
+
|
91
|
+
if File.exists? new_path
|
92
|
+
file = File.open(new_path, 'r')
|
93
|
+
# asset_date = Date.parse(@params[:asset_date])
|
94
|
+
asset = {
|
95
|
+
filename: upload_file[:filename],
|
96
|
+
size: file.size,
|
97
|
+
local_date: file.mtime.to_i,
|
98
|
+
asset_path: @params[:asset_path],
|
99
|
+
asset_date: @params[:asset_date],
|
100
|
+
uuid: @params[:uuid]
|
101
|
+
}
|
102
|
+
db.collection('assets').insert(asset)
|
103
|
+
{response: true}
|
104
|
+
else
|
105
|
+
{response: false}
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def file_list
|
110
|
+
@format = :json
|
111
|
+
|
112
|
+
uuid = @params[:uuid]
|
113
|
+
db.collection('assets').find({uuid: uuid}).to_a
|
114
|
+
end
|
115
|
+
|
116
|
+
def file_info
|
117
|
+
@format = :json
|
118
|
+
|
119
|
+
uuid = @params[:uuid]
|
120
|
+
asset_path = @params[:asset_path]
|
121
|
+
file_model.merge db.collection('assets').find({asset_path: asset_path, uuid: uuid}).to_a.first || {}
|
122
|
+
end
|
123
|
+
|
124
|
+
|
125
|
+
private
|
126
|
+
|
127
|
+
def db
|
128
|
+
Boxlet::Db.connection
|
129
|
+
end
|
130
|
+
|
131
|
+
def set_user
|
132
|
+
user_model.merge db.collection('users').find({uuid: @params[:uuid]}).to_a.first || {}
|
133
|
+
end
|
134
|
+
|
135
|
+
def user_upload_dir
|
136
|
+
user_upload_dir_name = Boxlet.config[:upload_dir] + "/" + (@params[:uuid] || '')
|
137
|
+
Dir.mkdir(user_upload_dir_name) unless File.exists?(user_upload_dir_name)
|
138
|
+
user_upload_dir_name
|
139
|
+
end
|
140
|
+
|
141
|
+
def free_space?
|
142
|
+
Boxlet::App.free_space > 50
|
143
|
+
end
|
144
|
+
|
145
|
+
|
146
|
+
# Models
|
147
|
+
|
148
|
+
def file_model
|
149
|
+
{
|
150
|
+
filename: '',
|
151
|
+
size: 0,
|
152
|
+
local_date: 0,
|
153
|
+
asset_path: '',
|
154
|
+
asset_date: '',
|
155
|
+
uuid: []
|
156
|
+
}
|
157
|
+
end
|
158
|
+
|
159
|
+
def user_model
|
160
|
+
{
|
161
|
+
uuid: '',
|
162
|
+
notifications: 1,
|
163
|
+
last_activity: Time.now
|
164
|
+
}
|
165
|
+
end
|
166
|
+
|
167
|
+
end
|
168
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require "rack/request"
|
2
|
+
require "rack/response"
|
3
|
+
require "boxlet/app/controller"
|
4
|
+
require "json"
|
5
|
+
|
6
|
+
|
7
|
+
module Boxlet
|
8
|
+
class Router
|
9
|
+
|
10
|
+
attr_accessor :method, :action
|
11
|
+
|
12
|
+
def initialize(method, action)
|
13
|
+
@method = method
|
14
|
+
@action = action
|
15
|
+
end
|
16
|
+
|
17
|
+
def call(env)
|
18
|
+
request = Rack::Request.new(env)
|
19
|
+
|
20
|
+
if Boxlet.debug?
|
21
|
+
puts "\n#{env["REMOTE_ADDR"]} - [#{Time.now.to_s}] #{@method.upcase} #{env["SERVER_PROTOCOL"]} => #{env["REQUEST_PATH"]}"
|
22
|
+
end
|
23
|
+
|
24
|
+
response = Rack::Response.new
|
25
|
+
controller = Boxlet::Controller.new(request)
|
26
|
+
if (@method == :* || request.get? && @method == :get) || (request.post? && @method == :post)
|
27
|
+
puts "Responding: #{@method.upcase} => #{@action}" if Boxlet.debug?
|
28
|
+
action_response = controller.action(@action)
|
29
|
+
response.status = 200
|
30
|
+
else
|
31
|
+
response.status = 404
|
32
|
+
raise "404"
|
33
|
+
end
|
34
|
+
|
35
|
+
if action_response[:format] == :json
|
36
|
+
response.write action_response[:content].to_json
|
37
|
+
else
|
38
|
+
response.write action_response[:content]
|
39
|
+
end
|
40
|
+
|
41
|
+
response.finish
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
module Boxlet
|
2
|
+
module Config
|
3
|
+
|
4
|
+
ARGS = {
|
5
|
+
:path => {
|
6
|
+
:short => 'f',
|
7
|
+
:default => Proc.new { Dir.pwd }
|
8
|
+
},
|
9
|
+
:port => {
|
10
|
+
:short => 'p',
|
11
|
+
:default => 8077,
|
12
|
+
:sanitizer => Proc.new { |p| p.to_i }
|
13
|
+
},
|
14
|
+
:host => {
|
15
|
+
:short => 'o',
|
16
|
+
:default => 'localhost'
|
17
|
+
},
|
18
|
+
:server_type => {
|
19
|
+
:short => 's',
|
20
|
+
:default => 'rack',
|
21
|
+
:sanitizer => Proc.new { |p| p.to_sym }
|
22
|
+
},
|
23
|
+
:environment => {
|
24
|
+
:short => 'E',
|
25
|
+
:default => 'development'
|
26
|
+
},
|
27
|
+
:daemonize => {
|
28
|
+
:short => 'D',
|
29
|
+
:default => 'false',
|
30
|
+
:sanitizer => Proc.new { |p| p == 'true' }
|
31
|
+
},
|
32
|
+
:debug => {
|
33
|
+
:short => 'd',
|
34
|
+
:default => 'true',
|
35
|
+
:sanitizer => Proc.new { |p| p == 'true' }
|
36
|
+
},
|
37
|
+
:upload_dir => {
|
38
|
+
:short => 'U',
|
39
|
+
:default => './uploads'
|
40
|
+
},
|
41
|
+
:tmp_dir => {
|
42
|
+
:short => 'T',
|
43
|
+
:default => './tmp'
|
44
|
+
},
|
45
|
+
:file_system_root => {
|
46
|
+
:short => 'r',
|
47
|
+
:default => '/'
|
48
|
+
},
|
49
|
+
:capacity => {
|
50
|
+
:short => 'C',
|
51
|
+
:default => '90%',
|
52
|
+
:sanitizer => Proc.new { |p| (p.to_i.to_s == p) ? p.to_i : p }
|
53
|
+
}
|
54
|
+
}
|
55
|
+
|
56
|
+
|
57
|
+
def populate_params!(argv, path_to_config)
|
58
|
+
@raw_config = load_config_file(path_to_config)
|
59
|
+
@raw_params = parse_arguments(argv)
|
60
|
+
# @config = @raw_params.merge(@raw_config)
|
61
|
+
@config = @raw_config.merge(@raw_params)
|
62
|
+
|
63
|
+
@config[:debug] = @raw_config[:debug] || @raw_params[:debug]
|
64
|
+
if @config[:debug]
|
65
|
+
pp @config
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
def symbolize_keys(hash)
|
71
|
+
hash.inject({}){|result, (key, value)|
|
72
|
+
new_key = key.instance_of?(String) ? key.to_sym : key
|
73
|
+
new_value = value.instance_of?(Hash) ? symbolize_keys(value) : value
|
74
|
+
|
75
|
+
result[new_key] = new_value
|
76
|
+
result
|
77
|
+
}
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
def parse_arguments(argv)
|
83
|
+
params = Hash.new
|
84
|
+
|
85
|
+
ARGS.each_pair do |param_name, param_attrs|
|
86
|
+
param_short_name = param_attrs[:short]
|
87
|
+
config_value = @raw_config[param_name.to_sym]
|
88
|
+
default = param_attrs[:default]
|
89
|
+
sanitizer = param_attrs[:sanitizer]
|
90
|
+
|
91
|
+
param_value = argv["--#{param_name}"] ||
|
92
|
+
(param_short_name.nil? ? nil : argv["-#{param_short_name}"]) ||
|
93
|
+
(config_value.nil? ? nil : config_value) ||
|
94
|
+
(default.is_a?(Proc) ? default.call : default)
|
95
|
+
|
96
|
+
param_value = sanitizer.call(param_value) if sanitizer.is_a?(Proc)
|
97
|
+
|
98
|
+
if !param_value.nil?
|
99
|
+
params[param_name] = param_value
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
params
|
104
|
+
end
|
105
|
+
|
106
|
+
def load_config_file(path_to_config)
|
107
|
+
begin
|
108
|
+
loaded_config = YAML.load_file(path_to_config)
|
109
|
+
symbolize_keys(loaded_config)
|
110
|
+
rescue
|
111
|
+
puts "Error loading config file! Using defaults..."
|
112
|
+
{}
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
|
118
|
+
|
119
|
+
end
|
data/lib/boxlet/db.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'mongo'
|
2
|
+
|
3
|
+
|
4
|
+
module Boxlet
|
5
|
+
module Db
|
6
|
+
|
7
|
+
extend self
|
8
|
+
include Mongo
|
9
|
+
|
10
|
+
attr_accessor :db
|
11
|
+
|
12
|
+
def connection
|
13
|
+
@db ||= self.connect
|
14
|
+
end
|
15
|
+
|
16
|
+
def connect
|
17
|
+
config = Boxlet.config
|
18
|
+
db_config = config[:db][config[:environment].to_sym || :development]
|
19
|
+
|
20
|
+
host = db_config[:host] || 'localhost'
|
21
|
+
port = db_config[:port] || MongoClient::DEFAULT_PORT
|
22
|
+
puts "Connecting to #{host}:#{port}" if Boxlet.debug?
|
23
|
+
client = MongoClient.new(host, port)
|
24
|
+
db = client.db(db_config[:db] || 'boxlet_development')
|
25
|
+
return db
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
data/lib/boxlet/log.rb
CHANGED
@@ -0,0 +1,37 @@
|
|
1
|
+
require "handlers/thin"
|
2
|
+
|
3
|
+
|
4
|
+
module Boxlet
|
5
|
+
class Runner
|
6
|
+
attr_accessor :server, :server_instance
|
7
|
+
|
8
|
+
def start(app, &block)
|
9
|
+
params = Boxlet.config
|
10
|
+
environment = ENV['RACK_ENV'] || params[:environment] rescue 'development'
|
11
|
+
default_host = environment == 'development' ? 'localhost' : '0.0.0.0'
|
12
|
+
|
13
|
+
params[:Host] = params.delete(:host) || default_host
|
14
|
+
params[:Port] = params.delete(:port) || 8077
|
15
|
+
|
16
|
+
server_type = params.delete(:server_type) || :thin
|
17
|
+
@server_instance = self.send server_type.to_sym, app, params
|
18
|
+
@server_instance.start do |server|
|
19
|
+
self.server = server
|
20
|
+
block.call(server) if block_given?
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def stop
|
25
|
+
@server.stop!
|
26
|
+
end
|
27
|
+
|
28
|
+
def rack(app, params)
|
29
|
+
Rack::Server.new(params.merge({app: app}))
|
30
|
+
end
|
31
|
+
|
32
|
+
def thin(app, params)
|
33
|
+
Boxlet::Handlers::Thin.new(app, params)
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
data/lib/boxlet/version.rb
CHANGED
@@ -0,0 +1,34 @@
|
|
1
|
+
require "thin"
|
2
|
+
require "rack/content_length"
|
3
|
+
require "rack/chunked"
|
4
|
+
|
5
|
+
|
6
|
+
module Boxlet
|
7
|
+
module Handlers
|
8
|
+
class Thin
|
9
|
+
attr_accessor :app, :params
|
10
|
+
|
11
|
+
def initialize(app, params={})
|
12
|
+
@app = app
|
13
|
+
@params = params
|
14
|
+
# super
|
15
|
+
end
|
16
|
+
|
17
|
+
# ported from https://github.com/rack/rack/tree/master/lib/rack/handler/thin.rb
|
18
|
+
def start
|
19
|
+
# environment = ENV['RACK_ENV'] || 'development'
|
20
|
+
# default_host = environment == 'development' ? : '0.0.0.0'
|
21
|
+
host = @params.delete(:Host) || 'localhost'
|
22
|
+
port = @params.delete(:Port) || 8077
|
23
|
+
|
24
|
+
args = [host, port, @app, @params]
|
25
|
+
|
26
|
+
# Thin versions below 0.8.0 do not support additional options
|
27
|
+
args.pop if ::Thin::VERSION::MAJOR < 1 && ::Thin::VERSION::MINOR < 8
|
28
|
+
server = ::Thin::Server.new(*args)
|
29
|
+
yield server if block_given?
|
30
|
+
server.start
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "rack"
|
2
|
+
require "rack/boxlet_url_map"
|
3
|
+
|
4
|
+
|
5
|
+
module Rack
|
6
|
+
class BoxletUrlBuilder < Builder
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def generate_map(default_app, mapping)
|
11
|
+
mapped = default_app ? {'/' => default_app} : {}
|
12
|
+
mapping.each { |r,b| mapped[r] = self.class.new(default_app, &b) }
|
13
|
+
BoxletUrlMap.new(mapped)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require "rack"
|
2
|
+
|
3
|
+
|
4
|
+
module Rack
|
5
|
+
class BoxletUrlMap < URLMap
|
6
|
+
|
7
|
+
def remap(map)
|
8
|
+
@mapping = map.map { |location, app|
|
9
|
+
if location.is_a? String
|
10
|
+
if location =~ %r{\Ahttps?://(.*?)(/.*)}
|
11
|
+
host, location = $1, $2
|
12
|
+
else
|
13
|
+
host = nil
|
14
|
+
end
|
15
|
+
|
16
|
+
unless location[0] == ?/
|
17
|
+
raise ArgumentError, "paths need to start with /"
|
18
|
+
end
|
19
|
+
|
20
|
+
location = location.chomp('/')
|
21
|
+
match = Regexp.new("^#{Regexp.quote(location).gsub('/', '/+')}(.*)", nil, 'n')
|
22
|
+
elsif location.is_a? Regexp
|
23
|
+
match = location
|
24
|
+
else
|
25
|
+
raise ArgumentError, "location should be an instance of String or Regexp"
|
26
|
+
end
|
27
|
+
|
28
|
+
[host, location, match, app]
|
29
|
+
}.sort_by do |(host, location, _, _)|
|
30
|
+
[host ? -host.size : INFINITY, (location.is_a?(String) ? -location.size : INFINITY)]
|
31
|
+
end
|
32
|
+
|
33
|
+
@mapping
|
34
|
+
end
|
35
|
+
|
36
|
+
def call(env)
|
37
|
+
path = env["PATH_INFO"]
|
38
|
+
script_name = env['SCRIPT_NAME']
|
39
|
+
hHost = env['HTTP_HOST']
|
40
|
+
sName = env['SERVER_NAME']
|
41
|
+
sPort = env['SERVER_PORT']
|
42
|
+
|
43
|
+
@mapping.each do |host, location, match, app|
|
44
|
+
unless hHost == host \
|
45
|
+
|| sName == host \
|
46
|
+
|| (!host && (hHost == sName || hHost == sName+':'+sPort))
|
47
|
+
next
|
48
|
+
end
|
49
|
+
|
50
|
+
next unless m = match.match(path.to_s)
|
51
|
+
|
52
|
+
rest = m[1]
|
53
|
+
next unless !rest || rest.empty? || rest[0] == ?/
|
54
|
+
|
55
|
+
return app.call(env)
|
56
|
+
end
|
57
|
+
|
58
|
+
[404, {"Content-Type" => "text/plain", "X-Cascade" => "pass"}, ["Not Found: #{path}"]]
|
59
|
+
|
60
|
+
ensure
|
61
|
+
env['PATH_INFO'] = path
|
62
|
+
env['SCRIPT_NAME'] = script_name
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
# ported from https://github.com/New-Bamboo/rack-raw-upload
|
2
|
+
require 'multi_json'
|
3
|
+
|
4
|
+
|
5
|
+
module Rack
|
6
|
+
class FileUpload
|
7
|
+
|
8
|
+
def initialize(app, options={})
|
9
|
+
@app = app
|
10
|
+
@paths = [options[:upload_dir]]
|
11
|
+
@explicit = options[:explicit]
|
12
|
+
@tmpdir = options[:tmp_dir] || Dir::tmpdir
|
13
|
+
@paths = [@paths] if @paths.kind_of?(String)
|
14
|
+
end
|
15
|
+
|
16
|
+
def call(env)
|
17
|
+
kick_in?(env) ? convert_and_pass_on(env) : @app.call(env)
|
18
|
+
end
|
19
|
+
|
20
|
+
def upload_path?(request_path)
|
21
|
+
return true if @paths.nil?
|
22
|
+
|
23
|
+
@paths.any? do |candidate|
|
24
|
+
literal_path_match?(request_path, candidate) || wildcard_path_match?(request_path, candidate)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def convert_and_pass_on(env)
|
32
|
+
if env['rack.input'].kind_of?(Tempfile)
|
33
|
+
env['rack.input'].extend(EqlFix)
|
34
|
+
tempfile = env['rack.input']
|
35
|
+
else
|
36
|
+
tempfile = Tempfile.new('raw-upload.', @tmpdir)
|
37
|
+
|
38
|
+
env['rack.input'].each do |chunk|
|
39
|
+
if chunk.respond_to?(:force_encoding)
|
40
|
+
tempfile << chunk.force_encoding('UTF-8')
|
41
|
+
else
|
42
|
+
tempfile << chunk
|
43
|
+
end
|
44
|
+
end
|
45
|
+
env['rack.input'].rewind
|
46
|
+
|
47
|
+
tempfile.flush
|
48
|
+
tempfile.rewind
|
49
|
+
end
|
50
|
+
fake_file = {
|
51
|
+
:filename => env['HTTP_X_FILE_NAME'],
|
52
|
+
:type => env['CONTENT_TYPE'],
|
53
|
+
:tempfile => tempfile,
|
54
|
+
}
|
55
|
+
env['rack.request.form_input'] = env['rack.input']
|
56
|
+
env['rack.request.form_hash'] ||= {}
|
57
|
+
env['rack.request.query_hash'] ||= {}
|
58
|
+
env['rack.request.form_hash']['file'] = fake_file
|
59
|
+
env['rack.request.query_hash']['file'] = fake_file
|
60
|
+
if env['HTTP_X_QUERY_PARAMS']
|
61
|
+
env['rack.errors'].puts("Warning! The header X-Query-Params is deprecated. Please use X-JSON-Params instead.")
|
62
|
+
inject_json_params!(env, env['HTTP_X_QUERY_PARAMS'])
|
63
|
+
end
|
64
|
+
if env['HTTP_X_JSON_PARAMS']
|
65
|
+
inject_json_params!(env, env['HTTP_X_JSON_PARAMS'])
|
66
|
+
end
|
67
|
+
if env['HTTP_X_PARAMS']
|
68
|
+
inject_query_params!(env, env['HTTP_X_PARAMS'])
|
69
|
+
end
|
70
|
+
@app.call(env)
|
71
|
+
end
|
72
|
+
|
73
|
+
def kick_in?(env)
|
74
|
+
env['HTTP_X_FILE_UPLOAD'] == 'true' ||
|
75
|
+
! @explicit && env['HTTP_X_FILE_UPLOAD'] != 'false' && raw_file_upload?(env) ||
|
76
|
+
env.has_key?('HTTP_X_FILE_UPLOAD') && env['HTTP_X_FILE_UPLOAD'] != 'false' && raw_file_upload?(env)
|
77
|
+
end
|
78
|
+
|
79
|
+
def raw_file_upload?(env)
|
80
|
+
upload_path?(env['PATH_INFO']) &&
|
81
|
+
%{POST PUT}.include?(env['REQUEST_METHOD']) &&
|
82
|
+
content_type_of_raw_file?(env['CONTENT_TYPE']) &&
|
83
|
+
env['CONTENT_LENGTH'].to_i > 0
|
84
|
+
end
|
85
|
+
|
86
|
+
def literal_path_match?(request_path, candidate)
|
87
|
+
candidate == request_path
|
88
|
+
end
|
89
|
+
|
90
|
+
def wildcard_path_match?(request_path, candidate)
|
91
|
+
return false unless candidate.include?('*')
|
92
|
+
regexp = '^' + candidate.gsub('.', '\.').gsub('*', '[^/]*') + '$'
|
93
|
+
!! (Regexp.new(regexp) =~ request_path)
|
94
|
+
end
|
95
|
+
|
96
|
+
def content_type_of_raw_file?(content_type)
|
97
|
+
case content_type
|
98
|
+
when %r{^application/x-www-form-urlencoded}, %r{^multipart/form-data}
|
99
|
+
false
|
100
|
+
else
|
101
|
+
true
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def random_string
|
106
|
+
(0...8).map{65.+(rand(25)).chr}.join
|
107
|
+
end
|
108
|
+
|
109
|
+
def inject_json_params!(env, params)
|
110
|
+
json = MultiJson.load(params)
|
111
|
+
env['rack.request.form_hash'].merge!(json)
|
112
|
+
env['rack.request.query_hash'].merge!(json)
|
113
|
+
end
|
114
|
+
|
115
|
+
def inject_query_params!(env, params)
|
116
|
+
json = Rack::Utils.parse_query(params)
|
117
|
+
env['rack.request.form_hash'].merge!(json)
|
118
|
+
env['rack.request.query_hash'].merge!(json)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
metadata
CHANGED
@@ -1,50 +1,166 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: boxlet
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.0.2
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
|
-
- Clayton Liggitt
|
9
7
|
- arktisklada
|
10
8
|
autorequire:
|
11
9
|
bindir: bin
|
12
10
|
cert_chain: []
|
13
|
-
date: 2014-
|
11
|
+
date: 2014-07-10 00:00:00.000000000 Z
|
14
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rack
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.5'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.5'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rack-contrib
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.1'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.1'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: thin
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.6'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.6'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: multi_json
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.10'
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: 1.10.1
|
65
|
+
type: :runtime
|
66
|
+
prerelease: false
|
67
|
+
version_requirements: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - "~>"
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: '1.10'
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: 1.10.1
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: mongo
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - "~>"
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '1.10'
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: 1.10.2
|
85
|
+
type: :runtime
|
86
|
+
prerelease: false
|
87
|
+
version_requirements: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - "~>"
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '1.10'
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: 1.10.2
|
95
|
+
- !ruby/object:Gem::Dependency
|
96
|
+
name: bson_ext
|
97
|
+
requirement: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - "~>"
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '1.10'
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: 1.10.2
|
105
|
+
type: :runtime
|
106
|
+
prerelease: false
|
107
|
+
version_requirements: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - "~>"
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '1.10'
|
112
|
+
- - ">="
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: 1.10.2
|
115
|
+
- !ruby/object:Gem::Dependency
|
116
|
+
name: sys-filesystem
|
117
|
+
requirement: !ruby/object:Gem::Requirement
|
118
|
+
requirements:
|
119
|
+
- - "~>"
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
version: '1.1'
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 1.1.2
|
125
|
+
type: :runtime
|
126
|
+
prerelease: false
|
127
|
+
version_requirements: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '1.1'
|
132
|
+
- - ">="
|
133
|
+
- !ruby/object:Gem::Version
|
134
|
+
version: 1.1.2
|
15
135
|
- !ruby/object:Gem::Dependency
|
16
136
|
name: bundler
|
17
137
|
requirement: !ruby/object:Gem::Requirement
|
18
|
-
none: false
|
19
138
|
requirements:
|
20
|
-
- - ~>
|
139
|
+
- - "~>"
|
21
140
|
- !ruby/object:Gem::Version
|
22
141
|
version: '1.3'
|
23
142
|
type: :development
|
24
143
|
prerelease: false
|
25
144
|
version_requirements: !ruby/object:Gem::Requirement
|
26
|
-
none: false
|
27
145
|
requirements:
|
28
|
-
- - ~>
|
146
|
+
- - "~>"
|
29
147
|
- !ruby/object:Gem::Version
|
30
148
|
version: '1.3'
|
31
149
|
- !ruby/object:Gem::Dependency
|
32
150
|
name: rake
|
33
151
|
requirement: !ruby/object:Gem::Requirement
|
34
|
-
none: false
|
35
152
|
requirements:
|
36
|
-
- -
|
153
|
+
- - "~>"
|
37
154
|
- !ruby/object:Gem::Version
|
38
|
-
version: '
|
155
|
+
version: '10.3'
|
39
156
|
type: :development
|
40
157
|
prerelease: false
|
41
158
|
version_requirements: !ruby/object:Gem::Requirement
|
42
|
-
none: false
|
43
159
|
requirements:
|
44
|
-
- -
|
160
|
+
- - "~>"
|
45
161
|
- !ruby/object:Gem::Version
|
46
|
-
version: '
|
47
|
-
description:
|
162
|
+
version: '10.3'
|
163
|
+
description: Upload pics from your phone
|
48
164
|
email:
|
49
165
|
- mail@enorganik.com
|
50
166
|
executables:
|
@@ -52,39 +168,47 @@ executables:
|
|
52
168
|
extensions: []
|
53
169
|
extra_rdoc_files: []
|
54
170
|
files:
|
55
|
-
- config.yml
|
56
171
|
- LICENSE.txt
|
57
172
|
- README.md
|
58
173
|
- Rakefile
|
174
|
+
- bin/boxlet
|
59
175
|
- boxlet.gemspec
|
176
|
+
- config.yml
|
177
|
+
- lib/boxlet.rb
|
178
|
+
- lib/boxlet/app.rb
|
179
|
+
- lib/boxlet/app/controller.rb
|
180
|
+
- lib/boxlet/app/router.rb
|
181
|
+
- lib/boxlet/config.rb
|
182
|
+
- lib/boxlet/db.rb
|
60
183
|
- lib/boxlet/log.rb
|
61
|
-
- lib/boxlet/
|
184
|
+
- lib/boxlet/runner.rb
|
62
185
|
- lib/boxlet/version.rb
|
63
|
-
- lib/
|
64
|
-
-
|
65
|
-
|
186
|
+
- lib/handlers/thin.rb
|
187
|
+
- lib/rack/boxlet_url_builder.rb
|
188
|
+
- lib/rack/boxlet_url_map.rb
|
189
|
+
- lib/rack/file_upload.rb
|
190
|
+
homepage: https://github.com/arktisklada/boxlet
|
66
191
|
licenses:
|
67
192
|
- MIT
|
193
|
+
metadata: {}
|
68
194
|
post_install_message:
|
69
195
|
rdoc_options: []
|
70
196
|
require_paths:
|
71
197
|
- lib
|
72
198
|
required_ruby_version: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
199
|
requirements:
|
75
|
-
- -
|
200
|
+
- - ">="
|
76
201
|
- !ruby/object:Gem::Version
|
77
202
|
version: '0'
|
78
203
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
79
|
-
none: false
|
80
204
|
requirements:
|
81
|
-
- -
|
205
|
+
- - ">="
|
82
206
|
- !ruby/object:Gem::Version
|
83
207
|
version: '0'
|
84
208
|
requirements: []
|
85
209
|
rubyforge_project:
|
86
|
-
rubygems_version:
|
210
|
+
rubygems_version: 2.2.2
|
87
211
|
signing_key:
|
88
|
-
specification_version:
|
89
|
-
summary:
|
212
|
+
specification_version: 4
|
213
|
+
summary: Upload pics from your phone
|
90
214
|
test_files: []
|
data/lib/boxlet/tcp_server.rb
DELETED
@@ -1,62 +0,0 @@
|
|
1
|
-
require "socket"
|
2
|
-
|
3
|
-
class TcpServer
|
4
|
-
|
5
|
-
include Log
|
6
|
-
|
7
|
-
def initialize()
|
8
|
-
@listen_ip = Boxlet::Server.config['tcp_listen_ip'] || '127.0.0.1'
|
9
|
-
@listen_port = Boxlet::Server.config['tcp_listen_port'] || 11311
|
10
|
-
|
11
|
-
@log = get_logger('log/tcp.log', 10, 1024000, Boxlet::Server.config['tcp_debug'] ? Logger::DEBUG : Logger::WARN);
|
12
|
-
@log.info("Initializing TCP server on #{@listen_ip}:#{@listen_port}")
|
13
|
-
@server = TCPServer.open(@listen_ip, @listen_port)
|
14
|
-
|
15
|
-
@connections = Hash.new
|
16
|
-
end
|
17
|
-
|
18
|
-
def start
|
19
|
-
@log.info("Starting TCP server")
|
20
|
-
|
21
|
-
# Start a new thread for the TCP server so that it does not block and
|
22
|
-
# hold up the rest of the program execution
|
23
|
-
# Thread.start() do
|
24
|
-
loop {
|
25
|
-
# When a new connection comes in, create a new thread and begin handling
|
26
|
-
# requests
|
27
|
-
Thread.start(@server.accept) do |client|
|
28
|
-
@log.info("Client connected!")
|
29
|
-
|
30
|
-
# Output welcome messages
|
31
|
-
client.puts Time.now.ctime
|
32
|
-
client.puts "Welcome to Boxlet!"
|
33
|
-
|
34
|
-
# Read input from TCP client
|
35
|
-
while line = client.gets
|
36
|
-
entry = line.split
|
37
|
-
cmd = entry.shift
|
38
|
-
|
39
|
-
case cmd
|
40
|
-
# Retrieve config value
|
41
|
-
when "config_get" then client.puts(Boxlet::Server.config[entry[0]] || "ERROR")
|
42
|
-
|
43
|
-
# Halt the server
|
44
|
-
when "stop" then
|
45
|
-
client.puts "Daemon halting!"
|
46
|
-
@log.info("Daemon halting!")
|
47
|
-
exit(0)
|
48
|
-
|
49
|
-
# Disconnect the client
|
50
|
-
when "quit" then
|
51
|
-
client.puts "Goodbye!"
|
52
|
-
client.close
|
53
|
-
else
|
54
|
-
client.puts "INVALID"
|
55
|
-
end
|
56
|
-
end
|
57
|
-
end
|
58
|
-
}
|
59
|
-
# end
|
60
|
-
end
|
61
|
-
|
62
|
-
end
|