diff --git a/lam/lib/modules/ldapPublicKey.inc b/lam/lib/modules/ldapPublicKey.inc
index 3c124168..ca413c60 100644
--- a/lam/lib/modules/ldapPublicKey.inc
+++ b/lam/lib/modules/ldapPublicKey.inc
@@ -35,6 +35,9 @@ $Id$
*/
class ldapPublicKey extends baseModule {
+ /** session variable for existing keys in self service */
+ const SESS_KEY_LIST = 'ldapPublicKey_keyList';
+
/**
* Returns meta data that is interpreted by parent class
*
@@ -65,7 +68,11 @@ class ldapPublicKey extends baseModule {
'keyList' => array(
"Headline" => _("SSH public key"), 'attr' => 'sshPublicKey',
"Text" => _("Please a comma separated list of your public SSH keys.")
- )
+ ),
+ 'upload' => array(
+ "Headline" => _("File upload"), 'attr' => 'sshPublicKey',
+ "Text" => _("Upload a file with one or more keys. Each line contains one key.")
+ ),
);
// upload fields
$return['upload_columns'] = array(
@@ -88,6 +95,13 @@ class ldapPublicKey extends baseModule {
return $return;
}
+ /**
+ * This function fills the message array.
+ **/
+ function load_Messages() {
+ $this->messages['file'][0] = array('ERROR', _('No file selected.'));
+ }
+
/**
* Returns the HTML meta data for the main account page.
*
@@ -103,7 +117,7 @@ class ldapPublicKey extends baseModule {
$return->addElement(new htmlOutputText(_('SSH public key')));
$sshInput = new htmlInputField('sshPublicKey' . $i, $this->attributes['sshPublicKey'][$i]);
$sshInput->setFieldSize(50);
- $sshInput->setFieldMaxLength(4096);
+ $sshInput->setFieldMaxLength(16384);
$return->addElement($sshInput);
$return->addElement(new htmlButton('delKey' . $i, 'del.png', true));
$return->addElement(new htmlHelpLink('key'), true);
@@ -117,7 +131,17 @@ class ldapPublicKey extends baseModule {
$return->addElement($sshNewKey);
$return->addElement(new htmlButton('addKey', 'add.png', true));
$return->addElement(new htmlHelpLink('key'));
- $return->addElement(new htmlHiddenInput('key_number', $keyCount));
+ $return->addElement(new htmlHiddenInput('key_number', $keyCount), true);
+ // file upload
+ $return->addElement(new htmlSpacer(null, '20px'), true);
+ $return->addElement(new htmlOutputText(_('Upload file')));
+ $uploadGroup = new htmlGroup();
+ $uploadGroup->addElement(new htmlInputFileUpload('sshPublicKeyFile'));
+ $uploadGroup->addElement(new htmlSpacer('1px', null));
+ $uploadGroup->addElement(new htmlButton('sshPublicKeyFileSubmit', _('Upload')));
+ $return->addElement($uploadGroup);
+ $return->addElement(new htmlOutputText(''));
+ $return->addElement(new htmlHelpLink('upload'));
return $return;
}
@@ -128,6 +152,7 @@ class ldapPublicKey extends baseModule {
* @return array list of info/error messages
*/
function process_attributes() {
+ $messages = array();
$this->attributes['sshPublicKey'] = array();
// check old keys
if (isset($_POST['key_number'])) {
@@ -142,8 +167,27 @@ class ldapPublicKey extends baseModule {
if (isset($_POST['sshPublicKey']) && ($_POST['sshPublicKey'] != "")) {
$this->attributes['sshPublicKey'][] = $_POST['sshPublicKey'];
}
- $this->attributes['sshPublicKey'] = array_unique($this->attributes['sshPublicKey']);
- return array();
+ // file upload
+ if (isset($_POST['sshPublicKeyFileSubmit'])) {
+ if ($_FILES['sshPublicKeyFile'] && ($_FILES['sshPublicKeyFile']['size'] > 0)) {
+ $handle = fopen($_FILES['sshPublicKeyFile']['tmp_name'], "r");
+ $data = fread($handle, 10000000);
+ fclose($handle);
+ $data = str_replace("\r\n", "\n", $data);
+ $data = str_replace("\r", "\n", $data);
+ $lines = explode("\n", $data);
+ foreach ($lines as $line) {
+ if (!empty($line) && !(strpos($line, '#') === 0)) {
+ $this->attributes['sshPublicKey'][] = $line;
+ }
+ }
+ }
+ else {
+ $messages[] = $this->messages['file'][0];
+ }
+ }
+ $this->attributes['sshPublicKey'] = array_values(array_unique($this->attributes['sshPublicKey']));
+ return $messages;
}
/**
@@ -207,26 +251,153 @@ class ldapPublicKey extends baseModule {
if (isset($attributes['sshPublicKey'][0])) {
$sshPublicKeys = $attributes['sshPublicKey'];
}
- $sshPublicKeyField = new htmlInputTextarea('ldapPublicKey_sshPublicKey', implode("\r\n", $sshPublicKeys), 100, 4);
- if (in_array('sshPublicKey', $readOnlyFields)) {
- $text = '';
- for ($i = 0; $i < sizeof($sshPublicKeys); $i++) {
- if ($i > 0) {
- $text .= '
';
- }
- $text .= htmlspecialchars($sshPublicKeys[$i]);
- }
- $sshPublicKeyField = new htmlOutputText($text, false);
- }
- $label = new htmlOutputText(_('SSH public keys'));
- $label->alignment = htmlElement::ALIGN_TOP;
- $return['sshPublicKey'] = new htmlTableRow(array(
- $label, $sshPublicKeyField
- ));
+ $_SESSION[self::SESS_KEY_LIST] = $sshPublicKeys;
+ $keyTable = new htmlTable();
+ // JavaScript functions
+ $keyTable->addElement($this->getSelfServiceKeysJSBlock(), true);
+ // input fields
+ $keyTable->addElement(new htmlDiv('sshPublicKeyDiv', $this->getSelfServiceKeys()), true);
+ // upload status
+ $uploadStatus = new htmlDiv('ldapPublicKey_upload_status_key', new htmlOutputText(''));
+ $uploadStatus->setCSSClasses(array('qq-upload-list'));
+ $uploadStatus->colspan = 7;
+ $keyTable->addElement($uploadStatus, true);
+ $keyLabel = new htmlOutputText(_('SSH public keys'));
+ $keyLabel->alignment = htmlElement::ALIGN_TOP;
+ $keyCells = array($keyLabel, $keyTable);
+ $keyRow = new htmlTableRow($keyCells);
+ $return['sshPublicKey'] = $keyRow;
}
return $return;
}
+ /**
+ * Returns the meta HTML code to display the key area.
+ * This also includes the file upload.
+ *
+ * @return htmlTable key content
+ */
+ private function getSelfServiceKeys() {
+ $keys = $_SESSION[self::SESS_KEY_LIST];
+ $content = new htmlTable();
+ if (sizeof($keys) > 0) {
+ $keyTable = new htmlTable();
+ for ($i = 0; $i < sizeof($keys); $i++) {
+ $keyInput = new htmlInputField('sshPublicKey_' . $i, $keys[$i]);
+ $keyInput->setFieldMaxLength(16384);
+ $keyTable->addElement($keyInput);
+ $delLink = new htmlLink('', '#', '../../graphics/del.png');
+ $delLink->setTitle(_('Delete'));
+ $delLink->setOnClick('ldapPublicKeyDeleteKey(' . $i . ', ' . sizeof($keys) . ');return false;');
+ $keyTable->addElement($delLink);
+ if ($i == (sizeof($keys) - 1)) {
+ $addLink = new htmlLink('', '#', '../../graphics/add.png');
+ $addLink->setTitle(_('Add'));
+ $addLink->setOnClick('ldapPublicKeyAddKey(' . sizeof($keys) . ');return false;');
+ $keyTable->addElement($addLink);
+ }
+ $keyTable->addNewLine();
+ }
+ $content->addElement($keyTable, true);
+ }
+ else {
+ $addLink = new htmlLink('', '#', '../../graphics/add.png');
+ $addLink->setTitle(_('Add'));
+ $addLink->setOnClick('ldapPublicKeyAddKey(' . sizeof($keys) . ');return false;');
+ $content->addElement($addLink, true);
+ }
+ // upload button
+ $uploadButtons = new htmlGroup();
+ $uploadButtons->addElement(new htmlDiv('ldapPublicKeyKeyUploadId', new htmlOutputText('')), true);
+ $keyUpload = new htmlJavaScript('ldapPublicKeyUploadKey(\'ldapPublicKeyKeyUploadId\', ' . sizeof($keys) . ');');
+ $uploadButtons->addElement($keyUpload);
+ $content->addElement($uploadButtons, true);
+ return $content;
+ }
+
+ /**
+ * Returns the Java Script functions to manage the keys.
+ *
+ * @return htmlJavaScript JS block
+ */
+ private static function getSelfServiceKeysJSBlock() {
+ $content = '
+ function ldapPublicKeyDeleteKey(id, count) {
+ var actionJSON = {
+ "action": "deleteKey",
+ "id": id
+ };
+ for (c = 0; c < count; c++) {
+ actionJSON["sshPublicKey_" + c] = jQuery(\'#sshPublicKey_\' + c).val();
+ }
+ jQuery.post(\'../misc/ajax.php?selfservice=1&module=ldapPublicKey&scope=user\', {jsonInput: actionJSON}, function(data) {ldapPublicKeyDeleteKeyHandleReply(data);}, \'json\');
+ }
+
+ function ldapPublicKeyDeleteKeyHandleReply(data) {
+ if (data.errorsOccured == "false") {
+ jQuery(\'#sshPublicKeyDiv\').html(data.html);
+ }
+ else {
+ alert(data.errormessage);
+ }
+ }
+
+ function ldapPublicKeyAddKey(count) {
+ var actionJSON = {
+ "action": "addKey"
+ };
+ for (c = 0; c < count; c++) {
+ actionJSON["sshPublicKey_" + c] = jQuery(\'#sshPublicKey_\' + c).val();
+ }
+ jQuery.post(\'../misc/ajax.php?selfservice=1&module=ldapPublicKey&scope=user\', {jsonInput: actionJSON}, function(data) {ldapPublicKeyAddKeyHandleReply(data);}, \'json\');
+ }
+
+ function ldapPublicKeyAddKeyHandleReply(data) {
+ if (data.errorsOccured == "false") {
+ jQuery(\'#sshPublicKeyDiv\').html(data.html);
+ }
+ else {
+ alert(data.errormessage);
+ }
+ }
+
+ function ldapPublicKeyUploadKey(elementID, count) {
+ var uploadStatus = document.getElementById(\'ldapPublicKey_upload_status_key\');
+ var parameters = {
+ action: \'ajaxKeyUpload\'
+ };
+ for (c = 0; c < count; c++) {
+ parameters["sshPublicKey_" + c] = jQuery(\'#sshPublicKey_\' + c).val();
+ }
+ var uploader = new qq.FineUploader({
+ element: document.getElementById(elementID),
+ listElement: uploadStatus,
+ request: {
+ endpoint: \'../misc/ajax.php?selfservice=1&module=ldapPublicKey&scope=user\',
+ forceMultipart: true,
+ paramsInBody: true,
+ params: parameters
+ },
+ multiple: false,
+ callbacks: {
+ onComplete: function(id, fileName, data) {
+ if (data.success) {
+ if (data.html) {
+ jQuery(\'#sshPublicKeyDiv\').html(data.html);
+ }
+ }
+ else {
+ alert(data.error);
+ }
+ }
+ }
+ });
+ }
+
+ ';
+ return new htmlJavaScript($content);
+ }
+
/**
* Checks if all input values are correct and returns the LDAP attributes which should be changed.
*
Return values:
@@ -250,7 +421,12 @@ class ldapPublicKey extends baseModule {
return $return; // skip processing if only a password change is done
}
if (in_array('sshPublicKey', $fields)) {
- $newKeys = explode("\r\n", trim($_POST['ldapPublicKey_sshPublicKey']));
+ $newKeys = array();
+ $counter = 0;
+ while (isset($_POST['sshPublicKey_' . $counter])) {
+ $newKeys[] = $_POST['sshPublicKey_' . $counter];
+ $counter++;
+ }
$count = sizeof($newKeys);
for ($i = 0; $i < $count; $i++) {
if (trim($newKeys[$i]) == '') {
@@ -289,6 +465,119 @@ class ldapPublicKey extends baseModule {
return $return;
}
+ /**
+ * Manages AJAX requests.
+ * This function may be called with or without an account container.
+ */
+ public function handleAjaxRequest() {
+ $x = $_POST;
+ $y = $_GET;
+ // AJAX uploads are non-JSON
+ if (isset($_GET['action']) && ($_GET['action'] == 'ajaxKeyUpload')) {
+ $this->ajaxUpload();
+ return;
+ }
+ $jsonInput = $_POST['jsonInput'];
+ $jsonReturn = self::invalidAjaxRequest();
+ if (isset($jsonInput['action'])) {
+ if ($jsonInput['action'] == 'deleteKey') {
+ $jsonReturn = $this->ajaxDeleteSelfServiceKey($jsonInput);
+ }
+ elseif ($jsonInput['action'] == 'addKey') {
+ $_SESSION[self::SESS_KEY_LIST][] = '';
+ ob_start();
+ $contentElement = $this->getSelfServiceKeys();
+ ob_end_clean();
+ ob_start();
+ $tabindex = 999;
+ parseHtml(null, $contentElement, array(), true, $tabindex, $this->get_scope());
+ $content = ob_get_contents();
+ ob_end_clean();
+ $jsonReturn = array(
+ 'errorsOccured' => 'false',
+ 'html' => $content,
+ );
+ }
+ }
+ echo json_encode($jsonReturn);
+ }
+
+ /**
+ * Handles an AJAX file upload and prints the JSON result.
+ */
+ private function ajaxUpload() {
+ $x = $_GET;
+ $y = $_FILES;
+ $result = array('success' => true);
+ if (!isset($_FILES['qqfile']) || ($_FILES['qqfile']['size'] < 10)) {
+ $result = array('error' => _('No file received.'));
+ }
+ else {
+ $handle = fopen($_FILES['qqfile']['tmp_name'], "r");
+ $data = fread($handle, 100000000);
+ fclose($handle);
+ $data = str_replace("\r\n", "\n", $data);
+ $data = str_replace("\r", "\n", $data);
+ $lines = explode("\n", $data);
+ foreach ($lines as $line) {
+ if (!empty($line) && !(strpos($line, '#') === 0)) {
+ $_SESSION[self::SESS_KEY_LIST][] = $line;
+ }
+ }
+ $_SESSION[self::SESS_KEY_LIST] = array_values(array_unique($_SESSION[self::SESS_KEY_LIST]));
+ ob_start();
+ $contentElement = $this->getSelfServiceKeys();
+ ob_end_clean();
+ ob_start();
+ $tabindex = 999;
+ parseHtml(null, $contentElement, array(), true, $tabindex, $this->get_scope());
+ $content = ob_get_contents();
+ ob_end_clean();
+ $result['html'] = $content;
+ }
+ echo json_encode($result);
+ }
+
+ /**
+ * Manages the deletion of a key.
+ *
+ * @param array $data JSON data
+ */
+ private function ajaxDeleteSelfServiceKey($data) {
+ if (!isset($data['id'])) {
+ return self::invalidAjaxRequest();
+ }
+ $index = $data['id'];
+ if (array_key_exists($index, $_SESSION[self::SESS_KEY_LIST])) {
+ unset($_SESSION[self::SESS_KEY_LIST][$index]);
+ $_SESSION[self::SESS_KEY_LIST] = array_values($_SESSION[self::SESS_KEY_LIST]);
+ }
+ ob_start();
+ $contentElement = $this->getSelfServiceKeys();
+ ob_end_clean();
+ ob_start();
+ $tabindex = 999;
+ parseHtml(null, $contentElement, array(), true, $tabindex, $this->get_scope());
+ $content = ob_get_contents();
+ ob_end_clean();
+ return array(
+ 'errorsOccured' => 'false',
+ 'html' => $content,
+ );
+ }
+
+ /**
+ * Invalid AJAX request received.
+ *
+ * @param String $message error message
+ */
+ public static function invalidAjaxRequest($message = null) {
+ if ($message == null) {
+ $message = _('Invalid request');
+ }
+ return array('errorsOccured' => 'true', 'errormessage' => $message);
+ }
+
}