📄 vutils.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/**************************************************************************/
/* VUtils.cpp */
/* */
/* This file contains utility routines to process VCARDS/VCAL's */
/* */
/* DISCLAIMER!!!: this does not FULLY support the vCard/vCalc spec */
/* it is intended as an example to the OBEX Inbox and nothing more */
/* I dont believe it will cause harm or behave strangly, but use it */
/* at your own risk! */
/* */
/* Functions included: */
/* getVCalStateObj -- singleton toget a pointer to vCal state info*/
/* vCardInputFunct -- used to handle globals/input conversion */
/* for vCard's (used in LOOKUP TABLE) */
/* vCalInputFunct -- used to handle globals/input conversion */
/* for vCal's (used in LOOKUP TABLE) */
/* _stricmp -- backwards compatiblity for HPC, is _stricmp */
/* StartDateToFileTime -- convert vCard time into FILETIME struct */
/* UnicodeToChar -- convert UNICODE to CHAR string */
/* */
/* ParseVCard -- parse out vCard... look for BEGIN/END */
/* ParseMajorComponents -- parse out major components from vCard */
/* stuff like TYPE, PARAMS, VALUE */
/* ParseLine -- take a vCard line and parse out FIELD info */
/* ParseFields -- do VALUE/FIELD parsing that ParseLine didnt */
/* */
/* */
/* Other related files: */
/* */
/* */
/**************************************************************************/
#include "VUtils.h"
//LOOKUP TABLE DEFINATIONS-------------------------------------------------
// g_sContactOidTranslator contains information on where to store
// information on an individual line from a vCard. The idea is this:
//
// 1. Fetch a line entry from a vCard
// 2. Parse out fields (and ordinal numbers for entry locations)
// this includes the name field, value, and parameters
// 3. Search through the folling table, looking for iOrd and
// a match on the name field. Once found, send each of the values
// through the inputFunction to handle initing global values
// and conversion to the correct type of CEPROPVAL struct
//
// DESCRIPTION OF FIELDS:
// Field: Description:
// 1. Field Name -- the name given by the VCard/cal spec
// 2. Conversion function ptr to convert the record to
// something that can be sent in a vcard
// *used for output*
// 3. Input fuction-- used to handle global values
// and conversion into CEPROPVAL struct. Use this
// to convert incoming data into format that can
// be used by the PocketPC
// 4. Record ID of the database entry
// 5. Ordinal # of the value in the vCard entry
// for example, on a N: (name field in vCard)
// the field is filled out like this:
// N:<last><first>.... the last name would have
// ordinal 1 and the first name 2... for items
// that only have one value (TITLE for exampe)
// set ORD to be 1
//#ifdef VCAL // <-- VCAL table
OID_TRANSLATOR g_sCalendarOidTranslator[] = {
//Name fields
{"DESCRIPTION:", UnicodeToChar, vCalInputFunct, HHPR_SUBJECT, 1, },
{"LOCATION:", UnicodeToChar, vCalInputFunct, HHPR_APPT_LOCATION, 1, },
{"DTSTART:", StartDateToFileTime, vCalInputFunct, HHPR_APPT_START_WHOLE, 1, },
{"DTEND:", StartDateToFileTime, vCalInputFunct, HHPR_APPT_DURATION, 1, },
};
UINT g_CalendarSize = ARRAYSIZE(g_sCalendarOidTranslator);
//#endif
//#ifdef VCARD // <-- vCard Table
OID_TRANSLATOR g_sContactOidTranslator[] = {
//Name fields
{"N:", UnicodeToChar, vCardInputFunct, PR_SURNAME_W, 1, },
{"N:", UnicodeToChar, vCardInputFunct, PR_GIVEN_NAME_W, 2, },
{"N:", UnicodeToChar, vCardInputFunct, HHPR_NAME_PREFIX, 4, },
{"N:", UnicodeToChar, vCardInputFunct, PR_GENERATION_W, 5, },
//home address fields
{"ADR;TYPE=home:", UnicodeToChar, vCardInputFunct, HHPR_HOME_ADDRESS_STREET, 3},
{"ADR;TYPE=home:", UnicodeToChar, vCardInputFunct, HHPR_HOME_ADDRESS_CITY, 4},
{"ADR;TYPE=home:", UnicodeToChar, vCardInputFunct, HHPR_HOME_ADDRESS_STATE, 5},
{"ADR;TYPE=home:", UnicodeToChar, vCardInputFunct, HHPR_HOME_ADDRESS_POSTAL_CODE, 6},
{"ADR;TYPE=home:", UnicodeToChar, vCardInputFunct, HHPR_HOME_ADDRESS_COUNTRY, 7},
//office address fields
{"ADR;TYPE=work:", UnicodeToChar, vCardInputFunct, HHPR_OFFICE_ADDRESS_STREET, 3},
{"ADR;TYPE=work:", UnicodeToChar, vCardInputFunct, HHPR_OFFICE_ADDRESS_CITY, 4},
{"ADR;TYPE=work:", UnicodeToChar, vCardInputFunct, HHPR_OFFICE_ADDRESS_STATE, 5},
{"ADR;TYPE=work:", UnicodeToChar, vCardInputFunct, HHPR_OFFICE_ADDRESS_POSTAL_CODE, 6},
{"ADR;TYPE=work:", UnicodeToChar, vCardInputFunct, HHPR_OFFICE_ADDRESS_COUNTRY, 7},
//phone number fields
{"TEL;TYPE=work:", UnicodeToChar, vCardInputFunct, PR_BUSINESS_TELEPHONE_NUMBER_W, 1},
{"TEL;TYPE=car:", UnicodeToChar, vCardInputFunct, PR_CAR_TELEPHONE_NUMBER_W, 1},
{"TEL;TYPE=home:", UnicodeToChar, vCardInputFunct, PR_HOME_TELEPHONE_NUMBER_W, 1},
{"TEL;TYPE=cell:", UnicodeToChar, vCardInputFunct, PR_CELLULAR_TELEPHONE_NUMBER_W, 1},
{"TEL;TYPE=pref:", UnicodeToChar, vCardInputFunct, PR_PRIMARY_TELEPHONE_NUMBER_W, 1},
//email addresses
{"EMAIL;TYPE=internet,pref:", UnicodeToChar, vCardInputFunct, HHPR_EMAIL1_EMAIL_ADDRESS,1},
{"EMAIL;TYPE=internet,pref:", UnicodeToChar, vCardInputFunct, HHPR_EMAIL2_EMAIL_ADDRESS,1},
//title
{"TITLE:", UnicodeToChar, vCardInputFunct, PR_TITLE_W, 1},
//company/organization
{"ORG:", UnicodeToChar, vCardInputFunct, PR_COMPANY_NAME_W, 1},
//---** when nothing else fits, give one of these a try
{"ADR:", UnicodeToChar, vCardInputFunct, HHPR_HOME_ADDRESS_STREET, 3},
{"ADR:", UnicodeToChar, vCardInputFunct, HHPR_HOME_ADDRESS_CITY, 4},
{"ADR:", UnicodeToChar, vCardInputFunct, HHPR_HOME_ADDRESS_STATE, 5},
{"ADR:", UnicodeToChar, vCardInputFunct, HHPR_HOME_ADDRESS_POSTAL_CODE, 6},
{"ADR:", UnicodeToChar, vCardInputFunct, HHPR_HOME_ADDRESS_COUNTRY, 7},
{"EMAIL;TYPE=HOME:", UnicodeToChar, vCardInputFunct, HHPR_EMAIL1_EMAIL_ADDRESS,1},
{"EMAIL;TYPE=PREF:", UnicodeToChar, vCardInputFunct, HHPR_EMAIL1_EMAIL_ADDRESS,1},
{"EMAIL;TYPE=INTERNET:", UnicodeToChar, vCardInputFunct, HHPR_EMAIL1_EMAIL_ADDRESS,1}
};
UINT g_ContactSize = ARRAYSIZE(g_sContactOidTranslator);
//#endif
/*****************************************************************************/
/* Function: vCardInputFunct */
/* convert data sent to this into a format compatible with the CE database */
/* */
/* RETURN a pointer to a CEPROPVAL (that must be destroyed later) */
/* describing the new database item */
/* */
/* Begin by converting the string into unicode, and replacing \r with */
/* ' ' */
/*****************************************************************************/
CEPROPVAL *vCardInputFunct(CEPROPID propID, LPSTR type, LPSTR pField, void *pState)
{
CEPROPVAL *prop = new CEPROPVAL;
memset(prop, 0, sizeof(CEPROPVAL));
prop->propid = propID;
int size,j;
size = MultiByteToWideChar(CP_ACP,
0,
pField,
-1,
0,
0);
ASSERT(size);
prop->val.lpwstr = new WCHAR [size];
MultiByteToWideChar(CP_ACP, 0, pField, -1,
prop->val.lpwstr, size);
//replace all \r's....
for(j=0; j<size; j++)
{
if(prop->val.lpwstr[j] == '\r')
prop->val.lpwstr[j] = ' ';
}
//take note of the propID... if its for SURNAME or GIVEN_NAME, put the value into
// global space
if(PR_SURNAME_W == propID)
{
VCardStateObj *pVCState = (VCardStateObj *)pState;
pVCState->pSurName = prop;
}
else if(PR_GIVEN_NAME_W == propID)
{
VCardStateObj *pVCState = (VCardStateObj *)pState;
pVCState->pGiven = prop;
}
return prop;
}
/*****************************************************************************/
/* Function: vCalInputFunct */
/* convert data sent to this into a format compatible with the CE database */
/* */
/* RETURN a pointer to a CEPROPVAL (that must be destroyed later) */
/* describing the new database item */
/* */
/* Begin by determining what TYPE of data this is */
/* for TIME's do a convertion into the FILETIME stuct used by CE */
/*****************************************************************************/
CEPROPVAL *vCalInputFunct(CEPROPID propID, LPSTR type, LPSTR pField, void *pState)
{
CEPROPVAL *prop = new CEPROPVAL;
memset(prop, 0, sizeof(CEPROPVAL));
prop->propid = propID;
ASSERT(pState);
//if this is the end, store the value into a global
if(strcmp(type, "DTEND:") == 0)
{
VCalStateObj *pGlobal = (VCalStateObj *)pState;
if(!pGlobal->stopTime) pGlobal->stopTime = new FILETIME;
StartDateToFileTime(pField, pGlobal->stopTime);
delete prop;
return 0;
}
//mark the start time
else if(strcmp(type, "DTSTART:") == 0)
{
VCalStateObj *pGlobal = (VCalStateObj *)pState;
if(!pGlobal->startTime) pGlobal->startTime = new FILETIME;
StartDateToFileTime(pField, pGlobal->startTime);
StartDateToFileTime(pField, &prop->val.filetime);
return prop;
}
//if its a STRING, do the uncode conversion
else if(LOWORD(propID) == CEVT_LPWSTR)
{
int size,j;
size = MultiByteToWideChar(CP_ACP,
0,
pField,
-1,
0,
0);
ASSERT(size);
prop->val.lpwstr = new WCHAR [size];
MultiByteToWideChar(CP_ACP, 0, pField, -1,
prop->val.lpwstr, size);
//replace all \r's....
for(j=0; j<size; j++)
{
if(prop->val.lpwstr[j] == '\r')
prop->val.lpwstr[j] = ' ';
}
return prop;
}
delete prop;
return 0;
}
/*****************************************************************************/
/* Function: StartDateToFileTime */
/* Do a convertion from a text string in the format */
/* <YYYY><MM><DD>T<HH><MM><SS> */
/* */
/* After conversion, put the results into a FILETIME struct */
/*****************************************************************************/
BOOL StartDateToFileTime(LPSTR dta, LPFILETIME pFileTime)
{
UINT dLen = strlen(dta);
SYSTEMTIME sTime;
char year[5];
char month[3];
char day[3];
if(dLen >= 8)
{
memcpy(year, dta, 4);
year[4] = 0;
memcpy(month, &dta[4], 2);
month[2] = 0;
memcpy(day, &dta[6], 2);
day[2] = 0;
//clear out the system time
memset(&sTime, 0, sizeof(SYSTEMTIME));
//copy in the values..
sTime.wYear = atoi(year);
sTime.wDay = atoi(day);
sTime.wMonth = atoi(month);
//now see if there is a time field
if(dLen >= 15)
{
char hour[3];
char min[3];
char sec[3];
memcpy(hour, &dta[9], 2);
hour[2] = 0;
memcpy(min, &dta[11], 2);
min[2] = 0;
memcpy(sec, &dta[13], 2);
sec[2] = 0;
sTime.wHour += atoi(hour);
sTime.wMinute = atoi(min);
sTime.wSecond = atoi(sec);
}
//BUGBUG: this conversion ISNT GOOD for all places! this is just for Seattle....
BOOL ret = SystemTimeToFileTime(&sTime, pFileTime);
_int64 time = pFileTime->dwHighDateTime;
time <<= 32;
time |= pFileTime->dwLowDateTime;
_int64 adj = 7;
adj *= 10000000;
adj *= 60;
adj *= 60;
time += adj;
pFileTime->dwHighDateTime = (DWORD)((time >> 32) & 0x00000000ffffffff);
pFileTime->dwLowDateTime = (DWORD)(time & 0x00000000ffffffff);
return ret;
}
else
{
return 0;
}
}
/*****************************************************************************/
/* Function: UnicodeToChar */
/* convert a UNICODE string into a byte string */
/* */
/* BUGBUG: DOES NOT HANDLE LANGUAGES OTHER THAN ENGISH! */
/* */
/* WARNING: this function ALLOCATES MEMORY that MUST BE FREED BY CALLER!! */
/* */
/* NOTE: this does the conversion required for vCard (escape chars) */
/*****************************************************************************/
char *UnicodeToChar(LPTSTR dta)
{
char *retBuf;
//convert the string from unicode
int requiredSize =
WideCharToMultiByte (CP_ACP, 0, dta, -1, 0, 0, NULL, NULL);
retBuf = new char[requiredSize];
if(!retBuf)
return 0;
if(WideCharToMultiByte (CP_ACP,
0,
dta,
-1,
retBuf,
requiredSize,
NULL,
NULL) == 0)
{
delete [] retBuf;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -