static memory_pool_t *map_pool = NULL;
static GList *maps = NULL;
-static gchar *hash_fill = "1";
+static gchar *hash_fill = "1";
/* Http reply */
struct http_reply {
gint code;
GHashTable *headers;
- gchar *cur_header;
-
+ gchar *cur_header;
gint parser_state;
};
/**
* FSM for parsing HTTP reply
*/
-static u_char *
-parse_http_reply (u_char * chunk, size_t len, struct http_reply *reply)
+static gchar *
+parse_http_reply (gchar * chunk, size_t len, struct http_reply *reply)
{
- u_char *s, *p, *err_str, *tmp;
+ gchar *s, *p, *err_str, *tmp;
p = chunk;
s = chunk;
* Read and parse chunked header
*/
static gint
-read_chunk_header (u_char * buf, size_t len, struct http_map_data *data)
+read_chunk_header (gchar * buf, size_t len, struct http_map_data *data)
{
- u_char chunkbuf[32], *p, *c;
+ gchar chunkbuf[32], *p, *c, *err_str;
gint skip = 0;
p = chunkbuf;
c = buf;
/* Find hex digits */
- while (g_ascii_isxdigit (*c) && p - chunkbuf < sizeof (chunkbuf) - 1) {
+ while (g_ascii_isxdigit (*c) && p - chunkbuf < sizeof (chunkbuf) - 1 && skip < len) {
*p++ = *c++;
skip++;
}
*p = '\0';
- data->chunk = strtoul (chunkbuf, NULL, 16);
+ data->chunk = strtoul (chunkbuf, &err_str, 16);
+ if (*err_str != '\0') {
+ return -1;
+ }
+
/* Now skip to CRLF */
- while (*c != '\n' && c - buf < len) {
+ while (*c != '\n' && skip < len) {
c++;
skip++;
}
- if (*c == '\n') {
+ if (*c == '\n' && skip < len) {
skip++;
c++;
}
- data->chunk_read = 0;
+ data->chunk_remain = data->chunk;
return skip;
}
* Helper callback for reading chunked reply
*/
static gboolean
-read_http_chunked (u_char * buf, size_t len, struct rspamd_map *map, struct http_map_data *data, struct map_cb_data *cbdata)
+read_http_chunked (gchar * buf, size_t len, struct rspamd_map *map, struct http_map_data *data, struct map_cb_data *cbdata)
{
- u_char *p = buf, *remain;
- guint32 skip = 0;
+ gchar *p = buf, *remain;
+ gint skip = 0;
- if (data->chunk == 0) {
+ if (data->chunked == 1) {
/* Read first chunk data */
- skip = read_chunk_header (buf, len, data);
- p += skip;
- len -= skip;
- }
-
- data->chunk_read += len;
- if (data->chunk_read >= data->chunk) {
- /* Read next chunk and feed callback with remaining buffer */
- remain = map->read_callback (map->pool, p, len - (data->chunk_read - data->chunk), cbdata);
- if (remain != NULL && remain != p) {
- /* copy remaining buffer to start of buffer */
- data->rlen = len - (remain - p);
- memmove (p, remain, data->rlen);
- data->chunk_read -= data->rlen;
+ if ((skip = read_chunk_header (buf, len, data)) != -1) {
+ p += skip;
+ len -= skip;
+ data->chunked = 2;
+ }
+ else {
+ msg_info ("invalid chunked reply: %*s", (gint)len, buf);
+ return FALSE;
}
}
- if (data->chunk_read >= data->chunk) {
- p = p + (len - (data->chunk_read - data->chunk));
- if (*p != '\r') {
- if (*p == '0') {
- return TRUE;
- }
- else {
- msg_info ("invalid chunked reply: %*s", (gint)len, buf);
- return FALSE;
- }
+
+ if (data->chunk_remain == 0) {
+ /* Read another chunk */
+ if ((skip = read_chunk_header (buf, len, data)) != -1) {
+ p += skip;
+ len -= skip;
}
- p += 2;
- if (len == p - buf) {
- /* Next chunk data is not available */
- data->chunk = 0;
- return TRUE;
+ else {
+ msg_info ("invalid chunked reply: %*s", (gint)len, buf);
+ return FALSE;
}
-
- len -= p - buf;
- skip = read_chunk_header (p, len, data);
- p += skip;
- len -= skip;
if (data->chunk == 0) {
return FALSE;
}
}
- remain = map->read_callback (map->pool, p, len, cbdata);
- if (remain != NULL && remain != p + len) {
- /* copy remaining buffer to start of buffer */
- data->rlen = len - (remain - p);
- memmove (p, remain, data->rlen);
+ if (data->chunk_remain <= len ) {
+ /* Call callback and move remaining buffer */
+ remain = map->read_callback (map->pool, p, data->chunk_remain, cbdata);
+ if (remain != NULL && remain != p + data->chunk_remain) {
+ /* Copy remaining buffer to start of buffer */
+ data->rlen = len - (remain - p);
+ memmove (buf, remain, data->rlen);
+ data->chunk_remain -= data->rlen;
+ }
+ else {
+ /* Copy other part */
+ data->rlen = len - data->chunk_remain;
+ if (data->rlen > 0) {
+ memmove (buf, p + data->chunk_remain, data->rlen);
+ }
+ data->chunk_remain = 0;
+ }
+
+ }
+ else {
+ /* Just read another portion of chunk */
+ data->chunk_remain -= len;
+ remain = map->read_callback (map->pool, p, len, cbdata);
+ if (remain != NULL && remain != p + len) {
+ /* copy remaining buffer to start of buffer */
+ data->rlen = len - (remain - p);
+ memmove (buf, remain, data->rlen);
+ }
}
return TRUE;
static gboolean
read_http_common (struct rspamd_map *map, struct http_map_data *data, struct http_reply *reply, struct map_cb_data *cbdata, gint fd)
{
- u_char *remain, *pos;
+ gchar *remain, *pos;
ssize_t r;
gchar *te;
}
pos = data->read_buf;
/* Check for chunked */
- if (!data->chunked && (te = g_hash_table_lookup (reply->headers, "Transfer-Encoding")) != NULL) {
- if (g_ascii_strcasecmp (te, "chunked") == 0) {
- data->chunked = TRUE;
+ if (data->chunked == 0) {
+ if ((te = g_hash_table_lookup (reply->headers, "Transfer-Encoding")) != NULL) {
+ if (g_ascii_strcasecmp (te, "chunked") == 0) {
+ data->chunked = 1;
+ }
+ else {
+ data->chunked = -1;
+ }
+ }
+ else {
+ data->chunked = -1;
}
}
- if (data->chunked) {
+
+ if (data->chunked > 0) {
return read_http_chunked (data->read_buf, r, map, data, cbdata);
}
/* Read more data */
read_map_file (struct rspamd_map *map, struct file_map_data *data)
{
struct map_cb_data cbdata;
- u_char buf[BUFSIZ], *remain;
+ gchar buf[BUFSIZ], *remain;
ssize_t r;
gint fd, rlen;
/**
* FSM for parsing lists
*/
-u_char *
-abstract_parse_kv_list (memory_pool_t * pool, u_char * chunk, size_t len, struct map_cb_data *data, insert_func func)
+gchar *
+abstract_parse_kv_list (memory_pool_t * pool, gchar * chunk, size_t len, struct map_cb_data *data, insert_func func)
{
- u_char *c, *p, *key = NULL, *value = NULL;
+ gchar *c, *p, *key = NULL, *value = NULL;
p = chunk;
c = p;
return c;
}
-u_char *
-abstract_parse_list (memory_pool_t * pool, u_char * chunk, size_t len, struct map_cb_data *data, insert_func func)
+gchar *
+abstract_parse_list (memory_pool_t * pool, gchar * chunk, size_t len, struct map_cb_data *data, insert_func func)
{
- u_char *s, *p, *str, *start;
+ gchar *s, *p, *str, *start;
p = chunk;
start = p;
}
/* Helpers */
-u_char *
-read_host_list (memory_pool_t * pool, u_char * chunk, size_t len, struct map_cb_data *data)
+gchar *
+read_host_list (memory_pool_t * pool, gchar * chunk, size_t len, struct map_cb_data *data)
{
if (data->cur_data == NULL) {
data->cur_data = g_hash_table_new (rspamd_strcase_hash, rspamd_strcase_equal);
}
}
-u_char *
-read_kv_list (memory_pool_t * pool, u_char * chunk, size_t len, struct map_cb_data *data)
+gchar *
+read_kv_list (memory_pool_t * pool, gchar * chunk, size_t len, struct map_cb_data *data)
{
if (data->cur_data == NULL) {
data->cur_data = g_hash_table_new (rspamd_strcase_hash, rspamd_strcase_equal);
}
}
-u_char *
-read_radix_list (memory_pool_t * pool, u_char * chunk, size_t len, struct map_cb_data *data)
+gchar *
+read_radix_list (memory_pool_t * pool, gchar * chunk, size_t len, struct map_cb_data *data)
{
if (data->cur_data == NULL) {
data->cur_data = radix_tree_create ();
cbd->cbdata.cur_data = NULL;
cbd->data->rlen = 0;
cbd->data->chunk = 0;
- cbd->data->chunk_read = 0;
+ cbd->data->chunk_remain = 0;
cbd->data->chunked = FALSE;
cbd->data->read_buf[0] = '\0';
gchar *path;
gchar *host;
time_t last_checked;
- gboolean chunked;
- u_char read_buf[BUFSIZ];
+ gshort chunked;
+ gchar read_buf[BUFSIZ];
guint32 rlen;
guint32 chunk;
- guint32 chunk_read;
+ guint32 chunk_remain;
};
/**
* Callback types
*/
-typedef u_char* (*map_cb_t)(memory_pool_t *pool, u_char *chunk, size_t len, struct map_cb_data *data);
+typedef gchar* (*map_cb_t)(memory_pool_t *pool, gchar *chunk, size_t len, struct map_cb_data *data);
typedef void (*map_fin_cb_t)(memory_pool_t *pool, struct map_cb_data *data);
/**
/**
* Radix list is a list like ip/mask
*/
-u_char* read_radix_list (memory_pool_t *pool, u_char *chunk, size_t len, struct map_cb_data *data);
+gchar* read_radix_list (memory_pool_t *pool, gchar *chunk, size_t len, struct map_cb_data *data);
void fin_radix_list (memory_pool_t *pool, struct map_cb_data *data);
/**
* Host list is an ordinal list of hosts or domains
*/
-u_char* read_host_list (memory_pool_t *pool, u_char *chunk, size_t len, struct map_cb_data *data);
+gchar* read_host_list (memory_pool_t *pool, gchar *chunk, size_t len, struct map_cb_data *data);
void fin_host_list (memory_pool_t *pool, struct map_cb_data *data);
/**
* Kv list is an ordinal list of keys and values separated by whitespace
*/
-u_char* read_kv_list (memory_pool_t *pool, u_char *chunk, size_t len, struct map_cb_data *data);
+gchar* read_kv_list (memory_pool_t *pool, gchar *chunk, size_t len, struct map_cb_data *data);
void fin_kv_list (memory_pool_t *pool, struct map_cb_data *data);
/**
* FSM for lists parsing (support comments, blank lines and partial replies)
*/
-u_char * abstract_parse_list (memory_pool_t * pool, u_char * chunk, size_t len, struct map_cb_data *data, insert_func func);
+gchar * abstract_parse_list (memory_pool_t * pool, gchar * chunk, size_t len, struct map_cb_data *data, insert_func func);
#endif