#!/usr/local/bin/ruby
#
# Uogashi Planing System
# (C)2000-2005 by HIROSE Yuuji [yuuji@gentei.org]
# $Id: uogashi.rb,v 1.14 2005/05/09 02:25:22 yuuji Exp $
# Last modified Mon May 9 11:24:04 2005 on firestorm
# See http://www.gentei.org/~yuuji/software/uogashi/
# このスクリプトはEUCで保存してください。
require 'cgi'
require 'kconv'
me = File.expand_path($0)
$mydir, $myname = File.dirname(me), File.basename(me)
$mybase = $myname.sub(/\.\w+$/, '')
=begin
【なんだこれ】
スクリプトと同じディレクトリの uogashi.conf というファイルに
表となる項目の一覧を書いておく。
例:
[uogashi.conf]
name
7/20 option(○,×,△)
7/21 option(○,×,△)
7/27 option(○,×,△)
ひとこと text(10)
すると、このページに何人かが書き込んだあとはこんな感じの表になる。
+----------+------+------+------+----------+
| name | 7/20 | 7/21 | 7/27 | ひとこと |
+----------+------+------+------+----------+
|yuuji | ○ | × | ○ | がおー |
+----------+------+------+------+----------+
|腹 | ○ | ○ | ○ | ぐおー |
+----------+------+------+------+----------+
|ま | ○ | ○ | ○ | ぎょー |
+----------+------+------+------+----------+
[登録or修正]
uogashi.conf は1行1エントリで、TAB区切りで記述。
最初の項目は表の項目名。TABで区切った第二項目はそのカラムの値となる
ものの属性を書く。属性は、
option 選択肢から選ばせる
text 任意の文字列
のどれか。optionは後続する括弧内に選択肢をカンマで区切って列挙する。
textは後続する括弧内に最大バイト数を書く。また、実際には uogashi.conf に
ページの管理者とか、ちょっとした体裁を決める値の定義を書く必要がある。た
とえば、こんなかんじ:
maintainer=yuuji@gentei.org
title=定例OB会
heading=定例OB会
leader=登録画面に進み,行けそうな日に○をつけてください(10日までに!)
bgcolor=yellow
# #で始まる行はコメント
name
7/20 option(○,×,△):stat
7/21 option(○,×,△):stat
7/27 option(○,×,△):stat
ひとこと text(10)
ここで初登場した option に対する :stat スイッチは、各選択肢が何人によっ
て選ばれたかの表を末尾にまとめて表示することを指示する。これで幹事さんも
楽チン。
- - - - - - - -
【インストール】
まずこのスクリプトを動かすディレクトリを決める。たとえば ~/public_html/uo/
そこでCGIが動くように .htaccess を確認。
[~/public_html/uo/.htaccess]
AddHandler cgi-script .cgi
DirectoryIndex uogashi.cgi
そして、uogashi.rb をコピー。で、実際に集計を取りたい事項の名前を決める。
ここでは、 "OB-kai2000" としよう。これがURLの一部になるのでたっぷり悩み
たまへ。では、集計ディレクトリの作成。
% cp uogashi.rb ~/public_html/uo
% cd ~/public_html/uo
% ./uogashi.rb install OB-kai2000
すると必要な項目を聞いて来るので適当に答えると
~/public_html/uo/OB-kai2000/
に必要なものが揃うのでそのURLを知合いに教えよう。そしてサクっと一番いい
日程を決めて飲み会に行こう。
ただしこのスクリプト、集計という幹事の手間を、出席者自身にやらせようとす
る性質上、悪意のある人がアクセスしたら一瞬で集計ディレクトリを壊されてし
まう。その辺は覚悟して、あくまでも良く知った仲間うちで利用し、部外者はア
クセスできないようにページ全体にパスワードをかける、使い終わったらすぐに
消去する、などの予防策を怠らないこと。
ちなみに、インストーラを使わずに手でインストールするには、
* uogashi.cgi を置くディレクトリに uogashi.conf をおく
httpdは読めればOK
* uogashi.cgi を置くディレクトリに uogashi.log, uopass.db をおく
httpdは書き込み許可が必要
* uogashi.cgi を置くディレクトリに repository/ ディレクトリを掘る
httpdは書き込み許可が必要
chmod 1777 repository などが適当
という条件を満たすようにファイル配置する。
さらにちなみに、Webインタフェースのインストーラもあるらしいぞ。
まず一個uogashi.cgiが動くページを作り、管理人のパスワードを設定した後で、
uogashi.cgi?webinstall
をアクセスすればいいらしい。パスワードが分かると誰でも作れちゃうので
取扱注意だ。よって、手取り足取り教えないのでがんばりたまへ。動きさえ
すればとても簡単に作れてしまう…。
【謝辞】
2003/6/3
YAMAGUCHI Takuya(takuya@yamaguch.sytes.net)さんにはBIND9付属のhostコマンドの
挙動について助言と対処法をいただきました。
感謝致します。
=end
$repository = "./repository"
$passwd = "./uopass"
class TableMaker
def initialize
@conf = $mybase + ".conf"
@ctitle = Array.new
@ctype = Array.new
@align = Array.new
@counter = Hash.new
@attr = defaultAttr
@cgi = CGI.new("html4Tr")
loadconf(@conf)
end
def defaultAttr
{
"title" => "Uogashi",
"bgcolor" => "white",
"heading" => "Table",
"leader" => "Uogashi Planning Table",
"inputwarning" => "全ての項目を埋めて「GO」",
"tablewidth" => "700",
"numbering" => "true",
"mail" => "/usr/bin/mail",
"sendmail" => "/usr/sbin/sendmail",
"hostcmd" => "/usr/bin/host",
"nslookup" => "/usr/sbin/nslookup",
"passwdlength" => 6,
"maintainer" => "",
"forgotten" => "wasureta",
"logfile" => "./#{$mybase}.log"
}
end
def loadconf(file)
i = 0
return unless test(?s, file)
IO.foreach(file){|line|
line.chop!
line.sub!(/^\s*#.*/, '')
next if /^$/ =~ line
case line
# title, type = line.split(/\t+/)
when /^([a-z]+)=(.*)/oi
key, value = $1, $2
case value
when /^(no|none|null|nil)$/io
@attr[key] = nil
else
@attr[key] = value
end
print "#{$1} set to #{$2}\n" if $DEBUG
else
@ctitle[i], @ctype[i], @align[i] = line.split(/\t+/)
@counter[@ctitle[i]] = Hash.new(0)
print @ctitle[i], "\n" if $DEBUG
i+=1
end
}
end
def cgi() @cgi end
def outputTable()
if test(?d, $repository) then
begin
cwd = Dir.pwd
rescue
cwd = `pwd`
end
i = -1
trs = @cgi.tr {
if /true/ =~ @attr["numbering"] then
@cgi.th{"番号"}
else
""
end + \
@ctitle.collect{|t|
next if @align[i+=1] == 'ignore'
@cgi.th{t}
}.join('')
}
Dir.open($repository){|dp|
Dir.chdir $repository
n = 0
dp.select{|x| # should contain @mark
/@/ =~ x ### /^\.\.?$/ !~ x
}.collect{|e| [e, File.stat(e).mtime]}.sort{|a, b|
b[1] <=> a[1]
}.each{|f, dummy|
trs += @cgi.tr {
i = -1
if /true/ =~ @attr["numbering"] then
@cgi.td("align" => "center"){(n+=1).to_s}
else
""
end + "\n" + \
IO.readlines(f).collect{|line|
i+=1
next if @align[i] == 'ignore'
line.chop!
if /^option.*:stat/ =~ @ctype[i] then
@counter[@ctitle[i]][line] += 1
end
if /^(name|名前|氏名|お?なまえ|御芳名)$/io =~ @ctitle[i] then
#line += "
(#{f})"
line = @cgi.a("name"=>f){line}
end
@cgi.td("align" => @align[i]){
if line > "" then line else "
" end
}
}.join('')
} + "\n"
}
}
# Dir.chdir cwd
@cgi.out({"charset" => "EUC-JP"}){
@cgi.html{
"\n" + @cgi.head{@cgi.title{@attr["title"]}} + "\n" + \
@cgi.body("bgcolor" => @attr["bgcolor"]) { "\n" + \
@cgi.h1{@attr["heading"]} + "\n" + \
@cgi.p{@attr["leader"]} + "\n" + \
@cgi.a("href" => "./"+$myname+"?entry"){"登録/修正する" }+"\n" + \
@cgi.table("border" => "1", "width" => @attr["tablewidth"]){
"\n" + trs} + "\n" +
@cgi.hr +
@cgi.a("href" => "./"+$myname+"?entry") {"登録/修正する" } +
statinfo() +
@cgi.br + @cgi.p{@attr["footer"]
} + "\n"
}
}
}
end
end # def outputTable
def statinfo
(0..@ctype.length-1).collect{|i|
next if @align[i] == 'ignore'
if /option\((.*)\).*:stat/ =~ @ctype[i] then
optlist = $1.split(',')
# p optlist
@cgi.table("border" => "1") { "\n" + \
@cgi.tr {
@cgi.th{"
"} + \
optlist.collect{|t| @cgi.th{t}}.join('')
} + "\n" + \
@cgi.tr {
@cgi.td {@ctitle[i]} + \
optlist.collect{|d|
@cgi.td{@counter[@ctitle[i]][d]}
}.join('') + "\n"
}
}
else
""
end
}.join("\n") + "\n"
end
def entry
@cgi.out({"charset" => "EUC-JP"}) {
@cgi.html {
@cgi.head{@cgi.title{@attr["title"]+" Entry"}+"\n"} + "\n" + \
@cgi.body("bgcolor" => @attr["bgcolor"]) {"\n" + \
@cgi.form("POST","./"+$myname+"?entry2") { "\n" + \
@cgi.table{
@cgi.tr {
@cgi.td{"あなたのメイルアドレス"} + \
@cgi.td{@cgi.text_field("email", nil, 40)} + "\n" } + \
@cgi.tr {
@cgi.td{"パスワード
(初回の場合は無記入)"} + \
@cgi.td{@cgi.password_field("passwd", nil, 40)} + "\n"
}
} + \
@cgi.submit("LOGIN") + @cgi.br + "\n"
} + "\n"
}
}
}
end # def entry
def entry2
params = @cgi.params
mail, passwd = ["email", "passwd"].collect{|x| params[x][0]}
pm = PasswdMgr.new($passwd, 0660)
userdata = if test(?s, "#{$repository}/#{mail}") then
userData("#{$repository}/#{mail}")
else
[]
end
if !checkmail(mail) then
htmlOut("Invalid Mail address",
@cgi.p{"メイルアドレスが無効です: #{mail}"})
elsif pm.userexist?(mail) then
if pm.checkpasswd(mail, passwd) then
outputForm(mail, passwd, userdata)
elsif passwd == @attr["forgotten"] then
sendMail(mail, "#{@attr['title']} password",
"(#{ENV['REMOTE_ADDR']} からのアクセスによる送信)\n" +
"#{@attr['title']} 用の #{mail} さんのパスワードは\n" +
(pm.getpasswd(mail)||"未定義") + "\nです。\n")
htmlOut("Sent to you", @cgi.p{"#{mail} 宛に送信しておきました"})
else
outputError("パスワードが違います")
end
else # First time registration
outputForm(mail, nil, userdata)
end
# p mail, passwd
pm.close()
end
def outputError(msg)
@cgi.out{
@cgi.html{
@cgi.head{@cgi.title{@attr["title"]+" error"}} + \
@cgi.body("bgcolor" => @attr["bgcolor"]){
@cgi.p{msg}
}
}
}
end
def outputForm(user, passwd, default = [])
@cgi.out({"charset" => "EUC-JP"}) {
@cgi.html {
@cgi.head{@cgi.title{@attr["title"]+" Entry for #{user}"}} + "\n" + \
@cgi.body("bgcolor" => @attr["bgcolor"]){
@cgi.p{"#{user} さんのデータ入力"} + "\n" + \
if passwd == nil
passwd = generateNewPasswd
pm = PasswdMgr.new($passwd)
pm.setpasswd(user, passwd)
pm.close()
sendMail(user, "Your password for #{@attr['title']}",
"あなたの #{@attr['title']} 用パスワードは\n" +
passwd + "\nです。保管しておいてください。\n" +
"(" + ENV['HTTP_REFERER'].sub(/\?.*/, "") + ")\n" +
"もしパスワードを忘れた場合は、本当のパスワードの" +
"代わりに\n#{@attr['forgotten']} と入れてください。\n")
@cgi.p{
"新規登録です。あなたのパスワードは"
} + @cgi.pre{passwd} + \
@cgi.p{"です。大切に保管してください。"} + "\n"
else
""
end + \
@cgi.p{@attr["inputwarning"]} + "\n" + @cgi.hr + "\n" + \
@cgi.form("POST", "./#{$myname}?register") {
"\n" + \
@cgi.hidden("email", user) + "\n" + \
@cgi.hidden("passwd", passwd) + "\n" + \
@cgi.table{
"\n" + \
(0..@ctitle.length-1).select{|i| @align[i]!='ignore'}.collect{|i|
title = @ctitle[i]
type = @ctype[i]
dflt = default[i]
@cgi.tr {
@cgi.td{title} + \
@cgi.td{
case type
when /^text(\((\d+)\))?/
# print title, default[i]
@cgi.text_field(title, dflt, $2)
when /option\((.*)\)/
@cgi.popup_menu({ "NAME" => title,
"VALUES" => popupValues($1, dflt)})
end
}
} + "\n"
}.join('')
} + \
@cgi.hr + "\n" + \
@cgi.submit("GO")
} + "\n"
} + "\n"
}
}
end
def popupValues(choice, default)
choice.split(",").collect{|elm|
if elm == default then [elm, true] else [elm] end
}
end
def userData(file)
IO.readlines(file).collect{|l|l.chop!}
end
def generateNewPasswd
srand(Time.now.to_i)
length = @attr["passwdlength"].to_i
left = "qazxswedcvfrtgb12345"
right = "yhnmjuik.lop;/67890-"
array = [left, right]
(1..length).collect{|i|
a = array[i%array.length]
a[rand(a.length), 1]
}.join('')
end
def register
params = @cgi.params
user = params["email"][0].strip
pm = PasswdMgr.new($passwd)
if !checkAllFilled(params) then
outputError("全ての項目を埋めてください")
elsif pm.checkpasswd(user, params["passwd"][0]) then
uback = File.umask
File.umask(002)
i = -1
open("#{$repository}/#{user}", "w") {|fp|
@ctitle.each{|k|
fp.print(if @align[i+=1] == 'ignore' then
'
'
else
params[k][0]
end + "\n")
}
}
if /.*\@.*/ =~ @attr["maintainer"] then
sendMail(@attr["maintainer"], @attr["title"]+" registration",
"#{@attr['title']} registration by #{user}\n" +
@ctitle.collect{|k|
sprintf "%-20s = #{params[k][0]}", k
}.join("\n"))
end
File.umask(uback)
htmlOut(@attr["title"]+" Result",
@cgi.p{"完了しました"} + \
@cgi.a("href" => "./#{$myname}"){"確認"})
else
outputError("送信エラー")
end
pm.close()
end
def checkAllFilled(params)
i = -1
@ctitle.each{|x|
@align[i+=1] == 'ignore' or params[x][0] or return false
}
true
end
def htmlOut(title, body)
@cgi.out({"charset" => "EUC-JP"}) {
@cgi.html {
@cgi.head{@cgi.title{title}}+"\n" + \
@cgi.body("bgcolor" => @attr["bgcolor"]) {
body
}
}
}
end
def setpasswd(user)
pm = PasswdMgr.new($passwd)
if pm.userexist?(user) then
begin
system "stty -echo"
STDERR.print "New passwd: "
p1 = STDIN.gets
STDERR.print "\nAgain: "
p2 = STDIN.gets
ensure
system "stty echo"
end
if (p1 == p2) then
pm.setpasswd(user, p1.chop!)
end
STDERR.print "New password for #{user} set successfully\n"
else
STDERR.print "User #{user} not found\n"
end
pm.close()
end
def adduser(user)
pm = PasswdMgr.new($passwd)
newpwd = generateNewPasswd
pm.setpasswd(user, newpwd)
print "#{user}'s password is #{newpwd}\n"
pm.close()
end
def deluser(user)
pm = PasswdMgr.new($passwd)
pm.delete(user)
pm.close()
end
def sendMail(to, subject, body)
body = Kconv::tojis(body)
subject = Kconv.tojis(subject)
if /\e/ =~ subject # If contains JIS chars...
subject = subject.split(//,1).pack('m')
subject = "=?iso-2022-jp?B?#{subject}?="
end
subject.gsub!(/\n/, '')
begin
if (m=open("|-", "w"))
m.print "To: #{to}\n"
m.print "Subject: #{subject}\n"
m.print "Mime-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Type: Text/Plain; charset=iso-2022-jp
"
m.print body, "\n"
m.close
else
# exec(@attr['mail'], "-s", subject, to)
exec(@attr['sendmail'], to)
end
putLog("Sent '#{subject}' to #{to}\n")
rescue
putLog("FAILED! - Sent '#{subject}' to #{to}\n")
end
end
def putLog(msg)
msg += "\n" unless /\n/ =~ msg
open(@attr["logfile"], "a+") {|lp|
lp.print Time.now.to_s + " " + msg
}
end
def checkmail(mail)
account, domain = mail.scan(/(.*)@(.*)/)[0]
return false unless account != nil && domain != nil
return false unless /^[-0-9a-z_.]+$/oi =~ domain
require 'socket'
begin
TCPSocket.gethostbyname(domain)
return true
rescue
if test(?x, @attr["hostcmd"])
open("| #{@attr['hostcmd']} -t mx #{domain}.", "r") {|ns|
#p ns.readlines.grep(/\d,\s*mail exchanger/)
return ! ns.readlines.grep(/is handled .*(by |=)\d+/).empty?
}
elsif test(?x, @attr["nslookup"])
open("| #{@attr['nslookup']} -type=mx #{domain}.", "r") {|ns|
#p ns.readlines.grep(/\d,\s*mail exchanger/)
return ! ns.readlines.grep(/\d,\s*mail exchanger/).empty?
}
end
return false
end
end # checkmail
def install(targetdir)
@attr = defaultAttr
STDERR.print "[] の中にあるのはデフォルト値\n\n"
newconfig = Hash.new
mailguessed = ENV["USER"]+"@"+`hostname`.chop!.sub!(/[^.]+./, '')
STDERR.print "あなた(=管理人)のメイルアドレス(重要) [#{mailguessed}]: "
if (l=STDIN.gets.chop!) == "" then l = mailguessed end
if !checkmail(l) then
STDERR.print "そんなメイルアドレスじゃあ管理させられんな\n"
exit 1
end
newconfig["maintainer"] = l
[ "タイトル:title",
"ページ背景色:bgcolor",
"見出し:heading",
"最初の一行説明文:leader",
"表の幅:tablewidth",
"表の番号づけ(true/false):numbering",
].each{|item|
guide, attr = item.scan(/(.*):(.*)/)[0]
default = @attr[attr]
STDERR.printf "%s [%s]: ", guide, default
value = Kconv::toeuc(STDIN.gets.chop)
if value > "" then
newconfig[attr] = value
end
}
# Input columns
cols = Array.new
q = lambda{|n, default|
odf = Kconv::toeuc("○,△,×")
STDERR.printf "第%d項目名 (もう要らないときは q) [\"%s\"]: ", n, default
l = Kconv::toeuc(STDIN.gets.chop)
throw :done, true if l == "q"
cols[n] = Array.new
if l == "" then l = default end
cols[n][0] = l
STDERR.print "種別 (1=text, 2=option) [2]: "
l = STDIN.gets.chop!
case l
when "1"
STDERR.print "text入力最大バイト数 [20]: "
if (l=STDIN.gets.chop) == "" then l = "20" end
cols[n][1] = "text(#{l})"
else
STDERR.print "選択肢を半角カンマで区切って入れてください [#{odf}]\n"
l = Kconv::toeuc(STDIN.gets.chop!)
if l == "" then l = odf end
cols[n][1] = "option(#{l})"
STDERR.print "この項目を集計する? [no]: "
if /y/i =~ STDIN.gets then cols[n][1] += ":stat" end
end
}
#q.call(0, "名前")
STDERR.print "勝手ながらインストーラでは第0項目名を「名前」に致します.\n"
cols[0] = ["名前", "text(20)"]
i=0
catch (:done) {
while true
q.call(i+=1, "項目#{i}")
end
}
confstr = confdump(newconfig, cols)
print "-" * 70 + "\n", confstr, "-"*70, "\n"
STDERR.print \
"設定ファイル(#{@conf})に書き出して作業ディレクトリも準備しますか? [y/N]: "
if /y/i =~ STDIN.gets then
if pid=fork then
Process.wait
else
File.umask(0)
Dir.mkdir(targetdir, 01777) unless test(?d, targetdir)
#Dir.chdir(targetdir)
open(targetdir+"/"+@conf, "w"){|fp| fp.print confstr}
repdir = targetdir+"/"+$repository
Dir.mkdir(repdir, 0777) unless test(?d, repdir)
clone = targetdir+"/"+$mybase+".cgi"
File.link($0, clone) unless test(?f, clone)
logfile = targetdir+"/"+@attr["logfile"]
open(logfile, "a+"){|fp| fp.chmod(0666)}
Dir.chdir(targetdir)
PasswdMgr.new($passwd, 0666).close()
exit 0
end
STDERR.print "\nディレクトリ属性とかあま目に設定したので後で直してね.\n"
STDERR.print "あと、\n\tDirectoryIndex\tuogashi.cgi\nなんてのを"
STDERR.print ".htaccess に書いとくといいかも。\n"
end
end
def webinstall
htmlOut("#{$mybase} planner web installer",
@cgi.form("POST", "#{$myname}?webinstall_2") { "\n" +
@cgi.table{ "\n" + \
@cgi.tr { "\n" + \
@cgi.td{"メイルアドレス"} +\
@cgi.td{@cgi.text_field("email", nil, 40)}
} + "\n" + \
@cgi.tr { "\n" + \
@cgi.td{"パスワード"} + \
@cgi.td{@cgi.password_field("passwd", nil, 40)}
}
} + \
@cgi.submit("OK") + @cgi.reset("reset")
})
end # webinstall_1
def webinstall_2
params = @cgi.params
admin = params["email"][0]
passwd = params["passwd"][0]
if admin != @attr["maintainer"]
htmlOut("#{$mybase} authentication error", @cgi.p{"管理人しかだめよ."})
exit 0
end
df = defaultAttr
htmlAuth(admin, passwd) # if invalid passwd, exits
pm = PasswdMgr.new($passwd)
sessionkey = Time.now.to_i.to_s
sessionpasswd = generateNewPasswd
pm.setpasswd(sessionkey, sessionpasswd.crypt("uo"))
pm.close()
sendMail(@attr["maintainer"], "uogashi: webinstall notice",
<
「ページ背景色」〜「表の番号付け」は任意。
「セッションパスワード」は、今メイルで送ったのでそれを入れる。
EOM
} + \
@cgi.form("POST", "#{$myname}?webinstall_3") { "\n" + \
@cgi.table("border" => "1") { "\n" + \
@cgi.tr { "\n" + \
@cgi.td{"セッションパスワード"} + \
@cgi.td{@cgi.password_field("pas", nil, 20)}
} + "\n" + \
@cgi.tr { "\n" + \
@cgi.td{"集計ディレクトリ名"} + \
@cgi.td{@cgi.text_field("dir", nil, 20)}
} + "\n" + \
@cgi.tr { "\n" + \
@cgi.td{"集計名(タイトル)"} + \
@cgi.td{@cgi.text_field("title", nil, 20)}
} + "\n" + \
@cgi.tr { "\n" + \
@cgi.td{"ページ先頭の見出し"} + \
@cgi.td{@cgi.text_field("heading", nil, 20)}
} + "\n" + \
@cgi.tr { "\n" + \
@cgi.td{"ページ背景色"} + \
@cgi.td{@cgi.text_field("bgcolor", df["bgcolor"], 20)}
} + "\n" + \
@cgi.tr { "\n" + \
@cgi.td{"最初の一行説明文"} + \
@cgi.td{@cgi.text_field("leader", df["leader"], 20)}
} + "\n" + \
@cgi.tr { "\n" + \
@cgi.td{"表の幅(nilとすると自由幅)"} + \
@cgi.td{@cgi.text_field("tablewidth", "700", 20)}
} + "\n" + \
@cgi.tr { "\n" + \
@cgi.td{"表の番号付け (true/false)"} + \
@cgi.td{@cgi.popup_menu("numbering", "true", "false")}
} + "\n"
} + "\n" + \
@cgi.p {
<<-GUIDE
続いて項目名を決定。
「種別」 text の場合は「値」に最大バイト数を
\n
「種別」 option の場合は「値」に選択肢文字列をカンマで区切って
入れる
例
晴れ,雨,曇,雪
必要なだけ項目を埋めたらそこから下は空欄のままにする。
GUIDE
} + \
@cgi.table("border" => "1") { "\n" + \
@cgi.tr { "\n" + \
@cgi.th{"項目名"}+@cgi.th{"種別"}+@cgi.th{"値"}
} + "\n" + \
@cgi.tr { "\n" + \
@cgi.td{@cgi.popup_menu("0,0",
"名前", "氏名", "なまえ",
"御芳名", "Name")} + "\n" + \
@cgi.td{@cgi.popup_menu("0,1", "text")} + "\n" + \
@cgi.hidden("0,2", "40") + @cgi.td{"40"}
} + \
(1..9).collect{|n|
@cgi.tr {
@cgi.td{@cgi.text_field("#{n},0", n<4 && "項目#{n}", 20)} \
+ "\n" + \
@cgi.td{@cgi.popup_menu("#{n},1", "option", "text",
"option:stat")} + \
@cgi.td{@cgi.text_field("#{n},2", n<4 && "○,△,×", 30)}
}
}.join("\n") + "\n"
} + \
@cgi.hidden("session", sessionkey) + "\n" + \
@cgi.hidden("adm", admin) + "\n" + \
@cgi.submit("OK") + " " + @cgi.reset("reset")
})
end # webinstall_2
def webinstall_3
params = @cgi.params
admin = params["adm"][0]; params.delete("adm")
sskey = params["session"][0]; params.delete("session")
spass = params["pas"][0]; params.delete("pas")
dir = params["dir"][0]; params.delete("dir")
if admin != @attr["maintainer"]
htmlOut("#{$mybase} authentication error", @cgi.p{"管理人しかだめよ."})
exit 0
end
if dir == nil || dir == ""
htmlOut("#{$mybase} directory error", @cgi.p{"ディレクトリ名は必須."})
exit 0
elsif /^[-0-9a-z_]+$/ !~ dir
htmlOut("#{$mybase} directory error",
@cgi.p{"ディレクトリ名は一応半角英数字だけにしといて下さい."})
exit 0
end
htmlAuth(sskey, spass.crypt("uo")) # if invalid passwd, exits
deluser(sskey) # remove session key
newconfig = Hash.new
newconfig["maintainer"] = admin
params.each_key{|key|
next unless /^[a-z]/ =~ key
newconfig[key] = params[key][0]
params.delete(key)
}
cols = Array.new
(0..9).each{|i|
break unless params["#{i},0"][0] && params["#{i},0"][0] > ""
cols[i] = Array.new
cols[i][0] = params["#{i},0"][0]
case (type=params["#{i},1"][0])
when /text/
cols[i][1] = "text(" + (params["#{i},2"][0] || "40") + ")"
when /option/
cols[i][1] = "option(" + (params["#{i},2"][0] || "○,△,×") + ")"
if /:stat/ =~ type
cols[i][1] += ":stat"
end
end
}
#htmlOut("Result", "OKおしまい
")
# Begin installation
begin
File.umask(0)
ucgi = dir+"/"+$mybase+".cgi"
test(?d, dir) || Dir.mkdir(dir, 01777)
test(?d, dir+"/repository") || Dir.mkdir(dir+"/repository", 01777)
test(?r, ucgi) && File.unlink(ucgi)
File.link($0, ucgi)
open("#{dir}/#{$mybase}.conf", "w") {|fp|
fp.print(confdump(newconfig, cols))
}
rescue
htmlOut("#{$mybase} installation error at final stage",
@cgi.p{
<<-EOM
エラー $!
書き込み時にエラーが起きました。おそらく
#{$mybase} の置いてあるディレクトリに書き込み権限が
無いのだと思います。webinstallを利用したい場合は
wwwサーバに自由に書き込みできる属性設定にしておいて
下さい。
EOM
})
exit 0
end
htmlOut("#{$mybase} installation done",
@cgi.p {
<<-EOM
以下の設定を #{dir}/#{$mybase}.conf に書き込みました。
EOM
} + \
@cgi.pre{confdump(newconfig, cols)} + \
@cgi.a("href" => "#{dir}/#{$mybase}.cgi"){
"新しく作成されたページ"
})
end # webinstall_3
def htmlAuth(user, passwd)
pm = PasswdMgr.new($passwd)
if pm.getpasswd(user) == nil then
htmlOut("#{$mybase} authentication error", @cgi.p{"パスワード設定せよ"})
exit 0
end
if !pm.checkpasswd(user, passwd) then
htmlOut("#{$mybase} authentication error", @cgi.p{"パスワード違うの."})
exit 0
end
end
def userdel(user)
pm = PasswdMgr.new($passwd)
pm.delete(user)
pm.close()
end
def confdump(prop, column)
prop.keys.collect{|k|
"#{k}=#{prop[k]}"
}.join("\n") + "\n" + \
(0..column.length-1).collect{|n|
column[n][0] + "\t" + column[n][1]
}.join("\n") + "\n"
end
end
class PasswdMgr
def initialize(name, mode=0640)
require 'dbm'
@pdb = DBM.open(name, mode)
end
def checkpasswd(user, passwd)
if @pdb[user] then
@pdb[user] == passwd
else
@pdb[user] = passwd # If empty, then set new passwd
true
end
end
def setpasswd(user, passwd)
@pdb[user] = passwd
end
def userexist?(user)
@pdb[user] ? true : false
end
def getpasswd(user)
@pdb[user]
end
def delete(user)
@pdb.delete(user)
end
def close()
@pdb.close()
end
end
args = ARGV.dup
#ARGV.shift
uogashi = TableMaker.new
open("uogashi.log", "w") {|lp|
lp.print `env|sort`
uogashi.cgi.params.each{|k, v|
lp.print "#{k}=#{v}\n"
}
}
if !args[0] and ENV["QUERY_STRING"]
args[0] = ENV["QUERY_STRING"]
end
case args[0]
when /^(entry2?|register)$/
eval "uogashi.#{args[0]}"
when /^(setpasswd|deluser|adduser|checkmail)$/
p (eval "uogashi.#{args[0]}('#{args[1]}')")
when "install"
if args[1] == nil
STDERR.print "Usage: #{$0} install 集計ディレクトリ名\n"
STDERR.print "例: #{$0} install uogashi\n"
exit 1
end
STDERR.print "args1=#{args[1]}\n"
uogashi.install(args[1])
when "webinstall"
uogashi.webinstall
when /webinstall_[23]/
eval "uogashi.#{args[0]}"
else
uogashi.outputTable
end
if __FILE__ == $0
end
# Local variables:
# buffer-file-coding-system: euc-jp
# End: