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