2
# -*- coding: utf-8 -*-
4
# Author: Stéphane Graber <stgraber@ubuntu.com>
5
# Written by Stéphane Graber <stgraber@stgraber.org>
6
# Daniel Bartlett <dan@f-box.org>
7
# Last modification : Mon Jan 6 18:46:46 EST 2014
9
# This program is free software; you can redistribute it and/or modify
10
# it under the terms of the GNU General Public License as published by
11
# the Free Software Foundation; either version 2 of the License, or
12
# (at your option) any later version.
14
# This program is distributed in the hope that it will be useful,
15
# but WITHOUT ANY WARRANTY; without even the implied warranty of
16
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
# GNU General Public License for more details.
19
# You should have received a copy of the GNU General Public License
20
# along with this program; if not, write to the Free Software
21
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23
from __future__ import print_function
26
if sys.version[0] == "2":
27
from ConfigParser import NoOptionError
28
from ConfigParser import SafeConfigParser as ConfigParser
29
from urllib import urlencode
30
from urllib import FancyURLopener
32
from configparser import ConfigParser, NoOptionError
33
from urllib.parse import urlencode
34
from urllib.request import FancyURLopener
36
# Set the default pastebin
37
defaultPB = "pastebin.com"
39
# Now try to override it with a distributor pastebin
42
release = platform.linux_distribution()[0].lower()
43
if release == 'debian':
44
defaultPB = "paste.debian.net"
45
elif release == 'fedora':
46
defaultPB = "fpaste.org"
47
elif release == 'ubuntu':
48
defaultPB = "paste.ubuntu.com"
58
import xml.dom.minidom
66
gettext.textdomain("pastebinit")
69
socket.setdefaulttimeout(15)
71
# Version number to show in the usage
73
configfile = os.path.expanduser("~/.pastebinit.xml")
75
# Custom urlopener to handle 401's
76
class pasteURLopener(FancyURLopener):
77
version = "Pastebinit v%s" % version
79
def http_error_401(self, url, fp, errcode, errmsg, headers, data=None):
82
def preloadPastebins():
83
# Check several places for config files:
84
# - global config in /etc/pastebin.d
85
# - for source checkout, config in the checkout
86
# - user's overrides in ~/.pastebin.d
87
# Files found later override files found earlier.
89
for confdir in ['/usr/share/pastebin.d', '/etc/pastebin.d',
90
'/usr/local/etc/pastebin.d',
91
os.path.expanduser('~/.pastebin.d'),
94
os.path.realpath(__file__)), 'pastebin.d')]:
96
confdirlist = os.listdir(confdir)
100
for fileitem in confdirlist:
101
if fileitem.startswith('.') or not fileitem.endswith('.conf'):
104
filename = os.path.join(confdir, fileitem)
105
instance = ConfigParser()
107
instance.read(filename)
111
if not instance.has_section('pastebin'):
112
print(_('%s: no section [pastebin]') % filename,
116
if not instance.has_option('pastebin', 'basename'):
117
print(_("%s: no 'basename' in [pastebin]") % filename,
121
pastebind[instance.get('pastebin', 'basename')] = instance
124
# Return the parameters depending of the pastebin used
125
def getParameters(website, pastebind, content, user, jabberid, version,
126
format, permatag, title, username,
128
"Return the parameters array for the selected pastebin"
130
for paste_name, paste_config in pastebind.items():
131
basename = paste_config.get('pastebin', 'basename')
133
https = paste_config.get('pastebin', 'https')
137
if basename == website or paste_name == website:
139
website = "https://%s" % basename
141
website = "http://%s" % basename
143
if re.search(paste_config.get('pastebin', 'regexp'), website):
144
if paste_config.has_option('pastebin', 'sizelimit'):
145
params['sizelimit'] = paste_config.get('pastebin',
148
for param in paste_config.options('format'):
149
paramname = paste_config.get('format', param)
151
params[paramname] = user
152
elif param == 'content':
153
params[paramname] = content
154
elif param == 'title':
155
params[paramname] = title
156
elif param == 'version':
157
params[paramname] = version
158
elif param == 'format':
160
params[paramname] = paste_config.get('defaults',
162
except NoOptionError:
163
params[paramname] = format
164
elif param == 'permatag':
165
params[paramname] = permatag
166
elif param == 'private':
167
params[paramname] = private
168
elif param == 'username':
169
params[paramname] = username
170
elif param == 'password':
171
params[paramname] = password
172
elif param == 'jabberid':
173
params[paramname] = jabberid
175
params[paramname] = paste_config.get('defaults', param)
177
return website, params
179
print(_("Unknown website, please post a bugreport to request "
180
"this pastebin to be added (%s)") % website,
184
# XML Handling methods
185
def getText(nodelist):
187
for node in nodelist:
188
if node.nodeType == node.TEXT_NODE:
192
def getNodes(nodes, title):
193
return nodes.getElementsByTagName(title)
195
def getFirstNode(nodes, title):
196
return getNodes(nodes, title)[0]
198
def getFirstNodeText(nodes, title):
199
return getText(getFirstNode(nodes, title).childNodes)
201
# Display usage instructions
202
def Usage(fd=sys.stdout):
203
print("pastebinit v" + version, file=fd)
204
print(_("Reads on stdin for input or takes a list of filenames "
205
"as parameters"), file=fd)
206
print(_("\t-E also print content to standard output"), file=fd)
207
print(_("Optional arguments (not supported by all pastebins):"),
209
print(_("\t-a <author:default is '%s'>") % user, file=fd)
210
print(_("\t-b <pastebin url:default is '%s'>") % website, file=fd)
211
print(_("\t-f <format of paste:default is '%s' (or from pastebin config)>") % format, file=fd) # noqa
212
print(_("\t-h This help screen"), file=fd)
213
print(_("\t-i <input file>"), file=fd)
214
print(_("\t-l List all supported pastebins"), file=fd)
215
print(_("\t-j <jabberid for notifications:default is '%s'>") %
217
print(_("\t-m <permatag for all versions of a post:default is blank>"),
219
print(_("\t-t <title of paste:default is blank>"), file=fd)
220
print(_("\t-P Private. Makes your paste hidden if possible"), file=fd)
221
print(_("\t-u <username> -p <password>"), file=fd)
222
print(_("\t-v Print the version number"), file=fd)
223
print(_("\t--verbose Verbose output to stderr"), file=fd)
227
user = os.environ.get('USER', os.environ.get('LOGNAME'))
240
# Example configuration file string
243
<pastebin>paste.debian.net</pastebin>
244
<author>A pastebinit user</author>
245
<jabberid>nobody@nowhere.org</jabberid>
246
<format>text</format>
250
# Open configuration file if it exists
253
configtext = f.read()
256
except KeyboardInterrupt:
257
print(_("KeyboardInterrupt caught."), file=sys.stderr)
262
# Parse configuration file
265
configxml = xml.dom.minidom.parseString(configtext)
266
for variable, key in (('pastebin', 'website'), ('author', 'user'),
267
('format', 'format'),
268
('jabberid', 'jabberid')):
270
value = getFirstNodeText(configxml, variable)
274
except KeyboardInterrupt:
275
print(_("KeyboardInterrupt caught."), file=sys.stderr)
278
print(_("Error parsing configuration file!"), file=sys.stderr)
279
print(_("Please ensure that your configuration file looks "
280
"similar to the following:"), file=sys.stderr)
281
print(configexample, file=sys.stderr)
286
optlist, arglist = getopt.getopt(sys.argv[1:],
287
'EPhvli:f:b:a:j:t:m:u:p:',
289
except KeyboardInterrupt:
290
print(_("KeyboardInterrupt caught."), file=sys.stderr)
292
except getopt.GetoptError as e:
293
print(_("Invalid arguments: %s!" % e)+"\n", file=sys.stderr)
298
pastebind = preloadPastebins()
300
# Iterate through options
306
filenames.append(opt[1])
318
print(_("Supported pastebins:"))
319
for pastebin in sorted(pastebind):
320
print("- %s" % pastebin)
333
print("pastebinit v" + version)
335
elif opt[0] == "--verbose":
341
filenames.append("-")
344
for filename in filenames:
345
# If - is specified as a filename read from stdin
346
# otherwise load the specified files.
348
content = sys.stdin.read()
351
with open(filename, "rb") as fd:
353
except KeyboardInterrupt:
354
print(_("KeyboardInterrupt caught."), file=sys.stderr)
357
print(_("Unable to read from: %s") % filename, file=sys.stderr)
361
print(_("You are trying to send an empty document, exiting."),
365
contents.append(content)
369
for content in contents:
370
# Get the parameter array
371
website, params = getParameters(website, pastebind, content, user,
372
jabberid, version, format,
373
permatag, title, username, password,
376
if not website.endswith("/"):
379
if "sizelimit" in params:
380
if len(content) > int(params['sizelimit']):
381
print(_("The content you are trying to send exceeds "
382
"the pastebin's size limit."), file=sys.stderr)
385
del params['sizelimit']
388
# Use page, without leading slash: website has a trailing one.
389
fetch_url = website + params['page'].lstrip("/")
393
if "regexp" in params:
394
reLink = params['regexp']
398
# Get target_url for replacement, only used with reLink.
399
if "target_url" in params:
400
relink_target_url = params["target_url"]
401
del params["target_url"]
403
print("Warning: using target_url without regexp.",
406
relink_target_url = website
407
if 'post_format' in params:
408
post_format = params['post_format']
409
del params['post_format']
411
post_format = 'standard'
413
url_opener = pasteURLopener()
415
if post_format == 'json':
417
params = json.dumps(params)
418
url_opener.addheader('Content-type', 'text/json')
420
print(_("Could not find any json library."), file=sys.stderr)
423
# Convert to a format usable with the HTML POST
424
params = urlencode(params)
426
# Send the informations and be redirected to the final page
428
print("POSTing to: %s\nParams: %s" % (
429
fetch_url, str(params)), file=sys.stderr)
431
page = url_opener.open(fetch_url, params)
432
except Exception as e:
433
print(_("Failed to contact the server: %s") % e, file=sys.stderr)
437
# Check if we have to apply a regexp
441
page_url = page.read().decode('utf-8').strip()
443
# Print the result of the regexp
444
page_url = relink_target_url + re.split(
446
page.read().decode('utf-8'))[1]
448
# Get the final page and show the url
450
print("-" * len(page.url))
453
print(page_url.strip())
454
except KeyboardInterrupt:
455
print(_("KeyboardInterrupt caught."), file=sys.stderr)
458
print(_("Unable to read or parse the result page, it could be a "
459
"server timeout or a change server side, "
460
"try with another pastebin."), file=sys.stderr)
463
except KeyboardInterrupt:
464
print(_("KeyboardInterrupt caught."), file=sys.stderr)