egalite 0.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 (113) hide show
  1. data/.gitignore +17 -0
  2. data/README.md +91 -0
  3. data/auth/basic.rb +32 -0
  4. data/blank.rb +53 -0
  5. data/egalite.rb +742 -0
  6. data/errorconsole.rb +77 -0
  7. data/examples/simple/example.rb +39 -0
  8. data/examples/simple/pages/test.html +15 -0
  9. data/examples/simple_db/example_db.rb +103 -0
  10. data/examples/simple_db/pages/edit.html +6 -0
  11. data/helper.rb +251 -0
  12. data/keitai/keitai.rb +107 -0
  13. data/keitai/ketai.rb +11 -0
  14. data/keitai/rack/ketai/carrier/abstract.rb +131 -0
  15. data/keitai/rack/ketai/carrier/au.rb +78 -0
  16. data/keitai/rack/ketai/carrier/docomo.rb +80 -0
  17. data/keitai/rack/ketai/carrier/emoji/ausjisstrtoemojiid.rb +1391 -0
  18. data/keitai/rack/ketai/carrier/emoji/docomosjisstrtoemojiid.rb +759 -0
  19. data/keitai/rack/ketai/carrier/emoji/emojidata.rb +836 -0
  20. data/keitai/rack/ketai/carrier/emoji/softbankutf8strtoemojiid.rb +1119 -0
  21. data/keitai/rack/ketai/carrier/emoji/softbankwebcodetoutf8str.rb +499 -0
  22. data/keitai/rack/ketai/carrier/iphone.rb +8 -0
  23. data/keitai/rack/ketai/carrier/softbank.rb +82 -0
  24. data/keitai/rack/ketai/carrier.rb +17 -0
  25. data/keitai/rack/ketai/middleware.rb +24 -0
  26. data/m17n.rb +193 -0
  27. data/rack/auth/abstract/handler.rb +37 -0
  28. data/rack/auth/abstract/request.rb +37 -0
  29. data/rack/auth/basic.rb +58 -0
  30. data/rack/auth/digest/md5.rb +124 -0
  31. data/rack/auth/digest/nonce.rb +51 -0
  32. data/rack/auth/digest/params.rb +55 -0
  33. data/rack/auth/digest/request.rb +40 -0
  34. data/rack/builder.rb +80 -0
  35. data/rack/cascade.rb +41 -0
  36. data/rack/chunked.rb +49 -0
  37. data/rack/commonlogger.rb +49 -0
  38. data/rack/conditionalget.rb +47 -0
  39. data/rack/config.rb +15 -0
  40. data/rack/content_length.rb +29 -0
  41. data/rack/content_type.rb +23 -0
  42. data/rack/deflater.rb +96 -0
  43. data/rack/directory.rb +157 -0
  44. data/rack/etag.rb +32 -0
  45. data/rack/file.rb +92 -0
  46. data/rack/handler/cgi.rb +62 -0
  47. data/rack/handler/evented_mongrel.rb +8 -0
  48. data/rack/handler/fastcgi.rb +89 -0
  49. data/rack/handler/lsws.rb +63 -0
  50. data/rack/handler/mongrel.rb +90 -0
  51. data/rack/handler/scgi.rb +59 -0
  52. data/rack/handler/swiftiplied_mongrel.rb +8 -0
  53. data/rack/handler/thin.rb +18 -0
  54. data/rack/handler/webrick.rb +73 -0
  55. data/rack/handler.rb +88 -0
  56. data/rack/head.rb +19 -0
  57. data/rack/lint.rb +567 -0
  58. data/rack/lobster.rb +65 -0
  59. data/rack/lock.rb +16 -0
  60. data/rack/logger.rb +20 -0
  61. data/rack/methodoverride.rb +27 -0
  62. data/rack/mime.rb +208 -0
  63. data/rack/mock.rb +190 -0
  64. data/rack/nulllogger.rb +18 -0
  65. data/rack/recursive.rb +61 -0
  66. data/rack/reloader.rb +109 -0
  67. data/rack/request.rb +273 -0
  68. data/rack/response.rb +150 -0
  69. data/rack/rewindable_input.rb +103 -0
  70. data/rack/runtime.rb +27 -0
  71. data/rack/sendfile.rb +144 -0
  72. data/rack/server.rb +271 -0
  73. data/rack/session/abstract/id.rb +140 -0
  74. data/rack/session/cookie.rb +90 -0
  75. data/rack/session/memcache.rb +119 -0
  76. data/rack/session/pool.rb +100 -0
  77. data/rack/showexceptions.rb +349 -0
  78. data/rack/showstatus.rb +106 -0
  79. data/rack/static.rb +38 -0
  80. data/rack/urlmap.rb +55 -0
  81. data/rack/utils.rb +662 -0
  82. data/rack.rb +81 -0
  83. data/route.rb +231 -0
  84. data/sendmail.rb +222 -0
  85. data/sequel_helper.rb +20 -0
  86. data/session.rb +132 -0
  87. data/stringify_hash.rb +63 -0
  88. data/support.rb +35 -0
  89. data/template.rb +287 -0
  90. data/test/french.html +13 -0
  91. data/test/french_msg.html +3 -0
  92. data/test/m17n.txt +30 -0
  93. data/test/mobile.html +15 -0
  94. data/test/setup.rb +8 -0
  95. data/test/static/test.txt +1 -0
  96. data/test/template.html +58 -0
  97. data/test/template_inner.html +1 -0
  98. data/test/template_innerparam.html +1 -0
  99. data/test/test_auth.rb +43 -0
  100. data/test/test_blank.rb +44 -0
  101. data/test/test_csrf.rb +87 -0
  102. data/test/test_errorconsole.rb +91 -0
  103. data/test/test_handler.rb +155 -0
  104. data/test/test_helper.rb +296 -0
  105. data/test/test_keitai.rb +107 -0
  106. data/test/test_m17n.rb +129 -0
  107. data/test/test_route.rb +192 -0
  108. data/test/test_sendmail.rb +146 -0
  109. data/test/test_session.rb +83 -0
  110. data/test/test_stringify_hash.rb +67 -0
  111. data/test/test_template.rb +114 -0
  112. data/test.bat +2 -0
  113. metadata +240 -0
