首页 > 编程语言 >php版本的umd电子书制作工具

php版本的umd电子书制作工具

时间:2023-02-09 14:35:25浏览次数:49  
标签:return filePath random param umd 版本 dec2hex php data

代码:

<?php
set_time_limit(0);
ini_set('memory_limit', '-1');
//error_reporting(E_ALL);
//ini_set('display_errors', 0);

/**
 +----------------------------------
 * UMD编码,文本转umd文件
 +----------------------------------
 */
class UMD
{
    public $bookinfo = array
    (
        "id"         =>         0,
        "title"     =>         "",
        "author"     =>         "xuxb",
        "year"         =>         "0",
        "month"     =>         "0",
        "day"         =>         "0",
        "sort"         =>         "",
        "publisher" =>         "",
        "seller"     =>         "",
        "cover"     =>         ""
    );
    public $chapters = array();
    public $chaptercount = 0;
    public $articlelen = 0;
    public $chaptitlelen = 0;
    public $charset = "GBK";
    public $handle;
    public $exts = 'txt|php|java|c|pl|py|conf|yaml|js|htm|html|css|jsp|h|cpp';
    public $result = [];

    function __construct()
    {
        $this->bookinfo['year'] = date("Y");
        $this->bookinfo['month'] = date("n");
        $this->bookinfo['day'] = date("j");
    }

    /**
     * 设置书籍编码
     *
     * @param String $charset
     */
    function setCharset($charset)
    {
        $this->charset = $charset;
    }

    /**
     * 设置添加书籍头信息
     *
     * @param Array $bookinfo
     */
    function addBookInfo($bookinfo = array())
    {
        //echo "addBookInfo-------->" . print_r($bookinfo, true)."\n";
        foreach($this->bookinfo as $key => $value)
        {
            if(isset($bookinfo[$key]))
            {
                $this->bookinfo[$key] = $bookinfo[$key];
            }
            if(($key != "id") && ($this->charset != "UCS"))
            {
                $this->bookinfo[$key] = iconv($this->charset,"UCS-2LE//IGNORE",$this->bookinfo[$key]);
            }
        }
    }

    /**
     * 设置添加章节
     *
     * @param String $c_title
     * @param String $c_content
     */
    function addChapter($c_title,$c_content)
    {
        //echo "addChapter-------->c_title:{$c_title}, c_content:{$c_content}\n";

        if ( $this->charset != "UCS" )
        {
            $c_title = iconv($this->charset,"UCS-2LE//IGNORE",$c_title);
            $c_content = iconv($this->charset,"UCS-2LE//IGNORE",$c_content);
        }
        $this->chapters[$this->chaptercount] = array
        (
            "title" => $c_title,
            "content" => $c_content
        );
        ++$this->chaptercount;
        $this->chaptitlelen += strlen($c_title);
        $this->articlelen += strlen($c_content);
    }

    /**
     * 从文件夹设置添加章节
     *
     * @param String $c_title
     * @param String $c_content
     */
    function addChapterFromDir($dirPath, $pre = '')
    {
        //echo "addChapterFromDir-------->dirPath:{$dirPath}, pre:{$pre}\n";

        if(is_file($dirPath)){
            return $this->addChapterFromFile($dirPath, $pre);
        }
        elseif(is_dir($dirPath) === false){
            return false;
        }

        $files = $this->listTxtFiles($dirPath);
        
        if(!isset($files) || !is_array($files) || empty($files)){
            return false;
        }

        foreach($files as $key=>$val)
        {
            $this->addChapterFromFile($val, $pre);
        }

        return true;
    }

