comparison after5.rb @ 87:1f99367752fb draft

Link to home in groupman()
author HIROSE Yuuji <yuuji@gentei.org>
date Thu, 19 Dec 2013 11:33:53 +0900
parents 26c81703a80c
children c4ea79816b2d
comparison
equal deleted inserted replaced
86:26c81703a80c 87:1f99367752fb
2 # -*- coding: euc-jp -*- 2 # -*- coding: euc-jp -*-
3 # 3 #
4 # Associative Scheduling Table - after5 4 # Associative Scheduling Table - after5
5 # (C)2003, 2004, 2006, 2008, 2012, 2013 by HIROSE Yuuji [yuuji<at>gentei.org] 5 # (C)2003, 2004, 2006, 2008, 2012, 2013 by HIROSE Yuuji [yuuji<at>gentei.org]
6 # $Id: after5.rb,v 1.20 2012/12/03 15:54:20 yuuji Exp $ 6 # $Id: after5.rb,v 1.20 2012/12/03 15:54:20 yuuji Exp $
7 # Last modified Mon Dec 16 10:56:24 2013 on firestorm 7 # Last modified Thu Dec 19 11:33:07 2013 on firestorm
8 # See http://www.gentei.org/~yuuji/software/after5/ 8 # See http://www.gentei.org/~yuuji/software/after5/
9 # このスクリプトはEUCで保存してください。 9 # このスクリプトはEUCで保存してください。
10 $hgid = <<_HGID_.split[1..-2].join(" ") 10 $hgid = <<_HGID_.split[1..-2].join(" ")
11 $HGid$ 11 $HGid$
12 _HGID_ 12 _HGID_
301 map[u][attr] = IO.readlines(file).join.toeuc.strip 301 map[u][attr] = IO.readlines(file).join.toeuc.strip
302 } 302 }
303 } 303 }
304 map 304 map
305 end 305 end
306 def ismembersemail(email) 306 def ismembersemail(email, grp = nil)
307 @usermap.keys.each {|u| 307 @usermap.keys.each {|u|
308 return u if u==email 308 return u if u==email
309 return u if mailaddress(u).split(/,\s*|\s+/).grep(email)[0] 309 return u if mailaddress(u, grp).split(/,\s*|\s+/).collect{|m|
310 m.sub(/^(skip|off):/i, "")
311 }.grep(email)[0]
310 } 312 }
311 nil 313 nil
312 end 314 end
313 def putuserattr(user, attr, text) 315 def putuserattr(user, attr, text)
314 # if text==nil, remove it 316 # if text==nil, remove it
348 else 350 else
349 return user.sub(/@.*/, '') 351 return user.sub(/@.*/, '')
350 end 352 end
351 end 353 end
352 def mailaddress(user, grp = nil) 354 def mailaddress(user, grp = nil)
353 grp ? mail4grp(user, grp) : \ 355 grp ? \
356 mail4grp(user, grp) : \
354 (getuserattr(user, 'email') || user) 357 (getuserattr(user, 'email') || user)
355 end 358 end
356 def setnickname(user, nickname) 359 def setnickname(user, nickname)
357 putuserattr(user, 'name', nickname) 360 putuserattr(user, 'name', nickname)
358 end 361 end
577 else 580 else
578 ! @groupmap.select{|k, v| k==instance}.empty? 581 ! @groupmap.select{|k, v| k==instance}.empty?
579 end 582 end
580 end 583 end
581 def mail4grp(usr, group) 584 def mail4grp(usr, group)
585 # If members/user file contains only "skip:" keyword,
586 # return "skip:email@add.re.ss"
587 default = mailaddress(usr)
582 file = File.expand_path((group+"/members/"+usr).untaint, @groupmapdir) 588 file = File.expand_path((group+"/members/"+usr).untaint, @groupmapdir)
583 if test(?s, file.untaint) 589 if test(?s, file.untaint)
584 open(file, "r"){|f|f.gets.chomp}.untaint 590 rcpt = open(file, "r"){|f|f.gets.chomp}.untaint
585 else 591 if /^(off|skip):/ =~ rcpt && /@/ !~ rcpt
586 mailaddress(usr) 592 rcpt = "skip:"+default
587 end 593 end
594 return rcpt
595 end
596 default
597 end
598 def delivergrpmail(user, grp)
599
588 end 600 end
589 def ismember(user, grouporuser) 601 def ismember(user, grouporuser)
590 return user if user==grouporuser 602 return user if user==grouporuser
591 if @groupmap[grouporuser] 603 if @groupmap[grouporuser]
592 @groupmap[grouporuser]['members'].grep(user)[0] && 604 @groupmap[grouporuser]['members'].grep(user)[0] &&
1352 maildomain=gentei.org 1364 maildomain=gentei.org
1353 1365
1354 And then prepare .qmail-$mailprefix-default file as below. 1366 And then prepare .qmail-$mailprefix-default file as below.
1355 | ./#{@myname} -list"], 1367 | ./#{@myname} -list"],
1356 'sendall_head' => ['「%s」宛のメイル送信', "Send message to `%s'"], 1368 'sendall_head' => ['「%s」宛のメイル送信', "Send message to `%s'"],
1369 'sendmem_head' => ['「%s」さん宛のメイル送信', "Send message to `%s'"],
1357 'sendall_note' => ['メンバーへの連絡だけでなく、グループ非加入者がこれから加入する旨の通知などにも有用。', 1370 'sendall_note' => ['メンバーへの連絡だけでなく、グループ非加入者がこれから加入する旨の通知などにも有用。',
1358 "Send this message to all of group."], 1371 "Send this message to all of group."],
1359 'sendall_done' => ['送信完了', "sending message done"], 1372 'sendall_done' => ['送信完了', "sending message done"],
1360 'body' => ['本文', 'Body'], 1373 'body' => ['本文', 'Body'],
1361 'rcptto' => ['宛先', 'Recipients'], 1374 'rcptto' => ['宛先', 'Recipients'],
1387 'aboutgroup' => ['グループ %s の操作', "Operations on group `%s'"], 1400 'aboutgroup' => ['グループ %s の操作', "Operations on group `%s'"],
1388 'groupwarn' => ['自分が参加してないグループAに、自分が参加しているグループBが含まれている場合、グループAにも加入していると見なされるので気をつけよう。管理者はグループのニックネームを変えられるよ。', 1401 'groupwarn' => ['自分が参加してないグループAに、自分が参加しているグループBが含まれている場合、グループAにも加入していると見なされるので気をつけよう。管理者はグループのニックネームを変えられるよ。',
1389 'Though you are not member of group A, you are treated as a member of A, if you join to the group B, which is a member of A. Think the nesting of groups carefully, please. Group administrator can change the group nickname.'], 1402 'Though you are not member of group A, you are treated as a member of A, if you join to the group B, which is a member of A. Think the nesting of groups carefully, please. Group administrator can change the group nickname.'],
1390 'address2send' => ['自分が参加しているグループのメンバーリストの先頭が自分。その直後にある入力欄には、そのML宛メッセージをどの宛先に配送するかを入れられる。そう、MLごとに自分への配送先を変えられるよ。', 1403 'address2send' => ['自分が参加しているグループのメンバーリストの先頭が自分。その直後にある入力欄には、そのML宛メッセージをどの宛先に配送するかを入れられる。そう、MLごとに自分への配送先を変えられるよ。',
1391 'The first entry of member list of a group to which you belongs, is you. Entry box just after your name is for address list you want to deliver messages to that ML. Thus, you can define different addresses for each ML.'], 1404 'The first entry of member list of a group to which you belongs, is you. Entry box just after your name is for address list you want to deliver messages to that ML. Thus, you can define different addresses for each ML.'],
1405 'skip:' => ['MLへの送信専用メイルアドレスは、アドレスの前に空白入れずに skip: を付けて登録できるよ(例: skip:hoge@example.com。ML登録メンバーのみの投稿を許すMLに書いてエラーを食らったときには、投稿アドレスを skip: つきで登録しとくとええよ。', "You can prefix `skip:' without any blanks to email address to register POST-ONLY address for the ML(eg. skip:you@example.com). When you get rejecting message from ML which allows only members to post, try to add POST-ONLY address to your email addresses entry of that group."],
1392 'wholemembers' => ['グループ内グループを考慮した上で、現在グループ %s への通知は以下のメンバーに送られる。', 1406 'wholemembers' => ['グループ内グループを考慮した上で、現在グループ %s への通知は以下のメンバーに送られる。',
1393 "Consiering the groups registered in another group, notification to the group `%s' is send to members as follows."], 1407 "Consiering the groups registered in another group, notification to the group `%s' is send to members as follows."],
1394 'noadmingroup' => ['管理できるグループはないっす', 1408 'noadmingroup' => ['管理できるグループはないっす',
1395 "'There's no groups under your administration."], 1409 "'There's no groups under your administration."],
1396 'nickname' => ['ニックネーム', 'nickname'], 1410 'nickname' => ['ニックネーム', 'nickname'],
1681 open(seqfile, "r"){|s|s.gets.to_i+1} 1695 open(seqfile, "r"){|s|s.gets.to_i+1}
1682 : 1 1696 : 1
1683 end 1697 end
1684 def sendMail(to, subject, body, from=nil, rcptto=nil, header={}, 1698 def sendMail(to, subject, body, from=nil, rcptto=nil, header={},
1685 thru=nil, spoolto=false) 1699 thru=nil, spoolto=false)
1686 # rcptto should be an Array 1700 # rcptto should be an Array or nil
1687 body = NKF.nkf("-j", body) unless thru 1701 body = NKF.nkf("-j", body) unless thru
1688 subject = NKF.nkf("-jM", (subject||"No subject").strip) 1702 subject = NKF.nkf("-jM", (subject||"No subject").strip)
1689 to = safecopy(to) # cleanup tainted address 1703 to = safecopy(to) # cleanup tainted address
1690 subject.gsub!(/\n/, '') 1704 subject.gsub!(/\n/, '')
1705 rcptto.reject!{|i| /^(skip|off):/i =~ i} if rcptto.is_a?(Array)
1691 begin 1706 begin
1692 if (m=open("|-", "w")) 1707 if (m=open("|-", "w"))
1693 header.each do |h, v| 1708 header.each do |h, v|
1694 m.printf("%s: %s\n", h.strip, v.strip) 1709 m.printf("%s: %s\n", h.strip, v.strip)
1695 end 1710 end
2774 ret + hold + body 2789 ret + hold + body
2775 end 2790 end
2776 def extract_attachment(attachment) 2791 def extract_attachment(attachment)
2777 # Must return [text, href] strings to attached files 2792 # Must return [text, href] strings to attached files
2778 href = ""; text = "" 2793 href = ""; text = ""
2779 dir = @attachmentdir 2794 dir = @attachmentdir + Time.now.strftime("/%Y%m")
2780 if %r,(https?://[^/]+), =~ @opt['url'] 2795 if %r,(https?://[^/]+), =~ @opt['url']
2781 server = $1 2796 server = $1
2782 else 2797 else
2783 msg = "`url' not set in after5.cf" 2798 msg = "`url' not set in after5.cf"
2784 return [msg, msg] 2799 return [msg, msg]
2785 end 2800 end
2786 2801 kakasi = @opt['kakasi'] && @opt['kakasi']+" -Ha -Ka -Ja -Ea -ka"
2787 urlbase = sprintf("%s%s/%s", 2802 urlbase = sprintf("%s%s/%s",
2788 server, File.dirname(ENV['SCRIPT_NAME']), dir) 2803 server, File.dirname(ENV['SCRIPT_NAME']), dir)
2789 count=0 2804 count=0
2790 attachment.each {|a| 2805 attachment.each {|a|
2791 basename = safecopy(File.basename(a['filename'])) 2806 basename = safecopy(File.basename(a['filename']))
2792 filename = safecopy(dir+"/"+basename) 2807 encname = (kakasi ?
2808 IO.popen(kakasi, "r+") do |k|
2809 k.puts basename
2810 k.close_write # force flush
2811 k.gets.chomp.downcase
2812 end
2813 :
2814 basename
2815 ).gsub(/([^-_0-9a-z=,.@])/){"~"+$1.unpack("H*")[0].to_s}
2816 filename = safecopy(dir+"/"+encname)
2793 umask = File.umask(022) 2817 umask = File.umask(022)
2794 sz = a['value'].bytesize 2818 sz = a['value'].bytesize
2795 next if sz == 0 2819 next if sz == 0
2796 count += 1 2820 count += 1
2797 if sz > @attachmentmax 2821 if sz > @attachmentmax
2799 count, basename, sz/1024**2) 2823 count, basename, sz/1024**2)
2800 text += msg; href += msg 2824 text += msg; href += msg
2801 next 2825 next
2802 end 2826 end
2803 begin 2827 begin
2804 (test(?d, dir) && test(?w, dir)) or Dir.mkdir(dir) 2828 require 'fileutils'
2829 (test(?d, dir) && test(?w, dir)) or FileUtils.mkdir_p(dir)
2805 open(filename, "w") {|x| x.write a['value']} 2830 open(filename, "w") {|x| x.write a['value']}
2806 File.chmod(0664, filename) 2831 File.chmod(0664, filename)
2807 text += sprintf("%d: %s/%s\n", count, urlbase, basename) 2832 text += sprintf("%d: %s/%s\n", count, urlbase, encname)
2808 href += sprintf("%d: <a href=\"%s\">%s/%s</a>\n", 2833 href += sprintf("%d: <a href=\"%s\">%s/%s</a>\n",
2809 count, filename, urlbase, basename) 2834 count, filename, urlbase, encname)
2810 rescue 2835 rescue
2811 ensure 2836 ensure
2812 File.umask(umask) 2837 File.umask(umask)
2813 end 2838 end
2814 } 2839 }
2839 end 2864 end
2840 end 2865 end
2841 if viamail then 2866 if viamail then
2842 prohibitviahttp() 2867 prohibitviahttp()
2843 name = unquoted(ENV['DEFAULT']) 2868 name = unquoted(ENV['DEFAULT'])
2844 user = @sc.ismembersemail(ENV['SENDER']) 2869 user = @sc.ismembersemail(ENV['SENDER']) # should here be (,name)??
2845 if Regexp.new("(.*)("+Regexp.quote(@mailadmsuffix)+")") =~ name 2870 if Regexp.new("(.*)("+Regexp.quote(@mailadmsuffix)+")") =~ name
2846 # To: GROUP/adm*@domain 2871 # To: GROUP/adm*@domain
2847 # -> Forward to group administrator(s) 2872 # -> Forward to group administrator(s)
2848 name, toadmin = $1, $2 2873 name, toadmin = $1, $2
2849 sendMail("dummy", 'dummy', # Original To: and Subject: go through 2874 sendMail("dummy", 'dummy', # Original To: and Subject: go through
2881 @O.print @H.p("No such group: #{name}") 2906 @O.print @H.p("No such group: #{name}")
2882 return true 2907 return true
2883 end 2908 end
2884 nick = @sc.nickname(user) 2909 nick = @sc.nickname(user)
2885 from = sprintf("%s <%s>", nick, user) 2910 from = sprintf("%s <%s>", nick, user)
2886 subj = @params['subject'][0]['value'] || "Message from "+@myname 2911 subj = @params['subject'][0]['value'].toeuc || "Message from "+@myname
2887 body = @params['body'][0]['value'].gsub("\r", "").untaint 2912 body = @params['body'][0]['value'].gsub("\r", "").untaint
2888 # Extract attachment file 2913 # Extract attachment file
2889 if @params['attachment'].is_a?(Array) 2914 if @params['attachment'].is_a?(Array)
2890 body += (extract_report = extract_attachment(@params['attachment']))[0] 2915 body += (extract_report = extract_attachment(@params['attachment']))[0]
2891 end 2916 end
2983 # On mail mode, check if sender can send message to list. 3008 # On mail mode, check if sender can send message to list.
2984 if viamail && @sc.getgroupattr(name, 'limitsender') 3009 if viamail && @sc.getgroupattr(name, 'limitsender')
2985 s = ENV['SENDER'] 3010 s = ENV['SENDER']
2986 if !catch(:senderok) { 3011 if !catch(:senderok) {
2987 throw :senderok, true if rcpts.grep(s)[0] 3012 throw :senderok, true if rcpts.grep(s)[0]
2988 throw :senderok, true if @sc.ismembersemail(s) 3013 throw :senderok, true if @sc.ismembersemail(s, name)
2989 } 3014 }
2990 # sender is not allowed to send to ML 3015 # sender is not allowed to send to ML
2991 sendMail(s, "You are not allowed to send to this ML", 3016 sendMail(s, "You are not allowed to send to this ML",
2992 ("Before posting to this list(%s),\n"+ 3017 ("Before posting to this list(%s),\n"+
2993 "subscribe to %s") % [to, @opt['url']], 3018 "subscribe to %s") % [to, @opt['url']],
3001 header, 3026 header,
3002 ENV['SENDER'], 3027 ENV['SENDER'],
3003 spooling ? mldir : nil) 3028 spooling ? mldir : nil)
3004 if !viamail then 3029 if !viamail then
3005 @O.print @H.elementln("h1"){msg('sendall_done')} 3030 @O.print @H.elementln("h1"){msg('sendall_done')}
3006 @O.print @H.p(sprintf(msg('sendall_head'), 3031 @O.print @H.p(sprintf(msg(groupmode ? 'sendall_head' : 'sendmem_head'),
3007 nickname(name))+" "+msg('done')) 3032 nickname(name))+" "+msg('done'))
3008 @O.print @H.elementln("pre"){extract_report[1]} 3033 @O.print @H.elementln("pre"){extract_report[1].toeuc}
3009 link2home() 3034 link2home()
3010 @O.print footer() 3035 @O.print footer()
3011 return true 3036 return true
3012 end 3037 end
3013 exit 0 3038 exit 0
3310 } 3335 }
3311 }.join("\n") 3336 }.join("\n")
3312 } + \ 3337 } + \
3313 '' + \ 3338 '' + \
3314 @H.p(msg('address2send')) + \ 3339 @H.p(msg('address2send')) + \
3340 @H.p(msg('skip:')) + \
3315 @H.p(msg('groupwarn', 'shortnameplz')) + \ 3341 @H.p(msg('groupwarn', 'shortnameplz')) + \
3316 @H.submit_reset("GO") 3342 @H.submit_reset("GO")
3317 } # form 3343 } # form
3344 link2home()
3345 @O.print footer()
3318 end 3346 end
3319 def groupnamesString() 3347 def groupnamesString()
3320 @H.elementln("p", {'class'=>'listup'}){ 3348 @H.elementln("p", {'class'=>'listup'}){
3321 @sc.groups().collect{|g|@sc.groupname(g)}.join(", ") 3349 @sc.groups().collect{|g|@sc.groupname(g)}.join(", ")
3322 } 3350 }
4226 argument.has_key?(key=$2) or argument[key]=[] 4254 argument.has_key?(key=$2) or argument[key]=[]
4227 newvalue = Hash.new 4255 newvalue = Hash.new
4228 if /^Content.*filename=([\'\"])?(\S*)\1/i =~ unit 4256 if /^Content.*filename=([\'\"])?(\S*)\1/i =~ unit
4229 newvalue['filename'] = $2 4257 newvalue['filename'] = $2
4230 end 4258 end
4231 newvalue['value'] = unit.sub(/.*\r\n\r\n/m, "") 4259 newvalue['value'] = unit.sub(/.*?\r\n\r\n/m, "") # Shortest match
4232 if /^Content-type:\s*(\S*)/i =~ unit 4260 if /^Content-type:\s*(\S*)/i =~ unit
4233 newvalue['content-type'] = $1 4261 newvalue['content-type'] = $1
4234 else 4262 else
4235 newvalue['value'].gsub!("\r\n", "\n") 4263 newvalue['value'].gsub!("\r\n", "\n")
4236 end 4264 end

yatex.org