~ubuntu-branches/ubuntu/trusty/virtualbox-ose/trusty

« back to all changes in this revision

Viewing changes to include/VBox/settings.h

  • Committer: Bazaar Package Importer
  • Author(s): Felix Geyer
  • Date: 2009-12-18 16:44:29 UTC
  • mfrom: (0.3.3 upstream) (0.4.6 squeeze)
  • Revision ID: james.westby@ubuntu.com-20091218164429-jd34ccexpv5na11a
Tags: 3.1.2-dfsg-1ubuntu1
* Merge from Debian unstable (LP: #498219), remaining changes:
  - Disable update action
    - debian/patches/u01-disable-update-action.dpatch
  - VirtualBox should go in Accessories, not in System tools (LP: #288590)
    - debian/virtualbox-ose-qt.files/virtualbox-ose.desktop
  - Add Apport hook
    - debian/virtualbox-ose.files/source_virtualbox-ose.py
    - debian/virtualbox-ose.install
  - Add Launchpad integration
    - debian/control
    - debian/lpi-bug.xpm
    - debian/patches/u02-lp-integration.dpatch
* Fixes the following bugs:
  - Kernel module fails to build with Linux >= 2.6.32 (LP: #474625)
  - X.Org drivers need to be rebuilt against X-Server 1.7 (LP: #495935)
  - The *-source packages try to build the kernel modules even though the
    kernel headers aren't available (LP: #473334)
* Replace *-source packages with transitional packages for *-dkms.
* Adapt u01-disable-update-action.dpatch and u02-lp-integration.dpatch for
  new upstream version.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/** @file
2
 
 * Settings File Manipulation API.
 
2
 * Settings file data structures.
 
3
 *
 
4
 * These structures are created by the settings file loader and filled with values
 
5
 * copied from the raw XML data. This allows us to finally make the XML reader
 
6
 * version-independent and read VirtualBox XML files from earlier versions without
 
7
 * requiring complicated, tedious and error-prone XSLT conversions.
 
8
 *
 
9
 * Note: Headers in Main code have been tweaked to only declare the structures
 
10
 * defined here so that this header need only be included from code files that
 
11
 * actually use these structures.
3
12
 */
4
13
 
5
14
/*
6
 
 * Copyright (C) 2007 Sun Microsystems, Inc.
 
15
 * Copyright (C) 2007-2009 Sun Microsystems, Inc.
7
16
 *
8
17
 * This file is part of VirtualBox Open Source Edition (OSE), as
9
18
 * available from http://www.virtualbox.org. This file is free software;
30
39
#ifndef ___VBox_settings_h
31
40
#define ___VBox_settings_h
32
41
 
33
 
#include <iprt/cdefs.h>
34
 
#include <iprt/cpputils.h>
35
 
#include <iprt/string.h>
36
 
 
37
 
#include <list>
38
 
#include <memory>
39
 
#include <limits>
40
 
 
41
42
#include <iprt/time.h>
42
43
 
 
44
#include "VBox/com/VirtualBox.h"
 
45
 
43
46
#include <VBox/com/Guid.h>
44
 
 
45
 
#include <VBox/xml.h>
46
 
 
47
 
// #include <stdarg.h>
48
 
 
49
 
/* these conflict with numeric_digits<>::min and max */
50
 
#undef min
51
 
#undef max
52
 
 
53
 
 
54
 
/** @defgroup   grp_settings    Settings File Manipulation API
55
 
 * @{
56
 
 *
57
 
 * The Settings File Manipulation API allows to maintain a configuration file
58
 
 * that contains "name-value" pairs grouped under named keys which are in turn
59
 
 * organized in a hierarchical tree-like structure:
60
 
 *
61
 
 * @code
62
 
 * <RootKey>
63
 
 *  <Key1 attr1="value" attr2=""/>
64
 
 *  <Key2 attr1="value">
65
 
 *   <SubKey1>SubKey1_Value</SubKey1>
66
 
 *   <SubKey2 attr1="value">SubKey2_Value</SubKey2>
67
 
 *   Key2_Value
68
 
 *  </Key2>
69
 
 * </RootKey>
70
 
 * @endcode
71
 
 *
72
 
 * All strings this API manipulates with are zero-terminated arrays of @c char
73
 
 * in UTF-8 encoding. Strings returned by the API are owned by the API unless
74
 
 * explicitly stated otherwise. Strings passed to the API are accessed by the
75
 
 * API only during the given API call unless explicitly stated otherwise. If
76
 
 * necessary, the API will make a copy of the supplied string.
77
 
 *
78
 
 * Error reporting is perfomed using C++ exceptions. All exceptions thrown by
79
 
 * this API are derived from settings::Error. This doesn't cover exceptions
80
 
 * that may be thrown by third-party library calls made by this API.
81
 
 *
82
 
 * All public classes represented by this API that support copy operations
83
 
 * (i.e. may be created or assigned from other instsances of the same class),
84
 
 * such as Key and Value classes, implement shallow copies and use this mode by
85
 
 * default. It means two things:
86
 
 *
87
 
 * 1. Instances of these classes can be freely copied around and used as return
88
 
 *    values. All copies will share the same internal data block (using the
89
 
 *    reference counting technique) so that the copy operation is cheap, both
90
 
 *    in terms of memory and speed.
91
 
 *
92
 
 * 2. Since copied instances share the same data, an attempt to change data in
93
 
 *    the original will be reflected in all existing copies.
94
 
 *
95
 
 * Making deep copies or detaching the existing shallow copy from its original
96
 
 * is not yet supported.
97
 
 *
98
 
 * Note that the Settings File API is not thread-safe. It means that if you
99
 
 * want to use the same instance of a class from the settings namespace on more
100
 
 * than one thread at a time, you will have to provide necessary access
101
 
 * serialization yourself.
102
 
 *
103
 
 * Due to some (not propely studied) libxml2 limitations, the Settings File
104
 
 * API is not thread-safe. Therefore, the API caller must provide
105
 
 * serialization for threads using this API simultaneously. Note though that
106
 
 * if the libxml2 library is (even imlicitly) used on some other thread which
107
 
 * doesn't use this API (e.g. third-party code), it may lead to resource
108
 
 * conflicts (followed by crashes, memory corruption etc.). A proper solution
109
 
 * for these conflicts is to be found.
110
 
 *
111
 
 * In order to load a settings file the program creates a TreeBackend instance
112
 
 * using one of the specific backends (e.g. XmlTreeBackend) and then passes an
113
 
 * Input stream object (e.g. File or MemoryBuf) to the TreeBackend::read()
114
 
 * method to parse the stream and build the settings tree. On success, the
115
 
 * program uses the TreeBackend::rootKey() method to access the root key of
116
 
 * the settings tree. The root key provides access to the whole tree of
117
 
 * settings through the methods of the Key class which allow to read, change
118
 
 * and create new key values. Below is an example that uses the XML backend to
119
 
 * load the settings tree, then modifies it and then saves the modifications.
120
 
 *
121
 
 * @code
122
 
    using namespace settings;
123
 
 
124
 
    try
125
 
    {
126
 
        File file (File::ReadWrite, "myfile.xml");
127
 
        XmlTreeBackend tree;
128
 
 
129
 
        // load the tree, parse it and validate using the XML schema
130
 
        tree.read (aFile, "myfile.xsd", XmlTreeBackend::Read_AddDefaults);
131
 
 
132
 
        // get the root key
133
 
        Key root = tree.key();
134
 
        printf ("root=%s\n", root.name());
135
 
 
136
 
        // enumerate all child keys of the root key named Foo
137
 
        Key::list children = root.keys ("Foo");
138
 
        for (Key::list::const_iterator it = children.begin();
139
 
             it != children.end();
140
 
             ++ it)
141
 
        {
142
 
            // get the "level" attribute
143
 
            int level = (*it).value <int> ("level");
144
 
            if (level > 5)
145
 
            {
146
 
                // if so, create a "Bar" key if it doesn't exist yet
147
 
                Key bar = (*it).createKey ("Bar");
148
 
                // set the "date" attribute
149
 
                RTTIMESPEC now;
150
 
                RTTimeNow (&now);
151
 
                bar.setValue <RTTIMESPEC> ("date", now);
152
 
            }
153
 
            else if (level < 2)
154
 
            {
155
 
                // if its below 2, delete the whole "Foo" key
156
 
                (*it).zap();
157
 
            }
158
 
        }
159
 
 
160
 
        // save the tree on success (the second try is to distinguish between
161
 
        // stream load and save errors)
162
 
        try
163
 
        {
164
 
            aTree.write (aFile);
165
 
        }
166
 
        catch (const EIPRTFailure &err)
167
 
        {
168
 
            // this is an expected exception that may happen in case of stream
169
 
            // read or write errors
170
 
            printf ("Could not save the settings file '%s' (%Rrc)");
171
 
                    file.uri(), err.rc());
172
 
 
173
 
            return FAILURE;
174
 
        }
175
 
 
176
 
        return SUCCESS;
177
 
    }
178
 
    catch (const EIPRTFailure &err)
179
 
    {
180
 
        // this is an expected exception that may happen in case of stream
181
 
        // read or write errors
182
 
        printf ("Could not load the settings file '%s' (%Rrc)");
183
 
                file.uri(), err.rc());
184
 
    }
185
 
    catch (const XmlTreeBackend::Error &err)
186
 
    {
187
 
        // this is an XmlTreeBackend specific exception that may
188
 
        // happen in case of XML parse or validation errors
189
 
        printf ("Could not load the settings file '%s'.\n%s"),
190
 
                file.uri(), err.what() ? err.what() : "Unknown error");
191
 
    }
192
 
    catch (const std::exception &err)
193
 
    {
194
 
        // the rest is unexpected (e.g. should not happen unless you
195
 
        // specifically wish so for some reason and therefore allow for a
196
 
        // situation that may throw one of these from within the try block
197
 
        // above)
198
 
        AssertMsgFailed ("Unexpected exception '%s' (%s)\n",
199
 
                         typeid (err).name(), err.what());
200
 
    }
201
 
    catch (...)
202
 
    {
203
 
        // this is even more unexpected, and no any useful info here
204
 
        AssertMsgFailed ("Unexpected exception\n");
205
 
    }
206
 
 
207
 
    return FAILURE;
208
 
 * @endcode
209
 
 *
210
 
 * Note that you can get a raw (string) value of the attribute using the
211
 
 * Key::stringValue() method but often it's simpler and better to use the
212
 
 * templated Key::value<>() method that can convert the string to a value of
213
 
 * the given type for you (and throw exceptions when the converison is not
214
 
 * possible). Similarly, the Key::setStringValue() method is used to set a raw
215
 
 * string value and there is a templated Key::setValue<>() method to set a
216
 
 * typed value which will implicitly convert it to a string.
217
 
 *
218
 
 * Currently, types supported by Key::value<>() and Key::setValue<>() include
219
 
 * all C and IPRT integer types, bool and RTTIMESPEC (represented as isoDate
220
 
 * in XML). You can always add support for your own types by creating
221
 
 * additional specializations of the FromString<>() and ToString<>() templates
222
 
 * in the settings namespace (see the real examples in this header).
223
 
 *
224
 
 * See individual funciton, class and method descriptions to get more details
225
 
 * on the Settings File Manipulation API.
226
 
 */
227
 
 
228
 
/*
229
 
 * Shut up MSVC complaining that auto_ptr[_ref] template instantiations (as a
230
 
 * result of private data member declarations of some classes below) need to
231
 
 * be exported too to in order to be accessible by clients.
232
 
 *
233
 
 * The alternative is to instantiate a template before the data member
234
 
 * declaration with the VBOXXML_CLASS prefix, but the standard disables
235
 
 * explicit instantiations in a foreign namespace. In other words, a declaration
236
 
 * like:
237
 
 *
238
 
 *   template class VBOXXML_CLASS std::auto_ptr <Data>;
239
 
 *
240
 
 * right before the member declaration makes MSVC happy too, but this is not a
241
 
 * valid C++ construct (and G++ spits it out). So, for now we just disable the
242
 
 * warning and will come back to this problem one day later.
243
 
 *
244
 
 * We also disable another warning (4275) saying that a DLL-exported class
245
 
 * inherits form a non-DLL-exported one (e.g. settings::ENoMemory ->
246
 
 * std::bad_alloc). I can't get how it can harm yet.
247
 
 */
248
 
#if defined(_MSC_VER)
249
 
#pragma warning (disable:4251)
250
 
#pragma warning (disable:4275)
251
 
#endif
252
 
 
253
 
/* Forwards */
254
 
typedef struct _xmlParserInput xmlParserInput;
255
 
typedef xmlParserInput *xmlParserInputPtr;
256
 
typedef struct _xmlParserCtxt xmlParserCtxt;
257
 
typedef xmlParserCtxt *xmlParserCtxtPtr;
258
 
typedef struct _xmlError xmlError;
259
 
typedef xmlError *xmlErrorPtr;
260
 
 
261
 
 
262
 
/**
263
 
 * Settings File Manipulation API namespace.
264
 
 */
 
47
#include <VBox/com/string.h>
 
48
 
 
49
#include <list>
 
50
#include <map>
 
51
#include <vector>
 
52
 
 
53
namespace xml
 
54
{
 
55
    class ElementNode;
 
56
}
 
57
 
265
58
namespace settings
266
59
{
267
60
 
268
 
// Exceptions (on top of vboxxml exceptions)
269
 
//////////////////////////////////////////////////////////////////////////////
270
 
 
271
 
class VBOXXML_CLASS ENoKey : public xml::LogicError
272
 
{
273
 
public:
274
 
 
275
 
    ENoKey (const char *aMsg = NULL) : xml::LogicError (aMsg) {}
276
 
};
277
 
 
278
 
class VBOXXML_CLASS ENoValue : public xml::LogicError
279
 
{
280
 
public:
281
 
 
282
 
    ENoValue (const char *aMsg = NULL) : xml::LogicError (aMsg) {}
283
 
};
284
 
 
285
 
class VBOXXML_CLASS ENoConversion : public xml::RuntimeError
286
 
{
287
 
public:
288
 
 
289
 
    ENoConversion (const char *aMsg = NULL) : RuntimeError (aMsg) {}
290
 
};
291
 
 
292
 
 
293
 
// Helpers
294
 
//////////////////////////////////////////////////////////////////////////////
295
 
 
296
 
// string -> type conversions
297
 
//////////////////////////////////////////////////////////////////////////////
298
 
 
299
 
/** @internal
300
 
 * Helper for the FromString() template, doesn't need to be called directly.
301
 
 */
302
 
DECLEXPORT (uint64_t) FromStringInteger (const char *aValue, bool aSigned,
303
 
                                         int aBits, uint64_t aMin, uint64_t aMax);
304
 
 
305
 
/**
306
 
 * Generic template function to perform a conversion of an UTF-8 string to an
307
 
 * arbitrary value of type @a T.
308
 
 *
309
 
 * This generic template is implenented only for 8-, 16-, 32- and 64- bit
310
 
 * signed and unsigned integers where it uses RTStrTo[U]Int64() to perform the
311
 
 * conversion. For all other types it throws an ENotImplemented
312
 
 * exception. Individual template specializations for known types should do
313
 
 * the conversion job.
314
 
 *
315
 
 * If the conversion is not possible (for example the string format is wrong
316
 
 * or meaningless for the given type), this template will throw an
317
 
 * ENoConversion exception. All specializations must do the same.
318
 
 *
319
 
 * If the @a aValue argument is NULL, this method will throw an ENoValue
320
 
 * exception. All specializations must do the same.
321
 
 *
322
 
 * @param aValue Value to convert.
323
 
 *
324
 
 * @return Result of conversion.
325
 
 */
326
 
template <typename T>
327
 
T FromString (const char *aValue)
328
 
{
329
 
    if (std::numeric_limits <T>::is_integer)
330
 
    {
331
 
        bool sign = std::numeric_limits <T>::is_signed;
332
 
        int bits = std::numeric_limits <T>::digits + (sign ? 1 : 0);
333
 
 
334
 
        return (T) FromStringInteger (aValue, sign, bits,
335
 
                                      (uint64_t) std::numeric_limits <T>::min(),
336
 
                                      (uint64_t) std::numeric_limits <T>::max());
337
 
    }
338
 
 
339
 
    throw xml::ENotImplemented (RT_SRC_POS);
340
 
}
341
 
 
342
 
/**
343
 
 * Specialization of FromString for bool.
344
 
 *
345
 
 * Converts "true", "yes", "on" to true and "false", "no", "off" to false.
346
 
 */
347
 
template<> DECLEXPORT (bool) FromString <bool> (const char *aValue);
348
 
 
349
 
/**
350
 
 * Specialization of FromString for RTTIMESPEC.
351
 
 *
352
 
 * Converts the date in ISO format (<YYYY>-<MM>-<DD>T<hh>:<mm>:<ss>[timezone])
353
 
 * to a RTTIMESPEC value. Currently, the timezone must always be Z (UTC).
354
 
 */
355
 
template<> DECLEXPORT (RTTIMESPEC) FromString <RTTIMESPEC> (const char *aValue);
356
 
 
357
 
/**
358
 
 * Converts a string of hex digits to memory bytes.
359
 
 *
360
 
 * @param aValue String to convert.
361
 
 * @param aLen   Where to store the length of the returned memory
362
 
 *               block (may be NULL).
363
 
 *
364
 
 * @return Result of conversion (a block of @a aLen bytes).
365
 
 */
366
 
DECLEXPORT (stdx::char_auto_ptr) FromString (const char *aValue, size_t *aLen);
367
 
 
368
 
// type -> string conversions
369
 
//////////////////////////////////////////////////////////////////////////////
370
 
 
371
 
/** @internal
372
 
 * Helper for the ToString() template, doesn't need to be called directly.
373
 
 */
374
 
DECLEXPORT (stdx::char_auto_ptr)
375
 
ToStringInteger (uint64_t aValue, unsigned int aBase,
376
 
                 bool aSigned, int aBits);
377
 
 
378
 
/**
379
 
 * Generic template function to perform a conversion of an arbitrary value to
380
 
 * an UTF-8 string.
381
 
 *
382
 
 * This generic template is implemented only for 8-, 16-, 32- and 64- bit
383
 
 * signed and unsigned integers where it uses RTStrFormatNumber() to perform
384
 
 * the conversion. For all other types it throws an ENotImplemented
385
 
 * exception. Individual template specializations for known types should do
386
 
 * the conversion job. If the conversion is not possible (for example the
387
 
 * given value doesn't have a string representation), the relevant
388
 
 * specialization should throw an ENoConversion exception.
389
 
 *
390
 
 * If the @a aValue argument's value would convert to a NULL string, this
391
 
 * method will throw an ENoValue exception. All specializations must do the
392
 
 * same.
393
 
 *
394
 
 * @param aValue Value to convert.
395
 
 * @param aExtra Extra flags to define additional formatting. In case of
396
 
 *               integer types, it's the base used for string representation.
397
 
 *
398
 
 * @return Result of conversion.
399
 
 */
400
 
template <typename T>
401
 
stdx::char_auto_ptr ToString (const T &aValue, unsigned int aExtra = 0)
402
 
{
403
 
    if (std::numeric_limits <T>::is_integer)
404
 
    {
405
 
        bool sign = std::numeric_limits <T>::is_signed;
406
 
        int bits = std::numeric_limits <T>::digits + (sign ? 1 : 0);
407
 
 
408
 
        return ToStringInteger (aValue, aExtra, sign, bits);
409
 
    }
410
 
 
411
 
    throw xml::ENotImplemented (RT_SRC_POS);
412
 
}
413
 
 
414
 
/**
415
 
 * Specialization of ToString for bool.
416
 
 *
417
 
 * Converts true to "true" and false to "false". @a aExtra is not used.
418
 
 */
419
 
template<> DECLEXPORT (stdx::char_auto_ptr)
420
 
ToString <bool> (const bool &aValue, unsigned int aExtra);
421
 
 
422
 
/**
423
 
 * Specialization of ToString for RTTIMESPEC.
424
 
 *
425
 
 * Converts the RTTIMESPEC value to the date string in ISO format
426
 
 * (<YYYY>-<MM>-<DD>T<hh>:<mm>:<ss>[timezone]). Currently, the timezone will
427
 
 * always be Z (UTC).
428
 
 *
429
 
 * @a aExtra is not used.
430
 
 */
431
 
template<> DECLEXPORT (stdx::char_auto_ptr)
432
 
ToString <RTTIMESPEC> (const RTTIMESPEC &aValue, unsigned int aExtra);
433
 
 
434
 
/**
435
 
 * Converts memory bytes to a null-terminated string of hex values.
436
 
 *
437
 
 * @param aData Pointer to the memory block.
438
 
 * @param aLen  Length of the memory block.
439
 
 *
440
 
 * @return Result of conversion.
441
 
 */
442
 
DECLEXPORT (stdx::char_auto_ptr) ToString (const void *aData, size_t aLen);
443
 
 
444
 
#if defined VBOX_MAIN_SETTINGS_ADDONS
445
 
 
446
 
/// @todo once string data in Bstr and Utf8Str is auto_ref_ptr, enable the
447
 
/// code below
448
 
 
449
 
#if 0
450
 
 
451
 
/** Specialization of FromString for Bstr. */
452
 
template<> com::Bstr FromString <com::Bstr> (const char *aValue);
453
 
 
454
 
#endif
455
 
 
456
 
/** Specialization of ToString for Bstr. */
457
 
template<> stdx::char_auto_ptr
458
 
ToString <com::Bstr> (const com::Bstr &aValue, unsigned int aExtra);
459
 
 
460
 
/** Specialization of FromString for Guid. */
461
 
template<> com::Guid FromString <com::Guid> (const char *aValue);
462
 
 
463
 
/** Specialization of ToString for Guid. */
464
 
template<> stdx::char_auto_ptr
465
 
ToString <com::Guid> (const com::Guid &aValue, unsigned int aExtra);
466
 
 
467
 
#endif // VBOX_MAIN_SETTINGS_ADDONS
468
 
 
469
 
// the rest
470
 
//////////////////////////////////////////////////////////////////////////////
471
 
 
472
 
/**
473
 
 * The Key class represents a settings key.
474
 
 *
475
 
 * Every settings key has a name and zero or more uniquely named values
476
 
 * (attributes). There is a special attribute with a NULL name that is called
477
 
 * a key value.
478
 
 *
479
 
 * Besides values, settings keys may contain other settings keys. This way,
480
 
 * settings keys form a tree-like (or a directory-like) hierarchy of keys. Key
481
 
 * names do not need to be unique even if they belong to the same parent key
482
 
 * which allows to have an array of keys of the same name.
483
 
 *
484
 
 * @note Key and Value objects returned by methods of the Key and TreeBackend
485
 
 * classes are owned by the given TreeBackend instance and may refer to data
486
 
 * that becomes invalid when this TreeBackend instance is destroyed.
487
 
 */
488
 
class VBOXXML_CLASS Key
489
 
{
490
 
public:
491
 
 
492
 
    typedef std::list <Key> List;
493
 
 
494
 
    /**
495
 
     * Key backend interface used to perform actual key operations.
496
 
     *
497
 
     * This interface is implemented by backends that provide specific ways of
498
 
     * storing settings keys.
499
 
     */
500
 
    class VBOXXML_CLASS Backend : public stdx::auto_ref
501
 
    {
502
 
    public:
503
 
 
504
 
        /** Performs the Key::name() function. */
505
 
        virtual const char *name() const = 0;
506
 
 
507
 
        /** Performs the Key::setName() function. */
508
 
        virtual void setName (const char *aName) = 0;
509
 
 
510
 
        /** Performs the Key::stringValue() function. */
511
 
        virtual const char *value (const char *aName) const = 0;
512
 
 
513
 
        /** Performs the Key::setStringValue() function. */
514
 
        virtual void setValue (const char *aName, const char *aValue) = 0;
515
 
 
516
 
        /** Performs the Key::keys() function. */
517
 
        virtual List keys (const char *aName = NULL) const = 0;
518
 
 
519
 
        /** Performs the Key::findKey() function. */
520
 
        virtual Key findKey (const char *aName) const = 0;
521
 
 
522
 
        /** Performs the Key::appendKey() function. */
523
 
        virtual Key appendKey (const char *aName) = 0;
524
 
 
525
 
        /** Performs the Key::zap() function. */
526
 
        virtual void zap() = 0;
527
 
 
528
 
        /**
529
 
         * Returns an opaque value that uniquely represents the position of
530
 
         * this key on the tree which is used to compare two keys. Two or more
531
 
         * keys may return the same value only if they actually represent the
532
 
         * same key (i.e. they have the same list of parents and children).
533
 
         */
534
 
        virtual void *position() const = 0;
535
 
    };
536
 
 
537
 
    /**
538
 
     * Creates a new key object. If @a aBackend is @c NULL then a null key is
539
 
     * created.
540
 
     *
541
 
     * Regular API users should never need to call this method with something
542
 
     * other than NULL argument (which is the default).
543
 
     *
544
 
     * @param aBackend      Key backend to use.
545
 
     */
546
 
    Key (Backend *aBackend = NULL) : m (aBackend) {}
547
 
 
548
 
    /**
549
 
     * Returns @c true if this key is null.
550
 
     */
551
 
    bool isNull() const { return m.is_null(); }
552
 
 
553
 
    /**
554
 
     * Makes this object a null key.
555
 
     *
556
 
     * Note that as opposed to #zap(), this methid does not delete the key from
557
 
     * the list of children of its parent key.
558
 
     */
559
 
    void setNull() { m = NULL; }
560
 
 
561
 
    /**
562
 
     * Returns the name of this key.
563
 
     * Returns NULL if this object a null (uninitialized) key.
564
 
     */
565
 
    const char *name() const { return m.is_null() ? NULL : m->name(); }
566
 
 
567
 
    /**
568
 
     * Sets the name of this key.
569
 
     *
570
 
     * @param aName New key name.
571
 
     */
572
 
    void setName (const char *aName) { if (!m.is_null()) m->setName (aName); }
573
 
 
574
 
    /**
575
 
     * Returns the value of the attribute with the given name as an UTF-8
576
 
     * string. Returns @c NULL if there is no attribute with the given name.
577
 
     *
578
 
     * @param aName     Name of the attribute. NULL may be used to
579
 
     *                  get the key value.
580
 
     */
581
 
    const char *stringValue (const char *aName) const
582
 
    {
583
 
        return m.is_null() ? NULL : m->value (aName);
584
 
    }
585
 
 
586
 
    /**
587
 
     * Sets the value of the attribute with the given name from an UTF-8
588
 
     * string. This method will do a copy of the supplied @a aValue string.
589
 
     *
590
 
     * @param aName     Name of the attribute. NULL may be used to
591
 
     *                  set the key value.
592
 
     * @param aValue    New value of the attribute. NULL may be used to
593
 
     *                  delete the value instead of setting it.
594
 
     */
595
 
    void setStringValue (const char *aName, const char *aValue)
596
 
    {
597
 
        if (!m.is_null()) m->setValue (aName, aValue);
598
 
    }
599
 
 
600
 
    /**
601
 
     * Returns the value of the attribute with the given name as an object of
602
 
     * type @a T. Throws ENoValue if there is no attribute with the given
603
 
     * name.
604
 
     *
605
 
     * This function calls #stringValue() to get the string representation of
606
 
     * the attribute and then calls the FromString() template to convert this
607
 
     * string to a value of the given type.
608
 
     *
609
 
     * @param aName     Name of the attribute. NULL may be used to
610
 
     *                  get the key value.
611
 
     */
612
 
    template <typename T>
613
 
    T value (const char *aName) const
614
 
    {
615
 
        try
616
 
        {
617
 
            return FromString <T> (stringValue (aName));
618
 
        }
619
 
        catch (const ENoValue &)
620
 
        {
621
 
            throw ENoValue(com::Utf8StrFmt("No such attribute '%s'", aName));
622
 
        }
623
 
    }
624
 
 
625
 
    /**
626
 
     * Returns the value of the attribute with the given name as an object of
627
 
     * type @a T. Returns the given default value if there is no attribute
628
 
     * with the given name.
629
 
     *
630
 
     * This function calls #stringValue() to get the string representation of
631
 
     * the attribute and then calls the FromString() template to convert this
632
 
     * string to a value of the given type.
633
 
     *
634
 
     * @param aName     Name of the attribute. NULL may be used to
635
 
     *                  get the key value.
636
 
     * @param aDefault  Default value to return for the missing attribute.
637
 
     */
638
 
    template <typename T>
639
 
    T valueOr (const char *aName, const T &aDefault) const
640
 
    {
641
 
        try
642
 
        {
643
 
            return FromString <T> (stringValue (aName));
644
 
        }
645
 
        catch (const ENoValue &)
646
 
        {
647
 
            return aDefault;
648
 
        }
649
 
    }
650
 
 
651
 
    /**
652
 
     * Sets the value of the attribute with the given name from an object of
653
 
     * type @a T. This method will do a copy of data represented by @a aValue
654
 
     * when necessary.
655
 
     *
656
 
     * This function converts the given value to a string using the ToString()
657
 
     * template and then calls #setStringValue().
658
 
     *
659
 
     * @param aName     Name of the attribute. NULL may be used to
660
 
     *                  set the key value.
661
 
     * @param aValue    New value of the attribute.
662
 
     * @param aExtra    Extra field used by some types to specify additional
663
 
     *                  details for storing the value as a string (such as the
664
 
     *                  base for decimal numbers).
665
 
     */
666
 
    template <typename T>
667
 
    void setValue (const char *aName, const T &aValue, unsigned int aExtra = 0)
668
 
    {
669
 
        try
670
 
        {
671
 
            stdx::char_auto_ptr value = ToString (aValue, aExtra);
672
 
            setStringValue (aName, value.get());
673
 
        }
674
 
        catch (const ENoValue &)
675
 
        {
676
 
            throw ENoValue(com::Utf8StrFmt("No value for attribute '%s'", aName));
677
 
        }
678
 
    }
679
 
 
680
 
    /**
681
 
     * Sets the value of the attribute with the given name from an object of
682
 
     * type @a T. If the value of the @a aValue object equals to the value of
683
 
     * the given @a aDefault object, then the attribute with the given name
684
 
     * will be deleted instead of setting its value to @a aValue.
685
 
     *
686
 
     * This function converts the given value to a string using the ToString()
687
 
     * template and then calls #setStringValue().
688
 
     *
689
 
     * @param aName     Name of the attribute. NULL may be used to
690
 
     *                  set the key value.
691
 
     * @param aValue    New value of the attribute.
692
 
     * @param aDefault  Default value to compare @a aValue to.
693
 
     * @param aExtra    Extra field used by some types to specify additional
694
 
     *                  details for storing the value as a string (such as the
695
 
     *                  base for decimal numbers).
696
 
     */
697
 
    template <typename T>
698
 
    void setValueOr (const char *aName, const T &aValue, const T &aDefault,
699
 
                     unsigned int aExtra = 0)
700
 
    {
701
 
        if (aValue == aDefault)
702
 
            zapValue (aName);
703
 
        else
704
 
            setValue <T> (aName, aValue, aExtra);
705
 
    }
706
 
 
707
 
    /**
708
 
     * Deletes the value of the attribute with the given name.
709
 
     * Shortcut to <tt>setStringValue(aName, NULL)</tt>.
710
 
     */
711
 
    void zapValue (const char *aName) { setStringValue (aName, NULL); }
712
 
 
713
 
    /**
714
 
     * Returns the key value.
715
 
     * Shortcut to <tt>stringValue (NULL)</tt>.
716
 
     */
717
 
    const char *keyStringValue() const { return stringValue (NULL); }
718
 
 
719
 
    /**
720
 
     * Sets the key value.
721
 
     * Shortcut to <tt>setStringValue (NULL, aValue)</tt>.
722
 
     */
723
 
    void setKeyStringValue (const char *aValue) { setStringValue (NULL, aValue); }
724
 
 
725
 
    /**
726
 
     * Returns the key value.
727
 
     * Shortcut to <tt>value (NULL)</tt>.
728
 
     */
729
 
    template <typename T>
730
 
    T keyValue() const { return value <T> (NULL); }
731
 
 
732
 
    /**
733
 
     * Returns the key value or the given default if the key value is NULL.
734
 
     * Shortcut to <tt>value (NULL)</tt>.
735
 
     */
736
 
    template <typename T>
737
 
    T keyValueOr (const T &aDefault) const { return valueOr <T> (NULL, aDefault); }
738
 
 
739
 
    /**
740
 
     * Sets the key value.
741
 
     * Shortcut to <tt>setValue (NULL, aValue, aExtra)</tt>.
742
 
     */
743
 
    template <typename T>
744
 
    void setKeyValue (const T &aValue, unsigned int aExtra = 0)
745
 
    {
746
 
        setValue <T> (NULL, aValue, aExtra);
747
 
    }
748
 
 
749
 
    /**
750
 
     * Sets the key value.
751
 
     * Shortcut to <tt>setValueOr (NULL, aValue, aDefault)</tt>.
752
 
     */
753
 
    template <typename T>
754
 
    void setKeyValueOr (const T &aValue, const T &aDefault,
755
 
                        unsigned int aExtra = 0)
756
 
    {
757
 
        setValueOr <T> (NULL, aValue, aDefault, aExtra);
758
 
    }
759
 
 
760
 
    /**
761
 
     * Deletes the key value.
762
 
     * Shortcut to <tt>zapValue (NULL)</tt>.
763
 
     */
764
 
    void zapKeyValue () { zapValue (NULL); }
765
 
 
766
 
    /**
767
 
     * Returns a list of all child keys named @a aName.
768
 
     *
769
 
     * If @a aname is @c NULL, returns a list of all child keys.
770
 
     *
771
 
     * @param aName     Child key name to list.
772
 
     */
773
 
    List keys (const char *aName = NULL) const
774
 
    {
775
 
        return m.is_null() ? List() : m->keys (aName);
776
 
    };
777
 
 
778
 
    /**
779
 
     * Returns the first child key with the given name.
780
 
     *
781
 
     * Throws ENoKey if no child key with the given name exists.
782
 
     *
783
 
     * @param aName     Child key name.
784
 
     */
785
 
    Key key (const char *aName) const
786
 
    {
787
 
        Key key = findKey (aName);
788
 
        if (key.isNull())
789
 
        {
790
 
            throw ENoKey(com::Utf8StrFmt("No such key '%s'", aName));
791
 
        }
792
 
        return key;
793
 
    }
794
 
 
795
 
    /**
796
 
     * Returns the first child key with the given name.
797
 
     *
798
 
     * As opposed to #key(), this method will not throw an exception if no
799
 
     * child key with the given name exists, but return a null key instead.
800
 
     *
801
 
     * @param aName     Child key name.
802
 
     */
803
 
    Key findKey (const char *aName) const
804
 
    {
805
 
        return m.is_null() ? Key() : m->findKey (aName);
806
 
    }
807
 
 
808
 
    /**
809
 
     * Creates a key with the given name as a child of this key and returns it
810
 
     * to the caller.
811
 
     *
812
 
     * If one or more child keys with the given name already exist, no new key
813
 
     * is created but the first matching child key is returned.
814
 
     *
815
 
     * @param aName Name of the child key to create.
816
 
     */
817
 
    Key createKey (const char *aName)
818
 
    {
819
 
        Key key = findKey (aName);
820
 
        if (key.isNull())
821
 
            key = appendKey (aName);
822
 
        return key;
823
 
    }
824
 
 
825
 
    /**
826
 
     * Appends a key with the given name to the list of child keys of this key
827
 
     * and returns the appended key to the caller.
828
 
     *
829
 
     * @param aName Name of the child key to create.
830
 
     */
831
 
    Key appendKey (const char *aName)
832
 
    {
833
 
        return m.is_null() ? Key() : m->appendKey (aName);
834
 
    }
835
 
 
836
 
    /**
837
 
     * Deletes this key.
838
 
     *
839
 
     * The deleted key is removed from the list of child keys of its parent
840
 
     * key and becomes a null object.
841
 
     */
842
 
    void zap()
843
 
    {
844
 
        if (!m.is_null())
845
 
        {
846
 
            m->zap();
847
 
            setNull();
848
 
        }
849
 
    }
850
 
 
851
 
    /**
852
 
     * Compares this object with the given object and returns @c true if both
853
 
     * represent the same key on the settings tree or if both are null
854
 
     * objects.
855
 
     *
856
 
     * @param that Object to compare this object with.
857
 
     */
858
 
    bool operator== (const Key &that) const
859
 
    {
860
 
        return m == that.m ||
861
 
               (!m.is_null() && !that.m.is_null() &&
862
 
                m->position() == that.m->position());
863
 
    }
864
 
 
865
 
    /**
866
 
     * Counterpart to operator==().
867
 
     */
868
 
    bool operator!= (const Key &that) const { return !operator== (that); }
869
 
 
870
 
private:
871
 
 
872
 
    stdx::auto_ref_ptr <Backend> m;
873
 
 
874
 
    friend class TreeBackend;
875
 
};
876
 
 
877
 
/**
878
 
 * The TreeBackend class represents a storage backend used to read a settings
879
 
 * tree from and write it to a stream.
880
 
 *
881
 
 * @note All Key objects returned by any of the TreeBackend methods (and by
882
 
 * methods of returned Key objects) are owned by the given TreeBackend
883
 
 * instance. When this instance is destroyed, all Key objects become invalid
884
 
 * and an attempt to access Key data will cause the program crash.
885
 
 */
886
 
class VBOXXML_CLASS TreeBackend
887
 
{
888
 
public:
889
 
 
890
 
    /**
891
 
     * Reads and parses the given input stream.
892
 
     *
893
 
     * On success, the previous settings tree owned by this backend (if any)
894
 
     * is deleted.
895
 
     *
896
 
     * The optional schema URI argument determines the name of the schema to
897
 
     * use for input validation. If the schema URI is NULL then the validation
898
 
     * is not performed. Note that you may set a custom input resolver if you
899
 
     * want to provide the input stream for the schema file (and for other
900
 
     * external entities) instead of letting the backend to read the specified
901
 
     * URI directly.
902
 
     *
903
 
     * This method will set the read/write position to the beginning of the
904
 
     * given stream before reading. After the stream has been successfully
905
 
     * parsed, the position will be set back to the beginning.
906
 
     *
907
 
     * @param aInput        Input stream.
908
 
     * @param aSchema       Schema URI to use for input stream validation.
909
 
     * @param aFlags        Optional bit flags.
910
 
     */
911
 
    void read (xml::Input &aInput, const char *aSchema = NULL, int aFlags = 0)
912
 
    {
913
 
        aInput.setPos (0);
914
 
        rawRead (aInput, aSchema, aFlags);
915
 
        aInput.setPos (0);
916
 
    }
917
 
 
918
 
    /**
919
 
     * Reads and parses the given input stream in a raw fashion.
920
 
     *
921
 
     * This method doesn't set the stream position to the beginnign before and
922
 
     * after reading but instead leaves it as is in both cases. It's the
923
 
     * caller's responsibility to maintain the correct position.
924
 
     *
925
 
     * @see read()
926
 
     */
927
 
    virtual void rawRead (xml::Input &aInput, const char *aSchema = NULL,
928
 
                          int aFlags = 0) = 0;
929
 
 
930
 
    /**
931
 
     * Writes the current settings tree to the given output stream.
932
 
     *
933
 
     * This method will set the read/write position to the beginning of the
934
 
     * given stream before writing. After the settings have been successfully
935
 
     * written to the stream, the stream will be truncated at the position
936
 
     * following the last byte written by this method anc ghd position will be
937
 
     * set back to the beginning.
938
 
     *
939
 
     * @param aOutput       Output stream.
940
 
     */
941
 
    void write (xml::Output &aOutput)
942
 
    {
943
 
        aOutput.setPos (0);
944
 
        rawWrite (aOutput);
945
 
        aOutput.truncate();
946
 
        aOutput.setPos (0);
947
 
    }
948
 
 
949
 
    /**
950
 
     * Writes the current settings tree to the given output stream in a raw
951
 
     * fashion.
952
 
     *
953
 
     * This method doesn't set the stream position to the beginnign before and
954
 
     * after reading and doesn't truncate the stream, but instead leaves it as
955
 
     * is in both cases. It's the caller's responsibility to maintain the
956
 
     * correct position and perform truncation.
957
 
     *
958
 
     * @see write()
959
 
     */
960
 
    virtual void rawWrite (xml::Output &aOutput) = 0;
961
 
 
962
 
    /**
963
 
     * Deletes the current settings tree.
964
 
     */
965
 
    virtual void reset() = 0;
966
 
 
967
 
    /**
968
 
     * Returns the root settings key.
969
 
     */
970
 
    virtual Key &rootKey() const = 0;
 
61
class ConfigFileError;
 
62
 
 
63
////////////////////////////////////////////////////////////////////////////////
 
64
//
 
65
// Helper classes
 
66
//
 
67
////////////////////////////////////////////////////////////////////////////////
 
68
 
 
69
// ExtraDataItem (used by both VirtualBox.xml and machines XML)
 
70
typedef std::map<com::Utf8Str, com::Utf8Str> ExtraDataItemsMap;
 
71
struct USBDeviceFilter;
 
72
typedef std::list<USBDeviceFilter> USBDeviceFiltersList;
 
73
 
 
74
/**
 
75
 * Common base class for both MainConfigFile and MachineConfigFile
 
76
 * which contains some common logic for both.
 
77
 */
 
78
class ConfigFileBase
 
79
{
 
80
public:
 
81
    bool fileExists();
971
82
 
972
83
protected:
973
 
 
974
 
    static Key::Backend *GetKeyBackend (const Key &aKey) { return aKey.m.raw(); }
975
 
};
976
 
 
977
 
class XmlKeyBackend;
978
 
 
979
 
/**
980
 
 * The XmlTreeBackend class uses XML markup to store settings trees.
981
 
 *
982
 
 * @note libxml2 and libxslt libraries used by the XmlTreeBackend are not
983
 
 * fully reentrant. To "fix" this, the XmlTreeBackend backend serializes access
984
 
 * to such non-reentrant parts using a global mutex so that only one thread can
985
 
 * use non-reentrant code at a time. Currently, this relates to the #rawRead()
986
 
 * method (and to #read() as a consequence). This means that only one thread can
987
 
 * parse an XML stream at a time; other threads trying to parse same or
988
 
 * different streams using different XmlTreeBackend and Input instances
989
 
 * will have to wait.
990
 
 *
991
 
 * Keep in mind that the above reentrancy fix does not imply thread-safety: it
992
 
 * is still the caller's responsibility to provide serialization if the same
993
 
 * XmlTreeBackend instnace (as well as instances of other classes from the
994
 
 * settings namespace) needs to be used by more than one thread.
995
 
 */
996
 
class VBOXXML_CLASS XmlTreeBackend : public TreeBackend
997
 
{
998
 
public:
999
 
 
1000
 
    /** Flags for TreeBackend::read(). */
1001
 
    enum
1002
 
    {
1003
 
        /**
1004
 
         * Sbstitute default values for missing attributes that have defaults
1005
 
         * in the XML schema. Otherwise, stringValue() will return NULL for
1006
 
         * such attributes.
1007
 
         */
1008
 
        Read_AddDefaults = RT_BIT (0),
1009
 
    };
1010
 
 
1011
 
    /**
1012
 
     * The EConversionCycle class represents a conversion cycle detected by the
1013
 
     * AutoConverter::needsConversion() implementation.
1014
 
     */
1015
 
    class VBOXXML_CLASS EConversionCycle : public xml::RuntimeError
1016
 
    {
1017
 
    public:
1018
 
 
1019
 
        EConversionCycle (const char *aMsg = NULL) : RuntimeError (aMsg) {}
1020
 
    };
1021
 
 
1022
 
    /**
1023
 
     * The InputResolver class represents an interface to provide input streams
1024
 
     * for external entities given an URL and entity ID.
1025
 
     */
1026
 
    class VBOXXML_CLASS InputResolver
1027
 
    {
1028
 
    public:
1029
 
 
1030
 
        /**
1031
 
         * Returns a newly allocated input stream for the given arguments. The
1032
 
         * caller will delete the returned object when no more necessary.
1033
 
         *
1034
 
         * @param aURI  URI of the external entity.
1035
 
         * @param aID   ID of the external entity (may be NULL).
1036
 
         *
1037
 
         * @return      Input stream created using @c new or NULL to indicate
1038
 
         *              a wrong URI/ID pair.
1039
 
         *
1040
 
         * @todo Return by value after implementing the copy semantics for
1041
 
         * Input subclasses.
1042
 
         */
1043
 
        virtual xml::Input *resolveEntity (const char *aURI, const char *aID) = 0;
1044
 
    };
1045
 
 
1046
 
    /**
1047
 
     * The AutoConverter class represents an interface to automatically convert
1048
 
     * old settings trees to a new version when the tree is read from the
1049
 
     * stream.
1050
 
     */
1051
 
    class VBOXXML_CLASS AutoConverter
1052
 
    {
1053
 
    public:
1054
 
 
1055
 
        /**
1056
 
         * Returns @true if the given tree needs to be converted using the XSLT
1057
 
         * template identified by #templateUri(), or @false if no conversion is
1058
 
         * required.
1059
 
         *
1060
 
         * The implementation normally checks for the "version" value of the
1061
 
         * root key to determine if the conversion is necessary. When the
1062
 
         * @a aOldVersion argument is not NULL, the implementation must return a
1063
 
         * non-NULL non-empty string representing the old version (before
1064
 
         * conversion) in it this string is used by XmlTreeBackend::oldVersion()
1065
 
         * and must be non-NULL to indicate that the conversion has been
1066
 
         * performed on the tree. The returned string must be allocated using
1067
 
         * RTStrDup() or such.
1068
 
         *
1069
 
         * This method is called again after the successful transformation to
1070
 
         * let the implementation retry the version check and request another
1071
 
         * transformation if necessary. This may be used to perform multi-step
1072
 
         * conversion like this: 1.1 => 1.2, 1.2 => 1.3 (instead of 1.1 => 1.3)
1073
 
         * which saves from the need to update all previous conversion
1074
 
         * templates to make each of them convert directly to the recent
1075
 
         * version.
1076
 
         *
1077
 
         * @note Multi-step transformations are performed in a loop that exits
1078
 
         *       only when this method returns @false. It's up to the
1079
 
         *       implementation to detect cycling (repeated requests to convert
1080
 
         *       from the same version) wrong version order, etc. and throw an
1081
 
         *       EConversionCycle exception to break the loop without returning
1082
 
         *       @false (which means the transformation succeeded).
1083
 
         *
1084
 
         * @param aRoot                 Root settings key.
1085
 
         * @param aOldVersionString     Where to store old version string
1086
 
         *                              pointer. May be NULL. Allocated memory is
1087
 
         *                              freed by the caller using RTStrFree().
1088
 
         */
1089
 
        virtual bool needsConversion (const Key &aRoot,
1090
 
                                      char **aOldVersion) const = 0;
1091
 
 
1092
 
        /**
1093
 
         * Returns the URI of the XSLT template to perform the conversion.
1094
 
         * This template will be applied to the tree if #needsConversion()
1095
 
         * returns @c true for this tree.
1096
 
         */
1097
 
        virtual const char *templateUri() const = 0;
1098
 
    };
1099
 
 
1100
 
    XmlTreeBackend();
1101
 
    ~XmlTreeBackend();
1102
 
 
1103
 
    /**
1104
 
     * Sets an external entity resolver used to provide input streams for
1105
 
     * entities referred to by the XML document being parsed.
1106
 
     *
1107
 
     * The given resolver object must exist as long as this instance exists or
1108
 
     * until a different resolver is set using setInputResolver() or reset
1109
 
     * using resetInputResolver().
1110
 
     *
1111
 
     * @param aResolver Resolver to use.
1112
 
     */
1113
 
    void setInputResolver (InputResolver &aResolver);
1114
 
 
1115
 
    /**
1116
 
     * Resets the entity resolver to the default resolver. The default
1117
 
     * resolver provides support for 'file:' and 'http:' protocols.
1118
 
     */
1119
 
    void resetInputResolver();
1120
 
 
1121
 
    /**
1122
 
     * Sets a settings tree converter and enables the automatic conversion.
1123
 
     *
1124
 
     * The Automatic settings tree conversion is useful for upgrading old
1125
 
     * settings files to the new version transparently during execution of the
1126
 
     * #read() method.
1127
 
     *
1128
 
     * The automatic conversion takes place after reading the document from the
1129
 
     * stream but before validating it. The given converter is asked if the
1130
 
     * conversion is necessary using the AutoConverter::needsConversion() call,
1131
 
     * and if so, the XSLT template specified by AutoConverter::templateUri() is
1132
 
     * applied to the settings tree.
1133
 
     *
1134
 
     * Note that in order to make the result of the conversion permanent, the
1135
 
     * settings tree needs to be exlicitly written back to the stream.
1136
 
     *
1137
 
     * The given converter object must exist as long as this instance exists or
1138
 
     * until a different converter is set using setAutoConverter() or reset
1139
 
     * using resetAutoConverter().
1140
 
     *
1141
 
     * @param aConverter    Settings converter to use.
1142
 
     */
1143
 
    void setAutoConverter (AutoConverter &aConverter);
1144
 
 
1145
 
    /**
1146
 
     * Disables the automatic settings conversion previously enabled by
1147
 
     * setAutoConverter(). By default automatic conversion it is disabled.
1148
 
     */
1149
 
    void resetAutoConverter();
1150
 
 
1151
 
    /**
1152
 
     * Returns a non-NULL string if the automatic settings conversion has been
1153
 
     * performed during the last successful #read() call. Returns @c NULL if
1154
 
     * there was no settings conversion.
1155
 
     *
1156
 
     * If #read() fails, this method will return the version string set by the
1157
 
     * previous successful #read() call or @c NULL if there were no #read()
1158
 
     * calls.
1159
 
     */
1160
 
    const char *oldVersion() const;
1161
 
 
1162
 
    void rawRead (xml::Input &aInput, const char *aSchema = NULL, int aFlags = 0);
1163
 
    void rawWrite (xml::Output &aOutput);
1164
 
    void reset();
1165
 
    Key &rootKey() const;
1166
 
 
1167
 
private:
1168
 
 
1169
 
    /* Obscure class data */
 
84
    ConfigFileBase(const com::Utf8Str *pstrFilename);
 
85
    ~ConfigFileBase();
 
86
 
 
87
    void parseUUID(com::Guid &guid,
 
88
                   const com::Utf8Str &strUUID) const;
 
89
    void parseTimestamp(RTTIMESPEC &timestamp,
 
90
                        const com::Utf8Str &str) const;
 
91
 
 
92
    com::Utf8Str makeString(const RTTIMESPEC &tm);
 
93
    com::Utf8Str makeString(const com::Guid &guid);
 
94
 
 
95
    void readExtraData(const xml::ElementNode &elmExtraData,
 
96
                       ExtraDataItemsMap &map);
 
97
    void readUSBDeviceFilters(const xml::ElementNode &elmDeviceFilters,
 
98
                              USBDeviceFiltersList &ll);
 
99
 
 
100
    void createStubDocument();
 
101
 
 
102
    void writeExtraData(xml::ElementNode &elmParent, const ExtraDataItemsMap &me);
 
103
    void writeUSBDeviceFilters(xml::ElementNode &elmParent,
 
104
                               const USBDeviceFiltersList &ll,
 
105
                               bool fHostMode);
 
106
 
 
107
    void clearDocument();
 
108
 
1170
109
    struct Data;
1171
 
    std::auto_ptr <Data> m;
1172
 
 
1173
 
    /* auto_ptr data doesn't have proper copy semantics */
1174
 
    DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP (XmlTreeBackend)
1175
 
 
1176
 
    static int ReadCallback (void *aCtxt, char *aBuf, int aLen);
1177
 
    static int WriteCallback (void *aCtxt, const char *aBuf, int aLen);
1178
 
    static int CloseCallback (void *aCtxt);
1179
 
 
1180
 
    static void ValidityErrorCallback (void *aCtxt, const char *aMsg, ...);
1181
 
    static void ValidityWarningCallback (void *aCtxt, const char *aMsg, ...);
1182
 
    static void StructuredErrorCallback (void *aCtxt, xmlErrorPtr aErr);
1183
 
 
1184
 
    static xmlParserInput *ExternalEntityLoader (const char *aURI,
1185
 
                                                 const char *aID,
1186
 
                                                 xmlParserCtxt *aCtxt);
1187
 
 
1188
 
    static XmlTreeBackend *sThat;
1189
 
 
1190
 
    static XmlKeyBackend *GetKeyBackend (const Key &aKey)
1191
 
    { return (XmlKeyBackend *) TreeBackend::GetKeyBackend (aKey); }
1192
 
};
1193
 
 
1194
 
} /* namespace settings */
1195
 
 
1196
 
 
1197
 
/*
1198
 
 * VBoxXml
1199
 
 *
1200
 
 *
 
110
    Data *m;
 
111
 
 
112
    friend class ConfigFileError;
 
113
};
 
114
 
 
115
////////////////////////////////////////////////////////////////////////////////
 
116
//
 
117
// VirtualBox.xml structures
 
118
//
 
119
////////////////////////////////////////////////////////////////////////////////
 
120
 
 
121
struct USBDeviceFilter
 
122
{
 
123
    USBDeviceFilter()
 
124
        : fActive(false),
 
125
          action(USBDeviceFilterAction_Null),
 
126
          ulMaskedInterfaces(0)
 
127
    {}
 
128
 
 
129
    com::Utf8Str            strName;
 
130
    bool                    fActive;
 
131
    com::Utf8Str            strVendorId,
 
132
                            strProductId,
 
133
                            strRevision,
 
134
                            strManufacturer,
 
135
                            strProduct,
 
136
                            strSerialNumber,
 
137
                            strPort;
 
138
    USBDeviceFilterAction_T action;                 // only used with host USB filters
 
139
    com::Utf8Str            strRemote;              // irrelevant for host USB objects
 
140
    uint32_t                ulMaskedInterfaces;     // irrelevant for host USB objects
 
141
};
 
142
 
 
143
struct Host
 
144
{
 
145
    USBDeviceFiltersList    llUSBDeviceFilters;
 
146
};
 
147
 
 
148
struct SystemProperties
 
149
{
 
150
    SystemProperties()
 
151
        : ulLogHistoryCount(3)
 
152
    {}
 
153
 
 
154
    com::Utf8Str            strDefaultMachineFolder;
 
155
    com::Utf8Str            strDefaultHardDiskFolder;
 
156
    com::Utf8Str            strDefaultHardDiskFormat;
 
157
    com::Utf8Str            strRemoteDisplayAuthLibrary;
 
158
    com::Utf8Str            strWebServiceAuthLibrary;
 
159
    uint32_t                ulLogHistoryCount;
 
160
};
 
161
 
 
162
typedef std::map<com::Utf8Str, com::Utf8Str> PropertiesMap;
 
163
 
 
164
struct Medium;
 
165
typedef std::list<Medium> MediaList;
 
166
 
 
167
struct Medium
 
168
{
 
169
    com::Guid       uuid;
 
170
    com::Utf8Str    strLocation;
 
171
    com::Utf8Str    strDescription;
 
172
 
 
173
    // the following are for hard disks only:
 
174
    com::Utf8Str    strFormat;
 
175
    bool            fAutoReset;         // optional, only for diffs, default is false
 
176
    PropertiesMap   properties;
 
177
    MediumType_T    hdType;
 
178
 
 
179
    MediaList       llChildren;         // only used with hard disks
 
180
};
 
181
 
 
182
struct MachineRegistryEntry
 
183
{
 
184
    com::Guid       uuid;
 
185
    com::Utf8Str    strSettingsFile;
 
186
};
 
187
typedef std::list<MachineRegistryEntry> MachinesRegistry;
 
188
 
 
189
struct DHCPServer
 
190
{
 
191
    com::Utf8Str    strNetworkName,
 
192
                    strIPAddress,
 
193
                    strIPNetworkMask,
 
194
                    strIPLower,
 
195
                    strIPUpper;
 
196
    bool            fEnabled;
 
197
};
 
198
typedef std::list<DHCPServer> DHCPServersList;
 
199
 
 
200
class MainConfigFile : public ConfigFileBase
 
201
{
 
202
public:
 
203
    MainConfigFile(const com::Utf8Str *pstrFilename);
 
204
 
 
205
    typedef enum {Error, HardDisk, DVDImage, FloppyImage} MediaType;
 
206
    void readMedium(MediaType t, const xml::ElementNode &elmMedium, MediaList &llMedia);
 
207
    void readMediaRegistry(const xml::ElementNode &elmMediaRegistry);
 
208
    void readMachineRegistry(const xml::ElementNode &elmMachineRegistry);
 
209
    void readDHCPServers(const xml::ElementNode &elmDHCPServers);
 
210
 
 
211
    void writeHardDisk(xml::ElementNode &elmMedium,
 
212
                       const Medium &m,
 
213
                       uint32_t level);
 
214
    void write(const com::Utf8Str strFilename);
 
215
 
 
216
    Host                    host;
 
217
    SystemProperties        systemProperties;
 
218
    MediaList               llHardDisks,
 
219
                            llDvdImages,
 
220
                            llFloppyImages;
 
221
    MachinesRegistry        llMachines;
 
222
    DHCPServersList         llDhcpServers;
 
223
    ExtraDataItemsMap       mapExtraDataItems;
 
224
};
 
225
 
 
226
////////////////////////////////////////////////////////////////////////////////
 
227
//
 
228
// Machine XML structures
 
229
//
 
230
////////////////////////////////////////////////////////////////////////////////
 
231
 
 
232
struct VRDPSettings
 
233
{
 
234
    VRDPSettings()
 
235
        : fEnabled(true),
 
236
          authType(VRDPAuthType_Null),
 
237
          ulAuthTimeout(5000),
 
238
          fAllowMultiConnection(false),
 
239
          fReuseSingleConnection(false)
 
240
    {}
 
241
 
 
242
    bool            fEnabled;
 
243
    com::Utf8Str    strPort;
 
244
    com::Utf8Str    strNetAddress;
 
245
    VRDPAuthType_T  authType;
 
246
    uint32_t        ulAuthTimeout;
 
247
    bool            fAllowMultiConnection,
 
248
                    fReuseSingleConnection;
 
249
};
 
250
 
 
251
struct BIOSSettings
 
252
{
 
253
    BIOSSettings()
 
254
        : fACPIEnabled(true),
 
255
          fIOAPICEnabled(false),
 
256
          fLogoFadeIn(true),
 
257
          fLogoFadeOut(false),
 
258
          ulLogoDisplayTime(0),
 
259
          biosBootMenuMode(BIOSBootMenuMode_MessageAndMenu),
 
260
          fPXEDebugEnabled(false),
 
261
          llTimeOffset(0)
 
262
    {}
 
263
 
 
264
    bool            fACPIEnabled,
 
265
                    fIOAPICEnabled,
 
266
                    fLogoFadeIn,
 
267
                    fLogoFadeOut;
 
268
    uint32_t        ulLogoDisplayTime;
 
269
    com::Utf8Str    strLogoImagePath;
 
270
    BIOSBootMenuMode_T  biosBootMenuMode;
 
271
    bool            fPXEDebugEnabled;
 
272
    int64_t         llTimeOffset;
 
273
};
 
274
 
 
275
struct USBController
 
276
{
 
277
    USBController()
 
278
        : fEnabled(false),
 
279
          fEnabledEHCI(false)
 
280
    {}
 
281
 
 
282
    bool                    fEnabled;
 
283
    bool                    fEnabledEHCI;
 
284
    USBDeviceFiltersList    llDeviceFilters;
 
285
};
 
286
 
 
287
struct NetworkAdapter
 
288
{
 
289
    NetworkAdapter()
 
290
        : ulSlot(0),
 
291
          type(NetworkAdapterType_Am79C970A),
 
292
          fEnabled(false),
 
293
          fCableConnected(false),
 
294
          ulLineSpeed(0),
 
295
          fTraceEnabled(false),
 
296
          mode(NetworkAttachmentType_Null)
 
297
    {}
 
298
 
 
299
    uint32_t                ulSlot;
 
300
 
 
301
    NetworkAdapterType_T    type;
 
302
    bool                    fEnabled;
 
303
    com::Utf8Str            strMACAddress;
 
304
    bool                    fCableConnected;
 
305
    uint32_t                ulLineSpeed;
 
306
    bool                    fTraceEnabled;
 
307
    com::Utf8Str            strTraceFile;
 
308
 
 
309
    NetworkAttachmentType_T mode;
 
310
    com::Utf8Str            strName;            // with NAT: nat network or empty;
 
311
                                                // with bridged: host interface or empty;
 
312
                                                // otherwise: network name (required)
 
313
};
 
314
typedef std::list<NetworkAdapter> NetworkAdaptersList;
 
315
 
 
316
struct SerialPort
 
317
{
 
318
    SerialPort()
 
319
        : fEnabled(false),
 
320
          ulIOBase(0),
 
321
          ulIRQ(0),
 
322
          portMode(PortMode_Disconnected),
 
323
          fServer(false)
 
324
    {}
 
325
 
 
326
    uint32_t        ulSlot;
 
327
 
 
328
    bool            fEnabled;
 
329
    uint32_t        ulIOBase;
 
330
    uint32_t        ulIRQ;
 
331
    PortMode_T      portMode;
 
332
    com::Utf8Str    strPath;
 
333
    bool            fServer;
 
334
};
 
335
typedef std::list<SerialPort> SerialPortsList;
 
336
 
 
337
struct ParallelPort
 
338
{
 
339
    ParallelPort()
 
340
        : fEnabled(false),
 
341
          ulIOBase(0),
 
342
          ulIRQ(0)
 
343
    {}
 
344
 
 
345
    uint32_t        ulSlot;
 
346
 
 
347
    bool            fEnabled;
 
348
    uint32_t        ulIOBase;
 
349
    uint32_t        ulIRQ;
 
350
    com::Utf8Str    strPath;
 
351
};
 
352
typedef std::list<ParallelPort> ParallelPortsList;
 
353
 
 
354
struct AudioAdapter
 
355
{
 
356
    AudioAdapter()
 
357
        : fEnabled(true),
 
358
          controllerType(AudioControllerType_AC97),
 
359
          driverType(AudioDriverType_Null)
 
360
    {}
 
361
 
 
362
    bool                    fEnabled;
 
363
    AudioControllerType_T   controllerType;
 
364
    AudioDriverType_T       driverType;
 
365
};
 
366
 
 
367
struct SharedFolder
 
368
{
 
369
    SharedFolder()
 
370
        : fWritable(false)
 
371
    {}
 
372
 
 
373
    com::Utf8Str    strName,
 
374
                    strHostPath;
 
375
    bool            fWritable;
 
376
};
 
377
typedef std::list<SharedFolder> SharedFoldersList;
 
378
 
 
379
struct GuestProperty
 
380
{
 
381
    GuestProperty()
 
382
        : timestamp(0)
 
383
    {};
 
384
 
 
385
    com::Utf8Str    strName,
 
386
                    strValue;
 
387
    uint64_t        timestamp;
 
388
    com::Utf8Str    strFlags;
 
389
};
 
390
typedef std::list<GuestProperty> GuestPropertiesList;
 
391
 
 
392
typedef std::map<uint32_t, DeviceType_T> BootOrderMap;
 
393
 
 
394
struct CpuIdLeaf
 
395
{
 
396
    CpuIdLeaf()
 
397
        : ulId(UINT32_MAX),
 
398
          ulEax(0),
 
399
          ulEbx(0),
 
400
          ulEcx(0),
 
401
          ulEdx(0)
 
402
    {}
 
403
 
 
404
    uint32_t                ulId;
 
405
    uint32_t                ulEax;
 
406
    uint32_t                ulEbx;
 
407
    uint32_t                ulEcx;
 
408
    uint32_t                ulEdx;
 
409
};
 
410
typedef std::list<CpuIdLeaf> CpuIdLeafsList;
 
411
 
 
412
struct Hardware
 
413
{
 
414
    Hardware();
 
415
 
 
416
    com::Utf8Str        strVersion;             // hardware version, optional
 
417
    com::Guid           uuid;                   // hardware uuid, optional (null).
 
418
 
 
419
    bool                fHardwareVirt,
 
420
                        fHardwareVirtExclusive,
 
421
                        fNestedPaging,
 
422
                        fVPID,
 
423
                        fSyntheticCpu,
 
424
                        fPAE;
 
425
    uint32_t            cCPUs;
 
426
    CpuIdLeafsList      llCpuIdLeafs;
 
427
 
 
428
    uint32_t            ulMemorySizeMB;
 
429
 
 
430
    BootOrderMap        mapBootOrder;           // item 0 has highest priority
 
431
 
 
432
    uint32_t            ulVRAMSizeMB;
 
433
    uint32_t            cMonitors;
 
434
    bool                fAccelerate3D,
 
435
                        fAccelerate2DVideo;     // requires settings version 1.8 (VirtualBox 3.1)
 
436
    FirmwareType_T      firmwareType;           // requires settings version 1.9 (VirtualBox 3.1)
 
437
 
 
438
    VRDPSettings        vrdpSettings;
 
439
 
 
440
    BIOSSettings        biosSettings;
 
441
    USBController       usbController;
 
442
    NetworkAdaptersList llNetworkAdapters;
 
443
    SerialPortsList     llSerialPorts;
 
444
    ParallelPortsList   llParallelPorts;
 
445
    AudioAdapter        audioAdapter;
 
446
 
 
447
    // technically these two have no business in the hardware section, but for some
 
448
    // clever reason <Hardware> is where they are in the XML....
 
449
    SharedFoldersList   llSharedFolders;
 
450
    ClipboardMode_T     clipboardMode;
 
451
 
 
452
    uint32_t            ulMemoryBalloonSize;
 
453
    uint32_t            ulStatisticsUpdateInterval;
 
454
 
 
455
    GuestPropertiesList llGuestProperties;
 
456
    com::Utf8Str        strNotificationPatterns;
 
457
};
 
458
 
 
459
/**
 
460
 * A device attached to a storage controller. This can either be a
 
461
 * hard disk or a DVD drive or a floppy drive and also specifies
 
462
 * which medium is "in" the drive; as a result, this is a combination
 
463
 * of the Main IMedium and IMediumAttachment interfaces.
1201
464
 */
1202
 
 
1203
 
 
1204
 
class VBoxXmlBase
1205
 
{
1206
 
protected:
1207
 
    VBoxXmlBase();
1208
 
 
1209
 
    ~VBoxXmlBase();
1210
 
 
1211
 
    xmlParserCtxtPtr m_ctxt;
1212
 
};
1213
 
 
1214
 
class VBoxXmlFile : public VBoxXmlBase
 
465
struct AttachedDevice
 
466
{
 
467
    AttachedDevice()
 
468
        : deviceType(DeviceType_Null),
 
469
          fPassThrough(false),
 
470
          lPort(0),
 
471
          lDevice(0)
 
472
    {}
 
473
 
 
474
    DeviceType_T        deviceType;         // only HardDisk, DVD or Floppy are allowed
 
475
 
 
476
    // DVDs can be in pass-through mode:
 
477
    bool                fPassThrough;
 
478
 
 
479
    int32_t             lPort;
 
480
    int32_t             lDevice;
 
481
 
 
482
    // if an image file is attached to the device (ISO, RAW, or hard disk image such as VDI),
 
483
    // this is its UUID; it depends on deviceType which media registry this then needs to
 
484
    // be looked up in. If no image file (only permitted for DVDs and floppies), then the UUID is NULL
 
485
    com::Guid           uuid;
 
486
 
 
487
    // for DVDs and floppies, the attachment can also be a host device:
 
488
    com::Utf8Str        strHostDriveSrc;        // if != NULL, value of <HostDrive>/@src
 
489
};
 
490
typedef std::list<AttachedDevice> AttachedDevicesList;
 
491
 
 
492
struct StorageController
 
493
{
 
494
    StorageController()
 
495
        : storageBus(StorageBus_IDE),
 
496
          controllerType(StorageControllerType_PIIX3),
 
497
          ulPortCount(2),
 
498
          ulInstance(0),
 
499
          lIDE0MasterEmulationPort(0),
 
500
          lIDE0SlaveEmulationPort(0),
 
501
          lIDE1MasterEmulationPort(0),
 
502
          lIDE1SlaveEmulationPort(0)
 
503
    {}
 
504
 
 
505
    com::Utf8Str        strName;
 
506
    StorageBus_T        storageBus;             // _SATA, _SCSI, _IDE
 
507
    StorageControllerType_T controllerType;
 
508
    uint32_t            ulPortCount;
 
509
    uint32_t            ulInstance;
 
510
 
 
511
    // only for when controllerType == StorageControllerType_IntelAhci:
 
512
    int32_t             lIDE0MasterEmulationPort,
 
513
                        lIDE0SlaveEmulationPort,
 
514
                        lIDE1MasterEmulationPort,
 
515
                        lIDE1SlaveEmulationPort;
 
516
 
 
517
    AttachedDevicesList llAttachedDevices;
 
518
};
 
519
typedef std::list<StorageController> StorageControllersList;
 
520
 
 
521
// wrap the list into an extra struct so we can use the struct without
 
522
// having to define the typedef above in headers
 
523
struct Storage
 
524
{
 
525
    StorageControllersList  llStorageControllers;
 
526
};
 
527
 
 
528
struct Snapshot;
 
529
typedef std::list<Snapshot> SnapshotsList;
 
530
 
 
531
struct Snapshot
 
532
{
 
533
    com::Guid       uuid;
 
534
    com::Utf8Str    strName,
 
535
                    strDescription;             // optional
 
536
    RTTIMESPEC      timestamp;
 
537
 
 
538
    com::Utf8Str    strStateFile;               // for online snapshots only
 
539
 
 
540
    Hardware        hardware;
 
541
    Storage         storage;
 
542
 
 
543
    SnapshotsList   llChildSnapshots;
 
544
};
 
545
 
 
546
 
 
547
class MachineConfigFile : public ConfigFileBase
1215
548
{
1216
549
public:
1217
 
    VBoxXmlFile();
1218
 
    ~VBoxXmlFile();
 
550
    MachineConfigFile(const com::Utf8Str *pstrFilename);
 
551
 
 
552
    void readNetworkAdapters(const xml::ElementNode &elmHardware, NetworkAdaptersList &ll);
 
553
    void readCpuIdTree(const xml::ElementNode &elmCpuid, CpuIdLeafsList &ll);
 
554
    void readSerialPorts(const xml::ElementNode &elmUART, SerialPortsList &ll);
 
555
    void readParallelPorts(const xml::ElementNode &elmLPT, ParallelPortsList &ll);
 
556
    void readGuestProperties(const xml::ElementNode &elmGuestProperties, Hardware &hw);
 
557
    void readStorageControllerAttributes(const xml::ElementNode &elmStorageController, StorageController &sctl);
 
558
    void readHardware(const xml::ElementNode &elmHardware, Hardware &hw, Storage &strg);
 
559
    void readHardDiskAttachments_pre1_7(const xml::ElementNode &elmHardDiskAttachments, Storage &strg);
 
560
    void readStorageControllers(const xml::ElementNode &elmStorageControllers, Storage &strg);
 
561
    void readDVDAndFloppies_pre1_9(const xml::ElementNode &elmHardware, Storage &strg);
 
562
    void readSnapshot(const xml::ElementNode &elmSnapshot, Snapshot &snap);
 
563
    void convertOldOSType_pre1_5(com::Utf8Str &str);
 
564
    void readMachine(const xml::ElementNode &elmMachine);
 
565
 
 
566
    void writeHardware(xml::ElementNode &elmParent, const Hardware &hw, const Storage &strg);
 
567
    void writeStorageControllers(xml::ElementNode &elmParent, const Storage &st);
 
568
    void writeSnapshot(xml::ElementNode &elmParent, const Snapshot &snap);
 
569
    void bumpSettingsVersionIfNeeded();
 
570
    void write(const com::Utf8Str &strFilename);
 
571
 
 
572
    com::Guid               uuid;
 
573
    com::Utf8Str            strName;
 
574
    bool                    fNameSync;
 
575
    com::Utf8Str            strDescription;
 
576
    com::Utf8Str            strOsType;
 
577
    com::Utf8Str            strStateFile;
 
578
    com::Guid               uuidCurrentSnapshot;
 
579
    com::Utf8Str            strSnapshotFolder;
 
580
    bool                    fTeleporterEnabled;
 
581
    uint32_t                uTeleporterPort;
 
582
    com::Utf8Str            strTeleporterAddress;
 
583
    com::Utf8Str            strTeleporterPassword;
 
584
 
 
585
    bool                    fCurrentStateModified;      // optional, default is true
 
586
    RTTIMESPEC              timeLastStateChange;        // optional, defaults to now
 
587
    bool                    fAborted;                   // optional, default is false
 
588
 
 
589
    Hardware                hardwareMachine;
 
590
    Storage                 storageMachine;
 
591
 
 
592
    ExtraDataItemsMap       mapExtraDataItems;
 
593
 
 
594
    SnapshotsList           llFirstSnapshot;            // first snapshot or empty list if there's none
1219
595
};
1220
596
 
1221
 
 
1222
 
 
1223
 
#if defined(_MSC_VER)
1224
 
#pragma warning (default:4251)
1225
 
#endif
1226
 
 
1227
 
/** @} */
 
597
} // namespace settings
 
598
 
1228
599
 
1229
600
#endif /* ___VBox_settings_h */