#!/usr/bin/env python # Written by Stephane Graber # Daniel Bartlett # Last modification : Mon Jan 28 22:33:23 CET 2008 # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA defaultPB = "http://pastebin.com" #Default pastebin try: import lsb_release release = lsb_release.get_distro_information()['ID'].lower() if release == 'debian': defaultPB = "http://paste.debian.net" elif release == 'fedora': defaultPB = "http://fpaste.org" elif release == 'ubuntu': defaultPB = "http://paste.ubuntu.com" except ImportError: pass try: import urllib, os, sys, re, getopt, xml.dom.minidom, gettext try: import json # For python 2.6 and newer except ImportError: try: import simplejson as json except ImportError: json = None from gettext import gettext as _ import configobj gettext.textdomain("pastebinit") version = "1.3" #Version number to show in the usage configfile = os.path.expanduser("~/.pastebinit.xml") # Custom urlopener to handle 401's class pasteURLopener(urllib.FancyURLopener): def http_error_401(self, url, fp, errcode, errmsg, headers, data=None): return None def preloadPastebins(): # Check several places for config files: # - global config in /etc/pastebin.d # - for source checkout, config in the checkout # - user's overrides in ~/.pastebin.d # Files found later override files found earlier. pastebind = {} for confdir in ['/usr/share/pastebin.d','/etc/pastebin.d','/usr/local/etc/pastebin.d', os.path.expanduser('~/.pastebin.d'), os.path.join(os.path.dirname(__file__), 'pastebin.d')]: try: confdirlist = os.listdir(confdir) except OSError: continue for fileitem in confdirlist: if fileitem.startswith('.'): continue filename = os.path.join(confdir, fileitem) try: bininstance = configobj.ConfigObj(filename) except configobj.ConfigObjError, e: print >> sys.stderr, '%s: %s' % (filename, e) continue try: section = bininstance['pastebin'] except KeyError: print >> sys.stderr, _('%s: no section [pastebin]') % filename continue try: basename = section['basename'] except KeyError: print >> sys.stderr, _("%s: no 'basename' in [pastebin]") % filename continue pastebind[basename] = bininstance return pastebind # pastey.net obfuscates parent ids for replies. Rather than taking the # post ID given as the parent ID, we must handle this by going to that # post page and looking up what the invisible parent ID field will be # set to for children. def doParentFixup(website, paramname, parentid): if parentid == "": return "" url_opener = pasteURLopener() page = url_opener.open(website + '/' + parentid, None) matches = re.split('") % user print _("\t-b ") % website print _("\t-f ") % format print _("\t-h This help screen") print _("\t-i ") print _("\t-l List all supported pastebins") print _("\t-j ") % jabberid print _("\t-m ") print _("\t-r ") print _("\t-t ") print _("\t-u <username> -p <password>") # Set defaults website = defaultPB user = os.environ.get('USER') jabberid = "" title = "" permatag = "" format = "text" username = "" password = "" filename = "" content = "" parentpid = "" #Example configuration file string configexample = """\ <pastebinit> <pastebin>http://paste.debian.net</pastebin> <author>A pastebinit user</author> <jabberid>nobody@nowhere.org</jabberid> <format>text</format> </pastebinit> """ #Open configuration file if it exists try: f = open(configfile) configtext = f.read() f.close() gotconfigxml = True except KeyboardInterrupt: sys.exit(_("KeyboardInterrupt caught.")) except: gotconfigxml = False #Parse configuration file if gotconfigxml: try: configxml = xml.dom.minidom.parseString(configtext) for variable,key in (('pastebin','website'),('author','user'),('format','format'),('jabberid','jabberid')): try: value = getFirstNodeText(configxml, variable) vars()[key]=value except: pass except KeyboardInterrupt: sys.exit(_("KeyboardInterrupt caught.")) except: print _("Error parsing configuration file!") print _("Please ensure that your configuration file looks similar to the following:") print configexample sys.exit(1) # Get options try: optlist, list = getopt.getopt(sys.argv[1:], 'hli:f:b:a:r:j:t:m:u:p:') except KeyboardInterrupt: sys.exit(_("KeyboardInterrupt caught.")) except getopt.GetoptError: print _("Invalid arguments!\n") Usage() sys.exit(1) pastebind = preloadPastebins() #get the config from /etc/pastebin.d/ # Iterate through options for opt in optlist: if opt[0] == "-h": Usage() sys.exit(1) if opt[0] == "-i": filename = opt[1] elif opt[0] == "-f": format = opt[1] elif opt[0] == "-b": website = opt[1] elif opt[0] == "-a": user = opt[1] elif opt[0] == "-r": parentpid = opt[1] elif opt[0] == "-j": jabberid = opt[1] elif opt[0] == "-l": print _("Supported pastebins:") for pastebin in sorted(pastebind): print "- %s" % pastebin sys.exit(0) elif opt[0] == "-t": title = opt[1] elif opt[0] == "-m": permatag = opt[1] elif opt[0] == "-u": username = opt[1] elif opt[0] == "-p": password = opt[1] if filename == "" and len(list) >= 1: filename = list[0] #If - is specified as a filename read from stdin, otherwise load the specified file. if (filename == "" or filename == "-") and content == "": content = sys.stdin.read() elif content == "": try: f = open(filename) content = f.read() f.close() except KeyboardInterrupt: sys.exit(_("KeyboardInterrupt caught.")) except: sys.exit(_("Unable to read from: %s") % filename) if not content: sys.exit(_("You are trying to send an empty document, exiting.")) params = getParameters(website, pastebind, content, user, jabberid, version, format, parentpid, permatag, title, username, password) #Get the parameters array if not website.endswith("/"): website += "/" if "sizelimit" in params: if len(content) > int(params['sizelimit']): sys.exit(_("The content you are trying to send exceeds the pastebin's size limit.")) else: del params['sizelimit'] reLink = None tmp_page = "" if "page" in params: website += params['page'] tmp_page = params['page'] del params["page"] if "regexp" in params: reLink = params['regexp'] del params["regexp"] if "target_url" in params: target_url = params["target_url"] del params["target_url"] else: target_url = None if 'post_format' in params: post_format = params['post_format'] del params['post_format'] else: post_format = 'standard' url_opener = pasteURLopener() if post_format == 'json': if json: params = json.dumps(params) url_opener.addheader('Content-type: text/json') else: sys.exit(_("Could not find any json library.")) else: params = urllib.urlencode(params) #Convert to a format usable with the HTML POST page = url_opener.open(website, params) #Send the informations and be redirected to the final page try: if reLink: #Check if we have to apply a regexp if target_url: website = target_url else: website = website.replace(tmp_page, "") if reLink == '(.*)': print page.read().strip() else: print website + re.split(reLink, page.read())[1] #Print the result of the Regexp else: print page.url #Get the final page and show the ur except KeyboardInterrupt: sys.exit(_("KeyboardInterrupt caught.")) except: sys.exit(_("Unable to read or parse the result page, it could be a server timeout or a change server side, try with another pastebin.")) except KeyboardInterrupt: sys.exit(_("KeyboardInterrupt caught."))