惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
H
Help Net Security
博客园_首页
P
Privacy International News Feed
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
T
Tenable Blog
Latest news
Latest news
D
Darknet – Hacking Tools, Hacker News & Cyber Security
爱范儿
爱范儿
Cyberwarzone
Cyberwarzone
P
Palo Alto Networks Blog
月光博客
月光博客
有赞技术团队
有赞技术团队
Know Your Adversary
Know Your Adversary
博客园 - 叶小钗
P
Proofpoint News Feed
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
S
Schneier on Security
A
About on SuperTechFans
F
Full Disclosure
The Cloudflare Blog
T
The Exploit Database - CXSecurity.com
S
SegmentFault 最新的问题
Apple Machine Learning Research
Apple Machine Learning Research
Microsoft Security Blog
Microsoft Security Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
N
News and Events Feed by Topic
www.infosecurity-magazine.com
www.infosecurity-magazine.com
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Webroot Blog
Webroot Blog
量子位
大猫的无限游戏
大猫的无限游戏
小众软件
小众软件
WordPress大学
WordPress大学
Last Week in AI
Last Week in AI
美团技术团队
Help Net Security
Help Net Security
Microsoft Azure Blog
Microsoft Azure Blog
GbyAI
GbyAI
云风的 BLOG
云风的 BLOG
Y
Y Combinator Blog
博客园 - 司徒正美
N
Netflix TechBlog - Medium
S
Security @ Cisco Blogs
B
Blog
P
Privacy & Cybersecurity Law Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
Hacker News - Newest:
Hacker News - Newest: "LLM"
V
Visual Studio Blog
NISL@THU
NISL@THU

博客园 - 卢春城

Lesktop开源IM移动端:接入LayIM移动端UI 开源企业即时通讯和在线客服 开源企业即时通讯和在线客服 在SQL Server中对视图进行增删改 WebBrowser介绍——Javascript与C++互操作 开源WebOS 一步一步打造WebIM(4)——Comet的特殊之处 网页信息抓取 一步一步打造WebIM(3)——性能测试 在线CHM阅读器(2)——文件提取及关键文件解析 一步一步打造WebIM(2)——消息缓存 一步一步打造WebIM(1) 谈谈网站设计时图片的使用 如何开发HTML编辑器 Variable控件[更新至1.3]--在客户端和服务器之间传送变量 公交车路线查询系统后台数据库设计--换乘算法改进与优化 公交车路线查询系统后台数据库设计 公交车路线查询系统后台数据库设计--引入步行路线 远程控制程序
在线CHM阅读器(1)——CHM文件格式概述
卢春城 · 2010-04-27 · via 博客园 - 卢春城

之前开源的WEBOS中有一个在线CHM阅读器,本文将介绍如何开发一个功能类似的在线CHM阅读器。

效果图

1

相关技术

1.Structured Storage

Structured Storage provides file and data persistence in COM by handling a single file as a structured collection of objects known as storages and streams.

The purpose of Structured Storage is to reduce the performance penalties and overhead associated with storing separate objects in a single file. Structured Storage provides a solution by defining how to handle a single file entity as a structured collection of two types of objects—storages and streams—through a standard implementation called Compound Files. This enables the user to interact with, and manage, a compound file as if it were a single file rather than a nested hierarchy of separate objects.

关于Structured Storage请查阅MSDN,CHM文件本质上就是一个结构化存储格式的文件,因此,如果要读取CHM中的文件,需要知道Structured Storage的相关API。

2.ISAPI筛选器

ISAPI(Internet Server Application Programming Interface)作为一种可用来替代CGI的方法,是由微软和Process软件公司联合提出的Web服务器上的API标准。ISAPI与Web服务器结合紧密,功能强大,能够获得大量的信息,因此利用ISAPI可以开发出灵活高效的Web服务器增强程序。实现CHM在线阅读器(在不反编译的情况下)需要使用ISAPI筛选器来实现URL重定向

3.Lesktop

Lesktop是一款用于开发RIA网站的开源JS界面库,Lesktop提供了一个功能强大的可视化开发工具帮助您快速的开发RIA网站。本文介绍的CHM在线阅读器将使用Lesktop来开发前台界面

CHM文件格式

1.反编译CHM文件

要阅读CHM文件,首先就必须反编译CHM文件,提取出其中的文件(网页,图片等),反编译CHM文件需要用到WIN32 API的StgOpenStorage函数,.NET反编译CHM文件的方法可阅读这篇文章:

CHM Help File Extractor

2.#SYSTEM文件

反编译CHM文件后,您可以在解压出来的文件中看到这个名称为#SYSTEM的文件,这个文件保存了一些关于CHM文件的信息,例如起始页,标题等等。#SYSTEM是一个二进制文件,其格式也并不复杂,格式如下所示:

ID(2字节)+数据长度(2字节)+数据(字节数由数据长度决定)

#SYSTEM文件就是有多个以上这种数据构成,根据这个规律,可以读取出所有ID对应的数据,并保存到一个Hashtable中,代码如下:

private bool ReadSession(BinaryReader reader)
{
    if (reader.BaseStream.Position >= reader.BaseStream.Length) return false;

    UInt16 id = reader.ReadUInt16();
    UInt16 count = reader.ReadUInt16();
    if (count + reader.BaseStream.Position <= reader.BaseStream.Length)
    {
        if (count > 0)
        {
            _session[id] = reader.ReadBytes(count);
        }
        return true;
    }
    else
    {
        return false;
    }
}

public ChmInfo(Stream stream)
{
    BinaryReader reader = new BinaryReader(stream);

    while (ReadSession(reader)) ;
}

目前可以确定的ID和数据对应关系如下:

0x0002 - 起始页的路径

0x0003 - 标题

0x0004 - 语言

根据这个对应关系,就可以读取出CHM文件的标题,起始页等。

3.目录文件(*.hhc)

如果CHM带有目录的话,反编译CHM文件后,您可以在解压出来的文件中看到一个扩展名为HHC的文件,这个文件保存了CHM的目录结构。

image

上图是一个HHC文件的内容,大概的规律是,每一个<LI><OBJECT>…<OBJECT>对应着目录树中的一个节点,<OBJECT>…<OBJECT>中的参数记录着该节点的属性(对应的页面,名称等)。如果这个节点有子节点的话,那么<LI>后面会紧跟着一个<UL></UL>,<UL>里面所有的节点都是其子节点。

上文已简单的介绍了如何反编译CHM的文件格式以及关键文件的格式,在下一篇文章中,将介绍如何处理目录文件(*.hhc文件)以及如何利用ISAPI筛选器在没有反编译出CHM内部文件的情况下实现一个在线CHM阅读器。

尽管目前这个系列还没有完成,但是您可以先下载源代码预览一下这个在线CHM阅读器:

在线CHM阅读器源代码(注意:该CHM阅读器需要用到ISAPI筛选器,请仔细阅读部署须知)

如果您有任何问题,可以通过WebIM与我联系。