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

📄 pgpprsbin.c

📁 PGP—Pretty Good Privacy
💻 C
📖 第 1 页 / 共 5 页
字号:
			if (input->bufptr == input->bufend) {
				memcpy(input->bufend, buf, s);
				(void)inputHeadSeek(&input->head, buf, s);
				input->bufptr = input->bufend += s;
				buf += s;
				size -= s;
			} else {
				/* Write what's already in the buffer */
				*error = inputToFifo(input);
				if (*error)
					break;
				/* Write the current header to the FIFO */
				t = pgpFifoWrite (&pgpByteFifoDesc,
						  input->fifo, buf, s);
				(void)inputHeadSeek(&input->head, buf, t);
				buf += t;
				size -= t;
				if (t != s) {
					*error = kPGPError_OutOfMemory;
					break;
				}
			}
		}

		/* Normal data to be copied */
		avail = desired;
		if (avail > size)
			avail = (unsigned)size;
		if (avail > input->head.pktlen)
			avail = (unsigned)input->head.pktlen;
		s = input->buffer+sizeof(input->buffer)-input->bufend;
		if (avail > s) {
			if (!s)
				break;
			avail = (unsigned)s;
		}
		memcpy(input->bufend, buf, avail);
		input->bufend += avail;
		input->head.pktlen -= avail;
		size -= avail;
		desired -= avail;
	}

	return size0-size;
}

/* Return true if there's more packet in here than will fit */
static int
inputOverfull(Input const *input)
{
	return input->bufend == input->buffer+sizeof(input->buffer) &&
		!inputFinished(&input->head);
}

/* How many merged bytes are available? */
static size_t 
inputMerged(Input const *input)
{
	return (size_t)(input->bufend - input->bufptr);
}

/* Pointer to the merged bytes */
static unsigned char const *
inputMergedPtr(Input const *input)
{
	return input->bufptr;
}

/*
 * Return a buffer and length corresponding to the next batch of
 * raw (unparsed) characters in the current packet.
 * The bytes might come from one of three places:
 * - The FIFO where they have been copied by inputMerge()
 * - The input buffer
 * - the passed-in external buffer
 * In the latter case, this parses ahead in the input buffer as many
 * subpackets as possible to give the largest block of data possible.
 *
 * Returns NULL with a length of 0 if there are no more bytes in the current
 * packet.  Returns "buf" with a length of 0 if size is 0.
 * That may or may not be NULL, depending on the caller.
 */
static PGPByte const *
inputRawPeek(Input const *input, PGPByte const *buf, size_t size,
             size_t *len)
{
	PGPByte const *p;
	size_t s;
	size_t size0;
	PGPSize ulen;
	Header head;

	pgpAssert(buf || !size);
	
	/* Try the byte FIFO */
	p = pgpFifoPeek (&pgpByteFifoDesc, input->fifo, &ulen);
	if (p) {
		*len = (size_t)ulen;
		return p;
	}
	/* Then the buffered data */
	if (input->passptr != input->bufend) {
		*len = input->bufend - input->passptr;
		return input->passptr;
	}
	/* Finally, the external buffer */

	size0 = size;
	p = buf;
	head = input->head;

	while (size && !inputFinished(&head)) {
		s = inputHeadSeek(&head, p, size);
		size -= s;
		if (!size)
			break;
		p += s;
		if (size <= head.pktlen) {
			size = 0;
			break;
		}
		size -= head.pktlen;
		p += head.pktlen;
		head.pktlen = 0;
	}

	*len = size0 - size;
	return buf;
}

/*
 * Skip forward over a given number of bytes of raw input data.
 * The number of bytes must be <= the number returned from
 * inputRawPeek().
 *
 * The FIFO and buffered data are simple.  If those are empty,
 * parse forward in the external buffer until the desired number of
 * bytes have been skipped, then store the parsing state.
 */
static size_t
inputRawSeek(Input *input, PGPByte const *buf, size_t size, unsigned len)
{
	size_t s;

	pgpAssert(buf || !size);
	
	/* If there's data in the FIFO, skip that... */
	if (pgpFifoSize (&pgpByteFifoDesc, input->fifo)) {
		pgpFifoSeek (&pgpByteFifoDesc, input->fifo, len);
		return 0;
	}
	/* Otherwise the buffered data */
	if (input->passptr != input->bufend) {
		pgpAssert(len <= (size_t)(input->bufend - input->passptr));
		input->passptr += len;
		if (input->bufptr < input->passptr)
			input->bufptr = input->passptr;
		return 0;
	}

	/* Finally, the external buffer */
	pgpAssert(len <= size);

	size = len;
	while (size) {
		s = inputHeadSeek(&input->head, buf, size);
		size -= s;
		if (!len)
			break;
		buf += s;
		if (size <= input->head.pktlen) {
			input->head.pktlen -= size;
			break;
		}
		size -= input->head.pktlen;
		buf += input->head.pktlen;
		input->head.pktlen = 0;
	}
	return len;
}

