⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 q3http.cpp

📁 奇趣公司比较新的qt/emd版本
💻 CPP
📖 第 1 页 / 共 5 页
字号:
		break;	    default:		finishedWithError( QHttp::tr("HTTP request failed"), UnknownError );		break;	}    }    close();}void Q3Http::slotBytesWritten( int written ){    d->bytesDone += written;    emit dataSendProgress( d->bytesDone, d->bytesTotal );    if ( !d->postDevice )	return;    if ( d->socket.bytesToWrite() == 0 ) {	int max = qMin<int>( 4096, d->postDevice->size() - d->postDevice->at() );	QByteArray arr( max );	int n = d->postDevice->readBlock( arr.data(), max );	if ( n != max ) {	    qWarning("Could not read enough bytes from the device");	    close();	    return;	}	if ( d->postDevice->atEnd() ) {	    d->postDevice = 0;	}	d->socket.writeBlock( arr.data(), max );    }}void Q3Http::slotReadyRead(){    if ( d->state != Reading ) {	setState( Reading );	d->buffer = QByteArray();	d->readHeader = true;	d->headerStr = QLatin1String("");	d->bytesDone = 0;	d->chunkedSize = -1;    }    while ( d->readHeader ) {	bool end = false;	QString tmp;	while ( !end && d->socket.canReadLine() ) {	    tmp = QLatin1String(d->socket.readLine());	    if ( tmp == QLatin1String("\r\n") || tmp == QLatin1String("\n") )		end = true;	    else		d->headerStr += tmp;	}	if ( !end )	    return;#if defined(Q3HTTP_DEBUG)	qDebug( "Q3Http: read response header:\n---{\n%s}---", d->headerStr.latin1() );#endif	d->response = Q3HttpResponseHeader( d->headerStr );	d->headerStr = QLatin1String("");#if defined(Q3HTTP_DEBUG)	qDebug( "Q3Http: read response header:\n---{\n%s}---", d->response.toString().latin1() );#endif	// Check header	if ( !d->response.isValid() ) {	    finishedWithError( QHttp::tr("Invalid HTTP response header"), InvalidResponseHeader );	    close();	    return;	}	// The 100-continue header is ignored, because when using the	// POST method, we send both the request header and data in	// one chunk.	if (d->response.statusCode() != 100) {	    d->readHeader = false;	    if ( d->response.hasKey( QLatin1String("transfer-encoding") ) &&		 d->response.value( QLatin1String("transfer-encoding") ).lower().contains( QLatin1String("chunked") ) )		d->chunkedSize = 0;	    emit responseHeaderReceived( d->response );	}    }    if ( !d->readHeader ) {	bool everythingRead = false;	if ( currentRequest().method() == QLatin1String("HEAD") ) {	    everythingRead = true;	} else {	    Q_ULONG n = d->socket.bytesAvailable();	    QByteArray *arr = 0;	    if ( d->chunkedSize != -1 ) {		// transfer-encoding is chunked		for ( ;; ) {		    // get chunk size		    if ( d->chunkedSize == 0 ) {			if ( !d->socket.canReadLine() )			    break;			QString sizeString = QLatin1String(d->socket.readLine());			int tPos = sizeString.find( QLatin1Char(';') );			if ( tPos != -1 )			    sizeString.truncate( tPos );			bool ok;			d->chunkedSize = sizeString.toInt( &ok, 16 );			if ( !ok ) {			    finishedWithError( QHttp::tr("Invalid HTTP chunked body"), WrongContentLength );			    close();                            delete arr;			    return;			}			if ( d->chunkedSize == 0 ) // last-chunk			    d->chunkedSize = -2;		    }		    // read trailer		    while ( d->chunkedSize == -2 && d->socket.canReadLine() ) {			QString read = QLatin1String(d->socket.readLine());			if ( read == QLatin1String("\r\n") || read == QLatin1String("\n") )			    d->chunkedSize = -1;		    }		    if ( d->chunkedSize == -1 ) {			everythingRead = true;			break;		    }		    // make sure that you can read the terminating CRLF,		    // otherwise wait until next time...		    n = d->socket.bytesAvailable();		    if ( n == 0 )			break;		    if ( (Q_LONG)n == d->chunkedSize || (Q_LONG)n == d->chunkedSize+1 ) {			n = d->chunkedSize - 1;			if ( n == 0 )			    break;		    }		    // read data		    uint toRead = QMIN( (Q_LONG)n, (d->chunkedSize < 0 ? (Q_LONG)n : d->chunkedSize) );		    if ( !arr )			arr = new QByteArray( 0 );		    uint oldArrSize = arr->size();		    arr->resize( oldArrSize + toRead );		    Q_LONG read = d->socket.readBlock( arr->data()+oldArrSize, toRead );		    arr->resize( oldArrSize + read );		    d->chunkedSize -= read;		    if ( d->chunkedSize == 0 && n - read >= 2 ) {			// read terminating CRLF			char tmp[2];			d->socket.readBlock( tmp, 2 );			if ( tmp[0] != '\r' || tmp[1] != '\n' ) {			    finishedWithError( QHttp::tr("Invalid HTTP chunked body"), WrongContentLength );			    close();                            delete arr;			    return;			}		    }		}	    } else if ( d->response.hasContentLength() ) {		n = qMin<ulong>( d->response.contentLength() - d->bytesDone, n );		if ( n > 0 ) {		    arr = new QByteArray( n );		    Q_LONG read = d->socket.readBlock( arr->data(), n );		    arr->resize( read );		}		if ( d->bytesDone + bytesAvailable() + n == d->response.contentLength() )		    everythingRead = true;	    } else if ( n > 0 ) {		// workaround for VC++ bug		QByteArray temp = d->socket.readAll();		arr = new QByteArray( temp );	    }	    if ( arr ) {		n = arr->size();		if ( d->toDevice ) {		    d->toDevice->writeBlock( arr->data(), n );		    delete arr;		    d->bytesDone += n;#if defined(Q3HTTP_DEBUG)		    qDebug( "Q3Http::slotReadyRead(): read %ld bytes (%d bytes done)", n, d->bytesDone );#endif		    if ( d->response.hasContentLength() )			emit dataReadProgress( d->bytesDone, d->response.contentLength() );		    else			emit dataReadProgress( d->bytesDone, 0 );		} else {		    d->rba.append( arr );#if defined(Q3HTTP_DEBUG)		    qDebug( "Q3Http::slotReadyRead(): read %ld bytes (%ld bytes done)", n, d->bytesDone + bytesAvailable() );#endif		    if ( d->response.hasContentLength() )			emit dataReadProgress( d->bytesDone + bytesAvailable(), d->response.contentLength() );		    else			emit dataReadProgress( d->bytesDone + bytesAvailable(), 0 );		    emit readyRead( d->response );		}	    }	}	if ( everythingRead ) {	    // Handle "Connection: close"	    if ( d->response.value(QLatin1String("connection")).lower() == QLatin1String("close") ) {		close();	    } else {		setState( Connected );		// Start a timer, so that we emit the keep alive signal		// "after" this method returned.		d->idleTimer = startTimer( 0 );	    }	}    }}/*!    Returns the current state of the object. When the state changes,    the stateChanged() signal is emitted.    \sa State stateChanged()*/Q3Http::State Q3Http::state() const{    return d->state;}/*!    Returns the last error that occurred. This is useful to find out    what happened when receiving a requestFinished() or a done()    signal with the \c error argument \c true.    If you start a new request, the error status is reset to \c NoError.*/Q3Http::Error Q3Http::error() const{    return d->error;}/*!    Returns a human-readable description of the last error that    occurred. This is useful to present a error message to the user    when receiving a requestFinished() or a done() signal with the \c    error argument \c true.*/QString Q3Http::errorString() const{    return d->errorString;}/*! \reimp*/void Q3Http::timerEvent( QTimerEvent *e ){    if ( e->timerId() == d->idleTimer ) {	killTimer( d->idleTimer );	d->idleTimer = 0;	if ( d->state == Connected ) {	    finishedWithSuccess();	} else if ( d->state != Unconnected ) {	    setState( Unconnected );	    finishedWithSuccess();	}    } else {	QObject::timerEvent( e );    }}void Q3Http::killIdleTimer(){    if (d->idleTimer)        killTimer( d->idleTimer );    d->idleTimer = 0;}void Q3Http::setState( int s ){#if defined(Q3HTTP_DEBUG)    qDebug( "Q3Http state changed %d -> %d", d->state, s );#endif    d->state = (State)s;    emit stateChanged( s );}void Q3Http::close(){    // If no connection is open -> ignore    if ( d->state == Closing || d->state == Unconnected )	return;    d->postDevice = 0;    setState( Closing );    // Already closed ?    if ( !d->socket.isOpen() ) {	d->idleTimer = startTimer( 0 );    } else {	// Close now.	d->socket.close();	// Did close succeed immediately ?	if ( d->socket.state() == Q3Socket::Idle ) {	    // Prepare to emit the requestFinished() signal.	    d->idleTimer = startTimer( 0 );	}    }}/********************************************************************** * * Q3Http implementation of the Q3NetworkProtocol interface * *********************************************************************//*! \reimp*/int Q3Http::supportedOperations() const{    return OpGet | OpPut;}/*! \reimp*/void Q3Http::operationGet( Q3NetworkOperation *op ){    connect( this, SIGNAL(readyRead(Q3HttpResponseHeader)),	    this, SLOT(clientReply(Q3HttpResponseHeader)) );    connect( this, SIGNAL(done(bool)),	    this, SLOT(clientDone(bool)) );    connect( this, SIGNAL(stateChanged(int)),	    this, SLOT(clientStateChanged(int)) );    bytesRead = 0;    op->setState( StInProgress );    Q3Url u( operationInProgress()->arg( 0 ) );    Q3HttpRequestHeader header( QLatin1String("GET"), u.encodedPathAndQuery(), 1, 0 );    header.setValue( QLatin1String("Host"), u.host() );    setHost( u.host(), u.port() != -1 ? u.port() : 80 );    request( header );}/*! \reimp*/void Q3Http::operationPut( Q3NetworkOperation *op ){    connect( this, SIGNAL(readyRead(Q3HttpResponseHeader)),	    this, SLOT(clientReply(Q3HttpResponseHeader)) );    connect( this, SIGNAL(done(bool)),	    this, SLOT(clientDone(bool)) );    connect( this, SIGNAL(stateChanged(int)),	    this, SLOT(clientStateChanged(int)) );    bytesRead = 0;    op->setState( StInProgress );    Q3Url u( operationInProgress()->arg( 0 ) );    Q3HttpRequestHeader header( QLatin1String("POST"), u.encodedPathAndQuery(), 1, 0 );    header.setValue( QLatin1String("Host"), u.host() );    setHost( u.host(), u.port() != -1 ? u.port() : 80 );    request( header, op->rawArg(1) );}void Q3Http::clientReply( const Q3HttpResponseHeader &rep ){    Q3NetworkOperation *op = operationInProgress();    if ( op ) {	if ( rep.statusCode() >= 400 && rep.statusCode() < 600 ) {	    op->setState( StFailed );	    op->setProtocolDetail(		    QString(QLatin1String("%1 %2")).arg(rep.statusCode()).arg(rep.reasonPhrase())						    );	    switch ( rep.statusCode() ) {		case 401:		case 403:		case 405:		    op->setErrorCode( ErrPermissionDenied );		    break;		case 404:		    op->setErrorCode(ErrFileNotExisting );		    break;		default:		    if ( op->operation() == OpGet )			op->setErrorCode( ErrGet );		    else			op->setErrorCode( ErrPut );		    break;	    }	}	// ### In cases of an error, should we still emit the data() signals?	if ( op->operation() == OpGet && bytesAvailable() > 0 ) {	    QByteArray ba = readAll();	    emit data( ba, op );	    bytesRead += ba.size();	    if ( rep.hasContentLength() ) {		emit dataTransferProgress( bytesRead, rep.contentLength(), op );	    }	}    }}void Q3Http::clientDone( bool err ){    disconnect( this, SIGNAL(readyRead(Q3HttpResponseHeader)),	    this, SLOT(clientReply(Q3HttpResponseHeader)) );    disconnect( this, SIGNAL(done(bool)),	    this, SLOT(clientDone(bool)) );    disconnect( this, SIGNAL(stateChanged(int)),	    this, SLOT(clientStateChanged(int)) );    if ( err ) {	Q3NetworkOperation *op = operationInProgress();	if ( op ) {	    op->setState( Q3NetworkProtocol::StFailed );	    op->setProtocolDetail( errorString() );	    switch ( error() ) {		case ConnectionRefused:		    op->setErrorCode( ErrHostNotFound );		    break;		case HostNotFound:		    op->setErrorCode( ErrHostNotFound );		    break;		default:		    if ( op->operation() == OpGet )			op->setErrorCode( ErrGet );		    else			op->setErrorCode( ErrPut );		    break;	    }	    emit finished( op );	}    } else {	Q3NetworkOperation *op = operationInProgress();	if ( op ) {	    if ( op->state() != StFailed ) {		op->setState( Q3NetworkProtocol::StDone );		op->setErrorCode( Q3NetworkProtocol::NoError );	    }	    emit finished( op );	}    }}void Q3Http::clientStateChanged( int state ){    if ( url() ) {	switch ( (State)state ) {	    case Connecting:		emit connectionStateChanged( ConHostFound, QHttp::tr( "Host %1 found" ).arg( url()->host() ) );		break;	    case Sending:		emit connectionStateChanged( ConConnected, QHttp::tr( "Connected to host %1" ).arg( url()->host() ) );		break;	    case Unconnected:		emit connectionStateChanged( ConClosed, QHttp::tr( "Connection to %1 closed" ).arg( url()->host() ) );		break;	    default:		break;	}    } else {	switch ( (State)state ) {	    case Connecting:		emit connecti

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -