function __construct()
 {
     global $wgModerationTimeToOverrideRejection;
     $mw_ts = new MWTimestamp(time());
     $mw_ts->timestamp->modify('-' . intval($wgModerationTimeToOverrideRejection) . ' seconds');
     $this->earliestReapprovableTimestamp = $mw_ts->getTimestamp(TS_MW);
     $this->mblockCheck = new ModerationBlockCheck();
     parent::__construct('Moderation', 'moderation');
 }
Пример #2
0
 public function execute()
 {
     $params = $this->extractRequestParams();
     $token = $params['token'];
     $maxage = $params['maxtokenage'];
     $salts = ApiQueryTokens::getTokenTypeSalts();
     $res = array();
     $tokenObj = ApiQueryTokens::getToken($this->getUser(), $this->getRequest()->getSession(), $salts[$params['type']]);
     if ($tokenObj->match($token, $maxage)) {
         $res['result'] = 'valid';
     } elseif ($maxage !== null && $tokenObj->match($token)) {
         $res['result'] = 'expired';
     } else {
         $res['result'] = 'invalid';
     }
     $ts = MediaWiki\Session\Token::getTimestamp($token);
     if ($ts !== null) {
         $mwts = new MWTimestamp();
         $mwts->timestamp->setTimestamp($ts);
         $res['generated'] = $mwts->getTimestamp(TS_ISO_8601);
     }
     $this->getResult()->addValue(null, $this->getModuleName(), $res);
 }
Пример #3
0
 /**
  * Convert dates like "Tue, 03 Jan 2012 22:01:04 GMT"/"2013-05-11T07:37:27.678360Z".
  * Dates might also come in like "2013-05-11T07:37:27.678360" from Swift listings,
  * missing the timezone suffix (though Ceph RGW does not appear to have this bug).
  *
  * @param string $ts
  * @param int $format Output format (TS_* constant)
  * @return string
  * @throws FileBackendError
  */
 protected function convertSwiftDate($ts, $format = TS_MW)
 {
     try {
         $timestamp = new MWTimestamp($ts);
         return $timestamp->getTimestamp($format);
     } catch (Exception $e) {
         throw new FileBackendError($e->getMessage());
     }
 }
Пример #4
0
/**
 * Get a timestamp string in one of various formats
 *
 * @param mixed $outputtype A timestamp in one of the supported formats, the
 *   function will autodetect which format is supplied and act accordingly.
 * @param mixed $ts Optional timestamp to convert, default 0 for the current time
 * @return string|bool String / false The same date in the format specified in $outputtype or false
 */
function wfTimestamp($outputtype = TS_UNIX, $ts = 0)
{
    try {
        $timestamp = new MWTimestamp($ts);
        return $timestamp->getTimestamp($outputtype);
    } catch (TimestampException $e) {
        wfDebug("wfTimestamp() fed bogus time value: TYPE={$outputtype}; VALUE={$ts}\n");
        return false;
    }
}
Пример #5
0
 /**
  * Reset the notification timestamp of this entry
  *
  * @param $force Whether to force the write query to be executed even if the
  *        page is not watched or the notification timestamp is already NULL.
  * @param int $oldid The revision id being viewed. If not given or 0, latest revision is assumed.
  */
 public function resetNotificationTimestamp($force = '', $oldid = 0)
 {
     // Only loggedin user can have a watchlist
     if (wfReadOnly() || $this->mUser->isAnon() || !$this->isAllowed('editmywatchlist')) {
         return;
     }
     if ($force != 'force') {
         $this->load();
         if (!$this->watched || $this->timestamp === null) {
             return;
         }
     }
     $title = $this->getTitle();
     if (!$oldid) {
         // No oldid given, assuming latest revision; clear the timestamp.
         $notificationTimestamp = null;
     } elseif (!$title->getNextRevisionID($oldid)) {
         // Oldid given and is the latest revision for this title; clear the timestamp.
         $notificationTimestamp = null;
     } else {
         // See if the version marked as read is more recent than the one we're viewing.
         // Call load() if it wasn't called before due to $force.
         $this->load();
         if ($this->timestamp === null) {
             // This can only happen if $force is enabled.
             $notificationTimestamp = null;
         } else {
             // Oldid given and isn't the latest; update the timestamp.
             // This will result in no further notification emails being sent!
             $dbr = wfGetDB(DB_SLAVE);
             $notificationTimestamp = $dbr->selectField('revision', 'rev_timestamp', array('rev_page' => $title->getArticleID(), 'rev_id' => $oldid));
             // We need to go one second to the future because of various strict comparisons
             // throughout the codebase
             $ts = new MWTimestamp($notificationTimestamp);
             $ts->timestamp->add(new DateInterval('PT1S'));
             $notificationTimestamp = $ts->getTimestamp(TS_MW);
             if ($notificationTimestamp < $this->timestamp) {
                 if ($force != 'force') {
                     return;
                 } else {
                     // This is a little silly…
                     $notificationTimestamp = $this->timestamp;
                 }
             }
         }
     }
     // If the page is watched by the user (or may be watched), update the timestamp on any
     // any matching rows
     $dbw = wfGetDB(DB_MASTER);
     $dbw->update('watchlist', array('wl_notificationtimestamp' => $notificationTimestamp), $this->dbCond(), __METHOD__);
     $this->timestamp = null;
 }
