ulxr_http_client.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                 ulxr_http_client.cpp  -  a simple http client
00003                              -------------------
00004     begin                : Sam Apr 20 2002
00005     copyright            : (C) 2002-2007 by Ewald Arnold
00006     email                : ulxmlrpcpp@ewald-arnold.de
00007 
00008     $Id: ulxr_http_client.cpp 940 2006-12-30 18:22:05Z ewald-arnold $
00009 
00010  ***************************************************************************/
00011 
00012 /**************************************************************************
00013  *
00014  * This program is free software; you can redistribute it and/or modify
00015  * it under the terms of the GNU Lesser General Public License as
00016  * published by the Free Software Foundation; either version 2 of the License,
00017  * or (at your option) any later version.
00018  *
00019  * This program is distributed in the hope that it will be useful,
00020  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00022  * GNU General Public License for more details.
00023  *
00024  * You should have received a copy of the GNU Lesser General Public License
00025  * along with this program; if not, write to the Free Software
00026  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00027  *
00028  ***************************************************************************/
00029 
00030 //#define ULXR_SHOW_TRACE
00031 //#define ULXR_DEBUG_OUTPUT
00032 //#define ULXR_SHOW_READ
00033 //#define ULXR_SHOW_WRITE
00034 
00035 #ifndef ULXR_OMIT_TCP_STUFF
00036 
00037 #define ULXR_NEED_EXPORTS
00038 #include <ulxmlrpcpp/ulxmlrpcpp.h>
00039 
00040 #if !defined(__BORLANDC__) && !defined(_MSC_VER)
00041 #include <unistd.h>
00042 #endif
00043 
00044 #include <cctype>
00045 #include <stdio.h>
00046 #include <sys/stat.h>
00047 
00048 #include <fstream>
00049 
00050 #include <ulxmlrpcpp/ulxr_http_client.h>
00051 #include <ulxmlrpcpp/ulxr_except.h>
00052 #include <ulxmlrpcpp/ulxr_http_protocol.h>
00053 
00054 
00055 namespace ulxr {
00056 
00057 
00058 ULXR_API_IMPL(void) BodyProcessor::process(const char * /* buffer */, unsigned /* len */)
00059 {
00060 }
00061 
00062 
00063 ULXR_API_IMPL0 BodyProcessor::~BodyProcessor()
00064 {
00065 }
00066 
00067 
00069 
00070 
00071 ULXR_API_IMPL0 HttpClient::HttpClient (HttpProtocol* prot)
00072 {
00073   ULXR_TRACE(ULXR_PCHAR("HttpClient(HttpProtocol*)"));
00074   protocol = prot;
00075   protocol->setChunkedTransfer(false);
00076 }
00077 
00078 
00079 ULXR_API_IMPL(void) HttpClient::interpreteHttpHeader()
00080 {
00081    ULXR_TRACE(ULXR_PCHAR("interpreteHttpHeader"));
00082    head_version = ULXR_PCHAR("");
00083    head_status = 500;
00084    head_phrase = ULXR_PCHAR("Internal error");
00085    protocol->splitHeaderLine(head_version, head_status, head_phrase);
00086    protocol->setPersistent(!protocol->determineClosing(head_version));
00087 }
00088 
00089 
00090 ULXR_API_IMPL(void) HttpClient::receiveResponse(BodyProcessor &proc)
00091 {
00092   ULXR_TRACE(ULXR_PCHAR("receiveResponse"));
00093   protocol->resetConnection();
00094 
00095   char buffer[ULXR_RECV_BUFFER_SIZE];
00096   char *buff_ptr;
00097 
00098   bool done = false;
00099   long readed;
00100   while (!done && ((readed = protocol->readRaw(buffer, sizeof(buffer))) > 0) )
00101   {
00102     buff_ptr = buffer;
00103 
00104     if (!protocol->hasBytesToRead())
00105       done = true;
00106 
00107     while (readed > 0)
00108     {
00109       Protocol::State state = protocol->connectionMachine(buff_ptr, readed);
00110       if (state == Protocol::ConnError)
00111         throw ConnectionException(TransportError,
00112                                   ulxr_i18n(ULXR_PCHAR("network problem occured")), 500);
00113 
00114       // switch to appropriate method when header is completely read
00115       else if (   state == Protocol::ConnSwitchToBody
00116                || state == Protocol::ConnBody)
00117       {
00118         interpreteHttpHeader();
00119         proc.process(buff_ptr, readed);
00120         readed = 0;
00121       }
00122     }
00123   }
00124 }
00125 
00126 
00129 class StringProcessor : public BodyProcessor
00130 {
00131  public:
00132    StringProcessor(Cpp8BitString &str_ref)
00133       : target(str_ref) {}
00134 
00135  public:
00136    virtual void process(const char *buffer, unsigned len)
00137    {
00138       target.append(buffer, len);
00139    }
00140 
00141  private:
00142    Cpp8BitString &target;
00143 };
00144 
00145 
00146 ULXR_API_IMPL(void) HttpClient::msgPUT(const Cpp8BitString &msg, const CppString &type,
00147                                     const CppString &resource)
00148 {
00149   ULXR_TRACE(ULXR_PCHAR("msgPUT"));
00150 
00151   if (!protocol->isOpen() )
00152     protocol->open();
00153 
00154   sendAuthentication();
00155   protocol->sendRequestHeader(ULXR_PCHAR("PUT"), resource, type, msg.length());
00156 #ifdef ULXR_USE_WXSTRING
00157   protocol->writeBody(msg.data(), msg.length());
00158 #else
00159   protocol->writeBody(msg.data(), msg.length());
00160 #endif
00161 
00162   BodyProcessor bp;
00163   receiveResponse(bp);
00164   if (getHttpStatus() != 200)
00165     throw ConnectionException(TransportError, getHttpPhrase(), getHttpStatus());
00166 
00167   if (!protocol->isPersistent() )
00168     protocol->close();
00169 }
00170 
00171 
00172 ULXR_API_IMPL(void) HttpClient::filePUT(const CppString &filename,
00173                                      const CppString &type,
00174                                      const CppString &resource)
00175 {
00176   ULXR_TRACE(ULXR_PCHAR("filePUT"));
00177 
00178   if (!protocol->isOpen() )
00179     protocol->open();
00180 
00181   FILE *ifs = fopen (getLatin1(filename).c_str(), "rb");
00182   if (ifs == 0)
00183     throw Exception(SystemError,
00184                     ulxr_i18n(ULXR_PCHAR("Cannot open file: "))+filename);
00185 
00186   struct stat statbuf;
00187   if (0 != stat (getLatin1(filename).c_str(), &statbuf) )
00188     throw Exception(SystemError,
00189                     ulxr_i18n(ULXR_PCHAR("Could not get information about file: "))+filename);
00190 
00191   sendAuthentication();
00192   protocol->sendRequestHeader(ULXR_PCHAR("PUT"), resource, type, statbuf.st_size);
00193 
00194   char buffer [ULXR_SEND_BUFFER_SIZE];
00195   long readed;
00196   try {
00197     while (!feof(ifs))
00198     {
00199       readed = fread(buffer, 1, sizeof(buffer), ifs);
00200       if (readed < 0)
00201         throw Exception(SystemError,
00202                         ulxr_i18n(ULXR_PCHAR("Could not read from file: "))+filename);
00203       protocol->writeBody(buffer, readed);
00204     }
00205   }
00206   catch (...)
00207   {
00208     fclose(ifs);
00209     throw;
00210   }
00211 
00212 //  bool eof_reached = feof(ifs);
00213   fclose(ifs);
00214 
00215   BodyProcessor bp;
00216   receiveResponse(bp);
00217 
00218   if (getHttpStatus() != 200)
00219     throw ConnectionException(TransportError,
00220                               getHttpPhrase(), getHttpStatus());
00221 
00222   if (!protocol->isPersistent() )
00223     protocol->close();
00224 }
00225 
00226 
00227 ULXR_API_IMPL(Cpp8BitString) HttpClient::msgGET(const CppString &resource)
00228 {
00229   ULXR_TRACE(ULXR_PCHAR("msgGET"));
00230   Cpp8BitString ret;
00231 
00232   if (!protocol->isOpen() )
00233     protocol->open();
00234 
00235   sendAuthentication();
00236   protocol->sendRequestHeader(ULXR_PCHAR("GET"), resource, ULXR_PCHAR(""), 0);
00237   StringProcessor sp (ret);
00238   receiveResponse(sp);
00239   if (getHttpStatus() != 200)
00240     throw ConnectionException(TransportError, getHttpPhrase(), getHttpStatus());
00241 
00242   if (!protocol->isPersistent() )
00243     protocol->close();
00244 
00245   return ret;
00246 }
00247 
00248 
00251 class FileProcessor : public BodyProcessor
00252 {
00253  public:
00254    FileProcessor(std::ostream &ostr_ref, const CppString &fn)
00255       : target(ostr_ref), name(fn) {}
00256 
00257  public:
00258    virtual void process(const char *buffer, unsigned len)
00259    {
00260      target.write(buffer, len);
00261      if (!target.good() )
00262        throw Exception(SystemError, ulxr_i18n(ULXR_PCHAR("Cannot write to file: "))+name);
00263    }
00264 
00265  private:
00266    std::ostream  &target;
00267    CppString         name;
00268 };
00269 
00270 
00271 ULXR_API_IMPL(void) HttpClient::fileGET(const CppString &filename,
00272                                      const CppString &resource)
00273 {
00274   ULXR_TRACE(ULXR_PCHAR("fileGET"));
00275 
00276   if (!protocol->isOpen() )
00277     protocol->open();
00278 
00279   std::ofstream ofs (getLatin1(filename).c_str(), std::ios::out | std::ios::binary);
00280   if (!ofs.good() )
00281     throw Exception(SystemError, ulxr_i18n(ULXR_PCHAR("Cannot create file: "))+filename);
00282 
00283   sendAuthentication();
00284   protocol->sendRequestHeader(ULXR_PCHAR("GET"), resource, ULXR_PCHAR(""), 0);
00285 
00286   FileProcessor fp(ofs, filename);
00287   receiveResponse(fp);
00288 
00289   if (getHttpStatus() != 200)
00290     throw ConnectionException(TransportError, getHttpPhrase(), getHttpStatus());
00291 
00292   if (!protocol->isPersistent() )
00293     protocol->close();
00294 }
00295 
00296 
00297 ULXR_API_IMPL(Cpp8BitString) HttpClient::msgPOST(
00298                      const Cpp8BitString &msg,
00299                      const CppString &type,
00300                      const CppString &resource)
00301 {
00302   ULXR_TRACE(ULXR_PCHAR("msgPOST"));
00303   Cpp8BitString ret;
00304 
00305   if (!protocol->isOpen() )
00306     protocol->open();
00307 
00308   sendAuthentication();
00309   protocol->sendRequestHeader(ULXR_PCHAR("POST"), resource, type, msg.length());
00310   protocol->writeBody(msg.data(), msg.length());
00311 
00312   StringProcessor sp (ret);
00313   receiveResponse(sp);
00314 
00315   if (getHttpStatus() != 200)
00316     throw ConnectionException(TransportError, getHttpPhrase(), getHttpStatus());
00317 
00318   if (!protocol->isPersistent() )
00319     protocol->close();
00320 
00321   return ret;
00322 }
00323 
00324 
00325 ULXR_API_IMPL(void) HttpClient::doDELETE(const CppString &resource)
00326 {
00327   ULXR_TRACE(ULXR_PCHAR("doDELETE"));
00328 
00329   if (!protocol->isOpen() )
00330     protocol->open();
00331 
00332   sendAuthentication();
00333   protocol->sendRequestHeader(ULXR_PCHAR("DELETE"), resource, ULXR_PCHAR(""), 0);
00334 
00335   BodyProcessor bp;
00336   receiveResponse(bp);
00337 
00338   if (getHttpStatus() != 200)
00339     throw ConnectionException(TransportError, getHttpPhrase(), getHttpStatus());
00340 
00341   if (!protocol->isPersistent() )
00342     protocol->close();
00343 }
00344 
00345 
00346 ULXR_API_IMPL(void) HttpClient::setMessageAuthentication(const CppString &user,
00347                                                       const CppString &pass)
00348 {
00349   ULXR_TRACE(ULXR_PCHAR("setMessageAuthentication"));
00350   http_user = user;
00351   http_pass = pass;
00352 }
00353 
00354 
00355 ULXR_API_IMPL(void) HttpClient::sendAuthentication()
00356 {
00357   ULXR_TRACE(ULXR_PCHAR("sendAuthentication"));
00358   if (http_user.length() != 0 && http_pass.length() != 0)
00359     protocol->setMessageAuthentication(http_user, http_pass);
00360 }
00361 
00362 
00363 ULXR_API_IMPL(int) HttpClient::getHttpStatus() const
00364 {
00365   return head_status;
00366 }
00367 
00368 
00369 ULXR_API_IMPL(CppString) HttpClient::getHttpPhrase() const
00370 {
00371   return head_phrase;
00372 }
00373 
00374 
00375 ULXR_API_IMPL(CppString) HttpClient::getHttpVersion() const
00376 {
00377   return head_version;
00378 }
00379 
00380 
00381 }  // namespace ulxr
00382 
00383 #endif // ULXR_OMIT_TCP_STUFF
00384 

Generated on Sun Aug 19 20:08:57 2007 for ulxmlrpcpp by  doxygen 1.5.1