static function AJAXPollRender($input, $args = array(), Parser $parser)
 {
     global $wgUser, $wgOut, $wgTitle, $wgScriptPath, $wgUseAjax;
     $parser->disableCache();
     $parser->addTrackingCategory('ajaxpoll-tracking-category');
     if ($wgUser->getName() == '') {
         $userName = wfGetIP();
     } else {
         $userName = $wgUser->getName();
     }
     // ID of the poll
     $id = strtoupper(md5($input));
     $par = new Parser();
     $input = $par->parse($input, $wgTitle, $wgOut->parserOptions());
     $input = trim(strip_tags($input->getText()));
     $lines = explode("\n", trim($input));
     // compatibility for non-ajax requests - just in case
     if (!$wgUseAjax) {
         $responseId = "ajaxpoll-post-id";
         $responseAnswer = "ajaxpoll-post-answer-{$id}";
         $responseToken = "ajaxPollToken";
         if (isset($_POST[$responseId]) && isset($_POST[$responseAnswer]) && $_POST[$responseId] == $id && isset($_POST[$responseToken])) {
             self::submitVote($id, intval($_POST[$responseAnswer]), $_POST[$responseToken]);
         }
     }
     $dbw = wfGetDB(DB_MASTER);
     $dbw->begin(__METHOD__);
     /**
      * Register poll in the database
      */
     $row = $dbw->selectRow(array('ajaxpoll_info'), array('COUNT(poll_id) AS count'), array('poll_id' => $id), __METHOD__);
     $showResultsBeforeVoting = null;
     if (array_key_exists('show-results-before-voting', $args)) {
         if (strval($args['show-results-before-voting']) !== '0') {
             $showResultsBeforeVoting = '1';
         } else {
             $showResultsBeforeVoting = '0';
         }
     }
     if (empty($row->count)) {
         $dbw->insert('ajaxpoll_info', array('poll_id' => $id, 'poll_show_results_before_voting' => $showResultsBeforeVoting, 'poll_txt' => $input, 'poll_date' => wfTimestampNow()), __METHOD__);
     } else {
         $dbw->update('ajaxpoll_info', array('poll_show_results_before_voting' => $showResultsBeforeVoting), array('poll_id' => $id), __METHOD__);
     }
     $dbw->commit(__METHOD__);
     switch ($lines[0]) {
         case 'STATS':
             $ret = self::buildStats($id, $userName);
             break;
         default:
             $ret = Html::rawElement('div', array('id' => 'ajaxpoll-container-' . $id), self::buildHTML($id, $userName, $lines));
             break;
     }
     return $ret;
 }
 private function applyTagArgs(Coord $coord)
 {
     global $wgContLang, $wgTypeToDim, $wgDefaultDim, $wgGeoDataWarningLevel, $wgGlobes;
     $args = $this->named;
     $coord->primary = isset($args['primary']);
     $coord->globe = isset($args['globe']) ? $wgContLang->lc($args['globe']) : $wgDefaultGlobe;
     if (!isset($wgGlobes[$coord->globe])) {
         if ($wgGeoDataWarningLevel['unknown globe'] == 'fail') {
             return Status::newFatal('geodata-bad-globe', $coord->globe);
         } elseif ($wgGeoDataWarningLevel['unknown globe'] == 'warn') {
             $this->parser->addTrackingCategory('geodata-unknown-globe-category');
         }
     }
     $coord->dim = $wgDefaultDim;
     if (isset($args['type'])) {
         $coord->type = preg_replace('/\\(.*?\\).*$/', '', $args['type']);
         if (isset($wgTypeToDim[$coord->type])) {
             $coord->dim = $wgTypeToDim[$coord->type];
         } else {
             if ($wgGeoDataWarningLevel['unknown type'] == 'fail') {
                 return Status::newFatal('geodata-bad-type', $coord->type);
             } elseif ($wgGeoDataWarningLevel['unknown type'] == 'warn') {
                 $this->parser->addTrackingCategory('geodata-unknown-type-category');
             }
         }
     }
     if (isset($args['scale'])) {
         $coord->dim = $args['scale'] / 10;
     }
     if (isset($args['dim'])) {
         $dim = $this->parseDim($args['dim']);
         if ($dim !== false) {
             $coord->dim = $dim;
         }
     }
     $coord->name = isset($args['name']) ? $args['name'] : null;
     if (isset($args['region'])) {
         $code = strtoupper($args['region']);
         if (preg_match('/^([A-Z]{2})(?:-([A-Z0-9]{1,3}))?$/', $code, $m)) {
             $coord->country = $m[1];
             $coord->region = isset($m[2]) ? $m[2] : null;
         } else {
             if ($wgGeoDataWarningLevel['invalid region'] == 'fail') {
                 return Status::newFatal('geodata-bad-region', $args['region']);
             } elseif ($wgGeoDataWarningLevel['invalid region'] == 'warn') {
                 $this->parser->addTrackingCategory('geodata-unknown-region-category');
             }
         }
     }
     return Status::newGood();
 }
 /**
  * #coordinates parser function callback
  * 
  * @param Parser $parser
  * @param PPFrame $frame
  * @param Array $args
  * @return Mixed
  */
 public function coordinates($parser, $frame, $args)
 {
     if ($parser != $this->parser) {
         throw new MWException(__METHOD__ . '() called by wrong parser');
     }
     $this->output = $parser->getOutput();
     if (!isset($this->output->geoData)) {
         $this->output->geoData = new CoordinatesOutput();
     }
     $this->unnamed = array();
     $this->named = array();
     $first = trim($frame->expand(array_shift($args)));
     $this->addArg($first);
     foreach ($args as $arg) {
         $bits = $arg->splitArg();
         $value = trim($frame->expand($bits['value']));
         if ($bits['index'] === '') {
             $this->named[trim($frame->expand($bits['name']))] = $value;
         } else {
             $this->addArg($value);
         }
     }
     $this->parseTagArgs();
     $status = GeoData::parseCoordinates($this->unnamed, $this->named['globe']);
     if ($status->isGood()) {
         $coord = $status->value;
         $status = $this->applyTagArgs($coord);
         if ($status->isGood()) {
             $status = $this->applyCoord($coord);
             if ($status->isGood()) {
                 return '';
             }
         }
     }
     $parser->addTrackingCategory('geodata-broken-tags-category');
     $errorText = $this->errorText($status);
     if ($errorText == '<>') {
         // Error that doesn't require a message,
         // can't think of a better way to pass this condition
         return '';
     }
     return array("<span class=\"error\">{$errorText}</span>", 'noparse' => false);
 }