Пример #6
0
 public function execute()
 {
     $user = $this->getUser();
     $errors = $this->getTitle()->getUserPermissionsErrors('abusefilter-log', $user);
     if (count($errors)) {
         $this->dieUsageMsg($errors[0]);
         return;
     }
     $params = $this->extractRequestParams();
     $prop = array_flip($params['prop']);
     $fld_ids = isset($prop['ids']);
     $fld_filter = isset($prop['filter']);
     $fld_user = isset($prop['user']);
     $fld_ip = isset($prop['ip']);
     $fld_title = isset($prop['title']);
     $fld_action = isset($prop['action']);
     $fld_details = isset($prop['details']);
     $fld_result = isset($prop['result']);
     $fld_timestamp = isset($prop['timestamp']);
     $fld_hidden = isset($prop['hidden']);
     $fld_revid = isset($prop['revid']);
     if ($fld_ip && !$user->isAllowed('abusefilter-private')) {
         $this->dieUsage('You don\'t have permission to view IP addresses', 'permissiondenied');
     }
     if ($fld_details && !$user->isAllowed('abusefilter-log-detail')) {
         $this->dieUsage('You don\'t have permission to view detailed abuse log entries', 'permissiondenied');
     }
     // Match permissions for viewing events on private filters to SpecialAbuseLog (bug 42814)
     if ($params['filter'] && !(AbuseFilterView::canViewPrivate() || $user->isAllowed('abusefilter-log-private'))) {
         // A specific filter parameter is set but the user isn't allowed to view all filters
         if (!is_array($params['filter'])) {
             $params['filter'] = array($params['filter']);
         }
         foreach ($params['filter'] as $filter) {
             if (AbuseFilter::filterHidden($filter)) {
                 $this->dieUsage('You don\'t have permission to view log entries for private filters', 'permissiondenied');
             }
         }
     }
     $result = $this->getResult();
     $this->addTables('abuse_filter_log');
     $this->addFields('afl_timestamp');
     $this->addFields('afl_rev_id');
     $this->addFields('afl_deleted');
     $this->addFields('afl_filter');
     $this->addFieldsIf('afl_id', $fld_ids);
     $this->addFieldsIf('afl_user_text', $fld_user);
     $this->addFieldsIf('afl_ip', $fld_ip);
     $this->addFieldsIf(array('afl_namespace', 'afl_title'), $fld_title);
     $this->addFieldsIf('afl_action', $fld_action);
     $this->addFieldsIf('afl_var_dump', $fld_details);
     $this->addFieldsIf('afl_actions', $fld_result);
     if ($fld_filter) {
         $this->addTables('abuse_filter');
         $this->addFields('af_public_comments');
         $this->addJoinConds(array('abuse_filter' => array('LEFT JOIN', 'af_id=afl_filter')));
     }
     $this->addOption('LIMIT', $params['limit'] + 1);
     $this->addWhereRange('afl_timestamp', $params['dir'], $params['start'], $params['end']);
     $db = $this->getDB();
     $notDeletedCond = SpecialAbuseLog::getNotDeletedCond($db);
     if (isset($params['user'])) {
         $u = User::newFromName($params['user']);
         if ($u) {
             // Username normalisation
             $params['user'] = $u->getName();
             $userId = $u->getId();
         } elseif (IP::isIPAddress($params['user'])) {
             // It's an IP, sanitize it
             $params['user'] = IP::sanitizeIP($params['user']);
             $userId = 0;
         }
         if (isset($userId)) {
             // Only add the WHERE for user in case it's either a valid user (but not necessary an existing one) or an IP
             $this->addWhere(array('afl_user' => $userId, 'afl_user_text' => $params['user']));
         }
     }
     $this->addWhereIf(array('afl_filter' => $params['filter']), isset($params['filter']));
     $this->addWhereIf($notDeletedCond, !SpecialAbuseLog::canSeeHidden($user));
     $title = $params['title'];
     if (!is_null($title)) {
         $titleObj = Title::newFromText($title);
         if (is_null($titleObj)) {
             $this->dieUsageMsg(array('invalidtitle', $title));
         }
         $this->addWhereFld('afl_namespace', $titleObj->getNamespace());
         $this->addWhereFld('afl_title', $titleObj->getDBkey());
     }
     $res = $this->select(__METHOD__);
     $count = 0;
     foreach ($res as $row) {
         if (++$count > $params['limit']) {
             // We've had enough
             $ts = new MWTimestamp($row->afl_timestamp);
             $this->setContinueEnumParameter('start', $ts->getTimestamp(TS_ISO_8601));
             break;
         }
         if (SpecialAbuseLog::isHidden($row) && !SpecialAbuseLog::canSeeHidden($user)) {
             continue;
         }
         $canSeeDetails = SpecialAbuseLog::canSeeDetails($row->afl_filter);
         $entry = array();
         if ($fld_ids) {
             $entry['id'] = intval($row->afl_id);
             $entry['filter_id'] = '';
             if ($canSeeDetails) {
                 $entry['filter_id'] = $row->afl_filter;
             }
         }
         if ($fld_filter) {
             $entry['filter'] = $row->af_public_comments;
         }
         if ($fld_user) {
             $entry['user'] = $row->afl_user_text;
         }
         if ($fld_ip) {
             $entry['ip'] = $row->afl_ip;
         }
         if ($fld_title) {
             $title = Title::makeTitle($row->afl_namespace, $row->afl_title);
             ApiQueryBase::addTitleInfo($entry, $title);
         }
         if ($fld_action) {
             $entry['action'] = $row->afl_action;
         }
         if ($fld_result) {
             $entry['result'] = $row->afl_actions;
         }
         if ($fld_revid && !is_null($row->afl_rev_id)) {
             $entry['revid'] = '';
             if ($canSeeDetails) {
                 $entry['revid'] = $row->afl_rev_id;
             }
         }
         if ($fld_timestamp) {
             $ts = new MWTimestamp($row->afl_timestamp);
             $entry['timestamp'] = $ts->getTimestamp(TS_ISO_8601);
         }
         if ($fld_details) {
             $entry['details'] = array();
             if ($canSeeDetails) {
                 $vars = AbuseFilter::loadVarDump($row->afl_var_dump);
                 if ($vars instanceof AbuseFilterVariableHolder) {
                     $entry['details'] = $vars->exportAllVars();
                 } else {
                     $entry['details'] = array_change_key_case($vars, CASE_LOWER);
                 }
             }
         }
         if ($fld_hidden) {
             $val = SpecialAbuseLog::isHidden($row);
             if ($val) {
                 $entry['hidden'] = $val;
             }
         }
         if ($entry) {
             $fit = $result->addValue(array('query', $this->getModuleName()), null, $entry);
             if (!$fit) {
                 $ts = new MWTimestamp($row->afl_timestamp);
                 $this->setContinueEnumParameter('start', $ts->getTimestamp(TS_ISO_8601));
                 break;
             }
         }
     }
     $result->setIndexedTagName_internal(array('query', $this->getModuleName()), 'item');
 }
 public function execute()
 {
     $user = $this->getUser();
     if (!$user->isAllowed('abusefilter-view')) {
         $this->dieUsage('You don\'t have permission to view abuse filters', 'permissiondenied');
     }
     $params = $this->extractRequestParams();
     $prop = array_flip($params['prop']);
     $fld_id = isset($prop['id']);
     $fld_desc = isset($prop['description']);
     $fld_pattern = isset($prop['pattern']);
     $fld_actions = isset($prop['actions']);
     $fld_hits = isset($prop['hits']);
     $fld_comments = isset($prop['comments']);
     $fld_user = isset($prop['lasteditor']);
     $fld_time = isset($prop['lastedittime']);
     $fld_status = isset($prop['status']);
     $fld_private = isset($prop['private']);
     $result = $this->getResult();
     $this->addTables('abuse_filter');
     $this->addFields('af_id');
     $this->addFields('af_hidden');
     $this->addFieldsIf('af_hit_count', $fld_hits);
     $this->addFieldsIf('af_enabled', $fld_status);
     $this->addFieldsIf('af_deleted', $fld_status);
     $this->addFieldsIf('af_public_comments', $fld_desc);
     $this->addFieldsIf('af_pattern', $fld_pattern);
     $this->addFieldsIf('af_actions', $fld_actions);
     $this->addFieldsIf('af_comments', $fld_comments);
     $this->addFieldsIf('af_user_text', $fld_user);
     $this->addFieldsIf('af_timestamp', $fld_time);
     $this->addOption('LIMIT', $params['limit'] + 1);
     $this->addWhereRange('af_id', $params['dir'], $params['startid'], $params['endid']);
     if (!is_null($params['show'])) {
         $show = array_flip($params['show']);
         /* Check for conflicting parameters. */
         if (isset($show['enabled']) && isset($show['!enabled']) || isset($show['deleted']) && isset($show['!deleted']) || isset($show['private']) && isset($show['!private'])) {
             $this->dieUsage('Incorrect parameter - mutually exclusive values may not be supplied', 'show');
         }
         $this->addWhereIf('af_enabled = 0', isset($show['!enabled']));
         $this->addWhereIf('af_enabled != 0', isset($show['enabled']));
         $this->addWhereIf('af_deleted = 0', isset($show['!deleted']));
         $this->addWhereIf('af_deleted != 0', isset($show['deleted']));
         $this->addWhereIf('af_hidden = 0', isset($show['!private']));
         $this->addWhereIf('af_hidden != 0', isset($show['private']));
     }
     $res = $this->select(__METHOD__);
     $showhidden = $user->isAllowed('abusefilter-modify');
     $count = 0;
     foreach ($res as $row) {
         if (++$count > $params['limit']) {
             // We've had enough
             $this->setContinueEnumParameter('startid', $row->af_id);
             break;
         }
         $entry = array();
         if ($fld_id) {
             $entry['id'] = intval($row->af_id);
         }
         if ($fld_desc) {
             $entry['description'] = $row->af_public_comments;
         }
         if ($fld_pattern && (!$row->af_hidden || $showhidden)) {
             $entry['pattern'] = $row->af_pattern;
         }
         if ($fld_actions) {
             $entry['actions'] = $row->af_actions;
         }
         if ($fld_hits) {
             $entry['hits'] = intval($row->af_hit_count);
         }
         if ($fld_comments && (!$row->af_hidden || $showhidden)) {
             $entry['comments'] = $row->af_comments;
         }
         if ($fld_user) {
             $entry['lasteditor'] = $row->af_user_text;
         }
         if ($fld_time) {
             $ts = new MWTimestamp($row->af_timestamp);
             $entry['lastedittime'] = $ts->getTimestamp(TS_ISO_8601);
         }
         if ($fld_private && $row->af_hidden) {
             $entry['private'] = '';
         }
         if ($fld_status) {
             if ($row->af_enabled) {
                 $entry['enabled'] = '';
             }
             if ($row->af_deleted) {
                 $entry['deleted'] = '';
             }
         }
         if ($entry) {
             $fit = $result->addValue(array('query', $this->getModuleName()), null, $entry);
             if (!$fit) {
                 $this->setContinueEnumParameter('startid', $row->af_id);
                 break;
             }
         }
     }
     $result->setIndexedTagName_internal(array('query', $this->getModuleName()), 'filter');
 }
