diff --git a/ddportfolioservice/config/routing.py b/ddportfolioservice/config/routing.py
index 6d6dfb6..3d116d4 100644
--- a/ddportfolioservice/config/routing.py
+++ b/ddportfolioservice/config/routing.py
@@ -41,6 +41,8 @@ def make_map():
     # CUSTOM ROUTES HERE
     map.connect('', controller='ddportfolio', action='index')
     map.connect('result', controller='ddportfolio', action='urllist')
+    map.connect('htmlformhelper.js', controller='showformscripts',
+                action='index')
     map.connect(':controller/:action/:id')
     map.connect('*url', controller='template', action='view')
 
diff --git a/ddportfolioservice/controllers/showformscripts.py b/ddportfolioservice/controllers/showformscripts.py
index 7664345..72a0aeb 100644
--- a/ddportfolioservice/controllers/showformscripts.py
+++ b/ddportfolioservice/controllers/showformscripts.py
@@ -1,13 +1,69 @@
+# -*- python -*-
+# -*- coding: utf-8 -*-
+#
+# DDPortfolio service ShowformscriptController.
+# Copyright (c) 2009 Jan Dittberner <jan@dittberner.info>
+#
+# This file is part of DDPortfolio service.
+#
+# DDPortfolio service is free software: you can redistribute it and/or
+# modify it under the terms of the GNU Affero General Public License
+# as published by the Free Software Foundation, either version 3 of
+# the License, or (at your option) any later version.
+#
+# DDPortfolio service 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
+# Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public
+# License along with this program.  If not, see
+# <http://www.gnu.org/licenses/>.
+#
 import logging
+import simplejson
 
 from ddportfolioservice.lib.base import *
+from ddportfolioservice.model.form import *
+from ddportfolioservice.model import keyfinder
+from webob.exc import HTTPBadRequest
 
 log = logging.getLogger(__name__)
 
 class ShowformscriptsController(BaseController):
+    """This controller is used to support data entry in showform.
+
+    It provides code for generating JavaScript as well as JSON
+    responses for autocompletion of fields."""
 
     def index(self):
-        # Return a rendered template
-        #   return render('/some/template.mako')
-        # or, Return a response
-        return 'Hello World'
+        """This action generates the helper script for the showform
+        page."""
+        response.headers['Content-Type'] = 'text/javascript'
+        return render('/showformscript.mako')
+
+    def fetchdddata(self):
+        schema = DDDataRequest()
+        try:
+            formencode.api.set_stdtranslation(
+                domain="FormEncode",
+                languages=[lang[0:2] for lang in request.languages])
+            form_result = schema.to_python(request.params)
+        except formencode.validators.Invalid, error:
+            errors = error.unpack_errors()
+            abort(400, "\n".join(
+                    ["%s: %s" % (key, errors[key]) for key in errors]))
+        
+        fields = dict([(field, func(str(form_result['email']))) \
+                           for (field, func) in \
+                           [('gpgfp', keyfinder.getFingerprintByEmail),
+                            ('name', keyfinder.getRealnameByEmail),
+                            ('username', keyfinder.getLoginByEmail)]])
+        fields['email'] = form_result['email']
+        if fields['username'] and fields['gpgfp'] and fields['name']:
+            fields['isdd'] = 1
+        else:
+            fields['isdd'] = 0
+        log.debug(fields)
+        response.headers['Content-Type'] = 'text/plain'
+        return simplejson.dumps(fields)
diff --git a/ddportfolioservice/model/form.py b/ddportfolioservice/model/form.py
index b8f39ed..b097c45 100644
--- a/ddportfolioservice/model/form.py
+++ b/ddportfolioservice/model/form.py
@@ -29,9 +29,14 @@ class DeveloperData(formencode.Schema):
     email = formencode.validators.Email(not_empty=True)
     name = formencode.validators.String(not_empty=True)
     gpgfp = formencode.All(formencode.validators.PlainText(),
-                           formencode.validators.MinLength(32),
-                           formencode.validators.MaxLength(32))
+                           formencode.validators.MinLength(40),
+                           formencode.validators.MaxLength(40))
     username = formencode.validators.PlainText()
     nonddemail = formencode.validators.Email()
     aliothusername = formencode.validators.PlainText()
     mode = formencode.validators.OneOf([u'json', u'html'], not_empty=True)
+
+class DDDataRequest(formencode.Schema):
+    """Validation schema for DDData request."""
+    allow_extra_fields = False
+    email = formencode.validators.Email(not_empty=True)
diff --git a/ddportfolioservice/templates/base.mako b/ddportfolioservice/templates/base.mako
index d209ec6..c01b4a0 100644
--- a/ddportfolioservice/templates/base.mako
+++ b/ddportfolioservice/templates/base.mako
@@ -1,7 +1,7 @@
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
           "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <%doc>
-Template for the data input form.
+Base template for XHTML templates.
 Copyright (c) 2009 Jan Dittberner <jan@dittberner.info>
 
 This file is part of DDPortfolio service.
diff --git a/ddportfolioservice/templates/showform.mako b/ddportfolioservice/templates/showform.mako
index fa37508..a520ae1 100644
--- a/ddportfolioservice/templates/showform.mako
+++ b/ddportfolioservice/templates/showform.mako
@@ -22,11 +22,17 @@ License along with this program.  If not, see
 <%def name="titleaddon()">
  - ${_('Enter your personal information')}
 </%def>
