PHP File Upload source analysis (RFC1867) need to know the friend can refer to
HTTP-based uploads are relatively more user-friendly and security-enhancing than FTP. can be applied to upload methods have put, WEBDAV, and RFC1867 three kinds, this article will analyze in PHP, how to implement the file upload based on RFC1867.
RFC1867
RCF1867 is the form-based File Upload in HTML Standard protocol, the RFC1867 standard makes two changes to HTML:
1 adds a file option for the type attribute of the INPUT element.
The 2 input tag can have the Accept property, which can specify a list of file types or 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 containingThe behavior that should be taken when the form is marked.
For example, when HTML wants to allow users to upload one or more files, he can write:
The code is as follows |
Copy Code |
|
This form, everyone must be not unfamiliar, and for PHP, it also defines a default table cell max_file_size, the user can use this hidden table unit is always recommended that PHP only allow the size of the upload file, for example, the above examples, We want users to upload files that cannot be larger than 5k bytes, then write as follows:
The code is as follows |
Copy Code |
|
Let's not say how unreliable this max_file_size is (so browser-based control is unreliable), and simply from the implementation, I will slowly introduce how this max_file_size works.
When the user selects a file (Laruence.txt) and fills in a good file description ("Laruence's personal Introduction"), click Upload, what happens?
Form submission
After the user determines the commit, the browser sends a packet of similar format to the page specified by the Action property in the form (in this case, upload.php):
|
copy code |
//request Header post/upload.php http/1.0rn ... Host:www.laruence.comrn ... Content-length:xxxxxrn ... Content-type:multipart/form-data, boundary=--------------7d51863950254rn ... rnrn //Start post data Contents ---- -----------7d51863950254 Content-disposition:form-data, name= "description" Laruence personal Introduction ------------- --7d51863950254 Content-disposition:form-data; name= "UserFile"; filename= "Laruence.txt" content-type:text/ Plain ... laruence.txt content ... ---------------7d51863950254 |
Next, is the server, how to process the data.
Accept Uploads
When the Web server, which is assumed to be Apache (also assuming that PHP is installed in module mode on Apache), to accept the user's data, first it is based on the HTTP request header, by determining the MIME type of PHP type, and then after some process (this part, You can see my previous PHP Life Cycle ppt) and will eventually give you control over to the PHP module.
At this time, PHP will call Sapi_activate to initialize a request, in this process, first determine the request type, at this time is the post, so to call Sapi_read_post_data, through Content-type, Find the rfc1867 handler function Rfc1867_post_handler, and call this handler to parse the data from post.
About Rfc1867_post_handler This part of the source code, can be found in mian/rfc1867.c, you can also see my previous deep understanding of PHP file upload, which also listed the source code.
Then, PHP through boundary, for each segment, through the check, whether the same definition:
Name and filename properties (named File upload)
No definition name defines filename (nameless upload)
Defined name does not define filename (normal data),
So that different treatments can be performed.
The code is as follows |
Copy Code |
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 the 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 is max_file_size.
The code is as follows |
Copy Code |
/* 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 it does, it will check the file size to see if it exceeds the value.
|
copy code |
if (PG (upload_max_filesize) > 0 && Total_bytes > PG (upload_max_filesize)) { Cancel_upload = upload_error_a; } else if (max_file_size && (t Otal_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 php default upload limit. The second part is to check the user-defined max_file_size, so the max_file_size defined in the form cannot exceed the maximum upload file size set in PHP.
Judging by the name and filename, if the file is uploaded, a temporary file of random name is created in the file upload directory according to the PHP settings:
The code is as follows |
Copy Code |
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 a file handle, and a temporary random file name.
Later, there will be some validation, such as the file name is legitimate, name is legitimate.
If these validations pass, then the content is read into and written to this temporary file.
.....
The code is as follows |
Copy Code |
else if (Blen > 0) { Wlen = Write (fd, buff, blen); Writes 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-in is complete. Record temporary variable name:
The code is as follows |
Copy Code |
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 it will be set:
The code is as follows |
Copy Code |
$_files[' UserFile '//name= "UserFile" |
If it is an unnamed upload, it will be set using Tmp_name:
The code is as follows |
Copy Code |
$_files[' tmp_name '//anonymous upload |
Finally, the user-written upload.php processing is given.
At this point in the upload.php, the user can use Move_uploaded_file to manipulate the file that was just generated.
http://www.bkjia.com/PHPjc/444674.html www.bkjia.com true http://www.bkjia.com/PHPjc/444674.html techarticle php File Upload source analysis (RFC1867) need to know the friend can refer to the HTTP-based upload, relative ease of use and security than the FTP to enhance a lot. Can be applied to upload ...