Пример #8
0
 function formatValue($name, $value)
 {
     static $msg = null;
     if ($msg === null) {
         $keys = ['anononlyblock', 'createaccountblock', 'noautoblockblock', 'emailblock', 'blocklist-nousertalk', 'unblocklink', 'change-blocklink'];
         foreach ($keys as $key) {
             $msg[$key] = $this->msg($key)->escaped();
         }
     }
     /** @var $row object */
     $row = $this->mCurrentRow;
     $language = $this->getLanguage();
     $formatted = '';
     switch ($name) {
         case 'ipb_timestamp':
             $formatted = htmlspecialchars($language->userTimeAndDate($value, $this->getUser()));
             break;
         case 'ipb_target':
             if ($row->ipb_auto) {
                 $formatted = $this->msg('autoblockid', $row->ipb_id)->parse();
             } else {
                 list($target, $type) = Block::parseTarget($row->ipb_address);
                 switch ($type) {
                     case Block::TYPE_USER:
                     case Block::TYPE_IP:
                         $formatted = Linker::userLink($target->getId(), $target);
                         $formatted .= Linker::userToolLinks($target->getId(), $target, false, Linker::TOOL_LINKS_NOBLOCK);
                         break;
                     case Block::TYPE_RANGE:
                         $formatted = htmlspecialchars($target);
                 }
             }
             break;
         case 'ipb_expiry':
             $formatted = htmlspecialchars($language->formatExpiry($value, true));
             if ($this->getUser()->isAllowed('block')) {
                 if ($row->ipb_auto) {
                     $links[] = Linker::linkKnown(SpecialPage::getTitleFor('Unblock'), $msg['unblocklink'], [], ['wpTarget' => "#{$row->ipb_id}"]);
                 } else {
                     $links[] = Linker::linkKnown(SpecialPage::getTitleFor('Unblock', $row->ipb_address), $msg['unblocklink']);
                     $links[] = Linker::linkKnown(SpecialPage::getTitleFor('Block', $row->ipb_address), $msg['change-blocklink']);
                 }
                 $formatted .= ' ' . Html::rawElement('span', ['class' => 'mw-blocklist-actions'], $this->msg('parentheses')->rawParams($language->pipeList($links))->escaped());
             }
             if ($value !== 'infinity') {
                 $timestamp = new MWTimestamp($value);
                 $formatted .= '<br />' . $this->msg('ipb-blocklist-duration-left', $language->formatDuration($timestamp->getTimestamp() - time(), ['minutes', 'hours', 'days', 'years']))->escaped();
             }
             break;
         case 'ipb_by':
             if (isset($row->by_user_name)) {
                 $formatted = Linker::userLink($value, $row->by_user_name);
                 $formatted .= Linker::userToolLinks($value, $row->by_user_name);
             } else {
                 $formatted = htmlspecialchars($row->ipb_by_text);
                 // foreign user?
             }
             break;
         case 'ipb_reason':
             $formatted = Linker::formatComment($value);
             break;
         case 'ipb_params':
             $properties = [];
             if ($row->ipb_anon_only) {
                 $properties[] = $msg['anononlyblock'];
             }
             if ($row->ipb_create_account) {
                 $properties[] = $msg['createaccountblock'];
             }
             if ($row->ipb_user && !$row->ipb_enable_autoblock) {
                 $properties[] = $msg['noautoblockblock'];
             }
             if ($row->ipb_block_email) {
                 $properties[] = $msg['emailblock'];
             }
             if (!$row->ipb_allow_usertalk) {
                 $properties[] = $msg['blocklist-nousertalk'];
             }
             $formatted = $language->commaList($properties);
             break;
         default:
             $formatted = "Unable to format {$name}";
             break;
     }
     return $formatted;
 }
