From c9008b3c7c9660a294312a51b31049a8845cfb1e Mon Sep 17 00:00:00 2001 From: Roland Gruber Date: Wed, 7 Dec 2016 21:17:20 +0100 Subject: [PATCH 1/3] fix PHP notices --- lam/lib/modules/posixAccount.inc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lam/lib/modules/posixAccount.inc b/lam/lib/modules/posixAccount.inc index 04f396a4..82fc52bc 100644 --- a/lam/lib/modules/posixAccount.inc +++ b/lam/lib/modules/posixAccount.inc @@ -2175,7 +2175,7 @@ class posixAccount extends baseModule implements passwordService { } // GECOS if (!$this->isBooleanConfigOptionSet('posixAccount_hidegecos')) { - if ($rawAccount[$ids['posixAccount_gecos']] != "") { + if (!empty($rawAccount[$ids['posixAccount_gecos']])) { if (get_preg($rawAccount[$ids['posixAccount_gecos']], 'gecos')) { $partialAccounts[$i]['gecos'] = $this->checkASCII($rawAccount[$ids['posixAccount_gecos']]); } @@ -2189,14 +2189,14 @@ class posixAccount extends baseModule implements passwordService { $gecos = ""; if (($rawAccount[$ids['inetOrgPerson_firstName']] != "") && ($rawAccount[$ids['inetOrgPerson_lastName']] != "")) { $gecos = $rawAccount[$ids['inetOrgPerson_firstName']] . " " . $rawAccount[$ids['inetOrgPerson_lastName']]; - if ($rawAccount[$ids['inetOrgPerson_telephone']] != "") { + if (!empty($rawAccount[$ids['inetOrgPerson_telephone']])) { $gecos = $gecos . ",," . $rawAccount[$ids['inetOrgPerson_telephone']]; // double "," because room is unknown - if ($rawAccount[$ids['inetOrgPerson_fax']] != "") { + if (!empty($rawAccount[$ids['inetOrgPerson_fax']])) { $gecos = $gecos . "," . $rawAccount[$ids['inetOrgPerson_fax']]; } } } - if ($gecos != "") { + if (!empty($gecos)) { $partialAccounts[$i]['gecos'] = $this->checkASCII($gecos); } } @@ -2452,7 +2452,7 @@ class posixAccount extends baseModule implements passwordService { $temp['dn_gon'][$gonMap[$gons[$g]]][$memberAttr][] = $accounts[$i]['dn']; } } - if ($dataRow[$col_home] != "") { + if (!empty($dataRow[$col_home])) { $temp['createHomes'][] = $i; } } From eddfb11cf0db9f1a2521e9d500eb3403ec091e44 Mon Sep 17 00:00:00 2001 From: Roland Gruber Date: Wed, 7 Dec 2016 21:18:06 +0100 Subject: [PATCH 2/3] Ajax file upload --- lam/lib/lists.inc | 4 +- lam/lib/tools/fileUpload.inc | 48 +-- lam/lib/upload.inc | 307 ++++++++++++++++++ lam/templates/lib/500_lam.js | 184 +++++++++-- lam/templates/massDoUpload.php | 277 ---------------- lam/templates/misc/ajax.php | 8 + .../{ => upload}/massBuildAccounts.php | 21 +- lam/templates/upload/massDoUpload.php | 88 +++++ lam/templates/{ => upload}/masscreate.php | 31 +- 9 files changed, 605 insertions(+), 363 deletions(-) create mode 100644 lam/lib/upload.inc delete mode 100644 lam/templates/massDoUpload.php rename lam/templates/{ => upload}/massBuildAccounts.php (95%) create mode 100644 lam/templates/upload/massDoUpload.php rename lam/templates/{ => upload}/masscreate.php (96%) diff --git a/lam/lib/lists.inc b/lam/lib/lists.inc index ea23a8b9..9eb15957 100644 --- a/lam/lib/lists.inc +++ b/lam/lib/lists.inc @@ -584,7 +584,7 @@ class lamList { } // file upload elseif (isset($_POST['fileUpload']) && checkIfNewEntriesAreAllowed($this->type)){ - metaRefresh("../masscreate.php?type=" . $this->type); + metaRefresh("../upload/masscreate.php?type=" . $this->type); exit; } } @@ -1091,7 +1091,7 @@ class lamList { elseif (isset($_GET['uploadAllOk'])) { StatusMessage('INFO', _("Upload has finished")); if (isset($_SESSION['mass_pdf']['file'])) { - StatusMessage('INFO', sprintf(_('You can download your PDF files {link=%s}{color=#d2131a}here{endcolor}{endlink}.'), '../' . $_SESSION['mass_pdf']['file'])); + StatusMessage('INFO', sprintf(_('You can download your PDF files {link=%s}{color=#d2131a}here{endcolor}{endlink}.'), $_SESSION['mass_pdf']['file'])); } } elseif (isset($_GET['accountEditInvalidID'])) { diff --git a/lam/lib/tools/fileUpload.inc b/lam/lib/tools/fileUpload.inc index e90f27c8..a2943cee 100644 --- a/lam/lib/tools/fileUpload.inc +++ b/lam/lib/tools/fileUpload.inc @@ -9,12 +9,12 @@ $Id$ it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 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 General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA @@ -30,56 +30,56 @@ $Id$ /** * File upload - * + * * @package tools - */ + */ class toolFileUpload implements LAMTool { - + /** * Returns the name of the tool. - * + * * @return string name */ function getName() { return _("File upload"); } - + /** * returns a description text for the tool. - * + * * @return string description */ function getDescription() { return _("Creates accounts by uploading a CSV formated file."); } - + /** * Returns a link to the tool page (relative to templates/). - * + * * @return string link */ function getLink() { - return "masscreate.php"; + return "upload/masscreate.php"; } - - /** + + /** * Returns if the tool requires write access to LDAP. - * + * * @return boolean true if write access is needed */ function getRequiresWriteAccess() { return true; } - + /** * Returns if the tool requires password change rights. - * + * * @return boolean true if password change rights are needed */ function getRequiresPasswordChangeRights() { return true; } - + /** * Returns the link to the tool image (relative to graphics/) * @@ -88,7 +88,7 @@ class toolFileUpload implements LAMTool { function getImageLink() { return 'up.gif'; } - + /** * Returns the prefered position of this tool on the tools page. * The position may be between 0 and 1000. 0 is the top position. @@ -98,16 +98,16 @@ class toolFileUpload implements LAMTool { function getPosition() { return 300; } - + /** * Returns a list of sub tools or an empty array. - * + * * @return array list of subtools (LAMTool) */ function getSubTools() { return array(); } - + /** * Returns if the tool is visible in the menu. * @@ -116,16 +116,16 @@ class toolFileUpload implements LAMTool { function isVisible() { return (sizeof($_SESSION['config']->get_ActiveTypes()) > 0); } - + /** * Returns if a tool may be hidden by configuration in the LAM server profile. - * + * * @return boolean hideable */ function isHideable() { return true; } - + } ?> \ No newline at end of file diff --git a/lam/lib/upload.inc b/lam/lib/upload.inc new file mode 100644 index 00000000..3836fa15 --- /dev/null +++ b/lam/lib/upload.inc @@ -0,0 +1,307 @@ + &$value) { + if (strpos($key, 'mass_') === 0) { + unset($_SESSION[$key]); + } + } + } + + /** + * Constructor + */ + public function __construct($scope) { + $this->accounts = unserialize(lamDecrypt($_SESSION['mass_accounts'])); + $this->data = unserialize(lamDecrypt($_SESSION['mass_data'])); + $this->scope = $scope; + $startTime = time(); + $maxTime = get_cfg_var('max_execution_time') - 5; + if ($maxTime > Uploader::TIME_LIMIT) $maxTime = Uploader::TIME_LIMIT; + if ($maxTime <= 0) $maxTime = Uploader::TIME_LIMIT; + $this->endTime = $startTime + $maxTime; + } + + /** + * Start or continues the file upload. + * + * @return String JSON of upload status + */ + public function doUpload() { + $this->securityCheck(); + if (!isset($_SESSION['mass_counter'])) { + return $this->startUpload(); + } + elseif ($_SESSION['mass_counter'] < sizeof($this->accounts)) { + return $this->continueUpload(); + } + elseif (!isset($_SESSION['mass_postActions']['finished'])) { + return $this->runPostActions(); + } + elseif (($_SESSION['mass_pdf']['structure'] != null) && !isset($_SESSION['mass_pdf']['finished'])) { + return $this->createPDF(); + } + return $this->buildUploadStatus(100, true, '', 100, true, 100); + } + + /** + * Continues to upload accounts. + * + * @return String JSON of upload status + */ + private function continueUpload() { + while (($_SESSION['mass_counter'] < sizeof($this->accounts)) && ($this->endTime > time())) { + $this->uploadEntry($_SESSION['mass_counter']); + $_SESSION['mass_counter']++; + } + $accountsProgress = round(($_SESSION['mass_counter'] * 100) / sizeof($this->accounts), 2); + $accountsFinished = ($_SESSION['mass_counter'] == sizeof($this->accounts)); + return $this->buildUploadStatus($accountsProgress, $accountsFinished); + } + + /** + * Performs the upload of a single LDAP entry. + * + * @param int $position position in $this->accounts. + */ + private function uploadEntry($position) { + $attrs = $this->accounts[$position]; + $dn = $attrs['dn']; + unset($attrs['dn']); + // remove informational attributes + foreach ($attrs as $key => $value) { + if (strpos($key, 'INFO.') === 0) { + unset($attrs[$key]); + } + } + // run preactions + $preAttributes = array(); + foreach ($attrs as $key => $value) { + $preAttributes[$key] = &$attrs[$key]; + } + $preAttributes['dn'] = &$dn; + $preMessages = doUploadPreActions($this->scope, $_SESSION['mass_selectedModules'], $preAttributes); + $preActionOk = true; + for ($i = 0; $i < sizeof($preMessages); $i++) { + if (($preMessages[$i][0] == 'ERROR') || ($preMessages[$i][0] == 'WARN')) { + $preActionOk = false; + $_SESSION['mass_errors'][] = $preMessages[$i]; + } + } + if ($preActionOk) { + // add LDAP entry + $success = @ldap_add($_SESSION['ldap']->server(), $dn, $attrs); + if (!$success) { + $errorMessage = array( + "ERROR", + _("LAM was unable to create account %s! An LDAP error occured."), + getDefaultLDAPErrorString($_SESSION['ldap']->server()), + array($position)); + $_SESSION['mass_errors'][] = $errorMessage; + $_SESSION['mass_failed'][] = $position; + } + } + } + + /** + * Starts the file upload. + * + * @return String JSON of upload status + */ + private function startUpload() { + $_SESSION['mass_counter'] = 0; + return $this->buildUploadStatus(); + } + + /** + * Returns the upload status as JSON. + * + * @param number $accountsProgress progress for LDAP entries + * @param string $accountsFinished all entries in LDAP + * @param string $postActionsTitle title for current post action + * @param number $postActionsProgress progress for post actions + * @param string $postActionsFinished post actions finished + * @param number $pdfProgress PDF creation progress + * @return String JSON status + */ + private function buildUploadStatus($accountsProgress = 0, $accountsFinished = false, + $postActionsTitle = '', $postActionsProgress = 0, $postActionsFinished = false, + $pdfProgress = 0) { + $pdfFinished = ($_SESSION['mass_pdf']['structure'] == null) || isset($_SESSION['mass_pdf']['finished']); + $allDone = $accountsFinished && $postActionsFinished && $pdfFinished; + $errorHtml = ''; + if ($allDone && !empty($_SESSION['mass_errors'])) { + foreach ($_SESSION['mass_errors'] as $error) { + $text = isset($error[2]) ? $error[2] : ''; + $vars = isset($error[3]) ? $error[3] : array(); + $errorHtml .= StatusMessage($error[0], $error[1], $text, $vars, true); + } + } + $status = array( + 'title' => _("LDAP upload in progress. Please wait."), + 'titleFinished' => _("Upload has finished"), + 'titleErrors' => _("There were errors while uploading:"), + 'titlePDF' => _('Create PDF files'), + 'accountsProgress' => $accountsProgress, + 'accountsFinished' => $accountsFinished, + 'postActionsTitle' => $postActionsTitle, + 'postActionsProgress' => $postActionsProgress, + 'postActionsFinished' => $postActionsFinished, + 'pdfProgress' => $pdfProgress, + 'pdfFinished' => $pdfFinished, + 'allDone' => $allDone, + 'errorHtml' => $errorHtml, + 'scope' => $this->scope + ); + return json_encode($status); + } + + /** + * Checks for security violations and stops processing if needed. + */ + private function securityCheck() { + if (!isLoggedIn() || empty($this->scope) + || isAccountTypeHidden($this->scope) + || !checkIfNewEntriesAreAllowed($this->scope) + || !checkIfWriteAccessIsAllowed($this->scope)) { + die; + } + } + + /** + * Performs any post create actions by modules. + * + * @return String JSON of upload status + */ + private function runPostActions() { + $return = $this->runModulePostActions(); + while (!isset($_SESSION['mass_postActions']['finished']) && ($this->endTime > time())) { + $return = $this->runModulePostActions(); + } + $title = _("Additional tasks for module:") . ' ' . getModuleAlias($return['module'], $this->scope); + $progress = round($return['progress'], 2); + $finished = isset($_SESSION['mass_postActions']['finished']); + return $this->buildUploadStatus(100, true, $title, $progress, $finished); + } + + /** + * Runs a single post create action by modules. + * + * @return array status array + */ + private function runModulePostActions() { + $return = doUploadPostActions($this->scope, $this->data, $_SESSION['mass_ids'], $_SESSION['mass_failed'], $_SESSION['mass_selectedModules'], $this->accounts); + if ($return['status'] == 'finished') { + $_SESSION['mass_postActions']['finished'] = true; + } + if (isset($return['errors'])) { + for ($i = 0; $i < sizeof($return['errors']); $i++) { + $_SESSION['mass_errors'][] = $return['errors'][$i]; + } + } + return $return; + } + + /** + * Creates the PDF files. + * + * @return String JSON of upload status + */ + private function createPDF() { + $file = $_SESSION['mass_pdf']['file']; + $pdfStructure = $_SESSION['mass_pdf']['structure']; + $pdfZip = new ZipArchive(); + if ($_SESSION['mass_pdf']['counter'] == 0) { + $pdfZipResult = @$pdfZip->open($_SESSION['mass_pdf']['file'], ZipArchive::CREATE); + if (!$pdfZipResult === true) { + $_SESSION['mass_errors'][] = array('ERROR', _('Unable to create ZIP file for PDF export.'), $file); + $_SESSION['mass_pdf']['finished'] = true; + } + } + else { + @$pdfZip->open($_SESSION['mass_pdf']['file']); + } + while (!isset($_SESSION['mass_pdf']['finished']) && ($this->endTime > time())) { + $attrs = $this->accounts[$_SESSION['mass_pdf']['counter']]; + $dn = $attrs['dn']; + // get informational attributes + $infoAttributes = array(); + foreach ($attrs as $key => $value) { + if (strpos($key, 'INFO.') === 0) { + $infoAttributes[$key] = $value; + } + } + // load account + $_SESSION['mass_pdfAccount'] = new accountContainer($this->scope, 'mass_pdfAccount'); + $pdfErrors = $_SESSION['mass_pdfAccount']->load_account($dn, $infoAttributes); + if (sizeof($pdfErrors) > 0) { + $_SESSION['mass_errors'] = array_merge($_SESSION['mass_errors'], $pdfErrors); + $_SESSION['mass_pdf']['finished'] = true; + break; + } + // create and save PDF + $pdfContent = createModulePDF(array($_SESSION['mass_pdfAccount']), $pdfStructure, true); + $fileName = $dn . '.pdf'; + $pdfZip->addFromString($fileName, $pdfContent); + $_SESSION['mass_pdf']['counter'] ++; + if ($_SESSION['mass_pdf']['counter'] >= sizeof($this->accounts)) { + $_SESSION['mass_pdf']['finished'] = true; + } + } + @$pdfZip->close(); + $progress = ($_SESSION['mass_pdf']['counter'] * 100) / sizeof($this->accounts); + return $this->buildUploadStatus(100, true, '', 100, true, $progress); + } + +} diff --git a/lam/templates/lib/500_lam.js b/lam/templates/lib/500_lam.js index 5e25db95..f0c80956 100644 --- a/lam/templates/lib/500_lam.js +++ b/lam/templates/lib/500_lam.js @@ -3,7 +3,7 @@ $Id$ This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/) - Copyright (C) 2003 - 2014 Roland Gruber + Copyright (C) 2003 - 2016 Roland Gruber This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -23,7 +23,7 @@ $Id$ /** * Called when user clicks on a table row. This toggles the checkbox in the row. - * + * * @param box checkbox name */ function list_click(box) { @@ -38,7 +38,7 @@ function list_click(box) { /** * The user changed the value in the OU selection box. This will reload the list view with the new suffix. - * + * * @param type account type * @param element dropdown box */ @@ -48,7 +48,7 @@ function listOUchanged(type, element) { /** * The user pressed a key in the page number box. On enter this will reload the list view with the new page. - * + * * @param url target URL * @param e event */ @@ -83,7 +83,7 @@ function listResizeITabContentDiv() { /** * Shows the dialog to change the list settings. - * + * * @param title dialog title * @param okText text for Ok button * @param cancelText text for Cancel button @@ -104,7 +104,7 @@ function listShowSettingsDialog(title, okText, cancelText) { /** * Submits the form by clicking on the given button if enter was pressed. * Example: SubmitForm('apply_filter', event); - * + * * @param id button ID * @param e event * @returns Boolean result @@ -147,7 +147,7 @@ function addResizeHandler(item, min, max) { } jQuery(item).toggleClass('imgExpanded'); } - ); + ); } /** @@ -168,7 +168,7 @@ function list_switchAccountSelection() { /** * The user changed the value in the profile selection box. This will reload the login page with the new profile. - * + * * @param element dropdown box */ function loginProfileChanged(element) { @@ -177,7 +177,7 @@ function loginProfileChanged(element) { /** * Shows the dialog to delete a profile. - * + * * @param title dialog title * @param okText text for Ok button * @param cancelText text for Cancel button @@ -206,7 +206,7 @@ function profileShowDeleteDialog(title, okText, cancelText, scope, selectFieldNa /** * Shows a simple dialog. - * + * * @param title dialog title * @param okText text for Ok button (optional, submits form) * @param cancelText text for Cancel button @@ -230,7 +230,7 @@ function showSimpleDialog(title, okText, cancelText, formID, dialogDivID) { /** * Shows the dialog to change the password. - * + * * @param title dialog title * @param okText text for Ok button * @param cancelText text for Cancel button @@ -259,7 +259,7 @@ function passwordShowChangeDialog(title, okText, cancelText, randomText, ajaxURL /** * Manages the password change when a button is pressed. - * + * * @param random "true" if random password should be generated * @param ajaxURL URL used for AJAX request */ @@ -292,7 +292,7 @@ function passwordHandleInput(random, ajaxURL) { /** * Manages the server reply to a password change request. - * + * * @param data JSON reply */ function passwordHandleReply(data) { @@ -306,12 +306,12 @@ function passwordHandleReply(data) { } else { jQuery('#passwordDialogMessageArea').html(data.messages); - } + } } /** * Shows a general confirmation dialog and submits a form if the user accepted. - * + * * @param title dialog title * @param okText text for Ok button * @param cancelText text for Cancel button @@ -345,7 +345,7 @@ function showConfirmationDialog(title, okText, cancelText, dialogDiv, formName, /** * Appends the input fields of a dialog back to the form and submits it. - * + * * @param dialogDiv ID of dialog div * @param formName name of form */ @@ -361,7 +361,7 @@ function appendDialogInputsToFormAndSubmit(dialogDiv, formName) { /** * Shows a simple confirmation dialog. * If the user presses Cancel then the current action is stopped (event.preventDefault()). - * + * * @param text dialog text * @param e event */ @@ -380,7 +380,7 @@ function confirmOrStopProcessing(text, e) { /** * Alines the elements with the given IDs to the same width. - * + * * @param elementIDs IDs */ function equalWidth(elementIDs) { @@ -401,7 +401,7 @@ function equalWidth(elementIDs) { /** * Alines the elements with the given IDs to the same height. - * + * * @param elementIDs IDs */ function equalHeight(elementIDs) { @@ -418,7 +418,7 @@ function equalHeight(elementIDs) { /** * Shows the dialog to change the list settings. - * + * * @param title dialog title * @param okText text for Ok button * @param cancelText text for Cancel button @@ -430,7 +430,7 @@ function showDistributionDialog(title, okText, cancelText, scope, type, selectFi // show dialog var buttonList = {}; var dialogId = ''; - + if (type == 'export') { // show structure name to export jQuery('#exportName').text(jQuery('[name=' + selectFieldName + ']').val()); @@ -451,7 +451,7 @@ function showDistributionDialog(title, okText, cancelText, scope, type, selectFi buttonList[okText] = function() { document.forms["importDialogForm_" + scope].submit(); }; } buttonList[cancelText] = function() { jQuery(this).dialog("close"); }; - + jQuery('#' + dialogId).dialog({ modal: true, title: title, @@ -468,7 +468,7 @@ function showDistributionDialog(title, okText, cancelText, scope, type, selectFi /** * Stores the current scroll position in the form. - * + * * @param formName ID of form */ function saveScrollPosition(formName) { @@ -484,11 +484,11 @@ function saveScrollPosition(formName) { name: 'scrollPositionLeft', value: left }).appendTo(jQuery('#' + formName)); -} +} /** * Shows the dialog to create a DNS zone. - * + * * @param title dialog title * @param okText text for Ok button * @param cancelText text for Cancel button @@ -528,14 +528,14 @@ jQuery(document).ready( /** * Checks if the given field has the same value as the reference field. * Field is marked red if different and green if equal. - * + * * @param fieldID ID of field to check * @param fieldIDReference ID of reference field */ function checkFieldsHaveSameValues(fieldID, fieldIDReference) { var field = jQuery('#' + fieldID); var fieldRef = jQuery('#' + fieldIDReference); - var check = + var check = function() { var value = field.val(); var valueRef = fieldRef.val(); @@ -546,7 +546,7 @@ function checkFieldsHaveSameValues(fieldID, fieldIDReference) { else { if (value == valueRef) { field.removeClass('markFail'); - field.addClass('markOk'); + field.addClass('markOk'); } else { field.addClass('markFail'); @@ -561,12 +561,12 @@ function checkFieldsHaveSameValues(fieldID, fieldIDReference) { /** * Checks if the value of the given password field matches LAM's password policy. * Field is marked red if fail and green if ok. - * + * * @param fieldID ID of field to check */ function checkPasswordStrength(fieldID, ajaxURL) { var field = jQuery('#' + fieldID); - var check = + var check = function() { var value = field.val(); var pwdJSON = { @@ -580,7 +580,7 @@ function checkPasswordStrength(fieldID, ajaxURL) { /** * Manages the server reply to a password strength check request. - * + * * @param data JSON reply * @param fieldID input field ID */ @@ -593,19 +593,19 @@ function checkPasswordStrengthHandleReply(data, fieldID) { } else if (field.val() == '') { field.removeClass('markFail'); - field.removeClass('markOk'); + field.removeClass('markOk'); } else { field.addClass('markFail'); field.removeClass('markOk'); field.prop('title', data.result); - } + } } /** * Updates the positions of a htmlSortable list in a hidden input field. * The positions must be separated by comma (e.g. "0,1,2,3"). - * + * * @param id HTML ID of hidden input field * @param oldPos old position * @param newPos new position @@ -631,7 +631,7 @@ function updateModulePositions(id, oldPos, newPos) { /** * Filters a select box by the value of the filter input field. - * + * * @param filterInput ID of input field for filter * @param select ID of select box to filter * @param event key event @@ -658,3 +658,117 @@ function filterSelect(filterInput, select, event) { } }); } + +window.lam = window.lam || {}; +window.lam.upload = window.lam.upload || {}; + +/** + * Continues a CSV file upload. + * + * @param url URL where to get status JSON + */ +window.lam.upload.continueUpload = function(url) { + jQuery.ajax({ + url: url, + method: 'POST', + data: 'jsonInput=' + }) + .done(function(jsonData){ + if (!jsonData.accountsFinished) { + window.lam.upload.printBasicStatus(jsonData); + } + else if (!jsonData.postActionsFinished) { + window.lam.upload.printPostActionStatus(jsonData); + } + else if (!jsonData.pdfFinished) { + window.lam.upload.printPDFStatus(jsonData); + } + // next call if not finished + if (!jsonData.allDone) { + window.lam.upload.continueUpload(url); + } + else { + window.lam.upload.uploadDone(jsonData); + } + }); +}; + +/** + * Prints the upload status when accounts are still being created. + * + * @param jsonData status JSON + */ +window.lam.upload.printBasicStatus = function(jsonData) { + var htmlOut = '
'; + htmlOut += '

