From ff3cc9d940d400eeb7669ca01f5bc1ffc2bb4b3f Mon Sep 17 00:00:00 2001
From: Jan Dittberner <jan@dittberner.info>
Date: Tue, 12 Sep 2017 21:58:46 +0200
Subject: [PATCH 1/3] Fix issues with incompletely filled forms

This commit reintroduces support for forms with email address as
the only mandatory parameter.
---
 debianmemberportfolio/forms.py            | 13 +++++++------
 debianmemberportfolio/model/urlbuilder.py |  4 ++--
 debianmemberportfolio/views.py            | 23 ++++++++++++-----------
 3 files changed, 21 insertions(+), 19 deletions(-)

diff --git a/debianmemberportfolio/forms.py b/debianmemberportfolio/forms.py
index 85ccadf..11f6b14 100644
--- a/debianmemberportfolio/forms.py
+++ b/debianmemberportfolio/forms.py
@@ -42,14 +42,15 @@ class PlainText(Regexp):
 
 class DeveloperData(FlaskForm):
     email = StringField('email', validators=[DataRequired(), Email()])
-    name = StringField('name', validators=[DataRequired()])
+    name = StringField('name', validators=[Optional(), DataRequired()])
     gpgfp = StringField('gpgfp', validators=[
-        FingerPrint(),
-        Length(min=32, max=40)
+        Optional(), FingerPrint(), Length(min=32, max=40)
+    ])
+    username = StringField('username', validators=[Optional(), PlainText()])
+    nonddemail = StringField('nonddemail', validators=[Optional(), Email()])
+    aliothusername = StringField('aliothusername', validators=[
+        Optional(), PlainText()
     ])
