1. 程式人生 > >php中的檔案包含

php中的檔案包含

php關鍵詞

      php中用於檔案包含的關鍵詞有:include、include_once、require、require_once。一般來說,把include和require分在一組裡,而include_once和require_once是一種改進完善形式。本文通過研究include和require的性質,兼顧include_once和require_once,獲得php檔案包含的基本知識和潛在問題,並提供一個可行的解決方案。

被包含檔案的型別

      使用包含關鍵詞包含的檔案,只要是文字檔案,php解析器都將檔案的內容作為php檔案處理。
     也即php解析器將當前執行指令碼的包含檔案讀出後,將php嵌入標籤中的內容作為原始碼執行,而其他沒有被標籤包含的將作為文字直接輸出。      設有兩個檔案a和b.php,內容分別如下:
a
akjfladskjfla<br> <? echo $_SERVER['PHP_SELF'],'<br>'; echo 'I am A<br>'; ?>

b.php
<?php include 'a'; echo $_SERVER['PHP_SELF'],'<br>'; echo 'I am B<br>'; ?>

     輸出如下:
akjfladskjfla  /webapp/codesnipe/b.php
I am A
/webapp/codesnipe/b.php
I am B
           檔案a無後綴名,其中包含了一個php嵌入標籤。如果執行檔案a,系統將會報錯。但是在檔案b中,包含了檔案a。沒有被包含在php嵌入標籤中的文字被直接輸出,而包含在標籤中的文字作為php原始碼執行。

資訊格式

      還是上面的實驗,我們把檔案a刪除,執行b.php。報錯資訊如下:
Warning: include(a) [function.include]: failed to open stream: No such file or directory in C:/xampp/htdocs/webapp/codesnipe/b.php on line 3

Warning: include() [function.include]: Failed opening 'a' for inclusion (include_path='.;C:/xampp/php/pear/') in C:/xampp/htdocs/webapp/codesnipe/b.php
 on line 3
/webapp/codesnipe/b.php
I am B

       可以對照上面,總結出報錯資訊的格式如下:        語句或函式:failed to open stream:具體的提示資訊,在檔案的第幾行

include和require的區別

      當遇到檔案找不到的情況是,它們的處理不同。include會發出警告,然後繼續執行下去;require則報錯,並停止當前指令碼的執行。
      資訊格式中給出的警告格式就是include發出的。兩個警告之後就是b.php的輸出內容。如果將include換成require,則資訊如下:
Warning: require(a) [function.require]: failed to open stream: No such file or directory in C:/xampp/htdocs/webapp/codesnipe/b.php on line 3

Fatal error: require() [function.require]: Failed opening required 'a' (include_path='.;C:/xampp/php/pear/') in C:/xampp/htdocs/webapp/codesnipe/b.php on line 3

      可見,它們資訊的格式相同,而且require第二個資訊變成了Fatal error。錯誤資訊後也沒有b.php執行後的輸出,因為require報錯之後就是的指令碼的執行退出了。

檔案包含的死迴圈

     最簡單的死迴圈形式是兩個檔案的形式:a.php和b.php。如果a.php中包含檔案b.php,而b.php中包含檔案a.php,則無論執行a.php還是b.php,都會進入死迴圈。
     只要將第一個例子中的a加上包含b.php的語句,就可以得到一個很好的例子。死迴圈的原因還容易理解,這裡不做解釋。可能有人覺得專案開發時不會犯這種低階的錯誤。專案小的時候可能正確,但是一個大型的軟體多人合作,如何保證沒有潛在的執行環呢?再說,從維護的角度來說,這種設計也不合理。

include_once和require_once

     include_once和require_once在第一次執行時,其結果和include和require一樣。其後再遇到檔案包含關鍵詞(同組的關鍵詞)則會跳過不執行。
     假設有三個檔案:indexa.php、indexb.php和indexc.php。其原始碼如下:
indexa.php
<?php include_once 'indexb.php'; echo $_SERVER['PHP_SELF'],'<br>'; echo 'I am A<br>'; ?>

indexb.php
<?php include_once 'indexa.php'; include_once 'indexc.php'; echo $_SERVER['PHP_SELF'],'<br>'; echo 'I am B<br>'; ?>

indexc.php
<?php include_once 'indexb.php'; include_once 'indexa.php'; echo $_SERVER['PHP_SELF'],'<br>'; echo 'I am C<br>'; ?>

輸出如下:
/webapp/codesnipe/indexa.php
I am C
/webapp/codesnipe/indexa.php
I am B
/webapp/codesnipe/indexa.php
I am A

     執行檔案indexa.php,遇到包含語句包含indexb.php,所以讀入indexb.php的原始碼。indexb.php的原始碼的第一句就包含檔案indexa.php。由於indexa.php的內容已經存在,故該包含語句無效;第二局包含indexc.php。indexc.php的原始碼的第一句包含檔案indexb.php。基於indexb.php的內容已經存在,故該語句同樣無效;同樣的第二個語句也無效。最後程式執行,結果就如上面所示。      將任一個include_once語句換成require_once,程式執行一樣。因而在同組內,處理錯誤處理不同,並沒有什麼差別。      為了更形象地理解,我們可以設想php解析器會給每個執行檔案建立一個原始碼來源記錄表。記錄表記錄了原始碼被包含進來的檔案完整路徑。include_once和require_once會在每次包含新檔案時,檢查新檔案是否已經在記錄表中。如果已經存在,檔案內容不會被包含進來;否則檔案路徑被記錄入記錄表,並將其內容包含進來。

