summaryrefslogtreecommitdiffstats
path: root/kioslave/http/http.h
blob: ea2e68a8a03a30f6c0b799c9b175dba1c46b1903 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
/*
   Copyright (C) 2000,2001 Dawit Alemayehu <adawit@kde.org>
   Copyright (C) 2000,2001 Waldo Bastian <bastian@kde.org>
   Copyright (C) 2000,2001 George Staikos <staikos@kde.org>
   Copyright (C) 2001,2002 Hamish Rodda <rodda@kde.org>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301, USA.
*/

#ifndef HTTP_H_
#define HTTP_H_


#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <stdio.h>
#include <time.h>

#include <qptrlist.h>
#include <qstrlist.h>
#include <qstringlist.h>

#include <kurl.h>
#include "kio/tcpslavebase.h"
#include "kio/http.h"

class DCOPClient;
class QDomElement;
class QDomNodeList;

namespace KIO {
    class AuthInfo;
}

class HTTPProtocol : public QObject, public KIO::TCPSlaveBase
{
  Q_OBJECT
public:
  HTTPProtocol( const QCString &protocol, const QCString &pool,
                const QCString &app );
  virtual ~HTTPProtocol();

  /** HTTP version **/
  enum HTTP_REV    {HTTP_None, HTTP_Unknown, HTTP_10, HTTP_11, SHOUTCAST};

  /** Authorization method used **/
  enum HTTP_AUTH   {AUTH_None, AUTH_Basic, AUTH_NTLM, AUTH_Digest, AUTH_Negotiate};

  /** HTTP / DAV method **/
  // Removed to interfaces/kio/http.h
  //enum HTTP_METHOD {HTTP_GET, HTTP_PUT, HTTP_POST, HTTP_HEAD, HTTP_DELETE,
  //                  HTTP_OPTIONS, DAV_PROPFIND, DAV_PROPPATCH, DAV_MKCOL,
  //                  DAV_COPY, DAV_MOVE, DAV_LOCK, DAV_UNLOCK, DAV_SEARCH };

  /** State of the current Connection **/
  struct HTTPState
  {
    HTTPState ()
    {
      port = 0;
      doProxy = false;
    }

    QString hostname;
    QString encoded_hostname;
    short unsigned int port;
    QString user;
    QString passwd;
    bool  doProxy;
  };

  /** DAV-specific request elements for the current connection **/
  struct DAVRequest
  {
    DAVRequest ()
    {
      overwrite = false;
      depth = 0;
    }

    QString desturl;
    bool overwrite;
    int depth;
  };

  /** The request for the current connection **/
  struct HTTPRequest
  {
    HTTPRequest ()
    {
      port = 0;
      method = KIO::HTTP_UNKNOWN;
      offset = 0;
      doProxy = false;
      allowCompressedPage = false;
      disablePassDlg = false;
      bNoAuth = false;
      bUseCache = false;
      bCachedRead = false;
      bCachedWrite = false;
      fcache = 0;
      bMustRevalidate = false;
      cacheExpireDateOffset = 0;
      bErrorPage = false;
      bUseCookiejar = false;
      expireDate = 0;
      creationDate = 0;
    }

    QString hostname;
    QString encoded_hostname;
    short unsigned int port;
    QString user;
    QString passwd;
    QString path;
    QString query;
    KIO::HTTP_METHOD method;
    KIO::CacheControl cache;
    KIO::filesize_t offset;
    bool doProxy;
    KURL url;
    QString window;                 // Window Id this request is related to.
    QString referrer;
    QString charsets;
    QString languages;
    bool allowCompressedPage;
    bool disablePassDlg;
    QString userAgent;
    QString id;
    DAVRequest davData;

    bool bNoAuth; // Do not authenticate

