KIO
authinfo.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "authinfo.h"
00022
00023 #include <config.h>
00024
00025 #include <sys/stat.h>
00026 #include <stdio.h>
00027 #include <fcntl.h>
00028 #include <unistd.h>
00029 #include <sys/types.h>
00030
00031 #include <QtCore/QByteArray>
00032 #include <QtCore/QDir>
00033 #include <QtCore/QFile>
00034 #include <QtDBus/QDBusArgument>
00035 #include <QtDBus/QDBusMetaType>
00036 #include <kde_file.h>
00037
00038 #include <kdebug.h>
00039 #include <kstandarddirs.h>
00040 #include <ksavefile.h>
00041
00042 #define NETRC_READ_BUF_SIZE 4096
00043
00044 using namespace KIO;
00045
00047
00048 class ExtraField
00049 {
00050 public:
00051 QString customTitle;
00052 AuthInfo::FieldFlags flags;
00053 QVariant value;
00054
00055 ExtraField() : flags(AuthInfo::ExtraFieldNoFlags) {}
00056 };
00057 Q_DECLARE_METATYPE(ExtraField)
00058
00059 QDataStream& operator<< (QDataStream& s, const ExtraField& extraField)
00060 {
00061 s << extraField.customTitle;
00062 s << (int)extraField.flags;
00063 s << extraField.value;
00064 return s;
00065 }
00066
00067 QDataStream& operator>> (QDataStream& s, ExtraField& extraField)
00068 {
00069 s >> extraField.customTitle ;
00070 int i;
00071 s >> i;
00072 extraField.flags = (AuthInfo::FieldFlags)i;
00073 s >> extraField.value ;
00074 return s;
00075 }
00076
00077 QDBusArgument &operator<<(QDBusArgument &argument, const ExtraField &extraField)
00078 {
00079 argument.beginStructure();
00080 argument << extraField.customTitle << (int)extraField.flags
00081 << QDBusVariant(extraField.value);
00082 argument.endStructure();
00083 return argument;
00084 }
00085
00086 const QDBusArgument &operator>>(const QDBusArgument &argument, ExtraField &extraField)
00087 {
00088 QDBusVariant value;
00089 int flag;
00090
00091 argument.beginStructure();
00092 argument >> extraField.customTitle >> flag >> value;
00093 argument.endStructure();
00094
00095 extraField.value = value.variant();
00096 extraField.flags = (KIO::AuthInfo::FieldFlags)flag;
00097 return argument;
00098 }
00099
00100 class KIO::AuthInfoPrivate
00101 {
00102 public:
00103 AuthInfoPrivate()
00104 {}
00105
00106 QMap<QString, ExtraField> extraFields;
00107 };
00108
00109
00111
00112 AuthInfo::AuthInfo() : d(new AuthInfoPrivate())
00113 {
00114 modified = false;
00115 readOnly = false;
00116 verifyPath = false;
00117 keepPassword = false;
00118 AuthInfo::registerMetaTypes();
00119 }
00120
00121 AuthInfo::AuthInfo( const AuthInfo& info ) : d(new AuthInfoPrivate())
00122 {
00123 (*this) = info;
00124 }
00125
00126 AuthInfo::~AuthInfo()
00127 {
00128 delete d;
00129 }
00130
00131 AuthInfo& AuthInfo::operator= ( const AuthInfo& info )
00132 {
00133 url = info.url;
00134 username = info.username;
00135 password = info.password;
00136 prompt = info.prompt;
00137 caption = info.caption;
00138 comment = info.comment;
00139 commentLabel = info.commentLabel;
00140 realmValue = info.realmValue;
00141 digestInfo = info.digestInfo;
00142 verifyPath = info.verifyPath;
00143 readOnly = info.readOnly;
00144 keepPassword = info.keepPassword;
00145 modified = info.modified;
00146 d->extraFields = info.d->extraFields;
00147 return *this;
00148 }
00149
00150 bool AuthInfo::isModified() const
00151 {
00152 return modified;
00153 }
00154
00155 void AuthInfo::setModified( bool flag )
00156 {
00157 modified = flag;
00158 }
00159
00161
00162 void AuthInfo::setExtraField(const QString &fieldName, const QVariant & value)
00163 {
00164 d->extraFields[fieldName].value = value;
00165 }
00166
00167 void AuthInfo::setExtraFieldFlags(const QString &fieldName, const FieldFlags flags)
00168 {
00169 d->extraFields[fieldName].flags = flags;
00170 }
00171
00172 QVariant AuthInfo::getExtraField(const QString &fieldName) const
00173 {
00174 if (!d->extraFields.contains(fieldName)) return QVariant();
00175 return d->extraFields[fieldName].value;
00176 }
00177
00178 AuthInfo::FieldFlags AuthInfo::getExtraFieldFlags(const QString &fieldName) const
00179 {
00180 if (!d->extraFields.contains(fieldName)) return AuthInfo::ExtraFieldNoFlags;
00181 return d->extraFields[fieldName].flags;
00182 }
00183
00184 void AuthInfo::registerMetaTypes()
00185 {
00186 qRegisterMetaType<ExtraField>();
00187 qRegisterMetaType<KIO::AuthInfo>();
00188 qDBusRegisterMetaType<ExtraField>();
00189 qDBusRegisterMetaType<KIO::AuthInfo>();
00190 }
00191
00193
00194 QDataStream& KIO::operator<< (QDataStream& s, const AuthInfo& a)
00195 {
00196 s << (quint8)1
00197 << a.url << a.username << a.password << a.prompt << a.caption
00198 << a.comment << a.commentLabel << a.realmValue << a.digestInfo
00199 << a.verifyPath << a.readOnly << a.keepPassword << a.modified
00200 << a.d->extraFields;
00201 return s;
00202 }
00203
00204 QDataStream& KIO::operator>> (QDataStream& s, AuthInfo& a)
00205 {
00206 quint8 version;
00207 s >> version
00208 >> a.url >> a.username >> a.password >> a.prompt >> a.caption
00209 >> a.comment >> a.commentLabel >> a.realmValue >> a.digestInfo
00210 >> a.verifyPath >> a.readOnly >> a.keepPassword >> a.modified
00211 >> a.d->extraFields;
00212 return s;
00213 }
00214
00215 QDBusArgument &KIO::operator<<(QDBusArgument &argument, const AuthInfo &a)
00216 {
00217 argument.beginStructure();
00218 argument << (quint8)1
00219 << a.url.url() << a.username << a.password << a.prompt << a.caption
00220 << a.comment << a.commentLabel << a.realmValue << a.digestInfo
00221 << a.verifyPath << a.readOnly << a.keepPassword << a.modified
00222 << a.d->extraFields;
00223 argument.endStructure();
00224 return argument;
00225 }
00226
00227 const QDBusArgument &KIO::operator>>(const QDBusArgument &argument, AuthInfo &a)
00228 {
00229 QString url;
00230 quint8 version;
00231
00232 argument.beginStructure();
00233 argument >> version
00234 >> url >> a.username >> a.password >> a.prompt >> a.caption
00235 >> a.comment >> a.commentLabel >> a.realmValue >> a.digestInfo
00236 >> a.verifyPath >> a.readOnly >> a.keepPassword >> a.modified
00237 >> a.d->extraFields;
00238 argument.endStructure();
00239
00240 a.url = url;
00241 return argument;
00242 }
00243
00244 typedef QList<NetRC::AutoLogin> LoginList;
00245 typedef QMap<QString, LoginList> LoginMap;
00246
00247 class NetRC::NetRCPrivate
00248 {
00249 public:
00250 NetRCPrivate()
00251 : isDirty(false)
00252 {}
00253 bool isDirty;
00254 LoginMap loginMap;
00255 };
00256
00257 NetRC* NetRC::instance = 0L;
00258
00259 NetRC::NetRC()
00260 : d( new NetRCPrivate )
00261 {
00262 }
00263
00264 NetRC::~NetRC()
00265 {
00266 delete instance;
00267 instance = 0L;
00268 delete d;
00269 }
00270
00271 NetRC* NetRC::self()
00272 {
00273 if ( !instance )
00274 instance = new NetRC;
00275 return instance;
00276 }
00277
00278 bool NetRC::lookup( const KUrl& url, AutoLogin& login, bool userealnetrc,
00279 const QString &_type, LookUpMode mode )
00280 {
00281
00282 if ( !url.isValid() )
00283 return false;
00284
00285 QString type = _type;
00286 if ( type.isEmpty() )
00287 type = url.protocol();
00288
00289 if ( d->loginMap.isEmpty() || d->isDirty )
00290 {
00291 d->loginMap.clear();
00292
00293 QString filename = KStandardDirs::locateLocal("config", QLatin1String("kionetrc"));
00294 bool status = parse (openf (filename));
00295
00296 if ( userealnetrc )
00297 {
00298 filename = QDir::homePath() + QLatin1String("/.netrc");
00299 status |= parse (openf(filename));
00300 }
00301
00302 if ( !status )
00303 return false;
00304 }
00305
00306 if ( !d->loginMap.contains( type ) )
00307 return false;
00308
00309 const LoginList& l = d->loginMap[type];
00310 if ( l.isEmpty() )
00311 return false;
00312
00313 for (LoginList::ConstIterator it = l.begin(); it != l.end(); ++it)
00314 {
00315 const AutoLogin &log = *it;
00316
00317 if ( (mode & defaultOnly) == defaultOnly &&
00318 log.machine == QLatin1String("default") &&
00319 (login.login.isEmpty() || login.login == log.login) )
00320 {
00321 login.type = log.type;
00322 login.machine = log.machine;
00323 login.login = log.login;
00324 login.password = log.password;
00325 login.macdef = log.macdef;
00326 }
00327
00328 if ( (mode & presetOnly) == presetOnly &&
00329 log.machine == QLatin1String("preset") &&
00330 (login.login.isEmpty() || login.login == log.login) )
00331 {
00332 login.type = log.type;
00333 login.machine = log.machine;
00334 login.login = log.login;
00335 login.password = log.password;
00336 login.macdef = log.macdef;
00337 }
00338
00339 if ( (mode & exactOnly) == exactOnly &&
00340 log.machine == url.host() &&
00341 (login.login.isEmpty() || login.login == log.login) )
00342 {
00343 login.type = log.type;
00344 login.machine = log.machine;
00345 login.login = log.login;
00346 login.password = log.password;
00347 login.macdef = log.macdef;
00348 break;
00349 }
00350 }
00351
00352 return true;
00353 }
00354
00355 void NetRC::reload()
00356 {
00357 d->isDirty = true;
00358 }
00359
00360 int NetRC::openf( const QString& f )
00361 {
00362 KDE_struct_stat sbuff;
00363 if ( KDE::stat(f, &sbuff) != 0 )
00364 return -1;
00365
00366
00367 if ( sbuff.st_mode != (S_IFREG|S_IRUSR|S_IWUSR) ||
00368 sbuff.st_uid != geteuid() )
00369 return -1;
00370
00371 return KDE::open( f, O_RDONLY );
00372 }
00373
00374 QString NetRC::extract( const char* buf, const char* key, int& pos )
00375 {
00376 int idx = pos;
00377 int m_len = strlen(key);
00378 int b_len = strlen(buf);
00379
00380 while( idx < b_len )
00381 {
00382 while( buf[idx] == ' ' || buf[idx] == '\t' )
00383 idx++;
00384
00385 if ( strncasecmp( buf+idx, key, m_len ) != 0 )
00386 idx++;
00387 else
00388 {
00389 idx += m_len;
00390 while( buf[idx] == ' ' || buf[idx] == '\t' )
00391 idx++;
00392
00393 int start = idx;
00394 while( buf[idx] != ' ' && buf[idx] != '\t' &&
00395 buf[idx] != '\n' && buf[idx] != '\r' )
00396 idx++;
00397
00398 if ( idx > start )
00399 {
00400 pos = idx;
00401 return QString::fromLatin1( buf+start, idx-start);
00402 }
00403 }
00404 }
00405
00406 return QString();
00407 }
00408
00409 bool NetRC::parse( int fd )
00410 {
00411 if (fd == -1)
00412 return false;
00413
00414 QString type;
00415 QString macro;
00416
00417 uint index = 0;
00418 bool isMacro = false;
00419 char* buf = new char[NETRC_READ_BUF_SIZE];
00420 FILE* fstream = KDE_fdopen( fd,"rb" );
00421
00422 while ( fgets (buf, NETRC_READ_BUF_SIZE, fstream) != 0L )
00423 {
00424 int pos = 0;
00425
00426 while ( buf[pos] == ' ' || buf[pos] == '\t' )
00427 pos++;
00428
00429 if ( buf[pos] == '#' || buf[pos] == '\n' ||
00430 buf[pos] == '\r' || buf[pos] == '\0' )
00431 {
00432 if ( buf[pos] != '#' && isMacro )
00433 isMacro = false;
00434
00435 continue;
00436 }
00437
00438 if ( isMacro )
00439 {
00440 int tail = strlen(buf);
00441 while( buf[tail-1] == '\n' || buf[tail-1] =='\r' )
00442 tail--;
00443
00444 QString mac = QString::fromLatin1(buf, tail).trimmed();
00445 if ( !mac.isEmpty() )
00446 d->loginMap[type][index].macdef[macro].append( mac );
00447
00448 continue;
00449 }
00450
00451 AutoLogin l;
00452 l.machine = extract( buf, "machine", pos );
00453 if ( l.machine.isEmpty() )
00454 {
00455 if (strncasecmp(buf+pos, "default", 7) == 0 )
00456 {
00457 pos += 7;
00458 l.machine = QLatin1String("default");
00459 }
00460 else if (strncasecmp(buf+pos, "preset", 6) == 0 )
00461 {
00462 pos += 6;
00463 l.machine = QLatin1String("preset");
00464 }
00465 }
00466
00467
00468 l.login = extract( buf, "login", pos );
00469
00470
00471 l.password = extract( buf, "password", pos );
00472 if ( l.password.isEmpty() )
00473 l.password = extract( buf, "account", pos );
00474
00475
00476 type = l.type = extract( buf, "type", pos );
00477 if ( l.type.isEmpty() && !l.machine.isEmpty() )
00478 type = l.type = QLatin1String("ftp");
00479
00480
00481 macro = extract( buf, "macdef", pos );
00482 isMacro = !macro.isEmpty();
00483
00484
00485 d->loginMap[l.type].append(l);
00486 index = d->loginMap[l.type].count()-1;
00487 }
00488
00489 delete [] buf;
00490 fclose (fstream);
00491 close (fd);
00492 return true;
00493 }