summaryrefslogtreecommitdiff
path: root/library/config.cpp
authorzecke <zecke>2005-04-16 22:02:12 (UTC)
committer zecke <zecke>2005-04-16 22:02:12 (UTC)
commit206784bc9919dca87a71de9b998ff0ece08bd8ca (patch) (unidiff)
treeb45acd807cdb073e6a9c0d07862f72b395c865a9 /library/config.cpp
parentf2b8a146b411a99c43050ab902f641ee406e3bab (diff)
downloadopie-206784bc9919dca87a71de9b998ff0ece08bd8ca.zip
opie-206784bc9919dca87a71de9b998ff0ece08bd8ca.tar.gz
opie-206784bc9919dca87a71de9b998ff0ece08bd8ca.tar.bz2
Opie X11:
Do not take the local qpeapplication.h but the Opie/X11 version
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,423 +1,423 @@
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;