hosted/index.php hosted/js hosted/skins lib/client lib/functions.php lib/hosted lib/recaptchalib.php public_html/index.php public_html/js public_html/skins

Aleksander Machniak machniak at kolabsys.com
Thu Sep 27 09:28:02 CEST 2012


 dev/null                                               |binary
 hosted/index.php                                       |   11 
 hosted/js                                              |    1 
 hosted/js/jquery.min.js                                |    1 
 hosted/js/kolab_admin.js                               |    1 
 hosted/js/kolab_hosted.js                              |  120 ------
 hosted/skins                                           |    1 
 hosted/skins/default/hosted.css                        |   44 --
 hosted/skins/default/images/error.png                  |    1 
 hosted/skins/default/images/favicon.png                |    1 
 hosted/skins/default/images/info.png                   |    1 
 hosted/skins/default/images/loading.gif                |    1 
 hosted/skins/default/style.css                         |    1 
 hosted/skins/default/templates/footer.html             |    1 
 hosted/skins/default/templates/signup.html             |   41 --
 hosted/skins/default/ui.js                             |    1 
 hosted/skins/kolabsys/hosted.css                       |   26 -
 hosted/skins/kolabsys/images/error.png                 |    1 
 hosted/skins/kolabsys/images/favicon.png               |    1 
 hosted/skins/kolabsys/images/info.png                  |    1 
 hosted/skins/kolabsys/images/loading.gif               |    1 
 hosted/skins/kolabsys/style.css                        |    1 
 hosted/skins/kolabsys/templates/signup.html            |   20 -
 hosted/skins/kolabsys/ui.js                            |    1 
 hosted/skins/minimal/hosted.css                        |    1 
 hosted/skins/minimal/images/error.png                  |    1 
 hosted/skins/minimal/images/favicon.png                |    1 
 hosted/skins/minimal/images/info.png                   |    1 
 hosted/skins/minimal/images/loading.gif                |    1 
 hosted/skins/minimal/style.css                         |    1 
 hosted/skins/minimal/templates/footer.html             |    1 
 hosted/skins/minimal/templates/signup.html             |   23 -
 hosted/skins/minimal/ui.js                             |    1 
 lib/client/kolab_client_task_signup.php                |  327 +++++++++++++++++
 lib/functions.php                                      |    1 
 lib/hosted/kolab_client_task_signup.php                |  327 -----------------
 lib/hosted/recaptchalib.php                            |  277 --------------
 lib/recaptchalib.php                                   |  277 ++++++++++++++
 public_html/index.php                                  |    2 
 public_html/js/kolab_hosted.js                         |  120 ++++++
 public_html/skins/default/hosted.css                   |   45 ++
 public_html/skins/default/images/logo_kolab.png        |binary
 public_html/skins/default/templates/signup.html        |   32 +
 public_html/skins/default/templates/signup_footer.html |    1 
 public_html/skins/default/ui.js                        |    2 
 public_html/skins/kolabsys/hosted.css                  |   26 +
 public_html/skins/kolabsys/style.css                   |    1 
 public_html/skins/kolabsys/templates/signup.html       |   20 +
 public_html/skins/kolabsys/ui.js                       |    1 
 public_html/skins/minimal/hosted.css                   |    1 
 public_html/skins/minimal/style.css                    |    1 
 public_html/skins/minimal/templates/signup.html        |   23 +
 public_html/skins/minimal/templates/signup_footer.html |    1 
 public_html/skins/minimal/ui.js                        |    1 
 54 files changed, 882 insertions(+), 914 deletions(-)

