Example #1
0
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;
}
Example #2
0
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;
}