KIO
authinfo.cpp
Go to the documentation of this file.
00001 /* 00002 * This file is part of the KDE libraries 00003 * Copyright (C) 2000-2001 Dawit Alemayehu <adawit@kde.org> 00004 * 00005 * This library is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU Library General Public 00007 * License as published by the Free Software Foundation; either 00008 * version 2 of the License, or (at your option) any later version. 00009 * 00010 * This library is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 * Library General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU Library General Public License 00016 * along with this library; see the file COPYING.LIB. If not, write to 00017 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00018 * Boston, MA 02110-1301, USA. 00019 */ 00020 00021 #include "authinfo.h" 00022 00023 #include <config.h> 00024 00025 #include <sys/stat.h> // don't move it down the include order, it breaks compilation on MSVC 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; // reserved for future use 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 // kDebug() << "AutoLogin lookup for: " << url.host(); 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 // Security check!! 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 // kDebug() << "Machine: " << l.machine; 00467 00468 l.login = extract( buf, "login", pos ); 00469 // kDebug() << "Login: " << l.login; 00470 00471 l.password = extract( buf, "password", pos ); 00472 if ( l.password.isEmpty() ) 00473 l.password = extract( buf, "account", pos ); 00474 // kDebug() << "Password: " << l.password; 00475 00476 type = l.type = extract( buf, "type", pos ); 00477 if ( l.type.isEmpty() && !l.machine.isEmpty() ) 00478 type = l.type = QLatin1String("ftp"); 00479 // kDebug() << "Type: " << l.type; 00480 00481 macro = extract( buf, "macdef", pos ); 00482 isMacro = !macro.isEmpty(); 00483 // kDebug() << "Macro: " << macro; 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 }
KDE 4.6 API Reference