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

httpfactory.cpp

Go to the documentation of this file.
00001 /*
00002 Opie-uBrowser.  a very small web browser, using on QTextBrowser for html display/parsing
00003 Copyright (C) 2002 Thomas Stephens
00004 
00005 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public
00006 License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later
00007 version.
00008 
00009 This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
00010 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
00011 Public License for more details.
00012 
00013 You should have received a copy of the GNU General Public License along with this program; if not, write to the Free
00014 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00015 */
00016 
00017 #include "httpfactory.h"
00018 
00019 HttpFactory::HttpFactory(QTextBrowser *newBrowser):QMimeSourceFactory()
00020 {
00021 //      socket = new QSocket;
00022         text = new QTextDrag;
00023         browser=newBrowser;
00024 //      comm = new HttpComm(socket, browser);
00025         image = new QImageDrag;
00026 }
00027 
00028 const QMimeSource * HttpFactory::data(const QString &abs_name) const
00029 {
00030         printf("HttpFactory::data: using absolute data func\n");
00031 
00032         int port=80, addrEnd, portSep;
00033         QString host, file, portS, name, tempString;
00034         bool done=false, isText=true;
00035         
00036 //      comm->setUp((QString *)&abs_name);
00037 
00038         name = abs_name;
00039 //      name = name.lower();
00040         name = name.stripWhiteSpace();
00041         
00042 //      printf("%s\n", name.latin1());
00043 
00044         if(name.startsWith("http://"))
00045         {
00046                 name = name.remove(0, 7);
00047         }
00048         else
00049         {
00050                 name.prepend(browser->context());
00051                 name = name.remove(0, 7);
00052         }
00053 
00054         addrEnd = name.find('/');
00055         if(addrEnd == -1)
00056         {
00057                 name += '/';
00058                 addrEnd = name.length()-1;
00059         }
00060 
00061         host = name;
00062         file = name;
00063 
00064         host.truncate(addrEnd);
00065         file.remove(0, addrEnd);
00066         
00067         portSep = host.find(':');
00068         if(portSep != -1)
00069         {
00070                 portS=host;
00071                 host.truncate(portSep);
00072                 portS.remove(0, portSep+1);
00073                 port = portS.toInt();
00074         }
00075 
00076 //      printf("%s %s %d\n", host.latin1(), file.latin1(), port);
00077         
00078         if(port == 80)
00079         {
00080                 portS="80";
00081         }
00082         
00083 //      if(file.find(".png", file.length()-4) != -1 || file.find(".gif", file.length()-4) != -1 || file.find(".jpg", file.length()-4) != -1)
00084 //      {
00085 //              isImage=true;
00086 //      }
00087 
00088 //      comm->setStuff(host, portS, file, text, image, isImage);
00089 
00090 //      socket->connectToHost(host, port);
00091 
00092         int con, bytesSent;
00093         struct sockaddr_in serverAddr;
00094         struct hostent * serverInfo = gethostbyname( host.latin1() );
00095         
00096         if( serverInfo == NULL )
00097         {
00098                 QMessageBox *mb = new QMessageBox(QObject::tr("Error!"),
00099                         QObject::tr("IP-Address not found"),
00100                         QMessageBox::NoIcon,
00101                         QMessageBox::Ok,
00102                         QMessageBox::NoButton,
00103                         QMessageBox::NoButton);
00104                 mb->exec();
00105                 perror("HttpFactory::data:");
00106                 return 0;
00107         }
00108         
00109         QByteArray data;
00110 //      printf( "HttpFactory::data: %s\n", inet_ntoa(*((struct in_addr *)serverInfo->h_addr )) );
00111         
00112         QString request("GET " + file + " HTTP/1.1\r\nHost: " + host + ':' + portS + "\r\nConnection: close\r\n\r\n");
00113          
00114         con = socket( AF_INET, SOCK_STREAM, 0 );
00115         if( con == -1 )
00116         {
00117                 QMessageBox *mb = new QMessageBox(QObject::tr("Error!"),
00118                         QObject::tr("Error creating socket"),
00119                         QMessageBox::NoIcon,
00120                         QMessageBox::Ok,
00121                         QMessageBox::NoButton,
00122                         QMessageBox::NoButton);
00123                 mb->exec();
00124                 perror("HttpFactory::data:");
00125                 return 0;
00126         }
00127         
00128         serverAddr.sin_family = AF_INET;
00129         serverAddr.sin_port = htons( port );
00130         serverAddr.sin_addr.s_addr = inet_addr( inet_ntoa(*((struct in_addr *)serverInfo->h_addr )) );
00131         memset( &(serverAddr.sin_zero), '\0', 8 );
00132         
00133         if(::connect( con, (struct sockaddr *)&serverAddr, sizeof(struct sockaddr)) == -1 )
00134         {
00135                 QMessageBox *mb = new QMessageBox(QObject::tr("Error!"),
00136                         QObject::tr("Error connecting to socket"),
00137                         QMessageBox::NoIcon,
00138                         QMessageBox::Ok,
00139                         QMessageBox::NoButton,
00140                         QMessageBox::NoButton);
00141                 mb->exec();
00142                 perror("HttpFactory::data:");
00143                 return 0;
00144         }
00145         
00146         
00147         bytesSent = send( con, request.latin1(), request.length(), 0);
00148 //      printf("HttpFactory::data: bytes written: %d out of: %d\n", bytesSent, request.length() );
00149 //      printf("HttpFactory::data: request sent:\n%s", request.latin1());
00150         
00151         data = this->processResponse( con, isText );
00152         
00153         ::close( con );
00154         
00155         if(isText)
00156         {
00157                 text->setText( QString( data ) );
00158                 return text;
00159         }
00160         else
00161         {
00162                 image->setImage( QImage( data ) );
00163                 return image;
00164         }
00165 }
00166 
00167 const QMimeSource * HttpFactory::data(const QString &abs_or_rel_name, const QString & context) const
00168 {
00169         printf("HttpFactory::data: using relative data func\n");
00170 
00171         if(abs_or_rel_name.startsWith(context))
00172         {
00173                 return data(abs_or_rel_name);
00174         }
00175         else
00176         {
00177                 return data(context + abs_or_rel_name);
00178         }
00179         
00180         return 0;
00181 }
00182 
00183 const QByteArray HttpFactory::processResponse( int sockfd, bool &isText ) const
00184 {
00185         QByteArray inputBin( 1 );
00186         QByteArray conClosedErr( 27 );
00187         char conClosedErrMsg[] = "Connection to server closed";
00188         QString currentLine;
00189         bool done=false, chunked=false;
00190         int dataLength = 0;
00191         
00192         for( int i = 0; i < 27; i++)
00193         {
00194                 conClosedErr[i] = conClosedErrMsg[i];
00195         }
00196         
00197         while( !done )
00198         {
00199                 recv( sockfd, inputBin.data(), inputBin.size(), 0 );
00200                 currentLine += *(inputBin.data());
00201                 
00202                 if( *(inputBin.data()) == '\n' )
00203                 {
00204                         if( currentLine.isEmpty() || currentLine.startsWith( "\r") )
00205                         {
00206                                 printf( "HttpFactory::processResponse: end of header\n" );
00207                                 if( chunked )
00208                                 {
00209                                         return recieveChunked( sockfd );
00210                                 } else {
00211                                         return recieveNormal( sockfd, dataLength );
00212                                 }
00213                                 done = true;
00214                         }
00215                         
00216                         if( currentLine.contains( "Transfer-Encoding: chunked", false) >= 1 )
00217                         {
00218                                 chunked = true;
00219 //                              printf( "HttpFactory::processResponse: chunked encoding\n" );
00220                         }
00221                         
00222                         if( currentLine.contains( "Content-Type: text", false ) >= 1 )
00223                         {
00224                                 isText = true;
00225 //                              printf( "HttpFactory::processResponse: content type text\n" );
00226                                 if( currentLine.contains( "html", false ) >= 1)
00227                                 {
00228                                         browser->setTextFormat(Qt::RichText);
00229 //                                      printf( "HttpFactory::processResponse: content type html\n" );
00230                                 }
00231                         }
00232                         
00233                         if( currentLine.contains( "Content-Type: image", false ) >= 1 )
00234                         {
00235                                 isText = false;
00236 //                              printf( "HttpFactory::processResponse: content type image\n" );
00237                         }
00238                         
00239                         if( currentLine.contains( "Content-Length", false ) >= 1 )
00240                         {
00241                                 currentLine.remove( 0, 16 );
00242                                 dataLength = currentLine.toInt();
00243 //                              printf( "HttpFactory::processResponse: content length: %d\n", dataLength );
00244                         }
00245                         
00246                         if( currentLine.contains( "404", false ) >= 1 )
00247                         {
00248 //                              printf( "HttpFactory::processResponse: 404 error\n" );
00249                                 return 0;
00250                         }
00251                         
00252                         currentLine = "";
00253 //                      printf("HttpFactory::processResponse: reseting currentLine: %s\n", currentLine.latin1() );
00254                 }
00255         }
00256 }
00257 
00258 const QByteArray HttpFactory::recieveNormal( int sockfd, int dataLen ) const
00259 {
00260 //      printf( "HttpFactory::recieveNormal: recieving w/out chunked encoding\n" );
00261         
00262         QByteArray data( dataLen );
00263         QByteArray temp( dataLen );
00264         int recieved, i;
00265         
00266         recieved = recv( sockfd, temp.data(), temp.size(), 0 );
00267 //      printf( "HttpFactory::recieveNormal: found some data: %s\n", (char *)temp.data() );
00268         for( i = 0; i < recieved; i++ )
00269         {
00270                 data[i] = temp[i];
00271         }
00272         dataLen -= recieved;
00273         while( dataLen > 0 )
00274         {
00275                 recieved = recv( sockfd, temp.data(), temp.size(), 0 );
00276                 dataLen -= recieved;
00277 //              printf( "HttpFactory::recieveNormal: found some more data: %s\n", (char *)temp.data() );
00278                 for( int j = 0; j < recieved; j++ )
00279                 {
00280                         data[i] = temp[j];
00281                         i++;
00282                 }
00283                 temp.fill('\0');
00284         }
00285         
00286 //      printf( "HttpFactory::recieveNormal: end of data\n" );
00287         return data;
00288 }
00289 
00290 const QByteArray HttpFactory::recieveChunked( int sockfd ) const
00291 {
00292 //      printf( "HttpFactory::recieveChunked: recieving data with chunked encoding\n" );
00293         
00294         QByteArray data;
00295         QByteArray temp( 1 );
00296         int recieved, i = 0, cSize = 0;
00297         QString cSizeS;
00298         
00299 //      printf( "HttpFactory::recieveChunked: temp.size(): %d\n", temp.size() );
00300         recv( sockfd, temp.data(), temp.size(), 0 );
00301         while( *(temp.data()) != '\n' && *(temp.data()) != ';' )
00302         {
00303 //              printf( "HttpFactory::recieveChunked: temp.size(): %d\n", temp.size() );
00304 //              printf( "HttpFactory::recieveChunked: temp.data(): %c\n", temp[0] );
00305                 cSizeS += temp[0];
00306                 recv( sockfd, temp.data(), temp.size(), 0 );
00307         }
00308         
00309 //      printf( "HttpFactory::recieveChunked: cSizeS: %s\n", cSizeS.latin1() );
00310         cSize = cSizeS.toInt( 0, 16 );
00311 //      printf( "HttpFactory::recieveChunked: first chunk of size: %d\n", cSize );
00312         
00313         if( *(temp.data()) == ';' )
00314         {
00315                 while( *(temp.data()) != '\n' )
00316                 {
00317                         recv( sockfd, temp.data(), temp.size(), 0 );
00318                 }
00319         }
00320         
00321         temp.fill( '\0', cSize );
00322         data.fill( '\0', cSize );
00323         
00324         while( cSize > 0 )
00325         {
00326                 while( cSize > 0 )
00327                 {
00328                         recieved = recv( sockfd, temp.data(), temp.size(), 0 );
00329                         cSize -= recieved;
00330                         for( int j = 0; j < recieved; j++ )
00331                         {
00332                                 data[i] = temp[j];
00333                                 i++;
00334                         }
00335                         temp.fill('\0', cSize);
00336                 }
00337                 
00338 //              printf( "HttpFactory::recieveChunked: current data:\n%s", data.data() );
00339                 
00340                 temp.fill('\0', 1);
00341                 cSizeS = "";
00342                 cSize = 0;
00343                 
00344                 recv( sockfd, temp.data(), temp.size(), 0 );
00345                 if( *(temp.data()) == '\r' )
00346                 {
00347                         recv( sockfd, temp.data(), temp.size(), 0 );
00348                 }
00349                 recv( sockfd, temp.data(), temp.size(), 0 );
00350                 while( *(temp.data()) != '\n' && *(temp.data()) != ';' )
00351                 {
00352 //                      printf( "HttpFactory::recieveChunked: temp.size(): %d\n", temp.size() );
00353 //                      printf( "HttpFactory::recieveChunked: temp.data(): %d\n", temp[0] );
00354                         cSizeS += temp[0];
00355                         recv( sockfd, temp.data(), temp.size(), 0 );
00356                 }
00357         
00358 //              printf( "HttpFactory::recieveChunked: cSizeS: %s\n", cSizeS.latin1() );
00359                 cSize = cSizeS.toInt( 0, 16 );
00360 //              printf( "HttpFactory::recieveChunked: next chunk of size: %d\n", cSize );
00361         
00362                 if( *(temp.data()) == ';' )
00363                 {
00364                         while( *(temp.data()) != '\n' )
00365                         {
00366                                 recv( sockfd, temp.data(), temp.size(), 0 );
00367                         }
00368                 }
00369         
00370                 temp.fill( '\0', cSize );
00371                 data.resize( data.size() + cSize );
00372         }
00373         
00374 //      printf( "HttpFactory::recieveChunked: end of data\n" );
00375         return data;
00376 }

Generated on Sat Nov 5 16:18:18 2005 for OPIE by  doxygen 1.4.2