GSM_Error VC_StoreText(char *Buffer, const size_t buff_len, size_t *Pos, const unsigned char *Text, const char *Start, const gboolean UTF8) { char *buffer=NULL; size_t len=0; GSM_Error error; len = UnicodeLength(Text); if (len == 0) return ERR_NONE; /* Need to be big enough to store quoted printable */ buffer = (char *)malloc(len * 8); if (buffer == NULL) return ERR_MOREMEMORY; if (UTF8) { EncodeUTF8QuotedPrintable(buffer, Text); error = VC_StoreLine(Buffer, buff_len, Pos, "%s:%s", Start, buffer); } else { EncodeUTF8QuotedPrintable(buffer, Text); if (UnicodeLength(Text) == strlen(buffer)) { /* Text is plain ASCII */ error = VC_StoreLine(Buffer, buff_len, Pos, "%s:%s", Start, buffer); } else { error = VC_StoreLine(Buffer, buff_len, Pos, "%s;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:%s", Start, buffer); } } free(buffer); buffer=NULL; return error; }
GSM_Error DUMMY_AddFilePart(GSM_StateMachine *s, GSM_File *File, int *Pos, int *Handle) { char *path; FILE *file; size_t pos; GSM_Error error; *Handle = 0; pos = UnicodeLength(File->ID_FullName); if (pos > 0 && (File->ID_FullName[2*pos - 2] != 0 || File->ID_FullName[2*pos - 1] != '/')) { File->ID_FullName[2*pos + 1] = '/'; File->ID_FullName[2*pos + 0] = 0; pos++; } CopyUnicodeString(File->ID_FullName + 2 * pos, File->Name); path = DUMMY_GetFSFilePath(s, File->ID_FullName); file = fopen(path, "w"); if (file == NULL) { free(path); error = DUMMY_Error(s, "fopen(w) failed"); if (error == ERR_EMPTY) return ERR_PERMISSION; return error; } if (fwrite(File->Buffer, 1, File->Used, file) != File->Used) { free(path); error = DUMMY_Error(s, "fwrite failed"); fclose(file); if (error == ERR_EMPTY) return ERR_PERMISSION; return error; } if (fclose(file) != 0) { free(path); error = DUMMY_Error(s, "fclose failed"); if (error == ERR_EMPTY) return ERR_PERMISSION; return error; } free(path); path=NULL; *Pos = File->Used; return ERR_EMPTY; }
int CopyStringFromDict(PyObject * dict, const char *key, size_t len, unsigned char *dest) { unsigned char *s; s = GetStringFromDict(dict, key); if (s == NULL) return 0; if (UnicodeLength(s) > len) { pyg_warning("Truncating text %s to %ld chars!\n", key, (long)len); s[2 * len] = 0; s[(2 * len) + 1] = 0; } CopyUnicodeString(dest, s); free(s); return 1; }
GSM_Error DUMMY_AddFolder(GSM_StateMachine *s, GSM_File *File) { char *path; size_t pos; pos = UnicodeLength(File->ID_FullName); if (pos > 0 && (File->ID_FullName[2*pos - 2] != 0 || File->ID_FullName[2*pos - 1] != '/')) { File->ID_FullName[2*pos + 1] = '/'; File->ID_FullName[2*pos + 0] = 0; pos++; } CopyUnicodeString(File->ID_FullName + 2 * pos, File->Name); path = DUMMY_GetFSFilePath(s, File->ID_FullName); if (MKDIR(path) != 0) { free(path); path=NULL; return DUMMY_Error(s, "mkdir failed"); } free(path); path=NULL; return ERR_NONE; }
static SQL_Error SMSDSQL_NamedQuery(GSM_SMSDConfig * Config, const char *sql_query, GSM_SMSMessage *sms, const SQL_Var *params, SQL_result * res) { char buff[65536], *ptr, c, static_buff[8192]; char *buffer2, *end; const char *to_print, *q = sql_query; int int_to_print; int numeric; int n, argc = 0; struct GSM_SMSDdbobj *db = Config->db; if (params != NULL) { while (params[argc].type != SQL_TYPE_NONE) argc++; } ptr = buff; do { if (*q != '%') { *ptr++ = *q; continue; } c = *(++q); if( c >= '0' && c <= '9'){ n = strtoul(q, &end, 10) - 1; if (n < argc && n >= 0) { switch(params[n].type){ case SQL_TYPE_INT: ptr += sprintf(ptr, "%i", params[n].v.i); break; case SQL_TYPE_STRING: buffer2 = db->QuoteString(Config, params[n].v.s); memcpy(ptr, buffer2, strlen(buffer2)); ptr += strlen(buffer2); free(buffer2); break; default: SMSD_Log(DEBUG_ERROR, Config, "SQL: unknown type: %i (application bug) in query: `%s`", params[n].type, sql_query); return SQL_BUG; break; } } else { SMSD_Log(DEBUG_ERROR, Config, "SQL: wrong number of parameter: %i (max %i) in query: `%s`", n+1, argc, sql_query); return SQL_BUG; } q = end - 1; continue; } numeric = 0; to_print = NULL; switch (c) { case 'I': to_print = Config->Status->IMEI; break; case 'P': to_print = Config->PhoneID; break; case 'N': snprintf(static_buff, sizeof(static_buff), "Gammu %s, %s, %s", GAMMU_VERSION, GetOS(), GetCompiler()); to_print = static_buff; break; case 'A': to_print = Config->CreatorID; break; default: if (sms != NULL) { switch (c) { case 'R': EncodeUTF8(static_buff, sms->Number); to_print = static_buff; break; case 'F': EncodeUTF8(static_buff, sms->SMSC.Number); to_print = static_buff; break; case 'u': if (sms->UDH.Type != UDH_NoUDH) { EncodeHexBin(static_buff, sms->UDH.Text, sms->UDH.Length); to_print = static_buff; }else{ to_print = ""; } break; case 'x': int_to_print = sms->Class; numeric = 1; break; case 'c': to_print = GSM_SMSCodingToString(sms->Coding); break; case 't': int_to_print = sms->MessageReference; numeric = 1; break; case 'E': switch (sms->Coding) { case SMS_Coding_Unicode_No_Compression: case SMS_Coding_Default_No_Compression: EncodeHexUnicode(static_buff, sms->Text, UnicodeLength(sms->Text)); break; case SMS_Coding_8bit: EncodeHexBin(static_buff, sms->Text, sms->Length); break; default: *static_buff = '\0'; break; } to_print = static_buff; break; case 'T': switch (sms->Coding) { case SMS_Coding_Unicode_No_Compression: case SMS_Coding_Default_No_Compression: EncodeUTF8(static_buff, sms->Text); to_print = static_buff; break; default: to_print = ""; break; } break; case 'V': if (sms->SMSC.Validity.Format == SMS_Validity_RelativeFormat) { int_to_print = sms->SMSC.Validity.Relative; } else { int_to_print = -1; } numeric = 1; break; case 'C': SMSDSQL_Time2String(Config, Fill_Time_T(sms->SMSCTime), static_buff, sizeof(static_buff)); to_print = static_buff; break; case 'd': SMSDSQL_Time2String(Config, Fill_Time_T(sms->DateTime), static_buff, sizeof(static_buff)); to_print = static_buff; break; case 'e': int_to_print = sms->DeliveryStatus; numeric = 1; break; default: SMSD_Log(DEBUG_ERROR, Config, "SQL: uexpected char '%c' in query: %s", c, sql_query); return SQL_BUG; } /* end of switch */ } else { SMSD_Log(DEBUG_ERROR, Config, "Syntax error in query.. uexpected char '%c' in query: %s", c, sql_query); return SQL_BUG; } break; } /* end of switch */ if (numeric) { ptr += sprintf(ptr, "%i", int_to_print); } else if (to_print != NULL) { buffer2 = db->QuoteString(Config, to_print); memcpy(ptr, buffer2, strlen(buffer2)); ptr += strlen(buffer2); free(buffer2); } else { memcpy(ptr, "NULL", 4); ptr += 4; } } while (*(++q) != '\0'); *ptr = '\0'; return SMSDSQL_Query(Config, buff, res); }
/* Find one multi SMS to sending and return it (or return ERR_EMPTY) * There is also set ID for SMS * File extension convention: * OUTxxxxx.txt : normal text SMS * Options appended to the extension applying to this SMS only: * d: delivery report requested * f: flash SMS * b: WAP bookmark as name,URL * e.g. OUTG20040620_193810_123_+4512345678_xpq.txtdf * is a flash text SMS requesting delivery reports */ static GSM_Error SMSDFiles_FindOutboxSMS(GSM_MultiSMSMessage * sms, GSM_SMSDConfig * Config, char *ID) { GSM_MultiPartSMSInfo SMSInfo; GSM_WAPBookmark Bookmark; char FileName[100], FullName[400]; unsigned char Buffer[(GSM_MAX_SMS_LENGTH * GSM_MAX_MULTI_SMS + 1) * 2]; unsigned char Buffer2[(GSM_MAX_SMS_LENGTH * GSM_MAX_MULTI_SMS + 1) * 2]; FILE *File; int i, len, phlen; char *pos1, *pos2, *options = NULL; gboolean backup = FALSE; #ifdef GSM_ENABLE_BACKUP GSM_SMS_Backup smsbackup; GSM_Error error; #endif #ifdef WIN32 struct _finddata_t c_file; intptr_t hFile; strcpy(FullName, Config->outboxpath); strcat(FullName, "OUT*.txt*"); hFile = _findfirst(FullName, &c_file); if (hFile == -1) { strcpy(FullName, Config->outboxpath); strcat(FullName, "OUT*.smsbackup*"); hFile = _findfirst(FullName, &c_file); backup = TRUE; } if (hFile == -1) { return ERR_EMPTY; } else { strcpy(FileName, c_file.name); } _findclose(hFile); #elif defined(HAVE_DIRBROWSING) struct dirent **namelist = NULL; int cur_file, num_files; char *pos; strcpy(FullName, Config->outboxpath); FullName[strlen(Config->outboxpath) - 1] = '\0'; num_files = scandir(FullName, &namelist, 0, alphasort); for (cur_file = 0; cur_file < num_files; cur_file++) { /* Hidden file or current/parent directory */ if (namelist[cur_file]->d_name[0] == '.') { continue; } /* We care only about files starting with out */ if (strncasecmp(namelist[cur_file]->d_name, "out", 3) != 0) { continue; } /* Check extension */ pos = strrchr(namelist[cur_file]->d_name, '.'); if (pos == NULL) { continue; } if (strncasecmp(pos, ".txt", 4) == 0) { /* We have found text file */ backup = FALSE; break; } if (strncasecmp(pos, ".smsbackup", 10) == 0) { /* We have found a SMS backup file */ backup = TRUE; break; } } /* Remember file name */ if (cur_file < num_files) { strcpy(FileName, namelist[cur_file]->d_name); } /* Free scandir result */ for (i = 0; i < num_files; i++) { free(namelist[i]); } free(namelist); namelist = NULL; /* Did we actually find something? */ if (cur_file >= num_files) { return ERR_EMPTY; } #else return ERR_NOTSUPPORTED; #endif strcpy(FullName, Config->outboxpath); strcat(FullName, FileName); if (backup) { #ifdef GSM_ENABLE_BACKUP /* Remember ID */ strcpy(ID, FileName); /* Load backup */ GSM_ClearSMSBackup(&smsbackup); error = GSM_ReadSMSBackupFile(FullName, &smsbackup); if (error != ERR_NONE) { return error; } /* Copy it to our message */ sms->Number = 0; for (i = 0; smsbackup.SMS[i] != NULL; i++) { sms->SMS[sms->Number++] = *smsbackup.SMS[i]; } /* Free memory */ GSM_FreeSMSBackup(&smsbackup); /* Set delivery report flag */ if (sms->SMS[0].PDU == SMS_Status_Report) { Config->currdeliveryreport = 1; } else { Config->currdeliveryreport = -1; } #else SMSD_Log(DEBUG_ERROR, Config, "SMS backup loading disabled at compile time!"); return ERR_DISABLED; #endif } else { options = strrchr(FileName, '.') + 4; File = fopen(FullName, "rb"); if (File == NULL) { return ERR_CANTOPENFILE; } len = fread(Buffer, 1, sizeof(Buffer) - 2, File); fclose(File); if ((len < 2) || (len >= 2 && ((Buffer[0] != 0xFF || Buffer[1] != 0xFE) && (Buffer[0] != 0xFE || Buffer[1] != 0xFF)))) { if (len > GSM_MAX_SMS_LENGTH * GSM_MAX_MULTI_SMS) len = GSM_MAX_SMS_LENGTH * GSM_MAX_MULTI_SMS; EncodeUnicode(Buffer2, Buffer, len); len = len * 2; memmove(Buffer, Buffer2, len); Buffer[len] = 0; Buffer[len + 1] = 0; } else { Buffer[len] = 0; Buffer[len + 1] = 0; /* Possibly convert byte order */ ReadUnicodeFile(Buffer2, Buffer); } GSM_ClearMultiPartSMSInfo(&SMSInfo); sms->Number = 0; SMSInfo.ReplaceMessage = 0; SMSInfo.Entries[0].Buffer = Buffer2; SMSInfo.Class = -1; SMSInfo.EntriesNum = 1; Config->currdeliveryreport = -1; if (strchr(options, 'd')) Config->currdeliveryreport = 1; if (strchr(options, 'f')) SMSInfo.Class = 0; /* flash SMS */ if (strcasecmp(Config->transmitformat, "unicode") == 0) { SMSInfo.Entries[0].ID = SMS_ConcatenatedTextLong; SMSInfo.UnicodeCoding = TRUE; } else if (strcasecmp(Config->transmitformat, "7bit") == 0) { SMSInfo.Entries[0].ID = SMS_ConcatenatedTextLong; SMSInfo.UnicodeCoding = FALSE; } else { /* auto */ SMSInfo.Entries[0].ID = SMS_ConcatenatedAutoTextLong; } if (strchr(options, 'b')) { // WAP bookmark as title,URL SMSInfo.Entries[0].Buffer = NULL; SMSInfo.Entries[0].Bookmark = &Bookmark; SMSInfo.Entries[0].ID = SMS_NokiaWAPBookmarkLong; SMSInfo.Entries[0].Bookmark->Location = 0; pos2 = mywstrstr(Buffer2, "\0,"); if (pos2 == NULL) { pos2 = Buffer2; } else { *pos2 = '\0'; pos2++; *pos2 = '\0'; pos2++; // replace comma by zero } len = UnicodeLength(Buffer2); if (len > 50) { len = 50; } memmove(&SMSInfo.Entries[0].Bookmark->Title, Buffer2, len * 2); pos1 = &SMSInfo.Entries[0].Bookmark->Title[0] + len * 2; *pos1 = '\0'; pos1++; *pos1 = '\0'; len = UnicodeLength(pos2); if (len > 255) { len = 255; } memmove(&SMSInfo.Entries[0].Bookmark->Address, pos2, len * 2); pos1 = &SMSInfo.Entries[0].Bookmark->Address[0] + len * 2; *pos1 = '\0'; pos1++; *pos1 = '\0'; } GSM_EncodeMultiPartSMS(GSM_GetDebug(Config->gsm), &SMSInfo, sms); strcpy(ID, FileName); pos1 = FileName; for (i = 1; i <= 3 && pos1 != NULL; i++) { pos1 = strchr(++pos1, '_'); } if (pos1 != NULL) { /* OUT<priority><date>_<time>_<serialno>_<phone number>_<anything>.txt */ pos2 = strchr(++pos1, '_'); if (pos2 != NULL) { phlen = strlen(pos1) - strlen(pos2); } else { /* something wrong */ return ERR_UNKNOWN; } } else if (i == 2) { /* OUTxxxxxxx.txt or OUTxxxxxxx */ pos1 = &FileName[3]; pos2 = strchr(pos1, '.'); if (pos2 == NULL) { phlen = strlen(pos1); } else { phlen = strlen(pos1) - strlen(pos2); } } else if (i == 4) { /* OUT<priority>_<phone number>_<serialno>.txt */ pos1 = strchr(FileName, '_'); pos2 = strchr(++pos1, '_'); phlen = strlen(pos1) - strlen(pos2); } else { /* something wrong */ return ERR_UNKNOWN; } for (len = 0; len < sms->Number; len++) { EncodeUnicode(sms->SMS[len].Number, pos1, phlen); } } if (sms->Number != 0) { DecodeUnicode(sms->SMS[0].Number, Buffer); if (options != NULL && strchr(options, 'b')) { // WAP bookmark as title,URL SMSD_Log(DEBUG_NOTICE, Config, "Found %i sms to \"%s\" with bookmark \"%s\" cod %i lgt %i udh: t %i l %i dlr: %i fls: %i", sms->Number, Buffer, DecodeUnicodeString(SMSInfo.Entries[0].Bookmark->Address), sms->SMS[0].Coding, sms->SMS[0].Length, sms->SMS[0].UDH.Type, sms->SMS[0].UDH.Length, Config->currdeliveryreport, SMSInfo.Class); } else { SMSD_Log(DEBUG_NOTICE, Config, "Found %i sms to \"%s\" with text \"%s\" cod %i lgt %i udh: t %i l %i dlr: %i fls: %i", sms->Number, Buffer, DecodeUnicodeString(sms->SMS[0].Text), sms->SMS[0].Coding, sms->SMS[0].Length, sms->SMS[0].UDH.Type, sms->SMS[0].UDH.Length, Config->currdeliveryreport, sms->SMS[0].Class); } } else { SMSD_Log(DEBUG_NOTICE, Config, "error: SMS-count = 0"); } return ERR_NONE; }
void NokiaAddPlayLists2(unsigned char *ID,unsigned char *Name,unsigned char *IDFolder) { GSM_Error error; gboolean Start = TRUE, Available = FALSE; GSM_File Files,Files2,Files3; int j,NamesPos2=0; size_t i, NamesPos = 0; unsigned char Buffer[20],Buffer2[500]; unsigned char *Names,*Names2,*Pointer; PlayListEntry *First,*Entry=NULL,*Prev; First = NULL; Names=NULL; Names2=NULL; CopyUnicodeString(Files.ID_FullName,ID); printf(_("Checking %s\n"),DecodeUnicodeString(Name)); /* looking into folder content (searching for mp3 and similiar) */ while (1) { error = GSM_GetFolderListing(gsm,&Files,Start); if (error == ERR_FOLDERPART) { printf("%s\n", _(" Only part handled!")); break; } if (error == ERR_EMPTY) break; if (error == ERR_FILENOTEXIST) return; Print_Error(error); if (!Files.Folder) { if (strcasestr(DecodeUnicodeConsole(Files.Name),".mp3")!=NULL || strcasestr(DecodeUnicodeConsole(Files.Name),".aac")!=NULL) { if (First==NULL) { First = malloc(sizeof(PlayListEntry)); Entry = First; } else { Entry->Next = malloc(sizeof(PlayListEntry)); Entry = Entry->Next; } Entry->Next = NULL; Entry->Name = malloc(strlen(DecodeUnicodeString(Files.ID_FullName))+1); sprintf(Entry->Name,"%s",DecodeUnicodeString(Files.ID_FullName)); /* converting Gammu drives to phone drives */ if (Entry->Name[0]=='a' || Entry->Name[0]=='A') { Entry->Name[0]='b'; } else if (Entry->Name[0]=='d' || Entry->Name[0]=='D') { Entry->Name[0]='a'; } Entry->NameUP = malloc(strlen(DecodeUnicodeString(Files.ID_FullName))+1); for (i = 0; i < strlen(DecodeUnicodeString(Files.ID_FullName)) + 1; i++) { Entry->NameUP[i] = tolower(Entry->Name[i]); } } } else { Names = (unsigned char *)realloc(Names,NamesPos+UnicodeLength(Files.ID_FullName)*2+2); CopyUnicodeString(Names+NamesPos,Files.ID_FullName); NamesPos+=UnicodeLength(Files.ID_FullName)*2+2; Names2 = (unsigned char *)realloc(Names2,NamesPos2+UnicodeLength(Files.Name)*2+2); CopyUnicodeString(Names2+NamesPos2,Files.Name); NamesPos2+=UnicodeLength(Files.Name)*2+2; } Start = FALSE; } if (First!=NULL) { /* sorting songs names */ Entry=First; while (Entry->Next!=NULL) { if (strcmp(Entry->NameUP,Entry->Next->NameUP)>0) { Pointer=Entry->Next->Name; Entry->Next->Name = Entry->Name; Entry->Name = Pointer; Pointer=Entry->Next->NameUP; Entry->Next->NameUP = Entry->NameUP; Entry->NameUP = Pointer; Entry=First; continue; } Entry=Entry->Next; } /* we checking, if file already exist.if yes, we look for another... */ i = 0; Files3.Buffer = NULL; while (1) { CopyUnicodeString(Files3.ID_FullName,IDFolder); CopyUnicodeString(Buffer2,Name); if (i!=0) { sprintf(Buffer, "%ld", (long)i); EncodeUnicode(Buffer2+UnicodeLength(Buffer2)*2,Buffer,strlen(Buffer)); } EncodeUnicode(Buffer2+UnicodeLength(Buffer2)*2,".m3u",4); Start = TRUE; Available = FALSE; while (1) { error = GSM_GetFolderListing(gsm,&Files3,Start); if (error == ERR_FOLDERPART) { printf("%s\n", _(" Problem with adding playlist")); break; } if (error == ERR_EMPTY) break; Print_Error(error); if (!Files3.Folder) { if (mywstrncasecmp(Buffer2,Files3.Name,-1)) { Available = TRUE; break; } } Start = FALSE; } if (!Available) break; i++; } /* preparing new playlist file date */ Files2.System = FALSE; Files2.Folder = FALSE; Files2.ReadOnly = FALSE; Files2.Hidden = FALSE; Files2.Protected = FALSE; Files2.ModifiedEmpty = FALSE; GSM_GetCurrentDateTime (&Files2.Modified); CopyUnicodeString(Files2.ID_FullName,IDFolder); CopyUnicodeString(Files2.Name,Buffer2); /* preparing new playlist file content */ Files2.Buffer=NULL; Files2.Buffer = (unsigned char *)realloc(Files2.Buffer,10); sprintf(Files2.Buffer,"#EXTM3U%c%c",13,10); Files2.Used = 9; Entry=First; while (Entry!=NULL) { Files2.Buffer = (unsigned char *)realloc(Files2.Buffer,Files2.Used+strlen(Entry->Name)+2+1); sprintf(Files2.Buffer+Files2.Used,"%s%c%c",Entry->Name,13,10); Files2.Used+=strlen(Entry->Name)+2; Entry=Entry->Next; } Files2.Used -= 2; for (i=0;i<Files2.Used;i++) { if (Files2.Buffer[i]=='/') Files2.Buffer[i]='\\'; } /* adding new playlist file */ sprintf(Buffer2, _("Writing file %s:"), DecodeUnicodeString(Files2.Name)); AddOneFile(&Files2, Buffer2, FALSE); /* cleaning buffers */ free(Files2.Buffer); Files2.Buffer=NULL; while (Entry!=NULL) { Entry=First; Prev=NULL; while (Entry->Next!=NULL) { Prev=Entry; Entry=Entry->Next; } free(Entry->Name); free(Entry->NameUP); free(Entry); Entry=NULL; if (Prev!=NULL) Prev->Next = NULL; } } /* going into subfolders */ if (NamesPos != 0) { i = 0; j = 0; while (i != NamesPos) { NokiaAddPlayLists2(Names+i,Names2+j,IDFolder); i+=UnicodeLength(Names+i)*2+2; j+=UnicodeLength(Names2+j)*2+2; } } free(Names); free(Names2); }
/** * We separate matching text (Start) to tokens and then try to find all * tokens in Buffer. We also accept tokens like PREF, CHARSET or ENCODING. * * Also it parses TYPE=* tokens, matching it to text types passed in Start * parameter. For example Start "TEL;FAX;VOICE" matches "TEL;TYPE=FAX,VOICE" * or "TEL;FAX;TYPE=VOICE" or "TEL;TYPE=FAX;TYPE=VOICE" and of course * "TEL;FAX;VOICE". * * When all tokens are matched we found matching line. */ gboolean ReadVCALText(char *Buffer, const char *Start, unsigned char *Value, const gboolean UTF8, GSM_EntryLocation *location) { char *line = NULL; char **tokens = NULL; char *charset = NULL; char *begin, *pos, *end, *end2; gboolean quoted_printable = FALSE; size_t numtokens, token; size_t i, j, len; gboolean found; gboolean ret = FALSE; /* Initialize output */ Value[0] = 0x00; Value[1] = 0x00; /* Count number of tokens */ len = strlen(Start); numtokens = 1; for (i = 0; i < len; i++) { if (Start[i] == ';') { numtokens++; } } /* Allocate memory */ line = strdup(Start); if (line == NULL) { dbgprintf(NULL, "Could not alloc!\n"); goto fail; } tokens = (char **)malloc(sizeof(char *) * numtokens); if (tokens == NULL) { dbgprintf(NULL, "Could not alloc!\n"); goto fail; } /* Parse Start to vCard tokens (separated by ;) */ token = 0; begin = line; for (i = 0; i < len; i++) { if (line[i] == ';') { tokens[token++] = begin; begin = line + i + 1; line[i] = 0; } } /* Store last token */ tokens[token] = begin; /* Compare first token, it must be in place */ pos = Buffer; len = strlen(tokens[0]); if (strncasecmp(pos, tokens[0], len) != 0) { goto fail; } /* Advance position */ pos += len; /* No need to check this token anymore */ tokens[0][0] = 0; /* Initialize location */ if (location != NULL) { *location = PBK_Location_Unknown; } /* Check remaining tokens */ while (*pos != ':') { if (*pos == ';') { pos++; } else { dbgprintf(NULL, "Could not parse! (stopped at string: %s)\n", pos); goto fail; } found = FALSE; for (token = 0; token < numtokens; token++) { len = strlen(tokens[token]); /* Skip already matched tokens */ if (len == 0) { continue; } if (strncasecmp(pos, tokens[token], len) == 0) { dbgprintf(NULL, "Found %s\n", tokens[token]); /* Advance position */ pos += len; /* We need to check one token less */ tokens[token][0] = 0; found = TRUE; break; } } if (!found) { if (strncasecmp(pos, "ENCODING=QUOTED-PRINTABLE", 25) == 0) { quoted_printable = TRUE; /* Advance position */ pos += 25; found = TRUE; } else if (strncasecmp(pos, "CHARSET=", 8) == 0) { /* Advance position */ pos += 8; /* Grab charset */ end = strchr(pos, ':'); end2 = strchr(pos, ';'); if (end == NULL && end2 == NULL) { dbgprintf(NULL, "Could not read charset!\n"); goto fail; } else if (end == NULL) { end = end2; } else if (end2 != NULL && end2 < end) { end = end2; } /* We basically want strndup, but it is not portable */ charset = strdup(pos); if (charset == NULL) { dbgprintf(NULL, "Could not alloc!\n"); goto fail; } charset[end - pos] = 0; pos = end; found = TRUE; } else if (strncasecmp(pos, "TZID=", 5) == 0) { /* @todo: We ignore time zone for now */ /* Advance position */ pos += 5; /* Go behind value */ end = strchr(pos, ':'); end2 = strchr(pos, ';'); if (end == NULL && end2 == NULL) { dbgprintf(NULL, "Could not read timezone!\n"); goto fail; } else if (end == NULL) { end = end2; } else if (end2 != NULL && end2 < end) { end = end2; } pos = end; found = TRUE; } else if (strncasecmp(pos, "TYPE=", 5) == 0) { /* We ignore TYPE= prefix */ pos += 5; /* Now process types, which should be comma separated */ while (*pos != ':' && *pos != ';') { found = FALSE; /* Go through tokens to match */ for (token = 0; token < numtokens; token++) { len = strlen(tokens[token]); /* Skip already matched tokens */ if (len == 0) { continue; } if (strncasecmp(pos, tokens[token], len) == 0) { dbgprintf(NULL, "Found %s\n", tokens[token]); /* Advance position */ pos += len; /* We need to check one token less */ tokens[token][0] = 0; found = TRUE; break; } } if (!found) { if (strncasecmp(pos, "PREF", 4) == 0) { /* We ignore pref token */ pos += 4; found = TRUE; } else if (strncasecmp(pos, "WORK", 4) == 0) { /* We ignore work token */ pos += 4; found = TRUE; if (location != NULL) { *location = PBK_Location_Work; } } else if (strncasecmp(pos, "HOME", 4) == 0) { /* We ignore home token */ pos += 4; found = TRUE; if (location != NULL) { *location = PBK_Location_Home; } } else { dbgprintf(NULL, "%s not found! (%s)\n", Start, pos); goto fail; } } if (*pos == ';' || *pos == ':') { dbgprintf(NULL, "End of TYPE= string\n"); break; } else if (*pos == ',') { /* Advance past separator */ pos++; } else { dbgprintf(NULL, "Could not parse TYPE=! (stopped at string: %s)\n", pos); goto fail; } } } else if (strncasecmp(pos, "PREF", 4) == 0) { /* We ignore pref token */ pos += 4; found = TRUE; } else if (location && strncasecmp(pos, "WORK", 4) == 0) { /* We ignore pref token */ pos += 4; found = TRUE; *location = PBK_Location_Work; } else if (location && strncasecmp(pos, "HOME", 4) == 0) { /* We ignore pref token */ pos += 4; found = TRUE; *location = PBK_Location_Home; } if (!found) { dbgprintf(NULL, "%s not found!\n", Start); goto fail; } } } /* Skip : */ pos++; /* Length of rest */ len = strlen(pos); /* Did we match all our tokens? */ for (token = 0; token < numtokens; token++) { if (strlen(tokens[token]) > 0) { dbgprintf(NULL, "All tokens did not match!\n"); goto fail; } } /* Decode the text */ if (charset == NULL) { if (quoted_printable) { if (UTF8) { DecodeUTF8QuotedPrintable(Value, pos, len); } else { DecodeISO88591QuotedPrintable(Value, pos, len); } } else { if (UTF8) { DecodeUTF8(Value, pos, len); } else { DecodeISO88591(Value, pos, len); } } } else { if (strcasecmp(charset, "UTF-8") == 0|| strcasecmp(charset, "\"UTF-8\"") == 0 ) { if (quoted_printable) { DecodeUTF8QuotedPrintable(Value, pos, len); } else { DecodeUTF8(Value, pos, len); } } else if (strcasecmp(charset, "UTF-7") == 0|| strcasecmp(charset, "\"UTF-7\"") == 0 ) { if (quoted_printable) { dbgprintf(NULL, "Unsupported charset: %s\n", charset); goto fail; } else { DecodeUTF7(Value, pos, len); } } else { dbgprintf(NULL, "Unsupported charset: %s\n", charset); goto fail; } } /* Postprocess escaped chars */ len = UnicodeLength(Value); for (i = 0; i < len; i++) { if (Value[(2 * i)] == 0 && Value[(2 * i) + 1] == '\\') { j = i + 1; if (Value[(2 * j)] == 0 && ( Value[(2 * j) + 1] == 'n' || Value[(2 * j) + 1] == 'N') ) { Value[(2 * i) + 1] = '\n'; } else if (Value[(2 * j)] == 0 && ( Value[(2 * j) + 1] == 'r' || Value[(2 * j) + 1] == 'R') ) { Value[(2 * i) + 1] = '\r'; } else if (Value[(2 * j)] == 0 && Value[(2 * j) + 1] == '\\') { Value[(2 * i) + 1] = '\\'; } else if (Value[(2 * j)] == 0 && Value[(2 * j) + 1] == ';') { Value[(2 * i) + 1] = ';'; } else if (Value[(2 * j)] == 0 && Value[(2 * j) + 1] == ',') { Value[(2 * i) + 1] = ','; } else { /* We ignore unknown for now */ continue; } /* Shift the string */ memmove(Value + (2 * j), Value + (2 * j) + 2, 2 * (len + 1 - j)); len--; } } ret = TRUE; dbgprintf(NULL, "ReadVCalText(%s) is \"%s\"\n", Start, DecodeUnicodeConsole(Value)); fail: free(line); line=NULL; free(tokens); tokens=NULL; free(charset); charset=NULL; return ret; }