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