Merge pull request #101 from LDAPAccountManager/configImportExport

Config import export
This commit is contained in:
gruberroland 2020-06-17 13:05:01 +02:00 committed by GitHub
commit 55ccddbf1e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 1986 additions and 193 deletions

View File

@ -4,6 +4,7 @@
"squizlabs/php_codesniffer" : "3.4.0"
},
"require": {
"ext-ldap": "*"
"ext-ldap": "*",
"ext-json": "*"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -1752,6 +1752,16 @@ function getLAMVersionText() {
return $text . ' - ' . LAMVersion();
}
/**
* Returns if the given release is a developer version.
*
* @param string version
* @return bool is developer version
*/
function isDeveloperVersion($version) {
return strpos($version, 'DEV') !== false;
}
/**
* LAM exception with title and message.
*

View File

@ -649,6 +649,78 @@ class LAMConfig {
$this->reload();
}
/**
* Returns the server profile data.
*
* @return array data
*/
public function exportData() {
$data = array();
$settingsToIgnore = array('modules', 'types', 'tools', 'jobs');
foreach ($this->settings as $setting) {
if (in_array($setting, $settingsToIgnore)) {
continue;
}
$data[$setting] = $this->$setting;
}
$data['typeSettings'] = $this->typeSettings;
$data['moduleSettings'] = $this->moduleSettings;
$data['toolSettings'] = $this->toolSettings;
$data['jobSettings'] = $this->jobSettings;
if ($this->jobsDatabase === 'SQLite') {
$dbFileName = __DIR__ . '/../config/' . $this->getName() . '.sqlite';
if (is_file($dbFileName) && is_readable($dbFileName)) {
$file = @fopen($dbFileName, "r");
if ($file) {
$dbData = fread($file, 100000000);
fclose($file);
$data['jobSQLite'] = base64_encode($dbData);
}
}
}
return $data;
}
/**
* Imports server profile data.
*
* @param array $data config data
* @throws LAMException import error
*/
public function importData($data) {
$settingsToIgnore = array('modules', 'types', 'tools', 'jobs', 'typeSettings',
'moduleSettings', 'toolSettings', 'jobSettings', 'jobSQLite');
foreach ($data as $dataKey => $dataValue) {
if (in_array($dataKey, $settingsToIgnore)) {
continue;
}
if (!in_array($dataKey, $this->settings)) {
logNewMessage(LOG_WARNING, 'Ignored setting during import: ' . $dataKey);
continue;
}
if (!(($dataValue === null) || is_array($dataValue) || is_string($dataValue) || is_int($dataValue) || is_bool($dataValue))) {
throw new LAMException('Invalid import data type for ' . htmlspecialchars($dataKey) . ': ' . gettype($dataValue));
}
$this->$dataKey = $dataValue;
}
$typeSettingsData = !empty($data['typeSettings']) && is_array($data['typeSettings']) ? $data['typeSettings'] : array();
$this->typeSettings = $typeSettingsData;
$moduleSettingsData = !empty($data['moduleSettings']) && is_array($data['moduleSettings']) ? $data['moduleSettings'] : array();
$this->moduleSettings = $moduleSettingsData;
$toolSettingsData = !empty($data['toolSettings']) && is_array($data['toolSettings']) ? $data['toolSettings'] : array();
$this->toolSettings = $toolSettingsData;
$jobSettingsData = !empty($data['jobSettings']) && is_array($data['jobSettings']) ? $data['jobSettings'] : array();
$this->jobSettings = $jobSettingsData;
if (!empty($data['jobSQLite'])) {
$dbFileName = __DIR__ . '/../config/' . $this->getName() . '.sqlite';
$file = @fopen($dbFileName, "wb");
if ($file) {
fputs($file, base64_decode($data['jobSQLite']));
fclose($file);
}
}
}
/**
* Reloads preferences from config file
*
@ -759,6 +831,10 @@ class LAMConfig {
/** Saves preferences to config file */
public function save() {
$conffile = $this->getPath();
if (!file_exists($conffile)) {
$newFile = fopen($conffile, 'wb');
fclose($newFile);
}
if (is_file($conffile) && is_readable($conffile)) {
$file = fopen($conffile, "r");
$file_array = array();
@ -1775,7 +1851,7 @@ class LAMConfig {
/**
* Returns a list of active account types.
*
* @return array list of types
* @return string[] list of types
*/
public function get_ActiveTypes() {
if (($this->activeTypes == '') || !isset($this->activeTypes)) {
@ -1789,7 +1865,7 @@ class LAMConfig {
/**
* Sets the list of active types.
*
* @param array list of types
* @param string[] list of types
*/
public function set_ActiveTypes($types) {
$this->activeTypes = implode(",", $types);
@ -2681,6 +2757,83 @@ class LAMCfgMain {
$this->reload();
}
/**
* Exports the configuration data.
*
* @return array config data
*/
public function exportData() {
$data = array();
foreach ($this->settings as $setting) {
$data[$setting] = $this->$setting;
}
return $data;
}
/**
* Imports configuration data.
*
* @param array $data config data
* @throws LAMException import error
*/
public function importData($data) {
foreach ($data as $dataKey => $dataValue) {
if (!in_array($dataKey, $this->settings)) {
logNewMessage(LOG_WARNING, 'Ignored setting during import: ' . $dataKey);
continue;
}
if (!(($dataValue === null) || is_array($dataValue) || is_string($dataValue) || is_int($dataValue) || is_bool($dataValue))) {
throw new LAMException('Invalid import data type for ' . htmlspecialchars($dataKey) . ': ' . gettype($dataValue));
}
$this->$dataKey = $dataValue;
}
}
/**
* Returns the content of the server certificates file
*
* @return null|string certificates
*/
public function exportCertificates() {
$fileName = $this->getSSLCaCertPath();
if ($fileName === null) {
return null;
}
$content = null;
$handle = @fopen($fileName, "r");
if ($handle) {
$content = fread($handle, 10000000);
fclose($handle);
}
return $content;
}
/**
* Imports the server certificates.
*
* @param null|string $certsContent certificates
* @throws LAMException write to file failed
*/
public function importCertificates($certsContent) {
$fileName = $this->getSSLCaCertPath();
if (empty($certsContent)) {
if ($fileName !== null) {
unlink($fileName);
}
return;
}
$fileName = $this->getInternalSSLCaCertFileName();
$handle = @fopen($fileName, "wb");
if ($handle) {
fputs($handle, $certsContent);
fclose($handle);
@chmod($fileName, 0600);
}
else {
throw new LAMException(printf(_('Unable to write file %s.'), $fileName));
}
}
/**
* Reloads preferences from config file config.cfg
*

View File

@ -3082,6 +3082,15 @@ class htmlStatusMessage extends htmlElement {
return array();
}
/**
* Returns the message type.
*
* @return String type
*/
public function getType() {
return $this->type;
}
}
/**
@ -3644,6 +3653,8 @@ class htmlSpan extends htmlElement {
/** htmlElement that generates inner content */
private $content = null;
/** onclick handler */
private $onclick = null;
/**
* Constructor.
@ -3674,13 +3685,27 @@ class htmlSpan extends htmlElement {
if (($this->cssClasses != null) && (sizeof($this->cssClasses) > 0)) {
$classesValue = ' class="' . implode(' ', $this->cssClasses) . '"';
}
echo '<span' . $classesValue . '>';
$onclickHandler = '';
if (!empty($this->onclick)) {
$onclickHandler = ' onclick="' . $this->onclick . '"';
}
echo '<span' . $classesValue . $onclickHandler . '>';
if ($this->content != null) {
$return = $this->content->generateHTML($module, $input, $values, $restricted, $tabindex, $scope);
}
echo '</span>';
return $return;
}
/**
* Sets the onclick event.
*
* @param string $event event handler code
*/
public function setOnclick($event) {
$this->onclick = $event;
}
}
/**
@ -4715,6 +4740,8 @@ class htmlResponsiveInputCheckbox extends htmlInputCheckbox {
private $renderParentHtml = false;
/** long label */
private $longLabel = false;
/** label after checkbox */
private $labelAfterCheckbox = false;
/**
* Constructor.
@ -4751,14 +4778,16 @@ class htmlResponsiveInputCheckbox extends htmlInputCheckbox {
$row = new htmlResponsiveRow();
$tabletColumnsLabel = 6;
$tabletColumnsBox = 6;
$mobileColumnsLabel = 10;
$mobileColumnsBox = 2;
if ($this->longLabel) {
$tabletColumnsLabel = 10;
$tabletColumnsBox = 2;
}
// label text
$labelGroup = new htmlGroup();
$labelGroup->addElement(new htmlOutputText($this->label));
$row->add($labelGroup, 10, $tabletColumnsLabel, $tabletColumnsLabel, 'responsiveLabel');
$text = new htmlSpan(new htmlOutputText($this->label));
$text->setCSSClasses($this->cssClasses);
$text->setOnclick('jQuery(\'#' . $this->name . '\').prop(\'checked\',!jQuery(\'#' . $this->name . '\').prop(\'checked\')); jQuery(\'#' . $this->name . '\').change();');
// input field
$fieldGroup = new htmlGroup();
$fieldGroup->addElement($this);
@ -4767,7 +4796,14 @@ class htmlResponsiveInputCheckbox extends htmlInputCheckbox {
$helpLink->setCSSClasses(array('margin-left5 align-unset-img'));
$fieldGroup->addElement($helpLink);
}
$row->add($fieldGroup, 2, $tabletColumnsBox, $tabletColumnsBox, 'responsiveField nowrap');
if ($this->labelAfterCheckbox) {
$row->add($fieldGroup, $mobileColumnsBox, $tabletColumnsBox, $tabletColumnsBox, 'responsiveLabel nowrap');
$row->add($text, $mobileColumnsLabel, $tabletColumnsLabel, $tabletColumnsLabel, 'responsiveField');
}
else {
$row->add($text, $mobileColumnsLabel, $tabletColumnsLabel, $tabletColumnsLabel, 'responsiveLabel');
$row->add($fieldGroup, $mobileColumnsBox, $tabletColumnsBox, $tabletColumnsBox, 'responsiveField nowrap');
}
return $row->generateHTML($module, $input, $values, $restricted, $tabindex, $scope);
}
@ -4779,6 +4815,15 @@ class htmlResponsiveInputCheckbox extends htmlInputCheckbox {
return '.row';
}
/**
* Sets if the label should be shown after the checkbox instead before it.
*
* @param bool $labelAfterCheckbox show label after box
*/
public function setLabelAfterCheckbox($labelAfterCheckbox = true) {
$this->labelAfterCheckbox = $labelAfterCheckbox;
}
}
/**

View File

@ -759,7 +759,7 @@ class lamList {
$selAccounts[] = $id;
}
// get possible PDF structures
$pdf_structures = \LAM\PDF\getPDFStructures($this->type->getId());
$pdf_structures = \LAM\PDF\getPDFStructures($this->type->getId(), $_SESSION['config']->getName());
$this->printHeader();

View File

@ -1454,7 +1454,7 @@ class accountContainer {
*/
private function loadProfileIfRequested() {
if (isset($_POST['accountContainerLoadProfile']) && isset($_POST['accountContainerSelectLoadProfile'])) {
$profile = \LAM\PROFILES\loadAccountProfile($_POST['accountContainerSelectLoadProfile'], $this->type->getId());
$profile = \LAM\PROFILES\loadAccountProfile($_POST['accountContainerSelectLoadProfile'], $this->type->getId(), $_SESSION['config']->getName());
$this->lastLoadedProfile = $_POST['accountContainerSelectLoadProfile'];
// pass profile to each module
$modules = array_keys($this->module);
@ -1775,7 +1775,7 @@ class accountContainer {
$this->lastLoadedProfile = $cookieProfileName;
}
}
$profile = \LAM\PROFILES\loadAccountProfile($profileName, $this->type->getId());
$profile = \LAM\PROFILES\loadAccountProfile($profileName, $this->type->getId(), $_SESSION['config']->getName());
// pass profile to each module
$modules = array_keys($this->module);
foreach ($modules as $module) $this->module[$module]->load_profile($profile);

View File

@ -61,7 +61,7 @@ include_once('pdfstruct.inc');
function createModulePDF($accounts, $pdf_structure, $font, $returnAsString = false) {
$account_type = $accounts[0]->get_type();
// Get PDF structure from xml file
$reader = new PDFStructureReader();
$reader = new PDFStructureReader($_SESSION['config']->getName());
$structure = $reader->read($account_type->getId(), $pdf_structure);
// get list of PDF keys
$pdfKeys = array();

View File

@ -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");
@ -44,18 +49,15 @@ include_once(__DIR__ . "/ldap.inc");
* @param string $typeId the account type
* @param string $profile server profile name
*
* @return array All available PDF structure definitions for the submitted account
* @return string[] All available PDF structure definitions for the submitted account
* scope. Each entry is a string being the filename that may be passed to the
* createModulePDF() function as second argument.
*/
function getPDFStructures($typeId, $profile = null) {
function getPDFStructures($typeId, $profile) {
$return = array();
if (!preg_match('/[a-zA-Z]+/', $typeId)) {
return null;
}
if (!isset($profile)) {
$profile = $_SESSION['config']->getName();
}
$path = dirname(__FILE__) . '/../config/pdf/' . $profile;
if(is_dir($path)) {
$dirHandle = opendir($path);
@ -75,14 +77,14 @@ function getPDFStructures($typeId, $profile = null) {
*
* @param string $typeId account type
* @param string $name Name of definition to delete
*
* @param string $serverProfileName server profile name
* @return boolean True if file was deleted or false if a problem occurred.
*/
function deletePDFStructure($typeId, $name) {
function deletePDFStructure($typeId, $name, $serverProfileName) {
if (!isValidPDFStructureName($name) || !preg_match('/[a-zA-Z]+/',$typeId)) {
return false;
}
$file = dirname(__FILE__) . '/../config/pdf/' . $_SESSION['config']->getName() . '/' . $name . '.' . $typeId . '.xml';
$file = dirname(__FILE__) . '/../config/pdf/' . $serverProfileName . '/' . $name . '.' . $typeId . '.xml';
if(is_file($file) && is_writable($file)) {
return unlink($file);
}
@ -95,11 +97,12 @@ function deletePDFStructure($typeId, $name) {
/**
* This function returns an array with all aviliable logo images.
*
* @return array list of logo files
* @param string $serverProfileName server profile name
* @return array list of logo files (array('filename' => PATH, 'infos' => array(width, height)))
*/
function getAvailableLogos() {
function getAvailableLogos($serverProfileName) {
$return = array();
$dirPath = dirname(__FILE__) . '/../config/pdf/' . $_SESSION['config']->getName() . '/logos/';
$dirPath = dirname(__FILE__) . '/../config/pdf/' . $serverProfileName . '/logos/';
$dirHandle = opendir($dirPath);
while($file = readdir($dirHandle)) {
if(!is_dir($file) && $file != '.' && $file != '..' && preg_match('/\\.(jpg|png)$/i',$file)) {
@ -120,7 +123,7 @@ function getAvailableLogos() {
* @param \LAM\TYPES\ConfiguredType $sourceType source type
* @param string $sourceStructureName structure name
* @param \LAM\TYPES\ConfiguredType $targetType target type
* @throws Exception
* @throws LAMException error during copy
*/
function copyStructure($sourceType, $sourceStructureName, $targetType) {
if (!isValidPDFStructureName($sourceStructureName)) {
@ -165,13 +168,17 @@ function copyStructureToTemplates($sourceType, $sourceName) {
*
* @param String $file full path of temporary file
* @param String $name file name
* @return StatusMessage status message to display
* @param string $serverProfileName server profile name
* @return htmlStatusMessage status message to display
*/
function uploadPDFLogo($file, $name) {
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".'));
}
$dirPath = dirname(__FILE__) . '/../config/pdf/' . $_SESSION['config']->getName() . '/logos/';
if ($serverProfileName === GLOBAL_PROFILE) {
$serverProfileName = '../templates/pdf';
}
$dirPath = dirname(__FILE__) . '/../config/pdf/' . $serverProfileName . '/logos/';
$success = copy($file, $dirPath . '/' . $name);
if ($success) {
return new htmlStatusMessage('INFO', _('Uploaded logo file.'), $name);
@ -185,12 +192,13 @@ function uploadPDFLogo($file, $name) {
* Deletes a PDF logo file.
*
* @param String $name file name
* @param string $serverProfileName server profile name
* @return StatusMessage status message to display
*/
function deletePDFLogo($name) {
function deletePDFLogo($name, $serverProfileName) {
// check if valid file
$found = false;
$logos = getAvailableLogos();
$logos = getAvailableLogos($serverProfileName);
foreach ($logos as $logo) {
if ($logo['filename'] === $name) {
$found = true;
@ -203,9 +211,9 @@ function deletePDFLogo($name) {
// check if still in use
$typeManager = new \LAM\TYPES\TypeManager();
$activeTypes = $typeManager->getConfiguredTypes();
$reader = new PDFStructureReader();
$reader = new PDFStructureReader($serverProfileName);
foreach ($activeTypes as $type) {
$structures = getPDFStructures($type->getId());
$structures = getPDFStructures($type->getId(), $serverProfileName);
foreach ($structures as $structure) {
try {
$data = $reader->read($type->getId(), $structure);
@ -220,7 +228,7 @@ function deletePDFLogo($name) {
}
}
// delete file
$dirPath = dirname(__FILE__) . '/../config/pdf/' . $_SESSION['config']->getName() . '/logos/';
$dirPath = dirname(__FILE__) . '/../config/pdf/' . $serverProfileName . '/logos/';
$success = @unlink($dirPath . '/' . $name);
if ($success) {
return new htmlStatusMessage('INFO', _('Logo file deleted.'), $name);
@ -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';
$templateDir = @dir($templatePath);
if ($templateDir) {
$entry = $templateDir->read();
while ($entry){
$path = $basePath . '/logos/' . $entry;
if ((strpos($entry, '.') !== 0) && !is_file($path)) {
$template = $templatePath . '/' . $entry;
$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){
$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;
}
/**
@ -301,6 +351,22 @@ function installPDFTemplates() {
*/
class PDFStructureReader {
private $serverProfileName;
/**
* Constructor.
*
* @param $serverProfileName server profile name
*/
public function __construct($serverProfileName) {
if ($serverProfileName === GLOBAL_PROFILE) {
$this->serverProfileName = '../templates/pdf';
}
else {
$this->serverProfileName = $serverProfileName;
}
}
/**
* Reads a PDF structure.
*
@ -324,7 +390,7 @@ class PDFStructureReader {
* @return string file name
*/
protected function getFileName($typeId, $name) {
return dirname(__FILE__) . '/../config/pdf/' . $_SESSION['config']->getName() . '/' . $name . '.' . $typeId . '.xml';
return dirname(__FILE__) . '/../config/pdf/' . $this->serverProfileName . '/' . $name . '.' . $typeId . '.xml';
}
/**
@ -334,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();
@ -411,12 +478,29 @@ class PDFStructureReader {
*/
class PDFStructureWriter {
private $serverProfileName;
/**
* Constructor.
*
* @param string $serverProfileName server profile name
*/
public function __construct($serverProfileName) {
if ($serverProfileName === GLOBAL_PROFILE) {
$this->serverProfileName = '../templates/pdf';
}
else {
$this->serverProfileName = $serverProfileName;
}
}
/**
* Writes the PDF structure to disk.
*
* @param string $typeId type ID
* @param string $name structure name
* @param PDFStructure $structure structure
* @throws LAMException error during write
*/
public function write($typeId, $name, $structure) {
$fileName = $this->getFileName($typeId, $name);
@ -430,16 +514,18 @@ class PDFStructureWriter {
* @param string $typeId type ID
* @param string $name structure name
* @return string file name
* @throws LAMException file not valid or not writable
*/
protected function getFileName($typeId, $name) {
if (!isValidPDFStructureName($name) || !preg_match('/[a-zA-Z]+/', $typeId)) {
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/' . $_SESSION['config']->getName())) {
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/' . $_SESSION['config']->getName() . '/' . $name . '.' . $typeId . '.xml';
return $baseDir . '/' . $name . '.' . $typeId . '.xml';
}
/**
@ -488,6 +574,7 @@ class PDFStructureWriter {
*
* @param string $xml XML
* @param string $file file name
* @throws LAMException error during write
*/
protected function writeXML($xml, $file) {
$handle = @fopen($file,'w');
@ -520,6 +607,57 @@ class PDFStructure {
private $sections = array();
/**
* Returns an array representation of the structure.
*
* @return array export data
*/
public function export() {
$data = array();
$data['title'] = $this->title;
$data['foldingMarks'] = $this->foldingMarks;
$data['logo'] = $this->logo;
$data['sections'] = array();
foreach($this->sections as $section) {
$type = ($section instanceof PDFTextSection) ? 'text' : 'entry';
$sectionData = $section->export();
$data['sections'][] = array(
'type' => $type,
'data' => $sectionData
);
}
return $data;
}
/**
* Imports an array representation of the structure.
*
* @param array $data import data
*/
public function import($data) {
if (isset($data['title'])) {
$this->title = $data['title'];
}
if (isset($data['foldingMarks'])) {
$this->foldingMarks = $data['foldingMarks'];
}
if (isset($data['logo'])) {
$this->logo = $data['logo'];
}
if (isset($data['sections'])) {
foreach($data['sections'] as $section) {
if ($section['type'] === 'text') {
$this->sections[] = new PDFTextSection($section['data']);
}
else {
$entrySection = new PDFEntrySection(null);
$entrySection->import($section['data']);
$this->sections[] = $entrySection;
}
}
}
}
/**
* Returns the logo file path.
*
@ -612,6 +750,15 @@ class PDFTextSection {
$this->text = $text;
}
/**
* Exports the section.
*
* @return string text
*/
public function export() {
return $this->getText();
}
/**
* Returns the text.
*
@ -631,7 +778,7 @@ class PDFTextSection {
class PDFEntrySection {
private $title;
private $entries;
private $entries = array();
/**
* Constructor
@ -642,6 +789,37 @@ class PDFEntrySection {
$this->title = $title;
}
/**
* Exports the section.
*
* @return array export data
*/
public function export() {
$data = array();
$data['title'] = $this->title;
$data['entries'] = array();
foreach($this->getEntries() as $entry) {
$data['entries'][] = $entry->getKey();
}
return $data;
}
/**
* Imports the section.
*
* @param array $data import data
*/
public function import($data) {
if (isset($data['title'])) {
$this->title = $data['title'];
}
if ($data['entries']) {
foreach($data['entries'] as $entry) {
$this->entries[] = new PDFSectionEntry($entry);
}
}
}
/**
* Returns if the title is an attribute value.
*

652
lam/lib/persistence.inc Normal file
View File

@ -0,0 +1,652 @@
<?php
namespace LAM\PERSISTENCE;
use LAM\PDF\PDFStructure;
use LAM\PDF\PDFStructureReader;
use LAM\PDF\PDFStructureWriter;
use LAMCfgMain;
use LAMConfig;
use LAMException;
use selfServiceProfile;
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;
use function LAM\PROFILES\installTemplateAccountProfile;
use function LAM\PROFILES\loadAccountProfile;
use function LAM\PROFILES\loadTemplateAccountProfile;
use function LAM\PROFILES\saveAccountProfile;
/*
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
Copyright (C) 2020 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
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
*/
/**
* This file includes functions to manage the persistence of LAM's configuration files.
*
* @package configuration
* @author Roland Gruber
*/
include_once __DIR__ . '/config.inc';
include_once __DIR__ . '/profiles.inc';
/**
* Exporter for LAM's configuration data.
*/
class ConfigDataExporter {
/**
* Exports LAM's configuration data in JSON format.
* @throws LAMException error during export
*/
public function exportAsJson() {
$mainCfg = $this->_getMainConfiguration();
$jsonData = array();
$jsonData['mainConfig'] = $this->_getMainConfigData($mainCfg);
$jsonData['certificates'] = $this->_getCertificates($mainCfg);
$serverProfileNames = getConfigProfiles();
$serverProfiles = array();
foreach ($serverProfileNames as $serverProfileName) {
$serverProfiles[$serverProfileName] = new \LAMConfig($serverProfileName);
}
$jsonData['serverProfiles'] = $this->_getServerProfiles($serverProfiles);
$jsonData['accountProfiles'] = $this->_getAccountProfiles($serverProfiles);
$jsonData['accountProfileTemplates'] = $this->_getAccountProfileTemplates();
$jsonData['pdfProfiles'] = $this->_getPdfProfiles($serverProfiles);
$jsonData['pdfProfileTemplates'] = $this->_getPdfProfileTemplates();
$jsonData['selfServiceProfiles'] = $this->_getSelfServiceProfiles();
/**
* TODO
*
* webauthn
*/
return json_encode($jsonData);
}
/**
* Returns the main configuration.
*
* @return LAMCfgMain main config
*/
public function _getMainConfiguration() {
return new LAMCfgMain();
}
/**
* Internal function to read master configuration.
*
* @param LAMCfgMain $mainCfg main config
* @return array data
*/
public function _getMainConfigData($mainCfg) {
return $mainCfg->exportData();
}
/**
* Returns the certificate file content.
*
* @param LAMCfgMain $mainCfg main config
* @return array data
*/
public function _getCertificates($mainCfg) {
return $mainCfg->exportCertificates();
}
/**
* Returns the content of the server profiles.
*
* @param array $serverProfiles list of server profiles (name => object)
* @return array $data
*/
public function _getServerProfiles($serverProfiles) {
$data = array();
foreach ($serverProfiles as $profileName => $serverProfile) {
$data[$profileName] = $serverProfile->exportData();
}
return $data;
}
/**
* Returns the content of the account profiles.
*
* @param array $serverProfiles list of server profiles (name => object)
* @return array $data
*/
public function _getAccountProfiles($serverProfiles) {
$data = array();
foreach ($serverProfiles as $profileName => $serverProfile) {
foreach ($serverProfile->get_ActiveTypes() as $typeId) {
$accountProfileNames = getAccountProfiles($typeId, $profileName);
foreach ($accountProfileNames as $accountProfileName) {
$accountProfile = loadAccountProfile($accountProfileName, $typeId, $profileName);
$data[$profileName][$typeId][$accountProfileName] = $accountProfile;
}
}
}
return $data;
}
/**
* Returns the content of the account profile templates.
*
* @return array $data
* @throws LAMException error reading template
*/
public function _getAccountProfileTemplates() {
$data = array();
$accountProfileTemplateNames = getProfileTemplateNames();
foreach ($accountProfileTemplateNames as $scope => $templateNames) {
foreach ($templateNames as $templateName) {
$accountProfileTemplate = loadTemplateAccountProfile($templateName, $scope);
$data[$scope][$templateName] = $accountProfileTemplate;
}
}
return $data;
}
/**
* Returns the content of the PDF profiles.
*
* @param array $serverProfiles list of server profiles (name => object)
* @return array $data
*/
public function _getPdfProfiles($serverProfiles) {
$data = array();
foreach ($serverProfiles as $profileName => $serverProfile) {
foreach ($serverProfile->get_ActiveTypes() as $typeId) {
$pdfProfileNames = getPDFStructures($typeId, $profileName);
$reader = new PDFStructureReader($profileName);
foreach ($pdfProfileNames as $pdfProfileName) {
$pdfStructure = $reader->read($typeId, $pdfProfileName);
$data[$profileName]['structures'][$typeId][$pdfProfileName] = $pdfStructure->export();
}
}
$logoData = getAvailableLogos($profileName);
foreach ($logoData as $logo) {
$logoFileName = $logo['filename'];
$logoPath = __DIR__ . '/../config/pdf/' . $profileName . '/logos/' . $logoFileName;
$handle = fopen($logoPath, 'r');
$logoBinary = fread($handle, 100000000);
fclose($handle);
$data[$profileName]['logos'][$logoFileName] = base64_encode($logoBinary);
}
}
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;
}
/**
* Returns the content of the self service profiles.
*
* @return array data
*/
public function _getSelfServiceProfiles() {
$data = array();
$profileTypes = getSelfServiceProfiles();
foreach ($profileTypes as $profileType => $profileNames) {
foreach ($profileNames as $profileName) {
$profile = loadSelfServiceProfile($profileName, $profileType);
if ($profile === false) {
continue;
}
$data[$profileType][$profileName] = $profile->export();
}
}
return $data;
}
}
/**
* Importer for LAM's configuration data.
*/
class ConfigDataImporter {
/**
* Returns a list of possible import objects.
*
* @param string $json JSON data
* @return ImporterStep[] steps
* @throws LAMException if invalid format
*/
public function getPossibleImportSteps($json) {
$data = json_decode($json, true);
if ($data === null) {
throw new LAMException(_('Unable to read import file.'));
}
$steps = array();
foreach ($data as $key => $value) {
switch ($key) {
case 'mainConfig':
$steps[] = new ImporterStep(_('General settings'), 'mainConfig', $value);
break;
case 'certificates':
$steps[] = new ImporterStep(_('SSL certificates'), 'certificates', $value);
break;
case 'serverProfiles':
$mainStep = new ImporterStep(_('Server profiles'), 'serverProfiles', $value);
foreach ($value as $profileName => $profileData) {
$mainStep->addSubStep(new ImporterStep($profileName, 'serverProfile_' . $profileName, $profileData));
}
$steps[] = $mainStep;
break;
case 'accountProfiles':
$mainStep = new ImporterStep(_('Account profiles'), 'accountProfiles', $value);
foreach ($value as $profileName => $profileData) {
$mainStep->addSubStep(new ImporterStep($profileName, 'accountProfile_' . $profileName, $profileData));
}
$steps[] = $mainStep;
break;
case 'accountProfileTemplates':
$steps[] = new ImporterStep(_('Account profiles') . ' - ' . _('Global templates'), 'accountProfileTemplates', $value);
break;
case 'pdfProfiles':
$mainStep = new ImporterStep(_('PDF structures'), 'pdfProfiles', $value);
foreach ($value as $profileName => $profileData) {
$mainStep->addSubStep(new ImporterStep($profileName, 'pdfProfile_' . $profileName, $profileData));
}
$steps[] = $mainStep;
break;
case 'pdfProfileTemplates':
$steps[] = new ImporterStep(_('PDF structures') . ' - ' . _('Global templates'), 'pdfProfileTemplates', $value);
break;
case 'selfServiceProfiles':
$steps[] = new ImporterStep(_('Self service profiles'), 'selfServiceProfiles', $value);
break;
default:
logNewMessage(LOG_WARNING, 'Unknown import type: ' . $key);
}
}
if (empty($steps)) {
throw new LAMException(_('Unable to read import file.'));
}
return $steps;
}
/**
* Runs the actual import.
*
* @param ImporterStep[] $steps import steps
* @throws LAMException if error occurred
*/
public function runImport($steps) {
foreach ($steps as $step) {
if (!$step->isActive()) {
continue;
}
$key = $step->getKey();
switch ($key) {
case 'mainConfig':
$this->importMainConfig($step->getValue());
break;
case 'certificates':
$this->importCertificates($step->getValue());
break;
case 'serverProfiles':
$this->importServerProfiles($step);
break;
case 'accountProfiles':
$this->importAccountProfiles($step);
break;
case 'accountProfileTemplates':
$this->importAccountProfileTemplates($step);
break;
case 'pdfProfiles':
$this->importPdfProfiles($step);
break;
case 'pdfProfileTemplates':
$this->importPdfProfileTemplates($step);
break;
case 'selfServiceProfiles':
$this->importSelfServiceProfiles($step);
break;
default:
logNewMessage(LOG_WARNING, 'Unknown import type: ' . $key);
}
}
}
/**
* Imports the main configuration.
*
* @param array $data main config data
* @throws LAMException error during import
*/
private function importMainConfig($data) {
$cfgMain = new LAMCfgMain();
$cfgMain->importData($data);
$cfgMain->save();
}
/**
* Imports the SSL certificates.
*
* @param null|string $data file content
* @throws LAMException error during import
*/
private function importCertificates($data) {
$cfgMain = new LAMCfgMain();
$cfgMain->importCertificates($data);
}
/**
* Imports the server profiles.
*
* @param ImporterStep $step step
* @throws LAMException error during import
*/
private function importServerProfiles($step) {
$failedProfiles = array();
foreach ($step->getSubSteps() as $profileStep) {
if (!$profileStep->isActive()) {
continue;
}
$data = $profileStep->getValue();
$profileName = str_replace('serverProfile_', '', $profileStep->getKey());
$serverProfile = new LAMConfig($profileName);
$serverProfile->importData($data);
$result = $serverProfile->save();
if ($result === LAMConfig::SAVE_FAIL) {
$failedProfiles[] = $profileName;
}
}
if (!empty($failedProfiles)) {
throw new LAMException(_('Unable to save server profile.'), implode(', ', $failedProfiles));
}
}
/**
* Imports the account profiles.
*
* @param ImporterStep $step step
* @throws LAMException error during import
*/
private function importAccountProfiles($step) {
$failedProfiles = array();
foreach ($step->getSubSteps() as $profileStep) {
if (!$profileStep->isActive()) {
continue;
}
$data = $profileStep->getValue();
$serverProfileName = str_replace('accountProfile_', '', $profileStep->getKey());
$serverProfile = new LAMConfig($serverProfileName);
foreach ($data as $typeId => $accountProfiles) {
foreach ($accountProfiles as $accountProfileName => $accountProfileData) {
$result = saveAccountProfile($accountProfileData, $accountProfileName, $typeId, $serverProfile);
if (!$result) {
$failedProfiles[] = $serverProfileName . ':' . $typeId . ':' . $accountProfileName;
}
}
}
}
if (!empty($failedProfiles)) {
throw new LAMException(_('Unable to save account profile.'), implode(', ', $failedProfiles));
}
}
/**
* Imports the account profile templates.
*
* @param ImporterStep $step step
* @throws LAMException error during import
*/
private function importAccountProfileTemplates($step) {
$data = $step->getValue();
foreach ($data as $typeId => $accountProfileTemplates) {
foreach ($accountProfileTemplates as $accountProfileTemplateName => $accountProfileData) {
installTemplateAccountProfile($typeId, $accountProfileTemplateName, $accountProfileData);
}
}
}
/**
* Imports the PDF profiles.
*
* @param ImporterStep $step step
* @throws LAMException error during import
*/
private function importPdfProfiles($step) {
$failedProfiles = array();
foreach ($step->getSubSteps() as $profileStep) {
if (!$profileStep->isActive()) {
continue;
}
$data = $profileStep->getValue();
$serverProfileName = str_replace('pdfProfile_', '', $profileStep->getKey());
if (isset($data['structures'])) {
$writer = new PDFStructureWriter($serverProfileName);
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) {
logNewMessage(LOG_ERR, $e->getTitle() . ' ' . $e->getMessage());
$failedProfiles[] = $serverProfileName . ':' . $typeId . ':' . $pdfProfileName;
}
}
}
}
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);
uploadPDFLogo($tempFilePath, $logoFileName, $serverProfileName);
unlink($tempFilePath);
}
}
}
if (!empty($failedProfiles)) {
throw new LAMException(_('Could not save PDF structure, access denied.'), implode(', ', $failedProfiles));
}
}
/**
* 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));
}
}
/**
* Imports the self service profiles.
*
* @param ImporterStep $step importer step
* @throws LAMException error saving profiles
*/
private function importSelfServiceProfiles($step) {
$failedNames = array();
$data = $step->getValue();
foreach ($data as $typeId => $profileData) {
foreach ($profileData as $profileName => $currentProfileData) {
$profile = selfServiceProfile::import($currentProfileData);
$result = saveSelfServiceProfile($profileName, $typeId, $profile);
if (!$result) {
$failedNames[] = $profileName;
}
}
}
if (!empty($failedNames)) {
throw new LAMException(_('Unable to save profile!'), implode(', ', $failedNames));
}
}
}
/**
* Step of the import process.
*/
class ImporterStep {
private $label;
private $key;
private $value;
private $active = false;
private $subSteps = array();
/**
* Constructor.
*
* @param string $label label
* @param string $key key
* @param array $value value
*/
public function __construct($label, $key, $value) {
$this->label = $label;
$this->key = $key;
$this->value = $value;
}
/**
* Returns the label.
*
* @return string label
*/
public function getLabel() {
return $this->label;
}
/**
* Returns the key.
*
* @return string key
*/
public function getKey() {
return $this->key;
}
/**
* Returns if this step should be executed.
*
* @return bool active
*/
public function isActive(): bool {
return $this->active;
}
/**
* Sets if this step should be executed.
*
* @param bool $active active
*/
public function setActive(bool $active) {
$this->active = $active;
}
/**
* Returns the value.
*
* @return string value
*/
public function getValue() {
return $this->value;
}
/**
* Adds a sub-step.
*
* @param ImporterStep $subStep sub-step
*/
public function addSubStep($subStep) {
$this->subSteps[] = $subStep;
}
/**
* Returns the sub-steps.
*
* @return ImporterStep[] sub-steps
*/
public function getSubSteps() {
return $this->subSteps;
}
}

View File

@ -1,5 +1,6 @@
<?php
namespace LAM\PROFILES;
use LAM\TYPES\TypeManager;
use \LAMException;
/*
@ -45,7 +46,6 @@ function getAccountProfiles($typeId, $profile = null) {
$dir = @dir(dirname(__FILE__) . "/../config/profiles/" . $profile);
$ret = array();
$pos = 0;
if ($dir) {
$entry = $dir->read();
while ($entry){
@ -83,26 +83,41 @@ function profileExists($name, $typeId) {
*
* @param string $profile name of the profile (without .<scope> extension)
* @param string $typeId account type
* @param string $serverProfileName server profile name
* @return array hash array (attribute => value)
*/
function loadAccountProfile($profile, $typeId) {
$typeManager = new \LAM\TYPES\TypeManager();
$type = $typeManager->getConfiguredType($typeId);
if (!isValidProfileName($profile) || !preg_match("/^[a-z0-9_]+$/i", $typeId) || ($type == null)) {
return false;
function loadAccountProfile($profile, $typeId, $serverProfileName) {
if (!isValidProfileName($profile) || !preg_match("/^[a-z0-9_]+$/i", $typeId)) {
logNewMessage(LOG_NOTICE, "Invalid account profile name: $serverProfileName:$profile:$typeId");
return array();
}
$file = substr(__FILE__, 0, strlen(__FILE__) - 17) . "/config/profiles/" . $serverProfileName . '/' . $profile . "." . $typeId;
try {
return readAccountProfileFile($file);
} catch (LAMException $e) {
StatusMessage('ERROR', $e->getTitle(), $e->getMessage());
}
return array();
}
/**
* Reads an account profile from the given file name.
*
* @param string $fileName file name
* @return array hash array (attribute => value)
* @throws LAMException error reading file
*/
function readAccountProfileFile($fileName) {
$settings = array();
$file = substr(__FILE__, 0, strlen(__FILE__) - 17) . "/config/profiles/" . $_SESSION['config']->getName() . '/' . $profile . "." . $typeId;
if (is_file($file)) {
$file = @fopen($file, "r");
if (is_file($fileName)) {
$file = @fopen($fileName, "r");
if ($file) {
while (!feof($file)) {
$line = fgets($file, 1024);
if (($line === false) || ($line == "\n") || ($line[0] == "#")) {
if (($line === false) || ($line == '') || ($line == "\n") || ($line[0] == "#")) {
continue; // ignore comments
}
// search keywords
$parts = array();
$parts = explode(": ", $line);
if (sizeof($parts) == 2) {
$option = $parts[0];
@ -113,16 +128,16 @@ function loadAccountProfile($profile, $typeId) {
}
}
fclose($file);
}
else {
StatusMessage("ERROR", "", _("Unable to load profile!") . " " . $file);
}
}
else {
StatusMessage("ERROR", "", _("Unable to load profile!") . " " . $file);
}
return $settings;
}
else {
throw new LAMException(_("Unable to load profile!"), $fileName);
}
}
else {
throw new LAMException(_("Unable to load profile!"), $fileName);
}
}
/**
* Saves an hash array (attribute => value) to an account profile
@ -132,27 +147,40 @@ function loadAccountProfile($profile, $typeId) {
* @param array $attributes hash array (attribute => value)
* @param string $profile name of the account profile (without .<scope> extension)
* @param string $typeId account type
* @param \LAMConfig $serverProfile server profile
* @return boolean true, if saving succeeded
*/
function saveAccountProfile($attributes, $profile, $typeId) {
if (!isLoggedIn()) return false;
function saveAccountProfile($attributes, $profile, $typeId, $serverProfile) {
// check profile name and type id
$typeManager = new \LAM\TYPES\TypeManager();
$typeManager = new TypeManager($serverProfile);
$type = $typeManager->getConfiguredType($typeId);
if (!isValidProfileName($profile) || !preg_match("/^[a-z0-9_]+$/i", $typeId) || ($type == null)) {
logNewMessage(LOG_NOTICE, 'Invalid account profile name: ' . $profile . ':' . $typeId);
return false;
}
if (!is_array($attributes)) {
logNewMessage(LOG_NOTICE, 'Invalid account profile data');
return false;
}
$path = substr(__FILE__, 0, strlen(__FILE__) - 17) . "/config/profiles/" . $_SESSION['config']->getName() . '/' . $profile . "." . $typeId;
$file = @fopen($path, "w");
$path = substr(__FILE__, 0, strlen(__FILE__) - 17) . "/config/profiles/" . $serverProfile->getName() . '/' . $profile . "." . $typeId;
return writeProfileDataToFile($path, $attributes);
}
/**
* Writes the profile data to the given file.
*
* @param string $fileName file name
* @param array $data profile data
* @return bool writing was ok
*/
function writeProfileDataToFile($fileName, $data) {
$file = @fopen($fileName, "w");
if ($file) {
// write attributes
$keys = array_keys($attributes);
$keys = array_keys($data);
for ($i = 0; $i < sizeof($keys); $i++) {
if (isset($attributes[$keys[$i]])) {
$line = $keys[$i] . ": " . implode("+::+", $attributes[$keys[$i]]) . "\n";
if (isset($data[$keys[$i]])) {
$line = $keys[$i] . ": " . implode("+::+", $data[$keys[$i]]) . "\n";
}
else {
$line = $keys[$i] . ": \n";
@ -163,6 +191,7 @@ function saveAccountProfile($attributes, $profile, $typeId) {
fclose($file);
}
else {
logNewMessage(LOG_NOTICE, 'Unable to open account profile file: ' . $fileName);
return false;
}
return true;
@ -179,7 +208,7 @@ function delAccountProfile($file, $typeId) {
if (!isLoggedIn()) {
return false;
}
$typeManager = new \LAM\TYPES\TypeManager();
$typeManager = new TypeManager();
$type = $typeManager->getConfiguredType($typeId);
if (!isValidProfileName($file) || !preg_match("/^[a-z0-9_]+$/i", $typeId) || ($type == null)) {
return false;
@ -206,7 +235,7 @@ function isValidProfileName($name) {
* @param \LAM\TYPES\ConfiguredType $sourceType source type
* @param string $sourceProfileName profile name
* @param \LAM\TYPES\ConfiguredType $targetType target type
* @throws Exception
* @throws LAMException error during copy
*/
function copyAccountProfile($sourceType, $sourceProfileName, $targetType) {
if (!isValidProfileName($sourceProfileName)) {
@ -229,7 +258,7 @@ function copyAccountProfile($sourceType, $sourceProfileName, $targetType) {
*
* @param \LAM\TYPES\ConfiguredType $sourceType source type
* @param string $sourceProfileName profile name
* @throws Exception
* @throws LAMException error during copy
*/
function copyAccountProfileToTemplates($sourceType, $sourceProfileName) {
if (!isValidProfileName($sourceProfileName)) {
@ -250,7 +279,34 @@ function copyAccountProfileToTemplates($sourceType, $sourceProfileName) {
* Installs template profiles to the current server profile.
*/
function installProfileTemplates() {
$templatePath = dirname(__FILE__) . '/../config/templates/profiles';
$allTemplates = getProfileTemplateNames();
$basePath = dirname(__FILE__) . '/../config/profiles/' . $_SESSION['config']->getName();
if (!file_exists($basePath)) {
mkdir($basePath, 0700, true);
}
$typeManager = new TypeManager();
foreach ($typeManager->getConfiguredTypes() as $type) {
if (empty($allTemplates[$type->getScope()])) {
continue;
}
foreach ($allTemplates[$type->getScope()] as $templateName) {
$path = $basePath . '/' . $templateName . '.' . $type->getId();
if (!is_file($path)) {
$template = getProfileTemplateFileName($type->getScope(), $templateName);
logNewMessage(LOG_DEBUG, 'Copy template ' . $template . ' to ' . $path);
@copy($template, $path);
}
}
}
}
/**
* Returns a list of all global profile templates.
*
* @return array names (array('user' => array('default', 'extra')))
*/
function getProfileTemplateNames() {
$templatePath = __DIR__ . '/../config/templates/profiles';
$templateDir = @dir($templatePath);
$allTemplates = array();
if ($templateDir) {
@ -265,24 +321,54 @@ function installProfileTemplates() {
$entry = $templateDir->read();
}
}
$basePath = dirname(__FILE__) . '/../config/profiles/' . $_SESSION['config']->getName();
if (!file_exists($basePath)) {
mkdir($basePath, 0700, true);
return $allTemplates;
}
$typeManager = new \LAM\TYPES\TypeManager();
foreach ($typeManager->getConfiguredTypes() as $type) {
if (empty($allTemplates[$type->getScope()])) {
continue;
/**
* Returns the file name of a global template.
*
* @param string $scope e.g. user
* @param string $name profile name
* @return string file name
*/
function getProfileTemplateFileName($scope, $name) {
return __DIR__ . '/../config/templates/profiles' . '/' . $name . '.' . $scope;
}
foreach ($allTemplates[$type->getScope()] as $templateName) {
$path = $basePath . '/' . $templateName . '.' . $type->getId();
if (!is_file($path)) {
$template = $templatePath . '/' . $templateName . '.' . $type->getScope();
logNewMessage(LOG_DEBUG, 'Copy template ' . $template . ' to ' . $path);
@copy($template, $path);
/**
* Loads a template profile of the given account scope.
*
* @param string $profile name of the profile (without .<scope> extension)
* @param string $scope account type
* @return array hash array (attribute => value)
* @throws LAMException error reading profile template
*/
function loadTemplateAccountProfile($profile, $scope) {
if (!isValidProfileName($profile) || !preg_match("/^[a-z0-9_]+$/i", $scope)) {
logNewMessage(LOG_NOTICE, "Invalid account profile name: $profile:$scope");
return array();
}
$fileName = getProfileTemplateFileName($scope, $profile);
return readAccountProfileFile($fileName);
}
/**
* Installs a single template from the given data.
*
* @param string $scope account type (e.g. user)
* @param string $name template name
* @param array $data profile data
* @throws LAMException error saving file
*/
function installTemplateAccountProfile($scope, $name, $data) {
if (!isValidProfileName($name) || !preg_match("/^[a-z0-9_]+$/i", $scope)) {
logNewMessage(LOG_NOTICE, "Invalid account profile name: $name:$scope");
return;
}
$fileName = getProfileTemplateFileName($scope, $name);
$success = writeProfileDataToFile($fileName, $data);
if (!$success) {
throw new LAMException('Unable to write account profile template: ' . $fileName);
}
}
?>

View File

@ -170,7 +170,7 @@ function checkSelfServiceOptions($scope, $fields, $attributes, $passwordChangeOn
/**
* Returns a list of all available self service profiles (without .conf)
*
* @return array profile names (array(<account type> => array(<profile1>, <profile2>, ...)))
* @return array profile names (array('account type' => array('profile1', 'profile2')))
*/
function getSelfServiceProfiles() {
$types = LAM\TYPES\getTypes();
@ -201,7 +201,7 @@ function getSelfServiceProfiles() {
*
* @param string $name profile name
* @param string $scope account type
* @return selfServiceProfile|false profile if file was readable, false otherwise
* @return false|selfServiceProfile profile or false if file was not readable
*/
function loadSelfServiceProfile($name, $scope) {
if (!preg_match("/^[0-9a-z _-]+$/i", $name) || !preg_match("/^[0-9a-z _-]+$/i", $scope)) {
@ -213,7 +213,13 @@ function loadSelfServiceProfile($name, $scope) {
$file = @fopen($file, "r");
if ($file) {
$data = fread($file, 10000000);
$profileData = @json_decode($data, true);
if ($profileData === null) {
$profile = unserialize($data);
}
else {
$profile = selfServiceProfile::import($profileData);
}
fclose($file);
}
else {
@ -249,7 +255,7 @@ function saveSelfServiceProfile($name, $scope, $profile) {
$file = @fopen($path, "w");
if ($file) {
// write settings to file
fputs($file, serialize($profile));
fputs($file, json_encode($profile->export()));
// close file
fclose($file);
}
@ -521,6 +527,32 @@ class selfServiceProfile {
$this->baseUrl = '';
}
/**
* Converts the export data back to a self service profile.
*
* @param array $data export data
* @return selfServiceProfile profile
*/
public static function import($data) {
$profile = new selfServiceProfile();
$vars = get_class_vars(selfServiceProfile::class);
foreach ($data as $key => $value) {
if (in_array($key, $vars)) {
$profile->$key = $value;
}
}
return $profile;
}
/**
* Returns a representation of the self service profile.
*
* @return array self service profile data
*/
public function export() {
return json_decode(json_encode($this), true);
}
/**
* Returns the server's base URL (e.g. https://www.example.com).
*

View File

@ -86,6 +86,10 @@ a img {
border: 0px;
}
a.img-padding1 img {
padding: 1rem;
}
a.classicBold {
color: blue;
text-decoration: none;
@ -462,6 +466,10 @@ table.collapse {
display: none;
}
.display-as-block {
display: block;
}
.nowrap {
white-space: nowrap;
}
@ -489,7 +497,7 @@ div.smallScroll {
}
.fullwidth {
width: 100%;
width: 100%!important;
}
.halfwidth {

View File

@ -0,0 +1,277 @@
<?php
namespace LAM\CONFIG;
use htmlButton;
use htmlGroup;
use htmlInputFileUpload;
use htmlLink;
use htmlOutputText;
use htmlResponsiveInputCheckbox;
use htmlResponsiveInputField;
use htmlResponsiveRow;
use htmlStatusMessage;
use htmlSubTitle;
use LAM\PERSISTENCE\ConfigDataExporter;
use LAM\PERSISTENCE\ConfigDataImporter;
use LAMCfgMain;
use LAMException;
/*
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
Copyright (C) 2020 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
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
*/
/**
* Import and export functions for LAM configuration.
*
* @package configuration
* @author Roland Gruber
*/
/** Access to persistence functions */
include_once('../../lib/persistence.inc');
// start session
if (strtolower(session_module_name()) == 'files') {
session_save_path("../../sess");
}
lam_start_session();
setlanguage();
if (!isset($_SESSION['cfgMain'])) {
$cfg = new LAMCfgMain();
$_SESSION['cfgMain'] = $cfg;
}
$cfg = &$_SESSION['cfgMain'];
// export
if (isset($_POST['exportConfig']) && $cfg->checkPassword($_SESSION["mainconf_password"])) {
$exporter = new ConfigDataExporter();
if (!headers_sent()) {
header('Content-Type: application/json; charset=utf-8');
header('Content-disposition: attachment; filename=lam-config.json');
}
try {
echo $exporter->exportAsJson();
}
catch (LAMException $e) {
logNewMessage('ERROR', $e->getTitle() . ' ' . $e->getMessage());
}
exit;
}
echo $_SESSION['header'];
printHeaderContents(_("Import and export configuration"), '../..');
?>
</head>
<body class="admin">
<?php
// include all JavaScript files
printJsIncludes('../..');
?>
<table class="lamTop ui-corner-all">
<tr>
<td align="left">
<a class="lamLogo" href="http://www.ldap-account-manager.org/" target="new_window">
<?php echo getLAMVersionText(); ?>
</a>
</td>
</tr>
</table>
<form action="confImportExport.php" method="post" autocomplete="off" enctype="multipart/form-data">
<br><br>
<?php
// check if user is logged in
if (!isset($_POST['submitLogin']) && !isset($_SESSION["mainconf_password"])) {
showLoginDialog();
exit();
}
// check login
if (isset($_POST['submitLogin']) && !checkLogin($cfg)) {
exit();
}
displayImportExport();
/**
* Shows the login dialog for the configuration master password.
*
* @param htmlStatusMessage $message message to show if any error occured
*/
function showLoginDialog($message = null) {
$tabindex = 0;
$content = new htmlResponsiveRow();
$loginContent = new htmlResponsiveRow();
$loginContent->setCSSClasses(array('maxrow fullwidth roundedShadowBox spacing5'));
if ($message !== null) {
$loginContent->add($message, 12);
}
$pwdInput = new htmlResponsiveInputField(_("Master password"), 'password', '', '236');
$pwdInput->setIsPassword(true);
$pwdInput->setCSSClasses(array('lam-initial-focus'));
$loginContent->add($pwdInput, 12);
$loginContent->addLabel(new htmlOutputText('&nbsp;', false));
$loginContent->addField(new htmlButton('submitLogin', _("Ok")));
$content->add($loginContent, 12);
parseHtml(null, $content, array(), false, $tabindex, null);
renderBackLink();
}
/**
* Renders the link back to login page.
*/
function renderBackLink() {
$tabindex = 0;
$content = new htmlResponsiveRow();
$content->addVerticalSpacer('2rem');
$content->add(new htmlLink(_('Back to login'), '../login.php', '../../graphics/undo.png'), 12);
$content->addVerticalSpacer('1rem');
parseHtml(null, $content, array(), false, $tabindex, null);
}
/**
* Checks the login password.
*
* @param LAMCfgMain $cfg main config
* @return bool login ok
*/
function checkLogin($cfg) {
$password = $_POST['password'];
if ($cfg->checkPassword($password)) {
$_SESSION["mainconf_password"] = $password;
return true;
}
showLoginDialog(new htmlStatusMessage('ERROR', _('The password is invalid! Please try again.')));
return false;
}
/**
* Displays the import/export functions.
*/
function displayImportExport() {
$tabindex = 0;
$content = new htmlResponsiveRow();
$content->add(new htmlSubTitle(_('Export')), 12);
$content->add(new htmlButton('exportConfig', _('Export')), 12);
$content->add(new htmlSubTitle(_('Import')), 12);
renderImportPart($content);
parseHtml(null, $content, array(), false, $tabindex, null);
renderBackLink();
}
/**
* Renders the import area.
*
* @param htmlResponsiveRow $content content where to add import part
*/
function renderImportPart($content) {
$validUpload = false;
$importSteps = array();
if (isset($_POST['importConfig'])) {
try {
if (empty($_FILES['import-file']['tmp_name'])) {
throw new LAMException('The file you uploaded is too large. Please check php.ini, upload_max_size setting');
}
$handle = fopen($_FILES['import-file']['tmp_name'], "r");
$data = fread($handle, 100000000);
fclose($handle);
$importer = new ConfigDataImporter();
$importSteps = $importer->getPossibleImportSteps($data);
$tmpFile = __DIR__ . '/../../tmp/internal/import_' . getRandomNumber() . '.tmp';
$file = @fopen($tmpFile, "w");
if ($file) {
fputs($file, $data);
fclose($file);
chmod($tmpFile, 0600);
}
$_SESSION['configImportFile'] = $tmpFile;
$validUpload = true;
}
catch (LAMException $e) {
$content->add(new htmlStatusMessage('ERROR', htmlspecialchars($e->getTitle()), htmlspecialchars($e->getMessage())), 12);
}
}
if (!isset($_POST['importConfigConfirm']) && !$validUpload) {
$content->add(new htmlInputFileUpload('import-file'), 12);
$content->add(new htmlButton('importConfig', _('Submit')), 12);
}
elseif (isset($_POST['importConfig'])) {
$content->add(new htmlOutputText(_('Import steps')), 12);
foreach ($importSteps as $importStep) {
$stepKey = 'step_' . $importStep->getKey();
$stepCheckbox = new htmlResponsiveInputCheckbox($stepKey, true, $importStep->getLabel());
$stepCheckbox->setLabelAfterCheckbox();
$stepCheckbox->setCSSClasses(array('bold'));
$subStepIds = array();
$content->add($stepCheckbox, 12);
$content->addVerticalSpacer('0.3rem');
foreach ($importStep->getSubSteps() as $subStep) {
$subStepKey = 'step_' . $subStep->getKey();
$subStepIds[] = $subStepKey;
$subStepCheckbox = new htmlResponsiveInputCheckbox($subStepKey, true, $subStep->getLabel());
$subStepCheckbox->setLabelAfterCheckbox();
$content->add($subStepCheckbox, 12);
}
$stepCheckbox->setTableRowsToShow($subStepIds);
$content->addVerticalSpacer('1rem');
}
$buttonGroup = new htmlGroup();
$buttonGroup->addElement(new htmlButton('importConfigConfirm', _('Import')));
$buttonGroup->addElement(new htmlButton('importCancel', _('Cancel')));
$content->add($buttonGroup, 12);
}
elseif (isset($_POST['importConfigConfirm'])) {
$handle = fopen($_SESSION['configImportFile'], "r");
$data = fread($handle, 100000000);
fclose($handle);
try {
$importer = new ConfigDataImporter();
$importSteps = $importer->getPossibleImportSteps($data);
foreach ($importSteps as $importStep) {
$importStep->setActive(isset($_POST['step_' . $importStep->getKey()]));
foreach ($importStep->getSubSteps() as $subStep) {
$subStep->setActive(isset($_POST['step_' . $subStep->getKey()]));
}
}
$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);
$content->add(new htmlButton('importCancel', _('Back')), 12);
}
}
}
?>
</form>
</body>
</html>

View File

@ -1,8 +1,11 @@
<?php
namespace LAM\CONFIG;
use htmlLink;
use htmlResponsiveRow;
/*
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
Copyright (C) 2003 - 2019 Roland Gruber
Copyright (C) 2003 - 2020 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
@ -42,6 +45,9 @@ setlanguage();
echo $_SESSION['header'];
printHeaderContents(_("Configuration overview"), '../..');
$tabindex = 0;
$content = new htmlResponsiveRow();
?>
</head>
<body class="admin">
@ -59,69 +65,45 @@ printHeaderContents(_("Configuration overview"), '../..');
</tr>
</table>
<br><br>
<TABLE border="0" width="100%" class="ui-corner-all roundedShadowBox">
<?php
$topContent = new htmlResponsiveRow();
$topContent->setCSSClasses(array('maxrow fullwidth roundedShadowBox spacing5'));
$mainCfgLink = new htmlLink(_("Edit general settings"), 'mainlogin.php', '../../graphics/bigTools.png');
$mainCfgLink->setCSSClasses(array('img-padding1 display-as-block'));
$topContent->add($mainCfgLink, 12);
$cfgLink = new htmlLink(_("Edit server profiles"), 'conflogin.php', '../../graphics/profiles.png');
$cfgLink->setCSSClasses(array('img-padding1 display-as-block'));
$topContent->add($cfgLink, 12);
if (isLAMProVersion()) {
echo "<tr><td rowspan=4 width=20>&nbsp;</td><td></td><td></td></tr>\n";
$selfServiceLink = new htmlLink(_("Edit self service"), '../selfService/adminLogin.php', '../../graphics/bigPeople.png');
$selfServiceLink->setCSSClasses(array('img-padding1 display-as-block'));
$topContent->add($selfServiceLink, 12);
}
else {
echo "<tr><td rowspan=3 width=20>&nbsp;</td><td></td><td></td></tr>\n";
if (isDeveloperVersion(LAMVersion())) {
$topContent->addVerticalSpacer('1rem');
$importExportLink = new htmlLink(_("Import and export configuration"), 'confImportExport.php', '../../graphics/confImportExport.png');
$importExportLink->setCSSClasses(array('img-padding1 display-as-block'));
$topContent->add($importExportLink, 12);
}
$content->add($topContent, 12);
$content->addVerticalSpacer('4rem');
?>
<TR>
<TD width="60" height="70">
<a href="mainlogin.php">
<IMG height="32" width="32" alt="general settings" src="../../graphics/bigTools.png">
</a>
</TD>
<TD>
<a href="mainlogin.php">
<?php echo _("Edit general settings") ?>
</a>
</TD>
</TR>
<TR>
<TD height="70">
<a href="conflogin.php" target="_self">
<IMG height="32" width="32" alt="server settings" src="../../graphics/profiles.png">
</a>
</TD>
<TD>
<a href="conflogin.php" target="_self">
<?php echo _("Edit server profiles"); ?>
</a>
</TD>
</TR>
<?php
if (isLAMProVersion()) {
echo "<TR>\n";
echo "<TD height=\"70\">\n";
echo "<a href=\"../selfService/adminLogin.php\" target=\"_self\">\n";
echo "<IMG height=\"32\" width=\"32\" alt=\"self service\" src=\"../../graphics/bigPeople.png\">\n";
echo "</a>\n";
echo "</TD>\n";
echo "<TD>\n";
echo "<a href=\"../selfService/adminLogin.php\" target=\"_self\">\n";
echo _("Edit self service");
echo "</a>\n";
echo "</TD>\n";
echo "</TR>\n";
}
?>
</TABLE>
<p><br></p>
<?php
if (isLAMProVersion()) {
include_once(__DIR__ . "/../../lib/env.inc");
$printer = new \LAM\ENV\LAMLicenseInfoPrinter();
$printer->printLicenseInfo();
echo "<br><br>";
$content->add($printer->getLicenseInfo(), 12);
$content->addVerticalSpacer('2rem');
}
?>
<p>&nbsp;<a href="../login.php"><IMG alt="back" src="../../graphics/undo.png">&nbsp;<?php echo _("Back to login") ?></a></p>
<p><br><br></p>
$content->add(new htmlLink(_("Back to login"), '../login.php', '../../graphics/undo.png'), 12);
$content->addVerticalSpacer('2rem');
parseHtml('none', $content, array(), true, $tabindex, 'none');
?>
</body>
</html>

View File

@ -21,7 +21,7 @@ use \LAM\TYPES\TypeManager;
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
Copyright (C) 2003 - 2006 Michael Duergner
2005 - 2018 Roland Gruber
2005 - 2020 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
@ -107,7 +107,7 @@ $container->add(new htmlTitle(_('PDF editor')), 12);
if (isset($_POST['deleteProfile']) && ($_POST['deleteProfile'] == 'true')) {
$typeToDelete = $typeManager->getConfiguredType($_POST['profileDeleteType']);
// delete structure
if (\LAM\PDF\deletePDFStructure($_POST['profileDeleteType'], $_POST['profileDeleteName'])) {
if (\LAM\PDF\deletePDFStructure($_POST['profileDeleteType'], $_POST['profileDeleteName'], $_SESSION['config']->getName())) {
$message = new htmlStatusMessage('INFO', _('Deleted PDF structure.'), $typeToDelete->getAlias() . ': ' . htmlspecialchars($_POST['profileDeleteName']));
$container->add($message, 12);
}
@ -173,13 +173,13 @@ if (!empty($_POST['export'])) {
if (isset($_POST['uploadLogo']) && !empty($_FILES['logoUpload']) && !empty($_FILES['logoUpload']['size'])) {
$file = $_FILES['logoUpload']['tmp_name'];
$filename = $_FILES['logoUpload']['name'];
$container->add(\LAM\PDF\uploadPDFLogo($file, $filename), 12);
$container->add(\LAM\PDF\uploadPDFLogo($file, $filename, $_SESSION['config']->getName()), 12);
}
// delete logo file
if (isset($_POST['delLogo'])) {
$toDel = $_POST['logo'];
$container->add(\LAM\PDF\deletePDFLogo($toDel), 12);
$container->add(\LAM\PDF\deletePDFLogo($toDel, $_SESSION['config']->getName()), 12);
}
// get list of account types
@ -192,7 +192,7 @@ foreach ($sortedTypes as $typeId => $title) {
'scope' => $type->getScope(),
'title' => $title,
'icon' => $type->getIcon(),
'templates' => \LAM\PDF\getPDFStructures($type->getId()));
'templates' => \LAM\PDF\getPDFStructures($type->getId(), $_SESSION['config']->getName()));
$availableTypes[$title] = $type->getId();
}
// check if a template should be edited
@ -275,7 +275,7 @@ include __DIR__ . '/../../lib/adminHeader.inc';
// manage logos
$container->addVerticalSpacer('4rem');
$container->add(new htmlSubTitle(_('Manage logos')), 12);
$logos = \LAM\PDF\getAvailableLogos();
$logos = \LAM\PDF\getAvailableLogos($_SESSION['config']->getName());
$logoOptions = array();
foreach ($logos as $logo) {
$file = $logo['filename'];

View File

@ -22,7 +22,7 @@ use LAM\PDF\PDFStructureWriter;
/*
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
Copyright (C) 2003 - 2006 Michael Duergner
2007 - 2019 Roland Gruber
2007 - 2020 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
@ -105,7 +105,7 @@ if(isset($_GET['abort'])) {
// Load PDF structure from file if it is not defined in session
if(!isset($_SESSION['currentPDFStructure'])) {
// Load structure file to be edit
$reader = new PDFStructureReader();
$reader = new PDFStructureReader($_SESSION['config']->getName());
try {
if(isset($_GET['edit'])) {
$_SESSION['currentPDFStructure'] = $reader->read($type->getId(), $_GET['edit']);
@ -135,7 +135,7 @@ if (!empty($_POST['form_submit'])) {
// main pdf structure page
$saveErrors = array();
if(isset($_GET['submit'])) {
$writer = new PDFStructureWriter();
$writer = new PDFStructureWriter($_SESSION['config']->getName());
try {
$writer->write($type->getId(), $_POST['pdfname'], $_SESSION['currentPDFStructure']);
unset($_SESSION['currentPDFStructure']);
@ -218,7 +218,7 @@ else if (isset($_POST['pdfname'])) {
// headline
$headline = $_SESSION['currentPDFStructure']->getTitle();
// logo
$logoFiles = \LAM\PDF\getAvailableLogos();
$logoFiles = \LAM\PDF\getAvailableLogos($_SESSION['config']->getName());
$logos = array(_('No logo') => 'none');
foreach($logoFiles as $logoFile) {
$logos[$logoFile['filename'] . ' (' . $logoFile['infos'][0] . ' x ' . $logoFile['infos'][1] . ")"] = $logoFile['filename'];

View File

@ -10,7 +10,7 @@ use \htmlSubTitle;
/*
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
Copyright (C) 2003 - 2019 Roland Gruber
Copyright (C) 2003 - 2020 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
@ -127,7 +127,7 @@ if (isset($_POST['save'])) {
$errors = checkProfileOptions($_POST['accounttype'], $options);
if (sizeof($errors) == 0) { // input data is valid, save profile
// save profile
if (\LAM\PROFILES\saveAccountProfile($options, $_POST['profname'], $_POST['accounttype'])) {
if (\LAM\PROFILES\saveAccountProfile($options, $_POST['profname'], $_POST['accounttype'], $_SESSION['config'])) {
metaRefresh('profilemain.php?savedSuccessfully=' . $_POST['profname']);
exit();
}
@ -168,7 +168,7 @@ if (isset($_POST['save'])) {
}
}
elseif (isset($_GET['edit'])) {
$old_options = \LAM\PROFILES\loadAccountProfile($_GET['edit'], $type->getId());
$old_options = \LAM\PROFILES\loadAccountProfile($_GET['edit'], $type->getId(), $_SESSION['config']->getName());
}
// display formular

View File

@ -294,7 +294,7 @@ function showMainPage(\LAM\TYPES\ConfiguredType $type, $selectedModules) {
$pdfCheckbox = new htmlResponsiveInputCheckbox('createPDF', $createPDF, _('Create PDF files'));
$pdfCheckbox->setTableRowsToShow(array('pdfStructure', 'pdf_font'));
$row->add($pdfCheckbox, 12);
$pdfStructures = \LAM\PDF\getPDFStructures($type->getId());
$pdfStructures = \LAM\PDF\getPDFStructures($type->getId(), $_SESSION['config']->getName());
$pdfSelected = array();
if (isset($_POST['pdfStructure'])) {
$pdfSelected = array($_POST['pdfStructure']);

View File

@ -120,4 +120,56 @@ class LAMCfgMainTest extends TestCase {
$this->assertFalse($this->conf->showLicenseWarningOnScreen());
}
/**
* Tests the export.
*/
public function testExportData() {
$this->conf->passwordMinLower = 3;
$this->conf->sessionTimeout = 240;
$this->conf->logLevel = LOG_ERR;
$this->conf->mailServer = 'mailserver';
$data = $this->conf->exportData();
$this->assertEquals(3, $data['passwordMinLower']);
$this->assertEquals(240, $data['sessionTimeout']);
$this->assertEquals(LOG_ERR, $data['logLevel']);
$this->assertEquals('mailserver', $data['mailServer']);
}
/**
* Tests the import.
*/
public function testImportData() {
$importData = array();
$importData['passwordMinLower'] = 3;
$importData['sessionTimeout'] = 240;
$importData['logLevel'] = LOG_ERR;
$importData['mailServer'] = 'mailserver';
$importData['allowedHosts'] = null;
$importData['IGNORE_ME'] = 'ignore';
$this->conf->importData($importData);
$this->assertEquals(3, $this->conf->passwordMinLower);
$this->assertEquals(240, $this->conf->sessionTimeout);
$this->assertEquals(LOG_ERR, $this->conf->logLevel);
$this->assertEquals('mailserver', $this->conf->mailServer);
$this->assertNull($this->conf->allowedHosts);
}
/**
* Tests the import with invalid data.
*/
public function testImportData_invalid() {
$importData = array();
$importData['passwordMinLower'] = 3;
$importData['sessionTimeout'] = 240;
$importData['logLevel'] = LOG_ERR;
$importData['mailServer'] = new LAMLanguage('de_de', 'UTF-8', 'DE');
$this->expectException(LAMException::class);
$this->conf->importData($importData);
}
}

View File

@ -3,7 +3,7 @@ use PHPUnit\Framework\TestCase;
/*
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
Copyright (C) 2016 - 2019 Roland Gruber
Copyright (C) 2016 - 2020 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
@ -21,7 +21,7 @@ use PHPUnit\Framework\TestCase;
*/
include_once 'lam/tests/utils/configuration.inc';
include_once __DIR__ . '/../utils/configuration.inc';
/**
* LAMConfig test case.
@ -858,6 +858,63 @@ class LAMConfigTest extends TestCase {
$this->assertEquals($sizeTypeSettings, sizeof($this->lAMConfig->get_typeSettings()));
}
/**
* Tests the export.
*/
public function testExportData() {
$this->lAMConfig->set_defaultLanguage('lang');
$this->lAMConfig->set_ServerURL('myserver');
$this->lAMConfig->set_typeSettings(array('typetest' => '1'));
$this->lAMConfig->set_moduleSettings(array('modtest' => '1'));
$this->lAMConfig->setToolSettings(array('tooltest' => '1'));
$this->lAMConfig->setJobSettings(array('jobtest' => '1'));
$data = $this->lAMConfig->exportData();
$this->assertEquals('lang', $data['defaultLanguage']);
$this->assertEquals('myserver', $data['ServerURL']);
$this->assertEquals(array('typetest' => '1'), $data['typeSettings']);
$this->assertEquals(array('modtest' => '1'), $data['moduleSettings']);
$this->assertEquals(array('tooltest' => '1'), $data['toolSettings']);
$this->assertEquals(array('jobtest' => '1'), $data['jobSettings']);
}
/**
* Tests the import.
*/
public function testImportData() {
$importData = array();
$importData['ServerURL'] = 'testserver';
$importData['defaultLanguage'] = 'de_DE.utf8';
$importData['typeSettings'] = array('typetest' => 'value');
$importData['toolSettings'] = array('tooltest' => 'value');
$importData['moduleSettings'] = array('modtest' => 'value');
$importData['jobSettings'] = array('jobtest' => 'value');
$importData['IGNORE_ME'] = 'ignore';
$this->lAMConfig->importData($importData);
$this->assertEquals('testserver', $this->lAMConfig->get_ServerURL());
$this->assertEquals('de_DE.utf8', $this->lAMConfig->get_defaultLanguage());
$this->assertEquals(array('typetest' => 'value'), $this->lAMConfig->get_typeSettings());
$this->assertEquals(array('tooltest' => 'value'), $this->lAMConfig->getToolSettings());
$this->assertEquals(array('modtest' => 'value'), $this->lAMConfig->get_moduleSettings());
$this->assertEquals(array('jobtest' => 'value'), $this->lAMConfig->getJobSettings());
}
/**
* Tests the import with invalid data.
*/
public function testImportData_invalid() {
$importData = array();
$importData['ServerURL'] = 'testserver';
$importData['typeSettings'] = array('typetest' => 'value');
$importData['defaultLanguage'] = new LAMLanguage('de_de', 'UTF-8', 'DE');
$this->expectException(LAMException::class);
$this->lAMConfig->importData($importData);
}
/**
* Saves the config
*/

View File

@ -24,7 +24,7 @@ include_once __DIR__ . '/../../lib/account.inc';
include_once __DIR__ . '/../../lib/security.inc';
/**
* LAMConfig test case.
* account.inc test cases.
*
* @author Roland Gruber
*/
@ -155,4 +155,13 @@ class AccountTest extends TestCase {
$this->assertFalse(isCommandlineSafeEmailAddress('test+abc@example.com'));
}
/**
* Tests isDeveloperVersion()
*/
function testIsDeveloperVersion() {
$this->assertFalse(isDeveloperVersion('0.4.1'));
$this->assertFalse(isDeveloperVersion('3.2.RC1'));
$this->assertTrue(isDeveloperVersion('4.5.DEV'));
}
}

View File

@ -1,4 +1,6 @@
<?php
use LAM\PDF\PDFSectionEntry;
use LAM\PDF\PDFTextSection;
use LAM\PDF\PDFEntrySection;
use LAM\PDF\PDFStructureReader;
@ -26,21 +28,22 @@ use PHPUnit\Framework\TestCase;
*/
include_once 'lam/lib/pdfstruct.inc';
include_once __DIR__ . '/../../lib/pdfstruct.inc';
/**
* Reads a sample PDF structure.
* Tests classes in pdfstruct.inc.
*
* @author Roland Gruber
*
*/
class ReadStructureTest extends TestCase {
class PdfStructTest extends TestCase {
/**
* Reads the sample structure.
*/
public function testRead() {
$reader = $this->getMockBuilder('\LAM\PDF\PDFStructureReader')
->setConstructorArgs(array('test'))
->setMethods(array('getFileName'))
->getMock();
$reader->method('getFileName')->willReturn($this->getTestFileName('test.xml'));
@ -99,17 +102,144 @@ class ReadStructureTest extends TestCase {
fclose($fileHandle);
// read structure
$reader = $this->getMockBuilder('\LAM\PDF\PDFStructureReader')
->setConstructorArgs(array('test'))
->setMethods(array('getFileName'))
->getMock();
$reader->method('getFileName')->willReturn($file);
$structure = $reader->read('type', 'name');
// create writer and get output XML
$writer = new PDFStructureWriter();
$writer = new PDFStructureWriter('test');
$xml = $writer->getXML($structure);
// compare
$this->assertEquals($originalXML, $xml);
}
/**
* Tests PDFTextSection
*/
public function testExportPDFTextSection() {
$section = new PDFTextSection('sometext');
$data = $section->export();
$this->assertEquals('sometext', $data);
}
/**
* Tests PDFEntrySection
*/
public function testExportPDFEntrySection() {
$section = new PDFEntrySection('mytitle');
$section->setEntries(array(new PDFSectionEntry('key1'), new PDFSectionEntry('key2')));
$data = $section->export();
$expected = array(
'title' => 'mytitle',
'entries' => array('key1', 'key2')
);
$this->assertEquals($expected, $data);
}
/**
* Tests PDFStructure
*/
public function testExportPDFStructure() {
$structure = new PDFStructure();
$structure->setFoldingMarks(PDFStructure::FOLDING_STANDARD);
$structure->setLogo('somelogo');
$structure->setTitle('mytitle');
$entrySection = new PDFEntrySection('sometitle');
$entrySection->setEntries(array(new PDFSectionEntry('key1')));
$structure->setSections(array(
new PDFTextSection('sometext'),
$entrySection
));
$data = $structure->export();
$expected = array(
'title' => 'mytitle',
'foldingMarks' => PDFStructure::FOLDING_STANDARD,
'logo' => 'somelogo',
'sections' => array(
array(
'type' => 'text',
'data' => 'sometext'
),
array(
'type' => 'entry',
'data' => array(
'title' => 'sometitle',
'entries' => array('key1')
)
)
)
);
$this->assertEquals($expected, $data);
}
/**
* Tests import in PDFEntrySection.
*/
public function testImportPDFEntrySection() {
$data = array(
'title' => 'mytitle',
'entries' => array('e1', 'e2')
);
$section = new PDFEntrySection(null);
$section->import($data);
$this->assertEquals('mytitle', $section->getTitle());
$entries = $section->getEntries();
$this->assertEquals(2, sizeof($entries));
$this->assertEquals('e1', ($entries[0]->getKey()));
$this->assertEquals('e2', ($entries[1]->getKey()));
}
/**
* Tests the import in PDFStructure.
*/
public function testImportPDFStructure() {
$data = array(
'title' => 'mytitle',
'foldingMarks' => PDFStructure::FOLDING_STANDARD,
'logo' => 'logo',
'sections' => array(
array(
'type' => 'text',
'data' => 'textvalue'
),
array(
'type' => 'entry',
'data' => array(
'title' => 'etitle',
'entries' => array('e1', 'e2')
)
),
)
);
$structure = new PDFStructure();
$structure->import($data);
$this->assertEquals('mytitle', $structure->getTitle());
$this->assertEquals(PDFStructure::FOLDING_STANDARD, $structure->getFoldingMarks());
$this->assertEquals('logo', $structure->getLogo());
$sections = $structure->getSections();
$this->assertEquals(2, sizeof($sections));
$this->assertTrue($sections[0] instanceof PDFTextSection);
$this->assertEquals('textvalue', $sections[0]->getText());
$this->assertTrue($sections[1] instanceof PDFEntrySection);
$entries = $sections[1]->getEntries();
$this->assertEquals(2, sizeof($entries));
$this->assertEquals('e1', $entries[0]->getKey());
$this->assertEquals('e2', $entries[1]->getKey());
}
}
?>

View File

@ -0,0 +1,104 @@
<?php
namespace LAM\PERSISTENCE;
use PHPUnit\Framework\TestCase;
/*
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
Copyright (C) 2020 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
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
*/
include_once __DIR__ . '/../../lib/persistence.inc';
/**
* ConfigDataExporter test case.
*
* @author Roland Gruber
*/
class ConfigDataExporterTest extends TestCase {
public function testExportAsJson() {
$mainData = array(
'confMainKey1' => 'val',
'confMainKey2' => 4,
'confMainKey3' => '',
);
$profileData = array(
'profile1' => array('ServerURL' => 'myserver'),
'profile2' => array('ServerURL' => 'myserver2'),
);
$accountProfileData = array(
'profile1' => array('user' => array('default' => array('key' => 'value'))),
'profile1' => array(
'user' => array('default' => array('key' => 'value')),
'group' => array('default' => array('key' => 'value')),
),
);
$accountProfileTemplateData = array(
'user' => array('default' => array('key' => 'value')),
'group' => array('default' => array('key' => 'value')),
);
$pdfData = array(
'profile1' => array('structures' => array(
'user' => array(
'default' => array('key' => 'value'))
)),
'profile1' => array('structures' => array(
'user' => array('default' => array('key' => 'value')),
'group' => array('default' => array('key' => 'value')),
)),
);
$pdfTemplateData = array(
'user' => array('default' => array('key' => 'value')),
'group' => array('default' => array('key' => 'value')),
);
$selfServiceData = array(
'profile1' => array('key' => 'value'),
'profile2' => array('key' => 'value'),
);
$expectedJson = json_encode(array(
'mainConfig' => $mainData,
'certificates' => 'certs',
'serverProfiles' => $profileData,
'accountProfiles' => $accountProfileData,
'accountProfileTemplates' => $accountProfileTemplateData,
'pdfProfiles' => $pdfData,
'pdfProfileTemplates' => $pdfTemplateData,
'selfServiceProfiles' => $selfServiceData,
));
$exporter = $this->getMockBuilder('\LAM\PERSISTENCE\ConfigDataExporter')
->setMethods(array('_getMainConfigData', '_getCertificates', '_getServerProfiles',
'_getAccountProfiles', '_getAccountProfileTemplates', '_getPdfProfiles',
'_getPdfProfileTemplates', '_getSelfServiceProfiles'))
->getMock();
$exporter->method('_getMainConfigData')->willReturn($mainData);
$exporter->method('_getCertificates')->willReturn('certs');
$exporter->method('_getServerProfiles')->willReturn($profileData);
$exporter->method('_getAccountProfiles')->willReturn($accountProfileData);
$exporter->method('_getAccountProfileTemplates')->willReturn($accountProfileTemplateData);
$exporter->method('_getPdfProfiles')->willReturn($pdfData);
$exporter->method('_getPdfProfileTemplates')->willReturn($pdfTemplateData);
$exporter->method('_getSelfServiceProfiles')->willReturn($selfServiceData);
$json = $exporter->exportAsJson();
$this->assertEquals($expectedJson, $json);
}
}

View File

@ -3,7 +3,7 @@ use PHPUnit\Framework\TestCase;
/*
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
Copyright (C) 2019 Roland Gruber
Copyright (C) 2019 - 2020 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
@ -21,7 +21,7 @@ use PHPUnit\Framework\TestCase;
*/
require_once 'lam/lib/selfService.inc';
require_once __DIR__ . '/../../lib/selfService.inc';
/**
* Checks selfServiceProfile.
@ -43,6 +43,23 @@ class selfServiceProfileTest extends TestCase {
$this->assertEquals('https://test.com', $profile->getBaseUrl());
}
public function testImportExport() {
$profile = new selfServiceProfile();
$moduleSettings = array('x1' => 'y1', 'x2' => 'y2');
$profile->moduleSettings = $moduleSettings;
$profile->baseColor = 'green';
$profile->language = 'de_DE@UTF8';
$profile->pageHeader = 'header';
$export = $profile->export();
$importedProfile = selfServiceProfile::import($export);
$this->assertEquals($moduleSettings, $importedProfile->moduleSettings);
$this->assertEquals('green', $importedProfile->baseColor);
$this->assertEquals('de_DE@UTF8', $importedProfile->language);
$this->assertEquals('header', $importedProfile->pageHeader);
}
}
?>