📄 utilsrecurrence.cpp
字号:
TIME_ZONE_INFORMATION tmz;
GetTimeZoneInformation(&tmz);
//----- server -> client => do not change date
z = (x-y) < 0 ? (x-y)*(-1) : (x-y) ;
//
// Change day? Backward and Forward are inverted because it is from utc to localtime
//
changeDay = z > 12 ? TRUE : FALSE;
if (changeDay) {
if (tmz.Bias < 0)
isBackward = FALSE;
else
isBackward = TRUE;
}
dummyEvent = getElementContent(ptrData, TEXT("RecurrenceType"), NULL);
if (dummyEvent != NULL && wcstol(dummyEvent, &dummy, 0) >= 0) {
pRecurrence->put_RecurrenceType(wcstol(dummyEvent, &dummy, 0));
delete [] dummyEvent;dummyEvent=NULL;
}
dummyEvent = getElementContent(ptrData, TEXT ("Interval"), NULL);
if (dummyEvent != NULL && wcstol(dummyEvent, &dummy, 0) > 0) {
pRecurrence->put_Interval(wcstol(dummyEvent, &dummy, 0));
delete [] dummyEvent;dummyEvent=NULL;
}
//
// Day of Month
//
dummyEvent = getElementContent(ptrData, TEXT ("DayOfMonth"), NULL);
if (dummyEvent != NULL && wcstol(dummyEvent, &dummy, 0) > 0) {
dayOfMonth = wcstol(dummyEvent, &dummy, 0);
if (changeDay) {
if (isBackward) {
dayOfMonth = dayOfMonth - 1;
if (dayOfMonth == 0) {
if (monthOfYear == 5 || monthOfYear == 7 || monthOfYear == 10) {
// if May, July, October the month before has 30 days
dayOfMonth = 30;
} else {
dayOfMonth = 31;
}
changeYearBackward = TRUE;
}
} else { // is
dayOfMonth = dayOfMonth + 1;
if (dayOfMonth > 31 ||
(dayOfMonth == 31 &&
(monthOfYear == 4 || monthOfYear == 6 || monthOfYear == 9)
)
) {
dayOfMonth = 1;
changeYearForward = TRUE;
}
}
}; //end if(changeDay)
pRecurrence->put_DayOfMonth(dayOfMonth);
delete [] dummyEvent;dummyEvent=NULL;
}
//
// Month of Year
//
dummyEvent = getElementContent(ptrData, TEXT ("MonthOfYear"), NULL);
if (dummyEvent != NULL && wcstol(dummyEvent, &dummy , 0) > 0) {
monthOfYear = wcstol(dummyEvent, &dummy , 0);
if (changeYearBackward) {
monthOfYear = monthOfYear - 1;
if (monthOfYear == 0) {
monthOfYear = 12;
}
} else if (changeYearForward) {
monthOfYear = monthOfYear + 1;
if (monthOfYear > 12) {
monthOfYear = 1;
}
}
pRecurrence->put_MonthOfYear(monthOfYear);
delete [] dummyEvent;dummyEvent=NULL;
}
//
// DayOfWeekMask
//
dummyEvent = getElementContent(ptrData, TEXT ("DayOfWeekMask"), NULL);
if (dummyEvent != NULL && wcstol(dummyEvent, &dummy, 0) > 0) {
dayOfWeekMask = wcstol(dummyEvent, &dummy, 0);
if (changeDay) {
if (isBackward) {
dayOfWeekMask = convertDayOfWeekMaskBackward(dayOfWeekMask);
} else {
dayOfWeekMask = convertDayOfWeekMaskForward(dayOfWeekMask);
}
}
pRecurrence->put_DayOfWeekMask(dayOfWeekMask);
delete [] dummyEvent;dummyEvent=NULL;
}
dummyEvent = getElementContent(ptrData, TEXT ("Instance"), NULL);
if (dummyEvent) {
if (wcstol(dummyEvent, &dummy, 0) > 0) {
pRecurrence->put_Instance(wcstol(dummyEvent, &dummy, 0));
}
delete [] dummyEvent; dummyEvent=NULL;
}
// Pattern Start Date
// -------------------
// We use recurrenceStart instead of PatternStartDate
// to handle timezone changes.
// PatternStartDate is used only as a backup if the others are not available
if (!recurrenceStart) {
dummyEvent = getElementContent(ptrData, TEXT("PatternStartDate"), NULL);
if (dummyEvent) {
// If is not empty, get it
if (*dummyEvent) {
recurrenceStart = getDATEFromString(dummyEvent);
}
delete [] dummyEvent; dummyEvent=NULL;
}
}
// Make sure the date is without the time part
recurrenceStart = (int)recurrenceStart;
pRecurrence->put_PatternStartDate(recurrenceStart);
if (dummyEvent) { delete [] dummyEvent; dummyEvent = NULL; }
//VARIANT_BOOL -- NoEndDate
dummyEvent = getElementContent(ptrData, TEXT ("NoEndDate"), NULL);
if (dummyEvent != NULL &&
(wcscmp(dummyEvent, TEXT("1")) == 0 ||
wcscmp(dummyEvent, TEXT("-1")) == 0 ||
wcscmp(dummyEvent, TEXT("True")) == 0)) {
pRecurrence->put_NoEndDate(VARIANT_TRUE);
} else {
pRecurrence->put_NoEndDate(VARIANT_FALSE);
//Pattern End Date
dummyEvent = getElementContent(ptrData, TEXT ("PatternEndDate"), NULL);
// If not null and not empty, parse it
if (dummyEvent && *dummyEvent) {
DATE en = getDATEFromString(dummyEvent);
pRecurrence->put_PatternEndDate(en);
delete [] dummyEvent; dummyEvent = NULL;
}
}
// Occurrences
//
dummyEvent = getElementContent(ptrData, TEXT ("Occurrences"), NULL);
if (dummyEvent != NULL && wcstol(dummyEvent, &dummy, 0) > 0) {
pRecurrence->put_Occurrences(wcstol(dummyEvent, &dummy , 0));
delete [] dummyEvent; dummyEvent = NULL;
}
}
/*
* Parse exceptions from server to client
*/
void parseExceptionTags(IRecurrencePattern* pRecurrence, IAppointment* pAppointment,
const wchar_t* ptrData, IP_OUTLOOK_APP* polApp,
const wchar_t* path) {
wchar_t* dummy = NULL;
wchar_t* dummyEvent = NULL;
wstring dummyEvent_s;
VARIANT_BOOL isNotAllDayEvent = TRUE;
unsigned int pos = 0;
dummyEvent = getElementContent(ptrData, TEXT ("Exceptions"), &pos);
if (dummyEvent != NULL) {
delete [] dummyEvent; dummyEvent = NULL;
// handling Exclude Date: they are the deleted exceptions
vector<RecurrenceException> exceptionsList;
vector<RecurrenceException>::iterator exceptionsListIterator;
exceptionsList = getExceptionList(pRecurrence, ptrData, EXCLUDE_DATE);
if (exceptionsList.size() > 0) {
pAppointment->Save();
}
for (exceptionsListIterator = exceptionsList.begin();
exceptionsListIterator != exceptionsList.end();
exceptionsListIterator++) {
if ((*exceptionsListIterator).isDeleted()) {
IAppointment* pExAppointment;
pRecurrence->GetOccurrence((*exceptionsListIterator).getOriginalDate(), &pExAppointment);
if(!pExAppointment) {
LOG.error("Error in handling calendar exception. Exc App is NULL. Date: %lu", (*exceptionsListIterator).getOriginalDate());
continue;
}
pExAppointment->Delete();
pExAppointment->Release();
}
}
exceptionsList.clear();
// handling including date
exceptionsList = getExceptionList(pRecurrence, ptrData, TEXT("IncludeDate"));
if (exceptionsList.size() > 0) {
long oid = 0;
vector<long> oids;
vector<long>::iterator oidsIterator;
pAppointment->Save();
pAppointment->get_Oid(&oid);
oids.push_back(oid);
for (exceptionsListIterator = exceptionsList.begin();
exceptionsListIterator != exceptionsList.end();
exceptionsListIterator++) {
if (!(*exceptionsListIterator).isDeleted()) {
oid = createAppointmentFromException(pAppointment, *exceptionsListIterator, polApp);
oids.push_back(oid);
}
}
writeOidToReset(oids, path);
}
}
}
/*
* Return the oid of the new appointment just inserted
*/
long createAppointmentFromException(IAppointment* pAppointment, RecurrenceException rec, IP_OUTLOOK_APP* polApp) {
IAppointment* pAppointmentCopy, *pAppointmentNew;
pAppointment->Copy(&pAppointmentCopy);
pAppointmentCopy->Save();
long oid = 0;
pAppointmentCopy->get_Oid(&oid);
pAppointmentCopy->Release();
polApp->GetItemFromOid (oid, (IDispatch**)&pAppointmentNew);
if (pAppointmentNew) {
DATE originaldate = rec.getOriginalDate();
DATE start = 0, end = 0;
pAppointment->get_Start(&start);
pAppointment->get_End(&end);
DATE offset = end - start;
end = (originaldate + offset);
pAppointmentNew->ClearRecurrencePattern();
pAppointmentNew->put_Start(originaldate);
pAppointmentNew->put_End(end);
pAppointmentNew->Save();
pAppointmentNew->Release();
}
return oid;
}
/*
* The file contains the oid of the appointment whose crc must be set to 0 during the
* creation of the cache file. It means to send to the server the right apppointmnet
* at the next sync
*/
void writeOidToReset(vector<long> oids, const wchar_t* wpath) {
wstring filename(L"appOidToReset.dat");
wstring path(wpath);
path += L"\\";
path += filename;
FILE* f;
f = _wfopen(path.c_str(), L"w+");
if (!f)
return;
int oidLength = oids.size();
for (int i = 0; i < oidLength; i++) {
long currentLongOid = oids[i];
fwprintf(f, TEXT("<oid>%i</oid>\n"), currentLongOid);
}
fflush(f);
fclose(f);
}
/*
* delete the occurrences of the recurrence if there are any between them
*/
void deleteIntraOccurrences(IRecurrencePattern* pRecurrence, DATE originalDate, DATE startDate) {
IAppointment* pExAppointment;
if (originalDate > startDate) {
for (originalDate-=1; originalDate > startDate; originalDate-=1) {
pRecurrence->GetOccurrence(originalDate, &pExAppointment);
if (pExAppointment) {
pExAppointment->Delete();
pExAppointment->Release();
}
}
} else {
for (originalDate+=1; originalDate < startDate; originalDate+=1) {
pRecurrence->GetOccurrence(originalDate, &pExAppointment);
if (pExAppointment) {
pExAppointment->Delete();
pExAppointment->Release();
}
}
}
}
vector<RecurrenceException> getExceptionList(IRecurrencePattern* pRecurrence,
const wchar_t* ptrData,
const wchar_t* action) {
wchar_t* dummy = NULL;
wchar_t* dummyEvent = NULL;
wstring dummyEvent_s;
VARIANT_BOOL isNotAllDayEvent = TRUE;
unsigned int pos = 0;
vector<RecurrenceException> listExceptions;
unsigned int previous = pos;
while ((dummyEvent = getElementContent(&ptrData[pos], (wchar_t*)action, &pos)) != NULL) {
if (wcscmp(dummyEvent, TEXT("")) == 0) {
pos += previous;
previous = pos;
continue;
}
BOOL isAllDayFormat = FALSE;
DATE originalDate;
RecurrenceException rec;
isAllDayFormat = isDateForAllDayEventFormat(dummyEvent);
if (isAllDayFormat) {
systemTimeToDoubleBirthFormat(dummyEvent, &originalDate, TEXT("START")); // put 00:00 for the date
} else {
systemTimeToDouble(dummyEvent, &originalDate, NULL);
}
rec.setOriginalDate(originalDate);
if (wcscmp(action, EXCLUDE_DATE) == 0) {
rec.setIsDeleted(TRUE);
} else {
rec.setIsDeleted(FALSE);
rec.setAllDayEvent(isAllDayFormat);
}
pos += previous;
previous = pos;
listExceptions.push_back(rec);
}
return listExceptions;
}
/*
* Try to check if exists already an occurrence in that date...
* If exists it delete the existing ont to insert the other appointment exception
*/
BOOL checkAlreadyAnException(IRecurrencePattern* pRecurrence, DATE originalDate, DATE startDate) {
IAppointment* pApp;
pRecurrence->GetOccurrence(startDate, &pApp);
if (pApp) {
if ((int)originalDate - (int)startDate) {
LOG.info("An exception of the calendar already exists. Delete it to insert the new one");
pApp->Delete();
pApp->Release();
return TRUE;
}
}
return FALSE;
}
/*
* The date in all day event format is yyyy-MM-dd
* To discover if it is in this format find the '-' char inside the string
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -