Overview

Packages

  • CONTENIDO
  • Core
    • Authentication
    • Backend
    • Cache
    • CEC
    • Chain
    • ContentType
    • Database
    • Debug
    • Exception
    • Frontend
      • Search
      • URI
      • Util
    • GenericDB
      • Model
    • GUI
      • HTML
    • I18N
    • LayoutHandler
    • Log
    • Security
    • Session
    • Util
    • Validation
    • Versioning
    • XML
  • Module
    • ContentRssCreator
    • ContentSitemapHtml
    • ContentSitemapXml
    • ContentUserForum
    • NavigationTop
    • ScriptCookieDirective
  • mpAutoloaderClassMap
  • None
  • Plugin
    • ContentAllocation
    • CronjobOverview
    • FormAssistant
    • FrontendLogic
    • FrontendUsers
    • Linkchecker
    • ModRewrite
    • Newsletter
    • Repository
      • FrontendNavigation
      • KeywordDensity
    • SearchSolr
    • SmartyWrapper
    • UrlShortener
    • UserForum
    • Workflow
  • PluginManager
  • Setup
    • Form
    • GUI
    • Helper
      • Environment
      • Filesystem
      • MySQL
      • PHP
    • UpgradeJob

Classes

  • cAjaxRequest
  • cAutoload
  • cBackend
  • cEffectiveSetting
  • cGuiScrollListAlltranslations
  • cHTMLValidator
  • cMailer
  • cModuleFileTranslation
  • cModuleHandler
  • cModuleSearch
  • cModuleSynchronizer
  • cModuleTemplateHandler
  • CodeMirror
  • cPasswordRequest
  • cPermission
  • cRegistry
  • cSystemPurge
  • cSystemtest
  • cTinymce4Configuration
  • cTinyMCE4Editor
  • cTinyMCEEditor
  • cWYSIWYGEditor
  • FrontendList
  • HtmlParser
  • TODOBackendList
  • TreeItem
  • UploadList
  • UploadSearchResultList

