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.
- data/.gitignore +17 -0
- data/README.md +91 -0
- data/auth/basic.rb +32 -0
- data/blank.rb +53 -0
- data/egalite.rb +742 -0
- data/errorconsole.rb +77 -0
- data/examples/simple/example.rb +39 -0
- data/examples/simple/pages/test.html +15 -0
- data/examples/simple_db/example_db.rb +103 -0
- data/examples/simple_db/pages/edit.html +6 -0
- data/helper.rb +251 -0
- data/keitai/keitai.rb +107 -0
- data/keitai/ketai.rb +11 -0
- data/keitai/rack/ketai/carrier/abstract.rb +131 -0
- data/keitai/rack/ketai/carrier/au.rb +78 -0
- data/keitai/rack/ketai/carrier/docomo.rb +80 -0
- data/keitai/rack/ketai/carrier/emoji/ausjisstrtoemojiid.rb +1391 -0
- data/keitai/rack/ketai/carrier/emoji/docomosjisstrtoemojiid.rb +759 -0
- data/keitai/rack/ketai/carrier/emoji/emojidata.rb +836 -0
- data/keitai/rack/ketai/carrier/emoji/softbankutf8strtoemojiid.rb +1119 -0
- data/keitai/rack/ketai/carrier/emoji/softbankwebcodetoutf8str.rb +499 -0
- data/keitai/rack/ketai/carrier/iphone.rb +8 -0
- data/keitai/rack/ketai/carrier/softbank.rb +82 -0
- data/keitai/rack/ketai/carrier.rb +17 -0
- data/keitai/rack/ketai/middleware.rb +24 -0
- data/m17n.rb +193 -0
- data/rack/auth/abstract/handler.rb +37 -0
- data/rack/auth/abstract/request.rb +37 -0
- data/rack/auth/basic.rb +58 -0
- data/rack/auth/digest/md5.rb +124 -0
- data/rack/auth/digest/nonce.rb +51 -0
- data/rack/auth/digest/params.rb +55 -0
- data/rack/auth/digest/request.rb +40 -0
- data/rack/builder.rb +80 -0
- data/rack/cascade.rb +41 -0
- data/rack/chunked.rb +49 -0
- data/rack/commonlogger.rb +49 -0
- data/rack/conditionalget.rb +47 -0
- data/rack/config.rb +15 -0
- data/rack/content_length.rb +29 -0
- data/rack/content_type.rb +23 -0
- data/rack/deflater.rb +96 -0
- data/rack/directory.rb +157 -0
- data/rack/etag.rb +32 -0
- data/rack/file.rb +92 -0
- data/rack/handler/cgi.rb +62 -0
- data/rack/handler/evented_mongrel.rb +8 -0
- data/rack/handler/fastcgi.rb +89 -0
- data/rack/handler/lsws.rb +63 -0
- data/rack/handler/mongrel.rb +90 -0
- data/rack/handler/scgi.rb +59 -0
- data/rack/handler/swiftiplied_mongrel.rb +8 -0
- data/rack/handler/thin.rb +18 -0
- data/rack/handler/webrick.rb +73 -0
- data/rack/handler.rb +88 -0
- data/rack/head.rb +19 -0
- data/rack/lint.rb +567 -0
- data/rack/lobster.rb +65 -0
- data/rack/lock.rb +16 -0
- data/rack/logger.rb +20 -0
- data/rack/methodoverride.rb +27 -0
- data/rack/mime.rb +208 -0
- data/rack/mock.rb +190 -0
- data/rack/nulllogger.rb +18 -0
- data/rack/recursive.rb +61 -0
- data/rack/reloader.rb +109 -0
- data/rack/request.rb +273 -0
- data/rack/response.rb +150 -0
- data/rack/rewindable_input.rb +103 -0
- data/rack/runtime.rb +27 -0
- data/rack/sendfile.rb +144 -0
- data/rack/server.rb +271 -0
- data/rack/session/abstract/id.rb +140 -0
- data/rack/session/cookie.rb +90 -0
- data/rack/session/memcache.rb +119 -0
- data/rack/session/pool.rb +100 -0
- data/rack/showexceptions.rb +349 -0
- data/rack/showstatus.rb +106 -0
- data/rack/static.rb +38 -0
- data/rack/urlmap.rb +55 -0
- data/rack/utils.rb +662 -0
- data/rack.rb +81 -0
- data/route.rb +231 -0
- data/sendmail.rb +222 -0
- data/sequel_helper.rb +20 -0
- data/session.rb +132 -0
- data/stringify_hash.rb +63 -0
- data/support.rb +35 -0
- data/template.rb +287 -0
- data/test/french.html +13 -0
- data/test/french_msg.html +3 -0
- data/test/m17n.txt +30 -0
- data/test/mobile.html +15 -0
- data/test/setup.rb +8 -0
- data/test/static/test.txt +1 -0
- data/test/template.html +58 -0
- data/test/template_inner.html +1 -0
- data/test/template_innerparam.html +1 -0
- data/test/test_auth.rb +43 -0
- data/test/test_blank.rb +44 -0
- data/test/test_csrf.rb +87 -0
- data/test/test_errorconsole.rb +91 -0
- data/test/test_handler.rb +155 -0
- data/test/test_helper.rb +296 -0
- data/test/test_keitai.rb +107 -0
- data/test/test_m17n.rb +129 -0
- data/test/test_route.rb +192 -0
- data/test/test_sendmail.rb +146 -0
- data/test/test_session.rb +83 -0
- data/test/test_stringify_hash.rb +67 -0
- data/test/test_template.rb +114 -0
- data/test.bat +2 -0
- 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
|