PHPファイルアップロードのソースコード解析(RFC1867)_PHPチュートリアル

WBOY
リリース: 2016-07-20 11:10:58
オリジナル
1021 人が閲覧しました

PHP ファイルアップロードのソースコード分析 (RFC1867) 知りたい人は参考にしてください

HTTP ベースのアップロードは、FTP よりも比較的使いやすく、安全です。この記事では、PUT、WEBDAV、RFC1867 などのアップロード方法を分析します。 PHP で RFC1867 に基づいたファイル アップロードを実装するための

RFC1867

RCF1867 は、HTML 標準プロトコルのフォームベースのファイル アップロードです。


1 type 属性にファイル オプションを追加しました。入力要素の。
2 input タグには、アップロードできるファイル タイプまたはファイル形式のリストを指定できる accept 属性を含めることができます。


さらに、この標準では、新しい MIME タイプ multipart/form-data も定義されており、enctype="multipart/form-data" または を含むファイルを処理する場合、フォームにマークを付けるときに取るべき動作。

たとえば、HTML でユーザーが 1 つ以上のファイルをアップロードできるようにしたい場合は、次のように記述できます:

コードは次のとおりです コードをコピーします


ファイルを選択:

ファイル説明:


このフォームは誰もがよく知っているはずですが、PHP では独自の定義があります。デフォルトのフォーム要素 MAX_FILE_SIZE。ユーザーは、この非表示のフォーム要素を使用して、PHP がアップロードするファイルの最大サイズのみを許可することを提案できます。たとえば、上記の例では、ユーザーがアップロードするファイルが 5000 (5k) を超えないようにすることができます。 ) バイトの場合、次のように記述できます:

コードは次のとおりです コードをコピー


ファイルを選択:

ファイルの説明:


この MAX_FILE_SIZE がどれほど信頼できないかは言うまでもありません (したがって、ブラウザベースの制御は信頼できません)。純粋に実装の観点から、この MAX_FILE_SIZE がどのように機能するかをゆっくり紹介します。 out ファイルの説明 (「Laruence の個人紹介」)、アップロードをクリックした後はどうなりますか?

フォーム送信

ユーザーが送信を確認した後、ブラウザは、action 属性で指定されたページに次のような形式のデータ パケットを送信します。フォーム内 (この場合は、upload.php):

コードは次のとおりです//リクエストヘッダー

次のステップは、サーバーがこのデータをどのように処理するかです。

アップロードを受け入れます

Web サーバー (ここでは Apache であると仮定します) (PHP がモジュール モードで Apache にインストールされていると仮定します) がユーザーのデータを受信すると、最初に決定します。 HTTP リクエスト ヘッダーに基づいて MIME TYPE を PHP タイプとして設定し、いくつかのプロセスを経た後 (この部分については、以前の PHP ライフ サイクルのページを参照してください)、最終的に制御を PHP モジュールに渡します。

これでこのプロセスでは、PHP は sapi_activate を呼び出してリクエストのタイプ (この時点では POST) を決定し、次に、sapi_read_post_data を呼び出して、rfc1867 処理関数 rfc1867_post_handler を呼び出します。 POST を分析するためのデータが来ます。

rfc1867_post_handler のソース コードは、mian/rfc1867.c にあります。また、ソース コードもリストされています。

その後、PHP は境界を介して、セグメントごとに、それらが同時に定義されているかどうかをチェックします:

名前とファイル名の属性 (名前付きファイルのアップロード)

名前は定義されていません、ファイル名は定義されています (名前なしのアップロード)
名前は定義されている、ファイル名が定義されていない (通常のデータ) ),

別の処理を実行します。

コードをコピー
POST /upload.php HTTP/1.0rn

...
Host : www.laruence .comrn
...
Content-length: xxxxxrn
...
Content-type: multipart/form-data、boundary=--------------7d51863950254rn
。 ..rnrn
//POST データコンテンツの開始
--------------7d51863950254
content-disposition: form-data name="description"
larence の自己紹介
---- --- --------7d51863950254
content-disposition: form-data; name="userfile"; filename="laruence.txt"
Content-Type: text/plain
... ラルエンスのコンテンツ.txt.. .
---------------7d51863950254