    // Cache related
    QString cef; // Cache Entry File belonging to this URL.
    bool bUseCache; // Whether the cache is active
    bool bCachedRead; // Whether the file is to be read from m_fcache.
    bool bCachedWrite; // Whether the file is to be written to m_fcache.
    FILE* fcache; // File stream of a cache entry
    QString etag; // ETag header.
    QString lastModified; // Last modified.
    bool bMustRevalidate; // Cache entry is expired.
    long cacheExpireDateOffset; // Position in the cache entry where the
                                  // 16 byte expire date is stored.
    time_t expireDate; // Date when the cache entry will expire
    time_t creationDate; // Date when the cache entry was created
    QString strCharset; // Charset

    // Indicates whether an error-page or error-msg should is preferred.
    bool bErrorPage;

    // Cookie flags
    bool bUseCookiejar;
    enum { CookiesAuto, CookiesManual, CookiesNone } cookieMode;
  };

  struct DigestAuthInfo
  {
    QCString nc;
    QCString qop;
    QCString realm;
    QCString nonce;
    QCString method;
    QCString cnonce;
    QCString username;
    QCString password;
    QStrList digestURI;
    QCString algorithm;
    QCString entityBody;
  };

//---------------------- Re-implemented methods ----------------
  virtual void setHost(const QString& host, int port, const QString& user,
                       const QString& pass);

  virtual void slave_status();

  virtual void get( const KURL& url );
  virtual void put( const KURL& url, int permissions, bool overwrite,
                    bool resume );

//----------------- Re-implemented methods for WebDAV -----------
  virtual void listDir( const KURL& url );
  virtual void mkdir( const KURL& url, int permissions );

  virtual void rename( const KURL& src, const KURL& dest, bool overwrite );
  virtual void copy( const KURL& src, const KURL& dest, int permissions, bool overwrite );
  virtual void del( const KURL& url, bool isfile );

  // ask the host whether it supports WebDAV & cache this info
  bool davHostOk();

  // send generic DAV request
  void davGeneric( const KURL& url, KIO::HTTP_METHOD method );

  // Send requests to lock and unlock resources
  void davLock( const KURL& url, const QString& scope,
                const QString& type, const QString& owner );
  void davUnlock( const KURL& url );

  // Calls httpClose() and finished()
  void davFinished();

  // Handle error conditions
  QString davError( int code = -1, QString url = QString::null );
//---------------------------- End WebDAV -----------------------

  /**
   * Special commands supported by this slave :
   * 1 - HTTP POST
   * 2 - Cache has been updated
   * 3 - SSL Certificate Cache has been updated
   * 4 - HTTP multi get
   * 5 - DAV LOCK     (see
   * 6 - DAV UNLOCK     README.webdav)
   */
  virtual void special( const QByteArray &data );

  virtual void mimetype( const KURL& url);

  virtual void stat( const KURL& url );

  virtual void reparseConfiguration();

  virtual void closeConnection(); // Forced close of connection

  void post( const KURL& url );
  void multiGet(const QByteArray &data);
  bool checkRequestURL( const KURL& );
  void cacheUpdate( const KURL &url, bool nocache, time_t expireDate);

  void httpError(); // Generate error message based on response code

  bool isOffline(const KURL &url); // Check network status

protected slots:
  void slotData(const QByteArray &);
  void error( int _errid, const QString &_text );

protected:
  int readChunked();    // Read a chunk
  int readLimited();    // Read maximum m_iSize bytes.
  int readUnlimited();  // Read as much as possible.

  /**
    * A "smart" wrapper around write that will use SSL_write or
    * write(2) depending on whether you've got an SSL connection or not.
    * The only shortcomming is that it uses the "global" file handles and
    * soforth.  So you can't really use this on individual files/sockets.
    */
  ssize_t write(const void *buf, size_t nbytes);

  /**
    * Another "smart" wrapper, this time around read that will
    * use SSL_read or read(2) depending on whether you've got an
    * SSL connection or not.
    */
  ssize_t read (void *b, size_t nbytes);

  char *gets (char *str, int size);

  void setRewindMarker();
  void rewind();

