rubko 0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/bin/rubko-deploy +40 -0
- data/bin/rubko-init +6 -0
- data/lib/rubko/app.rb +79 -0
- data/lib/rubko/asset/fileStream.rb +18 -0
- data/lib/rubko/asset/gzipStream.rb +26 -0
- data/lib/rubko/asset.rb +71 -0
- data/lib/rubko/base.rb +123 -0
- data/lib/rubko/controller.rb +17 -0
- data/lib/rubko/model.rb +5 -0
- data/lib/rubko/plugin.rb +7 -0
- data/lib/rubko/plugins/cookie.rb +45 -0
- data/lib/rubko/plugins/db.rb +389 -0
- data/lib/rubko/plugins/facebook.rb +50 -0
- data/lib/rubko/plugins/log.rb +49 -0
- data/lib/rubko/plugins/session.rb +88 -0
- data/lib/rubko/plugins/storage/db.rb +6 -0
- data/lib/rubko/plugins/storage/disk.rb +50 -0
- data/lib/rubko/plugins/storage/memory.rb +60 -0
- data/lib/rubko/plugins/url.rb +91 -0
- data/lib/rubko/socket.rb +23 -0
- data/lib/rubko/storage.rb +27 -0
- data/lib/rubko.rb +32 -0
- data/rubko.gemspec +22 -0
- data/stamp/.gitignore +3 -0
- data/stamp/config/db.rb +8 -0
- data/stamp/config/facebook.rb +8 -0
- data/stamp/config/session.rb +7 -0
- data/stamp/config/url.rb +7 -0
- data/stamp/config.ru +38 -0
- data/stamp/controllers/error404.rb +19 -0
- data/stamp/controllers/files.rb +20 -0
- data/stamp/controllers/welcome.rb +6 -0
- data/stamp/models/user.rb +14 -0
- data/stamp/public/css/.private/default.sass +31 -0
- data/stamp/public/img/favicon.png +0 -0
- data/stamp/public/js/jquery/iframize.js +25 -0
- data/stamp/public/js/jquery/translate.js +112 -0
- data/stamp/public/js/merge.sh +10 -0
- data/stamp/tarok.yml +17 -0
- data/stamp/views/welcome.haml +11 -0
- metadata +100 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 507cef7351098c01960413739e54b19d74ea872d
|
4
|
+
data.tar.gz: b6476fac467d2265b8777620e77b9557fc16e19f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 926e843d6848ceb3dccb87affd87b1c57998a8d38822517e2cbc02ef077cdde55fb2944d62741c7b67e04388cc2fcf6deea4b5fe59626fa47cf5ca33ce0ca19d
|
7
|
+
data.tar.gz: 35f3021ce7bae47895be95216f0358314dd93a5c47b972d94540aa0df94dfdfac662a1768f610c67a5ed37007fbf4f3342cc81650192dfa134be946c0905d032
|
data/.gitignore
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
*.gem
|
data/bin/rubko-deploy
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
# settings
|
4
|
+
|
5
|
+
ssh = true
|
6
|
+
host = 'hetzner:54321'
|
7
|
+
user = 'root'
|
8
|
+
remote = '/srv/http/' + File.basename(Dir.getwd)
|
9
|
+
|
10
|
+
exclude = [
|
11
|
+
'log.txt',
|
12
|
+
#'config/db.rb',
|
13
|
+
'.deploy.rb',
|
14
|
+
'.dev/',
|
15
|
+
'.run/',
|
16
|
+
'.repo/',
|
17
|
+
'.gitignore',
|
18
|
+
'.git/'
|
19
|
+
]
|
20
|
+
|
21
|
+
# program
|
22
|
+
|
23
|
+
require 'io/console'
|
24
|
+
print 'Password: ';
|
25
|
+
pass = STDIN.noecho(&:gets).strip
|
26
|
+
puts
|
27
|
+
|
28
|
+
protocol = ssh ? 'sftp' : 'ftp'
|
29
|
+
|
30
|
+
commands = [
|
31
|
+
'set ftp:list-options -a',
|
32
|
+
"open #{protocol}://#{user}:#{pass}@#{host}",
|
33
|
+
'lcd ./',
|
34
|
+
"cd #{remote}",
|
35
|
+
'mirror -L --reverse --only-newer --verbose ' + exclude.map { |el|
|
36
|
+
'--exclude-glob ' + el
|
37
|
+
}.join(' ')
|
38
|
+
]
|
39
|
+
|
40
|
+
system 'lftp', '-c', commands.join(';')
|
data/bin/rubko-init
ADDED
data/lib/rubko/app.rb
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'rubko/base'
|
2
|
+
require 'rubko/asset/gzipStream'
|
3
|
+
|
4
|
+
class Rubko::App
|
5
|
+
include Rubko::Base
|
6
|
+
|
7
|
+
def initialize(env, shared = nil)
|
8
|
+
@status = 200
|
9
|
+
@headers = {'Connection' => 'Keep-Alive', 'Date' => Time.now.httpdate}
|
10
|
+
@mime = 'text/html'
|
11
|
+
@body = ''
|
12
|
+
|
13
|
+
@shared = shared
|
14
|
+
@finalizers = []
|
15
|
+
|
16
|
+
@env = env
|
17
|
+
params = Rack::Utils.parse_nested_query @env['rack.input'].read
|
18
|
+
@params = Hash[ params.map { |k, v|
|
19
|
+
[ k.to_sym, v ]
|
20
|
+
} ]
|
21
|
+
|
22
|
+
super()
|
23
|
+
end
|
24
|
+
|
25
|
+
attr_accessor :status, :headers, :mime, :body
|
26
|
+
attr_reader :env, :params, :shared, :finalizers
|
27
|
+
|
28
|
+
def init(path)
|
29
|
+
url.path = path
|
30
|
+
request( *url.newPath )
|
31
|
+
end
|
32
|
+
|
33
|
+
def request(name = :welcome, action = nil, *path)
|
34
|
+
controller = loadController(name) || loadController(:error404)
|
35
|
+
|
36
|
+
calls = [ action ? "_#{action}" : 'index' ]
|
37
|
+
calls << calls.first + '_' + url.method
|
38
|
+
|
39
|
+
calls.map! { |call|
|
40
|
+
if controller.respond_to? call
|
41
|
+
@body = controller.__send__ call, *path
|
42
|
+
true
|
43
|
+
end
|
44
|
+
}
|
45
|
+
if calls.compact.empty?
|
46
|
+
@body = controller.other action, *path
|
47
|
+
end
|
48
|
+
|
49
|
+
# finalize request
|
50
|
+
finalizers.reverse_each(&:finalize)
|
51
|
+
@headers['Content-Type'] = "#{mime}; charset=utf-8" unless @status == 304
|
52
|
+
|
53
|
+
# make sure body responds to :each
|
54
|
+
@body = @body.to_s if Integer === @body
|
55
|
+
@body = [@body] if String === @body
|
56
|
+
@body = [] unless @body.respond_to? :each
|
57
|
+
|
58
|
+
# compress
|
59
|
+
if controller.compressible?
|
60
|
+
headers['Content-Encoding'] = 'gzip'
|
61
|
+
@body = Rubko::Asset::GzipStream.new @body
|
62
|
+
end
|
63
|
+
|
64
|
+
# add Content-Length header
|
65
|
+
if @body.respond_to? :bytesize
|
66
|
+
headers['Content-Length'] = @body.bytesize.to_s
|
67
|
+
elsif Array === @body
|
68
|
+
headers['Content-Length'] = @body.reduce(0) { |sum, x|
|
69
|
+
sum + x.bytesize
|
70
|
+
}.to_s
|
71
|
+
end
|
72
|
+
|
73
|
+
[@status, @headers, @body]
|
74
|
+
end
|
75
|
+
|
76
|
+
def production?
|
77
|
+
ENV['RACK_ENV'] == 'production'
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class Rubko::Asset::FileStream
|
2
|
+
def initialize(path, chunk = 32)
|
3
|
+
@path = path
|
4
|
+
@chunk = 1024*chunk
|
5
|
+
end
|
6
|
+
|
7
|
+
def each
|
8
|
+
File.open(@path, 'rb') { |f|
|
9
|
+
while part = f.read(@chunk)
|
10
|
+
yield part
|
11
|
+
end
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
def bytesize
|
16
|
+
File.size @path
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'rubko/controller'
|
2
|
+
require 'zlib'
|
3
|
+
|
4
|
+
class Rubko::Asset < Rubko::Controller
|
5
|
+
class GzipStream
|
6
|
+
def initialize(body, mtime = Time.now)
|
7
|
+
@body = body
|
8
|
+
@gzip = Zlib::GzipWriter.new self
|
9
|
+
@gzip.mtime = mtime
|
10
|
+
end
|
11
|
+
|
12
|
+
def each(&block)
|
13
|
+
@writer = block
|
14
|
+
@body.each { |part|
|
15
|
+
@gzip.write part
|
16
|
+
@gzip.flush
|
17
|
+
}
|
18
|
+
ensure
|
19
|
+
@gzip.close
|
20
|
+
end
|
21
|
+
|
22
|
+
def write(data)
|
23
|
+
@writer.call data
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/rubko/asset.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'rubko/controller'
|
2
|
+
|
3
|
+
# in case we want to serve files and get notified on hits
|
4
|
+
class Rubko::Asset < Rubko::Controller
|
5
|
+
|
6
|
+
def init
|
7
|
+
@dir = 'public'
|
8
|
+
end
|
9
|
+
|
10
|
+
attr_accessor :dir
|
11
|
+
|
12
|
+
def hit(*path)
|
13
|
+
puts "File #{path*'/'} hit." unless production?
|
14
|
+
end
|
15
|
+
|
16
|
+
def cache(*path)
|
17
|
+
end
|
18
|
+
|
19
|
+
def miss(*path)
|
20
|
+
puts "File #{path*'/'} not found (404)."
|
21
|
+
loadController(:error404).other( *path )
|
22
|
+
end
|
23
|
+
|
24
|
+
private :hit, :cache, :miss
|
25
|
+
|
26
|
+
def compressible?
|
27
|
+
super && @mime != 'application/octet-stream' &&
|
28
|
+
['application', 'text'].any? { |type|
|
29
|
+
@mime.start_with? type+'/'
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
attr_reader :mime, :modified
|
34
|
+
|
35
|
+
def index
|
36
|
+
other
|
37
|
+
end
|
38
|
+
|
39
|
+
def other(*path)
|
40
|
+
# protect private files
|
41
|
+
if path.include?('..') || path.include?('.private') && production?
|
42
|
+
return miss(*path)
|
43
|
+
end
|
44
|
+
|
45
|
+
path.shift if path[0] =~ /^\d*$/
|
46
|
+
path = "#{@dir}/#{path * '/'}"
|
47
|
+
@mime = Rack::Mime.mime_type File.extname(path)
|
48
|
+
if File.file? path
|
49
|
+
self.mime = @mime
|
50
|
+
headers['Cache-Control'] = 'public'
|
51
|
+
headers['Vary'] = 'Accept-Encoding'
|
52
|
+
|
53
|
+
@modified = File.mtime path
|
54
|
+
since = (Time.httpdate(env['HTTP_IF_MODIFIED_SINCE']).to_i rescue 0)
|
55
|
+
headers['Last-Modified'] = @modified.httpdate
|
56
|
+
headers['Expires'] = (DateTime.now >> 12).httpdate
|
57
|
+
|
58
|
+
if @modified.to_i <= since
|
59
|
+
cache( *path )
|
60
|
+
self.status = 304
|
61
|
+
''
|
62
|
+
else
|
63
|
+
hit( *path )
|
64
|
+
require 'rubko/asset/fileStream'
|
65
|
+
FileStream.new path
|
66
|
+
end
|
67
|
+
else
|
68
|
+
miss( *path )
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/lib/rubko/base.rb
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
require 'date'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
class Rubko
|
5
|
+
module Base
|
6
|
+
def initialize(parent = nil)
|
7
|
+
@parent = parent
|
8
|
+
finalizers << self if @parent
|
9
|
+
@plugins = {}
|
10
|
+
puts "#{self.class} initialized." unless production?
|
11
|
+
end
|
12
|
+
|
13
|
+
def init(*) end
|
14
|
+
def finalize(*) end
|
15
|
+
|
16
|
+
attr_accessor :parent
|
17
|
+
|
18
|
+
def loadFile(name)
|
19
|
+
require(name) || true
|
20
|
+
rescue LoadError
|
21
|
+
false
|
22
|
+
end
|
23
|
+
|
24
|
+
def camelize(array)
|
25
|
+
array.map { |x|
|
26
|
+
x.to_s.downcase.capitalize
|
27
|
+
}.join
|
28
|
+
end
|
29
|
+
def uncamelize(str)
|
30
|
+
str.to_s.split(/(?=[A-Z])/).map(&:downcase)
|
31
|
+
end
|
32
|
+
|
33
|
+
def load(what, name, *args)
|
34
|
+
Kernel.const_get(camelize [*[*name].reverse, what]).
|
35
|
+
new(self).tap { |x| x.init(*args) }
|
36
|
+
end
|
37
|
+
private :load
|
38
|
+
|
39
|
+
def loadPlugin(name, *args)
|
40
|
+
require 'rubko/plugin'
|
41
|
+
|
42
|
+
process = -> search, range, proc=nil {
|
43
|
+
p = Dir[search].sort_by { |x|
|
44
|
+
x.split('/').size
|
45
|
+
}.first
|
46
|
+
if p
|
47
|
+
loadFile p
|
48
|
+
p[range].split '/'
|
49
|
+
else
|
50
|
+
proc.call if proc
|
51
|
+
end
|
52
|
+
}
|
53
|
+
|
54
|
+
path = uncamelize(name).reverse * '/'
|
55
|
+
name = process.call "./plugins/**/#{path}.rb", 10..-4, -> {
|
56
|
+
d = __dir__
|
57
|
+
process.call "#{d}/plugins/**/#{path}.rb", (d.size+9)..-4
|
58
|
+
}
|
59
|
+
return false unless name
|
60
|
+
|
61
|
+
loadFile "./config/#{name * '/'}.rb"
|
62
|
+
load :plugin, name, *args
|
63
|
+
end
|
64
|
+
|
65
|
+
def loadController(name, *args)
|
66
|
+
require 'rubko/controller'
|
67
|
+
return false unless loadFile "./controllers/#{name}.rb"
|
68
|
+
load :controller, name, *args
|
69
|
+
end
|
70
|
+
|
71
|
+
def loadModel(name, *args)
|
72
|
+
require 'rubko/model'
|
73
|
+
return false unless loadFile "./models/#{name}.rb"
|
74
|
+
load :model, name, *args
|
75
|
+
end
|
76
|
+
|
77
|
+
def loadView(*name)
|
78
|
+
if production?
|
79
|
+
template = memory[:views, name]
|
80
|
+
end
|
81
|
+
unless template
|
82
|
+
fileName = 'views/'+name.join('/')+'.erb'
|
83
|
+
if File.exists? fileName
|
84
|
+
require 'erb'
|
85
|
+
template = ERB.new File.read(fileName)
|
86
|
+
else
|
87
|
+
fileName = 'views/'+name.join('/')+'.haml'
|
88
|
+
return unless File.exists? fileName
|
89
|
+
require 'haml'
|
90
|
+
template = Haml::Engine.new File.read(fileName), ugly: true, remove_whitespace: true
|
91
|
+
end
|
92
|
+
memory[:views, name] = template if production?
|
93
|
+
puts "Template #{name * '/'} initialized."
|
94
|
+
end
|
95
|
+
|
96
|
+
case template.class.to_s
|
97
|
+
when 'ERB'
|
98
|
+
template.result binding
|
99
|
+
when 'Haml::Engine'
|
100
|
+
template.render binding
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def method_missing(name, *args)
|
105
|
+
if @plugins && @plugins[name]
|
106
|
+
@plugins[name]
|
107
|
+
elsif parent
|
108
|
+
parent.__send__ name, *args
|
109
|
+
else
|
110
|
+
@plugins[name] = loadPlugin(name) || super
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def httpGet(url)
|
115
|
+
require 'net/http'
|
116
|
+
Net::HTTP.get_response(URI.parse url).body
|
117
|
+
end
|
118
|
+
|
119
|
+
def jsonParse(resource)
|
120
|
+
JSON.parse resource, symbolize_names: true
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'rubko/base'
|
2
|
+
|
3
|
+
class Rubko::Controller
|
4
|
+
include Rubko::Base
|
5
|
+
|
6
|
+
def index
|
7
|
+
'It works. Please create the index() method.'
|
8
|
+
end
|
9
|
+
|
10
|
+
def other(name, *args)
|
11
|
+
loadController('error404').other name, args
|
12
|
+
end
|
13
|
+
|
14
|
+
def compressible?
|
15
|
+
env['HTTP_ACCEPT_ENCODING'].to_s.split(',').map(&:strip).include? 'gzip'
|
16
|
+
end
|
17
|
+
end
|
data/lib/rubko/model.rb
ADDED
data/lib/rubko/plugin.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
class CookiePlugin < Rubko::Plugin
|
2
|
+
def init
|
3
|
+
@domain = nil
|
4
|
+
@path = url.base
|
5
|
+
@httpOnly = true
|
6
|
+
@secure = false
|
7
|
+
|
8
|
+
@maxAge = 30*24*60*60
|
9
|
+
@expires = nil
|
10
|
+
config
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_accessor :domain, :path, :httpOnly, :secure, :maxAge, :expires
|
14
|
+
|
15
|
+
def cookies
|
16
|
+
return @cookies if @cookies
|
17
|
+
return @cookies = {} unless env['HTTP_COOKIE']
|
18
|
+
|
19
|
+
@cookies = Rack::Utils.parse_query(env['HTTP_COOKIE'], ';,').
|
20
|
+
inject({}) { |h, (k,v)|
|
21
|
+
h.tap { |x|
|
22
|
+
x[k.to_sym] = (Array === v) ? v.first : v
|
23
|
+
}
|
24
|
+
}
|
25
|
+
end
|
26
|
+
private :cookies
|
27
|
+
|
28
|
+
def ip
|
29
|
+
Rack::Request.new(env).ip.encode 'UTF-8'
|
30
|
+
end
|
31
|
+
|
32
|
+
def [](key = nil)
|
33
|
+
key.nil? ? cookies : cookies[key]
|
34
|
+
end
|
35
|
+
|
36
|
+
def []=(key, val)
|
37
|
+
if val.nil?
|
38
|
+
Rack::Utils.delete_cookie_header! headers, key, domain: domain, path: path
|
39
|
+
else
|
40
|
+
Rack::Utils.set_cookie_header! headers, key, value: val, domain: domain, path: path,
|
41
|
+
httponly: httpOnly, secure: secure, max_age: maxAge.to_s, expires: expires
|
42
|
+
end
|
43
|
+
val
|
44
|
+
end
|
45
|
+
end
|