XmlRpcUtil.cpp
Go to the documentation of this file.
1 
2 #include "xmlrpcpp/XmlRpcUtil.h"
3 
4 #ifndef MAKEDEPEND
5 # include <ctype.h>
6 # include <iostream>
7 # include <stdarg.h>
8 # include <stdio.h>
9 # include <string.h>
10 # include <climits>
11 #endif
12 
13 #include "xmlrpcpp/XmlRpc.h"
14 
15 using namespace XmlRpc;
16 
17 
18 //#define USE_WINDOWS_DEBUG // To make the error and log messages go to VC++ debug output
19 #ifdef USE_WINDOWS_DEBUG
20 #define WIN32_LEAN_AND_MEAN
21 #include <windows.h>
22 #endif
23 
24 // Version id
25 const char XmlRpc::XMLRPC_VERSION[] = "XMLRPC++ 0.7";
26 
27 // Default log verbosity: 0 for no messages through 5 (writes everything)
29 
30 // Default log handler
31 static class DefaultLogHandler : public XmlRpcLogHandler {
32 public:
33 
34  void log(int level, const char* msg) {
35 #ifdef USE_WINDOWS_DEBUG
36  if (level <= _verbosity) { OutputDebugString(msg); OutputDebugString("\n"); }
37 #else
38  if (level <= _verbosity) std::cout << msg << std::endl;
39 #endif
40  }
41 
43 
44 // Message log singleton
46 
47 
48 // Default error handler
49 static class DefaultErrorHandler : public XmlRpcErrorHandler {
50 public:
51 
52 #ifdef USE_WINDOWS_DEBUG
53  void error(const char* msg) {
54  OutputDebugString(msg); OutputDebugString("\n");
55 #else
56  void error(const char*) {
57 #endif
58  // As far as I can tell, throwing an exception here is a bug, unless
59  // the intention is that the program should exit. Throughout the code,
60  // calls to error() are followed by cleanup code that does things like
61  // closing a failed socket. Thus it would seem that it should be
62  // possible to continue execution. But if the user just catches the
63  // exception that's thrown here, the library ends up in a bogus state.
64  // So I'm commenting out the throw. - BPG
65  //
66  //throw std::runtime_error(msg);
67  }
69 
70 
71 // Error handler singleton
73 
74 
75 // Easy API for log verbosity
78 
79 
80 
81 void XmlRpcUtil::log(int level, const char* fmt, ...)
82 {
83  if (level <= XmlRpcLogHandler::getVerbosity())
84  {
85  va_list va;
86  char buf[1024];
87  va_start( va, fmt);
88  std::vsnprintf(buf,sizeof(buf)-1,fmt,va);
89  va_end(va);
90  buf[sizeof(buf)-1] = 0;
91  XmlRpcLogHandler::getLogHandler()->log(level, buf);
92  }
93 }
94 
95 
96 void XmlRpcUtil::error(const char* fmt, ...)
97 {
98  va_list va;
99  va_start(va, fmt);
100  char buf[1024];
101  std::vsnprintf(buf,sizeof(buf)-1,fmt,va);
102  va_end(va);
103  buf[sizeof(buf)-1] = 0;
105 }
106 
107 
108 // Returns contents between <tag> and </tag>, updates offset to char after </tag>
109 // This method will skip *any* intermediate string to find the tag; as such, it is
110 // unsafe to use in general, and `nextTagData` should be used instead.
111 std::string
112 XmlRpcUtil::parseTag(const char* tag, std::string const& xml, int* offset)
113 {
114  if (offset == NULL) return std::string();
115  // avoid attempting to parse overly long xml input
116  if (xml.length() > size_t(INT_MAX)) return std::string();
117  if (*offset >= int(xml.length())) return std::string();
118  size_t istart = xml.find(tag, *offset);
119  if (istart == std::string::npos) return std::string();
120  istart += strlen(tag);
121  std::string etag = "</";
122  etag += tag + 1;
123  size_t iend = xml.find(etag, istart);
124  if (iend == std::string::npos) return std::string();
125 
126  *offset = int(iend + etag.length());
127  return xml.substr(istart, iend-istart);
128 }
129 
130 
131 // Returns true if the tag is found and updates offset to the char after the tag
132 bool
133 XmlRpcUtil::findTag(const char* tag, std::string const& xml, int* offset)
134 {
135  if (offset == NULL) return false;
136  if (xml.length() > size_t(INT_MAX)) return false;
137  if (*offset >= int(xml.length())) return false;
138  size_t istart = xml.find(tag, *offset);
139  if (istart == std::string::npos)
140  return false;
141 
142  *offset = int(istart + strlen(tag));
143  return true;
144 }
145 
146 
147 // Returns true if the tag is found at the specified offset (modulo any whitespace)
148 // and updates offset to the char after the tag
149 bool
150 XmlRpcUtil::nextTagIs(const char* tag, std::string const& xml, int* offset)
151 {
152  if (offset == NULL) return false;
153  if (xml.length() > size_t(INT_MAX)) return false;
154  if (*offset >= int(xml.length())) return false;
155  const char* cp = xml.c_str() + *offset;
156  int nc = 0;
157  while (*cp && isspace(*cp)) {
158  ++cp;
159  ++nc;
160  }
161 
162  int len = int(strlen(tag));
163  if (*cp && (strncmp(cp, tag, len) == 0)) {
164  *offset += nc + len;
165  return true;
166  }
167  return false;
168 }
169 
170 // Returns contents between <tag> and </tag> at the specified offset (modulo any whitespace),
171 // and updates offset to char after </tag>
172 std::string
173 XmlRpcUtil::nextTagData(const char* tag, std::string const& xml, int* offset)
174 {
175  if (offset == NULL) return std::string();
176  if (xml.length() > size_t(INT_MAX)) return std::string();
177  if (*offset >= int(xml.length())) return std::string();
178 
179  const char* start_cp = xml.c_str() + *offset;
180  const char* cp = start_cp;
181  while (*cp && isspace(*cp)) {
182  ++cp;
183  }
184 
185  const int len = int(strnlen(tag, xml.length()));
186  // Check if the tag is next; if not, we'll get out of here
187  if (!(*cp) || (strncmp(cp, tag, len) != 0)) {
188  return std::string();
189  }
190 
191  cp += len;
192 
193  // Now collect all of the data up to the next tag
194  std::string ret;
195  while (*cp) {
196  if (*cp == '<') {
197  break;
198  }
199  ret += *cp;
200  cp++;
201  }
202 
203  if (!(*cp)) {
204  return std::string();
205  }
206 
207  // Now find the end tag
208  std::string etag = "</";
209  etag += tag + 1;
210 
211  if (strncmp(cp, etag.c_str(), etag.length()) != 0) {
212  return std::string();
213  }
214 
215  cp += etag.length();
216 
217  *offset += (cp - start_cp);
218 
219  return ret;
220 }
221 
222 // Returns the next tag and updates offset to the char after the tag, or empty string
223 // if the next non-whitespace character is not '<'
224 std::string
225 XmlRpcUtil::getNextTag(std::string const& xml, int* offset)
226 {
227  if (offset == NULL) return std::string();
228  if (xml.length() > size_t(INT_MAX)) return std::string();
229  if (*offset >= int(xml.length())) return std::string();
230 
231  size_t pos = *offset;
232  const char* cp = xml.c_str() + pos;
233  while (*cp && isspace(*cp)) {
234  ++cp;
235  ++pos;
236  }
237 
238  if (*cp != '<') return std::string();
239 
240  std::string s;
241  do {
242  s += *cp;
243  ++pos;
244  } while (*cp++ != '>' && *cp != 0);
245 
246  *offset = int(pos);
247  return s;
248 }
249 
250 
251 
252 // xml encodings (xml-encoded entities are preceded with '&')
253 static const char AMP = '&';
254 static const char rawEntity[] = { '<', '>', '&', '\'', '\"', 0 };
255 static const char* xmlEntity[] = { "lt;", "gt;", "amp;", "apos;", "quot;", 0 };
256 static const int xmlEntLen[] = { 3, 3, 4, 5, 5 };
257 
258 
259 // Replace xml-encoded entities with the raw text equivalents.
260 
261 std::string
262 XmlRpcUtil::xmlDecode(const std::string& encoded)
263 {
264  std::string::size_type iAmp = encoded.find(AMP);
265  if (iAmp == std::string::npos)
266  return encoded;
267 
268  std::string decoded(encoded, 0, iAmp);
269  std::string::size_type iSize = encoded.size();
270  decoded.reserve(iSize);
271 
272  const char* ens = encoded.c_str();
273  while (iAmp != iSize) {
274  if (encoded[iAmp] == AMP && iAmp+1 < iSize) {
275  int iEntity;
276  for (iEntity=0; xmlEntity[iEntity] != 0; ++iEntity)
277  //if (encoded.compare(iAmp+1, xmlEntLen[iEntity], xmlEntity[iEntity]) == 0)
278  if (strncmp(ens+iAmp+1, xmlEntity[iEntity], xmlEntLen[iEntity]) == 0)
279  {
280  decoded += rawEntity[iEntity];
281  iAmp += xmlEntLen[iEntity]+1;
282  break;
283  }
284  if (xmlEntity[iEntity] == 0) // unrecognized sequence
285  decoded += encoded[iAmp++];
286 
287  } else {
288  decoded += encoded[iAmp++];
289  }
290  }
291 
292  return decoded;
293 }
294 
295 
296 // Replace raw text with xml-encoded entities.
297 
298 std::string
299 XmlRpcUtil::xmlEncode(const std::string& raw)
300 {
301  std::string::size_type iRep = raw.find_first_of(rawEntity);
302  if (iRep == std::string::npos)
303  return raw;
304 
305  std::string encoded(raw, 0, iRep);
306  std::string::size_type iSize = raw.size();
307 
308  while (iRep != iSize) {
309  int iEntity;
310  for (iEntity=0; rawEntity[iEntity] != 0; ++iEntity)
311  if (raw[iRep] == rawEntity[iEntity])
312  {
313  encoded += AMP;
314  encoded += xmlEntity[iEntity];
315  break;
316  }
317  if (rawEntity[iEntity] == 0)
318  encoded += raw[iRep];
319  ++iRep;
320  }
321  return encoded;
322 }
323 
324 
325 
XmlRpc::setVerbosity
XMLRPCPP_DECL void setVerbosity(int level)
Sets log message verbosity. This is short for XmlRpcLogHandler::setVerbosity(level)
Definition: XmlRpcUtil.cpp:77
defaultErrorHandler
DefaultErrorHandler defaultErrorHandler
XmlRpc::XmlRpcLogHandler
An interface allowing custom handling of informational message reporting.
Definition: XmlRpcUtil.h:47
XmlRpc::XmlRpcUtil::xmlEncode
static std::string xmlEncode(const std::string &raw)
Convert raw text to encoded xml.
Definition: XmlRpcUtil.cpp:299
s
XmlRpcServer s
Definition: HelloServer.cpp:11
DefaultLogHandler::log
void log(int level, const char *msg)
Output a message. Custom error handlers should define this method.
Definition: XmlRpcUtil.cpp:34
XmlRpc::XmlRpcUtil::log
static void log(int level, const char *fmt,...)
Dump messages somewhere.
Definition: XmlRpcUtil.cpp:81
XmlRpc::getVerbosity
XMLRPCPP_DECL int getVerbosity()
Returns log message verbosity. This is short for XmlRpcLogHandler::getVerbosity()
Definition: XmlRpcUtil.cpp:76
XmlRpc
Definition: XmlRpcClient.h:20
XmlRpc::XmlRpcLogHandler::getLogHandler
static XmlRpcLogHandler * getLogHandler()
Returns a pointer to the currently installed message reporting object.
Definition: XmlRpcUtil.h:52
xmlEntLen
static const int xmlEntLen[]
Definition: XmlRpcUtil.cpp:256
XmlRpc::XmlRpcUtil::parseTag
static std::string parseTag(const char *tag, std::string const &xml, int *offset)
Definition: XmlRpcUtil.cpp:112
DefaultLogHandler
Definition: XmlRpcUtil.cpp:31
XmlRpc::XmlRpcUtil::findTag
static bool findTag(const char *tag, std::string const &xml, int *offset)
Returns true if the tag is found and updates offset to the char after the tag.
Definition: XmlRpcUtil.cpp:133
xmlEntity
static const char * xmlEntity[]
Definition: XmlRpcUtil.cpp:255
XmlRpc::XmlRpcLogHandler::setVerbosity
static void setVerbosity(int v)
Specify the level of verbosity of informational messages. 0 is no output, 5 is very verbose.
Definition: XmlRpcUtil.h:64
XmlRpc::XmlRpcErrorHandler::_errorHandler
static XMLRPCPP_DECL XmlRpcErrorHandler * _errorHandler
Definition: XmlRpcUtil.h:43
XmlRpc::XmlRpcUtil::nextTagData
static std::string nextTagData(const char *tag, std::string const &xml, int *offset)
Definition: XmlRpcUtil.cpp:173
DefaultErrorHandler::error
void error(const char *)
Report an error. Custom error handlers should define this method.
Definition: XmlRpcUtil.cpp:56
XmlRpc::XmlRpcErrorHandler::error
virtual void error(const char *msg)=0
Report an error. Custom error handlers should define this method.
XmlRpc::XmlRpcErrorHandler
An interface allowing custom handling of error message reporting.
Definition: XmlRpcUtil.h:27
XmlRpc::XmlRpcUtil::nextTagIs
static bool nextTagIs(const char *tag, std::string const &xml, int *offset)
Definition: XmlRpcUtil.cpp:150
DefaultErrorHandler
Definition: XmlRpcUtil.cpp:49
XmlRpc::XmlRpcUtil::error
static void error(const char *fmt,...)
Dump error messages somewhere.
Definition: XmlRpcUtil.cpp:96
XmlRpc.h
XmlRpc::XmlRpcUtil::xmlDecode
static std::string xmlDecode(const std::string &encoded)
Convert encoded xml to raw text.
Definition: XmlRpcUtil.cpp:262
rawEntity
static const char rawEntity[]
Definition: XmlRpcUtil.cpp:254
defaultLogHandler
DefaultLogHandler defaultLogHandler
XmlRpc::XmlRpcLogHandler::_verbosity
static XMLRPCPP_DECL int _verbosity
Definition: XmlRpcUtil.h:72
XmlRpc::XMLRPC_VERSION
const XMLRPCPP_DECL char XMLRPC_VERSION[]
Version identifier.
Definition: XmlRpcUtil.cpp:25
XmlRpc::XmlRpcErrorHandler::getErrorHandler
static XmlRpcErrorHandler * getErrorHandler()
Returns a pointer to the currently installed error handling object.
Definition: XmlRpcUtil.h:32
XmlRpc::XmlRpcLogHandler::_logHandler
static XMLRPCPP_DECL XmlRpcLogHandler * _logHandler
Definition: XmlRpcUtil.h:71
XmlRpcUtil.h
AMP
static const char AMP
Definition: XmlRpcUtil.cpp:253
XmlRpc::XmlRpcLogHandler::log
virtual void log(int level, const char *msg)=0
Output a message. Custom error handlers should define this method.
XmlRpc::XmlRpcUtil::getNextTag
static std::string getNextTag(std::string const &xml, int *offset)
Definition: XmlRpcUtil.cpp:225
XmlRpc::XmlRpcLogHandler::getVerbosity
static int getVerbosity()
Returns the level of verbosity of informational messages. 0 is no output, 5 is very verbose.
Definition: XmlRpcUtil.h:60


xmlrpcpp
Author(s): Chris Morley, Konstantin Pilipchuk, Morgan Quigley, Austin Hendrix, Dirk Thomas , Jacob Perron
autogenerated on Thu Nov 23 2023 04:01:41