Пример #9
0
 /**
  * Outputs a table of existing drafts
  *
  * @param $title Title [optional] Title of article, defaults to all articles
  * @param $userID Integer: [optional] ID of user, defaults to current user
  * @return int Number of drafts in the table
  */
 public static function display($title = null, $userID = null)
 {
     global $wgOut, $wgRequest, $wgUser, $wgLang;
     // Gets draftID
     $currentDraft = Draft::newFromID($wgRequest->getIntOrNull('draft'));
     // Output HTML for list of drafts
     $drafts = Drafts::get($title, $userID);
     if (count($drafts) > 0) {
         global $egDraftsLifeSpan;
         // Internationalization
         // Add a summary, on Special:Drafts only
         if (!$title || $title->getNamespace() === NS_SPECIAL) {
             $wgOut->wrapWikiMsg('<div class="mw-drafts-summary">$1</div>', array('drafts-view-summary', $wgLang->formatNum($egDraftsLifeSpan)));
         }
         // Build XML
         $wgOut->addHTML(Xml::openElement('table', array('cellpadding' => 5, 'cellspacing' => 0, 'width' => '100%', 'border' => 0, 'id' => 'drafts-list-table', 'class' => 'section_text')));
         $wgOut->addHTML(Xml::openElement('tr'));
         $wgOut->addHTML(Xml::element('th', array(), wfMessage('drafts-view-article')->text()));
         $wgOut->addHTML(Xml::element('th', null, wfMessage('drafts-view-saved')->text()));
         $wgOut->addHTML(Xml::element('th', array()));
         $wgOut->addHTML(Xml::element('th', array()));
         $wgOut->addHTML(Xml::closeElement('tr'));
         // Add existing drafts for this page and user
         /**
          * @var $draft Draft
          */
         foreach ($drafts as $draft) {
             // Get article title text
             $htmlTitle = $draft->getTitle()->getEscapedText();
             // Build Article Load link
             $urlLoad = $draft->getTitle()->getFullURL('action=edit&draft=' . urlencode($draft->getID()));
             // Build discard link
             $urlDiscard = SpecialPage::getTitleFor('Drafts')->getFullURL(sprintf('discard=%s&token=%s', urlencode($draft->getID()), urlencode($wgUser->getEditToken())));
             // If in edit mode, return to editor
             if ($wgRequest->getText('action') == 'edit' || $wgRequest->getText('action') == 'submit') {
                 $urlDiscard .= '&returnto=' . urlencode('edit');
             }
             // Append section to titles and links
             if ($draft->getSection() !== null) {
                 // Detect section name
                 $lines = explode("\n", $draft->getText());
                 // If there is any content in the section
                 if (count($lines) > 0) {
                     $htmlTitle .= '#' . htmlspecialchars(trim(trim(substr($lines[0], 0, 255), '=')));
                 }
                 // Modify article link and title
                 $urlLoad .= '&section=' . urlencode($draft->getSection());
                 $urlDiscard .= '&section=' . urlencode($draft->getSection());
             }
             // Build XML
             $wgOut->addHTML(Xml::openElement('tr'));
             $wgOut->addHTML(Xml::openElement('td'));
             $wgOut->addHTML(Xml::element('a', array('href' => $urlLoad, 'style' => 'font-weight:' . ($currentDraft->getID() == $draft->getID() ? 'bold' : 'normal')), $htmlTitle));
             $wgOut->addHTML(Xml::closeElement('td'));
             $saveTime = new MWTimestamp($draft->getSaveTime());
             $wgOut->addHTML(Xml::element('td', null, $wgLang->timeanddate($saveTime->getTimestamp(), true)));
             $wgOut->addHTML(Xml::openElement('td'));
             $wgOut->addHTML(Xml::element('a', array('href' => $urlLoad), wfMessage('edit')->text()));
             $wgOut->addHTML(Xml::closeElement('td'));
             $wgOut->addHTML(Xml::openElement('td'));
             $jsClick = "if( wgDraft.getState() !== 'unchanged' )" . "return confirm('" . Xml::escapeJsString(wfMessage('drafts-view-warn')->escaped()) . "')";
             $wgOut->addHTML(Xml::element('a', array('href' => $urlDiscard, 'onclick' => $jsClick), wfMessage('drafts-view-discard')->text()));
             $wgOut->addHTML(Xml::closeElement('td'));
             $wgOut->addHTML(Xml::closeElement('tr'));
         }
         $wgOut->addHTML(Xml::closeElement('table'));
         // Return number of drafts
         return count($drafts);
     }
     return 0;
 }