  /**
    * Add an encoding on to the appropriate stack this
    * is nececesary because transfer encodings and
    * content encodings must be handled separately.
    */
  void addEncoding(QString, QStringList &);

  void configAuth( char *, bool );

  bool httpOpen();             // Open transfer
  void httpClose(bool keepAlive);  // Close transfer

  bool httpOpenConnection();   // Open connection
  void httpCloseConnection();  // Close connection
  void httpCheckConnection();  // Check whether to keep connection.

  void forwardHttpResponseHeader();

  bool readHeader();

  bool sendBody();

  // where dataInternal == true, the content is to be made available
  // to an internal function.
  bool readBody( bool dataInternal = false );

  /**
   * Performs a WebDAV stat or list
   */
  void davSetRequest( const QCString& requestXML );
  void davStatList( const KURL& url, bool stat = true );
  void davParsePropstats( const QDomNodeList& propstats, KIO::UDSEntry& entry );
  void davParseActiveLocks( const QDomNodeList& activeLocks,
                            uint& lockCount );

  /**
   * Parses a date & time string
   */
  long parseDateTime( const QString& input, const QString& type );

  /**
   * Returns the error code from a "HTTP/1.1 code Code Name" string
   */
  int codeFromResponse( const QString& response );

  /**
   * Extracts locks from metadata
   * Returns the appropriate If: header
   */
  QString davProcessLocks();

  /**
   * Send a cookie to the cookiejar
   */
  void addCookies( const QString &url, const QCString &cookieHeader);

  /**
   * Look for cookies in the cookiejar
   */
  QString findCookies( const QString &url);

  /**
   * Do a cache lookup for the current url. (m_state.url)
   *
   * @param readWrite If true, file is opened read/write.
   *                  If false, file is opened read-only.
   *
   * @return a file stream open for reading and at the start of
   *         the header section when the Cache entry exists and is valid.
   *         0 if no cache entry could be found, or if the entry is not
   *         valid (any more).
   */
  FILE *checkCacheEntry(bool readWrite = false);

  /**
   * Create a cache entry for the current url. (m_state.url)
   *
   * Set the contents type of the cache entry to 'mimetype'.
   */
  void createCacheEntry(const QString &mimetype, time_t expireDate);

  /**
   * Write data to cache.
   *
   * Write 'nbytes' from 'buffer' to the Cache Entry File
   */
  void writeCacheEntry( const char *buffer, int nbytes);

  /**
   * Close cache entry
   */
  void closeCacheEntry();

  /**
   * Update expire time of current cache entry.
   */
  void updateExpireDate(time_t expireDate, bool updateCreationDate=false);

  /**
   * Quick check whether the cache needs cleaning.
   */
  void cleanCache();

  /**
   * Performs a GET HTTP request.
   */
  // where dataInternal == true, the content is to be made available
  // to an internal function.
  void retrieveContent( bool dataInternal = false );

  /**
   * Performs a HEAD HTTP request.
   */
  bool retrieveHeader(bool close_connection = true);

  /**
   * Resets any per session settings.
   */
  void resetSessionSettings();

  /**
   * Resets settings related to parsing a response.
   */
  void resetResponseSettings();

  /**
   * Resets any per connection settings.  These are different from
   * per-session settings in that they must be invalidates every time
   * a request is made, e.g. a retry to re-send the header to the
   * server, as compared to only when a new request arrives.
   */
  void resetConnectionSettings();

  /**
   * Returns any pre-cached proxy authentication info
   * info in HTTP header format.
   */
  QString proxyAuthenticationHeader();

  /**
   * Retrieves authorization info from cache or user.
   */
  bool getAuthorization();

  /**
   * Saves valid authorization info in the cache daemon.
   */
  void saveAuthorization();

  /**
   * Creates the entity-header for Basic authentication.
   */
  QString createBasicAuth( bool isForProxy = false );

  /**
   * Creates the entity-header for Digest authentication.
   */
  QString createDigestAuth( bool isForProxy = false );

