summaryrefslogtreecommitdiff
path: root/library/config.cpp
Unidiff
Diffstat (limited to 'library/config.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--library/config.cpp2
1 files changed, 1 insertions, 1 deletions
diff --git a/library/config.cpp b/library/config.cpp
index 72bd4d2..73ddeb5 100644
--- a/library/config.cpp
+++ b/library/config.cpp
@@ -1,807 +1,807 @@
1/********************************************************************** 1/**********************************************************************
2** Copyright (C) 2000,2004 Trolltech AS. All rights reserved. 2** Copyright (C) 2000,2004 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 <qmessagebox.h> 22#include <qmessagebox.h>
23#if QT_VERSION <= 230 && defined(QT_NO_CODECS) 23#if QT_VERSION <= 230 && defined(QT_NO_CODECS)
24#include <qtextcodec.h> 24#include <qtextcodec.h>
25#endif 25#endif
26#include <qtextstream.h> 26#include <qtextstream.h>
27 27
28#include <sys/stat.h> 28#include <sys/stat.h>
29#include <sys/types.h> 29#include <sys/types.h>
30#include <sys/time.h> 30#include <sys/time.h>
31#include <fcntl.h> 31#include <fcntl.h>
32#include <stdlib.h> 32#include <stdlib.h>
33#include <time.h> 33#include <time.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#include "qpeapplication.h" 39#include <qtopia/qpeapplication.h>
40 40
41 41
42/* 42/*
43 * Internal Class 43 * Internal Class
44 */ 44 */
45class ConfigPrivate { 45class ConfigPrivate {
46public: 46public:
47 ConfigPrivate() : multilang(FALSE) {} 47 ConfigPrivate() : multilang(FALSE) {}
48 ConfigPrivate(const ConfigPrivate& o) : 48 ConfigPrivate(const ConfigPrivate& o) :
49 trfile(o.trfile), 49 trfile(o.trfile),
50 trcontext(o.trcontext), 50 trcontext(o.trcontext),
51 multilang(o.multilang) 51 multilang(o.multilang)
52 {} 52 {}
53 ConfigPrivate& operator=(const ConfigPrivate& o) 53 ConfigPrivate& operator=(const ConfigPrivate& o)
54 { 54 {
55 trfile = o.trfile; 55 trfile = o.trfile;
56 trcontext = o.trcontext; 56 trcontext = o.trcontext;
57 multilang = o.multilang; 57 multilang = o.multilang;
58 return *this; 58 return *this;
59 } 59 }
60 60
61 QString trfile; 61 QString trfile;
62 QCString trcontext; 62 QCString trcontext;
63 bool multilang; 63 bool multilang;
64}; 64};
65 65
66///////////////////////////////////////////////////////////////// 66/////////////////////////////////////////////////////////////////
67///////////////////////////////////////////////////////////////// 67/////////////////////////////////////////////////////////////////
68 68
69#ifndef Q_OS_WIN32 69#ifndef Q_OS_WIN32
70 70
71//#define DEBUG_CONFIG_CACHE 71//#define DEBUG_CONFIG_CACHE
72class ConfigData 72class ConfigData
73{ 73{
74public: 74public:
75 ConfigData() {} 75 ConfigData() {}
76 ConfigData( const ConfigGroupMap& cf, const ConfigPrivate& pri, 76 ConfigData( const ConfigGroupMap& cf, const ConfigPrivate& pri,
77 struct stat sbuf ) 77 struct stat sbuf )
78 : cfg( cf ), priv( pri ), mtime( sbuf.st_mtime ), 78 : cfg( cf ), priv( pri ), mtime( sbuf.st_mtime ),
79 size( sbuf.st_size ) 79 size( sbuf.st_size )
80 { 80 {
81 gettimeofday(&used, 0 ); 81 gettimeofday(&used, 0 );
82 } 82 }
83 83
84 ConfigGroupMap cfg; 84 ConfigGroupMap cfg;
85 ConfigPrivate priv; // Owned by this object 85 ConfigPrivate priv; // Owned by this object
86 time_t mtime; 86 time_t mtime;
87 unsigned int size; 87 unsigned int size;
88 struct timeval used; 88 struct timeval used;
89}; 89};
90 90
91 91
92class ConfigCache : public QObject { 92class ConfigCache : public QObject {
93public: 93public:
94 static ConfigCache* instance(); 94 static ConfigCache* instance();
95 95
96 void insert( const QString& fileName, const ConfigGroupMap& cfg, 96 void insert( const QString& fileName, const ConfigGroupMap& cfg,
97 const ConfigPrivate *priv ); 97 const ConfigPrivate *priv );
98 bool find(const QString& fileName, ConfigGroupMap& cfg, 98 bool find(const QString& fileName, ConfigGroupMap& cfg,
99 ConfigPrivate** priv ); 99 ConfigPrivate** priv );
100protected: 100protected:
101 void timerEvent( QTimerEvent* ); 101 void timerEvent( QTimerEvent* );
102 102
103private: 103private:
104 ConfigCache(); 104 ConfigCache();
105 void remove( const QString& fileName ); 105 void remove( const QString& fileName );
106 void removeLru(); 106 void removeLru();
107 107
108private: 108private:
109 QMap<QString, ConfigData> m_cached; 109 QMap<QString, ConfigData> m_cached;
110 unsigned int m_totalSize; 110 unsigned int m_totalSize;
111 int m_tid; 111 int m_tid;
112private: 112private:
113 static ConfigCache* m_inst; 113 static ConfigCache* m_inst;
114 static const unsigned int CONFIG_CACHE_SIZE = 8192; 114 static const unsigned int CONFIG_CACHE_SIZE = 8192;
115 static const unsigned int CONFIG_CACHE_TIMEOUT = 1000; 115 static const unsigned int CONFIG_CACHE_TIMEOUT = 1000;
116}; 116};
117 117
118ConfigCache* ConfigCache::m_inst = 0; 118ConfigCache* ConfigCache::m_inst = 0;
119/* 119/*
120 * get destroyed when qApp gets destroyed 120 * get destroyed when qApp gets destroyed
121 */ 121 */
122ConfigCache::ConfigCache() : QObject( qApp ), m_totalSize( 0 ), m_tid( 0 ) {} 122ConfigCache::ConfigCache() : QObject( qApp ), m_totalSize( 0 ), m_tid( 0 ) {}
123ConfigCache* ConfigCache::instance() { 123ConfigCache* ConfigCache::instance() {
124 if ( !m_inst ) 124 if ( !m_inst )
125 m_inst = new ConfigCache(); 125 m_inst = new ConfigCache();
126 126
127 return m_inst; 127 return m_inst;
128} 128}
129 129
130void ConfigCache::remove( const QString& fileName ) { 130void ConfigCache::remove( const QString& fileName ) {
131 QMap<QString, ConfigData>::Iterator it = m_cached.find( fileName ); 131 QMap<QString, ConfigData>::Iterator it = m_cached.find( fileName );
132 132
133 if ( it == m_cached.end() ) 133 if ( it == m_cached.end() )
134 return; 134 return;
135 135
136 m_totalSize -= (*it).size; 136 m_totalSize -= (*it).size;
137 m_cached.remove( it ); 137 m_cached.remove( it );
138} 138}
139 139
140void ConfigCache::removeLru() { 140void ConfigCache::removeLru() {
141 QMap<QString, ConfigData>::Iterator it = m_cached.begin(); 141 QMap<QString, ConfigData>::Iterator it = m_cached.begin();
142 QMap<QString, ConfigData>::Iterator lru = it; 142 QMap<QString, ConfigData>::Iterator lru = it;
143 ++it; 143 ++it;
144 for (; it != m_cached.end(); ++it) 144 for (; it != m_cached.end(); ++it)
145 if ((*it).used.tv_sec < (*lru).used.tv_sec || 145 if ((*it).used.tv_sec < (*lru).used.tv_sec ||
146 ((*it).used.tv_sec == (*lru).used.tv_sec && 146 ((*it).used.tv_sec == (*lru).used.tv_sec &&
147 (*it).used.tv_usec < (*lru).used.tv_usec)) 147 (*it).used.tv_usec < (*lru).used.tv_usec))
148 lru = it; 148 lru = it;
149 149
150 m_totalSize -= (*lru).size; 150 m_totalSize -= (*lru).size;
151 m_cached.remove(lru); 151 m_cached.remove(lru);
152} 152}
153 153
154void ConfigCache::timerEvent( QTimerEvent* ) { 154void ConfigCache::timerEvent( QTimerEvent* ) {
155 while ( m_totalSize > CONFIG_CACHE_SIZE ) 155 while ( m_totalSize > CONFIG_CACHE_SIZE )
156 removeLru(); 156 removeLru();
157 157
158 killTimer(m_tid); 158 killTimer(m_tid);
159 m_tid = 0; 159 m_tid = 0;
160} 160}
161 161
162void ConfigCache::insert( const QString& fileName, const ConfigGroupMap& cfg, 162void ConfigCache::insert( const QString& fileName, const ConfigGroupMap& cfg,
163 const ConfigPrivate* _priv ) { 163 const ConfigPrivate* _priv ) {
164 164
165 165
166 struct stat sbuf; 166 struct stat sbuf;
167 ::stat( QFile::encodeName(fileName), &sbuf ); 167 ::stat( QFile::encodeName(fileName), &sbuf );
168 if ( static_cast<unsigned int>(sbuf.st_size) >= CONFIG_CACHE_SIZE>>1) 168 if ( static_cast<unsigned int>(sbuf.st_size) >= CONFIG_CACHE_SIZE>>1)
169 return; 169 return;
170 170
171 /* 171 /*
172 * remove the old version and use the new one 172 * remove the old version and use the new one
173 */ 173 */
174 ConfigPrivate priv = _priv ? *_priv : ConfigPrivate(); 174 ConfigPrivate priv = _priv ? *_priv : ConfigPrivate();
175 ConfigData data( cfg, priv, sbuf ); 175 ConfigData data( cfg, priv, sbuf );
176 m_totalSize += data.size; 176 m_totalSize += data.size;
177 177
178 remove( fileName ); 178 remove( fileName );
179 m_cached.insert( fileName, data ); 179 m_cached.insert( fileName, data );
180 180
181 /* 181 /*
182 * we've overcommited allocation, let us clean up 182 * we've overcommited allocation, let us clean up
183 * soon 183 * soon
184 */ 184 */
185 if ( m_totalSize >= CONFIG_CACHE_SIZE ) 185 if ( m_totalSize >= CONFIG_CACHE_SIZE )
186 if ( !m_tid ) 186 if ( !m_tid )
187 m_tid = startTimer(CONFIG_CACHE_TIMEOUT); 187 m_tid = startTimer(CONFIG_CACHE_TIMEOUT);
188} 188}
189 189
190bool ConfigCache::find( const QString& fileName, ConfigGroupMap& cfg, 190bool ConfigCache::find( const QString& fileName, ConfigGroupMap& cfg,
191 ConfigPrivate **ppriv ) { 191 ConfigPrivate **ppriv ) {
192 QMap<QString, ConfigData>::Iterator it = m_cached.find(fileName); 192 QMap<QString, ConfigData>::Iterator it = m_cached.find(fileName);
193 if (it != m_cached.end()) { 193 if (it != m_cached.end()) {
194 ConfigData &data = *it; 194 ConfigData &data = *it;
195 struct stat sbuf; 195 struct stat sbuf;
196 ::stat(QFile::encodeName( fileName ), &sbuf); 196 ::stat(QFile::encodeName( fileName ), &sbuf);
197 197
198 if (data.mtime == sbuf.st_mtime && (int)data.size == sbuf.st_size) { 198 if (data.mtime == sbuf.st_mtime && (int)data.size == sbuf.st_size) {
199 cfg = data.cfg; 199 cfg = data.cfg;
200 200
201 /* 201 /*
202 * null pointer 202 * null pointer
203 */ 203 */
204 if ( *ppriv == 0 ) 204 if ( *ppriv == 0 )
205 *ppriv = new ConfigPrivate( data.priv ); 205 *ppriv = new ConfigPrivate( data.priv );
206 **ppriv = data.priv; 206 **ppriv = data.priv;
207 gettimeofday(&data.used, 0); 207 gettimeofday(&data.used, 0);
208 208
209 return true; 209 return true;
210 } 210 }
211 } 211 }
212 212
213 return false; 213 return false;
214} 214}
215 215
216#endif 216#endif
217 217
218 218
219/*! 219/*!
220 \internal 220 \internal
221*/ 221*/
222QString Config::configFilename(const QString& name, Domain d) 222QString Config::configFilename(const QString& name, Domain d)
223{ 223{
224 switch (d) { 224 switch (d) {
225 case File: 225 case File:
226 return name; 226 return name;
227 case User: { 227 case User: {
228 QDir dir = (QString(getenv("HOME")) + "/Settings"); 228 QDir dir = (QString(getenv("HOME")) + "/Settings");
229 if ( !dir.exists() ) 229 if ( !dir.exists() )
230 mkdir(dir.path().local8Bit(),0700); 230 mkdir(dir.path().local8Bit(),0700);
231 return dir.path() + "/" + name + ".conf"; 231 return dir.path() + "/" + name + ".conf";
232 } 232 }
233 } 233 }
234 return name; 234 return name;
235} 235}
236 236
237/* This cannot be made public because of binary compat issues */ 237/* This cannot be made public because of binary compat issues */
238void Config::read( QTextStream &s ) 238void Config::read( QTextStream &s )
239{ 239{
240#if QT_VERSION <= 230 && defined(QT_NO_CODECS) 240#if QT_VERSION <= 230 && defined(QT_NO_CODECS)
241 // The below should work, but doesn't in Qt 2.3.0 241 // The below should work, but doesn't in Qt 2.3.0
242 s.setCodec( QTextCodec::codecForMib( 106 ) ); 242 s.setCodec( QTextCodec::codecForMib( 106 ) );
243#else 243#else
244 s.setEncoding( QTextStream::UnicodeUTF8 ); 244 s.setEncoding( QTextStream::UnicodeUTF8 );
245#endif 245#endif
246 246
247 QStringList list = QStringList::split('\n', s.read() ); 247 QStringList list = QStringList::split('\n', s.read() );
248 248
249 for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) { 249 for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) {
250 if ( !parse( *it ) ) { 250 if ( !parse( *it ) ) {
251 git = groups.end(); 251 git = groups.end();
252 return; 252 return;
253 } 253 }
254 } 254 }
255} 255}
256 256
257/*! 257/*!
258 \class Config config.h 258 \class Config config.h
259 \brief The Config class provides for saving application cofniguration state. 259 \brief The Config class provides for saving application cofniguration state.
260 260
261 You should keep a Config in existence only while you do not want others 261 You should keep a Config in existence only while you do not want others
262 to be able to change the state. There is no locking currently, but there 262 to be able to change the state. There is no locking currently, but there
263 may be in the future. 263 may be in the future.
264*/ 264*/
265 265
266/*! 266/*!
267 \enum Config::ConfigGroup 267 \enum Config::ConfigGroup
268 \internal 268 \internal
269*/ 269*/
270 270
271/*! 271/*!
272 \enum Config::Domain 272 \enum Config::Domain
273 273
274 \value File 274 \value File
275 \value User 275 \value User
276 276
277 See Config for details. 277 See Config for details.
278*/ 278*/
279 279
280/*! 280/*!
281 Constructs a config that will load or create a configuration with the 281 Constructs a config that will load or create a configuration with the
282 given \a name in the given \a domain. 282 given \a name in the given \a domain.
283 283
284 You must call setGroup() before doing much else with the Config. 284 You must call setGroup() before doing much else with the Config.
285 285
286 In the default Domain, \e User, 286 In the default Domain, \e User,
287 the configuration is user-specific. \a name should not contain "/" in 287 the configuration is user-specific. \a name should not contain "/" in
288 this case, and in general should be the name of the C++ class that is 288 this case, and in general should be the name of the C++ class that is
289 primarily responsible for maintaining the configuration. 289 primarily responsible for maintaining the configuration.
290 290
291 In the File Domain, \a name is an absolute filename. 291 In the File Domain, \a name is an absolute filename.
292*/ 292*/
293Config::Config( const QString &name, Domain domain ) 293Config::Config( const QString &name, Domain domain )
294 : filename( configFilename(name,domain) ) 294 : filename( configFilename(name,domain) )
295{ 295{
296 git = groups.end(); 296 git = groups.end();
297 d = 0; 297 d = 0;
298 read(); 298 read();
299} 299}
300 300
301 301
302// Sharp ROM compatibility 302// Sharp ROM compatibility
303Config::Config ( const QString &name, bool what ) 303Config::Config ( const QString &name, bool what )
304 : filename( configFilename(name,what ? User : File) ) 304 : filename( configFilename(name,what ? User : File) )
305{ 305{
306 git = groups.end(); 306 git = groups.end();
307 d = 0; 307 d = 0;
308 read(); 308 read();
309} 309}
310 310
311/*! 311/*!
312 Writes any changes to disk and destroys the in-memory object. 312 Writes any changes to disk and destroys the in-memory object.
313*/ 313*/
314Config::~Config() 314Config::~Config()
315{ 315{
316 if ( changed ) 316 if ( changed )
317 write(); 317 write();
318 318
319 delete d; 319 delete d;
320} 320}
321 321
322/*! 322/*!
323 Returns whether the current group has an entry called \a key. 323 Returns whether the current group has an entry called \a key.
324*/ 324*/
325bool Config::hasKey( const QString &key ) const 325bool Config::hasKey( const QString &key ) const
326{ 326{
327 if ( groups.end() == git ) 327 if ( groups.end() == git )
328 return FALSE; 328 return FALSE;
329 ConfigGroup::ConstIterator it = ( *git ).find( key ); 329 ConfigGroup::ConstIterator it = ( *git ).find( key );
330 if ( it == ( *git ).end() ) { 330 if ( it == ( *git ).end() ) {
331 if ( d && !d->trcontext.isNull() ) { 331 if ( d && !d->trcontext.isNull() ) {
332 it = ( *git ).find( key + "[]" ); 332 it = ( *git ).find( key + "[]" );
333 } else if ( d && d->multilang ) { 333 } else if ( d && d->multilang ) {
334 it = ( *git ).find( key + "["+lang+"]" ); 334 it = ( *git ).find( key + "["+lang+"]" );
335 if ( it == ( *git ).end() && !glang.isEmpty() ) 335 if ( it == ( *git ).end() && !glang.isEmpty() )
336 it = ( *git ).find( key + "["+glang+"]" ); 336 it = ( *git ).find( key + "["+glang+"]" );
337 } 337 }
338 } 338 }
339 return it != ( *git ).end(); 339 return it != ( *git ).end();
340} 340}
341 341
342/*! 342/*!
343 Sets the current group for subsequent reading and writing of 343 Sets the current group for subsequent reading and writing of
344 entries to \a gname. Grouping allows the application to partition the namespace. 344 entries to \a gname. Grouping allows the application to partition the namespace.
345 345
346 This function must be called prior to any reading or writing 346 This function must be called prior to any reading or writing
347 of entries. 347 of entries.
348 348
349 The \a gname must not be empty. 349 The \a gname must not be empty.
350*/ 350*/
351void Config::setGroup( const QString &gname ) 351void Config::setGroup( const QString &gname )
352{ 352{
353 QMap< QString, ConfigGroup>::Iterator it = groups.find( gname ); 353 QMap< QString, ConfigGroup>::Iterator it = groups.find( gname );
354 if ( it == groups.end() ) { 354 if ( it == groups.end() ) {
355 git = groups.insert( gname, ConfigGroup() ); 355 git = groups.insert( gname, ConfigGroup() );
356 changed = TRUE; 356 changed = TRUE;
357 return; 357 return;
358 } 358 }
359 git = it; 359 git = it;
360} 360}
361 361
362/*! 362/*!
363 Writes a (\a key, \a value) entry to the current group. 363 Writes a (\a key, \a value) entry to the current group.
364 364
365 \sa readEntry() 365 \sa readEntry()
366*/ 366*/
367void Config::writeEntry( const QString &key, const char* value ) 367void Config::writeEntry( const QString &key, const char* value )
368{ 368{
369 writeEntry(key,QString(value)); 369 writeEntry(key,QString(value));
370} 370}
371 371
372/*! 372/*!
373 Writes a (\a key, \a value) entry to the current group. 373 Writes a (\a key, \a value) entry to the current group.
374 374
375 \sa readEntry() 375 \sa readEntry()
376*/ 376*/
377void Config::writeEntry( const QString &key, const QString &value ) 377void Config::writeEntry( const QString &key, const QString &value )
378{ 378{
379 if ( git == groups.end() ) { 379 if ( git == groups.end() ) {
380 qWarning( "no group set" ); 380 qWarning( "no group set" );
381 return; 381 return;
382 } 382 }
383 if ( (*git)[key] != value ) { 383 if ( (*git)[key] != value ) {
384 ( *git ).insert( key, value ); 384 ( *git ).insert( key, value );
385 changed = TRUE; 385 changed = TRUE;
386 } 386 }
387} 387}
388 388
389/* 389/*
390 Note that the degree of protection offered by the encryption here is 390 Note that the degree of protection offered by the encryption here is
391 only sufficient to avoid the most casual observation of the configuration 391 only sufficient to avoid the most casual observation of the configuration
392 files. People with access to the files can write down the contents and 392 files. People with access to the files can write down the contents and
393 decrypt it using this source code. 393 decrypt it using this source code.
394 394
395 Conceivably, and at some burden to the user, this encryption could 395 Conceivably, and at some burden to the user, this encryption could
396 be improved. 396 be improved.
397*/ 397*/
398static QString encipher(const QString& plain) 398static QString encipher(const QString& plain)
399{ 399{
400 // mainly, we make it long 400 // mainly, we make it long
401 QString cipher; 401 QString cipher;
402 int mix=28730492; 402 int mix=28730492;
403 for (int i=0; i<(int)plain.length(); i++) { 403 for (int i=0; i<(int)plain.length(); i++) {
404 int u = plain[i].unicode(); 404 int u = plain[i].unicode();
405 int c = u ^ mix; 405 int c = u ^ mix;
406 QString x = QString::number(c,36); 406 QString x = QString::number(c,36);
407 cipher.append(QChar('a'+x.length())); 407 cipher.append(QChar('a'+x.length()));
408 cipher.append(x); 408 cipher.append(x);
409 mix *= u; 409 mix *= u;
410 } 410 }
411 return cipher; 411 return cipher;
412} 412}
413 413
414static QString decipher(const QString& cipher) 414static QString decipher(const QString& cipher)
415{ 415{
416 QString plain; 416 QString plain;
417 int mix=28730492; 417 int mix=28730492;
418 for (int i=0; i<(int)cipher.length();) { 418 for (int i=0; i<(int)cipher.length();) {
419 int l = cipher[i].unicode()-'a'; 419 int l = cipher[i].unicode()-'a';
420 QString x = cipher.mid(i+1,l); i+=l+1; 420 QString x = cipher.mid(i+1,l); i+=l+1;
421 int u = x.toInt(0,36) ^ mix; 421 int u = x.toInt(0,36) ^ mix;
422 plain.append(QChar(u)); 422 plain.append(QChar(u));
423 mix *= u; 423 mix *= u;
424 } 424 }
425 return plain; 425 return plain;
426} 426}
427 427
428/*! 428/*!
429 Writes an encrypted (\a key, \a value) entry to the current group. 429 Writes an encrypted (\a key, \a value) entry to the current group.
430 430
431 Note that the degree of protection offered by the encryption is 431 Note that the degree of protection offered by the encryption is
432 only sufficient to avoid the most casual observation of the configuration 432 only sufficient to avoid the most casual observation of the configuration
433 files. 433 files.
434 434
435 \sa readEntry() 435 \sa readEntry()
436*/ 436*/
437void Config::writeEntryCrypt( const QString &key, const QString &value ) 437void Config::writeEntryCrypt( const QString &key, const QString &value )
438{ 438{
439 if ( git == groups.end() ) { 439 if ( git == groups.end() ) {
440 qWarning( "no group set" ); 440 qWarning( "no group set" );
441 return; 441 return;
442 } 442 }
443 QString evalue = encipher(value); 443 QString evalue = encipher(value);
444 if ( (*git)[key] != evalue ) { 444 if ( (*git)[key] != evalue ) {
445 ( *git ).insert( key, evalue ); 445 ( *git ).insert( key, evalue );
446 changed = TRUE; 446 changed = TRUE;
447 } 447 }
448} 448}
449 449
450/*! 450/*!
451 Writes a (\a key, \a num) entry to the current group. 451 Writes a (\a key, \a num) entry to the current group.
452 452
453 \sa readNumEntry() 453 \sa readNumEntry()
454*/ 454*/
455void Config::writeEntry( const QString &key, int num ) 455void Config::writeEntry( const QString &key, int num )
456{ 456{
457 QString s; 457 QString s;
458 s.setNum( num ); 458 s.setNum( num );
459 writeEntry( key, s ); 459 writeEntry( key, s );
460} 460}
461 461
462#ifdef Q_HAS_BOOL_TYPE 462#ifdef Q_HAS_BOOL_TYPE
463/*! 463/*!
464 Writes a (\a key, \a b) entry to the current group. This is equivalent 464 Writes a (\a key, \a b) entry to the current group. This is equivalent
465 to writing a 0 or 1 as an integer entry. 465 to writing a 0 or 1 as an integer entry.
466 466
467 \sa readBoolEntry() 467 \sa readBoolEntry()
468*/ 468*/
469void Config::writeEntry( const QString &key, bool b ) 469void Config::writeEntry( const QString &key, bool b )
470{ 470{
471 QString s; 471 QString s;
472 s.setNum( ( int )b ); 472 s.setNum( ( int )b );
473 writeEntry( key, s ); 473 writeEntry( key, s );
474} 474}
475#endif 475#endif
476 476
477/*! 477/*!
478 Writes a (\a key, \a lst) entry to the current group. The list 478 Writes a (\a key, \a lst) entry to the current group. The list
479 is separated by \a sep, so the strings must not contain that character. 479 is separated by \a sep, so the strings must not contain that character.
480 480
481 \sa readListEntry() 481 \sa readListEntry()
482*/ 482*/
483void Config::writeEntry( const QString &key, const QStringList &lst, const QChar &sep ) 483void Config::writeEntry( const QString &key, const QStringList &lst, const QChar &sep )
484{ 484{
485 QString s; 485 QString s;
486 QStringList::ConstIterator it = lst.begin(); 486 QStringList::ConstIterator it = lst.begin();
487 for ( ; it != lst.end(); ++it ) 487 for ( ; it != lst.end(); ++it )
488 s += *it + sep; 488 s += *it + sep;
489 writeEntry( key, s ); 489 writeEntry( key, s );
490} 490}
491 491
492/*! 492/*!
493 Removes the \a key entry from the current group. Does nothing if 493 Removes the \a key entry from the current group. Does nothing if
494 there is no such entry. 494 there is no such entry.
495*/ 495*/
496 496
497void Config::removeEntry( const QString &key ) 497void Config::removeEntry( const QString &key )
498{ 498{
499 if ( git == groups.end() ) { 499 if ( git == groups.end() ) {
500 qWarning( "no group set" ); 500 qWarning( "no group set" );
501 return; 501 return;
502 } 502 }
503 ( *git ).remove( key ); 503 ( *git ).remove( key );
504 changed = TRUE; 504 changed = TRUE;
505} 505}
506 506
507/*! 507/*!
508 \fn bool Config::operator == ( const Config & other ) const 508 \fn bool Config::operator == ( const Config & other ) const
509 509
510 Tests for equality with \a other. Config objects are equal if they refer to the same filename. 510 Tests for equality with \a other. Config objects are equal if they refer to the same filename.
511*/ 511*/
512 512
513/*! 513/*!
514 \fn bool Config::operator != ( const Config & other ) const 514 \fn bool Config::operator != ( const Config & other ) const
515 515
516 Tests for inequality with \a other. Config objects are equal if they refer to the same filename. 516 Tests for inequality with \a other. Config objects are equal if they refer to the same filename.
517*/ 517*/
518 518
519 519
520/*! 520/*!
521 \fn QString Config::readEntry( const QString &key, const QString &deflt ) const 521 \fn QString Config::readEntry( const QString &key, const QString &deflt ) const
522 522
523 Reads a string entry stored with \a key, defaulting to \a deflt if there is no entry. 523 Reads a string entry stored with \a key, defaulting to \a deflt if there is no entry.
524*/ 524*/
525 525
526/* 526/*
527 * ### !LocalTranslator::translate was kept out! 527 * ### !LocalTranslator::translate was kept out!
528 * 528 *
529 */ 529 */
530 530
531/*! 531/*!
532 \internal 532 \internal
533 For compatibility, non-const version. 533 For compatibility, non-const version.
534*/ 534*/
535QString Config::readEntry( const QString &key, const QString &deflt ) 535QString Config::readEntry( const QString &key, const QString &deflt )
536{ 536{
537 QString r; 537 QString r;
538 if ( d && !d->trcontext.isNull() ) { 538 if ( d && !d->trcontext.isNull() ) {
539 // Still try untranslated first, becuase: 539 // Still try untranslated first, becuase:
540 // 1. It's the common case 540 // 1. It's the common case
541 // 2. That way the value can be WRITTEN (becoming untranslated) 541 // 2. That way the value can be WRITTEN (becoming untranslated)
542 r = readEntryDirect( key ); 542 r = readEntryDirect( key );
543 if ( !r.isNull() ) 543 if ( !r.isNull() )
544 return r; 544 return r;
545 r = readEntryDirect( key + "[]" ); 545 r = readEntryDirect( key + "[]" );
546 if ( !r.isNull() ) 546 if ( !r.isNull() )
547 return qApp->translate(d->trfile,d->trcontext,r); 547 return qApp->translate(d->trfile,d->trcontext,r);
548 } else if ( d && d->multilang ) { 548 } else if ( d && d->multilang ) {
549 // For compatibilitity 549 // For compatibilitity
550 r = readEntryDirect( key + "["+lang+"]" ); 550 r = readEntryDirect( key + "["+lang+"]" );
551 if ( !r.isNull() ) 551 if ( !r.isNull() )
552 return r; 552 return r;
553 if ( !glang.isEmpty() ) { 553 if ( !glang.isEmpty() ) {
554 r = readEntryDirect( key + "["+glang+"]" ); 554 r = readEntryDirect( key + "["+glang+"]" );
555 if ( !r.isNull() ) 555 if ( !r.isNull() )
556 return r; 556 return r;
557 } 557 }
558 } 558 }
559 r = readEntryDirect( key, deflt ); 559 r = readEntryDirect( key, deflt );
560 return r; 560 return r;
561} 561}
562 562
563/*! 563/*!
564 \fn QString Config::readEntryCrypt( const QString &key, const QString &deflt ) const 564 \fn QString Config::readEntryCrypt( const QString &key, const QString &deflt ) const
565 565
566 Reads an encrypted string entry stored with \a key, defaulting to \a deflt if there is no entry. 566 Reads an encrypted string entry stored with \a key, defaulting to \a deflt if there is no entry.
567*/ 567*/
568 568
569/*! 569/*!
570 \internal 570 \internal
571 For compatibility, non-const version. 571 For compatibility, non-const version.
572*/ 572*/
573QString Config::readEntryCrypt( const QString &key, const QString &deflt ) 573QString Config::readEntryCrypt( const QString &key, const QString &deflt )
574{ 574{
575 QString res = readEntry( key ); 575 QString res = readEntry( key );
576 if ( res.isNull() ) 576 if ( res.isNull() )
577 return deflt; 577 return deflt;
578 return decipher(res); 578 return decipher(res);
579} 579}
580 580
581/*! 581/*!
582 \fn QString Config::readEntryDirect( const QString &key, const QString &deflt ) const 582 \fn QString Config::readEntryDirect( const QString &key, const QString &deflt ) const
583 \internal 583 \internal
584*/ 584*/
585 585
586/*! 586/*!
587 \internal 587 \internal
588 For compatibility, non-const version. 588 For compatibility, non-const version.
589*/ 589*/
590QString Config::readEntryDirect( const QString &key, const QString &deflt ) 590QString Config::readEntryDirect( const QString &key, const QString &deflt )
591{ 591{
592 if ( git == groups.end() ) { 592 if ( git == groups.end() ) {
593 //qWarning( "no group set" ); 593 //qWarning( "no group set" );
594 return deflt; 594 return deflt;
595 } 595 }
596 ConfigGroup::ConstIterator it = ( *git ).find( key ); 596 ConfigGroup::ConstIterator it = ( *git ).find( key );
597 if ( it != ( *git ).end() ) 597 if ( it != ( *git ).end() )
598 return *it; 598 return *it;
599 else 599 else
600 return deflt; 600 return deflt;
601} 601}
602 602
603/*! 603/*!
604 \fn int Config::readNumEntry( const QString &key, int deflt ) const 604 \fn int Config::readNumEntry( const QString &key, int deflt ) const
605 Reads a numeric entry stored with \a key, defaulting to \a deflt if there is no entry. 605 Reads a numeric entry stored with \a key, defaulting to \a deflt if there is no entry.
606*/ 606*/
607 607
608/*! 608/*!
609 \internal 609 \internal
610 For compatibility, non-const version. 610 For compatibility, non-const version.
611*/ 611*/
612int Config::readNumEntry( const QString &key, int deflt ) 612int Config::readNumEntry( const QString &key, int deflt )
613{ 613{
614 QString s = readEntry( key ); 614 QString s = readEntry( key );
615 if ( s.isEmpty() ) 615 if ( s.isEmpty() )
616 return deflt; 616 return deflt;
617 else 617 else
618 return s.toInt(); 618 return s.toInt();
619} 619}
620 620
621/*! 621/*!
622 \fn bool Config::readBoolEntry( const QString &key, bool deflt ) const 622 \fn bool Config::readBoolEntry( const QString &key, bool deflt ) const
623 Reads a bool entry stored with \a key, defaulting to \a deflt if there is no entry. 623 Reads a bool entry stored with \a key, defaulting to \a deflt if there is no entry.
624*/ 624*/
625 625
626/*! 626/*!
627 \internal 627 \internal
628 For compatibility, non-const version. 628 For compatibility, non-const version.
629*/ 629*/
630bool Config::readBoolEntry( const QString &key, bool deflt ) 630bool Config::readBoolEntry( const QString &key, bool deflt )
631{ 631{
632 QString s = readEntry( key ); 632 QString s = readEntry( key );
633 if ( s.isEmpty() ) 633 if ( s.isEmpty() )
634 return deflt; 634 return deflt;
635 else 635 else
636 return (bool)s.toInt(); 636 return (bool)s.toInt();
637} 637}
638 638
639/*! 639/*!
640 \fn QStringList Config::readListEntry( const QString &key, const QChar &sep ) const 640 \fn QStringList Config::readListEntry( const QString &key, const QChar &sep ) const
641 Reads a string list entry stored with \a key, and with \a sep as the separator. 641 Reads a string list entry stored with \a key, and with \a sep as the separator.
642*/ 642*/
643 643
644/*! 644/*!
645 \internal 645 \internal
646 For compatibility, non-const version. 646 For compatibility, non-const version.
647*/ 647*/
648QStringList Config::readListEntry( const QString &key, const QChar &sep ) 648QStringList Config::readListEntry( const QString &key, const QChar &sep )
649{ 649{
650 QString s = readEntry( key ); 650 QString s = readEntry( key );
651 if ( s.isEmpty() ) 651 if ( s.isEmpty() )
652 return QStringList(); 652 return QStringList();
653 else 653 else
654 return QStringList::split( sep, s ); 654 return QStringList::split( sep, s );
655} 655}
656 656
657/*! 657/*!
658 Removes all entries from the current group. 658 Removes all entries from the current group.
659*/ 659*/
660void Config::clearGroup() 660void Config::clearGroup()
661{ 661{
662 if ( git == groups.end() ) { 662 if ( git == groups.end() ) {
663 qWarning( "no group set" ); 663 qWarning( "no group set" );
664 return; 664 return;
665 } 665 }
666 if ( !(*git).isEmpty() ) { 666 if ( !(*git).isEmpty() ) {
667 ( *git ).clear(); 667 ( *git ).clear();
668 changed = TRUE; 668 changed = TRUE;
669 } 669 }
670} 670}
671 671
672/*! 672/*!
673 \internal 673 \internal
674*/ 674*/
675void Config::write( const QString &fn ) 675void Config::write( const QString &fn )
676{ 676{
677 QString oldGroup = git.key(); 677 QString oldGroup = git.key();
678 678
679 QString strNewFile; 679 QString strNewFile;
680 if ( !fn.isEmpty() ) 680 if ( !fn.isEmpty() )
681 filename = fn; 681 filename = fn;
682 strNewFile = filename + ".new"; 682 strNewFile = filename + ".new";
683 683
684 QFile f( strNewFile ); 684 QFile f( strNewFile );
685 if ( !f.open( IO_WriteOnly|IO_Raw ) ) { 685 if ( !f.open( IO_WriteOnly|IO_Raw ) ) {
686 qWarning( "could not open for writing `%s'", strNewFile.latin1() ); 686 qWarning( "could not open for writing `%s'", strNewFile.latin1() );
687 git = groups.end(); 687 git = groups.end();
688 return; 688 return;
689 } 689 }
690 690
691 QString str; 691 QString str;
692 QCString cstr; 692 QCString cstr;
693 QMap< QString, ConfigGroup >::Iterator g_it = groups.begin(); 693 QMap< QString, ConfigGroup >::Iterator g_it = groups.begin();
694 694
695 for ( ; g_it != groups.end(); ++g_it ) { 695 for ( ; g_it != groups.end(); ++g_it ) {
696 str += "[" + g_it.key() + "]\n"; 696 str += "[" + g_it.key() + "]\n";
697 ConfigGroup::Iterator e_it = ( *g_it ).begin(); 697 ConfigGroup::Iterator e_it = ( *g_it ).begin();
698 for ( ; e_it != ( *g_it ).end(); ++e_it ) 698 for ( ; e_it != ( *g_it ).end(); ++e_it )
699 str += e_it.key() + " = " + *e_it + "\n"; 699 str += e_it.key() + " = " + *e_it + "\n";
700 } 700 }
701 cstr = str.utf8(); 701 cstr = str.utf8();
702 702
703 int total_length; 703 int total_length;
704 total_length = f.writeBlock( cstr.data(), cstr.length() ); 704 total_length = f.writeBlock( cstr.data(), cstr.length() );
705 if ( total_length != int(cstr.length()) ) { 705 if ( total_length != int(cstr.length()) ) {
706 QMessageBox::critical( 0, QObject::tr("Out of Space"), 706 QMessageBox::critical( 0, QObject::tr("Out of Space"),
707 QObject::tr("There was a problem creating\nConfiguration Information \nfor this program.\n\nPlease free up some space and\ntry again.") ); 707 QObject::tr("There was a problem creating\nConfiguration Information \nfor this program.\n\nPlease free up some space and\ntry again.") );
708 f.close(); 708 f.close();
709 QFile::remove( strNewFile ); 709 QFile::remove( strNewFile );
710 return; 710 return;
711 } 711 }
712 712
713 f.close(); 713 f.close();
714 // now rename the file... 714 // now rename the file...
715 if ( rename( strNewFile, filename ) < 0 ) { 715 if ( rename( strNewFile, filename ) < 0 ) {
716 qWarning( "problem renaming the file %s to %s", strNewFile.latin1(), 716 qWarning( "problem renaming the file %s to %s", strNewFile.latin1(),
717 filename.latin1() ); 717 filename.latin1() );
718 QFile::remove( strNewFile ); 718 QFile::remove( strNewFile );
719 return; 719 return;
720 } 720 }
721 721
722#ifndef Q_OS_WIN32 722#ifndef Q_OS_WIN32
723 ConfigCache::instance()->insert( filename, groups, d ); 723 ConfigCache::instance()->insert( filename, groups, d );
724 setGroup( oldGroup ); 724 setGroup( oldGroup );
725#endif 725#endif
726 changed = FALSE; 726 changed = FALSE;
727} 727}
728 728
729/*! 729/*!
730 Returns whether the Config is in a valid state. 730 Returns whether the Config is in a valid state.
731*/ 731*/
732bool Config::isValid() const 732bool Config::isValid() const
733{ 733{
734 return groups.end() != git; 734 return groups.end() != git;
735} 735}
736 736
737/*! 737/*!
738 \internal 738 \internal
739*/ 739*/
740void Config::read() 740void Config::read()
741{ 741{
742 changed = FALSE; 742 changed = FALSE;
743 743
744 QString readFilename(filename); 744 QString readFilename(filename);
745 745
746 if ( !QFile::exists(filename) ) { 746 if ( !QFile::exists(filename) ) {
747 bool failed = TRUE; 747 bool failed = TRUE;
748 QFileInfo fi(filename); 748 QFileInfo fi(filename);
749 QString settingsDir = QDir::homeDirPath() + "/Settings"; 749 QString settingsDir = QDir::homeDirPath() + "/Settings";
750 if (fi.dirPath(TRUE) == settingsDir) { 750 if (fi.dirPath(TRUE) == settingsDir) {
751 // User setting - see if there is a default in $OPIEDIR/etc/default/ 751 // User setting - see if there is a default in $OPIEDIR/etc/default/
752 QString dftlFile = QPEApplication::qpeDir() + "etc/default/" + fi.fileName(); 752 QString dftlFile = QPEApplication::qpeDir() + "etc/default/" + fi.fileName();
753 if (QFile::exists(dftlFile)) { 753 if (QFile::exists(dftlFile)) {
754 readFilename = dftlFile; 754 readFilename = dftlFile;
755 failed = FALSE; 755 failed = FALSE;
756 } 756 }
757 } 757 }
758 if (failed) { 758 if (failed) {
759 git = groups.end(); 759 git = groups.end();
760 return; 760 return;
761 } 761 }
762 } 762 }
763 763
764#ifndef Q_OS_WIN32 764#ifndef Q_OS_WIN32
765 765
766 if (ConfigCache::instance()->find(readFilename, groups, &d)) { 766 if (ConfigCache::instance()->find(readFilename, groups, &d)) {
767 if ( d && d->multilang ) { 767 if ( d && d->multilang ) {
768 QStringList l = Global::languageList(); 768 QStringList l = Global::languageList();
769 lang = l[0]; 769 lang = l[0];
770 glang = l[1]; 770 glang = l[1];
771 } 771 }
772 git = groups.begin(); 772 git = groups.begin();
773 return; 773 return;
774 } 774 }
775#endif 775#endif
776 776
777 QFile f( readFilename ); 777 QFile f( readFilename );
778 if ( !f.open( IO_ReadOnly ) ) { 778 if ( !f.open( IO_ReadOnly ) ) {
779 git = groups.end(); 779 git = groups.end();
780 return; 780 return;
781 } 781 }
782 782
783 if (f.getch()!='[') { 783 if (f.getch()!='[') {
784 git = groups.end(); 784 git = groups.end();
785 return; 785 return;
786 } 786 }
787 f.ungetch('['); 787 f.ungetch('[');
788 788
789 QTextStream s( &f ); 789 QTextStream s( &f );
790 read( s ); 790 read( s );
791 f.close(); 791 f.close();
792 792
793#ifndef Q_OS_WIN32 793#ifndef Q_OS_WIN32
794 ConfigCache::instance()->insert(readFilename, groups, d); 794 ConfigCache::instance()->insert(readFilename, groups, d);
795#endif 795#endif
796} 796}
797 797
798/*! 798/*!
799 \internal 799 \internal
800*/ 800*/
801bool Config::parse( const QString &l ) 801bool Config::parse( const QString &l )
802{ 802{
803 QString line = l.stripWhiteSpace(); 803 QString line = l.stripWhiteSpace();
804 if ( line[ 0 ] == QChar( '[' ) ) { 804 if ( line[ 0 ] == QChar( '[' ) ) {
805 QString gname = line; 805 QString gname = line;
806 gname = gname.remove( 0, 1 ); 806 gname = gname.remove( 0, 1 );
807 if ( gname[ (int)gname.length() - 1 ] == QChar( ']' ) ) 807 if ( gname[ (int)gname.length() - 1 ] == QChar( ']' ) )