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