⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sshzlib.c

📁 大名鼎鼎的远程登录软件putty的Symbian版源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Zlib (RFC1950 / RFC1951) compression for PuTTY. *  * There will no doubt be criticism of my decision to reimplement * Zlib compression from scratch instead of using the existing zlib * code. People will cry `reinventing the wheel'; they'll claim * that the `fundamental basis of OSS' is code reuse; they'll want * to see a really good reason for me having chosen not to use the * existing code. *  * Well, here are my reasons. Firstly, I don't want to link the * whole of zlib into the PuTTY binary; PuTTY is justifiably proud * of its small size and I think zlib contains a lot of unnecessary * baggage for the kind of compression that SSH requires. *  * Secondly, I also don't like the alternative of using zlib.dll. * Another thing PuTTY is justifiably proud of is its ease of * installation, and the last thing I want to do is to start * mandating DLLs. Not only that, but there are two _kinds_ of * zlib.dll kicking around, one with C calling conventions on the * exported functions and another with WINAPI conventions, and * there would be a significant danger of getting the wrong one. *  * Thirdly, there seems to be a difference of opinion on the IETF * secsh mailing list about the correct way to round off a * compressed packet and start the next. In particular, there's * some talk of switching to a mechanism zlib isn't currently * capable of supporting (see below for an explanation). Given that * sort of uncertainty, I thought it might be better to have code * that will support even the zlib-incompatible worst case. *  * Fourthly, it's a _second implementation_. Second implementations * are fundamentally a Good Thing in standardisation efforts. The * difference of opinion mentioned above has arisen _precisely_ * because there has been only one zlib implementation and * everybody has used it. I don't intend that this should happen * again. */#include <stdlib.h>#include <assert.h>#ifdef ZLIB_STANDALONE/* * This module also makes a handy zlib decoding tool for when * you're picking apart Zip files or PDFs or PNGs. If you compile * it with ZLIB_STANDALONE defined, it builds on its own and * becomes a command-line utility. *  * Therefore, here I provide a self-contained implementation of the * macros required from the rest of the PuTTY sources. */#define snew(type) ( (type *) malloc(sizeof(type)) )#define snewn(n, type) ( (type *) malloc((n) * sizeof(type)) )#define sresize(x, n, type) ( (type *) realloc((x), (n) * sizeof(type)) )#define sfree(x) ( free((x)) )#else#include "ssh.h"#endif#ifndef FALSE#define FALSE 0#define TRUE (!FALSE)#endif/* ---------------------------------------------------------------------- * Basic LZ77 code. This bit is designed modularly, so it could be * ripped out and used in a different LZ77 compressor. Go to it, * and good luck :-) */struct LZ77InternalContext;struct LZ77Context {    struct LZ77InternalContext *ictx;    void *userdata;    void (*literal) (struct LZ77Context * ctx, unsigned char c);    void (*match) (struct LZ77Context * ctx, int distance, int len);};/* * Initialise the private fields of an LZ77Context. It's up to the * user to initialise the public fields. */static int lz77_init(struct LZ77Context *ctx);/* * Supply data to be compressed. Will update the private fields of * the LZ77Context, and will call literal() and match() to output. * If `compress' is FALSE, it will never emit a match, but will * instead call literal() for everything. */static void lz77_compress(struct LZ77Context *ctx,			  unsigned char *data, int len, int compress);/* * Modifiable parameters. */#define WINSIZE 32768		       /* window size. Must be power of 2! */#define HASHMAX 2039		       /* one more than max hash value */#define MAXMATCH 32		       /* how many matches we track */#define HASHCHARS 3		       /* how many chars make a hash *//* * This compressor takes a less slapdash approach than the * gzip/zlib one. Rather than allowing our hash chains to fall into * disuse near the far end, we keep them doubly linked so we can * _find_ the far end, and then every time we add a new byte to the * window (thus rolling round by one and removing the previous * byte), we can carefully remove the hash chain entry. */#define INVALID -1		       /* invalid hash _and_ invalid offset */struct WindowEntry {    short next, prev;		       /* array indices within the window */    short hashval;};struct HashEntry {    short first;		       /* window index of first in chain */};struct Match {    int distance, len;};struct LZ77InternalContext {    struct WindowEntry win[WINSIZE];    unsigned char data[WINSIZE];    int winpos;    struct HashEntry hashtab[HASHMAX];    unsigned char pending[HASHCHARS];    int npending;};static int lz77_hash(unsigned char *data){    return (257 * data[0] + 263 * data[1] + 269 * data[2]) % HASHMAX;}static int lz77_init(struct LZ77Context *ctx){    struct LZ77InternalContext *st;    int i;    st = snew(struct LZ77InternalContext);    if (!st)	return 0;    ctx->ictx = st;    for (i = 0; i < WINSIZE; i++)	st->win[i].next = st->win[i].prev = st->win[i].hashval = INVALID;    for (i = 0; i < HASHMAX; i++)	st->hashtab[i].first = INVALID;    st->winpos = 0;    st->npending = 0;    return 1;}static void lz77_advance(struct LZ77InternalContext *st,			 unsigned char c, int hash){    int off;    /*     * Remove the hash entry at winpos from the tail of its chain,     * or empty the chain if it's the only thing on the chain.     */    if (st->win[st->winpos].prev != INVALID) {	st->win[st->win[st->winpos].prev].next = INVALID;    } else if (st->win[st->winpos].hashval != INVALID) {	st->hashtab[st->win[st->winpos].hashval].first = INVALID;    }    /*     * Create a new entry at winpos and add it to the head of its     * hash chain.     */    st->win[st->winpos].hashval = hash;    st->win[st->winpos].prev = INVALID;    off = st->win[st->winpos].next = st->hashtab[hash].first;    st->hashtab[hash].first = st->winpos;    if (off != INVALID)	st->win[off].prev = st->winpos;    st->data[st->winpos] = c;    /*     * Advance the window pointer.     */    st->winpos = (st->winpos + 1) & (WINSIZE - 1);}#define CHARAT(k) ( (k)<0 ? st->data[(st->winpos+k)&(WINSIZE-1)] : data[k] )static void lz77_compress(struct LZ77Context *ctx,			  unsigned char *data, int len, int compress){    struct LZ77InternalContext *st = ctx->ictx;    int i, hash, distance, off, nmatch, matchlen, advance;    struct Match defermatch, matches[MAXMATCH];    int deferchr;    /*     * Add any pending characters from last time to the window. (We     * might not be able to.)     */    for (i = 0; i < st->npending; i++) {	unsigned char foo[HASHCHARS];	int j;	if (len + st->npending - i < HASHCHARS) {	    /* Update the pending array. */	    for (j = i; j < st->npending; j++)		st->pending[j - i] = st->pending[j];	    break;	}	for (j = 0; j < HASHCHARS; j++)	    foo[j] = (i + j < st->npending ? st->pending[i + j] :		      data[i + j - st->npending]);	lz77_advance(st, foo[0], lz77_hash(foo));    }    st->npending -= i;    defermatch.len = 0;    deferchr = '\0';    while (len > 0) {	/* Don't even look for a match, if we're not compressing. */	if (compress && len >= HASHCHARS) {	    /*	     * Hash the next few characters.	     */	    hash = lz77_hash(data);	    /*	     * Look the hash up in the corresponding hash chain and see	     * what we can find.	     */	    nmatch = 0;	    for (off = st->hashtab[hash].first;		 off != INVALID; off = st->win[off].next) {		/* distance = 1       if off == st->winpos-1 */		/* distance = WINSIZE if off == st->winpos   */		distance =		    WINSIZE - (off + WINSIZE - st->winpos) % WINSIZE;		for (i = 0; i < HASHCHARS; i++)		    if (CHARAT(i) != CHARAT(i - distance))			break;		if (i == HASHCHARS) {		    matches[nmatch].distance = distance;		    matches[nmatch].len = 3;		    if (++nmatch >= MAXMATCH)			break;		}	    }	} else {	    nmatch = 0;	    hash = INVALID;	}	if (nmatch > 0) {	    /*	     * We've now filled up matches[] with nmatch potential	     * matches. Follow them down to find the longest. (We	     * assume here that it's always worth favouring a	     * longer match over a shorter one.)	     */	    matchlen = HASHCHARS;	    while (matchlen < len) {		int j;		for (i = j = 0; i < nmatch; i++) {		    if (CHARAT(matchlen) ==			CHARAT(matchlen - matches[i].distance)) {			matches[j++] = matches[i];		    }		}		if (j == 0)		    break;		matchlen++;		nmatch = j;	    }	    /*	     * We've now got all the longest matches. We favour the	     * shorter distances, which means we go with matches[0].	     * So see if we want to defer it or throw it away.	     */	    matches[0].len = matchlen;	    if (defermatch.len > 0) {		if (matches[0].len > defermatch.len + 1) {		    /* We have a better match. Emit the deferred char,		     * and defer this match. */		    ctx->literal(ctx, (unsigned char) deferchr);		    defermatch = matches[0];		    deferchr = data[0];		    advance = 1;		} else {		    /* We don't have a better match. Do the deferred one. */		    ctx->match(ctx, defermatch.distance, defermatch.len);		    advance = defermatch.len - 1;		    defermatch.len = 0;		}	    } else {		/* There was no deferred match. Defer this one. */		defermatch = matches[0];		deferchr = data[0];		advance = 1;	    }	} else {	    /*	     * We found no matches. Emit the deferred match, if	     * any; otherwise emit a literal.	     */	    if (defermatch.len > 0) {		ctx->match(ctx, defermatch.distance, defermatch.len);		advance = defermatch.len - 1;		defermatch.len = 0;	    } else {		ctx->literal(ctx, data[0]);		advance = 1;	    }	}	/*	 * Now advance the position by `advance' characters,	 * keeping the window and hash chains consistent.	 */	while (advance > 0) {	    if (len >= HASHCHARS) {		lz77_advance(st, *data, lz77_hash(data));	    } else {		st->pending[st->npending++] = *data;	    }	    data++;	    len--;	    advance--;	}    }}/* ---------------------------------------------------------------------- * Zlib compression. We always use the static Huffman tree option. * Mostly this is because it's hard to scan a block in advance to * work out better trees; dynamic trees are great when you're * compressing a large file under no significant time constraint, * but when you're compressing little bits in real time, things get * hairier. *  * I suppose it's possible that I could compute Huffman trees based * on the frequencies in the _previous_ block, as a sort of * heuristic, but I'm not confident that the gain would balance out * having to transmit the trees. */struct Outbuf {    unsigned char *outbuf;    int outlen, outsize;    unsigned long outbits;    int noutbits;    int firstblock;    int comp_disabled;};static void outbits(struct Outbuf *out, unsigned long bits, int nbits){    assert(out->noutbits + nbits <= 32);    out->outbits |= bits << out->noutbits;    out->noutbits += nbits;    while (out->noutbits >= 8) {	if (out->outlen >= out->outsize) {	    out->outsize = out->outlen + 64;	    out->outbuf = sresize(out->outbuf, out->outsize, unsigned char);	}	out->outbuf[out->outlen++] = (unsigned char) (out->outbits & 0xFF);	out->outbits >>= 8;	out->noutbits -= 8;    }}static const unsigned char mirrorbytes[256] = {    0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,    0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,    0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,    0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,    0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,    0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,    0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,    0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,    0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,    0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,    0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,    0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,    0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,    0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,    0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,    0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,    0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,    0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,    0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,    0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,    0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,    0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,    0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,    0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,    0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,    0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,    0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,    0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,    0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,    0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,    0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,    0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,};typedef struct {    short code, extrabits;    int min, max;} coderecord;static const coderecord lencodes[] = {    {257, 0, 3, 3},    {258, 0, 4, 4},    {259, 0, 5, 5},    {260, 0, 6, 6},    {261, 0, 7, 7},    {262, 0, 8, 8},    {263, 0, 9, 9},    {264, 0, 10, 10},    {265, 1, 11, 12},    {266, 1, 13, 14},    {267, 1, 15, 16},    {268, 1, 17, 18},    {269, 2, 19, 22},    {270, 2, 23, 26},    {271, 2, 27, 30},    {272, 2, 31, 34},    {273, 3, 35, 42},    {274, 3, 43, 50},    {275, 3, 51, 58},    {276, 3, 59, 66},    {277, 4, 67, 82},    {278, 4, 83, 98},    {279, 4, 99, 114},    {280, 4, 115, 130},    {281, 5, 131, 162},    {282, 5, 163, 194},    {283, 5, 195, 226},    {284, 5, 227, 257},    {285, 0, 258, 258},};static const coderecord distcodes[] = {    {0, 0, 1, 1},    {1, 0, 2, 2},    {2, 0, 3, 3},    {3, 0, 4, 4},    {4, 1, 5, 6},    {5, 1, 7, 8},

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -