pgpprsasc.c
来自「著名的加密软件的应用于电子邮件中」· C语言 代码 · 共 2,441 行 · 第 1/5 页
C
2,441 行
/*
* This is the "start" position. Check if we are
* buffering and flush buffers if we are not. Then go
* to the next state.
*/
if (!ctx->buffering) {
*error = flushBuffers (ctx);
if (*error)
break;
}
ctx->state++;
/* FALLTHROUGH */
case 1:
case_1:
/* call readline until we have EOB or EOL */
retval = readLine (ctx, buf, size);
size -= retval;
buf += retval;
written += retval;
if (ctx->eol || ctx->eob)
ctx->state++;
else
break;
/* FALLTHROUGH */
case 2:
/*
* check the line for BEGIN. If it is not a begin
* then we should output this line. If it is a begin,
* then we need to parse it as an armor beginning.
* Use the special "bracketcmp" routine which ignores material in
* angle brackets "<>" as some mailers may stick those in front of
* our message to turn off some rich text features.
*/
if (ctx->armorlen > sizeof (prefix1) - 1 &&
0==bracketcmp (ctx->armorline, ctx->armorlen,
prefix1, sizeof (prefix1) - 1, &bracketlen)) {
ctx->state = 9;
goto case_9;
}
/*
* check the line to see if it is the beginning of a
* PGP binary message. This check is only done the
* first time through this loop, using ctx->annotation
* as the loop detector. If this is a PGP message,
* then treat it as such and buffer the data for
* processing through a parser.
*/
if (! ctx->annotation) {
if (pgpFileTypePGP (ctx->armorline, ctx->armorlen))
{
/*
* ooh, a binary PGP message fed into the
* ascii armor parser!
*/
ctx->state = 50;
goto case_50;
}
}
#if MIMEPARSE
/*
* Look for either the MIME content-type message, or what looks
* like a MIME message boundary (in case we don't have headers).
*/
if (ctx->armorlen > sizeof (prefix_mime1) &&
!strncasecmp (ctx->armorline, prefix_mime1,
sizeof (prefix_mime1) - 1)) {
/* MIME header */
ctx->state = 60;
goto case_60;
}
/*
* If no_mime_headers, we have only a body, so assume that a line
* starting with -- is a pgp/mime signed part. This is not a very
* good assumption in general, so we will assume that we had some
* reason to think so.
*/
if (ctx->no_mime_headers && ctx->eol &&
ctx->armorlen > 2 && !memcmp (ctx->armorline, "--", 2) &&
ctx->eol) {
/* Potential MIME initial body indicator */
ctx->state = 70;
goto case_70;
}
#endif
ctx->state++;
/* FALLTHROUGH */
case 3:
case_3:
/* send annotation if we need to */
if (! ctx->annotation) {
*error = sendAnnotate (ctx, myself,
PGPANN_NONPGP_BEGIN, NULL, 0);
if (*error)
break;
ctx->annotation = PGPANN_NONPGP_END;
ctx->depth_at_ann = ctx->scope_depth;
}
ctx->state++;
/* FALLTHROUGH */
case 4:
case_4:
/* output armorline buffer */
while (ctx->armorlen) {
retval = writeExtraData (ctx, ctx->armorptr,
ctx->armorlen, error);
ctx->armorptr += retval;
ctx->armorlen -= retval;
if (*error)
return written;
}
ctx->armorptr = ctx->armorline;
ctx->state++;
/* FALLTHROUGH */
case 5:
/*
* if EOL == 1, clear state and goto state 1, otherwise
* read data and return to state 4 to output the line.
*/
if (ctx->eol == 1) {
ctx->eol = 0;
ctx->eob = 0;
ctx->state = 1;
goto case_1;
}
if (!size)
break;
retval = readLine (ctx, buf, size);
size -= retval;
buf += retval;
written += retval;
ctx->state = 4;
goto case_4;
case 9:
case_9:
/*
* parse begin line. If this is not a valid begin
* line, assume that it is not and output it as
* non-PGP text (in state 3).
* bracketlen holds extra characters to skip from our parsing
*/
ptr = ctx->armorline + sizeof (prefix1) - 1 + bracketlen;
lineused = ctx->armorlen - (sizeof (prefix1) - 1) - bracketlen;
bracketlen = 0;
thispart = maxparts = 0;
do {
if (lineused == 0) {
/* not a valid BEGIN line */
ctx->state = 3;
goto case_3;
}
} while (isspace (ptr[--lineused]));
/* temporarily null-terminate this string */
temp_c = ptr[++lineused];
ptr[lineused] = '\0';
if (!memcmp (ptr, signedmsg, sizeof (signedmsg))) {
/* This is a clearsigned message */
if (ctx->eol) {
/*
* This looks like a clearsigned
* message. jump into the clearsigned
* parser and parse it.
*/
ctx->state = 30;
goto case_30;
}
/*
* Someone is playing with us.. This is an
* error.
*/
goto err_case_9;
}
/* skip the "whatever" in "-----BEGIN PGP whatever" */
while (isalnum (*ptr) || *ptr == ' ') {
ptr++;
lineused--;
}
/* check for multipart */
if (*ptr == ',') {
/* "-----BEGIN PGP whatever, PART x[/y]-----" */
if (memcmp (ptr, prefix2, sizeof (prefix2) - 1))
goto err_case_9;
ptr += sizeof (prefix2) - 1;
lineused -= sizeof (prefix2) - 1;
thispart = strtoul ((char *)ptr, (char **)&num, 10);
if (num == NULL || thispart < 0 || thispart > 999)
goto err_case_9;
lineused -= (num - ptr);
ptr = num;
/*
* now check for "/y", if it exists. It is
* legal for it not to exist, but it must have
* either a 'y' here or a messageID.
*/
if (*ptr == '/') {
maxparts = strtoul ((char *)ptr+1,
(char **)&num, 10);
if (!num || maxparts < 2 || maxparts > 999)
goto err_case_9;
lineused -= (num - ptr);
ptr = num;
}
} else {
thispart = maxparts = 1;
}
if (memcmp (ptr, suffix, sizeof (suffix)))
goto err_case_9;
ctx->thispart = thispart;
ctx->maxparts = maxparts;
ctx->state = 10;
goto case_10;
err_case_9:
ptr[lineused] = temp_c;
ctx->state = 3;
goto case_3;
case 10:
case_10:
/* Send end-annotation (if we sent a begin annotation) */
if (ctx->annotation) {
pgpAssert (ctx->depth_at_ann == ctx->scope_depth);
*error = sendAnnotate (ctx, myself, ctx->annotation,
NULL, 0);
if (*error)
break;
ctx->annotation = 0;
}
ctx->firstheader = TRUE; /* Help us recognize doubleline mode */
ctx->state++;
/* FALLTHROUGH */
case 11:
case_11:
/* read until EOL to get to end of the last line */
ctx->armorptr = ctx->armorline;
ctx->armorlen = 0;
while (ctx->eol != 1) {
ctx->armorlen = 1; /* Preserve 1st char for doublespace logic */
retval = readLine (ctx, buf, size);
written += retval;
buf += retval;
size -= retval;
if (!size)
return written;
}
ctx->eol = 0;
ctx->eob = 0;
ctx->armorlen = 0;
ctx->state++;
/* FALLTHROUGH */
case 12:
/* call readline until we have EOB or EOL */
retval = readLine (ctx, buf, size);
size -= retval;
buf += retval;
written += retval;
if (ctx->eol || ctx->eob)
ctx->state++;
else
break;
/* FALLTHROUGH */
case 13:
/*
* If this line is blank, go to state 15. If it is
* not blank, process it as a header and then goto
* state 11.
* If it is blank and firstheader is true, go into doublespace mode
* and keep parsing.
*/
ptr = ctx->armorline;
lineused = ctx->armorlen;
/* Find trailing white space... */
while (lineused && isspace (ptr[lineused - 1]))
lineused--;
if (ctx->firstheader) {
ctx->firstheader = FALSE;
if (lineused == 0) {
/* First line is blank after ----BEGIN PGP, doublespace mode */
ctx->doublespace = 1;
ctx->state = 11;
goto case_11;
}
}
if (lineused) {
int err;
/* temporarily null-terminate this string */
temp_c = ptr[lineused];
ptr[lineused] = '\0';
err = parseHeader (ctx, ptr, lineused);
if (err) {
*error = sendAnnotate (ctx, myself,
PGPANN_ARMOR_BADHEADER,
ctx->armorline,
lineused);
ptr[lineused] = temp_c;
if (*error)
break;
/* XXX: Ignore bad headers? */
}
ctx->state = 11;
goto case_11;
}
/* this is an empty line; now go deal with Armorlines */
ctx->state++;
/* FALLTHROUGH */
case 14:
/* state 14 is obsolete */
ctx->state++;
/* FALLTHROUGH */
case 15:
/* get the message and part information */
if (!ctx->part) {
/* This is true for all normal armor messages */
msg = getMessage (ctx, ctx->messageid, ctx->maxparts);
if (!msg) {
/* This is an error */
*error = PGPERR_NOMEM;
break;
}
part = getPart (ctx, msg, ctx->thispart);
if (!part) {
/* This is an error too */
*error = PGPERR_NOMEM;
break;
}
ctx->part = part;
}
ctx->expectcrc = 0;
ctx->state++;
/* FALLTHROUGH */
case 16:
/*
* Either try to make the message writable or send an
* annotation saying we have a message part.
*/
msg = ctx->part->msg;
if (ctx->thispart == 1) {
*error = writeMessage (ctx, msg);
if (*error)
break;
} else {
byte *b;
b = (byte *)pgpAlloc(kPGPPrsAscCmdBufSize);
if (b == NULL)
{
*error = PGPERR_NOMEM;
break;
}
i = 0;
memcpy (b, &ctx->thispart, sizeof (ctx->thispart));
i += sizeof (ctx->thispart);
memcpy (b+i, &ctx->maxparts, sizeof (ctx->maxparts));
i += sizeof (ctx->maxparts);
memcpy (b+i, ctx->messageid,
strlen (ctx->messageid));
i += strlen (ctx->messageid);
*error = sendAnnotate (ctx, myself, PGPANN_ARMOR_PART,
b, i);
pgpFree(b);
if (*error)
break;
}
ctx->state++;
/* FALLTHROUGH */
case 17:
case_17:
/* read until EOL to get to end of the last line */
ctx->armorptr = ctx->armorline;
ctx->armorlen = 0;
while (ctx->eol != 1) {
ctx->armorlen = 1; /* Preserve 1st char for doublespace logic */
retval = readLine (ctx, buf, size);
written += retval;
buf += retval;
size -= retval;
if (!size)
return written;
}
ctx->eol = 0;
ctx->eob = 0;
ctx->armorlen = 0;
ctx->state++;
/* FALLTHROUGH */
case 18:
/* call readline until we have EOB or EOL */
retval = readLine (ctx, buf, size);
size -= retval;
buf += retval;
written += retval;
if (ctx->eol || ctx->eob)
ctx->state++;
else
break;
/* FALLTHROUGH */
case 19:
/*
* make sure this is not a CRC line. If it is a CRC
* then goto state 21. if it is not a CRC line, then
* it must be an armorline. So, process it as an
* armor line and then fallthrough to state 20 to
* output it.
*/
if (ctx->armorline[0] == '=') {
/* This looks like a CRC */
ctx->state = 21;
goto case_21;
}
/* Make sure we're not expecting a CRC */
if (ctx->expectcrc) {
*error = sendAnnotate (ctx, myself, PGPANN_ARMOR_NOCRC,
ctx->armorline, ctx->armorlen);
if (*error)
break;
/* Well, maybe this is an end? */
ctx->state = 24;
goto case_24;
}
/* find the end of the armorline */
inlen = ctx->armorlen;
while (inlen && isspace (ctx->armorline[inlen - 1]))
inlen--;
/* check the length of the armorline */
if (inlen > 68) { /* 68 == 64 + 2*"=3D" extra space */
*error = sendAnnotate (ctx, myself,
PGPANN_ARMOR_TOOLONG,
ctx->armorline, ctx->armorlen);
if (*error)
break;
ctx->state = 26;
goto case_26;
}
i = dearmorLine (ctx, inlen);
if (i > 48 || i < 1) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?