From f01668fe48a86ed6c3a8b9bf38c1bc6055f51564 Mon Sep 17 00:00:00 2001 From: Isis Lovecruft Date: Thu, 11 Apr 2013 18:16:05 +0000 Subject: [PATCH 1/3] Add NOTES file to docs/ directory. --- docs/NOTES-python-gnupg-3.1-audit.gpg | Bin 0 -> 4534 bytes docs/NOTES-python-openpgp-implementations.gpg | Bin 0 -> 1291 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/NOTES-python-gnupg-3.1-audit.gpg create mode 100644 docs/NOTES-python-openpgp-implementations.gpg diff --git a/docs/NOTES-python-gnupg-3.1-audit.gpg b/docs/NOTES-python-gnupg-3.1-audit.gpg new file mode 100644 index 0000000000000000000000000000000000000000..3973e258b703216f403c6a56815c3e2cd69f050f GIT binary patch literal 4534 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 UX9Z211f!bt2}*oFr7V5}-MHW4bN~PV literal 0 HcmV?d00001 diff --git a/docs/NOTES-python-openpgp-implementations.gpg b/docs/NOTES-python-openpgp-implementations.gpg new file mode 100644 index 0000000000000000000000000000000000000000..0a6e020af7a5b54bc405bf6dd16ff856703b5d6c GIT binary patch literal 1291 zcmV+m1@!ub0t^FC$&H7!0T2%X5C3T(2tI*xUR^Y~kXKP6Whf49ikz+yphJ$MRUI6= zui(-{8;)P`scmE3)LuFtLD+>!|E0a8O`aLnrS7%msmf#JON>lO%2|J&&@In@mna?~ z4#wRFEv-I~v6rk0arelxFz`woPh8ZnQxUs8PJW->2o3hnwiU^|M8KQcMp%Acs!2Da z_7cvmX{ru*=?f_+0O>jcI=H%alja^Qm^qH_Y3WHJv=o5zVLIlWl3XkAGFk|K`xOxo zY*<&_SVG$!Gi^%oeAwer0%!))KW;9G`<<9i9!$|(OKW{2-hz!%eOiL)bxNwV%4;{$ zu3FtYtAgOJmpf)(U*HJU_ffsorJEG}f{ux;auk~nbe|PRHLNRs?WxV(-Axf&3*z3~ zQ5E6M7p`-avnZo@oPy{$`c@2WTQ&v|{^eX6Xe>MqP4CcpE_$uZ5{# zz?w3|5}HFsmCse20Uy7_K;pu%maKp{T8Vx*)I}bK8FWFnDS(U_tl3#{n5d!g8EA7Y z0nfI!bgts(J2|7s=f-5#Dc7oQp_hLjeqkj_E0k|7?)=4?trkl)h{oCU%h-np{%x~@ z)$|%2+EMzm?{Y&11eWbhAi-@*J`nFO{d>`v!Hocb3Mi)Ek)=i!?uRbX=;FN3M zJog!H$q^ml5e$pAF>0onDG}pU@D-6IzQ{JA7h^OEEC}2Ng7F#=xDmc8x%g>xd1fD5?%gK`7DKKn=<2q}%Xj&erz)e1)^~AVxHc8dtj!4h zLxZ?_L2z;n?&hBCxUWL&LUh!GwRUIi4bLSQH~K<)$b(;?zC11TfZeY#73f7x;4Wp| zj#C5eg~%)49S4`A1gbasCAIN;}=JI2(Zq>6mq}ywMcDet{rt@;X{fzU z;!%2EOg;y|k_8@%f#C1kex{chOr>LC<$ZCxbNP_9;eu%zEHfo^wNJZ$Gfr?T?^fTF Bc_07) literal 0 HcmV?d00001 From f68d01b9f2a2f2c609924a2751393dc229c6a428 Mon Sep 17 00:00:00 2001 From: Isis Lovecruft Date: Thu, 11 Apr 2013 18:21:32 +0000 Subject: [PATCH 2/3] Update the README. --- README.md | 46 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index aa46ee7..1d70df3 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,11 @@ # python-gnupg # ================ -Fork of python-gnupg-0.3.2, patched to remove Popen([...], shell=True). +Fork of python-gnupg-0.3.2, patched to remove ```Popen([...], shell=True)```. ### Installation ### --------------------- + +#### From this git repository #### To install this package from this git repository, do: ``` @@ -19,15 +20,44 @@ Optionally to build the documentation after installation, do: make docs ``` -To get started using python-gnupg's API, see the documentation online at [XXX -FIXME add readthedocs link](), and import the module like so: +To get started using python-gnupg's API, see the [online documentation](https://python-gnupg.readthedocs.org/en/latest/), +and import the module like so: ``` >>> import gnupg ``` +The primary interface class you'll likely want to interact with is +[```gnupg.GPG```](https://python-gnupg.readthedocs.org/en/latest/gnupg.html#gpg): +``` +>>> gpg = gnupg.GPG(gpgbinary='/usr/bin/gpg', +... gpghome='./keys', +... pubring='pubring.gpg', +... secring='secring.gpg') +>>> batch_key_input = gpg.gen_key_input() +>>> print batch_key_input +Key-Type: RSA +Name-Email: isis@wintermute +Name-Comment: Generated by gnupg.py +Key-Length: 4096 +Name-Real: Autogenerated Key +%pubring /home/isis/code/python-gnupg/keys/pubring.gpg +%secring /home/isis/code/python-gnupg/keys/secring.gpg +%commit -To install this package from a tarballed source distribution, do the following: +>>> key = gpg.gen_key(batch_key_input) +>>> print key.fingerprint +245D8FA30F543B742053949F553C0E154F2E7A98 -1. Extract all the files in the distribution archive to some directory on your system. -2. In that directory, run "python setup.py install". -3. Optionally, run "python test_gnupg.py" to ensure that the package is working as expected. +``` + +#### From PyPI #### +Hold your horses, boy. I haven't finished development, so the packages on +[PyPI](https://pypi.python.org) are still the old versions belonging to the +other authors. + +### Bug Reports & Feature Requests ### +Our bugtracker is [here](https://leap.se/code/projects/eip_server/issue/new). + +Please use that for bug reports and feature requests instead of github's +tracker. We're using github for code commenting and review between +collaborators. From 64fd83bf85d34bbfb63275ad5a08d0a5992b3acd Mon Sep 17 00:00:00 2001 From: Isis Lovecruft Date: Thu, 11 Apr 2013 18:37:16 +0000 Subject: [PATCH 3/3] Add bug reporter. --- report-a-bug | 260 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 260 insertions(+) create mode 100644 report-a-bug diff --git a/report-a-bug b/report-a-bug new file mode 100644 index 0000000..73e7b98 --- /dev/null +++ b/report-a-bug @@ -0,0 +1,260 @@ +#!/usr/bin/env python +#-*- coding: utf-8 -*- +''' + report-a-bug + ------------ + File a bug against python-gnupg. + + :authors: Wade Leftwich, + Will Holcomb, + Isis Lovecruft, + :license: AGPLv3, see LICENSE and COPYRIGHT files + :copyright: © 2002-2013 Wade Leftwich + © 2006 Will Holcomb + © 2013 Isis Agora Lovecruft + :date: 11 April 2013 + :version: 0.0.1 + +''' + +from __future__ import print_function +from cStringIO import StringIO +from datetime import datetime + +import cookielib +import mimetools +import mimetypes +#import httplib +import os +import stat +import tempfile +import urllib +import urllib2 + +# Controls how sequences are uncoded. If true, elements may be given multiple +# values by assigning a sequence. +doseq = 1 + +def _has_py3k(): + """Check if we're running on Python>=3.0.""" + try: + unicode + return False + except NameError: + return True + +## patch the stupid Python2.x input() problem: +if not _has_py3k(): + input = raw_input + +def _today(): + """Get the current date as a string in the form %Y-%m-%d.""" + now_string = datetime.now().__str__() + return now_string.split(' ', 1)[0] + +def _create_upload_list(): + """Create a dictionary containing information about files to upload.""" + + upload_list = list() + + WANT_UPLOAD = True + FILE_NUMBER = 1 + FILENAME_FIELD = 'attachments[' + str(FILE_NUMBER) + '][file]' + FILEDESC_FIELD = 'attachments[' + str(FILE_NUMBER) + '][description]' + + while WANT_UPLOAD: + do_upload = input("Would you like to attach a file to this ticket? " + + "(y/N) ") + if do_upload.strip() == "": + WANT_UPLOAD = False + break + else: + WANT_UPLOAD = True + + upload = input("Please specify the file to upload, as a filesystem " + + "absolute path or as relative to this directory (%s): " + % os.getcwd()).strip() + + if len(upload) > 0: + if upload.startswith('~'): + upload = os.path.expanduser(upload) + if not os.path.isabs(upload): + upload = os.path.abspath(upload) + try: + assert os.path.isfile(upload), "is not a file" + except AssertionError as ae: + print("Skipping: '%s' %s" % (upload, ae.message)) + else: + upload_fields = {'fields': [FILENAME_FIELD, FILEDESC_FIELD], + 'filepath': upload,} + upload_list.append(upload_fields) + FILE_NUMBER += 1 + return upload_list + +def _create_fields_and_headers(host, url, assign_to=None, + category=None, target_version=None): + REPO_NAME = os.getcwd().rsplit(os.path.sep, 1)[1] + + subject = input("Please provide a brief subject line for the ticket: ") + subject = REPO_NAME + ": " + subject + descript = input("Ticket description:\n ") + whatisit = input("Is this a feature request or a bug report? " + + "(1=feature, 2=bug) ") + if whatisit not in ['1', '2']: + whatisit = '2' + serious = input("How important is this? (1=important, 2=normal, 3=trivial) ") + if serious not in ['1', '2', '3']: + serious = '2' + + headers = { + 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', + 'Accept-Encoding': 'gzip, deflate', + 'Accept-Language': 'en-us,en-gb;q=0.9,en;', + 'Connection': 'keep-alive', + 'DNT': '1', + 'Host': host, + 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; rv:10.0) Gecko/20100101 Firefox/10.0', } + + fields = { + 'issue[tracker_id]': whatisit, + 'issue[subject]': subject, + 'issue[description]': descript, + 'issue[status_id]': '2', + 'issue[priority_id]': serious, + 'issue[assigned_to_id]': assign_to, + 'issue[category_id]': category, + 'issue[fixed_version_id]': target_version, + 'issue[start_date]': _today(), + 'issue[due_date]': '', + 'issue[estimated_hours]': '', + 'issue[done_ratio]': '0', + 'issue[custom_field_values][3]': '', + 'issue[custom_field_values][4]': '', + 'issue[custom_field_values][5]': '0', + 'send_notification': '0', + 'send_notification': '1', + 'commit': 'Create', } + + return fields, headers + + +class Callable: + def __init__(self, anycallable): + self.__call__ = anycallable + +class MultipartPostHandler(urllib2.BaseHandler): + handler_order = urllib2.HTTPHandler.handler_order - 10 # needs to run first + + def http_request(self, request): + data = request.get_data() + if data is not None and type(data) != str: + v_files = [] + v_vars = [] + try: + for (key, value) in data.items(): + if type(value) == file: + v_files.append((key, value)) + else: + v_vars.append((key, value)) + except TypeError: + systype, value, traceback = sys.exc_info() + raise TypeError("not non-string sequence or mapping object\n%s" + % traceback) + + if len(v_files) == 0: + data = urllib.urlencode(v_vars, doseq) + else: + boundary, data = self.multipart_encode(v_vars, v_files) + contenttype = 'multipart/form-data; boundary=%s' % boundary + if (request.has_header('Content-Type') and request.get_header( + 'Content-Type').find('multipart/form-data') != 0): + print("Replacing %s with %s" + % (request.get_header('content-type'), + 'multipart/form-data')) + request.add_unredirected_header('Content-Type', contenttype) + request.add_data(data) + return request + + def multipart_encode(self, fields=None, upload_list=None, + boundary=None, buf=None): + if fields is None: + fields = self.fields + if upload_list is None: + upload_list = self.upload_list + if boundary is None: + boundary = mimetools.choose_boundary() + if buf is None: + buf = StringIO() + + for (key, value) in fields: + buf.write('--%s\r\n' % boundary) + buf.write('Content-Disposition: form-data; name="%s"' % key) + buf.write('\r\n\r\n' + value + '\r\n') + + if isinstance(upload_list, list) and len(upload_list) > 0: + for upload in upload_list: + for (name, filepath) in upload: + with open(filepath) as fd: + file_size = os.fstat(fd.fileno())[stat.ST_SIZE] + filename = fd.name.split('/')[-1] + contenttype = mimetypes.guess_type(filename)[0] \ + or 'application/octet-stream' + buf.write('--%s\r\n' % boundary) + buf.write('Content-Disposition: form-data; ') + buf.write('name="%s"; filename="%s"' + % (name[0], filename)) + buf.write('Content-Type: %s\r\n' % contenttype) + # buf.write('Content-Length: %s\r\n' % file_size) + fd.seek(0) + buf.write('\r\n' + fd.read() + '\r\n') + buf.write('--' + boundary + '--\r\n\r\n') + buf.write('--%s\r\n' % boundary) + buf.write('Content-Disposition: form-data; ') + buf.write('name="%s"; filename="%s"' + % (name[1], filename)) + buf.write('\r\n\r\n') + buf.write('--' + boundary + '--\r\n\r\n') + + buf = buf.getvalue() + return boundary, buf + multipart_encode = Callable(multipart_encode) + + https_request = http_request + + +if __name__ == "__main__": + + raise SystemExit("Please fix me! This script needs a login handler.\n" + + "Everything else is finished.") + + ## if you're reusing this script please change these! + host = 'leap.se' + selector = '/code/projects/eip-server/issues/new' + assign_to = '30' ## isis + category = '26' ## email + target_version = '29' ## the close future + + url = 'https://' + host + selector + fields, headers = _create_fields_and_headers(host, selector, assign_to, + category, target_version) + upload_list = _create_upload_list() + cookies = cookielib.CookieJar() + opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookies), + MultipartPostHandler()) + urllib2.install_opener(opener) + + temp = tempfile.mkstemp(suffix=".html") + temp1 = tempfile.mkstemp(suffix=".html") + os.write(temp[0], opener.open('https://'+host+'/code/login', + {'username': 'cypherpunks', + 'password': 'writecode'}).read()) + + for index,upload in enumerate(upload_list): + for (field, filepath) in upload: + fields['file'+'-'+index] = open(filepath, 'rb') + res = opener.open(url, fields) + print("Posted to: %s" % res.geturl()) + print("Server response: %s " % res.code) + print(res.info()) + print(res.read()) + os.remove(temp[1])