Пример #10
0
 /**
  * Test requesting an invalid output format.
  * @expectedException TimestampException
  */
 function testInvalidOutput()
 {
     $timestamp = new MWTimestamp('1343761268');
     $timestamp->getTimestamp(98);
 }
 /**
  * formatDate handler
  */
 function formatDate($lang, $args)
 {
     $this->checkType('formatDate', 1, $args[0], 'string');
     $this->checkTypeOptional('formatDate', 2, $args[1], 'string', '');
     $this->checkTypeOptional('formatDate', 3, $args[2], 'boolean', false);
     list($format, $date, $local) = $args;
     $langcode = $lang->getCode();
     if ($date === '') {
         $cacheKey = $this->getParserOptions()->getTimestamp();
         $timestamp = new MWTimestamp($cacheKey);
         $date = $timestamp->getTimestamp(TS_ISO_8601);
         $useTTL = true;
     } else {
         # Correct for DateTime interpreting 'XXXX' as XX:XX o'clock
         if (preg_match('/^[0-9]{4}$/', $date)) {
             $date = '00:00 ' . $date;
         }
         $cacheKey = $date;
         $useTTL = false;
     }
     if (isset($this->timeCache[$format][$cacheKey][$langcode][$local])) {
         $ttl = $this->timeCache[$format][$cacheKey][$langcode][$local][1];
         if ($useTTL && $ttl !== null) {
             $this->getEngine()->setTTL($ttl);
         }
         return array($this->timeCache[$format][$cacheKey][$langcode][$local][0]);
     }
     # Default input timezone is UTC.
     try {
         $utc = new DateTimeZone('UTC');
         $dateObject = new DateTime($date, $utc);
     } catch (Exception $ex) {
         throw new Scribunto_LuaError("bad argument #2 to 'formatDate' (not a valid timestamp)");
     }
     # Set output timezone.
     if ($local) {
         global $wgLocaltimezone;
         if (isset($wgLocaltimezone)) {
             $tz = new DateTimeZone($wgLocaltimezone);
         } else {
             $tz = new DateTimeZone(date_default_timezone_get());
         }
     } else {
         $tz = $utc;
     }
     $dateObject->setTimezone($tz);
     # Generate timestamp
     $ts = $dateObject->format('YmdHis');
     if ($ts < 0) {
         throw new Scribunto_LuaError("mw.language:formatDate() only supports years from 0");
     } elseif ($ts >= 100000000000000.0) {
         throw new Scribunto_LuaError("mw.language:formatDate() only supports years up to 9999");
     }
     $ttl = null;
     $ret = $lang->sprintfDate($format, $ts, $tz, $ttl);
     $this->timeCache[$format][$cacheKey][$langcode][$local] = array($ret, $ttl);
     if ($useTTL && $ttl !== null) {
         $this->getEngine()->setTTL($ttl);
     }
     return array($ret);
 }