    /**
     * 从文件夹设置添加章节
     *
     * @param String $c_title
     * @param String $c_content
     */
    function addChapterFromFile($filePath, $pre='')
    {
        if(is_file($filePath) === false || empty($pre)){
            echo "addChapterFromFile is fail-------->filePath:{$filePath}, pre:{$pre}\n";
            return false;
        }
        
        $filePath = str_replace("\\", "/", $filePath);
        $fileParts = preg_split("/\//", $filePath);
        $fileName = $fileParts[sizeof($fileParts)-1];
        $chraptParts = preg_split('/\./', $fileName);

        $chraptName = preg_replace("/{$this->exts}/", "", strtolower($chraptParts[0]));
        $filecoding = $this->detect_encoding($filePath);
        $contents = trim($this->readFileContent($filePath));
        //需要转换时增加
        if($filecoding != 'GBK'){
            $contents = iconv($filecoding, 'GBK//IGNORE', $contents);
        }
        //echo "contents: {$contents}\n";
        //exit;
        
        $this->addChapter(($pre ? '['.$pre.']' : ''), $contents);

        return true;
    }

    /**
     * 从文件夹设置添加章节
     *
     * @param String $c_title
     * @param String $c_content
     */
    function addChapterFromPath($path)
    {
        //echo "addChapterFromPath-------->path:{$path}\n";

        if(is_file($path) === true)
        {
            $this->addChapterFromFile($path);
        }
        elseif(is_dir($path) === true)
        {
            $this->addChapterFromDir($path);
        }

        return false;
    }

    /**
     * 读取文件内容
     *
     * @param String $c_title
     * @param String $c_content
     */
    function readFileContent($fileName)
    {
        if(is_file($fileName) === false)
        {
            return false;
        }

        $fh = @fopen($fileName, "r");
        $contents = @fread($fh, filesize($fileName));
        @fclose($fh);

        return $contents;
    }

    /**
     * 获取某个目录下面的txt文件
     *
     * @param Int $fontSize
     * @param Int $screenWidth
     * @param Int $PID
     */
    function listTxtFiles($txtDir)
    {
        //echo "listTxtFiles-------->txtDir:{$txtDir}\n";

        if(is_dir($txtDir) === false)
        {
            return false;
        }
        
        $txtDir = str_replace("\\", "/", $txtDir);
        $dh = @opendir($txtDir);

        while(($file = @readdir($dh)) !== false)
        {
            if(stripos('.', $file) === false){}
            else{continue;}

            $fileParts = preg_split('/\./', $file);
            $fileExt = $fileParts[sizeof($fileParts)-1];
            if(!in_array(strtolower($fileExt), explode('|', $this->exts))){continue;}

            $result[] = $txtDir .'/'. $file;
        }

        @closedir($dh);

        return $result;
    }

    /**
     * 获取某个目录下面的txt文件
     *
     * @param Int $fontSize
     * @param Int $screenWidth
     * @param Int $PID
     */
    function listDirs($txtDir)
    {
        //echo "listDirs-------->txtDir:{$txtDir}\n";
        
        $txtDir = str_replace("\\", "/", $txtDir);
        if(!is_dir($txtDir)){
            //echo "listDirs.is_dir-------->false\n";
            $this->result[] = $txtDir .'/'. $file;
        }
        else{
            //echo "listDirs-------->txtDir:{$txtDir}\n";
            $dh = opendir($txtDir);
            
            $i = 1;
            while(($file = readdir($dh)) !== false){
                if($file == '.' || $file == '..'){continue;}
                //echo "listDirs.readdir-------->file{$i}:{$file}\n";
                $i++;

                if(is_dir($txtDir .'/'. $file)){
                    $this->listDirs($txtDir .'/'. $file);
                }
                else{
                    $this->result[] = $txtDir .'/'. $file;
                }
            }

            closedir($dh);
        }
    }

    /**
     * 获取路径
     *
     * @param String $string
     * @param Int $node
     * @return String
     */
    function getPath($filePath)
    {
        $filePath = trim($filePath);
        $filePath = str_replace("\\", '/', $filePath);

        while($filePath[strlen($filePath)-1] == '/')
        {
            $fileArr = preg_split('/\//', $filePath);
            unset($fileArr[sizeof($fileArr)-1]);
            $filePath = join('/', $fileArr);
        }

        while(stripos($filePath, '//') > 0)
        {
            $filePath = str_replace('//', '/', $filePath);
        }
        
        //echo "getPath-------->{$filePath}\n";
        return $filePath;
    }

