📄 addresstransfer.c
字号:
* FUNCTION: TransferImportVCard
*
* DESCRIPTION: Import a VCard 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
*
* RETURNS: true if the input was read
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* rsf 4/24/97 Initial Revision
* bhall 8/12/99 moved category beaming code from gromit codeline
* ABa 6/20/00 Integrate Pdi library
*
*************************************************************/
Boolean TransferImportVCard(DmOpenRef dbP, UInt16 pdiRefNum, PdiReaderType* reader, Boolean obeyUniqueIDs, Boolean beginAlreadyRead)
{
volatile AddrDBRecordType newRecord;
AddressPhoneLabels phoneLabel;
UInt16 phoneField;
UInt16 indexNew;
UInt16 indexOld;
UInt32 uid;
Err err;
UInt32 uniqueID;
volatile Err error = 0;
UInt16 property;
Char* addressBufferP = NULL;
Char* nameBufferP = NULL;
UInt16 i;
UInt16 categoryID;
char categoryName[dmCategoryLength];
// if we have ExgManager socket
if (reader->appData != NULL)
{
categoryID = ((ExgSocketPtr)(reader->appData))->appData;
}
// Initialize a new record
for (i=0; i < addrNumFields; i++)
newRecord.fields[i] = NULL; // clear the record
newRecord.options.phones.phone1 = 0; // Work
newRecord.options.phones.phone2 = 1; // Home
newRecord.options.phones.phone3 = 2; // Fax
newRecord.options.phones.phone4 = 7; // Other
newRecord.options.phones.phone5 = 3; // Email
newRecord.options.phones.displayPhoneForList = phone1 - firstPhoneField;
uid = 0;
ErrTry
{
TraceOutput(TL(appErrorClass, __FILE__ ":TransferImportVCard:%d", __LINE__));
phoneField = firstPhoneField;
if (!beginAlreadyRead)
{
PdiReadProperty(pdiRefNum, reader);
beginAlreadyRead = reader->property == kPdiPRN_BEGIN_VCARD;
}
// if not "BEGIN:VCARD"
if (!beginAlreadyRead)
ErrThrow(exgErrBadData);
PdiEnterObject(pdiRefNum, reader);
PdiDefineResizing(pdiRefNum, reader, 16, tableMaxTextItemSize);
TraceOutput(TL(appErrorClass, __FILE__ ":TransferImportVCard:%d", __LINE__));
while (PdiReadProperty(pdiRefNum, reader) == 0 && (property = reader->property) != kPdiPRN_END_VCARD)
{
TraceOutput(TL(appErrorClass, "TransferImportVCard (PdiReadProperty): property = %s", reader->propertyName));
switch(property)
{
case kPdiPRN_N:
PdiReadPropertyField(pdiRefNum, reader, (Char **) &newRecord.fields[name], kPdiResizableBuffer, kPdiDefaultFields);
PdiReadPropertyField(pdiRefNum, reader, (Char **) &newRecord.fields[firstName], kPdiResizableBuffer, kPdiDefaultFields);
break;
case kPdiPRN_ADR:
{
UInt8 n = 0;
UInt16 totalSize;
Char* addressPostOfficeP = NULL;
Char* addressExtendedP = NULL;
Char* strings[3];
PdiReadPropertyField(pdiRefNum, reader, &addressPostOfficeP, kPdiResizableBuffer, kPdiDefaultFields);
PdiReadPropertyField(pdiRefNum, reader, &addressExtendedP, kPdiResizableBuffer, kPdiDefaultFields);
PdiReadPropertyField(pdiRefNum, reader, (Char **) &newRecord.fields[address], kPdiResizableBuffer, kPdiDefaultFields);
PdiReadPropertyField(pdiRefNum, reader, (Char **) &newRecord.fields[city], kPdiResizableBuffer, kPdiDefaultFields);
PdiReadPropertyField(pdiRefNum, reader, (Char **) &newRecord.fields[state], kPdiResizableBuffer, kPdiDefaultFields);
PdiReadPropertyField(pdiRefNum, reader, (Char **) &newRecord.fields[zipCode], kPdiResizableBuffer, kPdiDefaultFields);
PdiReadPropertyField(pdiRefNum, reader, (Char **) &newRecord.fields[country], kPdiResizableBuffer, kPdiDefaultFields);
if (newRecord.fields[address] != NULL)
{
strings[n++] = newRecord.fields[address];
totalSize += StrLen(newRecord.fields[address]);
}
if (addressPostOfficeP != NULL)
{
strings[n++] = addressPostOfficeP;
totalSize += StrLen(addressPostOfficeP);
}
if (addressExtendedP != NULL)
{
strings[n++] = addressExtendedP;
totalSize += StrLen(addressExtendedP);
}
if (addressPostOfficeP != NULL || addressExtendedP != NULL)
{
Char* result = NULL;
totalSize += (n - 1) * (sizeOf7BitChar(linefeedChr) + sizeOf7BitChar(spaceChr)) + sizeOf7BitChar(nullChr);
if (totalSize > tableMaxTextItemSize)
{
totalSize = tableMaxTextItemSize;
}
result = MemHandleLock(MemHandleNew(totalSize));
if (result != NULL)
{
*result = 0;
while (n > 0)
{
n--;
StrNCat(result, strings[n], totalSize);
if (n != 0)
{
StrNCat(result, "\n ", totalSize);
}
}
}
if (addressPostOfficeP != NULL)
{
MemPtrFree(addressPostOfficeP);
}
if (addressExtendedP != NULL)
{
MemPtrFree(addressExtendedP);
}
if (newRecord.fields[address] != NULL && result != NULL)
{
MemPtrFree(newRecord.fields[address]);
}
if (result != NULL)
{
newRecord.fields[address] = result;
}
}
}
break;
case kPdiPRN_FN:
// Take care of FN iff no name nor first name.
if (newRecord.fields[name] == NULL && newRecord.fields[firstName] == NULL)
{
PdiReadPropertyField(pdiRefNum, reader, (Char **) &newRecord.fields[name], kPdiResizableBuffer, kPdiDefaultFields);
}
break;
case kPdiPRN_NICKNAME:
// Take care of nickname iff no first name.
if (newRecord.fields[firstName] == NULL)
{
PdiReadPropertyField(pdiRefNum, reader, (Char **) &newRecord.fields[firstName], kPdiResizableBuffer, kPdiDefaultFields);
}
break;
case kPdiPRN_ORG:
PdiReadPropertyField(pdiRefNum, reader, (Char **) &newRecord.fields[company], kPdiResizableBuffer, kPdiConvertSemicolon);
break;
case kPdiPRN_TITLE:
PdiReadPropertyField(pdiRefNum, reader, (Char **) &newRecord.fields[title], kPdiResizableBuffer, kPdiConvertSemicolon);
break;
case kPdiPRN_NOTE:
PdiDefineResizing(pdiRefNum, reader, 16, noteViewMaxLength);
PdiReadPropertyField(pdiRefNum, reader, (Char **) &newRecord.fields[note], kPdiResizableBuffer, kPdiNoFields);
PdiDefineResizing(pdiRefNum, reader, 16, tableMaxTextItemSize);
break;
case kPdiPRN_X_PALM_CATEGORY:
{
Char* categoryStringP = NULL;
PdiReadPropertyField(pdiRefNum, reader, &categoryStringP, kPdiResizableBuffer, kPdiNoFields);
if (categoryStringP != NULL)
{
// Make a copy
StrNCopy(categoryName, categoryStringP, dmCategoryLength - 1);
categoryName[dmCategoryLength - 1] = 0;
// Free the string (Imc routines allocate the space)
MemPtrFree(categoryStringP);
// If we ever decide to use vCard 3.0 CATEGORIES, we would need to skip additional ones here
}
}
break;
case kPdiPRN_TEL:
case kPdiPRN_EMAIL:
if (phoneField <= lastPhoneField)
{
if (reader->property == kPdiPRN_EMAIL)
{
phoneLabel = emailLabel;
}
else if (PdiParameterPairTest(reader, kPdiPAV_TYPE_FAX))
{
phoneLabel = faxLabel;
}
else if (PdiParameterPairTest(reader, kPdiPAV_TYPE_PAGER))
{
phoneLabel = pagerLabel;
}
else if (PdiParameterPairTest(reader, kPdiPAV_TYPE_CAR) || PdiParameterPairTest(reader, kPdiPAV_TYPE_CELL))
{
phoneLabel = mobileLabel;
}
else if (PdiParameterPairTest(reader, kPdiPAV_X_X_PALM_MAIN))
{
phoneLabel = mainLabel;
}
else if (PdiParameterPairTest(reader, kPdiPAV_TYPE_HOME))
{
phoneLabel = homeLabel;
}
else if (PdiParameterPairTest(reader, kPdiPAV_TYPE_WORK))
{
phoneLabel = workLabel;
}
else
{
phoneLabel = otherLabel;
}
SetPhoneLabel(&newRecord, phoneField, phoneLabel);
if (PdiParameterPairTest(reader, kPdiPAV_TYPE_PREF))
{
newRecord.options.phones.displayPhoneForList = phoneField - firstPhoneField;
}
PdiReadPropertyField(pdiRefNum, reader, (Char **) &newRecord.fields[phoneField], kPdiResizableBuffer, kPdiNoFields);
if (newRecord.fields[phoneField] != NULL)
{
phoneField++;
}
}
break;
case kPdiPRN_X_PALM_CUSTOM:
ErrNonFatalDisplayIf(reader->customFieldNumber >= (lastRenameableLabel - firstRenameableLabel + 1),
"Invalid Custom Field");
PdiReadPropertyField(pdiRefNum, reader, (Char **) &newRecord.fields[custom1 + reader->customFieldNumber],
kPdiResizableBuffer, kPdiNoFields);
break;
case kPdiPRN_BEGIN_VCARD:
TransferImportVCard(dbP, pdiRefNum, reader, obeyUniqueIDs, true);
break;
}
} // end while
// We don't have to search for the pref phone, because we are sure it is not null
// (or it is but there was no TEL or EMAIL property in the vcard and so the
// displayList is firstPhoneField)
// if the company and name fields are identical, assume company only
if (newRecord.fields[name] != NULL
&& newRecord.fields[company] != NULL
&& newRecord.fields[firstName] == NULL
&& StrCompare(newRecord.fields[name], newRecord.fields[company]) == 0)
{
MemPtrFree(newRecord.fields[name]);
newRecord.fields[name] = NULL;
}
// Before adding the record verify that one field at least in non NULL
for (i = 0; i < addrNumFields; i++)
{
if (newRecord.fields[i] != NULL)
goto addRecord;
}
// All fields are NULL: not really an error but we must not add the record
ErrThrow(errNone);
addRecord:
err = AddrDBNewRecord(dbP, (AddrDBRecordType*)&newRecord, &indexNew);
// Memory error ?
if (err)
ErrThrow(exgMemError);
#ifdef VCARD_CATEGORIES
// If a category was included, try to use it
if (categoryName[0])
{
UInt16 categoryID;
UInt16 attr;
Err err;
// Get the category ID
categoryID = CategoryFind(dbP, categoryName);
// If it doesn't exist, and we have room, create it
if (categoryID == dmAllCategories)
{
// Find the first unused category
categoryID = CategoryFind(dbP, "");
// If there is a slot, fill it with the name we were given
if (categoryID != dmAllCategories)
{
CategorySetName(dbP, categoryID, categoryName);
}
}
// Set the category for the record
if (categoryID != dmAllCategories)
{
// 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;
err = DmSetRecordInfo(dbP, indexNew, &attr, NULL);
}
}
}
#endif
// Set the category for the record
if (categoryID)
{
UInt16 attr;
Err err;
// 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;
err = DmSetRecordInfo(dbP, indexNew, &attr, NULL);
}
}
// If uid was set then a unique id was passed to be used.
if (uid != 0 && obeyUniqueIDs)
{
// We can't simply remove any old record using the unique id and
// then add the new record because removing the old record could
// move the new one. So, we find any old record, change the new
// record, and then remove the old one.
indexOld = indexNew;
// Find any record with this uid. indexOld changes only if
// such a record is found.
DmFindRecordByID (dbP, uid, &indexOld);
// Change this record to this uid. The dirty bit is set from
// newly making this record.
DmSetRecordInfo(dbP, indexNew, NULL, &uid);
// Now remove any old record.
if (indexOld != indexNew)
{
DmRemoveRecord(dbP, indexOld);
}
}
// Store the information necessary to navigate to the record inserted.
DmRecordInfo(dbP, indexNew, NULL, &uniqueID, NULL);
// DOLATER ABa: About the goto code if think I will remove this hack
// and add a thing like;
// if (I'm sure data is comming from exchange manager) then
// PrvTransferSetGoToParams.
// Why not a ExgSocketPtr in reader ?
// != NULL <=> I'm sure data is comming from exchange manager
// Or removing this call (and last one) from Import and storing indexNew
// in the reader structure (userdata). This will save time when importing a whole category
#if EMULATION_LEVEL != EMULATION_NONE
// Don't call PrvTransferSetGoToParams for shell commands. Do this by seeing which
// input function is passed - the one for shell commands or the local one for exchange.
if (reader->appData != NULL)
#endif
PrvTransferSetGoToParams (dbP, (ExgSocketPtr)(reader->appData), uniqueID);
;
TraceOutput(TL(appErrorClass, __FILE__ ":TransferImportVCard:%d", __LINE__));
} //end of ErrTry
ErrCatch(inErr)
{
// Throw the error after the memory is cleaned up.
error = inErr;
} ErrEndCatch
// Free any temporary buffers used to store the incoming data.
for (i=0; i < addrNumFields; i++)
{
if (newRecord.fields[i] != NULL)
{
MemPtrFree(newRecord.fields[i]);
newRecord.fields[i] = NULL; // clear the record
}
}
// misformed vCard (no BEGIN:xxx): we must stop the import
if (error == exgErrBadData)
return false;
// in other case (typically a memory error) we must throw up the error
if (error != errNone)
ErrThrow(error);
// if no error we must inform caller to continue iff not EOF
return ((reader->events & kPdiEOFEventMask) == 0);
}
/************************************************************
*
* FUNCTION: TransferExportVCard
*
* DESCRIPTION: Export a record as a Imc VCard record
*
* PARAMETERS:
* dbP - pointer to the database to export the records from
* index - the record number to export
* recordP - whether the begin statement has been read
* outputStream - pointer to where to export the record to
* outputFunc - function to send output to the stream
* writeUniqueIDs - true to write the record's unique id
*
* RETURNS: nothing
*
* HISTORY:
* 08/06/97 rsf Created by Roger Flores
* 06/09/99 grant Ensure that phone numbers labeled "other" aren't
* tagged as ";WORK" or ";HOME".
* 08/12/99 bhall moved category beaming code from gromit codeline
* 10/30/99 kwk Use TxtGetChar before calling TxtCharIsDigit.
* ABa 6/20/00 Integrate Pdi library
*
*************************************************************/
void TransferExportVCard(DmOpenRef dbP, Int16 index, AddrDBRecordType *recordP,
UInt16 pdiRefNum, PdiWriterType* writer, Boolean writeUniqueIDs)
{
int i;
UInt32 uid;
AddrAppInfoPtr appInfoP= NULL;
Char uidString[12];
Boolean personOnlyAtHome = false;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -