home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / qt3_emx.zip / examples / network / networkprotocol / nntp.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-11  |  7.2 KB  |  258 lines

  1. /****************************************************************************
  2. ** $Id:  qt/nntp.cpp   3.0.0   edited Jun 1 18:44 $
  3. **
  4. ** Copyright (C) 1992-2000 Trolltech AS.  All rights reserved.
  5. **
  6. ** This file is part of an example program for Qt.  This example
  7. ** program may be used, distributed and modified without limitation.
  8. **
  9. *****************************************************************************/
  10.  
  11. #include "nntp.h"
  12. #include <qurlinfo.h>
  13. #include <stdlib.h>
  14. #include <qurloperator.h>
  15. #include <qstringlist.h>
  16. #include <qregexp.h>
  17.  
  18. Nntp::Nntp()
  19.     : QNetworkProtocol(), connectionReady( FALSE ),
  20.       readGroups( FALSE ), readArticle( FALSE )
  21. {
  22.     // create the command socket and connect to its signals
  23.     commandSocket = new QSocket( this );
  24.     connect( commandSocket, SIGNAL( hostFound() ),
  25.          this, SLOT( hostFound() ) );
  26.     connect( commandSocket, SIGNAL( connected() ),
  27.          this, SLOT( connected() ) );
  28.     connect( commandSocket, SIGNAL( connectionClosed() ),
  29.          this, SLOT( closed() ) );
  30.     connect( commandSocket, SIGNAL( readyRead() ),
  31.          this, SLOT( readyRead() ) );
  32.     connect( commandSocket, SIGNAL( error( int ) ),
  33.          this, SLOT( error( int ) ) );
  34. }
  35.  
  36. Nntp::~Nntp()
  37. {
  38.     close();
  39.     delete commandSocket;
  40. }
  41.  
  42. void Nntp::operationListChildren( QNetworkOperation * )
  43. {
  44.     // create a command
  45.     QString path = url()->path(), cmd;
  46.     if ( path.isEmpty() || path == "/" ) {
  47.     // if the path is empty or we are in the root dir,
  48.     // we want to read the list of available newsgroups
  49.     cmd = "list newsgroups\r\n";
  50.     } else if ( url()->isDir() ) {
  51.     // if the path is a directory (in our case a news group)
  52.     // we want to list the articles of this group
  53.     path = path.replace( QRegExp( "/" ), "" );
  54.     cmd = "listgroup " + path + "\r\n";
  55.     } else
  56.     return;
  57.  
  58.     // write the command to the socket
  59.     commandSocket->writeBlock( cmd.latin1(), cmd.length() );
  60.     readGroups = TRUE;
  61. }
  62.  
  63. void Nntp::operationGet( QNetworkOperation *op )
  64. {
  65.     // get the dirPath of the URL (this is our news group)
  66.     // and the filename (which is the article we want to read)
  67.     QUrl u( op->arg( 0 ) );
  68.     QString dirPath = u.dirPath(), file = u.fileName();
  69.     dirPath = dirPath.replace( QRegExp( "/" ), "" );
  70.  
  71.     // go to the group in which the article is
  72.     QString cmd;
  73.     cmd = "group " + dirPath + "\r\n";
  74.     commandSocket->writeBlock( cmd.latin1(), cmd.length() );
  75.  
  76.     // read the head of the article
  77.     cmd = "article " + file + "\r\n";
  78.     commandSocket->writeBlock( cmd.latin1(), cmd.length() );
  79.     readArticle = TRUE;
  80. }
  81.  
  82. bool Nntp::checkConnection( QNetworkOperation * )
  83. {
  84.     // we are connected, return TRUE
  85.     if ( commandSocket->isOpen() && connectionReady )
  86.     return TRUE;
  87.  
  88.     // seems that there is no chance to connect
  89.     if ( commandSocket->isOpen() )
  90.     return FALSE;
  91.  
  92.     // don't call connectToHost() if we are already trying to connect
  93.     if ( commandSocket->state() == QSocket::Connecting )
  94.     return FALSE;
  95.  
  96.     // start connecting
  97.     connectionReady = FALSE;
  98.     commandSocket->connectToHost( url()->host(),
  99.                   url()->port() != -1 ? url()->port() : 119 );
  100.     return FALSE;
  101. }
  102.  
  103. void Nntp::close()
  104. {
  105.     // close the command socket
  106.     if ( commandSocket->isOpen() ) {
  107.      commandSocket->writeBlock( "quit\r\n", strlen( "quit\r\n" ) );
  108.      commandSocket->close();
  109.     }
  110. }
  111.  
  112. int Nntp::supportedOperations() const
  113. {
  114.     // we only support listing children and getting data
  115.     return OpListChildren | OpGet;
  116. }
  117.  
  118. void Nntp::hostFound()
  119. {
  120.     if ( url() )
  121.     emit connectionStateChanged( ConHostFound, tr( "Host %1 found" ).arg( url()->host() ) );
  122.     else
  123.     emit connectionStateChanged( ConHostFound, tr( "Host found" ) );
  124. }
  125.  
  126. void Nntp::connected()
  127. {
  128.     if ( url() )
  129.     emit connectionStateChanged( ConConnected, tr( "Connected to host %1" ).arg( url()->host() ) );
  130.     else
  131.     emit connectionStateChanged( ConConnected, tr( "Connected to host" ) );
  132. }
  133.  
  134. void Nntp::closed()
  135. {
  136.     if ( url() )
  137.     emit connectionStateChanged( ConClosed, tr( "Connection to %1 closed" ).arg( url()->host() ) );
  138.     else
  139.     emit connectionStateChanged( ConClosed, tr( "Connection closed" ) );
  140. }
  141.  
  142. void Nntp::readyRead()
  143. {
  144.     // new data arrived on the command socket
  145.  
  146.     // of we should read the list of available groups, let's do so
  147.     if ( readGroups ) {
  148.     parseGroups();
  149.     return;
  150.     }
  151.  
  152.     // of we should read an article, let's do so
  153.     if ( readArticle ) {
  154.     parseArticle();
  155.     return;
  156.     }
  157.  
  158.     // read the new data from the socket
  159.     QCString s;
  160.     s.resize( commandSocket->bytesAvailable() );
  161.     commandSocket->readBlock( s.data(), commandSocket->bytesAvailable() );
  162.  
  163.     if ( !url() )
  164.     return;
  165.  
  166.     // of the code of the server response was 200, we know that the
  167.     // server is ready to get commands from us now
  168.     if ( s.left( 3 ) == "200" )
  169.     connectionReady = TRUE;
  170. }
  171.  
  172. void Nntp::parseGroups()
  173. {
  174.     if ( !commandSocket->canReadLine() )
  175.     return;
  176.  
  177.     // read one line after the other
  178.     while ( commandSocket->canReadLine() ) {
  179.     QString s = commandSocket->readLine();
  180.  
  181.     // if the  line starts with a dot, all groups or articles have been listed,
  182.     // so we finished processing the listChildren() command
  183.     if ( s[ 0 ] == '.' ) {
  184.         readGroups = FALSE;
  185.         operationInProgress()->setState( StDone );
  186.         emit finished( operationInProgress() );
  187.         return;
  188.     }
  189.     
  190.     // if the code of the server response is 215 or 211
  191.     // the next line will be the first group or article (depending on what we read).
  192.     // So let others know that we start reading now...
  193.     if ( s.left( 3 ) == "215" || s.left( 3 ) == "211" ) {
  194.         operationInProgress()->setState( StInProgress );
  195.         emit start( operationInProgress() );
  196.         continue;
  197.     }
  198.     
  199.     // parse the line and create a QUrlInfo object
  200.     // which describes the child (group or article)
  201.     bool tab = s.find( '\t' ) != -1;
  202.     QString group = s.mid( 0, s.find( tab ? '\t' : ' ' ) );
  203.     QUrlInfo inf;
  204.     inf.setName( group );
  205.     QString path = url()->path();
  206.     inf.setDir( path.isEmpty() || path == "/" );
  207.     inf.setSymLink( FALSE );
  208.     inf.setFile( !inf.isDir() );
  209.     inf.setWritable( FALSE );
  210.     inf.setReadable( TRUE );
  211.     
  212.     // let others know about our new child
  213.     emit newChild( inf, operationInProgress() );
  214.     }
  215.     
  216. }
  217.  
  218. void Nntp::parseArticle()
  219. {
  220.     if ( !commandSocket->canReadLine() )
  221.     return;
  222.  
  223.     // read an article one line after the other
  224.     while ( commandSocket->canReadLine() ) {
  225.     QString s = commandSocket->readLine();
  226.  
  227.     // if the  line starts with a dot, we finished reading something
  228.     if ( s[ 0 ] == '.' ) {
  229.         readArticle = FALSE;
  230.         operationInProgress()->setState( StDone );
  231.         emit finished( operationInProgress() );
  232.         return;
  233.     }
  234.  
  235.     if ( s.right( 1 ) == "\n" )
  236.         s.remove( s.length() - 1, 1 );
  237.     
  238.     // emit the new data of the article which we read
  239.     emit data( QCString( s.ascii() ), operationInProgress() );
  240.     }
  241. }
  242.  
  243. void Nntp::error( int code )
  244. {
  245.     if ( code == QSocket::ErrHostNotFound ||
  246.      code == QSocket::ErrConnectionRefused ) {
  247.     // this signal is called if connecting to the server failed
  248.     if ( operationInProgress() ) {
  249.         QString msg = tr( "Host not found or couldn't connect to: \n" + url()->host() );
  250.         operationInProgress()->setState( StFailed );
  251.         operationInProgress()->setProtocolDetail( msg );
  252.         operationInProgress()->setErrorCode( (int)ErrHostNotFound );
  253.         clearOperationQueue();
  254.         emit finished( operationInProgress() );
  255.     }
  256.     }
  257. }
  258.