2011-05-24 41 views
2

我正在寫在PHP接受到本地輸入文件作爲參數的路徑的命令行應用程序的數據類型。輸入文件將包含以下之一:確定從file_get_contents()函數

  • JSON編碼關聯數組
  • serialized()版本聯合數組的
  • serialized()關聯數組
  • 基底的基底64編碼版本64編碼JSON編碼的關聯數組
  • 一個普通的舊PHP關聯數組
  • 垃圾

總之,有幾種不同的方案,我有過將被寫入該文件的控制權,以統一的方式,我可以理解,一旦我真的弄清楚格式。一旦我弄清楚如何攝入的數據,我可以運行它。

我正在考慮是:

  • 如果該文件的第一個字節是{,嘗試json_decode(),看它是否失敗。
  • 如果該文件的第一個字節是<$,嘗試include(),看它是否失敗。
  • 如果前三個字節的文件的匹配:[0-9],嘗試unserialize()
  • 如果不是前三,儘量base64_decode(),看它是否失敗。如果不是:
    • 檢查解碼數據的第一個字節一次。
    • 如果所有這些都失敗了,那就是垃圾。

這似乎只是相當簡單的任務相當昂貴。我能以更好的方式做到嗎?如果是這樣,怎麼樣?

+1

這是一個完美的例子,公約完成這項工作。如果您知道* all * JSON文件以.json結尾,那麼您不需要解析。如果你對環境沒有控制權,那麼運行不可信代碼(使用'include')是相當不安全的。 – rid 2011-05-24 18:43:27

+0

我會讓用戶簡單地指出它是什麼類型的文件,然後理智檢查它。這種自動化的方法似乎有太多的潛力被奇怪的邊緣情況所打擊。 – 2011-05-24 18:43:36

+0

以什麼方式「包含」失敗? – lonesomeday 2011-05-24 18:43:54

回答

2

這裏沒有太多的優化。魔術字節的方法已經是要走的路了。但是,當然可以避免實際的反序列化功能。對每個人使用驗證正則表達式是可行的(儘管模因通常比使PHP實際解包嵌套數組更快)。

base64很容易探測。

json可以使用正則表達式進行檢查。 Fastest way to check if a string is JSON in PHP?是用於保護JS的RFC版本。但是寫一個完整的json (?R)匹配規則是可行的。

serialize如果沒有正確的解包功能會更難一些。但是通過一些啓發式方法,你可以斷言它是一個序列化的blob。

php使用token_get_all可以更快地探測陣列腳本。或者如果格式和數據受到限制,再用正則表達式。

這裏更重要的問題是,你需要可靠性 - 還是簡單性和速度?

+0

正則表達式會比檢查前幾個字節便宜嗎?速度至關重要,但我也需要低誤報率。 – 2011-05-24 19:17:39

+0

你至少還應該做一個手動的$ string [0]比較。但是PCRE通常會更快地進行驗證。 – mario 2011-05-24 19:56:05

+0

啊,我明白你的意思了,我沒有看到森林,只有很多樹木。謝謝,是的,一個簡短的比賽,然後比較$ string [0]來驗證垃圾將比我正在考慮的更好。感謝您的幫助! – 2011-05-24 20:00:57

0

您可以嘗試json_decode()unserialize(),如果它們失敗,將返回NULL,然後base64_decode()並再次運行。它不是快速的,但它比解析它們的手無限少...

+1

我試圖想出一種方法來做一個'最佳猜測',希望避免每次都會降低可能性。這可以想象,加載和比較每小時cron數千個文件,速度真的很重要。 – 2011-05-24 18:51:26

0

這裏的問題是,如果你不知道它是什麼,你需要開發一個檢測算法。應該使用擴展名來設置約定(檢查擴展名,如果失敗,告訴誰將文件放在那裏以放置正確的擴展名),否則您需要檢查自己。大多數檢測實際文件類型的算法都會使用foreustics來確定它的內容(exe,jpg等),因爲通常它們有某種標識它們的簽名。因此,如果您不知道內容將用於定義什麼內容,最好查找特定於這些內容的功能。這有時意味着讀取多個字節。

1

對於速度,您可以使用file(1)實用程序並在/usr/share/file/magic中添加「幻數」。它應該比純粹的PHP選擇更快。

+0

這可能會起作用,但這必須是便攜式的。它是那些跆拳道之一?當你得到要求時,但必須這樣做。因爲如果你只是在處理GNU系統,問題就解決了。 – 2011-05-24 20:44:38

相關問題