~renatofilho/buteo-syncfw/more-verbose

« back to all changes in this revision

Viewing changes to libsyncprofile/ProfileManager.cpp

  • Committer: Sergey Gerasimenko
  • Date: 2010-06-29 12:51:21 UTC
  • Revision ID: git-v1:cd8dab07b102ac96752ece4f3cde5fc62697d717
Initial commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * This file is part of buteo-syncfw package
 
3
 *
 
4
 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
 
5
 *
 
6
 * Contact: Sateesh Kavuri <sateesh.kavuri@nokia.com>
 
7
 *
 
8
 * This library is free software; you can redistribute it and/or
 
9
 * modify it under the terms of the GNU Lesser General Public License
 
10
 * version 2.1 as published by the Free Software Foundation.
 
11
 *
 
12
 * This library is distributed in the hope that it will be useful, but
 
13
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 
15
 * Lesser General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU Lesser General Public
 
18
 * License along with this library; if not, write to the Free Software
 
19
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 
20
 * 02110-1301 USA
 
21
 *
 
22
 */
 
23
 
 
24
 
 
25
#include "ProfileManager.h"
 
26
 
 
27
#include <QDir>
 
28
#include <QFile>
 
29
#include <QTextStream>
 
30
#include <QDomDocument>
 
31
 
 
32
#include "ProfileFactory.h"
 
33
#include "ProfileEngineDefs.h"
 
34
 
 
35
#include "LogMacros.h"
 
36
#include "BtHelper.h"
 
37
 
 
38
namespace Buteo {
 
39
 
 
40
static const QString FORMAT_EXT = ".xml";
 
41
static const QString BACKUP_EXT = ".bak";
 
42
static const QString LOG_EXT = ".log";
 
43
static const QString LOG_DIRECTORY = "logs";
 
44
static const QString BT_PROFILE_TEMPLATE("bt_template");
 
45
 
 
46
const QString ProfileManager::DEFAULT_PRIMARY_PROFILE_PATH =
 
47
    QDir::homePath() + "/.sync/profiles";
 
48
const QString ProfileManager::DEFAULT_SECONDARY_PROFILE_PATH =
 
49
    "/etc/sync/profiles";
 
50
 
 
51
// Private implementation class for ProfileManager.
 
52
class ProfileManagerPrivate
 
53
{
 
54
public:
 
55
    ProfileManagerPrivate(const QString &aPrimaryPath,
 
56
                          const QString &aSecondaryPath);
 
57
 
 
58
    /*! \brief Loads a profile from persistent storage.
 
59
     *
 
60
     * \param aName Name of the profile to load.
 
61
     * \param aType Type of the profile to load.
 
62
     * \return The loaded profile. 0 if the profile was not found.
 
63
     */
 
64
    Profile *load(const QString &aName, const QString &aType);
 
65
 
 
66
    /*! \brief Loads the synchronization log associated with the given profile.
 
67
     *
 
68
     * \param aProfileName Name of the sync profile whose log shall be loaded.
 
69
     * \return The loaded log. 0 if the log was not found.
 
70
     */
 
71
    SyncLog *loadLog(const QString &aProfileName);
 
72
 
 
73
    bool parseFile(const QString &aPath, QDomDocument &aDoc);
 
74
 
 
75
    void restoreBackupIfFound(const QString &aProfilePath,
 
76
        const QString &aBackupPath);
 
77
 
 
78
    QDomDocument constructProfileDocument(const Profile &aProfile);
 
79
 
 
80
    bool writeProfileFile(const QString &aProfilePath, const QDomDocument &aDoc);
 
81
 
 
82
    QString findProfileFile(const QString &aName, const QString &aType);
 
83
 
 
84
    bool createBackup(const QString &aProfilePath, const QString &aBackupPath);
 
85
 
 
86
    bool matchProfile(const Profile &aProfile,
 
87
        const ProfileManager::SearchCriteria &aCriteria);
 
88
 
 
89
    bool matchKey(const Profile &aProfile,
 
90
        const ProfileManager::SearchCriteria &aCriteria);
 
91
 
 
92
    // Primary path for profiles.
 
93
    QString iPrimaryPath;
 
94
 
 
95
    // Secondary path for profiles.
 
96
    QString iSecondaryPath;
 
97
 
 
98
   
 
99
};
 
100
 
 
101
}
 
102
 
 
103
using namespace Buteo;
 
104
 
 
105
ProfileManagerPrivate::ProfileManagerPrivate(const QString &aPrimaryPath,
 
106
                                             const QString &aSecondaryPath)
 
107
:   iPrimaryPath(aPrimaryPath),
 
108
    iSecondaryPath(aSecondaryPath)
 
109
{
 
110
    if (iPrimaryPath.endsWith(QDir::separator()))
 
111
    {
 
112
        iPrimaryPath.chop(1);
 
113
    } // no else
 
114
    if (iSecondaryPath.endsWith(QDir::separator()))
 
115
    {
 
116
        iSecondaryPath.chop(1);
 
117
    } // no else
 
118
 
 
119
    LOG_DEBUG("Primary profile path set to" << iPrimaryPath);
 
120
    LOG_DEBUG("Secondary profile path set to" << iSecondaryPath);
 
121
}
 
