Subversion Repositories php-qbpwcf

Rev

Rev 350 | Rev 376 | 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~2026 MIN ZHI, CHEN

    This file is part of QBPWCF.

    QBPWCF is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the 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 of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with QBPWCF.  If not, see <http://www.gnu.org/licenses/>.

*/
namespace qbpwcf;

/*
類別說明:
跟網頁、資訊安全性有關的類別.
備註:
無.
*/
class security{

        /*
        #函式說明:
        #當前類別被呼叫的靜態方法不存在時,將會執行該函數,回報該方法不存在.
        #回傳結果:
        #$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

        /*
        #函式說明:
        #禁止特定的angent訪問我們的網站,例如google與百度的搜尋引擎。
        #回傳結果:
        #$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
        #$result["error"],錯誤訊息.
        #$result["function"],當前執行的函數名稱.
        #必填參數:
        #$conf["disableAngentName"],字串,要禁止拜訪的用戶端資訊,代表要禁止哪些瀏覽器/搜尋引擎瀏覽,格式爲 /(含有哪些關鍵字,若有多個請用「|」隔開。)/i.
        $conf["disableAngentName"]="/(Chrome|Mozilla|Internet)/i";
        #可省略參數:
        #$conf["transferLocation"],字串,如果是要禁止搜尋引擎,要轉址到那個地方?,若沒設定,則預設爲資安素養網的臉書(https://zh-tw.facebook.com/isafemoe).
        #$conf["transferLocation"]="";
        #參考資料:
        #http://php.net/manual/en/function.preg-match.php
        #備註:
        #無.
        */
        public static function preventSerchEngine(&$conf){

                #初始化要回傳的內容
                $result=array();

                #取得當前執行的函式
                $result["function"]=__FUNCTION__;

                #如果 $conf 不為陣列
                if(gettype($conf)!="array"){

                        #設置執行失敗
                        $result["status"]="false";

                        #設置執行錯誤訊息
                        $result["error"][]="\$conf變數須為陣列形態";

                        #如果傳入的參數為 null
                        if($conf==null){

                                #設置執行錯誤訊息
                                $result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";

                                }#if end

                        #回傳結果
                        return $result;

                        }#if end

                #debug,檢查 $_SERVER["HTTP_USER_AGENT"] 的內容
                #var_dump($_SERVER['HTTP_USER_AGENT']);

                #檢查參數
                #函式說明:
                #檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容。
                #$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
                #$reuslt["error"],執行不正常結束的錯訊息陣列.
                #$result["function"],當前執行的函式名稱.
                #$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
                #$result[$shouldBtCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
                #$result[$shouldBtCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
                #$result[$shouldBtCheckedVarName]["error"],每個參數設定的錯誤訊息
                #$result["argu"],字串陣列,目前輸入的參數名稱陣列.
                #$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
                #$result["notNeedVar"],字串陣列,多餘的參數名稱.
                #必填寫的參數:
                #$conf["variableCheck::checkArguments"]["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
                $conf["variableCheck::checkArguments"]["varInput"]=&$conf;
                #$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
                $conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("disableAngentName");
                #$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object");
                $conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string");
                #$conf["variableCheck::checkArguments"]["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
                $conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
                #可以省略的參數:
                #$conf["canBeEmptyString"],必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true"。
                #$conf["canBeEmptyString"]="false";
                #$conf["variableCheck::checkArguments"]["skipableVariableName"],爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
                $conf["variableCheck::checkArguments"]["skipableVariableName"]=array("transferLocation");
                #$conf["variableCheck::checkArguments"]["skipableVariableType"],爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");
                $conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string");
                #$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
                $conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("https://zh-tw.facebook.com/isafemoe");
                #$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

                #如果使用者的瀏覽器出現變數 $conf["disableAngentName"] 裡面的關鍵字
                if(preg_match($conf["disableAngentName"],$_SERVER["HTTP_USER_AGENT"])){

                        #則轉址特定頁面
                        #函式說明:
                        #設定session變數後,立即轉址.
                        #回傳結果:
                        #$result["status"],執行是否成功,"true"代表成功,"false"代表不成功.
                        #$result["function"],當前執行的函數名稱.
                        #$result["error"],錯誤訊息陣列.
                        #必填的參數:
                        #$conf["header::redirectionNow"]["headerLocation"],為要轉址到的地方,若爲 $_SERVER["PHP_SELF"],則爲回到目前頁面,全民資安素養網爲 https://isafe.moe.edu.tw/.
                        $conf["header::redirectionNow"]["headerLocation"]=$conf["transferLocation"];
                        #可省略的參數:
                        #$conf["sessionName"],字串陣列,可以指派session變數的名稱.
                        #$conf["sessionName"]=array("");
                        #$conf["sessionValue"]字串陣列,可以指派session變數的內容.
                        #$conf["sessionValue"]=array("");
                        #參靠資料來源:
                        #http://php.net/manual/en/reserved.variables.server.php
                        $redirectionNow=header::redirectionNow($conf["header::redirectionNow"]);
                        unset($conf["header::redirectionNow"]);

                        #如果轉址失敗
                        if($redirectionNow["status"]=="false"){

                                #設置執行失敗
                                $result["status"]="false";

                                #設置執行錯誤訊息
                                $result["error"]=$redirectionNow;

                                #回傳結果
                                return $result;

                                }#if end

                        }#if end

                #執行到這邊代表是可以拜訪的網頁瀏覽器
                $result["status"]="true";

                #回傳結果
                return $result;

                }#function preventSerchEngine end

        /*
        #函式說明:
        #禁止做任違反版權的事情,禁止在網頁按下滑鼠右鍵,禁止複製圖片,禁止開新分頁(失敗), 版權所有、Power by訊息.
        #回傳的內容:
        #保護版權的語法
        #必填參數:
        #無
        #可省略參數:
        #$conf["name"],字串,公司、組織、單位的名稱,預設不指定.
        #$conf["name"]="";
        #$conf["powerBy"],字串,由誰提供,預設爲QBPWCF.
        #$conf["powerBy"]="";
        #$conf["powerByLink"],字串,power by字串的連結目標,預設爲"https://www.qbpwcf.org".
        #$conf["powerByLink"]="";
        #$conf["bgColor"],字串,背景顏色,預設爲淡藍色.
        #$conf["bgColor"]="";
        #參考資料:
        #http://www.w3schools.com/jsref/dom_obj_event.asp
        #備註:
        #無.
        */
        public static function copyRight(&$conf){

                #初始化要回傳的結果
                $result=array();

                #取得當前執行的函數名稱
                $result["function"]=__FUNCTION__;

                #取得參數
                $result["argu"]=$conf;

                #如果 $conf 不為陣列
                if(gettype($conf)!="array"){

                        #設置執行失敗
                        $result["status"]="false";

                        #設置執行錯誤訊息
                        $result["error"][]="\$conf變數須為陣列形態";

                        #如果傳入的參數為 null
                        if(is_null($conf)){

                                #設置執行錯誤訊息
                                $result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";

                                }#if end

                        #回傳結果
                        return $result;

                        }#if end

                #初始化 content
                $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["mustBeFilledVariableName"]=array();
                #$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null代表不指定變數形態.
                #$conf["mustBeFilledVariableType"]=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("powerBy","powerByLink","bgColor");
                #$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
                $conf["variableCheck::checkArguments"]["skipableVariableName"]=array("name","powerBy","powerByLink","bgColor");
                #$conf["skipableVariableType"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");
                $conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string","string","string","string");
                #$conf["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
                $conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("","QBPWCF","https://www.qbpwcf.org","#DDDDFF");
                #$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

                #函式說明:
                #將要執行的script語法透過該函式執行(會在程式外層用<script></script>包起來).
                #回傳結果:
                #$result["status"],執行是否正常,"true"為正常,"false"為不正常.
                #$result["error"],錯誤訊息陣列
                #$result["function"],當前執行的函數名稱
                #$result["content"],要執行的javaScript語法
                #必填參數:
                #$conf["script"],字串,要執行的javaScript語法.
                $conf["javaScript::toScript"]["script"]="



                var copyRightSpan=document.createElement('span');
                var copyRightText=document.createTextNode('".$conf["name"]."');
                copyRightSpan.appendChild(copyRightText);

                //建立power by span
                var powerBySpan=document.createElement('span');
                var powerByA=document.createElement('a');
                powerByA.href='".$conf["powerByLink"]."';
                powerByA.target='_blank';
                var powerByText=document.createTextNode('Powered by '+'".$conf["powerBy"]."');
                powerByA.appendChild(powerByText);
                powerBySpan.appendChild(powerByA);

                //建立 copy right div
                var copyRightDiv=document.createElement('div');
                copyRightDiv.appendChild(copyRightSpan);
                copyRightDiv.appendChild(powerBySpan);
                copyRightDiv.style.backgroundColor='".$conf["bgColor"]."';
                copyRightDiv.style.textAlign='center';

                //顯現 copy right
                document.body.appendChild(copyRightDiv);

                ";
                #可省略參數:
                #$conf["onReady"],字串,是否要在網頁完全載入後再執行,"false"為不等載入完就先執行,預設為"true"要等載入完再執行.
                #$conf["onReady"]="true";
                #$conf["globalJs"],字串陣列,為要放入<script>標籤的js全域變數.
                #$conf["globalJs"]=array();
                #$conf["jsFunciton"],字串陣列,為要放入<script>標籤的js函數.
                #$conf["jsFunciton"]=array();
                #參考資料:
                #http://stackoverflow.com/questions/9899372/pure-javascript-equivalent-to-jquerys-ready-how-to-call-a-function-when-the
                $toScript=javaScript::toScript($conf["javaScript::toScript"]);
                unset($conf["javaScript::toScript"]);

                #如果建立 javascript 語法失敗
                if($toScript["status"]==="false"){

                        #設置執行失敗
                        $result["status"]="false";

                        #設置執行錯誤訊息
                        $result["error"]=$toScript;

                        #回傳結果
                        return $result;

                        }#if end

                #傳接 content
                $result["content"]=$result["content"].$toScript["content"];

                #保護版權的語法
                #oncontextmenu,按下滑鼠右鍵
                #onContextMenu,按下滑鼠右鍵
                #ondragstart,開始拖曳
                #onselsect,選取區塊時
                #onselectstart,開始選取區塊
                #onkeydown='if(event.tKey && event.ctrlKey),按下ctrl+t開分頁時
                $result["content"]=$result["content"]."
                        <html
                        oncontextmenu=\"return false\"
                        onContextMenu=\"window.event.returnValue=false\"
                        onselect=\"return false\"
                        onselectstart=\"return false\"
                        ondragstart=\"return false\"
                        oncopy=\"return false\"
                        onbeforeprint=\"return false\"
                        >\r\n";

                #設置執行正常
                $result["status"]="true";

                #回傳語法
                return $result;

                }#函式結束

