Mercurial > hgrepos > hgweb.cgi > after5
annotate after5.rb @ 86:26c81703a80c draft
Do not send to $SENDER when viamail mode
author | HIROSE Yuuji <yuuji@gentei.org> |
---|---|
date | Mon, 16 Dec 2013 10:57:45 +0900 |
parents | e2b6a2e8b5c7 |
children | 1f99367752fb |
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 $ |
86
26c81703a80c
Do not send to $SENDER when viamail mode
HIROSE Yuuji <yuuji@gentei.org>
parents:
85
diff
changeset
|
7 # Last modified Mon Dec 16 10:56:24 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 |
86
26c81703a80c
Do not send to $SENDER when viamail mode
HIROSE Yuuji <yuuji@gentei.org>
parents:
85
diff
changeset
|
2977 if user && !viamail # HTTP mode |
26c81703a80c
Do not send to $SENDER when viamail mode
HIROSE Yuuji <yuuji@gentei.org>
parents:
85
diff
changeset
|
2978 rcpts += @sc.mailaddress(user).split(/,\s*|\s+/).flatten # +sender |
26c81703a80c
Do not send to $SENDER when viamail mode
HIROSE Yuuji <yuuji@gentei.org>
parents:
85
diff
changeset
|
2979 end |
84
f67f5304baac
Add feature of sending message to a user
HIROSE Yuuji <yuuji@gentei.org>
parents:
83
diff
changeset
|
2980 end |
85 | 2981 # ENV["QMAILINJECT"] = "r" # for ML mode, use verp |
2982 # 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
|
2983 # 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
|
2984 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
|
2985 s = ENV['SENDER'] |
bdb7e40c2d4f
`limitsender' option to prohibit anonymous user to send to ML
HIROSE Yuuji <yuuji@gentei.org>
parents:
68
diff
changeset
|
2986 if !catch(:senderok) { |
bdb7e40c2d4f
`limitsender' option to prohibit anonymous user to send to ML
HIROSE Yuuji <yuuji@gentei.org>
parents:
68
diff
changeset
|
2987 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
|
2988 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
|
2989 } |
bdb7e40c2d4f
`limitsender' option to prohibit anonymous user to send to ML
HIROSE Yuuji <yuuji@gentei.org>
parents:
68
diff
changeset
|
2990 # 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
|
2991 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
|
2992 ("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
|
2993 "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
|
2994 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
|
2995 exit 0 |
bdb7e40c2d4f
`limitsender' option to prohibit anonymous user to send to ML
HIROSE Yuuji <yuuji@gentei.org>
parents:
68
diff
changeset
|
2996 end |
bdb7e40c2d4f
`limitsender' option to prohibit anonymous user to send to ML
HIROSE Yuuji <yuuji@gentei.org>
parents:
68
diff
changeset
|
2997 end |
70
2e293d4d8db4
Not using proc.call for the sake of displaying document title.
HIROSE Yuuji <yuuji@gentei.org>
parents:
69
diff
changeset
|
2998 # |
2e293d4d8db4
Not using proc.call for the sake of displaying document title.
HIROSE Yuuji <yuuji@gentei.org>
parents:
69
diff
changeset
|
2999 # OK to send, go ahead |
37
1515ea889ea1
First implementation of ML feature.
HIROSE Yuuji <yuuji@gentei.org>
parents:
36
diff
changeset
|
3000 sendMail(to, subj, body, from, rcpts, |
38
39da23b2edb9
Prepend bracket tag to subject.
HIROSE Yuuji <yuuji@gentei.org>
parents:
37
diff
changeset
|
3001 header, |
45
1b16890d61d6
ML: digited subject, ML-specific email addresses, spooling
HIROSE Yuuji <yuuji@gentei.org>
parents:
44
diff
changeset
|
3002 ENV['SENDER'], |
84
f67f5304baac
Add feature of sending message to a user
HIROSE Yuuji <yuuji@gentei.org>
parents:
83
diff
changeset
|
3003 spooling ? mldir : nil) |
37
1515ea889ea1
First implementation of ML feature.
HIROSE Yuuji <yuuji@gentei.org>
parents:
36
diff
changeset
|
3004 if !viamail then |
1515ea889ea1
First implementation of ML feature.
HIROSE Yuuji <yuuji@gentei.org>
parents:
36
diff
changeset
|
3005 @O.print @H.elementln("h1"){msg('sendall_done')} |
38
39da23b2edb9
Prepend bracket tag to subject.
HIROSE Yuuji <yuuji@gentei.org>
parents:
37
diff
changeset
|
3006 @O.print @H.p(sprintf(msg('sendall_head'), |
39da23b2edb9
Prepend bracket tag to subject.
HIROSE Yuuji <yuuji@gentei.org>
parents:
37
diff
changeset
|
3007 nickname(name))+" "+msg('done')) |
85 | 3008 @O.print @H.elementln("pre"){extract_report[1]} |
37
1515ea889ea1
First implementation of ML feature.
HIROSE Yuuji <yuuji@gentei.org>
parents:
36
diff
changeset
|
3009 link2home() |
1515ea889ea1
First implementation of ML feature.
HIROSE Yuuji <yuuji@gentei.org>
parents:
36
diff
changeset
|
3010 @O.print footer() |
1515ea889ea1
First implementation of ML feature.
HIROSE Yuuji <yuuji@gentei.org>
parents:
36
diff
changeset
|
3011 return true |
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 exit 0 |
1515ea889ea1
First implementation of ML feature.
HIROSE Yuuji <yuuji@gentei.org>
parents:
36
diff
changeset
|
3014 end |
1515ea889ea1
First implementation of ML feature.
HIROSE Yuuji <yuuji@gentei.org>
parents:
36
diff
changeset
|
3015 def listdraft(name) |
1515ea889ea1
First implementation of ML feature.
HIROSE Yuuji <yuuji@gentei.org>
parents:
36
diff
changeset
|
3016 return nil unless checkauth |
1515ea889ea1
First implementation of ML feature.
HIROSE Yuuji <yuuji@gentei.org>
parents:
36
diff
changeset
|
3017 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
|
3018 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
|
3019 @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
|
3020 return true |
07ef43ac4f15
Some ruby-1.9 workarounds and enhancement to logging and messaging.
HIROSE Yuuji <yuuji@gentei.org>
parents:
41
diff
changeset
|
3021 end |
07ef43ac4f15
Some ruby-1.9 workarounds and enhancement to logging and messaging.
HIROSE Yuuji <yuuji@gentei.org>
parents:
41
diff
changeset
|
3022 |
37
1515ea889ea1
First implementation of ML feature.
HIROSE Yuuji <yuuji@gentei.org>
parents:
36
diff
changeset
|
3023 user=@params['user'] |
1515ea889ea1
First implementation of ML feature.
HIROSE Yuuji <yuuji@gentei.org>
parents:
36
diff
changeset
|
3024 nickname = @sc.nickname(user) |
84
f67f5304baac
Add feature of sending message to a user
HIROSE Yuuji <yuuji@gentei.org>
parents:
83
diff
changeset
|
3025 groupmode = @sc.isgroup(name) |
37
1515ea889ea1
First implementation of ML feature.
HIROSE Yuuji <yuuji@gentei.org>
parents:
36
diff
changeset
|
3026 @O.print @H.elementln("h1") { |
1515ea889ea1
First implementation of ML feature.
HIROSE Yuuji <yuuji@gentei.org>
parents:
36
diff
changeset
|
3027 @mybase+' '+msg('sendall').sub("<br>", " ") |
1515ea889ea1
First implementation of ML feature.
HIROSE Yuuji <yuuji@gentei.org>
parents:
36
diff
changeset
|
3028 } |
1515ea889ea1
First implementation of ML feature.
HIROSE Yuuji <yuuji@gentei.org>
parents:
36
diff
changeset
|
3029 @O.print @H.elementln("h2") { |
1515ea889ea1
First implementation of ML feature.
HIROSE Yuuji <yuuji@gentei.org>
parents:
36
diff
changeset
|
3030 sprintf(msg('sendall_head'), nickname(name)) |
1515ea889ea1
First implementation of ML feature.
HIROSE Yuuji <yuuji@gentei.org>
parents:
36
diff
changeset
|
3031 } |
85 | 3032 if groupmode # (#includeself) |
3033 list = @sc.members(name) # +user | |
3034 else | |
3035 list = [name, user] | |
3036 end | |
3037 @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
|
3038 list.collect {|u| |
f67f5304baac
Add feature of sending message to a user
HIROSE Yuuji <yuuji@gentei.org>
parents:
83
diff
changeset
|
3039 @H.element("abbr", "title"=>u){ |
f67f5304baac
Add feature of sending message to a user
HIROSE Yuuji <yuuji@gentei.org>
parents:
83
diff
changeset
|
3040 @sc.nickname(u) |
f67f5304baac
Add feature of sending message to a user
HIROSE Yuuji <yuuji@gentei.org>
parents:
83
diff
changeset
|
3041 } |
f67f5304baac
Add feature of sending message to a user
HIROSE Yuuji <yuuji@gentei.org>
parents:
83
diff
changeset
|
3042 }.join(",\n"))) |
f67f5304baac
Add feature of sending message to a user
HIROSE Yuuji <yuuji@gentei.org>
parents:
83
diff
changeset
|
3043 @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
|
3044 @O.print \ |
85 | 3045 @H.elementln("form", { |
3046 'action' => @myname+'?-list', 'method'=>"POST", | |
3047 'enctype' => "multipart/form-data"}) { | |
37
1515ea889ea1
First implementation of ML feature.
HIROSE Yuuji <yuuji@gentei.org>
parents:
36
diff
changeset
|
3048 @H.elementln("table"){ |
1515ea889ea1
First implementation of ML feature.
HIROSE Yuuji <yuuji@gentei.org>
parents:
36
diff
changeset
|
3049 @H.elementln("tr"){ |
85 | 3050 @H.element("td"){"To"} + \ |
3051 @H.element("td"){ | |
3052 @H.element("code"){ | |
3053 groupmode ? defaultmladdress(quoted(name)) : @sc.nickname(name) | |
3054 } | |
3055 } | |
3056 } + \ | |
3057 @H.elementln("tr"){ | |
37
1515ea889ea1
First implementation of ML feature.
HIROSE Yuuji <yuuji@gentei.org>
parents:
36
diff
changeset
|
3058 @H.element("td"){"Subject"} + \ |
1515ea889ea1
First implementation of ML feature.
HIROSE Yuuji <yuuji@gentei.org>
parents:
36
diff
changeset
|
3059 @H.element("td"){ |
1515ea889ea1
First implementation of ML feature.
HIROSE Yuuji <yuuji@gentei.org>
parents:
36
diff
changeset
|
3060 @H.text("subject", "", 40, 128) |
1515ea889ea1
First implementation of ML feature.
HIROSE Yuuji <yuuji@gentei.org>
parents:
36
diff
changeset
|
3061 } |
1515ea889ea1
First implementation of ML feature.
HIROSE Yuuji <yuuji@gentei.org>
parents:
36
diff
changeset
|
3062 } + \ |
1515ea889ea1
First implementation of ML feature.
HIROSE Yuuji <yuuji@gentei.org>
parents:
36
diff
changeset
|
3063 @H.elementln("tr"){ |
85 | 3064 @H.element("td"){"Attachment"} + \ |
3065 @H.element("td"){ | |
3066 @H.element("input", "name"=>"attachment", "type"=>"file", 'multiple'=>true){} | |
3067 } | |
3068 } + \ | |
3069 @H.elementln("tr"){ | |
37
1515ea889ea1
First implementation of ML feature.
HIROSE Yuuji <yuuji@gentei.org>
parents:
36
diff
changeset
|
3070 @H.element("td"){ |
1515ea889ea1
First implementation of ML feature.
HIROSE Yuuji <yuuji@gentei.org>
parents:
36
diff
changeset
|
3071 msg('body') |
1515ea889ea1
First implementation of ML feature.
HIROSE Yuuji <yuuji@gentei.org>
parents:
36
diff
changeset
|
3072 } + \ |
1515ea889ea1
First implementation of ML feature.
HIROSE Yuuji <yuuji@gentei.org>
parents:
36
diff
changeset
|
3073 @H.element("td"){ |
1515ea889ea1
First implementation of ML feature.
HIROSE Yuuji <yuuji@gentei.org>
parents:
36
diff
changeset
|
3074 @H.element("textarea", @schedulearea.merge({"name"=>"body"})){} |
1515ea889ea1
First implementation of ML feature.
HIROSE Yuuji <yuuji@gentei.org>
parents:
36
diff
changeset
|
3075 } |
1515ea889ea1
First implementation of ML feature.
HIROSE Yuuji <yuuji@gentei.org>
parents:
36
diff
changeset
|
3076 } |
1515ea889ea1
First implementation of ML feature.
HIROSE Yuuji <yuuji@gentei.org>
parents:
36
diff
changeset
|
3077 } + # </table> |
1515ea889ea1
First implementation of ML feature.
HIROSE Yuuji <yuuji@gentei.org>
parents:
36
diff
changeset
|
3078 @H.hidden("name", name) + |
1515ea889ea1
First implementation of ML feature.
HIROSE Yuuji <yuuji@gentei.org>
parents:
36
diff
changeset
|
3079 @H.submit("send", "SEND") + |
1515ea889ea1
First implementation of ML feature.
HIROSE Yuuji <yuuji@gentei.org>
parents:
36
diff
changeset
|
3080 @H.reset("clear", "Clear") |
1515ea889ea1
First implementation of ML feature.
HIROSE Yuuji <yuuji@gentei.org>
parents:
36
diff
changeset
|
3081 } |
1515ea889ea1
First implementation of ML feature.
HIROSE Yuuji <yuuji@gentei.org>
parents:
36
diff
changeset
|
3082 @O.print @H.p(msg('sendall_note')) |
1515ea889ea1
First implementation of ML feature.
HIROSE Yuuji <yuuji@gentei.org>
parents:
36
diff
changeset
|
3083 end |
0 | 3084 |
36
e67737e49a5d
add a5userman.html multiplenotify.html
HIROSE Yuuji <yuuji@gentei.org>
parents:
35
diff
changeset
|
3085 # put Link to home |
e67737e49a5d
add a5userman.html multiplenotify.html
HIROSE Yuuji <yuuji@gentei.org>
parents:
35
diff
changeset
|
3086 def link2home() |
e67737e49a5d
add a5userman.html multiplenotify.html
HIROSE Yuuji <yuuji@gentei.org>
parents:
35
diff
changeset
|
3087 @O.print @H.p("-> " + @H.a(@myname+"?-today", "Home")) |
e67737e49a5d
add a5userman.html multiplenotify.html
HIROSE Yuuji <yuuji@gentei.org>
parents:
35
diff
changeset
|
3088 end |
e67737e49a5d
add a5userman.html multiplenotify.html
HIROSE Yuuji <yuuji@gentei.org>
parents:
35
diff
changeset
|
3089 |
0 | 3090 # |
3091 # user management | |
3092 def userman() | |
3093 if !checkauth | |
3094 return nil | |
3095 end | |
3096 user=@params['user'] | |
3097 nickname = @sc.nickname(user) | |
3098 tdclass = {} | |
3099 tdclass["width"] = "80px" if @oldagent # workaround for NN4 | |
3100 | |
3101 @O.print @H.elementln("h1"){ | |
3102 @mybase+' '+msg('user', 'management') | |
3103 } | |
3104 @O.print @H.p(@sc.mkusermap.inspect) if $DEBUG | |
3105 @O.print @H.p(msg('usermodwarn')) | |
3106 @O.print \ | |
3107 @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
|
3108 @H.elementln("table", {"class" => "border"}){ |
0 | 3109 @H.elementln("tr"){ |
3110 @H.element("td", tdclass) {msg('regaddress')} + \ | |
3111 @H.element("td") { | |
3112 @H.element("code"){user} | |
3113 } | |
3114 } + \ | |
3115 @H.elementln("tr"){ | |
50
0b104c49457a
Multiple email addresses can be acceptable
HIROSE Yuuji <yuuji@gentei.org>
parents:
48
diff
changeset
|
3116 @H.element("td", tdclass) {msg('mailaddress', 'multipleok')} + \ |
0 | 3117 @H.element("td") { |
55
9a82edb295ca
Adjust umask. Max width of email entry, enlarged.
HIROSE Yuuji <yuuji@gentei.org>
parents:
50
diff
changeset
|
3118 @H.text("newmail", mailaddress(user), @opt['size'], 180) |
0 | 3119 } |
3120 } + \ | |
3121 @H.elementln("tr"){ | |
3122 @H.element("td", tdclass) {msg('weburl')} + \ | |
3123 @H.element("td") { | |
3124 @H.text("webpage", webpage(user), @opt['size'], 80) | |
3125 } | |
3126 } + \ | |
3127 @H.elementln("tr"){ | |
3128 @H.element("td") {msg('nickname')} + \ | |
3129 @H.element("td") { | |
3130 @H.text("nickname", nickname, @opt['size'], 10) | |
3131 } | |
3132 } | |
3133 } + \ | |
50
0b104c49457a
Multiple email addresses can be acceptable
HIROSE Yuuji <yuuji@gentei.org>
parents:
48
diff
changeset
|
3134 @H.elementln("p"){msg('shortnameplz')} + \ |
0 | 3135 '<br>' + \ |
3136 @H.submit_reset("GO") | |
3137 } # form | |
3138 | |
3139 # | |
3140 # Next section, REMOVE USER! | |
3141 @O.print @H.elementln("h2"){ | |
3142 sprintf "%s %s %s", msg('user'), user, msg('deletion') | |
3143 } | |
3144 @O.print @H.p(msg('deletionwarn'))+"\n" | |
3145 @O.print @H.elementln("form", {'action'=>@myname+"?-delusersub+#{user}", 'method'=>'POST'}){ | |
3146 @H.hidden("user", user) + "\n" + \ | |
3147 @H.elementln("table"){ | |
3148 @H.elementln("tr"){ | |
3149 @H.elementln("td"){ | |
3150 sprintf msg('deluser'), user | |
3151 } + \ | |
3152 @H.elementln("td"){ | |
3153 @H.radio("delete", "yes", msg('yes')) + ' ' + \ | |
3154 @H.radio("delete", "no", msg('no'), true) | |
3155 } | |
3156 } + \ | |
3157 @H.elementln("tr"){ | |
3158 @H.elementln("td"){ | |
3159 sprintf msg('really?'), user | |
3160 } + \ | |
3161 @H.elementln("td"){ | |
3162 @H.radio("delete2", "yes", msg('yes')) + ' ' + \ | |
3163 @H.radio("delete2", "no", msg('no'), true) | |
3164 } | |
3165 } | |
3166 } + \ | |
3167 "<br>\n" + @H.submit_reset("GO") | |
3168 } | |
3169 | |
3170 | |
3171 end | |
3172 def usermod() | |
3173 if !checkauth | |
3174 return nil | |
3175 end | |
3176 @O.print @H.elementln("h1"){ | |
3177 msg('user', 'management')+" "+msg('done') | |
3178 } | |
3179 user=@params['user'] | |
3180 email = mailaddress(user) | |
3181 newmail = @params['newmail'] | |
3182 nickname = @sc.nickname(user) | |
3183 newnn = @params['nickname'].to_s.strip | |
3184 webpage = webpage(user) | |
3185 newweb = @params['webpage'] | |
3186 if email != newmail | |
3187 # change user's address | |
3188 if newmail == user | |
3189 newvalue = nil | |
3190 elsif checkmail(newmail) | |
3191 newvalue = newmail | |
3192 else | |
3193 @O.print @H.elementln("pre"){"Invalid mail address"} | |
3194 end | |
3195 @O.print @H.elementln("pre"){ | |
3196 if @sc.putuserattr(user, 'email', newvalue) | |
3197 sprintf "new mail address=\"%s\"", mailaddress(user) | |
3198 else | |
3199 sprintf "Setting new mail address to \"%s\" failed", newvalue | |
3200 end | |
3201 } | |
3202 end | |
3203 if nickname != newnn | |
3204 if @sc.setnickname(user, newnn) | |
3205 @O.print @H.p(msg('success')) | |
3206 @O.print @H.elementln("pre"){ | |
3207 sprintf "user=\"%s\"\nnickname=\"%s\"", user, @sc.nickname(user) | |
3208 } | |
3209 @O.print @H.p(msg('nicknamenote')) if newnn == '' | |
3210 else | |
3211 @O.print @H.p(msg('failure')) | |
3212 end | |
3213 end | |
3214 if newweb > '' && webpage != newweb | |
3215 if @sc.putuserattr(user, "webpage", newweb) | |
3216 @O.print @H.p(msg('success')) | |
3217 @O.print @H.elementln("pre"){ | |
3218 sprintf "user=\"%s\"\nwebpage=\"%s\"", user, webpage(user) | |
3219 } | |
3220 else | |
3221 @O.print @H.p("Update webpage"+msg('failure')) | |
3222 end | |
3223 end | |
36
e67737e49a5d
add a5userman.html multiplenotify.html
HIROSE Yuuji <yuuji@gentei.org>
parents:
35
diff
changeset
|
3224 link2home |
0 | 3225 end |
3226 # | |
3227 # Display form of group management | |
48
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3228 def groupman(grp = nil) |
0 | 3229 if !checkauth |
3230 return nil | |
3231 end | |
3232 user=@params['user'] | |
3233 nickname = @sc.nickname(user) | |
3234 tdclass = {} | |
3235 tdclass["width"] = "80px" if @oldagent # workaround for NN4 | |
3236 admclass = {'class'=>'admin'} | |
3237 grmap = @sc.groupmap | |
3238 | |
3239 @O.print @H.elementln("h1"){ | |
3240 @mybase+' '+msg('group', 'management') | |
3241 } | |
3242 $KCODE='e' if $DEBUG | |
48
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3243 if grp && group = grepgroup(grp) |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3244 @O.print @H.elementln("h2"){ |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3245 sprintf(msg('aboutgroup'), group) |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3246 } |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3247 grmap = {group => grmap[group]} |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3248 end |
0 | 3249 @O.print grmap.inspect if $DEBUG |
3250 @O.print @H.p(msg('joinmyself')+ | |
3251 @H.a(@myname+"?-newgroup", msg('newgroup'))) | |
3252 @O.print @H.p(msg('usermodwarn')) | |
3253 @O.print \ | |
3254 @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
|
3255 @H.elementln("table", {'class'=>'border'}){ |
47 | 3256 grmap.sort.collect{|g, ghash| |
45
1b16890d61d6
ML: digited subject, ML-specific email addresses, spooling
HIROSE Yuuji <yuuji@gentei.org>
parents:
44
diff
changeset
|
3257 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
|
3258 adminp = @sc.isadmin(user, g) |
0 | 3259 @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
|
3260 @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
|
3261 g + "<br>("+@sc.members(g).length.to_s+")" |
0 | 3262 } + \ |
3263 @H.element("td"){ | |
3264 @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
|
3265 if adminp |
0 | 3266 @H.a(@myname+"?-admgroup+#{g}", msg('adminop')) |
3267 else | |
3268 '--' | |
3269 end | |
3270 } | |
3271 } + \ | |
3272 @H.element("td"){ | |
3273 if ghash['admin'].grep(user)[0] | |
67
a421c2fefc32
Fix the argument for FileUtils.mkdir_p()
HIROSE Yuuji <yuuji@gentei.org>
parents:
66
diff
changeset
|
3274 @H.text("groupname-#{g}", ghash['name'], nil, 12) |
0 | 3275 else |
3276 ghash['name'] | |
3277 end + '<br>' + \ | |
66 | 3278 # 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
|
3279 # 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
|
3280 if memberp && adminp || !@sc.getgroupattr(g, 'inviteonly') |
66 | 3281 @H.radio("groupadd-#{g}", "yes", "IN", memberp) + " / " + \ |
3282 @H.radio("groupadd-#{g}", "no", "OUT", !memberp) | |
3283 else | |
3284 @H.element("small"){"("+msg('inviteonly')+")"} | |
3285 end | |
0 | 3286 } + \ |
3287 @H.element("td"){ | |
47 | 3288 @H.element("div", {'class'=>'memlist5'}){ |
3289 memlist = ghash['members'] | |
3290 if memberp # move this user to the beginning of list | |
3291 memlist.delete(user) | |
3292 memlist.unshift(user) | |
3293 end | |
3294 memlist.collect{|u| | |
84
f67f5304baac
Add feature of sending message to a user
HIROSE Yuuji <yuuji@gentei.org>
parents:
83
diff
changeset
|
3295 if u == user |
f67f5304baac
Add feature of sending message to a user
HIROSE Yuuji <yuuji@gentei.org>
parents:
83
diff
changeset
|
3296 @sc.nickname(u) + \ |
f67f5304baac
Add feature of sending message to a user
HIROSE Yuuji <yuuji@gentei.org>
parents:
83
diff
changeset
|
3297 "("+@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
|
3298 else |
f67f5304baac
Add feature of sending message to a user
HIROSE Yuuji <yuuji@gentei.org>
parents:
83
diff
changeset
|
3299 @H.a(@myname+"?-listdraft+#{u}", |
f67f5304baac
Add feature of sending message to a user
HIROSE Yuuji <yuuji@gentei.org>
parents:
83
diff
changeset
|
3300 @H.element("abbr", "title"=>u) { |
f67f5304baac
Add feature of sending message to a user
HIROSE Yuuji <yuuji@gentei.org>
parents:
83
diff
changeset
|
3301 @sc.nickname(u) |
f67f5304baac
Add feature of sending message to a user
HIROSE Yuuji <yuuji@gentei.org>
parents:
83
diff
changeset
|
3302 }) |
f67f5304baac
Add feature of sending message to a user
HIROSE Yuuji <yuuji@gentei.org>
parents:
83
diff
changeset
|
3303 end |
47 | 3304 }.join(", ") |
3305 } | |
3306 } + \ | |
37
1515ea889ea1
First implementation of ML feature.
HIROSE Yuuji <yuuji@gentei.org>
parents:
36
diff
changeset
|
3307 @H.element("td"){ |
1515ea889ea1
First implementation of ML feature.
HIROSE Yuuji <yuuji@gentei.org>
parents:
36
diff
changeset
|
3308 @H.a(@myname+"?-listdraft+#{g}", msg('sendall')) |
1515ea889ea1
First implementation of ML feature.
HIROSE Yuuji <yuuji@gentei.org>
parents:
36
diff
changeset
|
3309 } |
0 | 3310 } |
27 | 3311 }.join("\n") |
0 | 3312 } + \ |
3313 '' + \ | |
84
f67f5304baac
Add feature of sending message to a user
HIROSE Yuuji <yuuji@gentei.org>
parents:
83
diff
changeset
|
3314 @H.p(msg('address2send')) + \ |
0 | 3315 @H.p(msg('groupwarn', 'shortnameplz')) + \ |
3316 @H.submit_reset("GO") | |
3317 } # form | |
3318 end | |
2 | 3319 def groupnamesString() |
3320 @H.elementln("p", {'class'=>'listup'}){ | |
3321 @sc.groups().collect{|g|@sc.groupname(g)}.join(", ") | |
3322 } | |
3323 end | |
0 | 3324 def groupmod() |
3325 if !checkauth | |
3326 return nil | |
3327 end | |
3328 @O.print @H.elementln("h1"){ | |
3329 msg('group', 'management')+" "+msg('done') | |
3330 } | |
3331 user=@params['user'] | |
3332 @O.print @params.inspect if $DEBUG | |
3333 | |
3334 for grp in @sc.groups() | |
3335 # | |
62
2d33f85c3d9f
Introduce invitation-only mode for groups.
HIROSE Yuuji <yuuji@gentei.org>
parents:
61
diff
changeset
|
3336 # As a member, participate or retire |
2d33f85c3d9f
Introduce invitation-only mode for groups.
HIROSE Yuuji <yuuji@gentei.org>
parents:
61
diff
changeset
|
3337 |
0 | 3338 key = "groupadd-#{grp}" |
62
2d33f85c3d9f
Introduce invitation-only mode for groups.
HIROSE Yuuji <yuuji@gentei.org>
parents:
61
diff
changeset
|
3339 memberp = @sc.ismember(user, grp) |
0 | 3340 removep = (/no/i =~ @params[key]) |
3341 if @params[key] | |
62
2d33f85c3d9f
Introduce invitation-only mode for groups.
HIROSE Yuuji <yuuji@gentei.org>
parents:
61
diff
changeset
|
3342 # |
2d33f85c3d9f
Introduce invitation-only mode for groups.
HIROSE Yuuji <yuuji@gentei.org>
parents:
61
diff
changeset
|
3343 # Check the group is invitation-only mode. |
2d33f85c3d9f
Introduce invitation-only mode for groups.
HIROSE Yuuji <yuuji@gentei.org>
parents:
61
diff
changeset
|
3344 if !removep && !memberp && !@sc.isadmin(user, grp) |
2d33f85c3d9f
Introduce invitation-only mode for groups.
HIROSE Yuuji <yuuji@gentei.org>
parents:
61
diff
changeset
|
3345 @O.print @H.elementln("p") { |
2d33f85c3d9f
Introduce invitation-only mode for groups.
HIROSE Yuuji <yuuji@gentei.org>
parents:
61
diff
changeset
|
3346 sprintf(msg('invite-error'), grp) + "<br>\n" + \ |
2d33f85c3d9f
Introduce invitation-only mode for groups.
HIROSE Yuuji <yuuji@gentei.org>
parents:
61
diff
changeset
|
3347 @sc.admins(grp).join(", ") |
2d33f85c3d9f
Introduce invitation-only mode for groups.
HIROSE Yuuji <yuuji@gentei.org>
parents:
61
diff
changeset
|
3348 } |
2d33f85c3d9f
Introduce invitation-only mode for groups.
HIROSE Yuuji <yuuji@gentei.org>
parents:
61
diff
changeset
|
3349 sendMail(defaultmladdress(grp).sub("@", @mailadmsuffix+"@"), |
2d33f85c3d9f
Introduce invitation-only mode for groups.
HIROSE Yuuji <yuuji@gentei.org>
parents:
61
diff
changeset
|
3350 "Group paticipation attempt to #{grp}", |
2d33f85c3d9f
Introduce invitation-only mode for groups.
HIROSE Yuuji <yuuji@gentei.org>
parents:
61
diff
changeset
|
3351 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
|
3352 [user, grp, ENV['REMOTE_ADDR']]), |
2d33f85c3d9f
Introduce invitation-only mode for groups.
HIROSE Yuuji <yuuji@gentei.org>
parents:
61
diff
changeset
|
3353 nil, |
2d33f85c3d9f
Introduce invitation-only mode for groups.
HIROSE Yuuji <yuuji@gentei.org>
parents:
61
diff
changeset
|
3354 @sc.admins(grp)) |
2d33f85c3d9f
Introduce invitation-only mode for groups.
HIROSE Yuuji <yuuji@gentei.org>
parents:
61
diff
changeset
|
3355 next |
2d33f85c3d9f
Introduce invitation-only mode for groups.
HIROSE Yuuji <yuuji@gentei.org>
parents:
61
diff
changeset
|
3356 end |
2d33f85c3d9f
Introduce invitation-only mode for groups.
HIROSE Yuuji <yuuji@gentei.org>
parents:
61
diff
changeset
|
3357 # |
2d33f85c3d9f
Introduce invitation-only mode for groups.
HIROSE Yuuji <yuuji@gentei.org>
parents:
61
diff
changeset
|
3358 # OK to join/retire |
0 | 3359 if (!removep) ^ memberp |
3360 @sc.addgroup(grp, [user], removep) | |
3361 @O.print @H.elementln("p"){ | |
3362 sprintf "%s [%s] %s %s", msg('user'), user, | |
3363 removep ? msg('removedfromgp') : msg('addedtogroup'), grp | |
3364 } | |
3365 end | |
3366 end | |
3367 # | |
62
2d33f85c3d9f
Introduce invitation-only mode for groups.
HIROSE Yuuji <yuuji@gentei.org>
parents:
61
diff
changeset
|
3368 # 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
|
3369 key = "mail4-#{grp}" |
1b16890d61d6
ML: digited subject, ML-specific email addresses, spooling
HIROSE Yuuji <yuuji@gentei.org>
parents:
44
diff
changeset
|
3370 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
|
3371 @sc.addgroup(grp, [[user, @params[key]]]) |
1b16890d61d6
ML: digited subject, ML-specific email addresses, spooling
HIROSE Yuuji <yuuji@gentei.org>
parents:
44
diff
changeset
|
3372 newmemp = @sc.ismember(user, grp) |
1b16890d61d6
ML: digited subject, ML-specific email addresses, spooling
HIROSE Yuuji <yuuji@gentei.org>
parents:
44
diff
changeset
|
3373 @O.print @H.elementln("p") { |
1b16890d61d6
ML: digited subject, ML-specific email addresses, spooling
HIROSE Yuuji <yuuji@gentei.org>
parents:
44
diff
changeset
|
3374 sprintf("%s `%s' %s => %s%s", |
1b16890d61d6
ML: digited subject, ML-specific email addresses, spooling
HIROSE Yuuji <yuuji@gentei.org>
parents:
44
diff
changeset
|
3375 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
|
3376 @params[key]==mailaddress(user) ? "(same)" : "") |
1b16890d61d6
ML: digited subject, ML-specific email addresses, spooling
HIROSE Yuuji <yuuji@gentei.org>
parents:
44
diff
changeset
|
3377 } |
1b16890d61d6
ML: digited subject, ML-specific email addresses, spooling
HIROSE Yuuji <yuuji@gentei.org>
parents:
44
diff
changeset
|
3378 end |
1b16890d61d6
ML: digited subject, ML-specific email addresses, spooling
HIROSE Yuuji <yuuji@gentei.org>
parents:
44
diff
changeset
|
3379 # |
62
2d33f85c3d9f
Introduce invitation-only mode for groups.
HIROSE Yuuji <yuuji@gentei.org>
parents:
61
diff
changeset
|
3380 # as an owner, change the name of group |
0 | 3381 if @sc.isadmin(user, grp) && |
3382 (newname = @params["groupname-#{grp}"]) && | |
3383 @sc.groupname(grp) != newname | |
2 | 3384 @O.printf "@sc.name2group=%s<br>\n", @sc.name2group(newname) |
3385 if dupl=@sc.name2group(newname) | |
3386 @O.print @H.p(sprintf(msg('dupname'), newname)) | |
3387 @O.print groupnamesString() | |
3388 | |
3389 else | |
3390 @sc.setgroupname(grp, newname) | |
3391 @O.print @H.elementln("p"){ | |
3392 sprintf "%s %s%s %s", | |
3393 msg('group'), grp, msg('of', 'name', 'setto'), newname | |
3394 } | |
3395 end | |
0 | 3396 end |
3397 end | |
36
e67737e49a5d
add a5userman.html multiplenotify.html
HIROSE Yuuji <yuuji@gentei.org>
parents:
35
diff
changeset
|
3398 link2home |
0 | 3399 end |
3400 def users() | |
3401 unless pm=open_pm() | |
3402 outputError(msg('autherror')) | |
3403 return nil | |
3404 end | |
3405 pm.users | |
3406 end | |
3407 def grepgroup(gname) | |
3408 gr = @sc.groups.grep(gname)[0] | |
3409 end | |
3410 def admgroup(group = nil) | |
3411 # if group==nil, create new | |
3412 if !checkauth | |
3413 return nil | |
3414 end | |
3415 @O.print @H.elementln("h1"){ | |
3416 msg('group', 'management') | |
3417 } | |
3418 user=@params['user'] | |
3419 | |
3420 # Check the existent group's validity | |
3421 if group | |
3422 unless (gr=grepgroup(group)) | |
3423 @O.print @H.p("No such group #{group}") | |
3424 return nil | |
3425 end | |
3426 group = gr | |
3427 unless @sc.isadmin(user, group) | |
3428 @O.print @H.p("You are not administrator of #{group}.") | |
3429 return nil | |
3430 end | |
3431 @O.print @H.elementln("h2"){ | |
3432 msg('group')+" #{group}" + | |
3433 if group != @sc.groupname(group) | |
3434 " (#{@sc.groupname(group)})" | |
3435 end.to_s | |
3436 } | |
3437 actionmethod={'action'=>@myname+"?-admgroupsub", 'method'=>'POST'} | |
3438 else | |
3439 # New group creation | |
3440 @O.print @H.elementln("h2"){ | |
3441 msg('newgroup') | |
3442 } | |
3443 actionmethod={'action'=>@myname+"?-newgroupsub", 'method'=>'POST'} | |
3444 end | |
3445 | |
43 | 3446 userlist = ([user] + users()).uniq.sort |
0 | 3447 myselfclass = {'class'=>'admin'} |
55
9a82edb295ca
Adjust umask. Max width of email entry, enlarged.
HIROSE Yuuji <yuuji@gentei.org>
parents:
50
diff
changeset
|
3448 yesclass = {'class' => 'yes'} |
0 | 3449 colspan2 = {'colspan'=>'2'} |
48
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3450 colspan3 = {'colspan'=>'3'} |
0 | 3451 warnclass = {'class'=>'warn'} |
3452 warnp = nil | |
3453 | |
3454 @O.print @H.elementln("form", actionmethod){ | |
3455 @H.hidden('group', group) + "\n" + \ | |
3456 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
|
3457 # 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
|
3458 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
|
3459 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
|
3460 # In this context, should return simply "". |
0 | 3461 "" |
3462 else | |
3463 # new group creation | |
3464 grps = @sc.groups() | |
3465 i=1 | |
3466 defname = "group%03d"%i | |
3467 while grps.grep(defname)[0] | |
3468 defname = "group%03d"%(i+=1) | |
3469 end | |
3470 @H.element("pre"){ | |
3471 msg('group', 'of', 'id')+"\n"+@H.text("group", defname) + "\n" + \ | |
3472 msg('group', 'of', 'name', 'anystring')+"\n"+ \ | |
3473 @H.text("gname", '') + "\n" | |
3474 } | |
3475 end + \ | |
47 | 3476 @H.elementln("div", {'class'=>'memlist'}){ |
48
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3477 @H.elementln("table", {'border'=>'1'}){ |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3478 @H.elementln("tr") { |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3479 @H.elementln("th", colspan3) { |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3480 msg('member', 'of', 'joinquit', 'operation')} |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3481 } + \ |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3482 @H.elementln("tr"){ |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3483 @H.element("th"){msg('join')} + \ |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3484 @H.element("th"){msg('administrator')} + \ |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3485 @H.element("th"){msg('member')} |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3486 } + \ |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3487 userlist.collect{|u| |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3488 recursememp = nil |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3489 if group |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3490 memberp = (@sc.ismember(u, group) && true) |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3491 adminp = (@sc.isadmin(u, group) && true) |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3492 if !memberp && @sc.members(group).grep(u)[0] |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3493 recursememp = true |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3494 end |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3495 else |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3496 memberp = adminp = (u == user) |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3497 end |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3498 @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
|
3499 @H.element("td", memberp && yesclass){ |
9a82edb295ca
Adjust umask. Max width of email entry, enlarged.
HIROSE Yuuji <yuuji@gentei.org>
parents:
50
diff
changeset
|
3500 yes = memberp ? 'YES' : 'yes' |
9a82edb295ca
Adjust umask. Max width of email entry, enlarged.
HIROSE Yuuji <yuuji@gentei.org>
parents:
50
diff
changeset
|
3501 @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
|
3502 @H.radio('mem-'+u, 'no', 'no', !memberp) |
48
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3503 } + \ |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3504 @H.element("td"){ |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3505 @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
|
3506 @H.radio('adm-'+u, 'no', 'no', !adminp) |
48
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3507 } + \ |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3508 @H.element("td"){ |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3509 @H.element("abbr", "title"=>mailaddress(u)) { |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3510 @sc.nickname(u) |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3511 } + \ |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3512 if recursememp |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3513 warnp = true |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3514 @H.element("span", warnclass){"(*)"} |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3515 end.to_s |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3516 } |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3517 } |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3518 }.join + \ |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3519 # group names |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3520 @H.elementln("tr") { |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3521 @H.elementln("th", colspan3) { |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3522 msg('group', 'of', 'joinquit', 'operation')} |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3523 } + \ |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3524 @H.elementln("tr"){ |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3525 @H.element("th", colspan2){msg('join')} + \ |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3526 @H.element("th"){msg('group')} |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3527 } + \ |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3528 @sc.groups().sort.collect{|g| |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3529 next if group == g |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3530 memberp = @sc.ismember(g, group) |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3531 @H.element("tr"){ |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3532 @H.element("td", colspan2){ |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3533 @H.radio('mem-'+g, 'yes', 'YES / ', memberp) + \ |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3534 @H.radio('mem-'+g, 'no', 'NO', !memberp) |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3535 } + \ |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3536 @H.element("td"){ |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3537 if @sc.isadmin(user, g) |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3538 @H.a(@myname+"?-admgroup+#{g}", @sc.groupname(g)) |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3539 else |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3540 @sc.groupname(g) |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3541 end |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3542 } |
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 }.join |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3545 } |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3546 } + \ |
69
bdb7e40c2d4f
`limitsender' option to prohibit anonymous user to send to ML
HIROSE Yuuji <yuuji@gentei.org>
parents:
68
diff
changeset
|
3547 ["fromhack", "inviteonly", "limitsender"].collect do |param| |
62
2d33f85c3d9f
Introduce invitation-only mode for groups.
HIROSE Yuuji <yuuji@gentei.org>
parents:
61
diff
changeset
|
3548 @H.checkbox(param, "yes", msg(param), |
2d33f85c3d9f
Introduce invitation-only mode for groups.
HIROSE Yuuji <yuuji@gentei.org>
parents:
61
diff
changeset
|
3549 @sc.getgroupattr(group, param)) + "<br>\n" |
2d33f85c3d9f
Introduce invitation-only mode for groups.
HIROSE Yuuji <yuuji@gentei.org>
parents:
61
diff
changeset
|
3550 end.join + \ |
2d33f85c3d9f
Introduce invitation-only mode for groups.
HIROSE Yuuji <yuuji@gentei.org>
parents:
61
diff
changeset
|
3551 (group ? @H.elementln("p") { |
2d33f85c3d9f
Introduce invitation-only mode for groups.
HIROSE Yuuji <yuuji@gentei.org>
parents:
61
diff
changeset
|
3552 sprintf(msg('mladdress'), defaultmladdress(group)) + \ |
2d33f85c3d9f
Introduce invitation-only mode for groups.
HIROSE Yuuji <yuuji@gentei.org>
parents:
61
diff
changeset
|
3553 @H.text("mladdress", @sc.getgroupattr(group, 'mladdress'), |
2d33f85c3d9f
Introduce invitation-only mode for groups.
HIROSE Yuuji <yuuji@gentei.org>
parents:
61
diff
changeset
|
3554 @opt['size'], 80) |
84
f67f5304baac
Add feature of sending message to a user
HIROSE Yuuji <yuuji@gentei.org>
parents:
83
diff
changeset
|
3555 } + \ |
f67f5304baac
Add feature of sending message to a user
HIROSE Yuuji <yuuji@gentei.org>
parents:
83
diff
changeset
|
3556 @H.elementln('p') { |
f67f5304baac
Add feature of sending message to a user
HIROSE Yuuji <yuuji@gentei.org>
parents:
83
diff
changeset
|
3557 sprintf(msg('xmlname'), group) + \ |
f67f5304baac
Add feature of sending message to a user
HIROSE Yuuji <yuuji@gentei.org>
parents:
83
diff
changeset
|
3558 @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
|
3559 @opt['size'], 80) |
62
2d33f85c3d9f
Introduce invitation-only mode for groups.
HIROSE Yuuji <yuuji@gentei.org>
parents:
61
diff
changeset
|
3560 } : "") + \ |
48
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3561 @H.elementln('p') { |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3562 n = -1 |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3563 curtag = @sc.getgroupattr(group, 'subjtag') |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3564 values = @subjtags.collect {|x| |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3565 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
|
3566 curtag==@subjtags[n][1] ? ' selected' : "", |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3567 x[0]) |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3568 }.join("\n") |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3569 "Subject tag: " + \ |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3570 <<-_EOF_ |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3571 <select name="subjtag"> |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3572 <option value="">DEFAULT</option> |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3573 #{values} |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3574 </select> |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3575 _EOF_ |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3576 } + \ |
0 | 3577 @H.submit_reset("GO") |
3578 } # form | |
3579 @O.print @H.p(@H.element("span", warnclass){"(*)"}+ | |
3580 msg('recursewarn')) if warnp | |
2 | 3581 if group && (members = @sc.members(group))[0] |
0 | 3582 @O.print @H.p(sprintf(msg('wholemembers'), group)) |
3583 @O.print @H.elementln("p", {'class'=>'listup'}){ | |
2 | 3584 members.collect{|u|@sc.nickname(u)}.join(", ")} |
0 | 3585 end |
3586 | |
3587 # | |
3588 # Next section, REMOVE GROUP! | |
3589 return nil unless group | |
3590 @O.print @H.elementln("h2"){ | |
3591 sprintf "%s %s %s", msg('group'), group, msg('deletion') | |
3592 } | |
3593 @O.print @H.p(msg('deletionwarn'))+"\n" | |
3594 @O.print @H.elementln("form", {'action'=>@myname+"?-delgroupsub+#{group}", 'method'=>'POST'}){ | |
3595 @H.hidden("group", group) + "\n" + \ | |
3596 @H.elementln("table"){ | |
3597 @H.elementln("tr"){ | |
3598 @H.elementln("td"){ | |
3599 sprintf msg('delgroup'), group | |
3600 } + \ | |
3601 @H.elementln("td"){ | |
3602 @H.radio("delete", "yes", msg('yes')) + ' ' + \ | |
3603 @H.radio("delete", "no", msg('no'), true) | |
3604 } | |
3605 } + \ | |
3606 @H.elementln("tr"){ | |
3607 @H.elementln("td"){ | |
3608 sprintf msg('really?'), group | |
3609 } + \ | |
3610 @H.elementln("td"){ | |
3611 @H.radio("delete2", "yes", msg('yes')) + ' ' + \ | |
3612 @H.radio("delete2", "no", msg('no'), true) | |
3613 } | |
3614 } | |
3615 } + \ | |
3616 "<br>\n" + @H.submit_reset("GO") | |
3617 } | |
3618 | |
3619 @O.print footer() | |
3620 end | |
3621 def newgroup() | |
3622 admgroup(nil) | |
3623 end | |
3624 | |
3625 def delgroupsub(group) | |
3626 if !checkauth | |
3627 return nil | |
3628 end | |
3629 user = @params['user'] | |
3630 if group != @params['group'] | |
3631 @O.print @H.p("Group mismatch") | |
3632 return nil | |
3633 end | |
3634 unless (gr=grepgroup(group)) | |
3635 @O.print @H.p("No such group #{group}") | |
3636 return nil | |
3637 end | |
83
54d85f7d5676
- The parameter pswdlen surely works
HIROSE Yuuji <yuuji@gentei.org>
parents:
82
diff
changeset
|
3638 group = safecopy(gr) |
0 | 3639 unless @sc.isadmin(user, group) |
3640 @O.print @H.p("You are not administrator of #{group}.") | |
3641 return nil | |
3642 end | |
3643 unless @params['delete'] && /yes/i =~ @params['delete'] \ | |
3644 && @params['delete2'] && /yes/i =~ @params['delete2'] | |
3645 @O.print @H.p(msg('chicken')) | |
3646 return nil | |
3647 end | |
3648 @O.print @H.elementln("h1"){ | |
3649 msg('group')+" #{group} "+msg('deletion') | |
3650 } | |
83
54d85f7d5676
- The parameter pswdlen surely works
HIROSE Yuuji <yuuji@gentei.org>
parents:
82
diff
changeset
|
3651 if @sc.destroygroup(group) |
54d85f7d5676
- The parameter pswdlen surely works
HIROSE Yuuji <yuuji@gentei.org>
parents:
82
diff
changeset
|
3652 system(sprintf("rm -r ml/%s", group)) |
54d85f7d5676
- The parameter pswdlen surely works
HIROSE Yuuji <yuuji@gentei.org>
parents:
82
diff
changeset
|
3653 resmsg = msg("done") |
54d85f7d5676
- The parameter pswdlen surely works
HIROSE Yuuji <yuuji@gentei.org>
parents:
82
diff
changeset
|
3654 else |
54d85f7d5676
- The parameter pswdlen surely works
HIROSE Yuuji <yuuji@gentei.org>
parents:
82
diff
changeset
|
3655 resmsg = Omsg("failure") |
54d85f7d5676
- The parameter pswdlen surely works
HIROSE Yuuji <yuuji@gentei.org>
parents:
82
diff
changeset
|
3656 end |
42
07ef43ac4f15
Some ruby-1.9 workarounds and enhancement to logging and messaging.
HIROSE Yuuji <yuuji@gentei.org>
parents:
41
diff
changeset
|
3657 @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
|
3658 putLog("Delete group '#{group}' #{resmsg}\n") |
0 | 3659 |
3660 @O.print footer() | |
3661 end | |
3662 | |
3663 def deleteuser(user) | |
3664 @sc.deleteuser(user) && | |
3665 begin | |
3666 pm = open_pm | |
3667 pm.delete(user) | |
3668 pm.close() | |
3669 true | |
3670 rescue | |
3671 nil | |
3672 end | |
3673 end | |
3674 def delusersub(user) | |
3675 if !checkauth | |
3676 return nil | |
3677 end | |
3678 user = @params['user'] | |
3679 if user != @params['user'] | |
3680 @O.print @H.p("User mismatch") | |
3681 return nil | |
3682 end | |
3683 unless (us=users().grep(user)[0]) | |
3684 @O.print @H.p("No such user #{user}") | |
3685 return nil | |
3686 end | |
3687 user = us | |
3688 unless @params['delete'] && /yes/i =~ @params['delete'] \ | |
3689 && @params['delete2'] && /yes/i =~ @params['delete2'] | |
3690 @O.print @H.p(msg('chicken')) | |
3691 return nil | |
3692 end | |
3693 @O.print @H.elementln("h1"){ | |
3694 msg('user')+" #{user} "+msg('deletion') | |
3695 } | |
42
07ef43ac4f15
Some ruby-1.9 workarounds and enhancement to logging and messaging.
HIROSE Yuuji <yuuji@gentei.org>
parents:
41
diff
changeset
|
3696 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
|
3697 @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
|
3698 putLog("Delete user '#{user}' #{resmsg}\n") |
0 | 3699 |
7 | 3700 @O.print @H.p(@H.a(@myname, msg('login'))) |
0 | 3701 end |
3702 | |
3703 def admgroupsub() | |
3704 if !checkauth | |
3705 return nil | |
3706 end | |
3707 user = @params['user'] | |
3708 group = @params['group'] | |
3709 unless (gr=grepgroup(group)) | |
3710 @O.print @H.element("pre"){"No such group #{group.inspect}"} | |
3711 return nil | |
3712 end | |
3713 unless @sc.isadmin(user, group) | |
3714 @O.print @H.p("You are not administrator of #{group}.") | |
3715 return nil | |
3716 end | |
3717 gorup = gr | |
3718 @O.print @H.elementln("h1"){ | |
3719 msg('group', 'management', 'done') | |
3720 } | |
3721 @O.print @H.elementln("h2"){ | |
3722 msg('group')+" #{group}" + | |
3723 if group != @sc.groupname(group) | |
3724 " (#{@sc.groupname(group)})" | |
3725 end.to_s | |
3726 } | |
3727 somethingdone = nil | |
3728 for u in users() | |
2 | 3729 u = @sc.isuser(u) # users() value is considered tainted. |
3730 next unless u # Use registered value in @sc. | |
0 | 3731 for var, kind in { |
3732 "mem"=>['members', 'member'], 'adm'=>['admin', 'administrator']} | |
3733 memv = "#{var}-#{u}" | |
3734 if @params[memv] | |
3735 joinp = ((/^yes/i =~ @params[memv]) && true) | |
3736 membp = if var=='mem' | |
3737 @sc.ismember(u, group) | |
3738 else # admin | |
3739 @sc.isadmin(u, group) | |
3740 end && true | |
3741 if var=='adm' && @sc.admins(group).length == 1 && membp && !joinp | |
3742 @O.print @H.p(sprintf(msg('soleadmin'), u, group)) | |
3743 elsif joinp ^ membp | |
3744 somethingdone = true | |
3745 @sc.addgroup(group, [u], !joinp, kind[0]) | |
3746 @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
|
3747 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
|
3748 msg(kind[1]), |
07ef43ac4f15
Some ruby-1.9 workarounds and enhancement to logging and messaging.
HIROSE Yuuji <yuuji@gentei.org>
parents:
41
diff
changeset
|
3749 joinp ? msg('addedtogroup'): msg('removedfromgp'), group) |
0 | 3750 } |
3751 end | |
3752 end | |
3753 end | |
3754 end # users() | |
3755 | |
3756 # add or remove for group in groups | |
3757 for g in @sc.groups() | |
3758 next if g == group | |
3759 memv = "mem-#{g}" | |
3760 if @params[memv] | |
3761 joinp = ((/^yes/i =~ @params[memv]) && true) | |
3762 membp = (@sc.ismember(g, group) && true) | |
3763 if joinp ^ membp | |
3764 somethingdone = true | |
3765 @sc.addgroup(group, [g], !joinp) | |
3766 @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
|
3767 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
|
3768 msg('group'), g, |
07ef43ac4f15
Some ruby-1.9 workarounds and enhancement to logging and messaging.
HIROSE Yuuji <yuuji@gentei.org>
parents:
41
diff
changeset
|
3769 joinp ? |
07ef43ac4f15
Some ruby-1.9 workarounds and enhancement to logging and messaging.
HIROSE Yuuji <yuuji@gentei.org>
parents:
41
diff
changeset
|
3770 msg('addedtogroup') |
07ef43ac4f15
Some ruby-1.9 workarounds and enhancement to logging and messaging.
HIROSE Yuuji <yuuji@gentei.org>
parents:
41
diff
changeset
|
3771 : msg('removedfromgp'), group)) |
07ef43ac4f15
Some ruby-1.9 workarounds and enhancement to logging and messaging.
HIROSE Yuuji <yuuji@gentei.org>
parents:
41
diff
changeset
|
3772 } |
0 | 3773 end |
3774 end | |
3775 end # groups | |
47 | 3776 # Change parameter(s) |
3777 # 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
|
3778 ["fromhack", "inviteonly", "limitsender"].each {|param| |
62
2d33f85c3d9f
Introduce invitation-only mode for groups.
HIROSE Yuuji <yuuji@gentei.org>
parents:
61
diff
changeset
|
3779 parsetp = (@params[param] && /^yes/i =~ @params[param]) |
2d33f85c3d9f
Introduce invitation-only mode for groups.
HIROSE Yuuji <yuuji@gentei.org>
parents:
61
diff
changeset
|
3780 cursetp = (@sc.getgroupattr(group, param)!=nil) |
2d33f85c3d9f
Introduce invitation-only mode for groups.
HIROSE Yuuji <yuuji@gentei.org>
parents:
61
diff
changeset
|
3781 if cursetp ^ parsetp |
2d33f85c3d9f
Introduce invitation-only mode for groups.
HIROSE Yuuji <yuuji@gentei.org>
parents:
61
diff
changeset
|
3782 @sc.putgroupattr(group, param, @params[param]) |
2d33f85c3d9f
Introduce invitation-only mode for groups.
HIROSE Yuuji <yuuji@gentei.org>
parents:
61
diff
changeset
|
3783 @O.print @H.elementln("p") { |
2d33f85c3d9f
Introduce invitation-only mode for groups.
HIROSE Yuuji <yuuji@gentei.org>
parents:
61
diff
changeset
|
3784 putLog(sprintf("group: %s[%s] -> %s", |
2d33f85c3d9f
Introduce invitation-only mode for groups.
HIROSE Yuuji <yuuji@gentei.org>
parents:
61
diff
changeset
|
3785 group, param, @params[param].inspect)) |
2d33f85c3d9f
Introduce invitation-only mode for groups.
HIROSE Yuuji <yuuji@gentei.org>
parents:
61
diff
changeset
|
3786 } |
2d33f85c3d9f
Introduce invitation-only mode for groups.
HIROSE Yuuji <yuuji@gentei.org>
parents:
61
diff
changeset
|
3787 somethingdone = true |
2d33f85c3d9f
Introduce invitation-only mode for groups.
HIROSE Yuuji <yuuji@gentei.org>
parents:
61
diff
changeset
|
3788 end |
2d33f85c3d9f
Introduce invitation-only mode for groups.
HIROSE Yuuji <yuuji@gentei.org>
parents:
61
diff
changeset
|
3789 } |
48
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3790 # mladdress |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3791 newmladdress = @params['mladdress'] |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3792 newmladdress = nil if newmladdress == "" |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3793 curmladdress = @sc.getgroupattr(group, 'mladdress') |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3794 if newmladdress != curmladdress |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3795 defmladdress = defaultmladdress(group) |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3796 @sc.putgroupattr(group, 'mladdress', newmladdress) |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3797 @O.print @H.elementln("p") { |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3798 putLog(sprintf("group: %s[mladdress] <%s> -> <%s>", |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3799 group, |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3800 curmladdress || defmladdress, |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3801 newmladdress || defmladdress)) |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3802 } |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3803 somethingdone = true |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3804 end |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3805 # Subject tag bracket |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3806 newtag = @params['subjtag'] |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3807 if newtag == '' |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3808 newtag = nil |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3809 else |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3810 newtag = @subjtags[newtag.to_i % @subjtags.length][1] |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3811 end |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3812 @sc.putgroupattr(group, 'subjtag', newtag) |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3813 if newtag && newtag > "" |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3814 @O.print @H.elementln("p") { |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3815 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
|
3816 } |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3817 somethingdone = true |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
3818 end |
83
54d85f7d5676
- The parameter pswdlen surely works
HIROSE Yuuji <yuuji@gentei.org>
parents:
82
diff
changeset
|
3819 # X-ML-Name: Header value |
54d85f7d5676
- The parameter pswdlen surely works
HIROSE Yuuji <yuuji@gentei.org>
parents:
82
diff
changeset
|
3820 xmlname = @params['xmlname'] |
54d85f7d5676
- The parameter pswdlen surely works
HIROSE Yuuji <yuuji@gentei.org>
parents:
82
diff
changeset
|
3821 xmlname = nil if xmlname == "" |
54d85f7d5676
- The parameter pswdlen surely works
HIROSE Yuuji <yuuji@gentei.org>
parents:
82
diff
changeset
|
3822 curxmlname = @sc.getgroupattr(group, 'xmlname') |
54d85f7d5676
- The parameter pswdlen surely works
HIROSE Yuuji <yuuji@gentei.org>
parents:
82
diff
changeset
|
3823 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
|
3824 @sc.putgroupattr(group, 'xmlname', xmlname) |
54d85f7d5676
- The parameter pswdlen surely works
HIROSE Yuuji <yuuji@gentei.org>
parents:
82
diff
changeset
|
3825 @O.print @H.elementln("p") { |
54d85f7d5676
- The parameter pswdlen surely works
HIROSE Yuuji <yuuji@gentei.org>
parents:
82
diff
changeset
|
3826 putLog(sprintf("X-ML-Name: Set to %s", xmlname)) |
54d85f7d5676
- The parameter pswdlen surely works
HIROSE Yuuji <yuuji@gentei.org>
parents:
82
diff
changeset
|
3827 } |
54d85f7d5676
- The parameter pswdlen surely works
HIROSE Yuuji <yuuji@gentei.org>
parents:
82
diff
changeset
|
3828 somethingdone = true |
54d85f7d5676
- The parameter pswdlen surely works
HIROSE Yuuji <yuuji@gentei.org>
parents:
82
diff
changeset
|
3829 end |
0 | 3830 unless somethingdone |
3831 # @O.print @H.p(msg('nothingtodo')) | |
3832 end | |
36
e67737e49a5d
add a5userman.html multiplenotify.html
HIROSE Yuuji <yuuji@gentei.org>
parents:
35
diff
changeset
|
3833 # @O.print footer() |
e67737e49a5d
add a5userman.html multiplenotify.html
HIROSE Yuuji <yuuji@gentei.org>
parents:
35
diff
changeset
|
3834 link2home |
0 | 3835 end |
3836 def newgroupsub() | |
42
07ef43ac4f15
Some ruby-1.9 workarounds and enhancement to logging and messaging.
HIROSE Yuuji <yuuji@gentei.org>
parents:
41
diff
changeset
|
3837 return nil unless checkauth |
0 | 3838 user = @params['user'] |
3839 newgroup = @params['group'] | |
3840 newgname = @params['gname'] | |
3841 | |
3842 | |
3843 if @sc.groups.grep(newgroup)[0] | |
3844 @O.print @H.p(msg('existent')+newgroup) | |
3845 return nil | |
3846 end | |
2 | 3847 if dupl=@sc.name2group(newgname) |
3848 @O.print @H.p(sprintf(msg('dupname'), newgname)) | |
3849 @O.print groupnamesString() | |
3850 return nil | |
3851 end | |
42
07ef43ac4f15
Some ruby-1.9 workarounds and enhancement to logging and messaging.
HIROSE Yuuji <yuuji@gentei.org>
parents:
41
diff
changeset
|
3852 @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
|
3853 putLog("New group '#{newgroup}'(#{newgname}) created\n") |
47 | 3854 admgroupsub() |
0 | 3855 end |
3856 | |
14 | 3857 # |
3858 # Methods Related to viaMail functions | |
3859 def gen_sessionpswd() | |
3860 | |
3861 end | |
3862 def viamail_registform() | |
3863 c = "# " | |
3864 nl = "\n" | |
3865 user = @params['user'] | |
3866 msg('addsched') + "-" * 20 + nl*2 + \ | |
3867 c + msg('user') + nl + \ | |
3868 "user=" + user + nl*2 + \ | |
3869 c + msg('sessionpswd') + nl + \ | |
3870 "sp=hoge" + nl*2 + \ | |
3871 c + msg('date') + nl + \ | |
3872 "date="+Time.now.strftime("%Y/%m/%d") + nl*2 + \ | |
3873 c + msg('time') + sprintf(msg('24hourtxt'), @opt['alldaydir']) + nl + \ | |
3874 "time=3000"+nl*2 + \ | |
3875 c + msg('publicp') + nl + \ | |
3876 "public=yes" + nl*2 + \ | |
3877 c + msg('neednotify') + nl + \ | |
3878 "nt10m=yes (%s) | |
3879 nttoday=yes (%s) | |
3880 nt1d=yes (%s) | |
3881 nt7d=yes (%s)" % ["10"+msg('minutes')+msg('before'), | |
3882 msg('theday'), msg('precedingday'), | |
3883 "7"+msg('days')+msg('before')] + nl*2 + \ | |
3884 | |
3885 c + msg('schedulehere') | |
3886 end | |
3887 def viamail_footer() | |
3888 viamail_registform() | |
3889 end | |
3890 def show_by_text(date, days) | |
3891 user = @params['user'] | |
3892 personal = true | |
3893 sched = dayTextString(user, date, days, personal) | |
3894 # @O.print outstr | |
3895 | |
3896 sendMail(mailaddress(user), | |
3897 "After5 Schedule", | |
3898 @opt['url'] + "\n" + \ | |
3899 Time.now.strftime("%Y/%m/%d") + \ | |
3900 sprintf(msg('schedlist'), days) + "\n\n" + \ | |
3901 if sched > '' | |
3902 sched | |
3903 else | |
3904 msg('noplan')+"\n" | |
3905 end + \ | |
3906 viamail_footer | |
3907 ) | |
3908 | |
3909 end | |
3910 def parseHeader | |
3911 contline=nil | |
3912 header=Hash.new | |
3913 text=Array.new | |
3914 | |
3915 field=nil | |
3916 # header | |
3917 while line=STDIN.gets | |
3918 text << line | |
3919 break if /^$/ =~ line | |
3920 | |
3921 if /^\s+/ =~ line | |
3922 if field | |
3923 header[field][-1] << line | |
3924 end | |
3925 else | |
3926 if /^([^:]+):\s*(.*)/ =~ line | |
3927 field=$1.downcase | |
3928 header[field] or header[field] = [] | |
3929 header[field] << $2 | |
3930 end | |
3931 end | |
3932 end | |
3933 header | |
3934 end | |
3935 def mail_regsched() | |
3936 @params = Hash.new # Reset | |
3937 | |
3938 reqparams = %w[user sp date time public] | |
3939 otherparams = %w[nt10m nttoday nt1d nt7d] | |
3940 setall = lambda{ | |
3941 reqparams.each{|key| return false unless @params.has_key?(key)} | |
3942 return true | |
3943 } | |
3944 stack = "" | |
3945 while line=gets # !setall.call && line=gets | |
3946 if /^(\S+)=(.*)/ =~ line | |
3947 next unless reqparams.index($1) || otherparams.index($1) | |
3948 @params[$1] = $2 | |
3949 #if reqparams.index($1) | |
3950 STDERR.print "Set #{$1} to #{$2}\n" | |
3951 #end | |
3952 buf = "" | |
3953 elsif /^\s*\#|^$/ =~ line | |
3954 # skip comments | |
3955 else | |
3956 buf += line | |
3957 end | |
3958 end | |
3959 unless setall.call | |
3960 STDERR.print "Insufficient variables\n" | |
3961 exit 1 | |
3962 end | |
3963 p buf | |
3964 | |
3965 y, m, d = date2ymd(@params["date"]) | |
3966 @params["year"] = y | |
3967 @params["month"] = m | |
3968 @params["day"] = d | |
3969 @params["schedule"] = buf | |
3970 @params["editmode"] = "modify" | |
3971 @params["sessionpw"] = @params["sp"] | |
3972 p @params | |
3973 add_remove() | |
3974 end | |
3975 def mail_getsched() | |
3976 user = nil | |
3977 while bline=gets | |
3978 if /(\S+@\S+)/ =~ bline | |
3979 break if user=@sc.isuser($1) | |
3980 end | |
3981 end | |
3982 unless user | |
3983 sendMail(@opt['maintainer'], "viaMail Request Error", | |
3984 "This is `#{@mybase}' in #{@mydir}\n" + | |
3985 "Invalid schedule request from #{ENV['SENDER']}.\n\n") | |
3986 exit 1 | |
3987 end | |
3988 today = Time.now.strftime("%Y/%m/%d") | |
3989 days = 7 | |
3990 if bline=gets | |
3991 if /\d+/ =~ bline | |
3992 days = bline.to_i | |
3993 end | |
3994 end | |
3995 # Send user to schedules of today and near future | |
3996 @params['user'] = user | |
3997 show_by_text(today, days) | |
3998 end | |
3999 def doMail() | |
4000 days = 7 | |
4001 # Confirm `via Mail' | |
4002 prohibitviahttp() | |
4003 @H = TEXTout.new | |
4004 unless ENV['RECIPIENT'] && ENV['SENDER'] | |
4005 STDERR.print "Call me via qmail\n" | |
4006 exit 1 | |
4007 end | |
4008 @mailmode = true | |
4009 header = parseHeader # is this necessary? | |
4010 if /regist/ =~ ENV["EXT"] | |
4011 mail_regsched() | |
4012 else | |
4013 mail_getsched() | |
4014 end | |
4015 end | |
4016 | |
4017 # | |
4018 # Password related Methos | |
0 | 4019 def setpasswd(user) |
4020 prohibitviahttp() | |
4021 pm = open_pm() | |
4022 exit 1 unless pm | |
4023 if pm.userexist?(user) then | |
4024 begin | |
4025 system "stty -echo" | |
4026 STDERR.print "New passwd: " | |
4027 p1 = STDIN.gets | |
4028 STDERR.print "\nAgain: " | |
4029 p2 = STDIN.gets | |
4030 ensure | |
4031 system "stty echo" | |
4032 end | |
4033 if (p1 == p2) then | |
4034 pm.setpasswd(user, p1.chop!) | |
4035 end | |
4036 STDERR.print "New password for #{user} set successfully\n" | |
4037 else | |
4038 STDERR.print "User #{user} not found\n" | |
4039 end | |
4040 pm.close() | |
4041 exit 0 | |
4042 end | |
4043 def adduser(user) | |
4044 prohibitviahttp() | |
4045 pm = open_pm() | |
4046 exit 1 unless pm | |
60 | 4047 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
|
4048 printf("User %s already exists. Skip.\n", user) |
60 | 4049 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
|
4050 exit 1 |
595ff0134cd9
Skip creation of user which is already registered.
HIROSE Yuuji <yuuji@gentei.org>
parents:
58
diff
changeset
|
4051 end |
45
1b16890d61d6
ML: digited subject, ML-specific email addresses, spooling
HIROSE Yuuji <yuuji@gentei.org>
parents:
44
diff
changeset
|
4052 email = nil |
1b16890d61d6
ML: digited subject, ML-specific email addresses, spooling
HIROSE Yuuji <yuuji@gentei.org>
parents:
44
diff
changeset
|
4053 if /(.*@.*)=(.*@.*)/ =~ user |
1b16890d61d6
ML: digited subject, ML-specific email addresses, spooling
HIROSE Yuuji <yuuji@gentei.org>
parents:
44
diff
changeset
|
4054 user, email = $1, $2 |
1b16890d61d6
ML: digited subject, ML-specific email addresses, spooling
HIROSE Yuuji <yuuji@gentei.org>
parents:
44
diff
changeset
|
4055 end |
0 | 4056 newpwd = pm.setnewpasswd(user, 4) |
45
1b16890d61d6
ML: digited subject, ML-specific email addresses, spooling
HIROSE Yuuji <yuuji@gentei.org>
parents:
44
diff
changeset
|
4057 @sc.createuser(user, email) |
0 | 4058 print "#{user}'s password is #{newpwd}\n" |
4059 pm.close() | |
4060 exit 0 | |
4061 end | |
4062 def deluser(user) | |
4063 prohibitviahttp() | |
4064 pm = open_pm() | |
4065 exit 1 unless pm | |
4066 pm.delete(user) | |
45
1b16890d61d6
ML: digited subject, ML-specific email addresses, spooling
HIROSE Yuuji <yuuji@gentei.org>
parents:
44
diff
changeset
|
4067 @sc.deleteuser(user) |
0 | 4068 pm.close() |
4069 exit 0 | |
4070 end | |
4071 | |
4072 # read configuratoin file | |
4073 def readconf(conf) | |
4074 cf = "after5.cf" #conf # || @opt['conf'] | |
4075 cf = File.join(@mydir, cf) unless test(?s, cf) | |
4076 cf = File.join(ENV["HOME"], cf) unless test(?s, cf) | |
4077 return unless test(?s, cf) | |
4078 begin | |
4079 IO.foreach(cf){|line| | |
26 | 4080 line = line.toeuc |
0 | 4081 next if /^\s *#/ =~ line |
4082 line.chop! | |
4083 line.sub!(/^\s*#.*/, '') | |
4084 next if /^$/ =~ line | |
4085 case line | |
4086 # title, type = line.split(/\t+/) | |
4087 when /^([a-z]+)=(.*)/oi | |
4088 key, value = $1, $2 | |
4089 case value | |
6 | 4090 when /^(no|none|null|nil|false|0|off)$/io |
0 | 4091 @opt[key] = nil |
4092 else | |
45
1b16890d61d6
ML: digited subject, ML-specific email addresses, spooling
HIROSE Yuuji <yuuji@gentei.org>
parents:
44
diff
changeset
|
4093 @opt[key] = value.untaint |
0 | 4094 end |
4095 print "#{key} set to #{value}\n" if $DEBUG | |
4096 end | |
4097 } | |
4098 rescue | |
26 | 4099 STDERR.printf("Configuration file %s not readable\n", cf) |
0 | 4100 end |
4101 end | |
4102 | |
4103 def parsedate(string) | |
4104 if %r,^(\d\d\d\d+)/(\d+)/(\d+)/(\d+)/([^/]+)$, =~ string | |
4105 sprintf "%04d/%02d/%02d/%04d/%s", $1.to_i, $2.to_i, $3.to_i, $4.to_i, | |
4106 grepgroup($5) | |
4107 elsif %r,^(\d\d\d\d+)/(\d+)/(\d+)/(\d+), =~ string | |
4108 sprintf "%04d/%02d/%02d/%04d", $1.to_i, $2.to_i, $3.to_i, $4.to_i | |
4109 elsif %r,^(\d\d\d\d+)/(\d+)/(\d+), =~ string | |
4110 sprintf "%04d/%02d/%02d", $1.to_i, $2.to_i, $3.to_i | |
4111 elsif %r,^(\d\d\d\d+)/(\d+), =~ string | |
4112 sprintf "%04d/%02d", $1.to_i, $2.to_i | |
4113 elsif %r,^(\d\d\d\d+)/(\d+), =~ string | |
4114 sprintf "%04d", $1.to_i | |
4115 end | |
4116 end | |
4117 | |
4118 def getarg() | |
4119 argument = {} | |
48
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
4120 @oldargv = ARGV.dup |
0 | 4121 |
4122 while /^-/ =~ ARGV[0] | |
4123 case ARGV[0] | |
4124 when '-f' | |
4125 conf = ARGV[1] | |
4126 ARGV.shift | |
4127 when "-d" | |
4128 $DEBUG = true | |
4129 when "-install" | |
14 | 4130 when "-stream" |
4131 # ARGV.shift | |
4132 # @job = 'show_by_text "2005/1/18"' | |
4133 @job = 'doMail' | |
0 | 4134 when "-addsched" |
4135 @job = "addsched" | |
4136 when "-today" | |
4137 @job = "today" | |
2 | 4138 when "-today_p" |
4139 argument['displaymode'] = 'personal' | |
4140 @job = "today" | |
4141 when "-today_n" | |
4142 argument['displaymode'] = 'normal' | |
4143 @job = "today" | |
0 | 4144 when "-remove" |
4145 ARGV.shift | |
4146 @job = 'remove "'+parsedate(ARGV[0])+'"' | |
14 | 4147 when "-move" |
4148 ARGV.shift | |
4149 @job = 'move "'+parsedate(ARGV[0])+'"' | |
0 | 4150 when "-modify" |
4151 ARGV.shift | |
4152 @job = 'modify "'+parsedate(ARGV[0])+'"' | |
4153 when "-month" | |
4154 ARGV.shift | |
4155 @job = 'month "'+parsedate(ARGV[0])+'"' | |
4156 when "-show" | |
4157 ARGV.shift | |
4158 # @job = "show '"+ARGV[0]+"'" | |
4159 @job = "show '"+parsedate(ARGV[0])+"'" | |
4160 when "-login" | |
4161 @job = "login" | |
4162 when "-userman" | |
4163 @job = "userman" | |
4164 when "-usermod" | |
4165 @job = "usermod" | |
4166 when "-groupinout" | |
4167 @job = "groupinout" | |
4168 when "-groupsubmit" | |
4169 @job = "groupsubmit" | |
4170 when "-groupman" | |
48
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
4171 ARGV.shift |
05de5274c110
Another ml-address can be set.
HIROSE Yuuji <yuuji@gentei.org>
parents:
47
diff
changeset
|
4172 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
|
4173 @job = "groupman("+(x ? "'#{x.dup.untaint}'" : "") + ")" |
0 | 4174 when "-groupmod" |
4175 @job = "groupmod" | |
4176 when "-notify" | |
4177 @job = 'notify' # + exit | |
37
1515ea889ea1
First implementation of ML feature.
HIROSE Yuuji <yuuji@gentei.org>
parents:
36
diff
changeset
|
4178 when "-list" |
1515ea889ea1
First implementation of ML feature.
HIROSE Yuuji <yuuji@gentei.org>
parents:
36
diff
changeset
|
4179 @job = 'list' # + exit |
0 | 4180 when "-newgroup" |
4181 @job = 'newgroup' | |
42
07ef43ac4f15
Some ruby-1.9 workarounds and enhancement to logging and messaging.
HIROSE Yuuji <yuuji@gentei.org>
parents:
41
diff
changeset
|
4182 when /^-(admgroup|listdraft)$/ |
0 | 4183 ARGV.shift |
84
f67f5304baac
Add feature of sending message to a user
HIROSE Yuuji <yuuji@gentei.org>
parents:
83
diff
changeset
|
4184 #gr = safecopy(grepgroup(ARGV[0])) |
f67f5304baac
Add feature of sending message to a user
HIROSE Yuuji <yuuji@gentei.org>
parents:
83
diff
changeset
|
4185 gr = safecopy(ARGV[0]) # -listdraft can be called with user 2013/12/12 |
0 | 4186 ##gr.untaint |
37
1515ea889ea1
First implementation of ML feature.
HIROSE Yuuji <yuuji@gentei.org>
parents:
36
diff
changeset
|
4187 @job = safecopy($1)+' "'+gr+'"' |
0 | 4188 when "-admgroupsub" |
4189 @job = 'admgroupsub' | |
4190 when "-newgroupsub" | |
4191 @job = 'newgroupsub' | |
4192 when "-delusersub" | |
4193 ARGV.shift | |
6 | 4194 usr = safecopy(users().grep(ARGV[0])[0]) |
0 | 4195 @job = 'delusersub "'+usr+'"' |
4196 when "-delgroupsub" | |
4197 ARGV.shift | |
42
07ef43ac4f15
Some ruby-1.9 workarounds and enhancement to logging and messaging.
HIROSE Yuuji <yuuji@gentei.org>
parents:
41
diff
changeset
|
4198 gr = safecopy(grepgroup(ARGV[0])) |
0 | 4199 @job = 'delgroupsub "'+gr+'"' |
4200 when /-(setpasswd|deluser|adduser)$/ | |
4201 ARGV.shift | |
4202 @job = $1+ " '#{ARGV[0]}'" # + exit | |
4203 when "" | |
4204 end | |
4205 ARGV.shift | |
4206 end | |
4207 | |
4208 readconf(@conf) | |
4209 | |
4210 query = '' | |
4211 method = ENV["REQUEST_METHOD"] | |
4212 if /POST/i =~ method then | |
4213 length = ENV["CONTENT_LENGTH"].to_i | |
4214 query = STDIN.read(length) | |
4215 elsif /GET/i =~ method then | |
4216 query = ENV["QUERY_STRING"] | |
4217 else # executed from command line | |
4218 query = ARGV.join("&") | |
4219 end | |
4220 | |
85 | 4221 if ENV['CONTENT_TYPE'] && |
4222 %r,multipart/form-data.*boundary=(.*),i =~ ENV['CONTENT_TYPE'] | |
4223 boundary = $1 | |
4224 query.split("\r\n--"+boundary).each {|unit| | |
4225 if /Content-Disposition.*\bname=([\'\"])?(\S*)\1/i =~ unit | |
4226 argument.has_key?(key=$2) or argument[key]=[] | |
4227 newvalue = Hash.new | |
4228 if /^Content.*filename=([\'\"])?(\S*)\1/i =~ unit | |
4229 newvalue['filename'] = $2 | |
4230 end | |
4231 newvalue['value'] = unit.sub(/.*\r\n\r\n/m, "") | |
4232 if /^Content-type:\s*(\S*)/i =~ unit | |
4233 newvalue['content-type'] = $1 | |
4234 else | |
4235 newvalue['value'].gsub!("\r\n", "\n") | |
4236 end | |
4237 argument[key] << newvalue | |
4238 end | |
4239 } | |
4240 if $DEBUG | |
4241 open("/tmp/body", "w"){|x| | |
4242 x.write query.split("\r\n--"+boundary+"\r\n")[-1] | |
4243 argument.each{|k,v| | |
4244 x.printf(" %s => %s\n", k.inspect, v.inspect)} | |
4245 x.printf("boundary=\n%s\n",boundary) | |
4246 x.printf("ENV=%s\n",ENV.inspect) | |
4247 x.write query} | |
4248 end | |
4249 else | |
4250 for unit in query.split(/\&/) | |
4251 if /^([a-z][-_0-9@%a-z.]*)=(.*)/i =~ unit | |
4252 key, value = $1, $2 | |
4253 #value.gsub!(/%(..)/){[$1.hex].pack("c")} # これでURLデコードが一発 | |
4254 decode!(value) | |
4255 decode!(key) | |
4256 value = Kconv::toeuc(value) # EUCに変換 | |
4257 printf "[%s] = %s\n", key, value if $DEBUG | |
4258 argument[key] = value | |
4259 end | |
0 | 4260 end |
4261 end | |
4262 argument | |
4263 end | |
4264 def getcookie() | |
4265 cookie = {} | |
7 | 4266 return cookie unless ENV['HTTP_COOKIE'] |
4267 #if /value=(.*)/ =~ ENV['HTTP_COOKIE'] | |
4268 for cv in ENV['HTTP_COOKIE'].split(/[\; ]+/).grep(/(value|prefs)=(.*)/) | |
0 | 4269 # value=$1.gsub!(/%(..)/){[$1.hex].pack("c")} |
7 | 4270 next unless /\w+=(.*)/ =~ cv |
0 | 4271 value=decode!($1) |
7 | 4272 next unless value |
0 | 4273 for line in value.split("&") |
4274 if /(\w+)=(.*)/ =~ line | |
4275 key, value = $1, $2 | |
4276 #value.gsub!(/%(..)/){[$1.hex].pack("c")} # これでURLデコードが一発 | |
4277 decode!(value) | |
4278 value = Kconv::toeuc(value) # EUCに変換 | |
4279 printf "cookie[%s] = %s\n", key, value if $DEBUG | |
4280 cookie[key] = value | |
4281 end | |
4282 end | |
4283 end | |
4284 cookie | |
4285 end | |
4286 end | |
4287 | |
17 | 4288 $KCODE='e' if RUBY_VERSION < "1.9" |
0 | 4289 After5.new.doit |
4290 | |
4291 if __FILE__ == $0 | |
4292 end | |
4293 | |
4294 | |
4295 # Local variables: | |
4296 # buffer-file-coding-system: euc-jp | |
4297 # End: |