| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184 |
- #!/usr/bin/python
- import httplib
- import optparse
- import os
- import sys
- import threading
- import urllib
- import urlparse
- __version__ = (0, 1, 0)
- PASTEE_URL = "https://pastee.org"
- DEFAULT_LEXER = "text"
- DEFAULT_TTL = 30 # days
- class Paste:
- """Class representing a paste that has been submitted."""
- def __init__(self, content, lexer, url):
- """Constructor.
- Args:
- content: paste content
- lexer: lexer used for this paste
- url: URL to access the paste
- """
- self.content = content
- self.lexer = lexer
- self.url = url
- def __unicode__(self):
- return self.url
- def __str__(self):
- return str(self.__unicode__)
- class PasteClient:
- """Pasting client for a Pastee application.
- Instances of this class can be used to programmatically create new pastes on
- an installation of Pastee (https://pastee.org).
- This class is thread-safe.
- """
- def __init__(self, url=PASTEE_URL):
- """Constructor.
- Args:
- url: URL to Pastee installation (defaults to https://pastee.org)
- """
- parse = urlparse.urlsplit(url)
- self._scheme = parse[0]
- self._netloc = parse[1]
- self._lock = threading.Semaphore()
- def paste(self, content, lexer=None, ttl=None, key=None):
- """Create a new paste.
- Args:
- content: string of text to paste
- lexer: lexer to use (defaults to text)
- ttl: time-to-live in days (defaults to 30)
- key: encrypt paste with this key; if not specified, paste is not
- encrypted
- Returns:
- Paste object
- """
- if lexer is None:
- lexer = DEFAULT_LEXER
- if ttl is None:
- ttl = DEFAULT_TTL
- if self._scheme == "https":
- self._conn = httplib.HTTPSConnection(self._netloc)
- else:
- self._conn = httplib.HTTPConnection(self._netloc)
- headers = {"Content-type": "application/x-www-form-urlencoded",
- "Accept": "text/plain"}
- params = {"lexer": lexer,
- "content": content,
- "ttl": int(ttl * 86400)}
- if key is not None:
- params["encrypt"] = "checked"
- params["key"] = key
- self._lock.acquire()
- self._conn.request("POST", "/submit", urllib.urlencode(params), headers)
- response = self._conn.getresponse()
- self._lock.release()
- return self._make_paste(response, content, lexer)
- def paste_file(self, filename, lexer=None, ttl=None, key=None):
- """Create a new paste from a file.
- Args:
- filename: path to file
- lexer: lexer to use (defaults to extension of the file or text)
- ttl: time-to-live in days (defaults to 30)
- key: encrypt paste with this key; if not specified, paste is not
- encrypted
- Returns:
- Paste object
- """
- _, ext = os.path.splitext(filename)
- if lexer is None and ext:
- lexer = ext[1:] # remove leading period first
- # TODO(ms): need exception handling here
- fd = open(filename, "r")
- content = fd.read()
- fd.close()
- return self.paste(content, lexer=lexer, ttl=ttl, key=key)
- def _make_paste(self, response, content, lexer):
- for (key, value) in response.getheaders():
- if key.lower() == "location":
- return self._clean_url(value)
- return Paste(content, lexer, self._clean_url(value))
- def _clean_url(self, url):
- p = urlparse.urlsplit(url)
- scheme = p[0]
- netloc_split = p[1].split(":")
- hostname = netloc_split[0]
- if len(netloc_split) > 1:
- port = int(netloc_split[1])
- else:
- port = scheme == "https" and 443 or 80
- path = p[2]
- port_str = ""
- if port != 80 and scheme == "http":
- port_str = ":%d" % port
- elif port != 443 and scheme == "https":
- port_str = ":%d" % port
- return "%s://%s%s%s" % (scheme, hostname, port_str, path)
- def die_with_error(message):
- """Print a message and exit with exit code 1.
- Args:
- message: message to print before exiting
- """
- print "error: %s" % message
- sys.exit(1)
- def main():
- parser = optparse.OptionParser()
- parser.add_option("-l", "--lexer", dest="lexer", metavar="LEXERNAME",
- help=("Force use of a particular lexer (i.e. c, py). "
- "This defaults to the extension of the supplied "
- "filenames, or 'text' if pasting from stdin."))
- parser.add_option("-t", "--ttl", dest="ttl", metavar="DAYS",
- help=("Number of days before the paste will expire."))
- parser.add_option("-k", "--key", dest="key", metavar="PASSPHRASE",
- help=("Encrypt pastes with this key."))
- (options, filenames) = parser.parse_args()
- lexer = options.lexer
- key = options.key
- try:
- ttl = float(options.ttl)
- except ValueError:
- die_with_error("floating point number must be passed for TTL")
- except TypeError:
- ttl = None
- client = PasteClient()
- if filenames:
- # paste from multiple files
- for filename in filenames:
- print client.paste_file(filename, lexer=lexer, ttl=ttl, key=key)
- else:
- # paste from stdin
- print client.paste(sys.stdin.read(), lexer=lexer, ttl=ttl, key=key)
- if __name__ == "__main__":
- main()
|