#!/usr/local/bin/ruby require 'socket' require 'net/http' require 'cgi' require 'kconv' require 'timeout' # 定数 TIME_LIMIT = 30 EXPIRE_TIME = 60 * 60 *24 * 30 SAKURA_PORT = 9801 HTTP_PORT = 80 MAX_DATA_SIZE = 2014 # クッキー取得 cgi = CGI::new cookies = cgi.cookies begin # 適当にタイムアウト timeout(TIME_LIMIT) do # さくらとも呼ばれるひとかチェック # addr = ENV['HTTP_X_FORWARDED_FOR'] || ENV['REMOTE_ADDR'] addr = ENV['REMOTE_ADDR'] TCPSocket.open(addr, SAKURA_PORT).close # 更新情報を取得 url = ENV['QUERY_STRING'] raise unless %r|http://(.+?)(/.+)| =~ url host, port, path = $1, HTTP_PORT, $2 host, port = $1, $2 if host =~ /(.+):(.+)/ response, body = Net::HTTP.new(host, port).get(path) # 取得した更新情報を解析 kcode = Kconv::guess(body) if kcode != Kconv::SJIS body = Kconv::kconv body, Kconv::SJIS, kcode end update = body.split(/[\r\n]+/) author = update.shift first = update.shift second = update.shift update.map!{|line| next unless line =~ %r|(\d+)/(\d+)/(\d+)\s+(\d+):(\d+)\s+(.+)| [ Time::local($1, $2, $3, $4, $5), $6 ] } update.compact! # 現在時間とクッキーのexpire時間 now = Time::now expires = now + EXPIRE_TIME # スクリプト作成 unless cookies.include? url script = first else cookies[url].expires = expires update.reject!{|u| u[0] < now} raise if update.empty? update.collect!{|u| u[1]} script = second + '\n' + update.join('\n') end # 送信データ作成 data = <<-"END" SEND SSTP/1.0\r Sender: #{author}\r Script: #{script}\\e\r \r END # データサイズが2KB以内になるように丸め込む while data.size > MAX_DATA_SIZE raise unless data.sub!(/(^Script: .*?\\n).*?\\n/, '\1') end # データ送信 sock = TCPSocket.open(addr, SAKURA_PORT) sock.write data # 終了ステータスをチェック raise unless %r|SSTP/\d.\d 200 OK| =~ sock.read # クッキー更新 unless cookies.include? url cookies[url] = CGI::Cookie::new ('name' => url, 'value' => [ now.to_i.to_s ], 'expires' => expires) else cookies[url].value = [ now.to_i.to_s ] end end rescue end # ダミーGIF送信 cgi.out ('cookie' => cookies, 'type' => 'image/gif') { "GIF89a\001\000\001\000\200" + "\000\000\377\377\377\000\000\000!\371" + "\004\001\000\000\000\000,\000\000\000" + "\000\001\000\001\000\000\002\002D\001" + "\000;" }