nitro 0.1.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/AUTHORS +8 -0
- data/ChangeLog +1546 -0
- data/LICENCE +32 -0
- data/README +278 -0
- data/RELEASES +7 -0
- data/Rakefile +79 -0
- data/bin/cluster.rb +219 -0
- data/doc/architecture.txt +28 -0
- data/doc/bugs.txt +7 -0
- data/doc/css.txt +20 -0
- data/doc/ideas.txt +120 -0
- data/doc/pg.txt +47 -0
- data/doc/svn.txt +82 -0
- data/doc/todo.txt +30 -0
- data/etc/new-project.rb +18 -0
- data/examples/simple/README +15 -0
- data/examples/simple/app.rb +31 -0
- data/examples/simple/conf/apache.conf +100 -0
- data/examples/simple/conf/config.rb +89 -0
- data/examples/simple/conf/debug-config.rb +53 -0
- data/examples/simple/conf/live-config.rb +48 -0
- data/examples/simple/conf/overrides.rb +9 -0
- data/examples/simple/conf/requires.rb +51 -0
- data/examples/simple/ctl +32 -0
- data/examples/simple/env.rb +33 -0
- data/examples/simple/install.rb +12 -0
- data/examples/simple/lib/articles/entities.rb +35 -0
- data/examples/simple/lib/articles/lc-en.rb +36 -0
- data/examples/simple/lib/articles/methods.rb +55 -0
- data/examples/simple/lib/articles/part.rb +58 -0
- data/examples/simple/logs/access_log +2 -0
- data/examples/simple/logs/apache.log +3 -0
- data/examples/simple/logs/app.log +1 -0
- data/examples/simple/logs/events.log +1 -0
- data/examples/simple/root/add-article.sx +15 -0
- data/examples/simple/root/article-form.ss +20 -0
- data/examples/simple/root/comments-form.ss +16 -0
- data/examples/simple/root/comments.si +30 -0
- data/examples/simple/root/index.sx +44 -0
- data/examples/simple/root/shader/shader.xsl +100 -0
- data/examples/simple/root/shader/style.css +9 -0
- data/examples/simple/root/view-article.sx +30 -0
- data/examples/tiny/app.rb +30 -0
- data/examples/tiny/conf/apache.conf +100 -0
- data/examples/tiny/conf/config.rb +67 -0
- data/examples/tiny/conf/requires.rb +40 -0
- data/examples/tiny/ctl +31 -0
- data/examples/tiny/logs/access_log +9 -0
- data/examples/tiny/logs/apache.log +9 -0
- data/examples/tiny/root/index.sx +35 -0
- data/lib/n/app/cluster.rb +219 -0
- data/lib/n/app/cookie.rb +86 -0
- data/lib/n/app/filters/autologin.rb +50 -0
- data/lib/n/app/fragment.rb +67 -0
- data/lib/n/app/handlers.rb +120 -0
- data/lib/n/app/handlers/code-handler.rb +184 -0
- data/lib/n/app/handlers/page-handler.rb +612 -0
- data/lib/n/app/request-part.rb +59 -0
- data/lib/n/app/request.rb +653 -0
- data/lib/n/app/script.rb +398 -0
- data/lib/n/app/server.rb +53 -0
- data/lib/n/app/session.rb +224 -0
- data/lib/n/app/user.rb +47 -0
- data/lib/n/app/webrick-servlet.rb +213 -0
- data/lib/n/app/webrick.rb +70 -0
- data/lib/n/application.rb +187 -0
- data/lib/n/config.rb +31 -0
- data/lib/n/db.rb +217 -0
- data/lib/n/db/README +232 -0
- data/lib/n/db/connection.rb +369 -0
- data/lib/n/db/make-release.sh +26 -0
- data/lib/n/db/managed.rb +235 -0
- data/lib/n/db/mixins.rb +282 -0
- data/lib/n/db/mysql.rb +342 -0
- data/lib/n/db/psql.rb +378 -0
- data/lib/n/db/tools.rb +110 -0
- data/lib/n/db/utils.rb +99 -0
- data/lib/n/events.rb +118 -0
- data/lib/n/l10n.rb +22 -0
- data/lib/n/logger.rb +33 -0
- data/lib/n/macros.rb +53 -0
- data/lib/n/mixins.rb +46 -0
- data/lib/n/parts.rb +154 -0
- data/lib/n/properties.rb +194 -0
- data/lib/n/server.rb +61 -0
- data/lib/n/server/PLAYBACK.txt +8 -0
- data/lib/n/server/RESEARCH.txt +13 -0
- data/lib/n/server/filter.rb +77 -0
- data/lib/n/shaders.rb +167 -0
- data/lib/n/sitemap.rb +188 -0
- data/lib/n/std.rb +69 -0
- data/lib/n/sync/clc.rb +108 -0
- data/lib/n/sync/handler.rb +221 -0
- data/lib/n/sync/server.rb +170 -0
- data/lib/n/tools/README +11 -0
- data/lib/n/ui/date-select.rb +74 -0
- data/lib/n/ui/pager.rb +187 -0
- data/lib/n/ui/popup.rb +45 -0
- data/lib/n/ui/select.rb +41 -0
- data/lib/n/ui/tabs.rb +34 -0
- data/lib/n/utils/array.rb +92 -0
- data/lib/n/utils/cache.rb +144 -0
- data/lib/n/utils/gfx.rb +108 -0
- data/lib/n/utils/hash.rb +148 -0
- data/lib/n/utils/html.rb +147 -0
- data/lib/n/utils/http.rb +98 -0
- data/lib/n/utils/mail.rb +28 -0
- data/lib/n/utils/number.rb +31 -0
- data/lib/n/utils/pool.rb +66 -0
- data/lib/n/utils/string.rb +297 -0
- data/lib/n/utils/template.rb +38 -0
- data/lib/n/utils/time.rb +91 -0
- data/lib/n/utils/uri.rb +193 -0
- data/lib/xsl/base.xsl +205 -0
- data/lib/xsl/ce.xsl +30 -0
- data/lib/xsl/localization.xsl +23 -0
- data/lib/xsl/xforms.xsl +26 -0
- data/test/run.rb +95 -0
- metadata +187 -0
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
# = Synchronous Handler
|
|
2
|
+
#
|
|
3
|
+
# === Design:
|
|
4
|
+
#
|
|
5
|
+
# A handler can act as a multiplexer to implement multiple services
|
|
6
|
+
# per server.
|
|
7
|
+
#
|
|
8
|
+
# code: tml, drak
|
|
9
|
+
#
|
|
10
|
+
# (c) 2004 Navel, all rights reserved.
|
|
11
|
+
# $Id: handler.rb 71 2004-10-18 10:50:22Z gmosx $
|
|
12
|
+
|
|
13
|
+
require "timeout"
|
|
14
|
+
require "n/server"
|
|
15
|
+
|
|
16
|
+
module N; module Sync
|
|
17
|
+
|
|
18
|
+
class HandlerExitException < Exception; end
|
|
19
|
+
|
|
20
|
+
# = Worker
|
|
21
|
+
#
|
|
22
|
+
# Override this to create your worker.
|
|
23
|
+
#
|
|
24
|
+
class Handler
|
|
25
|
+
SEPARATOR = "\000"
|
|
26
|
+
|
|
27
|
+
# socket timeout in seconds
|
|
28
|
+
@@socket_timeout = 30
|
|
29
|
+
|
|
30
|
+
# handler timeout in seconds
|
|
31
|
+
@@handler_timeout = 60 * 60
|
|
32
|
+
|
|
33
|
+
attr :server, :socket
|
|
34
|
+
|
|
35
|
+
attr :thread, :touch_time
|
|
36
|
+
|
|
37
|
+
# status
|
|
38
|
+
attr_accessor :status
|
|
39
|
+
|
|
40
|
+
STATUS_IDLE = 0
|
|
41
|
+
STATUS_RUNNING = 10
|
|
42
|
+
STATUS_STOPPED = 20
|
|
43
|
+
|
|
44
|
+
def initialize(server, socket)
|
|
45
|
+
@server, @socket = server, socket
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def start
|
|
49
|
+
touch!
|
|
50
|
+
@thread = Thread.new(&method("run").to_proc)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def stop
|
|
54
|
+
unless STATUS_STOPPED == @status
|
|
55
|
+
@status = STATUS_STOPPED
|
|
56
|
+
$log.debug "Stoping handler" if $DBG
|
|
57
|
+
|
|
58
|
+
begin
|
|
59
|
+
@socket.close()
|
|
60
|
+
rescue Exception, StandardError => e
|
|
61
|
+
# gmosx: this is needed to be FAULT TOLERANT
|
|
62
|
+
# DRINK IT!
|
|
63
|
+
$log.error "Cannot close exception when stoping handler."
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# gmosx: why not? more FAULT TOLERANT.
|
|
67
|
+
@server.handlers.delete_if {|h| STATUS_STOPPED == h.status}
|
|
68
|
+
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# called by the garbage collector.
|
|
73
|
+
#
|
|
74
|
+
def gc!
|
|
75
|
+
@thread.raise HandlerExitException.new()
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def run
|
|
79
|
+
@status = STATUS_RUNNING
|
|
80
|
+
|
|
81
|
+
while (STATUS_RUNNING == @status) and (not @socket.closed?)
|
|
82
|
+
begin
|
|
83
|
+
unless cmd = read()
|
|
84
|
+
$log.error "Client closed connection"
|
|
85
|
+
@status = STATUS_IDLE
|
|
86
|
+
else
|
|
87
|
+
touch!
|
|
88
|
+
handle(cmd.chop())
|
|
89
|
+
end
|
|
90
|
+
rescue HandlerExitException => ex
|
|
91
|
+
@status = STATUS_IDLE
|
|
92
|
+
$log.debug "Handler exit" if $DBG
|
|
93
|
+
rescue Exception, StandardError => ex
|
|
94
|
+
@status = STATUS_IDLE
|
|
95
|
+
$log.debug ex if $DBG
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
begin
|
|
100
|
+
stop()
|
|
101
|
+
rescue Exception, StandardError => e
|
|
102
|
+
# gmosx: this rescue block needed to get debug info!
|
|
103
|
+
#
|
|
104
|
+
$log.error pp_exception(e)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def touch!
|
|
109
|
+
@touch_time = Time.now()
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def live?
|
|
113
|
+
return Time.now < @touch_time + @@handler_timeout
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Read xml from the socket
|
|
117
|
+
#
|
|
118
|
+
def read
|
|
119
|
+
return unless @status == STATUS_RUNNING
|
|
120
|
+
|
|
121
|
+
cmd = nil
|
|
122
|
+
|
|
123
|
+
# gmosx: no timeout here!
|
|
124
|
+
cmd = @socket.gets(SEPARATOR)
|
|
125
|
+
$log.debug "in: #{cmd}" if $DBG
|
|
126
|
+
|
|
127
|
+
return cmd
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# Write xml to the socket
|
|
131
|
+
#
|
|
132
|
+
def write(cmd)
|
|
133
|
+
return unless @status == STATUS_RUNNING
|
|
134
|
+
|
|
135
|
+
$log.debug "out: #{cmd}" if $DBG
|
|
136
|
+
|
|
137
|
+
begin
|
|
138
|
+
timeout(@@socket_timeout) { @socket << "#{cmd}#{SEPARATOR}" }
|
|
139
|
+
rescue Exception, StandardError => e
|
|
140
|
+
# gmosx: the socket is invalid close the handler.
|
|
141
|
+
$log.error pp_exception(e)
|
|
142
|
+
stop()
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# parse the xml commnad to create a ruby method call.
|
|
147
|
+
#
|
|
148
|
+
def parse(cmd)
|
|
149
|
+
return unless @status == STATUS_RUNNING
|
|
150
|
+
|
|
151
|
+
cmd = REXML::Document.new(cmd).root()
|
|
152
|
+
|
|
153
|
+
method = cmd.name().gsub(/-/, "_")
|
|
154
|
+
unless cmd.attributes.empty?
|
|
155
|
+
args = "(#{cmd.attributes.collect { |k, v| ":#{k.gsub(/-/, "_")} => '#{v}'" }.join(", ")})"
|
|
156
|
+
else
|
|
157
|
+
args = nil
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
return "cmd_#{method}#{args}"
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# Generic handler.
|
|
164
|
+
#
|
|
165
|
+
def handle(cmd)
|
|
166
|
+
if cmd = parse(cmd)
|
|
167
|
+
$log.debug "exec: #{cmd}" if $DBG
|
|
168
|
+
begin
|
|
169
|
+
eval(cmd)
|
|
170
|
+
rescue => ex
|
|
171
|
+
$log.error ex
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
# Send to another handler
|
|
177
|
+
#
|
|
178
|
+
def send(cmd, handler)
|
|
179
|
+
handler.write(cmd)
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# Broadcast to all handlers (clients)
|
|
183
|
+
#
|
|
184
|
+
def broadcast(cmd)
|
|
185
|
+
@server.broadcast(cmd)
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
# Broadcast to all other handlers (clients)
|
|
189
|
+
#
|
|
190
|
+
def broadcast_to_others(cmd)
|
|
191
|
+
for handler in @server.handlers
|
|
192
|
+
unless self == handler
|
|
193
|
+
handler.write(cmd)
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
# ------------------------------------------------------------------
|
|
199
|
+
|
|
200
|
+
def info(txt)
|
|
201
|
+
write(%|<info text="#{txt}" />|)
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
def error(txt)
|
|
205
|
+
write(%|<error text="#{txt}" />|)
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
# ------------------------------------------------------------------
|
|
209
|
+
# Commands
|
|
210
|
+
|
|
211
|
+
def cmd_ping(args)
|
|
212
|
+
cmd = %{<pong time="#{Time.now}"}
|
|
213
|
+
cmd += %{ challenge="#{args[:challenge]}"} if args
|
|
214
|
+
cmd += " />"
|
|
215
|
+
|
|
216
|
+
write(cmd)
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
end; end #modules
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# = Syncrhronous Server
|
|
2
|
+
#
|
|
3
|
+
# === Design:
|
|
4
|
+
#
|
|
5
|
+
# Should support clustered operation: A cluster of servers is spawned.
|
|
6
|
+
# The client connects to one of the servers at random. The client sticks
|
|
7
|
+
# to the server. Each server considers the others as clients and
|
|
8
|
+
# rebroadcasts all the events.
|
|
9
|
+
#
|
|
10
|
+
# We keep one service per server for simplicity, if we need multiple
|
|
11
|
+
# services we can implement a multiplexer service (handler).
|
|
12
|
+
#
|
|
13
|
+
# === TODO:
|
|
14
|
+
#
|
|
15
|
+
# - Investigate if this server can be done with select.
|
|
16
|
+
#
|
|
17
|
+
# code: gmosx, drak
|
|
18
|
+
#
|
|
19
|
+
# (c) 2004 Navel, all rights reserved.
|
|
20
|
+
# $Id: server.rb 71 2004-10-18 10:50:22Z gmosx $
|
|
21
|
+
|
|
22
|
+
require "thread"
|
|
23
|
+
require "socket"
|
|
24
|
+
require "rexml/document"
|
|
25
|
+
|
|
26
|
+
require "n/std"
|
|
27
|
+
require "n/application"
|
|
28
|
+
require "n/utils/array"
|
|
29
|
+
require "n/sync/handler"
|
|
30
|
+
|
|
31
|
+
module N; module Sync
|
|
32
|
+
|
|
33
|
+
# = Server
|
|
34
|
+
#
|
|
35
|
+
# A Synchronous server tha communicates with clients using
|
|
36
|
+
# application specific xml protocols. Typically communicates with
|
|
37
|
+
# Flash clients utilising the XmlSocket functionality to enable 'push'
|
|
38
|
+
# flash applications.
|
|
39
|
+
#
|
|
40
|
+
# The Macromedia XML Socket protocol is used, \000 is used as a eof
|
|
41
|
+
# marker. NO: the XML protocol is not really appropriate, better use
|
|
42
|
+
# a space optimized delimited ASCII protocol.
|
|
43
|
+
#
|
|
44
|
+
class Server < N::Application
|
|
45
|
+
MONITOR_INTERVAL = 2 * 60
|
|
46
|
+
|
|
47
|
+
# a single tcp server accepts all tcp requests
|
|
48
|
+
attr :tcp_server
|
|
49
|
+
|
|
50
|
+
# the listening address/port for this server.
|
|
51
|
+
attr_reader :address, :port
|
|
52
|
+
|
|
53
|
+
# the handler class, used to instantiate handlers
|
|
54
|
+
attr :handler_class
|
|
55
|
+
|
|
56
|
+
# maximum number of clients to connect.
|
|
57
|
+
attr_accessor :max_handlers
|
|
58
|
+
|
|
59
|
+
# the handler list, all handler attached to the server.
|
|
60
|
+
attr_accessor :handlers
|
|
61
|
+
|
|
62
|
+
# status
|
|
63
|
+
attr_accessor :status
|
|
64
|
+
|
|
65
|
+
STATUS_IDLE = 0
|
|
66
|
+
STATUS_RUNNING = 10
|
|
67
|
+
STATUS_STOPPED = 20
|
|
68
|
+
|
|
69
|
+
def initialize(address = "localhost", port = 2121, handler_class = N::Sync::Handler, max_handlers = nil)
|
|
70
|
+
@address, @port = address, port
|
|
71
|
+
@max_handlers = max_handlers
|
|
72
|
+
@name, @title = "nsync", "Navel Sync"
|
|
73
|
+
@status = STATUS_IDLE
|
|
74
|
+
|
|
75
|
+
@handlers = N::SafeArray.new()
|
|
76
|
+
@handler_class = handler_class
|
|
77
|
+
|
|
78
|
+
super()
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def start()
|
|
82
|
+
# a single tcp server accepts all tcp requests
|
|
83
|
+
@tcp_server = TCPServer.new(address, port)
|
|
84
|
+
|
|
85
|
+
start_monitor()
|
|
86
|
+
run()
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def stop()
|
|
90
|
+
@status = STATUS_STOPED
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def run()
|
|
94
|
+
@status = STATUS_RUNNING
|
|
95
|
+
$log.info "Server is running."
|
|
96
|
+
|
|
97
|
+
begin
|
|
98
|
+
while (STATUS_RUNNING == @status)
|
|
99
|
+
socket = @tcp_server.accept()
|
|
100
|
+
$log.debug "Socket accepted" if $DBG
|
|
101
|
+
handler = @handler_class.new(self, socket)
|
|
102
|
+
handlers << handler
|
|
103
|
+
handler.start()
|
|
104
|
+
end
|
|
105
|
+
rescue Exception, StandardError => e
|
|
106
|
+
$log.error pp_exception(e)
|
|
107
|
+
# tml, FIXME:
|
|
108
|
+
# this is dangerous! make more FAULT TOLERANT!
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
@status = STATUS_IDLE
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def shutdown()
|
|
115
|
+
end_monitor()
|
|
116
|
+
for handler in handlers
|
|
117
|
+
handler.stop()
|
|
118
|
+
end
|
|
119
|
+
Thread.exit()
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# ------------------------------------------------------------------
|
|
123
|
+
|
|
124
|
+
def start_monitor
|
|
125
|
+
@monitor = Thread.new {
|
|
126
|
+
begin
|
|
127
|
+
while true
|
|
128
|
+
sleep(MONITOR_INTERVAL)
|
|
129
|
+
$log.debug "monitor beat -- #{@handlers.size()} handlers" if $DBG
|
|
130
|
+
|
|
131
|
+
for handler in @handlers
|
|
132
|
+
unless handler.live?
|
|
133
|
+
$log.info "Idle handler detected!"
|
|
134
|
+
handler.gc!()
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
rescue Exception, StandardError => e
|
|
139
|
+
$log.error pp_exception(e)
|
|
140
|
+
end
|
|
141
|
+
}
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def end_monitor
|
|
145
|
+
Thread.kill(@monitor)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# ------------------------------------------------------------------
|
|
149
|
+
|
|
150
|
+
def send(cmd, handler)
|
|
151
|
+
handler.write(cmd)
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def broadcast(cmd)
|
|
155
|
+
for handler in @handlers
|
|
156
|
+
handler.write(cmd)
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
if $0 == __FILE__
|
|
163
|
+
require "n/logger"
|
|
164
|
+
|
|
165
|
+
$log = Logger.new(STDERR)
|
|
166
|
+
Server.new().exec()
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
end; end #modules
|
|
170
|
+
|
data/lib/n/tools/README
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
= Software Enginnering Tools
|
|
2
|
+
|
|
3
|
+
This directory contains standalone tools typically used in
|
|
4
|
+
software engineering and configuration, system administration,
|
|
5
|
+
or network management.
|
|
6
|
+
|
|
7
|
+
=== TODO:
|
|
8
|
+
|
|
9
|
+
- tool to replace all $xxx variables with english names.
|
|
10
|
+
|
|
11
|
+
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# = Date Select
|
|
2
|
+
#
|
|
3
|
+
# code:
|
|
4
|
+
# George Moschovitis <gm@navel.gr>
|
|
5
|
+
#
|
|
6
|
+
# (c) 2004 Navel, all rights reserved.
|
|
7
|
+
# $Id: select.rb 39 2004-09-29 12:40:53Z elathan $
|
|
8
|
+
|
|
9
|
+
module N; module UI
|
|
10
|
+
|
|
11
|
+
MONTHS_EN = %w{ - January February March April May June July August September October November December }
|
|
12
|
+
MONTHS_EL = %w{ - ���������� ����������� ������� �������� ����� ������� ������� ��������� ����������� ��������� ��������� ���������� }
|
|
13
|
+
|
|
14
|
+
# Date select.
|
|
15
|
+
#
|
|
16
|
+
def self.date_select(prefix, day, month, year, yorder = 0, locale = "en")
|
|
17
|
+
str = ""
|
|
18
|
+
months = ("en" == locale ? MONTHS_EN : MONTHS_EL)
|
|
19
|
+
|
|
20
|
+
str << %{
|
|
21
|
+
<select name="#{prefix}day">
|
|
22
|
+
<option value="0">--</option>
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
for i in (1..31)
|
|
26
|
+
if i == day
|
|
27
|
+
str << %{<option value="#{i}" selected="1">#{i}</option>}
|
|
28
|
+
else
|
|
29
|
+
str << %{<option value="#{i}">#{i}</option>}
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
str << %{
|
|
34
|
+
</select>
|
|
35
|
+
|
|
36
|
+
<select name="#{prefix}month">
|
|
37
|
+
<option value="0">-------</option>
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
for i in (1..12)
|
|
41
|
+
if i == month
|
|
42
|
+
str << %{<option value="#{i}" selected="1">#{months[i]}</option>}
|
|
43
|
+
else
|
|
44
|
+
str << %{<option value="#{i}">#{months[i]}</option>}
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
str << %{
|
|
49
|
+
</select>
|
|
50
|
+
|
|
51
|
+
<select name="#{prefix}year">
|
|
52
|
+
<option value="0">--</option>
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
nowyear = Time.now.year
|
|
56
|
+
|
|
57
|
+
for i in (0..60)
|
|
58
|
+
y = yorder < 0 ? nowyear - i : nowyear + i
|
|
59
|
+
if y == year
|
|
60
|
+
str << %{<option value="#{y}" selected="1">#{y}</option>}
|
|
61
|
+
else
|
|
62
|
+
str << %{<option value="#{y}">#{y}</option>}
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
str << %{
|
|
67
|
+
</select>
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return str
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
end; end # module
|
|
74
|
+
|