📄 pgpprsbin.c
字号:
myself->write = DoWrite;
}
}
break;
}
break;
default:
error = kPGPError_BadParams;
}
if (error) {
/* Get rid of partial pipelines (if any) */
if (IsNull(ctx->end) || IsNull(*(ctx->end)))
ctx->end = &oldhead;
parsePipelineTeardown (ctx);
} else {
/* Splice the new into the old */
*(ctx->end) = oldhead;
ctx->needcallback--;
}
return error;
}
static size_t
parseLiteral (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);
pgpAssert (error);
ctx = (PrsBinContext *)myself->priv;
pgpAssert (ctx);
pgpAssert (ctx->tail);
pgpAssert (!size || !ctx->eof);
*error = kPGPError_NoErr;
switch (ctx->state) {
case 0:
case 10: /* flags oldliteral, where length doesn't include prefix */
/* may also be pgpHeader.c packet, type 'P' */
/* Parse header; needed before callbacks are allowed */
len = inputMerge(&ctx->input, buf, size, 2, error);
buf += len;
size -= len;
if (*error || !size)
break;
/* Size is non-zero but we haven't got desired? EOP */
if (inputMerged(&ctx->input) < 2) {
pgpAssert(inputFinished(&ctx->input.head));
*error = ctx->tail->annotate(ctx->tail, myself,
PGPANN_PACKET_SHORT,
0, 0);
if (*error)
break;
myself->write = nextScope;
size -= nextScope (myself, buf, size, error);
break;
}
p = inputMergedPtr(&ctx->input);
/* Deal with "oldliteral" packets specially */
if (ctx->state == 10) {
if (p[0] == 'P') {
/* Special PGP 3 header */
myself->write = DoSkip;
size -= DoSkip (myself, buf, size, error);
break;
}
/* Else old-style packets; some PGPcompatible program does these */
/*
* That program uses "literal" length conventions, not
* "oldliteral", so don't do this:
*
* if (ctx->input.head.pktlen != ~0UL) {
* ctx->input.head.pktlen += 6 + p[1];
* }
*/
ctx->state = 0;
}
/* Get the name and timestamp fields */
len = inputMerge(&ctx->input, buf, size, 6+p[1], error);
buf += len;
size -= len;
/* Size may be zero here if output file is zero length */
if (*error)
break;
if (inputMerged(&ctx->input) < (unsigned)6+p[1]) {
if( size == 0 )
break;
/* Size is non-zero but we haven't got desired? EOP */
pgpAssert(inputFinished(&ctx->input.head));
*error = ctx->tail->annotate(ctx->tail, myself,
PGPANN_PACKET_SHORT,
0, 0);
if (*error)
break;
myself->write = nextScope;
size -= nextScope (myself, buf, size, error);
break;
}
ctx->subtype = p[0];
ctx->needcallback = 1;
ctx->end_scope = PGPANN_LITERAL_END;
*error = ctx->tail->annotate (ctx->tail, myself,
PGPANN_LITERAL_BEGIN, 0, 0);
if (*error)
break;
ctx->state++;
/* FALLTHROUGH */
case 1:
p = inputMergedPtr(&ctx->input);
*error = ctx->tail->annotate (ctx->tail, myself,
PGPANN_LITERAL_NAME,
p+2, (size_t)p[1]);
if (*error)
break;
ctx->state++;
/* FALLTHROUGH */
case 2:
/* Parse 4-byte timestamp */
p = inputMergedPtr(&ctx->input);
*error = ctx->tail->annotate (ctx->tail, myself,
PGPANN_LITERAL_TIMESTAMP,
p+2+p[1], 4);
if (*error)
break;
ctx->state++;
/* FALLTHROUGH */
case 3:
p = inputMergedPtr(&ctx->input);
if (ctx->subtype == PGP_LITERAL_TEXT) {
/* See if looks like PGP message, set as RECURSE type */
len = inputMerge(&ctx->input, buf, size,
6+p[1]+sizeof(pgp_message_begin)-1, error);
buf += len;
size -= len;
if (*error)
break;
if (inputMerged(&ctx->input) < 6+p[1]+sizeof(pgp_message_begin)-1){
/* Get more data if not enough to check */
if (!inputFinished(&ctx->input.head))
break;
} else {
if (memcmp (p+p[1]+6, pgp_message_begin,
sizeof(pgp_message_begin)-1) == 0) {
/* Looks like PGP message, set type as RECURSE */
ctx->subtype = PGP_LITERAL_RECURSE;
}
}
/* Advance buffer past initial data */
ctx->input.bufptr += p[1]+6;
ctx->nopurge = TRUE;
}
*error = ctx->tail->annotate (ctx->tail, myself,
PGPANN_LITERAL_TYPE, &ctx->subtype, 1);
if (*error)
break;
ctx->state++;
/* FALLTHROUGH */
case 4:
if (ctx->needcallback) {
*error = ctx->tail->annotate (ctx->tail, myself,
PGPANN_COMMIT, 0, 0);
if (*error)
break;
}
ctx->state++;
/* FALLTHROUGH */
case 5:
if (ctx->needcallback) {
*error = ProcessCallback (myself,
PGPANN_PARSER_PROCESS,
0, 0);
if (*error)
break;
}
ctx->state++;
/* Zero length files don't produce output, do an extra write here */
if( myself->write == DoWrite ) {
ctx->tail->write( ctx->tail, buf, 0, error );
}
if (*error)
break;
/* Write remaining chars from buf */
size -= myself->write(myself, buf, size, error);
break;
default:
pgpAssert (0); /* I should never get here */
}
return size0-size;
}
static size_t
parseCipher (PGPPipeline *myself, PGPByte const *buf, size_t size,
PGPError *error)
{
PrsBinContext *ctx;
size_t written = 0;
pgpAssert (myself);
pgpAssert (myself->magic == PARSERMAGIC);
pgpAssert (error);
ctx = (PrsBinContext *)myself->priv;
pgpAssert (ctx);
pgpAssert (ctx->tail);
pgpAssert (!size || !ctx->eof);
*error = kPGPError_NoErr;
switch (ctx->state) {
case 0:
/* Parse header; needed before callbacks are allowed */
written = inputMerge(&ctx->input, buf, size, MAXIVLEN+2, error);
buf += written;
size -= written;
if (*error || !size)
break;
/* Size is non-zero but we haven't got desired? EOP */
if (inputMerged(&ctx->input) < MAXIVLEN+2) {
pgpAssert(inputFinished(&ctx->input.head));
*error = ctx->tail->annotate(ctx->tail, myself,
PGPANN_PACKET_SHORT,
0, 0);
if (*error)
break;
myself->write = nextScope;
size -= nextScope (myself, buf, size, error);
break;
}
ctx->needcallback = 1;
/*
* If we're already in an encrypted scope (we've already
* sent some ESKs to the user), don't bother sending another
* one.
*/
if (ctx->end_scope) { /* Scope alreay open? */
ctx->state = 2;
goto got_esk;
}
/* No ESKs seen yet - open the scope */
ctx->end_scope = PGPANN_CIPHER_END;
*error = ctx->tail->annotate (ctx->tail, myself,
PGPANN_CIPHER_BEGIN, 0, 0);
if (*error)
break;
ctx->state++;
/* FALLTHROUGH */
case 1:
/* No ESKs seen yet - dummy one up */
*error = ctx->tail->annotate (ctx->tail, myself,
PGPANN_SKCIPHER_ESK, 0, 0);
if (*error)
break;
ctx->state++;
/* FALLTHROUGH */
case 2:
got_esk:
/* Okay, do a commit */
if (ctx->needcallback) {
*error = ctx->tail->annotate (ctx->tail, myself,
PGPANN_COMMIT, 0, 0);
if (*error)
break;
}
ctx->state++;
/* FALLTHROUGH */
case 3:
if (ctx->needcallback) {
*error = ProcessCallback (myself,
PGPANN_PARSER_PASSTHROUGH,
0, 0);
if (*error)
break;
}
ctx->state++;
written += myself->write(myself, buf, size, error);
break;
default:
pgpAssert (0);
}
return written;
}
static size_t
parseCompressed (PGPPipeline *myself, PGPByte const *buf, size_t size,
PGPError *error)
{
PrsBinContext *ctx;
size_t written = 0;
pgpAssert (myself);
pgpAssert (myself->magic == PARSERMAGIC);
pgpAssert (error);
ctx = (PrsBinContext *)myself->priv;
pgpAssert (ctx);
pgpAssert (ctx->tail);
pgpAssert (!size || !ctx->eof);
*error = kPGPError_NoErr;
switch (ctx->state) {
case 0:
/* Make sure we have the compression type */
written = inputMerge(&ctx->input, buf, size, 1, error);
buf += written;
size -= written;
if (*error || !size)
break;
/* Size is non-zero but we haven't got desired? EOP */
if (inputMerged(&ctx->input) < 1) {
pgpAssert(inputFinished(&ctx->input.head));
*error = ctx->tail->annotate(ctx->tail, myself,
PGPANN_PACKET_SHORT,
0, 0);
if (*error)
break;
myself->write = nextScope;
size -= nextScope (myself, buf, size, error);
break;
}
ctx->needcallback = 1;
ctx->end_scope = PGPANN_COMPRESSED_END;
*error = ctx->tail->annotate (ctx->tail, myself,
PGPANN_COMPRESSED_BEGIN,
inputMergedPtr(&ctx->input), 1);
if (*error)
break;
ctx->state++;
/* FALLTHROUGH */
case 1:
if (ctx->needcallback) {
*error = ctx->tail->annotate (ctx->tail, myself,
PGPANN_COMMIT, 0, 0);
if (*error)
break;
}
ctx->state++;
/* FALLTHROUGH */
case 2:
if (ctx->needcallback) {
*error = ProcessCallback (myself,
PGPANN_PARSER_RECURSE,
0, 0);
if (*error)
break;
}
ctx->state++;
written += myself->write(myself, buf, size, error);
break;
default:
pgpAssert (0);
}
return written;
}
/*
* Parse a general headerless packet. Unknown packets, comment packets
* and, in fact, things that aren't packets at all!
*/
static size_t
parseUnknown (PGPPipeline *myself, PGPByte const *buf, size_t size,
PGPError *error)
{
PrsBinContext *ctx;
size_t written = 0;
PGPByte b;
int begintype;
pgpAssert (myself);
pgpAssert (myself->magic == PARSERMAGIC);
pgpAssert (error);
ctx = (PrsBinContext *)myself->priv;
pgpAssert (ctx);
pgpAssert (ctx->tail);
pgpAssert (!size || !ctx->eof);
*error = kPGPError_NoErr;
switch (ctx->state) {
case 0:
/*
* As a convenience, we merge a leading prefix of the packet
* for identification purposes.
*/
written = inputMerge(&ctx->input, buf, size, 256, error);
buf += written;
size -= written;
if (*error)
return written;
if (inputMerged(&ctx->input) < 256 &&
!inputFinished(&ctx->input.head))
{
pgpAssert(!size);
return written;
}
/*
* We use this one function to provide different
* annotations for non-packets, comment packets, and
* unknown packets. Figure out the right one to use.
*/
b = ctx->input.buffer[0];
if (!IS_OLD_PKTBYTE(b) && !IS_NEW_PKTBYTE(b)) {
begintype = PGPANN_NONPACKET_BEGIN;
ctx->end_scope = PGPANN_NONPACKET_END;
} else if (PKTBYTE_TYPE (b) == PKTBYTE_COMMENT) {
begintype = PGPANN_COMMENT_BEGIN;
ctx->end_scope = PGPANN_COMMENT_END;
} else {
begintype = PGPANN_UNKNOWN_BEGIN;
ctx->end_scope = PGPANN_UNKNOWN_END;
}
ctx->needcallback = 1;
*error = ctx->tail->annotate (ctx->tail, myself, begintype,
inputMergedPtr(&ctx->input),
inputMerged(&ctx->input));
if (*error)
break;
ctx->state++;
/* FALLTHROUGH */
case 1:
if (ctx->needcallback) {
*error = ctx->tail->annotate (ctx->tail, myself,
PGPANN_COMMIT, 0, 0);
if (*error)
break;
}
ctx->state++;
/* FALLTHROUGH */
case 2:
if (ctx->needcallback) {
*error = ProcessCallback (myself, PGPANN_PARSER_EATIT,
0, 0);
if (*error)
break;
}
ctx->state++;
return written + myself->write(myself, buf, size, error);
/* NOTREACHED */
default:
pgpAssert (0);
}
return written;
}
/*
* This is called for most all key-type packets. Keys are just output
* within a key annotation scope. There is no callback, since no
* processing is done.
*/
static size_t
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -