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

📄 pgpprsasc.c

📁 vc环境下的pgp源码
💻 C
📖 第 1 页 / 共 5 页
字号:
		return NULL;

	while (*msg) {
		if (name && (*msg)->name && !memcmp (name, (*msg)->name,
		    strlen (name))) {
			/* Update the message size if we know it */
			if (!(*msg)->size && size)
				(*msg)->size = size;
			return *msg;
		}
		if (!name && !(*msg)->name && size == (*msg)->size &&
		    size != 1)
			return *msg;
		msg = &((*msg)->next);
	}

	*msg = (Message *)pgpContextMemAlloc( cdkContext,
		sizeof (**msg), kPGPMemoryMgrFlags_Clear);
	if (! *msg)
		return NULL;

	(*msg)->cdkContext	= cdkContext;
	
	if (name) {
		newname = (char *)pgpContextMemAlloc( cdkContext,
			strlen (name) + 1, kPGPMemoryMgrFlags_Clear);
		if (!newname) {
			pgpContextMemFree( cdkContext, *msg);
			*msg = NULL;
			return NULL;
		}
		memcpy (newname, name, strlen (name) + 1);
	} else
		newname = NULL;

	(*msg)->name = newname;
	(*msg)->size = size;
	(*msg)->msg_number = ++(ctx->msg_count);

	return *msg;
}

/*
 * We're done with this message so we can remove it from our queue
 * of pending messages.  Free any remaining message parts in the process.
 * We can also turn buffering off now.
 */
static void
freeMessage (PrsAscContext *ctx, Message *msg)
{
	Message **msgp = &ctx->msgs;
	MsgPart *part, *temp;
	PGPContextRef		cdkContext	= ctx->pipe.cdkContext;

	while (*msgp) {
		if (*msgp == msg) {
			*msgp = msg->next;
			part = msg->parts;
			if (msg->tail)
				/* Disconnect join module */
				*(msg->tail) = NULL;
			while (part) {
				temp = part;
				part = part->next;
				freePart (temp);
			}
			if (msg->name)
				pgpContextMemFree( cdkContext, msg->name);
			ctx->buffering = 0;
			pgpClearMemory( msg,  sizeof (*msg));
			pgpContextMemFree( cdkContext, msg);
				
			return;
		}
	}
	/* no match found */
	return;
}

/*
 * Buffer a command at the current spot in the data stream.  This is only
 * called when ctx->buffering is true.  What it does is find the delta
 * of this command in the data fifo from the last command in order to replay
 * the commands at the proper place.  It saves off context->written as
 * the offset and then resets the value to 0.
 *
 * The return value is 0 on success or an error code.
 *
 * Command Byte Syntax: <offset><cmd><arglen><arg>
 */
static PGPError
bufferCommand (
	PrsAscContext *ctx, PGPByte cmd, const PGPByte *arg, unsigned arglen)
{
	/* Make sure the command argument fits the buffer size */
	if (arglen > sizeof (ctx->cmdarg))
		return kPGPError_BadParams;

	if (pgpFifoWrite (ctx->fifod, ctx->ann, (PGPByte const *)&ctx->written,
			  sizeof (ctx->written)) != sizeof (ctx->written))
		return kPGPError_OutOfMemory;

	if (pgpFifoWrite (ctx->fifod, ctx->ann, &cmd, sizeof (cmd))
	    != sizeof (cmd))
		return kPGPError_OutOfMemory;

	if (pgpFifoWrite (ctx->fifod, ctx->ann, (PGPByte const *)&arglen,
			  sizeof (arglen)) != sizeof (arglen))
		return kPGPError_OutOfMemory;

	if (pgpFifoWrite (ctx->fifod, ctx->ann, arg, arglen) != arglen)
		return kPGPError_OutOfMemory;


	ctx->written = 0;
	return( kPGPError_NoErr );
}

/* Buffer up a write command for a particular message */
static PGPError
bufferWriteCommand (PrsAscContext *ctx, Message *msg)
{
	PGPByte arg[sizeof (msg)];
	memcpy (arg, (PGPByte const *)&msg, sizeof (arg));

	return bufferCommand (ctx, CMD_WRITE, arg, sizeof (arg));
}

/* Process a buffered Write command for a particular message */
static PGPError
parseWriteCommand (PrsAscContext *ctx)
{
	Message *msg;

	pgpAssert (ctx->cmdlen == sizeof (msg));
	memcpy ((PGPByte *)&msg, ctx->cmdarg, sizeof (msg));
	return writeMessage (ctx, msg);
}

