ESL_DECLARE(esl_status_t) esl_event_serialize(esl_event_t *event, char **str, esl_bool_t encode) { size_t len = 0; esl_event_header_t *hp; size_t llen = 0, dlen = 0, blocksize = 512, encode_len = 1536, new_len = 0; char *buf; char *encode_buf = NULL; /* used for url encoding of variables to make sure unsafe things stay out of the serialized copy */ int clen = 0; if (!event || !event->headers) return ESL_FAIL; *str = NULL; dlen = blocksize * 2; if (!(buf = malloc(dlen))) { return ESL_FAIL; } /* go ahead and give ourselves some space to work with, should save a few reallocs */ if (!(encode_buf = malloc(encode_len))) { esl_safe_free(buf); return ESL_FAIL; } /* esl_log_printf(ESL_CHANNEL_LOG, ESL_LOG_INFO, "hit serialized!.\n"); */ for (hp = event->headers; hp; hp = hp->next) { /* * grab enough memory to store 3x the string (url encode takes one char and turns it into %XX) * so we could end up with a string that is 3 times the originals length, unlikely but rather * be safe than destroy the string, also add one for the null. And try to be smart about using * the memory, allocate and only reallocate if we need more. This avoids an alloc, free CPU * destroying loop. */ if (!strcasecmp(hp->name, "content-length")) { clen++; } new_len = (strlen(hp->value) * 3) + 1; if (encode_len < new_len) { char *tmp; /* esl_log_printf(ESL_CHANNEL_LOG, ESL_LOG_INFO, "Allocing %d was %d.\n", ((strlen(hp->value) * 3) + 1), encode_len); */ /* we can use realloc for initial alloc as well, if encode_buf is zero it treats it as a malloc */ /* keep track of the size of our allocation */ encode_len = new_len; if (!(tmp = realloc(encode_buf, encode_len))) { /* oh boy, ram's gone, give back what little we grabbed and bail */ esl_safe_free(buf); esl_safe_free(encode_buf); return ESL_FAIL; } encode_buf = tmp; } /* handle any bad things in the string like newlines : etc that screw up the serialized format */ if (encode) { esl_url_encode(hp->value, encode_buf, encode_len); } else { esl_snprintf(encode_buf, encode_len, "%s", hp->value); } llen = strlen(hp->name) + strlen(encode_buf) + 8; if ((len + llen) > dlen) { char *m; dlen += (blocksize + (len + llen)); if ((m = realloc(buf, dlen))) { buf = m; } else { /* we seem to be out of memory trying to resize the serialize string, give back what we already have and give up */ esl_safe_free(buf); esl_safe_free(encode_buf); return ESL_FAIL; } } snprintf(buf + len, dlen - len, "%s: %s\n", hp->name, *encode_buf == '\0' ? "_undef_" : encode_buf); len = strlen(buf); } /* we are done with the memory we used for encoding, give it back */ esl_safe_free(encode_buf); if (event->body) { int blen = (int) strlen(event->body); llen = blen; if (blen) { llen += 25; } else { llen += 5; } if ((len + llen) > dlen) { char *m; dlen += (blocksize + (len + llen)); if ((m = realloc(buf, dlen))) { buf = m; } else { esl_safe_free(buf); return ESL_FAIL; } } if (blen) { if (clen) { snprintf(buf + len, dlen - len, "\n%s", event->body); } else { snprintf(buf + len, dlen - len, "Content-Length: %d\n\n%s", (int)strlen(event->body), event->body); } } } else { snprintf(buf + len, dlen - len, "\n"); } *str = buf; return ESL_SUCCESS; }
ESL_DECLARE(esl_status_t) esl_event_serialize(esl_event_t *event, char **str, esl_bool_t encode) { esl_size_t len = 0; esl_event_header_t *hp; esl_size_t llen = 0, dlen = 0, blocksize = 512, encode_len = 1536, new_len = 0; char *buf; char *encode_buf = NULL; /* used for url encoding of variables to make sure unsafe things stay out of the serialized copy */ *str = NULL; dlen = blocksize * 2; if (!(buf = malloc(dlen))) { abort(); } /* go ahead and give ourselves some space to work with, should save a few reallocs */ if (!(encode_buf = malloc(encode_len))) { abort(); } /* esl_log_printf(ESL_CHANNEL_LOG, ESL_LOG_INFO, "hit serialized!.\n"); */ for (hp = event->headers; hp; hp = hp->next) { /* * grab enough memory to store 3x the string (url encode takes one char and turns it into %XX) * so we could end up with a string that is 3 times the originals length, unlikely but rather * be safe than destroy the string, also add one for the null. And try to be smart about using * the memory, allocate and only reallocate if we need more. This avoids an alloc, free CPU * destroying loop. */ if (hp->idx) { int i; new_len = 0; for(i = 0; i < hp->idx; i++) { new_len += (strlen(hp->array[i]) * 3) + 1; } } else { new_len = (strlen(hp->value) * 3) + 1; } if (encode_len < new_len) { char *tmp; /* keep track of the size of our allocation */ encode_len = new_len; if (!(tmp = realloc(encode_buf, encode_len))) { abort(); } encode_buf = tmp; } /* handle any bad things in the string like newlines : etc that screw up the serialized format */ if (encode) { esl_url_encode(hp->value, encode_buf, encode_len); } else { esl_snprintf(encode_buf, encode_len, "[%s]", hp->value); } llen = strlen(hp->name) + strlen(encode_buf) + 8; if ((len + llen) > dlen) { char *m; char *old = buf; dlen += (blocksize + (len + llen)); if ((m = realloc(buf, dlen))) { buf = m; } else { buf = old; abort(); } } esl_snprintf(buf + len, dlen - len, "%s: %s\n", hp->name, *encode_buf == '\0' ? "_undef_" : encode_buf); len = strlen(buf); } /* we are done with the memory we used for encoding, give it back */ esl_safe_free(encode_buf); if (event->body) { int blen = (int) strlen(event->body); llen = blen; if (blen) { llen += 25; } else { llen += 5; } if ((len + llen) > dlen) { char *m; char *old = buf; dlen += (blocksize + (len + llen)); if ((m = realloc(buf, dlen))) { buf = m; } else { buf = old; abort(); } } if (blen) { esl_snprintf(buf + len, dlen - len, "Content-Length: %d\n\n%s", blen, event->body); } else { esl_snprintf(buf + len, dlen - len, "\n"); } } else { esl_snprintf(buf + len, dlen - len, "\n"); } *str = buf; return ESL_SUCCESS; }