Mercurial > hgrepos > hgweb.cgi > after5
annotate after5.rb @ 35:f5cff2e25520 draft
Consider holiday in lieu.
author | HIROSE Yuuji <yuuji@gentei.org> |
---|---|
date | Tue, 03 Apr 2012 20:36:49 +0900 |
parents | 844e2f9a037f |
children | e67737e49a5d |
rev | line source |
---|---|
17 | 1 #!/usr/local/bin/ruby19 |
16 | 2 # -*- coding: euc-jp -*- |
0 | 3 # |
4 # Associative Scheduling Table - after5 | |
22
8803e5d52611
Show guidance when wrong password entered.
HIROSE Yuuji <yuuji@gentei.org>
parents:
18
diff
changeset
|
5 # (C)2003, 2004, 2006, 2008, 2012 by HIROSE Yuuji [yuuji<at>gentei.org] |
26 | 6 # $Id: after5.rb,v 1.19 2012/04/01 11:52:25 yuuji Exp yuuji $ |
18 | 7 # $HGid$ |
35 | 8 # Last modified Tue Apr 3 20:32:44 2012 on firestorm |
0 | 9 # See http://www.gentei.org/~yuuji/software/after5/ |
10 # このスクリプトはEUCで保存してください。 | |
11 | |
12 require 'kconv' | |
17 | 13 require 'nkf' |
0 | 14 |
15 $charset = 'EUC-JP' | |
16 | |
17 class HTMLout | |
18 def contenttype(type = "text/html", charset = $charset) | |
19 sprintf "Content-type: %s; charset=%s\n\n", type, charset | |
20 end | |
21 def initialize(title = "Document") | |
22 @title = title | |
23 @eltstack = [] | |
24 end | |
25 def resetstack() | |
26 @eltstack = [] | |
27 end | |
28 def head(title = @title, css = "style.css") | |
29 sprintf <<__EOS__, title, css | |
30 <html> | |
31 <head> | |
32 <title>%s</title> | |
33 <link rel="stylesheet" type="text/css" href="%s"> | |
34 </head> | |
35 __EOS__ | |
36 end | |
37 | |
38 def startelement(elt, attrs = {}, nl = true) | |
39 attr = "" | |
40 if attrs.is_a?(Hash) | |
41 for k in attrs.keys | |
42 attr += " %s=\"%s\"" % [k, attrs[k]] | |
43 end | |
44 end | |
45 @eltstack.push(elt) | |
46 sprintf "<%s%s>%s", elt, attr, nl ? "\n" : "" | |
47 end | |
48 def endelement(elt = nil, nl = true) | |
49 if elt | |
50 x = elt | |
51 @eltstack.pop | |
52 else | |
53 x = @eltstack.pop | |
54 end | |
55 sprintf "</%s>%s", x, nl ? "\n" : "" | |
56 end | |
57 def element(elt, attrs = nil, nl = nil) | |
58 attr = "" | |
59 lf = nl ? "\n" : "" | |
60 if attrs.is_a?(Hash) | |
61 for k in attrs.keys | |
62 attr += " %s=\"%s\"" % [k, attrs[k]] | |
63 end | |
64 end | |
65 body = yield | |
66 sprintf "<%s%s>%s%s%s</%s>%s", elt, attr, lf, body, lf, elt, lf | |
67 end | |
68 def elementln(elt, attr=nil) | |
69 body = yield | |
70 element(elt, attr, true){body} | |
71 end | |
72 def a(href, anchor = nil, attrs = {}) | |
73 attr = attrs | |
74 attr['href'] = href | |
75 element("a", attr){ | |
76 anchor or href | |
77 } | |
78 end | |
79 def p(msg, attrs=nil) | |
80 element("p", attrs){msg} | |
81 end | |
82 def text(name, value='', size=nil, maxlength=nil) | |
83 sprintf "<input type=\"text\" name=\"%s\" value=\"%s\"%s%s>", | |
84 name, value, | |
85 size ? " size=\"%s\""%size.to_s : '', | |
86 maxlength ? " maxlength=\"%s\""%maxlength.to_s : '' | |
87 end | |
88 def hidden(name, value='') | |
89 sprintf "<input type=\"hidden\" name=\"%s\" value=\"%s\">", name, value | |
90 end | |
91 def radio(name, value, text='', checked=nil) | |
92 sprintf "<input type=\"radio\" name=\"%s\" value=\"%s\"%s>%s", | |
93 name, value, checked ? " checked" : "", text | |
94 end | |
95 def checkbox(name, value, text='', checked=nil) | |
96 sprintf "<input type=\"checkbox\" name=\"%s\" value=\"%s\"%s>%s", | |
97 name, value, checked ? " checked" : "", text | |
98 end | |
99 def submit(name, value, text='') | |
100 sprintf "<input type=\"submit\" name=\"%s\" value=\"%s\">%s\n", | |
101 name, value, text | |
102 end | |
103 def reset(name, value, text='') | |
104 sprintf "<input type=\"reset\" name=\"%s\" value=\"%s\">\n", | |
105 name, value, text | |
106 end | |
107 def submit_reset(name) | |
108 submit(name, "GO")+reset(name, "Reset") | |
109 end | |
110 | |
2 | 111 def select(name, range, selected=nil) |
112 #start = (b<e ? b : e) | |
113 #last = (b>e ? b : e) | |
114 c=0 | |
0 | 115 "<select name=\"#{name}\">\n" + \ |
2 | 116 range.collect{|i| |
3 | 117 value = (i.is_a?(Array) ? i[1] : i).to_s |
118 sprintf "<option%s%s>%s%s</option>", | |
119 (selected.to_s==value.to_s) ? " selected" : "", | |
120 i.is_a?(Array) ? " value=\"%s\"" % value : '', | |
121 i.is_a?(Array) ? i[0] : i.to_s, | |
2 | 122 (c+=1)%6==0 ? "\n" : '' |
0 | 123 }.join + \ |
124 "\n</select>\n" | |
125 end | |
126 end | |
14 | 127 class TEXTout |
128 def isBlock(elt) | |
129 /\b(tr|[udo]l|p|div)\b/i =~ elt | |
130 end | |
131 def isEOC(elt) | |
132 /\bt[dh]\b/i =~ elt | |
133 end | |
134 def eoelem(elt) | |
135 r = "" | |
136 r << "\n" if isBlock(elt) | |
137 r << " " if isEOC(elt) | |
138 r | |
139 end | |
140 def contenttype(type = "text/plain", charset = $charset) | |
141 ### sprintf "Content-type: %s; charset=%s\n\n", type, charset | |
142 "" | |
143 end | |
144 def initialize(title = "Document") | |
145 @title = title | |
146 @eltstack = [] | |
147 end | |
148 def resetstack() | |
149 @eltstack = [] | |
150 end | |
151 def head(title = @title, css = "style.css") | |
152 sprintf <<__EOS__, title, css | |
153 ===== [[[ %s ]]] ===== | |
154 __EOS__ | |
155 end | |
156 | |
157 def startelement(elt, attrs = {}, nl = true) | |
158 attr = "" | |
159 x = sprintf "%s", " "*@eltstack.length | |
160 @eltstack.push(elt) | |
161 x | |
162 end | |
163 def endelement(elt = nil, nl = true) | |
164 if elt | |
165 x = elt | |
166 @eltstack.pop | |
167 else | |
168 x = @eltstack.pop | |
169 end | |
170 eoelem(x) | |
171 end | |
172 def element(elt, attrs = nil, nl = nil) | |
173 attr = "" | |
174 lf = nl ? "\n" : "" | |
175 body = yield | |
176 #sprintf "<%s%s>%s%s%s</%s>%s", elt, attr, lf, body, lf, elt, lf | |
177 sprintf "%s%s", body, eoelem(elt) | |
178 end | |
179 def elementln(elt, attr=nil) | |
180 body = yield | |
181 sprintf "%s\n", body | |
182 end | |
183 def a(href, anchor = nil, attrs = {}) | |
184 attr = attrs | |
185 attr['href'] = href | |
186 # sprintf "%s\n", href | |
187 anchor | |
188 end | |
189 def p(msg, attrs=nil) | |
190 element("p", attrs){msg} | |
191 end | |
192 def text(name, value='', size=nil, maxlength=nil) | |
193 "" | |
194 end | |
195 def hidden(name, value='') | |
196 "" | |
197 end | |
198 def radio(name, value, text='', checked=nil) | |
199 "" | |
200 end | |
201 def checkbox(name, value, text='', checked=nil) | |
202 "" | |
203 end | |
204 def submit(name, value, text='') | |
205 "" | |
206 end | |
207 def reset(name, value, text='') | |
208 "" | |
209 end | |
210 def submit_reset(name) | |
211 "" | |
212 end | |
213 def select(name, range, selected=nil) | |
214 "" | |
215 end | |
216 end | |
0 | 217 |
218 class PasswdMgr | |
219 def initialize(name, mode=0640) | |
220 require 'dbm' | |
221 @pdb = DBM.open(name, mode) | |
222 end | |
223 def checkpasswd(user, passwd) | |
224 if @pdb[user] then | |
225 @pdb[user] == passwd.crypt(@pdb[user]) | |
226 end | |
227 end | |
228 def setpasswd(user, passwd) | |
229 salt = [rand(64),rand(64)].pack("C*").tr("\x00-\x3f","A-Za-z0-9./") | |
230 @pdb[user] = passwd.crypt(salt) | |
231 end | |
232 def userexist?(user) | |
233 @pdb[user] ? true : false | |
234 end | |
235 def getpasswd(user) | |
236 @pdb[user] | |
237 end | |
238 def delete(user) | |
239 @pdb.delete(user) | |
240 end | |
241 def close() | |
242 @pdb.close() | |
243 end | |
244 def newpasswd(length) | |
245 srand(Time.now.to_i) | |
246 left = "qazxswedcvfrtgb12345" | |
247 right = "yhnmjuik.lop;/67890-" | |
248 array = [left, right] | |
249 (1..length).collect{|i| | |
250 a = array[i%array.length] | |
251 a[rand(a.length), 1] | |
252 }.join('') | |
253 end | |
254 def users() | |
255 @pdb.keys | |
256 end | |
257 private :newpasswd | |
258 def setnewpasswd(user, length=8) | |
259 newp = newpasswd(length) | |
260 setpasswd(user, newp) | |
261 newp | |
262 end | |
263 end | |
264 | |
265 class ScheduleDir | |
266 def initialize(dir = "s") | |
267 @dir = dir | |
268 @schedulefile = "sched" | |
269 @usermapdir = File.join(@dir, "usermap") | |
270 @usermap = mkusermap() | |
271 @groupmapdir = File.join(@dir, "groupmap") | |
272 @groupmap = mkgroupmap() | |
273 @crondir = File.join(@dir, "crondir") | |
274 | |
275 end | |
276 def mkusermap() | |
277 map = {} | |
278 unless test(?d, @usermapdir) | |
279 mkdir_p(@usermapdir) | |
280 end | |
281 Dir.foreach(@usermapdir){|u| | |
282 next if /^\./ =~ u | |
283 newu = '' | |
284 u.split('').each{|c| # for security wrapping | |
12 | 285 newu << c[0].chr if %r,[-A-Z0-9/+_.@],i =~ c |
0 | 286 } |
287 u = newu | |
288 map[u] = {} | |
17 | 289 d = File.join(@usermapdir, u).untaint |
0 | 290 next unless test(?d, d) |
291 Dir.foreach(d){|attr| | |
292 next if /^\./ =~ attr | |
12 | 293 attr.untaint if /^[A-Z_][-A-Z_0-9]*$/i =~ attr |
17 | 294 file = File.join(@usermapdir, u, attr).untaint |
0 | 295 next unless test(?s, file) && test(?r, file) |
17 | 296 map[u][attr] = IO.readlines(file).join.toeuc.strip |
0 | 297 } |
298 } | |
299 map | |
300 end | |
301 def putuserattr(user, attr, text) | |
302 # if text==nil, remove it | |
303 d = File.join(@usermapdir, user) | |
304 Dir.mkdir(d) unless test(?d, d) | |
305 file = File.join(d, attr) | |
306 begin | |
2 | 307 unless @usermap[user] |
308 @usermap[user] = {} | |
309 mkdir_p(d) unless test(?d, d) | |
310 end | |
0 | 311 @usermap[user][attr] = text |
312 if text==nil | |
313 File.unlink(file) | |
314 else | |
315 open(file, "w"){|w| w.puts @usermap[user][attr]} | |
316 end | |
317 rescue | |
318 return nil | |
319 end | |
320 return {attr => text} | |
321 end | |
322 def getuserattr(user, attr) | |
323 # Should we distinguish between attribute is nil and "" ? | |
324 if @usermap.has_key?(user) && @usermap[user][attr].is_a?(String) && | |
325 @usermap[user][attr] > '' | |
326 return @usermap[user][attr] | |
327 else | |
328 return nil | |
329 end | |
330 end | |
331 | |
332 def nickname(user) | |
333 if @usermap.has_key?(user) && @usermap[user]['name'].is_a?(String) && | |
334 @usermap[user]['name'] > '' | |
335 return @usermap[user]['name'] | |
336 else | |
337 return user.sub(/@.*/, '') | |
338 end | |
339 end | |
340 def setnickname(user, nickname) | |
341 putuserattr(user, 'name', nickname) | |
342 end | |
343 | |
344 # | |
345 # make group map | |
346 def collectmembers(gname) | |
347 @visitedgroup=[] unless @visitedgroup | |
348 return [] unless @visitedgroup.grep(gname).empty? | |
349 @visitedgroup.push(gname) | |
350 mdir = File.join(@groupmapdir, gname, 'members') | |
351 return [] unless test(?d, mdir) | |
352 members = [] | |
353 Dir.foreach(mdir){|item| | |
354 next if /^\./ =~ item | |
355 item.untaint | |
356 next unless test(?f, File.join(mdir, item)) | |
357 if /.+@.+/ =~ item | |
358 members << item | |
359 else | |
360 members += collectmembers(item) | |
361 end | |
362 } | |
363 @visitedgroup.pop | |
364 members | |
365 end | |
366 def mkgroupmap() | |
367 map = {} | |
368 return map unless test(?d, @groupmapdir) | |
369 @visitedgroup = [] | |
370 Dir.foreach(@groupmapdir){|g| | |
371 next if /^\./ =~ g | |
372 newg = '' | |
373 next unless /^[-a-z0-9_.]+$/i =~ g | |
374 #g.untaint ## untaintじゃだめだ。map{g} のkeyがtaintedになっちゃうよ | |
375 gg = '' # for security wrapping | |
376 g.split('').each{|c| gg << c[0].chr if c != '`'} | |
377 g = gg | |
378 map[gg] = {} | |
17 | 379 d = File.join(@groupmapdir, g).untaint |
0 | 380 next unless test(?d, d) |
381 # get group name | |
17 | 382 gnf = File.join(d, 'name').untaint |
0 | 383 if test(?r, gnf) && test(?s, gnf) |
17 | 384 n = IO.readlines(gnf)[0].to_s.toeuc.strip |
0 | 385 map[g]['name'] = if n > '' then n else g end |
386 else | |
387 map[g]['name'] = g | |
388 end | |
389 # get administrators | |
390 # | |
17 | 391 gad = File.join(d, 'admin').untaint |
0 | 392 map[g]['admin'] = [] |
393 if test(?d, gad) | |
394 Dir.foreach(gad){|a| | |
395 # administrator should be a person (not group) | |
396 next unless /@/ =~ a | |
397 map[g]['admin'] << a | |
398 } | |
399 end | |
400 # collect members | |
401 #map[g]['members'] = collectmembers(g) | |
17 | 402 memd = File.join(d, 'members').untaint |
0 | 403 map[g]['members'] = [] |
404 if test(?d, memd) | |
405 Dir.foreach(memd){|a| | |
406 next if /^\./ =~ a | |
407 map[g]['members'] << a | |
408 } | |
409 end | |
410 } | |
411 map | |
412 end | |
413 def groupmap() | |
414 @groupmap | |
415 end | |
416 def groups() | |
417 @groupmap.keys | |
418 end | |
2 | 419 def addgroup(group, users, remove=nil, role='members') |
420 grp = groups.grep(group)[0] # group may be tainted, using kept name | |
421 return nil unless grp | |
0 | 422 for u in users |
423 next unless account_exists(u) | |
17 | 424 mdir = File.join(@groupmapdir, grp, role).untaint |
425 file = File.join(mdir, u).untaint | |
0 | 426 if remove |
427 @groupmap[grp][role].delete(u) | |
428 File.unlink(file) if test(?e, file) | |
429 else | |
430 @groupmap[grp][role] << u | |
431 @groupmap[grp][role].uniq | |
432 Dir.mkdir(file) unless test(?d, mdir) | |
433 open(file, "w"){|x|} # Touch it | |
434 end | |
435 end | |
436 grp | |
437 end | |
438 def setgroupname(grp, name) | |
439 return nil unless @groupmap[grp] | |
17 | 440 mdir = File.join(@groupmapdir, grp).untaint |
441 nfile = File.join(mdir, 'name').untaint | |
0 | 442 @groupmap[grp]['name'] = name |
443 if grp == name | |
444 # remove the name file because it is default name | |
445 File.unlink(nfile) if test(?e, nfile) | |
446 else | |
447 Dir.mkdir(mdir) unless test(?d, mdir) | |
448 open(nfile, "w"){|n| n.puts name.to_s.strip} | |
449 end | |
450 name | |
451 end | |
452 def creategroup(grp, grpname="", admin=[]) | |
2 | 453 grpptnOK = /^[-A-Z0-9._:!$%,]+$/i |
454 return nil unless grpptnOK =~ grp | |
455 gg = '' | |
456 grp.split('').each{|c| gg << c[0].chr if c =~ grpptnOK} | |
457 grp = gg | |
0 | 458 gdir = File.join(@groupmapdir, grp) |
459 mkdir_p(gdir) # Should not care errors here | |
460 Dir.mkdir(File.join(gdir, "admin")) | |
461 Dir.mkdir(File.join(gdir, "members")) | |
462 @groupmap[grp] = {} | |
463 if grpname == '' | |
464 @groupmap[grp]['name'] = grp | |
465 else | |
466 setgroupname(grp, grpname) | |
467 end | |
468 @groupmap[grp]['members'] = [] | |
469 @groupmap[grp]['admin'] = [] | |
470 addgroup(grp, admin) | |
471 addgroup(grp, admin, nil, 'admin') | |
472 return @groupmap[grp] | |
473 end | |
474 def createuser(user, email = nil) | |
475 return nil unless /@/ =~ user | |
476 return nil if %r@[\/()\;|,$\%^!\#&\'\"]@ =~ user | |
477 email = email || user | |
478 @usermap[user] = {} | |
479 Dir.mkdir(File.join(@usermapdir, user)) | |
480 putuserattr(user, 'email', email) | |
481 end | |
482 def deleteuser(user) | |
483 return nil unless @usermap[user] | |
484 begin | |
485 @usermap[user] # return value | |
486 ensure | |
487 @usermap.delete(user) | |
488 rm_rf(File.join(@usermapdir, user)) | |
489 rm_rf(File.join(@groupmapdir, "*/members/#{user}")) | |
490 rm_rf(File.join(@crondir, "[1-9]*-*-*/#{user}")) | |
491 rm_rf(File.join(@dir, "[1-9]*/[0-9][0-9]/[0-9][0-9]/[0-9]???/#{user}")) | |
492 end | |
493 end | |
494 def destroygroup(grp) | |
495 return nil unless @groupmap[grp] | |
496 begin | |
497 @groupmap[grp] # return value | |
498 ensure | |
499 @groupmap.delete(grp) | |
500 rm_rf(File.join(@groupmapdir, grp)) | |
501 rm_rf(File.join(@groupmapdir, "*/members/#{grp}")) | |
502 rm_rf(File.join(@crondir, "[1-9]*-*-*/#{grp}")) | |
503 rm_rf(File.join(@dir, "[1-9]*/[0-9][0-9]/[0-9][0-9]/[0-9]???/#{grp}")) | |
504 end | |
505 end | |
506 def rm_rf(path) | |
6 | 507 path.untaint |
0 | 508 if (list = Dir.glob(path))[0] |
509 for p in list | |
2 | 510 p.untaint |
0 | 511 system "/bin/rm -rf \"#{p}\"" |
512 end | |
513 cleanup_files(list[0]) | |
514 end | |
515 end | |
516 def account_exists(instance) | |
517 if /@/ =~ instance | |
518 true | |
519 else | |
520 ! @groupmap.select{|k, v| k==instance}.empty? | |
521 end | |
522 end | |
523 def ismember(user, grouporuser) | |
524 return true if user==grouporuser | |
525 if @groupmap[grouporuser] | |
526 @groupmap[grouporuser]['members'].grep(user)[0] | |
527 end | |
528 end | |
2 | 529 def isuser(user) |
530 @usermap[user] && @usermap.keys.grep(user)[0] | |
531 end | |
0 | 532 def isgroup(grp) |
533 @groupmap[grp] | |
534 end | |
535 def isadmin(user, group) | |
536 @groupmap[group] and @groupmap[group]['admin'].grep(user)[0] | |
537 end | |
538 def members(grp) | |
539 @groupmap[grp] and ####################@groupmap[grp]['members'] | |
540 collectmembers(grp) | |
541 end | |
542 def admins(grp) | |
543 @groupmap[grp] and @groupmap[grp]['admin'] | |
544 end | |
545 def groupname(grp) | |
546 @groupmap[grp] && @groupmap[grp]['name'] | |
547 end | |
2 | 548 def name2group(name) |
549 @groupmap.find{|g, v| v.is_a?(Hash) && v['name']==name} | |
550 end | |
551 def day_all(d, user=nil, personalonly = nil) | |
0 | 552 y, m, d = d.scan(%r,(\d\d\d\d+)/(\d+)/(\d+),)[0] |
553 #daydir = File.join(@dir, "%04d"%y.to_i, "%02d"%m.to_i, "%02d"%d.to_i) | |
554 daydir = File.join("s", "%04d"%y.to_i, "%02d"%m.to_i, "%02d"%d.to_i) | |
555 sched = {} | |
556 return sched unless test(?d, daydir) | |
557 Dir.foreach(daydir) {|time| | |
558 next if /^\./ =~ time | |
559 next unless /^\d\d\d\d$/ =~ time | |
560 time.untaint | |
561 t = File.join(daydir, time) | |
562 next unless test(?d, t) | |
563 sched[time] = {} | |
564 Dir.foreach(t){|who| | |
565 next if /^\./ =~ who | |
566 | |
567 visible = false | |
568 #next unless /@/ =~ who # user must be as user@do.ma.in | |
569 next unless account_exists(who) | |
7 | 570 ## next if personalonly && who != user #2004/1/16 |
0 | 571 who.untaint |
572 dir = File.join(t, who) | |
573 next unless test(?d, dir) && test(?x, dir) | |
574 pub = File.join(dir, 'pub') | |
7 | 575 if test(?f, pub) && test(?r, pub) && test(?s, pub) && |
576 !personalonly # unneccessary if personal mode | |
0 | 577 if IO.readlines(pub)[0].to_i > 0 |
578 visible = true | |
579 end | |
580 end | |
581 | |
582 | |
583 if ismember(user, who) || visible | |
584 sched[time][who] = {} | |
585 file = File.join(dir, @schedulefile) | |
586 if test(?s, file) && test(?r, file) && test(?s, file) | |
17 | 587 sched[time][who]['sched'] = IO.readlines(file).join.toeuc.chomp! |
6 | 588 sched[time][who]['regtime'] = File.stat(file).mtime |
0 | 589 end |
590 sched[time][who]['pub'] = visible | |
591 end | |
592 } #|who| | |
593 sched.delete(time) if sched[time].empty? | |
594 } | |
595 sched | |
596 end | |
597 | |
598 def scheduledir(user, y, m, d, time) | |
599 sprintf("%s/%04d/%02d/%02d/%04d/%s", | |
600 @dir, y.to_i, m.to_i, d.to_i, time.to_i, user) | |
601 end | |
602 def schedulefile(user, y, m, d, time) | |
603 File.join(scheduledir(user, y, m, d, time), @schedulefile) | |
604 end | |
605 def mkdir_p(path, mode=0777) | |
606 # Do not mkdir `path' for | |
607 # absolute paths | |
608 # those paths which contains `../' | |
609 # for the sake of security reason | |
610 return false if %r,\.\./|^/, =~ path | |
611 p = 0 | |
612 i=0 | |
613 while p=path.index("/", p) | |
614 dir = path[0..p].chop | |
615 p += 1 | |
616 break if i > 10 # overprotecting | |
617 next if test(?d, dir) | |
618 Dir.mkdir(dir, mode) | |
619 i += 1 | |
620 end | |
621 Dir.mkdir(path, mode) unless test(?d, path) | |
622 end | |
623 | |
624 # | |
625 # register schedule for user | |
626 # | |
627 def register(user, year, month, day, time, text, replace=nil) | |
628 # return code: 0 = succesfull new registration | |
629 # 1 = succesfull appending registration | |
630 dir = scheduledir(user, year, month, day, time) | |
631 file = schedulefile(user, year, month, day, time) | |
632 ret = 0 | |
633 um = File.umask(027) | |
634 begin | |
635 if !replace && test(?s, file) | |
636 ret = 1 | |
637 else | |
638 mkdir_p(dir, 0777) | |
639 end | |
640 ensure | |
641 File.umask(um) | |
642 end | |
643 open(file, replace ? "w" : "a"){|out|out.print text} | |
644 return ret | |
645 end | |
646 def getschedule(user, year, month, day, time) | |
647 file = schedulefile(user, year, month, day, time) | |
648 if test(?r, file) && test(?s, file) | |
17 | 649 return IO.readlines(file).join.toeuc |
0 | 650 end |
651 return nil | |
652 end | |
653 def remove(user, year, month, day, time) | |
654 file = schedulefile(user, year, month, day, time) | |
655 dir = File.dirname(file) | |
656 if test(?r, file) && test(?s, file) | |
657 File.unlink(file) | |
658 end | |
659 for f in Dir.glob(File.join(dir, "*")) | |
660 f.untaint | |
661 File.unlink(f) | |
662 end | |
663 Dir.rmdir(dir) if test(?d, dir) | |
664 begin | |
665 Dir.rmdir(File.dirname(dir)) | |
666 rescue | |
667 end | |
668 end | |
669 # | |
670 # register file | |
671 # | |
672 def putfile(user, year, month, day, time, file, contents) | |
673 scback = @schedulefile | |
674 begin | |
675 @schedulefile = File.basename(file) | |
676 register(user, year, month, day, time, contents, true) | |
677 ensure | |
678 @schedulefile = scback | |
679 end | |
680 end | |
681 def getfile(user, year, month, day, time, file) | |
682 scback = @schedulefile | |
683 begin | |
684 @schedulefile = File.basename(file) | |
685 getschedule(user, year, month, day, time) | |
686 ensure | |
687 @schedulefile = scback | |
688 end | |
689 end | |
690 def removefile(user, year, month, day, time, file) | |
691 dir = scheduledir(user, year, month, day, time) | |
692 file = File.join(dir, file) | |
693 if test(?e, file) | |
694 File.unlink(file) | |
695 end | |
696 end | |
697 # | |
698 # registration to crondir | |
699 # | |
700 def cronlink_file(nt_time, user, y, m, d, time) | |
701 subdir = nt_time.strftime("%Y-%m-%d-%H%M/#{user}") | |
702 cdir = File.join(@crondir, subdir) | |
703 File.join(cdir, sprintf("%04d-%02d-%02d-%04d", y, m, d, time)) | |
704 end | |
705 def register_crondir(nt_time, user, y, m, d, time) | |
706 linkfile = cronlink_file(nt_time, user, y, m, d, time) | |
707 mkdir_p(File.dirname(linkfile)) | |
708 scfile = schedulefile(user, y, m, d, time) | |
709 if test(?s, scfile) | |
710 sclink = File.join("../../..", scfile.sub!(Regexp.quote(@dir+'/'), '')) | |
711 File.symlink(sclink, linkfile) unless test(?e, linkfile) | |
712 return linkfile | |
713 end | |
714 return false | |
715 end | |
716 def remove_crondir(nt_time, user, y, m, d, time) | |
717 linkfile = cronlink_file(nt_time, user, y, m, d, time) | |
718 scfile = schedulefile(user, y, m, d, time) | |
719 if test(?e, linkfile) | |
720 File.unlink(linkfile) | |
721 begin | |
722 dir = linkfile | |
723 2.times {|x| | |
724 dir = File.dirname(dir) | |
725 if Dir.open(dir).collect.length <= 2 # is empty dir | |
726 Dir.rmdir(dir) | |
727 else | |
728 break | |
729 end | |
730 } | |
731 rescue | |
732 end | |
733 return linkfile | |
734 end | |
735 return false | |
736 end | |
737 | |
738 # | |
739 # return the Hash of crondir {user => files} | |
740 def notify_list(asof) | |
741 slack = 5*60 | |
742 gomifiles = [] | |
743 ntl = {} | |
744 return ntl unless test(?d, @crondir) | |
745 Dir.foreach(@crondir){|datedir| | |
2 | 746 next unless /(\d\d\d\d+)-(\d+)-(\d+)-(\d\d\d\d)/ =~ datedir |
10 | 747 ##datedir = sprintf("%04d-%02d-%02d-%04d", |
748 ## $1.to_i, $2.to_i, $3.to_i, $4.to_i) | |
749 datedir.untaint | |
0 | 750 dd = File.join(@crondir, datedir) |
751 next unless test(?d, dd) | |
752 y, m, d, hm = $1.to_i, $2.to_i, $3.to_i, $4.to_i | |
753 hh = hm/100 % 60 | |
754 mm = (hm%100) % 60 | |
755 t = Time.mktime(y, m, d, hh, mm) | |
756 next if t-slack > asof | |
757 # | |
758 # collect them | |
759 Dir.foreach(dd){|user| | |
2 | 760 # next unless /@/ =~ user || isgroup(user) |
761 next if /^\./ =~ user | |
762 if isgroup(user) | |
763 user = @groupmap.keys.grep(user)[0] | |
764 else | |
765 user = @usermap.keys.grep(user)[0] | |
766 end | |
767 next unless user | |
0 | 768 ud = File.join(dd, user) |
769 next unless test(?d, ud) | |
770 ntl[user] = {} | |
771 Dir.foreach(ud){|date| | |
772 next if /^\./ =~ date | |
773 unless /(\d\d\d\d+)-(\d+)-(\d+)-(\d\d\d\d)/ =~ date | |
774 gomifiles << File.join(ud, date) | |
775 next | |
776 end | |
13 | 777 #date = sprintf("%04d-%02d-%02d-%04d", |
778 # $1.to_i, $2.to_i, $3.to_i, $4.to_i) | |
779 date.untaint | |
0 | 780 f = File.join(ud, date) |
781 if test(?s, f) | |
782 ntl[user][date] = {} | |
783 ntl[user][date]['file'] = f | |
33 | 784 ntl[user][date]['text'] = |
785 IO.readlines(f).collect{|l| l.toeuc} # ...why? :-( | |
0 | 786 else |
787 File.unlink(f) # symlink points to nonexistent file | |
788 end | |
789 } | |
790 if ntl[user].empty? | |
791 # if ud does not contain valid cron symlinks, | |
792 # ud had been left badly. Remove it. | |
793 ntl.delete(user) | |
794 cleanup_files(gomifiles) | |
795 end | |
796 } | |
797 } | |
798 ntl | |
799 end | |
800 # | |
801 # cleanup file and directories | |
802 def cleanup_crondir(time) | |
803 Dir.foreach(@crnondir){|datedir| | |
804 dd = File.join(@crondir, datedir) | |
805 next unless test(?d, dd) | |
806 next unless /(\d\d\d\d+)-(\d+)-(\d+)-(\d\d\d\d)/ =~ dd | |
807 y, m, d, hm = $1.to_i, $2.to_i, $3.to_i, $4.to_i | |
808 hh = hm/100 % 60 | |
809 mm = (hm%100) % 60 | |
810 t = Time.mktime(y, m, d, hh, mm) | |
811 if t < time | |
812 system "rm -rf #{dd}" | |
813 end | |
814 } | |
815 end | |
816 # | |
817 # remove files in FILES, and remove parent directory if possible | |
818 def cleanup_files(files) | |
819 sentinel = File.stat(@dir).ino | |
16 | 820 me = $0.dup.untaint |
821 scriptsuid = File.stat(me).uid | |
0 | 822 for f in files |
2 | 823 if $SAFE > 0 |
824 f.untaint | |
825 if test(?e, f) && File.stat(f).uid != scriptsuid | |
826 f.taint | |
827 end | |
828 end | |
829 printf "Removing %s\n", f if $DEBUG | |
0 | 830 File.unlink(f) if test(?e, f) |
831 d = f | |
832 loop { | |
833 d = File.dirname(d) | |
834 break if d.length < 2 | |
835 break if File.stat(d).ino == sentinel | |
836 begin | |
837 puts "rmdir #{d}" if $DEBUG | |
838 Dir.rmdir(d) | |
839 rescue | |
840 break | |
841 end | |
842 } | |
843 end | |
844 end | |
845 end | |
846 | |
847 class StringIO<IO | |
848 def initialize() | |
849 @str="" | |
850 end | |
851 def foo=(str) | |
852 @str = str | |
853 end | |
2 | 854 def append(str) |
855 @str = str+@str | |
856 end | |
0 | 857 def print(str) |
858 @str << str | |
859 end | |
860 def puts(str) | |
861 @str << str+"\n" | |
862 end | |
863 def printf(*args) | |
864 @str << sprintf(*args) | |
865 end | |
866 def write(bytes) | |
867 print(bytes) | |
868 end | |
869 def gets() | |
870 return nil if @str == '' | |
871 p = @str.index(?\n) | |
872 if p | |
873 r = @str[0..p] | |
874 @str=@str[p+1..-1] | |
875 else | |
876 r = @str | |
877 end | |
878 return r | |
879 end | |
880 def readline() | |
881 this.gets() | |
882 end | |
883 def readlines() | |
884 r = @str | |
885 @str='' | |
886 r | |
887 end | |
888 | |
889 def p(*obj) | |
890 STDOUT.p(*obj) | |
891 end | |
892 end | |
893 | |
894 class CMDTimeout < Exception | |
895 def initialize() | |
896 @pw = IO.pipe | |
897 @pr = IO.pipe | |
898 @pe = IO.pipe | |
899 @timeout = false | |
900 end | |
901 def start(cmd, timeout, mixstderr=false) | |
902 if @pid=fork | |
903 @pw[0].close | |
904 @pr[1].close | |
905 @pe[1].close | |
906 # puts "parent!" | |
907 if @tk=fork | |
908 # main | |
909 else | |
910 @pw[1].close | |
911 @pr[0].close | |
912 @pe[0].close | |
913 trap(:INT){exit 0} | |
914 sleep timeout | |
915 begin | |
916 @timeout = true | |
917 STDERR.puts "TIMEOUT" | |
918 Process.kill :INT, @pid | |
919 rescue | |
920 #puts "Already done" | |
921 end | |
922 exit 0 | |
923 end | |
924 else | |
925 # Running this block with pid=@pid | |
926 trap(:INT){@timeout = true; exit 0} | |
927 @pw[1].close | |
928 STDIN.reopen(@pw[0]) | |
929 @pw[0].close | |
930 | |
931 @pr[0].close | |
932 STDOUT.reopen(@pr[1]) | |
933 if mixstderr | |
934 STDERR.reopen(@pr[1]) | |
935 else | |
936 STDERR.reopen(@pe[1]) | |
937 end | |
938 @pr[1].close | |
939 @pe[0].close | |
940 @pe[1].close | |
941 | |
15 | 942 exec(*cmd) |
0 | 943 exit 0 |
944 end | |
945 return [@pw[1], @pr[0], @pe[0]] | |
946 end | |
947 def wait() | |
948 Process.waitpid(@pid, nil) | |
949 end | |
950 def close() | |
951 @pr.each{|p| p.close unless p.closed?} | |
952 @pw.each{|p| p.close unless p.closed?} | |
953 @pe.each{|p| p.close unless p.closed?} | |
954 begin | |
955 Process.kill :INT, @tk | |
956 rescue | |
957 end | |
958 end | |
959 def timeout() | |
960 @timeout | |
961 end | |
962 end | |
963 | |
964 class Holiday | |
965 def initialize(dir = ".") | |
966 @@dir = dir | |
967 defined?(@@holiday) || setupHoliday | |
968 end | |
969 def setupHoliday(file = "holiday") | |
970 @@holiday = {} | |
971 return unless test(?f, file) && test(?s, file) | |
972 IO.foreach(file){|line| | |
17 | 973 line = line.toeuc.strip |
0 | 974 next if /^#/ =~ line |
975 date, what = line.scan(/(\S+)\s+(.*)/)[0] | |
976 if %r,(\d+)/(\d+)/(\d+), =~ date | |
977 cdate = sprintf("%d/%d/%d", $1.to_i, $2.to_i, $3.to_i) | |
978 @@holiday[cdate] || @@holiday[cdate] = [] | |
979 @@holiday[cdate] << what | |
980 elsif %r,(\d+)/(\d+), =~ date | |
981 cdate = sprintf("%d/%d", $1.to_i, $2.to_i) | |
982 @@holiday[cdate] || @@holiday[cdate] = [] | |
983 @@holiday[cdate] << what | |
984 elsif %r,(\d+)/(\w+), =~ date | |
985 cdate = sprintf("%d/%s", $1.to_i, $2.downcase) | |
986 @@holiday[cdate] || @@holiday[cdate] = [] | |
987 @@holiday[cdate] << what | |
988 end | |
989 } | |
990 end | |
991 def isHoliday(y, m, d, wday=nil) | |
992 y, m, d = y.to_i, m.to_i, d.to_i | |
993 wname = %w[sun mon tue wed thu fri sat] | |
35 | 994 wday = wname[wday || Time.mktime(y, m, d).wday] |
0 | 995 holiday = @@holiday[sprintf("%d/%d/%d", y, m, d)] || |
996 @@holiday[sprintf("%d/%d", m, d)] | |
997 unless holiday | |
998 nthweek = (d-1)/7+1 | |
999 holiday = @@holiday[sprintf("%d/w%d%s", m, nthweek, wday)] | |
1000 end | |
35 | 1001 if !holiday && wday == "mon" && d > 0 # d<1 when column is before 1th |
1002 # holiday in lieu | |
1003 yesterday = Time.mktime(y, m, d)-3600*24 | |
1004 holiday = ["振替休日"] if | |
1005 isHoliday(yesterday.year, yesterday.mon, yesterday.day) | |
1006 end | |
0 | 1007 holiday |
1008 end | |
1009 def holidays() | |
1010 @@holiday | |
1011 end | |
1012 end | |
1013 | |
1014 class After5 | |
1015 def initialize() | |
1016 @me = File.expand_path($0) | |
1017 @mydir, @myname = File.dirname(@me), File.basename(@me) | |
1 | 1018 @mybase = @myname.sub(/\.\w+$/, '') |
0 | 1019 @mydir.untaint |
1 | 1020 @mybase.untaint |
0 | 1021 Dir.chdir @mydir |
1 | 1022 @myname='a5.cgi' if test(?f, "a5.cgi") |
0 | 1023 @conf = nil |
1024 @schedulearea = {'rows'=>'4', 'cols'=>'60', 'name'=>'schedule'} | |
1025 @oldagent = (%r,Mozilla/4, =~ ENV['HTTP_USER_AGENT']) | |
2 | 1026 @lang = 0 |
14 | 1027 @mailmode = nil |
7 | 1028 @saveprefsregexp = /^(display(mode|days)$|nt|headline)/ |
0 | 1029 @opt = { |
1030 'conf' => @mybase+".cf", | |
1031 'css' => @mybase+".css", | |
13 | 1032 'logfile' => 's/'+@mybase+".log", |
0 | 1033 "sendmail" => "/usr/sbin/sendmail", |
1034 'hostcmd' => '/usr/bin/host', | |
1035 'nslookup' => '/usr/sbin/nsookup', | |
1036 'bg' => 'ivory', | |
8 | 1037 'name' => nil, |
0 | 1038 'at_bsd' => '%H:%M %b %d %Y', |
1039 'at_solaris' => '%H:%M %b %d,%Y', | |
1040 'schedir' => 's', | |
1041 'tdskip' => '<br>', | |
1042 'forgot' => 'wasureta', | |
1043 'size' => @oldagent ? '15' : '40', | |
1044 'morning' => '6', | |
1045 'night' => '22', | |
1046 'alldaydir' => '3000', | |
1047 'pswdlen' => 4, | |
6 | 1048 'pswddb' => 's/a5pswd', |
2 | 1049 'lang' => 'j', |
6 | 1050 'notifymail' => true, |
0 | 1051 } |
1052 @ntlist = [ | |
1053 ['nt10m', "10"+msg('minutes', 'before')], | |
1054 ['nt30m', "30"+msg('minutes', 'before')], | |
1055 ['nt60m', "60"+msg('minutes', 'before')], | |
1056 ['nttoday', msg('theday')], | |
1057 ['nt1d', "1"+msg('days', 'before')], | |
1058 ['nt2d', "2"+msg('days', 'before')], | |
1059 ['nt3d', "3"+msg('days', 'before')], | |
1060 ['nt7d', "7"+msg('days', 'before')], | |
1061 ['nt30d', "30"+msg('days', 'before')], | |
1062 ] | |
1063 ##@job = "today" | |
3 | 1064 @wnames = %w[sun mon tue wed thu fri sat] |
0 | 1065 @job = "login" |
1066 @sc = ScheduleDir.new | |
1067 @O = StringIO.new | |
1068 @H = HTMLout.new() | |
1069 @umback = File.umask | |
1070 @author = 'yuuji@gentei.org' | |
1071 @after5url = 'http://www.gentei.org/~yuuji/software/after5/' | |
1072 File.umask(007) | |
1073 end | |
1074 def doit() | |
1075 @params = getarg() | |
1076 @cookie = getcookie() | |
3 | 1077 importcookie() |
2 | 1078 @lang = (/^j/i =~ @opt['lang'] ? 0 : 1) |
0 | 1079 p @cookie if $DEBUG |
1080 p @params if $DEBUG | |
1081 | |
3 | 1082 ### @params['displaymode'] = @params['displaymode'] || @cookie['displaymode'] |
2 | 1083 personal = /personal/i =~ @params['displaymode'] |
1084 bodyclass = if personal then {'class'=>'personal'} end | |
0 | 1085 |
1086 ## x = {"align"=>'center'} | |
1087 ## @H.element("p", x, "hoge", nil) | |
1088 ## @H.element("p", nil, "buha", nil) | |
1089 | |
3 | 1090 if nil |
0 | 1091 if !@params['passwd'] && @cookie['passwd'] |
1092 @params['passwd'] = @cookie['passwd'] | |
1093 end | |
1094 if !@params['user'] && @cookie['user'] | |
1095 @params['user'] = @cookie['user'] | |
1096 end | |
3 | 1097 end |
0 | 1098 @params['user'] = safecopy(@params['user']) |
2 | 1099 |
15 | 1100 ######eval @job |
8 | 1101 a5name = if @opt['name'] && @opt['name'] > '' |
1102 sprintf("(%s)", @opt['name']) | |
1103 else | |
1104 "" | |
1105 end | |
2 | 1106 @O.append(@H.contenttype() + |
8 | 1107 @H.head(a5name+"After 5"+@job.sub(/\s*/, ' '), @opt['css'])) |
2 | 1108 @O.print @H.startelement("body", bodyclass, true) |
15 | 1109 # @job should be here because its output shoud go after <body>. |
1110 eval @job | |
0 | 1111 @O.print @H.endelement(nil, true) # body |
14 | 1112 @O.print @H.endelement("html", true) # html |
0 | 1113 setcookie() |
1114 | |
1115 print @O.readlines | |
1116 end | |
1117 def msg(*keyword) | |
1118 unless defined?(@msg) | |
1119 @msg = { | |
3 | 1120 'title' => ['みんなの予定表 <img src="after5.png" alt="「アフター5」">', 'Schedule table for us all <img src="after5.png" alt="After 5">'], |
0 | 1121 'login' => ['ログイン', 'Login'], |
1122 'loginfirst' => ['最初にログインすべし', 'Login first'], | |
1123 'autherror' => ['認証エラーがあったと管理者に伝えてくれっす', | |
1124 'Unexpected authentication error. Please tell this to the administrator'], | |
1125 'yourmail' => ['あなたのメイルアドレス', 'Your email address'], | |
1126 'passwd' => ['パスワード<br>(初回時は空欄)', | |
1127 'Passowrd<br>Left blank, first time'], | |
1128 'error' => ['エラー:', 'Error: '], | |
1129 'mailerror' => ['メイルアドレスが違います', 'Invalid email address'], | |
1130 'pswderror' => ['パスワードが違います', 'Password incorrect'], | |
22
8803e5d52611
Show guidance when wrong password entered.
HIROSE Yuuji <yuuji@gentei.org>
parents:
18
diff
changeset
|
1131 'forgotguide' => ['忘れた場合は %s と入力するよろし', |
8803e5d52611
Show guidance when wrong password entered.
HIROSE Yuuji <yuuji@gentei.org>
parents:
18
diff
changeset
|
1132 "Put \`%s' when you forgot password."], |
8 | 1133 'fmtdaysschedule'=> ['%s〜の予定', 'Schedule from %s'], |
18 | 1134 'schedtable' => ['予定表', 'Schedule Table'], |
0 | 1135 'noplan' => ['登録されている予定はありません', 'No plans'], |
1136 'allday' => ['全日', 'whole day'], | |
1137 'addsched' => ['新規予定項目の登録', 'Register new schedule'], | |
1138 'defthisday' => ['デフォルトの日付はこの日になってま', ''], | |
1139 '24hour' => ['24時間制4桁でね<br>(0000〜2359)<br>%sは時刻指定なし', 'in 24-hour<br>(0000-2359)<br>%s for whole day'], | |
14 | 1140 '24hourtxt' => ['24時間制4桁でね(0000〜2359), %sは時刻指定なし', 'in 24-hour(0000-2359), %s for whole day'], |
0 | 1141 'reqnotify' => ['通知メイルいるけ?', 'Previous notification'], |
1142 'rightnow' => ['登録時にすぐ', 'Right now on registration'], | |
1143 'immediatenote' => ['に以下の予定を登録しました', | |
1144 ", Your schedule has been registered as follows;"], | |
1145 'registerer_is' => ['登録名義: ', 'Register as '], | |
1146 'registerer' => ['登録者: ', 'registerer: '], | |
1147 'about' => ['約', 'about'], | |
1148 'minutes' => ['分', 'minutes'], | |
1149 'hours' => ['時間', 'hour(s)'], | |
1150 'days' => ['日', 'day(s)'], | |
2 | 1151 'daystodisplay' => ['日分表示', 'days to display'], |
0 | 1152 'before' => ['前', 'before'], |
2 | 1153 'precedingday' => ['前日', 'Preceding day'], |
0 | 1154 'theday' => ['当日朝', "the day's morning"], |
1155 'night' => ['(夜)', '(night)'], | |
1156 'publicok' => ['メンバーに<br>見せてもええね?', | |
1157 'visible from other members?'], | |
1158 'public' => ['公', 'pub'], | |
1159 'nonpublic' => ['非', 'sec'], | |
2 | 1160 'through' => ['〜', '=>'], |
0 | 1161 'yes' => ['はいな', 'yes'], |
29
e7a01e561e28
Message 'no' should contain only 'no'.
HIROSE Yuuji <yuuji@gentei.org>
parents:
28
diff
changeset
|
1162 'no' => ['やだ', 'nope'], |
2 | 1163 'wnames' => [%w[日 月 火 水 木 金 土], |
1164 %w[sun mon tue wed thu fri sat]], | |
1165 'whichday' => ['<small>(まとめ登録の場合)</small><br>期間中のどの日に?', | |
1166 '<small>(On multiple registration)</small><br>Which days in the term?'], | |
1167 'singleday' => ['一日分だけ登録', '1day regist'], | |
1168 'everyday' => ['毎日', 'everyday'], | |
0 | 1169 'invaliddate' => ['日付指定が変みたい', 'Invalid time string'], |
1170 'past' => ['それはもう過去の話ね', 'It had Pasted'], | |
1171 'putsomething' => ['何か書こうや', 'Write some message please'], | |
1172 'appended' => ['既存の予定に追加しました', 'Appended'], | |
1173 'append' => ['追加', 'append'], | |
1174 'join' => ['参加', 'join'], | |
1175 'regist' => ['登録', 'register'], | |
1176 'remove' => ['削除', 'remove'], | |
14 | 1177 'move' => ['移動', 'move'], |
1178 'newdate' => ['移動先時刻', 'New date'], | |
0 | 1179 'deletion' => ['完全消去', 'deletion'], |
1180 'deletionwarn' => ['OK押したら即消去。確認とらないぞ', | |
1181 'Hitting OK immediately delets this group, be carefully!'], | |
1182 'deluser' => ['%s ユーザ消してええかの?', "Delete the user `%s'"], | |
1183 'delgroup' => ['%s グループ消してええかの?', "Delete the group `%s'"], | |
1184 'really?' => ['ほんまにええけ?', 'Really?'], | |
1185 'chicken' => ['ふっ、腰抜けめ', 'Hey, chicken boy'], | |
1186 'modify' => ['修正', 'modify'], | |
1187 'done' => ['完了', 'done'], | |
1188 'success' => ['成功', 'success'], | |
1189 'failure' => ['失敗', 'failure'], | |
1190 'tomonthlist' => ['%s の一覧', 'all %s table'], | |
1191 'notifysubj' => @mybase+"'s reminder for your plan", | |
1192 'introduce' => ['はいこんにちは、'+@mybase+'ですよ〜。', | |
1193 "Hi, this is #{@mybase}'s notification."], | |
1194 'notifymail' => ['こんな予定がありまっせ。', | |
1195 "You have some eschedule below;"], | |
1196 'notification' => ['の通知', 'notification'], | |
1197 'newaccount' => ["新しいアカウントを作りました。\n"+ | |
1198 "パスワードは %s さん宛に送信しておきました。\n", | |
1199 "You got new account for #{@mybase}\n" + | |
1200 "Password was sent to %s.\nThank you.\n"], | |
1201 'accessfrom' => ["%s からのアクセスによる送信\n", | |
1202 "This mail was sent by the access from %s\n"], | |
1203 'newpassword' => ["%s さんのパスワードは %s です。\n", | |
1204 "The password of %s is %s\n"], | |
1205 'mischief' => ["身に覚えのない場合はいたずらです。どうしましょ。", | |
1206 'If you have no idea for getting this message, '+ | |
1207 'it is mischief by someone else'], | |
1208 'user' => ['ユーザ', 'user'], | |
1209 'group' => ['グループ', 'group'], | |
1210 'personal' => ['個人で', 'personal'], | |
17 | 1211 'registas' => ['グループ予定として登録?', 'Register as group?'], |
1212 'headsched' => ['下の枠内に予定を記入: 1行以内で短めに。 | |
1213 長くなるときは2行目以降に詳細を。', | |
1214 'Put shortest sentence as possible within 1 line. | |
1215 Or, put short subject in the first line, details in latter lines.'], | |
0 | 1216 'joinquit' => ['入退', 'joining/quiting'], |
1217 'of' => ['の', "'s"], | |
1218 'id' => ['ID(ローマ字1単語空白なしで)', 'ID(without spaces)'], | |
1219 'name' => ['名前', 'name'], | |
1220 'anystring' => ['(日本語OK)', '(any length, any characters)'], | |
1221 'setto' => ['を設定 → ', 'set to '], | |
2 | 1222 'dupname' => ['あー、%sってグループ名は既にあるん素。別のにして.', |
1223 "Group name `%s' already exists, choose another name."], | |
0 | 1224 'management' => ['管理', 'management'], |
1225 'administrator' => ['管理者', 'Administrator'], | |
1226 'newgroup' => ['新規グループ作成', 'Create new group'], | |
1227 'adminop' => ['管理<br>操作', "Administrative<br>operation"], | |
1228 'member' => ['メンバー', 'Member'], | |
2 | 1229 'personalmode' => ['自分のだけ表示モード', 'Display Personal Only'], |
1230 'normalmode' => ['全員分表示モード', "Display Everyone's"], | |
3 | 1231 'display' => ['予定表示行: ', 'Display schedule of: '], |
1232 'nameonly' => ['名前のみ', 'Name Only'], | |
1233 'head5char' => ['先頭5文字', 'Head 5 chars'], | |
1234 'headline' => ['先頭1行', 'Headline only'], | |
1235 'whole' => ['長くても全部', 'Whole text'], | |
6 | 1236 'hldays' => ['最新X日分強調', 'Hilight Recent X-days'], |
0 | 1237 'addedtogroup' => ['をグループに追加 →', 'added to the group:'], |
1238 'removedfromgp' => ['をグループから削除:', 'removed from the group:'], | |
1239 'soleadmin' => ['%s は %s の唯一の管理者なのでやめられないのだ', | |
1240 "%s is sole administrator of %s. Cannot retire."], | |
1241 'recursewarn' => ['個人では加入してないが、別の加入グループがこのグループに入っているので実質参加していることになっている。', | |
1242 'Though this member does not join to this group, it is assumed to be joining this group because other group where one joins is joined to this group.'], | |
1243 'regaddress' => ['登録アカウント名', 'Account id'], | |
1244 'existent' => ['既にあるんすよ → ', 'Already exists: '], | |
1245 'mailaddress' => ['通知送付先アドレス', 'Notification email address'], | |
1246 'weburl' => ['ゲストブックとかURL<br><small>(予定への反応を書いて欲しい場所)</small>', 'Your guest book URL'], | |
1247 'usermodwarn' => ['いちいち yes/no とか確認取らないから押したら最後、気いつけて。', | |
1248 'This is the final decision. Make sure and sure.'], | |
1249 'joinmyself' => ['自分自身が既存のグループに対して入る(IN)か出る(OUT)かを決めるのがここ。自分管理のグループに誰かを足すなら「管理操作」、新たにグループを作るなら', | |
1250 'In this page, you can decide put yourself IN or OUT of the existing groups. If you want to manage the member of your own group, go to'], | |
1251 'groupwarn' => ['自分が参加してないグループAに、自分が参加しているグループBが含まれている場合、グループAにも加入していると見なされるので気をつけよう。管理者はグループのニックネームを変えられるよ。', | |
1252 'Though you are not member of group A, you are treated as a member of A, if you join to the group B, which is a member of A. Think the nesting of groups carefully, please. Group administrator can change the group nickname.'], | |
1253 'wholemembers' => ['グループ内グループを考慮した上で、現在グループ %s への通知は以下のメンバーに送られる。', | |
1254 "Consiering the groups registered in another group, notification to the group `%s' is send to members as follows."], | |
1255 'noadmingroup' => ['管理できるグループはないっす', | |
1256 "'There's no groups under your administration."], | |
1257 'multiplemail' => ['複数の宛先に通知したいなら..', | |
1258 'Wanna send notify to multiple address...'], | |
1259 'nickname' => ['ニックネーム', 'nickname'], | |
1260 'shortnameplz' => ['表が崩れるほど長すぎるニックネームは嫌われるよ。短めにね。', | |
1261 'Because nickname is displayed many times in table, shorter name is prefered.'], | |
1262 'nicknamenote' => ['ニックネームを消去するとデフォルト名になりんす.', | |
1263 'Default name is displayed if you remove nickname.'], | |
1264 'nothingtodo' => ['って何もやることあらへんかったで', | |
14 | 1265 'Nothing to do for this transaction.'], |
1266 'schedlist' => [' and %d days Schedule list', | |
1267 'から%d日間の予定一覧'], | |
1268 'nothing' => ['なんもないす', 'Nothing'], | |
1269 'sessionpswd' => ['セッションパスワード(これはいじらないでね)', | |
1270 'Session Password(Do not modify this)'], | |
1271 'date' => ['日付', 'Date'], | |
1272 'time' => ['時刻指定', 'Time'], | |
1273 'publicp' => ['公開=yes、非公開=no', 'Public?'], | |
1274 'neednotify' => ['通知メイル(要らないのは消してね)', | |
1275 'Leave lines for notification timing'], | |
1276 'schedulehere' => ['以下登録内容', 'Your Schedule below'] | |
0 | 1277 } |
1278 end | |
1279 keyword.collect{|k| | |
1280 if @msg[k].is_a?(Array) | |
2 | 1281 @msg[k][@lang] |
0 | 1282 elsif @msg[k].is_a?(String) |
1283 @msg[k] | |
1284 else | |
1285 '' | |
1286 end | |
2 | 1287 }.join(['', ' '][@lang]) |
0 | 1288 end |
1289 | |
3 | 1290 def importcookie() |
7 | 1291 @cookie.keys.grep(@saveprefsregexp){|v| |
3 | 1292 @params[v] = @params[v] || @cookie[v] |
1293 } | |
7 | 1294 for v in %w[user passwd] |
1295 @params[v] = @params[v] || @cookie[v] | |
1296 end | |
3 | 1297 end |
0 | 1298 def setcookie() |
7 | 1299 a = {} |
1300 a['user'] = @params['user'] if @params['user'] | |
1301 a['passwd'] = @params['passwd'] if @params['passwd'] | |
1302 ac = gencookie("value", a, 3600*6*1) | |
1303 printf "Set-Cookie: %s\n", ac if ac | |
0 | 1304 p = {} |
7 | 1305 @params.keys.grep(@saveprefsregexp){|v| |
6 | 1306 p[v] = @params[v].to_s.strip if @params[v] && @params[v] > '' |
0 | 1307 } |
7 | 1308 c = gencookie("prefs", p, 3600*24*7) |
1309 str = [ac, c].select{|x|x}.join("; ") | |
1310 # printf "Set-Cookie: %s\n", str if str>'' | |
0 | 1311 printf "Set-Cookie: %s\n", c if c |
1312 end | |
1313 | |
1314 def encode(string) # borrowed from cgi.rb | |
1315 string.gsub(/([^ a-zA-Z0-9_.-]+)/n) do | |
1316 '%' + $1.unpack('H2' * $1.size).join('%').upcase | |
1317 end.tr(' ', '+') | |
1318 end | |
14 | 1319 def purify(string) |
1320 string.gsub(/[\040-\177]/) {encode($&)} | |
1321 end | |
0 | 1322 def decode!(string) |
1323 string.gsub!(/\+/, ' ') | |
1324 string.gsub!(/%(..)/){[$1.hex].pack("c")} | |
1325 end | |
14 | 1326 def decode(string) |
17 | 1327 string.gsub(/\+/, ' ').gsub(/%(..)/){[$1.hex].pack("c")} |
14 | 1328 end |
32
d23a2b3c456b
Save schedule text `as is' in a file and escape them for browser.
HIROSE Yuuji <yuuji@gentei.org>
parents:
31
diff
changeset
|
1329 def escape(string) |
d23a2b3c456b
Save schedule text `as is' in a file and escape them for browser.
HIROSE Yuuji <yuuji@gentei.org>
parents:
31
diff
changeset
|
1330 string.gsub(/&/n, '&').gsub(/\"/n, '"'). |
d23a2b3c456b
Save schedule text `as is' in a file and escape them for browser.
HIROSE Yuuji <yuuji@gentei.org>
parents:
31
diff
changeset
|
1331 gsub(/>/n, '>').gsub(/</n, '<') |
d23a2b3c456b
Save schedule text `as is' in a file and escape them for browser.
HIROSE Yuuji <yuuji@gentei.org>
parents:
31
diff
changeset
|
1332 end |
0 | 1333 |
7 | 1334 def gencookie(name, a, expire) |
0 | 1335 x = a.collect{|k, v| |
1336 sprintf("%s=%s", k, encode(v)) if v | |
1337 } | |
1338 x.delete(nil) | |
1339 return nil if x.empty? | |
1340 str = x.join('&') | |
1341 ex = (Time.new+expire).to_s | |
7 | 1342 sprintf "%s=%s; expires=%s", name, encode(str), ex |
0 | 1343 end |
1344 | |
1345 def login() | |
1346 @O.print @H.elementln("h1", nil){msg('title')} | |
1347 @O.print @H.elementln("h2", nil){msg('login')} | |
1348 format = {'method'=>'POST', 'action'=>@myname+"?-today"} | |
1349 @O.print @H.elementln("form", format){ | |
1350 @H.elementln("table", nil){ | |
1351 @H.elementln("tr", nil){ | |
1352 @H.element("td", nil){msg('yourmail')} + \ | |
1353 @H.element("td", nil){ | |
1354 sprintf '<input type="text" size="%s" name="user">', @opt['size'] | |
1355 } | |
1356 } + \ | |
1357 @H.elementln("tr", nil){ | |
1358 @H.element("td", nil){msg('passwd')} + \ | |
1359 @H.element("td", nil){ | |
1360 sprintf '<input type="password" size="%s" name="passwd">', @opt['size'] | |
1361 } | |
1362 } | |
1363 } + '<input type="submit" value="LOGIN">' | |
1364 } | |
1365 @O.print footer2() | |
1366 end | |
1367 def open_pm() | |
1368 begin | |
1369 PasswdMgr.new(@opt['pswddb']) | |
1370 rescue | |
1371 STDERR.printf "Cannot open pswd file [%s]\n", @opt['pswddb'] | |
1372 STDERR.printf "euid=#{Process.euid}, uid=#{Process.uid}\n", @opt['pswddb'] | |
1373 nil | |
1374 end | |
1375 end | |
1376 def outputError(*msg) | |
1377 @O.print @H.p(msg('error')+sprintf(*msg)) | |
1378 end | |
1379 def mailaddress(user) | |
1380 email = @sc.getuserattr(user, "email") | |
1381 email || user | |
1382 end | |
1383 def webpage(user) | |
1384 @sc.getuserattr(user, "webpage") | |
1385 end | |
14 | 1386 def checkauth_mail() |
1387 return true # temporary | |
1388 end | |
0 | 1389 def checkauth() |
14 | 1390 if @mailmode && @params['sessionpw'] |
1391 return checkauth_mail | |
1392 end | |
1393 auth = catch(:auth) { | |
0 | 1394 unless @params['user'] |
1395 outputError(@H.a(@myname, msg('loginfirst'))) | |
1396 throw :auth, nil | |
1397 end | |
1398 unless pm=open_pm() | |
1399 outputError(msg('autherror')) | |
1400 throw :auth, nil | |
1401 end | |
1402 user, passwd = @params['user'], @params['passwd'] | |
1403 email = mailaddress(user) | |
1404 if !checkmail(user) | |
1405 outputError(msg('mailerror')) | |
1406 throw :auth, nil | |
1407 end | |
1408 if pm.userexist?(user) | |
1409 if pm.checkpasswd(user, passwd) | |
1410 throw :auth, true | |
1411 elsif passwd == @opt['forgot'] | |
1412 newp = pm.setnewpasswd(user, @opt['pswdlen']) | |
1413 sendMail(email, "#{@mybase} password", | |
1414 "(#{ENV['REMOTE_ADDR']} からのアクセスによる送信)\n" + | |
7 | 1415 @opt['url'] + "\n" + |
0 | 1416 "#{@mybase} 用の #{user} さんのパスワードは\n" + |
1417 (newp || "未定義") + "\nです。\n") | |
1418 @O.print @H.p("#{email} 宛に送信しておきました") | |
1419 throw :auth, nil | |
1420 else | |
1421 outputError(msg('pswderror')) | |
22
8803e5d52611
Show guidance when wrong password entered.
HIROSE Yuuji <yuuji@gentei.org>
parents:
18
diff
changeset
|
1422 @O.print @H.p(sprintf(msg('forgotguide'), @opt['forgot'])) |
0 | 1423 throw :auth, nil |
1424 end | |
7 | 1425 elsif passwd == '' |
0 | 1426 newp = pm.setnewpasswd(user, @opt['pswdlen']) |
1427 @sc.createuser(user, user) | |
1428 sendMail(email, "#{@mybase} new account", | |
1429 sprintf(msg('accessfrom'), ENV['REMOTE_ADDR']) + | |
7 | 1430 sprintf(@opt['url']) + "\n" + |
0 | 1431 sprintf(msg('newpassword'), user, newp) + |
1432 sprintf(msg('mischief'))) | |
1433 @O.print @H.p(sprintf(msg('newaccount'), user)) | |
1434 @O.print @H.p(@H.a(@myname, msg('login'))) | |
1435 throw :auth, nil | |
7 | 1436 else |
1437 outputError(msg('pswderror')) | |
1438 throw :auth, nil | |
0 | 1439 end |
1440 } | |
1441 if auth | |
1442 return true | |
1443 else | |
1444 return false | |
1445 end | |
1446 end | |
1447 def safecopy(string) | |
1448 return nil unless string | |
1449 if $SAFE > 0 | |
1450 cpy='' | |
1451 string.split('').each{|c| | |
1452 cpy << c[0].chr if c[0] != ?` # ` | |
1453 } | |
28 | 1454 cpy.untaint |
0 | 1455 else |
1456 string | |
28 | 1457 end |
0 | 1458 end |
1459 def checkmail(mail) | |
1460 account, domain = mail.scan(/(.*)@(.*)/)[0] | |
1461 return false unless account != nil && domain != nil | |
17 | 1462 return false unless /^[-0-9a-z_.]+$/oi =~ domain.toeuc |
0 | 1463 domain = safecopy(domain) |
1464 require 'socket' | |
1465 begin | |
1466 TCPSocket.gethostbyname(domain) | |
1467 return true | |
1468 rescue | |
1469 if test(?x, @opt["hostcmd"]) | |
1470 open("| #{@opt['hostcmd']} -t mx #{domain}.", "r") {|ns| | |
1471 #p ns.readlines.grep(/\d,\s*mail exchanger/) | |
1472 return ! ns.readlines.grep(/is handled .*(by |=)\d+/).empty? | |
1473 } | |
1474 elsif test(?x, @opt["nslookup"]) | |
1475 open("| #{@opt['nslookup']} -type=mx #{domain}.", "r") {|ns| | |
1476 #p ns.readlines.grep(/\d,\s*mail exchanger/) | |
1477 return ! ns.readlines.grep(/\d,\s*mail exchanger/).empty? | |
1478 } | |
1479 end | |
1480 return false | |
1481 end | |
1482 end # checkmail | |
1483 | |
1484 # Logging | |
1485 # | |
1486 def putLog(msg) | |
1487 msg += "\n" unless /\n/ =~ msg | |
1488 open(@opt["logfile"], "a+") {|lp| | |
1489 lp.print Time.now.to_s + " " + msg | |
1490 } | |
1491 end | |
1492 | |
1493 def sendnotify(whom, subj, body) | |
1494 users = users() | |
1495 if grepgroup(whom) | |
1496 recipients = @sc.members(whom) | |
1497 else | |
1498 recipients=[whom] | |
1499 end | |
1500 for u in recipients | |
1501 if users.grep(u)[0] | |
1502 sendMail(mailaddress(u), subj, body) | |
1503 end | |
1504 end | |
1505 end | |
1506 | |
1507 def sendMail(to, subject, body) | |
17 | 1508 body = NKF.nkf("-j", body) |
1509 subject = NKF.nkf("-jM", subject) | |
0 | 1510 to = safecopy(to) # cleanup tainted address |
1511 subject.gsub!(/\n/, '') | |
1512 begin | |
1513 if (m=open("|-", "w")) | |
1514 m.print "To: #{to}\n" | |
1515 m.print "Subject: #{subject}\n" | |
1516 m.print "Mime-Version: 1.0 | |
1517 Content-Transfer-Encoding: 7bit | |
1518 Content-Type: Text/Plain; charset=iso-2022-jp | |
1519 | |
1520 " | |
1521 m.print body, "\n" | |
1522 m.close | |
1523 else | |
1524 # exec(@attr['mail'], "-s", subject, to) | |
1525 exec(@opt['sendmail'], to) | |
1526 exit 0; | |
1527 end | |
1528 putLog("Sent '#{subject}' to #{to}\n") | |
1529 return true | |
1530 rescue | |
1531 putLog("FAILED! - Sent '#{subject}' to #{to}\n") | |
1532 return nil | |
1533 end | |
1534 end # sendMail | |
1535 | |
1536 def today() | |
1537 today = Time.now | |
1538 showtable(today) | |
1539 end | |
1540 def isleap?(y) | |
1541 if y%400 == 0 | |
1542 true | |
1543 elsif y%100 == 0 || y%4 != 0 | |
1544 false | |
1545 else | |
1546 true | |
1547 end | |
1548 end | |
1549 def daysofmonth(year, month) | |
1550 dl = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] | |
1551 if month != 2 || !isleap?(year) | |
1552 dl[month-1] | |
1553 else | |
1554 29 | |
1555 end | |
1556 end | |
1557 # | |
1558 # Return the Time object at the last day of last month | |
1559 def lastmonth(today) | |
1560 Time.at(Time.mktime(today.year, today.month)-3600*24) | |
1561 end | |
1562 # | |
1563 # Return the Time object at the first day of next month | |
1564 def nextmonth(today) | |
1565 y, m = today.year, today.month | |
1566 Time.at(Time.mktime(y, m, daysofmonth(y, m))+3600*24) | |
1567 end | |
1568 | |
1569 def month(month) | |
1570 y, m = month.scan(%r,(\d\d\d\d+)/(\d+),)[0] | |
1571 if y && m | |
1572 showtable(Time.mktime(y, m, 1)) | |
1573 else | |
1574 outputError "%s %s", msg('invaliddate'), month | |
1575 return nil | |
1576 end | |
1577 end | |
1578 def footer1() | |
1579 "<br>" + \ | |
1580 @H.element("p"){ | |
1581 me = @myname+"?-"; delim = " / " | |
1582 @H.a(me+'userman', msg('user', 'management')) + delim + \ | |
2 | 1583 @H.a(me+'groupman', msg('group', 'management')) + delim + \ |
1584 if /personal/i =~ @params['displaymode'] | |
1585 @H.a(me+'today_n', msg('normalmode')) | |
1586 else | |
1587 @H.a(me+'today_p', msg('personalmode')) | |
1588 end | |
0 | 1589 } |
1590 end | |
1591 | |
1592 def footer2() | |
1593 "<hr>" + \ | |
1594 @H.element("code") { | |
1595 "This " + \ | |
1596 @H.a(@after5url, "After5") + \ | |
1597 " board is maintained by " + \ | |
1598 @opt['maintainer'].sub('@', "@") + "." | |
1599 } | |
1600 end | |
1601 def footer() | |
1602 footer1+footer2 | |
1603 end | |
1604 def nickname(userORgroup) | |
1605 if grepgroup(userORgroup) | |
1606 @sc.groupname(userORgroup) | |
1607 else | |
1608 @sc.nickname(userORgroup) | |
1609 end | |
1610 end | |
1611 # | |
1612 # show specified month's calendar | |
1613 def showtable(day) | |
1614 if !checkauth | |
1615 return nil | |
1616 end | |
17 | 1617 |
0 | 1618 month = day.month.to_s |
1619 first = Time.mktime(day.year, day.month, 1) | |
1620 last = daysofmonth(day.year, day.month) | |
1621 wday1 = first.wday | |
1622 start = 1-wday1 | |
3 | 1623 wname = @wnames |
0 | 1624 today = Time.now |
8 | 1625 todayy = today.year |
0 | 1626 todaym = today.month |
1627 todayd = today.day | |
1628 tdclass = {} | |
1629 tdclass["width"] = "64px" if @oldagent # workaround for NN4 | |
2 | 1630 personal = /personal/ =~ @params['displaymode'] |
3 | 1631 headline = @params['headline'] |
6 | 1632 headlinehl = @params['headlinehl'] |
1633 hldays = headlinehl.to_i * 3600*24 | |
1634 recent = {'class'=>'recent'} | |
3 | 1635 monthstr = sprintf "%d/%d", day.year, day.month |
1636 | |
0 | 1637 holiday = Holiday.new |
1638 # create dayofweek header | |
3 | 1639 @O.print @H.elementln("h1", nil){monthstr} |
2 | 1640 # which mode? |
1641 @O.print @H.p(msg(personal ? 'personalmode' : 'normalmode')) | |
1642 # | |
1643 # display table | |
0 | 1644 @O.print @H.startelement("table", {'border'=>"1", 'class'=>'main'}) |
1645 | |
1646 # day of week | |
1647 @O.print @H.startelement("tr") | |
1648 for w in wname | |
1649 @O.print @H.element("th", {'class'=>w}){w.capitalize} | |
1650 end | |
1651 @O.print "\n"+@H.endelement(nil, true) | |
1652 | |
1653 # create day table | |
1654 column = start | |
1655 ## p day, last | |
1656 while column <= last | |
1657 @O.print @H.elementln("tr", nil){ | |
1658 (column..column+6).collect{|d| | |
8 | 1659 todayp = (day.year==todayy && day.month==todaym && d==todayd) |
0 | 1660 wd=d-column |
1661 hd = holiday.isHoliday(day.year, day.month, d, wd) | |
1662 tdclass['class'] = (hd ? 'holiday' : wname[wd]) | |
1663 @H.element("td", tdclass){ | |
13 | 1664 if d>0 |
1665 thisday = first+(d-1)*3600*24 | |
1666 #date = "%d/%d/%d"%[day.year, day.month, d] | |
1667 date = "%d/%d/%d"%[thisday.year, thisday.month, thisday.day] | |
0 | 1668 @H.element("p", {'class'=>todayp ? 'todayline' : 'dayline'}){ |
13 | 1669 ##@H.a(@myname+"?-show+"+date, "%4d"%d) |
1670 @H.a(@myname+"?-show+"+date, "%4d"%thisday.day) | |
0 | 1671 } + \ |
1672 # isHoliday? | |
1673 if hd | |
1674 @H.element("small"){hd.join("<br>")} | |
1675 end.to_s + \ | |
1676 @H.element("p", {'class'=>'topic'}){ | |
2 | 1677 s = @sc.day_all(date, @params['user'], personal) |
0 | 1678 if !s.empty? |
1679 s.keys.sort.collect{|time| | |
1680 s[time].keys.sort.collect{|who| | |
32
d23a2b3c456b
Save schedule text `as is' in a file and escape them for browser.
HIROSE Yuuji <yuuji@gentei.org>
parents:
31
diff
changeset
|
1681 text = escape(s[time][who]['sched']) |
6 | 1682 topic = sprintf "%s%s", |
3 | 1683 time == @opt['alldaydir'] ? '' : time+":", |
2 | 1684 if personal |
9 | 1685 (@params['user'] == who ? "" : nickname(who)+"=") + |
7 | 1686 text ## .split("\n") ##[0] |
2 | 1687 else |
5 | 1688 nickname(who) + \ |
3 | 1689 if headline == 'whole' |
5 | 1690 '=' + text |
3 | 1691 elsif headline == 'head5char' |
5 | 1692 '=' + text.gsub(/\n/, '').sub(/(.{5}).*/, '\1') |
3 | 1693 elsif headline == 'headline' |
5 | 1694 '=' + text.split("\n")[0] |
3 | 1695 end.to_s |
2 | 1696 end |
6 | 1697 if hldays > 0 && |
1698 (today - s[time][who]['regtime']) < hldays | |
1699 topic = @H.element("span", recent){topic} | |
1700 end | |
1701 topic | |
3 | 1702 }.join("<br>") |
1703 }.join("<br>\n") | |
0 | 1704 else |
1705 @opt['tdskip'] | |
1706 end | |
1707 } | |
1708 else | |
1709 @opt['tdskip'] | |
1710 end | |
1711 } | |
1712 }.join | |
1713 } | |
1714 column += 7 | |
1715 end | |
1716 | |
1717 # month-link | |
1718 @O.print @H.elementln("tr", {'class'=>'monthlink'}){ | |
1719 lm1 = lastmonth(day) | |
1720 lm2 = lastmonth(lm1) | |
1721 lm3 = lastmonth(lm2) | |
1722 nm1 = nextmonth(day) | |
1723 nm2 = nextmonth(nm1) | |
1724 nm3 = nextmonth(nm2) | |
1725 [lm3, lm2, lm1, nil, nm1, nm2, nm3].collect{|t| | |
1726 @H.element("td"){ | |
1727 if t.is_a?(Time) | |
1728 ym = sprintf("%d/%d", t.year, t.month) | |
1729 @H.a(sprintf("%s?-month+%s", @myname, ym), ym) | |
1730 else | |
1731 sprintf "%d/%d", day.year, day.month | |
1732 end | |
1733 } | |
1734 }.join("\n") | |
1735 } | |
1736 @O.print "\n"+@H.endelement(nil, true) | |
1737 | |
1738 @O.print "showtable" if @params['user'] == @author | |
3 | 1739 @O.print @H.elementln("form", {'action'=>@myname+"?-month+#{monthstr}", 'method'=>'POST'}){ |
1740 choice = [ | |
1741 [msg('nameonly'), 'name'], | |
1742 [msg('head5char'), 'head5char'], | |
1743 [msg('headline'), 'headline'], | |
1744 [msg('whole'), 'whole']] | |
1745 msg('display') + \ | |
6 | 1746 @H.select('headline', choice, headline) + "/" + \ |
1747 msg('hldays') + \ | |
1748 @H.select('headlinehl', 0..30, headlinehl) + \ | |
3 | 1749 @H.submit("GO", "GO") |
1750 } | |
0 | 1751 @O.print footer |
1752 ##schedule.day_all("2003/12/22") | |
1753 # @O.print @H.endelement() | |
1754 end | |
1755 | |
1756 # | |
1757 # Put carrying values | |
1758 def hiddenvalues() | |
2 | 1759 h = %w[user displaymode].collect{|v| |
0 | 1760 if @params[v] |
1761 sprintf "<input type=\"hidden\" name=\"%s\" value=\"%s\">\n", | |
1762 v, @params[v] | |
1763 end | |
1764 } | |
1765 h.delete(nil) | |
1766 h.join | |
1767 end | |
2 | 1768 def date2ymd(date) |
1769 %r,(\d\d\d\d+)/(\d\d?)/(\d\d?), =~ date and | |
1770 [$1.to_i, $2.to_i, $3.to_i] | |
1771 end | |
0 | 1772 # |
1773 # Return the string of table | |
2 | 1774 def dayTableString(user, datestr, range, personal = nil) |
1775 #s = @sc.day_all(date, user, personal) | |
1776 #return '' if s.empty? | |
0 | 1777 r = '' |
2 | 1778 header = @H.startelement("table", {'border'=>'1'}, true) |
1779 | |
1780 day = Time.mktime(*date2ymd(datestr)) | |
1781 i = -1 | |
1782 while (i+=1) < range | |
1783 d = Time.at(day+i*3600*24) | |
1784 date = sprintf("%04d/%02d/%02d", d.year, d.month, d.day) | |
3 | 1785 datewn = @H.element("span", {'class'=>@wnames[d.wday]}){ |
1786 sprintf("%s(%s)", date, @msg['wnames'][@lang][d.wday]) | |
1787 } | |
2 | 1788 s = @sc.day_all(date, user, personal) |
1789 next if s.empty? | |
1790 | |
1791 r << @H.element("tr", nil){ | |
1792 @H.element("th", {'class'=>'time'}){'TIME'} + \ | |
3 | 1793 @H.element("th", nil){'Who - '+datewn+' - What'} |
2 | 1794 } |
6 | 1795 for time in s.keys.sort |
2 | 1796 tstr = case time |
1797 when @opt['alldaydir'] | |
1798 msg('allday') | |
1799 else | |
1800 sprintf "%02d:%02d", time.to_i/100, time.to_i%100 | |
1801 end | |
1802 r << @H.startelement("tr", nil, true) | |
1803 r << @H.element("th", {'class'=>'time'}){tstr} | |
1804 r << @H.element("td"){ | |
1805 @H.elementln("table"){ | |
1806 s[time].keys.collect{|who| | |
1807 editable = (user==who || @sc.ismember(user, who)) | |
1808 groupp = grepgroup(who) | |
1809 @H.element("tr"){ | |
1810 @H.element("td", {'class'=>groupp ? 'group' : 'who'}){ | |
1811 if !groupp && webpage(who) | |
1812 @H.a(webpage(who), nickname(who)) | |
1813 else | |
1814 nickname(who) | |
1815 end | |
1816 } + \ | |
1817 @H.element("td"){ | |
1818 if editable | |
1819 s[time][who]['pub'] ? msg('public') : | |
1820 msg('nonpublic') | |
1821 else | |
1822 @opt['tdskip'] | |
1823 end | |
1824 } + \ | |
1825 @H.element("td"){ | |
1826 if editable | |
1827 @H.a(@myname+"?-modify+#{date}/#{time}/#{who}", | |
1828 msg('modify')) | |
1829 else | |
1830 @opt['tdskip'] | |
1831 end | |
1832 } + \ | |
1833 @H.element("td"){ | |
1834 if editable | |
1835 @H.a(@myname+"?-remove+#{date}/#{time}/#{who}", | |
1836 msg('remove')) | |
1837 else | |
1838 @opt['tdskip'] | |
1839 end | |
1840 } + \ | |
14 | 1841 @H.element("td"){ |
1842 if editable | |
1843 @H.a(@myname+"?-move+#{date}/#{time}/#{who}", | |
1844 msg('move')) | |
1845 else | |
1846 @opt['tdskip'] | |
1847 end | |
1848 } + \ | |
32
d23a2b3c456b
Save schedule text `as is' in a file and escape them for browser.
HIROSE Yuuji <yuuji@gentei.org>
parents:
31
diff
changeset
|
1849 @H.element("td"){escape(s[time][who]['sched'])} |
2 | 1850 } |
1851 }.join("\n") | |
1852 } | |
0 | 1853 } |
2 | 1854 r << @H.endelement() |
1855 end | |
0 | 1856 end |
2 | 1857 footer = @H.endelement() |
1858 if r > '' | |
1859 header + r + footer | |
1860 else | |
1861 '' | |
1862 end | |
0 | 1863 end |
14 | 1864 def dayTextString(user, datestr, range, personal = nil) |
1865 r = '' | |
1866 cols = 20 | |
1867 header = "-" * cols + "\n" | |
1868 | |
1869 day = Time.mktime(*date2ymd(datestr)) | |
1870 i = -1 | |
1871 while (i+=1) < range | |
1872 d = Time.at(day+i*3600*24) | |
1873 date = sprintf("%04d/%02d/%02d", d.year, d.month, d.day) | |
1874 datewn = sprintf("%s(%s)", date, @msg['wnames'][@lang][d.wday]) | |
1875 s = @sc.day_all(date, user, personal) | |
1876 next if s.empty? | |
1877 | |
1878 r << sprintf("TIME Who %s - What\n", datewn) | |
1879 | |
1880 for time in s.keys.sort | |
1881 tstr = case time | |
1882 when @opt['alldaydir'] | |
1883 msg('allday') | |
1884 else | |
1885 sprintf "%02d:%02d", time.to_i/100, time.to_i%100 | |
1886 end | |
1887 r << s[time].keys.collect{|who| | |
1888 editable = (user==who || @sc.ismember(user, who)) | |
1889 groupp = grepgroup(who) | |
32
d23a2b3c456b
Save schedule text `as is' in a file and escape them for browser.
HIROSE Yuuji <yuuji@gentei.org>
parents:
31
diff
changeset
|
1890 sprintf("%-5s %-10s %s", |
d23a2b3c456b
Save schedule text `as is' in a file and escape them for browser.
HIROSE Yuuji <yuuji@gentei.org>
parents:
31
diff
changeset
|
1891 tstr, nickname(who), escape(s[time][who]['sched'])) |
14 | 1892 }.join("\n") + "\n" |
1893 end | |
1894 r << "-" * cols + "\n" | |
1895 end | |
1896 footer = "That's all\n" | |
1897 if r > '' | |
1898 header + r + footer | |
1899 else | |
1900 '' | |
1901 end | |
1902 | |
1903 end | |
0 | 1904 # |
2 | 1905 # new form |
1906 def displayRegistForm(date, multiple = true) | |
0 | 1907 # |
1908 # Link button to add new plan | |
1909 #now = Time.now+3600*24 | |
2 | 1910 thisyear, thismonth, thisday = date.scan(%r,(\d\d\d\d+)/(\d+)/(\d+),)[0] |
1911 user = @params['user'] | |
0 | 1912 now = Time.mktime(thisyear, thismonth, thisday.to_i, Time.now.hour) |
1913 y, m, d, h, min = now.year, now.month, now.day, now.hour, now.min | |
2 | 1914 nextweek = Time.at(now+3600*24*7) |
1915 ey, em, ed = nextweek.year, nextweek.month, nextweek.day | |
1916 rcsp = (multiple ? {'colspan'=>'2'} : nil) | |
1917 wnames = @msg['wnames'][@lang] | |
1918 wnames << @msg['everyday'][@lang] | |
1919 | |
0 | 1920 @O.print @H.element('h2', nil, true){msg('addsched')} |
1921 @O.print @H.element('p', nil){msg('defthisday')} | |
2 | 1922 |
0 | 1923 @O.print @H.element("form", {'action'=>@myname+"?-addsched", 'method'=>'POST'}){ |
2 | 1924 border1 = {'border'=>'1'} |
1925 border1c = {'border'=>'1', 'class'=>'c'} | |
1926 mygroup = @sc.groups().select{|g|@sc.ismember(user, g)} | |
0 | 1927 @H.elementln('table', border1){ |
1928 @H.elementln('tr'){ | |
1929 @H.element('th'){'Name'} + \ | |
2 | 1930 @H.element('td', rcsp){ |
0 | 1931 hiddenvalues() + @sc.nickname(user) |
1932 } | |
1933 } + \ | |
1934 @H.elementln('tr'){ | |
1935 @H.element('th'){'Year'} + \ | |
2 | 1936 @H.element('td'){@H.select("year", y..y+5, y)} + \ |
1937 if multiple | |
1938 @H.element('td'){ | |
1939 d1 = msg('singleday') | |
1940 msg('through')+@H.select("endyear", [d1]+(y..y+5).to_a, d1) | |
1941 } | |
1942 end | |
0 | 1943 } + \ |
1944 @H.elementln('tr'){ | |
1945 @H.element('th'){'Month'} + \ | |
2 | 1946 @H.element('td'){@H.select("month", 1..12, m)} + \ |
1947 if multiple | |
1948 @H.element('td'){ | |
1949 msg('through')+@H.select("endmonth", 1..12, em) | |
1950 } | |
1951 end | |
0 | 1952 } + \ |
1953 @H.elementln('tr'){ | |
1954 @H.element('th'){'Day'} + \ | |
2 | 1955 @H.element('td'){@H.select("day", 1..31, d)} + \ |
1956 if multiple | |
1957 @H.element('td'){ | |
1958 msg('through')+@H.select("endday", 1..31, ed) | |
1959 } | |
1960 end | |
0 | 1961 } + \ |
2 | 1962 if multiple |
1963 @H.elementln('tr'){ | |
1964 @H.element('th'){ | |
1965 msg('whichday') | |
1966 } + \ | |
1967 @H.element('td', rcsp){ | |
1968 @H.elementln('table', border1c){ | |
1969 @H.element('tr'){ | |
1970 i=-1 | |
1971 wnames.collect{|w| | |
1972 @H.element('td'){ | |
1973 i+=1 | |
1974 @H.radio('whichday', i.to_s, '', i==wnames.length-1) | |
1975 } | |
1976 }.join("\n") | |
1977 } + \ | |
1978 @H.element('tr'){ | |
1979 i=-1 | |
1980 wnames.collect{|w| | |
1981 @H.element('td'){w} | |
1982 }.join | |
1983 } | |
1984 } | |
1985 } | |
1986 } | |
1987 end + \ | |
0 | 1988 @H.elementln('tr'){ |
1989 @H.element('th'){'Time<br>'+ \ | |
1990 sprintf(msg('24hour'), @opt['alldaydir'])} + \ | |
2 | 1991 @H.element('td', rcsp){ |
0 | 1992 '<input type=text name="time" value="3000" size=8 maxlength="4">' |
1993 } | |
1994 } + \ | |
1995 @H.elementln('tr'){ | |
1996 @H.element('th'){msg('publicok')} + \ | |
2 | 1997 @H.element('td', rcsp){ |
0 | 1998 @H.radio('pub', 'yes', msg('yes')+'<br>', true) + \ |
1999 @H.radio('pub', 'no', msg('no')) | |
2000 } | |
2001 } | |
2002 ## table | |
2003 } + \ | |
2004 @H.elementln("p"){ # put notify mail checkbox | |
2005 msg('reqnotify') + '<br>' + \ | |
2006 @ntlist.collect{|n, v| | |
8 | 2007 # Actual variables of notifylist for submitting is "sub_"+n |
2008 @H.checkbox("sub_"+n, 'yes', v, @params[n]) | |
0 | 2009 }.join("\n") + \ |
2010 " " + @H.checkbox('rightnow', 'yes', msg('rightnow'), true) + \ | |
2011 "\n" | |
2012 } + \ | |
2013 if mygroup[0] | |
2014 @H.elementln("p"){ # put "register as" | |
2015 msg('registas') + "<br>\n" + \ | |
2016 mygroup.collect{|g| | |
2017 @H.radio('registas', g, @sc.groupname(g)) | |
2018 }.join(' ') + "\n/ " + \ | |
2019 @H.radio('registas', 'no', msg('personal')) | |
2020 } | |
2021 end.to_s + "\n" + \ | |
2 | 2022 @H.radio('editmode', 'remove', 'Delete?') + " / " + \ |
2023 @H.radio('editmode', 'modify', 'Overwrite?') + " / " + \ | |
2024 @H.radio('editmode', 'append', 'Append?', true) + "<br>\n" + \ | |
17 | 2025 @H.element("p"){msg('headsched') + \ |
2026 @H.element("textarea", @schedulearea){}} + # textarea | |
0 | 2027 @H.submit_reset("GO") |
2028 } #form | |
2 | 2029 end |
2030 # | |
2031 # show the schedule list of specified date | |
2032 # | |
2033 def show(date) | |
2034 if !checkauth | |
2035 return nil | |
2036 end | |
2037 user = safecopy(@params['user']) | |
2038 personal = (/personal/i =~ @params['displaymode']) | |
2039 @params['displaydays'] = @params['displaydays'] || @cookie['displaydays'] | |
3 | 2040 days = @params['displaydays'].to_i |
18 | 2041 days = (days > 0 ? days : 3) |
2 | 2042 |
2043 # str = @sc.day_all(date, user, personal) | |
2044 outstr = dayTableString(user, date, days, personal) | |
2045 | |
2046 @O.print @H.element("h1", nil){ | |
2047 sprintf msg('fmtdaysschedule'), date | |
2048 } | |
18 | 2049 @O.print @H.element("h2"){msg('schedtable')} |
2 | 2050 ## @O.print @H.p() |
2051 @O.print @H.elementln("form", {'action'=>@myname+"?-show+#{date}", 'method'=>'POST'}){ | |
2052 @H.elementln("p"){ | |
6 | 2053 msg(personal ? 'personalmode' : 'normalmode') + "<br>" + \ |
2 | 2054 @H.select("displaydays", 1..30, days) + msg('daystodisplay') + \ |
2055 @H.submit("GO", "GO") | |
2056 } | |
2057 } | |
2058 if outstr > '' | |
2059 @O.print outstr | |
2060 else | |
2061 @O.print @H.p(msg('noplan')) | |
2062 end #is_empty? | |
2063 thisyear, thismonth, thisday = date.scan(%r,(\d\d\d\d+)/(\d+)/(\d+),)[0] | |
2064 mstr = sprintf "%04d/%02d", thisyear.to_i, thismonth.to_i | |
2065 @O.print @H.a(@myname+"?-month+"+mstr, | |
2066 sprintf(msg('tomonthlist'), mstr)) | |
2067 | |
2068 | |
2069 # | |
2070 # Display registration form | |
2071 displayRegistForm(date) | |
0 | 2072 @O.print "show" if user == @author |
2073 end | |
2074 | |
2075 # | |
2076 # call process | |
2077 def call_process(cmd, input=nil, timeout=10) | |
2078 prc = CMDTimeout.new | |
2079 fds = prc.start(cmd, timeout, true) | |
2080 if input | |
2081 Thread.start { | |
2082 fds[0].sync = true | |
2083 fds[0].print.input | |
2084 fds[0] | |
2085 } | |
2086 end | |
2087 begin | |
2088 fds[1].readlines | |
2089 ensure | |
2090 prc.close() | |
2091 end | |
2092 end | |
2093 # | |
2094 # notification registerer | |
2095 def notify_time(year, month, day, time, symbol) | |
2096 if (t = time.to_i) > 2359 | |
2097 hh = mm = 0 | |
2098 else | |
2099 hh, mm = t/100, t%100 | |
2100 end | |
2101 base = Time.mktime(year.to_i, month.to_i, day.to_i, hh, mm) | |
2102 if /nt(\d+)([mh])$/ =~ symbol | |
2103 return nil if t > 2359 | |
2104 num, unit = $1.to_i, $2.downcase | |
2105 rate = {'h'=>3600, 'm'=>60}[unit] || 3600 | |
2106 return Time.at(base-rate*num) | |
2107 elsif /nt(\d+)d/ =~ symbol | |
2108 seconds = $1.to_i*3600*24 | |
14 | 2109 tday= Time.at(base-seconds) |
2110 target = [tday.year, tday.month, tday.day, @opt['night'].to_i] | |
2111 targetnight = Time.mktime(*target) | |
0 | 2112 elsif "nttoday" == symbol |
2113 Time.mktime(year.to_i, month.to_i, day.to_i, @opt['morning']) | |
2114 end | |
2115 end | |
2116 def reg_notify(user, year, month, day, time, text, cancelall = nil) | |
6 | 2117 return nil unless @opt['notifymail'] |
0 | 2118 threshold = 5*60 # Omit notifycation within 30min future |
2119 | |
2120 y, m, d, t, = year.to_i, month.to_i, day.to_i, time.to_i | |
2121 if t > 2359 | |
2122 hh = mm = 0 | |
2123 else | |
2124 hh = t/100 | |
2125 mm = t%100 | |
2126 end | |
2127 now = Time.now | |
2128 | |
2129 filearg = [user, year, month, day, t] | |
2130 @ntlist.each{|k, v| | |
8 | 2131 # @params[k]s are always defined in cookies, so we use @params["sub_"+k] |
2132 @params[k] = @params["sub_"+k] | |
0 | 2133 nt_time = notify_time(year, month, day, t, k) |
2134 if !nt_time | |
2135 # do nothing for allday schedule's notification before some minutes | |
2136 elsif cancelall || nt_time < now+threshold || | |
2137 /yes|on|true|1/ !~ @params[k] || !@params[k] | |
2138 # cancel | |
2139 uf = @sc.remove_crondir(nt_time, user, year, month, day, t) | |
2140 @sc.removefile(*(filearg+[k])) | |
2141 else | |
2142 # register | |
2143 lf = @sc.register_crondir(nt_time, user, year, month, day, t) | |
2144 @sc.putfile(*(filearg+[k, lf])) | |
2145 end | |
2146 } | |
2147 end | |
2148 def cancel_notify(user, year, month, day, time) | |
2149 reg_notify(user, year, month, day, time, 'dummy', true) | |
2150 end | |
2 | 2151 |
2152 def commit_schedule(who, y, m, d, timedir, text, repl, pub) | |
2153 | |
2154 end | |
2155 | |
14 | 2156 def regulate_time(y, m, d, tm) |
2157 if tm > 2399 | |
2158 sh, smin = 23, 59 | |
2159 timedir=@opt['alldaydir'] | |
2160 tmstr = msg('allday') | |
2161 else | |
2162 sh = (tm/100).to_i | |
2163 smin = (tm%100).to_i | |
2164 timedir = sprintf("%04d", tm) | |
2165 tmstr = sprintf("%d:%02d", sh, smin) | |
2166 end | |
2167 time = nil | |
2168 begin | |
2169 time = Time.mktime(y, m, d, sh, smin) | |
2170 rescue | |
2171 outputError "%s<br>\nyear=%s<br>month=%s<br>day=%s<br>time=%s\n", | |
2172 msg('invaliddate'), | |
2173 @params['year'], @params['month'], @params['day'], @params['time'] | |
2174 return nil | |
2175 end | |
2176 [time, timedir, tmstr] | |
2177 end | |
2178 | |
0 | 2179 # |
2180 # add or remove a schedule | |
2181 # | |
2182 def add_remove(remove = nil) | |
2183 if !checkauth | |
2184 return nil | |
2185 end | |
2186 user = registerer = @params['user'] | |
2187 as = @params['registas'] | |
2188 if as && as > '' && /^no$/ !~ as && @sc.ismember(user, as) | |
3 | 2189 if (gr=grepgroup(as)) |
2190 registerer = gr | |
2191 end | |
0 | 2192 end |
2193 now = Time.now | |
2 | 2194 #y, m, d, h, min = now.year, now.month, now.day, now.hour, now.min |
0 | 2195 |
2196 $KCODE='e' if $DEBUG | |
2197 @O.print @params.inspect if $DEBUG | |
2198 # | |
2199 # Check the validity of specified time | |
2200 sy = @params['year'].to_i | |
2201 sm = @params['month'].to_i | |
2202 sd = @params['day'].to_i | |
2203 tm = @params['time'].to_i | |
14 | 2204 |
2205 time, timedir, tmstr = regulate_time(sy, sm, sd, tm) | |
2 | 2206 |
2207 # | |
2208 # Check continuous schedule registration | |
2209 wwday = @params['whichday'].to_i | |
2210 if @params['endyear'] && @params['endmonth'] && @params['endday'] && | |
2211 (ey=@params['endyear'].to_i) > 0 && | |
2212 (em=@params['endmonth'].to_i) > 0 && | |
2213 (ed=@params['endday'].to_i) > 0 | |
2214 daylist = [] | |
2215 endtime = Time.mktime(ey, em, ed, 23, 59) | |
2216 ti = time | |
2217 begin | |
2218 if wwday==7 || wwday==ti.wday | |
2219 daylist << [ti.year, ti.month, ti.day] | |
2220 end | |
9 | 2221 end while (ti=Time.at(ti+3600*24)) <= endtime |
2 | 2222 else |
2223 daylist = [[sy, sm, sd]] | |
2224 end | |
2225 | |
2226 if !remove && !(@params['schedule'] && @params['schedule'].strip > '') | |
0 | 2227 outputError msg('putsomething') |
2228 return nil | |
2229 end | |
2230 | |
2 | 2231 |
2232 for y, m, d in daylist | |
2233 # do remove or addition | |
2234 if remove | |
2235 cancel_notify(registerer, y, m, d, timedir) | |
2236 begin | |
2237 @sc.remove(registerer, y, m, d, timedir) | |
2238 #########@O.print @H.p(msg('remove')+msg('done')) | |
2239 rescue | |
2240 outputError("Failed"+$!) | |
2241 end | |
2242 else | |
2243 if time < now | |
2244 outputError(msg('past')) | |
2245 return nil | |
2246 end | |
2247 begin | |
32
d23a2b3c456b
Save schedule text `as is' in a file and escape them for browser.
HIROSE Yuuji <yuuji@gentei.org>
parents:
31
diff
changeset
|
2248 |
d23a2b3c456b
Save schedule text `as is' in a file and escape them for browser.
HIROSE Yuuji <yuuji@gentei.org>
parents:
31
diff
changeset
|
2249 (text = @params['schedule'].toeuc.strip.gsub(/\r+\n/, $/)) << "\n" |
d23a2b3c456b
Save schedule text `as is' in a file and escape them for browser.
HIROSE Yuuji <yuuji@gentei.org>
parents:
31
diff
changeset
|
2250 # text = purify(text) |
d23a2b3c456b
Save schedule text `as is' in a file and escape them for browser.
HIROSE Yuuji <yuuji@gentei.org>
parents:
31
diff
changeset
|
2251 STDERR.print text |
2 | 2252 replace = (/modify/i =~ @params['editmode']) |
2253 rc = @sc.register(registerer, y, m, d, timedir, text, replace) | |
2254 if @params['pub'] && /yes/ =~ @params['pub'] | |
2255 @sc.putfile(registerer, y, m, d, timedir, 'pub', "1\n") | |
2256 else | |
2257 @sc.removefile(registerer, y, m, d, timedir, 'pub') | |
2258 end | |
2259 ######## @O.print @H.p(msg('appended')) if rc == 1 | |
2260 rescue | |
2261 outputError("Failed"+$!) | |
2262 end | |
17 | 2263 text = @sc.getschedule(registerer, y, m, d, timedir) |
2 | 2264 reg_notify(registerer, y, m, d, timedir, text) |
2265 | |
0 | 2266 end |
2 | 2267 |
2268 end | |
2269 | |
2270 if !remove && @params['rightnow'] && /yes/i =~ @params['rightnow'] | |
2271 header = sprintf("%s\n%s/%s/%s%s %s %s\n%s%s%s\n%s\n", | |
2272 @opt['url'], | |
2273 sy, sm, sd, | |
2274 if daylist.length > 1 | |
2275 "-%s/%s/%s" % daylist[-1] | |
2276 end, | |
2277 tmstr, msg('immediatenote'), | |
2278 msg('registerer_is'), nickname(registerer), | |
2279 if user!=registerer | |
2280 sprintf(" (%s%s)", | |
2281 msg('registerer'), nickname(user)) | |
2282 else | |
2283 "" | |
2284 end, | |
2285 "-"*70) | |
2286 sendnotify(registerer, "Registration completed", header+text) | |
0 | 2287 end |
14 | 2288 unless @mailmode |
2289 show(sprintf("%04d/%02d/%02d", sy, sm, sd)) | |
2290 @O.print "add_remove" if user == @author | |
2291 end | |
0 | 2292 end |
2293 | |
2294 # add | |
2295 def addsched() | |
14 | 2296 if "move" == @params['editmode'] |
2297 add_remove(:remove) | |
2298 for p in %w(year month day time) do | |
2299 @params[p] = @params["new"+p] | |
2300 end | |
2301 end | |
2302 add_remove(/^remove/i =~ @params['editmode']) | |
0 | 2303 end |
2304 | |
2305 # | |
2306 # Display remove or modify screen | |
14 | 2307 def remove_modify(datetime, editmode) |
0 | 2308 if !checkauth |
2309 return nil | |
2310 end | |
2311 | |
2312 user = @params['user'] | |
2313 y, m, d, time, dummy, as = | |
2314 datetime.scan(%r,(\d\d\d\d+)/(\d+)/(\d+)/(\d+)(/(.+))?,)[0] | |
2315 # datetime always contains trailing slash generated by parsedate | |
2316 # but if the trailing part is a user(not a group), it is removed | |
2317 # because it filtered out by grepgroup() function | |
2318 if ! (y && m && d && time) | |
2319 outputError "Invalid time specification" | |
2320 return nil | |
2321 elsif as && as > '' | |
2322 unless @sc.ismember(user, as) | |
2323 outputError "You have no permission to edit group %s's schedule", as | |
2324 return nil | |
2325 end | |
2326 user = as | |
2327 end | |
2328 unless text=@sc.getschedule(user, y, m, d, time) | |
2329 outputError "%s %s", datetime, msg('noplan') | |
2330 return nil | |
2331 end | |
32
d23a2b3c456b
Save schedule text `as is' in a file and escape them for browser.
HIROSE Yuuji <yuuji@gentei.org>
parents:
31
diff
changeset
|
2332 ## text = decode(text) |
0 | 2333 @O.print @H.elementln("h1"){ |
14 | 2334 sprintf "%s %s", datetime, msg(editmode) |
0 | 2335 } |
2336 @O.print @H.elementln("form", {'action'=>@myname+"?-addsched", 'method'=>'POST'}){ | |
2337 pubp=(@sc.getfile(user, y, m, d, time, 'pub').to_i > 0) | |
2338 if as | |
2339 @H.hidden("registas", as) | |
2340 end.to_s + \ | |
2341 "<input type=\"hidden\" name=\"year\" value=\"%04d\">\n" % y.to_i + \ | |
2342 "<input type=\"hidden\" name=\"month\" value=\"%02d\">\n" % m.to_i + \ | |
2343 "<input type=\"hidden\" name=\"day\" value=\"%02d\">\n" % d.to_i + \ | |
2344 "<input type=\"hidden\" name=\"time\" value=\"%04d\">\n" % time.to_i + \ | |
14 | 2345 if editmode=="move" |
2346 @H.elementln("table") { | |
2347 @H.elementln("tr", {"colspan" => "2"}) {msg('newdate')} + \ | |
2348 @H.elementln("tr") { | |
2349 @H.element("th"){"Year"} + \ | |
2350 @H.element("td"){@H.select("newyear", y.to_i..y.to_i+5, y)} | |
2351 } + \ | |
2352 @H.elementln("tr") { | |
2353 @H.element("th"){"Month"} + \ | |
2354 @H.element("td"){@H.select("newmonth", 1..12, m)} | |
2355 } + \ | |
2356 @H.elementln("tr") { | |
2357 @H.element("th"){"Day"} + \ | |
2358 @H.element("td"){@H.select("newday", 1..31, d)} | |
2359 } + \ | |
2360 @H.elementln("tr") { | |
2361 @H.element("th"){"Time"} + \ | |
2362 @H.element("td"){ | |
2363 "<input type=text name=\"newtime\" value=\"#{time}\" " + \ | |
2364 "size=\"8\" maxlength=\"4\">" | |
2365 } | |
2366 } | |
2367 } | |
2368 end.to_s + \ | |
2369 @H.elementln("div", {"style" => | |
2370 "visibility: " + | |
2371 (editmode=="move" ? "hidden" : "show") + "\""}) { | |
2372 msg('reqnotify') + "<br>\n" + \ | |
2373 @ntlist.collect{|nt, v| | |
2374 cronp = @sc.getfile(user, y, m, d, time, nt) | |
2375 sprintf "<input type=\"checkbox\" name=\"%s\"%s>%s \n", | |
2376 nt, (cronp ? " checked" : ""), v | |
2377 }.join + "<br>" | |
2378 } + \ | |
0 | 2379 @H.element("textarea", @schedulearea) {text} + "<br>" + \ |
2380 @H.radio("editmode", "append", msg('append')) + ' / ' + \ | |
14 | 2381 @H.radio("editmode", "modify", msg('modify'), editmode=="modify")+' / '+\ |
2382 @H.radio("editmode", "remove", msg('remove'), editmode=="remove")+' / '+\ | |
2383 @H.radio("editmode", "move", msg('move'), editmode=="move") + ' / ' + \ | |
0 | 2384 "<br>\n" + \ |
2385 msg('publicok') + \ | |
2386 @H.radio("pub", "yes", msg('yes'), pubp) + \ | |
2387 @H.radio("pub", "no", msg('no'), !pubp) + \ | |
2388 '<br>' + \ | |
2389 @H.submit_reset("GO") | |
2390 } | |
2391 @O.print "remove_modify" if user == @author | |
2392 end | |
2393 def remove(datetime) | |
14 | 2394 remove_modify(datetime, "remove") |
0 | 2395 end |
2396 def modify(datetime) | |
14 | 2397 remove_modify(datetime, "modify") |
2398 end | |
2399 def move(datetime) | |
2400 remove_modify(datetime, "move") | |
0 | 2401 end |
2402 | |
2403 def prohibitviahttp() | |
2404 %w[REMOTE_ADDR REMOTE_HOST SERVER_NAME].each{|v| | |
2405 if ENV[v] | |
2406 print "Content-type: text/plain\n\n" | |
2407 print "Do not call this via CGI" | |
2408 exit 0 | |
2409 end | |
2410 } | |
2411 end | |
2412 # | |
2413 # notify: call via cron | |
2414 def notify() | |
2415 prohibitviahttp() | |
2416 unless @opt['maintainer'] | |
2417 STDERR.printf "Set maintainer(email-address) in %s\n", @opt['conf'] | |
2418 STDERR.print "(ex) maintainer=yuuji@gentei.org\n" | |
2419 exit 0 | |
2420 end | |
2421 Dir.chdir @mydir | |
2422 line = "-"*25 | |
2423 indent = " " | |
2424 now = Time.now | |
2425 p "notifylist", @sc.notify_list(now) if $DEBUG | |
2426 @sc.notify_list(now).each{|u, datehash| | |
2427 dellist = [] | |
2428 content = datehash.sort.collect{|date, filehash| | |
2429 next unless /(\d\d\d\d+)-(\d+)-(\d+)-(\d\d\d\d)/ =~ date | |
2430 y, m, d, t = $1.to_i, $2.to_i, $3.to_i, $4.to_i | |
11 | 2431 ddiff=(Time.mktime(y, m, d) \ |
2432 - Time.mktime(now.year, now.month, now.day))/3600/24 | |
0 | 2433 if t > 2359 |
2434 hhmm = msg('allday') | |
11 | 2435 if ddiff > 1 |
2436 comment = "%d%s" % [ddiff, msg('days', 'before')] | |
2437 else | |
2438 comment = msg(now.hour > 18 ? 'precedingday' : 'theday') | |
2439 end | |
0 | 2440 else |
2441 hhmm = sprintf "%02d:%02d", t/100, t%100 | |
2 | 2442 diff = Time.mktime(y, m, d, t/100, t%100) - now |
0 | 2443 if diff < 7200 |
2444 comment = "%d%s" % [diff/60, msg('minutes', 'before')] | |
11 | 2445 elsif (ddiff == 0) |
0 | 2446 comment = "%s%d%s" % |
2447 [msg('about'), diff/3600, msg('hours', 'before')] | |
2448 else | |
2449 comment = "%d%s" % [ddiff, msg('days', 'before')] | |
2450 end | |
2451 end | |
2452 dellist << filehash['file'] | |
2453 sprintf("%s[[[%d/%d/%d %s]]]%s\n", line, y, m, d, hhmm, line) + \ | |
2454 sprintf("(%s %s)\n", comment, msg('notification')) + \ | |
31
aceb533dfa32
Schedule file is already decoded. No need to decode again.
HIROSE Yuuji <yuuji@gentei.org>
parents:
30
diff
changeset
|
2455 indent+filehash['text'].join(indent) + "\n\n" |
0 | 2456 } |
2457 # content.delete(nil) | |
2458 if content | |
2459 if $DEBUG | |
2460 print content | |
2461 else | |
2462 content.unshift(msg('introduce')+"\n"+msg('notifymail')+"\n") | |
2463 content.unshift(@opt['url'].to_s+"\n") | |
2464 if sendnotify(u, msg('notifysubj'), content.join) | |
2465 # send mail completed | |
2466 begin | |
2467 @sc.cleanup_files(dellist) | |
2468 rescue | |
2469 end | |
2470 end | |
2471 end | |
2472 end | |
2473 } | |
2474 if !(list=@sc.notify_list(now)).empty? | |
2475 subj = @mybase+": Undeleted old cron files detected" | |
2476 files = list.collect{|who, whash| | |
2477 whash.sort.collect{|date, fhash| fhash['file']}.join("\n") | |
2478 }.join("\n") | |
2479 sendMail(@opt['maintainer'], subj, | |
2480 "This is `#{@mybase}' in #{@mydir}\n" + | |
2481 "You'd better check and remove these files.\n\n"+files) | |
2482 end | |
2483 | |
2484 exit 0 | |
2485 end | |
2486 | |
2487 # | |
2488 # user management | |
2489 def userman() | |
2490 if !checkauth | |
2491 return nil | |
2492 end | |
2493 user=@params['user'] | |
2494 nickname = @sc.nickname(user) | |
2495 tdclass = {} | |
2496 tdclass["width"] = "80px" if @oldagent # workaround for NN4 | |
2497 | |
2498 @O.print @H.elementln("h1"){ | |
2499 @mybase+' '+msg('user', 'management') | |
2500 } | |
2501 @O.print @H.p(@sc.mkusermap.inspect) if $DEBUG | |
2502 @O.print @H.p(msg('usermodwarn')) | |
2503 @O.print \ | |
2504 @H.elementln("form", {'action'=>@myname+"?-usermod", 'method'=>'POST'}){ | |
2505 @H.elementln("table"){ | |
2506 @H.elementln("tr"){ | |
2507 @H.element("td", tdclass) {msg('regaddress')} + \ | |
2508 @H.element("td") { | |
2509 @H.element("code"){user} | |
2510 } | |
2511 } + \ | |
2512 @H.elementln("tr"){ | |
2513 @H.element("td", tdclass) {msg('mailaddress')} + \ | |
2514 @H.element("td") { | |
2515 @H.text("newmail", mailaddress(user), @opt['size'], 80) | |
2516 } | |
2517 } + \ | |
2518 @H.elementln("tr"){ | |
2519 @H.element("td", tdclass) {msg('weburl')} + \ | |
2520 @H.element("td") { | |
2521 @H.text("webpage", webpage(user), @opt['size'], 80) | |
2522 } | |
2523 } + \ | |
2524 @H.elementln("tr"){ | |
2525 @H.element("td") {msg('nickname')} + \ | |
2526 @H.element("td") { | |
2527 @H.text("nickname", nickname, @opt['size'], 10) | |
2528 } | |
2529 } | |
2530 } + \ | |
2531 @H.elementln("p"){ | |
2532 msg('shortnameplz') + "<br>\n" + \ | |
2533 @H.a(@after5url+"multiplenotify.html", msg('multiplemail')) | |
2534 } + \ | |
2535 '<br>' + \ | |
2536 @H.submit_reset("GO") | |
2537 } # form | |
2538 | |
2539 # | |
2540 # Next section, REMOVE USER! | |
2541 @O.print @H.elementln("h2"){ | |
2542 sprintf "%s %s %s", msg('user'), user, msg('deletion') | |
2543 } | |
2544 @O.print @H.p(msg('deletionwarn'))+"\n" | |
2545 @O.print @H.elementln("form", {'action'=>@myname+"?-delusersub+#{user}", 'method'=>'POST'}){ | |
2546 @H.hidden("user", user) + "\n" + \ | |
2547 @H.elementln("table"){ | |
2548 @H.elementln("tr"){ | |
2549 @H.elementln("td"){ | |
2550 sprintf msg('deluser'), user | |
2551 } + \ | |
2552 @H.elementln("td"){ | |
2553 @H.radio("delete", "yes", msg('yes')) + ' ' + \ | |
2554 @H.radio("delete", "no", msg('no'), true) | |
2555 } | |
2556 } + \ | |
2557 @H.elementln("tr"){ | |
2558 @H.elementln("td"){ | |
2559 sprintf msg('really?'), user | |
2560 } + \ | |
2561 @H.elementln("td"){ | |
2562 @H.radio("delete2", "yes", msg('yes')) + ' ' + \ | |
2563 @H.radio("delete2", "no", msg('no'), true) | |
2564 } | |
2565 } | |
2566 } + \ | |
2567 "<br>\n" + @H.submit_reset("GO") | |
2568 } | |
2569 | |
2570 | |
2571 end | |
2572 def usermod() | |
2573 if !checkauth | |
2574 return nil | |
2575 end | |
2576 @O.print @H.elementln("h1"){ | |
2577 msg('user', 'management')+" "+msg('done') | |
2578 } | |
2579 user=@params['user'] | |
2580 email = mailaddress(user) | |
2581 newmail = @params['newmail'] | |
2582 nickname = @sc.nickname(user) | |
2583 newnn = @params['nickname'].to_s.strip | |
2584 webpage = webpage(user) | |
2585 newweb = @params['webpage'] | |
2586 if email != newmail | |
2587 # change user's address | |
2588 if newmail == user | |
2589 newvalue = nil | |
2590 elsif checkmail(newmail) | |
2591 newvalue = newmail | |
2592 else | |
2593 @O.print @H.elementln("pre"){"Invalid mail address"} | |
2594 end | |
2595 @O.print @H.elementln("pre"){ | |
2596 if @sc.putuserattr(user, 'email', newvalue) | |
2597 sprintf "new mail address=\"%s\"", mailaddress(user) | |
2598 else | |
2599 sprintf "Setting new mail address to \"%s\" failed", newvalue | |
2600 end | |
2601 } | |
2602 end | |
2603 if nickname != newnn | |
2604 if @sc.setnickname(user, newnn) | |
2605 @O.print @H.p(msg('success')) | |
2606 @O.print @H.elementln("pre"){ | |
2607 sprintf "user=\"%s\"\nnickname=\"%s\"", user, @sc.nickname(user) | |
2608 } | |
2609 @O.print @H.p(msg('nicknamenote')) if newnn == '' | |
2610 else | |
2611 @O.print @H.p(msg('failure')) | |
2612 end | |
2613 end | |
2614 if newweb > '' && webpage != newweb | |
2615 if @sc.putuserattr(user, "webpage", newweb) | |
2616 @O.print @H.p(msg('success')) | |
2617 @O.print @H.elementln("pre"){ | |
2618 sprintf "user=\"%s\"\nwebpage=\"%s\"", user, webpage(user) | |
2619 } | |
2620 else | |
2621 @O.print @H.p("Update webpage"+msg('failure')) | |
2622 end | |
2623 end | |
2624 end | |
2625 # | |
2626 # Display form of group management | |
2627 def groupman() | |
2628 if !checkauth | |
2629 return nil | |
2630 end | |
2631 user=@params['user'] | |
2632 nickname = @sc.nickname(user) | |
2633 tdclass = {} | |
2634 tdclass["width"] = "80px" if @oldagent # workaround for NN4 | |
2635 admclass = {'class'=>'admin'} | |
2636 grmap = @sc.groupmap | |
2637 | |
2638 @O.print @H.elementln("h1"){ | |
2639 @mybase+' '+msg('group', 'management') | |
2640 } | |
2641 $KCODE='e' if $DEBUG | |
2642 @O.print grmap.inspect if $DEBUG | |
2643 @O.print @H.p(msg('joinmyself')+ | |
2644 @H.a(@myname+"?-newgroup", msg('newgroup'))) | |
2645 @O.print @H.p(msg('usermodwarn')) | |
2646 @O.print \ | |
2647 @H.elementln("form", {'action'=>@myname+"?-groupmod", 'method'=>'POST'}){ | |
2648 @H.elementln("table", {'border'=>'1', 'vertical-align'=>'top'}){ | |
2649 grmap.collect{|g, ghash| | |
2650 @H.elementln("tr"){ | |
2651 @H.element("td", @sc.isadmin(user, g) ? admclass : nil){ | |
2652 g | |
2653 } + \ | |
2654 @H.element("td"){ | |
2655 @H.element("div", {'class'=>'c'}) { | |
2656 if @sc.isadmin(user, g) | |
2657 @H.a(@myname+"?-admgroup+#{g}", msg('adminop')) | |
2658 else | |
2659 '--' | |
2660 end | |
2661 } | |
2662 } + \ | |
2663 @H.element("td"){ | |
2664 memberp = @sc.ismember(user, g) | |
2665 if ghash['admin'].grep(user)[0] | |
2666 @H.text("groupname-#{g}", ghash['name'], nil, 20) | |
2667 else | |
2668 ghash['name'] | |
2669 end + '<br>' + \ | |
2670 @H.radio("groupadd-#{g}", "yes", "IN", memberp) + " / " + \ | |
2671 @H.radio("groupadd-#{g}", "no", "OUT", !memberp) | |
2672 } + \ | |
2673 @H.element("td"){ | |
2674 ghash['members'].collect{|u| | |
2675 @sc.nickname(u) | |
2676 }.join(", ") | |
2677 } | |
2678 } | |
27 | 2679 }.join("\n") |
0 | 2680 } + \ |
2681 '' + \ | |
2682 @H.p(msg('groupwarn', 'shortnameplz')) + \ | |
2683 @H.submit_reset("GO") | |
2684 } # form | |
2685 end | |
2 | 2686 def groupnamesString() |
2687 @H.elementln("p", {'class'=>'listup'}){ | |
2688 @sc.groups().collect{|g|@sc.groupname(g)}.join(", ") | |
2689 } | |
2690 end | |
0 | 2691 def groupmod() |
2692 if !checkauth | |
2693 return nil | |
2694 end | |
2695 @O.print @H.elementln("h1"){ | |
2696 msg('group', 'management')+" "+msg('done') | |
2697 } | |
2698 user=@params['user'] | |
2699 @O.print @params.inspect if $DEBUG | |
2700 | |
2701 for grp in @sc.groups() | |
2702 # | |
2703 # as a member, participate or retire | |
2704 key = "groupadd-#{grp}" | |
2705 removep = (/no/i =~ @params[key]) | |
2706 memberp = @sc.ismember(user, grp) | |
2707 if @params[key] | |
2708 if (!removep) ^ memberp | |
2709 @sc.addgroup(grp, [user], removep) | |
2710 @O.print @H.elementln("p"){ | |
2711 sprintf "%s [%s] %s %s", msg('user'), user, | |
2712 removep ? msg('removedfromgp') : msg('addedtogroup'), grp | |
2713 } | |
2714 end | |
2715 end | |
2716 # | |
2717 # as a owner, change the name of group | |
2718 if @sc.isadmin(user, grp) && | |
2719 (newname = @params["groupname-#{grp}"]) && | |
2720 @sc.groupname(grp) != newname | |
2 | 2721 @O.printf "@sc.name2group=%s<br>\n", @sc.name2group(newname) |
2722 if dupl=@sc.name2group(newname) | |
2723 @O.print @H.p(sprintf(msg('dupname'), newname)) | |
2724 @O.print groupnamesString() | |
2725 | |
2726 else | |
2727 @sc.setgroupname(grp, newname) | |
2728 @O.print @H.elementln("p"){ | |
2729 sprintf "%s %s%s %s", | |
2730 msg('group'), grp, msg('of', 'name', 'setto'), newname | |
2731 } | |
2732 end | |
0 | 2733 end |
2734 end | |
2735 end | |
2736 def users() | |
2737 unless pm=open_pm() | |
2738 outputError(msg('autherror')) | |
2739 return nil | |
2740 end | |
2741 pm.users | |
2742 end | |
2743 def grepgroup(gname) | |
2744 gr = @sc.groups.grep(gname)[0] | |
2745 end | |
2746 def admgroup(group = nil) | |
2747 # if group==nil, create new | |
2748 if !checkauth | |
2749 return nil | |
2750 end | |
2751 @O.print @H.elementln("h1"){ | |
2752 msg('group', 'management') | |
2753 } | |
2754 user=@params['user'] | |
2755 | |
2756 # Check the existent group's validity | |
2757 if group | |
2758 unless (gr=grepgroup(group)) | |
2759 @O.print @H.p("No such group #{group}") | |
2760 return nil | |
2761 end | |
2762 group = gr | |
2763 unless @sc.isadmin(user, group) | |
2764 @O.print @H.p("You are not administrator of #{group}.") | |
2765 return nil | |
2766 end | |
2767 @O.print @H.elementln("h2"){ | |
2768 msg('group')+" #{group}" + | |
2769 if group != @sc.groupname(group) | |
2770 " (#{@sc.groupname(group)})" | |
2771 end.to_s | |
2772 } | |
2773 actionmethod={'action'=>@myname+"?-admgroupsub", 'method'=>'POST'} | |
2774 else | |
2775 # New group creation | |
2776 @O.print @H.elementln("h2"){ | |
2777 msg('newgroup') | |
2778 } | |
2779 actionmethod={'action'=>@myname+"?-newgroupsub", 'method'=>'POST'} | |
2780 end | |
2781 | |
2782 userlist = ([user] + users()).uniq | |
2783 myselfclass = {'class'=>'admin'} | |
2784 colspan2 = {'colspan'=>'2'} | |
2785 warnclass = {'class'=>'warn'} | |
2786 warnp = nil | |
2787 | |
2788 @O.print @H.elementln("form", actionmethod){ | |
2789 @H.hidden('group', group) + "\n" + \ | |
2790 if group | |
2791 "" | |
2792 else | |
2793 # new group creation | |
2794 grps = @sc.groups() | |
2795 i=1 | |
2796 defname = "group%03d"%i | |
2797 while grps.grep(defname)[0] | |
2798 defname = "group%03d"%(i+=1) | |
2799 end | |
2800 @H.element("pre"){ | |
2801 msg('group', 'of', 'id')+"\n"+@H.text("group", defname) + "\n" + \ | |
2802 msg('group', 'of', 'name', 'anystring')+"\n"+ \ | |
2803 @H.text("gname", '') + "\n" | |
2804 } | |
2805 end + \ | |
2806 @H.elementln("table", {'border'=>'1'}){ | |
2807 @H.elementln("tr"){ | |
2808 @H.element("th"){msg('join')} + \ | |
2809 @H.element("th"){msg('administrator')} + \ | |
2810 @H.element("th"){msg('member')} | |
2811 } + \ | |
2812 userlist.collect{|u| | |
2813 recursememp = nil | |
2814 if group | |
2815 memberp = (@sc.ismember(u, group) && true) | |
2816 adminp = (@sc.isadmin(u, group) && true) | |
2817 if !memberp && @sc.members(group).grep(u)[0] | |
2818 recursememp = true | |
2819 end | |
2820 else | |
2821 memberp = adminp = (u == user) | |
2822 end | |
2823 @H.elementln("tr", (u==user ? myselfclass : nil)){ | |
2824 @H.element("td"){ | |
2825 @H.radio('mem-'+u, 'yes', 'YES / ', memberp) + \ | |
2826 @H.radio('mem-'+u, 'no', 'NO', !memberp) | |
2827 } + \ | |
2828 @H.element("td"){ | |
2829 @H.radio('adm-'+u, 'yes', 'YES / ', adminp) + \ | |
2830 @H.radio('adm-'+u, 'no', 'NO', !adminp) | |
2831 } + \ | |
2832 @H.element("td"){ | |
2833 @sc.nickname(u) + \ | |
2834 if recursememp | |
2835 warnp = true | |
2836 @H.element("span", warnclass){"(*)"} | |
2837 end.to_s | |
2838 } | |
2839 } | |
2840 }.join + \ | |
2841 # group names | |
2842 @H.elementln("tr"){ | |
2843 @H.element("th", colspan2){msg('join')} + \ | |
2844 @H.element("th"){msg('group')} | |
2845 } + \ | |
2846 @sc.groups().collect{|g| | |
2847 next if group == g | |
2848 memberp = @sc.ismember(g, group) | |
2849 @H.element("tr"){ | |
2850 @H.element("td", colspan2){ | |
2851 @H.radio('mem-'+g, 'yes', 'YES / ', memberp) + \ | |
2852 @H.radio('mem-'+g, 'no', 'NO', !memberp) | |
2853 } + \ | |
2854 @H.element("td"){ | |
2855 if @sc.isadmin(user, g) | |
2856 @H.a(@myname+"?-admgroup+#{g}", @sc.groupname(g)) | |
2857 else | |
2858 @sc.groupname(g) | |
2859 end | |
2860 } | |
2861 } | |
2862 }.join | |
2863 } + "<br>\n" + \ | |
2864 @H.submit_reset("GO") | |
2865 } # form | |
2866 @O.print @H.p(@H.element("span", warnclass){"(*)"}+ | |
2867 msg('recursewarn')) if warnp | |
2 | 2868 if group && (members = @sc.members(group))[0] |
0 | 2869 @O.print @H.p(sprintf(msg('wholemembers'), group)) |
2870 @O.print @H.elementln("p", {'class'=>'listup'}){ | |
2 | 2871 members.collect{|u|@sc.nickname(u)}.join(", ")} |
0 | 2872 end |
2873 | |
2874 # | |
2875 # Next section, REMOVE GROUP! | |
2876 return nil unless group | |
2877 @O.print @H.elementln("h2"){ | |
2878 sprintf "%s %s %s", msg('group'), group, msg('deletion') | |
2879 } | |
2880 @O.print @H.p(msg('deletionwarn'))+"\n" | |
2881 @O.print @H.elementln("form", {'action'=>@myname+"?-delgroupsub+#{group}", 'method'=>'POST'}){ | |
2882 @H.hidden("group", group) + "\n" + \ | |
2883 @H.elementln("table"){ | |
2884 @H.elementln("tr"){ | |
2885 @H.elementln("td"){ | |
2886 sprintf msg('delgroup'), group | |
2887 } + \ | |
2888 @H.elementln("td"){ | |
2889 @H.radio("delete", "yes", msg('yes')) + ' ' + \ | |
2890 @H.radio("delete", "no", msg('no'), true) | |
2891 } | |
2892 } + \ | |
2893 @H.elementln("tr"){ | |
2894 @H.elementln("td"){ | |
2895 sprintf msg('really?'), group | |
2896 } + \ | |
2897 @H.elementln("td"){ | |
2898 @H.radio("delete2", "yes", msg('yes')) + ' ' + \ | |
2899 @H.radio("delete2", "no", msg('no'), true) | |
2900 } | |
2901 } | |
2902 } + \ | |
2903 "<br>\n" + @H.submit_reset("GO") | |
2904 } | |
2905 | |
2906 @O.print footer() | |
2907 end | |
2908 def newgroup() | |
2909 admgroup(nil) | |
2910 end | |
2911 | |
2912 def delgroupsub(group) | |
2913 if !checkauth | |
2914 return nil | |
2915 end | |
2916 user = @params['user'] | |
2917 if group != @params['group'] | |
2918 @O.print @H.p("Group mismatch") | |
2919 return nil | |
2920 end | |
2921 unless (gr=grepgroup(group)) | |
2922 @O.print @H.p("No such group #{group}") | |
2923 return nil | |
2924 end | |
2925 group = gr | |
2926 unless @sc.isadmin(user, group) | |
2927 @O.print @H.p("You are not administrator of #{group}.") | |
2928 return nil | |
2929 end | |
2930 unless @params['delete'] && /yes/i =~ @params['delete'] \ | |
2931 && @params['delete2'] && /yes/i =~ @params['delete2'] | |
2932 @O.print @H.p(msg('chicken')) | |
2933 return nil | |
2934 end | |
2935 @O.print @H.elementln("h1"){ | |
2936 msg('group')+" #{group} "+msg('deletion') | |
2937 } | |
2938 @O.print @H.p(@sc.destroygroup(group) ? msg("done") : msg("failure")) | |
2939 | |
2940 @O.print footer() | |
2941 end | |
2942 | |
2943 def deleteuser(user) | |
2944 @sc.deleteuser(user) && | |
2945 begin | |
2946 pm = open_pm | |
2947 pm.delete(user) | |
2948 pm.close() | |
2949 true | |
2950 rescue | |
2951 nil | |
2952 end | |
2953 end | |
2954 def delusersub(user) | |
2955 if !checkauth | |
2956 return nil | |
2957 end | |
2958 user = @params['user'] | |
2959 if user != @params['user'] | |
2960 @O.print @H.p("User mismatch") | |
2961 return nil | |
2962 end | |
2963 unless (us=users().grep(user)[0]) | |
2964 @O.print @H.p("No such user #{user}") | |
2965 return nil | |
2966 end | |
2967 user = us | |
2968 unless @params['delete'] && /yes/i =~ @params['delete'] \ | |
2969 && @params['delete2'] && /yes/i =~ @params['delete2'] | |
2970 @O.print @H.p(msg('chicken')) | |
2971 return nil | |
2972 end | |
2973 @O.print @H.elementln("h1"){ | |
2974 msg('user')+" #{user} "+msg('deletion') | |
2975 } | |
2976 @O.print @H.p(deleteuser(user) ? msg("done") : msg("failure")) | |
2977 | |
7 | 2978 @O.print @H.p(@H.a(@myname, msg('login'))) |
0 | 2979 end |
2980 | |
2981 def admgroupsub() | |
2982 if !checkauth | |
2983 return nil | |
2984 end | |
2985 user = @params['user'] | |
2986 group = @params['group'] | |
2987 unless (gr=grepgroup(group)) | |
2988 @O.print @H.element("pre"){"No such group #{group.inspect}"} | |
2989 return nil | |
2990 end | |
2991 unless @sc.isadmin(user, group) | |
2992 @O.print @H.p("You are not administrator of #{group}.") | |
2993 return nil | |
2994 end | |
2995 gorup = gr | |
2996 @O.print @H.elementln("h1"){ | |
2997 msg('group', 'management', 'done') | |
2998 } | |
2999 @O.print @H.elementln("h2"){ | |
3000 msg('group')+" #{group}" + | |
3001 if group != @sc.groupname(group) | |
3002 " (#{@sc.groupname(group)})" | |
3003 end.to_s | |
3004 } | |
3005 somethingdone = nil | |
3006 for u in users() | |
2 | 3007 u = @sc.isuser(u) # users() value is considered tainted. |
3008 next unless u # Use registered value in @sc. | |
0 | 3009 for var, kind in { |
3010 "mem"=>['members', 'member'], 'adm'=>['admin', 'administrator']} | |
3011 memv = "#{var}-#{u}" | |
3012 if @params[memv] | |
3013 joinp = ((/^yes/i =~ @params[memv]) && true) | |
3014 membp = if var=='mem' | |
3015 @sc.ismember(u, group) | |
3016 else # admin | |
3017 @sc.isadmin(u, group) | |
3018 end && true | |
3019 if var=='adm' && @sc.admins(group).length == 1 && membp && !joinp | |
3020 @O.print @H.p(sprintf(msg('soleadmin'), u, group)) | |
3021 elsif joinp ^ membp | |
3022 somethingdone = true | |
3023 @sc.addgroup(group, [u], !joinp, kind[0]) | |
3024 @O.print @H.elementln("p"){ | |
3025 sprintf "%s [%s](%s) %s %s", msg('user'), u, | |
3026 msg(kind[1]), | |
3027 joinp ? msg('addedtogroup'): msg('removedfromgp'), group | |
3028 } | |
3029 end | |
3030 end | |
3031 end | |
3032 end # users() | |
3033 | |
3034 # add or remove for group in groups | |
3035 for g in @sc.groups() | |
3036 next if g == group | |
3037 memv = "mem-#{g}" | |
3038 if @params[memv] | |
3039 joinp = ((/^yes/i =~ @params[memv]) && true) | |
3040 membp = (@sc.ismember(g, group) && true) | |
3041 if joinp ^ membp | |
3042 somethingdone = true | |
3043 @sc.addgroup(group, [g], !joinp) | |
3044 @O.print @H.elementln("p"){ | |
3045 sprintf "%s [%s] %s %s", msg('group'), g, | |
3046 joinp ? msg('addedtogroup'): msg('removedfromgp'), group | |
3047 } | |
3048 end | |
3049 end | |
3050 end # groups | |
3051 unless somethingdone | |
3052 # @O.print @H.p(msg('nothingtodo')) | |
3053 end | |
3054 @O.print footer() | |
3055 end | |
3056 def newgroupsub() | |
3057 if !checkauth | |
3058 nil | |
3059 end | |
3060 user = @params['user'] | |
3061 newgroup = @params['group'] | |
3062 newgname = @params['gname'] | |
3063 | |
3064 | |
3065 if @sc.groups.grep(newgroup)[0] | |
3066 @O.print @H.p(msg('existent')+newgroup) | |
3067 return nil | |
3068 end | |
2 | 3069 if dupl=@sc.name2group(newgname) |
3070 @O.print @H.p(sprintf(msg('dupname'), newgname)) | |
3071 @O.print groupnamesString() | |
3072 return nil | |
3073 end | |
0 | 3074 @sc.creategroup(newgroup, newgname, [user]) |
3075 admgroup(newgroup) | |
3076 end | |
3077 | |
14 | 3078 # |
3079 # Methods Related to viaMail functions | |
3080 def gen_sessionpswd() | |
3081 | |
3082 end | |
3083 def viamail_registform() | |
3084 c = "# " | |
3085 nl = "\n" | |
3086 user = @params['user'] | |
3087 msg('addsched') + "-" * 20 + nl*2 + \ | |
3088 c + msg('user') + nl + \ | |
3089 "user=" + user + nl*2 + \ | |
3090 c + msg('sessionpswd') + nl + \ | |
3091 "sp=hoge" + nl*2 + \ | |
3092 c + msg('date') + nl + \ | |
3093 "date="+Time.now.strftime("%Y/%m/%d") + nl*2 + \ | |
3094 c + msg('time') + sprintf(msg('24hourtxt'), @opt['alldaydir']) + nl + \ | |
3095 "time=3000"+nl*2 + \ | |
3096 c + msg('publicp') + nl + \ | |
3097 "public=yes" + nl*2 + \ | |
3098 c + msg('neednotify') + nl + \ | |
3099 "nt10m=yes (%s) | |
3100 nttoday=yes (%s) | |
3101 nt1d=yes (%s) | |
3102 nt7d=yes (%s)" % ["10"+msg('minutes')+msg('before'), | |
3103 msg('theday'), msg('precedingday'), | |
3104 "7"+msg('days')+msg('before')] + nl*2 + \ | |
3105 | |
3106 c + msg('schedulehere') | |
3107 end | |
3108 def viamail_footer() | |
3109 viamail_registform() | |
3110 end | |
3111 def show_by_text(date, days) | |
3112 user = @params['user'] | |
3113 personal = true | |
3114 sched = dayTextString(user, date, days, personal) | |
3115 # @O.print outstr | |
3116 | |
3117 sendMail(mailaddress(user), | |
3118 "After5 Schedule", | |
3119 @opt['url'] + "\n" + \ | |
3120 Time.now.strftime("%Y/%m/%d") + \ | |
3121 sprintf(msg('schedlist'), days) + "\n\n" + \ | |
3122 if sched > '' | |
3123 sched | |
3124 else | |
3125 msg('noplan')+"\n" | |
3126 end + \ | |
3127 viamail_footer | |
3128 ) | |
3129 | |
3130 end | |
3131 def parseHeader | |
3132 contline=nil | |
3133 header=Hash.new | |
3134 text=Array.new | |
3135 | |
3136 field=nil | |
3137 # header | |
3138 while line=STDIN.gets | |
3139 text << line | |
3140 break if /^$/ =~ line | |
3141 | |
3142 if /^\s+/ =~ line | |
3143 if field | |
3144 header[field][-1] << line | |
3145 end | |
3146 else | |
3147 if /^([^:]+):\s*(.*)/ =~ line | |
3148 field=$1.downcase | |
3149 header[field] or header[field] = [] | |
3150 header[field] << $2 | |
3151 end | |
3152 end | |
3153 end | |
3154 header | |
3155 end | |
3156 def mail_regsched() | |
3157 @params = Hash.new # Reset | |
3158 | |
3159 reqparams = %w[user sp date time public] | |
3160 otherparams = %w[nt10m nttoday nt1d nt7d] | |
3161 setall = lambda{ | |
3162 reqparams.each{|key| return false unless @params.has_key?(key)} | |
3163 return true | |
3164 } | |
3165 stack = "" | |
3166 while line=gets # !setall.call && line=gets | |
3167 if /^(\S+)=(.*)/ =~ line | |
3168 next unless reqparams.index($1) || otherparams.index($1) | |
3169 @params[$1] = $2 | |
3170 #if reqparams.index($1) | |
3171 STDERR.print "Set #{$1} to #{$2}\n" | |
3172 #end | |
3173 buf = "" | |
3174 elsif /^\s*\#|^$/ =~ line | |
3175 # skip comments | |
3176 else | |
3177 buf += line | |
3178 end | |
3179 end | |
3180 unless setall.call | |
3181 STDERR.print "Insufficient variables\n" | |
3182 exit 1 | |
3183 end | |
3184 p buf | |
3185 | |
3186 y, m, d = date2ymd(@params["date"]) | |
3187 @params["year"] = y | |
3188 @params["month"] = m | |
3189 @params["day"] = d | |
3190 @params["schedule"] = buf | |
3191 @params["editmode"] = "modify" | |
3192 @params["sessionpw"] = @params["sp"] | |
3193 p @params | |
3194 add_remove() | |
3195 end | |
3196 def mail_getsched() | |
3197 user = nil | |
3198 while bline=gets | |
3199 if /(\S+@\S+)/ =~ bline | |
3200 break if user=@sc.isuser($1) | |
3201 end | |
3202 end | |
3203 unless user | |
3204 sendMail(@opt['maintainer'], "viaMail Request Error", | |
3205 "This is `#{@mybase}' in #{@mydir}\n" + | |
3206 "Invalid schedule request from #{ENV['SENDER']}.\n\n") | |
3207 exit 1 | |
3208 end | |
3209 today = Time.now.strftime("%Y/%m/%d") | |
3210 days = 7 | |
3211 if bline=gets | |
3212 if /\d+/ =~ bline | |
3213 days = bline.to_i | |
3214 end | |
3215 end | |
3216 # Send user to schedules of today and near future | |
3217 @params['user'] = user | |
3218 show_by_text(today, days) | |
3219 end | |
3220 def doMail() | |
3221 days = 7 | |
3222 # Confirm `via Mail' | |
3223 prohibitviahttp() | |
3224 @H = TEXTout.new | |
3225 unless ENV['RECIPIENT'] && ENV['SENDER'] | |
3226 STDERR.print "Call me via qmail\n" | |
3227 exit 1 | |
3228 end | |
3229 @mailmode = true | |
3230 header = parseHeader # is this necessary? | |
3231 if /regist/ =~ ENV["EXT"] | |
3232 mail_regsched() | |
3233 else | |
3234 mail_getsched() | |
3235 end | |
3236 end | |
3237 | |
3238 # | |
3239 # Password related Methos | |
0 | 3240 def setpasswd(user) |
3241 prohibitviahttp() | |
3242 pm = open_pm() | |
3243 exit 1 unless pm | |
3244 if pm.userexist?(user) then | |
3245 begin | |
3246 system "stty -echo" | |
3247 STDERR.print "New passwd: " | |
3248 p1 = STDIN.gets | |
3249 STDERR.print "\nAgain: " | |
3250 p2 = STDIN.gets | |
3251 ensure | |
3252 system "stty echo" | |
3253 end | |
3254 if (p1 == p2) then | |
3255 pm.setpasswd(user, p1.chop!) | |
3256 end | |
3257 STDERR.print "New password for #{user} set successfully\n" | |
3258 else | |
3259 STDERR.print "User #{user} not found\n" | |
3260 end | |
3261 pm.close() | |
3262 exit 0 | |
3263 end | |
3264 def adduser(user) | |
3265 prohibitviahttp() | |
3266 pm = open_pm() | |
3267 exit 1 unless pm | |
3268 newpwd = pm.setnewpasswd(user, 4) | |
3269 print "#{user}'s password is #{newpwd}\n" | |
3270 pm.close() | |
3271 exit 0 | |
3272 end | |
3273 def deluser(user) | |
3274 prohibitviahttp() | |
3275 pm = open_pm() | |
3276 exit 1 unless pm | |
3277 pm.delete(user) | |
3278 pm.close() | |
3279 exit 0 | |
3280 end | |
3281 | |
3282 # read configuratoin file | |
3283 def readconf(conf) | |
3284 cf = "after5.cf" #conf # || @opt['conf'] | |
3285 cf = File.join(@mydir, cf) unless test(?s, cf) | |
3286 cf = File.join(ENV["HOME"], cf) unless test(?s, cf) | |
3287 return unless test(?s, cf) | |
3288 begin | |
3289 IO.foreach(cf){|line| | |
26 | 3290 line = line.toeuc |
0 | 3291 next if /^\s *#/ =~ line |
3292 line.chop! | |
3293 line.sub!(/^\s*#.*/, '') | |
3294 next if /^$/ =~ line | |
3295 case line | |
3296 # title, type = line.split(/\t+/) | |
3297 when /^([a-z]+)=(.*)/oi | |
3298 key, value = $1, $2 | |
3299 case value | |
6 | 3300 when /^(no|none|null|nil|false|0|off)$/io |
0 | 3301 @opt[key] = nil |
3302 else | |
3303 @opt[key] = value | |
3304 end | |
3305 print "#{key} set to #{value}\n" if $DEBUG | |
3306 end | |
3307 } | |
3308 rescue | |
26 | 3309 STDERR.printf("Configuration file %s not readable\n", cf) |
0 | 3310 end |
3311 end | |
3312 | |
3313 def parsedate(string) | |
3314 if %r,^(\d\d\d\d+)/(\d+)/(\d+)/(\d+)/([^/]+)$, =~ string | |
3315 sprintf "%04d/%02d/%02d/%04d/%s", $1.to_i, $2.to_i, $3.to_i, $4.to_i, | |
3316 grepgroup($5) | |
3317 elsif %r,^(\d\d\d\d+)/(\d+)/(\d+)/(\d+), =~ string | |
3318 sprintf "%04d/%02d/%02d/%04d", $1.to_i, $2.to_i, $3.to_i, $4.to_i | |
3319 elsif %r,^(\d\d\d\d+)/(\d+)/(\d+), =~ string | |
3320 sprintf "%04d/%02d/%02d", $1.to_i, $2.to_i, $3.to_i | |
3321 elsif %r,^(\d\d\d\d+)/(\d+), =~ string | |
3322 sprintf "%04d/%02d", $1.to_i, $2.to_i | |
3323 elsif %r,^(\d\d\d\d+)/(\d+), =~ string | |
3324 sprintf "%04d", $1.to_i | |
3325 end | |
3326 end | |
3327 | |
3328 def getarg() | |
3329 argument = {} | |
3330 | |
3331 while /^-/ =~ ARGV[0] | |
3332 case ARGV[0] | |
3333 when '-f' | |
3334 conf = ARGV[1] | |
3335 ARGV.shift | |
3336 when "-d" | |
3337 $DEBUG = true | |
3338 when "-install" | |
14 | 3339 when "-stream" |
3340 # ARGV.shift | |
3341 # @job = 'show_by_text "2005/1/18"' | |
3342 @job = 'doMail' | |
0 | 3343 when "-addsched" |
3344 @job = "addsched" | |
3345 when "-today" | |
3346 @job = "today" | |
2 | 3347 when "-today_p" |
3348 argument['displaymode'] = 'personal' | |
3349 @job = "today" | |
3350 when "-today_n" | |
3351 argument['displaymode'] = 'normal' | |
3352 @job = "today" | |
0 | 3353 when "-remove" |
3354 ARGV.shift | |
3355 @job = 'remove "'+parsedate(ARGV[0])+'"' | |
14 | 3356 when "-move" |
3357 ARGV.shift | |
3358 @job = 'move "'+parsedate(ARGV[0])+'"' | |
0 | 3359 when "-modify" |
3360 ARGV.shift | |
3361 @job = 'modify "'+parsedate(ARGV[0])+'"' | |
3362 when "-month" | |
3363 ARGV.shift | |
3364 @job = 'month "'+parsedate(ARGV[0])+'"' | |
3365 when "-show" | |
3366 ARGV.shift | |
3367 # @job = "show '"+ARGV[0]+"'" | |
3368 @job = "show '"+parsedate(ARGV[0])+"'" | |
3369 when "-login" | |
3370 @job = "login" | |
3371 when "-userman" | |
3372 @job = "userman" | |
3373 when "-usermod" | |
3374 @job = "usermod" | |
3375 when "-groupinout" | |
3376 @job = "groupinout" | |
3377 when "-groupsubmit" | |
3378 @job = "groupsubmit" | |
3379 when "-groupman" | |
3380 @job = "groupman" | |
3381 when "-groupmod" | |
3382 @job = "groupmod" | |
3383 when "-notify" | |
3384 @job = 'notify' # + exit | |
3385 when "-newgroup" | |
3386 @job = 'newgroup' | |
3387 when "-admgroup" | |
3388 ARGV.shift | |
3389 gr = safecopy(grepgroup(ARGV[0])) | |
3390 ##gr.untaint | |
3391 @job = 'admgroup "'+gr+'"' | |
3392 when "-admgroupsub" | |
3393 @job = 'admgroupsub' | |
3394 when "-newgroupsub" | |
3395 @job = 'newgroupsub' | |
3396 when "-delusersub" | |
3397 ARGV.shift | |
6 | 3398 usr = safecopy(users().grep(ARGV[0])[0]) |
0 | 3399 @job = 'delusersub "'+usr+'"' |
3400 when "-delgroupsub" | |
3401 ARGV.shift | |
3402 gr = grepgroup(ARGV[0]) | |
3403 @job = 'delgroupsub "'+gr+'"' | |
3404 when /-(setpasswd|deluser|adduser)$/ | |
3405 ARGV.shift | |
3406 @job = $1+ " '#{ARGV[0]}'" # + exit | |
3407 when "" | |
3408 end | |
3409 ARGV.shift | |
3410 end | |
3411 | |
3412 readconf(@conf) | |
3413 | |
3414 query = '' | |
3415 method = ENV["REQUEST_METHOD"] | |
3416 if /POST/i =~ method then | |
3417 length = ENV["CONTENT_LENGTH"].to_i | |
3418 query = STDIN.read(length) | |
3419 elsif /GET/i =~ method then | |
3420 query = ENV["QUERY_STRING"] | |
3421 else # executed from command line | |
3422 query = ARGV.join("&") | |
3423 end | |
3424 | |
3425 for unit in query.split(/\&/) | |
3426 if /^([a-z][-_0-9@%a-z.]*)=(.*)/i =~ unit | |
3427 key, value = $1, $2 | |
3428 #value.gsub!(/%(..)/){[$1.hex].pack("c")} # これでURLデコードが一発 | |
3429 decode!(value) | |
3430 decode!(key) | |
3431 value = Kconv::toeuc(value) # EUCに変換 | |
3432 printf "[%s] = %s\n", key, value if $DEBUG | |
3433 argument[key] = value | |
3434 end | |
3435 end | |
3436 argument | |
3437 end | |
3438 def getcookie() | |
3439 cookie = {} | |
7 | 3440 return cookie unless ENV['HTTP_COOKIE'] |
3441 #if /value=(.*)/ =~ ENV['HTTP_COOKIE'] | |
3442 for cv in ENV['HTTP_COOKIE'].split(/[\; ]+/).grep(/(value|prefs)=(.*)/) | |
0 | 3443 # value=$1.gsub!(/%(..)/){[$1.hex].pack("c")} |
7 | 3444 next unless /\w+=(.*)/ =~ cv |
0 | 3445 value=decode!($1) |
7 | 3446 next unless value |
0 | 3447 for line in value.split("&") |
3448 if /(\w+)=(.*)/ =~ line | |
3449 key, value = $1, $2 | |
3450 #value.gsub!(/%(..)/){[$1.hex].pack("c")} # これでURLデコードが一発 | |
3451 decode!(value) | |
3452 value = Kconv::toeuc(value) # EUCに変換 | |
3453 printf "cookie[%s] = %s\n", key, value if $DEBUG | |
3454 cookie[key] = value | |
3455 end | |
3456 end | |
3457 end | |
3458 cookie | |
3459 end | |
3460 end | |
3461 | |
17 | 3462 $KCODE='e' if RUBY_VERSION < "1.9" |
0 | 3463 After5.new.doit |
3464 | |
3465 if __FILE__ == $0 | |
3466 end | |
3467 | |
3468 | |
3469 # Local variables: | |
3470 # buffer-file-coding-system: euc-jp | |
3471 # End: |