/** * Run the controller and parse the password template * * @return Response */ public function run() { /** @var BackendTemplate|object $objTemplate */ $objTemplate = new \BackendTemplate('be_password'); if (\Input::post('FORM_SUBMIT') == 'tl_password') { $pw = \Input::postUnsafeRaw('password'); $cnf = \Input::postUnsafeRaw('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 (\Encryption::verify($pw, $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(); } $objTemplate->theme = \Backend::getTheme(); $objTemplate->messages = \Message::generate(); $objTemplate->base = \Environment::get('base'); $objTemplate->language = $GLOBALS['TL_LANGUAGE']; $objTemplate->title = \StringUtil::specialchars($GLOBALS['TL_LANG']['MSC']['pw_new']); $objTemplate->charset = \Config::get('characterSet'); $objTemplate->action = ampersand(\Environment::get('request')); $objTemplate->headline = $GLOBALS['TL_LANG']['MSC']['pw_change']; $objTemplate->submitButton = \StringUtil::specialchars($GLOBALS['TL_LANG']['MSC']['continue']); $objTemplate->password = $GLOBALS['TL_LANG']['MSC']['password'][0]; $objTemplate->confirm = $GLOBALS['TL_LANG']['MSC']['confirm'][0]; return $objTemplate->getResponse(); }
/** * Shorten a HTML string to a given number of characters * * The function preserves words, so the result might be a bit shorter or * longer than the number of characters given. It preserves allowed tags. * * @param string $strString The string to shorten * @param integer $intNumberOfChars The target number of characters * * @return string The shortened HTML string */ public static function substrHtml($strString, $intNumberOfChars) { $strReturn = ''; $intCharCount = 0; $arrOpenTags = array(); $arrTagBuffer = array(); $arrEmptyTags = array('area', 'base', 'br', 'col', 'hr', 'img', 'input', 'frame', 'link', 'meta', 'param'); $strString = preg_replace('/[\\t\\n\\r]+/', ' ', $strString); $strString = strip_tags($strString, \Config::get('allowedTags')); $strString = preg_replace('/ +/', ' ', $strString); // Seperate tags and text $arrChunks = preg_split('/(<[^>]+>)/', $strString, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); for ($i = 0, $c = count($arrChunks); $i < $c; $i++) { // Buffer tags to include them later if (preg_match('/<([^>]+)>/', $arrChunks[$i])) { $arrTagBuffer[] = $arrChunks[$i]; continue; } $buffer = $arrChunks[$i]; // Get the substring of the current text if (($arrChunks[$i] = static::substr($arrChunks[$i], $intNumberOfChars - $intCharCount, false)) == false) { break; } $blnModified = $buffer !== $arrChunks[$i]; $intCharCount += Utf8::strlen(static::decodeEntities($arrChunks[$i])); if ($intCharCount <= $intNumberOfChars) { foreach ($arrTagBuffer as $strTag) { $strTagName = strtolower(trim($strTag)); // Extract the tag name (see #5669) if (($pos = strpos($strTagName, ' ')) !== false) { $strTagName = substr($strTagName, 1, $pos - 1); } else { $strTagName = substr($strTagName, 1, -1); } // Skip empty tags if (in_array($strTagName, $arrEmptyTags)) { continue; } // Store opening tags in the open_tags array if (strncmp($strTagName, '/', 1) !== 0) { if (!empty($arrChunks[$i]) || $i < $c) { $arrOpenTags[] = $strTagName; } continue; } // Closing tags will be removed from the "open tags" array if (!empty($arrChunks[$i]) || $i < $c) { $arrOpenTags = array_values($arrOpenTags); for ($j = count($arrOpenTags) - 1; $j >= 0; $j--) { if ($strTagName == '/' . $arrOpenTags[$j]) { unset($arrOpenTags[$j]); break; } } } } // If the current chunk contains text, add tags and text to the return string if (strlen($arrChunks[$i]) || $i < $c) { $strReturn .= implode('', $arrTagBuffer) . $arrChunks[$i]; } // Stop after the first shortened chunk (see #7311) if ($blnModified) { break; } $arrTagBuffer = array(); continue; } break; } // Close all remaining open tags krsort($arrOpenTags); foreach ($arrOpenTags as $strTag) { $strReturn .= '</' . $strTag . '>'; } return trim($strReturn); }
/** * @covers Patchwork\Utf8::str_shuffle */ function testStr_shuffle() { $c = "déjà 한국어"; $c .= n::normalize($c, n::NFD); $this->assertTrue($c != ($d = u::str_shuffle($c)) || $c != ($d = u::str_shuffle($c))); $this->assertSame(strlen($c), strlen($d)); $this->assertSame(u::strlen($c), u::strlen($d)); $this->assertSame('', u::trim($d, $c)); }
/** * Recursively generate the tree and return it as HTML string * * @param string $table * @param integer $id * @param array $arrPrevNext * @param boolean $blnHasSorting * @param integer $intMargin * @param array $arrClipboard * @param boolean $blnCircularReference * @param boolean $protectedPage * @param boolean $blnNoRecursion * @param array $arrFound * * @return string */ protected function generateTree($table, $id, $arrPrevNext, $blnHasSorting, $intMargin = 0, $arrClipboard = null, $blnCircularReference = false, $protectedPage = false, $blnNoRecursion = false, $arrFound = array()) { static $session; /** @var AttributeBagInterface $objSessionBag */ $objSessionBag = \System::getContainer()->get('session')->getBag('contao_backend'); $session = $objSessionBag->all(); $node = $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['mode'] == 6 ? $this->strTable . '_' . $table . '_tree' : $this->strTable . '_tree'; // Toggle nodes if (\Input::get('ptg')) { $session[$node][\Input::get('ptg')] = isset($session[$node][\Input::get('ptg')]) && $session[$node][\Input::get('ptg')] == 1 ? 0 : 1; $objSessionBag->replace($session); $this->redirect(preg_replace('/(&(amp;)?|\\?)ptg=[^& ]*/i', '', \Environment::get('request'))); } $objRow = $this->Database->prepare("SELECT * FROM " . $table . " WHERE id=?")->limit(1)->execute($id); // Return if there is no result if ($objRow->numRows < 1) { $objSessionBag->replace($session); return ''; } $return = ''; $intSpacing = 20; $childs = array(); // Add the ID to the list of current IDs if ($this->strTable == $table) { $this->current[] = $objRow->id; } // Check whether there are child records if (!$blnNoRecursion) { if ($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['mode'] == 5 || $this->strTable != $table) { $objChilds = $this->Database->prepare("SELECT id FROM " . $table . " WHERE pid=?" . (!empty($arrFound) ? " AND id IN(" . implode(',', array_map('intval', $arrFound)) . ")" : '') . ($blnHasSorting ? " ORDER BY sorting" : ''))->execute($id); if ($objChilds->numRows) { $childs = $objChilds->fetchEach('id'); } } } $blnProtected = false; // Check whether the page is protected if ($table == 'tl_page') { $blnProtected = $objRow->protected || $protectedPage ? true : false; } $session[$node][$id] = is_int($session[$node][$id]) ? $session[$node][$id] : 0; $mouseover = $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['mode'] == 5 || $table == $this->strTable ? ' toggle_select hover-div"' : '"'; $return .= "\n " . '<li class="' . ($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['mode'] == 5 && $objRow->type == 'root' || $table != $this->strTable ? 'tl_folder' : 'tl_file') . ' click2edit' . $mouseover . '><div class="tl_left" style="padding-left:' . ($intMargin + $intSpacing) . 'px">'; // Calculate label and add a toggle button $args = array(); $folderAttribute = 'style="margin-left:20px"'; $showFields = $GLOBALS['TL_DCA'][$table]['list']['label']['fields']; $level = $intMargin / $intSpacing + 1; if (!empty($childs)) { $folderAttribute = ''; $img = !empty($arrFound) || $session[$node][$id] == 1 ? 'folMinus.gif' : 'folPlus.gif'; $alt = !empty($arrFound) || $session[$node][$id] == 1 ? $GLOBALS['TL_LANG']['MSC']['collapseNode'] : $GLOBALS['TL_LANG']['MSC']['expandNode']; $return .= '<a href="' . $this->addToUrl('ptg=' . $id) . '" title="' . specialchars($alt) . '" onclick="Backend.getScrollOffset();return AjaxRequest.toggleStructure(this,\'' . $node . '_' . $id . '\',' . $level . ',' . $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['mode'] . ')">' . \Image::getHtml($img, '', 'style="margin-right:2px"') . '</a>'; } foreach ($showFields as $k => $v) { // Decrypt the value if ($GLOBALS['TL_DCA'][$table]['fields'][$v]['eval']['encrypt']) { $objRow->{$v} = \Encryption::decrypt(deserialize($objRow->{$v})); } if (strpos($v, ':') !== false) { list($strKey, $strTable) = explode(':', $v); list($strTable, $strField) = explode('.', $strTable); $objRef = $this->Database->prepare("SELECT " . $strField . " FROM " . $strTable . " WHERE id=?")->limit(1)->execute($objRow->{$strKey}); $args[$k] = $objRef->numRows ? $objRef->{$strField} : ''; } elseif (in_array($GLOBALS['TL_DCA'][$table]['fields'][$v]['flag'], array(5, 6, 7, 8, 9, 10))) { $args[$k] = \Date::parse(\Config::get('datimFormat'), $objRow->{$v}); } elseif ($GLOBALS['TL_DCA'][$table]['fields'][$v]['inputType'] == 'checkbox' && !$GLOBALS['TL_DCA'][$table]['fields'][$v]['eval']['multiple']) { $args[$k] = $objRow->{$v} != '' ? isset($GLOBALS['TL_DCA'][$table]['fields'][$v]['label'][0]) ? $GLOBALS['TL_DCA'][$table]['fields'][$v]['label'][0] : $v : ''; } else { $args[$k] = $GLOBALS['TL_DCA'][$table]['fields'][$v]['reference'][$objRow->{$v}] ?: $objRow->{$v}; } } $label = vsprintf(strlen($GLOBALS['TL_DCA'][$table]['list']['label']['format']) ? $GLOBALS['TL_DCA'][$table]['list']['label']['format'] : '%s', $args); // Shorten the label if it is too long if ($GLOBALS['TL_DCA'][$table]['list']['label']['maxCharacters'] > 0 && $GLOBALS['TL_DCA'][$table]['list']['label']['maxCharacters'] < Utf8::strlen(strip_tags($label))) { $label = trim(\StringUtil::substrHtml($label, $GLOBALS['TL_DCA'][$table]['list']['label']['maxCharacters'])) . ' …'; } $label = preg_replace('/\\(\\) ?|\\[\\] ?|\\{\\} ?|<> ?/', '', $label); // Call the label_callback ($row, $label, $this) if (is_array($GLOBALS['TL_DCA'][$table]['list']['label']['label_callback'])) { $strClass = $GLOBALS['TL_DCA'][$table]['list']['label']['label_callback'][0]; $strMethod = $GLOBALS['TL_DCA'][$table]['list']['label']['label_callback'][1]; $this->import($strClass); $return .= $this->{$strClass}->{$strMethod}($objRow->row(), $label, $this, $folderAttribute, false, $blnProtected); } elseif (is_callable($GLOBALS['TL_DCA'][$table]['list']['label']['label_callback'])) { $return .= $GLOBALS['TL_DCA'][$table]['list']['label']['label_callback']($objRow->row(), $label, $this, $folderAttribute, false, $blnProtected); } else { $return .= \Image::getHtml('iconPLAIN.gif', '') . ' ' . $label; } $return .= '</div> <div class="tl_right">'; $previous = $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['mode'] == 6 ? $arrPrevNext['pp'] : $arrPrevNext['p']; $next = $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['mode'] == 6 ? $arrPrevNext['nn'] : $arrPrevNext['n']; $_buttons = ''; // Regular buttons ($row, $table, $root, $blnCircularReference, $childs, $previous, $next) if ($this->strTable == $table) { $_buttons .= \Input::get('act') == 'select' ? '<input type="checkbox" name="IDS[]" id="ids_' . $id . '" class="tl_tree_checkbox" value="' . $id . '">' : $this->generateButtons($objRow->row(), $table, $this->root, $blnCircularReference, $childs, $previous, $next); } // Paste buttons if ($arrClipboard !== false && \Input::get('act') != 'select') { $_buttons .= ' '; // Call paste_button_callback(&$dc, $row, $table, $blnCircularReference, $arrClipboard, $childs, $previous, $next) if (is_array($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['paste_button_callback'])) { $strClass = $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['paste_button_callback'][0]; $strMethod = $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['paste_button_callback'][1]; $this->import($strClass); $_buttons .= $this->{$strClass}->{$strMethod}($this, $objRow->row(), $table, $blnCircularReference, $arrClipboard, $childs, $previous, $next); } elseif (is_callable($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['paste_button_callback'])) { $_buttons .= $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['paste_button_callback']($this, $objRow->row(), $table, $blnCircularReference, $arrClipboard, $childs, $previous, $next); } else { $imagePasteAfter = \Image::getHtml('pasteafter.gif', sprintf($GLOBALS['TL_LANG'][$this->strTable]['pasteafter'][1], $id)); $imagePasteInto = \Image::getHtml('pasteinto.gif', sprintf($GLOBALS['TL_LANG'][$this->strTable]['pasteinto'][1], $id)); // Regular tree (on cut: disable buttons of the page all its childs to avoid circular references) if ($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['mode'] == 5) { $_buttons .= $arrClipboard['mode'] == 'cut' && ($blnCircularReference || $arrClipboard['id'] == $id) || $arrClipboard['mode'] == 'cutAll' && ($blnCircularReference || in_array($id, $arrClipboard['id'])) || !empty($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['root']) && !$GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['rootPaste'] && in_array($id, $this->root) ? \Image::getHtml('pasteafter_.gif') . ' ' : '<a href="' . $this->addToUrl('act=' . $arrClipboard['mode'] . '&mode=1&pid=' . $id . (!is_array($arrClipboard['id']) ? '&id=' . $arrClipboard['id'] : '')) . '" title="' . specialchars(sprintf($GLOBALS['TL_LANG'][$this->strTable]['pasteafter'][1], $id)) . '" onclick="Backend.getScrollOffset()">' . $imagePasteAfter . '</a> '; $_buttons .= $arrClipboard['mode'] == 'paste' && ($blnCircularReference || $arrClipboard['id'] == $id) || $arrClipboard['mode'] == 'cutAll' && ($blnCircularReference || in_array($id, $arrClipboard['id'])) ? \Image::getHtml('pasteinto_.gif') . ' ' : '<a href="' . $this->addToUrl('act=' . $arrClipboard['mode'] . '&mode=2&pid=' . $id . (!is_array($arrClipboard['id']) ? '&id=' . $arrClipboard['id'] : '')) . '" title="' . specialchars(sprintf($GLOBALS['TL_LANG'][$this->strTable]['pasteinto'][1], $id)) . '" onclick="Backend.getScrollOffset()">' . $imagePasteInto . '</a> '; } else { $_buttons .= $this->strTable == $table ? $arrClipboard['mode'] == 'cut' && ($blnCircularReference || $arrClipboard['id'] == $id) || $arrClipboard['mode'] == 'cutAll' && ($blnCircularReference || in_array($id, $arrClipboard['id'])) ? \Image::getHtml('pasteafter_.gif') : '<a href="' . $this->addToUrl('act=' . $arrClipboard['mode'] . '&mode=1&pid=' . $id . (!is_array($arrClipboard['id']) ? '&id=' . $arrClipboard['id'] : '')) . '" title="' . specialchars(sprintf($GLOBALS['TL_LANG'][$this->strTable]['pasteafter'][1], $id)) . '" onclick="Backend.getScrollOffset()">' . $imagePasteAfter . '</a> ' : ''; $_buttons .= $this->strTable != $table ? '<a href="' . $this->addToUrl('act=' . $arrClipboard['mode'] . '&mode=2&pid=' . $id . (!is_array($arrClipboard['id']) ? '&id=' . $arrClipboard['id'] : '')) . '" title="' . specialchars(sprintf($GLOBALS['TL_LANG'][$this->strTable]['pasteinto'][1], $id)) . '" onclick="Backend.getScrollOffset()">' . $imagePasteInto . '</a> ' : ''; } } } $return .= ($_buttons ?: ' ') . '</div><div style="clear:both"></div></li>'; // Add the records of the table itself if ($table != $this->strTable) { $objChilds = $this->Database->prepare("SELECT id FROM " . $this->strTable . " WHERE pid=?" . ($blnHasSorting ? " ORDER BY sorting" : ''))->execute($id); if ($objChilds->numRows) { $ids = $objChilds->fetchEach('id'); for ($j = 0, $c = count($ids); $j < $c; $j++) { $return .= $this->generateTree($this->strTable, $ids[$j], array('pp' => $ids[$j - 1], 'nn' => $ids[$j + 1]), $blnHasSorting, $intMargin + $intSpacing + 20, $arrClipboard, false, $j < count($ids) - 1 || !empty($childs), $blnNoRecursion, $arrFound); } } } // Begin a new submenu if (!$blnNoRecursion) { if (!empty($arrFound) || !empty($childs) && $session[$node][$id] == 1) { $return .= '<li class="parent" id="' . $node . '_' . $id . '"><ul class="level_' . $level . '">'; } // Add the records of the parent table if (!empty($arrFound) || $session[$node][$id] == 1) { if (is_array($childs)) { for ($k = 0, $c = count($childs); $k < $c; $k++) { $return .= $this->generateTree($table, $childs[$k], array('p' => $childs[$k - 1], 'n' => $childs[$k + 1]), $blnHasSorting, $intMargin + $intSpacing, $arrClipboard, $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['mode'] == 5 && $childs[$k] == $arrClipboard['id'] || $blnCircularReference ? true : false, $blnProtected || $protectedPage, $blnNoRecursion, $arrFound); } } } // Close the submenu if (!empty($arrFound) || !empty($childs) && $session[$node][$id] == 1) { $return .= '</ul></li>'; } } $objSessionBag->replace($session); return $return; }
/** * Returns length of the input string. * @param string $string The string which length is to be calculated. * @param string $encoding (optional) The used internally by this function character encoding. If it is omitted, the platform character set will be used by default. * @return int Returns the number of characters within the string. A multi-byte character is counted as 1. * This function is aimed at replacing the functions strlen() and mb_strlen() for human-language strings. * @link http://php.net/manual/en/function.strlen * @link http://php.net/manual/en/function.mb-strlen * Note: When you use strlen() to test for an empty string, you needn't change it to api_strlen(). * For example, in lines like the following: * if (strlen($string) > 0) * if (strlen($string) != 0) * there is no need the original function strlen() to be changed, it works correctly and faster for these cases. */ function api_strlen($string, $encoding = null) { return Utf8::strlen($string); }
/** * Recursively validate an input variable * * @param mixed $varInput The user input * * @return mixed The original or modified user input */ protected function validator($varInput) { if (is_array($varInput)) { foreach ($varInput as $k => $v) { $varInput[$k] = $this->validator($v); } return $varInput; } if (!$this->doNotTrim) { $varInput = trim($varInput); } if ($varInput == '') { if (!$this->mandatory) { return ''; } else { if ($this->strLabel == '') { $this->addError($GLOBALS['TL_LANG']['ERR']['mdtryNoLabel']); } else { $this->addError(sprintf($GLOBALS['TL_LANG']['ERR']['mandatory'], $this->strLabel)); } } } if ($this->minlength && $varInput != '' && Utf8::strlen($varInput) < $this->minlength) { $this->addError(sprintf($GLOBALS['TL_LANG']['ERR']['minlength'], $this->strLabel, $this->minlength)); } if ($this->maxlength && $varInput != '' && Utf8::strlen($varInput) > $this->maxlength) { $this->addError(sprintf($GLOBALS['TL_LANG']['ERR']['maxlength'], $this->strLabel, $this->maxlength)); } if ($this->minval && is_numeric($varInput) && $varInput < $this->minval) { $this->addError(sprintf($GLOBALS['TL_LANG']['ERR']['minval'], $this->strLabel, $this->minval)); } if ($this->maxval && is_numeric($varInput) && $varInput > $this->maxval) { $this->addError(sprintf($GLOBALS['TL_LANG']['ERR']['maxval'], $this->strLabel, $this->maxval)); } if ($this->rgxp != '') { switch ($this->rgxp) { // Special validation rule for style sheets case strncmp($this->rgxp, 'digit_', 6) === 0: $textual = explode('_', $this->rgxp); array_shift($textual); if (in_array($varInput, $textual) || strncmp($varInput, '$', 1) === 0) { break; } // DO NOT ADD A break; STATEMENT HERE // Numeric characters (including full stop [.] and minus [-]) // DO NOT ADD A break; STATEMENT HERE // Numeric characters (including full stop [.] and minus [-]) case 'digit': // Support decimal commas and convert them automatically (see #3488) if (substr_count($varInput, ',') == 1 && strpos($varInput, '.') === false) { $varInput = str_replace(',', '.', $varInput); } if (!\Validator::isNumeric($varInput)) { $this->addError(sprintf($GLOBALS['TL_LANG']['ERR']['digit'], $this->strLabel)); } break; // Natural numbers (positive integers) // Natural numbers (positive integers) case 'natural': if (!\Validator::isNatural($varInput)) { $this->addError(sprintf($GLOBALS['TL_LANG']['ERR']['natural'], $this->strLabel)); } break; // Alphabetic characters (including full stop [.] minus [-] and space [ ]) // Alphabetic characters (including full stop [.] minus [-] and space [ ]) case 'alpha': if (!\Validator::isAlphabetic($varInput)) { $this->addError(sprintf($GLOBALS['TL_LANG']['ERR']['alpha'], $this->strLabel)); } break; // Alphanumeric characters (including full stop [.] minus [-], underscore [_] and space [ ]) // Alphanumeric characters (including full stop [.] minus [-], underscore [_] and space [ ]) case 'alnum': if (!\Validator::isAlphanumeric($varInput)) { $this->addError(sprintf($GLOBALS['TL_LANG']['ERR']['alnum'], $this->strLabel)); } break; // Do not allow any characters that are usually encoded by class Input ([#<>()\=]) // Do not allow any characters that are usually encoded by class Input ([#<>()\=]) case 'extnd': if (!\Validator::isExtendedAlphanumeric(html_entity_decode($varInput))) { $this->addError(sprintf($GLOBALS['TL_LANG']['ERR']['extnd'], $this->strLabel)); } break; // Check whether the current value is a valid date format // Check whether the current value is a valid date format case 'date': if (!\Validator::isDate($varInput)) { $this->addError(sprintf($GLOBALS['TL_LANG']['ERR']['date'], \Date::getInputFormat(\Date::getNumericDateFormat()))); } else { // Validate the date (see #5086) try { new \Date($varInput, \Date::getNumericDateFormat()); } catch (\OutOfBoundsException $e) { $this->addError(sprintf($GLOBALS['TL_LANG']['ERR']['invalidDate'], $varInput)); } } break; // Check whether the current value is a valid time format // Check whether the current value is a valid time format case 'time': if (!\Validator::isTime($varInput)) { $this->addError(sprintf($GLOBALS['TL_LANG']['ERR']['time'], \Date::getInputFormat(\Date::getNumericTimeFormat()))); } break; // Check whether the current value is a valid date and time format // Check whether the current value is a valid date and time format case 'datim': if (!\Validator::isDatim($varInput)) { $this->addError(sprintf($GLOBALS['TL_LANG']['ERR']['dateTime'], \Date::getInputFormat(\Date::getNumericDatimFormat()))); } else { // Validate the date (see #5086) try { new \Date($varInput, \Date::getNumericDatimFormat()); } catch (\OutOfBoundsException $e) { $this->addError(sprintf($GLOBALS['TL_LANG']['ERR']['invalidDate'], $varInput)); } } break; // Check whether the current value is a valid friendly name e-mail address // Check whether the current value is a valid friendly name e-mail address case 'friendly': list($strName, $varInput) = \StringUtil::splitFriendlyEmail($varInput); // no break; // Check whether the current value is a valid e-mail address // no break; // Check whether the current value is a valid e-mail address case 'email': if (!\Validator::isEmail($varInput)) { $this->addError(sprintf($GLOBALS['TL_LANG']['ERR']['email'], $this->strLabel)); } if ($this->rgxp == 'friendly' && !empty($strName)) { $varInput = $strName . ' [' . $varInput . ']'; } break; // Check whether the current value is list of valid e-mail addresses // Check whether the current value is list of valid e-mail addresses case 'emails': $arrEmails = \StringUtil::trimsplit(',', $varInput); foreach ($arrEmails as $strEmail) { $strEmail = \Idna::encodeEmail($strEmail); if (!\Validator::isEmail($strEmail)) { $this->addError(sprintf($GLOBALS['TL_LANG']['ERR']['emails'], $this->strLabel)); break; } } break; // Check whether the current value is a valid URL // Check whether the current value is a valid URL case 'url': if (!\Validator::isUrl($varInput)) { $this->addError(sprintf($GLOBALS['TL_LANG']['ERR']['url'], $this->strLabel)); } break; // Check whether the current value is a valid alias // Check whether the current value is a valid alias case 'alias': if (!\Validator::isAlias($varInput)) { $this->addError(sprintf($GLOBALS['TL_LANG']['ERR']['alias'], $this->strLabel)); } break; // Check whether the current value is a valid folder URL alias // Check whether the current value is a valid folder URL alias case 'folderalias': if (!\Validator::isFolderAlias($varInput)) { $this->addError(sprintf($GLOBALS['TL_LANG']['ERR']['folderalias'], $this->strLabel)); } break; // Phone numbers (numeric characters, space [ ], plus [+], minus [-], parentheses [()] and slash [/]) // Phone numbers (numeric characters, space [ ], plus [+], minus [-], parentheses [()] and slash [/]) case 'phone': if (!\Validator::isPhone(html_entity_decode($varInput))) { $this->addError(sprintf($GLOBALS['TL_LANG']['ERR']['phone'], $this->strLabel)); } break; // Check whether the current value is a percent value // Check whether the current value is a percent value case 'prcnt': if (!\Validator::isPercent($varInput)) { $this->addError(sprintf($GLOBALS['TL_LANG']['ERR']['prcnt'], $this->strLabel)); } break; // Check whether the current value is a locale // Check whether the current value is a locale case 'locale': if (!\Validator::isLocale($varInput)) { $this->addError(sprintf($GLOBALS['TL_LANG']['ERR']['locale'], $this->strLabel)); } break; // Check whether the current value is a language code // Check whether the current value is a language code case 'language': if (!\Validator::isLanguage($varInput)) { $this->addError(sprintf($GLOBALS['TL_LANG']['ERR']['language'], $this->strLabel)); } break; // Check whether the current value is a Google+ ID or vanity name // Check whether the current value is a Google+ ID or vanity name case 'google+': if (!\Validator::isGooglePlusId($varInput)) { $this->addError(sprintf($GLOBALS['TL_LANG']['ERR']['invalidGoogleId'], $this->strLabel)); } break; // Check whether the current value is a field name // Check whether the current value is a field name case 'fieldname': if (!\Validator::isFieldName($varInput)) { $this->addError(sprintf($GLOBALS['TL_LANG']['ERR']['invalidFieldName'], $this->strLabel)); } break; // HOOK: pass unknown tags to callback functions // HOOK: pass unknown tags to callback functions default: if (isset($GLOBALS['TL_HOOKS']['addCustomRegexp']) && is_array($GLOBALS['TL_HOOKS']['addCustomRegexp'])) { foreach ($GLOBALS['TL_HOOKS']['addCustomRegexp'] as $callback) { $this->import($callback[0]); $break = $this->{$callback[0]}->{$callback[1]}($this->rgxp, $varInput, $this); // Stop the loop if a callback returned true if ($break === true) { break; } } } break; } } if ($this->isHexColor && $varInput != '' && strncmp($varInput, '$', 1) !== 0) { $varInput = preg_replace('/[^a-f0-9]+/i', '', $varInput); } if ($this->nospace && preg_match('/[\\t ]+/', $varInput)) { $this->addError(sprintf($GLOBALS['TL_LANG']['ERR']['noSpace'], $this->strLabel)); } if ($this->spaceToUnderscore) { $varInput = preg_replace('/\\s+/', '_', trim($varInput)); } if (is_bool($this->trailingSlash) && $varInput != '') { $varInput = preg_replace('/\\/+$/', '', $varInput) . ($this->trailingSlash ? '/' : ''); } return $varInput; }
/** * Creates an admin user. * * @return Response|RedirectResponse|null The response object */ private function createAdminUser() { $installTool = $this->container->get('contao.install_tool'); if (!$installTool->hasTable('tl_user')) { $this->context['hide_admin'] = true; return null; } if ($installTool->hasAdminUser()) { $this->context['has_admin'] = true; return null; } $request = $this->container->get('request_stack')->getCurrentRequest(); if ('tl_admin' !== $request->request->get('FORM_SUBMIT')) { return null; } $username = $request->request->get('username'); $name = $request->request->get('name'); $email = $request->request->get('email'); $password = $request->request->get('password'); $confirmation = $request->request->get('confirmation'); $this->context['admin_username_value'] = $username; $this->context['admin_name_value'] = $name; $this->context['admin_email_value'] = $email; // All fields are mandatory if ('' === $username || '' === $name || '' === $email || '' === $password) { $this->context['admin_error'] = $this->trans('admin_error'); return null; } // Do not allow special characters in usernames if (preg_match('/[#()\\/<=>]/', $username)) { $this->context['admin_username_error'] = $this->trans('admin_error_extnd'); return null; } // The username must not contain whitespace characters (see #4006) if (false !== strpos($username, ' ')) { $this->context['admin_username_error'] = $this->trans('admin_error_no_space'); return null; } // Validate the e-mail address (see #6003) if ($email !== filter_var($email, FILTER_VALIDATE_EMAIL)) { $this->context['admin_email_error'] = $this->trans('admin_error_email'); return null; } // The passwords do not match if ($password !== $confirmation) { $this->context['admin_password_error'] = $this->trans('admin_error_password_match'); return null; } $minlength = $installTool->getConfig('minPasswordLength'); // The password is too short if (Utf8::strlen($password) < $minlength) { $this->context['admin_password_error'] = sprintf($this->trans('password_too_short'), $minlength); return null; } // Password and username are the same if ($password === $username) { $this->context['admin_password_error'] = sprintf($this->trans('admin_error_password_user'), $minlength); return null; } $installTool->persistConfig('adminEmail', $email); $installTool->persistAdminUser($username, $name, $email, $password, $this->container->getParameter('locale')); return $this->getRedirectResponse(); }
public function test_empty_str() { $str = ''; $this->assertEquals(0, u::strlen($str)); }
/** * Determine the number of characters of a string * * @param string $str * * @return integer * * @deprecated Deprecated since Contao 4.0, to be removed in Contao 5.0. * Use Patchwork\Utf8::strlen() instead. */ function utf8_strlen($str) { @trigger_error('Using utf8_strlen() has been deprecated and will no longer work in Contao 5.0. Use Patchwork\\Utf8::strlen() instead.', E_USER_DEPRECATED); return Utf8::strlen($str); }
public function length() { return u::strlen($this->string); }
private function passwordValidator($password, $minLength, $username) { if (Utf8::strlen($password) < $minLength) { throw new \RuntimeException('The given password is too short (Minimum ' . $minLength . ' characters)'); } if ($password == $username) { throw new \RuntimeException('Username and password must not be the same'); } return $password; }
/** * Validate input and set value * * @param mixed $varInput The user input * * @return mixed The validated user input */ protected function validator($varInput) { $this->blnSubmitInput = false; if (!strlen($varInput) && (strlen($this->varValue) || !$this->mandatory)) { return ''; } if (Utf8::strlen($varInput) < \Config::get('minPasswordLength')) { $this->addError(sprintf($GLOBALS['TL_LANG']['ERR']['passwordLength'], \Config::get('minPasswordLength'))); } if ($varInput != $this->getPost($this->strName . '_confirm')) { $this->addError($GLOBALS['TL_LANG']['ERR']['passwordMatch']); } $varInput = parent::validator($varInput); if (!$this->hasErrors()) { $this->blnSubmitInput = true; return \Encryption::hash($varInput); } return ''; }
/** * Index a page * * @param array $arrData The data array * * @return boolean True if a new record was created */ public static function indexPage($arrData) { $objDatabase = \Database::getInstance(); $arrSet['url'] = $arrData['url']; $arrSet['title'] = $arrData['title']; $arrSet['protected'] = $arrData['protected']; $arrSet['filesize'] = $arrData['filesize']; $arrSet['groups'] = $arrData['groups']; $arrSet['pid'] = $arrData['pid']; $arrSet['language'] = $arrData['language']; // Get the file size from the raw content if (!$arrSet['filesize']) { $arrSet['filesize'] = number_format(strlen($arrData['content']) / 1024, 2, '.', ''); } // Replace special characters $strContent = str_replace(array("\n", "\r", "\t", ' ', ' '), ' ', $arrData['content']); // Strip script tags while (($intStart = strpos($strContent, '<script')) !== false) { if (($intEnd = strpos($strContent, '</script>', $intStart)) !== false) { $strContent = substr($strContent, 0, $intStart) . substr($strContent, $intEnd + 9); } else { break; // see #5119 } } // Strip style tags while (($intStart = strpos($strContent, '<style')) !== false) { if (($intEnd = strpos($strContent, '</style>', $intStart)) !== false) { $strContent = substr($strContent, 0, $intStart) . substr($strContent, $intEnd + 8); } else { break; // see #5119 } } // Strip non-indexable areas while (($intStart = strpos($strContent, '<!-- indexer::stop -->')) !== false) { if (($intEnd = strpos($strContent, '<!-- indexer::continue -->', $intStart)) !== false) { $intCurrent = $intStart; // Handle nested tags while (($intNested = strpos($strContent, '<!-- indexer::stop -->', $intCurrent + 22)) !== false && $intNested < $intEnd) { if (($intNewEnd = strpos($strContent, '<!-- indexer::continue -->', $intEnd + 26)) !== false) { $intEnd = $intNewEnd; $intCurrent = $intNested; } else { break; // see #5119 } } $strContent = substr($strContent, 0, $intStart) . substr($strContent, $intEnd + 26); } else { break; // see #5119 } } // HOOK: add custom logic if (isset($GLOBALS['TL_HOOKS']['indexPage']) && is_array($GLOBALS['TL_HOOKS']['indexPage'])) { foreach ($GLOBALS['TL_HOOKS']['indexPage'] as $callback) { \System::importStatic($callback[0])->{$callback[1]}($strContent, $arrData, $arrSet); } } // Free the memory unset($arrData['content']); // Calculate the checksum (see #4179) $arrSet['checksum'] = md5(preg_replace('/ +/', ' ', strip_tags($strContent))); // Return if the page is indexed and up to date $objIndex = $objDatabase->prepare("SELECT id, checksum FROM tl_search WHERE url=? AND pid=?")->limit(1)->execute($arrSet['url'], $arrSet['pid']); if ($objIndex->numRows && $objIndex->checksum == $arrSet['checksum']) { return false; } $arrMatches = array(); preg_match('/<\\/head>/', $strContent, $arrMatches, PREG_OFFSET_CAPTURE); $intOffset = strlen($arrMatches[0][0]) + $arrMatches[0][1]; // Split page in head and body section $strHead = substr($strContent, 0, $intOffset); $strBody = substr($strContent, $intOffset); unset($strContent); $tags = array(); // Get description if (preg_match('/<meta[^>]+name="description"[^>]+content="([^"]*)"[^>]*>/i', $strHead, $tags)) { $arrData['description'] = trim(preg_replace('/ +/', ' ', \StringUtil::decodeEntities($tags[1]))); } // Get keywords if (preg_match('/<meta[^>]+name="keywords"[^>]+content="([^"]*)"[^>]*>/i', $strHead, $tags)) { $arrData['keywords'] = trim(preg_replace('/ +/', ' ', \StringUtil::decodeEntities($tags[1]))); } // Read title and alt attributes if (preg_match_all('/<* (title|alt)="([^"]*)"[^>]*>/i', $strBody, $tags)) { $arrData['keywords'] .= ' ' . implode(', ', array_unique($tags[2])); } // Add a whitespace character before line-breaks and between consecutive tags (see #5363) $strBody = str_ireplace(array('<br', '><'), array(' <br', '> <'), $strBody); $strBody = strip_tags($strBody); // Put everything together $arrSet['text'] = $arrData['title'] . ' ' . $arrData['description'] . ' ' . $strBody . ' ' . $arrData['keywords']; $arrSet['text'] = trim(preg_replace('/ +/', ' ', \StringUtil::decodeEntities($arrSet['text']))); $arrSet['tstamp'] = time(); // Update an existing old entry if ($objIndex->numRows) { $objDatabase->prepare("UPDATE tl_search %s WHERE id=?")->set($arrSet)->execute($objIndex->id); $intInsertId = $objIndex->id; } else { // Check for a duplicate record with the same checksum $objDuplicates = $objDatabase->prepare("SELECT id, url FROM tl_search WHERE pid=? AND checksum=?")->limit(1)->execute($arrSet['pid'], $arrSet['checksum']); // Keep the existing record if ($objDuplicates->numRows) { // Update the URL if the new URL is shorter or the current URL is not canonical if (substr_count($arrSet['url'], '/') < substr_count($objDuplicates->url, '/') || strncmp($arrSet['url'] . '?', $objDuplicates->url, Utf8::strlen($arrSet['url']) + 1) === 0) { $objDatabase->prepare("UPDATE tl_search SET url=? WHERE id=?")->execute($arrSet['url'], $objDuplicates->id); } return false; } else { $objInsertStmt = $objDatabase->prepare("INSERT INTO tl_search %s")->set($arrSet)->execute(); $intInsertId = $objInsertStmt->insertId; } } // Remove quotes $strText = str_replace(array('´', '`'), "'", $arrSet['text']); unset($arrSet); // Remove special characters $strText = preg_replace(array('/- /', '/ -/', "/' /", "/ '/", '/\\. /', '/\\.$/', '/: /', '/:$/', '/, /', '/,$/', '/[^\\w\'.:,+-]/u'), ' ', $strText); // Split words $arrWords = preg_split('/ +/', Utf8::strtolower($strText)); $arrIndex = array(); // Index words foreach ($arrWords as $strWord) { // Strip a leading plus (see #4497) if (strncmp($strWord, '+', 1) === 0) { $strWord = substr($strWord, 1); } $strWord = trim($strWord); if (!strlen($strWord) || preg_match('/^[\\.:,\'_-]+$/', $strWord)) { continue; } if (preg_match('/^[\':,]/', $strWord)) { $strWord = substr($strWord, 1); } if (preg_match('/[\':,.]$/', $strWord)) { $strWord = substr($strWord, 0, -1); } if (isset($arrIndex[$strWord])) { $arrIndex[$strWord]++; continue; } $arrIndex[$strWord] = 1; } // Remove existing index $objDatabase->prepare("DELETE FROM tl_search_index WHERE pid=?")->execute($intInsertId); // Create new index foreach ($arrIndex as $k => $v) { $objDatabase->prepare("INSERT INTO tl_search_index (pid, word, relevance, language) VALUES (?, ?, ?, ?)")->execute($intInsertId, $k, $v, $arrData['language']); } return true; }
/** * Validate input and set value * * @param mixed $varInput * * @return string */ protected function validator($varInput) { $this->blnSubmitInput = false; if (($varInput == '' || $varInput == '*****') && $this->varValue != '') { return '*****'; } if (Utf8::strlen($varInput) < \Config::get('minPasswordLength')) { $this->addError(sprintf($GLOBALS['TL_LANG']['ERR']['passwordLength'], \Config::get('minPasswordLength'))); } if ($varInput != $this->getPost($this->strName . '_confirm')) { $this->addError($GLOBALS['TL_LANG']['ERR']['passwordMatch']); } if ($varInput == $GLOBALS['TL_USERNAME']) { $this->addError($GLOBALS['TL_LANG']['ERR']['passwordName']); } $varInput = parent::validator($varInput); if (!$this->hasErrors()) { $this->blnSubmitInput = true; \Message::addConfirmation($GLOBALS['TL_LANG']['MSC']['pw_changed']); return \Encryption::hash($varInput); } return ''; }
/** * Validates the password length and creates the password hash. * * @param string $password * * @return string * * @throws InvalidArgumentException */ private function validateAndHashPassword($password) { $framework = $this->getContainer()->get('contao.framework'); $framework->initialize(); /** @var Config $confirm */ $config = $framework->getAdapter(Config::class); $passwordLength = $config->get('minPasswordLength') ?: 8; if (Utf8::strlen($password) < $passwordLength) { throw new InvalidArgumentException(sprintf('The password must be at least %s characters long.', $passwordLength)); } /** @var Encryption $encryption */ $encryption = $framework->getAdapter(Encryption::class); return $encryption->hash($password); }