/**
  * Wrap and format the file's comment block, if the current
  * user is allowed to view it.
  *
  * @return string HTML
  */
 protected function getComment()
 {
     if ($this->file->userCan(File::DELETED_COMMENT, $this->list->getUser())) {
         $block = Linker::commentBlock($this->file->getDescription());
     } else {
         $block = ' ' . $this->list->msg('rev-deleted-comment')->escaped();
     }
     if ($this->file->isDeleted(File::DELETED_COMMENT)) {
         return "<span class=\"history-deleted\">{$block}</span>";
     }
     return $block;
 }
 /**
  * @param File $file
  * @param bool $dumpContents
  * @return string
  */
 function writeUpload($file, $dumpContents = false)
 {
     if ($file->isOld()) {
         $archiveName = "      " . Xml::element('archivename', null, $file->getArchiveName()) . "\n";
     } else {
         $archiveName = '';
     }
     if ($dumpContents) {
         $be = $file->getRepo()->getBackend();
         # Dump file as base64
         # Uses only XML-safe characters, so does not need escaping
         # @todo Too bad this loads the contents into memory (script might swap)
         $contents = '      <contents encoding="base64">' . chunk_split(base64_encode($be->getFileContents(array('src' => $file->getPath())))) . "      </contents>\n";
     } else {
         $contents = '';
     }
     if ($file->isDeleted(File::DELETED_COMMENT)) {
         $comment = Xml::element('comment', array('deleted' => 'deleted'));
     } else {
         $comment = Xml::elementClean('comment', null, $file->getDescription());
     }
     return "    <upload>\n" . $this->writeTimestamp($file->getTimestamp()) . $this->writeContributor($file->getUser('id'), $file->getUser('text')) . "      " . $comment . "\n" . "      " . Xml::element('filename', null, $file->getName()) . "\n" . $archiveName . "      " . Xml::element('src', null, $file->getCanonicalURL()) . "\n" . "      " . Xml::element('size', null, $file->getSize()) . "\n" . "      " . Xml::element('sha1base36', null, $file->getSha1()) . "\n" . "      " . Xml::element('rel', null, $file->getRel()) . "\n" . $contents . "    </upload>\n";
 }
 /**
  * Fetch file upload comment if it's available to this user
  *
  * @param File|ArchivedFile $file
  * @return string HTML fragment
  */
 function getFileComment($file)
 {
     if (!$file->userCan(File::DELETED_COMMENT, $this->getUser())) {
         return '<span class="history-deleted"><span class="comment">' . $this->msg('rev-deleted-comment')->escaped() . '</span></span>';
     }
     $link = Linker::commentBlock($file->getRawDescription());
     if ($file->isDeleted(File::DELETED_COMMENT)) {
         $link = '<span class="history-deleted">' . $link . '</span>';
     }
     return $link;
 }
 /**
  * Get result information for an image revision
  *
  * @param File $file
  * @param array $prop Array of properties to get (in the keys)
  * @param ApiResult $result
  * @param array $thumbParams Containing 'width' and 'height' items, or null
  * @param array|bool|string $opts Options for data fetching.
  *   This is an array consisting of the keys:
  *    'version': The metadata version for the metadata option
  *    'language': The language for extmetadata property
  *    'multilang': Return all translations in extmetadata property
  *    'revdelUser': User to use when checking whether to show revision-deleted fields.
  * @return array Result array
  */
 static function getInfo($file, $prop, $result, $thumbParams = null, $opts = false)
 {
     global $wgContLang;
     $anyHidden = false;
     if (!$opts || is_string($opts)) {
         $opts = array('version' => $opts ?: 'latest', 'language' => $wgContLang, 'multilang' => false, 'extmetadatafilter' => array(), 'revdelUser' => null);
     }
     $version = $opts['version'];
     $vals = array(ApiResult::META_TYPE => 'assoc');
     // Timestamp is shown even if the file is revdelete'd in interface
     // so do same here.
     if (isset($prop['timestamp'])) {
         $vals['timestamp'] = wfTimestamp(TS_ISO_8601, $file->getTimestamp());
     }
     // Handle external callers who don't pass revdelUser
     if (isset($opts['revdelUser']) && $opts['revdelUser']) {
         $revdelUser = $opts['revdelUser'];
         $canShowField = function ($field) use($file, $revdelUser) {
             return $file->userCan($field, $revdelUser);
         };
     } else {
         $canShowField = function ($field) use($file) {
             return !$file->isDeleted($field);
         };
     }
     $user = isset($prop['user']);
     $userid = isset($prop['userid']);
     if ($user || $userid) {
         if ($file->isDeleted(File::DELETED_USER)) {
             $vals['userhidden'] = true;
             $anyHidden = true;
         }
         if ($canShowField(File::DELETED_USER)) {
             if ($user) {
                 $vals['user'] = $file->getUser();
             }
             if ($userid) {
                 $vals['userid'] = $file->getUser('id');
             }
             if (!$file->getUser('id')) {
                 $vals['anon'] = true;
             }
         }
     }
     // This is shown even if the file is revdelete'd in interface
     // so do same here.
     if (isset($prop['size']) || isset($prop['dimensions'])) {
         $vals['size'] = intval($file->getSize());
         $vals['width'] = intval($file->getWidth());
         $vals['height'] = intval($file->getHeight());
         $pageCount = $file->pageCount();
         if ($pageCount !== false) {
             $vals['pagecount'] = $pageCount;
         }
         // length as in how many seconds long a video is.
         $length = $file->getLength();
         if ($length) {
             // Call it duration, because "length" can be ambiguous.
             $vals['duration'] = (double) $length;
         }
     }
     $pcomment = isset($prop['parsedcomment']);
     $comment = isset($prop['comment']);
     if ($pcomment || $comment) {
         if ($file->isDeleted(File::DELETED_COMMENT)) {
             $vals['commenthidden'] = true;
             $anyHidden = true;
         }
         if ($canShowField(File::DELETED_COMMENT)) {
             if ($pcomment) {
                 $vals['parsedcomment'] = Linker::formatComment($file->getDescription(File::RAW), $file->getTitle());
             }
             if ($comment) {
                 $vals['comment'] = $file->getDescription(File::RAW);
             }
         }
     }
     $canonicaltitle = isset($prop['canonicaltitle']);
     $url = isset($prop['url']);
     $sha1 = isset($prop['sha1']);
     $meta = isset($prop['metadata']);
     $extmetadata = isset($prop['extmetadata']);
     $commonmeta = isset($prop['commonmetadata']);
     $mime = isset($prop['mime']);
     $mediatype = isset($prop['mediatype']);
     $archive = isset($prop['archivename']);
     $bitdepth = isset($prop['bitdepth']);
     $uploadwarning = isset($prop['uploadwarning']);
     if ($uploadwarning) {
         $vals['html'] = SpecialUpload::getExistsWarning(UploadBase::getExistsWarning($file));
     }
     if ($file->isDeleted(File::DELETED_FILE)) {
         $vals['filehidden'] = true;
         $anyHidden = true;
     }
     if ($anyHidden && $file->isDeleted(File::DELETED_RESTRICTED)) {
         $vals['suppressed'] = true;
     }
     if (!$canShowField(File::DELETED_FILE)) {
         //Early return, tidier than indenting all following things one level
         return $vals;
     }
     if ($canonicaltitle) {
         $vals['canonicaltitle'] = $file->getTitle()->getPrefixedText();
     }
     if ($url) {
         if (!is_null($thumbParams)) {
             $mto = $file->transform($thumbParams);
             self::$transformCount++;
             if ($mto && !$mto->isError()) {
                 $vals['thumburl'] = wfExpandUrl($mto->getUrl(), PROTO_CURRENT);
                 // bug 23834 - If the URL's are the same, we haven't resized it, so shouldn't give the wanted
                 // thumbnail sizes for the thumbnail actual size
                 if ($mto->getUrl() !== $file->getUrl()) {
                     $vals['thumbwidth'] = intval($mto->getWidth());
                     $vals['thumbheight'] = intval($mto->getHeight());
                 } else {
                     $vals['thumbwidth'] = intval($file->getWidth());
                     $vals['thumbheight'] = intval($file->getHeight());
                 }
                 if (isset($prop['thumbmime']) && $file->getHandler()) {
                     list(, $mime) = $file->getHandler()->getThumbType($mto->getExtension(), $file->getMimeType(), $thumbParams);
                     $vals['thumbmime'] = $mime;
                 }
             } elseif ($mto && $mto->isError()) {
                 $vals['thumberror'] = $mto->toText();
             }
         }
         $vals['url'] = wfExpandUrl($file->getFullURL(), PROTO_CURRENT);
         $vals['descriptionurl'] = wfExpandUrl($file->getDescriptionUrl(), PROTO_CURRENT);
     }
     if ($sha1) {
         $vals['sha1'] = wfBaseConvert($file->getSha1(), 36, 16, 40);
     }
     if ($meta) {
         wfSuppressWarnings();
         $metadata = unserialize($file->getMetadata());
         wfRestoreWarnings();
         if ($metadata && $version !== 'latest') {
             $metadata = $file->convertMetadataVersion($metadata, $version);
         }
         $vals['metadata'] = $metadata ? self::processMetaData($metadata, $result) : null;
     }
     if ($commonmeta) {
         $metaArray = $file->getCommonMetaArray();
         $vals['commonmetadata'] = $metaArray ? self::processMetaData($metaArray, $result) : array();
     }
     if ($extmetadata) {
         // Note, this should return an array where all the keys
         // start with a letter, and all the values are strings.
         // Thus there should be no issue with format=xml.
         $format = new FormatMetadata();
         $format->setSingleLanguage(!$opts['multilang']);
         $format->getContext()->setLanguage($opts['language']);
         $extmetaArray = $format->fetchExtendedMetadata($file);
         if ($opts['extmetadatafilter']) {
             $extmetaArray = array_intersect_key($extmetaArray, array_flip($opts['extmetadatafilter']));
         }
         $vals['extmetadata'] = $extmetaArray;
     }
     if ($mime) {
         $vals['mime'] = $file->getMimeType();
     }
     if ($mediatype) {
         $vals['mediatype'] = $file->getMediaType();
     }
     if ($archive && $file->isOld()) {
         $vals['archivename'] = $file->getArchiveName();
     }
     if ($bitdepth) {
         $vals['bitdepth'] = $file->getBitDepth();
     }
     return $vals;
 }
