diff --git a/lam/lib/html.inc b/lam/lib/html.inc index bf6c515e..21fb7b7d 100644 --- a/lam/lib/html.inc +++ b/lam/lib/html.inc @@ -3082,6 +3082,15 @@ class htmlStatusMessage extends htmlElement { return array(); } + /** + * Returns the message type. + * + * @return String type + */ + public function getType() { + return $this->type; + } + } /** diff --git a/lam/lib/pdfstruct.inc b/lam/lib/pdfstruct.inc index e80591de..ef73e703 100644 --- a/lam/lib/pdfstruct.inc +++ b/lam/lib/pdfstruct.inc @@ -34,6 +34,11 @@ use \LAM\ImageUtils\ImageManipulationFactory; /** LAM configuration */ include_once(__DIR__ . "/config.inc"); +/** + * Use as server profile name to manage global templates. + */ +const GLOBAL_PROFILE = '__GLOBAL__'; + /** LDAP object */ include_once(__DIR__ . "/ldap.inc"); @@ -164,12 +169,15 @@ function copyStructureToTemplates($sourceType, $sourceName) { * @param String $file full path of temporary file * @param String $name file name * @param string $serverProfileName server profile name - * @return StatusMessage status message to display + * @return htmlStatusMessage status message to display */ function uploadPDFLogo($file, $name, $serverProfileName) { if (!preg_match('/[a-zA-Z0-9_-]+\\.(png)|(jpg)/i', $name)) { return new htmlStatusMessage('ERROR', _('Unable to upload logo file.'), _('The file name must end with ".png" or ".jpg".')); } + if ($serverProfileName === GLOBAL_PROFILE) { + $serverProfileName = '../templates/pdf'; + } $dirPath = dirname(__FILE__) . '/../config/pdf/' . $serverProfileName . '/logos/'; $success = copy($file, $dirPath . '/' . $name); if ($success) { @@ -242,21 +250,8 @@ function isValidPDFStructureName($name) { * Installs template structures to the current server profile. */ function installPDFTemplates() { - $templatePath = dirname(__FILE__) . '/../config/templates/pdf'; - $templateDir = @dir($templatePath); - $allTemplates = array(); - if ($templateDir) { - $entry = $templateDir->read(); - while ($entry){ - $parts = explode('.', $entry); - if ((strlen($entry) > 3) && (sizeof($parts) == 3)) { - $name = $parts[0]; - $scope = $parts[1]; - $allTemplates[$scope][] = $name; - } - $entry = $templateDir->read(); - } - } + $templatePath = __DIR__ . '/../config/templates/pdf'; + $allTemplates = getPdfTemplateNames(); $basePath = dirname(__FILE__) . '/../config/pdf/' . $_SESSION['config']->getName(); if (!file_exists($basePath)) { mkdir($basePath, 0700, true); @@ -278,20 +273,75 @@ function installPDFTemplates() { if (!file_exists($basePath . '/logos')) { mkdir($basePath . '/logos'); } - $templatePath = dirname(__FILE__) . '/../config/templates/pdf/logos'; + $logos = getPdfTemplateLogoNames(); + foreach ($logos as $logo) { + $path = $basePath . '/logos/' . $logo; + $template = $templatePath . '/logos/' . $logo; + if (!is_file($path)) { + logNewMessage(LOG_DEBUG, 'Copy template ' . $template . ' to ' . $path); + @copy($template, $path); + } + } +} + +/** + * Returns all PDF template names. + * + * @return array names (array('user' => array('default'))) + */ +function getPdfTemplateNames() { + $templatePath = __DIR__ . '/../config/templates/pdf'; $templateDir = @dir($templatePath); + $allTemplates = array(); if ($templateDir) { $entry = $templateDir->read(); while ($entry){ - $path = $basePath . '/logos/' . $entry; - if ((strpos($entry, '.') !== 0) && !is_file($path)) { - $template = $templatePath . '/' . $entry; - logNewMessage(LOG_DEBUG, 'Copy template ' . $template . ' to ' . $path); - @copy($template, $path); + $parts = explode('.', $entry); + if ((strlen($entry) > 3) && (sizeof($parts) == 3)) { + $name = $parts[0]; + $scope = $parts[1]; + $allTemplates[$scope][] = $name; } $entry = $templateDir->read(); } } + return $allTemplates; +} + +/** + * Returns all PDF template logo names. + * + * @return array names (array('user' => array('default.png'))) + */ +function getPdfTemplateLogoNames() { + $templatePath = __DIR__ . '/../config/templates/pdf/logos'; + $templateDir = @dir($templatePath); + $logos = array(); + if ($templateDir) { + $entry = $templateDir->read(); + while ($entry){ + if ((strpos($entry, '.') !== 0) && is_file($templatePath . '/' . $entry)) { + $logos[] = $entry; + } + $entry = $templateDir->read(); + } + } + return $logos; +} + +/** + * Returns the binary data of the PDF template logo. + * + * @param string $name file name (without path) + * @return string binary + */ +function getPdfTemplateLogoBinary($name) { + $templatePath = __DIR__ . '/../config/templates/pdf/logos'; + $fileName = $templatePath . '/' . $name; + $handle = fopen($fileName, 'r'); + $logoBinary = fread($handle, 100000000); + fclose($handle); + return $logoBinary; } /** @@ -309,7 +359,12 @@ class PDFStructureReader { * @param $serverProfileName server profile name */ public function __construct($serverProfileName) { - $this->serverProfileName = $serverProfileName; + if ($serverProfileName === GLOBAL_PROFILE) { + $this->serverProfileName = '../templates/pdf'; + } + else { + $this->serverProfileName = $serverProfileName; + } } /** @@ -345,6 +400,7 @@ class PDFStructureReader { * @return PDFStructure structure */ private function readPDFFile($file) { + logNewMessage(LOG_DEBUG, $file); $xml = new \XMLReader(); $xml->open($file); $structure = new PDFStructure(); @@ -430,7 +486,12 @@ class PDFStructureWriter { * @param string $serverProfileName server profile name */ public function __construct($serverProfileName) { - $this->serverProfileName = $serverProfileName; + if ($serverProfileName === GLOBAL_PROFILE) { + $this->serverProfileName = '../templates/pdf'; + } + else { + $this->serverProfileName = $serverProfileName; + } } /** @@ -460,10 +521,11 @@ class PDFStructureWriter { throw new \LAMException(_('PDF structure name not valid'), _('The name for that PDF-structure you submitted is not valid. A valid name must consist of the following characters: \'a-z\',\'A-Z\',\'0-9\',\'_\',\'-\'.')); } - if(!is_writable(dirname(__FILE__) . '/../config/pdf/' . $this->serverProfileName)) { - throw new \LAMException(_('Could not save PDF structure, access denied.')); + $baseDir = __DIR__ . '/../config/pdf/' . $this->serverProfileName; + if(!is_writable($baseDir)) { + throw new \LAMException(_('Could not save PDF structure, access denied to ' . $baseDir . '.')); } - return dirname(__FILE__) . '/../config/pdf/' . $this->serverProfileName . '/' . $name . '.' . $typeId . '.xml'; + return $baseDir . '/' . $name . '.' . $typeId . '.xml'; } /** diff --git a/lam/lib/persistence.inc b/lam/lib/persistence.inc index 59274f7f..5ad8b67d 100644 --- a/lam/lib/persistence.inc +++ b/lam/lib/persistence.inc @@ -8,6 +8,9 @@ use LAMConfig; use LAMException; use function LAM\PDF\getAvailableLogos; use function LAM\PDF\getPDFStructures; +use function LAM\PDF\getPdfTemplateLogoBinary; +use function LAM\PDF\getPdfTemplateLogoNames; +use function LAM\PDF\getPdfTemplateNames; use function LAM\PDF\uploadPDFLogo; use function LAM\PROFILES\getAccountProfiles; use function LAM\PROFILES\getProfileTemplateNames; @@ -68,8 +71,9 @@ class ConfigDataExporter { } $jsonData['serverProfiles'] = $this->_getServerProfiles($serverProfiles); $jsonData['accountProfiles'] = $this->_getAccountProfiles($serverProfiles); - $jsonData['accountProfileTemplates'] = $this->_getAccountProfileTemplates($serverProfiles); + $jsonData['accountProfileTemplates'] = $this->_getAccountProfileTemplates(); $jsonData['pdfProfiles'] = $this->_getPdfProfiles($serverProfiles); + $jsonData['pdfProfileTemplates'] = $this->_getPdfProfileTemplates(); /** * TODO * @@ -147,11 +151,10 @@ class ConfigDataExporter { /** * Returns the content of the account profile templates. * - * @param array $serverProfiles list of server profiles (name => object) * @return array $data * @throws LAMException error reading template */ - public function _getAccountProfileTemplates($serverProfiles) { + public function _getAccountProfileTemplates() { $data = array(); $accountProfileTemplateNames = getProfileTemplateNames(); foreach ($accountProfileTemplateNames as $scope => $templateNames) { @@ -193,6 +196,29 @@ class ConfigDataExporter { return $data; } + /** + * Returns the content of the account profile templates. + * + * @return array $data + * @throws LAMException error reading template + */ + public function _getPdfProfileTemplates() { + $data = array(); + $pdfTemplateNames = getPdfTemplateNames(); + $reader = new PDFStructureReader(\LAM\PDF\GLOBAL_PROFILE); + foreach ($pdfTemplateNames as $scope => $templateNames) { + foreach ($templateNames as $templateName) { + $pdfStructure = $reader->read($scope, $templateName); + $data['structures'][$scope][$templateName] = $pdfStructure->export(); + } + } + $logoNames = getPdfTemplateLogoNames(); + foreach ($logoNames as $logoName) { + $data['logos'][$logoName] = base64_encode(getPdfTemplateLogoBinary($logoName)); + } + return $data; + } + } /** @@ -245,6 +271,9 @@ class ConfigDataImporter { } $steps[] = $mainStep; break; + case 'pdfProfileTemplates': + $steps[] = new ImporterStep(_('PDF structures') . ' - ' . _('Global templates'), 'pdfProfileTemplates', $value); + break; default: logNewMessage(LOG_WARNING, 'Unknown import type: ' . $key); } @@ -286,6 +315,9 @@ class ConfigDataImporter { case 'pdfProfiles': $this->importPdfProfiles($step); break; + case 'pdfProfileTemplates': + $this->importPdfProfileTemplates($step); + break; default: logNewMessage(LOG_WARNING, 'Unknown import type: ' . $key); } @@ -409,7 +441,7 @@ class ConfigDataImporter { $writer->write($typeId, $pdfProfileName, $structure); } catch (LAMException $e) { - logNewMessage('ERROR', $e->getMessage()); + logNewMessage(LOG_ERR, $e->getTitle() . ' ' . $e->getMessage()); $failedProfiles[] = $serverProfileName . ':' . $typeId . ':' . $pdfProfileName; } } @@ -432,6 +464,54 @@ class ConfigDataImporter { } } + /** + * Imports the PDF profile templates. + * + * @param ImporterStep $step step + * @throws LAMException error during import + */ + private function importPdfProfileTemplates($step) { + $failedNames = array(); + $data = $step->getValue(); + if (isset($data['structures'])) { + $writer = new PDFStructureWriter(\LAM\PDF\GLOBAL_PROFILE); + foreach ($data['structures'] as $typeId => $pdfProfiles) { + foreach ($pdfProfiles as $pdfProfileName => $pdfProfileData) { + $structure = new PDFStructure(); + $structure->import($pdfProfileData); + try { + $writer->write($typeId, $pdfProfileName, $structure); + } + catch (LAMException $e) { + $failedNames[] = $typeId . ':' . $pdfProfileName; + logNewMessage(LOG_ERR, $e->getTitle() . ' ' . $e->getMessage()); + } + } + } + } + $failedLogos = array(); + if (isset($data['logos'])) { + foreach ($data['logos'] as $logoFileName => $logoData) { + $tempFilePath = tempnam("/tmp", "lam"); + $tempFile = fopen($tempFilePath, "w"); + $logoBinary = base64_decode($logoData); + fwrite($tempFile, $logoBinary); + fclose($tempFile); + $message = uploadPDFLogo($tempFilePath, $logoFileName, \LAM\PDF\GLOBAL_PROFILE); + unlink($tempFilePath); + if ($message->getType() === 'ERROR') { + $failedLogos[] = $logoFileName; + } + } + } + if (!empty($failedNames)) { + throw new LAMException(_('Could not save PDF structure, access denied.'), implode(', ', $failedNames)); + } + if (!empty($failedLogos)) { + throw new LAMException(_('Unable to upload logo file.'), implode(', ', $failedLogos)); + } + } + } /** diff --git a/lam/lib/profiles.inc b/lam/lib/profiles.inc index a45fe0f1..3a9711b1 100644 --- a/lam/lib/profiles.inc +++ b/lam/lib/profiles.inc @@ -114,7 +114,7 @@ function readAccountProfileFile($fileName) { if ($file) { while (!feof($file)) { $line = fgets($file, 1024); - if (($line == "\n")||($line[0] == "#")) { + if (($line == '') || ($line == "\n") || ($line[0] == "#")) { continue; // ignore comments } // search keywords diff --git a/lam/templates/config/confImportExport.php b/lam/templates/config/confImportExport.php index 182ae2a3..ea2e6677 100644 --- a/lam/templates/config/confImportExport.php +++ b/lam/templates/config/confImportExport.php @@ -262,6 +262,7 @@ printHeaderContents(_("Import and export configuration"), '../..'); $importer->runImport($importSteps); unlink($_SESSION['configImportFile']); $content->add(new htmlStatusMessage('INFO', _('Configuration import ended successful.')), 12); + $content->add(new htmlButton('importNew', _('New import')), 12); } catch (LAMException $e) { $content->add(new htmlStatusMessage('ERROR', htmlspecialchars($e->getTitle()), htmlspecialchars($e->getMessage())), 12);