122
 
 
123
Profile *ProfileManagerPrivate::load(const QString &aName, const QString &aType)
 
124
{
 
125
    QString profilePath = findProfileFile(aName, aType);
 
126
    QString backupProfilePath = profilePath + BACKUP_EXT;
 
127
 
 
128
    QDomDocument doc;
 
129
    Profile* profile = 0;
 
130
 
 
131
    restoreBackupIfFound(profilePath, backupProfilePath);
 
132
 
 
133
    if (parseFile(profilePath, doc))
 
134
    {
 
135
        ProfileFactory pf;
 
136
        profile = pf.createProfile(doc.documentElement());
 
137
 
 
138
        if (QFile::exists(backupProfilePath))
 
139
        {
 
140
            QFile::remove(backupProfilePath);
 
141
        }
 
142
    }
 
143
    else {
 
144
        LOG_WARNING("Failed to load profile:" << aName);
 
145
    }
 
146
        
 
147
    return profile;    
 
148
}
 
149
 
 
150
SyncLog *ProfileManagerPrivate::loadLog(const QString &aProfileName)
 
151
{
 
152
    QString fileName = iPrimaryPath + QDir::separator() + Profile::TYPE_SYNC + QDir::separator() +
 
153
        LOG_DIRECTORY + QDir::separator() + aProfileName + LOG_EXT + FORMAT_EXT;
 
154
 
 
155
    if (!QFile::exists(fileName))
 
156
    {
 
157
        LOG_DEBUG("No sync log found for profile:" << aProfileName);
 
158
        return 0;
 
159
    } // no else
 
160
 
 
161
    QFile file(fileName);
 
162
    if (!file.open(QIODevice::ReadOnly))
 
163
    {
 
164
        LOG_WARNING("Failed to open sync log file for reading:"
 
165
            << file.fileName());
 
166
        return 0;
 
167
    } // no else
 
168
 
 
169
    QDomDocument doc;
 
170
    if (!doc.setContent(&file)) {
 
171
        file.close();
 
172
        LOG_WARNING("Failed to parse XML from sync log file:"
 
173
            << file.fileName());
 
174
        return 0;
 
175
    } // no else
 
176
    file.close();
 
177
 
 
178
    return new SyncLog(doc.documentElement());
 
179
}
 
180
 
 
181
bool ProfileManagerPrivate::matchProfile(const Profile &aProfile,
 
182
    const ProfileManager::SearchCriteria &aCriteria)
 
183
{
 
184
    bool matched = false;
 
185
 
 
186
    const Profile *testProfile = &aProfile;
 
187
    if (!aCriteria.iSubProfileName.isEmpty())
 
188
    {
 
189
        // Sub-profile name was given, request a sub-profile with a
 
190
        // matching name and type.
 
191
        testProfile = aProfile.subProfile(aCriteria.iSubProfileName,
 
192
            aCriteria.iSubProfileType);
 
193
 
 
194
        if (testProfile != 0)
 
195
        {
 
196
            matched = matchKey(*testProfile, aCriteria);
 
197
        }
 
198
        else
 
199
        {
 
200
            if (aCriteria.iType == ProfileManager::SearchCriteria::NOT_EXISTS)
 
201
            {
 
202
                matched = true;
 
203
            }
 
204
            else
 
205
            {
 
206
                matched = false;
 
207
            }
 
208
        }
 
209
    }
 
210
    else if (!aCriteria.iSubProfileType.isEmpty())
 
211
    {
 
212
        // Sub-profile name was empty, but type was given. Get all
 
213
        // sub-profiles with the matching type.
 
214
        QStringList subProfileNames =
 
215
            aProfile.subProfileNames(aCriteria.iSubProfileType);
 
216
        if (!subProfileNames.isEmpty())
 
217
        {
 
218
            matched = false;
 
219
            foreach (const QString &subProfileName, subProfileNames)
 
220
            {
 
221
                testProfile = aProfile.subProfile(subProfileName,
 
222
                    aCriteria.iSubProfileType);
 
223
                if (testProfile != 0 && matchKey(*testProfile, aCriteria))
 
224
                {
 
225
                    matched = true;
 
226
                    break;
 
227
                }
 
228
            }
 
229
        }
 
230
        else
 
231
        {
 
232
            if (aCriteria.iType == ProfileManager::SearchCriteria::NOT_EXISTS)
 
233
            {
 
234
                matched = true;
 
235
            }
 
236
            else
 
237
            {
 
238
                matched = false;
 
239
            }
 
240
        }
 
241
    }
 
242
    else
 
243
    {
 
244
        matched = matchKey(aProfile, aCriteria);
 
245
    }
 
246
 
 
247
    return matched;
 
248
}
 
