原创 Firefox的HTTP内容解压代码阅读收藏

Firefox的HTTP内容解压代码阅读

(转载请注明来源于金庆的专栏)

参考firefox-2.0.0.4-source

RFC2612 3.5节Content codings, 内容编码定义了三种内容压缩方式:
gzip, compress, deflate, 但也可以注册新的压缩方式。

找到FireFox中的Http解压代码

Find 'deflate' in 'D:\mozilla\netwerk\streamconv\converters\nsHTTPCompressConv.h' :
D:\mozilla\netwerk\streamconv\converters\nsHTTPCompressConv.h(58):
#define    HTTP_DEFLATE_TYPE        "deflate"

nsHttpCompressConv.h
#define HTTP_DEFLATE_TYPE       "deflate"
#define HTTP_GZIP_TYPE          "gzip"
#define HTTP_X_GZIP_TYPE        "x-gzip"
#define HTTP_COMPRESS_TYPE      "compress"
#define HTTP_X_COMPRESS_TYPE    "x-compress"
#define HTTP_IDENTITY_TYPE      "identity"
#define HTTP_UNCOMPRESSED_TYPE  "uncompressed"

typedef 
enum    {
        HTTP_COMPRESS_GZIP,
        HTTP_COMPRESS_DEFLATE,
        HTTP_COMPRESS_COMPRESS,
        HTTP_COMPRESS_IDENTITY
    }
   CompressMode;


定位到类与方法

class nsHTTPCompressConv : public nsIStreamConverter

nsHTTPCompressConv::AsyncConvertData(const char *aFromType, ...)
比较类型串,设置解压模式。例
    else if (!PL_strncasecmp(aFromType, HTTP_DEFLATE_TYPE, sizeof(HTTP_DEFLATE_TYPE)-1))
        mMode = HTTP_COMPRESS_DEFLATE;

nsHTTPCompressConv::OnDataAvailable(...)
针对不同解压模式进行解压。

代码阅读
    switch (mMode)
    
{
        
case HTTP_COMPRESS_GZIP:
            streamLen 
= check_header(iStr, streamLen, &rv);
        
case HTTP_COMPRESS_DEFLATE:
            ...
            
break;
        
default:
            ...
    }


HTTP_COMPRESS_COMPRESS没有进行特别处理?
应该是无法解的,可能LZW解压算法有专利问题。

Gzip进行头部处理后就与deflate进行相似的解压。

        case HTTP_COMPRESS_DEFLATE:
            ...

            
if (mMode == HTTP_COMPRESS_DEFLATE)
                ... 
/* deflate */
            
else
                ... 
/* gzip */
            
break;

deflate与gzip解压的代码几乎相同,应该可以合成一块代码。
区别仅有:
  1. deflate使用inflateInit(),而gzip使用inflateInit2()进行初始化,比inflateInit()多一个参数: -MAX_WBITS,表示处理raw deflate数据。因为gzip数据中的zlib压缩数据块没有zlib header的两个字节。使用inflateInit2时要求zlib库忽略zlib header。在zlib手册中要求windowBits为8..15,但是实际上其它范围的数据有特殊作用,见zlib.h中的注释,如负数表示raw deflate。
  2. Apache的deflate变种可能也没有zlib header,需要添加假头后处理。即MS的错误deflate (raw deflate). zlib头第1字节一般是0x78, 第2字节与第一字节合起来的双字节应能被31整除,详见rfc1950。例如Firefox的zlib假头为0x7801,python zlib.compress()结果头部为0x789c。
deflate添假头,与gzip忽略头部效果应该是一样的,是否可以合并处理?
能否判断头部两个字节是zlib头部还是数据?是否有可能raw deflate数据按正常zlib块处理了而不报错?

check_header()

参考:GZIP文件格式简介

1. gz头:0x1f8b
2. Z_DEFLATED标志:0x08
...

其中FLG.FEXTRA的处理有个错误,额外可选项的长度应该是两个字节的合成:
                mLen = ((uInt) c & 0377) << 8;
应改为                
                mLen |= ((uInt) c & 0377) << 8;

因为该额外字段一般在HTTP的应用中不会出现,所以没有显现出来。                
我已提交:Bugzilla@Mozilla – Bug 383984

注意:GZIP文件格式简介中的额外字段的格式与rfc1952不一致,多了两个“选项ID”字节。

还有,
 case GZIP_COMMENT:
     if (mFlags & GZIP_COMMENT)

应改为:

 case GZIP_COMMENT:
     if (mFlags & COMMENT)

该错误已提交,Bugzilla@Mozilla – Bug 382849

zlib可以处理gzip头部,但所有gz函数都是针对gz文件进行的,没有直接在内存中处理gzip的,这好象是zlib功能上的一个不足吧?

相关rfc:
rfc1950: ZLIB Compressed Data Format Specification version 3.3
rfc1951: DEFLATE Compressed Data Format Specification version 1.3

(转载请注明来源于金庆的专栏)

TAGS: http,firefox,mozilla,netwerk,nshttpcompressconv,gzip,compress,deflate,zlib,代码阅读,解压

发表于 @ 2007年07月09日 11:29:00|评论(loading...)

新一篇: 自定义Firefox的配置保存路径 | 旧一篇: (Python编程)C语言内嵌API概览

用户操作
[即时聊天] [发私信] [加为好友]
金庆
订阅我的博客
XML聚合  FeedSky
订阅到鲜果
订阅到Google
订阅到抓虾
金庆的公告
XSTL封面 Locations of visitors to this page Codeguru Contributor
订阅 上海程序员
文章分类
收藏
    热门文章
    1 评“程序员怎么样才能保证自己的程序没有BUG”
    2 C语言HTML解析器ekhtml的VC编译
    3 log4cpp应用速成手册
    4 一个hash_map使用错误
    5 udp广播与直接广播
    6 评“加班文化”对软件企业的危害
    作者推荐
    1 设计死了吗?
    2 葵花宝典:软件开发高手是这样炼成的!
    3 TCP截包分段重组的设计
    4 Firefox的HTTP内容解压代码阅读
    5 不可思议:using namespace无效!
    6 作业调度问题深度搜索定界算法
    7 智能机器人编程游戏robocode的运行代码简析
    存档
    Csdn Blog version 3.1a
    Copyright © 金庆