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