249
 
 
250
bool ProfileManagerPrivate::matchKey(const Profile &aProfile,
 
251
    const ProfileManager::SearchCriteria &aCriteria)
 
252
{
 
253
    bool matched = false;
 
254
 
 
255
    if (!aCriteria.iKey.isEmpty())
 
256
    {
 
257
        // Key name was given, get a key with matching name.
 
258
        QString value = aProfile.key(aCriteria.iKey);
 
259
 
 
260
        if (value.isNull())
 
261
        {
 
262
            if (aCriteria.iType == ProfileManager::SearchCriteria::NOT_EXISTS ||
 
263
                aCriteria.iType == ProfileManager::SearchCriteria::NOT_EQUAL)
 
264
            {
 
265
                matched = true;
 
266
            }
 
267
            else
 
268
            {
 
269
                matched = false;
 
270
            }
 
271
        }
 
272
        else
 
273
        {
 
274
            switch (aCriteria.iType)
 
275
            {
 
276
            case ProfileManager::SearchCriteria::EXISTS:
 
277
                matched = true;
 
278
                break;
 
279
 
 
280
            case ProfileManager::SearchCriteria::NOT_EXISTS:
 
281
                matched = false;
 
282
                break;
 
283
 
 
284
            case ProfileManager::SearchCriteria::EQUAL:
 
285
                matched = (value == aCriteria.iValue);
 
286
                break;
 
287
 
 
288
            case ProfileManager::SearchCriteria::NOT_EQUAL:
 
289
                matched = (value != aCriteria.iValue);
 
290
                break;
 
291
 
 
292
            default:
 
293
                matched = false;
 
294
                break;
 
295
            }
 
296
        }
 
297
    }
 
298
    else
 
299
    {
 
300
        if (aCriteria.iType == ProfileManager::SearchCriteria::NOT_EXISTS)
 
301
        {
 
302
            matched = false;
 
303
        }
 
304
        else
 
305
        {
 
306
            matched = true;
 
307
        }
 
308
    }
 
309
 
 
310
    return matched;
 
311
}
 
312
 
 
313
ProfileManager::SearchCriteria::SearchCriteria()
 
314
 :  iType(ProfileManager::SearchCriteria::EQUAL)
 
315
{
 
316
}
 
317
 
 
318
ProfileManager::SearchCriteria::SearchCriteria(const SearchCriteria &aSource)
 
319
 :  iType(aSource.iType),
 
320
    iSubProfileName(aSource.iSubProfileName),
 
321
    iSubProfileType(aSource.iSubProfileType),
 
322
    iKey(aSource.iKey),
 
323
    iValue(aSource.iValue)
 
324
{
 
325
}
 
326
 
 
327
ProfileManager::ProfileManager(const QString &aPrimaryPath,
 
328
                               const QString &aSecondaryPath)
 
329
:   d_ptr(new ProfileManagerPrivate(aPrimaryPath, aSecondaryPath))
 
330
{
 
331
}
 
332
 
 
333
ProfileManager::~ProfileManager()
 
334
{
 
335
    delete d_ptr;
 
336
    d_ptr = 0;
 
337
}
 
338
 
 
339
Profile *ProfileManager::profile(const QString &aName, const QString &aType)
 
340
{
 
341
    return d_ptr->load(aName, aType);
 
342
}
 
343
 
 
344
SyncProfile *ProfileManager::syncProfile(const QString &aName)
 
345
{
 
346
    Profile *p = profile(aName, Profile::TYPE_SYNC);
 
347
    SyncProfile *syncProfile = 0;
 
348
    if (p != 0 && p->type() == Profile::TYPE_SYNC)
 
349
    {
 
350
        // RTTI is not allowed, use static_cast. Should be safe, because
 
351
        // type is verified.
 
352
        syncProfile = static_cast<SyncProfile*>(p);
 
353
 
 
354
        // Load and merge all sub-profiles.
 
355
        expand(*syncProfile);
 
356
 
 
357
        // Load sync log. If not found, create an empty log.
 
358
        if (syncProfile->log() == 0)
 
359
        {
 
360
            SyncLog *log = d_ptr->loadLog(aName);
 
361
            if (0 == log)
 
362
            {
 
363
                log = new SyncLog(aName);
 
364
            } // no else
 
365
            syncProfile->setLog(log);
 
366
        } // no else
 
367
    } // no else
 
368
 
 
369
    return syncProfile;
 
370
}
 
371
 
 
372
QStringList ProfileManager::profileNames(const QString &aType)
 