' + jsonData.title + '

'; + htmlOut += '
'; + htmlOut += '
'; + jQuery('#uploadContent').html(htmlOut); + jQuery('#progressbarGeneral').progressbar({ + value: jsonData.accountsProgress + }); +}; + +/** + * Prints the upload status when post actions run. + * + * @param jsonData status JSON + */ +window.lam.upload.printPostActionStatus = function(jsonData) { + var htmlOut = '
'; + htmlOut += '

' + jsonData.title + '

'; + htmlOut += '
'; + htmlOut += '
'; + if (jsonData.postActionsTitle) { + htmlOut += '

' + jsonData.postActionsTitle + '

'; + htmlOut += '
'; + } + jQuery('#uploadContent').html(htmlOut); + jQuery('#progressbarGeneral').progressbar({ + value: 100 + }); + if (jsonData.postActionsTitle) { + jQuery('#progressbarPostActions').progressbar({ + value: jsonData.postActionsProgress + }); + } +}; + +/** + * Prints the upload status when PDFs are generated. + * + * @param jsonData status JSON + */ +window.lam.upload.printPDFStatus = function(jsonData) { + var htmlOut = '
'; + htmlOut += '

' + jsonData.title + '

'; + htmlOut += '
'; + htmlOut += '
'; + htmlOut += '

