123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429 |
- #include <kopano/platform.h>
- #include <utility>
- #include "vtimezone.h"
- #include <mapidefs.h>
- #include <mapicode.h>
- #include <cstdlib>
- #include <cmath>
- #include <ctime>
- using namespace std;
- namespace KC {
- time_t icaltime_as_timet_with_server_zone(const struct icaltimetype tt)
- {
- struct tm stm;
- time_t t;
-
- if (icaltime_is_null_time(tt)) {
- return 0;
- }
-
- memset (&stm, 0, sizeof (struct tm));
- if (icaltime_is_date(tt)) {
- stm.tm_sec = stm.tm_min = stm.tm_hour = 0;
- } else {
- stm.tm_sec = tt.second;
- stm.tm_min = tt.minute;
- stm.tm_hour = tt.hour;
- }
- stm.tm_mday = tt.day;
- stm.tm_mon = tt.month-1;
- stm.tm_year = tt.year-1900;
- stm.tm_isdst = -1;
- t = mktime(&stm);
- return t;
- }
- static time_t SystemTimeToUnixTime(const SYSTEMTIME &stime)
- {
- return stime.wSecond + (stime.wMinute*60) + ((stime.wHour)*60*60);
- }
- static SYSTEMTIME TMToSystemTime(const struct tm &t)
- {
- SYSTEMTIME stime = {0};
- stime.wYear = t.tm_year;
- stime.wMonth = t.tm_mon;
- stime.wDayOfWeek = t.tm_wday;
- stime.wDay = t.tm_mday;
- stime.wHour = t.tm_hour;
- stime.wMinute = t.tm_min;
- stime.wSecond = t.tm_sec;
- stime.wMilliseconds = 0;
- return stime;
- }
- time_t ICalTimeTypeToUTC(icalcomponent *lpicRoot, icalproperty *lpicProp)
- {
- time_t tRet = 0;
- icalparameter *lpicTZParam = NULL;
- const char *lpszTZID = NULL;
- icaltimezone *lpicTimeZone = NULL;
- lpicTZParam = icalproperty_get_first_parameter(lpicProp, ICAL_TZID_PARAMETER);
- if (lpicTZParam) {
- lpszTZID = icalparameter_get_tzid(lpicTZParam);
- lpicTimeZone = icalcomponent_get_timezone(lpicRoot, lpszTZID);
- }
- tRet = icaltime_as_timet_with_zone(icalvalue_get_datetime(icalproperty_get_value(lpicProp)), lpicTimeZone);
- return tRet;
- }
- time_t ICalTimeTypeToLocal(icalproperty *lpicProp)
- {
- return icaltime_as_timet_with_server_zone(icalvalue_get_datetime(icalproperty_get_value(lpicProp)));
- }
- static struct tm UTC_ICalTime2UnixTime(icaltimetype tt)
- {
- struct tm stm = {0};
- memset(&stm, 0, sizeof(struct tm));
- if (icaltime_is_null_time(tt))
- return stm;
- stm.tm_sec = tt.second;
- stm.tm_min = tt.minute;
- stm.tm_hour = tt.hour;
- stm.tm_mday = tt.day;
- stm.tm_mon = tt.month-1;
- stm.tm_year = tt.year-1900;
- stm.tm_isdst = -1;
- return stm;
- }
- static HRESULT HrZoneToStruct(icalcomponent_kind kind, icalcomponent *lpVTZ,
- TIMEZONE_STRUCT *lpsTimeZone)
- {
- icalcomponent *icComp = NULL;
- icalcomponent *iterComp = NULL;
- icalproperty *tzFrom, *tzTo, *rRule, *dtStart;
- icaltimetype icTime;
- SYSTEMTIME *lpSysTime = NULL;
- SYSTEMTIME stRecurTime;
- icalrecurrencetype recur;
-
- iterComp = icalcomponent_get_first_component(lpVTZ, kind);
- while (iterComp != NULL) {
- icTime = icalcomponent_get_dtstart(iterComp);
- icTime.is_utc = 1;
- struct tm start = UTC_ICalTime2UnixTime(icTime);
- if (time(NULL) < mktime(&start) && icComp != nullptr)
- break;
- icComp = iterComp;
- iterComp = icalcomponent_get_next_component(lpVTZ, kind);
- }
- if (icComp == NULL)
- return MAPI_E_NOT_FOUND;
- dtStart = icalcomponent_get_first_property(icComp, ICAL_DTSTART_PROPERTY);
- tzFrom = icalcomponent_get_first_property(icComp, ICAL_TZOFFSETFROM_PROPERTY);
- tzTo = icalcomponent_get_first_property(icComp, ICAL_TZOFFSETTO_PROPERTY);
- rRule = icalcomponent_get_first_property(icComp, ICAL_RRULE_PROPERTY);
-
- if (tzFrom == NULL || tzTo == NULL || dtStart == NULL)
- return MAPI_E_NOT_FOUND;
- icTime = icalcomponent_get_dtstart(icComp);
- icTime.is_utc = 1;
- if (kind == ICAL_XSTANDARD_COMPONENT) {
-
- lpsTimeZone->lBias = -(icalproperty_get_tzoffsetto(tzTo) / 60);
- lpsTimeZone->lStdBias = 0;
- lpsTimeZone->lDstBias = (icalproperty_get_tzoffsetto(tzTo) - icalproperty_get_tzoffsetfrom(tzFrom)) / 60;
- lpsTimeZone->wStdYear = 0;
- lpSysTime = &lpsTimeZone->stStdDate;
- } else {
- lpsTimeZone->wDstYear = 0;
- lpSysTime = &lpsTimeZone->stDstDate;
- }
- memset(lpSysTime, 0, sizeof(SYSTEMTIME));
-
- if (!rRule) {
- stRecurTime = TMToSystemTime(UTC_ICalTime2UnixTime(icTime));
- lpSysTime->wMonth = stRecurTime.wMonth + 1;
- lpSysTime->wDayOfWeek = stRecurTime.wDayOfWeek;
- lpSysTime->wDay = int(stRecurTime.wDay / 7.0) + 1;
- lpSysTime->wHour = stRecurTime.wHour;
- lpSysTime->wMinute = stRecurTime.wMinute;
- return hrSuccess;
- }
- recur = icalproperty_get_rrule(rRule);
-
- if (recur.freq != ICAL_YEARLY_RECURRENCE ||
- recur.by_month[0] == ICAL_RECURRENCE_ARRAY_MAX ||
- recur.by_month[1] != ICAL_RECURRENCE_ARRAY_MAX)
- return hrSuccess;
- stRecurTime = TMToSystemTime(UTC_ICalTime2UnixTime(icTime));
- lpSysTime->wHour = stRecurTime.wHour;
- lpSysTime->wMinute = stRecurTime.wMinute;
- lpSysTime->wMonth = recur.by_month[0];
- if (icalrecurrencetype_day_position(recur.by_day[0]) == -1)
- lpSysTime->wDay = 5;
- else
- lpSysTime->wDay = icalrecurrencetype_day_position(recur.by_day[0]);
- lpSysTime->wDayOfWeek = icalrecurrencetype_day_day_of_week(recur.by_day[0]) - 1;
- return hrSuccess;
- }
- HRESULT HrParseVTimeZone(icalcomponent* lpVTZ, std::string* lpstrTZID, TIMEZONE_STRUCT* lpTimeZone)
- {
- HRESULT hr = hrSuccess;
- std::string strTZID;
- TIMEZONE_STRUCT tzRet;
- icalproperty *icProp = NULL;
- memset(&tzRet, 0, sizeof(TIMEZONE_STRUCT));
- icProp = icalcomponent_get_first_property(lpVTZ, ICAL_TZID_PROPERTY);
- if (icProp == NULL)
- return MAPI_E_CALL_FAILED;
- strTZID = icalproperty_get_tzid(icProp);
- if (strTZID.at(0) == '\"') {
-
- strTZID.erase(0, 1);
- strTZID.erase(strTZID.size()-1);
- }
- hr = HrZoneToStruct(ICAL_XSTANDARD_COMPONENT, lpVTZ, &tzRet);
- if (hr != hrSuccess)
- return hr;
-
- HrZoneToStruct(ICAL_XDAYLIGHT_COMPONENT, lpVTZ, &tzRet);
-
- {
- icalcomponent *icComp = NULL;
- icalproperty *tzSTDRule = NULL, *tzDSTRule = NULL;
- icalproperty *tzSTDDate = NULL, *tzDSTDate = NULL;
- icComp = icalcomponent_get_first_component(lpVTZ, ICAL_XSTANDARD_COMPONENT);
- if (icComp) {
- tzSTDRule = icalcomponent_get_first_property(icComp, ICAL_RRULE_PROPERTY);
- tzSTDDate = icalcomponent_get_first_property(icComp, ICAL_RDATE_PROPERTY);
- }
- icComp = icalcomponent_get_first_component(lpVTZ, ICAL_XDAYLIGHT_COMPONENT);
- if (icComp) {
- tzDSTRule = icalcomponent_get_first_property(icComp, ICAL_RRULE_PROPERTY);
- tzDSTDate = icalcomponent_get_first_property(icComp, ICAL_RDATE_PROPERTY);
- }
- if (tzSTDRule == NULL && tzDSTRule == NULL && tzSTDDate != NULL && tzDSTDate != NULL) {
-
- memset(&tzRet.stStdDate, 0, sizeof(SYSTEMTIME));
- memset(&tzRet.stDstDate, 0, sizeof(SYSTEMTIME));
- }
- }
- if (lpstrTZID)
- *lpstrTZID = std::move(strTZID);
- if (lpTimeZone)
- *lpTimeZone = tzRet;
- return hrSuccess;
- }
- HRESULT HrCreateVTimeZone(const std::string &strTZID, TIMEZONE_STRUCT &tsTimeZone, icalcomponent** lppVTZComp)
- {
- icalcomponent *icTZComp = NULL;
- icalcomponent *icComp = NULL;
- icaltimetype icTime;
- icalrecurrencetype icRec;
-
- if (tsTimeZone.stStdDate.wYear > 0 || tsTimeZone.stStdDate.wDay > 5 ||
- tsTimeZone.stStdDate.wDayOfWeek > 7 ||
- tsTimeZone.stDstDate.wYear > 0 || tsTimeZone.stDstDate.wDay > 5 ||
- tsTimeZone.stDstDate.wDayOfWeek > 7)
- return MAPI_E_INVALID_PARAMETER;
-
- icTZComp = icalcomponent_new(ICAL_VTIMEZONE_COMPONENT);
- icalcomponent_add_property(icTZComp, icalproperty_new_tzid(strTZID.c_str()));
-
- icComp = icalcomponent_new_xstandard();
- icTime = icaltime_from_timet_with_zone(SystemTimeToUnixTime(tsTimeZone.stStdDate), 0, nullptr);
- icalcomponent_add_property(icComp, icalproperty_new_dtstart(icTime));
- if (tsTimeZone.lStdBias == tsTimeZone.lDstBias || tsTimeZone.stStdDate.wMonth == 0 || tsTimeZone.stDstDate.wMonth == 0) {
-
- icalcomponent_add_property(icComp, icalproperty_new_tzoffsetfrom(-tsTimeZone.lBias *60));
- icalcomponent_add_property(icComp, icalproperty_new_tzoffsetto(-tsTimeZone.lBias *60));
- } else {
- icalcomponent_add_property(icComp, icalproperty_new_tzoffsetfrom( ((-tsTimeZone.lBias) + (-tsTimeZone.lDstBias)) *60) );
- icalcomponent_add_property(icComp, icalproperty_new_tzoffsetto(-tsTimeZone.lBias *60));
-
- icalrecurrencetype_clear(&icRec);
- icRec.freq = ICAL_YEARLY_RECURRENCE;
- icRec.interval = 1;
- icRec.by_month[0] = tsTimeZone.stStdDate.wMonth;
- icRec.by_month[1] = ICAL_RECURRENCE_ARRAY_MAX;
- icRec.week_start = ICAL_SUNDAY_WEEKDAY;
-
- icRec.by_day[0] = tsTimeZone.stStdDate.wDay == 5 ? -1*(8+tsTimeZone.stStdDate.wDayOfWeek+1) : (tsTimeZone.stStdDate.wDay)*8+tsTimeZone.stStdDate.wDayOfWeek+1;
- icRec.by_day[1] = ICAL_RECURRENCE_ARRAY_MAX;
-
- icalcomponent_add_property(icComp, icalproperty_new_rrule(icRec));
- }
- icalcomponent_add_component(icTZComp, icComp);
-
- if (tsTimeZone.lStdBias != tsTimeZone.lDstBias && tsTimeZone.stStdDate.wMonth != 0 && tsTimeZone.stDstDate.wMonth != 0) {
- icComp = icalcomponent_new_xdaylight();
- icTime = icaltime_from_timet_with_zone(SystemTimeToUnixTime(tsTimeZone.stDstDate), 0, nullptr);
- icalcomponent_add_property(icComp, icalproperty_new_dtstart(icTime));
- icalcomponent_add_property(icComp, icalproperty_new_tzoffsetfrom(-tsTimeZone.lBias *60));
- icalcomponent_add_property(icComp, icalproperty_new_tzoffsetto( ((-tsTimeZone.lBias) + (-tsTimeZone.lDstBias)) *60) );
-
- icalrecurrencetype_clear(&icRec);
- icRec.freq = ICAL_YEARLY_RECURRENCE;
- icRec.interval = 1;
- icRec.by_month[0] = tsTimeZone.stDstDate.wMonth;
- icRec.by_month[1] = ICAL_RECURRENCE_ARRAY_MAX;
- icRec.week_start = ICAL_SUNDAY_WEEKDAY;
- icRec.by_day[0] = tsTimeZone.stDstDate.wDay == 5 ? -1*(8+tsTimeZone.stDstDate.wDayOfWeek+1) : (tsTimeZone.stDstDate.wDay)*8+tsTimeZone.stDstDate.wDayOfWeek+1;
- icRec.by_day[1] = ICAL_RECURRENCE_ARRAY_MAX;
-
- icalcomponent_add_property(icComp, icalproperty_new_rrule(icRec));
- icalcomponent_add_component(icTZComp, icComp);
- }
- *lppVTZComp = icTZComp;
- return hrSuccess;
- }
- HRESULT HrGetTzStruct(const std::string &strTimezone, TIMEZONE_STRUCT *ttTimeZone)
- {
- icaltimezone *lpicTimeZone = NULL;
- icalcomponent *lpicComponent = NULL;
-
- if (strTimezone.empty())
- return MAPI_E_INVALID_PARAMETER;
- lpicTimeZone = icaltimezone_get_builtin_timezone(strTimezone.c_str());
- if (lpicTimeZone == NULL)
- return MAPI_E_NOT_FOUND;
- lpicComponent = icaltimezone_get_component(lpicTimeZone);
- if (lpicComponent == NULL)
- return MAPI_E_NOT_FOUND;
- return HrParseVTimeZone(lpicComponent, NULL, ttTimeZone);
- }
- }
|