2017-08-29 15 views
3

我要發佈一個文件到服務器與Content-Disposition頭(使用PHP 7.0在Ubuntu的捲曲度7.47)內提供該文件的文件名的相對路徑:

curl server/index.php -F "[email protected];filename=a/b/c.txt" 

運用--trace-ascii /dev/stdout選項顯示:

0000: POST /index.php HTTP/1.1 
0031: Host: server 
004a: User-Agent: curl/7.47.0 
0063: Accept: */* 
0070: Content-Length: 111511 
0088: Expect: 100-continue 
009e: Content-Type: multipart/form-data; boundary=-------------------- 
00de: ----e656f77ee2b4759a 
00f4: 
... 
0000: --------------------------e656f77ee2b4759a 
002c: Content-Disposition: form-data; name="file"; filename="a/b/c.txt 
006c: " 
006f: Content-Type: application/octet-stream 
0097: 
... 

現在,我簡單的測試腳本<?php print_r($_FILES["file"]); ?>輸出:

Array 
(
    [name] => c.txt 
    [type] => application/octet-stream 
    [tmp_name] => /tmp/phpNaikad 
    [error] => 0 
    [size] => 111310 
) 

Howeve r,我預計[name] => a/b/c.txt。我的邏輯缺陷在哪裏?

根據https://stackoverflow.com/a/3393822/1647737,文件名可以包含相對路徑。

PHP manual also implies this並建議用basename()進行消毒。

+0

我認爲你不能得到上傳的文件,由於安全原因,原來的路。也沒有PHP,也沒有JavaScript無法檢索這個信息。 – Wizard

+0

@Wizard你是正確的從瀏覽器內上傳;除了舊的IE版本之外,瀏覽器不會發送完整的本地路徑。但是這裏的截斷必須發生在服務器端(正如您可以從包含完整路徑的跟蹤中看到的那樣)。 –

+1

是的,我看到..但我懷疑由於同樣的原因,PHP方面削減了這一點。你可以[閱讀php解釋器的代碼](https://github.com/php/php-src/blob/c8aa6f3a9a3d2c114d0c5e0c9fdd0a465dbb54a5/main/rfc1867.c#L1151) – Wizard

回答

1

正如我們從php-interpreter sources,_basename()過濾器出於安全原因調用和/或修復某些特定的瀏覽器。

文件:PHP-的src/main/rfc1867.c

行〜1151及以下:

 /* The \ check should technically be needed for win32 systems only where 
     * it is a valid path separator. However, IE in all it's wisdom always sends 
     * the full path of the file on the user's filesystem, which means that unless 
     * the user does basename() they get a bogus file name. Until IE's user base drops 
     * to nill or problem is fixed this code must remain enabled for all systems. */ 
     s = _basename(internal_encoding, filename); 
     if (!s) { 
      s = filename; 
     }