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