Пример #1
0
void ContactList::compareWith(ContactList &pairList)
{
    for (int i=0; i<pairList.count(); i++)
        pairList[i].pairState = ContactItem::PairNotFound;
    for (int i=0; i<count(); i++) {
        ContactItem& item = (*this)[i];
        item.pairState = ContactItem::PairNotFound;
        item.pairItem = 0;
        // At first, search complete matching
        for(int j=0; j<pairList.count(); j++) {
            ContactItem& candidate = pairList[j];
            if (item.identicalTo(candidate)) {
                item.pairState = ContactItem::PairIdentical;
                item.pairItem = &candidate;
                item.pairIndex = j;
                candidate.pairItem = &item;
                candidate.pairState = ContactItem::PairIdentical;
                candidate.pairIndex = i;
                break;
            }
        }
        // If no identical records, search similar
        if (item.pairState==ContactItem::PairNotFound)
            for (int j=1; j<=MAX_COMPARE_PRIORITY_LEVEL; j++) {
                bool pairFound = false;
                for(int k=0; k<pairList.count(); k++) {
                    ContactItem& candidate = pairList[k];
                    if (item.similarTo(candidate, j)) {
                        pairFound = true;
                        item.pairState = ContactItem::PairSimilar;
                        item.pairItem = &candidate;
                        item.pairIndex = k;
                        candidate.pairItem = &item;
                        candidate.pairState = ContactItem::PairSimilar;
                        candidate.pairIndex = i;
                        break;
                    }
                }
                if (pairFound) break;
            }
    }
}
Пример #2
0
bool UDXFile::exportRecords(const QString &url, ContactList &list)
{
    QDomDocument::clear();
    QDomElement root = createElement("DataExchangeInfo");
    appendChild(root);
    // Original format also was UDX?
    bool wasUDX = false;
    if (!list.isEmpty())
        if (list[0].originalFormat=="UDX")
            wasUDX = true;
    // XML header
    QDomNode node = createProcessingInstruction("xml", "version=\"1.0\" encoding=\"utf-8\"");
    insertBefore(node, firstChild());
    // UDX header
    QDomElement recInfo = addElement(root, "RecordInfo");
    addElement(recInfo, "VendorInfo", "VendorUDX");
    addElement(recInfo, "DeviceInfo", "DeviceUDX");
    if (wasUDX)
        addElement(recInfo, "UdxVersion", list[0].version);
    else
        addElement(recInfo, "UdxVersion", "1.0");
    addElement(recInfo, "UserAgent", "AgentUDX");
    addElement(recInfo, "UserInfo", "UserUDX");
    addElement(recInfo, "Encoding", "UTF-8");
    addElement(recInfo, "FileSize", "          "); // strongly 10 spaces! (~~)
    addElement(recInfo, "Date", QDate::currentDate().toString("dd.MM.yyyy"));
    addElement(recInfo, "Language","CHS"); // wtf, but this code was in real russian-language udx
    QDomElement vcfInfo = addElement(recInfo, "RecordOfvCard");
    if (wasUDX)
        addElement(vcfInfo, "vCardVersion", list[0].subVersion);
    else
        addElement(vcfInfo, "vCardVersion", "2.1");
    addElement(vcfInfo, "vCardRecord", QString::number(list.count()));
    addElement(vcfInfo, "vCardLength", "          "); // strongly 10 spaces! (~~)
    addElement(recInfo, "RecordOfvCalendar");
    addElement(recInfo, "RecordOfSMS");
    addElement(recInfo, "RecordOfMMS");
    addElement(recInfo, "RecordOfEmail");
    // Parent tag for all records
    QDomElement vCard = addElement(root, "vCard");
    // Add missing sequences to records
    int maxSeq = 0;
    if (wasUDX) { // wasUDX - simply add missing
        foreach (const ContactItem& item, list)
            if (item.id.toInt()>maxSeq)
                    maxSeq = item.id.toInt();
        QSet<int> seqs;
        for (int i=0; i<list.count(); i++) {
            ContactItem& item = list[i];
            int currentID = item.id.toInt();
            if (currentID<1) // simply missing
                item.id = QString::number(++maxSeq);
            if (seqs.contains(currentID)) { // duplicate?
                _errors << QObject::tr("Warning: contact %1, duplicate id %2 changed to %3")
                     .arg(item.visibleName).arg(currentID).arg(++maxSeq);
                item.id = QString::number(maxSeq);
            }
            seqs.insert(item.id.toInt());
        }
    }
    else { // if original wasn't UDX, completely renumerate all
        for (int i=0; i<list.count(); i++)
Пример #3
0
bool UDXFile::importRecords(const QString &url, ContactList &list, bool append)
{
    if (!openFile(url, QIODevice::ReadOnly))
        return false;
    // Read XML
    QString err_msg;
    int err_line, err_col;
    if (!setContent(&file, &err_msg, &err_line, &err_col)) {
        _errors << QObject::tr("Can't read content from file %1\n%2\nline %3, col %4\n")
            .arg(url).arg(err_msg).arg(err_line).arg(err_col);
        closeFile();
        return false;
    }
    closeFile();
    // Root element
    QDomElement root = documentElement();
    if (root.nodeName()!="DataExchangeInfo") {
        _errors << QObject::tr("Root node is not 'DataExchangeInfo' at file\n%1").arg(url);
        return false;
    }
    // Codepage, version, expected record count
    QDomElement recInfo = root.firstChildElement("RecordInfo");
    if (recInfo.isNull()) {
        _errors << QObject::tr("Can't find 'RecordInfo' tag at file\n%1").arg(url);
        return false;
    }
    QString charSet = recInfo.firstChildElement("Encoding").text();
    if (charSet.isEmpty()) {
        _errors << QObject::tr("Warning: codepage not found, trying use UTF-8...");
        charSet = "UTF-8";
    }
    QString udxVer = recInfo.firstChildElement("UdxVersion").text();
    if (udxVer.isEmpty()) {
        _errors << QObject::tr("Warning: udx version not found, treat as 1.0...");
        udxVer = "1.0";
    }
    QDomElement vcfInfo = recInfo.firstChildElement("RecordOfvCard");
    QString vcVer = vcfInfo.firstChildElement("vCardVersion").text();
    int expCount = vcfInfo.firstChildElement("vCardRecord").text().toInt();
    // vCard set
    QDomElement vCard = root.firstChildElement("vCard");
    if (vCard.isNull()) {
        _errors << QObject::tr("Can't find 'vCard' records at file\n%1").arg(url);
        return false;
    }
    // QTextCodec* codec = QTextCodec::codecForName(charSet.toLocal8Bit()); TODO not works on windows
    ContactItem item;
    if (!append)
        list.clear();
    QDomElement vCardInfo = vCard.firstChildElement("vCardInfo");
    while (!vCardInfo.isNull()) {
        item.clear();
        item.originalFormat = "UDX";
        item.version = udxVer;
        item.subVersion = vcVer;
        item.id = vCardInfo.firstChildElement("Sequence").text();
        QDomElement fields = vCardInfo.firstChildElement("vCardField");
        if (fields.isNull())
            _errors << QObject::tr("Can't find 'vCardField' at sequence %1").arg(item.id);
        QDomElement field = fields.firstChildElement();
        while (!field.isNull()) {
            QString fldName = field.nodeName().toUpper();
            QString fldValue = field.text(); // codec->toUnicode(field.text().toLocal8Bit()); TODO not works on windows
            if (fldName=="N") {
                fldValue.replace("\\;", " ");
                // In ALL known me udx files part before first ; was EMPTY
                fldValue.remove(";");
                item.names = fldValue.split(" ");
                // If empty parts not in-middle, remove it
                item.dropFinalEmptyNames();
            }
            else if (fldName.startsWith("TEL")) {
                Phone phone;
                phone.number = fldValue;
                if (fldName=="TEL")
                    phone.tTypes << "CELL";
                else if (fldName=="TELHOME")
                    phone.tTypes << "HOME";
                else if (fldName=="TELWORK")
                    phone.tTypes << "WORK";
                else if (fldName=="TELFAX")
                    phone.tTypes << "FAX";
                else
                    _errors << QObject::tr("Unknown phone type: %1 (%2)").arg(phone.number).arg(item.names[0]);
                item.phones.push_back(phone);
            }
            else if (fldName=="ORGNAME")
                item.organization = fldValue;
            else if (fldName=="BDAY")
                item.birthday.value = QDateTime::fromString(fldValue, "yyyyMMdd"); // TODO Maybe, use DateItem::fromString
            else if (fldName=="EMAIL") {
                Email email;
                email.address = fldValue;
                email.emTypes << "pref";
                item.emails.push_back(email);
            }
            else
                _errors << QObject::tr("Unknown 'vCardfield' type: %1").arg(fldName);
            field = field.nextSiblingElement();
        }
        item.calculateFields();
        list.push_back(item);
        vCardInfo = vCardInfo.nextSiblingElement();
    }
    if (list.count()!=expCount)
        _errors << QObject::tr("%1 records read, %2 expected").arg(list.count()).arg(expCount);
    // Unknown tags statistics
    int totalUnknownTags = 0;
    foreach (const ContactItem& _item, list)
        totalUnknownTags += _item.unknownTags.count();
    if (totalUnknownTags)
        _errors << QObject::tr("%1 unknown tags found").arg(totalUnknownTags);
    // Ready
    return (!list.isEmpty());
}
Пример #4
0
// Main program loop
int Convertor::start()
{
    out << tr("Contact convertor by Mikhail Y. Zvyozdochkin\n");
    // Parse command line
    if (arguments().count()<2) {
        printUsage();
        return 1;
    }
    QString inPath, outPath, outFormat;
    bool forceOverwrite = false;
    bool forceSingleFile = false;
    bool forceDirectory = false;
    for (int i=1; i<arguments().count(); i++) {
        if (arguments()[i]=="-i") {
            i++;
            if (i==arguments().count()) {
                out << tr("linvert error: -i option present, but file path is missing\n");
                printUsage();
                return 2;
            }
            inPath = arguments()[i];
            continue;
        }
        else if (arguments()[i]=="-o") {
            i++;
            if (i==arguments().count()) {
                out << tr("linvert error: -o option present, but file path is missing\n");
                printUsage();
                return 3;
            }
            outPath = arguments()[i];
            continue;
        }
        else if (arguments()[i]=="-f") {
            i++;
            if (i==arguments().count()) {
                out << tr("linvert error: -f option present, but format name is missing\n");
                printUsage();
                return 4;
            }
            outFormat = arguments()[i];
            if (outFormat!="vcf21" && outFormat!="vcf30" && outFormat!="vcfauto" && outFormat!="udx" && outFormat!="copy") {
                out << tr("Unknown output format: %1\n").arg(outFormat);
                printUsage();
                return 5;
            }
            continue;
        }
        else if (arguments()[i]=="-w")
            forceOverwrite = true;
        else if (arguments()[i]=="-s")
            forceSingleFile = true;
        else if (arguments()[i]=="-d")
            forceDirectory = true;
        else {
            out << tr("Unknown option: %1\n").arg(arguments()[i]);
            printUsage();
            return 6;
        }
    }
    // Check input data completion
    if (inPath.isEmpty()) {
        out << tr("Input path is missing\n");
        printUsage();
        return 7;
    }
    if (outPath.isEmpty()) {
        out << tr("Output path is missing\n");
        printUsage();
        return 8;
    }
    if (outFormat.isEmpty()) {
        out << tr("Output format name is missing\n");
        printUsage();
        return 9;
    }
    if (forceSingleFile && forceDirectory) {
        out << tr("Options -s and -d are not compatible\n");
        printUsage();
        return 10;
    }
    if (forceDirectory && !outFormat.contains("vcf") && outFormat!="copy") {
        out << tr("-d option applicable only for vCard format");
        return 11;
    }
    // Check if output file exists
    QFile of(outPath);
    if (of.exists() && !forceOverwrite && !QFileInfo(outPath).isDir()) {
        out << tr("Output file already exists, use -w if necessary\n");
        printUsage();
        return 12;
    }
    // Define, create file or directory at output
    // (default: as input)
    FormatType ift = QFileInfo(inPath).isDir() ? ftDirectory : ftFile;
    FormatType oft = ift;
    if (forceSingleFile)
        oft = ftFile;
    else if (forceDirectory)
        oft = ftDirectory;
    // Read
    IFormat* iFormat = 0;
    FormatFactory factory;
    if (ift==ftFile)
        iFormat = factory.createObject(inPath);
    else
        iFormat = new VCFDirectory();
    if (!iFormat) {
        out << factory.error << "\n";
        return 13;
    }
    ContactList items;
    bool res = iFormat->importRecords(inPath, items, false);
    logFormat(iFormat);
    delete iFormat;
    if (!res)
        return 14;
    out << tr("%1 records read\n").arg(items.count());
    //Define output format
    gd.preferredVCFVersion = GlobalConfig::VCF21;
    IFormat* oFormat = 0;
    if (oft==ftDirectory)
        oFormat = new VCFDirectory();
    else if (outFormat.contains("vcf")) {
        if (outFormat=="vcf30")
            gd.preferredVCFVersion = GlobalConfig::VCF30;
        gd.useOriginalFileVersion = (outFormat=="vcfauto");
        oFormat = new VCFFile();
    }
    else if (outFormat.contains("udx"))
        oFormat = new UDXFile();
    else { // copy input format
        if (VCFFile::detect(inPath)) {
            gd.useOriginalFileVersion = true;
            oFormat = new VCFFile();
        }
        else if (UDXFile::detect(inPath))
            oFormat = new UDXFile();
        // else if (MPBFile::detect(inPath)) { TODO m.b. implement?
        else if (inPath.contains(".mpb", Qt::CaseInsensitive)) { // temp hack
            out << "MPB format is read-only and incompatible with 'copy' option. Use VCF or UDX for output file\n";
            return 15;
        }
        else {
            out << "Can't autodetect input format\n";
            return 16;
        }
    }
    // Write
    res = oFormat->exportRecords(outPath, items);
    logFormat(oFormat);
    delete oFormat;
    out << "Output file successfully written\n";
    return res ? 0 : 17;
}