373
{
 
374
    // Search for all profile files from the primary directory
 
375
    QStringList names;
 
376
    QString nameFilter = QString("*") + FORMAT_EXT;
 
377
    {
 
378
        QDir dir(d_ptr->iPrimaryPath + QDir::separator() + aType);
 
379
        QFileInfoList fileInfoList = dir.entryInfoList(QStringList(nameFilter),
 
380
            QDir::Files | QDir::NoSymLinks);
 
381
        foreach (const QFileInfo &fileInfo, fileInfoList)
 
382
        {
 
383
            names.append(fileInfo.completeBaseName());
 
384
        }
 
385
    }
 
386
 
 
387
    // Search for all profile files from the secondary directory
 
388
    {
 
389
        QDir dir(d_ptr->iSecondaryPath + QDir::separator() + aType);
 
390
        QFileInfoList fileInfoList = dir.entryInfoList(QStringList(nameFilter),
 
391
            QDir::Files | QDir::NoSymLinks);
 
392
        foreach (const QFileInfo &fileInfo, fileInfoList)
 
393
        {
 
394
            // Add only if the list does not yet contain the name.
 
395
            QString profileName = fileInfo.completeBaseName();
 
396
            if (!names.contains(profileName))
 
397
            {
 
398
                names.append(profileName);
 
399
            }
 
400
        }
 
401
    }
 
402
 
 
403
    return names;
 
404
}
 
405
 
 
406
QList<SyncProfile*> ProfileManager::allSyncProfiles()
 
407
{
 
408
    QList<SyncProfile*> profiles;
 
409
 
 
410
    QStringList names = profileNames(Profile::TYPE_SYNC);
 
411
    foreach (const QString &name, names)
 
412
    {
 
413
        SyncProfile *p = syncProfile(name);
 
414
        if (p != 0)
 
415
        {
 
416
            profiles.append(p);
 
417
        } // no else
 
418
    }
 
419
 
 
420
    return profiles;
 
421
}
 
422
 
 
423
QList<SyncProfile*> ProfileManager::allVisibleSyncProfiles()
 
424
{
 
425
    QList<SyncProfile*> profiles = allSyncProfiles();
 
426
    QList<SyncProfile*> visibleProfiles;
 
427
    foreach (SyncProfile *p, profiles)
 
428
    {
 
429
        if (!p->isHidden())
 
430
        {
 
431
            visibleProfiles.append(p);
 
432
        }
 
433
        else
 
434
        {
 
435
            delete p;
 
436
        }
 
437
    }
 
438
 
 
439
    return visibleProfiles;
 
440
}
 
441
 
 
442
QList<SyncProfile*> ProfileManager::getSyncProfilesByData(
 
443
        const QString &aSubProfileName,
 
444
        const QString &aSubProfileType,
 
445
        const QString &aKey, const QString &aValue)
 
446
{
 
447
    QList<SyncProfile*> allProfiles = allSyncProfiles();
 
448
    QList<SyncProfile*> matchingProfiles;
 
449
 
 
450
    foreach (SyncProfile *profile, allProfiles)
 
451
    {
 
452
        Profile *testProfile = profile;
 
453
        if (!aSubProfileName.isEmpty())
 
454
        {
 
455
            // Sub-profile name was given, request a sub-profile with a
 
456
            // matching name and type.
 
457
            testProfile = profile->subProfile(aSubProfileName, aSubProfileType);
 
458
        }
 
459
        else if (!aSubProfileType.isEmpty())
 
460
        {
 
461
            // Sub-profile name was empty, but type was given. Get the first
 
462
            // sub-profile with the matching type.
 
463
            QStringList subProfileNames =
 
464
                profile->subProfileNames(aSubProfileType);
 
465
            if (!subProfileNames.isEmpty())
 
466
            {
 
467
                testProfile = profile->subProfile(subProfileNames.first(),
 
468
                    aSubProfileType);
 
469
            }
 
470
            else
 
471
            {
 
472
                testProfile = 0;
 
473
            }
 
474
        }
 
475
 
 
476
        if (0 == testProfile) // Sub-profile was not found.
 
477
        {
 
478
            delete profile;
 
479
            profile = 0;
 
480
            continue; // Not a match, continue with next profile.
 
481
        }
 
482
 
 
483
        if (!aKey.isEmpty())
 
484
        {
 
485
            // Key name was given, get a key with matching name.
 
486
            QString value = testProfile->key(aKey);
 
487
            if (value.isNull() || // Key was not found.
 
488
                (!aValue.isEmpty() && (value != aValue))) // Value didn't match
 
489
            {
 
490
                delete profile;
 
491
                profile = 0;
 
492
                continue; // Not a match, continue with next profile.
 
493
            } // no else
 
494
        } // no else
 
495
 
 
496
        // Match, add profile to the list to be returned.
 
497
        matchingProfiles.append(profile);
 
498
    }
 
499
 
 
500
    return matchingProfiles;
 
501
}
 
502
 
 
503
QList<SyncProfile*> ProfileManager::getSyncProfilesByData(
 
504
    const QList<SearchCriteria> &aCriteria)
 
