summaryrefslogtreecommitdiffstats
path: root/examples/network/infoprotocol/infourlclient/qip.cpp
blob: ef71ea301dc95bc022070270041e6f7c1e503adf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/****************************************************************************
**
** 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 <qsocket.h>
#include <qurlinfo.h>
#include <qurloperator.h>
#include <qtextstream.h>

#include "qip.h"


Qip::Qip()
{
    state = Start;
    socket = new QSocket( this );
    connect( socket, SIGNAL(connected()), SLOT(socketConnected()) );
    connect( socket, SIGNAL(connectionClosed()), SLOT(socketConnectionClosed()) );
    connect( socket, SIGNAL(readyRead()), SLOT(socketReadyRead()) );
    connect( socket, SIGNAL(error(int)), SLOT(socketError(int)) );
}

int Qip::supportedOperations() const
{
    return OpListChildren | OpGet;
}

bool Qip::checkConnection( QNetworkOperation * )
{
    if ( socket->isOpen() )
	return TRUE;

    // don't call connectToHost() if we are already trying to connect
    if ( socket->state() == QSocket::Connecting )
	return FALSE;

    socket->connectToHost( url()->host(), url()->port() != -1 ? url()->port() : infoPort );
    return FALSE;
}

void Qip::operationListChildren( QNetworkOperation * )
{
    QTextStream os(socket);
    os << "LIST " + url()->path() + "\r\n";
    operationInProgress()->setState( StInProgress );
}

void Qip::operationGet( QNetworkOperation * )
{
    QTextStream os(socket);
    os << "GET " + url()->path() + "\r\n";
    operationInProgress()->setState( StInProgress );
}

void Qip::socketConnected()
{
    if ( url() )
	emit connectionStateChanged( ConConnected, tr( "Connected to host %1" ).arg( url()->host() ) );
    else
	emit connectionStateChanged( ConConnected, tr ("Connected to host" ) );
}

void Qip::socketConnectionClosed()
{
    if ( url() )
	emit connectionStateChanged( ConClosed, tr( "Connection to %1 closed" ).arg( url()->host() ) );
    else
	emit connectionStateChanged( ConClosed, tr ("Connection closed" ) );
}

void Qip::socketError( int code )
{
    if ( code == QSocket::ErrHostNotFound ||
	 code == QSocket::ErrConnectionRefused ) {
	error( ErrHostNotFound, tr( "Host not found or couldn't connect to: %1\n" ).arg( url()->host() ) );
    } else
	error( ErrUnsupported, tr( "Error" ) );
}

void Qip::socketReadyRead()
{
    // read from the server
    QTextStream stream( socket );
    QString line;
    while ( socket->canReadLine() ) {
	line = stream.readLine();
	if ( line.startsWith( "500" ) ) {
	    error( ErrValid, line.mid( 4 ) ); 
	} else if ( line.startsWith( "550" ) ) {
	    error( ErrFileNotExisting, line.mid( 4 ) ); 
	} else if ( line.startsWith( "212+" ) ) {
	    if ( state != List ) {
		state = List;
	        emit start( operationInProgress() );
	    }
	    QUrlInfo inf;
	    inf.setName( line.mid( 6 ) + QString( ( line[ 4 ] == 'D' ) ? "/" : "" ) );
	    inf.setDir( line[ 4 ] == 'D' );
	    inf.setSymLink( FALSE );
	    inf.setFile( line[ 4 ] == 'F' );
	    inf.setWritable( FALSE );
	    inf.setReadable( TRUE );
	    emit newChild( inf, operationInProgress() );
	} else if ( line.startsWith( "213+" ) ) {
	    state = Data;
	    emit data( line.mid( 4 ).utf8(), operationInProgress() );
	}
	if( line[3] == ' ' && state != Start) {
	    state = Start;
	    operationInProgress()->setState( StDone );
	    emit finished( operationInProgress() );
	}
    }
}

void Qip::error( int code, const QString& msg )
{
    if ( operationInProgress() ) {
	operationInProgress()->setState( StFailed );
	operationInProgress()->setErrorCode( code );
	operationInProgress()->setProtocolDetail( msg );
	clearOperationQueue();
	emit finished( operationInProgress() );
    }
    state = Start;
}