// vcard34conv-v4conv.cpp - vCard34Conv Object vCard4 conversion subroutines. // // (c) 2012-2015 Xestia Software Development. // // This file is part of Xestia Address Book. // // Xestia Address Book is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by the // Free Software Foundation, version 3 of the license. // // Xestia Address Book is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with Xestia Address Book. If not, see #include "vcard34conv.h" #include "vcard.h" #include "../version.h" #include "../common/textprocessing.h" #include #include #include #include bool vCard34Conv::ConvertToV4(wxString *wxSData, vCard *vCardOut){ // Convert a vCard 3.0 format into the vCard 4.0 format. std::map ContactFileLines; std::map ContactFileProcessed; std::map ContactFileProcessedWorking; std::map::iterator striter; std::map::iterator iterbool; std::map::iterator iterboolsub; wxString ContactLineRec; // Process the received data. wxStringTokenizer wSTContactFileLines(*wxSData, wxT("\r\n")); int ContactLineSeek = 0; while (wSTContactFileLines.HasMoreTokens() == TRUE){ ContactLineRec = wSTContactFileLines.GetNextToken(); ContactFileLines.insert(std::make_pair(ContactLineSeek, ContactLineRec)); ContactFileProcessed.insert(std::make_pair(ContactLineSeek, FALSE)); ContactLineSeek++; } bool QuoteMode = FALSE; bool PropertyFind = TRUE; bool ExtraLineSeek = TRUE; bool ExtraLineSeekSub = TRUE; bool FNFirst = FALSE; bool NicknameFirst = FALSE; bool TitleFirst = FALSE; bool OrganisationFirst = FALSE; bool NoteFirst = FALSE; bool PhotoFirst = FALSE; bool FoundData = FALSE; wxString wxSProperty; wxString wxSPropertyVCARD4; wxString wxSPropertySeg1; wxString wxSPropertySeg2; wxString wxSPropertyNextLine; wxString ContactLine; wxString ContactLineSub; wxString PropertyName; wxString PropertyValue; wxString PropertyDataStr; size_t ContactLineLen = 0; size_t ContactLineSubLen = 0; int QuoteBreakPoint = 0; size_t intPrevValueSub = 0; std::map PropertyData; std::map PropertyLock; std::map TempPropertyData; std::map TempPropertyLock; std::map TempSplitPoints; std::map TempSplitLength; std::map::iterator SLiter; wxString PropertFindSub; wxString wxSPropertySub; wxString wxSPropertySeg1Sub; wxString wxSPropertySeg2Sub; wxString wxSPropertyValues; wxString wxSPropertyData; wxString wxSPropertyNameConv; wxString wxSPropertyXVCard4Value; wxString ItemProcString; bool XVCard4Value = FALSE; bool VCard3Value = FALSE; wxString strVer; // Setup the version string. strVer.Append(wxT("-//Xestia//Address Book Version ")); strVer.Append(wxT(XSDAB_VERSION)); strVer.Append(wxT("//KW")); vCardOut->AddRaw(wxT("BEGIN"), wxT("VCARD")); vCardOut->AddRaw(wxT("VERSION"), wxT("4.0")); vCardOut->AddRaw(wxT("PRODID"), strVer); // FN // NICKNAME // TITLE // ORG // NOTE // PHOTO // Process the properties which have X-FIRST. // Clone the ContactFileProcessed into ContactFileProcessedWorking. ContactFileProcessedWorking.insert(ContactFileProcessed.begin(), ContactFileProcessed.end()); for (std::map::iterator iter = ContactFileLines.begin(); iter != ContactFileLines.end(); ++iter){ ExtraLineSeek = TRUE; iterbool = ContactFileProcessed.find(iter->first); ContactLine = iter->second; // Ignore certain variables as they are not needed. if (ContactLine == wxT("BEGIN:VCARD") || ContactLine == wxT("END:VCARD") || ContactLine.Mid(0, 8) == wxT("VERSION:") || ContactLine.Mid(0, 7) == wxT("PRODID:") || ContactLine.Mid(0, 5) == wxT("X-AIM") || ContactLine.Mid(0, 5) == wxT("X-MSN") || ContactLine.Mid(0, 5) == wxT("X-ICQ") || ContactLine.Mid(0, 10) == wxT("X-GADUGADU") || ContactLine.Mid(0, 7) == wxT("X-YAHOO") || ContactLine.Mid(0, 7) == wxT("X-SKYPE") || ContactLine.Mid(0, 8) == wxT("X-JABBER") || ContactLine.Mid(0, 4) == wxT("REV:")){ iterbool->second = TRUE; continue; } if (iterbool->second == TRUE){ continue; } if (ContactLine.Mid(0, 1) == wxT(" ") || ContactLine.Mid(0, 1) == wxT("\t")){ continue; } if (ContactLine.Mid(0, 4) == wxT("item")){ // Line is a itemn... so ignore. continue; } std::map DataLineProcess; std::map::iterator DLSLiter; std::map DataLineProcessOriginal; int DataLineSeek = 0; int DataLineSeekOrig = 0; std::map::iterator itersub = iter; DataLineProcessOriginal.insert(std::make_pair(DataLineSeekOrig, iterbool->first)); DataLineSeekOrig++; while (ExtraLineSeek == TRUE){ // Check if there is extra data on the next line // (indicated by space or tab at the start) and add data. itersub++; if (itersub == ContactFileLines.end()){ break; } iterboolsub = ContactFileProcessed.find(itersub->first); if (iterboolsub == ContactFileProcessed.end()){ break; } if (iterboolsub->second == TRUE){ continue; } wxSPropertyNextLine = itersub->second; if (wxSPropertyNextLine.Mid(0, 1) == wxT(" ") || wxSPropertyNextLine.Mid(0, 1) == wxT("\t")){ wxSPropertyNextLine.Remove(0, 1); ContactLine.Append(wxSPropertyNextLine); DataLineProcessOriginal.insert(std::make_pair(DataLineSeekOrig, iterboolsub->first)); DataLineSeekOrig++; } else { ExtraLineSeek = FALSE; } } ContactLineLen = ContactLine.Len(); for (int i = 0; i <= ContactLineLen; i++){ if ((ContactLine.Mid(i, 1) == wxT(";") || ContactLine.Mid(i, 1) == wxT(":")) && PropertyFind == TRUE){ PropertyFind = FALSE; } else if (PropertyFind == TRUE){ wxSProperty.Append(ContactLine.Mid(i, 1)); } if (ContactLine.Mid(i, 1) == wxT("\"")){ if (QuoteMode == TRUE){ QuoteMode = FALSE; } else { QuoteMode = TRUE; } } if (ContactLine.Mid(i, 1) == wxT(":") && ContactLine.Mid((i - 1), 1) != wxT("\\") && QuoteMode == FALSE){ QuoteBreakPoint = i; break; } } wxSPropertySeg1 = ContactLine.Mid(0, QuoteBreakPoint); wxSPropertySeg2 = ContactLine.Mid((QuoteBreakPoint + 1)); wxStringTokenizer wxSPropertySegSplit(wxSPropertySeg1, wxT(";")); wxSProperty = wxSPropertySegSplit.GetNextToken(); // Check what type of property it is. FoundData = FALSE; if ((wxSProperty == wxT("PHOTO") && PhotoFirst == FALSE) || (wxSProperty == wxT("NICKNAME") && NicknameFirst == FALSE) || (wxSProperty == wxT("TITLE") && TitleFirst == FALSE) || (wxSProperty == wxT("FN") && FNFirst == FALSE) || (wxSProperty == wxT("ORG") && OrganisationFirst == FALSE) || (wxSProperty == wxT("NOTE") && NoteFirst == FALSE)){ wxSPropertyVCARD4 = wxT("X-VCARD4-") + wxSProperty; intPrevValueSub = (wxSPropertyVCARD4.Len() + 2); for (std::map::iterator itersub = ContactFileLines.begin(); itersub != ContactFileLines.end(); ++itersub){ ContactLineSub = itersub->second; ExtraLineSeekSub = TRUE; iterboolsub = ContactFileProcessed.find(itersub->first); // Ignore certain variables as they are not needed. if (ContactLineSub == wxT("BEGIN:VCARD") || ContactLineSub == wxT("END:VCARD") || ContactLineSub.Mid(0, 8) == wxT("VERSION:") || ContactLineSub.Mid(0, 7) == wxT("PRODID:") || ContactLineSub.Mid(0, 5) == wxT("X-AIM") || ContactLineSub.Mid(0, 5) == wxT("X-MSN") || ContactLineSub.Mid(0, 5) == wxT("X-ICQ") || ContactLineSub.Mid(0, 10) == wxT("X-GADUGADU") || ContactLineSub.Mid(0, 7) == wxT("X-YAHOO") || ContactLineSub.Mid(0, 7) == wxT("X-SKYPE") || ContactLineSub.Mid(0, 8) == wxT("X-JABBER") || ContactLineSub.Mid(0, 4) == wxT("REV:")){ iterboolsub->second = TRUE; continue; } if (iterboolsub->second == TRUE){ continue; } if (ContactLineSub.Mid(0, 1) == wxT(" ") || ContactLineSub.Mid(0, 1) == wxT("\t")){ continue; } if (ContactLineSub.Mid(0, 4) == wxT("item")){ // Line is a itemn... so ignore. continue; } DataLineProcess.insert(std::make_pair(DataLineSeek, itersub->first)); DataLineSeek++; while (ExtraLineSeekSub == TRUE){ if (itersub == ContactFileLines.end()){ ExtraLineSeekSub = FALSE; continue; } else { itersub++; } iterboolsub = ContactFileProcessedWorking.find(itersub->first); wxSPropertyNextLine = itersub->second; if (wxSPropertyNextLine.Mid(0, 1) == wxT(" ") || wxSPropertyNextLine.Mid(0, 1) == wxT("\t")){ wxSPropertyNextLine.Remove(0, 1); ContactLineSub.Append(wxSPropertyNextLine); DataLineProcess.insert(std::make_pair(DataLineSeek, itersub->first)); DataLineSeek++; } else { itersub--; ExtraLineSeekSub = FALSE; } } ContactLineSubLen = ContactLineSub.Len(); PropertyFind = TRUE; wxSPropertySub.clear(); for (int i = 0; i <= ContactLineSubLen; i++){ if ((ContactLineSub.Mid(i, 1) == wxT(";") || ContactLineSub.Mid(i, 1) == wxT(":")) && PropertyFind == TRUE){ PropertyFind = FALSE; } else if (PropertyFind == TRUE){ wxSPropertySub.Append(ContactLineSub.Mid(i, 1)); } if (ContactLineSub.Mid(i, 1) == wxT("\"")){ if (QuoteMode == TRUE){ QuoteMode = FALSE; } else { QuoteMode = TRUE; } } if (ContactLineSub.Mid(i, 1) == wxT(":") && ContactLineSub.Mid((i - 1), 1) != wxT("\\") && QuoteMode == FALSE){ QuoteBreakPoint = i; break; } } if (wxSPropertySub != wxSPropertyVCARD4){ wxSPropertySub.clear(); DataLineSeek = 0; DataLineProcess.clear(); continue; } wxSPropertySeg1Sub = ContactLineSub.Mid(0, QuoteBreakPoint); wxSPropertySeg2Sub = ContactLineSub.Mid((QuoteBreakPoint + 1)); // Split the property name data. // Strip the X-VCARD4- from the variable. wxString wxSPropertyChopped = wxSPropertySeg1Sub.Mid(9); intPrevValueSub = (wxSProperty.Len() + 2); SplitValuesData(&wxSPropertyChopped, &TempSplitPoints, &TempSplitLength, (int)intPrevValueSub, &TempPropertyData); // Process the splitted data into temporary property data. // Look for certain property names and the X-FIRST // property name. bool ProcessData = FALSE; // Check for X-FIRST. for (std::map::iterator xfiter = TempPropertyData.begin(); xfiter != TempPropertyData.end(); ++xfiter){ PropertyName = xfiter->first; PropertyValue = xfiter->second; if (PropertyName == wxT("X-FIRST") && PropertyValue == wxT("TRUE")){ ProcessData = TRUE; if (wxSProperty == wxT("PHOTO")){ PhotoFirst = TRUE; } else if (wxSProperty == wxT("NICKNAME")){ NicknameFirst = TRUE; } else if (wxSProperty == wxT("TITLE")){ TitleFirst = TRUE; } else if (wxSProperty == wxT("FN")){ FNFirst = TRUE; } else if (wxSProperty == wxT("ORG")){ OrganisationFirst = TRUE; } else if (wxSProperty == wxT("NOTE")){ NoteFirst = TRUE; } break; } } if (ProcessData == FALSE){ DataLineProcess.clear(); DataLineSeek = 0; TempPropertyData.clear(); } else { for (std::map::iterator xfiter = TempPropertyData.begin(); xfiter != TempPropertyData.end(); ++xfiter){ PropertyName = xfiter->first; PropertyValue = xfiter->second; if (PropertyName == wxT("X-FIRST")){ continue; } PropertyData.insert(std::make_pair(PropertyName, PropertyValue)); PropertyLock.insert(std::make_pair(PropertyName, FALSE)); } // Mark all lines as processed. for (std::map::iterator dpiter = DataLineProcess.begin(); dpiter != DataLineProcess.end(); ++dpiter){ DLSLiter = ContactFileProcessed.find(dpiter->second); DLSLiter->second = TRUE; } for (std::map::iterator dpoiter = DataLineProcessOriginal.begin(); dpoiter != DataLineProcessOriginal.end(); ++dpoiter){ DLSLiter = ContactFileProcessed.find(dpoiter->second); DLSLiter->second = TRUE; } DataLineProcess.clear(); DataLineProcessOriginal.clear(); DataLineSeek = 0; DataLineSeekOrig = 0; TempSplitPoints.clear(); TempSplitLength.clear(); TempPropertyData.clear(); FoundData = TRUE; break; } } } else { wxSProperty.clear(); wxSPropertySub.Clear(); wxSPropertySeg1.Clear(); wxSPropertySeg2.Clear(); wxSPropertySeg1Sub.Clear(); wxSPropertySeg2Sub.Clear(); wxSPropertyValues.Clear(); wxSPropertyData.Clear(); wxSPropertyXVCard4Value.Clear(); wxSPropertyNameConv.Clear(); PropertyData.clear(); PropertyLock.clear(); ContactLine.clear(); ContactLineSub.clear(); DataLineProcess.clear(); DataLineProcessOriginal.clear(); TempSplitPoints.clear(); TempSplitLength.clear(); wxSPropertyVCARD4.clear(); DataLineSeek = 0; DataLineSeekOrig = 0; XVCard4Value = FALSE; VCard3Value = FALSE; } if (FoundData == FALSE){ wxSProperty.clear(); wxSPropertySub.Clear(); wxSPropertySeg1.Clear(); wxSPropertySeg2.Clear(); wxSPropertySeg1Sub.Clear(); wxSPropertySeg2Sub.Clear(); wxSPropertyValues.Clear(); wxSPropertyData.Clear(); wxSPropertyXVCard4Value.Clear(); wxSPropertyNameConv.Clear(); PropertyData.clear(); PropertyLock.clear(); ContactLine.clear(); ContactLineSub.clear(); DataLineProcess.clear(); DataLineProcessOriginal.clear(); TempSplitPoints.clear(); TempSplitLength.clear(); wxSPropertyVCARD4.clear(); DataLineSeek = 0; DataLineSeekOrig = 0; XVCard4Value = FALSE; VCard3Value = FALSE; } ConvertV4PropertyProc(&wxSProperty, &wxSPropertySeg1, &wxSPropertySeg2, &wxSPropertyValues, &wxSPropertyData, &wxSPropertyXVCard4Value, &wxSPropertyNameConv, &PropertyData, &PropertyLock, FALSE, &VCard3Value, &XVCard4Value); wxString FinalPropertyData; FinalPropertyData.Append(wxSPropertyNameConv); for (std::map::iterator striter = PropertyData.begin(); striter != PropertyData.end(); ++striter){ FinalPropertyData.Append(wxT(";")); FinalPropertyData.Append(striter->first); FinalPropertyData.Append(wxT("=")); FinalPropertyData.Append(striter->second); } wxString FinalPropValue; if (wxSPropertyXVCard4Value.IsEmpty()){ FinalPropValue = wxSPropertyData; } else { if (wxSPropertyXVCard4Value != wxSPropertyData){ FinalPropValue = wxSPropertyXVCard4Value; } } if (FinalPropertyData.IsEmpty() && FinalPropValue.IsEmpty()){ continue; } vCardOut->AddRaw(FinalPropertyData, FinalPropValue); wxSProperty.clear(); wxSPropertySub.Clear(); wxSPropertySeg1.Clear(); wxSPropertySeg2.Clear(); wxSPropertySeg1Sub.Clear(); wxSPropertySeg2Sub.Clear(); wxSPropertyValues.Clear(); wxSPropertyData.Clear(); wxSPropertyXVCard4Value.Clear(); wxSPropertyNameConv.Clear(); PropertyData.clear(); PropertyLock.clear(); ContactLine.clear(); ContactLineSub.clear(); DataLineProcess.clear(); DataLineProcessOriginal.clear(); wxSPropertyVCARD4.clear(); DataLineSeek = 0; DataLineSeekOrig = 0; XVCard4Value = FALSE; VCard3Value = FALSE; } // Process the non-itemn values. for (std::map::iterator iter = ContactFileLines.begin(); iter != ContactFileLines.end(); ++iter){ ExtraLineSeek = TRUE; iterbool = ContactFileProcessed.find(iter->first); ContactLine = iter->second; // Ignore certain variables as they are not needed. if (ContactLine == wxT("BEGIN:VCARD") || ContactLine == wxT("END:VCARD") || ContactLine.Mid(0, 8) == wxT("VERSION:") || ContactLine.Mid(0, 7) == wxT("PRODID:") || ContactLine.Mid(0, 5) == wxT("X-AIM") || ContactLine.Mid(0, 5) == wxT("X-MSN") || ContactLine.Mid(0, 5) == wxT("X-ICQ") || ContactLine.Mid(0, 10) == wxT("X-GADUGADU") || ContactLine.Mid(0, 7) == wxT("X-YAHOO") || ContactLine.Mid(0, 7) == wxT("X-SKYPE") || ContactLine.Mid(0, 8) == wxT("X-JABBER") || ContactLine.Mid(0, 4) == wxT("REV:")){ iterbool->second = TRUE; continue; } if (iterbool->second == TRUE){ continue; } if (ContactLine.Mid(0, 1) == wxT(" ") || ContactLine.Mid(0, 1) == wxT("\t")){ continue; } if (ContactLine.Mid(0, 4) == wxT("item")){ // Line is a itemn... so ignore. continue; } std::map::iterator itersub = iter; while (ExtraLineSeek == TRUE){ // Check if there is extra data on the next line // (indicated by space or tab at the start) and add data. if (itersub == ContactFileLines.end()){ ExtraLineSeekSub = FALSE; continue; } else { itersub++; } iterboolsub = ContactFileProcessedWorking.find(itersub->first); if (iterboolsub == ContactFileProcessedWorking.end()){ break; } if (iterboolsub->second == TRUE){ continue; } if (itersub == ContactFileLines.end()){ break; } wxSPropertyNextLine = itersub->second; if (wxSPropertyNextLine.Mid(0, 1) == wxT(" ") || wxSPropertyNextLine.Mid(0, 1) == wxT("\t")){ wxSPropertyNextLine.Remove(0, 1); ContactLine.Append(wxSPropertyNextLine); iterboolsub->second = TRUE; } else { ExtraLineSeek = FALSE; } } ContactLineLen = ContactLine.Len(); for (int i = 0; i <= ContactLineLen; i++){ if ((ContactLine.Mid(i, 1) == wxT(";") || ContactLine.Mid(i, 1) == wxT(":")) && PropertyFind == TRUE){ PropertyFind = FALSE; } else if (PropertyFind == TRUE){ wxSProperty.Append(ContactLine.Mid(i, 1)); } if (ContactLine.Mid(i, 1) == wxT("\"")){ if (QuoteMode == TRUE){ QuoteMode = FALSE; } else { QuoteMode = TRUE; } } if (ContactLine.Mid(i, 1) == wxT(":") && ContactLine.Mid((i - 1), 1) != wxT("\\") && QuoteMode == FALSE){ QuoteBreakPoint = i; break; } } wxSPropertySeg1 = ContactLine.Mid(0, QuoteBreakPoint); wxSPropertySeg2 = ContactLine.Mid((QuoteBreakPoint + 1)); wxStringTokenizer wxSPropertySegSplit(wxSPropertySeg1, wxT(";")); wxSProperty = wxSPropertySegSplit.GetNextToken(); std::map DataLineProcess; std::map::iterator DLSLiter; // Look for the X-VCARD4-(variablename) equivilant. wxSPropertyVCARD4 = wxT("X-VCARD4-") + wxSProperty; // Sort out remainder of the types. ConvertV4PropertyProc(&wxSProperty, &wxSPropertySeg1, &wxSPropertySeg2, &wxSPropertyValues, &wxSPropertyData, &wxSPropertyXVCard4Value, &wxSPropertyNameConv, &PropertyData, &PropertyLock, FALSE, &VCard3Value, &XVCard4Value); wxString FinalPropertyData; FinalPropertyData.Append(wxSPropertyNameConv); for (std::map::iterator striter = PropertyData.begin(); striter != PropertyData.end(); ++striter){ FinalPropertyData.Append(wxT(";")); FinalPropertyData.Append(striter->first); FinalPropertyData.Append(wxT("=")); FinalPropertyData.Append(striter->second); } wxString FinalPropValue; if (wxSPropertyXVCard4Value.IsEmpty()){ FinalPropValue = wxSPropertyData; } else { if (wxSPropertyXVCard4Value != wxSPropertyData){ FinalPropValue = wxSPropertyXVCard4Value; } } vCardOut->AddRaw(FinalPropertyData, FinalPropValue); wxSProperty.clear(); wxSPropertySub.Clear(); wxSPropertySeg1.Clear(); wxSPropertySeg2.Clear(); wxSPropertyValues.Clear(); wxSPropertyData.Clear(); wxSPropertyXVCard4Value.Clear(); wxSPropertyNameConv.Clear(); PropertyData.clear(); PropertyLock.clear(); ContactLine.clear(); XVCard4Value = FALSE; VCard3Value = FALSE; } size_t ItemStringSeekLen = 0; std::map NumberedName; std::map NumberedData; std::map NumberedPropValues; std::map NumberedPropOldValue; std::map UnNumberedName; std::map UnNumberedData; std::map UnNumberedPropValues; std::map UnNumberedPropOldValue; // Part 1: Get the itemn number. std::map::iterator iterboolsecsub; std::map::iterator itersub; std::map TempData; PropertyData.clear(); PropertyLock.clear(); wxString ItemString; wxString ItemStringSeek; wxString ItemPropName; ContactLineSeek = 0; ContactLineSub.clear(); ExtraLineSeekSub = 0; wxString wxSPropertyNextLineSub; ContactLineSubLen = 0; int ItemIndex = 0; PropertFindSub.clear(); wxSPropertySub.clear(); wxSPropertySeg1Sub.clear(); wxSPropertySeg2Sub.clear(); wxSPropertyValues.clear(); wxSPropertyData.clear(); wxSPropertyNameConv.clear(); wxSPropertyXVCard4Value.clear(); ItemProcString.clear(); XVCard4Value = FALSE; VCard3Value = FALSE; std::map ItemMapIndex; // Look for item in the initial line, process into a proper line then // look for other lines with the same item association. for (std::map::iterator iter = ContactFileLines.begin(); iter != ContactFileLines.end(); ++iter){ ExtraLineSeek = TRUE; iterbool = ContactFileProcessed.find(iter->first); if (iterbool->second == TRUE){ continue; } ContactLine = iter->second; if (ContactLine.Mid(0, 1) == wxT(" ") || ContactLine.Mid(0, 1) == wxT("\t")){ continue; } if (ContactLine.Mid(0, 4) != wxT("item")){ continue; } // Get Item data. std::map::iterator itersub = iter; while (ExtraLineSeek == TRUE){ // Check if there is extra data on the next line // (indicated by space or tab at the start) and add data. itersub++; iterboolsub = ContactFileProcessed.find(itersub->first); if (iterboolsub == ContactFileProcessed.end()){ break; } if (iterboolsub->second == TRUE){ continue; } if (itersub == ContactFileLines.end()){ break; } wxSPropertyNextLine = itersub->second; if (wxSPropertyNextLine.Mid(0, 1) == wxT(" ") || wxSPropertyNextLine.Mid(0, 1) == wxT("\t")){ wxSPropertyNextLine.Remove(0, 1); ContactLine.Append(wxSPropertyNextLine); iterboolsub->second = TRUE; } else { ExtraLineSeek = FALSE; } } ContactLineLen = ContactLine.Len(); for (int i = 0; i <= ContactLineLen; i++){ if ((ContactLine.Mid(i, 1) == wxT(";") || ContactLine.Mid(i, 1) == wxT(":")) && PropertyFind == TRUE){ PropertyFind = FALSE; } else if (PropertyFind == TRUE){ wxSProperty.Append(ContactLine.Mid(i, 1)); } if (ContactLine.Mid(i, 1) == wxT("\"")){ if (QuoteMode == TRUE){ QuoteMode = FALSE; } else { QuoteMode = TRUE; } } if (ContactLine.Mid(i, 1) == wxT(":") && ContactLine.Mid((i - 1), 1) != wxT("\\") && QuoteMode == FALSE){ QuoteBreakPoint = i; break; } } wxSPropertySeg1 = ContactLine.Mid(0, QuoteBreakPoint); wxSPropertySeg2 = ContactLine.Mid((QuoteBreakPoint + 1)); // Go through the lines and collect the lines like itemn. std::map *ItemListData; ItemListData = new std::map; wxStringTokenizer ItemData(wxSPropertySeg1, wxT(".")); ItemString = ItemData.GetNextToken(); ItemStringSeek = wxT("item") + ItemString.Mid(4); wxStringTokenizer ItemPropSplit(ItemData.GetNextToken(), wxT(";")); ItemPropName = ItemPropSplit.GetNextToken(); ItemStringSeekLen = ItemStringSeek.Len(); ItemIndex = 0; for (std::map::iterator itersec = ContactFileLines.begin(); itersec != ContactFileLines.end(); ++itersec){ ExtraLineSeek = TRUE; iterboolsub = ContactFileProcessed.find(itersec->first); if (iterboolsub->second == TRUE){ continue; } ContactLineSub = itersec->second; wxStringTokenizer ItemProcData(ContactLineSub, wxT(".")); ItemProcString = ItemData.GetNextToken(); if (ItemStringSeek != ContactLineSub.Mid(0, ItemStringSeekLen)){ continue; } ItemIndex++; ItemListData->insert(std::make_pair(ItemIndex, ContactLineSub)); iterboolsub->second = TRUE; } ItemListData->insert(std::make_pair(ItemIndex, ContactLineSub)); ItemMapIndex.insert(std::make_pair(ItemStringSeek, ItemListData)); } // Process each itemn set. for (std::map::iterator iter = ItemMapIndex.begin(); iter != ItemMapIndex.end(); ++iter){ std::map *ItemDataPtr; ItemDataPtr = (std::map*)iter->second; for (std::map::iterator itersub = ItemDataPtr->begin(); itersub != ItemDataPtr->end(); ++itersub){ ContactLine = itersub->second; ContactLineLen = ContactLine.Len(); for (int i = 0; i <= ContactLineLen; i++){ if ((ContactLine.Mid(i, 1) == wxT(";") || ContactLine.Mid(i, 1) == wxT(":")) && PropertyFind == TRUE){ PropertyFind = FALSE; } else if (PropertyFind == TRUE){ wxSProperty.Append(ContactLine.Mid(i, 1)); } if (ContactLine.Mid(i, 1) == wxT("\"")){ if (QuoteMode == TRUE){ QuoteMode = FALSE; } else { QuoteMode = TRUE; } } if (ContactLine.Mid(i, 1) == wxT(":") && ContactLine.Mid((i - 1), 1) != wxT("\\") && QuoteMode == FALSE){ QuoteBreakPoint = i; break; } } wxSPropertySeg1Sub = ContactLine.Mid(0, QuoteBreakPoint); wxSPropertySeg2Sub = ContactLine.Mid((QuoteBreakPoint + 1)); wxStringTokenizer wxSPropertySegSplit(wxSPropertySeg1Sub, wxT(";")); wxSProperty = wxSPropertySegSplit.GetNextToken(); // Sort out remainder of the types. // Skip certain X-* IM variables as they are processed via // IMPP. if (wxSProperty == wxT("X-AIM") || wxSProperty == wxT("X-MSN") || wxSProperty == wxT("X-ICQ") || wxSProperty == wxT("X-GADUGADU") || wxSProperty == wxT("X-YAHOO") || wxSProperty == wxT("X-SKYPE") || wxSProperty == wxT("X-JABBER")){ wxSProperty.clear(); wxSPropertySub.Clear(); wxSPropertySeg1.Clear(); wxSPropertySeg2.Clear(); wxSPropertyValues.Clear(); wxSPropertyData.Clear(); wxSPropertyXVCard4Value.Clear(); wxSPropertyNameConv.Clear(); PropertyData.clear(); PropertyLock.clear(); ContactLine.clear(); XVCard4Value = FALSE; VCard3Value = FALSE; continue; } ConvertV4PropertyProc(&wxSProperty, &wxSPropertySeg1Sub, &wxSPropertySeg2Sub, &wxSPropertyValues, &wxSPropertyData, &wxSPropertyXVCard4Value, &wxSPropertyNameConv, &PropertyData, &PropertyLock, TRUE, &VCard3Value, &XVCard4Value); } if (wxSPropertyNameConv.IsEmpty()){ wxSProperty.clear(); wxSPropertySub.Clear(); wxSPropertySeg1.Clear(); wxSPropertySeg2.Clear(); wxSPropertyValues.Clear(); wxSPropertyData.Clear(); wxSPropertyXVCard4Value.Clear(); wxSPropertyNameConv.Clear(); PropertyData.clear(); PropertyLock.clear(); ContactLine.clear(); XVCard4Value = FALSE; VCard3Value = FALSE; continue; } wxString FinalPropertyData; FinalPropertyData.Append(wxSPropertyNameConv); for (std::map::iterator striter = PropertyData.begin(); striter != PropertyData.end(); ++striter){ FinalPropertyData.Append(wxT(";")); FinalPropertyData.Append(striter->first); FinalPropertyData.Append(wxT("=")); FinalPropertyData.Append(striter->second); } wxString FinalPropValue; if (wxSPropertyXVCard4Value.IsEmpty()){ FinalPropValue = wxSPropertyData; } else { if (wxSPropertyXVCard4Value != wxSPropertyData){ FinalPropValue = wxSPropertyData; } else { FinalPropValue = wxSPropertyXVCard4Value; } } vCardOut->AddRaw(FinalPropertyData, FinalPropValue); wxSProperty.clear(); wxSPropertySub.Clear(); wxSPropertySeg1Sub.Clear(); wxSPropertySeg2Sub.Clear(); wxSPropertyValues.Clear(); wxSPropertyData.Clear(); wxSPropertyXVCard4Value.Clear(); wxSPropertyNameConv.Clear(); FinalPropertyData.clear(); FinalPropValue.clear(); PropertyData.clear(); PropertyLock.clear(); ContactLine.clear(); XVCard4Value = FALSE; VCard3Value = FALSE; TempData.clear(); } // Delete data. std::map *ItemEraseData; for (std::map::iterator iter = ItemMapIndex.begin(); iter != ItemMapIndex.end(); ++iter){ ItemEraseData = (std::map*)iter->second; delete ItemEraseData; ItemEraseData = NULL; } ItemMapIndex.clear(); vCardOut->AddRaw(wxT("END"), wxT("VCARD")); return TRUE; }