Пример #12
0
 /**
  * Reset the notification timestamp of this entry
  *
  * @param bool $force Whether to force the write query to be executed even if the
  *    page is not watched or the notification timestamp is already NULL.
  * @param int $oldid The revision id being viewed. If not given or 0, latest revision is assumed.
  * @mode int $mode WatchedItem::DEFERRED/IMMEDIATE
  */
 public function resetNotificationTimestamp($force = '', $oldid = 0, $mode = self::IMMEDIATE)
 {
     // Only loggedin user can have a watchlist
     if (wfReadOnly() || $this->mUser->isAnon() || !$this->isAllowed('editmywatchlist')) {
         return;
     }
     if ($force != 'force') {
         $this->load();
         if (!$this->watched || $this->timestamp === null) {
             return;
         }
     }
     $title = $this->getTitle();
     if (!$oldid) {
         // No oldid given, assuming latest revision; clear the timestamp.
         $notificationTimestamp = null;
     } elseif (!$title->getNextRevisionID($oldid)) {
         // Oldid given and is the latest revision for this title; clear the timestamp.
         $notificationTimestamp = null;
     } else {
         // See if the version marked as read is more recent than the one we're viewing.
         // Call load() if it wasn't called before due to $force.
         $this->load();
         if ($this->timestamp === null) {
             // This can only happen if $force is enabled.
             $notificationTimestamp = null;
         } else {
             // Oldid given and isn't the latest; update the timestamp.
             // This will result in no further notification emails being sent!
             $notificationTimestamp = Revision::getTimestampFromId($title, $oldid);
             // We need to go one second to the future because of various strict comparisons
             // throughout the codebase
             $ts = new MWTimestamp($notificationTimestamp);
             $ts->timestamp->add(new DateInterval('PT1S'));
             $notificationTimestamp = $ts->getTimestamp(TS_MW);
             if ($notificationTimestamp < $this->timestamp) {
                 if ($force != 'force') {
                     return;
                 } else {
                     // This is a little silly…
                     $notificationTimestamp = $this->timestamp;
                 }
             }
         }
     }
     // If the page is watched by the user (or may be watched), update the timestamp
     if ($mode === self::DEFERRED) {
         $job = new ActivityUpdateJob($title, array('type' => 'updateWatchlistNotification', 'userid' => $this->getUserId(), 'notifTime' => $notificationTimestamp, 'curTime' => time()));
         // Try to run this post-send
         DeferredUpdates::addCallableUpdate(function () use($job) {
             $job->run();
         });
     } else {
         $dbw = wfGetDB(DB_MASTER);
         $dbw->update('watchlist', array('wl_notificationtimestamp' => $dbw->timestampOrNull($notificationTimestamp)), $this->dbCond(), __METHOD__);
     }
     $this->timestamp = null;
 }
Пример #13
0
 /**
  * Internal helper function for converting UTC timezone to a user's timezone
  * @param $user User
  * @param $ts string
  * @param $format output format
  */
 private static function getUserLocalTime($user, $ts, $format = TS_MW)
 {
     $timestamp = new MWTimestamp($ts);
     $timestamp->offsetForUser($user);
     return $timestamp->getTimestamp($format);
 }
Пример #14
0
 private function getNotificationTimestamp(User $user, Title $title, $item, $force, $oldid)
 {
     if (!$oldid) {
         // No oldid given, assuming latest revision; clear the timestamp.
         return null;
     }
     if (!$title->getNextRevisionID($oldid)) {
         // Oldid given and is the latest revision for this title; clear the timestamp.
         return null;
     }
     if ($item === null) {
         $item = $this->loadWatchedItem($user, $title);
     }
     if (!$item) {
         // This can only happen if $force is enabled.
         return null;
     }
     // Oldid given and isn't the latest; update the timestamp.
     // This will result in no further notification emails being sent!
     // Calls Revision::getTimestampFromId in normal operation
     $notificationTimestamp = call_user_func($this->revisionGetTimestampFromIdCallback, $title, $oldid);
     // We need to go one second to the future because of various strict comparisons
     // throughout the codebase
     $ts = new MWTimestamp($notificationTimestamp);
     $ts->timestamp->add(new DateInterval('PT1S'));
     $notificationTimestamp = $ts->getTimestamp(TS_MW);
     if ($notificationTimestamp < $item->getNotificationTimestamp()) {
         if ($force != 'force') {
             return false;
         } else {
             // This is a little silly…
             return $item->getNotificationTimestamp();
         }
     }
     return $notificationTimestamp;
 }
