Mercurial > hgrepos > hgweb.cgi > after5
changeset 14:9aa45b698d56 draft
RCS-revision 1.15
date: 2007/04/28 01:21:33; author: yuuji; state: Exp; lines: +425 -44
decode schedule text
author | HIROSE Yuuji <yuuji@gentei.org> |
---|---|
date | Sat, 28 Apr 2007 01:21:33 +0859 |
parents | d2c36cb4206a |
children | 580c1b0fa27e |
files | after5.rb |
diffstat | 1 files changed, 425 insertions(+), 44 deletions(-) [+] |
line wrap: on
line diff
--- a/after5.rb Sat Apr 10 17:07:31 2004 +0859 +++ b/after5.rb Sat Apr 28 01:21:33 2007 +0859 @@ -1,9 +1,9 @@ #!/usr/local/bin/ruby # # Associative Scheduling Table - after5 -# (C)2003, 2004 by HIROSE Yuuji [yuuji@gentei.org] -# $Id: after5.rb,v 1.14 2004/04/10 17:07:31 yuuji Exp $ -# Last modified Sun Apr 11 02:07:17 2004 on firestorm +# (C)2003, 2004, 2006 by HIROSE Yuuji [yuuji@gentei.org] +# $Id: after5.rb,v 1.15 2007/04/28 01:21:33 yuuji Exp $ +# Last modified Sat Apr 28 10:19:45 2007 on firestorm # See http://www.gentei.org/~yuuji/software/after5/ # このスクリプトはEUCで保存してください。 @@ -121,6 +121,96 @@ "\n</select>\n" end end +class TEXTout + def isBlock(elt) + /\b(tr|[udo]l|p|div)\b/i =~ elt + end + def isEOC(elt) + /\bt[dh]\b/i =~ elt + end + def eoelem(elt) + r = "" + r << "\n" if isBlock(elt) + r << " " if isEOC(elt) + r + end + def contenttype(type = "text/plain", charset = $charset) + ### sprintf "Content-type: %s; charset=%s\n\n", type, charset + "" + end + def initialize(title = "Document") + @title = title + @eltstack = [] + end + def resetstack() + @eltstack = [] + end + def head(title = @title, css = "style.css") + sprintf <<__EOS__, title, css +===== [[[ %s ]]] ===== +__EOS__ + end + + def startelement(elt, attrs = {}, nl = true) + attr = "" + x = sprintf "%s", " "*@eltstack.length + @eltstack.push(elt) + x + end + def endelement(elt = nil, nl = true) + if elt + x = elt + @eltstack.pop + else + x = @eltstack.pop + end + eoelem(x) + end + def element(elt, attrs = nil, nl = nil) + attr = "" + lf = nl ? "\n" : "" + body = yield + #sprintf "<%s%s>%s%s%s</%s>%s", elt, attr, lf, body, lf, elt, lf + sprintf "%s%s", body, eoelem(elt) + end + def elementln(elt, attr=nil) + body = yield + sprintf "%s\n", body + end + def a(href, anchor = nil, attrs = {}) + attr = attrs + attr['href'] = href + # sprintf "%s\n", href + anchor + end + def p(msg, attrs=nil) + element("p", attrs){msg} + end + def text(name, value='', size=nil, maxlength=nil) + "" + end + def hidden(name, value='') + "" + end + def radio(name, value, text='', checked=nil) + "" + end + def checkbox(name, value, text='', checked=nil) + "" + end + def submit(name, value, text='') + "" + end + def reset(name, value, text='') + "" + end + def submit_reset(name) + "" + end + def select(name, range, selected=nil) + "" + end +end class PasswdMgr def initialize(name, mode=0640) @@ -924,6 +1014,7 @@ @schedulearea = {'rows'=>'4', 'cols'=>'60', 'name'=>'schedule'} @oldagent = (%r,Mozilla/4, =~ ENV['HTTP_USER_AGENT']) @lang = 0 + @mailmode = nil @saveprefsregexp = /^(display(mode|days)$|nt|headline)/ @opt = { 'conf' => @mybase+".cf", @@ -1007,7 +1098,7 @@ # @job is here @O.print @H.startelement("body", bodyclass, true) @O.print @H.endelement(nil, true) # body - @O.print "</html>\n" # html + @O.print @H.endelement("html", true) # html setcookie() print @O.readlines @@ -1032,6 +1123,7 @@ 'addsched' => ['新規予定項目の登録', 'Register new schedule'], 'defthisday' => ['デフォルトの日付はこの日になってま', ''], '24hour' => ['24時間制4桁でね<br>(0000〜2359)<br>%sは時刻指定なし', 'in 24-hour<br>(0000-2359)<br>%s for whole day'], + '24hourtxt' => ['24時間制4桁でね(0000〜2359), %sは時刻指定なし', 'in 24-hour(0000-2359), %s for whole day'], 'reqnotify' => ['通知メイルいるけ?', 'Previous notification'], 'rightnow' => ['登録時にすぐ', 'Right now on registration'], 'immediatenote' => ['に以下の予定を登録しました', @@ -1068,6 +1160,8 @@ 'join' => ['参加', 'join'], 'regist' => ['登録', 'register'], 'remove' => ['削除', 'remove'], + 'move' => ['移動', 'move'], + 'newdate' => ['移動先時刻', 'New date'], 'deletion' => ['完全消去', 'deletion'], 'deletionwarn' => ['OK押したら即消去。確認とらないぞ', 'Hitting OK immediately delets this group, be carefully!'], @@ -1150,7 +1244,18 @@ 'nicknamenote' => ['ニックネームを消去するとデフォルト名になりんす.', 'Default name is displayed if you remove nickname.'], 'nothingtodo' => ['って何もやることあらへんかったで', - 'Nothing to do for this transaction.'] + 'Nothing to do for this transaction.'], + 'schedlist' => [' and %d days Schedule list', + 'から%d日間の予定一覧'], + 'nothing' => ['なんもないす', 'Nothing'], + 'sessionpswd' => ['セッションパスワード(これはいじらないでね)', + 'Session Password(Do not modify this)'], + 'date' => ['日付', 'Date'], + 'time' => ['時刻指定', 'Time'], + 'publicp' => ['公開=yes、非公開=no', 'Public?'], + 'neednotify' => ['通知メイル(要らないのは消してね)', + 'Leave lines for notification timing'], + 'schedulehere' => ['以下登録内容', 'Your Schedule below'] } end keyword.collect{|k| @@ -1193,10 +1298,17 @@ '%' + $1.unpack('H2' * $1.size).join('%').upcase end.tr(' ', '+') end + def purify(string) + string.gsub(/[\040-\177]/) {encode($&)} + end def decode!(string) string.gsub!(/\+/, ' ') string.gsub!(/%(..)/){[$1.hex].pack("c")} end + def decode(string) + string.gsub(/\+/, ' ') + string.gsub(/%(..)/){[$1.hex].pack("c")} + end def gencookie(name, a, expire) x = a.collect{|k, v| @@ -1250,8 +1362,14 @@ def webpage(user) @sc.getuserattr(user, "webpage") end + def checkauth_mail() + return true # temporary + end def checkauth() - auth = catch (:auth) { + if @mailmode && @params['sessionpw'] + return checkauth_mail + end + auth = catch(:auth) { unless @params['user'] outputError(@H.a(@myname, msg('loginfirst'))) throw :auth, nil @@ -1542,7 +1660,7 @@ if !s.empty? s.keys.sort.collect{|time| s[time].keys.sort.collect{|who| - text = s[time][who]['sched'] + text = decode(s[time][who]['sched']) topic = sprintf "%s%s", time == @opt['alldaydir'] ? '' : time+":", if personal @@ -1702,6 +1820,14 @@ @opt['tdskip'] end } + \ + @H.element("td"){ + if editable + @H.a(@myname+"?-move+#{date}/#{time}/#{who}", + msg('move')) + else + @opt['tdskip'] + end + } + \ @H.element("td"){s[time][who]['sched']} } }.join("\n") @@ -1717,6 +1843,45 @@ '' end end + def dayTextString(user, datestr, range, personal = nil) + r = '' + cols = 20 + header = "-" * cols + "\n" + + day = Time.mktime(*date2ymd(datestr)) + i = -1 + while (i+=1) < range + d = Time.at(day+i*3600*24) + date = sprintf("%04d/%02d/%02d", d.year, d.month, d.day) + datewn = sprintf("%s(%s)", date, @msg['wnames'][@lang][d.wday]) + s = @sc.day_all(date, user, personal) + next if s.empty? + + r << sprintf("TIME Who %s - What\n", datewn) + + for time in s.keys.sort + tstr = case time + when @opt['alldaydir'] + msg('allday') + else + sprintf "%02d:%02d", time.to_i/100, time.to_i%100 + end + r << s[time].keys.collect{|who| + editable = (user==who || @sc.ismember(user, who)) + groupp = grepgroup(who) + sprintf("%-5s %-10s %s", tstr, nickname(who), s[time][who]['sched']) + }.join("\n") + "\n" + end + r << "-" * cols + "\n" + end + footer = "That's all\n" + if r > '' + header + r + footer + else + '' + end + + end # # new form def displayRegistForm(date, multiple = true) @@ -1920,9 +2085,9 @@ return Time.at(base-rate*num) elsif /nt(\d+)d/ =~ symbol seconds = $1.to_i*3600*24 - targetday= Time.at(base-seconds).to_a - targetnight = - Time.mktime(*(targetday.indexes(5,4,3)+[@opt['night'].to_i])) + tday= Time.at(base-seconds) + target = [tday.year, tday.month, tday.day, @opt['night'].to_i] + targetnight = Time.mktime(*target) elsif "nttoday" == symbol Time.mktime(year.to_i, month.to_i, day.to_i, @opt['morning']) end @@ -1967,6 +2132,29 @@ end + def regulate_time(y, m, d, tm) + if tm > 2399 + sh, smin = 23, 59 + timedir=@opt['alldaydir'] + tmstr = msg('allday') + else + sh = (tm/100).to_i + smin = (tm%100).to_i + timedir = sprintf("%04d", tm) + tmstr = sprintf("%d:%02d", sh, smin) + end + time = nil + begin + time = Time.mktime(y, m, d, sh, smin) + rescue + outputError "%s<br>\nyear=%s<br>month=%s<br>day=%s<br>time=%s\n", + msg('invaliddate'), + @params['year'], @params['month'], @params['day'], @params['time'] + return nil + end + [time, timedir, tmstr] + end + # # add or remove a schedule # @@ -1992,25 +2180,8 @@ sm = @params['month'].to_i sd = @params['day'].to_i tm = @params['time'].to_i - if tm > 2399 - timedir=@opt['alldaydir'] - sh, smin = 23, 59 - tmstr = msg('allday') - else - sh = (tm/100).to_i - smin = (tm%100).to_i - timedir = sprintf("%04d", tm) - tmstr = sprintf("%d:%02d", sh, smin) - end - time = nil - begin - time = Time.mktime(sy, sm, sd, sh, smin) - rescue - outputError "%s<br>\nyear=%s<br>month=%s<br>day=%s<br>time=%s\n", - msg('invaliddate'), - @params['year'], @params['month'], @params['day'], @params['time'] - return nil - end + + time, timedir, tmstr = regulate_time(sy, sm, sd, tm) # # Check continuous schedule registration @@ -2054,6 +2225,7 @@ end begin (text = @params['schedule'].strip.gsub(/\r+\n/, $/)) << "\n" + text = purify(text) replace = (/modify/i =~ @params['editmode']) rc = @sc.register(registerer, y, m, d, timedir, text, replace) if @params['pub'] && /yes/ =~ @params['pub'] @@ -2090,18 +2262,26 @@ "-"*70) sendnotify(registerer, "Registration completed", header+text) end - show(sprintf("%04d/%02d/%02d", sy, sm, sd)) - @O.print "add_remove" if user == @author + unless @mailmode + show(sprintf("%04d/%02d/%02d", sy, sm, sd)) + @O.print "add_remove" if user == @author + end end # add def addsched() - add_remove(/remove/i =~ @params['editmode']) + if "move" == @params['editmode'] + add_remove(:remove) + for p in %w(year month day time) do + @params[p] = @params["new"+p] + end + end + add_remove(/^remove/i =~ @params['editmode']) end # # Display remove or modify screen - def remove_modify(datetime, remove) + def remove_modify(datetime, editmode) if !checkauth return nil end @@ -2127,7 +2307,7 @@ return nil end @O.print @H.elementln("h1"){ - sprintf "%s %s", datetime, remove ? msg('remove') : msg('modify') + sprintf "%s %s", datetime, msg(editmode) } @O.print @H.elementln("form", {'action'=>@myname+"?-addsched", 'method'=>'POST'}){ pubp=(@sc.getfile(user, y, m, d, time, 'pub').to_i > 0) @@ -2138,16 +2318,45 @@ "<input type=\"hidden\" name=\"month\" value=\"%02d\">\n" % m.to_i + \ "<input type=\"hidden\" name=\"day\" value=\"%02d\">\n" % d.to_i + \ "<input type=\"hidden\" name=\"time\" value=\"%04d\">\n" % time.to_i + \ - msg('reqnotify') + "<br>\n" + \ - @ntlist.collect{|nt, v| - cronp = @sc.getfile(user, y, m, d, time, nt) - sprintf "<input type=\"checkbox\" name=\"%s\"%s>%s \n", - nt, (cronp ? " checked" : ""), v - }.join + "<br>" + \ + if editmode=="move" + @H.elementln("table") { + @H.elementln("tr", {"colspan" => "2"}) {msg('newdate')} + \ + @H.elementln("tr") { + @H.element("th"){"Year"} + \ + @H.element("td"){@H.select("newyear", y.to_i..y.to_i+5, y)} + } + \ + @H.elementln("tr") { + @H.element("th"){"Month"} + \ + @H.element("td"){@H.select("newmonth", 1..12, m)} + } + \ + @H.elementln("tr") { + @H.element("th"){"Day"} + \ + @H.element("td"){@H.select("newday", 1..31, d)} + } + \ + @H.elementln("tr") { + @H.element("th"){"Time"} + \ + @H.element("td"){ + "<input type=text name=\"newtime\" value=\"#{time}\" " + \ + "size=\"8\" maxlength=\"4\">" + } + } + } + end.to_s + \ + @H.elementln("div", {"style" => + "visibility: " + + (editmode=="move" ? "hidden" : "show") + "\""}) { + msg('reqnotify') + "<br>\n" + \ + @ntlist.collect{|nt, v| + cronp = @sc.getfile(user, y, m, d, time, nt) + sprintf "<input type=\"checkbox\" name=\"%s\"%s>%s \n", + nt, (cronp ? " checked" : ""), v + }.join + "<br>" + } + \ @H.element("textarea", @schedulearea) {text} + "<br>" + \ @H.radio("editmode", "append", msg('append')) + ' / ' + \ - @H.radio("editmode", "modify", msg('modify'), !remove) + ' / ' + \ - @H.radio("editmode", "remove", msg('remove'), remove) + ' / ' + \ + @H.radio("editmode", "modify", msg('modify'), editmode=="modify")+' / '+\ + @H.radio("editmode", "remove", msg('remove'), editmode=="remove")+' / '+\ + @H.radio("editmode", "move", msg('move'), editmode=="move") + ' / ' + \ "<br>\n" + \ msg('publicok') + \ @H.radio("pub", "yes", msg('yes'), pubp) + \ @@ -2158,10 +2367,13 @@ @O.print "remove_modify" if user == @author end def remove(datetime) - remove_modify(datetime, true) + remove_modify(datetime, "remove") end def modify(datetime) - remove_modify(datetime, false) + remove_modify(datetime, "modify") + end + def move(datetime) + remove_modify(datetime, "move") end def prohibitviahttp() @@ -2839,6 +3051,168 @@ admgroup(newgroup) end + # + # Methods Related to viaMail functions + def gen_sessionpswd() + + end + def viamail_registform() + c = "# " + nl = "\n" + user = @params['user'] + msg('addsched') + "-" * 20 + nl*2 + \ + c + msg('user') + nl + \ + "user=" + user + nl*2 + \ + c + msg('sessionpswd') + nl + \ + "sp=hoge" + nl*2 + \ + c + msg('date') + nl + \ + "date="+Time.now.strftime("%Y/%m/%d") + nl*2 + \ + c + msg('time') + sprintf(msg('24hourtxt'), @opt['alldaydir']) + nl + \ + "time=3000"+nl*2 + \ + c + msg('publicp') + nl + \ + "public=yes" + nl*2 + \ + c + msg('neednotify') + nl + \ + "nt10m=yes (%s) +nttoday=yes (%s) +nt1d=yes (%s) +nt7d=yes (%s)" % ["10"+msg('minutes')+msg('before'), + msg('theday'), msg('precedingday'), + "7"+msg('days')+msg('before')] + nl*2 + \ + + c + msg('schedulehere') + end + def viamail_footer() + viamail_registform() + end + def show_by_text(date, days) + user = @params['user'] + personal = true + sched = dayTextString(user, date, days, personal) + # @O.print outstr + + sendMail(mailaddress(user), + "After5 Schedule", + @opt['url'] + "\n" + \ + Time.now.strftime("%Y/%m/%d") + \ + sprintf(msg('schedlist'), days) + "\n\n" + \ + if sched > '' + sched + else + msg('noplan')+"\n" + end + \ + viamail_footer + ) + + end + def parseHeader + contline=nil + header=Hash.new + text=Array.new + + field=nil + # header + while line=STDIN.gets + text << line + break if /^$/ =~ line + + if /^\s+/ =~ line + if field + header[field][-1] << line + end + else + if /^([^:]+):\s*(.*)/ =~ line + field=$1.downcase + header[field] or header[field] = [] + header[field] << $2 + end + end + end + header + end + def mail_regsched() + @params = Hash.new # Reset + + reqparams = %w[user sp date time public] + otherparams = %w[nt10m nttoday nt1d nt7d] + setall = lambda{ + reqparams.each{|key| return false unless @params.has_key?(key)} + return true + } + stack = "" + while line=gets # !setall.call && line=gets + if /^(\S+)=(.*)/ =~ line + next unless reqparams.index($1) || otherparams.index($1) + @params[$1] = $2 + #if reqparams.index($1) + STDERR.print "Set #{$1} to #{$2}\n" + #end + buf = "" + elsif /^\s*\#|^$/ =~ line + # skip comments + else + buf += line + end + end + unless setall.call + STDERR.print "Insufficient variables\n" + exit 1 + end + p buf + + y, m, d = date2ymd(@params["date"]) + @params["year"] = y + @params["month"] = m + @params["day"] = d + @params["schedule"] = buf + @params["editmode"] = "modify" + @params["sessionpw"] = @params["sp"] + p @params + add_remove() + end + def mail_getsched() + user = nil + while bline=gets + if /(\S+@\S+)/ =~ bline + break if user=@sc.isuser($1) + end + end + unless user + sendMail(@opt['maintainer'], "viaMail Request Error", + "This is `#{@mybase}' in #{@mydir}\n" + + "Invalid schedule request from #{ENV['SENDER']}.\n\n") + exit 1 + end + today = Time.now.strftime("%Y/%m/%d") + days = 7 + if bline=gets + if /\d+/ =~ bline + days = bline.to_i + end + end + # Send user to schedules of today and near future + @params['user'] = user + show_by_text(today, days) + end + def doMail() + days = 7 + # Confirm `via Mail' + prohibitviahttp() + @H = TEXTout.new + unless ENV['RECIPIENT'] && ENV['SENDER'] + STDERR.print "Call me via qmail\n" + exit 1 + end + @mailmode = true + header = parseHeader # is this necessary? + if /regist/ =~ ENV["EXT"] + mail_regsched() + else + mail_getsched() + end + end + + # + # Password related Methos def setpasswd(user) prohibitviahttp() pm = open_pm() @@ -2937,6 +3311,10 @@ when "-d" $DEBUG = true when "-install" + when "-stream" + # ARGV.shift + # @job = 'show_by_text "2005/1/18"' + @job = 'doMail' when "-addsched" @job = "addsched" when "-today" @@ -2950,6 +3328,9 @@ when "-remove" ARGV.shift @job = 'remove "'+parsedate(ARGV[0])+'"' + when "-move" + ARGV.shift + @job = 'move "'+parsedate(ARGV[0])+'"' when "-modify" ARGV.shift @job = 'modify "'+parsedate(ARGV[0])+'"'