Main Page | Modules | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members | Related Pages

omgwebpagefetcher.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2005 by Tim Sutton   *
00003  *   tim@linfiniti.com   *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 2 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  *                                                                         *
00010  *   This program is distributed in the hope that it will be useful,       *
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00013  *   GNU General Public License for more details.                          *
00014  *                                                                         *
00015  *   You should have received a copy of the GNU General Public License     *
00016  *   along with this program; if not, write to the                         *
00017  *   Free Software Foundation, Inc.,                                       *
00018  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00019  ***************************************************************************/
00020 #include "omgwebpagefetcher.h"
00021 #include <QString>
00022 #include <QDebug>
00023 #include <iostream>
00024 #include <cassert>
00025 #include <QApplication>
00026 #include <QSettings>
00027 OmgWebPageFetcher::OmgWebPageFetcher(QObject *parent)
00028     : QObject(parent),
00029     mProxyId(0),
00030     mHostId(0),
00031     mHeaderId(0),
00032     mGetId(0)
00033 {
00034   mTimeOut = 30; // 30second timeout for web requests
00035   //
00036   // Setup signals and slots
00037   //
00038   connect(&mQHttp, SIGNAL(stateChanged(int)),
00039       this, SLOT(slotStateChanged(int)));
00040   connect(&mQHttp, SIGNAL(responseHeaderReceived(const QHttpResponseHeader &)),
00041       this, SLOT(slotResponseHeaderReceived(const QHttpResponseHeader &)));
00042   connect(&mQHttp, SIGNAL(requestFinished(int, bool)),
00043       this, SLOT(slotRequestFinished(int, bool)));
00044 }
00045 
00046 
00047 OmgWebPageFetcher::~OmgWebPageFetcher()
00048 {
00049   //finish should have been called already which deletes qhttp pointer
00050 }
00051 
00052 
00053 
00054 QString OmgWebPageFetcher::getPage(QString theUrl)
00055 {
00056   if (theUrl.isEmpty())
00057   {
00058     emit statusChanged("Can not have a request with empty url!");
00059     return QString("");
00060   }
00061   qDebug("Initialising Web Page Fetcher, current id should be 0, Current Id is: " + QString::number(mQHttp.currentId()).toLocal8Bit());
00062   //mQHttp.clearPendingRequests();
00063   mQUrl = QUrl(theUrl);
00064   emit statusChanged("Set url to :  " +  mQUrl.path());
00065   mBusyFlag=true;
00066   //
00067   // Setup proxy if needed
00068   //
00069   QSettings mySettings;
00070   bool myProxyFlag = mySettings.value("proxy/proxyEnabled", "0").toBool();
00071   if (myProxyFlag)
00072   {
00073     QString myHost = mySettings.value("proxy/proxyHost", "").toString();
00074     int myPort = mySettings.value("proxy/proxyPort", "").toInt();
00075     QString myUser = mySettings.value("proxy/proxyUser", "").toString();
00076     QString myPassword = mySettings.value("proxy/proxyPassword", "").toString();
00077     mProxyId = mQHttp.setProxy(myHost, myPort , myUser, myPassword);
00078     qDebug("User:" + myUser.toLocal8Bit());
00079     qDebug("Pwd: ********** ");
00080     qDebug("Host:" + myHost.toLocal8Bit());
00081     qDebug("Port:" + QString::number(myPort).toLocal8Bit());
00082     qDebug ("Id for proxy setup: " + QString::number(mProxyId).toLocal8Bit());
00083   }
00084   else //no proxy so we can just move on to getting the host
00085   {
00086     mHostId = mQHttp.setHost(mQUrl.host());
00087     qDebug("Set host to" + mQUrl.host().toLocal8Bit() + " request id is " + QString::number(mHostId).toLocal8Bit());
00088     //see slotRequesFinished.....
00089     //QTimer::singleShot( mTimeOut * 1000, this, SLOT(slotTimeOut()) );
00090   }
00091   // block until page is returned
00092   while (mBusyFlag)
00093   {
00094     QApplication::processEvents();
00095   }
00096   return mPageContent ;
00097 }
00098 
00099 void OmgWebPageFetcher::finish()
00100 {
00101   qDebug ("Web page fetcher finish() reached....");
00102   // Don't go back to slotRequestFinished
00103   /*
00104   mQHttp.blockSignals(true);
00105   disconnect(&mQHttp);
00106   mQHttp.abort();
00107   mQHttp.clearPendingRequests();
00108   mQHttp.close();
00109   */
00110   mProxyId=0;
00111   mHostId=0;
00112   mHeaderId=0;
00113   mGetId=0;
00114   emit statusChanged("Requests completed, closing connection");
00115   qDebug ("....done\n\n");
00116   mBusyFlag=false;
00117 }
00118 
00119 void OmgWebPageFetcher::slotRequestFinished(int id, bool error)
00120 {
00121   qDebug("Request " + QString::number(id).toLocal8Bit()  + " finished");
00122   qDebug("Proxy Id " + QString::number(mProxyId).toLocal8Bit() );
00123   qDebug("Host Id " + QString::number(mHostId).toLocal8Bit() );
00124   qDebug("Header Id " + QString::number(mHeaderId).toLocal8Bit() );
00125   qDebug("Body Id " + QString::number(mGetId).toLocal8Bit() );
00126   if(error)
00127   {
00128     qDebug("Request Finished Error: " +  mQHttp.errorString().toLocal8Bit());
00129     emit statusChanged(  "Error: " +  mQHttp.errorString() );
00130     //finish();
00131   }
00132   else if(id == mProxyId) //proxy setup ok (optional)
00133   {
00134     qDebug("Proxy set!");
00135     mHostId = mQHttp.setHost(mQUrl.host());
00136     qDebug("Set host to" + mQUrl.host().toLocal8Bit() + " request id is " + QString::number(mHostId).toLocal8Bit());
00137     //now we sit back and wait for the host id to come, then we
00138     //will ask for the header, then we will get the body...
00139     //QTimer::singleShot( mTimeOut * 1000, this, SLOT(slotTimeOut()) );
00140   }
00141   else if(id == mHostId) //host retrieved
00142   {
00143     qDebug("Host set!");
00144     if(!mQUrl.encodedQuery().isNull() || !mQUrl.fragment().isEmpty() )
00145     {
00146       mRequestQString = mQUrl.toString();
00147     }
00148     else
00149     {
00150       mRequestQString = mQUrl.path();
00152     }
00153     qDebug("Requesting headers for url \n" + mRequestQString.toLocal8Bit());
00154     mHeaderId = mQHttp.head(mRequestQString);
00155     qDebug("Header id for this request is " + QString::number(mHeaderId).toLocal8Bit());
00156   }
00157   else if(id == mHeaderId) //head retrieved
00158   {
00159     qDebug("Page header Received!");
00160     requestHeadFinished(id);
00161   }
00162   else if(id == mGetId)  //body retrieved
00163   {
00164     qDebug("Page body Received");
00165     mPageContent = mQHttp.readAll();
00166     mQHttp.blockSignals(true);
00167     //qDebug() << myContentString;
00168     qDebug ("Request completed...state id is now " +
00169            QString::number(mQHttp.state()).toLocal8Bit() 
00170            + "\nClosing connection");
00171     //
00172     // NOTE Its important to *first* call finish and then only emit the request finished signal
00173     // otherwise clients might start to manipulate thise object before it has properly cleaned
00174     // itself up!
00175     //
00176     finish();
00177     //must be last thing we do!
00178     //emit requestGetFinished(mPageContent);
00179   }
00180   else // id did not match any expected
00181   {
00182     qDebug ("Request finished for unknown id");
00183   }
00184 }
00185 
00186 void OmgWebPageFetcher::slotTimeOut()
00187 {
00188   //qDebug() <<   " * * * Web Page Fetcher request timed out * * * " ;
00189   if(mQHttp.state() == QHttp::Connecting)
00190   {
00191     assert(mQHttp.currentId() == mHeaderId ||
00192            mQHttp.currentId() == mGetId);
00193     emit statusChanged("Error: timeout on connection");
00194     finish();
00195   }
00196 }
00197 
00198 void OmgWebPageFetcher::slotResponseHeaderReceived(const QHttpResponseHeader& resp)
00199 {
00200   mQHttpResponseHeader = resp;
00201 }
00202 
00203 void OmgWebPageFetcher::requestHeadFinished(int id)
00204 {
00205   qDebug ("Header request finished");
00206   qDebug ("Content type returned : " + mQHttpResponseHeader.contentType().toLocal8Bit());
00207   assert(id == mHeaderId);
00208   int myStatusCode=mQHttpResponseHeader.statusCode();
00209   // 405 -> it might not support HEAD request's...
00210   // 200 -> ok, operation successful
00211   // See also http://www.the-eggman.com/seminars/html_error_codes.htm
00212   if( (myStatusCode == 200 || myStatusCode == 202 || myStatusCode == 405) &&
00213       (mQHttpResponseHeader.contentType() == "text/html" ||
00214        mQHttpResponseHeader.contentType() == "text/plain" ||
00215        mQHttpResponseHeader.contentType() == "text/xml") )
00216   {
00217     //move on to request the body now
00218     mGetId = mQHttp.get(mRequestQString);
00219     qDebug("Page header received successfully");
00220     emit statusChanged("Page header received successfully: " + mQHttpResponseHeader.statusCode());
00221   }
00222   else if (myStatusCode == 301)
00223   { 
00224     qDebug("301 Error");
00225     emit statusChanged("requestHeadFinished Error: " + QString::number(myStatusCode) + " Page moved permanently!");
00226     finish();
00227    }
00228    else if (myStatusCode == 302)
00229   {
00230     qDebug("302 Error");
00231     emit statusChanged("requestHeadFinished Error: " + QString::number(myStatusCode) + " Page moved temporarily!");
00232     finish();
00233   }
00234   else
00235   {
00236     qDebug("Header retrieval Error" + QString::number(myStatusCode).toLocal8Bit());
00237     emit statusChanged("requestHeadFinished Error: " + myStatusCode  );
00238     finish();
00239   }
00240 }
00241 
00242 
00243 
00244 QString OmgWebPageFetcher::url()
00245 {
00246   return mQUrl.toString();
00247 }
00248 
00249 
00250 void OmgWebPageFetcher::slotStateChanged(int state)
00251 {
00252   switch (state)
00253   {
00254   case QHttp::Unconnected:
00255     qDebug("---->State Change<---- Unconnected");
00256     emit statusChanged("Unconnected");
00257     break;
00258   case QHttp::HostLookup:
00259     qDebug("---->State Change<---- Host Lookup");
00260     emit statusChanged("Host Lookup");
00261     break;
00262   case QHttp::Connecting:
00263     qDebug("---->State Change<---- Connecting");
00264     emit statusChanged("Connecting");
00265     break;
00266   case QHttp::Sending:
00267     qDebug("---->State Change<---- Sending");
00268     emit statusChanged("Sending");
00269     break;
00270   case QHttp::Reading:
00271     qDebug("---->State Change<---- Reading");
00272     emit statusChanged("Reading");
00273     break;
00274   case QHttp::Connected:
00275     qDebug("---->State Change<---- Connected");
00276     emit statusChanged("Connected");
00277     break;
00278   case QHttp::Closing: ;
00279     qDebug("---->State Change<---- Closing");
00280     emit statusChanged("Closing");
00281     break;
00282   default :
00283     qDebug("---->State Change<---- Illegal state");
00284     emit statusChanged("Illegal state");
00285     break;
00286   }
00287 }

Generated on Mon Apr 28 15:09:21 2008 for openModellerDesktop by  doxygen 1.4.1-20050210