Пример #15
0
 function showImage()
 {
     global $wgOut;
     $wgOut->disable();
     $info = $this->retrieveCaptcha();
     if ($info) {
         $timestamp = new MWTimestamp();
         $info['viewed'] = $timestamp->getTimestamp();
         $this->storeCaptcha($info);
         $salt = $info['salt'];
         $hash = $info['hash'];
         return $this->getBackend()->streamFile(array('src' => $this->imagePath($salt, $hash), 'headers' => array("Cache-Control: private, s-maxage=0, max-age=3600")))->isOK();
     }
     wfHttpError(500, 'Internal Error', 'Requested bogus captcha image');
     return false;
 }
 /**
  * @param $parser Parser
  * @param $frame PPFrame
  * @param $format string
  * @param $date string
  * @param $language string
  * @param $local string|bool
  * @return string
  */
 public static function timeCommon($parser, $frame = null, $format = '', $date = '', $language = '', $local = false)
 {
     global $wgLocaltimezone;
     self::registerClearHook();
     if ($date === '') {
         $cacheKey = $parser->getOptions()->getTimestamp();
         $timestamp = new MWTimestamp($cacheKey);
         $date = $timestamp->getTimestamp(TS_ISO_8601);
         $useTTL = true;
     } else {
         $cacheKey = $date;
         $useTTL = false;
     }
     if (isset(self::$mTimeCache[$format][$cacheKey][$language][$local])) {
         $cachedVal = self::$mTimeCache[$format][$cacheKey][$language][$local];
         if ($useTTL && $cachedVal[1] !== null && $frame && is_callable(array($frame, 'setTTL'))) {
             $frame->setTTL($cachedVal[1]);
         }
         return $cachedVal[0];
     }
     # compute the timestamp string $ts
     # PHP >= 5.2 can handle dates before 1970 or after 2038 using the DateTime object
     $invalidTime = false;
     # the DateTime constructor must be used because it throws exceptions
     # when errors occur, whereas date_create appears to just output a warning
     # that can't really be detected from within the code
     try {
         # Default input timezone is UTC.
         $utc = new DateTimeZone('UTC');
         # Correct for DateTime interpreting 'XXXX' as XX:XX o'clock
         if (preg_match('/^[0-9]{4}$/', $date)) {
             $date = '00:00 ' . $date;
         }
         # Parse date
         # UTC is a default input timezone.
         $dateObject = new DateTime($date, $utc);
         # Set output timezone.
         if ($local) {
             if (isset($wgLocaltimezone)) {
                 $tz = new DateTimeZone($wgLocaltimezone);
             } else {
                 $tz = new DateTimeZone(date_default_timezone_get());
             }
         } else {
             $tz = $utc;
         }
         $dateObject->setTimezone($tz);
         # Generate timestamp
         $ts = $dateObject->format('YmdHis');
     } catch (Exception $ex) {
         $invalidTime = true;
     }
     $ttl = null;
     # format the timestamp and return the result
     if ($invalidTime) {
         $result = '<strong class="error">' . wfMessage('pfunc_time_error')->inContentLanguage()->escaped() . '</strong>';
     } else {
         self::$mTimeChars += strlen($format);
         if (self::$mTimeChars > self::$mMaxTimeChars) {
             return '<strong class="error">' . wfMessage('pfunc_time_too_long')->inContentLanguage()->escaped() . '</strong>';
         } else {
             if ($ts < 0) {
                 // Language can't deal with BC years
                 return '<strong class="error">' . wfMessage('pfunc_time_too_small')->inContentLanguage()->escaped() . '</strong>';
             } elseif ($ts < 100000000000000) {
                 // Language can't deal with years after 9999
                 if ($language !== '' && Language::isValidBuiltInCode($language)) {
                     // use whatever language is passed as a parameter
                     $langObject = Language::factory($language);
                 } else {
                     // use wiki's content language
                     $langObject = $parser->getFunctionLang();
                     StubObject::unstub($langObject);
                     // $ttl is passed by reference, which doesn't work right on stub objects
                 }
                 $result = $langObject->sprintfDate($format, $ts, $tz, $ttl);
             } else {
                 return '<strong class="error">' . wfMessage('pfunc_time_too_big')->inContentLanguage()->escaped() . '</strong>';
             }
         }
     }
     self::$mTimeCache[$format][$cacheKey][$language][$local] = array($result, $ttl);
     if ($useTTL && $ttl !== null && $frame && is_callable(array($frame, 'setTTL'))) {
         $frame->setTTL($ttl);
     }
     return $result;
 }
