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