#!/usr/bin/ruby require 'socket' require 'timeout' require 'kconv' include Kconv DEBUG = 0 HEADER_REGEX = /^(\w+):\s?(.*)$/ class DCUPsocketError < Exception ; end class DCUP attr :server attr :name attr :address attr :title attr :url attr :wrap attr :proxyserver attr :proxyport attr :body def initialize(io) parse_header(io) parse_body(io) end def parse_header(io) @header = {} # 各ヘッダが格納される @header_string = '' # 生のヘッダ全体が格納される while line = io.gets() break if /--- write below ---\n/ =~ line if HEADER_REGEX =~ line field_name = $1.capitalize if not @header.key?(field_name) @header[field_name] = $2 end end @server = get_value('Server') @name = get_value('Name') @address = get_value('Mail') @title = get_value('Title') @url = get_value('Url') @wrap = get_value('Autowrap') @proxyserver = get_value('Proxyserver') @proxyport = get_value('Proxyport') end end private :parse_header def parse_body(io) @body = '' while line = io.gets() @body << line.gsub(/\n/, "\r\n") end end private :parse_body # 指定されたヘッダの内容を文字列として返す. def [](field_name) if @header.include?(field_name) return @header[field_name] else return nil end end def get_value(field_name) if @header.key?(field_name) return @header[field_name] else return nil end end end class String public :kconv def escape(content = self) s = Kconv.kconv(content, Kconv::SJIS, Kconv::AUTO); s.gsub!(/[^a-zA-Z0-9_\-.]/n){ sprintf("%%%02X", $&.unpack("C")[0]) } return s end end class DCUPsocket def initialize( addr, po, pi, otime, rt ) @address = addr @port = po @pipe = (pi || []) @rtime = rt # @mode = Text @closed = false @sending = '' begin timeout( otime ) do @socket = TCPsocket.new( addr, po ) end rescue if TimeoutError === $! then raise( TimeoutError, 'Can\'t open TCP connection in' << otime.to_s << 'sec' ) else raise end end end def write(str) begin @socket.write str @socket.flush rescue raise end end def read( target ) begin ret = '' lastch = target[-1] targetlen = target.size find_target = false count = 0 until find_target do timeout( @rtime ) do @socket.each_byte do |ch| ret.concat( ch.chr ) if ch == lastch then if ret[ -targetlen, targetlen ] == target then find_target = true ; break end end count += 1 if count == 1024 then count = 0 ; break end end end end return ret rescue if TimeoutError === $! then mes = LOGSTAB + 'Can\'t read ' target.each_byte do |i| mes << i.to_s << ',' end mes << 'in ' << @rtime.to_s << 'sec' raise TimeoutError, mes else raise end end end end dcup = DCUP.new(STDIN) host = dcup.server.split(/\//)[2] if host =~ /www\.tcup/ cgi = dcup.server.split(/\//)[3] + "/" + dcup.server.split(/\//)[4].split(/\./)[0] + '.cgi' if dcup.proxyserver target = sprintf("http://%s/cgi-localbin/%s", host, cgi) else target = '/cgi-localbin/' + cgi end form_body = sprintf("action=regist&name=%s", dcup.name.escape) form_body << "&email=" if dcup.address form_body << sprintf("%s", dcup.address) end form_body << "&subject=" if dcup.title form_body << sprintf("%s", dcup.title.escape) end form_body << sprintf("&value=%s", dcup.body.escape) if dcup.url form_body << sprintf("&page=%s", dcup.url.escape) end else if host =~ /kondara\.sdri/ cgi = dcup.server.split(/\//)[4].split(/\./)[0] + '.cgi' if dcup.proxyserver target = sprintf("http://%s/RuBBS/%s", host, cgi) else target = '/RuBBS/' + cgi end form_body = sprintf("action=append&name=%s", dcup.name.escape) form_body << "&mail=" if dcup.address form_body << sprintf("%s", dcup.address) end form_body << "&subject=" if dcup.title form_body << sprintf("%s", dcup.title.escape) end form_body << sprintf("&contents=%s", dcup.body.escape) if dcup.url form_body << sprintf("%s", dcup.url.escape) end else if host =~ /www\.aurora/ cgi = dcup.server.split(/\//)[3] + ".cgi" if dcup.proxyserver target = sprintf("http://%s/cgi-bin/user/enqV3/%s", host, cgi[1..-1]) else target = '/cgi-bin/user/enqV3/' + cgi[1..-1] end form_body = sprintf("df=%s/bbs.dat", dcup.server.split(/\//)[4]) form_body << sprintf("|gb=%s/bbs.conf", dcup.server.split(/\//)[4]) form_body << sprintf("|dc=%s/dc.conf", dcup.server.split(/\//)[4]) form_body << sprintf("|ex=%s/field.conf", dcup.server.split(/\//)[4]) form_body << sprintf("|sp=%s/bbs.html", dcup.server.split(/\//)[4]) form_body << "|noesc=y" form_body = sprintf("option=%s", form_body.escape); form_body << "&name=" if dcup.name form_body << sprintf("%s", dcup.name.escape) end form_body << "&address=" if dcup.address form_body << sprintf("%s", dcup.address.escape) end form_body << "&subject=" if dcup.title form_body << sprintf("%s", dcup.title.escape) end form_body << "&url=" if dcup.url form_body << sprintf("%s", dcup.url.escape) end form_body << "&body=" if dcup.body form_body << sprintf("%s", dcup.body.escape) end else cgi = dcup.server.split(/\//)[3] + "/" + dcup.server.split(/\//)[4].split(/\./)[0] if dcup.proxyserver target = sprintf("http://%s/cgi-bin/%s", host, cgi) else target = '/cgi-bin/' + cgi end form_body = sprintf("action=append&name=%s", dcup.name.escape) form_body << "&mail=" if dcup.address form_body << sprintf("%s", dcup.address) end form_body << "&subject=" if dcup.title form_body << sprintf("%s", dcup.title.escape) end form_body << sprintf("&contents=%s", dcup.body.escape) if dcup.wrap == "yes" form_body << sprintf("&nowrap=false", dcup.url.escape) else form_body << sprintf("&nowrap=true", dcup.url.escape) end if dcup.url form_body << sprintf("%s", dcup.url.escape) end end end end if DEBUG != 1 if dcup.proxyserver dcupsocket = DCUPsocket.new(dcup.proxyserver, dcup.proxyport, nil, 60, 60) else dcupsocket = DCUPsocket.new(host, 80, nil, 60, 60) end end form = sprintf("POST %s HTTP/1.0\r\n", target) form << sprintf("Host: %s\r\n", host) form << "Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, image/png, */*\r\n" form << "Accept-Language: en\r\n" form << "Pragma: no-cache\r\n" form << "Cache-Control: no-cache\r\n" form << "User-Agent: DCUP/ruby 0.1 with Kondara\r\n" form << sprintf("Referer: %s\r\n", dcup.server) form << "Content-type: application/x-www-form-urlencoded\r\n" form << sprintf("Content-length: %d\r\n\r\n", form_body.length) form << form_body if DEBUG != 1 dcupsocket.write(form) stat = dcupsocket.read("\r\n") if stat.split[1] == "302" exit(0) else if stat.split[1] == "200" exit(0) else exit(1) end end else print form exit(0) end