forked from weirdhome
Fork of HTTPClient by
Diff: data/HTTPiCal.cpp
- Revision:
- 39:21fc7a4b6927
- Child:
- 40:bcb19f8dbba3
diff -r 2ef07232f65c -r 21fc7a4b6927 data/HTTPiCal.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/data/HTTPiCal.cpp Fri Mar 10 02:53:09 2017 +0000 @@ -0,0 +1,696 @@ +#include "HTTPiCal.h" + +#define DEBUG "iCal" +#include <cstdio> +#if (defined(DEBUG) && !defined(TARGET_LPC11U24)) +#define DBG(x, ...) std::printf("[DBG %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); +#define WARN(x, ...) std::printf("[WRN %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); +#define ERR(x, ...) std::printf("[ERR %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); +#define INFO(x, ...) std::printf("[INF %s %3d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); +#else +#define DBG(x, ...) +#define WARN(x, ...) +#define ERR(x, ...) +#define INFO(x, ...) +#endif + +HTTPiCal::HTTPiCal(int count) { + EventList = (Event_T *)malloc(count * sizeof(Event_T)); + if (EventList) { + EventSpaceCount = count; + EventCount = 0; + seeking = idle; + } else { + error("no space for event list"); + } +} + +HTTPiCal::~HTTPiCal() { + if (EventList) + free(EventList); +} + +void HTTPiCal::SetTimeWindow(time_t StartTime, time_t EndTime) { + gridStartTime = StartTime; + gridEndTime = EndTime; +} + +bool HTTPiCal::GetEvent(unsigned int i, Event_T * event) { + if (i < EventCount) { + *event = EventList[i]; + return true; + } else { + return false; + } +} + +void HTTPiCal::writeReset() { + //INFO("writeReset()"); + EventCount = 0; + lineBuf[0] = '\0'; +} + +int HTTPiCal::write(const char * buf, size_t len) { + const char * pStart = buf; + const char * pEOL; + size_t origLen = len; + + pEOL = strchr(pStart, '\n'); + //INFO("\r\n\r\nwrite[%d:%d] = \r\n%s\r\nend-write\r\n", len, pEOL - pStart, buf); + while (pEOL && (pEOL - pStart) < len) { + int lbLen = strlen(lineBuf); + strncpy(lineBuf + lbLen, pStart, (pEOL - pStart)); + lineBuf[lbLen + (pEOL - pStart) + 1] = '\0'; + if (lineBuf[pEOL - pStart + lbLen - 1] == '\r') + lineBuf[pEOL - pStart + lbLen - 1] = '\0'; + //INFO("lineBuf:[%s]", lineBuf); + ParseICalStream(lineBuf, gridStartTime, gridEndTime, -300); + //INFO(""); + lineBuf[0] = '\0'; + len -= (pEOL - pStart); + pStart = pEOL + 1; + while (pStart && *pStart && *pStart <= ' ') { + pStart++; + len--; + } + if (*pStart) + pEOL = strchr(pStart, '\n'); + else + pEOL = NULL; + } + if (len) { + strncpy(lineBuf, pStart, len); + lineBuf[len] = '\0'; + //INFO("fragment:[%s]", lineBuf); + } + //INFO("write returns %d", origLen); + return origLen; +} + +void HTTPiCal::setDataType(const char* type) { + //INFO("setDataType(%s)", type); +} + +//void HTTPiCal::setLocation(const char * location) { +// +//} + +void HTTPiCal::setIsChunked(bool chunked) { + INFO("setIsChunked(%d)", chunked); + m_chunked = chunked; +} + +void HTTPiCal::setDataLen(size_t len) { + //INFO("setDataLen(%d)", len); +} + + +const char * RPT_DAYS[] = { "SU", "MO", "TU", "WE", "TH", "FR", "SA", "" }; + +int HTTPiCal::GetNumEvents(void) +{ + return EventCount; +} + +const char * HTTPiCal::RepeatDayAbbrev(int i) +{ + if (i < 7) + return RPT_DAYS[i]; + else + return RPT_DAYS[7]; +} + +void HTTPiCal::SortEvents() +{ + bool swapped; + int e; + Event_T Event; + + do { + swapped = false; + for (e=0; e<EventCount-1; e++) { + if (EventList[e].Start > EventList[e+1].Start) { + Event = EventList[e]; + EventList[e] = EventList[e+1]; + EventList[e+1] = Event; + swapped = true; + } + } + } while (swapped); +} + +uint16_t HTTPiCal::AtoIxN(const char * p, int n) +{ + uint16_t res = 0; + + while (n--) { + res = (res * 10) + (*p - '0'); + p++; + } + return res; +} + +// YYYYMMDD[THHMMSS[Z]] +// VALUE=DATE:YYYYMMDD +time_t HTTPiCal::ParseDateStamp(const char * string, tz_sec_t tzoSec) +{ + time_t tStamp; + struct tm t; + struct tm * tnow; + + time(&tStamp); + tnow = localtime(&tStamp); + if (strncmp(string, "VALUE=DATE:", 11) == 0) { + string += 11; + } + //INFO("ParseDateStamp(%s,%d)\n", string, tzoSec); + t.tm_year = AtoIxN(string, 4) - 1900; + t.tm_mon = AtoIxN(string+4, 2) - 1; + t.tm_mday = AtoIxN(string+6, 2); + if (strlen(string) > 8) { + t.tm_hour = AtoIxN(string+9, 2); + t.tm_min = AtoIxN(string+11, 2); + t.tm_sec = AtoIxN(string+13, 2); + t.tm_isdst = tnow->tm_isdst; + } else { + t.tm_hour = 0; + t.tm_min = 0; + t.tm_sec = 0; + t.tm_isdst = tnow->tm_isdst; + } + tStamp = mktime(&t); + if (string[strlen(string)-1] == 'Z') { + //INFO("Applying tzoSec %d", tzoSec); + tStamp = tStamp + tzoTZIDSec; + } else { + tStamp = tStamp + tzoSec; + } + return tStamp; +} + +char * HTTPiCal::FormatCTime(time_t t) +{ + static char temp[4][80]; + static int i = 0; + + i &= 3; + strcpy(temp[i], ctime(&t)); + temp[i][strlen(temp[i])-1] = '\0'; + return temp[i++]; +} + + +void HTTPiCal::ShowEventInfo(Event_T & Event) +{ + char scratch[80]; + #define LF "\r\n" + + printf("******* Summary: %s" LF, Event.Summary); + printf(" Location: %s" LF, Event.Location); + printf(" Category: %s" LF, Event.Category); + printf(" Priority: %d" LF, Event.Priority); + sprintf(scratch, "%lu ", Event.Start); + sprintf(scratch + strlen(scratch), "%s", (Event.Start == 0) ? "" : ctime(&Event.Start)); + scratch[strlen(scratch)-1] = '\0'; + printf(" Start: %s" LF, scratch); + sprintf(scratch, "%lu ", Event.End); + sprintf(scratch + strlen(scratch), "%s", (Event.End == 0) ? "" : ctime(&Event.End)); + scratch[strlen(scratch)-1] = '\0'; + printf(" End: %s" LF, scratch); + printf(" Count: %d" LF, Event.Count); + printf(" Interval: %d" LF, Event.Interval); + printf(" RepeatFrq: %d" LF, Event.RepeatFreq); + printf(" RepeatDay: %02X" LF, Event.RepeatDays); + printf(" RepeatMonthDay: %08X" LF, Event.RepeatMonthDay); + printf(" RepeatMonthDayRev: %08X" LF, Event.RepeatMonthDayRev); + printf(" RepeatMonth: %04X" LF, Event.RepeatMonths); + sprintf(scratch, "%lu ", Event.Until); + sprintf(scratch + strlen(scratch), "%s", (Event.Until == 0) ? "" : ctime(&Event.Until)); + scratch[strlen(scratch)-1] = '\0'; + printf(" Until: %s" LF, scratch); + printf("" LF); +} + + +/// Computes the intersection of time1 and time2 ranges, and modifies time1 +/// range to represent the intersection. +/// +/// start1 is input as the start of the time1 range, and is written +/// to represent the intersection of the two ranges. +/// end1 is input as the end of the time1 range and is written to +/// represent the intersection of the two ranges. +/// start2 is the start of the time2 range. +/// end2 is the end of the time2 range. +/// returns true if the ranges have an intersection, and the time1 range +/// values have been modified. +/// +bool HTTPiCal::TimeIntersects(time_t * start1, time_t * end1, time_t * start2, time_t * end2) +{ + // |----Time1----| + // |--Time2--| false + // + // |----Time1----| + // |--Time2--| false + // + // |----Time1----| + // |----Time2----| + // |-Time1-| true + // + // |----Time1----| + // |----Time2----| + // |-Time1-| true + // + // |----Time1-------| + // |-Time2-| + // |-Time1-| true + // + // | Time1 (end1 == 0) + // | Time2 (end2 == 0) true + // + if (*start1 == *start2 && *end1 == 0 && *end2 == 0) + return true; + if (*end1 < *start2 || *end2 < *start1) + return false; + if (max(*start1,*start2) < min(*end1,*end2)) { + *start1 = max(*start1,*start2); + *end1 = min(*end1,*end2); + return true; + } else { + return false; + } +} + +bool HTTPiCal::isLeapYear(time_t t) +{ + int year; + struct tm * ts; + ts = localtime(&t); + + year = 1900 + ts->tm_year + 1; + if ((((year % 4) == 0) && ((year % 100) != 0)) || ((year % 400) == 0)) + return true; + else + return false; +} + +time_t HTTPiCal::NextInterval(time_t curTime, int repeatFreq, int interval) +{ + const time_t secperday = 60*60*24; + const int repeatFactor[] = {0, 1, 7, 30, 365}; + int delta = repeatFactor[repeatFreq]; + if (repeatFreq == 4 && isLeapYear(curTime)) + delta += 1; + //INFO("freq %d, interval %d, delta %d", repeatFreq, interval, delta); + return delta * interval * secperday; +} + + +// start1,end1 is the time range representing the visible grid +// start2,end2 is the time range of the event being tested +// Event is also the event being tested and permits testing the repeat information. +// +// If the event repeat pattern intersects with the display pattern, indicate this as "true" +// +bool HTTPiCal::RepeatMaskIntersects(time_t * start1, time_t * end1, time_t * start2, time_t * end2, Event_T * Event) +{ + bool intersects = false; + + //INFO("RepeatFreq: %d", Event->RepeatFreq); + if (Event->RepeatFreq == rptfDaily) { + //INFO("rptfDaily is not handled"); + } else if (Event->RepeatFreq == rptfWeekly) { + struct tm * timeinfo; + timeinfo = localtime(start1); + uint8_t daymask = Event->RepeatDays; + // now, check the tm_wday (0=Sunday, 1=Monday, ...) and see if we intersect with the event time + uint8_t testmask = 1 << timeinfo->tm_wday; + //INFO("Mask: Event mask: %02X, test mask: %02X", daymask, testmask); + if (daymask & testmask) + intersects = true; + else + intersects = false; + //INFO(" intersects: %02X", daymask & testmask); + return intersects; + } else if (Event->RepeatFreq == rptfYearly) { + //struct tm * timeinfo; + //timeinfo = localtime(start1); + //INFO("rptfYearly is not handled well yet"); + } + //INFO("Mask: no handler, returning true"); + return true; +} + +bool HTTPiCal::RepeatIntersects(time_t * start1, time_t * end1, time_t * start2, time_t * end2, Event_T * Event) +{ + INFO("** 1: (%s, %s)", FormatCTime(*start1), *end1 ? FormatCTime(*end1) : ""); + INFO(" 2: (%s, %s)", FormatCTime(*start2), *end2 ? FormatCTime(*end2) : ""); + INFO(" ev: (%s, %s)", FormatCTime(Event->Start), Event->End ? FormatCTime(Event->End) : ""); + if (TimeIntersects(start1, end1, start2, end2)) + return true; + if (Event && Event->RepeatFreq) { + INFO("RepeatFreq: %d", Event->RepeatFreq); + if (Event->Start < *start2 && Event->Until > *start2 ) { // Until=.... + INFO("Repeat until: %d", Event->Until); + do { + time_t interval = NextInterval(*start1, Event->RepeatFreq, (Event->Interval == 0) ? 1 : Event->Interval); + *start1 = *start1 + interval; + if (*end1) + *end1 = *end1 + interval; + INFO("** 1: (%s, %s)", FormatCTime(*start1), *end1 ? FormatCTime(*end1) : ""); + INFO("until (%24s, %s)", " ", FormatCTime(Event->Until)); + INFO(" 2: (%s, %s)", FormatCTime(*start2), *end2 ? FormatCTime(*end2) : ""); + if (!RepeatMaskIntersects(start1, end1, start2, end2, Event)) { + continue; // we're not on a repeat cycle (e.g. wrong day of the week) + } + if (TimeIntersects(start1, end1, start2, end2)) { + return true; + } + } while ((*end2 == 0 || *start1 < *end2) && *start1 < Event->Until); + } else if (Event->Start < *start2 && Event->Count) { // Count= + INFO("Repeat count %d", Event->Count); + int count = Event->Count - 1; + do { + time_t interval = NextInterval(*start1, Event->RepeatFreq, (Event->Interval == 0) ? 1 : Event->Interval); + *start1 = *start1 + interval; + if (*end1) + *end1 = *end1 + interval; + INFO("** 1: (%s, %s) - %d", FormatCTime(*start1), *end1 ? FormatCTime(*end1) : "", count); + INFO(" 2: (%s, %s)", FormatCTime(*start2), *end2 ? FormatCTime(*end2) : ""); + if (!RepeatMaskIntersects(start1, end1, start2, end2, Event)) { + continue; // we're not on a repeat cycle (e.g. wrong day of the week) + } + if (TimeIntersects(start1, end1, start2, end2)) { + return true; + } + } while (--count && *end1 < *start2); + } else if (Event->Start < *start2) { // no Count= and no Until= + INFO(" no Repeat end"); + do { + int rptFreq = Event->RepeatFreq; + if (Event->RepeatFreq == 2 && Event->RepeatDays != 0) + rptFreq--; + time_t interval = NextInterval(*start1, rptFreq, (Event->Interval == 0) ? 1 : Event->Interval); + *start1 = *start1 + interval; + if (*end1) + *end1 = *end1 + interval; + INFO("== 1: (%s, %s)", FormatCTime(*start1), *end1 ? FormatCTime(*end1) : ""); + INFO(" 2: (%s, %s)", FormatCTime(*start2), *end2 ? FormatCTime(*end2) : ""); + if (!RepeatMaskIntersects(start1, end1, start2, end2, Event)) { + continue; // we're not on a repeat cycle (e.g. wrong day of the week) + } + if (TimeIntersects(start1, end1, start2, end2)) { + return true; + } + } while (*start1 < *end2 || (*end2 == 0 && *start1 < *start2)); + } else { + INFO("falling out"); + } + } + INFO(" no intersection"); + return false; +} + +// All the stuff between +// BEGIN:VEVENT +// ... +// END:VEVENT +// +void HTTPiCal::ParseEvent(Event_T * Event, const char * pStart, tz_sec_t tzoSec) +{ + INFO("ParseEvent(...,'%s',%d)", pStart, tzoSec); + if (strncmp(pStart, "DTSTART:", 8) == 0) { + Event->Start = ParseDateStamp(pStart+8, tzoSec); + INFO(" Start: %s\n", ctime(&Event->Start)); + } else if (strncmp(pStart, "DTSTART;", 8) == 0) { + const char * p = pStart + 8; + tzoSec = ParseTZID(p); + p = strrchr(pStart, ':'); + if (p) { + Event->Start = ParseDateStamp(p+1, 0); // example was localtime with GMT -06:00 tzoSec); + INFO(" Start: %s", ctime(&Event->Start)); + } + } else if (strncmp(pStart, "DTEND:", 6) == 0) { + Event->End = ParseDateStamp(pStart+6, tzoSec); + //INFO(" End: %d\n", mktime(&Event->eventEnd)); + } else if (strncmp(pStart, "DTEND;", 6) == 0) { + const char * p = pStart + 6; + tzoSec = ParseTZID(p); + p = strrchr(pStart, ':'); + if (p) { + Event->End = ParseDateStamp(p+1, 0); // example was localtime with GMT -06:00 tzoSec); + INFO(" End: %s", ctime(&Event->End)); + } + } else if (strncmp(pStart, "SUMMARY:", 8) == 0) { + strncpy(Event->Summary, pStart+8, SUMMARY_CHARS-1); + Event->Summary[SUMMARY_CHARS-1] = '\0'; + //INFO(" Summary: %s\n", Event->Summary); + } else if (strncmp(pStart, "LOCATION:", 9) == 0) { + strncpy(Event->Location, pStart+9, LOCATION_CHARS-1); + Event->Location[LOCATION_CHARS-1] = '\0'; + //INFO(" Location: %s\n", Event->Location); + } else if (strncmp(pStart, "PRIORITY:", 9) == 0) { + Event->Priority = *(pStart+9) - '0'; + //INFO(" Priority: %d\n", Event->Priority); + } else if (strncmp(pStart, "CATEGORIES:", 11) == 0) { + strncpy(Event->Category, pStart+11, CATEGORY_CHARS-1); + Event->Category[CATEGORY_CHARS-1] = '\0'; + //INFO(" Category: %s\n", Event->Category); + } else if (strncmp(pStart, "RRULE:", 6) == 0) { + //RRULE:FREQ=WEEKLY;UNTIL=20140502T180000;BYDAY=MO,TU,WE,TH,FR + const char * p1, *p2; + //INFO("%s", pStart); + p1 = pStart + 6; // p1 = FREQ=WEEKLY;UNTIL=20140502T180000;BYDAY=MO,TU,WE,TH,FR + p2 = strchr(p1, ';'); + //if (p2) + // *p2++ = '\0'; + while (*p1) { + INFO("%s", p1); + if (strncmp(p1, "FREQ=", 5) == 0) { + //INFO("%s", p1); + p1 += 5; // p1 = WEEKLY;UNTIL=20140502T180000;BYDAY=MO,TU,WE,TH,FR + if (strncmp(p1, "WEEKLY", 6) == 0) { + //INFO(" %s", p1); + Event->RepeatFreq = rptfWeekly; + p1 += 6; + } else if (strncmp(p1, "DAILY", 5) == 0) { + //INFO(" %s", p1); + Event->RepeatFreq = rptfDaily; + p1 += 5; + } else if (strncmp(p1, "MONTHLY", 7) == 0) { + //INFO(" %s", p1); + Event->RepeatFreq = rptfMonthly; + p1 += 7; + } else if (strncmp(p1, "YEARLY", 6) == 0) { + //INFO(" %s", p1); + Event->RepeatFreq = rptfYearly; + p1 += 6; + } + } else if (strncmp(p1, "INTERVAL=", 9) == 0) { // INTERVAL=2 + //INFO("%s", p1); + p1 += 9; + Event->Interval = atoi(p1); + } else if (strncmp(p1, "COUNT=", 6) == 0) { // COUNT=12; + //INFO("%s", p1); + p1 += 6; // p1 = + Event->Count = atoi(p1); + } else if (strncmp(p1, "UNTIL=", 6) == 0) { + //INFO("%s", p1); + p1 += 6; // p1 = 20140502T180000;BYDAY=MO,TU,WE,TH,FR + //printf("UNTIL= {%s}\n", p1); + Event->Until = ParseDateStamp(p1, tzoSec); + //printf("UNTIL:: %d: %d\n", Event->Until, tzoSec); + } else if (strncmp(p1, "BYDAY=", 6) == 0) { + //INFO("%s", p1); + p1 += 6; // p1 = MO,TU,WE,TH,FR + while (*p1 >= ' ') { + //INFO(" %s", p1); + for (int d=0; d<7; d++) { + if (strncmp(p1,RepeatDayAbbrev(d),2) == 0) { + Event->RepeatDays |= (1 << d); + //INFO(" %s %02X", RepeatDayAbbrev(d), Event->RepeatDays); + break; + } + } + p1 += 3; + } + //INFO(" RepeatDay: %02X", Event->RepeatDays); + } else if (strncmp(p1, "BYMONTHDAY=", 11) == 0) { + // RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=2,15 + p1 += 11; + while (*p1 >= ' ') { + const char * px = p1; + while (*px >= ' ' && *px != ',') { // find , or ; or <nul> + px++; + } + //if (*px) + // *px++ = '\0'; + int num = atoi(p1); + if (num >= 0) + Event->RepeatMonthDay |= (1 << num); + else + Event->RepeatMonthDayRev |= (1 << -num); + p1 = px; + } + INFO(" RepeatMonthDay: %08X", Event->RepeatMonthDay); + } else if (strncmp(p1, "BYMONTH=", 8) == 0) { + // RRULE:FREQ=YEARLY;INTERVAL=2;COUNT=10;BYMONTH=1,2,3 + p1 += 8; + while (*p1 >= ' ') { + const char * px = p1; + while (*px >= ' ' && *px != ',') { // find , or ; or <nul> + px++; + } + //if (*px) + // *px++ = '\0'; + int num = atoi(p1); + if (num >= 0) + Event->RepeatMonths |= (1 << num); + //else + // ; // Event->RepeatMonthsRev |= (1 << -num); + p1 = px; + } + INFO(" RepeatMonths: %04X", Event->RepeatMonths); + } + if (!p2) + break; + p1 = p2 + 1; + p2 = strchr(p1, ';'); + //if (p2) + // *p2++ = '\0'; + } + } +} + + +// TZID="(GMT -06:00)":20140519T063000 +// TZID:(UTC-06:00) Central Time (US & Canada) +// TZID:(GMT -06:00) +HTTPiCal::tz_sec_t HTTPiCal::ParseTZID(const char * string) +{ + tz_sec_t tzo = 0; + bool sign = false; + + INFO("ParseTZID(%s)", string); // TZID="(GMT -06:00)":20140519T063000 + string += 5; // "(GMT -06:00)":20140519T063000 + if (*string == '"') + string++; // (GMT -06:00)":20140519T063000 + if ((strncmp(string, "(UTC", 4) == 0) + || (strncmp(string, "(GMT", 4) == 0) ){ + string += 4; + if (*string == ' ') + string++; + if (*string == '-') { + sign = true; + string++; + } + tzo = atoi(string) * 3600; + string = strchr(string, ':'); + if (string) { + string++; + tzo += atoi(string) * 60; + } + if (sign) + tzo = -tzo; + INFO(" tzo = %d", tzo); + } else { + ERR("Unhandled TZID(%s)", string); + } + return tzo; +} + +void HTTPiCal::ParseICalStart(void) { + tzAdjusted = false; + seeking = idle; + EventCount = 0; + +} + +int HTTPiCal::ParseICalClose(void) { + if (EventCount > 0) + SortEvents(); + return GetNumEvents(); +} + +int HTTPiCal::ParseICalStream(const char * pStart, time_t gridStartTime, time_t gridEndTime, tz_min_t tzoMin, bool showEvents) +{ + INFO("Parse(%s)", pStart); + //INFO("EventCount: %d, EventSpaceCount: %d, seeking: %d", EventCount, EventSpaceCount, seeking); + if (pStart && *pStart && EventCount < EventSpaceCount) { + switch (seeking) { + case idle: + if (strncmp(pStart, "BEGIN:VTIMEZONE", 15) == 0) { + //INFO("begin:timezone"); + seeking = inTimeZone; + } else if (strncmp(pStart, "BEGIN:VEVENT", 12) == 0) { + //INFO("begin:vevent"); + seeking = inEvent; + EventList[EventCount].Start = 0; + EventList[EventCount].End = 0; + EventList[EventCount].Until = 0; + EventList[EventCount].Summary[0] = '\0'; + EventList[EventCount].Location[0] = '\0'; + EventList[EventCount].Category[0] = '\0'; + EventList[EventCount].Count = 0; + EventList[EventCount].Interval = 0; + EventList[EventCount].RepeatFreq = rptfNone; + EventList[EventCount].RepeatDays = 0; + EventList[EventCount].RepeatMonthDay = 0; + EventList[EventCount].RepeatMonthDayRev = 0; + EventList[EventCount].RepeatMonths = 0; + EventList[EventCount].Priority = 5; // 5 is Normal + } + break; + case inTimeZone: + //INFO("inTimeZone:"); + // Can also pick up daylight savings time + if (strncmp(pStart, "END:VTIMEZONE", 13) == 0) { + seeking = idle; + } else if ((strncmp(pStart, "TZID:", 5) == 0) + || (strncmp(pStart, "TZID=", 5) == 0) ) { + tzoTZIDSec = ParseTZID(pStart); + tzAdjusted = true; + pStart += 5; + } else if (strncmp(pStart, "BEGIN:STANDARD", 14) == 0) { + + } else if (strncmp(pStart, "BEGIN:DAYLIGHT", 14) == 0) { + + } + break; + case inEvent: + //INFO("inEvent:"); + // inEvent + if (strncmp(pStart, "END:VEVENT", 10) == 0) { + // Timezone offset + if (!tzAdjusted) { + EventList[EventCount].Start += (60 * tzoMin); + if (EventList[EventCount].End) + EventList[EventCount].End += (60 * tzoMin); + } + // Process it + if (showEvents) + ShowEventInfo(EventList[EventCount]); + // Force to ALWAYS + time_t aStart = EventList[EventCount].Start; + time_t aEnd = EventList[EventCount].End; + if (gridStartTime + && RepeatIntersects(&aStart, &aEnd, &gridStartTime, &gridEndTime, &EventList[EventCount])) { + EventCount++; + if (showEvents) { + INFO(" +++++ Added Event %d", EventCount);//, EventList[EventCount].Summary); + } + } + seeking = idle; + } else { + //INFO("parse event data"); + ParseEvent(&EventList[EventCount], pStart, 60 * tzoMin); + } + // End of inEvent + break; + default: + INFO("default:"); + seeking = idle; + break; + } + } // while + return EventCount; +}