PHP File Upload source code analysis (RFC1867) _php tips

Source: Internet
Author: User
Tags file upload http request php file upload ftp client
You are not always in the user to upload the avatar when told the user "Please open the FTP client, upload files to the http://www.jb51.net/uploads/, and 2dk433423l.jpg named" it?

and HTTP based upload, relative to ease of use and security than FTP to enhance a lot. Can be applied to the upload method has put, WEBDAV, and RFC1867 Three, this article will be analyzed in PHP, is how to implement file upload based on RFC1867.

RFC1867

RCF1867 is the form-based File Upload in HTML Standard protocol, and the RFC1867 standard makes two modifications to HTML:
 

1 adds a file option to the type attribute of the INPUT element.
The 2 input tag can have a accept property that specifies the file type or list of file formats that can be uploaded.

  
In addition, this standard defines a new MIME type: Multipart/form-data, and when dealing with a enctype= "multipart/form-data" and/or containing <input type= "file" > The label of the form should be taken when the behavior.
  
For example, when HTML wants to allow a user to upload one or more files, he can write:

<form enctype= "Multipart/form-data" action= "upload.php" method=post>
Select File:
<input name= "UserFile" type= "File" >
File Description:
<input name= "description" type= "text" >
<input type= "Submit" value= "Upload" >
</form>

This form, everyone must be not unfamiliar, and for PHP, it itself defines a default table cell max_file_size, the user can through this hidden table unit has always recommended that PHP only allow the size of uploaded files, such as for the above example, We want users to upload files that are not larger than 5000 (5k) bytes, so you can write as follows:

<form enctype= "Multipart/form-data" action= "upload.php" method=post>
<input type= "hidden" value= "5000" name= "max_file_size" > <!--file size-->
Select File:
<input name= "UserFile" type= "File" >
File Description:
<input name= "description" type= "text" >
<input type= "Submit" value= "Upload" >
</form>

Let's not say, this max_file_size is how unreliable (so browser-based control, are unreliable), simply from the realization, I will slowly explain how this max_file_size work.

When the user chooses a file (Laruence.txt) and fills in the file description ("Laruence's personal Introduction"), what happens after you click upload?

Form submission

After the user determines the submission, the browser sends the following similar format packet to the page specified by the Action property in form (in this case, upload.php):

Request headers
post/upload.php http/1.0\r\n
...
host:www.laruence.com\r\n
...
content-length:xxxxx\r\n
...
Content-type:multipart/form-data, boundary=--------------7d51863950254\r\n
... \r\n\r\n
Start Post data content
---------------7d51863950254
Content-disposition:form-data; Name= "description"
Laruence's Personal introduction
---------------7d51863950254
Content-disposition:form-data; Name= "UserFile"; Filename= "Laruence.txt"
Content-type:text/plain
... the content of laruence.txt ...
---------------7d51863950254

Next, the server is how to process the data.

Accept Upload

When the Web server is assumed to be Apache (in addition to the assumption that PHP is installed on Apache in the form of a module), when it accepts the user's data, it begins with the HTTP request header by determining the MIME type as the PHP type and then after some process (this part, can refer to my previous php life Cycle ppt), will eventually give control to the PHP module.

At this point, PHP invokes sapi_activate to initialize a request, in which the request type is first judged, at which time it is post, to invoke Sapi_read_post_data, through Content-type, Find the rfc1867 handler function Rfc1867_post_handler to call this handler to analyze the post data.

About Rfc1867_post_handler This part of the source code, can be found in mian/rfc1867.c, also can see my previous in-depth understanding of PHP file upload, which also listed the source.

Then, PHP passes through the boundary, for each fragment, by checking whether it also defines:

Name and filename attributes (named file upload)
Name not defined filename (nameless upload)
Definition name does not define filename (normal data).

So that we can do different processing.

if (cd = Php_mime_get_hdr_value (header, "content-disposition")) {
Char *pair=null;
int end=0;

while (Isspace (*CD)) {
++CD;
}

while (*CD && (pair = Php_ap_getword (&CD, '; '))
{
Char *key=null, *word = pair;

while (Isspace (*CD)) {
++CD;
}

if (STRCHR (pair, ' = ')) {
Key = Php_ap_getword (&pair, ' = ');

if (!strcasecmp (Key, "name")) {
Get the Name field
if (param) {
Efree (param);
}
param = php_ap_getword_conf (&pair tsrmls_cc);
else if (!strcasecmp (key, "filename")) {
Get filename Field
if (filename) {
Efree (filename);
}
filename = php_ap_getword_conf (&pair tsrmls_cc);
}
}
if (key) {
Efree (key);
}
Efree (word);
}

In this process, PHP will check the normal data, whether there are max_file_size.

/* Normal form variable, safe to read all data into memory * *
if (!filename && param) {
unsigned int value_len;
Char *value = multipart_buffer_read_body (Mbuff, &value_len tsrmls_cc);
unsigned int new_val_len; /* Dummy Variable * *
......

if (!strcasecmp (param, "max_file_size")) {
max_file_size = Atol (value);
}

Efree (param);
Efree (value);
Continue
}

If you do, you will check to see if the file size is exceeded by its value.

if (PG (upload_max_filesize) > 0 && total_bytes > PG (upload_max_filesize)) {
Cancel_upload = upload_error_a;
else if (max_file_size && (Total_bytes > Max_file_size)) {
#if debug_file_upload
Sapi_module.sapi_error (E_notice,
"Max_file_size of%ld bytes Exceeded-file [%s=%s] Not saved",
max_file_size, param, filename);
#endif
Cancel_upload = Upload_error_b;
}

Through the above code, we can also see that the judgment is divided into two parts, the first part is to check the PHP default upload limit. The second part is to check user-defined max_file_size, so the max_file_size defined in the form cannot exceed the maximum upload file size set in PHP.

By the name and filename of the judge, if the file upload, according to PHP settings, in the file upload directory to create a random name of the temporary file:

if (!skip_upload) {
/* Handle file */
FD = PHP_OPEN_TEMPORARY_FD_EX (PG (Upload_tmp_dir),
"PHP", &temp_filename, 1 tsrmls_cc);
if (fd==-1) {
Sapi_module.sapi_error (E_warning,
"File upload error-unable to create a temporary file");
Cancel_upload = Upload_error_e;
}
}

Returns the file handle, and the temporary random file name.

After that, there will be some validation, such as the file name is legal, name is legal, and so on.

If these validations are passed, the content is read in and written to the temporary file.

.....
else if (Blen > 0) {
Wlen = Write (fd, buff, blen); Write to a temporary file.
if (Wlen = = 1) {
/* Write Failed * *
#if debug_file_upload
Sapi_module.sapi_error (E_notice, "write () failed-%s", Strerror (errno));
#endif
Cancel_upload = Upload_error_f;
}
}
....

Closes the temporary file handle when the loop read completes. Record temporary variable name:

Zend_hash_add (SG (rfc1867_uploaded_files), Temp_filename,
Strlen (Temp_filename) + 1, &temp_filename, sizeof (char *), NULL);

and generate a file variable, this time, if it is a well-known upload, then set:

$_files[' UserFile ']//name= "UserFile"

If it is an anonymous upload, the tmp_name is used to set:

$_files[' tmp_name ']//nameless upload

Ultimately to the user to write upload.php processing.

At this point in the upload.php, the user can use the Move_uploaded_file to manipulate the file just generated ~

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.