OSDN Git Service

3b2985b5031b17f3576a2be06fd89393f63664ca
[fukui-no-namari/fukui-no-namari.git] / src / FukuiNoNamari / submit_window.py
1 # Copyright (C) 2006 by Aiwota Programmer
2 # aiwotaprog@tetteke.tk
3 #
4 # This program is free software; you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation; either version 2 of the License, or
7 # (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17
18 import pygtk
19 pygtk.require('2.0')
20 import gtk
21 import gtk.glade
22 import gobject
23 import codecs
24 import urllib
25 import urllib2
26 import cookielib
27 import os.path
28
29 from BbsType import bbs_type_judge_uri
30 from BbsType import bbs_type_exception
31 from HTMLParserEx import HTMLParserEx
32 import datfile
33 import uri_opener
34 from http_sub import HTTPDebugHandler
35
36 GLADE_DIR = os.path.join(os.path.dirname(os.path.realpath(__file__)),
37                          "..", "data")
38 GLADE_FILENAME = "submit_window.glade"
39
40 cookie_jar = cookielib.CookieJar()
41 opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookie_jar),
42                               HTTPDebugHandler)
43
44 def open(uri):
45     if not uri:
46         raise ValueError, "parameter must not be empty"
47
48     WinWrap(uri)
49
50
51 class ConfirmationHTMLParser(HTMLParserEx):
52
53     def __init__(self):
54         HTMLParserEx.__init__(self)
55         self.message = ""
56         self.inputs = []
57         self.complete = False
58
59     def handle_starttag(self, tag, attr):
60         if tag == "br":
61             self.message += "\n"
62         elif tag == "input":
63             self.inputs.append(dict(attr))
64         elif tag == "meta":
65             attr_dict = dict(attr)
66             if "http-equiv" in attr_dict \
67                and attr_dict["http-equiv"] == "refresh":
68                 self.complete = True
69
70     def handle_endtag(self, tag):
71         pass
72
73     def handle_comment(self, comment):
74         print comment.strip()
75
76     def handle_data(self, data):
77         self.message += data
78
79     def handle_charref(self, ref):
80         data = None
81         try:
82             data = unichr(int(ref))
83         except:
84             data = "&#"+ref+";"
85         self.message += data
86
87     def handle_entityref(self, name):
88         if name in htmlentitydefs.name2codepoint:
89             codepoint = htmlentitydefs.name2codepoint[name]
90             self.message += unichr(codepoint)
91         else:
92             self.message += "&"+name+";"
93
94
95 class WinWrap:
96
97     def __init__(self, uri):
98         self.uri = uri
99         self.bbs_type = bbs_type_judge_uri.get_type(uri)
100         if not self.bbs_type.is_thread():
101             raise bbs_type_exception.BbsTypeError, \
102                   "the uri does not represent thread: " + uri
103
104         glade_path = os.path.join(GLADE_DIR, GLADE_FILENAME)
105         self.widget_tree = gtk.glade.XML(glade_path)
106         self.window = self.widget_tree.get_widget("submit_window")
107         self.entry_name = self.widget_tree.get_widget("entry_name")
108         self.entry_mail = self.widget_tree.get_widget("entry_mail")
109         self.textbuffer = self.widget_tree.get_widget("textview").get_buffer()
110
111         sigdic = {"on_submit_activate": self.on_submit_activate,
112                   "on_close_activate": self.on_close_activate}
113
114         self.widget_tree.signal_autoconnect(sigdic)
115
116         title = datfile.get_title_from_dat(self.bbs_type)
117         if title:
118             self.window.set_title(title)
119
120     def on_close_activate(self, widget):
121         self.window.destroy()
122
123     def on_submit_activate(self, widget):
124         name = self.entry_name.get_text()
125         mail = self.entry_mail.get_text()
126         msg = self.textbuffer.get_text(
127             self.textbuffer.get_start_iter(), self.textbuffer.get_end_iter())
128
129         self.post_dict = self.bbs_type.build_post_dict(name, mail, msg)
130         self.post_dict = self.bbs_type.set_extra_post(self.post_dict)
131
132         self.do_submit()
133
134     def do_submit(self):
135         post_encoded = urllib.urlencode(self.post_dict)
136         print post_encoded
137
138         req = urllib2.Request(self.bbs_type.get_post_uri(), post_encoded)
139         req.add_header("Referer", self.uri)
140
141         res = opener.open(req)
142         self.on_response(res)
143
144     def on_response(self, response):
145         data = response.read()
146         info = response.info()
147         if "Content-Type" in info:
148             import re
149             match = re.search(
150                 "charset=(?P<charset>[a-zA-Z0-9_\-]+)", info["Content-Type"])
151             if match:
152                 charset = match.group("charset").lower()
153
154         if charset in ("x-sjis", "x_sjis", "sjis", "shiftjis", "shift-jis",
155                        "shift_jis", "s-jis", "s_jis"):
156             encoding = "cp932"
157         elif charset in ("euc-jp", "euc_jp", "eucjp"):
158             encoding = "euc-jp"
159
160         if encoding:
161             data = data.decode(encoding, "replace")
162         p = ConfirmationHTMLParser()
163         p.feed(data)
164         p.close()
165
166         print data
167
168         window = gtk.Window()
169         if not p.complete:
170             window.set_default_size(500, 500)
171         textview = gtk.TextView()
172         textview.set_wrap_mode(gtk.WRAP_CHAR)
173         textview.set_editable(False)
174         buf = textview.get_buffer()
175         buf.insert(buf.get_end_iter(), p.message)
176
177         for input in p.inputs:
178             if "type" in input and input["type"] == "submit":
179                 button = gtk.Button(input["value"])
180                 button.connect("clicked",
181                                lambda widget: self.on_button_submit_clicked(
182                     widget, p.inputs, encoding))
183                 anchor = buf.create_child_anchor(buf.get_end_iter())
184                 textview.add_child_at_anchor(button, anchor)
185                 button.grab_focus()
186                 break
187
188         window.add(textview)
189         window.show_all()
190
191         if p.complete:
192
193             def on_timeout(widget):
194                 widget.destroy()
195                 uri_opener.open_uri(self.bbs_type.get_thread_uri(), True)
196
197             gobject.timeout_add(2 * 1000, on_timeout, window)
198
199     def on_button_submit_clicked(self, widget, inputs, encoding):
200         widget.get_toplevel().destroy()
201         self.post_dict = {}
202         for input in inputs:
203             if "name" in input and "value" in input:
204                 name = input["name"]
205                 value = input["value"]
206                 if encoding:
207                     value = value.encode(encoding, "replace")
208                 self.post_dict[name] = value
209
210         self.do_submit()