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

📄 memotransfer.c

📁 我的Palm OS 5 SDK zhCN_PIMApps代码。 使用codewarrior 开发环境
💻 C
📖 第 1 页 / 共 4 页
字号:
/******************************************************************************
 *
 * Copyright (c) 1995-2003 PalmSource, Inc. All rights reserved.
 *
 * File: MemoTransfer.c
 *
 * Release: Palm OS 5 SDK (68K) R3.
 *
 * Description:
 *      Memo Book routines to transfer records.
 *
 *****************************************************************************/

#include <StringMgr.h>
#include <TextMgr.h>
#include <UIResources.h>
#include <Category.h>
#include <Form.h>
#include <ErrorMgr.h>
#include <TraceMgr.h>

#include <PalmLocale.h>
#include <PalmUtils.h>

#include "MemoDB.h"
#include "MemoMain.h"
#include "MemoRsc.h"


/***********************************************************************
 *
 *	Internal Constants
 *
 ***********************************************************************/
#define identifierLengthMax			40
#define mimeVersionString			"MIME-Version: 1.0\015\012"
#define mimeMultipartString 		"Content-type: multipart/mixed;"
#define mimeBoundaryString 			"boundary="
#define memoSuffix					("." memoExtension)
#define simpleBoundary				"simple boundary"
#define delimiter					"--" simpleBoundary
#define crlf						"\015\012"

#define importBufferMaxLength		 80

#define stringZLen 					-1 	// pass to WriteFunc to calculate strlen


// Stream interface to exgsockets to optimize performance
#define maxStreamBuf 				512  // MUST BE LARGER than importBufferMaxLength

typedef struct StreamType {
	ExgSocketPtr socket;
	UInt16 pos;
	UInt16 len;
	UInt16 bufSize;
	Char   buf[maxStreamBuf];
} StreamType;


/***********************************************************************
 *
 *	Internal Functions
 *
 ***********************************************************************/
static void			PrvMemoImportMimeCleanup(DmOpenRef dbP, UInt32 firstRecordID, void* inputStream, UInt16 numRecordsReceived, UInt16* numRecordsReceivedP);
static void			PrvStreamInit(StreamType *streamP, ExgSocketPtr exgSocketP);
static void			PrvStreamFlush(StreamType *streamP);
static UInt32		PrvStreamWrite(StreamType *streamP, const Char * stringP, Int32 length, Err *errP);
static UInt32		PrvStreamRead(StreamType * streamP, Char *bufP, UInt32 length, Err *errP);
static ExgSocketPtr PrvStreamSocket(StreamType *streamP);
static UInt32		PrvReadFunction(const void * stream, Char * bufferP, UInt32 length);
static UInt32		PrvWriteFunction(void * stream, const Char * const bufferP, Int32 length);
static void			PrvTransferCleanFileName(Char* ioFileName);
static void			PrvSetDescriptionAndFilename(Char * textP, Char **descriptionPP, MemHandle *descriptionHP, Char **filenamePP, MemHandle *filenameHP, const Char * const prefix);
static Err			PrvMemoSendRecordTryCatch (DmOpenRef dbP, Int16 recordNum, MemoDBRecordPtr recordP, ExgSocketPtr exgSocketP);
static Err			PrvMemoSendCategoryTryCatch (DmOpenRef dbP, UInt16 categoryNum, ExgSocketPtr exgSocketP, UInt16 index);
static void			PrvMemoSetGoToParams (DmOpenRef dbP, ExgSocketPtr exgSocketP, UInt32 uniqueID);
static Err			PrvReadThroughCRLF(ReadFunctionF inputFunc, void * inputStreamP, Char * bufferP, UInt16 * bufferLengthP);
static void			PrvMemoImportFinishRecord(DmOpenRef dbP, UInt16 indexNew, MemHandle *newRecordHPtr, UInt16 *newRecordSizePtr, void * inputStream);

/************************************************************
 *
 * FUNCTION: MemoImportMime
 *
 * DESCRIPTION: Import a Mime record.
 *
 * PARAMETERS:
 *			dbP - pointer to the database to add the record to
 *			inputStream	- pointer to where to import the record from
 *			inputFunc - function to get input from the stream
 *			obeyUniqueIDs - true to obey any unique ids if possible
 *			beginAlreadyRead - whether the begin statement has been read
 *			numRecordsRecievedP - number of records received
 *
 * RETURNS: true if the input was read
 *
 *	REVISION HISTORY:
 *			Name	Date			Description
 *			----	----			-----------
 *			rsf		4/24/97			Initial Revision
 *			bob		01/26/98		re-wrote MIME parser part to get delimiters right
 *			grant	6/25/99			Return count of records received in numRecordsReceivedP.
 *			kwk		06/25/99		Moved return out of ErrTry block.
 *			FPa		11/22/00		Fixed ErrTry/Catch/Throw problems
 *
 *************************************************************/
