/**
  * @throws MWException
  * @param Title $title
  * @param int $id
  * @param string $key
  */
 function __construct($title, $id = 0, $key = '')
 {
     $this->id = -1;
     $this->title = false;
     $this->name = false;
     $this->group = 'deleted';
     // needed for direct use of constructor
     $this->key = '';
     $this->size = 0;
     $this->bits = 0;
     $this->width = 0;
     $this->height = 0;
     $this->metadata = '';
     $this->mime = "unknown/unknown";
     $this->media_type = '';
     $this->description = '';
     $this->user = 0;
     $this->user_text = '';
     $this->timestamp = null;
     $this->deleted = 0;
     $this->dataLoaded = false;
     $this->exists = false;
     $this->sha1 = '';
     if ($title instanceof Title) {
         $this->title = File::normalizeTitle($title, 'exception');
         $this->name = $title->getDBkey();
     }
     if ($id) {
         $this->id = $id;
     }
     if ($key) {
         $this->key = $key;
     }
     if (!$id && !$key && !$title instanceof Title) {
         throw new MWException("No specifications provided to ArchivedFile constructor.");
     }
 }
 /**
  * Create an UnregisteredLocalFile based on a path or a (title,repo) pair.
  * A FileRepo object is not required here, unlike most other File classes.
  * 
  * @throws MWException
  * @param $title Title|false
  * @param $repo FileRepo
  * @param $path string
  * @param $mime string
  */
 function __construct($title = false, $repo = false, $path = false, $mime = false)
 {
     if (!($title && $repo) && !$path) {
         throw new MWException(__METHOD__ . ': not enough parameters, must specify title and repo, or a full path');
     }
     if ($title instanceof Title) {
         $this->title = File::normalizeTitle($title, 'exception');
         $this->name = $repo->getNameFromTitle($title);
     } else {
         $this->name = basename($path);
         $this->title = File::normalizeTitle($this->name, 'exception');
     }
     $this->repo = $repo;
     if ($path) {
         $this->path = $path;
     } else {
         $this->assertRepoDefined();
         $this->path = $repo->getRootDirectory() . '/' . $repo->getHashPath($this->name) . $this->name;
     }
     if ($mime) {
         $this->mime = $mime;
     }
     $this->dims = array();
 }
