/** * Remove the recipient */ protected function removeSubscriber() { $varInput = Idna::encodeEmail(Input::get('email', true)); // Validate e-mail address if (!Validator::isEmail($varInput)) { $_SESSION['UNSUBSCRIBE_ERROR'] = $GLOBALS['TL_LANG']['ERR']['email']; $this->redirect($this->generateFrontendUrl($this->objModel->getRelated('jumpTo')->row())); } $objCleverReach = new CleverReach(); switch ($this->clr_unsubscribe) { case 'inactive': foreach ($this->clr_groups as $strGroupId) { $objCleverReach->receiverSetInactive($varInput, $strGroupId); } break; case 'delete': foreach ($this->clr_groups as $strGroupId) { $objCleverReach->receiverDelete($varInput, $strGroupId); } break; case 'email': default: $objCleverReach->sendUnsubscribeMail($varInput, $this->clr_form); break; } $this->redirect($this->generateFrontendUrl($this->objModel->getRelated('jumpTo')->row())); }
/** * Extract all e-mail addresses from a string * * @param string $strString The string * * @return array The e-mail addresses */ public static function extractEmail($strString) { $arrEmails = array(); preg_match_all('/(?:[^\\x00-\\x20\\x22\\x40\\x7F]+|\\x22[^\\x00-\\x1F\\x7F]+?\\x22)@(?:\\[(?:IPv)?[a-f0-9.:]+\\]|[\\w.-]+\\.[a-z]{2,63}\\b)/u', $strString, $arrEmails); foreach ($arrEmails[0] as $strKey => $strEmail) { if (!\Validator::isEmail($strEmail)) { unset($arrEmails[0][$strKey]); } } return array_values($arrEmails[0]); }
/** * 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; }
/** * Tests the isEmail() method. * * @param string $email The email * @param bool $expected The expected result * * @dataProvider emailProvider */ public function testEmail($email, $expected) { $this->assertEquals($expected, Validator::isEmail($email), 'Original: ' . $email . ' idna: ' . Idna::encodeEmail($email)); }
/** * Validate an e-mail address * * @param string $strEmail The e-mail address * * @return boolean True if it is a valid e-mail address * * @deprecated Deprecated since Contao 4.0, to be removed in Contao 5.0. * Use Validator::isEmail() instead. */ protected function isValidEmailAddress($strEmail) { @trigger_error('Using System::isValidEmailAddress() has been deprecated and will no longer work in Contao 5.0. Use Validator::isEmail() instead.', E_USER_DEPRECATED); return \Validator::isEmail($strEmail); }
/** * Return a form to choose a CSV file and import it * * @return string */ public function importRecipients() { if (\Input::get('key') != 'import') { return ''; } $this->import('BackendUser', 'User'); $class = $this->User->uploader; // See #4086 and #7046 if (!class_exists($class) || $class == 'DropZone') { $class = 'FileUpload'; } /** @var FileUpload $objUploader */ $objUploader = new $class(); // Import recipients if (\Input::post('FORM_SUBMIT') == 'tl_recipients_import') { $arrUploaded = $objUploader->uploadTo('system/tmp'); if (empty($arrUploaded)) { \Message::addError($GLOBALS['TL_LANG']['ERR']['all_fields']); $this->reload(); } $time = time(); $intTotal = 0; $intInvalid = 0; foreach ($arrUploaded as $strCsvFile) { $objFile = new \File($strCsvFile); if ($objFile->extension != 'csv') { \Message::addError(sprintf($GLOBALS['TL_LANG']['ERR']['filetype'], $objFile->extension)); continue; } // Get separator switch (\Input::post('separator')) { case 'semicolon': $strSeparator = ';'; break; case 'tabulator': $strSeparator = "\t"; break; case 'linebreak': $strSeparator = "\n"; break; default: $strSeparator = ','; break; } $arrRecipients = array(); $resFile = $objFile->handle; while (($arrRow = @fgetcsv($resFile, null, $strSeparator)) !== false) { $arrRecipients = array_merge($arrRecipients, $arrRow); } $arrRecipients = array_filter(array_unique($arrRecipients)); foreach ($arrRecipients as $strRecipient) { // Skip invalid entries if (!\Validator::isEmail($strRecipient)) { $this->log('Recipient address "' . $strRecipient . '" seems to be invalid and was not imported', __METHOD__, TL_ERROR); ++$intInvalid; continue; } // Check whether the e-mail address exists $objRecipient = $this->Database->prepare("SELECT COUNT(*) AS count FROM tl_newsletter_recipients WHERE pid=? AND email=?")->execute(\Input::get('id'), $strRecipient); if ($objRecipient->count > 0) { continue; } // Check whether the e-mail address has been blacklisted $objBlacklist = $this->Database->prepare("SELECT COUNT(*) AS count FROM tl_newsletter_blacklist WHERE pid=? AND hash=?")->execute(\Input::get('id'), md5($strRecipient)); if ($objBlacklist->count > 0) { $this->log('Recipient address "' . $strRecipient . '" has been unsubscribed and was not imported', __METHOD__, TL_ERROR); continue; } $this->Database->prepare("INSERT INTO tl_newsletter_recipients SET pid=?, tstamp={$time}, email=?, active=1")->execute(\Input::get('id'), $strRecipient); ++$intTotal; } } \Message::addConfirmation(sprintf($GLOBALS['TL_LANG']['tl_newsletter_recipients']['confirm'], $intTotal)); if ($intInvalid > 0) { \Message::addInfo(sprintf($GLOBALS['TL_LANG']['tl_newsletter_recipients']['invalid'], $intInvalid)); } \System::setCookie('BE_PAGE_OFFSET', 0, 0); $this->reload(); } // Return form return ' <div id="tl_buttons"> <a href="' . ampersand(str_replace('&key=import', '', \Environment::get('request'))) . '" class="header_back" title="' . specialchars($GLOBALS['TL_LANG']['MSC']['backBTTitle']) . '" accesskey="b">' . $GLOBALS['TL_LANG']['MSC']['backBT'] . '</a> </div> ' . \Message::generate() . ' <form action="' . ampersand(\Environment::get('request'), true) . '" id="tl_recipients_import" class="tl_form" method="post" enctype="multipart/form-data"> <div class="tl_formbody_edit"> <input type="hidden" name="FORM_SUBMIT" value="tl_recipients_import"> <input type="hidden" name="REQUEST_TOKEN" value="' . REQUEST_TOKEN . '"> <input type="hidden" name="MAX_FILE_SIZE" value="' . \Config::get('maxFileSize') . '"> <div class="tl_tbox"> <h3><label for="separator">' . $GLOBALS['TL_LANG']['MSC']['separator'][0] . '</label></h3> <select name="separator" id="separator" class="tl_select" onfocus="Backend.getScrollOffset()"> <option value="comma">' . $GLOBALS['TL_LANG']['MSC']['comma'] . '</option> <option value="semicolon">' . $GLOBALS['TL_LANG']['MSC']['semicolon'] . '</option> <option value="tabulator">' . $GLOBALS['TL_LANG']['MSC']['tabulator'] . '</option> <option value="linebreak">' . $GLOBALS['TL_LANG']['MSC']['linebreak'] . '</option> </select>' . ($GLOBALS['TL_LANG']['MSC']['separator'][1] != '' ? ' <p class="tl_help tl_tip">' . $GLOBALS['TL_LANG']['MSC']['separator'][1] . '</p>' : '') . ' <h3>' . $GLOBALS['TL_LANG']['MSC']['source'][0] . '</h3>' . $objUploader->generateMarkup() . (isset($GLOBALS['TL_LANG']['MSC']['source'][1]) ? ' <p class="tl_help tl_tip">' . $GLOBALS['TL_LANG']['MSC']['source'][1] . '</p>' : '') . ' </div> </div> <div class="tl_formbody_submit"> <div class="tl_submit_container"> <button type="submit" name="save" id="save" class="tl_submit" accesskey="s">' . $GLOBALS['TL_LANG']['tl_newsletter_recipients']['import'][0] . '</button> </div> </div> </form>'; }
/** * Validate the subscription form * * @param Widget $objWidget * * @return array|bool */ protected function validateForm(Widget $objWidget = null) { // Validate the e-mail address $varInput = \Idna::encodeEmail(\Input::post('email', true)); if (!\Validator::isEmail($varInput)) { $this->Template->mclass = 'error'; $this->Template->message = $GLOBALS['TL_LANG']['ERR']['email']; return false; } $this->Template->email = $varInput; // Validate the channel selection $arrChannels = \Input::post('channels'); if (!is_array($arrChannels)) { $this->Template->mclass = 'error'; $this->Template->message = $GLOBALS['TL_LANG']['ERR']['noChannels']; return false; } $arrChannels = array_intersect($arrChannels, $this->nl_channels); // see #3240 if (!is_array($arrChannels) || empty($arrChannels)) { $this->Template->mclass = 'error'; $this->Template->message = $GLOBALS['TL_LANG']['ERR']['noChannels']; return false; } $this->Template->selectedChannels = $arrChannels; // Check if there are any new subscriptions $arrSubscriptions = array(); if (($objSubscription = \NewsletterRecipientsModel::findBy(array("email=? AND active=1"), $varInput)) !== null) { $arrSubscriptions = $objSubscription->fetchEach('pid'); } $arrRemove = array_intersect($arrChannels, $arrSubscriptions); if (!is_array($arrRemove) || empty($arrRemove)) { $this->Template->mclass = 'error'; $this->Template->message = $GLOBALS['TL_LANG']['ERR']['unsubscribed']; return false; } // Validate the captcha if ($objWidget !== null) { $objWidget->validate(); if ($objWidget->hasErrors()) { return false; } } return array($varInput, $arrRemove); }
protected function addSubscriber() { $varInput = Idna::encodeEmail(Input::post('email', true)); // Validate the e-mail address if (!Validator::isEmail($varInput)) { $_SESSION['SUBSCRIBE_ERROR'] = $GLOBALS['TL_LANG']['ERR']['email']; $this->reload(); } $objCleverReach = new CleverReach(); foreach ($this->clr_groups as $strGroupId) { $objCleverReach->addReceiver($varInput, $strGroupId); } $objCleverReach->sendActivationMail($varInput, $this->clr_form); // Redirect to the jumpTo page if ($this->jumpTo && ($objTarget = $this->objModel->getRelated('jumpTo')) !== null) { $this->redirect($this->generateFrontendUrl($objTarget->row())); } $_SESSION['SUBSCRIBE_CONFIRM'] = $GLOBALS['TL_LANG']['MSC']['nl_confirm']; $this->reload(); }
/** * Create an admin user */ protected function createAdminUser() { try { $objAdmin = $this->Database->execute("SELECT COUNT(*) AS count FROM tl_user WHERE admin=1"); if ($objAdmin->count > 0) { $this->Template->adminCreated = true; } elseif (\Input::post('FORM_SUBMIT') == 'tl_admin') { // Do not allow special characters in usernames if (preg_match('/[#\\(\\)\\/<=>]/', \Input::post('username', true))) { $this->Template->usernameError = $GLOBALS['TL_LANG']['ERR']['extnd']; } elseif (strpos(\Input::post('username', true), ' ') !== false) { $this->Template->usernameError = sprintf($GLOBALS['TL_LANG']['ERR']['noSpace'], $GLOBALS['TL_LANG']['MSC']['username']); } elseif (!\Validator::isEmail(\Input::post('email', true))) { $this->Template->emailError = $GLOBALS['TL_LANG']['ERR']['email']; } elseif (\Input::post('pass', true) != \Input::post('confirm_pass', true)) { $this->Template->passwordError = $GLOBALS['TL_LANG']['ERR']['passwordMatch']; } elseif (utf8_strlen(\Input::post('pass', true)) < \Config::get('minPasswordLength')) { $this->Template->passwordError = sprintf($GLOBALS['TL_LANG']['ERR']['passwordLength'], \Config::get('minPasswordLength')); } elseif (\Input::post('pass', true) == \Input::post('username', true)) { $this->Template->passwordError = $GLOBALS['TL_LANG']['ERR']['passwordName']; } elseif (\Input::post('name') != '' && \Input::post('email', true) != '' && \Input::post('username', true) != '') { $time = time(); $strPassword = \Encryption::hash(\Input::post('pass', true)); $this->Database->prepare("INSERT INTO tl_user (tstamp, name, email, username, password, language, backendTheme, admin, showHelp, useRTE, useCE, thumbnails, dateAdded) VALUES ({$time}, ?, ?, ?, ?, ?, ?, 1, 1, 1, 1, 1, {$time})")->execute(\Input::post('name'), \Input::post('email', true), \Input::post('username', true), $strPassword, str_replace('-', '_', $GLOBALS['TL_LANGUAGE']), \Config::get('backendTheme')); \Config::persist('adminEmail', \Input::post('email', true)); // Scan the upload folder (see #6134) if ($this->Database->tableExists('tl_files') && $this->Database->query("SELECT COUNT(*) AS count FROM tl_files")->count < 1) { $this->import('Database\\Updater', 'Updater'); $this->Updater->scanUploadFolder(); } $this->reload(); } $this->Template->adminName = \Input::post('name'); $this->Template->adminEmail = \Input::post('email', true); $this->Template->adminUser = \Input::post('username', true); } } catch (ResponseException $e) { throw $e; // see #267 } catch (\Exception $e) { $this->Template->adminCreated = false; } }
/** * Extract all e-mail addresses from a string * * @param string $strString The string * @param string $strAllowedTags A list of allowed HTML tags * * @return array The e-mail addresses */ public static function extractEmail($strString, $strAllowedTags = '') { $arrEmails = array(); if (strpos($strString, '@') === false) { return $arrEmails; } // Find all mailto: addresses preg_match_all('/mailto:(?:[^\\x00-\\x20\\x22\\x40\\x7F]+|\\x22[^\\x00-\\x1F\\x7F]+?\\x22)@(?:\\[(?:IPv)?[a-f0-9.:]+\\]|[\\w.-]+\\.[a-z]{2,63}\\b)/u', $strString, $matches); foreach ($matches[0] as &$strEmail) { $strEmail = str_replace('mailto:', '', $strEmail); if (\Validator::isEmail($strEmail)) { $arrEmails[] = $strEmail; } } // Encode opening arrow brackets (see #3998) $strString = preg_replace_callback('@</?([^\\s<>/]*)@', function ($matches) use($strAllowedTags) { if ($matches[1] == '' || strpos(strtolower($strAllowedTags), '<' . strtolower($matches[1]) . '>') === false) { $matches[0] = str_replace('<', '<', $matches[0]); } return $matches[0]; }, $strString); // Find all addresses in the plain text preg_match_all('/(?:[^\\x00-\\x20\\x22\\x40\\x7F]+|\\x22[^\\x00-\\x1F\\x7F]+?\\x22)@(?:\\[(?:IPv)?[a-f0-9.:]+\\]|[\\w.-]+\\.[a-z]{2,63}\\b)/u', strip_tags($strString), $matches); foreach ($matches[0] as &$strEmail) { $strEmail = str_replace('<', '<', $strEmail); if (\Validator::isEmail($strEmail)) { $arrEmails[] = $strEmail; } } return array_unique($arrEmails); }