• UMD手机电子书的读取和制作源码(一)


    最近越来越多的朋友问UMD手机电子书格式的相关源码,我觉得也没有必要遮遮捂捂的,经我那软件开发哥们的同意,把核心的源码放出来。其实这部分源码的获得很简单,现在很多UMD电子书工具,都是用.net做的,大家找一个反编译软件就可以得到源码了,比如:Reflector.exe。

    UMD源代码下载

    Book_Types.cs/*http://www.joymo.cn,角摩手机电子书*/

    namespace JoymoEnt.JoymoParse.umd
    {
        using System;

        public class Book_Types
        {
            public static byte[] BOOK_TYPE_CARTTON = new byte[] { 2, 2 };
            public static byte[] BOOK_TYPE_COMIC_BOOK = new byte[] { 3, 2 };
            public static byte[] BOOK_TYPE_TEXT = new byte[] { 1, 1 };
        }
    }

    CUMDBook.cs/*http://www.joymo.cn,角摩手机电子书*/

    namespace JoymoEnt.JoymoParse.umd
    {
        using System;
        using System.Drawing;
        using System.IO;
        using System.Text;

        public class CUMDBook
        {
            private string _Book_Author = string.Empty;
            private CChapterList _Book_Chapters = null;
            private Image _Book_Cover = null;
            private Encoding _Book_Encoding = Encoding.Unicode;
            private string _Book_Kind = string.Empty;
            private string _Book_Path = string.Empty;
            private DateTime _Book_PublishDate = DateTime.Now;
            private string _Book_Publisher = string.Empty;
            private string _Book_Title = string.Empty;
            private byte[] _Book_Type = new byte[] { 1, 1 };
            private string _Book_Vendor = string.Empty;

            public void AppendChapter(CChapter chapter)
            {
                this._Book_Chapters.Add(chapter);
            }

            public CUMDBook()
            {
                if(_Book_Chapters == null)
                    _Book_Chapters = new CChapterList();
            }

            public CUMDBook(Property pro, CChapterList cList)
            {
                if (cList == null)
                    _Book_Chapters = new CChapterList();
                else
                    _Book_Chapters = cList;

                // 用Pro对book属性赋值
                _Book_Author = pro.Author;
                _Book_Path = pro.BookPath;
                _Book_Publisher = pro.Maker;
                _Book_Title = pro.BookName;
                _Book_Vendor = pro.Maker;
                _Book_Cover = Image.FromFile(pro.Conver);
               
            }

            public string CanSave()
            {
                if ((this.BookTitle == null) || (this.BookTitle.Length < 1))
                {
                    return "标题不能为空!";
                }
                if ((this.Author == null) || (this.Author.Length < 1))
                {
                    return "作者不能为空!";
                }
                if ((this.Chapters == null) || (this.Chapters.Count < 1))
                {
                    return "内容数量不能小于0!";
                }
                if ((this.BookPath == null) || (this.BookPath.Length < 1))
                {
                    return "保存文件的路径不正确!";
                }
                if (File.Exists(this.BookPath))
                {
                    try
                    {
                        File.Delete(this.BookPath);
                    }
                    catch (Exception exception)
                    {
                        Console.WriteLine(exception.Message);
                        return "无法覆盖,文件正在被使用!";
                    }
                }
                return null;
            }

            public string Author
            {
                get
                {
                    return this._Book_Author;
                }
                set
                {
                    this._Book_Author = value;
                }
            }

            public Encoding BookEncoding
            {
                get
                {
                    return this._Book_Encoding;
                }
            }

            public string BookKind
            {
                get
                {
                    return this._Book_Kind;
                }
                set
                {
                    this._Book_Kind = value;
                }
            }

            public string BookPath
            {
                get
                {
                    return this._Book_Path;
                }
                set
                {
                    this._Book_Path = value;
                }
            }

            public string BookTitle
            {
                get
                {
                    return this._Book_Title;
                }
                set
                {
                    this._Book_Title = value;
                }
            }

            public byte[] BookType
            {
                get
                {
                    return this._Book_Type;
                }
                set
                {
                    this._Book_Type = value;
                }
            }

            public CChapterList Chapters
            {
                get
                {
                    return this._Book_Chapters;
                }
            }

            public Image Cover
            {
                get
                {
                    return this._Book_Cover;
                }
                set
                {
                    this._Book_Cover = value;
                }
            }

            public DateTime PublishDate
            {
                get
                {
                    return this._Book_PublishDate;
                }
                set
                {
                    this._Book_PublishDate = value;
                }
            }

            public string Publisher
            {
                get
                {
                    return this._Book_Publisher;
                }
                set
                {
                    this._Book_Publisher = value;
                }
            }

            public string Vendor
            {
                get
                {
                    return this._Book_Vendor;
                }
                set
                {
                    this._Book_Vendor = value;
                }
            }
        }
    }

    CUMDFile.cs/*http://www.joymo.cn,角摩手机电子书*/

    namespace JoymoEnt.JoymoParse.umd
    {
        using ICSharpCode.SharpZipLib.Zip.Compression;
        using System;
        using System.Collections;
        using System.Drawing;
        using System.Drawing.Imaging;
        using System.IO;
        using System.Reflection;
        using System.Runtime.InteropServices;
        using System.Text;

        public class CUMDFile
        {
            private const int A_32K_BYTE = 0x8000;
            private const byte ACTUAL_WIDTH_S60_HORI = 0xcc;
            private const byte ACTUAL_WIDTH_S60_VERT = 0xac;
            private const byte ACTUAL_WIDTH_SP = 0xa6;
            private uint additionalCheck;
            private string author = string.Empty;
            private const uint BASE_REFN_CHAP_OFF = 0x3000;
            private const uint BASE_REFN_CHAP_STR = 0x4000;
            private const uint BASE_REFN_CONTENT = 0x2000;
            private const uint BASE_REFN_COVER = 0x1000;
            private const uint BASE_REFN_PAGE_OFFSET = 0x7000;
            private const string BEYOND_END_FLAG = ""0";
            private const int BYTE_LEN = 1;
            private int[] chapOff;
            private CChapterList chapters = new CChapterList();
            private int cid;
            private int contentLength;
            private Image cover;
            private const byte COVER_TYPE_BMP = 0;
            private const byte COVER_TYPE_GIF = 2;
            private const byte COVER_TYPE_JPG = 1;
            private Stream coverStream;
            private const int CURR_VERSION = 1;
            private string day;
            private const short DCTS_CMD_ID_AUTHOR = 3;
            private const short DCTS_CMD_ID_CDS_KEY = 240;
            private const short DCTS_CMD_ID_CHAP_OFF = 0x83;
            private const short DCTS_CMD_ID_CHAP_STR = 0x84;
            private const short DCTS_CMD_ID_CONTENT_ID = 10;
            private const short DCTS_CMD_ID_COVER_PAGE = 130;
            private const short DCTS_CMD_ID_DAY = 6;
            private const short DCTS_CMD_ID_FILE_LENGTH = 11;
            private const short DCTS_CMD_ID_FIXED_LEN = 12;
            private const short DCTS_CMD_ID_GENDER = 7;
            private const short DCTS_CMD_ID_LICENSE_KEY = 0xf1;
            private const short DCTS_CMD_ID_MONTH = 5;
            private const short DCTS_CMD_ID_PAGE_OFFSET = 0x87;
            private const short DCTS_CMD_ID_PUBLISHER = 8;
            private const short DCTS_CMD_ID_REF_CONTENT = 0x81;
            private const short DCTS_CMD_ID_TITLE = 2;
            private const short DCTS_CMD_ID_VENDOR = 9;
            private const short DCTS_CMD_ID_VERSION = 1;
            private const short DCTS_CMD_ID_YEAR = 4;
            private Encoding encoding = Encoding.Unicode;
            private string File_Name;
            private const byte FIXED_LINE_PER_PAGE_S60 = 50;
            private const byte FIXED_LINE_PER_PAGE_SP = 0x19;
            private string gender = string.Empty;
            private const int INT_LEN = 4;
            private const string KEY_CODE_TAB = ""t";
            private string month;
            private short pgkSeed = 0;
            private DateTime publishDate = DateTime.Now;
            private string publisher = string.Empty;
            private uint[] refContent;
            private const byte S60_FONT_SIZE_BIG = 0x10;
            private const byte S60_FONT_SIZE_SMALL = 12;
            private const byte SEREIS60_FONTS_COUNT = 2;
            private const int SHORT_LEN = 2;
            private const byte SP_FONT_SIZE_10 = 10;
            private const byte SP_FONT_SIZE_MAX = 0x10;
            private const byte SP_FONT_SIZE_MIN = 6;
            private const string SYMBIAN_RETURN = ""u2029";
            private const string SYMBIAN_SPACE = "銆€";
            private string text;
            private string title = string.Empty;
            private const byte UMD_DCTD_HEAD_LEN = 9;
            private const byte UMD_DCTS_HEAD_LEN = 5;
            private const int UMD_FREE_CID_MIN = 0x5f5e100;
            private const int UMD_FREE_PGK_SEED_MIN = 0x400;
            private const int UMD_LICENSEKEY_LEN = 0x10;
            private const int UMD_MAX_BOOKMARK_STR_LEN = 40;
            private const byte UMD_PLATFORM_ID_NONE = 0;
            private const byte UMD_PLATFORM_ID_S60 = 1;
            private const byte UMD_PLATFORM_ID_SP = 5;
            private const int UMD_SEGMENT_LENGTH = 0x8000;
            private string vendor = string.Empty;
            private const byte VER_PKG_LEN = 3;
            private static ArrayList widthData_S60 = new ArrayList();
            private static ArrayList widthData_SP = new ArrayList();
            private const string WINDOWS_RETURN = ""r"n";
            private string year;
            private const int ZIP_LEVEL = 9;
            private ArrayList zippedSeg = new ArrayList();

            public void AppendChapter()
            {
                CChapter chapter = new CChapter("第 " + (this.chapters.Count + 1) + "章", "");
                this.Chapters.Add(chapter);
            }

            public bool CanSave()
            {
                return ((this.File_Name != null) && (this.File_Name.Length > 0));
            }

            private byte CharWidth_S60(string @char, byte fontSize)/*http://www.joymo.cn,角摩手机电子书*/
            {
                ushort num = @char[0];
                foreach (SWidthData data in widthData_S60)
                {
                    if (((data.FontSize == fontSize) && (num >= data.rngFrom)) && (num <= data.rngTo))
                    {
                        if (data.vCount == 1)
                        {
                            return data.Value[0];
                        }
                        return data.Value[num - data.rngFrom];
                    }
                }
                return fontSize;
            }

            private byte CharWidth_SP(string @char, byte fontSize)
            {
                ushort num = @char[0];
                foreach (SWidthData data in widthData_SP)
                {
                    if (((data.FontSize == fontSize) && (num >= data.rngFrom)) && (num <= data.rngTo))
                    {
                        if (data.vCount == 1)
                        {
                            return data.Value[0];
                        }
                        return data.Value[num - data.rngFrom];
                    }
                }
                return fontSize;
            }

            public void Close()
            {
                this.File_Name = "";
                this.chapters.Clear();
            }

            public void Extract(string path)
            {
                string str = path.EndsWith(@""") ? path : (path + '""');
                if (!Directory.Exists(str))
                {
                    Directory.CreateDirectory(str);
                }
                this.SaveCover(str);
                for (int i = 0; i < this.chapOff.Length; i++)
                {
                    StreamWriter writer = new StreamWriter(str + this.chapters[i].Title + ".txt", false, Encoding.Unicode);
                    writer.Write(this.chapters[i].Content);
                    writer.Close();
                }
            }

            private bool GetPageOffsetS60(byte size, uint actualWidth, out uint[] result)
            {
                if ((size != 0x10) && (size != 12))
                {
                    result = new uint[0];
                    return false;
                }
                this.GetWidthData_S60();
                ArrayList pagesOff = new ArrayList();
                pagesOff.Add(0);
                while (((uint) pagesOff[pagesOff.Count - 1]) < this.text.Length)
                {
                    this.ParseOnePage((uint) (pagesOff.Count - 1), size, actualWidth, ref pagesOff, 1);
                }
                result = new uint[pagesOff.Count];
                for (int i = 0; i < pagesOff.Count; i++)
                {
                    result[i] = ((uint) pagesOff[i]) * 2;
                }
                return true;
            }

            private bool GetPageOffsetSP(byte size, uint actualWidth, out uint[] result)
            {
                if ((size < 6) || (size > 0x10))
                {
                    result = new uint[0];
                    return false;
                }
                ArrayList pagesOff = new ArrayList();
                pagesOff.Add(0);
                while (((uint) pagesOff[pagesOff.Count - 1]) < this.text.Length)
                {
                    this.ParseOnePage((uint) (pagesOff.Count - 1), size, actualWidth, ref pagesOff, 5);
                }
                result = new uint[pagesOff.Count];
                for (int i = 0; i < pagesOff.Count; i++)
                {
                    result[i] = ((uint) pagesOff[i]) * 2;
                }
                return true;
            }

            private void GetWidthData_S60()
            {
                if (widthData_S60.Count == 0)
                {
                    for (int i = 0; i < 2; i++)
                    {
                        string path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + @""FontWidthData"S60CHS." + ((i == 0) ? "S16" : "S12") + ".wdt";
                        if (File.Exists(path))
                        {
                            FileStream input = new FileStream(path, FileMode.Open, FileAccess.Read);
                            BinaryReader reader = new BinaryReader(input);
                            while (reader.BaseStream.Position < reader.BaseStream.Length)
                            {
                                SWidthData data = new SWidthData();
                                data.FontSize = (i == 0) ? ((byte) 0x10) : ((byte) 12);
                                data.rngFrom = reader.ReadUInt16();
                                data.rngTo = reader.ReadUInt16();
                                data.vCount = reader.ReadUInt16();
                                data.Value = reader.ReadBytes((int) data.vCount);
                                widthData_S60.Add(data);
                            }
                            reader.Close();
                            input.Close();
                        }
                    }
                }
            }

            private void GetWidthData_SP()
            {
                if (widthData_SP.Count == 0)
                {
                    for (int i = 6; i < 0x10; i++)
                    {
                        string path = string.Concat(new object[] { Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), @""FontWidthData"sunfon.s", i, ".wdt" });
                        if (File.Exists(path))
                        {
                            FileStream input = new FileStream(path, FileMode.Open, FileAccess.Read);
                            BinaryReader reader = new BinaryReader(input);
                            while (reader.BaseStream.Position < reader.BaseStream.Length)
                            {
                                SWidthData data = new SWidthData();
                                data.FontSize = (byte) i;
                                data.rngFrom = reader.ReadUInt16();
                                data.rngTo = reader.ReadUInt16();
                                data.vCount = reader.ReadUInt16();
                                data.Value = reader.ReadBytes((int) data.vCount);
                                widthData_SP.Add(data);
                            }
                            reader.Close();
                            input.Close();
                        }
                    }
                }
            }

            private void Initialize()
            {
                if (this.title.Length == 0)
                {
                    throw new ArgumentException("title");
                }
                if (this.author.Length == 0)
                {
                    throw new ArgumentException("author");
                }
                if (this.chapters.Count == 0)
                {
                    throw new ApplicationException("no chapter");
                }
                foreach (CChapter chapter in this.chapters)
                {
                    if (!chapter.Content.EndsWith(""u2029"))
                    {
                        chapter.Content = chapter.Content + ""u2029";
                    }
                }
                this.chapOff = new int[this.chapters.Count];
            }

            public void Make(string path)
            {
                this.Make(path, false);
            }

            public void Make(string path, bool overwrite)
            {
                uint[] numArray;
                if (File.Exists(path))
                {
                    File.Delete(path);
                }
                this.Initialize();
                string str = path;
                this.Prepare();
                FileStream output = new FileStream(str, FileMode.OpenOrCreate, FileAccess.Write);
                BinaryWriter writer = new BinaryWriter(output);
                writer.Write((uint) 0xde9a9b89);
                this.WriteSection(1, 0, 3, writer);
                this.WriteSection(2, 0, (byte) (this.title.Length * 2), writer);
                this.WriteSection(3, 0, (byte) (this.author.Length * 2), writer);
                this.WriteSection(4, 0, (byte) (this.year.Length * 2), writer);
                this.WriteSection(5, 0, (byte) (this.month.Length * 2), writer);
                this.WriteSection(6, 0, (byte) (this.day.Length * 2), writer);
                if (this.gender.Length != 0)
                {
                    this.WriteSection(7, 0, (byte) (this.gender.Length * 2), writer);
                }
                if (this.publisher.Length != 0)
                {
                    this.WriteSection(8, 0, (byte) (this.publisher.Length * 2), writer);
                }
                if (this.vendor.Length != 0)
                {
                    this.WriteSection(9, 0, (byte) (this.vendor.Length * 2), writer);
                }
                this.WriteSection(11, 0, 4, writer);
                Random random = new Random();
                this.additionalCheck = (uint) (0x3000 + random.Next(0xfff));
                this.WriteSection(0x83, 0, 4, writer);
                this.WriteAdditional(0x83, this.additionalCheck, (uint) (this.chapOff.Length * 4), writer);
                int num = 0;
                foreach (CChapter chapter in this.chapters)
                {
                    num += (chapter.Title.Length * 2) + 1;
                }
                this.additionalCheck = (uint) (0x4000 + random.Next(0xfff));
                this.WriteSection(0x84, 1, 4, writer);
                this.WriteAdditional(0x84, this.additionalCheck, (uint) num, writer);
                int num2 = 0;
                int num3 = 0;
                if (this.zippedSeg.Count > 1)
                {
                    num2 = random.Next(0, this.zippedSeg.Count - 1);
                    num3 = random.Next(0, this.zippedSeg.Count - 1);
                }
                this.refContent = new uint[this.zippedSeg.Count];
                for (int i = 0; i < this.zippedSeg.Count; i++)
                {
                    byte[] buffer = (byte[]) this.zippedSeg[i];
                    this.refContent[i] = (uint) (random.Next(1, 0xfffffff) * -1);
                    this.WriteAdditional(0x84, this.refContent[i], (uint) buffer.Length, writer);
                    if (i == num2)
                    {
                        this.WriteSection(0xf1, 0, 0x10, writer);
                    }
                    if (i == num3)
                    {
                        this.WriteSection(10, 0, 4, writer);
                    }
                }
                this.additionalCheck = (uint) (0x2000 + random.Next(0xfff));
                this.WriteSection(0x81, 1, 4, writer);
                this.WriteAdditional(0x81, this.additionalCheck, (uint) (this.refContent.Length * 4), writer);
                if (this.cover != null)
                {
                    this.coverStream = new MemoryStream();
                    this.cover.Save(this.coverStream, ImageFormat.Gif);
                    this.additionalCheck = (uint) (0x1000 + random.Next(0xfff));
                    this.WriteSection(130, 1, 5, writer);
                    this.WriteAdditional(130, this.additionalCheck, (uint) this.coverStream.Length, writer);
                    this.coverStream.Close();
                    this.coverStream = null;
                }
                this.GetPageOffsetS60(0x10, 0xcc, out numArray);
                this.WritePageOffset(0x10, 0xd0, ref numArray, writer, 1);
                this.GetPageOffsetS60(0x10, 0xac, out numArray);
                this.WritePageOffset(0x10, 0xb0, ref numArray, writer, 1);
                this.GetPageOffsetS60(12, 0xcc, out numArray);
                this.WritePageOffset(12, 0xd0, ref numArray, writer, 1);
                this.GetPageOffsetS60(12, 0xac, out numArray);
                this.WritePageOffset(12, 0xb0, ref numArray, writer, 1);
                this.GetPageOffsetSP(10, 0xa6, out numArray);
                this.WritePageOffset(10, 0xa6, ref numArray, writer, 5);
                this.WriteSection(12, 1, 4, writer);
                writer.Close();
            }

            public void Open(string strFileName)
            {
                this.Read(strFileName);
                this.File_Name = strFileName;
            }

            private void ParseOnePage(uint pageNumber, byte fontSize, uint screenWidth, ref ArrayList pagesOff, int PID)
            {
                if (pageNumber < pagesOff.Count)
                {
                    uint num = (uint) pagesOff[(int) pageNumber];
                    int num2 = 0;
                    string str = string.Empty;
                    ArrayList list = new ArrayList();
                    byte num3 = (PID == 1) ? ((byte) 50) : ((byte) 0x19);
                    for (byte i = 0; i < num3; i = (byte) (i + 1))
                    {
                        str = string.Empty;
                        string str2 = string.Empty;
                        byte num5 = 0;
                    Label_0053:
                        if (num < this.text.Length)
                        {
                            str2 = this.text.Substring((int) num, 1);
                        }
                        else
                        {
                            str2 = ""0";
                        }
                        switch (str2)
                        {
                            case ""t":
                            case ""0":
                                str2 = "銆€";
                                break;
                        }
                        byte num6 = this.CharWidth_S60(str2, fontSize);
                        if (str2 == ""u2029")
                        {
                            num6 = 0;
                        }
                        if ((num6 + num5) <= screenWidth)
                        {
                            num5 = (byte) (num5 + num6);
                            num++;
                            if (str2 != ""u2029")
                            {
                                str = str + str2;
                                goto Label_0053;
                            }
                        }
                        if (str2 != ""u2029")
                        {
                            list.Add(str.Length);
                        }
                        else
                        {
                            list.Add(str.Length + 1);
                        }
                        num2 += (int) list[i];
                        if (i == ((byte) (num3 - 1)))
                        {
                            if ((num < this.text.Length) && (num > ((uint) pagesOff[pagesOff.Count - 1])))
                            {
                                pagesOff.Add(((uint) num2) + ((uint) pagesOff[pagesOff.Count - 1]));
                            }
                            if (num >= this.text.Length)
                            {
                                pagesOff.Add((uint) this.text.Length);
                            }
                        }
                    }
                }
            }

            private void Prepare()
            {
                this.year = this.publishDate.Year.ToString();
                this.month = this.publishDate.Month.ToString();
                this.day = this.publishDate.Day.ToString();
                Random random = new Random();
                this.pgkSeed = (short) (random.Next(0x401, 0x7fff) % 0xffff);
                this.cid = random.Next(0x5f5e101, 0x3b9aca00);
                int byteIndex = 0;
                StringBuilder builder = new StringBuilder();
                for (int i = 0; i < this.chapters.Count; i++)
                {
                    CChapter chapter = this.chapters[i];
                    chapter.Content = chapter.Content.Replace(""r"n", ""u2029");
                    builder.Append(chapter.Content);
                    this.chapOff[i] = byteIndex;
                    byteIndex += chapter.Content.Length * 2;
                }
                this.contentLength = byteIndex;
                this.text = builder.ToString();
                byte[] bytes = new byte[this.contentLength];
                byteIndex = 0;
                for (int j = 0; j < this.chapters.Count; j++)
                {
                    CChapter chapter2 = this.chapters[j];
                    this.encoding.GetBytes(chapter2.Content, 0, chapter2.Content.Length, bytes, byteIndex);
                    byteIndex += chapter2.Content.Length * 2;
                }
                int num4 = 0;
                if ((bytes.Length % 0x8000) == 0)
                {
                    num4 = bytes.Length / 0x8000;
                }
                else
                {
                    num4 = (bytes.Length / 0x8000) + 1;
                }
                byteIndex = 0;
                byte[] output = new byte[0x8000];
                for (int k = 0; k < num4; k++)
                {
                    Deflater deflater = new Deflater(Deflater.BEST_COMPRESSION, false);
                    deflater.SetInput(bytes, byteIndex, Math.Min(0x8000, bytes.Length - byteIndex));
                    deflater.Finish();
                    deflater.Deflate(output);
                    byte[] destinationArray = new byte[deflater.TotalOut];
                    Array.Copy(output, 0, destinationArray, 0, destinationArray.Length);
                    this.zippedSeg.Add(destinationArray);
                    byteIndex += output.Length;
                }
            }

            private void Read(BinaryReader reader)
            {
                this.chapters.Clear();
                if (reader.ReadUInt32() != 0xde9a9b89)
                {
                    throw new ApplicationException("Wrong header");
                }
                char ch = (char) reader.PeekChar();
                while (ch == '#')
                {
                    reader.ReadChar();
                    short id = reader.ReadInt16();
                    byte b = reader.ReadByte();
                    byte length = (byte) (reader.ReadByte() - 5);
                    this.ReadSection(id, b, length, reader);
                    ch = (char) reader.PeekChar();
                    switch (id)
                    {
                        case 10:
                        case 0xf1:
                            id = 0x84;
                            break;
                    }
                    while (ch == '$')
                    {
                        reader.ReadChar();
                        uint check = reader.ReadUInt32();
                        uint num6 = reader.ReadUInt32() - 9;
                        this.ReadAdditional(id, check, num6, reader);
                        ch = (char) reader.PeekChar();
                    }
                }
                reader.Close();
                int destinationIndex = 0;
                byte[] destinationArray = new byte[this.contentLength];
                byte[] buf = new byte[0x8000];
                foreach (byte[] buffer3 in this.zippedSeg)
                {
                    Inflater inflater = new Inflater();
                    inflater.SetInput(buffer3);
                    inflater.Inflate(buf);
                    if (destinationIndex < destinationArray.Length)
                    {
                        Array.Copy(buf, 0, destinationArray, destinationIndex, Math.Min(destinationArray.Length - destinationIndex, inflater.TotalOut));
                        destinationIndex += inflater.TotalOut;
                    }
                }
                for (int i = 0; i < this.chapOff.Length; i++)
                {
                    this.chapters[i].Content = this.encoding.GetString(destinationArray, this.chapOff[i], ((i < (this.chapOff.Length - 1)) ? this.chapOff[i + 1] : destinationArray.Length) - this.chapOff[i]).Replace(""u2029", ""r"n");
                }
                this.zippedSeg.Clear();
                this.publishDate = new DateTime(int.Parse(this.year), int.Parse(this.month), int.Parse(this.day));
            }

            private void Read(string file)
            {
                BinaryReader reader = new BinaryReader(new FileStream(file, FileMode.Open));
                this.Read(reader);
            }

            protected virtual void ReadAdditional(short id, uint check, uint length, BinaryReader reader)
            {
                switch (id)
                {
                    case 0x81:
                        reader.ReadBytes((int) length);
                        return;

                    case 130:
                        this.cover = Image.FromStream(new MemoryStream(reader.ReadBytes((int) length)));
                        return;

                    case 0x83:
                        this.chapOff = new int[length / 4];
                        for (int i = 0; i < this.chapOff.Length; i++)
                        {
                            this.chapOff[i] = reader.ReadInt32();
                        }
                        return;

                    case 0x84:
                        if (this.additionalCheck == check)
                        {
                            int index = 0;
                            byte[] bytes = reader.ReadBytes((int) length);
                            while (index < bytes.Length)
                            {
                                byte count = bytes[index];
                                this.chapters.Add(new CChapter(this.encoding.GetString(bytes, ++index, count), string.Empty));
                                index += count;
                            }
                            return;
                        }
                        this.zippedSeg.Add(reader.ReadBytes((int) length));
                        return;
                }
                reader.ReadBytes((int) length);
            }

            protected virtual void ReadSection(short id, byte b, byte length, BinaryReader reader)
            {
                switch (id)
                {
                    case 1:
                        reader.ReadByte();
                        this.pgkSeed = reader.ReadInt16();
                        return;

                    case 2:
                        this.title = this.encoding.GetString(reader.ReadBytes(length));
                        return;

                    case 3:
                        this.author = this.encoding.GetString(reader.ReadBytes(length));
                        return;

                    case 4:
                        this.year = this.encoding.GetString(reader.ReadBytes(length));
                        return;

                    case 5:
                        this.month = this.encoding.GetString(reader.ReadBytes(length));
                        return;

                    case 6:
                        this.day = this.encoding.GetString(reader.ReadBytes(length));
                        return;

                    case 7:
                        this.gender = this.encoding.GetString(reader.ReadBytes(length));
                        return;

                    case 8:
                        this.publisher = this.encoding.GetString(reader.ReadBytes(length));
                        return;

                    case 9:
                        this.vendor = this.encoding.GetString(reader.ReadBytes(length));
                        return;

                    case 10:
                        this.cid = reader.ReadInt32();
                        return;

                    case 11:
                        this.contentLength = reader.ReadInt32();
                        return;

                    case 12:
                        reader.ReadUInt32();
                        return;

                    case 0x81:
                    case 0x83:
                    case 0x84:
                        this.additionalCheck = reader.ReadUInt32();
                        return;

                    case 130:
                        reader.ReadByte();
                        this.additionalCheck = reader.ReadUInt32();
                        return;
                }
                reader.ReadBytes(length);
            }

            public void Save()
            {
                this.Save(this.File_Name);
            }

            public void Save(string strFileName)
            {
                widthData_S60.Clear();
                widthData_SP.Clear();
                this.pgkSeed = 0;
                this.zippedSeg.Clear();
                this.chapOff = null;
                this.Make(strFileName, true);
                this.File_Name = strFileName;
            }

            public void SaveAs(string strFileName)
            {
                this.Save(strFileName);
            }

            protected virtual void SaveCover(string path)
            {
                Guid guid = this.cover.RawFormat.Guid;
                string str = ".tmp";
                if (guid == ImageFormat.Bmp.Guid)
                {
                    str = ".bmp";
                }
                else if (guid == ImageFormat.Gif.Guid)
                {
                    str = ".gif";
                }
                else if (guid == ImageFormat.Jpeg.Guid)
                {
                    str = ".jpg";
                }
                this.cover.Save(path + "cover" + str);
            }

            protected virtual void WriteAdditional(short id, uint check, uint length, BinaryWriter writer)
            {
                writer.Write('$');
                writer.Write(check);
                writer.Write((uint) (length + 9));
                switch (id)
                {
                    case 0x81:
                        foreach (uint num in this.refContent)
                        {
                            writer.Write(num);
                        }
                        return;

                    case 130:
                    {
                        this.coverStream.Seek(0L, SeekOrigin.Begin);
                        byte[] buffer = new byte[this.coverStream.Length];
                        this.coverStream.Read(buffer, 0, buffer.Length);
                        writer.Write(buffer);
                        this.coverStream.Close();
                        return;
                    }
                    case 0x83:
                        foreach (int num2 in this.chapOff)
                        {
                            writer.Write(num2);
                        }
                        return;

                    case 0x84:
                        if (this.additionalCheck != check)
                        {
                            int index = Array.IndexOf(this.refContent, check);
                            if (index != -1)
                            {
                                writer.Write((byte[]) this.zippedSeg[index]);
                            }
                            return;
                        }
                        foreach (CChapter chapter in this.chapters)
                        {
                            writer.Write((byte) (chapter.Title.Length * 2));
                            writer.Write(this.encoding.GetBytes(chapter.Title));
                        }
                        return;
                }
            }

            private void WritePageOffset(byte fontSize, byte screenWidth, ref uint[] data, BinaryWriter writer, byte PID)
            {
                Random random = new Random();
                uint num = (uint) (0x7000 + random.Next(0xfff));
                writer.Write('#');
                writer.Write((short) 0x87);
                writer.Write(PID);
                writer.Write((byte) 11);
                writer.Write(fontSize);
                writer.Write(screenWidth);
                writer.Write(num);
                writer.Write('$');
                writer.Write(num);
                writer.Write((uint) (9 + (data.Length * 4)));
                foreach (uint num2 in data)
                {
                    writer.Write(num2);
                }
            }

            protected virtual void WriteSection(short id, byte b, byte length, BinaryWriter writer)
            {
                writer.Write('#');
                writer.Write(id);
                writer.Write(b);
                writer.Write((byte) (length + 5));
                switch (id)
                {
                    case 1:
                        writer.Write((byte) 1);
                        writer.Write(this.pgkSeed);
                        return;

                    case 2:
                        writer.Write(this.encoding.GetBytes(this.title));
                        return;

                    case 3:
                        writer.Write(this.encoding.GetBytes(this.author));
                        return;

                    case 4:
                        writer.Write(this.encoding.GetBytes(this.year));
                        return;

                    case 5:
                        writer.Write(this.encoding.GetBytes(this.month));
                        return;

                    case 6:
                        writer.Write(this.encoding.GetBytes(this.day));
                        return;

                    case 7:
                        writer.Write(this.encoding.GetBytes(this.gender));
                        return;

                    case 8:
                        writer.Write(this.encoding.GetBytes(this.publisher));
                        return;

                    case 9:
                        writer.Write(this.encoding.GetBytes(this.vendor));
                        return;

                    case 10:
                        writer.Write(this.cid);
                        return;

                    case 11:
                        writer.Write(this.contentLength);
                        return;

                    case 12:
                        writer.Write((uint) (((uint) writer.BaseStream.Position) + 4));
                        return;

                    case 0x81:
                    case 0x83:
                    case 0x84:
                        writer.Write(this.additionalCheck);
                        return;

                    case 130:
                        writer.Write((byte) 1);
                        writer.Write(this.additionalCheck);
                        return;

                    case 0xf1:
                        writer.Write(Encoding.ASCII.GetBytes(""0"0"0"0"0"0"0"0"0"0"0"0"0"0"0"0"));
                        return;
                }
            }

            public string Author
            {
                get
                {
                    return this.author;
                }
                set
                {
                    this.author = value;
                }
            }

            public CChapterList Chapters
            {
                get
                {
                    return this.chapters;
                }
            }

            public Image Cover
            {
                get
                {
                    return this.cover;
                }
                set
                {
                    this.cover = value;
                }
            }

            public string Gender
            {
                get
                {
                    return this.gender;
                }
                set
                {
                    this.gender = value;
                }
            }

            public DateTime PublishDate
            {
                get
                {
                    return this.publishDate;
                }
                set
                {
                    this.publishDate = value;
                }
            }

            public string Publisher
            {
                get
                {
                    return this.publisher;
                }
                set
                {
                    this.publisher = value;
                }
            }

            public string Title
            {
                get
                {
                    return this.title;
                }
                set
                {
                    this.title = value;
                }
            }

            public string Vendor
            {
                get
                {
                    return this.vendor;
                }
                set
                {
                    this.vendor = value;
                }
            }

            [StructLayout(LayoutKind.Sequential)]
            private struct SWidthData
            {
                public byte FontSize;
                public ushort rngFrom;
                public ushort rngTo;
                public uint vCount;
                public byte[] Value;
            }
        }
    }

    UMDBookReader.cs

    namespace JoymoEnt.JoymoParse.umd
    {
        using ICSharpCode.SharpZipLib.Zip.Compression;
        using System;
        using System.Collections;
        using System.Drawing;
        using System.IO;

        public class UMDBookReader
        {
            private uint _AdditionalCheckNumber;
            private CUMDBook _Book = null;
            private int[] _ChaptersOff = null;
            private string _Publish_Day = string.Empty;
            private string _Publish_Month = string.Empty;
            private string _Publish_Year = string.Empty;
            private int _TotalContentLen = 0;
            private ArrayList _TotalImageList = new ArrayList();
            private ArrayList _ZippedContentList = new ArrayList();

            private CChapter GetChapter(int index)
            {
                if (index != this._Book.Chapters.Count)
                {
                    throw new Exception("堆栈溢出!");
                }
                this._Book.Chapters.Add(new CChapter());
                return this._Book.Chapters[index];
            }

            private void ParseChapterImages()
            {
                int count = 0;
                for (int i = 0; i < this._Book.Chapters.Count; i++)
                {
                    if (i < (this._Book.Chapters.Count - 1))
                    {
                        count = this._ChaptersOff[i + 1];
                    }
                    else
                    {
                        count = this._TotalImageList.Count;
                    }
                    int num1 = this._ChaptersOff[i];
                    for (int j = this._ChaptersOff[i]; j < count; j++)/*http://www.joymo.cn,角摩手机电子书*/
                    {
                        this._Book.Chapters[i].AppendImage((Image) this._TotalImageList[j]);
                    }
                }
                if (count < this._TotalImageList.Count)
                {
                    CChapter chapter = new CChapter("未知", string.Empty);
                    for (int k = count; k < this._TotalImageList.Count; k++)
                    {
                        chapter.AppendImage((Image) this._TotalImageList[k]);
                    }
                    this._Book.AppendChapter(chapter);
                }
                this._TotalImageList.Clear();
            }

            private void ParseChapterTxtContents()
            {
                int destinationIndex = 0;
                byte[] destinationArray = new byte[this._TotalContentLen];
                byte[] buf = new byte[0x8000];
                foreach (byte[] buffer3 in this._ZippedContentList)
                {
                    Inflater inflater = new Inflater();
                    inflater.SetInput(buffer3);
                    inflater.Inflate(buf);
                    if (destinationIndex < destinationArray.Length)
                    {
                        Array.Copy(buf, 0, destinationArray, destinationIndex, Math.Min(destinationArray.Length - destinationIndex, inflater.TotalOut));
                        destinationIndex += inflater.TotalOut;
                    }
                }
                for (int i = 0; i < this._ChaptersOff.Length; i++)
                {
                    int index = this._ChaptersOff[i];
                    int count = 0;
                    if (i < (this._ChaptersOff.Length - 1))
                    {
                        count = this._ChaptersOff[i + 1] - index;
                    }
                    else
                    {
                        count = destinationArray.Length - index;
                    }
                    this._Book.Chapters[i].Content = this._Book.BookEncoding.GetString(destinationArray, index, count).Replace(""u2029", ""r"n");
                }
                this._ZippedContentList.Clear();
            }

            private void Read(BinaryReader reader)
            {
                if (reader.ReadUInt32() != 0xde9a9b89)
                {
                    throw new ApplicationException("Wrong header");
                }
                short num2 = -1;
                char ch = (char) reader.PeekChar();
                while (ch == '#')
                {
                    reader.ReadChar();
                    short segType = reader.ReadInt16();
                    byte segFlag = reader.ReadByte();
                    byte length = (byte) (reader.ReadByte() - 5);
                    this.ReadSection(segType, segFlag, length, reader);
                    switch (segType)
                    {
                        case 0xf1:
                        case 10:
                            segType = num2;
                            break;
                    }
                    num2 = segType;
                    ch = (char) reader.PeekChar();
                    while (ch == '$')
                    {
                        reader.ReadChar();
                        uint additionalCheckNumber = reader.ReadUInt32();
                        uint num7 = reader.ReadUInt32() - 9;
                        this.ReadAdditionalSection(segType, additionalCheckNumber, num7, reader);
                        ch = (char) reader.PeekChar();
                    }
                    Console.WriteLine("BEGIN");
                    Console.WriteLine((int) segType);
                    Console.WriteLine(ch);
                    Console.WriteLine("END");
                }
            }

            public CUMDBook Read(string filepath)
            {
                if (!File.Exists(filepath))
                {
                    throw new Exception("找不到" + filepath);
                }
                this._Book = new CUMDBook();
                FileStream input = new FileStream(filepath, FileMode.Open, FileAccess.Read);
                if (input.CanRead)
                {
                    BinaryReader reader = new BinaryReader(input);
                    try
                    {
                        this.Read(reader);
                        input.Close();
                        input = null;
                        try
                        {
                            this._Book.PublishDate = new DateTime(int.Parse(this._Publish_Year), int.Parse(this._Publish_Month), int.Parse(this._Publish_Day));
                        }
                        catch (Exception)
                        {
                            this._Book.PublishDate = DateTime.Now;
                        }
                        if (this._Book.BookType[1] == 1)
                        {
                            this.ParseChapterTxtContents();
                        }
                        else if (this._Book.BookType[1] == 2)
                        {
                            this.ParseChapterImages();
                        }
                        this._Book.BookPath = filepath;
                        return this._Book;
                    }
                    catch (Exception exception)
                    {
                        Console.WriteLine(exception.Message);
                        Console.WriteLine(exception.StackTrace);
                        this._Book = null;
                        throw exception;
                    }
                    finally
                    {
                        reader.Close();
                        reader = null;
                    }
                }
                throw new Exception("文件正在被使用,无法读取!");
            }

            protected virtual void ReadAdditionalSection(short segType, uint additionalCheckNumber, uint length, BinaryReader reader)
            {
                switch (segType)
                {
                    case 14:
                    {
                        Image image = Image.FromStream(new MemoryStream(reader.ReadBytes((int) length)));
                        this._TotalImageList.Add(image);
                        return;
                    }
                    case 15:
                    {
                        Image image2 = Image.FromStream(new MemoryStream(reader.ReadBytes((int) length)));
                        this._TotalImageList.Add(image2);
                        return;
                    }
                    case 0x81:
                        reader.ReadBytes((int) length);
                        return;

                    case 130:
                        this._Book.Cover = Image.FromStream(new MemoryStream(reader.ReadBytes((int) length)));
                        return;

                    case 0x83:
                        this._ChaptersOff = null;
                        this._ChaptersOff = new int[length / 4];
                        for (int i = 0; i < this._ChaptersOff.Length; i++)
                        {
                            this._ChaptersOff[i] = reader.ReadInt32();
                        }
                        return;

                    case 0x84:
                        if (this._AdditionalCheckNumber == additionalCheckNumber)
                        {
                            int index = 0;
                            byte[] bytes = reader.ReadBytes((int) length);
                            while (index < bytes.Length)
                            {
                                byte count = bytes[index];
                                index++;
                                this._Book.Chapters.Add(new CChapter(this._Book.BookEncoding.GetString(bytes, index, count), string.Empty));
                                index += count;
                            }
                            return;
                        }
                        this._ZippedContentList.Add(reader.ReadBytes((int) length));
                        return;
                }
                Console.WriteLine("未知内容");
                Console.WriteLine("Seg Type = " + segType);
                Console.WriteLine("Seg Len = " + length);
                Console.WriteLine("content = " + reader.ReadBytes((int) length));
            }

            protected void ReadSection(short segType, byte segFlag, byte length, BinaryReader reader)
            {
                switch (segType)
                {
                    case 1:
                        this._Book.BookType[0] = reader.ReadByte();
                        this._Book.BookType[1] = this._Book.BookType[0];
                        reader.ReadInt16();
                        return;

                    case 2:
                        this._Book.BookTitle = this._Book.BookEncoding.GetString(reader.ReadBytes(length));
                        return;

                    case 3:
                        this._Book.Author = this._Book.BookEncoding.GetString(reader.ReadBytes(length));
                        return;

                    case 4:
                        this._Publish_Year = this._Book.BookEncoding.GetString(reader.ReadBytes(length));
                        return;

                    case 5:
                        this._Publish_Month = this._Book.BookEncoding.GetString(reader.ReadBytes(length));
                        return;

                    case 6:
                        this._Publish_Day = this._Book.BookEncoding.GetString(reader.ReadBytes(length));
                        return;

                    case 7:
                        this._Book.BookKind = this._Book.BookEncoding.GetString(reader.ReadBytes(length));
                        return;

                    case 8:
                        this._Book.Publisher = this._Book.BookEncoding.GetString(reader.ReadBytes(length));
                        return;

                    case 9:
                        this._Book.Vendor = this._Book.BookEncoding.GetString(reader.ReadBytes(length));
                        return;

                    case 10:
                        reader.ReadInt32();
                        return;

                    case 11:
                        this._TotalContentLen = reader.ReadInt32();
                        return;

                    case 12:
                        reader.ReadUInt32();
                        return;

                    case 13:
                        Console.WriteLine("Seq type = " + 13);
                        Console.WriteLine(reader.ReadUInt32());
                        return;

                    case 14:
                        reader.ReadByte();
                        return;

                    case 15:
                        reader.ReadBytes(length);
                        this._Book.BookType[0] = 3;
                        return;

                    case 0x81:
                    case 0x83:
                    case 0x84:
                        this._AdditionalCheckNumber = reader.ReadUInt32();
                        return;

                    case 130:
                        reader.ReadByte();
                        this._AdditionalCheckNumber = reader.ReadUInt32();
                        return;
                }
                byte[] buffer = reader.ReadBytes(length);
                Console.WriteLine("未知编码");
                Console.WriteLine("Seg Type = " + segType);
                Console.WriteLine("Seg Flag = " + segFlag);
                Console.WriteLine("Seg Len = " + length);
                Console.WriteLine("Seg content = " + buffer.ToString());
            }
        }
    }



  • 相关阅读:
    仿蘑菇街界面(2)
    centos安装qt开发环境
    ubuntu14.04 qt4 C++开发环境搭建
    ubuntu qt X11开发环境
    ubuntu14.04 qt4开发环境搭建(vnc use gnome)
    ubuntu gnome vnc
    ubuntu 14.04 vnc use gnome(ubuntu14.04 gnome for vnc4server)
    C++面向对象编程初步
    openStack CI(Continuous interaction)/CD(Continuous delivery) Gerrit/Jenkins安装及集成,插件配置
    shell programs
  • 原文地址:https://www.cnblogs.com/freemobile/p/1412229.html
Copyright © 2020-2023  润新知