extern Boolean
MemoImportMime(DmOpenRef dbR, void * inputStream, ReadFunctionF inputFunc,
			   Boolean UNUSED_PARAM(obeyUniqueIDs), Boolean UNUSED_PARAM(beginAlreadyRead), UInt16 *numRecordsReceivedP, Char* descriptionP, UInt16 descriptionSize)
{
	char *c;
	char boundaryString[69+2] = "";
	MemHandle newRecordH = NULL;
	Char * newRecordP;
	MemHandle newHandle;						// Used to follow resized records which move
	UInt16 indexNew = dmMaxRecordIndex;
	DmOpenRef dbP = dbR;
	Err err = 0;
	Char buffer[importBufferMaxLength + 1];
	UInt16 bufferLength = 0;
	UInt16 charsRead;
	UInt16 charsToWrite;
	UInt16 newRecordSize = 0;
	Char * nextCrChr;
	int addCr;
	Char * boundaryP;
	Char * boundaryEndP;
	UInt16 numRecordsReceived = 0;
	UInt32 firstRecordID = 0;

	// Keep the buffer always null terminated so we can use string functions on it.
	buffer[importBufferMaxLength] = nullChr;

	// Read chars into the buffer
	charsRead = inputFunc( inputStream, buffer, importBufferMaxLength - bufferLength);
	bufferLength += charsRead;
	buffer[bufferLength] = nullChr;

	if (charsRead == 0)
	{
		*numRecordsReceivedP = 0;
		return false;
	}

	// An error happens usually due to no memory.  It's easier just to
	// catch the error.  If an error happens, we remove the last record.
	// Then we throw a second time so the caller receives it and displays a message.
	ErrTry
	{
		// MIME start, find MIME ID and version
		if (StrNCompareAscii(buffer, mimeVersionString, StrLen(mimeVersionString)) == 0)
		{
			// Remove the MIME header
			MemMove(buffer, &buffer[StrLen(mimeVersionString)], bufferLength - StrLen(mimeVersionString));
			bufferLength -= StrLen(mimeVersionString);

			// Read chars into the buffer
			charsRead = inputFunc( inputStream, &buffer[bufferLength], importBufferMaxLength - bufferLength);
			bufferLength += charsRead;
			buffer[bufferLength] = nullChr;

			// scan header for a multi-part identifier
			// skip anything else until we get an entirely blank line
			do {
				if (StrNCompareAscii(buffer, mimeMultipartString, StrLen(mimeMultipartString)) == 0)
				{
					// found a multi-part header, parse out the boundary string

					// PREVIEW Aba: Here we know that the memo is multipart => several memos
					if (descriptionP)
					{
						MemHandle headerStringH;
						Char* 	  headerStringP;

						headerStringH = DmGetResource(strRsc, FindMemoHeaderStr);
						headerStringP = MemHandleLock(headerStringH);
						StrCopy(descriptionP, headerStringP);
						MemHandleUnlock(headerStringH);
						DmReleaseResource(headerStringH);

						return true;
					}

					boundaryP = StrStr(buffer, mimeBoundaryString);
					boundaryP += StrLen(mimeBoundaryString);

					// Remove the boundary stuff so we can read in more into the buffer
					MemMove(buffer, boundaryP, &buffer[bufferLength] - boundaryP);
					bufferLength = (&buffer[bufferLength] - boundaryP);

					// Read chars into the buffer
					charsRead = inputFunc( inputStream, &buffer[bufferLength], importBufferMaxLength - bufferLength);
					bufferLength += charsRead;
					buffer[bufferLength] = nullChr;

					boundaryP = buffer;
					if (*boundaryP == '"')
					{
						boundaryP++;
						boundaryEndP = StrChr(boundaryP, '"');
					}
					else
					{
						boundaryEndP = StrChr(boundaryP, crChr);
					}
					if (boundaryEndP == NULL)
					{
						ErrThrow(exgErrBadData);
					}
					boundaryString[0] = '-';
					boundaryString[1] = '-';
					MemMove(&boundaryString[2], boundaryP, boundaryEndP - boundaryP);
					boundaryString[boundaryEndP - boundaryP + 2] = nullChr;

					c = StrChr(boundaryEndP, crChr);
					if (c == NULL)
					{
						ErrThrow(exgErrBadData);
					}
					c += sizeOf7BitChar(crChr) + sizeOf7BitChar(linefeedChr);

					// Remove the boundary stuff so we can read in more into the buffer
					MemMove(buffer, c, &buffer[bufferLength] - c);
					bufferLength = (&buffer[bufferLength] - c);
				}
				else
				{
					// just an ordinary header line, skip it
					err = PrvReadThroughCRLF(inputFunc, inputStream, buffer, &bufferLength);
					if (err)
						ErrThrow(err);
				}

				// Read chars into the buffer
				charsRead = inputFunc( inputStream, &buffer[bufferLength], importBufferMaxLength - bufferLength);
				bufferLength += charsRead;
				buffer[bufferLength] = nullChr;

				// stop at blank line by itself or EOF
			} while (buffer[0] != crChr && buffer[0] != nullChr);
			
			// We've now parsed the MIME header.  Preamble, segments, and postamble below.
		} // end of MIME parser

		do {
			// find the boundary and remove it, along with any header info in the body part
			if (*boundaryString != nullChr)
			{
				// Keep reading until we find a boundary
				while (buffer[0] != nullChr && StrNCompareAscii(buffer, boundaryString, StrLen(boundaryString)) != 0)
				{
					err = PrvReadThroughCRLF(inputFunc, inputStream, buffer, &bufferLength);
					if (err)
						ErrThrow(err);
				}

				// Remove the boundary by removing all text until the end of the line.
				err = PrvReadThroughCRLF(inputFunc, inputStream, buffer, &bufferLength);
				if (err)
					ErrThrow(err);

				while (buffer[0] != nullChr && buffer[0] != crChr)
				{
					err = PrvReadThroughCRLF(inputFunc, inputStream, buffer, &bufferLength);
					if (err)
						ErrThrow(err);
				}
				err = PrvReadThroughCRLF(inputFunc, inputStream, buffer, &bufferLength);
				if (err)
					ErrThrow(err);
			}

			// could be that everything was header, and we're out of data.
			// weird error, but MemHandle it.
			if (bufferLength == 0)
			{
				ErrThrow(exgErrBadData);
			}


			addCr = 0;
			while (bufferLength > 0 &&
				   (*boundaryString == nullChr || StrNCompareAscii(buffer, boundaryString, StrLen(boundaryString)) != 0))
			{
				// find CR or end of buffer
				nextCrChr = StrChr(buffer, crChr);
				if (nextCrChr != NULL)
					charsToWrite = nextCrChr - buffer;
				else
					charsToWrite = bufferLength;

				// PREVIEW Aba: Here we have the first line and we can exit
				if (descriptionP)
				{
					if (charsToWrite >= descriptionSize)
						charsToWrite = descriptionSize - 1;

					StrNCopy(descriptionP, buffer, charsToWrite);
					descriptionP[charsToWrite] = '\0';
					return true;
				}

				// if we're going to overflow record, close it out (leave room for terminating null)
				if (newRecordSize + charsToWrite + addCr > memoMaxLength)
				{
					// since we try to stop parsing at each CR, and most records from other sources (MIME)
					// should have a CR at least every 76 characters, we probably don't have to worry about
					// word wrap.  Still, beaming a lot of just plain text could break records on random
					// boundaries...
					PrvMemoImportFinishRecord(dbP, indexNew, &newRecordH, &newRecordSize, inputStream);
					addCr = 0;
					numRecordsReceived++;
				}

				// Make a record if we need one
				if (newRecordH == NULL)
				{
					indexNew = dmMaxRecordIndex;
					newRecordH = DmNewRecord(dbP, (UInt16 *)&indexNew, bufferLength);
					if (newRecordH == 0)
						ErrThrow(exgMemError);
					newRecordSize = 0;
				}

				// Write the buffer out to the record
				newHandle = DmResizeRecord(dbP, indexNew, newRecordSize + charsToWrite + addCr);
				if (newHandle)
					newRecordH = newHandle;
				else
					ErrThrow(exgMemError);

				newRecordP = MemHandleLock(newRecordH);
				if (addCr != 0)
					DmWrite(newRecordP, newRecordSize++, "\n", 1);
				DmWrite(newRecordP, newRecordSize, buffer, charsToWrite);
				newRecordSize += charsToWrite;
				MemHandleUnlock(newRecordH);

				// Remove the chars written so we can read more into the buffer
				if (nextCrChr != NULL)
				{
					if (charsToWrite < importBufferMaxLength-1)
					{
						MemMove(buffer, nextCrChr+2, bufferLength-(charsToWrite+2));	// delete LF
						bufferLength -= charsToWrite+2;
					}
					else
						// CR/LF was split by end of buffer, so DON'T delete the CR, catch it next time 'round
					{
						MemMove(buffer, nextCrChr, bufferLength-(charsToWrite));		// don't delete CR or LF
						bufferLength -= charsToWrite;
						nextCrChr = NULL;
					}
				}
				else
					buffer[bufferLength = 0] = nullChr;

				// Now read more
				charsRead = inputFunc( inputStream, &buffer[bufferLength], importBufferMaxLength - bufferLength);
				bufferLength += charsRead;
				buffer[bufferLength] = nullChr;

				if (nextCrChr != NULL)
					addCr = 1;
				else
					addCr = 0;
			}	// end of segment parser

			// Set the category for the record
			if (PrvStreamSocket(inputStream)->appData) {
				UInt16	attr;
				Err		err;
				UInt16	categoryID = PrvStreamSocket(inputStream)->appData;

				// Get the attributes
				err = DmRecordInfo(dbP, indexNew, &attr, NULL, NULL);

				// Set them to include the category, and mark the record dirty
				if ((attr & dmRecAttrCategoryMask) != categoryID) {
					attr &= ~dmRecAttrCategoryMask;
					attr |= categoryID | dmRecAttrDirty;

⌨️ 快捷键说明

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