/** * Get a file and its metadata from the stash. * * @param $key String: key under which file information is stored * @param $noAuth Boolean (optional) Don't check authentication. Used by maintenance scripts. * @throws UploadStashFileNotFoundException * @throws UploadStashNotLoggedInException * @throws UploadStashWrongOwnerException * @throws UploadStashBadPathException * @return UploadStashFile */ public function getFile($key, $noAuth = false) { if (!preg_match(self::KEY_FORMAT_REGEX, $key)) { throw new UploadStashBadPathException("key '{$key}' is not in a proper format"); } if (!$noAuth) { if (!$this->isLoggedIn) { throw new UploadStashNotLoggedInException(__METHOD__ . ' No user is logged in, files must belong to users'); } } $dbr = $this->repo->getSlaveDb(); if (!isset($this->fileMetadata[$key])) { // try this first. if it fails to find the row, check for lag, wait, try again. if its still missing, throw an exception. // this more complex solution keeps things moving for page loads with many requests // (ie. validating image ownership) when replag is high if (!$this->fetchFileMetadata($key)) { $lag = $dbr->getLag(); if ($lag > 0 && $lag <= self::MAX_LAG) { // if there's not too much replication lag, just wait for the slave to catch up to our last insert. sleep(ceil($lag)); } elseif ($lag > self::MAX_LAG) { // that's a lot of lag to introduce into the middle of the UI. throw new UploadStashMaxLagExceededException('Couldn\'t load stashed file metadata, and replication lag is above threshold: (MAX_LAG=' . self::MAX_LAG . ')'); } // now that the waiting has happened, try again $this->fetchFileMetadata($key); } if (!isset($this->fileMetadata[$key])) { throw new UploadStashFileNotFoundException("key '{$key}' not found in stash"); } // create $this->files[$key] $this->initFile($key); // fetch fileprops $path = $this->fileMetadata[$key]['us_path']; if ($this->repo->isVirtualUrl($path)) { $path = $this->repo->resolveVirtualUrl($path); } $this->fileProps[$key] = File::getPropsFromPath($path); } if (!$this->files[$key]->exists()) { wfDebug(__METHOD__ . " tried to get file at {$key}, but it doesn't exist\n"); throw new UploadStashBadPathException("path doesn't exist"); } if (!$noAuth) { if ($this->fileMetadata[$key]['us_user'] != $this->userId) { throw new UploadStashWrongOwnerException("This file ({$key}) doesn't belong to the current user."); } } return $this->files[$key]; }
/** * Upload a file and record it in the DB * @param string $srcPath source storage path, virtual URL, or filesystem path * @param string $comment upload description * @param string $pageText text to use for the new description page, * if a new description page is created * @param $flags Integer|bool: flags for publish() * @param array|bool $props File properties, if known. This can be used to reduce the * upload time when uploading virtual URLs for which the file info * is already known * @param string|bool $timestamp timestamp for img_timestamp, or false to use the current time * @param $user User|null: User object or null to use $wgUser * * @return FileRepoStatus object. On success, the value member contains the * archive name, or an empty string if it was a new file. */ function upload( $srcPath, $comment, $pageText, $flags = 0, $props = false, $timestamp = false, $user = null ) { global $wgContLang; if ( $this->getRepo()->getReadOnlyReason() !== false ) { return $this->readOnlyFatalStatus(); } if ( !$props ) { wfProfileIn( __METHOD__ . '-getProps' ); if ( $this->repo->isVirtualUrl( $srcPath ) || FileBackend::isStoragePath( $srcPath ) ) { $props = $this->repo->getFileProps( $srcPath ); } else { $props = FSFile::getPropsFromPath( $srcPath ); } wfProfileOut( __METHOD__ . '-getProps' ); } $options = array(); $handler = MediaHandler::getHandler( $props['mime'] ); if ( $handler ) { $options['headers'] = $handler->getStreamHeaders( $props['metadata'] ); } else { $options['headers'] = array(); } // Trim spaces on user supplied text $comment = trim( $comment ); // truncate nicely or the DB will do it for us // non-nicely (dangling multi-byte chars, non-truncated version in cache). $comment = $wgContLang->truncate( $comment, 255 ); $this->lock(); // begin $status = $this->publish( $srcPath, $flags, $options ); if ( $status->successCount > 0 ) { # Essentially we are displacing any existing current file and saving # a new current file at the old location. If just the first succeeded, # we still need to displace the current DB entry and put in a new one. if ( !$this->recordUpload2( $status->value, $comment, $pageText, $props, $timestamp, $user ) ) { $status->fatal( 'filenotfound', $srcPath ); } } $this->unlock(); // done return $status; }
/** * Get a file and its metadata from the stash. * The noAuth param is a bit janky but is required for automated scripts which clean out the stash. * * @param $key String: key under which file information is stored * @param $noAuth Boolean (optional) Don't check authentication. Used by maintenance scripts. * @throws UploadStashFileNotFoundException * @throws UploadStashNotLoggedInException * @throws UploadStashWrongOwnerException * @throws UploadStashBadPathException * @return UploadStashFile */ public function getFile($key, $noAuth = false) { if (!preg_match(self::KEY_FORMAT_REGEX, $key)) { throw new UploadStashBadPathException("key '{$key}' is not in a proper format"); } if (!$noAuth) { if (!$this->isLoggedIn) { throw new UploadStashNotLoggedInException(__METHOD__ . ' No user is logged in, files must belong to users'); } } if (!isset($this->fileMetadata[$key])) { if (!$this->fetchFileMetadata($key)) { // If nothing was received, it's likely due to replication lag. Check the master to see if the record is there. $this->fetchFileMetadata($key, DB_MASTER); } if (!isset($this->fileMetadata[$key])) { throw new UploadStashFileNotFoundException("key '{$key}' not found in stash"); } // create $this->files[$key] $this->initFile($key); // fetch fileprops $path = $this->fileMetadata[$key]['us_path']; if ($this->repo->isVirtualUrl($path)) { $path = $this->repo->resolveVirtualUrl($path); } $this->fileProps[$key] = File::getPropsFromPath($path); } if (!$this->files[$key]->exists()) { wfDebug(__METHOD__ . " tried to get file at {$key}, but it doesn't exist\n"); throw new UploadStashBadPathException("path doesn't exist"); } if (!$noAuth) { if ($this->fileMetadata[$key]['us_user'] != $this->userId) { throw new UploadStashWrongOwnerException("This file ({$key}) doesn't belong to the current user."); } } return $this->files[$key]; }