public function testSanitize() { $given = array("field1" => "<p>A <strong>string</strong> with an <script></script>escaped apostrophe: it\\'s</p>", "field2" => array("it\\'s cool", "yeah it\\'s cool")); $expected = array("field1" => "<p>A <strong>string</strong> with an escaped apostrophe: it's</p>", "field2" => array("it's cool", "yeah it's cool")); $sanitizer = new Sanitizer($given); $sanitizer->stripslashes()->striptags(array("<p>", "<strong>")); $this->assertEquals($expected, $sanitizer->data); }
function __construct($job_id = false) { global $db; if (is_numeric($job_id)) { $sanitizer = new Sanitizer(); $sql = 'SELECT a.type_id AS type_id, a.category_id AS category_id, a.title AS title, a.summary AS summary, a.description AS description, a.company AS company, a.url AS url, a.apply AS apply, DATE_FORMAT(a.created_on, "' . DATE_FORMAT . '") AS created_on, a.created_on AS mysql_date, a.is_temp AS is_temp, a.is_active AS is_active, a.spotlight AS spotlight, a.views_count AS views_count, a.auth AS auth, a.city_id AS city_id, a.outside_location AS outside_location, a.poster_email AS poster_email, a.apply_online AS apply_online, b.name AS category_name, c.var_name as type_var_name, c.name as type_name, DATE_ADD(created_on, INTERVAL 30 DAY) AS closed_on, DATEDIFF(NOW(), created_on) AS days_old, cit.name AS city_name FROM ' . DB_PREFIX . 'jobs a LEFT JOIN ' . DB_PREFIX . 'cities cit on a.city_id = cit.id, ' . DB_PREFIX . 'categories b, ' . DB_PREFIX . 'types c WHERE a.category_id = b.id AND c.id = a.type_id AND a.id = ' . $job_id; $result = $db->query($sql); $row = $result->fetch_assoc(); if (!empty($row)) { $this->mId = $job_id; $this->mTypeId = $row['type_id']; $this->mCategoryId = $row['category_id']; $this->mCategoryName = $row['category_name']; $this->mTitle = str_replace('&', '&', $row['title']); $this->mSummary = str_replace('&', '&', $row['summary']); $this->mDescription = $row['description']; $this->mCompany = $row['company']; $this->mUrl = $row['url']; $this->mApply = $row['apply']; $this->mCreatedOn = $row['created_on']; $this->mClosedOn = $row['closed_on']; $this->mIsTemp = $row['is_temp']; $this->mIsActive = $row['is_active']; $this->mViewsCount = $row['views_count']; $this->mAuth = $row['auth']; $this->mCityId = $row['city_id']; $this->mMySqlDate = $row['mysql_date']; $this->mLocation = $this->GetLocation($row); $this->mLocationOutsideRo = $row['outside_location']; $this->mPosterEmail = $row['poster_email']; $this->mUrlTitle = $sanitizer->sanitize_title_with_dashes($this->mTitle . ' at ' . $this->mCompany); $this->mApplyOnline = $row['apply_online']; $this->mDaysOld = $row['days_old']; $this->mIsSpotlight = $row['spotlight']; $this->mTypeName = $row['type_name']; $this->mTypeVarName = $row['type_var_name']; } } }
public function getDiv($value) { global $wgOut, $wgPromoterAdPreview; if (array_key_exists('language', $this->mParams)) { $language = $this->mParams['language']; } else { $language = $wgOut->getContext()->getLanguage()->getCode(); } $html = Xml::openElement('div', array('id' => Sanitizer::escapeId("pr-ad-list-element-{$this->mParams['ad']}"), 'class' => "pr-ad-list-element")); // Make the label; this consists of a text link to the ad editor, and a series of status icons if (array_key_exists('withlabel', $this->mParams)) { $adName = $this->mParams['ad']; $html .= Xml::openElement('div', array('class' => 'pr-ad-list-element-label')); $html .= Linker::link(SpecialPage::getTitleFor('PromoterAds', "edit/{$adName}"), htmlspecialchars($adName), array('class' => 'pr-ad-list-element-label-text')); $html .= ' (' . Linker::link(SpecialPage::getTitleFor('Randompage'), $this->msg('promoter-live-preview'), array('class' => 'pr-ad-list-element-label-text'), array('ad' => $adName, 'uselang' => $language, 'force' => '1')) . ')'; // TODO: Output status icons $html .= Xml::tags('div', array('class' => 'pr-ad-list-element-label-icons'), ''); $html .= Xml::closeElement('div'); } // Add the ad preview if ($wgPromoterAdPreview) { $html .= $this->getInputHTML(null); } $html .= Xml::closeElement('div'); return $html; }
function execute() { global $wgLang, $wgRequest; global $wgOut, $wgExtensionsPath; global $wgUser, $wgCaptchaClass, $wgJsMimeType; $wgOut->addStyle(AssetsManager::getInstance()->getSassCommonURL('extensions/wikia/SpecialContact/SpecialContact.scss')); $this->mName = null; $this->mRealName = null; $this->mWhichWiki = null; $this->mProblem = $wgRequest->getText('wpContactSubject'); //subject $this->mProblemDesc = null; $this->mPosted = $wgRequest->wasPosted(); $this->mAction = $wgRequest->getVal('action'); $this->mEmail = $wgRequest->getText('wpEmail'); $this->mBrowser = $wgRequest->getText('wpBrowser'); $this->mAbTestInfo = $wgRequest->getText('wpAbTesting'); $this->mCCme = $wgRequest->getCheck('wgCC'); if ($this->mPosted && 'submit' == $this->mAction) { if (!$wgUser->isLoggedIn() && class_exists($wgCaptchaClass)) { $captchaObj = new $wgCaptchaClass(); $captchaObj->retrieveCaptcha(); $info = $captchaObj->retrieveCaptcha(); } #ubrfzy note: these were moved inside to (lazy) prevent some stupid bots $this->mName = $wgRequest->getText('wpName'); $this->mRealName = $wgRequest->getText('wpContactRealName'); $this->mWhichWiki = $wgRequest->getText('wpContactWikiName'); #sibject still handled outside of post check, because of existing hardcoded prefill links $this->mProblemDesc = $wgRequest->getText('wpContactDesc'); //body #malformed email? if (!Sanitizer::validateEmail($this->mEmail)) { $this->err[] .= wfMsg('invalidemailaddress'); $this->errInputs['wpEmail'] = true; } #empty message text? if (empty($this->mProblemDesc)) { $this->err[] .= wfMsg('specialcontact-nomessage'); $this->errInputs['wpContactDesc'] = true; } #captcha if (!$wgUser->isLoggedIn() && class_exists($wgCaptchaClass)) { // logged in users don't need the captcha (RT#139647) if (!(!empty($info) && $captchaObj->keyMatch($wgRequest->getVal('wpCaptchaWord'), $info))) { $this->err[] .= wfMsg('specialcontact-captchafail'); $this->errInputs['wpCaptchaWord'] = true; } } #no errors? if (empty($this->err)) { #send email $this->processCreation(); #stop here return; } #if there were any ->err s, they will be displayed in ContactForm } $this->mainContactForm(); }
function efGPManagerCustomToolboxAppend(&$skin) { global $wgOut, $wgUser; $tb = explode("\n", wfMsg('toolbox_append')); $new = array(); foreach ($tb as &$nt) { if (strpos($nt, '*') === 0) { $nt = trim($nt, '*'); $parts = explode('|', $nt); foreach ($parts as &$part) { $part = trim($part); } $href = wfMsgForContent($parts[0]); $text = wfMsgForContent($parts[1]); $perm = array_key_exists(2, $parts) ? $parts[2] : 'read'; if (!$wgUser->isAllowed($perm)) { continue; } if (wfEmptyMsg($parts[0], $href)) { $href = $parts[0]; } if (wfEmptyMsg($parts[1], $text)) { $text = $parts[1]; } $id = Sanitizer::escapeId($parts[1], 'noninitial'); $new[] = array($href, $text, $id); } } foreach ($new as $t) { echo '<li id="t-' . $t[2] . '"><a href="' . htmlspecialchars($t[0]) . '">' . $t[1] . '</a></li>'; } return true; }
/** * Builds the HTML code for this component * * @return String the HTML code */ public function getHtml() { $element = $this->getDomElement(); if ($element === null) { return ''; } $msgKey = $element->getAttribute('message'); $menuFactory = new MenuFactory(); if (empty($msgKey)) { $text = $element->textContent; $menu = $menuFactory->getMenuFromMessageText($text); } else { $menu = $menuFactory->getMenuFromMessage($msgKey); } $menu->setMenuItemFormatter(function ($href, $text, $depth, $subitems) { $href = \Sanitizer::cleanUrl($href); $text = htmlspecialchars($text); if ($depth === 1 && !empty($subitems)) { return "<li class=\"dropdown\"><a class=\"dropdown-toggle\" href=\"#\" data-toggle=\"dropdown\">{$text}<b class=\"caret\"></b></a>{$subitems}</li>"; } else { return "<li><a href=\"{$href}\">{$text}</a>{$subitems}</li>"; } }); $menu->setItemListFormatter(function ($rawItemsHtml, $depth) { if ($depth === 0) { return $rawItemsHtml; } elseif ($depth === 1) { return "<ul class=\"dropdown-menu\">{$rawItemsHtml}</ul>"; } else { return "<ul>{$rawItemsHtml}</ul>"; } }); return $menu->getHtml(); }
/** * Main execution point * * @param null|string $code Confirmation code passed to the page * @throws PermissionsError * @throws ReadOnlyError * @throws UserNotLoggedIn */ function execute($code) { // Ignore things like master queries/connections on GET requests. // It's very convenient to just allow formless link usage. $trxProfiler = Profiler::instance()->getTransactionProfiler(); $this->setHeaders(); $this->checkReadOnly(); $this->checkPermissions(); // This could also let someone check the current email address, so // require both permissions. if (!$this->getUser()->isAllowed('viewmyprivateinfo')) { throw new PermissionsError('viewmyprivateinfo'); } if ($code === null || $code === '') { $this->requireLogin('confirmemail_needlogin'); if (Sanitizer::validateEmail($this->getUser()->getEmail())) { $this->showRequestForm(); } else { $this->getOutput()->addWikiMsg('confirmemail_noemail'); } } else { $old = $trxProfiler->setSilenced(true); $this->attemptConfirm($code); $trxProfiler->setSilenced($old); } }
/** * Strip markup to show plaintext * @param string $text * @return string * @access private */ function _stripMarkup($text) { global $wgContLang; $text = substr($text, 0, 4096); // don't bother with long text... $text = str_replace("'''", "", $text); $text = str_replace("''", "", $text); $text = preg_replace('#__[a-z0-9_]+__#i', '', $text); // magic words $cleanChar = "[^|\\[\\]]"; $subLink = "\\[\\[{$cleanChar}*(?:\\|{$cleanChar}*)*\\]\\]"; $pipeContents = "(?:{$cleanChar}|{$subLink})*"; $text = preg_replace_callback("#\n\t\t\t\\[\\[\n\t\t\t\t({$cleanChar}*)\n\t\t\t\t(?:\\|({$pipeContents}))?\n\t\t\t\t(?:\\|{$pipeContents})*\n\t\t\t\\]\\]\n\t\t\t#six", array($this, '_stripLink'), $text); $protocols = wfUrlProtocols(); $text = preg_replace('#\\[(?:$protocols).*? (.*?)\\]#s', '$1', $text); // URL links $text = preg_replace('#</?[a-z0-9]+.*?>#s', '', $text); // HTML-style tags $text = preg_replace('#\\{\\|.*?\\|\\}#s', '', $text); // tables $text = preg_replace('#^:.*$#m', '', $text); // indented lines near start are usually disambigs or notices $text = Sanitizer::decodeCharReferences($text); return trim($text); }
/** * Creates HTML for the given tags * * @param string $tags Comma-separated list of tags * @param string $page A label for the type of action which is being displayed, * for example: 'history', 'contributions' or 'newpages' * @return array Array with two items: (html, classes) * - html: String: HTML for displaying the tags (empty string when param $tags is empty) * - classes: Array of strings: CSS classes used in the generated html, one class for each tag */ public static function formatSummaryRow($tags, $page) { global $wgLang; if (!$tags) { return array('', array()); } $classes = array(); $tags = explode(',', $tags); $displayTags = array(); foreach ($tags as $tag) { if (!$tag) { continue; } $description = self::tagDescription($tag); if ($description === false) { continue; } $displayTags[] = Xml::tags('span', array('class' => 'mw-tag-marker ' . Sanitizer::escapeClass("mw-tag-marker-{$tag}")), $description); $classes[] = Sanitizer::escapeClass("mw-tag-{$tag}"); } if (!$displayTags) { return array('', array()); } $markers = wfMessage('tag-list-wrapper')->numParams(count($displayTags))->rawParams($wgLang->commaList($displayTags))->parse(); $markers = Xml::tags('span', array('class' => 'mw-tag-markers'), $markers); return array($markers, $classes); }
protected function parseWikitext($title, $newRevId) { $apiParams = array('action' => 'parse', 'page' => $title->getPrefixedDBkey(), 'oldid' => $newRevId, 'prop' => 'text|revid|categorieshtml|displaytitle|modules|jsconfigvars'); $api = new ApiMain(new DerivativeRequest($this->getRequest(), $apiParams, false), true); $api->execute(); if (defined('ApiResult::META_CONTENT')) { $result = $api->getResult()->getResultData(null, array('BC' => array(), 'Types' => array(), 'Strip' => 'all')); } else { $result = $api->getResultData(); } $content = isset($result['parse']['text']['*']) ? $result['parse']['text']['*'] : false; $categorieshtml = isset($result['parse']['categorieshtml']['*']) ? $result['parse']['categorieshtml']['*'] : false; $links = isset($result['parse']['links']) ? $result['parse']['links'] : array(); $revision = Revision::newFromId($result['parse']['revid']); $timestamp = $revision ? $revision->getTimestamp() : wfTimestampNow(); $displaytitle = isset($result['parse']['displaytitle']) ? $result['parse']['displaytitle'] : false; $modules = isset($result['parse']['modules']) ? $result['parse']['modules'] : array(); $jsconfigvars = isset($result['parse']['jsconfigvars']) ? $result['parse']['jsconfigvars'] : array(); if ($content === false || strlen($content) && $revision === null) { return false; } if ($displaytitle !== false) { // Escape entities as in OutputPage::setPageTitle() $displaytitle = Sanitizer::normalizeCharReferences(Sanitizer::removeHTMLtags($displaytitle)); } return array('content' => $content, 'categorieshtml' => $categorieshtml, 'basetimestamp' => $timestamp, 'starttimestamp' => wfTimestampNow(), 'displayTitleHtml' => $displaytitle, 'modules' => $modules, 'jsconfigvars' => $jsconfigvars); }
function wfCSSRender(&$parser, $css) { global $wgOut, $wgRequest; $parser->mOutput->mCacheTime = -1; $url = false; if (preg_match('|\\{|', $css)) { # Inline CSS $css = htmlspecialchars(trim(Sanitizer::checkCss($css))); $parser->mOutput->addHeadItem(<<<EOT <style type="text/css"> /*<![CDATA[*/ {$css} /*]]>*/ </style> EOT ); } elseif ($css[0] == '/') { # File $url = $css; } else { # Article? $title = Title::newFromText($css); if (is_object($title)) { $url = $title->getLocalURL('action=raw&ctype=text/css'); $url = str_replace("&", "&", $url); } } if ($url) { $wgOut->addScript("<link rel=\"stylesheet\" type=\"text/css\" href=\"{$url}\" />"); } return ''; }
function PoemExtension($in, $param = array(), $parser = null) { /* using newlines in the text will cause the parser to add <p> tags, * which may not be desired in some cases */ $nl = isset($param['compact']) ? '' : "\n"; if (method_exists($parser, 'recursiveTagParse')) { //new methods in 1.8 allow nesting <nowiki> in <poem>. $tag = $parser->insertStripItem("<br />", $parser->mStripState); $text = preg_replace(array("/^\n/", "/\n\$/D", "/\n/", "/^( +)/me"), array("", "", "{$tag}\n", "str_replace(' ',' ','\\1')"), $in); $text = $parser->recursiveTagParse($text); } else { $text = preg_replace(array("/^\n/", "/\n\$/D", "/\n/", "/^( +)/me"), array("", "", "<br />\n", "str_replace(' ',' ','\\1')"), $in); $ret = $parser->parse($text, $parser->getTitle(), $parser->getOptions(), true, false); $text = $ret->getText(); } global $wgVersion; if (version_compare($wgVersion, "1.7alpha") >= 0) { // Pass HTML attributes through to the output. $attribs = Sanitizer::validateTagAttributes($param, 'div'); } else { // Can't guarantee safety on 1.6 or older. $attribs = array(); } // Wrap output in a <div> with "poem" class. if (isset($attribs['class'])) { $attribs['class'] = 'poem ' . $attribs['class']; } else { $attribs['class'] = 'poem'; } return Xml::openElement('div', $attribs) . $nl . trim($text) . "{$nl}</div>"; }
/** * Creates HTML for the given tags * * @param string $tags Comma-separated list of tags * @param string $page A label for the type of action which is being displayed, * for example: 'history', 'contributions' or 'newpages' * @param IContextSource|null $context * @note Even though it takes null as a valid argument, an IContextSource is preferred * in a new code, as the null value is subject to change in the future * @return array Array with two items: (html, classes) * - html: String: HTML for displaying the tags (empty string when param $tags is empty) * - classes: Array of strings: CSS classes used in the generated html, one class for each tag */ public static function formatSummaryRow($tags, $page, IContextSource $context = null) { if (!$tags) { return array('', array()); } if (!$context) { $context = RequestContext::getMain(); } $classes = array(); $tags = explode(',', $tags); $displayTags = array(); foreach ($tags as $tag) { if (!$tag) { continue; } $description = self::tagDescription($tag); if ($description === false) { continue; } $displayTags[] = Xml::tags('span', array('class' => 'mw-tag-marker ' . Sanitizer::escapeClass("mw-tag-marker-{$tag}")), $description); $classes[] = Sanitizer::escapeClass("mw-tag-{$tag}"); } if (!$displayTags) { return array('', array()); } $markers = $context->msg('tag-list-wrapper')->numParams(count($displayTags))->rawParams($context->getLanguage()->commaList($displayTags))->parse(); $markers = Xml::tags('span', array('class' => 'mw-tag-markers'), $markers); return array($markers, $classes); }
public static function receiverIsValid($receiver) { // Returns true if the parameter is a valid e-mail address, false if not $receiverIsValid = true; // There may be multiple e-mail addresses, divided by commas - which is valid // for us, but not for the validation functions we use below. So get the single // address into an array first, validate them one by one, and only if all are ok, // return true. $receiverArray = explode(',', str_replace(', ', ',', $receiver)); // To make sure some joker doesn't copy in a large number of e-mail addresses // and spams them all, lets set a (admittedly arbitrary) limit of 10. if (count($receiverArray) > 10) { return false; } if (method_exists('Sanitizer', 'validateEmail')) { // User::isValidEmailAddr() has been moved to Sanitizer::validateEmail as of // MediaWiki version 1.18 (I think). foreach ($receiverArray as $singleEmailAddress) { if (!Sanitizer::validateEmail($singleEmailAddress)) { $receiverIsValid = false; } } } else { foreach ($receiverArray as $singleEmailAddress) { if (!User::isValidEmailAddr($singleEmailAddress)) { $receiverIsValid = false; } } } return $receiverIsValid; }
/** * Show the special page * @param string|null $par */ public function execute($par) { $this->setHeaders(); $this->outputHeader(); $out = $this->getOutput(); $out->addModuleStyles('mediawiki.special'); $out->addHTML(\Html::openElement('table', array('class' => 'wikitable mw-listgrouprights-table')) . '<tr>' . \Html::element('th', null, $this->msg('listgrants-grant')->text()) . \Html::element('th', null, $this->msg('listgrants-rights')->text()) . '</tr>'); foreach ($this->getConfig()->get('GrantPermissions') as $grant => $rights) { $descs = array(); $rights = array_filter($rights); // remove ones with 'false' foreach ($rights as $permission => $granted) { $descs[] = $this->msg('listgrouprights-right-display', \User::getRightDescription($permission), '<span class="mw-listgrants-right-name">' . $permission . '</span>')->parse(); } if (!count($descs)) { $grantCellHtml = ''; } else { sort($descs); $grantCellHtml = '<ul><li>' . implode("</li>\n<li>", $descs) . '</li></ul>'; } $id = \Sanitizer::escapeId($grant); $out->addHTML(\Html::rawElement('tr', array('id' => $id), "<td>" . $this->msg("grant-{$grant}")->escaped() . "</td>" . "<td>" . $grantCellHtml . '</td>')); } $out->addHTML(\Html::closeElement('table')); }
/** * Format a line using the old system (aka without any javascript). * * @param RecentChange $rc Passed by reference * @param bool $watched (default false) * @param int $linenumber (default null) * * @return string|bool */ public function recentChangesLine(&$rc, $watched = false, $linenumber = null) { $classes = array(); // use mw-line-even/mw-line-odd class only if linenumber is given (feature from bug 14468) if ($linenumber) { if ($linenumber & 1) { $classes[] = 'mw-line-odd'; } else { $classes[] = 'mw-line-even'; } } // Indicate watched status on the line to allow for more // comprehensive styling. $classes[] = $watched && $rc->mAttribs['rc_timestamp'] >= $watched ? 'mw-changeslist-line-watched' : 'mw-changeslist-line-not-watched'; $html = $this->formatChangeLine($rc, $classes, $watched); if ($this->watchlist) { $classes[] = Sanitizer::escapeClass('watchlist-' . $rc->mAttribs['rc_namespace'] . '-' . $rc->mAttribs['rc_title']); } if (!Hooks::run('OldChangesListRecentChangesLine', array(&$this, &$html, $rc, &$classes))) { return false; } $dateheader = ''; // $html now contains only <li>...</li>, for hooks' convenience. $this->insertDateHeader($dateheader, $rc->mAttribs['rc_timestamp']); return "{$dateheader}<li class=\"" . implode(' ', $classes) . "\">" . $html . "</li>\n"; }
function testDecodeTagAttributes() { $this->assertEquals(Sanitizer::decodeTagAttributes('foo=bar'), array('foo' => 'bar'), 'Unquoted attribute'); $this->assertEquals(Sanitizer::decodeTagAttributes(' foo = bar '), array('foo' => 'bar'), 'Spaced attribute'); $this->assertEquals(Sanitizer::decodeTagAttributes('foo="bar"'), array('foo' => 'bar'), 'Double-quoted attribute'); $this->assertEquals(Sanitizer::decodeTagAttributes('foo=\'bar\''), array('foo' => 'bar'), 'Single-quoted attribute'); $this->assertEquals(Sanitizer::decodeTagAttributes('foo=\'bar\' baz="foo"'), array('foo' => 'bar', 'baz' => 'foo'), 'Several attributes'); $this->assertEquals(Sanitizer::decodeTagAttributes('foo=\'bar\' baz="foo"'), array('foo' => 'bar', 'baz' => 'foo'), 'Several attributes'); $this->assertEquals(Sanitizer::decodeTagAttributes('foo=\'bar\' baz="foo"'), array('foo' => 'bar', 'baz' => 'foo'), 'Several attributes'); $this->assertEquals(Sanitizer::decodeTagAttributes(':foo=\'bar\''), array(':foo' => 'bar'), 'Leading :'); $this->assertEquals(Sanitizer::decodeTagAttributes('_foo=\'bar\''), array('_foo' => 'bar'), 'Leading _'); $this->assertEquals(Sanitizer::decodeTagAttributes('Foo=\'bar\''), array('foo' => 'bar'), 'Leading capital'); $this->assertEquals(Sanitizer::decodeTagAttributes('FOO=BAR'), array('foo' => 'BAR'), 'Attribute keys are normalized to lowercase'); # Invalid beginning $this->assertEquals(Sanitizer::decodeTagAttributes('-foo=bar'), array(), 'Leading - is forbidden'); $this->assertEquals(Sanitizer::decodeTagAttributes('.foo=bar'), array(), 'Leading . is forbidden'); $this->assertEquals(Sanitizer::decodeTagAttributes('foo-bar=bar'), array('foo-bar' => 'bar'), 'A - is allowed inside the attribute'); $this->assertEquals(Sanitizer::decodeTagAttributes('foo-=bar'), array('foo-' => 'bar'), 'A - is allowed inside the attribute'); $this->assertEquals(Sanitizer::decodeTagAttributes('foo.bar=baz'), array('foo.bar' => 'baz'), 'A . is allowed inside the attribute'); $this->assertEquals(Sanitizer::decodeTagAttributes('foo.=baz'), array('foo.' => 'baz'), 'A . is allowed as last character'); $this->assertEquals(Sanitizer::decodeTagAttributes('foo6=baz'), array('foo6' => 'baz'), 'Numbers are allowed'); # This bit is more relaxed than XML rules, but some extensions use it, like ProofreadPage (see bug 27539) $this->assertEquals(Sanitizer::decodeTagAttributes('1foo=baz'), array('1foo' => 'baz'), 'Leading numbers are allowed'); $this->assertEquals(Sanitizer::decodeTagAttributes('foo$=baz'), array(), 'Symbols are not allowed'); $this->assertEquals(Sanitizer::decodeTagAttributes('foo@=baz'), array(), 'Symbols are not allowed'); $this->assertEquals(Sanitizer::decodeTagAttributes('foo~=baz'), array(), 'Symbols are not allowed'); $this->assertEquals(Sanitizer::decodeTagAttributes('foo=1[#^`*%w/('), array('foo' => '1[#^`*%w/('), 'All kind of characters are allowed as values'); $this->assertEquals(Sanitizer::decodeTagAttributes('foo="1[#^`*%\'w/("'), array('foo' => '1[#^`*%\'w/('), 'Double quotes are allowed if quoted by single quotes'); $this->assertEquals(Sanitizer::decodeTagAttributes('foo=\'1[#^`*%"w/(\''), array('foo' => '1[#^`*%"w/('), 'Single quotes are allowed if quoted by double quotes'); $this->assertEquals(Sanitizer::decodeTagAttributes('foo=&"'), array('foo' => '&"'), 'Special chars can be provided as entities'); $this->assertEquals(Sanitizer::decodeTagAttributes('foo=&foobar;'), array('foo' => '&foobar;'), 'Entity-like items are accepted'); }
/** * Main execution point * * @param null|string $code Confirmation code passed to the page */ function execute( $code ) { $this->setHeaders(); $this->checkReadOnly(); $this->checkPermissions(); // This could also let someone check the current email address, so // require both permissions. if ( !$this->getUser()->isAllowed( 'viewmyprivateinfo' ) ) { throw new PermissionsError( 'viewmyprivateinfo' ); } if ( $code === null || $code === '' ) { if ( $this->getUser()->isLoggedIn() ) { if ( Sanitizer::validateEmail( $this->getUser()->getEmail() ) ) { $this->showRequestForm(); } else { $this->getOutput()->addWikiMsg( 'confirmemail_noemail' ); } } else { $llink = Linker::linkKnown( SpecialPage::getTitleFor( 'Userlogin' ), $this->msg( 'loginreqlink' )->escaped(), array(), array( 'returnto' => $this->getTitle()->getPrefixedText() ) ); $this->getOutput()->addHTML( $this->msg( 'confirmemail_needlogin' )->rawParams( $llink )->parse() ); } } else { $this->attemptConfirm( $code ); } }
public function execute() { $this->commit = $this->hasOption('commit'); $dbr = $this->getDB(DB_SLAVE); $dbw = $this->getDB(DB_MASTER); $lastId = 0; do { $rows = $dbr->select('user', array('user_id', 'user_email'), array('user_id > ' . $dbr->addQuotes($lastId), 'user_email != ""', 'user_email_authenticated IS NULL'), __METHOD__, array('LIMIT' => $this->mBatchSize)); $count = $rows->numRows(); $badIds = array(); foreach ($rows as $row) { if (!Sanitizer::validateEmail(trim($row->user_email))) { $this->output("Found bad email: {$row->user_email} for user #{$row->user_id}\n"); $badIds[] = $row->user_id; } if ($row->user_id > $lastId) { $lastId = $row->user_id; } } if ($badIds) { $badCount = count($badIds); if ($this->commit) { $this->output("Removing {$badCount} emails from the database.\n"); $dbw->update('user', array('user_email' => ''), array('user_id' => $badIds), __METHOD__); foreach ($badIds as $badId) { User::newFromId($badId)->invalidateCache(); } wfWaitForSlaves(); } else { $this->output("Would have removed {$badCount} emails from the database.\n"); } } } while ($count !== 0); $this->output("Done.\n"); }
protected function checkContactLink($name, $url, &$countOk) { global $wgVersion; $ok = false; if (Sanitizer::validateEmail($url)) { $ok = true; // assume OK } else { $bits = wfParseUrl($url); if ($bits && isset($bits['scheme'])) { if ($bits['scheme'] == 'mailto') { $ok = true; // assume OK } elseif (in_array($bits['scheme'], array('http', 'https'))) { $req = MWHttpRequest::factory($url, array('method' => 'GET', 'timeout' => 8, 'sslVerifyHost' => false, 'sslVerifyCert' => false)); $req->setUserAgent("MediaWiki {$wgVersion}, CheckCongressLinks Checker"); $ok = $req->execute()->isOK(); } } } if ($ok) { ++$countOk; } else { $this->output("Broken: [{$name}] [{$url}]\n"); } }
/** * Ajax function to create checkboxes for a new group in $wgGroupPermissions * * @param String $group new group name * @return either <err#> if group already exist or html fragment */ function efConfigureAjax($group) { global $wgUser, $wgGroupPermissions; if (!$wgUser->isAllowed('configure-all')) { return '<err#>'; } if (isset($wgGroupPermissions[$group])) { $html = '<err#>'; } else { if (is_callable(array('User', 'getAllRights'))) { // 1.13 + $all = User::getAllRights(); } else { $all = array(); foreach ($wgGroupPermissions as $rights) { $all = array_merge($all, array_keys($rights)); } $all = array_unique($all); } $row = '<div style="-moz-column-count:2"><ul>'; foreach ($all as $right) { $id = Sanitizer::escapeId('wpwgGroupPermissions-' . $group . '-' . $right); $desc = is_callable(array('User', 'getRightDescription')) ? User::getRightDescription($right) : $right; $row .= '<li>' . Xml::checkLabel($desc, $id, $id) . "</li>\n"; } $row .= '</ul></div>'; $groupName = User::getGroupName($group); // Firefox seems to not like that :( $html = str_replace(' ', ' ', $row); } return $html; }
/** * Core parser tag hook function for 'pre'. * Text is treated roughly as 'nowiki' wrapped in an HTML 'pre' tag; * valid HTML attributes are passed on. * * @param string $text * @param array $attribs * @param Parser $parser * @return string HTML */ public static function pre($text, $attribs, $parser) { // Backwards-compatibility hack $content = StringUtils::delimiterReplace('<nowiki>', '</nowiki>', '$1', $text, 'i'); $attribs = Sanitizer::validateTagAttributes($attribs, 'pre'); return Xml::openElement('pre', $attribs) . Xml::escapeTagsOnly($content) . '</pre>'; }
protected function formatStory($story, $mode) { $item = array('GUID' => $story->getGUID(), 'link' => $story->getLink(), 'title' => Sanitizer::htmlStripTags2UTF8($story->getTitle()), 'description' => Sanitizer::htmlStripTags2UTF8($story->getDescription()), 'pubDate' => $story->getPubTimestamp()); if ($story->getContent()) { if ($mode == 'full') { $item['body'] = $story->getContent(); } $item['hasBody'] = TRUE; } else { $item['hasBody'] = FALSE; } $thumbnail = $story->getThumbnail(); if ($thumbnail && $thumbnail->getURL()) { $key = $this->requestedVersion < 2 ? 'image' : 'thumbnail'; $item[$key] = array('src' => $thumbnail->getURL(), 'width' => $thumbnail->getWidth(), 'height' => $thumbnail->getHeight()); } if ($this->requestedVersion >= 2) { $image = $story->getImage(); if ($image && $image->getURL()) { $item['image'] = array('src' => $image->getURL(), 'width' => $image->getWidth(), 'height' => $image->getHeight()); } } $author = $story->getAuthor(); $item['author'] = $author ? $author : ""; return $item; }
/** * Show the special page * * @param $subpage Mixed: parameter passed to the page or null */ public function execute($subpage) { global $wgRequest, $wgUser, $wgOut; $this->setHeaders(); $hash_key = $wgRequest->getText('key', null); $email = $token = $timestamp = null; if (!empty($hash_key)) { #$hask_key = urldecode ( $hash_key ); $data = Wikia::verifyUserSecretKey($hash_key, 'sha256'); error_log("data = " . print_r($data, true)); if (!empty($data)) { $username = isset($data['user']) ? $data['user'] : null; $token = isset($data['token']) ? $data['token'] : null; $timestamp = isset($data['signature1']) ? $data['signature1'] : null; $oUser = User::newFromName($username); $email = $oUser->getEmail(); } } else { $email = $wgRequest->getText('email', null); $token = $wgRequest->getText('token', null); $timestamp = $wgRequest->getText('timestamp', null); } if ($email == null || $token == null || $timestamp == null) { #give up now, abandon all hope. $wgOut->addWikiMsg('unsubscribe-badaccess'); return; } #validate timestamp isnt spoiled (you only have 7 days) $timeCutoff = strtotime("7 days ago"); if ($timestamp <= $timeCutoff) { $wgOut->addWikiMsg('unsubscribe-badtime'); // $wgOut->addHTML("timestamp={$timestamp}\n"); #DEVL (remove before release) // $wgOut->addHTML("timeCutoff={$timeCutoff}\n"); #DEVL (remove before release) return; } #generate what the token SHOULD be $shouldToken = wfGenerateUnsubToken($email, $timestamp); if ($token != $shouldToken) { $wgOut->addWikiMsg('unsubscribe-badtoken'); // $wgOut->addHTML("shouldtoken={$shouldToken}\n"); #DEVL (remove before release) return; } #does the non-blank email they gave us look like an email? if (Sanitizer::validateEmail($email) == false) { #email wasnt blank, but didnt look like any email $wgOut->addWikiMsg('unsubscribe-bademail'); // $wgOut->addHTML("email={$email}\n"); #DEVL (remove before release) return; } #at this point, the 3 params check out. #is this their 2nd pass at this? $confirmed = $wgRequest->getBool('confirm', null); if ($wgRequest->wasPosted() && $confirmed) { #this is the 2nd round, they pushed the button, so do it $this->procUnsub($email); } else { #this is 1st pass, give them a button to push $this->showInfo($email, $token, $timestamp); } }
private function checkEmail($addr, $expected = true, $msg = '') { if ($msg == '') { $msg = "Testing {$addr}"; } $this->assertEquals($expected, Sanitizer::validateEmail($addr), $msg); }
/** * Handles group notification. * * @since 0.1 * * @param SWLGroup $group * @param array $userIDs * @param SMWChangeSet $changes * * @return true */ public static function onGroupNotify( SWLGroup $group, array $userIDs, SWLChangeSet $changes ) { global $egSWLMailPerChange, $egSWLMaxMails; foreach ( $userIDs as $userID ) { $user = User::newFromId( $userID ); if ( $user->getOption( 'swl_email', false ) ) { if ( !method_exists( 'Sanitizer', 'validateEmail' ) || Sanitizer::validateEmail( $user->getEmail() ) ) { $lastNotify = $user->getOption( 'swl_last_notify' ); $lastWatch = $user->getOption( 'swl_last_watch' ); if ( is_null( $lastNotify ) || is_null( $lastWatch ) || $lastNotify < $lastWatch ) { $mailCount = $user->getOption( 'swl_mail_count', 0 ); if ( $egSWLMailPerChange || $mailCount < $egSWLMaxMails ) { SWLEmailer::notifyUser( $group, $user, $changes, $egSWLMailPerChange ); $user->setOption( 'swl_last_notify', wfTimestampNow() ); $user->setOption( 'swl_mail_count', $mailCount + 1 ); $user->saveSettings(); } } } } } return true; }
/** * Show a global usage section on the image page * * @param object $imagePage The ImagePage * @param string $html HTML to add to the image page as global usage section * @return bool */ public static function onImagePageAfterImageLinks($imagePage, &$html) { if (!self::hasResults($imagePage)) { return true; } $title = $imagePage->getFile()->getTitle(); $targetName = $title->getText(); $query = self::getImagePageQuery($title); $guHtml = ''; foreach ($query->getSingleImageResult() as $wiki => $result) { $wikiName = WikiMap::getWikiName($wiki); $escWikiName = Sanitizer::escapeClass($wikiName); /* Wikia change begin */ wfRunHooks('GlobalUsageImagePageWikiLink', array(&$wikiName)); /* Wikia change end */ $guHtml .= "<li class='mw-gu-onwiki-{$escWikiName}'>" . wfMsgExt('globalusage-on-wiki', 'parseinline', $targetName, $wikiName) . "\n<ul>"; foreach ($result as $item) { $guHtml .= "\t<li>" . SpecialGlobalUsage::formatItem($item) . "</li>\n"; } $guHtml .= "</ul></li>\n"; } if ($guHtml) { $html .= '<h2 id="globalusage">' . wfMsgHtml('globalusage') . "</h2>\n" . '<div id="mw-imagepage-section-globalusage">' . wfMsgExt('globalusage-of-file', 'parse') . "<ul>\n" . $guHtml . "</ul>\n"; if ($query->hasMore()) { $html .= wfMsgExt('globalusage-more', 'parse', $targetName); } $html .= '</div>'; } return true; }
protected function doCreate() { $params = $this->extractRequestParams(); // Do validations foreach (explode('|', 'username|password|email') as $field) { if (!isset($params[$field])) { $this->dieUsage("Missing parameter {$field}", 'missingparam'); } } $username = $params['username']; if (User::getCanonicalName($username, 'creatable') === false) { $this->dieUsage("User name is not acceptable", 'invalidusername'); } $user = User::newFromName($username); if ($user->getID() !== 0) { $this->dieUsage("User name is in use", 'nonfreeusername'); } $password = $params['password']; if (!$user->isValidPassword($password)) { $this->dieUsage("Password is not acceptable", 'invalidpassword'); } $email = $params['email']; if (!Sanitizer::validateEmail($email)) { $this->dieUsage("Email is not acceptable", 'invalidemail'); } $user = TranslateSandbox::addUser($username, $email, $password); $output = array('user' => array('name' => $user->getName(), 'id' => $user->getId())); $user->setOption('language', $this->getContext()->getLanguage()->getCode()); $user->saveSettings(); $this->getResult()->addValue(null, $this->getModuleName(), $output); }
protected function arrayFromVideo($video, $section) { $videoArray = array("id" => $video->getID(), "type" => $video->getType(), "title" => $video->getTitle(), "description" => Sanitizer::htmlStripTags2UTF8($video->getDescription()), "author" => $video->getAuthor(), "published" => array('date' => $video->getPublished()->format('Y-m-d H:i:s'), 'timezone_type' => 1, 'timezone' => $video->getPublished()->format('P')), "date" => $video->getPublished()->format('M n, Y'), "url" => $video->getURL(), "image" => $video->getImage(), "width" => $video->getWidth(), "height" => $video->getHeight(), "aspect" => $video->getAspectRatio(), "duration" => $video->getDuration(), "tags" => $video->getTags(), "mobileURL" => $video->getMobileURL(), "streamingURL" => $video->getStreamingURL(), "stillFrameImage" => $video->getStillFrameImage(), "playerURL" => FULL_URL_BASE . $this->configModule . '/player?' . http_build_query(array('section' => $section, 'videoid' => $video->getID()))); if ($this->requestedVersion >= 2) { $videoArray['published']['timestamp'] = $video->getPublished()->format('U'); $videoArray['playerURL'] = $video->getPlayerURL(); } return $videoArray; }
public static function convertDataToAttributes($data) { // get ID of current CK instance $instance = RTE::getInstanceId(); // properly encode JSON $encoded = RTEReverseParser::encodeRTEData($data); $encoded = Sanitizer::encodeAttribute($encoded); return " data-rte-meta=\"{$encoded}\" data-rte-instance=\"{$instance}\" "; }