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