KIO

authinfo.cpp
1 /*
2  This file is part of the KDE libraries
3  SPDX-FileCopyrightText: 2000-2001 Dawit Alemayehu <[email protected]>
4 
5  SPDX-License-Identifier: LGPL-2.0-or-later
6 */
7 
8 #include "authinfo.h"
9 
10 #include <QDir>
11 #include <QFile>
12 #include <QTextStream>
13 #include <QDataStream>
14 #include <QDBusArgument>
15 #include <QDBusMetaType>
16 
17 #include <QStandardPaths>
18 
19 using namespace KIO;
20 
22 
23 class ExtraField
24 {
25 public:
26  ExtraField()
27  : flags(AuthInfo::ExtraFieldNoFlags)
28  {
29  }
30 
31  ExtraField(const ExtraField &other)
32  : customTitle(other.customTitle),
33  flags(other.flags),
34  value(other.value)
35  {
36  }
37 
38  ExtraField &operator=(const ExtraField &other)
39  {
40  customTitle = other.customTitle;
41  flags = other.flags;
42  value = other.value;
43  return *this;
44  }
45 
46  QString customTitle; // reserved for future use
48  QVariant value;
49 };
50 Q_DECLARE_METATYPE(ExtraField)
51 
52 static QDataStream &operator<< (QDataStream &s, const ExtraField &extraField)
53 {
54  s << extraField.customTitle;
55  s << static_cast<int>(extraField.flags);
56  s << extraField.value;
57  return s;
58 }
59 
60 static QDataStream &operator>> (QDataStream &s, ExtraField &extraField)
61 {
62  s >> extraField.customTitle;
63  int i;
64  s >> i;
65  extraField.flags = AuthInfo::FieldFlags(i);
66  s >> extraField.value;
67  return s;
68 }
69 
70 static QDBusArgument &operator<<(QDBusArgument &argument, const ExtraField &extraField)
71 {
72  argument.beginStructure();
73  argument << extraField.customTitle << static_cast<int>(extraField.flags)
74  << QDBusVariant(extraField.value);
75  argument.endStructure();
76  return argument;
77 }
78 
79 static const QDBusArgument &operator>>(const QDBusArgument &argument, ExtraField &extraField)
80 {
81  QDBusVariant value;
82  int flag;
83 
84  argument.beginStructure();
85  argument >> extraField.customTitle >> flag >> value;
86  argument.endStructure();
87 
88  extraField.value = value.variant();
89  extraField.flags = KIO::AuthInfo::FieldFlags(flag);
90  return argument;
91 }
92 
93 class KIO::AuthInfoPrivate
94 {
95 public:
96  QMap<QString, ExtraField> extraFields;
97 };
98 
100 
101 AuthInfo::AuthInfo() : d(new AuthInfoPrivate())
102 {
103  modified = false;
104  readOnly = false;
105  verifyPath = false;
106  keepPassword = false;
108 }
109 
110 AuthInfo::AuthInfo(const AuthInfo &info) : d(new AuthInfoPrivate())
111 {
112  (*this) = info;
114 }
115 
117 {
118  delete d;
119 }
120 
122 {
123  url = info.url;
124  username = info.username;
125  password = info.password;
126  prompt = info.prompt;
127  caption = info.caption;
128  comment = info.comment;
129  commentLabel = info.commentLabel;
130  realmValue = info.realmValue;
131  digestInfo = info.digestInfo;
132  verifyPath = info.verifyPath;
133  readOnly = info.readOnly;
134  keepPassword = info.keepPassword;
135  modified = info.modified;
136  d->extraFields = info.d->extraFields;
137  return *this;
138 }
139 
141 {
142  return modified;
143 }
144 
145 void AuthInfo::setModified(bool flag)
146 {
147  modified = flag;
148 }
149 
151 
152 void AuthInfo::setExtraField(const QString &fieldName, const QVariant &value)
153 {
154  d->extraFields[fieldName].value = value;
155 }
156 
157 void AuthInfo::setExtraFieldFlags(const QString &fieldName, const FieldFlags flags)
158 {
159  d->extraFields[fieldName].flags = flags;
160 }
161 
162 QVariant AuthInfo::getExtraField(const QString &fieldName) const
163 {
164  const auto it = d->extraFields.constFind(fieldName);
165  if (it == d->extraFields.constEnd()) {
166  return QVariant();
167  }
168  return it->value;
169 }
170 
172 {
173  const auto it = d->extraFields.constFind(fieldName);
174  if (it == d->extraFields.constEnd()) {
175  return AuthInfo::ExtraFieldNoFlags;
176  }
177  return it->flags;
178 }
179 
181 {
182  qRegisterMetaType<ExtraField>();
183  qRegisterMetaType<KIO::AuthInfo>();
184  qDBusRegisterMetaType<ExtraField>();
185  qDBusRegisterMetaType<KIO::AuthInfo>();
186 }
187 
189 
190 QDataStream &KIO::operator<< (QDataStream &s, const AuthInfo &a)
191 {
192  s << quint8(1)
193  << a.url << a.username << a.password << a.prompt << a.caption
194  << a.comment << a.commentLabel << a.realmValue << a.digestInfo
195  << a.verifyPath << a.readOnly << a.keepPassword << a.modified
196  << a.d->extraFields;
197  return s;
198 }
199 
200 QDataStream &KIO::operator>> (QDataStream &s, AuthInfo &a)
201 {
202  quint8 version;
203  s >> version
204  >> a.url >> a.username >> a.password >> a.prompt >> a.caption
205  >> a.comment >> a.commentLabel >> a.realmValue >> a.digestInfo
206  >> a.verifyPath >> a.readOnly >> a.keepPassword >> a.modified
207  >> a.d->extraFields;
208  return s;
209 }
210 
211 QDBusArgument &KIO::operator<<(QDBusArgument &argument, const AuthInfo &a)
212 {
213  argument.beginStructure();
214  argument << quint8(1)
215  << a.url.toString() << a.username << a.password << a.prompt << a.caption
216  << a.comment << a.commentLabel << a.realmValue << a.digestInfo
217  << a.verifyPath << a.readOnly << a.keepPassword << a.modified
218  << a.d->extraFields;
219  argument.endStructure();
220  return argument;
221 }
222 
223 const QDBusArgument &KIO::operator>>(const QDBusArgument &argument, AuthInfo &a)
224 {
225  QString url;
226  quint8 version;
227 
228  argument.beginStructure();
229  argument >> version
230  >> url >> a.username >> a.password >> a.prompt >> a.caption
231  >> a.comment >> a.commentLabel >> a.realmValue >> a.digestInfo
232  >> a.verifyPath >> a.readOnly >> a.keepPassword >> a.modified
233  >> a.d->extraFields;
234  argument.endStructure();
235 
236  a.url = QUrl(url);
237  return argument;
238 }
239 
242 
243 class Q_DECL_HIDDEN NetRC::NetRCPrivate
244 {
245 public:
246  NetRCPrivate()
247  : isDirty(false),
248  index(-1)
249  {}
250  QString extract(const QString &buf, const QString &key);
251  void getMachinePart(const QString &line);
252  void getMacdefPart(const QString &line);
253 
254  bool isDirty;
255  LoginMap loginMap;
256  QTextStream fstream;
257  QString type;
258  int index;
259 };
260 
261 NetRC *NetRC::instance = nullptr;
262 
263 NetRC::NetRC()
264  : d(new NetRCPrivate)
265 {
266 }
267 
268 NetRC::~NetRC()
269 {
270  delete instance;
271  instance = nullptr;
272  delete d;
273 }
274 
275 NetRC *NetRC::self()
276 {
277  if (!instance) {
278  instance = new NetRC;
279  }
280  return instance;
281 }
282 
283 bool NetRC::lookup(const QUrl &url, AutoLogin &login, bool userealnetrc,
284  const QString &_type, LookUpMode mode)
285 {
286  //qDebug() << "AutoLogin lookup for: " << url.host();
287  if (!url.isValid()) {
288  return false;
289  }
290 
291  QString type = _type;
292  if (type.isEmpty()) {
293  type = url.scheme();
294  }
295 
296  if (d->loginMap.isEmpty() || d->isDirty) {
297  d->loginMap.clear();
298 
300  bool kionetrcStatus = parse(filename);
301  bool netrcStatus = false;
302  if (userealnetrc) {
303  filename = QDir::homePath() + QLatin1String("/.netrc");
304  netrcStatus = parse(filename);
305  }
306 
307  if (!(kionetrcStatus || netrcStatus)) {
308  return false;
309  }
310  }
311 
312  const auto loginIt = d->loginMap.constFind(type);
313  if (loginIt == d->loginMap.constEnd()) {
314  return false;
315  }
316 
317  const LoginList &l = *loginIt;
318  if (l.isEmpty()) {
319  return false;
320  }
321 
322  for (const AutoLogin &log : l) {
323  if ((mode & defaultOnly) == defaultOnly &&
324  log.machine == QLatin1String("default") &&
325  (login.login.isEmpty() || login.login == log.login)) {
326  login.type = log.type;
327  login.machine = log.machine;
328  login.login = log.login;
329  login.password = log.password;
330  login.macdef = log.macdef;
331  }
332 
333  if ((mode & presetOnly) == presetOnly &&
334  log.machine == QLatin1String("preset") &&
335  (login.login.isEmpty() || login.login == log.login)) {
336  login.type = log.type;
337  login.machine = log.machine;
338  login.login = log.login;
339  login.password = log.password;
340  login.macdef = log.macdef;
341  }
342 
343  if ((mode & exactOnly) == exactOnly &&
344  log.machine == url.host() &&
345  (login.login.isEmpty() || login.login == log.login)) {
346  login.type = log.type;
347  login.machine = log.machine;
348  login.login = log.login;
349  login.password = log.password;
350  login.macdef = log.macdef;
351  break;
352  }
353  }
354 
355  return true;
356 }
357 
359 {
360  d->isDirty = true;
361 }
362 
363 bool NetRC::parse(const QString &fileName)
364 {
365  QFile file(fileName);
368  return false;
369 
370  }
371  if (!file.open(QIODevice::ReadOnly)) {
372  return false;
373  }
374 
375  d->fstream.setDevice(&file);
376 
377  QString line;
378 
379  while (!d->fstream.atEnd()) {
380  line = d->fstream.readLine().simplified();
381 
382  // If line is a comment or is empty, read next line
383  if ((line.startsWith(QLatin1Char('#')) || line.isEmpty())) {
384  continue;
385  }
386 
387  // If line refers to a machine, maybe it is spread in more lines.
388  // getMachinePart() will take care of getting all the info and putting it into loginMap.
389  if ((line.startsWith(QLatin1String("machine"))
390  || line.startsWith(QLatin1String("default"))
391  || line.startsWith(QLatin1String("preset")))) {
392  d->getMachinePart(line);
393  continue;
394  }
395 
396  // If line refers to a macdef, it will be more than one line.
397  // getMacdefPart() will take care of getting all the lines of the macro
398  // and putting them into loginMap
399  if (line.startsWith(QLatin1String("macdef"))) {
400  d->getMacdefPart(line);
401  continue;
402  }
403  }
404  return true;
405 }
406 
407 QString NetRC::NetRCPrivate::extract(const QString &buf, const QString &key)
408 {
409 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
410  QStringList stringList = buf.split(QLatin1Char(' '), QString::SkipEmptyParts);
411 #else
412  QStringList stringList = buf.split(QLatin1Char(' '), Qt::SkipEmptyParts);
413 #endif
414  int i = stringList.indexOf(key);
415  if ((i != -1) && (i + 1 < stringList.size())) {
416  return stringList.at(i + 1);
417  } else {
418  return QString();
419  }
420 }
421 
422 void NetRC::NetRCPrivate::getMachinePart(const QString &line)
423 {
424  QString buf = line;
425  while (!(buf.contains(QLatin1String("login"))
426  && (buf.contains(QLatin1String("password")) || buf.contains(QLatin1String("account")) || buf.contains(QLatin1String("type"))))) {
427  buf += QLatin1Char(' ') + fstream.readLine().simplified();
428  }
429 
430  // Once we've got all the info, process it.
431  AutoLogin l;
432  l.machine = extract(buf, QStringLiteral("machine"));
433  if (l.machine.isEmpty()) {
434  if (buf.contains(QLatin1String("default"))) {
435  l.machine = QStringLiteral("default");
436  } else if (buf.contains(QLatin1String("preset"))) {
437  l.machine = QStringLiteral("preset");
438  }
439  }
440 
441  l.login = extract(buf, QStringLiteral("login"));
442  l.password = extract(buf, QStringLiteral("password"));
443  if (l.password.isEmpty()) {
444  l.password = extract(buf, QStringLiteral("account"));
445  }
446 
447  type = l.type = extract(buf, QStringLiteral("type"));
448  if (l.type.isEmpty() && !l.machine.isEmpty()) {
449  type = l.type = QStringLiteral("ftp");
450  }
451 
452  loginMap[l.type].append(l);
453  index = loginMap[l.type].count() - 1;
454 }
455 
456 void NetRC::NetRCPrivate::getMacdefPart(const QString &line)
457 {
458  QString buf = line;
459  QString macro = extract(buf, QStringLiteral("macdef"));
460  QString newLine;
461  while (!fstream.atEnd()) {
462  newLine = fstream.readLine().simplified();
463  if (!newLine.isEmpty()) {
464  buf += QLatin1Char('\n') + newLine;
465  } else {
466  break;
467  }
468  }
469  loginMap[type][index].macdef[macro].append(buf);
470 }
QString comment
Additional comment to be displayed when prompting the user for authentication information.
Definition: authinfo.h:157
QString & append(QChar ch)
QString writableLocation(QStandardPaths::StandardLocation type)
FieldFlags
Flags for extra fields.
Definition: authinfo.h:229
AuthInfo & operator=(const AuthInfo &info)
Custom assignment operator.
Definition: authinfo.cpp:121
static void registerMetaTypes()
Register the meta-types for AuthInfo.
Definition: authinfo.cpp:180
bool keepPassword
Flag to indicate the persistence of the given password.
Definition: authinfo.h:223
A namespace for KIO globals.
Definition: authinfo.h:21
void setExtraField(const QString &fieldName, const QVariant &value)
Set Extra Field Value.
Definition: authinfo.cpp:152
static NetRC * self()
A reference to the instance of the class.
Definition: authinfo.cpp:275
QString digestInfo
Field to store any extra authentication information for protocols that need it.
Definition: authinfo.h:190
void setExtraFieldFlags(const QString &fieldName, const FieldFlags flags)
Set Extra Field Flags.
Definition: authinfo.cpp:157
QDataStream & operator>>(QDataStream &in, KDateTime::Spec &spec)
void beginStructure()
const T & at(int i) const const
QString host(QUrl::ComponentFormattingOptions options) const const
QString simplified() const const
This class is intended to make it easier to prompt for, cache and retrieve authorization information...
Definition: authinfo.h:48
QVariant getExtraField(const QString &fieldName) const
Get Extra Field Value Check QVariant::isValid() to find out if the field exists.
Definition: authinfo.cpp:162
bool readOnly
Flag which if set forces the username field to be read-only.
Definition: authinfo.h:210
QString homePath()
QString toString(QUrl::FormattingOptions options) const const
int size() const const
void clear()
QUrl url
The URL for which authentication is to be stored.
Definition: authinfo.h:101
QString realmValue
A unique identifier that allows caching of multiple passwords for different resources in the same ser...
Definition: authinfo.h:180
bool isModified() const
Use this method to check if the object was modified.
Definition: authinfo.cpp:140
bool verifyPath
Flag that, if set, indicates whether a path match should be performed when requesting for cached auth...
Definition: authinfo.h:203
AuthInfo()
Default constructor.
Definition: authinfo.cpp:101
bool isEmpty() const const
bool isEmpty() const const
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const const
QStringList split(const QString &sep, QString::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
virtual bool open(QIODevice::OpenMode mode) override
int indexOf(QStringView str, int from) const const
QString scheme() const const
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
SkipEmptyParts
QDataStream & operator<<(QDataStream &out, const KDateTime::Spec &spec)
bool isValid() const const
void setModified(bool flag)
Use this method to indicate that this object has been modified.
Definition: authinfo.cpp:145
QString password
This is required for caching.
Definition: authinfo.h:111
QString username
This is required for caching.
Definition: authinfo.h:106
void reload()
Reloads the auto login information.
Definition: authinfo.cpp:358
~AuthInfo()
Destructor.
Definition: authinfo.cpp:116
virtual QFileDevice::Permissions permissions() const const override
bool lookup(const QUrl &url, AutoLogin &login, bool userealnetrc=false, const QString &type=QString(), LookUpMode mode=LookUpMode(exactOnly)|defaultOnly)
Looks up the login information for the given url.
Definition: authinfo.cpp:283
QString caption
The text to displayed in the title bar of the password prompting dialog.
Definition: authinfo.h:133
QString commentLabel
Descriptive label to be displayed in front of the comment when prompting the user for password...
Definition: authinfo.h:166
AuthInfo::FieldFlags getExtraFieldFlags(const QString &fieldName) const
Get Extra Field Flags.
Definition: authinfo.cpp:171
QString prompt
Information to be displayed when prompting the user for authentication information.
Definition: authinfo.h:122
void endStructure()
Contains auto login information.
Definition: authinfo.h:325
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Wed Sep 23 2020 23:01:38 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.