summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/zorglub.rb5
-rw-r--r--lib/zorglub/app.rb213
-rw-r--r--lib/zorglub/engines/file.rb20
-rw-r--r--lib/zorglub/engines/haml.rb26
-rw-r--r--lib/zorglub/engines/sass.rb27
-rw-r--r--lib/zorglub/node.rb546
-rw-r--r--lib/zorglub/rack_session.rb10
-rw-r--r--lib/zorglub/session.rb288
8 files changed, 557 insertions, 578 deletions
diff --git a/lib/zorglub.rb b/lib/zorglub.rb
index 586a184..b964bc5 100644
--- a/lib/zorglub.rb
+++ b/lib/zorglub.rb
@@ -1,11 +1,8 @@
#! /usr/bin/env ruby
-# -*- coding: UTF-8 -*-
module Zorglub
- VERSION = '0.1.0'
+ VERSION = '0.1.1'.freeze
end
require 'zorglub/node'
require 'zorglub/app'
-
-# EOF
diff --git a/lib/zorglub/app.rb b/lib/zorglub/app.rb
index 9619968..86adf1e 100644
--- a/lib/zorglub/app.rb
+++ b/lib/zorglub/app.rb
@@ -1,112 +1,113 @@
-# -*- coding: UTF-8 -*-
-
require 'rack'
module Zorglub
+ class App < Rack::URLMap
+ def initialize(map = {}, &block)
+ super
+ @map = map
+ @engines_cache = {}
+ @options = {
+ debug: false,
+ root: '.',
+ layout: 'default',
+ view_dir: 'view',
+ layout_dir: 'layout',
+ static_dir: 'static',
+ engine: nil,
+ engines_cache_enabled: true,
+ engines: {},
+ haml_options: {
+ format: :html5,
+ encoding: 'utf-8'
+ },
+ sass_options: {
+ syntax: :scss,
+ cache: false,
+ style: :compressed
+ },
+ session_options: {
+ enabled: false,
+ key: 'zorglub.sid',
+ secret: 'session-secret-secret',
+ sid_len: 64
+ }
+ }
+ instance_eval(&block) if block_given?
+ remap @map
+ end
+
+ attr_reader :engines_cache
+
+ def map(location, object)
+ return unless location && object
+ raise StandardError, "#{@map[location]} already mapped to #{location}" if @map.key? location
+
+ object.app = self
+ @map.merge! location.to_s => object
+ remap @map
+ end
+
+ def delete(location)
+ @map.delete location
+ remap @map
+ end
+
+ def at(location)
+ @map[location]
+ end
+
+ def to(object)
+ @map.invert[object]
+ end
+
+ def to_hash
+ @map.dup
+ end
+
+ # OPTIONS @options
+
+ def opt(sym)
+ @options[sym]
+ end
+
+ def opt!(sym, val)
+ @options[sym] = val
+ end
+
+ def register_engine!(name, ext, proc)
+ x = if ext.nil? || ext.empty?
+ nil
+ elsif ext[0] == '.'
+ ext.length == 1 ? nil : ext
+ else
+ ".#{ext}"
+ end
+ @options[:engines][name] = [proc, x]
+ end
+
+ def engine_proc_ext(engine, ext)
+ p, x = @options[:engines][engine]
+ return [nil, ''] if p.nil?
+
+ [p, ext.nil? || ext.empty? ? x : ext]
+ end
+
+ def view_base_path
+ _base_path @options[:view_path], :view_dir
+ end
+
+ def layout_base_path
+ _base_path @options[:layout_path], :layout_dir
+ end
+
+ def static_base_path
+ _base_path @options[:static_path], :static_dir
+ end
+
+ private
- class App < Rack::URLMap
-
- def initialize map={}, &block
- super
- @map = map
- @engines_cache = { }
- @options = {
- :debug => false,
- :root => '.',
- :layout => 'default',
- :view_dir => 'view',
- :layout_dir => 'layout',
- :static_dir => 'static',
- :engine => nil,
- :engines_cache_enabled => true,
- :engines => { },
- :haml_options => {
- :format => :html5,
- :encoding => 'utf-8'
- },
- :sass_options => {
- :syntax => :scss,
- :cache => :false,
- :style => :compressed
- },
- :session_options => {
- :enabled => false,
- :key => 'zorglub.sid',
- :secret => 'session-secret-secret',
- :sid_len => 64
- }
- }
- instance_eval &block if block_given?
- remap @map
- end
-
- attr_reader :engines_cache
-
- def map location, object
- return unless location and object
- raise Exception.new "#{@map[location]} already mapped to #{location}" if @map.has_key? location
- object.app = self
- @map.merge! location.to_s=>object
- remap @map
- end
-
- def delete location
- @map.delete location
- remap @map
- end
-
- def at location
- @map[location]
- end
-
- def to object
- @map.invert[object]
- end
-
- def to_hash
- @map.dup
- end
-
- # OPTIONS @options
-
- def opt sym
- @options[sym]
- end
-
- def opt! sym, val
- @options[sym] = val
- end
-
- def register_engine! name, ext, proc
- if ext.nil? or ext.empty?
- x = nil
- else
- x = (ext[0]=='.' ? (ext.length==1 ? nil : ext) : '.' + ext)
- end
- @options[:engines][name]=[ proc, x ]
- end
-
- def engine_proc_ext engine, ext
- p,x = @options[:engines][engine]
- return [nil, ''] if p.nil?
- [ p, ((ext.nil? or ext.empty?) ? x : ext ) ]
- end
-
- def view_base_path
- _base_path @options[:view_path], :view_dir
- end
-
- def layout_base_path
- _base_path @options[:layout_path], :layout_dir
- end
-
- def static_base_path
- _base_path @options[:static_path], :static_dir
- end
-
- private
- def _base_path p, sym
- ( p.nil? ? File.join(@options[:root], @options[sym]) : p )
- end
+ def _base_path(path, sym)
+ path.nil? ? File.join(@options[:root], @options[sym]) : path
end
+ end
end
diff --git a/lib/zorglub/engines/file.rb b/lib/zorglub/engines/file.rb
index dbf579d..748f701 100644
--- a/lib/zorglub/engines/file.rb
+++ b/lib/zorglub/engines/file.rb
@@ -1,18 +1,14 @@
-# -*- coding: UTF-8 -*-
-
require 'haml/util'
require 'haml/engine'
module Zorglub
- module Engines
- module File
- def self.proc path,obj
- content = ::File.open(path,'r'){|f| f.read }
- ext = path.sub /.*\.(.+)$/,'\1'
- return content, "text/#{ext}"
- end
- end
+ module Engines
+ module File
+ def self.proc(path, _obj)
+ content = ::File.read(path)
+ ext = path.sub(/.*\.(.+)$/, '\1')
+ [content, "text/#{ext}"]
+ end
end
+ end
end
-
-# EOF
diff --git a/lib/zorglub/engines/haml.rb b/lib/zorglub/engines/haml.rb
index e5013f8..b602773 100644
--- a/lib/zorglub/engines/haml.rb
+++ b/lib/zorglub/engines/haml.rb
@@ -1,22 +1,18 @@
-# -*- coding: UTF-8 -*-
-
require 'haml/util'
require 'haml/template'
module Zorglub
- module Engines
- module Haml
- def self.proc path,obj
- haml = ::Haml::Template.new( path )
- if obj.app.opt(:engines_cache_enabled)
- key = path.sub obj.app.opt(:root),''
- obj.app.engines_cache[key] ||= haml
- end
- html = haml.render(obj, obj.app.opt(:haml_options))
- return html, 'text/html'
- end
+ module Engines
+ module Haml
+ def self.proc(path, obj)
+ haml = ::Haml::Template.new(path)
+ if obj.app.opt(:engines_cache_enabled)
+ key = path.sub obj.app.opt(:root), ''
+ obj.app.engines_cache[key] ||= haml
end
+ html = haml.render(obj, obj.app.opt(:haml_options))
+ [html, 'text/html']
+ end
end
+ end
end
-
-# EOF
diff --git a/lib/zorglub/engines/sass.rb b/lib/zorglub/engines/sass.rb
index bc6b759..44973d5 100644
--- a/lib/zorglub/engines/sass.rb
+++ b/lib/zorglub/engines/sass.rb
@@ -1,22 +1,17 @@
-# -*- coding: UTF-8 -*-
-
require 'sass'
module Zorglub
- module Engines
- module Sass
- def self.proc path,obj
- if obj.app.opt(:engines_cache_enabled)
- key = path.sub obj.app.opt(:root),''
- sass = obj.app.engines_cache[key] ||= ::Sass::Engine.new( ::File.open(path,'r'){|f| f.read }, obj.app.opt(:sass_options) )
- else
- sass = ::Sass::Engine.new( ::File.open(path,'r'){|f| f.read }, obj.app.opt(:sass_options) )
- end
- css = sass.render
- return css, 'text/css'
- end
+ module Engines
+ module Sass
+ def self.proc(path, obj)
+ sass = ::Sass::Engine.new(::File.read(path), obj.app.opt(:sass_options))
+ if obj.app.opt(:engines_cache_enabled)
+ key = path.sub obj.app.opt(:root), ''
+ obj.app.engines_cache[key] ||= sass
end
+ css = sass.render
+ [css, 'text/css']
+ end
end
+ end
end
-
-# EOF
diff --git a/lib/zorglub/node.rb b/lib/zorglub/node.rb
index b360a5c..84cba92 100644
--- a/lib/zorglub/node.rb
+++ b/lib/zorglub/node.rb
@@ -1,334 +1,334 @@
-# -*- coding: UTF-8 -*-
-
require 'fileutils'
module Zorglub
+ class Node
+ UNDEFINED = -1
- class Node
-
- UNDEFINED=-1
-
- # class level engine, layout, static, layout_base_path, view_base_path configuration
+ # class level engine, layout, static, layout_base_path, view_base_path configuration
- class << self
+ class << self
+ attr_reader :static, :cache_lifetime
- attr_reader :static, :cache_lifetime
+ def engine!(engine)
+ @engine = engine
+ end
- def engine! engine
- @engine = engine
- end
+ def engine
+ @engine = @app.opt(:engine) if @engine == UNDEFINED && @app
+ @engine
+ end
- def engine
- @engine = @app.opt(:engine) if @engine==UNDEFINED and @app
- @engine
- end
+ def no_layout!
+ layout! nil
+ end
- def no_layout!
- layout! nil
- end
+ def layout!(layout)
+ @layout = layout
+ end
- def layout! layout
- @layout = layout
- end
+ def layout
+ @layout = @app.opt(:layout) if @layout == UNDEFINED && @app
+ @layout
+ end
- def layout
- @layout = @app.opt(:layout) if @layout==UNDEFINED and @app
- @layout
- end
+ def static!(val, lifetime = 0)
+ @static = [true, false].include?(val) ? val : false
+ @cache_lifetime = lifetime
+ end
- def static! val, lifetime=0
- @static = ( (val==true or val==false) ? val : false )
- @cache_lifetime = lifetime
- end
+ def layout_base_path!(path)
+ @layout_base_path = path
+ end
- def layout_base_path! path
- @layout_base_path = path
- end
+ def layout_base_path
+ @layout_base_path ||= @app.layout_base_path
+ end
- def layout_base_path
- @layout_base_path ||= @app.layout_base_path
- end
+ def view_base_path!(path)
+ @view_base_path = path
+ end
- def view_base_path! path
- @view_base_path = path
- end
-
- def view_base_path
- @view_base_path ||= @app.view_base_path
- end
- end
-
- # instance level engine, layout, view, static configuration
+ def view_base_path
+ @view_base_path ||= @app.view_base_path
+ end
+ end
- def engine! engine
- @engine = engine
- end
+ # instance level engine, layout, view, static configuration
- def no_layout!
- layout! nil
- end
+ def engine!(engine)
+ @engine = engine
+ end
- def layout! layout
- @layout = layout
- end
+ def no_layout!
+ layout! nil
+ end
- def layout
- return nil if @layout.nil?
- File.join(self.class.layout_base_path, @layout) + ext
- end
+ def layout!(layout)
+ @layout = layout
+ end
- def no_view!
- view! nil
- end
+ def layout
+ return nil if @layout.nil?
- def view! view
- @view = view
- end
+ File.join(self.class.layout_base_path, @layout) + ext
+ end
- def view
- return nil if @view.nil?
- File.join(self.class.view_base_path, @view) + ext
- end
+ def no_view!
+ view! nil
+ end
- def static! val, lifetime=0
- @static = ( (val==true or val==false) ? val : false )
- @cache_lifetime = lifetime
- end
+ def view!(view)
+ @view = view
+ end
- def static
- return nil if not @static or @view.nil?
- File.join(app.static_base_path, @view) + ext
- end
+ def view
+ return nil if @view.nil?
- def ext! ext
- @ext = ( (ext.nil? or ext.empty?) ? nil : (ext[0]=='.' ? (ext.length==1 ? nil : ext) : '.' + ext) )
- end
+ File.join(self.class.view_base_path, @view) + ext
+ end
- def ext
- @ext || ''
- end
+ def static!(val, lifetime = 0)
+ @static = [true, false].include?(val) ? val : false
+ @cache_lifetime = lifetime
+ end
- def mime! mime
- @mime = mime
- end
+ def static
+ return nil if !@static || @view.nil?
- # class level basic node functions
+ File.join(app.static_base_path, @view) + ext
+ end
- class << self
+ def ext!(ext)
+ @ext = if ext.nil? || ext.empty?
+ nil
+ elsif ext[0] == '.'
+ ext.length == 1 ? nil : ext
+ else
+ ".#{ext}"
+ end
+ end
- attr_accessor :app
- def map app, location
- @app = app
- @app.map location, self
- end
+ def ext
+ @ext || ''
+ end
- def r *args
- @r ||= @app.to self
- (args.empty? ? @r : File.join( @r, args.map { |x| x.to_s } ) )
- end
+ def mime!(mime)
+ @mime = mime
+ end
- end
+ # class level basic node functions
- # instance level basic node functions
+ class << self
+ attr_accessor :app
- def app
- self.class.app
- end
+ def map(app, location)
+ @app = app
+ @app.map location, self
+ end
- def map
- self.class.r
- end
+ def r *args
+ @r ||= @app.to self
+ args.empty? ? @r : File.join(@r, args.map(&:to_s))
+ end
+ end
- def r *args
- File.join map, (args.empty? ? meth : args.map { |x| x.to_s } )
- end
+ # instance level basic node functions
- def html
- [ :map, :r, :args, :engine, :layout, :view ].inject('') { |s,sym| s+="<p>#{sym} => #{self.send sym}</p>"; s }
- end
+ def app
+ self.class.app
+ end
- def redirect target, options={}, &block
- status = options[:status] || 302
- body = options[:body] || redirect_body(target)
- header = response.headers.merge('Location' => target.to_s)
- throw :stop_realize, Rack::Response.new(body, status, header, &block)
- end
+ def map
+ self.class.r
+ end
- def redirect_body target
- "You are being redirected, please follow this link to: <a href='#{target}'>#{target}</a>!"
- end
+ def r *args
+ File.join map, (args.empty? ? meth : args.map(&:to_s))
+ end
- # class level inherited values are key=>array, copied at inheritance
- # so they can be extanded at class level
- # values are copied from class into instance at object creation
- # so that can be extanded without modifying class level values
- # typical usage are css or js inclusions
+ def html
+ %i[map r args engine layout view].inject('') { |s, sym| s + "<p>#{sym} => #{send sym}</p>" }
+ end
- @cli_vals = { }
+ def redirect(target, options = {}, &block)
+ status = options[:status] || 302
+ body = options[:body] || redirect_body(target)
+ header = response.headers.merge('Location' => target.to_s)
+ throw :stop_realize, Rack::Response.new(body, status, header, &block)
+ end
- class << self
+ def redirect_body(target)
+ "You are being redirected, please follow this link to: <a href='#{target}'>#{target}</a>!"
+ end
- attr_reader :cli_vals
+ # class level inherited values are key=>array, copied at inheritance
+ # so they can be extanded at class level
+ # values are copied from class into instance at object creation
+ # so that can be extanded without modifying class level values
+ # typical usage are css or js inclusions
- def cli_val sym, *args
- vals = @cli_vals[sym] ||= []
- unless args.empty?
- vals.concat args
- vals.uniq!
- end
- vals
- end
+ @cli_vals = {}
- end
+ class << self
+ attr_reader :cli_vals
- def cli_val sym, *args
- vals = @cli_vals[sym] ||= []
- unless args.empty?
- vals.concat args
- vals.uniq!
- end
- vals
+ def cli_val(sym, *args)
+ vals = @cli_vals[sym] ||= []
+ unless args.empty?
+ vals.concat args
+ vals.uniq!
end
+ vals
+ end
+ end
- # before_all and after_all hooks
-
- @cli_vals[:before_all] = []
- @cli_vals[:after_all] = []
- class << self
-
- def call_before_hooks obj
- @cli_vals[:before_all].each do |blk| blk.call obj end
- end
-
- def before_all meth=nil, &blk
- @cli_vals[:before_all]<< ( meth.nil? ? blk : meth )
- @cli_vals[:before_all].uniq!
- end
-
- def call_after_hooks obj
- @cli_vals[:after_all].each do |blk| blk.call obj end
- end
+ def cli_val(sym, *args)
+ vals = @cli_vals[sym] ||= []
+ unless args.empty?
+ vals.concat args
+ vals.uniq!
+ end
+ vals
+ end
- def after_all meth=nil, &blk
- @cli_vals[:after_all]<< ( meth.nil? ? blk : meth )
- @cli_vals[:after_all].uniq!
- end
+ # before_all and after_all hooks
- end
+ @cli_vals[:before_all] = []
+ @cli_vals[:after_all] = []
+ class << self
+ def call_before_hooks(obj)
+ @cli_vals[:before_all].each { |blk| blk.call obj }
+ end
- # rack entry point, page computation methods
-
- class << self
-
- def inherited sub
- sub.engine! ( engine || (self==Zorglub::Node ? UNDEFINED : nil ) )
- sub.layout! ( layout || (self==Zorglub::Node ? UNDEFINED : nil ) )
- sub.instance_variable_set :@cli_vals, {}
- @cli_vals.each do |s,v| sub.cli_val s, *v end
- end
-
- def call env
- meth, *args = env['PATH_INFO'].sub(/^\/+/,'').split(/\//)
- meth ||= 'index'
- $stderr << "=> #{meth}(#{args.join ','})\n" if app.opt :debug
- node = self.new env, meth, args
- return error_404 node, meth if not node.respond_to? meth
- node.realize!
- end
-
- def partial env, meth, *args
- node = self.new env, meth.to_s, args, true
- return error_404 node, meth if not node.respond_to? meth
- node.feed! env[:no_hooks]
- node.content
- end
-
- def error_404 node, meth
- $stderr << " !! #{node.class.name}::#{meth} not found\n" if app.opt :debug
- resp = node.response
- resp.status = 404
- resp['Content-Type'] = 'text/plain'
- resp.write "%s mapped at %p can't respond to : %p" % [ node.class.name, node.map, node.meth ]
- resp
- end
+ def before_all(meth = nil, &blk)
+ @cli_vals[:before_all] << (meth.nil? ? blk : meth)
+ @cli_vals[:before_all].uniq!
+ end
- end
+ def call_after_hooks(obj)
+ @cli_vals[:after_all].each { |blk| blk.call obj }
+ end
- attr_reader :request, :response, :content, :mime, :state, :engine, :meth, :args
-
- def initialize env, meth, args, partial=false
- @meth = meth
- @args = args
- @partial = partial
- @request = Rack::Request.new env
- @response = Rack::Response.new
- @cli_vals ={}
- @debug = app.opt :debug
- @engine = self.class.engine
- @layout = ( partial ? nil : self.class.layout )
- @view = r(meth)
- @static = self.class.static
- @cache_lifetime = self.class.cache_lifetime
- self.class.cli_vals.each do |s,v| cli_val s, *v end
- end
+ def after_all(meth = nil, &blk)
+ @cli_vals[:after_all] << (meth.nil? ? blk : meth)
+ @cli_vals[:after_all].uniq!
+ end
+ end
- def realize!
- catch(:stop_realize) {
- feed!
- response.write @content
- response.headers['Content-Type'] ||= ( @mime || 'text/html' )
- response.finish
- response
- }
- end
+ # rack entry point, page computation methods
+
+ class << self
+ def inherited(sub)
+ super
+ sub.engine!(engine || (self == Zorglub::Node ? UNDEFINED : nil))
+ sub.layout!(layout || (self == Zorglub::Node ? UNDEFINED : nil))
+ sub.instance_variable_set :@cli_vals, {}
+ @cli_vals.each { |s, v| sub.cli_val s, *v }
+ end
+
+ def call(env)
+ meth, *args = env['PATH_INFO'].sub(%r{^/+}, '').split(%r{/})
+ meth ||= 'index'
+ $stderr << "=> #{meth}(#{args.join ','})\n" if app.opt :debug
+ node = new(env, meth, args)
+ return error404 node, meth unless node.respond_to? meth
+
+ node.realize!
+ end
+
+ def partial(env, meth, *args)
+ node = new env, meth.to_s, args, true
+ return error404 node, meth unless node.respond_to? meth
+
+ node.feed! env[:no_hooks]
+ node.content
+ end
+
+ def error404(node, meth)
+ $stderr << " !! #{node.class.name}::#{meth} not found\n" if app.opt :debug
+ resp = node.response
+ resp.status = 404
+ resp['Content-Type'] = 'text/plain'
+ resp.write "%<node.class.name>s mapped at %<node.map>p can't respond to : %<node.meth>p"
+ resp
+ end
+ end
- def feed! no_hooks=false
- @state = :pre_cb
- self.class.call_before_hooks self unless no_hooks
- @state = :meth
- @content = self.send @meth, *@args
- static_path = static
- if static_path.nil?
- compile_page!
- else
- static_page! static_path
- end
- @state = :post_cb
- self.class.call_after_hooks self unless no_hooks
- @state = :finished
- return @content, @mime
- end
+ attr_reader :request, :response, :content, :mime, :state, :engine, :meth, :args
+
+ def initialize(env, meth, args, partial = false)
+ @meth = meth
+ @args = args
+ @partial = partial
+ @request = Rack::Request.new env
+ @response = Rack::Response.new
+ @cli_vals = {}
+ @debug = app.opt :debug
+ @engine = self.class.engine
+ @layout = (partial ? nil : self.class.layout)
+ @view = r(meth)
+ @static = self.class.static
+ @cache_lifetime = self.class.cache_lifetime
+ self.class.cli_vals.each { |s, v| cli_val s, *v }
+ end
- def static_page! path
- if File.exist?(path) and ( @cache_lifetime.nil? or @cache_lifetime==0 or ( (Time.now-File.stat(path).mtime) < @cache_lifetime ) )
- $stderr << " * use cache file : #{path}\n" if @debug
- content = File.open(path, 'r') {|f| f.read }
- @content = content.sub /^@mime:(.*)\n/,''
- @mime = $1
- else
- compile_page!
- FileUtils.mkdir_p File.dirname(path)
- File.open(path, 'w') {|f| f.write("@mime:"+@mime+"\n"); f.write(@content); }
- $stderr << " * cache file created : #{path}\n" if @debug
- end
- end
+ def realize!
+ catch(:stop_realize) do
+ feed!
+ response.write @content
+ response.headers['Content-Type'] ||= @mime || 'text/html'
+ response.finish
+ response
+ end
+ end
- def compile_page!
- e, @ext = app.engine_proc_ext @engine, @ext
- v, l = view, layout
- if @debug
- $stderr << " * "+(e ? 'use engine' : 'no engine ')+" : "+(e ? e.to_s : '')+"\n"
- $stderr << " * "+((l and File.exist?(l)) ? 'use layout' : 'no layout ')+" : "+(l ? l : '')+"\n"
- $stderr << " * "+((v and File.exist?(v)) ? 'use view ' : 'no view ')+" : "+(v ? v : '')+"\n"
- end
- @state = ( @partial ? :partial : :view )
- @content, mime = e.call v, self if e and v and File.exist? v
- @mime ||= mime
- @state = :layout
- @content, mime = e.call l, self if e and l and File.exist? l
- @mime = mime if @mime.nil? and not mime.nil?
- end
+ def feed!(no_hooks = false)
+ @state = :pre_cb
+ self.class.call_before_hooks self unless no_hooks
+ @state = :meth
+ @content = send @meth, *@args
+ static_path = static
+ if static_path.nil?
+ compile_page!
+ else
+ static_page! static_path
+ end
+ @state = :post_cb
+ self.class.call_after_hooks self unless no_hooks
+ @state = :finished
+ [@content, @mime]
+ end
+ def static_page!(path)
+ if File.exist?(path) && (@cache_lifetime.nil? || @cache_lifetime.zero? ||
+ (Time.now - File.stat(path).mtime) < @cache_lifetime)
+ $stderr << " * use cache file : #{path}\n" if @debug
+ content = File.read(path)
+ @content = content.sub(/^@mime:(.*)\n/, '')
+ @mime = ::Regexp.last_match(1)
+ else
+ compile_page!
+ FileUtils.mkdir_p File.dirname(path)
+ File.open(path, 'w') { |f| f.write("@mime:#{@mime}\n#{@content}") }
+ $stderr << " * cache file created : #{path}\n" if @debug
+ end
end
+ def compile_page!
+ e, @ext = app.engine_proc_ext @engine, @ext
+ v = view
+ l = layout
+ if @debug
+ $stderr << " * #{e ? 'use engine' : 'no engine '} : #{e ? e.to_s : ''}\n"
+ $stderr << " * #{l && File.exist?(l) ? 'use layout' : 'no layout '} : #{l || ''}\n"
+ $stderr << " * #{v && File.exist?(v) ? 'use view ' : 'no view '} : #{v || ''}\n"
+ end
+ @state = @partial ? :partial : :view
+ @content, mime = e.call(v, self) if e && v && File.exist?(v)
+ @mime ||= mime
+ @state = :layout
+ @content, mime = e.call(l, self) if e && l && File.exist?(l)
+ @mime = mime if @mime.nil? && !mime.nil?
+ end
+ end
end
diff --git a/lib/zorglub/rack_session.rb b/lib/zorglub/rack_session.rb
index d08cd84..c78bb37 100644
--- a/lib/zorglub/rack_session.rb
+++ b/lib/zorglub/rack_session.rb
@@ -1,9 +1,7 @@
-# -*- coding: UTF-8 -*-
-
module Zorglub
- class Node
- def session
- @request.session
- end
+ class Node
+ def session
+ @request.session
end
+ end
end
diff --git a/lib/zorglub/session.rb b/lib/zorglub/session.rb
index fc5fdbe..05b91d6 100644
--- a/lib/zorglub/session.rb
+++ b/lib/zorglub/session.rb
@@ -1,152 +1,148 @@
-# -*- coding: UTF-8 -*-
-
require 'securerandom'
module Zorglub
+ class Node
+ @sessions = {}
+
+ class << self
+ attr_reader :sessions
+ end
+
+ def session
+ @session ||= SessionHash.new @request, @response, Node.sessions, app.opt(:session_options)
+ end
+ end
+
+ class SessionHash < Hash
+ def initialize(req, resp, sessions, options)
+ @request = req
+ @response = resp
+ @sessions = sessions
+ @sid = nil
+ @options = options
+ super()
+ end
+
+ def [](key)
+ load_data!
+ super key
+ end
+
+ def key?(key)
+ load_data!
+ super key
+ end
+ alias include? key?
+
+ def []=(key, value)
+ load_data!
+ super key, value
+ end
+
+ def clear
+ load_data!
+ # @response.delete_cookie @options[:key]
+ # @sessions.delete @sid
+ # @sid = nil
+ super
+ end
+
+ def to_hash
+ load_data!
+ h = {}.replace(self)
+ h.delete_if { |_k, v| v.nil? }
+ h
+ end
+
+ def update(hash)
+ load_data!
+ super stringify_keys(hash)
+ end
+
+ def delete(key)
+ load_data!
+ super key
+ end
+
+ def inspect
+ if loaded?
+ super
+ else
+ "#<#{self.class}:0x#{object_id.to_s(16)} not yet loaded>"
+ end
+ end
+
+ def exists?
+ loaded? ? @sessions.key?(@sid) : false
+ end
+
+ def loaded?
+ !@sid.nil?
+ end
+
+ def empty?
+ load_data!
+ super
+ end
+
+ private
+
+ def load_data!
+ return if loaded?
+ return unless @options[:enabled]
+
+ sid = @request.cookies[@options[:key]]
+ if sid.nil?
+ sid = generate_sid!
+ @response.set_cookie @options[:key], sid
+ end
+ replace @sessions[sid] ||= {}
+ @sessions[sid] = self
+ @sid = sid
+ end
+
+ def stringify_keys(other)
+ hash = {}
+ other.each do |key, value|
+ hash[key] = value
+ end
+ hash
+ end
+
+ def generate_sid!
+ begin sid = sid_algorithm end while @sessions.key? sid
+ sid
+ end
- class Node
-
- @sessions = {}
-
- class << self
- attr_reader :sessions
- end
-
- def session
- @session ||= SessionHash.new @request, @response, Node.sessions, app.opt(:session_options)
- end
- end
-
- class SessionHash < Hash
-
- def initialize req, resp, sessions, options
- @request = req
- @response = resp
- @sessions = sessions
- @sid = nil
- @options = options
- super()
- end
-
- def [] key
- load_data!
- super key
- end
-
- def has_key? key
- load_data!
- super key
- end
- alias :key? :has_key?
- alias :include? :has_key?
-
- def []= key, value
- load_data!
- super key, value
- end
-
- def clear
- load_data!
- # @response.delete_cookie @options[:key]
- # @sessions.delete @sid
- # @sid = nil
- super
- end
-
- def to_hash
- load_data!
- h = {}.replace(self)
- h.delete_if { |k,v| v.nil? }
- h
- end
-
- def update hash
- load_data!
- super stringify_keys(hash)
- end
-
- def delete key
- load_data!
- super key
- end
-
- def inspect
- if loaded?
- super
- else
- "#<#{self.class}:0x#{self.object_id.to_s(16)} not yet loaded>"
- end
- end
-
- def exists?
- ( loaded? ? @sessions.has_key?(@sid) : false )
- end
-
- def loaded?
- not @sid.nil?
- end
-
- def empty?
- load_data!
- super
- end
-
- private
-
- def load_data!
- return if loaded?
- if @options[:enabled]
- sid = @request.cookies[@options[:key]]
- if sid.nil?
- sid = generate_sid!
- @response.set_cookie @options[:key], sid
- end
- replace @sessions[sid] ||={}
- @sessions[sid] = self
- @sid = sid
- end
- end
-
- def stringify_keys other
- hash = {}
- other.each do |key, value|
- hash[key] = value
- end
- hash
- end
-
- def generate_sid!
- begin sid = sid_algorithm end while @sessions.has_key? sid
- sid
- end
-
- begin
- require 'securerandom'
- # Using SecureRandom, optional length.
- # SecureRandom is available since Ruby 1.8.7.
- # For Ruby versions earlier than that, you can require the uuidtools gem,
- # which has a drop-in replacement for SecureRandom.
- def sid_algorithm; SecureRandom.hex(@options[:sid_len]); end
- rescue LoadError
- require 'openssl'
- # Using OpenSSL::Random for generation, this is comparable in performance
- # with stdlib SecureRandom and also allows for optional length, it should
- # have the same behaviour as the SecureRandom::hex method of the
- # uuidtools gem.
- def sid_algorithm
- OpenSSL::Random.random_bytes(@options[:sid_len] / 2).unpack('H*')[0]
- end
- rescue LoadError
- # Digest::SHA2::hexdigest produces a string of length 64, although
- # collisions are not very likely, the entropy is still very low and
- # length is not optional.
- #
- # Replacing it with OS-provided random data would take a lot of code and
- # won't be as cross-platform as Ruby.
- def sid_algorithm
- entropy = [ srand, rand, Time.now.to_f, rand, $$, rand, object_id ]
- Digest::SHA2.hexdigest(entropy.join)
- end
- end
+ begin
+ require 'securerandom'
+ # Using SecureRandom, optional length.
+ # SecureRandom is available since Ruby 1.8.7.
+ # For Ruby versions earlier than that, you can require the uuidtools gem,
+ # which has a drop-in replacement for SecureRandom.
+ def sid_algorithm
+ SecureRandom.hex(@options[:sid_len])
+ end
+ rescue LoadError
+ require 'openssl'
+ # Using OpenSSL::Random for generation, this is comparable in performance
+ # with stdlib SecureRandom and also allows for optional length, it should
+ # have the same behaviour as the SecureRandom::hex method of the
+ # uuidtools gem.
+ def sid_algorithm
+ OpenSSL::Random.random_bytes(@options[:sid_len] / 2).unpack1('H*')[0]
+ end
+ rescue LoadError
+ # Digest::SHA2::hexdigest produces a string of length 64, although
+ # collisions are not very likely, the entropy is still very low and
+ # length is not optional.
+ #
+ # Replacing it with OS-provided random data would take a lot of code and
+ # won't be as cross-platform as Ruby.
+ def sid_algorithm
+ entropy = [srand, rand, Time.now.to_f, rand, $$, rand, object_id]
+ Digest::SHA2.hexdigest(entropy.join)
+ end
end
+ end
end