-<%def name="extrahead()">${h.javascript_link('/javascript/jquery/jquery.js')}</%def>
+<%def name="extrahead()">${h.javascript_link('/javascript/jquery/jquery.js',
+h.url_for(controller='showformscripts',
+action='index'))}</%def>
 ${h.form(h.url_for(action='urllist'), method='get')}
 <fieldset id="ddportfolio">
   <legend>${_('Debian Developer Portfolio')}</legend>
-  <div id="emailfield">
+  <div id="emailfield" \
+       % if 'email' in c.messages['errors']:
+       class="witherrors" \
+       % endif
+       >
     <label for="email">${_('Email address:')}
       % if 'email' in c.messages['errors']:
       <br />
@@ -35,7 +41,11 @@ ${h.form(h.url_for(action='urllist'), method='get')}
     </label><br />
     ${h.text('email', request.params.get('email', None), id='email')}<br />
   </div>
-  <div id="namefield">
+  <div id="namefield" \
+       % if 'name' in c.messages['errors']:
+       class="witherrors" \
+       % endif
+       >
     <label for="name">${_('Name:')}
       % if 'name' in c.messages['errors']:
       <br />
@@ -54,7 +64,11 @@ ${h.form(h.url_for(action='urllist'), method='get')}
     ${h.text('gpgfp', request.params.get('gpgfp', None),
     id='gpgfp', readonly='readonly')}<br />
   </div>
-  <div id="usernamefield">
+  <div id="usernamefield" \
+       % if 'username' in c.messages['errors']:
+       class="witherrors" \
+       % endif
+       >    
     <label for="username">${_('Debian user name:')}
       % if 'username' in c.messages['errors']:
       <br />
@@ -64,7 +78,11 @@ ${h.form(h.url_for(action='urllist'), method='get')}
     ${h.text('username', request.params.get('username', None),
     id='username')}<br />
   </div>
-  <div id="nonddemailfield">
+  <div id="nonddemailfield" \
+       % if 'nonddemail' in c.messages['errors']:
+       class="witherrors" \
+       % endif
+       >
     <label for="nonddemail">${_('Non DD email address:')}
       % if 'nonddemail' in c.messages['errors']:
       <br />
@@ -74,7 +92,11 @@ ${h.form(h.url_for(action='urllist'), method='get')}
     ${h.text('nonddemail', request.params.get('nonddemail', None),
     id='nonddemail')}<br />
   </div>
-  <div id="aliothusernamefield">
+  <div id="aliothusernamefield" \
+       % if 'aliothusername' in c.messages['errors']:
+       class="witherrors"
+       % endif
+       >
     <label for="aliothusername">${_('Alioth user name:')}
       % if 'aliothusername' in c.messages['errors']:
       <br />
diff --git a/ddportfolioservice/templates/showformscript.mako b/ddportfolioservice/templates/showformscript.mako
new file mode 100644
index 0000000..b951a78
--- /dev/null
+++ b/ddportfolioservice/templates/showformscript.mako
@@ -0,0 +1,78 @@
+## -*- coding: utf-8 -*-
+<%doc>
+Helper JavaScript for the data input form.
+Copyright (c) 2009 Jan Dittberner <jan@dittberner.info>
+
+This file is part of DDPortfolio service.
+
+DDPortfolio service is free software: you can redistribute it and/or
+modify it under the terms of the GNU Affero General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
+
+DDPortfolio service 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
+Affero General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public
+License along with this program.  If not, see
+<http://www.gnu.org/licenses/>.
+</%doc>
+
+function updateFields(data, textStatus) {
+    if (data.isdd == 1) {
+        $('#name').attr('value', data.name).attr('readonly', 'readonly');
+        $('#gpgfp').attr('value', data.gpgfp);
+        $('#username').attr('value', data.username).attr(
+            'readonly', 'readonly');
+        $('#nonddemail').attr('value', data.email).focus();
+        $('#aliothusername').attr('value', data.username);
+
+        $('#namefield').show();
+        $('#gpgfpfield').show();
+        $('#usernamefield').show();
+        $('#nonddemailfield').show();
+        $('#aliothusernamefield').show();
+
+        $('#nonddemail').focus().select();
+    } else {
+        $('#nonddemail').attr('value', data.email);
+        $('#name').removeAttr('readonly');
+        $('#username').removeAttr('readonly').attr('value', '');
+        $('#gpgfp').attr('value', '');
+
+        $('#usernamefield').hide();
+        $('#gpgfpfield').hide();
+        $('#nonddemailfield').hide();
+        $('#namefield').show();
+        $('#aliothusernamefield').show();
+
+        $('#name').focus().select();
+    }
+}
+
+function onBlurEmail() {
+    $.ajax({
+        'url' : '${h.url_for(action='fetchdddata')}',
+        'data' : {'email' : $('#email').attr('value')},
+        'dataType' : 'json',
+        'success' : updateFields,
+        'error' : function(request, textStatus, errorThrown) {
+            $('#email').focus();
+        }
+    });
+}
+
+$(document).ready(function() {
+    var fields = new Array(
+        '#namefield', '#usernamefield',
+        '#nonddemailfield', '#aliothusernamefield');
+    for (var index in fields) {
+        if (!$(fields[index]).hasClass('witherrors')) {
+            $(fields[index]).hide();
+        }
+    }
+
+    $('#email').blur(onBlurEmail).focus();
+});