/* Get rid of the header we've processed from the system. */
static void
inputPurge(Input *input)
{
	pgpFifoFlush (&pgpByteFifoDesc, input->fifo);
	input->passptr = input->bufptr = input->bufend = input->buffer;
}


#if 0
/*
 * Write all the already-buffered bytes from the current packet.
 * Return an error, if any is encountered.
 */
static int
DoRawFlush (PrsBinContext *ctx, PGPPipeline *tail)
{
	PGPError	error = kPGPError_NoErr;
	size_t len;
	PGPByte const *p;

	do {
		p = inputRawPeek(&ctx->input, NULL, 0, &len);
		if (!p)
			break;
		len = tail->write (tail, p, len, &error);
		(void)inputRawSeek(&ctx->input, NULL, 0, len);
	} while (!error);

	return error;
}
#endif


static size_t
DoSkip (PGPPipeline *myself, PGPByte const *buf, size_t size, PGPError *error)
{
	PrsBinContext *ctx;
	size_t size0 = size;
	PGPByte const *p;
	size_t len;

	pgpAssert (myself);
	pgpAssert (myself->magic == PARSERMAGIC);

	ctx = (PrsBinContext *)myself->priv;
	pgpAssert (ctx);
	pgpAssert (error);
	pgpAssert (!size || !ctx->eof);

	*error = kPGPError_NoErr;

	inputPurge (&ctx->input);

	for (;;) {
		p = inputPeek(&ctx->input, buf, size, &len);
		if (!p) {
			if (inputFinished(&ctx->input.head)) {
				/* End of input */
				myself->write = nextScope;
				size -= nextScope (myself, buf, size, error);
			}
			break;
		}
		if (!len && !size)
			break;
		len = inputSeek(&ctx->input, buf, size, len);
		size -= len;
		buf += len;
	}

	return size0-size;
}

/*
 * Write out the as-yet-unread body of this packet to the tail of this module.
 * At the end of the packet (inputFinished), set the state back to
 * nextScope.
 */
static size_t
DoWrite (PGPPipeline *myself, PGPByte const *buf, size_t size, PGPError *error)
{
	PrsBinContext *ctx;
	size_t len;
	size_t size0 = size;
	PGPByte const *p;

	pgpAssert (myself);
	pgpAssert (myself->magic == PARSERMAGIC);

	ctx = (PrsBinContext *)myself->priv;
	pgpAssert (ctx);
	pgpAssert (ctx->tail);
	pgpAssert (error);
	pgpAssert (!size || !ctx->eof);

	*error = kPGPError_NoErr;

	do {
		p = inputPeek(&ctx->input, buf, size, &len);
		if (!p) {
			if (inputFinished(&ctx->input.head)) {
				/* End of input */
				myself->write = nextScope;
				size -= nextScope (myself, buf, size, error);
			}
			break;
		}
		if (!len && !size)
			break;
		len = ctx->tail->write (ctx->tail, p, len, error);
		len = inputSeek(&ctx->input, buf, size, len);
		size -= len;
		buf += len;
	} while (!*error);

	return size0-size;
}


/*
 * Write out a series of packets to the tail of this module, keeping
 * track of packet boundaries, and counting pairs of signature headers
 * and footers.  When come to an unpaired footer, exit to process it.
 */
