1<?php 2namespace LAM\PROFILES; 3use LAM\TYPES\TypeManager; 4use \LAMException; 5/* 6 7 This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/) 8 Copyright (C) 2003 - 2020 Roland Gruber 9 10 This program is free software; you can redistribute it and/or modify 11 it under the terms of the GNU General Public License as published by 12 the Free Software Foundation; either version 2 of the License, or 13 (at your option) any later version. 14 15 This program is distributed in the hope that it will be useful, 16 but WITHOUT ANY WARRANTY; without even the implied warranty of 17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 GNU General Public License for more details. 19 20 You should have received a copy of the GNU General Public License 21 along with this program; if not, write to the Free Software 22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 24*/ 25 26/** 27* This file provides functions to load and save account profiles. 28* 29* @package profiles 30* @author Roland Gruber 31*/ 32 33 34/** 35* Returns an array of string with all available profiles for the given account type 36* 37* @param string $typeId account type 38* @param string $profile server profile name 39* @return array profile names 40*/ 41function getAccountProfiles($typeId, $profile = null) { 42 if (!isset($profile)) { 43 $profile = $_SESSION['config']->getName(); 44 } 45 46 $dir = @dir(dirname(__FILE__) . "/../config/profiles/" . $profile); 47 48 $ret = array(); 49 if ($dir) { 50 $entry = $dir->read(); 51 while ($entry){ 52 // check if filename ends with .<typeId> 53 if (strrpos($entry, '.')) { 54 $pos = strrpos($entry, '.'); 55 if (substr($entry, $pos + 1) == $typeId) { 56 $name = substr($entry, 0, $pos); 57 $ret[] = $name; 58 } 59 } 60 $entry = $dir->read(); 61 } 62 } 63 return $ret; 64} 65 66/** 67 * Returns if the given profile exists. 68 * 69 * @param string name profile name 70 * @param string $typeId type id 71 * @return bool exists 72 */ 73function profileExists($name, $typeId) { 74 if (!isValidProfileName($name) || !preg_match("/^[a-z0-9_]+$/i", $typeId) || ($typeId == null)) { 75 return false; 76 } 77 $file = substr(__FILE__, 0, strlen(__FILE__) - 17) . "/config/profiles/" . $_SESSION['config']->getName() . '/' . $name . "." . $typeId; 78 return is_file($file); 79} 80 81/** 82 * Loads an profile of the given account type 83 * 84 * @param string $profile name of the profile (without .<scope> extension) 85 * @param string $typeId account type 86 * @param string $serverProfileName server profile name 87 * @return array hash array (attribute => value) 88 */ 89function loadAccountProfile($profile, $typeId, $serverProfileName) { 90 if (!isValidProfileName($profile) || !preg_match("/^[a-z0-9_]+$/i", $typeId)) { 91 logNewMessage(LOG_NOTICE, "Invalid account profile name: $serverProfileName:$profile:$typeId"); 92 return array(); 93 } 94 $file = substr(__FILE__, 0, strlen(__FILE__) - 17) . "/config/profiles/" . $serverProfileName . '/' . $profile . "." . $typeId; 95 try { 96 return readAccountProfileFile($file); 97 } catch (LAMException $e) { 98 StatusMessage('ERROR', $e->getTitle(), $e->getMessage()); 99 } 100 return array(); 101} 102 103/** 104 * Reads an account profile from the given file name. 105 * 106 * @param string $fileName file name 107 * @return array hash array (attribute => value) 108 * @throws LAMException error reading file 109 */ 110function readAccountProfileFile($fileName) { 111 $settings = array(); 112 if (is_file($fileName)) { 113 $file = @fopen($fileName, "r"); 114 if ($file) { 115 while (!feof($file)) { 116 $line = fgets($file, 1024); 117 if (($line === false) || ($line == '') || ($line == "\n") || ($line[0] == "#")) { 118 continue; // ignore comments 119 } 120 // search keywords 121 $parts = explode(": ", $line); 122 if (sizeof($parts) == 2) { 123 $option = $parts[0]; 124 $value = $parts[1]; 125 // remove line ends 126 $value = chop($value); 127 $settings[$option] = explode("+::+", $value); 128 } 129 } 130 fclose($file); 131 return $settings; 132 } 133 else { 134 throw new LAMException(_("Unable to load profile!"), $fileName); 135 } 136 } 137 else { 138 throw new LAMException(_("Unable to load profile!"), $fileName); 139 } 140} 141 142/** 143* Saves an hash array (attribute => value) to an account profile 144* 145* file is created, if needed 146* 147* @param array $attributes hash array (attribute => value) 148* @param string $profile name of the account profile (without .<scope> extension) 149* @param string $typeId account type 150 * @param \LAMConfig $serverProfile server profile 151* @return boolean true, if saving succeeded 152*/ 153function saveAccountProfile($attributes, $profile, $typeId, $serverProfile) { 154 // check profile name and type id 155 $typeManager = new TypeManager($serverProfile); 156 $type = $typeManager->getConfiguredType($typeId); 157 if (!isValidProfileName($profile) || !preg_match("/^[a-z0-9_]+$/i", $typeId) || ($type == null)) { 158 logNewMessage(LOG_NOTICE, 'Invalid account profile name: ' . $profile . ':' . $typeId); 159 return false; 160 } 161 if (!is_array($attributes)) { 162 logNewMessage(LOG_NOTICE, 'Invalid account profile data'); 163 return false; 164 } 165 $path = substr(__FILE__, 0, strlen(__FILE__) - 17) . "/config/profiles/" . $serverProfile->getName() . '/' . $profile . "." . $typeId; 166 return writeProfileDataToFile($path, $attributes); 167} 168 169/** 170 * Writes the profile data to the given file. 171 * 172 * @param string $fileName file name 173 * @param array $data profile data 174 * @return bool writing was ok 175 */ 176function writeProfileDataToFile($fileName, $data) { 177 $file = @fopen($fileName, "w"); 178 if ($file) { 179 // write attributes 180 $keys = array_keys($data); 181 for ($i = 0; $i < sizeof($keys); $i++) { 182 if (isset($data[$keys[$i]])) { 183 $line = $keys[$i] . ": " . implode("+::+", $data[$keys[$i]]) . "\n"; 184 } 185 else { 186 $line = $keys[$i] . ": \n"; 187 } 188 fputs($file, $line); 189 } 190 // close file 191 fclose($file); 192 } 193 else { 194 logNewMessage(LOG_NOTICE, 'Unable to open account profile file: ' . $fileName); 195 return false; 196 } 197 return true; 198} 199 200/** 201* Deletes an account profile 202* 203* @param string $file name of profile (Without .<scope> extension) 204* @param string $typeId account type 205* @return boolean true if profile was deleted 206*/ 207function delAccountProfile($file, $typeId) { 208 if (!isLoggedIn()) { 209 return false; 210 } 211 $typeManager = new TypeManager(); 212 $type = $typeManager->getConfiguredType($typeId); 213 if (!isValidProfileName($file) || !preg_match("/^[a-z0-9_]+$/i", $typeId) || ($type == null)) { 214 return false; 215 } 216 $prof = substr(__FILE__, 0, strlen(__FILE__) - 16) . "config/profiles/". $_SESSION['config']->getName() . '/' . $file . "." . $typeId; 217 if (is_file($prof)) { 218 return @unlink($prof); 219 } 220 return false; 221} 222 223/** 224 * Returns if the given profile name is valid. 225 * 226 * @param string $name profile name 227 */ 228function isValidProfileName($name) { 229 return preg_match("/^[0-9a-z _-]+$/i", $name); 230} 231 232/** 233 * Copies an account profile from the given source to target. 234 * 235 * @param \LAM\TYPES\ConfiguredType $sourceType source type 236 * @param string $sourceProfileName profile name 237 * @param \LAM\TYPES\ConfiguredType $targetType target type 238 * @throws LAMException error during copy 239 */ 240function copyAccountProfile($sourceType, $sourceProfileName, $targetType) { 241 if (!isValidProfileName($sourceProfileName)) { 242 throw new LAMException(_('Failed to copy')); 243 } 244 $sourceConfig = $sourceType->getTypeManager()->getConfig()->getName(); 245 $sourceTypeId = $sourceType->getId(); 246 $targetConfig = $targetType->getTypeManager()->getConfig()->getName(); 247 $targetTypeId = $targetType->getId(); 248 $profilePath = dirname(__FILE__) . '/../config/profiles/'; 249 $src = $profilePath . $sourceConfig . '/' . $sourceProfileName . '.' . $sourceTypeId; 250 $dst = $profilePath . $targetConfig . '/' . $sourceProfileName . '.' . $targetTypeId; 251 if (!@copy($src, $dst)) { 252 throw new LAMException(_('Failed to copy'), $sourceConfig . ': ' . $sourceProfileName); 253 } 254} 255 256/** 257 * Copies an account profile from the given source to global templates. 258 * 259 * @param \LAM\TYPES\ConfiguredType $sourceType source type 260 * @param string $sourceProfileName profile name 261 * @throws LAMException error during copy 262 */ 263function copyAccountProfileToTemplates($sourceType, $sourceProfileName) { 264 if (!isValidProfileName($sourceProfileName)) { 265 throw new LAMException(_('Failed to copy')); 266 } 267 $sourceConfig = $sourceType->getTypeManager()->getConfig()->getName(); 268 $sourceTypeId = $sourceType->getId(); 269 $profilePath = dirname(__FILE__) . '/../config/profiles/'; 270 $templatePath = dirname(__FILE__) . '/../config/templates/profiles/'; 271 $src = $profilePath . $sourceConfig . '/' . $sourceProfileName . '.' . $sourceTypeId; 272 $dst = $templatePath . $sourceProfileName . '.' . $sourceType->getScope(); 273 if (!@copy($src, $dst)) { 274 throw new LAMException(_('Failed to copy'), $sourceConfig . ': ' . $sourceProfileName); 275 } 276} 277 278/** 279 * Installs template profiles to the current server profile. 280 */ 281function installProfileTemplates() { 282 $allTemplates = getProfileTemplateNames(); 283 $basePath = dirname(__FILE__) . '/../config/profiles/' . $_SESSION['config']->getName(); 284 if (!file_exists($basePath)) { 285 mkdir($basePath, 0700, true); 286 } 287 $typeManager = new TypeManager(); 288 foreach ($typeManager->getConfiguredTypes() as $type) { 289 if (empty($allTemplates[$type->getScope()])) { 290 continue; 291 } 292 foreach ($allTemplates[$type->getScope()] as $templateName) { 293 $path = $basePath . '/' . $templateName . '.' . $type->getId(); 294 if (!is_file($path)) { 295 $template = getProfileTemplateFileName($type->getScope(), $templateName); 296 logNewMessage(LOG_DEBUG, 'Copy template ' . $template . ' to ' . $path); 297 @copy($template, $path); 298 } 299 } 300 } 301} 302 303/** 304 * Returns a list of all global profile templates. 305 * 306 * @return array names (array('user' => array('default', 'extra'))) 307 */ 308function getProfileTemplateNames() { 309 $templatePath = __DIR__ . '/../config/templates/profiles'; 310 $templateDir = @dir($templatePath); 311 $allTemplates = array(); 312 if ($templateDir) { 313 $entry = $templateDir->read(); 314 while ($entry){ 315 $parts = explode('.', $entry); 316 if ((strlen($entry) > 3) && (sizeof($parts) == 2)) { 317 $name = $parts[0]; 318 $scope = $parts[1]; 319 $allTemplates[$scope][] = $name; 320 } 321 $entry = $templateDir->read(); 322 } 323 } 324 return $allTemplates; 325} 326 327/** 328 * Returns the file name of a global template. 329 * 330 * @param string $scope e.g. user 331 * @param string $name profile name 332 * @return string file name 333 */ 334function getProfileTemplateFileName($scope, $name) { 335 return __DIR__ . '/../config/templates/profiles' . '/' . $name . '.' . $scope; 336} 337 338/** 339 * Loads a template profile of the given account scope. 340 * 341 * @param string $profile name of the profile (without .<scope> extension) 342 * @param string $scope account type 343 * @return array hash array (attribute => value) 344 * @throws LAMException error reading profile template 345 */ 346function loadTemplateAccountProfile($profile, $scope) { 347 if (!isValidProfileName($profile) || !preg_match("/^[a-z0-9_]+$/i", $scope)) { 348 logNewMessage(LOG_NOTICE, "Invalid account profile name: $profile:$scope"); 349 return array(); 350 } 351 $fileName = getProfileTemplateFileName($scope, $profile); 352 return readAccountProfileFile($fileName); 353} 354 355/** 356 * Installs a single template from the given data. 357 * 358 * @param string $scope account type (e.g. user) 359 * @param string $name template name 360 * @param array $data profile data 361 * @throws LAMException error saving file 362 */ 363function installTemplateAccountProfile($scope, $name, $data) { 364 if (!isValidProfileName($name) || !preg_match("/^[a-z0-9_]+$/i", $scope)) { 365 logNewMessage(LOG_NOTICE, "Invalid account profile name: $name:$scope"); 366 return; 367 } 368 $fileName = getProfileTemplateFileName($scope, $name); 369 $success = writeProfileDataToFile($fileName, $data); 370 if (!$success) { 371 throw new LAMException('Unable to write account profile template: ' . $fileName); 372 } 373} 374 375