Mercurial > hg > svcore
comparison data/fileio/FileSource.cpp @ 762:3b2409646cc0 qt5
Get FileSource building
author | Chris Cannam |
---|---|
date | Mon, 11 Mar 2013 13:42:01 +0000 |
parents | 579b2da21e7a |
children | 2b3a8ae04597 |
comparison
equal
deleted
inserted
replaced
761:dc87569a196e | 762:3b2409646cc0 |
---|---|
18 #include "base/TempDirectory.h" | 18 #include "base/TempDirectory.h" |
19 #include "base/Exceptions.h" | 19 #include "base/Exceptions.h" |
20 #include "base/ProgressReporter.h" | 20 #include "base/ProgressReporter.h" |
21 #include "system/System.h" | 21 #include "system/System.h" |
22 | 22 |
23 #include <QHttp> | 23 #include <QNetworkAccessManager> |
24 #include <QFtp> | 24 #include <QNetworkReply> |
25 #include <QFileInfo> | 25 #include <QFileInfo> |
26 #include <QDir> | 26 #include <QDir> |
27 #include <QCoreApplication> | 27 #include <QCoreApplication> |
28 #include <QHttpResponseHeader> | |
29 | 28 |
30 #include <iostream> | 29 #include <iostream> |
31 #include <cstdlib> | 30 #include <cstdlib> |
32 | 31 |
33 #include <unistd.h> | 32 #include <unistd.h> |
34 | 33 |
35 //#define DEBUG_FILE_SOURCE 1 | 34 #define DEBUG_FILE_SOURCE 1 |
36 | 35 |
37 int | 36 int |
38 FileSource::m_count = 0; | 37 FileSource::m_count = 0; |
39 | 38 |
40 QMutex | 39 QMutex |
66 --urlExtantCountMap[url]; | 65 --urlExtantCountMap[url]; |
67 std::cerr << "FileSource: Now " << urlExtantCountMap[url] << " for this url, " << extantCount << " total" << std::endl; | 66 std::cerr << "FileSource: Now " << urlExtantCountMap[url] << " for this url, " << extantCount << " total" << std::endl; |
68 } | 67 } |
69 #endif | 68 #endif |
70 | 69 |
70 static QNetworkAccessManager nm; | |
71 | |
71 FileSource::FileSource(QString fileOrUrl, ProgressReporter *reporter, | 72 FileSource::FileSource(QString fileOrUrl, ProgressReporter *reporter, |
72 QString preferredContentType) : | 73 QString preferredContentType) : |
73 m_url(fileOrUrl, QUrl::StrictMode), | 74 m_url(fileOrUrl, QUrl::StrictMode), |
74 m_ftp(0), | |
75 m_http(0), | |
76 m_localFile(0), | 75 m_localFile(0), |
76 m_reply(0), | |
77 m_preferredContentType(preferredContentType), | 77 m_preferredContentType(preferredContentType), |
78 m_ok(false), | 78 m_ok(false), |
79 m_lastStatus(0), | 79 m_lastStatus(0), |
80 m_resource(fileOrUrl.startsWith(':')), | 80 m_resource(fileOrUrl.startsWith(':')), |
81 m_remote(isRemote(fileOrUrl)), | 81 m_remote(isRemote(fileOrUrl)), |
96 std::cerr << "FileSource::FileSource(" << fileOrUrl << "): url <" << m_url.toString() << ">" << std::endl; | 96 std::cerr << "FileSource::FileSource(" << fileOrUrl << "): url <" << m_url.toString() << ">" << std::endl; |
97 incCount(m_url.toString()); | 97 incCount(m_url.toString()); |
98 #endif | 98 #endif |
99 | 99 |
100 if (!canHandleScheme(m_url)) { | 100 if (!canHandleScheme(m_url)) { |
101 SVDEBUG << "FileSource::FileSource: ERROR: Unsupported scheme in URL \"" << m_url.toString() << "\"" << endl; | 101 std::cerr << "FileSource::FileSource: ERROR: Unsupported scheme in URL \"" << m_url.toString() << "\"" << std::endl; |
102 m_errorString = tr("Unsupported scheme in URL"); | 102 m_errorString = tr("Unsupported scheme in URL"); |
103 return; | 103 return; |
104 } | 104 } |
105 | 105 |
106 init(); | 106 init(); |
108 if (!isRemote() && | 108 if (!isRemote() && |
109 !isAvailable()) { | 109 !isAvailable()) { |
110 #ifdef DEBUG_FILE_SOURCE | 110 #ifdef DEBUG_FILE_SOURCE |
111 std::cerr << "FileSource::FileSource: Failed to open local file with URL \"" << m_url.toString() << "\"; trying again assuming filename was encoded" << std::endl; | 111 std::cerr << "FileSource::FileSource: Failed to open local file with URL \"" << m_url.toString() << "\"; trying again assuming filename was encoded" << std::endl; |
112 #endif | 112 #endif |
113 m_url = QUrl::fromEncoded(fileOrUrl.toAscii()); | 113 m_url = QUrl::fromEncoded(fileOrUrl.toLatin1()); |
114 init(); | 114 init(); |
115 } | 115 } |
116 | 116 |
117 if (isRemote() && | 117 if (isRemote() && |
118 (fileOrUrl.contains('%') || | 118 (fileOrUrl.contains('%') || |
136 // longer associating a filename with this url in the | 136 // longer associating a filename with this url in the |
137 // refcount map -- or createCacheFile will think we've | 137 // refcount map -- or createCacheFile will think we've |
138 // already done all the work and no request will be sent | 138 // already done all the work and no request will be sent |
139 deleteCacheFile(); | 139 deleteCacheFile(); |
140 | 140 |
141 m_url.setEncodedUrl(fileOrUrl.toAscii()); | 141 m_url = QUrl::fromEncoded(fileOrUrl.toLatin1()); |
142 | 142 |
143 m_ok = false; | 143 m_ok = false; |
144 m_done = false; | 144 m_done = false; |
145 m_lastStatus = 0; | 145 m_lastStatus = 0; |
146 init(); | 146 init(); |
151 emit statusAvailable(); | 151 emit statusAvailable(); |
152 emit ready(); | 152 emit ready(); |
153 } | 153 } |
154 | 154 |
155 #ifdef DEBUG_FILE_SOURCE | 155 #ifdef DEBUG_FILE_SOURCE |
156 SVDEBUG << "FileSource::FileSource(string) exiting" << endl; | 156 std::cerr << "FileSource::FileSource(string) exiting" << std::endl; |
157 #endif | 157 #endif |
158 } | 158 } |
159 | 159 |
160 FileSource::FileSource(QUrl url, ProgressReporter *reporter) : | 160 FileSource::FileSource(QUrl url, ProgressReporter *reporter) : |
161 m_url(url), | 161 m_url(url), |
162 m_ftp(0), | |
163 m_http(0), | |
164 m_localFile(0), | 162 m_localFile(0), |
163 m_reply(0), | |
165 m_ok(false), | 164 m_ok(false), |
166 m_lastStatus(0), | 165 m_lastStatus(0), |
167 m_resource(false), | 166 m_resource(false), |
168 m_remote(isRemote(url.toString())), | 167 m_remote(isRemote(url.toString())), |
169 m_done(false), | 168 m_done(false), |
170 m_leaveLocalFile(false), | 169 m_leaveLocalFile(false), |
171 m_reporter(reporter), | 170 m_reporter(reporter), |
172 m_refCounted(false) | 171 m_refCounted(false) |
173 { | 172 { |
174 #ifdef DEBUG_FILE_SOURCE | 173 #ifdef DEBUG_FILE_SOURCE |
175 SVDEBUG << "FileSource::FileSource(" << url.toString() << ") [as url]" << endl; | 174 std::cerr << "FileSource::FileSource(" << url.toString() << ") [as url]" << std::endl; |
176 incCount(m_url.toString()); | 175 incCount(m_url.toString()); |
177 #endif | 176 #endif |
178 | 177 |
179 if (!canHandleScheme(m_url)) { | 178 if (!canHandleScheme(m_url)) { |
180 SVDEBUG << "FileSource::FileSource: ERROR: Unsupported scheme in URL \"" << m_url.toString() << "\"" << endl; | 179 std::cerr << "FileSource::FileSource: ERROR: Unsupported scheme in URL \"" << m_url.toString() << "\"" << std::endl; |
181 m_errorString = tr("Unsupported scheme in URL"); | 180 m_errorString = tr("Unsupported scheme in URL"); |
182 return; | 181 return; |
183 } | 182 } |
184 | 183 |
185 init(); | 184 init(); |
186 | 185 |
187 #ifdef DEBUG_FILE_SOURCE | 186 #ifdef DEBUG_FILE_SOURCE |
188 SVDEBUG << "FileSource::FileSource(url) exiting" << endl; | 187 std::cerr << "FileSource::FileSource(url) exiting" << std::endl; |
189 #endif | 188 #endif |
190 } | 189 } |
191 | 190 |
192 FileSource::FileSource(const FileSource &rf) : | 191 FileSource::FileSource(const FileSource &rf) : |
193 QObject(), | 192 QObject(), |
194 m_url(rf.m_url), | 193 m_url(rf.m_url), |
195 m_ftp(0), | |
196 m_http(0), | |
197 m_localFile(0), | 194 m_localFile(0), |
195 m_reply(0), | |
198 m_ok(rf.m_ok), | 196 m_ok(rf.m_ok), |
199 m_lastStatus(rf.m_lastStatus), | 197 m_lastStatus(rf.m_lastStatus), |
200 m_resource(rf.m_resource), | 198 m_resource(rf.m_resource), |
201 m_remote(rf.m_remote), | 199 m_remote(rf.m_remote), |
202 m_done(false), | 200 m_done(false), |
203 m_leaveLocalFile(false), | 201 m_leaveLocalFile(false), |
204 m_reporter(rf.m_reporter), | 202 m_reporter(rf.m_reporter), |
205 m_refCounted(false) | 203 m_refCounted(false) |
206 { | 204 { |
207 #ifdef DEBUG_FILE_SOURCE | 205 #ifdef DEBUG_FILE_SOURCE |
208 SVDEBUG << "FileSource::FileSource(" << m_url.toString() << ") [copy ctor]" << endl; | 206 std::cerr << "FileSource::FileSource(" << m_url.toString() << ") [copy ctor]" << std::endl; |
209 incCount(m_url.toString()); | 207 incCount(m_url.toString()); |
210 #endif | 208 #endif |
211 | 209 |
212 if (!canHandleScheme(m_url)) { | 210 if (!canHandleScheme(m_url)) { |
213 SVDEBUG << "FileSource::FileSource: ERROR: Unsupported scheme in URL \"" << m_url.toString() << "\"" << endl; | 211 std::cerr << "FileSource::FileSource: ERROR: Unsupported scheme in URL \"" << m_url.toString() << "\"" << std::endl; |
214 m_errorString = tr("Unsupported scheme in URL"); | 212 m_errorString = tr("Unsupported scheme in URL"); |
215 return; | 213 return; |
216 } | 214 } |
217 | 215 |
218 if (!isRemote()) { | 216 if (!isRemote()) { |
219 m_localFilename = rf.m_localFilename; | 217 m_localFilename = rf.m_localFilename; |
220 } else { | 218 } else { |
221 QMutexLocker locker(&m_mapMutex); | 219 QMutexLocker locker(&m_mapMutex); |
222 #ifdef DEBUG_FILE_SOURCE | 220 #ifdef DEBUG_FILE_SOURCE |
223 SVDEBUG << "FileSource::FileSource(copy ctor): ref count is " | 221 std::cerr << "FileSource::FileSource(copy ctor): ref count is " |
224 << m_refCountMap[m_url] << endl; | 222 << m_refCountMap[m_url] << std::endl; |
225 #endif | 223 #endif |
226 if (m_refCountMap[m_url] > 0) { | 224 if (m_refCountMap[m_url] > 0) { |
227 m_refCountMap[m_url]++; | 225 m_refCountMap[m_url]++; |
228 #ifdef DEBUG_FILE_SOURCE | 226 #ifdef DEBUG_FILE_SOURCE |
229 std::cerr << "raised it to " << m_refCountMap[m_url] << std::endl; | 227 std::cerr << "raised it to " << m_refCountMap[m_url] << std::endl; |
237 } | 235 } |
238 | 236 |
239 m_done = true; | 237 m_done = true; |
240 | 238 |
241 #ifdef DEBUG_FILE_SOURCE | 239 #ifdef DEBUG_FILE_SOURCE |
242 SVDEBUG << "FileSource::FileSource(" << m_url.toString() << ") [copy ctor]: note: local filename is \"" << m_localFilename << "\"" << endl; | 240 std::cerr << "FileSource::FileSource(" << m_url.toString() << ") [copy ctor]: note: local filename is \"" << m_localFilename << "\"" << std::endl; |
243 #endif | 241 #endif |
244 | 242 |
245 #ifdef DEBUG_FILE_SOURCE | 243 #ifdef DEBUG_FILE_SOURCE |
246 SVDEBUG << "FileSource::FileSource(copy ctor) exiting" << endl; | 244 std::cerr << "FileSource::FileSource(copy ctor) exiting" << std::endl; |
247 #endif | 245 #endif |
248 } | 246 } |
249 | 247 |
250 FileSource::~FileSource() | 248 FileSource::~FileSource() |
251 { | 249 { |
378 #ifdef DEBUG_FILE_SOURCE | 376 #ifdef DEBUG_FILE_SOURCE |
379 std::cerr << "FileSource::init: Don't have local copy of \"" | 377 std::cerr << "FileSource::init: Don't have local copy of \"" |
380 << m_url.toString() << "\", retrieving" << std::endl; | 378 << m_url.toString() << "\", retrieving" << std::endl; |
381 #endif | 379 #endif |
382 | 380 |
383 if (scheme == "http") { | 381 if (scheme == "http" || scheme == "https" || scheme == "ftp") { |
384 initHttp(); | 382 initRemote(); |
385 #ifdef DEBUG_FILE_SOURCE | 383 #ifdef DEBUG_FILE_SOURCE |
386 std::cerr << "FileSource: initHttp succeeded" << std::endl; | 384 std::cerr << "FileSource: initRemote returned" << std::endl; |
387 #endif | 385 #endif |
388 } else if (scheme == "ftp") { | |
389 initFtp(); | |
390 } else { | 386 } else { |
391 m_remote = false; | 387 m_remote = false; |
392 m_ok = false; | 388 m_ok = false; |
393 } | 389 } |
394 } | 390 } |
428 } | 424 } |
429 } | 425 } |
430 } | 426 } |
431 | 427 |
432 void | 428 void |
433 FileSource::initHttp() | 429 FileSource::initRemote() |
434 { | 430 { |
435 m_ok = true; | 431 m_ok = true; |
436 int port = m_url.port(); | 432 |
437 m_http = new QHttp(m_url.host(), port < 0 ? 80 : port); | 433 QNetworkRequest req; |
438 connect(m_http, SIGNAL(done(bool)), this, SLOT(done(bool))); | 434 req.setUrl(m_url); |
439 connect(m_http, SIGNAL(dataReadProgress(int, int)), | 435 |
440 this, SLOT(dataReadProgress(int, int))); | 436 if (m_preferredContentType != "") { |
441 connect(m_http, SIGNAL(responseHeaderReceived(const QHttpResponseHeader &)), | |
442 this, SLOT(httpResponseHeaderReceived(const QHttpResponseHeader &))); | |
443 | |
444 // I don't quite understand this. url.path() returns a path | |
445 // without percent encoding; for example, spaces appear as | |
446 // literal spaces. This generally won't work if sent to the | |
447 // server directly. You can retrieve a correctly encoded URL | |
448 // from QUrl using url.toEncoded(), but that gives you the | |
449 // whole URL; there doesn't seem to be any way to retrieve | |
450 // only an encoded path. Furthermore there doesn't seem to be | |
451 // any way to convert a retrieved path into an encoded path | |
452 // without explicitly specifying that you don't want the path | |
453 // separators ("/") to be encoded. (Besides being painful to | |
454 // manage, I don't see how this can work correctly in any case | |
455 // where a percent-encoded "/" is supposed to appear within a | |
456 // path element?) There also seems to be no way to retrieve | |
457 // the path plus query string, i.e. everything that I need to | |
458 // send to the HTTP server. And no way for QHttp to take a | |
459 // QUrl argument. I'm obviously missing something. | |
460 | |
461 // So, two ways to do this: query the bits from the URL, | |
462 // encode them individually, and glue them back together | |
463 // again... | |
464 /* | |
465 QString path = QUrl::toPercentEncoding(m_url.path(), "/"); | |
466 QList<QPair<QString, QString> > query = m_url.queryItems(); | |
467 if (!query.empty()) { | |
468 QStringList q2; | |
469 for (QList<QPair<QString, QString> >::iterator i = query.begin(); | |
470 i != query.end(); ++i) { | |
471 q2.push_back(QString("%1=%3") | |
472 .arg(QString(QUrl::toPercentEncoding(i->first))) | |
473 .arg(QString(QUrl::toPercentEncoding(i->second)))); | |
474 } | |
475 path = QString("%1%2%3") | |
476 .arg(path).arg("?") | |
477 .arg(q2.join("&")); | |
478 } | |
479 */ | |
480 | |
481 // ...or, much simpler but relying on knowledge about the | |
482 // scheme://host/path/path/query etc format of the URL, we can | |
483 // get the whole URL ready-encoded and then split it on "/" as | |
484 // appropriate... | |
485 | |
486 QString path = "/" + QString(m_url.toEncoded()).section('/', 3); | |
487 | |
488 #ifdef DEBUG_FILE_SOURCE | |
489 SVDEBUG << "FileSource: path is \"" | |
490 << path << "\"" << endl; | |
491 #endif | |
492 | |
493 if (m_preferredContentType == "") { | |
494 m_http->get(path, m_localFile); | |
495 } else { | |
496 #ifdef DEBUG_FILE_SOURCE | 437 #ifdef DEBUG_FILE_SOURCE |
497 std::cerr << "FileSource: indicating preferred content type of \"" | 438 std::cerr << "FileSource: indicating preferred content type of \"" |
498 << m_preferredContentType << "\"" << std::endl; | 439 << m_preferredContentType << "\"" << std::endl; |
499 #endif | 440 #endif |
500 QHttpRequestHeader header("GET", path); | 441 req.setRawHeader |
501 header.setValue("Host", m_url.host()); | 442 ("Accept", |
502 header.setValue("Accept", QString("%1, */*").arg(m_preferredContentType)); | 443 QString("%1, */*").arg(m_preferredContentType).toLatin1()); |
503 m_http->request(header, 0, m_localFile); | 444 } |
504 } | 445 |
505 } | 446 m_reply = nm.get(req); |
506 | 447 |
507 void | 448 connect(m_reply, SIGNAL(readyRead()), |
508 FileSource::initFtp() | 449 this, SLOT(readyRead())); |
509 { | 450 connect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)), |
510 m_ok = true; | 451 this, SLOT(replyFailed(QNetworkReply::NetworkError))); |
511 m_ftp = new QFtp; | 452 connect(m_reply, SIGNAL(finished()), |
512 connect(m_ftp, SIGNAL(done(bool)), this, SLOT(done(bool))); | 453 this, SLOT(replyFinished())); |
513 connect(m_ftp, SIGNAL(commandFinished(int, bool)), | 454 connect(m_reply, SIGNAL(metadataChanged()), |
514 this, SLOT(ftpCommandFinished(int, bool))); | 455 this, SLOT(metadataChanged())); |
515 connect(m_ftp, SIGNAL(dataTransferProgress(qint64, qint64)), | 456 connect(m_reply, SIGNAL(downloadProgress(qint64, qint64)), |
516 this, SLOT(dataTransferProgress(qint64, qint64))); | 457 this, SLOT(downloadProgress(qint64, qint64))); |
517 m_ftp->connectToHost(m_url.host(), m_url.port(21)); | |
518 | |
519 QString username = m_url.userName(); | |
520 if (username == "") { | |
521 username = "anonymous"; | |
522 } | |
523 | |
524 QString password = m_url.password(); | |
525 if (password == "") { | |
526 password = QString("%1@%2").arg(getenv("USER")).arg(getenv("HOST")); | |
527 } | |
528 | |
529 m_ftp->login(username, password); | |
530 | |
531 QString dirpath = m_url.path().section('/', 0, -2); | |
532 QString filename = m_url.path().section('/', -1); | |
533 | |
534 if (dirpath == "") dirpath = "/"; | |
535 m_ftp->cd(dirpath); | |
536 m_ftp->get(filename, m_localFile); | |
537 } | 458 } |
538 | 459 |
539 void | 460 void |
540 FileSource::cleanup() | 461 FileSource::cleanup() |
541 { | 462 { |
542 if (m_done) { | 463 if (m_done) { |
543 delete m_localFile; // does not actually delete the file | 464 delete m_localFile; // does not actually delete the file |
544 m_localFile = 0; | 465 m_localFile = 0; |
545 } | 466 } |
546 m_done = true; | 467 m_done = true; |
547 if (m_http) { | 468 if (m_reply) { |
548 QHttp *h = m_http; | 469 QNetworkReply *r = m_reply; |
549 m_http = 0; | 470 m_reply = 0; |
550 h->abort(); | 471 r->abort(); |
551 h->deleteLater(); | 472 r->deleteLater(); |
552 } | |
553 if (m_ftp) { | |
554 QFtp *f = m_ftp; | |
555 m_ftp = 0; | |
556 f->abort(); | |
557 f->deleteLater(); | |
558 } | 473 } |
559 if (m_localFile) { | 474 if (m_localFile) { |
560 delete m_localFile; // does not actually delete the file | 475 delete m_localFile; // does not actually delete the file |
561 m_localFile = 0; | 476 m_localFile = 0; |
562 } | 477 } |
574 bool | 489 bool |
575 FileSource::canHandleScheme(QUrl url) | 490 FileSource::canHandleScheme(QUrl url) |
576 { | 491 { |
577 // Note that a "scheme" with length 1 is probably a DOS drive letter | 492 // Note that a "scheme" with length 1 is probably a DOS drive letter |
578 QString scheme = url.scheme().toLower(); | 493 QString scheme = url.scheme().toLower(); |
579 return (scheme == "http" || scheme == "ftp" || | 494 return (scheme == "http" || scheme == "https" || |
580 scheme == "file" || scheme == "qrc" || | 495 scheme == "ftp" || scheme == "file" || scheme == "qrc" || |
581 scheme == "" || scheme.length() == 1); | 496 scheme == "" || scheme.length() == 1); |
582 } | 497 } |
583 | 498 |
584 bool | 499 bool |
585 FileSource::isAvailable() | 500 FileSource::isAvailable() |
587 waitForStatus(); | 502 waitForStatus(); |
588 bool available = true; | 503 bool available = true; |
589 if (!m_ok) available = false; | 504 if (!m_ok) available = false; |
590 else available = (m_lastStatus / 100 == 2); | 505 else available = (m_lastStatus / 100 == 2); |
591 #ifdef DEBUG_FILE_SOURCE | 506 #ifdef DEBUG_FILE_SOURCE |
592 SVDEBUG << "FileSource::isAvailable: " << (available ? "yes" : "no") | 507 std::cerr << "FileSource::isAvailable: " << (available ? "yes" : "no") |
593 << endl; | 508 << std::endl; |
594 #endif | 509 #endif |
595 return available; | 510 return available; |
596 } | 511 } |
597 | 512 |
598 void | 513 void |
606 | 521 |
607 void | 522 void |
608 FileSource::waitForData() | 523 FileSource::waitForData() |
609 { | 524 { |
610 while (m_ok && !m_done) { | 525 while (m_ok && !m_done) { |
611 // SVDEBUG << "FileSource::waitForData: calling QApplication::processEvents" << endl; | 526 // std::cerr << "FileSource::waitForData: calling QApplication::processEvents" << std::endl; |
612 QCoreApplication::processEvents(); | 527 QCoreApplication::processEvents(); |
613 usleep(10000); | 528 usleep(10000); |
614 } | 529 } |
615 } | 530 } |
616 | 531 |
683 { | 598 { |
684 return m_errorString; | 599 return m_errorString; |
685 } | 600 } |
686 | 601 |
687 void | 602 void |
688 FileSource::dataReadProgress(int done, int total) | 603 FileSource::readyRead() |
689 { | 604 { |
690 dataTransferProgress(done, total); | 605 m_localFile->write(m_reply->readAll()); |
691 } | 606 } |
692 | 607 |
693 void | 608 void |
694 FileSource::httpResponseHeaderReceived(const QHttpResponseHeader &resp) | 609 FileSource::metadataChanged() |
695 { | 610 { |
696 #ifdef DEBUG_FILE_SOURCE | 611 #ifdef DEBUG_FILE_SOURCE |
697 SVDEBUG << "FileSource::httpResponseHeaderReceived" << endl; | 612 std::cerr << "FileSource::metadataChanged" << std::endl; |
698 #endif | 613 #endif |
699 | 614 |
700 if (resp.statusCode() / 100 == 3) { | 615 if (!m_reply) { |
701 QString location = resp.value("Location"); | 616 std::cerr << "WARNING: FileSource::metadataChanged() called without a reply object being known to us" << std::endl; |
702 #ifdef DEBUG_FILE_SOURCE | 617 return; |
703 SVDEBUG << "FileSource::responseHeaderReceived: redirect to \"" | 618 } |
704 << location << "\" received" << endl; | 619 |
620 int status = | |
621 m_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); | |
622 | |
623 if (status / 100 == 3) { | |
624 QString location = m_reply->header | |
625 (QNetworkRequest::LocationHeader).toString(); | |
626 #ifdef DEBUG_FILE_SOURCE | |
627 std::cerr << "FileSource::metadataChanged: redirect to \"" | |
628 << location << "\" received" << std::endl; | |
705 #endif | 629 #endif |
706 if (location != "") { | 630 if (location != "") { |
707 QUrl newUrl(location); | 631 QUrl newUrl(location); |
708 if (newUrl != m_url) { | 632 if (newUrl != m_url) { |
709 cleanup(); | 633 cleanup(); |
721 return; | 645 return; |
722 } | 646 } |
723 } | 647 } |
724 } | 648 } |
725 | 649 |
726 m_lastStatus = resp.statusCode(); | 650 m_lastStatus = status; |
727 if (m_lastStatus / 100 >= 4) { | 651 if (m_lastStatus / 100 >= 4) { |
728 m_errorString = QString("%1 %2") | 652 m_errorString = QString("%1 %2") |
729 .arg(resp.statusCode()).arg(resp.reasonPhrase()); | 653 .arg(status) |
730 #ifdef DEBUG_FILE_SOURCE | 654 .arg(m_reply->attribute |
731 SVDEBUG << "FileSource::responseHeaderReceived: " | 655 (QNetworkRequest::HttpReasonPhraseAttribute).toString()); |
732 << m_errorString << endl; | 656 #ifdef DEBUG_FILE_SOURCE |
657 std::cerr << "FileSource::metadataChanged: " | |
658 << m_errorString << std::endl; | |
733 #endif | 659 #endif |
734 } else { | 660 } else { |
735 #ifdef DEBUG_FILE_SOURCE | 661 #ifdef DEBUG_FILE_SOURCE |
736 SVDEBUG << "FileSource::responseHeaderReceived: " | 662 std::cerr << "FileSource::metadataChanged: " |
737 << m_lastStatus << endl; | 663 << m_lastStatus << std::endl; |
738 #endif | 664 #endif |
739 if (resp.hasContentType()) m_contentType = resp.contentType(); | 665 m_contentType = |
666 m_reply->header(QNetworkRequest::ContentTypeHeader).toString(); | |
740 } | 667 } |
741 emit statusAvailable(); | 668 emit statusAvailable(); |
742 } | 669 } |
743 | 670 |
744 void | 671 void |
745 FileSource::ftpCommandFinished(int id, bool error) | 672 FileSource::downloadProgress(qint64 done, qint64 total) |
746 { | |
747 #ifdef DEBUG_FILE_SOURCE | |
748 std::cerr << "FileSource::ftpCommandFinished(" << id << ", " << error << ")" << std::endl; | |
749 #endif | |
750 | |
751 if (!m_ftp) return; | |
752 | |
753 QFtp::Command command = m_ftp->currentCommand(); | |
754 | |
755 if (!error) { | |
756 #ifdef DEBUG_FILE_SOURCE | |
757 SVDEBUG << "FileSource::ftpCommandFinished: success for command " | |
758 << command << endl; | |
759 #endif | |
760 return; | |
761 } | |
762 | |
763 if (command == QFtp::ConnectToHost) { | |
764 m_errorString = tr("Failed to connect to FTP server"); | |
765 } else if (command == QFtp::Login) { | |
766 m_errorString = tr("Login failed"); | |
767 } else if (command == QFtp::Cd) { | |
768 m_errorString = tr("Failed to change to correct directory"); | |
769 } else if (command == QFtp::Get) { | |
770 m_errorString = tr("FTP download aborted"); | |
771 } | |
772 | |
773 m_lastStatus = 400; // for done() | |
774 } | |
775 | |
776 void | |
777 FileSource::dataTransferProgress(qint64 done, qint64 total) | |
778 { | 673 { |
779 int percent = int((double(done) / double(total)) * 100.0 - 0.1); | 674 int percent = int((double(done) / double(total)) * 100.0 - 0.1); |
780 emit progress(percent); | 675 emit progress(percent); |
781 } | 676 } |
782 | 677 |
789 m_ok = false; | 684 m_ok = false; |
790 m_errorString = tr("Download cancelled"); | 685 m_errorString = tr("Download cancelled"); |
791 } | 686 } |
792 | 687 |
793 void | 688 void |
794 FileSource::done(bool error) | 689 FileSource::replyFinished() |
795 { | 690 { |
796 emit progress(100); | 691 emit progress(100); |
797 | 692 |
798 #ifdef DEBUG_FILE_SOURCE | 693 #ifdef DEBUG_FILE_SOURCE |
799 std::cerr << "FileSource::done(" << error << ")" << std::endl; | 694 std::cerr << "FileSource::replyFinished()" << std::endl; |
800 #endif | 695 #endif |
801 | 696 |
802 if (m_done) return; | 697 if (m_done) return; |
803 | 698 |
804 if (error) { | 699 bool error = (m_lastStatus / 100 >= 4); |
805 if (m_http) { | |
806 m_errorString = m_http->errorString(); | |
807 } else if (m_ftp) { | |
808 m_errorString = m_ftp->errorString(); | |
809 } | |
810 } | |
811 | |
812 if (m_lastStatus / 100 >= 4) { | |
813 error = true; | |
814 } | |
815 | 700 |
816 cleanup(); | 701 cleanup(); |
817 | 702 |
818 if (!error) { | 703 if (!error) { |
819 QFileInfo fi(m_localFilename); | 704 QFileInfo fi(m_localFilename); |
841 | 726 |
842 void | 727 void |
843 FileSource::deleteCacheFile() | 728 FileSource::deleteCacheFile() |
844 { | 729 { |
845 #ifdef DEBUG_FILE_SOURCE | 730 #ifdef DEBUG_FILE_SOURCE |
846 SVDEBUG << "FileSource::deleteCacheFile(\"" << m_localFilename << "\")" << endl; | 731 std::cerr << "FileSource::deleteCacheFile(\"" << m_localFilename << "\")" << std::endl; |
847 #endif | 732 #endif |
848 | 733 |
849 cleanup(); | 734 cleanup(); |
850 | 735 |
851 if (m_localFilename == "") { | 736 if (m_localFilename == "") { |
882 #ifdef DEBUG_FILE_SOURCE | 767 #ifdef DEBUG_FILE_SOURCE |
883 std::cerr << "FileSource::deleteCacheFile: ERROR: Failed to delete file \"" << m_localFilename << "\"" << std::endl; | 768 std::cerr << "FileSource::deleteCacheFile: ERROR: Failed to delete file \"" << m_localFilename << "\"" << std::endl; |
884 #endif | 769 #endif |
885 } else { | 770 } else { |
886 #ifdef DEBUG_FILE_SOURCE | 771 #ifdef DEBUG_FILE_SOURCE |
887 SVDEBUG << "FileSource::deleteCacheFile: Deleted cache file \"" << m_localFilename << "\"" << endl; | 772 std::cerr << "FileSource::deleteCacheFile: Deleted cache file \"" << m_localFilename << "\"" << std::endl; |
888 #endif | 773 #endif |
889 m_localFilename = ""; | 774 m_localFilename = ""; |
890 } | 775 } |
891 | 776 |
892 m_fileCreationMutex.unlock(); | 777 m_fileCreationMutex.unlock(); |
899 { | 784 { |
900 { | 785 { |
901 QMutexLocker locker(&m_mapMutex); | 786 QMutexLocker locker(&m_mapMutex); |
902 | 787 |
903 #ifdef DEBUG_FILE_SOURCE | 788 #ifdef DEBUG_FILE_SOURCE |
904 SVDEBUG << "FileSource::createCacheFile: refcount is " << m_refCountMap[m_url] << endl; | 789 std::cerr << "FileSource::createCacheFile: refcount is " << m_refCountMap[m_url] << std::endl; |
905 #endif | 790 #endif |
906 | 791 |
907 if (m_refCountMap[m_url] > 0) { | 792 if (m_refCountMap[m_url] > 0) { |
908 m_refCountMap[m_url]++; | 793 m_refCountMap[m_url]++; |
909 m_localFilename = m_remoteLocalMap[m_url]; | 794 m_localFilename = m_remoteLocalMap[m_url]; |