📄 http.cc
字号:
} if( !disposition.isEmpty() ) { kdDebug(7113) << "(" << getpid() << ") Setting Content-Disposition metadata to: " << disposition << endl; setMetaData("content-disposition", disposition); } // Let the app know about the mime-type iff this is not // a redirection and the mime-type string is not empty. if (locationStr.isEmpty() && (!m_strMimeType.isEmpty() || m_request.method == HTTP_HEAD)) { kdDebug(7113) << "(" << getpid() << ") Emitting mimetype " << m_strMimeType << endl; mimeType( m_strMimeType ); } if (m_request.method == HTTP_HEAD) return true; if (!m_lastModified.isEmpty()) setMetaData("modified", m_lastModified); if (!mayCache) setMetaData("no-cache", "true"); // Do we want to cache this request? if ( m_bCachedWrite && !m_strMimeType.isEmpty() ) { // Check... createCacheEntry(m_strMimeType, expireDate); // Create a cache entry if (!m_fcache) m_bCachedWrite = false; // Error creating cache entry. m_expireDate = expireDate; } if (m_bCachedWrite && !m_strMimeType.isEmpty()) kdDebug(7113) << "(" << getpid() << ") Cache, adding \"" << m_request.url.url() << "\"" << endl; else if (m_bCachedWrite && m_strMimeType.isEmpty()) kdDebug(7113) << "(" << getpid() << ") Cache, pending \"" << m_request.url.url() << "\"" << endl; else kdDebug(7113) << "(" << getpid() << ") Cache, not adding \"" << m_request.url.url() << "\"" << endl; return true;}void HTTPProtocol::addEncoding(QString encoding, QStringList &encs){ encoding = encoding.stripWhiteSpace().lower(); // Identity is the same as no encoding if (encoding == "identity") { return; } else if (encoding == "8bit") { // Strange encoding returned by http://linac.ikp.physik.tu-darmstadt.de return; } else if (encoding == "chunked") { m_bChunked = true; // Anyone know of a better way to handle unknown sizes possibly/ideally with unsigned ints? //if ( m_cmd != CMD_COPY ) m_iSize = -1; } else if ((encoding == "x-gzip") || (encoding == "gzip")) { encs.append(QString::fromLatin1("gzip")); } else if ((encoding == "x-bzip2") || (encoding == "bzip2")) { encs.append(QString::fromLatin1("bzip2")); // Not yet supported! } else if ((encoding == "x-deflate") || (encoding == "deflate")) { encs.append(QString::fromLatin1("deflate")); } else { kdWarning(7113) << "(" << getpid() << ") Unknown encoding encountered. Please write code. " "pid = (" << getpid() << ") Encoding = \"" << encoding << "\"" << endl; }}bool HTTPProtocol::sendBody(){ int result=-1; int length=0; // Loop until we got 'dataEnd' kdDebug(7113) << "(" << getpid() << ") Response code: " << m_responseCode << endl; if ( m_responseCode == 401 || m_responseCode == 407 ) { // For RE-POST on authentication failure the // buffer should not be empty... if ( m_bufPOST.isNull() ) { error( ERR_ABORTED, m_request.hostname ); return false; } kdDebug(7113) << "(" << getpid() << ") POST'ing saved data..." << endl; length = m_bufPOST.size(); result = 0; } else { kdDebug(7113) << "(" << getpid() << ") POST'ing live data..." << endl; m_bufPOST.resize(0); QByteArray buffer; int old_size; do { dataReq(); // Request for data result = readData( buffer ); if ( result > 0 ) { length += result; old_size = m_bufPOST.size(); m_bufPOST.resize( old_size+result ); memcpy( m_bufPOST.data()+ old_size, buffer.data(), buffer.size() ); buffer.resize(0); } } while ( result > 0 ); } if ( result != 0 ) { error( ERR_ABORTED, m_request.hostname ); return false; } char c_buffer[64]; sprintf(c_buffer, "Content-Length: %d\r\n\r\n", length); kdDebug( 7113 ) << c_buffer << endl; // Send the content length... bool sendOk = (write(c_buffer, strlen(c_buffer)) == (ssize_t) strlen(c_buffer)); if (!sendOk) { kdDebug(7113) << "(" << getpid() << ") Connection broken when sending content length: (" << m_state.hostname << ")" << endl; error( ERR_CONNECTION_BROKEN, m_state.hostname ); return false; } // Send the data... sendOk = (write(m_bufPOST.data(), m_bufPOST.size()) == (ssize_t) m_bufPOST.size()); if (!sendOk) { kdDebug(7113) << "(" << getpid() << ") Connection broken when sending message body: (" << m_state.hostname << ")" << endl; error( ERR_CONNECTION_BROKEN, m_state.hostname ); return false; } return true;}void HTTPProtocol::http_close(){ if (m_fcache) { fclose(m_fcache); m_fcache = 0; if (m_bCachedWrite) { QString filename = m_state.cef + ".new"; unlink( filename.latin1() ); } } if (!m_bKeepAlive) http_closeConnection(); else kdDebug(7113) << "(" << getpid() << ") http_close: keep alive" << endl;}void HTTPProtocol::closeConnection(){ http_closeConnection();}void HTTPProtocol::http_closeConnection(){ kdDebug(7113) << "(" << getpid() << ") http_closeConnection: closing (" << getpid() << ")" << endl; m_bKeepAlive = false; // Just in case. CloseDescriptor();}void HTTPProtocol::slave_status(){ bool connected = isConnectionValid(); if ( !connected && m_iSock != -1 ) http_closeConnection(); slaveStatus( m_state.hostname, connected );}void HTTPProtocol::buildURL(){ m_request.url.setProtocol( m_protocol ); m_request.url.setUser( m_request.user ); m_request.url.setPass( m_request.passwd ); m_request.url.setHost( m_request.hostname ); m_request.url.setPort( m_request.port ); m_request.url.setPath( m_request.path ); if (m_request.query.length()) m_request.url.setQuery( m_request.query );}void HTTPProtocol::mimetype( const KURL& url ){ if ( !checkRequestURL( url ) ) return; kdDebug(7113) << "(" << getpid() << ") HTTPProtocol::mimetype " << url.prettyURL() << endl; m_request.method = HTTP_HEAD; m_request.path = url.path(); m_request.query = url.query(); m_request.cache = CC_Cache; m_request.offset = 0; m_request.doProxy = m_bUseProxy; m_request.url = url; retrieveHeader(); kdDebug(7113) << "(" << getpid() << ") http: mimetype = " << m_strMimeType << endl;}void HTTPProtocol::special( const QByteArray &data){ int tmp; QDataStream stream(data, IO_ReadOnly); stream >> tmp; switch (tmp) { case 1: // HTTP POST { KURL url; stream >> url; post( url ); break; } case 2: // cache_update { KURL url; bool no_cache; time_t expireDate; stream >> url >> no_cache >> expireDate; cache_update( url, no_cache, expireDate ); break; } default: // Some command we don't understand. // Just ignore it, it may come from some future version of KDE. break; }}void HTTPProtocol::decodeDeflate(){#ifdef DO_GZIP // Okay the code below can probably be replaced with // a single call to decompress(...) instead of a read/write // to and from a temporary file, but I was not sure of how to // estimate the size of the decompressed data which needs to be // passed as a parameter to decompress function call. Anyone // want to try this approach or have a better experience with // the cool zlib library ??? (DA) // // TODO: Neither deflate nor gzip completely check for errors!!! z_stream z; QByteArray tmp_buf; const unsigned int max_len = 1024; unsigned char in_buf[max_len]; // next_in unsigned char out_buf[max_len]; // next_out int status = Z_OK; //status of the deflation char* filename=strdup("/tmp/kio_http.XXXXXX"); z.avail_in = 0; z.avail_out = max_len; z.next_out = out_buf; // Create the file int fd = mkstemp(filename); // TODO: Need sanity check here. Doing no error checking when writing // to HD cannot be good :)) What if the target is bloody full or it // for some reason could not be written to ?? (DA) ::write(fd, m_bufEncodedData.data(), m_bufEncodedData.size()); // Write data into file lseek(fd, 0, SEEK_SET); FILE* fin = fdopen( fd, "rb" ); // Read back and decompress data. for( ; ; ) { if( z.avail_in == 0 ) { z.next_in = in_buf; z.avail_in = ::fread(in_buf, 1, max_len, fin ); } if( z.avail_in == 0 ) break; status = inflate( &z, Z_NO_FLUSH ); if( status != Z_OK ) break; unsigned int count = max_len - z.avail_out; if( count ) { unsigned int old_len = tmp_buf.size(); memcpy( tmp_buf.data() + old_len, out_buf, count ); z.next_out = out_buf; z.avail_out = max_len; } } for( ; ; ) { status = inflate( &z, Z_FINISH ); unsigned int count = max_len - z.avail_out; if ( count ) { unsigned int old_len = tmp_buf.size(); // Copy the data into a temporary buffer memcpy( tmp_buf.data() + old_len, out_buf, count ); z.next_out = out_buf; z.avail_out = max_len; } if( status != Z_OK ) break; } if( fin ) ::fclose( fin ); ::unlink(filename); // Bye bye to beloved temp file. We will miss you!! // Replace m_bufEncodedData with the // "decoded" data. m_bufEncodedData.resize(0); m_bufEncodedData = tmp_buf; m_bufEncodedData.detach(); free( filename );#endif}void HTTPProtocol::decodeGzip(){#ifdef DO_GZIP // Note I haven't found an implementation // that correctly handles this stuff. Apache // sends both Transfer-Encoding and Content-Length // headers, which is a no-no because the content // could really be bigger than the content-length // header implies.. like with gzip. // eek. This is no fun for progress indicators. QByteArray ar; char tmp_buf[1024], *filename=strdup("/tmp/kio_http.XXXXXX"); signed long len; int fd; // Siince I can't figure out how to do the mem to mem // gunzipping, this should suffice. It just writes out // the gzip'd data to a file. fd=mkstemp(filename); ::write(fd, m_bufEncodedData.data(), m_bufEncodedData.size()); lseek(fd, 0, SEEK_SET); gzFile gzf = gzdopen(fd, "rb"); unlink(filename); // If you want to inspect the raw data, comment this line out // And then reads it back in with gzread so it'll // decompress on the fly. while ( (len=gzread(gzf, tmp_buf, 1024))>0){ if (len < 0) break; // -1 is error int old_len=ar.size(); ar.resize(ar.size()+len); memcpy(ar.data()+old_len, tmp_buf, len); } gzclose(gzf); // And then we replace m_bufEncodedData with // the "decoded" data. m_bufEncodedData.resize(0); m_bufEncodedData=ar; m_bufEncodedData.detach(); free( filename );#endif}/** * Read a chunk from the data stream. */int HTTPProtocol::readChunked(){ if (m_iBytesLeft <= 0) { m_bufReceive.resize(4096); if (!gets(m_bufReceive.data(), m_bufReceive.size()-1)) { kdDebug(7113) << "(" << getpid() << ") gets() failure on Chunk header" << endl; return -1; } // We could have got the CRLF of the previous chunk. // If so, try again. if (m_bufReceive[0] == '\0') { if (!gets(m_bufReceive.data(), m_bufReceive.size()-1)) { kdDebug(7113) << "(" << getpid() << ") gets() failure on Chunk header" << endl; return -1; } } if (m_bEOF) { kdDebug(7113) << "(" << getpid() << ") EOF on Chunk header" << endl; return -1; } m_iBytesLeft = strtol(m_bufReceive.data(), 0, 16); if (m_iBytesLeft < 0) { kdDebug(7113) << "(" << getpid() << ") Negative chunk size" << endl; return -1; } // kdDebug(7113) << "(" << getpid() << ") Chunk size = " << m_iBytesLeft << " bytes" << endl; if (m_iBytesLeft == 0) { // Last chunk. // Skip trailers. do { // Skip trailer of last chunk. if (!gets(m_bufReceive.data(), m_bufReceive.size()-1)) { kdDebug(7113) << "(" << getpid() << ") gets() failure on Chunk trailer" << endl; return -1; } kdDebug(7113) << "(" << getpid() << ") Chunk trailer = \"" << m_bufReceive.data() << "\"" << endl; } while (strlen(m_bufReceive.data()) != 0); return 0; } } int bytesReceived = readLimited(); if (!m_iBytesLeft) m_iBytesLeft = -1; // Don't stop, continue with next chunk return bytesReceived;}int HTTPProtocol::readLimited(){ m_bufReceive.resize(4096); int bytesReceived; int bytesToReceive; if (m_iBytesL
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -