诸暨麻将添加redis
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

425 lines
12 KiB

  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
  9. *
  10. * This software is licensed as described in the file COPYING, which
  11. * you should have received as part of this distribution. The terms
  12. * are also available at http://curl.haxx.se/docs/copyright.html.
  13. *
  14. * You may opt to use, copy, modify, merge, publish, distribute and/or sell
  15. * copies of the Software, and permit persons to whom the Software is
  16. * furnished to do so, under the terms of the COPYING file.
  17. *
  18. * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
  19. * KIND, either express or implied.
  20. *
  21. ***************************************************************************/
  22. #include "server_setup.h"
  23. #include "getpart.h"
  24. #define ENABLE_CURLX_PRINTF
  25. /* make the curlx header define all printf() functions to use the curlx_*
  26. versions instead */
  27. #include "curlx.h" /* from the private lib dir */
  28. /* just to please curl_base64.h we create a fake struct */
  29. struct SessionHandle {
  30. int fake;
  31. };
  32. #include "curl_base64.h"
  33. #include "curl_memory.h"
  34. /* include memdebug.h last */
  35. #include "memdebug.h"
  36. #define EAT_SPACE(p) while(*(p) && ISSPACE(*(p))) (p)++
  37. #define EAT_WORD(p) while(*(p) && !ISSPACE(*(p)) && ('>' != *(p))) (p)++
  38. #ifdef DEBUG_GETPART
  39. #define show(x) printf x
  40. #else
  41. #define show(x) Curl_nop_stmt
  42. #endif
  43. #if defined(_MSC_VER) && defined(_DLL)
  44. # pragma warning(disable:4232) /* MSVC extension, dllimport identity */
  45. #endif
  46. curl_malloc_callback Curl_cmalloc = (curl_malloc_callback)malloc;
  47. curl_free_callback Curl_cfree = (curl_free_callback)free;
  48. curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc;
  49. curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)strdup;
  50. curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc;
  51. #if defined(WIN32) && defined(UNICODE)
  52. curl_wcsdup_callback Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup;
  53. #endif
  54. #if defined(_MSC_VER) && defined(_DLL)
  55. # pragma warning(default:4232) /* MSVC extension, dllimport identity */
  56. #endif
  57. /*
  58. * readline()
  59. *
  60. * Reads a complete line from a file into a dynamically allocated buffer.
  61. *
  62. * Calling function may call this multiple times with same 'buffer'
  63. * and 'bufsize' pointers to avoid multiple buffer allocations. Buffer
  64. * will be reallocated and 'bufsize' increased until whole line fits in
  65. * buffer before returning it.
  66. *
  67. * Calling function is responsible to free allocated buffer.
  68. *
  69. * This function may return:
  70. * GPE_OUT_OF_MEMORY
  71. * GPE_END_OF_FILE
  72. * GPE_OK
  73. */
  74. static int readline(char **buffer, size_t *bufsize, FILE *stream)
  75. {
  76. size_t offset = 0;
  77. size_t length;
  78. char *newptr;
  79. if(!*buffer) {
  80. *buffer = malloc(128);
  81. if(!*buffer)
  82. return GPE_OUT_OF_MEMORY;
  83. *bufsize = 128;
  84. }
  85. for(;;) {
  86. int bytestoread = curlx_uztosi(*bufsize - offset);
  87. if(!fgets(*buffer + offset, bytestoread, stream))
  88. return (offset != 0) ? GPE_OK : GPE_END_OF_FILE ;
  89. length = offset + strlen(*buffer + offset);
  90. if(*(*buffer + length - 1) == '\n')
  91. break;
  92. offset = length;
  93. if(length < *bufsize - 1)
  94. continue;
  95. newptr = realloc(*buffer, *bufsize * 2);
  96. if(!newptr)
  97. return GPE_OUT_OF_MEMORY;
  98. *buffer = newptr;
  99. *bufsize *= 2;
  100. }
  101. return GPE_OK;
  102. }
  103. /*
  104. * appenddata()
  105. *
  106. * This appends data from a given source buffer to the end of the used part of
  107. * a destination buffer. Arguments relative to the destination buffer are, the
  108. * address of a pointer to the destination buffer 'dst_buf', the length of data
  109. * in destination buffer excluding potential null string termination 'dst_len',
  110. * the allocated size of destination buffer 'dst_alloc'. All three destination
  111. * buffer arguments may be modified by this function. Arguments relative to the
  112. * source buffer are, a pointer to the source buffer 'src_buf' and indication
  113. * whether the source buffer is base64 encoded or not 'src_b64'.
  114. *
  115. * If the source buffer is indicated to be base64 encoded, this appends the
  116. * decoded data, binary or whatever, to the destination. The source buffer
  117. * may not hold binary data, only a null terminated string is valid content.
  118. *
  119. * Destination buffer will be enlarged and relocated as needed.
  120. *
  121. * Calling function is responsible to provide preallocated destination
  122. * buffer and also to deallocate it when no longer needed.
  123. *
  124. * This function may return:
  125. * GPE_OUT_OF_MEMORY
  126. * GPE_OK
  127. */
  128. static int appenddata(char **dst_buf, /* dest buffer */
  129. size_t *dst_len, /* dest buffer data length */
  130. size_t *dst_alloc, /* dest buffer allocated size */
  131. char *src_buf, /* source buffer */
  132. int src_b64) /* != 0 if source is base64 encoded */
  133. {
  134. size_t need_alloc, src_len;
  135. union {
  136. unsigned char *as_uchar;
  137. char *as_char;
  138. } buf64;
  139. src_len = strlen(src_buf);
  140. if(!src_len)
  141. return GPE_OK;
  142. buf64.as_char = NULL;
  143. if(src_b64) {
  144. /* base64 decode the given buffer */
  145. int error = (int) Curl_base64_decode(src_buf, &buf64.as_uchar, &src_len);
  146. if(error)
  147. return GPE_OUT_OF_MEMORY;
  148. src_buf = buf64.as_char;
  149. if(!src_len || !src_buf) {
  150. /*
  151. ** currently there is no way to tell apart an OOM condition in
  152. ** Curl_base64_decode() from zero length decoded data. For now,
  153. ** let's just assume it is an OOM condition, currently we have
  154. ** no input for this function that decodes to zero length data.
  155. */
  156. if(buf64.as_char)
  157. free(buf64.as_char);
  158. return GPE_OUT_OF_MEMORY;
  159. }
  160. }
  161. need_alloc = src_len + *dst_len + 1;
  162. /* enlarge destination buffer if required */
  163. if(need_alloc > *dst_alloc) {
  164. size_t newsize = need_alloc * 2;
  165. char *newptr = realloc(*dst_buf, newsize);
  166. if(!newptr) {
  167. if(buf64.as_char)
  168. free(buf64.as_char);
  169. return GPE_OUT_OF_MEMORY;
  170. }
  171. *dst_alloc = newsize;
  172. *dst_buf = newptr;
  173. }
  174. /* memcpy to support binary blobs */
  175. memcpy(*dst_buf + *dst_len, src_buf, src_len);
  176. *dst_len += src_len;
  177. *(*dst_buf + *dst_len) = '\0';
  178. if(buf64.as_char)
  179. free(buf64.as_char);
  180. return GPE_OK;
  181. }
  182. /*
  183. * getpart()
  184. *
  185. * This returns whole contents of specified XML-like section and subsection
  186. * from the given file. This is mostly used to retrieve a specific part from
  187. * a test definition file for consumption by test suite servers.
  188. *
  189. * Data is returned in a dynamically allocated buffer, a pointer to this data
  190. * and the size of the data is stored at the addresses that caller specifies.
  191. *
  192. * If the returned data is a string the returned size will be the length of
  193. * the string excluding null termination. Otherwise it will just be the size
  194. * of the returned binary data.
  195. *
  196. * Calling function is responsible to free returned buffer.
  197. *
  198. * This function may return:
  199. * GPE_NO_BUFFER_SPACE
  200. * GPE_OUT_OF_MEMORY
  201. * GPE_OK
  202. */
  203. int getpart(char **outbuf, size_t *outlen,
  204. const char *main, const char *sub, FILE *stream)
  205. {
  206. # define MAX_TAG_LEN 79
  207. char couter[MAX_TAG_LEN+1]; /* current outermost section */
  208. char cmain[MAX_TAG_LEN+1]; /* current main section */
  209. char csub[MAX_TAG_LEN+1]; /* current sub section */
  210. char ptag[MAX_TAG_LEN+1]; /* potential tag */
  211. char patt[MAX_TAG_LEN+1]; /* potential attributes */
  212. char *buffer = NULL;
  213. char *ptr;
  214. char *end;
  215. union {
  216. ssize_t sig;
  217. size_t uns;
  218. } len;
  219. size_t bufsize = 0;
  220. size_t outalloc = 256;
  221. int in_wanted_part = 0;
  222. int base64 = 0;
  223. int error;
  224. enum {
  225. STATE_OUTSIDE = 0,
  226. STATE_OUTER = 1,
  227. STATE_INMAIN = 2,
  228. STATE_INSUB = 3,
  229. STATE_ILLEGAL = 4
  230. } state = STATE_OUTSIDE;
  231. *outlen = 0;
  232. *outbuf = malloc(outalloc);
  233. if(!*outbuf)
  234. return GPE_OUT_OF_MEMORY;
  235. *(*outbuf) = '\0';
  236. couter[0] = cmain[0] = csub[0] = ptag[0] = patt[0] = '\0';
  237. while((error = readline(&buffer, &bufsize, stream)) == GPE_OK) {
  238. ptr = buffer;
  239. EAT_SPACE(ptr);
  240. if('<' != *ptr) {
  241. if(in_wanted_part) {
  242. show(("=> %s", buffer));
  243. error = appenddata(outbuf, outlen, &outalloc, buffer, base64);
  244. if(error)
  245. break;
  246. }
  247. continue;
  248. }
  249. ptr++;
  250. if('/' == *ptr) {
  251. /*
  252. ** closing section tag
  253. */
  254. ptr++;
  255. end = ptr;
  256. EAT_WORD(end);
  257. if((len.sig = end - ptr) > MAX_TAG_LEN) {
  258. error = GPE_NO_BUFFER_SPACE;
  259. break;
  260. }
  261. memcpy(ptag, ptr, len.uns);
  262. ptag[len.uns] = '\0';
  263. if((STATE_INSUB == state) && !strcmp(csub, ptag)) {
  264. /* end of current sub section */
  265. state = STATE_INMAIN;
  266. csub[0] = '\0';
  267. if(in_wanted_part) {
  268. /* end of wanted part */
  269. in_wanted_part = 0;
  270. break;
  271. }
  272. }
  273. else if((STATE_INMAIN == state) && !strcmp(cmain, ptag)) {
  274. /* end of current main section */
  275. state = STATE_OUTER;
  276. cmain[0] = '\0';
  277. if(in_wanted_part) {
  278. /* end of wanted part */
  279. in_wanted_part = 0;
  280. break;
  281. }
  282. }
  283. else if((STATE_OUTER == state) && !strcmp(couter, ptag)) {
  284. /* end of outermost file section */
  285. state = STATE_OUTSIDE;
  286. couter[0] = '\0';
  287. if(in_wanted_part) {
  288. /* end of wanted part */
  289. in_wanted_part = 0;
  290. break;
  291. }
  292. }
  293. }
  294. else if(!in_wanted_part) {
  295. /*
  296. ** opening section tag
  297. */
  298. /* get potential tag */
  299. end = ptr;
  300. EAT_WORD(end);
  301. if((len.sig = end - ptr) > MAX_TAG_LEN) {
  302. error = GPE_NO_BUFFER_SPACE;
  303. break;
  304. }
  305. memcpy(ptag, ptr, len.uns);
  306. ptag[len.uns] = '\0';
  307. /* ignore comments, doctypes and xml declarations */
  308. if(('!' == ptag[0]) || ('?' == ptag[0])) {
  309. show(("* ignoring (%s)", buffer));
  310. continue;
  311. }
  312. /* get all potential attributes */
  313. ptr = end;
  314. EAT_SPACE(ptr);
  315. end = ptr;
  316. while(*end && ('>' != *end))
  317. end++;
  318. if((len.sig = end - ptr) > MAX_TAG_LEN) {
  319. error = GPE_NO_BUFFER_SPACE;
  320. break;
  321. }
  322. memcpy(patt, ptr, len.uns);
  323. patt[len.uns] = '\0';
  324. if(STATE_OUTSIDE == state) {
  325. /* outermost element (<testcase>) */
  326. strcpy(couter, ptag);
  327. state = STATE_OUTER;
  328. continue;
  329. }
  330. else if(STATE_OUTER == state) {
  331. /* start of a main section */
  332. strcpy(cmain, ptag);
  333. state = STATE_INMAIN;
  334. continue;
  335. }
  336. else if(STATE_INMAIN == state) {
  337. /* start of a sub section */
  338. strcpy(csub, ptag);
  339. state = STATE_INSUB;
  340. if(!strcmp(cmain, main) && !strcmp(csub, sub)) {
  341. /* start of wanted part */
  342. in_wanted_part = 1;
  343. if(strstr(patt, "base64="))
  344. /* bit rough test, but "mostly" functional, */
  345. /* treat wanted part data as base64 encoded */
  346. base64 = 1;
  347. }
  348. continue;
  349. }
  350. }
  351. if(in_wanted_part) {
  352. show(("=> %s", buffer));
  353. error = appenddata(outbuf, outlen, &outalloc, buffer, base64);
  354. if(error)
  355. break;
  356. }
  357. } /* while */
  358. if(buffer)
  359. free(buffer);
  360. if(error != GPE_OK) {
  361. if(error == GPE_END_OF_FILE)
  362. error = GPE_OK;
  363. else {
  364. if(*outbuf)
  365. free(*outbuf);
  366. *outbuf = NULL;
  367. *outlen = 0;
  368. }
  369. }
  370. return error;
  371. }