Example #5
0
 /**
  * @param File $file
  * @returns string
  */
 private function fileLine($file)
 {
     global $wgLang, $wgTitle;
     $target = $this->page->getPrefixedText();
     $date = $wgLang->timeanddate($file->getTimestamp(), true);
     $del = '';
     # Hidden files...
     if ($file->isDeleted(File::DELETED_FILE)) {
         $del = ' <tt>' . wfMsgHtml('deletedrev') . '</tt>';
         if (!$file->userCan(File::DELETED_FILE)) {
             $pageLink = $date;
         } else {
             $pageLink = $this->skin->makeKnownLinkObj($wgTitle, $date, "target={$target}&file={$file->sha1}." . $file->getExtension());
         }
         $pageLink = '<span class="history-deleted">' . $pageLink . '</span>';
         # Regular files...
     } else {
         $url = $file->getUrlRel();
         $pageLink = "<a href=\"{$url}\">{$date}</a>";
     }
     $data = wfMsg('widthheight', $wgLang->formatNum($file->getWidth()), $wgLang->formatNum($file->getHeight())) . ' (' . wfMsgExt('nbytes', 'parsemag', $wgLang->formatNum($file->getSize())) . ')';
     $data = htmlspecialchars($data);
     return "<li>{$pageLink} " . $this->fileUserTools($file) . " {$data} " . $this->fileComment($file) . "{$del}</li>";
 }