505
{
 
506
    QList<SyncProfile*> allProfiles = allSyncProfiles();
 
507
    QList<SyncProfile*> matchingProfiles;
 
508
 
 
509
    foreach (SyncProfile *profile, allProfiles)
 
510
    {
 
511
        bool matched = true;
 
512
        if (profile == 0)
 
513
            continue;
 
514
 
 
515
        foreach (const SearchCriteria &criteria, aCriteria)
 
516
        {
 
517
            if (!d_ptr->matchProfile(*profile, criteria))
 
518
            {
 
519
                matched = false;
 
520
                break;
 
521
            }
 
522
        }
 
523
 
 
524
        if (matched)
 
525
        {
 
526
            matchingProfiles.append(profile);
 
527
        }
 
528
        else
 
529
        {
 
530
            delete profile;
 
531
            profile = 0;
 
532
        }
 
533
    }
 
534
 
 
535
    return matchingProfiles;
 
536
}
 
537
 
 
538
QList<SyncProfile*> ProfileManager::getSyncProfilesByStorage(
 
539
    const QString &aStorageName, bool aStorageMustBeEnabled)
 
540
{
 
541
    QList<SearchCriteria> criteriaList;
 
542
 
 
543
    // Require that the profile is not disabled.
 
544
    // Profile is enabled by default. Comparing with enabled = true would
 
545
    // not work, because the key may not exist at all, even if the profile
 
546
    // is enabled.
 
547
    SearchCriteria profileEnabled;
 
548
    profileEnabled.iType = SearchCriteria::NOT_EQUAL;
 
549
    profileEnabled.iKey = KEY_ENABLED;
 
550
    profileEnabled.iValue = BOOLEAN_FALSE;
 
551
    criteriaList.append(profileEnabled);
 
552
 
 
553
    // Profile must not be hidden.
 
554
    SearchCriteria profileVisible;
 
555
    profileVisible.iType = SearchCriteria::NOT_EQUAL;
 
556
    profileVisible.iKey = KEY_HIDDEN;
 
557
    profileVisible.iValue = BOOLEAN_TRUE;
 
558
    criteriaList.append(profileVisible);
 
559
 
 
560
    // Online service.
 
561
    SearchCriteria onlineService;
 
562
    onlineService.iType = SearchCriteria::EQUAL;
 
563
    onlineService.iSubProfileType = Profile::TYPE_SERVICE;
 
564
    // Service profile name is left empty. Key value is matched with all
 
565
    // found service sub-profiles, though there should be only one.
 
566
    onlineService.iKey = KEY_DESTINATION_TYPE;
 
567
    onlineService.iValue = VALUE_ONLINE;
 
568
    criteriaList.append(onlineService);
 
569
 
 
570
    // Storage must be supported.
 
571
    SearchCriteria storageSupported;
 
572
    storageSupported.iSubProfileName = aStorageName;
 
573
    storageSupported.iSubProfileType = Profile::TYPE_STORAGE;
 
574
    if (aStorageMustBeEnabled)
 
575
    {
 
576
        // Storage must be enabled also. Storages are disabled by default,
 
577
        // so we can compare with enabled = true.
 
578
        storageSupported.iType = SearchCriteria::EQUAL;
 
579
        storageSupported.iKey = KEY_ENABLED;
 
580
        storageSupported.iValue = BOOLEAN_TRUE;
 
581
    }
 
582
    else
 
583
    {
 
584
        // Existence of the storage sub-profile is sufficient.
 
585
        storageSupported.iType = SearchCriteria::EXISTS;
 
586
    }
 
587
    criteriaList.append(storageSupported);
 
588
 
 
589
    return getSyncProfilesByData(criteriaList);
 
590
}
 
591
 
 
592
 
 
593
bool ProfileManager::save(const Profile &aProfile)
 
594
{
 
595
    QDomDocument doc = d_ptr->constructProfileDocument(aProfile);
 
596
    if (doc.isNull())
 
597
    {
 
598
        LOG_WARNING("No profile data to write");
 
599
        return false;
 
600
    }
 
601
 
 
602
    // Create path for the new profile file.
 
603
    QDir dir;
 
604
    dir.mkpath(d_ptr->iPrimaryPath + QDir::separator() + aProfile.type());
 
605
    QString profilePath(d_ptr->iPrimaryPath + QDir::separator() +
 
606
        aProfile.type() + QDir::separator() + aProfile.name() + FORMAT_EXT);
 
607
 
 
608
    // Create a backup of the existing profile file.
 
609
    QString oldProfilePath = d_ptr->findProfileFile(aProfile.type(), aProfile.name());
 
610
    QString backupPath = profilePath + BACKUP_EXT;
 
611
 
 
612
    if (QFile::exists(oldProfilePath) &&
 
613
        !d_ptr->createBackup(oldProfilePath, backupPath))
 
614
    {
 
615
        LOG_WARNING("Failed to create profile backup");
 
616
    }
 
617
 
 
618
    bool profileWritten = false;
 
619
    if (d_ptr->writeProfileFile(profilePath, doc))
 
620
    {
 
621
        QFile::remove(backupPath);
 
622
        profileWritten = true;
 
623
    }
 
624
    else
 
625
    {
 
626
        LOG_WARNING("Failed to save profile:" << aProfile.name());
 
627
        profileWritten = false;
 
628
    }
 
629
 
 
630
    return profileWritten;
 
631
}
 
