• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

KDECore

khttpproxysocketdevice.cpp

Go to the documentation of this file.
00001 /*  -*- C++ -*-
00002  *  Copyright (C) 2003 Thiago Macieira <thiago.macieira@kdemail.net>
00003  *
00004  *
00005  *  Permission is hereby granted, free of charge, to any person obtaining
00006  *  a copy of this software and associated documentation files (the
00007  *  "Software"), to deal in the Software without restriction, including
00008  *  without limitation the rights to use, copy, modify, merge, publish,
00009  *  distribute, sublicense, and/or sell copies of the Software, and to
00010  *  permit persons to whom the Software is furnished to do so, subject to
00011  *  the following conditions:
00012  *
00013  *  The above copyright notice and this permission notice shall be included 
00014  *  in all copies or substantial portions of the Software.
00015  *
00016  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00017  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00018  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00019  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00020  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00021  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00022  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00023  */
00024 
00025 #include <config.h>
00026 
00027 #include <sys/types.h>
00028 #include <sys/socket.h>
00029 
00030 #include <qsocketnotifier.h>
00031 #include <qcstring.h>
00032 
00033 #include "kresolver.h"
00034 #include "ksocketaddress.h"
00035 #include "ksocketdevice.h"
00036 #include "khttpproxysocketdevice.h"
00037 
00038 using namespace KNetwork;
00039 
00040 KResolverEntry KHttpProxySocketDevice::defaultProxy;
00041 
00042 class KNetwork::KHttpProxySocketDevicePrivate
00043 {
00044 public:
00045   KResolverEntry proxy;
00046   QCString request;
00047   QCString reply;
00048   KSocketAddress peer;
00049 
00050   KHttpProxySocketDevicePrivate()
00051     : proxy(KHttpProxySocketDevice::defaultProxy)
00052   { }
00053 };
00054 
00055 KHttpProxySocketDevice::KHttpProxySocketDevice(const KSocketBase* parent)
00056   : KSocketDevice(parent), d(new KHttpProxySocketDevicePrivate)
00057 {
00058 }
00059 
00060 KHttpProxySocketDevice::KHttpProxySocketDevice(const KResolverEntry& proxy)
00061   : d(new KHttpProxySocketDevicePrivate)
00062 {
00063   d->proxy = proxy;
00064 }
00065 
00066 KHttpProxySocketDevice::~KHttpProxySocketDevice()
00067 {
00068   // nothing special to be done during closing
00069   // KSocketDevice::~KSocketDevice closes the socket
00070 
00071   delete d;
00072 }
00073 
00074 int KHttpProxySocketDevice::capabilities() const
00075 {
00076   return CanConnectString | CanNotBind | CanNotListen | CanNotUseDatagrams;
00077 }
00078 
00079 const KResolverEntry&
00080 KHttpProxySocketDevice::proxyServer() const
00081 {
00082   return d->proxy;
00083 }
00084 
00085 void KHttpProxySocketDevice::setProxyServer(const KResolverEntry& proxy)
00086 {
00087   d->proxy = proxy;
00088 }
00089 
00090 void KHttpProxySocketDevice::close()
00091 {
00092   d->reply = d->request = QCString();
00093   d->peer = KSocketAddress();
00094   KSocketDevice::close();
00095 }
00096 
00097 KSocketAddress KHttpProxySocketDevice::peerAddress() const
00098 {
00099   if (isOpen())
00100     return d->peer;
00101   return KSocketAddress();
00102 }
00103 
00104 KSocketAddress KHttpProxySocketDevice::externalAddress() const
00105 {
00106   return KSocketAddress();
00107 }
00108 
00109 bool KHttpProxySocketDevice::connect(const KResolverEntry& address)
00110 {
00111   if (d->proxy.family() == AF_UNSPEC)
00112     // no proxy server set !
00113     return KSocketDevice::connect(address);
00114 
00115   if (isOpen())
00116     {
00117       // socket is already open
00118       resetError();
00119       return true;
00120     }
00121 
00122   if (m_sockfd == -1)
00123     // socket isn't created yet
00124     return connect(address.address().nodeName(), 
00125            address.address().serviceName());
00126 
00127   d->peer = address.address();
00128   return parseServerReply();
00129 }
00130 
00131 bool KHttpProxySocketDevice::connect(const QString& node, const QString& service)
00132 {
00133   // same safety checks as above
00134   if (m_sockfd == -1 && (d->proxy.family() == AF_UNSPEC ||
00135              node.isEmpty() || service.isEmpty()))
00136     {
00137       // no proxy server set !
00138       setError(IO_ConnectError, NotSupported);
00139       return false;
00140     }
00141 
00142   if (isOpen())
00143     {
00144       // socket is already open
00145       return true;
00146     }
00147 
00148   if (m_sockfd == -1)
00149     {
00150       // must create the socket
00151       if (!KSocketDevice::connect(d->proxy))
00152     return false;       // also unable to contact proxy server
00153       setState(0);      // unset open flag
00154 
00155       // prepare the request
00156       QString request = QString::fromLatin1("CONNECT %1:%2 HTTP/1.1\r\n"
00157                         "Cache-Control: no-cache\r\n"
00158                         "Host: \r\n"
00159                         "\r\n");
00160       QString node2 = node;
00161       if (node.contains(':'))
00162     node2 = '[' + node + ']';
00163 
00164       d->request = request.arg(node2).arg(service).latin1();
00165     }
00166 
00167   return parseServerReply();
00168 }
00169 
00170 bool KHttpProxySocketDevice::parseServerReply()
00171 {
00172   // make sure we're connected
00173   if (!KSocketDevice::connect(d->proxy))
00174     if (error() == InProgress)
00175       return true;
00176     else if (error() != NoError)
00177       return false;
00178 
00179   if (!d->request.isEmpty())
00180     {
00181       // send request
00182       Q_LONG written = writeBlock(d->request, d->request.length());
00183       if (written < 0)
00184     {
00185       qDebug("KHttpProxySocketDevice: would block writing request!");
00186       if (error() == WouldBlock)
00187         setError(IO_ConnectError, InProgress);
00188       return error() == WouldBlock; // error
00189     }
00190       qDebug("KHttpProxySocketDevice: request written");
00191 
00192       d->request.remove(0, written);
00193 
00194       if (!d->request.isEmpty())
00195     {
00196       setError(IO_ConnectError, InProgress);
00197       return true;      // still in progress
00198     }
00199     }
00200 
00201   // request header is sent
00202   // must parse reply, but must also be careful not to read too much
00203   // from the buffer
00204 
00205   int index;
00206   if (!blocking())
00207     {
00208       Q_LONG avail = bytesAvailable();
00209       qDebug("KHttpProxySocketDevice: %ld bytes available", avail);
00210       setState(0);
00211       if (avail == 0)
00212     {
00213       setError(IO_ConnectError, InProgress);
00214       return true;
00215     }
00216       else if (avail < 0)
00217     return false;       // error!
00218 
00219       QByteArray buf(avail);
00220       if (peekBlock(buf.data(), avail) < 0)
00221     return false;       // error!
00222 
00223       QCString fullHeaders = d->reply + buf.data();
00224       // search for the end of the headers
00225       index = fullHeaders.find("\r\n\r\n");
00226       if (index == -1)
00227     {
00228       // no, headers not yet finished...
00229       // consume data from socket
00230       readBlock(buf.data(), avail);
00231       d->reply += buf.data();
00232       setError(IO_ConnectError, InProgress);
00233       return true;
00234     }
00235 
00236       // headers are finished
00237       index -= d->reply.length();
00238       d->reply += fullHeaders.mid(d->reply.length(), index + 4);
00239 
00240       // consume from socket
00241       readBlock(buf.data(), index + 4);
00242     }
00243   else
00244     {
00245       int state = 0;
00246       if (d->reply.right(3) == "\r\n\r")
00247     state = 3;
00248       else if (d->reply.right(2) == "\r\n")
00249     state = 2;
00250       else if (d->reply.right(1) == "\r")
00251     state = 1;
00252       while (state != 4)
00253     {
00254       char c = getch();
00255       d->reply += c;
00256 
00257       if ((state == 3 && c == '\n') ||
00258           (state == 1 && c == '\n') ||
00259           c == '\r')
00260         ++state;
00261       else
00262         state = 0;
00263     }
00264     }       
00265 
00266   // now really parse the reply
00267   qDebug("KHttpProxySocketDevice: get reply: %s\n",
00268      d->reply.left(d->reply.find('\r')).data());
00269   if (d->reply.left(7) != "HTTP/1." ||
00270       (index = d->reply.find(' ')) == -1 ||
00271       d->reply[index + 1] != '2')
00272     {
00273       setError(IO_ConnectError, NetFailure);
00274       return false;
00275     }
00276 
00277   // we've got it
00278   resetError();
00279   setState(IO_Open);
00280   return true;
00281 }

KDECore

Skip menu "KDECore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal