OSDN Git Service

5eb97beaa810b7ca1658639e790ce6c64436d3f8
[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         if "Content-Type" in info:
165             import re
166             match = re.search(
167                 "charset=(?P<charset>[a-zA-Z0-9_\-]+)", info["Content-Type"])
168             if match:
169                 charset = match.group("charset").lower()
170
171         if charset in ("x-sjis", "x_sjis", "sjis", "shiftjis", "shift-jis",
172                        "shift_jis", "s-jis", "s_jis"):
173             encoding = "cp932"
174         elif charset in ("euc-jp", "euc_jp", "eucjp"):
175             encoding = "euc-jp"
176
177         if encoding:
178             data = data.decode(encoding, "replace")
179         p = ConfirmationHTMLParser()
180         p.feed(data)
181         p.close()
182
183         print data
184
185         window = gtk.Window()
186         if not p.complete:
187             window.set_default_size(500, 500)
188         if p.title:
189             window.set_title(p.title)
190         textview = gtk.TextView()
191         textview.set_wrap_mode(gtk.WRAP_CHAR)
192         textview.set_editable(False)
193         buf = textview.get_buffer()
194         buf.insert(buf.get_end_iter(), p.message)
195
196         for input in p.inputs:
197             if "type" in input and input["type"] == "submit":
198                 button = gtk.Button(input["value"])
199                 button.connect("clicked",
200                                lambda widget: self.on_button_submit_clicked(
201                     widget, p.inputs, encoding))
202                 anchor = buf.create_child_anchor(buf.get_end_iter())
203                 textview.add_child_at_anchor(button, anchor)
204                 button.grab_focus()
205                 break
206
207         window.add(textview)
208         window.show_all()
209
210         if p.complete:
211
212             def on_timeout(widget):
213                 widget.destroy()
214                 uri_opener.open_uri(self.bbs_type.get_thread_uri(), True)
215                 self.window.destroy()
216
217             gobject.timeout_add(2 * 1000, on_timeout, window)
218
219     def on_button_submit_clicked(self, widget, inputs, encoding):
220         widget.get_toplevel().destroy()
221         self.post_dict = {}
222         for input in inputs:
223             if "name" in input and "value" in input:
224                 name = input["name"]
225                 value = input["value"].replace("&#10;", "\n");
226                 if encoding:
227                     value = value.encode(encoding, "replace")
228                 self.post_dict[name] = value
229
230         self.do_submit()