New commits:
commit 71fe77ab8367cb4473e6bac7d8f002f82a121b99
Author: Aleksander Machniak <alec at alec.pl>
Date:   Thu Sep 27 09:25:14 2012 +0200

    Integrate hosted/signup with core, fix Smarty cache issue (#1044)

diff --git a/hosted/index.php b/hosted/index.php
index 867a6e1..6414cbe 100644
--- a/hosted/index.php
+++ b/hosted/index.php
@@ -26,16 +26,7 @@
 // environment initialization
 require_once '../lib/functions.php';
 
-// starting task
-$task = kolab_utils::get_input('task', kolab_utils::REQUEST_GET);
-
-if (!$task) {
-    $task = 'signup';
-}
-
-$class = "kolab_client_task_$task";
-
-$KADM = new $class;
+$KADM = new kolab_client_task_signup;
 
 // run actions and send output
 $KADM->run();
diff --git a/hosted/js b/hosted/js
new file mode 120000
index 0000000..050426c
--- /dev/null
+++ b/hosted/js
@@ -0,0 +1 @@
+../public_html/js
\ No newline at end of file
diff --git a/hosted/js/jquery.min.js b/hosted/js/jquery.min.js
deleted file mode 120000
index c3b1873..0000000
--- a/hosted/js/jquery.min.js
+++ /dev/null
@@ -1 +0,0 @@
-../../public_html/js/jquery.min.js
\ No newline at end of file
diff --git a/hosted/js/kolab_admin.js b/hosted/js/kolab_admin.js
deleted file mode 120000
index ea11949..0000000
--- a/hosted/js/kolab_admin.js
+++ /dev/null
@@ -1 +0,0 @@
-../../public_html/js/kolab_admin.js
\ No newline at end of file
diff --git a/hosted/js/kolab_hosted.js b/hosted/js/kolab_hosted.js
deleted file mode 100644
index 9f717ae..0000000
--- a/hosted/js/kolab_hosted.js
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- +--------------------------------------------------------------------------+
- | This file is part of the Kolab Web Admin Panel                           |
- |                                                                          |
- | Copyright (C) 2011-2012, Kolab Systems AG                                |
- |                                                                          |
- | This program 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.                                      |
- |                                                                          |
- | 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 Affero General Public License for more details.                      |
- |                                                                          |
- | You should have received a copy of the GNU Affero General Public License |
- | along with kadm program. If not, see <http://www.gnu.org/licenses/>      |
- +--------------------------------------------------------------------------+
- | Author: Torsten Grote <grote at kolabsys.com>                               |
- +--------------------------------------------------------------------------+
-*/
-
-// overwrite user_save() function
-kadm.user_save = function(reload, section)
-{
-    var data = kadm.serialize_form('#'+this.env.form_id);
-
-    // check email address
-    if(typeof data.mailalternateaddress != 'undefined' && !isValidEmailAddress(data.mailalternateaddress)) {
-        kadm.display_message('signup.wrongmailalternateaddress', 'error');
-        kadm.form_value_error('mailalternateaddress');
-        return;
-    }
-
-    if (!kadm.check_required_fields(data)) {
-      kadm.display_message('form.required.empty', 'error');
-      return;
-    }
-
-    // check password
-    if (data.userpassword != data.userpassword2) {
-      kadm.display_message('user.password.mismatch', 'error');
-      kadm.form_value_error('userpassword2');
-      return;
-    }
-    delete data['userpassword2'];
-
-    kadm.http_post('signup.add_user', {data: data});
-};
-
-kadm.change_user_type = function()
-{
-    var data = kadm.serialize_form('#'+this.env.form_id);
-
-    kadm.http_post('signup.default', {data: data});
-};
-
-kadm.check_user_availability = function()
-{
-    // get form data and build new email address
-    var data = kadm.serialize_form('#signup-form');
-    var mail = data['uid'] + '@' + data['domain'];
-
-    if(isValidEmailAddress(mail)) {
-        // update future mail form field
-        $('input[name="mail"]').val(mail);
-
-        // check if user with that email address already exists
-        kadm.http_post('signup.check_user', {data: data});
-    } else {
-        kadm.update_user_info('signup.wronguid', 'uid');
-    }
-};
-
-kadm.update_user_info = function(msg, part)
-{
-    var span_id = 'availability';
-    if(!part.localeCompare('userpassword')) {
-        span_id = 'pass_match';
-    }
-
-    if (msg) {
-        msg = kadm.t(msg);
-    }
-
-    // display message next to form field
-    if($('span[id="'+span_id+'"]').length) {
-        // update existing span area
-        $('span[id="'+span_id+'"]').html(msg);
-    }
-    else {
-        // add span area and add message
-        $('input[name="'+part+'"]').after(' <span id="'+span_id+'" class="form_error">' + msg + '</span>');
-    }
-
-    // enable/disable button
-    if(msg == '') {
-        $('input[type="button"]').removeAttr("disabled");
-    } else {
-        $('input[type="button"]').attr("disabled", "disabled");
-    }
-};
-
-
-function password_match()
-{
-    if($('input[name="userpassword"]').val().localeCompare($('input[name="userpassword2"]').val())) {
-        kadm.update_user_info('user.password.mismatch', 'userpassword');
-    }
-    else {
-        kadm.update_user_info('', 'userpassword');
-    }
-}
-
-// TODO use form.validate api call for that
-function isValidEmailAddress(emailAddress) {
-    var pattern = new RegExp(/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i);
-    return pattern.test(emailAddress);
-};
diff --git a/hosted/skins b/hosted/skins
new file mode 120000
index 0000000..5327ffe
--- /dev/null
+++ b/hosted/skins
@@ -0,0 +1 @@
+../public_html/skins
\ No newline at end of file
diff --git a/hosted/skins/default/hosted.css b/hosted/skins/default/hosted.css
deleted file mode 100644
index bba4df6..0000000
--- a/hosted/skins/default/hosted.css
+++ /dev/null
@@ -1,44 +0,0 @@
-body {
-  background: #f0f0f0;
-  text-align: center;
-}
-
-#bodybox {
-  display: inline-block;
-  width: 900px;
-  text-align: left;
-}
-
-#logo {
-  width: 462px;
-  height: 100px;
-  position: relative;
-  margin: 10px;
-  cursor: default;
-}
-
-#content {
-  padding: 15px;
-}
-
-#taskcontent {
-  display: inline-block;
-  margin-top: 10px;
-  text-align: center;
-}
-
-form#signup-form {
-  padding-top: 10px;
-}
-
-td.label {
-  vertical-align: top;
-}
-
-table.form td {
-    text-align: left;
-}
-
-#footer {
-  text-align: center;
-}
diff --git a/hosted/skins/default/images/error.png b/hosted/skins/default/images/error.png
deleted file mode 120000
index fe901a7..0000000
--- a/hosted/skins/default/images/error.png
+++ /dev/null
@@ -1 +0,0 @@
-../../../../public_html/skins/default/images/error.png
\ No newline at end of file
diff --git a/hosted/skins/default/images/favicon.png b/hosted/skins/default/images/favicon.png
deleted file mode 120000
index 7ee1ea8..0000000
--- a/hosted/skins/default/images/favicon.png
+++ /dev/null
@@ -1 +0,0 @@
-../../../../public_html/skins/default/images/favicon.png
\ No newline at end of file
diff --git a/hosted/skins/default/images/info.png b/hosted/skins/default/images/info.png
deleted file mode 120000
index 8e1fec7..0000000
--- a/hosted/skins/default/images/info.png
+++ /dev/null
@@ -1 +0,0 @@
-../../../../public_html/skins/default/images/info.png
\ No newline at end of file
diff --git a/hosted/skins/default/images/loading.gif b/hosted/skins/default/images/loading.gif
deleted file mode 120000
index aaca76f..0000000
--- a/hosted/skins/default/images/loading.gif
+++ /dev/null
@@ -1 +0,0 @@
-../../../../public_html/skins/default/images/loading.gif
\ No newline at end of file
diff --git a/hosted/skins/default/images/logo.png b/hosted/skins/default/images/logo.png
deleted file mode 100644
index 0c06ff1..0000000
Binary files a/hosted/skins/default/images/logo.png and /dev/null differ
diff --git a/hosted/skins/default/style.css b/hosted/skins/default/style.css
deleted file mode 120000
index 6f5490d..0000000
--- a/hosted/skins/default/style.css
+++ /dev/null
@@ -1 +0,0 @@
-../../../public_html/skins/default/style.css
\ No newline at end of file
diff --git a/hosted/skins/default/templates/footer.html b/hosted/skins/default/templates/footer.html
deleted file mode 100644
index 24d972d..0000000
--- a/hosted/skins/default/templates/footer.html
+++ /dev/null
@@ -1 +0,0 @@
-{$engine->translate('signup.footer')}
diff --git a/hosted/skins/default/templates/signup.html b/hosted/skins/default/templates/signup.html
deleted file mode 100644
index 8043859..0000000
--- a/hosted/skins/default/templates/signup.html
+++ /dev/null
@@ -1,41 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-    <meta charset="utf-8" />
-    <title>{$engine->translate('signup.headline')}</title>
-    <link rel="stylesheet" href="{$skin_path}style.css" />
-    <link rel="stylesheet" href="{$skin_path}hosted.css" />
-    <link rel="shortcut icon" type="image/png" href="{$skin_path}images/favicon.png" />
-    <script src="js/jquery.min.js"></script>
-    <script src="js/kolab_admin.js"></script>
-    <script type="text/javascript" src="https://www.google.com/recaptcha/api/js/recaptcha_ajax.js"></script>
-    <script src="js/kolab_hosted.js"></script>
-    <script src="{$skin_path}ui.js"></script>
-</head>
-<body>
-    <div id="bodybox">
-        <div id="logo"></div>
-        <div id="content">
-
-
-        <div id="task_content" class="signup">
-    
-        <h1>{$engine->translate('signup.headline')}</h1>
-
-        <p>{$engine->translate('signup.intro1')}</p>
-
-        <p>{$engine->translate('signup.intro2')}</p>
-    
-        <div id="taskcontent" class="signup">{$form}</div>
-
-
-        </div>
-    
-        </div>
-        <div id="footer">
-            {include file="footer.html"}
-        </div>
-    </div>
-{$script}
-</body>
-</html>
diff --git a/hosted/skins/default/ui.js b/hosted/skins/default/ui.js
deleted file mode 120000
index 625253b..0000000
--- a/hosted/skins/default/ui.js
+++ /dev/null
@@ -1 +0,0 @@
-../../../public_html/skins/default/ui.js
\ No newline at end of file
diff --git a/hosted/skins/kolabsys/hosted.css b/hosted/skins/kolabsys/hosted.css
deleted file mode 100644
index 427d57d..0000000
--- a/hosted/skins/kolabsys/hosted.css
+++ /dev/null
@@ -1,26 +0,0 @@
-body {
-  background: #F3F3F3;
-  text-align: center;
-}
-
-#taskcontent {
-  width: 680px;
-  min-height: 100px;
-  max-height: 460px;
-}
-
-form#signup-form {
-  padding-top: 10px;
-}
-
-td.value input {
-    width: 250px;
-}
-
-td.label {
-  vertical-align: top;
-}
-
-table.form td {
-    text-align: left;
-}
diff --git a/hosted/skins/kolabsys/images/error.png b/hosted/skins/kolabsys/images/error.png
deleted file mode 120000
index fe901a7..0000000
--- a/hosted/skins/kolabsys/images/error.png
+++ /dev/null
@@ -1 +0,0 @@
-../../../../public_html/skins/default/images/error.png
\ No newline at end of file
diff --git a/hosted/skins/kolabsys/images/favicon.png b/hosted/skins/kolabsys/images/favicon.png
deleted file mode 120000
index 7ee1ea8..0000000
--- a/hosted/skins/kolabsys/images/favicon.png
+++ /dev/null
@@ -1 +0,0 @@
-../../../../public_html/skins/default/images/favicon.png
\ No newline at end of file
diff --git a/hosted/skins/kolabsys/images/info.png b/hosted/skins/kolabsys/images/info.png
deleted file mode 120000
index 8e1fec7..0000000
--- a/hosted/skins/kolabsys/images/info.png
+++ /dev/null
@@ -1 +0,0 @@
-../../../../public_html/skins/default/images/info.png
\ No newline at end of file
diff --git a/hosted/skins/kolabsys/images/loading.gif b/hosted/skins/kolabsys/images/loading.gif
deleted file mode 120000
index aaca76f..0000000
--- a/hosted/skins/kolabsys/images/loading.gif
+++ /dev/null
@@ -1 +0,0 @@
-../../../../public_html/skins/default/images/loading.gif
\ No newline at end of file
diff --git a/hosted/skins/kolabsys/style.css b/hosted/skins/kolabsys/style.css
deleted file mode 120000
index 6f5490d..0000000
--- a/hosted/skins/kolabsys/style.css
+++ /dev/null
@@ -1 +0,0 @@
-../../../public_html/skins/default/style.css
\ No newline at end of file
diff --git a/hosted/skins/kolabsys/templates/signup.html b/hosted/skins/kolabsys/templates/signup.html
deleted file mode 100644
index 7c756ae..0000000
--- a/hosted/skins/kolabsys/templates/signup.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-    <meta charset="utf-8" />
-    <title>Sign Up For Hosted Kolab</title>
-    <link rel="stylesheet" href="{$skin_path}style.css" />
-    <link rel="stylesheet" href="{$skin_path}hosted.css" />
-    <link rel="shortcut icon" type="image/png" href="{$skin_path}images/favicon.png" />
-    <script src="js/jquery.min.js"></script>
-    <script src="js/kolab_admin.js"></script>
-    <script type="text/javascript" src="https://www.google.com/recaptcha/api/js/recaptcha_ajax.js"></script>
-    <script src="js/kolab_hosted.js"></script>
-    <script src="{$skin_path}ui.js"></script>
-</head>
-<body>
-    <div id="taskcontent" class="signup">{$form}</div>
-
-    {$script}
-</body>
-</html>
diff --git a/hosted/skins/kolabsys/ui.js b/hosted/skins/kolabsys/ui.js
deleted file mode 120000
index 625253b..0000000
--- a/hosted/skins/kolabsys/ui.js
+++ /dev/null
@@ -1 +0,0 @@
-../../../public_html/skins/default/ui.js
\ No newline at end of file
diff --git a/hosted/skins/minimal/hosted.css b/hosted/skins/minimal/hosted.css
deleted file mode 120000
index a66df34..0000000
--- a/hosted/skins/minimal/hosted.css
+++ /dev/null
@@ -1 +0,0 @@
-../default/hosted.css
\ No newline at end of file
diff --git a/hosted/skins/minimal/images/error.png b/hosted/skins/minimal/images/error.png
deleted file mode 120000
index fe901a7..0000000
--- a/hosted/skins/minimal/images/error.png
+++ /dev/null
@@ -1 +0,0 @@
-../../../../public_html/skins/default/images/error.png
\ No newline at end of file
diff --git a/hosted/skins/minimal/images/favicon.png b/hosted/skins/minimal/images/favicon.png
deleted file mode 120000
index 7ee1ea8..0000000
--- a/hosted/skins/minimal/images/favicon.png
+++ /dev/null
@@ -1 +0,0 @@
-../../../../public_html/skins/default/images/favicon.png
\ No newline at end of file
diff --git a/hosted/skins/minimal/images/info.png b/hosted/skins/minimal/images/info.png
deleted file mode 120000
index 8e1fec7..0000000
--- a/hosted/skins/minimal/images/info.png
+++ /dev/null
@@ -1 +0,0 @@
-../../../../public_html/skins/default/images/info.png
\ No newline at end of file
diff --git a/hosted/skins/minimal/images/loading.gif b/hosted/skins/minimal/images/loading.gif
deleted file mode 120000
index aaca76f..0000000
--- a/hosted/skins/minimal/images/loading.gif
+++ /dev/null
@@ -1 +0,0 @@
-../../../../public_html/skins/default/images/loading.gif
\ No newline at end of file
diff --git a/hosted/skins/minimal/style.css b/hosted/skins/minimal/style.css
deleted file mode 120000
index 6f5490d..0000000
--- a/hosted/skins/minimal/style.css
+++ /dev/null
@@ -1 +0,0 @@
-../../../public_html/skins/default/style.css
\ No newline at end of file
diff --git a/hosted/skins/minimal/templates/footer.html b/hosted/skins/minimal/templates/footer.html
deleted file mode 100644
index 4b6bac5..0000000
--- a/hosted/skins/minimal/templates/footer.html
+++ /dev/null
@@ -1 +0,0 @@
-This is a service offered by <a href="http://kolabsys.com">Kolab Systems</a>.
diff --git a/hosted/skins/minimal/templates/signup.html b/hosted/skins/minimal/templates/signup.html
deleted file mode 100644
index 961dbf8..0000000
--- a/hosted/skins/minimal/templates/signup.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-    <meta charset="utf-8" />
-    <title>Sign Up For Hosted Kolab</title>
-    <link rel="stylesheet" href="{$skin_path}style.css" />
-    <link rel="stylesheet" href="{$skin_path}hosted.css" />
-    <link rel="shortcut icon" type="image/png" href="{$skin_path}images/favicon.png" />
-    <script src="js/jquery.min.js"></script>
-    <script src="js/kolab_admin.js"></script>
-    <script type="text/javascript" src="https://www.google.com/recaptcha/api/js/recaptcha_ajax.js"></script>
-    <script src="js/kolab_hosted.js"></script>
-    <script src="{$skin_path}ui.js"></script>
-</head>
-<body>
-    <div id="taskcontent" class="signup">{$form}</div>
-
-    <div id="footer">
-        {include file="footer.html"}
-    </div>
-{$script}
-</body>
-</html>
diff --git a/hosted/skins/minimal/ui.js b/hosted/skins/minimal/ui.js
deleted file mode 120000
index 625253b..0000000
--- a/hosted/skins/minimal/ui.js
+++ /dev/null
@@ -1 +0,0 @@
-../../../public_html/skins/default/ui.js
\ No newline at end of file
diff --git a/lib/client/kolab_client_task_signup.php b/lib/client/kolab_client_task_signup.php
new file mode 100644
index 0000000..a320216
--- /dev/null
+++ b/lib/client/kolab_client_task_signup.php
@@ -0,0 +1,327 @@
+<?php
+/*
+ +--------------------------------------------------------------------------+
+ | This file is part of the Kolab Web Admin Panel                           |
+ |                                                                          |
+ | Copyright (C) 2011-2012, Kolab Systems AG                                |
+ |                                                                          |
+ | This program 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.                                      |
+ |                                                                          |
+ | 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 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/>      |
+ +--------------------------------------------------------------------------+
+ | Author: Aleksander Machniak <machniak at kolabsys.com>                      |
+ | Author: Torsten Grote <grote at kolabsys.com>                               |
+ +--------------------------------------------------------------------------+
+*/
+
+require_once('recaptchalib.php');
+
+class kolab_client_task_signup extends kolab_client_task
+{
+    protected $ajax_only = true;
+
+    /**
+     * Overwrite Main execution.
+     */
+    public function run()
+    {
+        // don't set any cookies
+        ini_set('session.use_cookies', '0');
+
+        // Initialize locales
+        $this->locale_init();
+
+        // Assign self to template variable
+        $this->output->assign('engine', $this);
+
+        // Run security checks
+        // TODO figure out to reenable this
+//        $this->input_checks();
+
+        $action = $this->get_input('action', 'GET');
+
+        if ($action) {
+            $method = 'action_' . $action;
+            if (method_exists($this, $method)) {
+                $this->$method();
+            }
+        }
+        else if (method_exists($this, 'action_default')) {
+            $this->action_default();
+        }
+    }
+
+    private function login($domain=NULL)
+    {
+        if(is_null($domain)) {
+            $this->domain = $this->config_get('primary_domain');
+        }
+
+        // Login ($result is a kolab_client_api_result instance)
+        $result = $this->api->login($this->config_get('bind_dn'), $this->config_get('bind_pw'), $this->domain);
+
+        // Set the session token we got in the API client instance, so subsequent
+        // API calls are made in the same session.
+        $this->token = $result->get('session_token');
+        $this->api->set_session_token($this->token);
+    }
+
+    public function action_default()
+    {
+        $this->login();
+
+        $data = $this->get_input('data', 'POST');
+        $form = $this->user_form($data);
+
+        // add captcha
+        $publickey = $this->config_get('recaptcha_public_key');
+
+        if (!empty($publickey)) {
+            // TODO find a less dirty way to add captcha into form
+            $form = preg_replace('/<\/tbody>/', '<tr><td class="label">'.$this->translate('signup.captcha').'</td><td class="value"><div id="recaptcha_div"></div></td></tr></tbody>', $form);
+
+            // load captcha
+            $form .= '
+                <script type="text/javascript">
+                    Recaptcha.create("'.$publickey.'", "recaptcha_div", {theme: "red"});
+                </script>';
+        }
+
+        $this->output->assign('form', $form);
+        $this->output->set_object('taskcontent', $form);
+    }
+
+    // check if user already exists
+    public function action_check_user($data = array()) {
+        if(count($data) == 0) $data = $this->get_input('data', 'POST');
+
+        $this->login($data['domain']);
+
+        // Assemble mail attribute
+        $mail = $data['uid'].'@'.$data['domain'];
+
+        $post = array('search' => array('mail' => array('value' => $mail) ) );
+        $result = $this->api->post('users.list', null, $post);
+
+        if($result->get('count') > 0) {
+            $this->output->command('update_user_info("signup.userexists", "uid")');
+            return false;
+        }
+
+        $this->output->command('update_user_info("", "uid")');
+        return true;
+    }
+
+    public function action_add_user() {
+        $data = $this->get_input('data', 'POST');
+
+        $private_key = $this->config_get('recaptcha_private_key');
+
+        if (!empty($private_key)) {
+            // Check for valid CAPTCHA
+            $resp = recaptcha_check_answer(
+                        $private_key,
+                        $_SERVER['REMOTE_ADDR'],
+                        $data['recaptcha_challenge_field'],
+                        $data['recaptcha_response_field']
+            );
+
+            if (!$resp->is_valid) {
+                // What happens when the CAPTCHA was entered incorrectly
+                $this->output->command('display_message', "The reCAPTCHA wasn't entered correctly. Please reload and try it again.", 'error');
+                return;
+            }
+
+        }
+
+        // Check again for user availability before adding user
+        // this also logs into the API
+        // TODO perform security check on value of $data['uid'] and $data['domain']
+        if(!$this->action_check_user($data)) {
+            $this->output->command('form_value_error', 'uid');
+            return;
+        }
+
+        $this->api->get('system.select_domain', array('domain', $data['domain']));
+
+        // Remove domain from $data before adding user
+        unset($data['domain']);
+
+        $data['cn'] = $this->api->post('form_value.generate', $data);
+
+        // Add user
+        $result = $this->api->post('user.add', null, $data);
+
+        if (array_key_exists('error_code', $result)) {
+            $this->output->command('display_message', 'internalerror', 'error');
+            return;
+        } else {
+            $this->output->set_object('taskcontent', 'signup.usercreated');
+        }
+    }
+
+    private function user_form($data = array()) {
+        $attribs['id'] = 'signup-form';
+
+        $fields_map = array(
+            'type_id'                   => 'other',
+            'givenname'                 => 'other',
+            'sn'                        => 'other',
+            'cn'                        => 'other',
+            'mailalternateaddress'      => 'other',
+            'uid'                       => 'other',
+            'domain'                    => 'other',
+            'userpassword'              => 'other',
+            'userpassword2'             => 'other',
+            'mail'                      => 'other',
+            'alias'                     => 'other',
+        );
+
+        // Prepare fields
+        list($fields, $types, $type) = $this->form_prepare('user', $data, array('userpassword2'), 'hosted');
+        
+        // Show only required fields
+        foreach ($fields as $field_name => $field_attrs) {
+            if(!array_key_exists('required', $field_attrs) or $field_attrs['required'] != 'true') {
+                unset($fields[$field_name]);
+            }
+        }
+
+        // Add user type id selector
+        $accttypes = array();
+        foreach ($types as $idx => $elem) {
+            if($elem['used_for'] == 'hosted') {
+                $accttypes[$idx] = array('value' => $idx, 'content' => $elem['name']);
+            }
+        }
+
+        $fields['type_id'] = array(
+            'section'  => 'personal',
+            'type'     => kolab_form::INPUT_SELECT,
+            'options'  => $accttypes,
+            'onchange' => "kadm.change_user_type()",
+        );
+        
+        // Add object type field
+        $fields['object_type'] = array(
+            'type'     => kolab_form::INPUT_HIDDEN,
+            'value'    => 'user',
+        );
+ 
+        // Add available domains
+        $fields['domain'] = array(
+            'type'     => kolab_form::INPUT_SELECT,
+            'options'  => $this->get_domains(),
+            'onchange' => 'kadm.check_user_availability()',
+        );
+
+        // Check for user availability
+        $fields['uid']['onchange'] = 'kadm.check_user_availability()';
+
+        // Hide cn field
+        if (isset($fields['cn'])) {
+            // TODO use type info from user types table
+            $fields['cn']['type'] = kolab_form::INPUT_HIDDEN;
+
+            // TODO auto generate value again with indirect API call
+            $fields['cn']['value'] = 'temporary fake cn';
+            $fields['sn']['onchange'] = '';
+            $fields['givenname']['onchange'] = '';
+        }
+
+        // Add password confirmation
+        if (isset($fields['userpassword'])) {
+            $fields['userpassword2'] = $fields['userpassword'];
+            $fields['userpassword2']['onchange'] = 'password_match()';
+        }
+        
+        // Change field labels for hosted case
+        $fields['uid']['label'] = 'signup.username';
+        $fields['mail']['label'] = 'signup.futuremail';
+        if(isset($fields['mailalternateaddress'])) $fields['mailalternateaddress']['label'] = 'signup.mailalternateaddress';
+        $fields['domain']['label'] = 'signup.domain';
+
+        // Create form object and populate with fields
+        $form = $this->form_create('user', $attribs, array('other'), $fields, $fields_map, $data, true);
+
+        $form->set_title($this->translate('signup.formtitle'));
+
+        $this->output->add_translation('user.password.mismatch', 'user.add.success', 'signup.wronguid');
+
+        return $form->output();
+    }
+
+    protected function get_domains() {
+        // Get a list of domains ($domains again is a kolab_client_api_result instance)
+        $domains_list = $this->api->get('domains.list')->get('list');
+
+        if (empty($domains_list)) {
+            return array();
+        }
+
+        // The domain name attribute (the name of the LDAP attribute that holds the actual domain name space)
+        // is configurable as well. Provide a fallback.
+        $domain_name_attribute = $this->config->get('ldap','domain_name_attribute');
+        if (empty($domain_name_attribute)) {
+            $domain_name_attribute = 'associateddomain';
+        }
+
+        // Placeholder for the domain names in this deployment
+        $domain_names = array();
+
+        foreach ($domains_list as $domain_dn => $domain_attrs) {
+            // If $domain_attrs[$domain_name_attribute] is an array, the primary domain name space
+            // is the first value in the array.
+            if (is_array($domain_attrs[$domain_name_attribute])) {
+                $_domain_names = $domain_attrs[$domain_name_attribute];
+                $domain_name = array_shift($domain_attrs[$domain_name_attribute]);
+            } else {
+                $_domain_names = (array)($domain_attrs[$domain_name_attribute]);
+                $domain_name = $domain_attrs[$domain_name_attribute];
+            }
+
+            $parent_domain_only = $this->config->get($domain_name, 'hosted_parent_domain_only');
+
+            if (!empty($parent_domain_only) && in_array(strtolower($parent_domain_only), array('1', 'yes', 'true'))) {
+                $domain_names = array_merge($domain_names, array($domain_name));
+            } else {
+                $domain_names = array_merge($domain_names, $_domain_names);
+            }
+        }
+
+        // prepare array with proper key ids for form building
+        foreach ($domain_names as $domain) {
+            $domain_form_names[$domain] = $domain;
+        }
+
+        return $domain_form_names;
+    }
+
+    /**
+     * Overrides config_get() from kolab_client_task
+     * Returns configuration option value for hosting.
+     *
+     * @param string $name      Option name
+     * @param mixed  $fallback  Default value
+     * @param int    $type      Value type (one of Conf class constants)
+     *
+     * @return mixed Option value
+     */
+    public function config_get($name, $fallback = null, $type = null)
+    {
+        $value = $this->config->get('kolab_hosting', $name, $type);
+        if($value === null) {
+            $value = parent::config_get($name, $fallback, $type);
+        }
+        return $value !== null ? $value : $fallback;
+    }
+}
diff --git a/lib/functions.php b/lib/functions.php
index 8c74cf7..9761358 100644
--- a/lib/functions.php
+++ b/lib/functions.php
@@ -47,7 +47,6 @@ $include_path = INSTALL_PATH . PATH_SEPARATOR;
 $include_path .= INSTALL_PATH . '/client' . PATH_SEPARATOR;
 $include_path .= INSTALL_PATH . '/api' . PATH_SEPARATOR;
 $include_path .= INSTALL_PATH . '/ext' . PATH_SEPARATOR;
