From dba036816b279bc1539a9f3894fbc414665d2bce Mon Sep 17 00:00:00 2001 From: Michele Calgaro Date: Sun, 21 Apr 2019 23:22:20 +0900 Subject: Removed unnecessary and/or TDE-unrelated code. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michele Calgaro Signed-off-by: Slávek Banko --- tqtinterface/qt4/src/network/qt_network.pri | 23 - tqtinterface/qt4/src/network/tqdns.cpp | 5294 -------------------- tqtinterface/qt4/src/network/tqdns.h | 382 -- tqtinterface/qt4/src/network/tqftp.cpp | 2421 --------- tqtinterface/qt4/src/network/tqftp.h | 204 - tqtinterface/qt4/src/network/tqhostaddress.cpp | 459 -- tqtinterface/qt4/src/network/tqhostaddress.h | 131 - tqtinterface/qt4/src/network/tqhttp.cpp | 2384 --------- tqtinterface/qt4/src/network/tqhttp.h | 278 - tqtinterface/qt4/src/network/tqnetwork.cpp | 71 - tqtinterface/qt4/src/network/tqnetwork.h | 60 - tqtinterface/qt4/src/network/tqserversocket.cpp | 297 -- tqtinterface/qt4/src/network/tqserversocket.h | 95 - tqtinterface/qt4/src/network/tqsocket.cpp | 1668 ------ tqtinterface/qt4/src/network/tqsocket.h | 174 - tqtinterface/qt4/src/network/tqsocketdevice.cpp | 584 --- tqtinterface/qt4/src/network/tqsocketdevice.h | 185 - .../qt4/src/network/tqsocketdevice_unix.cpp | 1269 ----- 18 files changed, 15979 deletions(-) delete mode 100644 tqtinterface/qt4/src/network/qt_network.pri delete mode 100644 tqtinterface/qt4/src/network/tqdns.cpp delete mode 100644 tqtinterface/qt4/src/network/tqdns.h delete mode 100644 tqtinterface/qt4/src/network/tqftp.cpp delete mode 100644 tqtinterface/qt4/src/network/tqftp.h delete mode 100644 tqtinterface/qt4/src/network/tqhostaddress.cpp delete mode 100644 tqtinterface/qt4/src/network/tqhostaddress.h delete mode 100644 tqtinterface/qt4/src/network/tqhttp.cpp delete mode 100644 tqtinterface/qt4/src/network/tqhttp.h delete mode 100644 tqtinterface/qt4/src/network/tqnetwork.cpp delete mode 100644 tqtinterface/qt4/src/network/tqnetwork.h delete mode 100644 tqtinterface/qt4/src/network/tqserversocket.cpp delete mode 100644 tqtinterface/qt4/src/network/tqserversocket.h delete mode 100644 tqtinterface/qt4/src/network/tqsocket.cpp delete mode 100644 tqtinterface/qt4/src/network/tqsocket.h delete mode 100644 tqtinterface/qt4/src/network/tqsocketdevice.cpp delete mode 100644 tqtinterface/qt4/src/network/tqsocketdevice.h delete mode 100644 tqtinterface/qt4/src/network/tqsocketdevice_unix.cpp (limited to 'tqtinterface/qt4/src/network') diff --git a/tqtinterface/qt4/src/network/qt_network.pri b/tqtinterface/qt4/src/network/qt_network.pri deleted file mode 100644 index 6b8986a..0000000 --- a/tqtinterface/qt4/src/network/qt_network.pri +++ /dev/null @@ -1,23 +0,0 @@ -# Qt network module - -network { - HEADERS += $$NETWORK_H/tqdns.h \ - $$NETWORK_H/tqftp.h \ - $$NETWORK_H/tqhttp.h \ - $$NETWORK_H/tqhostaddress.h \ - $$NETWORK_H/tqnetwork.h \ - $$NETWORK_H/tqserversocket.h \ - $$NETWORK_H/tqsocket.h \ - $$NETWORK_H/tqsocketdevice.h - NETWORK_SOURCES = $$NETWORK_CPP/tqdns.cpp \ - $$NETWORK_CPP/tqftp.cpp \ - $$NETWORK_CPP/tqhttp.cpp \ - $$NETWORK_CPP/tqhostaddress.cpp \ - $$NETWORK_CPP/tqnetwork.cpp \ - $$NETWORK_CPP/tqserversocket.cpp \ - $$NETWORK_CPP/tqsocket.cpp \ - $$NETWORK_CPP/tqsocketdevice.cpp - unix:NETWORK_SOURCES += $$NETWORK_CPP/tqsocketdevice_unix.cpp - win32:NETWORK_SOURCES += $$NETWORK_CPP/tqsocketdevice_win.cpp - SOURCES += $$NETWORK_SOURCES -} diff --git a/tqtinterface/qt4/src/network/tqdns.cpp b/tqtinterface/qt4/src/network/tqdns.cpp deleted file mode 100644 index 4ba3a85..0000000 --- a/tqtinterface/qt4/src/network/tqdns.cpp +++ /dev/null @@ -1,5294 +0,0 @@ -#include "tqtglobaldefines.h" - -#ifdef USE_QT4 - -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the Qt3Support module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -// #include "Qt/qplatformdefs.h" - -#include "Qt/qbytearray.h" -#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) || defined(Q_OS_CYGWIN) -# include "qt_windows.h" -#else -# include -# include -# include -# include -extern "C" int res_init(); -#endif - -// POSIX Large File Support redefines open -> open64 -#if defined(open) -# undef open -#endif - -// POSIX Large File Support redefines truncate -> truncate64 -#if defined(truncate) -# undef truncate -#endif - -// Solaris redefines connect -> __xnet_connect with _XOPEN_SOURCE_EXTENDED. -#if defined(connect) -# undef connect -#endif - -// UnixWare 7 redefines socket -> _socket -#if defined(socket) -# undef socket -#endif - -#include "tqdns.h" - -#ifndef QT_NO_DNS - -#include "Qt/qdatetime.h" -#include "tqdict.h" -#include "tqptrlist.h" -#include "Qt/qstring.h" -#include "Qt/qtimer.h" -#include "Qt/qapplication.h" -#include "tqptrvector.h" -#include "tqstrlist.h" -#include "tqptrdict.h" -#include "Qt/qfile.h" -#include "Qt/qtextstream.h" -#include "tqsocketdevice.h" -#include "tqcleanuphandler.h" -#include - -// #include "Qt/qhostaddress.h" -// #include "Qt/qsocketnotifier.h" - -QT_BEGIN_NAMESPACE - -//#define TQDNS_DEBUG - -static Q_UINT16 theId; // ### seeded started by now() - - -static QDateTime * originOfTime = 0; - -static TQCleanupHandler q3dns_cleanup_time; - -static Q_UINT32 now() -{ - if ( originOfTime ) - return originOfTime->secsTo( QDateTime::currentDateTime() ); - - originOfTime = new QDateTime( QDateTime::currentDateTime() ); - theId = originOfTime->time().msec() * 60 + originOfTime->time().second(); - q3dns_cleanup_time.add( &originOfTime ); - return 0; -} - - -static TQPtrList * theNs = 0; -static TQStrList * theDomains = 0; -static bool ipv6support = false; - -class TQDnsPrivate { -public: - TQDnsPrivate() : queryTimer( 0 ), noNames(false) - { -#if defined(Q_DNS_SYNCHRONOUS) -#if defined(Q_OS_UNIX) - noEventLoop = qApp==0 || qApp->loopLevel()==0; -#else - noEventLoop = false; -#endif -#endif - } - ~TQDnsPrivate() - { - delete queryTimer; - } -private: - TQTimer * queryTimer; - bool noNames; -#if defined(Q_DNS_SYNCHRONOUS) - bool noEventLoop; -#endif - - friend class TQDns; - friend class TQDnsAnswer; -}; - - -class TQDnsRR; -class TQDnsDomain; - - - -// TQDnsRR is the class used to store a single RR. TQDnsRR can store -// all of the supported RR types. a TQDnsRR is always cached. - -// TQDnsRR is mostly constructed from the outside. a but hacky, but -// permissible since the entire class is internal. - -class TQDnsRR { -public: - TQDnsRR( const TQString & label ); - ~TQDnsRR(); - -public: - TQDnsDomain * domain; - TQDns::RecordType t; - bool nxdomain; - bool current; - Q_UINT32 expireTime; - Q_UINT32 deleteTime; - // somewhat space-wasting per-type data - // a / aaaa - TQHostAddress address; - // cname / mx / srv / ptr - TQString target; - // mx / srv - Q_UINT16 priority; - // srv - Q_UINT16 weight; - Q_UINT16 port; - // txt - TQString text; // could be overloaded into target... -private: - -}; - - -class TQDnsDomain { -public: - TQDnsDomain( const TQString & label ); - ~TQDnsDomain(); - - static void add( const TQString & label, TQDnsRR * ); - static TQPtrList * cached( const TQDns * ); - - void take( TQDnsRR * ); - - void sweep( Q_UINT32 thisSweep ); - - bool isEmpty() const { return rrs == 0 || rrs->isEmpty(); } - - TQString name() const { return l; } - -public: - TQString l; - TQPtrList * rrs; -}; - - -class TQDnsQuery: public TQTimer { // this inheritance is a very evil hack -public: - TQDnsQuery(): - id( 0 ), t( TQDns::None ), step(0), started(0), - dns( new TQPtrDict(17) ) {} - ~TQDnsQuery() { delete dns; } - Q_UINT16 id; - TQDns::RecordType t; - TQString l; - - uint step; - Q_UINT32 started; - - TQPtrDict * dns; -}; - - - -class TQDnsAnswer { -public: - TQDnsAnswer( TQDnsQuery * ); - TQDnsAnswer( const TQByteArray &, TQDnsQuery * ); - ~TQDnsAnswer(); - - void parse(); - void notify(); - - bool ok; - -private: - TQDnsQuery * query; - - Q_UINT8 * answer; - int size; - int pp; - - TQPtrList * rrs; - - // convenience - int next; - int ttl; - TQString label; - TQDnsRR * rr; - - TQString readString(bool multipleLabels = true); - void parseA(); - void parseAaaa(); - void parseMx(); - void parseSrv(); - void parseCname(); - void parsePtr(); - void parseTxt(); - void parseNs(); -}; - - -TQDnsRR::TQDnsRR( const TQString & label ) - : domain( 0 ), t( TQDns::None ), - nxdomain( false ), current( false ), - expireTime( 0 ), deleteTime( 0 ), - priority( 0 ), weight( 0 ), port( 0 ) -{ - TQDnsDomain::add( label, this ); -} - - -// not supposed to be deleted except by TQDnsDomain -TQDnsRR::~TQDnsRR() -{ - // nothing is necessary -} - - -// this one just sticks in a NXDomain -TQDnsAnswer::TQDnsAnswer( TQDnsQuery * query_ ) -{ - ok = true; - - answer = 0; - size = 0; - query = query_; - pp = 0; - rrs = new TQPtrList; - rrs->setAutoDelete( false ); - next = size; - ttl = 0; - label.clear(); - rr = 0; - - TQDnsRR * newrr = new TQDnsRR( query->l ); - newrr->t = query->t; - newrr->deleteTime = query->started + 10; - newrr->expireTime = query->started + 10; - newrr->nxdomain = true; - newrr->current = true; - rrs->append( newrr ); -} - - -TQDnsAnswer::TQDnsAnswer( const TQByteArray& answer_, - TQDnsQuery * query_ ) -{ - ok = true; - - answer = (Q_UINT8 *)(answer_.data()); - size = (int)answer_.size(); - query = query_; - pp = 0; - rrs = new TQPtrList; - rrs->setAutoDelete( false ); - next = size; - ttl = 0; - label.clear(); - rr = 0; -} - - -TQDnsAnswer::~TQDnsAnswer() -{ - if ( !ok && rrs ) { - TQPtrListIterator it( *rrs ); - TQDnsRR * tmprr; - while( (tmprr=it.current()) != 0 ) { - ++it; - tmprr->t = TQDns::None; // will be deleted soonish - } - } - delete rrs; -} - - -TQString TQDnsAnswer::readString(bool multipleLabels) -{ - int p = pp; - TQString r; - Q_UINT8 b; - for( ;; ) { - b = 128; - // Read one character - if ( p >= 0 && p < size ) - b = answer[p]; - - switch( b >> 6 ) { - case 0: - // b is less than 64 - p++; - - // Detect end of data - if ( b == 0 ) { - if ( p > pp ) - pp = p; - return r.isNull() ? TQT_TQSTRING(TQLatin1String( "." )) : r; - } - - // Read a label of size 'b' characters - if ( !r.isNull() ) - r += QLatin1Char('.'); - while( b-- > 0 ) - r += QLatin1Char( answer[p++] ); - - // Return immediately if we were only supposed to read one - // label. - if (!multipleLabels) - return r; - - break; - default: - // Ignore unrecognized control character, or p was out of - // range. - goto not_ok; - case 3: - // Use the next character to determine the relative offset - // to jump to before continuing the packet parsing. - int q = ( (answer[p] & 0x3f) << 8 ) + answer[p+1]; - - if ( q >= pp || q >= p ) - goto not_ok; - if ( p >= pp ) - pp = p + 2; - p = q; - } - } -not_ok: - ok = false; - return TQString(); -} - - - -void TQDnsAnswer::parseA() -{ - if ( next != pp + 4 ) { -#if defined(TQDNS_DEBUG) - qDebug( "TQDns: saw %d bytes long IN A for %s", - next - pp, label.ascii() ); -#endif - return; - } - - rr = new TQDnsRR( label ); - rr->t = TQDns::A; - rr->address = TQHostAddress( ( answer[pp+0] << 24 ) + - ( answer[pp+1] << 16 ) + - ( answer[pp+2] << 8 ) + - ( answer[pp+3] ) ); -#if defined(TQDNS_DEBUG) - qDebug( "TQDns: saw %s IN A %s (ttl %d)", label.ascii(), - rr->address.toString().ascii(), ttl ); -#endif -} - - -void TQDnsAnswer::parseAaaa() -{ - if ( next != pp + 16 ) { -#if defined(TQDNS_DEBUG) - qDebug( "TQDns: saw %d bytes long IN Aaaa for %s", - next - pp, label.ascii() ); -#endif - return; - } - - rr = new TQDnsRR( label ); - rr->t = TQDns::Aaaa; - rr->address = TQHostAddress( answer+pp ); -#if defined(TQDNS_DEBUG) - qDebug( "TQDns: saw %s IN Aaaa %s (ttl %d)", label.ascii(), - rr->address.toString().ascii(), ttl ); -#endif -} - - - -void TQDnsAnswer::parseMx() -{ - if ( next < pp + 2 ) { -#if defined(TQDNS_DEBUG) - qDebug( "TQDns: saw %d bytes long IN MX for %s", - next - pp, label.ascii() ); -#endif - return; - } - - rr = new TQDnsRR( label ); - rr->priority = (answer[pp] << 8) + answer[pp+1]; - pp += 2; - rr->target = readString().lower(); - if ( !ok ) { -#if defined(TQDNS_DEBUG) - qDebug( "TQDns: saw bad string in MX for %s", label.ascii() ); -#endif - return; - } - rr->t = TQDns::Mx; -#if defined(TQDNS_DEBUG) - qDebug( "TQDns: saw %s IN MX %d %s (ttl %d)", label.ascii(), - rr->priority, rr->target.ascii(), ttl ); -#endif -} - - -void TQDnsAnswer::parseSrv() -{ - if ( next < pp + 6 ) { -#if defined(TQDNS_DEBUG) - qDebug( "TQDns: saw %d bytes long IN SRV for %s", - next - pp, label.ascii() ); -#endif - return; - } - - rr = new TQDnsRR( label ); - rr->priority = (answer[pp] << 8) + answer[pp+1]; - rr->weight = (answer[pp+2] << 8) + answer[pp+3]; - rr->port = (answer[pp+4] << 8) + answer[pp+5]; - pp += 6; - rr->target = readString().lower(); - if ( !ok ) { -#if defined(TQDNS_DEBUG) - qDebug( "TQDns: saw bad string in SRV for %s", label.ascii() ); -#endif - return; - } - rr->t = TQDns::Srv; -#if defined(TQDNS_DEBUG) - qDebug( "TQDns: saw %s IN SRV %d %d %d %s (ttl %d)", label.ascii(), - rr->priority, rr->weight, rr->port, rr->target.ascii(), ttl ); -#endif -} - - -void TQDnsAnswer::parseCname() -{ - TQString target = readString().lower(); - if ( !ok ) { -#if defined(TQDNS_DEBUG) - qDebug( "TQDns: saw bad cname for for %s", label.ascii() ); -#endif - return; - } - - rr = new TQDnsRR( label ); - rr->t = TQDns::Cname; - rr->target = target; -#if defined(TQDNS_DEBUG) - qDebug( "TQDns: saw %s IN CNAME %s (ttl %d)", label.ascii(), - rr->target.ascii(), ttl ); -#endif -} - - -void TQDnsAnswer::parseNs() -{ - TQString target = readString().lower(); - if ( !ok ) { -#if defined(TQDNS_DEBUG) - qDebug( "TQDns: saw bad cname for for %s", label.ascii() ); -#endif - return; - } - - // parse, but ignore - -#if defined(TQDNS_DEBUG) - qDebug( "TQDns: saw %s IN NS %s (ttl %d)", label.ascii(), - target.ascii(), ttl ); -#endif -} - - -void TQDnsAnswer::parsePtr() -{ - TQString target = readString().lower(); - if ( !ok ) { -#if defined(TQDNS_DEBUG) - qDebug( "TQDns: saw bad PTR for for %s", label.ascii() ); -#endif - return; - } - - rr = new TQDnsRR( label ); - rr->t = TQDns::Ptr; - rr->target = target; -#if defined(TQDNS_DEBUG) - qDebug( "TQDns: saw %s IN PTR %s (ttl %d)", label.ascii(), - rr->target.ascii(), ttl ); -#endif -} - - -void TQDnsAnswer::parseTxt() -{ - TQString text = readString(false); - if ( !ok ) { -#if defined(TQDNS_DEBUG) - qDebug( "TQDns: saw bad TXT for for %s", label.ascii() ); -#endif - return; - } - - rr = new TQDnsRR( label ); - rr->t = TQDns::Txt; - rr->text = text; -#if defined(TQDNS_DEBUG) - qDebug( "TQDns: saw %s IN TXT \"%s\" (ttl %d)", label.ascii(), - rr->text.ascii(), ttl ); -#endif -} - - -void TQDnsAnswer::parse() -{ - // okay, do the work... - if ( (answer[2] & 0x78) != 0 ) { -#if defined(TQDNS_DEBUG) - qDebug( "DNS Manager: answer to wrong query type (%d)", answer[1] ); -#endif - ok = false; - return; - } - - // AA - bool aa = (answer[2] & 4) != 0; - - // TC - if ( (answer[2] & 2) != 0 ) { -#if defined(TQDNS_DEBUG) - qDebug( "DNS Manager: truncated answer; pressing on" ); -#endif - } - - // RD - bool rd = (answer[2] & 1) != 0; - - // we don't test RA - // we don't test the MBZ fields - - if ( (answer[3] & 0x0f) == 3 ) { -#if defined(TQDNS_DEBUG) - qDebug( "DNS Manager: saw NXDomain for %s", query->l.ascii() ); -#endif - // NXDomain. cache that for one minute. - rr = new TQDnsRR( query->l ); - rr->t = query->t; - rr->deleteTime = query->started + 60; - rr->expireTime = query->started + 60; - rr->nxdomain = true; - rr->current = true; - rrs->append( rr ); - return; - } - - if ( (answer[3] & 0x0f) != 0 ) { -#if defined(TQDNS_DEBUG) - qDebug( "DNS Manager: error code %d", answer[3] & 0x0f ); -#endif - ok = false; - return; - } - - int qdcount = ( answer[4] << 8 ) + answer[5]; - int ancount = ( answer[6] << 8 ) + answer[7]; - int nscount = ( answer[8] << 8 ) + answer[9]; - int adcount = (answer[10] << 8 ) +answer[11]; - - pp = 12; - - // read query - while( qdcount > 0 && pp < size ) { - // should I compare the string against query->l? - (void)readString(); - if ( !ok ) - return; - pp += 4; - qdcount--; - } - - // answers and stuff - int rrno = 0; - // if we parse the answer completely, but there are no answers, - // ignore the entire thing. - int answers = 0; - while( ( rrno < ancount || - ( ok && answers >0 && rrno < ancount + nscount + adcount ) ) && - pp < size ) { - label = readString().lower(); - if ( !ok ) - return; - int rdlength = 0; - if ( pp + 10 <= size ) - rdlength = ( answer[pp+8] << 8 ) + answer[pp+9]; - if ( pp + 10 + rdlength > size ) { -#if defined(TQDNS_DEBUG) - qDebug( "DNS Manager: ran out of stuff to parse (%d+%d>%d (%d)", - pp, rdlength, size, rrno < ancount ); -#endif - // if we're still in the AN section, we should go back and - // at least down the TTLs. probably best to invalidate - // the results. - // the rrs list is good for this - ok = ( rrno < ancount ); - return; - } - uint type, clas; - type = ( answer[pp+0] << 8 ) + answer[pp+1]; - clas = ( answer[pp+2] << 8 ) + answer[pp+3]; - ttl = ( answer[pp+4] << 24 ) + ( answer[pp+5] << 16 ) + - ( answer[pp+6] << 8 ) + answer[pp+7]; - pp = pp + 10; - if ( clas != 1 ) { -#if defined(TQDNS_DEBUG) - qDebug( "DNS Manager: class %d (not internet) for %s", - clas, label.isNull() ? "." : label.ascii() ); -#endif - } else { - next = pp + rdlength; - rr = 0; - switch( type ) { - case 1: - parseA(); - break; - case 28: - parseAaaa(); - break; - case 15: - parseMx(); - break; - case 33: - parseSrv(); - break; - case 5: - parseCname(); - break; - case 12: - parsePtr(); - break; - case 16: - parseTxt(); - break; - case 2: - parseNs(); - break; - default: - // something we don't know -#if defined(TQDNS_DEBUG) - qDebug( "DNS Manager: type %d for %s", type, - label.isNull() ? "." : label.ascii() ); -#endif - break; - } - if ( rr ) { - rr->deleteTime = 0; - if ( ttl > 0 ) - rr->expireTime = query->started + ttl; - else - rr->expireTime = query->started + 20; - if ( rrno < ancount ) { - answers++; - rr->deleteTime = rr->expireTime; - } - rr->current = true; - rrs->append( rr ); - } - } - if ( !ok ) - return; - pp = next; - next = size; - rrno++; - } - if ( answers == 0 ) { -#if defined(TQDNS_DEBUG) - qDebug( "DNS Manager: answer contained no answers" ); -#endif - ok = ( aa && rd ); - } - - // now go through the list and mark all the As that are referenced - // by something we care about. we want to cache such As. - rrs->first(); - TQDict used( 17 ); - used.setAutoDelete( false ); - while( (rr=rrs->current()) != 0 ) { - rrs->next(); - if ( rr->target.length() && rr->deleteTime > 0 && rr->current ) - used.insert( rr->target, (void*)42 ); - if ( ( rr->t == TQDns::A || rr->t == TQDns::Aaaa ) && - used.find( rr->domain->name() ) != 0 ) - rr->deleteTime = rr->expireTime; - } - - // next, for each RR, delete any older RRs that are equal to it - rrs->first(); - while( (rr=rrs->current()) != 0 ) { - rrs->next(); - if ( rr && rr->domain && rr->domain->rrs ) { - TQPtrList * drrs = rr->domain->rrs; - drrs->first(); - TQDnsRR * older; - while( (older=drrs->current()) != 0 ) { - if ( older != rr && - older->t == rr->t && - older->nxdomain == rr->nxdomain && - older->address == rr->address && - older->target == rr->target && - older->priority == rr->priority && - older->weight == rr->weight && - older->port == rr->port && - older->text == rr->text ) { - // well, it's equal, but it's not the same. so we kill it, - // but use its expiry time. -#if defined(TQDNS_DEBUG) - qDebug( "killing off old %d for %s, expire was %d", - older->t, older->domain->name().latin1(), - rr->expireTime ); -#endif - older->t = TQDns::None; - rr->expireTime = QMAX( older->expireTime, rr->expireTime ); - rr->deleteTime = QMAX( older->deleteTime, rr->deleteTime ); - older->deleteTime = 0; -#if defined(TQDNS_DEBUG) - qDebug( " adjusted expire is %d", rr->expireTime ); -#endif - } - drrs->next(); - } - } - } - -#if defined(TQDNS_DEBUG) - //qDebug( "DNS Manager: ()" ); -#endif -} - - -class TQDnsUgleHack: public TQDns { -public: - void ugle( bool emitAnyway=false ); -}; - - -void TQDnsAnswer::notify() -{ - if ( !rrs || !ok || !query || !query->dns ) - return; - - TQPtrDict notified; - notified.setAutoDelete( false ); - - TQPtrDictIterator it( *query->dns ); - TQDns * dns; - it.toFirst(); - while( (dns=(TQDns*)(it.current())) != 0 ) { - ++it; - if ( notified.find( (void*)dns ) == 0 ) { - notified.insert( (void*)dns, (void*)42 ); - if ( rrs->count() == 0 ) { -#if defined(TQDNS_DEBUG) - qDebug( "DNS Manager: found no answers!" ); -#endif - dns->d->noNames = true; - ((TQDnsUgleHack*)dns)->ugle( true ); - } else { - TQStringList n = dns->qualifiedNames(); - if ( query && n.contains(query->l) ) - ((TQDnsUgleHack*)dns)->ugle(); -#if defined(TQDNS_DEBUG) - else - qDebug( "DNS Manager: DNS thing %s not notified for %s", - dns->label().ascii(), query->l.ascii() ); -#endif - } - } - } -} - - -// -// -// TQDnsManager -// -// - - -class TQDnsManager: public TQDnsSocket { -private: -public: // just to silence the moronic g++. - TQDnsManager(); - ~TQDnsManager(); -public: - static TQDnsManager * manager(); - - TQDnsDomain * domain( const TQString & ); - - void transmitQuery( TQDnsQuery * ); - void transmitQuery( int ); - - // reimplementation of the slots - void cleanCache(); - void retransmit(); - void answer(); - -public: - TQPtrVector queries; - TQDict cache; - TQSocketDevice * ipv4Socket; -#if !defined (QT_NO_IPV6) - TQSocketDevice * ipv6Socket; -#endif -}; - - - -static TQDnsManager * globalManager = 0; - -static void cleanupDns() -{ - delete globalManager; - globalManager = 0; -} - -TQDnsManager * TQDnsManager::manager() -{ - if ( !globalManager ) { - qAddPostRoutine(cleanupDns); - new TQDnsManager(); - } - return globalManager; -} - - -void TQDnsUgleHack::ugle( bool emitAnyway) -{ - if ( emitAnyway || !isWorking() ) { -#if defined(TQDNS_DEBUG) - qDebug( "DNS Manager: status change for %s (type %d)", - label().ascii(), recordType() ); -#endif - emit resultsReady(); - } -} - - -TQDnsManager::TQDnsManager() - : TQDnsSocket( qApp, "Internal DNS manager" ), - queries( TQPtrVector( 0 ) ), - cache( TQDict( 83, false ) ), - ipv4Socket( new TQSocketDevice( TQSocketDevice::Datagram, TQSocketDevice::IPv4, 0 ) ) -#if !defined (QT_NO_IPV6) - , ipv6Socket( new TQSocketDevice( TQSocketDevice::Datagram, TQSocketDevice::IPv6, 0 ) ) -#endif -{ - cache.setAutoDelete( true ); - globalManager = this; - - TQTimer * sweepTimer = new TQTimer( this ); - sweepTimer->start( 1000 * 60 * 3 ); - connect( sweepTimer, TQT_SIGNAL(timeout()), - this, TQT_SLOT(cleanCache()) ); - - TQSocketNotifier * rn4 = new TQSocketNotifier( ipv4Socket->socket(), - TQSocketNotifier::Read, - TQT_TQOBJECT(this), "dns IPv4 socket watcher" ); - ipv4Socket->setAddressReusable( false ); - ipv4Socket->setBlocking( false ); - connect( rn4, TQT_SIGNAL(activated(int)), TQT_SLOT(answer()) ); - -#if !defined (QT_NO_IPV6) - // Don't connect the IPv6 socket notifier if the host does not - // support IPv6. - if ( ipv6Socket->socket() != -1 ) { - TQSocketNotifier * rn6 = new TQSocketNotifier( ipv6Socket->socket(), - TQSocketNotifier::Read, - TQT_TQOBJECT(this), "dns IPv6 socket watcher" ); - - ipv6support = true; - ipv6Socket->setAddressReusable( false ); - ipv6Socket->setBlocking( false ); - connect( rn6, TQT_SIGNAL(activated(int)), TQT_SLOT(answer()) ); - } -#endif - - if ( !theNs ) - TQDns::doResInit(); - - // O(n*n) stuff here. but for 3 and 6, O(n*n) with a low k should - // be perfect. the point is to eliminate any duplicates that - // might be hidden in the lists. - TQPtrList * ns = new TQPtrList; - - theNs->first(); - TQHostAddress * h; - while( (h=theNs->current()) != 0 ) { - ns->first(); - while( ns->current() != 0 && !(*ns->current() == *h) ) - ns->next(); - if ( !ns->current() ) { - ns->append( new TQHostAddress(*h) ); -#if defined(TQDNS_DEBUG) - qDebug( "using name server %s", h->toString().latin1() ); - } else { - qDebug( "skipping address %s", h->toString().latin1() ); -#endif - } - theNs->next(); - } - - delete theNs; - theNs = ns; - theNs->setAutoDelete( true ); - - TQStrList * domains = new TQStrList( true ); - - theDomains->first(); - const char * s; - while( (s=theDomains->current()) != 0 ) { - domains->first(); - while( domains->current() != 0 && qstrcmp( domains->current(), s ) ) - domains->next(); - if ( !domains->current() ) { - domains->append( s ); -#if defined(TQDNS_DEBUG) - qDebug( "searching domain %s", s ); - } else { - qDebug( "skipping domain %s", s ); -#endif - } - theDomains->next(); - } - - delete theDomains; - theDomains = domains; - theDomains->setAutoDelete( true ); -} - - -TQDnsManager::~TQDnsManager() -{ - if ( globalManager ) - globalManager = 0; - queries.setAutoDelete( true ); - cache.setAutoDelete( true ); - delete ipv4Socket; -#if !defined (QT_NO_IPV6) - delete ipv6Socket; -#endif -} - -static Q_UINT32 lastSweep = 0; - -void TQDnsManager::cleanCache() -{ - bool again = false; - TQDictIterator it( cache ); - TQDnsDomain * d; - Q_UINT32 thisSweep = now(); -#if defined(TQDNS_DEBUG) - qDebug( "TQDnsManager::cleanCache(: Called, time is %u, last was %u", - thisSweep, lastSweep ); -#endif - - while( (d=it.current()) != 0 ) { - ++it; - d->sweep( thisSweep ); // after this, d may be empty - if ( !again ) - again = !d->isEmpty(); - } - if ( !again ) - delete this; - lastSweep = thisSweep; -} - - -void TQDnsManager::retransmit() -{ - const TQT_BASE_OBJECT_NAME * o = sender(); - if ( o == 0 || globalManager == 0 || this != globalManager ) - return; - uint q = 0; - while( q < queries.size() && queries[q] != o ) - q++; - if ( q < queries.size() ) - transmitQuery( q ); -} - - -void TQDnsManager::answer() -{ - TQByteArray a( 16383 ); // large enough for anything, one suspects - - int r; -#if defined (QT_NO_IPV6) - r = ipv4Socket->readBlock(a.data(), a.size()); -#else - if (((TQSocketNotifier *)sender())->socket() == ipv4Socket->socket()) - r = ipv4Socket->readBlock(a.data(), a.size()); - else - r = ipv6Socket->readBlock(a.data(), a.size()); -#endif -#if defined(TQDNS_DEBUG) -#if !defined (QT_NO_IPV6) - qDebug("DNS Manager: answer arrived: %d bytes from %s:%d", r, - useIpv4Socket ? ipv4Socket->peerAddress().toString().ascii() - : ipv6Socket->peerAddress().toString().ascii(), - useIpv4Socket ? ipv4Socket->peerPort() : ipv6Socket->peerPort() ); -#else - qDebug("DNS Manager: answer arrived: %d bytes from %s:%d", r, - ipv4Socket->peerAddress().toString().ascii(), ipv4Socket->peerPort());; -#endif -#endif - if ( r < 12 ) - return; - // maybe we should check that the answer comes from port 53 on one - // of our name servers... - a.resize( r ); - - Q_UINT16 aid = (((Q_UINT8)a[0]) << 8) + ((Q_UINT8)a[1]); - uint i = 0; - while( i < queries.size() && - !( queries[i] && queries[i]->id == aid ) ) - i++; - if ( i == queries.size() ) { -#if defined(TQDNS_DEBUG) - qDebug( "DNS Manager: bad id (0x%04x) %d", aid, i ); -#endif - return; - } - - // at this point queries[i] is whatever we asked for. - - if ( ( (Q_UINT8)(a[2]) & 0x80 ) == 0 ) { -#if defined(TQDNS_DEBUG) - qDebug( "DNS Manager: received a query" ); -#endif - return; - } - - TQDnsQuery * q = queries[i]; - TQDnsAnswer answer( a, q ); - answer.parse(); - if ( answer.ok ) { - queries.take( i ); - answer.notify(); - delete q; - } -} - - -void TQDnsManager::transmitQuery( TQDnsQuery * query_ ) -{ - if ( !query_ ) - return; - - uint i = 0; - while( i < queries.size() && queries[i] != 0 ) - i++; - if ( i == queries.size() ) - queries.resize( i+1 ); - queries.insert( i, query_ ); - transmitQuery( i ); -} - - -void TQDnsManager::transmitQuery( int i ) -{ - if ( i < 0 || i >= (int)queries.size() ) - return; - TQDnsQuery * q = queries[i]; - - if ( q && q->step > 8 ) { - // okay, we've run out of retransmissions. we fake an NXDomain - // with a very short life time... - TQDnsAnswer answer( q ); - answer.notify(); - // and then get rid of the query - queries.take( i ); -#if defined(TQDNS_DEBUG) - qDebug( "DNS Manager: giving up on query 0x%04x", q->id ); -#endif - delete q; - TQTimer::singleShot( 0, TQDnsManager::manager(), TQT_SLOT(cleanCache()) ); - // and don't process anything more - return; - } - - if ((q && !q->dns) || q->dns->isEmpty()) - // no one currently wants the answer, so there's no point in - // retransmitting the query. we keep it, though. an answer may - // arrive for an earlier query transmission, and if it does we - // may benefit from caching the result. - return; - - TQByteArray p( 12 + q->l.length() + 2 + 4 ); - if ( p.size() > 500 ) - return; // way over the limit, so don't even try - - // header - // id - p[0] = (q->id & 0xff00) >> 8; - p[1] = q->id & 0x00ff; - p[2] = 1; // recursion desired, rest is 0 - p[3] = 0; // all is 0 - // one query - p[4] = 0; - p[5] = 1; - // no answers, name servers or additional data - p[6] = p[7] = p[8] = p[9] = p[10] = p[11] = 0; - - // the name is composed of several components. each needs to be - // written by itself... so we write... - // oh, and we assume that there's no funky characters in there. - int pp = 12; - uint lp = 0; - while( lp < (uint) q->l.length() ) { - int le = q->l.find( QLatin1Char('.'), lp ); - if ( le < 0 ) - le = q->l.length(); - TQString component = q->l.mid( lp, le-lp ); - p[pp++] = component.length(); - int cp; - for( cp=0; cp < (int)component.length(); cp++ ) - p[pp++] = component[cp].latin1(); - lp = le + 1; - } - // final null - p[pp++] = 0; - // query type - p[pp++] = 0; - switch( q->t ) { - case TQDns::A: - p[pp++] = 1; - break; - case TQDns::Aaaa: - p[pp++] = 28; - break; - case TQDns::Mx: - p[pp++] = 15; - break; - case TQDns::Srv: - p[pp++] = 33; - break; - case TQDns::Cname: - p[pp++] = 5; - break; - case TQDns::Ptr: - p[pp++] = 12; - break; - case TQDns::Txt: - p[pp++] = 16; - break; - default: - p[pp++] = (char)255; // any - break; - } - // query class (always internet) - p[pp++] = 0; - p[pp++] = 1; - - // if we have no name servers, we should regenerate ns in case - // name servers have recently been defined (like on windows, - // plugging/unplugging the network cable will change the name - // server entries) - if ( !theNs || theNs->isEmpty() ) - TQDns::doResInit(); - - if ( !theNs || theNs->isEmpty() ) { - // we don't find any name servers. We fake an NXDomain - // with a very short life time... - TQDnsAnswer answer( q ); - answer.notify(); - // and then get rid of the query - queries.take( i ); -#if defined(TQDNS_DEBUG) - qDebug( "DNS Manager: no DNS server found on query 0x%04x", q->id ); -#endif - delete q; - TQTimer::singleShot( 1000*10, TQDnsManager::manager(), TQT_SLOT(cleanCache()) ); - // and don't process anything more - return; - } - - TQHostAddress receiver = *theNs->at( q->step % theNs->count() ); - if (receiver.isIPv4Address()) - ipv4Socket->writeBlock( p.data(), pp, receiver, 53 ); -#if !defined (QT_NO_IPV6) - else - ipv6Socket->writeBlock( p.data(), pp, receiver, 53 ); -#endif -#if defined(TQDNS_DEBUG) - qDebug( "issuing query 0x%04x (%d) about %s type %d to %s", - q->id, q->step, q->l.ascii(), q->t, - ns->at( q->step % ns->count() )->toString().ascii() ); -#endif - if ( theNs->count() > 1 && q->step == 0 && queries.count() == 1 ) { - // if it's the first time, and we don't have any other - // outstanding queries, send nonrecursive queries to the other - // name servers too. - p[2] = 0; - TQHostAddress * server; - while( (server=theNs->next()) != 0 ) { - if (server->isIPv4Address()) - ipv4Socket->writeBlock( p.data(), pp, *server, 53 ); -#if !defined (QT_NO_IPV6) - else - ipv6Socket->writeBlock( p.data(), pp, *server, 53 ); -#endif -#if defined(TQDNS_DEBUG) - qDebug( "copying query to %s", server->toString().ascii() ); -#endif - } - } - q->step++; - // some testing indicates that normal dns queries take up to 0.6 - // seconds. the graph becomes steep around that point, and the - // number of errors rises... so it seems good to retry at that - // point. - q->start( q->step < theNs->count() ? 800 : 1500, true ); -} - - -TQDnsDomain * TQDnsManager::domain( const TQString & label ) -{ - TQDnsDomain * d = cache.find( label ); - if ( !d ) { - d = new TQDnsDomain( label ); - cache.insert( label, d ); - } - return d; -} - - -// -// -// the TQDnsDomain class looks after and coordinates queries for TQDnsRRs for -// each domain, and the cached TQDnsRRs. (A domain, in DNS terminology, is -// a node in the DNS. "no", "trolltech.com" and "lupinella.troll.no" are -// all domains.) -// -// - - -TQDnsDomain::TQDnsDomain( const TQString & label ) -{ - l = label; - rrs = 0; -} - - -TQDnsDomain::~TQDnsDomain() -{ - delete rrs; - rrs = 0; -} - - -void TQDnsDomain::add( const TQString & label, TQDnsRR * rr ) -{ - TQDnsDomain * d = TQDnsManager::manager()->domain( label ); - if ( !d->rrs ) { - d->rrs = new TQPtrList; - d->rrs->setAutoDelete( true ); - } - d->rrs->append( rr ); - rr->domain = d; -} - - -TQPtrList * TQDnsDomain::cached( const TQDns * r ) -{ - TQPtrList * l = new TQPtrList; - - // test at first if you have to start a query at all - if ( r->recordType() == TQDns::A ) { - if ( r->label().lower() == TQLatin1String("localhost") ) { - // undocumented hack. ipv4-specific. also, may be a memory - // leak? not sure. would be better to do this in doResInit(), - // anyway. - TQDnsRR *rrTmp = new TQDnsRR( r->label() ); - rrTmp->t = TQDns::A; - rrTmp->address = TQHostAddress( 0x7f000001 ); - rrTmp->current = true; - l->append( rrTmp ); - return l; - } - TQHostAddress tmp; - if ( tmp.setAddress( r->label() ) ) { - TQDnsRR *rrTmp = new TQDnsRR( r->label() ); - if ( tmp.isIPv4Address() ) { - rrTmp->t = TQDns::A; - rrTmp->address = tmp; - rrTmp->current = true; - l->append( rrTmp ); - } else { - rrTmp->nxdomain = true; - } - return l; - } - } - if ( r->recordType() == TQDns::Aaaa ) { - TQHostAddress tmp; - if ( tmp.setAddress(r->label()) ) { - TQDnsRR *rrTmp = new TQDnsRR( r->label() ); - if ( tmp.isIPv6Address() ) { - rrTmp->t = TQDns::Aaaa; - rrTmp->address = tmp; - rrTmp->current = true; - l->append( rrTmp ); - } else { - rrTmp->nxdomain = true; - } - return l; - } - } - - // if you reach this point, you have to do the query - TQDnsManager * m = TQDnsManager::manager(); - TQStringList n = r->qualifiedNames(); - bool nxdomain; - int cnamecount = 0; - int it = 0; - while( it < n.count() ) { - TQString s = *(n.at(it++)); - nxdomain = false; -#if defined(TQDNS_DEBUG) - qDebug( "looking at cache for %s (%s %d)", - s.ascii(), r->label().ascii(), r->recordType() ); -#endif - TQDnsDomain * d = m->domain( s ); -#if defined(TQDNS_DEBUG) - qDebug( " - found %d RRs", d && d->rrs ? d->rrs->count() : 0 ); -#endif - if ( d->rrs ) - d->rrs->first(); - TQDnsRR * rr; - bool answer = false; - while( d->rrs && (rr=d->rrs->current()) != 0 ) { - if ( rr->t == TQDns::Cname && r->recordType() != TQDns::Cname && - !rr->nxdomain && cnamecount < 16 ) { - // cname. if the code is ugly, that may just - // possibly be because the concept is. -#if defined(TQDNS_DEBUG) - qDebug( "found cname from %s to %s", - r->label().ascii(), rr->target.ascii() ); -#endif - s = rr->target; - d = m->domain( s ); - if ( d->rrs ) - d->rrs->first(); - it = n.count(); - // we've elegantly moved over to whatever the cname - // pointed to. well, not elegantly. let's remember - // that we've done something, anyway, so we can't be - // fooled into an infinte loop as well. - cnamecount++; - } else { - if ( rr->t == r->recordType() ) { - if ( rr->nxdomain ) - nxdomain = true; - else - answer = true; - l->append( rr ); - if ( rr->deleteTime <= lastSweep ) { - // we're returning something that'll be - // deleted soon. we assume that if the client - // wanted it twice, it'll want it again, so we - // ask the name server again right now. - TQDnsQuery * query = new TQDnsQuery; - query->started = now(); - query->id = ++theId; - query->t = rr->t; - query->l = rr->domain->name(); - // note that here, we don't bother about - // notification. but we do bother about - // timeouts: we make sure to use high timeouts - // and few tramsissions. - query->step = theNs->count(); - TQT_BASE_OBJECT_NAME::connect( query, TQT_SIGNAL(timeout()), - TQDnsManager::manager(), - TQT_SLOT(retransmit()) ); - TQDnsManager::manager()->transmitQuery( query ); - } - } - d->rrs->next(); - } - } - // if we found a positive result, return quickly - if ( answer && l->count() ) { -#if defined(TQDNS_DEBUG) - qDebug( "found %d records for %s", - l->count(), r->label().ascii() ); - l->first(); - while( l->current() ) { - qDebug( " type %d target %s address %s", - l->current()->t, - l->current()->target.latin1(), - l->current()->address.toString().latin1() ); - l->next(); - } -#endif - l->first(); - return l; - } - -#if defined(TQDNS_DEBUG) - if ( nxdomain ) - qDebug( "found NXDomain %s", s.ascii() ); -#endif - - if ( !nxdomain ) { - // if we didn't, and not a negative result either, perhaps - // we need to transmit a query. - uint q = 0; - while ( q < m->queries.size() && - ( m->queries[q] == 0 || - m->queries[q]->t != r->recordType() || - m->queries[q]->l != s ) ) - q++; - // we haven't done it before, so maybe we should. but - // wait - if it's an unqualified name, only ask when all - // the other alternatives are exhausted. - if ( q == m->queries.size() && ( s.find( QLatin1Char('.') ) >= 0 || - int(l->count()) >= n.count()-1 ) ) { - TQDnsQuery * query = new TQDnsQuery; - query->started = now(); - query->id = ++theId; - query->t = r->recordType(); - query->l = s; - query->dns->replace( (void*)r, (void*)r ); - TQT_BASE_OBJECT_NAME::connect( query, TQT_SIGNAL(timeout()), - TQDnsManager::manager(), TQT_SLOT(retransmit()) ); - TQDnsManager::manager()->transmitQuery( query ); - } else if ( q < m->queries.size() ) { - // if we've found an earlier query for the same - // domain/type, subscribe to its answer - m->queries[q]->dns->replace( (void*)r, (void*)r ); - } - } - } - l->first(); - return l; -} - - -void TQDnsDomain::sweep( Q_UINT32 thisSweep ) -{ - if ( !rrs ) - return; - - TQDnsRR * rr; - rrs->first(); - while( (rr=rrs->current()) != 0 ) { - if ( !rr->deleteTime ) - rr->deleteTime = thisSweep; // will hit next time around - -#if defined(TQDNS_DEBUG) - qDebug( "TQDns::sweep: %s type %d expires %u %u - %s / %s", - rr->domain->name().latin1(), rr->t, - rr->expireTime, rr->deleteTime, - rr->target.latin1(), rr->address.toString().latin1()); -#endif - if ( rr->current == false || - rr->t == TQDns::None || - rr->deleteTime <= thisSweep || - rr->expireTime <= thisSweep ) - rrs->remove(); - else - rrs->next(); - } - - if ( rrs->isEmpty() ) { - delete rrs; - rrs = 0; - } -} - - - - -// the itsy-bitsy little socket class I don't really need except for -// so I can subclass and reimplement the slots. - - -TQDnsSocket::TQDnsSocket( TQT_BASE_OBJECT_NAME * parent, const char * name ) - : TQObject( parent, name ) -{ - // nothing -} - - -TQDnsSocket::~TQDnsSocket() -{ - // nothing -} - - -void TQDnsSocket::cleanCache() -{ - // nothing -} - - -void TQDnsSocket::retransmit() -{ - // nothing -} - - -void TQDnsSocket::answer() -{ - // nothing -} - - -/*! - \class TQDns - \brief The TQDns class provides asynchronous DNS lookups. - - \compat - - Both Windows and Unix provide synchronous DNS lookups; Windows - provides some asynchronous support too. At the time of writing - neither operating system provides asynchronous support for - anything other than hostname-to-address mapping. - - TQDns rectifies this shortcoming, by providing asynchronous caching - lookups for the record types that we expect modern GUI - applications to need in the near future. - - The class is \e not straightforward to use (although it is much - simpler than the native APIs); TQSocket provides much easier to use - TCP connection facilities. The aim of TQDns is to provide a correct - and small API to the DNS and nothing more. (We use "correctness" - to mean that the DNS information is correctly cached, and - correctly timed out.) - - The API comprises a constructor, functions to set the DNS node - (the domain in DNS terminology) and record type (setLabel() and - setRecordType()), the corresponding get functions, an isWorking() - function to determine whether TQDns is working or reading, a - resultsReady() signal and query functions for the result. - - There is one query function for each RecordType, namely - addresses(), mailServers(), servers(), hostNames() and texts(). - There are also two generic query functions: canonicalName() - returns the name you'll presumably end up using (the exact meaning - of this depends on the record type) and qualifiedNames() returns a - list of the fully qualified names label() maps to. - - \sa TQSocket -*/ - -/*! - Constructs a DNS query object with invalid settings for both the - label and the search type. -*/ - -TQDns::TQDns() -{ - d = new TQDnsPrivate; - t = None; -} - - - - -/*! - Constructs a DNS query object that will return record type \a rr - information about \a label. - - The DNS lookup is started the next time the application enters the - event loop. When the result is found the signal resultsReady() is - emitted. - - \a rr defaults to \c A, IPv4 addresses. -*/ - -TQDns::TQDns( const TQString & label, RecordType rr ) -{ - d = new TQDnsPrivate; - t = rr; - setLabel( label ); - setStartQueryTimer(); // start query the next time we enter event loop -} - - - -/*! - Constructs a DNS query object that will return record type \a rr - information about host address \a address. The label is set to the - IN-ADDR.ARPA domain name. This is useful in combination with the - \c Ptr record type (e.g. if you want to look up a hostname for a - given address). - - The DNS lookup is started the next time the application enters the - event loop. When the result is found the signal resultsReady() is - emitted. - - \a rr defaults to \c Ptr, that maps addresses to hostnames. -*/ - -TQDns::TQDns( const TQHostAddress & address, RecordType rr ) -{ - d = new TQDnsPrivate; - t = rr; - setLabel( address ); - setStartQueryTimer(); // start query the next time we enter event loop -} - - - - -/*! - Destroys the DNS query object and frees its allocated resources. -*/ - -TQDns::~TQDns() -{ - if ( globalManager ) { - uint q = 0; - TQDnsManager * m = globalManager; - while( q < m->queries.size() ) { - TQDnsQuery * query=m->queries[q]; - if ( query && query->dns ) - (void)query->dns->take( (void*) this ); - q++; - } - - } - - delete d; - d = 0; -} - - - - -/*! - Sets this DNS query object to query for information about \a - label. - - This does not change the recordType(), but its isWorking() status - will probably change as a result. - - The DNS lookup is started the next time the application enters the - event loop. When the result is found the signal resultsReady() is - emitted. -*/ - -void TQDns::setLabel( const TQString & label ) -{ - l = label; - d->noNames = false; - - // construct a list of qualified names - n.clear(); - if ( l.length() > 1 && l[(int)l.length()-1] == QLatin1Char('.') ) { - n.append( TQT_TQSTRING(l.left( l.length()-1 )).lower() ); - } else { - int i = l.length(); - int dots = 0; - const int maxDots = 2; - while( i && dots < maxDots ) { - if ( l[--i] == QLatin1Char('.') ) - dots++; - } - if ( dots < maxDots ) { - (void)TQDnsManager::manager(); // create a TQDnsManager, if it is not already there - TQStrListIterator it( *theDomains ); - const char * dom; - while( (dom=it.current()) != 0 ) { - ++it; - n.append( l.lower() + QLatin1Char('.') + TQLatin1String(dom) ); - } - } - n.append( l.lower() ); - } - -#if defined(Q_DNS_SYNCHRONOUS) - if ( d->noEventLoop ) { - doSynchronousLookup(); - } else { - setStartQueryTimer(); // start query the next time we enter event loop - } -#else - setStartQueryTimer(); // start query the next time we enter event loop -#endif -#if defined(TQDNS_DEBUG) - qDebug( "TQDns::setLabel: %d address(es) for %s", n.count(), l.ascii() ); - int i = 0; - for( i = 0; i < (int)n.count(); i++ ) - qDebug( "TQDns::setLabel: %d: %s", i, n[i].ascii() ); -#endif -} - - -/*! - \overload - - Sets this DNS query object to query for information about the host - address \a address. The label is set to the IN-ADDR.ARPA domain - name. This is useful in combination with the \c Ptr record type - (e.g. if you want to look up a hostname for a given address). -*/ - -void TQDns::setLabel( const TQHostAddress & address ) -{ - setLabel( toInAddrArpaDomain( address ) ); -} - - -/*! - \fn TQStringList TQDns::qualifiedNames() const - - Returns a list of the fully qualified names label() maps to. - - Note that if you want to iterate over the list, you should iterate - over a copy, e.g. - \snippet doc/src/snippets/code/src_qt3support_network_q3dns.cpp 0 - -*/ - - -/*! - \fn TQString TQDns::label() const - - Returns the domain name for which this object returns information. - - \sa setLabel() -*/ - -/*! - \enum TQDns::RecordType - - This enum type defines the record types TQDns can handle. The DNS - provides many more; these are the ones we've judged to be in - current use, useful for GUI programs and important enough to - support right away: - - \value None No information. This exists only so that TQDns can - have a default. - - \value A IPv4 addresses. By far the most common type. - - \value Aaaa IPv6 addresses. So far mostly unused. - - \value Mx Mail eXchanger names. Used for mail delivery. - - \value Srv SeRVer names. Generic record type for finding - servers. So far mostly unused. - - \value Cname Canonical names. Maps from nicknames to the true - name (the canonical name) for a host. - - \value Ptr name PoinTeRs. Maps from IPv4 or IPv6 addresses to hostnames. - - \value Txt arbitrary TeXT for domains. - - We expect that some support for the - \l{http://www.rfc-editor.org/rfc/rfc2535.txt}{RFC 2535} - extensions will be added in future versions. -*/ - -/*! - Sets this object to query for record type \a rr records. - - The DNS lookup is started the next time the application enters the - event loop. When the result is found the signal resultsReady() is - emitted. - - \sa RecordType -*/ - -void TQDns::setRecordType( RecordType rr ) -{ - t = rr; - d->noNames = false; - setStartQueryTimer(); // start query the next time we enter event loop -} - -/*! - \internal - - Private slot for starting the query. -*/ -void TQDns::startQuery() -{ - // isWorking() starts the query (if necessary) - if ( !isWorking() ) - emit resultsReady(); -} - -/*! - The three functions TQDns::TQDns(TQString, RecordType), - TQDns::setLabel() and TQDns::setRecordType() may start a DNS lookup. - This function handles setting up the single shot timer. -*/ -void TQDns::setStartQueryTimer() -{ -#if defined(Q_DNS_SYNCHRONOUS) - if ( !d->queryTimer && !d->noEventLoop ) -#else - if ( !d->queryTimer ) -#endif - { - // start the query the next time we enter event loop - d->queryTimer = new TQTimer( this ); - connect( d->queryTimer, TQT_SIGNAL(timeout()), - this, TQT_SLOT(startQuery()) ); - d->queryTimer->start( 0, true ); - } -} - -/* - Transforms the host address \a address to the IN-ADDR.ARPA domain - name. Returns something indeterminate if you're sloppy or - naughty. This function has an IPv4-specific name, but works for - IPv6 too. -*/ -TQString TQDns::toInAddrArpaDomain( const TQHostAddress &address ) -{ - TQString s; - if ( address.isNull() ) { - // if the address isn't valid, neither of the other two make - // cases make sense. better to just return. - } else if ( address.isIp4Addr() ) { - Q_UINT32 i = address.ip4Addr(); - s.sprintf( "%d.%d.%d.%d.IN-ADDR.ARPA", - i & 0xff, (i >> 8) & 0xff, (i>>16) & 0xff, (i>>24) & 0xff ); - } else { - // RFC 3152. (1886 is deprecated, and clients no longer need to - // support it, in practice). - Q_IPV6ADDR i = address.toIPv6Address(); - s = TQLatin1String("ip6.arpa"); - uint b = 0; - while( b < 16 ) { - s = TQString::number( i.c[b]%16, 16 ) + QLatin1Char('.') + - TQString::number( i.c[b]/16, 16 ) + QLatin1Char('.') + s; - b++; - } - } - return s; -} - - -/*! - \fn TQDns::RecordType TQDns::recordType() const - - Returns the record type of this DNS query object. - - \sa setRecordType() RecordType -*/ - -/*! - \fn void TQDns::resultsReady() - - This signal is emitted when results are available for one of the - qualifiedNames(). -*/ - -/*! - Returns true if TQDns is doing a lookup for this object (i.e. if it - does not already have the necessary information); otherwise - returns false. - - TQDns emits the resultsReady() signal when the status changes to false. -*/ - -bool TQDns::isWorking() const -{ -#if defined(TQDNS_DEBUG) - qDebug( "TQDns::isWorking (%s, %d)", l.ascii(), t ); -#endif - if ( t == None ) - return false; - -#if defined(Q_DNS_SYNCHRONOUS) - if ( d->noEventLoop ) - return true; -#endif - - TQPtrList * ll = TQDnsDomain::cached( this ); - Q_LONG queries = n.count(); - while( ll->current() != 0 ) { - if ( ll->current()->nxdomain ) { - queries--; - } else { - delete ll; - return false; - } - ll->next(); - } - delete ll; - - if ( queries <= 0 ) - return false; - if ( d->noNames ) - return false; - return true; -} - - -/*! - Returns a list of the addresses for this name if this TQDns object - has a recordType() of TQDns::A or TQDns::Aaaa and the answer - is available; otherwise returns an empty list. - - As a special case, if label() is a valid numeric IP address, this - function returns that address. - - Note that if you want to iterate over the list, you should iterate - over a copy, e.g. - \snippet doc/src/snippets/code/src_qt3support_network_q3dns.cpp 1 - -*/ - -TQValueList TQDns::addresses() const -{ -#if defined(TQDNS_DEBUG) - qDebug( "TQDns::addresses (%s)", l.ascii() ); -#endif - TQValueList result; - if ( t != A && t != Aaaa ) - return result; - - TQPtrList * cached = TQDnsDomain::cached( this ); - - TQDnsRR * rr; - while( (rr=cached->current()) != 0 ) { - if ( rr->current && !rr->nxdomain ) - result.append( rr->address ); - cached->next(); - } - delete cached; - return result; -} - - -/*! - \class TQDns::MailServer - \brief The TQDns::MailServer class is described in TQDns::mailServers(). - - \internal -*/ - -/*! - Returns a list of mail servers if the record type is \c Mx. The - class TQDns::MailServer contains the following public variables: - \list - \i TQString TQDns::MailServer::name - \i Q_UINT16 TQDns::MailServer::priority - \endlist - - Note that if you want to iterate over the list, you should iterate - over a copy, e.g. - \snippet doc/src/snippets/code/src_qt3support_network_q3dns.cpp 2 - -*/ -TQValueList TQDns::mailServers() const -{ -#if defined(TQDNS_DEBUG) - qDebug( "TQDns::mailServers (%s)", l.ascii() ); -#endif - TQValueList result; - if ( t != Mx ) - return result; - - TQPtrList * cached = TQDnsDomain::cached( this ); - - TQDnsRR * rr; - while( (rr=cached->current()) != 0 ) { - if ( rr->current && !rr->nxdomain ) { - MailServer ms( rr->target, rr->priority ); - result.append( ms ); - } - cached->next(); - } - delete cached; - return result; -} - - -/*! - \class TQDns::Server - \brief The TQDns::Server class is described in TQDns::servers(). - - \internal -*/ - -/*! - Returns a list of servers if the record type is \c Srv. The class - TQDns::Server contains the following public variables: - \list - \i TQString TQDns::Server::name - \i Q_UINT16 TQDns::Server::priority - \i Q_UINT16 TQDns::Server::weight - \i Q_UINT16 TQDns::Server::port - \endlist - - Note that if you want to iterate over the list, you should iterate - over a copy, e.g. - \snippet doc/src/snippets/code/src_qt3support_network_q3dns.cpp 3 -*/ -TQValueList TQDns::servers() const -{ -#if defined(TQDNS_DEBUG) - qDebug( "TQDns::servers (%s)", l.ascii() ); -#endif - TQValueList result; - if ( t != Srv ) - return result; - - TQPtrList * cached = TQDnsDomain::cached( this ); - - TQDnsRR * rr; - while( (rr=cached->current()) != 0 ) { - if ( rr->current && !rr->nxdomain ) { - Server s( rr->target, rr->priority, rr->weight, rr->port ); - result.append( s ); - } - cached->next(); - } - delete cached; - return result; -} - - -/*! - Returns a list of host names if the record type is \c Ptr. - - Note that if you want to iterate over the list, you should iterate - over a copy, e.g. - \snippet doc/src/snippets/code/src_qt3support_network_q3dns.cpp 4 - -*/ -TQStringList TQDns::hostNames() const -{ -#if defined(TQDNS_DEBUG) - qDebug( "TQDns::hostNames (%s)", l.ascii() ); -#endif - TQStringList result; - if ( t != Ptr ) - return result; - - TQPtrList * cached = TQDnsDomain::cached( this ); - - TQDnsRR * rr; - while( (rr=cached->current()) != 0 ) { - if ( rr->current && !rr->nxdomain ) { - TQString str( rr->target ); - result.append( str ); - } - cached->next(); - } - delete cached; - return result; -} - - -/*! - Returns a list of texts if the record type is \c Txt. - - Note that if you want to iterate over the list, you should iterate - over a copy, e.g. - \snippet doc/src/snippets/code/src_qt3support_network_q3dns.cpp 5 -*/ -TQStringList TQDns::texts() const -{ -#if defined(TQDNS_DEBUG) - qDebug( "TQDns::texts (%s)", l.ascii() ); -#endif - TQStringList result; - if ( t != Txt ) - return result; - - TQPtrList * cached = TQDnsDomain::cached( this ); - - TQDnsRR * rr; - while( (rr=cached->current()) != 0 ) { - if ( rr->current && !rr->nxdomain ) { - TQString str( rr->text ); - result.append( str ); - } - cached->next(); - } - delete cached; - return result; -} - - -/*! - Returns the canonical name for this DNS node. (This works - regardless of what recordType() is set to.) - - If the canonical name isn't known, this function returns a null - string. - - The canonical name of a DNS node is its full name, or the full - name of the target of its CNAME. For example, if l.trolltech.com - is a CNAME to lillian.troll.no, and the search path for TQDns is - "trolltech.com", then the canonical name for all of "lillian", - "l", "lillian.troll.no." and "l.trolltech.com" is - "lillian.troll.no.". -*/ - -TQString TQDns::canonicalName() const -{ - // the cname should work regardless of the recordType(), so set the record - // type temporarily to cname when you look at the cache - TQDns *that = (TQDns*) this; // mutable function - RecordType oldType = t; - that->t = Cname; - TQPtrList * cached = TQDnsDomain::cached( that ); - that->t = oldType; - - TQDnsRR * rr; - while( (rr=cached->current()) != 0 ) { - if ( rr->current && !rr->nxdomain && rr->domain ) { - delete cached; - return rr->target; - } - cached->next(); - } - delete cached; - return TQString(); -} - -#if defined(Q_DNS_SYNCHRONOUS) -/*! \reimp -*/ -void TQDns::connectNotify( const char *signal ) -{ - if ( d->noEventLoop && qstrcmp(signal,TQT_SIGNAL(resultsReady()) )==0 ) { - doSynchronousLookup(); - } -} -#endif - -#if defined(Q_OS_WIN32) || defined(Q_OS_CYGWIN) - -#if defined(Q_DNS_SYNCHRONOUS) -void TQDns::doSynchronousLookup() -{ - // ### not implemented yet -} -#endif - -// the following typedefs are needed for GetNetworkParams() API call -#ifndef IP_TYPES_INCLUDED -#define MAX_HOSTNAME_LEN 128 -#define MAX_DOMAIN_NAME_LEN 128 -#define MAX_SCOPE_ID_LEN 256 -typedef struct { - char String[4 * 4]; -} IP_ADDRESS_STRING, *PIP_ADDRESS_STRING, IP_MASK_STRING, *PIP_MASK_STRING; -typedef struct _IP_ADDR_STRING { - struct _IP_ADDR_STRING* Next; - IP_ADDRESS_STRING IpAddress; - IP_MASK_STRING IpMask; - DWORD Context; -} IP_ADDR_STRING, *PIP_ADDR_STRING; -typedef struct { - char HostName[MAX_HOSTNAME_LEN + 4] ; - char DomainName[MAX_DOMAIN_NAME_LEN + 4]; - PIP_ADDR_STRING CurrentDnsServer; - IP_ADDR_STRING DnsServerList; - UINT NodeType; - char ScopeId[MAX_SCOPE_ID_LEN + 4]; - UINT EnableRouting; - UINT EnableProxy; - UINT EnableDns; -} FIXED_INFO, *PFIXED_INFO; -#endif -typedef DWORD (WINAPI *GNP)( PFIXED_INFO, PULONG ); - -// ### FIXME: this code is duplicated in qfiledialog.cpp -static TQString getWindowsRegString(HKEY key, const TQString &subKey) -{ - TQString s; - - wchar_t buf[1024]; - DWORD bsz = sizeof(buf) / sizeof(wchar_t); - int r = RegQueryValueEx(key, (wchar_t*)subKey.utf16(), 0, 0, (LPBYTE)buf, &bsz); - if (r == ERROR_SUCCESS) { - s = TQString::fromWCharArray(buf); - } else if (r == ERROR_MORE_DATA) { - char *ptr = new char[bsz+1]; - r = RegQueryValueEx(key, (wchar_t*)subKey.utf16(), 0, 0, (LPBYTE)ptr, &bsz); - if (r == ERROR_SUCCESS) - s = TQLatin1String(ptr); - delete [] ptr; - } - - return s; -} - -static bool getDnsParamsFromRegistry( const TQString &path, - TQString *domainName, TQString *nameServer, TQString *searchList ) -{ - HKEY k; - int r = RegOpenKeyEx( HKEY_LOCAL_MACHINE, (wchar_t*)path.utf16(), 0, KEY_READ, &k ); - - if ( r == ERROR_SUCCESS ) { - *domainName = getWindowsRegString( k, TQLatin1String("DhcpDomain") ); - if ( domainName->isEmpty() ) - *domainName = getWindowsRegString( k, TQLatin1String("Domain") ); - - *nameServer = getWindowsRegString( k, TQLatin1String("DhcpNameServer") ); - if ( nameServer->isEmpty() ) - *nameServer = getWindowsRegString( k, TQLatin1String("NameServer") ); - - *searchList = getWindowsRegString( k, TQLatin1String("SearchList") ); - } - RegCloseKey( k ); - return r == ERROR_SUCCESS; -} - -void TQDns::doResInit() -{ - char separator = 0; - - if ( theNs ) - delete theNs; - theNs = new TQPtrList; - theNs->setAutoDelete( true ); - theDomains = new TQStrList( true ); - theDomains->setAutoDelete( true ); - - TQString domainName, nameServer, searchList; - - bool gotNetworkParams = false; - // try the API call GetNetworkParams() first and use registry lookup only - // as a fallback - HINSTANCE hinstLib = LoadLibrary( L"iphlpapi" ); - if ( hinstLib != 0 ) { -#ifdef Q_OS_WINCE - GNP getNetworkParams = (GNP) GetProcAddress( hinstLib, L"GetNetworkParams" ); -#else - GNP getNetworkParams = (GNP) GetProcAddress( hinstLib, "GetNetworkParams" ); -#endif - if ( getNetworkParams != 0 ) { - ULONG l = 0; - DWORD res; - res = getNetworkParams( 0, &l ); - if ( res == ERROR_BUFFER_OVERFLOW ) { - FIXED_INFO *finfo = (FIXED_INFO*)new char[l]; - res = getNetworkParams( finfo, &l ); - if ( res == ERROR_SUCCESS ) { - domainName = TQLatin1String(finfo->DomainName); - nameServer = TQLatin1String(""); - IP_ADDR_STRING *dnsServer = &finfo->DnsServerList; - while ( dnsServer != 0 ) { - nameServer += TQLatin1String(dnsServer->IpAddress.String); - dnsServer = dnsServer->Next; - if ( dnsServer != 0 ) - nameServer += QLatin1Char(' '); - } - searchList = TQLatin1String(""); - separator = ' '; - gotNetworkParams = true; - } - delete[] finfo; - } - } - FreeLibrary( hinstLib ); - } - if ( !gotNetworkParams ) { - if ( getDnsParamsFromRegistry( - TQLatin1String("System\\CurrentControlSet\\Services\\Tcpip\\Parameters"), - &domainName, &nameServer, &searchList )) { - separator = ' '; - } else { - // Could not access the TCP/IP parameters - domainName = TQLatin1String(""); - nameServer = TQLatin1String("127.0.0.1"); - searchList = TQLatin1String(""); - separator = ' '; - } - } - - nameServer = nameServer.simplifyWhiteSpace(); - int first, last; - if ( !nameServer.isEmpty() ) { - first = 0; - do { - last = nameServer.find( QLatin1Char(separator), first ); - if ( last < 0 ) - last = nameServer.length(); - TQDns tmp( nameServer.mid( first, last-first ), TQDns::A ); - TQValueList address = tmp.addresses(); - Q_LONG i = address.count(); - while( i ) - theNs->append( new TQHostAddress(address[--i]) ); - first = last+1; - } while( first < (int)nameServer.length() ); - } - - searchList += QLatin1Char(' ') + domainName; - searchList = searchList.simplifyWhiteSpace().lower(); - first = 0; - do { - last = searchList.find( QLatin1Char(separator), first ); - if ( last < 0 ) - last = searchList.length(); - theDomains->append( qstrdup( searchList.mid( first, last-first ).latin1() ) ); - first = last+1; - } while( first < (int)searchList.length() ); -} - -#elif defined(Q_OS_UNIX) - -#if defined(Q_DNS_SYNCHRONOUS) -void TQDns::doSynchronousLookup() -{ - if ( t!=None && !l.isEmpty() ) { - TQValueListIterator it = n.begin(); - TQValueListIterator end = n.end(); - int type; - switch( t ) { - case TQDns::A: - type = 1; - break; - case TQDns::Aaaa: - type = 28; - break; - case TQDns::Mx: - type = 15; - break; - case TQDns::Srv: - type = 33; - break; - case TQDns::Cname: - type = 5; - break; - case TQDns::Ptr: - type = 12; - break; - case TQDns::Txt: - type = 16; - break; - default: - type = (char)255; // any - break; - } - while( it != end ) { - TQString s = *it; - it++; - TQByteArray ba( 512 ); - int len = res_search( s.latin1(), 1, type, (uchar*)ba.data(), ba.size() ); - if ( len > 0 ) { - ba.resize( len ); - - TQDnsQuery * query = new TQDnsQuery; - query->started = now(); - query->id = ++theId; - query->t = t; - query->l = s; - TQDnsAnswer a( ba, query ); - a.parse(); - } else if ( len == -1 ) { - // res_search error - } - } - emit resultsReady(); - } -} -#endif - -#if defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 3))) -#define Q_MODERN_RES_API -#endif - -void TQDns::doResInit() -{ - if ( theNs ) - return; - theNs = new TQPtrList; - theNs->setAutoDelete( true ); - theDomains = new TQStrList( true ); - theDomains->setAutoDelete( true ); - - // read resolv.conf manually. - QFile resolvConf(TQLatin1String("/etc/resolv.conf")); - if (resolvConf.open(QIODevice::ReadOnly)) { - QTextStream stream( &resolvConf ); - TQString line; - - while ( !stream.atEnd() ) { - line = stream.readLine(); - TQStringList list = TQStringList::split( TQLatin1String(" "), line ); - if( line.startsWith( QLatin1Char('#') ) || list.size() < 2 ) - continue; - const TQString type = list[0].lower(); - - if ( type == TQLatin1String("nameserver") ) { - TQHostAddress *address = new TQHostAddress(); - if ( address->setAddress( TQString(list[1]) ) ) { - // only add ipv6 addresses from resolv.conf if - // this host supports ipv6. - if ( address->isIPv4Address() || ipv6support ) - theNs->append( address ); - else - delete address; - } else { - delete address; - } - } else if ( type == TQLatin1String("search") ) { - TQStringList srch = TQStringList::split( TQLatin1String(" "), list[1] ); - for ( TQStringList::Iterator i = srch.begin(); i != srch.end(); ++i ) - theDomains->append( (*i).lower().local8Bit() ); - - } else if ( type == TQLatin1String("domain") ) { - theDomains->append( list[1].lower().local8Bit() ); - } - } - } - - if (theNs->isEmpty()) { -#if defined(Q_MODERN_RES_API) - struct __res_state res; - res_ninit( &res ); - int i; - // find the name servers to use - for( i=0; i < MAXNS && i < res.nscount; i++ ) - theNs->append( new TQHostAddress( ntohl( res.nsaddr_list[i].sin_addr.s_addr ) ) ); -# if defined(MAXDFLSRCH) - for( i=0; i < MAXDFLSRCH; i++ ) { - if ( res.dnsrch[i] && *(res.dnsrch[i]) ) - theDomains->append( TQT_TQSTRING(TQString::fromLatin1( res.dnsrch[i] )).lower().local8Bit() ); - else - break; - } -# endif - if ( *res.defdname ) - theDomains->append( TQT_TQSTRING(TQString::fromLatin1( res.defdname )).lower().local8Bit() ); -#else - res_init(); - int i; - // find the name servers to use - for( i=0; i < MAXNS && i < _res.nscount; i++ ) - theNs->append( new TQHostAddress( ntohl( _res.nsaddr_list[i].sin_addr.s_addr ) ) ); -# if defined(MAXDFLSRCH) - for( i=0; i < MAXDFLSRCH; i++ ) { - if ( _res.dnsrch[i] && *(_res.dnsrch[i]) ) - theDomains->append( TQString::fromLatin1( _res.dnsrch[i] ).lower().local8Bit() ); - else - break; - } -# endif - if ( *_res.defdname ) - theDomains->append( TQString::fromLatin1( _res.defdname ).lower().local8Bit() ); -#endif - - // the code above adds "0.0.0.0" as a name server at the slightest - // hint of trouble. so remove those again. - theNs->first(); - while( theNs->current() ) { - if ( theNs->current()->isNull() ) - delete theNs->take(); - else - theNs->next(); - } - } - - QFile hosts( TQString::fromLatin1( "/etc/hosts" ) ); - if ( hosts.open( QIODevice::ReadOnly ) ) { - // read the /etc/hosts file, creating long-life A and PTR RRs - // for the things we find. - QTextStream i( &hosts ); - TQString line; - while( !i.atEnd() ) { - line = TQT_TQSTRING(i.readLine()).simplifyWhiteSpace().lower(); - uint n = 0; - while( (int) n < line.length() && line[(int)n] != QLatin1Char('#') ) - n++; - line.truncate( n ); - n = 0; - while( (int) n < line.length() && !line[(int)n].isSpace() ) - n++; - TQString ip = line.left( n ); - TQHostAddress a; - a.setAddress( ip ); - if ( ( a.isIPv4Address() || a.isIPv6Address() ) && !a.isNull() ) { - bool first = true; - line = line.mid( n+1 ); - n = 0; - while( (int) n < line.length() && !line[(int)n].isSpace() ) - n++; - TQString hostname = line.left( n ); - // ### in case of bad syntax, hostname is invalid. do we care? - if ( n ) { - TQDnsRR * rr = new TQDnsRR( hostname ); - if ( a.isIPv4Address() ) - rr->t = TQDns::A; - else - rr->t = TQDns::Aaaa; - rr->address = a; - rr->deleteTime = UINT_MAX; - rr->expireTime = UINT_MAX; - rr->current = true; - if ( first ) { - first = false; - TQDnsRR * ptr = new TQDnsRR( TQDns::toInAddrArpaDomain( a ) ); - ptr->t = TQDns::Ptr; - ptr->target = hostname; - ptr->deleteTime = UINT_MAX; - ptr->expireTime = UINT_MAX; - ptr->current = true; - } - } - } - } - } -} - -#endif - -QT_END_NAMESPACE - -#endif // QT_NO_DNS - - -#else // USE_QT4 - -/**************************************************************************** -** -** Implementation of TQDns class. -** -** Created : 991122 -** -** Copyright (C) 1999-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the network module of the TQt 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 TQt 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.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** 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 "tqplatformdefs.h" - -// POSIX Large File Support redefines open -> open64 -#if defined(open) -# undef open -#endif - -// POSIX Large File Support redefines truncate -> truncate64 -#if defined(truncate) -# undef truncate -#endif - -// Solaris redefines connect -> __xnet_connect with _XOPEN_SOURCE_EXTENDED. -#if defined(connect) -# undef connect -#endif - -// UnixWare 7 redefines socket -> _socket -#if defined(socket) -# undef socket -#endif - -#include "tqdns.h" - -#ifndef TQT_NO_DNS - -#include "tqdatetime.h" -#include "tqdict.h" -#include "tqptrlist.h" -#include "tqstring.h" -#include "tqtimer.h" -#include "tqapplication.h" -#include "tqptrvector.h" -#include "tqstrlist.h" -#include "tqptrdict.h" -#include "tqfile.h" -#include "tqtextstream.h" -#include "tqsocketdevice.h" -#include "tqcleanuphandler.h" -#include -#ifdef TQ_OS_MAC -#include "../3rdparty/dlcompat/dlfcn.h" -#endif - -//#define TQDNS_DEBUG - -static TQ_UINT16 id; // ### seeded started by now() - - -static TQDateTime * originOfTime = 0; - -static TQCleanupHandler qdns_cleanup_time; - -static TQ_UINT32 now() -{ - if ( originOfTime ) - return originOfTime->secsTo( TQDateTime::tqcurrentDateTime() ); - - originOfTime = new TQDateTime( TQDateTime::tqcurrentDateTime() ); - ::id = originOfTime->time().msec() * 60 + originOfTime->time().second(); - qdns_cleanup_time.add( &originOfTime ); - return 0; -} - - -static TQPtrList * ns = 0; -static TQStrList * domains = 0; -static bool ipv6support = FALSE; - -static int qdns_res_init() -{ -#ifdef TQ_OS_MAC - typedef int (*PtrRes_init)(); - static PtrRes_init ptrRes_init = 0; - if (!ptrRes_init) - ptrRes_init = (PtrRes_init)DL_PREFIX(dlsym)(RTLD_NEXT, "res_init"); - if (ptrRes_init) - return (*ptrRes_init)(); - else - return -1; -#elif defined(TQ_OS_UNIX) - return res_init(); -#else - return 0; // not called at all on Windows. -#endif -} - - -class TQDnsPrivate { -public: - TQDnsPrivate() : queryTimer( 0 ), noNames(FALSE) - { -#if defined(TQ_DNS_SYNCHRONOUS) -#if defined(TQ_OS_UNIX) - noEventLoop = tqApp==0 || tqApp->loopLevel()==0; -#else - noEventLoop = FALSE; -#endif -#endif - } - ~TQDnsPrivate() - { - delete queryTimer; - } -private: - TQTimer * queryTimer; - bool noNames; -#if defined(TQ_DNS_SYNCHRONOUS) - bool noEventLoop; -#endif - - friend class TQDns; - friend class TQDnsAnswer; -}; - - -class TQDnsRR; -class TQDnsDomain; - - - -// TQDnsRR is the class used to store a single RR. TQDnsRR can store -// all of the supported RR types. a TQDnsRR is always cached. - -// TQDnsRR is mostly constructed from the outside. a but hacky, but -// permissible since the entire class is internal. - -class TQDnsRR { -public: - TQDnsRR( const TQString & label ); - ~TQDnsRR(); - -public: - TQDnsDomain * domain; - TQDns::RecordType t; - bool nxdomain; - bool current; - TQ_UINT32 expireTime; - TQ_UINT32 deleteTime; - // somewhat space-wasting per-type data - // a / aaaa - TQHostAddress address; - // cname / mx / srv / ptr - TQString target; - // mx / srv - TQ_UINT16 priority; - // srv - TQ_UINT16 weight; - TQ_UINT16 port; - // txt - TQString text; // could be overloaded into target... -private: - -}; - - -class TQDnsDomain { -public: - TQDnsDomain( const TQString & label ); - ~TQDnsDomain(); - - static void add( const TQString & label, TQDnsRR * ); - static TQPtrList * cached( const TQDns * ); - - void take( TQDnsRR * ); - - void sweep( TQ_UINT32 thisSweep ); - - bool isEmpty() const { return rrs == 0 || rrs->isEmpty(); } - - TQString name() const { return l; } - -public: - TQString l; - TQPtrList * rrs; -}; - - -class TQDnsQuery: public TQTimer { // this inheritance is a very evil hack -public: - TQDnsQuery(): - id( 0 ), t( TQDns::None ), step(0), started(0), - dns( new TQPtrDict(17) ) {} - ~TQDnsQuery() { delete dns; } - TQ_UINT16 id; - TQDns::RecordType t; - TQString l; - - uint step; - TQ_UINT32 started; - - TQPtrDict * dns; -}; - - - -class TQDnsAnswer { -public: - TQDnsAnswer( TQDnsQuery * ); - TQDnsAnswer( const TQByteArray &, TQDnsQuery * ); - ~TQDnsAnswer(); - - void parse(); - void notify(); - - bool ok; - -private: - TQDnsQuery * query; - - TQ_UINT8 * answer; - int size; - int pp; - - TQPtrList * rrs; - - // convenience - int next; - int ttl; - TQString label; - TQDnsRR * rr; - - TQString readString(bool multipleLabels = TRUE); - void parseA(); - void parseAaaa(); - void parseMx(); - void parseSrv(); - void parseCname(); - void parsePtr(); - void parseTxt(); - void parseNs(); -}; - - -TQDnsRR::TQDnsRR( const TQString & label ) - : domain( 0 ), t( TQDns::None ), - nxdomain( FALSE ), current( FALSE ), - expireTime( 0 ), deleteTime( 0 ), - priority( 0 ), weight( 0 ), port( 0 ) -{ - TQDnsDomain::add( label, this ); -} - - -// not supposed to be deleted except by TQDnsDomain -TQDnsRR::~TQDnsRR() -{ - // nothing is necessary -} - - -// this one just sticks in a NXDomain -TQDnsAnswer::TQDnsAnswer( TQDnsQuery * query_ ) -{ - ok = TRUE; - - answer = 0; - size = 0; - query = query_; - pp = 0; - rrs = new TQPtrList; - rrs->setAutoDelete( FALSE ); - next = size; - ttl = 0; - label = TQString::null; - rr = 0; - - TQDnsRR * newrr = new TQDnsRR( query->l ); - newrr->t = query->t; - newrr->deleteTime = query->started + 10; - newrr->expireTime = query->started + 10; - newrr->nxdomain = TRUE; - newrr->current = TRUE; - rrs->append( newrr ); -} - - -TQDnsAnswer::TQDnsAnswer( const TQByteArray& answer_, - TQDnsQuery * query_ ) -{ - ok = TRUE; - - answer = (TQ_UINT8 *)(answer_.data()); - size = (int)answer_.size(); - query = query_; - pp = 0; - rrs = new TQPtrList; - rrs->setAutoDelete( FALSE ); - next = size; - ttl = 0; - label = TQString::null; - rr = 0; -} - - -TQDnsAnswer::~TQDnsAnswer() -{ - if ( !ok && rrs ) { - TQPtrListIterator it( *rrs ); - TQDnsRR * tmprr; - while( (tmprr=it.current()) != 0 ) { - ++it; - tmprr->t = TQDns::None; // will be deleted soonish - } - } - delete rrs; -} - - -TQString TQDnsAnswer::readString(bool multipleLabels) -{ - int p = pp; - TQString r = TQString::null; - TQ_UINT8 b; - for( ;; ) { - b = 128; - // Read one character - if ( p >= 0 && p < size ) - b = answer[p]; - - switch( b >> 6 ) { - case 0: - // b is less than 64 - p++; - - // Detect end of data - if ( b == 0 ) { - if ( p > pp ) - pp = p; - return r.isNull() ? TQString( "." ) : r; - } - - // Read a label of size 'b' characters - if ( !r.isNull() ) - r += '.'; - while( b-- > 0 ) { - r += TQChar( answer[p] ); - p++; - } - - // Return immediately if we were only supposed to read one - // label. - if (!multipleLabels) - return r; - - break; - default: - // Ignore unrecognized control character, or p was out of - // range. - goto not_ok; - case 3: - // Use the next character to determine the relative offset - // to jump to before continuing the packet parsing. - int q = ( (answer[p] & 0x3f) << 8 ) + answer[p+1]; - - if ( q >= pp || q >= p ) - goto not_ok; - if ( p >= pp ) - pp = p + 2; - p = q; - } - } -not_ok: - ok = FALSE; - return TQString::null; -} - - - -void TQDnsAnswer::parseA() -{ - if ( next != pp + 4 ) { -#if defined(TQDNS_DEBUG) - qDebug( "TQDns: saw %d bytes long IN A for %s", - next - pp, label.ascii() ); -#endif - return; - } - - rr = new TQDnsRR( label ); - rr->t = TQDns::A; - rr->address = TQHostAddress( ( answer[pp+0] << 24 ) + - ( answer[pp+1] << 16 ) + - ( answer[pp+2] << 8 ) + - ( answer[pp+3] ) ); -#if defined(TQDNS_DEBUG) - qDebug( "TQDns: saw %s IN A %s (ttl %d)", label.ascii(), - rr->address.toString().ascii(), ttl ); -#endif -} - - -void TQDnsAnswer::parseAaaa() -{ - if ( next != pp + 16 ) { -#if defined(TQDNS_DEBUG) - qDebug( "TQDns: saw %d bytes long IN Aaaa for %s", - next - pp, label.ascii() ); -#endif - return; - } - - rr = new TQDnsRR( label ); - rr->t = TQDns::Aaaa; - rr->address = TQHostAddress( answer+pp ); -#if defined(TQDNS_DEBUG) - qDebug( "TQDns: saw %s IN Aaaa %s (ttl %d)", label.ascii(), - rr->address.toString().ascii(), ttl ); -#endif -} - - - -void TQDnsAnswer::parseMx() -{ - if ( next < pp + 2 ) { -#if defined(TQDNS_DEBUG) - qDebug( "TQDns: saw %d bytes long IN MX for %s", - next - pp, label.ascii() ); -#endif - return; - } - - rr = new TQDnsRR( label ); - rr->priority = (answer[pp] << 8) + answer[pp+1]; - pp += 2; - rr->target = readString().lower(); - if ( !ok ) { -#if defined(TQDNS_DEBUG) - qDebug( "TQDns: saw bad string in MX for %s", label.ascii() ); -#endif - return; - } - rr->t = TQDns::Mx; -#if defined(TQDNS_DEBUG) - qDebug( "TQDns: saw %s IN MX %d %s (ttl %d)", label.ascii(), - rr->priority, rr->target.ascii(), ttl ); -#endif -} - - -void TQDnsAnswer::parseSrv() -{ - if ( next < pp + 6 ) { -#if defined(TQDNS_DEBUG) - qDebug( "TQDns: saw %d bytes long IN SRV for %s", - next - pp, label.ascii() ); -#endif - return; - } - - rr = new TQDnsRR( label ); - rr->priority = (answer[pp] << 8) + answer[pp+1]; - rr->weight = (answer[pp+2] << 8) + answer[pp+3]; - rr->port = (answer[pp+4] << 8) + answer[pp+5]; - pp += 6; - rr->target = readString().lower(); - if ( !ok ) { -#if defined(TQDNS_DEBUG) - qDebug( "TQDns: saw bad string in SRV for %s", label.ascii() ); -#endif - return; - } - rr->t = TQDns::Srv; -#if defined(TQDNS_DEBUG) - qDebug( "TQDns: saw %s IN SRV %d %d %d %s (ttl %d)", label.ascii(), - rr->priority, rr->weight, rr->port, rr->target.ascii(), ttl ); -#endif -} - - -void TQDnsAnswer::parseCname() -{ - TQString target = readString().lower(); - if ( !ok ) { -#if defined(TQDNS_DEBUG) - qDebug( "TQDns: saw bad cname for for %s", label.ascii() ); -#endif - return; - } - - rr = new TQDnsRR( label ); - rr->t = TQDns::Cname; - rr->target = target; -#if defined(TQDNS_DEBUG) - qDebug( "TQDns: saw %s IN CNAME %s (ttl %d)", label.ascii(), - rr->target.ascii(), ttl ); -#endif -} - - -void TQDnsAnswer::parseNs() -{ - TQString target = readString().lower(); - if ( !ok ) { -#if defined(TQDNS_DEBUG) - qDebug( "TQDns: saw bad cname for for %s", label.ascii() ); -#endif - return; - } - - // parse, but ignore - -#if defined(TQDNS_DEBUG) - qDebug( "TQDns: saw %s IN NS %s (ttl %d)", label.ascii(), - target.ascii(), ttl ); -#endif -} - - -void TQDnsAnswer::parsePtr() -{ - TQString target = readString().lower(); - if ( !ok ) { -#if defined(TQDNS_DEBUG) - qDebug( "TQDns: saw bad PTR for for %s", label.ascii() ); -#endif - return; - } - - rr = new TQDnsRR( label ); - rr->t = TQDns::Ptr; - rr->target = target; -#if defined(TQDNS_DEBUG) - qDebug( "TQDns: saw %s IN PTR %s (ttl %d)", label.ascii(), - rr->target.ascii(), ttl ); -#endif -} - - -void TQDnsAnswer::parseTxt() -{ - TQString text = readString(FALSE); - if ( !ok ) { -#if defined(TQDNS_DEBUG) - qDebug( "TQDns: saw bad TXT for for %s", label.ascii() ); -#endif - return; - } - - rr = new TQDnsRR( label ); - rr->t = TQDns::Txt; - rr->text = text; -#if defined(TQDNS_DEBUG) - qDebug( "TQDns: saw %s IN TXT \"%s\" (ttl %d)", label.ascii(), - rr->text.ascii(), ttl ); -#endif -} - - -void TQDnsAnswer::parse() -{ - // okay, do the work... - if ( (answer[2] & 0x78) != 0 ) { -#if defined(TQDNS_DEBUG) - qDebug( "DNS Manager: answer to wrong query type (%d)", answer[1] ); -#endif - ok = FALSE; - return; - } - - // AA - bool aa = (answer[2] & 4) != 0; - - // TC - if ( (answer[2] & 2) != 0 ) { -#if defined(TQDNS_DEBUG) - qDebug( "DNS Manager: truncated answer; pressing on" ); -#endif - } - - // RD - bool rd = (answer[2] & 1) != 0; - - // we don't test RA - // we don't test the MBZ fields - - if ( (answer[3] & 0x0f) == 3 ) { -#if defined(TQDNS_DEBUG) - qDebug( "DNS Manager: saw NXDomain for %s", query->l.ascii() ); -#endif - // NXDomain. cache that for one minute. - rr = new TQDnsRR( query->l ); - rr->t = query->t; - rr->deleteTime = query->started + 60; - rr->expireTime = query->started + 60; - rr->nxdomain = TRUE; - rr->current = TRUE; - rrs->append( rr ); - return; - } - - if ( (answer[3] & 0x0f) != 0 ) { -#if defined(TQDNS_DEBUG) - qDebug( "DNS Manager: error code %d", answer[3] & 0x0f ); -#endif - ok = FALSE; - return; - } - - int qdcount = ( answer[4] << 8 ) + answer[5]; - int ancount = ( answer[6] << 8 ) + answer[7]; - int nscount = ( answer[8] << 8 ) + answer[9]; - int adcount = (answer[10] << 8 ) +answer[11]; - - pp = 12; - - // read query - while( qdcount > 0 && pp < size ) { - // should I compare the string against query->l? - (void)readString(); - if ( !ok ) - return; - pp += 4; - qdcount--; - } - - // answers and stuff - int rrno = 0; - // if we parse the answer completely, but there are no answers, - // ignore the entire thing. - int answers = 0; - while( ( rrno < ancount || - ( ok && answers >0 && rrno < ancount + nscount + adcount ) ) && - pp < size ) { - label = readString().lower(); - if ( !ok ) - return; - int rdlength = 0; - if ( pp + 10 <= size ) - rdlength = ( answer[pp+8] << 8 ) + answer[pp+9]; - if ( pp + 10 + rdlength > size ) { -#if defined(TQDNS_DEBUG) - qDebug( "DNS Manager: ran out of stuff to parse (%d+%d>%d (%d)", - pp, rdlength, size, rrno < ancount ); -#endif - // if we're still in the AN section, we should go back and - // at least down the TTLs. probably best to tqinvalidate - // the results. - // the rrs list is good for this - ok = ( rrno < ancount ); - return; - } - uint type, clas; - type = ( answer[pp+0] << 8 ) + answer[pp+1]; - clas = ( answer[pp+2] << 8 ) + answer[pp+3]; - ttl = ( answer[pp+4] << 24 ) + ( answer[pp+5] << 16 ) + - ( answer[pp+6] << 8 ) + answer[pp+7]; - pp = pp + 10; - if ( clas != 1 ) { -#if defined(TQDNS_DEBUG) - qDebug( "DNS Manager: class %d (not internet) for %s", - clas, label.isNull() ? "." : label.ascii() ); -#endif - } else { - next = pp + rdlength; - rr = 0; - switch( type ) { - case 1: - parseA(); - break; - case 28: - parseAaaa(); - break; - case 15: - parseMx(); - break; - case 33: - parseSrv(); - break; - case 5: - parseCname(); - break; - case 12: - parsePtr(); - break; - case 16: - parseTxt(); - break; - case 2: - parseNs(); - break; - default: - // something we don't know -#if defined(TQDNS_DEBUG) - qDebug( "DNS Manager: type %d for %s", type, - label.isNull() ? "." : label.ascii() ); -#endif - break; - } - if ( rr ) { - rr->deleteTime = 0; - if ( ttl > 0 ) - rr->expireTime = query->started + ttl; - else - rr->expireTime = query->started + 20; - if ( rrno < ancount ) { - answers++; - rr->deleteTime = rr->expireTime; - } - rr->current = TRUE; - rrs->append( rr ); - } - } - if ( !ok ) - return; - pp = next; - next = size; - rrno++; - } - if ( answers == 0 ) { -#if defined(TQDNS_DEBUG) - qDebug( "DNS Manager: answer contained no answers" ); -#endif - ok = ( aa && rd ); - } - - // now go through the list and mark all the As that are referenced - // by something we care about. we want to cache such As. - rrs->first(); - TQDict used( 17 ); - used.setAutoDelete( FALSE ); - while( (rr=rrs->current()) != 0 ) { - rrs->next(); - if ( rr->target.length() && rr->deleteTime > 0 && rr->current ) - used.insert( rr->target, (void*)42 ); - if ( ( rr->t == TQDns::A || rr->t == TQDns::Aaaa ) && - used.find( rr->domain->name() ) != 0 ) - rr->deleteTime = rr->expireTime; - } - - // next, for each RR, delete any older RRs that are equal to it - rrs->first(); - while( (rr=rrs->current()) != 0 ) { - rrs->next(); - if ( rr && rr->domain && rr->domain->rrs ) { - TQPtrList * drrs = rr->domain->rrs; - drrs->first(); - TQDnsRR * older; - while( (older=drrs->current()) != 0 ) { - if ( older != rr && - older->t == rr->t && - older->nxdomain == rr->nxdomain && - older->address == rr->address && - older->target == rr->target && - older->priority == rr->priority && - older->weight == rr->weight && - older->port == rr->port && - older->text == rr->text ) { - // well, it's equal, but it's not the same. so we kill it, - // but use its expiry time. -#if defined(TQDNS_DEBUG) - qDebug( "killing off old %d for %s, expire was %d", - older->t, older->domain->name().latin1(), - rr->expireTime ); -#endif - older->t = TQDns::None; - rr->expireTime = TQMAX( older->expireTime, rr->expireTime ); - rr->deleteTime = TQMAX( older->deleteTime, rr->deleteTime ); - older->deleteTime = 0; -#if defined(TQDNS_DEBUG) - qDebug( " adjusted expire is %d", rr->expireTime ); -#endif - } - drrs->next(); - } - } - } - -#if defined(TQDNS_DEBUG) - //qDebug( "DNS Manager: ()" ); -#endif -} - - -class TQDnsUgleHack: public TQDns { -public: - void ugle( bool emitAnyway=FALSE ); -}; - - -void TQDnsAnswer::notify() -{ - if ( !rrs || !ok || !query || !query->dns ) - return; - - TQPtrDict notified; - notified.setAutoDelete( FALSE ); - - TQPtrDictIterator it( *query->dns ); - TQDns * dns; - it.toFirst(); - while( (dns=(TQDns*)(it.current())) != 0 ) { - ++it; - if ( notified.find( (void*)dns ) == 0 ) { - notified.insert( (void*)dns, (void*)42 ); - if ( rrs->count() == 0 ) { -#if defined(TQDNS_DEBUG) - qDebug( "DNS Manager: found no answers!" ); -#endif - dns->d->noNames = TRUE; - ((TQDnsUgleHack*)dns)->ugle( TRUE ); - } else { - TQStringList n = dns->qualifiedNames(); - if ( query && n.contains(query->l) ) - ((TQDnsUgleHack*)dns)->ugle(); -#if defined(TQDNS_DEBUG) - else - qDebug( "DNS Manager: DNS thing %s not notified for %s", - dns->label().ascii(), query->l.ascii() ); -#endif - } - } - } -} - - -// -// -// TQDnsManager -// -// - - -class TQDnsManager: public TQDnsSocket { -private: -public: // just to silence the moronic g++. - TQDnsManager(); - ~TQDnsManager(); -public: - static TQDnsManager * manager(); - - TQDnsDomain * domain( const TQString & ); - - void transmitQuery( TQDnsQuery * ); - void transmitQuery( int ); - - // reimplementation of the Q_SLOTS - void cleanCache(); - void retransmit(); - void answer(); - -public: - TQPtrVector queries; - TQDict cache; - TQSocketDevice * ipv4Socket; -#if !defined (TQT_NO_IPV6) - TQSocketDevice * ipv6Socket; -#endif -}; - - - -static TQDnsManager * globalManager = 0; - -static void cleanupDns() -{ - delete globalManager; - globalManager = 0; -} - -TQDnsManager * TQDnsManager::manager() -{ - if ( !globalManager ) { - qAddPostRoutine(cleanupDns); - new TQDnsManager(); - } - return globalManager; -} - - -void TQDnsUgleHack::ugle( bool emitAnyway) -{ - if ( emitAnyway || !isWorking() ) { -#if defined(TQDNS_DEBUG) - qDebug( "DNS Manager: status change for %s (type %d)", - label().ascii(), recordType() ); -#endif - emit resultsReady(); - } -} - - -TQDnsManager::TQDnsManager() - : TQDnsSocket( tqApp, "Internal DNS manager" ), - queries( TQPtrVector( 0 ) ), - cache( TQDict( 83, FALSE ) ), - ipv4Socket( new TQSocketDevice( TQSocketDevice::Datagram, TQSocketDevice::IPv4, 0 ) ) -#if !defined (TQT_NO_IPV6) - , ipv6Socket( new TQSocketDevice( TQSocketDevice::Datagram, TQSocketDevice::IPv6, 0 ) ) -#endif -{ - cache.setAutoDelete( TRUE ); - globalManager = this; - - TQTimer * sweepTimer = new TQTimer( this ); - sweepTimer->start( 1000 * 60 * 3 ); - connect( sweepTimer, TQT_SIGNAL(timeout()), - this, TQT_SLOT(cleanCache()) ); - - TQSocketNotifier * rn4 = new TQSocketNotifier( ipv4Socket->socket(), - TQSocketNotifier::Read, - TQT_TQOBJECT(this), "dns IPv4 socket watcher" ); - ipv4Socket->setAddressReusable( FALSE ); - ipv4Socket->setBlocking( FALSE ); - connect( rn4, TQT_SIGNAL(activated(int)), TQT_SLOT(answer()) ); - -#if !defined (TQT_NO_IPV6) - // Don't connect the IPv6 socket notifier if the host does not - // support IPv6. - if ( ipv6Socket->socket() != -1 ) { - TQSocketNotifier * rn6 = new TQSocketNotifier( ipv6Socket->socket(), - TQSocketNotifier::Read, - TQT_TQOBJECT(this), "dns IPv6 socket watcher" ); - - ipv6support = TRUE; - ipv6Socket->setAddressReusable( FALSE ); - ipv6Socket->setBlocking( FALSE ); - connect( rn6, TQT_SIGNAL(activated(int)), TQT_SLOT(answer()) ); - } -#endif - - if ( !ns ) - TQDns::doResInit(); - - // O(n*n) stuff here. but for 3 and 6, O(n*n) with a low k should - // be perfect. the point is to eliminate any duplicates that - // might be hidden in the lists. - TQPtrList * ns = new TQPtrList; - - ::ns->first(); - TQHostAddress * h; - while( (h=::ns->current()) != 0 ) { - ns->first(); - while( ns->current() != 0 && !(*ns->current() == *h) ) - ns->next(); - if ( !ns->current() ) { - ns->append( new TQHostAddress(*h) ); -#if defined(TQDNS_DEBUG) - qDebug( "using name server %s", h->toString().latin1() ); - } else { - qDebug( "skipping address %s", h->toString().latin1() ); -#endif - } - ::ns->next(); - } - - delete ::ns; - ::ns = ns; - ::ns->setAutoDelete( TRUE ); - - TQStrList * domains = new TQStrList( TRUE ); - - ::domains->first(); - const char * s; - while( (s=::domains->current()) != 0 ) { - domains->first(); - while( domains->current() != 0 && qstrcmp( domains->current(), s ) ) - domains->next(); - if ( !domains->current() ) { - domains->append( s ); -#if defined(TQDNS_DEBUG) - qDebug( "searching domain %s", s ); - } else { - qDebug( "skipping domain %s", s ); -#endif - } - ::domains->next(); - } - - delete ::domains; - ::domains = domains; - ::domains->setAutoDelete( TRUE ); -} - - -TQDnsManager::~TQDnsManager() -{ - if ( globalManager ) - globalManager = 0; - queries.setAutoDelete( TRUE ); - cache.setAutoDelete( TRUE ); - delete ipv4Socket; -#if !defined (TQT_NO_IPV6) - delete ipv6Socket; -#endif -} - -static TQ_UINT32 lastSweep = 0; - -void TQDnsManager::cleanCache() -{ - bool again = FALSE; - TQDictIterator it( cache ); - TQDnsDomain * d; - TQ_UINT32 thisSweep = now(); -#if defined(TQDNS_DEBUG) - qDebug( "TQDnsManager::cleanCache(: Called, time is %u, last was %u", - thisSweep, lastSweep ); -#endif - - while( (d=it.current()) != 0 ) { - ++it; - d->sweep( thisSweep ); // after this, d may be empty - if ( !again ) - again = !d->isEmpty(); - } - if ( !again ) - delete this; - lastSweep = thisSweep; -} - - -void TQDnsManager::retransmit() -{ - const TQObject * o = sender(); - if ( o == 0 || globalManager == 0 || this != globalManager ) - return; - uint q = 0; - while( q < queries.size() && queries[q] != o ) - q++; - if ( q < queries.size() ) - transmitQuery( q ); -} - - -void TQDnsManager::answer() -{ - TQByteArray a( 16383 ); // large enough for anything, one suspects - - int r; -#if defined (TQT_NO_IPV6) - r = ipv4Socket->readBlock(a.data(), a.size()); -#else - if (((TQSocketNotifier *)sender())->socket() == ipv4Socket->socket()) - r = ipv4Socket->readBlock(a.data(), a.size()); - else - r = ipv6Socket->readBlock(a.data(), a.size()); -#endif -#if defined(TQDNS_DEBUG) -#if !defined (TQT_NO_IPV6) - qDebug("DNS Manager: answer arrived: %d bytes from %s:%d", r, - useIpv4Socket ? ipv4Socket->peerAddress().toString().ascii() - : ipv6Socket->peerAddress().toString().ascii(), - useIpv4Socket ? ipv4Socket->peerPort() : ipv6Socket->peerPort() ); -#else - qDebug("DNS Manager: answer arrived: %d bytes from %s:%d", r, - ipv4Socket->peerAddress().toString().ascii(), ipv4Socket->peerPort());; -#endif -#endif - if ( r < 12 ) - return; - // maybe we should check that the answer comes from port 53 on one - // of our name servers... - a.resize( r ); - - TQ_UINT16 aid = (((TQ_UINT8)a[0]) << 8) + ((TQ_UINT8)a[1]); - uint i = 0; - while( i < queries.size() && - !( queries[i] && queries[i]->id == aid ) ) - i++; - if ( i == queries.size() ) { -#if defined(TQDNS_DEBUG) - qDebug( "DNS Manager: bad id (0x%04x) %d", aid, i ); -#endif - return; - } - - // at this point queries[i] is whatever we asked for. - - if ( ( (TQ_UINT8)(a[2]) & 0x80 ) == 0 ) { -#if defined(TQDNS_DEBUG) - qDebug( "DNS Manager: received a query" ); -#endif - return; - } - - TQDnsQuery * q = queries[i]; - TQDnsAnswer answer( a, q ); - answer.parse(); - if ( answer.ok ) { - queries.take( i ); - answer.notify(); - delete q; - } -} - - -void TQDnsManager::transmitQuery( TQDnsQuery * query_ ) -{ - if ( !query_ ) - return; - - uint i = 0; - while( i < queries.size() && queries[i] != 0 ) - i++; - if ( i == queries.size() ) - queries.resize( i+1 ); - queries.insert( i, query_ ); - transmitQuery( i ); -} - - -void TQDnsManager::transmitQuery( int i ) -{ - if ( i < 0 || i >= (int)queries.size() ) - return; - TQDnsQuery * q = queries[i]; - - if ( q && q->step > 8 ) { - // okay, we've run out of retransmissions. we fake an NXDomain - // with a very short life time... - TQDnsAnswer answer( q ); - answer.notify(); - - if (globalManager == 0) - return; - - // and then get rid of the query - queries.take( i ); -#if defined(TQDNS_DEBUG) - qDebug( "DNS Manager: giving up on query 0x%04x", q->id ); -#endif - delete q; - TQTimer::singleShot( 0, TQDnsManager::manager(), TQT_SLOT(cleanCache()) ); - // and don't process anything more - return; - } - - if ( q && !q->dns || q->dns->isEmpty() ) - // noone currently wants the answer, so there's no point in - // retransmitting the query. we keep it, though. an answer may - // arrive for an earlier query transmission, and if it does we - // may benefit from caching the result. - return; - - TQByteArray p( 12 + q->l.length() + 2 + 4 ); - if ( p.size() > 500 ) - return; // way over the limit, so don't even try - - // header - // id - p[0] = (q->id & 0xff00) >> 8; - p[1] = q->id & 0x00ff; - p[2] = 1; // recursion desired, rest is 0 - p[3] = 0; // all is 0 - // one query - p[4] = 0; - p[5] = 1; - // no answers, name servers or additional data - p[6] = p[7] = p[8] = p[9] = p[10] = p[11] = 0; - - // the name is composed of several components. each needs to be - // written by itself... so we write... - // oh, and we assume that there's no funky characters in there. - int pp = 12; - uint lp = 0; - while( lp < q->l.length() ) { - int le = q->l.find( '.', lp ); - if ( le < 0 ) - le = q->l.length(); - TQString component = q->l.mid( lp, le-lp ); - p[pp++] = component.length(); - int cp; - for( cp=0; cp < (int)component.length(); cp++ ) - p[pp++] = component[cp].latin1(); - lp = le + 1; - } - // final null - p[pp++] = 0; - // query type - p[pp++] = 0; - switch( q->t ) { - case TQDns::A: - p[pp++] = 1; - break; - case TQDns::Aaaa: - p[pp++] = 28; - break; - case TQDns::Mx: - p[pp++] = 15; - break; - case TQDns::Srv: - p[pp++] = 33; - break; - case TQDns::Cname: - p[pp++] = 5; - break; - case TQDns::Ptr: - p[pp++] = 12; - break; - case TQDns::Txt: - p[pp++] = 16; - break; - default: - p[pp++] = (char)255; // any - break; - } - // query class (always internet) - p[pp++] = 0; - p[pp++] = 1; - - // if we have no name servers, we should regenerate ns in case - // name servers have recently been defined (like on windows, - // plugging/unplugging the network cable will change the name - // server entries) - if ( !ns || ns->isEmpty() ) - TQDns::doResInit(); - - if ( !ns || ns->isEmpty() ) { - // we don't find any name servers. We fake an NXDomain - // with a very short life time... - TQDnsAnswer answer( q ); - answer.notify(); - // and then get rid of the query - queries.take( i ); -#if defined(TQDNS_DEBUG) - qDebug( "DNS Manager: no DNS server found on query 0x%04x", q->id ); -#endif - delete q; - TQTimer::singleShot( 1000*10, TQDnsManager::manager(), TQT_SLOT(cleanCache()) ); - // and don't process anything more - return; - } - - TQHostAddress receiver = *ns->at( q->step % ns->count() ); - if (receiver.isIPv4Address()) - ipv4Socket->writeBlock( p.data(), pp, receiver, 53 ); -#if !defined (TQT_NO_IPV6) - else - ipv6Socket->writeBlock( p.data(), pp, receiver, 53 ); -#endif -#if defined(TQDNS_DEBUG) - qDebug( "issuing query 0x%04x (%d) about %s type %d to %s", - q->id, q->step, q->l.ascii(), q->t, - ns->at( q->step % ns->count() )->toString().ascii() ); -#endif - if ( ns->count() > 1 && q->step == 0 && queries.count() == 1 ) { - // if it's the first time, and we don't have any other - // outstanding queries, send nonrecursive queries to the other - // name servers too. - p[2] = 0; - TQHostAddress * server; - while( (server=ns->next()) != 0 ) { - if (server->isIPv4Address()) - ipv4Socket->writeBlock( p.data(), pp, *server, 53 ); -#if !defined (TQT_NO_IPV6) - else - ipv6Socket->writeBlock( p.data(), pp, *server, 53 ); -#endif -#if defined(TQDNS_DEBUG) - qDebug( "copying query to %s", server->toString().ascii() ); -#endif - } - } - q->step++; - // some testing indicates that normal dns queries take up to 0.6 - // seconds. the graph becomes steep around that point, and the - // number of errors rises... so it seems good to retry at that - // point. - q->start( q->step < ns->count() ? 800 : 1500, TRUE ); -} - - -TQDnsDomain * TQDnsManager::domain( const TQString & label ) -{ - TQDnsDomain * d = cache.find( label ); - if ( !d ) { - d = new TQDnsDomain( label ); - cache.insert( label, d ); - } - return d; -} - - -// -// -// the TQDnsDomain class looks after and coordinates queries for TQDnsRRs for -// each domain, and the cached TQDnsRRs. (A domain, in DNS terminology, is -// a node in the DNS. "no", "trolltech.com" and "lupinella.troll.no" are -// all domains.) -// -// - - -// this is ONLY to be called by TQDnsManager::domain(). noone else. -TQDnsDomain::TQDnsDomain( const TQString & label ) -{ - l = label; - rrs = 0; -} - - -TQDnsDomain::~TQDnsDomain() -{ - delete rrs; - rrs = 0; -} - - -void TQDnsDomain::add( const TQString & label, TQDnsRR * rr ) -{ - TQDnsDomain * d = TQDnsManager::manager()->domain( label ); - if ( !d->rrs ) { - d->rrs = new TQPtrList; - d->rrs->setAutoDelete( TRUE ); - } - d->rrs->append( rr ); - rr->domain = d; -} - - -TQPtrList * TQDnsDomain::cached( const TQDns * r ) -{ - TQPtrList * l = new TQPtrList; - - // test at first if you have to start a query at all - if ( r->recordType() == TQDns::A ) { - if ( r->label().lower() == "localhost" ) { - // undocumented hack. ipv4-specific. also, may be a memory - // leak? not sure. would be better to do this in doResInit(), - // anyway. - TQDnsRR *rrTmp = new TQDnsRR( r->label() ); - rrTmp->t = TQDns::A; - rrTmp->address = TQHostAddress( 0x7f000001 ); - rrTmp->current = TRUE; - l->append( rrTmp ); - return l; - } - TQHostAddress tmp; - if ( tmp.setAddress( r->label() ) ) { - TQDnsRR *rrTmp = new TQDnsRR( r->label() ); - if ( tmp.isIPv4Address() ) { - rrTmp->t = TQDns::A; - rrTmp->address = tmp; - rrTmp->current = TRUE; - l->append( rrTmp ); - } else { - rrTmp->nxdomain = TRUE; - } - return l; - } - } - if ( r->recordType() == TQDns::Aaaa ) { - TQHostAddress tmp; - if ( tmp.setAddress(r->label()) ) { - TQDnsRR *rrTmp = new TQDnsRR( r->label() ); - if ( tmp.isIPv6Address() ) { - rrTmp->t = TQDns::Aaaa; - rrTmp->address = tmp; - rrTmp->current = TRUE; - l->append( rrTmp ); - } else { - rrTmp->nxdomain = TRUE; - } - return l; - } - } - - // if you reach this point, you have to do the query - TQDnsManager * m = TQDnsManager::manager(); - TQStringList n = r->qualifiedNames(); - TQValueListIterator it = n.begin(); - TQValueListIterator end = n.end(); - bool nxdomain; - int cnamecount = 0; - while( it != end ) { - TQString s = *it++; - nxdomain = FALSE; -#if defined(TQDNS_DEBUG) - qDebug( "looking at cache for %s (%s %d)", - s.ascii(), r->label().ascii(), r->recordType() ); -#endif - TQDnsDomain * d = m->domain( s ); -#if defined(TQDNS_DEBUG) - qDebug( " - found %d RRs", d && d->rrs ? d->rrs->count() : 0 ); -#endif - if ( d->rrs ) - d->rrs->first(); - TQDnsRR * rr; - bool answer = FALSE; - while( d->rrs && (rr=d->rrs->current()) != 0 ) { - if ( rr->t == TQDns::Cname && r->recordType() != TQDns::Cname && - !rr->nxdomain && cnamecount < 16 ) { - // cname. if the code is ugly, that may just - // possibly be because the concept is. -#if defined(TQDNS_DEBUG) - qDebug( "found cname from %s to %s", - r->label().ascii(), rr->target.ascii() ); -#endif - s = rr->target; - d = m->domain( s ); - if ( d->rrs ) - d->rrs->first(); - it = end; - // we've elegantly moved over to whatever the cname - // pointed to. well, not elegantly. let's remember - // that we've done something, anyway, so we can't be - // fooled into an infinte loop as well. - cnamecount++; - } else { - if ( rr->t == r->recordType() ) { - if ( rr->nxdomain ) - nxdomain = TRUE; - else - answer = TRUE; - l->append( rr ); - if ( rr->deleteTime <= lastSweep ) { - // we're returning something that'll be - // deleted soon. we assume that if the client - // wanted it twice, it'll want it again, so we - // ask the name server again right now. - TQDnsQuery * query = new TQDnsQuery; - query->started = now(); - query->id = ++::id; - query->t = rr->t; - query->l = rr->domain->name(); - // note that here, we don't bother about - // notification. but we do bother about - // timeouts: we make sure to use high timeouts - // and few tramsissions. - query->step = ns->count(); - TQObject::connect( query, TQT_SIGNAL(timeout()), - TQDnsManager::manager(), - TQT_SLOT(retransmit()) ); - TQDnsManager::manager()->transmitQuery( query ); - } - } - d->rrs->next(); - } - } - // if we found a positive result, return quickly - if ( answer && l->count() ) { -#if defined(TQDNS_DEBUG) - qDebug( "found %d records for %s", - l->count(), r->label().ascii() ); - l->first(); - while( l->current() ) { - qDebug( " type %d target %s address %s", - l->current()->t, - l->current()->target.latin1(), - l->current()->address.toString().latin1() ); - l->next(); - } -#endif - l->first(); - return l; - } - -#if defined(TQDNS_DEBUG) - if ( nxdomain ) - qDebug( "found NXDomain %s", s.ascii() ); -#endif - - if ( !nxdomain ) { - // if we didn't, and not a negative result either, perhaps - // we need to transmit a query. - uint q = 0; - while ( q < m->queries.size() && - ( m->queries[q] == 0 || - m->queries[q]->t != r->recordType() || - m->queries[q]->l != s ) ) - q++; - // we haven't done it before, so maybe we should. but - // wait - if it's an unqualified name, only ask when all - // the other alternatives are exhausted. - if ( q == m->queries.size() && ( s.find( '.' ) >= 0 || - l->count() >= n.count()-1 ) ) { - TQDnsQuery * query = new TQDnsQuery; - query->started = now(); - query->id = ++::id; - query->t = r->recordType(); - query->l = s; - query->dns->replace( (void*)r, (void*)r ); - TQObject::connect( query, TQT_SIGNAL(timeout()), - TQDnsManager::manager(), TQT_SLOT(retransmit()) ); - TQDnsManager::manager()->transmitQuery( query ); - } else if ( q < m->queries.size() ) { - // if we've found an earlier query for the same - // domain/type, subscribe to its answer - m->queries[q]->dns->replace( (void*)r, (void*)r ); - } - } - } - l->first(); - return l; -} - - -void TQDnsDomain::sweep( TQ_UINT32 thisSweep ) -{ - if ( !rrs ) - return; - - TQDnsRR * rr; - rrs->first(); - while( (rr=rrs->current()) != 0 ) { - if ( !rr->deleteTime ) - rr->deleteTime = thisSweep; // will hit next time around - -#if defined(TQDNS_DEBUG) - qDebug( "TQDns::sweep: %s type %d expires %u %u - %s / %s", - rr->domain->name().latin1(), rr->t, - rr->expireTime, rr->deleteTime, - rr->target.latin1(), rr->address.toString().latin1()); -#endif - if ( rr->current == FALSE || - rr->t == TQDns::None || - rr->deleteTime <= thisSweep || - rr->expireTime <= thisSweep ) - rrs->remove(); - else - rrs->next(); - } - - if ( rrs->isEmpty() ) { - delete rrs; - rrs = 0; - } -} - - - - -// the itsy-bitsy little socket class I don't really need except for -// so I can subclass and reimplement the Q_SLOTS. - - -TQDnsSocket::TQDnsSocket( TQObject * parent, const char * name ) - : TQObject( parent, name ) -{ - // nothing -} - - -TQDnsSocket::~TQDnsSocket() -{ - // nothing -} - - -void TQDnsSocket::cleanCache() -{ - // nothing -} - - -void TQDnsSocket::retransmit() -{ - // nothing -} - - -void TQDnsSocket::answer() -{ - // nothing -} - - -/*! - \class TQDns tqdns.h - \brief The TQDns class provides asynchronous DNS lookups. -\if defined(commercial) - It is part of the TQt Enterprise Edition. -\endif - - \module network - \ingroup io - - Both Windows and Unix provide synchronous DNS lookups; Windows - provides some asynchronous support too. At the time of writing - neither operating system provides asynchronous support for - anything other than hostname-to-address mapping. - - TQDns rectifies this shortcoming, by providing asynchronous caching - lookups for the record types that we expect modern GUI - applications to need in the near future. - - The class is \e not straightforward to use (although it is much - simpler than the native APIs); TQSocket provides much easier to use - TCP connection facilities. The aim of TQDns is to provide a correct - and small API to the DNS and nothing more. (We use "correctness" - to mean that the DNS information is correctly cached, and - correctly timed out.) - - The API comprises a constructor, functions to set the DNS node - (the domain in DNS terminology) and record type (setLabel() and - setRecordType()), the corresponding get functions, an isWorking() - function to determine whether TQDns is working or reading, a - resultsReady() signal and query functions for the result. - - There is one query function for each RecordType, namely - addresses(), mailServers(), servers(), hostNames() and texts(). - There are also two generic query functions: canonicalName() - returns the name you'll presumably end up using (the exact meaning - of this depends on the record type) and qualifiedNames() returns a - list of the fully qualified names label() maps to. - - \sa TQSocket -*/ - -/*! - Constructs a DNS query object with invalid settings for both the - label and the search type. -*/ - -TQDns::TQDns() -{ - d = new TQDnsPrivate; - t = None; -} - - - - -/*! - Constructs a DNS query object that will return record type \a rr - information about \a label. - - The DNS lookup is started the next time the application enters the - event loop. When the result is found the signal resultsReady() is - emitted. - - \a rr defaults to \c A, IPv4 addresses. -*/ - -TQDns::TQDns( const TQString & label, RecordType rr ) -{ - d = new TQDnsPrivate; - t = rr; - setLabel( label ); - setStartQueryTimer(); // start query the next time we enter event loop -} - - - -/*! - Constructs a DNS query object that will return record type \a rr - information about host address \a address. The label is set to the - IN-ADDR.ARPA domain name. This is useful in combination with the - \c Ptr record type (e.g. if you want to look up a hostname for a - given address). - - The DNS lookup is started the next time the application enters the - event loop. When the result is found the signal resultsReady() is - emitted. - - \a rr defaults to \c Ptr, that maps addresses to hostnames. -*/ - -TQDns::TQDns( const TQHostAddress & address, RecordType rr ) -{ - d = new TQDnsPrivate; - t = rr; - setLabel( address ); - setStartQueryTimer(); // start query the next time we enter event loop -} - - - - -/*! - Destroys the DNS query object and frees its allocated resources. -*/ - -TQDns::~TQDns() -{ - if ( globalManager ) { - uint q = 0; - TQDnsManager * m = globalManager; - while( q < m->queries.size() ) { - TQDnsQuery * query=m->queries[q]; - if ( query && query->dns ) - (void)query->dns->take( (void*) this ); - q++; - } - - } - - delete d; - d = 0; -} - - - - -/*! - Sets this DNS query object to query for information about \a - label. - - This does not change the recordType(), but its isWorking() status - will probably change as a result. - - The DNS lookup is started the next time the application enters the - event loop. When the result is found the signal resultsReady() is - emitted. -*/ - -void TQDns::setLabel( const TQString & label ) -{ - l = label; - d->noNames = FALSE; - - // construct a list of qualified names - n.clear(); - if ( l.length() > 1 && l[(int)l.length()-1] == '.' ) { - n.append( l.left( l.length()-1 ).lower() ); - } else { - int i = l.length(); - int dots = 0; - const int maxDots = 2; - while( i && dots < maxDots ) { - if ( l[--i] == '.' ) - dots++; - } - if ( dots < maxDots ) { - (void)TQDnsManager::manager(); // create a TQDnsManager, if it is not already there - TQStrListIterator it( *domains ); - const char * dom; - while( (dom=it.current()) != 0 ) { - ++it; - n.append( l.lower() + "." + dom ); - } - } - n.append( l.lower() ); - } - -#if defined(TQ_DNS_SYNCHRONOUS) - if ( d->noEventLoop ) { - doSynchronousLookup(); - } else { - setStartQueryTimer(); // start query the next time we enter event loop - } -#else - setStartQueryTimer(); // start query the next time we enter event loop -#endif -#if defined(TQDNS_DEBUG) - qDebug( "TQDns::setLabel: %d address(es) for %s", n.count(), l.ascii() ); - int i = 0; - for( i = 0; i < (int)n.count(); i++ ) - qDebug( "TQDns::setLabel: %d: %s", i, n[i].ascii() ); -#endif -} - - -/*! - \overload - - Sets this DNS query object to query for information about the host - address \a address. The label is set to the IN-ADDR.ARPA domain - name. This is useful in combination with the \c Ptr record type - (e.g. if you want to look up a hostname for a given address). -*/ - -void TQDns::setLabel( const TQHostAddress & address ) -{ - setLabel( toInAddrArpaDomain( address ) ); -} - - -/*! - \fn TQStringList TQDns::qualifiedNames() const - - Returns a list of the fully qualified names label() maps to. - - Note that if you want to iterate over the list, you should iterate - over a copy, e.g. - \code - TQStringList list = myDns.qualifiedNames(); - TQStringList::Iterator it = list.begin(); - while( it != list.end() ) { - myProcessing( *it ); - ++it; - } - \endcode - -*/ - - -/*! - \fn TQString TQDns::label() const - - Returns the domain name for which this object returns information. - - \sa setLabel() -*/ - -/*! - \enum TQDns::RecordType - - This enum type defines the record types TQDns can handle. The DNS - provides many more; these are the ones we've judged to be in - current use, useful for GUI programs and important enough to - support right away: - - \value None No information. This exists only so that TQDns can - have a default. - - \value A IPv4 addresses. By far the most common type. - - \value Aaaa IPv6 addresses. So far mostly unused. - - \value Mx Mail eXchanger names. Used for mail delivery. - - \value Srv SeRVer names. Generic record type for finding - servers. So far mostly unused. - - \value Cname Canonical names. Maps from nicknames to the true - name (the canonical name) for a host. - - \value Ptr name PoinTeRs. Maps from IPv4 or IPv6 addresses to hostnames. - - \value Txt arbitrary TeXT for domains. - - We expect that some support for the - \link http://www.dns.net/dnsrd/rfc/rfc2535.html RFC-2535 \endlink - extensions will be added in future versions. -*/ - -/*! - Sets this object to query for record type \a rr records. - - The DNS lookup is started the next time the application enters the - event loop. When the result is found the signal resultsReady() is - emitted. - - \sa RecordType -*/ - -void TQDns::setRecordType( RecordType rr ) -{ - t = rr; - d->noNames = FALSE; - setStartQueryTimer(); // start query the next time we enter event loop -} - -/*! - \internal - - Private slot for starting the query. -*/ -void TQDns::startQuery() -{ - // isWorking() starts the query (if necessary) - if ( !isWorking() ) - emit resultsReady(); -} - -/*! - The three functions TQDns::TQDns(TQString, RecordType), - TQDns::setLabel() and TQDns::setRecordType() may start a DNS lookup. - This function handles setting up the single shot timer. -*/ -void TQDns::setStartQueryTimer() -{ -#if defined(TQ_DNS_SYNCHRONOUS) - if ( !d->queryTimer && !d->noEventLoop ) -#else - if ( !d->queryTimer ) -#endif - { - // start the query the next time we enter event loop - d->queryTimer = new TQTimer( this ); - connect( d->queryTimer, TQT_SIGNAL(timeout()), - this, TQT_SLOT(startQuery()) ); - d->queryTimer->start( 0, TRUE ); - } -} - -/* - Transforms the host address \a address to the IN-ADDR.ARPA domain - name. Returns something indeterminate if you're sloppy or - naughty. This function has an IPv4-specific name, but works for - IPv6 too. -*/ -TQString TQDns::toInAddrArpaDomain( const TQHostAddress &address ) -{ - TQString s; - if ( address.isNull() ) { - // if the address isn't valid, neither of the other two make - // cases make sense. better to just return. - } else if ( address.isIp4Addr() ) { - TQ_UINT32 i = address.ip4Addr(); - s.sprintf( "%d.%d.%d.%d.IN-ADDR.ARPA", - i & 0xff, (i >> 8) & 0xff, (i>>16) & 0xff, (i>>24) & 0xff ); - } else { - // RFC 3152. (1886 is deprecated, and clients no longer need to - // support it, in practice). - TQ_IPV6ADDR i = address.toIPv6Address(); - s = "ip6.arpa"; - uint b = 0; - while( b < 16 ) { - s = TQString::number( i.c[b]%16, 16 ) + "." + - TQString::number( i.c[b]/16, 16 ) + "." + s; - b++; - } - } - return s; -} - - -/*! - \fn TQDns::RecordType TQDns::recordType() const - - Returns the record type of this DNS query object. - - \sa setRecordType() RecordType -*/ - -/*! - \fn void TQDns::resultsReady() - - This signal is emitted when results are available for one of the - qualifiedNames(). -*/ - -/*! - Returns TRUE if TQDns is doing a lookup for this object (i.e. if it - does not already have the necessary information); otherwise - returns FALSE. - - TQDns emits the resultsReady() signal when the status changes to FALSE. -*/ - -bool TQDns::isWorking() const -{ -#if defined(TQDNS_DEBUG) - qDebug( "TQDns::isWorking (%s, %d)", l.ascii(), t ); -#endif - if ( t == None ) - return FALSE; - -#if defined(TQ_DNS_SYNCHRONOUS) - if ( d->noEventLoop ) - return TRUE; -#endif - - TQPtrList * ll = TQDnsDomain::cached( this ); - TQ_LONG queries = n.count(); - while( ll->current() != 0 ) { - if ( ll->current()->nxdomain ) { - queries--; - } else { - delete ll; - return FALSE; - } - ll->next(); - } - delete ll; - - if ( queries <= 0 ) - return FALSE; - if ( d->noNames ) - return FALSE; - return TRUE; -} - - -/*! - Returns a list of the addresses for this name if this TQDns object - has a recordType() of \c TQDns::A or \c TQDns::Aaaa and the answer - is available; otherwise returns an empty list. - - As a special case, if label() is a valid numeric IP address, this - function returns that address. - - Note that if you want to iterate over the list, you should iterate - over a copy, e.g. - \code - TQValueList list = myDns.addresses(); - TQValueList::Iterator it = list.begin(); - while( it != list.end() ) { - myProcessing( *it ); - ++it; - } - \endcode - -*/ - -TQValueList TQDns::addresses() const -{ -#if defined(TQDNS_DEBUG) - qDebug( "TQDns::addresses (%s)", l.ascii() ); -#endif - TQValueList result; - if ( t != A && t != Aaaa ) - return result; - - TQPtrList * cached = TQDnsDomain::cached( this ); - - TQDnsRR * rr; - while( (rr=cached->current()) != 0 ) { - if ( rr->current && !rr->nxdomain ) - result.append( rr->address ); - cached->next(); - } - delete cached; - return result; -} - - -/*! - \class TQDns::MailServer - \brief The TQDns::MailServer class is described in TQDns::mailServers(). -\if defined(commercial) - It is part of the TQt Enterprise Edition. -\endif - - \ingroup io - - \internal -*/ - -/*! - Returns a list of mail servers if the record type is \c Mx. The - class \c TQDns::MailServer contains the following public variables: - \list - \i TQString TQDns::MailServer::name - \i TQ_UINT16 TQDns::MailServer::priority - \endlist - - Note that if you want to iterate over the list, you should iterate - over a copy, e.g. - \code - TQValueList list = myDns.mailServers(); - TQValueList::Iterator it = list.begin(); - while( it != list.end() ) { - myProcessing( *it ); - ++it; - } - \endcode - -*/ -TQValueList TQDns::mailServers() const -{ -#if defined(TQDNS_DEBUG) - qDebug( "TQDns::mailServers (%s)", l.ascii() ); -#endif - TQValueList result; - if ( t != Mx ) - return result; - - TQPtrList * cached = TQDnsDomain::cached( this ); - - TQDnsRR * rr; - while( (rr=cached->current()) != 0 ) { - if ( rr->current && !rr->nxdomain ) { - MailServer ms( rr->target, rr->priority ); - result.append( ms ); - } - cached->next(); - } - delete cached; - return result; -} - - -/*! - \class TQDns::Server - \brief The TQDns::Server class is described in TQDns::servers(). -\if defined(commercial) - It is part of the TQt Enterprise Edition. -\endif - - \ingroup io - - \internal -*/ - -/*! - Returns a list of servers if the record type is \c Srv. The class - \c TQDns::Server contains the following public variables: - \list - \i TQString TQDns::Server::name - \i TQ_UINT16 TQDns::Server::priority - \i TQ_UINT16 TQDns::Server::weight - \i TQ_UINT16 TQDns::Server::port - \endlist - - Note that if you want to iterate over the list, you should iterate - over a copy, e.g. - \code - TQValueList list = myDns.servers(); - TQValueList::Iterator it = list.begin(); - while( it != list.end() ) { - myProcessing( *it ); - ++it; - } - \endcode -*/ -TQValueList TQDns::servers() const -{ -#if defined(TQDNS_DEBUG) - qDebug( "TQDns::servers (%s)", l.ascii() ); -#endif - TQValueList result; - if ( t != Srv ) - return result; - - TQPtrList * cached = TQDnsDomain::cached( this ); - - TQDnsRR * rr; - while( (rr=cached->current()) != 0 ) { - if ( rr->current && !rr->nxdomain ) { - Server s( rr->target, rr->priority, rr->weight, rr->port ); - result.append( s ); - } - cached->next(); - } - delete cached; - return result; -} - - -/*! - Returns a list of host names if the record type is \c Ptr. - - Note that if you want to iterate over the list, you should iterate - over a copy, e.g. - \code - TQStringList list = myDns.hostNames(); - TQStringList::Iterator it = list.begin(); - while( it != list.end() ) { - myProcessing( *it ); - ++it; - } - \endcode - -*/ -TQStringList TQDns::hostNames() const -{ -#if defined(TQDNS_DEBUG) - qDebug( "TQDns::hostNames (%s)", l.ascii() ); -#endif - TQStringList result; - if ( t != Ptr ) - return result; - - TQPtrList * cached = TQDnsDomain::cached( this ); - - TQDnsRR * rr; - while( (rr=cached->current()) != 0 ) { - if ( rr->current && !rr->nxdomain ) { - TQString str( rr->target ); - result.append( str ); - } - cached->next(); - } - delete cached; - return result; -} - - -/*! - Returns a list of texts if the record type is \c Txt. - - Note that if you want to iterate over the list, you should iterate - over a copy, e.g. - \code - TQStringList list = myDns.texts(); - TQStringList::Iterator it = list.begin(); - while( it != list.end() ) { - myProcessing( *it ); - ++it; - } - \endcode -*/ -TQStringList TQDns::texts() const -{ -#if defined(TQDNS_DEBUG) - qDebug( "TQDns::texts (%s)", l.ascii() ); -#endif - TQStringList result; - if ( t != Txt ) - return result; - - TQPtrList * cached = TQDnsDomain::cached( this ); - - TQDnsRR * rr; - while( (rr=cached->current()) != 0 ) { - if ( rr->current && !rr->nxdomain ) { - TQString str( rr->text ); - result.append( str ); - } - cached->next(); - } - delete cached; - return result; -} - - -/*! - Returns the canonical name for this DNS node. (This works - regardless of what recordType() is set to.) - - If the canonical name isn't known, this function returns a null - string. - - The canonical name of a DNS node is its full name, or the full - name of the target of its CNAME. For example, if l.trolltech.com - is a CNAME to lillian.troll.no, and the search path for TQDns is - "trolltech.com", then the canonical name for all of "lillian", - "l", "lillian.troll.no." and "l.trolltech.com" is - "lillian.troll.no.". -*/ - -TQString TQDns::canonicalName() const -{ - // the cname should work regardless of the recordType(), so set the record - // type temporarily to cname when you look at the cache - TQDns *that = (TQDns*) this; // mutable function - RecordType oldType = t; - that->t = Cname; - TQPtrList * cached = TQDnsDomain::cached( that ); - that->t = oldType; - - TQDnsRR * rr; - while( (rr=cached->current()) != 0 ) { - if ( rr->current && !rr->nxdomain && rr->domain ) { - delete cached; - return rr->target; - } - cached->next(); - } - delete cached; - return TQString::null; -} - -#if defined(TQ_DNS_SYNCHRONOUS) -/*! \reimp -*/ -void TQDns::connectNotify( const char *signal ) -{ - if ( d->noEventLoop && qstrcmp(signal,TQT_SIGNAL(resultsReady()) )==0 ) { - doSynchronousLookup(); - } -} -#endif - -#if defined(TQ_OS_WIN32) || defined(TQ_OS_CYGWIN) - -#if defined(TQ_DNS_SYNCHRONOUS) -void TQDns::doSynchronousLookup() -{ - // ### not implemented yet -} -#endif - -// the following typedefs are needed for GetNetworkParams() API call -#ifndef IP_TYPES_INCLUDED -#define MAX_HOSTNAME_LEN 128 -#define MAX_DOMAIN_NAME_LEN 128 -#define MAX_SCOPE_ID_LEN 256 -typedef struct { - char String[4 * 4]; -} IP_ADDRESS_STRING, *PIP_ADDRESS_STRING, IP_MASK_STRING, *PIP_MASK_STRING; -typedef struct _IP_ADDR_STRING { - struct _IP_ADDR_STRING* Next; - IP_ADDRESS_STRING IpAddress; - IP_MASK_STRING IpMask; - DWORD Context; -} IP_ADDR_STRING, *PIP_ADDR_STRING; -typedef struct { - char HostName[MAX_HOSTNAME_LEN + 4] ; - char DomainName[MAX_DOMAIN_NAME_LEN + 4]; - PIP_ADDR_STRING CurrentDnsServer; - IP_ADDR_STRING DnsServerList; - UINT NodeType; - char ScopeId[MAX_SCOPE_ID_LEN + 4]; - UINT EnableRouting; - UINT EnableProxy; - UINT EnableDns; -} FIXED_INFO, *PFIXED_INFO; -#endif -typedef DWORD (WINAPI *GNP)( PFIXED_INFO, PULONG ); - -// ### FIXME: this code is duplicated in qfiledialog.cpp -static TQString getWindowsRegString( HKEY key, const TQString &subKey ) -{ - TQString s; - TQT_WA( { - char buf[1024]; - DWORD bsz = sizeof(buf); - int r = RegQueryValueEx( key, (TCHAR*)subKey.ucs2(), 0, 0, (LPBYTE)buf, &bsz ); - if ( r == ERROR_SUCCESS ) { - s = TQString::fromUcs2( (unsigned short *)buf ); - } else if ( r == ERROR_MORE_DATA ) { - char *ptr = new char[bsz+1]; - r = RegQueryValueEx( key, (TCHAR*)subKey.ucs2(), 0, 0, (LPBYTE)ptr, &bsz ); - if ( r == ERROR_SUCCESS ) - s = ptr; - delete [] ptr; - } - } , { - char buf[512]; - DWORD bsz = sizeof(buf); - int r = RegQueryValueExA( key, subKey.local8Bit(), 0, 0, (LPBYTE)buf, &bsz ); - if ( r == ERROR_SUCCESS ) { - s = buf; - } else if ( r == ERROR_MORE_DATA ) { - char *ptr = new char[bsz+1]; - r = RegQueryValueExA( key, subKey.local8Bit(), 0, 0, (LPBYTE)ptr, &bsz ); - if ( r == ERROR_SUCCESS ) - s = ptr; - delete [] ptr; - } - } ); - return s; -} - -static bool getDnsParamsFromRegistry( const TQString &path, - TQString *domainName, TQString *nameServer, TQString *searchList ) -{ - HKEY k; - int r; - TQT_WA( { - r = RegOpenKeyEx( HKEY_LOCAL_MACHINE, - (TCHAR*)path.ucs2(), - 0, KEY_READ, &k ); - } , { - r = RegOpenKeyExA( HKEY_LOCAL_MACHINE, - path, - 0, KEY_READ, &k ); - } ); - - if ( r == ERROR_SUCCESS ) { - *domainName = getWindowsRegString( k, "DhcpDomain" ); - if ( domainName->isEmpty() ) - *domainName = getWindowsRegString( k, "Domain" ); - - *nameServer = getWindowsRegString( k, "DhcpNameServer" ); - if ( nameServer->isEmpty() ) - *nameServer = getWindowsRegString( k, "NameServer" ); - - *searchList = getWindowsRegString( k, "SearchList" ); - } - RegCloseKey( k ); - return r == ERROR_SUCCESS; -} - -void TQDns::doResInit() -{ - char separator = 0; - - if ( ns ) - delete ns; - ns = new TQPtrList; - ns->setAutoDelete( TRUE ); - domains = new TQStrList( TRUE ); - domains->setAutoDelete( TRUE ); - - TQString domainName, nameServer, searchList; - - bool gotNetworkParams = FALSE; - // try the API call GetNetworkParams() first and use registry lookup only - // as a fallback -#ifdef TQ_OS_TEMP - HINSTANCE hinstLib = LoadLibraryW( L"iphlpapi" ); -#else - HINSTANCE hinstLib = LoadLibraryA( "iphlpapi" ); -#endif - if ( hinstLib != 0 ) { -#ifdef TQ_OS_TEMP - GNP getNetworkParams = (GNP) GetProcAddressW( hinstLib, L"GetNetworkParams" ); -#else - GNP getNetworkParams = (GNP) GetProcAddress( hinstLib, "GetNetworkParams" ); -#endif - if ( getNetworkParams != 0 ) { - ULONG l = 0; - DWORD res; - res = getNetworkParams( 0, &l ); - if ( res == ERROR_BUFFER_OVERFLOW ) { - FIXED_INFO *finfo = (FIXED_INFO*)new char[l]; - res = getNetworkParams( finfo, &l ); - if ( res == ERROR_SUCCESS ) { - domainName = finfo->DomainName; - nameServer = ""; - IP_ADDR_STRING *dnsServer = &finfo->DnsServerList; - while ( dnsServer != 0 ) { - nameServer += dnsServer->IpAddress.String; - dnsServer = dnsServer->Next; - if ( dnsServer != 0 ) - nameServer += " "; - } - searchList = ""; - separator = ' '; - gotNetworkParams = TRUE; - } - delete[] finfo; - } - } - FreeLibrary( hinstLib ); - } - if ( !gotNetworkParams ) { - if ( getDnsParamsFromRegistry( - TQString( "System\\CurrentControlSet\\Services\\Tcpip\\Parameters" ), - &domainName, &nameServer, &searchList )) { - // for NT - separator = ' '; - } else if ( getDnsParamsFromRegistry( - TQString( "System\\CurrentControlSet\\Services\\VxD\\MSTCP" ), - &domainName, &nameServer, &searchList )) { - // for 95/98 - separator = ','; - } else { - // Could not access the TCP/IP parameters - domainName = ""; - nameServer = "127.0.0.1"; - searchList = ""; - separator = ' '; - } - } - - nameServer = nameServer.simplifyWhiteSpace(); - int first, last; - if ( !nameServer.isEmpty() ) { - first = 0; - do { - last = nameServer.find( separator, first ); - if ( last < 0 ) - last = nameServer.length(); - TQDns tmp( nameServer.mid( first, last-first ), TQDns::A ); - TQValueList address = tmp.addresses(); - TQ_LONG i = address.count(); - while( i ) - ns->append( new TQHostAddress(address[--i]) ); - first = last+1; - } while( first < (int)nameServer.length() ); - } - - searchList = searchList + " " + domainName; - searchList = searchList.simplifyWhiteSpace().lower(); - first = 0; - do { - last = searchList.find( separator, first ); - if ( last < 0 ) - last = searchList.length(); - domains->append( qstrdup( searchList.mid( first, last-first ) ) ); - first = last+1; - } while( first < (int)searchList.length() ); -} - -#elif defined(TQ_OS_UNIX) - -#if defined(TQ_DNS_SYNCHRONOUS) -void TQDns::doSynchronousLookup() -{ - if ( t!=None && !l.isEmpty() ) { - TQValueListIterator it = n.begin(); - TQValueListIterator end = n.end(); - int type; - switch( t ) { - case TQDns::A: - type = 1; - break; - case TQDns::Aaaa: - type = 28; - break; - case TQDns::Mx: - type = 15; - break; - case TQDns::Srv: - type = 33; - break; - case TQDns::Cname: - type = 5; - break; - case TQDns::Ptr: - type = 12; - break; - case TQDns::Txt: - type = 16; - break; - default: - type = (char)255; // any - break; - } - while( it != end ) { - TQString s = *it; - it++; - TQByteArray ba( 512 ); - int len = res_search( s.latin1(), 1, type, (uchar*)ba.data(), ba.size() ); - if ( len > 0 ) { - ba.resize( len ); - - TQDnsQuery * query = new TQDnsQuery; - query->started = now(); - query->id = ++::id; - query->t = t; - query->l = s; - TQDnsAnswer a( ba, query ); - a.parse(); - } else if ( len == -1 ) { - // res_search error - } - } - emit resultsReady(); - } -} -#endif - -#if defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 3))) -#define TQ_MODERN_RES_API -#else -#endif - -void TQDns::doResInit() -{ - if ( ns ) - return; - ns = new TQPtrList; - ns->setAutoDelete( TRUE ); - domains = new TQStrList( TRUE ); - domains->setAutoDelete( TRUE ); - - // read resolv.conf manually. - TQFile resolvConf("/etc/resolv.conf"); - if (resolvConf.open(IO_ReadOnly)) { - TQTextStream stream( &resolvConf ); - TQString line; - - while ( !stream.atEnd() ) { - line = stream.readLine(); - TQStringList list = TQStringList::split( " ", line ); - if ( line.startsWith( "#" ) || list.count() < 2 ) - continue; - const TQString type = list[0].lower(); - - if ( type == "nameserver" ) { - TQHostAddress *address = new TQHostAddress(); - if ( address->setAddress( TQString(list[1]) ) ) { - // only add ipv6 addresses from resolv.conf if - // this host supports ipv6. - if ( address->isIPv4Address() || ipv6support ) - ns->append( address ); - else - delete address; - } else { - delete address; - } - } else if ( type == "search" ) { - TQStringList srch = TQStringList::split( " ", list[1] ); - for ( TQStringList::Iterator i = srch.begin(); i != srch.end(); ++i ) - domains->append( (*i).lower() ); - - } else if ( type == "domain" ) { - domains->append( list[1].lower() ); - } - } - } - - if (ns->isEmpty()) { -#if defined(TQ_MODERN_RES_API) - struct __res_state res; - res_ninit( &res ); - int i; - // find the name servers to use - for( i=0; i < MAXNS && i < res.nscount; i++ ) - ns->append( new TQHostAddress( ntohl( res.nsaddr_list[i].sin_addr.s_addr ) ) ); -# if defined(MAXDFLSRCH) - for( i=0; i < MAXDFLSRCH; i++ ) { - if ( res.dnsrch[i] && *(res.dnsrch[i]) ) - domains->append( TQString::tqfromLatin1( res.dnsrch[i] ).lower() ); - else - break; - } -# endif - if ( *res.defdname ) - domains->append( TQString::tqfromLatin1( res.defdname ).lower() ); -#else - qdns_res_init(); - int i; - // find the name servers to use - for( i=0; i < MAXNS && i < _res.nscount; i++ ) - ns->append( new TQHostAddress( ntohl( _res.nsaddr_list[i].sin_addr.s_addr ) ) ); -# if defined(MAXDFLSRCH) - for( i=0; i < MAXDFLSRCH; i++ ) { - if ( _res.dnsrch[i] && *(_res.dnsrch[i]) ) - domains->append( TQString::tqfromLatin1( _res.dnsrch[i] ).lower() ); - else - break; - } -# endif - if ( *_res.defdname ) - domains->append( TQString::tqfromLatin1( _res.defdname ).lower() ); -#endif - - // the code above adds "0.0.0.0" as a name server at the slightest - // hint of trouble. so remove those again. - ns->first(); - while( ns->current() ) { - if ( ns->current()->isNull() ) - delete ns->take(); - else - ns->next(); - } - } - - TQFile hosts( TQString::tqfromLatin1( "/etc/hosts" ) ); - if ( hosts.open( IO_ReadOnly ) ) { - // read the /etc/hosts file, creating long-life A and PTR RRs - // for the things we find. - TQTextStream i( &hosts ); - TQString line; - while( !i.atEnd() ) { - line = i.readLine().simplifyWhiteSpace().lower(); - uint n = 0; - while( n < line.length() && line[(int)n] != '#' ) - n++; - line.truncate( n ); - n = 0; - while( n < line.length() && !line[(int)n].isSpace() ) - n++; - TQString ip = line.left( n ); - TQHostAddress a; - a.setAddress( ip ); - if ( ( a.isIPv4Address() || a.isIPv6Address() ) && !a.isNull() ) { - bool first = TRUE; - line = line.mid( n+1 ); - n = 0; - while( n < line.length() && !line[(int)n].isSpace() ) - n++; - TQString hostname = line.left( n ); - // ### in case of bad syntax, hostname is invalid. do we care? - if ( n ) { - TQDnsRR * rr = new TQDnsRR( hostname ); - if ( a.isIPv4Address() ) - rr->t = TQDns::A; - else - rr->t = TQDns::Aaaa; - rr->address = a; - rr->deleteTime = UINT_MAX; - rr->expireTime = UINT_MAX; - rr->current = TRUE; - if ( first ) { - first = FALSE; - TQDnsRR * ptr = new TQDnsRR( TQDns::toInAddrArpaDomain( a ) ); - ptr->t = TQDns::Ptr; - ptr->target = hostname; - ptr->deleteTime = UINT_MAX; - ptr->expireTime = UINT_MAX; - ptr->current = TRUE; - } - } - } - } - } -} - -#endif - -#endif // TQT_NO_DNS - -#endif // USE_QT4 \ No newline at end of file diff --git a/tqtinterface/qt4/src/network/tqdns.h b/tqtinterface/qt4/src/network/tqdns.h deleted file mode 100644 index 23c84ee..0000000 --- a/tqtinterface/qt4/src/network/tqdns.h +++ /dev/null @@ -1,382 +0,0 @@ -#include "tqtglobaldefines.h" - -#ifdef USE_QT4 - -/**************************************************************************** -** -** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the Qt3Support module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial Usage -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Nokia. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TQDNS_H -#define TQDNS_H - -#include -#include -#include -#include -#include - -#include "tqtimer.h" -#include "tqobject.h" -#include "tqhostaddress.h" -#include "tqsocketnotifier.h" - -#define TQLatin1String TQString -#define TQLatin1Char TQChar - -typedef qint8 Q_INT8; -typedef quint8 Q_UINT8; -typedef qint16 Q_INT16; -typedef quint16 Q_UINT16; -typedef qint32 Q_INT32; -typedef quint32 Q_UINT32; -typedef qint64 Q_INT64; -typedef quint64 Q_UINT64; -typedef qint64 Q_LLONG; -typedef quint64 Q_ULLONG; -#if defined(Q_OS_WIN64) -typedef __int64 Q_LONG; /* word up to 64 bit signed */ -typedef unsigned __int64 Q_ULONG; /* word up to 64 bit unsigned */ -#else -typedef long Q_LONG; /* word up to 64 bit signed */ -typedef unsigned long Q_ULONG; /* word up to 64 bit unsigned */ -#endif - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Qt3Support) - -#ifndef QT_NO_DNS - -//#define Q_DNS_SYNCHRONOUS - -class TQDnsPrivate; - -class Q_COMPAT_EXPORT TQDns: public TQObject { - Q_OBJECT - TQ_OBJECT -public: - enum RecordType { - None, - A, Aaaa, - Mx, Srv, - Cname, - Ptr, - Txt - }; - - TQDns(); - TQDns( const TQString & label, RecordType rr = A ); - TQDns( const TQHostAddress & address, RecordType rr = Ptr ); - virtual ~TQDns(); - - // to set/change the query - virtual void setLabel( const TQString & label ); - virtual void setLabel( const TQHostAddress & address ); - TQString label() const { return l; } - - virtual void setRecordType( RecordType rr = A ); - RecordType recordType() const { return t; } - - // whether something is happening behind the scenes - bool isWorking() const; - - // to query for replies - TQValueList addresses() const; - - class Q_COMPAT_EXPORT MailServer { - public: - MailServer( const TQString & n=TQString(), Q_UINT16 p=0 ) - :name(n), priority(p) {} - TQString name; - Q_UINT16 priority; - Q_DUMMY_COMPARISON_OPERATOR(MailServer) - }; - TQValueList mailServers() const; - - class Q_COMPAT_EXPORT Server { - public: - Server(const TQString & n=TQString(), Q_UINT16 p=0, Q_UINT16 w=0, Q_UINT16 po=0 ) - : name(n), priority(p), weight(w), port(po) {} - TQString name; - Q_UINT16 priority; - Q_UINT16 weight; - Q_UINT16 port; - Q_DUMMY_COMPARISON_OPERATOR(Server) - }; - TQValueList servers() const; - - TQStringList hostNames() const; - - TQStringList texts() const; - - TQString canonicalName() const; // ### real-world but uncommon: TQStringList - - TQStringList qualifiedNames() const { return n; } - -#if defined(Q_DNS_SYNCHRONOUS) -protected: - void connectNotify( const char *signal ); -#endif - -Q_SIGNALS: - void resultsReady(); - -private Q_SLOTS: - void startQuery(); - -private: - static void doResInit(); - void setStartQueryTimer(); - static TQString toInAddrArpaDomain( const TQHostAddress &address ); -#if defined(Q_DNS_SYNCHRONOUS) - void doSynchronousLookup(); -#endif - - TQString l; - TQStringList n; - RecordType t; - TQDnsPrivate * d; - - friend class TQDnsAnswer; - friend class TQDnsManager; -}; - - -// TQDnsSocket are sockets that are used for DNS lookup - -class TQDnsSocket: public TQObject { - Q_OBJECT - // note: Private not public. This class contains NO public API. -protected: - TQDnsSocket( TQT_BASE_OBJECT_NAME *, const char * ); - virtual ~TQDnsSocket(); - -private Q_SLOTS: - virtual void cleanCache(); - virtual void retransmit(); - virtual void answer(); -}; - -#endif // QT_NO_DNS - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // TQDNS_H - -#else // USE_QT4 - -/**************************************************************************** -** -** Definition of TQDns class. -** -** Created : 991122 -** -** Copyright (C) 1999-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the network module of the TQt 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 TQt 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.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** 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. -** -**********************************************************************/ - -#ifndef TQDNS_H -#define TQDNS_H - -#ifndef TQT_H -#include "tqobject.h" -#include "tqhostaddress.h" -#include "tqsocketnotifier.h" -#include "tqstringlist.h" -#endif // TQT_H - -#if !defined( TQT_MODULE_NETWORK ) || defined( TQT_LICENSE_PROFESSIONAL ) || defined( TQT_INTERNAL_NETWORK ) -#define TQM_EXPORT_DNS -#else -#define TQM_EXPORT_DNS TQ_EXPORT -#endif - -#ifndef TQT_NO_DNS - -//#define TQ_DNS_SYNCHRONOUS - -class TQDnsPrivate; - -class TQM_EXPORT_DNS TQDns: public TQObject { - Q_OBJECT - TQ_OBJECT -public: - enum RecordType { - None, - A, Aaaa, - Mx, Srv, - Cname, - Ptr, - Txt - }; - - TQDns(); - TQDns( const TQString & label, RecordType rr = A ); - TQDns( const TQHostAddress & address, RecordType rr = Ptr ); - virtual ~TQDns(); - - // to set/change the query - virtual void setLabel( const TQString & label ); - virtual void setLabel( const TQHostAddress & address ); - TQString label() const { return l; } - - virtual void setRecordType( RecordType rr = A ); - RecordType recordType() const { return t; } - - // whether something is happening behind the scenes - bool isWorking() const; - - // to query for replies - TQValueList addresses() const; - - class TQM_EXPORT_DNS MailServer { - public: - MailServer( const TQString & n=TQString::null, TQ_UINT16 p=0 ) - :name(n), priority(p) {} - TQString name; - TQ_UINT16 priority; - TQ_DUMMY_COMPARISON_OPERATOR(MailServer) - }; - TQValueList mailServers() const; - - class TQM_EXPORT_DNS Server { - public: - Server(const TQString & n=TQString::null, TQ_UINT16 p=0, TQ_UINT16 w=0, TQ_UINT16 po=0 ) - : name(n), priority(p), weight(w), port(po) {} - TQString name; - TQ_UINT16 priority; - TQ_UINT16 weight; - TQ_UINT16 port; - TQ_DUMMY_COMPARISON_OPERATOR(Server) - }; - TQValueList servers() const; - - TQStringList hostNames() const; - - TQStringList texts() const; - - TQString canonicalName() const; // ### real-world but uncommon: TQStringList - - TQStringList qualifiedNames() const { return n; } - -#if defined(TQ_DNS_SYNCHRONOUS) -protected: - void connectNotify( const char *signal ); -#endif - -Q_SIGNALS: - void resultsReady(); - -private Q_SLOTS: - void startQuery(); - -private: - static void doResInit(); - void setStartQueryTimer(); - static TQString toInAddrArpaDomain( const TQHostAddress &address ); -#if defined(TQ_DNS_SYNCHRONOUS) - void doSynchronousLookup(); -#endif - - TQString l; - TQStringList n; - RecordType t; - TQDnsPrivate * d; - - friend class TQDnsAnswer; - friend class TQDnsManager; -}; - - -// TQDnsSocket are sockets that are used for DNS lookup - -class TQDnsSocket: public TQObject { - Q_OBJECT - TQ_OBJECT - // note: Private not public. This class contains NO public API. -protected: - TQDnsSocket( TQObject *, const char * ); - virtual ~TQDnsSocket(); - -private Q_SLOTS: - virtual void cleanCache(); - virtual void retransmit(); - virtual void answer(); -}; - -#endif // TQT_NO_DNS - -#endif // TQDNS_H - -#endif // USE_QT4 \ No newline at end of file diff --git a/tqtinterface/qt4/src/network/tqftp.cpp b/tqtinterface/qt4/src/network/tqftp.cpp deleted file mode 100644 index 78f1ce8..0000000 --- a/tqtinterface/qt4/src/network/tqftp.cpp +++ /dev/null @@ -1,2421 +0,0 @@ -/**************************************************************************** -** -** Implementation of TQFtp class. -** -** Created : 970521 -** -** Copyright (C) 1997-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the network module of the TQt 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 TQt 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.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** 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 "tqftp.h" - -#ifndef TQT_NO_NETWORKPROTOCOL_FTP - -#include "tqsocket.h" -#include "tqsocketdevice.h" -#include "tqurlinfo.h" -#include "tqurloperator.h" -#include "tqstringlist.h" -#include "tqregexp.h" -#include "tqtimer.h" -#include "tqfileinfo.h" -#include "tqptrdict.h" // binary compatibility - -#ifndef TQT_NO_TEXTCODEC -#include "tqtextcodec.h" -#endif - -//#define TQFTPPI_DEBUG -//#define TQFTPDTP_DEBUG - - -class TQFtpPI; - -class TQFtpDTP : public TQObject -{ - Q_OBJECT - TQ_OBJECT - -public: - enum ConnectState { - CsHostFound, - CsConnected, - CsClosed, - CsHostNotFound, - CsConnectionRefused - }; - - TQFtpDTP( TQFtpPI *p, TQObject *parent=0, const char *name=0 ); - - void setData( TQByteArray * ); - void setDevice( TQIODevice * ); - void writeData(); - - void setBytesTotal( int bytes ) - { - bytesTotal = bytes; - bytesDone = 0; - emit dataTransferProgress( bytesDone, bytesTotal ); - } - - bool hasError() const; - TQString errorMessage() const; - void clearError(); - - void connectToHost( const TQString & host, TQ_UINT16 port ) - { socket.connectToHost( host, port ); } - - TQSocket::State socketState() const - { return socket.state(); } - - TQ_ULONG bytesAvailable() const - { return socket.bytesAvailable(); } - - TQ_LONG readBlock( char *data, TQ_ULONG maxlen ) - { - TQ_LONG read = socket.readBlock( data, maxlen ); - bytesDone += read; - return read; - } - - TQByteArray readAll() - { - TQByteArray tmp = TQT_TQBYTEARRAY_OBJECT(socket.readAll()); - bytesDone += tmp.size(); - return tmp; - } - - void abortConnection(); - - static bool parseDir( const TQString &buffer, const TQString &userName, TQUrlInfo *info ); - -Q_SIGNALS: - void listInfo( const TQUrlInfo& ); - void readyRead(); - void dataTransferProgress( int, int ); - - void connectState( int ); - -private Q_SLOTS: - void socketConnected(); - void socketReadyRead(); - void socketError( int ); - void socketConnectionClosed(); - void socketBytesWritten( int ); - -private: - void clearData() - { - is_ba = FALSE; - data.dev = 0; - } - - TQSocket socket; - TQFtpPI *pi; - TQString err; - int bytesDone; - int bytesTotal; - bool callWriteData; - - // If is_ba is TRUE, ba is used; ba is never 0. - // Otherwise dev is used; dev can be 0 or not. - union { - TQByteArray *ba; - TQIODevice *dev; - } data; - bool is_ba; -}; - -class TQFtpPI : public TQObject -{ - Q_OBJECT - TQ_OBJECT - -public: - TQFtpPI( TQObject *parent = 0 ); - - void connectToHost( const TQString &host, TQ_UINT16 port ); - - bool sendCommands( const TQStringList &cmds ); - bool sendCommand( const TQString &cmd ) - { return sendCommands( TQStringList( cmd ) ); } - - void clearPendingCommands(); - void abort(); - - TQString currentCommand() const - { return currentCmd; } - - bool rawCommand; - - TQFtpDTP dtp; // the PI has a DTP which is not the design of RFC 959, but it - // makes the design simpler this way -Q_SIGNALS: - void connectState( int ); - void finished( const TQString& ); - void error( int, const TQString& ); - void rawFtpReply( int, const TQString& ); - -private Q_SLOTS: - void hostFound(); - void connected(); - void connectionClosed(); - void delayedCloseFinished(); - void readyRead(); - void error( int ); - - void dtpConnectState( int ); - -private: - // the states are modelled after the generalized state diagram of RFC 959, - // page 58 - enum State { - Begin, - Idle, - Waiting, - Success, - Failure - }; - - enum AbortState { - None, - AbortStarted, - WaitForAbortToFinish - }; - - bool processReply(); - bool startNextCmd(); - - TQSocket commandSocket; - TQString replyText; - char replyCode[3]; - State state; - AbortState abortState; - TQStringList pendingCommands; - TQString currentCmd; - - bool waitForDtpToConnect; - bool waitForDtpToClose; -}; - -/********************************************************************** - * - * TQFtpCommand implemenatation - * - *********************************************************************/ -class TQFtpCommand -{ -public: - TQFtpCommand( TQFtp::Command cmd, TQStringList raw ); - TQFtpCommand( TQFtp::Command cmd, TQStringList raw, const TQByteArray &ba ); - TQFtpCommand( TQFtp::Command cmd, TQStringList raw, TQIODevice *dev ); - ~TQFtpCommand(); - - int id; - TQFtp::Command command; - TQStringList rawCmds; - - // If is_ba is TRUE, ba is used; ba is never 0. - // Otherwise dev is used; dev can be 0 or not. - union { - TQByteArray *ba; - TQIODevice *dev; - } data; - bool is_ba; - - static int idCounter; -}; - -int TQFtpCommand::idCounter = 0; - -TQFtpCommand::TQFtpCommand( TQFtp::Command cmd, TQStringList raw ) - : command(cmd), rawCmds(raw), is_ba(FALSE) -{ - id = ++idCounter; - data.dev = 0; -} - -TQFtpCommand::TQFtpCommand( TQFtp::Command cmd, TQStringList raw, const TQByteArray &ba ) - : command(cmd), rawCmds(raw), is_ba(TRUE) -{ - id = ++idCounter; - data.ba = new TQByteArray( ba ); -} - -TQFtpCommand::TQFtpCommand( TQFtp::Command cmd, TQStringList raw, TQIODevice *dev ) - : command(cmd), rawCmds(raw), is_ba(FALSE) -{ - id = ++idCounter; - data.dev = dev; -} - -TQFtpCommand::~TQFtpCommand() -{ - if ( is_ba ) - delete data.ba; -} - -/********************************************************************** - * - * TQFtpDTP implemenatation - * - *********************************************************************/ -TQFtpDTP::TQFtpDTP( TQFtpPI *p, TQObject *parent, const char *name ) : - TQObject( parent, name ), - socket( 0, "TQFtpDTP_socket" ), - pi( p ), - callWriteData( FALSE ) -{ - clearData(); - - connect( &socket, TQT_SIGNAL( connected() ), - TQT_SLOT( socketConnected() ) ); - connect( &socket, TQT_SIGNAL( readyRead() ), - TQT_SLOT( socketReadyRead() ) ); - connect( &socket, TQT_SIGNAL( error(int) ), - TQT_SLOT( socketError(int) ) ); - connect( &socket, TQT_SIGNAL( connectionClosed() ), - TQT_SLOT( socketConnectionClosed() ) ); - connect( &socket, TQT_SIGNAL( bytesWritten(int) ), - TQT_SLOT( socketBytesWritten(int) ) ); -} - -void TQFtpDTP::setData( TQByteArray *ba ) -{ - is_ba = TRUE; - data.ba = ba; -} - -void TQFtpDTP::setDevice( TQIODevice *dev ) -{ - is_ba = FALSE; - data.dev = dev; -} - -void TQFtpDTP::writeData() -{ - if ( is_ba ) { -#if defined(TQFTPDTP_DEBUG) - qDebug( "TQFtpDTP::writeData: write %d bytes", data.ba->size() ); -#endif - if ( data.ba->size() == 0 ) - emit dataTransferProgress( 0, bytesTotal ); - else - socket.writeBlock( data.ba->data(), data.ba->size() ); - socket.close(); - clearData(); - } else if ( data.dev ) { - callWriteData = FALSE; - const int blockSize = 16*1024; - char buf[blockSize]; - while ( !data.dev->atEnd() && socket.bytesToWrite()==0 ) { - TQ_LONG read = data.dev->readBlock( buf, blockSize ); -#if defined(TQFTPDTP_DEBUG) - qDebug( "TQFtpDTP::writeData: writeBlock() of size %d bytes", (int)read ); -#endif - socket.writeBlock( buf, read ); - if ( !data.dev ) - return; // this can happen when a command is aborted - } - if ( data.dev->atEnd() ) { - if ( bytesDone==0 && socket.bytesToWrite()==0 ) - emit dataTransferProgress( 0, bytesTotal ); - socket.close(); - clearData(); - } else { - callWriteData = TRUE; - } - } -} - -inline bool TQFtpDTP::hasError() const -{ - return !err.isNull(); -} - -inline TQString TQFtpDTP::errorMessage() const -{ - return err; -} - -inline void TQFtpDTP::clearError() -{ - err = TQString::null; -} - -void TQFtpDTP::abortConnection() -{ -#if defined(TQFTPDTP_DEBUG) - qDebug( "TQFtpDTP::abortConnection" ); -#endif - callWriteData = FALSE; - clearData(); - - socket.clearPendingData(); - socket.close(); -} - -bool TQFtpDTP::parseDir( const TQString &buffer, const TQString &userName, TQUrlInfo *info ) -{ - TQStringList lst = TQStringList::split( " ", buffer ); - - if ( lst.count() < 9 ) - return FALSE; - - TQString tmp; - - // permissions - tmp = lst[ 0 ]; - - if ( tmp[ 0 ] == TQChar( 'd' ) ) { - info->setDir( TRUE ); - info->setFile( FALSE ); - info->setSymLink( FALSE ); - } else if ( tmp[ 0 ] == TQChar( '-' ) ) { - info->setDir( FALSE ); - info->setFile( TRUE ); - info->setSymLink( FALSE ); - } else if ( tmp[ 0 ] == TQChar( 'l' ) ) { - info->setDir( TRUE ); // #### todo - info->setFile( FALSE ); - info->setSymLink( TRUE ); - } else { - return FALSE; - } - - static int user = 0; - static int group = 1; - static int other = 2; - static int readable = 0; - static int writable = 1; - static int executable = 2; - - bool perms[ 3 ][ 3 ]; - perms[0][0] = (tmp[ 1 ] == 'r'); - perms[0][1] = (tmp[ 2 ] == 'w'); - perms[0][2] = (tmp[ 3 ] == 'x'); - perms[1][0] = (tmp[ 4 ] == 'r'); - perms[1][1] = (tmp[ 5 ] == 'w'); - perms[1][2] = (tmp[ 6 ] == 'x'); - perms[2][0] = (tmp[ 7 ] == 'r'); - perms[2][1] = (tmp[ 8 ] == 'w'); - perms[2][2] = (tmp[ 9 ] == 'x'); - - // owner - tmp = lst[ 2 ]; - info->setOwner( tmp ); - - // group - tmp = lst[ 3 ]; - info->setGroup( tmp ); - - // ### not correct - info->setWritable( ( userName == info->owner() && perms[ user ][ writable ] ) || - perms[ other ][ writable ] ); - info->setReadable( ( userName == info->owner() && perms[ user ][ readable ] ) || - perms[ other ][ readable ] ); - - int p = 0; - if ( perms[ user ][ readable ] ) - p |= TQUrlInfo::ReadOwner; - if ( perms[ user ][ writable ] ) - p |= TQUrlInfo::WriteOwner; - if ( perms[ user ][ executable ] ) - p |= TQUrlInfo::ExeOwner; - if ( perms[ group ][ readable ] ) - p |= TQUrlInfo::ReadGroup; - if ( perms[ group ][ writable ] ) - p |= TQUrlInfo::WriteGroup; - if ( perms[ group ][ executable ] ) - p |= TQUrlInfo::ExeGroup; - if ( perms[ other ][ readable ] ) - p |= TQUrlInfo::ReadOther; - if ( perms[ other ][ writable ] ) - p |= TQUrlInfo::WriteOther; - if ( perms[ other ][ executable ] ) - p |= TQUrlInfo::ExeOther; - info->setPermissions( p ); - - // size - tmp = lst[ 4 ]; - info->setSize( tmp.toInt() ); - - // date and time - TQTime time; - TQString dateStr; - dateStr += "Sun "; - lst[ 5 ][ 0 ] = lst[ 5 ][ 0 ].upper(); - dateStr += lst[ 5 ]; - dateStr += ' '; - dateStr += lst[ 6 ]; - dateStr += ' '; - - if ( lst[ 7 ].contains( ":" ) ) { - time = TQTime( lst[ 7 ].left( 2 ).toInt(), lst[ 7 ].right( 2 ).toInt() ); - dateStr += TQString::number( TQDate::currentDate().year() ); - } else { - dateStr += lst[ 7 ]; - } - - TQDate date = TQT_TQDATE_OBJECT(TQDate::fromString( dateStr )); - info->setLastModified( TQDateTime( date, time ) ); - - if ( lst[ 7 ].contains( ":" ) ) { - const int futureTolerance = 600; - if( info->lastModified().secsTo( TQDateTime::tqcurrentDateTime() ) < -futureTolerance ) { - TQDateTime dt = info->lastModified(); - TQDate d = TQT_TQDATE_OBJECT(dt.date()); - d.setYMD(d.year()-1, d.month(), d.day()); - dt.setDate(d); - info->setLastModified(dt); - } - } - - // name - if ( info->isSymLink() ) - info->setName( lst[ 8 ].stripWhiteSpace() ); - else { - TQString n; - for ( uint i = 8; i < lst.count(); ++i ) - n += lst[ i ] + " "; - n = n.stripWhiteSpace(); - info->setName( n ); - } - return TRUE; -} - -void TQFtpDTP::socketConnected() -{ -#if !defined (TQ_WS_TQWS) - // Use a large send buffer to reduce the number - // of writeBlocks when download and uploading files. - // The actual size used here (128k) is default on most - // Unixes. - socket.socketDevice()->setSendBufferSize(128 * 1024); - socket.socketDevice()->setReceiveBufferSize(128 * 1024); -#endif - - bytesDone = 0; -#if defined(TQFTPDTP_DEBUG) - qDebug( "TQFtpDTP::connectState( CsConnected )" ); -#endif - emit connectState( TQFtpDTP::CsConnected ); -} - -void TQFtpDTP::socketReadyRead() -{ - if ( pi->currentCommand().isEmpty() ) { - socket.close(); -#if defined(TQFTPDTP_DEBUG) - qDebug( "TQFtpDTP::connectState( CsClosed )" ); -#endif - emit connectState( TQFtpDTP::CsClosed ); - return; - } - - if ( pi->currentCommand().startsWith("LIST") ) { - while ( socket.canReadLine() ) { - TQUrlInfo i; - TQString line = socket.readLine(); -#if defined(TQFTPDTP_DEBUG) - qDebug( "TQFtpDTP read (list): '%s'", line.latin1() ); -#endif - if ( parseDir( line, "", &i ) ) { - emit listInfo( i ); - } else { - // some FTP servers don't return a 550 if the file or directory - // does not exist, but rather write a text to the data socket - // -- try to catch these cases - if ( line.endsWith( "No such file or directory\r\n" ) ) - err = line; - } - } - } else { - if ( !is_ba && data.dev ) { - TQByteArray ba( socket.bytesAvailable() ); - TQ_LONG bytesRead = socket.readBlock( ba.data(), ba.size() ); - if ( bytesRead < 0 ) { - // ### error handling - return; - } - ba.resize( bytesRead ); - bytesDone += bytesRead; -#if defined(TQFTPDTP_DEBUG) - qDebug( "TQFtpDTP read: %d bytes (total %d bytes)", (int)bytesRead, bytesDone ); -#endif - emit dataTransferProgress( bytesDone, bytesTotal ); - if (data.dev) // make sure it wasn't deleted in the slot - data.dev->writeBlock( ba ); - } else { -#if defined(TQFTPDTP_DEBUG) - qDebug( "TQFtpDTP readyRead: %d bytes available (total %d bytes read)", (int)bytesAvailable(), bytesDone ); -#endif - emit dataTransferProgress( bytesDone+socket.bytesAvailable(), bytesTotal ); - emit readyRead(); - } - } -} - -void TQFtpDTP::socketError( int e ) -{ - if ( e == TQSocket::ErrHostNotFound ) { -#if defined(TQFTPDTP_DEBUG) - qDebug( "TQFtpDTP::connectState( CsHostNotFound )" ); -#endif - emit connectState( TQFtpDTP::CsHostNotFound ); - } else if ( e == TQSocket::ErrConnectionRefused ) { -#if defined(TQFTPDTP_DEBUG) - qDebug( "TQFtpDTP::connectState( CsConnectionRefused )" ); -#endif - emit connectState( TQFtpDTP::CsConnectionRefused ); - } -} - -void TQFtpDTP::socketConnectionClosed() -{ - if ( !is_ba && data.dev ) { - clearData(); - } -#if defined(TQFTPDTP_DEBUG) - qDebug( "TQFtpDTP::connectState( CsClosed )" ); -#endif - emit connectState( TQFtpDTP::CsClosed ); -} - -void TQFtpDTP::socketBytesWritten( int bytes ) -{ - bytesDone += bytes; -#if defined(TQFTPDTP_DEBUG) - qDebug( "TQFtpDTP::bytesWritten( %d )", bytesDone ); -#endif - emit dataTransferProgress( bytesDone, bytesTotal ); - if ( callWriteData ) - writeData(); -} - -/********************************************************************** - * - * TQFtpPI implemenatation - * - *********************************************************************/ -TQFtpPI::TQFtpPI( TQObject *parent ) : - TQObject( parent ), - rawCommand(FALSE), - dtp( this ), - commandSocket( 0, "TQFtpPI_socket" ), - state( Begin ), abortState( None ), - currentCmd( TQString::null ), - waitForDtpToConnect( FALSE ), - waitForDtpToClose( FALSE ) -{ - connect( &commandSocket, TQT_SIGNAL(hostFound()), - TQT_SLOT(hostFound()) ); - connect( &commandSocket, TQT_SIGNAL(connected()), - TQT_SLOT(connected()) ); - connect( &commandSocket, TQT_SIGNAL(connectionClosed()), - TQT_SLOT(connectionClosed()) ); - connect( &commandSocket, TQT_SIGNAL(delayedCloseFinished()), - TQT_SLOT(delayedCloseFinished()) ); - connect( &commandSocket, TQT_SIGNAL(readyRead()), - TQT_SLOT(readyRead()) ); - connect( &commandSocket, TQT_SIGNAL(error(int)), - TQT_SLOT(error(int)) ); - - connect( &dtp, TQT_SIGNAL(connectState(int)), - TQT_SLOT(dtpConnectState(int)) ); -} - -void TQFtpPI::connectToHost( const TQString &host, TQ_UINT16 port ) -{ - emit connectState( TQFtp::HostLookup ); - commandSocket.connectToHost( host, port ); -} - -/* - Sends the sequence of commands \a cmds to the FTP server. When the commands - are all done the finished() signal is emitted. When an error occurs, the - error() signal is emitted. - - If there are pending commands in the queue this functions returns FALSE and - the \a cmds are not added to the queue; otherwise it returns TRUE. -*/ -bool TQFtpPI::sendCommands( const TQStringList &cmds ) -{ - if ( !pendingCommands.isEmpty() ) - return FALSE; - - if ( commandSocket.state()!=TQSocket::Connected || state!=Idle ) { - emit error( TQFtp::NotConnected, TQFtp::tr( "Not connected" ) ); - return TRUE; // there are no pending commands - } - - pendingCommands = cmds; - startNextCmd(); - return TRUE; -} - -void TQFtpPI::clearPendingCommands() -{ - pendingCommands.clear(); - dtp.abortConnection(); - currentCmd = TQString::null; - state = Idle; -} - -void TQFtpPI::abort() -{ - pendingCommands.clear(); - - if ( abortState != None ) - // ABOR already sent - return; - - abortState = AbortStarted; -#if defined(TQFTPPI_DEBUG) - qDebug( "TQFtpPI send: ABOR" ); -#endif - commandSocket.writeBlock( "ABOR\r\n", 6 ); - - if ( currentCmd.startsWith("STOR ") ) - dtp.abortConnection(); -} - -void TQFtpPI::hostFound() -{ - emit connectState( TQFtp::Connecting ); -} - -void TQFtpPI::connected() -{ - state = Begin; -#if defined(TQFTPPI_DEBUG) -// qDebug( "TQFtpPI state: %d [connected()]", state ); -#endif - emit connectState( TQFtp::Connected ); -} - -void TQFtpPI::connectionClosed() -{ - commandSocket.close(); - emit connectState( TQFtp::Unconnected ); -} - -void TQFtpPI::delayedCloseFinished() -{ - emit connectState( TQFtp::Unconnected ); -} - -void TQFtpPI::error( int e ) -{ - if ( e == TQSocket::ErrHostNotFound ) { - emit connectState( TQFtp::Unconnected ); - emit error( TQFtp::HostNotFound, - TQFtp::tr( "Host %1 not found" ).arg( commandSocket.peerName() ) ); - } else if ( e == TQSocket::ErrConnectionRefused ) { - emit connectState( TQFtp::Unconnected ); - emit error( TQFtp::ConnectionRefused, - TQFtp::tr( "Connection refused to host %1" ).arg( commandSocket.peerName() ) ); - } -} - -void TQFtpPI::readyRead() -{ - if ( waitForDtpToClose ) - return; - - while ( commandSocket.canReadLine() ) { - // read line with respect to line continuation - TQString line = commandSocket.readLine(); - if ( replyText.isEmpty() ) { - if ( line.length() < 3 ) { - // ### protocol error - return; - } - const int lowerLimit[3] = {1,0,0}; - const int upperLimit[3] = {5,5,9}; - for ( int i=0; i<3; i++ ) { - replyCode[i] = line[i].digitValue(); - if ( replyCode[i]upperLimit[i] ) { - // ### protocol error - return; - } - } - } - TQString endOfMultiLine; - endOfMultiLine[0] = '0' + replyCode[0]; - endOfMultiLine[1] = '0' + replyCode[1]; - endOfMultiLine[2] = '0' + replyCode[2]; - endOfMultiLine[3] = ' '; - TQString lineCont( endOfMultiLine ); - lineCont[3] = '-'; - TQString lineLeft4 = line.left(4); - - while ( lineLeft4 != endOfMultiLine ) { - if ( lineLeft4 == lineCont ) - replyText += line.mid( 4 ); // strip 'xyz-' - else - replyText += line; - if ( !commandSocket.canReadLine() ) - return; - line = commandSocket.readLine(); - lineLeft4 = line.left(4); - } - replyText += line.mid( 4 ); // strip reply code 'xyz ' - if ( replyText.endsWith("\r\n") ) - replyText.truncate( replyText.length()-2 ); - - if ( processReply() ) - replyText = ""; - } -} - -/* - Process a reply from the FTP server. - - Returns TRUE if the reply was processed or FALSE if the reply has to be - processed at a later point. -*/ -bool TQFtpPI::processReply() -{ -#if defined(TQFTPPI_DEBUG) -// qDebug( "TQFtpPI state: %d [processReply() begin]", state ); - if ( replyText.length() < 400 ) - qDebug( "TQFtpPI recv: %d %s", 100*replyCode[0]+10*replyCode[1]+replyCode[2], replyText.latin1() ); - else - qDebug( "TQFtpPI recv: %d (text skipped)", 100*replyCode[0]+10*replyCode[1]+replyCode[2] ); -#endif - - // process 226 replies ("Closing Data Connection") only when the data - // connection is really closed to avoid short reads of the DTP - if ( 100*replyCode[0]+10*replyCode[1]+replyCode[2] == 226 ) { - if ( dtp.socketState() != TQSocket::Idle ) { - waitForDtpToClose = TRUE; - return FALSE; - } - } - - switch ( abortState ) { - case AbortStarted: - abortState = WaitForAbortToFinish; - break; - case WaitForAbortToFinish: - abortState = None; - return TRUE; - default: - break; - } - - // get new state - static const State table[5] = { - /* 1yz 2yz 3yz 4yz 5yz */ - Waiting, Success, Idle, Failure, Failure - }; - switch ( state ) { - case Begin: - if ( replyCode[0] == 1 ) { - return TRUE; - } else if ( replyCode[0] == 2 ) { - state = Idle; - emit finished( TQFtp::tr( "Connected to host %1" ).arg( commandSocket.peerName() ) ); - break; - } - // ### error handling - return TRUE; - case Waiting: - if ( replyCode[0]<0 || replyCode[0]>5 ) - state = Failure; - else - state = table[ replyCode[0] - 1 ]; - break; - default: - // ### spontaneous message - return TRUE; - } -#if defined(TQFTPPI_DEBUG) -// qDebug( "TQFtpPI state: %d [processReply() intermediate]", state ); -#endif - - // special actions on certain replies - int replyCodeInt = 100*replyCode[0] + 10*replyCode[1] + replyCode[2]; - emit rawFtpReply( replyCodeInt, replyText ); - if ( rawCommand ) { - rawCommand = FALSE; - } else if ( replyCodeInt == 227 ) { - // 227 Entering Passive Mode (h1,h2,h3,h4,p1,p2) - // rfc959 does not define this response precisely, and gives - // both examples where the parenthesis are used, and where - // they are missing. We need to scan for the address and host - // info. - TQRegExp addrPortPattern("(\\d+),(\\d+),(\\d+),(\\d+),(\\d+),(\\d+)"); - if (addrPortPattern.search(replyText) == -1) { -#if defined(TQFTPPI_DEBUG) - qDebug( "TQFtp: bad 227 response -- address and port information missing" ); -#endif - // ### error handling - } else { - QStringList lst = addrPortPattern.capturedTexts(); - TQString host = lst[1] + "." + lst[2] + "." + lst[3] + "." + lst[4]; - TQ_UINT16 port = ( lst[5].toUInt() << 8 ) + lst[6].toUInt(); - waitForDtpToConnect = TRUE; - dtp.connectToHost( host, port ); - } - } else if ( replyCodeInt == 230 ) { - if ( currentCmd.startsWith("USER ") && pendingCommands.count()>0 && - pendingCommands.first().startsWith("PASS ") ) { - // no need to send the PASS -- we are already logged in - pendingCommands.pop_front(); - } - // 230 User logged in, proceed. - emit connectState( TQFtp::LoggedIn ); - } else if ( replyCodeInt == 213 ) { - // 213 File status. - if ( currentCmd.startsWith("SIZE ") ) - dtp.setBytesTotal( replyText.simplifyWhiteSpace().toInt() ); - } else if ( replyCode[0]==1 && currentCmd.startsWith("STOR ") ) { - dtp.writeData(); - } - - // react on new state - switch ( state ) { - case Begin: - // ### should never happen - break; - case Success: - // ### success handling - state = Idle; - // no break! - case Idle: - if ( dtp.hasError() ) { - emit error( TQFtp::UnknownError, dtp.errorMessage() ); - dtp.clearError(); - } - startNextCmd(); - break; - case Waiting: - // ### do nothing - break; - case Failure: - emit error( TQFtp::UnknownError, replyText ); - state = Idle; - startNextCmd(); - break; - } -#if defined(TQFTPPI_DEBUG) -// qDebug( "TQFtpPI state: %d [processReply() end]", state ); -#endif - return TRUE; -} - -#ifndef TQT_NO_TEXTCODEC -TQM_EXPORT_FTP TQTextCodec *qt_ftp_filename_codec = 0; -#endif - -/* - Starts next pending command. Returns FALSE if there are no pending commands, - otherwise it returns TRUE. -*/ -bool TQFtpPI::startNextCmd() -{ - if ( waitForDtpToConnect ) - // don't process any new commands until we are connected - return TRUE; - -#if defined(TQFTPPI_DEBUG) - if ( state != Idle ) - qDebug( "TQFtpPI startNextCmd: Internal error! TQFtpPI called in non-Idle state %d", state ); -#endif - if ( pendingCommands.isEmpty() ) { - currentCmd = TQString::null; - emit finished( replyText ); - return FALSE; - } - currentCmd = pendingCommands.first(); - pendingCommands.pop_front(); -#if defined(TQFTPPI_DEBUG) - qDebug( "TQFtpPI send: %s", currentCmd.left( currentCmd.length()-2 ).latin1() ); -#endif - state = Waiting; -#ifndef TQT_NO_TEXTCODEC - if ( qt_ftp_filename_codec ) { - int len = 0; - TQCString enc = qt_ftp_filename_codec->fromUnicode(currentCmd,len); - commandSocket.writeBlock( enc.data(), len ); - } else -#endif - { - commandSocket.writeBlock( currentCmd.latin1(), currentCmd.length() ); - } - return TRUE; -} - -void TQFtpPI::dtpConnectState( int s ) -{ - switch ( s ) { - case TQFtpDTP::CsClosed: - if ( waitForDtpToClose ) { - // there is an unprocessed reply - if ( processReply() ) - replyText = ""; - else - return; - } - waitForDtpToClose = FALSE; - readyRead(); - return; - case TQFtpDTP::CsConnected: - waitForDtpToConnect = FALSE; - startNextCmd(); - return; - case TQFtpDTP::CsHostNotFound: - case TQFtpDTP::CsConnectionRefused: - emit error( TQFtp::ConnectionRefused, - TQFtp::tr( "Connection refused for data connection" ) ); - startNextCmd(); - return; - default: - return; - } -} - -/********************************************************************** - * - * TQFtpPrivate - * - *********************************************************************/ -class TQFtpPrivate -{ -public: - TQFtpPrivate() : - close_waitForStateChange(FALSE), - state( TQFtp::Unconnected ), - error( TQFtp::NoError ), - npWaitForLoginDone( FALSE ) - { pending.setAutoDelete( TRUE ); } - - TQFtpPI pi; - TQPtrList pending; - bool close_waitForStateChange; - TQFtp::State state; - TQFtp::Error error; - TQString errorString; - - bool npWaitForLoginDone; -}; - -static TQPtrDict *d_ptr = 0; -static void cleanup_d_ptr() -{ - delete d_ptr; - d_ptr = 0; -} -static TQFtpPrivate* d( const TQFtp* foo ) -{ - if ( !d_ptr ) { - d_ptr = new TQPtrDict; - d_ptr->setAutoDelete( TRUE ); - qAddPostRoutine( cleanup_d_ptr ); - } - TQFtpPrivate* ret = d_ptr->find( (void*)foo ); - if ( ! ret ) { - ret = new TQFtpPrivate; - d_ptr->replace( (void*) foo, ret ); - } - return ret; -} - -static void delete_d( const TQFtp* foo ) -{ - if ( d_ptr ) - d_ptr->remove( (void*) foo ); -} - -/********************************************************************** - * - * TQFtp implementation - * - *********************************************************************/ -/*! - \class TQFtp tqftp.h - \brief The TQFtp class provides an implementation of the FTP protocol. -\if defined(commercial) - It is part of the TQt Enterprise Edition. -\endif - - \ingroup io - \module network - - This class provides two different interfaces: one is the - TQNetworkProtocol interface that allows you to use FTP through the - TQUrlOperator abstraction. The other is a direct interface to FTP - that gives you lower-level access to the FTP protocol for finer - control. Using the direct interface you can also execute arbitrary - FTP commands. - - Don't mix the two interfaces, since the behavior is not - well-defined. - - If you want to use TQFtp with the TQNetworkProtocol interface, you - do not use it directly, but rather through a TQUrlOperator, for - example: - - \code - TQUrlOperator op( "ftp://ftp.trolltech.com" ); - op.listChildren(); // Asks the server to provide a directory listing - \endcode - - This code will only work if the TQFtp class is registered; to - register the class, you must call qInitNetworkProtocols() before - using a TQUrlOperator with TQFtp. - - The rest of this descrption describes the direct interface to FTP. - - The class works asynchronously, so there are no blocking - functions. If an operation cannot be executed immediately, the - function will still return straight away and the operation will be - scheduled for later execution. The results of scheduled operations - are reported via Q_SIGNALS. This approach depends on the event loop - being in operation. - - The operations that can be scheduled (they are called "commands" - in the rest of the documentation) are the following: - connectToHost(), login(), close(), list(), cd(), get(), put(), - remove(), mkdir(), rmdir(), rename() and rawCommand(). - - All of these commands return a unique identifier that allows you - to keep track of the command that is currently being executed. - When the execution of a command starts, the commandStarted() - signal with the command's identifier is emitted. When the command - is finished, the commandFinished() signal is emitted with the - command's identifier and a bool that indicates whether the command - finished with an error. - - In some cases, you might want to execute a sequence of commands, - e.g. if you want to connect and login to a FTP server. This is - simply achieved: - - \code - TQFtp *ftp = new TQFtp( this ); // this is an optional TQObject parent - ftp->connectToHost( "ftp.trolltech.com" ); - ftp->login(); - \endcode - - In this case two FTP commands have been scheduled. When the last - scheduled command has finished, a done() signal is emitted with - a bool argument that tells you whether the sequence finished with - an error. - - If an error occurs during the execution of one of the commands in - a sequence of commands, all the pending commands (i.e. scheduled, - but not yet executed commands) are cleared and no Q_SIGNALS are - emitted for them. - - Some commands, e.g. list(), emit additional Q_SIGNALS to report - their results. - - Example: If you want to download the INSTALL file from Trolltech's - FTP server, you would write this: - - \code - ftp->connectToHost( "ftp.trolltech.com" ); // id == 1 - ftp->login(); // id == 2 - ftp->cd( "qt" ); // id == 3 - ftp->get( "INSTALL" ); // id == 4 - ftp->close(); // id == 5 - \endcode - - For this example the following sequence of Q_SIGNALS is emitted - (with small variations, depending on network traffic, etc.): - - \code - start( 1 ) - stateChanged( HostLookup ) - stateChanged( Connecting ) - stateChanged( Connected ) - finished( 1, FALSE ) - - start( 2 ) - stateChanged( LoggedIn ) - finished( 2, FALSE ) - - start( 3 ) - finished( 3, FALSE ) - - start( 4 ) - dataTransferProgress( 0, 3798 ) - dataTransferProgress( 2896, 3798 ) - readyRead() - dataTransferProgress( 3798, 3798 ) - readyRead() - finished( 4, FALSE ) - - start( 5 ) - stateChanged( Closing ) - stateChanged( Unconnected ) - finished( 5, FALSE ) - - done( FALSE ) - \endcode - - The dataTransferProgress() signal in the above example is useful - if you want to show a \link TQProgressBar progressbar \endlink to - inform the user about the progress of the download. The - readyRead() signal tells you that there is data ready to be read. - The amount of data can be queried then with the bytesAvailable() - function and it can be read with the readBlock() or readAll() - function. - - If the login fails for the above example, the Q_SIGNALS would look - like this: - - \code - start( 1 ) - stateChanged( HostLookup ) - stateChanged( Connecting ) - stateChanged( Connected ) - finished( 1, FALSE ) - - start( 2 ) - finished( 2, TRUE ) - - done( TRUE ) - \endcode - - You can then get details about the error with the error() and - errorString() functions. - - The functions currentId() and currentCommand() provide more - information about the currently executing command. - - The functions hasPendingCommands() and clearPendingCommands() - allow you to query and clear the list of pending commands. - - The safest and easiest way to use the FTP protocol is to use - TQUrlOperator() or the FTP commands described above. If you are an - experienced network programmer and want to have complete control - you can use rawCommand() to execute arbitrary FTP commands. - - \sa \link network.html TQt Network Documentation \endlink TQNetworkProtocol, TQUrlOperator TQHttp -*/ - -/*! - Constructs a TQFtp object. -*/ -TQFtp::TQFtp() : TQNetworkProtocol() -{ - init(); -} - -/*! - Constructs a TQFtp object. The \a parent and \a name parameters - are passed to the TQObject constructor. -*/ -TQFtp::TQFtp( TQObject *parent, const char *name ) : TQNetworkProtocol() -{ - if ( parent ) - parent->insertChild( this ); - TQT_TQOBJECT(this)->setName( name ); - init(); -} - -void TQFtp::init() -{ - TQFtpPrivate *d = ::d( this ); - d->errorString = tr( "Unknown error" ); - - connect( &d->pi, TQT_SIGNAL(connectState(int)), - TQT_SLOT(piConnectState(int)) ); - connect( &d->pi, TQT_SIGNAL(finished(const TQString&)), - TQT_SLOT(piFinished(const TQString&)) ); - connect( &d->pi, TQT_SIGNAL(error(int,const TQString&)), - TQT_SLOT(piError(int,const TQString&)) ); - connect( &d->pi, TQT_SIGNAL(rawFtpReply(int,const TQString&)), - TQT_SLOT(piFtpReply(int,const TQString&)) ); - - connect( &d->pi.dtp, TQT_SIGNAL(readyRead()), - TQT_SIGNAL(readyRead()) ); - connect( &d->pi.dtp, TQT_SIGNAL(dataTransferProgress(int,int)), - TQT_SIGNAL(dataTransferProgress(int,int)) ); - connect( &d->pi.dtp, TQT_SIGNAL(listInfo(const TQUrlInfo&)), - TQT_SIGNAL(listInfo(const TQUrlInfo&)) ); -} - -/*! - \enum TQFtp::State - - This enum defines the connection state: - - \value Unconnected There is no connection to the host. - \value HostLookup A host name lookup is in progress. - \value Connecting An attempt to connect to the host is in progress. - \value Connected Connection to the host has been achieved. - \value LoggedIn Connection and user login have been achieved. - \value Closing The connection is closing down, but it is not yet - closed. (The state will be \c Unconnected when the connection is - closed.) - - \sa stateChanged() state() -*/ -/*! - \enum TQFtp::Error - - This enum identifies the error that occurred. - - \value NoError No error occurred. - \value HostNotFound The host name lookup failed. - \value ConnectionRefused The server refused the connection. - \value NotConnected Tried to send a command, but there is no connection to - a server. - \value UnknownError An error other than those specified above - occurred. - - \sa error() -*/ - -/*! - \enum TQFtp::Command - - This enum is used as the return value for the currentCommand() function. - This allows you to perform specific actions for particular - commands, e.g. in a FTP client, you might want to clear the - directory view when a list() command is started; in this case you - can simply check in the slot connected to the start() signal if - the currentCommand() is \c List. - - \value None No command is being executed. - \value ConnectToHost connectToHost() is being executed. - \value Login login() is being executed. - \value Close close() is being executed. - \value List list() is being executed. - \value Cd cd() is being executed. - \value Get get() is being executed. - \value Put put() is being executed. - \value Remove remove() is being executed. - \value Mkdir mkdir() is being executed. - \value Rmdir rmdir() is being executed. - \value Rename rename() is being executed. - \value RawCommand rawCommand() is being executed. - - \sa currentCommand() -*/ - -/*! - \fn void TQFtp::stateChanged( int state ) - - This signal is emitted when the state of the connection changes. - The argument \a state is the new state of the connection; it is - one of the \l State values. - - It is usually emitted in response to a connectToHost() or close() - command, but it can also be emitted "spontaneously", e.g. when the - server closes the connection unexpectedly. - - \sa connectToHost() close() state() State -*/ - -/*! - \fn void TQFtp::listInfo( const TQUrlInfo &i ); - - This signal is emitted for each directory entry the list() command - finds. The details of the entry are stored in \a i. - - \sa list() -*/ - -/*! - \fn void TQFtp::commandStarted( int id ) - - This signal is emitted when processing the command identified by - \a id starts. - - \sa commandFinished() done() -*/ - -/*! - \fn void TQFtp::commandFinished( int id, bool error ) - - This signal is emitted when processing the command identified by - \a id has finished. \a error is TRUE if an error occurred during - the processing; otherwise \a error is FALSE. - - \sa commandStarted() done() error() errorString() -*/ - -/*! - \fn void TQFtp::done( bool error ) - - This signal is emitted when the last pending command has finished; - (it is emitted after the last command's commandFinished() signal). - \a error is TRUE if an error occurred during the processing; - otherwise \a error is FALSE. - - \sa commandFinished() error() errorString() -*/ - -/*! - \fn void TQFtp::readyRead() - - This signal is emitted in response to a get() command when there - is new data to read. - - If you specify a tqdevice as the second argument in the get() - command, this signal is \e not emitted; instead the data is - written directly to the tqdevice. - - You can read the data with the readAll() or readBlock() functions. - - This signal is useful if you want to process the data in chunks as - soon as it becomes available. If you are only interested in the - complete data, just connect to the commandFinished() signal and - read the data then instead. - - \sa get() readBlock() readAll() bytesAvailable() -*/ - -/*! - \fn void TQFtp::dataTransferProgress( int done, int total ) - - This signal is emitted in response to a get() or put() request to - indicate the current progress of the download or upload. - - \a done is the amount of data that has already been transferred - and \a total is the total amount of data to be read or written. It - is possible that the TQFtp class is not able to determine the total - amount of data that should be transferred, in which case \a total - is 0. (If you connect this signal to a TQProgressBar, the progress - bar shows a busy indicator if the total is 0). - - \warning \a done and \a total are not necessarily the size in - bytes, since for large files these values might need to be - "scaled" to avoid overflow. - - \sa get() put() TQProgressBar::setProgress() -*/ - -/*! - \fn void TQFtp::rawCommandReply( int replyCode, const TQString &detail ); - - This signal is emitted in response to the rawCommand() function. - \a replyCode is the 3 digit reply code and \a detail is the text - that follows the reply code. - - \sa rawCommand() -*/ - -/*! - Connects to the FTP server \a host using port \a port. - - The stateChanged() signal is emitted when the state of the - connecting process changes, e.g. to \c HostLookup, then \c - Connecting, then \c Connected. - - The function does not block and returns immediately. The command - is scheduled, and its execution is performed asynchronously. The - function returns a unique identifier which is passed by - commandStarted() and commandFinished(). - - When the command is started the commandStarted() signal is - emitted. When it is finished the commandFinished() signal is - emitted. - - \sa stateChanged() commandStarted() commandFinished() -*/ -int TQFtp::connectToHost( const TQString &host, TQ_UINT16 port ) -{ - TQStringList cmds; - cmds << host; - cmds << TQString::number( (uint)port ); - return addCommand( new TQFtpCommand( ConnectToHost, cmds ) ); -} - -/*! - Logs in to the FTP server with the username \a user and the - password \a password. - - The stateChanged() signal is emitted when the state of the - connecting process changes, e.g. to \c LoggedIn. - - The function does not block and returns immediately. The command - is scheduled, and its execution is performed asynchronously. The - function returns a unique identifier which is passed by - commandStarted() and commandFinished(). - - When the command is started the commandStarted() signal is - emitted. When it is finished the commandFinished() signal is - emitted. - - \sa commandStarted() commandFinished() -*/ -int TQFtp::login( const TQString &user, const TQString &password ) -{ - TQStringList cmds; - cmds << ( TQString("USER ") + ( user.isNull() ? TQString("anonymous") : user ) + "\r\n" ); - cmds << ( TQString("PASS ") + ( password.isNull() ? TQString("anonymous@") : password ) + "\r\n" ); - return addCommand( new TQFtpCommand( Login, cmds ) ); -} - -/*! - Closes the connection to the FTP server. - - The stateChanged() signal is emitted when the state of the - connecting process changes, e.g. to \c Closing, then \c - Unconnected. - - The function does not block and returns immediately. The command - is scheduled, and its execution is performed asynchronously. The - function returns a unique identifier which is passed by - commandStarted() and commandFinished(). - - When the command is started the commandStarted() signal is - emitted. When it is finished the commandFinished() signal is - emitted. - - \sa stateChanged() commandStarted() commandFinished() -*/ -int TQFtp::close() -{ - return addCommand( new TQFtpCommand( Close, TQStringList("TQUIT\r\n") ) ); -} - -/*! - Lists the contents of directory \a dir on the FTP server. If \a - dir is empty, it lists the contents of the current directory. - - The listInfo() signal is emitted for each directory entry found. - - The function does not block and returns immediately. The command - is scheduled, and its execution is performed asynchronously. The - function returns a unique identifier which is passed by - commandStarted() and commandFinished(). - - When the command is started the commandStarted() signal is - emitted. When it is finished the commandFinished() signal is - emitted. - - \sa listInfo() commandStarted() commandFinished() -*/ -int TQFtp::list( const TQString &dir ) -{ - TQStringList cmds; - cmds << "TYPE A\r\n"; - cmds << "PASV\r\n"; - if ( dir.isEmpty() ) - cmds << "LIST\r\n"; - else - cmds << ( "LIST " + dir + "\r\n" ); - return addCommand( new TQFtpCommand( List, cmds ) ); -} - -/*! - Changes the working directory of the server to \a dir. - - The function does not block and returns immediately. The command - is scheduled, and its execution is performed asynchronously. The - function returns a unique identifier which is passed by - commandStarted() and commandFinished(). - - When the command is started the commandStarted() signal is - emitted. When it is finished the commandFinished() signal is - emitted. - - \sa commandStarted() commandFinished() -*/ -int TQFtp::cd( const TQString &dir ) -{ - return addCommand( new TQFtpCommand( Cd, TQStringList("CWD "+dir+"\r\n") ) ); -} - -/*! - Downloads the file \a file from the server. - - If \a dev is 0, then the readyRead() signal is emitted when there - is data available to read. You can then read the data with the - readBlock() or readAll() functions. - - If \a dev is not 0, the data is written directly to the tqdevice \a - dev. Make sure that the \a dev pointer is valid for the duration - of the operation (it is safe to delete it when the - commandFinished() signal is emitted). In this case the readyRead() - signal is \e not emitted and you cannot read data with the - readBlock() or readAll() functions. - - If you don't read the data immediately it becomes available, i.e. - when the readyRead() signal is emitted, it is still available - until the next command is started. - - For example, if you want to present the data to the user as soon - as there is something available, connect to the readyRead() signal - and read the data immediately. On the other hand, if you only want - to work with the complete data, you can connect to the - commandFinished() signal and read the data when the get() command - is finished. - - The function does not block and returns immediately. The command - is scheduled, and its execution is performed asynchronously. The - function returns a unique identifier which is passed by - commandStarted() and commandFinished(). - - When the command is started the commandStarted() signal is - emitted. When it is finished the commandFinished() signal is - emitted. - - \sa readyRead() dataTransferProgress() commandStarted() - commandFinished() -*/ -int TQFtp::get( const TQString &file, TQIODevice *dev ) -{ - TQStringList cmds; - cmds << ( "SIZE " + file + "\r\n" ); - cmds << "TYPE I\r\n"; - cmds << "PASV\r\n"; - cmds << ( "RETR " + file + "\r\n" ); - if ( dev ) - return addCommand( new TQFtpCommand( Get, cmds, dev ) ); - return addCommand( new TQFtpCommand( Get, cmds ) ); -} - -/*! - \overload - - Writes the data \a data to the file called \a file on the server. - The progress of the upload is reported by the - dataTransferProgress() signal. - - The function does not block and returns immediately. The command - is scheduled, and its execution is performed asynchronously. The - function returns a unique identifier which is passed by - commandStarted() and commandFinished(). - - When the command is started the commandStarted() signal is - emitted. When it is finished the commandFinished() signal is - emitted. - - \sa dataTransferProgress() commandStarted() commandFinished() -*/ -int TQFtp::put( const TQByteArray &data, const TQString &file ) -{ - TQStringList cmds; - cmds << "TYPE I\r\n"; - cmds << "PASV\r\n"; - cmds << ( "ALLO " + TQString::number(data.size()) + "\r\n" ); - cmds << ( "STOR " + file + "\r\n" ); - return addCommand( new TQFtpCommand( Put, cmds, data ) ); -} - -/*! - Reads the data from the IO tqdevice \a dev, and writes it to the - file called \a file on the server. The data is read in chunks from - the IO tqdevice, so this overload allows you to transmit large - amounts of data without the need to read all the data into memory - at once. - - Make sure that the \a dev pointer is valid for the duration of the - operation (it is safe to delete it when the commandFinished() is - emitted). -*/ -int TQFtp::put( TQIODevice *dev, const TQString &file ) -{ - TQStringList cmds; - cmds << "TYPE I\r\n"; - cmds << "PASV\r\n"; - if ( !dev->isSequentialAccess() ) - cmds << ( "ALLO " + TQString::number(dev->size()) + "\r\n" ); - cmds << ( "STOR " + file + "\r\n" ); - return addCommand( new TQFtpCommand( Put, cmds, dev ) ); -} - -/*! - Deletes the file called \a file from the server. - - The function does not block and returns immediately. The command - is scheduled, and its execution is performed asynchronously. The - function returns a unique identifier which is passed by - commandStarted() and commandFinished(). - - When the command is started the commandStarted() signal is - emitted. When it is finished the commandFinished() signal is - emitted. - - \sa commandStarted() commandFinished() -*/ -int TQFtp::remove( const TQString &file ) -{ - return addCommand( new TQFtpCommand( Remove, TQStringList("DELE "+file+"\r\n") ) ); -} - -/*! - Creates a directory called \a dir on the server. - - The function does not block and returns immediately. The command - is scheduled, and its execution is performed asynchronously. The - function returns a unique identifier which is passed by - commandStarted() and commandFinished(). - - When the command is started the commandStarted() signal is - emitted. When it is finished the commandFinished() signal is - emitted. - - \sa commandStarted() commandFinished() -*/ -int TQFtp::mkdir( const TQString &dir ) -{ - return addCommand( new TQFtpCommand( Mkdir, TQStringList("MKD "+dir+"\r\n") ) ); -} - -/*! - Removes the directory called \a dir from the server. - - The function does not block and returns immediately. The command - is scheduled, and its execution is performed asynchronously. The - function returns a unique identifier which is passed by - commandStarted() and commandFinished(). - - When the command is started the commandStarted() signal is - emitted. When it is finished the commandFinished() signal is - emitted. - - \sa commandStarted() commandFinished() -*/ -int TQFtp::rmdir( const TQString &dir ) -{ - return addCommand( new TQFtpCommand( Rmdir, TQStringList("RMD "+dir+"\r\n") ) ); -} - -/*! - Renames the file called \a oldname to \a newname on the server. - - The function does not block and returns immediately. The command - is scheduled, and its execution is performed asynchronously. The - function returns a unique identifier which is passed by - commandStarted() and commandFinished(). - - When the command is started the commandStarted() signal is - emitted. When it is finished the commandFinished() signal is - emitted. - - \sa commandStarted() commandFinished() -*/ -int TQFtp::rename( const TQString &oldname, const TQString &newname ) -{ - TQStringList cmds; - cmds << ( "RNFR " + oldname + "\r\n" ); - cmds << ( "RNTO " + newname + "\r\n" ); - return addCommand( new TQFtpCommand( Rename, cmds ) ); -} - -/*! - Sends the raw FTP command \a command to the FTP server. This is - useful for low-level FTP access. If the operation you wish to - perform has an equivalent TQFtp function, we recommend using the - function instead of raw FTP commands since the functions are - easier and safer. - - The function does not block and returns immediately. The command - is scheduled, and its execution is performed asynchronously. The - function returns a unique identifier which is passed by - commandStarted() and commandFinished(). - - When the command is started the commandStarted() signal is - emitted. When it is finished the commandFinished() signal is - emitted. - - \sa rawCommandReply() commandStarted() commandFinished() -*/ -int TQFtp::rawCommand( const TQString &command ) -{ - TQString cmd = command.stripWhiteSpace() + "\r\n"; - return addCommand( new TQFtpCommand( RawCommand, TQStringList(cmd) ) ); -} - -/*! - Returns the number of bytes that can be read from the data socket - at the moment. - - \sa get() readyRead() readBlock() readAll() -*/ -TQ_ULONG TQFtp::bytesAvailable() const -{ - TQFtpPrivate *d = ::d( this ); - return d->pi.dtp.bytesAvailable(); -} - -/*! - Reads \a maxlen bytes from the data socket into \a data and - returns the number of bytes read. Returns -1 if an error occurred. - - \sa get() readyRead() bytesAvailable() readAll() -*/ -TQ_LONG TQFtp::readBlock( char *data, TQ_ULONG maxlen ) -{ - TQFtpPrivate *d = ::d( this ); - return d->pi.dtp.readBlock( data, maxlen ); -} - -/*! - Reads all the bytes available from the data socket and returns - them. - - \sa get() readyRead() bytesAvailable() readBlock() -*/ -TQByteArray TQFtp::readAll() -{ - TQFtpPrivate *d = ::d( this ); - return d->pi.dtp.readAll(); -} - -/*! - Aborts the current command and deletes all scheduled commands. - - If there is an unfinished command (i.e. a command for which the - commandStarted() signal has been emitted, but for which the - commandFinished() signal has not been emitted), this function - sends an \c ABORT command to the server. When the server replies - that the command is aborted, the commandFinished() signal with the - \c error argument set to \c TRUE is emitted for the command. Due - to timing issues, it is possible that the command had already - finished before the abort request reached the server, in which - case, the commandFinished() signal is emitted with the \c error - argument set to \c FALSE. - - For all other commands that are affected by the abort(), no - Q_SIGNALS are emitted. - - If you don't start further FTP commands directly after the - abort(), there won't be any scheduled commands and the done() - signal is emitted. - - \warning Some FTP servers, for example the BSD FTP daemon (version - 0.3), wrongly return a positive reply even when an abort has - occurred. For these servers the commandFinished() signal has its - error flag set to \c FALSE, even though the command did not - complete successfully. - - \sa clearPendingCommands() -*/ -void TQFtp::abort() -{ - TQFtpPrivate *d = ::d( this ); - if ( d->pending.isEmpty() ) - return; - - clearPendingCommands(); - d->pi.abort(); -} - -/*! - Returns the identifier of the FTP command that is being executed - or 0 if there is no command being executed. - - \sa currentCommand() -*/ -int TQFtp::currentId() const -{ - TQFtpPrivate *d = ::d( this ); - TQFtpCommand *c = d->pending.getFirst(); - if ( c == 0 ) - return 0; - return c->id; -} - -/*! - Returns the command type of the FTP command being executed or \c - None if there is no command being executed. - - \sa currentId() -*/ -TQFtp::Command TQFtp::currentCommand() const -{ - TQFtpPrivate *d = ::d( this ); - TQFtpCommand *c = d->pending.getFirst(); - if ( c == 0 ) - return None; - return c->command; -} - -/*! - Returns the TQIODevice pointer that is used by the FTP command to read data - from or store data to. If there is no current FTP command being executed or - if the command does not use an IO tqdevice, this function returns 0. - - This function can be used to delete the TQIODevice in the slot connected to - the commandFinished() signal. - - \sa get() put() -*/ -TQIODevice* TQFtp::currentDevice() const -{ - TQFtpPrivate *d = ::d( this ); - TQFtpCommand *c = d->pending.getFirst(); - if ( !c ) - return 0; - if ( c->is_ba ) - return 0; - return c->data.dev; -} - -/*! - Returns TRUE if there are any commands scheduled that have not yet - been executed; otherwise returns FALSE. - - The command that is being executed is \e not considered as a - scheduled command. - - \sa clearPendingCommands() currentId() currentCommand() -*/ -bool TQFtp::hasPendingCommands() const -{ - TQFtpPrivate *d = ::d( this ); - return d->pending.count() > 1; -} - -/*! - Deletes all pending commands from the list of scheduled commands. - This does not affect the command that is being executed. If you - want to stop this this as well, use abort(). - - \sa hasPendingCommands() abort() -*/ -void TQFtp::clearPendingCommands() -{ - TQFtpPrivate *d = ::d( this ); - TQFtpCommand *c = 0; - if ( d->pending.count() > 0 ) - c = d->pending.take( 0 ); - d->pending.clear(); - if ( c ) - d->pending.append( c ); -} - -/*! - Returns the current state of the object. When the state changes, - the stateChanged() signal is emitted. - - \sa State stateChanged() -*/ -TQFtp::State TQFtp::state() const -{ - TQFtpPrivate *d = ::d( this ); - return d->state; -} - -/*! - Returns the last error that occurred. This is useful to find out - what when wrong when receiving a commandFinished() or a done() - signal with the \c error argument set to \c TRUE. - - If you start a new command, the error status is reset to \c NoError. -*/ -TQFtp::Error TQFtp::error() const -{ - TQFtpPrivate *d = ::d( this ); - return d->error; -} - -/*! - Returns a human-readable description of the last error that - occurred. This is useful for presenting a error message to the - user when receiving a commandFinished() or a done() signal with - the \c error argument set to \c TRUE. - - The error string is often (but not always) the reply from the - server, so it is not always possible to translate the string. If - the message comes from TQt, the string has already passed through - tr(). -*/ -TQString TQFtp::errorString() const -{ - TQFtpPrivate *d = ::d( this ); - return d->errorString; -} - -int TQFtp::addCommand( TQFtpCommand *cmd ) -{ - TQFtpPrivate *d = ::d( this ); - d->pending.append( cmd ); - - if ( d->pending.count() == 1 ) - // don't emit the commandStarted() signal before the id is returned - TQTimer::singleShot( 0, this, TQT_SLOT(startNextCommand()) ); - - return cmd->id; -} - -void TQFtp::startNextCommand() -{ - TQFtpPrivate *d = ::d( this ); - - TQFtpCommand *c = d->pending.getFirst(); - if ( c == 0 ) - return; - - d->error = NoError; - d->errorString = tr( "Unknown error" ); - - if ( bytesAvailable() ) - readAll(); // clear the data - emit commandStarted( c->id ); - - if ( c->command == ConnectToHost ) { - d->pi.connectToHost( c->rawCmds[0], c->rawCmds[1].toUInt() ); - } else { - if ( c->command == Put ) { - if ( c->is_ba ) { - d->pi.dtp.setData( c->data.ba ); - d->pi.dtp.setBytesTotal( c->data.ba->size() ); - } else if ( c->data.dev && (c->data.dev->isOpen() || c->data.dev->open(IO_ReadOnly) ) ) { - d->pi.dtp.setDevice( c->data.dev ); - if ( c->data.dev->isSequentialAccess() ) - d->pi.dtp.setBytesTotal( 0 ); - else - d->pi.dtp.setBytesTotal( c->data.dev->size() ); - } - } else if ( c->command == Get ) { - if ( !c->is_ba && c->data.dev ) { - d->pi.dtp.setDevice( c->data.dev ); - } - } else if ( c->command == Close ) { - d->state = TQFtp::Closing; - emit stateChanged( d->state ); - } - if ( !d->pi.sendCommands( c->rawCmds ) ) { - // ### error handling (this case should not happen) - } - } -} - -void TQFtp::piFinished( const TQString& ) -{ - TQFtpPrivate *d = ::d( this ); - TQFtpCommand *c = d->pending.getFirst(); - if ( c == 0 ) - return; - - if ( c->command == Close ) { - // The order of in which the Q_SLOTS are called is arbitrary, so - // disconnect the SIGNAL-TQT_SIGNAL temporary to make sure that we - // don't get the commandFinished() signal before the stateChanged() - // signal. - if ( d->state != TQFtp::Unconnected ) { - d->close_waitForStateChange = TRUE; - return; - } - } - emit commandFinished( c->id, FALSE ); - - d->pending.removeFirst(); - if ( d->pending.isEmpty() ) { - emit done( FALSE ); - } else { - startNextCommand(); - } -} - -void TQFtp::piError( int errorCode, const TQString &text ) -{ - TQFtpPrivate *d = ::d( this ); - TQFtpCommand *c = d->pending.getFirst(); - - // non-fatal errors - if ( c->command==Get && d->pi.currentCommand().startsWith("SIZE ") ) { - d->pi.dtp.setBytesTotal( -1 ); - return; - } else if ( c->command==Put && d->pi.currentCommand().startsWith("ALLO ") ) { - return; - } - - d->error = (Error)errorCode; - switch ( currentCommand() ) { - case ConnectToHost: - d->errorString = tr( "Connecting to host failed:\n%1" ).arg( text ); - break; - case Login: - d->errorString = tr( "Login failed:\n%1" ).arg( text ); - break; - case List: - d->errorString = tr( "Listing directory failed:\n%1" ).arg( text ); - break; - case Cd: - d->errorString = tr( "Changing directory failed:\n%1" ).arg( text ); - break; - case Get: - d->errorString = tr( "Downloading file failed:\n%1" ).arg( text ); - break; - case Put: - d->errorString = tr( "Uploading file failed:\n%1" ).arg( text ); - break; - case Remove: - d->errorString = tr( "Removing file failed:\n%1" ).arg( text ); - break; - case Mkdir: - d->errorString = tr( "Creating directory failed:\n%1" ).arg( text ); - break; - case Rmdir: - d->errorString = tr( "Removing directory failed:\n%1" ).arg( text ); - break; - default: - d->errorString = text; - break; - } - - d->pi.clearPendingCommands(); - clearPendingCommands(); - emit commandFinished( c->id, TRUE ); - - d->pending.removeFirst(); - if ( d->pending.isEmpty() ) - emit done( TRUE ); - else - startNextCommand(); -} - -void TQFtp::piConnectState( int state ) -{ - TQFtpPrivate *d = ::d( this ); - d->state = (State)state; - emit stateChanged( d->state ); - if ( d->close_waitForStateChange ) { - d->close_waitForStateChange = FALSE; - piFinished( tr( "Connection closed" ) ); - } -} - -void TQFtp::piFtpReply( int code, const TQString &text ) -{ - if ( currentCommand() == RawCommand ) { - TQFtpPrivate *d = ::d( this ); - d->pi.rawCommand = TRUE; - emit rawCommandReply( code, text ); - } -} - -/*! - Destructor. -*/ -TQFtp::~TQFtp() -{ - abort(); - close(); - delete_d( this ); -} - -/********************************************************************** - * - * TQFtp implementation of the TQNetworkProtocol interface - * - *********************************************************************/ -/*! \reimp -*/ -void TQFtp::operationListChildren( TQNetworkOperation *op ) -{ - op->setState( StInProgress ); - - cd( ( url()->path().isEmpty() ? TQString( "/" ) : url()->path() ) ); - list(); - emit start( op ); -} - -/*! \reimp -*/ -void TQFtp::operationMkDir( TQNetworkOperation *op ) -{ - op->setState( StInProgress ); - - mkdir( op->arg( 0 ) ); -} - -/*! \reimp -*/ -void TQFtp::operationRemove( TQNetworkOperation *op ) -{ - op->setState( StInProgress ); - - cd( ( url()->path().isEmpty() ? TQString( "/" ) : url()->path() ) ); - remove( TQUrl( op->arg( 0 ) ).path() ); -} - -/*! \reimp -*/ -void TQFtp::operationRename( TQNetworkOperation *op ) -{ - op->setState( StInProgress ); - - cd( ( url()->path().isEmpty() ? TQString( "/" ) : url()->path() ) ); - rename( op->arg( 0 ), op->arg( 1 )); -} - -/*! \reimp -*/ -void TQFtp::operationGet( TQNetworkOperation *op ) -{ - op->setState( StInProgress ); - - TQUrl u( op->arg( 0 ) ); - get( u.path() ); -} - -/*! \reimp -*/ -void TQFtp::operationPut( TQNetworkOperation *op ) -{ - op->setState( StInProgress ); - - TQUrl u( op->arg( 0 ) ); - put( op->rawArg(1), u.path() ); -} - -/*! \reimp -*/ -bool TQFtp::checkConnection( TQNetworkOperation *op ) -{ - TQFtpPrivate *d = ::d( this ); - if ( state() == Unconnected && !d->npWaitForLoginDone ) { - connect( this, TQT_SIGNAL(listInfo(const TQUrlInfo&)), - this, TQT_SLOT(npListInfo(const TQUrlInfo&)) ); - connect( this, TQT_SIGNAL(done(bool)), - this, TQT_SLOT(npDone(bool)) ); - connect( this, TQT_SIGNAL(stateChanged(int)), - this, TQT_SLOT(npStateChanged(int)) ); - connect( this, TQT_SIGNAL(dataTransferProgress(int,int)), - this, TQT_SLOT(npDataTransferProgress(int,int)) ); - connect( this, TQT_SIGNAL(readyRead()), - this, TQT_SLOT(npReadyRead()) ); - - d->npWaitForLoginDone = TRUE; - switch ( op->operation() ) { - case OpGet: - case OpPut: - { - TQUrl u( op->arg( 0 ) ); - connectToHost( u.host(), u.port() != -1 ? u.port() : 21 ); - } - break; - default: - connectToHost( url()->host(), url()->port() != -1 ? url()->port() : 21 ); - break; - } - TQString user = url()->user().isEmpty() ? TQString( "anonymous" ) : url()->user(); - TQString pass = url()->password().isEmpty() ? TQString( "anonymous@" ) : url()->password(); - login( user, pass ); - } - - if ( state() == LoggedIn ) - return TRUE; - return FALSE; -} - -/*! \reimp -*/ -int TQFtp::supportedOperations() const -{ - return OpListChildren | OpMkDir | OpRemove | OpRename | OpGet | OpPut; -} - -/*! \internal - Parses the string, \a buffer, which is one line of a directory - listing which came from the FTP server, and sets the values which - have been parsed to the url info object, \a info. -*/ -void TQFtp::parseDir( const TQString &buffer, TQUrlInfo &info ) -{ - TQFtpDTP::parseDir( buffer, url()->user(), &info ); -} - -void TQFtp::npListInfo( const TQUrlInfo & i ) -{ - if ( url() ) { - TQRegExp filt( url()->nameFilter(), FALSE, TRUE ); - if ( i.isDir() || filt.search( i.name() ) != -1 ) { - emit newChild( i, operationInProgress() ); - } - } else { - emit newChild( i, operationInProgress() ); - } -} - -void TQFtp::npDone( bool err ) -{ - TQFtpPrivate *d = ::d( this ); - - bool emitFinishedSignal = FALSE; - TQNetworkOperation *op = operationInProgress(); - if ( op ) { - if ( err ) { - op->setProtocolDetail( errorString() ); - op->setState( StFailed ); - if ( error() == HostNotFound ) { - op->setErrorCode( (int)ErrHostNotFound ); - } else { - switch ( op->operation() ) { - case OpListChildren: - op->setErrorCode( (int)ErrListChildren ); - break; - case OpMkDir: - op->setErrorCode( (int)ErrMkDir ); - break; - case OpRemove: - op->setErrorCode( (int)ErrRemove ); - break; - case OpRename: - op->setErrorCode( (int)ErrRename ); - break; - case OpGet: - op->setErrorCode( (int)ErrGet ); - break; - case OpPut: - op->setErrorCode( (int)ErrPut ); - break; - } - } - emitFinishedSignal = TRUE; - } else if ( !d->npWaitForLoginDone ) { - switch ( op->operation() ) { - case OpRemove: - emit removed( op ); - break; - case OpMkDir: - { - TQUrlInfo inf( op->arg( 0 ), 0, "", "", 0, TQDateTime(), - TQDateTime(), TRUE, FALSE, FALSE, TRUE, TRUE, TRUE ); - emit newChild( inf, op ); - emit createdDirectory( inf, op ); - } - break; - case OpRename: - emit itemChanged( operationInProgress() ); - break; - default: - break; - } - op->setState( StDone ); - emitFinishedSignal = TRUE; - } - } - d->npWaitForLoginDone = FALSE; - - if ( state() == Unconnected ) { - disconnect( this, TQT_SIGNAL(listInfo(const TQUrlInfo&)), - this, TQT_SLOT(npListInfo(const TQUrlInfo&)) ); - disconnect( this, TQT_SIGNAL(done(bool)), - this, TQT_SLOT(npDone(bool)) ); - disconnect( this, TQT_SIGNAL(stateChanged(int)), - this, TQT_SLOT(npStateChanged(int)) ); - disconnect( this, TQT_SIGNAL(dataTransferProgress(int,int)), - this, TQT_SLOT(npDataTransferProgress(int,int)) ); - disconnect( this, TQT_SIGNAL(readyRead()), - this, TQT_SLOT(npReadyRead()) ); - } - - // emit the finished() signal at the very end to avoid reentrance problems - if ( emitFinishedSignal ) - emit finished( op ); -} - -void TQFtp::npStateChanged( int state ) -{ - if ( url() ) { - if ( state == Connecting ) - emit connectionStateChanged( ConHostFound, tr( "Host %1 found" ).arg( url()->host() ) ); - else if ( state == Connected ) - emit connectionStateChanged( ConConnected, tr( "Connected to host %1" ).arg( url()->host() ) ); - else if ( state == Unconnected ) - emit connectionStateChanged( ConClosed, tr( "Connection to %1 closed" ).arg( url()->host() ) ); - } else { - if ( state == Connecting ) - emit connectionStateChanged( ConHostFound, tr( "Host found" ) ); - else if ( state == Connected ) - emit connectionStateChanged( ConConnected, tr( "Connected to host" ) ); - else if ( state == Unconnected ) - emit connectionStateChanged( ConClosed, tr( "Connection closed" ) ); - } -} - -void TQFtp::npDataTransferProgress( int bDone, int bTotal ) -{ - emit TQNetworkProtocol::dataTransferProgress( bDone, bTotal, operationInProgress() ); -} - -void TQFtp::npReadyRead() -{ - emit data( readAll(), operationInProgress() ); -} - -// ### unused -- delete in TQt 4.0 -/*! \internal -*/ -void TQFtp::hostFound() -{ -} -/*! \internal -*/ -void TQFtp::connected() -{ -} -/*! \internal -*/ -void TQFtp::closed() -{ -} -/*! \internal -*/ -void TQFtp::dataHostFound() -{ -} -/*! \internal -*/ -void TQFtp::dataConnected() -{ -} -/*! \internal -*/ -void TQFtp::dataClosed() -{ -} -/*! \internal -*/ -void TQFtp::dataReadyRead() -{ -} -/*! \internal -*/ -void TQFtp::dataBytesWritten( int ) -{ -} -/*! \internal -*/ -void TQFtp::error( int ) -{ -} - -#include "tqftp.tqmoc" - -#endif // TQT_NO_NETWORKPROTOCOL_FTP diff --git a/tqtinterface/qt4/src/network/tqftp.h b/tqtinterface/qt4/src/network/tqftp.h deleted file mode 100644 index afa7461..0000000 --- a/tqtinterface/qt4/src/network/tqftp.h +++ /dev/null @@ -1,204 +0,0 @@ -/**************************************************************************** -** -** Definition of TQFtp class. -** -** Created : 970521 -** -** Copyright (C) 1997-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the network module of the TQt 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 TQt 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.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** 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. -** -**********************************************************************/ - -#ifndef TQFTP_H -#define TQFTP_H - -#ifndef TQT_H -#include "tqstring.h" // char*->TQString conversion -#include "tqurlinfo.h" -#include "tqcstring.h" -#include "tqnetworkprotocol.h" -#endif // TQT_H - -#if !defined( TQT_MODULE_NETWORK ) || defined( TQT_LICENSE_PROFESSIONAL ) || defined( TQT_INTERNAL_NETWORK ) -#define TQM_EXPORT_FTP -#else -#define TQM_EXPORT_FTP TQ_EXPORT -#endif - -#ifndef TQT_NO_NETWORKPROTOCOL_FTP - - -class TQSocket; -class TQFtpCommand; - -class TQM_EXPORT_FTP TQFtp : public TQNetworkProtocol -{ - Q_OBJECT - TQ_OBJECT - -public: - TQFtp(); // ### TQt 4.0: get rid of this overload - TQFtp( TQObject *parent, const char *name=0 ); - virtual ~TQFtp(); - - int supportedOperations() const; - - // non-TQNetworkProtocol functions: - enum State { - Unconnected, - HostLookup, - Connecting, - Connected, - LoggedIn, - Closing - }; - enum Error { - NoError, - UnknownError, - HostNotFound, - ConnectionRefused, - NotConnected - }; - enum Command { - None, - ConnectToHost, - Login, - Close, - List, - Cd, - Get, - Put, - Remove, - Mkdir, - Rmdir, - Rename, - RawCommand - }; - - int connectToHost( const TQString &host, TQ_UINT16 port=21 ); - int login( const TQString &user=TQString::null, const TQString &password=TQString::null ); - int close(); - int list( const TQString &dir=TQString::null ); - int cd( const TQString &dir ); - int get( const TQString &file, TQIODevice *dev=0 ); - int put( const TQByteArray &data, const TQString &file ); - int put( TQIODevice *dev, const TQString &file ); - int remove( const TQString &file ); - int mkdir( const TQString &dir ); - int rmdir( const TQString &dir ); - int rename( const TQString &oldname, const TQString &newname ); - - int rawCommand( const TQString &command ); - - TQ_ULONG bytesAvailable() const; - TQ_LONG readBlock( char *data, TQ_ULONG maxlen ); - TQByteArray readAll(); - - int currentId() const; - TQIODevice* currentDevice() const; - Command currentCommand() const; - bool hasPendingCommands() const; - void clearPendingCommands(); - - State state() const; - - Error error() const; - TQString errorString() const; - -public Q_SLOTS: - void abort(); - -Q_SIGNALS: - void stateChanged( int ); - void listInfo( const TQUrlInfo& ); - void readyRead(); - void dataTransferProgress( int, int ); - void rawCommandReply( int, const TQString& ); - - void commandStarted( int ); - void commandFinished( int, bool ); - void done( bool ); - -protected: - void parseDir( const TQString &buffer, TQUrlInfo &info ); // ### TQt 4.0: delete this? (not public API) - void operationListChildren( TQNetworkOperation *op ); - void operationMkDir( TQNetworkOperation *op ); - void operationRemove( TQNetworkOperation *op ); - void operationRename( TQNetworkOperation *op ); - void operationGet( TQNetworkOperation *op ); - void operationPut( TQNetworkOperation *op ); - - // ### TQt 4.0: delete these - // unused variables: - TQSocket *commandSocket, *dataSocket; - bool connectionReady, passiveMode; - int getTotalSize, getDoneSize; - bool startGetOnFail; - int putToWrite, putWritten; - bool errorInListChildren; - -private: - void init(); - int addCommand( TQFtpCommand * ); - - bool checkConnection( TQNetworkOperation *op ); - -private Q_SLOTS: - void startNextCommand(); - void piFinished( const TQString& ); - void piError( int, const TQString& ); - void piConnectState( int ); - void piFtpReply( int, const TQString& ); - -private Q_SLOTS: - void npListInfo( const TQUrlInfo & ); - void npDone( bool ); - void npStateChanged( int ); - void npDataTransferProgress( int, int ); - void npReadyRead(); - -protected Q_SLOTS: - // ### TQt 4.0: delete these - void hostFound(); - void connected(); - void closed(); - void dataHostFound(); - void dataConnected(); - void dataClosed(); - void dataReadyRead(); - void dataBytesWritten( int nbytes ); - void error( int ); -}; - -#endif // TQT_NO_NETWORKPROTOCOL_FTP - -#endif // TQFTP_H diff --git a/tqtinterface/qt4/src/network/tqhostaddress.cpp b/tqtinterface/qt4/src/network/tqhostaddress.cpp deleted file mode 100644 index 5a4e5cf..0000000 --- a/tqtinterface/qt4/src/network/tqhostaddress.cpp +++ /dev/null @@ -1,459 +0,0 @@ -/**************************************************************************** -** -** Implementation of TQHostAddress class. -** -** Created : 979899 -** -** Copyright (C) 1997-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the network module of the TQt 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 TQt 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.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** 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 "tqhostaddress.h" -#include "tqstringlist.h" - -#ifdef USE_QT4 - -#else // USE_QT4 - -#ifndef TQT_NO_NETWORK -class TQHostAddressPrivate -{ -public: - TQHostAddressPrivate( TQ_UINT32 a_=0 ) : a(a_), isIp4(TRUE) - { - } - TQHostAddressPrivate( TQ_UINT8 *a_ ); - TQHostAddressPrivate(const TQ_IPV6ADDR &a_); - ~TQHostAddressPrivate() - { - } - - TQHostAddressPrivate & operator=( const TQHostAddressPrivate &from ) - { - a = from.a; - isIp4 = from.isIp4; - a6 = from.a6; - return *this; - } - -private: - TQ_UINT32 a; // ip 4 address - TQ_IPV6ADDR a6; // ip 6 address - bool isIp4; - - friend class TQHostAddress; -}; - -TQHostAddressPrivate::TQHostAddressPrivate(TQ_UINT8 *a_) : a(0), isIp4(FALSE) -{ - for ( int i=0; i<16; i++ ) { - a6.c[i] = a_[i]; - } -} - -TQHostAddressPrivate::TQHostAddressPrivate(const TQ_IPV6ADDR &a_) : a(0), isIp4(FALSE) -{ - a6 = a_; -} - -/*! - \class TQHostAddress tqhostaddress.h - \brief The TQHostAddress class provides an IP address. -\if defined(commercial) - It is part of the TQt Enterprise Edition. -\endif - - \ingroup io - \module network - - This class contains an IP address in a platform and protocol - independent manner. It stores both IPv4 and IPv6 addresses in a - way that you can easily access on any platform. - - TQHostAddress is normally used with the classes TQSocket, - TQServerSocket and TQSocketDevice to set up a server or to connect - to a host. - - Host addresses may be set with setAddress() and retrieved with - ip4Addr() or toString(). - - \sa TQSocket, TQServerSocket, TQSocketDevice -*/ - - -/*! - Creates a host address object with the IP address 0.0.0.0. -*/ -TQHostAddress::TQHostAddress() - : d( new TQHostAddressPrivate ) -{ -} - - -/*! - Creates a host address object for the IPv4 address \a ip4Addr. -*/ -TQHostAddress::TQHostAddress( TQ_UINT32 ip4Addr ) - : d( new TQHostAddressPrivate( ip4Addr ) ) -{ -} - - -/*! - Creates a host address object with the specified IPv6 address. - - \a ip6Addr must be a 16 byte array in network byte order - (high-order byte first). -*/ -TQHostAddress::TQHostAddress( TQ_UINT8 *ip6Addr ) - : d( new TQHostAddressPrivate( ip6Addr ) ) -{ -} - -/*! - Creates a host address object with the IPv6 address, \a ip6Addr. -*/ -TQHostAddress::TQHostAddress(const TQ_IPV6ADDR &ip6Addr) - : d(new TQHostAddressPrivate(ip6Addr)) -{ -} - -// ### DOC: Can only make this public if we specify precisely the -// format of the address string. -/*! - \internal -*/ -TQHostAddress::TQHostAddress(const TQString &address) - : d( new TQHostAddressPrivate ) -{ - setAddress( address ); -} - -/*! - Creates a copy of \a address. -*/ -TQHostAddress::TQHostAddress( const TQHostAddress &address ) - : d( new TQHostAddressPrivate ) -{ - *d = *(address.d); -} - - -/*! - Destroys the host address object. -*/ -TQHostAddress::~TQHostAddress() -{ - delete d; -} - - -/*! - Assigns another host address object \a address to this object and - returns a reference to this object. -*/ -TQHostAddress & TQHostAddress::operator=( const TQHostAddress & address ) -{ - *d = *(address.d); - return *this; -} - - -/*! - Set the IPv4 address specified by \a ip4Addr. -*/ -void TQHostAddress::setAddress( TQ_UINT32 ip4Addr ) -{ - delete d; - d = new TQHostAddressPrivate( ip4Addr ); -} - - -/*! - \overload - - Set the IPv6 address specified by \a ip6Addr. - - \a ip6Addr must be a 16 byte array in network byte order - (high-order byte first). -*/ -void TQHostAddress::setAddress( TQ_UINT8 *ip6Addr ) -{ - delete d; - d = new TQHostAddressPrivate( ip6Addr ); -} - -#ifndef TQT_NO_STRINGLIST -static bool parseIp4(const TQString& address, TQ_UINT32 *addr) -{ - TQStringList ipv4 = TQStringList::split(".", address, FALSE); - if (ipv4.count() == 4) { - int i = 0; - bool ok = TRUE; - while(ok && i < 4) { - uint byteValue = ipv4[i].toUInt(&ok); - if (byteValue > 255) - ok = FALSE; - if (ok) - *addr = (*addr << 8) + byteValue; - ++i; - } - if (ok) - return TRUE; - } - return FALSE; -} - -/*! - \overload - - Sets the IPv4 or IPv6 address specified by the string - representation \a address (e.g. "127.0.0.1"). Returns TRUE and - sets the address if the address was successfully parsed; otherwise - returns FALSE and leaves the address unchanged. -*/ -bool TQHostAddress::setAddress(const TQString& address) -{ - TQString a = address.simplifyWhiteSpace(); - - // try ipv4 - TQ_UINT32 maybeIp4 = 0; - if (parseIp4(address, &maybeIp4)) { - setAddress(maybeIp4); - return TRUE; - } - - // try ipv6 - TQStringList ipv6 = TQStringList::split(":", a, TRUE); - int count = (int)ipv6.count(); - if (count < 3) - return FALSE; // there must be at least two ":" - if (count > 8) - return FALSE; // maximum of seven ":" exceeded - TQ_UINT8 maybeIp6[16]; - int mc = 16; - int fillCount = 9 - count; - for (int i=count-1; i>=0; --i) { - if ( mc <= 0 ) - return FALSE; - - if (ipv6[i].isEmpty()) { - if (i==count-1) { - // special case: ":" is last character - if (!ipv6[i-1].isEmpty()) - return FALSE; - maybeIp6[--mc] = 0; - maybeIp6[--mc] = 0; - } else if (i==0) { - // special case: ":" is first character - if (!ipv6[i+1].isEmpty()) - return FALSE; - maybeIp6[--mc] = 0; - maybeIp6[--mc] = 0; - } else { - for (int j=0; j> 8) & 0xff; - } else { - if (i == count-1) { - // parse the ipv4 part of a mixed type - if (!parseIp4(ipv6[i], &maybeIp4)) - return FALSE; - maybeIp6[--mc] = maybeIp4 & 0xff; - maybeIp6[--mc] = (maybeIp4 >> 8) & 0xff; - maybeIp6[--mc] = (maybeIp4 >> 16) & 0xff; - maybeIp6[--mc] = (maybeIp4 >> 24) & 0xff; - --fillCount; - } else { - return FALSE; - } - } - } - } - if (mc == 0) { - setAddress(maybeIp6); - return TRUE; - } - - return FALSE; -} -#endif - -/*! - \obsolete - - Use isIPv4Address() instead. -*/ -bool TQHostAddress::isIp4Addr() const -{ - return isIPv4Address(); -} - -/*! - Returns TRUE if the host address represents an IPv4 address; - otherwise returns FALSE. -*/ -bool TQHostAddress::isIPv4Address() const -{ - return d->isIp4; -} - -/*! - \obsolete - - Use toIPv4Address() instead. -*/ -TQ_UINT32 TQHostAddress::ip4Addr() const -{ - return toIPv4Address(); -} - -/*! - Returns the IPv4 address as a number. - - For example, if the address is 127.0.0.1, the returned value is - 2130706433 (i.e. 0x7f000001). - - This value is only valid when isIp4Addr() returns TRUE. - - \sa toString() -*/ -TQ_UINT32 TQHostAddress::toIPv4Address() const -{ - return d->a; -} - -/*! - Returns TRUE if the host address represents an IPv6 address; - otherwise returns FALSE. -*/ -bool TQHostAddress::isIPv6Address() const -{ - return !d->isIp4; -} - -/*! - Returns the IPv6 address as a TQ_IPV6ADDR structure. The structure - consists of 16 unsigned characters. - - \code - TQ_IPV6ADDR addr = hostAddr.ip6Addr(); - // addr.c[] contains 16 unsigned characters - - for (int i = 0; i < 16; ++i) { - // process addr.c[i] - } - \endcode - - This value is only valid when isIPv6Address() returns TRUE. - - \sa toString() -*/ -TQ_IPV6ADDR TQHostAddress::toIPv6Address() const -{ - return d->a6; -} - -#ifndef TQT_NO_SPRINTF -/*! - Returns the address as a string. - - For example, if the address is the IPv4 address 127.0.0.1, the - returned string is "127.0.0.1". - - \sa ip4Addr() -*/ -TQString TQHostAddress::toString() const -{ - if ( d->isIp4 ) { - TQ_UINT32 i = ip4Addr(); - TQString s; - s.sprintf( "%d.%d.%d.%d", (i>>24) & 0xff, (i>>16) & 0xff, - (i >> 8) & 0xff, i & 0xff ); - return s; - } else { - TQ_UINT16 ugle[8]; - for ( int i=0; i<8; i++ ) { - ugle[i] = ( (TQ_UINT16)( d->a6.c[2*i] ) << 8 ) | - ( (TQ_UINT16)( d->a6.c[2*i+1] ) ); - } - TQString s; - s.sprintf( "%X:%X:%X:%X:%X:%X:%X:%X", - ugle[0], ugle[1], ugle[2], ugle[3], - ugle[4], ugle[5], ugle[6], ugle[7] ); - return s; - } -} -#endif - - -/*! - Returns TRUE if this host address is the same as \a other; - otherwise returns FALSE. -*/ -bool TQHostAddress::operator==( const TQHostAddress & other ) const -{ - return d->a == other.d->a; -} - - -/*! - Returns TRUE if this host address is null (INADDR_ANY or in6addr_any). The - default constructor creates a null address, and that address isn't valid - for any particular host or interface. -*/ -bool TQHostAddress::isNull() const -{ - if ( d->isIp4 ) - return d->a == 0; - int i = 0; - while( i < 16 ) { - if ( d->a6.c[i++] != 0 ) - return FALSE; - } - return TRUE; -} - -#endif //TQT_NO_NETWORK - -#endif // USE_QT4 \ No newline at end of file diff --git a/tqtinterface/qt4/src/network/tqhostaddress.h b/tqtinterface/qt4/src/network/tqhostaddress.h deleted file mode 100644 index 692bfd8..0000000 --- a/tqtinterface/qt4/src/network/tqhostaddress.h +++ /dev/null @@ -1,131 +0,0 @@ -/**************************************************************************** -** -** Definition of TQHostAddress class. -** -** Created : 979899 -** -** Copyright (C) 1997-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the network module of the TQt 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 TQt 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.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** 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. -** -**********************************************************************/ - -#ifndef TQHOSTADDRESS_H -#define TQHOSTADDRESS_H - -#include "tqtglobaldefines.h" - -#ifndef TQT_H -#include "tqstring.h" -#endif // TQT_H - -#if !defined( TQT_MODULE_NETWORK ) || defined( TQT_LICENSE_PROFESSIONAL ) || defined( TQT_INTERNAL_NETWORK ) -#define TQM_EXPORT_NETWORK -#else -#define TQM_EXPORT_NETWORK TQ_EXPORT -#endif - -#ifdef USE_QT4 - -#include - -#endif // USE_QT4 - -#ifndef TQT_NO_NETWORK -class TQHostAddressPrivate; - -typedef Q_IPV6ADDR TQ_IPV6ADDR; - -#ifdef USE_QT4 - -class TQM_EXPORT_NETWORK TQHostAddress : public QHostAddress -{ -public: - TQHostAddress() : QHostAddress() {} - TQHostAddress( TQ_UINT32 ip4Addr ) : QHostAddress( ip4Addr ) {} - TQHostAddress( TQ_UINT8 *ip6Addr ) : QHostAddress( ip6Addr ) {} - TQHostAddress(const TQ_IPV6ADDR &ip6Addr) : QHostAddress( ip6Addr ) {} -#ifndef TQT_NO_STRINGLIST - TQHostAddress(const QString &address) : QHostAddress( address ) {} -#endif - TQHostAddress( const QHostAddress &tqha ) : QHostAddress( tqha ) {} - - inline quint32 ip4Addr() const { return toIPv4Address(); } - inline bool isIPv4Address() const { return protocol() == QAbstractSocket::IPv4Protocol || protocol() == QAbstractSocket::UnknownNetworkLayerProtocol; } - inline bool isIp4Addr() const { return protocol() == QAbstractSocket::IPv4Protocol || protocol() == QAbstractSocket::UnknownNetworkLayerProtocol; } - inline bool isIPv6Address() const { return protocol() == QAbstractSocket::IPv6Protocol; } -}; - -#else // USE_QT4 - -class TQM_EXPORT_NETWORK TQHostAddress -{ -public: - TQHostAddress(); - TQHostAddress( TQ_UINT32 ip4Addr ); - TQHostAddress( TQ_UINT8 *ip6Addr ); - TQHostAddress(const TQ_IPV6ADDR &ip6Addr); -#ifndef TQT_NO_STRINGLIST - TQHostAddress(const TQString &address); -#endif - TQHostAddress( const TQHostAddress & ); - virtual ~TQHostAddress(); - - TQHostAddress & operator=( const TQHostAddress & ); - - void setAddress( TQ_UINT32 ip4Addr ); - void setAddress( TQ_UINT8 *ip6Addr ); -#ifndef TQT_NO_STRINGLIST - bool setAddress( const TQString& address ); -#endif - bool isIp4Addr() const; // obsolete - TQ_UINT32 ip4Addr() const; // obsolete - - bool isIPv4Address() const; - TQ_UINT32 toIPv4Address() const; - bool isIPv6Address() const; - TQ_IPV6ADDR toIPv6Address() const; - -#ifndef TQT_NO_SPRINTF - TQString toString() const; -#endif - - bool operator==( const TQHostAddress & ) const; - bool isNull() const; - -private: - TQHostAddressPrivate* d; -}; - -#endif // USE_QT4 - -#endif //TQT_NO_NETWORK -#endif diff --git a/tqtinterface/qt4/src/network/tqhttp.cpp b/tqtinterface/qt4/src/network/tqhttp.cpp deleted file mode 100644 index 6b1f061..0000000 --- a/tqtinterface/qt4/src/network/tqhttp.cpp +++ /dev/null @@ -1,2384 +0,0 @@ -/**************************************************************************** -** -** Implementation of TQHttp and related classes. -** -** Created : 970521 -** -** Copyright (C) 1997-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the network module of the TQt 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 TQt 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.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** 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 "tqhttp.h" - -#ifndef TQT_NO_NETWORKPROTOCOL_HTTP - -#include "tqsocket.h" -#include "tqtextstream.h" -#include "tqmap.h" -#include "tqstring.h" -#include "tqstringlist.h" -#include "tqcstring.h" -#include "tqbuffer.h" -#include "tqurloperator.h" -#include "tqtimer.h" -#include "private/tqinternal_p.h" - -//#define TQHTTP_DEBUG - -class TQHttpPrivate -{ -public: - TQHttpPrivate() : - state( TQHttp::Unconnected ), - error( TQHttp::NoError ), - hostname( TQString::null ), - port( 0 ), - toDevice( 0 ), - postDevice( 0 ), - bytesDone( 0 ), - chunkedSize( -1 ), - idleTimer( 0 ) - { - pending.setAutoDelete( TRUE ); - } - - TQSocket socket; - TQPtrList pending; - - TQHttp::State state; - TQHttp::Error error; - TQString errorString; - - TQString hostname; - TQ_UINT16 port; - - TQByteArray buffer; - TQIODevice* toDevice; - TQIODevice* postDevice; - - uint bytesDone; - uint bytesTotal; - TQ_LONG chunkedSize; - - TQHttpRequestHeader header; - - bool readHeader; - TQString headerStr; - TQHttpResponseHeader response; - - int idleTimer; - - TQMembuf rba; -}; - -class TQHttpRequest -{ -public: - TQHttpRequest() - { - id = ++idCounter; - } - virtual ~TQHttpRequest() - { } - - virtual void start( TQHttp * ) = 0; - virtual bool hasRequestHeader(); - virtual TQHttpRequestHeader requestHeader(); - - virtual TQIODevice* sourceDevice() = 0; - virtual TQIODevice* destinationDevice() = 0; - - int id; - -private: - static int idCounter; -}; - -int TQHttpRequest::idCounter = 0; - -bool TQHttpRequest::hasRequestHeader() -{ - return FALSE; -} - -TQHttpRequestHeader TQHttpRequest::requestHeader() -{ - return TQHttpRequestHeader(); -} - -/**************************************************** - * - * TQHttpNormalRequest - * - ****************************************************/ - -class TQHttpNormalRequest : public TQHttpRequest -{ -public: - TQHttpNormalRequest( const TQHttpRequestHeader &h, TQIODevice *d, TQIODevice *t ) : - header(h), to(t) - { - is_ba = FALSE; - data.dev = d; - } - - TQHttpNormalRequest( const TQHttpRequestHeader &h, TQByteArray *d, TQIODevice *t ) : - header(h), to(t) - { - is_ba = TRUE; - data.ba = d; - } - - ~TQHttpNormalRequest() - { - if ( is_ba ) - delete data.ba; - } - - void start( TQHttp * ); - bool hasRequestHeader(); - TQHttpRequestHeader requestHeader(); - - TQIODevice* sourceDevice(); - TQIODevice* destinationDevice(); - -protected: - TQHttpRequestHeader header; - -private: - union { - TQByteArray *ba; - TQIODevice *dev; - } data; - bool is_ba; - TQIODevice *to; -}; - -void TQHttpNormalRequest::start( TQHttp *http ) -{ - http->d->header = header; - - if ( is_ba ) { - http->d->buffer = *data.ba; - if ( http->d->buffer.size() > 0 ) - http->d->header.setContentLength( http->d->buffer.size() ); - - http->d->postDevice = 0; - } else { - http->d->buffer = TQByteArray(); - - if ( data.dev && ( data.dev->isOpen() || data.dev->open(IO_ReadOnly) ) ) { - http->d->postDevice = data.dev; - if ( http->d->postDevice->size() > 0 ) - http->d->header.setContentLength( http->d->postDevice->size() ); - } else { - http->d->postDevice = 0; - } - } - - if ( to && ( to->isOpen() || to->open(IO_WriteOnly) ) ) - http->d->toDevice = to; - else - http->d->toDevice = 0; - - http->sendRequest(); -} - -bool TQHttpNormalRequest::hasRequestHeader() -{ - return TRUE; -} - -TQHttpRequestHeader TQHttpNormalRequest::requestHeader() -{ - return header; -} - -TQIODevice* TQHttpNormalRequest::sourceDevice() -{ - if ( is_ba ) - return 0; - return data.dev; -} - -TQIODevice* TQHttpNormalRequest::destinationDevice() -{ - return to; -} - -/**************************************************** - * - * TQHttpPGHRequest - * (like a TQHttpNormalRequest, but for the convenience - * functions put(), get() and head() -- i.e. set the - * host header field correctly before sending the - * request) - * - ****************************************************/ - -class TQHttpPGHRequest : public TQHttpNormalRequest -{ -public: - TQHttpPGHRequest( const TQHttpRequestHeader &h, TQIODevice *d, TQIODevice *t ) : - TQHttpNormalRequest( h, d, t ) - { } - - TQHttpPGHRequest( const TQHttpRequestHeader &h, TQByteArray *d, TQIODevice *t ) : - TQHttpNormalRequest( h, d, t ) - { } - - ~TQHttpPGHRequest() - { } - - void start( TQHttp * ); -}; - -void TQHttpPGHRequest::start( TQHttp *http ) -{ - header.setValue( "Host", http->d->hostname ); - TQHttpNormalRequest::start( http ); -} - -/**************************************************** - * - * TQHttpSetHostRequest - * - ****************************************************/ - -class TQHttpSetHostRequest : public TQHttpRequest -{ -public: - TQHttpSetHostRequest( const TQString &h, TQ_UINT16 p ) : - hostname(h), port(p) - { } - - void start( TQHttp * ); - - TQIODevice* sourceDevice() - { return 0; } - TQIODevice* destinationDevice() - { return 0; } - -private: - TQString hostname; - TQ_UINT16 port; -}; - -void TQHttpSetHostRequest::start( TQHttp *http ) -{ - http->d->hostname = hostname; - http->d->port = port; - http->finishedWithSuccess(); -} - -/**************************************************** - * - * TQHttpCloseRequest - * - ****************************************************/ - -class TQHttpCloseRequest : public TQHttpRequest -{ -public: - TQHttpCloseRequest() - { } - void start( TQHttp * ); - - TQIODevice* sourceDevice() - { return 0; } - TQIODevice* destinationDevice() - { return 0; } -}; - -void TQHttpCloseRequest::start( TQHttp *http ) -{ - http->close(); -} - -/**************************************************** - * - * TQHttpHeader - * - ****************************************************/ - -/*! - \class TQHttpHeader tqhttp.h - \brief The TQHttpHeader class contains header information for HTTP. -\if defined(commercial) - It is part of the TQt Enterprise Edition. -\endif - - \ingroup io - \module network - - In most cases you should use the more specialized derivatives of - this class, TQHttpResponseHeader and TQHttpRequestHeader, rather - than directly using TQHttpHeader. - - TQHttpHeader provides the HTTP header fields. A HTTP header field - consists of a name followed by a colon, a single space, and the - field value. (See RFC 1945.) Field names are case-insensitive. A - typical header field looks like this: - \code - content-type: text/html - \endcode - - In the API the header field name is called the "key" and the - content is called the "value". You can get and set a header - field's value by using its key with value() and setValue(), e.g. - \code - header.setValue( "content-type", "text/html" ); - TQString contentType = header.value( "content-type" ); - \endcode - - Some fields are so common that getters and setters are provided - for them as a convenient alternative to using \l value() and - \l setValue(), e.g. contentLength() and contentType(), - setContentLength() and setContentType(). - - Each header key has a \e single value associated with it. If you - set the value for a key which already exists the previous value - will be discarded. - - \sa TQHttpRequestHeader TQHttpResponseHeader -*/ - -/*! - \fn int TQHttpHeader::majorVersion() const - - Returns the major protocol-version of the HTTP header. -*/ - -/*! - \fn int TQHttpHeader::minorVersion() const - - Returns the minor protocol-version of the HTTP header. -*/ - -/*! - Constructs an empty HTTP header. -*/ -TQHttpHeader::TQHttpHeader() - : valid( TRUE ) -{ -} - -/*! - Constructs a copy of \a header. -*/ -TQHttpHeader::TQHttpHeader( const TQHttpHeader& header ) - : valid( header.valid ) -{ - values = header.values; -} - -/*! - Constructs a HTTP header for \a str. - - This constructor parses the string \a str for header fields and - adds this information. The \a str should consist of one or more - "\r\n" delimited lines; each of these lines should have the format - key, colon, space, value. -*/ -TQHttpHeader::TQHttpHeader( const TQString& str ) - : valid( TRUE ) -{ - parse( str ); -} - -/*! - Destructor. -*/ -TQHttpHeader::~TQHttpHeader() -{ -} - -/*! - Assigns \a h and returns a reference to this http header. -*/ -TQHttpHeader& TQHttpHeader::operator=( const TQHttpHeader& h ) -{ - values = h.values; - valid = h.valid; - return *this; -} - -/*! - Returns TRUE if the HTTP header is valid; otherwise returns FALSE. - - A TQHttpHeader is invalid if it was created by parsing a malformed string. -*/ -bool TQHttpHeader::isValid() const -{ - return valid; -} - -/*! \internal - Parses the HTTP header string \a str for header fields and adds - the keys/values it finds. If the string is not parsed successfully - the TQHttpHeader becomes \link isValid() invalid\endlink. - - Returns TRUE if \a str was successfully parsed; otherwise returns FALSE. - - \sa toString() -*/ -bool TQHttpHeader::parse( const TQString& str ) -{ - TQStringList lst; - int pos = str.find( '\n' ); - if ( pos > 0 && str.at( pos - 1 ) == '\r' ) - lst = TQStringList::split( "\r\n", str.stripWhiteSpace(), FALSE ); - else - lst = TQStringList::split( "\n", str.stripWhiteSpace(), FALSE ); - - if ( lst.isEmpty() ) - return TRUE; - - TQStringList lines; - TQStringList::Iterator it = lst.begin(); - for( ; it != lst.end(); ++it ) { - if ( !(*it).isEmpty() ) { - if ( (*it)[0].isSpace() ) { - if ( !lines.isEmpty() ) { - lines.last() += " "; - lines.last() += (*it).stripWhiteSpace(); - } - } else { - lines.append( (*it) ); - } - } - } - - int number = 0; - it = lines.begin(); - for( ; it != lines.end(); ++it ) { - if ( !parseLine( *it, number++ ) ) { - valid = FALSE; - return FALSE; - } - } - return TRUE; -} - -/*! \internal -*/ -void TQHttpHeader::setValid( bool v ) -{ - valid = v; -} - -/*! - Returns the value for the entry with the given \a key. If no entry - has this \a key, an empty string is returned. - - \sa setValue() removeValue() hasKey() keys() -*/ -TQString TQHttpHeader::value( const TQString& key ) const -{ - return values[ key.lower() ]; -} - -/*! - Returns a list of the keys in the HTTP header. - - \sa hasKey() -*/ -TQStringList TQHttpHeader::keys() const -{ - return values.keys(); -} - -/*! - Returns TRUE if the HTTP header has an entry with the given \a - key; otherwise returns FALSE. - - \sa value() setValue() keys() -*/ -bool TQHttpHeader::hasKey( const TQString& key ) const -{ - return values.contains( key.lower() ); -} - -/*! - Sets the value of the entry with the \a key to \a value. - - If no entry with \a key exists, a new entry with the given \a key - and \a value is created. If an entry with the \a key already - exists, its value is discarded and replaced with the given \a - value. - - \sa value() hasKey() removeValue() -*/ -void TQHttpHeader::setValue( const TQString& key, const TQString& value ) -{ - values[ key.lower() ] = value; -} - -/*! - Removes the entry with the key \a key from the HTTP header. - - \sa value() setValue() -*/ -void TQHttpHeader::removeValue( const TQString& key ) -{ - values.remove( key.lower() ); -} - -/*! \internal - Parses the single HTTP header line \a line which has the format - key, colon, space, value, and adds key/value to the headers. The - linenumber is \a number. Returns TRUE if the line was successfully - parsed and the key/value added; otherwise returns FALSE. - - \sa parse() -*/ -bool TQHttpHeader::parseLine( const TQString& line, int ) -{ - int i = line.find( ":" ); - if ( i == -1 ) - return FALSE; - - values.insert( TQT_TQSTRING(line.left( i )).stripWhiteSpace().lower(), TQT_TQSTRING(line.mid( i + 1 )).stripWhiteSpace() ); - - return TRUE; -} - -/*! - Returns a string representation of the HTTP header. - - The string is suitable for use by the constructor that takes a - TQString. It consists of lines with the format: key, colon, space, - value, "\r\n". -*/ -TQString TQHttpHeader::toString() const -{ - if ( !isValid() ) - return ""; - - TQString ret = ""; - - TQMap::ConstIterator it = values.begin(); - for( ; it != values.end(); ++it ) - ret += it.key() + ": " + it.data() + "\r\n"; - - return ret; -} - -/*! - Returns TRUE if the header has an entry for the special HTTP - header field \c content-length; otherwise returns FALSE. - - \sa contentLength() setContentLength() -*/ -bool TQHttpHeader::hasContentLength() const -{ - return hasKey( "content-length" ); -} - -/*! - Returns the value of the special HTTP header field \c - content-length. - - \sa setContentLength() hasContentLength() -*/ -uint TQHttpHeader::contentLength() const -{ - return values[ "content-length" ].toUInt(); -} - -/*! - Sets the value of the special HTTP header field \c content-length - to \a len. - - \sa contentLength() hasContentLength() -*/ -void TQHttpHeader::setContentLength( int len ) -{ - values[ "content-length" ] = TQString::number( len ); -} - -/*! - Returns TRUE if the header has an entry for the the special HTTP - header field \c content-type; otherwise returns FALSE. - - \sa contentType() setContentType() -*/ -bool TQHttpHeader::hasContentType() const -{ - return hasKey( "content-type" ); -} - -/*! - Returns the value of the special HTTP header field \c content-type. - - \sa setContentType() hasContentType() -*/ -TQString TQHttpHeader::contentType() const -{ - TQString type = values[ "content-type" ]; - if ( type.isEmpty() ) - return TQString::null; - - int pos = type.find( ";" ); - if ( pos == -1 ) - return type; - - return TQT_TQSTRING(type.left( pos )).stripWhiteSpace(); -} - -/*! - Sets the value of the special HTTP header field \c content-type to - \a type. - - \sa contentType() hasContentType() -*/ -void TQHttpHeader::setContentType( const TQString& type ) -{ - values[ "content-type" ] = type; -} - -/**************************************************** - * - * TQHttpResponseHeader - * - ****************************************************/ - -/*! - \class TQHttpResponseHeader tqhttp.h - \brief The TQHttpResponseHeader class contains response header information for HTTP. -\if defined(commercial) - It is part of the TQt Enterprise Edition. -\endif - - \ingroup io - \module network - - This class is used by the TQHttp class to report the header - information that the client received from the server. - - HTTP responses have a status code that indicates the status of the - response. This code is a 3-digit integer result code (for details - see to RFC 1945). In addition to the status code, you can also - specify a human-readable text that describes the reason for the - code ("reason phrase"). This class allows you to get the status - code and the reason phrase. - - \sa TQHttpRequestHeader TQHttp -*/ - -/*! - Constructs an empty HTTP response header. -*/ -TQHttpResponseHeader::TQHttpResponseHeader() -{ - setValid( FALSE ); -} - -/*! - Constructs a HTTP response header with the status code \a code, - the reason phrase \a text and the protocol-version \a majorVer and - \a minorVer. -*/ -TQHttpResponseHeader::TQHttpResponseHeader( int code, const TQString& text, int majorVer, int minorVer ) - : TQHttpHeader(), statCode( code ), reasonPhr( text ), majVer( majorVer ), minVer( minorVer ) -{ -} - -/*! - Constructs a copy of \a header. -*/ -TQHttpResponseHeader::TQHttpResponseHeader( const TQHttpResponseHeader& header ) - : TQHttpHeader( header ), statCode( header.statCode ), reasonPhr( header.reasonPhr ), majVer( header.majVer ), minVer( header.minVer ) -{ -} - -/*! - Constructs a HTTP response header from the string \a str. The - string is parsed and the information is set. The \a str should - consist of one or more "\r\n" delimited lines; the first line should be the - status-line (format: HTTP-version, space, status-code, space, - reason-phrase); each of remaining lines should have the format key, colon, - space, value. -*/ -TQHttpResponseHeader::TQHttpResponseHeader( const TQString& str ) - : TQHttpHeader() -{ - parse( str ); -} - -/*! - Sets the status code to \a code, the reason phrase to \a text and - the protocol-version to \a majorVer and \a minorVer. - - \sa statusCode() reasonPhrase() majorVersion() minorVersion() -*/ -void TQHttpResponseHeader::setqStatusLine( int code, const TQString& text, int majorVer, int minorVer ) -{ - setValid( TRUE ); - statCode = code; - reasonPhr = text; - majVer = majorVer; - minVer = minorVer; -} - -/*! - Returns the status code of the HTTP response header. - - \sa reasonPhrase() majorVersion() minorVersion() -*/ -int TQHttpResponseHeader::statusCode() const -{ - return statCode; -} - -/*! - Returns the reason phrase of the HTTP response header. - - \sa statusCode() majorVersion() minorVersion() -*/ -TQString TQHttpResponseHeader::reasonPhrase() const -{ - return reasonPhr; -} - -/*! - Returns the major protocol-version of the HTTP response header. - - \sa minorVersion() statusCode() reasonPhrase() -*/ -int TQHttpResponseHeader::majorVersion() const -{ - return majVer; -} - -/*! - Returns the minor protocol-version of the HTTP response header. - - \sa majorVersion() statusCode() reasonPhrase() -*/ -int TQHttpResponseHeader::minorVersion() const -{ - return minVer; -} - -/*! \reimp -*/ -bool TQHttpResponseHeader::parseLine( const TQString& line, int number ) -{ - if ( number != 0 ) - return TQHttpHeader::parseLine( line, number ); - - TQString l = line.simplifyWhiteSpace(); - if ( l.length() < 10 ) - return FALSE; - - if ( l.left( 5 ) == "HTTP/" && l[5].isDigit() && l[6] == '.' && - l[7].isDigit() && l[8] == ' ' && l[9].isDigit() ) { - majVer = l[5].latin1() - '0'; - minVer = l[7].latin1() - '0'; - - int pos = l.find( ' ', 9 ); - if ( pos != -1 ) { - reasonPhr = l.mid( pos + 1 ); - statCode = l.mid( 9, pos - 9 ).toInt(); - } else { - statCode = l.mid( 9 ).toInt(); - reasonPhr = TQString::null; - } - } else { - return FALSE; - } - - return TRUE; -} - -/*! \reimp -*/ -TQString TQHttpResponseHeader::toString() const -{ - TQString ret( "HTTP/%1.%2 %3 %4\r\n%5\r\n" ); - return ret.arg( majVer ).arg ( minVer ).arg( statCode ).arg( reasonPhr ).arg( TQHttpHeader::toString() ); -} - -/**************************************************** - * - * TQHttpRequestHeader - * - ****************************************************/ - -/*! - \class TQHttpRequestHeader tqhttp.h - \brief The TQHttpRequestHeader class contains request header information for -\if defined(commercial) - It is part of the TQt Enterprise Edition. -\endif - HTTP. -\if defined(commercial_edition) - It is part of the TQt Enterprise Edition. -\endif - - \ingroup io - \module network - - This class is used in the TQHttp class to report the header - information if the client requests something from the server. - - HTTP requests have a method which describes the request's action. - The most common requests are "GET" and "POST". In addition to the - request method the header also includes a request-URI to specify - the location for the method to use. - - The method, request-URI and protocol-version can be set using a - constructor or later using setRequest(). The values can be - obtained using method(), path(), majorVersion() and - minorVersion(). - - This class is a TQHttpHeader subclass so that class's functions, - e.g. \link TQHttpHeader::setValue() setValue()\endlink, \link - TQHttpHeader::value() value()\endlink, etc. are also available. - - \sa TQHttpResponseHeader TQHttp - - \important value() setValue() -*/ - -/*! - Constructs an empty HTTP request header. -*/ -TQHttpRequestHeader::TQHttpRequestHeader() - : TQHttpHeader() -{ - setValid( FALSE ); -} - -/*! - Constructs a HTTP request header for the method \a method, the - request-URI \a path and the protocol-version \a majorVer and \a minorVer. -*/ -TQHttpRequestHeader::TQHttpRequestHeader( const TQString& method, const TQString& path, int majorVer, int minorVer ) - : TQHttpHeader(), m( method ), p( path ), majVer( majorVer ), minVer( minorVer ) -{ -} - -/*! - Constructs a copy of \a header. -*/ -TQHttpRequestHeader::TQHttpRequestHeader( const TQHttpRequestHeader& header ) - : TQHttpHeader( header ), m( header.m ), p( header.p ), majVer( header.majVer ), minVer( header.minVer ) -{ -} - -/*! - Constructs a HTTP request header from the string \a str. The \a - str should consist of one or more "\r\n" delimited lines; the first line - should be the request-line (format: method, space, request-URI, space - HTTP-version); each of the remaining lines should have the format key, - colon, space, value. -*/ -TQHttpRequestHeader::TQHttpRequestHeader( const TQString& str ) - : TQHttpHeader() -{ - parse( str ); -} - -/*! - This function sets the request method to \a method, the - request-URI to \a path and the protocol-version to \a majorVer and - \a minorVer. - - \sa method() path() majorVersion() minorVersion() -*/ -void TQHttpRequestHeader::setRequest( const TQString& method, const TQString& path, int majorVer, int minorVer ) -{ - setValid( TRUE ); - m = method; - p = path; - majVer = majorVer; - minVer = minorVer; -} - -/*! - Returns the method of the HTTP request header. - - \sa path() majorVersion() minorVersion() setRequest() -*/ -TQString TQHttpRequestHeader::method() const -{ - return m; -} - -/*! - Returns the request-URI of the HTTP request header. - - \sa method() majorVersion() minorVersion() setRequest() -*/ -TQString TQHttpRequestHeader::path() const -{ - return p; -} - -/*! - Returns the major protocol-version of the HTTP request header. - - \sa minorVersion() method() path() setRequest() -*/ -int TQHttpRequestHeader::majorVersion() const -{ - return majVer; -} - -/*! - Returns the minor protocol-version of the HTTP request header. - - \sa majorVersion() method() path() setRequest() -*/ -int TQHttpRequestHeader::minorVersion() const -{ - return minVer; -} - -/*! \reimp -*/ -bool TQHttpRequestHeader::parseLine( const TQString& line, int number ) -{ - if ( number != 0 ) - return TQHttpHeader::parseLine( line, number ); - - TQStringList lst = TQStringList::split( " ", line.simplifyWhiteSpace() ); - if ( lst.count() > 0 ) { - m = lst[0]; - if ( lst.count() > 1 ) { - p = lst[1]; - if ( lst.count() > 2 ) { - TQString v = lst[2]; - if ( v.length() >= 8 && v.left( 5 ) == "HTTP/" && - v[5].isDigit() && v[6] == '.' && v[7].isDigit() ) { - majVer = v[5].latin1() - '0'; - minVer = v[7].latin1() - '0'; - return TRUE; - } - } - } - } - - return FALSE; -} - -/*! \reimp -*/ -TQString TQHttpRequestHeader::toString() const -{ - TQString first( "%1 %2"); - TQString last(" HTTP/%3.%4\r\n%5\r\n" ); - return first.arg( m ).arg( p ) + - last.arg( majVer ).arg( minVer ).arg( TQHttpHeader::toString()); -} - - -/**************************************************** - * - * TQHttp - * - ****************************************************/ -/*! - \class TQHttp tqhttp.h - \brief The TQHttp class provides an implementation of the HTTP protocol. -\if defined(commercial) - It is part of the TQt Enterprise Edition. -\endif - - \ingroup io - \module network - - This class provides two different interfaces: one is the - TQNetworkProtocol interface that allows you to use HTTP through the - TQUrlOperator abstraction. The other is a direct interface to HTTP - that allows you to have more control over the requests and that - allows you to access the response header fields. - - Don't mix the two interfaces, since the behavior is not - well-defined. - - If you want to use TQHttp with the TQNetworkProtocol interface, you - do not use it directly, but rather through a TQUrlOperator, for - example: - - \code - TQUrlOperator op( "http://www.trolltech.com" ); - op.get( "index.html" ); - \endcode - - This code will only work if the TQHttp class is registered; to - register the class, you must call qInitNetworkProtocols() before - using a TQUrlOperator with HTTP. - - The TQNetworkProtocol interface for HTTP only supports the - operations operationGet() and operationPut(), i.e. - TQUrlOperator::get() and TQUrlOperator::put(), if you use it with a - TQUrlOperator. - - The rest of this descrption describes the direct interface to - HTTP. - - The class works asynchronously, so there are no blocking - functions. If an operation cannot be executed immediately, the - function will still return straight away and the operation will be - scheduled for later execution. The results of scheduled operations - are reported via Q_SIGNALS. This approach depends on the event loop - being in operation. - - The operations that can be scheduled (they are called "requests" - in the rest of the documentation) are the following: setHost(), - get(), post(), head() and request(). - - All of these requests return a unique identifier that allows you - to keep track of the request that is currently executed. When the - execution of a request starts, the requestStarted() signal with - the identifier is emitted and when the request is finished, the - requestFinished() signal is emitted with the identifier and a bool - that indicates if the request finished with an error. - - To make an HTTP request you must set up suitable HTTP headers. The - following example demonstrates, how to request the main HTML page - from the Trolltech home page (i.e. the URL - http://www.trolltech.com/index.html): - - \code - TQHttpRequestHeader header( "GET", "/index.html" ); - header.setValue( "Host", "www.trolltech.com" ); - http->setHost( "www.trolltech.com" ); - http->request( header ); - \endcode - - For the common HTTP requests \c GET, \c POST and \c HEAD, TQHttp - provides the convenience functions get(), post() and head(). They - already use a reasonable header and if you don't have to set - special header fields, they are easier to use. The above example - can also be written as: - - \code - http->setHost( "www.trolltech.com" ); // id == 1 - http->get( "/index.html" ); // id == 2 - \endcode - - For this example the following sequence of Q_SIGNALS is emitted - (with small variations, depending on network traffic, etc.): - - \code - requestStarted( 1 ) - requestFinished( 1, FALSE ) - - requestStarted( 2 ) - stateChanged( Connecting ) - stateChanged( Sending ) - dataSendProgress( 77, 77 ) - stateChanged( Reading ) - responseHeaderReceived( responseheader ) - dataReadProgress( 5388, 0 ) - readyRead( responseheader ) - dataReadProgress( 18300, 0 ) - readyRead( responseheader ) - stateChanged( Connected ) - requestFinished( 2, FALSE ) - - done( FALSE ) - - stateChanged( Closing ) - stateChanged( Unconnected ) - \endcode - - The dataSendProgress() and dataReadProgress() Q_SIGNALS in the above - example are useful if you want to show a \link TQProgressBar - progressbar\endlink to inform the user about the progress of the - download. The second argument is the total size of data. In - certain cases it is not possible to know the total amount in - advance, in which case the second argument is 0. (If you connect - to a TQProgressBar a total of 0 results in a busy indicator.) - - When the response header is read, it is reported with the - responseHeaderReceived() signal. - - The readyRead() signal tells you that there is data ready to be - read. The amount of data can then be queried with the - bytesAvailable() function and it can be read with the readBlock() - or readAll() functions. - - If an error occurs during the execution of one of the commands in - a sequence of commands, all the pending commands (i.e. scheduled, - but not yet executed commands) are cleared and no Q_SIGNALS are - emitted for them. - - For example, if you have the following sequence of reqeusts - - \code - http->setHost( "www.foo.bar" ); // id == 1 - http->get( "/index.html" ); // id == 2 - http->post( "register.html", data ); // id == 3 - \endcode - - and the get() request fails because the host lookup fails, then - the post() request is never executed and the Q_SIGNALS would look - like this: - - \code - requestStarted( 1 ) - requestFinished( 1, FALSE ) - - requestStarted( 2 ) - stateChanged( HostLookup ) - requestFinished( 2, TRUE ) - - done( TRUE ) - - stateChanged( Unconnected ) - \endcode - - You can then get details about the error with the error() and - errorString() functions. Note that only unexpected behaviour, like - network failure is considered as an error. If the server response - contains an error status, like a 404 response, this is reported as - a normal response case. So you should always check the \link - TQHttpResponseHeader::statusCode() status code \endlink of the - response header. - - The functions currentId() and currentRequest() provide more - information about the currently executing request. - - The functions hasPendingRequests() and clearPendingRequests() - allow you to query and clear the list of pending requests. - - \sa \link network.html TQt Network Documentation \endlink TQNetworkProtocol, TQUrlOperator TQFtp -*/ - -/*! - Constructs a TQHttp object. -*/ -TQHttp::TQHttp() -{ - init(); -} - -/*! - Constructs a TQHttp object. The parameters \a parent and \a name - are passed on to the TQObject constructor. -*/ -TQHttp::TQHttp( TQObject* parent, const char* name ) -{ - if ( parent ) - parent->insertChild( this ); - setName( name ); - init(); -} - -/*! - Constructs a TQHttp object. Subsequent requests are done by - connecting to the server \a hostname on port \a port. The - parameters \a parent and \a name are passed on to the TQObject - constructor. - - \sa setHost() -*/ -TQHttp::TQHttp( const TQString &hostname, TQ_UINT16 port, TQObject* parent, const char* name ) -{ - if ( parent ) - parent->insertChild( this ); - setName( name ); - init(); - - d->hostname = hostname; - d->port = port; -} - -void TQHttp::init() -{ - bytesRead = 0; - d = new TQHttpPrivate; - d->errorString = tr( "Unknown error" ); - - connect( &d->socket, TQT_SIGNAL( connected() ), - this, TQT_SLOT( slotConnected() ) ); - connect( &d->socket, TQT_SIGNAL( connectionClosed() ), - this, TQT_SLOT( slotClosed() ) ); - connect( &d->socket, TQT_SIGNAL( delayedCloseFinished() ), - this, TQT_SLOT( slotClosed() ) ); - connect( &d->socket, TQT_SIGNAL( readyRead() ), - this, TQT_SLOT( slotReadyRead() ) ); - connect( &d->socket, TQT_SIGNAL( error(int) ), - this, TQT_SLOT( slotError(int) ) ); - connect( &d->socket, TQT_SIGNAL( bytesWritten(int) ), - this, TQT_SLOT( slotBytesWritten(int) ) ); - - d->idleTimer = startTimer( 0 ); -} - -/*! - Destroys the TQHttp object. If there is an open connection, it is - closed. -*/ -TQHttp::~TQHttp() -{ - abort(); - delete d; -} - -/*! - \enum TQHttp::State - - This enum is used to specify the state the client is in: - - \value Unconnected There is no connection to the host. - \value HostLookup A host name lookup is in progress. - \value Connecting An attempt to connect to the host is in progress. - \value Sending The client is sending its request to the server. - \value Reading The client's request has been sent and the client - is reading the server's response. - \value Connected The connection to the host is open, but the client is - neither sending a request, nor waiting for a response. - \value Closing The connection is closing down, but is not yet - closed. (The state will be \c Unconnected when the connection is - closed.) - - \sa stateChanged() state() -*/ - -/*! \enum TQHttp::Error - - This enum identifies the error that occurred. - - \value NoError No error occurred. - \value HostNotFound The host name lookup failed. - \value ConnectionRefused The server refused the connection. - \value UnexpectedClose The server closed the connection unexpectedly. - \value InvalidResponseHeader The server sent an invalid response header. - \value WrongContentLength The client could not read the content correctly - because an error with respect to the content length occurred. - \value Aborted The request was aborted with abort(). - \value UnknownError An error other than those specified above - occurred. - - \sa error() -*/ - -/*! - \fn void TQHttp::stateChanged( int state ) - - This signal is emitted when the state of the TQHttp object changes. - The argument \a state is the new state of the connection; it is - one of the \l State values. - - This usually happens when a request is started, but it can also - happen when the server closes the connection or when a call to - closeConnection() succeeded. - - \sa get() post() head() request() closeConnection() state() State -*/ - -/*! - \fn void TQHttp::responseHeaderReceived( const TQHttpResponseHeader& resp ) - - This signal is emitted when the HTTP header of a server response - is available. The header is passed in \a resp. - - \sa get() post() head() request() readyRead() -*/ - -/*! - \fn void TQHttp::readyRead( const TQHttpResponseHeader& resp ) - - This signal is emitted when there is new response data to read. - - If you specified a tqdevice in the request where the data should be - written to, then this signal is \e not emitted; instead the data - is written directly to the tqdevice. - - The response header is passed in \a resp. - - You can read the data with the readAll() or readBlock() functions - - This signal is useful if you want to process the data in chunks as - soon as it becomes available. If you are only interested in the - complete data, just connect to the requestFinished() signal and - read the data then instead. - - \sa get() post() request() readAll() readBlock() bytesAvailable() -*/ - -/*! - \fn void TQHttp::dataSendProgress( int done, int total ) - - This signal is emitted when this object sends data to a HTTP - server to inform it about the progress of the upload. - - \a done is the amount of data that has already arrived and \a - total is the total amount of data. It is possible that the total - amount of data that should be transferred cannot be determined, in - which case \a total is 0.(If you connect to a TQProgressBar, the - progress bar shows a busy indicator if the total is 0). - - \warning \a done and \a total are not necessarily the size in - bytes, since for large files these values might need to be - "scaled" to avoid overflow. - - \sa dataReadProgress() post() request() TQProgressBar::setProgress() -*/ - -/*! - \fn void TQHttp::dataReadProgress( int done, int total ) - - This signal is emitted when this object reads data from a HTTP - server to indicate the current progress of the download. - - \a done is the amount of data that has already arrived and \a - total is the total amount of data. It is possible that the total - amount of data that should be transferred cannot be determined, in - which case \a total is 0.(If you connect to a TQProgressBar, the - progress bar shows a busy indicator if the total is 0). - - \warning \a done and \a total are not necessarily the size in - bytes, since for large files these values might need to be - "scaled" to avoid overflow. - - \sa dataSendProgress() get() post() request() TQProgressBar::setProgress() -*/ - -/*! - \fn void TQHttp::requestStarted( int id ) - - This signal is emitted when processing the request identified by - \a id starts. - - \sa requestFinished() done() -*/ - -/*! - \fn void TQHttp::requestFinished( int id, bool error ) - - This signal is emitted when processing the request identified by - \a id has finished. \a error is TRUE if an error occurred during - the processing; otherwise \a error is FALSE. - - \sa requestStarted() done() error() errorString() -*/ - -/*! - \fn void TQHttp::done( bool error ) - - This signal is emitted when the last pending request has finished; - (it is emitted after the last request's requestFinished() signal). - \a error is TRUE if an error occurred during the processing; - otherwise \a error is FALSE. - - \sa requestFinished() error() errorString() -*/ - -/*! - Aborts the current request and deletes all scheduled requests. - - For the current request, the requestFinished() signal with the \c - error argument \c TRUE is emitted. For all other requests that are - affected by the abort(), no Q_SIGNALS are emitted. - - Since this slot also deletes the scheduled requests, there are no - requests left and the done() signal is emitted (with the \c error - argument \c TRUE). - - \sa clearPendingRequests() -*/ -void TQHttp::abort() -{ - TQHttpRequest *r = d->pending.getFirst(); - if ( r == 0 ) - return; - - finishedWithError( tr("Request aborted"), Aborted ); - clearPendingRequests(); - d->socket.clearPendingData(); - close(); -} - -/*! - Returns the number of bytes that can be read from the response - content at the moment. - - \sa get() post() request() readyRead() readBlock() readAll() -*/ -TQ_ULONG TQHttp::bytesAvailable() const -{ -#if defined(TQHTTP_DEBUG) - qDebug( "TQHttp::bytesAvailable(): %d bytes", (int)d->rba.size() ); -#endif - return d->rba.size(); -} - -/*! - Reads \a maxlen bytes from the response content into \a data and - returns the number of bytes read. Returns -1 if an error occurred. - - \sa get() post() request() readyRead() bytesAvailable() readAll() -*/ -TQ_LONG TQHttp::readBlock( char *data, TQ_ULONG maxlen ) -{ - if ( data == 0 && maxlen != 0 ) { -#if defined(TQT_CHECK_NULL) - qWarning( "TQHttp::readBlock: Null pointer error" ); -#endif - return -1; - } - if ( maxlen >= d->rba.size() ) - maxlen = d->rba.size(); - d->rba.consumeBytes( maxlen, data ); - - d->bytesDone += maxlen; -#if defined(TQHTTP_DEBUG) - qDebug( "TQHttp::readBlock(): read %d bytes (%d bytes done)", (int)maxlen, d->bytesDone ); -#endif - return maxlen; -} - -/*! - Reads all the bytes from the response content and returns them. - - \sa get() post() request() readyRead() bytesAvailable() readBlock() -*/ -TQByteArray TQHttp::readAll() -{ - TQ_ULONG avail = bytesAvailable(); - TQByteArray tmp( avail ); - TQ_LONG read = readBlock( tmp.data(), avail ); - tmp.resize( read ); - return tmp; -} - -/*! - Returns the identifier of the HTTP request being executed or 0 if - there is no request being executed (i.e. they've all finished). - - \sa currentRequest() -*/ -int TQHttp::currentId() const -{ - TQHttpRequest *r = d->pending.getFirst(); - if ( r == 0 ) - return 0; - return r->id; -} - -/*! - Returns the request header of the HTTP request being executed. If - the request is one issued by setHost() or closeConnection(), it - returns an invalid request header, i.e. - TQHttpRequestHeader::isValid() returns FALSE. - - \sa currentId() -*/ -TQHttpRequestHeader TQHttp::currentRequest() const -{ - TQHttpRequest *r = d->pending.getFirst(); - if ( r != 0 && r->hasRequestHeader() ) - return r->requestHeader(); - return TQHttpRequestHeader(); -} - -/*! - Returns the TQIODevice pointer that is used as the data source of the HTTP - request being executed. If there is no current request or if the request - does not use an IO tqdevice as the data source, this function returns 0. - - This function can be used to delete the TQIODevice in the slot connected to - the requestFinished() signal. - - \sa currentDestinationDevice() post() request() -*/ -TQIODevice* TQHttp::currentSourceDevice() const -{ - TQHttpRequest *r = d->pending.getFirst(); - if ( !r ) - return 0; - return r->sourceDevice(); -} - -/*! - Returns the TQIODevice pointer that is used as to store the data of the HTTP - request being executed. If there is no current request or if the request - does not store the data to an IO tqdevice, this function returns 0. - - This function can be used to delete the TQIODevice in the slot connected to - the requestFinished() signal. - - \sa currentDestinationDevice() get() post() request() -*/ -TQIODevice* TQHttp::currentDestinationDevice() const -{ - TQHttpRequest *r = d->pending.getFirst(); - if ( !r ) - return 0; - return r->destinationDevice(); -} - -/*! - Returns TRUE if there are any requests scheduled that have not yet - been executed; otherwise returns FALSE. - - The request that is being executed is \e not considered as a - scheduled request. - - \sa clearPendingRequests() currentId() currentRequest() -*/ -bool TQHttp::hasPendingRequests() const -{ - return d->pending.count() > 1; -} - -/*! - Deletes all pending requests from the list of scheduled requests. - This does not affect the request that is being executed. If - you want to stop this this as well, use abort(). - - \sa hasPendingRequests() abort() -*/ -void TQHttp::clearPendingRequests() -{ - TQHttpRequest *r = 0; - if ( d->pending.count() > 0 ) - r = d->pending.take( 0 ); - d->pending.clear(); - if ( r ) - d->pending.append( r ); -} - -/*! - Sets the HTTP server that is used for requests to \a hostname on - port \a port. - - The function does not block and returns immediately. The request - is scheduled, and its execution is performed asynchronously. The - function returns a unique identifier which is passed by - requestStarted() and requestFinished(). - - When the request is started the requestStarted() signal is - emitted. When it is finished the requestFinished() signal is - emitted. - - \sa get() post() head() request() requestStarted() requestFinished() done() -*/ -int TQHttp::setHost(const TQString &hostname, TQ_UINT16 port ) -{ - return addRequest( new TQHttpSetHostRequest( hostname, port ) ); -} - -/*! - Sends a get request for \a path to the server set by setHost() or - as specified in the constructor. - - \a path must be an absolute path like \c /index.html or an - absolute URI like \c http://www.trolltech.com/index.html. - - If the IO tqdevice \a to is 0 the readyRead() signal is emitted - every time new content data is available to read. - - If the IO tqdevice \a to is not 0, the content data of the response - is written directly to the tqdevice. Make sure that the \a to - pointer is valid for the duration of the operation (it is safe to - delete it when the requestFinished() signal is emitted). - - The function does not block and returns immediately. The request - is scheduled, and its execution is performed asynchronously. The - function returns a unique identifier which is passed by - requestStarted() and requestFinished(). - - When the request is started the requestStarted() signal is - emitted. When it is finished the requestFinished() signal is - emitted. - - \sa setHost() post() head() request() requestStarted() requestFinished() done() -*/ -int TQHttp::get( const TQString& path, TQIODevice* to ) -{ - TQHttpRequestHeader header( "GET", path ); - header.setValue( "Connection", "Keep-Alive" ); - return addRequest( new TQHttpPGHRequest( header, (TQIODevice*)0, to ) ); -} - -/*! - Sends a post request for \a path to the server set by setHost() or - as specified in the constructor. - - \a path must be an absolute path like \c /index.html or an - absolute URI like \c http://www.trolltech.com/index.html. - - The incoming data comes via the \a data IO tqdevice. - - If the IO tqdevice \a to is 0 the readyRead() signal is emitted - every time new content data is available to read. - - If the IO tqdevice \a to is not 0, the content data of the response - is written directly to the tqdevice. Make sure that the \a to - pointer is valid for the duration of the operation (it is safe to - delete it when the requestFinished() signal is emitted). - - The function does not block and returns immediately. The request - is scheduled, and its execution is performed asynchronously. The - function returns a unique identifier which is passed by - requestStarted() and requestFinished(). - - When the request is started the requestStarted() signal is - emitted. When it is finished the requestFinished() signal is - emitted. - - \sa setHost() get() head() request() requestStarted() requestFinished() done() -*/ -int TQHttp::post( const TQString& path, TQIODevice* data, TQIODevice* to ) -{ - TQHttpRequestHeader header( "POST", path ); - header.setValue( "Connection", "Keep-Alive" ); - return addRequest( new TQHttpPGHRequest( header, data, to ) ); -} - -/*! - \overload - - \a data is used as the content data of the HTTP request. -*/ -int TQHttp::post( const TQString& path, const TQByteArray& data, TQIODevice* to ) -{ - TQHttpRequestHeader header( "POST", path ); - header.setValue( "Connection", "Keep-Alive" ); - return addRequest( new TQHttpPGHRequest( header, new TQByteArray(data), to ) ); -} - -/*! - Sends a header request for \a path to the server set by setHost() - or as specified in the constructor. - - \a path must be an absolute path like \c /index.html or an - absolute URI like \c http://www.trolltech.com/index.html. - - The function does not block and returns immediately. The request - is scheduled, and its execution is performed asynchronously. The - function returns a unique identifier which is passed by - requestStarted() and requestFinished(). - - When the request is started the requestStarted() signal is - emitted. When it is finished the requestFinished() signal is - emitted. - - \sa setHost() get() post() request() requestStarted() requestFinished() done() -*/ -int TQHttp::head( const TQString& path ) -{ - TQHttpRequestHeader header( "HEAD", path ); - header.setValue( "Connection", "Keep-Alive" ); - return addRequest( new TQHttpPGHRequest( header, (TQIODevice*)0, 0 ) ); -} - -/*! - Sends a request to the server set by setHost() or as specified in - the constructor. Uses the \a header as the HTTP request header. - You are responsible for setting up a header that is appropriate - for your request. - - The incoming data comes via the \a data IO tqdevice. - - If the IO tqdevice \a to is 0 the readyRead() signal is emitted - every time new content data is available to read. - - If the IO tqdevice \a to is not 0, the content data of the response - is written directly to the tqdevice. Make sure that the \a to - pointer is valid for the duration of the operation (it is safe to - delete it when the requestFinished() signal is emitted). - - The function does not block and returns immediately. The request - is scheduled, and its execution is performed asynchronously. The - function returns a unique identifier which is passed by - requestStarted() and requestFinished(). - - When the request is started the requestStarted() signal is - emitted. When it is finished the requestFinished() signal is - emitted. - - \sa setHost() get() post() head() requestStarted() requestFinished() done() -*/ -int TQHttp::request( const TQHttpRequestHeader &header, TQIODevice *data, TQIODevice *to ) -{ - return addRequest( new TQHttpNormalRequest( header, data, to ) ); -} - -/*! - \overload - - \a data is used as the content data of the HTTP request. -*/ -int TQHttp::request( const TQHttpRequestHeader &header, const TQByteArray &data, TQIODevice *to ) -{ - return addRequest( new TQHttpNormalRequest( header, new TQByteArray(data), to ) ); -} - -/*! - Closes the connection; this is useful if you have a keep-alive - connection and want to close it. - - For the requests issued with get(), post() and head(), TQHttp sets - the connection to be keep-alive. You can also do this using the - header you pass to the request() function. TQHttp only closes the - connection to the HTTP server if the response header requires it - to do so. - - The function does not block and returns immediately. The request - is scheduled, and its execution is performed asynchronously. The - function returns a unique identifier which is passed by - requestStarted() and requestFinished(). - - When the request is started the requestStarted() signal is - emitted. When it is finished the requestFinished() signal is - emitted. - - If you want to close the connection immediately, you have to use - abort() instead. - - \sa stateChanged() abort() requestStarted() requestFinished() done() -*/ -int TQHttp::closeConnection() -{ - return addRequest( new TQHttpCloseRequest() ); -} - -int TQHttp::addRequest( TQHttpRequest *req ) -{ - d->pending.append( req ); - - if ( d->pending.count() == 1 ) - // don't emit the requestStarted() signal before the id is returned - TQTimer::singleShot( 0, this, TQT_SLOT(startNextRequest()) ); - - return req->id; -} - -void TQHttp::startNextRequest() -{ - TQHttpRequest *r = d->pending.getFirst(); - if ( r == 0 ) - return; - - d->error = NoError; - d->errorString = tr( "Unknown error" ); - - if ( bytesAvailable() ) - readAll(); // clear the data - emit requestStarted( r->id ); - r->start( this ); -} - -void TQHttp::sendRequest() -{ - if ( d->hostname.isNull() ) { - finishedWithError( tr("No server set to connect to"), UnknownError ); - return; - } - - killIdleTimer(); - - // Do we need to setup a new connection or can we reuse an - // existing one ? - if ( d->socket.peerName() != d->hostname || d->socket.peerPort() != d->port - || d->socket.state() != TQSocket::Connection ) { - setState( TQHttp::Connecting ); - d->socket.connectToHost( d->hostname, d->port ); - } else { - slotConnected(); - } - -} - -void TQHttp::finishedWithSuccess() -{ - TQHttpRequest *r = d->pending.getFirst(); - if ( r == 0 ) - return; - - emit requestFinished( r->id, FALSE ); - d->pending.removeFirst(); - if ( d->pending.isEmpty() ) { - emit done( FALSE ); - } else { - startNextRequest(); - } -} - -void TQHttp::finishedWithError( const TQString& detail, int errorCode ) -{ - TQHttpRequest *r = d->pending.getFirst(); - if ( r == 0 ) - return; - - d->error = (Error)errorCode; - d->errorString = detail; - emit requestFinished( r->id, TRUE ); - - d->pending.clear(); - emit done( TRUE ); -} - -void TQHttp::slotClosed() -{ - if ( d->state == Closing ) - return; - - if ( d->state == Reading ) { - if ( d->response.hasKey( "content-length" ) ) { - // We got Content-Length, so did we get all bytes? - if ( d->bytesDone+bytesAvailable() != d->response.contentLength() ) { - finishedWithError( tr("Wrong content length"), WrongContentLength ); - } - } - } else if ( d->state == Connecting || d->state == Sending ) { - finishedWithError( tr("Server closed connection unexpectedly"), UnexpectedClose ); - } - - d->postDevice = 0; - setState( Closing ); - d->idleTimer = startTimer( 0 ); -} - -void TQHttp::slotConnected() -{ - if ( d->state != Sending ) { - d->bytesDone = 0; - setState( Sending ); - } - - TQString str = d->header.toString(); - d->bytesTotal = str.length(); - d->socket.writeBlock( str.latin1(), d->bytesTotal ); -#if defined(TQHTTP_DEBUG) - qDebug( "TQHttp: write request header:\n---{\n%s}---", str.latin1() ); -#endif - - if ( d->postDevice ) { - d->bytesTotal += d->postDevice->size(); - } else { - d->bytesTotal += d->buffer.size(); - d->socket.writeBlock( d->buffer.data(), d->buffer.size() ); - d->buffer = TQByteArray(); // save memory - } -} - -void TQHttp::slotError( int err ) -{ - d->postDevice = 0; - - if ( d->state == Connecting || d->state == Reading || d->state == Sending ) { - switch ( err ) { - case TQSocket::ErrConnectionRefused: - finishedWithError( tr("Connection refused"), ConnectionRefused ); - break; - case TQSocket::ErrHostNotFound: - finishedWithError( tr("Host %1 not found").arg(d->socket.peerName()), HostNotFound ); - break; - default: - finishedWithError( tr("HTTP request failed"), UnknownError ); - break; - } - } - - close(); -} - -void TQHttp::slotBytesWritten( int written ) -{ - d->bytesDone += written; - emit dataSendProgress( d->bytesDone, d->bytesTotal ); - - if ( !d->postDevice ) - return; - - if ( d->socket.bytesToWrite() == 0 ) { - int max = TQMIN( 4096, d->postDevice->size() - d->postDevice->at() ); - TQByteArray arr( max ); - - int n = d->postDevice->readBlock( arr.data(), max ); - if ( n != max ) { - qWarning("Could not read enough bytes from the tqdevice"); - close(); - return; - } - if ( d->postDevice->atEnd() ) { - d->postDevice = 0; - } - - d->socket.writeBlock( arr.data(), max ); - } -} - -void TQHttp::slotReadyRead() -{ - if ( d->state != Reading ) { - setState( Reading ); - d->buffer = TQByteArray(); - d->readHeader = TRUE; - d->headerStr = ""; - d->bytesDone = 0; - d->chunkedSize = -1; - } - - while ( d->readHeader ) { - bool end = FALSE; - TQString tmp; - while ( !end && d->socket.canReadLine() ) { - tmp = d->socket.readLine(); - if ( tmp == "\r\n" || tmp == "\n" ) - end = TRUE; - else - d->headerStr += tmp; - } - - if ( !end ) - return; - -#if defined(TQHTTP_DEBUG) - qDebug( "TQHttp: read response header:\n---{\n%s}---", d->headerStr.latin1() ); -#endif - d->response = TQHttpResponseHeader( d->headerStr ); - d->headerStr = ""; -#if defined(TQHTTP_DEBUG) - qDebug( "TQHttp: read response header:\n---{\n%s}---", d->response.toString().latin1() ); -#endif - // Check header - if ( !d->response.isValid() ) { - finishedWithError( tr("Invalid HTTP response header"), InvalidResponseHeader ); - close(); - return; - } - - // The 100-continue header is ignored, because when using the - // POST method, we send both the request header and data in - // one chunk. - if (d->response.statusCode() != 100) { - d->readHeader = FALSE; - if ( d->response.hasKey( "transfer-encoding" ) && - d->response.value( "transfer-encoding" ).lower().contains( "chunked" ) ) - d->chunkedSize = 0; - - emit responseHeaderReceived( d->response ); - } - } - - if ( !d->readHeader ) { - bool everythingRead = FALSE; - - if ( currentRequest().method() == "HEAD" ) { - everythingRead = TRUE; - } else { - TQ_ULONG n = d->socket.bytesAvailable(); - TQByteArray *arr = 0; - if ( d->chunkedSize != -1 ) { - // transfer-encoding is chunked - for ( ;; ) { - // get chunk size - if ( d->chunkedSize == 0 ) { - if ( !d->socket.canReadLine() ) - break; - TQString sizeString = d->socket.readLine(); - int tPos = sizeString.find( ';' ); - if ( tPos != -1 ) - sizeString.truncate( tPos ); - bool ok; - d->chunkedSize = sizeString.toInt( &ok, 16 ); - if ( !ok ) { - finishedWithError( tr("Invalid HTTP chunked body"), WrongContentLength ); - close(); - delete arr; - return; - } - if ( d->chunkedSize == 0 ) // last-chunk - d->chunkedSize = -2; - } - - // read trailer - while ( d->chunkedSize == -2 && d->socket.canReadLine() ) { - TQString read = d->socket.readLine(); - if ( read == "\r\n" || read == "\n" ) - d->chunkedSize = -1; - } - if ( d->chunkedSize == -1 ) { - everythingRead = TRUE; - break; - } - - // make sure that you can read the terminating CRLF, - // otherwise wait until next time... - n = d->socket.bytesAvailable(); - if ( n == 0 ) - break; - if ( (TQ_LONG)n == d->chunkedSize || (TQ_LONG)n == d->chunkedSize+1 ) { - n = d->chunkedSize - 1; - if ( n == 0 ) - break; - } - - // read data - uint toRead = TQMIN( (TQ_LONG)n, (d->chunkedSize < 0 ? (TQ_LONG)n : d->chunkedSize) ); - if ( !arr ) - arr = new TQByteArray( 0 ); - uint oldArrSize = arr->size(); - arr->resize( oldArrSize + toRead ); - TQ_LONG read = d->socket.readBlock( arr->data()+oldArrSize, toRead ); - arr->resize( oldArrSize + read ); - - d->chunkedSize -= read; - - if ( d->chunkedSize == 0 && n - read >= 2 ) { - // read terminating CRLF - char tmp[2]; - d->socket.readBlock( tmp, 2 ); - if ( tmp[0] != '\r' || tmp[1] != '\n' ) { - finishedWithError( tr("Invalid HTTP chunked body"), WrongContentLength ); - close(); - return; - } - } - } - } else if ( d->response.hasContentLength() ) { - n = TQMIN( d->response.contentLength() - d->bytesDone, n ); - if ( n > 0 ) { - arr = new TQByteArray( n ); - TQ_LONG read = d->socket.readBlock( arr->data(), n ); - arr->resize( read ); - } - if ( d->bytesDone + bytesAvailable() + n == d->response.contentLength() ) - everythingRead = TRUE; - } else if ( n > 0 ) { - // workaround for VC++ bug - TQByteArray temp = TQT_TQBYTEARRAY_OBJECT(d->socket.readAll()); - arr = new TQByteArray( temp ); - } - - if ( arr ) { - n = arr->size(); - if ( d->toDevice ) { - d->toDevice->writeBlock( arr->data(), n ); - delete arr; - d->bytesDone += n; -#if defined(TQHTTP_DEBUG) - qDebug( "TQHttp::slotReadyRead(): read %ld bytes (%d bytes done)", n, d->bytesDone ); -#endif - if ( d->response.hasContentLength() ) - emit dataReadProgress( d->bytesDone, d->response.contentLength() ); - else - emit dataReadProgress( d->bytesDone, 0 ); - } else { - d->rba.append( arr ); -#if defined(TQHTTP_DEBUG) - qDebug( "TQHttp::slotReadyRead(): read %ld bytes (%ld bytes done)", n, d->bytesDone + bytesAvailable() ); -#endif - if ( d->response.hasContentLength() ) - emit dataReadProgress( d->bytesDone + bytesAvailable(), d->response.contentLength() ); - else - emit dataReadProgress( d->bytesDone + bytesAvailable(), 0 ); - emit readyRead( d->response ); - } - } - } - - if ( everythingRead ) { - // Handle "Connection: close" - if ( d->response.value("connection").lower() == "close" ) { - close(); - } else { - setState( Connected ); - // Start a timer, so that we emit the keep alive signal - // "after" this method returned. - d->idleTimer = startTimer( 0 ); - } - } - } -} - -/*! - Returns the current state of the object. When the state changes, - the stateChanged() signal is emitted. - - \sa State stateChanged() -*/ -TQHttp::State TQHttp::state() const -{ - return d->state; -} - -/*! - Returns the last error that occurred. This is useful to find out - what happened when receiving a requestFinished() or a done() - signal with the \c error argument \c TRUE. - - If you start a new request, the error status is reset to \c NoError. -*/ -TQHttp::Error TQHttp::error() const -{ - return d->error; -} - -/*! - Returns a human-readable description of the last error that - occurred. This is useful to present a error message to the user - when receiving a requestFinished() or a done() signal with the \c - error argument \c TRUE. -*/ -TQString TQHttp::errorString() const -{ - return d->errorString; -} - -/*! \reimp -*/ -void TQHttp::timerEvent( TQTimerEvent *e ) -{ - if ( e->timerId() == d->idleTimer ) { - killTimer( d->idleTimer ); - d->idleTimer = 0; - - if ( d->state == Connected ) { - finishedWithSuccess(); - } else if ( d->state != Unconnected ) { - setState( Unconnected ); - finishedWithSuccess(); - } - } else { - TQObject::timerEvent( e ); - } -} - -void TQHttp::killIdleTimer() -{ - killTimer( d->idleTimer ); - d->idleTimer = 0; -} - -void TQHttp::setState( int s ) -{ -#if defined(TQHTTP_DEBUG) - qDebug( "TQHttp state changed %d -> %d", d->state, s ); -#endif - d->state = (State)s; - emit stateChanged( s ); -} - -void TQHttp::close() -{ - // If no connection is open -> ignore - if ( d->state == Closing || d->state == Unconnected ) - return; - - d->postDevice = 0; - setState( Closing ); - - // Already closed ? - if ( !d->socket.isOpen() ) { - d->idleTimer = startTimer( 0 ); - } else { - // Close now. - d->socket.close(); - - // Did close succeed immediately ? - if ( d->socket.state() == TQSocket::Idle ) { - // Prepare to emit the requestFinished() signal. - d->idleTimer = startTimer( 0 ); - } - } -} - -/********************************************************************** - * - * TQHttp implementation of the TQNetworkProtocol interface - * - *********************************************************************/ -/*! \reimp -*/ -int TQHttp::supportedOperations() const -{ - return OpGet | OpPut; -} - -/*! \reimp -*/ -void TQHttp::operationGet( TQNetworkOperation *op ) -{ - connect( this, TQT_SIGNAL(readyRead(const TQHttpResponseHeader&)), - this, TQT_SLOT(clientReply(const TQHttpResponseHeader&)) ); - connect( this, TQT_SIGNAL(done(bool)), - this, TQT_SLOT(clientDone(bool)) ); - connect( this, TQT_SIGNAL(stateChanged(int)), - this, TQT_SLOT(clientStateChanged(int)) ); - - bytesRead = 0; - op->setState( StInProgress ); - TQUrl u( operationInProgress()->arg( 0 ) ); - TQHttpRequestHeader header( "GET", u.encodedPathAndQuery(), 1, 0 ); - header.setValue( "Host", u.host() ); - setHost( u.host(), u.port() != -1 ? u.port() : 80 ); - request( header ); -} - -/*! \reimp -*/ -void TQHttp::operationPut( TQNetworkOperation *op ) -{ - connect( this, TQT_SIGNAL(readyRead(const TQHttpResponseHeader&)), - this, TQT_SLOT(clientReply(const TQHttpResponseHeader&)) ); - connect( this, TQT_SIGNAL(done(bool)), - this, TQT_SLOT(clientDone(bool)) ); - connect( this, TQT_SIGNAL(stateChanged(int)), - this, TQT_SLOT(clientStateChanged(int)) ); - - bytesRead = 0; - op->setState( StInProgress ); - TQUrl u( operationInProgress()->arg( 0 ) ); - TQHttpRequestHeader header( "POST", u.encodedPathAndQuery(), 1, 0 ); - header.setValue( "Host", u.host() ); - setHost( u.host(), u.port() != -1 ? u.port() : 80 ); - request( header, op->rawArg(1) ); -} - -void TQHttp::clientReply( const TQHttpResponseHeader &rep ) -{ - TQNetworkOperation *op = operationInProgress(); - if ( op ) { - if ( rep.statusCode() >= 400 && rep.statusCode() < 600 ) { - op->setState( StFailed ); - op->setProtocolDetail( - TQString("%1 %2").arg(rep.statusCode()).arg(rep.reasonPhrase()) - ); - switch ( rep.statusCode() ) { - case 401: - case 403: - case 405: - op->setErrorCode( ErrPermissionDenied ); - break; - case 404: - op->setErrorCode(ErrFileNotExisting ); - break; - default: - if ( op->operation() == OpGet ) - op->setErrorCode( ErrGet ); - else - op->setErrorCode( ErrPut ); - break; - } - } - // ### In cases of an error, should we still emit the data() Q_SIGNALS? - if ( op->operation() == OpGet && bytesAvailable() > 0 ) { - TQByteArray ba = readAll(); - emit data( ba, op ); - bytesRead += ba.size(); - if ( rep.hasContentLength() ) { - emit dataTransferProgress( bytesRead, rep.contentLength(), op ); - } - } - } -} - -void TQHttp::clientDone( bool err ) -{ - disconnect( this, TQT_SIGNAL(readyRead(const TQHttpResponseHeader&)), - this, TQT_SLOT(clientReply(const TQHttpResponseHeader&)) ); - disconnect( this, TQT_SIGNAL(done(bool)), - this, TQT_SLOT(clientDone(bool)) ); - disconnect( this, TQT_SIGNAL(stateChanged(int)), - this, TQT_SLOT(clientStateChanged(int)) ); - - if ( err ) { - TQNetworkOperation *op = operationInProgress(); - if ( op ) { - op->setState( TQNetworkProtocol::StFailed ); - op->setProtocolDetail( errorString() ); - switch ( error() ) { - case ConnectionRefused: - op->setErrorCode( ErrHostNotFound ); - break; - case HostNotFound: - op->setErrorCode( ErrHostNotFound ); - break; - default: - if ( op->operation() == OpGet ) - op->setErrorCode( ErrGet ); - else - op->setErrorCode( ErrPut ); - break; - } - emit finished( op ); - } - } else { - TQNetworkOperation *op = operationInProgress(); - if ( op ) { - if ( op->state() != StFailed ) { - op->setState( TQNetworkProtocol::StDone ); - op->setErrorCode( TQNetworkProtocol::NoError ); - } - emit finished( op ); - } - } - -} - -void TQHttp::clientStateChanged( int state ) -{ - if ( url() ) { - switch ( (State)state ) { - case Connecting: - emit connectionStateChanged( ConHostFound, tr( "Host %1 found" ).arg( url()->host() ) ); - break; - case Sending: - emit connectionStateChanged( ConConnected, tr( "Connected to host %1" ).arg( url()->host() ) ); - break; - case Unconnected: - emit connectionStateChanged( ConClosed, tr( "Connection to %1 closed" ).arg( url()->host() ) ); - break; - default: - break; - } - } else { - switch ( (State)state ) { - case Connecting: - emit connectionStateChanged( ConHostFound, tr( "Host found" ) ); - break; - case Sending: - emit connectionStateChanged( ConConnected, tr( "Connected to host" ) ); - break; - case Unconnected: - emit connectionStateChanged( ConClosed, tr( "Connection closed" ) ); - break; - default: - break; - } - } -} - -#endif diff --git a/tqtinterface/qt4/src/network/tqhttp.h b/tqtinterface/qt4/src/network/tqhttp.h deleted file mode 100644 index fb20d4f..0000000 --- a/tqtinterface/qt4/src/network/tqhttp.h +++ /dev/null @@ -1,278 +0,0 @@ -/**************************************************************************** -** -** Definition of TQHttp and related classes. -** -** Created : 970521 -** -** Copyright (C) 1997-2008 Trolltech ASA. All rights reserved. -** -** This file is part of the network module of the TQt 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 TQt 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.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** 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. -** -**********************************************************************/ - -#ifndef TQHTTP_H -#define TQHTTP_H - -#ifndef TQT_H -#include "tqobject.h" -#include "tqnetworkprotocol.h" -#include "tqstringlist.h" -#endif // TQT_H - -#if !defined( TQT_MODULE_NETWORK ) || defined( TQT_LICENSE_PROFESSIONAL ) || defined( TQT_INTERNAL_NETWORK ) -#define TQM_EXPORT_HTTP -#define TQM_TEMPLATE_EXTERN_HTTP -#else -#define TQM_EXPORT_HTTP TQ_EXPORT -#define TQM_TEMPLATE_EXTERN_HTTP TQ_TEMPLATE_EXTERN -#endif - -#ifndef TQT_NO_NETWORKPROTOCOL_HTTP - -class TQSocket; -class TQTimerEvent; -class TQTextStream; -class TQIODevice; - -class TQHttpPrivate; -class TQHttpRequest; - -class TQM_EXPORT_HTTP TQHttpHeader -{ -public: - TQHttpHeader(); - TQHttpHeader( const TQHttpHeader& header ); - TQHttpHeader( const TQString& str ); - virtual ~TQHttpHeader(); - - TQHttpHeader& operator=( const TQHttpHeader& h ); - - TQString value( const TQString& key ) const; - void setValue( const TQString& key, const TQString& value ); - void removeValue( const TQString& key ); - - TQStringList keys() const; - bool hasKey( const TQString& key ) const; - - bool hasContentLength() const; - uint contentLength() const; - void setContentLength( int len ); - - bool hasContentType() const; - TQString contentType() const; - void setContentType( const TQString& type ); - - virtual TQString toString() const; - bool isValid() const; - - virtual int majorVersion() const = 0; - virtual int minorVersion() const = 0; - -protected: - virtual bool parseLine( const TQString& line, int number ); - bool parse( const TQString& str ); - void setValid( bool ); - -private: - TQMap values; - bool valid; -}; - -class TQM_EXPORT_HTTP TQHttpResponseHeader : public TQHttpHeader -{ -private: - TQHttpResponseHeader( int code, const TQString& text = TQString::null, int majorVer = 1, int minorVer = 1 ); - TQHttpResponseHeader( const TQString& str ); - - void setqStatusLine( int code, const TQString& text = TQString::null, int majorVer = 1, int minorVer = 1 ); - -public: - TQHttpResponseHeader(); - TQHttpResponseHeader( const TQHttpResponseHeader& header ); - - int statusCode() const; - TQString reasonPhrase() const; - - int majorVersion() const; - int minorVersion() const; - - TQString toString() const; - -protected: - bool parseLine( const TQString& line, int number ); - -private: - int statCode; - TQString reasonPhr; - int majVer; - int minVer; - - friend class TQHttp; -}; - -class TQM_EXPORT_HTTP TQHttpRequestHeader : public TQHttpHeader -{ -public: - TQHttpRequestHeader(); - TQHttpRequestHeader( const TQString& method, const TQString& path, int majorVer = 1, int minorVer = 1 ); - TQHttpRequestHeader( const TQHttpRequestHeader& header ); - TQHttpRequestHeader( const TQString& str ); - - void setRequest( const TQString& method, const TQString& path, int majorVer = 1, int minorVer = 1 ); - - TQString method() const; - TQString path() const; - - int majorVersion() const; - int minorVersion() const; - - TQString toString() const; - -protected: - bool parseLine( const TQString& line, int number ); - -private: - TQString m; - TQString p; - int majVer; - int minVer; -}; - -class TQM_EXPORT_HTTP TQHttp : public TQNetworkProtocol -{ - Q_OBJECT - TQ_OBJECT - -public: - TQHttp(); - TQHttp( TQObject* parent, const char* name = 0 ); // ### TQt 4.0: make parent=0 and get rid of the TQHttp() constructor - TQHttp( const TQString &hostname, TQ_UINT16 port=80, TQObject* parent=0, const char* name = 0 ); - virtual ~TQHttp(); - - int supportedOperations() const; - - enum State { Unconnected, HostLookup, Connecting, Sending, Reading, Connected, Closing }; - enum Error { - NoError, - UnknownError, - HostNotFound, - ConnectionRefused, - UnexpectedClose, - InvalidResponseHeader, - WrongContentLength, - Aborted - }; - - int setHost(const TQString &hostname, TQ_UINT16 port=80 ); - - int get( const TQString& path, TQIODevice* to=0 ); - int post( const TQString& path, TQIODevice* data, TQIODevice* to=0 ); - int post( const TQString& path, const TQByteArray& data, TQIODevice* to=0 ); - int head( const TQString& path ); - int request( const TQHttpRequestHeader &header, TQIODevice *tqdevice=0, TQIODevice *to=0 ); - int request( const TQHttpRequestHeader &header, const TQByteArray &data, TQIODevice *to=0 ); - - int closeConnection(); - - TQ_ULONG bytesAvailable() const; - TQ_LONG readBlock( char *data, TQ_ULONG maxlen ); - TQByteArray readAll(); - - int currentId() const; - TQIODevice* currentSourceDevice() const; - TQIODevice* currentDestinationDevice() const; - TQHttpRequestHeader currentRequest() const; - bool hasPendingRequests() const; - void clearPendingRequests(); - - State state() const; - - Error error() const; - TQString errorString() const; - -public Q_SLOTS: - void abort(); - -Q_SIGNALS: - void stateChanged( int ); - void responseHeaderReceived( const TQHttpResponseHeader& resp ); - void readyRead( const TQHttpResponseHeader& resp ); - void dataSendProgress( int, int ); - void dataReadProgress( int, int ); - - void requestStarted( int ); - void requestFinished( int, bool ); - void done( bool ); - -protected: - void operationGet( TQNetworkOperation *op ); - void operationPut( TQNetworkOperation *op ); - - void timerEvent( TQTimerEvent * ); - -private Q_SLOTS: - void clientReply( const TQHttpResponseHeader &rep ); - void clientDone( bool ); - void clientStateChanged( int ); - - void startNextRequest(); - void slotReadyRead(); - void slotConnected(); - void slotError( int ); - void slotClosed(); - void slotBytesWritten( int ); - -private: - TQHttpPrivate *d; - void *unused; // ### TQt 4.0: remove this (in for binary compatibility) - int bytesRead; - - int addRequest( TQHttpRequest * ); - void sendRequest(); - void finishedWithSuccess(); - void finishedWithError( const TQString& detail, int errorCode ); - - void killIdleTimer(); - - void init(); - void setState( int ); - void close(); - - friend class TQHttpNormalRequest; - friend class TQHttpSetHostRequest; - friend class TQHttpCloseRequest; - friend class TQHttpPGHRequest; -}; - -#define TQ_DEFINED_TQHTTP -#include "tqwinexport.h" -#endif -#endif diff --git a/tqtinterface/qt4/src/network/tqnetwork.cpp b/tqtinterface/qt4/src/network/tqnetwork.cpp deleted file mode 100644 index 14cdda5..0000000 --- a/tqtinterface/qt4/src/network/tqnetwork.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/**************************************************************************** -** -** Implementation of qInitNetworkProtocols function. -** -** Created : 970521 -** -** Copyright (C) 2010 Timothy Pearson and (C) 1992-2008 Trolltech ASA. -** -** This file is part of the network module of the TQt 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 TQt 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.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** 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 "tqnetwork.h" - -#ifndef TQT_NO_NETWORK - -#include "tqnetworkprotocol.h" - -// protocols -#include "tqftp.h" -#include "tqhttp.h" - -/*! \file tqnetwork.h */ -/*! - \relates TQUrlOperator - - This function registers the network protocols for FTP and HTTP. - You must call this function before you use TQUrlOperator for - these protocols. - - This function is declared in \l tqnetwork.h. -*/ -void qInitNetworkProtocols() -{ -#ifndef TQT_NO_NETWORKPROTOCOL_FTP - TQNetworkProtocol::registerNetworkProtocol( "ftp", new TQNetworkProtocolFactory< TQFtp > ); -#endif -#ifndef TQT_NO_NETWORKPROTOCOL_HTTP - TQNetworkProtocol::registerNetworkProtocol( "http", new TQNetworkProtocolFactory< TQHttp > ); -#endif -} - -#endif // TQT_NO_NETWORK diff --git a/tqtinterface/qt4/src/network/tqnetwork.h b/tqtinterface/qt4/src/network/tqnetwork.h deleted file mode 100644 index 131f40f..0000000 --- a/tqtinterface/qt4/src/network/tqnetwork.h +++ /dev/null @@ -1,60 +0,0 @@ -/**************************************************************************** -** -** Definition of qInitNetworkProtocols function. -** -** Created : 970521 -** -** Copyright (C) 2010 Timothy Pearson and (C) 1992-2008 Trolltech ASA. -** -** This file is part of the network module of the TQt 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 TQt 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.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** 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. -** -**********************************************************************/ - -#ifndef TQNETWORK_H -#define TQNETWORK_H - -#ifndef TQT_H -#include "tqglobal.h" -#endif // TQT_H - -#if !defined( TQT_MODULE_NETWORK ) || defined( TQT_LICENSE_PROFESSIONAL ) || defined( TQT_INTERNAL_NETWORK ) -#define TQM_EXPORT_NETWORK -#else -#define TQM_EXPORT_NETWORK TQ_EXPORT -#endif - -#ifndef TQT_NO_NETWORK - -TQM_EXPORT_NETWORK void qInitNetworkProtocols(); - -#endif - -#endif diff --git a/tqtinterface/qt4/src/network/tqserversocket.cpp b/tqtinterface/qt4/src/network/tqserversocket.cpp deleted file mode 100644 index 02a15b0..0000000 --- a/tqtinterface/qt4/src/network/tqserversocket.cpp +++ /dev/null @@ -1,297 +0,0 @@ -/**************************************************************************** -** -** Implementation of TQServerSocket class. -** -** Created : 970521 -** -** Copyright (C) 2010 Timothy Pearson and (C) 1992-2008 Trolltech ASA. -** -** This file is part of the network module of the TQt 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 TQt 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.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** 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 "tqserversocket.h" - -#ifndef TQT_NO_NETWORK - -#include "tqsocketnotifier.h" - -class TQServerSocketPrivate { -public: - TQServerSocketPrivate(): s(0), n(0) {} - ~TQServerSocketPrivate() { delete n; delete s; } - TQSocketDevice *s; - TQSocketNotifier *n; -}; - - -/*! - \class TQServerSocket tqserversocket.h - \brief The TQServerSocket class provides a TCP-based server. -\if defined(commercial) - It is part of the TQt Enterprise Edition. -\endif - - \ingroup io - \module network - - This class is a convenience class for accepting incoming TCP - connections. You can specify the port or have TQServerSocket pick - one, and listen on just one address or on all the machine's - addresses. - - Using the API is very simple: subclass TQServerSocket, call the - constructor of your choice, and implement newConnection() to - handle new incoming connections. There is nothing more to do. - - (Note that due to lack of support in the underlying APIs, - TQServerSocket cannot accept or reject connections conditionally.) - - \sa TQSocket, TQSocketDevice, TQHostAddress, TQSocketNotifier -*/ - - -/*! - Creates a server socket object, that will serve the given \a port - on all the addresses of this host. If \a port is 0, TQServerSocket - will pick a suitable port in a system-dependent manner. Use \a - backlog to specify how many pending connections the server can - have. - - The \a parent and \a name arguments are passed on to the TQObject - constructor. - - \warning On Tru64 Unix systems a value of 0 for \a backlog means - that you don't accept any connections at all; you should specify a - value larger than 0. -*/ - -TQServerSocket::TQServerSocket( TQ_UINT16 port, int backlog, - TQObject *parent, const char *name ) - : TQObject( parent, name ) -{ - d = new TQServerSocketPrivate; - init( TQHostAddress(), port, backlog ); -} - - -/*! - Creates a server socket object, that will serve the given \a port - only on the given \a address. Use \a backlog to specify how many - pending connections the server can have. - - The \a parent and \a name arguments are passed on to the TQObject - constructor. - - \warning On Tru64 Unix systems a value of 0 for \a backlog means - that you don't accept any connections at all; you should specify a - value larger than 0. -*/ - -TQServerSocket::TQServerSocket( const TQHostAddress & address, TQ_UINT16 port, - int backlog, - TQObject *parent, const char *name ) - : TQObject( parent, name ) -{ - d = new TQServerSocketPrivate; - init( address, port, backlog ); -} - - -/*! - Construct an empty server socket. - - This constructor, in combination with setSocket(), allows us to - use the TQServerSocket class as a wrapper for other socket types - (e.g. Unix Domain Sockets under Unix). - - The \a parent and \a name arguments are passed on to the TQObject - constructor. - - \sa setSocket() -*/ - -TQServerSocket::TQServerSocket( TQObject *parent, const char *name ) - : TQObject( parent, name ) -{ - d = new TQServerSocketPrivate; -} - - -/*! - Returns TRUE if the construction succeeded; otherwise returns FALSE. -*/ -bool TQServerSocket::ok() const -{ - return !!d->s; -} - -/* - The common bit of the constructors. - */ -void TQServerSocket::init( const TQHostAddress & address, TQ_UINT16 port, int backlog ) -{ - d->s = new TQSocketDevice( TQSocketDevice::Stream, address.isIPv4Address() - ? TQSocketDevice::IPv4 : TQSocketDevice::IPv6, 0 ); -#if !defined(TQ_OS_WIN32) - // Under Unix, we want to be able to use the port, even if a socket on the - // same address-port is in TIME_WAIT. Under Windows this is possible anyway - // -- furthermore, the meaning of reusable is different: it means that you - // can use the same address-port for multiple listening sockets. - d->s->setAddressReusable( TRUE ); -#endif - if ( d->s->bind( address, port ) - && d->s->listen( backlog ) ) - { - d->n = new TQSocketNotifier( d->s->socket(), TQSocketNotifier::Read, - this, "accepting new connections" ); - connect( d->n, TQT_SIGNAL(activated(int)), - this, TQT_SLOT(incomingConnection(int)) ); - } else { - qWarning( "TQServerSocket: failed to bind or listen to the socket" ); - delete d->s; - d->s = 0; - } -} - - -/*! - Destroys the socket. - - This causes any backlogged connections (connections that have - reached the host, but not yet been completely set up by calling - TQSocketDevice::accept()) to be severed. - - Existing connections continue to exist; this only affects the - acceptance of new connections. -*/ -TQServerSocket::~TQServerSocket() -{ - delete d; -} - - -/*! - \fn void TQServerSocket::newConnection( int socket ) - - This pure virtual function is responsible for setting up a new - incoming connection. \a socket is the fd (file descriptor) for the - newly accepted connection. -*/ - - -void TQServerSocket::incomingConnection( int ) -{ - int fd = d->s->accept(); - if ( fd >= 0 ) - newConnection( fd ); -} - - -/*! - Returns the port number on which this server socket listens. This - is always non-zero; if you specify 0 in the constructor, - TQServerSocket will pick a non-zero port itself. ok() must be TRUE - before calling this function. - - \sa address() TQSocketDevice::port() -*/ -TQ_UINT16 TQServerSocket::port() const -{ - if ( !d || !d->s ) - return 0; - return d->s->port(); -} - - -/*! - Returns the operating system socket. -*/ -int TQServerSocket::socket() const -{ - if ( !d || !d->s ) - return -1; - - return d->s->socket(); -} - -/*! - Returns the address on which this object listens, or 0.0.0.0 if - this object listens on more than one address. ok() must be TRUE - before calling this function. - - \sa port() TQSocketDevice::address() -*/ -TQHostAddress TQServerSocket::address() const -{ - if ( !d || !d->s ) - return TQHostAddress(); - - return d->s->address(); -} - - -/*! - Returns a pointer to the internal socket tqdevice. The returned - pointer is 0 if there is no connection or pending connection. - - There is normally no need to manipulate the socket tqdevice directly - since this class does all the necessary setup for most client or - server socket applications. -*/ -TQSocketDevice *TQServerSocket::socketDevice() -{ - if ( !d ) - return 0; - - return d->s; -} - - -/*! - Sets the socket to use \a socket. bind() and listen() should - already have been called for \a socket. - - This allows us to use the TQServerSocket class as a wrapper for - other socket types (e.g. Unix Domain Sockets). -*/ -void TQServerSocket::setSocket( int socket ) -{ - delete d; - d = new TQServerSocketPrivate; - d->s = new TQSocketDevice( socket, TQSocketDevice::Stream ); - d->n = new TQSocketNotifier( d->s->socket(), TQSocketNotifier::Read, - this, "accepting new connections" ); - connect( d->n, TQT_SIGNAL(activated(int)), - this, TQT_SLOT(incomingConnection(int)) ); -} - -#endif //TQT_NO_NETWORK diff --git a/tqtinterface/qt4/src/network/tqserversocket.h b/tqtinterface/qt4/src/network/tqserversocket.h deleted file mode 100644 index d1f4a83..0000000 --- a/tqtinterface/qt4/src/network/tqserversocket.h +++ /dev/null @@ -1,95 +0,0 @@ -/**************************************************************************** -** -** Definition of TQServerSocketClass. -** -** Created : 970521 -** -** Copyright (C) 2010 Timothy Pearson and (C) 1992-2008 Trolltech ASA. -** -** This file is part of the network module of the TQt 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 TQt 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.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** 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. -** -**********************************************************************/ - -#ifndef TQSERVERSOCKET_H -#define TQSERVERSOCKET_H - -#ifndef TQT_H -#include "tqobject.h" -#include "tqhostaddress.h" -#include "tqsocketdevice.h" // ### remove or keep for users' convenience? -#endif // TQT_H -#ifndef TQT_NO_NETWORK - -#if !defined( TQT_MODULE_NETWORK ) || defined( TQT_LICENSE_PROFESSIONAL ) || defined( TQT_INTERNAL_NETWORK ) -#define TQM_EXPORT_NETWORK -#else -#define TQM_EXPORT_NETWORK TQ_EXPORT -#endif - -class TQServerSocketPrivate; - - -class TQM_EXPORT_NETWORK TQServerSocket : public TQObject -{ - Q_OBJECT - TQ_OBJECT -public: - TQServerSocket( TQ_UINT16 port, int backlog = 1, - TQObject *parent=0, const char *name=0 ); - TQServerSocket( const TQHostAddress & address, TQ_UINT16 port, int backlog = 1, - TQObject *parent=0, const char *name=0 ); - TQServerSocket( TQObject *parent=0, const char *name=0 ); - virtual ~TQServerSocket(); - - bool ok() const; - - TQ_UINT16 port() const ; - - int socket() const ; - virtual void setSocket( int socket ); - - TQHostAddress address() const ; - - virtual void newConnection( int socket ) = 0; - -protected: - TQSocketDevice *socketDevice(); - -private Q_SLOTS: - void incomingConnection( int socket ); - -private: - TQServerSocketPrivate *d; - void init( const TQHostAddress & address, TQ_UINT16 port, int backlog ); -}; - -#endif // TQT_NO_NETWORK -#endif // TQSERVERSOCKET_H diff --git a/tqtinterface/qt4/src/network/tqsocket.cpp b/tqtinterface/qt4/src/network/tqsocket.cpp deleted file mode 100644 index 8e4d40a..0000000 --- a/tqtinterface/qt4/src/network/tqsocket.cpp +++ /dev/null @@ -1,1668 +0,0 @@ -/**************************************************************************** -** -** Implementation of TQSocket class. -** -** Created : 970521 -** -** Copyright (C) 2010 Timothy Pearson and (C) 1992-2008 Trolltech ASA. -** -** This file is part of the network module of the TQt 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 TQt 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.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** 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 "tqsocket.h" -#ifndef TQT_NO_NETWORK -#include "tqptrlist.h" -#include "tqtimer.h" -#include "tqsocketdevice.h" -#include "tqdns.h" -#include "private/tqinternal_p.h" - -#include -#ifndef NO_ERRNO_H -#include -#endif - -//#define TQSOCKET_DEBUG - -/* - Perhaps this private functionality needs to be refactored. - - Comment from Robert D Gatlin (Intel): - - It would be nice to have the functionality inherent in TQSocket available - as a separate class as a standard part of the TQt library, something along - the line of: - - class TQByteBuffer : public TQIODevice { ... } - - The same class could/would be used within TQSocket for the Read/Write - buffers. - - The above class could be used in the following way(s): - - buffer.open( IO_WriteOnly | IO_Append ); - buffer.writeBlock( a ); // a = TQByteArray - buffer.close(); - - TQByteArray b; - b.resize( buffer.size() ); - buffer.open( IO_ReadOnly ); - buffer.readBlock( b.data(), b.size() ); - buffer.close(); - - But would also be useable with TQDataStream (via TQIODevice) with: - - buffer.open( IO_WriteOnly | IO_Append ); - TQDataStream is( &buffer ); - is << 100; - buffer.close(); - - buffer.open( IO_ReadOnly ); - TQDataStream os( &buffer ); - TQ_UINT32 x; - os >> x; - buffer.close(); - - The real usefulness is with any situations where data (TQByteArray) arrives - incrementally (as in TQSocket and filter case above). - - I tried using TQBuffer, but TQBuffer does not trim bytes from the front of - the buffer in cases like: - - TQBuffer buf; - buf.open( IO_ReadOnly ); - TQDataStream ds( &buf ); - TQ_INT32 x; - ds >> x; - buf.close(); - - In the above case, buf.size() will be identical before and after the - operation with TQDataStream. Based on the implementation of TQBuffer, it - does not appear well suited for this kind of operation. -*/ - -// Private class for TQSocket - -class TQSocketPrivate { -public: - TQSocketPrivate(); - ~TQSocketPrivate(); - void closeSocket(); - void close(); - void connectionClosed(); - void setSocketDevice( TQSocket *q, TQSocketDevice *tqdevice ); - - TQSocket::State state; // connection state - TQString host; // host name - TQ_UINT16 port; // host port - TQSocketDevice *socket; // connection socket - TQSocketNotifier *rsn, *wsn; // socket notifiers - TQMembuf rba; // read buffer - TQ_ULONG readBufferSize; // limit for the read buffer size - TQPtrList wba; // list of write bufs - TQHostAddress addr; // connection address - TQValueList addresses; // alternatives looked up - TQIODevice::Offset wsize; // write total buf size - TQIODevice::Offset windex; // write index -#ifndef TQT_NO_DNS - TQDns *dns4; - TQDns *dns6; -#endif - static TQPtrList sn_read_alreadyCalled; // used to avoid unwanted recursion - TQValueList l4; - TQValueList l6; -}; - -TQPtrList TQSocketPrivate::sn_read_alreadyCalled; - -TQSocketPrivate::TQSocketPrivate() - : state(TQSocket::Idle), host(TQString::tqfromLatin1("")), port(0), - socket(0), rsn(0), wsn(0), readBufferSize(0), wsize(0), windex(0) -{ -#ifndef TQT_NO_DNS - dns4 = 0; - dns6 = 0; -#endif - wba.setAutoDelete( TRUE ); -} - -TQSocketPrivate::~TQSocketPrivate() -{ - close(); - delete socket; -#ifndef TQT_NO_DNS - delete dns4; - delete dns6; -#endif -} - -void TQSocketPrivate::closeSocket() -{ - // Order is important here - the socket notifiers must go away - // before the socket does, otherwise libc or the kernel will - // become unhappy. - delete rsn; - rsn = 0; - delete wsn; - wsn = 0; - if ( socket ) - socket->close(); -} - -void TQSocketPrivate::close() -{ - closeSocket(); - wsize = 0; - rba.clear(); wba.clear(); - windex = 0; -} - -void TQSocketPrivate::connectionClosed() -{ - // We keep the open state in case there's unread incoming data - state = TQSocket::Idle; - closeSocket(); - wba.clear(); - windex = wsize = 0; -} - -void TQSocketPrivate::setSocketDevice( TQSocket *q, TQSocketDevice *tqdevice ) -{ - delete socket; - delete rsn; - delete wsn; - - if ( tqdevice ) { - socket = tqdevice; - } else { - socket = new TQSocketDevice( TQSocketDevice::Stream, - ( addr.isIPv4Address() ? - TQSocketDevice::IPv4 : - TQSocketDevice::IPv6 ), 0 ); - socket->setBlocking( FALSE ); - socket->setAddressReusable( TRUE ); - } - - rsn = new TQSocketNotifier( socket->socket(), - TQSocketNotifier::Read, TQT_TQOBJECT(q), "read" ); - wsn = new TQSocketNotifier( socket->socket(), - TQSocketNotifier::Write, TQT_TQOBJECT(q), "write" ); - - TQObject::connect( rsn, TQT_SIGNAL(activated(int)), q, TQT_SLOT(sn_read()) ); - rsn->setEnabled( FALSE ); - TQObject::connect( wsn, TQT_SIGNAL(activated(int)), q, TQT_SLOT(sn_write()) ); - wsn->setEnabled( FALSE ); -} - -/*! - \class TQSocket tqsocket.h - \brief The TQSocket class provides a buffered TCP connection. -\if defined(commercial) - It is part of the TQt Enterprise Edition. -\endif - - \ingroup io - \module network - - It provides a totally non-blocking TQIODevice, and modifies and - extends the API of TQIODevice with socket-specific code. - - Note that a TQApplication must have been constructed before this - class can be used. - - The functions you're likely to call most are connectToHost(), - bytesAvailable(), canReadLine() and the ones it inherits from - TQIODevice. - - connectToHost() is the most-used function. As its name implies, - it opens a connection to a named host. - - Most network protocols are either packet-oriented or - line-oriented. canReadLine() indicates whether a connection - contains an entire unread line or not, and bytesAvailable() - returns the number of bytes available for reading. - - The Q_SIGNALS error(), connected(), readyRead() and - connectionClosed() inform you of the progress of the connection. - There are also some less commonly used Q_SIGNALS. hostFound() is - emitted when connectToHost() has finished its DNS lookup and is - starting its TCP connection. delayedCloseFinished() is emitted - when close() succeeds. bytesWritten() is emitted when TQSocket - moves data from its "to be written" queue into the TCP - implementation. - - There are several access functions for the socket: state() returns - whether the object is idle, is doing a DNS lookup, is connecting, - has an operational connection, etc. address() and port() return - the IP address and port used for the connection. The peerAddress() - and peerPort() functions return the IP address and port used by - the peer, and peerName() returns the name of the peer (normally - the name that was passed to connectToHost()). socketDevice() - returns a pointer to the TQSocketDevice used for this socket. - - TQSocket inherits TQIODevice, and reimplements some functions. In - general, you can treat it as a TQIODevice for writing, and mostly - also for reading. The match isn't perfect, since the TQIODevice - API is designed for tqdevices that are controlled by the same - machine, and an asynchronous peer-to-peer network connection isn't - quite like that. For example, there is nothing that matches - TQIODevice::size() exactly. The documentation for open(), close(), - flush(), size(), at(), atEnd(), readBlock(), writeBlock(), - getch(), putch(), ungetch() and readLine() describes the - differences in detail. - - \warning TQSocket is not suitable for use in threads. If you need - to uses sockets in threads use the lower-level TQSocketDevice class. - - \warning Because TQt doesn't use the native socketstream - implementation on Mac OS X, TQSocket has an implicit transfer - latency of 100ms. You can achieve lower latency on Mac OS X by - using TQSocketDevice instead. - - \sa TQSocketDevice, TQHostAddress, TQSocketNotifier -*/ - -#ifdef USE_QT4 - -/*! - Reads \a maxlen bytes from the socket into \a data and returns the - number of bytes read. Returns -1 if an error occurred. -*/ - -qint64 TQSocket::readData( char *data, qint64 maxlen ) -{ - if ( data == 0 && maxlen != 0 ) { -#if defined(QT_CHECK_NULL) - qWarning( "TQSocket::readBlock: Null pointer error" ); -#endif - return -1; - } - if ( !isOpen() ) { -#if defined(QT_CHECK_STATE) - qWarning( "TQSocket::readBlock: Socket is not open" ); -#endif - return -1; - } - if ( maxlen >= d->rba.size() ) - maxlen = d->rba.size(); -#if defined(TQSOCKET_DEBUG) - qDebug( "TQSocket (%s): readBlock %d bytes", name(), (int)maxlen ); -#endif - d->rba.consumeBytes( maxlen, data ); - // After we read data from our internal buffer, if we use the - // setReadBufferSize() to limit our buffer, we might now be able to - // read more data in our buffer. So enable the read socket notifier, - // but do this only if we are not in a slot connected to the - // readyRead() signal since this might cause a bad recursive behavior. - // We can test for this condition by looking at the - // sn_read_alreadyCalled flag. - if ( d->rsn && TQSocketPrivate::sn_read_alreadyCalled.findRef(this) == -1 ) - d->rsn->setEnabled( true ); - return maxlen; -} - - -/*! - Writes \a len bytes to the socket from \a data and returns the - number of bytes written. Returns -1 if an error occurred. -*/ - -qint64 TQSocket::writeData( const char *data, qint64 len ) -{ -#if defined(QT_CHECK_NULL) - if ( data == 0 && len != 0 ) { - qWarning( "TQSocket::writeBlock: Null pointer error" ); - } -#endif -#if defined(QT_CHECK_STATE) - if ( !isOpen() ) { - qWarning( "TQSocket::writeBlock: Socket is not open" ); - return -1; - } -#endif -#if defined(QT_CHECK_STATE) - if ( d->state == Closing ) { - qWarning( "TQSocket::writeBlock: Cannot write, socket is closing" ); - } -#endif - if ( len == 0 || d->state == Closing || d->state == Idle ) - return 0; - TQByteArray *a = d->wba.last(); - - // next bit is sensitive. if we're writing really small chunks, - // try to buffer up since system calls are expensive, and nagle's - // algorithm is even more expensive. but if anything even - // remotely large is being written, try to issue a write at once. - - bool writeNow = ( d->wsize + len >= 1400 || len > 512 ); - - if ( a && a->size() + len < 128 ) { - // small buffer, resize - int i = a->size(); - a->resize( i+len ); - memcpy( a->data()+i, data, len ); - } else { - // append new buffer - a = new TQByteArray( len ); - memcpy( a->data(), data, len ); - d->wba.append( a ); - } - d->wsize += len; - if ( writeNow ) - flush(); - else if ( d->wsn ) - d->wsn->setEnabled( true ); -#if defined(TQSOCKET_DEBUG) - qDebug( "TQSocket (%s): writeBlock %d bytes", name(), (int)len ); -#endif - return len; -} - -#endif // USE_QT4 - - -/*! - Creates a TQSocket object in \c TQSocket::Idle state. - - The \a parent and \a name arguments are passed on to the TQObject - constructor. - - Note that a TQApplication must have been constructed before sockets - can be used. -*/ - -TQSocket::TQSocket( TQObject *parent, const char *name ) -#ifdef USE_QT4 - : TQIODevice() -#else // USE_QT4 - : TQObject( parent, name ) -#endif // USE_QT4 -{ -#ifdef USE_QT4 - setParent(parent); - setObjectName(name); -#endif // USE_QT4 - d = new TQSocketPrivate; - setSocketDevice( 0 ); - setFlags( IO_Direct ); - resetqStatus(); -} - - -/*! - Destroys the socket. Closes the connection if necessary. - - \sa close() -*/ - -TQSocket::~TQSocket() -{ -#if defined(TQSOCKET_DEBUG) - qDebug( "TQSocket (%s): Destroy", name() ); -#endif - if ( state() != Idle ) - close(); - TQ_ASSERT( d != 0 ); - delete d; -} - - -/*! - Returns a pointer to the internal socket tqdevice. - - There is normally no need to manipulate the socket tqdevice directly - since this class does the necessary setup for most applications. -*/ - -TQSocketDevice *TQSocket::socketDevice() -{ - return d->socket; -} - -/*! - Sets the internal socket tqdevice to \a tqdevice. Passing a \a tqdevice - of 0 will cause the internal socket tqdevice to be used. Any - existing connection will be disconnected before using the new \a - tqdevice. - - The new tqdevice should not be connected before being associated - with a TQSocket; after setting the socket call connectToHost() to - make the connection. - - This function is useful if you need to subclass TQSocketDevice and - want to use the TQSocket API, for example, to implement Unix domain - sockets. -*/ - -void TQSocket::setSocketDevice( TQSocketDevice *tqdevice ) -{ - if ( state() != Idle ) - close(); - d->setSocketDevice( this, tqdevice ); -} - -/*! - \enum TQSocket::State - - This enum defines the connection states: - - \value Idle if there is no connection - \value HostLookup during a DNS lookup - \value Connecting during TCP connection establishment - \value Connected when there is an operational connection - \value Closing if the socket is closing down, but is not yet closed. -*/ - -/*! - Returns the current state of the socket connection. - - \sa TQSocket::State -*/ - -TQSocket::State TQSocket::state() const -{ - return d->state; -} - - -#ifndef TQT_NO_DNS - -/*! - Attempts to make a connection to \a host on the specified \a port - and return immediately. - - Any connection or pending connection is closed immediately, and - TQSocket goes into the \c HostLookup state. When the lookup - succeeds, it emits hostFound(), starts a TCP connection and goes - into the \c Connecting state. Finally, when the connection - succeeds, it emits connected() and goes into the \c Connected - state. If there is an error at any point, it emits error(). - - \a host may be an IP address in string form, or it may be a DNS - name. TQSocket will do a normal DNS lookup if required. Note that - \a port is in native byte order, unlike some other libraries. - - \sa state() -*/ - -void TQSocket::connectToHost( const TQString &host, TQ_UINT16 port ) -{ -#if defined(TQSOCKET_DEBUG) - qDebug( "TQSocket (%s)::connectToHost: host %s, port %d", - name(), host.ascii(), port ); -#endif - setSocketIntern( -1 ); - d->state = HostLookup; - d->host = host; - d->port = port; - d->dns4 = new TQDns( host, TQDns::A ); - d->dns6 = new TQDns( host, TQDns::Aaaa ); - - // try if the address is already available (for faster connecting...) - tryConnecting(); - if ( d->state == HostLookup ) { - connect( d->dns4, TQT_SIGNAL(resultsReady()), - this, TQT_SLOT(tryConnecting()) ); - connect( d->dns6, TQT_SIGNAL(resultsReady()), - this, TQT_SLOT(tryConnecting()) ); - } -} - -#endif - - -/*! - This private Q_SLOTS continues the connection process where - connectToHost() leaves off. -*/ - -void TQSocket::tryConnecting() -{ -#if defined(TQSOCKET_DEBUG) - qDebug( "TQSocket (%s)::tryConnecting()", name() ); -#endif - // ### this ifdef isn't correct - addresses() also does /etc/hosts and - // numeric-address-as-string handling. -#ifndef TQT_NO_DNS - - if ( d->dns4 ) { - d->l4 = d->dns4->addresses(); - if ( !d->l4.isEmpty() || !d->dns4->isWorking() ) { -#if defined(TQSOCKET_DEBUG) - qDebug( "TQSocket (%s)::tryConnecting: host %s, port %d: " - "%d IPv4 addresses", - name(), d->host.ascii(), d->port, d->l4.count() ); -#endif - delete d->dns4; - d->dns4 = 0; - } - } - - if ( d->dns6 ) { - d->l6 = d->dns6->addresses(); - if ( !d->l6.isEmpty() || !d->dns6->isWorking() ) { -#if defined(TQSOCKET_DEBUG) - qDebug( "TQSocket (%s)::tryConnecting: host %s, port %d: " - "%d IPv6 addresses", - name(), d->host.ascii(), d->port, d->l6.count() ); -#endif - delete d->dns6; - d->dns6 = 0; - } - } - - if ( d->state == HostLookup ) { - if ( d->l4.isEmpty() && d->l6.isEmpty() && - !d->dns4 && !d->dns6 ) { - // no results and we're not still looking: give up - d->state = Idle; - emit error( ErrHostNotFound ); - return; - } - if ( d->l4.isEmpty() && d->l6.isEmpty() ) { - // no results (yet): try again later - return; - } - - // we've found something. press on with that. if we later find - // more, fine. - emit hostFound(); - d->state = Connecting; - } - - if ( d->state == Connecting ) { - d->addresses += d->l4; - d->addresses += d->l6; - d->l4.clear(); - d->l6.clear(); - - // try one address at a time, falling back to the next one if - // there is a connection failure. (should also support a timeout, - // or do multiple TCP-level connects at a time, with staggered - // starts to avoid bandwidth waste and cause fewer - // "connect-and-abort" errors. but that later.) - bool stuck = TRUE; - while( stuck ) { - stuck = FALSE; - if ( d->socket && - d->socket->connect( d->addr, d->port ) == FALSE ) { - if ( d->socket->error() == TQSocketDevice::NoError ) { - if ( d->wsn ) - d->wsn->setEnabled( TRUE ); - return; // not serious, try again later - } - -#if defined(TQSOCKET_DEBUG) - qDebug( "TQSocket (%s)::tryConnecting: " - "Gave up on IP address %s", - name(), d->socket->peerAddress().toString().ascii() ); -#endif - delete d->wsn; - d->wsn = 0; - delete d->rsn; - d->rsn = 0; - delete d->socket; - d->socket = 0; - - if(d->addresses.isEmpty()) { - emit error( ErrConnectionRefused ); - return; - } - } - // if the host has more addresses, try another some. - if ( d->socket == 0 && !d->addresses.isEmpty() ) { - d->addr = *d->addresses.begin(); - d->addresses.remove( d->addresses.begin() ); - d->setSocketDevice( this, 0 ); - stuck = TRUE; -#if defined(TQSOCKET_DEBUG) - qDebug( "TQSocket (%s)::tryConnecting: Trying IP address %s", - name(), d->addr.toString().ascii() ); -#endif - } - }; - - // The socket write notifier will fire when the connection succeeds - if ( d->wsn ) - d->wsn->setEnabled( TRUE ); - } -#endif -} - -/*! - \enum TQSocket::Error - - This enum specifies the possible errors: - \value ErrConnectionRefused if the connection was refused - \value ErrHostNotFound if the host was not found - \value ErrSocketRead if a read from the socket failed -*/ - -/*! - \fn void TQSocket::error( int ) - - This signal is emitted after an error occurred. The parameter is - the \l Error value. -*/ - -/*! - \fn void TQSocket::hostFound() - - This signal is emitted after connectToHost() has been called and - the host lookup has succeeded. - - \sa connected() -*/ - - -/*! - \fn void TQSocket::connected() - - This signal is emitted after connectToHost() has been called and a - connection has been successfully established. - - \sa connectToHost(), connectionClosed() -*/ - - -/*! - \fn void TQSocket::connectionClosed() - - This signal is emitted when the other end has closed the - connection. The read buffers may contain buffered input data which - you can read after the connection was closed. - - \sa connectToHost(), close() -*/ - - -/*! - \fn void TQSocket::delayedCloseFinished() - - This signal is emitted when a delayed close is finished. - - If you call close() and there is buffered output data to be - written, TQSocket goes into the \c TQSocket::Closing state and - returns immediately. It will then keep writing to the socket until - all the data has been written. Then, the delayedCloseFinished() - signal is emitted. - - \sa close() -*/ - - -/*! - \fn void TQSocket::readyRead() - - This signal is emitted every time there is new incoming data. - - Bear in mind that new incoming data is only reported once; if you do not - read all the data, this class buffers the data and you can read it later, - but no signal is emitted unless new data arrives. A good practice is to - read all data in the slot connected to this signal unless you are sure that - you need to receive more data to be able to process it. - - \sa readBlock(), readLine(), bytesAvailable() -*/ - - -/*! - \fn void TQSocket::bytesWritten( int nbytes ) - - This signal is emitted when data has been written to the network. - The \a nbytes parameter specifies how many bytes were written. - - The bytesToWrite() function is often used in the same context; it - indicates how many buffered bytes there are left to write. - - \sa writeBlock(), bytesToWrite() -*/ - - -/*! - Opens the socket using the specified TQIODevice file mode \a m. - This function is called automatically when needed and you should - not call it yourself. - - \sa close() -*/ - -bool TQSocket::open( int m ) -{ - if ( isOpen() ) { -#if defined(TQT_CHECK_STATE) - qWarning( "TQSocket::open: Already open" ); -#endif - return FALSE; - } - TQIODevice::setMode( m & IO_ReadWrite ); - setState( IO_Open ); - return TRUE; -} - - -/*! - Closes the socket. - - The read buffer is cleared. - - If the output buffer is empty, the state is set to \c - TQSocket::Idle and the connection is terminated immediately. If the - output buffer still contains data to be written, TQSocket goes into - the \c TQSocket::Closing state and the rest of the data will be - written. When all of the outgoing data have been written, the - state is set to \c TQSocket::Idle and the connection is terminated. - At this point, the delayedCloseFinished() signal is emitted. - - If you don't want that the data of the output buffer is written, call - clearPendingData() before you call close(). - - \sa state(), bytesToWrite() clearPendingData() -*/ - -void TQSocket::close() -{ - if ( !isOpen() || d->state == Idle ) // already closed - return; - if ( d->state == Closing ) - return; - if ( !d->rsn || !d->wsn ) - return; -#if defined(TQSOCKET_DEBUG) - qDebug( "TQSocket (%s): close socket", name() ); -#endif - if ( d->socket && d->wsize ) { // there's data to be written - d->state = Closing; - if ( d->rsn ) - d->rsn->setEnabled( FALSE ); - if ( d->wsn ) - d->wsn->setEnabled( TRUE ); - d->rba.clear(); // clear incoming data - return; - } - setFlags( IO_Sequential ); - resetqStatus(); - setState( 0 ); - d->close(); - d->state = Idle; -} - - -/*! - This function consumes \a nbytes bytes of data from the write - buffer. -*/ - -bool TQSocket::consumeWriteBuf( TQ_ULONG nbytes ) -{ - if ( nbytes <= 0 || nbytes > d->wsize ) - return FALSE; -#if defined(TQSOCKET_DEBUG) - qDebug( "TQSocket (%s): skipWriteBuf %d bytes", name(), (int)nbytes ); -#endif - d->wsize -= nbytes; - for ( ;; ) { - TQByteArray *a = d->wba.first(); - if ( d->windex + nbytes >= a->size() ) { - nbytes -= a->size() - d->windex; - d->wba.remove(); - d->windex = 0; - if ( nbytes == 0 ) - break; - } else { - d->windex += nbytes; - break; - } - } - return TRUE; -} - - - -/*! - Implementation of the abstract virtual TQIODevice::flush() function. -*/ - -void TQSocket::flush() -{ - if ( !d->socket ) - return; - bool osBufferFull = FALSE; - int consumed = 0; - while ( !osBufferFull && d->state >= Connecting && d->wsize > 0 ) { -#if defined(TQSOCKET_DEBUG) - qDebug( "TQSocket (%s): flush: Write data to the socket", name() ); -#endif - TQByteArray *a = d->wba.first(); - int nwritten; - int i = 0; - if ( (int)a->size() - d->windex < 1460 ) { - // Concatenate many smaller blocks. the first may be - // partial, but each subsequent block is copied entirely - // or not at all. the sizes here are picked so that we - // generally won't trigger nagle's algorithm in the tcp - // implementation: we concatenate if we'd otherwise send - // less than PMTU bytes (we assume PMTU is 1460 bytes), - // and concatenate up to the largest payload TCP/IP can - // carry. with these precautions, nagle's algorithm - // should apply only when really appropriate. - TQByteArray out( 65536 ); - int j = d->windex; - int s = a->size() - j; - while ( a && i+s < (int)out.size() ) { - memcpy( out.data()+i, a->data()+j, s ); - j = 0; - i += s; - a = d->wba.next(); - s = a ? a->size() : 0; - } - nwritten = d->socket->writeBlock( out.data(), i ); - if ( d->wsn ) - d->wsn->setEnabled( FALSE ); // the TQSocketNotifier documentation says so - } else { - // Big block, write it immediately - i = a->size() - d->windex; - nwritten = d->socket->writeBlock( a->data() + d->windex, i ); - if ( d->wsn ) - d->wsn->setEnabled( FALSE ); // the TQSocketNotifier documentation says so - } - if ( nwritten > 0 ) { - if ( consumeWriteBuf( nwritten ) ) - consumed += nwritten; - } - if ( nwritten < i ) - osBufferFull = TRUE; - } - if ( consumed > 0 ) { -#if defined(TQSOCKET_DEBUG) - qDebug( "TQSocket (%s): flush: wrote %d bytes, %d left", - name(), consumed, (int)d->wsize ); -#endif - emit bytesWritten( consumed ); - } - if ( d->state == Closing && d->wsize == 0 ) { -#if defined(TQSOCKET_DEBUG) - qDebug( "TQSocket (%s): flush: Delayed close done. Terminating.", - name() ); -#endif - setFlags( IO_Sequential ); - resetqStatus(); - setState( 0 ); - d->close(); - d->state = Idle; - emit delayedCloseFinished(); - return; - } - if ( !d->socket->isOpen() ) { - d->connectionClosed(); - emit connectionClosed(); - return; - } - if ( d->wsn ) - d->wsn->setEnabled( d->wsize > 0 ); // write if there's data -} - - -/*! - Returns the number of incoming bytes that can be read right now - (like bytesAvailable()). -*/ - -#ifdef USE_QT4 -qint64 TQSocket::size() const -#else // USE_QT4 -TQIODevice::Offset TQSocket::size() const -#endif // USE_QT4 -{ - return (Offset)bytesAvailable(); -} - - -/*! - Returns the current read index. Since TQSocket is a sequential - tqdevice, the current read index is always zero. -*/ - -#ifdef USE_QT4 -qint64 TQSocket::at() const -#else // USE_QT4 -TQIODevice::Offset TQSocket::at() const -#endif // USE_QT4 -{ - return 0; -} - - -/*! - \overload - - Moves the read index forward to \a index and returns TRUE if the - operation was successful; otherwise returns FALSE. Moving the - index forward means skipping incoming data. -*/ - -bool TQSocket::at( Offset index ) -{ - if ( index > d->rba.size() ) - return FALSE; - d->rba.consumeBytes( (TQ_ULONG)index, 0 ); // throw away data 0..index-1 - // After we read data from our internal buffer, if we use the - // setReadBufferSize() to limit our buffer, we might now be able to - // read more data in our buffer. So enable the read socket notifier, - // but do this only if we are not in a slot connected to the - // readyRead() signal since this might cause a bad recursive behavior. - // We can test for this condition by looking at the - // sn_read_alreadyCalled flag. - if ( d->rsn && TQSocketPrivate::sn_read_alreadyCalled.findRef(this) == -1 ) - d->rsn->setEnabled( TRUE ); - return TRUE; -} - - -/*! - Returns TRUE if there is no more data to read; otherwise returns FALSE. -*/ - -bool TQSocket::atEnd() const -{ - if ( d->socket == 0 ) - return TRUE; - TQSocket * that = (TQSocket *)this; - if ( that->d->socket->bytesAvailable() ) // a little slow, perhaps... - that->sn_read(); - return that->d->rba.size() == 0; -} - - -/*! - Returns the number of incoming bytes that can be read, i.e. the - size of the input buffer. Equivalent to size(). - - This function can trigger the readyRead() signal, if more data has - arrived on the socket. - - \sa bytesToWrite() -*/ - -#ifdef USE_QT4 -qint64 TQSocket::bytesAvailable() const -#else // USE_QT4 -TQ_ULONG TQSocket::bytesAvailable() const -#endif // USE_QT4 -{ - if ( d->socket == 0 ) - return 0; - TQSocket * that = (TQSocket *)this; - if ( that->d->socket->bytesAvailable() ) // a little slow, perhaps... - (void)that->sn_read(); - return that->d->rba.size(); -} - - -/*! - Wait up to \a msecs milliseconds for more data to be available. - - If \a msecs is -1 the call will block indefinitely. - - Returns the number of bytes available. - - If \a timeout is non-null and no error occurred (i.e. it does not - return -1): this function sets \a *timeout to TRUE, if the reason - for returning was that the timeout was reached; otherwise it sets - \a *timeout to FALSE. This is useful to find out if the peer - closed the connection. - - \warning This is a blocking call and should be avoided in event - driven applications. - - \sa bytesAvailable() -*/ - -TQ_ULONG TQSocket::waitForMore( int msecs, bool *timeout ) const -{ - if ( d->socket == 0 ) - return 0; - TQSocket * that = (TQSocket *)this; - if ( that->d->socket->waitForMore( msecs, timeout ) > 0 ) - (void)that->sn_read( TRUE ); - return that->d->rba.size(); -} - -/*! \overload -*/ - -TQ_ULONG TQSocket::waitForMore( int msecs ) const -{ - return waitForMore( msecs, 0 ); -} - -/*! - Returns the number of bytes that are waiting to be written, i.e. - the size of the output buffer. - - \sa bytesAvailable() clearPendingData() -*/ - -#ifdef USE_QT4 -qint64 TQSocket::bytesToWrite() const -#else // USE_QT4 -TQ_ULONG TQSocket::bytesToWrite() const -#endif // USE_QT4 -{ - return d->wsize; -} - -/*! - Deletes the data that is waiting to be written. This is useful if you want - to close the socket without waiting for all the data to be written. - - \sa bytesToWrite() close() delayedCloseFinished() -*/ - -void TQSocket::clearPendingData() -{ - d->wba.clear(); - d->windex = d->wsize = 0; -} - -/*! - Reads \a maxlen bytes from the socket into \a data and returns the - number of bytes read. Returns -1 if an error occurred. -*/ - -TQ_LONG TQSocket::readBlock( char *data, TQ_ULONG maxlen ) -{ - if ( data == 0 && maxlen != 0 ) { -#if defined(TQT_CHECK_NULL) - qWarning( "TQSocket::readBlock: Null pointer error" ); -#endif - return -1; - } - if ( !isOpen() ) { -#if defined(TQT_CHECK_STATE) - qWarning( "TQSocket::readBlock: Socket is not open" ); -#endif - return -1; - } - if ( maxlen >= d->rba.size() ) - maxlen = d->rba.size(); -#if defined(TQSOCKET_DEBUG) - qDebug( "TQSocket (%s): readBlock %d bytes", name(), (int)maxlen ); -#endif - d->rba.consumeBytes( maxlen, data ); - // After we read data from our internal buffer, if we use the - // setReadBufferSize() to limit our buffer, we might now be able to - // read more data in our buffer. So enable the read socket notifier, - // but do this only if we are not in a slot connected to the - // readyRead() signal since this might cause a bad recursive behavior. - // We can test for this condition by looking at the - // sn_read_alreadyCalled flag. - if ( d->rsn && TQSocketPrivate::sn_read_alreadyCalled.findRef(this) == -1 ) - d->rsn->setEnabled( TRUE ); - return maxlen; -} - - -/*! - Writes \a len bytes to the socket from \a data and returns the - number of bytes written. Returns -1 if an error occurred. -*/ - -TQ_LONG TQSocket::writeBlock( const char *data, TQ_ULONG len ) -{ -#if defined(TQT_CHECK_NULL) - if ( data == 0 && len != 0 ) { - qWarning( "TQSocket::writeBlock: Null pointer error" ); - } -#endif -#if defined(TQT_CHECK_STATE) - if ( !isOpen() ) { - qWarning( "TQSocket::writeBlock: Socket is not open" ); - return -1; - } -#endif -#if defined(TQT_CHECK_STATE) - if ( d->state == Closing ) { - qWarning( "TQSocket::writeBlock: Cannot write, socket is closing" ); - } -#endif - if ( len == 0 || d->state == Closing || d->state == Idle ) - return 0; - TQByteArray *a = d->wba.last(); - - // next bit is sensitive. if we're writing really small chunks, - // try to buffer up since system calls are expensive, and nagle's - // algorithm is even more expensive. but if anything even - // remotely large is being written, try to issue a write at once. - - bool writeNow = ( d->wsize + len >= 1400 || len > 512 ); - - if ( a && a->size() + len < 128 ) { - // small buffer, resize - int i = a->size(); - a->resize( i+len ); - memcpy( a->data()+i, data, len ); - } else { - // append new buffer - a = new TQByteArray( len ); - memcpy( a->data(), data, len ); - d->wba.append( a ); - } - d->wsize += len; - if ( writeNow ) - flush(); - else if ( d->wsn ) - d->wsn->setEnabled( TRUE ); -#if defined(TQSOCKET_DEBUG) - qDebug( "TQSocket (%s): writeBlock %d bytes", name(), (int)len ); -#endif - return len; -} - - -/*! - Reads a single byte/character from the internal read buffer. - Returns the byte/character read, or -1 if there is nothing to be - read. - - \sa bytesAvailable(), putch() -*/ - -int TQSocket::getch() -{ - if ( isOpen() && d->rba.size() > 0 ) { - uchar c; - d->rba.consumeBytes( 1, (char*)&c ); - // After we read data from our internal buffer, if we use the - // setReadBufferSize() to limit our buffer, we might now be able to - // read more data in our buffer. So enable the read socket notifier, - // but do this only if we are not in a slot connected to the - // readyRead() signal since this might cause a bad recursive behavior. - // We can test for this condition by looking at the - // sn_read_alreadyCalled flag. - if ( d->rsn && TQSocketPrivate::sn_read_alreadyCalled.findRef(this) == -1 ) - d->rsn->setEnabled( TRUE ); - return c; - } - return -1; -} - - -/*! - Writes the character \a ch to the output buffer. - - Returns \a ch, or -1 if an error occurred. - - \sa getch() -*/ - -int TQSocket::putch( int ch ) -{ - char buf[2]; - buf[0] = ch; - return writeBlock(buf, 1) == 1 ? ch : -1; -} - - -/*! - This implementation of the virtual function TQIODevice::ungetch() - prepends the character \a ch to the read buffer so that the next - read returns this character as the first character of the output. -*/ - -int TQSocket::ungetch( int ch ) -{ -#if defined(TQT_CHECK_STATE) - if ( !isOpen() ) { - qWarning( "TQSocket::ungetch: Socket not open" ); - return -1; - } -#endif - return d->rba.ungetch( ch ); -} - - -/*! - Returns TRUE if it's possible to read an entire line of text from - this socket at this time; otherwise returns FALSE. - - Note that if the peer closes the connection unexpectedly, this - function returns FALSE. This means that loops such as this won't - work: - - \code - while( !socket->canReadLine() ) // WRONG - ; - \endcode - - \sa readLine() -*/ - -bool TQSocket::canReadLine() const -{ - if ( ((TQSocket*)this)->d->rba.scanNewline( 0 ) ) - return TRUE; - return ( bytesAvailable() > 0 && - ((TQSocket*)this)->d->rba.scanNewline( 0 ) ); -} - -/*! - \reimp - \internal - So that it's not hidden by our other readLine(). -*/ -TQ_LONG TQSocket::readLine( char *data, TQ_ULONG maxlen ) -{ - return TQIODevice::readLine(data,maxlen); -} - -/*! - Returns a line of text including a terminating newline character - (\n). Returns "" if canReadLine() returns FALSE. - - \sa canReadLine() -*/ - -TQString TQSocket::readLine() -{ - TQByteArray a(256); - bool nl = d->rba.scanNewline( &a ); - TQString s; - if ( nl ) { - at( a.size() ); // skips the data read - s = TQString( a ); - } - return s; -} - -/*! - \internal - Internal slot for handling socket read notifications. - - This function has can usually only be entered once (i.e. no - recursive calls). If the argument \a force is TRUE, the function - is executed, but no readyRead() Q_SIGNALS are emitted. This - behaviour is useful for the waitForMore() function, so that it is - possible to call waitForMore() in a slot connected to the - readyRead() signal. -*/ - -void TQSocket::sn_read( bool force ) -{ - TQ_LONG maxToRead = 0; - if ( d->readBufferSize > 0 ) { - maxToRead = d->readBufferSize - d->rba.size(); - if ( maxToRead <= 0 ) { - if ( d->rsn ) - d->rsn->setEnabled( FALSE ); - return; - } - } - - // Use TQSocketPrivate::sn_read_alreadyCalled to avoid recursive calls of - // sn_read() (and as a result avoid emitting the readyRead() signal in a - // slot for readyRead(), if you use bytesAvailable()). - if ( !force && TQSocketPrivate::sn_read_alreadyCalled.findRef(this) != -1 ) - return; - TQSocketPrivate::sn_read_alreadyCalled.append( this ); - - char buf[4096]; - TQ_LONG nbytes = d->socket->bytesAvailable(); - TQ_LONG nread; - TQByteArray *a = 0; - - if ( state() == Connecting ) { - if ( nbytes > 0 ) { - tryConnection(); - } else { - // nothing to do, nothing to care about - TQSocketPrivate::sn_read_alreadyCalled.removeRef( this ); - return; - } - } - if ( state() == Idle ) { - TQSocketPrivate::sn_read_alreadyCalled.removeRef( this ); - return; - } - - if ( nbytes <= 0 ) { // connection closed? - // On Windows this may happen when the connection is still open. - // This happens when the system is heavily loaded and we have - // read all the data on the socket before a new WSAAsyncSelect - // event is processed. A new read operation would then block. - // This code is also useful when TQSocket is used without an - // event loop. - nread = d->socket->readBlock( buf, maxToRead ? TQMIN((TQ_LONG)sizeof(buf),maxToRead) : sizeof(buf) ); - if ( nread == 0 ) { // really closed - if ( !d->socket->isOpen() ) { -#if defined(TQSOCKET_DEBUG) - qDebug( "TQSocket (%s): sn_read: Connection closed", name() ); -#endif - d->connectionClosed(); - emit connectionClosed(); - } - TQSocketPrivate::sn_read_alreadyCalled.removeRef( this ); - return; - } else { - if ( nread < 0 ) { - if ( d->socket->error() == TQSocketDevice::NoError ) { - // all is fine - TQSocketPrivate::sn_read_alreadyCalled.removeRef( this ); - return; - } -#if defined(TQSOCKET_DEBUG) - qWarning( "TQSocket::sn_read (%s): Close error", name() ); -#endif - if ( d->rsn ) - d->rsn->setEnabled( FALSE ); - emit error( ErrSocketRead ); - TQSocketPrivate::sn_read_alreadyCalled.removeRef( this ); - return; - } - a = new TQByteArray( nread ); - memcpy( a->data(), buf, nread ); - } - - } else { // data to be read -#if defined(TQSOCKET_DEBUG) - qDebug( "TQSocket (%s): sn_read: %ld incoming bytes", name(), nbytes ); -#endif - if ( nbytes > (int)sizeof(buf) ) { - // big - a = new TQByteArray( nbytes ); - nread = d->socket->readBlock( a->data(), maxToRead ? TQMIN(nbytes,maxToRead) : nbytes ); - } else { - a = 0; - nread = d->socket->readBlock( buf, maxToRead ? TQMIN((TQ_LONG)sizeof(buf),maxToRead) : sizeof(buf) ); - if ( nread > 0 ) { - // ##### could setRawData - a = new TQByteArray( nread ); - memcpy( a->data(), buf, nread ); - } - } - if ( nread == 0 ) { -#if defined(TQSOCKET_DEBUG) - qDebug( "TQSocket (%s): sn_read: Connection closed", name() ); -#endif - // ### we should rather ask the socket tqdevice if it is closed - d->connectionClosed(); - emit connectionClosed(); - TQSocketPrivate::sn_read_alreadyCalled.removeRef( this ); - delete a; - return; - } else if ( nread < 0 ) { - delete a; - - if ( d->socket->error() == TQSocketDevice::NoError ) { - // all is fine - TQSocketPrivate::sn_read_alreadyCalled.removeRef( this ); - return; - } -#if defined(TQT_CHECK_RANGE) - qWarning( "TQSocket::sn_read: Read error" ); -#endif - if ( d->rsn ) - d->rsn->setEnabled( FALSE ); - emit error( ErrSocketRead ); - TQSocketPrivate::sn_read_alreadyCalled.removeRef( this ); - return; - } - if ( nread != (int)a->size() ) { // unexpected -#if defined(CHECK_RANGE) && !defined(TQ_OS_WIN32) - qWarning( "TQSocket::sn_read: Unexpected short read" ); -#endif - a->resize( nread ); - } - } - d->rba.append( a ); - if ( !force ) { - if ( d->rsn ) - d->rsn->setEnabled( FALSE ); - emit readyRead(); - if ( d->rsn ) - d->rsn->setEnabled( TRUE ); - } - - TQSocketPrivate::sn_read_alreadyCalled.removeRef( this ); -} - - -/*! - \internal - Internal slot for handling socket write notifications. -*/ - -void TQSocket::sn_write() -{ - if ( d->state == Connecting ) // connection established? - tryConnection(); - flush(); -} - -void TQSocket::emitErrorConnectionRefused() -{ - emit error( ErrConnectionRefused ); -} - -void TQSocket::tryConnection() -{ - if ( d->socket->connect( d->addr, d->port ) ) { - d->state = Connected; -#if defined(TQSOCKET_DEBUG) - qDebug( "TQSocket (%s): sn_write: Got connection to %s", - name(), peerName().ascii() ); -#endif - if ( d->rsn ) - d->rsn->setEnabled( TRUE ); - emit connected(); - } else { - d->state = Idle; - TQTimer::singleShot( 0, this, TQT_SLOT(emitErrorConnectionRefused()) ); - return; - } -} - - -/*! - Returns the socket number, or -1 if there is no socket at the moment. -*/ - -int TQSocket::socket() const -{ - if ( d->socket == 0 ) - return -1; - return d->socket->socket(); -} - -/*! - Sets the socket to use \a socket and the state() to \c Connected. - The socket must already be connected. - - This allows us to use the TQSocket class as a wrapper for other - socket types (e.g. Unix Domain Sockets). -*/ - -void TQSocket::setSocket( int socket ) -{ - setSocketIntern( socket ); - d->state = Connection; - d->rsn->setEnabled( TRUE ); -} - - -/*! - Sets the socket to \a socket. This is used by both setSocket() and - connectToHost() and can also be used on unconnected sockets. -*/ - -void TQSocket::setSocketIntern( int socket ) -{ - if ( state() != Idle ) { - clearPendingData(); - close(); - } - TQ_ULONG oldBufferSize = d ? d->readBufferSize : 0; - delete d; - - d = new TQSocketPrivate; - if (oldBufferSize) - d->readBufferSize = oldBufferSize; - if ( socket >= 0 ) { - TQSocketDevice *sd = new TQSocketDevice( socket, TQSocketDevice::Stream ); - sd->setBlocking( FALSE ); - sd->setAddressReusable( TRUE ); - d->setSocketDevice( this, sd ); - } - d->state = Idle; - - // Initialize the IO tqdevice flags - setFlags( IO_Direct ); - resetqStatus(); - open( IO_ReadWrite ); - - // hm... this is not very nice. - d->host = TQString::null; - d->port = 0; -#ifndef TQT_NO_DNS - delete d->dns4; - d->dns4 = 0; - delete d->dns6; - d->dns6 = 0; -#endif -} - - -/*! - Returns the host port number of this socket, in native byte order. -*/ - -TQ_UINT16 TQSocket::port() const -{ - if ( d->socket == 0 ) - return 0; - return d->socket->port(); -} - - -/*! - Returns the peer's host port number, normally as specified to the - connectToHost() function. If none has been set, this function - returns 0. - - Note that TQt always uses native byte order, i.e. 67 is 67 in TQt; - there is no need to call htons(). -*/ - -TQ_UINT16 TQSocket::peerPort() const -{ - if ( d->socket == 0 ) - return 0; - return d->socket->peerPort(); -} - - -/*! - Returns the host address of this socket. (This is normally the - main IP address of the host, but can be e.g. 127.0.0.1 for - connections to localhost.) -*/ - -TQHostAddress TQSocket::address() const -{ - if ( d->socket == 0 ) { - TQHostAddress tmp; - return tmp; - } - return d->socket->address(); -} - - -/*! - Returns the address of the connected peer if the socket is in - Connected state; otherwise an empty TQHostAddress is returned. -*/ - -TQHostAddress TQSocket::peerAddress() const -{ - if ( d->socket == 0 ) { - TQHostAddress tmp; - return tmp; - } - return d->socket->peerAddress(); -} - - -/*! - Returns the host name as specified to the connectToHost() - function. An empty string is returned if none has been set. -*/ - -TQString TQSocket::peerName() const -{ - return d->host; -} - -/*! - Sets the size of the TQSocket's internal read buffer to \a bufSize. - - Usually TQSocket reads all data that is available from the operating - system's socket. If the buffer size is limited to a certain size, this - means that the TQSocket class doesn't buffer more than this size of data. - - If the size of the read buffer is 0, the read buffer is unlimited and all - incoming data is buffered. This is the default. - - If you read the data in the readyRead() signal, you shouldn't use this - option since it might slow down your program unnecessary. This option is - useful if you only need to read the data at certain points in time, like in - a realtime streaming application. - - \sa readBufferSize() -*/ - -void TQSocket::setReadBufferSize( TQ_ULONG bufSize ) -{ - d->readBufferSize = bufSize; -} - -/*! - Returns the size of the read buffer. - - \sa setReadBufferSize() -*/ - -TQ_ULONG TQSocket::readBufferSize() const -{ - return d->readBufferSize; -} - -#endif //TQT_NO_NETWORK diff --git a/tqtinterface/qt4/src/network/tqsocket.h b/tqtinterface/qt4/src/network/tqsocket.h deleted file mode 100644 index 7b9453e..0000000 --- a/tqtinterface/qt4/src/network/tqsocket.h +++ /dev/null @@ -1,174 +0,0 @@ -/**************************************************************************** -** -** Definition of TQSocket class. -** -** Created : 970521 -** -** Copyright (C) 2010 Timothy Pearson and (C) 1992-2008 Trolltech ASA. -** -** This file is part of the network module of the TQt 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 TQt 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.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** 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. -** -**********************************************************************/ - -#ifndef TQSOCKET_H -#define TQSOCKET_H - -#ifndef TQT_H -#include "tqobject.h" -#include "tqiodevice.h" -#include "tqhostaddress.h" // int->TQHostAddress conversion -#endif // TQT_H - -#if !defined( TQT_MODULE_NETWORK ) || defined( TQT_LICENSE_PROFESSIONAL ) || defined( TQT_INTERNAL_NETWORK ) -#define TQM_EXPORT_NETWORK -#else -#define TQM_EXPORT_NETWORK TQ_EXPORT -#endif - -#ifndef TQT_NO_NETWORK -class TQSocketPrivate; -class TQSocketDevice; - -// #ifdef USE_QT4 -class TQM_EXPORT_NETWORK TQSocket : public TQIODevice -// #else // USE_QT4 -// class TQM_EXPORT_NETWORK TQSocket : public TQObject, public TQIODevice -// #endif // USE_QT4 -{ - Q_OBJECT - TQ_OBJECT -public: - enum Error { - ErrConnectionRefused, - ErrHostNotFound, - ErrSocketRead - }; - - TQSocket( TQObject *parent=0, const char *name=0 ); - virtual ~TQSocket(); - - enum State { Idle, HostLookup, Connecting, - Connected, Closing, - Connection=Connected }; - State state() const; - - int socket() const; - virtual void setSocket( int ); - - TQSocketDevice *socketDevice(); - virtual void setSocketDevice( TQSocketDevice * ); - -#ifndef TQT_NO_DNS - virtual void connectToHost( const TQString &host, TQ_UINT16 port ); -#endif - TQString peerName() const; - - // Implementation of TQIODevice abstract virtual functions - bool open( int mode ); - void close(); - void flush(); -#ifdef USE_QT4 - qint64 size() const; - qint64 at() const; -#else // USE_QT4 - Offset size() const; - Offset at() const; -#endif // USE_QT4 - bool at( Offset ); - bool atEnd() const; - -#ifdef USE_QT4 - qint64 bytesAvailable() const; // ### TQIODevice::Offset instead? - qint64 bytesToWrite() const; -#else // USE_QT4 - TQ_ULONG bytesAvailable() const; // ### TQIODevice::Offset instead? - TQ_ULONG bytesToWrite() const; -#endif // USE_QT4 - TQ_ULONG waitForMore( int msecs, bool *timeout ) const; - TQ_ULONG waitForMore( int msecs ) const; // ### TQt 4.0: merge the two overloads - void clearPendingData(); - - TQ_LONG readBlock( char *data, TQ_ULONG maxlen ); - TQ_LONG writeBlock( const char *data, TQ_ULONG len ); - TQ_LONG readLine( char *data, TQ_ULONG maxlen ); - - int getch(); - int putch( int ); - int ungetch(int); - - bool canReadLine() const; - virtual TQString readLine(); - - TQ_UINT16 port() const; - TQ_UINT16 peerPort() const; - TQHostAddress address() const; - TQHostAddress peerAddress() const; - - void setReadBufferSize( TQ_ULONG ); - TQ_ULONG readBufferSize() const; - -Q_SIGNALS: - void hostFound(); - void connected(); - void connectionClosed(); - void delayedCloseFinished(); - void readyRead(); - void bytesWritten( int nbytes ); - void error( int ); - -protected Q_SLOTS: - virtual void sn_read( bool force=FALSE ); - virtual void sn_write(); - -private Q_SLOTS: - void tryConnecting(); - void emitErrorConnectionRefused(); - -private: - TQSocketPrivate *d; - - bool consumeWriteBuf( TQ_ULONG nbytes ); - void tryConnection(); - void setSocketIntern( int socket ); - -private: // Disabled copy constructor and operator= -#if defined(TQ_DISABLE_COPY) - TQSocket( const TQSocket & ); - TQSocket &operator=( const TQSocket & ); -#endif - -protected: - qint64 readData(char *data, qint64 maxlen); - qint64 writeData(const char *data, qint64 len); -}; - -#endif //TQT_NO_NETWORK -#endif // TQSOCKET_H diff --git a/tqtinterface/qt4/src/network/tqsocketdevice.cpp b/tqtinterface/qt4/src/network/tqsocketdevice.cpp deleted file mode 100644 index e2f7287..0000000 --- a/tqtinterface/qt4/src/network/tqsocketdevice.cpp +++ /dev/null @@ -1,584 +0,0 @@ -/**************************************************************************** -** -** Implementation of TQSocketDevice class. -** -** Created : 970521 -** -** Copyright (C) 2010 Timothy Pearson and (C) 1992-2008 Trolltech ASA. -** -** This file is part of the network module of the TQt 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 TQt 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.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** 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 "tqsocketdevice.h" -#ifndef TQT_NO_NETWORK - -#include "tqwindowdefs.h" -#include - - -//#define TQSOCKETDEVICE_DEBUG - - -class TQSocketDevicePrivate -{ -public: - TQSocketDevicePrivate( TQSocketDevice::Protocol p ) - : protocol(p) - { } - - TQSocketDevice::Protocol protocol; -}; - - -/*! - \class TQSocketDevice tqsocketdevice.h - \brief The TQSocketDevice class provides a platform-independent low-level socket API. -\if defined(commercial) - It is part of the TQt Enterprise Edition. -\endif - - \ingroup io - \module network - - This class provides a low level API for working with sockets. Users of - this class are assumed to have networking experience. For most users the - TQSocket class provides a much easier and high level alternative, but - certain things (like UDP) can't be done with TQSocket and if you need a - platform-independent API for those, TQSocketDevice is the right choice. - - The essential purpose of the class is to provide a TQIODevice that - works on sockets, wrapped in a platform-independent API. - - When calling connect() or bind(), TQSocketDevice detects the - protocol family (IPv4, IPv6) automatically. Passing the protocol - family to TQSocketDevice's constructor or to setSocket() forces - creation of a socket tqdevice of a specific protocol. If not set, the - protocol will be detected at the first call to connect() or bind(). - - \sa TQSocket, TQSocketNotifier, TQHostAddress -*/ - - -/*! - \enum TQSocketDevice::Protocol - - This enum type describes the protocol family of the socket. Possible values - are: - - \value IPv4 The socket is an IPv4 socket. - \value IPv6 The socket is an IPv6 socket. - \value Unknown The protocol family of the socket is not known. This can - happen if you use TQSocketDevice with an already existing socket; it - tries to determine the protocol family, but this can fail if the - protocol family is not known to TQSocketDevice. - - \sa protocol() setSocket() -*/ - -/*! - \enum TQSocketDevice::Error - - This enum type describes the error states of TQSocketDevice. - - \value NoError No error has occurred. - - \value AlreadyBound The tqdevice is already bound, according to bind(). - - \value Inaccessible The operating system or firewall prohibited - the action. - - \value NoResources The operating system ran out of a resource. - - \value InternalError An internal error occurred in TQSocketDevice. - - \value Impossible An attempt was made to do something which makes - no sense. For example: - \code - ::close( sd->socket() ); - sd->writeBlock( someData, 42 ); - \endcode - The libc ::close() closes the socket, but TQSocketDevice is not aware - of this. So when you call writeBlock(), the impossible happens. - - \value NoFiles The operating system will not let TQSocketDevice open - another file. - - \value ConnectionRefused A connection attempt was rejected by the - peer. - - \value NetworkFailure There is a network failure. - - \value UnknownError The operating system did something - unexpected. -*/ - -/*! - \enum TQSocketDevice::Type - - This enum type describes the type of the socket: - \value Stream a stream socket (TCP, usually) - \value Datagram a datagram socket (UDP, usually) -*/ - - -/*! - Creates a TQSocketDevice object for the existing socket \a socket. - - The \a type argument must match the actual socket type; use \c - TQSocketDevice::Stream for a reliable, connection-oriented TCP - socket, or \c TQSocketDevice::Datagram for an unreliable, - connectionless UDP socket. -*/ -TQSocketDevice::TQSocketDevice( int socket, Type type ) - : fd( socket ), t( type ), p( 0 ), pp( 0 ), e( NoError ), - d(new TQSocketDevicePrivate(Unknown)) -{ -#if defined(TQSOCKETDEVICE_DEBUG) - qDebug( "TQSocketDevice: Created TQSocketDevice %p (socket %x, type %d)", - this, socket, type ); -#endif - init(); - setSocket( socket, type ); -} - -/*! - Creates a TQSocketDevice object for a stream or datagram socket. - - The \a type argument must be either \c TQSocketDevice::Stream for a - reliable, connection-oriented TCP socket, or \c - TQSocketDevice::Datagram for an unreliable UDP socket. - - The socket is created as an IPv4 socket. - - \sa blocking() protocol() -*/ -TQSocketDevice::TQSocketDevice( Type type ) - : fd( -1 ), t( type ), p( 0 ), pp( 0 ), e( NoError ), - d(new TQSocketDevicePrivate(IPv4)) -{ -#if defined(TQSOCKETDEVICE_DEBUG) - qDebug( "TQSocketDevice: Created TQSocketDevice object %p, type %d", - this, type ); -#endif - init(); - setSocket( createNewSocket(), type ); -} - -/*! - Creates a TQSocketDevice object for a stream or datagram socket. - - The \a type argument must be either \c TQSocketDevice::Stream for a - reliable, connection-oriented TCP socket, or \c - TQSocketDevice::Datagram for an unreliable UDP socket. - - The \a protocol indicates whether the socket should be of type IPv4 - or IPv6. Passing \c Unknown is not meaningful in this context and you - should avoid using (it creates an IPv4 socket, but your code is not easily - readable). - - The argument \a dummy is necessary for compatibility with some - compilers. - - \sa blocking() protocol() -*/ -TQSocketDevice::TQSocketDevice( Type type, Protocol protocol, int ) - : fd( -1 ), t( type ), p( 0 ), pp( 0 ), e( NoError ), - d(new TQSocketDevicePrivate(protocol)) -{ -#if defined(TQSOCKETDEVICE_DEBUG) - qDebug( "TQSocketDevice: Created TQSocketDevice object %p, type %d", - this, type ); -#endif - init(); - setSocket( createNewSocket(), type ); -} - -/*! - Destroys the socket tqdevice and closes the socket if it is open. -*/ -TQSocketDevice::~TQSocketDevice() -{ - close(); - delete d; - d = 0; -#if defined(TQSOCKETDEVICE_DEBUG) - qDebug( "TQSocketDevice: Destroyed TQSocketDevice %p", this ); -#endif -} - - -/*! - Returns TRUE if this is a valid socket; otherwise returns FALSE. - - \sa socket() -*/ -bool TQSocketDevice::isValid() const -{ - return fd != -1; -} - - -/*! - \fn Type TQSocketDevice::type() const - - Returns the socket type which is either \c TQSocketDevice::Stream - or \c TQSocketDevice::Datagram. - - \sa socket() -*/ -TQSocketDevice::Type TQSocketDevice::type() const -{ - return t; -} - -/*! - Returns the socket's protocol family, which is one of \c Unknown, \c IPv4, - or \c IPv6. - - TQSocketDevice either creates a socket with a well known protocol family or - it uses an already existing socket. In the first case, this function - returns the protocol family it was constructed with. In the second case, it - tries to determine the protocol family of the socket; if this fails, it - returns \c Unknown. - - \sa Protocol setSocket() -*/ -TQSocketDevice::Protocol TQSocketDevice::protocol() const -{ - if ( d->protocol == Unknown ) - d->protocol = getProtocol(); - return d->protocol; -} - -/*! - Returns the socket number, or -1 if it is an invalid socket. - - \sa isValid(), type() -*/ -int TQSocketDevice::socket() const -{ - return fd; -} - - -/*! - Sets the socket tqdevice to operate on the existing socket \a - socket. - - The \a type argument must match the actual socket type; use \c - TQSocketDevice::Stream for a reliable, connection-oriented TCP - socket, or \c TQSocketDevice::Datagram for an unreliable, - connectionless UDP socket. - - Any existing socket is closed. - - \sa isValid(), close() -*/ -void TQSocketDevice::setSocket( int socket, Type type ) -{ - if ( fd != -1 ) // close any open socket - close(); -#if defined(TQSOCKETDEVICE_DEBUG) - qDebug( "TQSocketDevice::setSocket: socket %x, type %d", socket, type ); -#endif - t = type; - fd = socket; - d->protocol = Unknown; - e = NoError; - setFlags( IO_Sequential ); - resetqStatus(); - open( IO_ReadWrite ); - fetchConnectionParameters(); -} - - -/*! - \reimp - - Opens the socket using the specified TQIODevice file \a mode. This - function is called from the TQSocketDevice constructors and from - the setSocket() function. You should not call it yourself. - - \sa close(). -*/ -bool TQSocketDevice::open( int mode ) -{ - if ( isOpen() || !isValid() ) - return FALSE; -#if defined(TQSOCKETDEVICE_DEBUG) - qDebug( "TQSocketDevice::open: mode %x", mode ); -#endif - setMode( mode & IO_ReadWrite ); - setState( IO_Open ); - return TRUE; -} - - -/*! - \reimp - - The current TQSocketDevice implementation does not buffer at all, - so this is a no-op. -*/ -void TQSocketDevice::flush() -{ -} - - -/*! - \reimp - - The size is meaningless for a socket, therefore this function returns 0. -*/ -#ifdef USE_QT4 -qint64 TQSocketDevice::size() const -#else // USE_QT4 -TQIODevice::Offset TQSocketDevice::size() const -#endif // USE_QT4 -{ - return 0; -} - - -/*! - \reimp - - The read/write index is meaningless for a socket, therefore this - function returns 0. -*/ -#ifdef USE_QT4 -qint64 TQSocketDevice::at() const -#else // USE_QT4 -TQIODevice::Offset TQSocketDevice::at() const -#endif // USE_QT4 -{ - return 0; -} - - -/*! - \reimp - - The read/write index is meaningless for a socket, therefore this - function does nothing and returns TRUE. -*/ -bool TQSocketDevice::at( Offset ) -{ - return TRUE; -} - - -/*! - \reimp - - Returns TRUE if no data is currently available at the socket; - otherwise returns FALSE. -*/ -bool TQSocketDevice::atEnd() const -{ - return bytesAvailable() <= 0; -} - - -/*! - \reimp - - \warning getch() is implemented as a one-byte readBlock(), so it - may be very slow if you call it more than a few times. - - \sa putch() readBlock() -*/ -int TQSocketDevice::getch() -{ - char buf[2]; - return readBlock(buf,1) == 1 ? buf[0] : -1; -} - - -/*! - \reimp - - \warning putch() is implemented as a one-byte writeBlock(), so it - may be very slow if you call it more than a few times. - - \sa getch() -*/ -int TQSocketDevice::putch( int ch ) -{ - char buf[2]; - buf[0] = ch; - return writeBlock(buf, 1) == 1 ? ch : -1; -} - - -/*! - \reimp - - This implementation of ungetch returns -1 (error). A socket is a - sequential tqdevice and does not allow any ungetch operation. -*/ -int TQSocketDevice::ungetch( int ) -{ - return -1; -} - - -/*! - Returns TRUE if the address of this socket can be used by other - sockets at the same time, and FALSE if this socket claims - exclusive ownership. - - \sa setAddressReusable() -*/ -bool TQSocketDevice::addressReusable() const -{ - return option( ReuseAddress ); -} - - -/*! - Sets the address of this socket to be usable by other sockets too - if \a enable is TRUE, and to be used exclusively by this socket if - \a enable is FALSE. - - When a socket is reusable, other sockets can use the same port - number (and IP address), which is generally useful. Of course - other sockets cannot use the same - (address,port,peer-address,peer-port) 4-tuple as this socket, so - there is no risk of confusing the two TCP connections. - - \sa addressReusable() -*/ -void TQSocketDevice::setAddressReusable( bool enable ) -{ - setOption( ReuseAddress, enable ); -} - - -/*! - Returns the size of the operating system receive buffer. - - \sa setReceiveBufferSize() -*/ -int TQSocketDevice::receiveBufferSize() const -{ - return option( ReceiveBuffer ); -} - - -/*! - Sets the size of the operating system receive buffer to \a size. - - The operating system receive buffer size effectively limits two - things: how much data can be in transit at any one moment, and how - much data can be received in one iteration of the main event loop. - - The default is operating system-dependent. A socket that receives - large amounts of data is probably best with a buffer size of - 49152. -*/ -void TQSocketDevice::setReceiveBufferSize( uint size ) -{ - setOption( ReceiveBuffer, size ); -} - - -/*! - Returns the size of the operating system send buffer. - - \sa setSendBufferSize() -*/ -int TQSocketDevice::sendBufferSize() const -{ - return option( SendBuffer ); -} - - -/*! - Sets the size of the operating system send buffer to \a size. - - The operating system send buffer size effectively limits how much - data can be in transit at any one moment. - - The default is operating system-dependent. A socket that sends - large amounts of data is probably best with a buffer size of - 49152. -*/ -void TQSocketDevice::setSendBufferSize( uint size ) -{ - setOption( SendBuffer, size ); -} - - -/*! - Returns the port number of this socket tqdevice. This may be 0 for a - while, but is set to something sensible as soon as a sensible - value is available. - - Note that TQt always uses native byte order, i.e. 67 is 67 in TQt; - there is no need to call htons(). -*/ -TQ_UINT16 TQSocketDevice::port() const -{ - return p; -} - - -/*! - Returns the address of this socket tqdevice. This may be 0.0.0.0 for - a while, but is set to something sensible as soon as a sensible - value is available. -*/ -TQHostAddress TQSocketDevice::address() const -{ - return a; -} - - -/*! - Returns the first error seen. -*/ -TQSocketDevice::Error TQSocketDevice::error() const -{ - return e; -} - - -/*! - Allows subclasses to set the error state to \a err. -*/ -void TQSocketDevice::setError( Error err ) -{ - e = err; -} -#endif //TQT_NO_NETWORK - diff --git a/tqtinterface/qt4/src/network/tqsocketdevice.h b/tqtinterface/qt4/src/network/tqsocketdevice.h deleted file mode 100644 index 050ad5b..0000000 --- a/tqtinterface/qt4/src/network/tqsocketdevice.h +++ /dev/null @@ -1,185 +0,0 @@ -/**************************************************************************** -** -** Definition of TQSocketDevice class. -** -** Created : 970521 -** -** Copyright (C) 2010 Timothy Pearson and (C) 1992-2008 Trolltech ASA. -** -** This file is part of the network module of the TQt 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 TQt 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.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** 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. -** -**********************************************************************/ - -#ifndef TQSOCKETDEVICE_H -#define TQSOCKETDEVICE_H - -#ifndef TQT_H -#include "tqiodevice.h" -#include "tqhostaddress.h" // int->TQHostAddress conversion -#endif // TQT_H - -#if !defined( TQT_MODULE_NETWORK ) || defined( TQT_LICENSE_PROFESSIONAL ) || defined( TQT_INTERNAL_NETWORK ) -#define TQM_EXPORT_NETWORK -#else -#define TQM_EXPORT_NETWORK TQ_EXPORT -#endif - -#ifndef TQT_NO_NETWORK -class TQSocketDevicePrivate; - -#define QT_SOCKLEN_T socklen_t - -class TQM_EXPORT_NETWORK TQSocketDevice: public TQIODevice -{ -public: - enum Type { Stream, Datagram }; - enum Protocol { IPv4, IPv6, Unknown }; - - TQSocketDevice( Type type = Stream ); - TQSocketDevice( Type type, Protocol protocol, int dummy ); - TQSocketDevice( int socket, Type type ); - virtual ~TQSocketDevice(); - - bool isValid() const; - Type type() const; - Protocol protocol() const; - - int socket() const; - virtual void setSocket( int socket, Type type ); - - bool open( int mode ); - void close(); - void flush(); - - // Implementation of TQIODevice abstract virtual functions -#ifdef USE_QT4 - qint64 size() const; - qint64 at() const; -#else // USE_QT4 - Offset size() const; - Offset at() const; -#endif // USE_QT4 - bool at( Offset ); - bool atEnd() const; - - bool blocking() const; - virtual void setBlocking( bool ); - - bool addressReusable() const; - virtual void setAddressReusable( bool ); - - int receiveBufferSize() const; - virtual void setReceiveBufferSize( uint ); - int sendBufferSize() const; - virtual void setSendBufferSize( uint ); - - virtual bool connect( const TQHostAddress &, TQ_UINT16 ); - - virtual bool bind( const TQHostAddress &, TQ_UINT16 ); - virtual bool listen( int backlog ); - virtual int accept(); - -#ifdef USE_QT4 - qint64 bytesAvailable() const; -#else // USE_QT4 - TQ_LONG bytesAvailable() const; -#endif // USE_QT4 - TQ_LONG waitForMore( int msecs, bool *timeout=0 ) const; - TQ_LONG readBlock( char *data, TQ_ULONG maxlen ); - TQ_LONG writeBlock( const char *data, TQ_ULONG len ); - virtual TQ_LONG writeBlock( const char *data, TQ_ULONG len, - const TQHostAddress & host, TQ_UINT16 port ); - - int getch(); - int putch( int ); - int ungetch(int); - - TQ_UINT16 port() const; - TQ_UINT16 peerPort() const; - TQHostAddress address() const; - TQHostAddress peerAddress() const; - - enum Error { - NoError, - AlreadyBound, - Inaccessible, - NoResources, - InternalError, - Bug = InternalError, // ### remove in 4.0? - Impossible, - NoFiles, - ConnectionRefused, - NetworkFailure, - UnknownError - }; - Error error() const; - -protected: - void setError( Error err ); - -private: - int fd; - Type t; - TQ_UINT16 p; - TQHostAddress a; - TQ_UINT16 pp; - TQHostAddress pa; - TQSocketDevice::Error e; - TQSocketDevicePrivate * d; - - enum Option { Broadcast, ReceiveBuffer, ReuseAddress, SendBuffer }; - - int option( Option ) const; - virtual void setOption( Option, int ); - - void fetchConnectionParameters(); -#if defined(TQ_OS_WIN32) - void fetchPeerConnectionParameters(); -#endif - - static void init(); - int createNewSocket(); - Protocol getProtocol() const; - -private: // Disabled copy constructor and operator= -#if defined(TQ_DISABLE_COPY) - TQSocketDevice( const TQSocketDevice & ); - TQSocketDevice &operator=( const TQSocketDevice & ); -#endif - -protected: -// void setError( Error err ); - qint64 readData(char *data, qint64 maxlen); - qint64 writeData(const char *data, qint64 len); -}; - -#endif // TQT_NO_NETWORK -#endif // TQSOCKETDEVICE_H diff --git a/tqtinterface/qt4/src/network/tqsocketdevice_unix.cpp b/tqtinterface/qt4/src/network/tqsocketdevice_unix.cpp deleted file mode 100644 index 46c3932..0000000 --- a/tqtinterface/qt4/src/network/tqsocketdevice_unix.cpp +++ /dev/null @@ -1,1269 +0,0 @@ -/**************************************************************************** -** -** Implementation of TQSocketDevice class. -** -** Created : 970521 -** -** Copyright (C) 2010 Timothy Pearson and (C) 1992-2008 Trolltech ASA. -** -** This file is part of the network module of the TQt 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 TQt 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.TQPL -** included in the packaging of this file. Licensees holding valid TQt -** Commercial licenses may use this file in accordance with the TQt -** 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 "tqplatformdefs.h" - -// Almost always the same. If not, specify in qplatformdefs.h. -#if !defined(TQT_SOCKOPTLEN_T) -# define TQT_SOCKOPTLEN_T TQT_SOCKLEN_T -#endif - -// Tru64 redefines accept -> _accept with _XOPEN_SOURCE_EXTENDED -static inline int qt_socket_accept(int s, struct sockaddr *addr, TQT_SOCKLEN_T *addrlen) -{ return ::accept(s, addr, addrlen); } -#if defined(accept) -# undef accept -#endif - -// Solaris redefines bind -> __xnet_bind with _XOPEN_SOURCE_EXTENDED -static inline int qt_socket_bind(int s, struct sockaddr *addr, TQT_SOCKLEN_T addrlen) -{ return ::bind(s, addr, addrlen); } -#if defined(bind) -# undef bind -#endif - -// Solaris redefines connect -> __xnet_connect with _XOPEN_SOURCE_EXTENDED -static inline int qt_socket_connect(int s, struct sockaddr *addr, TQT_SOCKLEN_T addrlen) -{ return ::connect(s, addr, addrlen); } -#if defined(connect) -# undef connect -#endif - -// UnixWare 7 redefines listen -> _listen -static inline int qt_socket_listen(int s, int backlog) -{ return ::listen(s, backlog); } -#if defined(listen) -# undef listen -#endif - -// UnixWare 7 redefines socket -> _socket -static inline int qt_socket_socket(int domain, int type, int protocol) -{ return ::socket(domain, type, protocol); } -#if defined(socket) -# undef socket -#endif - -#include "tqsocketdevice.h" - -#ifndef TQT_NO_NETWORK - -#include "tqwindowdefs.h" - -#include -#include - - -static inline void qt_socket_getportaddr( struct sockaddr *sa, - TQ_UINT16 *port, TQHostAddress *addr ) -{ -#if !defined(TQT_NO_IPV6) - if ( sa->sa_family == AF_INET6 ) { - struct sockaddr_in6 *sa6 = ( struct sockaddr_in6 * )sa; - TQ_IPV6ADDR tmp; - memcpy( &tmp, &sa6->sin6_addr.s6_addr, sizeof(tmp) ); - TQHostAddress a( tmp ); - *addr = a; - *port = ntohs( sa6->sin6_port ); - return; - } -#endif - struct sockaddr_in *sa4 = (struct sockaddr_in *)sa; - TQHostAddress a( ntohl( sa4->sin_addr.s_addr ) ); - *port = ntohs( sa4->sin_port ); - *addr = TQHostAddress( ntohl( sa4->sin_addr.s_addr ) ); - return; -} - -#ifdef USE_QT4 - -qint64 TQSocketDevice::readData( char *data, qint64 maxlen ) -{ -#if defined(QT_CHECK_NULL) - if ( data == 0 && maxlen != 0 ) { - qWarning( "TQSocketDevice::readBlock: Null pointer error" ); - } -#endif -#if defined(QT_CHECK_STATE) - if ( !isValid() ) { - qWarning( "TQSocketDevice::readBlock: Invalid socket" ); - return -1; - } - if ( !isOpen() ) { - qWarning( "TQSocketDevice::readBlock: Device is not open" ); - return -1; - } - if ( !isReadable() ) { - qWarning( "TQSocketDevice::readBlock: Read operation not permitted" ); - return -1; - } -#endif - bool done = false; - int r = 0; - while ( done == false ) { - if ( t == Datagram ) { -#if !defined(QT_NO_IPV6) - struct sockaddr_storage aa; -#else - struct sockaddr_in aa; -#endif - memset( &aa, 0, sizeof(aa) ); - QT_SOCKLEN_T sz; - sz = sizeof( aa ); - r = ::recvfrom( fd, data, maxlen, 0, - (struct sockaddr *)&aa, &sz ); - - qt_socket_getportaddr( (struct sockaddr *)&aa, &pp, &pa); - - } else { - r = ::read( fd, data, maxlen ); - } - done = true; - if ( r == 0 && t == Stream && maxlen > 0 ) { - // connection closed - close(); - } else if ( r >= 0 || errno == EAGAIN || errno == EWOULDBLOCK ) { - // nothing - } else if ( errno == EINTR ) { - done = false; - } else if ( e == NoError ) { - switch( errno ) { - case EIO: - case EISDIR: - case EBADF: - case EINVAL: - case EFAULT: - case ENOTCONN: - case ENOTSOCK: - e = Impossible; - break; -#if defined(ENONET) - case ENONET: -#endif - case EHOSTUNREACH: - case ENETDOWN: - case ENETUNREACH: - case ETIMEDOUT: - e = NetworkFailure; - break; - case EPIPE: - case ECONNRESET: - // connection closed - close(); - r = 0; - break; - default: - e = UnknownError; - break; - } - } - } - return r; -} - - -qint64 TQSocketDevice::writeData( const char *data, qint64 len ) -{ - if ( data == 0 && len != 0 ) { -#if defined(QT_CHECK_NULL) || defined(QSOCKETDEVICE_DEBUG) - qWarning( "TQSocketDevice::writeBlock: Null pointer error" ); -#endif - return -1; - } - if ( !isValid() ) { -#if defined(QT_CHECK_STATE) || defined(QSOCKETDEVICE_DEBUG) - qWarning( "TQSocketDevice::writeBlock: Invalid socket" ); -#endif - return -1; - } - if ( !isOpen() ) { -#if defined(QT_CHECK_STATE) || defined(QSOCKETDEVICE_DEBUG) - qWarning( "TQSocketDevice::writeBlock: Device is not open" ); -#endif - return -1; - } - if ( !isWritable() ) { -#if defined(QT_CHECK_STATE) || defined(QSOCKETDEVICE_DEBUG) - qWarning( "TQSocketDevice::writeBlock: Write operation not permitted" ); -#endif - return -1; - } - bool done = false; - int r = 0; - bool timeout; - while ( !done ) { - r = ::write( fd, data, len ); - done = true; - if ( r < 0 && e == NoError && - errno != EAGAIN && errno != EWOULDBLOCK ) { - switch( errno ) { - case EINTR: // signal - call read() or whatever again - done = false; - break; - case EPIPE: - case ECONNRESET: - // connection closed - close(); - r = 0; - break; - case ENOSPC: - case EIO: - case EISDIR: - case EBADF: - case EINVAL: - case EFAULT: - case ENOTCONN: - case ENOTSOCK: - e = Impossible; - break; -#if defined(ENONET) - case ENONET: -#endif - case EHOSTUNREACH: - case ENETDOWN: - case ENETUNREACH: - case ETIMEDOUT: - e = NetworkFailure; - break; - default: - e = UnknownError; - break; - } - } else if ( waitForMore( 0, &timeout ) == 0 ) { - if ( !timeout ) { - // connection closed - close(); - } - } - } - return r; -} - -#endif // USE_QT4 - - -//#define TQSOCKETDEVICE_DEBUG - -// internal -void TQSocketDevice::init() -{ -} - - -TQSocketDevice::Protocol TQSocketDevice::getProtocol() const -{ - if ( isValid() ) { -#if !defined (TQT_NO_IPV6) - struct sockaddr_storage sa; -#else - struct sockaddr sa; -#endif - memset( &sa, 0, sizeof(sa) ); - TQT_SOCKLEN_T sz = sizeof( sa ); -#if !defined (TQT_NO_IPV6) - struct sockaddr *sap = reinterpret_cast(&sa); - if ( !::getsockname(fd, sap, &sz) ) { - switch ( sap->sa_family ) { - case AF_INET: - return IPv4; - case AF_INET6: - return IPv6; - default: - return Unknown; - } - } -#else - if ( !::getsockname(fd, &sa, &sz) ) { - switch ( sa.sa_family ) { - case AF_INET: - return IPv4; - default: - return Unknown; - } - } -#endif - } - return Unknown; -} - -/*! - Creates a new socket identifier. Returns -1 if there is a failure - to create the new identifier; error() explains why. - - \sa setSocket() -*/ - -int TQSocketDevice::createNewSocket() -{ -#if !defined(TQT_NO_IPV6) - int s = qt_socket_socket( protocol() == IPv6 ? AF_INET6 : AF_INET, - t == Datagram ? SOCK_DGRAM : SOCK_STREAM, 0 ); -#else - int s = qt_socket_socket( AF_INET, t==Datagram?SOCK_DGRAM:SOCK_STREAM, 0 ); -#endif - if ( s < 0 ) { - switch( errno ) { - case EPROTONOSUPPORT: - e = InternalError; // 0 is supposed to work for both types - break; - case ENFILE: - e = NoFiles; // special case for this - break; - case EACCES: - e = Inaccessible; - break; - case ENOBUFS: - case ENOMEM: - e = NoResources; - break; - case EINVAL: - e = Impossible; - break; - default: - e = UnknownError; - break; - } - } else { - // ensure that the socket is closed on exec..() after being dup()'ed by - // fork() in TQProcess. - ::fcntl(s, F_SETFD, FD_CLOEXEC); - return s; - } - return -1; -} - -/*! - \reimp - - Closes the socket and sets the socket identifier to -1 (invalid). - - (This function ignores errors; if there are any then a file - descriptor leakage might result. As far as we know, the only error - that can arise is EBADF, and that would of course not cause - leakage. There may be OS-specfic errors that we haven't come - across, however.) - - \sa open() -*/ -void TQSocketDevice::close() -{ - if ( fd == -1 || !isOpen() ) // already closed - return; - setFlags( IO_Sequential ); - resetqStatus(); - setState( 0 ); - ::close( fd ); -#if defined(TQSOCKETDEVICE_DEBUG) - qDebug( "TQSocketDevice::close: Closed socket %x", fd ); -#endif - fd = -1; - fetchConnectionParameters(); -} - - -/*! - Returns TRUE if the socket is valid and in blocking mode; - otherwise returns FALSE. - - Note that this function does not set error(). - - \warning On Windows, this function always returns TRUE since the - ioctlsocket() function is broken. - - \sa setBlocking(), isValid() -*/ -bool TQSocketDevice::blocking() const -{ - if ( !isValid() ) - return TRUE; - int s = fcntl(fd, F_GETFL, 0); - return !(s >= 0 && ((s & O_NDELAY) != 0)); -} - - -/*! - Makes the socket blocking if \a enable is TRUE or nonblocking if - \a enable is FALSE. - - Sockets are blocking by default, but we recommend using - nonblocking socket operations, especially for GUI programs that - need to be responsive. - - \warning On Windows, this function should be used with care since - whenever you use a TQSocketNotifier on Windows, the socket is - immediately made nonblocking. - - \sa blocking(), isValid() -*/ -void TQSocketDevice::setBlocking( bool enable ) -{ -#if defined(TQSOCKETDEVICE_DEBUG) - qDebug( "TQSocketDevice::setBlocking( %d )", enable ); -#endif - if ( !isValid() ) - return; - int tmp = ::fcntl(fd, F_GETFL, 0); - if ( tmp >= 0 ) - tmp = ::fcntl( fd, F_SETFL, enable ? (tmp&~O_NDELAY) : (tmp|O_NDELAY) ); - if ( tmp >= 0 ) - return; - if ( e ) - return; - switch( errno ) { - case EACCES: - case EBADF: - e = Impossible; - break; - case EFAULT: - case EAGAIN: -#if EAGAIN != EWOULDBLOCK - case EWOULDBLOCK: -#endif - case EDEADLK: - case EINTR: - case EINVAL: - case EMFILE: - case ENOLCK: - case EPERM: - default: - e = UnknownError; - } -} - - -/*! - Returns the value of the socket option \a opt. -*/ -int TQSocketDevice::option( Option opt ) const -{ - if ( !isValid() ) - return -1; - int n = -1; - int v = -1; - switch ( opt ) { - case Broadcast: - n = SO_BROADCAST; - break; - case ReceiveBuffer: - n = SO_RCVBUF; - break; - case ReuseAddress: - n = SO_REUSEADDR; - break; - case SendBuffer: - n = SO_SNDBUF; - break; - } - if ( n != -1 ) { - TQT_SOCKOPTLEN_T len; - len = sizeof(v); - int r = ::getsockopt( fd, SOL_SOCKET, n, (char*)&v, &len ); - if ( r >= 0 ) - return v; - if ( !e ) { - TQSocketDevice *that = (TQSocketDevice*)this; // mutable function - switch( errno ) { - case EBADF: - case ENOTSOCK: - that->e = Impossible; - break; - case EFAULT: - that->e = InternalError; - break; - default: - that->e = UnknownError; - break; - } - } - return -1; - } - return v; -} - - -/*! - Sets the socket option \a opt to \a v. -*/ -void TQSocketDevice::setOption( Option opt, int v ) -{ - if ( !isValid() ) - return; - int n = -1; // for really, really bad compilers - switch ( opt ) { - case Broadcast: - n = SO_BROADCAST; - break; - case ReceiveBuffer: - n = SO_RCVBUF; - break; - case ReuseAddress: - n = SO_REUSEADDR; - break; - case SendBuffer: - n = SO_SNDBUF; - break; - default: - return; - } - if ( ::setsockopt( fd, SOL_SOCKET, n, (char*)&v, sizeof(v)) < 0 && - e == NoError ) { - switch( errno ) { - case EBADF: - case ENOTSOCK: - e = Impossible; - break; - case EFAULT: - e = InternalError; - break; - default: - e = UnknownError; - break; - } - } -} - - -/*! - Connects to the IP address and port specified by \a addr and \a - port. Returns TRUE if it establishes a connection; otherwise returns FALSE. - If it returns FALSE, error() explains why. - - Note that error() commonly returns NoError for non-blocking - sockets; this just means that you can call connect() again in a - little while and it'll probably succeed. -*/ -bool TQSocketDevice::connect( const TQHostAddress &addr, TQ_UINT16 port ) -{ - if ( !isValid() ) - return FALSE; - - pa = addr; - pp = port; - - struct sockaddr_in a4; - struct sockaddr *aa; - TQT_SOCKLEN_T aalen; - -#if !defined(TQT_NO_IPV6) - struct sockaddr_in6 a6; - - if ( addr.isIPv6Address() ) { - memset( &a6, 0, sizeof(a6) ); - a6.sin6_family = AF_INET6; - a6.sin6_port = htons( port ); - TQ_IPV6ADDR ip6 = addr.toIPv6Address(); - memcpy( &a6.sin6_addr.s6_addr, &ip6, sizeof(ip6) ); - - aalen = sizeof( a6 ); - aa = (struct sockaddr *)&a6; - } else -#endif - if ( addr.isIPv4Address() ) { - memset( &a4, 0, sizeof(a4) ); - a4.sin_family = AF_INET; - a4.sin_port = htons( port ); - a4.sin_addr.s_addr = htonl( addr.toIPv4Address() ); - - aalen = sizeof(a4); - aa = (struct sockaddr *)&a4; - } else { - e = Impossible; - return FALSE; - } - - int r = qt_socket_connect( fd, aa, aalen ); - if ( r == 0 ) { - fetchConnectionParameters(); - return TRUE; - } - if ( errno == EISCONN || errno == EALREADY || errno == EINPROGRESS ) { - fetchConnectionParameters(); - return TRUE; - } - if ( e != NoError || errno == EAGAIN || errno == EWOULDBLOCK ) { - return FALSE; - } - switch( errno ) { - case EBADF: - case ENOTSOCK: - e = Impossible; - break; - case EFAULT: - case EAFNOSUPPORT: - e = InternalError; - break; - case ECONNREFUSED: - e = ConnectionRefused; - break; - case ETIMEDOUT: - case ENETUNREACH: - e = NetworkFailure; - break; - case EADDRINUSE: - e = NoResources; - break; - case EACCES: - case EPERM: - e = Inaccessible; - break; - default: - e = UnknownError; - break; - } - return FALSE; -} - - -/*! - Assigns a name to an unnamed socket. The name is the host address - \a address and the port number \a port. If the operation succeeds, - bind() returns TRUE; otherwise it returns FALSE without changing - what port() and address() return. - - bind() is used by servers for setting up incoming connections. - Call bind() before listen(). -*/ -bool TQSocketDevice::bind( const TQHostAddress &address, TQ_UINT16 port ) -{ - if ( !isValid() ) - return FALSE; - int r; - struct sockaddr_in a4; -#if !defined(TQT_NO_IPV6) - struct sockaddr_in6 a6; - - if ( address.isIPv6Address() ) { - memset( &a6, 0, sizeof(a6) ); - a6.sin6_family = AF_INET6; - a6.sin6_port = htons( port ); - TQ_IPV6ADDR tmp = address.toIPv6Address(); - memcpy( &a6.sin6_addr.s6_addr, &tmp, sizeof(tmp) ); - - r = qt_socket_bind( fd, (struct sockaddr *)&a6, sizeof(a6) ); - } else -#endif - if ( address.isIPv4Address() ) { - memset( &a4, 0, sizeof(a4) ); - a4.sin_family = AF_INET; - a4.sin_port = htons( port ); - a4.sin_addr.s_addr = htonl( address.toIPv4Address() ); - - r = qt_socket_bind( fd, (struct sockaddr*)&a4, sizeof(a4) ); - } else { - e = Impossible; - return FALSE; - } - - if ( r < 0 ) { - switch( errno ) { - case EINVAL: - e = AlreadyBound; - break; - case EACCES: - e = Inaccessible; - break; - case ENOMEM: - e = NoResources; - break; - case EFAULT: // a was illegal - case ENAMETOOLONG: // sz was wrong - e = InternalError; - break; - case EBADF: // AF_UNIX only - case ENOTSOCK: // AF_UNIX only - case EROFS: // AF_UNIX only - case ENOENT: // AF_UNIX only - case ENOTDIR: // AF_UNIX only - case ELOOP: // AF_UNIX only - e = Impossible; - break; - default: - e = UnknownError; - break; - } - return FALSE; - } - fetchConnectionParameters(); - return TRUE; -} - - -/*! - Specifies how many pending connections a server socket can have. - Returns TRUE if the operation was successful; otherwise returns - FALSE. A \a backlog value of 50 is quite common. - - The listen() call only applies to sockets where type() is \c - Stream, i.e. not to \c Datagram sockets. listen() must not be - called before bind() or after accept(). - - \sa bind(), accept() -*/ -bool TQSocketDevice::listen( int backlog ) -{ - if ( !isValid() ) - return FALSE; - if ( qt_socket_listen( fd, backlog ) >= 0 ) - return TRUE; - if ( !e ) - e = Impossible; - return FALSE; -} - - -/*! - Extracts the first connection from the queue of pending - connections for this socket and returns a new socket identifier. - Returns -1 if the operation failed. - - \sa bind(), listen() -*/ -int TQSocketDevice::accept() -{ - if ( !isValid() ) - return -1; - -#if !defined (TQT_NO_IPV6) - struct sockaddr_storage aa; -#else - struct sockaddr aa; -#endif - TQT_SOCKLEN_T l = sizeof( aa ); - bool done; - int s; - do { - s = qt_socket_accept( fd, (struct sockaddr*)&aa, &l ); - // we'll blithely throw away the stuff accept() wrote to aa - done = TRUE; - if ( s < 0 && e == NoError ) { - switch( errno ) { - case EINTR: - done = FALSE; - break; -#if defined(EPROTO) - case EPROTO: -#endif -#if defined(ENONET) - case ENONET: -#endif - case ENOPROTOOPT: - case EHOSTDOWN: - case EOPNOTSUPP: - case EHOSTUNREACH: - case ENETDOWN: - case ENETUNREACH: - case ETIMEDOUT: - // in all these cases, an error happened during connection - // setup. we're not interested in what happened, so we - // just treat it like the client-closed-quickly case. - case EPERM: - // firewalling wouldn't let us accept. we treat it like - // the client-closed-quickly case. - case EAGAIN: -#if EAGAIN != EWOULDBLOCK - case EWOULDBLOCK: -#endif - // the client closed the connection before we got around - // to accept()ing it. - break; - case EBADF: - case ENOTSOCK: - e = Impossible; - break; - case EFAULT: - e = InternalError; - break; - case ENOMEM: - case ENOBUFS: - e = NoResources; - break; - default: - e = UnknownError; - break; - } - } - } while (!done); - // ensure that the socket is closed on exec..() after being dup()'ed by - // fork() in TQProcess. - ::fcntl(s, F_SETFD, FD_CLOEXEC); - return s; -} - - -/*! - Returns the number of bytes available for reading, or -1 if an - error occurred. - - \warning On Microsoft Windows, we use the ioctlsocket() function - to determine the number of bytes queued on the socket. According - to Microsoft (KB Q125486), ioctlsocket() sometimes returns an - incorrect number. The only safe way to determine the amount of - data on the socket is to read it using readBlock(). TQSocket has - workarounds to deal with this problem. -*/ -#ifdef USE_QT4 -qint64 TQSocketDevice::bytesAvailable() const -#else // USE_QT4 -TQ_LONG TQSocketDevice::bytesAvailable() const -#endif // USE_QT4 -{ - if ( !isValid() ) - return -1; - - /* - Apparently, there is not consistency among different operating - systems on how to use FIONREAD. - - FreeBSD, Linux and Solaris all expect the 3rd argument to - ioctl() to be an int, which is normally 32-bit even on 64-bit - machines. - - IRIX, on the other hand, expects a size_t, which is 64-bit on - 64-bit machines. - - So, the solution is to use size_t initialized to zero to make - sure all bits are set to zero, preventing underflow with the - FreeBSD/Linux/Solaris ioctls. - */ - size_t nbytes = 0; - // gives shorter than true amounts on Unix domain sockets. - if ( ::ioctl(fd, FIONREAD, (char*)&nbytes) < 0 ) - return -1; - return (TQ_LONG) *((int *) &nbytes); -} - - -/*! - Wait up to \a msecs milliseconds for more data to be available. If - \a msecs is -1 the call will block indefinitely. - - Returns the number of bytes available for reading, or -1 if an - error occurred. - - If \a timeout is non-null and no error occurred (i.e. it does not - return -1): this function sets \a *timeout to TRUE, if the reason - for returning was that the timeout was reached; otherwise it sets - \a *timeout to FALSE. This is useful to find out if the peer - closed the connection. - - \warning This is a blocking call and should be avoided in event - driven applications. - - \sa bytesAvailable() -*/ -TQ_LONG TQSocketDevice::waitForMore( int msecs, bool *timeout ) const -{ - if ( !isValid() ) - return -1; - if ( fd >= FD_SETSIZE ) - return -1; - - fd_set fds; - struct timeval tv; - - FD_ZERO( &fds ); - FD_SET( fd, &fds ); - - tv.tv_sec = msecs / 1000; - tv.tv_usec = (msecs % 1000) * 1000; - - int rv = select( fd+1, &fds, 0, 0, msecs < 0 ? 0 : &tv ); - - if ( rv < 0 ) - return -1; - - if ( timeout ) { - if ( rv == 0 ) - *timeout = TRUE; - else - *timeout = FALSE; - } - - return bytesAvailable(); -} - - -/*! - Reads \a maxlen bytes from the socket into \a data and returns the - number of bytes read. Returns -1 if an error occurred. Returning 0 - is not an error. For Stream sockets, 0 is returned when the remote - host closes the connection. For Datagram sockets, 0 is a valid - datagram size. -*/ -TQ_LONG TQSocketDevice::readBlock( char *data, TQ_ULONG maxlen ) -{ -#if defined(TQT_CHECK_NULL) - if ( data == 0 && maxlen != 0 ) { - qWarning( "TQSocketDevice::readBlock: Null pointer error" ); - } -#endif -#if defined(TQT_CHECK_STATE) - if ( !isValid() ) { - qWarning( "TQSocketDevice::readBlock: Invalid socket" ); - return -1; - } - if ( !isOpen() ) { - qWarning( "TQSocketDevice::readBlock: Device is not open" ); - return -1; - } - if ( !isReadable() ) { - qWarning( "TQSocketDevice::readBlock: Read operation not permitted" ); - return -1; - } -#endif - bool done = FALSE; - int r = 0; - while ( done == FALSE ) { - if ( t == Datagram ) { -#if !defined(TQT_NO_IPV6) - struct sockaddr_storage aa; -#else - struct sockaddr_in aa; -#endif - memset( &aa, 0, sizeof(aa) ); - TQT_SOCKLEN_T sz; - sz = sizeof( aa ); - r = ::recvfrom( fd, data, maxlen, 0, - (struct sockaddr *)&aa, &sz ); - - qt_socket_getportaddr( (struct sockaddr *)&aa, &pp, &pa); - - } else { - r = ::read( fd, data, maxlen ); - } - done = TRUE; - if ( r == 0 && t == Stream && maxlen > 0 ) { - // connection closed - close(); - } else if ( r >= 0 || errno == EAGAIN || errno == EWOULDBLOCK ) { - // nothing - } else if ( errno == EINTR ) { - done = FALSE; - } else if ( e == NoError ) { - switch( errno ) { - case EIO: - case EISDIR: - case EBADF: - case EINVAL: - case EFAULT: - case ENOTCONN: - case ENOTSOCK: - e = Impossible; - break; -#if defined(ENONET) - case ENONET: -#endif - case EHOSTUNREACH: - case ENETDOWN: - case ENETUNREACH: - case ETIMEDOUT: - e = NetworkFailure; - break; - case EPIPE: - case ECONNRESET: - // connection closed - close(); - r = 0; - break; - default: - e = UnknownError; - break; - } - } - } - return r; -} - - -/*! - Writes \a len bytes to the socket from \a data and returns the - number of bytes written. Returns -1 if an error occurred. - - This is used for \c TQSocketDevice::Stream sockets. -*/ -TQ_LONG TQSocketDevice::writeBlock( const char *data, TQ_ULONG len ) -{ - if ( data == 0 && len != 0 ) { -#if defined(TQT_CHECK_NULL) || defined(TQSOCKETDEVICE_DEBUG) - qWarning( "TQSocketDevice::writeBlock: Null pointer error" ); -#endif - return -1; - } - if ( !isValid() ) { -#if defined(TQT_CHECK_STATE) || defined(TQSOCKETDEVICE_DEBUG) - qWarning( "TQSocketDevice::writeBlock: Invalid socket" ); -#endif - return -1; - } - if ( !isOpen() ) { -#if defined(TQT_CHECK_STATE) || defined(TQSOCKETDEVICE_DEBUG) - qWarning( "TQSocketDevice::writeBlock: Device is not open" ); -#endif - return -1; - } - if ( !isWritable() ) { -#if defined(TQT_CHECK_STATE) || defined(TQSOCKETDEVICE_DEBUG) - qWarning( "TQSocketDevice::writeBlock: Write operation not permitted" ); -#endif - return -1; - } - bool done = FALSE; - int r = 0; - bool timeout; - while ( !done ) { - r = ::write( fd, data, len ); - done = TRUE; - if ( r < 0 && e == NoError && - errno != EAGAIN && errno != EWOULDBLOCK ) { - switch( errno ) { - case EINTR: // signal - call read() or whatever again - done = FALSE; - break; - case EPIPE: - case ECONNRESET: - // connection closed - close(); - r = 0; - break; - case ENOSPC: - case EIO: - case EISDIR: - case EBADF: - case EINVAL: - case EFAULT: - case ENOTCONN: - case ENOTSOCK: - e = Impossible; - break; -#if defined(ENONET) - case ENONET: -#endif - case EHOSTUNREACH: - case ENETDOWN: - case ENETUNREACH: - case ETIMEDOUT: - e = NetworkFailure; - break; - default: - e = UnknownError; - break; - } - } else if ( waitForMore( 0, &timeout ) == 0 ) { - if ( !timeout ) { - // connection closed - close(); - } - } - } - return r; -} - - -/*! - \overload - - Writes \a len bytes to the socket from \a data and returns the - number of bytes written. Returns -1 if an error occurred. - - This is used for \c TQSocketDevice::Datagram sockets. You must - specify the \a host and \a port of the destination of the data. -*/ -TQ_LONG TQSocketDevice::writeBlock( const char * data, TQ_ULONG len, - const TQHostAddress & host, TQ_UINT16 port ) -{ - if ( t != Datagram ) { -#if defined(TQT_CHECK_STATE) || defined(TQSOCKETDEVICE_DEBUG) - qWarning( "TQSocketDevice::sendBlock: Not datagram" ); -#endif - return -1; // for now - later we can do t/tcp - } - - if ( data == 0 && len != 0 ) { -#if defined(TQT_CHECK_NULL) || defined(TQSOCKETDEVICE_DEBUG) - qWarning( "TQSocketDevice::sendBlock: Null pointer error" ); -#endif - return -1; - } - if ( !isValid() ) { -#if defined(TQT_CHECK_STATE) || defined(TQSOCKETDEVICE_DEBUG) - qWarning( "TQSocketDevice::sendBlock: Invalid socket" ); -#endif - return -1; - } - if ( !isOpen() ) { -#if defined(TQT_CHECK_STATE) || defined(TQSOCKETDEVICE_DEBUG) - qWarning( "TQSocketDevice::sendBlock: Device is not open" ); -#endif - return -1; - } - if ( !isWritable() ) { -#if defined(TQT_CHECK_STATE) || defined(TQSOCKETDEVICE_DEBUG) - qWarning( "TQSocketDevice::sendBlock: Write operation not permitted" ); -#endif - return -1; - } - struct sockaddr_in a4; - struct sockaddr *aa; - TQT_SOCKLEN_T slen; -#if !defined(TQT_NO_IPV6) - struct sockaddr_in6 a6; - if ( host.isIPv6Address() ) { - memset( &a6, 0, sizeof(a6) ); - a6.sin6_family = AF_INET6; - a6.sin6_port = htons( port ); - - TQ_IPV6ADDR tmp = host.toIPv6Address(); - memcpy( &a6.sin6_addr.s6_addr, &tmp, sizeof(tmp) ); - slen = sizeof( a6 ); - aa = (struct sockaddr *)&a6; - } else -#endif - if ( host.isIPv4Address() ) { - memset( &a4, 0, sizeof(a4) ); - a4.sin_family = AF_INET; - a4.sin_port = htons( port ); - a4.sin_addr.s_addr = htonl( host.toIPv4Address() ); - slen = sizeof(a4); - aa = (struct sockaddr *)&a4; - } else { - e = Impossible; - return -1; - } - - // we'd use MSG_DONTWAIT + MSG_NOTQT_SIGNAL if Stevens were right. - // but apparently Stevens and most implementors disagree - bool done = FALSE; - int r = 0; - while ( !done ) { - r = ::sendto( fd, data, len, 0, aa, slen); - done = TRUE; - if ( r < 0 && e == NoError && - errno != EAGAIN && errno != EWOULDBLOCK ) { - switch( errno ) { - case EINTR: // signal - call read() or whatever again - done = FALSE; - break; - case ENOSPC: - case EPIPE: - case EIO: - case EISDIR: - case EBADF: - case EINVAL: - case EFAULT: - case ENOTCONN: - case ENOTSOCK: - e = Impossible; - break; -#if defined(ENONET) - case ENONET: -#endif - case EHOSTUNREACH: - case ENETDOWN: - case ENETUNREACH: - case ETIMEDOUT: - e = NetworkFailure; - break; - default: - e = UnknownError; - break; - } - } - } - return r; -} - - -/*! - Fetches information about both ends of the connection: whatever is - available. -*/ -void TQSocketDevice::fetchConnectionParameters() -{ - if ( !isValid() ) { - p = 0; - a = TQHostAddress(); - pp = 0; - pa = TQHostAddress(); - return; - } -#if !defined(TQT_NO_IPV6) - struct sockaddr_storage sa; -#else - struct sockaddr_in sa; -#endif - memset( &sa, 0, sizeof(sa) ); - TQT_SOCKLEN_T sz; - sz = sizeof( sa ); - if ( !::getsockname( fd, (struct sockaddr *)(&sa), &sz ) ) - qt_socket_getportaddr( (struct sockaddr *)&sa, &p, &a ); - - sz = sizeof( sa ); - if ( !::getpeername( fd, (struct sockaddr *)(&sa), &sz ) ) - qt_socket_getportaddr( (struct sockaddr *)&sa, &pp, &pa ); -} - - -/*! - Returns the port number of the port this socket tqdevice is - connected to. This may be 0 for a while, but is set to something - sensible as soon as a sensible value is available. - - Note that for Datagram sockets, this is the source port of the - last packet received, and that it is in native byte order. -*/ -TQ_UINT16 TQSocketDevice::peerPort() const -{ - return pp; -} - - -/*! - Returns the address of the port this socket tqdevice is connected - to. This may be 0.0.0.0 for a while, but is set to something - sensible as soon as a sensible value is available. - - Note that for Datagram sockets, this is the source port of the - last packet received. -*/ -TQHostAddress TQSocketDevice::peerAddress() const -{ - return pa; -} - -#endif //TQT_NO_NETWORK -- cgit v1.2.3