static size_t
DoWriteSignedPackets(PGPPipeline *myself, PGPByte const *buf, size_t size,
	       PGPError *error)
{
	PrsBinContext *ctx;
	size_t len;
	size_t size0 = size;
	PGPByte const *p;
	PGPByte b;

	pgpAssert (myself);
	pgpAssert (myself->magic == PARSERMAGIC);

	ctx = (PrsBinContext *)myself->priv;
	pgpAssert (ctx);
	pgpAssert (ctx->tail);
	pgpAssert (error);
	pgpAssert (!size || !ctx->eof);

	*error = kPGPError_NoErr;

	switch (ctx->state) {
	case 0:
		/* Here at the start of a packet */

		inputReset(&ctx->input);

		if (!size)
			return 0;	/* I need a packet header! */

		/*
		 * Track signature nesting.
		 * sig1nest holds the excess 1pass sig hdrs we've seen
		 * We distinguish old-style sig packets from new style by
		 * whether the packet type byte is old or new style.
		 */
		if (IS_NEW_PKTBYTE(buf[0])) {
			PGPByte bt = PKTBYTE_TYPE(buf[0]);
			if (bt==PKTBYTE_SIG && ctx->sig1nest==0) {
				/* This footer is what we are looking for */
				myself->write = nextScope;
				size -= nextScope (myself, buf, size, error);
				break;
			} else if (bt==PKTBYTE_1PASSSIG) { /* sig header */
				++ctx->sig1nest;
			} else if (bt==PKTBYTE_SIG) { /* sig footer */
				--ctx->sig1nest;
			}
		}

		/* Else read and pass on this packet */
		b = *(buf++);
		size--;

		if (inputStart(&ctx->input, b) < 0) {
			pgpAssert (0);	/* what to do here? */
		}


		ctx->state++;
		/* FALLTHROUGH */
	case 1:
		while (!inputFinished(&ctx->input.head)) {
			p = inputRawPeek(&ctx->input, buf, size, &len);
			if (!len)
				return size0-size;
			len = ctx->tail->write(ctx->tail, p, len, error);
			len = inputRawSeek(&ctx->input, buf, size, len);
			size -= len;
			buf += len;
			if (*error)
				return size0-size;
		}
		/* Here at end of packet */
		ctx->state = 0;
		break;
	}
		
	return size0-size;
}


/*
 * This function flushes the raw header bytes from the beginning of
 * the parser's buffer "over" the following module on to the following
 * parser, then falls through to writing the payload bytes to the following
 * module and the header bytes "over" it.
 */
static size_t
DoWriteNext (PGPPipeline *myself, PGPByte const *buf, size_t size,
	     PGPError *error)
{
	PrsBinContext *ctx;
	PGPByte const *p;
	size_t size0 = size;
	size_t len;
	PGPPipeline *tail, *next;

	pgpAssert (myself);
	pgpAssert (myself->magic == PARSERMAGIC);

	ctx = (PrsBinContext *)myself->priv;
	pgpAssert (ctx);
	pgpAssert (ctx->tail);
	pgpAssert (ctx->nextparser);
	pgpAssert (error);
	pgpAssert (!size || !ctx->eof);

	next = ctx->nextparser;
	*error = kPGPError_NoErr;

	for (;;) {
		p = inputRawPeek(&ctx->input, NULL, 0, &len);
		if (!len)
			break;
		len = next->write (next, p, len, error);
		(void)inputRawSeek(&ctx->input, NULL, 0, len);
		if (*error)
			return 0;
	}

	tail = ctx->tail;
	do {
		p = inputHeadPeek(&ctx->input.head, buf, size, &len);
		if (len) {
			len = next->write(next, p, len, error);
			(void)inputHeadSeek(&ctx->input.head, buf, len);
			buf += len;
			size -= len;
		} else {
			p = inputPeek(&ctx->input, buf, size, &len);
			if (len) {
				len = tail->write(tail, p, len, error);
				/* Note double "len" to prevent header skip */
				len = inputSeek(&ctx->input, buf, len, len);
				buf += len;
				size -= len;
			} else
				break;
		}
		if (*error)
			return size0-size;
	} while (size);

	/* If that's the end of this packet, continue with the next. */
	if (inputFinished(&ctx->input.head)) {
		/* End of input */
		myself->write = nextScope;
		size -= nextScope (myself, buf, size, error);
	}

	return size0-size;
}

/*
 * This function is called when we are checking the signature on a literal
 * packet.  The reason it is needed is that signatures are only on the BODY
 * of the literal packet, not the headers.  OOPS.  So find the size of
 * the literal packet header and pass it (external header and internal
 * header) "over" the hash module to the ctx->nextparser using
 * DoWriteNext.
 *
 * This does NOT report errors on a short or truncated literal packet, since
 * we're pretending not to be parsing it - the downstream parser will
 * notice it and do any necessary complaining.  It DOES, however, try
 * to write out such packets to the downstream parser so it can do the
 * reporting.
 */
static size_t
parseSignedLiteralMagic (PGPPipeline *myself,
                         PGPByte const *buf, size_t size, PGPError *error)
{

⌨️ 快捷键说明

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