Exemple #4
0
 /**
  * Create a new child frame
  * $args is optionally a multi-root PPNode or array containing the template arguments
  *
  * @param bool|array $args
  * @param Title|bool $title
  * @param int $indexOffset
  * @return PPTemplateFrame_DOM
  */
 public function newChild($args = false, $title = false, $indexOffset = 0)
 {
     $namedArgs = array();
     $numberedArgs = array();
     if ($title === false) {
         $title = $this->title;
     }
     if ($args !== false) {
         $xpath = false;
         if ($args instanceof PPNode) {
             $args = $args->node;
         }
         foreach ($args as $arg) {
             if ($arg instanceof PPNode) {
                 $arg = $arg->node;
             }
             if (!$xpath || $xpath->document !== $arg->ownerDocument) {
                 $xpath = new DOMXPath($arg->ownerDocument);
             }
             $nameNodes = $xpath->query('name', $arg);
             $value = $xpath->query('value', $arg);
             if ($nameNodes->item(0)->hasAttributes()) {
                 // Numbered parameter
                 $index = $nameNodes->item(0)->attributes->getNamedItem('index')->textContent;
                 $index = $index - $indexOffset;
                 if (isset($namedArgs[$index]) || isset($numberedArgs[$index])) {
                     $this->parser->getOutput()->addWarning(wfMessage('duplicate-args-warning', wfEscapeWikiText($this->title), wfEscapeWikiText($title), wfEscapeWikiText($index))->text());
                     $this->parser->addTrackingCategory('duplicate-args-category');
                 }
                 $numberedArgs[$index] = $value->item(0);
                 unset($namedArgs[$index]);
             } else {
                 // Named parameter
                 $name = trim($this->expand($nameNodes->item(0), PPFrame::STRIP_COMMENTS));
                 if (isset($namedArgs[$name]) || isset($numberedArgs[$name])) {
                     $this->parser->getOutput()->addWarning(wfMessage('duplicate-args-warning', wfEscapeWikiText($this->title), wfEscapeWikiText($title), wfEscapeWikiText($name))->text());
                     $this->parser->addTrackingCategory('duplicate-args-category');
                 }
                 $namedArgs[$name] = $value->item(0);
                 unset($numberedArgs[$name]);
             }
         }
     }
     return new PPTemplateFrame_DOM($this->preprocessor, $this, $numberedArgs, $namedArgs, $title);
 }
 /**
  * Override the title of the page when viewed, provided we've been given a
  * title which will normalise to the canonical title
  *
  * @param Parser $parser Parent parser
  * @param string $text Desired title text
  * @param string $uarg
  * @return string
  */
 public static function displaytitle($parser, $text = '', $uarg = '')
 {
     global $wgRestrictDisplayTitle;
     static $magicWords = null;
     if (is_null($magicWords)) {
         $magicWords = new MagicWordArray(['displaytitle_noerror', 'displaytitle_noreplace']);
     }
     $arg = $magicWords->matchStartToEnd($uarg);
     // parse a limited subset of wiki markup (just the single quote items)
     $text = $parser->doQuotes($text);
     // remove stripped text (e.g. the UNIQ-QINU stuff) that was generated by tag extensions/whatever
     $text = $parser->killMarkers($text);
     // list of disallowed tags for DISPLAYTITLE
     // these will be escaped even though they are allowed in normal wiki text
     $bad = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'div', 'blockquote', 'ol', 'ul', 'li', 'hr', 'table', 'tr', 'th', 'td', 'dl', 'dd', 'caption', 'p', 'ruby', 'rb', 'rt', 'rtc', 'rp', 'br'];
     // disallow some styles that could be used to bypass $wgRestrictDisplayTitle
     if ($wgRestrictDisplayTitle) {
         $htmlTagsCallback = function (&$params) {
             $decoded = Sanitizer::decodeTagAttributes($params);
             if (isset($decoded['style'])) {
                 // this is called later anyway, but we need it right now for the regexes below to be safe
                 // calling it twice doesn't hurt
                 $decoded['style'] = Sanitizer::checkCss($decoded['style']);
                 if (preg_match('/(display|user-select|visibility)\\s*:/i', $decoded['style'])) {
                     $decoded['style'] = '/* attempt to bypass $wgRestrictDisplayTitle */';
                 }
             }
             $params = Sanitizer::safeEncodeTagAttributes($decoded);
         };
     } else {
         $htmlTagsCallback = null;
     }
     // only requested titles that normalize to the actual title are allowed through
     // if $wgRestrictDisplayTitle is true (it is by default)
     // mimic the escaping process that occurs in OutputPage::setPageTitle
     $text = Sanitizer::normalizeCharReferences(Sanitizer::removeHTMLtags($text, $htmlTagsCallback, [], [], $bad));
     $title = Title::newFromText(Sanitizer::stripAllTags($text));
     if (!$wgRestrictDisplayTitle || $title instanceof Title && !$title->hasFragment() && $title->equals($parser->mTitle)) {
         $old = $parser->mOutput->getProperty('displaytitle');
         if ($old === false || $arg !== 'displaytitle_noreplace') {
             $parser->mOutput->setDisplayTitle($text);
         }
         if ($old !== false && $old !== $text && !$arg) {
             $converter = $parser->getConverterLanguage()->getConverter();
             return '<span class="error">' . wfMessage('duplicate-displaytitle', $converter->markNoConversion(wfEscapeWikiText($old)), $converter->markNoConversion(wfEscapeWikiText($text)))->inContentLanguage()->text() . '</span>';
         } else {
             return '';
         }
     } else {
         $parser->addTrackingCategory('restricted-displaytitle-ignored');
         $converter = $parser->getConverterLanguage()->getConverter();
         return '<span class="error">' . wfMessage('restricted-displaytitle', $converter->markNoConversion(wfEscapeWikiText($text)))->inContentLanguage()->text() . '</span>';
     }
 }
 /**
  * Create a new child frame
  * $args is optionally a multi-root PPNode or array containing the template arguments
  *
  * @param array|bool|PPNode_Hash_Array $args
  * @param Title|bool $title
  * @param int $indexOffset
  * @throws MWException
  * @return PPTemplateFrame_Hash
  */
 public function newChild($args = false, $title = false, $indexOffset = 0)
 {
     $namedArgs = array();
     $numberedArgs = array();
     if ($title === false) {
         $title = $this->title;
     }
     if ($args !== false) {
         if ($args instanceof PPNode_Hash_Array) {
             $args = $args->value;
         } elseif (!is_array($args)) {
             throw new MWException(__METHOD__ . ': $args must be array or PPNode_Hash_Array');
         }
         foreach ($args as $arg) {
             $bits = $arg->splitArg();
             if ($bits['index'] !== '') {
                 // Numbered parameter
                 $index = $bits['index'] - $indexOffset;
                 if (isset($namedArgs[$index]) || isset($numberedArgs[$index])) {
                     $this->parser->getOutput()->addWarning(wfMessage('duplicate-args-warning', wfEscapeWikiText($this->title), wfEscapeWikiText($title), wfEscapeWikiText($index))->text());
                     $this->parser->addTrackingCategory('duplicate-args-category');
                 }
                 $numberedArgs[$index] = $bits['value'];
                 unset($namedArgs[$index]);
             } else {
                 // Named parameter
                 $name = trim($this->expand($bits['name'], PPFrame::STRIP_COMMENTS));
                 if (isset($namedArgs[$name]) || isset($numberedArgs[$name])) {
                     $this->parser->getOutput()->addWarning(wfMessage('duplicate-args-warning', wfEscapeWikiText($this->title), wfEscapeWikiText($title), wfEscapeWikiText($name))->text());
                     $this->parser->addTrackingCategory('duplicate-args-category');
                 }
                 $namedArgs[$name] = $bits['value'];
                 unset($numberedArgs[$name]);
             }
         }
     }
     return new PPTemplateFrame_Hash($this->preprocessor, $this, $numberedArgs, $namedArgs, $title);
 }
 /**
  * Parser hook
  *
  * @param string $text
  * @param array $args
  * @param Parser $parser
  * @return string
  */
 public static function parserHook($text, $args = array(), $parser)
 {
     global $wgUseTidy;
     // Don't trim leading spaces away, just the linefeeds
     $out = preg_replace('/^\\n+/', '', rtrim($text));
     // Convert deprecated attributes
     if (isset($args['enclose'])) {
         if ($args['enclose'] === 'none') {
             $args['inline'] = true;
         }
         unset($args['enclose']);
     }
     $lexer = isset($args['lang']) ? $args['lang'] : '';
     $result = self::highlight($out, $lexer, $args);
     if (!$result->isGood()) {
         $parser->addTrackingCategory('syntaxhighlight-error-category');
     }
     $out = $result->getValue();
     // HTML Tidy will convert tabs to spaces incorrectly (bug 30930).
     // But the conversion from tab to space occurs while reading the input,
     // before the conversion from &#9; to tab, so we can armor it that way.
     if ($wgUseTidy) {
         $out = str_replace("\t", '&#9;', $out);
     }
     // Allow certain HTML attributes
     $htmlAttribs = Sanitizer::validateAttributes($args, array('style', 'class', 'id', 'dir'));
     if (!isset($htmlAttribs['class'])) {
         $htmlAttribs['class'] = self::HIGHLIGHT_CSS_CLASS;
     } else {
         $htmlAttribs['class'] .= ' ' . self::HIGHLIGHT_CSS_CLASS;
     }
     if (!(isset($htmlAttribs['dir']) && $htmlAttribs['dir'] === 'rtl')) {
         $htmlAttribs['dir'] = 'ltr';
     }
     if (isset($args['inline'])) {
         // Enforce inlineness. Stray newlines may result in unexpected list and paragraph processing
         // (also known as doBlockLevels()).
         $out = str_replace("\n", ' ', $out);
         $out = Html::rawElement('code', $htmlAttribs, $out);
     } else {
         // Not entirely sure what benefit this provides, but it was here already
         $htmlAttribs['class'] .= ' ' . 'mw-content-' . $htmlAttribs['dir'];
         // Unwrap Pygments output to provide our own wrapper. We can't just always use the 'nowrap'
         // option (pass 'inline'), since it disables other useful things like line highlighting.
         // Tolerate absence of quotes for Html::element() and wgWellFormedXml=false.
         $m = array();
         if (preg_match('/^<div class="?mw-highlight"?>(.*)<\\/div>$/s', trim($out), $m)) {
             $out = trim($m[1]);
         } else {
             throw new MWException('Unexpected output from Pygments encountered');
         }
         // Use 'nowiki' strip marker to prevent list processing (also known as doBlockLevels()).
         // However, leave the wrapping <div/> outside to prevent <p/>-wrapping.
         $marker = $parser->mUniqPrefix . '-syntaxhighlightinner-' . sprintf('%08X', $parser->mMarkerIndex++) . $parser::MARKER_SUFFIX;
         $parser->mStripState->addNoWiki($marker, $out);
         $out = Html::openElement('div', $htmlAttribs) . $marker . Html::closeElement('div');
     }
     // Register CSS
     $parser->getOutput()->addModuleStyles('ext.pygments');
     return $out;
 }