📄 evasocket.cpp
字号:
HttpHeader::HttpHeader(const QByteArray &data) : m_HeaderLen(0), m_ContentLen(0), m_Username(""), m_Password(""), m_Base64AuthParam(""){ parseHeader(data);}bool HttpHeader::parseHeader(const QByteArray &data){ QCString buf(data); if (buf.left(strlen(HTTP_VERSION)) != HTTP_VERSION){ //kdDebug() << "[HttpHeader] Not a HTTP command return, but might be data packet" << endl; return false; } int index = buf.find(HTTP_HEADER_END); if(index == -1) return false; m_HeaderLen = index + 1 + 3;// index + 1 + strlen("\r\n\r\n") /* NOTE:we use QString here for easy parsing */ QString header = buf.left(index + 1); QStringList lines = QStringList::split(HTTP_NEW_LINE, header); QStringList::Iterator lineIt = lines.begin(); /* first line should be the return code */ QString ret = *(lineIt++); QStringList items = QStringList::split(" ", ret); if(items.count() != 3){ kdDebug() << "[HttpHeader] Http header unknown: " << ret << endl; return false; } QStringList::Iterator itemIt = items.begin(); setMetaData(HTTP_REPLY_CODE, *(++itemIt)); for( ; lineIt != lines.end(); ++lineIt){ ret = *lineIt; QStringList items = QStringList::split(": ", ret); if(items.count() == 2){ if(items[0] == HTTP_SET_COOKIE){ QStringList cookies = QStringList::split(":", items[1]); m_Cookies[cookies[0]] = cookies[1]; } else { setMetaData(items[0], items[1]); } } else { kdDebug() << "[HttpHeader] line contains different parts" << ret << endl; } } return true;}const QCString HttpHeader::toCString(){ return "GET /forum/ HTTP/1.1\r\nHost: www.myswear.net\r\nUser-Agent: Eva 0.4.2\r\nAccept: */*\r\nConnection: Keep-Alive\r\n\r\n";}QCString HttpHeader::getProxyConnectHeader( const QString &destHost, const unsigned short port, const bool needAuth){ QCString buf; QTextStream stream(buf, IO_WriteOnly); stream << HTTP_CONNECT << " " << (destHost + ":" + QString::number(port)) << " " << HTTP_VERSION << HTTP_NEW_LINE; if(needAuth){ stream << HTTP_PROXY_BASIC; if(m_Base64AuthParam.isEmpty()){ stream << (QCodecs::base64Encode( (m_Username + ":" + m_Password).local8Bit())); } else stream << m_Base64AuthParam; stream << HTTP_NEW_LINE; } stream << HTTP_ACCEPT_ALL << HTTP_NEW_LINE; stream << HTTP_CONTENT_TYPE << ": text/html" << HTTP_NEW_LINE; stream << HTTP_PROXY_CONNECTION << ":" << HTTP_KEEP_ALIVE << HTTP_NEW_LINE; stream << HTTP_CONTENT_LENGTH << ": 0" << HTTP_NEW_LINE; stream << HTTP_NEW_LINE; return buf;}QCString HttpHeader::getCmdGetHeader(const bool useProxy, const bool needAuth){ QString buf; QTextStream stream(buf, IO_WriteOnly); stream << HTTP_CMD_GET << " "; if(useProxy){ stream << "http://" << getMetaData(HTTP_HOST); } stream << getMetaData(HTTP_CMD_GET) << " " << HTTP_VERSION << HTTP_NEW_LINE; stream << HTTP_HOST << ": " << getMetaData(HTTP_HOST) << HTTP_NEW_LINE; if(needAuth){ stream << HTTP_PROXY_BASIC; if(m_Base64AuthParam.isEmpty()){ stream << (QCodecs::base64Encode( (m_Username + ":" + m_Password).local8Bit())); } else stream << m_Base64AuthParam; stream << HTTP_NEW_LINE; } stream << HTTP_USER_AGENT << ": " << HTTP_DEFAULT_AGENT << HTTP_NEW_LINE; stream << HTTP_ACCEPT_ALL << HTTP_NEW_LINE; stream << HTTP_ACCEPT_LANGUAGE << ": " << HTTP_ACCEPT_DEFAULT_LANG << HTTP_NEW_LINE; stream << HTTP_ACCEPT_ENCODING << ": " << HTTP_ACCEPT_DEFAULT_ENCODE << HTTP_NEW_LINE; stream << HTTP_ACCEPT_CHARSET << ": " << HTTP_ACCEPT_DEFAULT_CHARSET << HTTP_NEW_LINE; stream << HTTP_KEEP_ALIVE << ": 300" << HTTP_NEW_LINE; if(useProxy) stream << HTTP_PROXY_CONNECTION << ": " << QString(HTTP_KEEP_ALIVE).lower() << HTTP_NEW_LINE; else stream << HTTP_CONNECTION << ": " << QString(HTTP_KEEP_ALIVE).lower() << HTTP_NEW_LINE; if(m_Cookies.count()){ stream << HTTP_COOKIE << ": "; QMap<QString, QString>::Iterator it; for( it = m_Cookies.begin(); it != m_Cookies.end(); ++it){ if(it != m_Cookies.begin()){ stream << "; "; } stream << it.key() << "=" << it.data(); } stream << HTTP_NEW_LINE; } stream << HTTP_NEW_LINE; return buf.latin1();}void HttpHeader::setCookie(const QString &name, const QString &value){ m_Cookies[name] = value;}void HttpHeader::setGetURI(const QString &uri){ setMetaData(HTTP_CMD_GET, uri);}void HttpHeader::setHost(const QString &host){ setMetaData(HTTP_HOST, host);}void HttpHeader::setAuthInfo(const QString &user, const QString &password){ m_Username = user; m_Password = password;}void HttpHeader::setBase64AuthParam( const QCString & param ){ m_Base64AuthParam = param;}const QString HttpHeader::getReplyCode() const{ return getMetaData(HTTP_REPLY_CODE);}const QMap<QString, QString> &HttpHeader::getCookies() const{ return m_Cookies;}const QString HttpHeader::getCookie(const QString &name) const{ return m_Cookies[name];}const unsigned int HttpHeader::getContentLength() { QString strLen = getMetaData(HTTP_CONTENT_LENGTH); bool ok = false; int len = strLen.toUInt(&ok); if(ok) return len; else return 0;}const unsigned int HttpHeader::getHeaderLength() const{ return m_HeaderLen;}const unsigned int HttpHeader::getContentsOffset() const{ return m_HeaderLen;}void HttpHeader::setMetaData(const QString &field, const QString &value){ m_Fields[field.lower()] = value;}const QString HttpHeader::getMetaData(const QString &field) const{ return m_Fields[field.lower()];}/** ============================================================== **/EvaHttp::EvaHttp( const QString & host, const unsigned short port ) : EvaSocket(host, port, EvaSocket::TCP), m_UseProxy(false), m_NeedAuth(false), m_IsProxyReady(false), m_ProxyHost(""), m_ProxyPort(8080), m_Host(host), m_Port(port), m_IODevice(0), m_BytesReceived(0){ m_Header.setHost(m_Host); QObject::connect(this, SIGNAL(isReady()), SLOT(tcpReady())); QObject::connect(this, SIGNAL(writeReady()), SLOT(slotWriteReady())); QObject::connect(this, SIGNAL(receivedData(int)), SLOT(parseData(int)));}void EvaHttp::setHost(const QString &host, const unsigned short port){ m_Host = host; m_Port = port; m_Header.setHost(m_Host);}void EvaHttp::setProxyServer( const QString & host, unsigned short port ){ if(host.isEmpty()) return; m_IsProxyReady = false; m_UseProxy = true; m_ProxyHost = host; m_ProxyPort = port;}void EvaHttp::setProxyAuthInfo( const QString & username, const QString & password ){ if(username.isEmpty() || password.isEmpty()) return; //kdDebug() << "[EvaHttp] u:" << username << ", p" << password << endl; m_IsProxyReady = false; m_NeedAuth = true; m_Header.setAuthInfo(username, password);}void EvaHttp::setBase64AuthParam( const QCString & param ){ if(param.isEmpty()) return; m_IsProxyReady = false; m_NeedAuth = true; m_Header.setBase64AuthParam( param);}void EvaHttp::get( const QString & path, QIODevice * to ){ m_BytesReceived = 0; m_IODevice = to; if(path.startsWith("/")){ m_Header.setGetURI(path); } else{ QUrl url(path); if(!url.isValid()){ kdDebug() << "[EvaHttp] uri of get is malformed" << endl; emit requestFinished(true); return; } else { //kdDebug() << "[EvaHttp] set host " << url.host() << endl; QString p; if(path.startsWith("http://")) p = path.right( path.length() - 7); //get rid of "http://" setHost( url.host()); QString rest = p.right( p.length() - p.find("/")); m_Header.setGetURI(rest); } } if(!m_UseProxy) startDnsLookup(m_Host); else{ EvaSocket::setHost(QHostAddress(m_ProxyHost), m_ProxyPort); startConnecting(); }}void EvaHttp::tcpReady( ){ QCString toSend; if(m_UseProxy){ toSend = m_Header.getCmdGetHeader(true, m_NeedAuth); //kdDebug() << "[EvaHttp] ("<< toSend.length() << ") connecting to proxy:\r\n" << endl; }else{ toSend = m_Header.getCmdGetHeader(); //kdDebug() << ("[EvaHttp] sending GET command:\r\n" + toSend) << endl; } write(toSend.data(), toSend.length());}void EvaHttp::slotWriteReady( ){}void EvaHttp::parseData( int len ){ //kdDebug() << "[EvaHttp] data comes (" << len << ")" << endl; char *readBuffer = new char[len]; if(!read(readBuffer, len)){ kdDebug() << "[EvaHttp] read data error" << endl; closeConnection(); emit requestFinished(true); return; } if(m_BytesReceived && (m_BytesReceived >= m_Header.getContentLength())) return; QByteArray buf; buf.setRawData(readBuffer, len); //kdDebug() << "[EvaHttp] raw data:\n" << buf << endl; if(m_Header.parseHeader(buf)){ bool ok = false; int replyCode = m_Header.getReplyCode().toInt(&ok); if(!ok){ kdDebug() << "[EvaHttp] Http reply code error" << endl; closeConnection(); emit requestFinished(true); return; } switch(replyCode){ case 200: if(m_UseProxy && !m_IsProxyReady){ m_IsProxyReady = true; QCString toSend = m_Header.getCmdGetHeader(); write(toSend.data(), toSend.length()); }else{ // do nothing, just wait for the contents } break; case 407: //Proxy Authentication Required kdDebug() << "[EvaHttp] Http reply code 407 (Proxy Authentication Required)" << endl; closeConnection(); emit requestFinished(true); break; case 501: // "Not Support" case 502: // "Proxy Error" default: kdDebug() << "[EvaHttp] Http reply code error" << endl; closeConnection(); emit requestFinished(true); break; } //kdDebug() << "[EvaHttp] Received:\n" << buf.data() << endl; //kdDebug() << "[EvaHttp] " << len << " bytes, reply:"<< replyCode <<",HeaderLen:"<< m_Header.getHeaderLength() // << ", contentsLength:"<<m_Header.getContentLength() << endl; if(len > (int)(m_Header.getHeaderLength())){ m_BytesReceived = len - m_Header.getHeaderLength(); int ret = m_IODevice->writeBlock(buf.data() + m_Header.getContentsOffset(), m_BytesReceived); if(ret == -1 || ret != m_BytesReceived ){ kdDebug() << "[EvaHttp] write error" << endl; closeConnection(); emit requestFinished(true); return; } if(m_BytesReceived == m_Header.getContentLength()) emit requestFinished(false); // now we done!!! } }else{ int bytesToWrite = len; if( (m_Header.getContentLength() - m_BytesReceived) < len){ bytesToWrite = m_Header.getContentLength() - m_BytesReceived; m_BytesReceived = m_Header.getContentLength(); }else m_BytesReceived += len; if(!m_IODevice){ emit readReady(); }else{ int ret = m_IODevice->writeBlock(buf.data(), bytesToWrite); if(ret == -1){ kdDebug() << "[EvaHttp] write error" << endl; closeConnection(); emit requestFinished(true); return; } if(m_BytesReceived == m_Header.getContentLength()){ //kdDebug() << "[EvaHttp] request Done!" << endl; emit requestFinished(false); // now we done!!! } } }}void EvaHttp::startDnsLookup( const QString & host ){ //kdDebug() << "{EvaHttp} looking for IP of " << host << endl; // host should be a URL string QDns * dns = new QDns(host, QDns::A); QObject::connect(dns, SIGNAL(resultsReady()), this, SLOT(getResultsSlot()));}void EvaHttp::getResultsSlot( ){ QDns *dns = (QDns *)(QObject::sender()); if(dns == 0 ){ kdDebug() << "[EvaHttp] Dns lookup error" << endl; emit requestFinished(true); return; } QValueList<QHostAddress> list = dns->addresses(); if(list.count() == 0 ){ kdDebug() << "[EvaHttp] Dns lookup error - no address" << endl; emit requestFinished(true); return; } QHostAddress addr = list[0]; EvaSocket::setHost(addr, m_Port); //kdDebug() << "{EvaHttp] DNS ready" << endl; startConnecting();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -