Tカードの情報提供無効化または有効化を自動で行うためのプログラム
[program/Application/ruby/tools/antiTsite.git] / Script / tsite_uncheck.rb
1 #!/usr/bin/env ruby
2 # coding: utf-8
3
4 # ライセンス条項(仮)
5 #   1.本プログラムは、
6 #       Tカードの情報提供無効化または有効化(以下、目的)の為に
7 #       個人が自分のために使用する場合に限り、
8 #     無料で使用することが出来ます。
9 #
10 #   2.本プログラムに関する全ての権利は、Ituki Kirihara/NIに帰属します。
11 #     著作権等は一切放棄しておりません。
12 #     (c) Copyright 2014 Ituki Kirihara/NI All rights reserved.
13 #
14 #   3.権利者は、本プログラムの使用その他全てに関して発生した全ての責任を負いません。
15 #     必ず個人の責任でご利用ください。
16 #
17 #   4.本ライセンスは仮ライセンスです。将来的に変更される可能性があります。
18 #     将来のライセンスは、「個人は目的の為になら無料で使用できる」という1.の項目以外に関しては、過去に遡って適用される可能性があります。
19
20 #   5.以下の事を行うことは出来ません
21 #     5.1.個人が、その個人本人のため以外に本プログラムを利用すること
22 #          第三者の代理実行、webによる本人以外へのサービス公開などは全て禁止します。
23 #
24 #     5.2.再配布(プログラムを改造したものも再配布は禁止します)
25 #          必ず、下に示すダウンロードURLへのリンクを用いて配布してください
26 #
27 #     5.3.ソースコードの一部、もしくは全てを、別の目的のために流用すること
28 #          オープンソースではありますが、別目的への転用はできません
29 #
30 #     5.4.商用利用
31 #
32 #     5.5.アクセス先への攻撃目的での使用
33 #
34 #     5.6.本ライセンスの書き換え
35 #
36 #   6.以下の事を行うことが出来ます
37 #     6.1.個人が、その個人本人のために本プログラムを、目的を達成するために変更し、実行する事ができます。
38 #          本人が、目的の為に利用する場合に限り、ソースコードを改造することが出来ます。
39 #          ただし、改造したソースコード全体を公開することはできません。
40 #          ※改造方法をwebで公開する事は問題ありません。これにはパッチファイルによる公開も含まれます。
41 #
42 #   7.以下の事を承認する必要があります
43 #     7.1.本プログラムにより発生した全ての責任は、利用者が負う必要があります。
44 #
45 #     7.2.プログラムの改造方法などを公開した場合、以下(7.2.4.)の条件のいずれかに該当する場合は、
46 #           7.2.1.改造者(プログラム変更者)は、譲渡可能な全ての権利を Ituki Kirihara/NIに譲渡し、
47 #           7.2.2.改造者は、譲渡不可能な全ての権利を行使せず、
48 #           7.2.3.改造者は、譲渡可能/不可能を問わず、全ての権利行使をItuki Kirihara/NIに一任する
49 #                 ※譲渡不可能な権利を行使する場合は、Ituki Kirihara/NIの指示のみにより、改造者が行使する形とする
50 #         事を承認しなければなりません
51 #           7.2.4.条件
52 #             7.2.4.1.プログラムを変更しないことで、セキュリティ上の問題が発生する変更(セキュリティ修正一般)
53 #             7.2.4.2.プログラムに内包されていたバグの修正・コードの変更(追加機能のないバグ修正一般)
54 #             7.2.4.3.外部の仕様の変更等により、目的を達成することが出来なくなった場合に
55 #                     公開された以外の方法で目標を達成することが困難な場合のコードの変更(外部の仕様変更による修正一般)
56 #
57 #     7.3.プログラムの改造方法などを公開した場合、上記(7.2.)に当てはまらない場合であっても、
58 #         Ituki Kirihara/NIとの交渉により権利の譲渡等をお願いする場合があります。
59 #
60 #     7.4.本ライセンスについて、判断が難しい場合は、Ituki Kirihara/NIの判断に従う
61 #
62 #     7.5.Ituki Kirihara/NIは本プログラムに関するサポート義務を負わない
63 #
64 #   8.その他
65 #     8.1.本ライセンスによらず、Ituki Kirihara/NIが承認した場合にはその内容に従って使用することが可能です。
66 #
67 #     8.2.紹介、改造方法などをItuki Kirihara/NIへ通知する義務はありませんが、教えて貰えると嬉しいです。
68 #
69 #
70 #  Ituki Kirihara/NI に関する情報
71 #    Webページ
72 #      http://fc.to/ituki/  いつき over TCP
73 #      http://blog.proj.jp/ituki/ いつきログ
74 #    Twitterアカウント
75 #      @ityuki ( https://twitter.com/ityuki )
76 #  本プログラムに関する情報
77 #    ダウンロードURL
78 #      http://blog.proj.jp/ituki/data/apps/tools/tsite_uncheck.zip
79 #    パッチ等置き場(準備中の可能性あり)
80 #      http://i-repo.proj.jp/program/Application/Ruby/tools/tsite_uncheck/
81 #
82
83 file_yahoo_id = "account.txt"
84 file_enable_list = 'enable.txt'
85 file_output_org_html = "tsite.org.html"
86 file_output_dest_html = "tsite.html"
87 file_output_dest_data = "tsite.txt"
88 file_tmp_cookie_cache = 'cookie.cachedb' # if nil, not cache
89
90 @enable_msg = true
91 @enable_anser_msg = true
92
93 @urls = {
94   # first access page
95   'tsite-check-login' => 'https://tsite.jp/accounts/optout/index.pl',
96   # login tsite url header
97   'tsite-login-url-header' => 'https://tsite.jp/',
98   # login tsite url 2 header
99   'tsite-login-url2-header' => 'https://tsite.jp/tm/pc/login/STKIp0001001.do?',
100   # post id 'form1' -> location Yahoo
101   'tsite-yahoologin-post' => 'https://tsite.jp/tm/pc/login/STKIp0011002.do',
102   'tsite-yahoologin-post2' => '../login/STKIp0011002.do',
103   # yahoo url header -> location Yahoo
104   'yahoo-login-url-header' => 'https://auth.login.yahoo.co.jp/',
105   # yahoo url header2
106   'yahoo-login-url2-header' => 'https://login.yahoo.co.jp/',
107   # yahoo login post -> post id 'login_form'
108   'yahoo-login' => 'https://login.yahoo.co.jp/config/login?',
109   # ok yahoo chap header
110   'yahoo-login-ok-chap-url-header' => 'https://login.yahoo.co.jp/config/login?',
111   # ok yahoo location -> location Yahoo
112   'yahoo-login-ok-url-header' => 'https://auth.login.yahoo.co.jp/',
113   # ok yahoo location 2 -> location tsite
114   'yahoo-login-ok-url2-header' => 'https://auth.login.yahoo.co.jp/',
115   # ok login location tsite -> location tsite
116   'tsite-login-ok-url-header' => 'https://tsite.jp/tm/pc/login/STKIp0010000.do?',
117   # login ok and return list, optout_status = ?
118   'tsite-return' => 'https://tsite.jp/accounts/optout/index.pl',
119   'tsite-return2' => 'http://tsite.jp/',
120   # post DISABLE
121   'tsite-disable' => 'https://tsite.jp/accounts/optout/index.pl',
122   # tsite-logout
123   'tsite-logout' => 'http://tsite.jp/logout/index.pl',
124   # yahoo-logout
125   'yahoo-logout' => 'http://www.yahoo.co.jp/r/pl2',
126 }
127
128
129 # 実行開始
130
131 puts ">  start program" if @enable_msg
132
133 require 'net/http'
134 require 'net/https'
135 require 'stringio'
136 require 'zlib'
137 require 'nokogiri'
138 require 'uri'
139 require 'Kconv'
140 require 'pstore'
141
142 @account = {}
143 @enable_id = []
144
145 File.foreach(file_yahoo_id){|l|
146   l.chomp!
147   if (@account['id'] == nil) then
148     @account['id'] = l
149   else
150     @account['pass'] = l
151     break
152   end
153 }
154
155 puts "*  Yahoo ID:" + @account['id'] if @enable_msg
156
157 if File.exists?(file_enable_list) then
158   File.foreach(file_enable_list){|l|
159     l.chomp!
160     next if (l == "" or l =~ /^#/)
161     @enable_id.push(l)
162   }
163 end
164
165 @tsite_cookie = ()
166 @yahoo_cookie = ()
167 @user_agent = 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.65 Safari/537.36'
168 @post_content_type = 'application/x-www-form-urlencoded'
169
170 cookie_cache = nil
171 if file_tmp_cookie_cache != nil then
172   cookie_cache = PStore.new(file_tmp_cookie_cache)
173 end
174
175 if cookie_cache != nil then
176   cookie_cache.transaction do
177     if (cookie_cache['tsite.jp'] != nil) then
178       @tsite_cookie = cookie_cache['tsite.jp']
179       puts "*  tsite.jp cookie cache enable" if @enable_msg
180     else
181       puts "*  tsite.jp cookie cache disable" if @enable_msg
182     end
183   end
184 end
185
186 if (ENV.key?("OCRA_EXECUTABLE")) then
187   if File.exists?(File.dirname(ENV['OCRA_EXECUTABLE']) + "/cacert.pem") then
188     puts "*  cert file is not original file" if @enable_msg
189   end
190 end
191
192
193 def get_cookie(cur,res)
194   cookie = cur
195   cookie = {} if (cookie == nil)
196   if (res.get_fields('set-cookie') != nil) then
197     res.get_fields('set-cookie').each{|str|
198       next if (str == "")
199       k,v = str[0...str.index('; ')].split('=',2)
200       k = '' if k == nil
201       v = '' if v == nil
202       cookie[k] = v
203     }
204   end
205   return nil if (cookie.length == 0)
206   return cookie
207 end
208
209 def access_site(url,post,cookie,ref)
210   uri = URI.parse(url)
211   target = uri.path
212   target = "/" if (target == nil or target == "" or target !~ /^\//)
213   target << "?" << uri.query if (uri.query != nil and uri.query != "")
214   http = nil
215   req = nil
216   if (url =~ /^http\:/) then
217     port = 80
218     port = uri.port if (uri.port != nil and uri.port != 80)
219     http = Net::HTTP.new(uri.host,port)
220     if (post == nil) then
221       req = Net::HTTP::Get.new(target)
222     else
223       req = Net::HTTP::Post.new(target)
224       req['content-type'] = @post_content_type
225       req['content-length'] = post.bytesize
226       req.body = post
227     end
228   elsif (url =~ /^https\:/) then
229     port = 443
230     port = uri.port if (uri.port != nil and uri.port != 443)
231     http = Net::HTTP.new(uri.host,port)
232     http.use_ssl = true
233     http.ca_path = File.dirname(__FILE__)
234     #http.ca_file = (File.dirname(__FILE__) + "/cacert.pem")
235     #http.ca_file = "cacert.pem"
236     if (ENV.key?("OCRA_EXECUTABLE")) then
237       if File.exists?(File.dirname(ENV['OCRA_EXECUTABLE']) + "/cacert.pem") then
238         http.ca_path = File.dirname(ENV['OCRA_EXECUTABLE'])
239       end
240     end
241     http.ca_file = http.ca_path + "/cacert.pem"
242     http.verify_mode = OpenSSL::SSL::VERIFY_PEER
243     if (post == nil) then
244       req = Net::HTTP::Get.new(target)
245     else
246       req = Net::HTTP::Post.new(target)
247       req['content-type'] = @post_content_type
248       req['content-length'] = post.bytesize
249       req.body = post
250     end
251   else
252     print "This url can't access method in program. sorry\nURL: ",url
253     exit
254   end
255   # add UA
256   req.add_field('User-Agent',@user_agent)
257   # add Accept
258   req.add_field('Accept','text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8')
259   req.add_field('Accept-Language','ja,en-us;q=0.7,en;q=0.3')
260   req.add_field('Accept-Encoding','gzip, deflate')
261   # add referer
262   if (ref != nil) then
263     req.add_field('Referer',ref)
264   end
265   # add cookie
266   if cookie != nil then
267     c = ""
268     cookie.each{|k,v|
269       c << "; " if c != ""
270       c << k << '=' << v
271     }
272     if (c != "") then
273       req.add_field('Cookie',c)
274     end
275   end
276   res = http.request(req)
277   if (res.code == "301" or res.code == "302") then
278     return {'location' => res['location'], 'cookie' => get_cookie(cookie,res) }
279   elsif (res.code == "200") then
280     body = res.body
281     if (res['content-encoding'] == nil or res['content-encoding'] == "") then
282       # ok
283     elsif (res['content-encoding'] == 'gzip') then
284       tmp = ""
285       StringIO.open(body, 'rb'){|sio|
286         tmp = Zlib::GzipReader.wrap(sio).read
287       }
288       body = tmp
289     elsif(res['content-encoding'] == 'deflate') then
290       begin
291         body = Zlib::Inflate.inflate(body)
292       rescue Zlib::DataError
293         body = Zlib::Inflate.new(-Zlib::MAX_WBITS).inflate(body)
294       end
295     else
296       print "This url can't accept encoding. sorry\ncontent-encoding:",res['content-encoding'],"\nURL: ",url
297       exit
298     end
299     charset = nil
300     if (res['content-type'] =~ /charset/) then
301       charset = res['content-type'].sub(/^(?:text|application)\/[A-Za-z0-9\-_]+[\s ]*?\;[\s ]*?charset[\s ]*?\=[\s ]*?([A-Za-z0-9\-_]+)[\s ]*?$/i,'\1')
302     end
303     if (!charset) then
304       if (res['content-type'] =~ /^text\/html[^A-Za-z0-9\-_]?/) then
305         # html check
306         charset = body.match(/\<meta[\s \t\n\r\f]+?http\-equiv[\s \t\n\r\f]*?\=(?:\"|\')?Content\-Type(?:\"|\')?[\s \t\n\r\f]+?content[\s \t\n\r\f]*?(?:\=|\=\"|\=\')text\/html[\s \t\n\r\f]*?\;[\s \t\n\r\f]*?charset[\s \t\n\r\f]*?\=[\s \t\n\r\f]*?([A-Za-z0-9\-\_]+)[\s \t\n\r\f]*?(?:\"|\')?[\s \t\n\r\f\/]*?\>/i).to_a[1]
307         if (!charset) then
308           charset = body.match(/\<meta[\s \t\n\r\f]+?content[\s \t\n\r\f]*?(?:\=|\=\"|\=\')text\/html[\s \t\n\r\f]*?\;[\s \t\n\r\f]*?charset[\s \t\n\r\f]*?\=[\s \t\n\r\f]*?([A-Za-z0-9\-\_]+)[\s \t\n\r\f]*?(?:"|')?[\s \t\n\r\f]+?http\-equiv[\s \t\n\r\f]*?\=(?:\=|\=\"|\=\')Content\-Type(?:\"|\')?[^\>]*?\/?[^\>]*?\>/i).to_a[1]
309         end
310       elsif (res['content-type'] =~ /^text\/xml[^A-Za-z0-9\-_]?/) then
311         # xml check
312         charset = body.match(/<\?xml[\s \t\n\r\f]+?version[\s \t\n\r\f]*?(?:\=|\=\"|\=\')[0-9]+\.[0-9]+(?:\"|\')?[\s \t\n\r\f]+?encoding[\s \t\n\r\f]*?(?:\=|\=\"|\=\')([A-Za-z0-9\-\_]+)(?:\"|\')?/i).to_a[1]
313         charset = "utf-8" if (!charset)
314       elsif (res['content-type'] =~  /^application\/(?:[A-Za-z0-9_\-\.]+\+xml|xml|[A-Za-z0-9_\-\.]+\.xml(?:\.[A-Za-z0-9_\-\.]+)?)[^A-Za-z0-9\-_]?/) then
315         # xmlっぽいの check
316         charset = body.match(/<\?xml[\s \t\n\r\f]+?version[\s \t\n\r\f]*?(?:\=|\=\"|\=\')[0-9]+\.[0-9]+(?:\"|\')?[\s \t\n\r\f]+?encoding[\s \t\n\r\f]*?(?:\=|\=\"|\=\')([A-Za-z0-9\-\_]+)(?:\"|\')?/i).to_a[1]
317         # デフォルト文字コードは設定しない
318       elsif (res['content-type'] =~ /^text\/css[^A-Za-z0-9\-_]?/) then
319         # css check
320         charset = body.match(/\@charset[\s]+\"([A-Za-z0-9\-\_]+)\"[\s]*\;/i).to_a[1]
321       end
322       if (charset == body) then
323         charset = nil
324       end
325     end
326     if (!charset) then
327       case Kconv.guess(body)
328         when Kconv::JIS
329           charset="jis"
330         when Kconv::EUC
331           charset="euc-jp"
332         when Kconv::SJIS
333           charset="sjis"
334         when Kconv::UTF8
335           charset="utf-8"
336         when Kconv::UTF16
337           charset="utf-16"
338         when Kconv::ASCII
339           charset="jis" # hack: ascii mode. $KCODE == "NONE" then UTF-8 mode. UTF-8 encode is yen or backslash problem :)
340         when Kconv::BINARY
341           # error
342         else
343           # error
344         end
345       # end case
346     end
347     if (charset =~ /^jis$/i or
348         charset =~ /^ISO\-2022\-JP$/i or
349         charset =~ /^csISO2022JP$/i or
350         charset =~ /^ISO\-2022\-JP\-2$/i or
351         charset =~ /^csISO2022JP2$/i) then
352       # jis
353       body.force_encoding('JIS')
354     elsif (charset =~ /^euc\-jp$/i or
355            charset =~ /^csEUCPkdFmtJapanese$/i) then
356       # euc-jp
357       body.force_encoding('EUC-JP')
358     elsif (charset =~ /^sjis$/i or
359            charset =~ /^Shift_JIS$/i or 
360            charset =~ /^Shift\-JIS$/i or # error
361            charset =~ /^Windows\-31J$/i or 
362            charset =~ /^csWindows31J$/i or 
363            charset =~ /^MS_Kanji$/i or 
364            charset =~ /^csShiftJIS$/i or
365            charset =~ /^CP932$/) then
366       # sjis
367       body.force_encoding('SJIS')
368     elsif (charset =~ /^UTF\-8$/i) then
369       # UTF-8
370       body.force_encoding('UTF-8')
371     elsif (charset =~ /^UTF\-16$/i) then
372       # UTF-16
373       body.force_encoding('UTF-16')
374     else
375       # unknown
376       body.force_encoding("ASCII-8BIT")
377     end
378     return {'body' => body, 'cookie' => get_cookie(cookie,res) }
379   else
380     print "This url can't execute this responce code in program. sorry\nRespoce Code:",res.code,"\nURL: ",url
381     exit
382   end
383 end
384
385 def check_url_header(url,header)
386   return if url[0,header.length] == header
387   print "URL header is not match. break program!\nURL:",url,"\nURL-Header:",header
388   raise
389   exit
390 end
391
392 def gen_urldata(current,key,val)
393   current = "" if (current == nil)
394   current << '&' if (current != '')
395   current << URI.encode_www_form_component(key) << "=" << URI.encode_www_form_component(val)
396   return current
397 end
398
399 def gen_urldatas(datas)
400   c = ""
401   datas.each{|k,v|
402     v.each{|v2|
403       c = gen_urldata(c,k,v2)
404     }
405   }
406   return c
407 end
408
409 def get_form_elements(doc)
410   ret = {}
411   #print doc.inner_html.encode("UTF-8").gsub(/\<\/?noscripts*(?:\/\s*)?\>/,'')
412   #doc = Nokogiri::HTML.parse(doc.inner_html.encode("UTF-8").gsub(/\<\/?noscripts*(?:\/\s*)?\>/,''))
413   doc.xpath('//input').each{ |node|
414     if (node['type'] == "text" or node['type'] == "password" or node['type'] == "hidden" or node['type'] == "submit") then
415       n = node['name']
416       n = '' if (n == nil)
417       ret[n] = [] if (ret[n] == nil)
418       ret[n].push(node['value'])
419     elsif(node['type'] == "checkbox" or node['type'] == "radio") then
420       if (node['checked'] != nil) then
421         n = node['name']
422         n = '' if (n == nil)
423         ret[n] = [] if (ret[n] == nil)
424         ret[n].push(node['value'])
425       end
426     elsif(node['type'] == "file" or node['type'] == "reset" or node['type'] == "button" or node['type'] == "image") then
427       # noting
428     else
429       print "Unknown type input type, skip:",node['type'],"\n"
430     end
431   }
432   doc.xpath('//textarea').each{ |node|
433     n = node['name']
434     n = '' if (n == nil)
435     ret[n] = [] if (ret[n] == nil)
436     ret[n].push(node['value'])
437   }
438   doc.xpath('//select').each{ |node|
439     n = node['name']
440     n = '' if (n == nil)
441     ret[n] = [] if (ret[n] == nil)
442     node.xpath('option').each{ |snode|
443       if (snode['selected'] != nil) then
444         ret[n].push(snode['value'])
445       end
446     }
447   }
448   return ret
449 end
450
451 # execute
452   # 1st access
453   puts "-> access to tsite.jp" if @enable_msg
454   ref = nil
455   ret = access_site(@urls['tsite-check-login'],nil,@tsite_cookie,ref)
456   @tsite_cookie = ret['cookie']
457   ref = @urls['tsite-check-login']
458   if (cookie_cache == nil or ret['location'] != nil or ret['body'] == nil or ret['body'] == "") then
459     puts "*  tsite.jp and yahoo.co.jp login mode" if @enable_msg
460     # default
461     url = ret['location']
462     check_url_header(url,@urls['tsite-login-url-header'])
463     # location
464     puts "-> access to tsite.jp login page" if @enable_msg
465     ret = access_site(url,nil,@tsite_cookie,ref)
466     @tsite_cookie = ret['cookie']
467     ref = url
468     url = ret['location']
469     check_url_header(url,@urls['tsite-login-url2-header'])
470     # tsite login page access
471     puts "-> access to tsite.jp login form page" if @enable_msg
472     ret = access_site(url,nil,@tsite_cookie,ref)
473     @tsite_cookie = ret['cookie']
474     doc = Nokogiri::HTML.parse(ret['body'])
475     form = doc.xpath('//form[@id="form1"]')
476     if (form.attr('action').value != @urls['tsite-yahoologin-post'] and form.attr('action').value != @urls['tsite-yahoologin-post2']) then
477       print "tsite login address is fail\nrequest:",@urls['tsite-yahoologin-post'],"\ninput:",form.attr('action').value
478       exit
479     end
480     if (form.attr('method').value.downcase != 'post') then
481       print "tsite login address method fail\nrequest:POST\ninput:",form.attr('method').value
482       exit
483     end
484     # post login to tsite
485     ref = url
486     url = @urls['tsite-yahoologin-post']
487     puts "-> access to yahoo.co.jp redirect from tsite.jp page" if @enable_msg
488     ret = access_site(url,gen_urldatas(get_form_elements(form)),@tsite_cookie,ref)
489     @tsite_cookie = ret['cookie']
490     # location yahoo login(location)
491     ref = url
492     url = ret['location']
493     check_url_header(url,@urls['yahoo-login-url-header'])
494     puts "-> access to tsite - yahoo login gw page" if @enable_msg
495     ret = access_site(url,nil,@yahoo_cookie,ref)
496     @yahoo_cookie = ret['cookie']
497     # location yahoo login page
498     ref = url
499     url = ret['location']
500     check_url_header(url,@urls['yahoo-login-url2-header'])
501     puts "-> access to yaho.co.jp login form page" if @enable_msg
502     ret = access_site(url,nil,@yahoo_cookie,ref)
503     @yahoo_cookie = ret['cookie']
504     doc = Nokogiri::HTML.parse(ret['body'])
505     form = doc.xpath('//form[@id="login_form"]')
506     if (form.attr('action').value != @urls['yahoo-login']) then
507       print "tsite login address is fail\nrequest:",@urls['yahoo-login'],"\ninput:",form.attr('action').value
508       exit
509     end
510     if (form.attr('method').value.downcase != 'post') then
511       print "tsite login address method fail\nrequest:POST\ninput:",form.attr('method').value
512       exit
513     end
514     # post login to yahoo
515     puts "*  yahoo.co.jp login, wait a 5 sec" if @enable_msg
516     sleep(5)
517     ref = url
518     url = @urls['yahoo-login']
519     fdata = get_form_elements(form)
520     fdata['login'] = [@account['id']]
521     fdata['passwd'] = [@account['pass']]
522     # javascript : .albatross value change
523     alb = ret['body'].match(/document\.getElementsByName\(\"\.albatross\"\)\[0\]\.value\s*\=\s*\"([^"]+)\"/)[1]
524     fdata['.albatross'] = [alb] if alb != nil
525     fdata.delete('.nojs')
526     # unchecked
527     fdata.delete('.persistent')
528     fdata.delete('')
529     puts "-> access to yahoo.co.jp login" if @enable_msg
530     ret = access_site(url,gen_urldatas(fdata),@yahoo_cookie,ref)
531     @yahoo_cookie = ret['cookie']
532     authloop = false
533     while (ret['location'] == nil or ret['location'] == @urls['yahoo-login']) do
534       puts "!  login error, no direct login" if @enable_msg and !authloop
535       puts "!  captcha error, retry" if @enable_msg and authloop
536       if (ret['body'] != nil and ret['body'] != "" and ret['body'] =~ /captchaAnswer/) then
537         puts "*  yahoo.co.jp request captcha" if @enable_msg
538         doc = Nokogiri::HTML.parse(ret['body'])
539         form = doc.xpath('//form[@id="captchaForm"]')
540         fdata = get_form_elements(form)
541         imgurl = form.xpath('//img[@id="captchaV5MultiByteCaptchaImg"]')[0]['src']
542         print "画像認証画面が必要です。\n連続アクセスした時などに必要となります\n"
543         print "改行(Enter)すると次のURLを開きます。表示されている文字を入力してください\n"
544         print "URL:",imgurl,"\n"
545         gets
546         system("start "+imgurl)
547         print "表示された文字が読めない場合はそのまま改行を押してください(再トライします)\n終了する場合は、半角スペースと改行を入力してください"
548         print "表示されている文字を入力してください:"
549         STDOUT.flush
550         chap = gets
551         chap = chap.encode("UTF-8")
552         chap.chomp!
553         if (chap != nil and (chap =~ /^[  \t]+$/)) then
554           print "中止しました\n"
555           exit
556         end
557         fdata['captchaAnswer'] = [chap]
558         ref = url
559         puts "-> access to yahoo.co.jp captcha auth" if @enable_msg
560         ret = access_site(url,gen_urldatas(fdata),@yahoo_cookie,ref)
561         @yahoo_cookie = ret['cookie']
562         authloop = true
563       else
564         print "Yahoo login fail... ID or PASSWORD is error!\n"
565         exit
566       end
567     end
568     if authloop == true then
569       # location to yahoo 0
570       ref = url
571       url = ret['location'] # checked
572       check_url_header(url,@urls['yahoo-login-ok-chap-url-header'])
573       puts "*  captcha auth ok"  if @enable_msg
574       puts "-> access to yahoo.co.jp after captche page" if @enable_msg
575       ret = access_site(url,nil,@yahoo_cookie,ref)
576       @yahoo_cookie = ret['cookie']
577       if (ret['body'] != nil) then
578         puts "*  yahoo.co.jp request retry login" if @enable_msg
579         doc = Nokogiri::HTML.parse(ret['body'])
580         form = doc.xpath('//form[@id="login_form"]')
581         if (form.attr('action').value != @urls['yahoo-login']) then
582           print "tsite login address is fail\nrequest:",@urls['yahoo-login'],"\ninput:",form.attr('action').value
583           exit
584         end
585         if (form.attr('method').value.downcase != 'post') then
586           print "tsite login address method fail\nrequest:POST\ninput:",form.attr('method').value
587           exit
588         end
589         # post re-login to yahoo
590         ref = url
591         url = @urls['yahoo-login']
592         fdata = get_form_elements(form)
593         fdata['login'] = [@account['id']]
594         fdata['passwd'] = [@account['pass']]
595         fdata.delete('.nojs')
596         fdata.delete('')
597         puts "-> access to yahoo.co.jp retry login" if @enable_msg
598         ret = access_site(url,gen_urldatas(fdata),@yahoo_cookie,ref)
599         @yahoo_cookie = ret['cookie']
600         if (ret['location'] == nil) then
601           print "Yahoo login fail... ID or PASSWORD is error!\n"
602           exit
603         end
604       end
605     end
606     # Login OK
607     # location to yahoo 1
608     ref = url
609     url = ret['location']
610     check_url_header(url,@urls['yahoo-login-ok-url-header'])
611     puts "*  yahoo.co.jp login ok" if @enable_msg
612     puts "-> access to yahoo.co.jp to yahoo.co.jp auth data locate page" if @enable_msg
613     ret = access_site(url,nil,@yahoo_cookie,ref)
614     @yahoo_cookie = ret['cookie']
615     # location to yahoo 2
616     ref = url
617     url = ret['location'] # checked
618     check_url_header(url,@urls['yahoo-login-ok-url2-header'])
619     puts "-> access to yahoo.co.jp redirest to tsite.jp page" if @enable_msg
620     ret = access_site(url,nil,@yahoo_cookie,ref)
621     @yahoo_cookie = ret['cookie']
622     # return to tsite
623     ref = url
624     url = ret['location'] # checked
625     check_url_header(url,@urls['tsite-login-ok-url-header'])
626     puts "-> access to tsite.jp login ok page" if @enable_msg
627     ret = access_site(url,nil,@tsite_cookie,ref)
628     @tsite_cookie = ret['cookie']
629     # return to original URL
630     if (ret['location'] != @urls['tsite-return'] and ret['location'] != @urls['tsite-return2']) then
631       print "tsite/yahoo login error...\nlocation:",ret['location'],"\nreturn:",@urls['tsite-return'],"\nreturn2:",@urls['tsite-return2'],"\n"
632       print "このエラーは、Tカードと関連付いていないYahooIDでログインした場合も発生します\n"
633       exit
634     end
635     ref = url
636     url = @urls['tsite-disable']
637     puts "-> access to tsite.jp optout page" if @enable_msg
638     ret = access_site(url,nil,@tsite_cookie,ref)
639     @tsite_cookie = ret['cookie']
640     if (ret['location'] != nil or ret['body'] == nil or ret['body'] == "") then
641       print "tsite/yahoo login error(2)..."
642       exit
643     end
644   end
645   # login end!
646   # update data
647   doc = Nokogiri::HTML.parse(ret['body'])
648   form = nil
649   doc.xpath('//form').each{|node|
650     if (node['action'] == @urls['tsite-disable']) then
651       form = node
652       break
653     end
654   }
655   if (form == nil or form.attr('method').downcase != 'post') then
656     print "tsite update error..."
657     exit
658   end
659   fdata = get_form_elements(form)
660   #if (fdata['optout_status'] != nil) then
661   #  fdata['optout_status'].each{|id|
662   #    print "Enable ID:",id.to_s
663   #    ok = false
664   #    @enable_id.each{|eid|
665   #      if (id == eid) then
666   #        ok = true
667   #        break
668   #      end
669   #    }
670   #    if ok then
671   #      print " -> enable\n"
672   #    else
673   #      print " -> disable\n"
674   #    end
675   #  }
676   #  if (@enable_id.length > 0) then
677   #    # enable id found
678   #    @enable_id.each{|id|
679   #      print "-> Enable ID:",id.to_s,"\n"
680   #    }
681   #    fdata['optout_status'] = @enable_id
682   #  else
683   #    # all clear
684   #    fdata.delete('optout_status')
685   #  end
686   #end
687   File.open(file_output_org_html,"w"){|io|
688     io.write(ret['body'])
689   }
690   if (@enable_id.length > 0) then
691     fdata['optout_status'] = @enable_id
692   else
693     fdata.delete('optout_status')
694   end
695   # output list
696   File.open(file_output_dest_data,"w"){|io|
697     io.puts "update time: " + Time.now.to_s,""
698     form.xpath('tr').each{|node|
699       no = Nokogiri::HTML.parse(node.inner_html.encode("UTF-8"))
700       id = no.xpath('//input[@name="optout_status"]').attr('value').value
701       name = no.xpath('//div[@class="text_box01"]').inner_text.gsub(/\n.*:/,'(') + ')'
702       checked = no.xpath('//input[@name="optout_status"]').attr('checked') == nil ? false : true
703       toOn = false
704       @enable_id.each{|eid|
705         toOn = true if id == eid
706       }
707       io.print id,":",name,"\n  ",checked ? ( toOn ? "*Enable*" : "Enable->disable" ) : (toOn ? "*disable->Enable*" : "disable"),"\n"
708     }
709   }
710   puts "*  optout information" if @enable_msg
711   File.foreach(file_output_dest_data){|l|
712     l.force_encoding("UTF-8")
713     print "**  " if @enable_anser_msg and @enable_msg
714     print l if @enable_anser_msg
715   }
716   # to disable
717   ref = url
718   url = @urls['tsite-disable']
719   fdata['on_next.x'] = ["20"]
720   fdata['on_next.y'] = ["30"]
721   puts "-> access to tsite.jp optout execute" if @enable_msg
722   ret = access_site(url,gen_urldatas(fdata),@tsite_cookie,ref)
723   @tsite_cookie = ret['cookie']
724   if (ret['body'] == nil or ret['body'] == "") then
725     puts "!  optout update error!!!!"
726     puts "!! can't recovery"
727   else
728     puts "*  optout update sucsess" if @enable_msg
729   end
730   ref = url
731   url = @urls['tsite-disable']
732   puts "-> access to tsite.jp optout result page" if @enable_msg
733   ret = access_site(url,nil,@tsite_cookie,ref)
734   @tsite_cookie = ret['cookie']
735   File.open(file_output_dest_html,"w"){|io|
736     io.write(ret['body'])
737   }
738   # logput or save
739   if cookie_cache != nil then
740     puts "*  save tsite.jp cookie data" if @enable_msg
741     puts "*  tsite.jp is not logout" if @enable_msg
742     cookie_cache.transaction do
743       cookie_cache['tsite.jp'] = @tsite_cookie
744     end
745   else
746     puts "-> access to tsite.jp logout page" if @enable_msg
747     access_site(@urls['tsite-logout'],nil,@tsite_cookie,nil)
748   end
749   puts "-> access to yahoo.co.jp logout page" if @enable_msg
750   access_site(@urls['yahoo-logout'],nil,@yahoo_cookie,nil)
751   #system("start "+file_output_dest_html)
752   puts ">  program finished" if @enable_msg
753
754