Example #6
0
 /**
  * Get an array of extended metadata. (See the imageinfo API for format.)
  *
  * @param File $file File to use
  * @return array [<property name> => ['value' => <value>]], or [] on error
  * @since 1.23
  */
 public function fetchExtendedMetadata(File $file)
 {
     $cache = ObjectCache::getMainWANInstance();
     // If revision deleted, exit immediately
     if ($file->isDeleted(File::DELETED_FILE)) {
         return [];
     }
     $cacheKey = wfMemcKey('getExtendedMetadata', $this->getLanguage()->getCode(), (int) $this->singleLang, $file->getSha1());
     $cachedValue = $cache->get($cacheKey);
     if ($cachedValue && Hooks::run('ValidateExtendedMetadataCache', [$cachedValue['timestamp'], $file])) {
         $extendedMetadata = $cachedValue['data'];
     } else {
         $maxCacheTime = $file instanceof ForeignAPIFile ? 60 * 60 * 12 : 60 * 60 * 24 * 30;
         $fileMetadata = $this->getExtendedMetadataFromFile($file);
         $extendedMetadata = $this->getExtendedMetadataFromHook($file, $fileMetadata, $maxCacheTime);
         if ($this->singleLang) {
             $this->resolveMultilangMetadata($extendedMetadata);
         }
         $this->discardMultipleValues($extendedMetadata);
         // Make sure the metadata won't break the API when an XML format is used.
         // This is an API-specific function so it would be cleaner to call it from
         // outside fetchExtendedMetadata, but this way we don't need to redo the
         // computation on a cache hit.
         $this->sanitizeArrayForAPI($extendedMetadata);
         $valueToCache = ['data' => $extendedMetadata, 'timestamp' => wfTimestampNow()];
         $cache->set($cacheKey, $valueToCache, $maxCacheTime);
     }
     return $extendedMetadata;
 }
 /**
  * @param File $file
  * @return string
  */
 protected function getThumbForLine($file)
 {
     $lang = $this->getLanguage();
     $user = $this->getUser();
     if ($file->allowInlineDisplay() && $file->userCan(File::DELETED_FILE, $user) && !$file->isDeleted(File::DELETED_FILE)) {
         $params = ['width' => '120', 'height' => '120'];
         $timestamp = wfTimestamp(TS_MW, $file->getTimestamp());
         $thumbnail = $file->transform($params);
         $options = ['alt' => $this->msg('filehist-thumbtext', $lang->userTimeAndDate($timestamp, $user), $lang->userDate($timestamp, $user), $lang->userTime($timestamp, $user))->text(), 'file-link' => true];
         if (!$thumbnail) {
             return $this->msg('filehist-nothumb')->escaped();
         }
         return $thumbnail->toHtml($options);
     } else {
         return $this->msg('filehist-nothumb')->escaped();
     }
 }
