Mercurial > hgrepos > hgweb.cgi > after5
comparison after5.rb @ 85:e2b6a2e8b5c7 draft
Enable inter-member mail
Support attachment files
author | HIROSE Yuuji <yuuji@gentei.org> |
---|---|
date | Mon, 16 Dec 2013 10:41:21 +0900 |
parents | f67f5304baac |
children | 26c81703a80c |
comparison
equal
deleted
inserted
replaced
84:f67f5304baac | 85:e2b6a2e8b5c7 |
---|---|
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 Thu Dec 12 18:09:01 2013 on firestorm | 7 # Last modified Mon Dec 16 10:38:55 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_ |
60 def element(elt, attrs = nil, nl = nil) | 60 def element(elt, attrs = nil, nl = nil) |
61 attr = "" | 61 attr = "" |
62 lf = nl ? "\n" : "" | 62 lf = nl ? "\n" : "" |
63 if attrs.is_a?(Hash) | 63 if attrs.is_a?(Hash) |
64 for k in attrs.keys | 64 for k in attrs.keys |
65 attr += " %s=\"%s\"" % [k, attrs[k]] | 65 attr += " %s=\"%s\"" % [k, attrs[k]] |
66 end | 66 end |
67 end | 67 end |
68 body = yield | 68 body = yield |
69 sprintf "<%s%s>%s%s%s</%s>%s", elt, attr, lf, body, lf, elt, lf | 69 sprintf "<%s%s>%s%s%s</%s>%s", elt, attr, lf, body, lf, elt, lf |
70 end | 70 end |
1097 @myname='a5.cgi' if test(?f, "a5.cgi") | 1097 @myname='a5.cgi' if test(?f, "a5.cgi") |
1098 @conf = nil | 1098 @conf = nil |
1099 @schedulearea = {'rows'=>'4', 'cols'=>'60', 'name'=>'schedule'} | 1099 @schedulearea = {'rows'=>'4', 'cols'=>'60', 'name'=>'schedule'} |
1100 @oldagent = (%r,Mozilla/4, =~ ENV['HTTP_USER_AGENT']) | 1100 @oldagent = (%r,Mozilla/4, =~ ENV['HTTP_USER_AGENT']) |
1101 @lang = 0 | 1101 @lang = 0 |
1102 @mlbasedir = "ml" | |
1103 @attachmentdir = "a" | |
1104 @attachmentmax = 8*1024**2 | |
1102 @mailmode = nil | 1105 @mailmode = nil |
1103 @mailadmdelimiter = "/" | 1106 @mailadmdelimiter = "/" |
1104 @mailadmsuffix = @mailadmdelimiter + "adm" | 1107 @mailadmsuffix = @mailadmdelimiter + "adm" |
1105 @saveprefsregexp = /^(display(mode|days)$|nt|headline)/ | 1108 @saveprefsregexp = /^(display(mode|days)$|nt|headline)/ |
1106 @opt = { | 1109 @opt = { |
1353 'sendall_head' => ['「%s」宛のメイル送信', "Send message to `%s'"], | 1356 'sendall_head' => ['「%s」宛のメイル送信', "Send message to `%s'"], |
1354 'sendall_note' => ['メンバーへの連絡だけでなく、グループ非加入者がこれから加入する旨の通知などにも有用。', | 1357 'sendall_note' => ['メンバーへの連絡だけでなく、グループ非加入者がこれから加入する旨の通知などにも有用。', |
1355 "Send this message to all of group."], | 1358 "Send this message to all of group."], |
1356 'sendall_done' => ['送信完了', "sending message done"], | 1359 'sendall_done' => ['送信完了', "sending message done"], |
1357 'body' => ['本文', 'Body'], | 1360 'body' => ['本文', 'Body'], |
1361 'rcptto' => ['宛先', 'Recipients'], | |
1358 'member' => ['メンバー', 'Member'], | 1362 'member' => ['メンバー', 'Member'], |
1359 'personalmode' => ['自分のだけ表示モード', 'Display Personal Only'], | 1363 'personalmode' => ['自分のだけ表示モード', 'Display Personal Only'], |
1360 'normalmode' => ['全員分表示モード', "Display Everyone's"], | 1364 'normalmode' => ['全員分表示モード', "Display Everyone's"], |
1361 'display' => ['予定表示行: ', 'Display schedule of: '], | 1365 'display' => ['予定表示行: ', 'Display schedule of: '], |
1362 'nameonly' => ['名前のみ', 'Name Only'], | 1366 'nameonly' => ['名前のみ', 'Name Only'], |
1679 end | 1683 end |
1680 def sendMail(to, subject, body, from=nil, rcptto=nil, header={}, | 1684 def sendMail(to, subject, body, from=nil, rcptto=nil, header={}, |
1681 thru=nil, spoolto=false) | 1685 thru=nil, spoolto=false) |
1682 # rcptto should be an Array | 1686 # rcptto should be an Array |
1683 body = NKF.nkf("-j", body) unless thru | 1687 body = NKF.nkf("-j", body) unless thru |
1684 subject = NKF.nkf("-jM", subject.strip) | 1688 subject = NKF.nkf("-jM", (subject||"No subject").strip) |
1685 to = safecopy(to) # cleanup tainted address | 1689 to = safecopy(to) # cleanup tainted address |
1686 subject.gsub!(/\n/, '') | 1690 subject.gsub!(/\n/, '') |
1687 begin | 1691 begin |
1688 if (m=open("|-", "w")) | 1692 if (m=open("|-", "w")) |
1689 header.each do |h, v| | 1693 header.each do |h, v| |
1697 Content-Transfer-Encoding: 7bit | 1701 Content-Transfer-Encoding: 7bit |
1698 Content-Type: Text/Plain; charset=iso-2022-jp" | 1702 Content-Type: Text/Plain; charset=iso-2022-jp" |
1699 # m.puts "Date: #{Time.now.strftime("%a, %d %b %Y %T %z")}" | 1703 # m.puts "Date: #{Time.now.strftime("%a, %d %b %Y %T %z")}" |
1700 m.print "\n" | 1704 m.print "\n" |
1701 end | 1705 end |
1702 m.print body, "\n" | 1706 m.write body |
1703 m.close | 1707 m.close |
1704 else | 1708 else |
1705 # exec(@attr['mail'], "-s", subject, to) | 1709 # exec(@attr['mail'], "-s", subject, to) |
1706 recipient = rcptto || to.split(/,\s*|\s+/) | 1710 recipient = rcptto || to.split(/,\s*|\s+/) |
1707 #p recipient | 1711 #p recipient |
1721 if ENV['MAILCMD'] | 1725 if ENV['MAILCMD'] |
1722 #exec("qmail-inject", "yuuji@gentei.org", "yuuji@koeki-u.ac.jp") | 1726 #exec("qmail-inject", "yuuji@gentei.org", "yuuji@koeki-u.ac.jp") |
1723 open("/tmp/body", "w") {|w| w.print STDIN.readlines.join | 1727 open("/tmp/body", "w") {|w| w.print STDIN.readlines.join |
1724 w.puts "---" | 1728 w.puts "---" |
1725 w.puts recipient.join(",\n") | 1729 w.puts recipient.join(",\n") |
1730 w.puts header.inspect | |
1731 w.puts "ENV: #{ENV.inspect}" | |
1726 } | 1732 } |
1727 exit 0 | 1733 exit 0 |
1734 elsif header['Return-path'] && /-@/ =~ header['Return-path'] | |
1735 # if VERP is requested | |
1736 mailcmd = ENV['MAILCMD'] || @opt['sendmail'] | |
1737 contents = STDIN.readlines | |
1738 recipient.uniq.each {|r| | |
1739 local, domain = header['Return-path'].split("@") | |
1740 newlocal = local+r.sub("@", "=") | |
1741 verp = newlocal+"@"+domain | |
1742 verp = safecopy(verp) | |
1743 open("| #{mailcmd} -f#{verp} -- #{r}", "w") {|m| | |
1744 m.write contents.join | |
1745 } | |
1746 } | |
1728 else | 1747 else |
1729 #recipient.unshift "-f"+header['return-path'] if header['return-path'] | 1748 recipient.unshift "-f"+header['Return-path'] if header['Return-path'] |
1730 exec(ENV['MAILCMD'] || @opt['sendmail'], *recipient) | 1749 exec(ENV['MAILCMD'] || @opt['sendmail'], *recipient) |
1731 end | 1750 end |
1732 end | 1751 end |
1733 exit 0; | 1752 exit 0; |
1734 end | 1753 end |
2720 hold = [] | 2739 hold = [] |
2721 ret = [] | 2740 ret = [] |
2722 skip = false | 2741 skip = false |
2723 while line = body.shift | 2742 while line = body.shift |
2724 case line.toeuc | 2743 case line.toeuc |
2725 when /^$/ | 2744 # #Below does not work correctly when (from|subject): is final line |
2726 hold << "\n" | 2745 # when /^$/ |
2727 break | 2746 # hold << "\n" |
2728 ## when /^(subject|from): /i | 2747 # break |
2729 when /^(\S+): /i # if new header comes | 2748 # ## when /^(subject|from): /i |
2749 when /^(\S+): /i, /^$/ # if new header comes or header ends | |
2730 if /^subject:/i =~ hold[0] # check previous header in hold space | 2750 if /^subject:/i =~ hold[0] # check previous header in hold space |
2731 sj = hold.join.toeuc.sub("Subject: ", "").gsub(tag, "").strip | 2751 sj = hold.join.toeuc.sub("Subject: ", "").gsub(tag, "").strip |
2732 removeregexp && sj && sj.gsub!(removeregexp, "") | 2752 removeregexp && sj && sj.gsub!(removeregexp, "") |
2733 sj = sj.sub(/^(re: *)+/i, "Re: ").gsub("\n", "") | 2753 sj = sj.sub(/^(re: *)+/i, "Re: ").gsub("\n", "") |
2734 hold = ["Subject: "+NKF.nkf('-jM', tag+" "+sj).strip+"\n"] | 2754 hold = ["Subject: "+NKF.nkf('-jM', tag+" "+sj).strip+"\n"] |
2735 elsif /^from/i =~ hold[0] && fromhack.is_a?(String) | 2755 elsif /^from/i =~ hold[0] && fromhack.is_a?(String) |
2736 from = hold.join.toeuc.sub(/From: */i, "").strip | 2756 from = hold.join.toeuc.sub(/From: */i, "").strip |
2737 email, comment = parseaddress(from) | 2757 email, comment = parseaddress(from) |
2738 if (!comment || comment=="") && comment = @sc.ismembersemail(email) | 2758 if (!comment || comment=="") && comment = @sc.ismembersemail(email) |
2739 # Reverse conversion of uname<->email | 2759 # Reverse conversion of uname<->email |
2740 comment = @sc.nickname(comment) || "" | 2760 comment = @sc.nickname(comment) || "whoareyou" |
2741 end | 2761 end |
2742 hold = ["From: "+rewritefrom(email, comment, fromhack)+"\n"] | 2762 hold = ["From: "+rewritefrom(email, comment, fromhack)+"\n"] |
2763 end | |
2764 if /^$/ =~ line.toeuc | |
2765 hold << line | |
2766 break | |
2743 end | 2767 end |
2744 ret += hold | 2768 ret += hold |
2745 hold = [line] | 2769 hold = [line] |
2746 when /^\s/ # continued line | 2770 when /^\s/ # continued line |
2747 hold << line | 2771 hold << line |
2748 end | 2772 end |
2749 end | 2773 end |
2750 ret + hold + body | 2774 ret + hold + body |
2751 end | 2775 end |
2776 def extract_attachment(attachment) | |
2777 # Must return [text, href] strings to attached files | |
2778 href = ""; text = "" | |
2779 dir = @attachmentdir | |
2780 if %r,(https?://[^/]+), =~ @opt['url'] | |
2781 server = $1 | |
2782 else | |
2783 msg = "`url' not set in after5.cf" | |
2784 return [msg, msg] | |
2785 end | |
2786 | |
2787 urlbase = sprintf("%s%s/%s", | |
2788 server, File.dirname(ENV['SCRIPT_NAME']), dir) | |
2789 count=0 | |
2790 attachment.each {|a| | |
2791 basename = safecopy(File.basename(a['filename'])) | |
2792 filename = safecopy(dir+"/"+basename) | |
2793 umask = File.umask(022) | |
2794 sz = a['value'].bytesize | |
2795 next if sz == 0 | |
2796 count += 1 | |
2797 if sz > @attachmentmax | |
2798 msg = sprintf("%d: %s is too large(%dMB), skipped\n", | |
2799 count, basename, sz/1024**2) | |
2800 text += msg; href += msg | |
2801 next | |
2802 end | |
2803 begin | |
2804 (test(?d, dir) && test(?w, dir)) or Dir.mkdir(dir) | |
2805 open(filename, "w") {|x| x.write a['value']} | |
2806 File.chmod(0664, filename) | |
2807 text += sprintf("%d: %s/%s\n", count, urlbase, basename) | |
2808 href += sprintf("%d: <a href=\"%s\">%s/%s</a>\n", | |
2809 count, filename, urlbase, basename) | |
2810 rescue | |
2811 ensure | |
2812 File.umask(umask) | |
2813 end | |
2814 } | |
2815 if count>0 | |
2816 text="\n\n[[Attached files below]]\n"+text | |
2817 href="[[Attached files]]\n"+href | |
2818 end | |
2819 [text.chomp, href.chomp] | |
2820 end | |
2752 def defaultmladdress(name) | 2821 def defaultmladdress(name) |
2753 prefix = (@opt['mailprefix'] || "") | 2822 prefix = (@opt['mailprefix'] || "") |
2754 dash = prefix > '' ? "-" : "" | 2823 dash = prefix > '' ? "-" : "" |
2755 sprintf("%s%s%s@%s", prefix, dash, name, @opt['maildomain']) | 2824 sprintf("%s%s%s@%s", prefix, dash, name, @opt['maildomain']) |
2756 end | 2825 end |
2757 def list() | 2826 def list() |
2758 # For debug: | 2827 # For debug: |
2759 # LOCAL=1 DEFAULT=name ./after5.rb -list | 2828 # LOCAL=1 DEFAULT=name ./after5.rb -list |
2760 # $DEFAULT is ML name | 2829 # $DEFAULT is ML name |
2761 viamail = ENV['LOCAL'] && ENV['DEFAULT'] # called via mail | 2830 viamail = ENV['LOCAL'] && ENV['DEFAULT'] # called via mail |
2762 from = toadmin = groupmode = fromhack = nil | 2831 from = toadmin = groupmode = fromhack = extract_report = nil |
2763 unless @opt['mailprefix'] && @opt['maildomain'] | 2832 unless @opt['mailprefix'] && @opt['maildomain'] |
2764 if viamail | 2833 if viamail |
2765 STDERR.print msg('sendall_err') % [@opt['conf']] | 2834 STDERR.print msg('sendall_err') % [@opt['conf']] |
2766 exit 0 | 2835 exit 0 |
2767 else | 2836 else |
2770 end | 2839 end |
2771 end | 2840 end |
2772 if viamail then | 2841 if viamail then |
2773 prohibitviahttp() | 2842 prohibitviahttp() |
2774 name = unquoted(ENV['DEFAULT']) | 2843 name = unquoted(ENV['DEFAULT']) |
2844 user = @sc.ismembersemail(ENV['SENDER']) | |
2775 if Regexp.new("(.*)("+Regexp.quote(@mailadmsuffix)+")") =~ name | 2845 if Regexp.new("(.*)("+Regexp.quote(@mailadmsuffix)+")") =~ name |
2776 # To: GROUP/adm*@domain | 2846 # To: GROUP/adm*@domain |
2777 # -> Forward to group administrator(s) | 2847 # -> Forward to group administrator(s) |
2778 name, toadmin = $1, $2 | 2848 name, toadmin = $1, $2 |
2779 sendMail("dummy", 'dummy', # Original To: and Subject: go through | 2849 sendMail("dummy", 'dummy', # Original To: and Subject: go through |
2796 "> "+STDIN.readlines.join("> ")) | 2866 "> "+STDIN.readlines.join("> ")) |
2797 exit 0 # should exit 0 in mail mode | 2867 exit 0 # should exit 0 in mail mode |
2798 end | 2868 end |
2799 else # via http | 2869 else # via http |
2800 return nil unless checkauth | 2870 return nil unless checkauth |
2801 name = unquoted(@params['name'].untaint) | 2871 # HERE CGI Params name, subject, attachment and body |
2872 # comes with enctype=multipart/form-data, | |
2873 # So we get them via Array | |
2874 name = unquoted(@params['name'][0]['value'].untaint) | |
2875 user = @params['user'] | |
2802 if @sc.isuser(name) | 2876 if @sc.isuser(name) |
2803 # groupmode = nil | 2877 # groupmode = nil |
2804 elsif grepgroup(name) | 2878 elsif grepgroup(name) |
2805 groupmode = true | 2879 groupmode = true |
2806 else | 2880 else |
2807 @O.print @H.p("No such group: #{name}") | 2881 @O.print @H.p("No such group: #{name}") |
2808 return true | 2882 return true |
2809 end | 2883 end |
2810 nick = @sc.nickname(@params['user']) | 2884 nick = @sc.nickname(user) |
2811 from = sprintf("%s <%s>", nick, @params['user']) | 2885 from = sprintf("%s <%s>", nick, user) |
2812 body = @params['body'].gsub("\r", "").untaint | 2886 subj = @params['subject'][0]['value'] || "Message from "+@myname |
2813 end | 2887 body = @params['body'][0]['value'].gsub("\r", "").untaint |
2814 | 2888 # Extract attachment file |
2889 if @params['attachment'].is_a?(Array) | |
2890 body += (extract_report = extract_attachment(@params['attachment']))[0] | |
2891 end | |
2892 end | |
2893 # Variables here | |
2894 # name: Destination group/user name | |
2895 # user: Member account or nil(not member) | |
2896 | |
2815 # Set values for header rewriting | 2897 # Set values for header rewriting |
2898 # We have to setup these variables: | |
2899 # to: Header To: | |
2900 # subj: Header Subject: | |
2901 # from: Header From: | |
2902 # rcpts: Array of recipients addresses | |
2903 # header: Hash of additional header values | |
2904 # body: String of mail body | |
2905 # spooling: Flag if spool ML files nor not | |
2906 # mldir: spooling directory name | |
2816 if groupmode # Run as ML | 2907 if groupmode # Run as ML |
2908 # To: should be ML address | |
2909 # Return-path: should be verp of PREFIX-RCPT@DOMAIN | |
2817 bracket = @sc.getgroupattr(name, 'subjtag') || @opt['mailbracket'] | 2910 bracket = @sc.getgroupattr(name, 'subjtag') || @opt['mailbracket'] |
2818 xmlname = @sc.getgroupattr(name, 'xmlname') || name | 2911 xmlname = @sc.getgroupattr(name, 'xmlname') || name |
2819 mldir = "ml/"+name | 2912 mldir = @mlbasedir+"/"+name |
2820 to = @sc.getgroupattr(name, 'mladdress') || defaultmladdress(name) | 2913 to = @sc.getgroupattr(name, 'mladdress') || defaultmladdress(name) |
2821 if @sc.getgroupattr(name, 'fromhack') | 2914 if @sc.getgroupattr(name, 'fromhack') |
2822 fromhack = to | 2915 fromhack = to |
2823 end | 2916 end |
2824 spooling = @opt['mlspooling'] | 2917 spooling = @opt['mlspooling'] |
2918 returnpath = to.sub("@", @mailadmsuffix+"-@") | |
2825 else # Run as p2p mail | 2919 else # Run as p2p mail |
2826 bracket = "NONE" # Throught Subject | 2920 # To: should be Destination user name |
2827 user = @params['user'] || ENV['SENDER'] | 2921 # Return-path: should be PREFIX-USER@DOMAIN or $SENDER(not member) |
2828 if @sc.ismembersemail(user) | 2922 bracket = "NONE" # Through Subject |
2829 sender = defaultmladdress(quoted(user)) | 2923 if user |
2924 returnpath = defaultmladdress(quoted(user)) | |
2830 else | 2925 else |
2831 sender = user | 2926 returnpath = ENV['SENDER'] |
2832 end | 2927 end |
2833 ###fromhack = sprintf("%s <%s>", nick, sender) | 2928 ###fromhack = sprintf("%s <%s>", nick, sender) |
2834 fromhack = sender | 2929 fromhack = returnpath |
2835 | 2930 |
2836 xmlname = name | 2931 xmlname = name |
2837 to = name | 2932 to = name |
2838 spooling = mldir = nil | 2933 spooling = mldir = nil |
2839 end | 2934 end |
2840 returnpath = to.sub("@", @mailadmsuffix+"-@") | |
2841 adminaddr = to.sub("@", @mailadmsuffix+"@") | 2935 adminaddr = to.sub("@", @mailadmsuffix+"@") |
2842 subj = @params['subject'] || "Message from "+@myname | |
2843 if bracket == "NONE" | 2936 if bracket == "NONE" |
2844 sjtag = "" | 2937 sjtag = "" |
2845 tagre = nil | 2938 tagre = nil |
2846 else | 2939 else |
2847 sjtag = bracket.gsub("%n", nickname(name)). | 2940 sjtag = bracket.gsub("%n", nickname(name)). |
2850 tagpt = Regexp.quote(bracket). # compute bracket pattern | 2943 tagpt = Regexp.quote(bracket). # compute bracket pattern |
2851 gsub("%n", Regexp.quote(nickname(name))). | 2944 gsub("%n", Regexp.quote(nickname(name))). |
2852 gsub("%i", Regexp.quote(name)). | 2945 gsub("%i", Regexp.quote(name)). |
2853 gsub(/%(\d*)c/, '\d+') | 2946 gsub(/%(\d*)c/, '\d+') |
2854 tagre = Regexp.new(tagpt) | 2947 tagre = Regexp.new(tagpt) |
2855 subj = sjtag.strip+" "+subj.gsub(Regexp.new(tagpt), "") | 2948 if !viamail |
2949 subj = sjtag.strip+" "+subj.gsub(Regexp.new(tagpt), "") | |
2950 end | |
2856 end | 2951 end |
2857 if viamail then | 2952 if viamail then |
2858 body = tagify_subj(STDIN.readlines, sjtag, tagre, fromhack).join | 2953 body = tagify_subj(STDIN.readlines, sjtag, tagre, fromhack).join |
2859 elsif fromhack # via http | 2954 elsif fromhack # via http |
2860 from = rewritefrom(@params['user'], nick, groupmode ? to : sender) | 2955 from = rewritefrom(user, nick, groupmode ? to : returnpath) |
2861 end | 2956 end |
2862 header = { | 2957 header = { |
2863 "X-ML-Driver" => ($hgid || @myname), | 2958 "X-ML-Driver" => ($hgid || @myname), |
2864 "X-ML-Driver-URI" => $myurl, | 2959 "X-ML-Driver-URI" => $myurl, |
2960 "Return-path" => returnpath | |
2865 } | 2961 } |
2866 if groupmode | 2962 if groupmode |
2867 header["Reply-to"] = to | 2963 header["Reply-to"] = to |
2868 header["X-ML-Name"] = xmlname | 2964 header["X-ML-Name"] = xmlname |
2869 header["X-ML-URI"] = sprintf("%s?-groupman+%s", @opt['url'], name) | 2965 header["X-ML-URI"] = sprintf("%s?-groupman+%s", @opt['url'], name) |
2870 header["Return-path"] = returnpath | |
2871 end | 2966 end |
2872 Dir.chdir @mydir | 2967 Dir.chdir @mydir |
2873 if groupmode | 2968 if groupmode # (#includeself) |
2874 rcpts = if grepgroup(name) | 2969 rcpts = if viamail |
2875 @sc.members(name) | 2970 @sc.members(name) |
2876 else | 2971 else |
2877 [name] | 2972 @sc.members(name) + [user] |
2878 end.collect {|u| mailaddress(u, name).split(/,\s*|\s+/)}.flatten | 2973 end.collect {|u| |
2974 mailaddress(u, name).split(/,\s*|\s+/)}.flatten.uniq | |
2879 else | 2975 else |
2880 rcpts = @sc.mailaddress(name).split(/,\s*|\s+/).flatten | 2976 rcpts = @sc.mailaddress(name).split(/,\s*|\s+/).flatten |
2881 rcpts += @sc.mailaddress(user).split(/,\s*|\s+/).flatten # +sender | 2977 rcpts += @sc.mailaddress(user).split(/,\s*|\s+/).flatten # +sender |
2882 end | 2978 end |
2883 ENV["QMAILINJECT"] = "r" # for ML mode, use verp | 2979 # ENV["QMAILINJECT"] = "r" # for ML mode, use verp |
2884 # | 2980 # For vodafone, QMAILINJECT=r doesn't work correctly |
2885 # On mail mode, check if sender can send message to list. | 2981 # On mail mode, check if sender can send message to list. |
2886 if viamail && @sc.getgroupattr(name, 'limitsender') | 2982 if viamail && @sc.getgroupattr(name, 'limitsender') |
2887 s = ENV['SENDER'] | 2983 s = ENV['SENDER'] |
2888 if !catch(:senderok) { | 2984 if !catch(:senderok) { |
2889 throw :senderok, true if rcpts.grep(s)[0] | 2985 throw :senderok, true if rcpts.grep(s)[0] |
2905 spooling ? mldir : nil) | 3001 spooling ? mldir : nil) |
2906 if !viamail then | 3002 if !viamail then |
2907 @O.print @H.elementln("h1"){msg('sendall_done')} | 3003 @O.print @H.elementln("h1"){msg('sendall_done')} |
2908 @O.print @H.p(sprintf(msg('sendall_head'), | 3004 @O.print @H.p(sprintf(msg('sendall_head'), |
2909 nickname(name))+" "+msg('done')) | 3005 nickname(name))+" "+msg('done')) |
3006 @O.print @H.elementln("pre"){extract_report[1]} | |
2910 link2home() | 3007 link2home() |
2911 @O.print footer() | 3008 @O.print footer() |
2912 return true | 3009 return true |
2913 end | 3010 end |
2914 exit 0 | 3011 exit 0 |
2928 @mybase+' '+msg('sendall').sub("<br>", " ") | 3025 @mybase+' '+msg('sendall').sub("<br>", " ") |
2929 } | 3026 } |
2930 @O.print @H.elementln("h2") { | 3027 @O.print @H.elementln("h2") { |
2931 sprintf(msg('sendall_head'), nickname(name)) | 3028 sprintf(msg('sendall_head'), nickname(name)) |
2932 } | 3029 } |
2933 list = groupmode ? @sc.members(name) : [name, user] | 3030 if groupmode # (#includeself) |
2934 @O.print @H.p(sprintf("%s: %s", msg('member'), | 3031 list = @sc.members(name) # +user |
3032 else | |
3033 list = [name, user] | |
3034 end | |
3035 @O.print @H.p(sprintf("%s: %s", msg('rcptto'), | |
2935 list.collect {|u| | 3036 list.collect {|u| |
2936 @H.element("abbr", "title"=>u){ | 3037 @H.element("abbr", "title"=>u){ |
2937 @sc.nickname(u) | 3038 @sc.nickname(u) |
2938 } | 3039 } |
2939 }.join(",\n"))) | 3040 }.join(",\n"))) |
2940 @O.print @H.p(sprintf("(total %d)", list.length))+"\n" | 3041 @O.print @H.p(sprintf("(total %d)", list.length))+"\n" |
2941 @O.print \ | 3042 @O.print \ |
2942 @H.elementln("form", {'action' => @myname+'?-list', 'method'=>"POST"}) { | 3043 @H.elementln("form", { |
3044 'action' => @myname+'?-list', 'method'=>"POST", | |
3045 'enctype' => "multipart/form-data"}) { | |
2943 @H.elementln("table"){ | 3046 @H.elementln("table"){ |
3047 @H.elementln("tr"){ | |
3048 @H.element("td"){"To"} + \ | |
3049 @H.element("td"){ | |
3050 @H.element("code"){ | |
3051 groupmode ? defaultmladdress(quoted(name)) : @sc.nickname(name) | |
3052 } | |
3053 } | |
3054 } + \ | |
2944 @H.elementln("tr"){ | 3055 @H.elementln("tr"){ |
2945 @H.element("td"){"Subject"} + \ | 3056 @H.element("td"){"Subject"} + \ |
2946 @H.element("td"){ | 3057 @H.element("td"){ |
2947 @H.text("subject", "", 40, 128) | 3058 @H.text("subject", "", 40, 128) |
3059 } | |
3060 } + \ | |
3061 @H.elementln("tr"){ | |
3062 @H.element("td"){"Attachment"} + \ | |
3063 @H.element("td"){ | |
3064 @H.element("input", "name"=>"attachment", "type"=>"file", 'multiple'=>true){} | |
2948 } | 3065 } |
2949 } + \ | 3066 } + \ |
2950 @H.elementln("tr"){ | 3067 @H.elementln("tr"){ |
2951 @H.element("td"){ | 3068 @H.element("td"){ |
2952 msg('body') | 3069 msg('body') |
4097 query = ENV["QUERY_STRING"] | 4214 query = ENV["QUERY_STRING"] |
4098 else # executed from command line | 4215 else # executed from command line |
4099 query = ARGV.join("&") | 4216 query = ARGV.join("&") |
4100 end | 4217 end |
4101 | 4218 |
4102 for unit in query.split(/\&/) | 4219 if ENV['CONTENT_TYPE'] && |
4103 if /^([a-z][-_0-9@%a-z.]*)=(.*)/i =~ unit | 4220 %r,multipart/form-data.*boundary=(.*),i =~ ENV['CONTENT_TYPE'] |
4104 key, value = $1, $2 | 4221 boundary = $1 |
4105 #value.gsub!(/%(..)/){[$1.hex].pack("c")} # これでURLデコードが一発 | 4222 query.split("\r\n--"+boundary).each {|unit| |
4106 decode!(value) | 4223 if /Content-Disposition.*\bname=([\'\"])?(\S*)\1/i =~ unit |
4107 decode!(key) | 4224 argument.has_key?(key=$2) or argument[key]=[] |
4108 value = Kconv::toeuc(value) # EUCに変換 | 4225 newvalue = Hash.new |
4109 printf "[%s] = %s\n", key, value if $DEBUG | 4226 if /^Content.*filename=([\'\"])?(\S*)\1/i =~ unit |
4110 argument[key] = value | 4227 newvalue['filename'] = $2 |
4228 end | |
4229 newvalue['value'] = unit.sub(/.*\r\n\r\n/m, "") | |
4230 if /^Content-type:\s*(\S*)/i =~ unit | |
4231 newvalue['content-type'] = $1 | |
4232 else | |
4233 newvalue['value'].gsub!("\r\n", "\n") | |
4234 end | |
4235 argument[key] << newvalue | |
4236 end | |
4237 } | |
4238 if $DEBUG | |
4239 open("/tmp/body", "w"){|x| | |
4240 x.write query.split("\r\n--"+boundary+"\r\n")[-1] | |
4241 argument.each{|k,v| | |
4242 x.printf(" %s => %s\n", k.inspect, v.inspect)} | |
4243 x.printf("boundary=\n%s\n",boundary) | |
4244 x.printf("ENV=%s\n",ENV.inspect) | |
4245 x.write query} | |
4246 end | |
4247 else | |
4248 for unit in query.split(/\&/) | |
4249 if /^([a-z][-_0-9@%a-z.]*)=(.*)/i =~ unit | |
4250 key, value = $1, $2 | |
4251 #value.gsub!(/%(..)/){[$1.hex].pack("c")} # これでURLデコードが一発 | |
4252 decode!(value) | |
4253 decode!(key) | |
4254 value = Kconv::toeuc(value) # EUCに変換 | |
4255 printf "[%s] = %s\n", key, value if $DEBUG | |
4256 argument[key] = value | |
4257 end | |
4111 end | 4258 end |
4112 end | 4259 end |
4113 argument | 4260 argument |
4114 end | 4261 end |
4115 def getcookie() | 4262 def getcookie() |