/* Buffer up an annotation */
static PGPError
bufferAnnotation (PrsAscContext *ctx, PGPPipeline *origin, int type,
		  PGPByte const *string, size_t size)
{
	PGPByte *arg;
	PGPByte *argp;
	PGPError retval;
	PGPContextRef		cdkContext	= ctx->pipe.cdkContext;

	arg = argp = (PGPByte *)pgpContextMemAlloc( cdkContext,
			sizeof (origin) + sizeof (type) + size + sizeof (size),
			kPGPMemoryMgrFlags_Clear );
	if (!arg)
		return kPGPError_OutOfMemory;

	memcpy (argp, (PGPByte const *)&origin, sizeof (origin));
	argp += sizeof (origin);

	memcpy (argp, (PGPByte const *)&type, sizeof (type));
	argp += sizeof (type);

	memcpy (argp, (PGPByte const *)&size, sizeof (size));
	argp += sizeof (size);

	memcpy (argp, string, size);
	argp += size;

	retval = bufferCommand (ctx, CMD_ANNOTATE, arg, argp-arg);
	pgpContextMemFree( cdkContext, arg);
	return retval;
}

static PGPError
parseAnnotation (PrsAscContext *ctx)
{
	PGPPipeline *origin;
	int type;
	size_t size;
	PGPByte *string, *argp = ctx->cmdarg;
	PGPError retval;
	PGPContextRef		cdkContext	= ctx->pipe.cdkContext;

	pgpAssert (ctx->cmdlen >= sizeof (origin) + sizeof (type) +
		sizeof (size));

	memcpy ((PGPByte *)&origin, argp, sizeof (origin));
	argp += sizeof (origin);

	memcpy ((PGPByte *)&type, argp, sizeof (type));
	argp += sizeof (type);

	memcpy ((PGPByte *)&size, argp, sizeof (size));
	argp += sizeof (size);

	/* make sure we have the right number of bytes remaining */
	pgpAssert ((ctx->cmdlen - size) == (unsigned)(argp - ctx->cmdarg));

	string = (PGPByte *)pgpContextMemAlloc( cdkContext,
		size, kPGPMemoryMgrFlags_Clear);
	if (string == NULL)
		return kPGPError_OutOfMemory;

	pgpCopyMemory (argp, string, size);

	retval = sendAnnotate (ctx, origin, type, string, size);

	pgpContextMemFree( cdkContext, string);
	return retval;
}

/*
 * Given a buffered command, process it appropriately.  The cmd, args,
 * and arglen are currently held in the ctx.  Set arglen to 0 and
 * return 0 on success, otherwise return an error.
 */
static PGPError
processCommand (PrsAscContext *ctx)
{
	PGPError	error = kPGPError_NoErr;

	switch (ctx->command) {
	case CMD_WRITE:
		error = parseWriteCommand (ctx);
		break;
	case CMD_ANNOTATE:
		error = parseAnnotation (ctx);
		break;
	default:
		/* unknown command type.  This should NEVER happen */
		pgpAssert (0);
	}

	if (!error)
		ctx->cmdlen = 0;
	return error;
}

/*
 * Write a buffer of data which is a message part.  This will either
 * write or buffer depending on what the current state of the world
 * is.
 *
 * This will either perform a write() or a pgpJoinBuffer() depending
 * on what it is and what the state is.  We perform a write if this is
 * the writing message, otherwise we just buffer it.
 */
static size_t
writePartData (MsgPart *part, PGPByte const *buf, size_t size, PGPError *error)
{
	Message *msg = part->msg;

	/* Ignore parts that we've already finished */
	if (part->done)
		return size;

	if (part->sig)
		return part->sig->write (part->sig, buf, size, error);

	if (msg->writing)
		return part->mod->write (part->mod, buf, size, error);

	return pgpJoinBuffer (part->mod, buf, size);
}

/*
 * This will write 'extra' data out.  In general this is just
 * non-Ascii armor data.  However if we are within a "buffering
 * everything" mode, then this will get buffered into the ctx->data
 * fifo and ctx->written will be increased.
 */
static size_t
writeExtraData (
	PrsAscContext *ctx, PGPByte const *buf, size_t size, PGPError *error)
{
	size_t written;

	/* Handle clearsign text */
	if (ctx->part && ctx->part->text)
		return ctx->part->text->write (ctx->part->text, buf, size,
					       error);

	pgpAssert (ctx->tail);

	if (ctx->buffering) {
		written = pgpFifoWrite (ctx->fifod, ctx->data, buf, size);
		ctx->written += written;
		return written;
	}

	return ctx->tail->write (ctx->tail, buf, size, error);
}

/*
 * This will start with the first part that we have.  For each part,
 * it will see if it is done.  If not, return 0.  If it is done, then
 * see if there is another part sitting after it.  If so, close this
 * part, return an error if one exists, or move on to the next part if
 * there was no error closing the part.  If there is not another part
 * after this one, then only close this one if this is the last part
 * (msg->size && part->num == msg->size).  Otherwise return 0.
 *
 * If we flushed the whole message, free it.
 */
