Merge lp:~tsyrus/pastebinit/pastebinthat into lp:pastebinit
- pastebinthat
- Merge into trunk
Proposed by
Terence Syrus
Status: | Work in progress |
---|---|
Proposed branch: | lp:~tsyrus/pastebinit/pastebinthat |
Merge into: | lp:pastebinit |
Diff against target: |
1419 lines (+639/-483) 21 files modified
pastebin.d/cxg.de.conf (+4/-7) pastebin.d/dpaste.com.conf (+17/-0) pastebin.d/fpaste.org.conf (+1/-1) pastebin.d/lpaste.net.conf (+2/-3) pastebin.d/p.defau.lt.conf (+2/-5) pastebin.d/paste.debian.net.conf (+1/-1) pastebin.d/paste.drizzle.org.conf (+6/-9) pastebin.d/paste.kde.org.conf (+10/-14) pastebin.d/paste.openstack.org.conf (+6/-9) pastebin.d/paste.pound-python.org.conf (+1/-1) pastebin.d/paste.ubuntu.com.conf (+1/-1) pastebin.d/paste.ubuntu.org.cn.conf (+1/-1) pastebin.d/paste2.org.conf (+1/-1) pastebin.d/pastebin.com.conf (+4/-5) pastebin.d/pastebin.mate-desktop.org.conf (+7/-9) pastebin.d/pb.daviey.com.conf (+4/-5) pastebin.d/slexy.org.conf (+2/-3) pastebin.d/sprunge.us.conf (+3/-5) pastebinit (+417/-398) test.py (+135/-0) test.sh (+14/-5) |
To merge this branch: | bzr merge lp:~tsyrus/pastebinit/pastebinthat |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Pastebinit Developers | Pending | ||
Review via email:
|
Commit message
Description of the change
Complete overhaul of pastebinit:
* significantly cleaned up code for less coupling and more readability
* changed config to a more sensible structure:
** only posted parameters are in the format section now
** parameters that were previously hidden but listed in the format section now live in the pastebin section
* added unit tests
* merged in all branches from ~blueyed
To post a comment you must log in.
Unmerged revisions
- 218. By Terence Syrus <email address hidden>
-
removed debug
- 217. By Terence Syrus <email address hidden>
-
removed unused method
- 216. By Terence Syrus <email address hidden>
-
added unit tests
- 215. By Terence Syrus <email address hidden>
-
major overhaul: tests + cleanup
- 214. By Terence Syrus <email address hidden>
-
major cleanup
also, updated pastebin.mate-desktop. org.conf - 213. By Terence Syrus <email address hidden>
-
merged changes from Daniel Hahler
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'pastebin.d/cxg.de.conf' |
2 | --- pastebin.d/cxg.de.conf 2012-06-13 16:41:21 +0000 |
3 | +++ pastebin.d/cxg.de.conf 2014-12-02 02:23:09 +0000 |
4 | @@ -1,14 +1,11 @@ |
5 | [pastebin] |
6 | basename = cxg.de |
7 | -regexp = http://cxg.de |
8 | +id_regexp = http://cxg.de |
9 | +result_type = url |
10 | +result_regexp = href="(http://cxg.de/.*)" |
11 | +page = /paste.php |
12 | |
13 | [format] |
14 | user = desc |
15 | content = pastetext |
16 | format = lang |
17 | -page = page |
18 | -regexp = regexp |
19 | - |
20 | -[defaults] |
21 | -page = /paste.php |
22 | -regexp = href="http://cxg.de/(.*)" |
23 | |
24 | === added file 'pastebin.d/dpaste.com.conf' |
25 | --- pastebin.d/dpaste.com.conf 1970-01-01 00:00:00 +0000 |
26 | +++ pastebin.d/dpaste.com.conf 2014-12-02 02:23:09 +0000 |
27 | @@ -0,0 +1,17 @@ |
28 | +[pastebin] |
29 | +basename = dpaste.com |
30 | +id_regexp = http://dpaste.com |
31 | +page = /api/v1/ |
32 | + |
33 | +[format] |
34 | +user = poster |
35 | +content = content |
36 | +title = title |
37 | +format = language |
38 | +hold = hold |
39 | + |
40 | +[defaults] |
41 | +# Empty means "Plain". |
42 | +format = |
43 | +# Keep it for 30 days after last access. Otherwise only for 7 days. |
44 | +hold = on |
45 | |
46 | === modified file 'pastebin.d/fpaste.org.conf' |
47 | --- pastebin.d/fpaste.org.conf 2014-01-06 20:58:13 +0000 |
48 | +++ pastebin.d/fpaste.org.conf 2014-12-02 02:23:09 +0000 |
49 | @@ -1,6 +1,6 @@ |
50 | [pastebin] |
51 | basename = fpaste.org |
52 | -regexp = http://fpaste.org |
53 | +id_regexp = http://fpaste.org |
54 | |
55 | [format] |
56 | user = paste_user |
57 | |
58 | === modified file 'pastebin.d/lpaste.net.conf' |
59 | --- pastebin.d/lpaste.net.conf 2014-01-06 22:59:43 +0000 |
60 | +++ pastebin.d/lpaste.net.conf 2014-12-02 02:23:09 +0000 |
61 | @@ -1,6 +1,7 @@ |
62 | [pastebin] |
63 | basename = lpaste.net |
64 | -regexp = http://lpaste.net |
65 | +id_regexp = http://lpaste.net |
66 | +page = new |
67 | |
68 | [format] |
69 | public = public |
70 | @@ -10,10 +11,8 @@ |
71 | channel = channel |
72 | content = paste |
73 | email = email |
74 | -page = page |
75 | |
76 | [defaults] |
77 | -page = new |
78 | public = Public |
79 | channel = |
80 | email = |
81 | |
82 | === modified file 'pastebin.d/p.defau.lt.conf' |
83 | --- pastebin.d/p.defau.lt.conf 2012-06-13 16:41:21 +0000 |
84 | +++ pastebin.d/p.defau.lt.conf 2014-12-02 02:23:09 +0000 |
85 | @@ -1,10 +1,7 @@ |
86 | [pastebin] |
87 | basename = p.defau.lt |
88 | -regexp = http://p.defau.lt |
89 | +id_regexp = http://p.defau.lt |
90 | +page = /submit.php |
91 | |
92 | [format] |
93 | content = code |
94 | -page = page |
95 | - |
96 | -[defaults] |
97 | -page = /submit.php |
98 | |
99 | === modified file 'pastebin.d/paste.debian.net.conf' |
100 | --- pastebin.d/paste.debian.net.conf 2012-06-13 16:41:21 +0000 |
101 | +++ pastebin.d/paste.debian.net.conf 2014-12-02 02:23:09 +0000 |
102 | @@ -1,6 +1,6 @@ |
103 | [pastebin] |
104 | basename = paste.debian.net |
105 | -regexp = http://paste.debian.net |
106 | +id_regexp = https?://paste.debian.net |
107 | |
108 | [format] |
109 | user = poster |
110 | |
111 | === modified file 'pastebin.d/paste.drizzle.org.conf' |
112 | --- pastebin.d/paste.drizzle.org.conf 2012-06-13 16:41:21 +0000 |
113 | +++ pastebin.d/paste.drizzle.org.conf 2014-12-02 02:23:09 +0000 |
114 | @@ -1,18 +1,15 @@ |
115 | [pastebin] |
116 | basename = paste.drizzle.org |
117 | -regexp = http://paste.drizzle.org |
118 | +id_regexp = http://paste.drizzle.org |
119 | +target_url = http://paste.drizzle.org/show/ |
120 | +result_type = id |
121 | +result_regexp = \"data\": \"([^"]*) |
122 | +post_format = json |
123 | +page = /json/?method=pastes.newPaste |
124 | |
125 | [format] |
126 | lang = language |
127 | -page = page |
128 | content = code |
129 | -post_format = post_format |
130 | -regexp = regexp |
131 | -target_url = target_url |
132 | |
133 | [defaults] |
134 | -page = /json/?method=pastes.newPaste |
135 | -post_format = json |
136 | lang = |
137 | -regexp = \"data\": \"([^"]*) |
138 | -target_url = http://paste.drizzle.org/show/ |
139 | |
140 | === modified file 'pastebin.d/paste.kde.org.conf' |
141 | --- pastebin.d/paste.kde.org.conf 2012-06-13 16:41:21 +0000 |
142 | +++ pastebin.d/paste.kde.org.conf 2014-12-02 02:23:09 +0000 |
143 | @@ -1,22 +1,18 @@ |
144 | [pastebin] |
145 | basename = paste.kde.org |
146 | -regexp = http://paste.kde.org |
147 | +id_regexp = http://paste.kde.org |
148 | +result_type = id |
149 | +result_regexp = <id>(.*)</id> |
150 | +page = /api/xml/create |
151 | |
152 | [format] |
153 | -user = paste_user |
154 | -format = paste_lang |
155 | -content = paste_data |
156 | -password = paste_password |
157 | -expire = paste_expire |
158 | -private = paste_private |
159 | -api = api_submit |
160 | -mode = mode |
161 | -regexp = regexp |
162 | +format = language |
163 | +content = data |
164 | +expire = expire |
165 | +private = private |
166 | +title = title |
167 | +password = password |
168 | |
169 | [defaults] |
170 | -private = 0 |
171 | format = text |
172 | expire = 86400 |
173 | -api = 1 |
174 | -mode = xml |
175 | -regexp = <id>(.*)</id> |
176 | |
177 | === modified file 'pastebin.d/paste.openstack.org.conf' |
178 | --- pastebin.d/paste.openstack.org.conf 2012-06-13 17:15:59 +0000 |
179 | +++ pastebin.d/paste.openstack.org.conf 2014-12-02 02:23:09 +0000 |
180 | @@ -1,18 +1,15 @@ |
181 | [pastebin] |
182 | basename = paste.openstack.org |
183 | -regexp = http://paste.openstack.org |
184 | +id_regexp = http://paste.openstack.org |
185 | +result_type = id |
186 | +result_regexp = \"data\": \"([^"]*) |
187 | +target_url = http://paste.openstack.org/show/ |
188 | +post_format = json |
189 | +page = /json/?method=pastes.newPaste |
190 | |
191 | [format] |
192 | lang = language |
193 | -page = page |
194 | content = code |
195 | -post_format = post_format |
196 | -regexp = regexp |
197 | -target_url = target_url |
198 | |
199 | [defaults] |
200 | -page = /json/?method=pastes.newPaste |
201 | -post_format = json |
202 | lang = |
203 | -regexp = \"data\": \"([^"]*) |
204 | -target_url = http://paste.openstack.org/show/ |
205 | |
206 | === modified file 'pastebin.d/paste.pound-python.org.conf' |
207 | --- pastebin.d/paste.pound-python.org.conf 2012-06-13 16:41:21 +0000 |
208 | +++ pastebin.d/paste.pound-python.org.conf 2014-12-02 02:23:09 +0000 |
209 | @@ -1,6 +1,6 @@ |
210 | [pastebin] |
211 | basename = paste.pound-python.org |
212 | -regexp = http://paste.pound-python.org |
213 | +id_regexp = http://paste.pound-python.org |
214 | |
215 | [format] |
216 | content = code |
217 | |
218 | === modified file 'pastebin.d/paste.ubuntu.com.conf' |
219 | --- pastebin.d/paste.ubuntu.com.conf 2012-06-13 16:41:21 +0000 |
220 | +++ pastebin.d/paste.ubuntu.com.conf 2014-12-02 02:23:09 +0000 |
221 | @@ -1,6 +1,6 @@ |
222 | [pastebin] |
223 | basename = paste.ubuntu.com |
224 | -regexp = http://paste.ubuntu.com |
225 | +id_regexp = http://paste.ubuntu.com |
226 | |
227 | [format] |
228 | user = poster |
229 | |
230 | === modified file 'pastebin.d/paste.ubuntu.org.cn.conf' |
231 | --- pastebin.d/paste.ubuntu.org.cn.conf 2012-06-13 16:41:21 +0000 |
232 | +++ pastebin.d/paste.ubuntu.org.cn.conf 2014-12-02 02:23:09 +0000 |
233 | @@ -1,6 +1,6 @@ |
234 | [pastebin] |
235 | basename = paste.ubuntu.org.cn |
236 | -regexp = http://paste.ubuntu.org.cn |
237 | +id_regexp = http://paste.ubuntu.org.cn |
238 | |
239 | [format] |
240 | user = poster |
241 | |
242 | === modified file 'pastebin.d/paste2.org.conf' |
243 | --- pastebin.d/paste2.org.conf 2014-01-06 23:16:01 +0000 |
244 | +++ pastebin.d/paste2.org.conf 2014-12-02 02:23:09 +0000 |
245 | @@ -1,6 +1,6 @@ |
246 | [pastebin] |
247 | basename = paste2.org |
248 | -regexp = http://paste2.org |
249 | +id_regexp = http://paste2.org |
250 | |
251 | [format] |
252 | title = description |
253 | |
254 | === modified file 'pastebin.d/pastebin.com.conf' |
255 | --- pastebin.d/pastebin.com.conf 2012-06-13 17:15:59 +0000 |
256 | +++ pastebin.d/pastebin.com.conf 2014-12-02 02:23:09 +0000 |
257 | @@ -1,6 +1,9 @@ |
258 | [pastebin] |
259 | basename = pastebin.com |
260 | -regexp = http://((([a-zA-Z0-9\-_\.]*)(pastebin\.com))) |
261 | +id_regexp = http://((([a-zA-Z0-9\-_\.]*)(pastebin\.com))) |
262 | +result_type = url |
263 | +result_regexp = (.*) |
264 | +page = /api/api_post.php |
265 | |
266 | [format] |
267 | content = api_paste_code |
268 | @@ -10,9 +13,7 @@ |
269 | expiry = api_paste_expire_date |
270 | format = api_paste_format |
271 | email = api_paste_email |
272 | -page = page |
273 | submit = submit |
274 | -regexp = regexp |
275 | api_dev_key = api_dev_key |
276 | api_option = api_option |
277 | |
278 | @@ -25,5 +26,3 @@ |
279 | email = |
280 | api_dev_key = 253ce2f0a45140ee0a44ca99aa492260 |
281 | api_option = paste |
282 | -page = /api/api_post.php |
283 | -regexp = (.*) |
284 | |
285 | === modified file 'pastebin.d/pastebin.mate-desktop.org.conf' |
286 | --- pastebin.d/pastebin.mate-desktop.org.conf 2014-01-06 20:40:29 +0000 |
287 | +++ pastebin.d/pastebin.mate-desktop.org.conf 2014-12-02 02:23:09 +0000 |
288 | @@ -1,14 +1,12 @@ |
289 | [pastebin] |
290 | basename = pastebin.mate-desktop.org |
291 | -regexp = http://pastebin.mate-desktop.org |
292 | +page = /api/json/create |
293 | +id_regexp = http://pastebin.mate-desktop.org |
294 | +result_type = id |
295 | +result_regexp = "id": "([^"]*)" |
296 | +post_format = json |
297 | |
298 | [format] |
299 | -content = text |
300 | +content = data |
301 | user = name |
302 | -format = lang |
303 | -page = page |
304 | -regexp = regexp |
305 | - |
306 | -[defaults] |
307 | -page = /api/create |
308 | -regexp = (.*) |
309 | +format = language |
310 | |
311 | === modified file 'pastebin.d/pb.daviey.com.conf' |
312 | --- pastebin.d/pb.daviey.com.conf 2012-06-13 17:15:59 +0000 |
313 | +++ pastebin.d/pb.daviey.com.conf 2014-12-02 02:23:09 +0000 |
314 | @@ -1,16 +1,15 @@ |
315 | [pastebin] |
316 | basename = pb.daviey.com |
317 | -regexp = http://pb.daviey.com |
318 | +id_regexp = http://pb.daviey.com |
319 | +result_regexp = "/(.*/)".* |
320 | +result_type = id |
321 | +page = api/?_call=new |
322 | |
323 | [format] |
324 | user = author |
325 | content = content |
326 | -page = page |
327 | expire_options = expires |
328 | title = title |
329 | -regexp = regexp |
330 | |
331 | [defaults] |
332 | -page = api/?_call=new |
333 | -regexp = "/(.*/)".* |
334 | expire_options = 7889232 |
335 | |
336 | === modified file 'pastebin.d/slexy.org.conf' |
337 | --- pastebin.d/slexy.org.conf 2012-06-13 17:15:59 +0000 |
338 | +++ pastebin.d/slexy.org.conf 2014-12-02 02:23:09 +0000 |
339 | @@ -1,12 +1,12 @@ |
340 | [pastebin] |
341 | basename = slexy.org |
342 | -regexp = http://slexy.org |
343 | +id_regexp = http://slexy.org |
344 | +page = /index.php/submit |
345 | |
346 | [format] |
347 | user = author |
348 | content = raw_paste |
349 | title = desc |
350 | -page = page |
351 | language = language |
352 | permissions = permissions |
353 | linenumbers = linenumbers |
354 | @@ -16,7 +16,6 @@ |
355 | |
356 | [defaults] |
357 | submit = Submit Paste |
358 | -page = /index.php/submit |
359 | language = text |
360 | permissions = 0 |
361 | comment = |
362 | |
363 | === modified file 'pastebin.d/sprunge.us.conf' |
364 | --- pastebin.d/sprunge.us.conf 2012-06-13 16:41:21 +0000 |
365 | +++ pastebin.d/sprunge.us.conf 2014-12-02 02:23:09 +0000 |
366 | @@ -1,11 +1,9 @@ |
367 | [pastebin] |
368 | basename = sprunge.us |
369 | -regexp = http://sprunge.us |
370 | +id_regexp = http://sprunge.us |
371 | +result_regexp=http://sprunge.us/(.*)$ |
372 | +result_type = id |
373 | |
374 | [format] |
375 | content = sprunge |
376 | format = lang |
377 | -regexp = regexp |
378 | - |
379 | -[defaults] |
380 | -regexp=http://sprunge.us/(.*)$ |
381 | |
382 | === modified file 'pastebinit' |
383 | --- pastebinit 2014-01-18 04:51:35 +0000 |
384 | +++ pastebinit 2014-12-02 02:23:09 +0000 |
385 | @@ -4,7 +4,7 @@ |
386 | # Author: Stéphane Graber <stgraber@ubuntu.com> |
387 | # Written by Stéphane Graber <stgraber@stgraber.org> |
388 | # Daniel Bartlett <dan@f-box.org> |
389 | -# Last modification : Mon Jan 6 18:46:46 EST 2014 |
390 | +# Last modification : Mon Nov 24 15:07:45 EST 2014 |
391 | |
392 | # This program is free software; you can redistribute it and/or modify |
393 | # it under the terms of the GNU General Public License as published by |
394 | @@ -23,224 +23,48 @@ |
395 | from __future__ import print_function |
396 | |
397 | import sys |
398 | +import os |
399 | +import re |
400 | +import getopt |
401 | +import gettext |
402 | +import socket |
403 | +import xml.dom.minidom |
404 | + |
405 | if sys.version[0] == "2": |
406 | - from ConfigParser import SafeConfigParser |
407 | + from ConfigParser import SafeConfigParser, NoOptionError, NoSectionError |
408 | from urllib import urlencode |
409 | from urllib import FancyURLopener |
410 | else: |
411 | - from configparser import SafeConfigParser |
412 | + #SafeConfigParser is now a deprecated alias to ConfigParser |
413 | + from configparser import \ |
414 | + ConfigParser as SafeConfigParser, NoOptionError, NoSectionError |
415 | from urllib.parse import urlencode |
416 | from urllib.request import FancyURLopener |
417 | |
418 | -# Set the default pastebin |
419 | -defaultPB = "http://pastebin.com" |
420 | |
421 | -# Now try to override it with a distributor pastebin |
422 | try: |
423 | - import lsb_release |
424 | - release = lsb_release.get_distro_information()['ID'].lower() |
425 | - if release == 'debian': |
426 | - defaultPB = "http://paste.debian.net" |
427 | - elif release == 'fedora': |
428 | - defaultPB = "http://fpaste.org" |
429 | - elif release == 'ubuntu': |
430 | - defaultPB = "http://paste.ubuntu.com" |
431 | + import json |
432 | except ImportError: |
433 | - pass |
434 | - |
435 | -try: |
436 | - import getopt |
437 | - import gettext |
438 | - import os |
439 | - import re |
440 | - import socket |
441 | - import xml.dom.minidom |
442 | - |
443 | - try: |
444 | - import json |
445 | - except ImportError: |
446 | - json = None |
447 | - |
448 | - _ = gettext.gettext |
449 | - gettext.textdomain("pastebinit") |
450 | - |
451 | - # Timeout after 5s |
452 | - socket.setdefaulttimeout(5) |
453 | - |
454 | - # Version number to show in the usage |
455 | - version = "1.4.1" |
456 | - configfile = os.path.expanduser("~/.pastebinit.xml") |
457 | - |
458 | - # Custom urlopener to handle 401's |
459 | - class pasteURLopener(FancyURLopener): |
460 | - version = "Pastebinit v%s" % version |
461 | - |
462 | - def http_error_401(self, url, fp, errcode, errmsg, headers, data=None): |
463 | - return None |
464 | - |
465 | - def preloadPastebins(): |
466 | - # Check several places for config files: |
467 | - # - global config in /etc/pastebin.d |
468 | - # - for source checkout, config in the checkout |
469 | - # - user's overrides in ~/.pastebin.d |
470 | - # Files found later override files found earlier. |
471 | - pastebind = {} |
472 | - for confdir in ['/usr/share/pastebin.d', '/etc/pastebin.d', |
473 | - '/usr/local/etc/pastebin.d', |
474 | - os.path.expanduser('~/.pastebin.d'), |
475 | - os.path.join( |
476 | - os.path.dirname( |
477 | - os.path.realpath(__file__)), 'pastebin.d')]: |
478 | - try: |
479 | - confdirlist = os.listdir(confdir) |
480 | - except OSError: |
481 | - continue |
482 | - |
483 | - for fileitem in confdirlist: |
484 | - if fileitem.startswith('.') or not fileitem.endswith('.conf'): |
485 | - continue |
486 | - |
487 | - filename = os.path.join(confdir, fileitem) |
488 | - instance = SafeConfigParser() |
489 | - try: |
490 | - instance.read(filename) |
491 | - except UnicodeError: |
492 | - continue |
493 | - |
494 | - if not instance.has_section('pastebin'): |
495 | - print(_('%s: no section [pastebin]') % filename, |
496 | - file=sys.stderr) |
497 | - continue |
498 | - |
499 | - if not instance.has_option('pastebin', 'basename'): |
500 | - print(_("%s: no 'basename' in [pastebin]") % filename, |
501 | - file=sys.stderr) |
502 | - continue |
503 | - |
504 | - pastebind[instance.get('pastebin', 'basename')] = instance |
505 | - return pastebind |
506 | - |
507 | - # pastey.net obfuscates parent ids for replies. Rather than taking the |
508 | - # post ID given as the parent ID, we must handle this by going to that |
509 | - # post page and looking up what the invisible parent ID field will be |
510 | - # set to for children. |
511 | - def doParentFixup(website, paramname, parentid): |
512 | - if parentid == "": |
513 | - return "" |
514 | - url_opener = pasteURLopener() |
515 | - page = url_opener.open(website + '/' + parentid, None) |
516 | - matches = re.split('<input.*?name="' + paramname + '".*?value="(.*?)"', |
517 | - page.read()) |
518 | - if len(matches) <= 1 or re.match(parentid, matches[1]) is None: |
519 | - # The obfuscated version didn't begin with the partial version, |
520 | - # or unable to find the obfuscated version for some reason! |
521 | - # Create a paste with no parent (should we throw, instead?) |
522 | - return "" |
523 | - return matches[1] |
524 | - |
525 | - #Return the parameters depending of the pastebin used |
526 | - def getParameters(website, pastebind, content, user, jabberid, version, |
527 | - format, parentpid, permatag, title, username, |
528 | - password): |
529 | - "Return the parameters array for the selected pastebin" |
530 | - params = {} |
531 | - for paste_name, paste_config in pastebind.items(): |
532 | - basename = paste_config.get('pastebin', 'basename') |
533 | - if basename == website or paste_name == website: |
534 | - website = "http://%s" % basename |
535 | - |
536 | - if re.search(paste_config.get('pastebin', 'regexp'), website): |
537 | - if paste_config.has_option('pastebin', 'sizelimit'): |
538 | - params['sizelimit'] = paste_config.get('pastebin', |
539 | - 'sizelimit') |
540 | - |
541 | - for param in paste_config.options('format'): |
542 | - paramname = paste_config.get('format', param) |
543 | - if param == 'user': |
544 | - params[paramname] = user |
545 | - elif param == 'content': |
546 | - params[paramname] = content |
547 | - elif param == 'title': |
548 | - params[paramname] = title |
549 | - elif param == 'version': |
550 | - params[paramname] = version |
551 | - elif param == 'format': |
552 | - params[paramname] = format |
553 | - elif param == 'parentpid': |
554 | - params[paramname] = doParentFixup(website, paramname, |
555 | - parentpid) |
556 | - elif param == 'permatag': |
557 | - params[paramname] = permatag |
558 | - elif param == 'username': |
559 | - params[paramname] = username |
560 | - elif param == 'password': |
561 | - params[paramname] = password |
562 | - elif param == 'jabberid': |
563 | - params[paramname] = jabberid |
564 | - else: |
565 | - params[paramname] = paste_config.get('defaults', param) |
566 | - if params: |
567 | - return website, params |
568 | - else: |
569 | - print(_("Unknown website, please post a bugreport to request " |
570 | - "this pastebin to be added (%s)") % website, |
571 | - file=sys.stderr) |
572 | - sys.exit(1) |
573 | - |
574 | - #XML Handling methods |
575 | - def getText(nodelist): |
576 | - rc = "" |
577 | - for node in nodelist: |
578 | - if node.nodeType == node.TEXT_NODE: |
579 | - rc = rc + node.data |
580 | - return rc |
581 | - |
582 | - def getNodes(nodes, title): |
583 | - return nodes.getElementsByTagName(title) |
584 | - |
585 | - def getFirstNode(nodes, title): |
586 | - return getNodes(nodes, title)[0] |
587 | - |
588 | - def getFirstNodeText(nodes, title): |
589 | - return getText(getFirstNode(nodes, title).childNodes) |
590 | - |
591 | - # Display usage instructions |
592 | - def Usage(fd=sys.stdout): |
593 | - print("pastebinit v" + version, file=fd) |
594 | - print(_("Reads on stdin for input or takes a list of filenames " |
595 | - "as parameters"), file=fd) |
596 | - print(_("Optional arguments (not supported by all pastebins):"), |
597 | - file=fd) |
598 | - print(_("\t-a <author:default is '%s'>") % user, file=fd) |
599 | - print(_("\t-b <pastebin url:default is '%s'>") % website, file=fd) |
600 | - print(_("\t-f <format of paste:default is '%s'>") % format, file=fd) |
601 | - print(_("\t-h This help screen"), file=fd) |
602 | - print(_("\t-i <input file>"), file=fd) |
603 | - print(_("\t-l List all supported pastebins"), file=fd) |
604 | - print(_("\t-j <jabberid for notifications:default is '%s'>") % |
605 | - jabberid, file=fd) |
606 | - print(_("\t-m <permatag for all versions of a post:default is blank>"), |
607 | - file=fd) |
608 | - print(_("\t-r <parent posts ID:defaults to none>"), file=fd) |
609 | - print(_("\t-t <title of paste:default is blank>"), file=fd) |
610 | - print(_("\t-u <username> -p <password>"), file=fd) |
611 | - print(_("\t-v Print the version number"), file=fd) |
612 | - |
613 | - # Set defaults |
614 | - website = defaultPB |
615 | - user = os.environ.get('USER') |
616 | - jabberid = "" |
617 | - title = "" |
618 | - permatag = "" |
619 | - format = "text" |
620 | - username = "" |
621 | - password = "" |
622 | - filenames = [] |
623 | - content = "" |
624 | - parentpid = "" |
625 | - |
626 | - #Example configuration file string |
627 | - configexample = """\ |
628 | + json = None |
629 | + |
630 | +#Enables input redirection during tests |
631 | +stdin = sys.stdin |
632 | +stderr = sys.stderr |
633 | +stdout = sys.stdout |
634 | + |
635 | +_ = gettext.gettext |
636 | +gettext.textdomain("pastebinit") |
637 | + |
638 | +# Timeout after 5s |
639 | +socket.setdefaulttimeout(5) |
640 | + |
641 | +# Version number to show in the usage |
642 | +version = "1.4.1" |
643 | +config_path = os.path.expanduser("~/.pastebinit.xml") |
644 | +verbose = False |
645 | + |
646 | +#Example configuration file string |
647 | +config_example = """\ |
648 | <pastebinit> |
649 | <pastebin>http://paste.debian.net</pastebin> |
650 | <author>A pastebinit user</author> |
651 | @@ -249,201 +73,396 @@ |
652 | </pastebinit> |
653 | """ |
654 | |
655 | - #Open configuration file if it exists |
656 | - try: |
657 | - f = open(configfile) |
658 | - configtext = f.read() |
659 | + |
660 | +class PasteURLopener(FancyURLopener): |
661 | + """Custom urlopener to handle 401's""" |
662 | + version = "Pastebinit v%s" % version |
663 | + |
664 | + def __init__(self, fmt=''): |
665 | + self.fmt = fmt |
666 | + FancyURLopener.__init__(self) |
667 | + |
668 | + def http_error_401(self, url, fp, errcode, errmsg, headers, data=None): |
669 | + return None |
670 | + |
671 | + def format_params(self, params): |
672 | + if self.fmt == 'json': |
673 | + if not json: |
674 | + print(_("Could not find any json library."), file=stderr) |
675 | + sys.exit(1) |
676 | + return json.dumps(params) |
677 | + else: |
678 | + return urlencode(params) |
679 | + |
680 | + def make_request(self, url, params): |
681 | + post_params = self.format_params(params) |
682 | + |
683 | + if self.fmt == 'json': |
684 | + self.addheader('Content-type', 'text/json') |
685 | + |
686 | + if verbose: |
687 | + print("POSTing to: %s" % url, file=stderr) |
688 | + print("\nParams: %s" % str(post_params), file=stderr) |
689 | + |
690 | + try: |
691 | + return self.open(url, post_params) |
692 | + except KeyboardInterrupt: |
693 | + print(_("KeyboardInterrupt caught."), file=stderr) |
694 | + sys.exit(1) |
695 | + except Exception as e: |
696 | + print(_("Failed to contact the server: %s") % e, file=stderr) |
697 | + sys.exit(1) |
698 | + |
699 | + |
700 | +def get_default_pastebin(): |
701 | + default = "http://pastebin.com" |
702 | + try: |
703 | + import lsb_release |
704 | + return { |
705 | + 'debian': "http://paste.debian.net", |
706 | + 'fedora': "http://fpaste.org", |
707 | + 'ubuntu': "http://paste.ubuntu.com", |
708 | + }[lsb_release.get_distro_information()['ID'].lower()] |
709 | + except KeyError: |
710 | + return default |
711 | + except ImportError: |
712 | + return default |
713 | + |
714 | + |
715 | +def defaults(): |
716 | + return { |
717 | + 'website': get_default_pastebin(), |
718 | + 'user': os.environ.get('USER'), |
719 | + 'format': "text", |
720 | + 'jabberid': "", |
721 | + 'title': "", |
722 | + 'permatag': "", |
723 | + 'username': "", |
724 | + 'password': "", |
725 | + 'parentpid': "", |
726 | + 'verbose': False, |
727 | + } |
728 | + |
729 | + |
730 | +def usage(fd): |
731 | + print("pastebinit v" + version, file=fd) |
732 | + print(_("Reads on stdin for input or takes a list of filenames " |
733 | + "as parameters"), file=fd) |
734 | + print(_("Optional arguments (not supported by all pastebins):"), file=fd) |
735 | + print(_("\t-a <author:default is '%s'>") % defaults()['user'], file=fd) |
736 | + print(_("\t-b <pastebin url:default is '%s'>") % defaults()['website'], |
737 | + file=fd) |
738 | + print(_("\t-f <format of paste:default is '%s' " |
739 | + "(or from pastebin config)>") % defaults()['format'], file=fd) |
740 | + print(_("\t-h This help screen"), file=fd) |
741 | + print(_("\t-i <input file>"), file=fd) |
742 | + print(_("\t-l List all supported pastebins"), file=fd) |
743 | + print(_("\t-j <jabberid for notifications:default is '%s'>") % |
744 | + defaults()['jabberid'], file=fd) |
745 | + print(_("\t-m <permatag for all versions of a post:default is blank>"), |
746 | + file=fd) |
747 | + print(_("\t-r <parent posts ID:defaults to none>"), file=fd) |
748 | + print(_("\t-t <title of paste:default is blank>"), file=fd) |
749 | + print(_("\t-u <username> -p <password>"), file=fd) |
750 | + print(_("\t-v Print the version number"), file=fd) |
751 | + print(_("\t--verbose Verbose output to stderr"), file=fd) |
752 | + |
753 | + |
754 | +def preloadPastebins(): |
755 | + """ |
756 | + Check several places for config files: |
757 | + - global config in /etc/pastebin.d |
758 | + - for source checkout, config in the checkout |
759 | + - user's overrides in ~/.pastebin.d |
760 | + Files found later override files found earlier. |
761 | + """ |
762 | + pastebind = {} |
763 | + for confdir in ['/usr/share/pastebin.d', |
764 | + '/etc/pastebin.d', |
765 | + '/usr/local/etc/pastebin.d', |
766 | + os.path.expanduser('~/.pastebin.d'), |
767 | + os.path.join( |
768 | + os.path.dirname(os.path.realpath(__file__)), |
769 | + 'pastebin.d'), |
770 | + ]: |
771 | + try: |
772 | + confdirlist = [ |
773 | + x for x in os.listdir(confdir) |
774 | + if x.endswith('.conf') and not x.startswith('.') |
775 | + ] |
776 | + except OSError: |
777 | + continue |
778 | + |
779 | + for fileitem in confdirlist: |
780 | + filename = os.path.join(confdir, fileitem) |
781 | + parser = SafeConfigParser() |
782 | + try: |
783 | + parser.read(filename) |
784 | + except UnicodeError: |
785 | + print(_('%s: Unicode Error') % filename, file=stderr) |
786 | + continue |
787 | + |
788 | + if not parser.has_section('pastebin'): |
789 | + print(_('%s: no section [pastebin]') % filename, |
790 | + file=stderr) |
791 | + continue |
792 | + |
793 | + if not parser.has_option('pastebin', 'basename'): |
794 | + print(_("%s: no 'basename' in [pastebin]") % filename, |
795 | + file=stderr) |
796 | + continue |
797 | + |
798 | + pastebind[parser.get('pastebin', 'basename')] = parser |
799 | + return pastebind |
800 | + |
801 | + |
802 | +def doParentFixup(paramname, settings): |
803 | + """ |
804 | + pastey.net obfuscates parent ids for replies. Rather than taking the |
805 | + post ID given as the parent ID, we must handle this by going to that |
806 | + post page and looking up what the invisible parent ID field will be |
807 | + set to for children. |
808 | + """ |
809 | + website = settings['website'] |
810 | + parentid = settings['parentid'] |
811 | + if not parentid: |
812 | + return "" |
813 | + if not website.endswith("/"): |
814 | + website += "/" |
815 | + matches = re.split( |
816 | + '<input.*?name="' + paramname + '".*?value="(.*?)"', |
817 | + PasteURLopener(settings.get('post_format', '')).open( |
818 | + website + parentid.lstrip('/'), None).read() |
819 | + ) |
820 | + if len(matches) <= 1 or re.match(parentid, matches[1]) is None: |
821 | + # The obfuscated version didn't begin with the partial version, |
822 | + # or unable to find the obfuscated version for some reason! |
823 | + # Create a paste with no parent (should we throw, instead?) |
824 | + return "" |
825 | + return matches[1] |
826 | + |
827 | + |
828 | +def getPasteConfig(website): |
829 | + for paste_name, paste_config in preloadPastebins().items(): |
830 | + basename = paste_config.get('pastebin', 'basename') |
831 | + if basename == website or paste_name == website: |
832 | + website = "http://%s" % basename |
833 | + if re.search(paste_config.get('pastebin', 'id_regexp'), website): |
834 | + if not website.endswith("/"): |
835 | + website += "/" |
836 | + return paste_config, website |
837 | + |
838 | + print(_("Unknown website, please post a bugreport to request this " |
839 | + "pastebin to be added (%s)") % website, |
840 | + file=stderr) |
841 | + sys.exit(1) |
842 | + |
843 | + |
844 | +def readPasteConfig(paste_config, settings): |
845 | + """Return the parameters array for the selected pastebin""" |
846 | + |
847 | + for param in paste_config.options('pastebin'): |
848 | + settings[param] = paste_config.get('pastebin', param) |
849 | + |
850 | + post_params = {} |
851 | + for param in paste_config.options('format'): |
852 | + paramname = paste_config.get('format', param) |
853 | + |
854 | + if param == 'content': |
855 | + pass |
856 | + elif param == 'parentpid': |
857 | + post_params[paramname] = doParentFixup(paramname, settings) |
858 | + else: |
859 | + try: |
860 | + post_params[paramname] = paste_config.get('defaults', param) |
861 | + except NoOptionError: |
862 | + pass |
863 | + except NoSectionError: |
864 | + pass |
865 | + |
866 | + try: |
867 | + post_params[paramname] = settings[param] |
868 | + except KeyError: |
869 | + pass |
870 | + |
871 | + return post_params |
872 | + |
873 | + |
874 | +def getText(parent_node): |
875 | + """Read the text from an XML node""" |
876 | + rc = "" |
877 | + for node in parent_node.childNodes: |
878 | + if node.nodeType == node.TEXT_NODE: |
879 | + rc += node.data |
880 | + else: |
881 | + rc += getText(node) |
882 | + return rc |
883 | + |
884 | + |
885 | +def readFile(location, mode="r"): |
886 | + f = open(location, mode) |
887 | + try: |
888 | + return f.read() |
889 | + except KeyboardInterrupt: |
890 | + print(_("KeyboardInterrupt caught."), file=stderr) |
891 | + sys.exit(1) |
892 | + except: |
893 | + print(_("Unable to read from: %s") % location, file=stderr) |
894 | + sys.exit(1) |
895 | + finally: |
896 | f.close() |
897 | - gotconfigxml = True |
898 | + |
899 | + |
900 | +def readConfigFile(config_text): |
901 | + """Update settings from config XML""" |
902 | + try: |
903 | + settings = {} |
904 | + configxml = xml.dom.minidom.parseString(config_text) |
905 | + for xml_var, setting in (('pastebin', 'website'), |
906 | + ('author', 'user'), |
907 | + ('format', 'format'), |
908 | + ('jabberid', 'jabberid')): |
909 | + try: |
910 | + settings[setting] = getText( |
911 | + configxml.getElementsByTagName(xml_var)[0]) |
912 | + except IndexError: |
913 | + pass |
914 | + return settings |
915 | except KeyboardInterrupt: |
916 | - print(_("KeyboardInterrupt caught."), file=sys.stderr) |
917 | + print(_("KeyboardInterrupt caught."), file=stderr) |
918 | sys.exit(1) |
919 | except: |
920 | - gotconfigxml = False |
921 | - |
922 | - #Parse configuration file |
923 | - if gotconfigxml: |
924 | + print(_("Error parsing configuration file!"), file=stderr) |
925 | + print(_("Please ensure that your configuration file looks " |
926 | + "similar to the following:"), file=stderr) |
927 | + print(config_example, file=stderr) |
928 | + sys.exit(1) |
929 | + |
930 | + |
931 | +def getOpts(args=sys.argv[1:]): |
932 | + try: |
933 | + optlist, arglist = getopt.getopt( |
934 | + args, 'hvli:f:b:a:r:j:t:m:u:p:', ('verbose',)) |
935 | + except getopt.GetoptError as e: |
936 | + print(_("Invalid arguments: %s!" % e) + "\n", file=stderr) |
937 | + usage(stderr) |
938 | + sys.exit(1) |
939 | + opts = dict(optlist) |
940 | + opts['-i'] = [opt[1] for opt in optlist if opt[0] == "-i"] + arglist |
941 | + return opts |
942 | + |
943 | + |
944 | +def readOptions(opts): |
945 | + settings = {} |
946 | + |
947 | + # Die if support information is requested |
948 | + if "-h" in opts: |
949 | + usage(stdout) |
950 | + sys.exit(0) |
951 | + if "-v" in opts: |
952 | + print("pastebinit v" + version, file=stdout) |
953 | + sys.exit(0) |
954 | + if "-l" in opts: |
955 | + print(_("Supported pastebins:"), file=stdout) |
956 | + for pastebin in sorted(preloadPastebins()): |
957 | + print("- %s" % pastebin, file=stdout) |
958 | + sys.exit(0) |
959 | + |
960 | + # Configure the environment |
961 | + def setFromOpt(opt, label): |
962 | try: |
963 | - configxml = xml.dom.minidom.parseString(configtext) |
964 | - for variable, key in (('pastebin', 'website'), ('author', 'user'), |
965 | - ('format', 'format'), |
966 | - ('jabberid', 'jabberid')): |
967 | - try: |
968 | - value = getFirstNodeText(configxml, variable) |
969 | - vars()[key] = value |
970 | - except: |
971 | - pass |
972 | - except KeyboardInterrupt: |
973 | - print(_("KeyboardInterrupt caught."), file=sys.stderr) |
974 | - sys.exit(1) |
975 | - except: |
976 | - print(_("Error parsing configuration file!"), file=sys.stderr) |
977 | - print(_("Please ensure that your configuration file looks " |
978 | - "similar to the following:"), file=sys.stderr) |
979 | - print(configexample, file=sys.stderr) |
980 | - sys.exit(1) |
981 | - |
982 | - # Get options |
983 | + settings[label] = opts[opt] |
984 | + except KeyError: |
985 | + pass |
986 | + |
987 | + setFromOpt('-b', 'website') |
988 | + setFromOpt('-a', 'user') |
989 | + setFromOpt('-f', 'format') |
990 | + setFromOpt('-j', 'jabberid') |
991 | + setFromOpt('-t', 'title') |
992 | + setFromOpt('-m', 'permatag') |
993 | + setFromOpt('-u', 'username') |
994 | + setFromOpt('-p', 'password') |
995 | + setFromOpt('-r', 'parentpid') |
996 | + settings['verbose'] = "--verbose" in opts |
997 | + |
998 | + settings['contents'] = [readFile(fname, "rb") for fname in opts['-i']] |
999 | + if not settings['contents']: |
1000 | + settings['contents'].append(stdin.read()) |
1001 | + return settings |
1002 | + |
1003 | + |
1004 | +def readPageURL(page, settings): |
1005 | + website = settings['website'] |
1006 | + result_type = settings.get('result_type', None) |
1007 | try: |
1008 | - optlist, arglist = getopt.getopt(sys.argv[1:], |
1009 | - 'hvli:f:b:a:r:j:t:m:u:p:') |
1010 | - except KeyboardInterrupt: |
1011 | - print(_("KeyboardInterrupt caught."), file=sys.stderr) |
1012 | - sys.exit(1) |
1013 | - except getopt.GetoptError: |
1014 | - print(_("Invalid arguments!\n"), file=sys.stderr) |
1015 | - Usage(sys.stderr) |
1016 | - sys.exit(1) |
1017 | - |
1018 | - # Get the config |
1019 | - pastebind = preloadPastebins() |
1020 | - |
1021 | - # Iterate through options |
1022 | - for opt in optlist: |
1023 | - if opt[0] == "-h": |
1024 | - Usage() |
1025 | - sys.exit(0) |
1026 | - if opt[0] == "-i": |
1027 | - filenames.append(opt[1]) |
1028 | - elif opt[0] == "-f": |
1029 | - format = opt[1] |
1030 | - elif opt[0] == "-b": |
1031 | - website = opt[1] |
1032 | - elif opt[0] == "-a": |
1033 | - user = opt[1] |
1034 | - elif opt[0] == "-r": |
1035 | - parentpid = opt[1] |
1036 | - elif opt[0] == "-j": |
1037 | - jabberid = opt[1] |
1038 | - elif opt[0] == "-l": |
1039 | - print(_("Supported pastebins:")) |
1040 | - for pastebin in sorted(pastebind): |
1041 | - print("- %s" % pastebin) |
1042 | - sys.exit(0) |
1043 | - elif opt[0] == "-t": |
1044 | - title = opt[1] |
1045 | - elif opt[0] == "-m": |
1046 | - permatag = opt[1] |
1047 | - elif opt[0] == "-u": |
1048 | - username = opt[1] |
1049 | - elif opt[0] == "-p": |
1050 | - password = opt[1] |
1051 | - elif opt[0] == "-v": |
1052 | - print("pastebinit v" + version) |
1053 | - sys.exit(0) |
1054 | - |
1055 | - filenames += arglist |
1056 | - |
1057 | - if not filenames: |
1058 | - filenames.append("-") |
1059 | - |
1060 | - contents = [] |
1061 | - for filename in filenames: |
1062 | - # If - is specified as a filename read from stdin |
1063 | - # otherwise load the specified files. |
1064 | - if filename == "-": |
1065 | - content = sys.stdin.read() |
1066 | + # Check if we have to apply a regexp |
1067 | + page_url = "" |
1068 | + if result_type: |
1069 | + result = page.read().decode('utf-8') |
1070 | + result_regex = settings.get('result_regexp', None) |
1071 | + if result_regex: |
1072 | + result = re.split(result_regex, result)[1] |
1073 | + |
1074 | + if result_type == 'url': |
1075 | + page_url = result.strip() |
1076 | + elif result_type == 'id': |
1077 | + page_url = settings.get('target_url', website) + result.strip() |
1078 | + else: |
1079 | + raise ValueError(_("Unsupported result_type: %s" % result_type)) |
1080 | else: |
1081 | - try: |
1082 | - with open(filename, "rb") as fd: |
1083 | - content = fd.read() |
1084 | - except KeyboardInterrupt: |
1085 | - print(_("KeyboardInterrupt caught."), file=sys.stderr) |
1086 | - sys.exit(1) |
1087 | - except: |
1088 | - print(_("Unable to read from: %s") % filename, file=sys.stderr) |
1089 | - sys.exit(1) |
1090 | - |
1091 | + page_url = page.url |
1092 | + |
1093 | + # You may have posted to https:, but were given an http: url |
1094 | + if website.startswith('https:'): |
1095 | + page_url = page_url.replace('http:', 'https:') |
1096 | + return page_url |
1097 | + |
1098 | + except KeyboardInterrupt: |
1099 | + print(_("KeyboardInterrupt caught."), file=stderr) |
1100 | + sys.exit(1) |
1101 | + except: |
1102 | + print(_("Unable to read or parse the result page, it could be a " |
1103 | + "server timeout or a change server side, " |
1104 | + "try with another pastebin."), file=stderr) |
1105 | + sys.exit(1) |
1106 | + |
1107 | + |
1108 | +def validateContents(settings): |
1109 | + """Check for invalid contents""" |
1110 | + for content in settings['contents']: |
1111 | if not content: |
1112 | print(_("You are trying to send an empty document, exiting."), |
1113 | - file=sys.stderr) |
1114 | - sys.exit(1) |
1115 | - |
1116 | - contents.append(content) |
1117 | - |
1118 | - for content in contents: |
1119 | - # Get the parameter array |
1120 | - website, params = getParameters(website, pastebind, content, user, |
1121 | - jabberid, version, format, parentpid, |
1122 | - permatag, title, username, password) |
1123 | - |
1124 | - if not website.endswith("/"): |
1125 | - website += "/" |
1126 | - |
1127 | - if "sizelimit" in params: |
1128 | - if len(content) > int(params['sizelimit']): |
1129 | - print(_("The content you are trying to send exceeds " |
1130 | - "the pastebin's size limit."), file=sys.stderr) |
1131 | - sys.exit(1) |
1132 | - else: |
1133 | - del params['sizelimit'] |
1134 | - |
1135 | - reLink = None |
1136 | - tmp_page = "" |
1137 | - if "page" in params: |
1138 | - website += params['page'] |
1139 | - tmp_page = params['page'] |
1140 | - del params["page"] |
1141 | - if "regexp" in params: |
1142 | - reLink = params['regexp'] |
1143 | - del params["regexp"] |
1144 | - if "target_url" in params: |
1145 | - target_url = params["target_url"] |
1146 | - del params["target_url"] |
1147 | - else: |
1148 | - target_url = None |
1149 | - if 'post_format' in params: |
1150 | - post_format = params['post_format'] |
1151 | - del params['post_format'] |
1152 | - else: |
1153 | - post_format = 'standard' |
1154 | - |
1155 | - url_opener = pasteURLopener() |
1156 | - |
1157 | - if post_format == 'json': |
1158 | - if json: |
1159 | - params = json.dumps(params) |
1160 | - url_opener.addheader('Content-type', 'text/json') |
1161 | - else: |
1162 | - print(_("Could not find any json library."), file=sys.stderr) |
1163 | - sys.exit(1) |
1164 | - else: |
1165 | - # Convert to a format usable with the HTML POST |
1166 | - params = urlencode(params) |
1167 | - |
1168 | - # Send the informations and be redirected to the final page |
1169 | - try: |
1170 | - page = url_opener.open(website, params) |
1171 | - except Exception as e: |
1172 | - print(_("Failed to contact the server: %s") % e, file=sys.stderr) |
1173 | - sys.exit(1) |
1174 | - |
1175 | - try: |
1176 | - # Check if we have to apply a regexp |
1177 | - if reLink: |
1178 | - if target_url: |
1179 | - website = target_url |
1180 | - else: |
1181 | - website = website.replace(tmp_page, "") |
1182 | - |
1183 | - if reLink == '(.*)': |
1184 | - print(page.read().decode('utf-8').strip()) |
1185 | - else: |
1186 | - # Print the result of the regexp |
1187 | - print(website + re.split(reLink, |
1188 | - page.read().decode('utf-8'))[1]) |
1189 | - else: |
1190 | - # Get the final page and show the url |
1191 | - print(page.url) |
1192 | - except KeyboardInterrupt: |
1193 | - print(_("KeyboardInterrupt caught."), file=sys.stderr) |
1194 | - sys.exit(1) |
1195 | - except: |
1196 | - print(_("Unable to read or parse the result page, it could be a " |
1197 | - "server timeout or a change server side, " |
1198 | - "try with another pastebin."), file=sys.stderr) |
1199 | - sys.exit(1) |
1200 | - |
1201 | -except KeyboardInterrupt: |
1202 | - print(_("KeyboardInterrupt caught."), file=sys.stderr) |
1203 | - sys.exit(1) |
1204 | + file=stderr) |
1205 | + sys.exit(1) |
1206 | + |
1207 | + if len(content) > int(settings.get('sizelimit', sys.maxsize)): |
1208 | + print(_("The content you are trying to send exceeds " |
1209 | + "the pastebin's size limit."), file=stderr) |
1210 | + sys.exit(1) |
1211 | + |
1212 | + |
1213 | +def main(): |
1214 | + try: |
1215 | + settings = defaults() |
1216 | + settings.update(readConfigFile(readFile(config_path))) |
1217 | + settings.update(readOptions(getOpts())) |
1218 | + verbose = settings['verbose'] |
1219 | + |
1220 | + paste_config, settings['website'] = getPasteConfig(settings['website']) |
1221 | + params = readPasteConfig(paste_config, settings) |
1222 | + |
1223 | + validateContents(settings) |
1224 | + opener = PasteURLopener(settings.get('post_format', '')) |
1225 | + |
1226 | + url = settings['website'] + settings.get('page', '').lstrip("/") |
1227 | + for content in settings['contents']: |
1228 | + params[paste_config.get('format', 'content')] = content |
1229 | + page = opener.make_request(url, params) |
1230 | + print(readPageURL(page, settings), file=stdout) |
1231 | + except KeyboardInterrupt: |
1232 | + print(_("KeyboardInterrupt caught."), file=stderr) |
1233 | + sys.exit(1) |
1234 | + |
1235 | +if __name__ == '__main__': |
1236 | + main() |
1237 | \ No newline at end of file |
1238 | |
1239 | === added symlink 'pastebinit.py' |
1240 | === target is u'pastebinit' |
1241 | === added file 'test.py' |
1242 | --- test.py 1970-01-01 00:00:00 +0000 |
1243 | +++ test.py 2014-12-02 02:23:09 +0000 |
1244 | @@ -0,0 +1,135 @@ |
1245 | +import unittest |
1246 | +import pastebinit |
1247 | +try: |
1248 | + from StringIO import StringIO |
1249 | +except ImportError: |
1250 | + from io import StringIO |
1251 | + |
1252 | +pastebinit.stdin = StringIO('') |
1253 | +pastebinit.stdout = StringIO('') |
1254 | +pastebinit.stderr = StringIO('') |
1255 | + |
1256 | + |
1257 | +class ConfigXMLTests(unittest.TestCase): |
1258 | + |
1259 | + def test_config_xml_parse(self): |
1260 | + xml = """\ |
1261 | + <pastebinit> |
1262 | + <pastebin>http://paste.debian.net</pastebin> |
1263 | + <author>A pastebinit user</author> |
1264 | + <jabberid>nobody@nowhere.org</jabberid> |
1265 | + <format>text</format> |
1266 | + </pastebinit> |
1267 | + """ |
1268 | + out = { |
1269 | + 'website': u'http://paste.debian.net', |
1270 | + 'user': u'A pastebinit user', |
1271 | + 'jabberid': u'nobody@nowhere.org', |
1272 | + 'format': u'text', |
1273 | + } |
1274 | + assert pastebinit.readConfigFile(xml) == out, 'readConfigFile failed' |
1275 | + |
1276 | + def test_config_xml_parse_missing(self): |
1277 | + xml = """\ |
1278 | + <pastebinit> |
1279 | + <author>A pastebinit user</author> |
1280 | + <jabberid>nobody@nowhere.org</jabberid> |
1281 | + <format>text</format> |
1282 | + </pastebinit> |
1283 | + """ |
1284 | + out = { |
1285 | + 'user': u'A pastebinit user', |
1286 | + 'jabberid': u'nobody@nowhere.org', |
1287 | + 'format': u'text', |
1288 | + } |
1289 | + assert pastebinit.readConfigFile(xml) == out, 'readConfigFile failed' |
1290 | + |
1291 | + def test_config_xml_parse_additional(self): |
1292 | + xml = """\ |
1293 | + <pastebinit> |
1294 | + <author>A pastebinit user</author> |
1295 | + <jabberid>nobody@nowhere.org</jabberid> |
1296 | + <format>text</format> |
1297 | + <test>nonsense</test> |
1298 | + </pastebinit> |
1299 | + """ |
1300 | + out = { |
1301 | + 'user': u'A pastebinit user', |
1302 | + 'jabberid': u'nobody@nowhere.org', |
1303 | + 'format': u'text', |
1304 | + } |
1305 | + assert pastebinit.readConfigFile(xml) == out, 'readConfigFile failed' |
1306 | + |
1307 | + def test_config_xml_parse_invalid(self): |
1308 | + try: |
1309 | + pastebinit.readConfigFile("invalid") |
1310 | + assert False, "Invalid file was parsed without error." |
1311 | + except SystemExit: |
1312 | + pass |
1313 | + |
1314 | + |
1315 | +class GetOptsTests(unittest.TestCase): |
1316 | + |
1317 | + def _check_arg(self, argname, settingname): |
1318 | + settings = pastebinit.readOptions(pastebinit.getOpts([argname, 'test'])) |
1319 | + assert settings[settingname] == 'test', "Failed to read " + argname |
1320 | + |
1321 | + def test_help(self): |
1322 | + try: |
1323 | + pastebinit.readOptions(['-h']) |
1324 | + assert False, "Failed to quit after help option" |
1325 | + except SystemExit: |
1326 | + pass |
1327 | + |
1328 | + def test_list(self): |
1329 | + try: |
1330 | + pastebinit.readOptions(['-l']) |
1331 | + assert False, "Failed to quit after list option" |
1332 | + except SystemExit: |
1333 | + pass |
1334 | + |
1335 | + def test_version(self): |
1336 | + try: |
1337 | + pastebinit.readOptions(['-v']) |
1338 | + assert False, "Failed to quit after version option" |
1339 | + except SystemExit: |
1340 | + pass |
1341 | + |
1342 | + def test_website(self): |
1343 | + self._check_arg('-b', 'website') |
1344 | + |
1345 | + def test_user(self): |
1346 | + self._check_arg('-a', 'user') |
1347 | + |
1348 | + def test_format(self): |
1349 | + self._check_arg('-f', 'format') |
1350 | + |
1351 | + def test_jabberid(self): |
1352 | + self._check_arg('-j', 'jabberid') |
1353 | + |
1354 | + def test_title(self): |
1355 | + self._check_arg('-t', 'title') |
1356 | + |
1357 | + def test_permatag(self): |
1358 | + self._check_arg('-m', 'permatag') |
1359 | + |
1360 | + def test_username(self): |
1361 | + self._check_arg('-u', 'username') |
1362 | + |
1363 | + def test_password(self): |
1364 | + self._check_arg('-p', 'password') |
1365 | + |
1366 | + def test_parentpid(self): |
1367 | + self._check_arg('-r', 'parentpid') |
1368 | + |
1369 | + def test_filenames(self): |
1370 | + opts = pastebinit.getOpts(['-i', 'testa', |
1371 | + '-i', 'testb', |
1372 | + '-i', 'testc', |
1373 | + ]) |
1374 | + assert opts['-i'] == [ |
1375 | + 'testa','testb','testc'], "Failed to read filenames" |
1376 | + |
1377 | + |
1378 | +if __name__ == "__main__": |
1379 | + unittest.main() |
1380 | |
1381 | === modified file 'test.sh' |
1382 | --- test.sh 2014-01-06 23:23:28 +0000 |
1383 | +++ test.sh 2014-12-02 02:23:09 +0000 |
1384 | @@ -1,11 +1,16 @@ |
1385 | #!/bin/sh |
1386 | -teststring="blah blah blah" |
1387 | +#paste.debian.net needs 3 lines |
1388 | +teststring="""\ |
1389 | +test from pastebinit |
1390 | +test from pastebinit |
1391 | +test from pastebinit |
1392 | +""" |
1393 | |
1394 | for interpreter in python python3; do |
1395 | - for pastebin in $($interpreter pastebinit -l | egrep "^-" | sed "s/^- //g") |
1396 | + for pastebin in $(ls pastebin.d/*.conf | sed 's~^pastebin.d/\(.*\)\.conf$~\1~') |
1397 | do |
1398 | echo "Trying http://$pastebin ($interpreter)" |
1399 | - URL=$(echo "$teststring\n$teststring\n$teststring" | $interpreter pastebinit -b http://$pastebin) |
1400 | + URL=$(echo teststring | $interpreter ./pastebinit.py -b http://$pastebin) |
1401 | |
1402 | if [ "$pastebin" = "paste.ubuntu.org.cn" ]; then |
1403 | out=$(wget -O - -q "$URL" | gzip -d | grep "$teststring") |
1404 | @@ -14,9 +19,13 @@ |
1405 | fi |
1406 | |
1407 | if [ -n "$out" ]; then |
1408 | - echo "PASS: http://$pastebin ($URL) ($interpreter)" |
1409 | + echo "PASS: http://$pastebin" |
1410 | + echo " ($URL)" |
1411 | + echo " ($interpreter)" |
1412 | else |
1413 | - echo "FAIL: http://$pastebin ($URL) ($interpreter)" |
1414 | + echo "FAIL: http://$pastebin" |
1415 | + echo " ($URL)" |
1416 | + echo " ($interpreter)" |
1417 | fi |
1418 | echo "" |
1419 | done |
Hi,
I'm sorry I didn't see this before, as you most likely figured out by now, I'm not very actively involved anymore as pastebinit pretty much just works for me and has done so for years.
I'm certainly happy with work to make it less crufty and better tested, unfortunately it looks like the bunch of changes I applied today makes this fail to apply.
Any chance you can rebase this on current pastebinit. I'll try to be faster to respond this time! :)