~ubuntu-branches/ubuntu/trusty/syncevolution/trusty-proposed

« back to all changes in this revision

Viewing changes to src/syncevo/SyncConfig.h

  • Committer: Bazaar Package Importer
  • Author(s): Tino Keitel
  • Date: 2011-07-20 16:02:02 UTC
  • mfrom: (3.1.7 experimental)
  • Revision ID: james.westby@ubuntu.com-20110720160202-e8uf7ogw4vh0q0f3
Tags: 1.1.99.5a-1
* New upstream version 1.1.99.5a, first release candiate for 1.2
* Added python-openssl dependency, the HTTP server needs it for HTTPS support
* Added versioned dependency on libsynthesis0 to get required features
* Fixed .orig.tar.gz generation in get-orig-source target
* Added myself to Uploaders:, thanks to David for sponsoring
* Use updated upstream tag for source package generation
* Removed 0001-Replace-with-in-call-to-PKG_CHECK_MODULES.patch, fixed upstream
* Renamed NEWS.Debian to NEWS so that it is actually used
* Updated NEWS for 1.1.99.5a

Show diffs side-by-side

added added

removed removed

Lines of Context:
46
46
 * @{
47
47
 */
48
48
 
 
49
/**
 
50
 * The SyncEvolution configuration is versioned, so that incompatible
 
51
 * changes to the on-disk config and files can be made more reliably.
 
52
 *
 
53
 * The on-disk configuration is versioned at three levels:
 
54
 * - root level
 
55
 * - context
 
56
 * - peer
 
57
 *
 
58
 * This granularity allows migrating individual peers, contexts or
 
59
 * everything to a new format.
 
60
 *
 
61
 * For each of these levels, two numbers are stored on disk and
 
62
 * hard-coded in the binary:
 
63
 * - current version = incremented each time the format is extended
 
64
 * - minimum version = set to current version each time a backwards
 
65
 *                     incompatible change is made
 
66
 *
 
67
 * This mirrors the libtool library versioning.
 
68
 *
 
69
 * Reading must check that the on-disk minimum version is <= the
 
70
 * binary's current version. Otherwise the config is too recent to
 
71
 * be used.
 
72
 *
 
73
 * Writing will bump minimum and current version on disk to the
 
74
 * versions in the binary. It will never decrease versions. This
 
75
 * works when the more recent format adds information that can
 
76
 * be safely ignored by older releases. If that is not possible,
 
77
 * then the "minimum" version must be increased to prevent older
 
78
 * releases from using the config.
 
79
 *
 
80
 * If bumping the versions increases the minimum version
 
81
 * beyond the version supported by the release which wrote the config,
 
82
 * that release will no longer work. Experimental releases will throw
 
83
 * an error and users must explicitly migrate to the current
 
84
 * format. Stable releases will migrate automatically.
 
85
 *
 
86
 * The on-disks current version can be checked to determine how to
 
87
 * handle it. It may be more obvious to simple check for the existence
 
88
 * of certain properties (that's how this was handled before the
 
89
 * introduction of versioning).
 
90
 *
 
91
 * Here are some simple rules for handling the versions:
 
92
 * - increase CUR version when adding new properties or files
 
93
 * - set MIN to CUR when it is not safe that older releases
 
94
 *   read and write a config with the current format
 
95
 *
 
96
 * SyncEvolution < 1.2 had no versioning. It's format is 0.
 
97
 * SyncEvolution 1.2:
 
98
 * - config peer min/cur version 1, because
 
99
 *   of modified libsynthesis binfiles and
 
100
 * - context min/cur version 1, because
 
101
 *   evolutionsource->database, evolutionuser/password->databaseUser/Password
 
102
 */
 
103
static const int CONFIG_ROOT_MIN_VERSION = 0;
 
104
static const int CONFIG_ROOT_CUR_VERSION = 0;
 
105
static const int CONFIG_CONTEXT_MIN_VERSION = 1;
 
106
static const int CONFIG_CONTEXT_CUR_VERSION = 1;
 
107
static const int CONFIG_PEER_MIN_VERSION = 1;
 
108
static const int CONFIG_PEER_CUR_VERSION = 1;
 
109
 
 
110
enum ConfigLevel {
 
111
    CONFIG_LEVEL_ROOT,      /**< = GLOBAL_SHARING */
 
112
    CONFIG_LEVEL_CONTEXT,   /**< = SOURCE_SET_SHARING */
 
113
    CONFIG_LEVEL_PEER,      /**< = NO_SHARING */
 
114
    CONFIG_LEVEL_MAX
 
115
};
 
116
 
 
117
std::string ConfigLevel2String(ConfigLevel level);
 
118
 
 
119
enum ConfigLimit {
 
120
    CONFIG_MIN_VERSION,
 
121
    CONFIG_CUR_VERSION,
 
122
    CONFIG_VERSION_MAX
 
123
};
 
124
 
 
125
extern int ConfigVersions[CONFIG_LEVEL_MAX][CONFIG_VERSION_MAX];
 
126
 
49
127
class SyncSourceConfig;
50
128
typedef SyncSourceConfig PersistentSyncSourceConfig;
51
129
class ConfigTree;
56
134
/** name of the per-source admin data property */
57
135
extern const char *const SourceAdminDataName;
58
136
 
 
137
/** simplified creation of string lists: InitList("foo") + "bar" + ... */
 
138
template<class T> class InitList : public list<T> {
 
139
 public:
 
140
    InitList() {}
 
141
    InitList(const T &initialValue) {
 
142
        list<T>::push_back(initialValue);
 
143
    }
 
144
    InitList &operator + (const T &rhs) {
 
145
        list<T>::push_back(rhs);
 
146
        return *this;
 
147
    }
 
148
    InitList &operator += (const T &rhs) {
 
149
        list<T>::push_back(rhs);
 
150
        return *this;
 
151
    }
 
152
};
 
153
typedef InitList<string> Aliases;
 
154
typedef InitList<Aliases> Values;
 
155
 
 
156
enum PropertyType {
 
157
    /** sync properties occur once per config */
 
158
    SYNC_PROPERTY_TYPE,
 
159
    /** source properties occur once per source in each config */
 
160
    SOURCE_PROPERTY_TYPE,
 
161
    /** exact type is unknown */
 
162
    UNKNOWN_PROPERTY_TYPE
 
163
};
 
164
 
 
165
/**
 
166
 * A property name with optional source and context.
 
167
 * String format is [<source>/]<property>[@<context>|@<peer>@<context>]
 
168
 *
 
169
 * Note that the part after the @ sign without another @ is always
 
170
 * a context. The normal shorthand of just <peer> without context
 
171
 * does not work here.
 
172
 */
 
173
class PropertySpecifier {
 
174
 public:
 
175
    std::string m_source;    /**< source name, empty if applicable to all or sync property */
 
176
    std::string m_property;  /**< property name, must not be empty */
 
177
    std::string m_config;    /**< config name, empty if none, otherwise @<context> or <peer>@<context> */
 
178
 
 
179
    enum {
 
180
        NO_NORMALIZATION = 0,
 
181
        NORMALIZE_SOURCE = 1,
 
182
        NORMALIZE_CONFIG = 2
 
183
    };
 
184
 
 
185
    /** parse, optionally also normalize source and config */
 
186
    static PropertySpecifier StringToPropSpec(const std::string &spec, int flags = NORMALIZE_SOURCE|NORMALIZE_CONFIG);
 
187
    std::string toString();
 
188
};
 
189
 
59
190
/**
60
191
 * A property has a name and a comment. Derived classes might have
61
192
 * additional code to read and write the property from/to a
63
194
 * on the fly, therefore the virtual get methods which return a
64
195
 * string value and not just a reference.
65
196
 *
 
197
 * In addition to the name, it may also have aliases. When reading
 
198
 * from a ConfigNode, all specified names are checked in the order in
 
199
 * which they are listed, and the first one found is used. When
 
200
 * writing, an existing key is overwritten, otherwise the main name is
 
201
 * created as a new key.
 
202
 *
66
203
 * A default value is returned if the ConfigNode doesn't have
67
204
 * a value set (= empty string). Invalid values in the configuration
68
205
 * trigger an exception. Setting invalid values does not because
98
235
 */
99
236
class ConfigProperty {
100
237
 public:
101
 
    ConfigProperty(const string &name, const string &comment,
 
238
        ConfigProperty(const string &name, const string &comment,
 
239
                       const string &def = string(""), const string &descr = string("")) :
 
240
        m_obligatory(false),
 
241
        m_hidden(false),
 
242
        m_sharing(NO_SHARING),
 
243
        m_flags(0),
 
244
        m_names(name),
 
245
        m_comment(boost::trim_right_copy(comment)),
 
246
        m_defValue(def),
 
247
        m_descr(descr)
 
248
        {}
 
249
 
 
250
    ConfigProperty(const Aliases &names, const string &comment,
102
251
                   const string &def = string(""), const string &descr = string("")) :
103
252
        m_obligatory(false),
104
253
        m_hidden(false),
105
254
        m_sharing(NO_SHARING),
106
255
        m_flags(0),
107
 
        m_name(name),
 
256
        m_names(names),
108
257
        m_comment(boost::trim_right_copy(comment)),
109
258
            m_defValue(def),
110
259
        m_descr(descr)
111
260
        {}
112
261
    virtual ~ConfigProperty() {}
113
 
    
114
 
    virtual string getName() const { return m_name; }
 
262
 
 
263
    /** name to be used for a specific node: first name if not in node, otherwise existing key */
 
264
    string getName(const ConfigNode &node) const;
 
265
 
 
266
    /** primary name */
 
267
    string getMainName() const { return m_names.front(); }
 
268
 
 
269
    /* virtual so that derived classes like SourceBackendConfigProperty can generate the result dynamically */
 
270
    virtual const Aliases &getNames() const { return m_names; }
115
271
    virtual string getComment() const { return m_comment; }
116
272
    virtual string getDefValue() const { return m_defValue; }
117
273
    virtual string getDescr() const { return m_descr; }
154
310
 
155
311
    /**
156
312
     * This is used to generate description dynamically according to the context information
157
 
     * Defalut implmenentation is to return value set in the constructor.
 
313
     * Default implmenentation is to return value set in the constructor, otherwise the server name.
158
314
     * Derived classes can override this function. Used by 'checkPassword' and 'savePassword'
159
315
     * to generate description for user interface.
160
316
     */
161
317
    virtual const string getDescr(const string &serverName,
162
318
                                  FilterConfigNode &globalConfigNode,
163
319
                                  const string &sourceName = string(),
164
 
                                  const boost::shared_ptr<FilterConfigNode> &sourceConfigNode=boost::shared_ptr<FilterConfigNode>()) const { return m_descr; }
 
320
                                  const boost::shared_ptr<FilterConfigNode> &sourceConfigNode=boost::shared_ptr<FilterConfigNode>()) const { return m_descr.empty() ? serverName : m_descr; }
165
321
 
166
322
 
167
323
    /** split \n separated comment into lines without \n, appending them to commentLines */
189
345
    Sharing getSharing() const { return m_sharing; }
190
346
    void setSharing(Sharing sharing) { m_sharing = sharing; }
191
347
 
192
 
    /**
193
 
     * special hacks for certain properties
194
 
     */
195
 
    enum Flags {
196
 
        SHARED_AND_UNSHARED = 1<<0   /**< value is stored with
197
 
                                        SOURCE_SET_SHARING and
198
 
                                        NO_SHARING, the later taking
199
 
                                        precedency when reading
200
 
                                        ("type"!) */
201
 
    };
202
 
    void setFlags(int flags) { m_flags = flags; }
203
 
    int getFlags(void) const { return m_flags; }
204
 
 
205
348
    /** set value unconditionally, even if it is not valid */
206
 
    void setProperty(ConfigNode &node, const string &value) const { node.setProperty(getName(), value, getComment()); }
 
349
    void setProperty(ConfigNode &node, const string &value) const { node.setProperty(getName(node), value, getComment()); }
207
350
    void setProperty(FilterConfigNode &node, const string &value, bool temporarily = false) const {
 
351
        string name = getName(node);
208
352
        if (temporarily) {
209
 
            node.addFilter(m_name, value);
 
353
            node.addFilter(name, value);
210
354
        } else {
211
 
            node.setProperty(m_name, value, getComment());
 
355
            node.setProperty(name, value, getComment());
212
356
        }
213
357
    }
214
358
 
215
359
    /** set default value of a property, marked as default unless forced setting */
216
360
    void setDefaultProperty(ConfigNode &node, bool force) const {
 
361
        string name = getName(node);
217
362
        string defValue = getDefValue();
218
 
        node.setProperty(m_name, defValue, getComment(), force ? NULL : &defValue);
 
363
        node.setProperty(name, defValue, getComment(), force ? NULL : &defValue);
219
364
    }
220
365
 
221
366
    /**
227
372
     *                      the default was returned instead
228
373
     */
229
374
    virtual string getProperty(const ConfigNode &node, bool *isDefault = NULL) const {
230
 
        string name = getName();
 
375
        string name = getName(node);
231
376
        string value = node.readProperty(name);
232
377
        if (!value.empty()) {
233
378
            string error;
248
393
 
249
394
    // true if property is set to non-empty value
250
395
    bool isSet(const ConfigNode &node) const {
251
 
        string name = getName();
 
396
        string name = getName(node);
252
397
        string value = node.readProperty(name);
253
398
        return !value.empty();
254
399
    }
261
406
    bool m_hidden;
262
407
    Sharing m_sharing;
263
408
    int m_flags;
264
 
    const string m_name, m_comment, m_defValue, m_descr;
265
 
};
266
 
 
267
 
template<class T> class InitList : public list<T> {
268
 
 public:
269
 
    InitList() {}
270
 
    InitList(const T &initialValue) {
271
 
        push_back(initialValue);
272
 
    }
273
 
    InitList &operator + (const T &rhs) {
274
 
        push_back(rhs);
275
 
        return *this;
276
 
    }
277
 
    InitList &operator += (const T &rhs) {
278
 
        push_back(rhs);
279
 
        return *this;
280
 
    }
281
 
};
282
 
typedef InitList<string> Aliases;
283
 
typedef InitList<Aliases> Values;
284
 
 
 
409
    const Aliases m_names;
 
410
    const string m_comment, m_defValue, m_descr;
 
411
};
285
412
 
286
413
/**
287
414
 * A string property which maps multiple different possible value
403
530
        ostringstream out;
404
531
 
405
532
        out << value;
406
 
        node.setProperty(getName(), out.str(), getComment());
 
533
        node.setProperty(getName(node), out.str(), getComment());
407
534
    }
408
535
    void setProperty(FilterConfigNode &node, const T &value, bool temporarily = false) const {
409
536
        ostringstream out;
 
537
        string name = getName(node);
410
538
 
411
539
        out << value;
412
540
        if (temporarily) {
413
 
            node.addFilter(getName(), out.str());
 
541
            node.addFilter(name, out.str());
414
542
        } else {
415
 
            node.setProperty(getName(), out.str(), getComment());
 
543
            node.setProperty(name, out.str(), getComment());
416
544
        }
417
545
    }
418
546
 
419
547
    T getPropertyValue(const ConfigNode &node, bool *isDefault = NULL) const {
420
 
        string name = getName();
 
548
        string name = getName(node);
421
549
        string value = node.readProperty(name);
422
550
        istringstream in(value);
423
551
        T res;
494
622
            error += endptr;
495
623
            return false;
496
624
        }
 
625
        // comparison might be always true for some types
 
626
#ifdef __clang__
 
627
#pragma clang diagnostic push
 
628
#pragma clang diagnostic ignored "-Wtautological-compare"
 
629
#endif
497
630
        if (val > Tmax || val < Tmin) {
498
631
            error = "range error";
499
632
            return false;
500
633
        }
 
634
#ifdef __clang__
 
635
#pragma clang diagnostic pop
 
636
#endif
501
637
        if (Tmin == 0) {
502
638
            // check that we didn't accidentally accept a negative value,
503
639
            // strtoul() does that
612
748
    PasswordConfigProperty(const string &name, const string &comment, const string &def = string(""),const string &descr = string("")) :
613
749
       ConfigProperty(name, comment, def, descr)
614
750
           {}
 
751
    PasswordConfigProperty(const Aliases &names, const string &comment, const string &def = string(""),const string &descr = string("")) :
 
752
       ConfigProperty(names, comment, def, descr)
 
753
           {}
615
754
 
616
755
    /**
617
756
     * Check the password and cache the result.
682
821
/**
683
822
 * A derived ConfigProperty class for the property "evolutionpassword"
684
823
 */
685
 
class EvolutionPasswordConfigProperty : public PasswordConfigProperty {
 
824
class DatabasePasswordConfigProperty : public PasswordConfigProperty {
686
825
 public:
687
 
    EvolutionPasswordConfigProperty(const string &name, 
688
 
                                    const string &comment, 
689
 
                                    const string &def = string(""),
690
 
                                    const string &descr = string("")): 
691
 
                                    PasswordConfigProperty(name,comment,def,descr)
 
826
    DatabasePasswordConfigProperty(const Aliases &names,
 
827
                                   const string &comment, 
 
828
                                   const string &def = string(""),
 
829
                                   const string &descr = string("")): 
 
830
    PasswordConfigProperty(names,comment,def,descr)
692
831
    {}
693
832
    virtual ConfigPasswordKey getPasswordKey(const string &descr,
694
833
                                             const string &serverName,
760
899
    /** case-insensitive search for property */
761
900
    const ConfigProperty *find(const string &propName) const {
762
901
        BOOST_FOREACH(const ConfigProperty *prop, *this) {
763
 
            if (boost::iequals(prop->getName(), propName)) {
764
 
                return prop;
 
902
            BOOST_FOREACH(const string &name, prop->getNames()) {
 
903
                if (boost::iequals(name, propName)) {
 
904
                    return prop;
 
905
                }
765
906
            }
766
907
        }
767
908
        return NULL;
769
910
};
770
911
 
771
912
/**
772
 
 * Store the current string value of a property in a cache
773
 
 * and return the "const char *" pointer that is expected by
774
 
 * the client library.
775
 
 */
776
 
class ConfigStringCache {
777
 
 public:
778
 
    const char *getProperty(const ConfigNode &node, const ConfigProperty &prop) {
779
 
        string value = prop.getProperty(node);
780
 
        return storeString(prop.getName(), value);
781
 
    }
782
 
 
783
 
    const char *storeString(const string &key, const string &value) {
784
 
        const string &entry = m_cache[key] = value;
785
 
        return entry.c_str();
786
 
    }
787
 
 
788
 
 private:
789
 
    map<string, string> m_cache;
790
 
};
791
 
 
792
 
/**
793
913
 * This class implements the client library configuration interface
794
914
 * by mapping values to properties to entries in a ConfigTree. The
795
915
 * mapping is either the traditional one used by SyncEvolution <= 0.7
834
954
     * places. Will succeed even if config does not
835
955
     * yet exist: flushing such a config creates it.
836
956
     *
 
957
     * Does a version check to ensure that the config can be
 
958
     * read. Users of the instance must to an explicit
 
959
     * prepareConfigForWrite() if the config or the files associated
 
960
     * with it (Synthesis bin files) are going to be written.
 
961
     *
837
962
     * @param peer   string that identifies the peer,
838
963
     *               matching regex (.*)(@([^@]*))? 
839
964
     *               where the $1 (the first part) is 
849
974
     *               as configuration tree instead of
850
975
     *               searching for it; always uses the
851
976
     *               current layout in that tree
 
977
     *
 
978
     * @param redirectPeerRootPath
 
979
     *               Can be used to redirect the per-peer
 
980
     *               files into a different directory. Only works
 
981
     *               in non-peer context configs.
 
982
     *               Used by SyncContext for local sync.
852
983
     */
853
984
    SyncConfig(const string &peer,
854
 
               boost::shared_ptr<ConfigTree> tree = boost::shared_ptr<ConfigTree>());
 
985
               boost::shared_ptr<ConfigTree> tree = boost::shared_ptr<ConfigTree>(),
 
986
               const string &redirectPeerRootPath = "");
 
987
 
855
988
 
856
989
    /**
857
990
     * Creates a temporary configuration.
859
992
     */
860
993
    SyncConfig();
861
994
 
 
995
    /**
 
996
     * determines whether the need to migrate a config causes a
 
997
     * STATUS_MIGRATION_NEEDED error or does the migration
 
998
     * automatically; default is to migrate automatically in
 
999
     * stable releases and to ask in development releases
 
1000
     */
 
1001
    enum ConfigWriteMode {
 
1002
        MIGRATE_AUTOMATICALLY,
 
1003
        ASK_USER_TO_MIGRATE
 
1004
    };
 
1005
    ConfigWriteMode getConfigWriteMode() const { return m_configWriteMode; }
 
1006
    void setConfigWriteMode(ConfigWriteMode mode) { m_configWriteMode = mode; }
 
1007
 
 
1008
    /**
 
1009
     * This does another version check which ensures that the config
 
1010
     * is not unintentionally altered so that it cannot be read by
 
1011
     * older SyncEvolution releases. If the config cannot be written
 
1012
     * without breaking older releases, then either the call will fail
 
1013
     * (development releases) or migrate the config (stable releases).
 
1014
     * Can be controlled via setConfigWriteMode();
 
1015
     *
 
1016
     * Also writes the current config versions into the config.
 
1017
     */
 
1018
    void prepareConfigForWrite();
 
1019
 
862
1020
   /** absolute directory name of the configuration root */
863
1021
    string getRootPath() const;
864
1022
 
945
1103
     * returns list of servers in either the old (.sync4j) or
946
1104
     * new config directory (.config), given as server name
947
1105
     * and absolute root of config
 
1106
     *
 
1107
     * Guaranteed to be sorted by the (context, peer name, path) tuple,
 
1108
     * in increasing order (foo@bar < abc@xyz < abc.old@xyz).
948
1109
     */
949
1110
    static ConfigList getConfigs();
950
1111
 
951
1112
    /**
 
1113
     * TODO: fix description of matchPeerTemplates() and remove getPeerTemplates()
 
1114
     *
952
1115
     * returns list of available config templates:
953
1116
     * for each peer listed in @peers, matching against the fingerprint information
954
1117
     * from the peer (deviceName likely), sorted by the matching score,
959
1122
     * The assumption currently is only work for SyncML client peers.
960
1123
     * DeviceList is a list of matching tuples <fingerprint, SyncConfig::MatchMode>.
961
1124
     */
962
 
    static TemplateList getPeerTemplates(const DeviceList &peers);
 
1125
    static TemplateList getPeerTemplates(const DeviceList &peers) { return matchPeerTemplates(peers, true); }
963
1126
 
964
1127
    /**
965
1128
     * match the built-in templates against @param fingerprint, return a list of
968
1131
    static TemplateList matchPeerTemplates(const DeviceList &peers, bool fuzzyMatch = true);
969
1132
 
970
1133
    /**
971
 
     * get the built-in default templates
972
 
     */
973
 
    static TemplateList getBuiltInTemplates ();
974
 
 
975
 
    /**
976
1134
     * Creates a new instance of a configuration template.
977
1135
     * The result can be modified to set filters, but it
978
1136
     * cannot be flushed.
979
1137
     *
980
1138
     * @param peer   a configuration name, *without* a context (scheduleworld, not scheduleworld@default),
981
1139
     * or a configuration path in the system directory which can avoid another fuzzy match process.
 
1140
     * "none" returns an empty template (default sync properties and dev ID set).
982
1141
     * @return NULL if no such template
983
1142
     */
984
1143
    static boost::shared_ptr<SyncConfig> createPeerTemplate(const string &peer);
985
1144
 
986
 
    /** true if the main configuration file already exists */
 
1145
    /**
 
1146
     * true if the main configuration file already exists;
 
1147
     * "main" here means the per-peer config or context config,
 
1148
     * depending on what the config refers to
 
1149
     */
987
1150
    bool exists() const;
988
1151
 
989
1152
    /**
 
1153
     * true if the config files for the selected level exist;
 
1154
     * false is returned for CONFIG_LEVEL_PEER and a config
 
1155
     * which refers to a context
 
1156
     */
 
1157
    bool exists(ConfigLevel level) const;
 
1158
 
 
1159
    /**
990
1160
     * The normalized, unique config name used by this instance.
991
1161
     * Empty if not backed up by a real config.
992
1162
     */
993
1163
    string getConfigName() const { return m_peer; }
994
1164
 
995
1165
    /**
 
1166
     * The normalized context used by this instance.
 
1167
     * Includes @ sign.
 
1168
     */
 
1169
    string getContextName() const;
 
1170
 
 
1171
    /**
 
1172
     * the normalized peer name, empty if not a peer config
 
1173
     */
 
1174
    string getPeerName() const;
 
1175
 
 
1176
    /**
 
1177
     * true if the config is for a peer, false if a context config
 
1178
     */
 
1179
    bool hasPeerProperties() const { return !m_peerPath.empty(); }
 
1180
 
 
1181
    /**
 
1182
     * returns names of peers inside this config;
 
1183
     * empty if not a context
 
1184
     */
 
1185
    list<string> getPeers() const;
 
1186
 
 
1187
    /**
996
1188
     * Do something before doing flush to files. This is particularly
997
1189
     * useful when user interface wants to do preparation jobs, such
998
1190
     * as savePassword and others.
1020
1212
     */
1021
1213
    static ConfigPropertyRegistry &getRegistry();
1022
1214
 
 
1215
    enum NormalizeFlags {
 
1216
        NORMALIZE_LONG_FORMAT = 0,  /**< include context in normal form */
 
1217
        NORMALIZE_SHORTHAND = 1,    /**< keep normal form shorter by not specifying @default */
 
1218
        NORMALIZE_IS_NEW = 2,       /**< does not refer to an existing config, do not search
 
1219
                                       for it among existing configs */
 
1220
        NORMALIZE_MAX = 0xFFFF
 
1221
    };
 
1222
 
1023
1223
    /**
1024
1224
     * Normalize a config string:
1025
1225
     * - lower case
1026
1226
     * - non-printable and unsafe characters (colon, slash, backslash)
1027
1227
     *   replaced by underscore
1028
 
     * - when no context specified: search for peer config first in @default,
1029
 
     *   then also in other contexts in alphabetical order
1030
 
     * - @default stripped
 
1228
     * - when no context specified and NORMALIZE_IS_NEW not set:
 
1229
     *   search for peer config first in @default, then also in other contexts
 
1230
     *   in alphabetical order
 
1231
     * - NORMALIZE_SHORTHAND set: @default stripped  (dangerous: result "foo"
 
1232
     *   may incorrectly be mapped to "foo@bar" if the "foo@default" config gets removed),
 
1233
     *   otherwise added if missing
1031
1234
     * - empty string replaced with "@default"
1032
1235
     */
1033
 
    static string normalizeConfigString(const string &config);
 
1236
    static string normalizeConfigString(const string &config, NormalizeFlags flags = NORMALIZE_SHORTHAND);
1034
1237
 
1035
1238
    /**
1036
1239
     * Split a config string (normalized or not) into the peer part
1046
1249
     * all sources. This can be used to e.g. temporarily override
1047
1250
     * the active sync mode.
1048
1251
     *
 
1252
     * All future calls of getSyncSourceNodes() will have these
 
1253
     * filters applied.
 
1254
     *
1049
1255
     * @param sync     true if the filter applies to sync properties,
1050
1256
     *                 false if it applies to sources
1051
1257
     * @param source   empty string if filter applies to all sources,
1076
1282
    }
1077
1283
 
1078
1284
    /**
 
1285
     * Returns the right config node for a certain registered property,
 
1286
     * looked up by name. NULL if not found.
 
1287
     */
 
1288
    boost::shared_ptr<FilterConfigNode> getNode(const std::string &propName);
 
1289
    boost::shared_ptr<const FilterConfigNode> getNode(const std::string &propName) const
 
1290
    {
 
1291
        return const_cast<SyncConfig *>(this)->getNode(propName);
 
1292
    }
 
1293
 
 
1294
    /**
1079
1295
     * Returns a wrapper around all properties of the given source
1080
1296
     * which are saved in the config tree. Note that this is different
1081
1297
     * from the set of sync source configs used by the SyncManager:
1102
1318
     * Creates config nodes for a certain node. The nodes are not
1103
1319
     * yet created in the backend if they do not yet exist.
1104
1320
     *
 
1321
     * Calling this for the same name repeatedly will return the
 
1322
     * same set of node instances. This allows to set properties
 
1323
     * temporarily in one place and have them used elsewhere.
 
1324
     *
 
1325
     * setConfigFilter() resets this cache of nodes. Requesting nodes
 
1326
     * after that call will create a new set of nodes with properties
 
1327
     * modified temporarily according to these filters.
 
1328
     *
1105
1329
     * @param name       the name of the sync source
1106
1330
     * @param trackName  additional part of the tracking node name (used for unit testing)
1107
1331
     */
1188
1412
    virtual string getDefaultPeer() const;
1189
1413
    virtual void setDefaultPeer(const string &value);
1190
1414
 
1191
 
    virtual const char *getLogDir() const;
 
1415
    virtual std::string getLogDir() const;
1192
1416
    virtual void setLogDir(const string &value, bool temporarily = false);
1193
1417
 
1194
1418
    virtual int getMaxLogDirs() const;
1200
1424
    virtual bool getPrintChanges() const;
1201
1425
    virtual void setPrintChanges(bool value, bool temporarily = false);
1202
1426
 
 
1427
    virtual bool getDumpData() const;
 
1428
    virtual void setDumpData(bool value, bool temporarily = false);
 
1429
 
1203
1430
    virtual std::string getWebURL() const;
1204
1431
    virtual void setWebURL(const std::string &url, bool temporarily = false);
1205
1432
 
1224
1451
    /**@}*/
1225
1452
 
1226
1453
    /**
1227
 
     * @name Settings inherited from Funambol
 
1454
     * @name SyncML Settings
1228
1455
     *
1229
 
     * These settings are required by the Funambol C++ client library.
 
1456
     * These settings are required by the Synthesis engine.
1230
1457
     * Some of them are hard-coded in this class. A derived class could
1231
1458
     * make them configurable again, should that be desired.
1232
1459
     */
1233
1460
    /**@{*/
1234
1461
 
1235
 
    virtual const char*  getUsername() const;
1236
 
    virtual void setUsername(const string &value, bool temporarily = false);
1237
 
    virtual const char*  getPassword() const;
1238
 
    virtual void setPassword(const string &value, bool temporarily = false);
1239
 
 
1240
 
    /**
1241
 
     * Look at the password setting and if it requires user interaction,
1242
 
     * get it from the user. Then store it for later usage in getPassword().
1243
 
     * Without this call, getPassword() returns the original, unmodified
1244
 
     * config string.
1245
 
     */
1246
 
    virtual void checkPassword(ConfigUserInterface &ui);
1247
 
 
1248
 
    /**
1249
 
     * Look at the password setting and if it needs special mechanism to
1250
 
     * save password, this function is used to store specified password
1251
 
     * in the config tree.
1252
 
     * @param ui the ui pointer
1253
 
     */
1254
 
    virtual void savePassword(ConfigUserInterface &ui); 
 
1462
    virtual std::string getSyncUsername() const;
 
1463
    virtual void setSyncUsername(const string &value, bool temporarily = false);
 
1464
    virtual std::string getSyncPassword() const;
 
1465
    virtual void setSyncPassword(const string &value, bool temporarily = false);
1255
1466
 
1256
1467
    virtual bool getPreventSlowSync() const;
1257
1468
    virtual void setPreventSlowSync(bool value, bool temporarily = false);
1258
1469
    virtual bool getUseProxy() const;
1259
1470
    virtual void setUseProxy(bool value, bool temporarily = false);
1260
 
    virtual const char*  getProxyHost() const;
 
1471
    virtual std::string getProxyHost() const;
1261
1472
    virtual void setProxyHost(const string &value, bool temporarily = false);
1262
1473
    virtual int getProxyPort() const { return 0; }
1263
 
    virtual const char* getProxyUsername() const;
 
1474
    virtual std::string getProxyUsername() const;
1264
1475
    virtual void setProxyUsername(const string &value, bool temporarily = false);
1265
 
    virtual const char* getProxyPassword() const;
1266
 
    virtual void checkProxyPassword(ConfigUserInterface &ui);
1267
 
    virtual void saveProxyPassword(ConfigUserInterface &ui);
 
1476
    virtual std::string getProxyPassword() const;
1268
1477
    virtual void setProxyPassword(const string &value, bool temporarily = false);
1269
1478
    virtual vector<string>  getSyncURL() const;
1270
1479
    virtual void setSyncURL(const string &value, bool temporarily = false);
1271
1480
    virtual void setSyncURL(const vector<string> &value, bool temporarily = false);
1272
 
    virtual const char*  getClientAuthType() const;
 
1481
    virtual std::string getClientAuthType() const;
1273
1482
    virtual void setClientAuthType(const string &value, bool temporarily = false);
1274
1483
    virtual unsigned long getMaxMsgSize() const;
1275
1484
    virtual void setMaxMsgSize(unsigned long value, bool temporarily = false);
1276
1485
    virtual unsigned int getMaxObjSize() const;
1277
1486
    virtual void setMaxObjSize(unsigned int value, bool temporarily = false);
1278
1487
    virtual unsigned long getReadBufferSize() const { return 0; }
1279
 
    virtual const char* getSSLServerCertificates() const;
 
1488
    virtual std::string getSSLServerCertificates() const;
1280
1489
 
1281
1490
    /**
1282
1491
     * iterate over files mentioned in getSSLServerCertificates()
1297
1506
    virtual bool  getCompression() const;
1298
1507
    virtual void setCompression(bool value, bool temporarily = false);
1299
1508
    virtual unsigned int getResponseTimeout() const { return 0; }
1300
 
    virtual const char*  getDevID() const;
 
1509
    virtual std::string getDevID() const;
1301
1510
    virtual void setDevID(const string &value, bool temporarily = false);
1302
1511
 
1303
1512
    /*Used for Server Alerted Sync*/
1304
 
    virtual const char* getRemoteIdentifier() const;
 
1513
    virtual std::string getRemoteIdentifier() const;
1305
1514
    virtual void setRemoteIdentifier (const string &value, bool temporaritly = false);
1306
1515
    virtual bool getPeerIsClient () const;
1307
1516
    virtual void setPeerIsClient (bool value, bool temporarily = false);
1308
 
    virtual const char* getSyncMLVersion() const;
 
1517
    virtual std::string getSyncMLVersion() const;
1309
1518
    virtual void setSyncMLVersion (const string &value, bool temporarily = false);
1310
1519
 
1311
1520
    /**
1313
1522
     * not necessarily unique. Can be used by a GUI instead
1314
1523
     * of the config name.
1315
1524
     */
1316
 
    virtual string getPeerName() const;
1317
 
    virtual void setPeerName(const string &name);
 
1525
    virtual string getUserPeerName() const;
 
1526
    virtual void setUserPeerName(const string &name);
1318
1527
 
1319
1528
    /**
1320
1529
     * The Device ID of our peer. Typically only relevant when the
1355
1564
    virtual bool getWBXML() const;
1356
1565
    virtual void setWBXML(bool isWBXML, bool temporarily = false);
1357
1566
 
1358
 
    virtual const char*  getUserAgent() const { return "SyncEvolution"; }
1359
 
    virtual const char*  getMan() const { return "Patrick Ohly"; }
1360
 
    virtual const char*  getMod() const { return "SyncEvolution"; }
1361
 
    virtual const char*  getOem() const { return "Open Source"; }
1362
 
    virtual const char*  getHwv() const { return "unknown"; }
1363
 
    virtual const char*  getSwv() const;
1364
 
    virtual const char*  getDevType() const;
 
1567
    virtual std::string getUserAgent() const { return "SyncEvolution"; }
 
1568
    virtual std::string getMan() const { return "Patrick Ohly"; }
 
1569
    virtual std::string getMod() const { return "SyncEvolution"; }
 
1570
    virtual std::string getOem() const { return "Open Source"; }
 
1571
    virtual std::string getHwv() const { return "unknown"; }
 
1572
    virtual std::string getSwv() const;
 
1573
    virtual std::string getDevType() const;
1365
1574
    /**@}*/
1366
1575
 
1367
 
private:
1368
1576
    enum Layout {
1369
1577
        SYNC4J_LAYOUT,        /**< .syncj4/evolution/<server>, SyncEvolution <= 0.7.x */
1370
1578
        HTTP_SERVER_LAYOUT,   /**< .config/syncevolution/<server> with sources
1374
1582
                                 SyncEvolution >= 1.0 */
1375
1583
    };
1376
1584
 
 
1585
    /** config versioning; setting is done internally */
 
1586
    int getConfigVersion(ConfigLevel level, ConfigLimit limit) const;
 
1587
 
 
1588
    /** file layout used by config */
 
1589
    Layout getLayout() const { return m_layout; }
 
1590
 
 
1591
private:
1377
1592
    /**
1378
1593
     * scans for peer configurations
1379
1594
     * @param root         absolute directory path
1384
1599
                         const std::string &configname,
1385
1600
                         SyncConfig::ConfigList &res);
1386
1601
 
 
1602
    /* internal access to configuration versioning */
 
1603
    void setConfigVersion(ConfigLevel level, ConfigLimit limit, int version);
 
1604
 
 
1605
    /**
 
1606
     * migrate root (""), context or peer config and everything contained in them to
 
1607
     * the current config format
 
1608
     */
 
1609
    void migrate(const std::string &config);
 
1610
 
1387
1611
    /**
1388
1612
     * set tree and nodes to VolatileConfigTree/Node
1389
1613
     */
1417
1641
    string m_contextPath;
1418
1642
 
1419
1643
    Layout m_layout;
 
1644
    string m_redirectPeerRootPath;
1420
1645
    string m_cachedPassword;
1421
1646
    string m_cachedProxyPassword;
 
1647
    ConfigWriteMode m_configWriteMode;
1422
1648
 
1423
1649
    /** holds all config nodes relative to the root that we found */
1424
1650
    boost::shared_ptr<ConfigTree> m_tree;
1426
1652
    /** access to global sync properties, independent of
1427
1653
        the context (for example, "defaultPeer") */
1428
1654
    boost::shared_ptr<FilterConfigNode> m_globalNode;
1429
 
        
 
1655
    boost::shared_ptr<ConfigNode> m_globalHiddenNode;
 
1656
 
1430
1657
    /** access to properties shared between peers */
1431
1658
    boost::shared_ptr<FilterConfigNode> m_contextNode;
1432
1659
    boost::shared_ptr<ConfigNode> m_contextHiddenNode;
1440
1667
 
1441
1668
    /**
1442
1669
     * temporary override for all sync source settings
 
1670
     * ("" as key) or specific sources (source name as key)
1443
1671
     */
1444
 
    FilterConfigNode::ConfigFilter m_sourceFilter;
1445
 
 
1446
 
    /** temporary override for settings of specific sources */
1447
 
    typedef std::map<std::string, FilterConfigNode::ConfigFilter> SourceFilters_t;
1448
 
    SourceFilters_t m_sourceFilters;
1449
 
 
1450
 
    mutable ConfigStringCache m_stringCache;
 
1672
    SourceProps m_sourceFilters;
1451
1673
 
1452
1674
    static string getOldRoot() {
1453
1675
        return getHome() + "/.sync4j/evolution";
1458
1680
        return xdg_root_str ? string(xdg_root_str) + "/syncevolution" :
1459
1681
            getHome() + "/.config/syncevolution";
1460
1682
    }
1461
 
 
 
1683
 
 
1684
    /** remember all SyncSourceNodes so that temporary changes survive */
 
1685
    map<string, SyncSourceNodes> m_nodeCache;
1462
1686
};
1463
1687
 
1464
1688
/**
1502
1726
    /** true if the peer-specific config node exists */
1503
1727
    bool exists() const { return m_peerNode->exists(); }
1504
1728
 
 
1729
    /** true if the context-specific config node exists */
 
1730
    bool dataConfigExists() const { return m_sharedNode->exists(); }
 
1731
 
1505
1732
    /**
1506
1733
     * Returns the right config node for a certain property,
1507
1734
     * depending on visibility and sharing.
1537
1764
};
1538
1765
 
1539
1766
/**
 
1767
 * nop deleter for boost::shared_ptr<SyncConfig>
 
1768
 */
 
1769
struct SyncConfigNOP
 
1770
{
 
1771
    void operator() (SyncConfig *) {}
 
1772
};
 
1773
 
 
1774
/**
1540
1775
 * same as SyncSourceNodes, but with only read access to properties
1541
1776
 */
1542
1777
class ConstSyncSourceNodes : private SyncSourceNodes
1556
1791
struct SourceType {
1557
1792
    SourceType():m_forceFormat(false)
1558
1793
    {}
 
1794
 
 
1795
    /**
 
1796
     * Parses the SyncEvolution <= 1.1 type specifier:
 
1797
     * <backend>[:<format>[:<version>][!]]
 
1798
     *
 
1799
     * The <version> part is not stored anymore (was required by file
 
1800
     * backend, but not actually used).
 
1801
     */
 
1802
    SourceType(const string &type);
 
1803
 
 
1804
    /**
 
1805
     * converts back to SyncEvolution <= 1.1 type specifier
 
1806
     */
 
1807
    string toString() const;
 
1808
 
1559
1809
    string m_backend; /**< identifies the SyncEvolution backend (either via a generic term like "addressbook" or a specific one like "Evolution Contacts") */
1560
 
    string m_format; /**< the format to be used (typically a MIME type) */
 
1810
    string m_localFormat;  /**< the format to be used inside the backend for storing items; typically
 
1811
                              hard-coded and not configurable */
 
1812
    string m_format; /**< the format to be used (typically a MIME type) when talking to our peer */
1561
1813
    bool   m_forceFormat; /**< force to use the client's preferred format instead giving the engine and server a choice */
1562
1814
};
1563
1815
 
1582
1834
    }
1583
1835
    boost::shared_ptr<const FilterConfigNode> getProperties(bool hidden = false) const { return const_cast<SyncSourceConfig *>(this)->getProperties(hidden); }
1584
1836
 
1585
 
    virtual const char*  getName() const { return m_name.c_str(); }
 
1837
    virtual std::string getName() const { return m_name.c_str(); }
1586
1838
 
1587
1839
    /**
1588
1840
     * Directory to be used by source when it needs to store
1621
1873
        return prop.isSet(*getProperties(prop.isHidden()));
1622
1874
    }
1623
1875
 
1624
 
    virtual const char *getUser() const;
 
1876
    virtual std::string getUser() const;
1625
1877
    virtual void setUser(const string &value, bool temporarily = false);
1626
1878
 
1627
 
    const char *getPassword() const;
 
1879
    virtual std::string getPassword() const;
1628
1880
    virtual void setPassword(const string &value, bool temporarily = false);
1629
1881
 
1630
1882
    /** same as SyncConfig::checkPassword() but with
1636
1888
    virtual void savePassword(ConfigUserInterface &ui, const string &serverName, FilterConfigNode& globalConfigNode);
1637
1889
 
1638
1890
    /** selects the backend database to use */
1639
 
    virtual const char *getDatabaseID() const;
 
1891
    virtual std::string getDatabaseID() const;
1640
1892
    virtual void setDatabaseID(const string &value, bool temporarily = false);
1641
1893
 
1642
1894
    /**
1651
1903
     * configuration; different SyncSources then check whether
1652
1904
     * they support that type. This call has to work before instantiating
1653
1905
     * a source and thus gets passed a node to read from.
1654
 
     *
1655
 
     * @return the pair of <backend> and the (possibly empty)
1656
 
     *         <format> specified in the "type" property; see
1657
 
     *         sourcePropSourceType in SyncConfig.cpp
1658
 
     *         for details
1659
1906
     */
1660
1907
    static SourceType getSourceType(const SyncSourceNodes &nodes);
1661
 
    static string getSourceTypeString(const SyncSourceNodes &nodes);
1662
1908
    virtual SourceType getSourceType() const;
1663
1909
 
1664
 
    /** set the source type in <backend>[:format] style */
1665
 
    virtual void setSourceType(const string &value, bool temporarily = false);
 
1910
    /** set source backend and formats in one step */
 
1911
    virtual void setSourceType(const SourceType &type, bool temporarily = false);
 
1912
 
 
1913
    virtual void setBackend(const std::string &value, bool temporarily = false);
 
1914
    virtual std::string getBackend() const;
 
1915
    virtual void setDatabaseFormat(const std::string &value, bool temporarily = false);
 
1916
    virtual std::string getDatabaseFormat() const;
 
1917
    virtual void setSyncFormat(const std::string &value, bool temporarily = false);
 
1918
    virtual std::string getSyncFormat() const;
 
1919
    virtual void setForceSyncFormat(bool value, bool temporarily = false);
 
1920
    virtual bool getForceSyncFormat() const;
1666
1921
 
1667
1922
    /**
1668
1923
     * Returns the SyncSource URI: used in SyncML to address the data
1672
1927
     * two different sync sources cannot access the same data at
1673
1928
     * the same time.
1674
1929
     */
1675
 
    virtual const char*  getURI() const;
 
1930
    virtual std::string getURI() const;
1676
1931
    virtual void setURI(const string &value, bool temporarily = false);
1677
1932
 
1678
1933
    /**
 
1934
     * like getURI(), but instead of returning an empty string when
 
1935
     * not configured, return the source name
 
1936
     */
 
1937
    virtual std::string getURINonEmpty() const;
 
1938
 
 
1939
 
 
1940
    /**
1679
1941
     * Gets the default syncMode.
1680
1942
     *
1681
1943
     * Sync modes can be one of:
1687
1949
     * - refresh-from-server
1688
1950
     * - refresh-from-client
1689
1951
     */
1690
 
    virtual const char*  getSync() const;
 
1952
    virtual std::string getSync() const;
1691
1953
    virtual void setSync(const string &value, bool temporarily = false);
1692
1954
 
1693
1955
 private:
1694
1956
    string m_name;
1695
1957
    SyncSourceNodes m_nodes;
1696
 
    mutable ConfigStringCache m_stringCache;
1697
1958
    string m_cachedPassword;
1698
1959
};
1699
1960