-    username = StringField('username', validators=[PlainText()])
-    nonddemail = StringField('nonddemail', validators=[Email()])
-    aliothusername = StringField('aliothusername', validators=[PlainText()])
     mode = RadioField(
         'mode', default='html', choices=[
             ('json', _('JSON')), ('html', _('HTML'))
diff --git a/debianmemberportfolio/model/urlbuilder.py b/debianmemberportfolio/model/urlbuilder.py
index f948ddc..d84e302 100644
--- a/debianmemberportfolio/model/urlbuilder.py
+++ b/debianmemberportfolio/model/urlbuilder.py
@@ -3,7 +3,7 @@
 #
 # Debian Member Portfolio Service url builder
 #
-# Copyright © 2009-2015 Jan Dittberner <jan@dittberner.info>
+# Copyright © 2009-2017 Jan Dittberner <jan@dittberner.info>
 #
 # This file is part of the Debian Member Portfolio Service.
 #
@@ -73,7 +73,7 @@ def _build_quoted_fields(fields):
                 qfields[key] = quote_plus(value)
             else:
                 qfields[key] = value
-            qfields[key] = qfields[key].replace('%', '%%')
+            qfields[key] = str(qfields[key]).replace('%', '%%')
 
     if 'gpgfp' not in qfields:
         fpr = keyfinder.getFingerprintByEmail(fields['email'].encode('utf8'))
diff --git a/debianmemberportfolio/views.py b/debianmemberportfolio/views.py
index 467ad2f..dd88aa3 100644
--- a/debianmemberportfolio/views.py
+++ b/debianmemberportfolio/views.py
@@ -3,7 +3,7 @@
 #
 # Debian Member Portfolio Service views
 #
-# Copyright © 2015 Jan Dittberner <jan@dittberner.info>
+# Copyright © 2015-2017 Jan Dittberner <jan@dittberner.info>
 #
 # This file is part of the Debian Member Portfolio Service.
 #
@@ -162,25 +162,26 @@ def urllist():
     form = DeveloperData(request.values)
     if form.validate():
         fields = dddatabuilder.build_data(form.data['email'])
-        rp = request.values
+
+        form_data = form.data.copy()
 
         if fields['type'] in (dddatabuilder.TYPE_DD, dddatabuilder.TYPE_DM):
             for dmtuple in DM_TUPLES:
-                if not dmtuple[0] in rp or not rp[dmtuple[0]]:
-                    rp[dmtuple[0]] = fields[dmtuple[1]]
+                if not form_data[dmtuple[0]]:
+                    form_data[dmtuple[0]] = fields[dmtuple[1]]
         if fields['type'] == dddatabuilder.TYPE_DD:
             for ddtuple in DD_TUPLES:
-                if not ddtuple[0] in rp or not rp[ddtuple[0]]:
-                    rp[ddtuple[0]] = fields[ddtuple[1]]
-        if form.data['wikihomepage'] is None:
+                if not form_data[ddtuple[0]]:
+                    form_data[ddtuple[0]] = fields[ddtuple[1]]
+        if not form_data['wikihomepage']:
             log.debug('generate wikihomepage from name')
-            form.data['wikihomepage'] = "".join([
-                part.capitalize() for part in form.data['name'].split()
+            form_data['wikihomepage'] = "".join([
+                part.capitalize() for part in form_data['name'].split()
             ])
 
-        data = build_urls(form.data)
+        data = build_urls(form_data)
 
-        if form.data['mode'] == 'json':
+        if form_data['mode'] == 'json':
             response = make_response(json.dumps(dict(
                 [("{}.{}".format(entry[1], entry[2].name), entry[3])
                  for entry in data if entry[0] == 'url'])))

From f11114f58047f50d0a71f42e4e24e4bbb1e04b64 Mon Sep 17 00:00:00 2001
From: Jan Dittberner <jan@dittberner.info>
Date: Tue, 12 Sep 2017 22:13:02 +0200
Subject: [PATCH 2/3] Strip non hexadecimal characters from GPG fingerprint
 input

This commit removes non hexadecimal characters from entered GPG
fingerprint values to allow copy and paste from gpg output.
---
 debianmemberportfolio/forms.py | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/debianmemberportfolio/forms.py b/debianmemberportfolio/forms.py
index 11f6b14..d4c87fc 100644
--- a/debianmemberportfolio/forms.py
+++ b/debianmemberportfolio/forms.py
@@ -28,6 +28,7 @@ from wtforms import IntegerField, StringField, RadioField
 from wtforms.validators import (
     AnyOf, DataRequired, Email, Length, Optional, Regexp
 )
+from string import hexdigits
 
 
 class FingerPrint(Regexp):
@@ -40,10 +41,17 @@ class PlainText(Regexp):
         super(PlainText, self).__init__(r'^[a-zA-Z\-0-9]*$')
 
 
+def gpg_fingerprint(data):
+    if data is not None:
+        return "".join([
+            char for char in str(data) if char.lower() in hexdigits])
+    return data
+
+
 class DeveloperData(FlaskForm):
     email = StringField('email', validators=[DataRequired(), Email()])
     name = StringField('name', validators=[Optional(), DataRequired()])
-    gpgfp = StringField('gpgfp', validators=[
+    gpgfp = StringField('gpgfp', filters=[gpg_fingerprint], validators=[
         Optional(), FingerPrint(), Length(min=32, max=40)
     ])
     username = StringField('username', validators=[Optional(), PlainText()])

From 0247ac612b3ad3275b7ee1b7387144e4f1192359 Mon Sep 17 00:00:00 2001
From: Jan Dittberner <jan@dittberner.info>
Date: Tue, 12 Sep 2017 22:14:47 +0200
Subject: [PATCH 3/3] Bump version to 0.5.2

---
 setup.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/setup.py b/setup.py
index d540125..052ce33 100644
--- a/setup.py
+++ b/setup.py
@@ -29,7 +29,7 @@ except ImportError:
 
 setup(
     name='debianmemberportfolio',
-    version='0.5.1',
+    version='0.5.2',
     description='service to create Debian Member Portfolio URLs',
     long_description="""This is a service implementation that returns a set of
     personalized URLs as outlined in https://wiki.debian.org/DDPortfolio. It