XmlRpcUtil.cpp
Go to the documentation of this file.
00001 
00002 #include "XmlRpcUtil.h"
00003 
00004 #ifndef MAKEDEPEND
00005 # include <ctype.h>
00006 # include <iostream>
00007 # include <stdarg.h>
00008 # include <stdio.h>
00009 # include <string.h>
00010 #endif
00011 
00012 #include "XmlRpc.h"
00013 
00014 using namespace XmlRpc;
00015 
00016 
00017 //#define USE_WINDOWS_DEBUG // To make the error and log messages go to VC++ debug output
00018 #ifdef USE_WINDOWS_DEBUG
00019 #define WIN32_LEAN_AND_MEAN
00020 #include <windows.h>
00021 #endif
00022 
00023 // Version id
00024 const char XmlRpc::XMLRPC_VERSION[] = "XMLRPC++ 0.7";
00025 
00026 // Default log verbosity: 0 for no messages through 5 (writes everything)
00027 int XmlRpcLogHandler::_verbosity = 0;
00028 
00029 // Default log handler
00030 static class DefaultLogHandler : public XmlRpcLogHandler {
00031 public:
00032 
00033   void log(int level, const char* msg) { 
00034 #ifdef USE_WINDOWS_DEBUG
00035     if (level <= _verbosity) { OutputDebugString(msg); OutputDebugString("\n"); }
00036 #else
00037     if (level <= _verbosity) std::cout << msg << std::endl; 
00038 #endif  
00039   }
00040 
00041 } defaultLogHandler;
00042 
00043 // Message log singleton
00044 XmlRpcLogHandler* XmlRpcLogHandler::_logHandler = &defaultLogHandler;
00045 
00046 
00047 // Default error handler
00048 static class DefaultErrorHandler : public XmlRpcErrorHandler {
00049 public:
00050 
00051 #ifdef USE_WINDOWS_DEBUG
00052   void error(const char* msg) {
00053     OutputDebugString(msg); OutputDebugString("\n");
00054 #else
00055   void error(const char*) {
00056 #endif  
00057     // As far as I can tell, throwing an exception here is a bug, unless
00058     // the intention is that the program should exit.  Throughout the code,
00059     // calls to error() are followed by cleanup code that does things like
00060     // closing a failed socket.  Thus it would seem that it should be
00061     // possible to continue execution.  But if the user just catches the
00062     // exception that's thrown here, the library ends up in a bogus state.
00063     // So I'm commenting out the throw.  - BPG
00064     //
00065     //throw std::runtime_error(msg);
00066   }
00067 } defaultErrorHandler;
00068 
00069 
00070 // Error handler singleton
00071 XmlRpcErrorHandler* XmlRpcErrorHandler::_errorHandler = &defaultErrorHandler;
00072 
00073 
00074 // Easy API for log verbosity
00075 int XmlRpc::getVerbosity() { return XmlRpcLogHandler::getVerbosity(); }
00076 void XmlRpc::setVerbosity(int level) { XmlRpcLogHandler::setVerbosity(level); }
00077 
00078  
00079 
00080 void XmlRpcUtil::log(int level, const char* fmt, ...)
00081 {
00082   if (level <= XmlRpcLogHandler::getVerbosity())
00083   {
00084     va_list va;
00085     char buf[1024];
00086     va_start( va, fmt);
00087     vsnprintf(buf,sizeof(buf)-1,fmt,va);
00088     va_end(va);
00089     buf[sizeof(buf)-1] = 0;
00090     XmlRpcLogHandler::getLogHandler()->log(level, buf);
00091   }
00092 }
00093 
00094 
00095 void XmlRpcUtil::error(const char* fmt, ...)
00096 {
00097   va_list va;
00098   va_start(va, fmt);
00099   char buf[1024];
00100   vsnprintf(buf,sizeof(buf)-1,fmt,va);
00101   va_end(va);
00102   buf[sizeof(buf)-1] = 0;
00103   XmlRpcErrorHandler::getErrorHandler()->error(buf);
00104 }
00105 
00106 
00107 // Returns contents between <tag> and </tag>, updates offset to char after </tag>
00108 std::string 
00109 XmlRpcUtil::parseTag(const char* tag, std::string const& xml, int* offset)
00110 {
00111   if (*offset >= int(xml.length())) return std::string();
00112   size_t istart = xml.find(tag, *offset);
00113   if (istart == std::string::npos) return std::string();
00114   istart += strlen(tag);
00115   std::string etag = "</";
00116   etag += tag + 1;
00117   size_t iend = xml.find(etag, istart);
00118   if (iend == std::string::npos) return std::string();
00119 
00120   *offset = int(iend + etag.length());
00121   return xml.substr(istart, iend-istart);
00122 }
00123 
00124 
00125 // Returns true if the tag is found and updates offset to the char after the tag
00126 bool 
00127 XmlRpcUtil::findTag(const char* tag, std::string const& xml, int* offset)
00128 {
00129   if (*offset >= int(xml.length())) return false;
00130   size_t istart = xml.find(tag, *offset);
00131   if (istart == std::string::npos)
00132     return false;
00133 
00134   *offset = int(istart + strlen(tag));
00135   return true;
00136 }
00137 
00138 
00139 // Returns true if the tag is found at the specified offset (modulo any whitespace)
00140 // and updates offset to the char after the tag
00141 bool 
00142 XmlRpcUtil::nextTagIs(const char* tag, std::string const& xml, int* offset)
00143 {
00144   if (*offset >= int(xml.length())) return false;
00145   const char* cp = xml.c_str() + *offset;
00146   int nc = 0;
00147   while (*cp && isspace(*cp)) {
00148     ++cp;
00149     ++nc;
00150   }
00151 
00152   int len = int(strlen(tag));
00153   if  (*cp && (strncmp(cp, tag, len) == 0)) {
00154     *offset += nc + len;
00155     return true;
00156   }
00157   return false;
00158 }
00159 
00160 // Returns the next tag and updates offset to the char after the tag, or empty string
00161 // if the next non-whitespace character is not '<'
00162 std::string 
00163 XmlRpcUtil::getNextTag(std::string const& xml, int* offset)
00164 {
00165   if (*offset >= int(xml.length())) return std::string();
00166 
00167   size_t pos = *offset;
00168   const char* cp = xml.c_str() + pos;
00169   while (*cp && isspace(*cp)) {
00170     ++cp;
00171     ++pos;
00172   }
00173 
00174   if (*cp != '<') return std::string();
00175 
00176   std::string s;
00177   do {
00178     s += *cp;
00179     ++pos;
00180   } while (*cp++ != '>' && *cp != 0);
00181 
00182   *offset = int(pos);
00183   return s;
00184 }
00185 
00186 
00187 
00188 // xml encodings (xml-encoded entities are preceded with '&')
00189 static const char  AMP = '&';
00190 static const char  rawEntity[] = { '<',   '>',   '&',    '\'',    '\"',    0 };
00191 static const char* xmlEntity[] = { "lt;", "gt;", "amp;", "apos;", "quot;", 0 };
00192 static const int   xmlEntLen[] = { 3,     3,     4,      5,       5 };
00193 
00194 
00195 // Replace xml-encoded entities with the raw text equivalents.
00196 
00197 std::string 
00198 XmlRpcUtil::xmlDecode(const std::string& encoded)
00199 {
00200   std::string::size_type iAmp = encoded.find(AMP);
00201   if (iAmp == std::string::npos)
00202     return encoded;
00203 
00204   std::string decoded(encoded, 0, iAmp);
00205   std::string::size_type iSize = encoded.size();
00206   decoded.reserve(iSize);
00207 
00208   const char* ens = encoded.c_str();
00209   while (iAmp != iSize) {
00210     if (encoded[iAmp] == AMP && iAmp+1 < iSize) {
00211       int iEntity;
00212       for (iEntity=0; xmlEntity[iEntity] != 0; ++iEntity)
00213         //if (encoded.compare(iAmp+1, xmlEntLen[iEntity], xmlEntity[iEntity]) == 0)
00214         if (strncmp(ens+iAmp+1, xmlEntity[iEntity], xmlEntLen[iEntity]) == 0)
00215         {
00216           decoded += rawEntity[iEntity];
00217           iAmp += xmlEntLen[iEntity]+1;
00218           break;
00219         }
00220       if (xmlEntity[iEntity] == 0)    // unrecognized sequence
00221         decoded += encoded[iAmp++];
00222 
00223     } else {
00224       decoded += encoded[iAmp++];
00225     }
00226   }
00227     
00228   return decoded;
00229 }
00230 
00231 
00232 // Replace raw text with xml-encoded entities.
00233 
00234 std::string 
00235 XmlRpcUtil::xmlEncode(const std::string& raw)
00236 {
00237   std::string::size_type iRep = raw.find_first_of(rawEntity);
00238   if (iRep == std::string::npos)
00239     return raw;
00240 
00241   std::string encoded(raw, 0, iRep);
00242   std::string::size_type iSize = raw.size();
00243 
00244   while (iRep != iSize) {
00245     int iEntity;
00246     for (iEntity=0; rawEntity[iEntity] != 0; ++iEntity)
00247       if (raw[iRep] == rawEntity[iEntity])
00248       {
00249         encoded += AMP;
00250         encoded += xmlEntity[iEntity];
00251         break;
00252       }
00253     if (rawEntity[iEntity] == 0)
00254       encoded += raw[iRep];
00255     ++iRep;
00256   }
00257   return encoded;
00258 }
00259 
00260 
00261 


xmlrpcpp
Author(s): Chris Morley, Konstantin Pilipchuk, Morgan Quigley
autogenerated on Tue Mar 7 2017 03:44:43