48 if ( !$performer->
isAllowed(
'upload_by_url' ) ) {
49 return 'upload_by_url';
52 return parent::isAllowed( $performer );
62 return $allowCopyUploads && parent::isEnabled();
75 if ( !count( $domains ) ) {
83 foreach ( $domains as $domain ) {
85 $domainPieces = explode(
'.', $domain );
86 $uploadDomainPieces = explode(
'.', $parsedUrl[
'host'] );
87 if ( count( $domainPieces ) === count( $uploadDomainPieces ) ) {
90 foreach ( $domainPieces as $index => $piece ) {
91 if ( $piece !==
'*' && $piece !== $uploadDomainPieces[$index] ) {
121 if ( !isset( $params[
'filename'] ) || !isset( $params[
'url'] ) ) {
127 return sha1( sprintf(
"%s|||%s", $params[
'filename'], $params[
'url'] ) );
138 $uploadCacheKey = $request->getText(
'wpCacheKey', $request->getText(
'key',
'' ) );
139 if ( $uploadCacheKey !==
'' ) {
140 return $uploadCacheKey;
142 $desiredDestName = $request->getText(
'wpDestFile' );
143 if ( !$desiredDestName ) {
144 $desiredDestName = $request->getText(
'wpUploadFileURL' );
148 'filename' => $desiredDestName,
149 'url' => trim( $request->getVal(
'wpUploadFileURL' ) )
163 $page =
wfMessage(
'copyupload-allowed-domains' )->inContentLanguage()->plain();
165 foreach ( explode(
"\n", $page ) as $line ) {
167 $line = preg_replace(
"/^\\s*([^#]*)\\s*((.*)?)$/",
"\\1", $line );
169 $line = trim( $line );
171 if ( $line !==
'' ) {
187 if ( !isset( self::$allowedUrls[
$url] ) ) {
190 ->onIsUploadAllowedFromUrl(
$url, $allowed );
191 self::$allowedUrls[
$url] = $allowed;
194 return self::$allowedUrls[
$url];
215 $tempPath = $initTempFile ? $this->makeTemporaryFile() :
null;
216 $fileSize = $initTempFile ? 0 :
null;
217 # File size and removeTempFile will be filled in later
218 $this->initializePathInfo( $name, $tempPath, $fileSize,
false );
226 $desiredDestName = $request->getText(
'wpDestFile' );
227 if ( !$desiredDestName ) {
228 $desiredDestName = $request->getText(
'wpUploadFileURL' );
232 trim( $request->getVal(
'wpUploadFileURL' ) )
241 $user = RequestContext::getMain()->getUser();
243 $url = $request->getVal(
'wpUploadFileURL' );
247 ->getPermissionManager()
248 ->userHasRight( $user,
'upload_by_url' );
266 $status = $this->canFetchFile();
267 if ( !$status->isGood() ) {
270 return $this->reallyFetchFile( $httpOptions );
280 return Status::newFatal(
'http-invalid-url', $this->mUrl );
283 if ( !self::isAllowedHost( $this->mUrl ) ) {
284 return Status::newFatal(
'upload-copy-upload-invalid-domain' );
286 if ( !self::isAllowedUrl( $this->mUrl ) ) {
287 return Status::newFatal(
'upload-copy-upload-invalid-url' );
289 return Status::newGood();
299 ->newTempFSFile(
'URL',
'urlupload_' );
300 $tmpFile->bind( $this );
302 return $tmpFile->getPath();
313 wfDebugLog(
'fileupload',
'Received chunk of ' . strlen( $buffer ) .
' bytes' );
314 $nbytes = fwrite( $this->mTmpHandle, $buffer );
316 if ( $nbytes == strlen( $buffer ) ) {
317 $this->mFileSize += $nbytes;
322 'Short write ' . $nbytes .
'/' . strlen( $buffer ) .
323 ' bytes, aborting with ' . $this->mFileSize .
' uploaded so far'
325 fclose( $this->mTmpHandle );
326 $this->mTmpHandle =
false;
345 $this->mTmpHandle = fopen( $this->mTempPath,
'wb' );
346 if ( !$this->mTmpHandle ) {
347 return Status::newFatal(
'tmp-create-error' );
349 wfDebugLog(
'fileupload',
'Temporary file created "' . $this->mTempPath .
'"' );
351 $this->mRemoveTempFile =
true;
352 $this->mFileSize = 0;
354 $options = $httpOptions + [
'followRedirects' => false ];
356 if ( $copyUploadProxy !==
false ) {
357 $options[
'proxy'] = $copyUploadProxy;
360 if ( $copyUploadTimeout && !isset( $options[
'timeout'] ) ) {
361 $options[
'timeout'] = $copyUploadTimeout;
365 'Starting download from "' . $this->mUrl .
'" ' .
366 '<' . implode(
',', array_keys( array_filter( $options ) ) ) .
'>'
371 $attemptsLeft = $options[
'maxRedirects'] ?? 5;
372 $targetUrl = $this->mUrl;
374 while ( $attemptsLeft > 0 ) {
375 $req = $requestFactory->create( $targetUrl, $options, __METHOD__ );
376 $req->setCallback( $this->saveTempFileChunk( ... ) );
377 $status = $req->execute();
378 if ( !$req->isRedirect() ) {
381 $targetUrl = $req->getFinalUrl();
383 ftruncate( $this->mTmpHandle, 0 );
384 rewind( $this->mTmpHandle );
388 if ( $attemptsLeft == 0 ) {
389 return Status::newFatal(
'upload-too-many-redirects' );
392 if ( $this->mTmpHandle ) {
394 fclose( $this->mTmpHandle );
395 $this->mTmpHandle =
null;
398 return Status::newFatal(
'tmp-write-error' );
402 if ( $status->isOK() ) {
403 wfDebugLog(
'fileupload',
'Download by URL completed successfully.' );
406 wfDebugLog(
'fileupload', $status->getWikiText(
false,
false,
'en' ) );
410 'Download by URL completed with HTTP status ' . $req->getStatus()
420class_alias( UploadFromUrl::class,
'UploadFromUrl' );
wfDebugLog( $logGroup, $text, $dest='all', array $context=[])
Send a line to a supplementary debug log file, if configured, or main debug log if not.
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
Group all the pieces relevant to the context of a request into one instance.
A class containing constants representing the names of configuration variables.
const CopyUploadTimeout
Name constant for the CopyUploadTimeout setting, for use with Config::get()
const AllowCopyUploads
Name constant for the AllowCopyUploads setting, for use with Config::get()
const CopyUploadProxy
Name constant for the CopyUploadProxy setting, for use with Config::get()
const CopyUploadAllowOnWikiDomainConfig
Name constant for the CopyUploadAllowOnWikiDomainConfig setting, for use with Config::get()
const CopyUploadsDomains
Name constant for the CopyUploadsDomains setting, for use with Config::get()