Пример #17
0
 /**
  * Check selected RFC 7232 precondition headers
  *
  * RFC 7232 envisions a particular model where you send your request to "a
  * resource", and for write requests that you can read "the resource" by
  * changing the method to GET. When the API receives a GET request, it
  * works out even though "the resource" from RFC 7232's perspective might
  * be many resources from MediaWiki's perspective. But it totally fails for
  * a POST, since what HTTP sees as "the resource" is probably just
  * "/api.php" with all the interesting bits in the body.
  *
  * Therefore, we only support RFC 7232 precondition headers for GET (and
  * HEAD). That means we don't need to bother with If-Match and
  * If-Unmodified-Since since they only apply to modification requests.
  *
  * And since we don't support Range, If-Range is ignored too.
  *
  * @since 1.26
  * @param ApiBase $module Api module being used
  * @return bool True on success, false should exit immediately
  */
 protected function checkConditionalRequestHeaders($module)
 {
     if ($this->mInternalMode) {
         // No headers to check in internal mode
         return true;
     }
     if ($this->getRequest()->getMethod() !== 'GET' && $this->getRequest()->getMethod() !== 'HEAD') {
         // Don't check POSTs
         return true;
     }
     $return304 = false;
     $ifNoneMatch = array_diff($this->getRequest()->getHeader('If-None-Match', WebRequest::GETHEADER_LIST) ?: array(), array(''));
     if ($ifNoneMatch) {
         if ($ifNoneMatch === array('*')) {
             // API responses always "exist"
             $etag = '*';
         } else {
             $etag = $module->getConditionalRequestData('etag');
         }
     }
     if ($ifNoneMatch && $etag !== null) {
         $test = substr($etag, 0, 2) === 'W/' ? substr($etag, 2) : $etag;
         $match = array_map(function ($s) {
             return substr($s, 0, 2) === 'W/' ? substr($s, 2) : $s;
         }, $ifNoneMatch);
         $return304 = in_array($test, $match, true);
     } else {
         $value = trim($this->getRequest()->getHeader('If-Modified-Since'));
         // Some old browsers sends sizes after the date, like this:
         //  Wed, 20 Aug 2003 06:51:19 GMT; length=5202
         // Ignore that.
         $i = strpos($value, ';');
         if ($i !== false) {
             $value = trim(substr($value, 0, $i));
         }
         if ($value !== '') {
             try {
                 $ts = new MWTimestamp($value);
                 if ($ts->getTimestamp(TS_RFC2822) === $value || $ts->format('l, d-M-y H:i:s') . ' GMT' === $value || $ts->format('D M j H:i:s Y') === $value || $ts->format('D M  j H:i:s Y') === $value) {
                     $lastMod = $module->getConditionalRequestData('last-modified');
                     if ($lastMod !== null) {
                         // Mix in some MediaWiki modification times
                         $modifiedTimes = array('page' => $lastMod, 'user' => $this->getUser()->getTouched(), 'epoch' => $this->getConfig()->get('CacheEpoch'));
                         if ($this->getConfig()->get('UseSquid')) {
                             // T46570: the core page itself may not change, but resources might
                             $modifiedTimes['sepoch'] = wfTimestamp(TS_MW, time() - $this->getConfig()->get('SquidMaxage'));
                         }
                         Hooks::run('OutputPageCheckLastModified', array(&$modifiedTimes));
                         $lastMod = max($modifiedTimes);
                         $return304 = wfTimestamp(TS_MW, $lastMod) <= $ts->getTimestamp(TS_MW);
                     }
                 }
             } catch (TimestampException $e) {
                 // Invalid timestamp, ignore it
             }
         }
     }
     if ($return304) {
         $this->getRequest()->response()->statusHeader(304);
         // Avoid outputting the compressed representation of a zero-length body
         MediaWiki\suppressWarnings();
         ini_set('zlib.output_compression', 0);
         MediaWiki\restoreWarnings();
         wfClearOutputBuffers();
         return false;
     }
     return true;
 }
 public function testApproveTimestamp()
 {
     $t = new ModerationTestsuite();
     $entry = $t->getSampleEntry();
     $TEST_TIME_CHANGE = '6 hours';
     $ACCEPTABLE_DIFFERENCE = 300;
     # in seconds
     $ts = new MWTimestamp(time());
     $ts->timestamp->modify('-' . $TEST_TIME_CHANGE);
     $dbw = wfGetDB(DB_MASTER);
     $dbw->update('moderation', array('mod_timestamp' => $ts->getTimestamp(TS_MW)), array('mod_id' => $entry->id), __METHOD__);
     $rev = $this->tryToApprove($t, $entry);
     # Page history should mention the time when edit was made,
     # not when it was approved.
     $expected = $ts->getTimestamp(TS_ISO_8601);
     $this->assertEquals($expected, $rev['timestamp'], "testApproveTimestamp(): approved edit has incorrect timestamp in the page history");
     # RecentChanges should mention the time when the edit was
     # approved, so that it won't "appear in the past", confusing
     # those who read RecentChanges.
     $ret = $t->query(array('action' => 'query', 'list' => 'recentchanges', 'rcprop' => 'timestamp', 'rclimit' => 1, 'rcuser' => $t->lastEdit['User']));
     $rc_timestamp = $ret['query']['recentchanges'][0]['timestamp'];
     $this->assertNotEquals($expected, $rc_timestamp, "testApproveTimestamp(): approved edit has \"appeared in the past\" in the RecentChanges");
     # Does the time in RecentChanges match the time of approval?
     #
     # NOTE: we don't know the time of approval to the second, so
     # string comparison can't be used. Difference can be seconds
     # or even minutes (if system time is off).
     $ts->timestamp->modify('+' . $TEST_TIME_CHANGE);
     $expected = $ts->getTimestamp(TS_UNIX);
     $ts_actual = new MWTimestamp($rc_timestamp);
     $actual = $ts_actual->getTimestamp(TS_UNIX);
     $this->assertLessThan($ACCEPTABLE_DIFFERENCE, abs($expected - $actual), "testApproveTimestamp(): timestamp of approved edit in RecentChanges is too different from the time of approval");
 }