Subversion Repositories qbpwcf-lib(archive)

Rev

Rev 883 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

#!/usr/bin/php
<?php

/*
        QBPWCF, Quick Build PHP website Component base on Fedora Linux.
    Copyright (C) 2015~2024 Min-Jhin,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/>.
    
*/

/*

計算檔案的checksum in 16 位元

參考資料:
https://www.programmersought.com/article/41936075398/
https://www.twblogs.net/a/5d3f3d47bd9eee51fbf902b2
https://www.itread01.com/content/1547685555.html

*/

#指派命名空間
namespace qbpwcf;

#以該檔案的實際位置的 lib path 為 include path 首位
exec("cd ".pathinfo(__FILE__)["dirname"]."/../lib;pwd;",$output,$status);
set_include_path($output[0].PATH_SEPARATOR.get_include_path());

#匯入外部套件
include("allInOne.php");

#如果沒有指定檔案參數
if(!isset($_SERVER["argv"][1]))
{
        echo "檔案參數是必須的".PHP_EOL;
        exit;

}#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["filePositionAndName"]=$_SERVER["argv"][1];
#$conf["fileArgu"],字串,php變數__FILE__的內容,亦即該檔案在檔案系統的絕對路徑
$conf["fileArgu"]=__FILE__;
#可省略參數:
#$conf["web"],是要取得網路上的檔案則為"true";反之則為"false".
$conf["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);
unset($conf);

#如果檔案取得失敗
if($getFileContent["status"]==="false")
{
        #印出內容
        var_dump($getFileContent);

        #結束執行
        exit;
}

#取得檔案的bytes長度
$fileBytes=strlen($getFileContent["fullContent"]);

#取得checksum bytes 1 的位置
$checksumAddr1=(int)($fileBytes/2);

#取得checksum bytes 2 的位置
$checksumAddr2=(int)($fileBytes/2)+1;

#取得checksum的第一個bytes位置
$checksumBytes1=$getFileContent["fullContent"][$checksumAddr1];

#取得checksum的第二個bytes位置
$checksumBytes2=$getFileContent["fullContent"][$checksumAddr2];

#將 checksum 位置的內容設置為 00
$getFileContent["fullContent"][$checksumAddr1]=chr(base_convert("00",16,10)); 
$getFileContent["fullContent"][$checksumAddr2]=chr(base_convert("00",16,10)); 

#存放結果變數
$sumOfHex4num=0;

#迴圈
for($i=0;$i<$fileBytes;$i=$i+2)
{
        #不存在就用00替補
        if(!isset($getFileContent["fullContent"][$i+1]))
        {
                $getFileContent["fullContent"][$i+1]="00";
        }
        
        #取得4個bytes的16進位數值
        $hex2bytes=sprintf("%02s",base_convert(ord($getFileContent["fullContent"][$i]),10,16)).sprintf("%02s",base_convert(ord($getFileContent["fullContent"][$i+1]),10,16));

        #加總
        $sumOfHex4num=$sumOfHex4num+(int)base_convert($hex2bytes,16,10);

}#for end

#更新成16進位
$sumOfHex4num=base_convert($sumOfHex4num,10,16);

#儲存加總的地方
$newSumOfHex4num=0;

#如果加總之後的長度大於4
while(strlen($sumOfHex4num)>4)
{
        #如果長度不是4的倍數
        if(strlen($sumOfHex4num)%4!==0)
        {
                //前面補一個0
                $sumOfHex4num="0".$sumOfHex4num;
                
                //繼續while
                continue;
        }

        for($i=0;$i<strlen($sumOfHex4num);$i=$i+4)
        {
                #取得4個的16進位數值
                $hex2bytes=$sumOfHex4num[$i].$sumOfHex4num[$i+1].$sumOfHex4num[$i+2].$sumOfHex4num[$i+3];

                #加總
                $newSumOfHex4num=$newSumOfHex4num+base_convert($hex2bytes,16,10);

        }#for end
        
        #更新成16進位
        $newSumOfHex4num=base_convert($newSumOfHex4num,10,16);
        
        #設置回儲存加總的地方
        $sumOfHex4num=$newSumOfHex4num;

}#while end

#取得 16 bit checksum
$checksumIn16bit=sprintf("%04s",base_convert(base_convert("ffff",16,10)-base_convert($sumOfHex4num,16,10),10,16));

#將 checksum 位置的內容設置為 checksum1 跟 checksum2
$getFileContent["fullContent"][$checksumAddr1]=$checksumBytes1;
$getFileContent["fullContent"][$checksumAddr2]=$checksumBytes2;

#存放結果變數
$sumOfHex4num=0;

#迴圈
for($i=0;$i<$fileBytes;$i=$i+2)
{
        #不存在就用00替補
        if(!isset($getFileContent["fullContent"][$i+1]))
        {
                $getFileContent["fullContent"][$i+1]="00";
        }
        
        #取得4個bytes的16進位數值
        $hex2bytes=sprintf("%02s",base_convert(ord($getFileContent["fullContent"][$i]),10,16)).sprintf("%02s",base_convert(ord($getFileContent["fullContent"][$i+1]),10,16));

        #加總
        $sumOfHex4num=$sumOfHex4num+(int)base_convert($hex2bytes,16,10);

}#for end

#更新成16進位
$sumOfHex4num=base_convert($sumOfHex4num,10,16);

#儲存加總的地方
$newSumOfHex4num=0;

#如果加總之後的長度大於4
while(strlen($sumOfHex4num)>4)
{
        #如果長度不是4的倍數
        if(strlen($sumOfHex4num)%4!==0)
        {
                //前面補一個0
                $sumOfHex4num="0".$sumOfHex4num;
                
                //繼續while
                continue;
        }

        for($i=0;$i<strlen($sumOfHex4num);$i=$i+4)
        {
                #取得4個的16進位數值
                $hex2bytes=$sumOfHex4num[$i].$sumOfHex4num[$i+1].$sumOfHex4num[$i+2].$sumOfHex4num[$i+3];

                #加總
                $newSumOfHex4num=$newSumOfHex4num+base_convert($hex2bytes,16,10);

        }#for end
        
        #更新成16進位
        $newSumOfHex4num=base_convert($newSumOfHex4num,10,16);
        
        #設置回儲存加總的地方
        $sumOfHex4num=$newSumOfHex4num;

}#while end

#取得 16 bit checksum
$shouldBe0000=sprintf("%04s",base_convert(base_convert("ffff",16,10)-base_convert($sumOfHex4num,16,10),10,16));

#如果加總的反數為0
if($shouldBe0000==="0000")
{
        #印出check sum
        echo $checksumIn16bit;
}
else
{
        #debug
        echo $shouldBe0000."!=0000";
}

?>