        /*
        #函式說明:
        #放置用空白圖片擋住要呈現的圖片
        #回傳結果:
        #$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
        #$result["error"],錯誤訊息.
        #$result["function"],當前執行的函數名稱.
        #$result["content"],語法.
        #必填參數:
        $conf["imgAddress"],字串,要放的圖片位置和名稱.
        $conf["imgAddress"]="";
        $conf["imgWidth"],字串,爲圖片的寬.
        $conf["imgWidth"]="";
        $conf["imgHeight"],字串,爲圖片的高.
        $conf["imgHeight"]="";
        $conf["imgLeft"]=,字串,爲圖片放置的位置距離網頁左邊多少.
        $conf["imgLeft"]="";
        $conf["imgTop"]=,字串,爲圖片放置的位置距離網頁頂端多少.
        $conf["imgTop"]="";
        #可省略參數:
        #$conf["useBase64"],字串,是否要用base64的方式呈現圖片,預設為"true"代表要用base64的方式呈現,反之可用"false".
        #$conf["useBase64"]="true";
        #參考資料:
        #無.
        #備註:
        #無.
        */
        public static function imgProtect(&$conf){

                #初始化要回傳的內容
                $result=array();

                #取得當前執行的函式
                $result["function"]=__FUNCTION__;

                #如果 $conf 不為陣列
                if(gettype($conf)!="array"){

                        #設置執行失敗
                        $result["status"]="false";

                        #設置執行錯誤訊息
                        $result["error"][]="\$conf變數須為陣列形態";

                        #如果傳入的參數為 null
                        if($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["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
                #$result[$shouldBtCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
                #$result[$shouldBtCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
                #$result[$shouldBtCheckedVarName]["error"],每個參數設定的錯誤訊息
                #$result["argu"],字串陣列,目前輸入的參數名稱陣列.
                #$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
                #$result["notNeedVar"],字串陣列,多餘的參數名稱.
                #必填寫的參數:
                #$conf["variableCheck::checkArguments"]["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
                $conf["variableCheck::checkArguments"]["varInput"]=&$conf;
                #$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
                $conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("imgAddress","imgWidth","imgHeight","imgLeft","imgTop");
                #$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object");
                $conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string","string","string","string","string");
                #$conf["variableCheck::checkArguments"]["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
                $conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
                #可以省略的參數:
                #$conf["canBeEmptyString"],必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true"。
                #$conf["canBeEmptyString"]="false";
                #$conf["variableCheck::checkArguments"]["skipableVariableName"],爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
                $conf["variableCheck::checkArguments"]["skipableVariableName"]=array("useBase64");
                #$conf["variableCheck::checkArguments"]["skipableVariableType"],爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");
                $conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string");
                #$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
                $conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("true");
                #$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

                #建立要放置的圖片樣式
                #函式說明:
                #創建 css 樣式
                #回傳結果:
                #$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
                #$result["css"],css設定內容
                #$result["function"],當前執行的函數
                #$result["error"],涵式錯誤訊息,若爲""則表示沒有錯誤
                $conf["css"]["createCssStyle"]["cssStyleName"]="imgStyle-".$conf["imgLeft"].$conf["imgTop"];
                $conf["css"]["createCssStyle"]["attributes"]=array("width","height","position","top","left");
                $conf["css"]["createCssStyle"]["content"]=array($conf["imgWidth"],$conf["imgHeight"],"absolute",$conf["imgTop"],$conf["imgLeft"]);
                $css=css::createCssStyle($conf["css"]["createCssStyle"]);
                unset($conf["css"]["createCssStyle"]);#清空變數避免出錯

                #如果建立css樣式失敗
                if($css["status"]=="false"){

                        #設置執行失敗
                        $result["status"]="false";

                        #設置執行錯誤訊息
                        $result["error"]=$css;

                        #回傳結果
                        return $result;

                        }#if end

                #串接css語法
                $result["content"]=$result["content"].$css["css"];

                #如果要用base64顯示圖片
                if($conf["useBase64"]=="true"){

                        #將圖片用base64加密呈現
                        #函數說明:
                        #用data:mimeType;base64,imgVar的形式來提供圖片的連結,亦即圖片儲存在變數裡面,本函式包含顯示圖片的語法.
                        #回傳結果:
                        #$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
                        #$result["error"],錯誤訊息
                        #$result["content"],圖片的連結資訊
                        #$result["function"],當前執行的函數名稱
                        #必填參數:
                        #$conf["img::data"]["imgPosition"],要轉存成2元碼的圖片檔案位置與名稱
                        $conf["img::data"]["imgPosition"]=$conf["imgAddress"];
                        #可省略參數:
                        #$conf["img::data"]["alt"],若沒有圖片要用什麼文字顯示。
                        $conf["img::data"]["alt"]="not found";
                        #$conf["img::data"]["class"],圖片要套用的css樣式名稱.
                        $conf["img::data"]["class"]="imgStyle-".$conf["imgLeft"].$conf["imgTop"];
                        #$conf["mimeType"],2元碼的內容是什麼,預設為"image/*".
                        #$conf["mimeType"]="image/*";
                        #$conf["compressType"],2元碼壓縮的方式,預設為"base64".
                        #$conf["compressType"]="base64";
                        #$conf["delImg"],讀取完圖片檔案後,要移除圖片嗎?"true"代表要移除,"false"代表不要移除,預設為"false".
                        #$conf["delImg"]="false";
                        #參考資料:
                        #將檔案用字串變數儲存起來=>http://php.net/manual/en/function.file-get-contents.php
                        #壓縮2元碼=>http://php.net/manual/en/function.base64-encode.php
                        $data=img::data($conf["img::data"]);
                        unset($conf["img::data"]);

                        #將圖片用base64加密呈現失敗
                        if($data["status"]=="false"){

                                #設置執行失敗
                                $result["status"]="false";

                                #設置執行錯誤訊息
                                $result["error"]=$data;

                                #回傳結果
                                return $result;

                                }#if end

                        #取得用base64放置圖片的語法
                        $result["content"]=$result["content"].$data["content"];

                        }#if end

                #反之為一般放置圖片的方式
                else{

                        #放置要放的圖片
                        #函式說明:
                        #放置可以套用css樣式的圖片
                        #回傳結果:
                        #$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
                        #$result["error"],錯誤訊息陣列
                        #$result["function"],當前函數執行的名稱
                        #$result["content"],印出圖片的語法。
                        $conf["img"]["show"]["position"]=$conf["imgAddress"];
                        $conf["img"]["show"]["alt"]="not found";
                        $conf["img"]["show"]["class"]="imgStyle-".$conf["imgLeft"].$conf["imgTop"];
                        $show=img::show($conf["img"]["show"]);
                        unset($conf["img"]["show"]);#清空變數避免出錯

                        #如果放置圖片的語法建立失敗
                        if($show["status"]=="false"){

                                #設置執行失敗
                                $result["status"]="false";

                                #設置執行錯誤訊息
                                $result["error"]=$show;

                                #回傳結果
                                return $result;

                                }#if end

                        #串接顯示圖片的語法
                        $result["content"]=$result["content"].$show["content"];

                        }#else end

                #建立圖片隔離層樣式
                $conf["css"]["createCssStyle"]["cssStyleName"]="imgIsolationLayerStyle".$conf["imgLeft"].$conf["imgTop"];
                $conf["css"]["createCssStyle"]["attributes"]=array("width","height","opacity","position","top","left");
                $conf["css"]["createCssStyle"]["content"]=array($conf["imgWidth"],$conf["imgHeight"],".0","absolute",$conf["imgTop"],$conf["imgLeft"]);
                $css=css::createCssStyle($conf["css"]["createCssStyle"]);
                unset($conf["css"]["createCssStyle"]);#清空變數避免出錯

                #如果建立css樣式失敗
                if($css["status"]=="false"){

                        #設置執行失敗
                        $result["status"]="false";

                        #設置執行錯誤訊息
                        $result["error"]=$css;

                        #回傳結果
                        return $result;

                        }#if end

                #取得圖片隔離層樣式程式碼
                $result["content"]=$result["content"].$css["css"];

                #放置隔離層
                #函式說明:
                #放置可以套用css樣式的圖片
                #回傳結果:
                #$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
                #$result["error"],錯誤訊息陣列
                #$result["function"],當前函數執行的名稱
                #$result["content"],印出圖片的語法。
                #必填參數:
                $conf["img"]["show"]["position"]="copyRight.png";#圖片位置
                #可省略參數:
                #$conf["img"]["show"]["alt"]="not found";#若沒有圖片要用什麼文字顯示。
                $conf["img"]["show"]["class"]="imgIsolationLayerStyle".$conf["imgLeft"].$conf["imgTop"];#要套用的css樣式類別名稱。
                $show=img::show($conf["img"]["show"]);
                unset($conf["img"]["show"]);

                #如果放置圖片的語法建立失敗
                if($show["status"]=="false"){

                        #設置執行失敗
                        $result["status"]="false";

                        #設置執行錯誤訊息
                        $result["error"]=$show;

                        #回傳結果
                        return $result;

                        }#if end

                #串接顯示隔離層圖片的語法
                $result["content"]=$result["content"].$show["content"];

                #執行到這邊代表執行成功
                $result["status"]="true";

                #回傳語法
                return $result;

                }#function imgProtect end

        /*
        #函式說明:
        #加密php檔案的內容將結果輸出.
        #回傳結果:
        #$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
        #$result["error"],錯誤訊息陣列.
        #$result["function"],當前執行的函式名稱.
        #$result["content"],加密好的php內容字串.
        #必填參數:
        #$conf["phpFile"],字串,要加密的php檔案位置與名稱.
        $conf["phpFile"]="";
        #$conf["fileArgu"],字串,php變數__FILE__的內容,亦即該檔案在檔案系統的絕對路徑
        $conf["fileArgu"]=__FILE__;
        #可省略參數:
        #無.
        #參考資料:
        #無.
        #備註:
        #僅支援單行只出現<?php、?>、其他內容的PHP檔案格式內容.
        */
        public static function encodePHP(&$conf){

                #初始化要回傳的內容
                $result=array();

                #取得當前執行的函式
                $result["function"]=__FUNCTION__;

                #如果 $conf 不為陣列
                if(gettype($conf)!="array"){

                        #設置執行失敗
                        $result["status"]="false";

                        #設置執行錯誤訊息
                        $result["error"][]="\$conf變數須為陣列形態";

                        #如果傳入的參數為 null
                        if($conf==null){

                                #設置執行錯誤訊息
                                $result["error"][]="\$conf變數不得為null,請檢查函數「".$result["function"]."」的參數設置有無正確!";

                                }#if end

                        #回傳結果
                        return $result;

                        }#if end

                #初始加密好的php程式內容
                $result["content"]="";

                #檢查參數
                #函式說明:
                #檢查必填與可省略的參數,可省略參數可指定預設要給與什麼數值內容。
                #$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
                #$reuslt["error"],執行不正常結束的錯訊息陣列.
                #$result["function"],當前執行的函式名稱.
                #$result["passed"],識別要檢查的全體變數是否存在以及型態是否正確的變數,"true"代表檢查全部通過;"false"代表檢查不通過
                #$result[$shouldBtCheckedVarName]["varExist"],所檢查的變數是否存在,"false"代表不存在;"true"代表存在
                #$result[$shouldBtCheckedVarName]["varType"],所檢查的變數型態是否正確,"false"代表錯誤;"true"代表正確
                #$result[$shouldBtCheckedVarName]["error"],每個參數設定的錯誤訊息
                #$result["argu"],字串陣列,目前輸入的參數名稱陣列.
                #$result["legalVarName"],字串陣列,合法可用的參數名稱陣列.
                #$result["notNeedVar"],字串陣列,多餘的參數名稱.
                #必填寫的參數:
                #$conf["variableCheck::checkArguments"]["varInput"],陣列變數,要檢查的陣列變數,請在要檢查的參數前面加上&,這樣變動的結果才能被套用。
                $conf["variableCheck::checkArguments"]["varInput"]=&$conf;
                #$conf["variableCheck::checkArguments"]["mustBeFilledVariableName"],爲必填參數的變數名稱陣列,形態爲陣列變數,元素數量需要跟"mustBeFilledVariableType"參數的元素數量一致,例如: $conf["mustBeFilledVariableName"] = array("id","account","password");
                $conf["variableCheck::checkArguments"]["mustBeFilledVariableName"]=array("phpFile","fileArgu");
                #$conf["variableCheck::checkArguments"]["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object");
                $conf["variableCheck::checkArguments"]["mustBeFilledVariableType"]=array("string","string");
                #$conf["variableCheck::checkArguments"]["referenceVarKey"],字串,$conf參數後面的key值,用於移除不要的參考陣列.
                $conf["variableCheck::checkArguments"]["referenceVarKey"]="variableCheck::checkArguments";
                #可以省略的參數:
                #$conf["canBeEmptyString"],必填變數內容如果是空字串就不能算是有設置的話,請設為"false",預設爲"true"。
                #$conf["canBeEmptyString"]="false";
                #$conf["variableCheck::checkArguments"]["skipableVariableName"],爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
                #$conf["variableCheck::checkArguments"]["skipableVariableName"]=array("useBase64");
                #$conf["variableCheck::checkArguments"]["skipableVariableType"],爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableType"] = array("string",integer,"double");
                #$conf["variableCheck::checkArguments"]["skipableVariableType"]=array("string");
                #$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"],字串陣列,每個不存在的可省略變數要初始化為什麼,null與代表不指定,若預設值是參數之一,請將$conf["mustBeFilledVar"]改成"\$conf["\mustBeFilledVar\"]".
                #$conf["variableCheck::checkArguments"]["skipableVarDefaultValue"]=array("true");
                #$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

                #函式說明:
                #依據行號分隔抓取檔案的內容,結果會回傳一個陣列
                #回傳的變數說明:
                #$result["status"],執行是否成功,"true"代表成功;"fasle"代表失敗.
                #$result["error"],錯誤訊息提示.
                #$result["warning"],警告訊息.
                #$result["function"],當前執行的函數名稱.
                #$result["fileContent"],爲檔案的內容陣列.
                #$result["lineCount"],爲檔案內容總共的行數.
                #$result["fullContent"],為檔案的完整內容.
                #$result["base64data"],為檔案的base64內容.
                #$result["mimeType"],為檔案的mime type.
                #必填參數:
                #$conf["filePositionAndName"],字串,爲檔案的位置以及名稱.
                $conf["fileAccess::getFileContent"]["filePositionAndName"]=$conf["phpFile"];
                #$conf["fileArgu"],字串,php變數__FILE__的內容,亦即該檔案在檔案系統的絕對路徑
                $conf["fileAccess::getFileContent"]["fileArgu"]=$conf["fileArgu"];
                #可省略參數:
                #$conf["web"],是要取得網路上的檔案則為"true";反之則為"false".
                $conf["fileAccess::getFileContent"]["web"]="false";
                #參考資料:
                #file(),取得檔案內容的行數.
                #file=>http:#php.net/manual/en/function.file.php
                #rtrim(),剔除透過file()取得每行內容結尾的換行符號.
                #filesize=>http://php.net/manual/en/function.filesize.php
                $getFileContent=fileAccess::getFileContent($conf["fileAccess::getFileContent"]);
                unset($conf["fileAccess::getFileContent"]);

                #如果讀取檔案內容失敗
                if($getFileContent["status"]==="false"){

                        #設置執行失敗
                        $result["status"]="false";

                        #設置執行錯誤訊息
                        $result["error"]=$getFileContent;

                        #回傳結果
                        return $result;

                        }#if end

                #加密過後的php內容
                $contentWithoutPhpTagArray=array();

                #識別是否開始php語法了.
                $isPHP=false;

                #識別是否讀取到php tag開頭
                $phpStart=false;

                #識別是否讀取到php tag結尾
                $phpEed=true;

                #針對每行內容
                foreach($getFileContent["fileContent"] as $index=>$line){

                        #debug
                        #echo "處理第".($index+1)."行".PHP_EOL;

                        #函式說明:
                        #將固定格式的字串分開,並回傳分開的結果。
                        #回傳結果:
                        #$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
                        #$result["error"],錯誤訊息陣列
                        #$result["function"],當前執行的函數名稱.
                        #$result["argu"],使用的參數.
                        #$result["oriStr"],要分割的原始字串內容
                        #$result["dataArray"],爲分割好字串的陣列內容,$result["dataArray"][$i]爲第($i+1)段的內容。
                        #$result["dataCounts"],爲總共分成幾段
                        #$result["found"],是否有在$conf["stringIn"]找到$conf["spiltSymbol"],"true"代表有找到,"false"代表沒有找到.
                        #必填的參數:
                        #$conf["stringIn"],字串,要處理的字串.
                        $conf["stringProcess::spiltString"]["stringIn"]=$line;
                        #$conf["spiltSymbol"],字串,爲以哪個符號作爲分割.
                        $conf["stringProcess::spiltString"]["spiltSymbol"]="<?php";
                        #可省略參數:
                        #$conf["allowEmptyStr"],是否允許分割出來空字串,預設為"false"不允許;"true"代表允許.
                        $conf["stringProcess::spiltString"]["allowEmptyStr"]="false";
                        $spiltString=stringProcess::spiltString($conf["stringProcess::spiltString"]);
                        unset($conf["stringProcess::spiltString"]);

                        #如果執行失敗
                        if($spiltString["status"]==="false"){

                                #設置執行失敗
                                $result["status"]="false";

                                #設置執行錯誤訊息
                                $result["error"]=$spiltString;

                                #回傳結果
                                return $result;

                                }#if end

                        #初始化該行的資訊描述
                        $lineInfo=array();

                        #如果沒有關鍵字
                        if($spiltString["found"]==="false" && $isPHP===false){

                                #初始化暫存的資訊
                                $tempLineInfo=array();

                                #預設該行不是php的內容
                                $tempLineInfo["isPHP"]=false;

                                #放置內容
                                $tempLineInfo["content"]=$line;

                                #儲存一行資訊描述
                                $lineInfo[]=$tempLineInfo;

                                }#if end

                        #反之有關鍵字且 現在是屬於 php 的範圍
                        else if($spiltString["found"]==="false" && $isPHP===true){

                                #確認該段目前沒有 "?".">" 結尾

                                #函式說明:
                                #將固定格式的字串分開,並回傳分開的結果。
                                #回傳結果:
                                #$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
                                #$result["error"],錯誤訊息陣列
                                #$result["function"],當前執行的函數名稱.
                                #$result["argu"],使用的參數.
                                #$result["oriStr"],要分割的原始字串內容
                                #$result["dataArray"],爲分割好字串的陣列內容,$result["dataArray"][$i]爲第($i+1)段的內容。
                                #$result["dataCounts"],爲總共分成幾段
                                #$result["found"],是否有在$conf["stringIn"]找到$conf["spiltSymbol"],"true"代表有找到,"false"代表沒有找到.
                                #必填的參數:
                                #$conf["stringIn"],字串,要處理的字串.
                                $conf["stringProcess::spiltString"]["stringIn"]=$line;
                                #$conf["spiltSymbol"],字串,爲以哪個符號作爲分割.
                                $conf["stringProcess::spiltString"]["spiltSymbol"]="?>";
                                #可省略參數:
                                #$conf["allowEmptyStr"],是否允許分割出來空字串,預設為"false"不允許;"true"代表允許.
                                $conf["stringProcess::spiltString"]["allowEmptyStr"]="false";
                                $spiltString=stringProcess::spiltString($conf["stringProcess::spiltString"]);
                                unset($conf["stringProcess::spiltString"]);

                                #如果執行失敗
                                if($spiltString["status"]==="false"){

                                        #設置執行失敗
                                        $result["status"]="false";

                                        #設置執行錯誤訊息
                                        $result["error"]=$spiltString;

                                        #回傳結果
                                        return $result;

                                        }#if end

                                #反之有關鍵字且 現在是屬於 php 的範圍
                                if($spiltString["found"]==="false" && $isPHP===true){

                                        #初始化暫存的資訊
                                        $tempLineInfo=array();

                                        #預設該行不是php的內容
                                        $tempLineInfo["isPHP"]=true;

                                        #放置內容
                                        $tempLineInfo["content"]=$line;

                                        #儲存一行資訊描述
                                        $lineInfo[]=$tempLineInfo;

                                        }#if end

                                #反之有找到關鍵字,且現在屬於 php 的範圍
                                else if($spiltString["found"]==="true" && $isPHP===true){

                                        #如果分割成0段
                                        if($spiltString["dataCounts"]===0){

                                                #識別是否開始php語法了.
                                                $isPHP=false;

                                                #識別是否讀取到php tag開頭
                                                $phpStart=false;

                                                #識別是否讀取到php tag結尾
                                                $phpEed=true;

                                                }#if end

                                        #如果分割成其他段落
                                        else{

                                                #設置執行錯誤訊息
                                                $result["error"][]="not supported now";

                                                }#else end

                                        }#if end

                                }#if end

                        #反之有關鍵字
                        else if($spiltString["found"]==="true"){

                                #識別是否開始php語法了.
                                $isPHP=true;

                                #識別是否讀取到php tag開頭
                                $phpStart=true;

                                #識別是否讀取到php tag結尾
                                $phpEed=false;

                                #如果切成兩段
                                if($spiltString["dataCounts"]===2){

                                        #儲存非 php 的字串
                                        $noPHPstr=$spiltString["dataArray"][0];

                                        #初始化暫存的資訊
                                        $tempLineInfo=array();

                                        #預設該行不是php的內容
                                        $tempLineInfo["isPHP"]=false;

                                        #放置內容
                                        $tempLineInfo["content"]=$noPHPstr;

                                        #儲存屬於 php 的字串
                                        $phpStr=$spiltString["dataArray"][1];

                                        #初始化暫存的資訊
                                        $tempLineInfo=array();

                                        #預設該行不是php的內容
                                        $tempLineInfo["isPHP"]=true;

                                        #放置內容
                                        $tempLineInfo["content"]=$noPHPstr;

                                        }#if end

                                #反之切成一段
                                else if($spiltString["dataCounts"]===1){

                                        #設置執行失敗
                                        $result["status"]="false";

                                        #設置執行錯誤訊息
                                        $result["error"][]="not supported now";

                                        #回傳結果
                                        return $result;

                                        }#else end

                                #反之切成0段
                                else if($spiltString["dataCounts"]===0){

                                        #do nothing

                                        }#else end

                                #反之
                                else{
                                        #設置執行失敗
                                        $result["status"]="false";

                                        #設置執行錯誤訊息
                                        $result["error"][]="not supported now";

                                        #回傳結果
                                        return $result;

                                        }#else end

                                }#else end

                        #真對每個字串
                        foreach($lineInfo as $linfo){

                                #記錄起來
                                $contentWithoutPhpTagArray[]=$linfo;

                                }#foreach end

                        }#foreach end

                #debug
                #var_dump($contentWithoutPhpTagArray);

                #儲存每行的檔案內容
                $res=array();

                #php段落
                $phpSection="";

                #針對每行程式
                foreach($contentWithoutPhpTagArray as $lineInfo){

                        #如果不是 php
                        if($lineInfo["isPHP"]===false){

                                #如果有php段落
                                if(!empty($phpSection)){

                                        #加密php程式
                                        $encodedPHP=base64_encode($phpSection);

                                        #串接內容
                                        $res[]="<?php eval(base64_decode(\"".$encodedPHP."\")); ?>";

                                        }#if end

                                #清空php段落
                                $phpSection="";

                                #串接內容
                                $res[]=$lineInfo["content"].PHP_EOL;

                                }#if end

                        #反之是 PHP 內容
                        else{
                                #有內容才處理
                                if(!empty($lineInfo["content"])){

                                        #串接php語法
                                        $phpSection=$phpSection.$lineInfo["content"].PHP_EOL;

                                        }#if end

                                }#else end

                        }#foreach end

                #如果有php段落
                if(!empty($phpSection)){

                        #加密php程式
                        $encodedPHP=base64_encode($phpSection);

                        #串接內容
                        $res[]="<?php eval(base64_decode(\"".$encodedPHP."\")); ?>";

                        }#if end

                #var_dump($res);exit;

                #針對每個要寫入的行內容
                foreach($res as $line){

                        $result["content"]=$result["content"].$line;

                        }#foreach end

                #設置執行正常
                $result["status"]="true";

                #回傳結果
                return $result;

                }#function encodePHP end
                
        /*
        #函式說明:
        #檢查 apache http(s) log 中疑似攻擊的記錄.
        #回傳結果:
        #$result["status"],字串,執行是否正常,"true"代表正常,"false"代表不正常.
        #$result["error"],錯誤訊息陣列.
        #$result["function"],字串,當前執行的函式名稱.
        #$result["content"],陣列,攻擊記錄資訊,每個元素為陣列key為"ip"者為攻擊者的ip;key為info者為其資訊陣列,其key為"log"者代表log的行內容;key為"time"者代表時間點;key為ip者代表ip.
        #必填參數:
        #無.
        #可省略參數:
        #$conf["logPath"],http log的路徑,預設為"/var/log/httpd".
        #$conf["logPath"]="/var/log/httpd";
        #$conf["https"],字串,是否為要查https的log,預設為"false",代表為http.
        #$conf["https"]="false";
        #參考資料:
        #無.
        #備註:
        #目前僅支援 apache 提供的 http(s) 服務.
        #攻擊者的定義包含http回應的code為4開頭或用戶使用 HTTP/1.0 協定或用戶使用 CONNECT method,且時間間隔不超過1秒鐘,次數達到3次.
        */
        public static function checkHttpAttackLog(&$conf){
        
                #初始化要回傳的結果
                $result=array();

                #取得當前執行的函數名稱
                $result["function"]=__FUNCTION__;

                #取得參數
                $result["argu"]=$conf;

                #如果 $conf 不為陣列
                if(gettype($conf)!="array"){

                        #設置執行失敗
                        $result["status"]="false";

                        #設置執行錯誤訊息
                        $result["error"][]="\$conf變數須為陣列形態";

                        #如果傳入的參數為 null
                        if(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["mustBeFilledVariableName"]=array();
                #$conf["mustBeFilledVariableType"],爲必填參數的變數陣列應該爲何種變數形態,形態爲陣列,元素數量需要跟"mustBeFilledVariableName"參數的元素數量一致,例如: $conf["mustBeFilledVariableType"] = array("string",integer,"double","resource","object"); , null、any代表不指定變數形態.其中 resource也包含"resource (closed)".
                #$conf["mustBeFilledVariableType"]=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("logPath","https");
                #$conf["skipableVariableName"],陣列字串,爲可省略參數的變數名稱陣列,形態爲陣列變數,例如: $conf["skipableVariableName"] = array("id","account","password");
                $conf["variableCheck::checkArguments"]["skipableVariableName"]=array("logPath","https");
                #$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("/var/log/httpd","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"]);
        
                #預設為http的log
                $logFile="access_log";
        
                #如果 https 為 "true"
                if($conf["https"]==="true"){
                
                        #設置為 https 的 log
                        $logFile="ssl_access_log";
                
                        }#if end
        
                #取得 http 存取記錄的 log
                #函式說明:
                #依據行號分隔抓取檔案的內容,結果會回傳一個陣列
                #回傳的變數說明:
                #$result["status"],執行是否成功,"true"代表成功;"fasle"代表失敗.
                #$result["error"],錯誤訊息提示.
                #$result["warning"],警告訊息.
                #$result["function"],當前執行的函數名稱.
                #$result["fileContent"],爲檔案的內容陣列.
                #$result["lineCount"],爲檔案內容總共的行數.
                #$result["fullContent"],為檔案的完整內容.
                #$result["base64dataOnly"],檔案的base64data.
                #$result["base64data"],為在網頁上給予src參數的數值.
                #$result["mimeType"],為檔案的mime type.
                #必填參數:
                #$conf["filePositionAndName"],字串,爲檔案的位置以及名稱.
                $conf["fileAccess::getFileContent"]["filePositionAndName"]=$conf["logPath"]."/".$logFile;
                #$conf["fileArgu"],字串,php變數__FILE__的內容,亦即該檔案在檔案系統的絕對路徑
                $conf["fileAccess::getFileContent"]["fileArgu"]=__FILE__;
                #可省略參數:
                #$conf["web"],是要取得網路上的檔案則為"true";反之預設為"false".
                #$conf["web"]="true";
                #$conf["createIfnotExist"],字串,預設為"false"代表檔案不存在也不需要建立;反之為"true".
                #$conf["createIfnotExist"]="false";
                #$conf["autoDeleteSpaceOnEachLineStart"],字串,預設為"false",不做額外處理;反之為"true"
                #$conf["autoDeleteSpaceOnEachLineStart"]="false";
                #參考資料:
                #file(),取得檔案內容的行數.
                #file=>http:#php.net/manual/en/function.file.php
                #rtrim(),剔除透過file()取得每行內容結尾的換行符號.
                #filesize=>http://php.net/manual/en/function.filesize.php
                #參考資料:
                #無.
                #備註:
                #無.
                $getFileContent=fileAccess::getFileContent($conf["fileAccess::getFileContent"]);
                unset($conf["fileAccess::getFileContent"]);

                #如果執行失敗
                if($getFileContent["status"]==="false"){

                        #設置執行失敗
                        $result["status"]="false";

                        #設置錯誤訊息
                        $result["error"]=$getFileContent;

                        #回傳結果
                        return $result;

                        }#if end
                
                /*
                http log 範例:
                36.149.205.198 - - [22/Jun/2026:15:49:21 +0800] "CONNECT api.ipapi.is:443 HTTP/1.1" 200 -
                36.149.205.198 - - [22/Jun/2026:15:49:24 +0800] "CONNECT ipwho.is:443 HTTP/1.1" 200 -
                36.149.205.198 - - [22/Jun/2026:15:49:18 +0800] "CONNECT push.services.mozilla.com:443 HTTP/1.1" 200 -
                120.48.6.159 - - [22/Jun/2026:15:49:20 +0800] "CONNECT ifconfig.me:443 HTTP/1.1" 200 -
                36.149.205.198 - - [22/Jun/2026:15:49:24 +0800] "CONNECT ipwho.is:443 HTTP/1.1" 200 -
                36.149.205.198 - - [22/Jun/2026:15:49:25 +0800] "CONNECT api.ipapi.is:443 HTTP/1.1" 200 -
                36.149.205.198 - - [22/Jun/2026:15:49:28 +0800] "CONNECT ipwho.is:443 HTTP/1.1" 200 -
                36.149.205.198 - - [22/Jun/2026:15:49:30 +0800] "CONNECT nexus.officeapps.live.com:443 HTTP/1.1" 200 -
                172.238.244.28 - - [22/Jun/2026:15:49:31 +0800] "GET / HTTP/1.0" 400 402
                36.149.205.198 - - [22/Jun/2026:15:49:29 +0800] "CONNECT api.ipapi.is:443 HTTP/1.1" 200 -
                36.149.205.198 - - [22/Jun/2026:15:49:33 +0800] "CONNECT qaz23.com:2869 HTTP/1.1" 403 353
                36.149.205.198 - - [22/Jun/2026:15:49:34 +0800] "CONNECT qaz23.com:2869 HTTP/1.1" 403 353
                */
                
                #初始化給予 search::getMatchFormatsStrings 使用的 formats 參數
                $formatsParamsOfsearchGetMatchFormatsStrings=array();           
                $formatsParamsOfsearchGetMatchFormatsStrings[]="\${ip} \${doNotNeed} [\${day}/\${month}/\${year}:\${hour}:\${min}:\${sec} \${timezone}] \${method} \${path} \${protocol} \${responseCode} \${bytesSend}";
                
                #尋找 http code 為 4xx 的內容行
                #函式說明:
                #尋找多個字串中是否含有符合多個格式之一的內容,且回傳解析好的變數數值.
                #回傳結果:
                #$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
                #$reuslt["error"],執行不正常結束的錯訊息陣列.
                #$result["function"],當前執行的函式名稱.
                #$result["argu"],所使用的參數.
                #$result["found"],是否有找到符合格式的字串內容,"true"代表有找到,"false"代表沒有找到.
                #$result["content"],陣列,第一維為對應formats參數的索引,第二維的key為lineNo者為inputs參數的索引;第二維的key為content者為符合的資訊,若為n個${*},則當found為"true"時,就會回傳n個元素;第二維的key為parsedVar者為符合的資訊,其數值以變數名稱作為索引,元素的索引為0~N,代表有幾個符合的同名變數.
                #必填參數:
                #$conf["inputs"],字串陣列,要檢查的字串集合.
                $conf["search::getMatchFormatsStrings"]["inputs"]=$getFileContent["fileContent"];
                #$conf["format"],格式字串陣列,要尋找的可能格式字串集合.格式為固定的字串("fixedStr format")與變數("${keyWordVarName}")組成.
                $conf["search::getMatchFormatsStrings"]["formats"]=$formatsParamsOfsearchGetMatchFormatsStrings;
                #可省略參數:
                #無.
                #參考資料:
                #無.
                #備註:
                #無.
                $getMatchFormatsStrings=search::getMatchFormatsStrings($conf["search::getMatchFormatsStrings"]);
                unset($conf["search::getMatchFormatsStrings"]);

                #如果執行異常
                if($getMatchFormatsStrings["status"]==="false"){
                
                        #設置執行失敗
                        $result["status"]="false";

                        #設置錯誤訊息
                        $result["error"]=$getMatchFormatsStrings;

                        #回傳結果
                        return $result;
                
                        }#if end
                        
                #如果沒有符合的項目
                if($getMatchFormatsStrings["found"]==="false"){
                
                        #設置結果
                        $result["content"]=array();
                        
                        #設置執行正常
                        $result["status"]="true";
                
                        #回傳結果
                        return $result;
                
                        }#if end
                
                #初始化要處理的ip資訊
                $ips=array();
                
                #初始化用 ip 為索引來儲存資料行
                $ips_byIp=array();
                
                #針對每個符合的規則
                foreach($getMatchFormatsStrings["content"] as $matchInfo){
                        
                        #取得符合條件的行索引
                        $index=$matchInfo["lineNo"];
                
                        #取得用戶要求的method
                        $method=$matchInfo["parsedVar"][0]["method"][0];
                
                        #取得用戶要求的protocal
                        $protocol=$matchInfo["parsedVar"][0]["protocol"][0];
                
                        #取得回應的code
                        $responseCode=$matchInfo["parsedVar"][0]["responseCode"][0];
                        
                        #如果 method 為 "CONNECT"
                        if($method==="CONNECT"){
                        
                                #這裡不做事情,但後面繼續執行
                        
                                }#if end
                        
                        #如果 protocol 為 "HTTP/1.0"
                        else if($protocol==="HTTP/1.0"){
                        
                                #這裡不做事情,但後面繼續執行
                        
                                }#if end
                        
                        #如果回應的 code 不為 4 開頭
                        else if($responseCode[0]!=="4"){
                        
                                #略過,看下一行
                                continue;
                        
                                }#if end
                        
                        #取得用戶要求的路徑
                        $path=$matchInfo["parsedVar"][0]["path"][0];
                                
                        #剔除要求的資源名稱結尾為 ".css" ".js" "favicon.ico" ".jpg" ".png" 者. - start
                        
                        #函式說明:
                        #尋找字串中是否含有符合多個格式之一的內容,且回傳解析好的變數數值.
                        #回傳結果:
                        #$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
                        #$reuslt["error"],執行不正常結束的錯訊息陣列.
                        #$result["function"],當前執行的函式名稱.
                        #$result["argu"],所使用的參數.
                        #$result["found"],是否有找到符合格式的字串內容,"true"代表有找到,"false"代表沒有找到.
                        #$result["content"],陣列,若為n個${*},則當found為"true"時,就會回傳n個元素.
                        #必填參數:
                        #$conf["input"],字串,要檢查的字串.
                        $conf["search::findSpecifyStrFormats"]["input"]=$getFileContent["fileContent"][$index];
                        #$conf["format"],格式字串陣列,要尋找的可能格式字串集合.格式為固定的字串("fixedStr format")與變數("${keyWordVarName}")組成.
                        $conf["search::findSpecifyStrFormats"]["formats"]=array("\${str}.css","\${str}.js","\${str}.favicon.ico","\${str}.jpg","\${str}.jpeg","\${str}.png","\${str}.webp");
                        #可省略參數:
                        #無.
                        #參考資料:
                        #無.
                        #備註:
                        #無.
                        $findSpecifyStrFormats=search::findSpecifyStrFormats($conf["search::findSpecifyStrFormats"]);
                        unset($conf["search::findSpecifyStrFormats"]);
                        
                        #如果執行異常
                        if($findSpecifyStrFormats["status"]==="false"){
                        
                                #設置執行失敗
                                $result["status"]="false";

                                #設置錯誤訊息
                                $result["error"]=$findSpecifyStrFormats;

                                #回傳結果
                                return $result;
                        
                                }#if end
                                
                        #如果有符合的項目
                        if($findSpecifyStrFormats["found"]==="true"){
                        
                                #略過,看下一行
                                continue;
                        
                                }#if end
                                
                        #剔除要求的資源名稱結尾為 ".css" ".js" "favicon.ico" ".jpg" ".jpeg" ".png" ".webp" 者. - end
                        
                        #時間格式的參考
                        # [\${day}/\${month}/\${year}:\${hour}:\${min}:\${sec} \${timezone}]
                
                        #取得 log 的時間點
                        $time=$matchInfo["parsedVar"][0]["day"][0]."/".$matchInfo["parsedVar"][0]["month"][0]."/".$matchInfo["parsedVar"][0]["year"][0].":".$matchInfo["parsedVar"][0]["hour"][0].":".$matchInfo["parsedVar"][0]["min"][0].":".$matchInfo["parsedVar"][0]["sec"][0]." ".$matchInfo["parsedVar"][0]["timezone"][0];
                
                        #以 ip 為索引來儲存資料行
                        $ips_byIp[$matchInfo["parsedVar"][0]["ip"][0]][]=array("log"=>$getFileContent["fileContent"][$index],"time"=>$time,"ip"=>$matchInfo["parsedVar"][0]["ip"][0]);
                
                        }#foreach end

                #針對每個可能有問題的IP
                foreach($ips_byIp as $ip => $infos){

                        #計數 ip 於同時間前來的計數
                        $ipSameTimeCount=0;

                        #用來存放來存取的同一時間
                        $ipSameTime="";

                        #看來拜訪的時間點
                        foreach($infos as $info){

                                #如果是初次
                                if($ipSameTime===""){

                                        #記錄時間點
                                        $ipSameTime=$info["time"];

                                        #同時間點計數加1
                                        $ipSameTimeCount++;

                                        }#if end

                                #反之如果時間點相同
                                else if($ipSameTime===$info["time"]){

                                        #同時間點計數加1
                                        $ipSameTimeCount++;

                                        }#if end

                                #反之時間點不相同
                                else{

                                        #記錄時間點
                                        $ipSameTime=$info["time"];

                                        #同時間點計數重設為1
                                        $ipSameTimeCount=1;

                                        }#else end

                                #如果同時間的計數達到3
                                if($ipSameTimeCount===3){

                                        #初始化暫存的陣列
                                        $tmp=array();
                                        
                                        #儲存資訊
                                        $tmp["info"]=$infos;
                                        
                                        #儲存ip
                                        $tmp["ip"]=$info["ip"];

                                        #取得有問題的IP
                                        $ips[]=$tmp;

                                        #換檢查下一個IP
                                        continue 2;

                                        }#if end

                                }#foreach end

                        }#foreach end
                        
                #設置結果
                $result["content"]=$ips;
                
                #設置執行正常
                $result["status"]="true";
        
                #回傳結果
                return $result;
        
                }#funcion checkHttpAttackLog end
                
        /*
        #函式說明:
        #檢查 postfixv log 中疑似攻擊的記錄.
        #回傳結果:
        #$result["status"],字串,執行是否正常,"true"代表正常,"false"代表不正常.
        #$result["error"],錯誤訊息陣列.
        #$result["function"],字串,當前執行的函式名稱.
        #$result["content"],陣列,攻擊記錄資訊,每個元素為陣列key為"ip"者為攻擊者的ip;key為info者為其資訊陣列,其key為"log"者代表log的行內容;key為"time"者代表時間點;key為ip者代表ip.
        #必填參數:
        #無.
        #可省略參數:
        #無
        #參考資料:
        #無.
        #備註:
        #無.
        */
        public static function checkPostfixAttackLog(){
        
                #初始化要回傳的結果
                $result=array();

                #取得當前執行的函數名稱
                $result["function"]=__FUNCTION__;
        
                #透過 journalctl -a -e -f --unit=postfix.service | grep "authentication failed" 來取得認證失敗的 ip
                #函式說明:
                #呼叫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"]="journalctl";
                #$conf["fileArgu"],字串,變數__FILE__的內容.
                $conf["external::callShell"]["fileArgu"]=__FILE__;
                #可省略參數:
                #$conf["argu"],陣列字串,指令搭配的參數,預設為空陣列.
                $conf["external::callShell"]["argu"]=array("-a","-e","--unit=postfix.service","|","grep","authentication failed","|","cat");
                #$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".
                $conf["external::callShell"]["escapeshellarg"]="true";
                #$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";
                #備註:
                #不是所有指令都能用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"]);

                if($callShell["status"]==="false"){
                
                        #如果有 statusCode
                        if(isset($callShell["statusCode"])){
                        
                                #如果shell回傳不為0也不為1
                                if($callShell["statusCode"]!==0 && $callShell["statusCode"]!==1){
                                
                                        #設置執行失敗
                                        $result["status"]="false";

                                        #設置錯誤訊息
                                        $result["error"]=$callShell;

                                        #回傳結果
                                        return $result;
                                
                                        }#if end
                        
                                }#if end
                                
                        #設置執行失敗
                        $result["status"]="false";

                        #設置錯誤訊息
                        $result["error"]=$callShell;

                        #回傳結果
                        return $result;
                
                        }#if end

                #儲存有問題的smtp IP
                $ips_smtp=array();

                #狀態碼不為1才執行
                if($callShell["statusCode"]!==1){

                        #初始化記錄每行log的時間點
                        $occurTime=array();

                        #初始化儲存log行資訊的變數
                        $oriLog=array();

                        #根據每筆記錄
                        foreach($callShell["output"] as $index => $line){

                                #截取出的格式
                                #Sep 28 07:54:16 qbpwcf.org postfix/smtpd[2766456]: warning: unknown[158.94.208.72]: SASL LOGIN authentication failed: (reason unavailable), sasl_username=1q2w
                                #Sep 28 07:57:15 qbpwcf.org postfix/smtpd[2768441]: warning: unknown[213.209.157.249]: SASL LOGIN authentication failed: (reason unavailable), sasl_username=sybase
                                #Sep 28 08:01:09 qbpwcf.org postfix/smtpd[2771112]: warning: unknown[213.209.157.165]: SASL LOGIN authentication failed: (reason unavailable), sasl_username=spam
                                #Sep 28 08:01:51 qbpwcf.org postfix/smtpd[2771112]: warning: unknown[103.109.20.174]: SASL LOGIN authentication failed: (reason unavailable), sasl_username=print@qbpwcf.org
                                #Sep 28 08:03:14 qbpwcf.org postfix/smtpd[2771112]: warning: unknown[62.60.130.148]: SASL LOGIN authentication failed: (reason unavailable), sasl_username=admin2
                                #Sep 28 08:16:06 qbpwcf.org postfix/smtpd[2781279]: warning: unknown[103.109.20.174]: SASL LOGIN authentication failed: (reason unavailable), sasl_username=user@qbpwcf.org
                                #Sep 28 08:16:44 qbpwcf.org postfix/smtpd[2781279]: warning: unknown[178.16.53.142]: SASL LOGIN authentication failed: (reason unavailable), sasl_username=hualing@qbpwcf.org
                                #Sep 28 08:16:53 qbpwcf.org postfix/smtpd[2781279]: warning: unknown[178.16.53.142]: SASL LOGIN authentication failed: (reason unavailable), sasl_username=hualing@qbpwcf.org
                                #Sep 28 08:17:06 qbpwcf.org postfix/smtpd[2781279]: warning: unknown[178.16.53.142]: SASL LOGIN authentication failed: (reason unavailable), sasl_username=hualing@qbpwcf.org
                                #Sep 28 08:17:16 qbpwcf.org postfix/smtpd[2781279]: warning: unknown[178.16.53.142]: SASL LOGIN authentication failed: Connection lost to authentication server, sasl_username=hualing@qbpwcf.org
                                #Sep 28 08:20:28 qbpwcf.org postfix/smtpd[2784204]: warning: unknown[158.94.208.72]: SASL LOGIN authentication failed: (reason unavailable), sasl_username=1q2w1q2w
                                #Sep 28 08:23:09 qbpwcf.org postfix/smtpd[2785986]: warning: unknown[213.209.157.249]: SASL LOGIN authentication failed: (reason unavailable), sasl_username=informix
                                #Sep 28 08:23:39 qbpwcf.org postfix/smtpd[2785986]: warning: unknown[62.60.130.148]: SASL LOGIN authentication failed: (reason unavailable), sasl_username=admin3
                                #May 22 12:58:54 qbpwcf.org postfix/smtpd[2059124]: warning: unknown[80.94.95.242]: SASL LOGIN authentication failed: Invalid authentication mechanism: 'LOGIN', sasl_username=(unavailable)
                                #May 22 12:58:59 qbpwcf.org postfix/smtpd[2059124]: warning: unknown[80.94.95.242]: SASL PLAIN authentication failed: (reason unavailable), sasl_username=nonexistent_user_26@qbpwcf.org
                                #May 22 12:59:07 qbpwcf.org postfix/smtpd[2059124]: warning: unknown[80.94.95.242]: SASL PLAIN authentication failed: (reason unavailable), sasl_username=finance@qbpwcf.org#"${doNotNeed} postfix/smtpd[${pid}]${doNotNeed}[${ip}]"
                                
                                #用 " " 分割 以取得 月日時分秒
                                #函式說明:
                                #將固定格式的字串分開,並回傳分開的結果.
                                #回傳結果:
                                #$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
                                #$result["error"],錯誤訊息陣列
                                #$result["function"],當前執行的函數名稱.
                                #$result["argu"],使用的參數.
                                #$result["oriStr"],要分割的原始字串內容
                                #$result["dataArray"],爲分割好字串的陣列內容,$result["dataArray"][$i]爲第($i+1)段的內容。
                                #$result["dataCounts"],爲總共分成幾段
                                #$result["found"],是否有在$conf["stringIn"]找到$conf["spiltSymbol"],"true"代表有找到,"false"代表沒有找到.
                                #必填參數:
                                #$conf["stringIn"],字串,要處理的字串.
                                $conf["stringProcess::spiltString"]["stringIn"]=$line;
                                #$conf["spiltSymbol"],字串,爲以哪個符號作爲分割.
                                $conf["stringProcess::spiltString"]["spiltSymbol"]=" ";
                                #可省略參數:
                                #$conf["allowEmptyStr"],是否允許分割出來空字串,預設為"false"不允許;"true"代表允許.
                                #$conf["allowEmptyStr"]="false";
                                #參考資料:
                                #無.
                                #備註:
                                #無.
                                $spiltString=stringProcess::spiltString($conf["stringProcess::spiltString"]);
                                unset($conf["stringProcess::spiltString"]);

                                #如果分割失敗
                                if($spiltString["status"]==="false"){

                                        #設置執行失敗
                                        $result["status"]="false";

                                        #設置錯誤訊息
                                        $result["error"]=$spiltString;

                                        #回傳結果
                                        return $result;

                                        }#if end

                                #如果分割失敗
                                if($spiltString["dataCounts"]<3){

                                        #設置執行失敗
                                        $result["status"]="false";

                                        #設置錯誤訊息
                                        $result["error"]=$spiltString;

                                        #回傳結果
                                        return $result;

                                        }#if end

                                #儲存時間
                                $occurTime[$index]=strtotime($spiltString["dataArray"][0]." ".$spiltString["dataArray"][1]." ".$spiltString["dataArray"][2]);

                                #取得 ip
                                #函式說明:
                                #尋找字串中是否含有符合格式的內容,且回傳解析好的變數數值.
                                #回傳結果:
                                #$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
                                #$reuslt["error"],執行不正常結束的錯訊息陣列.
                                #$result["function"],當前執行的函式名稱.
                                #$result["argu"],所使用的參數.
                                #$result["found"],是否有找到符合格式的字串內容,"true"代表有找到,"false"代表沒有找到.
                                #$result["content"],陣列,若為n個${*},則當found為"true"時,就會回傳n個元素.
                                #$result["parsedVar"][varName],陣列,解析好的變數陣列,varName為${}中的內容.
                                #必填參數:
                                #$conf["input"],字串,要檢查的字串.
                                $conf["search::findSpecifyStrFormat"]["input"]=$line;
                                #$conf["format"],格式字串,要尋找的格式字串.格式為固定的字串("fixedStr format")與變數("${keyWordVarName}")組成.
                                $conf["search::findSpecifyStrFormat"]["format"]="\${doNotNeed} postfix/smtpd[\${pid}]\${doNotNeed}[\${ip}]:[\${reason}]";
                                #可省略參數:
                                #$conf["varEqual"],陣列,變數對應的數值,null代表不指定,其他內容代表該變數解析出來必須要為該內容.
                                #$conf["search::findSpecifyStrFormat"]["varEqual"]=array(null,"found");
                                #$conf["varCon"],陣列,每個varEqual為null者,其是否有其他條件,預設為null代表無其他條件,條件的表示是用陣列的key與value來表達,例如:array("no_tail"=>" not"),就代表變數的結尾不能為" not",可以用的key有"head",代表開頭要有什麼;"no_head",代表不能為什麼開頭;"tail",代表要什麼結尾;"no_tail",代表不能什麼結尾.
                                #$conf["varCon"]=array("no_tail"=>" not");
                                #參考資料:
                                #無.
                                #備註:
                                #無.
                                $findSpecifyStrFormat=search::findSpecifyStrFormat($conf["search::findSpecifyStrFormat"]);
                                unset($conf["search::findSpecifyStrFormat"]);

                                #如果分割失敗
                                if($findSpecifyStrFormat["status"]==="false"){

                                        #設置執行失敗
                                        $result["status"]="false";

                                        #設置錯誤訊息
                                        $result["error"]=$findSpecifyStrFormat;

                                        #回傳結果
                                        return $result;

                                        }#if end

                                #如果沒有符合格式
                                if($findSpecifyStrFormat["found"]==="false"){

                                        #剔除時間點 記錄
                                        array_pop($occurTime);

                                        #跳過該行
                                        continue;

                                        }#if end

                                #取得解析好的ip
                                $ip=$findSpecifyStrFormat["parsedVar"]["ip"];

                                #儲存原始的log行內容
                                $oriLog[$index]=$spiltMutiString["spiltString"][$index ]["oriStr"];

                                #初始化暫存的陣列
                                $tmp=array();

                                #設置log、time
                                $tmp["info"][]=array("log"=>$oriLog[$index],"time"=>$occurTime[$index]);

                                #設置問題ip
                                $tmp["ip"]=$ip;
                                
                                #取得所需的有問題的IP
                                $ips_smtp[]=$tmp;

                                }#foreach end

                        }#if end
        
                #設置結果
                $result["content"]=$ips_smtp;
        
                #設置執行正常
                $result["status"]="true";
                
                #回傳結果
                return $result;
        
                }#function checkPostfixAttackLog end

        /*
        #函式說明:
        #檢查 named log 中疑似攻擊的記錄.
        #回傳結果:
        #$result["status"],字串,執行是否正常,"true"代表正常,"false"代表不正常.
        #$result["error"],錯誤訊息陣列.
        #$result["function"],字串,當前執行的函式名稱.
        #$result["content"],陣列,攻擊記錄資訊,每個元素為陣列key為"ip"者為攻擊者的ip;key為info者為其資訊陣列,其key為"log"者代表log的行內容;key為"time"者代表時間點;key為ip者代表ip.
        #必填參數:
        #無.
        #可省略參數:
        #無
        #參考資料:
        #無.
        #備註:
        #無.
        */
        public static function checkNamedAttackLog(){
        
                #初始化要回傳的結果
                $result=array();

                #取得當前執行的函數名稱
                $result["function"]=__FUNCTION__;
        
                #透過 journalctl -a -e -f --unit=named.service | grep ' query ' 來取得 IP
                #函式說明:
                #呼叫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"]="journalctl";
                #$conf["fileArgu"],字串,變數__FILE__的內容.
                $conf["external::callShell"]["fileArgu"]=__FILE__;
                #可省略參數:
                #$conf["argu"],陣列字串,指令搭配的參數,預設為空陣列.
                $conf["external::callShell"]["argu"]=array("-a","-e","--unit=named.service","|","grep"," query ","|","cat");
                #$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".
                $conf["external::callShell"]["escapeshellarg"]="true";
                #$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";
                #備註:
                #不是所有指令都能用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"]);

                #如果執行失敗
                if($callShell["status"]==="false"){

                        #如果有 statusCode
                        if(isset($callShell["statusCode"])){
                        
                                #如果shell回傳不為0也不為1
                                if($callShell["statusCode"]!==0 && $callShell["statusCode"]!==1){
                                
                                        #設置執行失敗
                                        $result["status"]="false";

                                        #設置錯誤訊息
                                        $result["error"]=$callShell;

                                        #回傳結果
                                        return $result;
                                
                                        }#if end
                        
                                }#if end
                                
                        #設置執行失敗
                        $result["status"]="false";

                        #設置錯誤訊息
                        $result["error"]=$callShell;

                        #回傳結果
                        return $result;
                        
                        }#if end

                #記錄攻擊者的IP
                $attacker_ips_namd=array();

                #狀態碼不為1才執行
                if($callShell["statusCode"]!==1){

                        #截取出的格式
                        #Nov 24 20:55:15 localhost.localdomain named[99512]: client @0x7f7714041d10 191.7.219.100#6238 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied
                        #Nov 24 20:55:15 localhost.localdomain named[99512]: client @0x7f77180297c0 191.7.219.100#6238 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied
                        #Nov 24 20:55:15 localhost.localdomain named[99512]: client @0x7f7714041d10 191.7.219.100#6238 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied
                        #Nov 24 20:55:15 localhost.localdomain named[99512]: client @0x7f77180297c0 191.7.219.100#6238 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied
                        #Nov 24 20:55:15 localhost.localdomain named[99512]: client @0x7f7714041d10 191.7.219.100#6238 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied
                        #Nov 24 20:55:17 localhost.localdomain named[99512]: client @0x7f7714041d10 34.80.86.198#31220 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied
                        #Nov 24 20:55:17 localhost.localdomain named[99512]: client @0x7f7714041d10 34.80.86.198#31220 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied
                        #Nov 24 20:55:17 localhost.localdomain named[99512]: client @0x7f7714041d10 34.80.86.198#31220 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied
                        #Nov 24 20:55:17 localhost.localdomain named[99512]: client @0x7f77180297c0 34.80.86.198#31220 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied
                        #Nov 24 20:55:17 localhost.localdomain named[99512]: client @0x7f770c077bf0 34.80.86.198#31220 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied
                        #Nov 24 20:55:17 localhost.localdomain named[99512]: client @0x7f770c077bf0 191.7.219.100#8794 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied
                        #Nov 24 20:55:17 localhost.localdomain named[99512]: client @0x7f77180297c0 191.7.219.100#8794 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied
                        #Nov 24 20:55:17 localhost.localdomain named[99512]: client @0x7f770c077bf0 191.7.219.100#8794 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied
                        #Nov 24 20:55:17 localhost.localdomain named[99512]: client @0x7f7714041d10 191.7.219.100#8794 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied
                        #Nov 24 20:55:18 localhost.localdomain named[99512]: client @0x7f770c077bf0 5.29.224.190#10027 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied
                        #Nov 24 20:55:18 localhost.localdomain named[99512]: client @0x7f770c077bf0 5.29.224.190#10027 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied
                        #Nov 24 20:55:18 localhost.localdomain named[99512]: client @0x7f7714041d10 5.29.224.190#10027 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied
                        #Nov 24 20:55:18 localhost.localdomain named[99512]: client @0x7f77180297c0 5.29.224.190#10027 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied
                        #Nov 24 20:55:18 localhost.localdomain named[99512]: client @0x7f7714041d10 5.29.224.190#10027 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied
                        #Nov 24 20:55:18 localhost.localdomain named[99512]: client @0x7f77180297c0 5.29.224.190#10027 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied
                        #Nov 24 20:55:18 localhost.localdomain named[99512]: client @0x7f7714041d10 5.29.224.190#10027 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied
                        #Nov 24 20:55:22 localhost.localdomain named[99512]: client @0x7f7714041d10 123.253.64.16#54404 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied
                        #Nov 24 20:55:22 localhost.localdomain named[99512]: client @0x7f7714041d10 123.253.64.16#54404 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied
                        #Nov 24 20:55:22 localhost.localdomain named[99512]: client @0x7f7714041d10 123.253.64.16#54404 (PEACECORPS.GOV): query (cache) 'PEACECORPS.GOV/ANY/IN' denied
                        #Dec 14 18:51:45 localhost.localdomain named[1159]: client @0x7f3dc801bc80 61.220.11.198#40052 (dns.qbpwcf.org): query 'dns.qbpwcf.org/AAAA/IN' denied
                        #Dec 14 18:51:45 localhost.localdomain named[1159]: client @0x7f3dc8003700 61.220.11.198#48628 (aesopower-cms-sock-latest.qbpwcf.org): query 'aesopower-cms-sock-latest.qbpwcf.org/A/IN' denied
                        #Dec 14 18:51:45 localhost.localdomain named[1159]: client @0x7f3dc8003700 61.220.11.198#52460 (dns.qbpwcf.org): query 'dns.qbpwcf.org/AAAA/IN' denied
                        #Dec 14 18:51:45 localhost.localdomain named[1159]: client @0x7f3dc801bc80 61.220.11.198#60457 (aesopower-cms-sock-latest.qbpwcf.org): query 'aesopower-cms-sock-latest.qbpwcf.org/A/IN' denied
                        #Dec 14 18:51:45 localhost.localdomain named[1159]: client @0x7f3dc801bc80 61.220.11.198#10213 (dns.qbpwcf.org): query 'dns.qbpwcf.org/AAAA/IN' denied
                        #Dec 14 18:51:45 localhost.localdomain named[1159]: client @0x7f3dc801bc80 61.220.11.198#44377 (aesopower-cms-sock-latest.qbpwcf.org): query 'aesopower-cms-sock-latest.qbpwcf.org/A/IN' denied
                        #Dec 14 18:51:45 localhost.localdomain named[1159]: client @0x7f3dc8003700 61.220.11.198#4481 (dns.qbpwcf.org): query 'dns.qbpwcf.org/AAAA/IN' denied
                        #Dec 14 18:51:45 localhost.localdomain named[1159]: client @0x7f3dc8003700 61.220.11.198#53061 (aesopower-cms-sock-latest.qbpwcf.org): query 'aesopower-cms-sock-latest.qbpwcf.org/A/IN' denied
                        #Dec 14 18:51:45 localhost.localdomain named[1159]: client @0x7f3dc8003700 61.220.11.198#31654 (dns.qbpwcf.org): query 'dns.qbpwcf.org/AAAA/IN' denied
                        #Dec 14 18:51:45 localhost.localdomain named[1159]: client @0x7f3dc802a410 61.220.11.198#57701 (aesopower-cms-sock-latest.qbpwcf.org): query 'aesopower-cms-sock-latest.qbpwcf.org/A/IN' denied
                        #Sep 29 03:37:20 dns.qbpwcf.org named[94]: client @0x7f60e00734e8 61.166.210.84#49954 (twitter.com): query failed (REFUSED) for twitter.com/IN/AAAA at ../../../lib/ns/query.c:5691
                        #Sep 29 03:37:20 dns.qbpwcf.org named[94]: client @0x7f60e006f428 61.166.210.84#49954 (twitter.com): query failed (REFUSED) for twitter.com/IN/A at ../../../lib/ns/query.c:5691
                        #Sep 29 03:37:21 dns.qbpwcf.org named[94]: client @0x7f60e80889a8 61.166.210.84#50057 (astrill4u.com): query failed (REFUSED) for astrill4u.com/IN/AAAA at ../../../lib/ns/query.c:5691
                        #Sep 29 03:37:21 dns.qbpwcf.org named[94]: client @0x7f60e805ed08 61.166.210.84#50057 (astrill4u.com): query failed (REFUSED) for astrill4u.com/IN/A at ../../../lib/ns/query.c:5691
                        #Sep 29 03:46:33 dns.qbpwcf.org named[94]: client @0x7f60d402b618 165.22.223.147#16200 (tool.lu): query failed (REFUSED) for tool.lu/IN/A at ../../../lib/ns/query.c:5691
                        #Sep 29 03:49:16 dns.qbpwcf.org named[94]: client @0x7f60e0060a28 76.20.229.207#80 (sl): query failed (REFUSED) for sl/IN/ANY at ../../../lib/ns/query.c:5691
                        #Sep 29 04:19:10 dns.qbpwcf.org named[94]: client @0x7f60e0060a28 76.20.229.207#80 (sl): query failed (REFUSED) for sl/IN/ANY at ../../../lib/ns/query.c:5691
                        #Sep 29 04:20:28 dns.qbpwcf.org named[94]: client @0x7f60e0060a28 76.20.229.207#80 (sl): query failed (REFUSED) for sl/IN/ANY at ../../../lib/ns/query.c:5691
                        #Sep 29 04:24:20 dns.qbpwcf.org named[94]: client @0x7f60e0060a28 76.20.229.207#80 (sl): query failed (REFUSED) for sl/IN/ANY at ../../../lib/ns/query.c:5691
                        #Sep 29 04:24:59 dns.qbpwcf.org named[94]: client @0x7f60e0060a28 76.20.229.207#80 (sl): query failed (REFUSED) for sl/IN/ANY at ../../../lib/ns/query.c:5691
                        #Sep 29 04:40:48 dns.qbpwcf.org named[94]: client @0x7f60f9377888 174.96.56.126#80 (sl): query failed (REFUSED) for sl/IN/ANY at ../../../lib/ns/query.c:5691
                        #${month} ${day} ${hour}:${min}:${sec} ${doNotNeed} client ${doNotNeed} ${ip}#${remoteRevPort} (${$queryTarget}): ${doNotNeed}

                        #函式說明:
                        #檢查多個字串中的每個字串是否有多個關鍵字
                        #回傳結果:
                        #$result["status"],整體來說,執行是否成功,"true"代表執行成功,"false"代表執行失敗。
                        #$result["function"],當前執行的函數名稱.
                        #$result["error"],錯誤訊息.
                        #$result["argu"],使用的參數.
                        #$result["foundedTrueKey"],結果為"true"的被搜尋元素key陣列,與其數值內容.
                        #$result["foundedKeyWords"],找到的關鍵字陣列.
                        #$result["foundedFalseKey"],結果為"false"的被搜尋元素key陣列,與其數值內容.
                        #$result["foundedTrueKeyWords"],二維陣列,各個字串有找到的關鍵字陣列.
                        #$result["foundedAll"],是否每個關鍵字都有找到,"true"代表每個都有找到,"false"代表沒有每個都找到.
                        #$result["keyWordsIncludeStr"],陣列,儲存有找到關鍵字的來源的索引(sourceIndex)與其內容(sourceVal)跟找到的關鍵字項目陣列(KeyWords).
                        #必填參數:
                        #$conf["keyWords"],字串陣列,想要搜尋的關鍵字.
                        $conf["search::findManyKeyWordsFromManyString"]["keyWords"]=array("(REFUSED)"," denied");
                        #$conf["stringArray"],字串陣列,要被搜尋的字串內容陣列.
                        $conf["search::findManyKeyWordsFromManyString"]["stringArray"]=$callShell["output"];
                        #可省略參數:
                        #$conf["completeEqual"],字串,是否內容要完全符合,不能多出任何不符合的內容,預設為"false"不需要完全符合.
                        #$conf["completeEqual"]="true";
                        #參考資料:
                        #無.
                        #備註:
                        #無.
                        $findManyKeyWordsFromManyString=search::findManyKeyWordsFromManyString($conf["search::findManyKeyWordsFromManyString"]);
                        unset($conf["search::findManyKeyWordsFromManyString"]);

                        #如果執行失敗
                        if($findManyKeyWordsFromManyString["status"]==="false"){

                                #設置執行失敗
                                $result["status"]="false";

                                #設置錯誤訊息
                                $result["error"]=$findManyKeyWordsFromManyString;

                                #回傳結果
                                return $result;

                                }#if end

                        #初始化儲存原始log行內容
                        #$oriLog=array();

                        #儲存疑似有問題的IP
                        $ips_named=array();

                        #初始化儲存確定有問題的ip
                        $attacker_ips_namd=array();

                        #針對每個符合的行
                        foreach($findManyKeyWordsFromManyString["foundedTrueKey"] as $oriLog){

                                #初始化儲存資訊的暫存陣列
                                $info=array();

                                #解析時間與來源ip
                                #函式說明:
                                #尋找字串中是否含有符合格式的內容,且回傳解析好的變數數值.
                                #回傳結果:
                                #$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
                                #$reuslt["error"],執行不正常結束的錯訊息陣列.
                                #$result["function"],當前執行的函式名稱.
                                #$result["argu"],所使用的參數.
                                #$result["found"],是否有找到符合格式的字串內容,"true"代表有找到,"false"代表沒有找到.
                                #$result["content"],陣列,若為n個${*},則當found為"true"時,就會回傳n個元素.
                                #$result["parsedVar"][varName],陣列,解析好的變數陣列,varName為${}中的內容.
                                #必填參數:
                                #$conf["input"],字串,要檢查的字串.
                                $conf["search::findSpecifyStrFormat"]["input"]=$oriLog;
                                #$conf["format"],格式字串,要尋找的格式字串.格式為固定的字串("fixedStr format")與變數("${keyWordVarName}")組成.
                                $conf["search::findSpecifyStrFormat"]["format"]="\${month} \${day} \${hour}:\${min}:\${sec} \${doNotNeed} client \${doNotNeed} \${ip}#\${remoteRevPort} (\${queryTarget}): \${doNotNeed}";
                                #可省略參數:
                                #$conf["varEqual"],陣列,變數對應的數值,null代表不指定,其他內容代表該變數解析出來必須要為該內容.
                                #$conf["search::findSpecifyStrFormat"]["varEqual"]=array(null,"found");
                                #$conf["varCon"],陣列,每個varEqual為null者,其是否有其他條件,預設為null代表無其他條件,條件的表示是用陣列的key與value來表達,例如:array("no_tail"=>" not"),就代表變數的結尾不能為" not",可以用的key有"head",代表開頭要有什麼;"no_head",代表不能為什麼開頭;"tail",代表要什麼結尾;"no_tail",代表不能什麼結尾.
                                #$conf["varCon"]=array("no_tail"=>" not");
                                #參考資料:
                                #無.
                                #備註:
                                #無.
                                $findSpecifyStrFormat=search::findSpecifyStrFormat($conf["search::findSpecifyStrFormat"]);
                                unset($conf["search::findSpecifyStrFormat"]);

                                #如果分割失敗
                                if($findSpecifyStrFormat["status"]==="false"){

                                        #設置執行失敗
                                        $result["status"]="false";

                                        #設置錯誤訊息
                                        $result["error"]=$findSpecifyStrFormat;

                                        #回傳結果
                                        return $result;

                                        }#if end

                                #如果沒有符合格式
                                if($findSpecifyStrFormat["found"]==="false"){

                                        #跳過該行
                                        continue;

                                        }#if end

                                #儲存時間點
                                $info["time"]=$findSpecifyStrFormat["parsedVar"]["month"][0]." ".$findSpecifyStrFormat["parsedVar"]["day"][0]." ".$findSpecifyStrFormat["parsedVar"]["hour"][0].":".$findSpecifyStrFormat["parsedVar"]["min"][0].":".$findSpecifyStrFormat["parsedVar"]["sec"][0];

                                #儲存ip
                                $info["ip"]=$findSpecifyStrFormat["parsedVar"]["ip"][0];

                                #儲存log
                                $info["log"]=$oriLog;

                                #儲存查詢的目標
                                $info["queryTarget"]=$findSpecifyStrFormat["parsedVar"]["queryTarget"][0];

                                #儲存疑似有問題的ip
                                $ips_named[$info["ip"]][]=$info;

                                }#foreach end

                        #針對每個可能有問題ip的每個log行
                        foreach($ips_named as $ip => $infos){

                                #初始化記錄ip來訪不大於1分鐘的計數
                                $count=0;

                                #初始化記錄歷史log跟time
                                $history=array();

                                #針對每個log行資訊
                                foreach($infos as $index => $info){

                                        #unixtime
                                        $time=strtotime($info["time"]);

                                        #如果沒有下筆記錄
                                        if(!isset($infos[$index+1])){

                                                #結束 foreach
                                                break;

                                                }#if end

                                        #取得unixtime
                                        $next_time=strtotime($infos[$index+1]["time"]);

                                        #如果時間間隔大於60秒
                                        if($next_time-$time>60){

                                                #跳過,看下筆記錄
                                                continue;

                                                }#if end

                                        #計數+1
                                        $count++;
                                        
                                        #記錄歷史資訊
                                        $history[]=array("time"=>$time,"log"=>$info["log"]);

                                        }#foreach end

                                #如果有達到3次
                                if($count>=3){

                                        #初始化暫存的陣列
                                        $tmp=array();
                                        
                                        #設置ip
                                        $tmp["ip"]=$ip;
                                        
                                        #設置info
                                        $tmp["info"]=$history;

                                        #記錄攻擊者的IP
                                        $attacker_ips_namd[]=$tmp;

                                        }#if end

                                }#foreach end

                        }#if end

                #設置結果
                $result["content"]=$attacker_ips_namd;
        
                #設置執行正常
                $result["status"]="true";
                
                #回傳結果
                return $result;
        
                }#function checkNamedAttackLog end
                
        /*
        #函式說明:
        #檢查 dovecot log 中疑似攻擊的記錄.
        #回傳結果:
        #$result["status"],字串,執行是否正常,"true"代表正常,"false"代表不正常.
        #$result["error"],錯誤訊息陣列.
        #$result["function"],字串,當前執行的函式名稱.
        #$result["content"],陣列,攻擊記錄資訊,每個元素為陣列key為"ip"者為攻擊者的ip;key為info者為其資訊陣列,其key為"log"者代表log的行內容;key為"time"者代表時間點;key為ip者代表ip.
        #必填參數:
        #無.
        #可省略參數:
        #無
        #參考資料:
        #無.
        #備註:
        #無.
        */
        public static function checkDovecotAttackLog(){
        
                #初始化要回傳的結果
                $result=array();

                #取得當前執行的函數名稱
                $result["function"]=__FUNCTION__;
                
                #透過 journalctl -a -e --unit=dovecot.service 來取得 IP
                #函式說明:
                #呼叫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"]="journalctl";
                #$conf["fileArgu"],字串,變數__FILE__的內容.
                $conf["external::callShell"]["fileArgu"]=__FILE__;
                #可省略參數:
                #$conf["argu"],陣列字串,指令搭配的參數,預設為空陣列.
                $conf["external::callShell"]["argu"]=array("-a","-e","--unit=dovecot.service");
                #$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".
                $conf["external::callShell"]["escapeshellarg"]="true";
                #$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";
                #備註:
                #不是所有指令都能用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"]);

                #如果執行失敗
                if($callShell["status"]==="false"){

                        #如果有 statusCode
                        if(isset($callShell["statusCode"])){
                        
                                #如果shell回傳不為0也不為1
                                if($callShell["statusCode"]!==0 && $callShell["statusCode"]!==1){
                                
                                        #設置執行失敗
                                        $result["status"]="false";

                                        #設置錯誤訊息
                                        $result["error"]=$callShell;

                                        #回傳結果
                                        return $result;
                                
                                        }#if end
                        
                                }#if end
                                
                        #設置執行失敗
                        $result["status"]="false";

                        #設置錯誤訊息
                        $result["error"]=$callShell;

                        #回傳結果
                        return $result;
                        
                        }#if end
                        
                #記錄攻擊者的IP
                $attacker_ips_imap=array();

                /* $callShell["output"] 範例截取結果
                Feb 23 00:24:58 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<MxQuPu+73xpliNc9>
                Feb 23 00:24:58 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<hH8xPu+7dBtliNc9>
                Feb 23 00:24:58 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<nmI0Pu+7zhtliNc9>
                Feb 23 00:24:58 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<1GU2Pu+7NBhliNc9>
                Feb 23 00:24:59 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 1 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<0Io5Pu+7sRhliNc9>
                Feb 23 00:24:59 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<zbQ+Pu+7rhlliNc9>
                Feb 23 00:24:59 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<0P5APu+7/BlliNc9>
                Feb 23 00:24:59 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<gKRDPu+7XhpliNc9>
                Feb 23 00:24:59 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<4hNHPu+77hpliNc9>
                Feb 23 00:25:00 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<belIPu+7bBtliNc9>
                Feb 23 00:25:00 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<VhRLPu+7xBtliNc9>
                Feb 23 00:46:19 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<loiMiu+7cxhliNc9>
                Feb 23 00:46:19 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<RNCQiu+7/xhliNc9>
                Feb 23 00:46:20 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 1 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<NWCTiu+7PBlliNc9>
                Feb 23 00:46:20 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<2tiViu+7hBlliNc9>
                Feb 23 00:46:20 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<w6Sbiu+7/xlliNc9>
                Feb 23 00:46:21 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<SkWkiu+7gBtliNc9>
                Feb 23 00:46:21 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<bGCmiu+7qBtliNc9>
                Feb 23 00:46:21 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<0E+oiu+76RtliNc9>
                Feb 23 00:46:21 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<FBGriu+7UhhliNc9>
                Feb 23 00:46:21 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<AeSsiu+7iBhliNc9>
                Feb 23 00:46:21 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<gpSuiu+70hhliNc9>
                Feb 23 01:40:38 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<zYfITPC7RBlliNc9>
                Feb 23 01:40:38 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<GULMTPC7zhlliNc9>
                Feb 23 01:40:38 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<3jjOTPC7CBpliNc9>
                Feb 23 01:40:38 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<vhHQTPC7UBpliNc9>
                Feb 23 01:40:38 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<vArTTPC7rxpliNc9>
                Feb 23 01:40:39 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<hDTXTPC7GhtliNc9>
                Feb 23 01:40:39 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<c6vZTPC7SRtliNc9>
                Feb 23 01:40:39 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<rQzcTPC7jBtliNc9>
                Feb 23 01:40:39 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<LSffTPC78htliNc9>
                Feb 23 01:40:39 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<XLThTPC7KBhliNc9>
                Feb 23 01:40:40 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<tZfjTPC7dxhliNc9>
                Feb 23 03:27:10 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<i3bIyfG7AxtliNc9>
                Feb 23 03:27:11 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<0sLVyfG7uxtliNc9>
                Feb 23 03:27:11 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<BJXZyfG7BhhliNc9>
                Feb 23 03:27:11 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<xK3cyfG7SxhliNc9>
                Feb 23 03:27:12 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 1 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<q43gyfG7aRhliNc9>
                Feb 23 03:27:12 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<Oj3syfG7FBlliNc9>
                Feb 23 03:27:12 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<SF7uyfG7RhlliNc9>
                Feb 23 03:27:13 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 1 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<IM/wyfG7ZRlliNc9>
                Feb 23 03:27:13 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<pXv1yfG7vBlliNc9>
                Feb 23 03:27:13 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<8ub4yfG7/xlliNc9>
                Feb 23 03:27:13 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<H0j7yfG7NRpliNc9>
                Feb 23 06:10:07 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 1 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<Zw6FEPS7WxhliNc9>
                Feb 23 06:10:08 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 1 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<vmKTEPS7cRpliNc9>
                Feb 23 06:10:08 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<SkOXEPS7BxtliNc9>
                Feb 23 06:10:08 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<H42bEPS7WRtliNc9>
                Feb 23 06:10:09 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<jFqoEPS7SRhliNc9>
                Feb 23 06:10:10 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<TNy4EPS7DhpliNc9>
                Feb 23 06:10:10 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<JYW7EPS7mBpliNc9>
                Feb 23 06:10:10 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=</Ve+EPS76hpliNc9>
                Feb 23 06:10:11 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<StLGEPS7qhtliNc9>
                Feb 23 06:10:11 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<7RnLEPS7DBhliNc9>
                Feb 23 06:10:11 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<6xTOEPS7eBhliNc9>
                Feb 23 06:29:27 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<YHy0VfS7uBhliNc9>
                Feb 23 06:29:28 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<WLW4VfS7fxlliNc9>
                Feb 23 06:29:28 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<lM66VfS73BlliNc9>
                Feb 23 06:29:28 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<Q4K9VfS7NxpliNc9>
                Feb 23 06:29:28 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<JiLBVfS7rRpliNc9>
                Feb 23 06:29:29 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<DETIVfS7qxtliNc9>
                Feb 23 06:29:29 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<UlLLVfS7GhhliNc9>
                Feb 23 06:29:29 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<safNVfS7txhliNc9>
                Feb 23 06:29:29 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<M/DQVfS7LxlliNc9>
                Feb 23 06:29:29 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<+zPTVfS7eRlliNc9>
                Feb 23 06:29:30 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 1 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<dxXWVfS72hlliNc9>
                Feb 23 06:44:28 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 1 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<S0pci/S7SxhliNc9>
                Feb 23 06:44:28 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<zThji/S78RhliNc9>
                Feb 23 06:44:28 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<8PJoi/S7ixlliNc9>
                Feb 23 06:44:29 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<Qkhui/S7PBpliNc9>
                Feb 23 06:44:29 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<SXVzi/S7hhtliNc9>
                Feb 23 06:44:29 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=</X55i/S7uhhliNc9>
                Feb 23 06:44:30 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<MHJ9i/S74hlliNc9>
                Feb 23 06:44:30 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<RBWBi/S7pRpliNc9>
                Feb 23 06:44:30 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<NJeGi/S7yhtliNc9>
                Feb 23 06:44:31 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<QsaMi/S7rxhliNc9>
                Feb 23 06:44:31 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<8fiPi/S7uBlliNc9>
                Feb 23 07:01:29 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 1 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<dt04yPS7KBlliNc9>
                Feb 23 07:01:29 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<ZMI9yPS7WxpliNc9>
                Feb 23 07:01:29 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<nTVAyPS7ARtliNc9>
                Feb 23 07:01:29 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<wj1CyPS7lxtliNc9>
                Feb 23 07:01:29 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<u7RFyPS7YRhliNc9>
                Feb 23 07:01:30 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<tpBLyPS7ZhlliNc9>
                Feb 23 07:01:30 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<CRdOyPS7wxlliNc9>
                Feb 23 07:01:30 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<v9NQyPS7JxpliNc9>
                Feb 23 07:01:30 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<81lUyPS73hpliNc9>
                Feb 23 07:01:31 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<PCZXyPS7TRtliNc9>
                Feb 23 07:01:31 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<VnNZyPS7qxtliNc9>
                Feb 23 07:14:28 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 1 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<op+l9vS7ZxhliNc9>
                Feb 23 07:14:28 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<aBCr9vS7CBlliNc9>
                Feb 23 07:14:28 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<0sOt9vS7dRlliNc9>
                Feb 23 07:14:28 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<NFaw9vS7xhlliNc9>
                Feb 23 07:14:28 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<QS609vS7SRpliNc9>
                Feb 23 07:14:29 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<4FW79vS76htliNc9>
                Feb 23 07:14:29 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<Fxu+9vS7gBhliNc9>
                Feb 23 07:14:29 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<3djA9vS75RhliNc9>
                Feb 23 07:14:30 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 1 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<hgzE9vS7mxlliNc9>
                Feb 23 07:14:30 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<J8TG9vS7GBpliNc9>
                Feb 23 07:14:30 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<t87I9vS7mBpliNc9>
                Feb 23 07:29:27 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<1xBILPW7MRtliNc9>
                Feb 23 07:29:28 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<IXZNLPW79htliNc9>
                Feb 23 07:29:28 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<6OdPLPW7chhliNc9>
                Feb 23 07:29:28 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<M5BSLPW78hhliNc9>
                Feb 23 07:29:28 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<Nv9VLPW7UxlliNc9>
                Feb 23 07:29:29 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<foJbLPW7KRpliNc9>
                Feb 23 07:29:29 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<EoVeLPW7nxpliNc9>
                Feb 23 07:29:29 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<DwNhLPW7JRtliNc9>
                Feb 23 07:29:29 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<mKhkLPW7ohtliNc9>
                Feb 23 07:29:29 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<3nhnLPW7/htliNc9>
                Feb 23 07:29:30 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 1 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<e+lpLPW7XRhliNc9>
                Feb 23 07:44:27 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<KtTtYfW7dBhliNc9>
                Feb 23 07:44:28 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<MLTxYfW77BhliNc9>
                Feb 23 07:44:28 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<9GL0YfW7KBlliNc9>
                Feb 23 07:44:28 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<JNT2YfW7fRlliNc9>
                Feb 23 07:44:28 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<8Zv5YfW72RlliNc9>
                Feb 23 07:44:29 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<lbv/YfW73BpliNc9>
                Feb 23 07:44:29 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<5zsCYvW7EBtliNc9>
                Feb 23 07:44:29 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<aE8EYvW7bRtliNc9>
                Feb 23 07:44:29 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<LEIHYvW75RtliNc9>
                Feb 23 07:44:29 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<rLsJYvW7MRhliNc9>
                Feb 23 07:44:29 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<9oMMYvW7ihhliNc9>
                Feb 23 07:59:28 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 1 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<x7SUl/W7mBpliNc9>
                Feb 23 07:59:28 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<k1KZl/W73xtliNc9>
                Feb 23 07:59:28 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<Veabl/W7PxhliNc9>
                Feb 23 07:59:28 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<Yamel/W7sxhliNc9>
                Feb 23 07:59:28 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<wpGil/W7OBlliNc9>
                Feb 23 07:59:29 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<+VCol/W7aBpliNc9>
                Feb 23 07:59:29 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<TMaql/W7zhpliNc9>
                Feb 23 07:59:29 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<KnKtl/W7GBtliNc9>
                Feb 23 07:59:29 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<Lkixl/W7ixtliNc9>
                Feb 23 07:59:30 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 1 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<8bWzl/W7ARhliNc9>
                Feb 23 07:59:30 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<70q2l/W7PBhliNc9>
                Sep 29 06:53:42 qbpwcf.org dovecot[98]: imap-login: Disconnected: Connection closed (no auth attempts in 0 secs): user=<>, rip=3.231.151.171, lip=169.254.2.1, TLS, session=<MaKQGOs/wIMD55er>
                Sep 29 07:42:58 qbpwcf.org auth[3737748]: pam_unix(dovecot:auth): check pass; user unknown
                Sep 29 07:42:58 qbpwcf.org auth[3737748]: pam_unix(dovecot:auth): authentication failure; logname=liveuser uid=0 euid=0 tty=dovecot ruser=account@qbpwcf.org rhost=62.60.131.29
                Sep 29 08:10:02 qbpwcf.org dovecot[98]: imap(liveuser)<3755807><SvyIKew/xLpyIuFn>: Disconnected: Connection closed (UID SEARCH finished 0.039 secs ago) in=119 out=1504 deleted=0 expunged=0 trashed=0 hdr_count=0 hdr_bytes=0 body_count=0 body_bytes=0
                Sep 29 08:12:02 qbpwcf.org dovecot[98]: imap-login: Login: user=<liveuser>, method=PLAIN, rip=149.102.158.38, lip=169.254.2.1, mpid=3757116, TLS, session=<B2O9MOw/TrmVZp4m>
                Sep 29 08:12:04 qbpwcf.org dovecot[98]: imap(liveuser)<3757116><B2O9MOw/TrmVZp4m>: Disconnected: Logged out in=240 out=21891 deleted=0 expunged=0 trashed=0 hdr_count=0 hdr_bytes=0 body_count=0 body_bytes=0
                Sep 29 08:12:06 qbpwcf.org dovecot[98]: imap-login: Login: user=<liveuser>, method=PLAIN, rip=149.102.158.38, lip=169.254.2.1, mpid=3757144, TLS, session=<S0rwMOw/XLmVZp4m>
                Sep 29 08:12:09 qbpwcf.org dovecot[98]: imap(liveuser)<3757144><S0rwMOw/XLmVZp4m>: Disconnected: Logged out in=885 out=25454 deleted=0 expunged=0 trashed=0 hdr_count=2 hdr_bytes=21658 body_count=0 body_bytes=0
                Sep 29 08:28:48 qbpwcf.org dovecot[98]: imap-login: Login: user=<liveuser>, method=PLAIN, rip=114.34.225.103, lip=169.254.2.1, mpid=3768144, TLS, session=<Gk6ybOw/nNpyIuFn>
                Sep 29 08:28:51 qbpwcf.org dovecot[98]: imap(liveuser)<3768144><Gk6ybOw/nNpyIuFn>: Disconnected: Connection closed (LIST finished 1.939 secs ago) in=50 out=17609 deleted=0 expunged=0 trashed=0 hdr_count=0 hdr_bytes=0 body_count=0 body_bytes=0
                Sep 29 08:28:51 qbpwcf.org dovecot[98]: imap-login: Login: user=<liveuser>, method=PLAIN, rip=114.34.225.103, lip=169.254.2.1, mpid=3768149, TLS, session=<ct7bbOw/qtpyIuFn>
                Sep 29 08:28:52 qbpwcf.org dovecot[98]: imap(liveuser)<3768149><ct7bbOw/qtpyIuFn>: Disconnected: Connection closed (UID FETCH finished 0.045 secs ago) in=196 out=2381 deleted=0 expunged=0 trashed=0 hdr_count=0 hdr_bytes=0 body_count=0 body_bytes=0
                Sep 29 08:28:53 qbpwcf.org dovecot[98]: imap-login: Login: user=<liveuser>, method=PLAIN, rip=114.34.225.103, lip=169.254.2.1, mpid=3768155, TLS, session=<DvP1bOw/tNpyIuFn>
                Sep 29 08:28:55 qbpwcf.org dovecot[98]: imap(liveuser)<3768155><DvP1bOw/tNpyIuFn>: Disconnected: Connection closed (UID SEARCH finished 0.180 secs ago) in=119 out=1504 deleted=0 expunged=0 trashed=0 hdr_count=0 hdr_bytes=0 body_count=0 body_bytes=0
                Sep 29 08:39:24 qbpwcf.org auth[3775219]: pam_unix(dovecot:auth): check pass; user unknown
                Sep 29 08:39:24 qbpwcf.org auth[3775219]: pam_unix(dovecot:auth): authentication failure; logname=liveuser uid=0 euid=0 tty=dovecot ruser=test rhost=196.251.92.78
                Sep 29 08:40:44 qbpwcf.org auth[3776113]: pam_unix(dovecot:auth): check pass; user unknown
                Sep 29 08:40:44 qbpwcf.org auth[3776113]: pam_unix(dovecot:auth): authentication failure; logname=liveuser uid=0 euid=0 tty=dovecot ruser=1q2w3e4r5t4567 rhost=158.94.208.72
                Sep 29 08:41:18 qbpwcf.org auth[3776113]: pam_unix(dovecot:auth): check pass; user unknown
                Sep 29 08:41:18 qbpwcf.org auth[3776113]: pam_unix(dovecot:auth): authentication failure; logname=liveuser uid=0 euid=0 tty=dovecot ruser=spam rhost=62.60.130.148
                */

                #認證失敗的關鍵字
                $keyWordAF="authentication failure";

                #未認證或SSL錯誤
                $keyWordNAA="no auth attempts";

                #搜尋符合關鍵字的log行
                #函式說明:
                #檢查多個字串中的每個字串是否有多個關鍵字
                #回傳結果:
                #$result["status"],整體來說,執行是否成功,"true"代表執行成功,"false"代表執行失敗。
                #$result["function"],當前執行的函數名稱.
                #$result["error"],錯誤訊息.
                #$result["argu"],使用的參數.
                #$result["foundedTrueKey"],結果為"true"的被搜尋元素key陣列,與其數值內容.
                #$result["foundedKeyWords"],找到的關鍵字陣列.
                #$result["foundedFalseKey"],結果為"false"的被搜尋元素key陣列,與其數值內容.
                #$result["foundedTrueKeyWords"],二維陣列,各個字串有找到的關鍵字陣列.
                #$result["foundedAll"],是否每個關鍵字都有找到,"true"代表每個都有找到,"false"代表沒有每個都找到.
                #$result["keyWordsIncludeStr"],陣列,儲存有找到關鍵字的來源的索引(sourceIndex)與其內容(sourceVal)跟找到的關鍵字項目陣列(KeyWords).
                #必填參數:
                #$conf["keyWords"],字串陣列,想要搜尋的關鍵字.
                $conf["search::findManyKeyWordsFromManyString"]["keyWords"]=array($keyWordAF,$keyWordNAA);
                #$conf["stringArray"],字串陣列,要被搜尋的字串內容陣列.
                $conf["search::findManyKeyWordsFromManyString"]["stringArray"]=$callShell["output"];
                #可省略參數:
                #$conf["completeEqual"],字串,是否內容要完全符合,不能多出任何不符合的內容,預設為"false"不需要完全符合.
                #$conf["completeEqual"]="true";
                #參考資料:
                #無.
                #備註:
                #無.
                $findManyKeyWordsFromManyString=search::findManyKeyWordsFromManyString($conf["search::findManyKeyWordsFromManyString"]);
                unset($conf["search::findManyKeyWordsFromManyString"]);

                #如果執行失敗
                if($findManyKeyWordsFromManyString["status"]==="false"){

                        #設置執行失敗
                        $result["status"]="false";

                        #設置錯誤訊息
                        $result["error"]=$findManyKeyWordsFromManyString;

                        #回傳結果
                        return $result;

                        }#if end

                #初始化儲存可能有問題的存取Dovecot服務遠端ip
                $rickyIpsOfDocecot=array();

                #針對每個符合的log行
                foreach($findManyKeyWordsFromManyString["foundedTrueKey"] as $index => $oriLog){

                        #找到的關鍵字
                        $foundKeyWord=$findManyKeyWordsFromManyString["foundedTrueKeyWords"][$index][0];

                        #依照符合的關鍵字
                        switch($foundKeyWord){

                                #如果是認證失敗
                                case $keyWordAF:

                                        #範例
                                        #Sep 29 08:41:18 qbpwcf.org auth[3776113]: pam_unix(dovecot:auth): authentication failure; logname=liveuser uid=0 euid=0 tty=dovecot ruser=spam rhost=62.60.130.148
                                        #${month} ${day} ${hour}:${min}:${sec} ${doNotNeed} : authentication failure; logname=${account} ${doNotNeed} rhost=${ip}

                                        #取得時間點跟遠端IP
                                        #函式說明:
                                        #尋找字串中是否含有符合格式的內容,且回傳解析好的變數數值.
                                        #回傳結果:
                                        #$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
                                        #$reuslt["error"],執行不正常結束的錯訊息陣列.
                                        #$result["function"],當前執行的函式名稱.
                                        #$result["argu"],所使用的參數.
                                        #$result["found"],是否有找到符合格式的字串內容,"true"代表有找到,"false"代表沒有找到.
                                        #$result["content"],陣列,若為n個${*},則當found為"true"時,就會回傳n個元素.
                                        #$result["parsedVar"][varName],陣列,解析好的變數陣列,varName為${}中的內容.
                                        #必填參數:
                                        #$conf["input"],字串,要檢查的字串.
                                        $conf["search::findSpecifyStrFormat"]["input"]=$oriLog;
                                        #$conf["format"],格式字串,要尋找的格式字串.格式為固定的字串("fixedStr format")與變數("${keyWordVarName}")組成.
                                        $conf["search::findSpecifyStrFormat"]["format"]="\${month} \${day} \${hour}:\${min}:\${sec} \${doNotNeed} : authentication failure; logname=\${account} \${doNotNeed} rhost=\${ip}";
                                        #可省略參數:
                                        #$conf["varEqual"],陣列,變數對應的數值,null代表不指定,其他內容代表該變數解析出來必須要為該內容.
                                        #$conf["search::findSpecifyStrFormat"]["varEqual"]=array(null,"found");
                                        #$conf["varCon"],陣列,每個varEqual為null者,其是否有其他條件,預設為null代表無其他條件,條件的表示是用陣列的key與value來表達,例如:array("no_tail"=>" not"),就代表變數的結尾不能為" not",可以用的key有"head",代表開頭要有什麼;"no_head",代表不能為什麼開頭;"tail",代表要什麼結尾;"no_tail",代表不能什麼結尾.
                                        #$conf["varCon"]=array("no_tail"=>" not");
                                        #參考資料:
                                        #無.
                                        #備註:
                                        #無.
                                        $findSpecifyStrFormat=search::findSpecifyStrFormat($conf["search::findSpecifyStrFormat"]);
                                        unset($conf["search::findSpecifyStrFormat"]);

                                        #如果分割失敗
                                        if($findSpecifyStrFormat["status"]==="false"){

                                                #設置執行失敗
                                                $result["status"]="false";

                                                #設置錯誤訊息
                                                $result["error"]=$findSpecifyStrFormat;

                                                #回傳結果
                                                return $result;

                                                }#if end

                                        #如果沒有符合格式
                                        if($findSpecifyStrFormat["found"]==="false"){

                                                #跳過該行
                                                continue 2;

                                                }#if end

                                        #取得時間點
                                        $time=$findSpecifyStrFormat["parsedVar"]["month"][0]." ".$findSpecifyStrFormat["parsedVar"]["day"][0]." ".$findSpecifyStrFormat["parsedVar"]["hour"][0].":".$findSpecifyStrFormat["parsedVar"]["min"][0].":".$findSpecifyStrFormat["parsedVar"]["sec"][0];

                                        #取得ip
                                        $ip=$findSpecifyStrFormat["parsedVar"]["ip"][0];

                                        #儲存其資訊
                                        $rickyIpsOfDocecot[$ip][]=array("time"=>$time,"ip"=>$ip,"log"=>$oriLog);

                                        #跳出  switch
                                        break;

                                #如果是未認證或SSL錯誤
                                case $keyWordNAA:

                                        #範例
                                        #Feb 23 07:59:30 localhost.localdomain dovecot[1427]: imap-login: Disconnected (no auth attempts in 0 secs): user=<>, rip=101.136.215.61, lip=169.254.1.1, TLS handshaking: SSL_accept() failed: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown: SSL alert number 46, session=<70q2l/W7PBhliNc9>
                                        #Sep 29 06:53:42 qbpwcf.org dovecot[98]: imap-login: Disconnected: Connection closed (no auth attempts in 0 secs): user=<>, rip=3.231.151.171, lip=169.254.2.1, TLS, session=<MaKQGOs/wIMD55er>
                                        #${month} ${day} ${hour}:${min}:${sec} ${doNotNeed} ( no auth attempts in ${doNotNeed} user=<${account}>, rip=${ip}, ${doNotNeed}

                                        #取得時間點跟遠端IP
                                        #函式說明:
                                        #尋找字串中是否含有符合格式的內容,且回傳解析好的變數數值.
                                        #回傳結果:
                                        #$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
                                        #$reuslt["error"],執行不正常結束的錯訊息陣列.
                                        #$result["function"],當前執行的函式名稱.
                                        #$result["argu"],所使用的參數.
                                        #$result["found"],是否有找到符合格式的字串內容,"true"代表有找到,"false"代表沒有找到.
                                        #$result["content"],陣列,若為n個${*},則當found為"true"時,就會回傳n個元素.
                                        #$result["parsedVar"][varName],陣列,解析好的變數陣列,varName為${}中的內容.
                                        #必填參數:
                                        #$conf["input"],字串,要檢查的字串.
                                        $conf["search::findSpecifyStrFormat"]["input"]=$oriLog;
                                        #$conf["format"],格式字串,要尋找的格式字串.格式為固定的字串("fixedStr format")與變數("${keyWordVarName}")組成.
                                        $conf["search::findSpecifyStrFormat"]["format"]="\${month} \${day} \${hour}:\${min}:\${sec} \${doNotNeed} ( no auth attempts in \${doNotNeed} user=<\${account}>, rip=\${ip}, \${doNotNeed}";
                                        #可省略參數:
                                        #$conf["varEqual"],陣列,變數對應的數值,null代表不指定,其他內容代表該變數解析出來必須要為該內容.
                                        #$conf["search::findSpecifyStrFormat"]["varEqual"]=array(null,"found");
                                        #$conf["varCon"],陣列,每個varEqual為null者,其是否有其他條件,預設為null代表無其他條件,條件的表示是用陣列的key與value來表達,例如:array("no_tail"=>" not"),就代表變數的結尾不能為" not",可以用的key有"head",代表開頭要有什麼;"no_head",代表不能為什麼開頭;"tail",代表要什麼結尾;"no_tail",代表不能什麼結尾.
                                        #$conf["varCon"]=array("no_tail"=>" not");
                                        #參考資料:
                                        #無.
                                        #備註:
                                        #無.
                                        $findSpecifyStrFormat=search::findSpecifyStrFormat($conf["search::findSpecifyStrFormat"]);
                                        unset($conf["search::findSpecifyStrFormat"]);

                                        #如果分割失敗
                                        if($findSpecifyStrFormat["status"]==="false"){

                                                #設置執行失敗
                                                $result["status"]="false";

                                                #設置錯誤訊息
                                                $result["error"]=$findSpecifyStrFormat;

                                                #回傳結果
                                                return $result;

                                                }#if end

                                        #如果沒有符合格式
                                        if($findSpecifyStrFormat["found"]==="false"){

                                                #跳過該行
                                                continue 2;

                                                }#if end

                                        #取得時間點
                                        $time=$findSpecifyStrFormat["parsedVar"]["month"][0]." ".$findSpecifyStrFormat["parsedVar"]["day"][0]." ".$findSpecifyStrFormat["parsedVar"]["hour"][0].":".$findSpecifyStrFormat["parsedVar"]["min"][0].":".$findSpecifyStrFormat["parsedVar"]["sec"][0];

                                        #取得ip
                                        $ip=$findSpecifyStrFormat["parsedVar"]["ip"][0];

                                        #儲存其資訊
                                        $rickyIpsOfDocecot[$ip][]=array("time"=>$time,"ip"=>$ip,"log"=>$oriLog);

                                        #跳出  switch
                                        break;

                                #不應該執行到這邊
                                default:

                                        #設置執行失敗
                                        $result["status"]="false";

                                        #設置錯誤訊息
                                        $result["error"][]="unexpected error";

                                        #設置錯誤訊息
                                        $result["error"][]=$findManyKeyWordsFromManyString;

                                        #回傳結果
                                        return $result;

                                }#switch end

                        }#foreach end

                #初始化儲存可能有問題的ip資訊
                $risky_ips=array();

                #針對每個ip
                foreach($rickyIpsOfDocecot as $ip => $info){

                        #如果同樣ip不到3次
                        if(count($rickyIpsOfDocecot[$ip])<3){

                                #換看下個ip
                                continue;

                                }#if end

                        #儲存可能有問題的ip資訊
                        $risky_ips[]=$rickyIpsOfDocecot[$ip];

                        }#foreach end

                #針對每個可能有問題ip的每個log行
                foreach($risky_ips as $ip => $infos){

                        #初始化暫存歷史資訊的陣列
                        $history=array();

                        #初始化記錄ip來訪不大於1分鐘的計數
                        $count=0;

                        #針對每個log行資訊
                        foreach($infos as $index => $info){

                                #unixtime
                                $time=strtotime($info["time"]);

                                #如果沒有下筆記錄
                                if(!isset($infos[$index+1])){

                                        #結束 foreach
                                        break;

                                        }#if end

                                #取得unixtime
                                $next_time=strtotime($infos[$index+1]["time"]);

                                #如果時間間隔大於60秒
                                if($next_time-$time>60){

                                        #跳過,看下筆記錄
                                        continue;

                                        }#if end

                                #計數+1
                                $count++;

                                #記錄該次事件資訊
                                $history[]=array("time"=>$time,"log"=>$info["log"]);

                                }#foreach end

                        #如果有達到3次
                        if($count>=3){

                                #初始化陣列
                                $tmp=array();

                                #記錄ip
                                $tmp["ip"]=$ip;

                                #記錄歷史資訊
                                $tmp["info"]=$history;

                                #記錄攻擊者的IP
                                $attacker_ips_imap[]=$ip;

                                }#if end

                        }#foreach end
                        
                #設置結果
                $result["content"]=$attacker_ips_imap;
        
                #設置執行正常
                $result["status"]="true";
                
                #回傳結果
                return $result;
        
                }#function checkDovecotAttackLog end
                
        /*
        #函式說明:
        #檢查 ssh log 中疑似攻擊的記錄.
        #回傳結果:
        #$result["status"],字串,執行是否正常,"true"代表正常,"false"代表不正常.
        #$result["error"],錯誤訊息陣列.
        #$result["function"],字串,當前執行的函式名稱.
        #$result["content"],陣列,攻擊記錄資訊,每個元素為陣列key為"ip"者為攻擊者的ip;key為info者為其資訊陣列,其key為"log"者代表log的行內容;key為"time"者代表時間點;key為ip者代表ip.
        #必填參數:
        #無.
        #可省略參數:
        #無
        #參考資料:
        #無.
        #備註:
        #無.
        */
        public static function checkSshAttackLog(){
        
                #初始化要回傳的結果
                $result=array();

                #取得當前執行的函數名稱
                $result["function"]=__FUNCTION__;
        
                #記錄ssh攻擊者的IP
                $attacker_ips_ssh=array();

                #透過 journalctl -a -e --unit=sshd.service來取得 ssh 攻擊者的 IP
                #函式說明:
                #呼叫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"]="journalctl";
                #$conf["fileArgu"],字串,變數__FILE__的內容.
                $conf["external::callShell"]["fileArgu"]=__FILE__;
                #可省略參數:
                #$conf["argu"],陣列字串,指令搭配的參數,預設為空陣列.
                $conf["external::callShell"]["argu"]=array("-a","-e","--unit=sshd.service");
                #$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".
                $conf["external::callShell"]["escapeshellarg"]="true";
                #$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";
                #備註:
                #不是所有指令都能用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"]);

                #如果執行失敗
                if($callShell["status"]==="false"){

                        #如果有 statusCode
                        if(isset($callShell["statusCode"])){
                        
                                #如果shell回傳不為0也不為1
                                if($callShell["statusCode"]!==0 && $callShell["statusCode"]!==1){
                                
                                        #設置執行失敗
                                        $result["status"]="false";

                                        #設置錯誤訊息
                                        $result["error"]=$callShell;

                                        #回傳結果
                                        return $result;
                                
                                        }#if end
                        
                                }#if end
                                
                        #設置執行失敗
                        $result["status"]="false";

                        #設置錯誤訊息
                        $result["error"]=$callShell;

                        #回傳結果
                        return $result;
                        
                        }#if end

                /*
                得到的範例輸出
                Sep 30 00:36:36 silverblue-guest.qbpwcf.org sshd-session[1607010]: Invalid user lizepeng from 60.213.10.69 port 39156
                Sep 30 00:36:36 silverblue-guest.qbpwcf.org sshd-session[1607010]: pam_unix(sshd:auth): check pass; user unknown
                Sep 30 00:36:36 silverblue-guest.qbpwcf.org sshd-session[1607010]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=60.213.10.69
                Sep 30 00:36:38 silverblue-guest.qbpwcf.org sshd-session[1607010]: Failed password for invalid user lizepeng from 60.213.10.69 port 39156 ssh2
                Sep 30 00:36:40 silverblue-guest.qbpwcf.org sshd-session[1607010]: Connection closed by invalid user lizepeng 60.213.10.69 port 39156 [preauth]
                Sep 30 05:54:01 silverblue-guest.qbpwcf.org sshd-session[2346022]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=60.213.10.81  user=root
                Sep 30 05:54:03 silverblue-guest.qbpwcf.org sshd-session[2346022]: Failed password for root from 60.213.10.81 port 41644 ssh2
                Sep 30 05:54:04 silverblue-guest.qbpwcf.org sshd-session[2346022]: Connection closed by authenticating user root 60.213.10.81 port 41644 [preauth]
                Sep 30 05:54:20 silverblue-guest.qbpwcf.org sshd-session[2346860]: Invalid user qy from 60.213.10.81 port 42960
                Sep 30 05:54:21 silverblue-guest.qbpwcf.org sshd-session[2346860]: pam_unix(sshd:auth): check pass; user unknown
                Sep 30 05:54:21 silverblue-guest.qbpwcf.org sshd-session[2346860]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=60.213.10.81
                Sep 30 05:54:22 silverblue-guest.qbpwcf.org sshd-session[2346860]: Failed password for invalid user qy from 60.213.10.81 port 42960 ssh2
                Sep 30 05:54:23 silverblue-guest.qbpwcf.org sshd-session[2346860]: Connection closed by invalid user qy 60.213.10.81 port 42960 [preauth]
                Sep 30 06:08:06 silverblue-guest.qbpwcf.org sshd-session[2378295]: Connection closed by 167.94.145.105 port 55712 [preauth]
                Sep 30 08:09:51 silverblue-guest.qbpwcf.org sshd-session[2662907]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=183.13.207.69  user=root
                Sep 30 08:09:54 silverblue-guest.qbpwcf.org sshd-session[2662907]: Failed password for root from 183.13.207.69 port 18258 ssh2
                Sep 30 08:09:54 silverblue-guest.qbpwcf.org sshd-session[2662907]: Connection closed by authenticating user root 183.13.207.69 port 18258 [preauth]
                Sep 30 08:10:11 silverblue-guest.qbpwcf.org sshd-session[2663658]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=183.13.207.69  user=root
                Sep 30 08:10:13 silverblue-guest.qbpwcf.org sshd-session[2663658]: Failed password for root from 183.13.207.69 port 17293 ssh2
                Sep 30 08:10:13 silverblue-guest.qbpwcf.org sshd-session[2663658]: Connection closed by authenticating user root 183.13.207.69 port 17293 [preauth]
                */

                #認證失敗的關鍵字
                $keyWordFP=" Failed password ";

                #不存在使用者的關鍵字
                $keyWordIU=" Invalid user ";

                #搜尋符合關鍵字的log行
                #函式說明:
                #檢查多個字串中的每個字串是否有多個關鍵字
                #回傳結果:
                #$result["status"],整體來說,執行是否成功,"true"代表執行成功,"false"代表執行失敗。
                #$result["function"],當前執行的函數名稱.
                #$result["error"],錯誤訊息.
                #$result["argu"],使用的參數.
                #$result["foundedTrueKey"],結果為"true"的被搜尋元素key陣列,與其數值內容.
                #$result["foundedKeyWords"],找到的關鍵字陣列.
                #$result["foundedFalseKey"],結果為"false"的被搜尋元素key陣列,與其數值內容.
                #$result["foundedTrueKeyWords"],二維陣列,各個字串有找到的關鍵字陣列.
                #$result["foundedAll"],是否每個關鍵字都有找到,"true"代表每個都有找到,"false"代表沒有每個都找到.
                #$result["keyWordsIncludeStr"],陣列,儲存有找到關鍵字的來源的索引(sourceIndex)與其內容(sourceVal)跟找到的關鍵字項目陣列(KeyWords).
                #必填參數:
                #$conf["keyWords"],字串陣列,想要搜尋的關鍵字.
                $conf["search::findManyKeyWordsFromManyString"]["keyWords"]=array($keyWordFP,$keyWordIU);
                #$conf["stringArray"],字串陣列,要被搜尋的字串內容陣列.
                $conf["search::findManyKeyWordsFromManyString"]["stringArray"]=$callShell["output"];
                #可省略參數:
                #$conf["completeEqual"],字串,是否內容要完全符合,不能多出任何不符合的內容,預設為"false"不需要完全符合.
                #$conf["completeEqual"]="true";
                #參考資料:
                #無.
                #備註:
                #無.
                $findManyKeyWordsFromManyString=search::findManyKeyWordsFromManyString($conf["search::findManyKeyWordsFromManyString"]);
                unset($conf["search::findManyKeyWordsFromManyString"]);

                #如果執行失敗
                if($findManyKeyWordsFromManyString["status"]==="false"){

                        #設置執行失敗
                        $result["status"]="false";

                        #設置錯誤訊息
                        $result["error"]=$findManyKeyWordsFromManyString;

                        #回傳結果
                        return $result;

                        }#if end

                #初始化儲存可能有問題的存取ssh服務遠端ip
                $risky_ips=array();

                #針對每個符合的log行
                foreach($findManyKeyWordsFromManyString["foundedTrueKey"] as $index => $oriLog){

                        #找到的關鍵字
                        $foundKeyWord=$findManyKeyWordsFromManyString["foundedTrueKeyWords"][$index][0];

                        #依照符合的關鍵字
                        switch($foundKeyWord){

                                #如果是秘密碼錯誤
                                case $keyWordFP:

                                        #範例
                                        #Sep 30 08:10:13 silverblue-guest.qbpwcf.org sshd-session[2663658]: Failed password for root from 183.13.207.69 port 17293 ssh2
                                        #${month} ${day} ${hour}:${min}:${sec} ${doNotNeed} Failed password for ${account} from ${ip} ${doNotNeed}

                                        #取得時間點跟遠端IP
                                        #函式說明:
                                        #尋找字串中是否含有符合格式的內容,且回傳解析好的變數數值.
                                        #回傳結果:
                                        #$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
                                        #$reuslt["error"],執行不正常結束的錯訊息陣列.
                                        #$result["function"],當前執行的函式名稱.
                                        #$result["argu"],所使用的參數.
                                        #$result["found"],是否有找到符合格式的字串內容,"true"代表有找到,"false"代表沒有找到.
                                        #$result["content"],陣列,若為n個${*},則當found為"true"時,就會回傳n個元素.
                                        #$result["parsedVar"][varName],陣列,解析好的變數陣列,varName為${}中的內容.
                                        #必填參數:
                                        #$conf["input"],字串,要檢查的字串.
                                        $conf["search::findSpecifyStrFormat"]["input"]=$oriLog;
                                        #$conf["format"],格式字串,要尋找的格式字串.格式為固定的字串("fixedStr format")與變數("${keyWordVarName}")組成.
                                        $conf["search::findSpecifyStrFormat"]["format"]="\${month} \${day} \${hour}:\${min}:\${sec} \${doNotNeed} Failed password for \${account} from \${ip} \${doNotNeed}";
                                        #可省略參數:
                                        #$conf["varEqual"],陣列,變數對應的數值,null代表不指定,其他內容代表該變數解析出來必須要為該內容.
                                        #$conf["search::findSpecifyStrFormat"]["varEqual"]=array(null,"found");
                                        #$conf["varCon"],陣列,每個varEqual為null者,其是否有其他條件,預設為null代表無其他條件,條件的表示是用陣列的key與value來表達,例如:array("no_tail"=>" not"),就代表變數的結尾不能為" not",可以用的key有"head",代表開頭要有什麼;"no_head",代表不能為什麼開頭;"tail",代表要什麼結尾;"no_tail",代表不能什麼結尾.
                                        #$conf["varCon"]=array("no_tail"=>" not");
                                        #參考資料:
                                        #無.
                                        #備註:
                                        #無.
                                        $findSpecifyStrFormat=search::findSpecifyStrFormat($conf["search::findSpecifyStrFormat"]);
                                        unset($conf["search::findSpecifyStrFormat"]);

                                        #如果分割失敗
                                        if($findSpecifyStrFormat["status"]==="false"){

                                                #設置執行失敗
                                                $result["status"]="false";

                                                #設置錯誤訊息
                                                $result["error"]=$findSpecifyStrFormat;

                                                #回傳結果
                                                return $result;

                                                }#if end

                                        #如果沒有符合格式
                                        if($findSpecifyStrFormat["found"]==="false"){

                                                #跳過該行
                                                continue 2;

                                                }#if end

                                        #取得時間點
                                        $time=$findSpecifyStrFormat["parsedVar"]["month"][0]." ".$findSpecifyStrFormat["parsedVar"]["day"][0]." ".$findSpecifyStrFormat["parsedVar"]["hour"][0].":".$findSpecifyStrFormat["parsedVar"]["min"][0].":".$findSpecifyStrFormat["parsedVar"]["sec"][0];

                                        #取得ip
                                        $ip=$findSpecifyStrFormat["parsedVar"]["ip"][0];

                                        #儲存其資訊
                                        $risky_ips[$ip][]=array("time"=>$time,"ip"=>$ip,"log"=>$oriLog);

                                        #跳出  switch
                                        break;

                                #如果是不存在的使用者
                                case $keyWordIU:

                                        #範例
                                        #Sep 30 00:36:36 silverblue-guest.qbpwcf.org sshd-session[1607010]: Invalid user lizepeng from 60.213.10.69 port 39156
                                        #${month} ${day} ${hour}:${min}:${sec} ${doNotNeed} Invalid user ${account} from ${ip} port ${doNotNeed}

                                        #取得時間點跟遠端IP
                                        #函式說明:
                                        #尋找字串中是否含有符合格式的內容,且回傳解析好的變數數值.
                                        #回傳結果:
                                        #$result["status"],執行是否正常,"true"代表正常,"false"代表不正常.
                                        #$reuslt["error"],執行不正常結束的錯訊息陣列.
                                        #$result["function"],當前執行的函式名稱.
                                        #$result["argu"],所使用的參數.
                                        #$result["found"],是否有找到符合格式的字串內容,"true"代表有找到,"false"代表沒有找到.
                                        #$result["content"],陣列,若為n個${*},則當found為"true"時,就會回傳n個元素.
                                        #$result["parsedVar"][varName],陣列,解析好的變數陣列,varName為${}中的內容.
                                        #必填參數:
                                        #$conf["input"],字串,要檢查的字串.
                                        $conf["search::findSpecifyStrFormat"]["input"]=$oriLog;
                                        #$conf["format"],格式字串,要尋找的格式字串.格式為固定的字串("fixedStr format")與變數("${keyWordVarName}")組成.
                                        $conf["search::findSpecifyStrFormat"]["format"]="\${month} \${day} \${hour}:\${min}:\${sec} \${doNotNeed} Invalid user \${account} from \${ip} port \${doNotNeed}";
                                        #可省略參數:
                                        #$conf["varEqual"],陣列,變數對應的數值,null代表不指定,其他內容代表該變數解析出來必須要為該內容.
                                        #$conf["search::findSpecifyStrFormat"]["varEqual"]=array(null,"found");
                                        #$conf["varCon"],陣列,每個varEqual為null者,其是否有其他條件,預設為null代表無其他條件,條件的表示是用陣列的key與value來表達,例如:array("no_tail"=>" not"),就代表變數的結尾不能為" not",可以用的key有"head",代表開頭要有什麼;"no_head",代表不能為什麼開頭;"tail",代表要什麼結尾;"no_tail",代表不能什麼結尾.
                                        #$conf["varCon"]=array("no_tail"=>" not");
                                        #參考資料:
                                        #無.
                                        #備註:
                                        #無.
                                        $findSpecifyStrFormat=search::findSpecifyStrFormat($conf["search::findSpecifyStrFormat"]);
                                        unset($conf["search::findSpecifyStrFormat"]);

                                        #如果分割失敗
                                        if($findSpecifyStrFormat["status"]==="false"){

                                                #設置執行失敗
                                                $result["status"]="false";

                                                #設置錯誤訊息
                                                $result["error"]=$findSpecifyStrFormat;

                                                #回傳結果
                                                return $result;

                                                }#if end

                                        #如果沒有符合格式
                                        if($findSpecifyStrFormat["found"]==="false"){

                                                #跳過該行
                                                continue 2;

                                                }#if end

                                        #取得時間點
                                        $time=$findSpecifyStrFormat["parsedVar"]["month"][0]." ".$findSpecifyStrFormat["parsedVar"]["day"][0]." ".$findSpecifyStrFormat["parsedVar"]["hour"][0].":".$findSpecifyStrFormat["parsedVar"]["min"][0].":".$findSpecifyStrFormat["parsedVar"]["sec"][0];

                                        #取得ip
                                        $ip=$findSpecifyStrFormat["parsedVar"]["ip"][0];

                                        #儲存其資訊
                                        $risky_ips[$ip][]=array("time"=>$time,"ip"=>$ip,"log"=>$oriLog);

                                        #跳出  switch
                                        break;

                                #不應該執行到這邊
                                default:

                                        #設置執行失敗
                                        $result["status"]="false";

                                        #設置錯誤訊息
                                        $result["error"][]="unexpected error";

                                        #設置錯誤訊息
                                        $result["error"][]=$findManyKeyWordsFromManyString;

                                        #回傳結果
                                        return $result;

                                }#switch end

                        }#foreach end

                #針對每個可能有問題ip的每個log行
                foreach($risky_ips as $ip => $infos){

                        #初始化暫存歷史記錄的陣列
                        $history=array();

                        #初始化記錄ip來訪不大於1分鐘的計數
                        $count=0;

                        #針對每個log行資訊
                        foreach($infos as $index => $info){

                                #unixtime
                                $time=strtotime($info["time"]);

                                #如果沒有下筆記錄
                                if(!isset($infos[$index+1])){

                                        #結束 foreach
                                        break;

                                        }#if end

                                #取得unixtime
                                $next_time=strtotime($infos[$index+1]["time"]);

                                #如果下筆時間記錄與當前這筆間隔大於60秒
                                if($next_time-$time>60){

                                        #跳過,看下筆記錄
                                        continue;

                                        }#if end

                                #計數+1
                                $count++;
                                
                                #記錄該次記錄
                                $history[]=array("time"=>$time,"log"=>$info["log"]);

                                }#foreach end

                        #如果有達到3次
                        if($count>=3){

                                #初始化暫存的陣列
                                $tmp=array();
                                
                                #取得資訊
                                $tmp["info"]=$history;
                                
                                #取得問題ip
                                $tmp["ip"]=$ip;

                                #記錄攻擊者的IP
                                $attacker_ips_ssh[]=$tmp;

                                }#if end

                        }#foreach end
        
                #設置結果
                $result["content"]=$attacker_ips_ssh;
        
                #設置執行正常
                $result["status"]="true";
                
                #回傳結果
                return $result;
        
                }#function checkSshAttackLog end

        }#class security end

?>