與前一組的區別

     這裡不需要多說,include和require並不檢查記錄表,這就是差別。通過這種方式,我們很容易解決潛在的死迴圈的問題,提高程式的可靠性。

目錄結構導致的錯誤

     檔案包含除了受到檔案包含關係影響,第二個重要因素就是檔案包含的目錄結構。前面的原始碼中我都包含了變數$_SERVER['PHP_SELF']的值。從輸出中可以看出變數的值是當前正在執行的指令碼的名稱,就是直接執行請求的php檔案而不是包含進來的檔案。這個事實說明,被包含檔案的原始碼將被執行在直接執行檔案的環境中,不如最終要的檔案查詢路徑。      一個簡單的例子。專案包含一個資料夾include,下面是兩個檔案indexb.php和indexc.php。和資料夾include同目錄的是檔案indexa.php。原始碼如下:
indexa.php
<?php include_once 'include/indexb.php'; echo $_SERVER['PHP_SELF'],'<br>'; echo 'I am A<br>'; ?>

indexb.php
<?php include_once './indexc.php'; echo $_SERVER['PHP_SELF'],'<br>'; echo 'I am B<br>'; ?>

indexc.php
<?php echo $_SERVER['PHP_SELF'],'<br>'; echo 'I am C<br>'; ?>

輸出如下:
Warning: include_once(./indexc.php) [function.include-once]: failed to open stream: No such file or directory in C:/xampp/htdocs/webapp/codesnipe/include/indexb.php on line 3

Warning: include_once() [function.include]: Failed opening './indexc.php' for inclusion (include_path='.;C:/xampp/php/pear/') in C:/xampp/htdocs/webapp/codesnipe/include/indexb.php on line 3
/webapp/codesnipe/indexa.php
I am B
/webapp/codesnipe/indexa.php
I am A

上面的輸出可以看出,indexb.php的原始碼中的"./indexc.php"中的"."指向的是indexa.php所在的目錄而不是include目錄本身,因而導致檔案查詢錯誤。如果把indexb.php中的"./indexc.php"改成"indexc.php",那麼指令碼將正常執行。這是因為php本身會有一個預設的檔案查詢路徑值。但是從可維護性角度來說,這種僥倖的正確時不可行的。

一個解決方案

     由於存在上面的問題,所以專案設計時會有一個系統的配置檔案,在配置檔案中設定系統的路徑值,通過這種方式來獲得要包含檔案的絕對路徑,從而避免上面的問題。具體的說明可見下一篇文章。

相關推薦

php://filter(檔案包含漏洞利用)

 檔案包含漏洞:https://blog.csdn.net/fageweiketang/article/details/80699051 篩選過濾應用:  1、 字串過濾器: string.rot13 對字串執行ROT13轉換 string.to

CTF檔案包含的一些技巧

i春秋作家:lem0n 原文來自:淺談記憶體取證 0x00 前言 網路攻擊記憶體化和網路犯罪隱遁化,使部分關鍵數字證據只存在於實體記憶體或暫存於頁面交換檔案中,這使得傳統的基於檔案系統的計算機取證不能有效應對.記憶體取證作為傳統檔案系統取證的重要補充,是計算機取證科學的重要組成部分,通過

【root-me CTF練習】Web伺服器安全-PHP 遠端檔案包含

靶機地址 http://challenge01.root-me.org/web-serveur/ch13/ 解題思路 根據題目,得知考的應該是include()函式遠端包含檔案,那麼則需要php.ini的配置選項allow_url_fopen和allow_u

PHP檔案上傳的功能模組實現

最近專案中PHP使用的比較多,對於一個前端的使用者,對其中的一些知識點記錄下來。今天講一下,檔案上傳的功能實現的一些知識。之前在專案中使用的nodejs實現過類似的功能,用PHP在做的時候,發現差不多大同小異。背後的邏輯差不多都是一樣的。 1.前端頁面要做的是,首先是提交方

php檔案包含

php關鍵詞       php中用於檔案包含的關鍵詞有:include、include_once、require、require_once。一般來說,把include和require分在一組裡,而include_once和require_once是一種改進完善形式。本文通過

PHP調用SVN命令更新網站方法(解決文件名包含中文更新失敗的問題)

設置 php tro 參數 名稱 www 文件 命令 更新失敗 想說寫一個通過網頁就可以執行 SVN 升級的程序,結果並不是我想得那樣簡單,有一些眉角需要註意的說。 先以 Apache 的用戶帳號執行 SVN checkout,這樣 Apache 才有 SVN 的鏈結權力,