Example #3
0
 public function findFiles(array $items, $flags = 0)
 {
     $finalFiles = array();
     // map of (DB key => corresponding File) for matches
     $searchSet = array();
     // map of (normalized DB key => search params)
     foreach ($items as $item) {
         if (is_array($item)) {
             $title = File::normalizeTitle($item['title']);
             if ($title) {
                 $searchSet[$title->getDBkey()] = $item;
             }
         } else {
             $title = File::normalizeTitle($item);
             if ($title) {
                 $searchSet[$title->getDBkey()] = array();
             }
         }
     }
     $fileMatchesSearch = function (File $file, array $search) {
         // Note: file name comparison done elsewhere (to handle redirects)
         $user = !empty($search['private']) && $search['private'] instanceof User ? $search['private'] : null;
         return $file->exists() && (empty($search['time']) && !$file->isOld() || !empty($search['time']) && $search['time'] === $file->getTimestamp()) && (!empty($search['private']) || !$file->isDeleted(File::DELETED_FILE)) && $file->userCan(File::DELETED_FILE, $user);
     };
     $that = $this;
     $applyMatchingFiles = function (ResultWrapper $res, &$searchSet, &$finalFiles) use($that, $fileMatchesSearch, $flags) {
         global $wgContLang;
         $info = $that->getInfo();
         foreach ($res as $row) {
             $file = $that->newFileFromRow($row);
             // There must have been a search for this DB key, but this has to handle the
             // cases were title capitalization is different on the client and repo wikis.
             $dbKeysLook = array(strtr($file->getName(), ' ', '_'));
             if (!empty($info['initialCapital'])) {
                 // Search keys for "hi.png" and "Hi.png" should use the "Hi.png file"
                 $dbKeysLook[] = $wgContLang->lcfirst($file->getName());
             }
             foreach ($dbKeysLook as $dbKey) {
                 if (isset($searchSet[$dbKey]) && $fileMatchesSearch($file, $searchSet[$dbKey])) {
                     $finalFiles[$dbKey] = $flags & FileRepo::NAME_AND_TIME_ONLY ? array('title' => $dbKey, 'timestamp' => $file->getTimestamp()) : $file;
                     unset($searchSet[$dbKey]);
                 }
             }
         }
     };
     $dbr = $this->getSlaveDB();
     // Query image table
     $imgNames = array();
     foreach (array_keys($searchSet) as $dbKey) {
         $imgNames[] = $this->getNameFromTitle(File::normalizeTitle($dbKey));
     }
     if (count($imgNames)) {
         $res = $dbr->select('image', LocalFile::selectFields(), array('img_name' => $imgNames), __METHOD__);
         $applyMatchingFiles($res, $searchSet, $finalFiles);
     }
     // Query old image table
     $oiConds = array();
     // WHERE clause array for each file
     foreach ($searchSet as $dbKey => $search) {
         if (isset($search['time'])) {
             $oiConds[] = $dbr->makeList(array('oi_name' => $this->getNameFromTitle(File::normalizeTitle($dbKey)), 'oi_timestamp' => $dbr->timestamp($search['time'])), LIST_AND);
         }
     }
     if (count($oiConds)) {
         $res = $dbr->select('oldimage', OldLocalFile::selectFields(), $dbr->makeList($oiConds, LIST_OR), __METHOD__);
         $applyMatchingFiles($res, $searchSet, $finalFiles);
     }
     // Check for redirects...
     foreach ($searchSet as $dbKey => $search) {
         if (!empty($search['ignoreRedirect'])) {
             continue;
         }
         $title = File::normalizeTitle($dbKey);
         $redir = $this->checkRedirect($title);
         // hopefully hits memcached
         if ($redir && $redir->getNamespace() == NS_FILE) {
             $file = $this->newFile($redir);
             if ($file && $fileMatchesSearch($file, $search)) {
                 $file->redirectedFrom($title->getDBkey());
                 if ($flags & FileRepo::NAME_AND_TIME_ONLY) {
                     $finalFiles[$dbKey] = array('title' => $file->getTitle()->getDBkey(), 'timestamp' => $file->getTimestamp());
                 } else {
                     $finalFiles[$dbKey] = $file;
                 }
             }
         }
     }
     return $finalFiles;
 }
Example #4
0
 /**
  * Find an instance of the named file created at the specified time
  * Returns false if the file does not exist. Repositories not supporting
  * version control should return false if the time is specified.
  *
  * @param $title Mixed: Title object or string
  * @param $options array Associative array of options:
  *     time:           requested time for an archived image, or false for the
  *                     current version. An image object will be returned which was
  *                     created at the specified time.
  *
  *     ignoreRedirect: If true, do not follow file redirects
  *
  *     private:        If true, return restricted (deleted) files if the current
  *                     user is allowed to view them. Otherwise, such files will not
  *                     be found.
  * @return File|false
  */
 public function findFile($title, $options = array())
 {
     $title = File::normalizeTitle($title);
     if (!$title) {
         return false;
     }
     $time = isset($options['time']) ? $options['time'] : false;
     # First try the current version of the file to see if it precedes the timestamp
     $img = $this->newFile($title);
     if (!$img) {
         return false;
     }
     if ($img->exists() && (!$time || $img->getTimestamp() == $time)) {
         return $img;
     }
     # Now try an old version of the file
     if ($time !== false) {
         $img = $this->newFile($title, $time);
         if ($img && $img->exists()) {
             if (!$img->isDeleted(File::DELETED_FILE)) {
                 return $img;
                 // always OK
             } elseif (!empty($options['private']) && $img->userCan(File::DELETED_FILE)) {
                 return $img;
             }
         }
     }
     # Now try redirects
     if (!empty($options['ignoreRedirect'])) {
         return false;
     }
     $redir = $this->checkRedirect($title);
     if ($redir && $title->getNamespace() == NS_FILE) {
         $img = $this->newFile($redir);
         if (!$img) {
             return false;
         }
         if ($img->exists()) {
             $img->redirectedFrom($title->getDBkey());
             return $img;
         }
     }
     return false;
 }
