%PDF- %PDF-
Direktori : /bin/X11/X11/X11/ |
Current File : //bin/X11/X11/X11/pastebinit |
#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Author: Stéphane Graber <stgraber@ubuntu.com> # Written by Stéphane Graber <stgraber@stgraber.org> # Daniel Bartlett <dan@f-box.org> # 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 from __future__ import print_function import sys from configparser import ConfigParser, NoOptionError from urllib.parse import urlencode from urllib import request # Set the default pastebin defaultPB = "dpaste.com" # Now try to override it with a distributor pastebin try: import distro release = distro.id() if release in ('debian', 'raspbian'): defaultPB = "paste.debian.net" elif release in ('fedora', 'centos', 'rhel', 'rocky'): defaultPB = "paste.centos.org" except ImportError: pass try: import getopt import gettext import os import re import socket import xml.dom.minidom try: import json except ImportError: json = None _ = gettext.gettext gettext.textdomain("pastebinit") # Timeout after 5s socket.setdefaulttimeout(15) # Version number to show in the usage version = "1.6.2" configfiles = [] for conffile in list(reversed(os.environ.get( 'XDG_CONFIG_DIRS', '').split(':'))) + ['/etc', '/usr/local/etc', os.environ.get('XDG_CONFIG_HOME', os.path.expanduser('~/.config')), os.path.expanduser('~/.pastebinit.xml')]: conffile = conffile.rstrip('/') if not conffile.endswith('pastebinit.xml'): conffile = os.path.join(conffile, 'pastebinit.xml') if conffile not in configfiles: configfiles.append(conffile) class PasteRequest(request.Request): version = "Pastebinit v%s" % version def __init__(self, *args, **opts): super(PasteRequest, self).__init__(*args, **opts) if 'User-Agent' not in self.headers: self.add_header('User-Agent', self.version) 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 = {} confdirs = [] for confdir in ['/usr/share', '/usr/local/share'] \ + list(reversed(os.environ.get('XDG_DATA_DIRS', '').split(':'))) \ + list(reversed(os.environ.get('XDG_CONFIG_DIRS', '').split(':'))) \ + ['/etc', '/usr/local/etc', os.environ.get('XDG_CONFIG_HOME', os.path.expanduser('~/.config')), os.path.expanduser('~/.pastebin.d')]: confdir = confdir.rstrip('/') if not confdir.endswith('pastebin.d'): confdir = os.path.join(confdir, 'pastebin.d') if confdir not in confdirs: confdirs.append(confdir) for confdir in confdirs: try: confdirlist = os.listdir(confdir) except OSError: continue for fileitem in confdirlist: if fileitem.startswith('.') or not fileitem.endswith('.conf'): continue filename = os.path.join(confdir, fileitem) instance = ConfigParser() try: instance.read(filename) except UnicodeError: continue if not instance.has_section('pastebin'): print(_('%s: no section [pastebin]') % filename, file=sys.stderr) continue if not instance.has_option('pastebin', 'basename'): print(_("%s: no 'basename' in [pastebin]") % filename, file=sys.stderr) continue pastebind[instance.get('pastebin', 'basename')] = instance return pastebind # Return the configuration depending of the pastebin used def getConfig(website): for config in list(pastebind.values()): basename = config.get('pastebin', 'basename') try: https = config.get('pastebin', 'https') except: https = False if basename == website: if https: website = "https://%s/" % basename else: website = "http://%s/" % basename return website, config['pastebin'] print(_("Unknown website, please post a bugreport to request " "this pastebin to be added (%s)") % website, file=sys.stderr) sys.exit(1) # Return the parameters depending of the pastebin used def getParameters(website, content): config = pastebind[website] params = {} for param in config.options('format'): paramname = config.get('format', param) if param == 'content': params[paramname] = content else: params[paramname] = config.get('defaults', param, vars=spec_opts, fallback=inline_opts.get(param)) return params # XML Handling methods def getText(nodelist): rc = "" for node in nodelist: if node.nodeType == node.TEXT_NODE: rc = rc + node.data return rc def getNodes(nodes, title): return nodes.getElementsByTagName(title) def getFirstNode(nodes, title): return getNodes(nodes, title)[0] def getFirstNodeText(nodes, title): return getText(getFirstNode(nodes, title).childNodes) # Display usage instructions def Usage(fd=sys.stdout): print("pastebinit v" + version, file=fd) print(_("\nReads on stdin for input or takes a list of files " "as parameters"), file=fd) print(_("\nUsage:\tpastebinit [OPTION...] [FILE...]"), file=fd) print(_("\nGeneral arguments:\n"), file=fd) print(_("\t-b <pastebin> (default is '%s')") % website, file=fd) print(_("\t-i <input file>"), file=fd) print(_("\t-l List all supported pastebins"), file=fd) print(_("\t-E Print the content to stdout too"), file=fd) print(_("\t-h Print this help screen"), file=fd) print(_("\t-v Print the version number"), file=fd) print(_("\t-V Print verbose output to stderr"), file=fd) print(_("\nOptional arguments (not supported by all pastebins):\n"), file=fd) print(_("\t-a <author> (default is '%s')") % inline_opts['user'], file=fd) print(_("\t-t <title of paste> (default is none)"), file=fd) print(_("\t-f <format of paste> (default is '%s')") % inline_opts['format'], file=fd) print(_("\t-j <jabberid> (default is '%s')") % inline_opts['jabberid'], file=fd) print(_("\t-m <permatag> (default is none)"), file=fd) print(_("\t-P <private level> (default is '%s')") % inline_opts['private'], file=fd) print(_("\t-u <username> -p <password>"), file=fd) # Set defaults website = defaultPB inline_opts = { 'user' : os.environ.get('USER', os.environ.get('LOGNAME')), 'jabberid' : "", 'title' : "", 'permatag' : "", 'format' : "text", 'private' : 1, 'username' : "", 'password' : "" } spec_opts = {} filenames = [] verbose = False echo = False # Example configuration file string configexample = """\ <pastebinit> <pastebin>paste.debian.net</pastebin> <author>A pastebinit user</author> <jabberid>nobody@nowhere.org</jabberid> <format>text</format> <private>1</private> </pastebinit> """ for configfile in configfiles: # Open configuration file if it exists try: f = open(configfile) configtext = f.read() f.close() gotconfigxml = True except KeyboardInterrupt: print(_("KeyboardInterrupt caught."), file=sys.stderr) sys.exit(1) 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'), ('private', 'private'), ('jabberid', 'jabberid')): try: value = getFirstNodeText(configxml, variable) if variable == 'pastebin': website = value else: spec_opts[key] = value except: pass except KeyboardInterrupt: print(_("KeyboardInterrupt caught."), file=sys.stderr) sys.exit(1) except: print(_("Error parsing configuration file!"), file=sys.stderr) print(_("Please ensure that your configuration file looks " "similar to the following:"), file=sys.stderr) print(configexample, file=sys.stderr) sys.exit(1) # Get options try: optlist, arglist = getopt.getopt(sys.argv[1:], 'EVP:hlva:b:f:i:t:j:m:u:p:') except KeyboardInterrupt: print(_("KeyboardInterrupt caught."), file=sys.stderr) sys.exit(1) except getopt.GetoptError as e: print((_("Invalid arguments: %s!") % e) + "\n", file=sys.stderr) Usage(sys.stderr) sys.exit(1) # Get the configuration of all pastebins pastebind = preloadPastebins() # Iterate through options for opt in optlist: if opt[0] == "-h": Usage() sys.exit(0) elif opt[0] == "-v": print("pastebinit v" + version) sys.exit(0) elif opt[0] == "-l": print(_("Supported pastebins:")) for pastebin in sorted(list(pastebind.keys())): print("- %s" % pastebin) sys.exit(0) elif opt[0] == "-b": website = opt[1] elif opt[0] == "-i": filenames.append(opt[1]) elif opt[0] == "-a": spec_opts['user'] = opt[1] elif opt[0] == "-t": spec_opts['title'] = opt[1] elif opt[0] == "-f": spec_opts['format'] = opt[1] elif opt[0] == "-j": spec_opts['jabberid'] = opt[1] elif opt[0] == "-m": spec_opts['permatag'] = opt[1] elif opt[0] == "-P": spec_opts['private'] = opt[1] elif opt[0] == "-u": spec_opts['username'] = opt[1] elif opt[0] == "-p": spec_opts['password'] = opt[1] elif opt[0] == "-E": echo = True elif opt[0] == "-V": verbose = True # Get the configuration if '://' in website: website = website.split('://')[1] website = website.strip('/') website, config = getConfig(website) filenames += arglist if not filenames: filenames.append("-") contents = [] for filename in filenames: # If - is specified as a filename read from stdin # otherwise load the specified files. content = "" if filename == "-": content = sys.stdin.read().rstrip() else: try: with open(filename, "r") as fd: content = fd.read().rstrip() except KeyboardInterrupt: print(_("KeyboardInterrupt caught."), file=sys.stderr) sys.exit(1) except: print(_("Unable to read from: %s") % filename, file=sys.stderr) sys.exit(1) if not content: print(_("You are trying to send an empty document, exiting."), file=sys.stderr) sys.exit(1) contents.append(content) if echo: print(content) if "post_page" in config: # Use post page, without leading slash, website has a trailing one. post_url = website + config['post_page'].lstrip('/') else: post_url = website if "paste_regexp" in config: reLink = config['paste_regexp'] else: reLink = False # Get target_page for replacement, only used with reLink. if "target_page" in config: relink_target_url = website + config['target_page'].lstrip('/') if not reLink: print("Warning: using target_page without paste_regexp.", file=sys.stderr) elif reLink: relink_target_url = website if "post_format" in config: post_format = config['post_format'] else: post_format = 'standard' if "user_length" in config: user_length = int(config['user_length']) user = pastebind[config['basename']].get('defaults', 'user', vars=spec_opts, fallback=inline_opts.get('user')) spec_opts['user'] = "%s~" % user[:user_length-1] for content in contents: # Get the parameters params = getParameters(config['basename'], content) if "sizelimit" in config: if len(content) > int(config['sizelimit']): print(_("The content you are trying to send exceeds " "the pastebin's size limit."), file=sys.stderr) sys.exit(1) req = PasteRequest(post_url) if post_format == 'json': if json: params = bytes(json.dumps(params), encoding='US-ASCII') req.add_header('Content-Type', 'text/json') else: print(_("Could not find any JSON library."), file=sys.stderr) sys.exit(1) else: # Convert to a format usable with the HTML POST params = bytes(urlencode(params), encoding='US-ASCII') # Send the informations and be redirected to the final page if verbose: print("POSTing to: %s\nParams: %s" % ( post_url, str(params)), file=sys.stderr) try: page = request.urlopen(req, params) except Exception as e: print(_("Failed to contact the server: %s") % e, file=sys.stderr) sys.exit(1) try: # Check if we have to apply a regexp paste_url = "" if reLink: result = page.read().decode('utf-8').strip() if reLink == '(.*)': paste_url = result else: # Print the result of the regexp result = re.split(reLink, result)[1] if '%s' not in relink_target_url: paste_url = relink_target_url + result else: paste_url = relink_target_url % result else: # Get the final page paste_url = page.url # Print the paste URL if echo: print("-" * len(paste_url)) print(paste_url) except KeyboardInterrupt: print(_("KeyboardInterrupt caught."), file=sys.stderr) sys.exit(1) except: print(_("Unable to read or parse the result page, it could be a " "server timeout or a change server side, " "try with another pastebin."), file=sys.stderr) sys.exit(1) except KeyboardInterrupt: print(_("KeyboardInterrupt caught."), file=sys.stderr) sys.exit(1)