Doc: Modularize QtNetwork documentation.
[profile/ivi/qtbase.git] / src / network / access / qnetworkreply.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtNetwork module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qnetworkreply.h"
43 #include "qnetworkreply_p.h"
44 #include <QtNetwork/qsslconfiguration.h>
45
46 QT_BEGIN_NAMESPACE
47
48 QNetworkReplyPrivate::QNetworkReplyPrivate()
49     : readBufferMaxSize(0),
50       operation(QNetworkAccessManager::UnknownOperation),
51       errorCode(QNetworkReply::NoError)
52     , isFinished(false)
53 {
54     // set the default attribute values
55     attributes.insert(QNetworkRequest::ConnectionEncryptedAttribute, false);
56 }
57
58
59 /*!
60     \class QNetworkReply
61     \since 4.4
62     \brief The QNetworkReply class contains the data and headers for a request
63     sent with QNetworkAccessManager
64
65     \reentrant
66     \ingroup network
67     \inmodule QtNetwork
68
69     The QNetworkReply class contains the data and meta data related to
70     a request posted with QNetworkAccessManager. Like QNetworkRequest,
71     it contains a URL and headers (both in parsed and raw form), some
72     information about the reply's state and the contents of the reply
73     itself.
74
75     QNetworkReply is a sequential-access QIODevice, which means that
76     once data is read from the object, it no longer kept by the
77     device. It is therefore the application's responsibility to keep
78     this data if it needs to. Whenever more data is received from the
79     network and processed, the readyRead() signal is emitted.
80
81     The downloadProgress() signal is also emitted when data is
82     received, but the number of bytes contained in it may not
83     represent the actual bytes received, if any transformation is done
84     to the contents (for example, decompressing and removing the
85     protocol overhead).
86
87     Even though QNetworkReply is a QIODevice connected to the contents
88     of the reply, it also emits the uploadProgress() signal, which
89     indicates the progress of the upload for operations that have such
90     content.
91
92     \note Do not delete the object in the slot connected to the
93     error() or finished() signal. Use deleteLater().
94
95     \sa QNetworkRequest, QNetworkAccessManager
96 */
97
98 /*!
99     \enum QNetworkReply::NetworkError
100
101     Indicates all possible error conditions found during the
102     processing of the request.
103
104     \value NoError              no error condition.
105     \note When the HTTP protocol returns a redirect no error will be
106     reported.  You can check if there is a redirect with the
107     QNetworkRequest::RedirectionTargetAttribute attribute.
108
109     \value ConnectionRefusedError  the remote server refused the
110     connection (the server is not accepting requests)
111
112     \value RemoteHostClosedError   the remote server closed the
113     connection prematurely, before the entire reply was received and
114     processed
115
116     \value HostNotFoundError       the remote host name was not found
117     (invalid hostname)
118
119     \value TimeoutError            the connection to the remote server
120     timed out
121
122     \value OperationCanceledError  the operation was canceled via calls
123     to abort() or close() before it was finished.
124
125     \value SslHandshakeFailedError the SSL/TLS handshake failed and the
126     encrypted channel could not be established. The sslErrors() signal
127     should have been emitted.
128
129     \value TemporaryNetworkFailureError the connection was broken due
130     to disconnection from the network, however the system has initiated
131     roaming to another access point. The request should be resubmitted
132     and will be processed as soon as the connection is re-established.
133
134     \value NetworkSessionFailedError   the connection was broken due
135     to disconnection from the network or failure to start the network.
136
137     \value BackgroundRequestNotAllowedError the background request
138     is not currently allowed due to platform policy.
139
140     \value ProxyConnectionRefusedError the connection to the proxy
141     server was refused (the proxy server is not accepting requests)
142
143     \value ProxyConnectionClosedError  the proxy server closed the
144     connection prematurely, before the entire reply was received and
145     processed
146
147     \value ProxyNotFoundError          the proxy host name was not
148     found (invalid proxy hostname)
149
150     \value ProxyTimeoutError           the connection to the proxy
151     timed out or the proxy did not reply in time to the request sent
152
153     \value ProxyAuthenticationRequiredError the proxy requires
154     authentication in order to honour the request but did not accept
155     any credentials offered (if any)
156
157     \value ContentAccessDenied          the access to the remote
158     content was denied (similar to HTTP error 401)
159
160     \value ContentOperationNotPermittedError the operation requested
161     on the remote content is not permitted
162
163     \value ContentNotFoundError         the remote content was not
164     found at the server (similar to HTTP error 404)
165
166     \value AuthenticationRequiredError  the remote server requires
167     authentication to serve the content but the credentials provided
168     were not accepted (if any)
169
170     \value ContentReSendError          the request needed to be sent
171     again, but this failed for example because the upload data
172     could not be read a second time.
173
174     \value ProtocolUnknownError         the Network Access API cannot
175     honor the request because the protocol is not known
176
177     \value ProtocolInvalidOperationError the requested operation is
178     invalid for this protocol
179
180     \value UnknownNetworkError          an unknown network-related
181     error was detected
182
183     \value UnknownProxyError            an unknown proxy-related error
184     was detected
185
186     \value UnknownContentError          an unknown error related to
187     the remote content was detected
188
189     \value ProtocolFailure              a breakdown in protocol was
190     detected (parsing error, invalid or unexpected responses, etc.)
191
192     \sa error()
193 */
194
195 /*!
196     \fn void QNetworkReply::sslErrors(const QList<QSslError> &errors)
197
198     This signal is emitted if the SSL/TLS session encountered errors
199     during the set up, including certificate verification errors. The
200     \a errors parameter contains the list of errors.
201
202     To indicate that the errors are not fatal and that the connection
203     should proceed, the ignoreSslErrors() function should be called
204     from the slot connected to this signal. If it is not called, the
205     SSL session will be torn down before any data is exchanged
206     (including the URL).
207
208     This signal can be used to display an error message to the user
209     indicating that security may be compromised and display the
210     SSL settings (see sslConfiguration() to obtain it). If the user
211     decides to proceed after analyzing the remote certificate, the
212     slot should call ignoreSslErrors().
213
214     \sa QSslSocket::sslErrors(), QNetworkAccessManager::sslErrors(),
215     sslConfiguration(), ignoreSslErrors()
216 */
217
218 /*!
219     \fn void QNetworkReply::metaDataChanged()
220
221     \omit FIXME: Update name? \endomit
222
223     This signal is emitted whenever the metadata in this reply
224     changes. metadata is any information that is not the content
225     (data) itself, including the network headers. In the majority of
226     cases, the metadata will be known fully by the time the first
227     byte of data is received. However, it is possible to receive
228     updates of headers or other metadata during the processing of the
229     data.
230
231     \sa header(), rawHeaderList(), rawHeader(), hasRawHeader()
232 */
233
234 /*!
235     \fn void QNetworkReply::finished()
236
237     This signal is emitted when the reply has finished
238     processing. After this signal is emitted, there will be no more
239     updates to the reply's data or metadata.
240
241     Unless close() has been called, the reply will be still be opened
242     for reading, so the data can be retrieved by calls to read() or
243     readAll(). In particular, if no calls to read() were made as a
244     result of readyRead(), a call to readAll() will retrieve the full
245     contents in a QByteArray.
246
247     This signal is emitted in tandem with
248     QNetworkAccessManager::finished() where that signal's reply
249     parameter is this object.
250
251     \note Do not delete the object in the slot connected to this
252     signal. Use deleteLater().
253
254     You can also use isFinished() to check if a QNetworkReply
255     has finished even before you receive the finished() signal.
256
257     \sa QNetworkAccessManager::finished(), isFinished()
258 */
259
260 /*!
261     \fn void QNetworkReply::error(QNetworkReply::NetworkError code)
262
263     This signal is emitted when the reply detects an error in
264     processing. The finished() signal will probably follow, indicating
265     that the connection is over.
266
267     The \a code parameter contains the code of the error that was
268     detected. Call errorString() to obtain a textual representation of
269     the error condition.
270
271     \note Do not delete the object in the slot connected to this
272     signal. Use deleteLater().
273
274     \sa error(), errorString()
275 */
276
277 /*!
278     \fn void QNetworkReply::uploadProgress(qint64 bytesSent, qint64 bytesTotal)
279
280     This signal is emitted to indicate the progress of the upload part
281     of this network request, if there's any. If there's no upload
282     associated with this request, this signal will not be emitted.
283
284     The \a bytesSent
285     parameter indicates the number of bytes uploaded, while \a
286     bytesTotal indicates the total number of bytes to be uploaded. If
287     the number of bytes to be uploaded could not be determined, \a
288     bytesTotal will be -1.
289
290     The upload is finished when \a bytesSent is equal to \a
291     bytesTotal. At that time, \a bytesTotal will not be -1.
292
293     \sa downloadProgress()
294 */
295
296 /*!
297     \fn void QNetworkReply::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
298
299     This signal is emitted to indicate the progress of the download
300     part of this network request, if there's any. If there's no
301     download associated with this request, this signal will be emitted
302     once with 0 as the value of both \a bytesReceived and \a
303     bytesTotal.
304
305     The \a bytesReceived parameter indicates the number of bytes
306     received, while \a bytesTotal indicates the total number of bytes
307     expected to be downloaded. If the number of bytes to be downloaded
308     is not known, \a bytesTotal will be -1.
309
310     The download is finished when \a bytesReceived is equal to \a
311     bytesTotal. At that time, \a bytesTotal will not be -1.
312
313     Note that the values of both \a bytesReceived and \a bytesTotal
314     may be different from size(), the total number of bytes
315     obtained through read() or readAll(), or the value of the
316     header(ContentLengthHeader). The reason for that is that there may
317     be protocol overhead or the data may be compressed during the
318     download.
319
320     \sa uploadProgress(), bytesAvailable()
321 */
322
323 /*!
324     \fn void QNetworkReply::abort()
325
326     Aborts the operation immediately and close down any network
327     connections still open. Uploads still in progress are also
328     aborted.
329
330     \sa close()
331 */
332
333 /*!
334     Creates a QNetworkReply object with parent \a parent.
335
336     You cannot directly instantiate QNetworkReply objects. Use
337     QNetworkAccessManager functions to do that.
338 */
339 QNetworkReply::QNetworkReply(QObject *parent)
340     : QIODevice(*new QNetworkReplyPrivate, parent)
341 {
342 }
343
344 /*!
345     \internal
346 */
347 QNetworkReply::QNetworkReply(QNetworkReplyPrivate &dd, QObject *parent)
348     : QIODevice(dd, parent)
349 {
350 }
351
352 /*!
353     Disposes of this reply and frees any resources associated with
354     it. If any network connections are still open, they will be
355     closed.
356
357     \sa abort(), close()
358 */
359 QNetworkReply::~QNetworkReply()
360 {
361 }
362
363 /*!
364     Closes this device for reading. Unread data is discarded, but the
365     network resources are not discarded until they are finished. In
366     particular, if any upload is in progress, it will continue until
367     it is done.
368
369     The finished() signal is emitted when all operations are over and
370     the network resources are freed.
371
372     \sa abort(), finished()
373 */
374 void QNetworkReply::close()
375 {
376     QIODevice::close();
377 }
378
379 /*!
380     \internal
381 */
382 bool QNetworkReply::isSequential() const
383 {
384     return true;
385 }
386
387 /*!
388     Returns the size of the read buffer, in bytes.
389
390     \sa setReadBufferSize()
391 */
392 qint64 QNetworkReply::readBufferSize() const
393 {
394     return d_func()->readBufferMaxSize;
395 }
396
397 /*!
398     Sets the size of the read buffer to be \a size bytes. The read
399     buffer is the buffer that holds data that is being downloaded off
400     the network, before it is read with QIODevice::read(). Setting the
401     buffer size to 0 will make the buffer unlimited in size.
402
403     QNetworkReply will try to stop reading from the network once this
404     buffer is full (i.e., bytesAvailable() returns \a size or more),
405     thus causing the download to throttle down as well. If the buffer
406     is not limited in size, QNetworkReply will try to download as fast
407     as possible from the network.
408
409     Unlike QAbstractSocket::setReadBufferSize(), QNetworkReply cannot
410     guarantee precision in the read buffer size. That is,
411     bytesAvailable() can return more than \a size.
412
413     \sa readBufferSize()
414 */
415 void QNetworkReply::setReadBufferSize(qint64 size)
416 {
417     Q_D(QNetworkReply);
418     d->readBufferMaxSize = size;
419 }
420
421 /*!
422     Returns the QNetworkAccessManager that was used to create this
423     QNetworkReply object. Initially, it is also the parent object.
424 */
425 QNetworkAccessManager *QNetworkReply::manager() const
426 {
427     return d_func()->manager;
428 }
429
430 /*!
431     Returns the request that was posted for this reply. In special,
432     note that the URL for the request may be different than that of
433     the reply.
434
435     \sa QNetworkRequest::url(), url(), setRequest()
436 */
437 QNetworkRequest QNetworkReply::request() const
438 {
439     return d_func()->request;
440 }
441
442 /*!
443     Returns the operation that was posted for this reply.
444
445     \sa setOperation()
446 */
447 QNetworkAccessManager::Operation QNetworkReply::operation() const
448 {
449     return d_func()->operation;
450 }
451
452 /*!
453     Returns the error that was found during the processing of this
454     request. If no error was found, returns NoError.
455
456     \sa setError()
457 */
458 QNetworkReply::NetworkError QNetworkReply::error() const
459 {
460     return d_func()->errorCode;
461 }
462
463 /*!
464     \since 4.6
465
466     Returns true when the reply has finished or was aborted.
467
468     \sa isRunning()
469 */
470 bool QNetworkReply::isFinished() const
471 {
472     return d_func()->isFinished;
473 }
474
475 /*!
476     \since 4.6
477
478     Returns true when the request is still processing and the
479     reply has not finished or was aborted yet.
480
481     \sa isFinished()
482 */
483 bool QNetworkReply::isRunning() const
484 {
485     return !isFinished();
486 }
487
488 /*!
489     Returns the URL of the content downloaded or uploaded. Note that
490     the URL may be different from that of the original request.
491
492     \sa request(), setUrl(), QNetworkRequest::url()
493 */
494 QUrl QNetworkReply::url() const
495 {
496     return d_func()->url;
497 }
498
499 /*!
500     Returns the value of the known header \a header, if that header
501     was sent by the remote server. If the header was not sent, returns
502     an invalid QVariant.
503
504     \sa rawHeader(), setHeader(), QNetworkRequest::header()
505 */
506 QVariant QNetworkReply::header(QNetworkRequest::KnownHeaders header) const
507 {
508     return d_func()->cookedHeaders.value(header);
509 }
510
511 /*!
512     Returns true if the raw header of name \a headerName was sent by
513     the remote server
514
515     \sa rawHeader()
516 */
517 bool QNetworkReply::hasRawHeader(const QByteArray &headerName) const
518 {
519     Q_D(const QNetworkReply);
520     return d->findRawHeader(headerName) != d->rawHeaders.constEnd();
521 }
522
523 /*!
524     Returns the raw contents of the header \a headerName as sent by
525     the remote server. If there is no such header, returns an empty
526     byte array, which may be indistinguishable from an empty
527     header. Use hasRawHeader() to verify if the server sent such
528     header field.
529
530     \sa setRawHeader(), hasRawHeader(), header()
531 */
532 QByteArray QNetworkReply::rawHeader(const QByteArray &headerName) const
533 {
534     Q_D(const QNetworkReply);
535     QNetworkHeadersPrivate::RawHeadersList::ConstIterator it =
536         d->findRawHeader(headerName);
537     if (it != d->rawHeaders.constEnd())
538         return it->second;
539     return QByteArray();
540 }
541
542 /*! \typedef QNetworkReply::RawHeaderPair
543
544   RawHeaderPair is a QPair<QByteArray, QByteArray> where the first
545   QByteArray is the header name and the second is the header.
546  */
547
548 /*!
549   Returns a list of raw header pairs.
550  */
551 const QList<QNetworkReply::RawHeaderPair>& QNetworkReply::rawHeaderPairs() const
552 {
553     Q_D(const QNetworkReply);
554     return d->rawHeaders;
555 }
556
557 /*!
558     Returns a list of headers fields that were sent by the remote
559     server, in the order that they were sent. Duplicate headers are
560     merged together and take place of the latter duplicate.
561 */
562 QList<QByteArray> QNetworkReply::rawHeaderList() const
563 {
564     return d_func()->rawHeadersKeys();
565 }
566
567 /*!
568     Returns the attribute associated with the code \a code. If the
569     attribute has not been set, it returns an invalid QVariant (type QVariant::Null).
570
571     You can expect the default values listed in
572     QNetworkRequest::Attribute to be applied to the values returned by
573     this function.
574
575     \sa setAttribute(), QNetworkRequest::Attribute
576 */
577 QVariant QNetworkReply::attribute(QNetworkRequest::Attribute code) const
578 {
579     return d_func()->attributes.value(code);
580 }
581
582 #ifndef QT_NO_SSL
583 /*!
584     Returns the SSL configuration and state associated with this
585     reply, if SSL was used. It will contain the remote server's
586     certificate, its certificate chain leading to the Certificate
587     Authority as well as the encryption ciphers in use.
588
589     The peer's certificate and its certificate chain will be known by
590     the time sslErrors() is emitted, if it's emitted.
591 */
592 QSslConfiguration QNetworkReply::sslConfiguration() const
593 {
594     QSslConfiguration config;
595     sslConfigurationImplementation(config);
596     return config;
597 }
598
599 /*!
600     Sets the SSL configuration for the network connection associated
601     with this request, if possible, to be that of \a config.
602 */
603 void QNetworkReply::setSslConfiguration(const QSslConfiguration &config)
604 {
605     setSslConfigurationImplementation(config);
606 }
607
608 /*!
609     \overload
610     \since 4.6
611
612     If this function is called, the SSL errors given in \a errors
613     will be ignored.
614
615     Note that you can set the expected certificate in the SSL error:
616     If, for instance, you want to issue a request to a server that uses
617     a self-signed certificate, consider the following snippet:
618
619     \snippet code/src_network_access_qnetworkreply.cpp 0
620
621     Multiple calls to this function will replace the list of errors that
622     were passed in previous calls.
623     You can clear the list of errors you want to ignore by calling this
624     function with an empty list.
625
626     \sa sslConfiguration(), sslErrors(), QSslSocket::ignoreSslErrors()
627 */
628 void QNetworkReply::ignoreSslErrors(const QList<QSslError> &errors)
629 {
630     ignoreSslErrorsImplementation(errors);
631 }
632 #endif
633
634 /*!
635   \fn void QNetworkReply::sslConfigurationImplementation(QSslConfiguration &configuration) const
636   \since 5.0
637
638   This virtual method is provided to enable overriding the behavior of
639   sslConfiguration(). sslConfiguration() is a public wrapper for this method.
640   The configuration will be returned in \a configuration.
641
642   \sa sslConfiguration()
643 */
644 void QNetworkReply::sslConfigurationImplementation(QSslConfiguration &) const
645 {
646 }
647
648 /*!
649   \fn void QNetworkReply::setSslConfigurationImplementation(const QSslConfiguration &configuration)
650   \since 5.0
651
652   This virtual method is provided to enable overriding the behavior of
653   setSslConfiguration(). setSslConfiguration() is a public wrapper for this method.
654   If you override this method use \a configuration to set the SSL configuration.
655
656   \sa sslConfigurationImplementation(), setSslConfiguration()
657 */
658 void QNetworkReply::setSslConfigurationImplementation(const QSslConfiguration &)
659 {
660 }
661
662 /*!
663   \fn void QNetworkReply::ignoreSslErrorsImplementation(const QList<QSslError> &errors)
664   \since 5.0
665
666   This virtual method is provided to enable overriding the behavior of
667   ignoreSslErrors(). ignoreSslErrors() is a public wrapper for this method.
668   \a errors contains the errors the user wishes ignored.
669
670   \sa ignoreSslErrors()
671 */
672 void QNetworkReply::ignoreSslErrorsImplementation(const QList<QSslError> &)
673 {
674 }
675
676 /*!
677     If this function is called, SSL errors related to network
678     connection will be ignored, including certificate validation
679     errors.
680
681     Note that calling this function without restraint may pose a
682     security risk for your application. Use it with care.
683
684     This function can be called from the slot connected to the
685     sslErrors() signal, which indicates which errors were
686     found.
687
688     \sa sslConfiguration(), sslErrors(), QSslSocket::ignoreSslErrors()
689 */
690 void QNetworkReply::ignoreSslErrors()
691 {
692 }
693
694 /*!
695     \internal
696 */
697 qint64 QNetworkReply::writeData(const char *, qint64)
698 {
699     return -1;                  // you can't write
700 }
701
702 /*!
703     Sets the associated operation for this object to be \a
704     operation. This value will be returned by operation().
705
706     Note: the operation should be set when this object is created and
707     not changed again.
708
709     \sa operation(), setRequest()
710 */
711 void QNetworkReply::setOperation(QNetworkAccessManager::Operation operation)
712 {
713     Q_D(QNetworkReply);
714     d->operation = operation;
715 }
716
717 /*!
718     Sets the associated request for this object to be \a request. This
719     value will be returned by request().
720
721     Note: the request should be set when this object is created and
722     not changed again.
723
724     \sa request(), setOperation()
725 */
726 void QNetworkReply::setRequest(const QNetworkRequest &request)
727 {
728     Q_D(QNetworkReply);
729     d->request = request;
730 }
731
732 /*!
733     Sets the error condition to be \a errorCode. The human-readable
734     message is set with \a errorString.
735
736     Calling setError() does not emit the error(QNetworkReply::NetworkError)
737     signal.
738
739     \sa error(), errorString()
740 */
741 void QNetworkReply::setError(NetworkError errorCode, const QString &errorString)
742 {
743     Q_D(QNetworkReply);
744     d->errorCode = errorCode;
745     setErrorString(errorString); // in QIODevice
746 }
747
748 /*!
749     \since 4.8
750     Sets the reply as \a finished.
751
752     After having this set the replies data must not change.
753
754     \sa isFinished()
755 */
756 void QNetworkReply::setFinished(bool finished)
757 {
758     Q_D(QNetworkReply);
759     d->isFinished = finished;
760 }
761
762
763 /*!
764     Sets the URL being processed to be \a url. Normally, the URL
765     matches that of the request that was posted, but for a variety of
766     reasons it can be different (for example, a file path being made
767     absolute or canonical).
768
769     \sa url(), request(), QNetworkRequest::url()
770 */
771 void QNetworkReply::setUrl(const QUrl &url)
772 {
773     Q_D(QNetworkReply);
774     d->url = url;
775 }
776
777 /*!
778     Sets the known header \a header to be of value \a value. The
779     corresponding raw form of the header will be set as well.
780
781     \sa header(), setRawHeader(), QNetworkRequest::setHeader()
782 */
783 void QNetworkReply::setHeader(QNetworkRequest::KnownHeaders header, const QVariant &value)
784 {
785     Q_D(QNetworkReply);
786     d->setCookedHeader(header, value);
787 }
788
789 /*!
790     Sets the raw header \a headerName to be of value \a value. If \a
791     headerName was previously set, it is overridden. Multiple HTTP
792     headers of the same name are functionally equivalent to one single
793     header with the values concatenated, separated by commas.
794
795     If \a headerName matches a known header, the value \a value will
796     be parsed and the corresponding parsed form will also be set.
797
798     \sa rawHeader(), header(), setHeader(), QNetworkRequest::setRawHeader()
799 */
800 void QNetworkReply::setRawHeader(const QByteArray &headerName, const QByteArray &value)
801 {
802     Q_D(QNetworkReply);
803     d->setRawHeader(headerName, value);
804 }
805
806 /*!
807     Sets the attribute \a code to have value \a value. If \a code was
808     previously set, it will be overridden. If \a value is an invalid
809     QVariant, the attribute will be unset.
810
811     \sa attribute(), QNetworkRequest::setAttribute()
812 */
813 void QNetworkReply::setAttribute(QNetworkRequest::Attribute code, const QVariant &value)
814 {
815     Q_D(QNetworkReply);
816     if (value.isValid())
817         d->attributes.insert(code, value);
818     else
819         d->attributes.remove(code);
820 }
821
822 QT_END_NAMESPACE