Example #5
0
 /**
  * Checks if there is a redirect named as $title
  *
  * @param $title Title of file
  * @return bool
  */
 function checkRedirect(Title $title)
 {
     global $wgMemc;
     $title = File::normalizeTitle($title, 'exception');
     $memcKey = $this->getSharedCacheKey('image_redirect', md5($title->getDBkey()));
     if ($memcKey === false) {
         $memcKey = $this->getLocalCacheKey('image_redirect', md5($title->getDBkey()));
         $expiry = 300;
         // no invalidation, 5 minutes
     } else {
         $expiry = 86400;
         // has invalidation, 1 day
     }
     $cachedValue = $wgMemc->get($memcKey);
     if ($cachedValue === ' ' || $cachedValue === '') {
         // Does not exist
         return false;
     } elseif (strval($cachedValue) !== '') {
         return Title::newFromText($cachedValue, NS_FILE);
     }
     // else $cachedValue is false or null: cache miss
     $id = $this->getArticleID($title);
     if (!$id) {
         $wgMemc->set($memcKey, " ", $expiry);
         return false;
     }
     $dbr = $this->getSlaveDB();
     $row = $dbr->selectRow('redirect', array('rd_title', 'rd_namespace'), array('rd_from' => $id), __METHOD__);
     if ($row && $row->rd_namespace == NS_FILE) {
         $targetTitle = Title::makeTitle($row->rd_namespace, $row->rd_title);
         $wgMemc->set($memcKey, $targetTitle->getDBkey(), $expiry);
         return $targetTitle;
     } else {
         $wgMemc->set($memcKey, '', $expiry);
         return false;
     }
 }
Example #6
0
 /**
  * Find many files at once.
  *
  * @param array $items An array of titles, or an array of findFile() options with
  *    the "title" option giving the title. Example:
  *
  *     $findItem = array( 'title' => $title, 'private' => true );
  *     $findBatch = array( $findItem );
  *     $repo->findFiles( $findBatch );
  *
  *    No title should appear in $items twice, as the result use titles as keys
  * @param int $flags Supports:
  *     - FileRepo::NAME_AND_TIME_ONLY : return a (search title => (title,timestamp)) map.
  *       The search title uses the input titles; the other is the final post-redirect title.
  *       All titles are returned as string DB keys and the inner array is associative.
  * @return array Map of (file name => File objects) for matches
  */
 public function findFiles(array $items, $flags = 0)
 {
     $result = array();
     foreach ($items as $item) {
         if (is_array($item)) {
             $title = $item['title'];
             $options = $item;
             unset($options['title']);
         } else {
             $title = $item;
             $options = array();
         }
         $file = $this->findFile($title, $options);
         if ($file) {
             $searchName = File::normalizeTitle($title)->getDBkey();
             // must be valid
             if ($flags & self::NAME_AND_TIME_ONLY) {
                 $result[$searchName] = array('title' => $file->getTitle()->getDBkey(), 'timestamp' => $file->getTimestamp());
             } else {
                 $result[$searchName] = $file;
             }
         }
     }
     return $result;
 }
Example #7
0
 /**
  * Search repositories for many files at once.
  *
  * @param array $items An array of titles, or an array of findFile() options with
  *    the "title" option giving the title. Example:
  *
  *     $findItem = array( 'title' => $title, 'private' => true );
  *     $findBatch = array( $findItem );
  *     $repo->findFiles( $findBatch );
  *
  *    No title should appear in $items twice, as the result use titles as keys
  * @param int $flags Supports:
  *     - FileRepo::NAME_AND_TIME_ONLY : return a (search title => (title,timestamp)) map.
  *       The search title uses the input titles; the other is the final post-redirect title.
  *       All titles are returned as string DB keys and the inner array is associative.
  * @return array Map of (file name => File objects) for matches
  *
  * @param array $inputItems
  * @param integer $flags
  * @return array
  */
 function findFiles(array $inputItems, $flags = 0)
 {
     if (!$this->reposInitialised) {
         $this->initialiseRepos();
     }
     $items = array();
     foreach ($inputItems as $item) {
         if (!is_array($item)) {
             $item = array('title' => $item);
         }
         $item['title'] = File::normalizeTitle($item['title']);
         if ($item['title']) {
             $items[$item['title']->getDBkey()] = $item;
         }
     }
     $images = $this->localRepo->findFiles($items, $flags);
     foreach ($this->foreignRepos as $repo) {
         // Remove found files from $items
         foreach ($images as $name => $image) {
             unset($items[$name]);
         }
         $images = array_merge($images, $repo->findFiles($items, $flags));
     }
     return $images;
 }