48 if ( !$performer->
isAllowed(
'upload_by_url' ) ) {
49 return 'upload_by_url';
52 return parent::isAllowed( $performer );
62 return $allowCopyUploads && parent::isEnabled();
76 if ( !count( $domains ) ) {
79 $parsedUrl = $urlUtils->parse(
$url );
84 foreach ( $domains as $domain ) {
86 $domainPieces = explode(
'.', $domain );
87 $uploadDomainPieces = explode(
'.', $parsedUrl[
'host'] );
88 if ( count( $domainPieces ) === count( $uploadDomainPieces ) ) {
91 foreach ( $domainPieces as $index => $piece ) {
92 if ( $piece !==
'*' && $piece !== $uploadDomainPieces[$index] ) {
122 if ( !isset( $params[
'filename'] ) || !isset( $params[
'url'] ) ) {
128 return sha1( sprintf(
"%s|||%s", $params[
'filename'], $params[
'url'] ) );
139 $uploadCacheKey =
$request->getText(
'wpCacheKey',
$request->getText(
'key',
'' ) );
140 if ( $uploadCacheKey !==
'' ) {
141 return $uploadCacheKey;
143 $desiredDestName =
$request->getText(
'wpDestFile' );
144 if ( !$desiredDestName ) {
145 $desiredDestName =
$request->getText(
'wpUploadFileURL' );
149 'filename' => $desiredDestName,
150 'url' => trim(
$request->getVal(
'wpUploadFileURL' ) )
164 $page =
wfMessage(
'copyupload-allowed-domains' )->inContentLanguage()->plain();
166 foreach ( explode(
"\n", $page ) as $line ) {
168 $line = preg_replace(
"/^\\s*([^#]*)\\s*((.*)?)$/",
"\\1", $line );
170 $line = trim( $line );
172 if ( $line !==
'' ) {
188 if ( !isset( self::$allowedUrls[
$url] ) ) {
191 ->onIsUploadAllowedFromUrl(
$url, $allowed );
192 self::$allowedUrls[
$url] = $allowed;
195 return self::$allowedUrls[
$url];
216 $tempPath = $initTempFile ? $this->makeTemporaryFile() :
null;
217 $fileSize = $initTempFile ? 0 :
null;
218 # File size and removeTempFile will be filled in later
219 $this->initializePathInfo( $name, $tempPath, $fileSize,
false );
227 $desiredDestName =
$request->getText(
'wpDestFile' );
228 if ( !$desiredDestName ) {
229 $desiredDestName =
$request->getText(
'wpUploadFileURL' );
233 trim(
$request->getVal(
'wpUploadFileURL' ) )
242 $user = RequestContext::getMain()->getUser();
248 ->getPermissionManager()
249 ->userHasRight( $user,
'upload_by_url' );
267 $status = $this->canFetchFile();
268 if ( !$status->isGood() ) {
271 return $this->reallyFetchFile( $httpOptions );
281 return Status::newFatal(
'http-invalid-url', $this->mUrl );
284 if ( !self::isAllowedHost( $this->mUrl ) ) {
285 return Status::newFatal(
'upload-copy-upload-invalid-domain' );
287 if ( !self::isAllowedUrl( $this->mUrl ) ) {
288 return Status::newFatal(
'upload-copy-upload-invalid-url' );
290 return Status::newGood();
300 ->newTempFSFile(
'URL',
'urlupload_' );
301 $tmpFile->bind( $this );
303 return $tmpFile->getPath();
314 wfDebugLog(
'fileupload',
'Received chunk of ' . strlen( $buffer ) .
' bytes' );
315 $nbytes = fwrite( $this->mTmpHandle, $buffer );
317 if ( $nbytes == strlen( $buffer ) ) {
318 $this->mFileSize += $nbytes;
323 'Short write ' . $nbytes .
'/' . strlen( $buffer ) .
324 ' bytes, aborting with ' . $this->mFileSize .
' uploaded so far'
326 fclose( $this->mTmpHandle );
327 $this->mTmpHandle =
false;
346 $this->mTmpHandle = fopen( $this->mTempPath,
'wb' );
347 if ( !$this->mTmpHandle ) {
348 return Status::newFatal(
'tmp-create-error' );
350 wfDebugLog(
'fileupload',
'Temporary file created "' . $this->mTempPath .
'"' );
352 $this->mRemoveTempFile =
true;
353 $this->mFileSize = 0;
355 $options = $httpOptions + [
'followRedirects' => false ];
357 if ( $copyUploadProxy !==
false ) {
358 $options[
'proxy'] = $copyUploadProxy;
361 if ( $copyUploadTimeout && !isset( $options[
'timeout'] ) ) {
362 $options[
'timeout'] = $copyUploadTimeout;
366 'Starting download from "' . $this->mUrl .
'" ' .
367 '<' . implode(
',', array_keys( array_filter( $options ) ) ) .
'>'
372 $attemptsLeft = $options[
'maxRedirects'] ?? 5;
373 $targetUrl = $this->mUrl;
375 while ( $attemptsLeft > 0 ) {
376 $req = $requestFactory->create( $targetUrl, $options, __METHOD__ );
377 $req->setCallback( $this->saveTempFileChunk( ... ) );
378 $status = $req->execute();
379 if ( !$req->isRedirect() ) {
382 $targetUrl = $req->getFinalUrl();
384 ftruncate( $this->mTmpHandle, 0 );
385 rewind( $this->mTmpHandle );
389 if ( $attemptsLeft == 0 ) {
390 return Status::newFatal(
'upload-too-many-redirects' );
393 if ( $this->mTmpHandle ) {
395 fclose( $this->mTmpHandle );
396 $this->mTmpHandle =
null;
399 return Status::newFatal(
'tmp-write-error' );
403 if ( $status->isOK() ) {
404 wfDebugLog(
'fileupload',
'Download by URL completed successfully.' );
407 wfDebugLog(
'fileupload', $status->getWikiText(
false,
false,
'en' ) );
411 'Download by URL completed with HTTP status ' . $req->getStatus()
421class_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()