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
00018 #ifdef USE_WINDOWS_DEBUG
00019 #define WIN32_LEAN_AND_MEAN
00020 #include <windows.h>
00021 #endif
00022
00023
00024 const char XmlRpc::XMLRPC_VERSION[] = "XMLRPC++ 0.7";
00025
00026
00027 int XmlRpcLogHandler::_verbosity = 0;
00028
00029
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
00044 XmlRpcLogHandler* XmlRpcLogHandler::_logHandler = &defaultLogHandler;
00045
00046
00047
00048 static class DefaultErrorHandler : public XmlRpcErrorHandler {
00049 public:
00050
00051 void error(const char* msg) {
00052 #ifdef USE_WINDOWS_DEBUG
00053 OutputDebugString(msg); OutputDebugString("\n");
00054 #else
00055 std::cerr << msg << std::endl;
00056 #endif
00057 }
00058 } defaultErrorHandler;
00059
00060
00061
00062 XmlRpcErrorHandler* XmlRpcErrorHandler::_errorHandler = &defaultErrorHandler;
00063
00064
00065
00066 int XmlRpc::getVerbosity() { return XmlRpcLogHandler::getVerbosity(); }
00067 void XmlRpc::setVerbosity(int level) { XmlRpcLogHandler::setVerbosity(level); }
00068
00069
00070
00071 void XmlRpcUtil::log(int level, const char* fmt, ...)
00072 {
00073 if (level <= XmlRpcLogHandler::getVerbosity())
00074 {
00075 va_list va;
00076 char buf[1024];
00077 va_start( va, fmt);
00078 vsnprintf(buf,sizeof(buf)-1,fmt,va);
00079 buf[sizeof(buf)-1] = 0;
00080 XmlRpcLogHandler::getLogHandler()->log(level, buf);
00081 }
00082 }
00083
00084
00085 void XmlRpcUtil::error(const char* fmt, ...)
00086 {
00087 va_list va;
00088 va_start(va, fmt);
00089 char buf[1024];
00090 vsnprintf(buf,sizeof(buf)-1,fmt,va);
00091 buf[sizeof(buf)-1] = 0;
00092 XmlRpcErrorHandler::getErrorHandler()->error(buf);
00093 }
00094
00095
00096
00097 std::string
00098 XmlRpcUtil::parseTag(const char* tag, std::string const& xml, int* offset)
00099 {
00100 if (*offset >= int(xml.length())) return std::string();
00101 size_t istart = xml.find(tag, *offset);
00102 if (istart == std::string::npos) return std::string();
00103 istart += strlen(tag);
00104 std::string etag = "</";
00105 etag += tag + 1;
00106 size_t iend = xml.find(etag, istart);
00107 if (iend == std::string::npos) return std::string();
00108
00109 *offset = int(iend + etag.length());
00110 return xml.substr(istart, iend-istart);
00111 }
00112
00113
00114
00115 bool
00116 XmlRpcUtil::findTag(const char* tag, std::string const& xml, int* offset)
00117 {
00118 if (*offset >= int(xml.length())) return false;
00119 size_t istart = xml.find(tag, *offset);
00120 if (istart == std::string::npos)
00121 return false;
00122
00123 *offset = int(istart + strlen(tag));
00124 return true;
00125 }
00126
00127
00128
00129
00130 bool
00131 XmlRpcUtil::nextTagIs(const char* tag, std::string const& xml, int* offset)
00132 {
00133 if (*offset >= int(xml.length())) return false;
00134 const char* cp = xml.c_str() + *offset;
00135 int nc = 0;
00136 while (*cp && isspace(*cp)) {
00137 ++cp;
00138 ++nc;
00139 }
00140
00141 int len = int(strlen(tag));
00142 if (*cp && (strncmp(cp, tag, len) == 0)) {
00143 *offset += nc + len;
00144 return true;
00145 }
00146 return false;
00147 }
00148
00149
00150
00151 std::string
00152 XmlRpcUtil::getNextTag(std::string const& xml, int* offset)
00153 {
00154 if (*offset >= int(xml.length())) return std::string();
00155
00156 size_t pos = *offset;
00157 const char* cp = xml.c_str() + pos;
00158 while (*cp && isspace(*cp)) {
00159 ++cp;
00160 ++pos;
00161 }
00162
00163 if (*cp != '<') return std::string();
00164
00165 std::string s;
00166 do {
00167 s += *cp;
00168 ++pos;
00169 } while (*cp++ != '>' && *cp != 0);
00170
00171 *offset = int(pos);
00172 return s;
00173 }
00174
00175
00176
00177
00178 static const char AMP = '&';
00179 static const char rawEntity[] = { '<', '>', '&', '\'', '\"', 0 };
00180 static const char* xmlEntity[] = { "lt;", "gt;", "amp;", "apos;", "quot;", 0 };
00181 static const int xmlEntLen[] = { 3, 3, 4, 5, 5 };
00182
00183
00184
00185
00186 std::string
00187 XmlRpcUtil::xmlDecode(const std::string& encoded)
00188 {
00189 std::string::size_type iAmp = encoded.find(AMP);
00190 if (iAmp == std::string::npos)
00191 return encoded;
00192
00193 std::string decoded(encoded, 0, iAmp);
00194 std::string::size_type iSize = encoded.size();
00195 decoded.reserve(iSize);
00196
00197 const char* ens = encoded.c_str();
00198 while (iAmp != iSize) {
00199 if (encoded[iAmp] == AMP && iAmp+1 < iSize) {
00200 int iEntity;
00201 for (iEntity=0; xmlEntity[iEntity] != 0; ++iEntity)
00202
00203 if (strncmp(ens+iAmp+1, xmlEntity[iEntity], xmlEntLen[iEntity]) == 0)
00204 {
00205 decoded += rawEntity[iEntity];
00206 iAmp += xmlEntLen[iEntity]+1;
00207 break;
00208 }
00209 if (xmlEntity[iEntity] == 0)
00210 decoded += encoded[iAmp++];
00211
00212 } else {
00213 decoded += encoded[iAmp++];
00214 }
00215 }
00216
00217 return decoded;
00218 }
00219
00220
00221
00222
00223 std::string
00224 XmlRpcUtil::xmlEncode(const std::string& raw)
00225 {
00226 std::string::size_type iRep = raw.find_first_of(rawEntity);
00227 if (iRep == std::string::npos)
00228 return raw;
00229
00230 std::string encoded(raw, 0, iRep);
00231 std::string::size_type iSize = raw.size();
00232
00233 while (iRep != iSize) {
00234 int iEntity;
00235 for (iEntity=0; rawEntity[iEntity] != 0; ++iEntity)
00236 if (raw[iRep] == rawEntity[iEntity])
00237 {
00238 encoded += AMP;
00239 encoded += xmlEntity[iEntity];
00240 break;
00241 }
00242 if (rawEntity[iEntity] == 0)
00243 encoded += raw[iRep];
00244 ++iRep;
00245 }
00246 return encoded;
00247 }
00248
00249
00250