|
MythTV
0.26-pre
|
00001 // -*- Mode: c++ -*- 00002 // Copyright (c) 2008, Daniel Thor Kristjansson 00003 // Licensed under the GPL v2 or later, see COPYING for details 00004 00005 // Qt headers 00006 #include <QHttp> 00007 00008 // Myth headers 00009 #include "mythhttphandler.h" 00010 #include "mythhttppool.h" 00011 #include "mythlogging.h" 00012 00013 #define LOC QString("MythHttpHandler: ") 00014 00015 const uint MythHttpHandler::kMaxRedirectCount = 32; 00016 00017 MythHttpHandler::MythHttpHandler(MythHttpPool *pool) : 00018 m_pool(pool), m_qhttp(new QHttp()) 00019 { 00020 connect(m_qhttp, SIGNAL(done(bool)), 00021 this, SLOT(Done(bool))); 00022 connect(m_qhttp, SIGNAL(requestFinished(int,bool)), 00023 this, SLOT(RequestFinished(int,bool))); 00024 connect(m_qhttp, SIGNAL(requestStarted(int)), 00025 this, SLOT(RequestStarted(int))); 00026 connect(m_qhttp, SIGNAL(stateChanged(int)), 00027 this, SLOT(StateChanged(int))); 00028 connect(m_qhttp, SIGNAL(responseHeaderReceived(const QHttpResponseHeader&)), 00029 this, SLOT(ResponseHeaderReceived(const QHttpResponseHeader&))); 00030 } 00031 00032 void MythHttpHandler::TeardownAll(void) 00033 { 00034 QMutexLocker locker(&m_lock); 00035 00036 if (m_qhttp) 00037 { 00038 m_qhttp->abort(); 00039 m_qhttp->disconnect(); 00040 m_qhttp->deleteLater(); 00041 } 00042 m_pool = NULL; 00043 m_qhttp = NULL; 00044 } 00045 00046 bool MythHttpHandler::HasPendingRequests(void) const 00047 { 00048 QMutexLocker locker(&m_lock); 00049 return (m_qhttp->hasPendingRequests() || 00050 m_qhttp->currentRequest().isValid() || 00051 !m_urls.empty()); 00052 } 00053 00054 void MythHttpHandler::AddUrlRequest(const QUrl &url) 00055 { 00056 QMutexLocker locker(&m_lock); 00057 00058 LOG(VB_NETWORK, LOG_DEBUG, LOC + 00059 QString("AddUrlRequest(%1)").arg(url.toString())); 00060 00061 if (!m_qhttp->hasPendingRequests() && !m_qhttp->currentRequest().isValid()) 00062 Get(url); 00063 else 00064 m_urls.push_back(url); 00065 } 00066 00067 void MythHttpHandler::Get(const QUrl &url) 00068 { 00069 LOG(VB_NETWORK, LOG_DEBUG, LOC + QString("Get(%1)").arg(url.toString())); 00070 00071 m_cur_url = url; 00072 m_cur_status_id = 0; 00073 m_cur_status_str = QString::null; 00074 m_cur_redirect_cnt = 0; 00075 00076 QHttp::ConnectionMode mode = 00077 m_cur_url.scheme().toLower() == "https" ? QHttp::ConnectionModeHttps : 00078 QHttp::ConnectionModeHttp; 00079 m_qhttp->setHost(m_cur_url.host(), mode, 00080 m_cur_url.port() == -1 ? 0 : m_cur_url.port()); 00081 00082 if (!m_cur_url.userName().isEmpty()) 00083 m_qhttp->setUser(m_cur_url.userName(), m_cur_url.password()); 00084 00085 QByteArray path = QUrl::toPercentEncoding(m_cur_url.path(), "!$&'()*+,;=:@/"); 00086 if (path.isEmpty()) 00087 path = "/"; 00088 00089 if (m_cur_url.hasQuery()) 00090 path += "?" + m_cur_url.encodedQuery(); 00091 00092 m_cur_get_id = m_qhttp->get(path); 00093 } 00094 00095 void MythHttpHandler::RemoveUrlRequest(const QUrl &url) 00096 { 00097 QMutexLocker locker(&m_lock); 00098 00099 UrlQueue urls = m_urls; 00100 m_urls.clear(); 00101 while (!urls.empty()) 00102 { 00103 QUrl item = urls.front(); 00104 urls.pop_front(); 00105 if (item != url) 00106 m_urls.push_back(item); 00107 } 00108 00109 if (url == m_cur_url) 00110 { 00111 m_cur_url = QUrl(); 00112 m_cur_status_id = 0; 00113 m_cur_status_str = QString::null; 00114 m_cur_redirect_cnt = 0; 00115 m_cur_get_id = 0; 00116 m_qhttp->abort(); 00117 } 00118 } 00119 00120 void MythHttpHandler::Done(bool error) 00121 { 00122 QMutexLocker locker(&m_lock); 00123 00124 LOG(VB_NETWORK, LOG_DEBUG, LOC + QString("Done(%1) url: %2") 00125 .arg(error).arg(m_cur_url.toString())); 00126 00127 if (m_pool) 00128 m_pool->Done(m_cur_url.host(), this); 00129 } 00130 00131 void MythHttpHandler::ResponseHeaderReceived(const QHttpResponseHeader &resp) 00132 { 00133 QMutexLocker locker(&m_lock); 00134 00135 LOG(VB_NETWORK, LOG_DEBUG, LOC + 00136 QString("ResponseHeaderReceived(%1,%2) url: %3") 00137 .arg(resp.statusCode()).arg(resp.reasonPhrase()) 00138 .arg(m_cur_url.toString())); 00139 m_cur_status_id = resp.statusCode(); 00140 m_cur_status_str = resp.reasonPhrase(); 00141 } 00142 00143 static QString extract_url(const QString &text) 00144 { 00145 QString url = text; 00146 static QMutex lock; 00147 static QRegExp aTagExp("<a.*href.*=.*>", Qt::CaseInsensitive); 00148 static QRegExp httpEndExp("\"|\\s|\'"); 00149 00150 QMutexLocker locker(&lock); 00151 00152 int a_tag = url.indexOf(aTagExp); 00153 if (a_tag >= 0) 00154 { 00155 url = url.mid(a_tag+1); 00156 url = url.left(url.indexOf(">")); 00157 url = url.mid(url.indexOf("href", Qt::CaseInsensitive) + 4); 00158 url = url.mid(url.indexOf("=") + 1); 00159 url = url.trimmed(); 00160 if ((url.size()>=2) && url[0] == QChar('"')) 00161 { 00162 url = url.mid(1); 00163 if (url[url.length()-1] == QChar('"')) 00164 url = url.left(url.length()-1); 00165 } 00166 if ((url.size()>=2) && url[0] == QChar('\'')) 00167 { 00168 url = url.mid(1); 00169 if (url[url.length()-1] == QChar('\'')) 00170 url = url.left(url.length()-1); 00171 } 00172 return url; 00173 } 00174 00175 int http = url.indexOf("http:"); 00176 if (http >= 0) 00177 { 00178 url = url.mid(http); 00179 int end_http = url.indexOf(httpEndExp); 00180 url = url.left(end_http); 00181 return url; 00182 } 00183 00184 return QString::null; 00185 } 00186 00187 void MythHttpHandler::RequestFinished(int id, bool error) 00188 { 00189 QMutexLocker locker(&m_lock); 00190 00191 LOG(VB_NETWORK, LOG_DEBUG, LOC + QString("RequestFinished(%1,%2) url: %3") 00192 .arg(id).arg(error).arg(m_cur_url.toString())); 00193 if (error && m_pool) 00194 { 00195 m_pool->Update(m_qhttp->error(), m_qhttp->errorString(), 00196 m_cur_url, 00197 m_cur_status_id, m_cur_status_str, QByteArray()); 00198 } 00199 else if ((id == m_cur_get_id) && m_pool) 00200 { 00201 if ((307 == m_cur_status_id) || // temporary move.. 00202 (303 == m_cur_status_id) || // move.. MUST use get 00203 (302 == m_cur_status_id) || // temporary move.. 00204 (301 == m_cur_status_id)) // permanent move.. 00205 { 00206 m_cur_status_id = 0; 00207 QString urlStr = extract_url(QString(m_qhttp->readAll())); 00208 if (!urlStr.isEmpty() && m_cur_redirect_cnt < kMaxRedirectCount) 00209 { 00210 m_cur_redirect_cnt++; 00211 QUrl url = QUrl(urlStr); 00212 m_qhttp->setHost(url.host()); 00213 QString path = url.path().isEmpty() ? "/" : url.path(); 00214 m_cur_get_id = m_qhttp->get(path); 00215 return; 00216 } 00217 } 00218 00219 m_pool->Update(QHttp::NoError, QString::null, 00220 m_cur_url, 00221 m_cur_status_id, m_cur_status_str, 00222 m_qhttp->readAll()); 00223 } 00224 else 00225 return; 00226 00227 if (!m_urls.empty()) 00228 { 00229 Get(m_urls.front()); 00230 m_urls.pop_front(); 00231 } 00232 } 00233 00234 void MythHttpHandler::RequestStarted(int id) 00235 { 00236 QMutexLocker locker(&m_lock); 00237 00238 LOG(VB_NETWORK, LOG_DEBUG, LOC + QString("RequestStarted(%1) url: %2") 00239 .arg(id).arg(m_cur_url.toString())); 00240 } 00241 00242 void MythHttpHandler::StateChanged(int state) 00243 { 00244 QMutexLocker locker(&m_lock); 00245 00246 LOG(VB_NETWORK, LOG_DEBUG, LOC + QString("StateChanged(%1) url: %2") 00247 .arg(state).arg(m_cur_url.toString())); 00248 } 00249
1.7.6.1