PHP的文件包含

條件語句 就會 spa 腳本 服務器 即使 兩種 情況 查看 在PHP中,包含文件有兩種方式:include和require。這兩種方式的功能一樣,只有一個區別,就是使用require包含一個文件時,如果出現錯誤,腳本不會繼續執行;而如果使用include包含,即使出現錯誤

php程式碼實現form表單檔案的上傳

<?php //1、注意:檔案上傳之後的資訊都儲存在$_FILES全域性變數中。 // print_r($_FILES); //2、判斷使用者是否提交資料 if(!empty($_FILES)){ //3、獲取當前上傳檔案的型別 $type=$_FILES["m

PHPcurl模擬post上傳及接收檔案

public function Action_Upload(){ $this->path_config(); exit(); $furl="@d:\develop\JMFrameworkWithDemo.rar"; $url= "http://localh

php 字串是否包含指定字串的多種方法

編寫程式的時候,經常要處理字串,最基本就是字串的查詢,在php檢測字串中是否包含指定字串可以使用正則,如果你對正則不瞭解,那麼有幾個函式可以為您提供方便。 1. strstr strstr() 函式搜尋一個字串在另一個字串中的第一次出現。 該函式返回字串的其餘部分(從匹配點)。如果未找到所搜

opencv3.3 該檔案包含不能在當前內碼表(936)表示的字元。請將該檔案儲存為 Unicode 格式以防止資料丟失

VS2015 + opencv3.3 執行報錯: warning C4819: 該檔案包含不能在當前內碼表(936)中表示的字元。請將該檔案儲存為 Unicode 格式以防止資料丟失  error C2065: “ptr”: 未宣告的識別符號 error C2065: “ptr”:

simplelink_cc2640r2_sdk_1_40_00_45 之 C/C++ Compiler 標頭檔案包含的巨集值

simplelink_cc2640r2_sdk_1_40_00_45 ---------------------------------------------------------------- $SRC_BLE_DIR$=C:\Users\coolban_one\Desktop\C

VS2017 報錯該檔案包含不能在當前內碼表(936)表示的字元。請將該檔案儲存為 Unicode 格式以防止資料丟失

尤其程式碼是從linux平臺複製過來: 報錯如圖: 更有甚者基本函式都報錯: 當下檢查發現if else break case等基本函式並無問題時,報錯行數明顯不一致等一定要注意文件編碼格式, 最簡單的辦法是用notepad++,逐個將.

PHP./和/的使用區別,相對路徑巢狀包含問題,專案使用絕對路徑

./:表示同級目錄(當前檔案所屬資料夾),每個資料夾下都有“.”檔案,代表當前目錄 ../:表示上級目錄(當前檔案所屬資料夾的上級資料夾),每個資料夾下都有“..”檔案,表示上級目錄 什麼都沒有:就是表示同級目錄。區別./在於./會自動匹配任意目錄下的.資料夾,被其他檔案包含之後會

bugku-flag在index裡(本地檔案包含漏洞+php偽協議)

題目地址http://123.206.87.240:8005/post/ click點選進去 從 url地址可以猜測,需要用到 php://filter偽協議。 用法: php://filter/read=convert.base64encode/resourc

PHP使用Redis接管檔案儲存Session

前言 之前找了網上的一套直播系統給客戶用,剛開始是沒問題的,在後麵人數上來之後網站開始變得卡頓,卡的一批。之後檢視php慢日誌發現session_start()的身影,好吧,原來是萬惡的檔案儲存session,跟我之前進的坑一模一樣……之前做的教務查詢系統直接用的session沒有用cookie,結果在高併

php fogets讀取檔案

<?php header('content-type:text/html;charset=utf-8'); $file ="1.txt"; if(!file_exists($file)){ die('檔案不存在'); } //檢測檔案是否存在 $str = file_get_

php資料的儲存(主要講述的檔案的儲存)

程式語言中對資料劃分了很多的型別,但資料與之相關的有兩個方面:其一是值,其二是型別。 程式在運算的過程中,會產生資料,但程式執行結束記憶體中的資料都會丟失。如果想儲存程式執行過程中產生資料,要儲存起來。儲存的位置文字檔案或資料庫。 但是文字檔案中只能儲存字元資訊。為了將資料的資料與型別一

PHP使用Redis接管檔案儲存Session詳解

前言 php預設使用檔案儲存session,如果併發量大,效率會非常低。而redis對高併發的支援非常好,可以利用redis替換檔案來儲存session。 最近就遇到了這個問題,之前找了網上的一套直播系統給客戶用,剛開始是沒問題的,在後麵人數上來之後網站開始變得卡頓,卡的一批。之後檢視php慢日誌發現se

php檔案包含漏洞(利用phpinfo)復現

 利用docker復現該漏洞,訪問http://192.168.80.156:8080/phpinfo.php,可以看到頁面出現phpinfo頁面 再訪問http://192.168.80.156:8080/lfi.php?file=/etc/passwd,可以看到該頁面是存在檔案包含漏洞的。