  /**
   * Creates the entity-header for NTLM authentication.
   */
  QString createNTLMAuth( bool isForProxy = false );

  /**
   * Creates the entity-header for Negotiate authentication.
   */
  QString createNegotiateAuth();

  /**
   * create GSS error string
   */
  QCString gssError( int major_status, int minor_status );

  /**
   * Calcualtes the message digest response based on RFC 2617.
   */
  void calculateResponse( DigestAuthInfo &info, QCString &Response );

  /**
   * Prompts the user for authorization retry.
   */
  bool retryPrompt();

  /**
   * Creates authorization prompt info.
   */
  void promptInfo( KIO::AuthInfo& info );

protected:
  HTTPState m_state;
  HTTPRequest m_request;
  QPtrList<HTTPRequest> m_requestQueue;

  bool m_bBusy; // Busy handling request queue.
  bool m_bEOF;
  bool m_bEOD;

//--- Settings related to a single response only
  QStringList m_responseHeader; // All headers
  KURL m_redirectLocation;
  bool m_bRedirect; // Indicates current request is a redirection

  // Processing related
  bool m_bChunked; // Chunked tranfer encoding
  KIO::filesize_t m_iSize; // Expected size of message
  KIO::filesize_t m_iBytesLeft; // # of bytes left to receive in this message.
  KIO::filesize_t m_iContentLeft; // # of content bytes left
  QByteArray m_bufReceive; // Receive buffer
  bool m_dataInternal; // Data is for internal consumption
  char m_lineBuf[1024];
  char m_rewindBuf[8192];
  size_t m_rewindCount;
  char *m_linePtr;
  size_t m_lineCount;
  char *m_lineBufUnget;
  char *m_linePtrUnget;
  size_t m_lineCountUnget;

  // Mimetype determination
  bool m_cpMimeBuffer;
  QByteArray m_mimeTypeBuffer;

  // Language/Encoding related
  QStringList m_qTransferEncodings;
  QStringList m_qContentEncodings;
  QString m_sContentMD5;
  QString m_strMimeType;


//--- WebDAV
  // Data structure to hold data which will be passed to an internal func.
  QByteArray m_bufWebDavData;
  QStringList m_davCapabilities;

  bool m_davHostOk;
  bool m_davHostUnsupported;
//----------

  // Holds the POST data so it won't get lost on if we
  // happend to get a 401/407 response when submitting,
  // a form.
  QByteArray m_bufPOST;

  // Cache related
  int m_maxCacheAge; // Maximum age of a cache entry.
  long m_maxCacheSize; // Maximum cache size in Kb.
  QString m_strCacheDir; // Location of the cache.



//--- Proxy related members
  bool m_bUseProxy;
  bool m_bNeedTunnel; // Whether we need to make a SSL tunnel
  bool m_bIsTunneled; // Whether we have an active SSL tunnel
  bool m_bProxyAuthValid;
  int m_iProxyPort;
  KURL m_proxyURL;
  QString m_strProxyRealm;

  // Operation mode
  QCString m_protocol;

  // Authentication
  QString m_strRealm;
  QString m_strAuthorization;
  QString m_strProxyAuthorization;
  HTTP_AUTH Authentication;
  HTTP_AUTH ProxyAuthentication;
  bool m_bUnauthorized;
  short unsigned int m_iProxyAuthCount;
  short unsigned int m_iWWWAuthCount;

  // First request on a connection
  bool m_bFirstRequest;

  // Persistent connections
  bool m_bKeepAlive;
  int m_keepAliveTimeout; // Timeout in seconds.

  // Persistent proxy connections
  bool m_bPersistentProxyConnection;


  // Indicates whether there was some connection error.
  bool m_bError;

  // Previous and current response codes
  unsigned int m_responseCode;
  unsigned int m_prevResponseCode;

  // Values that determine the remote connection timeouts.
  int m_proxyConnTimeout;
  int m_remoteConnTimeout;
  int m_remoteRespTimeout;

  int m_pid;
};
#endif