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 #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
00058
00059
00060
00061
00062
00063
00064
00065
00066 }
00067 } defaultErrorHandler;
00068
00069
00070
00071 XmlRpcErrorHandler* XmlRpcErrorHandler::_errorHandler = &defaultErrorHandler;
00072
00073
00074
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
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
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
00140
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
00161
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
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
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
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)
00221 decoded += encoded[iAmp++];
00222
00223 } else {
00224 decoded += encoded[iAmp++];
00225 }
00226 }
00227
00228 return decoded;
00229 }
00230
00231
00232
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