jenkins-bot has submitted this change and it was merged.

Change subject: Add "upload" type to API
......................................................................


Add "upload" type to API

If a file upload is not formatted correctly for PHP to recognize it as a
file upload rather than a regular field, the API will wind up trying to
load the file contents as a text field. Since these file contents are
often a large binary file, this will tend to run out of memory trying to
apply Unicode normalization.

To prevent this and to allow for a helpful error message, mark
parameters that are supposed to be file uploads.

Bug: 44909
Change-Id: Ia4586953e2ad2d72d08852689e060e39e7920d50
---
M RELEASE-NOTES-1.21
M includes/api/ApiBase.php
M includes/api/ApiImport.php
M includes/api/ApiMain.php
M includes/api/ApiUpload.php
5 files changed, 53 insertions(+), 3 deletions(-)

Approvals:
  Yurik: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/RELEASE-NOTES-1.21 b/RELEASE-NOTES-1.21
index b651f5e..1d56221 100644
--- a/RELEASE-NOTES-1.21
+++ b/RELEASE-NOTES-1.21
@@ -244,6 +244,10 @@
 * (bug 44923) action=upload works correctly if the entire file is uploaded in
   the first chunk.
 * Added 'continue=' parameter to streamline client iteration over complex 
query results
+* (bug 44909) API parameters may now be marked as type "upload", which is now
+  used for action=upload's 'file' and 'chunk' parameters. This type will raise
+  an error during parameter validation if the parameter is given but not
+  recognized as an uploaded file.
 
 === API internal changes in 1.21 ===
 * For debugging only, a new global $wgDebugAPI removes many API restrictions 
when true.
diff --git a/includes/api/ApiBase.php b/includes/api/ApiBase.php
index 4a6dad3..480404c 100644
--- a/includes/api/ApiBase.php
+++ b/includes/api/ApiBase.php
@@ -468,6 +468,9 @@
                                                                        $desc 
.= $paramPrefix . $intRangeStr;
                                                                }
                                                                break;
+                                                       case 'upload':
+                                                               $desc .= 
$paramPrefix . "Must be posted as a file upload using multipart/form-data";
+                                                               break;
                                                }
                                        }
 
@@ -917,6 +920,29 @@
                        }
 
                        $value = $this->getMain()->getCheck( $encParamName );
+               } elseif ( $type == 'upload' ) {
+                       if ( isset( $default ) ) {
+                               // Having a default value is not allowed
+                               ApiBase::dieDebug( __METHOD__, "File upload 
param $encParamName's default is set to '$default'. File upload parameters may 
not have a default." );
+                       }
+                       if ( $multi ) {
+                               ApiBase::dieDebug( __METHOD__, "Multi-values 
not supported for $encParamName" );
+                       }
+                       $value = $this->getMain()->getUpload( $encParamName );
+                       if ( !$value->exists() ) {
+                               // This will get the value without trying to 
normalize it
+                               // (because trying to normalize a large binary 
file
+                               // accidentally uploaded as a field fails 
spectacularly)
+                               $value = 
$this->getMain()->getRequest()->unsetVal( $encParamName );
+                               if ( $value !== null ) {
+                                       $this->dieUsage(
+                                               "File upload param 
$encParamName is not a file upload; " .
+                                               "be sure to use 
multipart/form-data for your POST and include " .
+                                               "a filename in the 
Content-Disposition header.",
+                                               "badupload_{$encParamName}"
+                                       );
+                               }
+                       }
                } else {
                        $value = $this->getMain()->getVal( $encParamName, 
$default );
 
@@ -1013,6 +1039,8 @@
                                                        $value = $value[0];
                                                }
                                                break;
+                                       case 'upload': // nothing to do
+                                               break;
                                        default:
                                                ApiBase::dieDebug( __METHOD__, 
"Param $encParamName's type is unknown - $type" );
                                }
diff --git a/includes/api/ApiImport.php b/includes/api/ApiImport.php
index 408805e..1f0a5fa 100644
--- a/includes/api/ApiImport.php
+++ b/includes/api/ApiImport.php
@@ -105,7 +105,9 @@
                                ApiBase::PARAM_REQUIRED => true
                        ),
                        'summary' => null,
-                       'xml' => null,
+                       'xml' => array(
+                               ApiBase::PARAM_TYPE => 'upload',
+                       ),
                        'interwikisource' => array(
                                ApiBase::PARAM_TYPE => $wgImportSources
                        ),
diff --git a/includes/api/ApiMain.php b/includes/api/ApiMain.php
index 2d40de8..7053ef3 100644
--- a/includes/api/ApiMain.php
+++ b/includes/api/ApiMain.php
@@ -919,6 +919,18 @@
        }
 
        /**
+        * Get a request upload, and register the fact that it was used, for 
logging.
+        *
+        * @since 1.21
+        * @param $name string Parameter name
+        * @return WebRequestUpload
+        */
+       public function getUpload( $name ) {
+               $this->mParamsUsed[$name] = true;
+               return $this->getRequest()->getUpload( $name );
+       }
+
+       /**
         * Report unused parameters, so the client gets a hint in case it gave 
us parameters we don't know,
         * for example in case of spelling mistakes or a missing 'g' prefix for 
generators.
         */
diff --git a/includes/api/ApiUpload.php b/includes/api/ApiUpload.php
index eabcf9b..05d3b5a 100644
--- a/includes/api/ApiUpload.php
+++ b/includes/api/ApiUpload.php
@@ -679,7 +679,9 @@
                                ),
                        ),
                        'ignorewarnings' => false,
-                       'file' => null,
+                       'file' => array(
+                               ApiBase::PARAM_TYPE => 'upload',
+                       ),
                        'url' => null,
                        'filekey' => null,
                        'sessionkey' => array(
@@ -690,7 +692,9 @@
 
                        'filesize' => null,
                        'offset' => null,
-                       'chunk' => null,
+                       'chunk' => array(
+                               ApiBase::PARAM_TYPE => 'upload',
+                       ),
 
                        'async' => false,
                        'asyncdownload' => false,

-- 
To view, visit https://gerrit.wikimedia.org/r/51041
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: Ia4586953e2ad2d72d08852689e060e39e7920d50
Gerrit-PatchSet: 5
Gerrit-Project: mediawiki/core
Gerrit-Branch: master
Gerrit-Owner: Anomie <[email protected]>
Gerrit-Reviewer: Alex Monk <[email protected]>
Gerrit-Reviewer: Anomie <[email protected]>
Gerrit-Reviewer: Parent5446 <[email protected]>
Gerrit-Reviewer: Umherirrender <[email protected]>
Gerrit-Reviewer: Yurik <[email protected]>
Gerrit-Reviewer: jenkins-bot

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to