source: qutecom-2.2/wengophone/src/model/config/ConfigImporter.cpp @ 639:adfe29945e89

Last change on this file since 639:adfe29945e89 was 639:adfe29945e89, checked in by laurent@…, 3 years ago

fix import config and bump config version

File size: 31.9 KB
Line 
1/*
2 * WengoPhone, a voice over Internet phone
3 * Copyright (C) 2004-2006  Wengo
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 */
19
20#include "ConfigImporter.h"
21
22#include "Config.h"
23#include "ConfigManager.h"
24
25#include <model/account/wengo/WengoAccount.h>
26#include <model/contactlist/Contact.h>
27#include <model/contactlist/ContactList.h>
28#include <model/contactlist/ContactListXMLSerializer.h>
29#include <model/contactlist/ContactListXMLSerializer1.h>
30#include <model/profile/EnumSex.h>
31#include <model/profile/StreetAddress.h>
32#include <model/profile/UserProfile.h>
33#include <model/profile/UserProfileHandler.h>
34#include <model/profile/UserProfileFileStorage1.h>
35#include <model/profile/UserProfileXMLSerializer.h>
36
37#include <imwrapper/IMAccountListXMLSerializer.h>
38#include <imwrapper/IMAccountListXMLSerializer1.h>
39
40#include <cutil/global.h>
41
42#include <util/Base64.h>
43#include <util/File.h>
44#include <util/Logger.h>
45#include <util/Path.h>
46#include <util/String.h>
47
48#include <settings/SettingsXMLSerializer.h>
49
50#include <map>
51#include <string>
52#include <vector>
53#include <sstream>
54#include <iostream>
55
56using namespace std;
57
58typedef struct telNumber_s {
59        string key;
60        string value;
61} telNumber_t;
62
63typedef std::list<telNumber_t *> telNumberList;
64typedef std::list<telNumber_t *>::iterator telNumberIt;
65
66typedef struct address_s {
67        string street;
68        string city;
69        string post_code;
70        string state;
71        string country;
72} address_t;
73
74typedef struct birthday_s {
75        int day;
76        int month;
77        int year;
78} birthday_t;
79
80#define MALE 0
81#define FEMALE 1
82#define UNKNOWN 2
83
84typedef struct vcard_s {
85        string id;
86        string fname;
87        string lname;
88        int gender;
89        string company;
90        string website;
91        birthday_t birthday;
92        string note;
93        address_t address;
94        telNumberList numbers;
95        StringList emails;
96        string owner;
97        bool blocked;
98} vcard_t;
99
100typedef std::list<vcard_t *> vcardList;
101typedef std::list<vcard_t *>::iterator vcardIt;
102
103static const char * HOME_NUMBER_KEY = "home";
104static const char * WORK_NUMBER_KEY = "work";
105static const char * CELL_NUMBER_KEY = "cell";
106static const char * FAX_NUMBER_KEY = "fax";
107static const char * OTHER_NUMBER_KEY = "other";
108
109telNumber_t * createNewNodeNumber(const std::string & key, const std::string & value) {
110        telNumber_t * number = new telNumber_t();
111
112        memset(number, 0, sizeof(telNumber_t));
113        number->key = key;
114        number->value = value;
115
116        return number;
117}
118
119StringList mySplit(const std::string & str, char sep) {
120        string word;
121        StringList wordList;
122        istringstream strStream(str);
123
124        while (std::getline(strStream, word, sep)) {
125                wordList += word;
126        }
127
128        return wordList;
129}
130
131static void initVcard(vcard_t * mVcard) {
132        if (mVcard) {
133                mVcard->gender = UNKNOWN;
134                mVcard->blocked = false;
135                mVcard->birthday.day = 1;
136                mVcard->birthday.month = 1;
137                mVcard->birthday.year = 1900;
138        }
139}
140
141static const int CONFIG_UNKNOWN = 0;
142static const int CONFIG_VERSION1 = 1;
143static const int CONFIG_VERSION2 = 2;
144static const int CONFIG_VERSION3 = 3;
145static const int CONFIG_VERSION4 = 4;
146static const int CONFIG_VERSION5 = 5;
147static const int CONFIG_VERSION6 = 6;
148static const int CONFIG_VERSION7 = 7;
149static const int CONFIG_VERSION8 = 8;
150static const int CONFIG_VERSION9 = 9;
151static const int CONFIG_VERSION10 = 10;
152static const int CONFIG_VERSION11 = 11;
153static const int CONFIG_VERSION12 = 12;
154static const int CONFIG_VERSION13 = 13;
155static const int CONFIG_VERSION14 = 14;
156static const int CONFIG_VERSION15 = 15;
157
158static const std::string USERPROFILE_FILENAME = "userprofile.xml";
159static const std::string USERCONFIG_FILENAME = "user.config";
160static const std::string IMACCOUNTS_FILENAME = "imaccounts.xml";
161static const std::string CONTACTLIST_FILENAME = "contactlist.xml";
162static const std::string NEW_HISTORY_FILENAME = "history.xml";
163static const std::string OLD_HISTORY_FILENAME = "_history";
164static const std::string CONFIG_FILENAME = "config.xml";
165static const std::string FAKE_LOGIN = "**fake_identity**";
166static const std::string FAKE_PASSWORD = "**fake_password**";
167static const std::string CONTACT_PREFIX = "#IMPORTED_CONTACT#";
168
169void ConfigImporter::importConfig() {
170        Config& config = ConfigManager::getInstance().getCurrentConfig();
171        int systemVersion = boost::any_cast<int>( config.getDefaultValue(Config::CONFIG_VERSION_KEY) );
172        int localVersion = detectLastVersion();
173
174        if (localVersion != CONFIG_UNKNOWN && localVersion < systemVersion) {
175                if (localVersion == CONFIG_VERSION1) {
176                        importConfigFromV1toV3();
177                        localVersion = CONFIG_VERSION3;
178                }
179
180                if (localVersion == CONFIG_VERSION2) {
181                        importConfigFromV2toV3();
182                        localVersion = CONFIG_VERSION3;
183                }
184
185                if (localVersion == CONFIG_VERSION3) {
186                        importConfigFromV3toV4();
187                        localVersion = CONFIG_VERSION4;
188                }
189
190                if (localVersion == CONFIG_VERSION4) {
191                        importConfigFromV4toV5();
192                        localVersion = CONFIG_VERSION5;
193                }
194
195                if (localVersion == CONFIG_VERSION5) {
196                        importConfigFromV5toV6();
197                        localVersion = CONFIG_VERSION6;
198                }
199
200                if (localVersion == CONFIG_VERSION6) {
201                        importConfigFromV6toV7();
202                        localVersion = CONFIG_VERSION7;
203                }
204
205                if (localVersion == CONFIG_VERSION7) {
206                        importConfigFromV7toV8();
207                        localVersion = CONFIG_VERSION8;
208                }
209
210                if (localVersion == CONFIG_VERSION8) {
211                        // Nothing to do, just bump the version number
212                        localVersion = CONFIG_VERSION9;
213                }
214               
215                if (localVersion == CONFIG_VERSION9) {
216                        // Nothing to do, just bump the version number
217                        localVersion = CONFIG_VERSION10;
218                }
219               
220                if (localVersion == CONFIG_VERSION10) {
221                        // Nothing to do, just bump the version number
222                        localVersion = CONFIG_VERSION11;
223                }
224               
225                if (localVersion == CONFIG_VERSION11) {
226                        // Nothing to do, just bump the version number
227                        localVersion = CONFIG_VERSION12;
228                }
229               
230                if (localVersion == CONFIG_VERSION12) {
231                        // Nothing to do, just bump the version number
232                        localVersion = CONFIG_VERSION13;
233                }
234               
235                if (localVersion == CONFIG_VERSION13) {
236                        // Nothing to do, just bump the version number
237                        localVersion = CONFIG_VERSION14;
238                }
239               
240                if (localVersion == CONFIG_VERSION14) {
241                        // Nothing to do, just bump the version number
242                        localVersion = CONFIG_VERSION15;
243                }
244
245                if (localVersion < systemVersion) {
246                        LOG_FATAL("importer: config=" + String::fromNumber(localVersion)
247                                + " failed to reach config=" + String::fromNumber(systemVersion));
248                }
249
250                // Set the new version number
251                Settings settings = readConfigFile();
252                settings.set(Config::CONFIG_VERSION_KEY, systemVersion);
253                writeConfigFile(settings);
254        }
255}
256
257unsigned ConfigImporter::detectLastVersion() {
258        string ConfigPathV1 = getWengoClassicConfigPath();
259        string ConfigPathV2 = Config::getConfigDir();
260
261        bool dirV1Exists = !ConfigPathV1.empty()
262                && File::exists(ConfigPathV1.substr(0, ConfigPathV1.size() - 1));
263        bool dirV2Exists = !ConfigPathV2.empty()
264                && File::exists(ConfigPathV2.substr(0, ConfigPathV2.size() - 1));
265
266        if (dirV2Exists) {
267                if (File::exists(ConfigPathV2 + "profiles")) {
268                       
269                        std::string configFilename = ConfigPathV2 + CONFIG_FILENAME;
270                        if (!File::exists(configFilename)) {
271                                return CONFIG_UNKNOWN;
272                        }
273                        Settings settings = readConfigFile();
274                        if (settings.contains(Config::CONFIG_VERSION_KEY)) {
275                                return settings.getIntegerKeyValue(Config::CONFIG_VERSION_KEY);
276                        } else {
277                                // If the config version does not exist, it means that the
278                                // config is older than version 4.
279                                return CONFIG_VERSION3;
280                        }
281                } else if (File::exists(ConfigPathV2 + "user.config")) {
282                        return CONFIG_VERSION2;
283                } else if (dirV1Exists) {
284                        return CONFIG_VERSION1;
285                }
286        } else if (dirV1Exists) {
287                return CONFIG_VERSION1;
288        }
289
290        return CONFIG_UNKNOWN;
291}
292
293string ConfigImporter::getWengoClassicConfigPath() {
294        string result;
295
296#if defined(OS_WINDOWS)
297        result = File::convertPathSeparators(Path::getHomeDirPath() + "wengo/");
298#elif defined(OS_LINUX)
299        result = File::convertPathSeparators(Path::getHomeDirPath() + ".wengo/");
300#endif
301
302        return result;
303}
304
305/**
306 * Works like std::getline() but will remove any ending '\r'. This is necessary
307 * because the WengoPhone Classic creates files ending with '\r\n', regardless
308 * of the platform
309 */
310static void getStrippedLine(std::ifstream& stream, std::string& line) {
311        std::getline(stream, line);
312        if (line[line.size() - 1] == '\r') {
313                line = line.substr(0, line.size() - 1);
314        }
315}
316
317bool ConfigImporter::classicVcardParser(const string & vcardFile, void * structVcard) {
318        vcard_t * mVcard = (vcard_t *) structVcard;
319        std::ifstream fileStream;
320        string lastLine;
321
322        fileStream.open(vcardFile.c_str());
323        if (!fileStream) {
324                LOG_ERROR("cannot open the file: " + vcardFile);
325                return false;
326        }
327
328        getStrippedLine(fileStream, lastLine);
329        if (lastLine != "BEGIN:VCARD") {
330                return false;
331        }
332
333        String key, value, tmp;
334
335        getStrippedLine(fileStream, tmp);
336
337        while (!lastLine.empty()) {
338                int pos = lastLine.find(":", 0);
339                key = lastLine.substr(0, pos);
340                value = lastLine.substr(pos + 1, lastLine.length() - (pos + 1));
341
342                if (!value.empty()) {
343                        if (!key.compare("N")) {
344                                StringList mList = mySplit(value, ';');
345                                mVcard->lname = mList[0];
346                                mVcard->fname = mList[1];
347
348                                if (!mList[4].compare("Mme.")) {
349                                        mVcard->gender = FEMALE;
350                                }
351                                else if (!mList[4].compare("Mr.")) {
352                                        mVcard->gender = MALE;
353                                }
354                                else {
355                                        mVcard->gender = UNKNOWN;
356                                }
357                        }
358                        else if (!key.compare("TEL;TYPE=home")) {
359                                mVcard->numbers.push_back(createNewNodeNumber(HOME_NUMBER_KEY, value));
360                        }
361
362                        else if (!key.compare("TEL;TYPE=work")) {
363                                mVcard->numbers.push_back       (createNewNodeNumber(WORK_NUMBER_KEY, value));
364                        }
365
366                        else if (!key.compare("TEL;TYPE=cell")) {
367                                mVcard->numbers.push_back(createNewNodeNumber(CELL_NUMBER_KEY, value));
368                        }
369
370                        else if (!key.compare("TEL;TYPE=pref")) {
371                                mVcard->id = CONTACT_PREFIX + value;
372                        }
373
374                        else if (!key.compare("TEL;TYPE=fax")) {
375                                mVcard->numbers.push_back(createNewNodeNumber(FAX_NUMBER_KEY, value));
376                        }
377
378                        else if (!key.compare("TEL;TYPE=other")) {
379                                mVcard->numbers.push_back(createNewNodeNumber(OTHER_NUMBER_KEY, value));
380                        }
381
382                        else if (!key.compare("EMAIL")) {
383                                mVcard->emails += value;
384                        }
385
386                        else if (!key.compare("ORG")) {
387                                mVcard->company = value;
388                        }
389
390                        else if (!key.compare("URL")) {
391                                mVcard->website = value;
392                        }
393
394                        else if (!key.compare("BDAY")) {
395                                StringList mList = mySplit(value, '-');
396                                mVcard->birthday.year = atoi(mList[0].c_str());
397                                mVcard->birthday.month = atoi(mList[1].c_str());
398                                mVcard->birthday.day = atoi(mList[2].c_str());
399                        }
400                        else if (!key.compare("NOTE")) {
401                                mVcard->note = value;
402                        }
403
404                        else if (!key.compare("ADR;TYPE=home;TYPE=pref")) {
405                                StringList mList = mySplit(value, ';');
406                                mVcard->address.street = mList[2];
407                                mVcard->address.city = mList[3];
408                                mVcard->address.state = mList[4];
409                                mVcard->address.post_code = mList[5];
410                                mVcard->address.country = mList[6];
411                        }
412                        else {
413                                LOG_DEBUG("KEY " + key + " not supported");
414                        }
415                }
416
417                lastLine = tmp.trim();
418                getStrippedLine(fileStream, tmp);
419
420                if (!tmp.empty()) {
421                        if (tmp.find(":", 0) == string::npos) {
422                                lastLine += tmp.trim();
423                                getStrippedLine(fileStream, tmp);
424                        }
425                }
426        }
427
428        return true;
429}
430
431bool ConfigImporter::classicXMLParser(const string & xmlFile, void *structVcard) {
432        vcard_t *mVcard = (vcard_t *) structVcard;
433        std::ifstream fileStream;
434        String lastLine;
435
436        mVcard->blocked = false;
437
438        fileStream.open(xmlFile.c_str());
439        if (!fileStream) {
440                LOG_ERROR("cannot open the file: " + xmlFile);
441                return false;
442        }
443
444        std::getline(fileStream, lastLine);
445
446        while (!lastLine.empty()) {
447                lastLine = lastLine.trim();
448
449                if (!strncmp(lastLine.c_str(), "<blocked>", 9)) {
450                        int pos1 = lastLine.find_first_of('>');
451                        int pos2 = lastLine.find_last_of('<');
452                        string resp = ((String)lastLine.substr(pos1 + 1, pos2 - (pos1 + 1))).trim();
453
454                        if (resp == "true") {
455                                mVcard->blocked = true;
456                        }
457                }
458
459                std::getline(fileStream, lastLine);
460        }
461
462        return true;
463}
464
465string ConfigImporter::classicVCardToString(void *structVcard) {
466        vcard_t * mVcard = (vcard_t *) structVcard;
467        string res = "<wgcard version=\"1.0\" xmlns=\"http://www.openwengo.org/wgcard/1.0\">\n";
468
469        //Todo: look at ProfileXMLSerializer and try to use the same serializer
470        if (!mVcard->id.empty()) {
471                res += ("<wengoid>" + mVcard->id + "</wengoid>\n");
472        }
473
474        res += "<name>\n";
475        if (!mVcard->fname.empty()) {
476                res += ("<first><![CDATA[" + mVcard->fname + "]]></first>\n");
477        }
478        if (!mVcard->lname.empty()) {
479                res += ("<last><![CDATA[" + mVcard->lname + "]]></last>\n");
480        }
481        res += "</name>\n";
482
483        if (mVcard->gender == MALE) {
484                res += ("<sex>male</sex>\n");
485        }
486        else if (mVcard->gender == FEMALE) {
487                res += ("<sex>female</sex>\n");
488        }
489
490        if (!mVcard->website.empty()) {
491                res += ("<url type=\"website\">" + mVcard->website + "</url>\n");
492        }
493
494        if (mVcard->birthday.day && mVcard->birthday.month && mVcard->birthday.year) {
495                res += "<birthday>\n<date>\n";
496                res += ("<day>" + String::fromNumber(mVcard->birthday.day) + "</day>\n");
497                res += ("<month>" + String::fromNumber(mVcard->birthday.month) + "</month>\n");
498                res += ("<year>" + String::fromNumber(mVcard->birthday.year) + "</year>\n");
499                res += "</date>\n</birthday>\n";
500        }
501
502        if (!mVcard->company.empty()) {
503                res += "<organization>" + mVcard->company + "</organization>\n";
504        }
505
506        telNumberIt it;
507        for (it = mVcard->numbers.begin(); it != mVcard->numbers.end(); it++) {
508                if (!(*it)->key.compare("home") && !((*it)->value.empty())) {
509                        res += "<tel type=\"home\">" + (*it)->value + "</tel>\n";
510                }
511                else if (!(*it)->key.compare("work") && !((*it)->value.empty())) {
512                        res += "<tel type=\"work\">" + (*it)->value + "</tel>\n";
513                }
514                else if (!(*it)->key.compare("cell") && !((*it)->value.empty())) {
515                        res += "<tel type=\"cell\">" + (*it)->value + "</tel>\n";
516                }
517                else if (!(*it)->key.compare("fax") && !((*it)->value.empty())) {
518                        res += "<fax type=\"home\">" + (*it)->value + "</fax>\n";
519                }
520        }
521
522        res += "<address type=\"home\">\n";
523        if (!mVcard->address.street.empty()) {
524                res += ("<street><![CDATA[" + mVcard->address.street + "]]></street>\n");
525        }
526        if (!mVcard->address.city.empty()) {
527                res += ("<locality><![CDATA[" + mVcard->address.city + "]]></locality>\n");
528        }
529        if (!mVcard->address.state.empty()) {
530                res += ("<region><![CDATA[" + mVcard->address.state + "]]></region>\n");
531        }
532        if (!mVcard->address.post_code.empty()) {
533                res += ("<postcode><![CDATA[" + mVcard->address.post_code + "]]></postcode>\n");
534        }
535        if (!mVcard->address.country.empty()) {
536                res += ("<country><![CDATA[" + mVcard->address.country + "]]></country>\n");
537        }
538        res += "</address>\n";
539
540        if (!mVcard->id.empty()) {
541                res += "<im protocol=\"SIP/SIMPLE\">\n";
542                res += ("<id>" + mVcard->id + "</id>\n");
543                res += ("<account>" + mVcard->owner + "</account>");
544                res += "</im>\n";
545        }
546
547        if (mVcard->emails.size() >= 1 && !mVcard->emails[0].empty()) {
548                res += ("<email type=\"home\">" + mVcard->emails[0] + "</email>\n");
549        }
550        if (mVcard->emails.size() >= 2 && !mVcard->emails[1].empty()) {
551                res += ("<email type=\"work\">" + mVcard->emails[1] + "</email>\n");
552        }
553        if (mVcard->emails.size() >= 3 && !mVcard->emails[2].empty()) {
554                res += ("<email type=\"other\">" + mVcard->emails[2] + "</email>\n");
555        }
556
557        if (!mVcard->note.empty()) {
558                res += ("<notes><![CDATA[" + mVcard->note + "]]></notes>\n");
559        }
560
561        res += ("<group><![CDATA[Wengo]]></group>\n");
562
563        res += "</wgcard>\n";
564        return res;
565}
566
567void ConfigImporter::addContactDetails(Contact & contact, void * structVcard) {
568        vcard_t * mVcard = (vcard_t *) structVcard;
569
570        contact.setFirstName(mVcard->fname);
571        contact.setLastName(mVcard->lname);
572        contact.setCompany(mVcard->company);
573        contact.setBirthdate(Date(mVcard->birthday.day, mVcard->birthday.month, mVcard->birthday.year));
574        contact.setNotes(mVcard->note);
575        contact.setWebsite(mVcard->website);
576        if (!mVcard->address.city.empty()) {
577                StreetAddress adress;
578                adress.setStreet(mVcard->address.street);
579                adress.setCity(mVcard->address.city);
580                adress.setZipCode(mVcard->address.post_code);
581                adress.setStateProvince(mVcard->address.state);
582                adress.setCountry(mVcard->address.country);
583                contact.setStreetAddress(adress);
584        }
585
586        if (mVcard->gender != UNKNOWN) {
587                contact.setSex(mVcard->gender == MALE ? EnumSex::SexMale : EnumSex::SexFemale);
588        }
589
590        telNumberIt it;
591        for (it = mVcard->numbers.begin(); it != mVcard->numbers.end(); it++) {
592                if (!(*it)->key.compare(HOME_NUMBER_KEY) && !((*it)->value.empty())) {
593                        contact.setHomePhone((*it)->value);
594                }
595                else if (!(*it)->key.compare(WORK_NUMBER_KEY) && !((*it)->value.empty())) {
596                        contact.setWorkPhone((*it)->value);
597                }
598                else if (!(*it)->key.compare(CELL_NUMBER_KEY) && !((*it)->value.empty())) {
599                        contact.setMobilePhone((*it)->value);
600                }
601                else if (!(*it)->key.compare(FAX_NUMBER_KEY) && !((*it)->value.empty())) {
602                        contact.setFax((*it)->value);
603                }
604                else if (!(*it)->key.compare(OTHER_NUMBER_KEY) && !((*it)->value.empty())) {
605                        contact.setOtherPhone((*it)->value);
606                }
607        }
608
609        if (mVcard->emails.size() >= 1 && !mVcard->emails[0].empty()) {
610                contact.setPersonalEmail(mVcard->emails[0]);
611        }
612        if (mVcard->emails.size() >= 2 && !mVcard->emails[1].empty()) {
613                contact.setWorkPhone(mVcard->emails[1]);
614        }
615        if (mVcard->emails.size() >= 3 && !mVcard->emails[2].empty()) {
616                contact.setOtherPhone(mVcard->emails[2]);
617        }
618}
619
620bool ConfigImporter::importContactsFromV1toV3(const string & fromDir, UserProfile & userProfile) {
621        File mDir(fromDir);
622        StringList fileList = mDir.getFileList();
623        ContactList & contactList = userProfile.getContactList();
624
625        contactList.addContactGroup("Classic");
626
627        IMAccountList imAccountList =
628                userProfile.getIMAccountManager().getIMAccountsOfProtocol(EnumIMProtocol::IMProtocolWengo);
629
630        if (!imAccountList.size()) {
631                return false;
632        }
633
634        for (unsigned i = 0; i < fileList.size(); i++) {
635                File mFile(fromDir + fileList[i]);
636                string Id = fileList[i].substr(0, fileList[i].find("_", 0));
637                vcard_t mVcard;
638
639                initVcard(&mVcard);
640                if (!mFile.getExtension().compare("vcf")) {
641                        if (classicVcardParser(fromDir + fileList[i], &mVcard) == false) {
642                                continue;
643                        }
644
645                        int extPos = fileList[i].find_last_of('.');
646                        string fileWoExt = fileList[i].substr(0, extPos + 1);
647                        classicXMLParser(fromDir + fileWoExt + "xml", &mVcard);
648
649                        IMContact imContact(*imAccountList.begin(), mVcard.id);
650                        Contact & contact = contactList.createContact();
651                        contact.setGroupId(contactList.getContactGroupIdFromName("Classic"));
652                        addContactDetails(contact, &mVcard);
653                        contact.addIMContact(imContact);
654                }
655        }
656        return true;
657}
658
659typedef struct last_user_s {
660        string login;
661        string password;
662        bool auto_login;
663} last_user_t;
664
665void * ConfigImporter::getLastWengoUser(const std::string & configUserFile, int version) {
666        std::ifstream fileStream;
667        String lastLine;
668
669        last_user_t * lastUser = new last_user_t();
670        fileStream.open(configUserFile.c_str());
671        if (!fileStream) {
672                LOG_ERROR("cannot open the file: " + configUserFile);
673                return NULL;
674        }
675
676        std::getline(fileStream, lastLine);
677
678        while (!lastLine.empty()) {
679                lastLine = lastLine.trim();
680
681                if (!strncmp(lastLine.c_str(), "<login>", 7)) {
682                        int pos1, pos2;
683                        if (version == CONFIG_VERSION2) {
684                                pos1 = lastLine.find_first_of('>');
685                                pos2 = lastLine.find_last_of('<');
686                        } else {
687                                pos2 = lastLine.find_first_of(']');
688                                pos1 = lastLine.find_last_of('[');
689                        }
690
691                        lastUser->login = ((String)lastLine.substr(pos1 + 1, pos2 - (pos1 + 1))).trim();
692                }
693                else if (!strncmp(lastLine.c_str(), "<password>", 10)) {
694                        int pos1, pos2;
695                        if (version == CONFIG_VERSION2) {
696                                pos1 = lastLine.find_first_of('>');
697                                pos2 = lastLine.find_last_of('<');
698                        } else {
699                                pos2 = lastLine.find_first_of(']');
700                                pos1 = lastLine.find_last_of('[');
701                        }
702
703                        lastUser->password = ((String) lastLine.substr(pos1 + 1, pos2 - (pos1 + 1))).trim();
704                }
705                else if (!strncmp(lastLine.c_str(), "<autoLogin>", 11)) {
706                        int pos1 = lastLine.find_first_of('>');
707                        int pos2 = lastLine.find_last_of('<');
708                        string resp = ((String) lastLine.substr(pos1 + 1, pos2 - (pos1 + 1))).trim();
709
710                        if (resp == (version == CONFIG_VERSION2 ? "1" : "true")) {
711                                lastUser->auto_login = true;
712                        } else {
713                                lastUser->auto_login = false;
714                        }
715                }
716
717                std::getline(fileStream, lastLine);
718        }
719
720        return lastUser;
721}
722
723bool ConfigImporter::importConfigFromV1toV3() {
724        string classicPath = getWengoClassicConfigPath();
725        File mDir(classicPath);
726        last_user_t * lastUser = (last_user_t *) getLastWengoUser(classicPath + USERCONFIG_FILENAME, CONFIG_VERSION1);
727        if (lastUser) {
728                UserProfile userProfile;
729                WengoAccount wAccount(lastUser->login, lastUser->password, true);
730                userProfile.setSipAccount(wAccount, false);
731       
732                // An SSO request was made here before.
733                // The SSO request was made to get the SIP identity of the user and link Wengo contacts to this id.
734                // Faking this SSO request.
735                IMAccount imAccount(FAKE_LOGIN, FAKE_PASSWORD, EnumIMProtocol::IMProtocolWengo);
736                userProfile.addIMAccount(imAccount);
737
738                string sep = mDir.getPathSeparator();
739                String oldPath = classicPath + lastUser->login + sep + "contacts" + sep;
740                importContactsFromV1toV3(oldPath, userProfile);
741
742                String accountDir(userProfile.getProfileDirectory());
743                File::createPath(accountDir);
744                UserProfileFileStorage1 fStorage(userProfile);
745                fStorage.save(userProfile.getName());
746
747                Settings settings = readConfigFile();
748                settings.set(Config::PROFILE_LAST_USED_NAME_KEY, userProfile.getName());
749                writeConfigFile(settings);
750        }
751
752        return true;
753}
754
755bool ConfigImporter::importConfigFromV2toV3() {
756        String configDir = Config::getConfigDir();
757
758        FileReader file(configDir + USERPROFILE_FILENAME);
759        if (file.open()) {
760                string data = file.read();
761
762                last_user_t * lastUser = (last_user_t *) getLastWengoUser(configDir + USERCONFIG_FILENAME, CONFIG_VERSION2);
763                if (lastUser == NULL) {
764                        return false;
765                }
766
767                UserProfile userProfile;
768
769                UserProfileXMLSerializer serializer(userProfile);
770                serializer.unserialize(data);
771
772                WengoAccount wAccount(lastUser->login, Base64::decode(lastUser->password), true);
773                userProfile.setSipAccount(wAccount, false);
774       
775                // An SSO request was made here before.
776                // The SSO request was made to get the SIP identity of the user and link Wengo contacts to this id.
777                // Faking this SSO request.
778                IMAccount imAccount(FAKE_LOGIN, FAKE_PASSWORD, EnumIMProtocol::IMProtocolWengo);
779                userProfile.addIMAccount(imAccount);
780
781                //remove user.config and userprofile.xml from the main directory
782                File userConfigFile(configDir + USERCONFIG_FILENAME);
783                userConfigFile.remove();
784                File userProfileFile(configDir + USERPROFILE_FILENAME);
785                userProfileFile.remove();
786
787                String accountDir(userProfile.getProfileDirectory());
788                File::createPath(accountDir);
789                UserProfileFileStorage1 fStorage(userProfile);
790                fStorage.save(userProfile.getName());
791
792                File mFile1(configDir + IMACCOUNTS_FILENAME);
793                mFile1.move(accountDir + IMACCOUNTS_FILENAME, true);
794
795                File mFile2(configDir + CONTACTLIST_FILENAME);
796                mFile2.move(accountDir + CONTACTLIST_FILENAME, true);
797
798                File mDir(configDir);
799                StringList dirList = mDir.getFileList();
800                for (unsigned i = 0; i < dirList.size(); i++) {
801                        if (dirList[i].length() > OLD_HISTORY_FILENAME.length()) {
802                                if (dirList[i].substr(dirList[i].length() - OLD_HISTORY_FILENAME.length()) == OLD_HISTORY_FILENAME) {
803                                        File mFile3(configDir + dirList[i]);
804                                        mFile3.move(accountDir + NEW_HISTORY_FILENAME, true);
805                                        break;
806                                }
807                        }
808                }
809
810                Settings settings = readConfigFile();
811                settings.set(Config::PROFILE_LAST_USED_NAME_KEY, userProfile.getName());
812                writeConfigFile(settings);
813        }
814
815        return true;
816}
817
818bool ConfigImporter::importConfigFromV3toV4() {
819        StringList list = UserProfileHandler::getUserProfileNames();
820        std::string sipSimpleProtocol = EnumIMProtocol::toString(EnumIMProtocol::IMProtocolSIPSIMPLE);
821        std::string wengoProtocol = EnumIMProtocol::toString(EnumIMProtocol::IMProtocolWengo);
822
823        for (StringList::const_iterator it = list.begin();
824                it != list.end();
825                ++it) {
826
827                std::string userProfileDirectory = File::convertPathSeparators(Config::getConfigDir() + "profiles/" + *it + "/");
828
829                //Replacing in imaccounts.xml
830                FileReader iIMAccountsFile(userProfileDirectory + "imaccounts.xml");
831                iIMAccountsFile.open();
832                String data = iIMAccountsFile.read();
833
834                data.replace(sipSimpleProtocol, wengoProtocol);
835
836                FileWriter oIMAccountsFile(userProfileDirectory + "imaccounts.xml");
837                oIMAccountsFile.write(data);
838                ////
839
840                //Replacing in contactlist.xml
841                FileReader iContactListFile(userProfileDirectory + "contactlist.xml");
842                iContactListFile.open();
843                data = iContactListFile.read();
844
845                data.replace(sipSimpleProtocol, wengoProtocol);
846
847                FileWriter oContactListFile(userProfileDirectory + "contactlist.xml");
848                oContactListFile.write(data);
849                ////
850        }
851
852        return true;
853}
854
855bool ConfigImporter::importConfigFromV4toV5() {
856        std::string configFilename = Config::getConfigDir() + CONFIG_FILENAME;
857        //Replacing in config.xml
858        FileReader iConfigFile(configFilename);
859        iConfigFile.open();
860        String data = iConfigFile.read();
861
862        // Fix video.quality key (int to string)
863        data.replace("<video.quality><int>0</int></video.quality>",
864                "<video.quality><string>VideoQualityNormal</string></video.quality>");
865        data.replace("<video.quality><int>1</int></video.quality>",
866                "<video.quality><string>VideoQualityGood</string></video.quality>");
867        data.replace("<video.quality><int>2</int></video.quality>",
868                "<video.quality><string>VideoQualityVeryGood</string></video.quality>");
869        data.replace("<video.quality><int>3</int></video.quality>",
870                "<video.quality><string>VideoQualityExcellent</string></video.quality>");
871
872        FileWriter oConfigFile(configFilename);
873        oConfigFile.write(data);
874        ////
875
876        return true;
877}
878
879Settings ConfigImporter::readConfigFile() {
880        Settings settings;
881        std::string configFilename = Config::getConfigDir() + CONFIG_FILENAME;
882        FileReader iConfigFile(configFilename);
883        if (iConfigFile.open()) {
884                std::string data = iConfigFile.read();
885                SettingsXMLSerializer serializer(settings);
886                serializer.unserialize(data);
887        }
888        return settings;
889}
890
891void ConfigImporter::writeConfigFile(Settings& settings) {
892        std::string configFilename = Config::getConfigDir() + CONFIG_FILENAME;
893        SettingsXMLSerializer serializer(settings);
894        std::string data = serializer.serialize();
895
896        FileWriter oConfigFile(configFilename);
897        oConfigFile.write(data);
898}
899
900bool ConfigImporter::importConfigFromV5toV6() {
901        Settings settings = readConfigFile();
902
903        // In V5 (WengoPhone 2.0), the values of GENERAL_SHOW_OFFLINE_CONTACTS_KEY
904        // and GENERAL_SHOW_GROUPS_KEY were the opposite of their meaning.
905        if (settings.contains(Config::GENERAL_SHOW_OFFLINE_CONTACTS_KEY)) {
906                settings.set(Config::GENERAL_SHOW_OFFLINE_CONTACTS_KEY,
907                        !settings.getBooleanKeyValue(Config::GENERAL_SHOW_OFFLINE_CONTACTS_KEY)
908                        );
909        }
910
911        if (settings.contains(Config::GENERAL_SHOW_GROUPS_KEY)) {
912                settings.set(Config::GENERAL_SHOW_GROUPS_KEY,
913                        !settings.getBooleanKeyValue(Config::GENERAL_SHOW_GROUPS_KEY)
914                        );
915        }
916
917        writeConfigFile(settings);
918        return true;
919}
920
921bool ConfigImporter::importConfigFromV6toV7() {
922        StringList list = UserProfileHandler::getUserProfileNames();
923        std::map<std::string, EnumIMProtocol::IMProtocol> accountMap;
924
925        for (StringList::const_iterator it = list.begin();
926                it != list.end();
927                ++it) {
928
929                std::string userProfileDirectory = File::convertPathSeparators(Config::getConfigDir() + "profiles/" + *it + "/");
930
931                //Replacing AIM/ICQ in imaccounts.xml
932                FileReader iIMAccountsFile(userProfileDirectory + "imaccounts.xml");
933                iIMAccountsFile.open();
934                String data = iIMAccountsFile.read();
935                static const std::string AIMICQACCSTR = "<account protocol=\"AIM/ICQ\">";
936                static const std::string LOGINSTR = "<login>";
937
938                std::string::size_type accPos = data.find(AIMICQACCSTR);
939                while (accPos != std::string::npos) {
940                        // Gets login and protocol
941                        std::string::size_type loginPos = data.find(LOGINSTR, accPos + AIMICQACCSTR.size());
942                        std::string login = data.substr(loginPos + LOGINSTR.size(),
943                                data.find("</login>", loginPos) - loginPos - LOGINSTR.size());
944                        bool beginsWithDigit = (String(login.substr(0, 1)).toInteger() != 0);
945                        EnumIMProtocol::IMProtocol protocol = EnumIMProtocol::IMProtocolAIM;
946                        if (beginsWithDigit) {
947                                protocol = EnumIMProtocol::IMProtocolICQ;
948                        }
949                        ////
950
951                        // Changing protocol line
952                        data.replaceInRange(accPos, AIMICQACCSTR.size(), "AIM/ICQ", EnumIMProtocol::toString(protocol));
953                        ////
954
955                        // Inserting account in map for changing contactlist.xml
956                        accountMap[login] = protocol;
957                        ////
958
959                        accPos += AIMICQACCSTR.size();
960                        accPos = data.find(AIMICQACCSTR);
961                }
962
963                FileWriter oIMAccountsFile(userProfileDirectory + "imaccounts.xml");
964                oIMAccountsFile.write(data);
965                ////
966
967                //Replacing in contactlist.xml
968                FileReader iContactListFile(userProfileDirectory + "contactlist.xml");
969                iContactListFile.open();
970                data = iContactListFile.read();
971                static const std::string AIMICQIMSTR = "<im protocol=\"AIM/ICQ\">";
972                static const std::string ACCOUNTSTR = "<account>";
973
974                std::string::size_type imPos = data.find(AIMICQIMSTR);
975                while (imPos != std::string::npos) {
976                        std::string::size_type accountPos = data.find(ACCOUNTSTR, imPos + AIMICQIMSTR.size());
977                        std::string account = data.substr(accountPos + ACCOUNTSTR.size(),
978                                data.find("</account>", accountPos) - accountPos - ACCOUNTSTR.size());
979                        data.replaceInRange(imPos, AIMICQIMSTR.size(), "AIM/ICQ", EnumIMProtocol::toString(accountMap[account]));
980
981                        imPos += AIMICQIMSTR.size();
982                        imPos = data.find(AIMICQIMSTR);
983                }
984
985                FileWriter oContactListFile(userProfileDirectory + "contactlist.xml");
986                oContactListFile.write(data);
987                ////
988        }
989
990        return true;
991}
992
993bool ConfigImporter::importConfigFromV7toV8() {
994        StringList list = UserProfileHandler::getUserProfileNames();
995        std::map<std::string, EnumIMProtocol::IMProtocol> accountMap;
996
997        for (StringList::const_iterator it = list.begin();
998                it != list.end();
999                ++it) {
1000
1001                std::string userProfileDirectory = File::convertPathSeparators(Config::getConfigDir() + "profiles/" + *it + "/");
1002
1003                //Loading data
1004                FileReader iIMAccountsFile(userProfileDirectory + "imaccounts.xml");
1005                iIMAccountsFile.open();
1006                String data = iIMAccountsFile.read();
1007
1008                IMAccountList imAccountList;
1009                IMAccountListXMLSerializer1 imAccountListSerializer1(imAccountList);
1010                imAccountListSerializer1.unserialize(data);
1011
1012                FileReader iContactListFile(userProfileDirectory + "contactlist.xml");
1013                iContactListFile.open();
1014                data = iContactListFile.read();
1015
1016                UserProfile userProfile;
1017                ContactList contactList(userProfile);
1018                ContactListXMLSerializer1 contactListSerializer1(contactList, imAccountList);
1019                contactListSerializer1.unserialize(data);
1020
1021                // Look for IMAccount and Contact link to the IMAccount with login FAKE_LOGIN. It has been introduced by a previous importation step
1022                // to avoid the SSO request.
1023                for (IMAccountList::iterator ait = imAccountList.begin(); ait != imAccountList.end(); ++ait) {
1024                        if (((*ait).getProtocol() == EnumIMProtocol::IMProtocolWengo)
1025                                && ((*ait).getLogin() == FAKE_LOGIN)) {
1026
1027                                // Update contact links to this IMAccount (update UUID and remove CONTACT_PREFIX).
1028                                for (ContactList::Contacts::iterator cit = const_cast<ContactList::Contacts &>(contactList.getContacts()).begin();
1029                                        cit != contactList.getContacts().end();
1030                                        cit++) {
1031                                        IMContactSet & imContactSet = const_cast<IMContactSet &>((*cit).getIMContactSet());
1032                                        for (IMContactSet::iterator imit = imContactSet.begin();
1033                                                imit != imContactSet.end();
1034                                                imit++) {
1035                                                if (String((*imit).getContactId()).beginsWith(CONTACT_PREFIX)) {
1036                                                        const_cast<IMContact &>(*imit).setContactId((*imit).getContactId().substr(CONTACT_PREFIX.size()));
1037                                                        const_cast<IMContact &>(*imit).setIMAccount(&(*ait));
1038                                                }
1039                                        }
1040                                }
1041
1042                                // Removing the IMAccount
1043                                imAccountList.erase(ait);
1044                                break;
1045                        }
1046                }
1047                ////
1048
1049                IMAccountListXMLSerializer lastIMAccountListSerializer(imAccountList);
1050                data = lastIMAccountListSerializer.serialize();
1051                FileWriter oIMAccountsFile(userProfileDirectory + "imaccounts.xml");
1052                oIMAccountsFile.write(data);
1053
1054                ContactListXMLSerializer lastContactListSerializer(contactList, imAccountList);
1055                data = lastContactListSerializer.serialize();
1056                FileWriter oContactListFile(userProfileDirectory + "contactlist.xml");
1057                oContactListFile.write(data);
1058                ////   
1059        }
1060
1061        return true;
1062}
Note: See TracBrowser for help on using the repository browser.