diff options
Diffstat (limited to 'examples/network/networkprotocol')
-rw-r--r-- | examples/network/networkprotocol/README | 5 | ||||
-rw-r--r-- | examples/network/networkprotocol/main.cpp | 29 | ||||
-rw-r--r-- | examples/network/networkprotocol/networkprotocol.doc | 26 | ||||
-rw-r--r-- | examples/network/networkprotocol/networkprotocol.pro | 10 | ||||
-rw-r--r-- | examples/network/networkprotocol/nntp.cpp | 256 | ||||
-rw-r--r-- | examples/network/networkprotocol/nntp.h | 49 | ||||
-rw-r--r-- | examples/network/networkprotocol/view.cpp | 90 | ||||
-rw-r--r-- | examples/network/networkprotocol/view.h | 37 |
8 files changed, 502 insertions, 0 deletions
diff --git a/examples/network/networkprotocol/README b/examples/network/networkprotocol/README new file mode 100644 index 0000000..7c1e69d --- /dev/null +++ b/examples/network/networkprotocol/README @@ -0,0 +1,5 @@ +This class shows you how to implement your own network protocols and how to +use them in a program. This example is part of the network module. + +The class Nntp implements the nntp protocol. The implementation of the +protocol is not complete and should not be used in real programs. diff --git a/examples/network/networkprotocol/main.cpp b/examples/network/networkprotocol/main.cpp new file mode 100644 index 0000000..8d636e4 --- /dev/null +++ b/examples/network/networkprotocol/main.cpp @@ -0,0 +1,29 @@ +/**************************************************************************** +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of an example program for Qt. This example +** program may be used, distributed and modified without limitation. +** +*****************************************************************************/ + +#include <qapplication.h> +#include <qnetwork.h> + +#include "nntp.h" +#include "view.h" + +int main( int argc, char **argv ) +{ + QApplication a( argc, argv ); + + qInitNetworkProtocols(); + QNetworkProtocol::registerNetworkProtocol( "nntp", new QNetworkProtocolFactory<Nntp> ); + + View v; + v.resize( 600, 600 ); + v.show(); + a.setMainWidget( &v ); + + return a.exec(); +} diff --git a/examples/network/networkprotocol/networkprotocol.doc b/examples/network/networkprotocol/networkprotocol.doc new file mode 100644 index 0000000..ea00797 --- /dev/null +++ b/examples/network/networkprotocol/networkprotocol.doc @@ -0,0 +1,26 @@ +/* +*/ + +/*! \page networkprotocol-example.html + + \ingroup network-examples + + \title A simple NNTP implementation + + This example shows how to implement your own QNetworkProtocol. The + protocol that was chosen for this example is NTTP. Please note that this + implementation is very simple since it is designed to be an example. It + should not be used as a real NNTP implemention. + + <hr> + + Header file (nntp.h): + + \include network/networkprotocol/nntp.h + + <hr> + + Implementation (nntp.cpp): + + \include network/networkprotocol/nntp.cpp +*/ diff --git a/examples/network/networkprotocol/networkprotocol.pro b/examples/network/networkprotocol/networkprotocol.pro new file mode 100644 index 0000000..1c6ea07 --- /dev/null +++ b/examples/network/networkprotocol/networkprotocol.pro @@ -0,0 +1,10 @@ +TEMPLATE = app +TARGET = networkprotocol + +CONFIG += qt warn_on release + +REQUIRES = network full-config + +HEADERS = nntp.h view.h +SOURCES = main.cpp \ + nntp.cpp view.cpp diff --git a/examples/network/networkprotocol/nntp.cpp b/examples/network/networkprotocol/nntp.cpp new file mode 100644 index 0000000..1307b9b --- /dev/null +++ b/examples/network/networkprotocol/nntp.cpp @@ -0,0 +1,256 @@ +/**************************************************************************** +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of an example program for Qt. This example +** program may be used, distributed and modified without limitation. +** +*****************************************************************************/ + +#include "nntp.h" +#include <qurlinfo.h> +#include <stdlib.h> +#include <qurloperator.h> +#include <qstringlist.h> +#include <qregexp.h> + +Nntp::Nntp() + : QNetworkProtocol(), connectionReady( FALSE ), + readGroups( FALSE ), readArticle( FALSE ) +{ + // create the command socket and connect to its signals + commandSocket = new QSocket( this ); + connect( commandSocket, SIGNAL( hostFound() ), + this, SLOT( hostFound() ) ); + connect( commandSocket, SIGNAL( connected() ), + this, SLOT( connected() ) ); + connect( commandSocket, SIGNAL( connectionClosed() ), + this, SLOT( closed() ) ); + connect( commandSocket, SIGNAL( readyRead() ), + this, SLOT( readyRead() ) ); + connect( commandSocket, SIGNAL( error( int ) ), + this, SLOT( error( int ) ) ); +} + +Nntp::~Nntp() +{ + close(); + delete commandSocket; +} + +void Nntp::operationListChildren( QNetworkOperation * ) +{ + // create a command + QString path = url()->path(), cmd; + if ( path.isEmpty() || path == "/" ) { + // if the path is empty or we are in the root dir, + // we want to read the list of available newsgroups + cmd = "list newsgroups\r\n"; + } else if ( url()->isDir() ) { + // if the path is a directory (in our case a news group) + // we want to list the articles of this group + path = path.replace( "/", "" ); + cmd = "listgroup " + path + "\r\n"; + } else + return; + + // write the command to the socket + commandSocket->writeBlock( cmd.latin1(), cmd.length() ); + readGroups = TRUE; +} + +void Nntp::operationGet( QNetworkOperation *op ) +{ + // get the dirPath of the URL (this is our news group) + // and the filename (which is the article we want to read) + QUrl u( op->arg( 0 ) ); + QString dirPath = u.dirPath(), file = u.fileName(); + dirPath = dirPath.replace( "/", "" ); + + // go to the group in which the article is + QString cmd; + cmd = "group " + dirPath + "\r\n"; + commandSocket->writeBlock( cmd.latin1(), cmd.length() ); + + // read the head of the article + cmd = "article " + file + "\r\n"; + commandSocket->writeBlock( cmd.latin1(), cmd.length() ); + readArticle = TRUE; +} + +bool Nntp::checkConnection( QNetworkOperation * ) +{ + // we are connected, return TRUE + if ( commandSocket->isOpen() && connectionReady ) + return TRUE; + + // seems that there is no chance to connect + if ( commandSocket->isOpen() ) + return FALSE; + + // don't call connectToHost() if we are already trying to connect + if ( commandSocket->state() == QSocket::Connecting ) + return FALSE; + + // start connecting + connectionReady = FALSE; + commandSocket->connectToHost( url()->host(), + url()->port() != -1 ? url()->port() : 119 ); + return FALSE; +} + +void Nntp::close() +{ + // close the command socket + if ( commandSocket->isOpen() ) { + commandSocket->writeBlock( "quit\r\n", strlen( "quit\r\n" ) ); + commandSocket->close(); + } +} + +int Nntp::supportedOperations() const +{ + // we only support listing children and getting data + return OpListChildren | OpGet; +} + +void Nntp::hostFound() +{ + if ( url() ) + emit connectionStateChanged( ConHostFound, tr( "Host %1 found" ).arg( url()->host() ) ); + else + emit connectionStateChanged( ConHostFound, tr( "Host found" ) ); +} + +void Nntp::connected() +{ + if ( url() ) + emit connectionStateChanged( ConConnected, tr( "Connected to host %1" ).arg( url()->host() ) ); + else + emit connectionStateChanged( ConConnected, tr( "Connected to host" ) ); +} + +void Nntp::closed() +{ + if ( url() ) + emit connectionStateChanged( ConClosed, tr( "Connection to %1 closed" ).arg( url()->host() ) ); + else + emit connectionStateChanged( ConClosed, tr( "Connection closed" ) ); +} + +void Nntp::readyRead() +{ + // new data arrived on the command socket + + // of we should read the list of available groups, let's do so + if ( readGroups ) { + parseGroups(); + return; + } + + // of we should read an article, let's do so + if ( readArticle ) { + parseArticle(); + return; + } + + // read the new data from the socket + QCString s; + s.resize( commandSocket->bytesAvailable() + 1 ); + commandSocket->readBlock( s.data(), commandSocket->bytesAvailable() ); + + if ( !url() ) + return; + + // of the code of the server response was 200, we know that the + // server is ready to get commands from us now + if ( s.left( 3 ) == "200" ) + connectionReady = TRUE; +} + +void Nntp::parseGroups() +{ + if ( !commandSocket->canReadLine() ) + return; + + // read one line after the other + while ( commandSocket->canReadLine() ) { + QString s = commandSocket->readLine(); + + // if the line starts with a dot, all groups or articles have been listed, + // so we finished processing the listChildren() command + if ( s[ 0 ] == '.' ) { + readGroups = FALSE; + operationInProgress()->setState( StDone ); + emit finished( operationInProgress() ); + return; + } + + // if the code of the server response is 215 or 211 + // the next line will be the first group or article (depending on what we read). + // So let others know that we start reading now... + if ( s.left( 3 ) == "215" || s.left( 3 ) == "211" ) { + operationInProgress()->setState( StInProgress ); + emit start( operationInProgress() ); + continue; + } + + // parse the line and create a QUrlInfo object + // which describes the child (group or article) + bool tab = s.find( '\t' ) != -1; + QString group = s.mid( 0, s.find( tab ? '\t' : ' ' ) ); + QUrlInfo inf; + inf.setName( group ); + QString path = url()->path(); + inf.setDir( path.isEmpty() || path == "/" ); + inf.setSymLink( FALSE ); + inf.setFile( !inf.isDir() ); + inf.setWritable( FALSE ); + inf.setReadable( TRUE ); + + // let others know about our new child + emit newChild( inf, operationInProgress() ); + } + +} + +void Nntp::parseArticle() +{ + if ( !commandSocket->canReadLine() ) + return; + + // read an article one line after the other + while ( commandSocket->canReadLine() ) { + QString s = commandSocket->readLine(); + + // if the line starts with a dot, we finished reading something + if ( s[ 0 ] == '.' ) { + readArticle = FALSE; + operationInProgress()->setState( StDone ); + emit finished( operationInProgress() ); + return; + } + + if ( s.right( 1 ) == "\n" ) + s.remove( s.length() - 1, 1 ); + + // emit the new data of the article which we read + emit data( QCString( s.ascii() ), operationInProgress() ); + } +} + +void Nntp::error( int code ) +{ + if ( code == QSocket::ErrHostNotFound || + code == QSocket::ErrConnectionRefused ) { + // this signal is called if connecting to the server failed + if ( operationInProgress() ) { + QString msg = tr( "Host not found or couldn't connect to: \n" + url()->host() ); + operationInProgress()->setState( StFailed ); + operationInProgress()->setProtocolDetail( msg ); + operationInProgress()->setErrorCode( (int)ErrHostNotFound ); + clearOperationQueue(); + emit finished( operationInProgress() ); + } + } +} diff --git a/examples/network/networkprotocol/nntp.h b/examples/network/networkprotocol/nntp.h new file mode 100644 index 0000000..82a8142 --- /dev/null +++ b/examples/network/networkprotocol/nntp.h @@ -0,0 +1,49 @@ +/**************************************************************************** +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of an example program for Qt. This example +** program may be used, distributed and modified without limitation. +** +*****************************************************************************/ + +#ifndef NNTP_H +#define NNTP_H + +#include <qsocket.h> +#include <qnetworkprotocol.h> + +class Nntp : public QNetworkProtocol +{ + Q_OBJECT + +public: + Nntp(); + virtual ~Nntp(); + virtual int supportedOperations() const; + +protected: + virtual void operationListChildren( QNetworkOperation *op ); + virtual void operationGet( QNetworkOperation *op ); + + QSocket *commandSocket; + bool connectionReady; + bool readGroups; + bool readArticle; + +private: + bool checkConnection( QNetworkOperation *op ); + void close(); + void parseGroups(); + void parseArticle(); + +protected slots: + void hostFound(); + void connected(); + void closed(); + void readyRead(); + void error( int ); + +}; + +#endif diff --git a/examples/network/networkprotocol/view.cpp b/examples/network/networkprotocol/view.cpp new file mode 100644 index 0000000..fed5bdf --- /dev/null +++ b/examples/network/networkprotocol/view.cpp @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of an example program for Qt. This example +** program may be used, distributed and modified without limitation. +** +*****************************************************************************/ + +#include "view.h" + +#include <qlabel.h> +#include <qpushbutton.h> +#include <qmultilineedit.h> +#include <qfiledialog.h> + +View::View() + : QVBox() +{ + // setup the GUI + setSpacing( 5 ); + setMargin( 5 ); + + QLabel *l = new QLabel( this ); + l->setAlignment( Qt::WordBreak ), + l->setText( tr( "The button below opens the QFileDialog and you " + "can choose a file then which is downloaded and " + "opened below then. You can use for that the <b>local " + "filesystem</b> using the file protocol, you can download " + "files from an <b>FTP</b> server using the ftp protocol and " + "you can download and open <b>USENET</b> articles using the " + "demo implementation of the nntp protocol of this " + "example (<i>This implementation of the nntp protocol is a very " + "basic and incomplete one, so you need to connect to a news server " + "which allows reading without authentification</i>)\n" + "To open a file from the local filesystem, enter in the " + "path combobox of the file dialog a url starting with file " + "(like <u>file:/usr/bin</u>), to download something from an FTP " + "server, use something like <u>ftp://ftp.trolltech.com</u> as url, and " + "for downloading a news article start with an url like " + "<u>nntp://news.tu-graz.ac.at</u> " ) ); + QPushButton *b = new QPushButton( tr( "Open a file..." ), this ); + connect( b, SIGNAL( clicked() ), + this, SLOT( downloadFile() ) ); + + fileView = new QMultiLineEdit( this ); + fileView->setReadOnly( TRUE ); + + // if new data comes in, display it + connect( &op, SIGNAL( data( const QByteArray &, QNetworkOperation * ) ), + this, SLOT( newData( const QByteArray & ) ) ); +} + +void View::downloadFile() +{ + // QString file = QFileDialog::getOpenFileName(); + // under Windows you must not use the native file dialog + QString file = getOpenFileName(); + if ( !file.isEmpty() ) { + // clear the view + fileView->clear(); + + // download the data + op = file; + op.get(); + } +} + +QString View::getOpenFileName() +{ + static QString workingDirectory = QDir::currentDirPath(); + + QFileDialog *dlg = new QFileDialog( workingDirectory, + QString::null, 0, 0, TRUE ); + dlg->setCaption( QFileDialog::tr( "Open" ) ); + dlg->setMode( QFileDialog::ExistingFile ); + QString result; + if ( dlg->exec() == QDialog::Accepted ) { + result = dlg->selectedFile(); + workingDirectory = dlg->url(); + } + delete dlg; + return result; +} + +void View::newData( const QByteArray &ba ) +{ + // append new data + fileView->append( ba ); +} diff --git a/examples/network/networkprotocol/view.h b/examples/network/networkprotocol/view.h new file mode 100644 index 0000000..9baba75 --- /dev/null +++ b/examples/network/networkprotocol/view.h @@ -0,0 +1,37 @@ +/**************************************************************************** +** +** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved. +** +** This file is part of an example program for Qt. This example +** program may be used, distributed and modified without limitation. +** +*****************************************************************************/ + +#ifndef VIEW_H +#define VIEW_H + +#include <qvbox.h> +#include <qcstring.h> +#include <qurloperator.h> + +class QMultiLineEdit; + +class View : public QVBox +{ + Q_OBJECT + +public: + View(); + +private slots: + void downloadFile(); + void newData( const QByteArray &ba ); + +private: + QMultiLineEdit *fileView; + QUrlOperator op; + + QString getOpenFileName(); +}; + +#endif |