Functions

  • addArtspec
  • addSortImages
  • backToMainArea
  • buildArticleSelect
  • buildCategorySelect
  • buildCategorySelectRights
  • buildHeapTable
  • buildStackString
  • buildTree
  • buildUserOrGroupPermsFromRequest
  • callPluginStore
  • cApiCatGetLevelNode
  • cApiImageCheckCachedImageValidity
  • cApiImageCheckImageEditingPosibility
  • cApiImageGetCacheFileName
  • cApiImageGetTargetDimensions
  • cApiImageIsAnimGif
  • cApiImgScale
  • cApiImgScaleGetMD5CacheFile
  • cApiImgScaleHQ
  • cApiImgScaleImageMagick
  • cApiImgScaleLQ
  • cApiIsImageMagickAvailable
  • cApiStrCleanURLCharacters
  • cApiStrNormalizeLineEndings
  • cApiStrRecodeString
  • cApiStrReplaceDiacritics
  • cApiStrTrimAfterWord
  • cApiStrTrimHard
  • cApiStrTrimSentence
  • cDeprecated
  • cDie
  • cError
  • checkLangInClients
  • checkPathInformation
  • cInclude
  • compareUrlStrings
  • conChangeTemplateForCat
  • conCopyArticle
  • conCopyArtLang
  • conCopyContainerConf
  • conCopyContent
  • conCopyMetaTags
  • conCopyTemplateConfiguration
  • conCreateLocationString
  • conDeeperCategoriesArray
  • conDeleteart
  • conEditArt
  • conEditFirstTime
  • conFetchCategoryTree
  • conFlagOnOffline
  • conGenerateCode
  • conGenerateCodeForAllArts
  • conGenerateCodeForAllArtsInCategory
  • conGenerateCodeForAllartsUsingLayout
  • conGenerateCodeForAllartsUsingMod
  • conGenerateCodeForAllArtsUsingTemplate
  • conGenerateCodeForArtInAllCategories
  • conGenerateCodeForClient
  • conGenerateKeywords
  • conGetAvailableMetaTagTypes
  • conGetCategoryArticleId
  • conGetCategoryAssignments
  • conGetContainerConfiguration
  • conGetContentFromArticle
  • conGetHtmlTranslationTable
  • conGetMetaValue
  • conGetTemplateConfigurationIdForArticle
  • conGetTemplateConfigurationIdForCategory
  • conGetTopmostCat
  • conGetUsedModules
  • conHtmlentities
  • conHtmlEntityDecode
  • conHtmlSpecialChars
  • conIsLocked
  • conLock
  • conLockBulkEditing
  • conMakeArticleIndex
  • conMakeCatOnline
  • conMakeInlineScript
  • conMakeOnline
  • conMakeOnlineBulkEditing
  • conMakePublic
  • conMakeStart
  • conMoveArticles
  • conPhp54Check
  • conRemoveOldCategoryArticle
  • conSaveContentEntry
  • conSetCodeFlag
  • conSetCodeFlagBulkEditing
  • conSetMetaValue
  • conSyncArticle
  • copyRightsForElement
  • createBulkEditingFunction
  • createRandomName
  • createRightsForElement
  • cWarning
  • dbGetColumns
  • dbGetIndexes
  • dbGetPrimaryKeyName
  • dbTableExists
  • dbUpgradeTable
  • defineIfNotDefined
  • deleteArtspec
  • deleteRightsForElement
  • deleteSystemProperty
  • displayDatetime
  • emptyLogFile
  • endAndLogTiming
  • extractNumber
  • generateDisplayFilePath
  • generateJs
  • getAllClientsAndLanguages
  • getArtLang
  • getArtspec
  • getAvailableContentTypes
  • getCanonicalDay
  • getCanonicalMonth
  • getDirectorySize
  • getEffectiveSetting
  • getEffectiveSettingsByType
  • getEncodingByLanguage
  • getFileContents
  • getFileInformation
  • getFileType
  • getGroupOrUserName
  • getIDForArea
  • getJsHelpContext
  • getLanguageNamesByClient
  • getLanguagesByClient
  • getmicrotime
  • getNamedFrame
  • getParam
  • getParentAreaId
  • getSearchResults
  • getStrExpandCollapseButton
  • getSystemProperties
  • getSystemPropertiesByType
  • getSystemProperty
  • getTemplateSelect
  • getUplExpandCollapseButton
  • htmldecode
  • htmlentities_iso88592
  • humanReadableSize
  • includePlugins
  • insertEmptyStrRow
  • ipMatch
  • isAlphanumeric
  • isArchive
  • isArtInMultipleUse
  • isFunctionDisabled
  • isGroup
  • isIPv4
  • isRunningFromWeb
  • isStartArticle
  • isUtf8
  • isValidMail
  • langActivateDeactivateLanguage
  • langDeleteLanguage
  • langEditLanguage
  • langGetTextDirection
  • langNewLanguage
  • langRenameLanguage
  • layDeleteLayout
  • layEditLayout
  • machineReadableSize
  • mailLogBulkEditingFunctions
  • mailLogDecodeAddresses
  • markSubMenuItem
  • mask
  • modDeleteModule
  • modEditModule
  • phpInfoToHtml
  • plugin_include
  • prCreateURLNameLocationString
  • prDeleteCacheFileContent
  • prGetCacheFileContent
  • prResolvePathViaCategoryNames
  • prResolvePathViaURLNames
  • prWriteCacheFileContent
  • putFileContents
  • recursiveCopy
  • removeFileInformation
  • renderBackendBreadcrumb
  • renderLabel
  • renderSelectProperty
  • renderTextProperty
  • saveGroupRights
  • saveRights
  • scanDirectory
  • scanPlugins
  • sendEncodingHeader
  • set_magic_quotes_gpc
  • setArtspecDefault
  • setArtspecOnline
  • setSystemProperty
  • showTree
  • startTiming
  • statCreateLocationString
  • statDisplayTopChooser
  • statDisplayYearlyTopChooser
  • statGetAvailableMonths
  • statGetAvailableYears
  • statResetStatistic
  • statsArchive
  • statsDisplayInfo
  • statsOverviewAll
  • statsOverviewTop
  • statsOverviewTopYear
  • statsOverviewYear
  • strAssignTemplate
  • strBuildSqlValues
  • strCheckTreeForErrors
  • strCopyCategory
  • strCopyTree
  • strDeeperCategoriesArray
  • strDeleteCategory
  • strHasArticles
  • strHasStartArticle
  • strMakePublic
  • strMakeVisible
  • strMoveCatTargetallowed
  • strMoveDownCategory
  • strMoveSubtree
  • strMoveUpCategory
  • strNewCategory
  • strNewTree
  • strNextBackwards
  • strNextDeeper
  • strNextDeeperAll
  • strNextPost
  • strOrderedPostTreeList
  • strRemakeTreeTable
  • strRenameCategory
  • strRenameCategoryAlias
  • strSortPrePost
  • strSyncCategory
  • systemHavePerm
  • tplAutoFillModules
  • tplBrowseLayoutForContainers
  • tplcfgDuplicate
  • tplDeleteTemplate
  • tplDuplicateTemplate
  • tplEditTemplate
  • tplGetContainerDefault
  • tplGetContainerMode
  • tplGetContainerName
  • tplGetContainerNumbersInLayout
  • tplGetContainerTypes
  • tplGetInUsedData
  • tplIsTemplateInUse
  • tplPreparseLayout
  • tplProcessSendContainerConfiguration
  • updateClientCache
  • updateFileInformation
  • uplCreateFriendlyName
  • uplDirectoryListRecursive
  • uplGetDirectoriesToExclude
  • uplGetFileExtension
  • uplGetFileIcon
  • uplGetFileTypeDescription
  • uplGetThumbnail
  • uplHasFiles
  • uplHasSubdirs
  • uplmkdir
  • uplRecursiveDBDirectoryList
  • uplRecursiveDirectoryList
  • uplRenameDirectory
  • uplSearch
  • uplSyncDirectory
  • uplSyncDirectoryDBFS
  • Overview
  • Package
  • Class
  • Tree
  • Deprecated
  • Todo
  1: <?php
  2: /**
  3:  * This file contains the the password request class.
  4:  *
  5:  * @package Core
  6:  * @subpackage Backend
  7:  * @author Timo Trautmann
  8:  * @copyright four for business AG <www.4fb.de>
  9:  * @license http://www.contenido.org/license/LIZENZ.txt
 10:  * @link http://www.4fb.de
 11:  * @link http://www.contenido.org
 12:  */
 13: 
 14: defined('CON_FRAMEWORK') || die('Illegal call: Missing framework initialization - request aborted.');
 15: 
 16: /**
 17:  * Class for handling passwort recovery for backend users.
 18:  * If a user has set his e-mail address, this class
 19:  * generates a new Password for user and submits to his e-mail address.
 20:  * Submitting a new Password is
 21:  * only possible every 30 minutes Mailsender, Mailsendername and Mailserver are
 22:  * set into system properties.
 23:  * There it is also possible to deactivate this feature.
 24:  *
 25:  * @package Core
 26:  * @subpackage Backend
 27:  */
 28: class cPasswordRequest {
 29: 
 30:     /**
 31:      * The CONTENIDO database object
 32:      *
 33:      * @var cDb
 34:      */
 35:     protected $_db;
 36: 
 37:     /**
 38:      * The CONTENIDO configuration array
 39:      *
 40:      * @var array
 41:      */
 42:     protected $_cfg;
 43: 
 44:     /**
 45:      * The CONTENIDO template object
 46:      *
 47:      * @var cTemplate
 48:      */
 49:     protected $_tpl;
 50: 
 51:     /**
 52:      * Username of user which requests password
 53:      *
 54:      * @var string
 55:      */
 56:     protected $_username;
 57: 
 58:     /**
 59:      * E-mail address of user which requests password
 60:      *
 61:      * @var string
 62:      */
 63:     protected $_email;
 64: 
 65:     /**
 66:      * Time in minutes after which user is allowed to request a new password
 67:      *
 68:      * @var int
 69:      */
 70:     protected $_reloadTime;
 71: 
 72:     /**
 73:      * Length of validation token, which is generated automatically
 74:      *
 75:      * @var int
 76:      */
 77:     protected $_tokenLength;
 78: 
 79:     /**
 80:      * Defines if passwort request is enabled or disabled.
 81:      * Default: This feature is enabled
 82:      *
 83:      * @var bool
 84:      */
 85:     protected $_isEnabled;
 86: 
 87:     /**
 88:      * E-mail address of the sender
 89:      *
 90:      * @var string
 91:      */
 92:     protected $_sendermail;
 93: 
 94:     /**
 95:      * Name of the sender
 96:      *
 97:      * @var string
 98:      */
 99:     protected $_sendername;
100: 
101:     /**
102:      * Constructor to create an instance of this class.
103:      *
104:      * Initializes class variables.
105:      *
106:      * @param cDb $db
107:      *         The CONTENIDO database object
108:      * @param array $cfg
109:      *         The CONTENIDO configuration array
110:      */
111:     public function __construct($db, $cfg) {
112:         // generate new dbobject, if it does not exist
113:         if (!is_object($db)) {
114:             $this->_db = cRegistry::getDb();
115:         } else {
116:             $this->_db = $db;
117:         }
118: 
119:         // init class variables
120:         $this->_cfg = $cfg;
121:         $this->_tpl = new cTemplate();
122:         $this->_username = '';
123:         $this->_email = '';
124: 
125:         // set reload to 4 hours (60*4 minutes)
126:         $this->_reloadTime = 240;
127: 
128:         // set token length to 14 chars
129:         $this->_tokenLength = 14;
130: 
131:         // get systemproperty, which definies if password request is enabled
132:         // (true) or disabled (false) : default to enabled
133:         $sEnable = getSystemProperty('pw_request', 'enable');
134:         if ($sEnable == 'false') {
135:             $this->_isEnabled = false;
136:         } else {
137:             $this->_isEnabled = true;
138:         }
139: 
140:         // get systemproperty for senders mail and validate mail address, if not
141:         // set use standard sender
142:         $sendermail = getSystemProperty('system', 'mail_sender');
143:         if (preg_match("/^.+@.+\.([A-Za-z0-9\-_]{1,20})$/", $sendermail)) {
144:             $this->_sendermail = $sendermail;
145:         } else {
146:             $this->_sendermail = 'info@contenido.org';
147:         }
148: 
149:         // get systemproperty for senders name, if not set use CONTENIDO Backend
150:         $sendername = getSystemProperty('system', 'mail_sender_name');
151:         if ($sendername != '') {
152:             $this->_sendername = $sendername;
153:         } else {
154:             $this->_sendername = 'CONTENIDO Backend';
155:         }
156: 
157:         // show form if password reset is wished
158:         // if feature is not enabled, do nothing
159:         if (true === $this->_isEnabled) {
160:             // check if confirmation link from mail used
161:             if (isset($_GET['pw_reset'])
162:             && '' !== $_GET['pw_reset']) {
163:                 // check if requests found
164:                 $aRequests = $this->_getCurrentRequests();
165:                 if (count($aRequests) > 0) {
166:                     // check if form with username and new password was filled out
167:                     if (false === isset($_POST['user_name'])
168:                     || false === isset($_POST['user_pw'])
169:                     || false === isset($_POST['user_pw_repeat'])) {
170:                         // show form to set new password
171:                         $this->renderNewPwForm();
172:                     } else {
173:                         // do validation checks then set new password for user in database
174:                         $this->_handleResetPw();
175:                     }
176:                 }
177:             }
178:         }
179:     }
180: 
181:     /**
182:      * Function displays form for password request, if
183:      * password is submitted this function also starts the
184:      * passwort reset request and sending process
185:      *
186:      * @param bool $return [optional]
187:      *         Return or print template
188:      * @return string
189:      *         rendered HTML code
190:      */
191:     public function renderForm($return = false) {
192:         // if feature is not enabled, do nothing
193:         if (!$this->_isEnabled) {
194:             return '';
195:         }
196: 
197:         $message = '';
198: 
199:         // if form is sumbitted call function handleNewPassword() and set
200:         // submitted username to class variable $sUsername
201:         if (isset($_POST['action']) && $_POST['action'] == 'request_pw') {
202:             // avoid SQL-Injection, first check if submitted vars are escaped
203:             // automatically
204:             $this->_username = $_POST['request_username'];
205: 
206:             $message = $this->_handleNewPassword();
207:             // if form is submitted, show corresponding password request layer
208:             $this->_tpl->set('s', 'JS_CALL', 'showRequestLayer();');
209:         } else {
210:             // by default request layer is invisible so do nothing
211:             $this->_tpl->set('s', 'JS_CALL', '');
212:         }
213: 
214:         // generate new form
215:         $form = new cHTMLForm('request_pw', 'index.php', 'post');
216: 
217:         // generate input for username
218:         $inputUsername = new cHTMLTextbox('request_username', stripslashes($_POST['request_username']), '', '', 'request_username');
219:         $inputUsername->setStyle('width:215px;');
220: 
221:         // set request action and current language
222:         $form->setVar('action', 'request_pw');
223:         $form->setVar('belang', $GLOBALS['belang']);
224: 
225:         // generate submitbutton and fill the form
226:         $form->setContent('<input class="password_request_input" type="image" src="images/submit.gif" alt="' . i18n('Submit') . '" title="' . i18n('Submit') . '">' . $inputUsername->render());
227:         $this->_tpl->set('s', 'FORM', $form->render());
228:         $this->_tpl->set('s', 'MESSAGE', $message);
229:         $this->_tpl->set('s', 'LABEL', i18n('Please enter your login') . ':');
230: 
231:         // if handleNewPassword() returns a message, display it
232:         return $this->_tpl->generate($this->_cfg['path']['contenido'] . $this->_cfg['path']['templates'] . $this->_cfg['templates']['request_password'], $return);
233:     }
234: 
235:     /**
236:      * function to display form to set new password for user
237:      */
238:     public function renderNewPwForm() {
239:         if (isset($_POST['action']) && $_POST['action'] == 'reset_pw') {
240:             $this->_username = $_POST['request_username'];
241: 
242:             $message = $this->_handleNewPassword();
243:             // do not show password reset form
244:             $this->_tpl->set('s', 'JS_CALL', '');
245:         } else {
246:             // show password reset form using JavaScript
247:             $this->_tpl->set('s', 'JS_CALL', 'showResetLayer();');
248:         }
249: 
250:         $msg = i18n('You may now set a new password');
251:         $this->_tpl->set('s', 'RESET_LABEL', $msg);
252: 
253:         // insert form with username, password and password repeat fields
254:         $form = new cHTMLForm('reset_form', htmlentities(cRegistry::getBackendUrl()) . '?pw_reset=' . $_GET['pw_reset']);
255: 
256:         $fields = array();
257:         $userNameLbl = new cHTMLDiv(new cHTMLLabel(i18n('User name') . ': ', 'user_name'));
258:         $userNameBox = new cHTMLTextbox('user_name');
259:         $userNameBox->removeAttribute('size');
260:         $userNameBox = new cHTMLDiv($userNameBox);
261: 
262:         $userPwLbl = new cHTMLLabel(i18n('New password') . ': ', 'user_pw');
263:         $userPwBox = new cHTMLTextbox('user_pw');
264:         $userPwBox->setAttribute('type', 'password');
265:         $userPwBox->removeAttribute('size');
266:         $userPwBox = new cHTMLDiv($userPwBox);
267: 
268:         $userPwRepeatLbl = new cHTMLLabel(i18n('Confirm new password'), 'user_pw_repeat');
269:         $userPwRepeatBox = new cHTMLTextbox('user_pw_repeat');
270:         $userPwRepeatBox->setAttribute('type', 'password');
271:         $userPwRepeatBox->removeAttribute('size');
272: 
273:         $sendBtn = new cHTMLButton('submit');
274:         $sendBtn->setAttribute('type', 'image');
275:         $sendBtn->setAttribute('src', 'images/submit.gif');
276:         $sendBtn->setAttribute('alt', i18n('Submit'));
277:         $sendBtn->setAttribute('title', i18n('Submit'));
278: 
279:         $sendBtn->removeAttribute('value');
280:         $form->setContent(array($userNameLbl, $userNameBox, $userPwLbl, $userPwBox, $userPwRepeatLbl, $userPwRepeatBox, $sendBtn));
281: 
282:         $this->_tpl->set('s', 'RESET_MESSAGE', '');
283: 
284:         $this->_tpl->set('s', 'RESET_FORM', $form->render());
285:     }
286: 
287:     /**
288:      * Getter function to obtain an array of all current user password reset requests
289:      *
290:      * @return array
291:      */
292:     protected function _getCurrentRequests() {
293:         $oApiUserPasswordRequest = new cApiUserPasswordRequestCollection();
294: 
295:         return $oApiUserPasswordRequest->fetchCurrentRequests();
296:     }
297: 
298:     /**
299:      * Function checks password request for errors and sends a mail using
300:      * _submitMail() in case of valid requests
301:      *
302:      * @return string
303:      */
304:     protected function _handleNewPassword() {
305:         // notification message, which is returned to caller
306:         $message = '';
307: 
308:         // check if requested username exists, also get email and timestamp when
309:         // user last requests a new password (last_pw_request)
310: //         $ocApiUser = new cApiUser(cSecurity::toInteger($this->_username));
311:         $sql = "SELECT username, email FROM " . $this->_cfg['tab']['user'] . "
312:                  WHERE username = '" . $this->_db->escape($this->_username) . "'
313:                  AND (valid_from <= NOW() OR valid_from = '0000-00-00 00:00:00' OR valid_from IS NULL)
314:                  AND (valid_to >= NOW() OR valid_to = '0000-00-00 00:00:00' OR valid_to IS NULL)";
315: 
316:         $this->_db->query($sql);
317:         if ($this->_db->nextRecord() && md5($this->_username) == md5($this->_db->f('username'))) {
318:             // by default user is allowed to request new password
319:             $isAllowed = true;
320: 
321:             // we need latest password request for timelimit comparison
322:             $lastPwRequest = '0000-00-00 00:00:00';
323: 
324:             // check if user has already used max amount of reset requests
325:             $oApiUser = new cApiUser();
326:             // try to load user by name
327:             // this should always work because username in database already confirmed
328:             if (false === $oApiUser->loadBy('username', $this->_username)) {
329:                 $isAllowed = false;
330:                 $message = i18n('New password was submitted to your e-mail address.');
331:             } else {
332:                 $oApiPasswordRequestCol = new cApiUserPasswordRequestCollection();
333:                 $requests = $oApiPasswordRequestCol->fetchAvailableRequests();
334: 
335:                 // do maintainance for all user password requests
336:                 foreach ($requests as $oApiUserPasswordRequest) {
337:                     // get time of password reset request
338:                     $reqTime = $oApiUserPasswordRequest->get('request');
339: 
340:                     // if $reqTime is newer than $lastPwRequest then use this as new last password request time
341:                     if (strtotime($lastPwRequest) < strtotime($reqTime)
342:                     && $this->_db->f($oApiUser->getPrimaryKeyName()) === $oApiUser->get($oApiUser->getPrimaryKeyName())) {
343:                         $lastPwRequest = $reqTime;
344:                     }
345: 
346:                     // check if password request is too old and considered outdated
347:                     // by default 1 day old requests are outdated
348:                     if (false === ($outdatedStr = getEffectiveSetting('pw_request', 'outdated_threshold', false))
349:                     || '' === $outdatedStr) {
350:                         $outdatedStr = '-1 day';
351:                     }
352:                     // convert times to DateTime objects for comparison
353:                     // force all data to be compared using UTC timezone
354:                     $outdated = new DateTime('now', new DateTimeZone('UTC'));
355:                     $outdated->modify($outdatedStr);
356:                     $expiration = new DateTime($oApiUserPasswordRequest->get('expiration'), new DateTimeZone('UTC'));
357:                     if (false === $oApiUserPasswordRequest->get('expiration')
358:                     || '' === $oApiUserPasswordRequest->get('expiration')
359:                     || $expiration < $outdated) {
360:                         // delete password request as it is considered outdated
361:                         $oApiPasswordRequestCol->delete($oApiUserPasswordRequest->get($oApiUserPasswordRequest->getPrimaryKeyName()));
362:                     }
363:                 }
364: 
365:                 // get all password reset requests related to entered username in form
366:                 $uid = $oApiUser->get($oApiUser->getPrimaryKeyName());
367:                 $requests = $oApiPasswordRequestCol->fetchAvailableRequests($uid);
368: 
369:                 // get amount of max password reset requests
370:                 if (false === ($resetThreshold = getEffectiveSetting('pw_request', 'reset_threshold', false))
371:                 || '' === $resetThreshold) {
372:                     // use 4 as default value
373:                     $resetThreshold = 4;
374:                 }
375: 
376:                 // check if there are more than allowed number of password requests for user
377:                 if (count($requests) > $resetThreshold) {
378:                     $isAllowed = false;
379:                     $message = i18n('Too many password reset requests. You may wait before requesting a new password.');
380:                 }
381:                 unset($requests);
382:             }
383: 
384:             // store users mail address to class variable
385:             $this->_email = $this->_db->f('email');
386: 
387:             // check if there is a correct last request date
388:             if (preg_match('/^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})$/', $lastPwRequest, $aMatches)) {
389:                 $lastRequest = mktime($aMatches[4], $aMatches[5], $aMatches[6], $aMatches[2], $aMatches[3], $aMatches[1]);
390: 
391:                 // check if this last request is longer ago than timelimit.
392:                 if ((time() - $lastRequest) < (60 * $this->_reloadTime)) {
393:                     // user is not allowed to request new password, he has to wait
394:                     $isAllowed = false;
395:                     $message = sprintf(i18n('Password requests are allowed every %s minutes.'), $this->_reloadTime);
396:                 }
397:             }
398: 
399:             $this->_username = stripslashes($this->_username);
400: 
401: 
402:             // check if syntax of users mail address is correct and there is no
403:             // standard mail address like admin_kunde@IhreSite.de or
404:             // sysadmin@IhreSite.de
405:             if ((!preg_match("/^.+@.+\.([A-Za-z0-9\-_]{1,20})$/", $this->_email) || $this->_email == 'sysadmin@IhreSite.de' || $this->_email == 'admin_kunde@IhreSite.de') && $isAllowed) {
406:                 $isAllowed = false;
407:                 // $sMessage = i18n('The requested user has no valid e-mail
408:                 // address. Submitting new password is not possible. Please
409:                 // contact your system- administrator for further support.');
410:                 $message = i18n('No matching data found. Please contact your system administrator.');
411:             }
412: 
413:             // if there are no errors, call function _generateToken(), else wait
414:             // a while, then return error message
415:             if ($isAllowed) {
416:                 // generate a new token
417:                 $token = $this->_generateToken();
418: 
419:                 // how long should the password reset request be valid?
420:                 // use 4 hours as expiration time
421:                 $expiration = new DateTime('+4 hour', new DateTimeZone('UTC'));
422: 
423:                 if (false !== $token
424:                 && false !== $this->_safePwResetRequest($token, $expiration)) {
425:                     $this->_submitMail($token);
426:                     $message = i18n('New password was submitted to your e-mail address.');
427:                 } else {
428:                     $message = i18n('An unknown problem occurred. Please contact your system administrator.');
429:                 }
430:             } else {
431:                 sleep(5);
432:             }
433:         } else {
434:             // sleep a while, then return error message
435:             // $sMessage = i18n('This user does not exist.');
436:             $message = i18n('No matching data found. Please contact your system administrator.');
437:             sleep(5);
438:         }
439:         return $message;
440:     }
441: 
442:     /**
443:      * Function checks password reset request for errors and sets a new password in case there is no error
444:      */
445:     protected function _handleResetPw() {
446:         $this->_tpl->set('s', 'JS_CALL', 'showResetLayer();');
447:         $username = (string) $_POST['user_name'];
448:         $pw = (string) $_POST['user_pw'];
449:         $pwRepeat = (string) $_POST['user_pw_repeat'];
450: 
451:         if (0 === strlen($username)) {
452:             $this->_tpl->set('s', 'RESET_MESSAGE', i18n('Username can\'t be empty'));
453:             $this->_tpl->set('s', 'RESET_LABEL', '');
454:             $this->renderNewPwForm();
455:             return;
456:         }
457:         if ($pw !== $pwRepeat) {
458:             $this->_tpl->set('s', 'RESET_MESSAGE', i18n('Passwords don\'t match'));
459:             $this->_tpl->set('s', 'RESET_LABEL', '');
460:             $this->renderNewPwForm();
461:             return;
462:         }
463:         if ((string) $_POST['user_pw'] === (string) $_GET['pw_reset']) {
464:             $this->_tpl->set('s', 'RESET_MESSAGE', i18n('You may not use the confirmation token as password'));
465:             $this->_tpl->set('s', 'RESET_LABEL', '');
466:             $this->renderNewPwForm();
467:             return;
468:         }
469: 
470:         // pass data to cApiUser class
471:         $oApiUser = new cApiUser();
472:         $oApiUser->loadUserByUsername($username);
473:         // check if user exists
474:         if (false === $oApiUser->isLoaded()) {
475:             // present same message as if it worked
476:             // so we do not give information whether a user exists
477:             $this->_tpl->set('s', 'RESET_MESSAGE', i18n('New password has been set.'));
478:             $this->_tpl->set('s', 'RESET_LABEL', '');
479:             $this->_tpl->set('s', 'RESET_FORM', '');
480:             return;
481:         }
482: 
483:         $oPasswordRequest = new cApiUserPasswordRequestCollection();
484:         // check if username matches validation token
485:         // user alice must not be able to set password for a different user bob
486: 
487:         // get available requests for all users
488:         if (null === ($requests = $this->_getCurrentRequests())) {
489:             // no password requests found but do not tell user
490:             $this->_tpl->set('s', 'RESET_MESSAGE', i18n('New password has been set.'));
491:             $this->_tpl->set('s', 'RESET_LABEL', '');
492:             $this->_tpl->set('s', 'RESET_FORM', '');
493:             return;
494:         }
495: 
496:         // check if passed get parameter matches request for one user
497:         $validUser = false;
498:         foreach ($requests as $request) {
499:             // match validation token against database password reset entry
500:             if ($request->get('validation_token') === $_GET['pw_reset'])
501:             {
502:                 // we found the used token
503:                 if ($oApiUser->get($oApiUser->getPrimaryKeyName()) === $request->get($oApiUser->getPrimaryKeyName())) {
504:                     // user entered in form matches user related to validation token
505:                     $validUser = true;
506:                 }
507:             }
508:         }
509:         if (false === $validUser) {
510:             // no password requests found for this user
511:             // but let the user think it could set password for different user
512:             $this->_tpl->set('s', 'RESET_MESSAGE', i18n('New password has been set.'));
513:             $this->_tpl->set('s', 'RESET_LABEL', '');
514:             $this->_tpl->set('s', 'RESET_FORM', '');
515:             return;
516:         }
517: 
518:         // try to set password
519:         $res = $oApiUser->setPassword($pw);
520: 
521:         $msg = '';
522:         // check if password was accepted by cApiUser class
523:         if (cApiUser::PASS_OK !== $res) {
524:             // password not accepted, present error message from cApiUser class to end user
525:             $msg = cApiUser::getErrorString($res);
526:             $this->_tpl->set('s', 'RESET_MESSAGE', $msg);
527:             $this->_tpl->set('s', 'RESET_LABEL', '');
528:             $this->renderNewPwForm();
529:             return;
530:         }
531:         // check if new password can be saved for user
532:         if (false !== $oApiUser->store()) {
533:             $this->_tpl->set('s', 'RESET_LABEL', '');
534:             $this->_tpl->set('s', 'RESET_FORM', '');
535:             // remove all password requests for this user from database
536:             $oPasswordRequest->deleteByUserId($oApiUser->get($oApiUser->getPrimaryKeyName()));
537:             $msg = i18n('New password has been set.');
538:         } else {
539:             // password could not be saved
540:             $msg = i18n('An unknown problem occurred. Please contact your system administrator.');
541:         }
542: 
543:         // display message in form
544:         $this->_tpl->set('s', 'RESET_MESSAGE', $msg);
545:     }
546: 
547:     /**
548:      * Save request into db for future validity check
549:      * @param string $token
550:      *         Token used to check for validity at user confirmation part
551:      * @param DateTime
552:      *         Expiration time of reset request validity
553:      * @return bool
554:      *         whether password request could be safed successfully
555:      */
556:     protected function _safePwResetRequest($token, DateTime $expiration) {
557:         $oUserPwRequestCol = new cApiUserPasswordRequestCollection();
558:         $oUserPwRequest = $oUserPwRequestCol->createNewItem();
559: 
560:         // set request data
561:         $requestTime = new DateTime('now', new DateTimeZone('UTC'));
562:         $oApiUser = new cApiUser();
563:         $oApiUser->loadBy('username', $this->_username);
564: 
565:         $oUserPwRequest->set($oApiUser->getPrimaryKeyName(), $oApiUser->get($oApiUser->getPrimaryKeyName()));
566:         $oUserPwRequest->set('request', $requestTime->format('Y-m-d H:i:s'));
567:         $oUserPwRequest->set('expiration', $expiration->format('Y-m-d H:i:s'));
568:         $oUserPwRequest->set('validation_token', $token);
569: 
570:         // save request data
571:         return $oUserPwRequest->store();
572:     }
573: 
574:     /**
575:      * Function submits new password to users mail address
576:      *
577:      * @param string $token
578:      *         The token used to authorise password change
579:      */
580:     protected function _submitMail($token) {
581:         $cfg = cRegistry::getConfig();
582: 
583:         $token = (string) $token;
584: 
585:         // get translation for mailbody and insert username and new password
586:         $msg = i18n("Dear CONTENIDO-User %s,\n\nA request to change your password for Content Management System CONTENIDO was made. ");
587:         $msg .= i18n("Use the following URL to confirm the password change:\n\n");
588:         $msg .= cRegistry::getBackendUrl() . '?pw_reset=';
589:         $msg .= i18n("%s\n\nBest regards\n\nYour CONTENIDO sysadmin");
590:         $mailBody = sprintf($msg, $this->_username, $token);
591: 
592:         $mailer = new cMailer();
593:         $from = array(
594:             $this->_sendermail => $this->_sendername
595:         );
596: 
597:         // Decoding and encoding for charsets (without UTF-8)
598:         if ($cfg['php_settings']['default_charset'] != 'UTF-8') {
599:             $subject = utf8_encode(conHtmlEntityDecode(stripslashes(i18n('Your new password for CONTENIDO Backend')), '', $cfg['php_settings']['default_charset']));
600:             $body = utf8_encode(conHtmlEntityDecode($mailBody, '', $cfg['php_settings']['default_charset']));
601:         } else {
602:             $subject = conHtmlEntityDecode(stripslashes(i18n('Your new password for CONTENIDO Backend')));
603:             $body = conHtmlEntityDecode($mailBody);
604:         }
605: 
606:         $mailer->sendMail($from, $this->_email, $subject, $body);
607:     }
608: 
609:     /**
610:      * Function generates new token
611:      *
612:      * @return string
613:      *         The new token
614:      */
615:     protected function _generateToken() {
616:         // possible chars which were used in password
617:         $chars = "ABCDEFGHJKLMNOPQRSTUVWXYZabcdefghjkmnopqrstuvwxyz123456789";
618: 
619:         $password = "";
620: 
621:         // for each character of token choose one from $sChars randomly
622:         for ($i = 0; $i < $this->_tokenLength; $i++) {
623:             $password .= $chars[rand(0, strlen($chars))];
624:         }
625: 
626:         return $password;
627:     }
628: }
629: 
CMS CONTENIDO 4.9.11 API documentation generated by ApiGen 2.8.0