' + jsonData.titlePDF + '

'; + htmlOut += '
'; + jQuery('#uploadContent').html(htmlOut); + jQuery('#progressbarGeneral').progressbar({ + value: 100 + }); + jQuery('#progressbarPDF').progressbar({ + value: jsonData.pdfProgress + }); +}; + +/** + * Upload finished, check for errors. + * + * @param jsonData status JSON + */ +window.lam.upload.uploadDone = function(jsonData) { + if (jsonData.errorHtml) { + var htmlOut = '
'; + htmlOut += '

' + jsonData.titleErrors + '

'; + htmlOut += '
'; + htmlOut += jsonData.errorHtml; + jQuery('#uploadContent').html(htmlOut); + } + else { + top.location.href = '../lists/list.php?type=' + jsonData.scope + '&uploadAllOk'; + } +} diff --git a/lam/templates/massDoUpload.php b/lam/templates/massDoUpload.php deleted file mode 100644 index 438cca58..00000000 --- a/lam/templates/massDoUpload.php +++ /dev/null @@ -1,277 +0,0 @@ -'; - -// create accounts -$accounts = unserialize(lamDecrypt($_SESSION['mass_accounts'])); -if (($_SESSION['mass_counter'] < sizeof($accounts)) || !isset($_SESSION['mass_postActions']['finished']) || !isset($_SESSION['mass_pdf']['finished'])) { - $startTime = time(); - $maxTime = get_cfg_var('max_execution_time') - 5; - if ($maxTime > 60) $maxTime = 60; - if ($maxTime <= 0) $maxTime = 60; - echo "
\n"; - echo "