    /**
     * 获取文件名
     *
     * @param String $string
     * @param Int $node
     * @return String
     */
    function getName($filePath)
    {
        $filePath = $this->getPath($filePath);
        $filePath = rtrim($filePath, '/');
        
        if(is_dir($filePath)){
            if(stripos($filePath, '/') === false){
                $bookName = str_replace(':', '', dirname($filePath));
            }
            else{
                $filePats = preg_split('/\//', $filePath);
                $bookName = $filePats[sizeof($filePats) - 1];
                $bookName = str_replace(':', '', $bookName);
            }
        }
        else{
            $filePats = preg_split('/\/|\./', $filePath);
            $bookName = $filePats[sizeof($filePats) - 2];
            $bookName = str_replace(':', '', $bookName);
        }
        
        //echo "getName-------->{$filePath}\n";
        return $bookName;
    }

    /**
     * 写入简介及其他相关信息
     *
     * @param String $string
     * @param Int $node
     * @return String
     */
    function makeInfo($string,$node)
    {
        $data  = chr(35).chr($node).chr(0).chr(0);
        $data .= $this->dec2hex(strlen($string) + 5,1);
        $data .= $string;
        return $data;
    }

    /**
     * 十进制转十六进制
     *
     * @param String $string
     * @param Int $length
     * @return String
     */
    function dec2hex($string,$length)
    {
        $data = "";
        $length *= 2;
        $c_string = substr(sprintf("%0".$length."s",dechex($string)),0 - $length);
        for ($i = 0;$i < $length;$i += 2)
        {
            $data = chr(hexdec(substr($c_string,$i,2))).$data;
        }
        return $data;
    }

    /**
     * 写入章节偏移量
     *
     * @param Int $fontSize
     * @param Int $screenWidth
     * @param Int $PID
     */
    function writePageOffset($fontSize,$screenWidth,$PID)
    {
        $h = mt_rand(28672,32767);
        $content_len = $this->articlelen + $this->chaptercount * 2;
        $data = pack('H*',"2387");
        $data .= pack('n',$PID);
        $data .= chr(0x0B);
        $data .= chr($fontSize).chr($screenWidth);
        $data .= $this->dec2hex($h,4);
        $data .= chr(36);
        $data .= $this->dec2hex($h,4);
        $random = 17;
        $data .= $this->dec2hex($random,4);
        $random = 0;
        $data .= $this->dec2hex($random,4);
        $data .= $this->dec2hex($content_len,4);
        //$data .= $this->dec2hex(floor($content_len / 2),4);
        fwrite($this->handle,$data,strlen($data));
        unset($data);
    }

