egalite 0.0.1 → 0.0.2
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/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/Rakefile +1 -0
- data/egalite.gemspec +24 -0
- data/lib/egalite/auth/basic.rb +32 -0
- data/lib/egalite/blank.rb +53 -0
- data/lib/egalite/errorconsole.rb +77 -0
- data/lib/egalite/helper.rb +251 -0
- data/lib/egalite/keitai/keitai.rb +107 -0
- data/lib/egalite/keitai/ketai.rb +11 -0
- data/lib/egalite/keitai/rack/ketai/carrier/abstract.rb +131 -0
- data/lib/egalite/keitai/rack/ketai/carrier/au.rb +78 -0
- data/lib/egalite/keitai/rack/ketai/carrier/docomo.rb +80 -0
- data/lib/egalite/keitai/rack/ketai/carrier/emoji/ausjisstrtoemojiid.rb +1391 -0
- data/lib/egalite/keitai/rack/ketai/carrier/emoji/docomosjisstrtoemojiid.rb +759 -0
- data/lib/egalite/keitai/rack/ketai/carrier/emoji/emojidata.rb +836 -0
- data/lib/egalite/keitai/rack/ketai/carrier/emoji/softbankutf8strtoemojiid.rb +1119 -0
- data/lib/egalite/keitai/rack/ketai/carrier/emoji/softbankwebcodetoutf8str.rb +499 -0
- data/lib/egalite/keitai/rack/ketai/carrier/iphone.rb +8 -0
- data/lib/egalite/keitai/rack/ketai/carrier/softbank.rb +82 -0
- data/lib/egalite/keitai/rack/ketai/carrier.rb +17 -0
- data/lib/egalite/keitai/rack/ketai/middleware.rb +24 -0
- data/lib/egalite/m17n.rb +193 -0
- data/lib/egalite/route.rb +231 -0
- data/lib/egalite/sendmail.rb +222 -0
- data/lib/egalite/sequel_helper.rb +20 -0
- data/lib/egalite/session.rb +132 -0
- data/lib/egalite/stringify_hash.rb +63 -0
- data/lib/egalite/support.rb +35 -0
- data/lib/egalite/template.rb +287 -0
- data/lib/egalite/version.rb +3 -0
- data/lib/egalite.rb +744 -0
- metadata +35 -3
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Shunichi Arai
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/egalite.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'egalite/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "egalite"
|
8
|
+
spec.version = Egalite::VERSION
|
9
|
+
spec.authors = ["Shunichi Arai"]
|
10
|
+
spec.email = ["arai@mellowtone.co.jp"]
|
11
|
+
spec.description = %q{Egalite - yet another web application framework. see description at https://github.com/araipiyo/egalite}
|
12
|
+
spec.summary = %q{Egalite - yet another web application framework.}
|
13
|
+
spec.homepage = "https://github.com/araipiyo/egalite"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_dependency "rack"
|
24
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
|
2
|
+
module Egalite
|
3
|
+
module Auth
|
4
|
+
class Basic
|
5
|
+
def self.authorize(req,realm)
|
6
|
+
auth = req.authorization
|
7
|
+
return unauthorized(realm) if auth.blank?
|
8
|
+
(method,credentials) = auth.split(' ', 2)
|
9
|
+
return bad_request if method.downcase != "basic"
|
10
|
+
(username,password) = credentials.unpack("m*").first.split(/:/,2)
|
11
|
+
return unauthorized(realm) unless yield(username,password)
|
12
|
+
true
|
13
|
+
end
|
14
|
+
def self.unauthorized(realm)
|
15
|
+
return [ 401,
|
16
|
+
{ 'Content-Type' => 'text/plain',
|
17
|
+
'Content-Length' => '0',
|
18
|
+
'WWW-Authenticate' => 'Basic realm="%s"' % realm },
|
19
|
+
[]
|
20
|
+
]
|
21
|
+
end
|
22
|
+
def self.bad_request
|
23
|
+
return [ 400,
|
24
|
+
{ 'Content-Type' => 'text/plain',
|
25
|
+
'Content-Length' => '0' },
|
26
|
+
[]
|
27
|
+
]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# I stole it from ActiveSupport library of Ruby on Rails
|
2
|
+
# (MIT License)
|
3
|
+
|
4
|
+
class Object
|
5
|
+
# An object is blank if it's nil, empty, or a whitespace string.
|
6
|
+
# For example, "", " ", nil, [], and {} are blank.
|
7
|
+
#
|
8
|
+
# This simplifies
|
9
|
+
# if !address.nil? && !address.empty?
|
10
|
+
# to
|
11
|
+
# if !address.blank?
|
12
|
+
def blank?
|
13
|
+
respond_to?(:empty?) ? empty? : !self
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class NilClass #:nodoc:
|
18
|
+
def blank?
|
19
|
+
true
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class FalseClass #:nodoc:
|
24
|
+
def blank?
|
25
|
+
true
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class TrueClass #:nodoc:
|
30
|
+
def blank?
|
31
|
+
false
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class Array #:nodoc:
|
36
|
+
alias_method :blank?, :empty?
|
37
|
+
end
|
38
|
+
|
39
|
+
class Hash #:nodoc:
|
40
|
+
alias_method :blank?, :empty?
|
41
|
+
end
|
42
|
+
|
43
|
+
class String #:nodoc:
|
44
|
+
def blank?
|
45
|
+
self !~ /\S/
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class Numeric #:nodoc:
|
50
|
+
def blank?
|
51
|
+
false
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
|
2
|
+
class EgaliteErrorController < Egalite::Controller
|
3
|
+
def self.password=(pass)
|
4
|
+
@@password=pass
|
5
|
+
end
|
6
|
+
def self.database=(db)
|
7
|
+
@@database=db
|
8
|
+
end
|
9
|
+
def before_filter
|
10
|
+
return false unless @@password
|
11
|
+
Egalite::Auth::Basic.authorize(req, 'EgaliteError') { |username,password|
|
12
|
+
username == 'admin' and password == @@password
|
13
|
+
}
|
14
|
+
end
|
15
|
+
def get
|
16
|
+
hb = Egalite::HTMLTagBuilder
|
17
|
+
raw("<html><body>" +
|
18
|
+
hb.ol([ hb.a('latest','�ŐV�G���[�ꗗ'),
|
19
|
+
hb.a('frequent','���p�x�G���[�ꗗ'),
|
20
|
+
hb.a('security','�Z�L�����e�B�G���[�ꗗ'),
|
21
|
+
"<form action='detail'>�G���[�ԍ�: <input type='text' name='id'><input type='submit'></form>",
|
22
|
+
]) + "</body></html>")
|
23
|
+
end
|
24
|
+
def display(recs)
|
25
|
+
hb = Egalite::HTMLTagBuilder
|
26
|
+
raw("<body><html>" +
|
27
|
+
table_by_array(
|
28
|
+
['��ʔԍ�(�ڍ�)', '������', '���e', 'URL', '�폜'],
|
29
|
+
recs.map { |rec|
|
30
|
+
[hb.a(url_for(:action => :group, :id => rec[:md5]),rec[:md5]),
|
31
|
+
rec[:count],
|
32
|
+
rec[:text][0..50],
|
33
|
+
rec[:url][0..50],
|
34
|
+
hb.a(url_for(:action => :delete, :id => rec[:md5]),'�폜'),
|
35
|
+
]
|
36
|
+
}
|
37
|
+
) + "</body></html>")
|
38
|
+
end
|
39
|
+
def latest(lim)
|
40
|
+
lim ||= 100
|
41
|
+
display(@@database.fetch("SELECT md5, text, url, count(*) as count FROM logs WHERE checked_at is null AND severity != 'security' GROUP BY md5, text, url ORDER BY max(created_at) DESC LIMIT ?",lim.to_i))
|
42
|
+
end
|
43
|
+
def frequent(lim)
|
44
|
+
lim ||= 100
|
45
|
+
display(@@database.fetch("SELECT md5, text, url, count(*) as count FROM logs WHERE checked_at is null AND severity != 'security' GROUP BY md5, text, url ORDER BY count(*) DESC LIMIT ?",lim.to_i))
|
46
|
+
end
|
47
|
+
def security(lim)
|
48
|
+
lim ||= 100
|
49
|
+
display(@@database.fetch("SELECT md5, text, url, count(*) as count FROM logs WHERE checked_at is null AND severity == 'security' GROUP BY md5, text, url ORDER BY count(*) DESC LIMIT ?",lim.to_i))
|
50
|
+
end
|
51
|
+
def group(md5)
|
52
|
+
rec = @@database[:logs].filter(:md5 => md5).first
|
53
|
+
raw("<html><body>"+Egalite::HTMLTagBuilder.ul([
|
54
|
+
rec[:md5],
|
55
|
+
rec[:url],
|
56
|
+
rec[:text],
|
57
|
+
]) +"</body></html>")
|
58
|
+
end
|
59
|
+
def delete(md5)
|
60
|
+
@@database[:logs].filter(:md5 => md5).update(:checked_at => Time.now)
|
61
|
+
redirect :action => nil
|
62
|
+
end
|
63
|
+
def detail(id)
|
64
|
+
rec = @@database[:logs].filter(:id => id.to_i).first
|
65
|
+
return "no record found." unless rec
|
66
|
+
raw("<html><body>"+Egalite::HTMLTagBuilder.ul([
|
67
|
+
rec[:id],
|
68
|
+
rec[:severity],
|
69
|
+
rec[:created_at],
|
70
|
+
rec[:md5],
|
71
|
+
rec[:ipaddress],
|
72
|
+
rec[:url],
|
73
|
+
rec[:text],
|
74
|
+
]) +"</body></html>")
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
@@ -0,0 +1,251 @@
|
|
1
|
+
|
2
|
+
module Egalite
|
3
|
+
|
4
|
+
module HTMLTagBuilder
|
5
|
+
def escape_html(s)
|
6
|
+
s.is_a?(NonEscapeString) ? s : NonEscapeString.new(Rack::Utils.escape_html(s))
|
7
|
+
end
|
8
|
+
def _tag(name , soc, attributes)
|
9
|
+
close = soc == :close ? '/' : ''
|
10
|
+
solo = soc == :solo ? '/' : ''
|
11
|
+
|
12
|
+
atr = if attributes and not attributes.empty?
|
13
|
+
s = attributes.map { |k,v| "#{escape_html(k)}='#{escape_html(v)}'" }.join(' ')
|
14
|
+
" #{s}"
|
15
|
+
else
|
16
|
+
""
|
17
|
+
end
|
18
|
+
NonEscapeString.new("<#{close}#{escape_html(name)}#{atr}#{solo}>")
|
19
|
+
end
|
20
|
+
def tag_solo(name, attributes = {})
|
21
|
+
_tag(name, :solo, attributes)
|
22
|
+
end
|
23
|
+
def tag_open(name, attributes = {})
|
24
|
+
_tag(name, :open, attributes)
|
25
|
+
end
|
26
|
+
def tag_close(name, attributes = {})
|
27
|
+
_tag(name, :close, attributes)
|
28
|
+
end
|
29
|
+
class <<self
|
30
|
+
include Egalite::HTMLTagBuilder
|
31
|
+
def tag(tag, s, attributes = {})
|
32
|
+
tag_open(tag, attributes) + escape_html(s) + tag_close(tag, {})
|
33
|
+
end
|
34
|
+
%w[br hr].each { |t|
|
35
|
+
define_method(t) { tag_solo(t) }
|
36
|
+
}
|
37
|
+
%w[h1 h2 h3 h4 b i p html body].each { |t|
|
38
|
+
define_method(t) { |s|
|
39
|
+
tag(t, s)
|
40
|
+
}
|
41
|
+
}
|
42
|
+
def a(url, s)
|
43
|
+
tag('a', s, :href=>url)
|
44
|
+
end
|
45
|
+
def li(array)
|
46
|
+
array.map{ |s| "<li>#{escape_html(s)}</li>" }.join("\n")
|
47
|
+
end
|
48
|
+
def ol(array)
|
49
|
+
"<ol>#{li(array)}</ol>"
|
50
|
+
end
|
51
|
+
def ul(array)
|
52
|
+
"<ul>#{li(array)}</ul>"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
class TableHelper
|
58
|
+
private
|
59
|
+
def self.opt(opts)
|
60
|
+
opts.map { |k,v| " #{escape_html(k)}='#{escape_html(v)}'" }.join
|
61
|
+
end
|
62
|
+
def self.escape_html(s)
|
63
|
+
s.is_a?(NonEscapeString) ? s : Rack::Utils.escape_html(s)
|
64
|
+
end
|
65
|
+
def self._table(header, content, table_opts)
|
66
|
+
head = ""
|
67
|
+
if header
|
68
|
+
head = header.map {|s| "<th>#{escape_html(s)}</th>" }.join
|
69
|
+
head = " <tr>#{head}</tr>\n"
|
70
|
+
end
|
71
|
+
body = content.map { |line| " <tr>#{yield(line)}</tr>\n" }
|
72
|
+
NonEscapeString.new("<table#{opt(table_opts)}>\n#{head}#{body}</table>")
|
73
|
+
end
|
74
|
+
public
|
75
|
+
def self.table_by_hash(keys, header, content, table_opts = {})
|
76
|
+
unless keys.size == header.size
|
77
|
+
raise ArgumentError, "key and header count mismatch"
|
78
|
+
end
|
79
|
+
|
80
|
+
_table(header, content, table_opts) { |line|
|
81
|
+
keys.map { |key| "<td>#{escape_html(line[key])}</td>"}.join
|
82
|
+
}
|
83
|
+
end
|
84
|
+
def self.table_by_array(header, content, table_opts = {})
|
85
|
+
_table(header, content, table_opts) { |line|
|
86
|
+
line.map { |s| "<td>#{escape_html(s)}</td>" }.join
|
87
|
+
}
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
class FormHelper
|
92
|
+
include HTMLTagBuilder
|
93
|
+
|
94
|
+
private
|
95
|
+
def expand_name(s)
|
96
|
+
s = "#{@param_name}[#{s}]" if @param_name
|
97
|
+
escape_html(s)
|
98
|
+
end
|
99
|
+
def raw(s)
|
100
|
+
NonEscapeString.new(s)
|
101
|
+
end
|
102
|
+
|
103
|
+
public # export just for testing
|
104
|
+
|
105
|
+
def opt(opts)
|
106
|
+
opts.map { |k,v|
|
107
|
+
next "" if [:default,:checked,:selected, :nil].member?(k)
|
108
|
+
" #{escape_html(k)}='#{escape_html(v)}'"
|
109
|
+
}.join
|
110
|
+
end
|
111
|
+
def opt_as_hash(opts)
|
112
|
+
o = opts.dup
|
113
|
+
o.each_key { |k|
|
114
|
+
o.delete(k) if [:default,:checked,:selected, :nil].member?(k)
|
115
|
+
}
|
116
|
+
o
|
117
|
+
end
|
118
|
+
|
119
|
+
public
|
120
|
+
|
121
|
+
def initialize(data = {}, param_name = nil, opts = {})
|
122
|
+
@data = lambda { |k|
|
123
|
+
if data.respond_to?(k)
|
124
|
+
data.send(k)
|
125
|
+
elsif data.respond_to?(:[])
|
126
|
+
data[k]
|
127
|
+
end
|
128
|
+
}
|
129
|
+
|
130
|
+
@param_name = param_name
|
131
|
+
@form_opts = opts
|
132
|
+
end
|
133
|
+
def form(method, url=nil)
|
134
|
+
attrs = opt_as_hash(@form_opts)
|
135
|
+
attrs[:method] = method.to_s.upcase
|
136
|
+
attrs[:action] = url if url
|
137
|
+
tag_open(:form,attrs)
|
138
|
+
end
|
139
|
+
def close
|
140
|
+
tag_close(:form,nil)
|
141
|
+
end
|
142
|
+
def _text(value, name, opts)
|
143
|
+
attrs = opt_as_hash(opts)
|
144
|
+
attrs[:value] = value if value
|
145
|
+
attrs[:size] ||= 30
|
146
|
+
attrs[:type] = 'text'
|
147
|
+
attrs[:name] = expand_name(name)
|
148
|
+
tag_solo(:input, attrs)
|
149
|
+
end
|
150
|
+
def text(name, opts = {})
|
151
|
+
_text(@data[name] || opts[:default], name, opts)
|
152
|
+
end
|
153
|
+
def timestamp_text(name, opts = {})
|
154
|
+
# todo: enable locale
|
155
|
+
# todo: could unify to text()
|
156
|
+
value = @data[name] || opts[:default]
|
157
|
+
value = value.strftime('%Y-%m-%d %H:%M:%S')
|
158
|
+
_text(value,name,opts)
|
159
|
+
end
|
160
|
+
def password(name, opts = {})
|
161
|
+
value = @data[name] || opts[:default]
|
162
|
+
attrs = opt_as_hash(opts)
|
163
|
+
attrs[:value] = value if value
|
164
|
+
attrs[:type] = "password"
|
165
|
+
attrs[:name] = expand_name(name)
|
166
|
+
tag_solo(:input,attrs)
|
167
|
+
end
|
168
|
+
def hidden(name, opts = {})
|
169
|
+
value = @data[name] || opts[:default]
|
170
|
+
attrs = opt_as_hash(opts)
|
171
|
+
attrs[:value] = value if value
|
172
|
+
attrs[:type] = "hidden"
|
173
|
+
attrs[:name] = expand_name(name)
|
174
|
+
tag_solo(:input,attrs)
|
175
|
+
end
|
176
|
+
def checkbox(name, value="true", opts = {})
|
177
|
+
checked = (@data[name] || opts[:default] || opts[:checked])
|
178
|
+
checked = false if @data[name] == false
|
179
|
+
|
180
|
+
attr_cb = opt_as_hash(opts)
|
181
|
+
attr_cb[:type] = 'checkbox'
|
182
|
+
attr_cb[:name] = expand_name(name)
|
183
|
+
attr_cb[:value] = value
|
184
|
+
attr_cb[:checked] = "checked" if checked
|
185
|
+
|
186
|
+
ucv = opts[:uncheckedvalue] || 'false'
|
187
|
+
attr_h = {:type => 'hidden', :name => expand_name(name), :value => ucv}
|
188
|
+
hidden = opts[:nohidden] ? '' : tag_solo(:input, attr_h)
|
189
|
+
|
190
|
+
raw "#{hidden}#{tag_solo(:input, attr_cb)}"
|
191
|
+
end
|
192
|
+
def radio(name, choice, opts = {})
|
193
|
+
selected = (@data[name] == choice)
|
194
|
+
selected = (opts[:default] == choice) || opts[:selected] if @data[name] == nil
|
195
|
+
|
196
|
+
attrs = opt_as_hash(opts)
|
197
|
+
attrs[:selected] = 'selected' if selected
|
198
|
+
attrs[:name] = expand_name(name)
|
199
|
+
attrs[:value] = choice
|
200
|
+
attrs[:type] = 'radio'
|
201
|
+
|
202
|
+
tag_solo(:input, attrs)
|
203
|
+
end
|
204
|
+
def textarea(name, opts = {})
|
205
|
+
value = escape_html(@data[name] || opts[:default])
|
206
|
+
raw "<textarea name='#{expand_name(name)}'#{opt(opts)}>#{value}</textarea>"
|
207
|
+
end
|
208
|
+
def file(name, opts = {})
|
209
|
+
attrs = opt_as_hash(opts)
|
210
|
+
attrs[:name] = expand_name(name)
|
211
|
+
attrs[:type] = 'file'
|
212
|
+
tag_solo(:input, attrs)
|
213
|
+
end
|
214
|
+
def submit(value = nil, name = nil, opts = {})
|
215
|
+
attrs = opt_as_hash(opts)
|
216
|
+
attrs[:name] = expand_name(name) if name
|
217
|
+
attrs[:value] = value if value
|
218
|
+
attrs[:type] = 'submit'
|
219
|
+
tag_solo(:input, attrs)
|
220
|
+
end
|
221
|
+
def image
|
222
|
+
end
|
223
|
+
def select_by_array(name, options, opts = {})
|
224
|
+
optionstr = options.map {|o|
|
225
|
+
flag = o[0] == @data[name]
|
226
|
+
a = {:value => o[0]}
|
227
|
+
a[:selected] = 'selected' if flag
|
228
|
+
"#{tag_open(:option, a)}#{escape_html(o[1])}</option>"
|
229
|
+
}.join('')
|
230
|
+
|
231
|
+
raw "<select name='#{expand_name(name)}'#{opt(opts)}>#{optionstr}</select>"
|
232
|
+
end
|
233
|
+
def select_by_association(name, options, optname, opts = {})
|
234
|
+
idname = (opts[:idname] || "id").to_sym
|
235
|
+
optionstr = options.map {|o|
|
236
|
+
flag = o[idname] == @data[name]
|
237
|
+
a = {:value => o[idname]}
|
238
|
+
a[:selected] = 'selected' if flag
|
239
|
+
"#{tag_open(:option, a)}#{escape_html(o[optname])}</option>"
|
240
|
+
}.join('')
|
241
|
+
|
242
|
+
if opts[:nil]
|
243
|
+
selected = (@data[name] == nil) ? "selected='selected'" : ''
|
244
|
+
optionstr = "<option value='' #{selected}>#{escape_html(opts[:nil])}</option>" + optionstr
|
245
|
+
end
|
246
|
+
|
247
|
+
raw "<select name='#{expand_name(name)}'#{opt(opts)}>#{optionstr}</select>"
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
|
2
|
+
$LOAD_PATH << File.join(File.dirname(__FILE__))
|
3
|
+
|
4
|
+
require 'ketai'
|
5
|
+
require 'uri'
|
6
|
+
require 'openssl'
|
7
|
+
require 'base64'
|
8
|
+
|
9
|
+
module Egalite
|
10
|
+
module Keitai
|
11
|
+
class URLSession
|
12
|
+
def self.encrypt(s,key)
|
13
|
+
cipher = OpenSSL::Cipher.new("bf-cbc")
|
14
|
+
cipher.pkcs5_keyivgen(key)
|
15
|
+
cipher.encrypt
|
16
|
+
e = cipher.update(s) + cipher.final
|
17
|
+
Base64.encode64(e).tr('+/=','_.-').gsub!("\n","")
|
18
|
+
end
|
19
|
+
def self.decrypt(s,key)
|
20
|
+
cipher = OpenSSL::Cipher.new("bf-cbc")
|
21
|
+
cipher.pkcs5_keyivgen(key)
|
22
|
+
cipher.decrypt
|
23
|
+
e = s.tr('_.-','+/=')
|
24
|
+
e = Base64.decode64(e)
|
25
|
+
d = cipher.update(e) + cipher.final
|
26
|
+
d
|
27
|
+
end
|
28
|
+
end
|
29
|
+
module Session
|
30
|
+
def load_keitai_session(sessionid)
|
31
|
+
session.load_from_param(sessionid)
|
32
|
+
end
|
33
|
+
def modify_url_for_keitai(url,sstr)
|
34
|
+
uri = URI.parse(URI.escape(URI.unescape(url)))
|
35
|
+
return url if not uri.scheme.blank? and uri.scheme !~ /(http|https)/
|
36
|
+
if uri.host and uri.host !~ my_host
|
37
|
+
crypted_url = URLSession.encrypt(url,redirector_crypt_key)
|
38
|
+
File.join(redirector_url,crypted_url)
|
39
|
+
else
|
40
|
+
array = uri.query.to_s.split('&')
|
41
|
+
qhash = array.inject({}) { |a,s| (k,v) = s.split('=',2); a[k] = v; a }
|
42
|
+
qhash['sessionid']=sstr
|
43
|
+
uri.query = qhash.map {|k,v| "#{k}=#{v}"}.join('&')
|
44
|
+
uri.to_s
|
45
|
+
end
|
46
|
+
end
|
47
|
+
def replace_url_for_keitai(body,sstr)
|
48
|
+
body.gsub!(/<a.+?href=(?:'(.+?)'|"(.+?)").+?>/) { |s|
|
49
|
+
url = ($1 || $2)
|
50
|
+
url_after = modify_url_for_keitai(url,sstr)
|
51
|
+
s.sub(url,url_after)
|
52
|
+
}
|
53
|
+
body.gsub!(/(<form.+?>)/) { |s|
|
54
|
+
s + "\n<input type='hidden' name='sessionid' value='#{sstr}'/>\n"
|
55
|
+
}
|
56
|
+
end
|
57
|
+
def redirector_url
|
58
|
+
"/redirector"
|
59
|
+
end
|
60
|
+
def do_after_filter_for_keitai(response,session)
|
61
|
+
code = response[0]
|
62
|
+
headers = response[1]
|
63
|
+
body = response[2].join
|
64
|
+
|
65
|
+
if session and session.sstr
|
66
|
+
sstr = session.sstr
|
67
|
+
if headers['Location']
|
68
|
+
headers['Location'] = modify_url_for_keitai(headers['Location'],sstr)
|
69
|
+
end
|
70
|
+
replace_url_for_keitai(body,sstr)
|
71
|
+
response[2] = [body]
|
72
|
+
end
|
73
|
+
response
|
74
|
+
end
|
75
|
+
end
|
76
|
+
class Controller < Egalite::Controller
|
77
|
+
include Session
|
78
|
+
|
79
|
+
def before_filter
|
80
|
+
load_keitai_session(params[:sessionid])
|
81
|
+
super
|
82
|
+
end
|
83
|
+
def redirector_crypt_key
|
84
|
+
"Example1"
|
85
|
+
end
|
86
|
+
def my_host
|
87
|
+
/^www.example.com$/
|
88
|
+
end
|
89
|
+
def after_filter(response)
|
90
|
+
do_after_filter_for_keitai(response,session)
|
91
|
+
super(response)
|
92
|
+
response
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
class Redirector < Egalite::Controller
|
97
|
+
def get(crypted_url)
|
98
|
+
url = URLSession.decrypt(crypted_url, redirector_crypt_key)
|
99
|
+
"<html><body>外部サイトへ移動しようとしています。以下のリンクをクリックしてください。<br/><br/><a href='#{URI.escape(url)}'>リンク</a></body></html>"
|
100
|
+
end
|
101
|
+
def redirector_crypt_key
|
102
|
+
"Example1"
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
end
|