static PGPError
flushMessage (PrsAscContext *ctx, Message *msg)
{
	MsgPart *temp, *part = msg->parts;
	PGPError	error = kPGPError_NoErr;

	do {
		if (!part->done)
			break;

		if (part->next) {
			error = closePart (part);
			if (error)
				break;
			temp = part->next;
			freePart (part);
			part = temp;

		} else if (part->num == msg->size) {
			pgpAssert (!part->next);

			error = closePart (part);
			if (error)
				break;
			error = ctx->tail->annotate (ctx->tail, ctx->myself,
						     PGPANN_ARMOR_END, NULL,
						     0);
			if (error)
				break;
			freeMessage (ctx, msg);
			/* freeMessage will free the last part */
			break;
		} else
			break;

	} while (part);

	return error;
} 

/*
 * Set the state so that we are writing out this message.  It means that
 * we are probably going to be buffering everything else until this message
 * is done.  If we are already "buffering" everything, then buffer up this
 * command for later execution.
 */
static PGPError
writeMessage (PrsAscContext *ctx, Message *msg)
{
	PGPError	error;

	msg->foundpart1 = 1;
	if (ctx->buffering)
		return bufferWriteCommand (ctx, msg);

	error = ctx->tail->annotate (ctx->tail,
		ctx->myself, PGPANN_ARMOR_BEGIN,
		(PGPByte *)&ctx->sectoff, sizeof(ctx->sectoff));
	if (error)
		return error;

	ctx->buffering = 1;
	msg->writing = 1;

	/* Start flushing the message now */

	return flushMessage (ctx, msg);
}

/*
 * This is the main logic in flushing out the buffered data.  This
 * function will try to flush the data fifo and command fifo in order
 * to create the appropriate output stream.
 *
 * There are two streams which need to be merged.  Since the command
 * stream gives deltas into the datastream, we need to use the command
 * stream as the control.  No problem.
 *
 * First, we flush out any data in the data stream until the next
 * command, until ctx->left == 0.  Next, if ctx->cmdlen != 0 we
 * process the command in the ctx command buffer.  If that returns
 * without error we read in the next command/offset into ctx (->left
 * and ->cmdlen) and then repeat.  It at any time an error occurs,
 * stop and return the error code.
 */
static PGPError
flushBuffers (PrsAscContext *ctx)
{
	PGPSize datalen, cmdlen, len;
	PGPByte const *ptr;
	PGPError	error = kPGPError_NoErr;
	size_t written;

	pgpAssert (! ctx->buffering);

	datalen = pgpFifoSize (ctx->fifod, ctx->data);
	cmdlen = pgpFifoSize (ctx->fifod, ctx->ann);

	/* If nothing is buffered, just return ok */
	if (!datalen && !cmdlen)
		return( kPGPError_NoErr );

	/* Now try to flush the buffers... */
	do {
		/*
		 * If buffering gets turned on processing a command,
		 * just exit this function so more data can be read in.
		 */
		if (ctx->buffering)
			return( kPGPError_NoErr );

		/* First flush any data until the next command */
		while (ctx->left) {
			ptr = pgpFifoPeek (ctx->fifod, ctx->data, &len);
			pgpAssert (len);
			pgpAssert (ptr);

			if (len > ctx->left)
				len = ctx->left;
			written = writeExtraData (ctx, ptr, len, &error);
			pgpFifoSeek (ctx->fifod, ctx->data, written);
			ctx->left -= written;
			datalen -= written;
			if (error)
				return error;
		}

		/* Process the buffered command, if any */
		if (ctx->cmdlen) {
			error = processCommand (ctx);
			if (error)
				return error;
		}

		/*
		 * Now, read in the data for the next command.  The
		 * syntax is: <offset><cmd><arglen><arg>
		 */
		if (cmdlen) {
			if (pgpFifoRead (ctx->fifod, ctx->ann,
					 (PGPByte *)&ctx->left,
					 sizeof (ctx->left)) !=
			    sizeof (ctx->left))
				return kPGPError_FIFOReadError;
			cmdlen -= sizeof (ctx->left);

			if (pgpFifoRead (ctx->fifod, ctx->ann, &ctx->command,
					 sizeof (ctx->command)) !=
			    sizeof (ctx->command))
				return kPGPError_FIFOReadError;
			cmdlen -= sizeof (ctx->command);

			if (pgpFifoRead (ctx->fifod, ctx->ann,
					 (PGPByte *)&ctx->cmdlen,
					 sizeof (ctx->cmdlen)) !=
			    sizeof (ctx->cmdlen))

⌨️ 快捷键说明

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