    /**
     * 编译生成UMD
     *
     * @param String $filename
     * @return Boolean
     */
    function makeUmd($filename)
    {
        //echo "makeUmd-------->{$filename}\n";
        $this->handle = fopen($filename,"wb");
        if(!$this->handle)
        {
            return false;
        }
        flock($this->handle,LOCK_EX);

        $data  = "";
        $data .= pack('H*',"899B9ADE");                                //头 umd文件标志
        $data .= pack('H*',"230100000801");                            //0x01--文件开始
        $data .= $this->dec2hex(mt_rand(1025,32767),2);
        $data .= $this->makeInfo($this->bookinfo['title'],2);        //0x02--标题
        $data .= $this->makeInfo($this->bookinfo['author'],3);        //0x03--作者
        $data .= $this->makeInfo($this->bookinfo['year'],4);        //0x04--年
        $data .= $this->makeInfo($this->bookinfo['month'],5);        //0x05--月
        $data .= $this->makeInfo($this->bookinfo['day'],6);            //0x06--日
        $data .= $this->makeInfo($this->bookinfo['sort'],7);        //0x07--小说类型
        $data .= $this->makeInfo($this->bookinfo['publisher'],8);    //0x08--出版商
        $data .= $this->makeInfo($this->bookinfo['seller'],9);        //0x09--零售商
        fwrite($this->handle,$data,strlen($data));

        //0x0b--内容长度
        $data = "";
        $data .= pack('H*',"230B000009");
        $data .= $this->dec2hex($this->articlelen + $this->chaptercount * 2,4);

        //0x83--章节偏移 写入章节数
        $data .= pack('H*',"2383000109");
        $random = mt_rand(12288,16383);
        $data .= $this->dec2hex($random,4);
        $data .= pack('H*',"24");
        $data .= $this->dec2hex($random,4);
        $random = $this->chaptercount * 4 + 9;
        $data .= $this->dec2hex($random,4);
        $chapteroffset = 0;

        foreach($this->chapters as $key => $value)
        {
            $data .= $this->dec2hex($chapteroffset,4);
            $chapteroffset += strlen($value['content']) + 2;
        }

        //0x84--章节标题,正文
        $data .= pack('H*',"2384000109");
        $random = mt_rand(16384,20479);
        $data .= $this->dec2hex($random,4);
        $data .= pack('H*',"24");
        $data .= $this->dec2hex($random,4);
        $random = 9 + $this->chaptitlelen + $this->chaptercount;
        $data .= $this->dec2hex($random,4);

        foreach($this->chapters as $key => $value)
        {
            $random = strlen($value['title']);
            $data .= $this->dec2hex($random,1);
            $data .= $value['title'];
        }
        fwrite($this->handle,$data,strlen($data));

        $ss  = 0;
        $oo = 32768;
        $chapstr = "";
        foreach($this->chapters as $key => $value)
        {
            $chapstr .= $value['content'].chr(41).chr(32);
        }
        $chap_len = strlen($chapstr);

        $maximum = ceil($chap_len / $oo);
        $num_1 = mt_rand(0,$maximum - 1);
        $num_2 = mt_rand(0,$maximum - 1);
        $aa = array();
        for($i = 0;$i < $maximum;++$i)
        {
            $data = "";
            $data .= chr(36);
            $numrand = mt_rand(4.02653e+009,4.29497e+009);
            $aa[$i] = $numrand;
            $data .= $this->dec2hex($numrand,4);
            $c_chapstr = substr($chapstr,$ss,$oo);
            $ss += $oo ;
            $z_chapstr = gzcompress($c_chapstr);
            $random = 9 + strlen($z_chapstr);
            $data .= $this->dec2hex($random,4);
            $data .= $z_chapstr ;
            if($i == $num_1)
            {
                $data .= pack('H*',"23F100001500000000000000000000000000000000");
            }
            if ($i == $num_2)
            {
                $data .= pack('H*',"230A000009");
                $data .= $this->dec2hex($this->bookinfo['id'] + 268435456,4);
            }
            fwrite($this->handle,$data,strlen($data));
        }

        //0x81--正文写入完毕
        $data = "";
        $data .= pack('H*',"2381000109");
        $random = mt_rand(8192,12287);
        $data .= $this->dec2hex($random,4);
        $data .= chr(36);
        $data .= $this->dec2hex($random,4);
        $random = 9 + $maximum * 4;
        $data .= $this->dec2hex($random,4);
        for($i = 0;$i < $maximum;++$i)
        {
            $data .= $this->dec2hex($aa[$i],4);
        }
        fwrite($this->handle,$data,strlen($data));

        //0x82--封面
        $data = "";
        if(!empty($this->bookinfo['cover']) || is_file($this->bookinfo['cover']))
        {
            $data .= pack('H*',"238200011001");
            $random = mt_rand(4096,8191);
            $data .= $this->dec2hex($random,4);
            $data .= chr(36);
            $data .= $this->dec2hex($random,4);
            $coverstream = file_get_contents($this->bookinfo['cover']);
            $random = strlen($coverstream) + 9;
            $data .= $this->dec2hex($random,4);
            $data .= $coverstream;
            fwrite($this->handle,$data,strlen($data));
            $data = "";
        }

        //0x87--PageOffset
        $this->writePageOffset(0x10,0xD0,0x01);
        $this->writePageOffset(0x10,0xB0,0x01);
        $this->writePageOffset(0x0C,0xD0,0x01);
        $this->writePageOffset(0x0C,0xB0,0x01);
        $this->writePageOffset(0x0A,0xA6,0x05);

        //0x0c--文件结束
        $data .= pack('H*',"230C000109");
        $random = 4 + strlen($data) + ftell($this->handle);
        $data .= $this->dec2hex($random,4);
        fwrite($this->handle,$data,strlen($data));

        unset($data);
        flock($this->handle,LOCK_UN);
        fclose($this->handle);
        @chmod($filename,0755);
        return true;
    }

