summaryrefslogtreecommitdiffstats
path: root/src/kernel/qnetworkprotocol.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel/qnetworkprotocol.cpp')
-rw-r--r--src/kernel/qnetworkprotocol.cpp1265
1 files changed, 1265 insertions, 0 deletions
diff --git a/src/kernel/qnetworkprotocol.cpp b/src/kernel/qnetworkprotocol.cpp
new file mode 100644
index 0000000..4173584
--- /dev/null
+++ b/src/kernel/qnetworkprotocol.cpp
@@ -0,0 +1,1265 @@
+/****************************************************************************
+**
+** Implementation of QNetworkProtocol class
+**
+** Created : 950429
+**
+** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
+**
+** This file is part of the kernel module of the Qt GUI Toolkit.
+**
+** This file may be used under the terms of the GNU General
+** Public License versions 2.0 or 3.0 as published by the Free
+** Software Foundation and appearing in the files LICENSE.GPL2
+** and LICENSE.GPL3 included in the packaging of this file.
+** Alternatively you may (at your option) use any later version
+** of the GNU General Public License if such license has been
+** publicly approved by Trolltech ASA (or its successors, if any)
+** and the KDE Free Qt Foundation.
+**
+** Please review the following information to ensure GNU General
+** Public Licensing requirements will be met:
+** http://trolltech.com/products/qt/licenses/licensing/opensource/.
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
+** or contact the sales department at sales@trolltech.com.
+**
+** This file may be used under the terms of the Q Public License as
+** defined by Trolltech ASA and appearing in the file LICENSE.QPL
+** included in the packaging of this file. Licensees holding valid Qt
+** Commercial licenses may use this file in accordance with the Qt
+** Commercial License Agreement provided with the Software.
+**
+** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
+** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
+** herein.
+**
+**********************************************************************/
+
+#include "qnetworkprotocol.h"
+
+#ifndef QT_NO_NETWORKPROTOCOL
+
+#include "qlocalfs.h"
+#include "qurloperator.h"
+#include "qtimer.h"
+#include "qmap.h"
+#include "qptrqueue.h"
+
+//#define QNETWORKPROTOCOL_DEBUG
+#define NETWORK_OP_DELAY 1000
+
+extern Q_EXPORT QNetworkProtocolDict *qNetworkProtocolRegister;
+
+QNetworkProtocolDict *qNetworkProtocolRegister = 0;
+
+class QNetworkProtocolPrivate
+{
+public:
+ QNetworkProtocolPrivate( QNetworkProtocol *p )
+ {
+ url = 0;
+ opInProgress = 0;
+ opStartTimer = new QTimer( p );
+ removeTimer = new QTimer( p );
+ operationQueue.setAutoDelete( FALSE );
+ autoDelete = FALSE;
+ removeInterval = 10000;
+ oldOps.setAutoDelete( FALSE );
+ }
+
+ ~QNetworkProtocolPrivate()
+ {
+ removeTimer->stop();
+ if ( opInProgress ) {
+ if ( opInProgress == operationQueue.head() )
+ operationQueue.dequeue();
+ opInProgress->free();
+ }
+ while ( operationQueue.head() ) {
+ operationQueue.head()->free();
+ operationQueue.dequeue();
+ }
+ while ( oldOps.first() ) {
+ oldOps.first()->free();
+ oldOps.removeFirst();
+ }
+ delete opStartTimer;
+ }
+
+ QUrlOperator *url;
+ QPtrQueue< QNetworkOperation > operationQueue;
+ QNetworkOperation *opInProgress;
+ QTimer *opStartTimer, *removeTimer;
+ int removeInterval;
+ bool autoDelete;
+ QPtrList< QNetworkOperation > oldOps;
+};
+
+/*!
+ \class QNetworkProtocol qnetworkprotocol.h
+ \brief The QNetworkProtocol class provides a common API for network protocols.
+\if defined(commercial)
+ It is part of the <a href="commercialeditions.html">Qt Enterprise Edition</a>.
+\endif
+
+ \module network
+ \ingroup io
+ \module network
+ \mainclass
+
+ This is a base class which should be used for network protocols
+ implementations that can then be used in Qt (e.g. in the file
+ dialog) together with the QUrlOperator.
+
+ The easiest way to implement a new network protocol is to
+ reimplement the operation*() methods, e.g. operationGet(), etc.
+ Only the supported operations should be reimplemented. To specify
+ which operations are supported, also reimplement
+ supportedOperations() and return an int that is OR'd together
+ using the supported operations from the \l
+ QNetworkProtocol::Operation enum.
+
+ When you implement a network protocol this way, it is important to
+ emit the correct signals. Also, always emit the finished() signal
+ when an operation is done (on success \e and on failure). Qt
+ relies on correctly emitted finished() signals.
+
+ For a detailed description of the Qt Network Architecture and how
+ to implement and use network protocols in Qt, see the \link
+ network.html Qt Network Documentation\endlink.
+*/
+
+/*!
+ \fn void QNetworkProtocol::newChildren( const QValueList<QUrlInfo> &i, QNetworkOperation *op )
+
+ This signal is emitted after listChildren() was called and new
+ children (files) have been read from the list of files. \a i holds
+ the information about the new children. \a op is the pointer to
+ the operation object which contains all the information about the
+ operation, including the state, etc.
+
+ When a protocol emits this signal, QNetworkProtocol is smart
+ enough to let the QUrlOperator, which is used by the network
+ protocol, emit its corresponding signal.
+
+ When implementing your own network protocol and reading children,
+ you usually don't read one child at once, but rather a list of
+ them. That's why this signal takes a list of QUrlInfo objects. If
+ you prefer to read just one child at a time you can use the
+ convenience signal newChild(), which takes a single QUrlInfo
+ object.
+*/
+
+/*!
+ \fn void QNetworkProtocol::newChild( const QUrlInfo &i, QNetworkOperation *op )
+
+ This signal is emitted if a new child (file) has been read.
+ QNetworkProtocol automatically connects it to a slot which creates
+ a list of QUrlInfo objects (with just one QUrlInfo \a i) and emits
+ the newChildren() signal with this list. \a op is the pointer to
+ the operation object which contains all the information about the
+ operation that has finished, including the state, etc.
+
+ This is just a convenience signal useful for implementing your own
+ network protocol. In all other cases connect to the newChildren()
+ signal with its list of QUrlInfo objects.
+*/
+
+/*!
+ \fn void QNetworkProtocol::finished( QNetworkOperation *op )
+
+ This signal is emitted when an operation finishes. This signal is
+ always emitted, for both success and failure. \a op is the pointer
+ to the operation object which contains all the information about
+ the operation, including the state, etc. Check the state and error
+ code of the operation object to determine whether or not the
+ operation was successful.
+
+ When a protocol emits this signal, QNetworkProtocol is smart
+ enough to let the QUrlOperator, which is used by the network
+ protocol, emit its corresponding signal.
+*/
+
+/*!
+ \fn void QNetworkProtocol::start( QNetworkOperation *op )
+
+ Some operations (such as listChildren()) emit this signal when
+ they start processing the operation. \a op is the pointer to the
+ operation object which contains all the information about the
+ operation, including the state, etc.
+
+ When a protocol emits this signal, QNetworkProtocol is smart
+ enough to let the QUrlOperator, which is used by the network
+ protocol, emit its corresponding signal.
+*/
+
+/*!
+ \fn void QNetworkProtocol::createdDirectory( const QUrlInfo &i, QNetworkOperation *op )
+
+ This signal is emitted when mkdir() has been succesful and the
+ directory has been created. \a i holds the information about the
+ new directory. \a op is the pointer to the operation object which
+ contains all the information about the operation, including the
+ state, etc. Using op->arg( 0 ), you can get the file name of the
+ new directory.
+
+ When a protocol emits this signal, QNetworkProtocol is smart
+ enough to let the QUrlOperator, which is used by the network
+ protocol, emit its corresponding signal.
+*/
+
+/*!
+ \fn void QNetworkProtocol::removed( QNetworkOperation *op )
+
+ This signal is emitted when remove() has been succesful and the
+ file has been removed. \a op holds the file name of the removed
+ file in the first argument, accessible with op->arg( 0 ). \a op is
+ the pointer to the operation object which contains all the
+ information about the operation, including the state, etc.
+
+ When a protocol emits this signal, QNetworkProtocol is smart
+ enough to let the QUrlOperator, which is used by the network
+ protocol, emit its corresponding signal.
+*/
+
+/*!
+ \fn void QNetworkProtocol::itemChanged( QNetworkOperation *op )
+
+ This signal is emitted whenever a file which is a child of this
+ URL has been changed, e.g. by successfully calling rename(). \a op
+ holds the original and the new file names in the first and second
+ arguments, accessible with op->arg( 0 ) and op->arg( 1 )
+ respectively. \a op is the pointer to the operation object which
+ contains all the information about the operation, including the
+ state, etc.
+
+ When a protocol emits this signal, QNetworkProtocol is smart
+ enough to let the QUrlOperator, which is used by the network
+ protocol, emit its corresponding signal.
+*/
+
+/*!
+ \fn void QNetworkProtocol::data( const QByteArray &data,
+ QNetworkOperation *op )
+
+ This signal is emitted when new \a data has been received after
+ calling get() or put(). \a op holds the name of the file from
+ which data is retrieved or uploaded in its first argument, and the
+ (raw) data in its second argument. You can get them with
+ op->arg( 0 ) and op->rawArg( 1 ). \a op is the pointer to the
+ operation object, which contains all the information about the
+ operation, including the state, etc.
+
+ When a protocol emits this signal, QNetworkProtocol is smart
+ enough to let the QUrlOperator (which is used by the network
+ protocol) emit its corresponding signal.
+*/
+
+/*!
+ \fn void QNetworkProtocol::dataTransferProgress( int bytesDone, int bytesTotal, QNetworkOperation *op )
+
+ This signal is emitted during the transfer of data (using put() or
+ get()). \a bytesDone is how many bytes of \a bytesTotal have been
+ transferred. \a bytesTotal may be -1, which means that the total
+ number of bytes is not known. \a op is the pointer to the
+ operation object which contains all the information about the
+ operation, including the state, etc.
+
+ When a protocol emits this signal, QNetworkProtocol is smart
+ enough to let the QUrlOperator, which is used by the network
+ protocol, emit its corresponding signal.
+*/
+
+/*!
+ \fn void QNetworkProtocol::connectionStateChanged( int state, const QString &data )
+
+ This signal is emitted whenever the state of the connection of the
+ network protocol is changed. \a state describes the new state,
+ which is one of, \c ConHostFound, \c ConConnected or \c ConClosed.
+ \a data is a message text.
+*/
+
+/*!
+ \enum QNetworkProtocol::State
+
+ This enum contains the state that a QNetworkOperation can have.
+
+ \value StWaiting The operation is in the QNetworkProtocol's queue
+ waiting to be prcessed.
+
+ \value StInProgress The operation is being processed.
+
+ \value StDone The operation has been processed succesfully.
+
+ \value StFailed The operation has been processed but an error occurred.
+
+ \value StStopped The operation has been processed but has been
+ stopped before it finished, and is waiting to be processed.
+
+*/
+
+/*!
+ \enum QNetworkProtocol::Operation
+
+ This enum lists the possible operations that a network protocol
+ can support. supportedOperations() returns an int of these that is
+ OR'd together. Also, the type() of a QNetworkOperation is always
+ one of these values.
+
+ \value OpListChildren List the children of a URL, e.g. of a directory.
+ \value OpMkDir Create a directory.
+ \value OpRemove Remove a child (e.g. a file).
+ \value OpRename Rename a child (e.g. a file).
+ \value OpGet Get data from a location.
+ \value OpPut Put data to a location.
+*/
+
+/*!
+ \enum QNetworkProtocol::ConnectionState
+
+ When the connection state of a network protocol changes it emits
+ the signal connectionStateChanged(). The first argument is one of
+ the following values:
+
+ \value ConHostFound Host has been found.
+ \value ConConnected Connection to the host has been established.
+ \value ConClosed Connection has been closed.
+*/
+
+/*!
+ \enum QNetworkProtocol::Error
+
+ When an operation fails (finishes unsuccessfully), the
+ QNetworkOperation of the operation returns an error code which has
+ one of the following values:
+
+ \value NoError No error occurred.
+
+ \value ErrValid The URL you are operating on is not valid.
+
+ \value ErrUnknownProtocol There is no protocol implementation
+ available for the protocol of the URL you are operating on (e.g.
+ if the protocol is http and no http implementation has been
+ registered).
+
+ \value ErrUnsupported The operation is not supported by the
+ protocol.
+
+ \value ErrParse The URL could not be parsed correctly.
+
+ \value ErrLoginIncorrect You needed to login but the username
+ or password is wrong.
+
+ \value ErrHostNotFound The specified host (in the URL) couldn't
+ be found.
+
+ \value ErrListChildren An error occurred while listing the
+ children (files).
+
+ \value ErrMkDir An error occurred when creating a directory.
+
+ \value ErrRemove An error occurred when removing a child (file).
+
+ \value ErrRename An error occurred when renaming a child (file).
+
+ \value ErrGet An error occurred while getting (retrieving) data.
+
+ \value ErrPut An error occurred while putting (uploading) data.
+
+ \value ErrFileNotExisting A file which is needed by the operation
+ doesn't exist.
+
+ \value ErrPermissionDenied Permission for doing the operation has
+ been denied.
+
+ You should also use these error codes when implementing custom
+ network protocols. If this is not possible, you can define your own
+ error codes by using integer values that don't conflict with any
+ of these values.
+*/
+
+/*!
+ Constructor of the network protocol base class. Does some
+ initialization and connecting of signals and slots.
+*/
+
+QNetworkProtocol::QNetworkProtocol()
+ : QObject()
+{
+ d = new QNetworkProtocolPrivate( this );
+
+ connect( d->opStartTimer, SIGNAL( timeout() ),
+ this, SLOT( startOps() ) );
+ connect( d->removeTimer, SIGNAL( timeout() ),
+ this, SLOT( removeMe() ) );
+
+ if ( url() ) {
+ connect( this, SIGNAL( data(const QByteArray&,QNetworkOperation*) ),
+ url(), SIGNAL( data(const QByteArray&,QNetworkOperation*) ) );
+ connect( this, SIGNAL( finished(QNetworkOperation*) ),
+ url(), SIGNAL( finished(QNetworkOperation*) ) );
+ connect( this, SIGNAL( start(QNetworkOperation*) ),
+ url(), SIGNAL( start(QNetworkOperation*) ) );
+ connect( this, SIGNAL( newChildren(const QValueList<QUrlInfo>&,QNetworkOperation*) ),
+ url(), SIGNAL( newChildren(const QValueList<QUrlInfo>&,QNetworkOperation*) ) );
+ connect( this, SIGNAL( newChildren(const QValueList<QUrlInfo>&,QNetworkOperation*) ),
+ url(), SLOT( addEntry(const QValueList<QUrlInfo>&) ) );
+ connect( this, SIGNAL( createdDirectory(const QUrlInfo&,QNetworkOperation*) ),
+ url(), SIGNAL( createdDirectory(const QUrlInfo&,QNetworkOperation*) ) );
+ connect( this, SIGNAL( removed(QNetworkOperation*) ),
+ url(), SIGNAL( removed(QNetworkOperation*) ) );
+ connect( this, SIGNAL( itemChanged(QNetworkOperation*) ),
+ url(), SIGNAL( itemChanged(QNetworkOperation*) ) );
+ connect( this, SIGNAL( dataTransferProgress(int,int,QNetworkOperation*) ),
+ url(), SIGNAL( dataTransferProgress(int,int,QNetworkOperation*) ) );
+ connect( this, SIGNAL( connectionStateChanged(int,const QString&) ),
+ url(), SIGNAL( connectionStateChanged(int,const QString&) ) );
+ }
+
+ connect( this, SIGNAL( finished(QNetworkOperation*) ),
+ this, SLOT( processNextOperation(QNetworkOperation*) ) );
+ connect( this, SIGNAL( newChild(const QUrlInfo&,QNetworkOperation*) ),
+ this, SLOT( emitNewChildren(const QUrlInfo&,QNetworkOperation*) ) );
+
+}
+
+/*!
+ Destructor.
+*/
+
+QNetworkProtocol::~QNetworkProtocol()
+{
+ delete d;
+}
+
+/*!
+ Sets the QUrlOperator, on which the protocol works, to \a u.
+
+ \sa QUrlOperator
+*/
+
+void QNetworkProtocol::setUrl( QUrlOperator *u )
+{
+ if ( url() ) {
+ disconnect( this, SIGNAL( data(const QByteArray&,QNetworkOperation*) ),
+ url(), SIGNAL( data(const QByteArray&,QNetworkOperation*) ) );
+ disconnect( this, SIGNAL( finished(QNetworkOperation*) ),
+ url(), SIGNAL( finished(QNetworkOperation*) ) );
+ disconnect( this, SIGNAL( start(QNetworkOperation*) ),
+ url(), SIGNAL( start(QNetworkOperation*) ) );
+ disconnect( this, SIGNAL( newChildren(const QValueList<QUrlInfo>&,QNetworkOperation*) ),
+ url(), SIGNAL( newChildren(const QValueList<QUrlInfo>&,QNetworkOperation*) ) );
+ disconnect( this, SIGNAL( newChildren(const QValueList<QUrlInfo>&,QNetworkOperation*) ),
+ url(), SLOT( addEntry(const QValueList<QUrlInfo>&) ) );
+ disconnect( this, SIGNAL( createdDirectory(const QUrlInfo&,QNetworkOperation*) ),
+ url(), SIGNAL( createdDirectory(const QUrlInfo&,QNetworkOperation*) ) );
+ disconnect( this, SIGNAL( removed(QNetworkOperation*) ),
+ url(), SIGNAL( removed(QNetworkOperation*) ) );
+ disconnect( this, SIGNAL( itemChanged(QNetworkOperation*) ),
+ url(), SIGNAL( itemChanged(QNetworkOperation*) ) );
+ disconnect( this, SIGNAL( dataTransferProgress(int,int,QNetworkOperation*) ),
+ url(), SIGNAL( dataTransferProgress(int,int,QNetworkOperation*) ) );
+ disconnect( this, SIGNAL( connectionStateChanged(int,const QString&) ),
+ url(), SIGNAL( connectionStateChanged(int,const QString&) ) );
+ }
+
+
+ // ### if autoDelete is TRUE, we should delete the QUrlOperator (something
+ // like below; but that is not possible since it would delete this, too).
+ //if ( d->autoDelete && (d->url!=u) ) {
+ // delete d->url; // destructor deletes the network protocol
+ //}
+ d->url = u;
+
+ if ( url() ) {
+ connect( this, SIGNAL( data(const QByteArray&,QNetworkOperation*) ),
+ url(), SIGNAL( data(const QByteArray&,QNetworkOperation*) ) );
+ connect( this, SIGNAL( finished(QNetworkOperation*) ),
+ url(), SIGNAL( finished(QNetworkOperation*) ) );
+ connect( this, SIGNAL( start(QNetworkOperation*) ),
+ url(), SIGNAL( start(QNetworkOperation*) ) );
+ connect( this, SIGNAL( newChildren(const QValueList<QUrlInfo>&,QNetworkOperation*) ),
+ url(), SIGNAL( newChildren(const QValueList<QUrlInfo>&,QNetworkOperation*) ) );
+ connect( this, SIGNAL( newChildren(const QValueList<QUrlInfo>&,QNetworkOperation*) ),
+ url(), SLOT( addEntry(const QValueList<QUrlInfo>&) ) );
+ connect( this, SIGNAL( createdDirectory(const QUrlInfo&,QNetworkOperation*) ),
+ url(), SIGNAL( createdDirectory(const QUrlInfo&,QNetworkOperation*) ) );
+ connect( this, SIGNAL( removed(QNetworkOperation*) ),
+ url(), SIGNAL( removed(QNetworkOperation*) ) );
+ connect( this, SIGNAL( itemChanged(QNetworkOperation*) ),
+ url(), SIGNAL( itemChanged(QNetworkOperation*) ) );
+ connect( this, SIGNAL( dataTransferProgress(int,int,QNetworkOperation*) ),
+ url(), SIGNAL( dataTransferProgress(int,int,QNetworkOperation*) ) );
+ connect( this, SIGNAL( connectionStateChanged(int,const QString&) ),
+ url(), SIGNAL( connectionStateChanged(int,const QString&) ) );
+ }
+
+ if ( !d->opInProgress && !d->operationQueue.isEmpty() )
+ d->opStartTimer->start( 0, TRUE );
+}
+
+/*!
+ For processing operations the network protocol base class calls
+ this method quite often. This should be reimplemented by new
+ network protocols. It should return TRUE if the connection is OK
+ (open); otherwise it should return FALSE. If the connection is not
+ open the protocol should open it.
+
+ If the connection can't be opened (e.g. because you already tried
+ but the host couldn't be found), set the state of \a op to
+ QNetworkProtocol::StFailed and emit the finished() signal with
+ this QNetworkOperation as argument.
+
+ \a op is the operation that needs an open connection.
+*/
+
+bool QNetworkProtocol::checkConnection( QNetworkOperation * )
+{
+ return TRUE;
+}
+
+/*!
+ Returns an int that is OR'd together using the enum values of
+ \l{QNetworkProtocol::Operation}, which describes which operations
+ are supported by the network protocol. Should be reimplemented by
+ new network protocols.
+*/
+
+int QNetworkProtocol::supportedOperations() const
+{
+ return 0;
+}
+
+/*!
+ Adds the operation \a op to the operation queue. The operation
+ will be processed as soon as possible. This method returns
+ immediately.
+*/
+
+void QNetworkProtocol::addOperation( QNetworkOperation *op )
+{
+#ifdef QNETWORKPROTOCOL_DEBUG
+ qDebug( "QNetworkOperation: addOperation: %p %d", op, op->operation() );
+#endif
+ d->operationQueue.enqueue( op );
+ if ( !d->opInProgress )
+ d->opStartTimer->start( 0, TRUE );
+}
+
+/*!
+ Static method to register a network protocol for Qt. For example,
+ if you have an implementation of NNTP (called Nntp) which is
+ derived from QNetworkProtocol, call:
+ \code
+ QNetworkProtocol::registerNetworkProtocol( "nntp", new QNetworkProtocolFactory<Nntp> );
+ \endcode
+ after which your implementation is registered for future nntp
+ operations.
+
+ The name of the protocol is given in \a protocol and a pointer to
+ the protocol factory is given in \a protocolFactory.
+*/
+
+void QNetworkProtocol::registerNetworkProtocol( const QString &protocol,
+ QNetworkProtocolFactoryBase *protocolFactory )
+{
+ if ( !qNetworkProtocolRegister ) {
+ qNetworkProtocolRegister = new QNetworkProtocolDict;
+ QNetworkProtocol::registerNetworkProtocol( "file", new QNetworkProtocolFactory< QLocalFs > );
+ }
+
+ qNetworkProtocolRegister->insert( protocol, protocolFactory );
+}
+
+/*!
+ Static method to get a new instance of the network protocol \a
+ protocol. For example, if you need to do some FTP operations, do
+ the following:
+ \code
+ QFtp *ftp = QNetworkProtocol::getNetworkProtocol( "ftp" );
+ \endcode
+ This returns a pointer to a new instance of an ftp implementation
+ or null if no protocol for ftp was registered. The ownership of
+ the pointer is transferred to you, so you must delete it if you
+ don't need it anymore.
+
+ Normally you should not work directly with network protocols, so
+ you will not need to call this method yourself. Instead, use
+ QUrlOperator, which makes working with network protocols much more
+ convenient.
+
+ \sa QUrlOperator
+*/
+
+QNetworkProtocol *QNetworkProtocol::getNetworkProtocol( const QString &protocol )
+{
+ if ( !qNetworkProtocolRegister ) {
+ qNetworkProtocolRegister = new QNetworkProtocolDict;
+ QNetworkProtocol::registerNetworkProtocol( "file", new QNetworkProtocolFactory< QLocalFs > );
+ }
+
+ if ( protocol.isNull() )
+ return 0;
+
+ QNetworkProtocolFactoryBase *factory = qNetworkProtocolRegister->find( protocol );
+ if ( factory )
+ return factory->createObject();
+
+ return 0;
+}
+
+/*!
+ Returns TRUE if the only protocol registered is for working on the
+ local filesystem; returns FALSE if other network protocols are
+ also registered.
+*/
+
+bool QNetworkProtocol::hasOnlyLocalFileSystem()
+{
+ if ( !qNetworkProtocolRegister )
+ return FALSE;
+
+ QDictIterator< QNetworkProtocolFactoryBase > it( *qNetworkProtocolRegister );
+ for ( ; it.current(); ++it )
+ if ( it.currentKey() != "file" )
+ return FALSE;
+ return TRUE;
+}
+
+/*!
+ \internal
+ Starts processing network operations.
+*/
+
+void QNetworkProtocol::startOps()
+{
+#ifdef QNETWORKPROTOCOL_DEBUG
+ qDebug( "QNetworkOperation: start processing operations" );
+#endif
+ processNextOperation( 0 );
+}
+
+/*!
+ \internal
+ Processes the operation \a op. It calls the
+ corresponding operation[something]( QNetworkOperation * )
+ methods.
+*/
+
+void QNetworkProtocol::processOperation( QNetworkOperation *op )
+{
+ if ( !op )
+ return;
+
+ switch ( op->operation() ) {
+ case OpListChildren:
+ operationListChildren( op );
+ break;
+ case OpMkDir:
+ operationMkDir( op );
+ break;
+ case OpRemove:
+ operationRemove( op );
+ break;
+ case OpRename:
+ operationRename( op );
+ break;
+ case OpGet:
+ operationGet( op );
+ break;
+ case OpPut:
+ operationPut( op );
+ break;
+ }
+}
+
+/*!
+ When implementing a new network protocol, this method should be
+ reimplemented if the protocol supports listing children (files);
+ this method should then process this QNetworkOperation.
+
+ When you reimplement this method it's very important that you emit
+ the correct signals at the correct time (especially the finished()
+ signal after processing an operation). Take a look at the \link
+ network.html Qt Network Documentation\endlink which describes in
+ detail how to reimplement this method. You may also want to look
+ at the example implementation in
+ examples/network/networkprotocol/nntp.cpp.
+
+ \a op is the pointer to the operation object which contains all
+ the information on the operation that has finished, including the
+ state, etc.
+*/
+
+void QNetworkProtocol::operationListChildren( QNetworkOperation * )
+{
+}
+
+/*!
+ When implementing a new network protocol, this method should be
+ reimplemented if the protocol supports making directories; this
+ method should then process this QNetworkOperation.
+
+ When you reimplement this method it's very important that you emit
+ the correct signals at the correct time (especially the finished()
+ signal after processing an operation). Take a look at the \link
+ network.html Qt Network Documentation\endlink which describes in
+ detail how to reimplement this method. You may also want to look
+ at the example implementation in
+ examples/network/networkprotocol/nntp.cpp.
+
+ \a op is the pointer to the operation object which contains all
+ the information on the operation that has finished, including the
+ state, etc.
+*/
+
+void QNetworkProtocol::operationMkDir( QNetworkOperation * )
+{
+}
+
+/*!
+ When implementing a new network protocol, this method should be
+ reimplemented if the protocol supports removing children (files);
+ this method should then process this QNetworkOperation.
+
+ When you reimplement this method it's very important that you emit
+ the correct signals at the correct time (especially the finished()
+ signal after processing an operation). Take a look at the \link
+ network.html Qt Network Documentation\endlink which is describes
+ in detail how to reimplement this method. You may also want to
+ look at the example implementation in
+ examples/network/networkprotocol/nntp.cpp.
+
+ \a op is the pointer to the operation object which contains all
+ the information on the operation that has finished, including the
+ state, etc.
+*/
+
+void QNetworkProtocol::operationRemove( QNetworkOperation * )
+{
+}
+
+/*!
+ When implementing a new newtork protocol, this method should be
+ reimplemented if the protocol supports renaming children (files);
+ this method should then process this QNetworkOperation.
+
+ When you reimplement this method it's very important that you emit
+ the correct signals at the correct time (especially the finished()
+ signal after processing an operation). Take a look at the \link
+ network.html Qt Network Documentation\endlink which describes in
+ detail how to reimplement this method. You may also want to look
+ at the example implementation in
+ examples/network/networkprotocol/nntp.cpp.
+
+ \a op is the pointer to the operation object which contains all
+ the information on the operation that has finished, including the
+ state, etc.
+*/
+
+void QNetworkProtocol::operationRename( QNetworkOperation * )
+{
+}
+
+/*!
+ When implementing a new network protocol, this method should be
+ reimplemented if the protocol supports getting data; this method
+ should then process the QNetworkOperation.
+
+ When you reimplement this method it's very important that you emit
+ the correct signals at the correct time (especially the finished()
+ signal after processing an operation). Take a look at the \link
+ network.html Qt Network Documentation\endlink which describes in
+ detail how to reimplement this method. You may also want to look
+ at the example implementation in
+ examples/network/networkprotocol/nntp.cpp.
+
+ \a op is the pointer to the operation object which contains all
+ the information on the operation that has finished, including the
+ state, etc.
+*/
+
+void QNetworkProtocol::operationGet( QNetworkOperation * )
+{
+}
+
+/*!
+ When implementing a new network protocol, this method should be
+ reimplemented if the protocol supports putting (uploading) data;
+ this method should then process the QNetworkOperation.
+
+ When you reimplement this method it's very important that you emit
+ the correct signals at the correct time (especially the finished()
+ signal after processing an operation). Take a look at the \link
+ network.html Qt Network Documentation\endlink which describes in
+ detail how to reimplement this method. You may also want to look
+ at the example implementation in
+ examples/network/networkprotocol/nntp.cpp.
+
+ \a op is the pointer to the operation object which contains all
+ the information on the operation that has finished, including the
+ state, etc.
+*/
+
+void QNetworkProtocol::operationPut( QNetworkOperation * )
+{
+}
+
+/*! \internal
+*/
+
+void QNetworkProtocol::operationPutChunk( QNetworkOperation * )
+{
+}
+
+/*!
+ \internal
+ Handles operations. Deletes the previous operation object and
+ tries to process the next operation. It also checks the connection state
+ and only processes the next operation, if the connection of the protocol
+ is open. Otherwise it waits until the protocol opens the connection.
+*/
+
+void QNetworkProtocol::processNextOperation( QNetworkOperation *old )
+{
+#ifdef QNETWORKPROTOCOL_DEBUG
+ qDebug( "QNetworkOperation: process next operation, old: %p", old );
+#endif
+ d->removeTimer->stop();
+
+ if ( old )
+ d->oldOps.append( old );
+ if ( d->opInProgress && d->opInProgress!=old )
+ d->oldOps.append( d->opInProgress );
+
+ if ( d->operationQueue.isEmpty() ) {
+ d->opInProgress = 0;
+ if ( d->autoDelete )
+ d->removeTimer->start( d->removeInterval, TRUE );
+ return;
+ }
+
+ QNetworkOperation *op = d->operationQueue.head();
+
+ d->opInProgress = op;
+
+ if ( !checkConnection( op ) ) {
+ if ( op->state() != QNetworkProtocol::StFailed ) {
+ d->opStartTimer->start( 0, TRUE );
+ } else {
+ d->operationQueue.dequeue();
+ clearOperationQueue();
+ emit finished( op );
+ }
+
+ return;
+ }
+
+ d->opInProgress = op;
+ d->operationQueue.dequeue();
+ processOperation( op );
+}
+
+/*!
+ Returns the QUrlOperator on which the protocol works.
+*/
+
+QUrlOperator *QNetworkProtocol::url() const
+{
+ return d->url;
+}
+
+/*!
+ Returns the operation, which is being processed, or 0 of no
+ operation is being processed at the moment.
+*/
+
+QNetworkOperation *QNetworkProtocol::operationInProgress() const
+{
+ return d->opInProgress;
+}
+
+/*!
+ Clears the operation queue.
+*/
+
+void QNetworkProtocol::clearOperationQueue()
+{
+ d->operationQueue.dequeue();
+ d->operationQueue.setAutoDelete( TRUE );
+ d->operationQueue.clear();
+}
+
+/*!
+ Stops the current operation that is being processed and clears all
+ waiting operations.
+*/
+
+void QNetworkProtocol::stop()
+{
+ QNetworkOperation *op = d->opInProgress;
+ clearOperationQueue();
+ if ( op ) {
+ op->setState( StStopped );
+ op->setProtocolDetail( tr( "Operation stopped by the user" ) );
+ emit finished( op );
+ setUrl( 0 );
+ op->free();
+ }
+}
+
+/*!
+ Because it's sometimes hard to take care of removing network
+ protocol instances, QNetworkProtocol provides an auto-delete
+ mechanism. If you set \a b to TRUE, the network protocol instance
+ is removed after it has been inactive for \a i milliseconds (i.e.
+ \a i milliseconds after the last operation has been processed).
+ If you set \a b to FALSE the auto-delete mechanism is switched
+ off.
+
+ If you switch on auto-delete, the QNetworkProtocol also deletes
+ its QUrlOperator.
+*/
+
+void QNetworkProtocol::setAutoDelete( bool b, int i )
+{
+ d->autoDelete = b;
+ d->removeInterval = i;
+}
+
+/*!
+ Returns TRUE if auto-deleting is enabled; otherwise returns FALSE.
+
+ \sa QNetworkProtocol::setAutoDelete()
+*/
+
+bool QNetworkProtocol::autoDelete() const
+{
+ return d->autoDelete;
+}
+
+/*!
+ \internal
+*/
+
+void QNetworkProtocol::removeMe()
+{
+ if ( d->autoDelete ) {
+#ifdef QNETWORKPROTOCOL_DEBUG
+ qDebug( "QNetworkOperation: autodelete of QNetworkProtocol %p", this );
+#endif
+ delete d->url; // destructor deletes the network protocol
+ }
+}
+
+void QNetworkProtocol::emitNewChildren( const QUrlInfo &i, QNetworkOperation *op )
+{
+ QValueList<QUrlInfo> lst;
+ lst << i;
+ emit newChildren( lst, op );
+}
+
+class QNetworkOperationPrivate
+{
+public:
+ QNetworkProtocol::Operation operation;
+ QNetworkProtocol::State state;
+ QMap<int, QString> args;
+ QMap<int, QByteArray> rawArgs;
+ QString protocolDetail;
+ int errorCode;
+ QTimer *deleteTimer;
+};
+
+/*!
+ \class QNetworkOperation
+
+ \brief The QNetworkOperation class provides common operations for network protocols.
+\if defined(commercial)
+ It is part of the <a href="commercialeditions.html">Qt Enterprise Edition</a>.
+\endif
+
+ \module network
+ \ingroup io
+
+ An object is created to describe the operation and the current
+ state for each operation that a network protocol should process.
+
+ For a detailed description of the Qt Network Architecture and how
+ to implement and use network protocols in Qt, see the \link
+ network.html Qt Network Documentation\endlink.
+
+ \sa QNetworkProtocol
+*/
+
+/*!
+ Constructs a network operation object. \a operation is the type of
+ the operation, and \a arg0, \a arg1 and \a arg2 are the first
+ three arguments of the operation. The state is initialized to
+ QNetworkProtocol::StWaiting.
+
+ \sa QNetworkProtocol::Operation QNetworkProtocol::State
+*/
+
+QNetworkOperation::QNetworkOperation( QNetworkProtocol::Operation operation,
+ const QString &arg0, const QString &arg1,
+ const QString &arg2 )
+{
+ d = new QNetworkOperationPrivate;
+ d->deleteTimer = new QTimer( this );
+ connect( d->deleteTimer, SIGNAL( timeout() ),
+ this, SLOT( deleteMe() ) );
+ d->operation = operation;
+ d->state = QNetworkProtocol::StWaiting;
+ d->args[ 0 ] = arg0;
+ d->args[ 1 ] = arg1;
+ d->args[ 2 ] = arg2;
+ d->rawArgs[ 0 ] = QByteArray( 0 );
+ d->rawArgs[ 1 ] = QByteArray( 0 );
+ d->rawArgs[ 2 ] = QByteArray( 0 );
+ d->protocolDetail = QString::null;
+ d->errorCode = (int)QNetworkProtocol::NoError;
+}
+
+/*!
+ Constructs a network operation object. \a operation is the type of
+ the operation, and \a arg0, \a arg1 and \a arg2 are the first
+ three raw data arguments of the operation. The state is
+ initialized to QNetworkProtocol::StWaiting.
+
+ \sa QNetworkProtocol::Operation QNetworkProtocol::State
+*/
+
+QNetworkOperation::QNetworkOperation( QNetworkProtocol::Operation operation,
+ const QByteArray &arg0, const QByteArray &arg1,
+ const QByteArray &arg2 )
+{
+ d = new QNetworkOperationPrivate;
+ d->deleteTimer = new QTimer( this );
+ connect( d->deleteTimer, SIGNAL( timeout() ),
+ this, SLOT( deleteMe() ) );
+ d->operation = operation;
+ d->state = QNetworkProtocol::StWaiting;
+ d->args[ 0 ] = QString::null;
+ d->args[ 1 ] = QString::null;
+ d->args[ 2 ] = QString::null;
+ d->rawArgs[ 0 ] = arg0;
+ d->rawArgs[ 1 ] = arg1;
+ d->rawArgs[ 2 ] = arg2;
+ d->protocolDetail = QString::null;
+ d->errorCode = (int)QNetworkProtocol::NoError;
+}
+
+/*!
+ Destructor.
+*/
+
+QNetworkOperation::~QNetworkOperation()
+{
+ delete d;
+}
+
+/*!
+ Sets the \a state of the operation object. This should be done by
+ the network protocol during processing; at the end it should be
+ set to QNetworkProtocol::StDone or QNetworkProtocol::StFailed,
+ depending on success or failure.
+
+ \sa QNetworkProtocol::State
+*/
+
+void QNetworkOperation::setState( QNetworkProtocol::State state )
+{
+ if ( d->deleteTimer->isActive() ) {
+ d->deleteTimer->stop();
+ d->deleteTimer->start( NETWORK_OP_DELAY );
+ }
+ d->state = state;
+}
+
+/*!
+ If the operation failed, the error message can be specified as \a
+ detail.
+*/
+
+void QNetworkOperation::setProtocolDetail( const QString &detail )
+{
+ if ( d->deleteTimer->isActive() ) {
+ d->deleteTimer->stop();
+ d->deleteTimer->start( NETWORK_OP_DELAY );
+ }
+ d->protocolDetail = detail;
+}
+
+/*!
+ Sets the error code to \a ec.
+
+ If the operation failed, the protocol should set an error code to
+ describe the error in more detail. If possible, one of the error
+ codes defined in QNetworkProtocol should be used.
+
+ \sa setProtocolDetail() QNetworkProtocol::Error
+*/
+
+void QNetworkOperation::setErrorCode( int ec )
+{
+ if ( d->deleteTimer->isActive() ) {
+ d->deleteTimer->stop();
+ d->deleteTimer->start( NETWORK_OP_DELAY );
+ }
+ d->errorCode = ec;
+}
+
+/*!
+ Sets the network operation's \a{num}-th argument to \a arg.
+*/
+
+void QNetworkOperation::setArg( int num, const QString &arg )
+{
+ if ( d->deleteTimer->isActive() ) {
+ d->deleteTimer->stop();
+ d->deleteTimer->start( NETWORK_OP_DELAY );
+ }
+ d->args[ num ] = arg;
+}
+
+/*!
+ Sets the network operation's \a{num}-th raw data argument to \a arg.
+*/
+
+void QNetworkOperation::setRawArg( int num, const QByteArray &arg )
+{
+ if ( d->deleteTimer->isActive() ) {
+ d->deleteTimer->stop();
+ d->deleteTimer->start( NETWORK_OP_DELAY );
+ }
+ d->rawArgs[ num ] = arg;
+}
+
+/*!
+ Returns the type of the operation.
+*/
+
+QNetworkProtocol::Operation QNetworkOperation::operation() const
+{
+ if ( d->deleteTimer->isActive() ) {
+ d->deleteTimer->stop();
+ d->deleteTimer->start( NETWORK_OP_DELAY );
+ }
+ return d->operation;
+}
+
+/*!
+ Returns the state of the operation. You can determine whether an
+ operation is still waiting to be processed, is being processed,
+ has been processed successfully, or failed.
+*/
+
+QNetworkProtocol::State QNetworkOperation::state() const
+{
+ if ( d->deleteTimer->isActive() ) {
+ d->deleteTimer->stop();
+ d->deleteTimer->start( NETWORK_OP_DELAY );
+ }
+ return d->state;
+}
+
+/*!
+ Returns the operation's \a{num}-th argument. If this argument was
+ not already set, an empty string is returned.
+*/
+
+QString QNetworkOperation::arg( int num ) const
+{
+ if ( d->deleteTimer->isActive() ) {
+ d->deleteTimer->stop();
+ d->deleteTimer->start( NETWORK_OP_DELAY );
+ }
+ return d->args[ num ];
+}
+
+/*!
+ Returns the operation's \a{num}-th raw data argument. If this
+ argument was not already set, an empty bytearray is returned.
+*/
+
+QByteArray QNetworkOperation::rawArg( int num ) const
+{
+ if ( d->deleteTimer->isActive() ) {
+ d->deleteTimer->stop();
+ d->deleteTimer->start( NETWORK_OP_DELAY );
+ }
+ return d->rawArgs[ num ];
+}
+
+/*!
+ Returns a detailed error message for the last error. This must
+ have been set using setProtocolDetail().
+*/
+
+QString QNetworkOperation::protocolDetail() const
+{
+ if ( d->deleteTimer->isActive() ) {
+ d->deleteTimer->stop();
+ d->deleteTimer->start( NETWORK_OP_DELAY );
+ }
+ return d->protocolDetail;
+}
+
+/*!
+ Returns the error code for the last error that occurred.
+*/
+
+int QNetworkOperation::errorCode() const
+{
+ if ( d->deleteTimer->isActive() ) {
+ d->deleteTimer->stop();
+ d->deleteTimer->start( NETWORK_OP_DELAY );
+ }
+ return d->errorCode;
+}
+
+/*!
+ \internal
+*/
+
+QByteArray& QNetworkOperation::raw( int num ) const
+{
+ if ( d->deleteTimer->isActive() ) {
+ d->deleteTimer->stop();
+ d->deleteTimer->start( NETWORK_OP_DELAY );
+ }
+ return d->rawArgs[ num ];
+}
+
+/*!
+ Sets this object to delete itself when it hasn't been used for one
+ second.
+
+ Because QNetworkOperation pointers are passed around a lot the
+ QNetworkProtocol generally does not have enough knowledge to
+ delete these at the correct time. If a QNetworkProtocol doesn't
+ need an operation any more it will call this function instead.
+
+ Note: you should never need to call the method yourself.
+*/
+
+void QNetworkOperation::free()
+{
+ d->deleteTimer->start( NETWORK_OP_DELAY );
+}
+
+/*!
+ \internal
+ Internal slot for auto-deletion.
+*/
+
+void QNetworkOperation::deleteMe()
+{
+ delete this;
+}
+
+#endif