Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MAX_FILE_SIZE in PHP - what's the point?

Tags:

php

I was trying to make a file upload form and checked the PHP documentation to refresh my memory on the subject. Here is a link to the relevant article. All of a sudden I noticed this message:

The MAX_FILE_SIZE hidden field (measured in bytes) must precede the file input field, and its value is the maximum filesize accepted by PHP. This form element should always be used as it saves users the trouble of waiting for a big file being transferred only to find that it was too large and the transfer failed. Keep in mind: fooling this setting on the browser side is quite easy, so never rely on files with a greater size being blocked by this feature. It is merely a convenience feature for users on the client side of the application. The PHP settings (on the server side) for maximum-size, however, cannot be fooled.

OK... Say what? First it tells that it must precede the file upload field. Then it tells us that it is merely for convenience. And besides - it's on client side anyway so anyone can mess with it. After googling around I also found information that there are no known browsers that support it.

WTF? Why is it said that it must precede the file upload field if it seems to be (for all intents and purposes) absolutely pointless? Should I bother putting it in my HTML at all?

like image 897
Vilx- Avatar asked Sep 04 '09 20:09

Vilx-


4 Answers

After failed attempt to find any authoritative information about MAX_FILE_INFO i've decided to resort to drastic measures - and peeked at PHP's holy source.

I scanned entire PHP source recursively using grep:

grep -ri MAX_FILE_SIZE .

The only place that mentioned this variable was (excluding tests folder) - rfc1867.c file. Completely expectable since rfc1867 standard deals with file uploads.

Related C code:

......
if (!strcasecmp(param, "MAX_FILE_SIZE")) {                                                                                                                                                                              
   max_file_size = atol(value);
}
......
......
if (PG(upload_max_filesize) > 0 && (total_bytes+blen) > PG(upload_max_filesize)) {
    cancel_upload = UPLOAD_ERROR_A;
} else if (max_file_size && ((total_bytes+blen) > max_file_size)) {
    cancel_upload = UPLOAD_ERROR_B;
} else if
....

So - here's short explanation of above code:

1) first we get the value of MAX_FILE_SIZE into max_file_size variable.

2) Then we check if max_file_size value exists and if the sum of already accepted bytes (total_bytes) + the size of bytes in the buffer(blen) exceeds max_file_size.

3) If 2 is true - at this point we cancel upload with some error code that's been set by this constant: UPLOAD_ERROR_B

BUT - as you can see - right before checking max_file_size variable - PHP performs EXACTLY THE SAME CHECK for upload_max_filesize variable!!! So - there we have it.

Conclusion: IMHO - op is right - there is 0 point in including MAX_FILE_SIZE into your forms! Simply set upload_max_filesize in your php.ini file or dynamically via ini_set().

like image 112
Stann Avatar answered Nov 04 '22 17:11

Stann


At the moment there are no browsers that actually care about the MAX_FILE_SIZE directive so it is pretty pointless. I suppose it does give you more granular control over max sizes on upload (as the poster above stated) rather than going with php.ini's, but personally I just ignore it, and you probably should too. It will certainly not stop a user uploading a larger than required file - the manual is fairly misleading in this regard.

like image 20
Meep3D Avatar answered Nov 04 '22 16:11

Meep3D


Until we find browsers that support it, there's no point on the client side.

However, on the server side, MAX_FILE_SIZE does affect the values you get from $_FILES['your_file'].

Assuming the browser's request actually made it through post_max_size, usually this is what PHP gives:

array(5) {
    ["name"]=> string(11) "my_upload.dll"
    ["type"]=> string(24) "application/x-msdownload"
    ["tmp_name"]=> string(26) "C:\WINDOWS\Temp\php86A.tmp"
    ["error"]=> int(0) // UPLOAD_ERR_OK
    ["size"]=> int(238592)
}

But if uploaded file size exceeds MAX_FILE_SIZE, you'd see:

array(5) {
    ["name"]=> string(11) "my_upload.dll"
    ["type"]=> string(0) ""
    ["tmp_name"]=> string(0) ""
    ["error"]=> int(2) // UPLOAD_ERR_FORM_SIZE
    ["size"]=> int(0)
} 

And the part on "MAX_FILE_SIZE must precede the file input field" is not a joke. It actually works because PHP will interpret the browser's POST request payload sequentially:

<input name=F1 type=file> 
<input name=F2 type=file>
F1 and F2 will not be affected by MAX_FILE_SIZE

<input name=MAX_FILE_SIZE value=1024 type=hidden>
<input name=F3 type=file>
<input name=F4 type=file>
F3 and F4 will have MAX_FILE_SIZE = 1024 bytes

<input name=MAX_FILE_SIZE value=0 type=hidden>
<input name=F5 type=file>
<input name=F6 type=file>
F5 and F6 will have MAX_FILE_SIZE = 0 (infinite)

<input name=MAX_FILE_SIZE value=1 type=hidden>
<input name=F7 type=file> 
<input name=F8 type=file>
F7 and F8 will have MAX_FILE_SIZE = 1 byte

Also note that PHP interprets MAX_FILE_SIZE case insensitively, so maX_fILe_sIZE and Max_File_SIZE would work too.

like image 12
Pacerier Avatar answered Nov 04 '22 16:11

Pacerier


I believe the point is that conformant browsers would prevent form submission in the case where the user selected a file that was too large, which would save them having to perform at least a partial upload (which could take a while) of a file that was going to be rejected.

On the server side, PHP still checks and enforces the various limits set in PHP.ini, and will reference the fact that an upload was too large in the normal manner, i.e. an error code set in $_FILES. You might think of the field as an analogy to JavaScript validation - we might do a quick client-side check for the user's convenience, but we still do a proper server-side test and enforce it for all requests.

As others have stated, there don't appear to be any browsers that actually bother to perform this check, making it relatively useless.

like image 2
Rob Avatar answered Nov 04 '22 17:11

Rob