632
 
 
633
SyncProfile *ProfileManager::createTempSyncProfile (const QString &destAddress, bool &saveNewProfile)
 
634
{
 
635
        saveNewProfile = true;
 
636
        if (destAddress.contains("USB")) { //USB - PCSUite no requirement to save profile
 
637
                LOG_INFO("USB connect - pc");
 
638
                saveNewProfile = false;
 
639
                return new SyncProfile(destAddress);
 
640
        }
 
641
                
 
642
        BtHelper btHelp(destAddress);
 
643
        QMap <QString , QVariant> mapVal = btHelp.getDeviceProperties();
 
644
        uint classType = mapVal.value("Class").toInt(); 
 
645
        uint pcsuiteClass = 0x100; //Major Device Class - Computer!
 
646
 
 
647
        if (classType & pcsuiteClass) {
 
648
                LOG_INFO("Device major class is Computer"); // not required to save profile 
 
649
                saveNewProfile = false;
 
650
                return new SyncProfile(destAddress);
 
651
        }
 
652
 
 
653
        QString profileName = mapVal.value("Name").toString();
 
654
        if (profileName.isEmpty()) {
 
655
                //Todo : What to show if name is empty !!
 
656
                //Fixes 171340
 
657
                profileName = QString ("qtn_sync_dest_name_device_default");
 
658
        }
 
659
        while (profileNames(Profile::TYPE_SYNC).contains(profileName)){
 
660
                profileName += "_";
 
661
        }
 
662
 
 
663
        
 
664
        LOG_INFO("Profile Name :" << profileName);
 
665
        SyncProfile *tProfile = syncProfile(BT_PROFILE_TEMPLATE);               
 
666
        Profile *service = tProfile->serviceProfile();
 
667
        if (service != 0) {
 
668
                tProfile->setName(profileName);
 
669
                tProfile->setEnabled(true);
 
670
                tProfile->setBoolKey("hidden", false);
 
671
                service->setKey(KEY_BT_ADDRESS, destAddress);
 
672
                service->setKey(KEY_BT_NAME, "deviceName");
 
673
         } else {
 
674
                 LOG_WARNING("No service profile, unable to update properties"); 
 
675
         }
 
676
 
 
677
        return tProfile;
 
678
}
 
679
 
 
680
 
 
681
void ProfileManager::enableStorages (Profile &aProfile, 
 
682
                QMap<QString , bool> &aStorageMap)
 
683
{
 
684
        
 
685
        QMapIterator<QString, bool> i(aStorageMap);
 
686
        LOG_INFO("ProfileManager::enableStorages");
 
687
        while (i.hasNext()) {
 
688
                i.next();
 
689
                Profile *profile = aProfile.subProfile(i.key(), Profile::TYPE_STORAGE);
 
690
                if (profile)
 
691
                        profile->setEnabled(i.value());
 
692
                else 
 
693
                        LOG_WARNING("No storage profile by key :" << i.key());
 
694
        }
 
695
        return ;
 
696
}
 
697
 
 
698
bool ProfileManager::remove(const QString &aName, const QString &aType)
 
699
{
 
700
    bool success = false;
 
701
    QString filePath = d_ptr->iPrimaryPath + QDir::separator() + aType + QDir::separator() + aName + FORMAT_EXT;
 
702
 
 
703
    // Try to load profile without expanding it. We need to check from the
 
704
    // profile data if the profile is protected before removing it.
 
705
    Profile *p = d_ptr->load(aName, aType);
 
706
    if (p)
 
707
    {
 
708
        if (!p->isProtected())
 
709
        {
 
710
            success = QFile::remove(filePath);
 
711
            if (success){
 
712
                    QString logFilePath = d_ptr->iPrimaryPath + QDir::separator() + aType + QDir::separator() +
 
713
                            LOG_DIRECTORY + QDir::separator() + aName + LOG_EXT + FORMAT_EXT;
 
714
                    success = QFile::remove(logFilePath);
 
715
            }
 
716
        }
 
717
        else
 
718
        {
 
719
            LOG_DEBUG( "Cannot remove protected profile:" << aName );
 
720
        }
 
721
        delete p;
 
722
        p = 0;
 
723
    }
 
724
    else
 
725
    {
 
726
        LOG_DEBUG( "Profile not found from the primary path, cannot remove:" << aName );
 
727
    }
 
728
 
 
729
    return success;
 
730
}
 
731
 
 
732
void ProfileManager::expand(Profile &aProfile)
 