Example #8
0
 /**
  * Wrap and format the file's comment block, if the current
  * user is allowed to view it.
  *
  * @return string HTML
  */
 protected function getComment()
 {
     if ($this->file->userCan(File::DELETED_COMMENT)) {
         $block = Linker::commentBlock($this->file->description);
     } else {
         $block = ' ' . wfMsgHtml('rev-deleted-comment');
     }
     if ($this->file->isDeleted(File::DELETED_COMMENT)) {
         return "<span class=\"history-deleted\">{$block}</span>";
     }
     return $block;
 }
Example #9
0
 /**
  * Get an array of extended metadata. (See the imageinfo API for format.)
  *
  * @param File $file File to use
  * @return array [<property name> => ['value' => <value>]], or [] on error
  * @since 1.23
  */
 public function fetchExtendedMetadata(File $file)
 {
     global $wgMemc;
     wfProfileIn(__METHOD__);
     // If revision deleted, exit immediately
     if ($file->isDeleted(File::DELETED_FILE)) {
         wfProfileOut(__METHOD__);
         return array();
     }
     $cacheKey = wfMemcKey('getExtendedMetadata', $this->getLanguage()->getCode(), (int) $this->singleLang, $file->getSha1());
     $cachedValue = $wgMemc->get($cacheKey);
     if ($cachedValue && wfRunHooks('ValidateExtendedMetadataCache', array($cachedValue['timestamp'], $file))) {
         $extendedMetadata = $cachedValue['data'];
     } else {
         $maxCacheTime = $file instanceof ForeignAPIFile ? 60 * 60 * 12 : 60 * 60 * 24 * 30;
         $fileMetadata = $this->getExtendedMetadataFromFile($file);
         $extendedMetadata = $this->getExtendedMetadataFromHook($file, $fileMetadata, $maxCacheTime);
         if ($this->singleLang) {
             $this->resolveMultilangMetadata($extendedMetadata);
         }
         // Make sure the metadata won't break the API when an XML format is used.
         // This is an API-specific function so it would be cleaner to call it from
         // outside fetchExtendedMetadata, but this way we don't need to redo the
         // computation on a cache hit.
         $this->sanitizeArrayForXml($extendedMetadata);
         $valueToCache = array('data' => $extendedMetadata, 'timestamp' => wfTimestampNow());
         $wgMemc->set($cacheKey, $valueToCache, $maxCacheTime);
     }
     wfProfileOut(__METHOD__);
     return $extendedMetadata;
 }