Rev 220 | Rev 239 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
<?php/*QBPWCF, Quick Build PHP website Component base on Fedora Linux.Copyright (C) 2014~2025 MIN ZHI, CHENThis file is part of QBPWCF.QBPWCF is free software: you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation, either version 3 of the License, or(at your option) any later version.QBPWCF is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with QBPWCF. If not, see <http://www.gnu.org/licenses/>.*/namespace qbpwcf;/*類別說明:跟socket應用相關的類別.備註:無.*/class sock{/*#函式說明:#當前類別被呼叫的靜態方法不存在時,將會執行該函數,回報該方法不存在.#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$reuslt["error"],執行不正常結束的錯訊息陣列.#$result["function"],當前執行的函式名稱.#必填參數:#$method,物件,為物件實體或類別名稱,會自動置入該參數.#$arguments,陣列,為呼叫方法時所用的參數.#可省略參數:#無.#參考資料:#__call=>http://php.net/manual/en/language.oop5.overloading.php#object.callstatic#備註:#無.*/public function __call($method,$arguments){#取得當前執行的函式$result["function"]=__FUNCTION__;#設置執行不正常$result["status"]="false";#設置執行錯誤$result["error"][]=__NAMESPACE__ ."/".$method."() 不存在!";#設置所丟入的參數$result["error"][]=$arguments;#回傳結果return $result;}#function __call end/*#函式說明:#當前類別被呼叫的靜態方法不存在時,將會執行該函數,回報該方法不存在.#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$reuslt["error"],執行不正常結束的錯訊息陣列.#$result["function"],當前執行的函式名稱.#必填參數:#$method,物件,為物件實體或類別名稱,會自動置入該參數.#$arguments,陣列,為呼叫方法時所用的參數.#可省略參數:#無.#參考資料:#__callStatic=>http://php.net/manual/en/language.oop5.overloading.php#object.callstatic#備註:#無.*/public static function __callStatic($method,$arguments){#取得當前執行的函式$result["function"]=__FUNCTION__;#設置執行不正常$result["status"]="false";#設置執行錯誤$result["error"][]="欲呼叫的". __NAMESPACE__ ."/".$method."() 不存在!";#設置所丟入的參數$result["error"][]=$arguments;#回傳結果return $result;}#function __callStatic end/*#函式說明:#建立 unix domain socket server, 僅提供具備檔案存取權限的用戶使用,預設提供可以下達任何指令的功能.#回傳結果:#$result["status"],"true"代表執行正常;"false"代表執行不正常.#$result["error"],錯誤訊息陣列.#$result["function"],當前執行的函式名稱.#$result["serverCache"],函式結束前,儲存在serverCache的內容,若有元素"exit"存在則代表是正常結束.#$result["serverCache"]["serverSide"],server side 的 cache.#$result["serverCache"]["serverSide"]["procs"], server side 的 procs cache,儲存執行的子程序資訊.#$result["serverCache"]["clientSide"],client site 的 cache.#必填參數:#$conf["sock"],字串,socket檔案要放在哪邊,名稱為何.$conf["sock"]="";#$conf["fileArgu"],字串,變數__FILE__的內容.$conf["fileArgu"]=__FILE__;#可省略參數:#$conf["changeOwner"],字串,要將socket檔案的擁有着權限進行修改."user.group"代表擁有者帳號為user,群組為group.#$conf["changeOwner"]="";#$conf["changePermission"],字串,要將socket檔案的權限設為多少.ex: "0666"(所有帳戶都有存取的權限) 或 "0660"(僅有擁有者與群組帳戶有存取的權限) 或 "0600"(只有擁有者有權限執行).#$conf["changePermission"]="";#$conf["sessionTimeout"],字串,當連線結束後於下一次連線間隔多久就算session timeout,server端會將記錄移除,client端需要重新拿取id,預設為300秒.#$conf["sessionTimeout"]="300";#$conf["addOnProcessFunc"],字串陣列,增加用於處理 json request 的函式名稱,給予的參數為array("request"=>收到的json訊息,"sock"=>用戶的socket,"clientCache"=>給予所有用戶的cache),若收到的不是json而是"quit"則代表用戶要結束連線;若收到的是$shutdownStr則代表要結束本函式.回傳的內容必須為陣列,例如 $res["continue"]="true"代表要繼續執行下一個addOnProcessFunc;"false"代表代表到此為止. $res["content"]="replaced content";代表要將收到的訊息取代成"replaced content". 最少要有回傳 $res["status"]數值"true"代表執行正常;"false"代表執行不正常.#$conf["addOnProcessFunc"]=array();#$conf["funcToRunWhenIdle"],字串陣列,當沒有事件產生時,要執行的函式名稱,給予參數為array("client"=>所有用戶,"clientCache"=>$result["serverCache"]["clientSide"]["addOnProcessFunc"][$funcToRunWhenIdle],"serverCache"=>$result["serverCache"]["serverSide"]["funcToRunWhenIdle"][$funcToRunWhenIdle]).#$conf["funcToRunWhenIdle"]=array();#$conf["paramsForFuncToRunWhenIdle"],2維陣列,每個元素代表指定給予funcToRunWhenIdle參數中的指定元素的參數.#$conf["paramsForFuncToRunWhenIdle"]=array();#$conf["infoToFunction"],陣列,需要增加給addOnProcessFunc跟funcToRunWhenIdle函式的資訊,在函式中其參數的info鍵值.#$conf["infoToFunction"]=array("debug"=>$debug);#$conf["shutdownStrAddr"],字串,儲存收到用戶傳什麼樣的字串會結束本函式的檔案位置與名稱,預設為 $conf["sock"].".shutdown".#$conf["shutdownStrAddr"]="";#參考資料:#http://php.net/manual/en/function.stream-socket-server.php#備註:#無.*/public static function unixDomainSockServer(&$conf){#初始化要回傳的結果$result=array();#取得當前執行的函數名稱$result["function"]=__FUNCTION__;#如果沒有參數if(func_num_args()==0){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]="函數".$result["function"]."需要參數";#回傳結果return $result;}#if end#涵式說明:#判斷當前環境為web還是cmd#回傳結果:#$result,"web"或"cmd"if(csInformation::getEnv()==="web"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"][]="函數 ".$result["function"]." 僅能在命令列環境下運行!";#回傳結果return $result;}#if end#取得參數$result["argu"]=$conf;#如果 $conf 不為陣列if(gettype($conf)!="array"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"][]="\$conf變數須為陣列形態";#如果傳入的參數為 nullif($conf==null){#設置執行錯誤訊息$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";}#if end#回傳結果return $result;}#if end#檢查參數#函式說明:#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容。#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$reuslt["error"],執行不正常結束的錯訊息陣列.#$result["function"],當前執行的函式名稱.#$result["argu"],設置給予的參數.#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.#$result["argu"],字串陣列,目前輸入的參數名稱陣列.#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.#$result["notNeedVar"],字串陣列,多餘的參數名稱.#必填寫的參數:#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。$conf["variableCheck::checkArguments"]["varInput"]=&$conf;#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";#可以省略的參數:#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("sock","fileArgu");#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string","string");#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.#$conf["canBeEmptyString"]="false";#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.#$conf["canNotBeEmpty"]=array();#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.#$conf["canBeEmpty"]=array();#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("changeOwner","changePermission","sessionTimeout","addOnProcessFunc","funcToRunWhenIdle","infoToFunction","shutdownStrAddr");#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("changeOwner","changePermission","sessionTimeout","addOnProcessFunc","funcToRunWhenIdle","infoToFunction","paramsForFuncToRunWhenIdle","shutdownStrAddr");#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","string","string","array","array","array","array","array");#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf[\"mustBeFilledVar\"]".$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("root.".webUser,null,"300",null,null,null,array(),null);#$conf["disallowAllSkipableVarIsEmpty"],字串,是否允許每個可省略參數都為空字串,預設為"true"允許,反之為"false".#$conf["disallowAllSkipableVarIsEmpty"]="";#$conf["disallowAllSkipableVarIsEmptyArray"],字串,是否允許每個可省略參數都為空陣列,預設為"true"允許,反之為"false".#$conf["disallowAllSkipableVarIsEmptyArray"]="";#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.#$conf["arrayCountEqualCheck"][]=array();#參考資料來源:#array_keys=>http://php.net/manual/en/function.array-keys.php$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);unset($conf["variableCheck::checkArguments"]);#如果檢查參數失敗if($checkArguments["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$checkArguments;#回傳結果return $result;}#if end#如果檢查參數不通過if($checkArguments["passed"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$checkArguments;#回傳結果return $result;}#if end#縮減 socket 的路徑,避免出錯.#函式說明:#將檔案目錄的絕對位置中的 "../" 剔除變成直觀的路徑.#回傳結果:#$result["status"],執行是否成功,"true"代表執行成功,"false"代表執行失敗.#$result["function"],當前執行的函數.#$result["error"],錯誤訊息陣列.#$result["argu"],使用者參數.#$result["changedPath"],處理完後回傳的目錄字串.#$result["oriPath"],原始的路徑字串#必填參數:#$conf["dirStr"],字串,要處理的檔案目錄字串.$conf["stringProcess::changeDirByDotDotSolidus"]["dirStr"]=$conf["sock"];#可省略參數:#無.#參考資料:#無.#備註:#考慮用realpath取代$changeDirByDotDotSolidus=stringProcess::changeDirByDotDotSolidus($conf["stringProcess::changeDirByDotDotSolidus"]);unset($conf["stringProcess::changeDirByDotDotSolidus"]);#如果執行異常if($changeDirByDotDotSolidus["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$changeDirByDotDotSolidus;#回傳結果return $result;}#if end#取得整理過後的直觀路徑$conf["sock"]=$changeDirByDotDotSolidus["changedPath"];#取得 socket 的路徑#函式說明:#將字串特定關鍵字與其後面的內容剔除#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$result["error"],錯誤訊息陣列.#$result["warning"],警告訊息鎮列.#$result["founded"],有無找到定字串"true"代表有,"false"代表沒有.#$result["function"],當前執行的函數名稱.#$result["oriStr"],要處理的原始字串內容.#$result["content"],處理好的的字串內容.#$result["argu"],使用的參數.#必填參數:#$conf["stringIn"],字串,要處理的字串.$conf["stringProcess::delStrAfterKeyWord"]["stringIn"]=$conf["sock"];#$conf["keyWord"],字串,特定字串.$conf["stringProcess::delStrAfterKeyWord"]["keyWord"]="/";#可省略參數:#$conf["deleteLastRepeatedOne"],字串,預設為"false";若為"true"則代表連續遇到同 $conf["keyWord"] 的內容,要將移除內容的起點往後移動到為後一個 $conf["keyWord"].$conf["stringProcess::delStrAfterKeyWord"]["deleteLastRepeatedOne"]="true";#參考資料:#無.#備註:#無.$delStrAfterKeyWord=stringProcess::delStrAfterKeyWord($conf["stringProcess::delStrAfterKeyWord"]);unset($conf["stringProcess::delStrAfterKeyWord"]);#如果執行失敗if($delStrAfterKeyWord["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"][]=$delStrAfterKeyWord;#設置錯誤訊息$result["error"][]="建立 unix domain socket(".$conf["sock"].") 失敗";#印出錯誤訊息echo print_r($result,true);#回傳結果return $result;}#if end#如果有 "/"if($delStrAfterKeyWord["founded"]==="true"){#確保建立socket的路徑有存在#函式說明:#確保路徑存在.#回傳結果:#$result["status"],執行正常與否,"true"代表正常,"false"代表不正常.#$result["error"],錯誤訊息陣列.#$resutl["function"],當前執行的涵式名稱.#$result["path"],建立好的路徑字串.#$result["fileName"],檔案名稱,若 $conf["haveFileName"] 為 "true" 則會回傳.#$result["argu"],使用的參數.#必填參數:#$conf["path"],要檢查的路徑$conf["fileAccess::validatePath"]["path"]=$delStrAfterKeyWord["content"];#$conf["fileArgu"],字串,php變數__FILE__的內容,亦即該檔案在檔案系統的絕對路徑$conf["fileAccess::validatePath"]["fileArgu"]=__FILE__;#可省略參數:#$conf["haveFileName"],字串,"true"代表有$conf["path"]檔案名稱,"false"代表$conf["path"]為純路徑,預設為"false".$conf["fileAccess::validatePath"]["haveFileName"]="false";#$conf["dirPermission"],字串,新建資料夾的權限設定,預設爲0770,亦即擁有者,同群組者可以讀,寫,存取,其他人僅能存取.#$conf["dirPermission"]="";#$conf["web"],是否為檔案系統,"true"為網頁路徑,"false"為網頁系統,預設為"false".$conf["fileAccess::validatePath"]["web"]="false";#參考資料:#無.#備註:#無.$validatePath=fileAccess::validatePath($conf["fileAccess::validatePath"]);unset($conf["fileAccess::validatePath"]);#如果執行失敗if($validatePath["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"][]=$validatePath;#設置錯誤訊息$result["error"][]="建立 unix domain socket(".$conf["sock"].") 失敗";#印出錯誤訊息echo print_r($result,true);#回傳結果return $result;}#if end}#if end#如果同名 unix domain socket file 存在if(file_exists($conf["sock"])){#則移除之.unlink($conf["sock"]);}#if end#預設的 unix socket addr$unixAddr="unix://".$conf["sock"];#建立 unix domain socket$socket=stream_socket_server($unixAddr, $errno, $errstr);#如果建立 unix domain socket 失敗if(!$socket){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"][]=$errstr." (".$errno.")";#設置錯誤訊息$result["error"][]="建立 unix domain socket(".$conf["sock"].") 失敗";#印出錯誤訊息echo print_r($result,true);#回傳結果return $result;}#if end#如果建立 unix domain socket 成功else{#產生用於代表結束本函式的字串#函式說明:#使用 linux 的 uuid 指令來產生 uuid 字串#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$result["error"],錯誤訊息.#$result["function"],當前執行的函式名稱.#$result["content"],uuid.#必填參數:#無.#可省略參數:#無.#參考資料:#無.#備註:#無.$uuid=cmd::uuid();#如果執行失敗if($uuid["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$uuid;#回傳結果return $result;}#if end#設置代表結束本服務的uuid字串$shutdownStr=$uuid["content"];#如果沒有設置if(!isset($conf["shutdownStrAddr"])){#初始化存放 shutdownStr 的檔案$conf["shutdownStrAddr"]=$conf["sock"].".shutdownStr";}#if end#如果檔案位置名稱跟socket一樣else if($conf["sock"]===$conf["shutdownStrAddr"]){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"][]="參數shutdownStrAddr跟sock不可一樣";#設置錯誤訊息$result["error"][]=$checkArguments;#回傳結果return $result;}#else end#建立裡面儲存若要結束本程式需要接收到什麼樣的字串#函式說明:#將字串寫入到檔案#回傳結果:#$result["status"],"true"表示檔案寫入成功,"false"表示檔案寫入失敗.#$result["error"],錯誤訊息陣列.#$result["function"],當前執行的函數名稱.#$result["fileInfo"],實際上寫入的檔案資訊陣列.#$result["fileInfo"]["createdFileName"],建立好的檔案名稱.#$result["fileInfo"]["createdFilePath"],檔案建立的路徑.#$result["fileInfo"]["createdFilePathAndName"].建立好的檔案名稱與路徑.#$result["argu"],使用的參數.#必填參數:#$conf["fileArgu"],字串,php變數__FILE__的內容,亦即該檔案在檔案系統的絕對路徑$conf["fileAccess::writeTextIntoFile"]["fileArgu"]=$conf["fileArgu"];#可省略參數:#$conf["fileName"],字串,爲要編輯的檔案名稱,預設為隨機產生的檔案名稱.$conf["fileAccess::writeTextIntoFile"]["fileName"]=$conf["shutdownStrAddr"];#$conf["inputString"],字串,爲要寫入到裏面的內容,若要每筆資料寫入後換行,則可以在字串內容後面加上 \r\n 即可,預設為"".$conf["fileAccess::writeTextIntoFile"]["inputString"]=$shutdownStr;#$conf["writeMethod"],字串,爲檔案撰寫的方式,可省略,是複寫'a'還是,重新寫入'w',預設爲'w',重新寫入.#$conf["writeMethod"]="a";#$conf["checkRepeat"],字串,"true"代表建立檔案之前要先檢查檔案是否存在,若存在則在原名稱後面加上從(1)開始的編號.#$conf["checkRepeat"]="";#$conf["filenameExtensionStartPoint"],字串,檔案的副檔名是從倒數第幾個小數點(dot)開始,預設為"1",最後一個小數點,必須與$conf["checkRepeat"]搭配才會生效.#$conf["filenameExtensionStartPoint"]="";#$conf["repeatNameRule"],字串,遇到相同名稱的檔案要如何加上識別的編號,編號用「\$i」表示,預設為"(\$i)",必須與$conf["checkRepeat"]搭配才會生效.#$conf["repeatNameRule"]="";#$conf["web"],檔案是否位於網站上"true",若是在檔案系統則為"false",預設為"true".$conf["fileAccess::writeTextIntoFile"]["web"]="false";#參考資料:#無.#備註:#無.$writeTextIntoFile=fileAccess::writeTextIntoFile($conf["fileAccess::writeTextIntoFile"]);unset($conf["fileAccess::writeTextIntoFile"]);#如果執行失敗if($writeTextIntoFile["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$writeTextIntoFile;#回傳結果return $result;}#if end#debug#var_dump(__LINE__,$writeTextIntoFile);exit;#初始化 client 陣列$client=array();#如果有設置$conf["changeOwner"]if(isset($conf["changeOwner"])){#如果裡面的"."不是一個if(substr_count($conf["changeOwner"],".")!==1){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"][]="參數 changeOwner 應為 username.groupname";#印出錯誤訊息echo print_r($result,true);#回傳結果return $result;}#if end#改變檔案的擁有者#函式說明:#使用 linux 的 chown 指令來修改目標檔案或目錄的擁有者跟群組擁有者資訊.#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$result["error"],錯誤訊息.#$result["function"],當前執行的函式名稱.#$result["cmd"],執行的指令.#$result["content"],執行的結果陣列,如果參數 "recursive" 跟 "excludeSelf" 都有設定的話,就會回傳該結果.#必填參數:#$conf["owner"],字串,要變哪個使用者擁有.$conf["cmd::chown"]["owner"]=explode(".",$conf["changeOwner"])[0];#$conf["target"],字串,需要變更擁有者、 群組的目標.$conf["cmd::chown"]["target"]=$conf["sock"];#可省略參數:#$conf["group"],字串,要變成什麼群組擁有,預設跟"owner"一樣.$conf["cmd::chown"]["group"]=explode(".",$conf["changeOwner"])[1];#$conf["recursive"],字串,"true"代表目標目錄底下的內容都要套用,預設為"false".#$conf["recursive"]="true";#$conf["excludeSelf"],字串,預設為"false"代表不處理;若為"true"則會排除目標自己(資料夾).#$conf["excludeSelf"]="true";#參考資料:#無.#備註:#無.$chown=cmd::chown($conf["cmd::chown"]);unset($conf["cmd::chown"]);#如果改變檔案擁有者限失敗if($chown===false){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"][]="改變 ".$conf["sock"]." 檔案的擁有資訊為 ".explode(".",$conf["changeOwner"])[0]." 失敗,通常只有系統帳戶才能變更之.";#印出錯誤訊息echo print_r($result,true);#回傳結果return $result;}#if end}#if end#如果有設置 $conf["changePermission"]if(isset($conf["changePermission"])){#函式說明:#使用 linux 的 chmod 指令來修改目標檔案或目錄的權限.#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$result["error"],錯誤訊息.#$result["function"],當前執行的函式名稱.#$result["cmd"],執行的指令.#$result["content"],執行的結果陣列,如果參數 "recursive" 跟 "excludeSelf" 都有設定的話,就會回傳該結果.#必填參數:#$conf["mode"],字串,要變成什麼權限.$conf["cmd::chmod"]["mode"]=$conf["changePermission"];#$conf["target"],字串,需要變更權限的目標.$conf["cmd::chmod"]["target"]=$conf["sock"];#可省略參數:#$conf["recursive"],字串,"true"代表目標目錄底下的內容都要套用,預設為"false".#$conf["recursive"]="true";#$conf["excludeSelf"],字串,預設為"false"代表不處理;若為"true"則會排除目標自己(資料夾).#$conf["excludeSelf"]="true";#參考資料:#無.#備註:#無.$chmod=cmd::chmod($conf["cmd::chmod"]);unset($conf["cmd::chmod"]);#如果變更檔案權限失敗if($chmod["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$chmod;#印出錯誤訊息echo print_r($result,true);#回傳結果return $result;}#if end}#if end#初始化儲存 server 資訊的變數,預設數值為 $result 自己$result["serverCache"]=&$result;#初始化方便識別 server 資訊的變數$serverCache=&$result["serverCache"];#初始化 server site cache$serverCache["serverSide"]=array();#初始化 儲存 透過 proc 執行的子程序$serverCache["serverSide"]["procs"]=array();#初始化 client site cache$serverCache["clientSide"]=array();#初始化方便識別 client site cache 資訊的變數$clientCache=&$serverCache["clientSide"];#將建立的 listen sock 放到 $master 陣列$master[] = $socket;#永久監聽, 不 timeoutwhile(true){#debug#var_dump(__LINE__,gmdate("Y-m-d H:i:s",time()));#設置給 stream_select 監控的sock變數$read = $write = $except = $master;#等待5秒,看有沒有連線進來讀寫資料$mod_fd = stream_select($read, $write, $except, 5);#如果執行失敗if($mod_fd===FALSE){#提示錯誤訊息echo "Stream_select failed at ".gmdate("Y-m-d H:i:s",time());#結束監聽exit(1);}#if end#如果沒有訊息,代表閒置時可以做的事情else if($mod_fd===0){#提示idleecho ".";#清除 session timeout 的連線 - start#初始化要給 server 的回應$res=array();#初始化計數移除幾個用戶$res["delIdleConCount"]=0;#針對每個 $clientforeach($client as $index=>$uncheckClient){#如果上次的要求時間為300秒前.if(time()-(int)$uncheckClient["last_req_time"]>$conf["sessionTimeout"]){#移除該用戶變數unset($client["$index"]);#計數移除了幾個用戶$res["delIdleConCount"]++;}#if end}#foreach end#設置執行正常$res["status"]="true";#如果有移除閒置的連線if($res["delIdleConCount"]>0){#印出給 server 的訊息echo PHP_EOL."response:".PHP_EOL.print_r($res,true);}#if end#清除 session timeout 的連線 - end#清除 太久沒有 被查詢的 proc(子程序) - start#初始化要給 server 的回應$res=array();#初始化計數移除幾個沒被關注的子程序$res["delIdleProcCount"]=0;#針對每個 子程序foreach($serverCache["serverSide"]["procs"] as $procIndex=>$procInfo){#debug#var_dump(__FUNCTION__,__LINE__,$procInfo);#如果上次的要求時間為300秒前.if(time()-(int)$procInfo["latestAccessTime"]>$conf["sessionTimeout"]){#若運行中if($procInfo["content"][0]["statusCode"]==="?"){#更新資訊#函式說明:#更新透過proc執行的多程序資訊.#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$reuslt["error"],執行不正常結束的錯訊息陣列.#$result["function"],當前執行的函式名稱.#$result["argu"],使用的參數.#$result["content"],陣列,每個元素為其指令執行的結果訊息陣列,key為"status"代表執行是否正常的識別;key為"statusCode"代表程式結束後回傳給對應executeBy程式的數值;key為"output"代表標準輸出,若為resource,則代表為pipe;key為"error"代表非標準輸出,若為resource,則代表為pipe;key為"input"代表成功輸入的指令;key為"process"代表該程序經proc_open後的process source;key為"proc_get_status"代表程序的資訊.#必填參數:#$conf["procs"],陣列,運行self::proc後回傳的content.$conf["threads::proc_update"]["procs"]=$procInfo["content"];#可省略參數:#無.#參考資料:#無.#備註:#無.$proc_update=threads::proc_update($conf["threads::proc_update"]);unset($conf["threads::proc_update"]);#若執行不正常if($proc_update["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$proc_update;#印出錯誤訊息echo print_r($result,true);#回傳結果return $result;}#if end#更新程序狀態$procInfo["content"]=$proc_update["content"][0];#更新會後存取時間#若已經執行結束if($procInfo["content"]["statusCode"]!=="?"){#換下一個continue;}#if end#執行到這代表一樣再運行中#終止程序proc_close($procInfo["content"]["process"]);#移除該用戶變數unset($serverCache["serverSide"]["procs"][$procIndex]);#換下一個continue;}#if end#反之為已運行結束#移除該用戶變數unset($serverCache["serverSide"]["procs"][$procIndex]);#計數移除幾個沒被關注的子程序$res["delIdleProcCount"]++;}#if end}#foreach end#設置執行正常$res["status"]="true";#如果有移除沒被關注的子程序if($res["delIdleProcCount"]>0){#印出給 server 的訊息echo PHP_EOL."response:".PHP_EOL.print_r($res,true);}#if end#清除 太久沒有 被查詢的 proc(子程序) - end#如果有設置 idle 要執行的函式if(isset($conf["funcToRunWhenIdle"])){#提示有idle要執行的函式echo "response:".PHP_EOL."There is funcToRunWhenIdle param set.".PHP_EOL;#針對每個 funcToRunWhenIdleforeach($conf["funcToRunWhenIdle"] as $index => $funcToRunWhenIdle){#提示正要執行的函式echo "response:".PHP_EOL."Executeing ".$funcToRunWhenIdle."...".PHP_EOL;#初始化要給 funcToRunWhenIdle 函式的參數$parasmForFuncToRunWhenIdle=array();#取得所有用戶$parasmForFuncToRunWhenIdle["client"]=&$client;#如果有設置 infoToFunctionif(isset($conf["infoToFunction"])){#設置info$parasmForFuncToRunWhenIdle["info"]=&$conf["infoToFunction"];}#if end#debug#var_dump(__FILE__,__LINE__,$serverCache["serverSide"]);#如果屬於該 $funcToRunWhenIdle 的 server side cache 不存在if(!isset($serverCache["serverSide"]["funcToRunWhenIdle"][$funcToRunWhenIdle])){#初始化為空陣列$serverCache["serverSide"]["funcToRunWhenIdle"][$funcToRunWhenIdle]=array();}#if end#設置給予 $funcToRunWhenIdle 函式的 serverCache 參數$parasmForFuncToRunWhenIdle["serverCache"]=&$serverCache;#儲存 $funcToRunWhenIdle 函式 的運行結束的時間點到 server side 的 cache$serverCache["serverSide"]["funcToRunWhenIdle"][$funcToRunWhenIdle]["lastRunTime"]=time::unix()["content"];#如果有要指定給 $funcToRunWhenIdle 的參數if(isset($conf["paramsForFuncToRunWhenIdle"][$index])){#針對每個 要給予 funcToRunWhenIdle 的參數foreach($conf["paramsForFuncToRunWhenIdle"][$index] as $arguKeyForFuncToRunWhenIdle => $arguValueForFuncToRunWhenIdle){#設置給予 funcToRunWhenIdle 的參數$parasmForFuncToRunWhenIdle[$arguKeyForFuncToRunWhenIdle]=$arguValueForFuncToRunWhenIdle;#debug#var_dump(__LINE__,$parasmForFuncToRunWhenIdle);}#foreach end}#if end/* debug#函式說明:#撰寫log#回傳結果:#$result["status"],狀態,"true"或"false".#$result["error"],錯誤訊息陣列.#$result["function"],當前函式的名稱.#$result["argu"],使用的參數.#$result["content"],要寫入log的內容字串.#必填參數:#$conf["path"],字串,log檔案的路徑與名稱.$conf["logs::record"]["path"]=$conf["sock"].".log";#$conf["content"],any,要寫的內容,若內容不為字串則會用var_dump的格式寫入.$conf["logs::record"]["content"]=$parasmForFuncToRunWhenIdle;#$conf["fileArgu"],字串,php變數__FILE__的內容,亦即該檔案在檔案系統的絕對路徑$conf["logs::record"]["fileArgu"]=__FILE__;#可省略參數:#$conf["rewrite"],預設為"false",接續寫入;反之"true"代表重新寫入.#$conf["rewrite"]="false";#$conf["returnOnly"],預設為"false",會寫入到log檔案.若為"true"則不會寫入log.#$conf["returnOnly"]="true";#參考資料:#無.#備註:#無.$record=logs::record($conf["logs::record"]);unset($conf["logs::record"]);#如果執行失敗if($record["status"]==="false"){#設置執行錯誤識別$result["status"]="false";#設置執行錯誤$result["error"]=$record;#回傳結果return $result;}#if end*/#debug#var_dump(__LINE__,$parasmForFuncToRunWhenIdle);#debug#var_dump(__LINE__,"\$call_user_func=".$funcToRunWhenIdle."(\$parasmForFuncToRunWhenIdle);");#呼叫 $funcToRunWhenIdle 函式,參數用 $client[$request->id], 取得執行後的回應.eval("\$call_user_func=".$funcToRunWhenIdle."(\$parasmForFuncToRunWhenIdle);");/* debug#函式說明:#撰寫log#回傳結果:#$result["status"],狀態,"true"或"false".#$result["error"],錯誤訊息陣列.#$result["function"],當前函式的名稱.#$result["argu"],使用的參數.#$result["content"],要寫入log的內容字串.#必填參數:#$conf["path"],字串,log檔案的路徑與名稱.$conf["logs::record"]["path"]=$conf["sock"].".log";#$conf["content"],any,要寫的內容,若內容不為字串則會用var_dump的格式寫入.$conf["logs::record"]["content"]=$call_user_func;#$conf["fileArgu"],字串,php變數__FILE__的內容,亦即該檔案在檔案系統的絕對路徑$conf["logs::record"]["fileArgu"]=__FILE__;#可省略參數:#$conf["rewrite"],預設為"false",接續寫入;反之"true"代表重新寫入.#$conf["rewrite"]="false";#$conf["returnOnly"],預設為"false",會寫入到log檔案.若為"true"則不會寫入log.#$conf["returnOnly"]="true";#參考資料:#無.#備註:#無.$record=logs::record($conf["logs::record"]);unset($conf["logs::record"]);#如果執行失敗if($record["status"]==="false"){#設置執行錯誤識別$result["status"]="false";#設置執行錯誤$result["error"]=$record;#回傳結果return $result;}#if end*/#儲存 $funcToRunWhenIdle 函式 的運行結果資訊到 server side 的 cache$serverCache["serverSide"]["funcToRunWhenIdle"][$funcToRunWhenIdle]["result"]=&$call_user_func;#儲存 $funcToRunWhenIdle 函式 的運行結束的時間點到 server side 的 cache$serverCache["serverSide"]["funcToRunWhenIdle"][$funcToRunWhenIdle]["lastEndTime"]=time::unix()["content"];#debug#var_dump(__FILE__,__LINE__,$serverCache);#如果 運行 $funcToRunWhenIdle 後回傳的內容含有 key 為 status 的元素if(isset($call_user_func["status"])){#如果其數值為 "false"if($call_user_func["status"]==="false"){#印出訊息,結束執行var_dump(__FILE__,__LINE__,$call_user_func);exit;}#if end}#if end#如果有訊息要提示if(isset($call_user_func["content"])){#印出提示訊息var_dump($call_user_func["content"]);}#if end#如果 運行 $funcToRunWhenIdle 後回傳的內容含有 key 為 cache 的元素if(isset($call_user_func["cache"])){#debug#var_dump(__FILE__,__LINE__,$call_user_func["cache"]);#儲存到 server side 的 cache$serverCache["serverSide"]["funcToRunWhenIdle"][$funcToRunWhenIdle]["cache"]=&$call_user_func["cache"];/*#debug#函式說明:#撰寫log#回傳結果:#$result["status"],狀態,"true"或"false".#$result["error"],錯誤訊息陣列.#$result["function"],當前函式的名稱.#$result["argu"],使用的參數.#$result["content"],要寫入log的內容字串.#必填參數:#$conf["path"],字串,log檔案的路徑與名稱.$conf["logs::record"]["path"]=$conf["sock"].".log";#$conf["content"],any,要寫的內容,若內容不為字串則會用var_dump的格式寫入.$conf["logs::record"]["content"]=$call_user_func;#$conf["fileArgu"],字串,php變數__FILE__的內容,亦即該檔案在檔案系統的絕對路徑$conf["logs::record"]["fileArgu"]=__FILE__;#可省略參數:#$conf["rewrite"],預設為"false",接續寫入;反之"true"代表重新寫入.#$conf["rewrite"]="false";#$conf["returnOnly"],預設為"false",會寫入到log檔案.若為"true"則不會寫入log.#$conf["returnOnly"]="true";#參考資料:#無.#備註:#無.$record=logs::record($conf["logs::record"]);unset($conf["logs::record"]);#如果執行失敗if($record["status"]==="false"){#設置執行錯誤識別$result["status"]="false";#設置執行錯誤$result["error"]=$record;#回傳結果return $result;}#if end*/}#if end#如果回傳結果含有 exit 元素if(isset($call_user_func["exit"])){/*#debug#函式說明:#撰寫log#回傳結果:#$result["status"],狀態,"true"或"false".#$result["error"],錯誤訊息陣列.#$result["function"],當前函式的名稱.#$result["argu"],使用的參數.#$result["content"],要寫入log的內容字串.#必填參數:#$conf["path"],字串,log檔案的路徑與名稱.$conf["logs::record"]["path"]=$conf["sock"].".log";#$conf["content"],any,要寫的內容,若內容不為字串則會用var_dump的格式寫入.$conf["logs::record"]["content"]=$call_user_func["exit"];#$conf["fileArgu"],字串,php變數__FILE__的內容,亦即該檔案在檔案系統的絕對路徑$conf["logs::record"]["fileArgu"]=__FILE__;#可省略參數:#$conf["rewrite"],預設為"false",接續寫入;反之"true"代表重新寫入.#$conf["rewrite"]="false";#$conf["returnOnly"],預設為"false",會寫入到log檔案.若為"true"則不會寫入log.#$conf["returnOnly"]="true";#參考資料:#無.#備註:#無.$record=logs::record($conf["logs::record"]);unset($conf["logs::record"]);#如果執行失敗if($record["status"]==="false"){#設置執行錯誤識別$result["status"]="false";#設置執行錯誤$result["error"]=$record;#回傳結果return $result;}#if end*/#如果是要結束daemon執行if($call_user_func["exit"]==="true"){#設置daemon結束的原因$call_user_func["exit"]="exit by funcToRunWhenIdle(".$funcToRunWhenIdle.")";#設置執行正常$result["status"]="true";#結束執行return $result;}#if end}#if end#提示正要執行的函式echo "response:".PHP_EOL.$funcToRunWhenIdle." Executed.".PHP_EOL;}#foreach end}#if end#等待下個要求continue;}#if end#有偵測到讀寫的動作else{#針對每個 sock 陣列foreach($read as $readStream){#如果元素是 listen 的 socketif($readStream === $socket){#當等待別人連線時,若有人連線進來.$conn = stream_socket_accept($socket);#取得 meta data#$stream_meta_data=stream_get_meta_data($conn);#debug#var_dump(__LINE__,$stream_meta_data);#印出有連線進來的訊息echo "received a connection".PHP_EOL;#初始化取得的內容$request="";#初始化要回應的內容$res=array();#取得 request 的時間$last_req_time=time();#當有要求時while(!feof($conn)){#讀取要求$tmp=fgets($conn, 1024);#如果讀到 PHP_EOLif($tmp===PHP_EOL){#結束讀取要求break;}#if end#串接回應$request=$request.$tmp;}#while end#印出有連線進來的訊息echo "received content:".PHP_EOL.$request.PHP_EOL;#parse request json$request=json_decode($request);#如果 parse json 失敗if($request===false){#設置錯誤訊息$res["error"]="要求格式必須為json";#設置執行失敗$res["status"]="false";#印出回的訊息echo "res:".print_r($res,true);#寫入回應的內容fwrite($conn,json_encode($res).PHP_EOL);#結束回應fwrite($conn,PHP_EOL.PHP_EOL);#關閉socket連線,將回應輸出.fclose($conn);#等待下個要求continue;}#if end#若無ID資訊if(!isset($request->id)){#無窮迴圈while(true){#set client id 設置要回應的訊息#函式說明:#呼叫shell執行系統命令,並取得回傳的內容.#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$result["error"],錯誤訊息陣列.#$result["function"],當前執行的函數名稱.#$result["argu"],使用的參數.#$result["cmd"],執行的指令內容.#$result["fullCmd"],如果參數 $conf["inBackGround"] 為 "true" 則會回傳該值.#$result["output"],爲執行完二元碼後的輸出陣列,若 $conf["inBackGround"] 為 "true",則為當下的輸出.#$result["tmpFileOutput"],儲存輸出的暫存檔案名稱,若 $conf["inBackGround"] 為 "true" 則會回傳該值.#$result["running"],是否還在執行.#$result["pid"],pid.#$result["statusCode"],執行結束後的代碼.#必填參數:#$conf["command"],字串,要執行的指令.$conf["external::callShell"]["command"]="uuid";#$conf["fileArgu"],字串,變數__FILE__的內容.$conf["external::callShell"]["fileArgu"]=__FILE__;#可省略參數:#$conf["argu"],陣列字串,指令搭配的參數,預設為空陣列.#$conf["argu"]=array("");#$conf["arguIsAddr"],陣列字串,指令搭配的哪些參數為路徑,為路徑的參數會進行轉換以便符合呼叫當前函數的位置,預設不指定,若有3個參數,其中第3個參數為路徑,則表示為array("false","false","true").#$conf["arguIsAddr"]=array();#$conf["plainArgu"],字串陣列,哪幾個參數不要加上"",若為"true"則代表不用包;反之"false"則代表要包.#$conf["plainArgu"]=array();#$conf["useApostrophe"],字串陣列,如果有需要包住,則用「'」,而非「"」處理.前者為"true";後者為"false".#$conf["useApostrophe"]=array();#$conf["pre"],陣列,要在本指令前執行的每個指令與參數.#$conf["pre"][$i]["cmd"],字串,要在本指令前執行的第$i+1個指令.#$conf["pre"][$i]["param"],陣列字串,要在本指令前執行的第$i+1個指令的參數.#$conf["enablePrintDescription"],字串,是否要印出$conf["printDescription"]的內容,"true"代表要,"false"代表不要,預設為"false".#$conf["enablePrintDescription"]="true";#$conf["printDescription"],字串,執行該外部程式前要印出來的的文字,預設為$conf["command"]的內容加上使用的$conf["argu"]參數.#$conf["printDescription"]="";#$conf["escapeshellarg"],字串,是否要啟用過濾參數,用了比較安全,但可能會出錯,"true"為啟用,"false"為不啟用,預設為"false".如果參數為"< 、<< 、> 、>> 、| 、2>&1"之一則不會過濾.$conf["external::callShell"]["escapeshellarg"]="true";#$conf["thereIsShellVar"],陣列字串,指令搭配的參數"argu",若含有「\'」,則取代為「"」.每個argu參數都要有對應的元素."true"代表要置換.#$conf["thereIsShellVar"]=array();#$conf["username"],字串,要用什麼使用者來執行,預設為執行php的使用者,該參數不適用於apache環境.#$conf["username"]="";#$conf["password"],字串,root的使用者密碼,預設不使用密碼,該參數不適用於apache環境.#$conf["password"]="";#$conf["useScript"],字串,是否要啟用Linux的script指令來記錄輸出,"true"代表要,Fedora的selinux會擋住該操作;"false"代表不要,預設為"false".#$conf["useScript"]="";#$conf["logFilePath"],字串,當 $conf["useScript"] 為 "true" 時,輸出的內容要暫存到哪裡,預設為 "/tmp/.qbpwcf_tmp/external/callShell/".#$conf["logFilePath"]=".qbpwcf_tmp/external/callShell/";#$conf["inBackGround"],字串,是否要在背景執行,且不會等待程式執行結束再執行下一個指令,"true"代表是,"false"代表不要,預設為"false",如果$conf["command"]有用「;」區隔的多個指令將會出錯.#$conf["inBackGround"]="";#$conf["getErr"],字串,"true"代表將錯誤輸出變成標準輸出,反之"false"為不變動.#$conf["getErr"]="false";#$conf["doNotRun"],字串,"true"代表不執行指令,預設為"false"會執行指令.#$conf["doNotRun"]="false";#參考資料:#exec=>http://php.net/manual/en/function.exec.php#escapeshellcmd=>http://php.net/manual/en/function.escapeshellcmd.php#escapeshellarg=>http://php.net/manual/en/function.escapeshellarg.php#備註:#不是所有指令都能用apache的身份執行,目前已知java,javac指令無法執行,使用root身份可能會被selinux阻擋.#若使用的 command、argu 參數,含有 ~ 則會被視為字串,若有需要其於 shell 中代表的家目錄位置,可用 fileAccess::tildeToPath 來進行轉換.$callShell=external::callShell($conf["external::callShell"]);unset($conf["external::callShell"]);#如果執行失敗if($callShell["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$callShell;#回傳結果return $result;}#if end#如果沒有預期的 uuid 回應if(!isset($callShell["output"][0])){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"][]="get uuid failed!";#設置錯誤訊息$result["error"][]=$callShell;#回傳結果return $result;}#if end#檢查 client id 是否已經存在if(isset($client[$callShell["output"][0]])){#休息一微秒usleep(1);#再次建立id試試continue;}#if end#設置回應的id$res["id"]=$callShell["output"][0];#建立id完畢break;}#while end#儲存使用者id與最後一次來request的時間$client[$res["id"]]=array("last_req_time"=>$last_req_time);#印出用戶端列表echo "clients:".print_r($client,true);#設置執行正常$res["status"]="true";#印出回的訊息echo "response:".PHP_EOL.print_r($res,true);#寫入回應的內容fwrite($conn,json_encode($res).PHP_EOL);#結束回應fwrite($conn,PHP_EOL.PHP_EOL);#關閉socket連線,將回應輸出.fclose($conn);#等待下個要求continue;}#if end#若ID資訊不存在if(!isset($client[$request->id])){#設置執行失敗$res["status"]="false";#設置ID不存在的訊息$res["error"]="ID:".$request->id." 不存在,請再要一次ID.";#印出回的訊息echo "response:".PHP_EOL.print_r($res,true);#寫入回應的內容fwrite($conn,json_encode($res).PHP_EOL);#結束回應fwrite($conn,PHP_EOL.PHP_EOL);#關閉socket連線,將回應輸出.fclose($conn);#等待下個要求continue;}#if end#如果有客製化訊息if(isset($request->custom)){#取代之$request=$request->custom;}#if end#若有要執行的指令 cmd,且非客製化.if(isset($request->cmd)){#如果是要結束連線if($request->cmd==="quit"){#設置執行正常$res["status"]="true";#設置訊息$res["content"]="將關閉與您的連線";#寫入回應的內容fwrite($conn,json_encode($res).PHP_EOL);#結束回應fwrite($conn,PHP_EOL.PHP_EOL);#關閉socket連線,將回應輸出.fclose($conn);#移除該用戶變數unset($client[$index]);#計數移除了幾個用戶$res["delCount"]++;#設置執行正常$res["status"]="true";#印出回的訊息echo "response:".PHP_EOL.print_r($res,true);#等待下個要求continue;}#if end#如果是要結束serverif($request->cmd===$shutdownStr){#設置執行正常$res["status"]="true";#設置訊息$res["content"]="本服務將結束";#寫入回應的內容fwrite($conn,json_encode($res).PHP_EOL);#結束回應fwrite($conn,PHP_EOL.PHP_EOL);#關閉socket連線,將回應輸出.fclose($conn);#設置執行正常$result["status"]="true";#結束本程式return $result;}#if end#涵式說明:#呼叫shell執行系統命令,並取得回傳的內容.#回傳的結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$result["error"],錯誤訊息陣列.#$result["function"],當前執行的函數名稱.#$result["argu"],使用的參數.#$result["cmd"],執行的指令內容.#$result["fullCmd"],如果參數 $conf["inBackGround"] 為 "true" 則會回傳該值.#$result["output"],爲執行完二元碼後的輸出陣列,若 $conf["inBackGround"] 為 "true",則為當下的輸出.#$result["tmpFileOutput"],儲存輸出的暫村檔案名稱,若 $conf["inBackGround"] 為 "true" 則會回傳該值.#$result["running"],是否還在執行.#$result["pid"],pid#必填的參數#$conf["command"],字串,要執行的指令與.$conf["external::callShell"]["command"]=$request->cmd;#$conf["fileArgu"],字串,變數__FILE__的內容.$conf["external::callShell"]["fileArgu"]=$conf["fileArgu"];#可省略參數:#如果有指定參數if(isset($request->param)){#$conf["argu"],陣列字串,指令搭配的參數,預設為空陣列.$conf["external::callShell"]["argu"]=$request->param;}#if end#$conf["arguIsAddr"],陣列字串,指令搭配的哪些參數為路徑,為路徑的參數會進行轉換以便符合呼叫當前函數的位置,預設不指定,若有3個參數,其中第3個參數為路徑,則表示為array("false","false","true").#$conf["arguIsAddr"]=array();#$conf["pre"],陣列,要在本指令前執行的每個指令與參數.#$conf["pre"][$i]["cmd"],字串,要在本指令前執行的第$i+1個指令.#$conf["pre"][$i]["param"],陣列字串,要在本指令前執行的第$i+1個指令的參數.#$conf["enablePrintDescription"],字串,是否要印出$conf["printDescription"]的內容,"true"代表要,"false"代表不要,預設為"false".#$conf["enablePrintDescription"]="true";#$conf["printDescription"],字串,執行該外部程式前要印出來的的文字,預設為$conf["command"]的內容.#$conf["printDescription"]="";#如果有參數if(isset($request->param)){#如果有識別是否已經 escaped 參數if(isset($request->escaped)){#設置預設要 escape$needEscaped="true";#如果已經 ecapedif($request->escaped){#設置不用 escape$needEscaped="false";}#if end#$conf["escapeshellarg"],字串,是否要啟用過濾參數,用了比較安全,但可能會出錯,"true"為啟用,"false"為不啟用,預設為"false".$conf["external::callShell"]["escapeshellarg"]=$needEscaped;}#if end}#if end#如果有設置要用特定的使用者身份執行if(isset($request->user) && isset($request->password)){#$conf["username"],字串,要用什麼使用者來執行,預設為執行php的使用者,該參數不適用於apache環境.$conf["external::callShell"]["username"]=$request->user;#$conf["password"],字串,與$conf["username"]搭配的使用者密碼,預設不使用密碼,該參數不適用於apache環境.$conf["external::callShell"]["password"]=$request->password;}#if end#$conf["useScript"],字串,是否要啟用Linux的script指令來記錄輸出,"true"代表要,Fedora的selinux會擋住該操作;"false"代表不要,預設為"false".#$conf["useScript"]="";#$conf["logFilePath"],字串,當 $conf["useScript"] 為 "true" 時,輸出的內容要暫存到哪裡,預設為 "/tmp/.qbpwcf_tmp/external/callShell/".#$conf["logFilePath"]=".qbpwcf_tmp/external/callShell/";#$conf["inBackGround"],字串,是否要在背景執行,且不會等待程式執行結束再執行下一個指令,"true"代表是,"false"代表不要,預設為"false",如果$conf["command"]有用「;」區隔的多個指令將會出錯.#$conf["inBackGround"]="";#備註:#不是所有指令都能用apache的身份執行,目前已知java,javac指令無法執行,使用root身份可能會被selinux阻擋.#參考資料:#exec=>http://php.net/manual/en/function.exec.php#escapeshellcmd=>http://php.net/manual/en/function.escapeshellcmd.php#escapeshellarg=>http://php.net/manual/en/function.escapeshellarg.php$callShell=external::callShell($conf["external::callShell"]);unset($conf["external::callShell"]);#設置要回覆的內容$res=$callShell;#印出回的訊息echo "response:".PHP_EOL.print_r($res,true);#寫入回應的內容fwrite($conn,json_encode($res).PHP_EOL);#結束回應fwrite($conn,PHP_EOL.PHP_EOL);#關閉socket連線,將回應輸出.fclose($conn);#更新使用者id與最後一次來request的時間$client[$request->id]["last_req_time"]=$last_req_time;#等待下個要求continue;}#if end#設置接收到json字串資訊$client[$request->id]["request"]=(array)($request);#設置用戶端的socket$client[$request->id]["socket"]=$conn;#如果有要求在背景中執行指令的訊息if(isset($request->cmdInBg)){#debug#var_dump(__FUNCTION__,__LINE__,$request);#如果有參數if(isset($request->param)){#函式說明:#將一維陣列轉換為用特定符號間隔的字串,ex:array("1","2","3") to "a;b;c;".#回傳的結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$result["function"],當前執行的function名稱#$result["error"],錯誤訊息陣列.#$result["content"],處理好的字串.#$result["argu"],使用的參數.#必填參數:#$conf["inputArray"],字串陣列,要轉成字串的一維陣列.$conf["arrays::arrayToString"]["inputArray"]=$request->param;#可省略參數:#$conf["spiltSymbol"],字串,用來區隔字串的符號,預設為;$conf["arrays::arrayToString"]["spiltSymbol"]=" ";#$conf["skipEnd"],字串,結尾是否不要加上符號,預設為"false",要加上符號,"true"代表不要加上符號。$conf["arrays::arrayToString"]["skipEnd"]="true";#$conf["spiltSymbolAtStart"],字串,是否要在開頭加上spiltSymbol,預設為"false",代表不要;反之為“true”.$conf["arrays::arrayToString"]["spiltSymbolAtStart"]="true";#參考資料:#無.#備註:#無.$arrayToString=arrays::arrayToString($conf["arrays::arrayToString"]);unset($conf["arrays::arrayToString"]);#如果執行失敗if($arrayToString["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$arrayToString;#回傳結果return $result;}#if end#串接參數$request->cmdInBg=$request->cmdInBg.$arrayToString["content"];}#if end#函式說明:#透過proc來多執行序運作.#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$reuslt["error"],執行不正常結束的錯訊息陣列.#$result["function"],當前執行的函式名稱.#$result["argu"],使用的參數.#$result["content"],陣列,每個元素為其指令執行的結果訊息陣列,key為"status"代表執行是否正常的識別;key為"statusCode"代表程式結束後回傳給對應executeBy程式的數值;key為"output"代表標準輸出,若為resource,則代表為pipe;key為"error"代表非標準輸出,若為resource,則代表為pipe;key為"input"代表成功輸入的指令;key為"process"代表該程序經proc_open後的process source;key為"proc_get_status"代表程序的資訊.#必填參數:#$conf["cmds"],字串陣列,每個元素代表要執行的指令與參數.$conf["threads::proc"]["cmds"]=array($request->cmdInBg);#可省略參數:#$conf["wait"],字串,是否需要等待所有程序結束,預設為"true"要等待;反之為"false"不要等待.$conf["threads::proc"]["wait"]="false";#$conf["workingDir"],字串陣列,個別程式執行時的家目錄,預設不指定.#$conf["workingDir"]=array("path");#$conf["envs"],2維字串陣列,每個元素代表個別程式執行時的指定環境變數,key變數名稱;value為變數內容.預設為array("QBPWCF" => "Quick Build PHP Website Componment base on Fedora Linux");#$conf["envs"]=array(array("key"=>"value"));#$conf["executeBy"],字串陣列,每個元素代表個別指令要用什麼程式執行,預設為"bash".#$conf["executeBy"]=array("bash");#參考資料:#https://www.php.net/manual/en/function.proc-open.php#https://www.php.net/manual/en/function.proc-get-status.php#備註:#若需要取得當下的執行狀況,請使用 self::proc_update 來更新.$proc=threads::proc($conf["threads::proc"]);unset($conf["threads::proc"]);#如果執行失敗if($proc["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$proc;#回傳結果return $result;}#if end#函式說明:#使用 linux 的 uuid 指令來產生 uuid 字串#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$result["error"],錯誤訊息.#$result["function"],當前執行的函式名稱.#$result["content"],uuid.#必填參數:#無.#可省略參數:#無.#參考資料:#無.#備註:#無.$uuid=cmd::uuid();#如果執行失敗if($uuid["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$uuid;#回傳結果return $result;}#if end#取得 uuid$uuid=$uuid["content"];#儲存到 server side 的 procs$result["serverCache"]["serverSide"]["procs"][$uuid]=$proc;#設置最後的檢查時間為當下$result["serverCache"]["serverSide"]["procs"][$uuid]["latestAccessTime"]=time();#設置要回覆的內容$res=array("status"=>"true","content"=>$uuid);#印出回的訊息echo "response:".PHP_EOL.print_r($res,true);#寫入回應的內容fwrite($conn,json_encode($res).PHP_EOL);#結束回應fwrite($conn,PHP_EOL.PHP_EOL);#關閉socket連線,將回應輸出.fclose($conn);#更新使用者id與最後一次來request的時間$client[$request->id]["last_req_time"]=$last_req_time;#等待下個要求continue;}#if end#如果要查詢程序執行的狀況if(isset($request->QueryProcByUUID)){#如果沒有 proc 資訊if(!isset($result["serverCache"]["serverSide"]["procs"])){#設置要回覆的內容$res=array("status"=>"true","content"=>"");#印出回的訊息echo "response:".PHP_EOL.print_r($res,true);#寫入回應的內容fwrite($conn,json_encode($res).PHP_EOL);#結束回應fwrite($conn,PHP_EOL.PHP_EOL);#關閉socket連線,將回應輸出.fclose($conn);#更新使用者id與最後一次來request的時間$client[$request->id]["last_req_time"]=$last_req_time;#等待下個要求continue;}#if end#函式說明:#更新透過proc執行的多程序資訊.#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$reuslt["error"],執行不正常結束的錯訊息陣列.#$result["function"],當前執行的函式名稱.#$result["argu"],使用的參數.#$result["content"],陣列,每個元素為其指令執行的結果訊息陣列,key為"status"代表執行是否正常的識別;key為"statusCode"代表程式結束後回傳給對應executeBy程式的數值;key為"output"代表標準輸出,若為resource,則代表為pipe;key為"error"代表非標準輸出,若為resource,則代表為pipe;key為"input"代表成功輸入的指令;key為"process"代表該程序經proc_open後的process source;key為"proc_get_status"代表程序的資訊.#必填參數:#$conf["procs"],陣列,運行self::proc後回傳的content.$conf["threads::proc_update"]["procs"]=$result["serverCache"]["serverSide"]["procs"][$request->QueryProcByUUID]["content"];#可省略參數:#無.#參考資料:#無.#備註:#無.$proc_update=threads::proc_update($conf["threads::proc_update"]);unset($conf["threads::proc_update"]);#如果執行失敗if($proc_update["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$proc_update;#回傳結果return $result;}#if end#更新 serverSide 的 proc cache$result["serverCache"]["serverSide"]["procs"][$request->QueryProcByUUID]["content"]=$proc_update["content"];#設置最後檢查的時間$result["serverCache"]["serverSide"]["procs"][$request->QueryProcByUUID]["latestAccessTime"]=time();#印出子程序的資訊echo "proc info:".PHP_EOL.print_r($proc_update["content"][0],true);#初始化要回傳的內容$res=array();#設置 pid$res["pid"]=$proc_update["content"][0]["proc_get_status"]["pid"];#設置輸入的內容$res["input"]=$proc_update["content"][0]["input"];#預設設置已經結束執行$res["running"]="false";#如果尚在執行if($proc_update["content"][0]["statusCode"]==="?"){#設置正在執行$res["running"]="true";}#if end#如果已經結束執行if($res["running"]==="false"){#設置執行後得到的標準輸出$res["output"]=$proc_update["content"][0]["content"];#設置執行後得到的錯誤輸出$res["error"]=$proc_update["content"][0]["error"];}#if end#設置回應正常$res["status"]="true";#印出回的訊息echo "response:".PHP_EOL.print_r($res,true);#寫入回應的內容fwrite($conn,json_encode($res).PHP_EOL);#結束回應fwrite($conn,PHP_EOL.PHP_EOL);#關閉socket連線,將回應輸出.fclose($conn);#更新使用者id與最後一次來request的時間$client[$request->id]["last_req_time"]=$last_req_time;#等待下個要求continue;}#if end#debug#var_dump(__LINE__,$conn,$client[$request->id]);#如果存在 addOnProcessFuncif(isset($conf["addOnProcessFunc"])){#針對每個 addOnProcessFuncforeach($conf["addOnProcessFunc"] as $addOnProcessFunc){#如果有設置 infoToFunctionif(isset($conf["infoToFunction"])){#設置info$client[$request->id]["info"]=&$conf["infoToFunction"];}#if end#設置client cache$client[$request->id]["clientCache"]=&$clientCache;#呼叫 $addOnProcessFunc 函式,參數用 $client[$request->id], 取得執行後的回應.eval("\$call_user_func=".$addOnProcessFunc."(\$client[\$request->id]);");/* debug#函式說明:#撰寫log#回傳結果:#$result["status"],狀態,"true"或"false".#$result["error"],錯誤訊息陣列.#$result["function"],當前函式的名稱.#$result["argu"],使用的參數.#$result["content"],要寫入log的內容字串.#必填參數:#$conf["path"],字串,log檔案的路徑與名稱.$conf["logs::record"]["path"]=$conf["sock"].".log";#$conf["content"],any,要寫的內容,若內容不為字串則會用var_dump的格式寫入.$conf["logs::record"]["content"]=$call_user_func;#$conf["fileArgu"],字串,php變數__FILE__的內容,亦即該檔案在檔案系統的絕對路徑$conf["logs::record"]["fileArgu"]=__FILE__;#可省略參數:#$conf["rewrite"],預設為"false",接續寫入;反之"true"代表重新寫入.#$conf["rewrite"]="false";#$conf["returnOnly"],預設為"false",會寫入到log檔案.若為"true"則不會寫入log.#$conf["returnOnly"]="true";#參考資料:#無.#備註:#無.$record=logs::record($conf["logs::record"]);unset($conf["logs::record"]);#如果執行失敗if($record["status"]==="false"){#設置執行錯誤識別$result["status"]="false";#設置執行錯誤$result["error"]=$record;#回傳結果return $result;}#if end*/#如果回應不是 arrayif(gettype($call_user_func)!=="array"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"][]=$call_user_func;#設置錯誤訊息$result["error"][]=$conf;#印出error資訊echo "error:".print_r($result,true);#回應錯誤訊息給用戶fwrite($conn,json_encode($result).PHP_EOL);#結束回應fwrite($conn,PHP_EOL.PHP_EOL);#關閉socket連線,將回應輸出.fclose($conn);#回傳結果return $result;}#if end#檢查回應的格式#函式說明:#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容。#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$reuslt["error"],執行不正常結束的錯訊息陣列.#$result["function"],當前執行的函式名稱.#$result["argu"],設置給予的參數.#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.#$result["argu"],字串陣列,目前輸入的參數名稱陣列.#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.#$result["notNeedVar"],字串陣列,多餘的參數名稱.#必填寫的參數:#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。$conf["variableCheck::checkArguments"]["varInput"]=&$call_user_func;#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";#可以省略的參數:#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("status");#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string");#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.$conf["variableCheck::checkArguments"]["canBeEmptyString"]="false";#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.#$conf["canNotBeEmpty"]=array();#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.#$conf["canBeEmpty"]=array();#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.#$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("function","continue");#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("function","continue","content","cache","argu","error");#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","string",null,"array","array","array");#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array($addOnProcessFunc,"true",null,null,null,null);#$conf["disallowAllSkipableVarIsEmpty"],字串,是否允許每個可省略參數都為空字串,預設為"true"允許,反之為"false".#$conf["disallowAllSkipableVarIsEmpty"]="";#$conf["disallowAllSkipableVarIsEmptyArray"],字串,是否允許每個可省略參數都為空陣列,預設為"true"允許,反之為"false".#$conf["disallowAllSkipableVarIsEmptyArray"]="";#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.#$conf["arrayCountEqualCheck"][]=array();#參考資料來源:#array_keys=>http://php.net/manual/en/function.array-keys.php$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);unset($conf["variableCheck::checkArguments"]);#如果檢查參數失敗if($checkArguments["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$checkArguments;#印出error資訊echo "error:".print_r($result,true);#回應錯誤訊息給用戶fwrite($conn,json_encode($result).PHP_EOL);#結束回應fwrite($conn,PHP_EOL.PHP_EOL);#關閉socket連線,將回應輸出.fclose($conn);#回傳結果return $result;}#if end#如果檢查參數不通過if($checkArguments["passed"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$checkArguments;#印出error資訊echo "error:".print_r($result,true);#回應錯誤訊息給用戶fwrite($conn,json_encode($result).PHP_EOL);#結束回應fwrite($conn,PHP_EOL.PHP_EOL);#關閉socket連線,將回應輸出.fclose($conn);#回傳結果return $result;}#if end#如果回應不正常if($call_user_func["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"][]=$call_user_func;#設置錯誤訊息$result["error"][]=$conf;#印出error資訊echo "error:".print_r($result,true);#回應錯誤訊息給用戶fwrite($conn,json_encode($result).PHP_EOL);#結束回應fwrite($conn,PHP_EOL.PHP_EOL);#關閉socket連線,將回應輸出.fclose($conn);#回傳結果return $result;}#if end#如果回應有 content 元素if(isset($call_user_func["content"])){#用收到 content 元素內容來更新 $client[id]["request"]$client[$request->id]["request"]=$call_user_func["content"];}#if end#如果回傳 cache 元素if(isset($call_user_func["cache"])){#用收到 cache 元素內容來更新 server side 的 cache$result["serverCache"]["clientSide"]["addOnProcessFunc"][$addOnProcessFunc]=&$call_user_func["cache"];}#if end#如果回應不要往後面執行if($call_user_func["continue"]==="false"){#結束 foreachbreak;}#if end}#foreach end}#if end#執行到這代表是要保持連線#設置執行正常$res["status"]="true";#印出回的訊息echo "response:".PHP_EOL.print_r($res,true);#debug#var_dump(__LINE__,$conn,get_resource_type($conn));#如果資源形態沒有異常(用戶關閉連線後,會有resource type變成"Unknown"的結果)if(get_resource_type($conn)!=="Unknown"){#函式說明:#用fwrite寫入到resource,可以指定每個寫入字串的結尾方式.#回傳結果:#$result["status"],執行是否正常,"true"為正常,"false"為不正常.#$result["error"],錯誤訊息陣列.#$result["function"],當前執行的函數名稱.#$result["argu"],使用的參數.#$result["is_writable"],參數stream是否為可寫入的resource,"true"代表可寫入;"false"代表不可寫入.#必填參數:#$conf["stream"],resource,寫入的目標.$conf["sock::fwrite"]["stream"]=&$conn;#$conf["data"],字串陣列,要寫入的內容,每個元素代表每段要寫入的內容.$conf["sock::fwrite"]["data"]=array(json_encode($res).PHP_EOL);#可省略參數:#$conf["msgEndType"],字串,訊息結尾要怎麼寫,預設為"none",代表不做處理;"EOL"代表結尾要用PHP_EOL;"HTTP/1.1"代表"data"參數最多為2個,分別為header跟body,結尾方式為兩個PHP_EOL.$conf["sock::fwrite"]["msgEndType"]="HTTP/1.1";#$conf["autoClose"],字串,寫入結束後是否要關閉resource,預設為"false"代表保持開着;反之為"true".$conf["sock::fwrite"]["autoClose"]="true";#參考資料:#https://stackoverflow.com/questions/5294305/how-to-check-if-a-php-stream-resource-is-readable-or-writable#5294425#https://www.php.net/manual/en/function.stream-get-meta-data.php#https://www.php.net/manual/en/function.is-writable.php#https://www.php.net/manual/en/function.socket-get-status.php#備註:#無.$fwrite=sock::fwrite($conf["sock::fwrite"]);unset($conf["sock::fwrite"]);#如果執行失敗if($fwrite["status"]==="false"){#如果有 is_writableif(isset($fwrite["is_writable"])){#如果有 is_writableif($fwrite["is_writable"]==="true"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$fwrite;#印出error資訊echo "error:".print_r($result,true);#結束並回傳1給shellexit(1);}#if end}#if end#反之else{#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$fwrite;#印出error資訊echo "error:".print_r($result,true);#結束並回傳1給shellexit(1);}#else end}#if end}#if end#更新使用者id與最後一次來request的時間$client[$request->id]["last_req_time"]=$last_req_time;#印出用戶端列表echo "clients:".print_r($client,true);#等待下個要求continue;}#if end#socket 陣列不是我們建立的 socketelse{#顯示 socket 的狀態var_dump("socket_get_status".socket_get_status($conn));}#else end}#foreach end}#else end}#while end#關閉 unix domain socketfclose($socket);}#else end}#function unixDomainSockServer end/*#函式說明:#連線到 unixDomainSockServer 提供的 unix domain socket.#回傳結果:#$result["status"],"true"代表執行正常;"false"代表執行不正常.#$result["error"],錯誤訊息陣列.#$result["function"],當前執行的函式名稱.#$result["content"],取得的回應,讀到EOL,才會結束.#必填參數:#$conf["sock"],字串,要連線的unix domain socket.$conf["sock"]="";#可省略參數:#$conf["id"],字串,取得的id,若無此值,則會得到新的數值.#$conf["id"]="";#$conf["cmd"],字串,要執行的指令,當$conf["id"]參數合法時,才會執行.#$conf["cmd"]="";#$conf["param"],參數陣列.#$conf["param"]=array();#$conf["escaped"],字串,param參數是否已經escaped了,預設為"false",反之為"true".#$conf["escaped"]="true";#$conf["custom"],陣列,要客制化傳輸的內容,會覆蓋以上除了$conf["id"]以外的可省略參數.#$conf["custom"]=array();#$conf["raw"],字串,要直接傳送的字串內容,會忽略其他可省略參數.#$conf["raw"]="";#參考資料:#http://php.net/manual/en/function.stream-socket-client.php#http://php.net/manual/en/function.stream-get-contents.php#備註:#無.*/public static function unixDomainSockClient(&$conf){#初始化要回傳的結果$result=array();#取得當前執行的函數名稱$result["function"]=__FUNCTION__;#如果沒有參數if(func_num_args()==0){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]="函數".$result["function"]."需要參數";#回傳結果return $result;}#if end#取得參數$result["argu"]=$conf;#如果 $conf 不為陣列if(gettype($conf)!="array"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"][]="\$conf變數須為陣列形態";#如果傳入的參數為 nullif($conf==null){#設置執行錯誤訊息$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";}#if end#回傳結果return $result;}#if end#檢查參數#函式說明:#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容。#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$reuslt["error"],執行不正常結束的錯訊息陣列.#$result["function"],當前執行的函式名稱.#$result["argu"],設置給予的參數.#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.#$result["argu"],字串陣列,目前輸入的參數名稱陣列.#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.#$result["notNeedVar"],字串陣列,多餘的參數名稱.#必填寫的參數:#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。$conf["variableCheck::checkArguments"]["varInput"]=&$conf;#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";#可以省略的參數:#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("sock");#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string");#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.#$conf["canBeEmptyString"]="false";#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.#$conf["canNotBeEmpty"]=array();#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.#$conf["canBeEmpty"]=array();#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("id","cmd","param","escaped","custom");#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("id","cmd","param","escaped","custom","raw");#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","string","array","string","array","string");#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array(null,null,null,"false",null,null);#$conf["disallowAllSkipableVarIsEmpty"],字串,是否允許每個可省略參數都為空字串,預設為"true"允許,反之為"false".#$conf["disallowAllSkipableVarIsEmpty"]="";#$conf["disallowAllSkipableVarIsEmptyArray"],字串,是否允許每個可省略參數都為空陣列,預設為"true"允許,反之為"false".#$conf["disallowAllSkipableVarIsEmptyArray"]="";#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.#$conf["arrayCountEqualCheck"][]=array();#參考資料來源:#array_keys=>http://php.net/manual/en/function.array-keys.php$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);unset($conf["variableCheck::checkArguments"]);#如果檢查參數失敗if($checkArguments["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$checkArguments;#回傳結果return $result;}#if end#如果檢查參數不通過if($checkArguments["passed"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$checkArguments;#回傳結果return $result;}#if end#檢查 unix socket 檔案 $conf["sock"] 是否存在.#函式說明:#檢查多個檔案與資料夾是否存在.#回傳的結果:#$result["status"],執行正常與否,"true"代表正常,"false"代表不正常.#$result["error"],錯誤訊息陣列.#$resutl["function"],當前執行的涵式名稱.#$result["argu"],使用的參數.#$result["allExist"],所有檔案皆存在的識別,"true"代表皆存在,"false"代表沒有全部都存在.#$result["varName"][$i],爲第$i個資料夾或檔案的路徑與名稱。#$result["varNameFullPath"][$i],爲第$i個資料夾或檔案的完整檔案系統路徑與名稱,如果不存在則代表路徑是網址.#$result["varNameWebPath"][$i],為第$i個資料夾或檔案的網址#$result["varExist"][$i],爲第$i個資料夾或檔案是否存在,"true"代表存在,"false"代表不存在。#必填參數:#$conf["fileArray"],陣列字串,要檢查是否存在的檔案有哪些,須爲一維陣列數值。$conf["variableCheck::checkArguments"]["fileArray"]=array($conf["sock"]);#$conf["fileArgu"],字串,php變數__FILE__的內容,亦即該檔案在檔案系統的絕對路徑$conf["variableCheck::checkArguments"]["fileArgu"]=__FILE__;#可省略參數:#$conf["disableWebSearch"],"字串",是否取消「當檔案找不到時,改用catchWebContent類別的wget函數來檢查檔案是否存在於網路上」的功能,"false"不取消,若要取消該功能請設為"true",若抓到的內容為空字串則會視為檔案不存在,預設為"true".#$conf["disableWebSearch"]="false";#$conf["userDir"],字串,網頁是否置放於家目錄底下,"true"為是,"false"為不是,預設為"true".$conf["variableCheck::checkArguments"]["userDir"]="false";#$conf["web"],字串,檔案是放在web就是"true",反之為檔案系統"false",預設為"true".$conf["variableCheck::checkArguments"]["web"]="false";#參考資料:#http://php.net/manual/en/function.file-exists.php#http://php.net/manual/en/control-structures.foreach.php#備註:#函數file_exists檢查的路徑為檔案系統的路徑#$result["varName"][$i]結果未實作$checkMultiFileExist=fileAccess::checkMultiFileExist($conf["variableCheck::checkArguments"]);unset($conf["variableCheck::checkArguments"]);#如果檢查失敗if($checkMultiFileExist["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$checkMultiFileExist;#回傳結果return $result;}#if end#如果檢查失敗if($checkMultiFileExist["allExist"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$checkMultiFileExist;#回傳結果return $result;}#if end#初始化取得的回應$result["content"]="";#debug#var_dump(__LINE__,"before connect");#嘗試30秒內連線到 unix domain socket$fp=@stream_socket_client("unix://".$conf["sock"], $errno, $errstr, 30, STREAM_CLIENT_ASYNC_CONNECT );#如果開啟 unix domain socket 失敗if(!$fp){#設置執行錯誤識別$result["status"]="false";#設置錯誤訊息$result["error"]=$errstr." (".$errno.")";#回傳結果return $result;}#if end#反之開啟 unix domain socket 成功,且沒有raw參數存在else if(!isset($conf["raw"])){#初始化要傳送的要求$req=array();#如果有設置 $conf["id"]if(isset($conf["id"])){#設置識別自己的id$req["id"]=$conf["id"];}#if end#如果有設置 $conf["cmd"]if(isset($conf["cmd"])){#設置要執行的指令$req["cmd"]=$conf["cmd"];}#if end#如果有設置 $conf["param"]if(isset($conf["param"])){#設置要執行的指令參數$req["param"]=$conf["param"];#設置參數是否已經escaped$req["escaped"]=$conf["escaped"];}#if end#如果有設置 $conf["custom"]if(isset($conf["custom"])){#用 $conf["custom"] 來取代 $req$req=$conf["custom"];#如果有設置 $conf["id"]if(isset($conf["id"])){#設置識別自己的id$req["id"]=$conf["id"];}#if end}#if end#debug#var_dump(__LINE__,"before write ".json_encode($req));#傳送要求fwrite($fp,json_encode($req).PHP_EOL);#結束要求fwrite($fp,PHP_EOL.PHP_EOL);#如果回應為空while(strlen($result["content"])<2){#當有回應時while(!feof($fp)){#讀取回應$tmp=fgets($fp, 1024);#debug#var_dump($tmp);#debug#var_dump(__LINE__,"got ".$tmp);#如果讀到 PHP_EOLif($tmp===PHP_EOL){#結束讀取回應break 2;}#if end#串接回應$result["content"]=$result["content"].$tmp;}#while end}#while end#關閉 socketfclose($fp);}#else end#反之有有raw參數存在else{#傳送要求fwrite($fp,trim($conf["raw"]).PHP_EOL);#當有回應時while(!feof($fp)){#讀取回應$tmp=fgets($fp, 1024);#debug#var_dump($tmp);#debug#var_dump(__LINE__,"got ".$tmp);#如果讀到 PHP_EOLif($tmp===PHP_EOL){#結束讀取回應break;}#if end#串接回應$result["content"]=$result["content"].$tmp;}#while end#關閉 socketfclose($fp);}#else end#設置執行正常$result["status"]="true";#回傳結果return $result;}#function unixDomainSockClient end/*#函式說明:#連線到 usr/bin/qbpwcf-usock.php 產生的 unix domain socket,運行指定的指令.#回傳結果:#$result["status"],"true"代表執行正常;"false"代表執行不正常.#$result["error"],錯誤訊息陣列.#$result["function"],當前執行的函式名稱.#$result["argu"],使用的參數.#$result["content"],執行完指令的結果,回傳的格式為external::callShell的回傳結果.#必填參數:#$conf["fileArgu"],字串,變數__FILE__的內容.$conf["fileArgu"]=__FILE__;#$conf["command"],字串,要執行的指令名稱.$conf["command"]="";#可省略參數:#$conf["sock"],字串,要連線的 usr/bin/qbpwcf-sock.php(sock::unixDomainSockServer) 所產生的 unix domain socket 路徑與名稱,預設為 qbpwcf_usock_path.#$conf["sock"]=qbpwcf_usock_path;#$conf["argu"],陣列字串,指令搭配的參數,預設為空陣列.#$conf["argu"]=array();#$conf["commandIncludeArgu"],字串,是否command含有參數,預設為"false"代表沒有;反之為"true".#$conf["commandIncludeArgu"]="false";#$conf["commandInBg"],字串,是否要將程序放在背景執行,再取得相關資訊,預設為"false"代表不要;反之為"true".#$conf["commandInBg"]="false";#參考資料:#無.#備註:#無.*/public static function execAnyCmdByQBPWCFunixSocket(&$conf){#初始化要回傳的結果$result=array();#取得當前執行的函數名稱$result["function"]=__FUNCTION__;#如果沒有參數if(func_num_args()==0){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]="函數".$result["function"]."需要參數";#回傳結果return $result;}#if end#取得參數$result["argu"]=$conf;#如果 $conf 不為陣列if(gettype($conf)!="array"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"][]="\$conf變數須為陣列形態";#如果傳入的參數為 nullif($conf==null){#設置執行錯誤訊息$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";}#if end#回傳結果return $result;}#if end#檢查參數#函式說明:#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容。#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$reuslt["error"],執行不正常結束的錯訊息陣列.#$result["function"],當前執行的函式名稱.#$result["argu"],設置給予的參數.#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.#$result["argu"],字串陣列,目前輸入的參數名稱陣列.#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.#$result["notNeedVar"],字串陣列,多餘的參數名稱.#必填寫的參數:#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。$conf["variableCheck::checkArguments"]["varInput"]=&$conf;#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";#可以省略的參數:#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("fileArgu","command");#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string","string");#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.#$conf["canBeEmptyString"]="false";#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.#$conf["canNotBeEmpty"]=array();#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.#$conf["canBeEmpty"]=array();#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("sock");#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("sock","argu","commandIncludeArgu","commandInBg");#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","array","string","string");#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array(qbpwcf_usock_path,array(),"false","false");#$conf["disallowAllSkipableVarIsEmpty"],字串,是否允許每個可省略參數都為空字串,預設為"true"允許,反之為"false".#$conf["disallowAllSkipableVarIsEmpty"]="";#$conf["disallowAllSkipableVarIsEmptyArray"],字串,是否允許每個可省略參數都為空陣列,預設為"true"允許,反之為"false".#$conf["disallowAllSkipableVarIsEmptyArray"]="";#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.#$conf["arrayCountEqualCheck"][]=array();#參考資料來源:#array_keys=>http://php.net/manual/en/function.array-keys.php$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);unset($conf["variableCheck::checkArguments"]);#如果檢查參數失敗if($checkArguments["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$checkArguments;#回傳結果return $result;}#if end#如果檢查參數不通過if($checkArguments["passed"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$checkArguments;#回傳結果return $result;}#if end#如果指令已經包含參數了if($conf["commandIncludeArgu"]==="true"){#函式說明:#將指令字串解析成陣列,方便給予 external::callShell 使用#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$reuslt["error"],執行不正常結束的錯訊息陣列.#$result["function"],當前執行的函式名稱.#$result["content"],解析好的指令陣列.#$result["cmd"],解析好的指令名稱.#$result["argus"],解析好的參數陣列.#$result["argu"],所使用的參數.#必填參數#$conf["cmdStr"],字串,要解析的指令字串$conf["cmd::parseCmdString"]["cmdStr"]=$conf["command"];#可省略參數:#無.#參考資料:#無.#備註:#無.$parseCmdString=cmd::parseCmdString($conf["cmd::parseCmdString"]);unset($conf["cmd::parseCmdString"]);#debug#var_dump(__FUNCTION__,__LINE__,$parseCmdString);exit;#如果執行失敗if($parseCmdString["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$parseCmdString;#回傳結果return $result;}#if end#取得解析好的指令名稱$conf["command"]=$parseCmdString["cmd"];#取得解析好的參數陣列$conf["argu"]=$parseCmdString["argus"];#debug#var_dump(__LINE__,$parseCmdString);}#if end#函式說明:#呼叫shell執行系統命令,並取得回傳的內容.#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$result["error"],錯誤訊息陣列.#$result["function"],當前執行的函數名稱.#$result["argu"],使用的參數.#$result["cmd"],執行的指令內容.#$result["fullCmd"],如果參數 $conf["inBackGround"] 為 "true" 則會回傳該值.#$result["output"],爲執行完二元碼後的輸出陣列,若 $conf["inBackGround"] 為 "true",則為當下的輸出.#$result["tmpFileOutput"],儲存輸出的暫存檔案名稱,若 $conf["inBackGround"] 為 "true" 則會回傳該值.#$result["running"],是否還在執行.#$result["pid"],pid.#$result["statusCode"],執行結束後的代碼.#$result["escape"],陣列,儲存重新排序過且已經escape過的指令(key為"cmd")與參數(key為"argu").#必填參數:#$conf["command"],字串,要執行的指令.$conf["external::callShell"]["command"]=$conf["command"];#$conf["fileArgu"],字串,變數__FILE__的內容.$conf["external::callShell"]["fileArgu"]=$conf["fileArgu"];#可省略參數:#$conf["argu"],陣列字串,指令搭配的參數,預設為空陣列.$conf["external::callShell"]["argu"]=$conf["argu"];#$conf["arguIsAddr"],陣列字串,指令搭配的哪些參數為路徑,為路徑的參數會進行轉換以便符合呼叫當前函數的位置,預設不指定,若有3個參數,其中第3個參數為路徑,則表示為array("false","false","true").#$conf["arguIsAddr"]=array();#$conf["pre"],陣列,要在本指令前執行的每個指令與參數.#$conf["pre"][$i]["cmd"],字串,要在本指令前執行的第$i+1個指令.#$conf["pre"][$i]["param"],陣列字串,要在本指令前執行的第$i+1個指令的參數.#$conf["enablePrintDescription"],字串,是否要印出$conf["printDescription"]的內容,"true"代表要,"false"代表不要,預設為"false".#$conf["enablePrintDescription"]="true";#$conf["printDescription"],字串,執行該外部程式前要印出來的的文字,預設為$conf["command"]的內容加上使用的$conf["argu"]參數.#$conf["printDescription"]="";#$conf["escapeshellarg"],字串,是否要啟用過濾參數,用了比較安全,但可能會出錯,"true"為啟用,"false"為不啟用,預設為"false".如果參數為"< 、<< 、> 、>> 、| 、2>&1"之一則不會過濾.$conf["external::callShell"]["escapeshellarg"]="true";#$conf["thereIsShellVar"],陣列字串,指令搭配的參數"argu",若含有「\'」,則取代為「"」.每個argu參數都要有對應的元素."true"代表要置換.#$conf["thereIsShellVar"]=array();#$conf["username"],字串,要用什麼使用者來執行,預設為執行php的使用者,該參數不適用於apache環境.#$conf["username"]="";#$conf["password"],字串,root的使用者密碼,預設不使用密碼,該參數不適用於apache環境.#$conf["password"]="";#$conf["useScript"],字串,是否要啟用Linux的script指令來記錄輸出,"true"代表要,Fedora的selinux會擋住該操作;"false"代表不要,預設為"false".#$conf["useScript"]="";#$conf["logFilePath"],字串,當 $conf["useScript"] 為 "true" 時,輸出的內容要暫存到哪裡,預設為 "/tmp/.qbpwcf_tmp/external/callShell/".#$conf["logFilePath"]=".qbpwcf_tmp/external/callShell/";#$conf["inBackGround"],字串,是否要在背景執行,且不會等待程式執行結束再執行下一個指令,"true"代表是,"false"代表不要,預設為"false",如果$conf["command"]有用「;」區隔的多個指令將會出錯.#$conf["inBackGround"]="";#$conf["getErr"],字串,"true"代表將錯誤輸出變成標準輸出,反之"false"為不變動.#$conf["getErr"]="false";#$conf["doNotRun"],字串,"true"代表不執行指令,預設為"false"會執行指令.$conf["external::callShell"]["doNotRun"]="true";#參考資料:#exec=>http://php.net/manual/en/function.exec.php#escapeshellcmd=>http://php.net/manual/en/function.escapeshellcmd.php#escapeshellarg=>http://php.net/manual/en/function.escapeshellarg.php#備註:#不是所有指令都能用apache的身份執行,目前已知java,javac指令無法執行,使用root身份可能會被selinux阻擋.#若使用的 command、argu 參數,含有 ~ 則會被視為字串,若有需要其於 shell 中代表的家目錄位置,可用 fileAccess::tildeToPath 來進行轉換.$callShell=external::callShell($conf["external::callShell"]);unset($conf["external::callShell"]);#debug#var_dump(__LINE__,$callShell);#如果檢查參數作業出錯if($callShell["status"]=="false"){#設置執行錯誤識別$result["status"]="false";#設置錯誤訊息$result["error"]=$callShell;#回傳結果return $result;}#if end#函式說明:#連線到 unixDomainSockServer 提供的 unix domain socket.#回傳結果:#$result["status"],"true"代表執行正常;"false"代表執行不正常.#$result["error"],錯誤訊息陣列.#$result["function"],當前執行的函式名稱.#$result["content"],取得的回應.#必填參數:#$conf["sock"],字串,要連線的unix domain socket.$conf["sock::unixDomainSockClient"]["sock"]=$conf["sock"];#可省略參數:#$conf["id"],字串,取得的id,若無此值,則會得到新的數值.#$conf["id"]="";#$conf["cmd"],字串,要執行的指令,當$conf["id"]參數合法時,才會執行.$conf["sock::unixDomainSockClient"]["cmd"]=$callShell["escape"]["cmd"];#$conf["param"],參數陣列.$conf["sock::unixDomainSockClient"]["param"]=$callShell["escape"]["argu"];#$conf["escaped"],字串,param參數是否已經escaped了,預設為"false",反之為"true".$conf["sock::unixDomainSockClient"]["escaped"]="true";#$conf["custom"],陣列,要客制化傳輸的內容,會覆蓋以上除了$conf["id"]以外的可省略參數.#如果要在背景執行指令if($conf["commandInBg"]==="true" && isset($conf["sock::unixDomainSockClient"]["cmd"]) ){#設定要在背景執行的指令$conf["sock::unixDomainSockClient"]["custom"]["cmdInBg"]=$conf["sock::unixDomainSockClient"]["cmd"];#設定要在背景執行的指令$conf["sock::unixDomainSockClient"]["custom"]["param"]=$conf["sock::unixDomainSockClient"]["param"];#移除不要的參數unset($conf["sock::unixDomainSockClient"]["cmd"]);#移除不要的參數unset($conf["sock::unixDomainSockClient"]["param"]);#保存 custom 參數$custom=$conf["sock::unixDomainSockClient"]["custom"];#debug#var_dump(__LINE__,$custom);}#if end#$conf["raw"],字串,要直接傳送的字串內容,會忽略其他可省略參數.#$conf["raw"]="";#參考資料:#http://php.net/manual/en/function.stream-socket-client.php#http://php.net/manual/en/function.stream-get-contents.php#備註:#無.$paramsOfUnixDomainSockClient=$conf["sock::unixDomainSockClient"];$unixDomainSockClient=sock::unixDomainSockClient($paramsOfUnixDomainSockClient);unset($paramsOfUnixDomainSockClient);#如果執行失敗if($unixDomainSockClient["status"]==="false"){#設置執行錯誤識別$result["status"]="false";#設置錯誤訊息$result["error"]=$unixDomainSockClient;#回傳結果return $result;}#if end#debug#var_dump(__LINE__,$unixDomainSockClient);#如果不是 json 字串if(json_validate(trim($unixDomainSockClient["content"]))==="false"){#設置執行錯誤識別$result["status"]="false";#設置錯誤訊息$result["error"][]=trim($unixDomainSockClient["content"])." is not json string!";#設置錯誤訊息$result["error"][]=$unixDomainSockClient;#回傳結果return $result;}#if end#取得json回應$jsonRes=json_decode(trim($unixDomainSockClient["content"]));#debug#var_dump(__LINE__,$jsonRes);#如果執行失敗if($jsonRes===null){#設置執行錯誤識別$result["status"]="false";#設置錯誤訊息$result["error"]=$unixDomainSockClient;#回傳結果return $result;}#if end#如果沒有產生新idif(!isset($jsonRes->id)){#設置執行錯誤識別$result["status"]="false";#設置錯誤訊息$result["error"]=$unixDomainSockClient;#回傳結果return $result;}#if end#用新的id再傳送一次要求給 qbpwcf_usock_path$paramsOfUnixDomainSockClient=$conf["sock::unixDomainSockClient"];$paramsOfUnixDomainSockClient["id"]=$jsonRes->id;#var_dump(__LINE__,$paramsOfUnixDomainSockClient);$unixDomainSockClient=sock::unixDomainSockClient($paramsOfUnixDomainSockClient);unset($paramsOfUnixDomainSockClient);#如果執行失敗if($unixDomainSockClient["status"]==="false"){#設置執行錯誤識別$result["status"]="false";#設置錯誤訊息$result["error"]=$unixDomainSockClient;#回傳結果return $result;}#if end#debug#var_dump(__LINE__,$unixDomainSockClient["content"]);#如果輸出非 jsonif(json_validate(trim($unixDomainSockClient["content"]))===false){#設置錯誤識別$result["status"]="false";#設置錯誤訊息$result["error"][]="got not json output";#設置錯誤訊息$result["error"][]=json_last_error().":".json_last_error_msg();#回傳結果return $result;}#if end#取得json回應$jsonRes=(array)json_decode($unixDomainSockClient["content"]);#如果執行失敗if($jsonRes===null){#設置執行錯誤識別$result["status"]="false";#設置錯誤訊息$result["error"]=$unixDomainSockClient;#回傳結果return $result;}#if end#如果執行指令失敗if($jsonRes["status"]==="false"){#設置執行錯誤識別$result["status"]="false";#設置錯誤訊息$result["error"]=$jsonRes["error"];#回傳結果return $result;}#if end#執行正常$result["status"]="true";#設置執行的結果$result["content"]=$jsonRes;#回傳結果return $result;}#public function execAnyCmdByQBPWCFunixSocket end/*#函式說明:#詢問透過 sock::unixDomainSockServer 執行的程序狀況#回傳結果:#$result["status"],"true"代表執行正常;"false"代表執行不正常.#$result["error"],錯誤訊息陣列.#$result["function"],當前執行的函式名稱.#$result["argu"],使用的參數.#$result["content"],陣列,程序的資訊.#$result["content"]["pid"],字串,程序的pid.#$result["content"]["running"],字串,是否正常執行中.#$result["content"]["statusCode"],字串,回傳給 shell 的代碼.#$result["content"]["input"],字串,輸入的內容.#$result["content"]["output"],字串,標準輸出的內容.#$result["content"]["error"],字串,錯誤輸出的內容.#必填參數:#$conf["uuid"],字串,proc的uuid.$conf["uuid"]="";#可省略參數:#$conf["sock"],字串,要連線的 usr/bin/qbpwcf-sock.php(sock::unixDomainSockServer) 所產生的 unix domain socket 路徑與名稱,預設為 qbpwcf_usock_path.#$conf["sock"]=qbpwcf_usock_path;#參考資料:#無.#備註:#無.*/public static function getProcInfo(&$conf){#初始化要回傳的結果$result=array();#取得當前執行的函數名稱$result["function"]=__FUNCTION__;#如果沒有參數if(func_num_args()==0){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]="函數".$result["function"]."需要參數";#回傳結果return $result;}#if end#取得參數$result["argu"]=$conf;#如果 $conf 不為陣列if(gettype($conf)!="array"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"][]="\$conf變數須為陣列形態";#如果傳入的參數為 nullif($conf==null){#設置執行錯誤訊息$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";}#if end#回傳結果return $result;}#if end#檢查參數#函式說明:#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容。#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$reuslt["error"],執行不正常結束的錯訊息陣列.#$result["function"],當前執行的函式名稱.#$result["argu"],設置給予的參數.#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.#$result["argu"],字串陣列,目前輸入的參數名稱陣列.#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.#$result["notNeedVar"],字串陣列,多餘的參數名稱.#必填寫的參數:#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。$conf["variableCheck::checkArguments"]["varInput"]=&$conf;#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";#可以省略的參數:#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("uuid");#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string");#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.#$conf["canBeEmptyString"]="false";#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.#$conf["canNotBeEmpty"]=array();#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.#$conf["canBeEmpty"]=array();#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("sock");#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("sock");#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string");#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array(qbpwcf_usock_path);#$conf["disallowAllSkipableVarIsEmpty"],字串,是否允許每個可省略參數都為空字串,預設為"true"允許,反之為"false".#$conf["disallowAllSkipableVarIsEmpty"]="";#$conf["disallowAllSkipableVarIsEmptyArray"],字串,是否允許每個可省略參數都為空陣列,預設為"true"允許,反之為"false".#$conf["disallowAllSkipableVarIsEmptyArray"]="";#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.#$conf["arrayCountEqualCheck"][]=array();#參考資料來源:#array_keys=>http://php.net/manual/en/function.array-keys.php$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);unset($conf["variableCheck::checkArguments"]);#如果檢查參數失敗if($checkArguments["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$checkArguments;#回傳結果return $result;}#if end#如果檢查參數不通過if($checkArguments["passed"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$checkArguments;#回傳結果return $result;}#if end函式說明:#連線到 unixDomainSockServer 提供的 unix domain socket.#回傳結果:#$result["status"],"true"代表執行正常;"false"代表執行不正常.#$result["error"],錯誤訊息陣列.#$result["function"],當前執行的函式名稱.#$result["content"],取得的回應.#必填參數:#$conf["sock"],字串,要連線的unix domain socket.$conf["sock::unixDomainSockClient"]["sock"]=$conf["sock"];#可省略參數:#$conf["id"],字串,取得的id,若無此值,則會得到新的數值.#$conf["id"]="";#$conf["cmd"],字串,要執行的指令,當$conf["id"]參數合法時,才會執行.#$conf["cmd"]="";#$conf["param"],參數陣列.#$conf["param"]=array();#$conf["escaped"],字串,param參數是否已經escaped了,預設為"false",反之為"true".#$conf["escaped"]="true";#$conf["custom"],陣列,要客制化傳輸的內容,會覆蓋以上除了$conf["id"]以外的可省略參數.$conf["sock::unixDomainSockClient"]["custom"]=array("QueryProcByUUID"=>$conf["uuid"]);#$conf["raw"],字串,要直接傳送的字串內容,會忽略其他可省略參數.#$conf["raw"]="";#參考資料:#http://php.net/manual/en/function.stream-socket-client.php#http://php.net/manual/en/function.stream-get-contents.php#備註:#無.$paramsOfUnixDomainSockClient=$conf["sock::unixDomainSockClient"];$unixDomainSockClient=sock::unixDomainSockClient($paramsOfUnixDomainSockClient);unset($paramsOfUnixDomainSockClient);#如果執行失敗if($unixDomainSockClient["status"]==="false"){#設置執行錯誤識別$result["status"]="false";#設置錯誤訊息$result["error"]=$unixDomainSockClient;#回傳結果return $result;}#if end#debug#var_dump(__LINE__,$unixDomainSockClient);#如果不是 json 字串if(json_validate(trim($unixDomainSockClient["content"]))==="false"){#設置執行錯誤識別$result["status"]="false";#設置錯誤訊息$result["error"][]=trim($unixDomainSockClient["content"])." is not json string!";#設置錯誤訊息$result["error"][]=$unixDomainSockClient;#回傳結果return $result;}#if end#取得json回應$jsonRes=json_decode(trim($unixDomainSockClient["content"]));#debug#var_dump(__LINE__,$jsonRes);#如果執行失敗if($jsonRes===null){#設置執行錯誤識別$result["status"]="false";#設置錯誤訊息$result["error"]=$unixDomainSockClient;#回傳結果return $result;}#if end#如果沒有產生新idif(!isset($jsonRes->id)){#設置執行錯誤識別$result["status"]="false";#設置錯誤訊息$result["error"]=$unixDomainSockClient;#回傳結果return $result;}#if end#用新的id再傳送一次要求給 qbpwcf_usock_path$paramsOfUnixDomainSockClient=$conf["sock::unixDomainSockClient"];$paramsOfUnixDomainSockClient["id"]=$jsonRes->id;$unixDomainSockClient=sock::unixDomainSockClient($paramsOfUnixDomainSockClient);unset($paramsOfUnixDomainSockClient);#如果執行失敗if($unixDomainSockClient["status"]==="false"){#設置執行錯誤識別$result["status"]="false";#設置錯誤訊息$result["error"]=$unixDomainSockClient;#回傳結果return $result;}#if end#debug#var_dump(__LINE__,$unixDomainSockClient["content"]);#如果輸出非 jsonif(json_validate(trim($unixDomainSockClient["content"]))===false){#設置錯誤識別$result["status"]="false";#設置錯誤訊息$result["error"][]="got not json output";#設置錯誤訊息$result["error"][]=json_last_error().":".json_last_error_msg();#設置原始訊息$result["error"][]="ori res:".$unixDomainSockClient["content"];#回傳結果return $result;}#if end#取得json回應$jsonRes=(array)json_decode($unixDomainSockClient["content"]);#如果執行失敗if($jsonRes===null){#設置執行錯誤識別$result["status"]="false";#設置錯誤訊息$result["error"]=$unixDomainSockClient;#回傳結果return $result;}#if end#如果執行指令失敗if($jsonRes["status"]==="false"){#設置執行錯誤識別$result["status"]="false";#設置錯誤訊息$result["error"]=$jsonRes["error"];#回傳結果return $result;}#if end#移除不需要的元素unset($jsonRes["status"]);#執行正常$result["status"]="true";#$result["content"],陣列,程序的資訊.#$result["content"]["pid"],字串,程序的pid.#$result["content"]["running"],字串,是否正常執行中.#$result["content"]["statusCode"],字串,回傳給 shell 的代碼.#$result["content"]["input"],字串,輸入的內容.#$result["content"]["output"],字串,標準輸出的內容.#$result["content"]["error"],字串,錯誤輸出的內容.#初始執行的結果$result["content"]=$jsonRes;#回傳結果return $result;}#function getProcInfo end/*#函式說明:#傳送 raw 訊息到 unix domain socket.#回傳結果:#$result["status"],"true"代表執行正常;"false"代表執行不正常.#$result["error"],錯誤訊息陣列.#$result["function"],當前執行的函式名稱.#$result["argu"],使用的參數.#$result["content"],得到的回應.#必填參數:#$conf["msg"],字串,要傳送的訊息.$conf["msg"]="";#$conf["sock"],字串,要連線的的 unix domain socket 路徑與名稱#$conf["sock"]="";#可省略參數:#無.#參考資料:#無.#備註:#無.*/public static function sendRawMsgUnixSocket(&$conf){#初始化要回傳的結果$result=array();#取得當前執行的函數名稱$result["function"]=__FUNCTION__;#如果沒有參數if(func_num_args()==0){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]="函數".$result["function"]."需要參數";#回傳結果return $result;}#if end#取得參數$result["argu"]=$conf;#如果 $conf 不為陣列if(gettype($conf)!="array"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"][]="\$conf變數須為陣列形態";#如果傳入的參數為 nullif($conf==null){#設置執行錯誤訊息$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";}#if end#回傳結果return $result;}#if end#函式說明:#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容.#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$result["error"],執行不正常結束的錯訊息陣列.#$result["simpleError"],簡單表示的錯誤訊息.#$result["function"],當前執行的函式名稱.#$result["argu"],設置給予的參數.#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.#$result["argu"],字串陣列,目前輸入的參數名稱陣列.#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.#$result["notNeedVar"],字串陣列,多餘的參數名稱.#必填參數:#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。$conf["variableCheck::checkArguments"]["varInput"]=&$conf;#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";#可省略參數:#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("msg","sock");#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string","string");#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.#$conf["canBeEmptyString"]="false";#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.#$conf["canNotBeEmpty"]=array();#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.#$conf["canBeEmpty"]=array();#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.#$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("sock");#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");#$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("sock");#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");#$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string");#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".#$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array(qbpwcf_usock_path);#$conf["disallowAllSkipableVarIsEmpty"],字串,是否允許每個可省略參數都為空字串,預設為"true"允許,反之為"false".#$conf["disallowAllSkipableVarIsEmpty"]="";#$conf["disallowAllSkipableVarIsEmptyArray"],字串,是否允許每個可省略參數都為空陣列,預設為"true"允許,反之為"false".#$conf["disallowAllSkipableVarIsEmptyArray"]="";#$conf["disallowAllSkipableVarNotExist"],字串,是否不允許每個可省略參數都不存在,預設為"false"代表允許,反之為"true".#$conf["disallowAllSkipableVarNotExist"]="";#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.#$conf["arrayCountEqualCheck"][]=array();#參考資料:#array_keys=>http://php.net/manual/en/function.array-keys.php#備註:#無.$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);unset($conf["variableCheck::checkArguments"]);#如果執行失敗if($checkArguments["status"]==="false"){#設置執行錯誤識別$result["status"]="false";#設置錯誤訊息$result["error"]=$checkArguments["error"];#回傳結果return $result;}#if end#如果檢查不通過if($checkArguments["status"]==="false"){#設置執行錯誤識別$result["status"]="false";#設置錯誤訊息$result["error"]=$checkArguments["error"];#回傳結果return $result;}#if end#讓存放unix domain socket的路徑存在#函式說明:#確保路徑存在.#回傳結果:#$result["status"],執行正常與否,"true"代表正常,"false"代表不正常.#$result["error"],錯誤訊息陣列.#$resutl["function"],當前執行的涵式名稱.#$result["path"],建立好的路徑字串.#$result["fileName"],檔案名稱,若 $conf["haveFileName"] 為 "true" 則會回傳.#$result["argu"],使用的參數.#必填參數:#$conf["path"],要檢查的路徑$conf["fileAccess::validatePath"]["path"]=$conf["sock"];#$conf["fileArgu"],字串,php變數__FILE__的內容,亦即該檔案在檔案系統的絕對路徑$conf["fileAccess::validatePath"]["fileArgu"]=__FILE__;#可省略參數:#$conf["haveFileName"],字串,"true"代表有$conf["path"]檔案名稱,"false"代表$conf["path"]為純路徑,預設為"false".$conf["fileAccess::validatePath"]["haveFileName"]="true";#$conf["dirPermission"],字串,新建資料夾的權限設定,預設爲0770,亦即擁有者,同群組者可以讀,寫,存取,其他人無法使用.#$conf["dirPermission"]="";#$conf["web"],是否為檔案系統,"true"為網頁路徑,"false"為網頁系統,預設為"false".$conf["fileAccess::validatePath"]["web"]="false";#參考資料:#無.#備註:#無.$validatePath=fileAccess::validatePath($conf["fileAccess::validatePath"]);unset($conf["fileAccess::validatePath"]);#如果執行失敗if($validatePath["status"]==="false"){#設置錯誤識別$result["status"]="false";#設置錯誤訊息$result["error"]=$validatePath;#回傳結果return $result;}#if end#變更 working dir$chdir=chdir($validatePath["path"]);#嘗試30秒內連線到 unix domain socket$fp=stream_socket_client("unix://".$validatePath["fileName"], $errno, $errstr, 30, STREAM_CLIENT_ASYNC_CONNECT );#如果開啟 unix domain socket 失敗if(!$fp){#設置執行錯誤識別$result["status"]="false";#設置錯誤訊息$result["error"]=$errstr." (".$errno.")";#回傳結果return $result;}#if end#傳遞訊息$fwrite=fwrite($fp,$conf["msg"]);#如果傳遞失敗if($fwrite===false){#關閉unix domain socket@fclose($fp);#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"][]="傳遞訊息(".$conf["msg"].")失敗";#回傳結果return $result;}#if end#設置執行正常$result["status"]="true";#回傳結果return $result;}#function sendRawMsgUnixSocket/*#連線到 sock::unixDomainSocketServer 產生的 unix domain socket,傳送指定的訊息.#回傳結果:#$result["status"],"true"代表執行正常;"false"代表執行不正常.#$result["error"],錯誤訊息陣列.#$result["function"],當前執行的函式名稱.#$result["argu"],使用的參數.#$result["content"],得到的回應.#必填參數:#$conf["msg"],陣列,要傳送的訊息,其主$conf["msg"]["id"],是無法指定的.$conf["msg"]=array();#可省略參數:#$conf["sock"],字串,要連線的 usr/bin/qbpwcf-sock.php 所產生的 unix domain socket 路徑與名稱,預設為 qbpwcf_usock_path.#$conf["sock"]=qbpwcf_usock_path;#參考資料:#無.#備註:#無.*/public static function sendAnyMsgToQBPWCFunixSocket(&$conf){#初始化要回傳的結果$result=array();#取得當前執行的函數名稱$result["function"]=__FUNCTION__;#如果沒有參數if(func_num_args()==0){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]="函數".$result["function"]."需要參數";#回傳結果return $result;}#if end#取得參數$result["argu"]=$conf;#如果 $conf 不為陣列if(gettype($conf)!="array"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"][]="\$conf變數須為陣列形態";#如果傳入的參數為 nullif($conf==null){#設置執行錯誤訊息$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";}#if end#回傳結果return $result;}#if end#函式說明:#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容.#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$result["error"],執行不正常結束的錯訊息陣列.#$result["simpleError"],簡單表示的錯誤訊息.#$result["function"],當前執行的函式名稱.#$result["argu"],設置給予的參數.#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.#$result["argu"],字串陣列,目前輸入的參數名稱陣列.#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.#$result["notNeedVar"],字串陣列,多餘的參數名稱.#必填參數:#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。$conf["variableCheck::checkArguments"]["varInput"]=&$conf;#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";#可省略參數:#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("msg");#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("array");#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.#$conf["canBeEmptyString"]="false";#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.#$conf["canNotBeEmpty"]=array();#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.#$conf["canBeEmpty"]=array();#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("sock");#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("sock");#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string");#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array(qbpwcf_usock_path);#$conf["disallowAllSkipableVarIsEmpty"],字串,是否允許每個可省略參數都為空字串,預設為"true"允許,反之為"false".#$conf["disallowAllSkipableVarIsEmpty"]="";#$conf["disallowAllSkipableVarIsEmptyArray"],字串,是否允許每個可省略參數都為空陣列,預設為"true"允許,反之為"false".#$conf["disallowAllSkipableVarIsEmptyArray"]="";#$conf["disallowAllSkipableVarNotExist"],字串,是否不允許每個可省略參數都不存在,預設為"false"代表允許,反之為"true".#$conf["disallowAllSkipableVarNotExist"]="";#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.#$conf["arrayCountEqualCheck"][]=array();#參考資料:#array_keys=>http://php.net/manual/en/function.array-keys.php#備註:#無.$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);unset($conf["variableCheck::checkArguments"]);#如果執行失敗if($checkArguments["status"]==="false"){#設置執行錯誤識別$result["status"]="false";#設置錯誤訊息$result["error"]=$checkArguments["error"];#回傳結果return $result;}#if end#如果檢查不通過if($checkArguments["status"]==="false"){#設置執行錯誤識別$result["status"]="false";#設置錯誤訊息$result["error"]=$checkArguments["error"];#回傳結果return $result;}#if end#函式說明:#連線到 unixDomainSockServer 提供的 unix domain socket.#回傳結果:#$result["status"],"true"代表執行正常;"false"代表執行不正常.#$result["error"],錯誤訊息陣列.#$result["function"],當前執行的函式名稱.#$result["content"],取得的回應,讀到EOL,才會結束.#必填參數:#$conf["sock"],字串,要連線的unix domain socket.$conf["sock::unixDomainSockClient"]["sock"]=$conf["sock"];#可省略參數:#$conf["id"],字串,取得的id,若無此值,則會得到新的數值.#$conf["id"]="";#$conf["cmd"],字串,要執行的指令,當$conf["id"]參數合法時,才會執行.#$conf["cmd"]="";#$conf["param"],參數陣列.#$conf["param"]=array();#$conf["escaped"],字串,param參數是否已經escaped了,預設為"false",反之為"true".#$conf["escaped"]="true";#$conf["custom"],陣列,要客制化傳輸的內容,會覆蓋以上除了$conf["id"]以外的可省略參數.$conf["sock::unixDomainSockClient"]["custom"]=$conf["msg"];#參考資料:#http://php.net/manual/en/function.stream-socket-client.php#http://php.net/manual/en/function.stream-get-contents.php#備註:#無.$paramsOfUnixDomainSockClient=$conf["sock::unixDomainSockClient"];$unixDomainSockClient=sock::unixDomainSockClient($conf["sock::unixDomainSockClient"]);unset($conf["sock::unixDomainSockClient"]);#如果執行失敗if($unixDomainSockClient["status"]==="false"){#設置執行錯誤識別$result["status"]="false";#設置錯誤訊息$result["error"]=$unixDomainSockClient;#回傳結果return $result;}#if end#取得json回應$jsonRes=json_decode($unixDomainSockClient["content"]);#如果執行失敗if($jsonRes===null){#設置執行錯誤識別$result["status"]="false";#設置錯誤訊息$result["error"]=$unixDomainSockClient;#回傳結果return $result;}#if end#如果沒有產生新idif(!isset($jsonRes->id)){#設置執行錯誤識別$result["status"]="false";#設置錯誤訊息$result["error"]=$unixDomainSockClient;#回傳結果return $result;}#if end#用新的id再傳送一次要求給 qbpwcf_usock_path$paramsOfUnixDomainSockClient["id"]=$jsonRes->id;$unixDomainSockClient=sock::unixDomainSockClient($paramsOfUnixDomainSockClient);unset($paramsOfUnixDomainSockClient);#如果執行失敗if($unixDomainSockClient["status"]==="false"){#設置執行錯誤識別$result["status"]="false";#設置錯誤訊息$result["error"]=$unixDomainSockClient;#回傳結果return $result;}#if end#取得回應$result["content"]=$unixDomainSockClient["content"];#設置執行正常$result["status"]="true";#回傳結果return $result;}#function sendAnyMsgToQBPWCFunixSocket end/*#函式說明:#重複連線到 unixDomainSockServer 提供的 unix domain socket, 避免其 listen timeout, 並清除逾時的連線.#回傳結果:#$result["status"],"true"代表執行正常;"false"代表執行不正常.#$result["error"],錯誤訊息陣列.#$result["function"],當前執行的函式名稱.#必填參數:#$conf["sock"],字串,要連線的unix domain socket.$conf["sock"]="";#可省略參數:#無.#參考資料:#無.#備註:#無.*/public static function keepAliveUnixDomainSockConnection(&$conf){#初始化要回傳的結果$result=array();#取得當前執行的函數名稱$result["function"]=__FUNCTION__;#如果沒有參數if(func_num_args()==0){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]="函數".$result["function"]."需要參數";#回傳結果return $result;}#if end#涵式說明:#判斷當前環境為web還是cmd#回傳結果:#$result,"web"或"cmd"if(csInformation::getEnv()==="web"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"][]="函數 ".$result["function"]." 僅能在命令列環境下運行!";#回傳結果return $result;}#if end#取得參數$result["argu"]=$conf;#如果 $conf 不為陣列if(gettype($conf)!="array"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"][]="\$conf變數須為陣列形態";#如果傳入的參數為 nullif($conf==null){#設置執行錯誤訊息$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";}#if end#回傳結果return $result;}#if end#檢查參數#函式說明:#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容。#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$reuslt["error"],執行不正常結束的錯訊息陣列.#$result["function"],當前執行的函式名稱.#$result["argu"],設置給予的參數.#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.#$result["argu"],字串陣列,目前輸入的參數名稱陣列.#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.#$result["notNeedVar"],字串陣列,多餘的參數名稱.#必填寫的參數:#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。$conf["variableCheck::checkArguments"]["varInput"]=&$conf;#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";#可以省略的參數:#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("sock");#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string");#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.#$conf["canBeEmptyString"]="false";#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.#$conf["canNotBeEmpty"]=array();#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.#$conf["canBeEmpty"]=array();#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.#$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("id","cmd","param","clear");#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");#$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("id","cmd","param","clear");#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");#$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","string","array","string");#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".#$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array();#$conf["disallowAllSkipableVarIsEmpty"],字串,是否允許每個可省略參數都為空字串,預設為"true"允許,反之為"false".#$conf["disallowAllSkipableVarIsEmpty"]="";#$conf["disallowAllSkipableVarIsEmptyArray"],字串,是否允許每個可省略參數都為空陣列,預設為"true"允許,反之為"false".#$conf["disallowAllSkipableVarIsEmptyArray"]="";#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.#$conf["arrayCountEqualCheck"][]=array();#參考資料來源:#array_keys=>http://php.net/manual/en/function.array-keys.php$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);unset($conf["variableCheck::checkArguments"]);#如果檢查參數失敗if($checkArguments["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$checkArguments;#回傳結果return $result;}#if end#如果檢查參數不通過if($checkArguments["passed"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$checkArguments;#回傳結果return $result;}#if end#函式說明:#連線到 unixDomainSockServer 提供的 unix domain socket.#回傳結果:#$result["status"],"true"代表執行正常;"false"代表執行不正常.#$result["error"],錯誤訊息陣列.#$result["function"],當前執行的函式名稱.#$result["content"],取得的回應.#必填參數:#$conf["sock"],字串,要連線的unix domain socket.$conf["sock::unixDomainSockClient"]["sock"]=$conf["sock"];#可省略參數:#$conf["id"],字串,取得的id,若無此值,則會得到新的數值.#$conf["id"]="";#$conf["cmd"],字串,要執行的指令.#$conf["cmd"]="";#$conf["param"],參數陣列.#$conf["param"]=array();#參考資料:#http://php.net/manual/en/function.stream-socket-client.php#http://php.net/manual/en/function.stream-get-contents.php$unixDomainSockClient=sock::unixDomainSockClient($conf["sock::unixDomainSockClient"]);unset($conf["sock::unixDomainSockClient"]);#建立連線失敗if($unixDomainSockClient["status"]==="false"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]=$unixDomainSockClient;#回傳結果return $result;}#if end#取得回應$res=$unixDomainSockClient["content"];#解析回應$res=json_decode(trim($res));#如果解析失敗if($res===false){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"][]="解析回應失敗";#回傳結果return $result;}#if end#取得id$id=$res->id;#無窮迴圈while(true){#函式說明:#連線到 unixDomainSockServer 提供的 unix domain socket.#回傳結果:#$result["status"],"true"代表執行正常;"false"代表執行不正常.#$result["error"],錯誤訊息陣列.#$result["function"],當前執行的函式名稱.#$result["content"],取得的回應.#必填參數:#$conf["sock"],字串,要連線的unix domain socket.$conf["sock::unixDomainSockClient"]["sock"]=$conf["sock"];#可省略參數:#$conf["id"],字串,取得的id,若無此值,則會得到新的數值.$conf["sock::unixDomainSockClient"]["id"]=$id;#$conf["cmd"],字串,要執行的指令.#$conf["cmd"]="";#$conf["param"],參數陣列.#$conf["param"]=array();#參考資料:#http://php.net/manual/en/function.stream-socket-client.php#http://php.net/manual/en/function.stream-get-contents.php$unixDomainSockClient=sock::unixDomainSockClient($conf["sock::unixDomainSockClient"]);unset($conf["sock::unixDomainSockClient"]);#建立連線失敗if($unixDomainSockClient["status"]==="false"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]=$unixDomainSockClient;#回傳結果return $result;}#if end#取得回應$res=$unixDomainSockClient["content"];#解析回應$res=json_decode($res);#如果解析失敗if($res===false){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"][]="解析回應失敗";#回傳結果return $result;}#if end#show resvar_dump($res);#停止執行sleep(60);}#while end#設置執行不正常$result["status"]="false";#設置錯誤訊息$result["error"][]="程式不應該中斷";#回傳結果return $reuslt;}#function keepAliveUnixDomainSockConnection end/*#函式說明:#tcp client#回傳結果:#$result["status"],"true"代表執行正常;"false"代表執行不正常.#$result["error"],錯誤訊息陣列.#$result["function"],當前執行的函式名稱.#$result["argu"],使用的參數.#$result["content"],取得的回應內容.#必填參數:#$conf["port"],整數,tcp server listen port.$conf["port"]=;#$conf["dataToSend"],字串,要傳送的資訊.$conf["dataToSend"]="";#可省略參數:#$conf["ip"],整數字串,tcp serer listen ip, default is 127.0.0.1.#$conf["ip"]="127.0.0.1";#$conf["sec"],整數,等待回應的秒數,預設為5秒.#$conf["sec"]=5;#$conf["microSec"],整數,等待回應的毫秒數,預設為0毫秒#$conf["microSec"]=0;#參考資料:#https://www.php.net/manual/en/sockets.examples.php#https://www.php.net/manual/en/function.socket-get-option.php#備註:#無.*/public static function tcpClient(&$conf){#初始化要回傳的結果$result=array();#取得當前執行的函數名稱$result["function"]=__FUNCTION__;#如果沒有參數if(func_num_args()==0){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]="函數".$result["function"]."需要參數";#回傳結果return $result;}#if end#涵式說明:#判斷當前環境為web還是cmd#回傳結果:#$result,"web"或"cmd"if(csInformation::getEnv()==="web"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"][]="函數 ".$result["function"]." 僅能在命令列環境下運行!";#回傳結果return $result;}#if end#取得參數$result["argu"]=$conf;#如果 $conf 不為陣列if(gettype($conf)!="array"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"][]="\$conf變數須為陣列形態";#如果傳入的參數為 nullif($conf==null){#設置執行錯誤訊息$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";}#if end#回傳結果return $result;}#if end#初始化取得的回應$result["content"]="";#檢查參數#函式說明:#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容。#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$reuslt["error"],執行不正常結束的錯訊息陣列.#$result["function"],當前執行的函式名稱.#$result["argu"],設置給予的參數.#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.#$result["argu"],字串陣列,目前輸入的參數名稱陣列.#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.#$result["notNeedVar"],字串陣列,多餘的參數名稱.#必填寫的參數:#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。$conf["variableCheck::checkArguments"]["varInput"]=&$conf;#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";#可以省略的參數:#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("port","dataToSend");#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("integer","string");#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.$conf["variableCheck::checkArguments"]["canBeEmptyString"]="false";#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.#$conf["canNotBeEmpty"]=array();#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.#$conf["canBeEmpty"]=array();#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("ip");#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("ip","sec","microSec");#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","integer","integer");#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("127.0.0.1",5,0);#$conf["disallowAllSkipableVarIsEmpty"],字串,是否允許每個可省略參數都為空字串,預設為"true"允許,反之為"false".#$conf["disallowAllSkipableVarIsEmpty"]="";#$conf["disallowAllSkipableVarIsEmptyArray"],字串,是否允許每個可省略參數都為空陣列,預設為"true"允許,反之為"false".#$conf["disallowAllSkipableVarIsEmptyArray"]="";#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.#$conf["arrayCountEqualCheck"][]=array();#參考資料來源:#array_keys=>http://php.net/manual/en/function.array-keys.php$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);unset($conf["variableCheck::checkArguments"]);#如果檢查參數失敗if($checkArguments["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$checkArguments;#回傳結果return $result;}#if end#如果檢查參數不通過if($checkArguments["passed"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$checkArguments;#回傳結果return $result;}#if end#建立 tcp socket client$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);#設置接收資料的最長等待時間socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array("sec"=>$conf["sec"],"usec"=>$conf["microSec"]));#如果建立 socket 失敗if ($socket === false) {#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"][]="socket_create() failed: reason: " . socket_strerror(socket_last_error());#回傳結果return $result;}#if end#連線到 tcp socket server$socket_connect = socket_connect($socket, $conf["ip"], $conf["port"]);#如果連線到 tcp socket server 失敗if ($socket_connect === false) {#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"][]="socket_connect() failed. Reason: ($result) " . socket_strerror(socket_last_error($socket));#回傳結果return $result;}#if end#傳送訊息到 tcp serversocket_write($socket, $conf["dataToSend"].PHP_EOL, strlen($conf["dataToSend"].PHP_EOL));#取得回應while ($out = socket_read($socket, 2048)) {#設置取得的回應$result["content"]=$result["content"].$out;#debug#echo $result["content"];}#while end#關閉socketsocket_close($socket);#設置處理正常$result["status"]="true";#回傳結果return $result;}#function tcpClient end/*#函式說明:#udp client#回傳結果:#$result["status"],"true"代表執行正常;"false"代表執行不正常.#$result["error"],錯誤訊息陣列.#$result["function"],當前執行的函式名稱.#$result["argu"],使用的參數.#$result["content"],取得的回應內容字串,為每個回應的內容直接串接.#$result["contentArray"],取得的回應字串陣列,為每個回應的內容,各別儲存成陣列中的元素.#$result["sock"],可重複使用的socket資源.#必填參數:#$conf["port"],整數,target port.$conf["port"]=;#$conf["dataToSend"],陣列字串,要傳送的多個訊息,每個訊息傳送結束後才會讀取回應.$conf["dataToSend"]=array("");#可省略參數:#$conf["ip"],整數字串,tcp serer listen ip, default is 127.0.0.1.#$conf["ip"]="127.0.0.1";#$conf["timeout"],整數,預設為10秒,代表接收訊息的等待時間上限.#$conf["timeout"]=10;#$conf["secSleepAfterSend"],整數,預設為1秒.#$conf["secSleepAfterSend"]=1;#$conf["closeAtEnd"],字串,預設為"true",代表函式結束後要斷開連線.#$conf["closeAtEnd"]="true";#$conf["sock"],resource,要重複使用的socket資源,預設不指定.#$conf["sock"]=;#參考資料:#https://www.php.net/manual/en/sockets.examples.php#備註:#無.*/public static function udpClient(&$conf){#初始化要回傳的結果$result=array();#取得當前執行的函數名稱$result["function"]=__FUNCTION__;#如果沒有參數if(func_num_args()==0){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]="函數".$result["function"]."需要參數";#回傳結果return $result;}#if end#涵式說明:#判斷當前環境為web還是cmd#回傳結果:#$result,"web"或"cmd"if(csInformation::getEnv()==="web"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"][]="函數 ".$result["function"]." 僅能在命令列環境下運行!";#回傳結果return $result;}#if end#取得參數$result["argu"]=$conf;#如果 $conf 不為陣列if(gettype($conf)!="array"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"][]="\$conf變數須為陣列形態";#如果傳入的參數為 nullif($conf==null){#設置執行錯誤訊息$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";}#if end#回傳結果return $result;}#if end#初始化取得的回應$result["content"]="";#檢查參數#函式說明:#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容。#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$reuslt["error"],執行不正常結束的錯訊息陣列.#$result["function"],當前執行的函式名稱.#$result["argu"],設置給予的參數.#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.#$result["argu"],字串陣列,目前輸入的參數名稱陣列.#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.#$result["notNeedVar"],字串陣列,多餘的參數名稱.#必填寫的參數:#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。$conf["variableCheck::checkArguments"]["varInput"]=&$conf;#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";#可以省略的參數:#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("port","dataToSend");#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("integer","array");#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.$conf["variableCheck::checkArguments"]["canBeEmptyString"]="false";#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.#$conf["canNotBeEmpty"]=array();#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.#$conf["canBeEmpty"]=array();#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("ip","secSleepAfterSend","closeAtEnd","timeout");#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("ip","secSleepAfterSend","closeAtEnd","sock","timeout");#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","integer","string","object","integer");#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("127.0.0.1",1,"false",null,10);#$conf["disallowAllSkipableVarIsEmpty"],字串,是否允許每個可省略參數都為空字串,預設為"true"允許,反之為"false".#$conf["disallowAllSkipableVarIsEmpty"]="";#$conf["disallowAllSkipableVarIsEmptyArray"],字串,是否允許每個可省略參數都為空陣列,預設為"true"允許,反之為"false".#$conf["disallowAllSkipableVarIsEmptyArray"]="";#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.#$conf["arrayCountEqualCheck"][]=array();#參考資料來源:#array_keys=>http://php.net/manual/en/function.array-keys.php$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);unset($conf["variableCheck::checkArguments"]);#如果檢查參數失敗if($checkArguments["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$checkArguments;#回傳結果return $result;}#if end#如果檢查參數不通過if($checkArguments["passed"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$checkArguments;#回傳結果return $result;}#if end#如果沒有指定要用既有的 socketif(!isset($conf["sock"])){#建立 udp socket client$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);#設置 timeout 為 $conf["timeout"] 秒$timeout = array('sec'=>$conf["timeout"],'usec'=>0);socket_set_option($socket,SOL_SOCKET,SO_RCVTIMEO,$timeout);#如果建立 socket 失敗if ($socket === false) {#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"][]="socket_create() failed: reason: " . socket_strerror(socket_last_error());#回傳結果return $result;}#if end#連線到 udp socket server$socket_connect = socket_connect($socket, $conf["ip"], $conf["port"]);#如果連線到 udp socket server 失敗if ($socket_connect === false) {#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"][]="socket_connect() failed. Reason: ($result) " . socket_strerror(socket_last_error($socket));#回傳結果return $result;}#if end}#if end#反之else{#取得要重複使用的socket$socket=&$conf["sock"];}#else end#有幾個訊息就跑幾次for($i=0;$i<count($conf["dataToSend"]);$i++){#傳送訊息到 tcp serversocket_write($socket, $conf["dataToSend"][$i], strlen($conf["dataToSend"][$i]));#取得回應while ($out = socket_read($socket, 2048)) {#設置取得的回應,儲存到陣列裡面.$result["contentArray"][]=$out;#設置取得的回應,儲存成字串,串接在一塊.$result["content"]=$result["content"].$out;}#while end#如果有多個訊息要傳遞,且不是最後一個訊息if(count($conf["dataToSend"])>1 && $i!==count($conf["dataToSend"])-1){#休息一下sleep($conf["secSleepAfterSend"]);}#if end}#for end#如果要關閉連線if($conf["closeAtEnd"]==="true"){#關閉socketsocket_close($socket);}#if end#取得使用的socket$result["sock"]=$socket;#設置處理正常$result["status"]="true";#回傳結果return $result;}#function udpClient end/*#函式說明:#建立tcp server#必填參數:#$conf["port"],整數,tcp server listen port.$conf["port"]=;#可省略參數:#$conf["ip"],整數字串,tcp server listen ip, default is 0.0.0.0.#$conf["ip"]="0.0.0.0";#$conf["processFuncs"],字串陣列,要將收到的訊息作什麼事情的函式們,預設為空陣列,裡面若是自己建立的涵式,可這樣呼叫"\qbpwcf\your function name".#$conf["processFuncs"]=array();#$conf["serverFuncs"],字串陣列,於idle時,server要執行的函式們,預設為空陣列.#$conf["serverFuncs"]=array();#$conf["welcomeMsg"],字串,是否要顯示歡迎訊息,預設為"true"代表要顯示歡迎訊息;"false"代表不要顯示歡迎訊息.#$conf["welcomeMsg"]="true";#$conf["socketSelectTimeountSec"],整數,代表要等候幾秒才抓取有異動的連線,預設為0代表立即抓取有異動的連線,但是會吃很多cpu.#$conf["socketSelectTimeountSec"]=0;#$conf["socketSelectTimeountUsec"],整數,代表要等候幾微秒才抓取有異動的連線,預設不使用.#$conf["socketSelectTimeountUsec"]=5000;#參考資料:#無.#備註:#無.*/public static function tcpServer(&$conf){#初始化要回傳的結果$result=array();#取得當前執行的函數名稱$result["function"]=__FUNCTION__;#如果沒有參數if(func_num_args()==0){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]="函數".$result["function"]."需要參數";#回傳結果return $result;}#if end#涵式說明:#判斷當前環境為web還是cmd#回傳結果:#$result,"web"或"cmd"if(csInformation::getEnv()==="web"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"][]="函數 ".$result["function"]." 僅能在命令列環境下運行!";#回傳結果return $result;}#if end#取得參數$result["argu"]=$conf;#如果 $conf 不為陣列if(gettype($conf)!="array"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"][]="\$conf變數須為陣列形態";#如果傳入的參數為 nullif($conf==null){#設置執行錯誤訊息$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";}#if end#回傳結果return $result;}#if end#檢查參數#函式說明:#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容。#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$reuslt["error"],執行不正常結束的錯訊息陣列.#$result["function"],當前執行的函式名稱.#$result["argu"],設置給予的參數.#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.#$result["argu"],字串陣列,目前輸入的參數名稱陣列.#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.#$result["notNeedVar"],字串陣列,多餘的參數名稱.#必填寫的參數:#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。$conf["variableCheck::checkArguments"]["varInput"]=&$conf;#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";#可以省略的參數:#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("port");#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("integer");#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.#$conf["canBeEmptyString"]="false";#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.#$conf["canNotBeEmpty"]=array();#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.#$conf["canBeEmpty"]=array();#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("ip","welcomeMsg");#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("ip","processFuncs","welcomeMsg","socketSelectTimeountSec","socketSelectTimeountUsec","serverFuncs");#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","array","string","integer","integer","array");#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("0.0.0.0",array(),"true",0,null,null);#$conf["disallowAllSkipableVarIsEmpty"],字串,是否允許每個可省略參數都為空字串,預設為"true"允許,反之為"false".#$conf["disallowAllSkipableVarIsEmpty"]="";#$conf["disallowAllSkipableVarIsEmptyArray"],字串,是否允許每個可省略參數都為空陣列,預設為"true"允許,反之為"false".#$conf["disallowAllSkipableVarIsEmptyArray"]="";#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.#$conf["arrayCountEqualCheck"][]=array();#參考資料來源:#array_keys=>http://php.net/manual/en/function.array-keys.php$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);unset($conf["variableCheck::checkArguments"]);#如果檢查參數失敗if($checkArguments["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$checkArguments;#回傳結果return $result;}#if end#如果檢查參數不通過if($checkArguments["passed"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$checkArguments;#回傳結果return $result;}#if end#程式不會 timeoutset_time_limit(0);#Turn on implicit output flushing so we see what we're getting as it comes in.ob_implicit_flush();#set listen ip and port$address = $conf["ip"];#set listen port$port = $conf["port"];//如果建立 socket 失敗if (($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === false) {echo "socket_create() failed: reason: " . socket_strerror(socket_last_error()) . PHP_EOL;}#if end//如果 bind socket 失敗if (socket_bind($sock, $address, $port) === false) {echo "socket_bind() failed: reason: " . socket_strerror(socket_last_error($sock)) . PHP_EOL;}#if end//如果 socket listen 超過 5 秒仍未成功if (socket_listen($sock, 5) === false) {echo "socket_listen() failed: reason: " . socket_strerror(socket_last_error($sock)) . PHP_EOL;}#if end// create a list of all the clients that will be connected to us..// add the listening socket to this list$clients = array("serverSock"=>$sock);#無窮迴圈do {#each resourceforeach($clients as $rk=>$csock){#if not socket resourceif(get_resource_type($csock)!=="Socket"){#deleteunset($clients[$rk]);}#if end}#foreach end#found server sock$serverSock=false;#each resourceforeach($clients as $rk=>$csock){#if not socket resourceif($rk==="serverSock"){#found server sock$serverSock=true;}#if end}#if end#not found server sockif(!$serverSock){#endexit;}#if end#for socket select$read = $clients;$write = NULL;$except = NULL;#如果沒設定微妙if(!isset($conf["socketSelectTimeountUsec"])){#get interesting socket$num_changed_sockets = socket_select($read, $write, $except, $conf["socketSelectTimeountSec"]);}#if end#反之有設定微妙else{#get interesting socket$num_changed_sockets = socket_select($read, $write, $except, $conf["socketSelectTimeountSec"], $conf["socketSelectTimeountUsec"]);}#else end#socket_select failedif ($num_changed_sockets === false) {#NOTICE to serverecho "socket_select failed".PHP_EOL;}#At least at one of the sockets something interesting happenedelse if ($num_changed_sockets > 0) {/* debugecho "At least at one of the sockets something interesting happened".PHP_EOL;echo "\$read:".PHP_EOL;var_dump($read);echo "\$write:".PHP_EOL;var_dump($write);echo "\$except:".PHP_EOL;var_dump($except);*/// check if there is a client trying to connectif (in_array($sock, $read)) {#accept the client, and add him to the $clients array$clients[] = $newsock = socket_accept($sock);#如果要顯示歡迎訊息if($conf["welcomeMsg"]==="true"){#send the client a welcome messagesocket_write($newsock, "Welcome to QBPWCF tcpServer".PHP_EOL."There are ".(count($clients) - 1)." client(s) connected to the server".PHP_EOL);}#if end#嘗試取得遠端的ip與port#參考資料:https://www.php.net/manual/en/function.socket-getpeername.php@socket_getpeername($newsock, $ip);#如果有抓到 $ipif(isset($ip)){#提示有新的使用者echo "New client connected: ".$ip.PHP_EOL;}#if end// remove the listening socket from the clients-with-data array$key = array_search($sock, $read);unset($read[$key]);}#message receivedelse{// loop through all the clients that have data to read fromforeach ($read as $read_sock) {// read until newline or 1024 bytes// socket_read while show errors when the client is disconnected, so silence the error messages$data = @socket_read($read_sock, 1024, PHP_NORMAL_READ);// check if the client is disconnectedif ($data === false){// remove client for $clients array$key = array_search($read_sock, $clients);unset($clients[$key]);echo "client disconnected.".PHP_EOL;// continue to the next client to read from, if anycontinue;}// trim off the trailing/beginning white spaces$data = trim($data);// check if there is any data after trimming off the spacesif(!empty($data)){// send this to all the clients in the $clients array (except the first one, which is a listening socket)foreach ($clients as $send_sock) {// if its the listening sock or the client that we got the message from, go to the next one in the list#如果是Server Socketif ($send_sock === $sock){#server debugecho "reveiced:".$data.PHP_EOL;#針對每個用來處理輸入字串的函式foreach($conf["processFuncs"] as $proFunc){#呼叫函式,參數為輸入的字串data跟client socket, server socket, 每個 socket#https://www.php.net/manual/en/function.call-user-func.php$param=array("data"=>$data,"serverSock"=>$sock,"clientSock"=>$read_sock,"allSockArray"=>$clients);$params=array();$params[]=&$param;$result=call_user_func_array($proFunc,$params);#如果有回傳結果if($result!==NULL){#如果執行出錯if($result["status"]==="false"){#印出結果var_dump($result);}}}}/*#如果是Sender Socketelse if ($send_sock === $read_sock){continue;}*//*#msg to others/broadcastelse{// write the message to the client -- add a newline character to the end of the messagesocket_write($send_sock, $data.PHP_EOL);}//end of broadcast*/} //foreach end}#if end} // end of reading foreach}#msg received end}#something happen end#反之沒有用戶插手else{#提示idle#echo "idle:".time().PHP_EOL;#如果沒有設置 $conf["serverFuncs"]if(!isset($conf["serverFuncs"])){#設置為空陣列$conf["serverFuncs"]=array();}#if end#針對每個用來處理輸入字串的函式foreach($conf["serverFuncs"] as $proFunc){#呼叫函式,參數為輸入的字串data跟client socket, server socket, 每個 socket#https://www.php.net/manual/en/function.call-user-func.php$result=call_user_func_array($proFunc,array());#如果有回傳結果if($result!==NULL){#如果執行出錯if($result["status"]==="false"){#印出結果var_dump($result);}//if end}//if end}//foreach end}#else end} while (true);#關閉listen的socketsocket_close($sock);}#function tcpServer end/*#函式說明:#建立 udp server#必填參數:#$conf["port"],整數,udp server listen port.$conf["port"]=;#可省略參數:#$conf["ip"],整數字串,udp serer listen ip, default is 0.0.0.0.#$conf["ip"]="0.0.0.0";#$conf["processFuncs"],字串陣列,要將收到的訊息作什麼事情的函式們,預設為空陣列.#$conf["processFuncs"]=array();#$conf["welcomeMsg"],字串,是否要顯示歡迎訊息,預設為"true"代表要顯示歡迎訊息;"false"代表不要顯示歡迎訊息.#$conf["welcomeMsg"]="true";#$conf["socketSelectTimeountSec"],整數,代表要等候幾秒才抓取有異動的連線,預設為0代表立即抓取有異動的連線,但是會吃很多cpu.#$conf["socketSelectTimeountSec"]=0;#$conf["socketSelectTimeountUsec"],整數,代表要等候幾微秒才抓取有異動的連線,預設不使用.#$conf["socketSelectTimeountUsec"]=5000;#參考資料:#https://www.jianshu.com/p/097463d08664#備註:#無.*/public static function udpServer(&$conf){#初始化要回傳的結果$result=array();#取得當前執行的函數名稱$result["function"]=__FUNCTION__;#如果沒有參數if(func_num_args()==0){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]="函數".$result["function"]."需要參數";#回傳結果return $result;}#if end#涵式說明:#判斷當前環境為web還是cmd#回傳結果:#$result,"web"或"cmd"if(csInformation::getEnv()==="web"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"][]="函數 ".$result["function"]." 僅能在命令列環境下運行!";#回傳結果return $result;}#if end#取得參數$result["argu"]=$conf;#如果 $conf 不為陣列if(gettype($conf)!="array"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"][]="\$conf變數須為陣列形態";#如果傳入的參數為 nullif($conf==null){#設置執行錯誤訊息$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";}#if end#回傳結果return $result;}#if end#檢查參數#函式說明:#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容。#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$reuslt["error"],執行不正常結束的錯訊息陣列.#$result["function"],當前執行的函式名稱.#$result["argu"],設置給予的參數.#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.#$result["argu"],字串陣列,目前輸入的參數名稱陣列.#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.#$result["notNeedVar"],字串陣列,多餘的參數名稱.#必填寫的參數:#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。$conf["variableCheck::checkArguments"]["varInput"]=&$conf;#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";#可以省略的參數:#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("port");#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("integer");#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.#$conf["canBeEmptyString"]="false";#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.#$conf["canNotBeEmpty"]=array();#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.#$conf["canBeEmpty"]=array();#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("ip","welcomeMsg","socketSelectTimeountUsec");#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("ip","processFuncs","welcomeMsg","socketSelectTimeountSec","socketSelectTimeountUsec");#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","array","string","integer","integer");#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("0.0.0.0",array(),"true",0,null);#$conf["disallowAllSkipableVarIsEmpty"],字串,是否允許每個可省略參數都為空字串,預設為"true"允許,反之為"false".#$conf["disallowAllSkipableVarIsEmpty"]="";#$conf["disallowAllSkipableVarIsEmptyArray"],字串,是否允許每個可省略參數都為空陣列,預設為"true"允許,反之為"false".#$conf["disallowAllSkipableVarIsEmptyArray"]="";#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.#$conf["arrayCountEqualCheck"][]=array();#參考資料來源:#array_keys=>http://php.net/manual/en/function.array-keys.php$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);unset($conf["variableCheck::checkArguments"]);#如果檢查參數失敗if($checkArguments["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$checkArguments;#回傳結果return $result;}#if end#如果檢查參數不通過if($checkArguments["passed"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$checkArguments;#回傳結果return $result;}#if end#Allow the script to hang around waiting for connections.set_time_limit(0);#Turn on implicit output flushing so we see what we're getting as it comes in.ob_implicit_flush();#set listen ip and port$address = $conf["ip"];#set listen port$port = $conf["port"];//如果建立 socket 失敗if (($sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP)) === false) {echo "socket_create() failed: reason: " . socket_strerror(socket_last_error()) . PHP_EOL;}#if end//如果 bind socket 失敗if (socket_bind($sock, $address, $port) === false) {echo "socket_bind() failed: reason: " . socket_strerror(socket_last_error($sock)) . PHP_EOL;}#if end// create a list of all the clients that will be connected to us..// add the listening socket to this list$clients = array("serverSock"=>$sock);#無窮迴圈do {#each resourceforeach($clients as $rk=>$csock){#if not socket resourceif(gettype($csock)==="boolean"){#deleteunset($clients[$rk]);}#if not socket resourceelse if(get_resource_type($csock)!=="Socket"){#deleteunset($clients[$rk]);}}#found server sock$serverSock=false;#each resourceforeach($clients as $rk=>$csock){#if not socket resourceif($rk==="serverSock"){#found server sock$serverSock=true;}}#not found server sockif(!$serverSock){#endexit;}#for socket select$read = $clients;$write = NULL;$except = NULL;#如果未設置 $conf["socketSelectTimeountUsec"]if(!isset($conf["socketSelectTimeountUsec"])){#get interesting socket$num_changed_sockets = socket_select($read, $write, $except, $conf["socketSelectTimeountSec"]);}#if end#反之有設置 $conf["socketSelectTimeountUsec"]else{#get interesting socket$num_changed_sockets = socket_select($read, $write, $except, $conf["socketSelectTimeountSec"], $conf["socketSelectTimeountUsec"]);}#else end#socket_select failedif ($num_changed_sockets === false) {#NOTICE to serverecho "socket_select failed".PHP_EOL;}#if end#At least at one of the sockets something interesting happenedelse if ($num_changed_sockets > 0) {// check if there is a client trying to connectif (in_array($sock, $read)) {#accept the client, and add him to the $clients array$receivedBytes=socket_recvfrom($sock,$data,1024,0,$remote_ip,$remote_port);$key=$remote_ip.":".$remote_port;$clients[$key] = $newsock = $sock;#如果要顯示歡迎訊息if($conf["welcomeMsg"]==="true"){# send the client a welcome messagesocket_sendto($newsock, "Welcome to QBPWCF udpServer".PHP_EOL."There are ".(count($clients) - 1)." client(s) connected to the server".PHP_EOL, 1024, 0, $remote_ip, $remote_port);}#if end#debugecho "client connected:".$key.PHP_EOL;echo "client sended:".$data;echo "all client:".PHP_EOL;var_dump($clients);#針對每個用來處理輸入字串的函式foreach($conf["processFuncs"] as $proFunc){#呼叫函式,參數為輸入的字串data跟client socket, server socket, 每個 socket#https://www.php.net/manual/en/function.call-user-func.php$param=array("data"=>trim($data),"serverSock"=>$sock,"clientKey"=>$key,"allSockArray"=>&$clients);$params=array();$params[]=&$param;$result=call_user_func_array($proFunc,$params);#如果有回傳結果if($result!==NULL){#如果執行出錯if($result["status"]==="false"){#印出結果var_dump($result);}}}#debugecho "last all client:".PHP_EOL;var_dump($clients);# remove the listening socket from the clients-with-data array$key = array_search($sock, $read);unset($read[$key]);}#if end}#something happen end} while (true);#關閉listen的socketsocket_close($sock);}#function tcpServer end/*#函式說明:#針對收到的內容,原封不動地傳回給用戶.#必填參數:#$conf["data"],字串,要處理的內容.$conf["data"]="";#$conf["clientSock"],resource socket.$conf["clientSock"]=;#$conf["serverSock"],resource socket.$conf["serverSock"]=;#$conf["allSockArray"],resource陣列.$conf["allSockArray"]=array();#可省略參數:#無.#參考資料:#無.#備註:#無.*/public function echoService(&$conf){#初始化要回傳的結果$result=array();#取得當前執行的函數名稱$result["function"]=__FUNCTION__;#如果沒有參數if(func_num_args()==0){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]="函數".$result["function"]."需要參數";#回傳結果return $result;}#if end#涵式說明:#判斷當前環境為web還是cmd#回傳結果:#$result,"web"或"cmd"if(csInformation::getEnv()==="web"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"][]="函數 ".$result["function"]." 僅能在命令列環境下運行!";#回傳結果return $result;}#if end#取得參數$result["argu"]=$conf;#如果 $conf 不為陣列if(gettype($conf)!="array"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"][]="\$conf變數須為陣列形態";#如果傳入的參數為 nullif($conf==null){#設置執行錯誤訊息$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";}#if end#回傳結果return $result;}#if end#檢查參數#函式說明:#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容。#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$reuslt["error"],執行不正常結束的錯訊息陣列.#$result["function"],當前執行的函式名稱.#$result["argu"],設置給予的參數.#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.#$result["argu"],字串陣列,目前輸入的參數名稱陣列.#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.#$result["notNeedVar"],字串陣列,多餘的參數名稱.#必填寫的參數:#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。$conf["variableCheck::checkArguments"]["varInput"]=&$conf;#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";#可以省略的參數:#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("data","clientSock","serverSock","allSockArray");#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string","resource","resource","array");#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.#$conf["canBeEmptyString"]="false";#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.#$conf["canNotBeEmpty"]=array();#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.#$conf["canBeEmpty"]=array();#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.#$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("ip");#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");#$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("ip","processFuncs");#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");#$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","array");#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".#$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("0.0.0.0",array());#$conf["disallowAllSkipableVarIsEmpty"],字串,是否允許每個可省略參數都為空字串,預設為"true"允許,反之為"false".#$conf["disallowAllSkipableVarIsEmpty"]="";#$conf["disallowAllSkipableVarIsEmptyArray"],字串,是否允許每個可省略參數都為空陣列,預設為"true"允許,反之為"false".#$conf["disallowAllSkipableVarIsEmptyArray"]="";#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.#$conf["arrayCountEqualCheck"][]=array();#參考資料來源:#array_keys=>http://php.net/manual/en/function.array-keys.php$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);unset($conf["variableCheck::checkArguments"]);#如果檢查參數失敗if($checkArguments["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$checkArguments;#回傳結果return $result;}#if end#如果檢查參數不通過if($checkArguments["passed"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$checkArguments;#回傳結果return $result;}#if end#將內容原封不動還給 client@socket_write($conf["clientSock"], $conf["data"].PHP_EOL);}#function echoService end/*#函式說明:#針對收到的內容,原封不動地傳回給用戶.協定為UDP.#回傳結果:#無.#必填參數:#$conf["data"],字串,要處理的內容.$conf["data"]="";#$conf["clientKey"],resource socket key$conf["clientKey"]=;#$conf["serverSock"],resource socket.$conf["serverSock"]=;#$conf["allSockArray"],resource陣列.$conf["allSockArray"]=array();#可省略參數:#無.#參考資料:#無.#備註:#無.*/public function echoServiceU(&$conf){#初始化要回傳的結果$result=array();#取得當前執行的函數名稱$result["function"]=__FUNCTION__;#如果沒有參數if(func_num_args()==0){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]="函數".$result["function"]."需要參數";#回傳結果return $result;}#if end#涵式說明:#判斷當前環境為web還是cmd#回傳結果:#$result,"web"或"cmd"if(csInformation::getEnv()==="web"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"][]="函數 ".$result["function"]." 僅能在命令列環境下運行!";#回傳結果return $result;}#if end#取得參數$result["argu"]=$conf;#如果 $conf 不為陣列if(gettype($conf)!="array"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"][]="\$conf變數須為陣列形態";#如果傳入的參數為 nullif($conf==null){#設置執行錯誤訊息$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";}#if end#回傳結果return $result;}#if end#檢查參數#函式說明:#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容。#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$reuslt["error"],執行不正常結束的錯訊息陣列.#$result["function"],當前執行的函式名稱.#$result["argu"],設置給予的參數.#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.#$result["argu"],字串陣列,目前輸入的參數名稱陣列.#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.#$result["notNeedVar"],字串陣列,多餘的參數名稱.#必填寫的參數:#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。$conf["variableCheck::checkArguments"]["varInput"]=&$conf;#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";#可以省略的參數:#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("data","clientKey","serverSock","allSockArray");#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string","string","resource","array");#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.#$conf["canBeEmptyString"]="false";#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.#$conf["canNotBeEmpty"]=array();#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.#$conf["canBeEmpty"]=array();#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.#$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("ip");#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");#$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("ip","processFuncs");#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");#$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","array");#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".#$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("0.0.0.0",array());#$conf["disallowAllSkipableVarIsEmpty"],字串,是否允許每個可省略參數都為空字串,預設為"true"允許,反之為"false".#$conf["disallowAllSkipableVarIsEmpty"]="";#$conf["disallowAllSkipableVarIsEmptyArray"],字串,是否允許每個可省略參數都為空陣列,預設為"true"允許,反之為"false".#$conf["disallowAllSkipableVarIsEmptyArray"]="";#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.#$conf["arrayCountEqualCheck"][]=array();#參考資料來源:#array_keys=>http://php.net/manual/en/function.array-keys.php$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);unset($conf["variableCheck::checkArguments"]);#如果檢查參數失敗if($checkArguments["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$checkArguments;#回傳結果return $result;}#if end#如果檢查參數不通過if($checkArguments["passed"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$checkArguments;#回傳結果return $result;}#if end#將內容原封不動還給 client$strArray=explode(":",$conf["clientKey"]);$remote_ip=$strArray[0];$remote_port=$strArray[1];socket_sendto($conf["serverSock"], $conf["data"].PHP_EOL, 1024, 0, $remote_ip, $remote_port);}#function echoServiceU end/*#函式說明:#針對收到的內容,若是"quit"則斷開用戶的連線,若是"shutdown"則關閉Server Listen的socket.#回傳結果:#無.#必填參數:#$conf["data"],字串,要處理的內容.$conf["data"]="";#$conf["clientSock"],resource socket.$conf["clientSock"]=;#$conf["serverSock"],resource socket.$conf["serverSock"]=;#$conf["allSockArray"],resource陣列.$conf["allSockArray"]=array();#可省略參數:#無.#參考資料:#無.#備註:#無.*/public function endService(&$conf){#初始化要回傳的結果$result=array();#取得當前執行的函數名稱$result["function"]=__FUNCTION__;#如果沒有參數if(func_num_args()==0){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]="函數".$result["function"]."需要參數";#回傳結果return $result;}#if end#涵式說明:#判斷當前環境為web還是cmd#回傳結果:#$result,"web"或"cmd"if(csInformation::getEnv()==="web"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"][]="函數 ".$result["function"]." 僅能在命令列環境下運行!";#回傳結果return $result;}#if end#取得參數$result["argu"]=$conf;#如果 $conf 不為陣列if(gettype($conf)!="array"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"][]="\$conf變數須為陣列形態";#如果傳入的參數為 nullif($conf==null){#設置執行錯誤訊息$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";}#if end#回傳結果return $result;}#if end#檢查參數#函式說明:#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容。#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$reuslt["error"],執行不正常結束的錯訊息陣列.#$result["function"],當前執行的函式名稱.#$result["argu"],設置給予的參數.#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.#$result["argu"],字串陣列,目前輸入的參數名稱陣列.#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.#$result["notNeedVar"],字串陣列,多餘的參數名稱.#必填寫的參數:#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。$conf["variableCheck::checkArguments"]["varInput"]=&$conf;#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";#可以省略的參數:#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("data","clientSock","serverSock","allSockArray");#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string","resource","resource","array");#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.#$conf["canBeEmptyString"]="false";#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.#$conf["canNotBeEmpty"]=array();#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.#$conf["canBeEmpty"]=array();#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.#$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("ip");#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");#$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("ip","processFuncs");#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");#$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","array");#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".#$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("0.0.0.0",array());#$conf["disallowAllSkipableVarIsEmpty"],字串,是否允許每個可省略參數都為空字串,預設為"true"允許,反之為"false".#$conf["disallowAllSkipableVarIsEmpty"]="";#$conf["disallowAllSkipableVarIsEmptyArray"],字串,是否允許每個可省略參數都為空陣列,預設為"true"允許,反之為"false".#$conf["disallowAllSkipableVarIsEmptyArray"]="";#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.#$conf["arrayCountEqualCheck"][]=array();#參考資料來源:#array_keys=>http://php.net/manual/en/function.array-keys.php$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);unset($conf["variableCheck::checkArguments"]);#如果檢查參數失敗if($checkArguments["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$checkArguments;#回傳結果return $result;}#if end#如果檢查參數不通過if($checkArguments["passed"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$checkArguments;#回傳結果return $result;}#if end#針對輸入的內容switch($conf["data"]){#如果是 "quit"case "quit":#關閉與用戶之間的連線socket_close($conf["clientSock"]);break;#如果是 "shutdown"case "shutdown":#關閉 Server Listen 的 socksocket_close($conf["serverSock"]);break;default:}#switch end}#function endService end/*#函式說明:#針對收到的內容,若是"quit"則斷開用戶的連線,若是"shutdown"則關閉Server Listen的socket,協定為UDP.#回傳結果:#無.#必填參數:#$conf["data"],字串,要處理的內容.$conf["data"]="";#$conf["clientKey"],resource socket key.$conf["clientKey"]=;#$conf["serverSock"],resource socket.$conf["serverSock"]=;#$conf["allSockArray"],resource陣列.$conf["allSockArray"]=array();#可省略參數:#無.#參考資料:#無.#備註:#無.*/public function endServiceU(&$conf){#初始化要回傳的結果$result=array();#取得當前執行的函數名稱$result["function"]=__FUNCTION__;#如果沒有參數if(func_num_args()==0){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]="函數".$result["function"]."需要參數";#回傳結果return $result;}#if end#涵式說明:#判斷當前環境為web還是cmd#回傳結果:#$result,"web"或"cmd"if(csInformation::getEnv()==="web"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"][]="函數 ".$result["function"]." 僅能在命令列環境下運行!";#回傳結果return $result;}#if end#取得參數$result["argu"]=$conf;#如果 $conf 不為陣列if(gettype($conf)!="array"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"][]="\$conf變數須為陣列形態";#如果傳入的參數為 nullif($conf==null){#設置執行錯誤訊息$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";}#if end#回傳結果return $result;}#if end#檢查參數#函式說明:#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容。#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$reuslt["error"],執行不正常結束的錯訊息陣列.#$result["function"],當前執行的函式名稱.#$result["argu"],設置給予的參數.#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.#$result["argu"],字串陣列,目前輸入的參數名稱陣列.#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.#$result["notNeedVar"],字串陣列,多餘的參數名稱.#必填寫的參數:#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。$conf["variableCheck::checkArguments"]["varInput"]=&$conf;#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";#可以省略的參數:#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("data","clientKey","serverSock","allSockArray");#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string","string","resource","array");#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.#$conf["canBeEmptyString"]="false";#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.#$conf["canNotBeEmpty"]=array();#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.#$conf["canBeEmpty"]=array();#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.#$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("ip");#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");#$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("ip","processFuncs");#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");#$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","array");#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".#$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("0.0.0.0",array());#$conf["disallowAllSkipableVarIsEmpty"],字串,是否允許每個可省略參數都為空字串,預設為"true"允許,反之為"false".#$conf["disallowAllSkipableVarIsEmpty"]="";#$conf["disallowAllSkipableVarIsEmptyArray"],字串,是否允許每個可省略參數都為空陣列,預設為"true"允許,反之為"false".#$conf["disallowAllSkipableVarIsEmptyArray"]="";#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.#$conf["arrayCountEqualCheck"][]=array();#參考資料來源:#array_keys=>http://php.net/manual/en/function.array-keys.php$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);unset($conf["variableCheck::checkArguments"]);#如果檢查參數失敗if($checkArguments["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$checkArguments;#回傳結果return $result;}#if end#如果檢查參數不通過if($checkArguments["passed"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤訊息$result["error"]=$checkArguments;#回傳結果return $result;}#if end#針對輸入的內容switch($conf["data"]){#如果是 "quit"case "quit":#從 $conf["clientKey"] 取得用戶的IP與port$strArray=explode(":",$conf["clientKey"]);$remote_ip=$strArray[0];$remote_port=$strArray[1];#卸除儲存與用戶之間連線的socket變數unset($conf["allSockArray"][$conf["clientKey"]]);break;#如果是 "shutdown"case "shutdown":#關閉 Server Listen 的 socksocket_close($conf["serverSock"]);break;default:}#switch end}#function endServiceU end/*#函式說明:#給予unixDomainSockServer函式的addOnProcessFunc參數用的函式,在背景執行指令.#回傳結果:#$result["status"],執行是否正常,"true"為正常,"false"為不正常.#$result["error"],錯誤訊息陣列.#$result["function"],當前執行的函數名稱.#$result["argu"],使用的參數.#$result["continue"],"true"代表執行到此函式為止;"false"代表允許後面的函式繼續執行.#$result["cache"],要暫存在server端的內容.#必填參數:$conf["request"],json字串,key為"cmd2run"者,代表要執行的指令;key為"params"者,為要傳入的參數,一個元素代表一個參數.#$conf["request"]="";$conf["sock"],resource,用戶socket.#$conf["sock"]=;#可省略參數:#$conf["clientCache"],陣列,讓client使用的cache.#$conf["clientCache"]=array();#參考資料:#無.#備註:#無.*/public static function addOnProcessFuncForUnixDomainSockServerInRunWithAutoAddMemoryDaemon(&$conf=array()){#初始化要回傳的結果$result=array();#取得當前執行的函數名稱$result["function"]=__FUNCTION__;#取得參數$result["argu"]=$conf;#允許後面的函式繼續執行$result["continue"]="true";#如果 $conf 不為陣列if(gettype($conf)!="array"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"][]="\$conf變數須為陣列形態";#如果傳入的參數為 nullif(is_null($conf)){#設置執行錯誤訊息$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";}#if end#回傳結果return $result;}#if end#函式說明:#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容.#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$result["error"],執行不正常結束的錯訊息陣列.#$result["simpleError"],簡單表示的錯誤訊息.#$result["function"],當前執行的函式名稱.#$result["argu"],設置給予的參數.#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.#$result["argu"],字串陣列,目前輸入的參數名稱陣列.#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.#$result["notNeedVar"],字串陣列,多餘的參數名稱.#必填參數:#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。$conf["variableCheck::checkArguments"]["varInput"]=&$conf;#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";#可省略參數:#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("request","socket");#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string","resource");#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.#$conf["canBeEmptyString"]="false";#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.#$conf["canNotBeEmpty"]=array();#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.#$conf["canBeEmpty"]=array();#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.#$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("last_req_time","info");#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("last_req_time","info","clientCache");#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","array","array");#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".#$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array($phpMaxMemInConfig,"10",null);#$conf["disallowAllSkipableVarIsEmpty"],字串,是否允許每個可省略參數都為空字串,預設為"true"允許,反之為"false".#$conf["disallowAllSkipableVarIsEmpty"]="";#$conf["disallowAllSkipableVarIsEmptyArray"],字串,是否允許每個可省略參數都為空陣列,預設為"true"允許,反之為"false".#$conf["disallowAllSkipableVarIsEmptyArray"]="";#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.#$conf["arrayCountEqualCheck"][]=array();#參考資料:#array_keys=>http://php.net/manual/en/function.array-keys.php#備註:#無.$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);unset($conf["variableCheck::checkArguments"]);#debug#var_dump(__LINE__,$checkArguments);#如果執行失敗if($checkArguments["status"]==="false"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]=$checkArguments;#回傳結果return $result;}#if end#如果檢查不通過if($checkArguments["passed"]==="false"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]=$checkArguments;#回傳結果return $result;}#if end#將需求變成陣列$request=(array)json_decode($conf["request"]);#函式說明:#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容.#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$result["error"],執行不正常結束的錯訊息陣列.#$result["simpleError"],簡單表示的錯誤訊息.#$result["function"],當前執行的函式名稱.#$result["argu"],設置給予的參數.#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.#$result["argu"],字串陣列,目前輸入的參數名稱陣列.#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.#$result["notNeedVar"],字串陣列,多餘的參數名稱.#必填參數:#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。$conf["variableCheck::checkArguments"]["varInput"]=&$request;#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";#可省略參數:#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("cmd2run");#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string");#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.#$conf["variableCheck::checkArguments"]["canBeEmptyString"]="true";#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.#$conf["variableCheck::checkArguments"]["canNotBeEmpty"]=array("cmd");#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.#$conf["canBeEmpty"]=array();#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.#$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("params");#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("id","params");#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","array");#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".#$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array($phpMaxMemInConfig,"10",null);#$conf["disallowAllSkipableVarIsEmpty"],字串,是否允許每個可省略參數都為空字串,預設為"true"允許,反之為"false".#$conf["disallowAllSkipableVarIsEmpty"]="";#$conf["disallowAllSkipableVarIsEmptyArray"],字串,是否允許每個可省略參數都為空陣列,預設為"true"允許,反之為"false".#$conf["disallowAllSkipableVarIsEmptyArray"]="";#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.#$conf["arrayCountEqualCheck"][]=array();#參考資料:#array_keys=>http://php.net/manual/en/function.array-keys.php#備註:#無.$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);unset($conf["variableCheck::checkArguments"]);#debug#var_dump(__LINE__,$checkArguments);#如果執行失敗if($checkArguments["status"]==="false"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]=$checkArguments;#回傳結果return $result;}#if end#如果檢查不通過if($checkArguments["passed"]==="false"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]=$checkArguments;#回傳結果return $result;}#if end#函式說明:#呼叫shell執行系統命令,並取得回傳的內容.#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$result["error"],錯誤訊息陣列.#$result["function"],當前執行的函數名稱.#$result["argu"],使用的參數.#$result["cmd"],執行的指令內容.#$result["fullCmd"],如果參數 $conf["inBackGround"] 為 "true" 則會回傳該值.#$result["output"],爲執行完二元碼後的輸出陣列,若 $conf["inBackGround"] 為 "true",則為當下的輸出.#$result["tmpFileOutput"],儲存輸出的暫存檔案名稱,若 $conf["inBackGround"] 為 "true" 則會回傳該值.#$result["running"],是否還在執行.#$result["pid"],pid.#$result["statusCode"],執行結束後的代碼.#$result["escape"],陣列,儲存重新排序過且已經escape過的指令(key為"cmd")與參數(key為"argu")與兩者組合的一維陣列(key為"array").#必填參數:#$conf["command"],字串,要執行的指令.$conf["external::callShell"]["command"]=$request["cmd2run"];#$conf["fileArgu"],字串,變數__FILE__的內容.$conf["external::callShell"]["fileArgu"]=__FILE__;#可省略參數:#$conf["argu"],陣列字串,指令搭配的參數,預設為空陣列.$conf["external::callShell"]["argu"]=$request["params"];#$conf["arguIsAddr"],陣列字串,指令搭配的哪些參數為路徑,為路徑的參數會進行轉換以便符合呼叫當前函數的位置,預設不指定,若有3個參數,其中第3個參數為路徑,則表示為array("false","false","true").#$conf["arguIsAddr"]=array();#$conf["pre"],陣列,要在本指令前執行的每個指令與參數.#$conf["pre"][$i]["cmd"],字串,要在本指令前執行的第$i+1個指令.#$conf["pre"][$i]["param"],陣列字串,要在本指令前執行的第$i+1個指令的參數.#$conf["enablePrintDescription"],字串,是否要印出$conf["printDescription"]的內容,"true"代表要,"false"代表不要,預設為"false".#$conf["enablePrintDescription"]="true";#$conf["printDescription"],字串,執行該外部程式前要印出來的的文字,預設為$conf["command"]的內容加上使用的$conf["argu"]參數.#$conf["printDescription"]="";#$conf["escapeshellarg"],字串,是否要啟用過濾參數,用了比較安全,但可能會出錯,"true"為啟用,"false"為不啟用,預設為"false".如果參數為"< 、<< 、> 、>> 、| 、2>&1"之一則不會過濾.$conf["external::callShell"]["escapeshellarg"]="true";#$conf["thereIsShellVar"],陣列字串,指令搭配的參數"argu",若含有「\'」,則取代為「"」.每個argu參數都要有對應的元素."true"代表要置換.#$conf["thereIsShellVar"]=array();#$conf["username"],字串,要用什麼使用者來執行,預設為執行php的使用者,該參數不適用於apache環境.#$conf["username"]="";#$conf["password"],字串,root的使用者密碼,預設不使用密碼,該參數不適用於apache環境.#$conf["password"]="";#$conf["useScript"],字串,是否要啟用Linux的script指令來記錄輸出,"true"代表要,Fedora的selinux會擋住該操作;"false"代表不要,預設為"false".#$conf["useScript"]="";#$conf["logFilePath"],字串,當 $conf["useScript"] 為 "true" 時,輸出的內容要暫存到哪裡,預設為 "/tmp/.qbpwcf_tmp/external/callShell/".#$conf["logFilePath"]=".qbpwcf_tmp/external/callShell/";#$conf["inBackGround"],字串,是否要在背景執行,且不會等待程式執行結束再執行下一個指令,"true"代表是,"false"代表不要,預設為"false",如果$conf["command"]有用「;」區隔的多個指令將會出錯.#$conf["inBackGround"]="";#$conf["getErr"],字串,"true"代表將錯誤輸出變成標準輸出,反之"false"為不變動.#$conf["getErr"]="false";#$conf["doNotRun"],字串,"true"代表不執行指令,預設為"false"會執行指令.$conf["external::callShell"]["doNotRun"]="true";#參考資料:#exec=>http://php.net/manual/en/function.exec.php#escapeshellcmd=>http://php.net/manual/en/function.escapeshellcmd.php#escapeshellarg=>http://php.net/manual/en/function.escapeshellarg.php#備註:#不是所有指令都能用apache的身份執行,目前已知java,javac指令無法執行,使用root身份可能會被selinux阻擋.#若使用的 command、argu 參數,含有 ~ 則會被視為字串,若有需要其於 shell 中代表的家目錄位置,可用 fileAccess::tildeToPath 來進行轉換.$callShell=external::callShell($conf["external::callShell"]);unset($conf["external::callShell"]);#如果執行失敗if($callShell["status"]==="false"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]=$callShell;#回傳結果return $result;}#if end#函式說明:#將一維陣列轉換為用特定符號間隔的字串,ex:array("1","2","3") to "a;b;c;".#回傳的結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$result["function"],當前執行的function名稱#$result["error"],錯誤訊息陣列.#$result["content"],處理好的字串.#$result["argu"],使用的參數.#必填參數:#$conf["inputArray"],字串陣列,要轉成字串的一維陣列.$conf["arrays::arrayToString"]["inputArray"]=$callShell["escape"]["array"];#可省略參數:#$conf["spiltSymbol"],字串,用來區隔字串的符號,預設為;$conf["arrays::arrayToString"]["spiltSymbol"]=" ";#$conf["skipEnd"],字串,結尾是否不要加上符號,預設為"false",要加上符號,"true"代表不要加上符號。$conf["arrays::arrayToString"]["skipEnd"]="true";#參考資料:#無.#備註:#無.$arrayToString=arrays::arrayToString($conf["arrays::arrayToString"]);unset($conf["arrays::arrayToString"]);#如果執行失敗if($arrayToString["status"]==="false"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]=$arrayToString;#回傳結果return $result;}#if end#函式說明:#透過proc來多執行序運作.#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$reuslt["error"],執行不正常結束的錯訊息陣列.#$result["function"],當前執行的函式名稱.#$result["argu"],使用的參數.#$result["content"],陣列,每個元素為其指令執行的結果訊息陣列,key為"status"代表執行是否正常的識別;key為"statusCode"代表程式結束後回傳給對應executeBy程式的數值;key為"output"代表標準輸出,若為resource,則代表為pipe;key為"error"代表非標準輸出,若為resource,則代表為pipe;key為"input"代表成功輸入的指令;key為"process"代表該程序經proc_open後的process source;key為"proc_get_status"代表程序的資訊.#必填參數:#$conf["cmds"],字串陣列,每個元素代表要執行的指令與參數.$conf["threads::proc"]["cmds"]=array($arrayToString["content"]);#可省略參數:#$conf["wait"],字串,是否需要等待所有程序結束,預設為"true"要等待;反之為"false"不要等待.#$conf["threads::proc"]["wait"]="false";#$conf["workingDir"],字串陣列,個別程式執行時的家目錄,預設不指定.#$conf["workingDir"]=array("path");#$conf["envs"],2維字串陣列,每個元素代表個別程式執行時的指定環境變數,key變數名稱;value為變數內容.預設為array("QBPWCF" => "Quick Build PHP Website Componment base on Fedora Linux");#$conf["envs"]=array(array("key"=>"value"));#$conf["executeBy"],字串陣列,每個元素代表個別指令要用什麼程式執行,預設為"bash".#$conf["executeBy"]=array("bash");#參考資料:#https://www.php.net/manual/en/function.proc-open.php#https://www.php.net/manual/en/function.proc-get-status.php#備註:#無.$proc=threads::proc($conf["threads::proc"]);unset($conf["threads::proc"]);/* debug#函式說明:#撰寫log#回傳結果:#$result["status"],狀態,"true"或"false".#$result["error"],錯誤訊息陣列.#$result["function"],當前函式的名稱.#$result["argu"],使用的參數.#$result["content"],要寫入log的內容字串.#必填參數:#$conf["path"],字串,log檔案的路徑與名稱.$conf["logs::record"]["path"]=$conf["socket"]."(sock::addOnProcessFuncForUnixDomainSockServerInRunWithAutoAddMemoryDaemon).log";#$conf["content"],any,要寫的內容,若內容不為字串則會用var_dump的格式寫入.$conf["logs::record"]["content"]=$proc;#$conf["fileArgu"],字串,php變數__FILE__的內容,亦即該檔案在檔案系統的絕對路徑$conf["logs::record"]["fileArgu"]=__FILE__;#可省略參數:#$conf["rewrite"],預設為"false",接續寫入;反之"true"代表重新寫入.#$conf["rewrite"]="false";#$conf["returnOnly"],預設為"false",會寫入到log檔案.若為"true"則不會寫入log.#$conf["returnOnly"]="true";#參考資料:#無.#備註:#無.$record=logs::record($conf["logs::record"]);unset($conf["logs::record"]);#如果執行失敗if($record["status"]==="false"){#設置執行錯誤識別$result["status"]="false";#設置執行錯誤$result["error"]=$record;#回傳結果return $result;}#if end*/#設置要暫存在server端的內容$result["cache"]=&$proc;#如果執行失敗if($proc["status"]==="false"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]=$proc;#回傳結果return $result;}#if end#設置執行正常$result["status"]="true";#後面的程式不要執行$result["continue"]="false";#回傳結果return $result;}#function addOnProcessFuncForUnixDomainSockServerInRunWithAutoAddMemoryDaemon end/*#函式說明:#執行程式時,依照需要增加記憶體的上限.#回傳結果:#$result["status"],執行是否正常,"true"為正常,"false"為不正常.#$result["error"],錯誤訊息陣列.#$result["function"],當前執行的函數名稱.#$result["argu"],使用的參數.#$result["content"],程式執行後的結果(unix domain socket server的輸出).#必填參數:#$conf["cmd"],字串參數,要執行的指令.$conf["cmd"]="";#可省略參數:#$conf["params"],陣列字串參數,每個元素代表依序哦昂使用的參數.#$conf["params"]=array("");#$conf["fileArgu"],字串,__FILE__的內容.#$conf["fileArgu"]="";#參考資料:#https://www.php.net/manual/en/function.memory-get-usage.php#https://www.php.net/manual/en/ini.core.php#ini.memory-limit#https://www.php.net/manual/en/function.stream-get-meta-data.php#備註:#無.*/public static function runWithAutoAddMemoryDaemon(&$conf=array()){#初始化要回傳的結果$result=array();#取得當前執行的函數名稱$result["function"]=__FUNCTION__;#取得參數$result["argu"]=$conf;#如果 $conf 不為陣列if(gettype($conf)!="array"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"][]="\$conf變數須為陣列形態";#如果傳入的參數為 nullif(is_null($conf)){#設置執行錯誤訊息$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";}#if end#回傳結果return $result;}#if end#檢查參數#函式說明:#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容.#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$result["error"],執行不正常結束的錯訊息陣列.#$result["simpleError"],簡單表示的錯誤訊息.#$result["function"],當前執行的函式名稱.#$result["argu"],設置給予的參數.#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.#$result["argu"],字串陣列,目前輸入的參數名稱陣列.#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.#$result["notNeedVar"],字串陣列,多餘的參數名稱.#必填參數:#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。$conf["variableCheck::checkArguments"]["varInput"]=&$conf;#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";#可省略參數:#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("cmd");#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string");#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.$conf["variableCheck::checkArguments"]["canBeEmptyString"]="false";#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.#$conf["canNotBeEmpty"]=array();#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.#$conf["canBeEmpty"]=array();#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("params","fileArgu");#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("params","fileArgu");#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("array","string");#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array(null,__FILE__);#$conf["disallowAllSkipableVarIsEmpty"],字串,是否允許每個可省略參數都為空字串,預設為"true"允許,反之為"false".#$conf["disallowAllSkipableVarIsEmpty"]="";#$conf["disallowAllSkipableVarIsEmptyArray"],字串,是否允許每個可省略參數都為空陣列,預設為"true"允許,反之為"false".#$conf["disallowAllSkipableVarIsEmptyArray"]="";#$conf["disallowAllSkipableVarNotExist"],字串,是否不允許每個可省略參數都不存在,預設為"false"代表允許,反之為"true".#$conf["disallowAllSkipableVarNotExist"]="";#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.#$conf["arrayCountEqualCheck"][]=array();#參考資料:#array_keys=>http://php.net/manual/en/function.array-keys.php#備註:#無.$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);unset($conf["variableCheck::checkArguments"]);#如果執行失敗if($checkArguments["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤資訊$result["error"]=$checkArguments;#回傳結果return $result;}#if end#如果檢查不通過if($checkArguments["passed"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤資訊$result["error"]=$checkArguments;#回傳結果return $result;}#if end/*#函式說明:#於 ./tmp 底下建立暫存目錄與回傳暫存檔案名稱路徑#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$result["error"],錯誤訊息.#$result["function"],當前執行的函數名稱.#$result["content"],暫存檔案的路徑與名稱.#必填參數:#無.#可省略參數:#無.#參考資料:#無.#備註:#無.*/$conf["fileAccess::createTempFile"]=array();$createTempFile=fileAccess::createTempFile($conf["fileAccess::createTempFile"]);unset($conf["fileAccess::createTempFile"]);#如果執行失敗if($createTempFile["status"]==="false"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]=$createTempFile;#回傳結果return $result;}#if end#取得暫存的 unix domain socket 檔案$tmpUnixDomainSock=$createTempFile["content"];#初始化用來運行 unixDomainSockServer.php 的參數$argu=array();#設置參數$argu[]="--sock";#設置參數$argu[]=$tmpUnixDomainSock;#設置參數$argu[]="--addOnProcessFunc";#設置參數$argu[]="\qbpwcf\sock::addOnProcessFuncForUnixDomainSockServerInRunWithAutoAddMemoryDaemon";#設置參數$argu[]="--funcToRunWhenIdle";#設置參數$argu[]="\qbpwcf\config::autoAddMemory";#設置參數$argu[]="--onlyOutputCache";#設置參數$argu[]="true";#設置參數$argu[]="--cacheLayer";#設置參數$argu[]="serverCache";#設置參數$argu[]="--cacheLayer";#設置參數$argu[]="serverSide";#設置參數$argu[]="--cacheLayer";#設置參數$argu[]="funcToRunWhenIdle";#設置參數$argu[]="--cacheLayer";#設置參數$argu[]="\qbpwcf\config::autoAddMemory";#設置參數$argu[]="--cacheLayer";#設置參數$argu[]="cache";#設置參數$argu[]="--cacheLayer";#設置參數$argu[]="stdout";#函式說明:#呼叫shell執行系統命令,並取得回傳的內容.#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$result["error"],錯誤訊息陣列.#$result["function"],當前執行的函數名稱.#$result["argu"],使用的參數.#$result["cmd"],執行的指令內容.#$result["fullCmd"],如果參數 $conf["inBackGround"] 為 "true" 則會回傳該值.#$result["output"],爲執行完二元碼後的輸出陣列,若 $conf["inBackGround"] 為 "true",則為當下的輸出.#$result["tmpFileOutput"],儲存輸出的暫存檔案名稱,若 $conf["inBackGround"] 為 "true" 則會回傳該值.#$result["running"],是否還在執行.#$result["pid"],pid.#$result["statusCode"],執行結束後的代碼.#$result["escape"],陣列,儲存重新排序過且已經escape過的指令(key為"cmd")與參數(key為"argu")與兩者組合的一維陣列(key為"array").#必填參數:#$conf["command"],字串,要執行的指令.$conf["external::callShell"]["command"]="unixDomainSockServer.php";#$conf["fileArgu"],字串,變數__FILE__的內容.$conf["external::callShell"]["fileArgu"]=$conf["fileArgu"];#可省略參數:#$conf["argu"],陣列字串,指令搭配的參數,預設為空陣列.$conf["external::callShell"]["argu"]=$argu;#$conf["arguIsAddr"],陣列字串,指令搭配的哪些參數為路徑,為路徑的參數會進行轉換以便符合呼叫當前函數的位置,預設不指定,若有3個參數,其中第3個參數為路徑,則表示為array("false","false","true").#$conf["arguIsAddr"]=array();#$conf["pre"],陣列,要在本指令前執行的每個指令與參數.#$conf["pre"][$i]["cmd"],字串,要在本指令前執行的第$i+1個指令.#$conf["pre"][$i]["param"],陣列字串,要在本指令前執行的第$i+1個指令的參數.#$conf["enablePrintDescription"],字串,是否要印出$conf["printDescription"]的內容,"true"代表要,"false"代表不要,預設為"false".#$conf["enablePrintDescription"]="true";#$conf["printDescription"],字串,執行該外部程式前要印出來的的文字,預設為$conf["command"]的內容加上使用的$conf["argu"]參數.#$conf["printDescription"]="";#$conf["escapeshellarg"],字串,是否要啟用過濾參數,用了比較安全,但可能會出錯,"true"為啟用,"false"為不啟用,預設為"false".如果參數為"< 、<< 、> 、>> 、| 、2>&1"之一則不會過濾.$conf["external::callShell"]["escapeshellarg"]="true";#$conf["thereIsShellVar"],陣列字串,指令搭配的參數"argu",若含有「\'」,則取代為「"」.每個argu參數都要有對應的元素."true"代表要置換.#$conf["thereIsShellVar"]=array();#$conf["username"],字串,要用什麼使用者來執行,預設為執行php的使用者,該參數不適用於apache環境.#$conf["username"]="";#$conf["password"],字串,root的使用者密碼,預設不使用密碼,該參數不適用於apache環境.#$conf["password"]="";#$conf["useScript"],字串,是否要啟用Linux的script指令來記錄輸出,"true"代表要,Fedora的selinux會擋住該操作;"false"代表不要,預設為"false".#$conf["useScript"]="";#$conf["logFilePath"],字串,當 $conf["useScript"] 為 "true" 時,輸出的內容要暫存到哪裡,預設為 "/tmp/.qbpwcf_tmp/external/callShell/".#$conf["logFilePath"]=".qbpwcf_tmp/external/callShell/";#$conf["inBackGround"],字串,是否要在背景執行,且不會等待程式執行結束再執行下一個指令,"true"代表是,"false"代表不要,預設為"false",如果$conf["command"]有用「;」區隔的多個指令將會出錯.#$conf["inBackGround"]="";#$conf["getErr"],字串,"true"代表將錯誤輸出變成標準輸出,反之"false"為不變動.#$conf["getErr"]="false";#$conf["doNotRun"],字串,"true"代表不執行指令,預設為"false"會執行指令.$conf["external::callShell"]["doNotRun"]="true";#參考資料:#exec=>http://php.net/manual/en/function.exec.php#escapeshellcmd=>http://php.net/manual/en/function.escapeshellcmd.php#escapeshellarg=>http://php.net/manual/en/function.escapeshellarg.php#備註:#不是所有指令都能用apache的身份執行,目前已知java,javac指令無法執行,使用root身份可能會被selinux阻擋.#若使用的 command、argu 參數,含有 ~ 則會被視為字串,若有需要其於 shell 中代表的家目錄位置,可用 fileAccess::tildeToPath 來進行轉換.$callShell=external::callShell($conf["external::callShell"]);unset($conf["external::callShell"]);#debug#var_dump(__LINE__,$callShell);exit;#如果執行失敗if($callShell["status"]==="false"){#如果socket存在if(file_exists($tmpUnixDomainSock)){#移除之unlink($tmpUnixDomainSock);}#if end#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]=$callShell;#回傳結果return $result;}#if end#函式說明:#將一維陣列轉換為用特定符號間隔的字串,ex:array("1","2","3") to "a;b;c;".#回傳的結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$result["function"],當前執行的function名稱#$result["error"],錯誤訊息陣列.#$result["content"],處理好的字串.#$result["argu"],使用的參數.#必填參數:#$conf["inputArray"],字串陣列,要轉成字串的一維陣列.$conf["arrays::arrayToString"]["inputArray"]=$callShell["escape"]["array"];#可省略參數:#$conf["spiltSymbol"],字串,用來區隔字串的符號,預設為;$conf["arrays::arrayToString"]["spiltSymbol"]=" ";#$conf["skipEnd"],字串,結尾是否不要加上符號,預設為"false",要加上符號,"true"代表不要加上符號。$conf["arrays::arrayToString"]["skipEnd"]="true";#參考資料:#無.#備註:#無.$arrayToString=arrays::arrayToString($conf["arrays::arrayToString"]);unset($conf["arrays::arrayToString"]);#如果執行失敗if($arrayToString["status"]==="false"){#如果socket存在if(file_exists($tmpUnixDomainSock)){#移除之unlink($tmpUnixDomainSock);}#if end#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]=$arrayToString;#回傳結果return $result;}#if end#函式說明:#透過proc來多執行序運作.#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$reuslt["error"],執行不正常結束的錯訊息陣列.#$result["function"],當前執行的函式名稱.#$result["argu"],使用的參數.#$result["content"],陣列,每個元素為其指令執行的結果訊息陣列,key為"status"代表執行是否正常的識別;key為"statusCode"代表程式結束後回傳給對應executeBy程式的數值;key為"output"代表標準輸出,若為resource,則代表為pipe;key為"error"代表非標準輸出,若為resource,則代表為pipe;key為"input"代表成功輸入的指令;key為"process"代表該程序經proc_open後的process source;key為"proc_get_status"代表程序的資訊.#必填參數:#$conf["cmds"],字串陣列,每個元素代表要執行的指令與參數.$conf["threads::proc"]["cmds"]=array($arrayToString["content"]);#可省略參數:#$conf["wait"],字串,是否需要等待所有程序結束,預設為"true"要等待;反之為"false"不要等待.$conf["threads::proc"]["wait"]="false";#$conf["workingDir"],字串陣列,個別程式執行時的家目錄,預設不指定.#$conf["workingDir"]=array("path");#$conf["envs"],2維字串陣列,每個元素代表個別程式執行時的指定環境變數,key變數名稱;value為變數內容.預設為array("QBPWCF" => "Quick Build PHP Website Componment base on Fedora Linux");#$conf["envs"]=array(array("key"=>"value"));#$conf["executeBy"],字串陣列,每個元素代表個別指令要用什麼程式執行,預設為"bash".#$conf["executeBy"]=array("bash");#參考資料:#https://www.php.net/manual/en/function.proc-open.php#https://www.php.net/manual/en/function.proc-get-status.php#備註:#無.$procForUnixDoaminSocket=threads::proc($conf["threads::proc"]);unset($conf["threads::proc"]);#如果執行失敗if($procForUnixDoaminSocket["status"]==="false"){#如果socket存在if(file_exists($tmpUnixDomainSock)){#移除之unlink($tmpUnixDomainSock);}#if end#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]=$procForUnixDoaminSocket;#回傳結果return $result;}#if end#var_dump($procForUnixDoaminSocket);exit;#如果 unix doamin socket server 沒有在運行if($procForUnixDoaminSocket["content"][0]["proc_get_status"]["running"]===false){#如果socket存在if(file_exists($tmpUnixDomainSock)){#移除之unlink($tmpUnixDomainSock);}#if end#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]=$procForUnixDoaminSocket;#回傳結果return $result;}#if end#如果當下 unix doamin socket server 沒有在運行if(proc_get_status($procForUnixDoaminSocket["content"][0]["process"])["running"]===false){#如果socket存在if(file_exists($tmpUnixDomainSock)){#移除之unlink($tmpUnixDomainSock);}#if end#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]=$procForUnixDoaminSocket;#回傳結果return $result;}#if end#debug#var_dump(__LINE__,"before send msg");#初始化要求執行程式的訊息$msg=array();#設置執行的指令$msg["cmd2run"]=$conf["cmd"];#如果有參數if(isset($conf["params"])){#設置參數$msg["params"]=$conf["params"];}#if end#初始化儲存等待了幾秒$waitSec=0;#無窮迴圈while(true){#函式說明:#連線到 unixDomainSockServer 提供的 unix domain socket.#回傳結果:#$result["status"],"true"代表執行正常;"false"代表執行不正常.#$result["error"],錯誤訊息陣列.#$result["function"],當前執行的函式名稱.#$result["content"],取得的回應.#必填參數:#$conf["sock"],字串,要連線的unix domain socket.$conf["sock::unixDomainSockClient"]["sock"]=$tmpUnixDomainSock;#可省略參數:#$conf["id"],字串,取得的id,若無此值,則會得到新的數值.#$conf["id"]="";#$conf["cmd"],字串,要執行的指令,當$conf["id"]參數合法時,才會執行.#$conf["sock::unixDomainSockClient"]["cmd"]=$callShell["escape"]["cmd"];#$conf["param"],參數陣列.#$conf["sock::unixDomainSockClient"]["param"]=$callShell["escape"]["argu"];#$conf["escaped"],字串,param參數是否已經escaped了,預設為"false",反之為"true".#$conf["sock::unixDomainSockClient"]["escaped"]="true";#$conf["custom"],陣列,要客制化傳輸的內容,會覆蓋以上除了$conf["id"]以外的可省略參數.#$conf["custom"]=array();#參考資料:#http://php.net/manual/en/function.stream-socket-client.php#http://php.net/manual/en/function.stream-get-contents.php#備註:#無.$paramsOfUnixDomainSockClient=$conf["sock::unixDomainSockClient"];$unixDomainSockClient=sock::unixDomainSockClient($paramsOfUnixDomainSockClient);unset($paramsOfUnixDomainSockClient);#如果執行成功if($unixDomainSockClient["status"]==="true"){#debug#var_dump(__LINE__,"before parse id");#跳出whilebreak;}#if end#提示錯誤else{#debug#var_dump(__LINE__,$unixDomainSockClient);}#else end#如果當下 unix doamin socket server 沒有在運行if(proc_get_status($procForUnixDoaminSocket["content"][0]["process"])["running"]===false){#如果socket存在if(file_exists($tmpUnixDomainSock)){#移除之unlink($tmpUnixDomainSock);}#if end#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"][]="client取得回應前server就意外結束了";#設置執行錯誤訊息$result["error"][]=$procForUnixDoaminSocket;#回傳結果return $result;}#if end#等後1秒,擔心unix domain socket server 尚未跑起來.sleep(1);#已等待時間加1秒$waitSec=$waitSec+1;}#while end#debug#var_dump(__LINE__,"json string got:".$unixDomainSockClient["content"]);#取得json回應$jsonRes=json_decode($unixDomainSockClient["content"]);#如果執行失敗if($jsonRes===null){#如果socket存在if(file_exists($tmpUnixDomainSock)){#移除之unlink($tmpUnixDomainSock);}#if end#設置執行錯誤識別$result["status"]="false";#設置錯誤訊息$result["error"]=$unixDomainSockClient;#回傳結果return $result;}#if end#如果沒有產生新idif(!isset($jsonRes->id)){#如果socket存在if(file_exists($tmpUnixDomainSock)){#移除之unlink($tmpUnixDomainSock);}#if end#設置執行錯誤識別$result["status"]="false";#設置錯誤訊息$result["error"]=$unixDomainSockClient;#回傳結果return $result;}#if end#debug#var_dump(__LINE__,"got id:".$jsonRes->id);#debug#while(true){};#用新的id再傳送一次要求給 qbpwcf_usock_path$paramsOfUnixDomainSockClient=array();$paramsOfUnixDomainSockClient["sock"]=$tmpUnixDomainSock;$paramsOfUnixDomainSockClient["id"]=$jsonRes->id;$paramsOfUnixDomainSockClient["custom"]=$msg;$unixDomainSockClient=sock::unixDomainSockClient($paramsOfUnixDomainSockClient);unset($paramsOfUnixDomainSockClient);#debug#var_dump(__LINE__,$unixDomainSockClient);#如果執行失敗if($unixDomainSockClient["status"]==="false"){#如果socket存在if(file_exists($tmpUnixDomainSock)){#移除之unlink($tmpUnixDomainSock);}#if end#設置執行錯誤識別$result["status"]="false";#設置錯誤訊息$result["error"]=$unixDomainSockClient;#回傳結果return $result;}#if end#debug#var_dump(__LINE__,$unixDomainSockClient);#如果有回應的內容if(!empty($unixDomainSockClient["content"])){#取得json回應$jsonRes=(array)json_decode($unixDomainSockClient["content"]);#如果執行失敗if($jsonRes===null){#如果socket存在if(file_exists($tmpUnixDomainSock)){#移除之unlink($tmpUnixDomainSock);}#if end#設置執行錯誤識別$result["status"]="false";#設置錯誤訊息$result["error"]=$unixDomainSockClient;#回傳結果return $result;}#if end#如果執行指令失敗if($jsonRes["status"]==="false"){#如果socket存在if(file_exists($tmpUnixDomainSock)){#移除之unlink($tmpUnixDomainSock);}#if end#設置執行錯誤識別$result["status"]="false";#設置錯誤訊息$result["error"]=$jsonRes["error"];#回傳結果return $result;}#if end#印出client收到的結果#var_dump($jsonRes);}#if end#debug#var_dump(__LINE__,$procForUnixDoaminSocket);#初始化儲存標準輸出$result["content"]["stdout"]="";#初始化儲存非標準輸出$result["content"]["stderr"]="";#等待 unixDomainSockServer 結束執行while(true){#取得程序狀態$proc_get_status=proc_get_status($procForUnixDoaminSocket["content"][0]["process"]);/* debug#函式說明:#撰寫log#回傳結果:#$result["status"],狀態,"true"或"false".#$result["error"],錯誤訊息陣列.#$result["function"],當前函式的名稱.#$result["argu"],使用的參數.#$result["content"],要寫入log的內容字串.#必填參數:#$conf["path"],字串,log檔案的路徑與名稱.$conf["logs::record"]["path"]="/tmp/sock::runWithAutoAddMemoryDaemon.log";#$conf["content"],any,要寫的內容,若內容不為字串則會用var_dump的格式寫入.$conf["logs::record"]["content"]=$proc_get_status;#$conf["fileArgu"],字串,php變數__FILE__的內容,亦即該檔案在檔案系統的絕對路徑$conf["logs::record"]["fileArgu"]=__FILE__;#可省略參數:#$conf["rewrite"],預設為"false",接續寫入;反之"true"代表重新寫入.#$conf["rewrite"]="false";#$conf["returnOnly"],預設為"false",會寫入到log檔案.若為"true"則不會寫入log.#$conf["returnOnly"]="true";#參考資料:#無.#備註:#無.$record=logs::record($conf["logs::record"]);unset($conf["logs::record"]);#如果執行失敗if($record["status"]==="false"){#設置執行錯誤識別$result["status"]="false";#設置執行錯誤$result["error"]=$record;#回傳結果return $result;}#if end*/#確認process是否存在#ps auxwf | grep sshd | grep -v 'grep' | wc -l#函式說明:#呼叫shell執行系統命令,並取得回傳的內容.#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$result["error"],錯誤訊息陣列.#$result["function"],當前執行的函數名稱.#$result["argu"],使用的參數.#$result["cmd"],執行的指令內容.#$result["fullCmd"],如果參數 $conf["inBackGround"] 為 "true" 則會回傳該值.#$result["output"],爲執行完二元碼後的輸出陣列,若 $conf["inBackGround"] 為 "true",則為當下的輸出.#$result["tmpFileOutput"],儲存輸出的暫存檔案名稱,若 $conf["inBackGround"] 為 "true" 則會回傳該值.#$result["running"],是否還在執行.#$result["pid"],pid.#$result["statusCode"],執行結束後的代碼.#$result["escape"],陣列,儲存重新排序過且已經escape過的指令(key為"cmd")與參數(key為"argu")與兩者組合的一維陣列(key為"array").#必填參數:#$conf["command"],字串,要執行的指令.$conf["external::callShell"]["command"]="ps";#$conf["fileArgu"],字串,變數__FILE__的內容.$conf["external::callShell"]["fileArgu"]=$conf["fileArgu"];#可省略參數:#$conf["argu"],陣列字串,指令搭配的參數,預設為空陣列.$conf["external::callShell"]["argu"]=array("auxwf","|","grep",$proc_get_status["pid"],"|","grep","-v","'grep'","|","wc","-l");#$conf["arguIsAddr"],陣列字串,指令搭配的哪些參數為路徑,為路徑的參數會進行轉換以便符合呼叫當前函數的位置,預設不指定,若有3個參數,其中第3個參數為路徑,則表示為array("false","false","true").#$conf["arguIsAddr"]=array();#$conf["pre"],陣列,要在本指令前執行的每個指令與參數.#$conf["pre"][$i]["cmd"],字串,要在本指令前執行的第$i+1個指令.#$conf["pre"][$i]["param"],陣列字串,要在本指令前執行的第$i+1個指令的參數.#$conf["enablePrintDescription"],字串,是否要印出$conf["printDescription"]的內容,"true"代表要,"false"代表不要,預設為"false".#$conf["enablePrintDescription"]="true";#$conf["printDescription"],字串,執行該外部程式前要印出來的的文字,預設為$conf["command"]的內容加上使用的$conf["argu"]參數.#$conf["printDescription"]="";#$conf["escapeshellarg"],字串,是否要啟用過濾參數,用了比較安全,但可能會出錯,"true"為啟用,"false"為不啟用,預設為"false".如果參數為"< 、<< 、> 、>> 、| 、2>&1"之一則不會過濾.#$conf["escapeshellarg"]="false";#$conf["thereIsShellVar"],陣列字串,指令搭配的參數"argu",若含有「\'」,則取代為「"」.每個argu參數都要有對應的元素."true"代表要置換.#$conf["thereIsShellVar"]=array();#$conf["username"],字串,要用什麼使用者來執行,預設為執行php的使用者,該參數不適用於apache環境.#$conf["username"]="";#$conf["password"],字串,root的使用者密碼,預設不使用密碼,該參數不適用於apache環境.#$conf["password"]="";#$conf["useScript"],字串,是否要啟用Linux的script指令來記錄輸出,"true"代表要,Fedora的selinux會擋住該操作;"false"代表不要,預設為"false".#$conf["useScript"]="";#$conf["logFilePath"],字串,當 $conf["useScript"] 為 "true" 時,輸出的內容要暫存到哪裡,預設為 "/tmp/.qbpwcf_tmp/external/callShell/".#$conf["logFilePath"]=".qbpwcf_tmp/external/callShell/";#$conf["inBackGround"],字串,是否要在背景執行,且不會等待程式執行結束再執行下一個指令,"true"代表是,"false"代表不要,預設為"false",如果$conf["command"]有用「;」區隔的多個指令將會出錯.#$conf["inBackGround"]="";#$conf["getErr"],字串,"true"代表將錯誤輸出變成標準輸出,反之"false"為不變動.#$conf["getErr"]="false";#$conf["doNotRun"],字串,"true"代表不執行指令,預設為"false"會執行指令.#$conf["doNotRun"]="false";#參考資料:#exec=>http://php.net/manual/en/function.exec.php#escapeshellcmd=>http://php.net/manual/en/function.escapeshellcmd.php#escapeshellarg=>http://php.net/manual/en/function.escapeshellarg.php#備註:#不是所有指令都能用apache的身份執行,目前已知java,javac指令無法執行,使用root身份可能會被selinux阻擋.#若使用的 command、argu 參數,含有 ~ 則會被視為字串,若有需要其於 shell 中代表的家目錄位置,可用 fileAccess::tildeToPath 來進行轉換.$callShell=external::callShell($conf["external::callShell"]);unset($conf["external::callShell"]);#如果執行失敗if($callShell["status"]==="false"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]=$callShell;#回傳結果return $result;}#if end#如果沒有輸出結果if(!isset($callShell["output"][0])){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"]=$callShell;#回傳結果return $result;}#if end#如果執行結束了if( $proc_get_status["running"]===false || $callShell["output"][0]==="0" ){#取得程式執行過程產生的標準輸出$result["content"]["stdout"]=$procForUnixDoaminSocket["content"][0]["content"];#如果是resourceif(gettype($result["content"]["stdout"])==="resource"){#讀取內容$result["content"]["stdout"]=stream_get_contents($result["content"]["stdout"]);}#if end#取得程式執行過程產生的非標準輸出$result["content"]["stderr"]=$procForUnixDoaminSocket["content"][0]["error"];#如果是resourceif(gettype($result["content"]["stderr"])==="resource"){#讀取內容$result["content"]["stderr"]=stream_get_contents($result["content"]["stderr"]);}#if end#跳出 whilebreak;}#if end#休息1秒sleep(1);}#while end#如果socket存在if(file_exists($tmpUnixDomainSock)){#移除之unlink($tmpUnixDomainSock);}#if end#設置執行正常$result["status"]="true";#回傳結果return $result;}#function runWithAutoAddMemoryDaemon end/*#函式說明:#用fwrite寫入到resource,可以指定每個寫入字串的結尾方式.#回傳結果:#$result["status"],執行是否正常,"true"為正常,"false"為不正常.#$result["error"],錯誤訊息陣列.#$result["function"],當前執行的函數名稱.#$result["argu"],使用的參數.#$result["is_writable"],參數stream是否為可寫入的resource,"true"代表可寫入;"false"代表不可寫入.#必填參數:#$conf["stream"],resource,寫入的目標.$conf["stream"]="";#$conf["data"],字串陣列,要寫入的內容,每個元素代表每段要寫入的內容.$conf["data"]=array();#可省略參數:#$conf["msgEndType"],字串,訊息結尾要怎麼寫,預設為"none",代表不做處理;"EOL"代表結尾要用PHP_EOL;"HTTP/1.1"代表"data"參數最多為2個,分別為header跟body,結尾方式為兩個PHP_EOL.#$conf["msgEndType"]="";#$conf["autoClose"],字串,寫入結束後是否要關閉resource,預設為"false"代表保持開着;反之為"true".#$conf["autoClose"]="false";#參考資料:#https://stackoverflow.com/questions/5294305/how-to-check-if-a-php-stream-resource-is-readable-or-writable#5294425#https://www.php.net/manual/en/function.stream-get-meta-data.php#https://www.php.net/manual/en/function.is-writable.php#https://www.php.net/manual/en/function.socket-get-status.php#https://www.php.net/manual/en/function.fopen.php#備註:#無.*/public static function fwrite(&$conf=array()){#初始化要回傳的結果$result=array();#取得當前執行的函數名稱$result["function"]=__FUNCTION__;#取得參數$result["argu"]=$conf;#如果 $conf 不為陣列if(gettype($conf)!="array"){#設置執行失敗$result["status"]="false";#設置執行錯誤訊息$result["error"][]="\$conf變數須為陣列形態";#如果傳入的參數為 nullif(is_null($conf)){#設置執行錯誤訊息$result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";}#if end#回傳結果return $result;}#if end#檢查參數#函式說明:#檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容.#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$result["error"],執行不正常結束的錯訊息陣列.#$result["simpleError"],簡單表示的錯誤訊息.#$result["function"],當前執行的函式名稱.#$result["argu"],設置給予的參數.#$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過#$result[$shouldBeCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在#$result[$shouldBeCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確#$result[$shouldBeCheckedVarName]["error"],每個參數設定的錯誤訊息#$result["shouldNotBeEmpty"],不應該為空字串或控陣列的變數.#$result["argu"],字串陣列,目前輸入的參數名稱陣列.#$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.#$result["notNeedVar"],字串陣列,多餘的參數名稱.#必填參數:#$conf["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。$conf["variableCheck::checkArguments"]["varInput"]=&$conf;#$conf["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.$conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";#可省略參數:#$conf["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("stream","data");#$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("resource","array");#$conf["canBeEmptyString"],字串,必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true",可以為空字串.#$conf["variableCheck::checkArguments"]["canBeEmptyString"]="false";#$conf["canNotBeEmpty"],字串陣列,哪些必填參數的內容不得為空字串或空陣列,僅當$conf["canBeEmptyString"]為"true"時會生效.$conf["variableCheck::checkArguments"]["canNotBeEmpty"]=array("stream");#$conf["canBeEmpty"],字串陣列,哪些必填參數的內容可為空字串或空陣列,僅當$conf["canBeEmptyString"]為"false"時會生效.#$conf["canBeEmpty"]=array();#$conf["skipableVariableCanNotBeEmpty"],字串陣列,哪些可省略參數不可以為空字串或空陣列.$conf["variableCheck::checkArguments"]["skipableVariableCanNotBeEmpty"]=array("msgEndType","autoClose");#$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("msgEndType","autoClose");#$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","string");#$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("none","false");#$conf["disallowAllSkipableVarIsEmpty"],字串,是否允許每個可省略參數都為空字串,預設為"true"允許,反之為"false".#$conf["disallowAllSkipableVarIsEmpty"]="";#$conf["disallowAllSkipableVarIsEmptyArray"],字串,是否允許每個可省略參數都為空陣列,預設為"true"允許,反之為"false".#$conf["disallowAllSkipableVarIsEmptyArray"]="";#$conf["disallowAllSkipableVarNotExist"],字串,是否不允許每個可省略參數都不存在,預設為"false"代表允許,反之為"true".#$conf["disallowAllSkipableVarNotExist"]="";#$conf["arrayCountEqualCheck"],字串陣列,為檢查哪些陣列參數的元素數量要一樣,$conf["arrayCountEqualCheck"][$i]=array()為第$i組key為哪些的變數其元素數量要相等.#$conf["arrayCountEqualCheck"][]=array();#參考資料:#array_keys=>http://php.net/manual/en/function.array-keys.php#備註:#無.$checkArguments=variableCheck::checkArguments($conf["variableCheck::checkArguments"]);unset($conf["variableCheck::checkArguments"]);#如果執行失敗if($checkArguments["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤資訊$result["error"]=$checkArguments;#回傳結果return $result;}#if end#如果檢查不通過if($checkArguments["passed"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤資訊$result["error"]=$checkArguments;#回傳結果return $result;}#if end#debug#var_dump(__LINE__,$conf["stream"]);/*#函式說明:#處理各種錯誤與例外.#回傳結果:#$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.#$result["passed"],檢查是否通過,"true"代表通過,"false"代表不通過.#$result["argu"],使用的參數.#$result["function"],當前執行的函數.#$result["error"],涵式錯誤訊息陣列.#必填參數:#無.#可省略參數:#$conf["allowCodition"],陣列,滿足什麼條件的錯誤跟例外要繼續執行而不中斷.$conf["variableCheck::setErrorHandler"]["allowCodition"]=array("stream_get_meta_data(): supplied resource is not a valid stream resource","[function] => stream_get_meta_data");#$conf["debug"],字串,"true"代表遇到不允許繼續執行的例外時要輸出debug資訊;預設為"false";$conf["variableCheck::setErrorHandler"]["debug"]="true";#$conf["format"],字串,遇到不允許的錯誤時,要用什麼格式呈現,預設為"html",其他選擇有"cmd".#$conf["format"]="html";#參考資料:#無.#備註:#無.$setErrorHandler=variableCheck::setErrorHandler($conf["variableCheck::setErrorHandler"]);unset($conf["variableCheck::setErrorHandler"]);#如果有回傳內容if($setErrorHandler!==null){#設置執行失敗$result["status"]="false";#設置錯誤資訊$result["error"]=$setErrorHandler;#回傳結果return $result;}#if end*/#取得 stream 狀態$stream_get_meta_data=stream_get_meta_data($conf["stream"]);#debug#var_dump(__LINE__,$stream_get_meta_data);#如果存在 uriif(isset($stream_get_meta_data["uri"])){#取得能否寫入$is_writable=is_writable($stream_get_meta_data["uri"]);}#if end#反之用 mode 來判斷else if(isset($stream_get_meta_data["mode"])){#函式說明:#檢查一個字串裡面是否有多個關鍵字#回傳結果:#$result["status"],"true"代表執行成功,"false"代表執行失敗.#$result["error"],錯誤訊息.#$result["function"],當前執行的函數名稱.#$result["founded"],是否有找到的關鍵字,"true"代表有找到關鍵字;"false"代表沒有找到關鍵字.#$result["foundedKeyWords"],找到的關鍵字.#$result["foundedAll"],是否有找到全部的關鍵字,"true"代表有;"false"代表沒有.#$result["argu"],使用的參數.#必填參數:#$conf["keyWords"],字串陣列,想要搜尋的關鍵字.$conf["search::findManyKeyWords"]["keyWords"]=array("r+","w","a","x","c");#$conf["string"],字串,要被搜尋的字串內容.$conf["search::findManyKeyWords"]["string"]=$stream_get_meta_data["mode"];#可省略參數:#$conf["completeEqual"],字串,是否內容要完全符合,不能多出任何不符合的內容,預設為不需要完全符合.#$conf["completeEqual"]="true";#參考資料:#無.#備註:#無.$findManyKeyWords=search::findManyKeyWords($conf["search::findManyKeyWords"]);unset($conf["search::findManyKeyWords"]);#如果執行失敗if($findManyKeyWords["status"]==="false"){#設置執行失敗$result["status"]="false";#設置錯誤資訊$result["error"]=$findManyKeyWords;#回傳結果return $result;}#if end#如果模式含有寫入的屬性if($findManyKeyWords["founded"]==="true"){#設置可以寫入$is_writable=true;}#if end}#else#反之需要其他判斷方式else{#設置警示訊息$result["warning"][]="無法判別 resource 能否寫入";#設置警示訊息$result["warning"][]=$stream_get_meta_data;#直接放行$is_writable=true;}#else end#如果不可寫入if($is_writable!==true){#設置執行失敗$result["status"]="false";#設置錯誤資訊$result["error"][]="resource 無法寫入";#設置錯誤資訊$result["error"][]=$stream_get_meta_data;#設置resource不可寫入$result["is_writable"]="false";#回傳結果return $result;}#if end#設置resource可寫入$result["is_writable"]="true";#判斷訊息結尾的格式switch($conf["msgEndType"]){#如果是 "none"case "none":#要寫入的每個字串foreach($conf["data"] as $msg){#寫入內容fwrite($conf["stream"],$msg);}#foreach endbreak;#如果是 "EOL"case "EOL":#要寫入的每個字串foreach($conf["data"] as $msg){#寫入內容,用PHP_EOL結尾.fwrite($conf["stream"],$msg.PHP_EOL);}#foreach endbreak;#如果是 "HTTP/1.1"case "HTTP/1.1":#如果要寫入的字串大於2段if(count($conf["data"])>2){#設置執行失敗$result["status"]="false";#設置錯誤資訊$result["error"][]="當參數 msgEndType 為 ".$conf["msgEndType"]." 時,參數 data 的數量不得超過2個.";#設置resource不可寫入$result["is_writable"]="false";#回傳結果return $result;}#if end#要寫入的每個字串foreach($conf["data"] as $msg){#寫入 header/bodyfwrite($conf["stream"],$msg.PHP_EOL.PHP_EOL);}#foreach end#跳出switchbreak;#非預期的類型default:#設置執行失敗$result["status"]="false";#設置錯誤資訊$result["error"][]="unsupported msgEndType ".$conf["msgEndType"];#回傳結果return $result;}#switch end#若要關閉resourceif($conf["autoClose"]==="true"){#關閉resouce.fclose($conf["stream"]);}#if end#設置執行正常$result["status"]="true";#回傳結果return $result;}#function fwrite end}#class sock end?>