/** * Run the controller and parse the password template */ public function run() { $this->Template = new BackendTemplate('be_password'); if (Input::post('FORM_SUBMIT') == 'tl_password') { $pw = Input::postRaw('password'); $cnf = Input::postRaw('confirm'); // The passwords do not match if ($pw != $cnf) { Message::addError($GLOBALS['TL_LANG']['ERR']['passwordMatch']); } elseif (utf8_strlen($pw) < Config::get('minPasswordLength')) { Message::addError(sprintf($GLOBALS['TL_LANG']['ERR']['passwordLength'], Config::get('minPasswordLength'))); } elseif ($pw == $this->User->username) { Message::addError($GLOBALS['TL_LANG']['ERR']['passwordName']); } else { // Make sure the password has been changed if (crypt($pw, $this->User->password) === $this->User->password) { Message::addError($GLOBALS['TL_LANG']['MSC']['pw_change']); } else { $this->loadDataContainer('tl_user'); // Trigger the save_callback if (is_array($GLOBALS['TL_DCA']['tl_user']['fields']['password']['save_callback'])) { foreach ($GLOBALS['TL_DCA']['tl_user']['fields']['password']['save_callback'] as $callback) { if (is_array($callback)) { $this->import($callback[0]); $pw = $this->{$callback}[0]->{$callback}[1]($pw); } elseif (is_callable($callback)) { $pw = $callback($pw); } } } $objUser = UserModel::findByPk($this->User->id); $objUser->pwChange = ''; $objUser->password = Encryption::hash($pw); $objUser->save(); Message::addConfirmation($GLOBALS['TL_LANG']['MSC']['pw_changed']); $this->redirect('contao/main.php'); } } $this->reload(); } $this->Template->theme = Backend::getTheme(); $this->Template->messages = Message::generate(); $this->Template->base = Environment::get('base'); $this->Template->language = $GLOBALS['TL_LANGUAGE']; $this->Template->title = specialchars($GLOBALS['TL_LANG']['MSC']['pw_new']); $this->Template->charset = Config::get('characterSet'); $this->Template->action = ampersand(Environment::get('request')); $this->Template->headline = $GLOBALS['TL_LANG']['MSC']['pw_change']; $this->Template->submitButton = specialchars($GLOBALS['TL_LANG']['MSC']['continue']); $this->Template->password = $GLOBALS['TL_LANG']['MSC']['password'][0]; $this->Template->confirm = $GLOBALS['TL_LANG']['MSC']['confirm'][0]; $this->Template->output(); }
/** * {@inheritdoc} */ public function handle(\Input $input) { $configFile = new \File($this->configPathname); if ($input->post('save')) { $tempPathname = $this->configPathname . '~'; $tempFile = new \File($tempPathname); $config = $input->postRaw('config'); $config = html_entity_decode($config, ENT_QUOTES, 'UTF-8'); $tempFile->write($config); $tempFile->close(); $validator = new ConfigValidator($this->io); list($errors, $publishErrors, $warnings) = $validator->validate(TL_ROOT . '/' . $tempPathname); if (!$errors && !$publishErrors) { $_SESSION['TL_CONFIRM'][] = $GLOBALS['TL_LANG']['composer_client']['configValid']; $this->import('Files'); $this->Files->rename($tempPathname, $this->configPathname); } else { $tempFile->delete(); $_SESSION['COMPOSER_EDIT_CONFIG'] = $config; if ($errors) { foreach ($errors as $message) { $_SESSION['TL_ERROR'][] = 'Error: ' . $message; } } if ($publishErrors) { foreach ($publishErrors as $message) { $_SESSION['TL_ERROR'][] = 'Publish error: ' . $message; } } } if ($warnings) { foreach ($warnings as $message) { $_SESSION['TL_ERROR'][] = 'Warning: ' . $message; } } $this->reload(); } if (isset($_SESSION['COMPOSER_EDIT_CONFIG'])) { $config = $_SESSION['COMPOSER_EDIT_CONFIG']; unset($_SESSION['COMPOSER_EDIT_CONFIG']); } else { $config = $configFile->getContent(); } $template = new \BackendTemplate('be_composer_client_editor'); $template->composer = $this->composer; $template->config = $config; return $template->parse(); }
/** * Return a search form that allows to search results using regular expressions * * @return string */ protected function searchMenu() { $searchFields = array(); $session = $this->Session->getData(); // Get search fields foreach ($GLOBALS['TL_DCA'][$this->strTable]['fields'] as $k => $v) { if ($v['search']) { $searchFields[] = $k; } } // Return if there are no search fields if (empty($searchFields)) { return ''; } // Store search value in the current session if (\Input::post('FORM_SUBMIT') == 'tl_filters') { $session['search'][$this->strTable]['value'] = ''; $session['search'][$this->strTable]['field'] = \Input::post('tl_field', true); // Make sure the regular expression is valid if (\Input::postRaw('tl_value') != '') { try { $this->Database->prepare("SELECT * FROM " . $this->strTable . " WHERE " . \Input::post('tl_field', true) . " REGEXP ?")->limit(1)->execute(\Input::postRaw('tl_value')); $session['search'][$this->strTable]['value'] = \Input::postRaw('tl_value'); } catch (\Exception $e) { } } $this->Session->setData($session); } elseif ($session['search'][$this->strTable]['value'] != '') { $strPattern = "CAST(%s AS CHAR) REGEXP ?"; if (substr(\Config::get('dbCollation'), -3) == '_ci') { $strPattern = "LOWER(CAST(%s AS CHAR)) REGEXP LOWER(?)"; } $fld = $session['search'][$this->strTable]['field']; if (isset($GLOBALS['TL_DCA'][$this->strTable]['fields'][$fld]['foreignKey'])) { list($t, $f) = explode('.', $GLOBALS['TL_DCA'][$this->strTable]['fields'][$fld]['foreignKey']); $this->procedure[] = "(" . sprintf($strPattern, $fld) . " OR " . sprintf($strPattern, "(SELECT {$f} FROM {$t} WHERE {$t}.id={$this->strTable}.{$fld})") . ")"; $this->values[] = $session['search'][$this->strTable]['value']; } else { $this->procedure[] = sprintf($strPattern, $fld); } $this->values[] = $session['search'][$this->strTable]['value']; } $options_sorter = array(); foreach ($searchFields as $field) { $option_label = $GLOBALS['TL_DCA'][$this->strTable]['fields'][$field]['label'][0] ?: (is_array($GLOBALS['TL_LANG']['MSC'][$field]) ? $GLOBALS['TL_LANG']['MSC'][$field][0] : $GLOBALS['TL_LANG']['MSC'][$field]); $options_sorter[utf8_romanize($option_label) . '_' . $field] = ' <option value="' . specialchars($field) . '"' . ($field == $session['search'][$this->strTable]['field'] ? ' selected="selected"' : '') . '>' . $option_label . '</option>'; } // Sort by option values $options_sorter = natcaseksort($options_sorter); $active = $session['search'][$this->strTable]['value'] != '' ? true : false; return ' <div class="tl_search tl_subpanel"> <strong>' . $GLOBALS['TL_LANG']['MSC']['search'] . ':</strong> <select name="tl_field" class="tl_select' . ($active ? ' active' : '') . '"> ' . implode("\n", $options_sorter) . ' </select> <span> = </span> <input type="search" name="tl_value" class="tl_text' . ($active ? ' active' : '') . '" value="' . specialchars($session['search'][$this->strTable]['value']) . '"> </div>'; }
/** * Load the source editor * * @return string */ public function source() { $this->isValid($this->intId); if (is_dir(TL_ROOT . '/' . $this->intId)) { $this->log('Folder "' . $this->intId . '" cannot be edited', __METHOD__, TL_ERROR); $this->redirect('contao/main.php?act=error'); } elseif (!file_exists(TL_ROOT . '/' . $this->intId)) { $this->log('File "' . $this->intId . '" does not exist', __METHOD__, TL_ERROR); $this->redirect('contao/main.php?act=error'); } $this->import('BackendUser', 'User'); // Check user permission if (!$this->User->hasAccess('f5', 'fop')) { $this->log('Not enough permissions to edit the file source of file "' . $this->intId . '"', __METHOD__, TL_ERROR); $this->redirect('contao/main.php?act=error'); } $objFile = new \File($this->intId, true); // Check whether file type is editable if (!in_array($objFile->extension, trimsplit(',', strtolower(\Config::get('editableFiles'))))) { $this->log('File type "' . $objFile->extension . '" (' . $this->intId . ') is not allowed to be edited', __METHOD__, TL_ERROR); $this->redirect('contao/main.php?act=error'); } $objMeta = null; $objVersions = null; // Add the versioning routines if ($this->blnIsDbAssisted && \Dbafs::shouldBeSynchronized($this->intId)) { $objMeta = \FilesModel::findByPath($objFile->value); if ($objMeta === null) { $objMeta = \Dbafs::addResource($objFile->value); } $objVersions = new \Versions($this->strTable, $objMeta->id); if (!$GLOBALS['TL_DCA'][$this->strTable]['config']['hideVersionMenu']) { // Compare versions if (\Input::get('versions')) { $objVersions->compare(); } // Restore a version if (\Input::post('FORM_SUBMIT') == 'tl_version' && \Input::post('version') != '') { $objVersions->restore(\Input::post('version')); // Purge the script cache (see #7005) if ($objFile->extension == 'css' || $objFile->extension == 'scss' || $objFile->extension == 'less') { $this->import('Automator'); $this->Automator->purgeScriptCache(); } $this->reload(); } } $objVersions->initialize(); } $strContent = $objFile->getContent(); if ($objFile->extension == 'svgz') { $strContent = gzdecode($strContent); } // Process the request if (\Input::post('FORM_SUBMIT') == 'tl_files') { // Restore the basic entities (see #7170) $strSource = \StringUtil::restoreBasicEntities(\Input::postRaw('source')); // Save the file if (md5($strContent) != md5($strSource)) { if ($objFile->extension == 'svgz') { $strSource = gzencode($strSource); } // Write the file $objFile->write($strSource); $objFile->close(); // Update the database if ($this->blnIsDbAssisted && $objMeta !== null) { /** @var \FilesModel $objMeta */ $objMeta->hash = $objFile->hash; $objMeta->save(); $objVersions->create(); } // Purge the script cache (see #7005) if ($objFile->extension == 'css' || $objFile->extension == 'scss' || $objFile->extension == 'less') { $this->import('Automator'); $this->Automator->purgeScriptCache(); } } if (\Input::post('saveNclose')) { \System::setCookie('BE_PAGE_OFFSET', 0, 0); $this->redirect($this->getReferer()); } $this->reload(); } $codeEditor = ''; // Prepare the code editor if (\Config::get('useCE')) { $selector = 'ctrl_source'; $type = $objFile->extension; // Load the code editor configuration ob_start(); include TL_ROOT . '/system/config/ace.php'; $codeEditor = ob_get_contents(); ob_end_clean(); unset($selector, $type); } // Versions overview if ($GLOBALS['TL_DCA'][$this->strTable]['config']['enableVersioning'] && !$GLOBALS['TL_DCA'][$this->strTable]['config']['hideVersionMenu'] && $this->blnIsDbAssisted && $objVersions !== null) { $version = $objVersions->renderDropdown(); } else { $version = ''; } // Submit buttons $arrButtons = array(); $arrButtons['save'] = '<input type="submit" name="save" id="save" class="tl_submit" accesskey="s" value="' . specialchars($GLOBALS['TL_LANG']['MSC']['save']) . '">'; $arrButtons['saveNclose'] = '<input type="submit" name="saveNclose" id="saveNclose" class="tl_submit" accesskey="c" value="' . specialchars($GLOBALS['TL_LANG']['MSC']['saveNclose']) . '">'; // Call the buttons_callback (see #4691) if (is_array($GLOBALS['TL_DCA'][$this->strTable]['edit']['buttons_callback'])) { foreach ($GLOBALS['TL_DCA'][$this->strTable]['edit']['buttons_callback'] as $callback) { if (is_array($callback)) { $this->import($callback[0]); $arrButtons = $this->{$callback[0]}->{$callback[1]}($arrButtons, $this); } elseif (is_callable($callback)) { $arrButtons = $callback($arrButtons, $this); } } } // Add the form return $version . ' <div id="tl_buttons"> <a href="' . $this->getReferer(true) . '" class="header_back" title="' . specialchars($GLOBALS['TL_LANG']['MSC']['backBTTitle']) . '" accesskey="b" onclick="Backend.getScrollOffset()">' . $GLOBALS['TL_LANG']['MSC']['backBT'] . '</a> </div> ' . \Message::generate() . ' <form action="' . ampersand(\Environment::get('request'), true) . '" id="tl_files" class="tl_form" method="post"> <div class="tl_formbody_edit"> <input type="hidden" name="FORM_SUBMIT" value="tl_files"> <input type="hidden" name="REQUEST_TOKEN" value="' . REQUEST_TOKEN . '"> <div class="tl_tbox"> <h3><label for="ctrl_source">' . $GLOBALS['TL_LANG']['tl_files']['editor'][0] . '</label></h3> <textarea name="source" id="ctrl_source" class="tl_textarea monospace" rows="12" cols="80" style="height:400px" onfocus="Backend.getScrollOffset()">' . "\n" . htmlspecialchars($strContent) . '</textarea>' . (\Config::get('showHelp') && strlen($GLOBALS['TL_LANG']['tl_files']['editor'][1]) ? ' <p class="tl_help tl_tip">' . $GLOBALS['TL_LANG']['tl_files']['editor'][1] . '</p>' : '') . ' </div> </div> <div class="tl_formbody_submit"> <div class="tl_submit_container"> ' . implode(' ', $arrButtons) . ' </div> </div> </form>' . "\n\n" . $codeEditor; }
/** * Load the source editor * @return string */ public function source() { $this->isValid($this->intId); if (is_dir(TL_ROOT . '/' . $this->intId)) { $this->log('Folder "' . $this->intId . '" cannot be edited', 'DC_Folder source()', TL_ERROR); $this->redirect('contao/main.php?act=error'); } elseif (!file_exists(TL_ROOT . '/' . $this->intId)) { $this->log('File "' . $this->intId . '" does not exist', 'DC_Folder source()', TL_ERROR); $this->redirect('contao/main.php?act=error'); } $this->import('BackendUser', 'User'); // Check user permission if (!$this->User->isAdmin && !$this->User->hasAccess('f5', 'fop')) { $this->log('Not enough permissions to edit the file source of file "' . $this->intId . '"', 'DC_Folder source()', TL_ERROR); $this->redirect('contao/main.php?act=error'); } $objFile = new \File($this->intId); // Check whether file type is editable if (!in_array($objFile->extension, trimsplit(',', $GLOBALS['TL_CONFIG']['editableFiles']))) { $this->log('File type "' . $objFile->extension . '" (' . $this->intId . ') is not allowed to be edited', 'DC_Folder source()', TL_ERROR); $this->redirect('contao/main.php?act=error'); } $strContent = $objFile->getContent(); // Process the request if (\Input::post('FORM_SUBMIT') == 'tl_files') { // Save the file if (md5($strContent) != md5(\Input::postRaw('source'))) { $objFile->write(\Input::postRaw('source')); $objFile->close(); // Update the md5 hash if ($this->blnIsDbAssisted) { $objMeta = \FilesModel::findByPath($objFile->value); $objMeta->hash = md5_file(TL_ROOT . '/' . $objFile->value); $objMeta->save(); } } if (\Input::post('saveNclose')) { setcookie('BE_PAGE_OFFSET', 0, 0, '/'); $this->redirect($this->getReferer()); } $this->reload(); } $codeEditor = ''; // Prepare the code editor if ($GLOBALS['TL_CONFIG']['useCE']) { $type = ''; // The following types are supported by CodeMirror switch ($objFile->extension) { case 'c': case 'cc': case 'cpp': case 'c++': case 'h': case 'hh': case 'hpp': case 'h++': $type = 'clike'; break; case 'css': $type = 'css'; break; case 'patch': $type = 'diff'; break; case 'htm': case 'html': case 'tpl': case 'html5': case 'xhtml': $type = 'htmlmixed'; break; case 'js': $type = 'javascript'; break; case 'php': case 'inc': $type = 'php'; break; case 'sql': $type = 'sql'; break; case 'xml': $type = 'xml'; break; } // Fall back to HTML if ($type == '') { $type = 'htmlmixed'; } $this->ceFields = array(array('id' => 'ctrl_source', 'type' => $type)); $this->language = $GLOBALS['TL_LANGUAGE']; // Load the code editor configuration ob_start(); include TL_ROOT . '/system/config/codeMirror.php'; $codeEditor = ob_get_contents(); ob_end_clean(); } return ' <div id="tl_buttons"> <a href="' . $this->getReferer(true) . '" class="header_back" title="' . specialchars($GLOBALS['TL_LANG']['MSC']['backBTTitle']) . '" accesskey="b" onclick="Backend.getScrollOffset()">' . $GLOBALS['TL_LANG']['MSC']['backBT'] . '</a> </div> <h2 class="sub_headline">' . sprintf($GLOBALS['TL_LANG']['tl_files']['editFile'], $objFile->basename) . '</h2> ' . \Message::generate() . ' <form action="' . ampersand(\Environment::get('request'), true) . '" id="tl_files" class="tl_form" method="post"> <div class="tl_formbody_edit"> <input type="hidden" name="FORM_SUBMIT" value="tl_files"> <input type="hidden" name="REQUEST_TOKEN" value="' . REQUEST_TOKEN . '"> <div class="tl_tbox"> <h3><label for="ctrl_source">' . $GLOBALS['TL_LANG']['tl_files']['editor'][0] . '</label></h3> <textarea name="source" id="ctrl_source" class="tl_textarea monospace" rows="12" cols="80" style="height:400px" onfocus="Backend.getScrollOffset()">' . "\n" . htmlspecialchars($strContent) . '</textarea>' . ($GLOBALS['TL_CONFIG']['showHelp'] && strlen($GLOBALS['TL_LANG']['tl_files']['editor'][1]) ? ' <p class="tl_help tl_tip">' . $GLOBALS['TL_LANG']['tl_files']['editor'][1] . '</p>' : '') . ' </div> </div> <div class="tl_formbody_submit"> <div class="tl_submit_container"> <input type="submit" name="save" id="save" class="tl_submit" accesskey="s" value="' . specialchars($GLOBALS['TL_LANG']['MSC']['save']) . '"> <input type="submit" name="saveNclose" id="saveNclose" class="tl_submit" accesskey="c" value="' . specialchars($GLOBALS['TL_LANG']['MSC']['saveNclose']) . '"> </div> </div> </form>' . "\n\n" . $codeEditor; }
/** * Get post parameter and filter value. * @param string $aKey The post key. When filtering html, remove all attribs and * keep the plain tags. * @param string $aMode '': no filtering * 'nohtml': strip all html * 'text': Keep tags p br ul li em * @return string The filtered input. */ protected function filterPost($aKey, $aMode = '') { $v = trim(Input::postRaw($aKey)); if ($v == '' || $aMode == '') { return $v; } switch ($aMode) { case 'nohtml': $v = strip_tags($v); break; case 'text': $v = strip_tags($v, REPOSITORY_TEXTTAGS); break; } // switch $v = preg_replace('/<(\\w+) .*>/U', '<$1>', $v); return $v; }
/** * Generate module * * @return void */ protected function compile() { global $objPage; $this->maxlength = $GLOBALS['TL_CONFIG']['avatar_maxsize']; $this->extensions = $GLOBALS['TL_CONFIG']['avatar_filetype']; $this->uploadFolder = $GLOBALS['TL_CONFIG']['avatar_dir']; $this->storeFile = $this->uploadFolder != '' ? true : false; $arrImage = deserialize($GLOBALS['TL_CONFIG']['avatar_maxdims']); $this->import('FrontendUser', 'User'); $strAvatar = $this->User->avatar; $strAlt = $this->User->firstname . " " . $this->User->lastname; $objFile = \FilesModel::findByUuid($strAvatar); if ($objFile === null && $GLOBALS['TL_CONFIG']['avatar_fallback_image']) { $objFile = \FilesModel::findByUuid($GLOBALS['TL_CONFIG']['avatar_fallback_image']); } if ($objFile !== null) { $this->Template->avatar = '<img src="' . TL_FILES_URL . \Image::get($objFile->path, $arrImage[0], $arrImage[1], $arrImage[2]) . '" width="' . $arrImage[0] . '" height="' . $arrImage[1] . '" alt="' . $strAlt . '" class="avatar">'; } elseif ($this->User->gender != '') { $this->Template->avatar = '<img src="' . TL_FILES_URL . \Image::get("system/modules/avatar/assets/" . $this->User->gender . ".png", $arrImage[0], $arrImage[1], $arrImage[2]) . '" width="' . $arrImage[0] . '" height="' . $arrImage[1] . '" alt="Avatar" class="avatar">'; } else { $this->Template->avatar = '<img src="' . TL_FILES_URL . \Image::get("system/modules/avatar/assets/male.png", $arrImage[0], $arrImage[1], $arrImage[2]) . '" width="' . $arrImage[0] . '" height="' . $arrImage[1] . '" alt="Avatar" class="avatar">'; } $this->Template->action = ampersand(\Environment::get('request')); $this->Template->formId = 'avatar_' . $this->id; $this->Template->method = 'post'; $this->Template->enctype = 'multipart/form-data'; $this->Template->attributes = ''; $this->Template->avatar_reset_label = $GLOBALS['TL_LANG']['AVATAR']['reset']; $this->Template->avatar_submit_value = $GLOBALS['TL_LANG']['AVATAR']['save']; $this->Template->avatar_file_label = sprintf($GLOBALS['TL_LANG']['AVATAR']['file']['1'], $this->extensions, $this->maxlength, $arrImage[0], $arrImage[1]); // Confirm or remove a subscription if (\Input::get('token')) { static::changeSubscriptionStatus($objTemplate); return; } // Remove the avatar if (\Input::postRaw('avatar_reset')) { \Database::getInstance()->prepare("UPDATE `tl_member` SET avatar='' WHERE `id`=?")->execute($this->User->id); $this->reload(); } $file = $_FILES[$this->strName]; $maxlength_kb = $this->getReadableSize($this->maxlength); // Romanize the filename $file['name'] = utf8_romanize($file['name']); // File was not uploaded if (!is_uploaded_file($file['tmp_name'])) { if (in_array($file['error'], array(1, 2))) { $this->Template->error = sprintf($GLOBALS['TL_LANG']['ERR']['filesize'], $maxlength_kb); $this->log('File "' . $file['name'] . '" exceeds the maximum file size of ' . $maxlength_kb, 'FormFileUpload validate()', TL_ERROR); } if ($file['error'] == 3) { $this->Template->error = sprintf($GLOBALS['TL_LANG']['ERR']['filepartial'], $file['name']); $this->log('File "' . $file['name'] . '" was only partially uploaded', 'FormFileUpload validate()', TL_ERROR); } unset($_FILES[$this->strName]); return; } // File is too big if ($this->maxlength > 0 && $file['size'] > $this->maxlength) { $this->Template->error = sprintf($GLOBALS['TL_LANG']['ERR']['filesize'], $maxlength_kb); $this->log('File "' . $file['name'] . '" exceeds the maximum file size of ' . $maxlength_kb, 'FormFileUpload validate()', TL_ERROR); unset($_FILES[$this->strName]); return; } $strExtension = pathinfo($file['name'], PATHINFO_EXTENSION); $uploadTypes = trimsplit(',', $this->extensions); // File type is not allowed if (!in_array(strtolower($strExtension), $uploadTypes)) { $this->Template->error = sprintf($GLOBALS['TL_LANG']['ERR']['filetype'], $strExtension); $this->log('File type "' . $strExtension . '" is not allowed to be uploaded (' . $file['name'] . ')', 'FormFileUpload validate()', TL_ERROR); unset($_FILES[$this->strName]); return; } $blnResize = false; if (($arrImageSize = @getimagesize($file['tmp_name'])) != false) { // Image exceeds maximum image width if ($arrImageSize[0] > $arrImage[0]) { if ($GLOBALS['TL_CONFIG']['avatar_resize']) { $blnResize = true; } else { $this->Template->error = sprintf($GLOBALS['TL_LANG']['ERR']['filewidth'], $file['name'], $arrImage[0]); $this->log('File "' . $file['name'] . '" exceeds the maximum image width of ' . $arrImage[0] . ' pixels', 'FormFileUpload validate()', TL_ERROR); unset($_FILES[$this->strName]); return; } } // Image exceeds maximum image height if ($arrImageSize[1] > $arrImage[1]) { if ($GLOBALS['TL_CONFIG']['avatar_resize']) { $blnResize = true; } else { $this->Template->error = sprintf($GLOBALS['TL_LANG']['ERR']['fileheight'], $file['name'], $arrImage[1]); $this->log('File "' . $file['name'] . '" exceeds the maximum image height of ' . $arrImage[1] . ' pixels', 'FormFileUpload validate()', TL_ERROR); unset($_FILES[$this->strName]); return; } } } $_SESSION['FILES'][$this->strName] = $_FILES[$this->strName]; $this->log('File "' . $file['name'] . '" uploaded successfully', 'FormFileUpload validate()', TL_FILES); if ($this->storeFile) { $intUploadFolder = $this->uploadFolder; if ($this->User->assignDir && $this->User->homeDir) { $intUploadFolder = $this->User->homeDir; } $objUploadFolder = \FilesModel::findByUuid($intUploadFolder); // The upload folder could not be found if ($objUploadFolder === null) { throw new \Exception("Invalid upload folder ID {$intUploadFolder}"); } $strUploadFolder = $objUploadFolder->path; // Store the file if the upload folder exists if ($strUploadFolder != '' && is_dir(TL_ROOT . '/' . $strUploadFolder)) { $this->import('Files'); // Do not overwrite existing files if ($this->doNotOverwrite && file_exists(TL_ROOT . '/' . $strUploadFolder . '/' . $file['name'])) { $offset = 1; $pathinfo = pathinfo($file['name']); $name = $pathinfo['filename']; $arrAll = scan(TL_ROOT . '/' . $strUploadFolder); $arrFiles = preg_grep('/^' . preg_quote($name, '/') . '.*\\.' . preg_quote($pathinfo['extension'], '/') . '/', $arrAll); foreach ($arrFiles as $strFile) { if (preg_match('/__[0-9]+\\.' . preg_quote($pathinfo['extension'], '/') . '$/', $strFile)) { $strFile = str_replace('.' . $pathinfo['extension'], '', $strFile); $intValue = intval(substr($strFile, strrpos($strFile, '_') + 1)); $offset = max($offset, $intValue); } } $file['name'] = str_replace($name, $name . '__' . ++$offset, $file['name']); } $this->Files->move_uploaded_file($file['tmp_name'], $strUploadFolder . '/' . $file['name']); $this->Files->chmod($strUploadFolder . '/' . $file['name'], $GLOBALS['TL_CONFIG']['defaultFileChmod']); if ($blnResize) { \Image::resize($strUploadFolder . '/' . $file['name'], $arrImage[0], $arrImage[1], $arrImage[2]); } $_SESSION['FILES'][$this->strName] = array('name' => $file['name'], 'type' => $file['type'], 'tmp_name' => TL_ROOT . '/' . $strUploadFolder . '/' . $file['name'], 'error' => $file['error'], 'size' => $file['size'], 'uploaded' => true); $this->loadDataContainer('tl_files'); // Generate the DB entries if ($GLOBALS['TL_DCA']['tl_files']['config']['databaseAssisted']) { $strFile = $strUploadFolder . '/' . $file['name']; $objFile = \FilesModel::findByPath($strFile); // Existing file is being replaced (see #4818) if ($objFile !== null) { $objFile->tstamp = time(); $objFile->path = $strFile; $objFile->hash = md5_file(TL_ROOT . '/' . $strFile); $objFile->save(); } else { \Dbafs::addResource($strFile); } // Update the hash of the target folder \Dbafs::updateFolderHashes($strUploadFolder); } // Update Userdata $strFile = $strUploadFolder . '/' . $file['name']; $objFile = \FilesModel::findByPath($strFile); // new Avatar for Member \Database::getInstance()->prepare("UPDATE tl_member SET avatar=? WHERE id=?")->execute($objFile->uuid, $this->User->id); $this->log('File "' . $file['name'] . '" has been moved to "' . $strUploadFolder . '"', 'FormFileUpload validate()', TL_FILES); } } unset($_FILES[$this->strName]); $this->reload(); }
/** * Try to login the current user * * @return boolean True if the user could be logged in */ public function login() { \System::loadLanguageFile('default'); // Do not continue if username or password are missing if (empty($_POST['username']) || empty($_POST['password'])) { return false; } // Load the user object if ($this->findBy('username', \Input::post('username', true)) == false) { $blnLoaded = false; // HOOK: pass credentials to callback functions if (isset($GLOBALS['TL_HOOKS']['importUser']) && is_array($GLOBALS['TL_HOOKS']['importUser'])) { foreach ($GLOBALS['TL_HOOKS']['importUser'] as $callback) { $this->import($callback[0], 'objImport', true); $blnLoaded = $this->objImport->{$callback}[1](\Input::post('username', true), \Input::postRaw('password'), $this->strTable); // Load successfull if ($blnLoaded === true) { break; } } } // Return if the user still cannot be loaded if (!$blnLoaded || $this->findBy('username', \Input::post('username', true)) == false) { \Message::addError($GLOBALS['TL_LANG']['ERR']['invalidLogin']); $this->log('Could not find user "' . \Input::post('username', true) . '"', __METHOD__, TL_ACCESS); return false; } } $time = time(); // Set the user language if (\Input::post('language')) { $this->language = \Input::post('language'); } // Lock the account if there are too many login attempts if ($this->loginCount < 1) { $this->locked = $time; $this->loginCount = \Config::get('loginCount'); $this->save(); // Add a log entry and the error message, because checkAccountStatus() will not be called (see #4444) $this->log('The account has been locked for security reasons', __METHOD__, TL_ACCESS); \Message::addError(sprintf($GLOBALS['TL_LANG']['ERR']['accountLocked'], ceil(($this->locked + \Config::get('lockPeriod') - $time) / 60))); // Send admin notification if (\Config::get('adminEmail') != '') { $objEmail = new \Email(); $objEmail->subject = $GLOBALS['TL_LANG']['MSC']['lockedAccount'][0]; $objEmail->text = sprintf($GLOBALS['TL_LANG']['MSC']['lockedAccount'][1], $this->username, TL_MODE == 'FE' ? $this->firstname . " " . $this->lastname : $this->name, \Idna::decode(\Environment::get('base')), ceil(\Config::get('lockPeriod') / 60)); $objEmail->sendTo(\Config::get('adminEmail')); } return false; } // Check the account status if ($this->checkAccountStatus() == false) { return false; } // The password has been generated with crypt() if (\Encryption::test($this->password)) { $blnAuthenticated = crypt(\Input::postRaw('password'), $this->password) === $this->password; } else { list($strPassword, $strSalt) = explode(':', $this->password); $blnAuthenticated = $strSalt == '' ? $strPassword === sha1(\Input::postRaw('password')) : $strPassword === sha1($strSalt . \Input::postRaw('password')); // Store a SHA-512 encrpyted version of the password if ($blnAuthenticated) { $this->password = \Encryption::hash(\Input::postRaw('password')); } } // HOOK: pass credentials to callback functions if (!$blnAuthenticated && isset($GLOBALS['TL_HOOKS']['checkCredentials']) && is_array($GLOBALS['TL_HOOKS']['checkCredentials'])) { foreach ($GLOBALS['TL_HOOKS']['checkCredentials'] as $callback) { $this->import($callback[0], 'objAuth', true); $blnAuthenticated = $this->objAuth->{$callback}[1](\Input::post('username', true), \Input::postRaw('password'), $this); // Authentication successfull if ($blnAuthenticated === true) { break; } } } // Redirect if the user could not be authenticated if (!$blnAuthenticated) { --$this->loginCount; $this->save(); \Message::addError($GLOBALS['TL_LANG']['ERR']['invalidLogin']); $this->log('Invalid password submitted for username "' . $this->username . '"', __METHOD__, TL_ACCESS); return false; } $this->setUserFromDb(); // Update the record $this->lastLogin = $this->currentLogin; $this->currentLogin = $time; $this->loginCount = \Config::get('loginCount'); $this->save(); // Generate the session $this->generateSession(); $this->log('User "' . $this->username . '" has logged in', __METHOD__, TL_ACCESS); // HOOK: post login callback if (isset($GLOBALS['TL_HOOKS']['postLogin']) && is_array($GLOBALS['TL_HOOKS']['postLogin'])) { foreach ($GLOBALS['TL_HOOKS']['postLogin'] as $callback) { $this->import($callback[0], 'objLogin', true); $this->objLogin->{$callback}[1]($this); } } return true; }
/** * Store the install tool password */ protected function storeInstallToolPassword() { $strPassword = Input::postRaw('password'); // The passwords do not match if ($strPassword != Input::postRaw('confirm_password')) { $this->Template->passwordError = $GLOBALS['TL_LANG']['ERR']['passwordMatch']; } elseif (utf8_strlen($strPassword) < Config::get('minPasswordLength')) { $this->Template->passwordError = sprintf($GLOBALS['TL_LANG']['ERR']['passwordLength'], Config::get('minPasswordLength')); } else { $strPassword = Encryption::hash($strPassword); Config::persist('installPassword', $strPassword); $this->reload(); } }
/** * Return a search form that allows to search results using regular expressions * @return string */ protected function searchMenu() { $searchFields = array(); $session = $this->Session->getData(); // Get search fields foreach ($GLOBALS['TL_DCA'][$this->strTable]['fields'] as $k => $v) { if ($v['search']) { $searchFields[] = $k; } } // Return if there are no search fields if (empty($searchFields)) { return ''; } // Store search value in the current session if (\Input::post('FORM_SUBMIT') == 'tl_filters') { $session['search'][$this->strTable]['value'] = ''; $session['search'][$this->strTable]['field'] = \Input::post('tl_field', true); // Make sure the regular expression is valid if (\Input::postRaw('tl_value') != '') { try { $this->Database->prepare("SELECT * FROM " . $this->strTable . " WHERE " . \Input::post('tl_field', true) . " REGEXP ?")->limit(1)->execute(\Input::postRaw('tl_value')); $session['search'][$this->strTable]['value'] = \Input::postRaw('tl_value'); } catch (Exception $e) { } } $this->Session->setData($session); } elseif ($session['search'][$this->strTable]['value'] != '') { $this->procedure[] = "CAST(" . $session['search'][$this->strTable]['field'] . " AS CHAR) REGEXP ?"; $this->values[] = $session['search'][$this->strTable]['value']; } $options_sorter = array(); foreach ($searchFields as $field) { $option_label = $GLOBALS['TL_DCA'][$this->strTable]['fields'][$field]['label'][0] ?: $GLOBALS['TL_LANG']['MSC'][$field]; $options_sorter[utf8_romanize($option_label) . '_' . $field] = ' <option value="' . specialchars($field) . '"' . ($field == $session['search'][$this->strTable]['field'] ? ' selected="selected"' : '') . '>' . $option_label . '</option>'; } // Sort by option values $options_sorter = natcaseksort($options_sorter); $active = $session['search'][$this->strTable]['value'] != '' ? true : false; return ' <div class="tl_search tl_subpanel"> <strong>' . $GLOBALS['TL_LANG']['MSC']['search'] . ':</strong> <select name="tl_field" class="tl_select' . ($active ? ' active' : '') . '"> ' . implode("\n", $options_sorter) . ' </select> <span> = </span> <input type="text" name="tl_value" class="tl_text' . ($active ? ' active' : '') . '" value="' . specialchars($session['search'][$this->strTable]['value']) . '"> </div>'; }
/** * Run the communication as client * * @return void */ public function run() { // If we have a ping, just do nothing if (\Input::get("act") == "ping") { // Clean output buffer while (@ob_end_clean()) { } exit; } /* --------------------------------------------------------------------- * Check if we have a old AES or a new AES with IV. * Set codifyengine keys. * Check the connection ID and refresh/delete it. */ // Check if IV was send, when send use the new AES else the old one. try { $this->objCodifyengineBasic = Factory::getEngine("aes"); $this->setCodifyengine(\Input::get("engine")); } catch (\RuntimeException $exc) { \System::log("Try to load the engine for ctoCommunication with error: " . $exc->getMessage(), __FUNCTION__ . " | " . __CLASS__, TL_ERROR); // Clean output buffer while (@ob_end_clean()) { } exit; } // Check if we have a incomming connection for handshake if (in_array(\Input::get("act"), array("CTOCOM_HELLO", "CTOCOM_START_HANDSHAKE", "CTOCOM_CHECK_HANDSHAKE", "CTOCOM_VERSION"))) { $this->objCodifyengine->setKey($GLOBALS['TL_CONFIG']['ctoCom_APIKey']); $this->objCodifyengineBasic->setKey($GLOBALS['TL_CONFIG']['ctoCom_APIKey']); $strCodifyKey = $GLOBALS['TL_CONFIG']['ctoCom_APIKey']; } else { // Use the private key from connection pool if (strlen(\Input::get("con")) != 0) { // Check if we have some data $arrConnections = \Database::getInstance()->prepare("SELECT * FROM tl_ctocom_cache WHERE uid=?")->execute(\Input::get("con"))->fetchAllAssoc(); if (count($arrConnections) == 0) { \System::log(vsprintf("Call from %s with a unknown connection ID.", \Environment::get('ip')), __FUNCTION__ . " | " . __CLASS__, TL_ERROR); // Clean output buffer while (@ob_end_clean()) { } exit; } // Check if time out isn't reached. if ($arrConnections[0]["tstamp"] + $this->intHandshakeTimeout < time()) { \Database::getInstance()->prepare("DELETE FROM tl_ctocom_cache WHERE uid=?")->execute(\Input::get("con")); \System::log(vsprintf("Call from %s with a expired connection ID.", \Environment::get('ip')), __FUNCTION__ . " | " . __CLASS__, TL_ERROR); // Clean output buffer while (@ob_end_clean()) { } exit; } // Reset timestamp \Database::getInstance()->prepare("UPDATE tl_ctocom_cache %s WHERE uid=?")->set(array("tstamp" => time()))->execute(\Input::get("con")); // Set codify key from database $this->objCodifyengineBasic->setKey($arrConnections[0]["shared_secret_key"]); $this->objCodifyengine->setKey($arrConnections[0]["shared_secret_key"]); $strCodifyKey = $arrConnections[0]["shared_secret_key"]; } else { \System::log(vsprintf("Call from %s without a connection ID.", \Environment::get('ip')), __FUNCTION__ . " | " . __CLASS__, TL_ERROR); // Clean output buffer while (@ob_end_clean()) { } exit; } } /* --------------------------------------------------------------------- * Check the API key. * Check if the API Key was send. * Check if the API key contains the RPC Call and the API Key from this * Contao Version. */ // Check if a API-Key was send if (strlen(\Input::get("apikey")) == 0) { \System::log(vsprintf("Call from %s without a API Key.", \Environment::get('ip')), __FUNCTION__ . " | " . __CLASS__, TL_ERROR); // Clean output buffer while (@ob_end_clean()) { } exit; } // Check RPC Call from get and the RPC Call from API-Key $mixVar = $this->objCodifyengineBasic->Decrypt(base64_decode(\Input::get("apikey", true))); $mixVar = trimsplit("@\\|@", $mixVar); $strApiKey = $mixVar[1]; $strAction = $mixVar[0]; if ($strAction != \Input::get("act")) { \System::log(vsprintf("Error Api Key from %s. Request action: %s | Key action: %s | Api: %s", array(\Environment::get('ip'), \Input::get("act"), $strAction, $strApiKey)), __FUNCTION__ . " | " . __CLASS__, TL_ERROR); // Clean output buffer while (@ob_end_clean()) { } exit; } if ($GLOBALS['TL_CONFIG']['ctoCom_APIKey'] != $strApiKey) { \System::log(vsprintf("Call from %s with a wrong API Key: %s", array(\Environment::get('ip'), \Input::get("apikey"))), __FUNCTION__ . " | " . __CLASS__, TL_ERROR); // Clean output buffer while (@ob_end_clean()) { } exit; } /* --------------------------------------------------------------------- * Check language settings */ if (empty($GLOBALS['TL_LANGUAGE'])) { $GLOBALS['TL_LANGUAGE'] = "en"; } /* --------------------------------------------------------------------- * Set I/O System */ if (strlen(\Input::get("format")) != 0) { if (\CtoCommunication\InputOutput\Factory::engineExist(\Input::get("format"))) { $this->setIOEngine(\Input::get("format")); } else { $this->setIOEngine(); $this->objError = new Error(); $this->objError->setLanguage("unknown_io"); $this->objError->setID(10); $this->objError->setObject(""); $this->objError->setMessage("No I/O Interface found for accept."); $this->objError->setRPC(""); $this->objError->setClass(""); $this->objError->setFunction(""); $this->generateOutput(); exit; } } else { $strAccept = $_SERVER['HTTP_ACCEPT']; $strAccept = preg_replace("/;q=\\d\\.\\d/", "", $strAccept); $arrAccept = trimsplit(",", $strAccept); $strIOEngine = false; foreach ($arrAccept as $key => $value) { $strIOEngine = \CtoCommunication\InputOutput\Factory::getEngingenameForAccept($value); if ($strIOEngine !== false) { break; } } if ($strIOEngine === false) { $this->objIOEngine = \CtoCommunication\InputOutput\Factory::getEngine('default'); $this->objError = new Error(); $this->objError->setLanguage("unknown_io"); $this->objError->setID(10); $this->objError->setObject(""); $this->objError->setMessage("No I/O Interface found for accept: {$strAccept}"); $this->objError->setRPC(""); $this->objError->setClass(""); $this->objError->setFunction(""); $this->generateOutput(); exit; } else { $this->setIOEngine($strIOEngine); } } /* --------------------------------------------------------------------- * Run RPC-Check function */ // Check if act is set $mixRPCCall = \Input::get("act"); if (strlen($mixRPCCall) == 0) { $this->objError = new Error(); $this->objError->setLanguage("rpc_missing"); $this->objError->setID(1); $this->objError->setObject(""); $this->objError->setMessage("Missing RPC Call"); $this->objError->setRPC($mixRPCCall); $this->objError->setClass(""); $this->objError->setFunction(""); $this->generateOutput(); exit; } if (!array_key_exists($mixRPCCall, $this->arrRpcList)) { $this->objError = new Error(); $this->objError->setLanguage("rpc_unknown"); $this->objError->setID(1); $this->objError->setObject(""); $this->objError->setMessage("Unknown RPC Call"); $this->objError->setRPC($mixRPCCall); $this->objError->setClass(""); $this->objError->setFunction(""); $this->generateOutput(); exit; } /* --------------------------------------------------------------------- * Build a list with parameter from the POST */ $arrParameter = array(); if ($this->arrRpcList[$mixRPCCall]["parameter"] != false && is_array($this->arrRpcList[$mixRPCCall]["parameter"])) { switch ($this->arrRpcList[$mixRPCCall]["typ"]) { // Decode post case "POST": // Decode each post $arrPostValues = array(); foreach ($_POST as $key => $value) { if (version_compare('3.2.16', VERSION . '.' . BUILD, '<=') && version_compare('3.3.0', VERSION . '.' . BUILD, '>') || version_compare('3.3.7', VERSION . '.' . BUILD, '<=')) { // Get the raw data. $mixPost = \Input::postUnsafeRaw($key); } else { // Get the raw data for older contao versions. $mixPost = \Input::postRaw($key); } $mixPost = $this->objIOEngine->InputPost($mixPost, $this->objCodifyengine); $arrPostValues[$key] = $mixPost; \Input::setPost($key, $mixPost); } // Check if all post are set foreach ($this->arrRpcList[$mixRPCCall]["parameter"] as $value) { $arrPostKey = array_keys($arrPostValues); if (!in_array($value, $arrPostKey)) { $arrParameter[$value] = null; } else { // Get the raw data. $arrParameter[$value] = $arrPostValues[$value]; } } unset($arrPostValues); break; default: break; } } /* --------------------------------------------------------------------- * Call function */ try { $strClassname = $this->arrRpcList[$mixRPCCall]["class"]; if (!class_exists($strClassname)) { $this->objError = new Error(); $this->objError->setLanguage("rpc_class_not_exists"); $this->objError->setID(4); $this->objError->setObject($value); $this->objError->setMessage("The choosen class didn`t exists."); $this->objError->setRPC($mixRPCCall); $this->objError->setClass($this->arrRpcList[$mixRPCCall]["class"]); $this->objError->setFunction($this->arrRpcList[$mixRPCCall]["function"]); $this->generateOutput(); exit; } $objReflection = new \ReflectionClass($strClassname); if ($objReflection->hasMethod("getInstance")) { $object = call_user_func_array(array($this->arrRpcList[$mixRPCCall]["class"], "getInstance"), array()); $this->mixOutput = call_user_func_array(array($object, $this->arrRpcList[$mixRPCCall]["function"]), $arrParameter); } else { $object = new $this->arrRpcList[$mixRPCCall]["class"](); $this->mixOutput = call_user_func_array(array($object, $this->arrRpcList[$mixRPCCall]["function"]), $arrParameter); } } catch (\Exception $exc) { $this->objError = new Error(); $this->objError->setLanguage("rpc_unknown_exception"); $this->objError->setID(3); $this->objError->setObject(""); $this->objError->setMessage($exc->getMessage()); $this->objError->setRPC($mixRPCCall); $this->objError->setClass($this->arrRpcList[$mixRPCCall]["class"]); $this->objError->setFunction($this->arrRpcList[$mixRPCCall]["function"]); $this->objError->setException($exc); \System::log(vsprintf("RPC Exception: %s | %s", array($exc->getMessage(), nl2br($exc->getTraceAsString()))), __CLASS__ . " | " . __FUNCTION__, TL_ERROR); $this->generateOutput(); exit; } $this->generateOutput(); exit; }
/** * Return a search form that allows to search results using regular expressions * @return string */ protected function searchMenu() { $searchFields = array(); $session = $this->Session->getData(); // Get search fields foreach ($GLOBALS['TL_DCA'][$this->strTable]['fields'] as $k => $v) { if ($v['search']) { $searchFields[] = $k; } } // Return if there are no search fields if (empty($searchFields)) { return ''; } $strSessionKey = $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['mode'] == 4 ? $this->strTable . '_' . CURRENT_ID : strlen($this->strFormKey) ? $this->strFormKey : $this->strTable; // Store search value in the current session if (\Input::post('FORM_SUBMIT') == 'tl_filters') { $session['search'][$strSessionKey]['value'] = ''; $session['search'][$strSessionKey]['field'] = \Input::post('tl_field', true); // Make sure the regular expression is valid if (\Input::postRaw('tl_value') != '') { $sqlSearchField = '(SELECT value FROM tl_formdata_details WHERE ff_name=\'' . \Input::post('tl_field', true) . '\' AND pid=f.id)'; try { \Database::getInstance()->prepare("SELECT * " . (!empty($this->arrSqlDetails) ? ',' . implode(', ', array_values($this->arrSqlDetails)) : '') . " FROM " . $this->strTable . " f WHERE " . $sqlSearchField . " REGEXP ?")->limit(1)->execute(\Input::postRaw('tl_value')); $session['search'][$strSessionKey]['value'] = \Input::postRaw('tl_value'); } catch (\Exception $e) { } } $this->Session->setData($session); } elseif ($session['search'][$strSessionKey]['value'] != '') { $sqlSearchField = $session['search'][$strSessionKey]['field']; if (in_array($sqlSearchField, $this->arrDetailFields)) { $sqlSearchField = '(SELECT value FROM tl_formdata_details WHERE ff_name=\'' . $session['search'][$strSessionKey]['field'] . '\' AND pid=f.id)'; } if (substr($GLOBALS['TL_CONFIG']['dbCollation'], -3) == '_ci') { $this->procedure[] = "LOWER(CAST(" . $sqlSearchField . " AS CHAR)) REGEXP LOWER(?)"; } else { $this->procedure[] = "CAST(" . $sqlSearchField . " AS CHAR) REGEXP ?"; } $this->values[] = $session['search'][$strSessionKey]['value']; } $options_sorter = array(); foreach ($searchFields as $field) { $option_label = strlen($GLOBALS['TL_DCA'][$this->strTable]['fields'][$field]['label'][0]) ? $GLOBALS['TL_DCA'][$this->strTable]['fields'][$field]['label'][0] : $GLOBALS['TL_LANG']['MSC'][$field]; $options_sorter[utf8_romanize($option_label) . '_' . $field] = ' <option value="' . specialchars($field) . '"' . ($field == $session['search'][$strSessionKey]['field'] ? ' selected="selected"' : '') . '>' . $option_label . '</option>'; } // Sort by option values $options_sorter = natcaseksort($options_sorter); $active = $session['search'][$strSessionKey]['value'] != '' ? true : false; return ' <div class="tl_search tl_subpanel"> <strong>' . $GLOBALS['TL_LANG']['MSC']['search'] . ':</strong> <select name="tl_field" class="tl_select' . ($active ? ' active' : '') . '"> ' . implode("\n", $options_sorter) . ' </select> <span> = </span> <input type="text" name="tl_value" class="tl_text' . ($active ? ' active' : '') . '" value="' . specialchars($session['search'][$strSessionKey]['value']) . '"> </div>'; }