File indexing completed on 2025-11-09 11:08:56

0001 /*
0002     This file is part of the KDE File Manager
0003     SPDX-FileCopyrightText: 1998 Waldo Bastian <bastian@kde.org>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-only OR LGPL-3.0-only
0006 */
0007 
0008 // KDE File Manager -- HTTP Cookies
0009 
0010 #ifndef KCOOKIEJAR_H
0011 #define KCOOKIEJAR_H
0012 
0013 #include <QHash>
0014 #include <QSet>
0015 #include <QString>
0016 #include <QStringList>
0017 #include <qwindowdefs.h> //WId
0018 
0019 #include <QLoggingCategory>
0020 Q_DECLARE_LOGGING_CATEGORY(KIO_COOKIEJAR)
0021 
0022 class KConfig;
0023 class KCookieJar;
0024 class KHttpCookie;
0025 class KHttpCookieList;
0026 
0027 typedef KHttpCookie *KHttpCookiePtr;
0028 
0029 enum KCookieAdvice {
0030     KCookieDunno = 0,
0031     KCookieAccept,
0032     KCookieAcceptForSession,
0033     KCookieReject,
0034     KCookieAsk,
0035 };
0036 
0037 class KHttpCookie
0038 {
0039     friend class KCookieJar;
0040     friend class KHttpCookieList;
0041     friend QDebug operator<<(QDebug, const KHttpCookie &); // for cookieStr()
0042 
0043 protected:
0044     QString mHost;
0045     QString mDomain;
0046     QString mPath;
0047     QString mName;
0048     QString mValue;
0049     qint64 mExpireDate;
0050     int mProtocolVersion;
0051     bool mSecure;
0052     bool mCrossDomain;
0053     bool mHttpOnly;
0054     bool mExplicitPath;
0055     QList<WId> mWindowIds;
0056     QList<int> mPorts;
0057     KCookieAdvice mUserSelectedAdvice;
0058 
0059     QString cookieStr(bool useDOMFormat) const;
0060 
0061 public:
0062     explicit KHttpCookie(const QString &_host = QString(),
0063                          const QString &_domain = QString(),
0064                          const QString &_path = QString(),
0065                          const QString &_name = QString(),
0066                          const QString &_value = QString(),
0067                          qint64 _expireDate = 0,
0068                          int _protocolVersion = 0,
0069                          bool _secure = false,
0070                          bool _httpOnly = false,
0071                          bool _explicitPath = false);
0072 
0073     QString domain() const
0074     {
0075         return mDomain;
0076     }
0077     QString host() const
0078     {
0079         return mHost;
0080     }
0081     QString path() const
0082     {
0083         return mPath;
0084     }
0085     QString name() const
0086     {
0087         return mName;
0088     }
0089     QString value() const
0090     {
0091         return mValue;
0092     }
0093     QList<WId> &windowIds()
0094     {
0095         return mWindowIds;
0096     }
0097     const QList<WId> &windowIds() const
0098     {
0099         return mWindowIds;
0100     }
0101     const QList<int> &ports() const
0102     {
0103         return mPorts;
0104     }
0105     void fixDomain(const QString &domain)
0106     {
0107         mDomain = domain;
0108     }
0109     qint64 expireDate() const
0110     {
0111         return mExpireDate;
0112     }
0113     int protocolVersion() const
0114     {
0115         return mProtocolVersion;
0116     }
0117     bool isSecure() const
0118     {
0119         return mSecure;
0120     }
0121     /**
0122      *  If currentDate is -1, the default, then the current timestamp in UTC
0123      *  is used for comparison against this cookie's expiration date.
0124      */
0125     bool isExpired(qint64 currentDate = -1) const;
0126     bool isCrossDomain() const
0127     {
0128         return mCrossDomain;
0129     }
0130     bool isHttpOnly() const
0131     {
0132         return mHttpOnly;
0133     }
0134     bool hasExplicitPath() const
0135     {
0136         return mExplicitPath;
0137     }
0138     bool match(const QString &fqdn, const QStringList &domainList, const QString &path, int port = -1) const;
0139 
0140     KCookieAdvice getUserSelectedAdvice() const
0141     {
0142         return mUserSelectedAdvice;
0143     }
0144     void setUserSelectedAdvice(KCookieAdvice advice)
0145     {
0146         mUserSelectedAdvice = advice;
0147     }
0148 };
0149 
0150 QDebug operator<<(QDebug, const KHttpCookie &);
0151 
0152 class KHttpCookieList : public QList<KHttpCookie>
0153 {
0154 public:
0155     KHttpCookieList()
0156         : QList<KHttpCookie>()
0157         , advice(KCookieDunno)
0158     {
0159     }
0160     virtual ~KHttpCookieList()
0161     {
0162     }
0163 
0164     KCookieAdvice getAdvice() const
0165     {
0166         return advice;
0167     }
0168     void setAdvice(KCookieAdvice _advice)
0169     {
0170         advice = _advice;
0171     }
0172 
0173 private:
0174     KCookieAdvice advice;
0175 };
0176 
0177 QDebug operator<<(QDebug, const KHttpCookieList &);
0178 
0179 class KCookieJar
0180 {
0181 public:
0182     /**
0183      * Constructs a new cookie jar
0184      *
0185      * One jar should be enough for all cookies.
0186      */
0187     KCookieJar();
0188 
0189     /**
0190      * Destructs the cookie jar
0191      *
0192      * Poor little cookies, they will all be eaten by the cookie monster!
0193      */
0194     ~KCookieJar();
0195 
0196     KCookieJar(const KCookieJar &) = delete;
0197     KCookieJar &operator=(const KCookieJar &) = delete;
0198 
0199     /**
0200      * Returns whether the cookiejar has been changed
0201      */
0202     bool changed() const
0203     {
0204         return m_cookiesChanged || m_configChanged;
0205     }
0206 
0207     /**
0208      * Store all the cookies in a safe(?) place
0209      */
0210     bool saveCookies(const QString &_filename);
0211 
0212     /**
0213      * Load all the cookies from file and add them to the cookie jar.
0214      */
0215     bool loadCookies(const QString &_filename);
0216 
0217     /**
0218      * Save the cookie configuration
0219      */
0220     void saveConfig(KConfig *_config);
0221 
0222     /**
0223      * Load the cookie configuration
0224      */
0225     void loadConfig(KConfig *_config, bool reparse = false);
0226 
0227     /**
0228      * Looks for cookies in the cookie jar which are appropriate for _url.
0229      * Returned is a string containing all appropriate cookies in a format
0230      * which can be added to a HTTP-header without any additional processing.
0231      *
0232      * If @p useDOMFormat is true, the string is formatted in a format
0233      * in compliance with the DOM standard.
0234      * @p pendingCookies contains a list of cookies that have not been
0235      * approved yet by the user but that will be included in the result
0236      * none the less.
0237      */
0238     QString findCookies(const QString &_url, bool useDOMFormat, WId windowId, KHttpCookieList *pendingCookies = nullptr);
0239 
0240     /**
0241      * This function parses cookie_headers and returns a linked list of
0242      * valid KHttpCookie objects for all cookies found in cookie_headers.
0243      * If no cookies could be found 0 is returned.
0244      *
0245      * cookie_headers should be a concatenation of all lines of a HTTP-header
0246      * which start with "Set-Cookie". The lines should be separated by '\n's.
0247      */
0248     KHttpCookieList makeCookies(const QString &_url, const QByteArray &cookie_headers, WId windowId);
0249 
0250     /**
0251      * This function parses cookie_headers and returns a linked list of
0252      * valid KHttpCookie objects for all cookies found in cookie_headers.
0253      * If no cookies could be found 0 is returned.
0254      *
0255      * cookie_domstr should be a concatenation of "name=value" pairs, separated
0256      * by a semicolon ';'.
0257      */
0258     KHttpCookieList makeDOMCookies(const QString &_url, const QByteArray &cookie_domstr, WId windowId);
0259 
0260     /**
0261      * This function hands a KHttpCookie object over to the cookie jar.
0262      */
0263     void addCookie(KHttpCookie &cookie);
0264 
0265     /**
0266      * This function tells whether a single KHttpCookie object should
0267      * be considered persistent. Persistent cookies do not get deleted
0268      * at the end of the session and are saved on disk.
0269      */
0270     bool cookieIsPersistent(const KHttpCookie &cookie) const;
0271 
0272     /**
0273      * This function advises whether a single KHttpCookie object should
0274      * be added to the cookie jar.
0275      *
0276      * Possible return values are:
0277      *     - KCookieAccept, the cookie should be added
0278      *     - KCookieAcceptForSession, the cookie should be added as session cookie
0279      *     - KCookieReject, the cookie should not be added
0280      *     - KCookieAsk, the user should decide what to do
0281      *
0282      * Before sending cookies back to a server this function is consulted,
0283      * so that cookies having advice KCookieReject are not sent back.
0284      */
0285     KCookieAdvice cookieAdvice(const KHttpCookie &cookie) const;
0286 
0287     /**
0288      * This function gets the advice for all cookies originating from
0289      * _domain.
0290      *
0291      *     - KCookieDunno, no specific advice for _domain
0292      *     - KCookieAccept, accept all cookies for _domain
0293      *     - KCookieAcceptForSession, accept all cookies for _domain as session cookies
0294      *     - KCookieReject, reject all cookies for _domain
0295      *     - KCookieAsk, the user decides what to do with cookies for _domain
0296      */
0297     KCookieAdvice getDomainAdvice(const QString &_domain) const;
0298 
0299     /**
0300      * This function sets the advice for all cookies originating from
0301      * _domain.
0302      *
0303      * _advice can have the following values:
0304      *     - KCookieDunno, no specific advice for _domain
0305      *     - KCookieAccept, accept all cookies for _domain
0306      *     - KCookieAcceptForSession, accept all cookies for _domain as session cookies
0307      *     - KCookieReject, reject all cookies for _domain
0308      *     - KCookieAsk, the user decides what to do with cookies for _domain
0309      */
0310     void setDomainAdvice(const QString &domain, KCookieAdvice advice);
0311 
0312     /**
0313      * This function sets the advice for all cookies originating from
0314      * the same domain as _cookie
0315      *
0316      * _advice can have the following values:
0317      *     - KCookieDunno, no specific advice for _domain
0318      *     - KCookieAccept, accept all cookies for _domain
0319      *     - KCookieAcceptForSession, accept all cookies for _domain as session cookies
0320      *     - KCookieReject, reject all cookies for _domain
0321      *     - KCookieAsk, the user decides what to do with cookies for _domain
0322      */
0323     void setDomainAdvice(const KHttpCookie &_cookie, KCookieAdvice _advice);
0324 
0325     /**
0326      * Get the global advice for cookies
0327      *
0328      * The returned advice can have the following values:
0329      *     - KCookieAccept, accept cookies
0330      *     - KCookieAcceptForSession, accept cookies as session cookies
0331      *     - KCookieReject, reject cookies
0332      *     - KCookieAsk, the user decides what to do with cookies
0333      *
0334      * The global advice is used if the domain has no advice set.
0335      */
0336     KCookieAdvice getGlobalAdvice() const
0337     {
0338         return m_globalAdvice;
0339     }
0340 
0341     /**
0342      * This function sets the global advice for cookies
0343      *
0344      * _advice can have the following values:
0345      *     - KCookieAccept, accept cookies
0346      *     - KCookieAcceptForSession, accept cookies as session cookies
0347      *     - KCookieReject, reject cookies
0348      *     - KCookieAsk, the user decides what to do with cookies
0349      *
0350      * The global advice is used if the domain has no advice set.
0351      */
0352     void setGlobalAdvice(KCookieAdvice _advice);
0353 
0354     /**
0355      * Get a list of all domains known to the cookie jar.
0356      * A domain is known to the cookie jar if:
0357      *     - It has a cookie originating from the domain
0358      *     - It has a specific advice set for the domain
0359      */
0360     const QStringList &getDomainList();
0361 
0362     /**
0363      * Get a list of all cookies in the cookie jar originating from _domain.
0364      */
0365     KHttpCookieList *getCookieList(const QString &_domain, const QString &_fqdn);
0366 
0367     /**
0368      * Remove & delete a cookie from the jar.
0369      *
0370      * cookieIterator should be one of the entries in a KHttpCookieList.
0371      * Update your KHttpCookieList by calling getCookieList after
0372      * calling this function.
0373      */
0374     void eatCookie(const KHttpCookieList::iterator &cookieIterator);
0375 
0376     /**
0377      * Remove & delete all cookies for @p domain.
0378      */
0379     void eatCookiesForDomain(const QString &domain);
0380 
0381     /**
0382      * Remove & delete all cookies
0383      */
0384     void eatAllCookies();
0385 
0386     /**
0387      * Removes all end of session cookies set by the
0388      * session @p windId.
0389      */
0390     void eatSessionCookies(long windowId);
0391 
0392     /**
0393      * Removes all end of session cookies set by the
0394      * session @p windId.
0395      */
0396     void eatSessionCookies(const QString &fqdn, WId windowId, bool isFQDN = true);
0397 
0398     /**
0399      * Parses _url and returns the FQDN (_fqdn) and path (_path).
0400      */
0401     static bool parseUrl(const QString &_url, QString &_fqdn, QString &_path, int *port = nullptr);
0402 
0403     /**
0404      * Returns a list of domains in @p _domainList relevant for this host.
0405      * The list is sorted with the FQDN listed first and the top-most
0406      * domain listed last
0407      */
0408     void extractDomains(const QString &_fqdn, QStringList &_domainList) const;
0409 
0410     static QString adviceToStr(KCookieAdvice _advice);
0411     static KCookieAdvice strToAdvice(const QString &_str);
0412 
0413     enum KCookieDefaultPolicy {
0414         ApplyToShownCookiesOnly = 0,
0415         ApplyToCookiesFromDomain = 1,
0416         ApplyToAllCookies = 2,
0417     };
0418     /** Returns the user's choice in the cookie window */
0419     KCookieDefaultPolicy preferredDefaultPolicy() const
0420     {
0421         return m_preferredPolicy;
0422     }
0423 
0424     /** Returns the */
0425     bool showCookieDetails() const
0426     {
0427         return m_showCookieDetails;
0428     }
0429 
0430     /**
0431      * Sets the user's default preference cookie policy.
0432      */
0433     void setPreferredDefaultPolicy(KCookieDefaultPolicy value)
0434     {
0435         m_preferredPolicy = value;
0436     }
0437 
0438     /**
0439      * Sets the user's preference of level of detail displayed
0440      * by the cookie dialog.
0441      */
0442     void setShowCookieDetails(bool value)
0443     {
0444         m_showCookieDetails = value;
0445     }
0446 
0447 protected:
0448     void stripDomain(const QString &_fqdn, QString &_domain) const;
0449     QString stripDomain(const KHttpCookie &cookie) const;
0450 
0451 protected:
0452     QStringList m_domainList;
0453     KCookieAdvice m_globalAdvice;
0454     QHash<QString, KHttpCookieList *> m_cookieDomains;
0455     QSet<QString> m_twoLevelTLD;
0456     QSet<QString> m_gTLDs;
0457 
0458     bool m_configChanged;
0459     bool m_cookiesChanged;
0460     bool m_showCookieDetails;
0461     bool m_rejectCrossDomainCookies;
0462     bool m_autoAcceptSessionCookies;
0463 
0464     KCookieDefaultPolicy m_preferredPolicy;
0465 };
0466 #endif