rubko 0.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.
Files changed (43) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/bin/rubko-deploy +40 -0
  4. data/bin/rubko-init +6 -0
  5. data/lib/rubko/app.rb +79 -0
  6. data/lib/rubko/asset/fileStream.rb +18 -0
  7. data/lib/rubko/asset/gzipStream.rb +26 -0
  8. data/lib/rubko/asset.rb +71 -0
  9. data/lib/rubko/base.rb +123 -0
  10. data/lib/rubko/controller.rb +17 -0
  11. data/lib/rubko/model.rb +5 -0
  12. data/lib/rubko/plugin.rb +7 -0
  13. data/lib/rubko/plugins/cookie.rb +45 -0
  14. data/lib/rubko/plugins/db.rb +389 -0
  15. data/lib/rubko/plugins/facebook.rb +50 -0
  16. data/lib/rubko/plugins/log.rb +49 -0
  17. data/lib/rubko/plugins/session.rb +88 -0
  18. data/lib/rubko/plugins/storage/db.rb +6 -0
  19. data/lib/rubko/plugins/storage/disk.rb +50 -0
  20. data/lib/rubko/plugins/storage/memory.rb +60 -0
  21. data/lib/rubko/plugins/url.rb +91 -0
  22. data/lib/rubko/socket.rb +23 -0
  23. data/lib/rubko/storage.rb +27 -0
  24. data/lib/rubko.rb +32 -0
  25. data/rubko.gemspec +22 -0
  26. data/stamp/.gitignore +3 -0
  27. data/stamp/config/db.rb +8 -0
  28. data/stamp/config/facebook.rb +8 -0
  29. data/stamp/config/session.rb +7 -0
  30. data/stamp/config/url.rb +7 -0
  31. data/stamp/config.ru +38 -0
  32. data/stamp/controllers/error404.rb +19 -0
  33. data/stamp/controllers/files.rb +20 -0
  34. data/stamp/controllers/welcome.rb +6 -0
  35. data/stamp/models/user.rb +14 -0
  36. data/stamp/public/css/.private/default.sass +31 -0
  37. data/stamp/public/img/favicon.png +0 -0
  38. data/stamp/public/js/jquery/iframize.js +25 -0
  39. data/stamp/public/js/jquery/translate.js +112 -0
  40. data/stamp/public/js/merge.sh +10 -0
  41. data/stamp/tarok.yml +17 -0
  42. data/stamp/views/welcome.haml +11 -0
  43. 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
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require 'fileutils'
4
+
5
+ stamp = File.expand_path '../stamp', __dir__
6
+ FileUtils.cp_r Dir["#{stamp}/*"], '.'
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
@@ -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
@@ -0,0 +1,5 @@
1
+ require 'rubko/base'
2
+
3
+ class Rubko::Model
4
+ include Rubko::Base
5
+ end
@@ -0,0 +1,7 @@
1
+ require 'rubko/base'
2
+
3
+ class Rubko::Plugin
4
+ include Rubko::Base
5
+
6
+ def config; end
7
+ end
@@ -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