" . _("LDAP upload in progress. Please wait.") . "

\n"; - echo "
"; - $progress = ($_SESSION['mass_counter'] * 100) / sizeof($accounts); - ?> -
- - time())) { - // create accounts as long as max_execution_time is not near - $attrs = $accounts[$_SESSION['mass_counter']]; - $dn = $attrs['dn']; - unset($attrs['dn']); - // remove informational attributes - foreach ($attrs as $key => $value) { - if (strpos($key, 'INFO.') === 0) { - unset($attrs[$key]); - } - } - // run preactions - $preAttributes = array(); - foreach ($attrs as $key => $value) { - $preAttributes[$key] = &$attrs[$key]; - } - $preAttributes['dn'] = &$dn; - $preMessages = doUploadPreActions($scope, $_SESSION['mass_selectedModules'], $preAttributes); - $preActionOk = true; - for ($i = 0; $i < sizeof($preMessages); $i++) { - if (($preMessages[$i][0] == 'ERROR') || ($preMessages[$i][0] == 'WARN')) { - $preActionOk = false; - $_SESSION['mass_errors'][] = $preMessages[$i]; - } - } - if ($preActionOk) { - // add LDAP entry - $success = @ldap_add($_SESSION['ldap']->server(), $dn, $attrs); - if (!$success) { - $errorMessage = array( - "ERROR", - _("LAM was unable to create account %s! An LDAP error occured."), - getDefaultLDAPErrorString($_SESSION['ldap']->server()), - array($_SESSION['mass_counter'])); - $_SESSION['mass_errors'][] = $errorMessage; - $_SESSION['mass_failed'][] = $_SESSION['mass_counter']; - } - } - $_SESSION['mass_counter']++; - } - $progress = ($_SESSION['mass_counter'] * 100) / sizeof($accounts); - ?> - - = sizeof($accounts)) && !isset($_SESSION['mass_postActions']['finished'])) { - $data = unserialize(lamDecrypt($_SESSION['mass_data'])); - $return = doUploadPostActions($scope, $data, $_SESSION['mass_ids'], $_SESSION['mass_failed'], $_SESSION['mass_selectedModules'], $accounts); - if ($return['status'] == 'finished') { - $_SESSION['mass_postActions']['finished'] = true; - } - for ($i = 0; $i < sizeof($return['errors']); $i++) $_SESSION['mass_errors'][] = $return['errors'][$i]; - echo "

" . _("Additional tasks for module:") . ' ' . getModuleAlias($return['module'], $scope) . "

\n"; - ?> -
- - time())) { - $return = doUploadPostActions($scope, $data, $_SESSION['mass_ids'], $_SESSION['mass_failed'], $_SESSION['mass_selectedModules'], $accounts); - if ($return['status'] == 'finished') { - $_SESSION['mass_postActions']['finished'] = true; - } - if (isset($return['errors'])) { - for ($i = 0; $i < sizeof($return['errors']); $i++) { - $_SESSION['mass_errors'][] = $return['errors'][$i]; - } - } - } - } - // create PDF when upload post actions are done - if (isset($_SESSION['mass_postActions']['finished'])) { - if (($_SESSION['mass_pdf']['structure'] != null) && !isset($_SESSION['mass_pdf']['finished'])) { - $file = $_SESSION['mass_pdf']['file']; - $pdfStructure = $_SESSION['mass_pdf']['structure']; - $pdfZip = new ZipArchive(); - if ($_SESSION['mass_pdf']['counter'] == 0) { - $pdfZipResult = @$pdfZip->open($_SESSION['mass_pdf']['file'], ZipArchive::CREATE); - if (!$pdfZipResult === true) { - $_SESSION['mass_errors'][] = array('ERROR', _('Unable to create ZIP file for PDF export.'), $file); - $_SESSION['mass_pdf']['finished'] = true; - } - } - else { - @$pdfZip->open($_SESSION['mass_pdf']['file']); - } - // show progress bar - $progress = ($_SESSION['mass_pdf']['counter'] * 100) / sizeof($accounts); - echo "