-$include_path .= INSTALL_PATH . '/hosted' . PATH_SEPARATOR;
 $include_path .= ini_get('include_path');
 
 if (set_include_path($include_path) === false) {
diff --git a/lib/hosted/kolab_client_task_signup.php b/lib/hosted/kolab_client_task_signup.php
deleted file mode 100644
index 6ebcdd9..0000000
--- a/lib/hosted/kolab_client_task_signup.php
+++ /dev/null
@@ -1,327 +0,0 @@
-<?php
-/*
- +--------------------------------------------------------------------------+
- | This file is part of the Kolab Web Admin Panel                           |
- |                                                                          |
- | Copyright (C) 2011-2012, Kolab Systems AG                                |
- |                                                                          |
- | This program 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.                                      |
- |                                                                          |
- | 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 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/>      |
- +--------------------------------------------------------------------------+
- | Author: Aleksander Machniak <machniak at kolabsys.com>                      |
- | Author: Torsten Grote <grote at kolabsys.com>                               |
- +--------------------------------------------------------------------------+
-*/
-
-require_once('hosted/recaptchalib.php');
-
-class kolab_client_task_signup extends kolab_client_task
-{
-    protected $ajax_only = true;
-
-    /**
-     * Overwrite Main execution.
-     */
-    public function run()
-    {
-        // don't set any cookies
-        ini_set('session.use_cookies', '0');
-
-        // Initialize locales
-        $this->locale_init();
-
-        // Assign self to template variable
-        $this->output->assign('engine', $this);
-
-        // Run security checks
-        // TODO figure out to reenable this
-//        $this->input_checks();
-
-        $action = $this->get_input('action', 'GET');
-
-        if ($action) {
-            $method = 'action_' . $action;
-            if (method_exists($this, $method)) {
-                $this->$method();
-            }
-        }
-        else if (method_exists($this, 'action_default')) {
-            $this->action_default();
-        }
-    }
-
-    private function login($domain=NULL)
-    {
-        if(is_null($domain)) {
-            $this->domain = $this->config_get('primary_domain');
-        }
-
-        // Login ($result is a kolab_client_api_result instance)
-        $result = $this->api->login($this->config_get('bind_dn'), $this->config_get('bind_pw'), $this->domain);
-
-        // Set the session token we got in the API client instance, so subsequent
-        // API calls are made in the same session.
-        $this->token = $result->get('session_token');
-        $this->api->set_session_token($this->token);
-    }
-
-    public function action_default()
-    {
-        $this->login();
-
-        $data = $this->get_input('data', 'POST');
-        $form = $this->user_form($data);
-
-        // add captcha
-        $publickey = $this->config_get('recaptcha_public_key');
-
-        if (!empty($publickey)) {
-            // TODO find a less dirty way to add captcha into form
-            $form = preg_replace('/<\/tbody>/', '<tr><td class="label">'.$this->translate('signup.captcha').'</td><td class="value"><div id="recaptcha_div"></div></td></tr></tbody>', $form);
-
-            // load captcha
-            $form .= '
-                <script type="text/javascript">
-                    Recaptcha.create("'.$publickey.'", "recaptcha_div", {theme: "red"});
-                </script>';
-        }
-
-        $this->output->assign('form', $form);
-        $this->output->set_object('taskcontent', $form);
-    }
-
-    // check if user already exists
-    public function action_check_user($data = array()) {
-        if(count($data) == 0) $data = $this->get_input('data', 'POST');
-
-        $this->login($data['domain']);
-
-        // Assemble mail attribute
-        $mail = $data['uid'].'@'.$data['domain'];
-
-        $post = array('search' => array('mail' => array('value' => $mail) ) );
-        $result = $this->api->post('users.list', null, $post);
-
-        if($result->get('count') > 0) {
-            $this->output->command('update_user_info("signup.userexists", "uid")');
-            return false;
-        }
-
-        $this->output->command('update_user_info("", "uid")');
-        return true;
-    }
-
-    public function action_add_user() {
-        $data = $this->get_input('data', 'POST');
-
-        $private_key = $this->config_get('recaptcha_private_key');
-
-        if (!empty($private_key)) {
-            // Check for valid CAPTCHA
-            $resp = recaptcha_check_answer(
-                        $private_key,
-                        $_SERVER['REMOTE_ADDR'],
-                        $data['recaptcha_challenge_field'],
-                        $data['recaptcha_response_field']
-            );
-
-            if (!$resp->is_valid) {
-                // What happens when the CAPTCHA was entered incorrectly
-                $this->output->command('display_message', "The reCAPTCHA wasn't entered correctly. Please reload and try it again.", 'error');
-                return;
-            }
-
-        }
-
-        // Check again for user availability before adding user
-        // this also logs into the API
-        // TODO perform security check on value of $data['uid'] and $data['domain']
-        if(!$this->action_check_user($data)) {
-            $this->output->command('form_value_error', 'uid');
-            return;
-        }
-
-        $this->api->get('system.select_domain', array('domain', $data['domain']));
-
-        // Remove domain from $data before adding user
-        unset($data['domain']);
-
-        $data['cn'] = $this->api->post('form_value.generate', $data);
-
-        // Add user
-        $result = $this->api->post('user.add', null, $data);
-
-        if (array_key_exists('error_code', $result)) {
-            $this->output->command('display_message', 'internalerror', 'error');
-            return;
-        } else {
-            $this->output->set_object('taskcontent', 'signup.usercreated');
-        }
-    }
-
-    private function user_form($data = array()) {
-        $attribs['id'] = 'signup-form';
-
-        $fields_map = array(
-            'type_id'                   => 'other',
-            'givenname'                 => 'other',
-            'sn'                        => 'other',
-            'cn'                        => 'other',
-            'mailalternateaddress'      => 'other',
-            'uid'                       => 'other',
-            'domain'                    => 'other',
-            'userpassword'              => 'other',
-            'userpassword2'             => 'other',
-            'mail'                      => 'other',
-            'alias'                     => 'other',
-        );
-
-        // Prepare fields
-        list($fields, $types, $type) = $this->form_prepare('user', $data, array('userpassword2'), 'hosted');
-        
-        // Show only required fields
-        foreach ($fields as $field_name => $field_attrs) {
-            if(!array_key_exists('required', $field_attrs) or $field_attrs['required'] != 'true') {
-                unset($fields[$field_name]);
-            }
-        }
-
-        // Add user type id selector
-        $accttypes = array();
-        foreach ($types as $idx => $elem) {
-            if($elem['used_for'] == 'hosted') {
-                $accttypes[$idx] = array('value' => $idx, 'content' => $elem['name']);
-            }
-        }
-
-        $fields['type_id'] = array(
-            'section'  => 'personal',
-            'type'     => kolab_form::INPUT_SELECT,
-            'options'  => $accttypes,
-            'onchange' => "kadm.change_user_type()",
-        );
-        
-        // Add object type field
-        $fields['object_type'] = array(
-            'type'     => kolab_form::INPUT_HIDDEN,
-            'value'    => 'user',
-        );
- 
-        // Add available domains
-        $fields['domain'] = array(
-            'type'     => kolab_form::INPUT_SELECT,
-            'options'  => $this->get_domains(),
-            'onchange' => 'kadm.check_user_availability()',
-        );
-
-        // Check for user availability
-        $fields['uid']['onchange'] = 'kadm.check_user_availability()';
-
-        // Hide cn field
-        if (isset($fields['cn'])) {
-            // TODO use type info from user types table
-            $fields['cn']['type'] = kolab_form::INPUT_HIDDEN;
-
-            // TODO auto generate value again with indirect API call
-            $fields['cn']['value'] = 'temporary fake cn';
-            $fields['sn']['onchange'] = '';
-            $fields['givenname']['onchange'] = '';
-        }
-
-        // Add password confirmation
-        if (isset($fields['userpassword'])) {
-            $fields['userpassword2'] = $fields['userpassword'];
-            $fields['userpassword2']['onchange'] = 'password_match()';
-        }
-        
-        // Change field labels for hosted case
-        $fields['uid']['label'] = 'signup.username';
-        $fields['mail']['label'] = 'signup.futuremail';
-        if(isset($fields['mailalternateaddress'])) $fields['mailalternateaddress']['label'] = 'signup.mailalternateaddress';
-        $fields['domain']['label'] = 'signup.domain';
-
-        // Create form object and populate with fields
-        $form = $this->form_create('user', $attribs, array('other'), $fields, $fields_map, $data, true);
-
-        $form->set_title($this->translate('signup.formtitle'));
-
-        $this->output->add_translation('user.password.mismatch', 'user.add.success', 'signup.wronguid');
-
-        return $form->output();
-    }
-
-    protected function get_domains() {
-        // Get a list of domains ($domains again is a kolab_client_api_result instance)
-        $domains_list = $this->api->get('domains.list')->get('list');
-
-        if (empty($domains_list)) {
-            return array();
-        }
-
-        // The domain name attribute (the name of the LDAP attribute that holds the actual domain name space)
-        // is configurable as well. Provide a fallback.
-        $domain_name_attribute = $this->config->get('ldap','domain_name_attribute');
-        if (empty($domain_name_attribute)) {
-            $domain_name_attribute = 'associateddomain';
-        }
-
-        // Placeholder for the domain names in this deployment
-        $domain_names = array();
-
-        foreach ($domains_list as $domain_dn => $domain_attrs) {
-            // If $domain_attrs[$domain_name_attribute] is an array, the primary domain name space
-            // is the first value in the array.
-            if (is_array($domain_attrs[$domain_name_attribute])) {
-                $_domain_names = $domain_attrs[$domain_name_attribute];
-                $domain_name = array_shift($domain_attrs[$domain_name_attribute]);
-            } else {
-                $_domain_names = (array)($domain_attrs[$domain_name_attribute]);
-                $domain_name = $domain_attrs[$domain_name_attribute];
-            }
-
-            $parent_domain_only = $this->config->get($domain_name, 'hosted_parent_domain_only');
-
-            if (!empty($parent_domain_only) && in_array(strtolower($parent_domain_only), array('1', 'yes', 'true'))) {
-                $domain_names = array_merge($domain_names, array($domain_name));
-            } else {
-                $domain_names = array_merge($domain_names, $_domain_names);
-            }
-        }
-
-        // prepare array with proper key ids for form building
-        foreach ($domain_names as $domain) {
-            $domain_form_names[$domain] = $domain;
-        }
-
-        return $domain_form_names;
-    }
-
-    /**
-     * Overrides config_get() from kolab_client_task
-     * Returns configuration option value for hosting.
-     *
-     * @param string $name      Option name
-     * @param mixed  $fallback  Default value
-     * @param int    $type      Value type (one of Conf class constants)
-     *
-     * @return mixed Option value
-     */
-    public function config_get($name, $fallback = null, $type = null)
-    {
-        $value = $this->config->get('kolab_hosting', $name, $type);
-        if($value === null) {
-            $value = parent::config_get($name, $fallback, $type);
-        }
-        return $value !== null ? $value : $fallback;
-    }
-}
diff --git a/lib/hosted/recaptchalib.php b/lib/hosted/recaptchalib.php
deleted file mode 100644
index 32c4f4d..0000000
--- a/lib/hosted/recaptchalib.php
+++ /dev/null
@@ -1,277 +0,0 @@
-<?php
-/*
- * This is a PHP library that handles calling reCAPTCHA.
- *    - Documentation and latest version
- *          http://recaptcha.net/plugins/php/
- *    - Get a reCAPTCHA API Key
- *          https://www.google.com/recaptcha/admin/create
- *    - Discussion group
- *          http://groups.google.com/group/recaptcha
- *
- * Copyright (c) 2007 reCAPTCHA -- http://recaptcha.net
- * AUTHORS:
- *   Mike Crawford
- *   Ben Maurer
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-/**
- * The reCAPTCHA server URL's
- */
-define("RECAPTCHA_API_SERVER", "http://www.google.com/recaptcha/api");
-define("RECAPTCHA_API_SECURE_SERVER", "https://www.google.com/recaptcha/api");
-define("RECAPTCHA_VERIFY_SERVER", "www.google.com");
-
-/**
- * Encodes the given data into a query string format
- * @param $data - array of string elements to be encoded
- * @return string - encoded request
- */
-function _recaptcha_qsencode ($data) {
-        $req = "";
-        foreach ( $data as $key => $value )
-                $req .= $key . '=' . urlencode( stripslashes($value) ) . '&';
-
-        // Cut the last '&'
-        $req=substr($req,0,strlen($req)-1);
-        return $req;
-}
-
-
-
-/**
- * Submits an HTTP POST to a reCAPTCHA server
- * @param string $host
- * @param string $path
- * @param array $data
- * @param int port
- * @return array response
- */
-function _recaptcha_http_post($host, $path, $data, $port = 80) {
-
-        $req = _recaptcha_qsencode ($data);
-
-        $http_request  = "POST $path HTTP/1.0\r\n";
-        $http_request .= "Host: $host\r\n";
-        $http_request .= "Content-Type: application/x-www-form-urlencoded;\r\n";
-        $http_request .= "Content-Length: " . strlen($req) . "\r\n";
-        $http_request .= "User-Agent: reCAPTCHA/PHP\r\n";
-        $http_request .= "\r\n";
-        $http_request .= $req;
-
-        $response = '';
-        if( false == ( $fs = @fsockopen($host, $port, $errno, $errstr, 10) ) ) {
-                die ('Could not open socket');
-        }
-
-        fwrite($fs, $http_request);
-
-        while ( !feof($fs) )
-                $response .= fgets($fs, 1160); // One TCP-IP packet
-        fclose($fs);
-        $response = explode("\r\n\r\n", $response, 2);
-
-        return $response;
-}
-
-
-
-/**
- * Gets the challenge HTML (javascript and non-javascript version).
- * This is called from the browser, and the resulting reCAPTCHA HTML widget
- * is embedded within the HTML form it was called from.
- * @param string $pubkey A public key for reCAPTCHA
- * @param string $error The error given by reCAPTCHA (optional, default is null)
- * @param boolean $use_ssl Should the request be made over ssl? (optional, default is false)
-
- * @return string - The HTML to be embedded in the user's form.
- */
-function recaptcha_get_html ($pubkey, $error = null, $use_ssl = false)
-{
-	if ($pubkey == null || $pubkey == '') {
-		die ("To use reCAPTCHA you must get an API key from <a href='https://www.google.com/recaptcha/admin/create'>https://www.google.com/recaptcha/admin/create</a>");
-	}
-	
-	if ($use_ssl) {
-                $server = RECAPTCHA_API_SECURE_SERVER;
-        } else {
-                $server = RECAPTCHA_API_SERVER;
-        }
-
-        $errorpart = "";
-        if ($error) {
-           $errorpart = "&error=" . $error;
-        }
-        return '<script type="text/javascript" src="'. $server . '/challenge?k=' . $pubkey . $errorpart . '"></script>
-
-	<noscript>
-  		<iframe src="'. $server . '/noscript?k=' . $pubkey . $errorpart . '" height="300" width="500" frameborder="0"></iframe><br/>
-  		<textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
-  		<input type="hidden" name="recaptcha_response_field" value="manual_challenge"/>
-	</noscript>';
-}
-
-
-
-
-/**
- * A ReCaptchaResponse is returned from recaptcha_check_answer()
- */
-class ReCaptchaResponse {
-        var $is_valid;
-        var $error;
-}
-
-
-/**
-  * Calls an HTTP POST function to verify if the user's guess was correct
-  * @param string $privkey
-  * @param string $remoteip
-  * @param string $challenge
-  * @param string $response
-  * @param array $extra_params an array of extra variables to post to the server
-  * @return ReCaptchaResponse
-  */
-function recaptcha_check_answer ($privkey, $remoteip, $challenge, $response, $extra_params = array())
-{
-	if ($privkey == null || $privkey == '') {
-		die ("To use reCAPTCHA you must get an API key from <a href='https://www.google.com/recaptcha/admin/create'>https://www.google.com/recaptcha/admin/create</a>");
-	}
-
-	if ($remoteip == null || $remoteip == '') {
-		die ("For security reasons, you must pass the remote ip to reCAPTCHA");
-	}
-
-	
-	
-        //discard spam submissions
-        if ($challenge == null || strlen($challenge) == 0 || $response == null || strlen($response) == 0) {
-                $recaptcha_response = new ReCaptchaResponse();
-                $recaptcha_response->is_valid = false;
-                $recaptcha_response->error = 'incorrect-captcha-sol';
-                return $recaptcha_response;
-        }
-
-        $response = _recaptcha_http_post (RECAPTCHA_VERIFY_SERVER, "/recaptcha/api/verify",
-                                          array (
-                                                 'privatekey' => $privkey,
-                                                 'remoteip' => $remoteip,
-                                                 'challenge' => $challenge,
-                                                 'response' => $response
-                                                 ) + $extra_params
-                                          );
-
-        $answers = explode ("\n", $response [1]);
-        $recaptcha_response = new ReCaptchaResponse();
-
-        if (trim ($answers [0]) == 'true') {
-                $recaptcha_response->is_valid = true;
-        }
-        else {
-                $recaptcha_response->is_valid = false;
-                $recaptcha_response->error = $answers [1];
-        }
-        return $recaptcha_response;
-
-}
-
-/**
- * gets a URL where the user can sign up for reCAPTCHA. If your application
- * has a configuration page where you enter a key, you should provide a link
- * using this function.
- * @param string $domain The domain where the page is hosted
- * @param string $appname The name of your application
- */
-function recaptcha_get_signup_url ($domain = null, $appname = null) {
-	return "https://www.google.com/recaptcha/admin/create?" .  _recaptcha_qsencode (array ('domains' => $domain, 'app' => $appname));
-}
-
-function _recaptcha_aes_pad($val) {
-	$block_size = 16;
-	$numpad = $block_size - (strlen ($val) % $block_size);
-	return str_pad($val, strlen ($val) + $numpad, chr($numpad));
-}
-
-/* Mailhide related code */
-
-function _recaptcha_aes_encrypt($val,$ky) {
-	if (! function_exists ("mcrypt_encrypt")) {
-		die ("To use reCAPTCHA Mailhide, you need to have the mcrypt php module installed.");
-	}
-	$mode=MCRYPT_MODE_CBC;   
-	$enc=MCRYPT_RIJNDAEL_128;
-	$val=_recaptcha_aes_pad($val);
-	return mcrypt_encrypt($enc, $ky, $val, $mode, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
-}
-
-
-function _recaptcha_mailhide_urlbase64 ($x) {
-	return strtr(base64_encode ($x), '+/', '-_');
-}
-
-/* gets the reCAPTCHA Mailhide url for a given email, public key and private key */
-function recaptcha_mailhide_url($pubkey, $privkey, $email) {
-	if ($pubkey == '' || $pubkey == null || $privkey == "" || $privkey == null) {
-		die ("To use reCAPTCHA Mailhide, you have to sign up for a public and private key, " .
-		     "you can do so at <a href='http://www.google.com/recaptcha/mailhide/apikey'>http://www.google.com/recaptcha/mailhide/apikey</a>");
-	}
-	
-
-	$ky = pack('H*', $privkey);
-	$cryptmail = _recaptcha_aes_encrypt ($email, $ky);
-	
-	return "http://www.google.com/recaptcha/mailhide/d?k=" . $pubkey . "&c=" . _recaptcha_mailhide_urlbase64 ($cryptmail);
-}
-
-/**
- * gets the parts of the email to expose to the user.
- * eg, given johndoe at example,com return ["john", "example.com"].
- * the email is then displayed as john... at example.com
- */
-function _recaptcha_mailhide_email_parts ($email) {
-	$arr = preg_split("/@/", $email );
-
-	if (strlen ($arr[0]) <= 4) {
-		$arr[0] = substr ($arr[0], 0, 1);
-	} else if (strlen ($arr[0]) <= 6) {
-		$arr[0] = substr ($arr[0], 0, 3);
-	} else {
-		$arr[0] = substr ($arr[0], 0, 4);
-	}
-	return $arr;
-}
-
-/**
- * Gets html to display an email address given a public an private key.
- * to get a key, go to:
- *
- * http://www.google.com/recaptcha/mailhide/apikey
- */
-function recaptcha_mailhide_html($pubkey, $privkey, $email) {
-	$emailparts = _recaptcha_mailhide_email_parts ($email);
-	$url = recaptcha_mailhide_url ($pubkey, $privkey, $email);
-	
-	return htmlentities($emailparts[0]) . "<a href='" . htmlentities ($url) .
-		"' onclick=\"window.open('" . htmlentities ($url) . "', '', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=300'); return false;\" title=\"Reveal this e-mail address\">...</a>@" . htmlentities ($emailparts [1]);
-
-}
-
-
-?>
diff --git a/lib/recaptchalib.php b/lib/recaptchalib.php
new file mode 100644
index 0000000..32c4f4d
--- /dev/null
+++ b/lib/recaptchalib.php
@@ -0,0 +1,277 @@
+<?php
+/*
+ * This is a PHP library that handles calling reCAPTCHA.
+ *    - Documentation and latest version
+ *          http://recaptcha.net/plugins/php/
+ *    - Get a reCAPTCHA API Key
+ *          https://www.google.com/recaptcha/admin/create
+ *    - Discussion group
+ *          http://groups.google.com/group/recaptcha
+ *
+ * Copyright (c) 2007 reCAPTCHA -- http://recaptcha.net
+ * AUTHORS:
+ *   Mike Crawford
+ *   Ben Maurer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/**
+ * The reCAPTCHA server URL's
+ */
+define("RECAPTCHA_API_SERVER", "http://www.google.com/recaptcha/api");
+define("RECAPTCHA_API_SECURE_SERVER", "https://www.google.com/recaptcha/api");
+define("RECAPTCHA_VERIFY_SERVER", "www.google.com");
+
+/**
+ * Encodes the given data into a query string format
+ * @param $data - array of string elements to be encoded
+ * @return string - encoded request
+ */
+function _recaptcha_qsencode ($data) {
+        $req = "";
+        foreach ( $data as $key => $value )
+                $req .= $key . '=' . urlencode( stripslashes($value) ) . '&';
+
+        // Cut the last '&'
+        $req=substr($req,0,strlen($req)-1);
+        return $req;
+}
+
+
+
+/**
+ * Submits an HTTP POST to a reCAPTCHA server
+ * @param string $host
+ * @param string $path
+ * @param array $data
+ * @param int port
+ * @return array response
+ */
+function _recaptcha_http_post($host, $path, $data, $port = 80) {
+
+        $req = _recaptcha_qsencode ($data);
+
+        $http_request  = "POST $path HTTP/1.0\r\n";
+        $http_request .= "Host: $host\r\n";
+        $http_request .= "Content-Type: application/x-www-form-urlencoded;\r\n";
+        $http_request .= "Content-Length: " . strlen($req) . "\r\n";
+        $http_request .= "User-Agent: reCAPTCHA/PHP\r\n";
+        $http_request .= "\r\n";
+        $http_request .= $req;
+
+        $response = '';
+        if( false == ( $fs = @fsockopen($host, $port, $errno, $errstr, 10) ) ) {
+                die ('Could not open socket');
+        }
+
+        fwrite($fs, $http_request);
+
+        while ( !feof($fs) )
+                $response .= fgets($fs, 1160); // One TCP-IP packet
+        fclose($fs);
+        $response = explode("\r\n\r\n", $response, 2);
+
+        return $response;
+}
+
+
+
+/**
+ * Gets the challenge HTML (javascript and non-javascript version).
+ * This is called from the browser, and the resulting reCAPTCHA HTML widget
+ * is embedded within the HTML form it was called from.
+ * @param string $pubkey A public key for reCAPTCHA
+ * @param string $error The error given by reCAPTCHA (optional, default is null)
+ * @param boolean $use_ssl Should the request be made over ssl? (optional, default is false)
+
+ * @return string - The HTML to be embedded in the user's form.
+ */
+function recaptcha_get_html ($pubkey, $error = null, $use_ssl = false)
+{
+	if ($pubkey == null || $pubkey == '') {
+		die ("To use reCAPTCHA you must get an API key from <a href='https://www.google.com/recaptcha/admin/create'>https://www.google.com/recaptcha/admin/create</a>");
+	}
+	
+	if ($use_ssl) {
+                $server = RECAPTCHA_API_SECURE_SERVER;
+        } else {
+                $server = RECAPTCHA_API_SERVER;
+        }
+
+        $errorpart = "";
+        if ($error) {
+           $errorpart = "&error=" . $error;
+        }
+        return '<script type="text/javascript" src="'. $server . '/challenge?k=' . $pubkey . $errorpart . '"></script>
+
+	<noscript>
+  		<iframe src="'. $server . '/noscript?k=' . $pubkey . $errorpart . '" height="300" width="500" frameborder="0"></iframe><br/>
+  		<textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea>
+  		<input type="hidden" name="recaptcha_response_field" value="manual_challenge"/>
+	</noscript>';
+}
+
+
+
+
+/**
+ * A ReCaptchaResponse is returned from recaptcha_check_answer()
+ */
+class ReCaptchaResponse {
+        var $is_valid;
+        var $error;
+}
+
+
+/**
+  * Calls an HTTP POST function to verify if the user's guess was correct
+  * @param string $privkey
+  * @param string $remoteip
+  * @param string $challenge
+  * @param string $response
+  * @param array $extra_params an array of extra variables to post to the server
+  * @return ReCaptchaResponse
+  */
+function recaptcha_check_answer ($privkey, $remoteip, $challenge, $response, $extra_params = array())
+{
+	if ($privkey == null || $privkey == '') {
+		die ("To use reCAPTCHA you must get an API key from <a href='https://www.google.com/recaptcha/admin/create'>https://www.google.com/recaptcha/admin/create</a>");
+	}
+
+	if ($remoteip == null || $remoteip == '') {
+		die ("For security reasons, you must pass the remote ip to reCAPTCHA");
+	}
+
+	
+	
+        //discard spam submissions
+        if ($challenge == null || strlen($challenge) == 0 || $response == null || strlen($response) == 0) {
+                $recaptcha_response = new ReCaptchaResponse();
+                $recaptcha_response->is_valid = false;
+                $recaptcha_response->error = 'incorrect-captcha-sol';
+                return $recaptcha_response;
+        }
+
+        $response = _recaptcha_http_post (RECAPTCHA_VERIFY_SERVER, "/recaptcha/api/verify",
+                                          array (
+                                                 'privatekey' => $privkey,
+                                                 'remoteip' => $remoteip,
+                                                 'challenge' => $challenge,
+                                                 'response' => $response
+                                                 ) + $extra_params
+                                          );
+
+        $answers = explode ("\n", $response [1]);
+        $recaptcha_response = new ReCaptchaResponse();
+
+        if (trim ($answers [0]) == 'true') {
+                $recaptcha_response->is_valid = true;
+        }
+        else {
+                $recaptcha_response->is_valid = false;
+                $recaptcha_response->error = $answers [1];
+        }
+        return $recaptcha_response;
+
+}
+
+/**
+ * gets a URL where the user can sign up for reCAPTCHA. If your application
+ * has a configuration page where you enter a key, you should provide a link
+ * using this function.
+ * @param string $domain The domain where the page is hosted
+ * @param string $appname The name of your application
+ */
+function recaptcha_get_signup_url ($domain = null, $appname = null) {
+	return "https://www.google.com/recaptcha/admin/create?" .  _recaptcha_qsencode (array ('domains' => $domain, 'app' => $appname));
+}
+
+function _recaptcha_aes_pad($val) {
+	$block_size = 16;
+	$numpad = $block_size - (strlen ($val) % $block_size);
+	return str_pad($val, strlen ($val) + $numpad, chr($numpad));
+}
+
+/* Mailhide related code */
+
+function _recaptcha_aes_encrypt($val,$ky) {
+	if (! function_exists ("mcrypt_encrypt")) {
+		die ("To use reCAPTCHA Mailhide, you need to have the mcrypt php module installed.");
+	}
+	$mode=MCRYPT_MODE_CBC;   
+	$enc=MCRYPT_RIJNDAEL_128;
+	$val=_recaptcha_aes_pad($val);
+	return mcrypt_encrypt($enc, $ky, $val, $mode, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0");
+}
+
+
+function _recaptcha_mailhide_urlbase64 ($x) {
+	return strtr(base64_encode ($x), '+/', '-_');
+}
+
+/* gets the reCAPTCHA Mailhide url for a given email, public key and private key */
+function recaptcha_mailhide_url($pubkey, $privkey, $email) {
+	if ($pubkey == '' || $pubkey == null || $privkey == "" || $privkey == null) {
+		die ("To use reCAPTCHA Mailhide, you have to sign up for a public and private key, " .
+		     "you can do so at <a href='http://www.google.com/recaptcha/mailhide/apikey'>http://www.google.com/recaptcha/mailhide/apikey</a>");
+	}
+	
+
+	$ky = pack('H*', $privkey);
+	$cryptmail = _recaptcha_aes_encrypt ($email, $ky);
+	
+	return "http://www.google.com/recaptcha/mailhide/d?k=" . $pubkey . "&c=" . _recaptcha_mailhide_urlbase64 ($cryptmail);
+}
+
+/**
+ * gets the parts of the email to expose to the user.
+ * eg, given johndoe at example,com return ["john", "example.com"].
+ * the email is then displayed as john... at example.com
+ */
+function _recaptcha_mailhide_email_parts ($email) {
+	$arr = preg_split("/@/", $email );
+
+	if (strlen ($arr[0]) <= 4) {
+		$arr[0] = substr ($arr[0], 0, 1);
+	} else if (strlen ($arr[0]) <= 6) {
+		$arr[0] = substr ($arr[0], 0, 3);
+	} else {
+		$arr[0] = substr ($arr[0], 0, 4);
+	}
+	return $arr;
+}
+
+/**
+ * Gets html to display an email address given a public an private key.
+ * to get a key, go to:
+ *
+ * http://www.google.com/recaptcha/mailhide/apikey
+ */
+function recaptcha_mailhide_html($pubkey, $privkey, $email) {
+	$emailparts = _recaptcha_mailhide_email_parts ($email);
+	$url = recaptcha_mailhide_url ($pubkey, $privkey, $email);
+	
+	return htmlentities($emailparts[0]) . "<a href='" . htmlentities ($url) .
+		"' onclick=\"window.open('" . htmlentities ($url) . "', '', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=500,height=300'); return false;\" title=\"Reveal this e-mail address\">...</a>@" . htmlentities ($emailparts [1]);
+
+}
+
+
+?>
diff --git a/public_html/index.php b/public_html/index.php
index 3e78361..1f9f1ed 100644
--- a/public_html/index.php
+++ b/public_html/index.php
@@ -29,7 +29,7 @@ require_once '../lib/functions.php';
 // starting task
 $task = kolab_utils::get_input('task', kolab_utils::REQUEST_GET);
 
-if (!$task) {
+if (!$task || $task == 'signup') {
     $task = 'main';
 }
 
diff --git a/public_html/js/kolab_hosted.js b/public_html/js/kolab_hosted.js
new file mode 100644
index 0000000..9f717ae
--- /dev/null
+++ b/public_html/js/kolab_hosted.js
@@ -0,0 +1,120 @@
+/*
+ +--------------------------------------------------------------------------+
+ | This file is part of the Kolab Web Admin Panel                           |
+ |                                                                          |
+ | Copyright (C) 2011-2012, Kolab Systems AG                                |
+ |                                                                          |
+ | This program 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.                                      |
+ |                                                                          |
+ | 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 Affero General Public License for more details.                      |
+ |                                                                          |
+ | You should have received a copy of the GNU Affero General Public License |
+ | along with kadm program. If not, see <http://www.gnu.org/licenses/>      |
+ +--------------------------------------------------------------------------+
+ | Author: Torsten Grote <grote at kolabsys.com>                               |
+ +--------------------------------------------------------------------------+
+*/
+
+// overwrite user_save() function
+kadm.user_save = function(reload, section)
+{
+    var data = kadm.serialize_form('#'+this.env.form_id);
+
+    // check email address
+    if(typeof data.mailalternateaddress != 'undefined' && !isValidEmailAddress(data.mailalternateaddress)) {
+        kadm.display_message('signup.wrongmailalternateaddress', 'error');
+        kadm.form_value_error('mailalternateaddress');
+        return;
+    }
+
+    if (!kadm.check_required_fields(data)) {
+      kadm.display_message('form.required.empty', 'error');
+      return;
+    }
+
+    // check password
+    if (data.userpassword != data.userpassword2) {
+      kadm.display_message('user.password.mismatch', 'error');
+      kadm.form_value_error('userpassword2');
+      return;
+    }
+    delete data['userpassword2'];
+
+    kadm.http_post('signup.add_user', {data: data});
+};
+
+kadm.change_user_type = function()
+{
+    var data = kadm.serialize_form('#'+this.env.form_id);
+
+    kadm.http_post('signup.default', {data: data});
+};
+
+kadm.check_user_availability = function()
+{
+    // get form data and build new email address
+    var data = kadm.serialize_form('#signup-form');
+    var mail = data['uid'] + '@' + data['domain'];
+
+    if(isValidEmailAddress(mail)) {
+        // update future mail form field
+        $('input[name="mail"]').val(mail);
+
+        // check if user with that email address already exists
+        kadm.http_post('signup.check_user', {data: data});
+    } else {
+        kadm.update_user_info('signup.wronguid', 'uid');
+    }
+};
+
+kadm.update_user_info = function(msg, part)
+{
+    var span_id = 'availability';
+    if(!part.localeCompare('userpassword')) {
+        span_id = 'pass_match';
+    }
+
+    if (msg) {
+        msg = kadm.t(msg);
+    }
+
+    // display message next to form field
+    if($('span[id="'+span_id+'"]').length) {
+        // update existing span area
+        $('span[id="'+span_id+'"]').html(msg);
+    }
+    else {
+        // add span area and add message
+        $('input[name="'+part+'"]').after(' <span id="'+span_id+'" class="form_error">' + msg + '</span>');
+    }
+
+    // enable/disable button
+    if(msg == '') {
+        $('input[type="button"]').removeAttr("disabled");
+    } else {
+        $('input[type="button"]').attr("disabled", "disabled");
+    }
+};
+
+
+function password_match()
+{
+    if($('input[name="userpassword"]').val().localeCompare($('input[name="userpassword2"]').val())) {
+        kadm.update_user_info('user.password.mismatch', 'userpassword');
+    }
+    else {
+        kadm.update_user_info('', 'userpassword');
+    }
+}
+
+// TODO use form.validate api call for that
+function isValidEmailAddress(emailAddress) {
+    var pattern = new RegExp(/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i);
+    return pattern.test(emailAddress);
+};
diff --git a/public_html/skins/default/hosted.css b/public_html/skins/default/hosted.css
new file mode 100644
index 0000000..694d19d
--- /dev/null
+++ b/public_html/skins/default/hosted.css
@@ -0,0 +1,45 @@
+body {
+  background: #f0f0f0;
+  text-align: center;
+}
+
+#bodybox {
+  display: inline-block;
+  width: 900px;
+  text-align: left;
+}
+
+#logo {
+  width: 462px;
+  height: 100px;
+  position: relative;
+  margin: 10px;
+  cursor: default;
+  background: url(images/logo_kolab.png) 0 0 no-repeat;
+}
+
+#content {
+  padding: 15px;
+}
+
+#taskcontent {
+  display: inline-block;
+  margin-top: 10px;
+  text-align: center;
+}
+
+form#signup-form {
+  padding-top: 10px;
+}
+
+td.label {
+  vertical-align: top;
+}
+
+table.form td {
+    text-align: left;
+}
+
+#footer {
+  text-align: center;
+}
diff --git a/public_html/skins/default/images/logo_kolab.png b/public_html/skins/default/images/logo_kolab.png
new file mode 100644
index 0000000..0c06ff1
Binary files /dev/null and b/public_html/skins/default/images/logo_kolab.png differ
diff --git a/public_html/skins/default/templates/signup.html b/public_html/skins/default/templates/signup.html
new file mode 100644
index 0000000..66a649a
--- /dev/null
+++ b/public_html/skins/default/templates/signup.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="utf-8" />
+    <title>{$engine->translate('signup.headline')}</title>
+    <link rel="stylesheet" href="{$skin_path}style.css" />
+    <link rel="stylesheet" href="{$skin_path}hosted.css" />
+    <link rel="shortcut icon" type="image/png" href="{$skin_path}images/favicon.png" />
+    <script src="js/jquery.min.js"></script>
+    <script src="js/kolab_admin.js"></script>
+    <script type="text/javascript" src="https://www.google.com/recaptcha/api/js/recaptcha_ajax.js"></script>
+    <script src="js/kolab_hosted.js"></script>
+    <script src="{$skin_path}ui.js"></script>
+</head>
+<body>
+    <div id="bodybox">
+        <div id="logo"></div>
+        <div id="content">
+            <div id="task_content" class="signup">
+                <h1>{$engine->translate('signup.headline')}</h1>
+                <p>{$engine->translate('signup.intro1')}</p>
+                <p>{$engine->translate('signup.intro2')}</p>
+                <div id="taskcontent" class="signup">{$form}</div>
+            </div>
+        </div>
+        <div id="footer">
+            {include file="signup_footer.html"}
+        </div>
+    </div>
+{$script}
+</body>
+</html>
diff --git a/public_html/skins/default/templates/signup_footer.html b/public_html/skins/default/templates/signup_footer.html
new file mode 100644
index 0000000..24d972d
--- /dev/null
+++ b/public_html/skins/default/templates/signup_footer.html
@@ -0,0 +1 @@
+{$engine->translate('signup.footer')}
diff --git a/public_html/skins/default/ui.js b/public_html/skins/default/ui.js
index c0dc901..45bfd51 100644
--- a/public_html/skins/default/ui.js
+++ b/public_html/skins/default/ui.js
@@ -153,7 +153,7 @@ function ui_resize()
   var h = $('#content').height();
   // resize UI elements
   if (h - 22 > 380) {
-    $('#taskcontent').css({'min-height': h - 22});
+    $('#taskcontent:not(.signup)').css({'min-height': h - 22});
   }
 };
 