733
{
 
734
    if (aProfile.isLoaded())
 
735
        return; // Already expanded.
 
736
 
 
737
    // Load and merge sub-profiles.
 
738
    int prevSubCount = 0;
 
739
    QList<Profile*> subProfiles = aProfile.allSubProfiles();
 
740
    int subCount = subProfiles.size();
 
741
    while (subCount > prevSubCount)
 
742
    {
 
743
        foreach (Profile *sub, subProfiles)
 
744
        {
 
745
            if (!sub->isLoaded())
 
746
            {
 
747
                Profile *loadedProfile = profile(sub->name(), sub->type());
 
748
                if (loadedProfile != 0)
 
749
                {
 
750
                    aProfile.merge(*loadedProfile);
 
751
                    delete loadedProfile;
 
752
                    loadedProfile = 0;
 
753
                }
 
754
                else
 
755
                {
 
756
                    // No separate profile file for the sub-profile.
 
757
                    LOG_DEBUG( "Referenced sub-profile not found:" <<
 
758
                        sub->name() );
 
759
                    LOG_DEBUG( "Referenced from:" << aProfile.name() <<
 
760
                        aProfile.type() );
 
761
                }
 
762
                sub->setLoaded(true);
 
763
            } // no else
 
764
        }
 
765
 
 
766
        // Load/merge may have created new sub-profile entries. Those need
 
767
        // to be loaded also. Loop if sub-profile count has changed.
 
768
        prevSubCount = subCount;
 
769
        subProfiles = aProfile.allSubProfiles();
 
770
        subCount = subProfiles.size();
 
771
    }
 
772
 
 
773
    aProfile.setLoaded(true);
 
774
}
 
775
 
 
776
bool ProfileManager::saveLog(const SyncLog &aLog)
 
777
{
 
778
    QDir dir;
 
779
    QString fullPath = d_ptr->iPrimaryPath + QDir::separator() + Profile::TYPE_SYNC + QDir::separator() +
 
780
        LOG_DIRECTORY;
 
781
    dir.mkpath(fullPath);
 
782
    QFile file(fullPath + QDir::separator() + aLog.profileName() + LOG_EXT + FORMAT_EXT);
 
783
 
 
784
    if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate))
 
785
    {
 
786
        LOG_WARNING("Failed to open sync log file for writing:"
 
787
            << file.fileName());
 
788
        return false;
 
789
    } // no else
 
790
 
 
791
    QDomDocument doc;
 
792
    QDomProcessingInstruction xmlHeading =
 
793
        doc.createProcessingInstruction("xml",
 
794
        "version=\"1.0\" encoding=\"UTF-8\"");
 
795
    doc.appendChild(xmlHeading);
 
796
 
 
797
    QDomElement root = aLog.toXml(doc);
 
798
    if (root.isNull())
 
799
    {
 
800
        LOG_WARNING("Failed to convert sync log to XML");
 
801
        return false;
 
802
    } // no else
 
803
 
 
804
    doc.appendChild(root);
 
805
 
 
806
    QTextStream outputStream(&file);
 
807
 
 
808
    outputStream << doc.toString(PROFILE_INDENT);
 
809
 
 
810
    file.close();
 
811
 
 
812
    return true;
 
813
}
 
814
 
 
815
void ProfileManager::saveRemoteTargetId(Profile &aProfile,const QString& aTargetId )
 
816
{
 
817
        LOG_DEBUG("saveRemoteTargetId :" << aTargetId);
 
818
        aProfile.setKey (KEY_REMOTE_ID, aTargetId);
 
819
        save (aProfile);
 
820
}
 
821
 
 
822
 
 
823
bool ProfileManager::rename(const QString &aName, const QString &aNewName)
 
824
{
 
825
    bool ret = false;
 
826
    // Rename the sync profile
 
827
    QString source = d_ptr->iPrimaryPath + QDir::separator() +  Profile::TYPE_SYNC + QDir::separator() +
 
828
                     aName + FORMAT_EXT;
 
829
    QString destination = d_ptr->iPrimaryPath + QDir::separator() + Profile::TYPE_SYNC + QDir::separator() +
 
830
                          aNewName + FORMAT_EXT;
 
831
    ret = QFile::rename(source, destination);
 
832
    if(true == ret)
 
833
    {
 
834
        // Rename the sync log
 
835
        QString sourceLog = d_ptr->iPrimaryPath + QDir::separator() +  Profile::TYPE_SYNC + QDir::separator() +
 
836
                            LOG_DIRECTORY + QDir::separator() + aName + LOG_EXT  + FORMAT_EXT;
 
837
        QString destinationLog = d_ptr->iPrimaryPath + QDir::separator() +  Profile::TYPE_SYNC + QDir::separator() +
 
838
                            LOG_DIRECTORY + QDir::separator() + aNewName + LOG_EXT  + FORMAT_EXT;
 
839
        ret = QFile::rename(sourceLog, destinationLog);
 
840
        if(false == ret)
 
841
        {
 
842
            // Roll back the earlier rename
 
843
            QFile::rename(destination, source);
 
844
        }
 
845
    }
 
846
    if(false == ret)
 
847
    {
 
848
        LOG_WARNING("Failed to rename profile" << aName);
 
849
    }
 
850
    return ret;
 
851
}
 
852
 
 
853
bool ProfileManager::saveSyncResults(QString aProfileName,
 
854
                                     const SyncResults &aResults)
 
