00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "server_setup.h"
00023
00024 #include "getpart.h"
00025
00026 #define ENABLE_CURLX_PRINTF
00027
00028
00029 #include "curlx.h"
00030
00031
00032 struct Curl_easy {
00033 int fake;
00034 };
00035
00036 #include "curl_base64.h"
00037 #include "curl_memory.h"
00038
00039
00040 #include "memdebug.h"
00041
00042 #define EAT_SPACE(p) while(*(p) && ISSPACE(*(p))) (p)++
00043
00044 #define EAT_WORD(p) while(*(p) && !ISSPACE(*(p)) && ('>' != *(p))) (p)++
00045
00046 #ifdef DEBUG_GETPART
00047 #define show(x) printf x
00048 #else
00049 #define show(x) Curl_nop_stmt
00050 #endif
00051
00052 #if defined(_MSC_VER) && defined(_DLL)
00053 # pragma warning(disable:4232)
00054 #endif
00055
00056 curl_malloc_callback Curl_cmalloc = (curl_malloc_callback)malloc;
00057 curl_free_callback Curl_cfree = (curl_free_callback)free;
00058 curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc;
00059 curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)strdup;
00060 curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc;
00061 #if defined(WIN32) && defined(UNICODE)
00062 curl_wcsdup_callback Curl_cwcsdup = (curl_wcsdup_callback)_wcsdup;
00063 #endif
00064
00065 #if defined(_MSC_VER) && defined(_DLL)
00066 # pragma warning(default:4232)
00067 #endif
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087 static int readline(char **buffer, size_t *bufsize, FILE *stream)
00088 {
00089 size_t offset = 0;
00090 size_t length;
00091 char *newptr;
00092
00093 if(!*buffer) {
00094 *buffer = malloc(128);
00095 if(!*buffer)
00096 return GPE_OUT_OF_MEMORY;
00097 *bufsize = 128;
00098 }
00099
00100 for(;;) {
00101 int bytestoread = curlx_uztosi(*bufsize - offset);
00102
00103 if(!fgets(*buffer + offset, bytestoread, stream))
00104 return (offset != 0) ? GPE_OK : GPE_END_OF_FILE;
00105
00106 length = offset + strlen(*buffer + offset);
00107 if(*(*buffer + length - 1) == '\n')
00108 break;
00109 offset = length;
00110 if(length < *bufsize - 1)
00111 continue;
00112
00113 newptr = realloc(*buffer, *bufsize * 2);
00114 if(!newptr)
00115 return GPE_OUT_OF_MEMORY;
00116 *buffer = newptr;
00117 *bufsize *= 2;
00118 }
00119
00120 return GPE_OK;
00121 }
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149 static int appenddata(char **dst_buf,
00150 size_t *dst_len,
00151 size_t *dst_alloc,
00152 char *src_buf,
00153 int src_b64)
00154 {
00155 size_t need_alloc = 0;
00156 size_t src_len = strlen(src_buf);
00157
00158 if(!src_len)
00159 return GPE_OK;
00160
00161 need_alloc = src_len + *dst_len + 1;
00162
00163 if(src_b64) {
00164 if(src_buf[src_len - 1] == '\r')
00165 src_len--;
00166
00167 if(src_buf[src_len - 1] == '\n')
00168 src_len--;
00169 }
00170
00171
00172 if(need_alloc > *dst_alloc) {
00173 size_t newsize = need_alloc * 2;
00174 char *newptr = realloc(*dst_buf, newsize);
00175 if(!newptr) {
00176 return GPE_OUT_OF_MEMORY;
00177 }
00178 *dst_alloc = newsize;
00179 *dst_buf = newptr;
00180 }
00181
00182
00183 memcpy(*dst_buf + *dst_len, src_buf, src_len);
00184 *dst_len += src_len;
00185 *(*dst_buf + *dst_len) = '\0';
00186
00187 return GPE_OK;
00188 }
00189
00190 static int decodedata(char **buf,
00191 size_t *len)
00192 {
00193 int error = 0;
00194 unsigned char *buf64 = NULL;
00195 size_t src_len = 0;
00196
00197 if(!*len)
00198 return GPE_OK;
00199
00200
00201 error = (int) Curl_base64_decode(*buf, &buf64, &src_len);
00202 if(error)
00203 return GPE_OUT_OF_MEMORY;
00204
00205 if(!src_len) {
00206
00207
00208
00209
00210
00211
00212 free(buf64);
00213
00214 return GPE_OUT_OF_MEMORY;
00215 }
00216
00217
00218 memcpy(*buf, buf64, src_len);
00219 *len = src_len;
00220 *(*buf + src_len) = '\0';
00221
00222 free(buf64);
00223
00224 return GPE_OK;
00225 }
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249 int getpart(char **outbuf, size_t *outlen,
00250 const char *main, const char *sub, FILE *stream)
00251 {
00252 # define MAX_TAG_LEN 79
00253 char couter[MAX_TAG_LEN+1];
00254 char cmain[MAX_TAG_LEN+1];
00255 char csub[MAX_TAG_LEN+1];
00256 char ptag[MAX_TAG_LEN+1];
00257 char patt[MAX_TAG_LEN+1];
00258 char *buffer = NULL;
00259 char *ptr;
00260 char *end;
00261 union {
00262 ssize_t sig;
00263 size_t uns;
00264 } len;
00265 size_t bufsize = 0;
00266 size_t outalloc = 256;
00267 int in_wanted_part = 0;
00268 int base64 = 0;
00269 int error;
00270
00271 enum {
00272 STATE_OUTSIDE = 0,
00273 STATE_OUTER = 1,
00274 STATE_INMAIN = 2,
00275 STATE_INSUB = 3,
00276 STATE_ILLEGAL = 4
00277 } state = STATE_OUTSIDE;
00278
00279 *outlen = 0;
00280 *outbuf = malloc(outalloc);
00281 if(!*outbuf)
00282 return GPE_OUT_OF_MEMORY;
00283 *(*outbuf) = '\0';
00284
00285 couter[0] = cmain[0] = csub[0] = ptag[0] = patt[0] = '\0';
00286
00287 while((error = readline(&buffer, &bufsize, stream)) == GPE_OK) {
00288
00289 ptr = buffer;
00290 EAT_SPACE(ptr);
00291
00292 if('<' != *ptr) {
00293 if(in_wanted_part) {
00294 show(("=> %s", buffer));
00295 error = appenddata(outbuf, outlen, &outalloc, buffer, base64);
00296 if(error)
00297 break;
00298 }
00299 continue;
00300 }
00301
00302 ptr++;
00303
00304 if('/' == *ptr) {
00305
00306
00307
00308
00309 ptr++;
00310 end = ptr;
00311 EAT_WORD(end);
00312 len.sig = end - ptr;
00313 if(len.sig > MAX_TAG_LEN) {
00314 error = GPE_NO_BUFFER_SPACE;
00315 break;
00316 }
00317 memcpy(ptag, ptr, len.uns);
00318 ptag[len.uns] = '\0';
00319
00320 if((STATE_INSUB == state) && !strcmp(csub, ptag)) {
00321
00322 state = STATE_INMAIN;
00323 csub[0] = '\0';
00324 if(in_wanted_part) {
00325
00326 in_wanted_part = 0;
00327
00328
00329 if(base64) {
00330 error = decodedata(outbuf, outlen);
00331 if(error)
00332 return error;
00333 }
00334 break;
00335 }
00336 }
00337 else if((STATE_INMAIN == state) && !strcmp(cmain, ptag)) {
00338
00339 state = STATE_OUTER;
00340 cmain[0] = '\0';
00341 if(in_wanted_part) {
00342
00343 in_wanted_part = 0;
00344
00345
00346 if(base64) {
00347 error = decodedata(outbuf, outlen);
00348 if(error)
00349 return error;
00350 }
00351 break;
00352 }
00353 }
00354 else if((STATE_OUTER == state) && !strcmp(couter, ptag)) {
00355
00356 state = STATE_OUTSIDE;
00357 couter[0] = '\0';
00358 if(in_wanted_part) {
00359
00360 in_wanted_part = 0;
00361 break;
00362 }
00363 }
00364
00365 }
00366 else if(!in_wanted_part) {
00367
00368
00369
00370
00371
00372 end = ptr;
00373 EAT_WORD(end);
00374 len.sig = end - ptr;
00375 if(len.sig > MAX_TAG_LEN) {
00376 error = GPE_NO_BUFFER_SPACE;
00377 break;
00378 }
00379 memcpy(ptag, ptr, len.uns);
00380 ptag[len.uns] = '\0';
00381
00382
00383 if(('!' == ptag[0]) || ('?' == ptag[0])) {
00384 show(("* ignoring (%s)", buffer));
00385 continue;
00386 }
00387
00388
00389 ptr = end;
00390 EAT_SPACE(ptr);
00391 end = ptr;
00392 while(*end && ('>' != *end))
00393 end++;
00394 len.sig = end - ptr;
00395 if(len.sig > MAX_TAG_LEN) {
00396 error = GPE_NO_BUFFER_SPACE;
00397 break;
00398 }
00399 memcpy(patt, ptr, len.uns);
00400 patt[len.uns] = '\0';
00401
00402 if(STATE_OUTSIDE == state) {
00403
00404 strcpy(couter, ptag);
00405 state = STATE_OUTER;
00406 continue;
00407 }
00408 else if(STATE_OUTER == state) {
00409
00410 strcpy(cmain, ptag);
00411 state = STATE_INMAIN;
00412 continue;
00413 }
00414 else if(STATE_INMAIN == state) {
00415
00416 strcpy(csub, ptag);
00417 state = STATE_INSUB;
00418 if(!strcmp(cmain, main) && !strcmp(csub, sub)) {
00419
00420 in_wanted_part = 1;
00421 if(strstr(patt, "base64="))
00422
00423
00424 base64 = 1;
00425 }
00426 continue;
00427 }
00428
00429 }
00430
00431 if(in_wanted_part) {
00432 show(("=> %s", buffer));
00433 error = appenddata(outbuf, outlen, &outalloc, buffer, base64);
00434 if(error)
00435 break;
00436 }
00437
00438 }
00439
00440 free(buffer);
00441
00442 if(error != GPE_OK) {
00443 if(error == GPE_END_OF_FILE)
00444 error = GPE_OK;
00445 else {
00446 free(*outbuf);
00447 *outbuf = NULL;
00448 *outlen = 0;
00449 }
00450 }
00451
00452 return error;
00453 }
00454