" . _('Create PDF files') . "

\n"; - ?> -
- - time())) { - $attrs = $accounts[$_SESSION['mass_pdf']['counter']]; - $dn = $attrs['dn']; - // get informational attributes - $infoAttributes = array(); - foreach ($attrs as $key => $value) { - if (strpos($key, 'INFO.') === 0) { - $infoAttributes[$key] = $value; - } - } - // load account - $_SESSION['pdfAccount'] = new accountContainer($scope, 'pdfAccount'); - $pdfErrors = $_SESSION['pdfAccount']->load_account($dn, $infoAttributes); - if (sizeof($pdfErrors) > 0) { - $_SESSION['mass_errors'] = array_merge($_SESSION['mass_errors'], $pdfErrors); - $_SESSION['mass_pdf']['finished'] = true; - break; - } - // create and save PDF - $pdfContent = createModulePDF(array($_SESSION['pdfAccount']), $pdfStructure, true); - $fileName = $dn . '.pdf'; - $pdfZip->addFromString($fileName, $pdfContent); - $_SESSION['mass_pdf']['counter'] ++; - if ($_SESSION['mass_pdf']['counter'] >= sizeof($accounts)) { - $_SESSION['mass_pdf']['finished'] = true; - } - } - @$pdfZip->close(); - } - else { - $_SESSION['mass_pdf']['finished'] = true; - } - } - // refresh with JavaScript - echo "\n"; -} -// all accounts have been created -else { - echo "
\n"; - echo "

" . _("Upload has finished") . "

\n"; - echo "
"; - if (sizeof($_SESSION['mass_errors']) > 0) { - echo "
\n"; - echo "

" . _("There were errors while uploading:") . "

\n"; - echo "
"; - for ($i = 0; $i < sizeof($_SESSION['mass_errors']); $i++) { - call_user_func_array('StatusMessage', $_SESSION['mass_errors'][$i]); - echo "
"; - } - } - else { - // redirect to list if no errors occured - echo "\n"; - } -} -echo ''; -include 'main_footer.php'; - - -?> \ No newline at end of file diff --git a/lam/templates/misc/ajax.php b/lam/templates/misc/ajax.php index f1c438d7..ca870ea5 100644 --- a/lam/templates/misc/ajax.php +++ b/lam/templates/misc/ajax.php @@ -88,6 +88,14 @@ class lamAjax { elseif ($function == 'passwordStrengthCheck') { lamAjax::checkPasswordStrength($jsonInput); } + elseif ($function == 'upload') { + include_once('../../lib/upload.inc'); + $uploader = new LAM\UPLOAD\Uploader($_GET['scope']); + ob_start(); + $jsonOut = $uploader->doUpload(); + ob_end_clean(); + echo $jsonOut; + } } /** diff --git a/lam/templates/massBuildAccounts.php b/lam/templates/upload/massBuildAccounts.php similarity index 95% rename from lam/templates/massBuildAccounts.php rename to lam/templates/upload/massBuildAccounts.php index aadd18fe..05567514 100644 --- a/lam/templates/massBuildAccounts.php +++ b/lam/templates/upload/massBuildAccounts.php @@ -29,13 +29,13 @@ $Id$ */ /** security functions */ -include_once("../lib/security.inc"); +include_once("../../lib/security.inc"); /** access to configuration */ -include_once('../lib/config.inc'); +include_once('../../lib/config.inc'); /** status messages */ -include_once('../lib/status.inc'); +include_once('../../lib/status.inc'); /** account modules */ -include_once('../lib/modules.inc'); +include_once('../../lib/modules.inc'); // Start session @@ -49,7 +49,7 @@ if (!checkIfWriteAccessIsAllowed()) die(); // Redirect to startpage if user is not loged in if (!isLoggedIn()) { - metaRefresh("login.php"); + metaRefresh("../login.php"); exit; } @@ -88,7 +88,7 @@ if (isset($_GET['showldif'])) { exit; } -include 'main_header.php'; +include '../main_header.php'; $scope = htmlspecialchars($_POST['scope']); // check if account type is ok @@ -215,7 +215,6 @@ if ($_FILES['inputfile'] && ($_FILES['inputfile']['size'] > 0)) { else { // store accounts in session $_SESSION['mass_accounts'] = lamEncrypt(serialize($accounts)); - $_SESSION['mass_counter'] = 0; $_SESSION['mass_errors'] = array(); $_SESSION['mass_failed'] = array(); $_SESSION['mass_postActions'] = array(); @@ -229,7 +228,7 @@ if ($_FILES['inputfile'] && ($_FILES['inputfile']['size'] > 0)) { if (isset($_POST['createPDF']) && ($_POST['createPDF'] == 'on')) { $_SESSION['mass_pdf']['structure'] = $_POST['pdfStructure']; $_SESSION['mass_pdf']['counter'] = 0; - $_SESSION['mass_pdf']['file'] = '../tmp/lam_pdf' . getRandomNumber() . '.zip'; + $_SESSION['mass_pdf']['file'] = '../../tmp/lam_pdf' . getRandomNumber() . '.zip'; } else { $_SESSION['mass_pdf']['structure'] = null; @@ -238,8 +237,8 @@ if ($_FILES['inputfile'] && ($_FILES['inputfile']['size'] > 0)) { $container->addElement(new htmlTitle(_("LAM has checked your input and is now ready to create the accounts.")), true); $container->addElement(new htmlSpacer(null, '10px'), true); $buttonContainer = new htmlTable(); - $buttonContainer->addElement(new htmlLink(_("Upload accounts to LDAP"), 'massDoUpload.php', '../graphics/up.gif', true)); - $buttonContainer->addElement(new htmlLink(_("Show LDIF file"), 'massBuildAccounts.php?showldif=true', '../graphics/edit.png', true)); + $buttonContainer->addElement(new htmlLink(_("Upload accounts to LDAP"), 'massDoUpload.php', '../../graphics/up.gif', true)); + $buttonContainer->addElement(new htmlLink(_("Show LDIF file"), 'massBuildAccounts.php?showldif=true', '../../graphics/edit.png', true)); $buttonContainer->addElement(new htmlSpacer('10px', null)); massPrintBackButton($scope, $selectedModules, $buttonContainer); $container->addElement($buttonContainer, true); @@ -263,7 +262,7 @@ parseHtml(null, $container, array(), false, $tabindex, $scope); echo ''; echo ''; -include 'main_footer.php'; +include '../main_footer.php'; /** * Prints a back button to the page where the user enters a file to upload. diff --git a/lam/templates/upload/massDoUpload.php b/lam/templates/upload/massDoUpload.php new file mode 100644 index 00000000..b0fca7dc --- /dev/null +++ b/lam/templates/upload/massDoUpload.php @@ -0,0 +1,88 @@ +'; +$tokenPrefix = '?' . getSecurityTokenName() . '=' . getSecurityTokenValue(); +?> + + +'; +include '../main_footer.php'; +?> diff --git a/lam/templates/masscreate.php b/lam/templates/upload/masscreate.php similarity index 96% rename from lam/templates/masscreate.php rename to lam/templates/upload/masscreate.php index ad457020..69de336b 100644 --- a/lam/templates/masscreate.php +++ b/lam/templates/upload/masscreate.php @@ -29,16 +29,17 @@ $Id$ */ /** security functions */ -include_once("../lib/security.inc"); +include_once("../../lib/security.inc"); /** access to configuration */ -include_once('../lib/config.inc'); +include_once('../../lib/config.inc'); /** status messages */ -include_once('../lib/status.inc'); +include_once('../../lib/status.inc'); /** account modules */ -include_once('../lib/modules.inc'); +include_once('../../lib/modules.inc'); /** Used to get PDF information. */ -include_once('../lib/pdfstruct.inc'); - +include_once('../../lib/pdfstruct.inc'); +/** upload functions */ +include_once('../../lib/upload.inc'); // Start session startSecureSession(); @@ -53,7 +54,7 @@ checkIfToolIsActive('toolFileUpload'); // Redirect to startpage if user is not loged in if (!isLoggedIn()) { - metaRefresh("login.php"); + metaRefresh("../login.php"); exit; } @@ -73,7 +74,9 @@ if (isset($_GET['getCSV'])) { exit; } -include 'main_header.php'; +LAM\UPLOAD\Uploader::cleanSession(); + +include '../main_header.php'; // get possible types and remove those which do not support file upload $types = $_SESSION['config']->get_ActiveTypes(); @@ -173,7 +176,7 @@ for ($i = 0; $i < sizeof($types); $i++) { $module = moduleCache::getModule($modules[$m], $types[$i]); $iconImage = $module->getIcon(); if (!is_null($iconImage) && !(strpos($iconImage, 'http') === 0) && !(strpos($iconImage, '/') === 0)) { - $iconImage = '../graphics/' . $iconImage; + $iconImage = '../../graphics/' . $iconImage; } $innerTable->addElement(new htmlImage($iconImage)); $enabled = true; @@ -223,7 +226,7 @@ function changeVisibleModules(element) { echo "\n"; echo ''; -include 'main_footer.php'; +include '../main_footer.php'; /** * Displays the acount type specific main page of the upload. @@ -253,7 +256,7 @@ function showMainPage($scope, $selectedModules) { $inputContainer->addElement(new htmlOutputText(_("CSV file"))); $inputContainer->addElement(new htmlInputFileUpload('inputfile')); $inputContainer->addElement(new htmlSpacer('10px', null)); - $inputContainer->addElement(new htmlLink(_("Download sample CSV file"), 'masscreate.php?getCSV=1', '../graphics/save.png', true)); + $inputContainer->addElement(new htmlLink(_("Download sample CSV file"), 'masscreate.php?getCSV=1', '../../graphics/save.png', true)); $inputContainer->addElement(new htmlHiddenInput('scope', $scope)); $inputContainer->addElement(new htmlHiddenInput('selectedModules', implode(',', $selectedModules)), true); // PDF @@ -285,7 +288,7 @@ function showMainPage($scope, $selectedModules) { $columnContainer = new htmlTable(); $columnContainer->setCSSClasses(array($scope . 'list', 'collapse')); // DN options - $dnTitle = new htmlSubTitle(_("DN settings"), '../graphics/logo32.png'); + $dnTitle = new htmlSubTitle(_("DN settings"), '../../graphics/logo32.png'); $dnTitle->colspan = 20; $columnContainer->addElement($dnTitle, true); $columnContainer->addElement($columnSpacer); @@ -357,7 +360,7 @@ function showMainPage($scope, $selectedModules) { $module = moduleCache::getModule($modules[$m], $scope); $icon = $module->getIcon(); if (($icon != null) && !(strpos($icon, 'http') === 0) && !(strpos($icon, '/') === 0)) { - $icon = '../graphics/' . $icon; + $icon = '../../graphics/' . $icon; } $moduleTitle = new htmlSubTitle(getModuleAlias($modules[$m], $scope), $icon); $moduleTitle->colspan = 20; @@ -473,7 +476,7 @@ function showMainPage($scope, $selectedModules) { $_SESSION['mass_csv'] = $sampleCSV; echo ''; - include 'main_footer.php'; + include '../main_footer.php'; die; } From 308e3292c92d7c313db91001053e669d75d785c8 Mon Sep 17 00:00:00 2001 From: Roland Gruber Date: Thu, 8 Dec 2016 18:17:04 +0100 Subject: [PATCH 3/3] fixed error message --- lam/lib/lamdaemon.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lam/lib/lamdaemon.inc b/lam/lib/lamdaemon.inc index 6685323d..43d49fd7 100644 --- a/lam/lib/lamdaemon.inc +++ b/lam/lib/lamdaemon.inc @@ -99,7 +99,7 @@ function lamLoginSSH($handle) { $username = $entry[0]['uid'][0]; } if (empty($username)) { - throw new Exception(sprintf(_("Your LAM admin user (%s) must be a valid Unix account to work with lamdaemon!"), $credentials[0])); + throw new Exception(sprintf(_("Your LAM admin user (%s) must be a valid Unix account to work with lamdaemon!"), getAbstractDN($credentials[0]))); } } $password = $credentials[1];