コードは次のとおりですコードをコピー /* 通常形式の変数、すべてのデータをメモリに安全に読み込むことができます */
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 = ペア;

while (isspace(*cd)) {

++cd;
}

if (strchr(pair, '=') ) {

key = php_ap_getword(&pair, '=' ); F if (! Strcasecmp (key, "name") {
// 名前フィールドを取得します

iF (Param) {

EFREE (Param); } else if ( !strcasecmp(key, "ファイル名")) {
(key) {
efree(key);
}
efree(word);
}






このプロセスでは、PHP がチェックします。あるかどうか通常のデータの MAX_FILE_SIZE



コードは次のとおりです

コードをコピー

if (!filename && param) {

unsigned int value_len;

char *value = multipart_buffer_read_body(mbuff, &value_len TSRMLS_CC); unsigned / (value); continue;
}

「はい」の場合、その値に従ってファイル サイズを超えているかどうかを確認します

コードは次のとおりです コードをコピーします

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 %ld バイトを超えました - [%s = %s] 保存されていません",
max_file_size, param, filename);
#endif
cancel_upload = UPLOAD_ERROR_B;
}

上記のコードを通して、判定が 2 つの部分に分かれていることもわかります。 、最初の部分は、PHP のデフォルトのアップロード制限を確認することです。2 番目の部分は、ユーザー定義の MAX_FILE_SIZE を確認することです。したがって、フォームで定義されている MAX_FILE_SIZE は、PHP で設定されている最大アップロード ファイル サイズを超えることはできません。

名前とファイル名を判断することで、ファイルアップロードの場合、PHPの設定に従ってファイルアップロードディレクトリにランダムな名前の一時ファイルを作成します:

コードは次のとおりです コードをコピーします

if (! Skip_upload) {
/* ハンドル ファイル */
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,
"ファイルのアップロード エラー - 一時ファイルを作成できません") ;
Cancel_upload = UPLOAD_ERROR_E;
}
}

ファイル ハンドルと一時的なランダム ファイル名を返します。

その後、ファイル名が正当である、名前が正当であるなどの検証。

これらの検証に合格した場合は、内容を読み取り、この一時ファイルに書き込みます。

...

コードは次のとおりです コードをコピーします

else if (blen > 0) {
wlen = write(fd, buff, blen) //一時ファイルを書き込みます
if (wlen == -1) {
/* 書き込みに失敗しました */
#if DEBUG_FILE_UPLOAD
sapi_module.sapi_error(E_NOTICE, "write( ) failed - %s", strerror(errno));
#endif
cancel_upload = UPLOAD_ERROR_F;
}
}
... .

ループ読み込みが完了したら、一時ファイルハンドルを閉じます。 レコード一時変数名:

コードは以下の通りです コードをコピー

zend_hash_add(SG( rfc1867_uploaded_files) , temp_filename,
strlen(temp_filename) + 1, &temp_filename, sizeof(char *), N ULL);

このとき、名前を付けてアップロードするとFILE変数が生成されます。設定します:

コードは次のとおりです コードをコピーします

$_FILES['userfile'] //name="userfile "

名前なしのアップロードの場合は、tmp_name を使用して設定します:

コードは次のとおりです コードをコピーします

$_FILES['tmp_name'] //無名アップロード

最後にupload.phpの処理をユーザーに渡します。

この時点でupload.phpでは、ユーザーはmove_uploaded_fileで生成したばかりのファイルを操作することができます


www.bkjia.com本当http://www.bkjia.com/PHPjc/444674.html技術記事 PHP ファイルアップロードのソースコード解析 (RFC1867) 知っておく必要がある友人はそれを参照できます。HTTP ベースのアップロードは、FTP よりも比較的使いやすく、安全に適用できます。
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート
私たちについて 免責事項 Sitemap
PHP中国語ウェブサイト:福祉オンライン PHP トレーニング,PHP 学習者の迅速な成長を支援します!