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