00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <qdir.h>
00022 #include <qfile.h>
00023 #include <qfileinfo.h>
00024 #include <qmessagebox.h>
00025 #if QT_VERSION <= 230 && defined(QT_NO_CODECS)
00026 #include <qtextcodec.h>
00027 #endif
00028 #include <qtextstream.h>
00029
00030 #include <sys/stat.h>
00031 #include <sys/types.h>
00032 #include <fcntl.h>
00033 #include <stdlib.h>
00034 #include <unistd.h>
00035
00036 #define QTOPIA_INTERNAL_LANGLIST
00037 #include "config.h"
00038 #include "global.h"
00039
00040
00044 QString Config::configFilename(const QString& name, Domain d)
00045 {
00046 switch (d) {
00047 case File:
00048 return name;
00049 case User: {
00050 QDir dir = (QString(getenv("HOME")) + "/Settings");
00051 if ( !dir.exists() )
00052 mkdir(dir.path().local8Bit(),0700);
00053 return dir.path() + "/" + name + ".conf";
00054 }
00055 }
00056 return name;
00057 }
00058
00095 Config::Config( const QString &name, Domain domain )
00096 : filename( configFilename(name,domain) )
00097 {
00098 git = groups.end();
00099 read();
00100 QStringList l = Global::languageList();
00101 lang = l[0];
00102 glang = l[1];
00103 }
00104
00105
00106
00107 Config::Config ( const QString &name, bool what )
00108 : filename( configFilename(name,what ? User : File) )
00109 {
00110 git = groups.end();
00111 read();
00112 QStringList l = Global::languageList();
00113 lang = l[0];
00114 glang = l[1];
00115 }
00116
00120 Config::~Config()
00121 {
00122 if ( changed )
00123 write();
00124 }
00125
00129 bool Config::hasKey( const QString &key ) const
00130 {
00131 if ( groups.end() == git )
00132 return FALSE;
00133 ConfigGroup::ConstIterator it = ( *git ).find( key );
00134 return it != ( *git ).end();
00135 }
00136
00146 void Config::setGroup( const QString &gname )
00147 {
00148 QMap< QString, ConfigGroup>::Iterator it = groups.find( gname );
00149 if ( it == groups.end() ) {
00150 git = groups.insert( gname, ConfigGroup() );
00151 changed = TRUE;
00152 return;
00153 }
00154 git = it;
00155 }
00156
00162 void Config::writeEntry( const QString &key, const char* value )
00163 {
00164 writeEntry(key,QString(value));
00165 }
00166
00172 void Config::writeEntry( const QString &key, const QString &value )
00173 {
00174 if ( git == groups.end() ) {
00175 qWarning( "no group set" );
00176 return;
00177 }
00178 if ( (*git)[key] != value ) {
00179 ( *git ).insert( key, value );
00180 changed = TRUE;
00181 }
00182 }
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193 static QString encipher(const QString& plain)
00194 {
00195
00196 QString cipher;
00197 int mix=28730492;
00198 for (int i=0; i<(int)plain.length(); i++) {
00199 int u = plain[i].unicode();
00200 int c = u ^ mix;
00201 QString x = QString::number(c,36);
00202 cipher.append(QChar('a'+x.length()));
00203 cipher.append(x);
00204 mix *= u;
00205 }
00206 return cipher;
00207 }
00208
00209 static QString decipher(const QString& cipher)
00210 {
00211 QString plain;
00212 int mix=28730492;
00213 for (int i=0; i<(int)cipher.length();) {
00214 int l = cipher[i].unicode()-'a';
00215 QString x = cipher.mid(i+1,l); i+=l+1;
00216 int u = x.toInt(0,36) ^ mix;
00217 plain.append(QChar(u));
00218 mix *= u;
00219 }
00220 return plain;
00221 }
00222
00232 void Config::writeEntryCrypt( const QString &key, const QString &value )
00233 {
00234 if ( git == groups.end() ) {
00235 qWarning( "no group set" );
00236 return;
00237 }
00238 QString evalue = encipher(value);
00239 if ( (*git)[key] != evalue ) {
00240 ( *git ).insert( key, evalue );
00241 changed = TRUE;
00242 }
00243 }
00244
00250 void Config::writeEntry( const QString &key, int num )
00251 {
00252 QString s;
00253 s.setNum( num );
00254 writeEntry( key, s );
00255 }
00256
00257 #ifdef Q_HAS_BOOL_TYPE
00258
00264 void Config::writeEntry( const QString &key, bool b )
00265 {
00266 QString s;
00267 s.setNum( ( int )b );
00268 writeEntry( key, s );
00269 }
00270 #endif
00271
00278 void Config::writeEntry( const QString &key, const QStringList &lst, const QChar &sep )
00279 {
00280 QString s;
00281 QStringList::ConstIterator it = lst.begin();
00282 for ( ; it != lst.end(); ++it )
00283 s += *it + sep;
00284 writeEntry( key, s );
00285 }
00286
00292 void Config::removeEntry( const QString &key )
00293 {
00294 if ( git == groups.end() ) {
00295 qWarning( "no group set" );
00296 return;
00297 }
00298 ( *git ).remove( key );
00299 changed = TRUE;
00300 }
00301
00324 QString Config::readEntry( const QString &key, const QString &deflt )
00325 {
00326 QString res = readEntryDirect( key+"["+lang+"]" );
00327 if ( !res.isNull() )
00328 return res;
00329 if ( !glang.isEmpty() ) {
00330 res = readEntryDirect( key+"["+glang+"]" );
00331 if ( !res.isNull() )
00332 return res;
00333 }
00334 return readEntryDirect( key, deflt );
00335 }
00336
00347 QString Config::readEntryCrypt( const QString &key, const QString &deflt )
00348 {
00349 QString res = readEntryDirect( key+"["+lang+"]" );
00350 if ( res.isNull() && glang.isEmpty() )
00351 res = readEntryDirect( key+"["+glang+"]" );
00352 if ( res.isNull() )
00353 res = readEntryDirect( key, QString::null );
00354 if ( res.isNull() )
00355 return deflt;
00356 return decipher(res);
00357 }
00358
00368 QString Config::readEntryDirect( const QString &key, const QString &deflt )
00369 {
00370 if ( git == groups.end() ) {
00371
00372 return deflt;
00373 }
00374 ConfigGroup::ConstIterator it = ( *git ).find( key );
00375 if ( it != ( *git ).end() )
00376 return *it;
00377 else
00378 return deflt;
00379 }
00380
00390 int Config::readNumEntry( const QString &key, int deflt )
00391 {
00392 QString s = readEntry( key );
00393 if ( s.isEmpty() )
00394 return deflt;
00395 else
00396 return s.toInt();
00397 }
00398
00408 bool Config::readBoolEntry( const QString &key, bool deflt )
00409 {
00410 QString s = readEntry( key );
00411 if ( s.isEmpty() )
00412 return deflt;
00413 else
00414 return (bool)s.toInt();
00415 }
00416
00426 QStringList Config::readListEntry( const QString &key, const QChar &sep )
00427 {
00428 QString s = readEntry( key );
00429 if ( s.isEmpty() )
00430 return QStringList();
00431 else
00432 return QStringList::split( sep, s );
00433 }
00434
00438 void Config::clearGroup()
00439 {
00440 if ( git == groups.end() ) {
00441 qWarning( "no group set" );
00442 return;
00443 }
00444 if ( !(*git).isEmpty() ) {
00445 ( *git ).clear();
00446 changed = TRUE;
00447 }
00448 }
00449
00453 void Config::write( const QString &fn )
00454 {
00455 QString strNewFile;
00456 if ( !fn.isEmpty() )
00457 filename = fn;
00458 strNewFile = filename + ".new";
00459
00460 QFile f( strNewFile );
00461 if ( !f.open( IO_WriteOnly|IO_Raw ) ) {
00462 qWarning( "could not open for writing `%s'", strNewFile.latin1() );
00463 git = groups.end();
00464 return;
00465 }
00466
00467 QString str;
00468 QCString cstr;
00469 QMap< QString, ConfigGroup >::Iterator g_it = groups.begin();
00470
00471 for ( ; g_it != groups.end(); ++g_it ) {
00472 str += "[" + g_it.key() + "]\n";
00473 ConfigGroup::Iterator e_it = ( *g_it ).begin();
00474 for ( ; e_it != ( *g_it ).end(); ++e_it )
00475 str += e_it.key() + " = " + *e_it + "\n";
00476 }
00477 cstr = str.utf8();
00478
00479 int total_length;
00480 total_length = f.writeBlock( cstr.data(), cstr.length() );
00481 if ( total_length != int(cstr.length()) ) {
00482 QMessageBox::critical( 0, QObject::tr("Out of Space"),
00483 QObject::tr("There was a problem creating\nConfiguration Information \nfor this program.\n\nPlease free up some space and\ntry again.") );
00484 f.close();
00485 QFile::remove( strNewFile );
00486 return;
00487 }
00488
00489 f.close();
00490
00491 if ( rename( strNewFile, filename ) < 0 ) {
00492 qWarning( "problem renaming the file %s to %s", strNewFile.latin1(),
00493 filename.latin1() );
00494 QFile::remove( strNewFile );
00495 }
00496 }
00497
00501 bool Config::isValid() const
00502 {
00503 return groups.end() != git;
00504 }
00505
00509 void Config::read()
00510 {
00511 changed = FALSE;
00512
00513 if ( !QFileInfo( filename ).exists() ) {
00514 git = groups.end();
00515 return;
00516 }
00517
00518 QFile f( filename );
00519 if ( !f.open( IO_ReadOnly ) ) {
00520 git = groups.end();
00521 return;
00522 }
00523
00524
00525
00526
00527
00528
00529 if ( f.size() > 100000 ) {
00530 return;
00531 }
00532
00533
00534 QTextStream s( &f );
00535 #if QT_VERSION <= 230 && defined(QT_NO_CODECS)
00536
00537 s.setCodec( QTextCodec::codecForMib( 106 ) );
00538 #else
00539 s.setEncoding( QTextStream::UnicodeUTF8 );
00540 #endif
00541
00542 QStringList list = QStringList::split('\n', s.read() );
00543 f.close();
00544
00545 for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) {
00546 if ( !parse( *it ) ) {
00547 git = groups.end();
00548 return;
00549 }
00550 }
00551 }
00552
00556 bool Config::parse( const QString &l )
00557 {
00558 QString line = l.stripWhiteSpace();
00559
00560 if ( line [0] == QChar ( '#' ))
00561 return true;
00562
00563 if ( line[ 0 ] == QChar( '[' ) ) {
00564 QString gname = line;
00565 gname = gname.remove( 0, 1 );
00566 if ( gname[ (int)gname.length() - 1 ] == QChar( ']' ) )
00567 gname = gname.remove( gname.length() - 1, 1 );
00568 git = groups.insert( gname, ConfigGroup() );
00569 } else if ( !line.isEmpty() ) {
00570 if ( git == groups.end() )
00571 return FALSE;
00572 int eq = line.find( '=' );
00573 if ( eq == -1 )
00574 return FALSE;
00575 QString key = line.left(eq).stripWhiteSpace();
00576 QString value = line.mid(eq+1).stripWhiteSpace();
00577 ( *git ).insert( key, value );
00578 }
00579 return TRUE;
00580 }