summaryrefslogtreecommitdiff
path: root/library/config.cpp
authoreilers <eilers>2003-08-08 14:45:49 (UTC)
committer eilers <eilers>2003-08-08 14:45:49 (UTC)
commit14d394e6c107b037a09a31a92605034fe50f7813 (patch) (unidiff)
tree800699cf4dc9681c3eb023340634dd6a15fd04c8 /library/config.cpp
parentdbc6ea35f5535a1f69deb7ebbafc0f721721dbf2 (diff)
downloadopie-14d394e6c107b037a09a31a92605034fe50f7813.zip
opie-14d394e6c107b037a09a31a92605034fe50f7813.tar.gz
opie-14d394e6c107b037a09a31a92605034fe50f7813.tar.bz2
Merged branches from BRANCH_1_0
Diffstat (limited to 'library/config.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--library/config.cpp26
1 files changed, 18 insertions, 8 deletions
diff --git a/library/config.cpp b/library/config.cpp
index b47c620..b28c771 100644
--- a/library/config.cpp
+++ b/library/config.cpp
@@ -1,570 +1,580 @@
1/********************************************************************** 1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved. 2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3** 3**
4** This file is part of Qtopia Environment. 4** This file is part of Qtopia Environment.
5** 5**
6** This file may be distributed and/or modified under the terms of the 6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software 7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the 8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file. 9** packaging of this file.
10** 10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13** 13**
14** See http://www.trolltech.com/gpl/ for GPL licensing information. 14** See http://www.trolltech.com/gpl/ for GPL licensing information.
15** 15**
16** Contact info@trolltech.com if any conditions of this licensing are 16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you. 17** not clear to you.
18** 18**
19**********************************************************************/ 19**********************************************************************/
20 20
21#include <qdir.h> 21#include <qdir.h>
22#include <qfile.h> 22#include <qfile.h>
23#include <qfileinfo.h> 23#include <qfileinfo.h>
24#include <qmessagebox.h> 24#include <qmessagebox.h>
25#if QT_VERSION <= 230 && defined(QT_NO_CODECS) 25#if QT_VERSION <= 230 && defined(QT_NO_CODECS)
26#include <qtextcodec.h> 26#include <qtextcodec.h>
27#endif 27#endif
28#include <qtextstream.h> 28#include <qtextstream.h>
29 29
30#include <sys/stat.h> 30#include <sys/stat.h>
31#include <sys/types.h> 31#include <sys/types.h>
32#include <fcntl.h> 32#include <fcntl.h>
33#include <stdlib.h> 33#include <stdlib.h>
34#include <unistd.h> 34#include <unistd.h>
35 35
36#define QTOPIA_INTERNAL_LANGLIST 36#define QTOPIA_INTERNAL_LANGLIST
37#include "config.h" 37#include "config.h"
38#include "global.h" 38#include "global.h"
39 39
40 40
41/*! 41/*!
42 \internal 42 \internal
43*/ 43*/
44QString Config::configFilename(const QString& name, Domain d) 44QString Config::configFilename(const QString& name, Domain d)
45{ 45{
46 switch (d) { 46 switch (d) {
47 case File: 47 case File:
48 return name; 48 return name;
49 case User: { 49 case User: {
50 QDir dir = (QString(getenv("HOME")) + "/Settings"); 50 QDir dir = (QString(getenv("HOME")) + "/Settings");
51 if ( !dir.exists() ) 51 if ( !dir.exists() )
52 mkdir(dir.path().local8Bit(),0700); 52 mkdir(dir.path().local8Bit(),0700);
53 return dir.path() + "/" + name + ".conf"; 53 return dir.path() + "/" + name + ".conf";
54 } 54 }
55 } 55 }
56 return name; 56 return name;
57} 57}
58 58
59/*! 59/*!
60 \class Config config.h 60 \class Config config.h
61 \brief The Config class provides for saving application cofniguration state. 61 \brief The Config class provides for saving application cofniguration state.
62 62
63 You should keep a Config in existence only while you do not want others 63 You should keep a Config in existence only while you do not want others
64 to be able to change the state. There is no locking currently, but there 64 to be able to change the state. There is no locking currently, but there
65 may be in the future. 65 may be in the future.
66*/ 66*/
67 67
68/*! 68/*!
69 \enum Config::ConfigGroup 69 \enum Config::ConfigGroup
70 \internal 70 \internal
71*/ 71*/
72 72
73/*! 73/*!
74 \enum Config::Domain 74 \enum Config::Domain
75 75
76 \value File 76 \value File
77 \value User 77 \value User
78 78
79 See Config for details. 79 See Config for details.
80*/ 80*/
81 81
82/*! 82/*!
83 Constructs a config that will load or create a configuration with the 83 Constructs a config that will load or create a configuration with the
84 given \a name in the given \a domain. 84 given \a name in the given \a domain.
85 85
86 You must call setGroup() before doing much else with the Config. 86 You must call setGroup() before doing much else with the Config.
87 87
88 In the default Domain, \e User, 88 In the default Domain, \e User,
89 the configuration is user-specific. \a name should not contain "/" in 89 the configuration is user-specific. \a name should not contain "/" in
90 this case, and in general should be the name of the C++ class that is 90 this case, and in general should be the name of the C++ class that is
91 primarily responsible for maintaining the configuration. 91 primarily responsible for maintaining the configuration.
92 92
93 In the File Domain, \a name is an absolute filename. 93 In the File Domain, \a name is an absolute filename.
94*/ 94*/
95Config::Config( const QString &name, Domain domain ) 95Config::Config( const QString &name, Domain domain )
96 : filename( configFilename(name,domain) ) 96 : filename( configFilename(name,domain) )
97{ 97{
98 git = groups.end(); 98 git = groups.end();
99 read(); 99 read();
100 QStringList l = Global::languageList(); 100 QStringList l = Global::languageList();
101 lang = l[0]; 101 lang = l[0];
102 glang = l[1]; 102 glang = l[1];
103} 103}
104 104
105 105
106// Sharp ROM compatibility 106// Sharp ROM compatibility
107Config::Config ( const QString &name, bool what ) 107Config::Config ( const QString &name, bool what )
108 : filename( configFilename(name,what ? User : File) ) 108 : filename( configFilename(name,what ? User : File) )
109{ 109{
110 git = groups.end(); 110 git = groups.end();
111 read(); 111 read();
112 QStringList l = Global::languageList(); 112 QStringList l = Global::languageList();
113 lang = l[0]; 113 lang = l[0];
114 glang = l[1]; 114 glang = l[1];
115} 115}
116 116
117/*! 117/*!
118 Writes any changes to disk and destroys the in-memory object. 118 Writes any changes to disk and destroys the in-memory object.
119*/ 119*/
120Config::~Config() 120Config::~Config()
121{ 121{
122 if ( changed ) 122 if ( changed )
123 write(); 123 write();
124} 124}
125 125
126/*! 126/*!
127 Returns whether the current group has an entry called \a key. 127 Returns whether the current group has an entry called \a key.
128*/ 128*/
129bool Config::hasKey( const QString &key ) const 129bool Config::hasKey( const QString &key ) const
130{ 130{
131 if ( groups.end() == git ) 131 if ( groups.end() == git )
132 return FALSE; 132 return FALSE;
133 ConfigGroup::ConstIterator it = ( *git ).find( key ); 133 ConfigGroup::ConstIterator it = ( *git ).find( key );
134 return it != ( *git ).end(); 134 return it != ( *git ).end();
135} 135}
136 136
137/*! 137/*!
138 Sets the current group for subsequent reading and writing of 138 Sets the current group for subsequent reading and writing of
139 entries to \a gname. Grouping allows the application to partition the namespace. 139 entries to \a gname. Grouping allows the application to partition the namespace.
140 140
141 This function must be called prior to any reading or writing 141 This function must be called prior to any reading or writing
142 of entries. 142 of entries.
143 143
144 The \a gname must not be empty. 144 The \a gname must not be empty.
145*/ 145*/
146void Config::setGroup( const QString &gname ) 146void Config::setGroup( const QString &gname )
147{ 147{
148 QMap< QString, ConfigGroup>::Iterator it = groups.find( gname ); 148 QMap< QString, ConfigGroup>::Iterator it = groups.find( gname );
149 if ( it == groups.end() ) { 149 if ( it == groups.end() ) {
150 git = groups.insert( gname, ConfigGroup() ); 150 git = groups.insert( gname, ConfigGroup() );
151 changed = TRUE; 151 changed = TRUE;
152 return; 152 return;
153 } 153 }
154 git = it; 154 git = it;
155} 155}
156 156
157/*! 157/*!
158 Writes a (\a key, \a value) entry to the current group. 158 Writes a (\a key, \a value) entry to the current group.
159 159
160 \sa readEntry() 160 \sa readEntry()
161*/ 161*/
162void Config::writeEntry( const QString &key, const char* value ) 162void Config::writeEntry( const QString &key, const char* value )
163{ 163{
164 writeEntry(key,QString(value)); 164 writeEntry(key,QString(value));
165} 165}
166 166
167/*! 167/*!
168 Writes a (\a key, \a value) entry to the current group. 168 Writes a (\a key, \a value) entry to the current group.
169 169
170 \sa readEntry() 170 \sa readEntry()
171*/ 171*/
172void Config::writeEntry( const QString &key, const QString &value ) 172void Config::writeEntry( const QString &key, const QString &value )
173{ 173{
174 if ( git == groups.end() ) { 174 if ( git == groups.end() ) {
175 qWarning( "no group set" ); 175 qWarning( "no group set" );
176 return; 176 return;
177 } 177 }
178 if ( (*git)[key] != value ) { 178 if ( (*git)[key] != value ) {
179 ( *git ).insert( key, value ); 179 ( *git ).insert( key, value );
180 changed = TRUE; 180 changed = TRUE;
181 } 181 }
182} 182}
183 183
184/* 184/*
185 Note that the degree of protection offered by the encryption here is 185 Note that the degree of protection offered by the encryption here is
186 only sufficient to avoid the most casual observation of the configuration 186 only sufficient to avoid the most casual observation of the configuration
187 files. People with access to the files can write down the contents and 187 files. People with access to the files can write down the contents and
188 decrypt it using this source code. 188 decrypt it using this source code.
189 189
190 Conceivably, and at some burden to the user, this encryption could 190 Conceivably, and at some burden to the user, this encryption could
191 be improved. 191 be improved.
192*/ 192*/
193static QString encipher(const QString& plain) 193static QString encipher(const QString& plain)
194{ 194{
195 // mainly, we make it long 195 // mainly, we make it long
196 QString cipher; 196 QString cipher;
197 int mix=28730492; 197 int mix=28730492;
198 for (int i=0; i<(int)plain.length(); i++) { 198 for (int i=0; i<(int)plain.length(); i++) {
199 int u = plain[i].unicode(); 199 int u = plain[i].unicode();
200 int c = u ^ mix; 200 int c = u ^ mix;
201 QString x = QString::number(c,36); 201 QString x = QString::number(c,36);
202 cipher.append(QChar('a'+x.length())); 202 cipher.append(QChar('a'+x.length()));
203 cipher.append(x); 203 cipher.append(x);
204 mix *= u; 204 mix *= u;
205 } 205 }
206 return cipher; 206 return cipher;
207} 207}
208 208
209static QString decipher(const QString& cipher) 209static QString decipher(const QString& cipher)
210{ 210{
211 QString plain; 211 QString plain;
212 int mix=28730492; 212 int mix=28730492;
213 for (int i=0; i<(int)cipher.length();) { 213 for (int i=0; i<(int)cipher.length();) {
214 int l = cipher[i].unicode()-'a'; 214 int l = cipher[i].unicode()-'a';
215 QString x = cipher.mid(i+1,l); i+=l+1; 215 QString x = cipher.mid(i+1,l); i+=l+1;
216 int u = x.toInt(0,36) ^ mix; 216 int u = x.toInt(0,36) ^ mix;
217 plain.append(QChar(u)); 217 plain.append(QChar(u));
218 mix *= u; 218 mix *= u;
219 } 219 }
220 return plain; 220 return plain;
221} 221}
222 222
223/*! 223/*!
224 Writes an encrypted (\a key, \a value) entry to the current group. 224 Writes an encrypted (\a key, \a value) entry to the current group.
225 225
226 Note that the degree of protection offered by the encryption is 226 Note that the degree of protection offered by the encryption is
227 only sufficient to avoid the most casual observation of the configuration 227 only sufficient to avoid the most casual observation of the configuration
228 files. 228 files.
229 229
230 \sa readEntry() 230 \sa readEntry()
231*/ 231*/
232void Config::writeEntryCrypt( const QString &key, const QString &value ) 232void Config::writeEntryCrypt( const QString &key, const QString &value )
233{ 233{
234 if ( git == groups.end() ) { 234 if ( git == groups.end() ) {
235 qWarning( "no group set" ); 235 qWarning( "no group set" );
236 return; 236 return;
237 } 237 }
238 QString evalue = encipher(value); 238 QString evalue = encipher(value);
239 if ( (*git)[key] != evalue ) { 239 if ( (*git)[key] != evalue ) {
240 ( *git ).insert( key, evalue ); 240 ( *git ).insert( key, evalue );
241 changed = TRUE; 241 changed = TRUE;
242 } 242 }
243} 243}
244 244
245/*! 245/*!
246 Writes a (\a key, \a num) entry to the current group. 246 Writes a (\a key, \a num) entry to the current group.
247 247
248 \sa readNumEntry() 248 \sa readNumEntry()
249*/ 249*/
250void Config::writeEntry( const QString &key, int num ) 250void Config::writeEntry( const QString &key, int num )
251{ 251{
252 QString s; 252 QString s;
253 s.setNum( num ); 253 s.setNum( num );
254 writeEntry( key, s ); 254 writeEntry( key, s );
255} 255}
256 256
257#ifdef Q_HAS_BOOL_TYPE 257#ifdef Q_HAS_BOOL_TYPE
258/*! 258/*!
259 Writes a (\a key, \a b) entry to the current group. This is equivalent 259 Writes a (\a key, \a b) entry to the current group. This is equivalent
260 to writing a 0 or 1 as an integer entry. 260 to writing a 0 or 1 as an integer entry.
261 261
262 \sa readBoolEntry() 262 \sa readBoolEntry()
263*/ 263*/
264void Config::writeEntry( const QString &key, bool b ) 264void Config::writeEntry( const QString &key, bool b )
265{ 265{
266 QString s; 266 QString s;
267 s.setNum( ( int )b ); 267 s.setNum( ( int )b );
268 writeEntry( key, s ); 268 writeEntry( key, s );
269} 269}
270#endif 270#endif
271 271
272/*! 272/*!
273 Writes a (\a key, \a lst) entry to the current group. The list 273 Writes a (\a key, \a lst) entry to the current group. The list
274 is separated by \a sep, so the strings must not contain that character. 274 is separated by \a sep, so the strings must not contain that character.
275 275
276 \sa readListEntry() 276 \sa readListEntry()
277*/ 277*/
278void Config::writeEntry( const QString &key, const QStringList &lst, const QChar &sep ) 278void Config::writeEntry( const QString &key, const QStringList &lst, const QChar &sep )
279{ 279{
280 QString s; 280 QString s;
281 QStringList::ConstIterator it = lst.begin(); 281 QStringList::ConstIterator it = lst.begin();
282 for ( ; it != lst.end(); ++it ) 282 for ( ; it != lst.end(); ++it )
283 s += *it + sep; 283 s += *it + sep;
284 writeEntry( key, s ); 284 writeEntry( key, s );
285} 285}
286 286
287/*! 287/*!
288 Removes the \a key entry from the current group. Does nothing if 288 Removes the \a key entry from the current group. Does nothing if
289 there is no such entry. 289 there is no such entry.
290*/ 290*/
291 291
292void Config::removeEntry( const QString &key ) 292void Config::removeEntry( const QString &key )
293{ 293{
294 if ( git == groups.end() ) { 294 if ( git == groups.end() ) {
295 qWarning( "no group set" ); 295 qWarning( "no group set" );
296 return; 296 return;
297 } 297 }
298 ( *git ).remove( key ); 298 ( *git ).remove( key );
299 changed = TRUE; 299 changed = TRUE;
300} 300}
301 301
302/*! 302/*!
303 \fn bool Config::operator == ( const Config & other ) const 303 \fn bool Config::operator == ( const Config & other ) const
304 304
305 Tests for equality with \a other. Config objects are equal if they refer to the same filename. 305 Tests for equality with \a other. Config objects are equal if they refer to the same filename.
306*/ 306*/
307 307
308/*! 308/*!
309 \fn bool Config::operator != ( const Config & other ) const 309 \fn bool Config::operator != ( const Config & other ) const
310 310
311 Tests for inequality with \a other. Config objects are equal if they refer to the same filename. 311 Tests for inequality with \a other. Config objects are equal if they refer to the same filename.
312*/ 312*/
313 313
314/*! 314/*!
315 \fn QString Config::readEntry( const QString &key, const QString &deflt ) const 315 \fn QString Config::readEntry( const QString &key, const QString &deflt ) const
316 316
317 Reads a string entry stored with \a key, defaulting to \a deflt if there is no entry. 317 Reads a string entry stored with \a key, defaulting to \a deflt if there is no entry.
318*/ 318*/
319 319
320/*! 320/*!
321 \internal 321 \internal
322 For compatibility, non-const version. 322 For compatibility, non-const version.
323*/ 323*/
324QString Config::readEntry( const QString &key, const QString &deflt ) 324QString Config::readEntry( const QString &key, const QString &deflt )
325{ 325{
326 QString res = readEntryDirect( key+"["+lang+"]" ); 326 QString res = readEntryDirect( key+"["+lang+"]" );
327 if ( !res.isNull() ) 327 if ( !res.isNull() )
328 return res; 328 return res;
329 if ( !glang.isEmpty() ) { 329 if ( !glang.isEmpty() ) {
330 res = readEntryDirect( key+"["+glang+"]" ); 330 res = readEntryDirect( key+"["+glang+"]" );
331 if ( !res.isNull() ) 331 if ( !res.isNull() )
332 return res; 332 return res;
333 } 333 }
334 return readEntryDirect( key, deflt ); 334 return readEntryDirect( key, deflt );
335} 335}
336 336
337/*! 337/*!
338 \fn QString Config::readEntryCrypt( const QString &key, const QString &deflt ) const 338 \fn QString Config::readEntryCrypt( const QString &key, const QString &deflt ) const
339 339
340 Reads an encrypted string entry stored with \a key, defaulting to \a deflt if there is no entry. 340 Reads an encrypted string entry stored with \a key, defaulting to \a deflt if there is no entry.
341*/ 341*/
342 342
343/*! 343/*!
344 \internal 344 \internal
345 For compatibility, non-const version. 345 For compatibility, non-const version.
346*/ 346*/
347QString Config::readEntryCrypt( const QString &key, const QString &deflt ) 347QString Config::readEntryCrypt( const QString &key, const QString &deflt )
348{ 348{
349 QString res = readEntryDirect( key+"["+lang+"]" ); 349 QString res = readEntryDirect( key+"["+lang+"]" );
350 if ( res.isNull() && glang.isEmpty() ) 350 if ( res.isNull() && glang.isEmpty() )
351 res = readEntryDirect( key+"["+glang+"]" ); 351 res = readEntryDirect( key+"["+glang+"]" );
352 if ( res.isNull() ) 352 if ( res.isNull() )
353 res = readEntryDirect( key, QString::null ); 353 res = readEntryDirect( key, QString::null );
354 if ( res.isNull() ) 354 if ( res.isNull() )
355 return deflt; 355 return deflt;
356 return decipher(res); 356 return decipher(res);
357} 357}
358 358
359/*! 359/*!
360 \fn QString Config::readEntryDirect( const QString &key, const QString &deflt ) const 360 \fn QString Config::readEntryDirect( const QString &key, const QString &deflt ) const
361 \internal 361 \internal
362*/ 362*/
363 363
364/*! 364/*!
365 \internal 365 \internal
366 For compatibility, non-const version. 366 For compatibility, non-const version.
367*/ 367*/
368QString Config::readEntryDirect( const QString &key, const QString &deflt ) 368QString Config::readEntryDirect( const QString &key, const QString &deflt )
369{ 369{
370 if ( git == groups.end() ) { 370 if ( git == groups.end() ) {
371 //qWarning( "no group set" ); 371 //qWarning( "no group set" );
372 return deflt; 372 return deflt;
373 } 373 }
374 ConfigGroup::ConstIterator it = ( *git ).find( key ); 374 ConfigGroup::ConstIterator it = ( *git ).find( key );
375 if ( it != ( *git ).end() ) 375 if ( it != ( *git ).end() )
376 return *it; 376 return *it;
377 else 377 else
378 return deflt; 378 return deflt;
379} 379}
380 380
381/*! 381/*!
382 \fn int Config::readNumEntry( const QString &key, int deflt ) const 382 \fn int Config::readNumEntry( const QString &key, int deflt ) const
383 Reads a numeric entry stored with \a key, defaulting to \a deflt if there is no entry. 383 Reads a numeric entry stored with \a key, defaulting to \a deflt if there is no entry.
384*/ 384*/
385 385
386/*! 386/*!
387 \internal 387 \internal
388 For compatibility, non-const version. 388 For compatibility, non-const version.
389*/ 389*/
390int Config::readNumEntry( const QString &key, int deflt ) 390int Config::readNumEntry( const QString &key, int deflt )
391{ 391{
392 QString s = readEntry( key ); 392 QString s = readEntry( key );
393 if ( s.isEmpty() ) 393 if ( s.isEmpty() )
394 return deflt; 394 return deflt;
395 else 395 else
396 return s.toInt(); 396 return s.toInt();
397} 397}
398 398
399/*! 399/*!
400 \fn bool Config::readBoolEntry( const QString &key, bool deflt ) const 400 \fn bool Config::readBoolEntry( const QString &key, bool deflt ) const
401 Reads a bool entry stored with \a key, defaulting to \a deflt if there is no entry. 401 Reads a bool entry stored with \a key, defaulting to \a deflt if there is no entry.
402*/ 402*/
403 403
404/*! 404/*!
405 \internal 405 \internal
406 For compatibility, non-const version. 406 For compatibility, non-const version.
407*/ 407*/
408bool Config::readBoolEntry( const QString &key, bool deflt ) 408bool Config::readBoolEntry( const QString &key, bool deflt )
409{ 409{
410 QString s = readEntry( key ); 410 QString s = readEntry( key );
411 if ( s.isEmpty() ) 411 if ( s.isEmpty() )
412 return deflt; 412 return deflt;
413 else 413 else
414 return (bool)s.toInt(); 414 return (bool)s.toInt();
415} 415}
416 416
417/*! 417/*!
418 \fn QStringList Config::readListEntry( const QString &key, const QChar &sep ) const 418 \fn QStringList Config::readListEntry( const QString &key, const QChar &sep ) const
419 Reads a string list entry stored with \a key, and with \a sep as the separator. 419 Reads a string list entry stored with \a key, and with \a sep as the separator.
420*/ 420*/
421 421
422/*! 422/*!
423 \internal 423 \internal
424 For compatibility, non-const version. 424 For compatibility, non-const version.
425*/ 425*/
426QStringList Config::readListEntry( const QString &key, const QChar &sep ) 426QStringList Config::readListEntry( const QString &key, const QChar &sep )
427{ 427{
428 QString s = readEntry( key ); 428 QString s = readEntry( key );
429 if ( s.isEmpty() ) 429 if ( s.isEmpty() )
430 return QStringList(); 430 return QStringList();
431 else 431 else
432 return QStringList::split( sep, s ); 432 return QStringList::split( sep, s );
433} 433}
434 434
435/*! 435/*!
436 Removes all entries from the current group. 436 Removes all entries from the current group.
437*/ 437*/
438void Config::clearGroup() 438void Config::clearGroup()
439{ 439{
440 if ( git == groups.end() ) { 440 if ( git == groups.end() ) {
441 qWarning( "no group set" ); 441 qWarning( "no group set" );
442 return; 442 return;
443 } 443 }
444 if ( !(*git).isEmpty() ) { 444 if ( !(*git).isEmpty() ) {
445 ( *git ).clear(); 445 ( *git ).clear();
446 changed = TRUE; 446 changed = TRUE;
447 } 447 }
448} 448}
449 449
450/*! 450/*!
451 \internal 451 \internal
452*/ 452*/
453void Config::write( const QString &fn ) 453void Config::write( const QString &fn )
454{ 454{
455 QString strNewFile; 455 QString strNewFile;
456 if ( !fn.isEmpty() ) 456 if ( !fn.isEmpty() )
457 filename = fn; 457 filename = fn;
458 strNewFile = filename + ".new"; 458 strNewFile = filename + ".new";
459 459
460 QFile f( strNewFile ); 460 QFile f( strNewFile );
461 if ( !f.open( IO_WriteOnly|IO_Raw ) ) { 461 if ( !f.open( IO_WriteOnly|IO_Raw ) ) {
462 qWarning( "could not open for writing `%s'", strNewFile.latin1() ); 462 qWarning( "could not open for writing `%s'", strNewFile.latin1() );
463 git = groups.end(); 463 git = groups.end();
464 return; 464 return;
465 } 465 }
466 466
467 QString str; 467 QString str;
468 QCString cstr; 468 QCString cstr;
469 QMap< QString, ConfigGroup >::Iterator g_it = groups.begin(); 469 QMap< QString, ConfigGroup >::Iterator g_it = groups.begin();
470 470
471 for ( ; g_it != groups.end(); ++g_it ) { 471 for ( ; g_it != groups.end(); ++g_it ) {
472 str += "[" + g_it.key() + "]\n"; 472 str += "[" + g_it.key() + "]\n";
473 ConfigGroup::Iterator e_it = ( *g_it ).begin(); 473 ConfigGroup::Iterator e_it = ( *g_it ).begin();
474 for ( ; e_it != ( *g_it ).end(); ++e_it ) 474 for ( ; e_it != ( *g_it ).end(); ++e_it )
475 str += e_it.key() + " = " + *e_it + "\n"; 475 str += e_it.key() + " = " + *e_it + "\n";
476 } 476 }
477 cstr = str.utf8(); 477 cstr = str.utf8();
478 478
479 int total_length; 479 int total_length;
480 total_length = f.writeBlock( cstr.data(), cstr.length() ); 480 total_length = f.writeBlock( cstr.data(), cstr.length() );
481 if ( total_length != int(cstr.length()) ) { 481 if ( total_length != int(cstr.length()) ) {
482 QMessageBox::critical( 0, QObject::tr("Out of Space"), 482 QMessageBox::critical( 0, QObject::tr("Out of Space"),
483 QObject::tr("There was a problem creating\nConfiguration Information \nfor this program.\n\nPlease free up some space and\ntry again.") ); 483 QObject::tr("There was a problem creating\nConfiguration Information \nfor this program.\n\nPlease free up some space and\ntry again.") );
484 f.close(); 484 f.close();
485 QFile::remove( strNewFile ); 485 QFile::remove( strNewFile );
486 return; 486 return;
487 } 487 }
488 488
489 f.close(); 489 f.close();
490 // now rename the file... 490 // now rename the file...
491 if ( rename( strNewFile, filename ) < 0 ) { 491 if ( rename( strNewFile, filename ) < 0 ) {
492 qWarning( "problem renaming the file %s to %s", strNewFile.latin1(), 492 qWarning( "problem renaming the file %s to %s", strNewFile.latin1(),
493 filename.latin1() ); 493 filename.latin1() );
494 QFile::remove( strNewFile ); 494 QFile::remove( strNewFile );
495 } 495 }
496} 496}
497 497
498/*! 498/*!
499 Returns whether the Config is in a valid state. 499 Returns whether the Config is in a valid state.
500*/ 500*/
501bool Config::isValid() const 501bool Config::isValid() const
502{ 502{
503 return groups.end() != git; 503 return groups.end() != git;
504} 504}
505 505
506/*! 506/*!
507 \internal 507 \internal
508*/ 508*/
509void Config::read() 509void Config::read()
510{ 510{
511 changed = FALSE; 511 changed = FALSE;
512 512
513 if ( !QFileInfo( filename ).exists() ) { 513 if ( !QFileInfo( filename ).exists() ) {
514 git = groups.end(); 514 git = groups.end();
515 return; 515 return;
516 } 516 }
517 517
518 QFile f( filename ); 518 QFile f( filename );
519 if ( !f.open( IO_ReadOnly ) ) { 519 if ( !f.open( IO_ReadOnly ) ) {
520 git = groups.end(); 520 git = groups.end();
521 return; 521 return;
522 } 522 }
523 523
524
525 // hack to avoid problems if big files are passed to test
526 // if they are valid configs ( like passing a mp3 ... )
527 // I just hope that there are no conf files > 100000 byte
528 // not the best solution, find something else later
529 if ( f.size() > 100000 ) {
530 return;
531 }
532
533
524 QTextStream s( &f ); 534 QTextStream s( &f );
525#if QT_VERSION <= 230 && defined(QT_NO_CODECS) 535#if QT_VERSION <= 230 && defined(QT_NO_CODECS)
526 // The below should work, but doesn't in Qt 2.3.0 536 // The below should work, but doesn't in Qt 2.3.0
527 s.setCodec( QTextCodec::codecForMib( 106 ) ); 537 s.setCodec( QTextCodec::codecForMib( 106 ) );
528#else 538#else
529 s.setEncoding( QTextStream::UnicodeUTF8 ); 539 s.setEncoding( QTextStream::UnicodeUTF8 );
530#endif 540#endif
531 541
532 QStringList list = QStringList::split('\n', s.read() ); 542 QStringList list = QStringList::split('\n', s.read() );
533 f.close(); 543 f.close();
534 544
535 for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) { 545 for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) {
536 if ( !parse( *it ) ) { 546 if ( !parse( *it ) ) {
537 git = groups.end(); 547 git = groups.end();
538 return; 548 return;
539 } 549 }
540 } 550 }
541} 551}
542 552
543/*! 553/*!
544 \internal 554 \internal
545*/ 555*/
546bool Config::parse( const QString &l ) 556bool Config::parse( const QString &l )
547{ 557{
548 QString line = l.stripWhiteSpace(); 558 QString line = l.stripWhiteSpace();
549 559
550 if ( line [0] == QChar ( '#' )) 560 if ( line [0] == QChar ( '#' ))
551 return true; // ignore comments 561 return true; // ignore comments
552 562
553 if ( line[ 0 ] == QChar( '[' ) ) { 563 if ( line[ 0 ] == QChar( '[' ) ) {
554 QString gname = line; 564 QString gname = line;
555 gname = gname.remove( 0, 1 ); 565 gname = gname.remove( 0, 1 );
556 if ( gname[ (int)gname.length() - 1 ] == QChar( ']' ) ) 566 if ( gname[ (int)gname.length() - 1 ] == QChar( ']' ) )
557 gname = gname.remove( gname.length() - 1, 1 ); 567 gname = gname.remove( gname.length() - 1, 1 );
558 git = groups.insert( gname, ConfigGroup() ); 568 git = groups.insert( gname, ConfigGroup() );
559 } else if ( !line.isEmpty() ) { 569 } else if ( !line.isEmpty() ) {
560 if ( git == groups.end() ) 570 if ( git == groups.end() )
561 return FALSE; 571 return FALSE;
562 int eq = line.find( '=' ); 572 int eq = line.find( '=' );
563 if ( eq == -1 ) 573 if ( eq == -1 )
564 return FALSE; 574 return FALSE;
565 QString key = line.left(eq).stripWhiteSpace(); 575 QString key = line.left(eq).stripWhiteSpace();
566 QString value = line.mid(eq+1).stripWhiteSpace(); 576 QString value = line.mid(eq+1).stripWhiteSpace();
567 ( *git ).insert( key, value ); 577 ( *git ).insert( key, value );
568 } 578 }
569 return TRUE; 579 return TRUE;
570} 580}