OSDN Git Service

Multithreads are abandoned. Alternatly, The asyncore substitutes.(#16776)
[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 import sys
29 import htmlentitydefs
30
31 from BbsType import bbs_type_judge_uri
32 from BbsType import bbs_type_exception
33 from HTMLParserEx import HTMLParserEx
34 import datfile
35 import uri_opener
36 import config
37 from http_sub import HTTPDebugHandler
38
39 GLADE_FILENAME = "submit_window.glade"
40
41 cookie_jar = cookielib.CookieJar()
42 opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookie_jar),
43                               HTTPDebugHandler)
44
45 def open(uri):
46     if not uri:
47         raise ValueError, "parameter must not be empty"
48
49     WinWrap(uri)
50
51
52 class ConfirmationHTMLParser(HTMLParserEx):
53
54     def __init__(self):
55         HTMLParserEx.__init__(self)
56         self.message = ""
57         self.inputs = []
58         self.complete = False
59         self.title = ""
60         self.in_head = False
61         self.in_title = False
62
63     def handle_starttag(self, tag, attr):
64         if tag == "br":
65             self.message += "\n"
66         elif tag == "input":
67             self.inputs.append(dict(attr))
68         elif tag == "title":
69             self.in_title = True
70         elif tag == "head":
71             self.in_head = True
72         elif tag == "meta":
73             attr_dict = dict(attr)
74             if "http-equiv" in attr_dict \
75                and attr_dict["http-equiv"] == "refresh":
76                 self.complete = True
77
78     def handle_endtag(self, tag):
79         if tag == "title":
80             self.in_title = False
81         elif tag == "head":
82             self.in_head = False
83
84     def handle_comment(self, comment):
85         pass
86
87     def handle_data(self, data):
88         if self.in_title:
89             self.title = data
90         elif not self.in_head:
91             self.message += data.rstrip()
92
93     def handle_charref(self, ref):
94         data = None
95         try:
96             data = unichr(int(ref))
97         except:
98             data = "&#"+ref+";"
99         self.message += data
100
101     def handle_entityref(self, name):
102         if name in htmlentitydefs.name2codepoint:
103             codepoint = htmlentitydefs.name2codepoint[name]
104             self.message += unichr(codepoint)
105         else:
106             self.message += "&"+name+";"
107
108
109 class WinWrap:
110
111     def __init__(self, uri):
112         self.uri = uri
113         self.bbs_type = bbs_type_judge_uri.get_type(uri)
114         if not self.bbs_type.is_thread():
115             raise bbs_type_exception.BbsTypeError, \
116                   "the uri does not represent thread: " + uri
117
118         glade_path = os.path.join(config.glade_dir, GLADE_FILENAME)
119         self.widget_tree = gtk.glade.XML(glade_path)
120         self.window = self.widget_tree.get_widget("submit_window")
121         self.entry_name = self.widget_tree.get_widget("entry_name")
122         self.entry_mail = self.widget_tree.get_widget("entry_mail")
123         self.textbuffer = self.widget_tree.get_widget("textview").get_buffer()
124
125         sigdic = {"on_submit_activate": self.on_submit_activate,
126                   "on_close_activate": self.on_close_activate}
127
128         self.widget_tree.signal_autoconnect(sigdic)
129
130         title = datfile.get_title_from_dat(self.bbs_type)
131         if title:
132             self.window.set_title(title)
133
134     def on_close_activate(self, widget):
135         self.window.destroy()
136
137     def on_submit_activate(self, widget):
138         name = self.entry_name.get_text()
139         mail = self.entry_mail.get_text()
140         msg = self.textbuffer.get_text(
141             self.textbuffer.get_start_iter(), self.textbuffer.get_end_iter())
142
143         self.post_dict = self.bbs_type.build_post_dict(name, mail, msg)
144         self.post_dict = self.bbs_type.set_extra_post(self.post_dict)
145
146         self.do_submit()
147
148     def do_submit(self):
149         for name, value in self.post_dict.iteritems():
150             print "%s: %s" \
151                   % (name, value.decode(self.bbs_type.encoding, "replace"))
152         post_encoded = urllib.urlencode(self.post_dict)
153
154         req = urllib2.Request(self.bbs_type.get_post_uri(), post_encoded)
155         req.add_header("Referer", self.uri)
156         req.add_header("User-agent", config.User_Agent)
157
158         res = opener.open(req)
159         self.on_response(res)
160
161     def on_response(self, response):
162         data = response.read()
163         info = response.info()
164
165         # suppose same encoding used in dat files.
166         encoding = self.bbs_type.encoding
167         # if there is charset in response headers, use it.
168         if "Content-Type" in info:
169             import re
170             match = re.search(
171                 "charset=(?P<charset>[a-zA-Z0-9_\-]+)", info["Content-Type"])
172             if match:
173                 charset = match.group("charset").lower()
174
175                 if charset in ("x-sjis", "x_sjis", "sjis", "shiftjis",
176                                "shift-jis", "shift_jis", "s-jis", "s_jis"):
177                     encoding = "cp932"
178                 elif charset in ("euc-jp", "euc_jp", "eucjp"):
179                     encoding = "euc-jp"
180         data = data.decode(encoding, "replace")
181         p = ConfirmationHTMLParser()
182         p.feed(data)
183         p.close()
184
185         print data
186
187         window = gtk.Window()
188         if not p.complete:
189             window.set_default_size(500, 500)
190         if p.title:
191             window.set_title(p.title)
192         textview = gtk.TextView()
193         textview.set_wrap_mode(gtk.WRAP_CHAR)
194         textview.set_editable(False)
195         buf = textview.get_buffer()
196         buf.insert(buf.get_end_iter(), p.message)
197
198         for input in p.inputs:
199             if "type" in input and input["type"] == "submit":
200                 button = gtk.Button(input["value"])
201                 button.connect("clicked",
202                                lambda widget: self.on_button_submit_clicked(
203                     widget, p.inputs, encoding))
204                 anchor = buf.create_child_anchor(buf.get_end_iter())
205                 textview.add_child_at_anchor(button, anchor)
206                 button.grab_focus()
207                 break
208
209         window.add(textview)
210         window.show_all()
211
212         if p.complete:
213
214             def on_timeout(widget):
215                 widget.destroy()
216                 uri_opener.open_uri(self.bbs_type.get_thread_uri(), True)
217                 self.window.destroy()
218
219             gobject.timeout_add(2 * 1000, on_timeout, window)
220
221     def on_button_submit_clicked(self, widget, inputs, encoding):
222         widget.get_toplevel().destroy()
223         self.post_dict = {}
224         for input in inputs:
225             if "name" in input and "value" in input:
226                 name = input["name"]
227                 value = input["value"].replace("&#10;", "\n");
228                 if encoding:
229                     value = value.encode(encoding, "replace")
230                 self.post_dict[name] = value
231
232         self.do_submit()