855
{
 
856
    FUNCTION_CALL_TRACE;
 
857
    bool success = false;
 
858
 
 
859
    SyncLog *log = d_ptr->loadLog(aProfileName);
 
860
    if (!log)
 
861
    {
 
862
        // No log yet, create new.
 
863
        log = new SyncLog(aProfileName);
 
864
    } // no else
 
865
 
 
866
    if (log)
 
867
    {
 
868
        log->addResults(aResults);
 
869
        success = saveLog(*log);
 
870
        delete log;
 
871
        log = 0;
 
872
    } // no else
 
873
 
 
874
    return success;
 
875
}
 
876
 
 
877
bool ProfileManagerPrivate::parseFile(const QString &aPath, QDomDocument &aDoc)
 
878
{
 
879
    bool parsingOk = false;
 
880
    
 
881
    if (QFile::exists(aPath))
 
882
    {
 
883
        QFile file(aPath);
 
884
 
 
885
        if (file.open(QIODevice::ReadOnly))
 
886
        {
 
887
            parsingOk = aDoc.setContent(&file);
 
888
            file.close();
 
889
 
 
890
            if (!parsingOk)
 
891
            {
 
892
                LOG_WARNING("Failed to parse profile XML: " << aPath);
 
893
            }
 
894
        }
 
895
        else {
 
896
            LOG_WARNING("Failed to open profile file for reading:" << aPath);
 
897
        }
 
898
    }
 
899
    else
 
900
    {
 
901
        LOG_WARNING("Profile file not found:" << aPath);
 
902
    }
 
903
 
 
904
 
 
905
 
 
906
    return parsingOk;
 
907
}
 
908
 
 
909
QDomDocument ProfileManagerPrivate::constructProfileDocument(const Profile &aProfile)
 
910
{
 
911
    QDomDocument doc;
 
912
    QDomElement root = aProfile.toXml(doc);
 
913
    
 
914
    if (root.isNull())
 
915
    {
 
916
        LOG_WARNING("Failed to convert profile to XML");
 
917
    }
 
918
    else
 
919
    {
 
920
        QDomProcessingInstruction xmlHeading =
 
921
                doc.createProcessingInstruction("xml",
 
922
                "version=\"1.0\" encoding=\"UTF-8\"");
 
923
        
 
924
        doc.appendChild(xmlHeading);
 
925
        doc.appendChild(root);
 
926
    }
 
927
 
 
928
    return doc;
 
929
}
 
930
 
 
931
bool ProfileManagerPrivate::writeProfileFile(const QString &aProfilePath,
 
932
    const QDomDocument &aDoc)
 
933
{   
 
934
    QFile file(aProfilePath);
 
935
    bool profileWritten = false;
 
936
 
 
937
    if (file.open(QIODevice::WriteOnly | QIODevice::Truncate))
 
938
    {
 
939
        QTextStream outputStream(&file);
 
940
        outputStream << aDoc.toString(PROFILE_INDENT);
 
941
        file.close();
 
942
        profileWritten = true;
 
943
    }
 
944
    else
 
945
    {
 
946
        LOG_WARNING("Failed to open profile file for writing:" << aProfilePath);
 
947
        profileWritten = false;
 
948
    }
 
949
    
 
950
    return profileWritten;
 
951
}
 
952
 
 
953
void ProfileManagerPrivate::restoreBackupIfFound(const QString &aProfilePath,
 
954
    const QString &aBackupPath)
 
955
{
 
956
    if (QFile::exists(aBackupPath))
 
957
    {
 
958
        LOG_WARNING("Profile backup file found. The actual profile may be corrupted.");
 
959
 
 
960
        QDomDocument doc;
 
961
        if (parseFile(aBackupPath, doc))
 
962
        {
 
963
            LOG_DEBUG("Restoring profile from backup");
 
964
            QFile::remove(aProfilePath);
 
965
            QFile::copy(aBackupPath, aProfilePath);
 
966
        }
 
967
        else
 
968
        {
 
969
            LOG_WARNING("Failed to parse backup file");
 
970
            LOG_DEBUG("Removing backup file");
 
971
            QFile::remove(aBackupPath);
 
972
        }
 
973
    }
 
974
}
 
975
 
 
976
bool ProfileManagerPrivate::createBackup(const QString &aProfilePath,
 
977
    const QString &aBackupPath)
 
978
{
 
979
    return QFile::copy(aProfilePath, aBackupPath);
 
980
}
 
981
 
 
982
QString ProfileManagerPrivate::findProfileFile(const QString &aName, const QString &aType)
 
983
{
 
984
    QString fileName = aType + QDir::separator() + aName + FORMAT_EXT;
 
985
    QString primaryPath = iPrimaryPath + QDir::separator() + fileName;
 
986
    QString secondaryPath = iSecondaryPath + QDir::separator() + fileName;
 
987
 
 
988
    if (QFile::exists(primaryPath))
 
989
    {
 
990
        return primaryPath;
 
991
    }
 
992
    else if (!QFile::exists(secondaryPath))
 
993
    {
 
994
        return primaryPath;
 
995
    }
 
996
    else
 
997
    {
 
998
        return secondaryPath;
 
999
    }
 
1000
}