File: | src/mod/xml_int/mod_xml_rpc/../../../../libs/xmlrpc-c/src/registry.c |
Location: | line 430, column 17 |
Description: | Function call argument is an uninitialized value |
1 | /*========================================================================= | |||
2 | XML-RPC Server Method Registry | |||
3 | =========================================================================== | |||
4 | These are the functions that implement the XML-RPC method registry. | |||
5 | ||||
6 | A method registry is a list of XML-RPC methods for a server to | |||
7 | implement, along with the details of how to implement each -- most | |||
8 | notably a function pointer for a function that executes the method. | |||
9 | ||||
10 | To build an XML-RPC server, just add a communication facility. | |||
11 | ||||
12 | Copyright information is at end of file | |||
13 | ||||
14 | =========================================================================*/ | |||
15 | ||||
16 | #include <assert.h> | |||
17 | #include <stdlib.h> | |||
18 | #include <string.h> | |||
19 | ||||
20 | #include "xmlrpc_config.h" | |||
21 | #include "bool.h" | |||
22 | #include "mallocvar.h" | |||
23 | #include "xmlrpc-c/base_int.h" | |||
24 | #include "xmlrpc-c/string_int.h" | |||
25 | #include "xmlrpc-c/base.h" | |||
26 | #include "xmlrpc-c/server.h" | |||
27 | #include "method.h" | |||
28 | #include "system_method.h" | |||
29 | #include "version.h" | |||
30 | ||||
31 | #include "registry.h" | |||
32 | ||||
33 | ||||
34 | unsigned int const xmlrpc_server_version_major = XMLRPC_VERSION_MAJOR1; | |||
35 | unsigned int const xmlrpc_server_version_minor = XMLRPC_VERSION_MINOR26; | |||
36 | unsigned int const xmlrpc_server_version_point = XMLRPC_VERSION_POINT0; | |||
37 | ||||
38 | ||||
39 | ||||
40 | void | |||
41 | xmlrpc_server_version(unsigned int * const majorP, | |||
42 | unsigned int * const minorP, | |||
43 | unsigned int * const pointP) { | |||
44 | ||||
45 | *majorP = XMLRPC_VERSION_MAJOR1; | |||
46 | *minorP = XMLRPC_VERSION_MINOR26; | |||
47 | *pointP = XMLRPC_VERSION_POINT0; | |||
48 | } | |||
49 | ||||
50 | ||||
51 | ||||
52 | xmlrpc_registry * | |||
53 | xmlrpc_registry_new(xmlrpc_env * const envP) { | |||
54 | ||||
55 | xmlrpc_registry * registryP; | |||
56 | ||||
57 | XMLRPC_ASSERT_ENV_OK(envP)do if (!((envP) != ((void*)0) && (envP->fault_string == ((void*)0)) && !(envP)->fault_occurred)) xmlrpc_assertion_failed ("../../../../libs/xmlrpc-c/src/registry.c", 57); while (0); | |||
58 | ||||
59 | MALLOCVAR(registryP)registryP = malloc(sizeof(*registryP)); | |||
60 | ||||
61 | if (registryP == NULL((void*)0)) | |||
62 | xmlrpc_faultf(envP, "Could not allocate memory for registry"); | |||
63 | else { | |||
64 | registryP->introspectionEnabled = true; | |||
65 | registryP->defaultMethodFunction = NULL((void*)0); | |||
66 | registryP->preinvokeFunction = NULL((void*)0); | |||
67 | registryP->shutdownServerFn = NULL((void*)0); | |||
68 | registryP->dialect = xmlrpc_dialect_i8; | |||
69 | ||||
70 | xmlrpc_methodListCreate(envP, ®istryP->methodListP); | |||
71 | if (!envP->fault_occurred) | |||
72 | xmlrpc_installSystemMethods(envP, registryP); | |||
73 | ||||
74 | if (envP->fault_occurred) | |||
75 | free(registryP); | |||
76 | } | |||
77 | return registryP; | |||
78 | } | |||
79 | ||||
80 | ||||
81 | ||||
82 | void | |||
83 | xmlrpc_registry_free(xmlrpc_registry * const registryP) { | |||
84 | ||||
85 | XMLRPC_ASSERT_PTR_OK(registryP)do if (!((registryP) != ((void*)0))) xmlrpc_assertion_failed( "../../../../libs/xmlrpc-c/src/registry.c", 85); while (0); | |||
86 | ||||
87 | xmlrpc_methodListDestroy(registryP->methodListP); | |||
88 | ||||
89 | free(registryP); | |||
90 | } | |||
91 | ||||
92 | ||||
93 | ||||
94 | static void | |||
95 | registryAddMethod(xmlrpc_env * const envP, | |||
96 | xmlrpc_registry * const registryP, | |||
97 | const char * const methodName, | |||
98 | xmlrpc_method1 method1, | |||
99 | xmlrpc_method2 method2, | |||
100 | const char * const signatureString, | |||
101 | const char * const help, | |||
102 | void * const userData, | |||
103 | size_t const stackSize) { | |||
104 | ||||
105 | const char * const helpString = | |||
106 | help ? help : "No help is available for this method."; | |||
107 | ||||
108 | xmlrpc_methodInfo * methodP; | |||
109 | ||||
110 | XMLRPC_ASSERT_ENV_OK(envP)do if (!((envP) != ((void*)0) && (envP->fault_string == ((void*)0)) && !(envP)->fault_occurred)) xmlrpc_assertion_failed ("../../../../libs/xmlrpc-c/src/registry.c", 110); while (0); | |||
111 | XMLRPC_ASSERT_PTR_OK(registryP)do if (!((registryP) != ((void*)0))) xmlrpc_assertion_failed( "../../../../libs/xmlrpc-c/src/registry.c", 111); while (0); | |||
112 | XMLRPC_ASSERT_PTR_OK(methodName)do if (!((methodName) != ((void*)0))) xmlrpc_assertion_failed ("../../../../libs/xmlrpc-c/src/registry.c", 112); while (0); | |||
113 | XMLRPC_ASSERT(method1 != NULL || method2 != NULL)do if (!(method1 != ((void*)0) || method2 != ((void*)0))) xmlrpc_assertion_failed ("../../../../libs/xmlrpc-c/src/registry.c", 113); while (0); | |||
114 | ||||
115 | xmlrpc_methodCreate(envP, method1, method2, userData, | |||
116 | signatureString, helpString, stackSize, &methodP); | |||
117 | ||||
118 | if (!envP->fault_occurred) { | |||
119 | xmlrpc_methodListAdd(envP, registryP->methodListP, methodName, | |||
120 | methodP); | |||
121 | ||||
122 | if (envP->fault_occurred) | |||
123 | xmlrpc_methodDestroy(methodP); | |||
124 | } | |||
125 | } | |||
126 | ||||
127 | ||||
128 | ||||
129 | void | |||
130 | xmlrpc_registry_add_method_w_doc( | |||
131 | xmlrpc_env * const envP, | |||
132 | xmlrpc_registry * const registryP, | |||
133 | const char * const host ATTR_UNUSED__attribute__((__unused__)), | |||
134 | const char * const methodName, | |||
135 | xmlrpc_method1 const method, | |||
136 | void * const serverInfo, | |||
137 | const char * const signatureString, | |||
138 | const char * const help) { | |||
139 | ||||
140 | XMLRPC_ASSERT(host == NULL)do if (!(host == ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/registry.c" , 140); while (0); | |||
141 | ||||
142 | registryAddMethod(envP, registryP, methodName, method, NULL((void*)0), | |||
143 | signatureString, help, serverInfo, 0); | |||
144 | } | |||
145 | ||||
146 | ||||
147 | ||||
148 | void | |||
149 | xmlrpc_registry_add_method(xmlrpc_env * const envP, | |||
150 | xmlrpc_registry * const registryP, | |||
151 | const char * const host, | |||
152 | const char * const methodName, | |||
153 | xmlrpc_method1 const method, | |||
154 | void * const serverInfoP) { | |||
155 | ||||
156 | xmlrpc_registry_add_method_w_doc( | |||
157 | envP, registryP, host, methodName, | |||
158 | method, serverInfoP, "?", "No help is available for this method."); | |||
159 | } | |||
160 | ||||
161 | ||||
162 | ||||
163 | void | |||
164 | xmlrpc_registry_add_method2(xmlrpc_env * const envP, | |||
165 | xmlrpc_registry * const registryP, | |||
166 | const char * const methodName, | |||
167 | xmlrpc_method2 method, | |||
168 | const char * const signatureString, | |||
169 | const char * const help, | |||
170 | void * const serverInfo) { | |||
171 | ||||
172 | registryAddMethod(envP, registryP, methodName, NULL((void*)0), method, | |||
173 | signatureString, help, serverInfo, 0); | |||
174 | } | |||
175 | ||||
176 | ||||
177 | ||||
178 | void | |||
179 | xmlrpc_registry_add_method3( | |||
180 | xmlrpc_env * const envP, | |||
181 | xmlrpc_registry * const registryP, | |||
182 | const struct xmlrpc_method_info3 * const infoP) { | |||
183 | ||||
184 | registryAddMethod(envP, registryP, infoP->methodName, NULL((void*)0), | |||
185 | infoP->methodFunction, | |||
186 | infoP->signatureString, infoP->help, infoP->serverInfo, | |||
187 | infoP->stackSize); | |||
188 | } | |||
189 | ||||
190 | ||||
191 | ||||
192 | void | |||
193 | xmlrpc_registry_set_default_method( | |||
194 | xmlrpc_env * const envP ATTR_UNUSED__attribute__((__unused__)), | |||
195 | xmlrpc_registry * const registryP ATTR_UNUSED__attribute__((__unused__)), | |||
196 | xmlrpc_default_method const function, | |||
197 | void * const userData) { | |||
198 | ||||
199 | XMLRPC_ASSERT_ENV_OK(envP)do if (!((envP) != ((void*)0) && (envP->fault_string == ((void*)0)) && !(envP)->fault_occurred)) xmlrpc_assertion_failed ("../../../../libs/xmlrpc-c/src/registry.c", 199); while (0); | |||
200 | XMLRPC_ASSERT_PTR_OK(registryP)do if (!((registryP) != ((void*)0))) xmlrpc_assertion_failed( "../../../../libs/xmlrpc-c/src/registry.c", 200); while (0); | |||
201 | XMLRPC_ASSERT_PTR_OK(function)do if (!((function) != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/registry.c" , 201); while (0); | |||
202 | ||||
203 | /* Note: this may be the first default method, or it may be a replacement | |||
204 | of the current one. | |||
205 | */ | |||
206 | ||||
207 | registryP->defaultMethodFunction = function; | |||
208 | registryP->defaultMethodUserData = userData; | |||
209 | } | |||
210 | ||||
211 | ||||
212 | ||||
213 | /* This is our guess at what a method function requires when the user | |||
214 | doesn't say. | |||
215 | */ | |||
216 | #define METHOD_FUNCTION_STACK128*1024 128*1024 | |||
217 | ||||
218 | ||||
219 | ||||
220 | static size_t | |||
221 | methodStackSize(const xmlrpc_methodInfo * const methodP) { | |||
222 | ||||
223 | return methodP->stackSize == | |||
224 | 0 ? METHOD_FUNCTION_STACK128*1024 : methodP->stackSize; | |||
225 | } | |||
226 | ||||
227 | ||||
228 | ||||
229 | size_t | |||
230 | xmlrpc_registry_max_stackSize(xmlrpc_registry * const registryP) { | |||
231 | /*---------------------------------------------------------------------------- | |||
232 | Return the maximum amount of stack required by the methods in registry | |||
233 | *registryP. | |||
234 | ||||
235 | If there are no methods, return 0. | |||
236 | -----------------------------------------------------------------------------*/ | |||
237 | xmlrpc_methodNode * p; | |||
238 | size_t stackSize; | |||
239 | ||||
240 | for (p = registryP->methodListP->firstMethodP, stackSize = 0; | |||
241 | p; | |||
242 | p = p->nextP) { | |||
243 | ||||
244 | stackSize = MAX(stackSize, methodStackSize(p->methodP))((stackSize) > (methodStackSize(p->methodP)) ? (stackSize ) : (methodStackSize(p->methodP))); | |||
245 | } | |||
246 | return stackSize; | |||
247 | } | |||
248 | ||||
249 | ||||
250 | ||||
251 | void | |||
252 | xmlrpc_registry_set_preinvoke_method( | |||
253 | xmlrpc_env * const envP ATTR_UNUSED__attribute__((__unused__)), | |||
254 | xmlrpc_registry * const registryP ATTR_UNUSED__attribute__((__unused__)), | |||
255 | xmlrpc_preinvoke_method const function, | |||
256 | void * const userData) { | |||
257 | ||||
258 | XMLRPC_ASSERT_ENV_OK(envP)do if (!((envP) != ((void*)0) && (envP->fault_string == ((void*)0)) && !(envP)->fault_occurred)) xmlrpc_assertion_failed ("../../../../libs/xmlrpc-c/src/registry.c", 258); while (0); | |||
259 | XMLRPC_ASSERT_PTR_OK(registryP)do if (!((registryP) != ((void*)0))) xmlrpc_assertion_failed( "../../../../libs/xmlrpc-c/src/registry.c", 259); while (0); | |||
260 | XMLRPC_ASSERT_PTR_OK(function)do if (!((function) != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/registry.c" , 260); while (0); | |||
261 | ||||
262 | registryP->preinvokeFunction = function; | |||
263 | registryP->preinvokeUserData = userData; | |||
264 | } | |||
265 | ||||
266 | ||||
267 | ||||
268 | void | |||
269 | xmlrpc_registry_set_shutdown(xmlrpc_registry * const registryP, | |||
270 | xmlrpc_server_shutdown_fn * const shutdownFn, | |||
271 | void * const context) { | |||
272 | ||||
273 | XMLRPC_ASSERT_PTR_OK(registryP)do if (!((registryP) != ((void*)0))) xmlrpc_assertion_failed( "../../../../libs/xmlrpc-c/src/registry.c", 273); while (0); | |||
274 | XMLRPC_ASSERT_PTR_OK(shutdownFn)do if (!((shutdownFn) != ((void*)0))) xmlrpc_assertion_failed ("../../../../libs/xmlrpc-c/src/registry.c", 274); while (0); | |||
275 | ||||
276 | registryP->shutdownServerFn = shutdownFn; | |||
277 | ||||
278 | registryP->shutdownContext = context; | |||
279 | } | |||
280 | ||||
281 | ||||
282 | ||||
283 | void | |||
284 | xmlrpc_registry_set_dialect(xmlrpc_env * const envP, | |||
285 | xmlrpc_registry * const registryP, | |||
286 | xmlrpc_dialect const dialect) { | |||
287 | ||||
288 | if (dialect != xmlrpc_dialect_i8 && | |||
289 | dialect != xmlrpc_dialect_apache) | |||
290 | xmlrpc_faultf(envP, "Invalid dialect argument -- not of type " | |||
291 | "xmlrpc_dialect. Numerical value is %u", dialect); | |||
292 | else | |||
293 | registryP->dialect = dialect; | |||
294 | } | |||
295 | ||||
296 | ||||
297 | ||||
298 | static void | |||
299 | callNamedMethod(xmlrpc_env * const envP, | |||
300 | xmlrpc_methodInfo * const methodP, | |||
301 | xmlrpc_value * const paramArrayP, | |||
302 | void * const callInfoP, | |||
303 | xmlrpc_value ** const resultPP) { | |||
304 | ||||
305 | if (methodP->methodFnType2) | |||
306 | *resultPP = | |||
307 | methodP->methodFnType2(envP, paramArrayP, | |||
308 | methodP->userData, callInfoP); | |||
309 | else { | |||
310 | assert(methodP->methodFnType1)((methodP->methodFnType1) ? (void) (0) : __assert_fail ("methodP->methodFnType1" , "../../../../libs/xmlrpc-c/src/registry.c", 310, __PRETTY_FUNCTION__ )); | |||
311 | *resultPP = | |||
312 | methodP->methodFnType1(envP, paramArrayP, methodP->userData); | |||
313 | } | |||
314 | } | |||
315 | ||||
316 | ||||
317 | ||||
318 | void | |||
319 | xmlrpc_dispatchCall(xmlrpc_env * const envP, | |||
320 | xmlrpc_registry * const registryP, | |||
321 | const char * const methodName, | |||
322 | xmlrpc_value * const paramArrayP, | |||
323 | void * const callInfoP, | |||
324 | xmlrpc_value ** const resultPP) { | |||
325 | ||||
326 | if (registryP->preinvokeFunction) | |||
327 | registryP->preinvokeFunction(envP, methodName, paramArrayP, | |||
328 | registryP->preinvokeUserData); | |||
329 | ||||
330 | if (!envP->fault_occurred) { | |||
331 | xmlrpc_methodInfo * methodP; | |||
332 | ||||
333 | xmlrpc_methodListLookupByName(registryP->methodListP, methodName, | |||
334 | &methodP); | |||
335 | ||||
336 | if (methodP) | |||
337 | callNamedMethod(envP, methodP, paramArrayP, callInfoP, resultPP); | |||
338 | else { | |||
339 | if (registryP->defaultMethodFunction) | |||
340 | *resultPP = registryP->defaultMethodFunction( | |||
341 | envP, callInfoP, methodName, paramArrayP, | |||
342 | registryP->defaultMethodUserData); | |||
343 | else { | |||
344 | /* No matching method, and no default. */ | |||
345 | xmlrpc_env_set_fault_formatted( | |||
346 | envP, XMLRPC_NO_SUCH_METHOD_ERROR(-506), | |||
347 | "Method '%s' not defined", methodName); | |||
348 | } | |||
349 | } | |||
350 | } | |||
351 | /* For backward compatibility, for sloppy users: */ | |||
352 | if (envP->fault_occurred) | |||
353 | *resultPP = NULL((void*)0); | |||
354 | } | |||
355 | ||||
356 | ||||
357 | ||||
358 | /*========================================================================= | |||
359 | ** xmlrpc_registry_process_call | |||
360 | **========================================================================= | |||
361 | ** | |||
362 | */ | |||
363 | ||||
364 | static void | |||
365 | serializeFault(xmlrpc_env * const envP, | |||
366 | xmlrpc_env const fault, | |||
367 | xmlrpc_mem_block * const responseXmlP) { | |||
368 | ||||
369 | xmlrpc_env env; | |||
370 | ||||
371 | xmlrpc_env_init(&env); | |||
372 | ||||
373 | xmlrpc_serialize_fault(&env, responseXmlP, &fault); | |||
374 | ||||
375 | if (env.fault_occurred) | |||
376 | xmlrpc_faultf(envP, | |||
377 | "Executed XML-RPC method completely and it " | |||
378 | "generated a fault response, but we failed " | |||
379 | "to encode that fault response as XML-RPC " | |||
380 | "so we could send it to the client. %s", | |||
381 | env.fault_string); | |||
382 | ||||
383 | xmlrpc_env_clean(&env); | |||
384 | } | |||
385 | ||||
386 | ||||
387 | ||||
388 | void | |||
389 | xmlrpc_registry_process_call2(xmlrpc_env * const envP, | |||
390 | xmlrpc_registry * const registryP, | |||
391 | const char * const callXml, | |||
392 | size_t const callXmlLen, | |||
393 | void * const callInfo, | |||
394 | xmlrpc_mem_block ** const responseXmlPP) { | |||
395 | ||||
396 | xmlrpc_mem_block * responseXmlP; | |||
397 | ||||
398 | XMLRPC_ASSERT_ENV_OK(envP)do if (!((envP) != ((void*)0) && (envP->fault_string == ((void*)0)) && !(envP)->fault_occurred)) xmlrpc_assertion_failed ("../../../../libs/xmlrpc-c/src/registry.c", 398); while (0); | |||
399 | XMLRPC_ASSERT_PTR_OK(callXml)do if (!((callXml) != ((void*)0))) xmlrpc_assertion_failed("../../../../libs/xmlrpc-c/src/registry.c" , 399); while (0); | |||
400 | ||||
401 | xmlrpc_traceXml("XML-RPC CALL", callXml, callXmlLen); | |||
402 | ||||
403 | /* Allocate our output buffer. | |||
404 | ** If this fails, we need to die in a special fashion. */ | |||
405 | responseXmlP = XMLRPC_MEMBLOCK_NEW(char, envP, 0)xmlrpc_mem_block_new((envP), sizeof(char) * (0)); | |||
406 | if (!envP->fault_occurred) { | |||
407 | const char * methodName; | |||
408 | xmlrpc_value * paramArrayP; | |||
409 | xmlrpc_env fault; | |||
410 | xmlrpc_env parseEnv; | |||
411 | ||||
412 | xmlrpc_env_init(&fault); | |||
413 | xmlrpc_env_init(&parseEnv); | |||
414 | ||||
415 | xmlrpc_parse_call(&parseEnv, callXml, callXmlLen, | |||
416 | &methodName, ¶mArrayP); | |||
417 | ||||
418 | if (parseEnv.fault_occurred) | |||
419 | xmlrpc_env_set_fault_formatted( | |||
420 | &fault, XMLRPC_PARSE_ERROR(-503), | |||
421 | "Call XML not a proper XML-RPC call. %s", | |||
422 | parseEnv.fault_string); | |||
423 | else { | |||
424 | xmlrpc_value * resultP; | |||
425 | ||||
426 | xmlrpc_dispatchCall(&fault, registryP, methodName, paramArrayP, | |||
427 | callInfo, &resultP); | |||
428 | ||||
429 | if (!fault.fault_occurred) { | |||
430 | xmlrpc_serialize_response2(envP, responseXmlP, | |||
| ||||
431 | resultP, registryP->dialect); | |||
432 | ||||
433 | xmlrpc_DECREF(resultP); | |||
434 | } | |||
435 | xmlrpc_strfree(methodName); | |||
436 | xmlrpc_DECREF(paramArrayP); | |||
437 | } | |||
438 | if (!envP->fault_occurred && fault.fault_occurred) | |||
439 | serializeFault(envP, fault, responseXmlP); | |||
440 | ||||
441 | xmlrpc_env_clean(&parseEnv); | |||
442 | xmlrpc_env_clean(&fault); | |||
443 | ||||
444 | if (envP->fault_occurred) | |||
445 | XMLRPC_MEMBLOCK_FREE(char, responseXmlP)xmlrpc_mem_block_free(responseXmlP); | |||
446 | else { | |||
447 | *responseXmlPP = responseXmlP; | |||
448 | xmlrpc_traceXml("XML-RPC RESPONSE", | |||
449 | XMLRPC_MEMBLOCK_CONTENTS(char, responseXmlP)((char*) xmlrpc_mem_block_contents(responseXmlP)), | |||
450 | XMLRPC_MEMBLOCK_SIZE(char, responseXmlP)(xmlrpc_mem_block_size(responseXmlP) / sizeof(char))); | |||
451 | } | |||
452 | } | |||
453 | } | |||
454 | ||||
455 | ||||
456 | ||||
457 | xmlrpc_mem_block * | |||
458 | xmlrpc_registry_process_call(xmlrpc_env * const envP, | |||
459 | xmlrpc_registry * const registryP, | |||
460 | const char * const host ATTR_UNUSED__attribute__((__unused__)), | |||
461 | const char * const callXml, | |||
462 | size_t const callXmlLen) { | |||
463 | ||||
464 | xmlrpc_mem_block * responseXmlP; | |||
465 | ||||
466 | xmlrpc_registry_process_call2(envP, registryP, callXml, callXmlLen, NULL((void*)0), | |||
| ||||
467 | &responseXmlP); | |||
468 | ||||
469 | return responseXmlP; | |||
470 | } | |||
471 | ||||
472 | ||||
473 | ||||
474 | /* Copyright (C) 2001 by First Peer, Inc. All rights reserved. | |||
475 | ** Copyright (C) 2001 by Eric Kidd. All rights reserved. | |||
476 | ** Copyright (C) 2001 by Luke Howard. All rights reserved. | |||
477 | ** | |||
478 | ** Redistribution and use in source and binary forms, with or without | |||
479 | ** modification, are permitted provided that the following conditions | |||
480 | ** are met: | |||
481 | ** 1. Redistributions of source code must retain the above copyright | |||
482 | ** notice, this list of conditions and the following disclaimer. | |||
483 | ** 2. Redistributions in binary form must reproduce the above copyright | |||
484 | ** notice, this list of conditions and the following disclaimer in the | |||
485 | ** documentation and/or other materials provided with the distribution. | |||
486 | ** 3. The name of the author may not be used to endorse or promote products | |||
487 | ** derived from this software without specific prior written permission. | |||
488 | ** | |||
489 | ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |||
490 | ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||
491 | ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||
492 | ** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |||
493 | ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |||
494 | ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |||
495 | ** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||
496 | ** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |||
497 | ** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |||
498 | ** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
499 | ** SUCH DAMAGE. */ |