diff --git a/public_html/skins/kolabsys/hosted.css b/public_html/skins/kolabsys/hosted.css
new file mode 100644
index 0000000..427d57d
--- /dev/null
+++ b/public_html/skins/kolabsys/hosted.css
@@ -0,0 +1,26 @@
+body {
+  background: #F3F3F3;
+  text-align: center;
+}
+
+#taskcontent {
+  width: 680px;
+  min-height: 100px;
+  max-height: 460px;
+}
+
+form#signup-form {
+  padding-top: 10px;
+}
+
+td.value input {
+    width: 250px;
+}
+
+td.label {
+  vertical-align: top;
+}
+
+table.form td {
+    text-align: left;
+}
diff --git a/public_html/skins/kolabsys/style.css b/public_html/skins/kolabsys/style.css
new file mode 120000
index 0000000..2bc3133
--- /dev/null
+++ b/public_html/skins/kolabsys/style.css
@@ -0,0 +1 @@
+../default/style.css
\ No newline at end of file
diff --git a/public_html/skins/kolabsys/templates/signup.html b/public_html/skins/kolabsys/templates/signup.html
new file mode 100644
index 0000000..7c756ae
--- /dev/null
+++ b/public_html/skins/kolabsys/templates/signup.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="utf-8" />
+    <title>Sign Up For Hosted Kolab</title>
+    <link rel="stylesheet" href="{$skin_path}style.css" />
+    <link rel="stylesheet" href="{$skin_path}hosted.css" />
+    <link rel="shortcut icon" type="image/png" href="{$skin_path}images/favicon.png" />
+    <script src="js/jquery.min.js"></script>
+    <script src="js/kolab_admin.js"></script>
+    <script type="text/javascript" src="https://www.google.com/recaptcha/api/js/recaptcha_ajax.js"></script>
+    <script src="js/kolab_hosted.js"></script>
+    <script src="{$skin_path}ui.js"></script>
+</head>
+<body>
+    <div id="taskcontent" class="signup">{$form}</div>
+
+    {$script}
+</body>
+</html>
diff --git a/public_html/skins/kolabsys/ui.js b/public_html/skins/kolabsys/ui.js
new file mode 120000
index 0000000..b845f3f
--- /dev/null
+++ b/public_html/skins/kolabsys/ui.js
@@ -0,0 +1 @@
+../default/ui.js
\ No newline at end of file
diff --git a/public_html/skins/minimal/hosted.css b/public_html/skins/minimal/hosted.css
new file mode 120000
index 0000000..a66df34
--- /dev/null
+++ b/public_html/skins/minimal/hosted.css
@@ -0,0 +1 @@
+../default/hosted.css
\ No newline at end of file
diff --git a/public_html/skins/minimal/style.css b/public_html/skins/minimal/style.css
new file mode 120000
index 0000000..2bc3133
--- /dev/null
+++ b/public_html/skins/minimal/style.css
@@ -0,0 +1 @@
+../default/style.css
\ No newline at end of file
diff --git a/public_html/skins/minimal/templates/signup.html b/public_html/skins/minimal/templates/signup.html
new file mode 100644
index 0000000..ccf16b8
--- /dev/null
+++ b/public_html/skins/minimal/templates/signup.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="utf-8" />
+    <title>Sign Up For Hosted Kolab</title>
+    <link rel="stylesheet" href="{$skin_path}style.css" />
+    <link rel="stylesheet" href="{$skin_path}hosted.css" />
+    <link rel="shortcut icon" type="image/png" href="{$skin_path}images/favicon.png" />
+    <script src="js/jquery.min.js"></script>
+    <script src="js/kolab_admin.js"></script>
+    <script type="text/javascript" src="https://www.google.com/recaptcha/api/js/recaptcha_ajax.js"></script>
+    <script src="js/kolab_hosted.js"></script>
+    <script src="{$skin_path}ui.js"></script>
+</head>
+<body>
+    <div id="taskcontent" class="signup">{$form}</div>
+
+    <div id="footer">
+        {include file="signup_footer.html"}
+    </div>
+{$script}
+</body>
+</html>
diff --git a/public_html/skins/minimal/templates/signup_footer.html b/public_html/skins/minimal/templates/signup_footer.html
new file mode 100644
index 0000000..4b6bac5
--- /dev/null
+++ b/public_html/skins/minimal/templates/signup_footer.html
@@ -0,0 +1 @@
+This is a service offered by <a href="http://kolabsys.com">Kolab Systems</a>.
diff --git a/public_html/skins/minimal/ui.js b/public_html/skins/minimal/ui.js
new file mode 120000
index 0000000..b845f3f
--- /dev/null
+++ b/public_html/skins/minimal/ui.js
@@ -0,0 +1 @@
+../default/ui.js
\ No newline at end of file





More information about the commits mailing list