#include "palm_sync.h" /*********************************************************************** * * Function: tm2vcaldatetime * * Summary: converts an tm struct to a vcal datetime string * ***********************************************************************/ char *tm2vcaldatetime(struct tm time) { return g_strdup_printf("%04d%02d%02dT%02d%02d%02d", time.tm_year + 1900, time.tm_mon + 1, time.tm_mday, time.tm_hour, time.tm_min, time.tm_sec); } char *tm2vcaldate(struct tm time) { return g_strdup_printf("%04d%02d%02d", time.tm_year + 1900, time.tm_mon + 1, time.tm_mday); } char *escape_chars(char *str) { gchar **array = g_strsplit(str, ",", 0); gchar *newstr = g_strjoinv("\\,", array); g_strfreev(array); g_free(str); return newstr; } /*********************************************************************** * * Function: vcaltime2tm * * Summary: converts an vcal datetime stringto a tm struct * ***********************************************************************/ struct tm vcaltime2tm(char *vcaltime) { char buffer[1024]; struct tm time; //year strncpy(buffer, vcaltime, 4); buffer[4] = 0; time.tm_year = atoi(buffer) - 1900; //month strncpy(buffer, vcaltime + 4, 2); buffer[2] = 0; time.tm_mon = atoi(buffer) - 1; //day strncpy(buffer, vcaltime + 6, 2); buffer[2] = 0; time.tm_mday = atoi(buffer); if (strlen(vcaltime) != 8) { //hour strncpy(buffer, vcaltime + 9, 2); buffer[2] = 0; time.tm_hour = atoi(buffer); //minute strncpy(buffer, vcaltime + 11, 2); buffer[2] = 0; time.tm_min = atoi(buffer); //second strncpy(buffer, vcaltime + 13, 2); buffer[2] = 0; time.tm_sec = atoi(buffer); } else { time.tm_hour = 0; time.tm_min= 0; time.tm_sec = 0; } return time; } /*********************************************************************** * * Function: calendar2vevent * * Summary: converts an palm calendar record to an vevent card * ***********************************************************************/ GString *calendar2vevent(palm_connection *conn, struct Appointment appointment) { VObjectO *vcal; VObjectO *vevent; VObjectO *prop; GString *vcalstr; char *vcalptr; char buffer[1024]; char *tmp; int i; palm_debug(conn, 2, "Translating calendar to vevent"); palm_debug(conn, 3, "Calendar Entry:\nevent: %i\nbegin: %s\nend: %s\nalarm: %i\nadvance: %i\nadvanceUnits: %i\nrepeatType: %i\nrepeatForever: %i\nrepeatEnd %s:\nrepeatFrequency: %i\nrepeatDay: %i\nrepeatDays:\nrepeatWeekstart: %i\nexceptions: %i\nexception:\ndescription: %s\nnote: %s\n", appointment.event, tm2vcaldatetime(appointment.begin), tm2vcaldatetime(appointment.end), appointment.alarm, appointment.advance, appointment.advanceUnits, appointment.repeatType, appointment.repeatForever, tm2vcaldatetime(appointment.repeatEnd), appointment.repeatFrequency, appointment.repeatDay, appointment.repeatWeekstart, appointment.exceptions, appointment.description, appointment.note); vcal = newVObjectO(VCCalPropO); vevent = addPropO(vcal, VCEventPropO); addPropValueO(vevent, VCVersionPropO, "2.0"); //UTF8 conversion if (appointment.description) { tmp = g_convert(appointment.description, strlen(appointment.description), "utf8", conn->codepage, NULL, NULL, NULL); free(appointment.description); appointment.description = tmp; } if (appointment.note) { tmp = g_convert(appointment.note, strlen(appointment.note), "utf8", conn->codepage, NULL, NULL, NULL); free(appointment.note); appointment.note = tmp; } /* note */ if(appointment.note && strlen(appointment.note)) prop = addPropValueO(vevent, VCDescriptionPropO, g_strescape(appointment.note, NULL)); /* description */ if(appointment.description) { prop = addPropValueO(vevent, VCSummaryPropO, escape_chars(g_strescape(appointment.description, NULL))); } /* begin and end*/ if(appointment.event == 1) { prop = addPropValueO(vevent, VCDTstartPropO, tm2vcaldate(appointment.begin)); addPropValueO(prop, VCValuePropO, "DATE"); prop = addPropValueO(vevent, VCDTendPropO, tm2vcaldate(appointment.end)); addPropValueO(prop, VCValuePropO, "DATE"); } else { prop = addPropValueO(vevent, VCDTstartPropO, tm2vcaldatetime(appointment.begin)); addPropValueO(prop, VCValuePropO, "DATE-TIME"); prop = addPropValueO(vevent, VCDTendPropO, tm2vcaldatetime(appointment.end)); addPropValueO(prop, VCValuePropO, "DATE-TIME"); } /* alarm */ if(appointment.alarm) { prop = addPropO(vevent, VCAlarmPropO); addPropValueO(prop, VCActionPropO, "DISPLAY"); switch(appointment.advanceUnits) { case 0: snprintf(buffer, 1024, "-PT%iM", appointment.advance); break; case 1: snprintf(buffer, 1024, "-PT%iH", appointment.advance); break; case 2: snprintf(buffer, 1024, "-P%iD", appointment.advance); break; } if (appointment.description) addPropValueO(prop, VCDescriptionPropO, appointment.description); prop = addPropValueO(prop, VCTriggerPropO, buffer); addPropValueO(prop, VCRelatedPropO, "START"); addPropValueO(prop, VCValuePropO, "DURATION"); } //recurrence if (appointment.repeatType != repeatNone) { GString *rrulestr = g_string_new(""); /*Frequency*/ switch (appointment.repeatType) { case repeatDaily: rrulestr = g_string_append(rrulestr, "FREQ=DAILY;"); break; case repeatWeekly: g_string_append(rrulestr, "FREQ=WEEKLY;"); g_string_append(rrulestr, "BYDAY="); for(i = 0; i < 6; i++) { if (appointment.repeatDays[i]) { switch (i) { case 0: g_string_append(rrulestr, "SU,"); break; case 1: g_string_append(rrulestr, "MO,"); break; case 2: g_string_append(rrulestr, "TU,"); break; case 3: g_string_append(rrulestr, "WE,"); break; case 4: g_string_append(rrulestr, "TH,"); break; case 5: g_string_append(rrulestr, "FR,"); break; case 6: g_string_append(rrulestr, "SA,"); break; } } } //Now remove the coma g_string_truncate(rrulestr, strlen(rrulestr->str) - 1); g_string_append(rrulestr, ";"); break; case repeatMonthlyByDate: g_string_append(rrulestr, "FREQ=MONTHLY;"); g_string_append_printf(rrulestr, "BYMONTHDAY=%i;", appointment.begin.tm_mday); break; case repeatMonthlyByDay: g_string_append(rrulestr, "FREQ=MONTHLY;"); g_string_append_printf(rrulestr, "BYSETPOS=%i;", (int)(appointment.repeatDay / 7) + 1); g_string_append(rrulestr, "BYDAY="); switch (appointment.repeatDay % 7) { case 0: g_string_append(rrulestr, "SU,"); break; case 1: g_string_append(rrulestr, "MO,"); break; case 2: g_string_append(rrulestr, "TU,"); break; case 3: g_string_append(rrulestr, "WE,"); break; case 4: g_string_append(rrulestr, "TH,"); break; case 5: g_string_append(rrulestr, "FR,"); break; case 6: g_string_append(rrulestr, "SA,"); break; } //Now remove the coma g_string_truncate(rrulestr, strlen(rrulestr->str) - 1); g_string_append(rrulestr, ";"); break; case repeatYearly: g_string_append(rrulestr, "FREQ=YEARLY;"); break; /* repeatNone */ default: break; } /* interval */ if (appointment.repeatFrequency) { g_string_append_printf(rrulestr, "INTERVAL=%i;", appointment.repeatFrequency); } //repeatEnd if (!appointment.repeatForever) { g_string_append_printf(rrulestr, "UNTIL=%s;", tm2vcaldatetime(appointment.repeatEnd)); } //remove ; g_string_truncate(rrulestr, strlen(rrulestr->str) - 1); addPropValueO(vevent, VCRRulePropO, strdup(rrulestr->str)); g_string_free(rrulestr, FALSE); //exceptions if (appointment.exceptions) { for (i = 0; i < appointment.exceptions; i++) { prop = addPropValueO(vevent, "EXDATE", tm2vcaldate(appointment.exception[i])); addPropValueO(prop, "VALUE", "DATE"); } } } vcalptr = writeMemVObjectO(0,0,vcal); vcalstr = g_string_new(vcalptr); free(vcalptr); deleteVObjectO(vcal); palm_debug(conn, 3, "VCARD:\n%s", vcalstr->str); return vcalstr; } /*********************************************************************** * * Function: isAAttributefO * * Summary: vevent2calendar helper function for RRULE * ***********************************************************************/ char *isAAttributeOfO(char *rrule, char *pair) { char* val = NULL; gchar** attrval; gchar **rruletokens = g_strsplit(rrule, ";", 0); int i; for(i=0; rruletokens[i]!=NULL; i++) { attrval = g_strsplit(rruletokens[i], "=", 2); val = g_strdup(attrval[1]); if(strcmp(attrval[0], pair) == 0) { g_strfreev(attrval); g_strfreev(rruletokens); return val; } g_strfreev(attrval); g_free(val); } return NULL; } /*********************************************************************** * * Function: vevent2calendar * * Summary: converts an vevent card to an palm calendar record * ***********************************************************************/ void vevent2calendar(palm_connection *conn, palm_entry *entry, char *vevent) { VObjectO *v, *t, *prop, *vcal; VObjectIteratorO iter, j; const char *n; char *buffer; char *attrValue; char *day; char *rrulestr; palm_debug(conn, 2, "converting vevent to calendar"); registerMimeErrorHandlerO(VObjectOErrorHander); vcal = Parse_MIMEO(vevent, strlen(vevent)); initPropIteratorO(&iter,vcal); memset(&(entry->appointment), 0, sizeof(entry->appointment)); entry->appointment.event = 0; entry->appointment.alarm = 0; entry->appointment.advance = 0; entry->appointment.advanceUnits = 0; entry->appointment.repeatForever = 1; entry->appointment.repeatType = repeatNone; entry->appointment.repeatFrequency = 0; entry->appointment.repeatWeekstart= 0; entry->appointment.exception = malloc(sizeof(struct tm) * 20); entry->appointment.exceptions = 0; entry->appointment.description = ""; entry->appointment.note = NULL; while(moreIterationO(&iter)) { v = nextVObjectO(&iter); n = vObjectNameO(v); if (n) { if (strcmp(n,VCEventPropO) == 0) { initPropIteratorO(&j,v); while(moreIterationO(&j)) { t = nextVObjectO(&j); n = vObjectNameO(t); attrValue = fakeCStringO(vObjectUStringZValueO(t)); //Summary if(strcmp(n,VCSummaryPropO) == 0) { entry->appointment.description = g_strcompress(g_convert(attrValue, strlen(attrValue), conn->codepage ,"utf8", NULL, NULL, NULL)); } //Note if(strcmp(n,VCDescriptionPropO) == 0) { entry->appointment.note = g_strcompress(g_convert(attrValue, strlen(attrValue), conn->codepage ,"utf8", NULL, NULL, NULL)); } //Begin if(strcmp(n,VCDTstartPropO) == 0) { entry->appointment.begin = vcaltime2tm(attrValue); if (strlen(attrValue) == 8) { entry->appointment.event = 1; } } //End if(strcmp(n,VCDTendPropO) == 0) entry->appointment.end = vcaltime2tm(attrValue); //Alarm if(strcmp(n,VCAlarmPropO) == 0) { entry->appointment.alarm = 1; if ((prop = isAPropertyOfO(t, VCTriggerPropO))) { buffer = fakeCStringO(vObjectUStringZValueO(prop)); switch(buffer[strlen(buffer)-1]) { case 'M': entry->appointment.advanceUnits = 0; break; case 'H': entry->appointment.advanceUnits = 1; break; case 'D': entry->appointment.advanceUnits = 2; break; default: entry->appointment.advanceUnits = 0; } buffer[strlen(buffer)-1] = 0; entry->appointment.advance = atoi(buffer + 3); free(buffer); } } //recurrence if(strcmp(n,VCRRulePropO) == 0) { buffer = fakeCStringO(vObjectUStringZValueO(t)); //Frequency if ((rrulestr = isAAttributeOfO(buffer, VCFreqPropO))) { switch(rrulestr[0]) { case 'D': entry->appointment.repeatType = repeatDaily; break; case 'W': entry->appointment.repeatType = repeatWeekly; if ((day = isAAttributeOfO(buffer, "BYDAY"))) { gchar** weekdaystokens = g_strsplit(day, ",", 7); int j = 0; for(j = 0; weekdaystokens[j] != NULL; j++) { if(!strcmp(weekdaystokens[j], "SU")) { entry->appointment.repeatDays[0] = 1; } else if(!strcmp(weekdaystokens[j], "MO")) { entry->appointment.repeatDays[1] = 1; } else if(!strcmp(weekdaystokens[j], "TU")) { entry->appointment.repeatDays[2] = 1; } else if(!strcmp(weekdaystokens[j], "WE")) { entry->appointment.repeatDays[3] = 1; } else if(!strcmp(weekdaystokens[j], "TH")) { entry->appointment.repeatDays[4] = 1; } else if(!strcmp(weekdaystokens[j], "FR")) { entry->appointment.repeatDays[5] = 1; } else if(!strcmp(weekdaystokens[j], "SA")) { entry->appointment.repeatDays[6] = 1; } } g_free(day); } break; case 'M': //We now need to find out if by date or by day if ((day = isAAttributeOfO(buffer, "BYMONTHDAY"))) { //By date if (atoi(day) <= 0) { palm_debug(conn, 0, "Unsupported Recurrence Rule: Counting days from the end of the month"); } else { entry->appointment.repeatType = repeatMonthlyByDate; //Now set the date entry->appointment.begin.tm_mday = atoi(day); } g_free(day); } else if ((day = isAAttributeOfO(buffer, "BYDAY"))) { //By day entry->appointment.repeatType = repeatMonthlyByDay; if (!strcmp(day, "SU")) { entry->appointment.repeatDay = (7 * atoi(isAAttributeOfO(buffer, "BYSETPOS"))) - 7; } else if (!strcmp(day, "MO")) { entry->appointment.repeatDay = (7 * atoi(isAAttributeOfO(buffer, "BYSETPOS"))) - 6; } else if (!strcmp(day, "TU")) { entry->appointment.repeatDay = (7 * atoi(isAAttributeOfO(buffer, "BYSETPOS"))) - 5; } else if (!strcmp(day, "WE")) { entry->appointment.repeatDay = (7 * atoi(isAAttributeOfO(buffer, "BYSETPOS"))) - 4; } else if (!strcmp(day, "TH")) { entry->appointment.repeatDay = (7 * atoi(isAAttributeOfO(buffer, "BYSETPOS"))) - 3; } else if (!strcmp(day, "FR")) { entry->appointment.repeatDay = (7 * atoi(isAAttributeOfO(buffer, "BYSETPOS"))) - 2; } else if (!strcmp(day, "SA")) { entry->appointment.repeatDay = (7 * atoi(isAAttributeOfO(buffer, "BYSETPOS"))) - 1; } g_free(day); } break; case 'Y': entry->appointment.repeatType = repeatYearly; break; } g_free(rrulestr); } //repeatEnd if ((rrulestr = isAAttributeOfO(buffer, VCUntilPropO))) { entry->appointment.repeatEnd = vcaltime2tm(rrulestr); entry->appointment.repeatForever = 0; g_free(rrulestr); } //For if ((rrulestr = isAAttributeOfO(buffer, "COUNT"))) { palm_debug(conn, 0, "Unable to translate \"COUNT\" Property. (\"For\" Recurrence in Evolution)"); g_free(rrulestr); } //Intervall if ((rrulestr = isAAttributeOfO(buffer, VCIntervalPropO))) { entry->appointment.repeatFrequency = atoi(rrulestr); g_free(rrulestr); } } //Exceptions TODO if(strcmp(n,"EXDATE") == 0) { entry->appointment.exception[entry->appointment.exceptions] = vcaltime2tm(fakeCStringO(vObjectUStringZValueO(t))); entry->appointment.exceptions++; } if (attrValue) free(attrValue); } } } } palm_debug(conn, 2 , "end: vcal2calendar"); palm_debug(conn, 3, "Calendar Entry:\nevent: %i\nbegin: %s\nend: %s\nalarm: %i\nadvance: %i\nadvanceUnits: %i\nrepeatType: %i\nrepeatForever: %i\nrepeatEnd %s:\nrepeatFrequency: %i\nrepeatDay:\nrepeatDays:\nrepeatWeekstart: %i\nexceptions: %i\nexception:\ndescription: %s\nnote: %s\n" , entry->appointment.event, tm2vcaldatetime(entry->appointment.begin), tm2vcaldatetime(entry->appointment.end), entry->appointment.alarm, entry->appointment.advance, entry->appointment.advanceUnits, entry->appointment.repeatType, entry->appointment.repeatForever, tm2vcaldatetime(entry->appointment.repeatEnd), entry->appointment.repeatFrequency, entry->appointment.repeatWeekstart, entry->appointment.exceptions, entry->appointment.description, entry->appointment.note); deleteVObjectO(vcal); } /*********************************************************************** * * Function: todo2vcard * * Summary: converts an palm todo record to an vcard * ***********************************************************************/ GString *todo2vcal(palm_connection *conn, struct ToDo todo, char *category) { VObjectO *vcal; VObjectO *vtodo; VObjectO *prop; GString *vcalstr; char *vcalptr; char buffer[1024]; time_t now; struct tm *now_tm; char *tmp; palm_debug(conn, 2, "Translating todo to vcard"); palm_debug(conn, 2, "ToDo Entry:\nIndefinite: %i\nDue: %s\nPriority: %i\nComplete: %i\nDescription: %s\nNote: %s", todo.indefinite, tm2vcaldatetime(todo.due), todo.priority, todo.complete, todo.description, todo.note); vcal = newVObjectO(VCCalPropO); vtodo = addPropO(vcal, VCTodoPropO); addPropValueO(vtodo, VCVersionPropO, "2.0"); //UTF8 conversion if (todo.description) { tmp = g_convert(todo.description, strlen(todo.description), "utf8", conn->codepage, NULL, NULL, NULL); free(todo.description); todo.description = tmp; } if (todo.note) { tmp = g_convert(todo.note, strlen(todo.note), "utf8", conn->codepage, NULL, NULL, NULL); free(todo.note); todo.note = tmp; } //priority if (todo.priority) { snprintf(buffer, 1024, "%i", todo.priority + 2); addPropValueO(vtodo, VCPriorityPropO, buffer); } //due if (todo.indefinite == 0) { prop = addPropValueO(vtodo, VCDuePropO, tm2vcaldatetime(todo.due)); addPropValueO(prop, VCValuePropO, "DATE"); } /* completed */ if(todo.complete) { now = time(NULL); now_tm = gmtime(&now); addPropValueO(vtodo, VCCompletedPropO, tm2vcaldatetime(*now_tm)); addPropValueO(vtodo, VCStatusPropO, "COMPLETED"); } /* note */ if(todo.note && strlen(todo.note)) { prop = addPropValueO(vtodo, VCDescriptionPropO, escape_chars(g_strescape(todo.note, NULL))); //addPropValueO(prop, "ENCODING", "QUOTED-PRINTABLE"); } /* description */ if(todo.description) { addPropValueO(vtodo, VCSummaryPropO, escape_chars(g_strescape(todo.description, NULL))); } if (category) { addPropValueO(vtodo, "CATEGORIES", category); } vcalptr = writeMemVObjectO(0,0,vcal); vcalstr = g_string_new(vcalptr); free(vcalptr); deleteVObjectO(vcal); palm_debug(conn, 3, "VCARD:\n%s", vcalstr->str); return vcalstr; } /*********************************************************************** * * Function: vcal2todo * * Summary: converts an vcard to an palm todo record * ***********************************************************************/ void vcal2todo(palm_connection *conn, palm_entry *entry, char *vcard) { VObjectO *v, *t, *vcal; VObjectIteratorO iter, j; const char *n; char *attrValue; palm_debug(conn, 2, "converting vcal to todo"); registerMimeErrorHandlerO(VObjectOErrorHander); vcal = Parse_MIMEO(vcard, strlen(vcard)); initPropIteratorO(&iter,vcal); memset(&(entry->todo), 0, sizeof(entry->todo)); entry->todo.priority = 0; entry->todo.complete = 0; entry->todo.description = ""; entry->todo.note = ""; entry->todo.indefinite = 1; while(moreIterationO(&iter)) { v = nextVObjectO(&iter); n = vObjectNameO(v); if (n) { if (strcmp(n,VCTodoPropO) == 0) { initPropIteratorO(&j,v); while(moreIterationO(&j)) { t = nextVObjectO(&j); n = vObjectNameO(t); attrValue = fakeCStringO(vObjectUStringZValueO(t)); //Priority if(strcmp(n,VCPriorityPropO) == 0) { entry->todo.priority = atoi(attrValue) - 2; if (entry->todo.priority < 1) { //Never go lower than 1 entry->todo.priority = 1; } if (atoi(attrValue) == 0) { //Default to priority 5 entry->todo.priority = 5; } } //Complete if(strcmp(n,VCStatusPropO) == 0) { if(!strcmp(attrValue, "COMPLETED")) { entry->todo.complete = 1; } } //Summary if(strcmp(n,VCSummaryPropO) == 0) { entry->todo.description = g_strcompress(g_convert(attrValue, strlen(attrValue), conn->codepage ,"utf8", NULL, NULL, NULL)); } //Note if(strcmp(n,VCDescriptionPropO) == 0) { entry->todo.note = g_strcompress(g_convert(attrValue, strlen(attrValue), conn->codepage ,"utf8", NULL, NULL, NULL)); } //Due if(strcmp(n,VCDuePropO) == 0) { entry->todo.due = vcaltime2tm(attrValue); entry->todo.indefinite = 0; } //Categories if (!strcmp(n, "CATEGORIES")) { palm_debug(conn, 3, "GOT CATEGORIES: %s\n", attrValue); gchar **array = g_strsplit(g_strcompress(attrValue), ",", 0); int z = 0; while (array[z] != NULL) { palm_debug(conn, 3, "testing %s\n", array[z]); entry->catID = get_category_id_from_name(conn, array[z]); if (entry->catID != 0) { palm_debug(conn, 3, "Found category %i\n", entry->catID); break; } z++; } g_strfreev(array); } if (attrValue) free(attrValue); } } } } palm_debug(conn, 2 , "end: vcal2todo"); palm_debug(conn, 2, "ToDo Entry:\nIndefinite: %i\nDue: %s\nPriority: %i\nComplete: %i\nDescription: %s\nNote: %s", entry->todo.indefinite, tm2vcaldatetime(entry->todo.due), entry->todo.priority, entry->todo.complete, entry->todo.description, entry->todo.note); deleteVObjectO(vcal); } /*********************************************************************** * * Function: address2vcard * * Summary: converts an palm address entry to a vcard entry * ***********************************************************************/ GString *address2vcard(palm_connection *conn, struct Address address, char *category) { VObjectO *nameprop = NULL, *prop = NULL, *addrprop = NULL; VObjectO *vcard; int i = 0; GString *vcardstr; char *vcardptr; gchar *label = NULL; gchar *fullname = NULL; palm_debug(conn, 2, "Converting address to vcard"); vcard = newVObjectO(VCCardPropO); addPropValueO(vcard, VCVersionPropO, "2.1"); for (i = 0; i < 19; i++) { if (address.entry[i]) { char *tmp; palm_debug(conn, 3, "Palm Entry: %i: %s", i, address.entry[i]); tmp = g_convert(address.entry[i], strlen(address.entry[i]), "utf8", conn->codepage, NULL, NULL, NULL); free(address.entry[i]); address.entry[i] = tmp; switch (i) { case 0: //Last Name if (!nameprop) nameprop = addPropO(vcard, "N"); addPropValueO(nameprop, VCFamilyNamePropO, address.entry[i]); fullname = g_strdup(address.entry[0]); break; case 1: //First Name if (!nameprop) nameprop = addPropO(vcard, "N"); addPropValueO(nameprop, VCGivenNamePropO, address.entry[i]); if (fullname) g_free(fullname); fullname = g_strconcat(address.entry[1], " ", address.entry[0], NULL); break; case 2: //Company prop = addPropO(vcard, "ORG"); addPropValueO(prop, "ORGNAME", address.entry[i]); break; case 3: case 4: case 5: case 6: case 7: palm_debug(conn, 3, "GOT TEL with phoneLabel %i", address.phoneLabel[i - 3]); switch (address.phoneLabel[i - 3]) { case 0: prop = addPropValueO(vcard, "TEL", address.entry[i]); addPropO(prop, "WORK"); addPropO(prop, "VOICE"); break; case 1: prop = addPropValueO(vcard, "TEL", address.entry[i]); addPropO(prop, "HOME"); break; case 2: prop = addPropValueO(vcard, "TEL", address.entry[i]); addPropO(prop, "WORK"); addPropO(prop, "FAX"); break; case 3: prop = addPropValueO(vcard, "TEL", address.entry[i]); addPropO(prop, "VOICE"); break; case 4: prop = addPropValueO(vcard, "EMAIL", address.entry[i]); addPropO(prop, "INTERNET"); break; case 5: prop = addPropValueO(vcard, "TEL", address.entry[i]); addPropO(prop, "PREF"); break; case 6: prop = addPropValueO(vcard, "TEL", address.entry[i]); addPropO(prop, "PAGER"); break; case 7: prop = addPropValueO(vcard, "TEL", address.entry[i]); addPropO(prop, "CELL"); break; } break; case 8: if (!addrprop) { addrprop = addPropO(vcard, "ADR"); addPropValueO(addrprop, "ENCODING", "QUOTED-PRINTABLE"); } addPropValueO(addrprop, "STREET", address.entry[i]); break; case 9: if (!addrprop) { addrprop = addPropO(vcard, "ADR"); addPropValueO(addrprop, "ENCODING", "QUOTED-PRINTABLE"); } addPropValueO(addrprop, "L", address.entry[i]); break; case 10: if (!addrprop) { addrprop = addPropO(vcard, "ADR"); addPropValueO(addrprop, "ENCODING", "QUOTED-PRINTABLE"); } addPropValueO(addrprop, "R", address.entry[i]); break; case 11: if (!addrprop) { addrprop = addPropO(vcard, "ADR"); addPropValueO(addrprop, "ENCODING", "QUOTED-PRINTABLE"); } addPropValueO(addrprop, "PC", address.entry[i]); break; case 12: if (!addrprop) { addrprop = addPropO(vcard, "ADR"); addPropValueO(addrprop, "ENCODING", "QUOTED-PRINTABLE"); } addPropValueO(addrprop, "C", address.entry[i]); break; case 13: prop = addPropValueO(vcard, "TITLE", address.entry[i]); break; case 18: prop = addPropValueO(vcard, "NOTE", address.entry[i]); addPropValueO(prop, "ENCODING", "QUOTED-PRINTABLE"); break; } } } if (addrprop) { //Make the Label for (i = 8; i <= 12; i++) { if (address.entry[i]) { if (!label) { label = ""; } else { label = g_strconcat(label, "\n", NULL); } label = g_strconcat(label, address.entry[i], NULL); } } prop = addPropValueO(vcard, "LABEL", label); addPropValueO(prop, "ENCODING", "QUOTED-PRINTABLE"); addPropO(prop, "WORK"); } if (category) { addPropValueO(vcard, "CATEGORIES", category); } //Write the Fullname if (fullname) { addPropValueO(vcard, VCFullNamePropO, fullname); g_free(fullname); } vcardptr = writeMemVObjectO(0,0,vcard); vcardstr = g_string_new(vcardptr); free(vcardptr); deleteVObjectO(vcard); palm_debug(conn, 3, "VCARD:\n%s", vcardstr->str); return vcardstr; } /*********************************************************************** * * Function: vcard2address * * Summary: converts an vcard to a palm address entry * ***********************************************************************/ void vcard2address(palm_connection *conn, palm_entry *entry, char *vcard) { VObjectO *v, *prop, *vcontact; VObjectIteratorO iter; const char *attributes; int teliter = 0; int i; palm_debug(conn, 2, "converting vcard to address"); registerMimeErrorHandlerO(VObjectOErrorHander); vcontact = Parse_MIMEO(vcard, strlen(vcard)); initPropIteratorO(&iter,vcontact); //memset(&entry->address, 0, sizeof(entry->address)); for (i = 0; i < 19; i++) { entry->address.entry[i] = NULL; } while(moreIterationO(&iter)) { v = nextVObjectO(&iter); attributes = vObjectNameO(v); //Name if (!strcmp(attributes, "N")) { if ((prop = isAPropertyOfO(v, "F"))) { entry->address.entry[0] = fakeCStringO(vObjectUStringZValueO(prop)); } if ((prop = isAPropertyOfO(v, "G"))) { entry->address.entry[1] = fakeCStringO(vObjectUStringZValueO(prop)); } goto next; } //Company if (!strcmp(attributes, "ORG")) { if ((prop = isAPropertyOfO(v, "ORGNAME"))) { entry->address.entry[2] = fakeCStringO(vObjectUStringZValueO(prop)); } goto next; } //Telephone if (!strcmp(attributes, "TEL")) { entry->address.entry[3 + teliter] = fakeCStringO(vObjectUStringZValueO(v)); if (isAPropertyOfO(v, "WORK") && isAPropertyOfO(v, "VOICE")) { entry->address.phoneLabel[teliter] = 0; teliter++; goto next; } if (isAPropertyOfO(v, "HOME") && !(isAPropertyOfO(v, "FAX"))) { entry->address.phoneLabel[teliter] = 1; teliter++; goto next; } if (isAPropertyOfO(v, "FAX")) { entry->address.phoneLabel[teliter] = 2; teliter++; goto next; } if (!(isAPropertyOfO(v, "WORK")) && !(isAPropertyOfO(v, "HOME")) && isAPropertyOfO(v, "VOICE")) { entry->address.phoneLabel[teliter] = 3; teliter++; goto next; } if (isAPropertyOfO(v, "PREF") && !(isAPropertyOfO(v, "FAX"))) { entry->address.phoneLabel[teliter] = 5; teliter++; goto next; } if (isAPropertyOfO(v, "PAGER")) { entry->address.phoneLabel[teliter] = 6; teliter++; goto next; } if (isAPropertyOfO(v, "CELL")) { entry->address.phoneLabel[teliter] = 7; teliter++; goto next; } palm_debug(conn, 0, "Unknown TEL entry"); } //EMail if (!strcmp(attributes, "EMAIL")) { entry->address.entry[3 + teliter] = fakeCStringO(vObjectUStringZValueO(v)); entry->address.phoneLabel[teliter] = 4; teliter++; goto next; } if (!strcmp(attributes, "ADR")) { if ((prop = isAPropertyOfO(v, VCStreetAddressPropO))) { entry->address.entry[8] = fakeCStringO(vObjectUStringZValueO(prop)); } if ((prop = isAPropertyOfO(v, VCCityPropO))) { entry->address.entry[9] = fakeCStringO(vObjectUStringZValueO(prop)); } if ((prop = isAPropertyOfO(v, VCRegionPropO))) { entry->address.entry[10] = fakeCStringO(vObjectUStringZValueO(prop)); } if ((prop = isAPropertyOfO(v, VCPostalCodePropO))) { entry->address.entry[11] = fakeCStringO(vObjectUStringZValueO(prop)); } if ((prop = isAPropertyOfO(v, VCCountryNamePropO))) { entry->address.entry[12] = fakeCStringO(vObjectUStringZValueO(prop)); } goto next; } //Title if (!strcmp(attributes, "TITLE")) { entry->address.entry[13] = fakeCStringO(vObjectUStringZValueO(v)); goto next; } //Note if (!strcmp(attributes, "NOTE")) { entry->address.entry[18] = fakeCStringO(vObjectUStringZValueO(v)); goto next; } //Categories if (!strcmp(attributes, "CATEGORIES")) { palm_debug(conn, 3, "GOT CATEGORIES: %s\n", fakeCStringO(vObjectUStringZValueO(v))); gchar **array = g_strsplit(fakeCStringO(vObjectUStringZValueO(v)), ",", 0); int z = 0; while (array[z] != NULL) { palm_debug(conn, 3, "testing %s\n", array[z]); entry->catID = get_category_id_from_name(conn, array[z]); if (entry->catID != 0) { palm_debug(conn, 3, "Found category %i\n", entry->catID); break; } z++; } g_strfreev(array); goto next; } //Ignore these if (!strcmp(attributes, "LABEL") || !strcmp(attributes, "FN") || !strcmp(attributes, "VERSION") || !strcmp(attributes, "X-EVOLUTION-FILE-AS") || !strcmp(attributes, "UID")) goto next; //Catch all palm_debug(conn, 1, "Unable to translate Vcard prop %s to a palm entry", attributes); next: ; } for (i = 0; i < 19; i++) { if (entry->address.entry[i]) { char *tmp = g_convert(entry->address.entry[i], strlen(entry->address.entry[i]), conn->codepage ,"utf8", NULL, NULL, NULL); free(entry->address.entry[i]); entry->address.entry[i] = tmp; } if (entry->address.entry[i] && !strlen(entry->address.entry[i])) { free(entry->address.entry[i]); entry->address.entry[i] = NULL; palm_debug(conn, 3, "Address %i: %s", i, entry->address.entry[i]); } } deleteVObjectO(vcontact); palm_debug(conn, 2, "end: vcard2address"); } /*********************************************************************** * * Function: VObjectOErrorHander * * Summary: generic parse error handler * ***********************************************************************/ void VObjectOErrorHander(char *errstr) { printf("VObjectO parse failed: %s\n", errstr); }