OSDN Git Service

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