File indexing completed on 2024-05-19 04:55:59

0001 /**
0002  * \file httpclient.h
0003  * Client to connect to HTTP server.
0004  *
0005  * \b Project: Kid3
0006  * \author Urs Fleisch
0007  * \date 30 Dec 2008
0008  *
0009  * Copyright (C) 2008-2024  Urs Fleisch
0010  *
0011  * This file is part of Kid3.
0012  *
0013  * Kid3 is free software; you can redistribute it and/or modify
0014  * it under the terms of the GNU General Public License as published by
0015  * the Free Software Foundation; either version 2 of the License, or
0016  * (at your option) any later version.
0017  *
0018  * Kid3 is distributed in the hope that it will be useful,
0019  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0020  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0021  * GNU General Public License for more details.
0022  *
0023  * You should have received a copy of the GNU General Public License
0024  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
0025  */
0026 
0027 #pragma once
0028 
0029 #include <QObject>
0030 //#include <QString>
0031 #include <QNetworkReply>
0032 #include <QPointer>
0033 #include <QMap>
0034 #include "kid3api.h"
0035 
0036 class QByteArray;
0037 class QNetworkAccessManager;
0038 class QDateTime;
0039 class QTimer;
0040 
0041 /**
0042  * Client to connect to HTTP server.
0043  */
0044 class KID3_CORE_EXPORT HttpClient : public QObject {
0045   Q_OBJECT
0046 public:
0047   /** Name-value map for raw HTTP headers. */
0048   typedef QMap<QByteArray, QByteArray> RawHeaderMap;
0049 
0050   /**
0051    * Constructor.
0052    *
0053    * @param netMgr  network access manager
0054    */
0055   explicit HttpClient(QNetworkAccessManager* netMgr);
0056 
0057   /**
0058    * Destructor.
0059    */
0060   ~HttpClient() override;
0061 
0062   /**
0063    * Send a HTTP GET request.
0064    *
0065    * @param url URL
0066    * @param headers optional raw headers to send
0067    */
0068   void sendRequest(const QUrl& url,
0069                    const RawHeaderMap& headers = RawHeaderMap());
0070 
0071   /**
0072    * Send a HTTP GET request.
0073    *
0074    * @param server host name
0075    * @param path   path of the URL
0076    * @param scheme scheme, default is "http"
0077    * @param headers optional raw headers to send
0078    */
0079   void sendRequest(const QString& server, const QString& path,
0080                    const QString& scheme = QLatin1String("http"),
0081                    const RawHeaderMap& headers = RawHeaderMap());
0082 
0083   /**
0084    * Abort request.
0085    */
0086   void abort();
0087 
0088   /**
0089    * Get content length.
0090    * @return size of body in bytes, 0 if unknown.
0091    */
0092   unsigned long getContentLength() const { return m_rcvBodyLen; }
0093 
0094   /**
0095    * Get content type.
0096    * @return MIME type, empty if unknown.
0097    */
0098   QString getContentType() const { return m_rcvBodyType; }
0099 
0100   /**
0101    * Extract name and port from string.
0102    *
0103    * @param namePort input string with "name:port"
0104    * @param name     output string with "name"
0105    * @param port     output integer with port
0106    */
0107   static void splitNamePort(const QString& namePort,
0108                             QString& name, int& port);
0109 
0110 signals:
0111   /**
0112    * Emitted to report progress.
0113    * Parameter: state text, bytes received, total bytes.
0114    */
0115   void progress(const QString&, int, int);
0116 
0117   /**
0118    * Emitted when response received.
0119    * Parameter: bytes containing result of request
0120    */
0121   void bytesReceived(const QByteArray&);
0122 
0123 private slots:
0124   /**
0125    * Called when the request is finished.
0126    */
0127   void networkReplyFinished();
0128 
0129   /**
0130    * Called to report connection progress.
0131    *
0132    * @param received bytes received
0133    * @param total total bytes
0134    */
0135   void networkReplyProgress(qint64 received, qint64 total);
0136 
0137   /**
0138    * Called when an error occurred.
0139    *
0140    * @param code error code
0141    */
0142   void networkReplyError(QNetworkReply::NetworkError code);
0143 
0144   /**
0145    * Called to start delayed sendRequest().
0146    */
0147   void delayedSendRequest();
0148 
0149 private:
0150   /**
0151    * Emit a progress signal with step/total steps.
0152    *
0153    * @param text       state text
0154    * @param step       current step
0155    * @param totalSteps total number of steps
0156    */
0157   void emitProgress(const QString& text, int step, int totalSteps);
0158 
0159   /**
0160    * Emit a progress signal with bytes received/total bytes.
0161    *
0162    * @param text state text
0163    */
0164   void emitProgress(const QString& text);
0165 
0166   /**
0167    * Read the available bytes.
0168    */
0169   void readBytesAvailable();
0170 
0171   /**
0172    * Get string with proxy or destination and port.
0173    * If a proxy is set, the proxy is returned, else the real destination.
0174    *
0175    * @param dst real destination
0176    *
0177    * @return "destinationname:port".
0178    */
0179   static QString getProxyOrDest(const QString& dst);
0180 
0181   /** network access manager */
0182   QNetworkAccessManager* m_netMgr;
0183   /** network reply if available, else 0 */
0184   QPointer<QNetworkReply> m_reply;
0185   /** content length of entity-body, 0 if not available */
0186   unsigned long m_rcvBodyLen;
0187   /** content type */
0188   QString m_rcvBodyType;
0189   /** Timer used to delay requests */
0190   QTimer* m_requestTimer;
0191   /** Context for delayedSendRequest() */
0192   struct {
0193     QUrl url;
0194     RawHeaderMap headers;
0195   } m_delayedSendRequestContext;
0196 
0197   friend struct MinimumRequestIntervalInitializer;
0198 
0199   /** Time when last request was sent to server */
0200   static QMap<QString, QDateTime> s_lastRequestTime;
0201   /** Minimum interval between two requests to server in ms */
0202   static QMap<QString, int> s_minimumRequestInterval;
0203 };