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* msg) {
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  defaultLogHandler.log(0, msg);
68  }
70 
71 
72 // Error handler singleton
74 
75 
76 // Easy API for log verbosity
79 
80 
81 
82 void XmlRpcUtil::log(int level, const char* fmt, ...)
83 {
84  if (level <= XmlRpcLogHandler::getVerbosity())
85  {
86  va_list va;
87  char buf[1024];
88  va_start( va, fmt);
89  std::vsnprintf(buf,sizeof(buf)-1,fmt,va);
90  va_end(va);
91  buf[sizeof(buf)-1] = 0;
92  XmlRpcLogHandler::getLogHandler()->log(level, buf);
93  }
94 }
95 
96 
97 void XmlRpcUtil::error(const char* fmt, ...)
98 {
99  va_list va;
100  va_start(va, fmt);
101  char buf[1024];
102  std::vsnprintf(buf,sizeof(buf)-1,fmt,va);
103  va_end(va);
104  buf[sizeof(buf)-1] = 0;
106 }
107 
108 
109 // Returns contents between <tag> and </tag>, updates offset to char after </tag>
110 // This method will skip *any* intermediate string to find the tag; as such, it is
111 // unsafe to use in general, and `nextTagData` should be used instead.
112 std::string
113 XmlRpcUtil::parseTag(const char* tag, std::string const& xml, int* offset)
114 {
115  if (offset == NULL) return std::string();
116  // avoid attempting to parse overly long xml input
117  if (xml.length() > size_t(INT_MAX)) return std::string();
118  if (*offset >= int(xml.length())) return std::string();
119  size_t istart = xml.find(tag, *offset);
120  if (istart == std::string::npos) return std::string();
121  istart += strlen(tag);
122  std::string etag = "</";
123  etag += tag + 1;
124  size_t iend = xml.find(etag, istart);
125  if (iend == std::string::npos) return std::string();
126 
127  *offset = int(iend + etag.length());
128  return xml.substr(istart, iend-istart);
129 }
130 
131 
132 // Returns true if the tag is found and updates offset to the char after the tag
133 bool
134 XmlRpcUtil::findTag(const char* tag, std::string const& xml, int* offset)
135 {
136  if (offset == NULL) return false;
137  if (xml.length() > size_t(INT_MAX)) return false;
138  if (*offset >= int(xml.length())) return false;
139  size_t istart = xml.find(tag, *offset);
140  if (istart == std::string::npos)
141  return false;
142 
143  *offset = int(istart + strlen(tag));
144  return true;
145 }
146 
147 
148 // Returns true if the tag is found at the specified offset (modulo any whitespace)
149 // and updates offset to the char after the tag
150 bool
151 XmlRpcUtil::nextTagIs(const char* tag, std::string const& xml, int* offset)
152 {
153  if (offset == NULL) return false;
154  if (xml.length() > size_t(INT_MAX)) return false;
155  if (*offset >= int(xml.length())) return false;
156  const char* cp = xml.c_str() + *offset;
157  int nc = 0;
158  while (*cp && isspace(*cp)) {
159  ++cp;
160  ++nc;
161  }
162 
163  int len = int(strlen(tag));
164  if (*cp && (strncmp(cp, tag, len) == 0)) {
165  *offset += nc + len;
166  return true;
167  }
168  return false;
169 }
170 
171 // Returns contents between <tag> and </tag> at the specified offset (modulo any whitespace),
172 // and updates offset to char after </tag>
173 std::string
174 XmlRpcUtil::nextTagData(const char* tag, std::string const& xml, int* offset)
175 {
176  if (offset == NULL) return std::string();
177  if (xml.length() > size_t(INT_MAX)) return std::string();
178  if (*offset >= int(xml.length())) return std::string();
179 
180  const char* start_cp = xml.c_str() + *offset;
181  const char* cp = start_cp;
182  while (*cp && isspace(*cp)) {
183  ++cp;
184  }
185 
186  const int len = int(strnlen(tag, xml.length()));
187  // Check if the tag is next; if not, we'll get out of here
188  if (!(*cp) || (strncmp(cp, tag, len) != 0)) {
189  return std::string();
190  }
191 
192  cp += len;
193 
194  // Now collect all of the data up to the next tag
195  std::string ret;
196  while (*cp) {
197  if (*cp == '<') {
198  break;
199  }
200  ret += *cp;
201  cp++;
202  }
203 
204  if (!(*cp)) {
205  return std::string();
206  }
207 
208  // Now find the end tag
209  std::string etag = "</";
210  etag += tag + 1;
211 
212  if (strncmp(cp, etag.c_str(), etag.length()) != 0) {
213  return std::string();
214  }
215 
216  cp += etag.length();
217 
218  *offset += (cp - start_cp);
219 
220  return ret;
221 }
222 
223 // Returns the next tag and updates offset to the char after the tag, or empty string
224 // if the next non-whitespace character is not '<'
225 std::string
226 XmlRpcUtil::getNextTag(std::string const& xml, int* offset)
227 {
228  if (offset == NULL) return std::string();
229  if (xml.length() > size_t(INT_MAX)) return std::string();
230  if (*offset >= int(xml.length())) return std::string();
231 
232  size_t pos = *offset;
233  const char* cp = xml.c_str() + pos;
234  while (*cp && isspace(*cp)) {
235  ++cp;
236  ++pos;
237  }
238 
239  if (*cp != '<') return std::string();
240 
241  std::string s;
242  do {
243  s += *cp;
244  ++pos;
245  } while (*cp++ != '>' && *cp != 0);
246 
247  *offset = int(pos);
248  return s;
249 }
250 
251 
252 
253 // xml encodings (xml-encoded entities are preceded with '&')
254 static const char AMP = '&';
255 static const char rawEntity[] = { '<', '>', '&', '\'', '\"', 0 };
256 static const char* xmlEntity[] = { "lt;", "gt;", "amp;", "apos;", "quot;", 0 };
257 static const int xmlEntLen[] = { 3, 3, 4, 5, 5 };
258 
259 
260 // Replace xml-encoded entities with the raw text equivalents.
261 
262 std::string
263 XmlRpcUtil::xmlDecode(const std::string& encoded)
264 {
265  std::string::size_type iAmp = encoded.find(AMP);
266  if (iAmp == std::string::npos)
267  return encoded;
268 
269  std::string decoded(encoded, 0, iAmp);
270  std::string::size_type iSize = encoded.size();
271  decoded.reserve(iSize);
272 
273  const char* ens = encoded.c_str();
274  while (iAmp != iSize) {
275  if (encoded[iAmp] == AMP && iAmp+1 < iSize) {
276  int iEntity;
277  for (iEntity=0; xmlEntity[iEntity] != 0; ++iEntity)
278  //if (encoded.compare(iAmp+1, xmlEntLen[iEntity], xmlEntity[iEntity]) == 0)
279  if (strncmp(ens+iAmp+1, xmlEntity[iEntity], xmlEntLen[iEntity]) == 0)
280  {
281  decoded += rawEntity[iEntity];
282  iAmp += xmlEntLen[iEntity]+1;
283  break;
284  }
285  if (xmlEntity[iEntity] == 0) // unrecognized sequence
286  decoded += encoded[iAmp++];
287 
288  } else {
289  decoded += encoded[iAmp++];
290  }
291  }
292 
293  return decoded;
294 }
295 
296 
297 // Replace raw text with xml-encoded entities.
298 
299 std::string
300 XmlRpcUtil::xmlEncode(const std::string& raw)
301 {
302  std::string::size_type iRep = raw.find_first_of(rawEntity);
303  if (iRep == std::string::npos)
304  return raw;
305 
306  std::string encoded(raw, 0, iRep);
307  std::string::size_type iSize = raw.size();
308 
309  while (iRep != iSize) {
310  int iEntity;
311  for (iEntity=0; rawEntity[iEntity] != 0; ++iEntity)
312  if (raw[iRep] == rawEntity[iEntity])
313  {
314  encoded += AMP;
315  encoded += xmlEntity[iEntity];
316  break;
317  }
318  if (rawEntity[iEntity] == 0)
319  encoded += raw[iRep];
320  ++iRep;
321  }
322  return encoded;
323 }
324 
325 
326 
XmlRpc::setVerbosity
XMLRPCPP_DECL void setVerbosity(int level)
Sets log message verbosity. This is short for XmlRpcLogHandler::setVerbosity(level)
Definition: XmlRpcUtil.cpp:78
defaultErrorHandler
DefaultErrorHandler defaultErrorHandler
XmlRpc::XmlRpcLogHandler
An interface allowing custom handling of informational message reporting.
Definition: XmlRpcUtil.h:47
DefaultErrorHandler::error
void error(const char *msg)
Report an error. Custom error handlers should define this method.
Definition: XmlRpcUtil.cpp:56
XmlRpc::XmlRpcUtil::xmlEncode
static std::string xmlEncode(const std::string &raw)
Convert raw text to encoded xml.
Definition: XmlRpcUtil.cpp:300
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:82
XmlRpc::getVerbosity
XMLRPCPP_DECL int getVerbosity()
Returns log message verbosity. This is short for XmlRpcLogHandler::getVerbosity()
Definition: XmlRpcUtil.cpp:77
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:257
XmlRpc::XmlRpcUtil::parseTag
static std::string parseTag(const char *tag, std::string const &xml, int *offset)
Definition: XmlRpcUtil.cpp:113
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:134
xmlEntity
static const char * xmlEntity[]
Definition: XmlRpcUtil.cpp:256
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:174
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:151
DefaultErrorHandler
Definition: XmlRpcUtil.cpp:49
XmlRpc::XmlRpcUtil::error
static void error(const char *fmt,...)
Dump error messages somewhere.
Definition: XmlRpcUtil.cpp:97
XmlRpc.h
XmlRpc::XmlRpcUtil::xmlDecode
static std::string xmlDecode(const std::string &encoded)
Convert encoded xml to raw text.
Definition: XmlRpcUtil.cpp:263
rawEntity
static const char rawEntity[]
Definition: XmlRpcUtil.cpp:255
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:254
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:226
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 Sat Apr 26 2025 02:59:11