    /**
     * 检测文件编码
     * @param string $file 文件路径
     * @return string|null 返回 编码名 或 null
     */
    function detect_encoding($file) {
        $list = array('GBK', 'UTF-8', 'UTF-16LE', 'UTF-16BE', 'ISO-8859-1');
        $str = file_get_contents($file);
        foreach ($list as $item) {
            $tmp = mb_convert_encoding($str, $item, $item);
            if (md5($tmp) == md5($str)) {
                return $item;
            }
        }
        return null;
    }
     
    /**
     * 自动解析编码读入文件
     * @param string $file 文件路径
     * @param string $charset 读取编码
     * @return string 返回读取内容
     */
    function auto_read($file, $charset='UTF-8') {
        $list = array('GBK', 'UTF-8', 'UTF-16LE', 'UTF-16BE', 'ISO-8859-1');
        $str = file_get_contents($file);
        foreach ($list as $item) {
            $tmp = mb_convert_encoding($str, $item, $item);
            if (md5($tmp) == md5($str)) {
                return mb_convert_encoding($str, $charset, $item);
            }
        }
        return "";
    }

}

//测试效果
$filePath = isset($argv[1]) && $argv[1] ? trim($argv[1]) : './xz'; 

if($filePath == ''){
    echo "USAGE:php ".__FILE__." [PATH]...";
    exit;
}

if(file_exists($filePath) === false){
    echo "PATH:$filePath is not exists...";
    exit;
}

$umd = new UMD();
$filePath = $umd->getPath($filePath);
$bookName = $umd->getName($filePath);
echo "filePath: {$filePath}\n";
echo "bookName: {$bookName}\n";
//exit;

$umd->addBookInfo(array('title'=>$bookName));

if(is_dir($filePath)){
    $umd->listDirs($filePath);//echo "目录下有这些文件:".print_r($dirs, true)."\n";
    //print_r($umd->result);

    foreach($umd->result as $dir){
        $tmps = explode('/', $dir);
        $tmps = $tmps[count($tmps)-1];
        $tmps = explode('.', $tmps);
        unset($tmps[count($tmps)-1]);
        $chraptName = implode('.', $tmps);
        $chraptName = preg_replace("/\[|\]|【|】|(|)/", '', $chraptName);
        $chraptName = preg_replace("/\.\./", '.', $chraptName);
        $chraptName = trim($chraptName, '.');
        //$umd->addChapter('['.$chraptName.']', '');
        echo "dir: {$dir}\n";
        echo "chraptName: {$chraptName}\n";

        $umd->addChapterFromFile($dir, $chraptName);
    }
}
else{
    $umd->addChapterFromFile($filePath, $bookName);
}

$umd->makeUmd($bookName . '.umd');

 

执行示例:

 

 

 

 

标签:return,filePath,random,param,umd,版本,dec2hex,php,data
From: https://www.cnblogs.com/xuxiaobo/p/17105147.html

相关文章