Esempio n. 1
0
 protected function castBool($args)
 {
     if (count($args) < 1) {
         throw new AFPUserVisibleException('noparams', $this->mCur->pos, array(__METHOD__));
     }
     $val = $args[0];
     return AFPData::castTypes($val, AFPData::DBool);
 }
 /**
  * @param $vars AbuseFilterVariableHolder
  * @return AFPData|array|int|mixed|null|string
  * @throws MWException
  * @throws AFPException
  */
 function compute($vars)
 {
     $parameters = $this->mParameters;
     $result = null;
     if (!wfRunHooks('AbuseFilter-interceptVariable', array($this->mMethod, $vars, $parameters, &$result))) {
         return $result instanceof AFPData ? $result : AFPData::newFromPHPVar($result);
     }
     switch ($this->mMethod) {
         case 'diff':
             $text1Var = $parameters['oldtext-var'];
             $text2Var = $parameters['newtext-var'];
             $text1 = $vars->getVar($text1Var)->toString() . "\n";
             $text2 = $vars->getVar($text2Var)->toString() . "\n";
             $result = wfDiff($text1, $text2);
             break;
         case 'diff-split':
             $diff = $vars->getVar($parameters['diff-var'])->toString();
             $line_prefix = $parameters['line-prefix'];
             $diff_lines = explode("\n", $diff);
             $interest_lines = array();
             foreach ($diff_lines as $line) {
                 if (substr($line, 0, 1) === $line_prefix) {
                     $interest_lines[] = substr($line, strlen($line_prefix));
                 }
             }
             $result = $interest_lines;
             break;
         case 'links-from-wikitext':
             // This should ONLY be used when sharing a parse operation with the edit.
             /* @var WikiPage $article */
             $article = $parameters['article'];
             if ($article !== null && (!defined('MW_SUPPORTS_CONTENTHANDLER') || $article->getContentModel() === CONTENT_MODEL_WIKITEXT)) {
                 $textVar = $parameters['text-var'];
                 // XXX: Use prepareContentForEdit. But we need a Content object for that.
                 $new_text = $vars->getVar($textVar)->toString();
                 $content = ContentHandler::makeContent($new_text, $article->getTitle());
                 $editInfo = $article->prepareContentForEdit($content);
                 $links = array_keys($editInfo->output->getExternalLinks());
                 $result = $links;
                 break;
             }
             // Otherwise fall back to database
         // Otherwise fall back to database
         case 'links-from-wikitext-nonedit':
         case 'links-from-wikitext-or-database':
             // TODO: use Content object instead, if available! In any case, use WikiPage, not Article.
             $article = self::articleFromTitle($parameters['namespace'], $parameters['title']);
             if ($vars->getVar('context')->toString() == 'filter') {
                 $links = $this->getLinksFromDB($article);
                 wfDebug("AbuseFilter: loading old links from DB\n");
             } elseif (!defined('MW_SUPPORTS_CONTENTHANDLER') || $article->getContentModel() === CONTENT_MODEL_WIKITEXT) {
                 wfDebug("AbuseFilter: loading old links from Parser\n");
                 $textVar = $parameters['text-var'];
                 $wikitext = $vars->getVar($textVar)->toString();
                 $editInfo = $this->parseNonEditWikitext($wikitext, $article);
                 $links = array_keys($editInfo->output->getExternalLinks());
             } else {
                 // TODO: Get links from Content object. But we don't have the content object.
                 //      And for non-text content, $wikitext is usually not going to be a valid
                 //      serialization, but rather some dummy text for filtering.
                 $links = array();
             }
             $result = $links;
             break;
         case 'link-diff-added':
         case 'link-diff-removed':
             $oldLinkVar = $parameters['oldlink-var'];
             $newLinkVar = $parameters['newlink-var'];
             $oldLinks = $vars->getVar($oldLinkVar)->toString();
             $newLinks = $vars->getVar($newLinkVar)->toString();
             $oldLinks = explode("\n", $oldLinks);
             $newLinks = explode("\n", $newLinks);
             if ($this->mMethod == 'link-diff-added') {
                 $result = array_diff($newLinks, $oldLinks);
             }
             if ($this->mMethod == 'link-diff-removed') {
                 $result = array_diff($oldLinks, $newLinks);
             }
             break;
         case 'parse-wikitext':
             // Should ONLY be used when sharing a parse operation with the edit.
             $article = $parameters['article'];
             if ($article !== null && (!defined('MW_SUPPORTS_CONTENTHANDLER') || $article->getContentModel() === CONTENT_MODEL_WIKITEXT)) {
                 $textVar = $parameters['wikitext-var'];
                 // XXX: Use prepareContentForEdit. But we need a Content object for that.
                 $new_text = $vars->getVar($textVar)->toString();
                 $editInfo = $article->prepareTextForEdit($new_text);
                 if (isset($parameters['pst']) && $parameters['pst']) {
                     $result = $editInfo->pstContent->serialize($editInfo->format);
                 } else {
                     $newHTML = $editInfo->output->getText();
                     // Kill the PP limit comments. Ideally we'd just remove these by not setting the
                     // parser option, but then we can't share a parse operation with the edit, which is bad.
                     $result = preg_replace('/<!--\\s*NewPP limit report[^>]*-->\\s*$/si', '', $newHTML);
                 }
                 break;
             }
             // Otherwise fall back to database
         // Otherwise fall back to database
         case 'parse-wikitext-nonedit':
             // TODO: use Content object instead, if available! In any case, use WikiPage, not Article.
             $article = self::articleFromTitle($parameters['namespace'], $parameters['title']);
             $textVar = $parameters['wikitext-var'];
             if (!defined('MW_SUPPORTS_CONTENTHANDLER') || $article->getContentModel() === CONTENT_MODEL_WIKITEXT) {
                 if (isset($parameters['pst']) && $parameters['pst']) {
                     // $textVar is already PSTed when it's not loaded from an ongoing edit.
                     $result = $vars->getVar($textVar)->toString();
                 } else {
                     $text = $vars->getVar($textVar)->toString();
                     $editInfo = $this->parseNonEditWikitext($text, $article);
                     $result = $editInfo->output->getText();
                 }
             } else {
                 // TODO: Parser Output from Content object. But we don't have the content object.
                 //      And for non-text content, $wikitext is usually not going to be a valid
                 //      serialization, but rather some dummy text for filtering.
                 $result = '';
             }
             break;
         case 'strip-html':
             $htmlVar = $parameters['html-var'];
             $html = $vars->getVar($htmlVar)->toString();
             $result = StringUtils::delimiterReplace('<', '>', '', $html);
             break;
         case 'load-recent-authors':
             $cutOff = $parameters['cutoff'];
             $title = Title::makeTitle($parameters['namespace'], $parameters['title']);
             if (!$title->exists()) {
                 $result = '';
                 break;
             }
             $dbr = wfGetDB(DB_SLAVE);
             $res = $dbr->select('revision', 'DISTINCT rev_user_text', array('rev_page' => $title->getArticleID(), 'rev_timestamp<' . $dbr->addQuotes($dbr->timestamp($cutOff))), __METHOD__, array('ORDER BY' => 'rev_timestamp DESC', 'LIMIT' => 10));
             $users = array();
             foreach ($res as $row) {
                 $users[] = $row->rev_user_text;
             }
             $result = $users;
             break;
         case 'get-page-restrictions':
             $action = $parameters['action'];
             $title = Title::makeTitle($parameters['namespace'], $parameters['title']);
             $rights = $title->getRestrictions($action);
             $rights = count($rights) ? $rights : array();
             $result = $rights;
             break;
         case 'simple-user-accessor':
             $user = $parameters['user'];
             $method = $parameters['method'];
             if (!$user) {
                 throw new MWException('No user parameter given.');
             }
             $obj = self::getUserObject($user);
             if (!$obj) {
                 throw new MWException("Invalid username {$user}");
             }
             $result = call_user_func(array($obj, $method));
             break;
         case 'user-age':
             $user = $parameters['user'];
             $asOf = $parameters['asof'];
             $obj = self::getUserObject($user);
             if ($obj->getId() == 0) {
                 $result = 0;
                 break;
             }
             $registration = $obj->getRegistration();
             $result = wfTimestamp(TS_UNIX, $asOf) - wfTimestampOrNull(TS_UNIX, $registration);
             break;
         case 'user-groups':
             // Deprecated but needed by old log entries
             $user = $parameters['user'];
             $obj = self::getUserObject($user);
             $result = $obj->getEffectiveGroups();
             break;
         case 'length':
             $s = $vars->getVar($parameters['length-var'])->toString();
             $result = strlen($s);
             break;
         case 'subtract':
             $v1 = $vars->getVar($parameters['val1-var'])->toFloat();
             $v2 = $vars->getVar($parameters['val2-var'])->toFloat();
             $result = $v1 - $v2;
             break;
         case 'revision-text-by-id':
             $rev = Revision::newFromId($parameters['revid']);
             $result = AbuseFilter::revisionToString($rev);
             break;
         case 'revision-text-by-timestamp':
             $timestamp = $parameters['timestamp'];
             $title = Title::makeTitle($parameters['namespace'], $parameters['title']);
             $dbr = wfGetDB(DB_SLAVE);
             $rev = Revision::loadFromTimestamp($dbr, $title, $timestamp);
             $result = AbuseFilter::revisionToString($rev);
             break;
         default:
             if (wfRunHooks('AbuseFilter-computeVariable', array($this->mMethod, $vars, $parameters, &$result))) {
                 throw new AFPException('Unknown variable compute type ' . $this->mMethod);
             }
     }
     return $result instanceof AFPData ? $result : AFPData::newFromPHPVar($result);
 }
 function compute($vars)
 {
     $parameters = $this->mParameters;
     $result = null;
     switch ($this->mMethod) {
         case 'diff':
             $text1Var = $parameters['oldtext-var'];
             $text2Var = $parameters['newtext-var'];
             $text1 = $vars->getVar($text1Var)->toString();
             $text2 = $vars->getVar($text2Var)->toString();
             $result = wfDiff($text1, $text2);
             $result = trim(preg_replace("/^\\\\ No newline at end of file\n/m", '', $result));
             break;
         case 'diff-split':
             $diff = $vars->getVar($parameters['diff-var'])->toString();
             $line_prefix = $parameters['line-prefix'];
             $diff_lines = explode("\n", $diff);
             $interest_lines = array();
             foreach ($diff_lines as $line) {
                 if (substr($line, 0, 1) === $line_prefix) {
                     $interest_lines[] = substr($line, strlen($line_prefix));
                 }
             }
             $result = $interest_lines;
             break;
         case 'links-from-wikitext':
             // This should ONLY be used when sharing a parse operation with the edit.
             $article = $parameters['article'];
             if ($article) {
                 $textVar = $parameters['text-var'];
                 $new_text = $vars->getVar($textVar)->toString();
                 $editInfo = $article->prepareTextForEdit($new_text);
                 $links = array_keys($editInfo->output->getExternalLinks());
                 $result = $links;
                 break;
             }
             // Otherwise fall back to database
         // Otherwise fall back to database
         case 'links-from-wikitext-nonedit':
         case 'links-from-wikitext-or-database':
             $article = self::articleFromTitle($parameters['namespace'], $parameters['title']);
             if ($vars->getVar('context')->toString() == 'filter') {
                 $links = $this->getLinksFromDB($article);
                 wfDebug("AbuseFilter: loading old links from DB\n");
             } else {
                 wfDebug("AbuseFilter: loading old links from Parser\n");
                 $textVar = $parameters['text-var'];
                 $wikitext = $vars->getVar($textVar)->toString();
                 $editInfo = $this->parseNonEditWikitext($wikitext, $article);
                 $links = array_keys($editInfo->output->getExternalLinks());
             }
             $result = $links;
             break;
         case 'link-diff-added':
         case 'link-diff-removed':
             $oldLinkVar = $parameters['oldlink-var'];
             $newLinkVar = $parameters['newlink-var'];
             $oldLinks = $vars->getVar($oldLinkVar)->toString();
             $newLinks = $vars->getVar($newLinkVar)->toString();
             $oldLinks = explode("\n", $oldLinks);
             $newLinks = explode("\n", $newLinks);
             if ($this->mMethod == 'link-diff-added') {
                 $result = array_diff($newLinks, $oldLinks);
             }
             if ($this->mMethod == 'link-diff-removed') {
                 $result = array_diff($oldLinks, $newLinks);
             }
             break;
         case 'parse-wikitext':
             // Should ONLY be used when sharing a parse operation with the edit.
             $article = $parameters['article'];
             if ($article) {
                 $textVar = $parameters['wikitext-var'];
                 $new_text = $vars->getVar($textVar)->toString();
                 $editInfo = $article->prepareTextForEdit($new_text);
                 $newHTML = $editInfo->output->getText();
                 // Kill the PP limit comments. Ideally we'd just remove these by not setting the
                 // parser option, but then we can't share a parse operation with the edit, which is bad.
                 $result = preg_replace('/<!--\\s*NewPP limit report[^>]*-->\\s*$/si', '', $newHTML);
                 break;
             }
             // Otherwise fall back to database
         // Otherwise fall back to database
         case 'parse-wikitext-nonedit':
             $article = self::articleFromTitle($parameters['namespace'], $parameters['title']);
             $textVar = $parameters['wikitext-var'];
             $text = $vars->getVar($textVar)->toString();
             $editInfo = $this->parseNonEditWikitext($text, $article);
             $result = $editInfo->output->getText();
             break;
         case 'strip-html':
             $htmlVar = $parameters['html-var'];
             $html = $vars->getVar($htmlVar)->toString();
             $result = StringUtils::delimiterReplace('<', '>', '', $html);
             break;
         case 'load-recent-authors':
             $cutOff = $parameters['cutoff'];
             $title = Title::makeTitle($parameters['namespace'], $parameters['title']);
             if (!$title->exists()) {
                 $result = '';
                 break;
             }
             $dbr = wfGetDB(DB_SLAVE);
             $res = $dbr->select('revision', 'DISTINCT rev_user_text', array('rev_page' => $title->getArticleId(), 'rev_timestamp<' . $dbr->addQuotes($dbr->timestamp($cutOff))), __METHOD__, array('ORDER BY' => 'rev_timestamp DESC', 'LIMIT' => 10));
             $users = array();
             foreach ($res as $row) {
                 $users[] = $row->rev_user_text;
             }
             $result = $users;
             break;
         case 'get-page-restrictions':
             $action = $parameters['action'];
             $title = Title::makeTitle($parameters['namespace'], $parameters['title']);
             $rights = $title->getRestrictions($action);
             $rights = count($rights) ? $rights : array();
             $result = $rights;
             break;
         case 'simple-user-accessor':
             $user = $parameters['user'];
             $method = $parameters['method'];
             if (!$user) {
                 throw new MWException('No user parameter given.');
             }
             $obj = self::userObjectFromName($user);
             if (!$obj) {
                 throw new MWException("Invalid username {$user}");
             }
             $result = call_user_func(array($obj, $method));
             break;
         case 'user-age':
             $user = $parameters['user'];
             $asOf = $parameters['asof'];
             $obj = self::userObjectFromName($user);
             if ($obj->getId() == 0) {
                 $result = 0;
                 break;
             }
             $registration = $obj->getRegistration();
             $result = wfTimestamp(TS_UNIX, $asOf) - wfTimestampOrNull(TS_UNIX, $registration);
             break;
         case 'user-groups':
             $user = $parameters['user'];
             $obj = self::userObjectFromName($user);
             $result = $obj->getEffectiveGroups();
             break;
         case 'length':
             $s = $vars->getVar($parameters['length-var'])->toString();
             $result = strlen($s);
             break;
         case 'subtract':
             $v1 = $vars->getVar($parameters['val1-var'])->toFloat();
             $v2 = $vars->getVar($parameters['val2-var'])->toFloat();
             $result = $v1 - $v2;
             break;
         case 'revision-text-by-id':
             $rev = Revision::newFromId($parameters['revid']);
             $result = $rev->getText();
             break;
         case 'revision-text-by-timestamp':
             $timestamp = $parameters['timestamp'];
             $title = Title::makeTitle($parameters['namespace'], $parameters['title']);
             $dbr = wfGetDB(DB_SLAVE);
             $rev = Revision::loadFromTimestamp($dbr, $title, $timestamp);
             if ($rev) {
                 $result = $rev->getText();
             } else {
                 $result = '';
             }
             break;
         default:
             if (wfRunHooks('AbuseFilter-computeVariable', array($this->mMethod, $vars))) {
                 throw new AFPException('Unknown variable compute type ' . $this->mMethod);
             }
     }
     return $result instanceof AFPData ? $result : AFPData::newFromPHPVar($result);
 }