data/rack.rb ADDED
@@ -0,0 +1,81 @@
1
+ # Copyright (C) 2007, 2008, 2009, 2010 Christian Neukirchen <purl.org/net/chneukirchen>
2
+ #
3
+ # Rack is freely distributable under the terms of an MIT-style license.
4
+ # See COPYING or http://www.opensource.org/licenses/mit-license.php.
5
+
6
+ # The Rack main module, serving as a namespace for all core Rack
7
+ # modules and classes.
8
+ #
9
+ # All modules meant for use in your application are <tt>autoload</tt>ed here,
10
+ # so it should be enough just to <tt>require rack.rb</tt> in your code.
11
+
12
+ module Rack
13
+ # The Rack protocol version number implemented.
14
+ VERSION = [1,1]
15
+
16
+ # Return the Rack protocol version as a dotted string.
17
+ def self.version
18
+ VERSION.join(".")
19
+ end
20
+
21
+ # Return the Rack release as a dotted string.
22
+ def self.release
23
+ "1.2"
24
+ end
25
+
26
+ autoload :Builder, "rack/builder"
27
+ autoload :Cascade, "rack/cascade"
28
+ autoload :Chunked, "rack/chunked"
29
+ autoload :CommonLogger, "rack/commonlogger"
30
+ autoload :ConditionalGet, "rack/conditionalget"
31
+ autoload :Config, "rack/config"
32
+ autoload :ContentLength, "rack/content_length"
33
+ autoload :ContentType, "rack/content_type"
34
+ autoload :ETag, "rack/etag"
35
+ autoload :File, "rack/file"
36
+ autoload :Deflater, "rack/deflater"
37
+ autoload :Directory, "rack/directory"
38
+ autoload :ForwardRequest, "rack/recursive"
39
+ autoload :Handler, "rack/handler"
40
+ autoload :Head, "rack/head"
41
+ autoload :Lint, "rack/lint"
42
+ autoload :Lock, "rack/lock"
43
+ autoload :Logger, "rack/logger"
44
+ autoload :MethodOverride, "rack/methodoverride"
45
+ autoload :Mime, "rack/mime"
46
+ autoload :NullLogger, "rack/nulllogger"
47
+ autoload :Recursive, "rack/recursive"
48
+ autoload :Reloader, "rack/reloader"
49
+ autoload :Runtime, "rack/runtime"
50
+ autoload :Sendfile, "rack/sendfile"
51
+ autoload :Server, "rack/server"
52
+ autoload :ShowExceptions, "rack/showexceptions"
53
+ autoload :ShowStatus, "rack/showstatus"
54
+ autoload :Static, "rack/static"
55
+ autoload :URLMap, "rack/urlmap"
56
+ autoload :Utils, "rack/utils"
57
+
58
+ autoload :MockRequest, "rack/mock"
59
+ autoload :MockResponse, "rack/mock"
60
+
61
+ autoload :Request, "rack/request"
62
+ autoload :Response, "rack/response"
63
+
64
+ module Auth
65
+ autoload :Basic, "rack/auth/basic"
66
+ autoload :AbstractRequest, "rack/auth/abstract/request"
67
+ autoload :AbstractHandler, "rack/auth/abstract/handler"
68
+ module Digest
69
+ autoload :MD5, "rack/auth/digest/md5"
70
+ autoload :Nonce, "rack/auth/digest/nonce"
71
+ autoload :Params, "rack/auth/digest/params"
72
+ autoload :Request, "rack/auth/digest/request"
73
+ end
74
+ end
75
+
76
+ module Session
77
+ autoload :Cookie, "rack/session/cookie"
78
+ autoload :Pool, "rack/session/pool"
79
+ autoload :Memcache, "rack/session/memcache"
80
+ end
81
+ end
data/route.rb ADDED
@@ -0,0 +1,231 @@
1
+ module Egalite
2
+ class Route
3
+ def initialize(route_def)
4
+ @route = route_def
5
+ @controller = nil
6
+ @prefix = nil
7
+ @action = nil
8
+ end
9
+ def self.default_routes
10
+ routes = []
11
+ routes << Route.new([
12
+ [:controller],
13
+ [:controller],
14
+ [:action],
15
+ [:param_arg, :id],
16
+ [:params]
17
+ ])
18
+ routes << Route.new([
19
+ [:controller],
20
+ [:controller],
21
+ [:param_arg, :id],
22
+ [:params]
23
+ ])
24
+ routes << Route.new([
25
+ [:controller],
26
+ [:action],
27
+ [:param_arg, :id],
28
+ [:params]
29
+ ])
30
+ routes << Route.new([
31
+ [:controller],
32
+ [:param_arg, :id],
33
+ [:params]
34
+ ])
35
+ routes << Route.new([
36
+ [:action],
37
+ [:param_arg, :id],
38
+ [:params]
39
+ ])
40
+ routes << Route.new([
41
+ [:param_arg, :id],
42
+ [:params]
43
+ ])
44
+ routes
45
+ end
46
+
47
+
48
+ def match(path)
49
+ path = path.sub(/^\/+/,'')
50
+ pathary = path.to_s.split('/')
51
+ controller = nil
52
+ action = nil
53
+ path_params = []
54
+ params = {}
55
+ prefix = []
56
+ @route.each { |fragment|
57
+ command = fragment[0]
58
+
59
+ case command
60
+ when :controller
61
+ if pathary.empty? and controller
62
+ controller += '/index'
63
+ elsif pathary.empty?
64
+ return nil
65
+ else
66
+ controller += '/' if controller
67
+ controller ||= ''
68
+ controller += pathary.shift
69
+ end
70
+ when :action
71
+ return nil if pathary.empty?
72
+ action = pathary.shift
73
+ when :param
74
+ next if pathary.empty?
75
+ val = pathary.shift
76
+ params[fragment[1]] = val
77
+ prefix << val unless controller
78
+ when :param_arg
79
+ next if pathary.empty?
80
+ val = pathary.shift
81
+ params[fragment[1]] = val if fragment[1]
82
+ path_params << val
83
+ prefix << val unless controller
84
+ when :param_fix
85
+ return nil if pathary[0] != fragment[2]
86
+ params[fragment[1]] = pathary.shift
87
+ prefix << val unless controller
88
+ when :controller_fix
89
+ return nil if pathary[0] != fragment[1]
90
+ controller += '/' if controller
91
+ controller ||= ''
92
+ controller += pathary.shift
93
+ when :params
94
+ path_params += pathary
95
+ pathary = []
96
+ end
97
+ }
98
+ return nil if pathary.size > 0
99
+ @controller = controller
100
+ @action = action
101
+ @path_params = path_params
102
+ @params = params
103
+ @prefix = prefix.join('/')
104
+ [controller, action, path_params, params]
105
+ end
106
+
107
+ def escape(s)
108
+ Rack::Utils.escape(s)
109
+ end
110
+
111
+ def get_path_and_params_from_params(params, current_host = nil, current_port = nil, current_scheme = nil)
112
+ route = @route || []
113
+ pathary = []
114
+ controller_exist = false
115
+ action_exist = false
116
+ contfrags = (@controller || "").to_s.split('/')
117
+
118
+ scheme = nil
119
+ host = nil
120
+ port = nil
121
+ if params[:scheme]
122
+ scheme = params[:scheme].to_s
123
+ params.delete(:scheme)
124
+ end
125
+ if params[:host]
126
+ host = params[:host]
127
+ params.delete(:host)
128
+ end
129
+ if params[:port]
130
+ port = params[:port].to_i
131
+ params.delete(:port)
132
+ end
133
+ if (scheme or port or host)
134
+ raise "get_path_and_params_from_params: current_host is not supplied." unless host or current_host
135
+ scheme = scheme || current_scheme || 'http'
136
+ prefix = "#{scheme}://#{host || current_host}"
137
+ unless (current_scheme == 'http' and current_port == 80) or (current_scheme == 'https' and current_port == 443)
138
+ port ||= current_port
139
+ end
140
+ if port
141
+ unless (scheme == 'http' and port == 80) or (scheme == 'https' and port == 443)
142
+ prefix << ":#{port}"
143
+ end
144
+ end
145
+ end
146
+
147
+ route.each { |fragment|
148
+ command = fragment[0]
149
+
150
+ case command
151
+ when :controller
152
+ next if controller_exist
153
+ if params[:controller] == nil
154
+ pathary += contfrags
155
+ elsif params[:controller] =~ /^\//
156
+ pathary += params[:controller].to_s.split('/')
157
+ else
158
+ pathary += contfrags[0..-2]
159
+ pathary += params[:controller].to_s.split('/')
160
+ end
161
+ controller_exist = pathary.size
162
+ params.delete(:controller)
163
+ when :action
164
+ pathary << (params[:action] || (controller_exist ? nil : @action))
165
+ action_exist = true
166
+ params.delete(:action)
167
+ when :param
168
+ pathary << params[fragment[1]]
169
+ params.delete(fragment[1])
170
+ when :param_arg
171
+ pathary << params[fragment[1]]
172
+ params.delete(fragment[1])
173
+ when :param_fix
174
+ value = params[fragment[1]]
175
+ value = fragment[2] unless value
176
+ pathary << params[fragment[1]]
177
+ params.delete(fragment[1])
178
+ when :controller_fix
179
+ next
180
+ when :params
181
+ ary = (params[:params] || [])
182
+ if ary.respond_to?(:map)
183
+ pathary += ary.map { |s| s.to_s }
184
+ else
185
+ pathary += [ary.to_s]
186
+ end
187
+ params.delete(:params)
188
+ end
189
+ }
190
+ if not action_exist and params[:action]
191
+ if controller_exist
192
+ pathary.insert(controller_exist,params[:action])
193
+ else
194
+ pathary.unshift(params[:action])
195
+ end
196
+ params.delete(:action)
197
+ end
198
+ if not controller_exist and params[:controller]
199
+ pathary.unshift(params[:controller].to_s.split('/')).flatten!
200
+ params.delete(:controller)
201
+ end
202
+ pathary = pathary.compact.map { |frag| escape(frag) }
203
+ path = "/" + pathary.join('/').sub(/\/+$/,'').sub(/^\//,'')
204
+
205
+ [path, params, pathary, prefix]
206
+ end
207
+
208
+ def url_for(params, host = nil, port = nil, scheme = nil)
209
+ (path, params, z, prefix) = get_path_and_params_from_params(params, host, port, scheme)
210
+ if params and params.size > 0
211
+ q = []
212
+ params.each { |k,v|
213
+ if v.is_a?(Hash)
214
+ v.each { |k2,v2|
215
+ next if v2 == nil
216
+ q << "#{escape(k)}[#{escape(k2)}]=#{escape(v2)}"
217
+ }
218
+ else
219
+ q << "#{escape(k)}=#{escape(v)}" if v
220
+ end
221
+ }
222
+ path += "?" + q.join('&') unless q.empty?
223
+ end
224
+ "#{prefix}#{path}"
225
+ end
226
+
227
+ def link_to(title, params, host = nil, port = nil, scheme = nil)
228
+ "<a href='#{url_for(params, host, port, scheme)}'>#{title}</a>"
229
+ end
230
+ end
231
+ end
data/sendmail.rb ADDED
@@ -0,0 +1,222 @@
1
+
2
+ require 'template'
3
+ require 'nkf'
4
+ require 'time'
5
+
6
+ # mailheaders
7
+ # {
8
+ # :date => Time.new,
9
+ # :from => 'ARAI Shunichi <arai@example.com>', # encoded by Sendmail.address
10
+ # :reply_to => ,
11
+ # :to => 'tanaka@example.com', # encoded by Sendmail.address
12
+ # :cc => '', # encoded by Sendmail.address
13
+ # :bcc => '',
14
+ # :message_id => '',
15
+ # :in_reply_to => '',
16
+ # :references => '',
17
+ # :subject => '',
18
+ # }
19
+
20
+ module Sendmail
21
+ class QualifiedMailbox < String
22
+ end
23
+ class <<self
24
+ @@mock = false
25
+ def mock=(bool)
26
+ @@mock=bool
27
+ end
28
+ def folding(h, s) # folding white space. see RFC5322, section 2.3.3 and 3.2.2.
29
+ len = 78 - h.size - ": ".size
30
+ len2nd = 78 - " ".size
31
+ lines = []
32
+ line = ""
33
+ s.strip.split(/\s+/).each { |c| # each word (according to gmail's behavior)
34
+ if (line+c).size > len
35
+ len = len2nd
36
+ lines << line.strip
37
+ line = c + " "
38
+ else
39
+ line << c + " "
40
+ end
41
+ }
42
+ lines << line.strip if line.size > 0
43
+ lines.join("\n ")
44
+ end
45
+ def multibyte_folding(h, s, encoding = 'UTF-8') # RFC2047
46
+ bracketsize = "=?#{encoding}?B??=".size
47
+ len = 76 - h.size - ": ".size - bracketsize
48
+ len2nd = 76 - bracketsize
49
+ lines = []
50
+ line = ""
51
+ s = s.gsub(/\s+/, ' ').strip
52
+ s.split(//).each { |c| # each character (including multi-byte ones)
53
+ teststr = line+c
54
+ teststr = NKF.nkf('-Wj',teststr) if encoding =~ /iso-2022-jp/i
55
+ if [teststr].pack('m').chomp.size > len
56
+ len = len2nd
57
+ lines << line
58
+ line = c
59
+ else
60
+ line << c
61
+ end
62
+ }
63
+ lines << line if line.size > 0
64
+ lines = lines.map { |s| "=?#{encoding}?B?#{[s].pack('m').gsub(/\n/,'')}?=" }
65
+ lines.join("\n ")
66
+ end
67
+ def vchar(s)
68
+ s.gsub(/[\x00-\x1f\x7f]/,'')
69
+ end
70
+ def wsp(s)
71
+ s.gsub(/\s+/,' ')
72
+ end
73
+ def quote_string(s)
74
+ '"' + vchar(wsp(s)).gsub(/\\/,"\\\\\\").gsub(/\"/,'\\\"') + '"'
75
+ end
76
+ def multibyte?(s)
77
+ s.each_byte.any? { |c| c > 0x7f }
78
+ end
79
+ def encode_phrase(header, s)
80
+ if multibyte?(s)
81
+ multibyte_folding(header, s)
82
+ else
83
+ folding(header, quote_string(s))
84
+ end
85
+ end
86
+ def encode_unstructured(header, s)
87
+ if multibyte?(s)
88
+ multibyte_folding(header, s)
89
+ else
90
+ folding(header, vchar(wsp(s)))
91
+ end
92
+ end
93
+ def atext; '[0-9a-zA-Z!#$%&\'*+\-/=?\^_`{|}~]'; end
94
+ def atext_loose; '[0-9a-zA-Z!#$%&\'*+\-/=?\^_`{|}~.]'; end
95
+
96
+ def check_domain(s)
97
+ s =~ /\A#{atext}+?(\.#{atext}+?)+\Z/
98
+ end
99
+ def check_local_loose(s)
100
+ s =~ /\A#{atext_loose}+\Z/
101
+ end
102
+ def parse_addrspec(addrspec)
103
+ # no support for CFWS, FWS, and domain-literal.
104
+ if addrspec[0,1] == '"' # quoted-string
105
+ addrspec =~ /\A(\".*?[^\\]\")\@(.+)\Z/
106
+ (local, domain) = [$1, $2]
107
+ return nil if local =~ /[\x00-\x1f\x7f]/
108
+ return nil unless check_domain(domain)
109
+ [local, domain]
110
+ else
111
+ (local, domain) = addrspec.split(/@/,2)
112
+ return nil unless check_local_loose(local)
113
+ return nil unless check_domain(domain)
114
+ [local, domain]
115
+ end
116
+ end
117
+ def address(addrspec, name = nil, header='Reply-to')
118
+ # mailbox in RFC5322 section 3.4. not 'address' as in RFC.
119
+ raise 'invalid mail address.' unless parse_addrspec(addrspec)
120
+ if name and name.size > 0
121
+ QualifiedMailbox.new(folding(header, "#{encode_phrase(header, name)} <#{addrspec}>"))
122
+ else
123
+ addrspec
124
+ end
125
+ end
126
+ def mailboxlist(value, header = 'Reply-to')
127
+ case value
128
+ when QualifiedMailbox: value
129
+ when String: parse_addrspec(value) ? value : nil
130
+ when Hash: address(value[:address],value[:name],header)
131
+ when Array
132
+ folding(header, value.map { |v|
133
+ v.is_a?(Array) ? address(v[0],v[1]) : mailboxlist(v,header)
134
+ }.join(', '))
135
+ else
136
+ nil
137
+ end
138
+ end
139
+ def message(body, params)
140
+ headers = {}
141
+
142
+ raise "From must be exist." unless params[:from]
143
+ raise "The number of sender must be zero or one." if params[:sender].is_a?(Array) and params[:sender].size > 1
144
+ raise "When the number of 'from' is more than one, sender must be exist" if params[:from].is_a?(Array) and params[:from].size > 1 and not params[:sender]
145
+
146
+ %w[From To Sender Reply-To Cc].each { |s|
147
+ v = params[s.gsub(/-/,'_').downcase.to_sym]
148
+ headers[s] = mailboxlist(v,s) if v and v.size >= 1
149
+ }
150
+
151
+ headers["Subject"] = encode_unstructured("Subject",params[:subject].to_s) if params[:subject]
152
+ headers["MIME-Version"] = "1.0"
153
+ date = params[:date] || Time.now
154
+ headers["Date"] = date.is_a?(Time) ? date.rfc822 : date
155
+ headers["Content-Type"] = "text/plain; charset=UTF-8"
156
+
157
+ if multibyte?(body)
158
+ headers["Content-Transfer-Encoding"] = "base64"
159
+ body = [body].pack('m')
160
+ else
161
+ headers["Content-Transfer-Encoding"] = "7bit"
162
+ end
163
+
164
+ text = [headers.map{|k,v| "#{k}: #{v}"}.join("\n"),body].join("\n\n")
165
+ end
166
+ private
167
+ def _extract_addrspec(value)
168
+ case value
169
+ when QualifiedMailbox
170
+ value =~ /<(#{atext_loose}+?@#{atext_loose}+?)>\Z/
171
+ $1
172
+ when String: parse_addrspec(value) ? value : nil
173
+ when Hash: parse_addrspec(value[:address]) ? value[:address] : nil
174
+ when Array
175
+ value.map { |v|
176
+ if v.is_a?(Array)
177
+ parse_addrspec(v[0]) ? v[0] : nil
178
+ else
179
+ _extract_addrspec(v)
180
+ end
181
+ }
182
+ else nil
183
+ end
184
+ end
185
+ public
186
+ def to_addresses(params)
187
+ addresses = [:to, :cc, :bcc].map { |s|
188
+ _extract_addrspec(params[s])
189
+ }
190
+ addresses.flatten.compact.uniq
191
+ end
192
+ def _send(text, envelope_from, to, host = 'localhost')
193
+ if @@mock
194
+ @@lastmail = [text, envelope_from, to, host]
195
+ else
196
+ Net::SMTP.start(host) { |smtp|
197
+ smtp.send_message(text, envelope_from, to)
198
+ }
199
+ end
200
+ end
201
+ def lastmail
202
+ @@lastmail if @@lastmail
203
+ end
204
+ def send(body, params, host = 'localhost')
205
+ _send(
206
+ message(body, params),
207
+ _extract_addrspec(params[:envelope_from] || params[:sender] || params[:from]),
208
+ to_addresses(params),
209
+ host
210
+ )
211
+ end
212
+ def send_with_template(filename, params, host = 'localhost')
213
+ File.open("mail/"+ filename ,"r") { |f|
214
+ text = f.read
215
+ tengine = Egalite::HTMLTemplate.new
216
+ tengine.default_escape = false
217
+ text = tengine.handleTemplate(text,params)
218
+ send(text, params, host)
219
+ }
220
+ end
221
+ end
222
+ end
data/sequel_helper.rb ADDED
@@ -0,0 +1,20 @@
1
+
2
+ class Sequel::Model
3
+ def update_with(hash, *selection)
4
+ data = {}
5
+ selection.flatten.each { |k| data[k] = hash[k] || hash[k.to_sym] }
6
+ update(data)
7
+ end
8
+ def update_without(hash, *selection)
9
+ hash = hash.clone
10
+ selection.flatten.each { |k| hash.delete(k.to_s) if hash.key?(k.to_s) }
11
+ selection.flatten.each { |k| hash.delete(k.to_sym) if hash.key?(k.to_sym) }
12
+ update(hash)
13
+ end
14
+ def to_hash
15
+ hash = {}
16
+ self.each { |k,v| hash[k] = v }
17
+ hash
18
+ end
19
+ end
20
+
data/session.rb ADDED
@@ -0,0 +1,132 @@
1
+
2
+ require 'openssl'
3
+
4
+ module Egalite
5
+ class Session
6
+ attr_accessor :expire_after, :hash, :cookie_name
7
+
8
+ def initialize(env, cookies, opts = {})
9
+ @env = env
10
+ @cookies = cookies
11
+ @cookie_name = opts[:cookie_name] || 'egalite_session'
12
+ @expire_after = opts[:expire_after] || (86400 * 30)
13
+ @secure = opts[:secure] || false
14
+ @path = opts[:path] || '/'
15
+ @hash = {}
16
+ @loaded = false
17
+ end
18
+ def create
19
+ raise NotImplementedError
20
+ end
21
+ def load
22
+ raise NotImplementedError
23
+ end
24
+ def save
25
+ raise NotImplementedError
26
+ end
27
+ def delete
28
+ raise NotImplementedError
29
+ end
30
+ def [](k)
31
+ @hash[k]
32
+ end
33
+ def []=(k,v)
34
+ @hash[k] = v
35
+ end
36
+ end
37
+ class SessionSequel < Session
38
+ def self.create_table(db, opts = {})
39
+ table = opts[:table_name] || :sessions
40
+
41
+ db.create_table(table) {
42
+ primary_key :id, :integer, :auto_increment => true
43
+ column :mac, :varchar
44
+ column :updated_at, :timestamp
45
+ }
46
+ end
47
+
48
+ def initialize(env, cookies, opts = {})
49
+ @db = env.db
50
+ @table = opts[:tablename] || :sessions
51
+
52
+ super(env, cookies, opts)
53
+ end
54
+ def cookie
55
+ {
56
+ :value => @sstr,
57
+ :expires => Time.now + @expire_after,
58
+ :path => @path,
59
+ :secure => @secure
60
+ }
61
+ end
62
+ def sstr
63
+ @sstr
64
+ end
65
+ def _load(_sstr)
66
+ return false unless _sstr and _sstr.size > 0
67
+ (sid,mac) = _sstr.split(/_/)
68
+
69
+ sid = sid.to_i
70
+ return false if sid <= 0
71
+ return false unless mac and mac.size > 0
72
+
73
+ rec = @db[@table][:id => sid]
74
+ return false unless rec and rec[:mac] == mac
75
+
76
+ # timeout check
77
+ updated = rec[:updated_at]
78
+ return false if Time.now > (updated + @expire_after)
79
+
80
+ @sstr = _sstr
81
+ @hash = rec
82
+ @sid = sid
83
+ @mac = mac
84
+ @loaded = true
85
+ @cookies[@cookie_name] = cookie
86
+
87
+ @db[@table].filter(:id => sid).update(:updated_at => 'now')
88
+
89
+ true
90
+ end
91
+ def load_from_param(_sstr)
92
+ _load(_sstr)
93
+ end
94
+ def load
95
+ _sstr = @cookies[@cookie_name]
96
+ _sstr = _sstr[0] if _sstr.is_a?(Array)
97
+ _load(_sstr)
98
+ end
99
+ def create(hash = nil)
100
+ @sid = @db[@table].insert({})
101
+ @mac = OpenSSL::Random.random_bytes(8).unpack('h*')[0]
102
+ hash ||= {}
103
+ @db[@table].filter(:id => @sid).update(hash.merge(:mac => @mac,:updated_at => Time.now))
104
+ @hash = @db[@table][:id => @sid]
105
+
106
+ @sstr = "#@sid" + "_#@mac"
107
+ @cookies[@cookie_name] = cookie
108
+ @loaded = true
109
+
110
+ true
111
+ end
112
+ def delete
113
+ @cookies[@cookie_name] = {
114
+ :value => nil,
115
+ :expires => Time.now - 3600,
116
+ :path => @path,
117
+ :secure => @secure
118
+ }
119
+ @db[@table].filter(:id => @sid).delete
120
+ @loaded = false
121
+ true
122
+ end
123
+ def save
124
+ return false unless @loaded
125
+ [:updated_at, :mac, :id].each { |s| @hash.delete(s) }
126
+ @db[@table].filter(:id => @sid).update(
127
+ {:updated_at => Time.now}.merge(@hash)
128
+ )
129
+ true
130
+ end
131
+ end
132
+ end # module