Beispiel #1
0
         } else {
             $commentText = file_get_contents($f);
             if (!$commentText) {
                 echo " Failed to load comment file {$f}, using default comment. ";
             }
         }
     }
     if (!$commentText) {
         $commentText = $comment;
     }
 }
 # Import the file
 if (isset($options['dry'])) {
     echo " publishing {$file} by '" . $wgUser->getName() . "', comment '{$commentText}'... ";
 } else {
     $mwProps = new MWFileProps(MimeMagic::singleton());
     $props = $mwProps->getPropsFromPath($file, true);
     $flags = 0;
     $publishOptions = [];
     $handler = MediaHandler::getHandler($props['mime']);
     if ($handler) {
         $publishOptions['headers'] = $handler->getStreamHeaders($props['metadata']);
     } else {
         $publishOptions['headers'] = [];
     }
     $archive = $image->publish($file, $flags, $publishOptions);
     if (!$archive->isGood()) {
         echo "failed. (" . $archive->getWikiText(false, false, 'en') . ")\n";
         $failed++;
         continue;
     }
Beispiel #2
0
 /**
  * A verification routine suitable for partial files
  *
  * Runs the blacklist checks, but not any checks that may
  * assume the entire file is present.
  *
  * @return mixed True for valid or array with error message key.
  */
 protected function verifyPartialFile()
 {
     global $wgAllowJavaUploads, $wgDisableUploadScriptChecks;
     # getTitle() sets some internal parameters like $this->mFinalExtension
     $this->getTitle();
     $mwProps = new MWFileProps(MimeMagic::singleton());
     $this->mFileProps = $mwProps->getPropsFromPath($this->mTempPath, $this->mFinalExtension);
     # check MIME type, if desired
     $mime = $this->mFileProps['file-mime'];
     $status = $this->verifyMimeType($mime);
     if ($status !== true) {
         return $status;
     }
     # check for htmlish code and javascript
     if (!$wgDisableUploadScriptChecks) {
         if (self::detectScript($this->mTempPath, $mime, $this->mFinalExtension)) {
             return ['uploadscripted'];
         }
         if ($this->mFinalExtension == 'svg' || $mime == 'image/svg+xml') {
             $svgStatus = $this->detectScriptInSvg($this->mTempPath, true);
             if ($svgStatus !== false) {
                 return $svgStatus;
             }
         }
     }
     # Check for Java applets, which if uploaded can bypass cross-site
     # restrictions.
     if (!$wgAllowJavaUploads) {
         $this->mJavaDetected = false;
         $zipStatus = ZipDirectoryReader::read($this->mTempPath, [$this, 'zipEntryCallback']);
         if (!$zipStatus->isOK()) {
             $errors = $zipStatus->getErrorsArray();
             $error = reset($errors);
             if ($error[0] !== 'zip-wrong-format') {
                 return $error;
             }
         }
         if ($this->mJavaDetected) {
             return ['uploadjava'];
         }
     }
     # Scan the uploaded file for viruses
     $virus = $this->detectVirus($this->mTempPath);
     if ($virus) {
         return ['uploadvirus', $virus];
     }
     return true;
 }
Beispiel #3
0
 /**
  * Get properties of a file with a given virtual URL/storage path.
  * Properties should ultimately be obtained via FSFile::getProps().
  *
  * @param string $virtualUrl
  * @return array
  */
 public function getFileProps($virtualUrl)
 {
     $fsFile = $this->getLocalReference($virtualUrl);
     $mwProps = new MWFileProps(MimeMagic::singleton());
     if ($fsFile) {
         $props = $mwProps->getPropsFromPath($fsFile->getPath(), true);
     } else {
         $props = $mwProps->newPlaceholderProps();
     }
     return $props;
 }
Beispiel #4
0
 /**
  * Stash a file in a temp directory and record that we did this in the
  * database, along with other metadata.
  *
  * @param string $path Path to file you want stashed
  * @param string $sourceType The type of upload that generated this file
  *   (currently, I believe, 'file' or null)
  * @throws UploadStashBadPathException
  * @throws UploadStashFileException
  * @throws UploadStashNotLoggedInException
  * @return UploadStashFile|null File, or null on failure
  */
 public function stashFile($path, $sourceType = null)
 {
     if (!is_file($path)) {
         wfDebug(__METHOD__ . " tried to stash file at '{$path}', but it doesn't exist\n");
         throw new UploadStashBadPathException("path doesn't exist");
     }
     $mwProps = new MWFileProps(MimeMagic::singleton());
     $fileProps = $mwProps->getPropsFromPath($path, true);
     wfDebug(__METHOD__ . " stashing file at '{$path}'\n");
     // we will be initializing from some tmpnam files that don't have extensions.
     // most of MediaWiki assumes all uploaded files have good extensions. So, we fix this.
     $extension = self::getExtensionForPath($path);
     if (!preg_match("/\\.\\Q{$extension}\\E\$/", $path)) {
         $pathWithGoodExtension = "{$path}.{$extension}";
     } else {
         $pathWithGoodExtension = $path;
     }
     // If no key was supplied, make one.  a mysql insertid would be totally
     // reasonable here, except that for historical reasons, the key is this
     // random thing instead.  At least it's not guessable.
     // Some things that when combined will make a suitably unique key.
     // see: http://www.jwz.org/doc/mid.html
     list($usec, $sec) = explode(' ', microtime());
     $usec = substr($usec, 2);
     $key = Wikimedia\base_convert($sec . $usec, 10, 36) . '.' . Wikimedia\base_convert(mt_rand(), 10, 36) . '.' . $this->userId . '.' . $extension;
     $this->fileProps[$key] = $fileProps;
     if (!preg_match(self::KEY_FORMAT_REGEX, $key)) {
         throw new UploadStashBadPathException("key '{$key}' is not in a proper format");
     }
     wfDebug(__METHOD__ . " key for '{$path}': {$key}\n");
     // if not already in a temporary area, put it there
     $storeStatus = $this->repo->storeTemp(basename($pathWithGoodExtension), $path);
     if (!$storeStatus->isOK()) {
         // It is a convention in MediaWiki to only return one error per API
         // exception, even if multiple errors are available. We use reset()
         // to pick the "first" thing that was wrong, preferring errors to
         // warnings. This is a bit lame, as we may have more info in the
         // $storeStatus and we're throwing it away, but to fix it means
         // redesigning API errors significantly.
         // $storeStatus->value just contains the virtual URL (if anything)
         // which is probably useless to the caller.
         $error = $storeStatus->getErrorsArray();
         $error = reset($error);
         if (!count($error)) {
             $error = $storeStatus->getWarningsArray();
             $error = reset($error);
             if (!count($error)) {
                 $error = ['unknown', 'no error recorded'];
             }
         }
         // At this point, $error should contain the single "most important"
         // error, plus any parameters.
         $errorMsg = array_shift($error);
         throw new UploadStashFileException("Error storing file in '{$path}': " . wfMessage($errorMsg, $error)->text());
     }
     $stashPath = $storeStatus->value;
     // fetch the current user ID
     if (!$this->isLoggedIn) {
         throw new UploadStashNotLoggedInException(__METHOD__ . ' No user is logged in, files must belong to users');
     }
     // insert the file metadata into the db.
     wfDebug(__METHOD__ . " inserting {$stashPath} under {$key}\n");
     $dbw = $this->repo->getMasterDB();
     $serializedFileProps = serialize($fileProps);
     if (strlen($serializedFileProps) > self::MAX_US_PROPS_SIZE) {
         // Database is going to truncate this and make the field invalid.
         // Prioritize important metadata over file handler metadata.
         // File handler should be prepared to regenerate invalid metadata if needed.
         $fileProps['metadata'] = false;
         $serializedFileProps = serialize($fileProps);
     }
     $this->fileMetadata[$key] = ['us_id' => $dbw->nextSequenceValue('uploadstash_us_id_seq'), 'us_user' => $this->userId, 'us_key' => $key, 'us_orig_path' => $path, 'us_path' => $stashPath, 'us_props' => $dbw->encodeBlob($serializedFileProps), 'us_size' => $fileProps['size'], 'us_sha1' => $fileProps['sha1'], 'us_mime' => $fileProps['mime'], 'us_media_type' => $fileProps['media_type'], 'us_image_width' => $fileProps['width'], 'us_image_height' => $fileProps['height'], 'us_image_bits' => $fileProps['bits'], 'us_source_type' => $sourceType, 'us_timestamp' => $dbw->timestamp(), 'us_status' => 'finished'];
     $dbw->insert('uploadstash', $this->fileMetadata[$key], __METHOD__);
     // store the insertid in the class variable so immediate retrieval
     // (possibly laggy) isn't necesary.
     $this->fileMetadata[$key]['us_id'] = $dbw->insertId();
     # create the UploadStashFile object for this file.
     $this->initFile($key);
     return $this->getFile($key);
 }
Beispiel #5
0
 /**
  * Upload a file and record it in the DB
  * @param string|FSFile $src 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 int|bool $flags 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|null $user User object or null to use $wgUser
  * @param string[] $tags Change tags to add to the log entry and page revision.
  *   (This doesn't check $user's permissions.)
  * @return Status On success, the value member contains the
  *     archive name, or an empty string if it was a new file.
  */
 function upload($src, $comment, $pageText, $flags = 0, $props = false, $timestamp = false, $user = null, $tags = [])
 {
     global $wgContLang;
     if ($this->getRepo()->getReadOnlyReason() !== false) {
         return $this->readOnlyFatalStatus();
     }
     $srcPath = $src instanceof FSFile ? $src->getPath() : $src;
     if (!$props) {
         if ($this->repo->isVirtualUrl($srcPath) || FileBackend::isStoragePath($srcPath)) {
             $props = $this->repo->getFileProps($srcPath);
         } else {
             $mwProps = new MWFileProps(MimeMagic::singleton());
             $props = $mwProps->getPropsFromPath($srcPath, true);
         }
     }
     $options = [];
     $handler = MediaHandler::getHandler($props['mime']);
     if ($handler) {
         $options['headers'] = $handler->getStreamHeaders($props['metadata']);
     } else {
         $options['headers'] = [];
     }
     // 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($src, $flags, $options);
     if ($status->successCount >= 2) {
         // There will be a copy+(one of move,copy,store).
         // The first succeeding does not commit us to updating the DB
         // since it simply copied the current version to a timestamped file name.
         // It is only *preferable* to avoid leaving such files orphaned.
         // Once the second operation goes through, then the current version was
         // updated and we must therefore update the DB too.
         $oldver = $status->value;
         if (!$this->recordUpload2($oldver, $comment, $pageText, $props, $timestamp, $user, $tags)) {
             $status->fatal('filenotfound', $srcPath);
         }
     }
     $this->unlock();
     // done
     return $status;
 }
Beispiel #6
0
 /**
  * @param string $fileName
  * @return array
  */
 function getFileProps($fileName)
 {
     if (FileRepo::isVirtualUrl($fileName)) {
         list($repoName, , ) = $this->splitVirtualUrl($fileName);
         if ($repoName === '') {
             $repoName = 'local';
         }
         $repo = $this->getRepo($repoName);
         return $repo->getFileProps($fileName);
     } else {
         $mwProps = new MWFileProps(MimeMagic::singleton());
         return $mwProps->getPropsFromPath($fileName, true);
     }
 }