summaryrefslogtreecommitdiffstats
path: root/examples/network/networkprotocol/nntp.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'examples/network/networkprotocol/nntp.cpp')
-rw-r--r--examples/network/networkprotocol/nntp.cpp256
1 files changed, 256 insertions, 0 deletions
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() );
+ }
+ }
+}