00001 #include <iostream>
00002 #include <qapplication.h>
00003 #include <qregexp.h>
00004 #include <unistd.h>
00005
00006 #include "mythcontext.h"
00007 #include "compat.h"
00008
00009 using namespace std;
00010
00011 #include "qmdcodec.h"
00012 #include "httpcomms.h"
00013
00014 HttpComms::HttpComms()
00015 : http(0)
00016 {
00017 init();
00018 }
00019
00020
00021 HttpComms::HttpComms(QUrl &url, int timeoutms)
00022 : http(0)
00023 {
00024 init();
00025 request(url, timeoutms);
00026 }
00027
00028 HttpComms::HttpComms(QUrl &url, QHttpRequestHeader &header, int timeoutms)
00029 {
00030 init();
00031 request(url, header, timeoutms);
00032 }
00033
00034 HttpComms::~HttpComms()
00035 {
00036 if (m_timer)
00037 delete m_timer;
00038
00039 delete http;
00040 }
00041
00042 void HttpComms::init()
00043 {
00044
00045 m_authNeeded = false;
00046 http = new QHttp();
00047 m_redirectedURL = "";
00048 m_done = false;
00049 m_statusCode = 0;
00050 m_responseReason = "";
00051 m_timer = NULL;
00052 m_timeout = false;
00053
00054
00055 connect(http, SIGNAL(done(bool)), this, SLOT(done(bool)));
00056 connect(http, SIGNAL(stateChanged(int)), this, SLOT(stateChanged(int)));
00057 connect(http, SIGNAL(responseHeaderReceived(const QHttpResponseHeader &)),
00058 this, SLOT(headerReceived(const QHttpResponseHeader &)));
00059 connect(http, SIGNAL(dataReadProgress(int, int)), this, SLOT(dataReadProgress(int, int)));
00060
00061 }
00062
00063 void HttpComms::request(QUrl &url, int timeoutms, bool allowGzip)
00064 {
00065 QHttpRequestHeader header("GET", url.encodedPathAndQuery());
00066 QString userAgent = "Mozilla/9.876 (X11; U; Linux 2.2.12-20 i686, en) "
00067 "Gecko/25250101 Netscape/5.432b1";
00068
00069 header.setValue("Host", url.host());
00070 header.setValue("User-Agent", userAgent);
00071
00072 if (allowGzip)
00073 header.setValue( "Accept-Encoding", "gzip");
00074
00075 request(url, header, timeoutms);
00076 }
00077
00078
00079
00080 void HttpComms::request(QUrl &url,
00081 QHttpRequestHeader &header,
00082 int timeoutms,
00083 QIODevice *pData )
00084 {
00085 Q_UINT16 port = 80;
00086
00087 if (url.hasPort())
00088 port = url.port();
00089
00090 http->setHost(url.host(), port);
00091
00092 m_url = url.toString();
00093 m_curRequest = header;
00094
00095 if (m_timer)
00096 m_timer->stop();
00097
00098 if (timeoutms > 0 )
00099 {
00100 if (!m_timer)
00101 {
00102 m_timer = new QTimer();
00103 connect(m_timer, SIGNAL(timeout()), SLOT(timeout()));
00104 }
00105 m_timeoutInterval = timeoutms;
00106 m_timer->start(timeoutms, TRUE);
00107 }
00108
00109 if (m_cookie)
00110 {
00111 header.setValue("Cookie", m_cookie);
00112 }
00113
00114 http->request(header, pData);
00115 }
00116
00117 void HttpComms::stop()
00118 {
00119 disconnect(http, 0, 0, 0);
00120 http->abort();
00121
00122 if (m_timer)
00123 m_timer->stop();
00124 }
00125
00126 void HttpComms::done(bool error)
00127 {
00128 if (error)
00129 {
00130 VERBOSE(VB_IMPORTANT, QString("HttpComms::done() - NetworkOperation Error on Finish: "
00131 "%1 (%2): url: '%3'")
00132 .arg(http->errorString())
00133 .arg(error)
00134 .arg(m_url.toString().latin1()));
00135 }
00136 else if (m_authNeeded)
00137 {
00138 VERBOSE(VB_NETWORK, QString("Authentication pending, ignoring done from first request."));
00139 return;
00140 }
00141 else if (http->bytesAvailable())
00142 {
00143 m_data.resize(http->bytesAvailable());
00144 m_data = http->readAll();
00145 }
00146
00147 VERBOSE(VB_NETWORK, QString("done: %1 bytes").arg(m_data.size()));
00148
00149 if (m_timer)
00150 m_timer->stop();
00151
00152 m_done = true;
00153 }
00154
00155 void HttpComms::stateChanged(int state)
00156 {
00157 QString stateStr;
00158
00159 switch (state)
00160 {
00161 case QHttp::Unconnected: stateStr = "unconnected"; break;
00162 case QHttp::HostLookup: stateStr = "host lookup"; break;
00163 case QHttp::Connecting: stateStr = "connecting"; break;
00164 case QHttp::Sending: stateStr = "sending"; break;
00165 case QHttp::Reading: stateStr = "reading"; break;
00166 case QHttp::Connected: stateStr = "connected"; break;
00167 case QHttp::Closing: stateStr = "closing"; break;
00168 default: stateStr = "unknown state: "; break;
00169 }
00170
00171 VERBOSE(VB_NETWORK, QString("HttpComms::stateChanged: %1 (%2)")
00172 .arg(stateStr)
00173 .arg(state));
00174 }
00175
00176 void HttpComms::headerReceived(const QHttpResponseHeader &resp)
00177 {
00178 m_statusCode = resp.statusCode();
00179 m_responseReason = resp.reasonPhrase();
00180
00181 QString sidkey = "set-cookie";
00182
00183 if (resp.hasKey(sidkey))
00184 {
00185 QRegExp rx("PHPSESSID=(.+);");
00186 rx.setMinimal(true);
00187 rx.setCaseSensitive(false);
00188 if (rx.search(resp.value(sidkey)) >= 0)
00189 {
00190 m_cookie = "PHPSESSID=" + rx.cap(1);
00191 VERBOSE(VB_NETWORK, QString("HttpComms found cookie: %1").arg(m_cookie));
00192 }
00193 }
00194
00195
00196 VERBOSE(VB_NETWORK, QString("Got HTTP response: %1:%2")
00197 .arg(m_statusCode)
00198 .arg(m_responseReason));
00199 VERBOSE(VB_NETWORK, QString("Keys: %1")
00200 .arg(resp.keys().join(",") ));
00201
00202
00203 if (resp.statusCode() >= 300 && resp.statusCode() <= 400)
00204 {
00205
00206 QString uri = resp.value("LOCATION");
00207 VERBOSE(VB_NETWORK, QString("Redirection to: '%1'").arg(uri));
00208
00209 m_redirectedURL = resp.value("LOCATION");
00210 m_authNeeded = false;
00211 }
00212 else if ((resp.statusCode() == 401))
00213 {
00214
00215
00216
00217 m_authNeeded = !m_authNeeded;
00218 if (m_authNeeded)
00219 {
00220 QString authHeader(resp.value("www-authenticate"));
00221
00222 if (authHeader.startsWith("Digest") )
00223 {
00224 if (!createDigestAuth(false, authHeader, &m_curRequest) )
00225 {
00226 m_authNeeded = false;
00227 return;
00228 }
00229 }
00230 else
00231 {
00232 QCString auth = QCodecs::base64Encode( QCString( m_webCredentials.user +
00233 ":" + m_webCredentials.pass ) );
00234 m_curRequest.setValue( "Authorization", QString( "Basic " ).append( auth.data() ) );
00235 }
00236
00237 if (m_timer)
00238 {
00239 m_timer->stop();
00240 m_timer->start(m_timeoutInterval, TRUE);
00241 }
00242
00243
00244
00245 if (m_cookie)
00246 {
00247 m_curRequest.setValue("Cookie", m_cookie);
00248 }
00249
00250 http->request(m_curRequest);
00251 }
00252 }
00253 else
00254 {
00255 m_authNeeded = false;
00256 }
00257 }
00258
00259 void HttpComms::timeout()
00260 {
00261 VERBOSE(VB_IMPORTANT, QString("HttpComms::Timeout for url: %1")
00262 .arg(m_url.toString().latin1()));
00263 m_timeout = true;
00264 m_done = true;
00265 }
00266
00267 void HttpComms::dataReadProgress(int done, int total)
00268 {
00269 m_progress = done;
00270 m_total = total;
00271 }
00272
00273
00279 QString HttpComms::getHttp(QString &url,
00280 int timeoutMS, int maxRetries,
00281 int maxRedirects, bool allowGzip,
00282 Credentials *webCred, bool isInQtEventThread)
00283 {
00284 int redirectCount = 0;
00285 int timeoutCount = 0;
00286 QString res = "";
00287 HttpComms *httpGrabber = NULL;
00288 QString hostname = "";
00289
00290 while (1)
00291 {
00292 QUrl qurl(url);
00293 if (hostname == "")
00294 hostname = qurl.host();
00295 if (!qurl.hasHost())
00296 qurl.setHost(hostname);
00297
00298 VERBOSE(VB_NETWORK, QString("getHttp: grabbing: %1").arg(qurl.toString()));
00299
00300 if (httpGrabber != NULL)
00301 delete httpGrabber;
00302
00303 httpGrabber = new HttpComms;
00304
00305 if (webCred)
00306 httpGrabber->setCredentials(*webCred, CRED_WEB);
00307
00308 httpGrabber->request(qurl, timeoutMS, allowGzip);
00309
00310
00311 while (!httpGrabber->isDone())
00312 {
00313 if (isInQtEventThread)
00314 qApp->processEvents();
00315 usleep(10000);
00316 }
00317
00318
00319 if (httpGrabber->isTimedout())
00320 {
00321 VERBOSE(VB_NETWORK, QString("timeout for url: %1").arg(url.latin1()));
00322
00323
00324 if (timeoutCount++ >= maxRetries)
00325 {
00326 VERBOSE(VB_IMPORTANT, QString("Failed to contact server for url: %1").arg(url.latin1()));
00327 break;
00328 }
00329
00330
00331 VERBOSE(VB_NETWORK, QString("Attempt # %1/%2 for url: %3")
00332 .arg(timeoutCount + 1)
00333 .arg(maxRetries)
00334 .arg(url.latin1()));
00335
00336 continue;
00337 }
00338
00339
00340 if (!httpGrabber->getRedirectedURL().isEmpty())
00341 {
00342 VERBOSE(VB_NETWORK, QString("Redirection: %1, count: %2, max: %3")
00343 .arg(httpGrabber->getRedirectedURL().latin1())
00344 .arg(redirectCount)
00345 .arg(maxRedirects));
00346 if (redirectCount++ < maxRedirects)
00347 url = httpGrabber->getRedirectedURL();
00348
00349
00350 timeoutCount = 0;
00351 continue;
00352 }
00353
00354 res = httpGrabber->getData();
00355 break;
00356 }
00357
00358 delete httpGrabber;
00359
00360
00361 VERBOSE(VB_NETWORK, QString("Got %1 bytes from url: '%2'")
00362 .arg(res.length())
00363 .arg(url.latin1()));
00364 VERBOSE(VB_NETWORK, res);
00365
00366 return res;
00367 }
00368
00369
00370
00371 bool HttpComms::getHttpFile(const QString& filename, QString& url, int timeoutMS,
00372 int maxRetries, int maxRedirects,
00373 bool allowGzip, Credentials* webCred)
00374 {
00375 int redirectCount = 0;
00376 int timeoutCount = 0;
00377 QByteArray data(0);
00378 bool res = false;
00379 HttpComms *httpGrabber = NULL;
00380 QString hostname = "";
00381
00382 while (1)
00383 {
00384 QUrl qurl(url);
00385 if (hostname == "")
00386 hostname = qurl.host();
00387
00388 if (!qurl.hasHost())
00389 qurl.setHost(hostname);
00390
00391 VERBOSE(VB_NETWORK, QString("getHttp: grabbing: '%1'")
00392 .arg(qurl.toString()));
00393
00394 if (httpGrabber != NULL)
00395 delete httpGrabber;
00396
00397 httpGrabber = new HttpComms;
00398
00399 if (webCred)
00400 httpGrabber->setCredentials(*webCred, CRED_WEB);
00401
00402 httpGrabber->request(qurl, timeoutMS, allowGzip);
00403
00404 while (!httpGrabber->isDone())
00405 {
00406 qApp->processEvents();
00407 usleep(10000);
00408 }
00409
00410 int statusCode = httpGrabber->getStatusCode();
00411 if (statusCode < 200 || statusCode > 401)
00412 {
00413 VERBOSE(VB_IMPORTANT, QString("Server returned an error status code %1 for url: %2")
00414 .arg(statusCode)
00415 .arg(url.latin1()));
00416 break;
00417 }
00418
00419
00420 if (httpGrabber->isTimedout())
00421 {
00422 VERBOSE(VB_NETWORK, QString("Timeout for url: '%1'")
00423 .arg(url.latin1()));
00424
00425
00426 if (timeoutCount++ >= maxRetries)
00427 {
00428 VERBOSE(VB_IMPORTANT, QString("Failed to contact server for url: '%1'")
00429 .arg(url.latin1()));
00430 break;
00431 }
00432
00433
00434 VERBOSE(VB_NETWORK, QString("Attempt # %1/%2 for url: %3")
00435 .arg(timeoutCount + 1)
00436 .arg(maxRetries)
00437 .arg(url.latin1()));
00438
00439 continue;
00440 }
00441
00442
00443 if (!httpGrabber->getRedirectedURL().isEmpty())
00444 {
00445 VERBOSE(VB_NETWORK, QString("redirection: '%1', count: %2, max: %3")
00446 .arg(httpGrabber->getRedirectedURL().latin1())
00447 .arg(redirectCount)
00448 .arg(maxRedirects));
00449
00450 if (redirectCount++ < maxRedirects)
00451 url = httpGrabber->getRedirectedURL();
00452
00453
00454 timeoutCount = 0;
00455 continue;
00456 }
00457
00458 data = httpGrabber->getRawData();
00459
00460 if (data.size() > 0)
00461 {
00462 VERBOSE(VB_NETWORK, QString("getHttpFile: saving to file: '%1'")
00463 .arg(filename));
00464
00465 QFile file(filename);
00466 if (file.open( IO_WriteOnly ))
00467 {
00468 QDataStream stream(& file);
00469 stream.writeRawBytes( (const char*) (data), data.size() );
00470 file.close();
00471 res = true;
00472 VERBOSE(VB_NETWORK, QString("getHttpFile: File saved OK"));
00473 }
00474 else
00475 VERBOSE(VB_NETWORK, QString("getHttpFile: Failed to open file for writing"));
00476 }
00477 else
00478 VERBOSE(VB_NETWORK, QString("getHttpFile: nothing to save to file!"));
00479
00480 break;
00481 }
00482
00483 VERBOSE(VB_NETWORK, QString("Got %1 bytes from url: '%2'")
00484 .arg(data.size())
00485 .arg(url.latin1()));
00486
00487 delete httpGrabber;
00488
00489 return res;
00490 }
00491
00497 QString HttpComms::postHttp(QUrl &url ,
00498 QHttpRequestHeader *pAddlHdr , QIODevice *pData,
00499 int timeoutMS , int maxRetries,
00500 int maxRedirects, bool allowGzip,
00501 Credentials *webCred , bool isInQtEventThread)
00502 {
00503 int redirectCount = 0;
00504 int timeoutCount = 0;
00505 QString res = "";
00506 HttpComms *httpGrabber = NULL;
00507 QString hostname = "";
00508
00509 QHttpRequestHeader header( "POST", url.encodedPathAndQuery());
00510 QString userAgent = "Mozilla/9.876 (X11; U; Linux 2.2.12-20 i686, en) "
00511 "Gecko/25250101 Netscape/5.432b1";
00512
00513 header.setValue("Host", url.host());
00514 header.setValue("User-Agent", userAgent);
00515
00516 if (allowGzip)
00517 header.setValue( "Accept-Encoding", "gzip");
00518
00519
00520
00521 if (pAddlHdr)
00522 {
00523 QStringList keys = pAddlHdr->keys();
00524
00525 for ( QStringList::Iterator it = keys.begin(); it != keys.end(); ++it )
00526 header.setValue( *it, pAddlHdr->value( *it ));
00527 }
00528
00529 while (1)
00530 {
00531 if (hostname == "")
00532 hostname = url.host();
00533 if (!url.hasHost())
00534 url.setHost(hostname);
00535
00536 VERBOSE(VB_NETWORK, QString("postHttp: grabbing: %1").arg(url.toString()));
00537
00538 if (httpGrabber != NULL)
00539 delete httpGrabber;
00540
00541 httpGrabber = new HttpComms;
00542
00543 if (webCred)
00544 httpGrabber->setCredentials(*webCred, CRED_WEB);
00545
00546 httpGrabber->request(url, header, timeoutMS, pData );
00547
00548 while (!httpGrabber->isDone())
00549 {
00550 if (isInQtEventThread)
00551 qApp->processEvents();
00552 usleep(10000);
00553 }
00554
00555
00556 if (httpGrabber->isTimedout())
00557 {
00558 VERBOSE(VB_NETWORK, QString("timeout for url: %1").arg(url.toString()));
00559
00560
00561 if (timeoutCount++ >= maxRetries)
00562 {
00563 VERBOSE(VB_IMPORTANT, QString("Failed to contact server for url: %1").arg(url.toString()));
00564 break;
00565 }
00566
00567
00568 VERBOSE(VB_NETWORK, QString("Attempt # %1/%2 for url: %3")
00569 .arg(timeoutCount + 1)
00570 .arg(maxRetries)
00571 .arg(url.toString()));
00572
00573 continue;
00574 }
00575
00576
00577 if (!httpGrabber->getRedirectedURL().isEmpty())
00578 {
00579 VERBOSE(VB_NETWORK, QString("Redirection: %1, count: %2, max: %3")
00580 .arg(httpGrabber->getRedirectedURL().latin1())
00581 .arg(redirectCount)
00582 .arg(maxRedirects));
00583 if (redirectCount++ < maxRedirects)
00584 url = QUrl( httpGrabber->getRedirectedURL() );
00585
00586
00587 timeoutCount = 0;
00588 continue;
00589 }
00590
00591 res = httpGrabber->getData();
00592 break;
00593 }
00594
00595 delete httpGrabber;
00596
00597
00598 VERBOSE(VB_NETWORK, QString("Got %1 bytes from url: '%2'")
00599 .arg(res.length())
00600 .arg(url.toString()));
00601 VERBOSE(VB_NETWORK, res);
00602
00603 return res;
00604 }
00605
00606
00607 bool HttpComms::createDigestAuth ( bool isForProxy, const QString& authStr, QHttpRequestHeader* request)
00608 {
00609 const char *p;
00610 QString header;
00611 QString auth;
00612 QCString opaque;
00613 QCString Response;
00614
00615 DigestAuthInfo info;
00616
00617 opaque = "";
00618
00619 if ( isForProxy )
00620 {
00621 header = "Proxy-Authorization";
00622 auth = "Digest ";
00623 info.username = m_proxyCredentials.user.latin1();
00624 info.password = m_proxyCredentials.pass.latin1();
00625 p = authStr.latin1();
00626 }
00627 else
00628 {
00629 header = "Authorization";
00630 auth = "Digest ";
00631 info.username = m_webCredentials.user.latin1();
00632 info.password = m_webCredentials.pass.latin1();
00633 p = authStr.latin1();
00634 }
00635
00636 if (!p || !*p)
00637 return false;
00638
00639 p += 6;
00640
00641 if ( info.username.isEmpty() || info.password.isEmpty() || !p )
00642 return false;
00643
00644
00645 info.realm = "";
00646 info.algorithm = "MD5";
00647 info.nonce = "";
00648 info.qop = "";
00649
00650
00651
00652 info.cnonce = "QPDExMTQ";
00653
00654
00655 info.nc = "00000001";
00656
00657
00658 info.method = request->method();
00659
00660
00661 while (*p)
00662 {
00663 int i = 0;
00664 while ( (*p == ' ') || (*p == ',') || (*p == '\t')) {p++;}
00665
00666 if (strncasecmp(p, "realm=", 6 )==0)
00667 {
00668 p+=6;
00669 while ( *p == '"' ) p++;
00670 while ( p[i] != '"' ) i++;
00671 info.realm = QCString( p, i+1 );
00672 }
00673 else if (strncasecmp(p, "algorith=", 9)==0)
00674 {
00675 p+=9;
00676 while ( *p == '"' ) p++;
00677 while ( ( p[i] != '"' ) && ( p[i] != ',' ) && ( p[i] != '\0' ) ) i++;
00678 info.algorithm = QCString(p, i+1);
00679 }
00680 else if (strncasecmp(p, "algorithm=", 10)==0)
00681 {
00682 p+=10;
00683 while ( *p == '"' ) p++;
00684 while ( ( p[i] != '"' ) && ( p[i] != ',' ) && ( p[i] != '\0' ) ) i++;
00685 info.algorithm = QCString(p,i+1);
00686 }
00687 else if (strncasecmp(p, "domain=", 7)==0)
00688 {
00689 p+=7;
00690 while ( *p == '"' ) p++;
00691 while ( p[i] != '"' ) i++;
00692 int pos;
00693 int idx = 0;
00694 QCString uri = QCString(p,i+1);
00695 do
00696 {
00697 pos = uri.find( ' ', idx );
00698
00699 if ( pos != -1 )
00700 {
00701 QUrl u (m_url, uri.mid(idx, pos-idx));
00702 if (u.isValid ())
00703 info.digestURI.append( u.toString().latin1() );
00704 }
00705 else
00706 {
00707 QUrl u (m_url, uri.mid(idx, uri.length()-idx));
00708 if (u.isValid ())
00709 info.digestURI.append( u.toString().latin1() );
00710 }
00711 idx = pos+1;
00712 } while ( pos != -1 );
00713 }
00714 else if (strncasecmp(p, "nonce=", 6)==0)
00715 {
00716 p+=6;
00717 while ( *p == '"' ) p++;
00718 while ( p[i] != '"' ) i++;
00719 info.nonce = QCString(p,i+1);
00720 }
00721 else if (strncasecmp(p, "opaque=", 7)==0)
00722 {
00723 p+=7;
00724 while ( *p == '"' ) p++;
00725 while ( p[i] != '"' ) i++;
00726 opaque = QCString(p,i+1);
00727 }
00728 else if (strncasecmp(p, "qop=", 4)==0)
00729 {
00730 p+=4;
00731 while ( *p == '"' ) p++;
00732 while ( p[i] != '"' ) i++;
00733 info.qop = QCString(p,i+1);
00734 }
00735 p+=(i+1);
00736 }
00737
00738 if (info.realm.isEmpty() || info.nonce.isEmpty())
00739 return false;
00740
00741 info.digestURI.append (m_url.encodedPathAndQuery());
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753 calculateDigestResponse( info, Response );
00754
00755 auth += "username=\"";
00756 auth += info.username;
00757
00758 auth += "\", realm=\"";
00759 auth += info.realm;
00760 auth += "\"";
00761
00762 auth += ", nonce=\"";
00763 auth += info.nonce;
00764
00765 auth += "\", uri=\"";
00766 auth += m_url.encodedPathAndQuery();
00767
00768 auth += "\", algorithm=\"";
00769 auth += info.algorithm;
00770 auth +="\"";
00771
00772 if ( !info.qop.isEmpty() )
00773 {
00774 auth += ", qop=\"";
00775 auth += info.qop;
00776 auth += "\", cnonce=\"";
00777 auth += info.cnonce;
00778 auth += "\", nc=";
00779 auth += info.nc;
00780 }
00781
00782 auth += ", response=\"";
00783 auth += Response;
00784 if ( !opaque.isEmpty() )
00785 {
00786 auth += "\", opaque=\"";
00787 auth += opaque;
00788 }
00789
00790 auth += "\"";
00791
00792
00793 VERBOSE(VB_NETWORK, QString("Setting auth header %1 to '%2'")
00794 .arg(header).arg(auth));
00795
00796
00797 if (request)
00798 request->setValue(header, auth);
00799
00800 return true;
00801 }
00802
00803
00804 void HttpComms::calculateDigestResponse( DigestAuthInfo& info, QCString& Response )
00805 {
00806 QMD5 md;
00807 QCString HA1;
00808 QCString HA2;
00809
00810
00811 QCString authStr = info.username;
00812 authStr += ':';
00813 authStr += info.realm;
00814 authStr += ':';
00815 authStr += info.password;
00816 md.update( authStr );
00817
00818 if ( info.algorithm.lower() == "md5-sess" )
00819 {
00820 authStr = md.hexDigest();
00821 authStr += ':';
00822 authStr += info.nonce;
00823 authStr += ':';
00824 authStr += info.cnonce;
00825 md.reset();
00826 md.update( authStr );
00827 }
00828
00829 HA1 = md.hexDigest();
00830
00831
00832
00833
00834 authStr = info.method;
00835 authStr += ':';
00836 authStr += m_url.encodedPathAndQuery().latin1();
00837 if ( info.qop == "auth-int" )
00838 {
00839 authStr += ':';
00840 authStr += info.entityBody;
00841 }
00842
00843 md.reset();
00844 md.update( authStr );
00845 HA2 = md.hexDigest();
00846
00847
00848
00849
00850 authStr = HA1;
00851 authStr += ':';
00852 authStr += info.nonce;
00853 authStr += ':';
00854 if ( !info.qop.isEmpty() )
00855 {
00856 authStr += info.nc;
00857 authStr += ':';
00858 authStr += info.cnonce;
00859 authStr += ':';
00860 authStr += info.qop;
00861 authStr += ':';
00862 }
00863
00864 authStr += HA2;
00865 md.reset();
00866 md.update( authStr );
00867 Response = md.hexDigest();
00868
00869
00870 }
00871
00872