Fixed custom headers and Basic authorization, added support for redirection, functional file download interface can be used for SW updates and more.
Dependents: Sample_HTTPClient Sample_HTTPClient LWM2M_NanoService_Ethernet LWM2M_NanoService_Ethernet ... more
Fork of HTTPClient by
HTTPiCal.cpp
00001 #include "HTTPiCal.h" 00002 00003 //#include "Utility.h" // private memory manager 00004 #ifndef UTILITY_H 00005 #define swMalloc malloc // use the standard 00006 #define swFree free 00007 #endif 00008 00009 //#define DEBUG "iCal" 00010 #include <cstdio> 00011 #if (defined(DEBUG) && !defined(TARGET_LPC11U24)) 00012 #define DBG(x, ...) std::printf("[DBG %s %4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); 00013 #define WARN(x, ...) std::printf("[WRN %s %4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); 00014 #define ERR(x, ...) std::printf("[ERR %s %4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); 00015 #define INFO(x, ...) std::printf("[INF %s %4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__); 00016 #else 00017 #define DBG(x, ...) 00018 #define WARN(x, ...) 00019 #define ERR(x, ...) 00020 #define INFO(x, ...) 00021 #endif 00022 00023 HTTPiCal::HTTPiCal(int count) { 00024 EventList = (Event_T *)swMalloc(count * sizeof(Event_T)); 00025 if (EventList) { 00026 EventSpaceCount = count; 00027 EventCount = 0; 00028 seeking = idle; 00029 } else { 00030 error("no space for event list"); 00031 } 00032 } 00033 00034 HTTPiCal::~HTTPiCal() { 00035 if (EventList) 00036 swFree(EventList); 00037 } 00038 00039 void HTTPiCal::SetTimeWindow(time_t StartTime, time_t EndTime) { 00040 gridStartTime = StartTime; 00041 gridEndTime = EndTime; 00042 } 00043 00044 bool HTTPiCal::GetEvent(unsigned int i, Event_T * event) { 00045 if (i < EventCount) { 00046 *event = EventList[i]; 00047 return true; 00048 } else { 00049 return false; 00050 } 00051 } 00052 00053 void HTTPiCal::writeReset() { 00054 //INFO("writeReset()"); 00055 EventCount = 0; 00056 seeking = idle; 00057 lineBuf[0] = '\0'; 00058 } 00059 00060 int HTTPiCal::write(const char * buf, size_t len) { 00061 const char * pStart = buf; 00062 const char * pEOL; 00063 size_t origLen = len; 00064 00065 pEOL = strchr(pStart, '\n'); 00066 //INFO("\r\n\r\nwrite[%d:%d] = \r\n%s\r\nend-write\r\n", len, pEOL - pStart, buf); 00067 //printf("lineBuf:[%d] %s\r\n", len, buf); 00068 while (pEOL && (pEOL - pStart) < len) { 00069 int lbLen = strlen(lineBuf); 00070 strncpy(lineBuf + lbLen, pStart, (pEOL - pStart)); 00071 lineBuf[lbLen + (pEOL - pStart) + 1] = '\0'; 00072 if (lineBuf[pEOL - pStart + lbLen - 1] == '\r') 00073 lineBuf[pEOL - pStart + lbLen - 1] = '\0'; 00074 //printf("lineBuf:[%s]\r\n", lineBuf); 00075 ParseICalStream(lineBuf, gridStartTime, gridEndTime, -300); 00076 //INFO(""); 00077 lineBuf[0] = '\0'; 00078 len -= (pEOL - pStart); 00079 pStart = pEOL + 1; 00080 while (pStart && *pStart && *pStart <= ' ') { 00081 pStart++; 00082 len--; 00083 } 00084 if (*pStart) 00085 pEOL = strchr(pStart, '\n'); 00086 else 00087 pEOL = NULL; 00088 } 00089 if (len) { 00090 strncpy(lineBuf, pStart, len); 00091 lineBuf[len] = '\0'; 00092 //INFO("fragment:[%s]", lineBuf); 00093 } 00094 //INFO("write returns %d", origLen); 00095 return origLen; 00096 } 00097 00098 void HTTPiCal::setDataType(const char* type) { 00099 //INFO("setDataType(%s)", type); 00100 } 00101 00102 //void HTTPiCal::setLocation(const char * location) { 00103 // 00104 //} 00105 00106 void HTTPiCal::setIsChunked(bool chunked) { 00107 INFO("setIsChunked(%d)", chunked); 00108 m_chunked = chunked; 00109 } 00110 00111 void HTTPiCal::setDataLen(size_t len) { 00112 //INFO("setDataLen(%d)", len); 00113 } 00114 00115 00116 static const char * RPT_DAYS[] = { "SU", "MO", "TU", "WE", "TH", "FR", "SA", "" }; 00117 00118 00119 const char * HTTPiCal::RepeatDayAbbrev(int i) 00120 { 00121 if (i < 7) 00122 return RPT_DAYS[i]; 00123 else 00124 return RPT_DAYS[7]; 00125 } 00126 00127 void HTTPiCal::SortEvents() 00128 { 00129 bool swapped; 00130 int e; 00131 Event_T Event; 00132 00133 do { 00134 swapped = false; 00135 for (e=0; e<EventCount-1; e++) { 00136 if (EventList[e].Start > EventList[e+1].Start) { 00137 Event = EventList[e]; 00138 EventList[e] = EventList[e+1]; 00139 EventList[e+1] = Event; 00140 swapped = true; 00141 } 00142 } 00143 } while (swapped); 00144 } 00145 00146 uint16_t HTTPiCal::AtoIxN(const char * p, int n) 00147 { 00148 uint16_t res = 0; 00149 00150 while (n--) { 00151 res = (res * 10) + (*p - '0'); 00152 p++; 00153 } 00154 return res; 00155 } 00156 00157 // YYYYMMDD[THHMMSS[Z]] 00158 // VALUE=DATE:YYYYMMDD 00159 time_t HTTPiCal::ParseDateStamp(const char * string, tz_sec_t tzoSec) 00160 { 00161 time_t tStamp; 00162 struct tm t; 00163 struct tm * tnow; 00164 00165 time(&tStamp); 00166 tnow = localtime(&tStamp); 00167 if (strncmp(string, "VALUE=DATE:", 11) == 0) { 00168 string += 11; 00169 } 00170 //INFO("ParseDateStamp(%s,%d)\n", string, tzoSec); 00171 t.tm_year = AtoIxN(string, 4) - 1900; 00172 t.tm_mon = AtoIxN(string+4, 2) - 1; 00173 t.tm_mday = AtoIxN(string+6, 2); 00174 if (strlen(string) > 8) { 00175 t.tm_hour = AtoIxN(string+9, 2); 00176 t.tm_min = AtoIxN(string+11, 2); 00177 t.tm_sec = AtoIxN(string+13, 2); 00178 t.tm_isdst = tnow->tm_isdst; 00179 } else { 00180 t.tm_hour = 0; 00181 t.tm_min = 0; 00182 t.tm_sec = 0; 00183 t.tm_isdst = tnow->tm_isdst; 00184 } 00185 tStamp = mktime(&t); 00186 if (string[strlen(string)-1] == 'Z') { 00187 //INFO("Applying tzoSec %d", tzoSec); 00188 tStamp = tStamp + tzoTZIDSec; 00189 } else { 00190 tStamp = tStamp + tzoSec; 00191 } 00192 return tStamp; 00193 } 00194 00195 // since this returns the string from a static buffer, and unknowing users 00196 // might call this twice in a single command (e.g. printf(..., FormatCTime(time1), FormatCTime(time2)); 00197 // this define controls how many of these can execute. 00198 #define NumCallsPerArgList 2 00199 char * HTTPiCal::FormatCTime(time_t t) 00200 { 00201 static char temp[NumCallsPerArgList][30]; 00202 static int i = 0; 00203 00204 i %= NumCallsPerArgList; 00205 strcpy(temp[i], ctime(&t)); 00206 temp[i][strlen(temp[i])-1] = '\0'; 00207 return temp[i++]; 00208 } 00209 00210 00211 void HTTPiCal::ShowEventInfo(Event_T & Event) 00212 { 00213 char scratch[80]; 00214 #define LF "\r\n" 00215 00216 printf("******* Summary: %s" LF, Event.Summary); 00217 printf(" Location: %s" LF, Event.Location); 00218 printf(" Category: %s" LF, Event.Category); 00219 printf(" Priority: %d" LF, Event.Priority); 00220 sprintf(scratch, "%lu ", Event.Start); 00221 sprintf(scratch + strlen(scratch), "%s", (Event.Start == 0) ? "" : ctime(&Event.Start)); 00222 scratch[strlen(scratch)-1] = '\0'; 00223 printf(" Start: %s" LF, scratch); 00224 sprintf(scratch, "%lu ", Event.End); 00225 sprintf(scratch + strlen(scratch), "%s", (Event.End == 0) ? "" : ctime(&Event.End)); 00226 scratch[strlen(scratch)-1] = '\0'; 00227 printf(" End: %s" LF, scratch); 00228 printf(" Count: %d" LF, Event.Count); 00229 printf(" Interval: %d" LF, Event.Interval); 00230 printf(" RepeatFrq: %d" LF, Event.RepeatFreq); 00231 printf(" RepeatDay: %02X" LF, Event.RepeatDays); 00232 printf(" RepeatMonthDay: %08X" LF, Event.RepeatMonthDay); 00233 printf(" RepeatMonthDayRev: %08X" LF, Event.RepeatMonthDayRev); 00234 printf(" RepeatMonth: %04X" LF, Event.RepeatMonths); 00235 sprintf(scratch, "%lu ", Event.Until); 00236 sprintf(scratch + strlen(scratch), "%s", (Event.Until == 0) ? "" : ctime(&Event.Until)); 00237 scratch[strlen(scratch)-1] = '\0'; 00238 printf(" Until: %s" LF, scratch); 00239 printf("" LF); 00240 } 00241 00242 00243 /// Computes the intersection of time1 and time2 ranges, and modifies time1 00244 /// range to represent the intersection. 00245 /// 00246 /// start1 is input as the start of the time1 range, and is written 00247 /// to represent the intersection of the two ranges. 00248 /// end1 is input as the end of the time1 range and is written to 00249 /// represent the intersection of the two ranges. 00250 /// start2 is the start of the time2 range. 00251 /// end2 is the end of the time2 range. 00252 /// returns true if the ranges have an intersection, and the time1 range 00253 /// values have been modified. 00254 /// 00255 bool HTTPiCal::TimeIntersects(time_t * start1, time_t * end1, time_t * start2, time_t * end2) 00256 { 00257 // |----Time1----| 00258 // |--Time2--| false 00259 // 00260 // |----Time1----| 00261 // |--Time2--| false 00262 // 00263 // |----Time1----| 00264 // |----Time2----| 00265 // |-Time1-| true 00266 // 00267 // |----Time1----| 00268 // |----Time2----| 00269 // |-Time1-| true 00270 // 00271 // |----Time1-------| 00272 // |-Time2-| 00273 // |-Time1-| true 00274 // 00275 // | Time1 (end1 == 0) 00276 // | Time2 (end2 == 0) true 00277 // 00278 if (*start1 == *start2 && *end1 == 0 && *end2 == 0) 00279 return true; 00280 if (*end1 < *start2 || *end2 < *start1) 00281 return false; 00282 if (max(*start1,*start2) < min(*end1,*end2)) { 00283 *start1 = max(*start1,*start2); 00284 *end1 = min(*end1,*end2); 00285 return true; 00286 } else { 00287 return false; 00288 } 00289 } 00290 00291 bool HTTPiCal::isLeapYear(time_t t) 00292 { 00293 int year; 00294 struct tm * ts; 00295 ts = localtime(&t); 00296 00297 year = 1900 + ts->tm_year + 1; 00298 if ((((year % 4) == 0) && ((year % 100) != 0)) || ((year % 400) == 0)) 00299 return true; 00300 else 00301 return false; 00302 } 00303 00304 time_t HTTPiCal::NextInterval(time_t curTime, int repeatFreq, int interval) 00305 { 00306 const time_t secperday = 60*60*24; 00307 const int repeatFactor[] = {0, 1, 7, 30, 365}; 00308 int delta = repeatFactor[repeatFreq]; 00309 if (repeatFreq == 4 && isLeapYear(curTime)) 00310 delta += 1; 00311 //INFO("freq %d, interval %d, delta %d", repeatFreq, interval, delta); 00312 return delta * interval * secperday; 00313 } 00314 00315 00316 // start1,end1 is the time range representing the visible grid 00317 // start2,end2 is the time range of the event being tested 00318 // Event is also the event being tested and permits testing the repeat information. 00319 // 00320 // If the event repeat pattern intersects with the display pattern, indicate this as "true" 00321 // 00322 bool HTTPiCal::RepeatMaskIntersects(time_t * start1, time_t * end1, time_t * start2, time_t * end2, Event_T * Event) 00323 { 00324 bool intersects = false; 00325 00326 //INFO("RepeatFreq: %d", Event->RepeatFreq); 00327 if (Event->RepeatFreq == rptfDaily) { 00328 //INFO("rptfDaily is not handled"); 00329 } else if (Event->RepeatFreq == rptfWeekly) { 00330 struct tm * timeinfo; 00331 timeinfo = localtime(start1); 00332 uint8_t daymask = Event->RepeatDays; 00333 // now, check the tm_wday (0=Sunday, 1=Monday, ...) and see if we intersect with the event time 00334 uint8_t testmask = 1 << timeinfo->tm_wday; 00335 //INFO("Mask: Event mask: %02X, test mask: %02X", daymask, testmask); 00336 if (daymask & testmask) 00337 intersects = true; 00338 else 00339 intersects = false; 00340 //INFO(" intersects: %02X", daymask & testmask); 00341 return intersects; 00342 } else if (Event->RepeatFreq == rptfYearly) { 00343 //struct tm * timeinfo; 00344 //timeinfo = localtime(start1); 00345 //INFO("rptfYearly is not handled well yet"); 00346 } 00347 //INFO("Mask: no handler, returning true"); 00348 return true; 00349 } 00350 00351 bool HTTPiCal::RepeatIntersects(time_t * start1, time_t * end1, time_t * start2, time_t * end2, Event_T * Event) 00352 { 00353 INFO("** 1: (%s, %s)", FormatCTime(*start1), *end1 ? FormatCTime(*end1) : ""); 00354 INFO(" 2: (%s, %s)", FormatCTime(*start2), *end2 ? FormatCTime(*end2) : ""); 00355 INFO(" ev: (%s, %s)", FormatCTime(Event->Start), Event->End ? FormatCTime(Event->End) : ""); 00356 if (TimeIntersects(start1, end1, start2, end2)) 00357 return true; 00358 if (Event && Event->RepeatFreq) { 00359 INFO("RepeatFreq: %d", Event->RepeatFreq); 00360 if (Event->Start < *start2 && Event->Until > *start2 ) { // Until=.... 00361 INFO("Repeat until: %d", Event->Until); 00362 do { 00363 time_t interval = NextInterval(*start1, Event->RepeatFreq, (Event->Interval == 0) ? 1 : Event->Interval); 00364 *start1 = *start1 + interval; 00365 if (*end1) 00366 *end1 = *end1 + interval; 00367 INFO("** 1: (%s, %s)", FormatCTime(*start1), *end1 ? FormatCTime(*end1) : ""); 00368 INFO("until (%24s, %s)", " ", FormatCTime(Event->Until)); 00369 INFO(" 2: (%s, %s)", FormatCTime(*start2), *end2 ? FormatCTime(*end2) : ""); 00370 if (!RepeatMaskIntersects(start1, end1, start2, end2, Event)) { 00371 continue; // we're not on a repeat cycle (e.g. wrong day of the week) 00372 } 00373 if (TimeIntersects(start1, end1, start2, end2)) { 00374 return true; 00375 } 00376 } while ((*end2 == 0 || *start1 < *end2) && *start1 < Event->Until); 00377 } else if (Event->Start < *start2 && Event->Count) { // Count= 00378 INFO("Repeat count %d", Event->Count); 00379 int count = Event->Count - 1; 00380 do { 00381 time_t interval = NextInterval(*start1, Event->RepeatFreq, (Event->Interval == 0) ? 1 : Event->Interval); 00382 *start1 = *start1 + interval; 00383 if (*end1) 00384 *end1 = *end1 + interval; 00385 INFO("** 1: (%s, %s) - %d", FormatCTime(*start1), *end1 ? FormatCTime(*end1) : "", count); 00386 INFO(" 2: (%s, %s)", FormatCTime(*start2), *end2 ? FormatCTime(*end2) : ""); 00387 if (!RepeatMaskIntersects(start1, end1, start2, end2, Event)) { 00388 continue; // we're not on a repeat cycle (e.g. wrong day of the week) 00389 } 00390 if (TimeIntersects(start1, end1, start2, end2)) { 00391 return true; 00392 } 00393 } while (--count && *end1 < *start2); 00394 } else if (Event->Start < *start2) { // no Count= and no Until= 00395 INFO(" no Repeat end"); 00396 do { 00397 int rptFreq = Event->RepeatFreq; 00398 if (Event->RepeatFreq == 2 && Event->RepeatDays != 0) 00399 rptFreq--; 00400 time_t interval = NextInterval(*start1, rptFreq, (Event->Interval == 0) ? 1 : Event->Interval); 00401 *start1 = *start1 + interval; 00402 if (*end1) 00403 *end1 = *end1 + interval; 00404 INFO("== 1: (%s, %s)", FormatCTime(*start1), *end1 ? FormatCTime(*end1) : ""); 00405 INFO(" 2: (%s, %s)", FormatCTime(*start2), *end2 ? FormatCTime(*end2) : ""); 00406 if (!RepeatMaskIntersects(start1, end1, start2, end2, Event)) { 00407 continue; // we're not on a repeat cycle (e.g. wrong day of the week) 00408 } 00409 if (TimeIntersects(start1, end1, start2, end2)) { 00410 return true; 00411 } 00412 } while (*start1 < *end2 || (*end2 == 0 && *start1 < *start2)); 00413 } else { 00414 INFO("falling out"); 00415 } 00416 } 00417 INFO(" no intersection"); 00418 return false; 00419 } 00420 00421 // All the stuff between 00422 // BEGIN:VEVENT 00423 // ... 00424 // END:VEVENT 00425 // 00426 void HTTPiCal::ParseEvent(Event_T * Event, const char * pStart, tz_sec_t tzoSec) 00427 { 00428 INFO("ParseEvent(...,'%s',%d)", pStart, tzoSec); 00429 if (strncmp(pStart, "DTSTART:", 8) == 0) { 00430 Event->Start = ParseDateStamp(pStart+8, tzoSec); 00431 INFO(" Start: %s\n", ctime(&Event->Start)); 00432 } else if (strncmp(pStart, "DTSTART;", 8) == 0) { 00433 const char * p = pStart + 8; 00434 tzoSec = ParseTZID(p); 00435 p = strrchr(pStart, ':'); 00436 if (p) { 00437 Event->Start = ParseDateStamp(p+1, 0); // example was localtime with GMT -06:00 tzoSec); 00438 INFO(" Start: %s", ctime(&Event->Start)); 00439 } 00440 } else if (strncmp(pStart, "DTEND:", 6) == 0) { 00441 Event->End = ParseDateStamp(pStart+6, tzoSec); 00442 //INFO(" End: %d\n", mktime(&Event->eventEnd)); 00443 } else if (strncmp(pStart, "DTEND;", 6) == 0) { 00444 const char * p = pStart + 6; 00445 tzoSec = ParseTZID(p); 00446 p = strrchr(pStart, ':'); 00447 if (p) { 00448 Event->End = ParseDateStamp(p+1, 0); // example was localtime with GMT -06:00 tzoSec); 00449 INFO(" End: %s", ctime(&Event->End)); 00450 } 00451 } else if (strncmp(pStart, "SUMMARY:", 8) == 0) { 00452 strncpy(Event->Summary, pStart+8, SUMMARY_CHARS-1); 00453 Event->Summary[SUMMARY_CHARS-1] = '\0'; 00454 //INFO(" Summary: %s\n", Event->Summary); 00455 } else if (strncmp(pStart, "LOCATION:", 9) == 0) { 00456 strncpy(Event->Location, pStart+9, LOCATION_CHARS-1); 00457 Event->Location[LOCATION_CHARS-1] = '\0'; 00458 //INFO(" Location: %s\n", Event->Location); 00459 } else if (strncmp(pStart, "PRIORITY:", 9) == 0) { 00460 Event->Priority = *(pStart+9) - '0'; 00461 //INFO(" Priority: %d\n", Event->Priority); 00462 } else if (strncmp(pStart, "CATEGORIES:", 11) == 0) { 00463 strncpy(Event->Category, pStart+11, CATEGORY_CHARS-1); 00464 Event->Category[CATEGORY_CHARS-1] = '\0'; 00465 //INFO(" Category: %s\n", Event->Category); 00466 } else if (strncmp(pStart, "RRULE:", 6) == 0) { 00467 //RRULE:FREQ=WEEKLY;UNTIL=20140502T180000;BYDAY=MO,TU,WE,TH,FR 00468 const char * p1, *p2; 00469 //INFO("%s", pStart); 00470 p1 = pStart + 6; // p1 = FREQ=WEEKLY;UNTIL=20140502T180000;BYDAY=MO,TU,WE,TH,FR 00471 p2 = strchr(p1, ';'); 00472 //if (p2) 00473 // *p2++ = '\0'; 00474 while (*p1) { 00475 INFO("%s", p1); 00476 if (strncmp(p1, "FREQ=", 5) == 0) { 00477 //INFO("%s", p1); 00478 p1 += 5; // p1 = WEEKLY;UNTIL=20140502T180000;BYDAY=MO,TU,WE,TH,FR 00479 if (strncmp(p1, "WEEKLY", 6) == 0) { 00480 //INFO(" %s", p1); 00481 Event->RepeatFreq = rptfWeekly; 00482 p1 += 6; 00483 } else if (strncmp(p1, "DAILY", 5) == 0) { 00484 //INFO(" %s", p1); 00485 Event->RepeatFreq = rptfDaily; 00486 p1 += 5; 00487 } else if (strncmp(p1, "MONTHLY", 7) == 0) { 00488 //INFO(" %s", p1); 00489 Event->RepeatFreq = rptfMonthly; 00490 p1 += 7; 00491 } else if (strncmp(p1, "YEARLY", 6) == 0) { 00492 //INFO(" %s", p1); 00493 Event->RepeatFreq = rptfYearly; 00494 p1 += 6; 00495 } 00496 } else if (strncmp(p1, "INTERVAL=", 9) == 0) { // INTERVAL=2 00497 //INFO("%s", p1); 00498 p1 += 9; 00499 Event->Interval = atoi(p1); 00500 } else if (strncmp(p1, "COUNT=", 6) == 0) { // COUNT=12; 00501 //INFO("%s", p1); 00502 p1 += 6; // p1 = 00503 Event->Count = atoi(p1); 00504 } else if (strncmp(p1, "UNTIL=", 6) == 0) { 00505 //INFO("%s", p1); 00506 p1 += 6; // p1 = 20140502T180000;BYDAY=MO,TU,WE,TH,FR 00507 //printf("UNTIL= {%s}\n", p1); 00508 Event->Until = ParseDateStamp(p1, tzoSec); 00509 //printf("UNTIL:: %d: %d\n", Event->Until, tzoSec); 00510 } else if (strncmp(p1, "BYDAY=", 6) == 0) { 00511 //INFO("%s", p1); 00512 p1 += 6; // p1 = MO,TU,WE,TH,FR 00513 while (*p1 >= ' ') { 00514 //INFO(" %s", p1); 00515 for (int d=0; d<7; d++) { 00516 if (strncmp(p1,RepeatDayAbbrev(d),2) == 0) { 00517 Event->RepeatDays |= (1 << d); 00518 //INFO(" %s %02X", RepeatDayAbbrev(d), Event->RepeatDays); 00519 break; 00520 } 00521 } 00522 p1 += 3; 00523 } 00524 //INFO(" RepeatDay: %02X", Event->RepeatDays); 00525 } else if (strncmp(p1, "BYMONTHDAY=", 11) == 0) { 00526 // RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=2,15 00527 p1 += 11; 00528 while (*p1 >= ' ') { 00529 const char * px = p1; 00530 while (*px >= ' ' && *px != ',') { // find , or ; or <nul> 00531 px++; 00532 } 00533 //if (*px) 00534 // *px++ = '\0'; 00535 int num = atoi(p1); 00536 if (num >= 0) 00537 Event->RepeatMonthDay |= (1 << num); 00538 else 00539 Event->RepeatMonthDayRev |= (1 << -num); 00540 p1 = px; 00541 } 00542 INFO(" RepeatMonthDay: %08X", Event->RepeatMonthDay); 00543 } else if (strncmp(p1, "BYMONTH=", 8) == 0) { 00544 // RRULE:FREQ=YEARLY;INTERVAL=2;COUNT=10;BYMONTH=1,2,3 00545 p1 += 8; 00546 while (*p1 >= ' ') { 00547 const char * px = p1; 00548 while (*px >= ' ' && *px != ',') { // find , or ; or <nul> 00549 px++; 00550 } 00551 //if (*px) 00552 // *px++ = '\0'; 00553 int num = atoi(p1); 00554 if (num >= 0) 00555 Event->RepeatMonths |= (1 << num); 00556 //else 00557 // ; // Event->RepeatMonthsRev |= (1 << -num); 00558 p1 = px; 00559 } 00560 INFO(" RepeatMonths: %04X", Event->RepeatMonths); 00561 } 00562 if (!p2) 00563 break; 00564 p1 = p2 + 1; 00565 p2 = strchr(p1, ';'); 00566 //if (p2) 00567 // *p2++ = '\0'; 00568 } 00569 } 00570 } 00571 00572 00573 // TZID="(GMT -06:00)":20140519T063000 00574 // TZID:(UTC-06:00) Central Time (US & Canada) 00575 // TZID:(GMT -06:00) 00576 HTTPiCal::tz_sec_t HTTPiCal::ParseTZID(const char * string) 00577 { 00578 tz_sec_t tzo = 0; 00579 bool sign = false; 00580 00581 INFO("ParseTZID(%s)", string); // TZID="(GMT -06:00)":20140519T063000 00582 string += 5; // "(GMT -06:00)":20140519T063000 00583 if (*string == '"') 00584 string++; // (GMT -06:00)":20140519T063000 00585 if ((strncmp(string, "(UTC", 4) == 0) 00586 || (strncmp(string, "(GMT", 4) == 0) ){ 00587 string += 4; 00588 if (*string == ' ') 00589 string++; 00590 if (*string == '-') { 00591 sign = true; 00592 string++; 00593 } 00594 tzo = atoi(string) * 3600; 00595 string = strchr(string, ':'); 00596 if (string) { 00597 string++; 00598 tzo += atoi(string) * 60; 00599 } 00600 if (sign) 00601 tzo = -tzo; 00602 INFO(" tzo = %d", tzo); 00603 } else { 00604 ERR("Unhandled TZID(%s)", string); 00605 } 00606 return tzo; 00607 } 00608 00609 int HTTPiCal::ParseICalStream(const char * pStart, time_t gridStartTime, time_t gridEndTime, tz_min_t tzoMin, bool showEvents) 00610 { 00611 INFO("Parse(%s)", pStart); 00612 //INFO("EventCount: %d, EventSpaceCount: %d, seeking: %d", EventCount, EventSpaceCount, seeking); 00613 if (pStart && *pStart && EventCount < EventSpaceCount) { 00614 switch (seeking) { 00615 case idle: 00616 if (strncmp(pStart, "BEGIN:VTIMEZONE", 15) == 0) { 00617 //INFO("begin:timezone"); 00618 seeking = inTimeZone; 00619 } else if (strncmp(pStart, "BEGIN:VEVENT", 12) == 0) { 00620 //INFO("begin:vevent"); 00621 seeking = inEvent; 00622 EventList[EventCount].Start = 0; 00623 EventList[EventCount].End = 0; 00624 EventList[EventCount].Until = 0; 00625 EventList[EventCount].Summary[0] = '\0'; 00626 EventList[EventCount].Location[0] = '\0'; 00627 EventList[EventCount].Category[0] = '\0'; 00628 EventList[EventCount].Count = 0; 00629 EventList[EventCount].Interval = 0; 00630 EventList[EventCount].RepeatFreq = rptfNone; 00631 EventList[EventCount].RepeatDays = 0; 00632 EventList[EventCount].RepeatMonthDay = 0; 00633 EventList[EventCount].RepeatMonthDayRev = 0; 00634 EventList[EventCount].RepeatMonths = 0; 00635 EventList[EventCount].Priority = 5; // 5 is Normal 00636 } 00637 break; 00638 case inTimeZone: 00639 //INFO("inTimeZone:"); 00640 // Can also pick up daylight savings time 00641 if (strncmp(pStart, "END:VTIMEZONE", 13) == 0) { 00642 seeking = idle; 00643 } else if ((strncmp(pStart, "TZID:", 5) == 0) 00644 || (strncmp(pStart, "TZID=", 5) == 0) ) { 00645 tzoTZIDSec = ParseTZID(pStart); 00646 tzAdjusted = true; 00647 pStart += 5; 00648 } else if (strncmp(pStart, "BEGIN:STANDARD", 14) == 0) { 00649 00650 } else if (strncmp(pStart, "BEGIN:DAYLIGHT", 14) == 0) { 00651 00652 } 00653 break; 00654 case inEvent: 00655 //INFO("inEvent:"); 00656 // inEvent 00657 if (strncmp(pStart, "END:VEVENT", 10) == 0) { 00658 // Timezone offset 00659 if (!tzAdjusted) { 00660 EventList[EventCount].Start += (60 * tzoMin); 00661 if (EventList[EventCount].End) 00662 EventList[EventCount].End += (60 * tzoMin); 00663 } 00664 // Process it 00665 if (showEvents) { 00666 //printf("ev: %d\r\n", EventCount); 00667 ShowEventInfo(EventList[EventCount]); 00668 } 00669 // Force to ALWAYS 00670 time_t aStart = EventList[EventCount].Start; 00671 time_t aEnd = EventList[EventCount].End; 00672 if (gridStartTime 00673 && RepeatIntersects(&aStart, &aEnd, &gridStartTime, &gridEndTime, &EventList[EventCount])) { 00674 EventCount++; 00675 if (showEvents) { 00676 INFO(" +++++ Added Event %d", EventCount);//, EventList[EventCount].Summary); 00677 } 00678 } 00679 seeking = idle; 00680 } else { 00681 //INFO("parse event data"); 00682 ParseEvent(&EventList[EventCount], pStart, 60 * tzoMin); 00683 } 00684 // End of inEvent 00685 break; 00686 default: 00687 INFO("default:"); 00688 seeking = idle; 00689 break; 00690 } 00691 } // while 00692 return EventCount; 00693 }
Generated on Tue Jul 12 2022 17:30:35 by
![doxygen](doxygen.png)