\
a[n * SIZE_BIT / CHAR_BIT] &= (0xF << (4 - (n % (CHAR_BIT/SIZE_BIT) * SIZE_BIT))); \
a[n * SIZE_BIT / CHAR_BIT] |= (acc << (n % (CHAR_BIT/SIZE_BIT) * SIZE_BIT)); \
-} while (0);
+} while (0);
#define DECBIT(a, n, acc) do { \
acc = a[n * SIZE_BIT / CHAR_BIT] & (0xF << (n % (CHAR_BIT / SIZE_BIT) * SIZE_BIT)); \
#define GETBIT(a, n) (a[n * SIZE_BIT / CHAR_BIT] & (0xF << (n % (CHAR_BIT/SIZE_BIT) * SIZE_BIT)))
/* Common hash functions */
-unsigned int
-bloom_sax_hash(const char *key)
+unsigned int
+bloom_sax_hash (const char *key)
{
- unsigned int h = 0;
+ unsigned int h = 0;
- while(*key) h ^= (h<<5) + (h>>2) + (unsigned char)*key++;
+ while (*key)
+ h ^= (h << 5) + (h >> 2) + (unsigned char)*key++;
return h;
}
-unsigned int
-bloom_sdbm_hash(const char *key)
+unsigned int
+bloom_sdbm_hash (const char *key)
{
- unsigned int h = 0;
+ unsigned int h = 0;
- while(*key) h = (unsigned char)*key++ + (h<<6) + (h<<16) - h;
+ while (*key)
+ h = (unsigned char)*key++ + (h << 6) + (h << 16) - h;
return h;
}
unsigned int
bloom_fnv_hash (const char *key)
{
- unsigned int h = 0;
-
+ unsigned int h = 0;
+
while (*key) {
h ^= (unsigned char)*key++;
- h += (h<<1) + (h<<4) + (h<<7) + (h<<8) + (h<<24);
+ h += (h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24);
}
return h;
}
-unsigned int
+unsigned int
bloom_rs_hash (const char *key)
{
- unsigned int b = 378551;
- unsigned int a = 63689;
- unsigned int hash = 0;
+ unsigned int b = 378551;
+ unsigned int a = 63689;
+ unsigned int hash = 0;
while (*key) {
hash = hash * a + (unsigned char)*key++;
return hash;
}
-unsigned int
+unsigned int
bloom_js_hash (const char *key)
{
- unsigned int hash = 1315423911;
+ unsigned int hash = 1315423911;
while (*key) {
hash ^= ((hash << 5) + (unsigned char)*key++ + (hash >> 2));
}
-unsigned int
+unsigned int
bloom_elf_hash (const char *key)
{
- unsigned int hash = 0;
- unsigned int x = 0;
+ unsigned int hash = 0;
+ unsigned int x = 0;
while (*key) {
hash = (hash << 4) + (unsigned char)*key++;
- if((x = hash & 0xF0000000L) != 0) {
+ if ((x = hash & 0xF0000000L) != 0) {
hash ^= (x >> 24);
}
hash &= ~x;
}
-unsigned int
+unsigned int
bloom_bkdr_hash (const char *key)
{
- unsigned int seed = 131; /* 31 131 1313 13131 131313 etc.. */
- unsigned int hash = 0;
+ unsigned int seed = 131; /* 31 131 1313 13131 131313 etc.. */
+ unsigned int hash = 0;
while (*key) {
- hash = (hash * seed) + (unsigned char)*key ++;
+ hash = (hash * seed) + (unsigned char)*key++;
}
return hash;
}
-unsigned int
+unsigned int
bloom_ap_hash (const char *key)
{
- unsigned int hash = 0xAAAAAAAA;
- unsigned int i = 0;
+ unsigned int hash = 0xAAAAAAAA;
+ unsigned int i = 0;
while (*key) {
- hash ^= ((i & 1) == 0) ? ((hash << 7) ^ ((unsigned char)*key) * (hash >> 3)) :
- (~((hash << 11) + (((unsigned char)*key) ^ (hash >> 5))));
+ hash ^= ((i & 1) == 0) ? ((hash << 7) ^ ((unsigned char)*key) * (hash >> 3)) : (~((hash << 11) + (((unsigned char)*key) ^ (hash >> 5))));
key++;
}
return hash;
}
-bloom_filter_t *
+bloom_filter_t *
bloom_create (size_t size, size_t nfuncs, ...)
{
- bloom_filter_t *bloom;
- va_list l;
- int n;
+ bloom_filter_t *bloom;
+ va_list l;
+ int n;
if (!(bloom = g_malloc (sizeof (bloom_filter_t)))) {
return NULL;
}
- if (!(bloom->a = g_new0 (char, (size + CHAR_BIT - 1) / CHAR_BIT * SIZE_BIT))) {
+ if (!(bloom->a = g_new0 (char, (size + CHAR_BIT - 1) / CHAR_BIT * SIZE_BIT))) {
g_free (bloom);
return NULL;
}
}
void
-bloom_destroy (bloom_filter_t *bloom)
+bloom_destroy (bloom_filter_t * bloom)
{
g_free (bloom->a);
g_free (bloom->funcs);
}
gboolean
-bloom_add (bloom_filter_t *bloom, const char *s)
+bloom_add (bloom_filter_t * bloom, const char *s)
{
- size_t n;
- u_char t;
+ size_t n;
+ u_char t;
for (n = 0; n < bloom->nfuncs; ++n) {
INCBIT (bloom->a, bloom->funcs[n] (s) % bloom->asize, t);
}
gboolean
-bloom_del (bloom_filter_t *bloom, const char *s)
+bloom_del (bloom_filter_t * bloom, const char *s)
{
- size_t n;
- u_char t;
+ size_t n;
+ u_char t;
for (n = 0; n < bloom->nfuncs; ++n) {
DECBIT (bloom->a, bloom->funcs[n] (s) % bloom->asize, t);
}
return TRUE;
-
+
}
gboolean
bloom_check (bloom_filter_t * bloom, const char *s)
{
- size_t n;
+ size_t n;
for (n = 0; n < bloom->nfuncs; ++n) {
if (!(GETBIT (bloom->a, bloom->funcs[n] (s) % bloom->asize)))
#define G_DISPATCHER_ERROR dispatcher_error_quark()
-static void dispatcher_cb (int fd, short what, void *arg);
+static void dispatcher_cb (int fd, short what, void *arg);
-static inline GQuark
+static inline GQuark
dispatcher_error_quark (void)
{
- return g_quark_from_static_string ("g-dispatcher-error-quark");
+ return g_quark_from_static_string ("g-dispatcher-error-quark");
}
#define BUFREMAIN(x) (x)->data->size - ((x)->pos - (x)->data->begin)
-static gboolean
-write_buffers (int fd, rspamd_io_dispatcher_t *d, gboolean is_delayed)
+static gboolean
+write_buffers (int fd, rspamd_io_dispatcher_t * d, gboolean is_delayed)
{
- GList *cur;
- GError *err;
- rspamd_buffer_t *buf;
- ssize_t r;
+ GList *cur;
+ GError *err;
+ rspamd_buffer_t *buf;
+ ssize_t r;
/* Fix order */
if (d->out_buffers) {
}
cur = g_list_first (d->out_buffers);
while (cur) {
- buf = (rspamd_buffer_t *)cur->data;
+ buf = (rspamd_buffer_t *) cur->data;
if (BUFREMAIN (buf) == 0) {
/* Skip empty buffers */
cur = g_list_next (cur);
return FALSE;
}
}
-
+
event_del (d->ev);
event_set (d->ev, fd, EV_READ | EV_PERSIST, dispatcher_cb, (void *)d);
event_add (d->ev, d->tv);
}
static void
-read_buffers (int fd, rspamd_io_dispatcher_t *d, gboolean skip_read)
+read_buffers (int fd, rspamd_io_dispatcher_t * d, gboolean skip_read)
{
- ssize_t r;
- GError *err;
- f_str_t res;
- char *c, *b;
- char **pos;
- size_t *len;
- enum io_policy saved_policy;
-
+ ssize_t r;
+ GError *err;
+ f_str_t res;
+ char *c, *b;
+ char **pos;
+ size_t *len;
+ enum io_policy saved_policy;
+
if (d->wanna_die) {
rspamd_remove_dispatcher (d);
return;
pos = &d->in_buf->pos;
len = &d->in_buf->data->len;
-
+
if (BUFREMAIN (d->in_buf) == 0) {
/* Buffer is full, try to call callback with overflow error */
if (d->err_callback) {
*pos += r;
*len += r;
}
- msg_debug ("read_buffers: read %ld characters, policy is %s, watermark is: %ld",
- (long int)r, d->policy == BUFFER_LINE ? "LINE" : "CHARACTER",
- (long int)d->nchars);
+ msg_debug ("read_buffers: read %ld characters, policy is %s, watermark is: %ld", (long int)r, d->policy == BUFFER_LINE ? "LINE" : "CHARACTER", (long int)d->nchars);
}
-
+
saved_policy = d->policy;
c = d->in_buf->data->begin;
b = c;
r = 0;
switch (d->policy) {
- case BUFFER_LINE:
- while (r < *len) {
- if (*c == '\n') {
- res.begin = b;
- res.len = r;
- if (r != 0 && *(c - 1) == '\r') {
- res.len --;
- }
- if (d->read_callback) {
- if (!d->read_callback (&res, d->user_data)) {
- return;
- }
- /* Move remaining string to begin of buffer (draining) */
- memmove (d->in_buf->data->begin, c + 1, *len - r - 1);
- b = d->in_buf->data->begin;
- c = b;
- *len -= r + 1;
- *pos = b + *len;
- r = 0;
- if (d->policy != saved_policy) {
- msg_debug ("read_buffers: policy changed during callback, restart buffer's processing");
- read_buffers (fd, d, TRUE);
- return;
- }
- }
- }
- r ++;
- c ++;
- }
- break;
- case BUFFER_CHARACTER:
- r = d->nchars;
- if (*len >= r) {
+ case BUFFER_LINE:
+ while (r < *len) {
+ if (*c == '\n') {
res.begin = b;
res.len = r;
- c = b + r;
+ if (r != 0 && *(c - 1) == '\r') {
+ res.len--;
+ }
if (d->read_callback) {
if (!d->read_callback (&res, d->user_data)) {
return;
}
/* Move remaining string to begin of buffer (draining) */
- memmove (d->in_buf->data->begin, c, *len - r);
+ memmove (d->in_buf->data->begin, c + 1, *len - r - 1);
b = d->in_buf->data->begin;
c = b;
- *len -= r;
+ *len -= r + 1;
*pos = b + *len;
+ r = 0;
if (d->policy != saved_policy) {
msg_debug ("read_buffers: policy changed during callback, restart buffer's processing");
read_buffers (fd, d, TRUE);
}
}
}
- break;
+ r++;
+ c++;
+ }
+ break;
+ case BUFFER_CHARACTER:
+ r = d->nchars;
+ if (*len >= r) {
+ res.begin = b;
+ res.len = r;
+ c = b + r;
+ if (d->read_callback) {
+ if (!d->read_callback (&res, d->user_data)) {
+ return;
+ }
+ /* Move remaining string to begin of buffer (draining) */
+ memmove (d->in_buf->data->begin, c, *len - r);
+ b = d->in_buf->data->begin;
+ c = b;
+ *len -= r;
+ *pos = b + *len;
+ if (d->policy != saved_policy) {
+ msg_debug ("read_buffers: policy changed during callback, restart buffer's processing");
+ read_buffers (fd, d, TRUE);
+ return;
+ }
+ }
+ }
+ break;
}
}
static void
dispatcher_cb (int fd, short what, void *arg)
{
- rspamd_io_dispatcher_t *d = (rspamd_io_dispatcher_t *)arg;
- GError *err;
+ rspamd_io_dispatcher_t *d = (rspamd_io_dispatcher_t *) arg;
+ GError *err;
msg_debug ("dispatcher_cb: in dispatcher callback, what: %d, fd: %d", (int)what, fd);
switch (what) {
- case EV_TIMEOUT:
- if (d->err_callback) {
- err = g_error_new (G_DISPATCHER_ERROR, ETIMEDOUT, "IO timeout");
- d->err_callback (err, d->user_data);
- }
- break;
- case EV_WRITE:
- /* No data to write, disable further EV_WRITE to this fd */
- if (d->out_buffers == NULL) {
- event_del (d->ev);
- event_set (d->ev, fd, EV_READ | EV_PERSIST, dispatcher_cb, (void *)d);
- event_add (d->ev, d->tv);
- }
- else {
- /* Delayed write */
- write_buffers (fd, d, TRUE);
- }
- break;
- case EV_READ:
- read_buffers (fd, d, FALSE);
- break;
+ case EV_TIMEOUT:
+ if (d->err_callback) {
+ err = g_error_new (G_DISPATCHER_ERROR, ETIMEDOUT, "IO timeout");
+ d->err_callback (err, d->user_data);
+ }
+ break;
+ case EV_WRITE:
+ /* No data to write, disable further EV_WRITE to this fd */
+ if (d->out_buffers == NULL) {
+ event_del (d->ev);
+ event_set (d->ev, fd, EV_READ | EV_PERSIST, dispatcher_cb, (void *)d);
+ event_add (d->ev, d->tv);
+ }
+ else {
+ /* Delayed write */
+ write_buffers (fd, d, TRUE);
+ }
+ break;
+ case EV_READ:
+ read_buffers (fd, d, FALSE);
+ break;
}
}
-rspamd_io_dispatcher_t*
+rspamd_io_dispatcher_t *
rspamd_create_dispatcher (int fd, enum io_policy policy,
- dispatcher_read_callback_t read_cb,
- dispatcher_write_callback_t write_cb,
- dispatcher_err_callback_t err_cb,
- struct timeval *tv, void *user_data)
+ dispatcher_read_callback_t read_cb, dispatcher_write_callback_t write_cb, dispatcher_err_callback_t err_cb, struct timeval *tv, void *user_data)
{
- rspamd_io_dispatcher_t *new;
+ rspamd_io_dispatcher_t *new;
if (fd == -1) {
return NULL;
}
-
+
new = g_malloc (sizeof (rspamd_io_dispatcher_t));
bzero (new, sizeof (rspamd_io_dispatcher_t));
return new;
}
-void
-rspamd_remove_dispatcher (rspamd_io_dispatcher_t *dispatcher)
+void
+rspamd_remove_dispatcher (rspamd_io_dispatcher_t * dispatcher)
{
if (dispatcher != NULL) {
event_del (dispatcher->ev);
}
}
-void
-rspamd_set_dispatcher_policy (rspamd_io_dispatcher_t *d,
- enum io_policy policy,
- size_t nchars)
+void
+rspamd_set_dispatcher_policy (rspamd_io_dispatcher_t * d, enum io_policy policy, size_t nchars)
{
- f_str_t *tmp;
- int t;
+ f_str_t *tmp;
+ int t;
if (d->policy != policy) {
d->policy = policy;
msg_debug ("rspamd_set_dispatcher_policy: new input length watermark is %ld", (long int)d->nchars);
}
-gboolean
-rspamd_dispatcher_write (rspamd_io_dispatcher_t *d,
- void *data,
- size_t len, gboolean delayed, gboolean allocated)
+gboolean
+rspamd_dispatcher_write (rspamd_io_dispatcher_t * d, void *data, size_t len, gboolean delayed, gboolean allocated)
{
- rspamd_buffer_t *newbuf;
+ rspamd_buffer_t *newbuf;
newbuf = memory_pool_alloc (d->pool, sizeof (rspamd_buffer_t));
if (!allocated) {
newbuf->data = fstralloc (d->pool, len);
-
+
/* We need to copy data to temporary internal buffer to avoid using of stack variables */
memcpy (newbuf->data->begin, data, len);
}
newbuf->pos = newbuf->data->begin;
newbuf->data->len = len;
-
+
d->out_buffers = g_list_prepend (d->out_buffers, newbuf);
if (!delayed) {
return TRUE;
}
-void
-rspamd_dispatcher_pause (rspamd_io_dispatcher_t *d)
+void
+rspamd_dispatcher_pause (rspamd_io_dispatcher_t * d)
{
event_del (d->ev);
}
#define DEFAULT_SCORE 10.0
-extern int yylineno;
-extern char *yytext;
+extern int yylineno;
+extern char *yytext;
int
add_memcached_server (struct config_file *cf, char *str)
{
- char *cur_tok, *err_str;
- struct memcached_server *mc;
- struct hostent *hent;
- uint16_t port;
+ char *cur_tok, *err_str;
+ struct memcached_server *mc;
+ struct hostent *hent;
+ uint16_t port;
- if (str == NULL) return 0;
+ if (str == NULL)
+ return 0;
cur_tok = strsep (&str, ":");
- if (cur_tok == NULL || *cur_tok == '\0') return 0;
+ if (cur_tok == NULL || *cur_tok == '\0')
+ return 0;
- if(cf->memcached_servers_num == MAX_MEMCACHED_SERVERS) {
+ if (cf->memcached_servers_num == MAX_MEMCACHED_SERVERS) {
yywarn ("yyparse: maximum number of memcached servers is reached %d", MAX_MEMCACHED_SERVERS);
}
-
+
mc = &cf->memcached_servers[cf->memcached_servers_num];
- if (mc == NULL) return 0;
+ if (mc == NULL)
+ return 0;
/* cur_tok - server name, str - server port */
if (str == NULL) {
port = DEFAULT_MEMCACHED_PORT;
}
else {
- port = (uint16_t)strtoul (str, &err_str, 10);
+ port = (uint16_t) strtoul (str, &err_str, 10);
if (*err_str != '\0') {
return 0;
}
return 0;
}
else {
- memcpy((char *)&mc->addr, hent->h_addr, sizeof(struct in_addr));
+ memcpy ((char *)&mc->addr, hent->h_addr, sizeof (struct in_addr));
}
}
mc->port = port;
int
parse_bind_line (struct config_file *cfg, struct worker_conf *cf, char *str)
{
- char *cur_tok, *err_str;
- struct hostent *hent;
- size_t s;
- char **host;
- int16_t *family, *port;
- struct in_addr *addr;
-
- if (str == NULL) return 0;
+ char *cur_tok, *err_str;
+ struct hostent *hent;
+ size_t s;
+ char **host;
+ int16_t *family, *port;
+ struct in_addr *addr;
+
+ if (str == NULL)
+ return 0;
cur_tok = strsep (&str, ":");
host = &cf->bind_host;
*port = DEFAULT_BIND_PORT;
family = &cf->bind_family;
addr = &cf->bind_addr;
-
+
if (cur_tok[0] == '/' || cur_tok[0] == '.') {
#ifdef HAVE_DIRNAME
/* Try to check path of bind credit */
- struct stat st;
- int fd;
- char *copy = memory_pool_strdup (cfg->cfg_pool, cur_tok);
+ struct stat st;
+ int fd;
+ char *copy = memory_pool_strdup (cfg->cfg_pool, cur_tok);
if (stat (copy, &st) == -1) {
if (errno == ENOENT) {
if ((fd = open (cur_tok, O_RDWR | O_TRUNC | O_CREAT, S_IWUSR | S_IRUSR)) == -1) {
*family = AF_UNIX;
return 1;
- } else {
+ }
+ else {
if (*str != '\0') {
- *port = (uint16_t)strtoul (str, &err_str, 10);
+ *port = (uint16_t) strtoul (str, &err_str, 10);
if (*err_str != '\0') {
yyerror ("parse_bind_line: cannot read numeric value: %s", err_str);
return 0;
if (strcmp (cur_tok, "*") == 0) {
*host = memory_pool_strdup (cfg->cfg_pool, cur_tok);
addr->s_addr = htonl (INADDR_ANY);
- } else if (!inet_aton (cur_tok, addr)) {
+ }
+ else if (!inet_aton (cur_tok, addr)) {
/* Try to call gethostbyname */
hent = gethostbyname (cur_tok);
if (hent == NULL) {
}
else {
*host = memory_pool_strdup (cfg->cfg_pool, cur_tok);
- memcpy((char *)addr, hent->h_addr, sizeof(struct in_addr));
+ memcpy ((char *)addr, hent->h_addr, sizeof (struct in_addr));
s = strlen (cur_tok) + 1;
}
}
memory_pool_delete (cfg->cfg_pool);
}
-char*
+char *
get_module_opt (struct config_file *cfg, char *module_name, char *opt_name)
{
- GList *cur_opt;
- struct module_opt *cur;
-
+ GList *cur_opt;
+ struct module_opt *cur;
+
cur_opt = g_hash_table_lookup (cfg->modules_opts, module_name);
if (cur_opt == NULL) {
return NULL;
}
-
+
while (cur_opt) {
cur = cur_opt->data;
if (strcmp (cur->param, opt_name) == 0) {
size_t
parse_limit (const char *limit)
{
- size_t result = 0;
- char *err_str;
+ size_t result = 0;
+ char *err_str;
- if (!limit || *limit == '\0') return 0;
+ if (!limit || *limit == '\0')
+ return 0;
result = strtoul (limit, &err_str, 10);
unsigned int
parse_seconds (const char *t)
{
- unsigned int result = 0;
- char *err_str;
+ unsigned int result = 0;
+ char *err_str;
- if (!t || *t == '\0') return 0;
+ if (!t || *t == '\0')
+ return 0;
result = strtoul (t, &err_str, 10);
if (*err_str == 's' || *err_str == 'S') {
result *= 1000;
}
- /* Minutes */
- else if (*err_str == 'm' || *err_str == 'M') {
- /* Handle ms correctly */
- if (*(err_str + 1) == 's' || *(err_str + 1) == 'S') {
- result *= 60 * 1000;
- }
- }
- /* Hours */
- else if (*err_str == 'h' || *err_str == 'H') {
- result *= 60 * 60 * 1000;
- }
- /* Days */
- else if (*err_str == 'd' || *err_str == 'D') {
- result *= 24 * 60 * 60 * 1000;
- }
+ /* Minutes */
+ else if (*err_str == 'm' || *err_str == 'M') {
+ /* Handle ms correctly */
+ if (*(err_str + 1) == 's' || *(err_str + 1) == 'S') {
+ result *= 60 * 1000;
+ }
+ }
+ /* Hours */
+ else if (*err_str == 'h' || *err_str == 'H') {
+ result *= 60 * 60 * 1000;
+ }
+ /* Days */
+ else if (*err_str == 'd' || *err_str == 'D') {
+ result *= 24 * 60 * 60 * 1000;
+ }
}
return result;
char
parse_flag (const char *str)
{
- if (!str || !*str) return -1;
+ if (!str || !*str)
+ return -1;
if ((*str == 'Y' || *str == 'y') && *(str + 1) == '\0') {
return 1;
}
- if ((*str == 'Y' || *str == 'y') &&
- (*(str + 1) == 'E' || *(str + 1) == 'e') &&
- (*(str + 2) == 'S' || *(str + 2) == 's') &&
- *(str + 3) == '\0') {
- return 1;
+ if ((*str == 'Y' || *str == 'y') && (*(str + 1) == 'E' || *(str + 1) == 'e') && (*(str + 2) == 'S' || *(str + 2) == 's') && *(str + 3) == '\0') {
+ return 1;
}
if ((*str == 'N' || *str == 'n') && *(str + 1) == '\0') {
return 0;
}
- if ((*str == 'N' || *str == 'n') &&
- (*(str + 1) == 'O' || *(str + 1) == 'o') &&
- *(str + 2) == '\0') {
- return 0;
+ if ((*str == 'N' || *str == 'n') && (*(str + 1) == 'O' || *(str + 1) == 'o') && *(str + 2) == '\0') {
+ return 0;
}
return -1;
* Try to substitute all variables in given string
* Return: newly allocated string with substituted variables (original string may be freed if variables are found)
*/
-char *
+char *
substitute_variable (struct config_file *cfg, char *name, char *str, u_char recursive)
{
- char *var, *new, *v_begin, *v_end, *p, t;
- size_t len;
- gboolean changed = FALSE;
+ char *var, *new, *v_begin, *v_end, *p, t;
+ size_t len;
+ gboolean changed = FALSE;
if (str == NULL) {
yywarn ("substitute_variable: trying to substitute variable in NULL string");
return NULL;
}
-
+
p = str;
while ((v_begin = strstr (p, "${")) != NULL) {
len = strlen (str);
/* Allocate new string */
new = memory_pool_alloc (cfg->cfg_pool, len - strlen (v_begin) + strlen (var) + 3);
- snprintf (new, len - strlen (v_begin) + strlen (var) + 3, "%s(%s)%s",
- str, var, v_end + 1);
+ snprintf (new, len - strlen (v_begin) + strlen (var) + 3, "%s(%s)%s", str, var, v_end + 1);
p = new;
str = new;
changed = TRUE;
}
-
+
if (changed && name != NULL) {
g_hash_table_insert (cfg->variables, name, str);
}
static void
substitute_module_variables (gpointer key, gpointer value, gpointer data)
{
- struct config_file *cfg = (struct config_file *)data;
- GList *cur_opt = (GList *)value;
- struct module_opt *cur;
+ struct config_file *cfg = (struct config_file *)data;
+ GList *cur_opt = (GList *) value;
+ struct module_opt *cur;
while (cur_opt) {
cur = cur_opt->data;
static void
substitute_all_variables (gpointer key, gpointer value, gpointer data)
{
- struct config_file *cfg = (struct config_file *)data;
+ struct config_file *cfg = (struct config_file *)data;
/* Do recursive substitution */
(void)substitute_variable (cfg, (char *)key, (char *)value, 1);
static void
parse_filters_str (struct config_file *cfg, const char *str)
{
- gchar **strvec, **p;
- struct filter *cur;
- int i;
-
+ gchar **strvec, **p;
+ struct filter *cur;
+ int i;
+
if (str == NULL) {
- return;
+ return;
}
strvec = g_strsplit (str, ",", 0);
cur = NULL;
/* Search modules from known C modules */
for (i = 0; i < MODULES_NUM; i++) {
- g_strstrip (*p);
+ g_strstrip (*p);
if (strcasecmp (modules[i].name, *p) == 0) {
cur = memory_pool_alloc (cfg->cfg_pool, sizeof (struct filter));
cur->type = C_FILTER;
msg_debug ("parse_filters_str: found C filter %s", *p);
cur->func_name = memory_pool_strdup (cfg->cfg_pool, *p);
- cur->module = &modules[i];
+ cur->module = &modules[i];
cfg->filters = g_list_prepend (cfg->filters, cur);
break;
- }
+ }
}
if (cur != NULL) {
/* Go to next iteration */
cur->type = PERL_FILTER;
cur->func_name = memory_pool_strdup (cfg->cfg_pool, *p);
cfg->filters = g_list_prepend (cfg->filters, cur);
- p ++;
+ p++;
}
g_strfreev (strvec);
static void
fill_cfg_params (struct config_file *cfg)
{
- struct config_scalar *scalars;
-
- scalars = memory_pool_alloc (cfg->cfg_pool, 10 * sizeof (struct config_scalar));
-
- scalars[0].type = SCALAR_TYPE_STR;
- scalars[0].pointer = &cfg->cfg_name;
- g_hash_table_insert (cfg->cfg_params, "cfg_name", &scalars[0]);
- scalars[1].type = SCALAR_TYPE_STR;
- scalars[1].pointer = &cfg->pid_file;
- g_hash_table_insert (cfg->cfg_params, "pid_file", &scalars[1]);
- scalars[2].type = SCALAR_TYPE_STR;
- scalars[2].pointer = &cfg->temp_dir;
- g_hash_table_insert (cfg->cfg_params, "temp_dir", &scalars[2]);
- scalars[3].type = SCALAR_TYPE_SIZE;
- scalars[3].pointer = &cfg->max_statfile_size;
- g_hash_table_insert (cfg->cfg_params, "max_statfile_size", &scalars[3]);
+ struct config_scalar *scalars;
+
+ scalars = memory_pool_alloc (cfg->cfg_pool, 10 * sizeof (struct config_scalar));
+
+ scalars[0].type = SCALAR_TYPE_STR;
+ scalars[0].pointer = &cfg->cfg_name;
+ g_hash_table_insert (cfg->cfg_params, "cfg_name", &scalars[0]);
+ scalars[1].type = SCALAR_TYPE_STR;
+ scalars[1].pointer = &cfg->pid_file;
+ g_hash_table_insert (cfg->cfg_params, "pid_file", &scalars[1]);
+ scalars[2].type = SCALAR_TYPE_STR;
+ scalars[2].pointer = &cfg->temp_dir;
+ g_hash_table_insert (cfg->cfg_params, "temp_dir", &scalars[2]);
+ scalars[3].type = SCALAR_TYPE_SIZE;
+ scalars[3].pointer = &cfg->max_statfile_size;
+ g_hash_table_insert (cfg->cfg_params, "max_statfile_size", &scalars[3]);
}
void
post_load_config (struct config_file *cfg)
{
- struct timespec ts;
- struct metric *def_metric;
+ struct timespec ts;
+ struct metric *def_metric;
g_hash_table_foreach (cfg->variables, substitute_all_variables, cfg);
g_hash_table_foreach (cfg->modules_opts, substitute_module_variables, cfg);
parse_filters_str (cfg, cfg->filters_str);
- fill_cfg_params (cfg);
+ fill_cfg_params (cfg);
#ifdef HAVE_CLOCK_PROCESS_CPUTIME_ID
clock_getres (CLOCK_PROCESS_CPUTIME_ID, &ts);
void
parse_err (const char *fmt, ...)
{
- va_list aq;
- char logbuf[BUFSIZ], readbuf[32];
- int r;
-
+ va_list aq;
+ char logbuf[BUFSIZ], readbuf[32];
+ int r;
+
va_start (aq, fmt);
g_strlcpy (readbuf, yytext, sizeof (readbuf));
void
parse_warn (const char *fmt, ...)
{
- va_list aq;
- char logbuf[BUFSIZ], readbuf[32];
- int r;
-
+ va_list aq;
+ char logbuf[BUFSIZ], readbuf[32];
+ int r;
+
va_start (aq, fmt);
g_strlcpy (readbuf, yytext, sizeof (readbuf));
void
unescape_quotes (char *line)
{
- char *c = line, *t;
+ char *c = line, *t;
while (*c) {
if (*c == '\\' && *(c + 1) == '"') {
t = c;
while (*t) {
*t = *(t + 1);
- t ++;
+ t++;
}
}
- c ++;
+ c++;
}
}
-GList *
-parse_comma_list (memory_pool_t *pool, char *line)
+GList *
+parse_comma_list (memory_pool_t * pool, char *line)
{
- GList *res = NULL;
- char *c, *p, *str;
-
+ GList *res = NULL;
+ char *c, *p, *str;
+
c = line;
p = c;
c = p;
continue;
}
- p ++;
+ p++;
}
if (res != NULL) {
- memory_pool_add_destructor (pool, (pool_destruct_func)g_list_free, res);
+ memory_pool_add_destructor (pool, (pool_destruct_func) g_list_free, res);
}
return res;
}
-struct classifier_config *
+struct classifier_config *
check_classifier_cfg (struct config_file *cfg, struct classifier_config *c)
{
if (c == NULL) {
}
if (c->opts == NULL) {
c->opts = g_hash_table_new (g_str_hash, g_str_equal);
- memory_pool_add_destructor (cfg->cfg_pool, (pool_destruct_func)g_hash_table_destroy, c->opts);
+ memory_pool_add_destructor (cfg->cfg_pool, (pool_destruct_func) g_hash_table_destroy, c->opts);
}
return c;
#include <sys/types.h>
#include "classifiers.h"
-struct classifier classifiers[] = {
+struct classifier classifiers[] = {
{
- .name = "winnow",
- .init_func = winnow_init,
- .classify_func = winnow_classify,
- .learn_func = winnow_learn,
- },
+ .name = "winnow",
+ .init_func = winnow_init,
+ .classify_func = winnow_classify,
+ .learn_func = winnow_learn,
+ },
};
-struct classifier*
+struct classifier *
get_classifier (char *name)
{
- int i;
+ int i;
- for (i = 0; i < sizeof (classifiers) / sizeof (classifiers[0]); i ++) {
+ for (i = 0; i < sizeof (classifiers) / sizeof (classifiers[0]); i++) {
if (strcmp (classifiers[i].name, name) == 0) {
return &classifiers[i];
}
#define WINNOW_DEMOTION 0.83
struct winnow_callback_data {
- statfile_pool_t *pool;
- struct classifier_ctx *ctx;
- stat_file_t *file;
- double sum;
- int count;
- int in_class;
- time_t now;
+ statfile_pool_t *pool;
+ struct classifier_ctx *ctx;
+ stat_file_t *file;
+ double sum;
+ int count;
+ int in_class;
+ time_t now;
};
-static gboolean
-classify_callback (gpointer key, gpointer value, gpointer data)
+static gboolean
+classify_callback (gpointer key, gpointer value, gpointer data)
{
- token_node_t *node = key;
- struct winnow_callback_data *cd = data;
- float v;
-
+ token_node_t *node = key;
+ struct winnow_callback_data *cd = data;
+ float v;
+
/* Consider that not found blocks have value 1 */
if ((v = statfile_pool_get_block (cd->pool, cd->file, node->h1, node->h2, cd->now)) < 0.00001) {
cd->sum += 1;
}
else {
cd->sum += v;
- cd->in_class ++;
+ cd->in_class++;
}
- cd->count ++;
+ cd->count++;
return FALSE;
}
-static gboolean
-learn_callback (gpointer key, gpointer value, gpointer data)
+static gboolean
+learn_callback (gpointer key, gpointer value, gpointer data)
{
- token_node_t *node = key;
- struct winnow_callback_data *cd = data;
- float v, c;
+ token_node_t *node = key;
+ struct winnow_callback_data *cd = data;
+ float v, c;
c = (cd->in_class) ? WINNOW_PROMOTION : WINNOW_DEMOTION;
statfile_pool_set_block (cd->pool, cd->file, node->h1, node->h2, cd->now, v * c);
}
- cd->count ++;
-
+ cd->count++;
+
return FALSE;
}
-struct classifier_ctx*
-winnow_init (memory_pool_t *pool, struct classifier_config *cfg)
+struct classifier_ctx *
+winnow_init (memory_pool_t * pool, struct classifier_config *cfg)
{
- struct classifier_ctx *ctx = memory_pool_alloc (pool, sizeof (struct classifier_ctx));
+ struct classifier_ctx *ctx = memory_pool_alloc (pool, sizeof (struct classifier_ctx));
ctx->pool = pool;
ctx->cfg = cfg;
return ctx;
}
-void
-winnow_classify (struct classifier_ctx *ctx, statfile_pool_t *pool, GTree *input, struct worker_task *task)
+
+void
+winnow_classify (struct classifier_ctx *ctx, statfile_pool_t * pool, GTree * input, struct worker_task *task)
{
- struct winnow_callback_data data;
- double *res = memory_pool_alloc (ctx->pool, sizeof (double));
- double max = 0;
- GList *cur;
- struct statfile *st, *sel = NULL;
+ struct winnow_callback_data data;
+ double *res = memory_pool_alloc (ctx->pool, sizeof (double));
+ double max = 0;
+ GList *cur;
+ struct statfile *st, *sel = NULL;
g_assert (pool != NULL);
g_assert (ctx != NULL);
data.count = 0;
data.now = time (NULL);
data.ctx = ctx;
-
+
cur = ctx->cfg->statfiles;
while (cur) {
st = cur->data;
g_tree_foreach (input, classify_callback, &data);
statfile_pool_unlock_file (pool, data.file);
}
-
+
if (data.count != 0) {
*res = (data.sum / data.count);
}
}
cur = g_list_next (cur);
}
-
+
if (sel != NULL) {
insert_result (task, ctx->cfg->metric, sel->symbol, 1, NULL);
}
}
void
-winnow_learn (struct classifier_ctx *ctx, statfile_pool_t *pool, char *symbol, GTree *input, int in_class)
+winnow_learn (struct classifier_ctx *ctx, statfile_pool_t * pool, char *symbol, GTree * input, int in_class)
{
- struct winnow_callback_data data = {
- .file = NULL,
+ struct winnow_callback_data data = {
+ .file = NULL,
.sum = 0,
.count = 0,
};
- GList *cur;
- struct statfile *st;
-
+ GList *cur;
+ struct statfile *st;
+
g_assert (pool != NULL);
g_assert (ctx != NULL);
data.in_class = in_class;
data.now = time (NULL);
data.ctx = ctx;
-
+
cur = g_list_first (ctx->cfg->statfiles);
while (cur) {
st = cur->data;
if (strcmp (symbol, st->symbol) == 0) {
if ((data.file = statfile_pool_open (pool, st->path)) == NULL) {
/* Try to create statfile */
- if (statfile_pool_create (pool,
- st->path, st->size / sizeof (struct stat_file_block)) == -1) {
+ if (statfile_pool_create (pool, st->path, st->size / sizeof (struct stat_file_block)) == -1) {
msg_err ("winnow_learn: cannot create statfile %s", st->path);
return;
}
};
struct controller_command {
- char *command;
- gboolean privilleged;
- enum command_type type;
+ char *command;
+ gboolean privilleged;
+ enum command_type type;
};
struct custom_controller_command {
- const char *command;
- gboolean privilleged;
- gboolean require_message;
- controller_func_t handler;
+ const char *command;
+ gboolean privilleged;
+ gboolean require_message;
+ controller_func_t handler;
};
static struct controller_command commands[] = {
{"counters", FALSE, COMMAND_COUNTERS},
};
-static GList *custom_commands = NULL;
+static GList *custom_commands = NULL;
-static GCompletion *comp;
-static time_t start_time;
+static GCompletion *comp;
+static time_t start_time;
-static char greetingbuf[1024];
-extern rspamd_hash_t *counters;
+static char greetingbuf[1024];
+extern rspamd_hash_t *counters;
-static gboolean controller_write_socket (void *arg);
+static gboolean controller_write_socket (void *arg);
-static
-void sig_handler (int signo)
+static
+ void
+sig_handler (int signo)
{
switch (signo) {
- case SIGINT:
- case SIGTERM:
- _exit (1);
- break;
+ case SIGINT:
+ case SIGTERM:
+ _exit (1);
+ break;
}
}
static void
sigusr_handler (int fd, short what, void *arg)
{
- struct rspamd_worker *worker = (struct rspamd_worker *)arg;
+ struct rspamd_worker *worker = (struct rspamd_worker *)arg;
/* Do not accept new connections, preparing to end worker's process */
- struct timeval tv;
+ struct timeval tv;
tv.tv_sec = 2;
tv.tv_usec = 0;
event_del (&worker->sig_ev);
return;
}
-static gchar*
+static gchar *
completion_func (gpointer elem)
{
- struct controller_command *cmd = (struct controller_command *)elem;
+ struct controller_command *cmd = (struct controller_command *)elem;
return cmd->command;
}
static void
free_session (void *ud)
{
- GList *part;
- struct mime_part *p;
- struct controller_session *session = ud;
-
+ GList *part;
+ struct mime_part *p;
+ struct controller_session *session = ud;
+
msg_debug ("free_session: freeing session %p", session);
-
+
while ((part = g_list_first (session->parts))) {
session->parts = g_list_remove_link (session->parts, part);
p = (struct mime_part *)part->data;
}
static int
-check_auth (struct controller_command *cmd, struct controller_session *session)
+check_auth (struct controller_command *cmd, struct controller_session *session)
{
- char out_buf[128];
- int r;
+ char out_buf[128];
+ int r;
if (cmd->privilleged && !session->authorized) {
r = snprintf (out_buf, sizeof (out_buf), "not authorized" CRLF);
static void
counter_write_callback (gpointer key, gpointer value, void *data)
{
- struct controller_session *session = data;
- struct counter_data *cd = value;
- char *name = key;
- char out_buf[128];
- int r;
+ struct controller_session *session = data;
+ struct counter_data *cd = value;
+ char *name = key;
+ char out_buf[128];
+ int r;
r = snprintf (out_buf, sizeof (out_buf), "%s: %llu" CRLF, name, (unsigned long long int)cd->value);
rspamd_dispatcher_write (session->dispatcher, out_buf, r, TRUE, FALSE);
static void
process_command (struct controller_command *cmd, char **cmd_args, struct controller_session *session)
{
- char out_buf[BUFSIZ], *arg, *err_str;
- int r = 0, days, hours, minutes;
- time_t uptime;
- unsigned long size = 0;
- struct classifier_config *cl;
- memory_pool_stat_t mem_st;
- char *password = g_hash_table_lookup (session->worker->cf->params, "password");
+ char out_buf[BUFSIZ], *arg, *err_str;
+ int r = 0, days, hours, minutes;
+ time_t uptime;
+ unsigned long size = 0;
+ struct classifier_config *cl;
+ memory_pool_stat_t mem_st;
+ char *password = g_hash_table_lookup (session->worker->cf->params, "password");
switch (cmd->type) {
- case COMMAND_PASSWORD:
- arg = *cmd_args;
- if (!arg || *arg == '\0') {
- msg_debug ("process_command: empty password passed");
- r = snprintf (out_buf, sizeof (out_buf), "password command requires one argument" CRLF);
- rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE);
- return;
+ case COMMAND_PASSWORD:
+ arg = *cmd_args;
+ if (!arg || *arg == '\0') {
+ msg_debug ("process_command: empty password passed");
+ r = snprintf (out_buf, sizeof (out_buf), "password command requires one argument" CRLF);
+ rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE);
+ return;
+ }
+ if (password == NULL) {
+ r = snprintf (out_buf, sizeof (out_buf), "password command disabled in config, authorized access unallowed" CRLF);
+ rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE);
+ return;
+ }
+ if (strncmp (arg, password, strlen (arg)) == 0) {
+ session->authorized = 1;
+ r = snprintf (out_buf, sizeof (out_buf), "password accepted" CRLF);
+ rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE);
+ }
+ else {
+ session->authorized = 0;
+ r = snprintf (out_buf, sizeof (out_buf), "password NOT accepted" CRLF);
+ rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE);
+ }
+ break;
+ case COMMAND_QUIT:
+ session->state = STATE_QUIT;
+ break;
+ case COMMAND_RELOAD:
+ if (check_auth (cmd, session)) {
+ r = snprintf (out_buf, sizeof (out_buf), "reload request sent" CRLF);
+ rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE);
+ kill (getppid (), SIGHUP);
+ }
+ break;
+ case COMMAND_STAT:
+ if (check_auth (cmd, session)) {
+ memory_pool_stat (&mem_st);
+ r = snprintf (out_buf, sizeof (out_buf), "Messages scanned: %u" CRLF, session->worker->srv->stat->messages_scanned);
+ r += snprintf (out_buf + r, sizeof (out_buf) - r, "Messages learned: %u" CRLF, session->worker->srv->stat->messages_learned);
+ r += snprintf (out_buf + r, sizeof (out_buf) - r, "Connections count: %u" CRLF, session->worker->srv->stat->connections_count);
+ r += snprintf (out_buf + r, sizeof (out_buf) - r, "Control connections count: %u" CRLF, session->worker->srv->stat->control_connections_count);
+ r += snprintf (out_buf + r, sizeof (out_buf) - r, "Pools allocated: %ld" CRLF, (long int)mem_st.pools_allocated);
+ r += snprintf (out_buf + r, sizeof (out_buf) - r, "Pools freed: %ld" CRLF, (long int)mem_st.pools_freed);
+ r += snprintf (out_buf + r, sizeof (out_buf) - r, "Bytes allocated: %ld" CRLF, (long int)mem_st.bytes_allocated);
+ r += snprintf (out_buf + r, sizeof (out_buf) - r, "Memory chunks allocated: %ld" CRLF, (long int)mem_st.chunks_allocated);
+ r += snprintf (out_buf + r, sizeof (out_buf) - r, "Shared chunks allocated: %ld" CRLF, (long int)mem_st.shared_chunks_allocated);
+ r += snprintf (out_buf + r, sizeof (out_buf) - r, "Chunks freed: %ld" CRLF, (long int)mem_st.chunks_freed);
+ r += snprintf (out_buf + r, sizeof (out_buf) - r, "Oversized chunks: %ld" CRLF, (long int)mem_st.oversized_chunks);
+ rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE);
+ }
+ break;
+ case COMMAND_SHUTDOWN:
+ if (check_auth (cmd, session)) {
+ r = snprintf (out_buf, sizeof (out_buf), "shutdown request sent" CRLF);
+ rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE);
+ kill (getppid (), SIGTERM);
+ }
+ break;
+ case COMMAND_UPTIME:
+ if (check_auth (cmd, session)) {
+ uptime = time (NULL) - start_time;
+ /* If uptime more than 2 hours, print as a number of days. */
+ if (uptime >= 2 * 3600) {
+ days = uptime / 86400;
+ hours = uptime / 3600 - days * 3600;
+ minutes = uptime / 60 - hours * 60 - days * 3600;
+ r = snprintf (out_buf, sizeof (out_buf), "%d day%s %d hour%s %d minute%s" CRLF, days, days > 1 ? "s" : " ", hours, hours > 1 ? "s" : " ", minutes, minutes > 1 ? "s" : " ");
}
- if (password == NULL) {
- r = snprintf (out_buf, sizeof (out_buf), "password command disabled in config, authorized access unallowed" CRLF);
- rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE);
- return;
- }
- if (strncmp (arg, password, strlen (arg)) == 0) {
- session->authorized = 1;
- r = snprintf (out_buf, sizeof (out_buf), "password accepted" CRLF);
- rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE);
+ /* If uptime is less than 1 minute print only seconds */
+ else if (uptime / 60 == 0) {
+ r = snprintf (out_buf, sizeof (out_buf), "%d second%s" CRLF, (int)uptime, (int)uptime > 1 ? "s" : " ");
}
+ /* Else print the minutes and seconds. */
else {
- session->authorized = 0;
- r = snprintf (out_buf, sizeof (out_buf), "password NOT accepted" CRLF);
- rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE);
+ hours = uptime / 3600;
+ minutes = uptime / 60 - hours * 3600;
+ uptime -= hours * 3600 + minutes * 60;
+ r = snprintf (out_buf, sizeof (out_buf), "%d hour%s %d minite%s %d second%s" CRLF, hours, hours > 1 ? "s" : " ", minutes, minutes > 1 ? "s" : " ", (int)uptime, uptime > 1 ? "s" : " ");
}
- break;
- case COMMAND_QUIT:
- session->state = STATE_QUIT;
- break;
- case COMMAND_RELOAD:
- if (check_auth (cmd, session)) {
- r = snprintf (out_buf, sizeof (out_buf), "reload request sent" CRLF);
+ rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE);
+ }
+ break;
+ case COMMAND_LEARN:
+ if (check_auth (cmd, session)) {
+ arg = *cmd_args;
+ if (!arg || *arg == '\0') {
+ msg_debug ("process_command: no statfile specified in learn command");
+ r = snprintf (out_buf, sizeof (out_buf), "learn command requires at least two arguments: stat filename and its size" CRLF);
rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE);
- kill (getppid (), SIGHUP);
+ return;
}
- break;
- case COMMAND_STAT:
- if (check_auth (cmd, session)) {
- memory_pool_stat (&mem_st);
- r = snprintf (out_buf, sizeof (out_buf), "Messages scanned: %u" CRLF,
- session->worker->srv->stat->messages_scanned);
- r += snprintf (out_buf + r, sizeof (out_buf) - r , "Messages learned: %u" CRLF,
- session->worker->srv->stat->messages_learned);
- r += snprintf (out_buf + r, sizeof (out_buf) - r, "Connections count: %u" CRLF,
- session->worker->srv->stat->connections_count);
- r += snprintf (out_buf + r, sizeof (out_buf) - r, "Control connections count: %u" CRLF,
- session->worker->srv->stat->control_connections_count);
- r += snprintf (out_buf + r, sizeof (out_buf) - r, "Pools allocated: %ld" CRLF,
- (long int)mem_st.pools_allocated);
- r += snprintf (out_buf + r, sizeof (out_buf) - r, "Pools freed: %ld" CRLF,
- (long int)mem_st.pools_freed);
- r += snprintf (out_buf + r, sizeof (out_buf) - r, "Bytes allocated: %ld" CRLF,
- (long int)mem_st.bytes_allocated);
- r += snprintf (out_buf + r, sizeof (out_buf) - r, "Memory chunks allocated: %ld" CRLF,
- (long int)mem_st.chunks_allocated);
- r += snprintf (out_buf + r, sizeof (out_buf) - r, "Shared chunks allocated: %ld" CRLF,
- (long int)mem_st.shared_chunks_allocated);
- r += snprintf (out_buf + r, sizeof (out_buf) - r, "Chunks freed: %ld" CRLF,
- (long int)mem_st.chunks_freed);
- r += snprintf (out_buf + r, sizeof (out_buf) - r, "Oversized chunks: %ld" CRLF,
- (long int)mem_st.oversized_chunks);
+ arg = *(cmd_args + 1);
+ if (arg == NULL || *arg == '\0') {
+ msg_debug ("process_command: no statfile size specified in learn command");
+ r = snprintf (out_buf, sizeof (out_buf), "learn command requires at least two arguments: stat filename and its size" CRLF);
rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE);
+ return;
}
- break;
- case COMMAND_SHUTDOWN:
- if (check_auth (cmd, session)) {
- r = snprintf (out_buf, sizeof (out_buf), "shutdown request sent" CRLF);
+ size = strtoul (arg, &err_str, 10);
+ if (err_str && *err_str != '\0') {
+ msg_debug ("process_command: statfile size is invalid: %s", arg);
+ r = snprintf (out_buf, sizeof (out_buf), "learn size is invalid" CRLF);
rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE);
- kill (getppid (), SIGTERM);
+ return;
}
- break;
- case COMMAND_UPTIME:
- if (check_auth (cmd, session)) {
- uptime = time (NULL) - start_time;
- /* If uptime more than 2 hours, print as a number of days. */
- if (uptime >= 2 * 3600) {
- days = uptime / 86400;
- hours = uptime / 3600 - days * 3600;
- minutes = uptime / 60 - hours * 60 - days * 3600;
- r = snprintf (out_buf, sizeof (out_buf), "%d day%s %d hour%s %d minute%s" CRLF,
- days, days > 1 ? "s" : " ",
- hours, hours > 1 ? "s" : " ",
- minutes, minutes > 1 ? "s" : " ");
- }
- /* If uptime is less than 1 minute print only seconds */
- else if (uptime / 60 == 0) {
- r = snprintf (out_buf, sizeof (out_buf), "%d second%s" CRLF, (int)uptime, (int)uptime > 1 ? "s" : " ");
- }
- /* Else print the minutes and seconds. */
- else {
- hours = uptime / 3600;
- minutes = uptime / 60 - hours * 3600;
- uptime -= hours * 3600 + minutes * 60;
- r = snprintf (out_buf, sizeof (out_buf), "%d hour%s %d minite%s %d second%s" CRLF,
- hours, hours > 1 ? "s" : " ",
- minutes, minutes > 1 ? "s" : " ",
- (int)uptime, uptime > 1 ? "s" : " ");
- }
+
+ session->learn_symbol = memory_pool_strdup (session->session_pool, *cmd_args);
+ cl = g_hash_table_lookup (session->cfg->classifiers_symbols, *cmd_args);
+ if (cl == NULL) {
+ r = snprintf (out_buf, sizeof (out_buf), "statfile %s is not defined" CRLF, *cmd_args);
rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE);
- }
- break;
- case COMMAND_LEARN:
- if (check_auth (cmd, session)) {
- arg = *cmd_args;
- if (!arg || *arg == '\0') {
- msg_debug ("process_command: no statfile specified in learn command");
- r = snprintf (out_buf, sizeof (out_buf), "learn command requires at least two arguments: stat filename and its size" CRLF);
- rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE);
- return;
- }
- arg = *(cmd_args + 1);
- if (arg == NULL || *arg == '\0') {
- msg_debug ("process_command: no statfile size specified in learn command");
- r = snprintf (out_buf, sizeof (out_buf), "learn command requires at least two arguments: stat filename and its size" CRLF);
- rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE);
- return;
- }
- size = strtoul (arg, &err_str, 10);
- if (err_str && *err_str != '\0') {
- msg_debug ("process_command: statfile size is invalid: %s", arg);
- r = snprintf (out_buf, sizeof (out_buf), "learn size is invalid" CRLF);
- rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE);
- return;
- }
+ return;
- session->learn_symbol = memory_pool_strdup (session->session_pool, *cmd_args);
- cl = g_hash_table_lookup (session->cfg->classifiers_symbols, *cmd_args);
- if (cl == NULL) {
- r = snprintf (out_buf, sizeof (out_buf), "statfile %s is not defined" CRLF, *cmd_args);
- rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE);
- return;
+ }
+ session->learn_classifier = cl;
- }
- session->learn_classifier = cl;
-
- /* By default learn positive */
- session->in_class = 1;
- /* Get all arguments */
- while (*cmd_args++) {
- arg = *cmd_args;
- if (arg && *arg == '-') {
- switch (*(arg + 1)) {
- case 'r':
- arg = *(cmd_args + 1);
- if (!arg || *arg == '\0') {
- r = snprintf (out_buf, sizeof (out_buf), "recipient is not defined" CRLF);
- rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE);
- return;
- }
- session->learn_rcpt = memory_pool_strdup (session->session_pool, arg);
- break;
- case 'f':
- arg = *(cmd_args + 1);
- if (!arg || *arg == '\0') {
- r = snprintf (out_buf, sizeof (out_buf), "from is not defined" CRLF);
- rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE);
- return;
- }
- session->learn_from = memory_pool_strdup (session->session_pool, arg);
- break;
- case 'n':
- session->in_class = 0;
- break;
- default:
- r = snprintf (out_buf, sizeof (out_buf), "tokenizer is not defined" CRLF);
- rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE);
- return;
+ /* By default learn positive */
+ session->in_class = 1;
+ /* Get all arguments */
+ while (*cmd_args++) {
+ arg = *cmd_args;
+ if (arg && *arg == '-') {
+ switch (*(arg + 1)) {
+ case 'r':
+ arg = *(cmd_args + 1);
+ if (!arg || *arg == '\0') {
+ r = snprintf (out_buf, sizeof (out_buf), "recipient is not defined" CRLF);
+ rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE);
+ return;
}
+ session->learn_rcpt = memory_pool_strdup (session->session_pool, arg);
+ break;
+ case 'f':
+ arg = *(cmd_args + 1);
+ if (!arg || *arg == '\0') {
+ r = snprintf (out_buf, sizeof (out_buf), "from is not defined" CRLF);
+ rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE);
+ return;
+ }
+ session->learn_from = memory_pool_strdup (session->session_pool, arg);
+ break;
+ case 'n':
+ session->in_class = 0;
+ break;
+ default:
+ r = snprintf (out_buf, sizeof (out_buf), "tokenizer is not defined" CRLF);
+ rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE);
+ return;
}
}
- rspamd_set_dispatcher_policy (session->dispatcher, BUFFER_CHARACTER, size);
- session->state = STATE_LEARN;
}
- break;
- case COMMAND_HELP:
- r = snprintf (out_buf, sizeof (out_buf),
- "Rspamd CLI commands (* - privilleged command):" CRLF
- " help - this help message" CRLF
- "(*) learn <statfile> <size> [-r recipient], [-f from] [-n] - learn message to specified statfile" CRLF
- " quit - quit CLI session" CRLF
- "(*) reload - reload rspamd" CRLF
- "(*) shutdown - shutdown rspamd" CRLF
- " stat - show different rspamd stat" CRLF
- " counters - show rspamd counters" CRLF
- " uptime - rspamd uptime" CRLF);
- rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE);
- break;
- case COMMAND_COUNTERS:
- rspamd_hash_foreach (counters, counter_write_callback, session);
- break;
+ rspamd_set_dispatcher_policy (session->dispatcher, BUFFER_CHARACTER, size);
+ session->state = STATE_LEARN;
+ }
+ break;
+ case COMMAND_HELP:
+ r = snprintf (out_buf, sizeof (out_buf),
+ "Rspamd CLI commands (* - privilleged command):" CRLF
+ " help - this help message" CRLF
+ "(*) learn <statfile> <size> [-r recipient], [-f from] [-n] - learn message to specified statfile" CRLF
+ " quit - quit CLI session" CRLF
+ "(*) reload - reload rspamd" CRLF
+ "(*) shutdown - shutdown rspamd" CRLF " stat - show different rspamd stat" CRLF " counters - show rspamd counters" CRLF " uptime - rspamd uptime" CRLF);
+ rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE);
+ break;
+ case COMMAND_COUNTERS:
+ rspamd_hash_foreach (counters, counter_write_callback, session);
+ break;
}
}
-static gboolean
+static gboolean
process_custom_command (char *line, char **cmd_args, struct controller_session *session)
{
- GList *cur;
+ GList *cur;
struct custom_controller_command *cmd;
cur = custom_commands;
return FALSE;
}
-static gboolean
-controller_read_socket (f_str_t *in, void *arg)
+static gboolean
+controller_read_socket (f_str_t * in, void *arg)
{
- struct controller_session *session = (struct controller_session *)arg;
- struct classifier_ctx *cls_ctx;
- int len, i, r;
- char *s, **params, *cmd, out_buf[128];
- struct worker_task *task;
- struct mime_text_part *part;
- GList *comp_list, *cur = NULL;
- GTree *tokens = NULL;
- f_str_t c;
+ struct controller_session *session = (struct controller_session *)arg;
+ struct classifier_ctx *cls_ctx;
+ int len, i, r;
+ char *s, **params, *cmd, out_buf[128];
+ struct worker_task *task;
+ struct mime_text_part *part;
+ GList *comp_list, *cur = NULL;
+ GTree *tokens = NULL;
+ f_str_t c;
switch (session->state) {
- case STATE_COMMAND:
- s = fstrcstr (in, session->session_pool);
- params = g_strsplit (s, " ", -1);
-
- memory_pool_add_destructor (session->session_pool, (pool_destruct_func)g_strfreev, params);
-
- len = g_strv_length (params);
- if (len > 0) {
- cmd = g_strstrip (params[0]);
- comp_list = g_completion_complete (comp, cmd, NULL);
- switch (g_list_length (comp_list)) {
- case 1:
- process_command ((struct controller_command *)comp_list->data, ¶ms[1], session);
- break;
- case 0:
- if (!process_custom_command (cmd, ¶ms[1], session)) {
- msg_debug ("Unknown command: '%s'", cmd);
- i = snprintf (out_buf, sizeof (out_buf), "Unknown command" CRLF);
- if (!rspamd_dispatcher_write (session->dispatcher, out_buf, i, FALSE, FALSE)) {
- return FALSE;
- }
- }
- break;
- default:
- msg_debug ("Ambigious command: '%s'", cmd);
- i = snprintf (out_buf, sizeof (out_buf), "Ambigious command" CRLF);
- if (!rspamd_dispatcher_write (session->dispatcher, out_buf, i, FALSE, FALSE)) {
- return FALSE;
- }
- break;
+ case STATE_COMMAND:
+ s = fstrcstr (in, session->session_pool);
+ params = g_strsplit (s, " ", -1);
+
+ memory_pool_add_destructor (session->session_pool, (pool_destruct_func) g_strfreev, params);
+
+ len = g_strv_length (params);
+ if (len > 0) {
+ cmd = g_strstrip (params[0]);
+ comp_list = g_completion_complete (comp, cmd, NULL);
+ switch (g_list_length (comp_list)) {
+ case 1:
+ process_command ((struct controller_command *)comp_list->data, ¶ms[1], session);
+ break;
+ case 0:
+ if (!process_custom_command (cmd, ¶ms[1], session)) {
+ msg_debug ("Unknown command: '%s'", cmd);
+ i = snprintf (out_buf, sizeof (out_buf), "Unknown command" CRLF);
+ if (!rspamd_dispatcher_write (session->dispatcher, out_buf, i, FALSE, FALSE)) {
+ return FALSE;
+ }
}
+ break;
+ default:
+ msg_debug ("Ambigious command: '%s'", cmd);
+ i = snprintf (out_buf, sizeof (out_buf), "Ambigious command" CRLF);
+ if (!rspamd_dispatcher_write (session->dispatcher, out_buf, i, FALSE, FALSE)) {
+ return FALSE;
+ }
+ break;
}
- if (session->state == STATE_COMMAND) {
- session->state = STATE_REPLY;
- }
- if (session->state != STATE_LEARN && session->state != STATE_OTHER) {
- if (!rspamd_dispatcher_write (session->dispatcher, END, sizeof (END) - 1, FALSE, TRUE)) {
- return FALSE;
- }
+ }
+ if (session->state == STATE_COMMAND) {
+ session->state = STATE_REPLY;
+ }
+ if (session->state != STATE_LEARN && session->state != STATE_OTHER) {
+ if (!rspamd_dispatcher_write (session->dispatcher, END, sizeof (END) - 1, FALSE, TRUE)) {
+ return FALSE;
}
+ }
- break;
- case STATE_LEARN:
- session->learn_buf = in;
- task = construct_task (session->worker);
-
- task->msg = memory_pool_alloc (task->task_pool, sizeof (f_str_t));
- task->msg->begin = in->begin;
- task->msg->len = in->len;
-
- r = process_message (task);
- if (r == -1) {
- msg_warn ("read_socket: processing of message failed");
- free_task (task, FALSE);
- session->state = STATE_REPLY;
- r = snprintf (out_buf, sizeof (out_buf), "cannot process message" CRLF);
- rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE);
- return FALSE;
- }
- cur = g_list_first (task->text_parts);
- while (cur) {
- part = cur->data;
- if (part->is_empty) {
- cur = g_list_next (cur);
- continue;
- }
- c.begin = part->content->data;
- c.len = part->content->len;
+ break;
+ case STATE_LEARN:
+ session->learn_buf = in;
+ task = construct_task (session->worker);
- if (!session->learn_classifier->tokenizer->tokenize_func (session->learn_classifier->tokenizer,
- session->session_pool, &c, &tokens)) {
- i = snprintf (out_buf, sizeof (out_buf), "learn fail, tokenizer error" CRLF);
- free_task (task, FALSE);
- if (!rspamd_dispatcher_write (session->dispatcher, out_buf, i, FALSE, FALSE)) {
- return FALSE;
- }
- session->state = STATE_REPLY;
- return TRUE;
- }
+ task->msg = memory_pool_alloc (task->task_pool, sizeof (f_str_t));
+ task->msg->begin = in->begin;
+ task->msg->len = in->len;
+
+ r = process_message (task);
+ if (r == -1) {
+ msg_warn ("read_socket: processing of message failed");
+ free_task (task, FALSE);
+ session->state = STATE_REPLY;
+ r = snprintf (out_buf, sizeof (out_buf), "cannot process message" CRLF);
+ rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE);
+ return FALSE;
+ }
+ cur = g_list_first (task->text_parts);
+ while (cur) {
+ part = cur->data;
+ if (part->is_empty) {
cur = g_list_next (cur);
+ continue;
}
- cls_ctx = session->learn_classifier->classifier->init_func (session->session_pool, session->learn_classifier);
- session->learn_classifier->classifier->learn_func (cls_ctx, session->worker->srv->statfile_pool,
- session->learn_symbol, tokens, session->in_class);
- session->worker->srv->stat->messages_learned ++;
+ c.begin = part->content->data;
+ c.len = part->content->len;
+
+ if (!session->learn_classifier->tokenizer->tokenize_func (session->learn_classifier->tokenizer, session->session_pool, &c, &tokens)) {
+ i = snprintf (out_buf, sizeof (out_buf), "learn fail, tokenizer error" CRLF);
+ free_task (task, FALSE);
+ if (!rspamd_dispatcher_write (session->dispatcher, out_buf, i, FALSE, FALSE)) {
+ return FALSE;
+ }
+ session->state = STATE_REPLY;
+ return TRUE;
+ }
+ cur = g_list_next (cur);
+ }
+ cls_ctx = session->learn_classifier->classifier->init_func (session->session_pool, session->learn_classifier);
+ session->learn_classifier->classifier->learn_func (cls_ctx, session->worker->srv->statfile_pool, session->learn_symbol, tokens, session->in_class);
+ session->worker->srv->stat->messages_learned++;
- free_task (task, FALSE);
- i = snprintf (out_buf, sizeof (out_buf), "learn ok" CRLF);
- if (!rspamd_dispatcher_write (session->dispatcher, out_buf, i, FALSE, FALSE)) {
- return FALSE;
- }
+ free_task (task, FALSE);
+ i = snprintf (out_buf, sizeof (out_buf), "learn ok" CRLF);
+ if (!rspamd_dispatcher_write (session->dispatcher, out_buf, i, FALSE, FALSE)) {
+ return FALSE;
+ }
- session->state = STATE_REPLY;
- break;
- case STATE_OTHER:
- if (session->other_handler) {
- session->other_handler (session, in);
- }
- session->state = STATE_REPLY;
- break;
- case STATE_WAIT:
- rspamd_dispatcher_pause (session->dispatcher);
- break;
- default:
- msg_debug ("controller_read_socket: unknown state while reading %d", session->state);
- break;
+ session->state = STATE_REPLY;
+ break;
+ case STATE_OTHER:
+ if (session->other_handler) {
+ session->other_handler (session, in);
+ }
+ session->state = STATE_REPLY;
+ break;
+ case STATE_WAIT:
+ rspamd_dispatcher_pause (session->dispatcher);
+ break;
+ default:
+ msg_debug ("controller_read_socket: unknown state while reading %d", session->state);
+ break;
}
- if (session->state == STATE_REPLY || session->state == STATE_QUIT) {
- (void)controller_write_socket (session);
- }
+ if (session->state == STATE_REPLY || session->state == STATE_QUIT) {
+ (void)controller_write_socket (session);
+ }
- return TRUE;
+ return TRUE;
}
-static gboolean
+static gboolean
controller_write_socket (void *arg)
{
- struct controller_session *session = (struct controller_session *)arg;
-
+ struct controller_session *session = (struct controller_session *)arg;
+
if (session->state == STATE_QUIT) {
/* Free buffers */
- destroy_session (session->s);
- return FALSE;
+ destroy_session (session->s);
+ return FALSE;
}
else if (session->state == STATE_REPLY) {
session->state = STATE_COMMAND;
rspamd_set_dispatcher_policy (session->dispatcher, BUFFER_LINE, BUFSIZ);
}
- return TRUE;
+ return TRUE;
}
static void
-controller_err_socket (GError *err, void *arg)
+controller_err_socket (GError * err, void *arg)
{
- struct controller_session *session = (struct controller_session *)arg;
+ struct controller_session *session = (struct controller_session *)arg;
if (err->code != EOF) {
msg_info ("controller_err_socket: abnormally closing control connection, error: %s", err->message);
}
/* Free buffers */
- destroy_session (session->s);
+ destroy_session (session->s);
}
static void
accept_socket (int fd, short what, void *arg)
{
- struct rspamd_worker *worker = (struct rspamd_worker *)arg;
- struct sockaddr_storage ss;
- struct controller_session *new_session;
- struct timeval *io_tv;
- socklen_t addrlen = sizeof(ss);
- int nfd;
+ struct rspamd_worker *worker = (struct rspamd_worker *)arg;
+ struct sockaddr_storage ss;
+ struct controller_session *new_session;
+ struct timeval *io_tv;
+ socklen_t addrlen = sizeof (ss);
+ int nfd;
if ((nfd = accept_from_socket (fd, (struct sockaddr *)&ss, &addrlen)) == -1) {
msg_warn ("accept_socket: accept failed: %s", strerror (errno));
new_session->cfg = worker->srv->cfg;
new_session->state = STATE_COMMAND;
new_session->session_pool = memory_pool_new (memory_pool_get_size () - 1);
- worker->srv->stat->control_connections_count ++;
+ worker->srv->stat->control_connections_count++;
/* Set up dispatcher */
- io_tv = memory_pool_alloc (new_session->session_pool, sizeof (struct timeval));
+ io_tv = memory_pool_alloc (new_session->session_pool, sizeof (struct timeval));
io_tv->tv_sec = CONTROLLER_IO_TIMEOUT;
io_tv->tv_usec = 0;
- new_session->s = new_async_session (new_session->session_pool, free_session, new_session);
+ new_session->s = new_async_session (new_session->session_pool, free_session, new_session);
- new_session->dispatcher = rspamd_create_dispatcher (nfd, BUFFER_LINE, controller_read_socket,
- controller_write_socket, controller_err_socket, io_tv,
- (void *)new_session);
+ new_session->dispatcher = rspamd_create_dispatcher (nfd, BUFFER_LINE, controller_read_socket, controller_write_socket, controller_err_socket, io_tv, (void *)new_session);
rspamd_dispatcher_write (new_session->dispatcher, greetingbuf, strlen (greetingbuf), FALSE, FALSE);
}
void
start_controller (struct rspamd_worker *worker)
{
- struct sigaction signals;
- int i;
- GList *comp_list = NULL;
- char *hostbuf;
- long int hostmax;
+ struct sigaction signals;
+ int i;
+ GList *comp_list = NULL;
+ char *hostbuf;
+ long int hostmax;
worker->srv->pid = getpid ();
event_init ();
sigprocmask (SIG_UNBLOCK, &signals.sa_mask, NULL);
/* SIGUSR2 handler */
- signal_set (&worker->sig_ev, SIGUSR2, sigusr_handler, (void *) worker);
+ signal_set (&worker->sig_ev, SIGUSR2, sigusr_handler, (void *)worker);
signal_add (&worker->sig_ev, NULL);
-
+
start_time = time (NULL);
/* Init command completion */
- for (i = 0; i < G_N_ELEMENTS (commands); i ++) {
+ for (i = 0; i < G_N_ELEMENTS (commands); i++) {
comp_list = g_list_prepend (comp_list, &commands[i]);
}
comp = g_completion_new (completion_func);
hostbuf[hostmax - 1] = '\0';
snprintf (greetingbuf, sizeof (greetingbuf), "Rspamd version %s is running on %s" CRLF, RVERSION, hostbuf);
/* Accept event */
- event_set(&worker->bind_ev, worker->cf->listen_sock, EV_READ | EV_PERSIST, accept_socket, (void *)worker);
- event_add(&worker->bind_ev, NULL);
+ event_set (&worker->bind_ev, worker->cf->listen_sock, EV_READ | EV_PERSIST, accept_socket, (void *)worker);
+ event_add (&worker->bind_ev, NULL);
/* Send SIGUSR2 to parent */
kill (getppid (), SIGUSR2);
gperf_profiler_init (worker->srv->cfg, "controller");
-
+
event_loop (0);
exit (EXIT_SUCCESS);
}
-void
+void
register_custom_controller_command (const char *name, controller_func_t handler, gboolean privilleged, gboolean require_message)
{
struct custom_controller_command *cmd;
-
+
cmd = g_malloc (sizeof (struct custom_controller_command));
cmd->command = name;
cmd->handler = handler;
#include "events.h"
-struct rspamd_async_session*
-new_async_session (memory_pool_t *pool, event_finalizer_t fin, void *user_data)
+struct rspamd_async_session *
+new_async_session (memory_pool_t * pool, event_finalizer_t fin, void *user_data)
{
- struct rspamd_async_session *new;
+ struct rspamd_async_session *new;
new = memory_pool_alloc (pool, sizeof (struct rspamd_async_session));
new->pool = pool;
new->wanna_die = FALSE;
new->events = g_queue_new ();
- memory_pool_add_destructor (pool, (pool_destruct_func)g_queue_free, new->events);
+ memory_pool_add_destructor (pool, (pool_destruct_func) g_queue_free, new->events);
return new;
}
-void
+void
register_async_event (struct rspamd_async_session *session, event_finalizer_t fin, void *user_data, gboolean forced)
{
- struct rspamd_async_event *new, *ev;
- GList *cur;
+ struct rspamd_async_event *new, *ev;
+ GList *cur;
if (session == NULL) {
msg_info ("register_async_event: session is NULL");
return;
}
-
+
if (forced) {
/* For forced events try first to increase its reference */
cur = session->events->head;
while (cur) {
ev = cur->data;
if (ev->forced && ev->fin == fin) {
- ev->ref ++;
+ ev->ref++;
return;
}
cur = g_list_next (cur);
g_queue_push_head (session->events, new);
}
-void
+void
remove_forced_event (struct rspamd_async_session *session, event_finalizer_t fin)
{
- struct rspamd_async_event *ev;
- GList *cur;
+ struct rspamd_async_event *ev;
+ GList *cur;
if (session == NULL) {
msg_info ("remove_forced_event: session is NULL");
return;
}
-
+
cur = session->events->head;
while (cur) {
ev = cur->data;
if (ev->forced && ev->fin == fin) {
- ev->ref --;
+ ev->ref--;
if (ev->ref == 0) {
g_queue_delete_link (session->events, cur);
}
}
}
-void
-remove_normal_event (struct rspamd_async_session *session, event_finalizer_t fin, void *ud)
+void
+remove_normal_event (struct rspamd_async_session *session, event_finalizer_t fin, void *ud)
{
- struct rspamd_async_event *ev;
- GList *cur;
+ struct rspamd_async_event *ev;
+ GList *cur;
if (session == NULL) {
msg_info ("remove_forced_event: session is NULL");
return;
}
-
+
cur = session->events->head;
while (cur) {
ev = cur->data;
gboolean
destroy_session (struct rspamd_async_session *session)
{
- struct rspamd_async_event *ev;
- GList *cur, *tmp;
+ struct rspamd_async_event *ev;
+ GList *cur, *tmp;
if (session == NULL) {
msg_info ("destroy_session: session is NULL");
return FALSE;
}
-
+
session->wanna_die = TRUE;
-
+
cur = session->events->head;
while (cur) {
#include "expressions.h"
#include "html.h"
-gboolean rspamd_compare_encoding (struct worker_task *task, GList *args);
-gboolean rspamd_header_exists (struct worker_task *task, GList *args);
-gboolean rspamd_content_type_compare_param (struct worker_task *task, GList *args);
-gboolean rspamd_content_type_has_param (struct worker_task *task, GList *args);
-gboolean rspamd_content_type_is_subtype (struct worker_task *task, GList *args);
-gboolean rspamd_content_type_is_type (struct worker_task *task, GList *args);
-gboolean rspamd_parts_distance (struct worker_task *task, GList *args);
-gboolean rspamd_recipients_distance (struct worker_task *task, GList *args);
-gboolean rspamd_has_content_part (struct worker_task *task, GList *args);
-gboolean rspamd_has_content_part_len (struct worker_task *task, GList *args);
-gboolean rspamd_has_only_html_part (struct worker_task *task, GList *args);
-gboolean rspamd_is_recipients_sorted (struct worker_task *task, GList *args);
-gboolean rspamd_compare_transfer_encoding (struct worker_task *task, GList *args);
-gboolean rspamd_is_html_balanced (struct worker_task *task, GList *args);
-gboolean rspamd_has_html_tag (struct worker_task *task, GList *args);
-gboolean rspamd_has_fake_html (struct worker_task *task, GList *args);
+gboolean rspamd_compare_encoding (struct worker_task *task, GList * args);
+gboolean rspamd_header_exists (struct worker_task *task, GList * args);
+gboolean rspamd_content_type_compare_param (struct worker_task *task, GList * args);
+gboolean rspamd_content_type_has_param (struct worker_task *task, GList * args);
+gboolean rspamd_content_type_is_subtype (struct worker_task *task, GList * args);
+gboolean rspamd_content_type_is_type (struct worker_task *task, GList * args);
+gboolean rspamd_parts_distance (struct worker_task *task, GList * args);
+gboolean rspamd_recipients_distance (struct worker_task *task, GList * args);
+gboolean rspamd_has_content_part (struct worker_task *task, GList * args);
+gboolean rspamd_has_content_part_len (struct worker_task *task, GList * args);
+gboolean rspamd_has_only_html_part (struct worker_task *task, GList * args);
+gboolean rspamd_is_recipients_sorted (struct worker_task *task, GList * args);
+gboolean rspamd_compare_transfer_encoding (struct worker_task *task, GList * args);
+gboolean rspamd_is_html_balanced (struct worker_task *task, GList * args);
+gboolean rspamd_has_html_tag (struct worker_task *task, GList * args);
+gboolean rspamd_has_fake_html (struct worker_task *task, GList * args);
/*
* List of internal functions of rspamd
* Sorted by name to use bsearch
*/
static struct _fl {
- const char *name;
- rspamd_internal_func_t func;
+ const char *name;
+ rspamd_internal_func_t func;
} rspamd_functions_list[] = {
- { "compare_encoding", rspamd_compare_encoding },
- { "compare_parts_distance", rspamd_parts_distance },
- { "compare_recipients_distance", rspamd_recipients_distance },
- { "compare_transfer_encoding", rspamd_compare_transfer_encoding },
- { "content_type_compare_param", rspamd_content_type_compare_param },
- { "content_type_has_param", rspamd_content_type_has_param },
- { "content_type_is_subtype", rspamd_content_type_is_subtype },
- { "content_type_is_type", rspamd_content_type_is_type },
- { "has_content_part", rspamd_has_content_part },
- { "has_content_part_len", rspamd_has_content_part_len },
- { "has_fake_html", rspamd_has_fake_html },
- { "has_html_tag", rspamd_has_html_tag },
- { "has_only_html_part", rspamd_has_only_html_part },
- { "header_exists", rspamd_header_exists },
- { "is_html_balanced", rspamd_is_html_balanced },
- { "is_recipients_sorted", rspamd_is_recipients_sorted },
-};
-
-static struct _fl *list_ptr = &rspamd_functions_list[0];
-static uint32_t functions_number = sizeof (rspamd_functions_list) / sizeof (struct _fl);
-static gboolean list_allocated = FALSE;
+ {
+ "compare_encoding", rspamd_compare_encoding}, {
+ "compare_parts_distance", rspamd_parts_distance}, {
+ "compare_recipients_distance", rspamd_recipients_distance}, {
+ "compare_transfer_encoding", rspamd_compare_transfer_encoding}, {
+ "content_type_compare_param", rspamd_content_type_compare_param}, {
+ "content_type_has_param", rspamd_content_type_has_param}, {
+ "content_type_is_subtype", rspamd_content_type_is_subtype}, {
+ "content_type_is_type", rspamd_content_type_is_type}, {
+ "has_content_part", rspamd_has_content_part}, {
+ "has_content_part_len", rspamd_has_content_part_len}, {
+ "has_fake_html", rspamd_has_fake_html}, {
+ "has_html_tag", rspamd_has_html_tag}, {
+ "has_only_html_part", rspamd_has_only_html_part}, {
+ "header_exists", rspamd_header_exists}, {
+ "is_html_balanced", rspamd_is_html_balanced}, {
+"is_recipients_sorted", rspamd_is_recipients_sorted},};
+
+static struct _fl *list_ptr = &rspamd_functions_list[0];
+static uint32_t functions_number = sizeof (rspamd_functions_list) / sizeof (struct _fl);
+static gboolean list_allocated = FALSE;
/* Bsearch routine */
static int
fl_cmp (const void *s1, const void *s2)
{
- struct _fl *fl1 = (struct _fl *)s1;
- struct _fl *fl2 = (struct _fl *)s2;
+ struct _fl *fl1 = (struct _fl *)s1;
+ struct _fl *fl2 = (struct _fl *)s2;
return strcmp (fl1->name, fl2->name);
}
/* Cache for regular expressions that are used in functions */
-static GHashTable *re_cache = NULL;
+static GHashTable *re_cache = NULL;
-void *
+void *
re_cache_check (const char *line)
{
if (re_cache == NULL) {
if (re_cache == NULL) {
re_cache = g_hash_table_new (g_str_hash, g_str_equal);
}
-
+
g_hash_table_insert (re_cache, line, pointer);
}
/* Task cache functions */
-void
+void
task_cache_add (struct worker_task *task, struct rspamd_regexp *re, int32_t result)
{
- if (result == 0) {
- result = -1;
- }
+ if (result == 0) {
+ result = -1;
+ }
g_hash_table_insert (task->re_cache, re->regexp_text, GINT_TO_POINTER (result));
}
int32_t
task_cache_check (struct worker_task *task, struct rspamd_regexp *re)
{
- gpointer res;
- int32_t r;
+ gpointer res;
+ int32_t r;
if ((res = g_hash_table_lookup (task->re_cache, re->regexp_text)) != NULL) {
- r = GPOINTER_TO_INT (res);
- if (r == -1) {
- return 0;
- }
- return 1;
+ r = GPOINTER_TO_INT (res);
+ if (r == -1) {
+ return 0;
+ }
+ return 1;
}
return -1;
}
* Functions for parsing expressions
*/
struct expression_stack {
- char op;
- struct expression_stack *next;
+ char op;
+ struct expression_stack *next;
};
/*
* Push operand or operator to stack
*/
-static struct expression_stack*
-push_expression_stack (memory_pool_t *pool, struct expression_stack *head, char op)
+static struct expression_stack *
+push_expression_stack (memory_pool_t * pool, struct expression_stack *head, char op)
{
- struct expression_stack *new;
+ struct expression_stack *new;
new = memory_pool_alloc (pool, sizeof (struct expression_stack));
new->op = op;
- new->next = head;
- return new;
+ new->next = head;
+ return new;
}
/*
static char
delete_expression_stack (struct expression_stack **head)
{
- struct expression_stack *cur;
- char res;
+ struct expression_stack *cur;
+ char res;
- if(*head == NULL) return 0;
+ if (*head == NULL)
+ return 0;
cur = *head;
res = cur->op;
-
+
*head = cur->next;
return res;
}
logic_priority (char a)
{
switch (a) {
- case '!':
- return 3;
- case '|':
- case '&':
- return 2;
- case '(':
- return 1;
- default:
- return 0;
+ case '!':
+ return 3;
+ case '|':
+ case '&':
+ return 2;
+ case '(':
+ return 1;
+ default:
+ return 0;
}
}
* Return FALSE if symbol is not operation symbol (operand)
* Return TRUE if symbol is operation symbol
*/
-static gboolean
+static gboolean
is_operation_symbol (char a)
{
switch (a) {
- case '!':
- case '&':
- case '|':
- case '(':
- case ')':
- return TRUE;
- default:
- return FALSE;
+ case '!':
+ case '&':
+ case '|':
+ case '(':
+ case ')':
+ return TRUE;
+ default:
+ return FALSE;
}
}
/*
* Return TRUE if symbol can be regexp flag
*/
-static gboolean
+static gboolean
is_regexp_flag (char a)
{
switch (a) {
- case 'i':
- case 'm':
- case 'x':
- case 's':
- case 'u':
- case 'o':
- case 'r':
- case 'H':
- case 'M':
- case 'P':
- case 'U':
- case 'X':
- return TRUE;
- default:
- return FALSE;
+ case 'i':
+ case 'm':
+ case 'x':
+ case 's':
+ case 'u':
+ case 'o':
+ case 'r':
+ case 'H':
+ case 'M':
+ case 'P':
+ case 'U':
+ case 'X':
+ return TRUE;
+ default:
+ return FALSE;
}
}
static void
-insert_expression (memory_pool_t *pool, struct expression **head, int type, char op, void *operand)
+insert_expression (memory_pool_t * pool, struct expression **head, int type, char op, void *operand)
{
- struct expression *new, *cur;
-
+ struct expression *new, *cur;
+
new = memory_pool_alloc (pool, sizeof (struct expression));
new->type = type;
if (new->type != EXPR_OPERATION) {
}
}
-static struct expression*
-maybe_parse_expression (memory_pool_t *pool, char *line)
+static struct expression *
+maybe_parse_expression (memory_pool_t * pool, char *line)
{
- struct expression *expr;
- char *p = line;
+ struct expression *expr;
+ char *p = line;
while (*p) {
if (is_operation_symbol (*p)) {
return parse_expression (pool, line);
}
- p ++;
+ p++;
}
expr = memory_pool_alloc (pool, sizeof (struct expression));
* Make inverse polish record for specified expression
* Memory is allocated from given pool
*/
-struct expression*
-parse_expression (memory_pool_t *pool, char *line)
+struct expression *
+parse_expression (memory_pool_t * pool, char *line)
{
- struct expression *expr = NULL;
- struct expression_stack *stack = NULL;
- struct expression_function *func = NULL, *old;
- struct expression *arg;
- GQueue *function_stack;
- char *p, *c, *str, op;
- gboolean in_regexp = FALSE;
- int brackets = 0;
+ struct expression *expr = NULL;
+ struct expression_stack *stack = NULL;
+ struct expression_function *func = NULL, *old;
+ struct expression *arg;
+ GQueue *function_stack;
+ char *p, *c, *str, op;
+ gboolean in_regexp = FALSE;
+ int brackets = 0;
enum {
SKIP_SPACES,
if (line == NULL || pool == NULL) {
return NULL;
- }
+ }
msg_debug ("parse_expression: parsing expression {{ %s }}", line);
-
+
function_stack = g_queue_new ();
p = line;
c = p;
while (*p) {
switch (state) {
- case SKIP_SPACES:
- if (!g_ascii_isspace (*p)) {
- if (is_operation_symbol (*p)) {
- state = READ_OPERATOR;
- } else if (*p == '/') {
- c = ++p;
- state = READ_REGEXP;
- } else {
- c = p;
- state = READ_FUNCTION;
- }
+ case SKIP_SPACES:
+ if (!g_ascii_isspace (*p)) {
+ if (is_operation_symbol (*p)) {
+ state = READ_OPERATOR;
+ }
+ else if (*p == '/') {
+ c = ++p;
+ state = READ_REGEXP;
}
else {
- p ++;
+ c = p;
+ state = READ_FUNCTION;
}
- break;
- case READ_OPERATOR:
- if (*p == ')') {
- if (stack == NULL) {
- return NULL;
- }
- /* Pop all operators from stack to nearest '(' or to head */
- while (stack && stack->op != '(') {
- op = delete_expression_stack (&stack);
- if (op != '(') {
- insert_expression (pool, &expr, EXPR_OPERATION, op, NULL);
- }
- }
- if (stack) {
- op = delete_expression_stack (&stack);
+ }
+ else {
+ p++;
+ }
+ break;
+ case READ_OPERATOR:
+ if (*p == ')') {
+ if (stack == NULL) {
+ return NULL;
+ }
+ /* Pop all operators from stack to nearest '(' or to head */
+ while (stack && stack->op != '(') {
+ op = delete_expression_stack (&stack);
+ if (op != '(') {
+ insert_expression (pool, &expr, EXPR_OPERATION, op, NULL);
}
}
- else if (*p == '(') {
- /* Push it to stack */
+ if (stack) {
+ op = delete_expression_stack (&stack);
+ }
+ }
+ else if (*p == '(') {
+ /* Push it to stack */
+ stack = push_expression_stack (pool, stack, *p);
+ }
+ else {
+ if (stack == NULL) {
stack = push_expression_stack (pool, stack, *p);
}
+ /* Check priority of logic operation */
else {
- if (stack == NULL) {
+ if (logic_priority (stack->op) < logic_priority (*p)) {
stack = push_expression_stack (pool, stack, *p);
}
- /* Check priority of logic operation */
else {
- if (logic_priority (stack->op) < logic_priority (*p)) {
- stack = push_expression_stack (pool, stack, *p);
- }
- else {
- /* Pop all operations that have higher priority than this one */
- while((stack != NULL) && (logic_priority (stack->op) >= logic_priority (*p))) {
- op = delete_expression_stack (&stack);
- if (op != '(') {
- insert_expression (pool, &expr, EXPR_OPERATION, op, NULL);
- }
+ /* Pop all operations that have higher priority than this one */
+ while ((stack != NULL) && (logic_priority (stack->op) >= logic_priority (*p))) {
+ op = delete_expression_stack (&stack);
+ if (op != '(') {
+ insert_expression (pool, &expr, EXPR_OPERATION, op, NULL);
}
- stack = push_expression_stack (pool, stack, *p);
}
+ stack = push_expression_stack (pool, stack, *p);
}
}
- p ++;
- state = SKIP_SPACES;
- break;
+ }
+ p++;
+ state = SKIP_SPACES;
+ break;
- case READ_REGEXP:
- if (*p == '/' && *(p - 1) != '\\') {
- if (*(p + 1)) {
- p ++;
- }
- state = READ_REGEXP_FLAGS;
+ case READ_REGEXP:
+ if (*p == '/' && *(p - 1) != '\\') {
+ if (*(p + 1)) {
+ p++;
}
- else {
- p ++;
- }
- break;
+ state = READ_REGEXP_FLAGS;
+ }
+ else {
+ p++;
+ }
+ break;
- case READ_REGEXP_FLAGS:
- if (!is_regexp_flag (*p) || *(p + 1) == '\0') {
- if (c != p) {
- if ((is_regexp_flag (*p) || *p == '/') && *(p + 1) == '\0') {
- p ++;
- }
- str = memory_pool_alloc (pool, p - c + 2);
- g_strlcpy (str, c - 1, (p - c + 2));
- g_strstrip (str);
- msg_debug ("parse_expression: found regexp: %s", str);
- if (strlen (str) > 0) {
- insert_expression (pool, &expr, EXPR_REGEXP, 0, str);
- }
+ case READ_REGEXP_FLAGS:
+ if (!is_regexp_flag (*p) || *(p + 1) == '\0') {
+ if (c != p) {
+ if ((is_regexp_flag (*p) || *p == '/') && *(p + 1) == '\0') {
+ p++;
+ }
+ str = memory_pool_alloc (pool, p - c + 2);
+ g_strlcpy (str, c - 1, (p - c + 2));
+ g_strstrip (str);
+ msg_debug ("parse_expression: found regexp: %s", str);
+ if (strlen (str) > 0) {
+ insert_expression (pool, &expr, EXPR_REGEXP, 0, str);
}
- c = p;
- state = SKIP_SPACES;
- }
- else {
- p ++;
}
- break;
+ c = p;
+ state = SKIP_SPACES;
+ }
+ else {
+ p++;
+ }
+ break;
- case READ_FUNCTION:
- if (*p == '/') {
- /* In fact it is regexp */
- state = READ_REGEXP;
- c ++;
- p ++;
- } else if (*p == '(') {
- func = memory_pool_alloc (pool, sizeof (struct expression_function));
- func->name = memory_pool_alloc (pool, p - c + 1);
- func->args = NULL;
- g_strlcpy (func->name, c, (p - c + 1));
- g_strstrip (func->name);
- state = READ_FUNCTION_ARGUMENT;
- g_queue_push_tail (function_stack, func);
- insert_expression (pool, &expr, EXPR_FUNCTION, 0, func);
- c = ++p;
- } else if (is_operation_symbol (*p)) {
- /* In fact it is not function, but symbol */
- if (c != p) {
- str = memory_pool_alloc (pool, p - c + 1);
- g_strlcpy (str, c, (p - c + 1));
- g_strstrip (str);
- if (strlen (str) > 0) {
- insert_expression (pool, &expr, EXPR_STR, 0, str);
- }
+ case READ_FUNCTION:
+ if (*p == '/') {
+ /* In fact it is regexp */
+ state = READ_REGEXP;
+ c++;
+ p++;
+ }
+ else if (*p == '(') {
+ func = memory_pool_alloc (pool, sizeof (struct expression_function));
+ func->name = memory_pool_alloc (pool, p - c + 1);
+ func->args = NULL;
+ g_strlcpy (func->name, c, (p - c + 1));
+ g_strstrip (func->name);
+ state = READ_FUNCTION_ARGUMENT;
+ g_queue_push_tail (function_stack, func);
+ insert_expression (pool, &expr, EXPR_FUNCTION, 0, func);
+ c = ++p;
+ }
+ else if (is_operation_symbol (*p)) {
+ /* In fact it is not function, but symbol */
+ if (c != p) {
+ str = memory_pool_alloc (pool, p - c + 1);
+ g_strlcpy (str, c, (p - c + 1));
+ g_strstrip (str);
+ if (strlen (str) > 0) {
+ insert_expression (pool, &expr, EXPR_STR, 0, str);
}
- state = READ_OPERATOR;
}
- else if (*(p + 1) == '\0') {
- /* In fact it is not function, but symbol */
- p ++;
- if (c != p) {
- str = memory_pool_alloc (pool, p - c + 1);
- g_strlcpy (str, c, (p - c + 1));
- g_strstrip (str);
- if (strlen (str) > 0) {
- insert_expression (pool, &expr, EXPR_STR, 0, str);
- }
+ state = READ_OPERATOR;
+ }
+ else if (*(p + 1) == '\0') {
+ /* In fact it is not function, but symbol */
+ p++;
+ if (c != p) {
+ str = memory_pool_alloc (pool, p - c + 1);
+ g_strlcpy (str, c, (p - c + 1));
+ g_strstrip (str);
+ if (strlen (str) > 0) {
+ insert_expression (pool, &expr, EXPR_STR, 0, str);
}
- state = SKIP_SPACES;
- }
- else {
- p ++;
}
- break;
-
- case READ_FUNCTION_ARGUMENT:
- if (*p == '/' && !in_regexp) {
- in_regexp = TRUE;
- p ++;
- }
- if (!in_regexp) {
- /* Append argument to list */
- if (*p == ',' || (*p == ')' && brackets == 0)) {
- arg = memory_pool_alloc (pool, sizeof (struct expression));
- str = memory_pool_alloc (pool, p - c + 1);
- g_strlcpy (str, c, (p - c + 1));
- g_strstrip (str);
- /* Recursive call */
- arg = maybe_parse_expression (pool, str);
- func->args = g_list_append (func->args, arg);
- /* Pop function */
- if (*p == ')') {
- /* Last function in chain, goto skipping spaces state */
- old = func;
- func = g_queue_pop_tail (function_stack);
- if (g_queue_get_length (function_stack) == 0) {
- state = SKIP_SPACES;
- }
+ state = SKIP_SPACES;
+ }
+ else {
+ p++;
+ }
+ break;
+
+ case READ_FUNCTION_ARGUMENT:
+ if (*p == '/' && !in_regexp) {
+ in_regexp = TRUE;
+ p++;
+ }
+ if (!in_regexp) {
+ /* Append argument to list */
+ if (*p == ',' || (*p == ')' && brackets == 0)) {
+ arg = memory_pool_alloc (pool, sizeof (struct expression));
+ str = memory_pool_alloc (pool, p - c + 1);
+ g_strlcpy (str, c, (p - c + 1));
+ g_strstrip (str);
+ /* Recursive call */
+ arg = maybe_parse_expression (pool, str);
+ func->args = g_list_append (func->args, arg);
+ /* Pop function */
+ if (*p == ')') {
+ /* Last function in chain, goto skipping spaces state */
+ old = func;
+ func = g_queue_pop_tail (function_stack);
+ if (g_queue_get_length (function_stack) == 0) {
+ state = SKIP_SPACES;
}
- c = p + 1;
- }
- else if (*p == '(') {
- brackets ++;
- }
- else if (*p == ')') {
- brackets --;
}
+ c = p + 1;
}
- else if (*p == '/' && *(p - 1) != '\\') {
- in_regexp = FALSE;
+ else if (*p == '(') {
+ brackets++;
}
- p ++;
- break;
+ else if (*p == ')') {
+ brackets--;
+ }
+ }
+ else if (*p == '/' && *(p - 1) != '\\') {
+ in_regexp = FALSE;
+ }
+ p++;
+ break;
}
}
return NULL;
}
/* Pop everything from stack */
- while(stack != NULL) {
+ while (stack != NULL) {
op = delete_expression_stack (&stack);
if (op != '(') {
insert_expression (pool, &expr, EXPR_OPERATION, op, NULL);
/*
* Rspamd regexp utility functions
*/
-struct rspamd_regexp*
-parse_regexp (memory_pool_t *pool, char *line, gboolean raw_mode)
+struct rspamd_regexp *
+parse_regexp (memory_pool_t * pool, char *line, gboolean raw_mode)
{
- char *begin, *end, *p, *src;
- struct rspamd_regexp *result, *check;
- int regexp_flags = G_REGEX_OPTIMIZE | G_REGEX_NO_AUTO_CAPTURE;
- GError *err = NULL;
-
+ char *begin, *end, *p, *src;
+ struct rspamd_regexp *result, *check;
+ int regexp_flags = G_REGEX_OPTIMIZE | G_REGEX_NO_AUTO_CAPTURE;
+ GError *err = NULL;
+
src = line;
result = memory_pool_alloc0 (pool, sizeof (struct rspamd_regexp));
/* Skip whitespaces */
while (g_ascii_isspace (*line)) {
- line ++;
+ line++;
}
if (line == '\0') {
msg_warn ("parse_regexp: got empty regexp");
}
/* Find begin of regexp */
while (*line && *line != '/') {
- line ++;
+ line++;
}
if (*line != '\0') {
begin = line + 1;
/* Find end */
end = begin;
while (*end && (*end != '/' || *(end - 1) == '\\')) {
- end ++;
+ end++;
}
if (end == begin || *end != '/') {
msg_warn ("parse_regexp: no trailing / in regexp %s", src);
p = end + 1;
while (p != NULL) {
switch (*p) {
- case 'i':
- regexp_flags |= G_REGEX_CASELESS;
- p ++;
- break;
- case 'm':
- regexp_flags |= G_REGEX_MULTILINE;
- p ++;
- break;
- case 's':
- regexp_flags |= G_REGEX_DOTALL;
- p ++;
- break;
- case 'x':
- regexp_flags |= G_REGEX_EXTENDED;
- p ++;
- break;
- case 'u':
- regexp_flags |= G_REGEX_UNGREEDY;
- p ++;
- break;
- case 'o':
- regexp_flags |= G_REGEX_OPTIMIZE;
- p ++;
- break;
- case 'r':
- regexp_flags |= G_REGEX_RAW;
- p ++;
- break;
+ case 'i':
+ regexp_flags |= G_REGEX_CASELESS;
+ p++;
+ break;
+ case 'm':
+ regexp_flags |= G_REGEX_MULTILINE;
+ p++;
+ break;
+ case 's':
+ regexp_flags |= G_REGEX_DOTALL;
+ p++;
+ break;
+ case 'x':
+ regexp_flags |= G_REGEX_EXTENDED;
+ p++;
+ break;
+ case 'u':
+ regexp_flags |= G_REGEX_UNGREEDY;
+ p++;
+ break;
+ case 'o':
+ regexp_flags |= G_REGEX_OPTIMIZE;
+ p++;
+ break;
+ case 'r':
+ regexp_flags |= G_REGEX_RAW;
+ p++;
+ break;
/* Type flags */
- case 'H':
- if (result->type == REGEXP_NONE) {
- result->type = REGEXP_HEADER;
- }
- p ++;
- break;
- case 'M':
- if (result->type == REGEXP_NONE) {
- result->type = REGEXP_MESSAGE;
- }
- p ++;
- break;
- case 'P':
- if (result->type == REGEXP_NONE) {
- result->type = REGEXP_MIME;
- }
- p ++;
- break;
- case 'U':
- if (result->type == REGEXP_NONE) {
- result->type = REGEXP_URL;
- }
- p ++;
- break;
- case 'X':
- if (result->type == REGEXP_NONE || result->type == REGEXP_HEADER) {
- result->type = REGEXP_RAW_HEADER;
- }
- p ++;
- break;
+ case 'H':
+ if (result->type == REGEXP_NONE) {
+ result->type = REGEXP_HEADER;
+ }
+ p++;
+ break;
+ case 'M':
+ if (result->type == REGEXP_NONE) {
+ result->type = REGEXP_MESSAGE;
+ }
+ p++;
+ break;
+ case 'P':
+ if (result->type == REGEXP_NONE) {
+ result->type = REGEXP_MIME;
+ }
+ p++;
+ break;
+ case 'U':
+ if (result->type == REGEXP_NONE) {
+ result->type = REGEXP_URL;
+ }
+ p++;
+ break;
+ case 'X':
+ if (result->type == REGEXP_NONE || result->type == REGEXP_HEADER) {
+ result->type = REGEXP_RAW_HEADER;
+ }
+ p++;
+ break;
/* Stop flags parsing */
- default:
- p = NULL;
- break;
+ default:
+ p = NULL;
+ break;
}
}
}
result->regexp = g_regex_new (begin, regexp_flags, 0, &err);
result->regexp_text = memory_pool_strdup (pool, begin);
- memory_pool_add_destructor (pool, (pool_destruct_func)g_regex_unref, (void *)result->regexp);
+ memory_pool_add_destructor (pool, (pool_destruct_func) g_regex_unref, (void *)result->regexp);
if (result->regexp == NULL || err != NULL) {
*end = '/';
}
else {
result->raw_regexp = g_regex_new (begin, regexp_flags | G_REGEX_RAW, 0, &err);
- memory_pool_add_destructor (pool, (pool_destruct_func)g_regex_unref, (void *)result->raw_regexp);
+ memory_pool_add_destructor (pool, (pool_destruct_func) g_regex_unref, (void *)result->raw_regexp);
}
*end = '/';
msg_warn ("parse_regexp: could not read raw regexp: %s while reading regexp %s", err->message, src);
return NULL;
}
-
+
/* Add to cache for further usage */
re_cache_add (result->regexp_text, result);
return result;
}
-gboolean
-call_expression_function (struct expression_function *func, struct worker_task *task)
+gboolean
+call_expression_function (struct expression_function * func, struct worker_task * task)
{
- struct _fl *selected, key;
+ struct _fl *selected, key;
key.name = func->name;
- selected = bsearch (&key, list_ptr, functions_number,
- sizeof (struct _fl), fl_cmp);
+ selected = bsearch (&key, list_ptr, functions_number, sizeof (struct _fl), fl_cmp);
if (selected == NULL) {
msg_warn ("call_expression_function: call to undefined function %s", key.name);
return FALSE;
}
-
+
return selected->func (task, func->args);
}
-struct expression_argument *
+struct expression_argument *
get_function_arg (struct expression *expr, struct worker_task *task, gboolean want_string)
{
- GQueue *stack;
- gsize cur, op1, op2;
- struct expression_argument *res;
- struct expression *it;
+ GQueue *stack;
+ gsize cur, op1, op2;
+ struct expression_argument *res;
+ struct expression *it;
if (expr == NULL) {
msg_warn ("get_function_arg: NULL expression passed");
res->type = EXPRESSION_ARGUMENT_EXPR;
res->data = expr;
return res;
- } else if (it->type == EXPR_FUNCTION) {
- cur = (gsize)call_expression_function ((struct expression_function *)it->content.operand, task);
- msg_debug ("get_function_arg: function %s returned %s", ((struct expression_function *)it->content.operand)->name,
- cur ? "true" : "false");
- } else if (it->type == EXPR_OPERATION) {
+ }
+ else if (it->type == EXPR_FUNCTION) {
+ cur = (gsize) call_expression_function ((struct expression_function *)it->content.operand, task);
+ msg_debug ("get_function_arg: function %s returned %s", ((struct expression_function *)it->content.operand)->name, cur ? "true" : "false");
+ }
+ else if (it->type == EXPR_OPERATION) {
if (g_queue_is_empty (stack)) {
/* Queue has no operands for operation, exiting */
msg_debug ("get_function_arg: invalid expression");
return NULL;
}
switch (it->content.operation) {
- case '!':
- op1 = GPOINTER_TO_SIZE (g_queue_pop_head (stack));
- op1 = !op1;
- g_queue_push_head (stack, GSIZE_TO_POINTER (op1));
- break;
- case '&':
- op1 = GPOINTER_TO_SIZE (g_queue_pop_head (stack));
- op2 = GPOINTER_TO_SIZE (g_queue_pop_head (stack));
- g_queue_push_head (stack, GSIZE_TO_POINTER (op1 && op2));
- case '|':
- op1 = GPOINTER_TO_SIZE (g_queue_pop_head (stack));
- op2 = GPOINTER_TO_SIZE (g_queue_pop_head (stack));
- g_queue_push_head (stack, GSIZE_TO_POINTER (op1 || op2));
- default:
- it = it->next;
- continue;
+ case '!':
+ op1 = GPOINTER_TO_SIZE (g_queue_pop_head (stack));
+ op1 = !op1;
+ g_queue_push_head (stack, GSIZE_TO_POINTER (op1));
+ break;
+ case '&':
+ op1 = GPOINTER_TO_SIZE (g_queue_pop_head (stack));
+ op2 = GPOINTER_TO_SIZE (g_queue_pop_head (stack));
+ g_queue_push_head (stack, GSIZE_TO_POINTER (op1 && op2));
+ case '|':
+ op1 = GPOINTER_TO_SIZE (g_queue_pop_head (stack));
+ op2 = GPOINTER_TO_SIZE (g_queue_pop_head (stack));
+ g_queue_push_head (stack, GSIZE_TO_POINTER (op1 || op2));
+ default:
+ it = it->next;
+ continue;
}
}
if (it) {
void
register_expression_function (const char *name, rspamd_internal_func_t func)
{
- static struct _fl *new;
+ static struct _fl *new;
+
+ functions_number++;
- functions_number ++;
-
new = g_new (struct _fl, functions_number);
memcpy (new, list_ptr, (functions_number - 1) * sizeof (struct _fl));
if (list_allocated) {
}
gboolean
-rspamd_compare_encoding (struct worker_task *task, GList *args)
+rspamd_compare_encoding (struct worker_task *task, GList * args)
{
- struct expression_argument *arg;
+ struct expression_argument *arg;
if (args == NULL || task == NULL) {
return FALSE;
return TRUE;
}
-gboolean
-rspamd_header_exists (struct worker_task *task, GList *args)
+gboolean
+rspamd_header_exists (struct worker_task * task, GList * args)
{
- struct expression_argument *arg;
- GList *headerlist;
+ struct expression_argument *arg;
+ GList *headerlist;
if (args == NULL || task == NULL) {
return FALSE;
* its hashes and check for threshold, if value is greater than threshold, return TRUE
* and return FALSE otherwise.
*/
-gboolean
-rspamd_parts_distance (struct worker_task *task, GList *args)
-{
- int threshold;
- struct mime_text_part *p1, *p2;
- GList *cur;
- struct expression_argument *arg;
-
+gboolean
+rspamd_parts_distance (struct worker_task * task, GList * args)
+{
+ int threshold;
+ struct mime_text_part *p1, *p2;
+ GList *cur;
+ struct expression_argument *arg;
+
if (args == NULL) {
msg_debug ("rspamd_parts_distance: no threshold is specified, assume it 100");
threshold = 100;
return FALSE;
}
-gboolean
-rspamd_content_type_compare_param (struct worker_task *task, GList *args)
+gboolean
+rspamd_content_type_compare_param (struct worker_task * task, GList * args)
{
- char *param_name, *param_pattern;
- const char *param_data;
- struct rspamd_regexp *re;
- struct expression_argument *arg;
- GMimeObject *part;
- const GMimeContentType *ct;
- int r;
-
+ char *param_name, *param_pattern;
+ const char *param_data;
+ struct rspamd_regexp *re;
+ struct expression_argument *arg;
+ GMimeObject *part;
+ const GMimeContentType *ct;
+ int r;
+
if (args == NULL) {
msg_warn ("rspamd_content_type_compare_param: no parameters to function");
return FALSE;
}
arg = get_function_arg (args->data, task, TRUE);
param_pattern = arg->data;
-
+
part = g_mime_message_get_mime_part (task->message);
if (part) {
ct = g_mime_object_get_content_type (part);
}
}
}
-
+
return FALSE;
-}
+}
-gboolean
-rspamd_content_type_has_param (struct worker_task *task, GList *args)
+gboolean
+rspamd_content_type_has_param (struct worker_task * task, GList * args)
{
- char *param_name;
- const char *param_data;
- struct expression_argument *arg;
- GMimeObject *part;
- const GMimeContentType *ct;
-
+ char *param_name;
+ const char *param_data;
+ struct expression_argument *arg;
+ GMimeObject *part;
+ const GMimeContentType *ct;
+
if (args == NULL) {
msg_warn ("rspamd_content_type_compare_param: no parameters to function");
return FALSE;
return FALSE;
}
}
-
+
return TRUE;
}
/* In gmime24 this function is opaque, so define it here to avoid errors when compiling with gmime24 */
typedef struct {
- char *type;
- char *subtype;
-
- GMimeParam *params;
- GHashTable *param_hash;
+ char *type;
+ char *subtype;
+
+ GMimeParam *params;
+ GHashTable *param_hash;
} localContentType;
-gboolean
-rspamd_content_type_is_subtype (struct worker_task *task, GList *args)
+gboolean
+rspamd_content_type_is_subtype (struct worker_task *task, GList * args)
{
- char *param_pattern;
- struct rspamd_regexp *re;
- struct expression_argument *arg;
- GMimeObject *part;
- const localContentType *ct;
- int r;
-
+ char *param_pattern;
+ struct rspamd_regexp *re;
+ struct expression_argument *arg;
+ GMimeObject *part;
+ const localContentType *ct;
+ int r;
+
if (args == NULL) {
msg_warn ("rspamd_content_type_compare_param: no parameters to function");
return FALSE;
}
-
+
arg = get_function_arg (args->data, task, TRUE);
param_pattern = arg->data;
part = g_mime_message_get_mime_part (task->message);
if (ct == NULL) {
return FALSE;
}
-
+
if (*param_pattern == '/') {
/* This is regexp, so compile and create g_regexp object */
if ((re = re_cache_check (param_pattern)) == NULL) {
return FALSE;
}
-gboolean
-rspamd_content_type_is_type (struct worker_task *task, GList *args)
+gboolean
+rspamd_content_type_is_type (struct worker_task * task, GList * args)
{
- char *param_pattern;
- struct rspamd_regexp *re;
- GMimeObject *part;
- const localContentType *ct;
- struct expression_argument *arg;
- int r;
-
+ char *param_pattern;
+ struct rspamd_regexp *re;
+ GMimeObject *part;
+ const localContentType *ct;
+ struct expression_argument *arg;
+ int r;
+
if (args == NULL) {
msg_warn ("rspamd_content_type_compare_param: no parameters to function");
return FALSE;
}
-
+
arg = get_function_arg (args->data, task, TRUE);
param_pattern = arg->data;
if (ct == NULL) {
return FALSE;
}
-
+
if (*param_pattern == '/') {
/* This is regexp, so compile and create g_regexp object */
if ((re = re_cache_check (param_pattern)) == NULL) {
}
struct addr_list {
- const char *name;
- const char *addr;
+ const char *name;
+ const char *addr;
};
#define COMPARE_RCPT_LEN 3
#define MIN_RCPT_TO_COMPARE 5
-gboolean
-rspamd_recipients_distance (struct worker_task *task, GList *args)
+gboolean
+rspamd_recipients_distance (struct worker_task *task, GList * args)
{
- struct expression_argument *arg;
- InternetAddressList *cur;
- InternetAddress *addr;
- double threshold;
- struct addr_list *ar;
- char *c;
- int num, i, j, hits = 0, total = 0;
-
+ struct expression_argument *arg;
+ InternetAddressList *cur;
+ InternetAddress *addr;
+ double threshold;
+ struct addr_list *ar;
+ char *c;
+ int num, i, j, hits = 0, total = 0;
+
if (args == NULL) {
msg_warn ("rspamd_content_type_compare_param: no parameters to function");
return FALSE;
}
-
+
arg = get_function_arg (args->data, task, TRUE);
errno = 0;
threshold = strtod ((char *)arg->data, NULL);
ar[i].addr = c + 1;
}
cur = internet_address_list_next (cur);
- i ++;
+ i++;
}
/* Cycle all elements in array */
- for (i = 0; i < num; i ++) {
- for (j = i + 1; j < num; j ++) {
+ for (i = 0; i < num; i++) {
+ for (j = i + 1; j < num; j++) {
if (ar[i].name && ar[j].name && g_ascii_strncasecmp (ar[i].name, ar[j].name, COMPARE_RCPT_LEN) == 0) {
/* Common name part */
- hits ++;
+ hits++;
}
else if (ar[i].addr && ar[j].addr && g_ascii_strcasecmp (ar[i].addr, ar[j].addr) == 0) {
/* Common address part, but different name */
- hits ++;
+ hits++;
}
- total ++;
+ total++;
}
}
return FALSE;
}
-gboolean
-rspamd_has_only_html_part (struct worker_task *task, GList *args)
+gboolean
+rspamd_has_only_html_part (struct worker_task * task, GList * args)
{
- struct mime_text_part *p;
- GList *cur;
- gboolean res = FALSE;
+ struct mime_text_part *p;
+ GList *cur;
+ gboolean res = FALSE;
cur = g_list_first (task->text_parts);
while (cur) {
return res;
}
-static gboolean
-is_recipient_list_sorted (const InternetAddressList *ia)
+static gboolean
+is_recipient_list_sorted (const InternetAddressList * ia)
{
- const InternetAddressList *cur;
- InternetAddress *addr;
- gboolean res = TRUE;
- struct addr_list current = {NULL, NULL}, previous = {NULL, NULL};
-
+ const InternetAddressList *cur;
+ InternetAddress *addr;
+ gboolean res = TRUE;
+ struct addr_list current = { NULL, NULL }, previous = {
+ NULL, NULL};
+
/* Do not check to short address lists */
if (internet_address_list_length (ia) < MIN_RCPT_TO_COMPARE) {
return FALSE;
}
gboolean
-rspamd_is_recipients_sorted (struct worker_task *task, GList *args)
+rspamd_is_recipients_sorted (struct worker_task * task, GList * args)
{
/* Check all types of addresses */
if (is_recipient_list_sorted (g_mime_message_get_recipients (task->message, GMIME_RECIPIENT_TYPE_TO)) == TRUE) {
return FALSE;
}
-static inline gboolean
-compare_subtype (struct worker_task *task, const localContentType *ct, char *subtype)
+static inline gboolean
+compare_subtype (struct worker_task *task, const localContentType * ct, char *subtype)
{
- struct rspamd_regexp *re;
- int r;
+ struct rspamd_regexp *re;
+ int r;
if (*subtype == '/') {
/* This is regexp, so compile and create g_regexp object */
return FALSE;
}
-static inline gboolean
+static inline gboolean
compare_len (struct mime_part *part, int min, int max)
{
if (min == 0 && max == 0) {
}
}
-gboolean
-common_has_content_part (struct worker_task *task, char *param_type, char *param_subtype, int min_len, int max_len)
+gboolean
+common_has_content_part (struct worker_task * task, char *param_type, char *param_subtype, int min_len, int max_len)
{
- struct rspamd_regexp *re;
- struct mime_part *part;
- GList *cur;
- const localContentType *ct;
- int r;
-
+ struct rspamd_regexp *re;
+ struct mime_part *part;
+ GList *cur;
+ const localContentType *ct;
+ int r;
+
cur = g_list_first (task->parts);
while (cur) {
part = cur->data;
- ct = (localContentType *)part->type;
+ ct = (localContentType *) part->type;
if (ct == NULL) {
cur = g_list_next (cur);
continue;
}
-
+
if (*param_type == '/') {
/* This is regexp, so compile and create g_regexp object */
if ((re = re_cache_check (param_type)) == NULL) {
}
gboolean
-rspamd_has_content_part (struct worker_task *task, GList *args)
+rspamd_has_content_part (struct worker_task * task, GList * args)
{
- char *param_type = NULL, *param_subtype = NULL;
- struct expression_argument *arg;
+ char *param_type = NULL, *param_subtype = NULL;
+ struct expression_argument *arg;
if (args == NULL) {
msg_warn ("rspamd_has_content_part: no parameters to function");
return FALSE;
}
-
+
arg = get_function_arg (args->data, task, TRUE);
param_type = arg->data;
args = args->next;
}
gboolean
-rspamd_has_content_part_len (struct worker_task *task, GList *args)
+rspamd_has_content_part_len (struct worker_task * task, GList * args)
{
- char *param_type = NULL, *param_subtype = NULL;
- int min = 0, max = 0;
- struct expression_argument *arg;
+ char *param_type = NULL, *param_subtype = NULL;
+ int min = 0, max = 0;
+ struct expression_argument *arg;
if (args == NULL) {
msg_warn ("rspamd_has_content_part_len: no parameters to function");
return FALSE;
}
-
+
arg = get_function_arg (args->data, task, TRUE);
param_type = arg->data;
args = args->next;
return common_has_content_part (task, param_type, param_subtype, min, max);
}
-gboolean
-rspamd_compare_transfer_encoding (struct worker_task *task, GList *args)
+gboolean
+rspamd_compare_transfer_encoding (struct worker_task * task, GList * args)
{
- GMimeObject *part;
- GMimePartEncodingType enc_req, part_enc;
- struct expression_argument *arg;
-
+ GMimeObject *part;
+ GMimePartEncodingType enc_req, part_enc;
+ struct expression_argument *arg;
+
if (args == NULL) {
msg_warn ("rspamd_compare_transfer_encoding: no parameters to function");
return FALSE;
}
-
+
arg = get_function_arg (args->data, task, TRUE);
enc_req = g_mime_part_encoding_from_string (arg->data);
#ifndef GMIME24
if (part) {
if (GMIME_IS_PART (part)) {
part_enc = g_mime_part_get_encoding (GMIME_PART (part));
-
- msg_debug ("rspamd_compare_transfer_encoding: got encoding in part: %d and compare with %d",
- (int)part_enc, (int)enc_req);
+
+ msg_debug ("rspamd_compare_transfer_encoding: got encoding in part: %d and compare with %d", (int)part_enc, (int)enc_req);
g_object_unref (part);
return part_enc == enc_req;
return FALSE;
}
-gboolean
-rspamd_is_html_balanced (struct worker_task *task, GList *args)
+gboolean
+rspamd_is_html_balanced (struct worker_task * task, GList * args)
{
- struct mime_text_part *p;
- GList *cur;
- gboolean res = TRUE;
+ struct mime_text_part *p;
+ GList *cur;
+ gboolean res = TRUE;
cur = g_list_first (task->text_parts);
while (cur) {
}
struct html_callback_data {
- struct html_tag *tag;
- gboolean *res;
+ struct html_tag *tag;
+ gboolean *res;
};
-static gboolean
-search_html_node_callback (GNode *node, gpointer data)
+static gboolean
+search_html_node_callback (GNode * node, gpointer data)
{
- struct html_callback_data *cd = data;
- struct html_node *nd;
-
+ struct html_callback_data *cd = data;
+ struct html_node *nd;
+
nd = node->data;
if (nd) {
if (nd->tag == cd->tag) {
return FALSE;
}
-gboolean
-rspamd_has_html_tag (struct worker_task *task, GList *args)
+gboolean
+rspamd_has_html_tag (struct worker_task * task, GList * args)
{
- struct mime_text_part *p;
- GList *cur;
- struct expression_argument *arg;
- struct html_tag *tag;
- gboolean res = FALSE;
- struct html_callback_data cd;
-
+ struct mime_text_part *p;
+ GList *cur;
+ struct expression_argument *arg;
+ struct html_tag *tag;
+ gboolean res = FALSE;
+ struct html_callback_data cd;
+
if (args == NULL) {
msg_warn ("rspamd_has_html_tag: no parameters to function");
return FALSE;
}
-
+
arg = get_function_arg (args->data, task, TRUE);
tag = get_tag_by_name (arg->data);
if (tag == NULL) {
}
-gboolean
-rspamd_has_fake_html (struct worker_task *task, GList *args)
+gboolean
+rspamd_has_fake_html (struct worker_task * task, GList * args)
{
- struct mime_text_part *p;
- GList *cur;
- gboolean res = FALSE;
-
+ struct mime_text_part *p;
+ GList *cur;
+ gboolean res = FALSE;
+
cur = g_list_first (task->text_parts);
while (cur && res == FALSE) {
#include "tokenizers/tokenizers.h"
#ifndef WITHOUT_PERL
-#include "perl.h"
+# include "perl.h"
#endif
#ifdef WITH_LUA
-#include "lua/lua_common.h"
+# include "lua/lua_common.h"
#endif
void
-insert_result (struct worker_task *task, const char *metric_name, const char *symbol, double flag, GList *opts)
+insert_result (struct worker_task *task, const char *metric_name, const char *symbol, double flag, GList * opts)
{
- struct metric *metric;
- struct metric_result *metric_res;
- struct symbol *s;
- struct cache_item *item;
- int i;
+ struct metric *metric;
+ struct metric_result *metric_res;
+ struct symbol *s;
+ struct cache_item *item;
+ int i;
metric = g_hash_table_lookup (task->worker->srv->cfg->metrics, metric_name);
if (metric == NULL) {
metric_res = memory_pool_alloc (task->task_pool, sizeof (struct metric_result));
metric_res->symbols = g_hash_table_new (g_str_hash, g_str_equal);
metric_res->checked = FALSE;
- memory_pool_add_destructor (task->task_pool, (pool_destruct_func)g_hash_table_destroy, metric_res->symbols);
+ memory_pool_add_destructor (task->task_pool, (pool_destruct_func) g_hash_table_destroy, metric_res->symbols);
metric_res->metric = metric;
- g_hash_table_insert (task->results, (gpointer)metric_name, metric_res);
+ g_hash_table_insert (task->results, (gpointer) metric_name, metric_res);
}
-
+
if ((s = g_hash_table_lookup (metric_res->symbols, symbol)) != NULL) {
if (s->options && opts) {
/* Append new options */
}
else if (opts) {
s->options = opts;
- memory_pool_add_destructor (task->task_pool, (pool_destruct_func)g_list_free, s->options);
+ memory_pool_add_destructor (task->task_pool, (pool_destruct_func) g_list_free, s->options);
}
s->score = flag;
s->options = opts;
if (opts) {
- memory_pool_add_destructor (task->task_pool, (pool_destruct_func)g_list_free, s->options);
+ memory_pool_add_destructor (task->task_pool, (pool_destruct_func) g_list_free, s->options);
}
- g_hash_table_insert (metric_res->symbols, (gpointer)symbol, s);
+ g_hash_table_insert (metric_res->symbols, (gpointer) symbol, s);
}
/* Process cache item */
if (metric->cache) {
- for (i = 0; i < metric->cache->used_items; i ++) {
+ for (i = 0; i < metric->cache->used_items; i++) {
item = &metric->cache->items[i];
if (flag > 0 && strcmp (item->s->symbol, symbol) == 0) {
- item->s->frequency ++;
+ item->s->frequency++;
}
}
}
* Default consolidation function based on factors in config file
*/
struct consolidation_callback_data {
- struct worker_task *task;
- double score;
+ struct worker_task *task;
+ double score;
};
static void
consolidation_callback (gpointer key, gpointer value, gpointer arg)
{
- double *factor, fs;
- struct symbol *s = (struct symbol *)value;
+ double *factor, fs;
+ struct symbol *s = (struct symbol *)value;
struct consolidation_callback_data *data = (struct consolidation_callback_data *)arg;
if (check_factor_settings (data->task, key, &fs)) {
double
factor_consolidation_func (struct worker_task *task, const char *metric_name, const char *unused)
{
- struct metric_result *metric_res;
- double res = 0.;
+ struct metric_result *metric_res;
+ double res = 0.;
struct consolidation_callback_data data = { task, 0 };
metric_res = g_hash_table_lookup (task->results, metric_name);
if (metric_res == NULL) {
return res;
}
-
+
g_hash_table_foreach (metric_res->symbols, consolidation_callback, &data);
return data.score;
static void
call_filter_by_name (struct worker_task *task, const char *name, enum filter_type filt_type)
{
- struct module_ctx *c_module;
- int res = 0;
-
+ struct module_ctx *c_module;
+ int res = 0;
+
switch (filt_type) {
- case C_FILTER:
- c_module = g_hash_table_lookup (task->worker->srv->cfg->c_modules, name);
- if (c_module) {
- res = 1;
- c_module->filter (task);
- }
- else {
- msg_debug ("call_filter_by_name: %s is not a C module", name);
- }
- break;
- case PERL_FILTER:
+ case C_FILTER:
+ c_module = g_hash_table_lookup (task->worker->srv->cfg->c_modules, name);
+ if (c_module) {
res = 1;
+ c_module->filter (task);
+ }
+ else {
+ msg_debug ("call_filter_by_name: %s is not a C module", name);
+ }
+ break;
+ case PERL_FILTER:
+ res = 1;
#ifndef WITHOUT_PERL
- perl_call_filter (name, task);
+ perl_call_filter (name, task);
#elif defined(WITH_LUA)
- lua_call_filter (name, task);
+ lua_call_filter (name, task);
#else
- msg_err ("call_filter_by_name: trying to call perl function while perl support is disabled %s", name);
+ msg_err ("call_filter_by_name: trying to call perl function while perl support is disabled %s", name);
#endif
- break;
+ break;
}
msg_debug ("call_filter_by_name: filter name: %s, result: %d", name, (int)res);
static void
metric_process_callback_common (gpointer key, gpointer value, void *data, gboolean is_forced)
{
- struct worker_task *task = (struct worker_task *)data;
- struct metric_result *metric_res = (struct metric_result *)value;
-
+ struct worker_task *task = (struct worker_task *)data;
+ struct metric_result *metric_res = (struct metric_result *)value;
+
if (metric_res->checked && !is_forced) {
/* Already checked */
return;
}
-
+
/* Set flag */
metric_res->checked = TRUE;
else {
metric_res->score = factor_consolidation_func (task, metric_res->metric->name, NULL);
}
- msg_debug ("process_metric_callback: got result %.2f from consolidation function for metric %s",
- metric_res->score, metric_res->metric->name);
+ msg_debug ("process_metric_callback: got result %.2f from consolidation function for metric %s", metric_res->score, metric_res->metric->name);
}
static void
}
/* Return true if metric has score that is more than spam score for it */
-static gboolean
+static gboolean
check_metric_is_spam (struct worker_task *task, struct metric *metric)
{
- struct metric_result *res;
- double ms;
+ struct metric_result *res;
+ double ms;
res = g_hash_table_lookup (task->results, metric->name);
if (res) {
static int
continue_process_filters (struct worker_task *task)
{
- GList *cur = task->save.entry;
- struct cache_item *item = task->save.item;
+ GList *cur = task->save.entry;
+ struct cache_item *item = task->save.item;
+
+ struct metric *metric = cur->data;
- struct metric *metric = cur->data;
-
while (cur) {
metric = cur->data;
while (call_symbol_callback (task, metric->cache, &item)) {
return 1;
}
-int
+int
process_filters (struct worker_task *task)
{
- GList *cur;
- struct metric *metric;
- struct cache_item *item = NULL;
+ GList *cur;
+ struct metric *metric;
+ struct cache_item *item = NULL;
if (task->save.saved) {
task->save.saved = 0;
}
struct composites_data {
- struct worker_task *task;
- struct metric_result *metric_res;
+ struct worker_task *task;
+ struct metric_result *metric_res;
};
static void
composites_foreach_callback (gpointer key, gpointer value, void *data)
{
- struct composites_data *cd = (struct composites_data *)data;
- struct expression *expr = (struct expression *)value;
- GQueue *stack;
- GList *symbols = NULL, *s;
- gsize cur, op1, op2;
- struct symbol *res;
-
+ struct composites_data *cd = (struct composites_data *)data;
+ struct expression *expr = (struct expression *)value;
+ GQueue *stack;
+ GList *symbols = NULL, *s;
+ gsize cur, op1, op2;
+ struct symbol *res;
+
stack = g_queue_new ();
while (expr) {
return;
}
switch (expr->content.operation) {
- case '!':
- op1 = GPOINTER_TO_SIZE (g_queue_pop_head (stack));
- op1 = !op1;
- g_queue_push_head (stack, GSIZE_TO_POINTER (op1));
- break;
- case '&':
- op1 = GPOINTER_TO_SIZE (g_queue_pop_head (stack));
- op2 = GPOINTER_TO_SIZE (g_queue_pop_head (stack));
- g_queue_push_head (stack, GSIZE_TO_POINTER (op1 && op2));
- case '|':
- op1 = GPOINTER_TO_SIZE (g_queue_pop_head (stack));
- op2 = GPOINTER_TO_SIZE (g_queue_pop_head (stack));
- g_queue_push_head (stack, GSIZE_TO_POINTER (op1 || op2));
- default:
- expr = expr->next;
- continue;
+ case '!':
+ op1 = GPOINTER_TO_SIZE (g_queue_pop_head (stack));
+ op1 = !op1;
+ g_queue_push_head (stack, GSIZE_TO_POINTER (op1));
+ break;
+ case '&':
+ op1 = GPOINTER_TO_SIZE (g_queue_pop_head (stack));
+ op2 = GPOINTER_TO_SIZE (g_queue_pop_head (stack));
+ g_queue_push_head (stack, GSIZE_TO_POINTER (op1 && op2));
+ case '|':
+ op1 = GPOINTER_TO_SIZE (g_queue_pop_head (stack));
+ op2 = GPOINTER_TO_SIZE (g_queue_pop_head (stack));
+ g_queue_push_head (stack, GSIZE_TO_POINTER (op1 || op2));
+ default:
+ expr = expr->next;
+ continue;
}
}
expr = expr->next;
return;
}
-static gboolean
+static gboolean
check_autolearn (struct statfile_autolearn_params *params, struct worker_task *task)
-{
- char *metric_name = DEFAULT_METRIC;
- struct metric_result *metric_res;
- GList *cur;
+{
+ char *metric_name = DEFAULT_METRIC;
+ struct metric_result *metric_res;
+ GList *cur;
if (params->metric != NULL) {
metric_name = (char *)params->metric;
else {
/* Process score of metric */
metric_process_callback_normal ((void *)metric_name, metric_res, task);
- if ((params->threshold_min != 0 && metric_res->score > params->threshold_min) ||
- (params->threshold_max != 0 && metric_res->score < params->threshold_max)) {
+ if ((params->threshold_min != 0 && metric_res->score > params->threshold_min) || (params->threshold_max != 0 && metric_res->score < params->threshold_max)) {
/* Now check for specific symbols */
if (params->symbols) {
cur = params->symbols;
}
void
-process_autolearn (struct statfile *st, struct worker_task *task, GTree *tokens,
- struct classifier *classifier, char *filename, struct classifier_ctx* ctx)
+process_autolearn (struct statfile *st, struct worker_task *task, GTree * tokens, struct classifier *classifier, char *filename, struct classifier_ctx *ctx)
{
if (check_autolearn (st->autolearn, task)) {
if (tokens) {
msg_info ("process_autolearn: message with id <%s> autolearned statfile '%s'", task->message_id, filename);
/* Check opened */
- if (! statfile_pool_is_open (task->worker->srv->statfile_pool, filename)) {
+ if (!statfile_pool_is_open (task->worker->srv->statfile_pool, filename)) {
/* Try open */
if (statfile_pool_open (task->worker->srv->statfile_pool, filename) == NULL) {
/* Try create */
- if (statfile_pool_create (task->worker->srv->statfile_pool,
- filename, st->size / sizeof (struct stat_file_block)) == -1) {
+ if (statfile_pool_create (task->worker->srv->statfile_pool, filename, st->size / sizeof (struct stat_file_block)) == -1) {
msg_info ("process_autolearn: error while creating statfile %s", filename);
return;
}
}
static void
-composites_metric_callback (gpointer key, gpointer value, void *data)
+composites_metric_callback (gpointer key, gpointer value, void *data)
{
- struct worker_task *task = (struct worker_task *)data;
- struct composites_data *cd = memory_pool_alloc (task->task_pool, sizeof (struct composites_data));
- struct metric_result *metric_res = (struct metric_result *)value;
+ struct worker_task *task = (struct worker_task *)data;
+ struct composites_data *cd = memory_pool_alloc (task->task_pool, sizeof (struct composites_data));
+ struct metric_result *metric_res = (struct metric_result *)value;
cd->task = task;
cd->metric_res = (struct metric_result *)metric_res;
g_hash_table_foreach (task->cfg->composite_symbols, composites_foreach_callback, cd);
}
-void
+void
make_composites (struct worker_task *task)
{
g_hash_table_foreach (task->results, composites_metric_callback, task);
struct statfile_callback_data {
- GHashTable *tokens;
- struct worker_task *task;
+ GHashTable *tokens;
+ struct worker_task *task;
};
static void
classifiers_callback (gpointer value, void *arg)
{
- struct statfile_callback_data *data= (struct statfile_callback_data *)arg;
- struct worker_task *task = data->task;
- struct classifier_config *cl = value;
- struct classifier_ctx *ctx;
- struct mime_text_part *text_part;
- struct statfile *st;
- GTree *tokens = NULL;
- GList *cur;
- f_str_t c;
-
+ struct statfile_callback_data *data = (struct statfile_callback_data *)arg;
+ struct worker_task *task = data->task;
+ struct classifier_config *cl = value;
+ struct classifier_ctx *ctx;
+ struct mime_text_part *text_part;
+ struct statfile *st;
+ GTree *tokens = NULL;
+ GList *cur;
+ f_str_t c;
+
cur = g_list_first (task->text_parts);
if ((tokens = g_hash_table_lookup (data->tokens, cl->tokenizer)) == NULL) {
while (cur != NULL) {
if (tokens == NULL) {
return;
}
-
+
ctx = cl->classifier->init_func (task->task_pool, cl);
cl->classifier->classify_func (ctx, task->worker->srv->statfile_pool, tokens, task);
-
+
/* Autolearning */
cur = g_list_first (cl->statfiles);
while (cur) {
void
process_statfiles (struct worker_task *task)
{
- struct statfile_callback_data cd;
-
+ struct statfile_callback_data cd;
+
cd.task = task;
cd.tokens = g_hash_table_new (g_direct_hash, g_direct_equal);
static void
insert_metric_header (gpointer metric_name, gpointer metric_value, gpointer data)
{
- struct worker_task *task = (struct worker_task *)data;
- int r = 0;
+ struct worker_task *task = (struct worker_task *)data;
+ int r = 0;
/* Try to be rfc2822 compatible and avoid long headers with folding */
- char header_name[128], outbuf[1000];
- GList *symbols = NULL, *cur;
- struct metric_result *metric_res = (struct metric_result *)metric_value;
- double ms;
-
+ char header_name[128], outbuf[1000];
+ GList *symbols = NULL, *cur;
+ struct metric_result *metric_res = (struct metric_result *)metric_value;
+ double ms;
+
snprintf (header_name, sizeof (header_name), "X-Spam-%s", metric_res->metric->name);
if (!check_metric_settings (task, metric_res->metric, &ms)) {
* Search first occurence of character in string
*/
ssize_t
-fstrchr (f_str_t *src, char c)
+fstrchr (f_str_t * src, char c)
{
- register ssize_t cur = 0;
+ register ssize_t cur = 0;
while (cur < src->len) {
if (*(src->begin + cur) == c) {
return cur;
}
- cur ++;
+ cur++;
}
return -1;
* Search last occurence of character in string
*/
ssize_t
-fstrrchr (f_str_t *src, char c)
+fstrrchr (f_str_t * src, char c)
{
- register ssize_t cur = src->len;
+ register ssize_t cur = src->len;
while (cur > 0) {
if (*(src->begin + cur) == c) {
return cur;
}
- cur --;
+ cur--;
}
return -1;
* Search for pattern in orig
*/
ssize_t
-fstrstr (f_str_t *orig, f_str_t *pattern)
+fstrstr (f_str_t * orig, f_str_t * pattern)
{
- register ssize_t cur = 0, pcur = 0;
+ register ssize_t cur = 0, pcur = 0;
if (pattern->len > orig->len) {
return -1;
pcur = 0;
break;
}
- cur ++;
- pcur ++;
+ cur++;
+ pcur++;
}
return cur - pattern->len;
}
- cur ++;
+ cur++;
}
return -1;
* Search for pattern in orig ignoring case
*/
ssize_t
-fstrstri (f_str_t *orig, f_str_t *pattern)
+fstrstri (f_str_t * orig, f_str_t * pattern)
{
- register ssize_t cur = 0, pcur = 0;
+ register ssize_t cur = 0, pcur = 0;
if (pattern->len > orig->len) {
return -1;
pcur = 0;
break;
}
- cur ++;
- pcur ++;
+ cur++;
+ pcur++;
}
return cur - pattern->len;
}
- cur ++;
+ cur++;
}
return -1;
* 0 - last word extracted
*/
int
-fstrtok (f_str_t *text, const char *sep, f_tok_t *state)
+fstrtok (f_str_t * text, const char *sep, f_tok_t * state)
{
- register size_t cur;
- const char *csep = sep;
+ register size_t cur;
+ const char *csep = sep;
if (state->pos >= text->len) {
return -1;
state->pos = cur + 1;
return 1;
}
- csep ++;
+ csep++;
}
csep = sep;
- cur ++;
+ cur++;
}
-
+
/* Last word */
state->word.begin = (text->begin + state->pos);
state->word.len = cur - state->pos;
* Copy one string into other
*/
size_t
-fstrcpy (f_str_t *dest, f_str_t *src)
+fstrcpy (f_str_t * dest, f_str_t * src)
{
- register size_t cur = 0;
+ register size_t cur = 0;
if (dest->size < src->len) {
return 0;
while (cur < src->len && cur < dest->size) {
*(dest->begin + cur) = *(src->begin + cur);
- cur ++;
+ cur++;
}
return cur;
* Concatenate two strings
*/
size_t
-fstrcat (f_str_t *dest, f_str_t *src)
+fstrcat (f_str_t * dest, f_str_t * src)
{
- register size_t cur = 0;
- char *p = dest->begin + dest->len;
+ register size_t cur = 0;
+ char *p = dest->begin + dest->len;
if (dest->size < src->len + dest->len) {
return 0;
while (cur < src->len) {
*p = *(src->begin + cur);
- p ++;
- cur ++;
+ p++;
+ cur++;
}
dest->len += src->len;
/*
* Make copy of string to 0-terminated string
*/
-char*
-fstrcstr (f_str_t *str, memory_pool_t *pool)
+char *
+fstrcstr (f_str_t * str, memory_pool_t * pool)
{
- char *res;
+ char *res;
res = memory_pool_alloc (pool, str->len + 1);
memcpy (res, str->begin, str->len);
* Push one character to fstr
*/
int
-fstrpush (f_str_t *dest, char c)
+fstrpush (f_str_t * dest, char c)
{
if (dest->size < dest->len) {
/* Need to reallocate string */
}
*(dest->begin + dest->len) = c;
- dest->len ++;
+ dest->len++;
return 1;
}
/*
* Allocate memory for f_str_t
*/
-f_str_t*
-fstralloc (memory_pool_t *pool, size_t len)
+f_str_t *
+fstralloc (memory_pool_t * pool, size_t len)
{
- f_str_t *res = memory_pool_alloc (pool, sizeof (f_str_t));
+ f_str_t *res = memory_pool_alloc (pool, sizeof (f_str_t));
res->begin = memory_pool_alloc (pool, len);
res->size = len;
- res->len = 0;
+ res->len = 0;
return res;
}
/*
* Truncate string to its len
*/
-f_str_t*
-fstrtruncate (memory_pool_t *pool, f_str_t *orig)
+f_str_t *
+fstrtruncate (memory_pool_t * pool, f_str_t * orig)
{
- f_str_t *res;
+ f_str_t *res;
if (orig == NULL || orig->len == 0 || orig->size <= orig->len) {
return orig;
/*
* Enlarge string to new size
*/
-f_str_t*
-fstrgrow (memory_pool_t *pool, f_str_t *orig, size_t newlen)
+f_str_t *
+fstrgrow (memory_pool_t * pool, f_str_t * orig, size_t newlen)
{
- f_str_t *res;
+ f_str_t *res;
if (orig == NULL || orig->len == 0 || orig->size >= newlen) {
return orig;
* Return hash value for a string
*/
uint32_t
-fstrhash (f_str_t *str)
+fstrhash (f_str_t * str)
{
- size_t i;
- uint32_t hval;
- uint32_t tmp;
- char *c = str->begin;
+ size_t i;
+ uint32_t hval;
+ uint32_t tmp;
+ char *c = str->begin;
if (str == NULL) {
return 0;
}
hval = str->len;
- for (i = 0; i < str->len; i++, c++) {
+ for (i = 0; i < str->len; i++, c++) {
/*
* xor in the current byte against each byte of hval
* (which alone gaurantees that every bit of input will have
hval ^= tmp;
/* add some bits out of the middle as low order bits */
- hval = hval + ((hval >> 12) & 0x0000ffff) ;
+ hval = hval + ((hval >> 12) & 0x0000ffff);
/* swap most and min significative bytes */
tmp = (hval << 24) | ((hval >> 24) & 0xff);
}
void
-fstrstrip (f_str_t *str)
+fstrstrip (f_str_t * str)
{
- char *p = str->begin;
- int r = 0;
+ char *p = str->begin;
+ int r = 0;
while (r < str->len) {
if (g_ascii_isspace (*p)) {
- p ++;
- r ++;
+ p++;
+ r++;
}
else {
break;
}
}
-
+
if (r > 0) {
memmove (str->begin, p, str->len - r);
str->len -= r;
p = str->begin + str->len;
while (r > 0) {
if (g_ascii_isspace (*p)) {
- p --;
- r --;
+ p--;
+ r--;
}
else {
break;
#define HASH_INIT 0x28021967
struct roll_state {
- uint32_t h[3];
- char window[ROLL_WINDOW_SIZE];
- int n;
+ uint32_t h[3];
+ char window[ROLL_WINDOW_SIZE];
+ int n;
};
-static struct roll_state rs;
+static struct roll_state rs;
/* Rolling hash function based on Adler-32 checksum */
-static uint32_t
+static uint32_t
fuzzy_roll_hash (char c)
{
/* Check window position */
rs.h[1] -= rs.h[0];
rs.h[1] += ROLL_WINDOW_SIZE * c;
-
+
rs.h[0] += c;
rs.h[0] -= rs.window[rs.n];
-
+
/* Save current symbol */
rs.window[rs.n] = c;
- rs.n ++;
-
+ rs.n++;
+
rs.h[2] <<= 5;
rs.h[2] ^= c;
-
+
return rs.h[0] + rs.h[1] + rs.h[2];
}
/* A simple non-rolling hash, based on the FNV hash */
-static uint32_t
+static uint32_t
fuzzy_fnv_hash (char c, uint32_t hval)
{
hval ^= c;
- hval += (hval<<1) + (hval<<4) + (hval<<7) + (hval<<8) + (hval<<24);
+ hval += (hval << 1) + (hval << 4) + (hval << 7) + (hval << 8) + (hval << 24);
return hval;
}
/* Calculate blocksize depending on length of input */
-static uint32_t
-fuzzy_blocksize (uint32_t len)
+static uint32_t
+fuzzy_blocksize (uint32_t len)
{
-
+
if (len < MIN_FUZZY_BLOCK_SIZE) {
return MIN_FUZZY_BLOCK_SIZE;
}
/* Update hash with new symbol */
void
-fuzzy_update (fuzzy_hash_t *h, char c)
+fuzzy_update (fuzzy_hash_t * h, char c)
{
h->rh = fuzzy_roll_hash (c);
- h->h = fuzzy_fnv_hash(c, h->h);
-
+ h->h = fuzzy_fnv_hash (c, h->h);
+
if (h->rh % h->block_size == (h->block_size - 1)) {
h->hash_pipe[h->hi] = h->h;
if (h->hi < FUZZY_HASHLEN - 2) {
h->h = HASH_INIT;
- h->hi ++;
+ h->hi++;
}
}
}
*/
uint32_t
lev_distance (char *s1, int len1, char *s2, int len2)
-{
- int i;
- int *row; /* we only need to keep one row of costs */
- int *end;
- int half, nx;
- char *sx, *char2p, char1;
- int *p, D, x, offset, c3;
+{
+ int i;
+ int *row; /* we only need to keep one row of costs */
+ int *end;
+ int half, nx;
+ char *sx, *char2p, char1;
+ int *p, D, x, offset, c3;
/* strip common prefix */
while (len1 > 0 && len2 > 0 && *s1 == *s2) {
- len1 --;
- len2 --;
- s1 ++;
- s2 ++;
+ len1--;
+ len2--;
+ s1++;
+ s2++;
}
/* strip common suffix */
- while (len1 > 0 && len2 > 0 && s1[len1-1] == s2[len2-1]) {
+ while (len1 > 0 && len2 > 0 && s1[len1 - 1] == s2[len2 - 1]) {
len1--;
len2--;
}
return len2 - (memchr (s2, *s1, len2) != NULL);
}
- len1 ++;
- len2 ++;
+ len1++;
+ len2++;
half = len1 >> 1;
/* initalize first row */
- row = g_malloc (len2 * sizeof(int));
+ row = g_malloc (len2 * sizeof (int));
end = row + len2 - 1;
for (i = 0; i < len2; i++) {
row[i] = i;
}
/* Calculate fuzzy hash for specified string */
-fuzzy_hash_t *
-fuzzy_init (f_str_t *in, memory_pool_t *pool)
+fuzzy_hash_t *
+fuzzy_init (f_str_t * in, memory_pool_t * pool)
{
- fuzzy_hash_t *new;
- int i, repeats = 0;
- char *c = in->begin, last = '\0';
+ fuzzy_hash_t *new;
+ int i, repeats = 0;
+ char *c = in->begin, last = '\0';
new = memory_pool_alloc0 (pool, sizeof (fuzzy_hash_t));
bzero (&rs, sizeof (rs));
new->block_size = fuzzy_blocksize (in->len);
-
- for (i = 0; i < in->len; i ++) {
+
+ for (i = 0; i < in->len; i++) {
if (*c == last) {
- repeats ++;
+ repeats++;
}
else {
repeats = 0;
fuzzy_update (new, *c);
}
last = *c;
- c ++;
+ c++;
}
return new;
}
-fuzzy_hash_t *
-fuzzy_init_byte_array (GByteArray *in, memory_pool_t *pool)
+fuzzy_hash_t *
+fuzzy_init_byte_array (GByteArray * in, memory_pool_t * pool)
{
- f_str_t f;
+ f_str_t f;
f.begin = in->data;
f.len = in->len;
/* Compare score of difference between two hashes 0 - different hashes, 100 - identical hashes */
int
-fuzzy_compare_hashes (fuzzy_hash_t *h1, fuzzy_hash_t *h2)
+fuzzy_compare_hashes (fuzzy_hash_t * h1, fuzzy_hash_t * h2)
{
- int res, l1, l2;
+ int res, l1, l2;
/* If we have hashes of different size, input strings are too different */
if (h1->block_size != h2->block_size) {
return 0;
}
-
+
l1 = strlen (h1->hash_pipe);
l2 = strlen (h2->hash_pipe);
/* Number of insuccessfull bind retries */
#define MAX_RETRIES 40
-static GQueue *hashes[BUCKETS];
-static bloom_filter_t *bf;
+static GQueue *hashes[BUCKETS];
+static bloom_filter_t *bf;
/* Number of cache modifications */
-static uint32_t mods = 0;
+static uint32_t mods = 0;
/* For evtimer */
-static struct timeval tmv;
-static struct event tev;
+static struct timeval tmv;
+static struct event tev;
struct rspamd_fuzzy_node {
- fuzzy_hash_t h;
- uint64_t time;
+ fuzzy_hash_t h;
+ uint64_t time;
};
-static void
+static void
sig_handler (int signo)
-{
+{
switch (signo) {
- case SIGINT:
- /* Ignore SIGINT as we should got SIGTERM after it anyway */
- return;
- case SIGTERM:
+ case SIGINT:
+ /* Ignore SIGINT as we should got SIGTERM after it anyway */
+ return;
+ case SIGTERM:
#ifdef WITH_PROFILER
- exit (0);
+ exit (0);
#else
- _exit (1);
+ _exit (1);
#endif
- break;
+ break;
}
}
static void
sync_cache (struct rspamd_worker *wrk)
{
- int fd, i;
- char *filename, *exp_str;
- GList *cur, *tmp;
- struct rspamd_fuzzy_node *node;
- uint64_t expire, now;
-
+ int fd, i;
+ char *filename, *exp_str;
+ GList *cur, *tmp;
+ struct rspamd_fuzzy_node *node;
+ uint64_t expire, now;
+
/* Check for modifications */
if (mods < MOD_LIMIT) {
return;
}
-
+
msg_info ("sync_cache: syncing fuzzy hash storage");
filename = g_hash_table_lookup (wrk->cf->params, "hashfile");
if (filename == NULL) {
msg_err ("sync_cache: cannot create hash file %s: %s", filename, strerror (errno));
return;
}
-
- now = (uint64_t)time (NULL);
- for (i = 0; i < BUCKETS; i ++) {
+
+ now = (uint64_t) time (NULL);
+ for (i = 0; i < BUCKETS; i++) {
cur = hashes[i]->head;
while (cur) {
node = cur->data;
close (fd);
}
-static void
+static void
sigterm_handler (int fd, short what, void *arg)
{
- struct rspamd_worker *worker = (struct rspamd_worker *)arg;
- static struct timeval tv = {
+ struct rspamd_worker *worker = (struct rspamd_worker *)arg;
+ static struct timeval tv = {
.tv_sec = 0,
.tv_usec = 0,
};
-
+
mods = MOD_LIMIT + 1;
sync_cache (worker);
close (worker->cf->listen_sock);
static void
sigusr_handler (int fd, short what, void *arg)
{
- struct rspamd_worker *worker = (struct rspamd_worker *)arg;
+ struct rspamd_worker *worker = (struct rspamd_worker *)arg;
/* Do not accept new connections, preparing to end worker's process */
- struct timeval tv;
+ struct timeval tv;
tv.tv_sec = SOFT_SHUTDOWN_TIME;
tv.tv_usec = 0;
event_del (&worker->sig_ev);
return;
}
-static gboolean
+static gboolean
read_hashes_file (struct rspamd_worker *wrk)
{
- int r, fd, i;
- struct stat st;
- char *filename;
- struct rspamd_fuzzy_node *node;
+ int r, fd, i;
+ struct stat st;
+ char *filename;
+ struct rspamd_fuzzy_node *node;
- for (i = 0; i < BUCKETS; i ++) {
+ for (i = 0; i < BUCKETS; i++) {
hashes[i] = g_queue_new ();
}
msg_err ("read_hashes_file: cannot open hash file %s: %s", filename, strerror (errno));
return FALSE;
}
-
+
fstat (fd, &st);
-
+
for (;;) {
node = g_malloc (sizeof (struct rspamd_fuzzy_node));
r = read (fd, node, sizeof (struct rspamd_fuzzy_node));
if (r != sizeof (struct rspamd_fuzzy_node)) {
- break;
+ break;
}
g_queue_push_head (hashes[node->h.block_size % BUCKETS], node);
bloom_add (bf, node->h.hash_pipe);
return TRUE;
}
-static gboolean
+static gboolean
process_check_command (struct fuzzy_cmd *cmd)
{
- GList *cur;
- struct rspamd_fuzzy_node *h;
- fuzzy_hash_t s;
- int prob = 0;
-
+ GList *cur;
+ struct rspamd_fuzzy_node *h;
+ fuzzy_hash_t s;
+ int prob = 0;
+
if (!bloom_check (bf, cmd->hash)) {
- return FALSE;
+ return FALSE;
}
memcpy (s.hash_pipe, cmd->hash, sizeof (s.hash_pipe));
return FALSE;
}
-static gboolean
+static gboolean
process_write_command (struct fuzzy_cmd *cmd)
{
- struct rspamd_fuzzy_node *h;
+ struct rspamd_fuzzy_node *h;
if (bloom_check (bf, cmd->hash)) {
- return FALSE;
+ return FALSE;
}
h = g_malloc (sizeof (struct rspamd_fuzzy_node));
memcpy (&h->h.hash_pipe, &cmd->hash, sizeof (cmd->hash));
h->h.block_size = cmd->blocksize;
- h->time = (uint64_t)time (NULL);
+ h->time = (uint64_t) time (NULL);
g_queue_push_head (hashes[cmd->blocksize % BUCKETS], h);
bloom_add (bf, cmd->hash);
- mods ++;
+ mods++;
msg_info ("process_write_command: fuzzy hash was successfully added");
-
+
return TRUE;
}
-static gboolean
+static gboolean
process_delete_command (struct fuzzy_cmd *cmd)
{
- GList *cur, *tmp;
- struct rspamd_fuzzy_node *h;
- fuzzy_hash_t s;
- gboolean res = FALSE;
+ GList *cur, *tmp;
+ struct rspamd_fuzzy_node *h;
+ fuzzy_hash_t s;
+ gboolean res = FALSE;
if (!bloom_check (bf, cmd->hash)) {
- return FALSE;
+ return FALSE;
}
-
+
memcpy (s.hash_pipe, cmd->hash, sizeof (s.hash_pipe));
s.block_size = cmd->blocksize;
cur = hashes[cmd->blocksize % BUCKETS]->head;
bloom_del (bf, cmd->hash);
msg_info ("process_delete_command: fuzzy hash was successfully deleted");
res = TRUE;
- mods ++;
+ mods++;
continue;
}
cur = g_list_next (cur);
process_fuzzy_command (struct fuzzy_session *session)
{
switch (session->cmd.cmd) {
- case FUZZY_CHECK:
- CMD_PROCESS(check);
- break;
- case FUZZY_WRITE:
- CMD_PROCESS(write);
- break;
- case FUZZY_DEL:
- CMD_PROCESS(delete);
- break;
- default:
- if (sendto (session->fd, "ERR" CRLF, sizeof ("ERR" CRLF) - 1, 0, (struct sockaddr *)&session->sa, session->salen) == -1) {
- msg_err ("process_fuzzy_command: error while writing reply: %s", strerror (errno));
- }
- break;
+ case FUZZY_CHECK:
+ CMD_PROCESS (check);
+ break;
+ case FUZZY_WRITE:
+ CMD_PROCESS (write);
+ break;
+ case FUZZY_DEL:
+ CMD_PROCESS (delete);
+ break;
+ default:
+ if (sendto (session->fd, "ERR" CRLF, sizeof ("ERR" CRLF) - 1, 0, (struct sockaddr *)&session->sa, session->salen) == -1) {
+ msg_err ("process_fuzzy_command: error while writing reply: %s", strerror (errno));
+ }
+ break;
}
}
static void
accept_fuzzy_socket (int fd, short what, void *arg)
{
- struct rspamd_worker *worker = (struct rspamd_worker *)arg;
- struct fuzzy_session session;
- ssize_t r;
-
+ struct rspamd_worker *worker = (struct rspamd_worker *)arg;
+ struct fuzzy_session session;
+ ssize_t r;
+
session.worker = worker;
session.fd = fd;
- session.pos = (u_char *)&session.cmd;
+ session.pos = (u_char *) & session.cmd;
session.salen = sizeof (session.sa);
/* Got some data */
return;
}
}
-}
+}
static void
sync_callback (int fd, short what, void *arg)
{
- struct rspamd_worker *worker = (struct rspamd_worker *)arg;
- /* Timer event */
+ struct rspamd_worker *worker = (struct rspamd_worker *)arg;
+ /* Timer event */
evtimer_set (&tev, sync_callback, worker);
/* Plan event with jitter */
tmv.tv_sec = SYNC_TIMEOUT + SYNC_TIMEOUT * g_random_double ();
void
start_fuzzy_storage (struct rspamd_worker *worker)
{
- struct sigaction signals;
- struct event sev;
- int retries = 0;
+ struct sigaction signals;
+ struct event sev;
+ int retries = 0;
worker->srv->pid = getpid ();
worker->srv->type = TYPE_FUZZY;
sigprocmask (SIG_UNBLOCK, &signals.sa_mask, NULL);
/* SIGUSR2 handler */
- signal_set (&worker->sig_ev, SIGUSR2, sigusr_handler, (void *) worker);
+ signal_set (&worker->sig_ev, SIGUSR2, sigusr_handler, (void *)worker);
signal_add (&worker->sig_ev, NULL);
- signal_set (&sev, SIGTERM, sigterm_handler, (void *) worker);
+ signal_set (&sev, SIGTERM, sigterm_handler, (void *)worker);
signal_add (&sev, NULL);
/* Send SIGUSR2 to parent */
if (!read_hashes_file (worker)) {
msg_err ("read_hashes_file: cannot read hashes file, it can be created after save procedure");
}
- /* Timer event */
+ /* Timer event */
evtimer_set (&tev, sync_callback, worker);
/* Plan event with jitter */
tmv.tv_sec = SYNC_TIMEOUT + SYNC_TIMEOUT * g_random_double ();
exit (0);
}
}
- event_set(&worker->bind_ev, worker->cf->listen_sock, EV_READ | EV_PERSIST, accept_fuzzy_socket, (void *)worker);
- event_add(&worker->bind_ev, NULL);
+ event_set (&worker->bind_ev, worker->cf->listen_sock, EV_READ | EV_PERSIST, accept_fuzzy_socket, (void *)worker);
+ event_add (&worker->bind_ev, NULL);
gperf_profiler_init (worker->srv->cfg, "fuzzy");
event_loop (0);
exit (EXIT_SUCCESS);
}
-
* will use this function internally.
*/
static inline struct rspamd_hash_node **
-rspamd_hash_lookup_node (rspamd_hash_t *hash, gconstpointer key, guint *hash_return)
+rspamd_hash_lookup_node (rspamd_hash_t * hash, gconstpointer key, guint * hash_return)
{
- struct rspamd_hash_node **node_ptr, *node;
- guint hash_value;
- hash_value = (* hash->hash_func) (key);
+ struct rspamd_hash_node **node_ptr, *node;
+ guint hash_value;
+ hash_value = (*hash->hash_func) (key);
if (hash->shared) {
memory_pool_rlock_rwlock (hash->lock);
*hash_return = hash_value;
/* Hash table lookup needs to be fast.
- * We therefore remove the extra conditional of testing
- * whether to call the key_equal_func or not from
- * the inner loop.
- *
- * Additional optimisation: first check if our full hash
- * values are equal so we can avoid calling the full-blown
- * key equality function in most cases.
- */
+ * We therefore remove the extra conditional of testing
+ * whether to call the key_equal_func or not from
+ * the inner loop.
+ *
+ * Additional optimisation: first check if our full hash
+ * values are equal so we can avoid calling the full-blown
+ * key equality function in most cases.
+ */
if (hash->key_equal_func) {
while ((node = *node_ptr)) {
if (node->key_hash == hash_value && hash->key_equal_func (node->key, key)) {
- break;
+ break;
}
node_ptr = &(*node_ptr)->next;
}
- } else {
+ }
+ else {
while ((node = *node_ptr)) {
if (node->key == key) {
break;
* No table resize is performed.
*/
static void
-rspamd_hash_remove_node (rspamd_hash_t *hash, struct rspamd_hash_node ***node_ptr_ptr)
+rspamd_hash_remove_node (rspamd_hash_t * hash, struct rspamd_hash_node ***node_ptr_ptr)
{
- struct rspamd_hash_node **node_ptr, *node;
+ struct rspamd_hash_node **node_ptr, *node;
if (hash->shared) {
memory_pool_wlock_rwlock (hash->lock);
}
node_ptr = *node_ptr_ptr;
node = *node_ptr;
-
+
*node_ptr = node->next;
-
+
hash->nnodes--;
if (hash->shared) {
memory_pool_wunlock_rwlock (hash->lock);
* nodes currently held.
*/
static void
-rspamd_hash_resize (rspamd_hash_t *hash)
+rspamd_hash_resize (rspamd_hash_t * hash)
{
- struct rspamd_hash_node **new_nodes;
- struct rspamd_hash_node *node, *next;
- guint hash_val;
- gint new_size, i;
+ struct rspamd_hash_node **new_nodes;
+ struct rspamd_hash_node *node, *next;
+ guint hash_val;
+ gint new_size, i;
new_size = g_spaced_primes_closest (hash->nnodes);
new_size = CLAMP (new_size, HASH_TABLE_MIN_SIZE, HASH_TABLE_MAX_SIZE);
-
+
if (hash->shared) {
new_nodes = memory_pool_alloc_shared (hash->pool, sizeof (struct rspamd_hash_node *) * new_size);
- } else {
+ }
+ else {
new_nodes = memory_pool_alloc (hash->pool, sizeof (struct rspamd_hash_node *) * new_size);
}
* Resizes the hash table, if needed.
*/
static inline void
-rspamd_hash_maybe_resize (rspamd_hash_t *hash)
+rspamd_hash_maybe_resize (rspamd_hash_t * hash)
{
- gint nnodes = hash->nnodes;
- gint size = hash->size;
-
- if ((size >= 3 * nnodes && size > HASH_TABLE_MIN_SIZE) ||
- (3 * size <= nnodes && size < HASH_TABLE_MAX_SIZE)) {
+ gint nnodes = hash->nnodes;
+ gint size = hash->size;
+
+ if ((size >= 3 * nnodes && size > HASH_TABLE_MIN_SIZE) || (3 * size <= nnodes && size < HASH_TABLE_MAX_SIZE)) {
rspamd_hash_resize (hash);
}
}
/* Create new hash in specified pool */
-rspamd_hash_t*
-rspamd_hash_new (memory_pool_t *pool, GHashFunc hash_func, GEqualFunc key_equal_func)
+rspamd_hash_t *
+rspamd_hash_new (memory_pool_t * pool, GHashFunc hash_func, GEqualFunc key_equal_func)
{
- rspamd_hash_t* hash;
+ rspamd_hash_t *hash;
hash = memory_pool_alloc (pool, sizeof (rspamd_hash_t));
- hash->size = HASH_TABLE_MIN_SIZE;
- hash->nnodes = 0;
- hash->hash_func = hash_func ? hash_func : g_direct_hash;
- hash->key_equal_func = key_equal_func;
- hash->nodes = memory_pool_alloc0 (pool, sizeof (struct rspamd_hash_node*) * hash->size);
- hash->shared = 0;
- hash->pool = pool;
-
+ hash->size = HASH_TABLE_MIN_SIZE;
+ hash->nnodes = 0;
+ hash->hash_func = hash_func ? hash_func : g_direct_hash;
+ hash->key_equal_func = key_equal_func;
+ hash->nodes = memory_pool_alloc0 (pool, sizeof (struct rspamd_hash_node *) * hash->size);
+ hash->shared = 0;
+ hash->pool = pool;
+
return hash;
}
/*
* Create new hash in specified pool using shared memory
*/
-rspamd_hash_t*
-rspamd_hash_new_shared (memory_pool_t *pool, GHashFunc hash_func, GEqualFunc key_equal_func, gint size)
+rspamd_hash_t *
+rspamd_hash_new_shared (memory_pool_t * pool, GHashFunc hash_func, GEqualFunc key_equal_func, gint size)
{
- rspamd_hash_t* hash;
+ rspamd_hash_t *hash;
hash = memory_pool_alloc_shared (pool, sizeof (rspamd_hash_t));
- hash->size = size;
- hash->nnodes = 0;
- hash->hash_func = hash_func ? hash_func : g_direct_hash;
- hash->key_equal_func = key_equal_func;
- hash->nodes = memory_pool_alloc0_shared (pool, sizeof (struct rspamd_hash_node*) * hash->size);
- hash->shared = 1;
+ hash->size = size;
+ hash->nnodes = 0;
+ hash->hash_func = hash_func ? hash_func : g_direct_hash;
+ hash->key_equal_func = key_equal_func;
+ hash->nodes = memory_pool_alloc0_shared (pool, sizeof (struct rspamd_hash_node *) * hash->size);
+ hash->shared = 1;
/* Get mutex from pool for locking on insert/remove operations */
- hash->lock = memory_pool_get_rwlock (pool);
- hash->pool = pool;
-
+ hash->lock = memory_pool_get_rwlock (pool);
+ hash->pool = pool;
+
return hash;
}
/*
* Insert item in hash
*/
-void
-rspamd_hash_insert (rspamd_hash_t *hash, gpointer key, gpointer value)
+void
+rspamd_hash_insert (rspamd_hash_t * hash, gpointer key, gpointer value)
{
- struct rspamd_hash_node **node_ptr, *node;
- guint key_hash;
+ struct rspamd_hash_node **node_ptr, *node;
+ guint key_hash;
g_return_if_fail (hash != NULL);
- node_ptr = rspamd_hash_lookup_node (hash, key, &key_hash);
+ node_ptr = rspamd_hash_lookup_node (hash, key, &key_hash);
if (hash->shared) {
memory_pool_wlock_rwlock (hash->lock);
else {
node = memory_pool_alloc (hash->pool, sizeof (struct rspamd_hash_node));
}
-
+
node->key = key;
node->value = value;
node->key_hash = key_hash;
node->next = NULL;
-
+
*node_ptr = node;
- hash->nnodes ++;
- }
+ hash->nnodes++;
+ }
if (hash->shared) {
memory_pool_wunlock_rwlock (hash->lock);
}
-
+
if (!hash->shared) {
rspamd_hash_maybe_resize (hash);
}
/*
* Remove item from hash
*/
-gboolean
-rspamd_hash_remove (rspamd_hash_t *hash, gpointer key)
+gboolean
+rspamd_hash_remove (rspamd_hash_t * hash, gpointer key)
{
- struct rspamd_hash_node **node_ptr;
+ struct rspamd_hash_node **node_ptr;
g_return_val_if_fail (hash != NULL, FALSE);
/*
* Lookup item from hash
*/
-gpointer
-rspamd_hash_lookup (rspamd_hash_t *hash, gpointer key)
+gpointer
+rspamd_hash_lookup (rspamd_hash_t * hash, gpointer key)
{
- struct rspamd_hash_node *node;
+ struct rspamd_hash_node *node;
g_return_val_if_fail (hash != NULL, NULL);
-
+
node = *rspamd_hash_lookup_node (hash, key, NULL);
-
+
return node ? node->value : NULL;
}
/*
* Iterate throught hash
*/
-void
-rspamd_hash_foreach (rspamd_hash_t *hash, GHFunc func, gpointer user_data)
+void
+rspamd_hash_foreach (rspamd_hash_t * hash, GHFunc func, gpointer user_data)
{
- struct rspamd_hash_node *node;
- gint i;
-
+ struct rspamd_hash_node *node;
+ gint i;
+
g_return_if_fail (hash != NULL);
g_return_if_fail (func != NULL);
}
for (i = 0; i < hash->size; i++) {
for (node = hash->nodes[i]; node; node = node->next) {
- (* func) (node->key, node->value, user_data);
+ (*func) (node->key, node->value, user_data);
}
}
if (hash->shared) {
#include "html.h"
#include "url.h"
-sig_atomic_t tags_sorted = 0;
-
-static struct html_tag tag_defs[] =
-{
- /* W3C defined elements */
- { Tag_A, "a", (CM_INLINE)},
- { Tag_ABBR, "abbr", (CM_INLINE)},
- { Tag_ACRONYM, "acronym", (CM_INLINE)},
- { Tag_ADDRESS, "address", (CM_BLOCK)},
- { Tag_APPLET, "applet", (CM_OBJECT|CM_IMG|CM_INLINE|CM_PARAM)},
- { Tag_AREA, "area", (CM_BLOCK|CM_EMPTY)},
- { Tag_B, "b", (CM_INLINE)},
- { Tag_BASE, "base", (CM_HEAD|CM_EMPTY)},
- { Tag_BASEFONT, "basefont", (CM_INLINE|CM_EMPTY)},
- { Tag_BDO, "bdo", (CM_INLINE)},
- { Tag_BIG, "big", (CM_INLINE)},
- { Tag_BLOCKQUOTE, "blockquote", (CM_BLOCK)},
- { Tag_BODY, "body", (CM_HTML|CM_OPT|CM_OMITST)},
- { Tag_BR, "br", (CM_INLINE|CM_EMPTY)},
- { Tag_BUTTON, "button", (CM_INLINE)},
- { Tag_CAPTION, "caption", (CM_TABLE)},
- { Tag_CENTER, "center", (CM_BLOCK)},
- { Tag_CITE, "cite", (CM_INLINE)},
- { Tag_CODE, "code", (CM_INLINE)},
- { Tag_COL, "col", (CM_TABLE|CM_EMPTY)},
- { Tag_COLGROUP, "colgroup", (CM_TABLE|CM_OPT)},
- { Tag_DD, "dd", (CM_DEFLIST|CM_OPT|CM_NO_INDENT)},
- { Tag_DEL, "del", (CM_INLINE|CM_BLOCK|CM_MIXED)},
- { Tag_DFN, "dfn", (CM_INLINE)},
- { Tag_DIR, "dir", (CM_BLOCK|CM_OBSOLETE)},
- { Tag_DIV, "div", (CM_BLOCK)},
- { Tag_DL, "dl", (CM_BLOCK)},
- { Tag_DT, "dt", (CM_DEFLIST|CM_OPT|CM_NO_INDENT)},
- { Tag_EM, "em", (CM_INLINE)},
- { Tag_FIELDSET, "fieldset", (CM_BLOCK)},
- { Tag_FONT, "font", (CM_INLINE)},
- { Tag_FORM, "form", (CM_BLOCK)},
- { Tag_FRAME, "frame", (CM_FRAMES|CM_EMPTY)},
- { Tag_FRAMESET, "frameset", (CM_HTML|CM_FRAMES)},
- { Tag_H1, "h1", (CM_BLOCK|CM_HEADING)},
- { Tag_H2, "h2", (CM_BLOCK|CM_HEADING)},
- { Tag_H3, "h3", (CM_BLOCK|CM_HEADING)},
- { Tag_H4, "h4", (CM_BLOCK|CM_HEADING)},
- { Tag_H5, "h5", (CM_BLOCK|CM_HEADING)},
- { Tag_H6, "h6", (CM_BLOCK|CM_HEADING)},
- { Tag_HEAD, "head", (CM_HTML|CM_OPT|CM_OMITST)},
- { Tag_HR, "hr", (CM_BLOCK|CM_EMPTY)},
- { Tag_HTML, "html", (CM_HTML|CM_OPT|CM_OMITST)},
- { Tag_I, "i", (CM_INLINE)},
- { Tag_IFRAME, "iframe", (CM_INLINE)},
- { Tag_IMG, "img", (CM_INLINE|CM_IMG|CM_EMPTY)},
- { Tag_INPUT, "input", (CM_INLINE|CM_IMG|CM_EMPTY)},
- { Tag_INS, "ins", (CM_INLINE|CM_BLOCK|CM_MIXED)},
- { Tag_ISINDEX, "isindex", (CM_BLOCK|CM_EMPTY)},
- { Tag_KBD, "kbd", (CM_INLINE)},
- { Tag_LABEL, "label", (CM_INLINE)},
- { Tag_LEGEND, "legend", (CM_INLINE)},
- { Tag_LI, "li", (CM_LIST|CM_OPT|CM_NO_INDENT)},
- { Tag_LINK, "link", (CM_HEAD|CM_EMPTY)},
- { Tag_LISTING, "listing", (CM_BLOCK|CM_OBSOLETE)},
- { Tag_MAP, "map", (CM_INLINE)},
- { Tag_MENU, "menu", (CM_BLOCK|CM_OBSOLETE)},
- { Tag_META, "meta", (CM_HEAD|CM_EMPTY)},
- { Tag_NOFRAMES, "noframes", (CM_BLOCK|CM_FRAMES)},
- { Tag_NOSCRIPT, "noscript", (CM_BLOCK|CM_INLINE|CM_MIXED)},
- { Tag_OBJECT, "object", (CM_OBJECT|CM_HEAD|CM_IMG|CM_INLINE|CM_PARAM)},
- { Tag_OL, "ol", (CM_BLOCK)},
- { Tag_OPTGROUP, "optgroup", (CM_FIELD|CM_OPT)},
- { Tag_OPTION, "option", (CM_FIELD|CM_OPT)},
- { Tag_P, "p", (CM_BLOCK|CM_OPT)},
- { Tag_PARAM, "param", (CM_INLINE|CM_EMPTY)},
- { Tag_PLAINTEXT, "plaintext", (CM_BLOCK|CM_OBSOLETE)},
- { Tag_PRE, "pre", (CM_BLOCK)},
- { Tag_Q, "q", (CM_INLINE)},
- { Tag_RB, "rb", (CM_INLINE)},
- { Tag_RBC, "rbc", (CM_INLINE)},
- { Tag_RP, "rp", (CM_INLINE)},
- { Tag_RT, "rt", (CM_INLINE)},
- { Tag_RTC, "rtc", (CM_INLINE)},
- { Tag_RUBY, "ruby", (CM_INLINE)},
- { Tag_S, "s", (CM_INLINE)},
- { Tag_SAMP, "samp", (CM_INLINE)},
- { Tag_SCRIPT, "script", (CM_HEAD|CM_MIXED|CM_BLOCK|CM_INLINE)},
- { Tag_SELECT, "select", (CM_INLINE|CM_FIELD)},
- { Tag_SMALL, "small", (CM_INLINE)},
- { Tag_SPAN, "span", (CM_INLINE)},
- { Tag_STRIKE, "strike", (CM_INLINE)},
- { Tag_STRONG, "strong", (CM_INLINE)},
- { Tag_STYLE, "style", (CM_HEAD)},
- { Tag_SUB, "sub", (CM_INLINE)},
- { Tag_SUP, "sup", (CM_INLINE)},
- { Tag_TABLE, "table", (CM_BLOCK)},
- { Tag_TBODY, "tbody", (CM_TABLE|CM_ROWGRP|CM_OPT)},
- { Tag_TD, "td", (CM_ROW|CM_OPT|CM_NO_INDENT)},
- { Tag_TEXTAREA, "textarea", (CM_INLINE|CM_FIELD)},
- { Tag_TFOOT, "tfoot", (CM_TABLE|CM_ROWGRP|CM_OPT)},
- { Tag_TH, "th", (CM_ROW|CM_OPT|CM_NO_INDENT)},
- { Tag_THEAD, "thead", (CM_TABLE|CM_ROWGRP|CM_OPT)},
- { Tag_TITLE, "title", (CM_HEAD)},
- { Tag_TR, "tr", (CM_TABLE|CM_OPT)},
- { Tag_TT, "tt", (CM_INLINE)},
- { Tag_U, "u", (CM_INLINE)},
- { Tag_UL, "ul", (CM_BLOCK)},
- { Tag_VAR, "var", (CM_INLINE)},
- { Tag_XMP, "xmp", (CM_BLOCK|CM_OBSOLETE)},
- { Tag_NEXTID, "nextid", (CM_HEAD|CM_EMPTY)},
-
- /* proprietary elements */
- { Tag_ALIGN, "align", (CM_BLOCK)},
- { Tag_BGSOUND, "bgsound", (CM_HEAD|CM_EMPTY)},
- { Tag_BLINK, "blink", (CM_INLINE)},
- { Tag_COMMENT, "comment", (CM_INLINE)},
- { Tag_EMBED, "embed", (CM_INLINE|CM_IMG|CM_EMPTY)},
- { Tag_ILAYER, "ilayer", (CM_INLINE)},
- { Tag_KEYGEN, "keygen", (CM_INLINE|CM_EMPTY)},
- { Tag_LAYER, "layer", (CM_BLOCK)},
- { Tag_MARQUEE, "marquee", (CM_INLINE|CM_OPT)},
- { Tag_MULTICOL, "multicol", (CM_BLOCK)},
- { Tag_NOBR, "nobr", (CM_INLINE)},
- { Tag_NOEMBED, "noembed", (CM_INLINE)},
- { Tag_NOLAYER, "nolayer", (CM_BLOCK|CM_INLINE|CM_MIXED)},
- { Tag_NOSAVE, "nosave", (CM_BLOCK)},
- { Tag_SERVER, "server", (CM_HEAD|CM_MIXED|CM_BLOCK|CM_INLINE)},
- { Tag_SERVLET, "servlet", (CM_OBJECT|CM_IMG|CM_INLINE|CM_PARAM)},
- { Tag_SPACER, "spacer", (CM_INLINE|CM_EMPTY)},
- { Tag_WBR, "wbr", (CM_INLINE|CM_EMPTY)},
+sig_atomic_t tags_sorted = 0;
+
+static struct html_tag tag_defs[] = {
+ /* W3C defined elements */
+ {Tag_A, "a", (CM_INLINE)},
+ {Tag_ABBR, "abbr", (CM_INLINE)},
+ {Tag_ACRONYM, "acronym", (CM_INLINE)},
+ {Tag_ADDRESS, "address", (CM_BLOCK)},
+ {Tag_APPLET, "applet", (CM_OBJECT | CM_IMG | CM_INLINE | CM_PARAM)},
+ {Tag_AREA, "area", (CM_BLOCK | CM_EMPTY)},
+ {Tag_B, "b", (CM_INLINE)},
+ {Tag_BASE, "base", (CM_HEAD | CM_EMPTY)},
+ {Tag_BASEFONT, "basefont", (CM_INLINE | CM_EMPTY)},
+ {Tag_BDO, "bdo", (CM_INLINE)},
+ {Tag_BIG, "big", (CM_INLINE)},
+ {Tag_BLOCKQUOTE, "blockquote", (CM_BLOCK)},
+ {Tag_BODY, "body", (CM_HTML | CM_OPT | CM_OMITST)},
+ {Tag_BR, "br", (CM_INLINE | CM_EMPTY)},
+ {Tag_BUTTON, "button", (CM_INLINE)},
+ {Tag_CAPTION, "caption", (CM_TABLE)},
+ {Tag_CENTER, "center", (CM_BLOCK)},
+ {Tag_CITE, "cite", (CM_INLINE)},
+ {Tag_CODE, "code", (CM_INLINE)},
+ {Tag_COL, "col", (CM_TABLE | CM_EMPTY)},
+ {Tag_COLGROUP, "colgroup", (CM_TABLE | CM_OPT)},
+ {Tag_DD, "dd", (CM_DEFLIST | CM_OPT | CM_NO_INDENT)},
+ {Tag_DEL, "del", (CM_INLINE | CM_BLOCK | CM_MIXED)},
+ {Tag_DFN, "dfn", (CM_INLINE)},
+ {Tag_DIR, "dir", (CM_BLOCK | CM_OBSOLETE)},
+ {Tag_DIV, "div", (CM_BLOCK)},
+ {Tag_DL, "dl", (CM_BLOCK)},
+ {Tag_DT, "dt", (CM_DEFLIST | CM_OPT | CM_NO_INDENT)},
+ {Tag_EM, "em", (CM_INLINE)},
+ {Tag_FIELDSET, "fieldset", (CM_BLOCK)},
+ {Tag_FONT, "font", (CM_INLINE)},
+ {Tag_FORM, "form", (CM_BLOCK)},
+ {Tag_FRAME, "frame", (CM_FRAMES | CM_EMPTY)},
+ {Tag_FRAMESET, "frameset", (CM_HTML | CM_FRAMES)},
+ {Tag_H1, "h1", (CM_BLOCK | CM_HEADING)},
+ {Tag_H2, "h2", (CM_BLOCK | CM_HEADING)},
+ {Tag_H3, "h3", (CM_BLOCK | CM_HEADING)},
+ {Tag_H4, "h4", (CM_BLOCK | CM_HEADING)},
+ {Tag_H5, "h5", (CM_BLOCK | CM_HEADING)},
+ {Tag_H6, "h6", (CM_BLOCK | CM_HEADING)},
+ {Tag_HEAD, "head", (CM_HTML | CM_OPT | CM_OMITST)},
+ {Tag_HR, "hr", (CM_BLOCK | CM_EMPTY)},
+ {Tag_HTML, "html", (CM_HTML | CM_OPT | CM_OMITST)},
+ {Tag_I, "i", (CM_INLINE)},
+ {Tag_IFRAME, "iframe", (CM_INLINE)},
+ {Tag_IMG, "img", (CM_INLINE | CM_IMG | CM_EMPTY)},
+ {Tag_INPUT, "input", (CM_INLINE | CM_IMG | CM_EMPTY)},
+ {Tag_INS, "ins", (CM_INLINE | CM_BLOCK | CM_MIXED)},
+ {Tag_ISINDEX, "isindex", (CM_BLOCK | CM_EMPTY)},
+ {Tag_KBD, "kbd", (CM_INLINE)},
+ {Tag_LABEL, "label", (CM_INLINE)},
+ {Tag_LEGEND, "legend", (CM_INLINE)},
+ {Tag_LI, "li", (CM_LIST | CM_OPT | CM_NO_INDENT)},
+ {Tag_LINK, "link", (CM_HEAD | CM_EMPTY)},
+ {Tag_LISTING, "listing", (CM_BLOCK | CM_OBSOLETE)},
+ {Tag_MAP, "map", (CM_INLINE)},
+ {Tag_MENU, "menu", (CM_BLOCK | CM_OBSOLETE)},
+ {Tag_META, "meta", (CM_HEAD | CM_EMPTY)},
+ {Tag_NOFRAMES, "noframes", (CM_BLOCK | CM_FRAMES)},
+ {Tag_NOSCRIPT, "noscript", (CM_BLOCK | CM_INLINE | CM_MIXED)},
+ {Tag_OBJECT, "object", (CM_OBJECT | CM_HEAD | CM_IMG | CM_INLINE | CM_PARAM)},
+ {Tag_OL, "ol", (CM_BLOCK)},
+ {Tag_OPTGROUP, "optgroup", (CM_FIELD | CM_OPT)},
+ {Tag_OPTION, "option", (CM_FIELD | CM_OPT)},
+ {Tag_P, "p", (CM_BLOCK | CM_OPT)},
+ {Tag_PARAM, "param", (CM_INLINE | CM_EMPTY)},
+ {Tag_PLAINTEXT, "plaintext", (CM_BLOCK | CM_OBSOLETE)},
+ {Tag_PRE, "pre", (CM_BLOCK)},
+ {Tag_Q, "q", (CM_INLINE)},
+ {Tag_RB, "rb", (CM_INLINE)},
+ {Tag_RBC, "rbc", (CM_INLINE)},
+ {Tag_RP, "rp", (CM_INLINE)},
+ {Tag_RT, "rt", (CM_INLINE)},
+ {Tag_RTC, "rtc", (CM_INLINE)},
+ {Tag_RUBY, "ruby", (CM_INLINE)},
+ {Tag_S, "s", (CM_INLINE)},
+ {Tag_SAMP, "samp", (CM_INLINE)},
+ {Tag_SCRIPT, "script", (CM_HEAD | CM_MIXED | CM_BLOCK | CM_INLINE)},
+ {Tag_SELECT, "select", (CM_INLINE | CM_FIELD)},
+ {Tag_SMALL, "small", (CM_INLINE)},
+ {Tag_SPAN, "span", (CM_INLINE)},
+ {Tag_STRIKE, "strike", (CM_INLINE)},
+ {Tag_STRONG, "strong", (CM_INLINE)},
+ {Tag_STYLE, "style", (CM_HEAD)},
+ {Tag_SUB, "sub", (CM_INLINE)},
+ {Tag_SUP, "sup", (CM_INLINE)},
+ {Tag_TABLE, "table", (CM_BLOCK)},
+ {Tag_TBODY, "tbody", (CM_TABLE | CM_ROWGRP | CM_OPT)},
+ {Tag_TD, "td", (CM_ROW | CM_OPT | CM_NO_INDENT)},
+ {Tag_TEXTAREA, "textarea", (CM_INLINE | CM_FIELD)},
+ {Tag_TFOOT, "tfoot", (CM_TABLE | CM_ROWGRP | CM_OPT)},
+ {Tag_TH, "th", (CM_ROW | CM_OPT | CM_NO_INDENT)},
+ {Tag_THEAD, "thead", (CM_TABLE | CM_ROWGRP | CM_OPT)},
+ {Tag_TITLE, "title", (CM_HEAD)},
+ {Tag_TR, "tr", (CM_TABLE | CM_OPT)},
+ {Tag_TT, "tt", (CM_INLINE)},
+ {Tag_U, "u", (CM_INLINE)},
+ {Tag_UL, "ul", (CM_BLOCK)},
+ {Tag_VAR, "var", (CM_INLINE)},
+ {Tag_XMP, "xmp", (CM_BLOCK | CM_OBSOLETE)},
+ {Tag_NEXTID, "nextid", (CM_HEAD | CM_EMPTY)},
+
+ /* proprietary elements */
+ {Tag_ALIGN, "align", (CM_BLOCK)},
+ {Tag_BGSOUND, "bgsound", (CM_HEAD | CM_EMPTY)},
+ {Tag_BLINK, "blink", (CM_INLINE)},
+ {Tag_COMMENT, "comment", (CM_INLINE)},
+ {Tag_EMBED, "embed", (CM_INLINE | CM_IMG | CM_EMPTY)},
+ {Tag_ILAYER, "ilayer", (CM_INLINE)},
+ {Tag_KEYGEN, "keygen", (CM_INLINE | CM_EMPTY)},
+ {Tag_LAYER, "layer", (CM_BLOCK)},
+ {Tag_MARQUEE, "marquee", (CM_INLINE | CM_OPT)},
+ {Tag_MULTICOL, "multicol", (CM_BLOCK)},
+ {Tag_NOBR, "nobr", (CM_INLINE)},
+ {Tag_NOEMBED, "noembed", (CM_INLINE)},
+ {Tag_NOLAYER, "nolayer", (CM_BLOCK | CM_INLINE | CM_MIXED)},
+ {Tag_NOSAVE, "nosave", (CM_BLOCK)},
+ {Tag_SERVER, "server", (CM_HEAD | CM_MIXED | CM_BLOCK | CM_INLINE)},
+ {Tag_SERVLET, "servlet", (CM_OBJECT | CM_IMG | CM_INLINE | CM_PARAM)},
+ {Tag_SPACER, "spacer", (CM_INLINE | CM_EMPTY)},
+ {Tag_WBR, "wbr", (CM_INLINE | CM_EMPTY)},
};
-sig_atomic_t entities_sorted = 0;
+sig_atomic_t entities_sorted = 0;
struct _entity;
-typedef struct _entity entity;
+typedef struct _entity entity;
-struct _entity
-{
- char *name;
- uint code;
+struct _entity {
+ char *name;
+ uint code;
};
-static entity entities_defs[] =
-{
- /*
- ** Markup pre-defined character entities
- */
- { "quot", 34 },
- { "amp", 38 },
- { "apos", 39 },
- { "lt", 60 },
- { "gt", 62 },
-
- /*
- ** Latin-1 character entities
- */
- { "nbsp", 160 },
- { "iexcl", 161 },
- { "cent", 162 },
- { "pound", 163 },
- { "curren", 164 },
- { "yen", 165 },
- { "brvbar", 166 },
- { "sect", 167 },
- { "uml", 168 },
- { "copy", 169 },
- { "ordf", 170 },
- { "laquo", 171 },
- { "not", 172 },
- { "shy", 173 },
- { "reg", 174 },
- { "macr", 175 },
- { "deg", 176 },
- { "plusmn", 177 },
- { "sup2", 178 },
- { "sup3", 179 },
- { "acute", 180 },
- { "micro", 181 },
- { "para", 182 },
- { "middot", 183 },
- { "cedil", 184 },
- { "sup1", 185 },
- { "ordm", 186 },
- { "raquo", 187 },
- { "frac14", 188 },
- { "frac12", 189 },
- { "frac34", 190 },
- { "iquest", 191 },
- { "Agrave", 192 },
- { "Aacute", 193 },
- { "Acirc", 194 },
- { "Atilde", 195 },
- { "Auml", 196 },
- { "Aring", 197 },
- { "AElig", 198 },
- { "Ccedil", 199 },
- { "Egrave", 200 },
- { "Eacute", 201 },
- { "Ecirc", 202 },
- { "Euml", 203 },
- { "Igrave", 204 },
- { "Iacute", 205 },
- { "Icirc", 206 },
- { "Iuml", 207 },
- { "ETH", 208 },
- { "Ntilde", 209 },
- { "Ograve", 210 },
- { "Oacute", 211 },
- { "Ocirc", 212 },
- { "Otilde", 213 },
- { "Ouml", 214 },
- { "times", 215 },
- { "Oslash", 216 },
- { "Ugrave", 217 },
- { "Uacute", 218 },
- { "Ucirc", 219 },
- { "Uuml", 220 },
- { "Yacute", 221 },
- { "THORN", 222 },
- { "szlig", 223 },
- { "agrave", 224 },
- { "aacute", 225 },
- { "acirc", 226 },
- { "atilde", 227 },
- { "auml", 228 },
- { "aring", 229 },
- { "aelig", 230 },
- { "ccedil", 231 },
- { "egrave", 232 },
- { "eacute", 233 },
- { "ecirc", 234 },
- { "euml", 235 },
- { "igrave", 236 },
- { "iacute", 237 },
- { "icirc", 238 },
- { "iuml", 239 },
- { "eth", 240 },
- { "ntilde", 241 },
- { "ograve", 242 },
- { "oacute", 243 },
- { "ocirc", 244 },
- { "otilde", 245 },
- { "ouml", 246 },
- { "divide", 247 },
- { "oslash", 248 },
- { "ugrave", 249 },
- { "uacute", 250 },
- { "ucirc", 251 },
- { "uuml", 252 },
- { "yacute", 253 },
- { "thorn", 254 },
- { "yuml", 255 },
-
- /*
- ** Extended Entities defined in HTML 4: Symbols
- */
- { "fnof", 402 },
- { "Alpha", 913 },
- { "Beta", 914 },
- { "Gamma", 915 },
- { "Delta", 916 },
- { "Epsilon", 917 },
- { "Zeta", 918 },
- { "Eta", 919 },
- { "Theta", 920 },
- { "Iota", 921 },
- { "Kappa", 922 },
- { "Lambda", 923 },
- { "Mu", 924 },
- { "Nu", 925 },
- { "Xi", 926 },
- { "Omicron", 927 },
- { "Pi", 928 },
- { "Rho", 929 },
- { "Sigma", 931 },
- { "Tau", 932 },
- { "Upsilon", 933 },
- { "Phi", 934 },
- { "Chi", 935 },
- { "Psi", 936 },
- { "Omega", 937 },
- { "alpha", 945 },
- { "beta", 946 },
- { "gamma", 947 },
- { "delta", 948 },
- { "epsilon", 949 },
- { "zeta", 950 },
- { "eta", 951 },
- { "theta", 952 },
- { "iota", 953 },
- { "kappa", 954 },
- { "lambda", 955 },
- { "mu", 956 },
- { "nu", 957 },
- { "xi", 958 },
- { "omicron", 959 },
- { "pi", 960 },
- { "rho", 961 },
- { "sigmaf", 962 },
- { "sigma", 963 },
- { "tau", 964 },
- { "upsilon", 965 },
- { "phi", 966 },
- { "chi", 967 },
- { "psi", 968 },
- { "omega", 969 },
- { "thetasym", 977 },
- { "upsih", 978 },
- { "piv", 982 },
- { "bull", 8226 },
- { "hellip", 8230 },
- { "prime", 8242 },
- { "Prime", 8243 },
- { "oline", 8254 },
- { "frasl", 8260 },
- { "weierp", 8472 },
- { "image", 8465 },
- { "real", 8476 },
- { "trade", 8482 },
- { "alefsym", 8501 },
- { "larr", 8592 },
- { "uarr", 8593 },
- { "rarr", 8594 },
- { "darr", 8595 },
- { "harr", 8596 },
- { "crarr", 8629 },
- { "lArr", 8656 },
- { "uArr", 8657 },
- { "rArr", 8658 },
- { "dArr", 8659 },
- { "hArr", 8660 },
- { "forall", 8704 },
- { "part", 8706 },
- { "exist", 8707 },
- { "empty", 8709 },
- { "nabla", 8711 },
- { "isin", 8712 },
- { "notin", 8713 },
- { "ni", 8715 },
- { "prod", 8719 },
- { "sum", 8721 },
- { "minus", 8722 },
- { "lowast", 8727 },
- { "radic", 8730 },
- { "prop", 8733 },
- { "infin", 8734 },
- { "ang", 8736 },
- { "and", 8743 },
- { "or", 8744 },
- { "cap", 8745 },
- { "cup", 8746 },
- { "int", 8747 },
- { "there4", 8756 },
- { "sim", 8764 },
- { "cong", 8773 },
- { "asymp", 8776 },
- { "ne", 8800 },
- { "equiv", 8801 },
- { "le", 8804 },
- { "ge", 8805 },
- { "sub", 8834 },
- { "sup", 8835 },
- { "nsub", 8836 },
- { "sube", 8838 },
- { "supe", 8839 },
- { "oplus", 8853 },
- { "otimes", 8855 },
- { "perp", 8869 },
- { "sdot", 8901 },
- { "lceil", 8968 },
- { "rceil", 8969 },
- { "lfloor", 8970 },
- { "rfloor", 8971 },
- { "lang", 9001 },
- { "rang", 9002 },
- { "loz", 9674 },
- { "spades", 9824 },
- { "clubs", 9827 },
- { "hearts", 9829 },
- { "diams", 9830 },
-
- /*
- ** Extended Entities defined in HTML 4: Special (less Markup at top)
- */
- { "OElig", 338 },
- { "oelig", 339 },
- { "Scaron", 352 },
- { "scaron", 353 },
- { "Yuml", 376 },
- { "circ", 710 },
- { "tilde", 732 },
- { "ensp", 8194 },
- { "emsp", 8195 },
- { "thinsp", 8201 },
- { "zwnj", 8204 },
- { "zwj", 8205 },
- { "lrm", 8206 },
- { "rlm", 8207 },
- { "ndash", 8211 },
- { "mdash", 8212 },
- { "lsquo", 8216 },
- { "rsquo", 8217 },
- { "sbquo", 8218 },
- { "ldquo", 8220 },
- { "rdquo", 8221 },
- { "bdquo", 8222 },
- { "dagger", 8224 },
- { "Dagger", 8225 },
- { "permil", 8240 },
- { "lsaquo", 8249 },
- { "rsaquo", 8250 },
- { "euro", 8364 },
+static entity entities_defs[] = {
+ /*
+ ** Markup pre-defined character entities
+ */
+ {"quot", 34},
+ {"amp", 38},
+ {"apos", 39},
+ {"lt", 60},
+ {"gt", 62},
+
+ /*
+ ** Latin-1 character entities
+ */
+ {"nbsp", 160},
+ {"iexcl", 161},
+ {"cent", 162},
+ {"pound", 163},
+ {"curren", 164},
+ {"yen", 165},
+ {"brvbar", 166},
+ {"sect", 167},
+ {"uml", 168},
+ {"copy", 169},
+ {"ordf", 170},
+ {"laquo", 171},
+ {"not", 172},
+ {"shy", 173},
+ {"reg", 174},
+ {"macr", 175},
+ {"deg", 176},
+ {"plusmn", 177},
+ {"sup2", 178},
+ {"sup3", 179},
+ {"acute", 180},
+ {"micro", 181},
+ {"para", 182},
+ {"middot", 183},
+ {"cedil", 184},
+ {"sup1", 185},
+ {"ordm", 186},
+ {"raquo", 187},
+ {"frac14", 188},
+ {"frac12", 189},
+ {"frac34", 190},
+ {"iquest", 191},
+ {"Agrave", 192},
+ {"Aacute", 193},
+ {"Acirc", 194},
+ {"Atilde", 195},
+ {"Auml", 196},
+ {"Aring", 197},
+ {"AElig", 198},
+ {"Ccedil", 199},
+ {"Egrave", 200},
+ {"Eacute", 201},
+ {"Ecirc", 202},
+ {"Euml", 203},
+ {"Igrave", 204},
+ {"Iacute", 205},
+ {"Icirc", 206},
+ {"Iuml", 207},
+ {"ETH", 208},
+ {"Ntilde", 209},
+ {"Ograve", 210},
+ {"Oacute", 211},
+ {"Ocirc", 212},
+ {"Otilde", 213},
+ {"Ouml", 214},
+ {"times", 215},
+ {"Oslash", 216},
+ {"Ugrave", 217},
+ {"Uacute", 218},
+ {"Ucirc", 219},
+ {"Uuml", 220},
+ {"Yacute", 221},
+ {"THORN", 222},
+ {"szlig", 223},
+ {"agrave", 224},
+ {"aacute", 225},
+ {"acirc", 226},
+ {"atilde", 227},
+ {"auml", 228},
+ {"aring", 229},
+ {"aelig", 230},
+ {"ccedil", 231},
+ {"egrave", 232},
+ {"eacute", 233},
+ {"ecirc", 234},
+ {"euml", 235},
+ {"igrave", 236},
+ {"iacute", 237},
+ {"icirc", 238},
+ {"iuml", 239},
+ {"eth", 240},
+ {"ntilde", 241},
+ {"ograve", 242},
+ {"oacute", 243},
+ {"ocirc", 244},
+ {"otilde", 245},
+ {"ouml", 246},
+ {"divide", 247},
+ {"oslash", 248},
+ {"ugrave", 249},
+ {"uacute", 250},
+ {"ucirc", 251},
+ {"uuml", 252},
+ {"yacute", 253},
+ {"thorn", 254},
+ {"yuml", 255},
+
+ /*
+ ** Extended Entities defined in HTML 4: Symbols
+ */
+ {"fnof", 402},
+ {"Alpha", 913},
+ {"Beta", 914},
+ {"Gamma", 915},
+ {"Delta", 916},
+ {"Epsilon", 917},
+ {"Zeta", 918},
+ {"Eta", 919},
+ {"Theta", 920},
+ {"Iota", 921},
+ {"Kappa", 922},
+ {"Lambda", 923},
+ {"Mu", 924},
+ {"Nu", 925},
+ {"Xi", 926},
+ {"Omicron", 927},
+ {"Pi", 928},
+ {"Rho", 929},
+ {"Sigma", 931},
+ {"Tau", 932},
+ {"Upsilon", 933},
+ {"Phi", 934},
+ {"Chi", 935},
+ {"Psi", 936},
+ {"Omega", 937},
+ {"alpha", 945},
+ {"beta", 946},
+ {"gamma", 947},
+ {"delta", 948},
+ {"epsilon", 949},
+ {"zeta", 950},
+ {"eta", 951},
+ {"theta", 952},
+ {"iota", 953},
+ {"kappa", 954},
+ {"lambda", 955},
+ {"mu", 956},
+ {"nu", 957},
+ {"xi", 958},
+ {"omicron", 959},
+ {"pi", 960},
+ {"rho", 961},
+ {"sigmaf", 962},
+ {"sigma", 963},
+ {"tau", 964},
+ {"upsilon", 965},
+ {"phi", 966},
+ {"chi", 967},
+ {"psi", 968},
+ {"omega", 969},
+ {"thetasym", 977},
+ {"upsih", 978},
+ {"piv", 982},
+ {"bull", 8226},
+ {"hellip", 8230},
+ {"prime", 8242},
+ {"Prime", 8243},
+ {"oline", 8254},
+ {"frasl", 8260},
+ {"weierp", 8472},
+ {"image", 8465},
+ {"real", 8476},
+ {"trade", 8482},
+ {"alefsym", 8501},
+ {"larr", 8592},
+ {"uarr", 8593},
+ {"rarr", 8594},
+ {"darr", 8595},
+ {"harr", 8596},
+ {"crarr", 8629},
+ {"lArr", 8656},
+ {"uArr", 8657},
+ {"rArr", 8658},
+ {"dArr", 8659},
+ {"hArr", 8660},
+ {"forall", 8704},
+ {"part", 8706},
+ {"exist", 8707},
+ {"empty", 8709},
+ {"nabla", 8711},
+ {"isin", 8712},
+ {"notin", 8713},
+ {"ni", 8715},
+ {"prod", 8719},
+ {"sum", 8721},
+ {"minus", 8722},
+ {"lowast", 8727},
+ {"radic", 8730},
+ {"prop", 8733},
+ {"infin", 8734},
+ {"ang", 8736},
+ {"and", 8743},
+ {"or", 8744},
+ {"cap", 8745},
+ {"cup", 8746},
+ {"int", 8747},
+ {"there4", 8756},
+ {"sim", 8764},
+ {"cong", 8773},
+ {"asymp", 8776},
+ {"ne", 8800},
+ {"equiv", 8801},
+ {"le", 8804},
+ {"ge", 8805},
+ {"sub", 8834},
+ {"sup", 8835},
+ {"nsub", 8836},
+ {"sube", 8838},
+ {"supe", 8839},
+ {"oplus", 8853},
+ {"otimes", 8855},
+ {"perp", 8869},
+ {"sdot", 8901},
+ {"lceil", 8968},
+ {"rceil", 8969},
+ {"lfloor", 8970},
+ {"rfloor", 8971},
+ {"lang", 9001},
+ {"rang", 9002},
+ {"loz", 9674},
+ {"spades", 9824},
+ {"clubs", 9827},
+ {"hearts", 9829},
+ {"diams", 9830},
+
+ /*
+ ** Extended Entities defined in HTML 4: Special (less Markup at top)
+ */
+ {"OElig", 338},
+ {"oelig", 339},
+ {"Scaron", 352},
+ {"scaron", 353},
+ {"Yuml", 376},
+ {"circ", 710},
+ {"tilde", 732},
+ {"ensp", 8194},
+ {"emsp", 8195},
+ {"thinsp", 8201},
+ {"zwnj", 8204},
+ {"zwj", 8205},
+ {"lrm", 8206},
+ {"rlm", 8207},
+ {"ndash", 8211},
+ {"mdash", 8212},
+ {"lsquo", 8216},
+ {"rsquo", 8217},
+ {"sbquo", 8218},
+ {"ldquo", 8220},
+ {"rdquo", 8221},
+ {"bdquo", 8222},
+ {"dagger", 8224},
+ {"Dagger", 8225},
+ {"permil", 8240},
+ {"lsaquo", 8249},
+ {"rsaquo", 8250},
+ {"euro", 8364},
};
static int
tag_cmp (const void *m1, const void *m2)
{
- const struct html_tag *p1 = m1;
- const struct html_tag *p2 = m2;
+ const struct html_tag *p1 = m1;
+ const struct html_tag *p2 = m2;
return g_ascii_strcasecmp (p1->name, p2->name);
}
static int
entity_cmp (const void *m1, const void *m2)
{
- const entity *p1 = m1;
- const entity *p2 = m2;
+ const entity *p1 = m1;
+ const entity *p2 = m2;
return g_ascii_strcasecmp (p1->name, p2->name);
}
-static GNode*
-construct_html_node (memory_pool_t *pool, char *text)
+static GNode *
+construct_html_node (memory_pool_t * pool, char *text)
{
- struct html_node *html;
- GNode *n = NULL;
- struct html_tag key, *found;
- char t;
- int taglen = strlen (text);
+ struct html_node *html;
+ GNode *n = NULL;
+ struct html_tag key, *found;
+ char t;
+ int taglen = strlen (text);
if (text == NULL || *text == '\0') {
return NULL;
}
-
+
html = memory_pool_alloc0 (pool, sizeof (struct html_node));
/* Check whether this tag is fully closed */
/* Check xml tag */
if (*text == '?' && g_ascii_strncasecmp (text + 1, "xml", sizeof ("xml") - 1) == 0) {
- html->flags |= FL_XML;
- html->tag = NULL;
+ html->flags |= FL_XML;
+ html->tag = NULL;
}
else {
if (*text == '/') {
html->flags |= FL_CLOSING;
- text ++;
+ text++;
}
/* Find end of tag name */
return n;
}
-static gboolean
-check_balance (GNode *node, GNode **cur_level)
+static gboolean
+check_balance (GNode * node, GNode ** cur_level)
{
- struct html_node *arg = node->data, *tmp;
- GNode *cur;
-
+ struct html_node *arg = node->data, *tmp;
+ GNode *cur;
+
if (arg->flags & FL_CLOSING) {
/* First of all check whether this tag is closing tag for parent node */
cur = node->parent;
else {
return TRUE;
}
-
+
return FALSE;
}
-struct html_tag *
+struct html_tag *
get_tag_by_name (const char *name)
{
- struct html_tag key;
+ struct html_tag key;
key.name = name;
/* Decode HTML entitles in text */
void
-decode_entitles (char *s, guint *len)
+decode_entitles (char *s, guint * len)
{
- guint l;
- char *t = s; /* t - tortoise */
- char *h = s; /* h - hare */
- char *e = s;
- char *end_ptr;
- int state = 0, val, base;
- entity *found, key;
+ guint l;
+ char *t = s; /* t - tortoise */
+ char *h = s; /* h - hare */
+ char *e = s;
+ char *end_ptr;
+ int state = 0, val, base;
+ entity *found, key;
if (len == NULL || *len == 0) {
- l = strlen (s);
+ l = strlen (s);
}
else {
- l = *len;
+ l = *len;
}
-
+
while (h - s < l) {
switch (state) {
/* Out of entitle */
- case 0:
- if (*h == '&') {
- state = 1;
- e = h;
- h ++;
- continue;
+ case 0:
+ if (*h == '&') {
+ state = 1;
+ e = h;
+ h++;
+ continue;
+ }
+ else {
+ *t = *h;
+ h++;
+ t++;
+ }
+ break;
+ case 1:
+ if (*h == ';') {
+ /* Determine base */
+ /* First find in entities table */
+
+ key.name = e + 1;
+ *h = '\0';
+ if (*(e + 1) != '#' && (found = bsearch (&key, entities_defs, G_N_ELEMENTS (entities_defs), sizeof (entity), entity_cmp)) != NULL) {
+ if (found->code > 0 || found->code < 127) {
+ *t = (char)found->code;
+ }
+ else {
+ /* Skip undecoded */
+ t = h;
+ }
}
else {
- *t = *h;
- h ++;
- t ++;
- }
- break;
- case 1:
- if (*h == ';') {
- /* Determine base */
- /* First find in entities table */
-
- key.name = e + 1;
- *h = '\0';
- if (*(e + 1) != '#' &&
- (found = bsearch (&key, entities_defs, G_N_ELEMENTS (entities_defs), sizeof ( entity), entity_cmp)) != NULL) {
- if (found->code > 0 || found->code < 127) {
- *t = (char)found->code;
- }
- else {
- /* Skip undecoded */
- t = h;
- }
+ if (*(e + 2) == 'x' || *(e + 2) == 'X') {
+ base = 16;
+ }
+ else if (*(e + 2) == 'o' || *(e + 2) == 'O') {
+ base = 8;
+ }
+ else {
+ base = 10;
+ }
+ if (base == 10) {
+ val = strtoul ((e + 2), &end_ptr, base);
}
else {
- if (*(e + 2) == 'x' || *(e + 2) == 'X') {
- base = 16;
- }
- else if (*(e + 2) == 'o' || *(e + 2) == 'O') {
- base = 8;
- }
- else {
- base = 10;
- }
- if (base == 10) {
- val = strtoul ((e + 2), &end_ptr, base);
- }
- else {
- val = strtoul ((e + 3), &end_ptr, base);
- }
- if ((end_ptr != NULL && *end_ptr != '\0') || (val == 0 || val > 127)) {
- /* Skip undecoded */
- t = h;
- }
- else {
- *t = (char)val;
- }
+ val = strtoul ((e + 3), &end_ptr, base);
+ }
+ if ((end_ptr != NULL && *end_ptr != '\0') || (val == 0 || val > 127)) {
+ /* Skip undecoded */
+ t = h;
+ }
+ else {
+ *t = (char)val;
}
- *h = ';';
- state = 0;
- t ++;
}
- h ++;
- break;
+ *h = ';';
+ state = 0;
+ t++;
+ }
+ h++;
+ break;
}
}
*t = '\0';
-
+
if (len != NULL) {
*len = t - s;
}
static void
parse_tag_url (struct worker_task *task, struct mime_text_part *part, tag_id_t id, char *tag_text)
{
- char *c = NULL, *p;
- int len, rc;
- char *url_text;
- struct uri *url;
- gboolean got_single_quote = FALSE, got_double_quote = FALSE;
+ char *c = NULL, *p;
+ int len, rc;
+ char *url_text;
+ struct uri *url;
+ gboolean got_single_quote = FALSE, got_double_quote = FALSE;
/* For A tags search for href= and for IMG tags search for src= */
if (id == Tag_A) {
c += len;
/* Skip spaces after eqsign */
while (g_ascii_isspace (*c)) {
- c ++;
+ c++;
}
len = 0;
p = c;
break;
}
else {
- len ++;
+ len++;
}
}
else if (got_single_quote) {
break;
}
else {
- len ++;
+ len++;
}
}
- else if (g_ascii_isspace(*p) || *p == '>' || (*p == '/' && *(p + 1) == '>') || *p == '\r' || *p == '\n') {
+ else if (g_ascii_isspace (*p) || *p == '>' || (*p == '/' && *(p + 1) == '>') || *p == '\r' || *p == '\n') {
break;
}
else {
got_single_quote = !got_single_quote;
}
else {
- len ++;
+ len++;
}
}
- p ++;
+ p++;
}
if (got_single_quote || got_double_quote) {
if (len == 0) {
return;
}
-
+
url_text = memory_pool_alloc (task->task_pool, len + 1);
g_strlcpy (url_text, c, len + 1);
decode_entitles (url_text, NULL);
- if (g_ascii_strncasecmp (url_text, "http://", sizeof ("http://") - 1) != 0) {
- return;
- }
+ if (g_ascii_strncasecmp (url_text, "http://", sizeof ("http://") - 1) != 0) {
+ return;
+ }
url = memory_pool_alloc (task->task_pool, sizeof (struct uri));
rc = parse_uri (url, url_text, task->task_pool);
task->urls = g_list_prepend (task->urls, url);
}
}
- }
+ }
}
gboolean
-add_html_node (struct worker_task *task, memory_pool_t *pool, struct mime_text_part *part, char *tag_text, GNode **cur_level)
+add_html_node (struct worker_task *task, memory_pool_t * pool, struct mime_text_part *part, char *tag_text, GNode ** cur_level)
{
- GNode *new;
- struct html_node *data;
+ GNode *new;
+ struct html_node *data;
if (!tags_sorted) {
qsort (tag_defs, G_N_ELEMENTS (tag_defs), sizeof (struct html_tag), tag_cmp);
new = g_node_new (NULL);
*cur_level = new;
part->html_nodes = new;
- memory_pool_add_destructor (pool, (pool_destruct_func)g_node_destroy, part->html_nodes);
+ memory_pool_add_destructor (pool, (pool_destruct_func) g_node_destroy, part->html_nodes);
/* Call once again with root node */
return add_html_node (task, pool, part, tag_text, cur_level);
}
parse_tag_url (task, part, data->tag->id, tag_text);
}
if (data->flags & FL_CLOSING) {
- if (! *cur_level) {
+ if (!*cur_level) {
msg_debug ("add_html_node: bad parent node");
return FALSE;
}
#include "jansson.h"
#include "strbuffer.h"
-typedef int (*dump_func) (const char *buffer, int size, void *data);
+typedef int (*dump_func) (const char *buffer, int size, void *data);
struct string {
- char *buffer;
- int length;
- int size;
+ char *buffer;
+ int length;
+ int size;
};
static int
static int
dump_to_file (const char *buffer, int size, void *data)
{
- FILE *dest = (FILE *) data;
+ FILE *dest = (FILE *) data;
if (fwrite (buffer, size, 1, dest) != 1)
return -1;
return 0;
}
/* 256 spaces (the maximum indentation size) */
-static char whitespace[] =
+static char whitespace[] =
" ";
static int
dump_indent (uint32_t flags, int depth, dump_func dump, void *data)
{
if (JSON_INDENT (flags) > 0) {
- int i, ws_count = JSON_INDENT (flags);
+ int i, ws_count = JSON_INDENT (flags);
if (dump ("\n", 1, data))
return -1;
static int
dump_string (const char *str, dump_func dump, void *data)
{
- const char *end;
+ const char *end;
if (dump ("\"", 1, data))
return -1;
end = str;
while (1) {
- const char *text;
- char seq[7];
- int length;
+ const char *text;
+ char seq[7];
+ int length;
while (*end && *end != '\\' && *end != '"' && (*end < 0 || *end > 0x1F))
end++;
}
static int
-do_dump (const json_t * json, uint32_t flags, int depth,
- dump_func dump, void *data)
+do_dump (const json_t * json, uint32_t flags, int depth, dump_func dump, void *data)
{
switch (json_typeof (json)) {
case JSON_NULL:
case JSON_INTEGER:
{
- char *buffer;
- int size, ret;
+ char *buffer;
+ int size, ret;
size = asprintf (&buffer, "%d", json_integer_value (json));
if (size == -1)
case JSON_REAL:
{
- char *buffer;
- int size, ret;
+ char *buffer;
+ int size, ret;
size = asprintf (&buffer, "%.17f", json_real_value (json));
if (size == -1)
case JSON_ARRAY:
{
- int i;
- int n = json_array_size (json);
+ int i;
+ int n = json_array_size (json);
if (dump ("[", 1, data))
return -1;
return -1;
for (i = 0; i < n; ++i) {
- if (do_dump (json_array_get (json, i), flags, depth + 1,
- dump, data))
+ if (do_dump (json_array_get (json, i), flags, depth + 1, dump, data))
return -1;
if (i < n - 1) {
- if (dump (",", 1, data) ||
- dump_indent (flags, depth + 1, dump, data))
+ if (dump (",", 1, data) || dump_indent (flags, depth + 1, dump, data))
return -1;
}
else {
case JSON_OBJECT:
{
- void *iter = json_object_iter ((json_t *) json);
+ void *iter = json_object_iter ((json_t *) json);
if (dump ("{", 1, data))
return -1;
return -1;
while (iter) {
- void *next =
- json_object_iter_next ((json_t *) json, iter);
+ void *next = json_object_iter_next ((json_t *) json, iter);
dump_string (json_object_iter_key (iter), dump, data);
- if (dump (": ", 2, data) ||
- do_dump (json_object_iter_value (iter), flags, depth + 1,
- dump, data))
+ if (dump (": ", 2, data) || do_dump (json_object_iter_value (iter), flags, depth + 1, dump, data))
return -1;
if (next) {
- if (dump (",", 1, data) ||
- dump_indent (flags, depth + 1, dump, data))
+ if (dump (",", 1, data) || dump_indent (flags, depth + 1, dump, data))
return -1;
}
else {
}
-char *
+char *
json_dumps (const json_t * json, uint32_t flags)
{
- strbuffer_t strbuff;
- char *result;
+ strbuffer_t strbuff;
+ char *result;
if (!json_is_array (json) && !json_is_object (json))
return NULL;
int
json_dump_file (const json_t * json, const char *path, uint32_t flags)
{
- int result;
+ int result;
- FILE *output = fopen (path, "w");
+ FILE *output = fopen (path, "w");
if (!output)
return -1;
#include "../config.h"
#include "hashtable.h"
-typedef struct hashtable_list list_t;
-typedef struct hashtable_pair pair_t;
+typedef struct hashtable_list list_t;
+typedef struct hashtable_pair pair_t;
typedef struct hashtable_bucket bucket_t;
#define container_of(ptr_, type_, member_) \
}
}
-static unsigned int primes[] = {
+static unsigned int primes[] = {
5, 13, 23, 53, 97, 193, 389, 769, 1543, 3079, 6151, 12289, 24593,
49157, 98317, 196613, 393241, 786433, 1572869, 3145739, 6291469,
12582917, 25165843, 50331653, 100663319, 201326611, 402653189,
805306457, 1610612741
};
-static const unsigned int num_primes = sizeof (primes) / sizeof (unsigned int);
+static const unsigned int num_primes = sizeof (primes) / sizeof (unsigned int);
static inline unsigned int
num_buckets (hashtable_t * hashtable)
}
-static pair_t *
-hashtable_find_pair (hashtable_t * hashtable, bucket_t * bucket,
- const void *key, unsigned int hash)
+static pair_t *
+hashtable_find_pair (hashtable_t * hashtable, bucket_t * bucket, const void *key, unsigned int hash)
{
- list_t *list;
- pair_t *pair;
+ list_t *list;
+ pair_t *pair;
if (bucket_is_empty (hashtable, bucket))
return NULL;
static int
hashtable_do_del (hashtable_t * hashtable, const void *key, unsigned int hash)
{
- pair_t *pair;
- bucket_t *bucket;
- unsigned int index;
+ pair_t *pair;
+ bucket_t *bucket;
+ unsigned int index;
index = hash % num_buckets (hashtable);
bucket = &hashtable->buckets[index];
static int
hashtable_do_rehash (hashtable_t * hashtable)
{
- list_t *list, *next;
- pair_t *pair;
- unsigned int i, index, new_size;
+ list_t *list, *next;
+ pair_t *pair;
+ unsigned int i, index, new_size;
g_free (hashtable->buckets);
return -1;
for (i = 0; i < num_buckets (hashtable); i++) {
- hashtable->buckets[i].first = hashtable->buckets[i].last =
- &hashtable->list;
+ hashtable->buckets[i].first = hashtable->buckets[i].last = &hashtable->list;
}
list = hashtable->list.next;
}
-hashtable_t *
-hashtable_create (key_hash_fn hash_key, key_cmp_fn cmp_keys,
- free_fn free_key, free_fn free_value)
+hashtable_t *
+hashtable_create (key_hash_fn hash_key, key_cmp_fn cmp_keys, free_fn free_key, free_fn free_value)
{
- hashtable_t *hashtable = g_malloc (sizeof (hashtable_t));
+ hashtable_t *hashtable = g_malloc (sizeof (hashtable_t));
if (!hashtable)
return NULL;
}
int
-hashtable_init (hashtable_t * hashtable,
- key_hash_fn hash_key, key_cmp_fn cmp_keys,
- free_fn free_key, free_fn free_value)
+hashtable_init (hashtable_t * hashtable, key_hash_fn hash_key, key_cmp_fn cmp_keys, free_fn free_key, free_fn free_value)
{
- unsigned int i;
+ unsigned int i;
hashtable->size = 0;
hashtable->num_buckets = 0; /* index to primes[] */
hashtable->free_value = free_value;
for (i = 0; i < num_buckets (hashtable); i++) {
- hashtable->buckets[i].first = hashtable->buckets[i].last =
- &hashtable->list;
+ hashtable->buckets[i].first = hashtable->buckets[i].last = &hashtable->list;
}
return 0;
void
hashtable_close (hashtable_t * hashtable)
{
- list_t *list, *next;
- pair_t *pair;
+ list_t *list, *next;
+ pair_t *pair;
for (list = hashtable->list.next; list != &hashtable->list; list = next) {
next = list->next;
pair = list_to_pair (list);
hashtable->free_key (pair->key);
if (hashtable->free_value)
hashtable->free_value (pair->value);
- g_free (pair);
+ g_free (pair);
}
g_free (hashtable->buckets);
int
hashtable_set (hashtable_t * hashtable, void *key, void *value)
{
- pair_t *pair;
- bucket_t *bucket;
- unsigned int hash, index;
+ pair_t *pair;
+ bucket_t *bucket;
+ unsigned int hash, index;
hash = hashtable->hash_key (key);
return 0;
}
-void *
+void *
hashtable_get (hashtable_t * hashtable, const void *key)
{
- pair_t *pair;
- unsigned int hash;
- bucket_t *bucket;
+ pair_t *pair;
+ unsigned int hash;
+ bucket_t *bucket;
hash = hashtable->hash_key (key);
bucket = &hashtable->buckets[hash % num_buckets (hashtable)];
int
hashtable_del (hashtable_t * hashtable, const void *key)
{
- unsigned int hash = hashtable->hash_key (key);
+ unsigned int hash = hashtable->hash_key (key);
return hashtable_do_del (hashtable, key, hash);
}
-void *
+void *
hashtable_iter (hashtable_t * hashtable)
{
return hashtable_iter_next (hashtable, &hashtable->list);
}
-void *
+void *
hashtable_iter_next (hashtable_t * hashtable, void *iter)
{
- list_t *list = (list_t *) iter;
+ list_t *list = (list_t *) iter;
if (list->next == &hashtable->list)
return NULL;
return list->next;
}
-void *
+void *
hashtable_iter_key (void *iter)
{
- pair_t *pair = list_to_pair ((list_t *) iter);
+ pair_t *pair = list_to_pair ((list_t *) iter);
return pair->key;
}
-void *
+void *
hashtable_iter_value (void *iter)
{
- pair_t *pair = list_to_pair ((list_t *) iter);
+ pair_t *pair = list_to_pair ((list_t *) iter);
return pair->value;
}
#define TOKEN_NULL 261
/* read one byte from stream, return EOF on end of file */
-typedef int (*get_func) (void *data);
+typedef int (*get_func) (void *data);
/* return non-zero if end of file has been reached */
-typedef int (*eof_func) (void *data);
+typedef int (*eof_func) (void *data);
typedef struct {
- get_func get;
- eof_func eof;
- void *data;
- int stream_pos;
- char buffer[5];
- int buffer_pos;
+ get_func get;
+ eof_func eof;
+ void *data;
+ int stream_pos;
+ char buffer[5];
+ int buffer_pos;
} stream_t;
typedef struct {
- stream_t stream;
- strbuffer_t saved_text;
- int token;
- int line, column;
+ stream_t stream;
+ strbuffer_t saved_text;
+ int token;
+ int line, column;
union {
- char *string;
- int integer;
- double real;
+ char *string;
+ int integer;
+ double real;
} value;
} lex_t;
static void
error_set (json_error_t * error, const lex_t * lex, const char *msg, ...)
{
- va_list ap;
- char text[JSON_ERROR_TEXT_LENGTH];
+ va_list ap;
+ char text[JSON_ERROR_TEXT_LENGTH];
if (!error || error->text[0] != '\0') {
/* error already set */
va_end (ap);
if (lex) {
- const char *saved_text = strbuffer_value (&lex->saved_text);
+ const char *saved_text = strbuffer_value (&lex->saved_text);
error->line = lex->line;
if (saved_text && saved_text[0]) {
if (lex->saved_text.length <= 20) {
- snprintf (error->text, JSON_ERROR_TEXT_LENGTH,
- "%s near '%s'", text, saved_text);
+ snprintf (error->text, JSON_ERROR_TEXT_LENGTH, "%s near '%s'", text, saved_text);
}
else
snprintf (error->text, JSON_ERROR_TEXT_LENGTH, "%s", text);
}
else {
- snprintf (error->text, JSON_ERROR_TEXT_LENGTH,
- "%s near end of file", text);
+ snprintf (error->text, JSON_ERROR_TEXT_LENGTH, "%s near end of file", text);
}
}
else {
static char
stream_get (stream_t * stream, json_error_t * error)
{
- char c;
+ char c;
if (!stream->buffer[stream->buffer_pos]) {
stream->buffer[0] = stream->get (stream->data);
if (c < 0) {
/* multi-byte UTF-8 sequence */
- int i, count;
+ int i, count;
count = utf8_check_first (c);
if (!count)
return stream->buffer[stream->buffer_pos++];
out:
- error_set (error, NULL, "unable to decode byte 0x%x at position %d",
- (unsigned char)c, stream->stream_pos);
+ error_set (error, NULL, "unable to decode byte 0x%x at position %d", (unsigned char)c, stream->stream_pos);
stream->buffer[0] = EOF;
stream->buffer[1] = '\0';
static int
lex_get_save (lex_t * lex, json_error_t * error)
{
- char c = stream_get (&lex->stream, error);
+ char c = stream_get (&lex->stream, error);
lex_save (lex, c);
return c;
}
static void
lex_unget_unsave (lex_t * lex, char c)
{
- char d;
+ char d;
stream_unget (&lex->stream, c);
d = strbuffer_pop (&lex->saved_text);
g_assert (c == d);
static int
decode_unicode_escape (const char *str)
{
- int i;
- int value = 0;
+ int i;
+ int value = 0;
g_assert (str[0] == 'u');
for (i = 1; i <= 4; i++) {
- char c = str[i];
+ char c = str[i];
value <<= 4;
if (g_ascii_isdigit (c))
value += c - '0';
static void
lex_scan_string (lex_t * lex, json_error_t * error)
{
- char c;
- const char *p;
- char *t;
- int i;
+ char c;
+ const char *p;
+ char *t;
+ int i;
lex->value.string = NULL;
lex->token = TOKEN_INVALID;
c = lex_get_save (lex, error);
}
}
- else if (c == '"' || c == '\\' || c == '/' || c == 'b' ||
- c == 'f' || c == 'n' || c == 'r' || c == 't')
+ else if (c == '"' || c == '\\' || c == '/' || c == 'b' || c == 'f' || c == 'n' || c == 'r' || c == 't')
c = lex_get_save (lex, error);
else {
lex_unget_unsave (lex, c);
if (*p == '\\') {
p++;
if (*p == 'u') {
- char buffer[4];
- int length;
- int value;
+ char buffer[4];
+ int length;
+ int value;
value = decode_unicode_escape (p);
p += 5;
if (0xD800 <= value && value <= 0xDBFF) {
/* surrogate pair */
if (*p == '\\' && *(p + 1) == 'u') {
- int value2 = decode_unicode_escape (++p);
+ int value2 = decode_unicode_escape (++p);
p += 5;
if (0xDC00 <= value2 && value2 <= 0xDFFF) {
/* valid second surrogate */
- value = ((value - 0xD800) << 10) +
- (value2 - 0xDC00) + 0x10000;
+ value = ((value - 0xD800) << 10) + (value2 - 0xDC00) + 0x10000;
}
else {
/* invalid second surrogate */
- error_set (error, lex,
- "invalid Unicode '\\u%04X\\u%04X'",
- value, value2);
+ error_set (error, lex, "invalid Unicode '\\u%04X\\u%04X'", value, value2);
goto out;
}
}
else {
/* no second surrogate */
- error_set (error, lex, "invalid Unicode '\\u%04X'",
- value);
+ error_set (error, lex, "invalid Unicode '\\u%04X'", value);
goto out;
}
}
static void
lex_scan_number (lex_t * lex, char c, json_error_t * error)
{
- const char *saved_text;
- char *end;
+ const char *saved_text;
+ char *end;
lex->token = TOKEN_INVALID;
static int
lex_scan (lex_t * lex, json_error_t * error)
{
- char c;
+ char c;
strbuffer_clear (&lex->saved_text);
else if (g_ascii_isupper (c) || g_ascii_islower (c)) {
/* eat up the whole identifier for clearer error messages */
- const char *saved_text;
+ const char *saved_text;
c = lex_get_save (lex, error);
while (g_ascii_isupper (c) || g_ascii_islower (c))
return lex->token;
}
-static char *
+static char *
lex_steal_string (lex_t * lex)
{
- char *result = NULL;
+ char *result = NULL;
if (lex->token == TOKEN_STRING) {
result = lex->value.string;
lex->value.string = NULL;
/*** parser ***/
-static json_t *parse_value (lex_t * lex, json_error_t * error);
+static json_t *parse_value (lex_t * lex, json_error_t * error);
-static json_t *
+static json_t *
parse_object (lex_t * lex, json_error_t * error)
{
- json_t *object = json_object ();
+ json_t *object = json_object ();
if (!object)
return NULL;
return object;
while (1) {
- char *key;
- json_t *value;
+ char *key;
+ json_t *value;
if (lex->token != TOKEN_STRING) {
error_set (error, lex, "string or '}' expected");
return NULL;
}
-static json_t *
+static json_t *
parse_array (lex_t * lex, json_error_t * error)
{
- json_t *array = json_array ();
+ json_t *array = json_array ();
if (!array)
return NULL;
return array;
while (lex->token) {
- json_t *elem = parse_value (lex, error);
+ json_t *elem = parse_value (lex, error);
if (!elem)
goto error;
return NULL;
}
-static json_t *
+static json_t *
parse_value (lex_t * lex, json_error_t * error)
{
- json_t *json;
+ json_t *json;
switch (lex->token) {
case TOKEN_STRING:{
return json;
}
-json_t *
+json_t *
parse_json (lex_t * lex, json_error_t * error)
{
error_init (error);
}
typedef struct {
- const char *data;
- int pos;
+ const char *data;
+ int pos;
} string_data_t;
static int
string_get (void *data)
{
- char c;
- string_data_t *stream = (string_data_t *) data;
+ char c;
+ string_data_t *stream = (string_data_t *) data;
c = stream->data[stream->pos];
if (c == '\0')
return EOF;
static int
string_eof (void *data)
{
- string_data_t *stream = (string_data_t *) data;
+ string_data_t *stream = (string_data_t *) data;
return (stream->data[stream->pos] == '\0');
}
-json_t *
+json_t *
json_loads (const char *string, json_error_t * error)
{
- lex_t lex;
- json_t *result;
+ lex_t lex;
+ json_t *result;
- string_data_t stream_data = {
+ string_data_t stream_data = {
.data = string,
.pos = 0
};
return result;
}
-json_t *
+json_t *
json_loadf (FILE * input, json_error_t * error)
{
- lex_t lex;
- json_t *result;
+ lex_t lex;
+ json_t *result;
if (lex_init (&lex, (get_func) fgetc, (eof_func) feof, input))
return NULL;
return result;
}
-json_t *
+json_t *
json_load_file (const char *path, json_error_t * error)
{
- json_t *result;
- FILE *fp;
+ json_t *result;
+ FILE *fp;
fp = fopen (path, "r");
if (!fp) {
- error_set (error, NULL, "unable to open %s: %s",
- path, strerror (errno));
+ error_set (error, NULL, "unable to open %s: %s", path, strerror (errno));
return NULL;
}
strbuff->value[0] = '\0';
}
-const char *
+const char *
strbuffer_value (const strbuffer_t * strbuff)
{
return strbuff->value;
}
-char *
+char *
strbuffer_steal_value (strbuffer_t * strbuff)
{
- char *result = strbuff->value;
+ char *result = strbuff->value;
strbuffer_init (strbuff);
return result;
}
strbuffer_append_bytes (strbuffer_t * strbuff, const char *data, int size)
{
if (strbuff->length + size >= strbuff->size) {
- strbuff->size = max (strbuff->size * STRBUFFER_FACTOR,
- strbuff->length + size + 1);
+ strbuff->size = max (strbuff->size * STRBUFFER_FACTOR, strbuff->length + size + 1);
strbuff->value = realloc (strbuff->value, strbuff->size);
if (!strbuff->value)
strbuffer_pop (strbuffer_t * strbuff)
{
if (strbuff->length > 0) {
- char c = strbuff->value[--strbuff->length];
+ char c = strbuff->value[--strbuff->length];
strbuff->value[strbuff->length] = '\0';
return c;
}
int
utf8_check_first (char byte)
{
- unsigned char u = (unsigned char)byte;
+ unsigned char u = (unsigned char)byte;
if (u < 0x80)
return 1;
int
utf8_check_full (const char *buffer, int size)
{
- int i, value = 0;
- unsigned char u = (unsigned char)buffer[0];
+ int i, value = 0;
+ unsigned char u = (unsigned char)buffer[0];
if (size == 2) {
value = u & 0x1F;
return 0;
}
- else if ((size == 2 && value < 0x80) ||
- (size == 3 && value < 0x800) || (size == 4 && value < 0x10000)) {
+ else if ((size == 2 && value < 0x80) || (size == 3 && value < 0x800) || (size == 4 && value < 0x10000)) {
/* overlong encoding */
return 0;
}
int
utf8_check_string (const char *string, int length)
{
- int i;
+ int i;
if (length == -1)
length = strlen (string);
for (i = 0; i < length; i++) {
- int count = utf8_check_first (string[i]);
+ int count = utf8_check_first (string[i]);
if (count == 0)
return 0;
else if (count > 1) {
((type_ *)((char *)ptr_ - (size_t)&((type_ *)0)->member_))
typedef struct {
- json_t json;
- hashtable_t hashtable;
+ json_t json;
+ hashtable_t hashtable;
} json_object_t;
typedef struct {
- json_t json;
- unsigned int size;
- unsigned int entries;
- json_t **table;
+ json_t json;
+ unsigned int size;
+ unsigned int entries;
+ json_t **table;
} json_array_t;
typedef struct {
- json_t json;
- char *value;
+ json_t json;
+ char *value;
} json_string_t;
typedef struct {
- json_t json;
- double value;
+ json_t json;
+ double value;
} json_real_t;
typedef struct {
- json_t json;
- int value;
+ json_t json;
+ int value;
} json_integer_t;
#define json_to_object(json_) container_of(json_, json_object_t, json)
static unsigned int
hash_string (const void *key)
{
- const char *str = (const char *)key;
- unsigned int hash = 5381;
- unsigned int c;
+ const char *str = (const char *)key;
+ unsigned int hash = 5381;
+ unsigned int c;
while ((c = (unsigned int)*str)) {
hash = ((hash << 5) + hash) + c;
json_decref ((json_t *) value);
}
-json_t *
+json_t *
json_object (void)
{
- json_object_t *object = g_malloc (sizeof (json_object_t));
+ json_object_t *object = g_malloc (sizeof (json_object_t));
if (!object)
return NULL;
json_init (&object->json, JSON_OBJECT);
- if (hashtable_init (&object->hashtable, hash_string, string_equal,
- g_free, value_decref)) {
+ if (hashtable_init (&object->hashtable, hash_string, string_equal, g_free, value_decref)) {
g_free (object);
return NULL;
}
g_free (object);
}
-json_t *
+json_t *
json_object_get (const json_t * json, const char *key)
{
- json_object_t *object;
+ json_object_t *object;
if (!json_is_object (json))
return NULL;
int
json_object_set_new_nocheck (json_t * json, const char *key, json_t * value)
{
- json_object_t *object;
+ json_object_t *object;
if (!key || !value)
return -1;
int
json_object_del (json_t * json, const char *key)
{
- json_object_t *object;
+ json_object_t *object;
if (!json_is_object (json))
return -1;
return hashtable_del (&object->hashtable, key);
}
-void *
+void *
json_object_iter (json_t * json)
{
- json_object_t *object;
+ json_object_t *object;
if (!json_is_object (json))
return NULL;
return hashtable_iter (&object->hashtable);
}
-void *
+void *
json_object_iter_next (json_t * json, void *iter)
{
- json_object_t *object;
+ json_object_t *object;
if (!json_is_object (json) || iter == NULL)
return NULL;
return hashtable_iter_next (&object->hashtable, iter);
}
-const char *
+const char *
json_object_iter_key (void *iter)
{
if (!iter)
return (const char *)hashtable_iter_key (iter);
}
-json_t *
+json_t *
json_object_iter_value (void *iter)
{
if (!iter)
/*** array ***/
-json_t *
+json_t *
json_array (void)
{
- json_array_t *array = g_malloc (sizeof (json_array_t));
+ json_array_t *array = g_malloc (sizeof (json_array_t));
if (!array)
return NULL;
json_init (&array->json, JSON_ARRAY);
static void
json_delete_array (json_array_t * array)
{
- unsigned int i;
+ unsigned int i;
for (i = 0; i < array->entries; i++)
json_decref (array->table[i]);
return json_to_array (json)->entries;
}
-json_t *
+json_t *
json_array_get (const json_t * json, unsigned int index)
{
- json_array_t *array;
+ json_array_t *array;
if (!json_is_array (json))
return NULL;
array = json_to_array (json);
int
json_array_set_new (json_t * json, unsigned int index, json_t * value)
{
- json_array_t *array;
+ json_array_t *array;
if (!value)
return -1;
int
json_array_append_new (json_t * json, json_t * value)
{
- json_array_t *array;
+ json_array_t *array;
if (!value)
return -1;
/*** string ***/
-json_t *
+json_t *
json_string_nocheck (const char *value)
{
- json_string_t *string;
+ json_string_t *string;
if (!value)
return NULL;
return &string->json;
}
-json_t *
+json_t *
json_string (const char *value)
{
if (!value || !utf8_check_string (value, -1))
return json_string_nocheck (value);
}
-const char *
+const char *
json_string_value (const json_t * json)
{
if (!json_is_string (json))
/*** integer ***/
-json_t *
+json_t *
json_integer (int value)
{
- json_integer_t *integer = g_malloc (sizeof (json_integer_t));
+ json_integer_t *integer = g_malloc (sizeof (json_integer_t));
if (!integer)
return NULL;
json_init (&integer->json, JSON_INTEGER);
/*** real ***/
-json_t *
+json_t *
json_real (double value)
{
- json_real_t *real = g_malloc (sizeof (json_real_t));
+ json_real_t *real = g_malloc (sizeof (json_real_t));
if (!real)
return NULL;
json_init (&real->json, JSON_REAL);
/*** simple values ***/
-json_t *
+json_t *
json_true (void)
{
- static json_t the_true = {
+ static json_t the_true = {
.type = JSON_TRUE,
.refcount = 1
};
}
-json_t *
+json_t *
json_false (void)
{
- static json_t the_false = {
+ static json_t the_false = {
.type = JSON_FALSE,
.refcount = 1
};
}
-json_t *
+json_t *
json_null (void)
{
- static json_t the_null = {
+ static json_t the_null = {
.type = JSON_NULL,
.refcount = 1
};
#include "modules.h"
#include "message.h"
-static char greetingbuf[1024];
-static struct timeval io_tv;
+static char greetingbuf[1024];
+static struct timeval io_tv;
-static gboolean lmtp_write_socket (void *arg);
+static gboolean lmtp_write_socket (void *arg);
-static
-void sig_handler (int signo)
+static
+ void
+sig_handler (int signo)
{
switch (signo) {
- case SIGINT:
- case SIGTERM:
- _exit (1);
- break;
+ case SIGINT:
+ case SIGTERM:
+ _exit (1);
+ break;
}
}
static void
sigusr_handler (int fd, short what, void *arg)
{
- struct rspamd_worker *worker = (struct rspamd_worker *)arg;
+ struct rspamd_worker *worker = (struct rspamd_worker *)arg;
/* Do not accept new connections, preparing to end worker's process */
- struct timeval tv;
+ struct timeval tv;
tv.tv_sec = SOFT_SHUTDOWN_TIME;
tv.tv_usec = 0;
event_del (&worker->sig_ev);
static void
rcpt_destruct (void *pointer)
{
- struct worker_task *task = (struct worker_task *)pointer;
+ struct worker_task *task = (struct worker_task *)pointer;
if (task->rcpt) {
g_list_free (task->rcpt);
static void
free_lmtp_task (struct rspamd_lmtp_proto *lmtp, gboolean is_soft)
{
- GList *part;
- struct mime_part *p;
+ GList *part;
+ struct mime_part *p;
if (lmtp) {
msg_debug ("free_lmtp_task: free pointer %p", lmtp->task);
/*
* Callback that is called when there is data to read in buffer
*/
-static gboolean
-lmtp_read_socket (f_str_t *in, void *arg)
+static gboolean
+lmtp_read_socket (f_str_t * in, void *arg)
{
- struct rspamd_lmtp_proto *lmtp = (struct rspamd_lmtp_proto *)arg;
- struct worker_task *task = lmtp->task;
- ssize_t r;
+ struct rspamd_lmtp_proto *lmtp = (struct rspamd_lmtp_proto *)arg;
+ struct worker_task *task = lmtp->task;
+ ssize_t r;
switch (task->state) {
- case READ_COMMAND:
- case READ_HEADER:
- if (read_lmtp_input_line (lmtp, in) != 0) {
- msg_info ("read_lmtp_socket: closing lmtp connection due to protocol error");
- lmtp->task->state = CLOSING_CONNECTION;
- }
- /* Task was read, recall read handler once more with new state to process message and write reply */
- if (task->state == READ_MESSAGE) {
- lmtp_read_socket (in, arg);
- }
- break;
- case READ_MESSAGE:
- r = process_message (lmtp->task);
- r = process_filters (lmtp->task);
- if (r == -1) {
- task->last_error = "Filter processing error";
- task->error_code = LMTP_FAILURE;
- task->state = WRITE_ERROR;
- lmtp_write_socket (lmtp);
- }
- else if (r == 0) {
- task->state = WAIT_FILTER;
- rspamd_dispatcher_pause (lmtp->task->dispatcher);
- }
- else {
- process_statfiles (lmtp->task);
- task->state = WRITE_REPLY;
- lmtp_write_socket (lmtp);
- }
- break;
- default:
- msg_debug ("lmtp_read_socket: invalid state while reading from socket %d", lmtp->task->state);
- break;
+ case READ_COMMAND:
+ case READ_HEADER:
+ if (read_lmtp_input_line (lmtp, in) != 0) {
+ msg_info ("read_lmtp_socket: closing lmtp connection due to protocol error");
+ lmtp->task->state = CLOSING_CONNECTION;
+ }
+ /* Task was read, recall read handler once more with new state to process message and write reply */
+ if (task->state == READ_MESSAGE) {
+ lmtp_read_socket (in, arg);
+ }
+ break;
+ case READ_MESSAGE:
+ r = process_message (lmtp->task);
+ r = process_filters (lmtp->task);
+ if (r == -1) {
+ task->last_error = "Filter processing error";
+ task->error_code = LMTP_FAILURE;
+ task->state = WRITE_ERROR;
+ lmtp_write_socket (lmtp);
+ }
+ else if (r == 0) {
+ task->state = WAIT_FILTER;
+ rspamd_dispatcher_pause (lmtp->task->dispatcher);
+ }
+ else {
+ process_statfiles (lmtp->task);
+ task->state = WRITE_REPLY;
+ lmtp_write_socket (lmtp);
+ }
+ break;
+ default:
+ msg_debug ("lmtp_read_socket: invalid state while reading from socket %d", lmtp->task->state);
+ break;
}
return TRUE;
/*
* Callback for socket writing
*/
-static gboolean
+static gboolean
lmtp_write_socket (void *arg)
{
- struct rspamd_lmtp_proto *lmtp = (struct rspamd_lmtp_proto *)arg;
-
+ struct rspamd_lmtp_proto *lmtp = (struct rspamd_lmtp_proto *)arg;
+
switch (lmtp->task->state) {
- case WRITE_REPLY:
- if (write_lmtp_reply (lmtp) == 1) {
- lmtp->task->state = WAIT_FILTER;
- }
- else {
- lmtp->task->state = CLOSING_CONNECTION;
- }
- break;
- case WRITE_ERROR:
- write_lmtp_reply (lmtp);
+ case WRITE_REPLY:
+ if (write_lmtp_reply (lmtp) == 1) {
+ lmtp->task->state = WAIT_FILTER;
+ }
+ else {
lmtp->task->state = CLOSING_CONNECTION;
- break;
- case CLOSING_CONNECTION:
- msg_debug ("lmtp_write_socket: normally closing connection");
- free_lmtp_task (lmtp, TRUE);
- return FALSE;
- break;
- default:
- msg_debug ("lmtp_write_socket: invalid state while writing to socket %d", lmtp->task->state);
- break;
+ }
+ break;
+ case WRITE_ERROR:
+ write_lmtp_reply (lmtp);
+ lmtp->task->state = CLOSING_CONNECTION;
+ break;
+ case CLOSING_CONNECTION:
+ msg_debug ("lmtp_write_socket: normally closing connection");
+ free_lmtp_task (lmtp, TRUE);
+ return FALSE;
+ break;
+ default:
+ msg_debug ("lmtp_write_socket: invalid state while writing to socket %d", lmtp->task->state);
+ break;
}
return TRUE;
* Called if something goes wrong
*/
static void
-lmtp_err_socket (GError *err, void *arg)
+lmtp_err_socket (GError * err, void *arg)
{
- struct rspamd_lmtp_proto *lmtp = (struct rspamd_lmtp_proto *)arg;
+ struct rspamd_lmtp_proto *lmtp = (struct rspamd_lmtp_proto *)arg;
msg_info ("lmtp_err_socket: abnormally closing connection, error: %s", err->message);
/* Free buffers */
free_lmtp_task (lmtp, FALSE);
static void
accept_socket (int fd, short what, void *arg)
{
- struct rspamd_worker *worker = (struct rspamd_worker *)arg;
- struct sockaddr_storage ss;
- struct worker_task *new_task;
- struct rspamd_lmtp_proto *lmtp;
- socklen_t addrlen = sizeof(ss);
- int nfd;
+ struct rspamd_worker *worker = (struct rspamd_worker *)arg;
+ struct sockaddr_storage ss;
+ struct worker_task *new_task;
+ struct rspamd_lmtp_proto *lmtp;
+ socklen_t addrlen = sizeof (ss);
+ int nfd;
if ((nfd = accept_from_socket (fd, (struct sockaddr *)&ss, &addrlen)) == -1) {
msg_warn ("accept_socket: accept failed: %s", strerror (errno));
new_task->cfg = worker->srv->cfg;
new_task->task_pool = memory_pool_new (memory_pool_get_size ());
/* Add destructor for recipients list (it would be better to use anonymous function here */
- memory_pool_add_destructor (new_task->task_pool, (pool_destruct_func)rcpt_destruct, new_task);
+ memory_pool_add_destructor (new_task->task_pool, (pool_destruct_func) rcpt_destruct, new_task);
new_task->results = g_hash_table_new (g_str_hash, g_str_equal);
- memory_pool_add_destructor (new_task->task_pool, (pool_destruct_func)g_hash_table_destroy, new_task->results);
- worker->srv->stat->connections_count ++;
+ memory_pool_add_destructor (new_task->task_pool, (pool_destruct_func) g_hash_table_destroy, new_task->results);
+ worker->srv->stat->connections_count++;
lmtp->task = new_task;
lmtp->state = LMTP_READ_LHLO;
/* Set up dispatcher */
- new_task->dispatcher = rspamd_create_dispatcher (nfd, BUFFER_LINE, lmtp_read_socket,
- lmtp_write_socket, lmtp_err_socket, &io_tv,
- (void *)lmtp);
+ new_task->dispatcher = rspamd_create_dispatcher (nfd, BUFFER_LINE, lmtp_read_socket, lmtp_write_socket, lmtp_err_socket, &io_tv, (void *)lmtp);
rspamd_dispatcher_write (lmtp->task->dispatcher, greetingbuf, strlen (greetingbuf), FALSE, FALSE);
}
void
start_lmtp_worker (struct rspamd_worker *worker)
{
- struct sigaction signals;
- int i;
- char *hostbuf;
- long int hostmax;
+ struct sigaction signals;
+ int i;
+ char *hostbuf;
+ long int hostmax;
worker->srv->pid = getpid ();
worker->srv->type = TYPE_LMTP;
sigprocmask (SIG_UNBLOCK, &signals.sa_mask, NULL);
/* SIGUSR2 handler */
- signal_set (&worker->sig_ev, SIGUSR2, sigusr_handler, (void *) worker);
+ signal_set (&worker->sig_ev, SIGUSR2, sigusr_handler, (void *)worker);
signal_add (&worker->sig_ev, NULL);
-
+
/* Accept event */
- event_set(&worker->bind_ev, worker->cf->listen_sock, EV_READ | EV_PERSIST, accept_socket, (void *)worker);
- event_add(&worker->bind_ev, NULL);
+ event_set (&worker->bind_ev, worker->cf->listen_sock, EV_READ | EV_PERSIST, accept_socket, (void *)worker);
+ event_add (&worker->bind_ev, NULL);
/* Perform modules configuring */
- for (i = 0; i < MODULES_NUM; i ++) {
+ for (i = 0; i < MODULES_NUM; i++) {
modules[i].module_config_func (worker->srv->cfg);
}
#define OUTBUFSIZ 1000
/* LMTP commands */
-static f_str_t lhlo_command = {
+static f_str_t lhlo_command = {
.begin = "LHLO",
.len = sizeof ("LHLO") - 1
};
-static f_str_t mail_command = {
+
+static f_str_t mail_command = {
.begin = "MAIL FROM:",
.len = sizeof ("MAIL FROM:") - 1
};
-static f_str_t rcpt_command = {
+
+static f_str_t rcpt_command = {
.begin = "RCPT TO:",
.len = sizeof ("RCPT TO:") - 1
};
-static f_str_t data_command = {
+
+static f_str_t data_command = {
.begin = "DATA",
.len = sizeof ("DATA") - 1
};
-static f_str_t data_dot = {
+
+static f_str_t data_dot = {
.begin = ".\r\n",
.len = sizeof (".\r\n") - 1
};
-static const char *mail_regexp = "[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?";
-static GRegex *mail_re = NULL;
+static const char *mail_regexp = "[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?";
+static GRegex *mail_re = NULL;
/*
* Extract e-mail from read line
* return <> if no valid address detected
*/
-static char *
-extract_mail (memory_pool_t *pool, f_str_t *line)
+static char *
+extract_mail (memory_pool_t * pool, f_str_t * line)
{
- GError *err = NULL;
- char *match;
- GMatchInfo *info;
+ GError *err = NULL;
+ char *match;
+ GMatchInfo *info;
if (mail_re == NULL) {
/* Compile regexp */
static void
out_lmtp_reply (struct worker_task *task, int code, char *rcode, char *msg)
{
- char outbuf[OUTBUFSIZ];
- int r;
-
+ char outbuf[OUTBUFSIZ];
+ int r;
+
if (*rcode == '\0') {
r = snprintf (outbuf, OUTBUFSIZ, "%d %s\r\n", code, msg);
}
rspamd_dispatcher_write (task->dispatcher, outbuf, r, FALSE, FALSE);
}
-int
-read_lmtp_input_line (struct rspamd_lmtp_proto *lmtp, f_str_t *line)
+int
+read_lmtp_input_line (struct rspamd_lmtp_proto *lmtp, f_str_t * line)
{
- char *c, *rcpt;
- f_str_t fstr;
- unsigned int i = 0, l = 0, size;
+ char *c, *rcpt;
+ f_str_t fstr;
+ unsigned int i = 0, l = 0, size;
switch (lmtp->state) {
- case LMTP_READ_LHLO:
- /* Search LHLO line */
- if ((i = fstrstri (line, &lhlo_command)) == -1) {
- msg_info ("read_lmtp_input_line: LHLO expected but not found");
- out_lmtp_reply (lmtp->task, LMTP_BAD_CMD, "5.0.0", "Need LHLO here");
- return -1;
- }
- else {
- i += lhlo_command.len;
- c = line->begin + i;
- /* Skip spaces */
- while (g_ascii_isspace (*c) && i < line->len) {
- i ++;
- c ++;
- }
- lmtp->task->helo = memory_pool_alloc (lmtp->task->task_pool, line->len - i + 1);
- /* Strlcpy makes string null terminated by design */
- g_strlcpy (lmtp->task->helo, c, line->len - i + 1);
- lmtp->state = LMTP_READ_FROM;
- out_lmtp_reply (lmtp->task, LMTP_OK, "", "Ok");
- return 0;
+ case LMTP_READ_LHLO:
+ /* Search LHLO line */
+ if ((i = fstrstri (line, &lhlo_command)) == -1) {
+ msg_info ("read_lmtp_input_line: LHLO expected but not found");
+ out_lmtp_reply (lmtp->task, LMTP_BAD_CMD, "5.0.0", "Need LHLO here");
+ return -1;
+ }
+ else {
+ i += lhlo_command.len;
+ c = line->begin + i;
+ /* Skip spaces */
+ while (g_ascii_isspace (*c) && i < line->len) {
+ i++;
+ c++;
}
- break;
- case LMTP_READ_FROM:
- /* Search MAIL FROM: line */
- if ((i = fstrstri (line, &mail_command)) == -1) {
- msg_info ("read_lmtp_input_line: MAIL expected but not found");
- out_lmtp_reply (lmtp->task, LMTP_BAD_CMD, "5.0.0", "Need MAIL here");
+ lmtp->task->helo = memory_pool_alloc (lmtp->task->task_pool, line->len - i + 1);
+ /* Strlcpy makes string null terminated by design */
+ g_strlcpy (lmtp->task->helo, c, line->len - i + 1);
+ lmtp->state = LMTP_READ_FROM;
+ out_lmtp_reply (lmtp->task, LMTP_OK, "", "Ok");
+ return 0;
+ }
+ break;
+ case LMTP_READ_FROM:
+ /* Search MAIL FROM: line */
+ if ((i = fstrstri (line, &mail_command)) == -1) {
+ msg_info ("read_lmtp_input_line: MAIL expected but not found");
+ out_lmtp_reply (lmtp->task, LMTP_BAD_CMD, "5.0.0", "Need MAIL here");
+ return -1;
+ }
+ else {
+ i += mail_command.len;
+ c = line->begin + i;
+ fstr.begin = line->begin + i;
+ fstr.len = line->len - i;
+ lmtp->task->from = extract_mail (lmtp->task->task_pool, &fstr);
+ lmtp->state = LMTP_READ_RCPT;
+ out_lmtp_reply (lmtp->task, LMTP_OK, "2.1.0", "Sender ok");
+ return 0;
+ }
+ break;
+ case LMTP_READ_RCPT:
+ /* Search RCPT_TO: line */
+ if ((i = fstrstri (line, &rcpt_command)) == -1) {
+ msg_info ("read_lmtp_input_line: RCPT expected but not found");
+ out_lmtp_reply (lmtp->task, LMTP_NO_RCPT, "5.5.4", "Need RCPT here");
+ return -1;
+ }
+ else {
+ i += rcpt_command.len;
+ c = line->begin + i;
+ fstr.begin = line->begin + i;
+ fstr.len = line->len - i;
+ rcpt = extract_mail (lmtp->task->task_pool, &fstr);
+ if (*rcpt == '<' && *(rcpt + 1) == '>') {
+ /* Invalid or empty rcpt not allowed */
+ msg_info ("read_lmtp_input_line: bad recipient");
+ out_lmtp_reply (lmtp->task, LMTP_NO_RCPT, "5.5.4", "Bad recipient");
return -1;
}
- else {
- i += mail_command.len;
- c = line->begin + i;
- fstr.begin = line->begin + i;
- fstr.len = line->len - i;
- lmtp->task->from = extract_mail (lmtp->task->task_pool, &fstr);
- lmtp->state = LMTP_READ_RCPT;
- out_lmtp_reply (lmtp->task, LMTP_OK, "2.1.0", "Sender ok");
- return 0;
- }
- break;
- case LMTP_READ_RCPT:
- /* Search RCPT_TO: line */
- if ((i = fstrstri (line, &rcpt_command)) == -1) {
- msg_info ("read_lmtp_input_line: RCPT expected but not found");
- out_lmtp_reply (lmtp->task, LMTP_NO_RCPT, "5.5.4", "Need RCPT here");
- return -1;
+ /* Strlcpy makes string null terminated by design */
+ lmtp->task->rcpt = g_list_prepend (lmtp->task->rcpt, rcpt);
+ lmtp->state = LMTP_READ_DATA;
+ out_lmtp_reply (lmtp->task, LMTP_OK, "2.1.0", "Recipient ok");
+ return 0;
+ }
+ break;
+ case LMTP_READ_DATA:
+ /* Search DATA line */
+ if ((i = fstrstri (line, &data_command)) == -1) {
+ msg_info ("read_lmtp_input_line: DATA expected but not found");
+ out_lmtp_reply (lmtp->task, LMTP_BAD_CMD, "5.0.0", "Need DATA here");
+ return -1;
+ }
+ else {
+ i += data_command.len;
+ c = line->begin + i;
+ /* Skip spaces */
+ while (g_ascii_isspace (*c++)) {
+ i++;
}
- else {
- i += rcpt_command.len;
- c = line->begin + i;
- fstr.begin = line->begin + i;
- fstr.len = line->len - i;
- rcpt = extract_mail (lmtp->task->task_pool, &fstr);
- if (*rcpt == '<' && *(rcpt + 1) == '>') {
- /* Invalid or empty rcpt not allowed */
- msg_info ("read_lmtp_input_line: bad recipient");
- out_lmtp_reply (lmtp->task, LMTP_NO_RCPT, "5.5.4", "Bad recipient");
- return -1;
+ rcpt = memory_pool_alloc (lmtp->task->task_pool, line->len - i + 1);
+ /* Strlcpy makes string null terminated by design */
+ g_strlcpy (rcpt, c, line->len - i + 1);
+ lmtp->task->rcpt = g_list_prepend (lmtp->task->rcpt, rcpt);
+ lmtp->state = LMTP_READ_MESSAGE;
+ out_lmtp_reply (lmtp->task, LMTP_DATA, "", "Enter message, ending with \".\" on a line by itself");
+ lmtp->task->msg = fstralloc (lmtp->task->task_pool, BUFSIZ);
+ return 0;
+ }
+ break;
+ case LMTP_READ_MESSAGE:
+ if (strncmp (line->begin, data_dot.begin, line->len) == 0) {
+ lmtp->state = LMTP_READ_DOT;
+ lmtp->task->state = READ_MESSAGE;
+ return 0;
+ }
+ else {
+ l = lmtp->task->msg->len;
+ size = lmtp->task->msg->size;
+ if (l + line->len > size) {
+ /* Grow buffer */
+ if (line->len > size) {
+ size += line->len << 1;
}
- /* Strlcpy makes string null terminated by design */
- lmtp->task->rcpt = g_list_prepend (lmtp->task->rcpt, rcpt);
- lmtp->state = LMTP_READ_DATA;
- out_lmtp_reply (lmtp->task, LMTP_OK, "2.1.0", "Recipient ok");
- return 0;
- }
- break;
- case LMTP_READ_DATA:
- /* Search DATA line */
- if ((i = fstrstri (line, &data_command)) == -1) {
- msg_info ("read_lmtp_input_line: DATA expected but not found");
- out_lmtp_reply (lmtp->task, LMTP_BAD_CMD, "5.0.0", "Need DATA here");
- return -1;
- }
- else {
- i += data_command.len;
- c = line->begin + i;
- /* Skip spaces */
- while (g_ascii_isspace (*c++)) {
- i ++;
+ else {
+ /* size *= 2 */
+ size <<= 1;
}
- rcpt = memory_pool_alloc (lmtp->task->task_pool, line->len - i + 1);
- /* Strlcpy makes string null terminated by design */
- g_strlcpy (rcpt, c, line->len - i + 1);
- lmtp->task->rcpt = g_list_prepend (lmtp->task->rcpt, rcpt);
- lmtp->state = LMTP_READ_MESSAGE;
- out_lmtp_reply (lmtp->task, LMTP_DATA, "", "Enter message, ending with \".\" on a line by itself");
- lmtp->task->msg = fstralloc (lmtp->task->task_pool, BUFSIZ);
- return 0;
+ lmtp->task->msg = fstrgrow (lmtp->task->task_pool, lmtp->task->msg, size);
}
- break;
- case LMTP_READ_MESSAGE:
- if (strncmp (line->begin, data_dot.begin, line->len) == 0) {
- lmtp->state = LMTP_READ_DOT;
- lmtp->task->state = READ_MESSAGE;
- return 0;
- }
- else {
- l = lmtp->task->msg->len;
- size = lmtp->task->msg->size;
- if (l + line->len > size) {
- /* Grow buffer */
- if (line->len > size) {
- size += line->len << 1;
- }
- else {
- /* size *= 2 */
- size <<= 1;
- }
- lmtp->task->msg = fstrgrow (lmtp->task->task_pool, lmtp->task->msg, size);
- }
- fstrcat (lmtp->task->msg, line);
- return 0;
- }
- break;
- case LMTP_READ_DOT:
- /* We have some input after reading dot, close connection as we have no currently support of multiply
- * messages per session
- */
- out_lmtp_reply (lmtp->task, LMTP_QUIT, "", "Bye");
+ fstrcat (lmtp->task->msg, line);
return 0;
- break;
- }
+ }
+ break;
+ case LMTP_READ_DOT:
+ /* We have some input after reading dot, close connection as we have no currently support of multiply
+ * messages per session
+ */
+ out_lmtp_reply (lmtp->task, LMTP_QUIT, "", "Bye");
+ return 0;
+ break;
+ }
return 0;
}
struct mta_callback_data {
- struct worker_task *task;
- rspamd_io_dispatcher_t *dispatcher;
+ struct worker_task *task;
+ rspamd_io_dispatcher_t *dispatcher;
enum {
LMTP_WANT_GREETING,
LMTP_WANT_MAIL,
} state;
};
-static gboolean
-parse_mta_str (f_str_t *in, struct mta_callback_data *cd)
+static gboolean
+parse_mta_str (f_str_t * in, struct mta_callback_data *cd)
{
- int r;
- static f_str_t okres1 = {
+ int r;
+ static f_str_t okres1 = {
.begin = "250 ",
.len = sizeof ("250 ") - 1,
- },
- okres2 = {
- .begin = "220 ",
- .len = sizeof ("220 ") - 1,
- },
- datares = {
- .begin = "354 ",
- .len = sizeof ("354 ") - 1,
- };
+ }
+ , okres2 = {
+ .begin = "220 ",.len = sizeof ("220 ") - 1,}
+ , datares = {
+ .begin = "354 ",.len = sizeof ("354 ") - 1,};
switch (cd->state) {
- case LMTP_WANT_GREETING:
- case LMTP_WANT_MAIL:
- case LMTP_WANT_RCPT:
- case LMTP_WANT_DATA:
- case LMTP_WANT_CLOSING:
- r = fstrstr (in, &okres1);
- if (r == -1) {
- r = fstrstr (in, &okres2);
- }
- break;
- case LMTP_WANT_DOT:
- r = fstrstr (in, &datares);
- break;
+ case LMTP_WANT_GREETING:
+ case LMTP_WANT_MAIL:
+ case LMTP_WANT_RCPT:
+ case LMTP_WANT_DATA:
+ case LMTP_WANT_CLOSING:
+ r = fstrstr (in, &okres1);
+ if (r == -1) {
+ r = fstrstr (in, &okres2);
+ }
+ break;
+ case LMTP_WANT_DOT:
+ r = fstrstr (in, &datares);
+ break;
}
return r != -1;
/*
* Callback that is called when there is data to read in buffer
*/
-static gboolean
-mta_read_socket (f_str_t *in, void *arg)
+static gboolean
+mta_read_socket (f_str_t * in, void *arg)
{
- struct mta_callback_data *cd = (struct mta_callback_data *)arg;
- char outbuf[1024], *hostbuf, *c;
- int hostmax, r;
- GList *cur;
- static f_str_t contres1 = {
+ struct mta_callback_data *cd = (struct mta_callback_data *)arg;
+ char outbuf[1024], *hostbuf, *c;
+ int hostmax, r;
+ GList *cur;
+ static f_str_t contres1 = {
.begin = "250-",
.len = sizeof ("250-") - 1,
- },
- contres2 = {
- .begin = "220-",
- .len = sizeof ("220-") - 1,
- };
-
+ }
+ , contres2 = {
+ .begin = "220-",.len = sizeof ("220-") - 1,};
+
if (fstrstr (in, &contres1) != -1 || fstrstr (in, &contres2) != -1) {
/* Skip such lines */
return TRUE;
}
switch (cd->state) {
- case LMTP_WANT_GREETING:
- if (!parse_mta_str (in, cd)) {
- msg_warn ("mta_read_socket: got bad greeting");
- close_mta_connection (cd, FALSE);
- return FALSE;
- }
- hostmax = sysconf (_SC_HOST_NAME_MAX) + 1;
- hostbuf = alloca (hostmax);
- gethostname (hostbuf, hostmax);
- hostbuf[hostmax - 1] = '\0';
- if (cd->task->cfg->deliver_lmtp) {
- r = snprintf (outbuf, sizeof (outbuf), "LHLO %s" CRLF, hostbuf);
- }
- else {
- r = snprintf (outbuf, sizeof (outbuf), "HELO %s" CRLF, hostbuf);
- }
- rspamd_dispatcher_write (cd->task->dispatcher, outbuf, r, FALSE, FALSE);
- cd->state = LMTP_WANT_MAIL;
- break;
- case LMTP_WANT_MAIL:
- if (!parse_mta_str (in, cd)) {
- msg_warn ("mta_read_socket: got bad helo");
- close_mta_connection (cd, FALSE);
- return FALSE;
- }
- r = snprintf (outbuf, sizeof (outbuf), "MAIL FROM: <%s>" CRLF, cd->task->from);
- rspamd_dispatcher_write (cd->task->dispatcher, outbuf, r, FALSE, FALSE);
- cd->state = LMTP_WANT_RCPT;
- break;
- case LMTP_WANT_RCPT:
- if (!parse_mta_str (in, cd)) {
- msg_warn ("mta_read_socket: got bad mail from");
- close_mta_connection (cd, FALSE);
- return FALSE;
- }
- cur = g_list_first (cd->task->rcpt);
- r = 0;
- while (cur) {
- r += snprintf (outbuf + r, sizeof (outbuf) -r, "RCPT TO: <%s>" CRLF, (char *)cur->data);
- cur = g_list_next (cur);
- }
+ case LMTP_WANT_GREETING:
+ if (!parse_mta_str (in, cd)) {
+ msg_warn ("mta_read_socket: got bad greeting");
+ close_mta_connection (cd, FALSE);
+ return FALSE;
+ }
+ hostmax = sysconf (_SC_HOST_NAME_MAX) + 1;
+ hostbuf = alloca (hostmax);
+ gethostname (hostbuf, hostmax);
+ hostbuf[hostmax - 1] = '\0';
+ if (cd->task->cfg->deliver_lmtp) {
+ r = snprintf (outbuf, sizeof (outbuf), "LHLO %s" CRLF, hostbuf);
+ }
+ else {
+ r = snprintf (outbuf, sizeof (outbuf), "HELO %s" CRLF, hostbuf);
+ }
+ rspamd_dispatcher_write (cd->task->dispatcher, outbuf, r, FALSE, FALSE);
+ cd->state = LMTP_WANT_MAIL;
+ break;
+ case LMTP_WANT_MAIL:
+ if (!parse_mta_str (in, cd)) {
+ msg_warn ("mta_read_socket: got bad helo");
+ close_mta_connection (cd, FALSE);
+ return FALSE;
+ }
+ r = snprintf (outbuf, sizeof (outbuf), "MAIL FROM: <%s>" CRLF, cd->task->from);
+ rspamd_dispatcher_write (cd->task->dispatcher, outbuf, r, FALSE, FALSE);
+ cd->state = LMTP_WANT_RCPT;
+ break;
+ case LMTP_WANT_RCPT:
+ if (!parse_mta_str (in, cd)) {
+ msg_warn ("mta_read_socket: got bad mail from");
+ close_mta_connection (cd, FALSE);
+ return FALSE;
+ }
+ cur = g_list_first (cd->task->rcpt);
+ r = 0;
+ while (cur) {
+ r += snprintf (outbuf + r, sizeof (outbuf) - r, "RCPT TO: <%s>" CRLF, (char *)cur->data);
+ cur = g_list_next (cur);
+ }
- rspamd_dispatcher_write (cd->task->dispatcher, outbuf, r, FALSE, FALSE);
- cd->state = LMTP_WANT_DATA;
- break;
- case LMTP_WANT_DATA:
- if (!parse_mta_str (in, cd)) {
- msg_warn ("mta_read_socket: got bad rcpt");
- close_mta_connection (cd, FALSE);
- return FALSE;
- }
- r = snprintf (outbuf, sizeof (outbuf), "DATA" CRLF);
- rspamd_dispatcher_write (cd->task->dispatcher, outbuf, r, FALSE, FALSE);
- cd->state = LMTP_WANT_DOT;
- break;
- case LMTP_WANT_DOT:
- if (!parse_mta_str (in, cd)) {
- msg_warn ("mta_read_socket: got bad data");
- close_mta_connection (cd, FALSE);
- return FALSE;
- }
- c = g_mime_object_to_string ((GMimeObject *)cd->task->message);
- r = strlen (c);
- rspamd_dispatcher_write (cd->task->dispatcher, c, r, TRUE, TRUE);
- memory_pool_add_destructor (cd->task->task_pool, (pool_destruct_func)g_free, c);
- r = snprintf (outbuf, sizeof (outbuf), CRLF "." CRLF);
- rspamd_dispatcher_write (cd->task->dispatcher, outbuf, r, FALSE, FALSE);
- cd->state = LMTP_WANT_CLOSING;
- case LMTP_WANT_CLOSING:
- if (!parse_mta_str (in, cd)) {
- msg_warn ("mta_read_socket: message not delivered");
- close_mta_connection (cd, FALSE);
- return FALSE;
- }
- close_mta_connection (cd, TRUE);
- break;
+ rspamd_dispatcher_write (cd->task->dispatcher, outbuf, r, FALSE, FALSE);
+ cd->state = LMTP_WANT_DATA;
+ break;
+ case LMTP_WANT_DATA:
+ if (!parse_mta_str (in, cd)) {
+ msg_warn ("mta_read_socket: got bad rcpt");
+ close_mta_connection (cd, FALSE);
+ return FALSE;
+ }
+ r = snprintf (outbuf, sizeof (outbuf), "DATA" CRLF);
+ rspamd_dispatcher_write (cd->task->dispatcher, outbuf, r, FALSE, FALSE);
+ cd->state = LMTP_WANT_DOT;
+ break;
+ case LMTP_WANT_DOT:
+ if (!parse_mta_str (in, cd)) {
+ msg_warn ("mta_read_socket: got bad data");
+ close_mta_connection (cd, FALSE);
+ return FALSE;
+ }
+ c = g_mime_object_to_string ((GMimeObject *) cd->task->message);
+ r = strlen (c);
+ rspamd_dispatcher_write (cd->task->dispatcher, c, r, TRUE, TRUE);
+ memory_pool_add_destructor (cd->task->task_pool, (pool_destruct_func) g_free, c);
+ r = snprintf (outbuf, sizeof (outbuf), CRLF "." CRLF);
+ rspamd_dispatcher_write (cd->task->dispatcher, outbuf, r, FALSE, FALSE);
+ cd->state = LMTP_WANT_CLOSING;
+ case LMTP_WANT_CLOSING:
+ if (!parse_mta_str (in, cd)) {
+ msg_warn ("mta_read_socket: message not delivered");
+ close_mta_connection (cd, FALSE);
+ return FALSE;
+ }
+ close_mta_connection (cd, TRUE);
+ break;
}
return TRUE;
* Called if something goes wrong
*/
static void
-mta_err_socket (GError *err, void *arg)
+mta_err_socket (GError * err, void *arg)
{
- struct mta_callback_data *cd = (struct mta_callback_data *)arg;
+ struct mta_callback_data *cd = (struct mta_callback_data *)arg;
msg_info ("mta_err_socket: abnormaly terminating connection with MTA");
close_mta_connection (cd, FALSE);
}
static int
lmtp_deliver_mta (struct worker_task *task)
{
- int sock;
- struct sockaddr_un *un;
- struct mta_callback_data *cd;
-
+ int sock;
+ struct sockaddr_un *un;
+ struct mta_callback_data *cd;
+
if (task->cfg->deliver_family == AF_UNIX) {
un = alloca (sizeof (struct sockaddr_un));
sock = make_unix_socket (task->cfg->deliver_host, un, FALSE);
if (sock == -1) {
msg_warn ("lmtp_deliver_mta: cannot create socket for %s, %s", task->cfg->deliver_host, strerror (errno));
}
-
+
cd = memory_pool_alloc (task->task_pool, sizeof (struct mta_callback_data));
cd->task = task;
cd->state = LMTP_WANT_GREETING;
- cd->dispatcher = rspamd_create_dispatcher (sock, BUFFER_LINE, mta_read_socket,
- NULL, mta_err_socket, NULL,
- (void *)cd);
+ cd->dispatcher = rspamd_create_dispatcher (sock, BUFFER_LINE, mta_read_socket, NULL, mta_err_socket, NULL, (void *)cd);
return 0;
}
-static char*
+static char *
format_lda_args (struct worker_task *task)
{
- char *res, *c, *r;
- size_t len;
- GList *rcpt;
- gboolean got_args = FALSE;
+ char *res, *c, *r;
+ size_t len;
+ GList *rcpt;
+ gboolean got_args = FALSE;
c = task->cfg->deliver_agent_path;
/* Find first arg */
if ((c = strchr (c, ' ')) == NULL) {
return task->cfg->deliver_agent_path;
}
-
+
/* Calculate length of result string */
len = strlen (task->cfg->deliver_agent_path);
while (*c) {
if (*c == '%') {
c++;
switch (*c) {
- case 'f':
- /* Insert from */
- len += strlen (task->from) - 2;
- break;
- case 'r':
- /* Insert list of recipients */
- rcpt = g_list_first (task->rcpt);
- len -= 2;
- while (rcpt) {
- len += strlen ((char *)rcpt->data) + 1;
- rcpt = g_list_next (rcpt);
- }
- break;
+ case 'f':
+ /* Insert from */
+ len += strlen (task->from) - 2;
+ break;
+ case 'r':
+ /* Insert list of recipients */
+ rcpt = g_list_first (task->rcpt);
+ len -= 2;
+ while (rcpt) {
+ len += strlen ((char *)rcpt->data) + 1;
+ rcpt = g_list_next (rcpt);
+ }
+ break;
}
}
- c ++;
- len ++;
+ c++;
+ len++;
}
res = memory_pool_alloc (task->task_pool, len + 1);
r = res;
c = task->cfg->deliver_agent_path;
-
+
while (*c) {
if (*c == ' ') {
got_args = TRUE;
}
if (got_args && *c == '%') {
switch (*(c + 1)) {
- case 'f':
- /* Insert from */
- c += 2;
- len = strlen (task->from);
- memcpy (r, task->from, len);
+ case 'f':
+ /* Insert from */
+ c += 2;
+ len = strlen (task->from);
+ memcpy (r, task->from, len);
+ r += len;
+ break;
+ case 'r':
+ /* Insert list of recipients */
+ c += 2;
+ rcpt = g_list_first (task->rcpt);
+ while (rcpt) {
+ len = strlen ((char *)rcpt->data) + 1;
+ memcpy (r, rcpt->data, len);
r += len;
- break;
- case 'r':
- /* Insert list of recipients */
- c += 2;
- rcpt = g_list_first (task->rcpt);
- while (rcpt) {
- len = strlen ((char *)rcpt->data) + 1;
- memcpy (r, rcpt->data, len);
- r += len;
- *r++ = ' ';
- rcpt = g_list_next (rcpt);
- }
- break;
- default:
- *r = *c;
- r ++;
- c ++;
- break;
+ *r++ = ' ';
+ rcpt = g_list_next (rcpt);
+ }
+ break;
+ default:
+ *r = *c;
+ r++;
+ c++;
+ break;
}
}
else {
*r = *c;
- r ++;
- c ++;
+ r++;
+ c++;
}
}
static int
lmtp_deliver_lda (struct worker_task *task)
{
- char *args, **argv;
- GMimeStream *stream;
- int rc, ecode, p[2], argc;
- pid_t cpid, pid;
+ char *args, **argv;
+ GMimeStream *stream;
+ int rc, ecode, p[2], argc;
+ pid_t cpid, pid;
if ((args = format_lda_args (task)) == NULL) {
return -1;
}
-
+
/* Format arguments in shell style */
if (!g_shell_parse_argv (args, &argc, &argv, NULL)) {
msg_info ("lmtp_deliver_lda: cannot parse arguments");
msg_info ("lmtp_deliver_lda: cannot open pipe: %s", strerror (errno));
return -1;
}
-
+
/* Fork to exec LDA */
#ifdef HAVE_VFORK
if ((cpid = vfork ()) == -1) {
msg_info ("lmtp_deliver_lda: cannot fork: %s", strerror (errno));
return -1;
}
-#else
+#else
if ((cpid = fork ()) == -1) {
g_strfreev (argv);
msg_info ("lmtp_deliver_lda: cannot fork: %s", strerror (errno));
close (p[1]);
/* Set standart IO descriptors */
if (p[0] != STDIN_FILENO) {
- (void)dup2(p[0], STDIN_FILENO);
- (void)close(p[0]);
+ (void)dup2 (p[0], STDIN_FILENO);
+ (void)close (p[0]);
}
execv (argv[0], argv);
_exit (127);
}
-
+
close (p[0]);
stream = g_mime_stream_fs_new (p[1]);
- if (g_mime_object_write_to_stream ((GMimeObject *)task->message, stream) == -1) {
+ if (g_mime_object_write_to_stream ((GMimeObject *) task->message, stream) == -1) {
g_strfreev (argv);
msg_info ("lmtp_deliver_lda: cannot write stream to lda");
return -1;
#if defined(HAVE_WAIT4)
do {
- pid = wait4(cpid, &rc, 0, NULL);
+ pid = wait4 (cpid, &rc, 0, NULL);
} while (pid == -1 && errno == EINTR);
#elif defined(HAVE_WAITPID)
do {
- pid = waitpid(cpid, &rc, 0);
+ pid = waitpid (cpid, &rc, 0);
} while (pid == -1 && errno == EINTR);
#else
-#error wait mechanisms are undefined
+# error wait mechanisms are undefined
#endif
if (rc == -1) {
g_strfreev (argv);
int
write_lmtp_reply (struct rspamd_lmtp_proto *lmtp)
{
- int r;
+ int r;
msg_debug ("write_lmtp_reply: writing reply to client");
if (lmtp->task->error_code != 0) {
/* Lua module init function */
#define MODULE_INIT_FUNC "module_init"
-lua_State *L = NULL;
-const luaL_reg null_reg[] = {
+lua_State *L = NULL;
+const luaL_reg null_reg[] = {
{"__tostring", lua_class_tostring},
- {NULL, NULL}
+ {NULL, NULL}
};
/* Logger methods */
-LUA_FUNCTION_DEF(logger, err);
-LUA_FUNCTION_DEF(logger, warn);
-LUA_FUNCTION_DEF(logger, info);
-LUA_FUNCTION_DEF(logger, debug);
-
-static const struct luaL_reg loggerlib_m[] = {
- LUA_INTERFACE_DEF(logger, err),
- LUA_INTERFACE_DEF(logger, warn),
- LUA_INTERFACE_DEF(logger, info),
- LUA_INTERFACE_DEF(logger, debug),
+LUA_FUNCTION_DEF (logger, err);
+LUA_FUNCTION_DEF (logger, warn);
+LUA_FUNCTION_DEF (logger, info);
+LUA_FUNCTION_DEF (logger, debug);
+
+static const struct luaL_reg loggerlib_m[] = {
+ LUA_INTERFACE_DEF (logger, err),
+ LUA_INTERFACE_DEF (logger, warn),
+ LUA_INTERFACE_DEF (logger, info),
+ LUA_INTERFACE_DEF (logger, debug),
{"__tostring", lua_class_tostring},
- {NULL, NULL}
+ {NULL, NULL}
};
/* Util functions */
-void
-lua_newclass (lua_State *L, const char *classname, const struct luaL_reg *func)
+void
+lua_newclass (lua_State * L, const char *classname, const struct luaL_reg *func)
{
- luaL_newmetatable (L, classname); /* mt */
- lua_pushstring(L, "__index");
- lua_pushvalue(L, -2); /* pushes the metatable */
- lua_settable(L, -3); /* metatable.__index = metatable */
-
- lua_pushstring (L, "class"); /* mt,"__index",it,"class" */
- lua_pushstring (L, classname); /* mt,"__index",it,"class",classname */
- lua_rawset (L, -3); /* mt,"__index",it */
-
- luaL_openlib(L, NULL, func, 0);
+ luaL_newmetatable (L, classname); /* mt */
+ lua_pushstring (L, "__index");
+ lua_pushvalue (L, -2); /* pushes the metatable */
+ lua_settable (L, -3); /* metatable.__index = metatable */
+
+ lua_pushstring (L, "class"); /* mt,"__index",it,"class" */
+ lua_pushstring (L, classname); /* mt,"__index",it,"class",classname */
+ lua_rawset (L, -3); /* mt,"__index",it */
+
+ luaL_openlib (L, NULL, func, 0);
}
-int
-lua_class_tostring (lua_State *L)
+int
+lua_class_tostring (lua_State * L)
{
- char buf[32];
+ char buf[32];
if (!lua_getmetatable (L, 1)) {
goto error;
}
- lua_pushstring (L, "__index");
- lua_gettable (L, -2);
+ lua_pushstring (L, "__index");
+ lua_gettable (L, -2);
- if (!lua_istable (L, -1)) {
- goto error;
+ if (!lua_istable (L, -1)) {
+ goto error;
}
- lua_pushstring (L, "class");
- lua_gettable (L, -2);
+ lua_pushstring (L, "class");
+ lua_gettable (L, -2);
- if (!lua_isstring (L, -1)) {
+ if (!lua_isstring (L, -1)) {
goto error;
}
- snprintf (buf, sizeof (buf), "%p", lua_touserdata (L, 1));
+ snprintf (buf, sizeof (buf), "%p", lua_touserdata (L, 1));
- lua_pushfstring (L, "%s: %s", lua_tostring (L, -1), buf);
+ lua_pushfstring (L, "%s: %s", lua_tostring (L, -1), buf);
- return 1;
+ return 1;
-error:
- lua_pushstring (L, "invalid object passed to 'lua_common.c:__tostring'");
- lua_error (L);
- return 1;
+ error:
+ lua_pushstring (L, "invalid object passed to 'lua_common.c:__tostring'");
+ lua_error (L);
+ return 1;
}
-void
-lua_setclass (lua_State *L, const char *classname, int objidx)
+void
+lua_setclass (lua_State * L, const char *classname, int objidx)
{
luaL_getmetatable (L, classname);
if (objidx < 0) {
}
/* assume that table is at the top */
-void
-lua_set_table_index (lua_State *L, const char *index, const char *value)
+void
+lua_set_table_index (lua_State * L, const char *index, const char *value)
{
lua_pushstring (L, index);
lua_pushstring (L, value);
- lua_settable(L, -3);
+ lua_settable (L, -3);
}
/*** Logger interface ***/
static int
-lua_logger_err (lua_State *L)
+lua_logger_err (lua_State * L)
{
- const char *msg;
- msg = luaL_checkstring (L, 1);
- msg_err (msg);
- return 1;
+ const char *msg;
+ msg = luaL_checkstring (L, 1);
+ msg_err (msg);
+ return 1;
}
static int
-lua_logger_warn (lua_State *L)
+lua_logger_warn (lua_State * L)
{
- const char *msg;
- msg = luaL_checkstring (L, 1);
- msg_warn (msg);
- return 1;
+ const char *msg;
+ msg = luaL_checkstring (L, 1);
+ msg_warn (msg);
+ return 1;
}
static int
-lua_logger_info (lua_State *L)
+lua_logger_info (lua_State * L)
{
- const char *msg;
- msg = luaL_checkstring (L, 1);
- msg_info (msg);
- return 1;
+ const char *msg;
+ msg = luaL_checkstring (L, 1);
+ msg_info (msg);
+ return 1;
}
static int
-lua_logger_debug (lua_State *L)
+lua_logger_debug (lua_State * L)
{
- const char *msg;
- msg = luaL_checkstring (L, 1);
- msg_debug (msg);
- return 1;
+ const char *msg;
+ msg = luaL_checkstring (L, 1);
+ msg_debug (msg);
+ return 1;
}
/*** Init functions ***/
int
-luaopen_rspamd (lua_State *L)
+luaopen_rspamd (lua_State * L)
{
- luaL_openlib(L, "rspamd", null_reg, 0);
- /* make version string available to scripts */
- lua_pushstring(L, "_VERSION");
- lua_pushstring(L, RVERSION);
- lua_rawset(L, -3);
-
+ luaL_openlib (L, "rspamd", null_reg, 0);
+ /* make version string available to scripts */
+ lua_pushstring (L, "_VERSION");
+ lua_pushstring (L, RVERSION);
+ lua_rawset (L, -3);
+
return 1;
}
int
-luaopen_logger (lua_State *L)
+luaopen_logger (lua_State * L)
{
luaL_openlib (L, "rspamd_logger", loggerlib_m, 0);
- return 1;
+ return 1;
}
static void
if (L == NULL) {
L = lua_open ();
luaL_openlibs (L);
-
- (void)luaopen_rspamd (L);
- (void)luaopen_logger (L);
- (void)luaopen_config (L);
- (void)luaopen_metric (L);
+
+ (void)luaopen_rspamd (L);
+ (void)luaopen_logger (L);
+ (void)luaopen_config (L);
+ (void)luaopen_metric (L);
(void)luaopen_task (L);
- (void)luaopen_textpart (L);
+ (void)luaopen_textpart (L);
(void)luaopen_message (L);
}
}
void
init_lua_filters (struct config_file *cfg)
{
- struct config_file **pcfg;
- GList *cur;
- struct script_module *module;
-
+ struct config_file **pcfg;
+ GList *cur;
+ struct script_module *module;
+
init_lua ();
cur = g_list_first (cfg->script_modules);
while (cur) {
if (module->path) {
if (luaL_loadfile (L, module->path) != 0) {
msg_info ("lua_init_filters: load of %s failed: %s", module->path, lua_tostring (L, -1));
- cur = g_list_next (cur);
- continue;
- }
+ cur = g_list_next (cur);
+ continue;
+ }
/* Call module init function */
pcfg = lua_newuserdata (L, sizeof (struct config_file *));
lua_setclass (L, "rspamd{config}", -1);
*pcfg = cfg;
- lua_setglobal (L, "rspamd_config");
+ lua_setglobal (L, "rspamd_config");
/* do the call (1 arguments, 1 result) */
- if (lua_pcall(L, 0, LUA_MULTRET, 0) != 0) {
+ if (lua_pcall (L, 0, LUA_MULTRET, 0) != 0) {
msg_info ("lua_init_filters: init of %s failed: %s", module->path, lua_tostring (L, -1));
}
}
int
lua_call_filter (const char *function, struct worker_task *task)
{
- int result;
- struct worker_task **ptask;
+ int result;
+ struct worker_task **ptask;
lua_getglobal (L, function);
ptask = lua_newuserdata (L, sizeof (struct worker_task *));
lua_setclass (L, "rspamd{task}", -1);
*ptask = task;
-
+
if (lua_pcall (L, 1, 1, 0) != 0) {
msg_info ("lua_call_filter: call to %s failed", function);
}
msg_info ("lua_call_filter: function %s must return a number", function);
}
result = lua_tonumber (L, -1);
- lua_pop (L, 1); /* pop returned value */
+ lua_pop (L, 1); /* pop returned value */
return result;
}
int
lua_call_chain_filter (const char *function, struct worker_task *task, int *marks, unsigned int number)
{
- int result, i;
+ int result, i;
lua_getglobal (L, function);
- for (i = 0; i < number; i ++) {
+ for (i = 0; i < number; i++) {
lua_pushnumber (L, marks[i]);
}
if (lua_pcall (L, number, 1, 0) != 0) {
msg_info ("lua_call_header_filter: function %s must return a number", function);
}
result = lua_tonumber (L, -1);
- lua_pop (L, 1); /* pop returned value */
+ lua_pop (L, 1); /* pop returned value */
return result;
}
* LUA custom consolidation function
*/
struct consolidation_callback_data {
- struct worker_task *task;
- double score;
- const char *func;
+ struct worker_task *task;
+ double score;
+ const char *func;
};
static void
lua_consolidation_callback (gpointer key, gpointer value, gpointer arg)
{
- double res;
- struct symbol *s = (struct symbol *)value;
+ double res;
+ struct symbol *s = (struct symbol *)value;
struct consolidation_callback_data *data = (struct consolidation_callback_data *)arg;
lua_getglobal (L, data->func);
msg_info ("lua_consolidation_callback: function %s must return a number", data->func);
}
res = lua_tonumber (L, -1);
- lua_pop (L, 1); /* pop returned value */
+ lua_pop (L, 1); /* pop returned value */
data->score += res;
}
double
lua_consolidation_func (struct worker_task *task, const char *metric_name, const char *function_name)
{
- struct metric_result *metric_res;
- double res = 0.;
+ struct metric_result *metric_res;
+ double res = 0.;
struct consolidation_callback_data data = { task, 0, function_name };
if (function_name == NULL) {
void
add_luabuf (const char *line)
{
- int error;
+ int error;
init_lua ();
- error = luaL_loadbuffer(L, line, strlen(line), "config") ||
- lua_pcall(L, 0, 0, 0);
+ error = luaL_loadbuffer (L, line, strlen (line), "config") || lua_pcall (L, 0, 0, 0);
if (error) {
- yyerror ("lua error: %s", lua_tostring(L, -1));
- lua_pop(L, 1); /* pop error message from the stack */
+ yyerror ("lua error: %s", lua_tostring (L, -1));
+ lua_pop (L, 1); /* pop error message from the stack */
}
}
#include "lua_common.h"
/* Config file methods */
-LUA_FUNCTION_DEF(config, get_module_opt);
-LUA_FUNCTION_DEF(config, get_metric);
-LUA_FUNCTION_DEF(config, get_all_opt);
-
-static const struct luaL_reg configlib_m[] = {
- LUA_INTERFACE_DEF(config, get_module_opt),
- LUA_INTERFACE_DEF(config, get_metric),
- LUA_INTERFACE_DEF(config, get_all_opt),
+LUA_FUNCTION_DEF (config, get_module_opt);
+LUA_FUNCTION_DEF (config, get_metric);
+LUA_FUNCTION_DEF (config, get_all_opt);
+
+static const struct luaL_reg configlib_m[] = {
+ LUA_INTERFACE_DEF (config, get_module_opt),
+ LUA_INTERFACE_DEF (config, get_metric),
+ LUA_INTERFACE_DEF (config, get_all_opt),
{"__tostring", lua_class_tostring},
- {NULL, NULL}
+ {NULL, NULL}
};
/* Metric methods */
-LUA_FUNCTION_DEF(metric, register_symbol);
+LUA_FUNCTION_DEF (metric, register_symbol);
-static const struct luaL_reg metriclib_m[] = {
- LUA_INTERFACE_DEF(metric, register_symbol),
+static const struct luaL_reg metriclib_m[] = {
+ LUA_INTERFACE_DEF (metric, register_symbol),
{"__tostring", lua_class_tostring},
{NULL, NULL}
};
-static struct config_file *
-lua_check_config (lua_State *L)
+static struct config_file *
+lua_check_config (lua_State * L)
{
- void *ud = luaL_checkudata (L, 1, "rspamd{config}");
+ void *ud = luaL_checkudata (L, 1, "rspamd{config}");
luaL_argcheck (L, ud != NULL, 1, "'config' expected");
return *((struct config_file **)ud);
}
-static struct metric *
-lua_check_metric (lua_State *L)
+static struct metric *
+lua_check_metric (lua_State * L)
{
- void *ud = luaL_checkudata (L, 1, "rspamd{metric}");
+ void *ud = luaL_checkudata (L, 1, "rspamd{metric}");
luaL_argcheck (L, ud != NULL, 1, "'metric' expected");
return *((struct metric **)ud);
}
/*** Config functions ***/
static int
-lua_config_get_module_opt (lua_State *L)
+lua_config_get_module_opt (lua_State * L)
{
- struct config_file *cfg = lua_check_config (L);
- const char *mname, *optname, *val;
-
- if (cfg) {
- mname = luaL_checkstring (L, 2);
- optname = luaL_checkstring (L, 3);
-
- if (mname && optname) {
- val = get_module_opt (cfg, (char *)mname, (char *)optname);
- if (val) {
- lua_pushstring (L, val);
- return 1;
- }
- }
- }
- lua_pushnil (L);
- return 1;
+ struct config_file *cfg = lua_check_config (L);
+ const char *mname, *optname, *val;
+
+ if (cfg) {
+ mname = luaL_checkstring (L, 2);
+ optname = luaL_checkstring (L, 3);
+
+ if (mname && optname) {
+ val = get_module_opt (cfg, (char *)mname, (char *)optname);
+ if (val) {
+ lua_pushstring (L, val);
+ return 1;
+ }
+ }
+ }
+ lua_pushnil (L);
+ return 1;
}
static int
-lua_config_get_all_opt (lua_State *L)
+lua_config_get_all_opt (lua_State * L)
{
- struct config_file *cfg = lua_check_config (L);
- const char *mname;
- GList *cur_opt;
- struct module_opt *cur;
+ struct config_file *cfg = lua_check_config (L);
+ const char *mname;
+ GList *cur_opt;
+ struct module_opt *cur;
- if (cfg) {
- mname = luaL_checkstring (L, 2);
+ if (cfg) {
+ mname = luaL_checkstring (L, 2);
- if (mname) {
+ if (mname) {
cur_opt = g_hash_table_lookup (cfg->modules_opts, mname);
if (cur_opt == NULL) {
lua_pushnil (L);
return 1;
}
-
+
lua_newtable (L);
while (cur_opt) {
cur = cur_opt->data;
cur_opt = g_list_next (cur_opt);
}
return 1;
- }
- }
- lua_pushnil (L);
- return 1;
+ }
+ }
+ lua_pushnil (L);
+ return 1;
}
static int
-lua_config_get_metric (lua_State *L)
+lua_config_get_metric (lua_State * L)
{
- struct config_file *cfg = lua_check_config (L);
- struct metric *metric, **pmetric;
- const char *name;
-
- if (cfg) {
- name = luaL_checkstring (L, 2);
- metric = g_hash_table_lookup (cfg->metrics, name);
- if (metric) {
- pmetric = lua_newuserdata (L, sizeof (struct metric *));
- lua_setclass (L, "rspamd{metric}", -1);
- *pmetric = metric;
+ struct config_file *cfg = lua_check_config (L);
+ struct metric *metric, **pmetric;
+ const char *name;
+
+ if (cfg) {
+ name = luaL_checkstring (L, 2);
+ metric = g_hash_table_lookup (cfg->metrics, name);
+ if (metric) {
+ pmetric = lua_newuserdata (L, sizeof (struct metric *));
+ lua_setclass (L, "rspamd{metric}", -1);
+ *pmetric = metric;
return 1;
- }
- }
+ }
+ }
+
+ lua_pushnil (L);
+ return 1;
- lua_pushnil (L);
- return 1;
-
}
/*** Metric functions ***/
struct lua_callback_data {
- const char *name;
- lua_State *L;
+ const char *name;
+ lua_State *L;
};
static void
lua_metric_symbol_callback (struct worker_task *task, gpointer ud)
{
- struct lua_callback_data *cd = ud;
- struct worker_task **ptask;
+ struct lua_callback_data *cd = ud;
+ struct worker_task **ptask;
lua_getglobal (cd->L, cd->name);
ptask = lua_newuserdata (cd->L, sizeof (struct worker_task *));
lua_setclass (cd->L, "rspamd{task}", -1);
*ptask = task;
- if (lua_pcall(cd->L, 1, 1, 0) != 0) {
- msg_warn ("lua_metric_symbol_callback: error running function %s: %s",
- cd->name, lua_tostring(cd->L, -1));
+ if (lua_pcall (cd->L, 1, 1, 0) != 0) {
+ msg_warn ("lua_metric_symbol_callback: error running function %s: %s", cd->name, lua_tostring (cd->L, -1));
}
}
static int
-lua_metric_register_symbol (lua_State *L)
+lua_metric_register_symbol (lua_State * L)
{
- struct metric *metric = lua_check_metric (L);
- const char *name, *callback;
- double weight;
- struct lua_callback_data *cd;
+ struct metric *metric = lua_check_metric (L);
+ const char *name, *callback;
+ double weight;
+ struct lua_callback_data *cd;
if (metric) {
name = g_strdup (luaL_checkstring (L, 2));
if (name) {
cd = g_malloc (sizeof (struct lua_callback_data));
cd->name = g_strdup (callback);
- cd->L = L;
+ cd->L = L;
register_symbol (&metric->cache, name, weight, lua_metric_symbol_callback, cd);
}
}
}
int
-luaopen_config (lua_State *L)
+luaopen_config (lua_State * L)
{
- lua_newclass (L, "rspamd{config}", configlib_m);
+ lua_newclass (L, "rspamd{config}", configlib_m);
luaL_openlib (L, "rspamd_config", null_reg, 0);
- return 1;
+ return 1;
}
int
-luaopen_metric (lua_State *L)
+luaopen_metric (lua_State * L)
{
- lua_newclass (L, "rspamd{metric}", metriclib_m);
+ lua_newclass (L, "rspamd{metric}", metriclib_m);
luaL_openlib (L, "rspamd_metric", null_reg, 0);
- return 1;
+ return 1;
}
lua_pushnil (L); \
} \
return 1; \
-}
+}
#define LUA_GMIME_BRIDGE_SET(class, name, mime_class) \
static int \
lua_pushnil (L); \
} \
return 1; \
-}
+}
/* Message methods */
-LUA_FUNCTION_DEF(message, get_subject);
-LUA_FUNCTION_DEF(message, set_subject);
-LUA_FUNCTION_DEF(message, get_message_id);
-LUA_FUNCTION_DEF(message, set_message_id);
-LUA_FUNCTION_DEF(message, get_sender);
-LUA_FUNCTION_DEF(message, set_sender);
-LUA_FUNCTION_DEF(message, get_reply_to);
-LUA_FUNCTION_DEF(message, set_reply_to);
-LUA_FUNCTION_DEF(message, get_header);
-LUA_FUNCTION_DEF(message, set_header);
-
-static const struct luaL_reg msglib_m[] = {
- LUA_INTERFACE_DEF(message, get_subject),
- LUA_INTERFACE_DEF(message, set_subject),
- LUA_INTERFACE_DEF(message, get_message_id),
- LUA_INTERFACE_DEF(message, set_message_id),
- LUA_INTERFACE_DEF(message, get_sender),
- LUA_INTERFACE_DEF(message, set_sender),
- LUA_INTERFACE_DEF(message, get_reply_to),
- LUA_INTERFACE_DEF(message, set_reply_to),
- LUA_INTERFACE_DEF(message, get_header),
- LUA_INTERFACE_DEF(message, set_header),
+LUA_FUNCTION_DEF (message, get_subject);
+LUA_FUNCTION_DEF (message, set_subject);
+LUA_FUNCTION_DEF (message, get_message_id);
+LUA_FUNCTION_DEF (message, set_message_id);
+LUA_FUNCTION_DEF (message, get_sender);
+LUA_FUNCTION_DEF (message, set_sender);
+LUA_FUNCTION_DEF (message, get_reply_to);
+LUA_FUNCTION_DEF (message, set_reply_to);
+LUA_FUNCTION_DEF (message, get_header);
+LUA_FUNCTION_DEF (message, set_header);
+
+static const struct luaL_reg msglib_m[] = {
+ LUA_INTERFACE_DEF (message, get_subject),
+ LUA_INTERFACE_DEF (message, set_subject),
+ LUA_INTERFACE_DEF (message, get_message_id),
+ LUA_INTERFACE_DEF (message, set_message_id),
+ LUA_INTERFACE_DEF (message, get_sender),
+ LUA_INTERFACE_DEF (message, set_sender),
+ LUA_INTERFACE_DEF (message, get_reply_to),
+ LUA_INTERFACE_DEF (message, set_reply_to),
+ LUA_INTERFACE_DEF (message, get_header),
+ LUA_INTERFACE_DEF (message, set_header),
{"__tostring", lua_class_tostring},
{NULL, NULL}
};
-static GMimeMessage *
-lua_check_message (lua_State *L)
+static GMimeMessage *
+lua_check_message (lua_State * L)
{
- void *ud = luaL_checkudata (L, 1, "rspamd{message}");
+ void *ud = luaL_checkudata (L, 1, "rspamd{message}");
luaL_argcheck (L, ud != NULL, 1, "'message' expected");
- return *((GMimeMessage **)ud);
+ return *((GMimeMessage **) ud);
}
/*** Message interface ***/
-LUA_GMIME_BRIDGE_GET(message, get_subject, Message)
-LUA_GMIME_BRIDGE_SET(message, set_subject, Message)
-LUA_GMIME_BRIDGE_GET(message, get_message_id, Message)
-LUA_GMIME_BRIDGE_SET(message, set_message_id, Message)
-LUA_GMIME_BRIDGE_GET(message, get_sender, Message)
-LUA_GMIME_BRIDGE_SET(message, set_sender, Message)
-LUA_GMIME_BRIDGE_GET(message, get_reply_to, Message)
-LUA_GMIME_BRIDGE_SET(message, set_reply_to, Message)
-
-static int
-lua_message_get_header (lua_State *L)
+LUA_GMIME_BRIDGE_GET (message, get_subject, Message)
+ LUA_GMIME_BRIDGE_SET (message, set_subject, Message)
+ LUA_GMIME_BRIDGE_GET (message, get_message_id, Message)
+ LUA_GMIME_BRIDGE_SET (message, set_message_id, Message)
+ LUA_GMIME_BRIDGE_GET (message, get_sender, Message)
+ LUA_GMIME_BRIDGE_SET (message, set_sender, Message)
+ LUA_GMIME_BRIDGE_GET (message, get_reply_to, Message)
+ LUA_GMIME_BRIDGE_SET (message, set_reply_to, Message)
+
+ static int
+ lua_message_get_header (lua_State * L)
{
- const char *headern;
- GMimeMessage *obj = lua_check_message (L);
- GList *res = NULL, *cur;
- int i = 1;
+ const char *headern;
+ GMimeMessage *obj = lua_check_message (L);
+ GList *res = NULL, *cur;
+ int i = 1;
if (obj != NULL) {
headern = luaL_checkstring (L, 2);
res = message_get_header (NULL, obj, headern);
if (res) {
cur = res;
- lua_newtable (L);
+ lua_newtable (L);
while (cur) {
lua_pushstring (L, (const char *)cur->data);
- lua_rawseti(L, -2, i++);
+ lua_rawseti (L, -2, i++);
g_free (cur->data);
cur = g_list_next (cur);
}
static int
-lua_message_set_header (lua_State *L)
+lua_message_set_header (lua_State * L)
{
- const char *headern, *headerv;
- GMimeMessage *obj = lua_check_message (L);
+ const char *headern, *headerv;
+ GMimeMessage *obj = lua_check_message (L);
if (obj != NULL) {
headern = luaL_checkstring (L, 2);
else {
lua_pushnil (L);
}
-
+
return 1;
}
int
-luaopen_message (lua_State *L)
+luaopen_message (lua_State * L)
{
lua_newclass (L, "rspamd{message}", msglib_m);
luaL_openlib (L, "rspamd_message", null_reg, 0);
-
+
return 1;
}
-
#include <evdns.h>
/* Task methods */
-LUA_FUNCTION_DEF(task, get_message);
-LUA_FUNCTION_DEF(task, insert_result);
-LUA_FUNCTION_DEF(task, get_urls);
-LUA_FUNCTION_DEF(task, get_text_parts);
-LUA_FUNCTION_DEF(task, get_raw_headers);
-LUA_FUNCTION_DEF(task, get_received_headers);
-LUA_FUNCTION_DEF(task, resolve_dns_a);
-LUA_FUNCTION_DEF(task, resolve_dns_ptr);
-LUA_FUNCTION_DEF(task, call_rspamd_function);
-
-static const struct luaL_reg tasklib_m[] = {
- LUA_INTERFACE_DEF(task, get_message),
- LUA_INTERFACE_DEF(task, insert_result),
- LUA_INTERFACE_DEF(task, get_urls),
- LUA_INTERFACE_DEF(task, get_text_parts),
- LUA_INTERFACE_DEF(task, get_raw_headers),
- LUA_INTERFACE_DEF(task, get_received_headers),
- LUA_INTERFACE_DEF(task, resolve_dns_a),
- LUA_INTERFACE_DEF(task, resolve_dns_ptr),
- LUA_INTERFACE_DEF(task, call_rspamd_function),
+LUA_FUNCTION_DEF (task, get_message);
+LUA_FUNCTION_DEF (task, insert_result);
+LUA_FUNCTION_DEF (task, get_urls);
+LUA_FUNCTION_DEF (task, get_text_parts);
+LUA_FUNCTION_DEF (task, get_raw_headers);
+LUA_FUNCTION_DEF (task, get_received_headers);
+LUA_FUNCTION_DEF (task, resolve_dns_a);
+LUA_FUNCTION_DEF (task, resolve_dns_ptr);
+LUA_FUNCTION_DEF (task, call_rspamd_function);
+
+static const struct luaL_reg tasklib_m[] = {
+ LUA_INTERFACE_DEF (task, get_message),
+ LUA_INTERFACE_DEF (task, insert_result),
+ LUA_INTERFACE_DEF (task, get_urls),
+ LUA_INTERFACE_DEF (task, get_text_parts),
+ LUA_INTERFACE_DEF (task, get_raw_headers),
+ LUA_INTERFACE_DEF (task, get_received_headers),
+ LUA_INTERFACE_DEF (task, resolve_dns_a),
+ LUA_INTERFACE_DEF (task, resolve_dns_ptr),
+ LUA_INTERFACE_DEF (task, call_rspamd_function),
{"__tostring", lua_class_tostring},
{NULL, NULL}
};
/* Textpart methods */
-LUA_FUNCTION_DEF(textpart, get_content);
-LUA_FUNCTION_DEF(textpart, is_empty);
-LUA_FUNCTION_DEF(textpart, is_html);
-LUA_FUNCTION_DEF(textpart, get_fuzzy);
-
-static const struct luaL_reg textpartlib_m[] = {
- LUA_INTERFACE_DEF(textpart, get_content),
- LUA_INTERFACE_DEF(textpart, is_empty),
- LUA_INTERFACE_DEF(textpart, is_html),
- LUA_INTERFACE_DEF(textpart, get_fuzzy),
+LUA_FUNCTION_DEF (textpart, get_content);
+LUA_FUNCTION_DEF (textpart, is_empty);
+LUA_FUNCTION_DEF (textpart, is_html);
+LUA_FUNCTION_DEF (textpart, get_fuzzy);
+
+static const struct luaL_reg textpartlib_m[] = {
+ LUA_INTERFACE_DEF (textpart, get_content),
+ LUA_INTERFACE_DEF (textpart, is_empty),
+ LUA_INTERFACE_DEF (textpart, is_html),
+ LUA_INTERFACE_DEF (textpart, get_fuzzy),
{"__tostring", lua_class_tostring},
{NULL, NULL}
};
/* Utility functions */
-static struct worker_task *
-lua_check_task (lua_State *L)
+static struct worker_task *
+lua_check_task (lua_State * L)
{
- void *ud = luaL_checkudata (L, 1, "rspamd{task}");
+ void *ud = luaL_checkudata (L, 1, "rspamd{task}");
luaL_argcheck (L, ud != NULL, 1, "'task' expected");
return *((struct worker_task **)ud);
}
-static struct mime_text_part *
-lua_check_textpart (lua_State *L)
+static struct mime_text_part *
+lua_check_textpart (lua_State * L)
{
- void *ud = luaL_checkudata (L, 1, "rspamd{textpart}");
+ void *ud = luaL_checkudata (L, 1, "rspamd{textpart}");
luaL_argcheck (L, ud != NULL, 1, "'textpart' expected");
return *((struct mime_text_part **)ud);
}
/*** Task interface ***/
static int
-lua_task_get_message (lua_State *L)
+lua_task_get_message (lua_State * L)
{
- GMimeMessage **pmsg;
- struct worker_task *task = lua_check_task (L);
+ GMimeMessage **pmsg;
+ struct worker_task *task = lua_check_task (L);
if (task != NULL) {
/* XXX write handler for message object */
return 1;
}
-static int
-lua_task_insert_result (lua_State *L)
+static int
+lua_task_insert_result (lua_State * L)
{
- struct worker_task *task = lua_check_task (L);
- const char *metric_name, *symbol_name, *param;
- double flag;
- GList *params = NULL;
- int i, top;
+ struct worker_task *task = lua_check_task (L);
+ const char *metric_name, *symbol_name, *param;
+ double flag;
+ GList *params = NULL;
+ int i, top;
if (task != NULL) {
metric_name = memory_pool_strdup (task->task_pool, luaL_checkstring (L, 2));
flag = luaL_checknumber (L, 4);
top = lua_gettop (L);
/* Get additional options */
- for (i = 5; i <= top; i ++) {
+ for (i = 5; i <= top; i++) {
param = luaL_checkstring (L, i);
params = g_list_prepend (params, memory_pool_strdup (task->task_pool, param));
}
return 1;
}
-static int
-lua_task_get_urls (lua_State *L)
+static int
+lua_task_get_urls (lua_State * L)
{
- int i = 1;
- struct worker_task *task = lua_check_task (L);
- GList *cur;
- struct uri *url;
+ int i = 1;
+ struct worker_task *task = lua_check_task (L);
+ GList *cur;
+ struct uri *url;
if (task != NULL) {
- lua_newtable (L);
+ lua_newtable (L);
cur = g_list_first (task->urls);
while (cur) {
url = cur->data;
lua_pushstring (L, struri (url));
- lua_rawseti(L, -2, i++);
+ lua_rawseti (L, -2, i++);
cur = g_list_next (cur);
}
}
}
static int
-lua_task_get_text_parts (lua_State *L)
+lua_task_get_text_parts (lua_State * L)
{
- int i = 1;
- struct worker_task *task = lua_check_task (L);
- GList *cur;
- struct mime_text_part *part, **ppart;
+ int i = 1;
+ struct worker_task *task = lua_check_task (L);
+ GList *cur;
+ struct mime_text_part *part, **ppart;
if (task != NULL) {
- lua_newtable (L);
+ lua_newtable (L);
cur = task->text_parts;
while (cur) {
part = cur->data;
ppart = lua_newuserdata (L, sizeof (struct mime_text_part *));
*ppart = part;
lua_setclass (L, "rspamd{textpart}", -1);
- /* Make it array */
- lua_rawseti(L, -2, i++);
+ /* Make it array */
+ lua_rawseti (L, -2, i++);
cur = g_list_next (cur);
}
- return 1;
+ return 1;
}
lua_pushnil (L);
return 1;
}
static int
-lua_task_get_raw_headers (lua_State *L)
+lua_task_get_raw_headers (lua_State * L)
{
- struct worker_task *task = lua_check_task (L);
+ struct worker_task *task = lua_check_task (L);
- if (task) {
+ if (task) {
lua_pushstring (L, task->raw_headers);
- }
+ }
else {
lua_pushnil (L);
}
- return 1;
+ return 1;
}
static int
-lua_task_get_received_headers (lua_State *L)
+lua_task_get_received_headers (lua_State * L)
{
- struct worker_task *task = lua_check_task (L);
- GList *cur;
- struct received_header *rh;
- int i = 1;
+ struct worker_task *task = lua_check_task (L);
+ GList *cur;
+ struct received_header *rh;
+ int i = 1;
- if (task) {
+ if (task) {
lua_newtable (L);
cur = g_list_first (task->received);
while (cur) {
lua_set_table_index (L, "real_hostname", rh->real_hostname);
lua_set_table_index (L, "real_ip", rh->real_ip);
lua_set_table_index (L, "by_hostname", rh->by_hostname);
- lua_rawseti(L, -2, i++);
+ lua_rawseti (L, -2, i++);
cur = g_list_next (cur);
}
- }
+ }
else {
lua_pushnil (L);
}
-
+
return 1;
}
struct lua_dns_callback_data {
- lua_State *L;
- struct worker_task *task;
- const char *callback;
- const char *to_resolve;
+ lua_State *L;
+ struct worker_task *task;
+ const char *callback;
+ const char *to_resolve;
};
-static void
+static void
lua_dns_callback (int result, char type, int count, int ttl, void *addresses, void *arg)
{
- struct lua_dns_callback_data *cd = arg;
- int i;
- struct in_addr ina;
- struct worker_task **ptask;
+ struct lua_dns_callback_data *cd = arg;
+ int i;
+ struct in_addr ina;
+ struct worker_task **ptask;
lua_getglobal (cd->L, cd->callback);
ptask = lua_newuserdata (cd->L, sizeof (struct worker_task *));
if (type == DNS_IPv4_A) {
lua_newtable (cd->L);
- for (i = 1; i <= count; i ++) {
- memcpy (&ina.s_addr, ((in_addr_t *)addresses) + i - 1, sizeof (in_addr_t));
+ for (i = 1; i <= count; i++) {
+ memcpy (&ina.s_addr, ((in_addr_t *) addresses) + i - 1, sizeof (in_addr_t));
/* Actually this copy memory, so using of inet_ntoa is valid */
lua_pushstring (cd->L, inet_ntoa (ina));
lua_rawseti (cd->L, -2, i);
}
else if (type == DNS_PTR) {
lua_newtable (cd->L);
- for (i = 1; i <= count; i ++) {
+ for (i = 1; i <= count; i++) {
lua_pushstring (cd->L, ((char **)addresses)[i - 1]);
lua_rawseti (cd->L, -2, i);
}
msg_info ("lua_dns_callback: call to %s failed: %s", cd->callback, lua_tostring (cd->L, -1));
}
- cd->task->save.saved --;
+ cd->task->save.saved--;
if (cd->task->save.saved == 0) {
/* Call other filters */
cd->task->save.saved = 1;
process_filters (cd->task);
}
- remove_forced_event (cd->task->s, (event_finalizer_t)lua_dns_callback);
+ remove_forced_event (cd->task->s, (event_finalizer_t) lua_dns_callback);
}
static int
-lua_task_resolve_dns_a (lua_State *L)
+lua_task_resolve_dns_a (lua_State * L)
{
- struct worker_task *task = lua_check_task (L);
- struct lua_dns_callback_data *cd;
+ struct worker_task *task = lua_check_task (L);
+ struct lua_dns_callback_data *cd;
if (task) {
cd = memory_pool_alloc (task->task_pool, sizeof (struct lua_dns_callback_data));
return 0;
}
if (evdns_resolve_ipv4 (cd->to_resolve, DNS_QUERY_NO_SEARCH, lua_dns_callback, (void *)cd) == 0) {
- task->save.saved ++;
- register_async_event (task->s, (event_finalizer_t)lua_dns_callback, NULL, TRUE);
- }
+ task->save.saved++;
+ register_async_event (task->s, (event_finalizer_t) lua_dns_callback, NULL, TRUE);
+ }
}
return 0;
}
static int
-lua_task_resolve_dns_ptr (lua_State *L)
+lua_task_resolve_dns_ptr (lua_State * L)
{
- struct worker_task *task = lua_check_task (L);
- struct lua_dns_callback_data *cd;
- struct in_addr *ina;
+ struct worker_task *task = lua_check_task (L);
+ struct lua_dns_callback_data *cd;
+ struct in_addr *ina;
if (task) {
cd = memory_pool_alloc (task->task_pool, sizeof (struct lua_dns_callback_data));
return 0;
}
if (evdns_resolve_reverse (ina, DNS_QUERY_NO_SEARCH, lua_dns_callback, (void *)cd) == 0) {
- task->save.saved ++;
- register_async_event (task->s, (event_finalizer_t)lua_dns_callback, NULL, TRUE);
- }
+ task->save.saved++;
+ register_async_event (task->s, (event_finalizer_t) lua_dns_callback, NULL, TRUE);
+ }
}
return 0;
}
static int
-lua_task_call_rspamd_function (lua_State *L)
+lua_task_call_rspamd_function (lua_State * L)
{
- struct worker_task *task = lua_check_task (L);
- struct expression_function f;
- int i, top;
- gboolean res;
- char *arg;
+ struct worker_task *task = lua_check_task (L);
+ struct expression_function f;
+ int i, top;
+ gboolean res;
+ char *arg;
if (task) {
f.name = (char *)luaL_checkstring (L, 2);
f.args = NULL;
top = lua_gettop (L);
/* Get arguments after function name */
- for (i = 3; i <= top; i ++) {
+ for (i = 3; i <= top; i++) {
arg = (char *)luaL_checkstring (L, i);
if (arg != NULL) {
f.args = g_list_prepend (f.args, arg);
/**** Textpart implementation *****/
static int
-lua_textpart_get_content (lua_State *L)
+lua_textpart_get_content (lua_State * L)
{
- struct mime_text_part *part = lua_check_textpart (L);
+ struct mime_text_part *part = lua_check_textpart (L);
if (part == NULL || part->is_empty) {
lua_pushnil (L);
return 1;
}
-
+
lua_pushlstring (L, part->content->data, part->content->len);
return 1;
}
static int
-lua_textpart_is_empty (lua_State *L)
+lua_textpart_is_empty (lua_State * L)
{
- struct mime_text_part *part = lua_check_textpart (L);
+ struct mime_text_part *part = lua_check_textpart (L);
if (part == NULL) {
lua_pushnil (L);
}
static int
-lua_textpart_is_html (lua_State *L)
+lua_textpart_is_html (lua_State * L)
{
- struct mime_text_part *part = lua_check_textpart (L);
+ struct mime_text_part *part = lua_check_textpart (L);
if (part == NULL) {
lua_pushnil (L);
}
static int
-lua_textpart_get_fuzzy (lua_State *L)
+lua_textpart_get_fuzzy (lua_State * L)
{
- struct mime_text_part *part = lua_check_textpart (L);
+ struct mime_text_part *part = lua_check_textpart (L);
if (part == NULL || part->is_empty) {
lua_pushnil (L);
return 1;
}
-
+
lua_pushlstring (L, part->fuzzy->hash_pipe, sizeof (part->fuzzy->hash_pipe));
return 1;
}
/* Init part */
int
-luaopen_task (lua_State *L)
+luaopen_task (lua_State * L)
{
lua_newclass (L, "rspamd{task}", tasklib_m);
luaL_openlib (L, "rspamd_task", null_reg, 0);
-
+
return 1;
}
int
-luaopen_textpart (lua_State *L)
+luaopen_textpart (lua_State * L)
{
lua_newclass (L, "rspamd{textpart}", textpartlib_m);
luaL_openlib (L, "rspamd_textpart", null_reg, 0);
-
+
return 1;
}
-
#ifndef WITHOUT_PERL
-#include <EXTERN.h> /* from the Perl distribution */
-#include <perl.h> /* from the Perl distribution */
+# include <EXTERN.h> /* from the Perl distribution */
+# include <perl.h> /* from the Perl distribution */
-# ifndef PERL_IMPLICIT_CONTEXT
-# undef dTHXa
-# define dTHXa(a)
-# endif
-#include "perl.h"
+# ifndef PERL_IMPLICIT_CONTEXT
+# undef dTHXa
+# define dTHXa(a)
+# endif
+# include "perl.h"
#elif defined(WITH_LUA)
-#include "lua/lua_common.h"
+# include "lua/lua_common.h"
#endif
/* 2 seconds to fork new process in place of dead one */
#define SOFT_FORK_TIME 2
-struct config_file *cfg;
+struct config_file *cfg;
-rspamd_hash_t *counters;
+rspamd_hash_t *counters;
-static void sig_handler (int );
-static struct rspamd_worker * fork_worker (struct rspamd_main *, struct worker_conf *);
-
-sig_atomic_t do_restart;
-sig_atomic_t do_terminate;
-sig_atomic_t child_dead;
-sig_atomic_t child_ready;
-sig_atomic_t got_alarm;
+static void sig_handler (int);
+static struct rspamd_worker *fork_worker (struct rspamd_main *, struct worker_conf *);
-extern int yynerrs;
-extern FILE *yyin;
+sig_atomic_t do_restart;
+sig_atomic_t do_terminate;
+sig_atomic_t child_dead;
+sig_atomic_t child_ready;
+sig_atomic_t got_alarm;
-static int dump_vars = 0;
-static int dump_cache = 0;
+extern int yynerrs;
+extern FILE *yyin;
+
+static int dump_vars = 0;
+static int dump_cache = 0;
#ifndef WITHOUT_PERL
-extern void xs_init(pTHX);
-extern PerlInterpreter *perl_interpreter;
+extern void xs_init (pTHX);
+extern PerlInterpreter *perl_interpreter;
#endif
/* Active workers */
-static GList *active_workers = NULL;
+static GList *active_workers = NULL;
/* List of workers that are pending to start */
-static GList *workers_pending = NULL;
+static GList *workers_pending = NULL;
-static
-void sig_handler (int signo)
+static
+ void
+sig_handler (int signo)
{
switch (signo) {
- case SIGHUP:
- do_restart = 1;
- do_reopen_log = 1;
- break;
- case SIGINT:
- case SIGTERM:
- do_terminate = 1;
- break;
- case SIGCHLD:
- child_dead = 1;
- break;
- case SIGUSR2:
- child_ready = 1;
- break;
- case SIGALRM:
- got_alarm = 1;
- break;
+ case SIGHUP:
+ do_restart = 1;
+ do_reopen_log = 1;
+ break;
+ case SIGINT:
+ case SIGTERM:
+ do_terminate = 1;
+ break;
+ case SIGCHLD:
+ child_dead = 1;
+ break;
+ case SIGUSR2:
+ child_ready = 1;
+ break;
+ case SIGALRM:
+ got_alarm = 1;
+ break;
}
}
-static void
+static void
read_cmd_line (int argc, char **argv, struct config_file *cfg)
{
- int ch;
- while ((ch = getopt(argc, argv, "tVChfc:u:g:")) != -1) {
+ int ch;
+ while ((ch = getopt (argc, argv, "tVChfc:u:g:")) != -1) {
switch (ch) {
- case 'f':
- cfg->no_fork = 1;
- break;
- case 'c':
- if (optarg && cfg->cfg_name) {
- cfg->cfg_name = memory_pool_strdup (cfg->cfg_pool, optarg);
- }
- break;
- case 't':
- cfg->config_test = 1;
- break;
- case 'V':
- dump_vars = 1;
- break;
- case 'C':
- dump_cache = 1;
- break;
- case 'u':
- if (optarg) {
- cfg->rspamd_user = memory_pool_strdup (cfg->cfg_pool, optarg);
- }
- break;
- case 'g':
- if (optarg) {
- cfg->rspamd_group = memory_pool_strdup (cfg->cfg_pool, optarg);
- }
- break;
- case 'h':
- case '?':
- default:
- /* Show help message and exit */
- printf ("Rspamd version " RVERSION "\n"
- "Usage: rspamd [-t] [-h] [-n] [-f] [-c config_file]\n"
- "-h: This help message\n"
- "-t: Do config test and exit\n"
- "-C: Dump symbols cache stats and exit\n"
- "-V Print all rspamd variables and exit\n"
- "-f: Do not daemonize main process\n"
- "-c: Specify config file (./rspamd.conf is used by default)\n"
- "-u: User to run rspamd as\n"
- "-g: Group to run rspamd as\n");
- exit (0);
- break;
+ case 'f':
+ cfg->no_fork = 1;
+ break;
+ case 'c':
+ if (optarg && cfg->cfg_name) {
+ cfg->cfg_name = memory_pool_strdup (cfg->cfg_pool, optarg);
+ }
+ break;
+ case 't':
+ cfg->config_test = 1;
+ break;
+ case 'V':
+ dump_vars = 1;
+ break;
+ case 'C':
+ dump_cache = 1;
+ break;
+ case 'u':
+ if (optarg) {
+ cfg->rspamd_user = memory_pool_strdup (cfg->cfg_pool, optarg);
+ }
+ break;
+ case 'g':
+ if (optarg) {
+ cfg->rspamd_group = memory_pool_strdup (cfg->cfg_pool, optarg);
+ }
+ break;
+ case 'h':
+ case '?':
+ default:
+ /* Show help message and exit */
+ printf ("Rspamd version " RVERSION "\n"
+ "Usage: rspamd [-t] [-h] [-n] [-f] [-c config_file]\n"
+ "-h: This help message\n"
+ "-t: Do config test and exit\n"
+ "-C: Dump symbols cache stats and exit\n"
+ "-V Print all rspamd variables and exit\n"
+ "-f: Do not daemonize main process\n"
+ "-c: Specify config file (./rspamd.conf is used by default)\n" "-u: User to run rspamd as\n" "-g: Group to run rspamd as\n");
+ exit (0);
+ break;
}
}
}
static void
-drop_priv (struct config_file *cfg)
+drop_priv (struct config_file *cfg)
{
- struct passwd *pwd;
- struct group *grp;
+ struct passwd *pwd;
+ struct group *grp;
if (geteuid () == 0 && cfg->rspamd_user) {
pwd = getpwnam (cfg->rspamd_user);
msg_err ("drop_priv: cannot setgid to %d (%s), aborting", (int)grp->gr_gid, strerror (errno));
exit (-errno);
}
- if (initgroups(cfg->rspamd_user, grp->gr_gid) == -1) {
+ if (initgroups (cfg->rspamd_user, grp->gr_gid) == -1) {
msg_err ("drop_priv: initgroups failed (%s), aborting", strerror (errno));
exit (-errno);
}
config_logger (struct rspamd_main *rspamd, gboolean is_fatal)
{
switch (rspamd->cfg->log_type) {
- case RSPAMD_LOG_CONSOLE:
- if (!rspamd->cfg->no_fork) {
- if (is_fatal) {
- fprintf (stderr, "Cannot log to console while daemonized, disable logging\n");
- }
- rspamd->cfg->log_fd = -1;
- rspamd->cfg->logf = NULL;
+ case RSPAMD_LOG_CONSOLE:
+ if (!rspamd->cfg->no_fork) {
+ if (is_fatal) {
+ fprintf (stderr, "Cannot log to console while daemonized, disable logging\n");
}
- else {
- rspamd->cfg->logf = stderr;
- rspamd->cfg->log_fd = STDERR_FILENO;
- }
- rspamd_set_logger (file_log_function, rspamd->cfg);
- g_log_set_default_handler (file_log_function, rspamd->cfg);
- break;
- case RSPAMD_LOG_FILE:
- if (rspamd->cfg->log_file == NULL || open_log (rspamd->cfg) == -1) {
- if (is_fatal) {
- fprintf (stderr, "Fatal error, cannot open logfile, exiting\n");
- exit (EXIT_FAILURE);
- }
- else {
- msg_err ("config_logger: cannot log to file, logfile unaccessable");
- }
+ rspamd->cfg->log_fd = -1;
+ rspamd->cfg->logf = NULL;
+ }
+ else {
+ rspamd->cfg->logf = stderr;
+ rspamd->cfg->log_fd = STDERR_FILENO;
+ }
+ rspamd_set_logger (file_log_function, rspamd->cfg);
+ g_log_set_default_handler (file_log_function, rspamd->cfg);
+ break;
+ case RSPAMD_LOG_FILE:
+ if (rspamd->cfg->log_file == NULL || open_log (rspamd->cfg) == -1) {
+ if (is_fatal) {
+ fprintf (stderr, "Fatal error, cannot open logfile, exiting\n");
+ exit (EXIT_FAILURE);
}
else {
- rspamd_set_logger (file_log_function, rspamd->cfg);
- g_log_set_default_handler (file_log_function, rspamd->cfg);
+ msg_err ("config_logger: cannot log to file, logfile unaccessable");
}
- break;
- case RSPAMD_LOG_SYSLOG:
- if (open_log (rspamd->cfg) == -1) {
- if (is_fatal) {
- fprintf (stderr, "Fatal error, cannot open syslog facility, exiting\n");
- exit (EXIT_FAILURE);
- }
- else {
- msg_err ("config_logger: cannot log to syslog");
- }
+ }
+ else {
+ rspamd_set_logger (file_log_function, rspamd->cfg);
+ g_log_set_default_handler (file_log_function, rspamd->cfg);
+ }
+ break;
+ case RSPAMD_LOG_SYSLOG:
+ if (open_log (rspamd->cfg) == -1) {
+ if (is_fatal) {
+ fprintf (stderr, "Fatal error, cannot open syslog facility, exiting\n");
+ exit (EXIT_FAILURE);
}
else {
- rspamd_set_logger (syslog_log_function, rspamd->cfg);
- g_log_set_default_handler (syslog_log_function, rspamd->cfg);
+ msg_err ("config_logger: cannot log to syslog");
}
- break;
+ }
+ else {
+ rspamd_set_logger (syslog_log_function, rspamd->cfg);
+ g_log_set_default_handler (syslog_log_function, rspamd->cfg);
+ }
+ break;
}
}
static void
reread_config (struct rspamd_main *rspamd)
{
- struct config_file *tmp_cfg;
- char *cfg_file;
- FILE *f;
+ struct config_file *tmp_cfg;
+ char *cfg_file;
+ FILE *f;
- tmp_cfg = (struct config_file *) g_malloc (sizeof (struct config_file));
+ tmp_cfg = (struct config_file *)g_malloc (sizeof (struct config_file));
if (tmp_cfg) {
bzero (tmp_cfg, sizeof (struct config_file));
tmp_cfg->cfg_pool = memory_pool_new (memory_pool_get_size ());
init_defaults (tmp_cfg);
cfg_file = memory_pool_strdup (tmp_cfg->cfg_pool, rspamd->cfg->cfg_name);
- f = fopen (rspamd->cfg->cfg_name , "r");
+ f = fopen (rspamd->cfg->cfg_name, "r");
if (f == NULL) {
- msg_warn ("reread_config: cannot open file: %s", rspamd->cfg->cfg_name );
+ msg_warn ("reread_config: cannot open file: %s", rspamd->cfg->cfg_name);
}
else {
yyin = f;
yyrestart (yyin);
- if (yyparse() != 0 || yynerrs > 0) {
+ if (yyparse () != 0 || yynerrs > 0) {
msg_warn ("reread_config: yyparse: cannot parse config file, %d errors", yynerrs);
fclose (f);
}
}
}
-static struct rspamd_worker *
-fork_worker (struct rspamd_main *rspamd, struct worker_conf *cf)
+static struct rspamd_worker *
+fork_worker (struct rspamd_main *rspamd, struct worker_conf *cf)
{
- struct rspamd_worker *cur;
+ struct rspamd_worker *cur;
/* Starting worker process */
cur = (struct rspamd_worker *)g_malloc (sizeof (struct rspamd_worker));
if (cur) {
bzero (cur, sizeof (struct rspamd_worker));
- active_workers = g_list_prepend (active_workers, cur);
+ active_workers = g_list_prepend (active_workers, cur);
cur->srv = rspamd;
cur->type = cf->type;
- cur->pid = fork();
+ cur->pid = fork ();
cur->cf = cf;
cur->pending = FALSE;
switch (cur->pid) {
- case 0:
- /* Drop privilleges */
- drop_priv (cfg);
- switch (cf->type) {
- case TYPE_CONTROLLER:
- setproctitle ("controller process");
- pidfile_close (rspamd->pfh);
- msg_info ("fork_worker: starting controller process %d", getpid ());
- start_controller (cur);
- break;
- case TYPE_LMTP:
- setproctitle ("lmtp process");
- pidfile_close (rspamd->pfh);
- msg_info ("fork_worker: starting lmtp process %d", getpid ());
- start_lmtp_worker (cur);
- break;
- case TYPE_FUZZY:
- setproctitle ("fuzzy storage");
- pidfile_close (rspamd->pfh);
- msg_info ("fork_worker: starting fuzzy storage process %d", getpid ());
- start_fuzzy_storage (cur);
- break;
- case TYPE_WORKER:
- default:
- setproctitle ("worker process");
- pidfile_close (rspamd->pfh);
- msg_info ("fork_worker: starting worker process %d", getpid ());
- start_worker (cur);
- break;
- }
+ case 0:
+ /* Drop privilleges */
+ drop_priv (cfg);
+ switch (cf->type) {
+ case TYPE_CONTROLLER:
+ setproctitle ("controller process");
+ pidfile_close (rspamd->pfh);
+ msg_info ("fork_worker: starting controller process %d", getpid ());
+ start_controller (cur);
break;
- case -1:
- msg_err ("fork_worker: cannot fork main process. %s", strerror (errno));
- pidfile_remove (rspamd->pfh);
- exit (-errno);
+ case TYPE_LMTP:
+ setproctitle ("lmtp process");
+ pidfile_close (rspamd->pfh);
+ msg_info ("fork_worker: starting lmtp process %d", getpid ());
+ start_lmtp_worker (cur);
+ break;
+ case TYPE_FUZZY:
+ setproctitle ("fuzzy storage");
+ pidfile_close (rspamd->pfh);
+ msg_info ("fork_worker: starting fuzzy storage process %d", getpid ());
+ start_fuzzy_storage (cur);
break;
+ case TYPE_WORKER:
+ default:
+ setproctitle ("worker process");
+ pidfile_close (rspamd->pfh);
+ msg_info ("fork_worker: starting worker process %d", getpid ());
+ start_worker (cur);
+ break;
+ }
+ break;
+ case -1:
+ msg_err ("fork_worker: cannot fork main process. %s", strerror (errno));
+ pidfile_remove (rspamd->pfh);
+ exit (-errno);
+ break;
}
}
static void
dump_module_variables (gpointer key, gpointer value, gpointer data)
-{
- GList *cur_opt;
- struct module_opt *cur;
-
- cur_opt = (GList *)value;
+{
+ GList *cur_opt;
+ struct module_opt *cur;
+
+ cur_opt = (GList *) value;
while (cur_opt) {
cur = cur_opt->data;
static int
create_listen_socket (struct in_addr *addr, int port, int family, char *path)
{
- int listen_sock = -1;
- struct sockaddr_un *un_addr;
+ int listen_sock = -1;
+ struct sockaddr_un *un_addr;
/* Create listen socket */
if (family == AF_INET) {
if ((listen_sock = make_tcp_socket (addr, port, TRUE, TRUE)) == -1) {
}
}
else {
- un_addr = (struct sockaddr_un *) alloca (sizeof (struct sockaddr_un));
+ un_addr = (struct sockaddr_un *)alloca (sizeof (struct sockaddr_un));
if (!un_addr || (listen_sock = make_unix_socket (path, un_addr, TRUE)) == -1) {
msg_err ("create_listen_socket: cannot create unix listen socket. %s", strerror (errno));
}
}
-
+
if (listen_sock != -1) {
if (listen (listen_sock, -1) == -1) {
msg_err ("start_lmtp: cannot listen on socket. %s", strerror (errno));
static void
fork_delayed (struct rspamd_main *rspamd)
{
- GList *cur;
- struct worker_conf *cf;
+ GList *cur;
+ struct worker_conf *cf;
while (workers_pending != NULL) {
cur = workers_pending;
static void
spawn_workers (struct rspamd_main *rspamd)
{
- GList *cur;
- struct worker_conf *cf;
- int i, listen_sock;
+ GList *cur;
+ struct worker_conf *cf;
+ int i, listen_sock;
cur = cfg->workers;
/* Create listen socket */
if (cf->type != TYPE_FUZZY) {
- listen_sock = create_listen_socket (&cf->bind_addr, cf->bind_port,
- cf->bind_family, cf->bind_host);
+ listen_sock = create_listen_socket (&cf->bind_addr, cf->bind_port, cf->bind_family, cf->bind_host);
if (listen_sock == -1) {
- exit(-errno);
+ exit (-errno);
}
cf->listen_sock = listen_sock;
}
}
}
-static const char *
+static const char *
get_process_type (enum process_type type)
{
switch (type) {
- case TYPE_MAIN:
- return "main";
- case TYPE_WORKER:
- return "worker";
- case TYPE_FUZZY:
- return "fuzzy";
- case TYPE_CONTROLLER:
- return "controller";
- case TYPE_LMTP:
- return "lmtp";
+ case TYPE_MAIN:
+ return "main";
+ case TYPE_WORKER:
+ return "worker";
+ case TYPE_FUZZY:
+ return "fuzzy";
+ case TYPE_CONTROLLER:
+ return "controller";
+ case TYPE_LMTP:
+ return "lmtp";
}
return NULL;
}
-int
+int
main (int argc, char **argv, char **env)
{
- struct rspamd_main *rspamd;
- struct module_ctx *cur_module = NULL;
- int res = 0, i;
- struct sigaction signals;
- struct rspamd_worker *cur, *active_worker;
- struct rlimit rlim;
- struct metric *metric;
- struct cache_item *item;
- struct filter *filt;
- FILE *f;
- pid_t wrk;
- GList *l;
+ struct rspamd_main *rspamd;
+ struct module_ctx *cur_module = NULL;
+ int res = 0, i;
+ struct sigaction signals;
+ struct rspamd_worker *cur, *active_worker;
+ struct rlimit rlim;
+ struct metric *metric;
+ struct cache_item *item;
+ struct filter *filt;
+ FILE *f;
+ pid_t wrk;
+ GList *l;
#ifndef WITHOUT_PERL
- char *args[] = { "", "-e", "0", NULL };
+ char *args[] = { "", "-e", "0", NULL };
#endif
rspamd = (struct rspamd_main *)g_malloc (sizeof (struct rspamd_main));
cfg = (struct config_file *)g_malloc (sizeof (struct config_file));
rspamd->cfg = cfg;
if (!rspamd || !rspamd->cfg) {
- fprintf(stderr, "Cannot allocate memory\n");
- exit(-errno);
+ fprintf (stderr, "Cannot allocate memory\n");
+ exit (-errno);
}
-
+
do_terminate = 0;
do_restart = 0;
child_dead = 0;
#ifndef HAVE_SETPROCTITLE
init_title (argc, argv, environ);
#endif
-
- f = fopen (rspamd->cfg->cfg_name , "r");
+
+ f = fopen (rspamd->cfg->cfg_name, "r");
if (f == NULL) {
- msg_err ("main: cannot open file: %s", rspamd->cfg->cfg_name );
+ msg_err ("main: cannot open file: %s", rspamd->cfg->cfg_name);
return EBADF;
}
yyin = f;
- if (yyparse() != 0 || yynerrs > 0) {
+ if (yyparse () != 0 || yynerrs > 0) {
msg_err ("main: cannot parse config file, %d errors", yynerrs);
return EBADF;
}
counters = rspamd_hash_new_shared (rspamd->server_pool, g_str_hash, g_str_equal, 64);
/* Init C modules */
- l = g_list_first (rspamd->cfg->filters);
+ l = g_list_first (rspamd->cfg->filters);
while (l) {
filt = l->data;
if (filt->module) {
cur_module = memory_pool_alloc (rspamd->cfg->cfg_pool, sizeof (struct module_ctx));
- if (filt->module->module_init_func(cfg, &cur_module) == 0) {
- g_hash_table_insert (cfg->c_modules, (gpointer)filt->module->name, cur_module);
+ if (filt->module->module_init_func (cfg, &cur_module) == 0) {
+ g_hash_table_insert (cfg->c_modules, (gpointer) filt->module->name, cur_module);
}
}
l = g_list_next (l);
}
l = g_list_next (l);
}
- #if defined(WITH_LUA)
+#if defined(WITH_LUA)
init_lua_filters (cfg);
- #endif
+#endif
if (dump_vars) {
dump_cfg_vars ();
}
printf ("Cache for metric: %s\n", metric->name);
printf ("-----------------------------------------------------------------\n");
printf ("| Pri | Symbol | Weight | Frequency | Avg. time |\n");
- for (i = 0; i < metric->cache->used_items; i ++) {
+ for (i = 0; i < metric->cache->used_items; i++) {
item = &metric->cache->items[i];
printf ("-----------------------------------------------------------------\n");
- printf ("| %3d | %22s | %6.1f | %9d | %9.3f |\n", i, item->s->symbol,
- item->s->weight, item->s->frequency,
- item->s->avg_time);
+ printf ("| %3d | %22s | %6.1f | %9d | %9.3f |\n", i, item->s->symbol, item->s->weight, item->s->frequency, item->s->avg_time);
}
printf ("-----------------------------------------------------------------\n");
}
/* Set stack size for pcre */
- getrlimit(RLIMIT_STACK, &rlim);
+ getrlimit (RLIMIT_STACK, &rlim);
rlim.rlim_cur = 100 * 1024 * 1024;
- setrlimit(RLIMIT_STACK, &rlim);
-
+ setrlimit (RLIMIT_STACK, &rlim);
+
config_logger (rspamd, TRUE);
- msg_info ("main: rspamd "RVERSION " is starting");
- rspamd->cfg->cfg_name = memory_pool_strdup (rspamd->cfg->cfg_pool, rspamd->cfg->cfg_name );
+ msg_info ("main: rspamd " RVERSION " is starting");
+ rspamd->cfg->cfg_name = memory_pool_strdup (rspamd->cfg->cfg_pool, rspamd->cfg->cfg_name);
/* Strictly set temp dir */
if (!rspamd->cfg->temp_dir) {
exit (-errno);
}
- rspamd->pid = getpid();
+ rspamd->pid = getpid ();
rspamd->type = TYPE_MAIN;
-
+
init_signals (&signals, sig_handler);
#endif
/* Block signals to use sigsuspend in future */
- sigprocmask(SIG_BLOCK, &signals.sa_mask, NULL);
+ sigprocmask (SIG_BLOCK, &signals.sa_mask, NULL);
setproctitle ("main process");
l = g_list_next (l);
}
-
+
spawn_workers (rspamd);
/* Signal processing cycle */
msg_debug ("main: catch SIGCHLD signal, finding terminated worker");
/* Remove dead child form childs list */
wrk = waitpid (0, &res, 0);
- l = g_list_first (active_workers);
- while (l) {
- cur = l->data;
+ l = g_list_first (active_workers);
+ while (l) {
+ cur = l->data;
if (wrk == cur->pid) {
/* Catch situations if active worker is abnormally terminated */
if (cur == active_worker) {
active_worker = NULL;
}
- active_workers = g_list_remove_link (active_workers, l);
+ active_workers = g_list_remove_link (active_workers, l);
if (WIFEXITED (res) && WEXITSTATUS (res) == 0) {
/* Normal worker termination, do not fork one more */
- msg_info ("main: %s process %d terminated normally",
- get_process_type (cur->type), cur->pid);
+ msg_info ("main: %s process %d terminated normally", get_process_type (cur->type), cur->pid);
}
else {
if (WIFSIGNALED (res)) {
- msg_warn ("main: %s process %d terminated abnormally by signal: %d",
- get_process_type (cur->type),
- cur->pid, WTERMSIG(res));
+ msg_warn ("main: %s process %d terminated abnormally by signal: %d", get_process_type (cur->type), cur->pid, WTERMSIG (res));
}
else {
- msg_warn ("main: %s process %d terminated abnormally",
- get_process_type (cur->type), cur->pid);
+ msg_warn ("main: %s process %d terminated abnormally", get_process_type (cur->type), cur->pid);
}
/* Fork another worker in replace of dead one */
delay_fork (cur->cf);
}
- g_list_free_1 (l);
+ g_list_free_1 (l);
g_free (cur);
}
l = g_list_next (l);
}
}
- if (do_restart) {
+ if (do_restart) {
do_restart = 0;
do_reopen_log = 1;
msg_info ("main: rspamd " RVERSION " is restarting");
- l = g_list_first (active_workers);
- while (l) {
- cur = l->data;
- /* Start new workers that would reread configuration */
+ l = g_list_first (active_workers);
+ while (l) {
+ cur = l->data;
+ /* Start new workers that would reread configuration */
cur->pending = FALSE;
active_worker = fork_worker (rspamd, cur->cf);
- active_worker->pending = TRUE;
+ active_worker->pending = TRUE;
l = g_list_next (l);
- }
+ }
}
if (child_ready) {
child_ready = 0;
cur->is_dying = 1;
}
else {
- msg_info ("main: %s process %d has been successfully started",
- get_process_type (cur->type), cur->pid);
+ msg_info ("main: %s process %d has been successfully started", get_process_type (cur->type), cur->pid);
}
l = g_list_next (l);
}
}
g_list_free (active_workers);
-
+
msg_info ("main: terminating...");
-
+
free_config (rspamd->cfg);
g_free (rspamd->cfg);
g_free (rspamd);
#include "util.h"
#include "mem_pool.h"
-static memory_pool_t *map_pool = NULL;
+static memory_pool_t *map_pool = NULL;
-static GList *maps = NULL;
-static char *hash_fill = "1";
+static GList *maps = NULL;
+static char *hash_fill = "1";
/* Http reply */
struct http_reply {
- int code;
- GHashTable *headers;
- char *cur_header;
+ int code;
+ GHashTable *headers;
+ char *cur_header;
- int parser_state;
+ int parser_state;
};
struct http_callback_data {
- struct event ev;
- struct timeval tv;
- struct rspamd_map *map;
- struct http_map_data *data;
- struct http_reply *reply;
- struct map_cb_data cbdata;
-
- int state;
- int fd;
+ struct event ev;
+ struct timeval tv;
+ struct rspamd_map *map;
+ struct http_map_data *data;
+ struct http_reply *reply;
+ struct map_cb_data cbdata;
+
+ int state;
+ int fd;
};
/* Value in seconds after whitch we would try to do stat on list file */
static int
connect_http (struct rspamd_map *map, struct http_map_data *data, gboolean is_async)
{
- int sock;
+ int sock;
if ((sock = make_tcp_socket (&data->addr, data->port, FALSE, is_async)) == -1) {
msg_info ("connect_http: cannot connect to http server %s: %d, %s", data->host, errno, strerror (errno));
static void
write_http_request (struct rspamd_map *map, struct http_map_data *data, int sock)
{
- char outbuf[BUFSIZ];
- int r;
+ char outbuf[BUFSIZ];
+ int r;
- r = snprintf (outbuf, sizeof (outbuf), "GET %s%s HTTP/1.1" CRLF
- "Connection: close" CRLF
- "Host: %s" CRLF, (*data->path == '/') ? "" : "/",
- data->path, data->host);
+ r = snprintf (outbuf, sizeof (outbuf), "GET %s%s HTTP/1.1" CRLF "Connection: close" CRLF "Host: %s" CRLF, (*data->path == '/') ? "" : "/", data->path, data->host);
if (data->last_checked != 0) {
r += snprintf (outbuf + r, sizeof (outbuf) - r, "If-Modified-Since: %s" CRLF, asctime (gmtime (&data->last_checked)));
}
}
}
-static u_char *
-parse_http_reply (u_char *chunk, size_t len, struct http_reply *reply)
+static u_char *
+parse_http_reply (u_char * chunk, size_t len, struct http_reply *reply)
{
- u_char *s, *p, *err_str, *tmp;
+ u_char *s, *p, *err_str, *tmp;
p = chunk;
s = chunk;
while (p - chunk < len) {
switch (reply->parser_state) {
/* Search status code */
- case 0:
- /* Search for status code */
- if (*p != ' ') {
- p ++;
- }
- else {
- /* Try to parse HTTP reply code */
- reply->code = strtoul (++p, (char **)&err_str, 10);
- if (*err_str != ' ') {
- msg_info ("parse_http_reply: error while reading HTTP status code: %s", p);
- return NULL;
- }
- /* Now skip to end of status string */
- reply->parser_state = 1;
- continue;
+ case 0:
+ /* Search for status code */
+ if (*p != ' ') {
+ p++;
+ }
+ else {
+ /* Try to parse HTTP reply code */
+ reply->code = strtoul (++p, (char **)&err_str, 10);
+ if (*err_str != ' ') {
+ msg_info ("parse_http_reply: error while reading HTTP status code: %s", p);
+ return NULL;
}
- break;
+ /* Now skip to end of status string */
+ reply->parser_state = 1;
+ continue;
+ }
+ break;
/* Skip to end of line */
- case 1:
- if (*p == '\n') {
- /* Switch to read header state */
- reply->parser_state = 2;
- }
- /* Each skipped symbol is proceeded */
- s = ++p;
- break;
+ case 1:
+ if (*p == '\n') {
+ /* Switch to read header state */
+ reply->parser_state = 2;
+ }
+ /* Each skipped symbol is proceeded */
+ s = ++p;
+ break;
/* Read header value */
- case 2:
- if (*p == ':') {
- reply->cur_header = g_malloc (p - s + 1);
- g_strlcpy (reply->cur_header, s, p - s + 1);
- reply->parser_state = 3;
- }
- else if (*p == '\r' && *(p + 1) == '\n') {
- /* Last empty line */
- reply->parser_state = 5;
- }
- p ++;
- break;
+ case 2:
+ if (*p == ':') {
+ reply->cur_header = g_malloc (p - s + 1);
+ g_strlcpy (reply->cur_header, s, p - s + 1);
+ reply->parser_state = 3;
+ }
+ else if (*p == '\r' && *(p + 1) == '\n') {
+ /* Last empty line */
+ reply->parser_state = 5;
+ }
+ p++;
+ break;
/* Skip spaces after header name */
- case 3:
- if (*p != ' ') {
- s = p;
- reply->parser_state = 4;
- }
- else {
- p ++;
- }
- break;
+ case 3:
+ if (*p != ' ') {
+ s = p;
+ reply->parser_state = 4;
+ }
+ else {
+ p++;
+ }
+ break;
/* Read header value */
- case 4:
- if (*p == '\r') {
- if (reply->cur_header != NULL) {
- tmp = g_malloc (p - s + 1);
- g_strlcpy (tmp, s, p - s + 1);
- g_hash_table_insert (reply->headers, reply->cur_header, tmp);
- reply->cur_header = NULL;
- }
- reply->parser_state = 1;
+ case 4:
+ if (*p == '\r') {
+ if (reply->cur_header != NULL) {
+ tmp = g_malloc (p - s + 1);
+ g_strlcpy (tmp, s, p - s + 1);
+ g_hash_table_insert (reply->headers, reply->cur_header, tmp);
+ reply->cur_header = NULL;
}
- p ++;
- break;
- case 5:
- /* Set pointer to begining of HTTP body */
- p ++;
- s = p;
- reply->parser_state = 6;
- break;
- case 6:
- /* Headers parsed, just return */
- return p;
- break;
+ reply->parser_state = 1;
+ }
+ p++;
+ break;
+ case 5:
+ /* Set pointer to begining of HTTP body */
+ p++;
+ s = p;
+ reply->parser_state = 6;
+ break;
+ case 6:
+ /* Headers parsed, just return */
+ return p;
+ break;
}
}
}
static int
-read_chunk_header (u_char *buf, size_t len, struct http_map_data *data)
+read_chunk_header (u_char * buf, size_t len, struct http_map_data *data)
{
- u_char chunkbuf[32], *p, *c;
- int skip = 0;
+ u_char chunkbuf[32], *p, *c;
+ int skip = 0;
p = chunkbuf;
c = buf;
while (g_ascii_isxdigit (*c) && p - chunkbuf < sizeof (chunkbuf) - 1) {
*p++ = *c++;
- skip ++;
+ skip++;
}
*p = '\0';
data->chunk = strtoul (chunkbuf, NULL, 16);
/* Now skip to CRLF */
while (*c != '\n' && c - buf < len) {
- c ++;
- skip ++;
+ c++;
+ skip++;
}
if (*c == '\n') {
- skip ++;
- c ++;
+ skip++;
+ c++;
}
data->chunk_read = 0;
-
+
return skip;
}
-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)
+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)
{
- u_char *p = buf, *remain;
- uint32_t skip = 0, rlen;
-
+ u_char *p = buf, *remain;
+ uint32_t skip = 0, rlen;
+
if (data->chunk == 0) {
/* Read first chunk data */
skip = read_chunk_header (buf, len, data);
return TRUE;
}
-static gboolean
+static gboolean
read_http_common (struct rspamd_map *map, struct http_map_data *data, struct http_reply *reply, struct map_cb_data *cbdata, int fd)
{
- u_char buf[BUFSIZ], *remain, *pos;
- int rlen;
- ssize_t r;
- char *te;
+ u_char buf[BUFSIZ], *remain, *pos;
+ int rlen;
+ ssize_t r;
+ char *te;
rlen = 0;
if ((r = read (fd, buf + rlen, sizeof (buf) - rlen - 1)) > 0) {
- buf[r ++] = '\0';
+ buf[r++] = '\0';
remain = parse_http_reply (buf, r - 1, reply);
if (remain != NULL && remain != buf) {
/* copy remaining buffer to start of buffer */
static void
read_http_sync (struct rspamd_map *map, struct http_map_data *data)
{
- struct map_cb_data cbdata;
- int fd;
- struct http_reply *repl;
+ struct map_cb_data cbdata;
+ int fd;
+ struct http_reply *repl;
if (map->read_callback == NULL || map->fin_callback == NULL) {
msg_err ("read_map_file: bad callback for reading map file");
return;
}
write_http_request (map, data, fd);
-
+
cbdata.state = 0;
cbdata.prev_data = *map->user_data;
cbdata.cur_data = NULL;
repl->parser_state = 0;
repl->code = 404;
repl->headers = g_hash_table_new_full (rspamd_strcase_hash, rspamd_strcase_equal, g_free, g_free);
-
+
while (read_http_common (map, data, repl, &cbdata, fd));
close (fd);
static void
read_map_file (struct rspamd_map *map, struct file_map_data *data)
{
- struct map_cb_data cbdata;
- u_char buf[BUFSIZ], *remain;
- ssize_t r;
- int fd, rlen;
-
+ struct map_cb_data cbdata;
+ u_char buf[BUFSIZ], *remain;
+ ssize_t r;
+ int fd, rlen;
+
if (map->read_callback == NULL || map->fin_callback == NULL) {
msg_err ("read_map_file: bad callback for reading map file");
return;
cbdata.state = 0;
cbdata.prev_data = *map->user_data;
cbdata.cur_data = NULL;
-
+
rlen = 0;
while ((r = read (fd, buf + rlen, sizeof (buf) - rlen - 1)) > 0) {
- buf[r ++] = '\0';
+ buf[r++] = '\0';
remain = map->read_callback (map->pool, buf, r - 1, &cbdata);
if (remain != NULL) {
/* copy remaining buffer to start of buffer */
memmove (buf, remain, rlen);
}
}
-
+
close (fd);
map->fin_callback (map->pool, &cbdata);
*map->user_data = cbdata.cur_data;
}
-gboolean
+gboolean
add_map (const char *map_line, map_cb_t read_callback, map_fin_cb_t fin_callback, void **user_data)
{
- struct rspamd_map *new_map;
- enum fetch_proto proto;
- const char *def, *p, *hostend;
- struct file_map_data *fdata;
- struct http_map_data *hdata;
- char portbuf[6];
- int i, s, fd;
- struct hostent *hent;
+ struct rspamd_map *new_map;
+ enum fetch_proto proto;
+ const char *def, *p, *hostend;
+ struct file_map_data *fdata;
+ struct http_map_data *hdata;
+ char portbuf[6];
+ int i, s, fd;
+ struct hostent *hent;
/* First of all detect protocol line */
if (strncmp (map_line, "http://", sizeof ("http://") - 1) == 0) {
new_map->fin_callback = fin_callback;
new_map->user_data = user_data;
new_map->protocol = proto;
-
+
/* Now check for each proto separately */
if (proto == PROTO_FILE) {
if ((fd = open (def, O_RDONLY)) == -1) {
if ((p = strchr (def, ':')) != NULL) {
hostend = p;
i = 0;
- p ++;
+ p++;
while (g_ascii_isdigit (*p) && i < sizeof (portbuf) - 1) {
- portbuf[i ++] = *p ++;
+ portbuf[i++] = *p++;
}
if (*p != '/') {
msg_info ("add_map: bad http map definition: %s", def);
return FALSE;
}
else {
- memcpy (&hdata->addr, hent->h_addr, sizeof(struct in_addr));
+ memcpy (&hdata->addr, hent->h_addr, sizeof (struct in_addr));
}
}
/* Now try to connect */
return TRUE;
}
-typedef void (*insert_func)(gpointer st, gconstpointer key, gpointer value);
+typedef void (*insert_func) (gpointer st, gconstpointer key, gpointer value);
-static u_char*
-abstract_parse_list (memory_pool_t *pool, u_char *chunk, size_t len, struct map_cb_data *data, insert_func func)
+static u_char *
+abstract_parse_list (memory_pool_t * pool, u_char * chunk, size_t len, struct map_cb_data *data, insert_func func)
{
- u_char *s, *p, *str, *start;
+ u_char *s, *p, *str, *start;
p = chunk;
start = p;
while (p - chunk < len) {
switch (data->state) {
/* READ_SYMBOL */
- case 0:
- if (*p == '#') {
- if (s != str) {
- *s = '\0';
- s = memory_pool_strdup (pool, g_strstrip (str));
- if (strlen (s) > 0) {
- func (data->cur_data, s, hash_fill);
- }
- s = str;
- start = p;
- }
- data->state = 1;
- }
- else if (*p == '\r' || *p == '\n') {
- if (s != str) {
- *s = '\0';
- s = memory_pool_strdup (pool, g_strstrip (str));
- if (strlen (s) > 0) {
- func (data->cur_data, s, hash_fill);
- }
- s = str;
- start = p;
+ case 0:
+ if (*p == '#') {
+ if (s != str) {
+ *s = '\0';
+ s = memory_pool_strdup (pool, g_strstrip (str));
+ if (strlen (s) > 0) {
+ func (data->cur_data, s, hash_fill);
}
- while (*p == '\r' || *p == '\n') {
- p ++;
- }
- }
- else {
- *s = *p;
- s ++;
- p ++;
+ s = str;
+ start = p;
}
- break;
- /* SKIP_COMMENT */
- case 1:
- if (*p == '\r' || *p == '\n') {
- while (*p == '\r' || *p == '\n') {
- p ++;
+ data->state = 1;
+ }
+ else if (*p == '\r' || *p == '\n') {
+ if (s != str) {
+ *s = '\0';
+ s = memory_pool_strdup (pool, g_strstrip (str));
+ if (strlen (s) > 0) {
+ func (data->cur_data, s, hash_fill);
}
s = str;
start = p;
- data->state = 0;
}
- else {
- p ++;
+ while (*p == '\r' || *p == '\n') {
+ p++;
}
- break;
+ }
+ else {
+ *s = *p;
+ s++;
+ p++;
+ }
+ break;
+ /* SKIP_COMMENT */
+ case 1:
+ if (*p == '\r' || *p == '\n') {
+ while (*p == '\r' || *p == '\n') {
+ p++;
+ }
+ s = str;
+ start = p;
+ data->state = 0;
+ }
+ else {
+ p++;
+ }
+ break;
}
}
static void
radix_tree_insert_helper (gpointer st, gconstpointer key, gpointer value)
{
- radix_tree_t *tree = st;
-
- uint32_t mask = 0xFFFFFFFF;
- uint32_t ip;
- char *token, *ipnet, *err_str, **strv, **cur;
- struct in_addr ina;
- int k;
-
- strv = g_strsplit_set ((char *)key, " ,;", 0);
+ radix_tree_t *tree = st;
+
+ uint32_t mask = 0xFFFFFFFF;
+ uint32_t ip;
+ char *token, *ipnet, *err_str, **strv, **cur;
+ struct in_addr ina;
+ int k;
+
+ strv = g_strsplit_set ((char *)key, " ,;", 0);
cur = strv;
- while (*cur) {
+ while (*cur) {
if (**cur == '\0') {
- cur ++;
+ cur++;
continue;
}
ipnet = *cur;
return;
}
- ip = ntohl ((uint32_t)ina.s_addr);
+ ip = ntohl ((uint32_t) ina.s_addr);
k = radix32tree_insert (tree, ip, mask, 1);
if (k == -1) {
msg_warn ("radix_tree_insert_helper: cannot insert ip to tree: %s, mask %X", inet_ntoa (ina), mask);
else if (k == 1) {
msg_warn ("add_ip_radix: ip %s, mask %X, value already exists", inet_ntoa (ina), mask);
}
- cur ++;
+ cur++;
}
g_strfreev (strv);
}
-u_char *
-read_host_list (memory_pool_t *pool, u_char *chunk, size_t len, struct map_cb_data *data)
-{
+u_char *
+read_host_list (memory_pool_t * pool, u_char * 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);
}
- return abstract_parse_list (pool, chunk, len, data, (insert_func)g_hash_table_insert);
+ return abstract_parse_list (pool, chunk, len, data, (insert_func) g_hash_table_insert);
}
-void
-fin_host_list (memory_pool_t *pool, struct map_cb_data *data)
+void
+fin_host_list (memory_pool_t * pool, struct map_cb_data *data)
{
if (data->prev_data) {
g_hash_table_destroy (data->prev_data);
}
}
-u_char *
-read_radix_list (memory_pool_t *pool, u_char *chunk, size_t len, struct map_cb_data *data)
+u_char *
+read_radix_list (memory_pool_t * pool, u_char * chunk, size_t len, struct map_cb_data *data)
{
if (data->cur_data == NULL) {
data->cur_data = radix_tree_create ();
}
- return abstract_parse_list (pool, chunk, len, data, (insert_func)radix_tree_insert_helper);
+ return abstract_parse_list (pool, chunk, len, data, (insert_func) radix_tree_insert_helper);
}
-void
-fin_radix_list (memory_pool_t *pool, struct map_cb_data *data)
+void
+fin_radix_list (memory_pool_t * pool, struct map_cb_data *data)
{
if (data->prev_data) {
radix_tree_free (data->prev_data);
static void
file_callback (int fd, short what, void *ud)
{
- struct rspamd_map *map = ud;
- struct file_map_data *data = map->map_data;
- struct stat st;
+ struct rspamd_map *map = ud;
+ struct file_map_data *data = map->map_data;
+ struct stat st;
/* Plan event again with jitter */
evtimer_del (&map->ev);
else {
return;
}
-
+
msg_info ("rereading map file %s", data->filename);
read_map_file (map, data);
}
static void
http_async_callback (int fd, short what, void *ud)
{
- struct http_callback_data *cbd = ud;
-
+ struct http_callback_data *cbd = ud;
+
/* Begin of connection */
if (what == EV_WRITE) {
if (cbd->state == 0) {
free_http_cbdata (cbd);
return;
- }
+ }
else if (cbd->state == 1) {
/* Write to log that data is modified */
msg_info ("http_async_callback: rereading map data from %s", cbd->data->host);
static void
http_callback (int fd, short what, void *ud)
{
- struct rspamd_map *map = ud;
- struct http_map_data *data = map->map_data;
- int sock;
- struct http_callback_data *cbd;
+ struct rspamd_map *map = ud;
+ struct http_map_data *data = map->map_data;
+ int sock;
+ struct http_callback_data *cbd;
/* Plan event again with jitter */
evtimer_del (&map->ev);
}
/* Start watching event for all maps */
-void
+void
start_map_watch (void)
{
- GList *cur = maps;
- struct rspamd_map *map;
-
+ GList *cur = maps;
+ struct rspamd_map *map;
+
/* First of all do synced read of data */
while (cur) {
map = cur->data;
#define MUTEX_SPIN_COUNT 100
#ifdef _THREAD_SAFE
-pthread_mutex_t stat_mtx = PTHREAD_MUTEX_INITIALIZER;
-#define STAT_LOCK() do { pthread_mutex_lock (&stat_mtx); } while (0)
-#define STAT_UNLOCK() do { pthread_mutex_unlock (&stat_mtx); } while (0)
+pthread_mutex_t stat_mtx = PTHREAD_MUTEX_INITIALIZER;
+# define STAT_LOCK() do { pthread_mutex_lock (&stat_mtx); } while (0)
+# define STAT_UNLOCK() do { pthread_mutex_unlock (&stat_mtx); } while (0)
#else
-#define STAT_LOCK() do {} while (0)
-#define STAT_UNLOCK() do {} while (0)
+# define STAT_LOCK() do {} while (0)
+# define STAT_UNLOCK() do {} while (0)
#endif
/*
#undef MEMORY_GREEDY
/* Internal statistic */
-static memory_pool_stat_t *mem_pool_stat = NULL;
+static memory_pool_stat_t *mem_pool_stat = NULL;
-static struct _pool_chain *
-pool_chain_new (memory_pool_ssize_t size)
+static struct _pool_chain *
+pool_chain_new (memory_pool_ssize_t size)
{
- struct _pool_chain *chain;
+ struct _pool_chain *chain;
g_assert (size > 0);
chain = g_slice_alloc (sizeof (struct _pool_chain));
- g_assert (chain != NULL);
+ g_assert (chain != NULL);
chain->begin = g_slice_alloc (size);
- g_assert (chain->begin != NULL);
+ g_assert (chain->begin != NULL);
chain->len = size;
chain->pos = chain->begin;
chain->next = NULL;
STAT_LOCK ();
- mem_pool_stat->chunks_allocated ++;
+ mem_pool_stat->chunks_allocated++;
STAT_UNLOCK ();
-
+
return chain;
}
static struct _pool_chain_shared *
-pool_chain_new_shared (memory_pool_ssize_t size)
+pool_chain_new_shared (memory_pool_ssize_t size)
{
- struct _pool_chain_shared *chain;
+ struct _pool_chain_shared *chain;
#if defined(HAVE_MMAP_ANON)
- chain = mmap (NULL, size + sizeof (struct _pool_chain_shared), PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED, -1, 0);
+ chain = mmap (NULL, size + sizeof (struct _pool_chain_shared), PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0);
g_assert (chain != MAP_FAILED);
- chain->begin = ((u_char *)chain) + sizeof (struct _pool_chain_shared);
+ chain->begin = ((u_char *) chain) + sizeof (struct _pool_chain_shared);
g_assert (chain->begin != MAP_FAILED);
#elif defined(HAVE_MMAP_ZERO)
- int fd;
+ int fd;
fd = open ("/dev/zero", O_RDWR);
if (fd == -1) {
return NULL;
}
- chain = mmap (NULL, size + sizeof (struct _pool_chain_shared), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+ chain = mmap (NULL, size + sizeof (struct _pool_chain_shared), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
g_assert (chain != MAP_FAILED);
- chain->begin = ((u_char *)chain) + sizeof (struct _pool_chain_shared);
+ chain->begin = ((u_char *) chain) + sizeof (struct _pool_chain_shared);
g_assert (chain->begin != MAP_FAILED);
#else
-# error No mmap methods are defined
+# error No mmap methods are defined
#endif
chain->len = size;
chain->pos = chain->begin;
chain->lock = 0;
chain->next = NULL;
STAT_LOCK ();
- mem_pool_stat->shared_chunks_allocated ++;
+ mem_pool_stat->shared_chunks_allocated++;
STAT_UNLOCK ();
-
+
return chain;
}
* @param size size of pool's page
* @return new memory pool object
*/
-memory_pool_t*
+memory_pool_t *
memory_pool_new (memory_pool_ssize_t size)
{
- memory_pool_t *new;
-
+ memory_pool_t *new;
+
g_assert (size > 0);
/* Allocate statistic structure if it is not allocated before */
if (mem_pool_stat == NULL) {
#if defined(HAVE_MMAP_ANON)
- mem_pool_stat = mmap (NULL, sizeof (memory_pool_stat_t), PROT_READ|PROT_WRITE, MAP_ANON|MAP_SHARED, -1, 0);
+ mem_pool_stat = mmap (NULL, sizeof (memory_pool_stat_t), PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0);
g_assert (stat != MAP_FAILED);
#elif defined(HAVE_MMAP_ZERO)
- int fd;
+ int fd;
fd = open ("/dev/zero", O_RDWR);
g_assert (fd != -1);
- mem_pool_stat = mmap (NULL, sizeof (memory_pool_stat_t), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+ mem_pool_stat = mmap (NULL, sizeof (memory_pool_stat_t), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
g_assert (chain != MAP_FAILED);
#else
-# error No mmap methods are defined
+# error No mmap methods are defined
#endif
}
new = g_slice_alloc (sizeof (memory_pool_t));
- g_assert (new != NULL);
+ g_assert (new != NULL);
new->cur_pool = pool_chain_new (size);
new->shared_pool = NULL;
new->first_pool = new->cur_pool;
new->destructors = NULL;
- mem_pool_stat->pools_allocated ++;
+ mem_pool_stat->pools_allocated++;
return new;
}
-void *
-memory_pool_alloc (memory_pool_t *pool, memory_pool_ssize_t size)
+void *
+memory_pool_alloc (memory_pool_t * pool, memory_pool_ssize_t size)
{
- u_char *tmp;
- struct _pool_chain *new, *cur;
+ u_char *tmp;
+ struct _pool_chain *new, *cur;
if (pool) {
#ifdef MEMORY_GREEDY
new = pool_chain_new (cur->len);
}
else {
- mem_pool_stat->oversized_chunks ++;
+ mem_pool_stat->oversized_chunks++;
new = pool_chain_new (size + cur->len);
}
/* Attach new pool to chain */
mem_pool_stat->bytes_allocated += size;
STAT_UNLOCK ();
return new->begin;
- }
+ }
tmp = cur->pos;
cur->pos += size;
STAT_LOCK ();
return NULL;
}
-void *
-memory_pool_alloc0 (memory_pool_t *pool, memory_pool_ssize_t size)
+void *
+memory_pool_alloc0 (memory_pool_t * pool, memory_pool_ssize_t size)
{
- void *pointer = memory_pool_alloc (pool, size);
+ void *pointer = memory_pool_alloc (pool, size);
if (pointer) {
bzero (pointer, size);
}
return pointer;
}
-void *
-memory_pool_alloc0_shared (memory_pool_t *pool, memory_pool_ssize_t size)
+void *
+memory_pool_alloc0_shared (memory_pool_t * pool, memory_pool_ssize_t size)
{
- void *pointer = memory_pool_alloc_shared (pool, size);
+ void *pointer = memory_pool_alloc_shared (pool, size);
if (pointer) {
bzero (pointer, size);
}
return pointer;
}
-char *
-memory_pool_strdup (memory_pool_t *pool, const char *src)
+char *
+memory_pool_strdup (memory_pool_t * pool, const char *src)
{
- memory_pool_ssize_t len;
- char *newstr;
+ memory_pool_ssize_t len;
+ char *newstr;
if (src == NULL) {
return NULL;
return newstr;
}
-char *
-memory_pool_fstrdup (memory_pool_t *pool, const struct f_str_s *src)
+char *
+memory_pool_fstrdup (memory_pool_t * pool, const struct f_str_s *src)
{
- char *newstr;
+ char *newstr;
if (src == NULL) {
return NULL;
}
-char *
-memory_pool_strdup_shared (memory_pool_t *pool, const char *src)
+char *
+memory_pool_strdup_shared (memory_pool_t * pool, const char *src)
{
- memory_pool_ssize_t len;
- char *newstr;
+ memory_pool_ssize_t len;
+ char *newstr;
if (src == NULL) {
return NULL;
}
-void *
-memory_pool_alloc_shared (memory_pool_t *pool, memory_pool_ssize_t size)
+void *
+memory_pool_alloc_shared (memory_pool_t * pool, memory_pool_ssize_t size)
{
- u_char *tmp;
- struct _pool_chain_shared *new, *cur;
+ u_char *tmp;
+ struct _pool_chain_shared *new, *cur;
if (pool) {
g_assert (size > 0);
new = pool_chain_new_shared (cur->len);
}
else {
- mem_pool_stat->oversized_chunks ++;
+ mem_pool_stat->oversized_chunks++;
new = pool_chain_new_shared (size + cur->len);
}
/* Attach new pool to chain */
/* Find pool for a pointer, returns NULL if pointer is not in pool */
static struct _pool_chain_shared *
-memory_pool_find_pool (memory_pool_t *pool, void *pointer)
+memory_pool_find_pool (memory_pool_t * pool, void *pointer)
{
- struct _pool_chain_shared *cur = pool->shared_pool;
+ struct _pool_chain_shared *cur = pool->shared_pool;
while (cur) {
- if ((u_char *)pointer >= cur->begin && (u_char *)pointer <= (cur->begin + cur->len)) {
+ if ((u_char *) pointer >= cur->begin && (u_char *) pointer <= (cur->begin + cur->len)) {
return cur;
}
cur = cur->next;
}
static inline int
-__mutex_spin (memory_pool_mutex_t *mutex)
+__mutex_spin (memory_pool_mutex_t * mutex)
{
/* check spin count */
if (g_atomic_int_dec_and_test (&mutex->spin)) {
g_atomic_int_set (&mutex->spin, MUTEX_SPIN_COUNT);
}
#ifdef HAVE_ASM_PAUSE
- __asm __volatile("pause");
+ __asm __volatile ("pause");
#elif defined(HAVE_SCHED_YIELD)
(void)sched_yield ();
#elif defined(HAVE_NANOSLEEP)
- struct timespec ts;
+ struct timespec ts;
ts.tv_sec = 0;
ts.tv_nsec = MUTEX_SLEEP_TIME;
/* Spin */
while (nanosleep (&ts, &ts) == -1 && errno == EINTR);
#else
-# error No methods to spin are defined
+# error No methods to spin are defined
#endif
return 1;
}
static void
-memory_pool_mutex_spin (memory_pool_mutex_t *mutex)
+memory_pool_mutex_spin (memory_pool_mutex_t * mutex)
{
while (!g_atomic_int_compare_and_exchange (&mutex->lock, 0, 1)) {
if (!__mutex_spin (mutex)) {
/* Simple implementation of spinlock */
void
-memory_pool_lock_shared (memory_pool_t *pool, void *pointer)
+memory_pool_lock_shared (memory_pool_t * pool, void *pointer)
{
- struct _pool_chain_shared *chain;
+ struct _pool_chain_shared *chain;
chain = memory_pool_find_pool (pool, pointer);
if (chain == NULL) {
return;
}
-
+
memory_pool_lock_mutex (chain->lock);
}
-void memory_pool_unlock_shared (memory_pool_t *pool, void *pointer)
+void
+memory_pool_unlock_shared (memory_pool_t * pool, void *pointer)
{
- struct _pool_chain_shared *chain;
+ struct _pool_chain_shared *chain;
chain = memory_pool_find_pool (pool, pointer);
if (chain == NULL) {
return;
}
-
+
memory_pool_unlock_mutex (chain->lock);
}
void
-memory_pool_add_destructor (memory_pool_t *pool, pool_destruct_func func, void *data)
+memory_pool_add_destructor (memory_pool_t * pool, pool_destruct_func func, void *data)
{
- struct _pool_destructors *cur, *tmp;
+ struct _pool_destructors *cur, *tmp;
cur = memory_pool_alloc (pool, sizeof (struct _pool_destructors));
if (cur) {
}
void
-memory_pool_delete (memory_pool_t *pool)
+memory_pool_delete (memory_pool_t * pool)
{
- struct _pool_chain *cur = pool->first_pool, *tmp;
- struct _pool_chain_shared *cur_shared = pool->shared_pool, *tmp_shared;
- struct _pool_destructors *destructor = pool->destructors;
-
+ struct _pool_chain *cur = pool->first_pool, *tmp;
+ struct _pool_chain_shared *cur_shared = pool->shared_pool, *tmp_shared;
+ struct _pool_destructors *destructor = pool->destructors;
+
/* Call all pool destructors */
while (destructor) {
/* Avoid calling destructors for NULL pointers */
- if (destructor->data != NULL) {
+ if (destructor->data != NULL) {
destructor->func (destructor->data);
}
destructor = destructor->prev;
g_slice_free1 (tmp->len, tmp->begin);
g_slice_free (struct _pool_chain, tmp);
STAT_LOCK ();
- mem_pool_stat->chunks_freed ++;
+ mem_pool_stat->chunks_freed++;
STAT_UNLOCK ();
}
/* Unmap shared memory */
cur_shared = cur_shared->next;
munmap (tmp_shared, tmp_shared->len + sizeof (struct _pool_chain_shared));
STAT_LOCK ();
- mem_pool_stat->chunks_freed ++;
+ mem_pool_stat->chunks_freed++;
STAT_UNLOCK ();
}
- mem_pool_stat->pools_freed ++;
+ mem_pool_stat->pools_freed++;
g_slice_free (memory_pool_t, pool);
}
void
-memory_pool_stat (memory_pool_stat_t *st)
+memory_pool_stat (memory_pool_stat_t * st)
{
st->pools_allocated = mem_pool_stat->pools_allocated;
st->pools_freed = mem_pool_stat->pools_freed;
memory_pool_get_size ()
{
#ifdef HAVE_GETPAGESIZE
- return MAX (getpagesize (), FIXED_POOL_SIZE);
+ return MAX (getpagesize (), FIXED_POOL_SIZE);
#else
return MAX (sysconf (_SC_PAGESIZE), FIXED_POOL_SIZE);
#endif
}
-memory_pool_mutex_t*
-memory_pool_get_mutex (memory_pool_t *pool)
+memory_pool_mutex_t *
+memory_pool_get_mutex (memory_pool_t * pool)
{
- memory_pool_mutex_t *res;
+ memory_pool_mutex_t *res;
if (pool != NULL) {
res = memory_pool_alloc_shared (pool, sizeof (memory_pool_mutex_t));
res->lock = 0;
return NULL;
}
-void
-memory_pool_lock_mutex (memory_pool_mutex_t *mutex)
+void
+memory_pool_lock_mutex (memory_pool_mutex_t * mutex)
{
memory_pool_mutex_spin (mutex);
mutex->owner = getpid ();
}
-void
-memory_pool_unlock_mutex (memory_pool_mutex_t *mutex)
+void
+memory_pool_unlock_mutex (memory_pool_mutex_t * mutex)
{
mutex->owner = 0;
(void)g_atomic_int_compare_and_exchange (&mutex->lock, 1, 0);
}
-memory_pool_rwlock_t*
-memory_pool_get_rwlock (memory_pool_t *pool)
+memory_pool_rwlock_t *
+memory_pool_get_rwlock (memory_pool_t * pool)
{
- memory_pool_rwlock_t *lock;
+ memory_pool_rwlock_t *lock;
lock = memory_pool_alloc_shared (pool, sizeof (memory_pool_rwlock_t));
lock->__r_lock = memory_pool_get_mutex (pool);
return lock;
}
-void
-memory_pool_rlock_rwlock (memory_pool_rwlock_t *lock)
+void
+memory_pool_rlock_rwlock (memory_pool_rwlock_t * lock)
{
/* Spin on write lock */
while (g_atomic_int_get (&lock->__w_lock->lock)) {
break;
}
}
-
+
g_atomic_int_inc (&lock->__r_lock->lock);
lock->__r_lock->owner = getpid ();
}
-void
-memory_pool_wlock_rwlock (memory_pool_rwlock_t *lock)
+void
+memory_pool_wlock_rwlock (memory_pool_rwlock_t * lock)
{
/* Spin on write lock first */
memory_pool_lock_mutex (lock->__w_lock);
}
}
-void
-memory_pool_runlock_rwlock (memory_pool_rwlock_t *lock)
+void
+memory_pool_runlock_rwlock (memory_pool_rwlock_t * lock)
{
if (g_atomic_int_get (&lock->__r_lock->lock)) {
(void)g_atomic_int_dec_and_test (&lock->__r_lock->lock);
}
}
-void
-memory_pool_wunlock_rwlock (memory_pool_rwlock_t *lock)
+void
+memory_pool_wunlock_rwlock (memory_pool_rwlock_t * lock)
{
memory_pool_unlock_mutex (lock->__w_lock);
}
#define HOST "127.0.0.1"
#define PORT 11211
-memcached_param_t cur_param;
+memcached_param_t cur_param;
static void
-test_memc_callback (memcached_ctx_t *ctx, memc_error_t error, void *data)
-{
- int s;
- int r;
- int *num = ((int *)data);
+test_memc_callback (memcached_ctx_t * ctx, memc_error_t error, void *data)
+{
+ int s;
+ int r;
+ int *num = ((int *)data);
printf ("result of memc command '%s' is '%s'\n", ctx->cmd, memc_strerror (error));
/* Connect */
if (*num == 0) {
}
-int
+int
main (int argc, char **argv)
{
- memcached_ctx_t mctx;
- char *addr, buf[512];
- int num = 0;
-
+ memcached_ctx_t mctx;
+ char *addr, buf[512];
+ int num = 0;
+
event_init ();
strcpy (cur_param.key, "testkey");
strcpy (buf, "test_value");
else {
addr = HOST;
}
-
+
mctx.protocol = TCP_TEXT;
mctx.timeout.tv_sec = 1;
mctx.timeout.tv_usec = 0;
inet_aton (addr, &mctx.addr);
memc_init_ctx (&mctx);
-
+
event_loop (0);
return 0;
}
*/
#ifdef _THREAD_SAFE
-#include <pthread.h>
+# include <pthread.h>
#endif
#include <stdarg.h>
#define MAX_RETRIES 3
/* Header for udp protocol */
-struct memc_udp_header
-{
- uint16_t req_id;
- uint16_t seq_num;
- uint16_t dg_sent;
- uint16_t unused;
+struct memc_udp_header {
+ uint16_t req_id;
+ uint16_t seq_num;
+ uint16_t dg_sent;
+ uint16_t unused;
};
-static void socket_callback (int fd, short what, void *arg);
-static int memc_parse_header (char *buf, size_t *len, char **end);
+static void socket_callback (int fd, short what, void *arg);
+static int memc_parse_header (char *buf, size_t * len, char **end);
/*
* Write to syslog if OPT_DEBUG is specified
*/
static void
-memc_log (const memcached_ctx_t *ctx, int line, const char *fmt, ...)
+memc_log (const memcached_ctx_t * ctx, int line, const char *fmt, ...)
{
- va_list args;
+ va_list args;
if (ctx->options & MEMC_OPT_DEBUG) {
va_start (args, fmt);
g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "memc_debug(%d): host: %s, port: %d", line, inet_ntoa (ctx->addr), ntohs (ctx->port));
* Callback for write command
*/
static void
-write_handler (int fd, short what, memcached_ctx_t *ctx)
+write_handler (int fd, short what, memcached_ctx_t * ctx)
{
- char read_buf[READ_BUFSIZ];
- int retries;
- ssize_t r;
- struct memc_udp_header header;
- struct iovec iov[4];
+ char read_buf[READ_BUFSIZ];
+ int retries;
+ ssize_t r;
+ struct memc_udp_header header;
+ struct iovec iov[4];
/* Write something to memcached */
if (what == EV_WRITE) {
ctx->callback (ctx, SERVER_ERROR, ctx->callback_data);
}
if (header.req_id != ctx->count && retries < MAX_RETRIES) {
- retries ++;
+ retries++;
/* Not our reply packet */
continue;
}
* Callback for read command
*/
static void
-read_handler (int fd, short what, memcached_ctx_t *ctx)
+read_handler (int fd, short what, memcached_ctx_t * ctx)
{
- char read_buf[READ_BUFSIZ];
- char *p;
- ssize_t r;
- size_t datalen;
- struct memc_udp_header header;
- struct iovec iov[2];
- int retries = 0, t;
-
+ char read_buf[READ_BUFSIZ];
+ char *p;
+ ssize_t r;
+ size_t datalen;
+ struct memc_udp_header header;
+ struct iovec iov[2];
+ int retries = 0, t;
+
if (what == EV_WRITE) {
/* Send command to memcached */
if (ctx->protocol == UDP_TEXT) {
else {
p = read_buf;
}
-
- if (strncmp (ctx->param->buf + ctx->param->bufpos + r - sizeof (END_TRAILER) - sizeof (CRLF) + 2,
- END_TRAILER, sizeof (END_TRAILER) - 1) == 0) {
+
+ if (strncmp (ctx->param->buf + ctx->param->bufpos + r - sizeof (END_TRAILER) - sizeof (CRLF) + 2, END_TRAILER, sizeof (END_TRAILER) - 1) == 0) {
r -= sizeof (END_TRAILER) - sizeof (CRLF) - 2;
memcpy (ctx->param->buf + ctx->param->bufpos, p, r);
event_del (&ctx->mem_ev);
event_del (&ctx->mem_ev);
ctx->callback (ctx, SERVER_TIMEOUT, ctx->callback_data);
}
-
+
}
/*
* Callback for delete command
*/
static void
-delete_handler (int fd, short what, memcached_ctx_t *ctx)
+delete_handler (int fd, short what, memcached_ctx_t * ctx)
{
- char read_buf[READ_BUFSIZ];
- int retries;
- ssize_t r;
- struct memc_udp_header header;
- struct iovec iov[2];
+ char read_buf[READ_BUFSIZ];
+ int retries;
+ ssize_t r;
+ struct memc_udp_header header;
+ struct iovec iov[2];
/* Write something to memcached */
if (what == EV_WRITE) {
return;
}
if (header.req_id != ctx->count && retries < MAX_RETRIES) {
- retries ++;
+ retries++;
/* Not our reply packet */
continue;
}
static void
socket_callback (int fd, short what, void *arg)
{
- memcached_ctx_t *ctx = (memcached_ctx_t *)arg;
+ memcached_ctx_t *ctx = (memcached_ctx_t *) arg;
switch (ctx->op) {
- case CMD_NULL:
- /* Do nothing here */
- break;
- case CMD_CONNECT:
- /* We have write readiness after connect call, so reinit event */
- ctx->cmd = "connect";
- if (what == EV_WRITE) {
- event_del (&ctx->mem_ev);
- event_set (&ctx->mem_ev, ctx->sock, EV_READ | EV_PERSIST | EV_TIMEOUT, socket_callback, (void *)ctx);
- event_add (&ctx->mem_ev, NULL);
- ctx->callback (ctx, OK, ctx->callback_data);
- ctx->alive = 1;
- }
- else {
- ctx->callback (ctx, SERVER_TIMEOUT, ctx->callback_data);
- ctx->alive = 0;
- }
- break;
- case CMD_WRITE:
- write_handler (fd, what, ctx);
- break;
- case CMD_READ:
- read_handler (fd, what, ctx);
- break;
- case CMD_DELETE:
- delete_handler (fd, what, ctx);
- break;
+ case CMD_NULL:
+ /* Do nothing here */
+ break;
+ case CMD_CONNECT:
+ /* We have write readiness after connect call, so reinit event */
+ ctx->cmd = "connect";
+ if (what == EV_WRITE) {
+ event_del (&ctx->mem_ev);
+ event_set (&ctx->mem_ev, ctx->sock, EV_READ | EV_PERSIST | EV_TIMEOUT, socket_callback, (void *)ctx);
+ event_add (&ctx->mem_ev, NULL);
+ ctx->callback (ctx, OK, ctx->callback_data);
+ ctx->alive = 1;
+ }
+ else {
+ ctx->callback (ctx, SERVER_TIMEOUT, ctx->callback_data);
+ ctx->alive = 0;
+ }
+ break;
+ case CMD_WRITE:
+ write_handler (fd, what, ctx);
+ break;
+ case CMD_READ:
+ read_handler (fd, what, ctx);
+ break;
+ case CMD_DELETE:
+ delete_handler (fd, what, ctx);
+ break;
}
}
* Common callback function for memcached operations if no user's callback is specified
*/
static void
-common_memc_callback (memcached_ctx_t *ctx, memc_error_t error, void *data)
+common_memc_callback (memcached_ctx_t * ctx, memc_error_t error, void *data)
{
memc_log (ctx, __LINE__, "common_memc_callback: result of memc command '%s' is '%s'", ctx->cmd, memc_strerror (error));
}
* Make socket for udp connection
*/
static int
-memc_make_udp_sock (memcached_ctx_t *ctx)
+memc_make_udp_sock (memcached_ctx_t * ctx)
{
- struct sockaddr_in sc;
- int ofl;
+ struct sockaddr_in sc;
+ int ofl;
bzero (&sc, sizeof (struct sockaddr_in *));
sc.sin_family = AF_INET;
}
/* set nonblocking */
- ofl = fcntl(ctx->sock, F_GETFL, 0);
- fcntl(ctx->sock, F_SETFL, ofl | O_NONBLOCK);
+ ofl = fcntl (ctx->sock, F_GETFL, 0);
+ fcntl (ctx->sock, F_SETFL, ofl | O_NONBLOCK);
/*
* Call connect to set default destination for datagrams
ctx->op = CMD_CONNECT;
event_set (&ctx->mem_ev, ctx->sock, EV_WRITE | EV_TIMEOUT, socket_callback, (void *)ctx);
event_add (&ctx->mem_ev, NULL);
- return connect (ctx->sock, (struct sockaddr*)&sc, sizeof (struct sockaddr_in));
+ return connect (ctx->sock, (struct sockaddr *)&sc, sizeof (struct sockaddr_in));
}
/*
* Make socket for tcp connection
*/
static int
-memc_make_tcp_sock (memcached_ctx_t *ctx)
+memc_make_tcp_sock (memcached_ctx_t * ctx)
{
- struct sockaddr_in sc;
- int ofl, r;
+ struct sockaddr_in sc;
+ int ofl, r;
bzero (&sc, sizeof (struct sockaddr_in *));
sc.sin_family = AF_INET;
}
/* set nonblocking */
- ofl = fcntl(ctx->sock, F_GETFL, 0);
- fcntl(ctx->sock, F_SETFL, ofl | O_NONBLOCK);
-
- if ((r = connect (ctx->sock, (struct sockaddr*)&sc, sizeof (struct sockaddr_in))) == -1) {
+ ofl = fcntl (ctx->sock, F_GETFL, 0);
+ fcntl (ctx->sock, F_SETFL, ofl | O_NONBLOCK);
+
+ if ((r = connect (ctx->sock, (struct sockaddr *)&sc, sizeof (struct sockaddr_in))) == -1) {
if (errno != EINPROGRESS) {
close (ctx->sock);
ctx->sock = -1;
* Parse VALUE reply from server and set len argument to value returned by memcached
*/
static int
-memc_parse_header (char *buf, size_t *len, char **end)
+memc_parse_header (char *buf, size_t * len, char **end)
{
- char *p, *c;
- int i;
+ char *p, *c;
+ int i;
/* VALUE <key> <flags> <bytes> [<cas unique>]\r\n */
c = strstr (buf, CRLF);
return -1;
}
*end = c + sizeof (CRLF) - 1;
-
+
if (strncmp (buf, "VALUE ", sizeof ("VALUE ") - 1) == 0) {
p = buf + sizeof ("VALUE ") - 1;
-
+
/* Read bytes value and ignore all other fields, such as flags and key */
for (i = 0; i < 2; i++) {
while (p++ < c && *p != ' ');
* Common read command handler for memcached
*/
memc_error_t
-memc_read (memcached_ctx_t *ctx, const char *cmd, memcached_param_t *param)
+memc_read (memcached_ctx_t * ctx, const char *cmd, memcached_param_t * param)
{
ctx->cmd = cmd;
ctx->op = CMD_READ;
* Common write command handler for memcached
*/
memc_error_t
-memc_write (memcached_ctx_t *ctx, const char *cmd, memcached_param_t *param, int expire)
+memc_write (memcached_ctx_t * ctx, const char *cmd, memcached_param_t * param, int expire)
{
ctx->cmd = cmd;
ctx->op = CMD_WRITE;
return OK;
}
+
/*
* Delete command handler
*/
memc_error_t
-memc_delete (memcached_ctx_t *ctx, memcached_param_t *param)
+memc_delete (memcached_ctx_t * ctx, memcached_param_t * param)
{
ctx->cmd = "delete";
ctx->op = CMD_DELETE;
* writing is done to each memcached server
*/
memc_error_t
-memc_write_mirror (memcached_ctx_t *ctx, size_t memcached_num, const char *cmd, memcached_param_t *param, int expire)
+memc_write_mirror (memcached_ctx_t * ctx, size_t memcached_num, const char *cmd, memcached_param_t * param, int expire)
{
- memc_error_t r, result = OK;
+ memc_error_t r, result = OK;
- while (memcached_num --) {
+ while (memcached_num--) {
if (ctx[memcached_num].alive == 1) {
r = memc_write (&ctx[memcached_num], cmd, param, expire);
if (r != OK) {
* reading is done from first active memcached server
*/
memc_error_t
-memc_read_mirror (memcached_ctx_t *ctx, size_t memcached_num, const char *cmd, memcached_param_t *param)
+memc_read_mirror (memcached_ctx_t * ctx, size_t memcached_num, const char *cmd, memcached_param_t * param)
{
- memc_error_t r, result = OK;
+ memc_error_t r, result = OK;
- while (memcached_num --) {
+ while (memcached_num--) {
if (ctx[memcached_num].alive == 1) {
r = memc_read (&ctx[memcached_num], cmd, param);
if (r != OK) {
* deleting is done for each active memcached server
*/
memc_error_t
-memc_delete_mirror (memcached_ctx_t *ctx, size_t memcached_num, const char *cmd, memcached_param_t *param)
+memc_delete_mirror (memcached_ctx_t * ctx, size_t memcached_num, const char *cmd, memcached_param_t * param)
{
- memc_error_t r, result = OK;
+ memc_error_t r, result = OK;
- while (memcached_num --) {
+ while (memcached_num--) {
if (ctx[memcached_num].alive == 1) {
r = memc_delete (&ctx[memcached_num], param);
if (r != OK) {
/*
* Initialize memcached context for specified protocol
*/
-int
-memc_init_ctx (memcached_ctx_t *ctx)
+int
+memc_init_ctx (memcached_ctx_t * ctx)
{
if (ctx == NULL) {
return -1;
}
switch (ctx->protocol) {
- case UDP_TEXT:
- return memc_make_udp_sock (ctx);
- break;
- case TCP_TEXT:
- return memc_make_tcp_sock (ctx);
- break;
+ case UDP_TEXT:
+ return memc_make_udp_sock (ctx);
+ break;
+ case TCP_TEXT:
+ return memc_make_tcp_sock (ctx);
+ break;
/* Not implemented */
- case UDP_BIN:
- case TCP_BIN:
- default:
- return -1;
+ case UDP_BIN:
+ case TCP_BIN:
+ default:
+ return -1;
}
}
+
/*
* Mirror init
*/
-int
-memc_init_ctx_mirror (memcached_ctx_t *ctx, size_t memcached_num)
+int
+memc_init_ctx_mirror (memcached_ctx_t * ctx, size_t memcached_num)
{
- int r, result = -1;
+ int r, result = -1;
while (memcached_num--) {
if (ctx[memcached_num].alive == 1) {
r = memc_init_ctx (&ctx[memcached_num]);
* Close context connection
*/
int
-memc_close_ctx (memcached_ctx_t *ctx)
+memc_close_ctx (memcached_ctx_t * ctx)
{
if (ctx != NULL && ctx->sock != -1) {
event_del (&ctx->mem_ev);
return -1;
}
+
/*
* Mirror close
*/
-int
-memc_close_ctx_mirror (memcached_ctx_t *ctx, size_t memcached_num)
+int
+memc_close_ctx_mirror (memcached_ctx_t * ctx, size_t memcached_num)
{
- int r = 0;
+ int r = 0;
while (memcached_num--) {
if (ctx[memcached_num].alive == 1) {
r = memc_close_ctx (&ctx[memcached_num]);
}
-const char * memc_strerror (memc_error_t err)
+const char *
+memc_strerror (memc_error_t err)
{
- const char *p;
+ const char *p;
switch (err) {
- case OK:
- p = "Ok";
- break;
- case BAD_COMMAND:
- p = "Bad command";
- break;
- case CLIENT_ERROR:
- p = "Client error";
- break;
- case SERVER_ERROR:
- p = "Server error";
- break;
- case SERVER_TIMEOUT:
- p = "Server timeout";
- break;
- case NOT_EXISTS:
- p = "Key not found";
- break;
- case EXISTS:
- p = "Key already exists";
- break;
- case WRONG_LENGTH:
- p = "Wrong result length";
- break;
- default:
- p = "Unknown error";
- break;
+ case OK:
+ p = "Ok";
+ break;
+ case BAD_COMMAND:
+ p = "Bad command";
+ break;
+ case CLIENT_ERROR:
+ p = "Client error";
+ break;
+ case SERVER_ERROR:
+ p = "Server error";
+ break;
+ case SERVER_TIMEOUT:
+ p = "Server timeout";
+ break;
+ case NOT_EXISTS:
+ p = "Key not found";
+ break;
+ case EXISTS:
+ p = "Key already exists";
+ break;
+ case WRONG_LENGTH:
+ p = "Wrong result length";
+ break;
+ default:
+ p = "Unknown error";
+ break;
}
return p;
#define RECURSION_LIMIT 30
-GByteArray*
-strip_html_tags (struct worker_task *task, memory_pool_t *pool, struct mime_text_part *part, GByteArray *src, int *stateptr)
+GByteArray *
+strip_html_tags (struct worker_task *task, memory_pool_t * pool, struct mime_text_part *part, GByteArray * src, int *stateptr)
{
- uint8_t *tbuf = NULL, *p, *tp = NULL, *rp, *tbegin = NULL, c, lc;
- int br, i = 0, depth = 0, in_q = 0;
- int state = 0;
- GByteArray *buf;
- GNode *level_ptr = NULL;
+ uint8_t *tbuf = NULL, *p, *tp = NULL, *rp, *tbegin = NULL, c, lc;
+ int br, i = 0, depth = 0, in_q = 0;
+ int state = 0;
+ GByteArray *buf;
+ GNode *level_ptr = NULL;
if (stateptr)
state = *stateptr;
-
+
buf = g_byte_array_sized_new (src->len);
g_byte_array_append (buf, src->data, src->len);
while (i < src->len) {
switch (c) {
- case '\0':
- break;
- case '<':
- if (g_ascii_isspace(*(p + 1))) {
- goto reg_char;
- }
- if (state == 0) {
- lc = '<';
- tbegin = p + 1;
- state = 1;
- } else if (state == 1) {
- depth++;
- }
- break;
+ case '\0':
+ break;
+ case '<':
+ if (g_ascii_isspace (*(p + 1))) {
+ goto reg_char;
+ }
+ if (state == 0) {
+ lc = '<';
+ tbegin = p + 1;
+ state = 1;
+ }
+ else if (state == 1) {
+ depth++;
+ }
+ break;
- case '(':
- if (state == 2) {
- if (lc != '"' && lc != '\'') {
- lc = '(';
- br++;
- }
- } else if (state == 0) {
- *(rp++) = c;
+ case '(':
+ if (state == 2) {
+ if (lc != '"' && lc != '\'') {
+ lc = '(';
+ br++;
}
- break;
+ }
+ else if (state == 0) {
+ *(rp++) = c;
+ }
+ break;
- case ')':
- if (state == 2) {
- if (lc != '"' && lc != '\'') {
- lc = ')';
- br--;
- }
- } else if (state == 0) {
- *(rp++) = c;
+ case ')':
+ if (state == 2) {
+ if (lc != '"' && lc != '\'') {
+ lc = ')';
+ br--;
}
- break;
+ }
+ else if (state == 0) {
+ *(rp++) = c;
+ }
+ break;
- case '>':
- if (depth) {
- depth--;
- break;
- }
+ case '>':
+ if (depth) {
+ depth--;
+ break;
+ }
- if (in_q) {
- break;
- }
+ if (in_q) {
+ break;
+ }
- switch (state) {
- case 1: /* HTML/XML */
- lc = '>';
- in_q = state = 0;
- *p = '\0';
- add_html_node (task, pool, part, tbegin, &level_ptr);
- *p = '>';
- break;
-
- case 2: /* PHP */
- if (!br && lc != '\"' && *(p-1) == '?') {
- in_q = state = 0;
- tp = tbuf;
- }
- break;
-
- case 3:
- in_q = state = 0;
- tp = tbuf;
- break;
-
- case 4: /* JavaScript/CSS/etc... */
- if (p >= src->data + 2 && *(p-1) == '-' && *(p-2) == '-') {
- in_q = state = 0;
- tp = tbuf;
- }
- break;
-
- default:
- *(rp++) = c;
- break;
- }
+ switch (state) {
+ case 1: /* HTML/XML */
+ lc = '>';
+ in_q = state = 0;
+ *p = '\0';
+ add_html_node (task, pool, part, tbegin, &level_ptr);
+ *p = '>';
break;
- case '"':
- case '\'':
- if (state == 2 && *(p-1) != '\\') {
- if (lc == c) {
- lc = '\0';
- } else if (lc != '\\') {
- lc = c;
- }
- } else if (state == 0) {
- *(rp++) = c;
- }
- if (state && p != src->data && *(p-1) != '\\' && (!in_q || *p == in_q)) {
- if (in_q) {
- in_q = 0;
- } else {
- in_q = *p;
- }
+ case 2: /* PHP */
+ if (!br && lc != '\"' && *(p - 1) == '?') {
+ in_q = state = 0;
+ tp = tbuf;
}
break;
-
- case '!':
- /* JavaScript & Other HTML scripting languages */
- if (state == 1 && *(p-1) == '<') {
- state = 3;
- lc = c;
- } else {
- if (state == 0) {
- *(rp++) = c;
- }
- }
+
+ case 3:
+ in_q = state = 0;
+ tp = tbuf;
break;
- case '-':
- if (state == 3 && p >= src->data + 2 && *(p-1) == '-' && *(p-2) == '!') {
- state = 4;
- } else {
- goto reg_char;
+ case 4: /* JavaScript/CSS/etc... */
+ if (p >= src->data + 2 && *(p - 1) == '-' && *(p - 2) == '-') {
+ in_q = state = 0;
+ tp = tbuf;
}
break;
- case '?':
+ default:
+ *(rp++) = c;
+ break;
+ }
+ break;
- if (state == 1 && *(p-1) == '<') {
- br = 0;
- state = 2;
- break;
+ case '"':
+ case '\'':
+ if (state == 2 && *(p - 1) != '\\') {
+ if (lc == c) {
+ lc = '\0';
}
+ else if (lc != '\\') {
+ lc = c;
+ }
+ }
+ else if (state == 0) {
+ *(rp++) = c;
+ }
+ if (state && p != src->data && *(p - 1) != '\\' && (!in_q || *p == in_q)) {
+ if (in_q) {
+ in_q = 0;
+ }
+ else {
+ in_q = *p;
+ }
+ }
+ break;
- case 'E':
- case 'e':
- /* !DOCTYPE exception */
- if (state == 3 && p > src->data + 6
- && g_ascii_tolower(*(p-1)) == 'p'
- && g_ascii_tolower(*(p-2)) == 'y'
- && g_ascii_tolower(*(p-3)) == 't'
- && g_ascii_tolower(*(p-4)) == 'c'
- && g_ascii_tolower(*(p-5)) == 'o'
- && g_ascii_tolower(*(p-6)) == 'd') {
- state = 1;
- break;
+ case '!':
+ /* JavaScript & Other HTML scripting languages */
+ if (state == 1 && *(p - 1) == '<') {
+ state = 3;
+ lc = c;
+ }
+ else {
+ if (state == 0) {
+ *(rp++) = c;
}
- /* fall-through */
+ }
+ break;
- case 'l':
+ case '-':
+ if (state == 3 && p >= src->data + 2 && *(p - 1) == '-' && *(p - 2) == '!') {
+ state = 4;
+ }
+ else {
+ goto reg_char;
+ }
+ break;
- /* swm: If we encounter '<?xml' then we shouldn't be in
- * state == 2 (PHP). Switch back to HTML.
- */
+ case '?':
- if (state == 2 && p > src->data + 2 && *(p-1) == 'm' && *(p-2) == 'x') {
- state = 1;
- break;
- }
+ if (state == 1 && *(p - 1) == '<') {
+ br = 0;
+ state = 2;
+ break;
+ }
- /* fall-through */
- default:
-reg_char:
- if (state == 0) {
- *(rp++) = c;
- }
+ case 'E':
+ case 'e':
+ /* !DOCTYPE exception */
+ if (state == 3 && p > src->data + 6
+ && g_ascii_tolower (*(p - 1)) == 'p'
+ && g_ascii_tolower (*(p - 2)) == 'y'
+ && g_ascii_tolower (*(p - 3)) == 't' && g_ascii_tolower (*(p - 4)) == 'c' && g_ascii_tolower (*(p - 5)) == 'o' && g_ascii_tolower (*(p - 6)) == 'd') {
+ state = 1;
+ break;
+ }
+ /* fall-through */
+
+ case 'l':
+
+ /* swm: If we encounter '<?xml' then we shouldn't be in
+ * state == 2 (PHP). Switch back to HTML.
+ */
+
+ if (state == 2 && p > src->data + 2 && *(p - 1) == 'm' && *(p - 2) == 'x') {
+ state = 1;
break;
+ }
+
+ /* fall-through */
+ default:
+ reg_char:
+ if (state == 0) {
+ *(rp++) = c;
+ }
+ break;
}
i++;
if (i < src->len) {
c = *(++p);
}
- }
+ }
if (rp < buf->data + src->len) {
*rp = '\0';
g_byte_array_set_size (buf, rp - buf->data);
}
-
+
/* Check tag balancing */
if (level_ptr && level_ptr->data != NULL) {
- part->is_balanced = FALSE;
+ part->is_balanced = FALSE;
}
if (stateptr) {
}
static void
-parse_qmail_recv (memory_pool_t *pool, char *line, struct received_header *r)
+parse_qmail_recv (memory_pool_t * pool, char *line, struct received_header *r)
{
- char *s, *p, t;
-
+ char *s, *p, t;
+
/* We are intersted only with received from network headers */
if ((p = strstr (line, "from network")) == NULL) {
r->is_error = 2;
return;
}
-
+
p += sizeof ("from network") - 1;
while (g_ascii_isspace (*p) || *p == '[') {
- p ++;
+ p++;
}
/* format is ip/host */
s = p;
/* Now try to parse hostname */
s = ++p;
while (g_ascii_isalnum (*p) || *p == '.' || *p == '-' || *p == '_') {
- p ++;
+ p++;
}
t = *p;
*p = '\0';
}
static void
-parse_recv_header (memory_pool_t *pool, char *line, struct received_header *r)
+parse_recv_header (memory_pool_t * pool, char *line, struct received_header *r)
{
- char *p, *s, t, **res = NULL;
- int state = 0, next_state = 0;
-
+ char *p, *s, t, **res = NULL;
+ int state = 0, next_state = 0;
+
g_strstrip (line);
p = line;
s = line;
while (*p) {
switch (state) {
/* Initial state, search for from */
- case 0:
- if (*p == 'f' || *p == 'F') {
- if (g_ascii_tolower (*++p) == 'r' &&
- g_ascii_tolower (*++p) == 'o' &&
- g_ascii_tolower (*++p) == 'm') {
- p ++;
- state = 99;
- next_state = 1;
- }
- }
- else {
- /* This can be qmail header, parse it separately */
- parse_qmail_recv (pool, line, r);
- return;
- }
- break;
- /* Read hostname */
- case 1:
- if (*p == '[') {
- /* This should be IP address */
- res = &r->from_ip;
- state = 98;
- next_state = 3;
- s = ++p;
- }
- else if (g_ascii_isalnum (*p) || *p == '.' || *p == '-' || *p == '_') {
- p ++;
- }
- else {
- t = *p;
- *p = '\0';
- r->from_hostname = memory_pool_strdup (pool, s);
- *p = t;
+ case 0:
+ if (*p == 'f' || *p == 'F') {
+ if (g_ascii_tolower (*++p) == 'r' && g_ascii_tolower (*++p) == 'o' && g_ascii_tolower (*++p) == 'm') {
+ p++;
state = 99;
- next_state = 3;
+ next_state = 1;
}
- break;
+ }
+ else {
+ /* This can be qmail header, parse it separately */
+ parse_qmail_recv (pool, line, r);
+ return;
+ }
+ break;
+ /* Read hostname */
+ case 1:
+ if (*p == '[') {
+ /* This should be IP address */
+ res = &r->from_ip;
+ state = 98;
+ next_state = 3;
+ s = ++p;
+ }
+ else if (g_ascii_isalnum (*p) || *p == '.' || *p == '-' || *p == '_') {
+ p++;
+ }
+ else {
+ t = *p;
+ *p = '\0';
+ r->from_hostname = memory_pool_strdup (pool, s);
+ *p = t;
+ state = 99;
+ next_state = 3;
+ }
+ break;
/* Try to extract additional info */
- case 3:
- /* Try to extract ip or () info or by */
- if (g_ascii_tolower (*p) == 'b' && g_ascii_tolower (*(p + 1)) == 'y') {
- p += 2;
- /* Skip spaces after by */
- state = 99;
- next_state = 5;
- }
- else if (*p == '(') {
- state = 99;
- next_state = 4;
- p ++;
- }
- else if (*p == '[') {
- /* Got ip before '(' so extract it */
- s = ++p;
- res = &r->from_ip;
- state = 98;
- next_state = 3;
- }
- else {
- p ++;
- }
- break;
+ case 3:
+ /* Try to extract ip or () info or by */
+ if (g_ascii_tolower (*p) == 'b' && g_ascii_tolower (*(p + 1)) == 'y') {
+ p += 2;
+ /* Skip spaces after by */
+ state = 99;
+ next_state = 5;
+ }
+ else if (*p == '(') {
+ state = 99;
+ next_state = 4;
+ p++;
+ }
+ else if (*p == '[') {
+ /* Got ip before '(' so extract it */
+ s = ++p;
+ res = &r->from_ip;
+ state = 98;
+ next_state = 3;
+ }
+ else {
+ p++;
+ }
+ break;
/* We are in () block. Here can be found real hostname and real ip, this is written by some MTA */
- case 4:
- /* End of block */
- if (*p == ')') {
- p ++;
- state = 3;
- }
- else if (g_ascii_isalnum (*p) || *p == '.' || *p == '-' || *p == '_') {
- p ++;
- }
- else if (*p == '[') {
- s = ++p;
- state = 98;
- res = &r->real_ip;
- next_state = 3;
- }
- else {
- if (s != p) {
- /* Got some real hostname */
- /* check whether it is helo or p is not space symbol*/
- if (!g_ascii_isspace (*p) || *(p + 1) != '[') {
- /* skip all */
- while (*p++ != ')' && *p != '\0');
- state = 3;
- }
- else {
- t = *p;
- *p = '\0';
- r->real_hostname = memory_pool_strdup (pool, s);
- *p = t;
- /* Now parse ip */
- p += 2;
- s = p;
- res = &r->real_ip;
- state = 98;
- next_state = 4;
- }
+ case 4:
+ /* End of block */
+ if (*p == ')') {
+ p++;
+ state = 3;
+ }
+ else if (g_ascii_isalnum (*p) || *p == '.' || *p == '-' || *p == '_') {
+ p++;
+ }
+ else if (*p == '[') {
+ s = ++p;
+ state = 98;
+ res = &r->real_ip;
+ next_state = 3;
+ }
+ else {
+ if (s != p) {
+ /* Got some real hostname */
+ /* check whether it is helo or p is not space symbol */
+ if (!g_ascii_isspace (*p) || *(p + 1) != '[') {
+ /* skip all */
+ while (*p++ != ')' && *p != '\0');
+ state = 3;
}
else {
- r->is_error = 1;
- return;
+ t = *p;
+ *p = '\0';
+ r->real_hostname = memory_pool_strdup (pool, s);
+ *p = t;
+ /* Now parse ip */
+ p += 2;
+ s = p;
+ res = &r->real_ip;
+ state = 98;
+ next_state = 4;
}
}
- break;
- /* Got by word */
- case 5:
- /* Here can be only hostname */
- if (g_ascii_isalnum (*p) || *p == '.' || *p == '-' || *p == '_') {
- p ++;
- }
else {
- /* We got something like hostname */
- t = *p;
- *p = '\0';
- r->by_hostname = memory_pool_strdup (pool, s);
- *p = t;
- /* Now end of parsing */
+ r->is_error = 1;
return;
}
- break;
+ }
+ break;
+ /* Got by word */
+ case 5:
+ /* Here can be only hostname */
+ if (g_ascii_isalnum (*p) || *p == '.' || *p == '-' || *p == '_') {
+ p++;
+ }
+ else {
+ /* We got something like hostname */
+ t = *p;
+ *p = '\0';
+ r->by_hostname = memory_pool_strdup (pool, s);
+ *p = t;
+ /* Now end of parsing */
+ return;
+ }
+ break;
/* Extract ip */
- case 98:
- while (g_ascii_isdigit (*++p) || *p == '.');
- if (*p != ']') {
- /* Not an ip in fact */
- state = next_state;
- p ++;
- }
- else {
- *p = '\0';
- *res = memory_pool_strdup (pool, s);
- *p = ']';
- p ++;
- state = next_state;
- }
- break;
+ case 98:
+ while (g_ascii_isdigit (*++p) || *p == '.');
+ if (*p != ']') {
+ /* Not an ip in fact */
+ state = next_state;
+ p++;
+ }
+ else {
+ *p = '\0';
+ *res = memory_pool_strdup (pool, s);
+ *p = ']';
+ p++;
+ state = next_state;
+ }
+ break;
/* Skip spaces */
- case 99:
- if (!g_ascii_isspace (*p)) {
- state = next_state;
- s = p;
- }
- else {
- p ++;
- }
- break;
- case 100:
- r->is_error = 1;
- return;
- break;
+ case 99:
+ if (!g_ascii_isspace (*p)) {
+ state = next_state;
+ s = p;
+ }
+ else {
+ p++;
+ }
+ break;
+ case 100:
+ r->is_error = 1;
+ return;
+ break;
}
}
static void
free_byte_array_callback (void *pointer)
{
- GByteArray *arr = (GByteArray *)pointer;
+ GByteArray *arr = (GByteArray *) pointer;
g_byte_array_free (arr, TRUE);
}
-static GByteArray *
-convert_text_to_utf (struct worker_task *task, GByteArray *part_content, GMimeContentType *type, struct mime_text_part *text_part)
+static GByteArray *
+convert_text_to_utf (struct worker_task *task, GByteArray * part_content, GMimeContentType * type, struct mime_text_part *text_part)
{
- GError *err = NULL;
- gsize read_bytes, write_bytes;
- const char *charset;
- gchar *res_str;
- GByteArray *result_array;
+ GError *err = NULL;
+ gsize read_bytes, write_bytes;
+ const char *charset;
+ gchar *res_str;
+ GByteArray *result_array;
if (task->cfg->raw_mode) {
text_part->is_raw = TRUE;
text_part->is_raw = TRUE;
return part_content;
}
-
+
if (g_ascii_strcasecmp (charset, "utf-8") == 0 || g_ascii_strcasecmp (charset, "utf8") == 0) {
text_part->is_raw = TRUE;
return part_content;
}
-
- res_str = g_convert_with_fallback (part_content->data, part_content->len,
- "UTF-8", charset, NULL,
- &read_bytes, &write_bytes, &err);
+
+ res_str = g_convert_with_fallback (part_content->data, part_content->len, "UTF-8", charset, NULL, &read_bytes, &write_bytes, &err);
if (res_str == NULL) {
msg_warn ("convert_text_to_utf: cannot convert from %s to utf8: %s", charset, err ? err->message : "unknown problem");
text_part->is_raw = TRUE;
result_array = memory_pool_alloc (task->task_pool, sizeof (GByteArray));
result_array->data = res_str;
result_array->len = write_bytes + 1;
- memory_pool_add_destructor (task->task_pool, (pool_destruct_func)g_free, res_str);
+ memory_pool_add_destructor (task->task_pool, (pool_destruct_func) g_free, res_str);
text_part->is_raw = FALSE;
return result_array;
}
static void
-process_text_part (struct worker_task *task, GByteArray *part_content, GMimeContentType *type, gboolean is_empty)
+process_text_part (struct worker_task *task, GByteArray * part_content, GMimeContentType * type, gboolean is_empty)
{
- struct mime_text_part *text_part;
+ struct mime_text_part *text_part;
if (g_mime_content_type_is_type (type, "text", "html") || g_mime_content_type_is_type (type, "text", "xhtml")) {
msg_debug ("mime_foreach_callback: got urls from text/html part");
text_part->is_balanced = TRUE;
text_part->html_nodes = NULL;
- text_part->html_urls = g_tree_new ( (GCompareFunc)g_ascii_strcasecmp);
- text_part->urls = g_tree_new ( (GCompareFunc)g_ascii_strcasecmp);
+ text_part->html_urls = g_tree_new ((GCompareFunc) g_ascii_strcasecmp);
+ text_part->urls = g_tree_new ((GCompareFunc) g_ascii_strcasecmp);
text_part->content = strip_html_tags (task, task->task_pool, text_part, part_content, NULL);
}
text_part->fuzzy = fuzzy_init_byte_array (text_part->content, task->task_pool);
- memory_pool_add_destructor (task->task_pool, (pool_destruct_func)free_byte_array_callback, text_part->content);
- memory_pool_add_destructor (task->task_pool, (pool_destruct_func)g_tree_destroy, text_part->html_urls);
- memory_pool_add_destructor (task->task_pool, (pool_destruct_func)g_tree_destroy, text_part->urls);
+ memory_pool_add_destructor (task->task_pool, (pool_destruct_func) free_byte_array_callback, text_part->content);
+ memory_pool_add_destructor (task->task_pool, (pool_destruct_func) g_tree_destroy, text_part->html_urls);
+ memory_pool_add_destructor (task->task_pool, (pool_destruct_func) g_tree_destroy, text_part->urls);
task->text_parts = g_list_prepend (task->text_parts, text_part);
- }
+ }
else if (g_mime_content_type_is_type (type, "text", "plain")) {
msg_debug ("mime_foreach_callback: got urls from text/plain part");
text_part->content = text_part->orig;
text_part->fuzzy = fuzzy_init_byte_array (text_part->content, task->task_pool);
text_part->html_urls = NULL;
- text_part->urls = g_tree_new ( (GCompareFunc)g_ascii_strcasecmp);
+ text_part->urls = g_tree_new ((GCompareFunc) g_ascii_strcasecmp);
url_parse_text (task->task_pool, task, text_part, FALSE);
task->text_parts = g_list_prepend (task->text_parts, text_part);
- memory_pool_add_destructor (task->task_pool, (pool_destruct_func)g_tree_destroy, text_part->urls);
+ memory_pool_add_destructor (task->task_pool, (pool_destruct_func) g_tree_destroy, text_part->urls);
}
}
#ifdef GMIME24
static void
-mime_foreach_callback (GMimeObject *parent, GMimeObject *part, gpointer user_data)
+mime_foreach_callback (GMimeObject * parent, GMimeObject * part, gpointer user_data)
#else
static void
-mime_foreach_callback (GMimeObject *part, gpointer user_data)
+mime_foreach_callback (GMimeObject * part, gpointer user_data)
#endif
{
- struct worker_task *task = (struct worker_task *)user_data;
- struct mime_part *mime_part;
- GMimeContentType *type;
- GMimeDataWrapper *wrapper;
- GMimeStream *part_stream;
- GByteArray *part_content;
-
- task->parts_count ++;
-
+ struct worker_task *task = (struct worker_task *)user_data;
+ struct mime_part *mime_part;
+ GMimeContentType *type;
+ GMimeDataWrapper *wrapper;
+ GMimeStream *part_stream;
+ GByteArray *part_content;
+
+ task->parts_count++;
+
/* 'part' points to the current part node that g_mime_message_foreach_part() is iterating over */
-
+
/* find out what class 'part' is... */
if (GMIME_IS_MESSAGE_PART (part)) {
/* message/rfc822 or message/news */
- GMimeMessage *message;
-
+ GMimeMessage *message;
+
/* g_mime_message_foreach_part() won't descend into
- child message parts, so if we want to count any
- subparts of this child message, we'll have to call
- g_mime_message_foreach_part() again here. */
-
+ child message parts, so if we want to count any
+ subparts of this child message, we'll have to call
+ g_mime_message_foreach_part() again here. */
+
message = g_mime_message_part_get_message ((GMimeMessagePart *) part);
if (task->parser_recursion++ < RECURSION_LIMIT) {
#ifdef GMIME24
return;
}
g_object_unref (message);
- } else if (GMIME_IS_MESSAGE_PARTIAL (part)) {
+ }
+ else if (GMIME_IS_MESSAGE_PARTIAL (part)) {
/* message/partial */
-
+
/* this is an incomplete message part, probably a
- large message that the sender has broken into
- smaller parts and is sending us bit by bit. we
- could save some info about it so that we could
- piece this back together again once we get all the
- parts? */
- } else if (GMIME_IS_MULTIPART (part)) {
+ large message that the sender has broken into
+ smaller parts and is sending us bit by bit. we
+ could save some info about it so that we could
+ piece this back together again once we get all the
+ parts? */
+ }
+ else if (GMIME_IS_MULTIPART (part)) {
/* multipart/mixed, multipart/alternative, multipart/related, multipart/signed, multipart/encrypted, etc... */
-
+
/* we'll get to finding out if this is a signed/encrypted multipart later... */
if (task->parser_recursion++ < RECURSION_LIMIT) {
g_mime_multipart_foreach ((GMimeMultipart *) part, mime_foreach_callback, task);
msg_err ("mime_foreach_callback: endless recursion detected: %d", task->parser_recursion);
return;
}
- } else if (GMIME_IS_PART (part)) {
+ }
+ else if (GMIME_IS_PART (part)) {
/* a normal leaf part, could be text/plain or image/jpeg etc */
#ifdef GMIME24
- type = (GMimeContentType *)g_mime_object_get_content_type (GMIME_OBJECT (part));
+ type = (GMimeContentType *) g_mime_object_get_content_type (GMIME_OBJECT (part));
#else
- type = (GMimeContentType *)g_mime_part_get_content_type (GMIME_PART (part));
+ type = (GMimeContentType *) g_mime_part_get_content_type (GMIME_PART (part));
#endif
if (type == NULL) {
msg_warn ("mime_foreach_callback: type of part is unknown, assume text/plain");
type = g_mime_content_type_new ("text", "plain");
- memory_pool_add_destructor (task->task_pool, (pool_destruct_func)g_mime_content_type_destroy, type);
+ memory_pool_add_destructor (task->task_pool, (pool_destruct_func) g_mime_content_type_destroy, type);
}
wrapper = g_mime_part_get_content_object (GMIME_PART (part));
if (wrapper != NULL) {
else {
msg_warn ("mime_foreach_callback: cannot get wrapper for mime part, type of part: %s/%s", type->type, type->subtype);
}
- } else {
+ }
+ else {
g_assert_not_reached ();
}
}
static void
destroy_message (void *pointer)
{
- GMimeMessage *msg = pointer;
+ GMimeMessage *msg = pointer;
msg_debug ("destroy_message: freeing pointer %p", msg);
g_object_unref (msg);
int
process_message (struct worker_task *task)
{
- GMimeMessage *message;
- GMimeParser *parser;
- GMimeStream *stream;
- GByteArray *tmp;
- GList *first, *cur;
- struct received_header *recv;
-
+ GMimeMessage *message;
+ GMimeParser *parser;
+ GMimeStream *stream;
+ GByteArray *tmp;
+ GList *first, *cur;
+ struct received_header *recv;
+
tmp = memory_pool_alloc (task->task_pool, sizeof (GByteArray));
tmp->data = task->msg->begin;
tmp->len = task->msg->len;
msg_warn ("process_message: cannot construct mime from stream");
return -1;
}
-
+
task->message = message;
- memory_pool_add_destructor (task->task_pool, (pool_destruct_func)destroy_message, task->message);
-
+ memory_pool_add_destructor (task->task_pool, (pool_destruct_func) destroy_message, task->message);
+
task->parser_recursion = 0;
#ifdef GMIME24
g_mime_message_foreach (message, mime_foreach_callback, task);
#else
g_mime_message_foreach_part (message, mime_foreach_callback, task);
#endif
-
+
msg_debug ("process_message: found %d parts in message", task->parts_count);
if (task->queue_id == NULL) {
task->queue_id = (char *)g_mime_message_get_message_id (task->message);
#endif
/* Parse received headers */
- first = message_get_header (task->task_pool, message, "Received");
+ first = message_get_header (task->task_pool, message, "Received");
cur = first;
while (cur) {
recv = memory_pool_alloc0 (task->task_pool, sizeof (struct received_header));
}
if (task->raw_headers) {
- memory_pool_add_destructor (task->task_pool, (pool_destruct_func)g_free, task->raw_headers);
+ memory_pool_add_destructor (task->task_pool, (pool_destruct_func) g_free, task->raw_headers);
}
task->rcpts = g_mime_message_get_all_recipients (message);
if (task->rcpts) {
- memory_pool_add_destructor (task->task_pool, (pool_destruct_func)internet_address_list_destroy, task->rcpts);
+ memory_pool_add_destructor (task->task_pool, (pool_destruct_func) internet_address_list_destroy, task->rcpts);
}
-
+
if (task->worker) {
- task->worker->srv->stat->messages_scanned ++;
+ task->worker->srv->stat->messages_scanned++;
}
/* free the parser (and the stream) */
}
struct raw_header {
- struct raw_header *next;
- char *name;
- char *value;
-};
+ struct raw_header *next;
+ char *name;
+ char *value;
+};
typedef struct _GMimeHeader {
- GHashTable *hash;
- GHashTable *writers;
- struct raw_header *headers;
+ GHashTable *hash;
+ GHashTable *writers;
+ struct raw_header *headers;
} local_GMimeHeader;
#ifndef GMIME24
static void
-header_iterate (memory_pool_t *pool, struct raw_header *h, GList **ret, const char *field)
+header_iterate (memory_pool_t * pool, struct raw_header *h, GList ** ret, const char *field)
{
while (h) {
if (h->value && !g_strncasecmp (field, h->name, strlen (field))) {
}
#else
static void
-header_iterate (memory_pool_t *pool, GMimeHeaderList *ls, GList **ret, const char field)
+header_iterate (memory_pool_t * pool, GMimeHeaderList * ls, GList ** ret, const char field)
{
- GMimeHeaderIter *iter;
- const char *name;
+ GMimeHeaderIter *iter;
+ const char *name;
if (g_mime_header_list_get_iter (ls, iter)) {
while (g_mime_header_iter_is_valid (iter)) {
struct multipart_cb_data {
- GList *ret;
- memory_pool_t *pool;
- const char *field;
- gboolean try_search;
- int rec;
+ GList *ret;
+ memory_pool_t *pool;
+ const char *field;
+ gboolean try_search;
+ int rec;
};
#define MAX_REC 10
static void
#ifdef GMIME24
-multipart_iterate (GMimeObject *parent, GMimeObject *part, gpointer user_data)
+multipart_iterate (GMimeObject * parent, GMimeObject * part, gpointer user_data)
#else
-multipart_iterate (GMimeObject *part, gpointer user_data)
+multipart_iterate (GMimeObject * part, gpointer user_data)
#endif
{
- struct multipart_cb_data *data = user_data;
- struct raw_header *h;
- GList *l = NULL;
-
- if (data->try_search && GMIME_IS_PART (part)) {
+ struct multipart_cb_data *data = user_data;
+ struct raw_header *h;
+ GList *l = NULL;
+
+ if (data->try_search && GMIME_IS_PART (part)) {
#ifdef GMIME24
- GMimeHeaderList *ls;
+ GMimeHeaderList *ls;
- ls = GMIME_OBJECT(message)->headers;
+ ls = GMIME_OBJECT (message)->headers;
header_iterate (data->pool, ls, &l, data->field);
#else
h = part->headers->headers;
data->ret = g_list_concat (l, data->ret);
}
}
- else if (data->try_search && GMIME_IS_MULTIPART (part)) {
+ else if (data->try_search && GMIME_IS_MULTIPART (part)) {
/* Maybe endless recursion here ? */
if (data->rec++ < MAX_REC) {
- g_mime_multipart_foreach (GMIME_MULTIPART (part), multipart_iterate, data);
+ g_mime_multipart_foreach (GMIME_MULTIPART (part), multipart_iterate, data);
}
else {
msg_info ("multipart_iterate: maximum recurse limit is over, stop recursing, %d", data->rec);
}
}
-static GList *
-local_message_get_header(memory_pool_t *pool, GMimeMessage *message, const char *field)
+static GList *
+local_message_get_header (memory_pool_t * pool, GMimeMessage * message, const char *field)
{
- GList *gret = NULL;
- GMimeObject *part;
- struct multipart_cb_data cb = {
+ GList *gret = NULL;
+ GMimeObject *part;
+ struct multipart_cb_data cb = {
.try_search = TRUE,
.rec = 0,
.ret = NULL,
cb.field = field;
#ifndef GMIME24
- struct raw_header *h;
+ struct raw_header *h;
if (field == NULL) {
return NULL;
}
- h = GMIME_OBJECT(message)->headers->headers;
+ h = GMIME_OBJECT (message)->headers->headers;
header_iterate (pool, h, &gret, field);
-
+
if (gret == NULL) {
/* Try to iterate with mime part headers */
part = g_mime_message_get_mime_part (message);
return gret;
#else
- GMimeHeaderList *ls;
+ GMimeHeaderList *ls;
- ls = GMIME_OBJECT(message)->headers;
+ ls = GMIME_OBJECT (message)->headers;
header_iterate (pool, ls, &gret, field);
if (gret == NULL) {
/* Try to iterate with mime part headers */
ls = part->headers;
header_iterate (pool, ls, &gret, field);
if (gret == NULL && GMIME_IS_MULTIPART (part)) {
- g_mime_multipart_foreach (GMIME_MULTIPART (part), multipart_iterate, &cb);
+ g_mime_multipart_foreach (GMIME_MULTIPART (part), multipart_iterate, &cb);
if (cb.ret != NULL) {
gret = cb.ret;
}
* @string: A string of date
*
* Set the sent-date on a MIME Message.
-**/
+**/
void
-local_mime_message_set_date_from_string (GMimeMessage *message, const gchar *string)
+local_mime_message_set_date_from_string (GMimeMessage * message, const gchar * string)
{
- time_t date;
- int offset = 0;
+ time_t date;
+ int offset = 0;
date = g_mime_utils_header_decode_date (string, &offset);
- g_mime_message_set_date (message, date, offset);
+ g_mime_message_set_date (message, date, offset);
}
/*
* Replacements for standart gmime functions but converting adresses to IA
*/
-static const char*
-local_message_get_sender (GMimeMessage *message)
+static const char *
+local_message_get_sender (GMimeMessage * message)
{
- char *res;
- const char *from = g_mime_message_get_sender (message);
- InternetAddressList *ia;
-
+ char *res;
+ const char *from = g_mime_message_get_sender (message);
+ InternetAddressList *ia;
+
#ifndef GMIME24
ia = internet_address_parse_string (from);
#else
}
res = internet_address_list_to_string (ia, FALSE);
internet_address_list_destroy (ia);
-
+
return res;
}
-static const char*
-local_message_get_reply_to (GMimeMessage *message)
+static const char *
+local_message_get_reply_to (GMimeMessage * message)
{
- char *res;
- const char *from = g_mime_message_get_reply_to (message);
- InternetAddressList *ia;
+ char *res;
+ const char *from = g_mime_message_get_reply_to (message);
+ InternetAddressList *ia;
#ifndef GMIME24
ia = internet_address_parse_string (from);
}
res = internet_address_list_to_string (ia, FALSE);
internet_address_list_destroy (ia);
-
+
return res;
}
#ifdef GMIME24
-#define ADD_RECIPIENT_TEMPLATE(type,def) \
+# define ADD_RECIPIENT_TEMPLATE(type,def) \
static void \
local_message_add_recipients_from_string_##type (GMimeMessage *message, const gchar *string, const gchar *value) \
{ \
internet_address_list_append (il, new); \
} \
-ADD_RECIPIENT_TEMPLATE(to, GMIME_RECIPIENT_TYPE_TO)
-ADD_RECIPIENT_TEMPLATE(cc, GMIME_RECIPIENT_TYPE_CC)
-ADD_RECIPIENT_TEMPLATE(bcc, GMIME_RECIPIENT_TYPE_BCC)
-
-#define GET_RECIPIENT_TEMPLATE(type,def) \
+ADD_RECIPIENT_TEMPLATE (to, GMIME_RECIPIENT_TYPE_TO)
+ ADD_RECIPIENT_TEMPLATE (cc, GMIME_RECIPIENT_TYPE_CC)
+ ADD_RECIPIENT_TEMPLATE (bcc, GMIME_RECIPIENT_TYPE_BCC)
+# define GET_RECIPIENT_TEMPLATE(type,def) \
static InternetAddressList* \
local_message_get_recipients_##type (GMimeMessage *message, const char *unused) \
{ \
return g_mime_message_get_recipients (message, (def)); \
}
-
-GET_RECIPIENT_TEMPLATE(to, GMIME_RECIPIENT_TYPE_TO)
-GET_RECIPIENT_TEMPLATE(cc, GMIME_RECIPIENT_TYPE_CC)
-GET_RECIPIENT_TEMPLATE(bcc, GMIME_RECIPIENT_TYPE_BCC)
-
+ GET_RECIPIENT_TEMPLATE (to, GMIME_RECIPIENT_TYPE_TO)
+ GET_RECIPIENT_TEMPLATE (cc, GMIME_RECIPIENT_TYPE_CC)
+ GET_RECIPIENT_TEMPLATE (bcc, GMIME_RECIPIENT_TYPE_BCC)
#endif
-
-
/* different declarations for different types of set and get functions */
-typedef const char *(*GetFunc) (GMimeMessage *message);
-typedef InternetAddressList *(*GetRcptFunc) (GMimeMessage *message, const char *type );
-typedef GList *(*GetListFunc) (memory_pool_t *pool, GMimeMessage *message, const char *type );
-typedef void (*SetFunc) (GMimeMessage *message, const char *value);
-typedef void (*SetListFunc) (GMimeMessage *message, const char *field, const char *value);
+ typedef const char *(*GetFunc) (GMimeMessage * message);
+ typedef InternetAddressList *(*GetRcptFunc) (GMimeMessage * message, const char *type);
+ typedef GList *(*GetListFunc) (memory_pool_t * pool, GMimeMessage * message, const char *type);
+ typedef void (*SetFunc) (GMimeMessage * message, const char *value);
+ typedef void (*SetListFunc) (GMimeMessage * message, const char *field, const char *value);
/** different types of functions
*
* - function with additional "field" argument (given arbitrary header field name)
* - get returns Glist*
**/
-enum {
- FUNC_CHARPTR = 0,
- FUNC_CHARFREEPTR,
- FUNC_IA,
- FUNC_LIST
-};
+ enum {
+ FUNC_CHARPTR = 0,
+ FUNC_CHARFREEPTR,
+ FUNC_IA,
+ FUNC_LIST
+ };
/**
* fieldfunc struct: structure of MIME fields and corresponding get and set
* functions.
**/
-static struct {
- char * name;
- GetFunc func;
- GetRcptFunc rcptfunc;
- GetListFunc getlistfunc;
- SetFunc setfunc;
- SetListFunc setlfunc;
- gint functype;
-} fieldfunc[] = {
- { "From", local_message_get_sender, NULL, NULL, g_mime_message_set_sender, NULL, FUNC_CHARFREEPTR },
- { "Reply-To", local_message_get_reply_to, NULL, NULL, g_mime_message_set_reply_to, NULL, FUNC_CHARFREEPTR },
+ static struct {
+ char *name;
+ GetFunc func;
+ GetRcptFunc rcptfunc;
+ GetListFunc getlistfunc;
+ SetFunc setfunc;
+ SetListFunc setlfunc;
+ gint functype;
+ } fieldfunc[] =
+{
+ {
+ "From", local_message_get_sender, NULL, NULL, g_mime_message_set_sender, NULL, FUNC_CHARFREEPTR}, {
+ "Reply-To", local_message_get_reply_to, NULL, NULL, g_mime_message_set_reply_to, NULL, FUNC_CHARFREEPTR},
#ifndef GMIME24
- { "To", NULL, (GetRcptFunc)g_mime_message_get_recipients, NULL, NULL, (SetListFunc)g_mime_message_add_recipients_from_string, FUNC_IA },
- { "Cc", NULL, (GetRcptFunc)g_mime_message_get_recipients, NULL, NULL, (SetListFunc)g_mime_message_add_recipients_from_string, FUNC_IA },
- { "Bcc",NULL, (GetRcptFunc)g_mime_message_get_recipients, NULL, NULL, (SetListFunc)g_mime_message_add_recipients_from_string, FUNC_IA },
- { "Date", (GetFunc)g_mime_message_get_date_string, NULL, NULL, local_mime_message_set_date_from_string, NULL, FUNC_CHARFREEPTR },
+ {
+ "To", NULL, (GetRcptFunc) g_mime_message_get_recipients, NULL, NULL, (SetListFunc) g_mime_message_add_recipients_from_string, FUNC_IA}, {
+ "Cc", NULL, (GetRcptFunc) g_mime_message_get_recipients, NULL, NULL, (SetListFunc) g_mime_message_add_recipients_from_string, FUNC_IA}, {
+ "Bcc", NULL, (GetRcptFunc) g_mime_message_get_recipients, NULL, NULL, (SetListFunc) g_mime_message_add_recipients_from_string, FUNC_IA}, {
+ "Date", (GetFunc) g_mime_message_get_date_string, NULL, NULL, local_mime_message_set_date_from_string, NULL, FUNC_CHARFREEPTR},
#else
- { "To", NULL, local_message_get_recipients_to, NULL, NULL, local_message_add_recipients_from_string_to, FUNC_IA },
- { "Cc", NULL, local_message_get_recipients_cc, NULL, NULL, local_message_add_recipients_from_string_cc, FUNC_IA },
- { "Bcc", NULL, local_message_get_recipients_bcc, NULL, NULL, local_message_add_recipients_from_string_bcc, FUNC_IA },
- { "Date", g_mime_message_get_date_as_string, NULL, NULL, local_mime_message_set_date_from_string, NULL, FUNC_CHARFREEPTR },
+ {
+ "To", NULL, local_message_get_recipients_to, NULL, NULL, local_message_add_recipients_from_string_to, FUNC_IA}, {
+ "Cc", NULL, local_message_get_recipients_cc, NULL, NULL, local_message_add_recipients_from_string_cc, FUNC_IA}, {
+ "Bcc", NULL, local_message_get_recipients_bcc, NULL, NULL, local_message_add_recipients_from_string_bcc, FUNC_IA}, {
+ "Date", g_mime_message_get_date_as_string, NULL, NULL, local_mime_message_set_date_from_string, NULL, FUNC_CHARFREEPTR},
#endif
- { "Subject", g_mime_message_get_subject, NULL, NULL, g_mime_message_set_subject, NULL, FUNC_CHARPTR },
- { "Message-Id", g_mime_message_get_message_id, NULL, NULL, g_mime_message_set_message_id, NULL, FUNC_CHARPTR },
+ {
+ "Subject", g_mime_message_get_subject, NULL, NULL, g_mime_message_set_subject, NULL, FUNC_CHARPTR}, {
+ "Message-Id", g_mime_message_get_message_id, NULL, NULL, g_mime_message_set_message_id, NULL, FUNC_CHARPTR},
#ifndef GMIME24
- { NULL, NULL, NULL, local_message_get_header, NULL, g_mime_message_add_header, FUNC_LIST }
+ {
+ NULL, NULL, NULL, local_message_get_header, NULL, g_mime_message_add_header, FUNC_LIST}
#else
- { NULL, NULL, NULL, local_message_get_header, NULL, g_mime_object_append_header, FUNC_LIST }
+ {
+ NULL, NULL, NULL, local_message_get_header, NULL, g_mime_object_append_header, FUNC_LIST}
#endif
};
+
/**
* message_set_header: set header of any type excluding special (Content- and MIME-Version:)
**/
void
-message_set_header (GMimeMessage *message, const char *field, const char *value)
+message_set_header (GMimeMessage * message, const char *field, const char *value)
{
- gint i;
+ gint i;
if (!g_strcasecmp (field, "MIME-Version:") || !g_strncasecmp (field, "Content-", 8)) {
return;
}
- for (i=0; i<=HEADER_UNKNOWN; ++i) {
- if (!fieldfunc[i].name || !g_strncasecmp(field, fieldfunc[i].name, strlen(fieldfunc[i].name))) {
+ for (i = 0; i <= HEADER_UNKNOWN; ++i) {
+ if (!fieldfunc[i].name || !g_strncasecmp (field, fieldfunc[i].name, strlen (fieldfunc[i].name))) {
switch (fieldfunc[i].functype) {
- case FUNC_CHARPTR:
- (*(fieldfunc[i].setfunc))(message, value);
- break;
- case FUNC_IA:
- (*(fieldfunc[i].setlfunc))(message, fieldfunc[i].name, value);
- break;
- case FUNC_LIST:
- (*(fieldfunc[i].setlfunc))(message, field, value);
- break;
+ case FUNC_CHARPTR:
+ (*(fieldfunc[i].setfunc)) (message, value);
+ break;
+ case FUNC_IA:
+ (*(fieldfunc[i].setlfunc)) (message, fieldfunc[i].name, value);
+ break;
+ case FUNC_LIST:
+ (*(fieldfunc[i].setlfunc)) (message, field, value);
+ break;
}
break;
- }
+ }
}
}
*
* You should free the GList list by yourself.
**/
-GList *
-message_get_header (memory_pool_t *pool, GMimeMessage *message, const char *field)
+GList *
+message_get_header (memory_pool_t * pool, GMimeMessage * message, const char *field)
{
- gint i;
- char * ret = NULL, *ia_string;
- GList * gret = NULL;
- InternetAddressList *ia_list = NULL, *ia;
+ gint i;
+ char *ret = NULL, *ia_string;
+ GList *gret = NULL;
+ InternetAddressList *ia_list = NULL, *ia;
for (i = 0; i <= HEADER_UNKNOWN; ++i) {
- if (!fieldfunc[i].name || !g_strncasecmp(field, fieldfunc[i].name, strlen(fieldfunc[i].name))) {
+ if (!fieldfunc[i].name || !g_strncasecmp (field, fieldfunc[i].name, strlen (fieldfunc[i].name))) {
switch (fieldfunc[i].functype) {
- case FUNC_CHARFREEPTR:
- ret = (char *)(*(fieldfunc[i].func))(message);
- break;
- case FUNC_CHARPTR:
- ret = (char *)(*(fieldfunc[i].func))(message);
- break;
- case FUNC_IA:
- ia_list = (*(fieldfunc[i].rcptfunc))(message, field);
- gret = g_list_alloc();
- ia = ia_list;
+ case FUNC_CHARFREEPTR:
+ ret = (char *)(*(fieldfunc[i].func)) (message);
+ break;
+ case FUNC_CHARPTR:
+ ret = (char *)(*(fieldfunc[i].func)) (message);
+ break;
+ case FUNC_IA:
+ ia_list = (*(fieldfunc[i].rcptfunc)) (message, field);
+ gret = g_list_alloc ();
+ ia = ia_list;
#ifndef GMIME24
- while (ia && ia->address) {
+ while (ia && ia->address) {
- ia_string = internet_address_to_string ((InternetAddress *)ia->address, FALSE);
- memory_pool_add_destructor (pool, (pool_destruct_func)g_free, ia_string);
- gret = g_list_prepend (gret, ia_string);
- ia = ia->next;
- }
+ ia_string = internet_address_to_string ((InternetAddress *) ia->address, FALSE);
+ memory_pool_add_destructor (pool, (pool_destruct_func) g_free, ia_string);
+ gret = g_list_prepend (gret, ia_string);
+ ia = ia->next;
+ }
#else
- i = internet_address_list_length (ia);
- while (i > 0) {
- ia_string = internet_address_to_string (internet_address_list_get_address (ia, i), FALSE);
- memory_pool_add_destructor (pool, (pool_destruct_func)g_free, ia_string);
- gret = g_list_prepend (gret, ia_string);
- -- i;
- }
+ i = internet_address_list_length (ia);
+ while (i > 0) {
+ ia_string = internet_address_to_string (internet_address_list_get_address (ia, i), FALSE);
+ memory_pool_add_destructor (pool, (pool_destruct_func) g_free, ia_string);
+ gret = g_list_prepend (gret, ia_string);
+ --i;
+ }
#endif
- break;
- case FUNC_LIST:
- gret = (*(fieldfunc[i].getlistfunc))(pool, message, field);
- break;
+ break;
+ case FUNC_LIST:
+ gret = (*(fieldfunc[i].getlistfunc)) (pool, message, field);
+ break;
}
break;
- }
+ }
}
if (gret == NULL && ret != NULL) {
if (pool != NULL) {
#include "perl.h"
#include "cfg_file.h"
-#include <EXTERN.h> /* from the Perl distribution */
-#include <perl.h> /* from the Perl distribution */
+#include <EXTERN.h> /* from the Perl distribution */
+#include <perl.h> /* from the Perl distribution */
#ifndef PERL_IMPLICIT_CONTEXT
-#undef dTHXa
-#define dTHXa(a)
+# undef dTHXa
+# define dTHXa(a)
#endif
/* Perl module init function */
#define MODULE_INIT_FUNC "module_init"
-PerlInterpreter *perl_interpreter;
+PerlInterpreter *perl_interpreter;
-static HV *rspamd_task_stash;
-static HV *rspamd_cfg_stash;
+static HV *rspamd_task_stash;
+static HV *rspamd_cfg_stash;
-extern void boot_DynaLoader (pTHX_ CV* cv);
-extern void boot_Socket (pTHX_ CV* cv);
+extern void boot_DynaLoader (pTHX_ CV * cv);
+extern void boot_Socket (pTHX_ CV * cv);
void
-xs_init(pTHX)
+xs_init (pTHX)
{
dXSUB_SYS;
/* DynaLoader is a special case */
newXS ("DynaLoader::boot_DynaLoader", boot_DynaLoader, __FILE__);
- rspamd_task_stash = gv_stashpv("rspamd_task", TRUE);
- rspamd_cfg_stash = gv_stashpv("rspamd_config", TRUE);
+ rspamd_task_stash = gv_stashpv ("rspamd_task", TRUE);
+ rspamd_cfg_stash = gv_stashpv ("rspamd_config", TRUE);
}
void
init_perl_filters (struct config_file *cfg)
{
- struct perl_module *module;
- char *init_func;
- size_t funclen;
- SV* sv;
-
+ struct perl_module *module;
+ char *init_func;
+ size_t funclen;
+ SV *sv;
+
dTHXa (perl_interpreter);
PERL_SET_CONTEXT (perl_interpreter);
SAVETMPS;
PUSHMARK (SP);
- sv = sv_2mortal (sv_bless (newRV_noinc (newSViv (PTR2IV(cfg))), rspamd_cfg_stash));
+ sv = sv_2mortal (sv_bless (newRV_noinc (newSViv (PTR2IV (cfg))), rspamd_cfg_stash));
XPUSHs (sv);
PUTBACK;
/* Call module init function */
int
perl_call_header_filter (const char *function, struct worker_task *task)
{
- int result;
- SV* sv;
+ int result;
+ SV *sv;
dTHXa (perl_interpreter);
PERL_SET_CONTEXT (perl_interpreter);
SAVETMPS;
PUSHMARK (SP);
- sv = sv_2mortal (sv_bless (newRV_noinc (newSViv (PTR2IV(task))), rspamd_task_stash));
+ sv = sv_2mortal (sv_bless (newRV_noinc (newSViv (PTR2IV (task))), rspamd_task_stash));
XPUSHs (sv);
PUTBACK;
-
+
call_pv (function, G_SCALAR);
SPAGAIN;
int
perl_call_chain_filter (const char *function, struct worker_task *task, int *marks, unsigned int number)
{
- int result, i;
- AV *av;
- SV *sv;
+ int result, i;
+ AV *av;
+ SV *sv;
dTHXa (perl_interpreter);
PERL_SET_CONTEXT (perl_interpreter);
dSP;
-
+
ENTER;
SAVETMPS;
- av = newAV();
+ av = newAV ();
av_extend (av, number);
- for (i = 0; i < number; i ++) {
+ for (i = 0; i < number; i++) {
av_push (av, sv_2mortal (newSViv (marks[i])));
}
PUSHMARK (SP);
- sv = sv_2mortal (sv_bless (newRV_noinc (newSViv (PTR2IV(task))), rspamd_task_stash));
+ sv = sv_2mortal (sv_bless (newRV_noinc (newSViv (PTR2IV (task))), rspamd_task_stash));
XPUSHs (sv);
- XPUSHs (sv_2mortal ((SV *)AvARRAY (av)));
+ XPUSHs (sv_2mortal ((SV *) AvARRAY (av)));
PUTBACK;
-
+
call_pv (function, G_SCALAR);
SPAGAIN;
return result;
}
-void
-perl_call_memcached_callback (memcached_ctx_t *ctx, memc_error_t error, void *data)
+void
+perl_call_memcached_callback (memcached_ctx_t * ctx, memc_error_t error, void *data)
{
struct {
- SV *callback;
- struct worker_task *task;
- } *callback_data = data;
- SV *sv;
-
+ SV *callback;
+ struct worker_task *task;
+ } *callback_data = data;
+ SV *sv;
+
dTHXa (perl_interpreter);
PERL_SET_CONTEXT (perl_interpreter);
ENTER;
SAVETMPS;
PUSHMARK (SP);
- sv = sv_2mortal (sv_bless (newRV_noinc (newSViv (PTR2IV(callback_data->task))), rspamd_task_stash));
+ sv = sv_2mortal (sv_bless (newRV_noinc (newSViv (PTR2IV (callback_data->task))), rspamd_task_stash));
XPUSHs (sv);
XPUSHs (sv_2mortal (newSViv (error)));
XPUSHs (sv_2mortal (newSVpv (ctx->param->buf, ctx->param->bufsize)));
PUTBACK;
call_sv (callback_data->callback, G_SCALAR);
-
+
/* Set save point */
callback_data->task->save.saved = 0;
process_filters (callback_data->task);
* Perl custom consolidation function
*/
struct consolidation_callback_data {
- struct worker_task *task;
- double score;
- const char *func;
+ struct worker_task *task;
+ double score;
+ const char *func;
};
static void
perl_consolidation_callback (gpointer key, gpointer value, gpointer arg)
{
- double res;
- struct symbol *s = (struct symbol *)value;
+ double res;
+ struct symbol *s = (struct symbol *)value;
struct consolidation_callback_data *data = (struct consolidation_callback_data *)arg;
-
+
dTHXa (perl_interpreter);
PERL_SET_CONTEXT (perl_interpreter);
SAVETMPS;
PUSHMARK (SP);
-
+
XPUSHs (sv_2mortal (newSVpv ((const char *)key, 0)));
XPUSHs (sv_2mortal (newSVnv (s->score)));
PUTBACK;
-
+
call_pv (data->func, G_SCALAR);
SPAGAIN;
double
perl_consolidation_func (struct worker_task *task, const char *metric_name, const char *function_name)
{
- struct metric_result *metric_res;
- double res = 0.;
+ struct metric_result *metric_res;
+ double res = 0.;
struct consolidation_callback_data data = { task, 0, function_name };
if (function_name == NULL) {
#define DEFAULT_THRESHOLD 0.1
struct chartable_ctx {
- int (*filter)(struct worker_task *task);
- char *metric;
- char *symbol;
- double threshold;
+ int (*filter) (struct worker_task * task);
+ char *metric;
+ char *symbol;
+ double threshold;
- memory_pool_t *chartable_pool;
+ memory_pool_t *chartable_pool;
};
-static struct chartable_ctx *chartable_module_ctx = NULL;
+static struct chartable_ctx *chartable_module_ctx = NULL;
-static int chartable_mime_filter (struct worker_task *task);
-static void chartable_symbol_callback (struct worker_task *task, void *unused);
+static int chartable_mime_filter (struct worker_task *task);
+static void chartable_symbol_callback (struct worker_task *task, void *unused);
int
chartable_module_init (struct config_file *cfg, struct module_ctx **ctx)
chartable_module_ctx->chartable_pool = memory_pool_new (memory_pool_get_size ());
*ctx = (struct module_ctx *)chartable_module_ctx;
-
+
return 0;
}
int
chartable_module_config (struct config_file *cfg)
{
- char *value;
- int res = TRUE;
- struct metric *metric;
- double *w;
+ char *value;
+ int res = TRUE;
+ struct metric *metric;
+ double *w;
if ((value = get_module_opt (cfg, "chartable", "metric")) != NULL) {
chartable_module_ctx->metric = memory_pool_strdup (chartable_module_ctx->chartable_pool, value);
return chartable_module_config (cfg);
}
-static gboolean
+static gboolean
check_part (struct mime_text_part *part, gboolean raw_mode)
{
- unsigned char *p, *p1;
- gunichar c, t;
- GUnicodeScript scc, sct;
- uint32_t mark = 0, total = 0;
- uint32_t remain = part->content->len;
-
+ unsigned char *p, *p1;
+ gunichar c, t;
+ GUnicodeScript scc, sct;
+ uint32_t mark = 0, total = 0;
+ uint32_t remain = part->content->len;
+
p = part->content->data;
if (part->is_raw || raw_mode) {
while (remain > 1) {
- if ((g_ascii_isalpha (*p) && (*(p + 1) & 0x80)) ||
- ((*p & 0x80) && g_ascii_isalpha (*(p + 1)))) {
- mark ++;
- total ++;
+ if ((g_ascii_isalpha (*p) && (*(p + 1) & 0x80)) || ((*p & 0x80) && g_ascii_isalpha (*(p + 1)))) {
+ mark++;
+ total++;
}
/* Current and next symbols are of one class */
- else if (((*p & 0x80) && (*(p + 1) & 0x80)) ||
- (g_ascii_isalpha (*p) && g_ascii_isalpha (*(p + 1)))) {
- total ++;
+ else if (((*p & 0x80) && (*(p + 1) & 0x80)) || (g_ascii_isalpha (*p) && g_ascii_isalpha (*(p + 1)))) {
+ total++;
}
- p ++;
- remain --;
+ p++;
+ remain--;
}
}
else {
while (remain > 0) {
c = g_utf8_get_char_validated (p, remain);
- if (c == (gunichar)-2 || c == (gunichar)-1) {
- /* Invalid characters detected, stop processing*/
+ if (c == (gunichar) - 2 || c == (gunichar) - 1) {
+ /* Invalid characters detected, stop processing */
return FALSE;
}
p1 = g_utf8_next_char (p);
remain -= p1 - p;
p = p1;
-
+
if (remain > 0) {
t = g_utf8_get_char_validated (p, remain);
- if (c == (gunichar)-2 || c == (gunichar)-1) {
- /* Invalid characters detected, stop processing*/
+ if (c == (gunichar) - 2 || c == (gunichar) - 1) {
+ /* Invalid characters detected, stop processing */
return FALSE;
}
sct = g_unichar_get_script (t);
if (g_unichar_isalnum (c) && g_unichar_isalnum (t)) {
/* We have two unicode alphanumeric characters, so we can check its script */
if (sct != scc) {
- mark ++;
+ mark++;
}
- total ++;
+ total++;
}
p1 = g_utf8_next_char (p);
remain -= p1 - p;
return ((double)mark / (double)total) > chartable_module_ctx->threshold;
}
-static void
+static void
chartable_symbol_callback (struct worker_task *task, void *unused)
-{
- GList *cur;
- struct mime_text_part *part;
+{
+ GList *cur;
+ struct mime_text_part *part;
if (check_view (task->cfg->views, chartable_module_ctx->symbol, task)) {
cur = g_list_first (task->text_parts);
while (cur) {
part = cur->data;
if (!part->is_empty && check_part (part, task->cfg->raw_mode)) {
- insert_result (task, chartable_module_ctx->metric, chartable_module_ctx->symbol, 1, NULL);
+ insert_result (task, chartable_module_ctx->metric, chartable_module_ctx->symbol, 1, NULL);
}
cur = g_list_next (cur);
}
}
-static int
+static int
chartable_mime_filter (struct worker_task *task)
{
/* XXX: remove it */
#define DEFAULT_SYMBOL "R_BAD_EMAIL"
-static const char *email_re_text = "[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+(?:[A-Z]{2}|com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum)\\b";
+static const char *email_re_text =
+ "[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+(?:[A-Z]{2}|com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum)\\b";
struct email_ctx {
- int (*filter)(struct worker_task *task);
- char *metric;
- char *symbol;
- GRegex *email_re;
+ int (*filter) (struct worker_task * task);
+ char *metric;
+ char *symbol;
+ GRegex *email_re;
- GHashTable *blacklist;
- char *blacklist_file;
+ GHashTable *blacklist;
+ char *blacklist_file;
- memory_pool_t *email_pool;
+ memory_pool_t *email_pool;
};
-static struct email_ctx *email_module_ctx = NULL;
+static struct email_ctx *email_module_ctx = NULL;
-static int emails_mime_filter (struct worker_task *task);
-static void emails_symbol_callback (struct worker_task *task, void *unused);
-static int emails_command_handler (struct worker_task *task);
+static int emails_mime_filter (struct worker_task *task);
+static void emails_symbol_callback (struct worker_task *task, void *unused);
+static int emails_command_handler (struct worker_task *task);
int
emails_module_init (struct config_file *cfg, struct module_ctx **ctx)
{
- GError *err = NULL;
+ GError *err = NULL;
email_module_ctx = g_malloc (sizeof (struct email_ctx));
email_module_ctx->email_pool = memory_pool_new (memory_pool_get_size ());
email_module_ctx->email_re = g_regex_new (email_re_text, G_REGEX_RAW | G_REGEX_OPTIMIZE | G_REGEX_CASELESS, 0, &err);
email_module_ctx->blacklist = g_hash_table_new (rspamd_strcase_hash, rspamd_strcase_equal);
-
+
*ctx = (struct module_ctx *)email_module_ctx;
-
+
register_protocol_command ("emails", emails_command_handler);
return 0;
int
emails_module_config (struct config_file *cfg)
{
- char *value;
- int res = TRUE;
- struct metric *metric;
- double *w;
+ char *value;
+ int res = TRUE;
+ struct metric *metric;
+ double *w;
if ((value = get_module_opt (cfg, "emails", "metric")) != NULL) {
email_module_ctx->metric = memory_pool_strdup (email_module_ctx->email_pool, value);
if (add_map (value, read_host_list, fin_host_list, (void **)&email_module_ctx->blacklist)) {
email_module_ctx->blacklist_file = memory_pool_strdup (email_module_ctx->email_pool, value + sizeof ("file://") - 1);
}
- }
+ }
metric = g_hash_table_lookup (cfg->metrics, email_module_ctx->metric);
if (metric == NULL) {
return emails_module_config (cfg);
}
-static GList *
+static GList *
extract_emails (struct worker_task *task)
{
- GList *res = NULL, *cur;
- GMatchInfo *info;
- GError *err = NULL;
- struct mime_text_part *part;
- char *email_str;
- int rc;
+ GList *res = NULL, *cur;
+ GMatchInfo *info;
+ GError *err = NULL;
+ struct mime_text_part *part;
+ char *email_str;
+ int rc;
cur = g_list_first (task->text_parts);
while (cur) {
email_str = g_match_info_fetch (info, 0);
if (email_str != NULL) {
res = g_list_prepend (res, email_str);
- memory_pool_add_destructor (task->task_pool, (pool_destruct_func)g_free, email_str);
+ memory_pool_add_destructor (task->task_pool, (pool_destruct_func) g_free, email_str);
}
/* Get next match */
g_match_info_next (info, &err);
cur = g_list_next (cur);
}
if (res != NULL) {
- memory_pool_add_destructor (task->task_pool, (pool_destruct_func)g_list_free, res);
+ memory_pool_add_destructor (task->task_pool, (pool_destruct_func) g_list_free, res);
}
-
+
return res;
}
-static int
+static int
emails_command_handler (struct worker_task *task)
{
- GList *emails, *cur;
- char outbuf[BUFSIZ];
- int r, num = 0;
+ GList *emails, *cur;
+ char outbuf[BUFSIZ];
+ int r, num = 0;
emails = extract_emails (task);
r = snprintf (outbuf, sizeof (outbuf), "%s 0 %s" CRLF, (task->proto == SPAMC_PROTO) ? SPAMD_REPLY_BANNER : RSPAMD_REPLY_BANNER, "OK");
-
+
r += snprintf (outbuf + r, sizeof (outbuf) - r - 2, "Emails: ");
-
+
cur = g_list_first (emails);
while (cur) {
- num ++;
+ num++;
if (g_list_next (cur) != NULL) {
r += snprintf (outbuf + r, sizeof (outbuf) - r - 2, "%s, ", (char *)cur->data);
}
}
cur = g_list_next (cur);
}
-
- outbuf[r++] = '\r'; outbuf[r++] = '\n';
+
+ outbuf[r++] = '\r';
+ outbuf[r++] = '\n';
rspamd_dispatcher_write (task->dispatcher, outbuf, r, FALSE, FALSE);
msg_info ("process_message: msg ok, id: <%s>, %d emails extracted", task->message_id, num);
return 0;
}
-static void
+static void
emails_symbol_callback (struct worker_task *task, void *unused)
-{
- GList *emails, *cur;
+{
+ GList *emails, *cur;
if (check_view (task->cfg->views, email_module_ctx->symbol, task)) {
while (cur) {
if (g_hash_table_lookup (email_module_ctx->blacklist, cur->data) != NULL) {
- insert_result (task, email_module_ctx->metric, email_module_ctx->symbol, 1,
- g_list_prepend (NULL, memory_pool_strdup (task->task_pool, (char *)cur->data)));
-
+ insert_result (task, email_module_ctx->metric, email_module_ctx->symbol, 1, g_list_prepend (NULL, memory_pool_strdup (task->task_pool, (char *)cur->data)));
+
}
cur = g_list_next (cur);
}
}
-static int
+static int
emails_mime_filter (struct worker_task *task)
{
/* XXX: remove this */
#define DEFAULT_PORT 11335
struct storage_server {
- struct upstream up;
- char *name;
- struct in_addr addr;
- uint16_t port;
+ struct upstream up;
+ char *name;
+ struct in_addr addr;
+ uint16_t port;
};
struct fuzzy_ctx {
- int (*filter)(struct worker_task *task);
- char *metric;
- char *symbol;
- struct storage_server *servers;
- int servers_num;
- memory_pool_t *fuzzy_pool;
+ int (*filter) (struct worker_task * task);
+ char *metric;
+ char *symbol;
+ struct storage_server *servers;
+ int servers_num;
+ memory_pool_t *fuzzy_pool;
};
struct fuzzy_client_session {
- int state;
- fuzzy_hash_t *h;
- struct event ev;
- struct timeval tv;
- struct worker_task *task;
- struct storage_server *server;
+ int state;
+ fuzzy_hash_t *h;
+ struct event ev;
+ struct timeval tv;
+ struct worker_task *task;
+ struct storage_server *server;
};
struct fuzzy_learn_session {
- struct event ev;
- fuzzy_hash_t *h;
- int cmd;
- int *saved;
- struct timeval tv;
- struct controller_session *session;
- struct storage_server *server;
- struct worker_task *task;
+ struct event ev;
+ fuzzy_hash_t *h;
+ int cmd;
+ int *saved;
+ struct timeval tv;
+ struct controller_session *session;
+ struct storage_server *server;
+ struct worker_task *task;
};
-static struct fuzzy_ctx *fuzzy_module_ctx = NULL;
+static struct fuzzy_ctx *fuzzy_module_ctx = NULL;
-static int fuzzy_mime_filter (struct worker_task *task);
-static void fuzzy_symbol_callback (struct worker_task *task, void *unused);
-static void fuzzy_add_handler (char **args, struct controller_session *session);
-static void fuzzy_delete_handler (char **args, struct controller_session *session);
+static int fuzzy_mime_filter (struct worker_task *task);
+static void fuzzy_symbol_callback (struct worker_task *task, void *unused);
+static void fuzzy_add_handler (char **args, struct controller_session *session);
+static void fuzzy_delete_handler (char **args, struct controller_session *session);
static void
parse_servers_string (char *str)
{
- char **strvec, *p, portbuf[6], *name;
- int num, i, j, port;
- struct hostent *hent;
- struct in_addr addr;
+ char **strvec, *p, portbuf[6], *name;
+ int num, i, j, port;
+ struct hostent *hent;
+ struct in_addr addr;
strvec = g_strsplit (str, ",", 0);
num = g_strv_length (strvec);
fuzzy_module_ctx->servers = memory_pool_alloc0 (fuzzy_module_ctx->fuzzy_pool, sizeof (struct storage_server) * num);
- for (i = 0; i < num; i ++) {
+ for (i = 0; i < num; i++) {
g_strstrip (strvec[i]);
if ((p = strchr (strvec[i], ':')) != NULL) {
j = 0;
- p ++;
+ p++;
while (g_ascii_isdigit (*(p + j)) && j < sizeof (portbuf) - 1) {
portbuf[j] = *(p + j);
- j ++;
+ j++;
}
portbuf[j] = '\0';
port = atoi (portbuf);
continue;
}
else {
- fuzzy_module_ctx->servers[fuzzy_module_ctx->servers_num].port = port;
- fuzzy_module_ctx->servers[fuzzy_module_ctx->servers_num].name = name;
- memcpy (&fuzzy_module_ctx->servers[fuzzy_module_ctx->servers_num].addr, hent->h_addr, sizeof(struct in_addr));
- fuzzy_module_ctx->servers_num ++;
+ fuzzy_module_ctx->servers[fuzzy_module_ctx->servers_num].port = port;
+ fuzzy_module_ctx->servers[fuzzy_module_ctx->servers_num].name = name;
+ memcpy (&fuzzy_module_ctx->servers[fuzzy_module_ctx->servers_num].addr, hent->h_addr, sizeof (struct in_addr));
+ fuzzy_module_ctx->servers_num++;
}
}
else {
- fuzzy_module_ctx->servers[fuzzy_module_ctx->servers_num].port = port;
- fuzzy_module_ctx->servers[fuzzy_module_ctx->servers_num].name = name;
- memcpy (&fuzzy_module_ctx->servers[fuzzy_module_ctx->servers_num].addr, hent->h_addr, sizeof(struct in_addr));
- fuzzy_module_ctx->servers_num ++;
+ fuzzy_module_ctx->servers[fuzzy_module_ctx->servers_num].port = port;
+ fuzzy_module_ctx->servers[fuzzy_module_ctx->servers_num].name = name;
+ memcpy (&fuzzy_module_ctx->servers[fuzzy_module_ctx->servers_num].addr, hent->h_addr, sizeof (struct in_addr));
+ fuzzy_module_ctx->servers_num++;
}
}
fuzzy_module_ctx->fuzzy_pool = memory_pool_new (memory_pool_get_size ());
fuzzy_module_ctx->servers = NULL;
fuzzy_module_ctx->servers_num = 0;
-
+
*ctx = (struct module_ctx *)fuzzy_module_ctx;
return 0;
int
fuzzy_check_module_config (struct config_file *cfg)
{
- char *value;
- int res = TRUE;
- struct metric *metric;
- double *w;
+ char *value;
+ int res = TRUE;
+ struct metric *metric;
+ double *w;
if ((value = get_module_opt (cfg, "fuzzy_check", "metric")) != NULL) {
fuzzy_module_ctx->metric = memory_pool_strdup (fuzzy_module_ctx->fuzzy_pool, value);
}
if ((value = get_module_opt (cfg, "fuzzy_check", "servers")) != NULL) {
parse_servers_string (value);
- }
+ }
metric = g_hash_table_lookup (cfg->metrics, fuzzy_module_ctx->metric);
if (metric == NULL) {
register_custom_controller_command ("fuzzy_add", fuzzy_add_handler, TRUE, TRUE);
register_custom_controller_command ("fuzzy_del", fuzzy_delete_handler, TRUE, TRUE);
-
+
return res;
}
static void
fuzzy_io_fin (void *ud)
{
- struct fuzzy_client_session *session = ud;
+ struct fuzzy_client_session *session = ud;
event_del (&session->ev);
- session->task->save.saved --;
+ session->task->save.saved--;
if (session->task->save.saved == 0) {
/* Call other filters */
session->task->save.saved = 1;
static void
fuzzy_io_callback (int fd, short what, void *arg)
{
- struct fuzzy_client_session *session = arg;
- struct fuzzy_cmd cmd;
- char buf[sizeof ("ERR")];
+ struct fuzzy_client_session *session = arg;
+ struct fuzzy_cmd cmd;
+ char buf[sizeof ("ERR")];
if (what == EV_WRITE) {
/* Send command to storage */
}
goto ok;
}
-
+
return;
- err:
- msg_err ("fuzzy_io_callback: got error on IO with server %s:%d, %d, %s", session->server->name, session->server->port,
- errno, strerror (errno));
- ok:
- close (fd);
- remove_normal_event (session->task->s, fuzzy_io_fin, session);
+ err:
+ msg_err ("fuzzy_io_callback: got error on IO with server %s:%d, %d, %s", session->server->name, session->server->port, errno, strerror (errno));
+ ok:
+ close (fd);
+ remove_normal_event (session->task->s, fuzzy_io_fin, session);
}
static void
fuzzy_learn_fin (void *arg)
{
- struct fuzzy_learn_session *session = arg;
+ struct fuzzy_learn_session *session = arg;
event_del (&session->ev);
- (*session->saved) --;
+ (*session->saved)--;
if (*session->saved == 0) {
session->session->state = STATE_REPLY;
}
static void
fuzzy_learn_callback (int fd, short what, void *arg)
{
- struct fuzzy_learn_session *session = arg;
- struct fuzzy_cmd cmd;
- char buf[sizeof ("ERR" CRLF)];
+ struct fuzzy_learn_session *session = arg;
+ struct fuzzy_cmd cmd;
+ char buf[sizeof ("ERR" CRLF)];
if (what == EV_WRITE) {
/* Send command to storage */
}
goto ok;
}
-
+
return;
- err:
- msg_err ("fuzzy_learn_callback: got error in IO with server %s:%d, %d, %s", session->server->name,
- session->server->port, errno, strerror (errno));
- ok:
- close (fd);
- remove_normal_event (session->session->s, fuzzy_learn_fin, session);
+ err:
+ msg_err ("fuzzy_learn_callback: got error in IO with server %s:%d, %d, %s", session->server->name, session->server->port, errno, strerror (errno));
+ ok:
+ close (fd);
+ remove_normal_event (session->session->s, fuzzy_learn_fin, session);
}
-static void
+static void
fuzzy_symbol_callback (struct worker_task *task, void *unused)
{
- struct mime_text_part *part;
- struct fuzzy_client_session *session;
- struct storage_server *selected;
- GList *cur;
- int sock;
+ struct mime_text_part *part;
+ struct fuzzy_client_session *session;
+ struct storage_server *selected;
+ GList *cur;
+ int sock;
cur = task->text_parts;
continue;
}
selected = (struct storage_server *)get_upstream_by_hash (fuzzy_module_ctx->servers, fuzzy_module_ctx->servers_num,
- sizeof (struct storage_server), task->ts.tv_sec,
- DEFAULT_UPSTREAM_ERROR_TIME, DEFAULT_UPSTREAM_DEAD_TIME,
- DEFAULT_UPSTREAM_MAXERRORS,
- part->fuzzy->hash_pipe, sizeof (part->fuzzy->hash_pipe));
+ sizeof (struct storage_server), task->ts.tv_sec,
+ DEFAULT_UPSTREAM_ERROR_TIME, DEFAULT_UPSTREAM_DEAD_TIME, DEFAULT_UPSTREAM_MAXERRORS, part->fuzzy->hash_pipe, sizeof (part->fuzzy->hash_pipe));
if (selected) {
if ((sock = make_udp_socket (&selected->addr, selected->port, FALSE, TRUE)) == -1) {
msg_warn ("fuzzy_symbol_callback: cannot connect to %s, %d, %s", selected->name, errno, strerror (errno));
- }
+ }
else {
session = memory_pool_alloc (task->task_pool, sizeof (struct fuzzy_client_session));
event_set (&session->ev, sock, EV_WRITE, fuzzy_io_callback, session);
session->server = selected;
event_add (&session->ev, &session->tv);
register_async_event (task->s, fuzzy_io_fin, session, FALSE);
- task->save.saved ++;
+ task->save.saved++;
}
}
cur = g_list_next (cur);
}
static void
-fuzzy_process_handler (struct controller_session *session, f_str_t *in)
+fuzzy_process_handler (struct controller_session *session, f_str_t * in)
{
- struct worker_task *task;
- struct fuzzy_learn_session *s;
- struct mime_text_part *part;
- struct storage_server *selected;
- GList *cur;
- int sock, r, cmd = 0, *saved;
- char out_buf[BUFSIZ];
-
+ struct worker_task *task;
+ struct fuzzy_learn_session *s;
+ struct mime_text_part *part;
+ struct storage_server *selected;
+ GList *cur;
+ int sock, r, cmd = 0, *saved;
+ char out_buf[BUFSIZ];
+
if (session->other_data) {
cmd = GPOINTER_TO_SIZE (session->other_data);
}
task = construct_task (session->worker);
session->other_data = task;
session->state = STATE_WAIT;
-
+
task->msg = memory_pool_alloc (task->task_pool, sizeof (f_str_t));
task->msg->begin = in->begin;
task->msg->len = in->len;
continue;
}
selected = (struct storage_server *)get_upstream_by_hash (fuzzy_module_ctx->servers, fuzzy_module_ctx->servers_num,
- sizeof (struct storage_server), task->ts.tv_sec,
- DEFAULT_UPSTREAM_ERROR_TIME, DEFAULT_UPSTREAM_DEAD_TIME,
- DEFAULT_UPSTREAM_MAXERRORS,
- part->fuzzy->hash_pipe, sizeof (part->fuzzy->hash_pipe));
+ sizeof (struct storage_server), task->ts.tv_sec,
+ DEFAULT_UPSTREAM_ERROR_TIME, DEFAULT_UPSTREAM_DEAD_TIME, DEFAULT_UPSTREAM_MAXERRORS, part->fuzzy->hash_pipe, sizeof (part->fuzzy->hash_pipe));
if (selected) {
if ((sock = make_udp_socket (&selected->addr, selected->port, FALSE, TRUE)) == -1) {
msg_warn ("fuzzy_symbol_callback: cannot connect to %s, %d, %s", selected->name, errno, strerror (errno));
rspamd_dispatcher_write (session->dispatcher, out_buf, r, FALSE, FALSE);
free_task (task, FALSE);
return;
- }
+ }
else {
s = memory_pool_alloc (session->session_pool, sizeof (struct fuzzy_learn_session));
event_set (&s->ev, sock, EV_WRITE, fuzzy_learn_callback, s);
s->cmd = cmd;
s->saved = saved;
event_add (&s->ev, &s->tv);
- (*saved) ++;
+ (*saved)++;
register_async_event (session->s, fuzzy_learn_fin, s, FALSE);
}
}
static void
fuzzy_controller_handler (char **args, struct controller_session *session, int cmd)
{
- char *arg, out_buf[BUFSIZ], *err_str;
- uint32_t size;
- int r;
+ char *arg, out_buf[BUFSIZ], *err_str;
+ uint32_t size;
+ int r;
arg = *args;
if (!arg || *arg == '\0') {
fuzzy_controller_handler (args, session, FUZZY_DEL);
}
-static int
+static int
fuzzy_mime_filter (struct worker_task *task)
{
/* XXX: remove this */
#define DEFAULT_STATFILE_PREFIX "./"
struct regexp_module_item {
- struct expression *expr;
- char *symbol;
- long int avg_time;
+ struct expression *expr;
+ char *symbol;
+ long int avg_time;
};
struct autolearn_data {
- char *statfile_name;
- char *symbol;
- float weight;
+ char *statfile_name;
+ char *symbol;
+ float weight;
};
struct regexp_ctx {
- int (*filter)(struct worker_task *task);
- GHashTable *autolearn_symbols;
- char *metric;
- char *statfile_prefix;
+ int (*filter) (struct worker_task * task);
+ GHashTable *autolearn_symbols;
+ char *metric;
+ char *statfile_prefix;
- memory_pool_t *regexp_pool;
+ memory_pool_t *regexp_pool;
};
-static struct regexp_ctx *regexp_module_ctx = NULL;
+static struct regexp_ctx *regexp_module_ctx = NULL;
-static int regexp_common_filter (struct worker_task *task);
-static gboolean rspamd_regexp_match_number (struct worker_task *task, GList *args);
-static gboolean rspamd_raw_header_exists (struct worker_task *task, GList *args);
-static void process_regexp_item (struct worker_task *task, void *user_data);
+static int regexp_common_filter (struct worker_task *task);
+static gboolean rspamd_regexp_match_number (struct worker_task *task, GList * args);
+static gboolean rspamd_raw_header_exists (struct worker_task *task, GList * args);
+static void process_regexp_item (struct worker_task *task, void *user_data);
int
*ctx = (struct module_ctx *)regexp_module_ctx;
register_expression_function ("regexp_match_number", rspamd_regexp_match_number);
register_expression_function ("raw_header_exists", rspamd_raw_header_exists);
-
+
return 0;
}
-static gboolean
-read_regexp_expression (memory_pool_t *pool, struct regexp_module_item *chain, char *symbol, char *line, struct config_file *cfg)
-{
- struct expression *e, *cur;
+static gboolean
+read_regexp_expression (memory_pool_t * pool, struct regexp_module_item *chain, char *symbol, char *line, struct config_file *cfg)
+{
+ struct expression *e, *cur;
e = parse_expression (regexp_module_ctx->regexp_pool, line);
if (e == NULL) {
void
parse_autolearn_param (const char *param, const char *value, struct config_file *cfg)
{
- struct autolearn_data *d;
- char *p;
+ struct autolearn_data *d;
+ char *p;
p = memory_pool_strdup (regexp_module_ctx->regexp_pool, value);
d = memory_pool_alloc (regexp_module_ctx->regexp_pool, sizeof (struct autolearn_data));
int
regexp_module_config (struct config_file *cfg)
{
- GList *cur_opt = NULL;
- struct module_opt *cur;
- struct regexp_module_item *cur_item;
- struct metric *metric;
- char *value;
- int res = TRUE;
- double *w;
+ GList *cur_opt = NULL;
+ struct module_opt *cur;
+ struct regexp_module_item *cur_item;
+ struct metric *metric;
+ char *value;
+ int res = TRUE;
+ double *w;
if ((value = get_module_opt (cfg, "regexp", "metric")) != NULL) {
regexp_module_ctx->metric = memory_pool_strdup (regexp_module_ctx->regexp_pool, value);
else {
regexp_module_ctx->statfile_prefix = DEFAULT_STATFILE_PREFIX;
}
-
+
metric = g_hash_table_lookup (cfg->metrics, regexp_module_ctx->metric);
if (metric == NULL) {
msg_err ("regexp_module_config: cannot find metric definition %s", regexp_module_ctx->metric);
else {
register_symbol (&metric->cache, cur->param, *w, process_regexp_item, cur_item);
}
-
+
cur_opt = g_list_next (cur_opt);
}
-
+
return res;
}
return regexp_module_config (cfg);
}
-static const char *
+static const char *
find_raw_header_pos (const char *headers, const char *headerv)
{
- const char *p = headers;
- gsize headerlen = strlen (headerv);
+ const char *p = headers;
+ gsize headerlen = strlen (headerv);
if (headers == NULL) {
return NULL;
/* Try to find headers only at the begin of line */
if (*p == '\r' || *p == '\n') {
if (*(p + 1) == '\n' && *p == '\r') {
- p ++;
+ p++;
}
if (g_ascii_isspace (*(++p))) {
/* Folding */
}
}
if (*p != '\0') {
- p ++;
+ p++;
}
}
}
struct url_regexp_param {
- struct worker_task *task;
- GRegex *regexp;
- struct rspamd_regexp *re;
- gboolean found;
+ struct worker_task *task;
+ GRegex *regexp;
+ struct rspamd_regexp *re;
+ gboolean found;
};
-static gboolean
+static gboolean
tree_url_callback (gpointer key, gpointer value, void *data)
{
- struct url_regexp_param *param = data;
- struct uri *url = value;
+ struct url_regexp_param *param = data;
+ struct uri *url = value;
if (g_regex_match (param->regexp, struri (url), 0, NULL) == TRUE) {
task_cache_add (param->task, param->re, 1);
return FALSE;
}
-static gsize
+static gsize
process_regexp (struct rspamd_regexp *re, struct worker_task *task)
{
- char *headerv, *c, t;
- struct mime_text_part *part;
- GList *cur, *headerlist;
- GRegex *regexp;
- struct url_regexp_param callback_param;
- int r;
-
+ char *headerv, *c, t;
+ struct mime_text_part *part;
+ GList *cur, *headerlist;
+ GRegex *regexp;
+ struct url_regexp_param callback_param;
+ int r;
+
if (re == NULL) {
msg_info ("process_regexp: invalid regexp passed");
return 0;
}
-
+
if ((r = task_cache_check (task, re)) != -1) {
msg_debug ("process_regexp: regexp /%s/ is found in cache, result: %d", re->regexp_text, r);
return r == 1;
}
switch (re->type) {
- case REGEXP_NONE:
- msg_warn ("process_regexp: bad error detected: /%s/ has invalid regexp type", re->regexp_text);
+ case REGEXP_NONE:
+ msg_warn ("process_regexp: bad error detected: /%s/ has invalid regexp type", re->regexp_text);
+ return 0;
+ case REGEXP_HEADER:
+ if (re->header == NULL) {
+ msg_info ("process_regexp: header regexp without header name: '%s'", re->regexp_text);
+ task_cache_add (task, re, 0);
return 0;
- case REGEXP_HEADER:
- if (re->header == NULL) {
- msg_info ("process_regexp: header regexp without header name: '%s'", re->regexp_text);
- task_cache_add (task, re, 0);
- return 0;
- }
- msg_debug ("process_regexp: checking header regexp: %s = /%s/", re->header, re->regexp_text);
- headerlist = message_get_header (task->task_pool, task->message, re->header);
- if (headerlist == NULL) {
- task_cache_add (task, re, 0);
- return 0;
- }
- else {
- memory_pool_add_destructor (task->task_pool, (pool_destruct_func)g_list_free, headerlist);
- if (re->regexp == NULL) {
- msg_debug ("process_regexp: regexp contains only header and it is found %s", re->header);
- task_cache_add (task, re, 1);
- return 1;
- }
- cur = headerlist;
- while (cur) {
- msg_debug ("process_regexp: found header \"%s\" with value \"%s\"", re->header, (char *)cur->data);
- if (cur->data && g_regex_match (re->regexp, cur->data, 0, NULL) == TRUE) {
- task_cache_add (task, re, 1);
- return 1;
- }
- cur = g_list_next (cur);
- }
- task_cache_add (task, re, 0);
- return 0;
+ }
+ msg_debug ("process_regexp: checking header regexp: %s = /%s/", re->header, re->regexp_text);
+ headerlist = message_get_header (task->task_pool, task->message, re->header);
+ if (headerlist == NULL) {
+ task_cache_add (task, re, 0);
+ return 0;
+ }
+ else {
+ memory_pool_add_destructor (task->task_pool, (pool_destruct_func) g_list_free, headerlist);
+ if (re->regexp == NULL) {
+ msg_debug ("process_regexp: regexp contains only header and it is found %s", re->header);
+ task_cache_add (task, re, 1);
+ return 1;
}
- break;
- case REGEXP_MIME:
- msg_debug ("process_regexp: checking mime regexp: /%s/", re->regexp_text);
- cur = g_list_first (task->text_parts);
+ cur = headerlist;
while (cur) {
- part = (struct mime_text_part *)cur->data;
- /* Skip empty parts */
- if (part->is_empty) {
- cur = g_list_next (cur);
- continue;
- }
- if (part->is_raw) {
- regexp = re->raw_regexp;
- }
- else {
- regexp = re->regexp;
- }
- if (g_regex_match_full (regexp, part->orig->data, part->orig->len, 0, 0, NULL, NULL) == TRUE) {
+ msg_debug ("process_regexp: found header \"%s\" with value \"%s\"", re->header, (char *)cur->data);
+ if (cur->data && g_regex_match (re->regexp, cur->data, 0, NULL) == TRUE) {
task_cache_add (task, re, 1);
return 1;
}
}
task_cache_add (task, re, 0);
return 0;
- case REGEXP_MESSAGE:
- msg_debug ("process_regexp: checking message regexp: /%s/", re->regexp_text);
- if (g_regex_match_full (re->raw_regexp, task->msg->begin, task->msg->len, 0, 0, NULL, NULL) == TRUE) {
+ }
+ break;
+ case REGEXP_MIME:
+ msg_debug ("process_regexp: checking mime regexp: /%s/", re->regexp_text);
+ cur = g_list_first (task->text_parts);
+ while (cur) {
+ part = (struct mime_text_part *)cur->data;
+ /* Skip empty parts */
+ if (part->is_empty) {
+ cur = g_list_next (cur);
+ continue;
+ }
+ if (part->is_raw) {
+ regexp = re->raw_regexp;
+ }
+ else {
+ regexp = re->regexp;
+ }
+ if (g_regex_match_full (regexp, part->orig->data, part->orig->len, 0, 0, NULL, NULL) == TRUE) {
task_cache_add (task, re, 1);
return 1;
}
- task_cache_add (task, re, 0);
- return 0;
- case REGEXP_URL:
- msg_debug ("process_regexp: checking url regexp: /%s/", re->regexp_text);
- cur = g_list_first (task->text_parts);
- while (cur) {
- part = (struct mime_text_part *)cur->data;
- /* Skip empty parts */
- if (part->is_empty) {
- cur = g_list_next (cur);
- continue;
- }
- if (part->is_raw) {
- regexp = re->raw_regexp;
- }
- else {
- regexp = re->regexp;
- }
- callback_param.task = task;
- callback_param.regexp = regexp;
- callback_param.re = re;
- callback_param.found = FALSE;
- if (part->urls) {
- g_tree_foreach (part->urls, tree_url_callback, &callback_param);
- }
- if (part->html_urls && callback_param.found == FALSE) {
- g_tree_foreach (part->html_urls, tree_url_callback, &callback_param);
- }
+ cur = g_list_next (cur);
+ }
+ task_cache_add (task, re, 0);
+ return 0;
+ case REGEXP_MESSAGE:
+ msg_debug ("process_regexp: checking message regexp: /%s/", re->regexp_text);
+ if (g_regex_match_full (re->raw_regexp, task->msg->begin, task->msg->len, 0, 0, NULL, NULL) == TRUE) {
+ task_cache_add (task, re, 1);
+ return 1;
+ }
+ task_cache_add (task, re, 0);
+ return 0;
+ case REGEXP_URL:
+ msg_debug ("process_regexp: checking url regexp: /%s/", re->regexp_text);
+ cur = g_list_first (task->text_parts);
+ while (cur) {
+ part = (struct mime_text_part *)cur->data;
+ /* Skip empty parts */
+ if (part->is_empty) {
cur = g_list_next (cur);
+ continue;
}
- if (callback_param.found == FALSE) {
- task_cache_add (task, re, 0);
+ if (part->is_raw) {
+ regexp = re->raw_regexp;
}
+ else {
+ regexp = re->regexp;
+ }
+ callback_param.task = task;
+ callback_param.regexp = regexp;
+ callback_param.re = re;
+ callback_param.found = FALSE;
+ if (part->urls) {
+ g_tree_foreach (part->urls, tree_url_callback, &callback_param);
+ }
+ if (part->html_urls && callback_param.found == FALSE) {
+ g_tree_foreach (part->html_urls, tree_url_callback, &callback_param);
+ }
+ cur = g_list_next (cur);
+ }
+ if (callback_param.found == FALSE) {
+ task_cache_add (task, re, 0);
+ }
+ return 0;
+ case REGEXP_RAW_HEADER:
+ msg_debug ("process_regexp: checking for raw header: %s with regexp: /%s/", re->header, re->regexp_text);
+ if (task->raw_headers == NULL) {
+ msg_debug ("process_regexp: cannot check for raw header in message, no headers found");
+ task_cache_add (task, re, 0);
+ return 0;
+ }
+ if ((headerv = (char *)find_raw_header_pos (task->raw_headers, re->header)) == NULL) {
+ /* No header was found */
+ task_cache_add (task, re, 0);
return 0;
- case REGEXP_RAW_HEADER:
- msg_debug ("process_regexp: checking for raw header: %s with regexp: /%s/", re->header, re->regexp_text);
- if (task->raw_headers == NULL) {
- msg_debug ("process_regexp: cannot check for raw header in message, no headers found");
- task_cache_add (task, re, 0);
- return 0;
- }
- if ((headerv = (char *)find_raw_header_pos (task->raw_headers, re->header)) == NULL) {
- /* No header was found */
- task_cache_add (task, re, 0);
- return 0;
- }
- /* Now the main problem is to find position of end of raw header */
- c = headerv;
- while (*c) {
- /* We need to handle all types of line end */
- if ((*c == '\r' && *(c + 1) == '\n')) {
- c ++;
- /* Check for folding */
- if (!g_ascii_isspace (*(c + 1))) {
- c ++;
- break;
- }
- }
- else if (*c == '\r' || *c == '\n') {
- if (!g_ascii_isspace (*(c + 1))) {
- c ++;
- break;
- }
+ }
+ /* Now the main problem is to find position of end of raw header */
+ c = headerv;
+ while (*c) {
+ /* We need to handle all types of line end */
+ if ((*c == '\r' && *(c + 1) == '\n')) {
+ c++;
+ /* Check for folding */
+ if (!g_ascii_isspace (*(c + 1))) {
+ c++;
+ break;
}
- c ++;
- }
- /* Temporary null terminate this part of string */
- t = *c;
- *c = '\0';
- msg_debug ("process_regexp: found raw header \"%s\" with value \"%s\"", re->header, headerv);
- if (g_regex_match (re->raw_regexp, headerv, 0, NULL) == TRUE) {
- *c = t;
- task_cache_add (task, re, 1);
- return 1;
}
+ else if (*c == '\r' || *c == '\n') {
+ if (!g_ascii_isspace (*(c + 1))) {
+ c++;
+ break;
+ }
+ }
+ c++;
+ }
+ /* Temporary null terminate this part of string */
+ t = *c;
+ *c = '\0';
+ msg_debug ("process_regexp: found raw header \"%s\" with value \"%s\"", re->header, headerv);
+ if (g_regex_match (re->raw_regexp, headerv, 0, NULL) == TRUE) {
*c = t;
- task_cache_add (task, re, 0);
- return 0;
- default:
- msg_warn ("process_regexp: bad error detected: %p is not a valid regexp object", re);
+ task_cache_add (task, re, 1);
+ return 1;
+ }
+ *c = t;
+ task_cache_add (task, re, 0);
+ return 0;
+ default:
+ msg_warn ("process_regexp: bad error detected: %p is not a valid regexp object", re);
}
/* Not reached */
return 0;
}
-static gboolean
-optimize_regexp_expression (struct expression **e, GQueue *stack, gboolean res)
+static gboolean
+optimize_regexp_expression (struct expression **e, GQueue * stack, gboolean res)
{
- struct expression *it = (*e)->next;
- gboolean ret = FALSE, is_nearest = TRUE;
- int skip_level = 0;
-
+ struct expression *it = (*e)->next;
+ gboolean ret = FALSE, is_nearest = TRUE;
+ int skip_level = 0;
+
/* Skip nearest logical operators from optimization */
if (!it || (it->type == EXPR_OPERATION && it->content.operation != '!')) {
g_queue_push_head (stack, GSIZE_TO_POINTER (res));
continue;
}
else {
- skip_level --;
+ skip_level--;
}
/* Check whether we found corresponding operator for this operand */
if (skip_level <= 0) {
}
else {
is_nearest = FALSE;
- skip_level ++;
+ skip_level++;
}
it = it->next;
}
return ret;
}
-static gboolean
+static gboolean
process_regexp_expression (struct expression *expr, char *symbol, struct worker_task *task)
{
- GQueue *stack;
- gsize cur, op1, op2;
- struct expression *it = expr;
- struct rspamd_regexp *re;
- gboolean try_optimize = TRUE;
-
+ GQueue *stack;
+ gsize cur, op1, op2;
+ struct expression *it = expr;
+ struct rspamd_regexp *re;
+ gboolean try_optimize = TRUE;
+
stack = g_queue_new ();
while (it) {
else {
g_queue_push_head (stack, GSIZE_TO_POINTER (cur));
}
- } else if (it->type == EXPR_FUNCTION) {
- cur = (gsize)call_expression_function ((struct expression_function *)it->content.operand, task);
- msg_debug ("process_regexp_expression: function %s returned %s", ((struct expression_function *)it->content.operand)->name,
- cur ? "true" : "false");
+ }
+ else if (it->type == EXPR_FUNCTION) {
+ cur = (gsize) call_expression_function ((struct expression_function *)it->content.operand, task);
+ msg_debug ("process_regexp_expression: function %s returned %s", ((struct expression_function *)it->content.operand)->name, cur ? "true" : "false");
if (try_optimize) {
try_optimize = optimize_regexp_expression (&it, stack, cur);
}
else {
g_queue_push_head (stack, GSIZE_TO_POINTER (cur));
}
- } else if (it->type == EXPR_REGEXP) {
+ }
+ else if (it->type == EXPR_REGEXP) {
/* Compile regexp if it is not parsed */
if (it->content.operand == NULL) {
it = it->next;
re = parse_regexp (task->cfg->cfg_pool, it->content.operand, task->cfg->raw_mode);
if (re == NULL) {
msg_warn ("process_regexp_expression: cannot parse regexp, skip expression");
- g_queue_free (stack);
+ g_queue_free (stack);
return FALSE;
}
it->content.operand = re;
it->type = EXPR_REGEXP_PARSED;
/* Continue with this regexp once again */
continue;
- } else if (it->type == EXPR_OPERATION) {
+ }
+ else if (it->type == EXPR_OPERATION) {
if (g_queue_is_empty (stack)) {
/* Queue has no operands for operation, exiting */
msg_warn ("process_regexp_expression: regexp expression seems to be invalid: empty stack while reading operation");
}
msg_debug ("process_regexp_expression: got operation %c", it->content.operation);
switch (it->content.operation) {
- case '!':
- op1 = GPOINTER_TO_SIZE (g_queue_pop_head (stack));
- op1 = !op1;
- try_optimize = optimize_regexp_expression (&it, stack, op1);
- break;
- case '&':
- op1 = GPOINTER_TO_SIZE (g_queue_pop_head (stack));
- op2 = GPOINTER_TO_SIZE (g_queue_pop_head (stack));
- try_optimize = optimize_regexp_expression (&it, stack, op1 && op2);
- break;
- case '|':
- op1 = GPOINTER_TO_SIZE (g_queue_pop_head (stack));
- op2 = GPOINTER_TO_SIZE (g_queue_pop_head (stack));
- try_optimize = optimize_regexp_expression (&it, stack, op1 || op2);
- break;
- default:
- it = it->next;
- continue;
+ case '!':
+ op1 = GPOINTER_TO_SIZE (g_queue_pop_head (stack));
+ op1 = !op1;
+ try_optimize = optimize_regexp_expression (&it, stack, op1);
+ break;
+ case '&':
+ op1 = GPOINTER_TO_SIZE (g_queue_pop_head (stack));
+ op2 = GPOINTER_TO_SIZE (g_queue_pop_head (stack));
+ try_optimize = optimize_regexp_expression (&it, stack, op1 && op2);
+ break;
+ case '|':
+ op1 = GPOINTER_TO_SIZE (g_queue_pop_head (stack));
+ op2 = GPOINTER_TO_SIZE (g_queue_pop_head (stack));
+ try_optimize = optimize_regexp_expression (&it, stack, op1 || op2);
+ break;
+ default:
+ it = it->next;
+ continue;
}
}
if (it) {
else {
msg_warn ("process_regexp_expression: regexp expression seems to be invalid: empty stack at the end of expression, symbol %s", symbol);
}
-
+
g_queue_free (stack);
return FALSE;
static void
process_regexp_item (struct worker_task *task, void *user_data)
-{
- struct regexp_module_item *item = user_data;
+{
+ struct regexp_module_item *item = user_data;
if (process_regexp_expression (item->expr, item->symbol, task)) {
insert_result (task, regexp_module_ctx->metric, item->symbol, 1, NULL);
}
}
-static int
+static int
regexp_common_filter (struct worker_task *task)
{
/* XXX: remove this shit too */
- return 0;
+ return 0;
}
-static gboolean
-rspamd_regexp_match_number (struct worker_task *task, GList *args)
+static gboolean
+rspamd_regexp_match_number (struct worker_task *task, GList * args)
{
- int param_count, res = 0;
- struct expression_argument *arg;
- GList *cur;
-
+ int param_count, res = 0;
+ struct expression_argument *arg;
+ GList *cur;
+
if (args == NULL) {
msg_warn ("rspamd_regexp_match_number: no parameters to function");
return FALSE;
}
-
+
arg = get_function_arg (args->data, task, TRUE);
param_count = strtoul (arg->data, NULL, 10);
-
+
cur = args->next;
while (cur) {
arg = get_function_arg (cur->data, task, FALSE);
if (arg && arg->type == EXPRESSION_ARGUMENT_BOOL) {
- if ((gboolean)GPOINTER_TO_SIZE (arg->data)) {
- res ++;
+ if ((gboolean) GPOINTER_TO_SIZE (arg->data)) {
+ res++;
}
}
else {
if (process_regexp_expression (cur->data, "regexp_match_number", task)) {
- res ++;
+ res++;
}
if (res >= param_count) {
return TRUE;
return res >= param_count;
}
-static gboolean
-rspamd_raw_header_exists (struct worker_task *task, GList *args)
+static gboolean
+rspamd_raw_header_exists (struct worker_task *task, GList * args)
{
- struct expression_argument *arg;
+ struct expression_argument *arg;
if (args == NULL || task == NULL) {
return FALSE;
#include "surbl.h"
-static struct surbl_ctx *surbl_module_ctx = NULL;
+static struct surbl_ctx *surbl_module_ctx = NULL;
-static int surbl_filter (struct worker_task *task);
-static void surbl_test_url (struct worker_task *task, void *user_data);
-static void dns_callback (int result, char type, int count, int ttl, void *addresses, void *data);
-static void process_dns_results (struct worker_task *task, struct suffix_item *suffix, char *url, uint32_t addr);
-static int urls_command_handler (struct worker_task *task);
+static int surbl_filter (struct worker_task *task);
+static void surbl_test_url (struct worker_task *task, void *user_data);
+static void dns_callback (int result, char type, int count, int ttl, void *addresses, void *data);
+static void process_dns_results (struct worker_task *task, struct suffix_item *suffix, char *url, uint32_t addr);
+static int urls_command_handler (struct worker_task *task);
#define SURBL_ERROR surbl_error_quark ()
#define WHITELIST_ERROR 0
GQuark
surbl_error_quark (void)
{
- return g_quark_from_static_string ("surbl-error-quark");
+ return g_quark_from_static_string ("surbl-error-quark");
}
int
surbl_module_init (struct config_file *cfg, struct module_ctx **ctx)
{
- GError *err = NULL;
-
- surbl_module_ctx = g_malloc (sizeof (struct surbl_ctx));
-
- surbl_module_ctx->filter = surbl_filter;
- surbl_module_ctx->use_redirector = 0;
- surbl_module_ctx->suffixes = NULL;
- surbl_module_ctx->bits = NULL;
- surbl_module_ctx->surbl_pool = memory_pool_new (memory_pool_get_size ());
-
- surbl_module_ctx->tld2_file = NULL;
- surbl_module_ctx->whitelist_file = NULL;
-
- surbl_module_ctx->tld2 = g_hash_table_new (rspamd_strcase_hash, rspamd_strcase_equal);
- surbl_module_ctx->redirector_hosts = g_hash_table_new (rspamd_strcase_hash, rspamd_strcase_equal);
- surbl_module_ctx->whitelist = g_hash_table_new (rspamd_strcase_hash, rspamd_strcase_equal);
- /* Register destructors */
- memory_pool_add_destructor (surbl_module_ctx->surbl_pool, (pool_destruct_func)g_hash_table_destroy, surbl_module_ctx->tld2);
- memory_pool_add_destructor (surbl_module_ctx->surbl_pool, (pool_destruct_func)g_hash_table_destroy, surbl_module_ctx->whitelist);
- memory_pool_add_destructor (surbl_module_ctx->surbl_pool, (pool_destruct_func)g_hash_table_destroy, surbl_module_ctx->redirector_hosts);
-
- memory_pool_add_destructor (surbl_module_ctx->surbl_pool, (pool_destruct_func)g_list_free, surbl_module_ctx->suffixes);
- memory_pool_add_destructor (surbl_module_ctx->surbl_pool, (pool_destruct_func)g_list_free, surbl_module_ctx->bits);
-
- /* Init matching regexps */
- surbl_module_ctx->extract_hoster_regexp = g_regex_new ("([^.]+)\\.([^.]+)\\.([^.]+)$", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, &err);
- surbl_module_ctx->extract_normal_regexp = g_regex_new ("([^.]+)\\.([^.]+)$", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, &err);
- surbl_module_ctx->extract_ip_regexp = g_regex_new ("(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, &err);
- surbl_module_ctx->extract_numeric_regexp = g_regex_new ("(\\d{5,20})$", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, &err);
-
- *ctx = (struct module_ctx *)surbl_module_ctx;
-
- register_protocol_command ("urls", urls_command_handler);
-
- return 0;
+ GError *err = NULL;
+
+ surbl_module_ctx = g_malloc (sizeof (struct surbl_ctx));
+
+ surbl_module_ctx->filter = surbl_filter;
+ surbl_module_ctx->use_redirector = 0;
+ surbl_module_ctx->suffixes = NULL;
+ surbl_module_ctx->bits = NULL;
+ surbl_module_ctx->surbl_pool = memory_pool_new (memory_pool_get_size ());
+
+ surbl_module_ctx->tld2_file = NULL;
+ surbl_module_ctx->whitelist_file = NULL;
+
+ surbl_module_ctx->tld2 = g_hash_table_new (rspamd_strcase_hash, rspamd_strcase_equal);
+ surbl_module_ctx->redirector_hosts = g_hash_table_new (rspamd_strcase_hash, rspamd_strcase_equal);
+ surbl_module_ctx->whitelist = g_hash_table_new (rspamd_strcase_hash, rspamd_strcase_equal);
+ /* Register destructors */
+ memory_pool_add_destructor (surbl_module_ctx->surbl_pool, (pool_destruct_func) g_hash_table_destroy, surbl_module_ctx->tld2);
+ memory_pool_add_destructor (surbl_module_ctx->surbl_pool, (pool_destruct_func) g_hash_table_destroy, surbl_module_ctx->whitelist);
+ memory_pool_add_destructor (surbl_module_ctx->surbl_pool, (pool_destruct_func) g_hash_table_destroy, surbl_module_ctx->redirector_hosts);
+
+ memory_pool_add_destructor (surbl_module_ctx->surbl_pool, (pool_destruct_func) g_list_free, surbl_module_ctx->suffixes);
+ memory_pool_add_destructor (surbl_module_ctx->surbl_pool, (pool_destruct_func) g_list_free, surbl_module_ctx->bits);
+
+ /* Init matching regexps */
+ surbl_module_ctx->extract_hoster_regexp = g_regex_new ("([^.]+)\\.([^.]+)\\.([^.]+)$", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, &err);
+ surbl_module_ctx->extract_normal_regexp = g_regex_new ("([^.]+)\\.([^.]+)$", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, &err);
+ surbl_module_ctx->extract_ip_regexp = g_regex_new ("(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, &err);
+ surbl_module_ctx->extract_numeric_regexp = g_regex_new ("(\\d{5,20})$", G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, &err);
+
+ *ctx = (struct module_ctx *)surbl_module_ctx;
+
+ register_protocol_command ("urls", urls_command_handler);
+
+ return 0;
}
int
surbl_module_config (struct config_file *cfg)
{
- struct hostent *hent;
- GList *cur_opt;
- struct module_opt *cur;
- struct suffix_item *new_suffix;
- struct surbl_bit_item *new_bit;
- struct metric *metric;
- double *w;
-
- char *value, *cur_tok, *str;
- uint32_t bit;
-
-
- if ((value = get_module_opt (cfg, "surbl", "redirector")) != NULL) {
- str = memory_pool_strdup (surbl_module_ctx->surbl_pool, value);
- cur_tok = strsep (&str, ":");
- if (!inet_aton (cur_tok, &surbl_module_ctx->redirector_addr)) {
- /* Try to call gethostbyname */
- hent = gethostbyname (cur_tok);
- if (hent != NULL) {
- memcpy((char *)&surbl_module_ctx->redirector_addr, hent->h_addr, sizeof(struct in_addr));
- if (str != NULL) {
- surbl_module_ctx->redirector_port = (uint16_t)strtoul (str, NULL, 10);
- }
- else {
- surbl_module_ctx->redirector_port = DEFAULT_REDIRECTOR_PORT;
- }
- surbl_module_ctx->use_redirector = 1;
- }
- }
- }
- if ((value = get_module_opt (cfg, "surbl", "weight")) != NULL) {
- surbl_module_ctx->weight = atoi (value);
- }
- else {
- surbl_module_ctx->weight = DEFAULT_SURBL_WEIGHT;
- }
- if ((value = get_module_opt (cfg, "surbl", "url_expire")) != NULL) {
- surbl_module_ctx->url_expire = atoi (value);
- }
- else {
- surbl_module_ctx->url_expire = DEFAULT_SURBL_URL_EXPIRE;
- }
- if ((value = get_module_opt (cfg, "surbl", "redirector_connect_timeout")) != NULL) {
- surbl_module_ctx->connect_timeout = parse_seconds (value);
- }
- else {
- surbl_module_ctx->connect_timeout = DEFAULT_REDIRECTOR_CONNECT_TIMEOUT;
- }
- if ((value = get_module_opt (cfg, "surbl", "redirector_read_timeout")) != NULL) {
- surbl_module_ctx->read_timeout = parse_seconds (value);
- }
- else {
- surbl_module_ctx->read_timeout = DEFAULT_REDIRECTOR_READ_TIMEOUT;
- }
- if ((value = get_module_opt (cfg, "surbl", "redirector_hosts_map")) != NULL) {
- add_map (value, read_host_list, fin_host_list, (void **)&surbl_module_ctx->redirector_hosts);
- }
- else {
- surbl_module_ctx->read_timeout = DEFAULT_REDIRECTOR_READ_TIMEOUT;
- }
- if ((value = get_module_opt (cfg, "surbl", "max_urls")) != NULL) {
- surbl_module_ctx->max_urls = atoi (value);
- }
- else {
- surbl_module_ctx->max_urls = DEFAULT_SURBL_MAX_URLS;
- }
- if ((value = get_module_opt (cfg, "surbl", "metric")) != NULL) {
- surbl_module_ctx->metric = memory_pool_strdup (surbl_module_ctx->surbl_pool, value);
- }
- else {
- surbl_module_ctx->metric = DEFAULT_METRIC;
- }
- if ((value = get_module_opt (cfg, "surbl", "2tld")) != NULL) {
- if (add_map (value, read_host_list, fin_host_list, (void **)&surbl_module_ctx->tld2)) {
- surbl_module_ctx->tld2_file = memory_pool_strdup (surbl_module_ctx->surbl_pool, value + sizeof ("file://") - 1);
- }
- }
- if ((value = get_module_opt (cfg, "surbl", "whitelist")) != NULL) {
- if (add_map (value, read_host_list, fin_host_list, (void **)&surbl_module_ctx->whitelist)) {
- surbl_module_ctx->whitelist_file = memory_pool_strdup (surbl_module_ctx->surbl_pool, value + sizeof ("file://") - 1);
- }
- }
-
- metric = g_hash_table_lookup (cfg->metrics, surbl_module_ctx->metric);
- if (metric == NULL) {
- msg_err ("surbl_module_config: cannot find metric definition %s", surbl_module_ctx->metric);
- return FALSE;
- }
-
-
- cur_opt = g_hash_table_lookup (cfg->modules_opts, "surbl");
- while (cur_opt) {
- cur = cur_opt->data;
- if (!g_strncasecmp (cur->param, "suffix", sizeof ("suffix") - 1)) {
- if ((str = strchr (cur->param, '_')) != NULL) {
- new_suffix = memory_pool_alloc (surbl_module_ctx->surbl_pool, sizeof (struct suffix_item));
- *str = '\0';
- new_suffix->symbol = memory_pool_strdup (surbl_module_ctx->surbl_pool, str + 1);
- new_suffix->suffix = memory_pool_strdup (surbl_module_ctx->surbl_pool, cur->value);
- msg_debug ("surbl_module_config: add new surbl suffix: %s with symbol: %s",
- new_suffix->suffix, new_suffix->symbol);
- *str = '_';
- surbl_module_ctx->suffixes = g_list_prepend (surbl_module_ctx->suffixes, new_suffix);
- /* Search in factors hash table */
- w = g_hash_table_lookup (cfg->factors, new_suffix->symbol);
- if (w == NULL) {
- register_symbol (&metric->cache, new_suffix->symbol, 1, surbl_test_url, new_suffix);
- }
- else {
- register_symbol (&metric->cache, new_suffix->symbol, *w, surbl_test_url, new_suffix);
- }
- }
- }
- if (!g_strncasecmp (cur->param, "bit", sizeof ("bit") - 1)) {
- if ((str = strchr (cur->param, '_')) != NULL) {
- bit = strtoul (str + 1, NULL, 10);
- if (bit != 0) {
- new_bit = memory_pool_alloc (surbl_module_ctx->surbl_pool, sizeof (struct surbl_bit_item));
- new_bit->bit = bit;
- new_bit->symbol = memory_pool_strdup (surbl_module_ctx->surbl_pool, cur->value);
- msg_debug ("surbl_module_config: add new bit suffix: %d with symbol: %s",
- (int)new_bit->bit, new_bit->symbol);
- surbl_module_ctx->bits = g_list_prepend (surbl_module_ctx->bits, new_bit);
- }
- }
- }
- cur_opt = g_list_next (cur_opt);
- }
- /* Add default suffix */
- if (surbl_module_ctx->suffixes == NULL) {
- new_suffix = memory_pool_alloc (surbl_module_ctx->surbl_pool, sizeof (struct suffix_item));
- new_suffix->suffix = memory_pool_strdup (surbl_module_ctx->surbl_pool, DEFAULT_SURBL_SUFFIX);
- new_suffix->symbol = memory_pool_strdup (surbl_module_ctx->surbl_pool, DEFAULT_SURBL_SYMBOL);
- msg_debug ("surbl_module_config: add default surbl suffix: %s with symbol: %s",
- new_suffix->suffix, new_suffix->symbol);
- surbl_module_ctx->suffixes = g_list_prepend (surbl_module_ctx->suffixes, new_suffix);
- w = g_hash_table_lookup (cfg->factors, new_suffix->symbol);
- if (w == NULL) {
- register_symbol (&metric->cache, new_suffix->symbol, 1, surbl_test_url, new_suffix);
- }
- else {
- register_symbol (&metric->cache, new_suffix->symbol, *w, surbl_test_url, new_suffix);
- }
- }
-
- return TRUE;
+ struct hostent *hent;
+ GList *cur_opt;
+ struct module_opt *cur;
+ struct suffix_item *new_suffix;
+ struct surbl_bit_item *new_bit;
+ struct metric *metric;
+ double *w;
+
+ char *value, *cur_tok, *str;
+ uint32_t bit;
+
+
+ if ((value = get_module_opt (cfg, "surbl", "redirector")) != NULL) {
+ str = memory_pool_strdup (surbl_module_ctx->surbl_pool, value);
+ cur_tok = strsep (&str, ":");
+ if (!inet_aton (cur_tok, &surbl_module_ctx->redirector_addr)) {
+ /* Try to call gethostbyname */
+ hent = gethostbyname (cur_tok);
+ if (hent != NULL) {
+ memcpy ((char *)&surbl_module_ctx->redirector_addr, hent->h_addr, sizeof (struct in_addr));
+ if (str != NULL) {
+ surbl_module_ctx->redirector_port = (uint16_t) strtoul (str, NULL, 10);
+ }
+ else {
+ surbl_module_ctx->redirector_port = DEFAULT_REDIRECTOR_PORT;
+ }
+ surbl_module_ctx->use_redirector = 1;
+ }
+ }
+ }
+ if ((value = get_module_opt (cfg, "surbl", "weight")) != NULL) {
+ surbl_module_ctx->weight = atoi (value);
+ }
+ else {
+ surbl_module_ctx->weight = DEFAULT_SURBL_WEIGHT;
+ }
+ if ((value = get_module_opt (cfg, "surbl", "url_expire")) != NULL) {
+ surbl_module_ctx->url_expire = atoi (value);
+ }
+ else {
+ surbl_module_ctx->url_expire = DEFAULT_SURBL_URL_EXPIRE;
+ }
+ if ((value = get_module_opt (cfg, "surbl", "redirector_connect_timeout")) != NULL) {
+ surbl_module_ctx->connect_timeout = parse_seconds (value);
+ }
+ else {
+ surbl_module_ctx->connect_timeout = DEFAULT_REDIRECTOR_CONNECT_TIMEOUT;
+ }
+ if ((value = get_module_opt (cfg, "surbl", "redirector_read_timeout")) != NULL) {
+ surbl_module_ctx->read_timeout = parse_seconds (value);
+ }
+ else {
+ surbl_module_ctx->read_timeout = DEFAULT_REDIRECTOR_READ_TIMEOUT;
+ }
+ if ((value = get_module_opt (cfg, "surbl", "redirector_hosts_map")) != NULL) {
+ add_map (value, read_host_list, fin_host_list, (void **)&surbl_module_ctx->redirector_hosts);
+ }
+ else {
+ surbl_module_ctx->read_timeout = DEFAULT_REDIRECTOR_READ_TIMEOUT;
+ }
+ if ((value = get_module_opt (cfg, "surbl", "max_urls")) != NULL) {
+ surbl_module_ctx->max_urls = atoi (value);
+ }
+ else {
+ surbl_module_ctx->max_urls = DEFAULT_SURBL_MAX_URLS;
+ }
+ if ((value = get_module_opt (cfg, "surbl", "metric")) != NULL) {
+ surbl_module_ctx->metric = memory_pool_strdup (surbl_module_ctx->surbl_pool, value);
+ }
+ else {
+ surbl_module_ctx->metric = DEFAULT_METRIC;
+ }
+ if ((value = get_module_opt (cfg, "surbl", "2tld")) != NULL) {
+ if (add_map (value, read_host_list, fin_host_list, (void **)&surbl_module_ctx->tld2)) {
+ surbl_module_ctx->tld2_file = memory_pool_strdup (surbl_module_ctx->surbl_pool, value + sizeof ("file://") - 1);
+ }
+ }
+ if ((value = get_module_opt (cfg, "surbl", "whitelist")) != NULL) {
+ if (add_map (value, read_host_list, fin_host_list, (void **)&surbl_module_ctx->whitelist)) {
+ surbl_module_ctx->whitelist_file = memory_pool_strdup (surbl_module_ctx->surbl_pool, value + sizeof ("file://") - 1);
+ }
+ }
+
+ metric = g_hash_table_lookup (cfg->metrics, surbl_module_ctx->metric);
+ if (metric == NULL) {
+ msg_err ("surbl_module_config: cannot find metric definition %s", surbl_module_ctx->metric);
+ return FALSE;
+ }
+
+
+ cur_opt = g_hash_table_lookup (cfg->modules_opts, "surbl");
+ while (cur_opt) {
+ cur = cur_opt->data;
+ if (!g_strncasecmp (cur->param, "suffix", sizeof ("suffix") - 1)) {
+ if ((str = strchr (cur->param, '_')) != NULL) {
+ new_suffix = memory_pool_alloc (surbl_module_ctx->surbl_pool, sizeof (struct suffix_item));
+ *str = '\0';
+ new_suffix->symbol = memory_pool_strdup (surbl_module_ctx->surbl_pool, str + 1);
+ new_suffix->suffix = memory_pool_strdup (surbl_module_ctx->surbl_pool, cur->value);
+ msg_debug ("surbl_module_config: add new surbl suffix: %s with symbol: %s", new_suffix->suffix, new_suffix->symbol);
+ *str = '_';
+ surbl_module_ctx->suffixes = g_list_prepend (surbl_module_ctx->suffixes, new_suffix);
+ /* Search in factors hash table */
+ w = g_hash_table_lookup (cfg->factors, new_suffix->symbol);
+ if (w == NULL) {
+ register_symbol (&metric->cache, new_suffix->symbol, 1, surbl_test_url, new_suffix);
+ }
+ else {
+ register_symbol (&metric->cache, new_suffix->symbol, *w, surbl_test_url, new_suffix);
+ }
+ }
+ }
+ if (!g_strncasecmp (cur->param, "bit", sizeof ("bit") - 1)) {
+ if ((str = strchr (cur->param, '_')) != NULL) {
+ bit = strtoul (str + 1, NULL, 10);
+ if (bit != 0) {
+ new_bit = memory_pool_alloc (surbl_module_ctx->surbl_pool, sizeof (struct surbl_bit_item));
+ new_bit->bit = bit;
+ new_bit->symbol = memory_pool_strdup (surbl_module_ctx->surbl_pool, cur->value);
+ msg_debug ("surbl_module_config: add new bit suffix: %d with symbol: %s", (int)new_bit->bit, new_bit->symbol);
+ surbl_module_ctx->bits = g_list_prepend (surbl_module_ctx->bits, new_bit);
+ }
+ }
+ }
+ cur_opt = g_list_next (cur_opt);
+ }
+ /* Add default suffix */
+ if (surbl_module_ctx->suffixes == NULL) {
+ new_suffix = memory_pool_alloc (surbl_module_ctx->surbl_pool, sizeof (struct suffix_item));
+ new_suffix->suffix = memory_pool_strdup (surbl_module_ctx->surbl_pool, DEFAULT_SURBL_SUFFIX);
+ new_suffix->symbol = memory_pool_strdup (surbl_module_ctx->surbl_pool, DEFAULT_SURBL_SYMBOL);
+ msg_debug ("surbl_module_config: add default surbl suffix: %s with symbol: %s", new_suffix->suffix, new_suffix->symbol);
+ surbl_module_ctx->suffixes = g_list_prepend (surbl_module_ctx->suffixes, new_suffix);
+ w = g_hash_table_lookup (cfg->factors, new_suffix->symbol);
+ if (w == NULL) {
+ register_symbol (&metric->cache, new_suffix->symbol, 1, surbl_test_url, new_suffix);
+ }
+ else {
+ register_symbol (&metric->cache, new_suffix->symbol, *w, surbl_test_url, new_suffix);
+ }
+ }
+
+ return TRUE;
}
int
surbl_module_reconfig (struct config_file *cfg)
{
- memory_pool_delete (surbl_module_ctx->surbl_pool);
- surbl_module_ctx->surbl_pool = memory_pool_new (1024);
+ memory_pool_delete (surbl_module_ctx->surbl_pool);
+ surbl_module_ctx->surbl_pool = memory_pool_new (1024);
- return surbl_module_config (cfg);
+ return surbl_module_config (cfg);
}
-static char *
-format_surbl_request (memory_pool_t *pool, f_str_t *hostname, struct suffix_item *suffix, char **host_end, gboolean append_suffix, GError **err)
+static char *
+format_surbl_request (memory_pool_t * pool, f_str_t * hostname, struct suffix_item *suffix, char **host_end, gboolean append_suffix, GError ** err)
{
- GMatchInfo *info;
- char *result = NULL;
- int len, slen, r;
-
- if (suffix != NULL) {
- slen = strlen (suffix->suffix);
- }
- else if (!append_suffix) {
- slen = 0;
- }
- else {
- g_assert_not_reached ();
- }
- len = hostname->len + slen + 2;
-
- /* First try to match numeric expression */
- if (g_ascii_isdigit (*hostname->begin)) {
- if (g_regex_match_full (surbl_module_ctx->extract_ip_regexp, hostname->begin, hostname->len, 0, 0, &info, NULL) == TRUE) {
- gchar *octet1, *octet2, *octet3, *octet4;
- octet1 = g_match_info_fetch (info, 1);
- octet2 = g_match_info_fetch (info, 2);
- octet3 = g_match_info_fetch (info, 3);
- octet4 = g_match_info_fetch (info, 4);
- result = memory_pool_alloc (pool, len);
- msg_debug ("format_surbl_request: got numeric host for check: %s.%s.%s.%s", octet1, octet2, octet3, octet4);
- r = snprintf (result, len, "%s.%s.%s.%s", octet4, octet3, octet2, octet1);
- if (g_hash_table_lookup (surbl_module_ctx->whitelist, result) != NULL) {
- g_free (octet1);
- g_free (octet2);
- g_free (octet3);
- g_free (octet4);
- g_match_info_free (info);
- msg_debug ("format_surbl_request: url %s is whitelisted", result);
- g_set_error (err,
- SURBL_ERROR, /* error domain */
- WHITELIST_ERROR, /* error code */
- "URL is whitelisted: %s", /* error message format string */
- result);
-
- return NULL;
- }
- if (append_suffix) {
- r += snprintf (result + r, len - r, ".%s", suffix->suffix);
- }
- *host_end = result + r - slen - 1;
- g_free (octet1);
- g_free (octet2);
- g_free (octet3);
- g_free (octet4);
- g_match_info_free (info);
- return result;
- }
- g_match_info_free (info);
- if (g_regex_match_full (surbl_module_ctx->extract_numeric_regexp, hostname->begin, hostname->len, 0, 0, &info, NULL) == TRUE) {
- gchar *ip = g_match_info_fetch (info, 1);
- uint64_t ip_num;
-
- errno = 0;
- ip_num = strtoull (ip, NULL, 10);
- if (errno != 0) {
- g_match_info_free (info);
- msg_info ("format_surbl_request: cannot convert ip to number '%s': %s", ip, strerror (errno));
- g_set_error (err,
- SURBL_ERROR, /* error domain */
- CONVERSION_ERROR, /* error code */
- "URL cannot be decoded");
- g_free (ip);
-
- return NULL;
- }
-
- len = sizeof ("255.255.255.255") + slen;
- result = memory_pool_alloc (pool, len);
- /* Hack for bugged windows resolver */
- ip_num &= 0xFFFFFFFF;
- /* Get octets */
- r = snprintf (result, len, "%u.%u.%u.%u",
- (uint32_t)ip_num & 0x000000FF,
- (uint32_t)(ip_num & 0x0000FF00) >> 8,
- (uint32_t)(ip_num & 0x00FF0000) >> 16,
- (uint32_t)(ip_num & 0xFF000000) >> 24);
- if (append_suffix) {
- r += snprintf (result + r, len - r, ".%s", suffix->suffix);
- }
- *host_end = result + r - slen - 1;
- g_free (ip);
- g_match_info_free (info);
- return result;
- }
- g_match_info_free (info);
- }
- /* Try to match normal domain */
- if (g_regex_match_full (surbl_module_ctx->extract_normal_regexp, hostname->begin, hostname->len, 0, 0, &info, NULL) == TRUE) {
- gchar *part1, *part2;
- part1 = g_match_info_fetch (info, 1);
- part2 = g_match_info_fetch (info, 2);
- g_match_info_free (info);
- result = memory_pool_alloc (pool, len);
- r = snprintf (result, len, "%s.%s", part1, part2);
- if (g_hash_table_lookup (surbl_module_ctx->tld2, result) != NULL) {
- /* Match additional part for hosters */
- g_free (part1);
- g_free (part2);
- if (g_regex_match_full (surbl_module_ctx->extract_hoster_regexp, hostname->begin, hostname->len, 0, 0, &info, NULL) == TRUE) {
- gchar *hpart1, *hpart2, *hpart3;
- hpart1 = g_match_info_fetch (info, 1);
- hpart2 = g_match_info_fetch (info, 2);
- hpart3 = g_match_info_fetch (info, 3);
- msg_debug ("format_surbl_request: got hoster 3-d level domain %s.%s.%s", hpart1, hpart2, hpart3);
- r = snprintf (result, len, "%s.%s.%s", hpart1, hpart2, hpart3);
- if (g_hash_table_lookup (surbl_module_ctx->whitelist, result) != NULL) {
- g_free (hpart1);
- g_free (hpart2);
- g_free (hpart3);
- g_match_info_free (info);
- msg_debug ("format_surbl_request: url %s is whitelisted", result);
- g_set_error (err,
- SURBL_ERROR, /* error domain */
- WHITELIST_ERROR, /* error code */
- "URL is whitelisted: %s", /* error message format string */
- result);
- return NULL;
- }
- if (append_suffix) {
- r += snprintf (result + r, len - r, ".%s", suffix->suffix);
- }
- *host_end = result + r - slen - 1;
- g_free (hpart1);
- g_free (hpart2);
- g_free (hpart3);
- g_match_info_free (info);
- return result;
- }
- g_match_info_free (info);
- *host_end = NULL;
- return NULL;
- }
- else {
- if (g_hash_table_lookup (surbl_module_ctx->whitelist, result) != NULL) {
- g_free (part1);
- g_free (part2);
- msg_debug ("format_surbl_request: url %s is whitelisted", result);
- g_set_error (err,
- SURBL_ERROR, /* error domain */
- WHITELIST_ERROR, /* error code */
- "URL is whitelisted: %s", /* error message format string */
- result);
- return NULL;
- }
- if (append_suffix) {
- r += snprintf (result + r, len - r, ".%s", suffix->suffix);
- }
- *host_end = result + r - slen - 1;
- msg_debug ("format_surbl_request: got normal 2-d level domain %s.%s", part1, part2);
- }
- g_free (part1);
- g_free (part2);
- return result;
- }
-
- g_match_info_free (info);
- *host_end = NULL;
- return NULL;
+ GMatchInfo *info;
+ char *result = NULL;
+ int len, slen, r;
+
+ if (suffix != NULL) {
+ slen = strlen (suffix->suffix);
+ }
+ else if (!append_suffix) {
+ slen = 0;
+ }
+ else {
+ g_assert_not_reached ();
+ }
+ len = hostname->len + slen + 2;
+
+ /* First try to match numeric expression */
+ if (g_ascii_isdigit (*hostname->begin)) {
+ if (g_regex_match_full (surbl_module_ctx->extract_ip_regexp, hostname->begin, hostname->len, 0, 0, &info, NULL) == TRUE) {
+ gchar *octet1, *octet2, *octet3, *octet4;
+ octet1 = g_match_info_fetch (info, 1);
+ octet2 = g_match_info_fetch (info, 2);
+ octet3 = g_match_info_fetch (info, 3);
+ octet4 = g_match_info_fetch (info, 4);
+ result = memory_pool_alloc (pool, len);
+ msg_debug ("format_surbl_request: got numeric host for check: %s.%s.%s.%s", octet1, octet2, octet3, octet4);
+ r = snprintf (result, len, "%s.%s.%s.%s", octet4, octet3, octet2, octet1);
+ if (g_hash_table_lookup (surbl_module_ctx->whitelist, result) != NULL) {
+ g_free (octet1);
+ g_free (octet2);
+ g_free (octet3);
+ g_free (octet4);
+ g_match_info_free (info);
+ msg_debug ("format_surbl_request: url %s is whitelisted", result);
+ g_set_error (err, SURBL_ERROR, /* error domain */
+ WHITELIST_ERROR, /* error code */
+ "URL is whitelisted: %s", /* error message format string */
+ result);
+
+ return NULL;
+ }
+ if (append_suffix) {
+ r += snprintf (result + r, len - r, ".%s", suffix->suffix);
+ }
+ *host_end = result + r - slen - 1;
+ g_free (octet1);
+ g_free (octet2);
+ g_free (octet3);
+ g_free (octet4);
+ g_match_info_free (info);
+ return result;
+ }
+ g_match_info_free (info);
+ if (g_regex_match_full (surbl_module_ctx->extract_numeric_regexp, hostname->begin, hostname->len, 0, 0, &info, NULL) == TRUE) {
+ gchar *ip = g_match_info_fetch (info, 1);
+ uint64_t ip_num;
+
+ errno = 0;
+ ip_num = strtoull (ip, NULL, 10);
+ if (errno != 0) {
+ g_match_info_free (info);
+ msg_info ("format_surbl_request: cannot convert ip to number '%s': %s", ip, strerror (errno));
+ g_set_error (err, SURBL_ERROR, /* error domain */
+ CONVERSION_ERROR, /* error code */
+ "URL cannot be decoded");
+ g_free (ip);
+
+ return NULL;
+ }
+
+ len = sizeof ("255.255.255.255") + slen;
+ result = memory_pool_alloc (pool, len);
+ /* Hack for bugged windows resolver */
+ ip_num &= 0xFFFFFFFF;
+ /* Get octets */
+ r = snprintf (result, len, "%u.%u.%u.%u",
+ (uint32_t) ip_num & 0x000000FF, (uint32_t) (ip_num & 0x0000FF00) >> 8, (uint32_t) (ip_num & 0x00FF0000) >> 16, (uint32_t) (ip_num & 0xFF000000) >> 24);
+ if (append_suffix) {
+ r += snprintf (result + r, len - r, ".%s", suffix->suffix);
+ }
+ *host_end = result + r - slen - 1;
+ g_free (ip);
+ g_match_info_free (info);
+ return result;
+ }
+ g_match_info_free (info);
+ }
+ /* Try to match normal domain */
+ if (g_regex_match_full (surbl_module_ctx->extract_normal_regexp, hostname->begin, hostname->len, 0, 0, &info, NULL) == TRUE) {
+ gchar *part1, *part2;
+ part1 = g_match_info_fetch (info, 1);
+ part2 = g_match_info_fetch (info, 2);
+ g_match_info_free (info);
+ result = memory_pool_alloc (pool, len);
+ r = snprintf (result, len, "%s.%s", part1, part2);
+ if (g_hash_table_lookup (surbl_module_ctx->tld2, result) != NULL) {
+ /* Match additional part for hosters */
+ g_free (part1);
+ g_free (part2);
+ if (g_regex_match_full (surbl_module_ctx->extract_hoster_regexp, hostname->begin, hostname->len, 0, 0, &info, NULL) == TRUE) {
+ gchar *hpart1, *hpart2, *hpart3;
+ hpart1 = g_match_info_fetch (info, 1);
+ hpart2 = g_match_info_fetch (info, 2);
+ hpart3 = g_match_info_fetch (info, 3);
+ msg_debug ("format_surbl_request: got hoster 3-d level domain %s.%s.%s", hpart1, hpart2, hpart3);
+ r = snprintf (result, len, "%s.%s.%s", hpart1, hpart2, hpart3);
+ if (g_hash_table_lookup (surbl_module_ctx->whitelist, result) != NULL) {
+ g_free (hpart1);
+ g_free (hpart2);
+ g_free (hpart3);
+ g_match_info_free (info);
+ msg_debug ("format_surbl_request: url %s is whitelisted", result);
+ g_set_error (err, SURBL_ERROR, /* error domain */
+ WHITELIST_ERROR, /* error code */
+ "URL is whitelisted: %s", /* error message format string */
+ result);
+ return NULL;
+ }
+ if (append_suffix) {
+ r += snprintf (result + r, len - r, ".%s", suffix->suffix);
+ }
+ *host_end = result + r - slen - 1;
+ g_free (hpart1);
+ g_free (hpart2);
+ g_free (hpart3);
+ g_match_info_free (info);
+ return result;
+ }
+ g_match_info_free (info);
+ *host_end = NULL;
+ return NULL;
+ }
+ else {
+ if (g_hash_table_lookup (surbl_module_ctx->whitelist, result) != NULL) {
+ g_free (part1);
+ g_free (part2);
+ msg_debug ("format_surbl_request: url %s is whitelisted", result);
+ g_set_error (err, SURBL_ERROR, /* error domain */
+ WHITELIST_ERROR, /* error code */
+ "URL is whitelisted: %s", /* error message format string */
+ result);
+ return NULL;
+ }
+ if (append_suffix) {
+ r += snprintf (result + r, len - r, ".%s", suffix->suffix);
+ }
+ *host_end = result + r - slen - 1;
+ msg_debug ("format_surbl_request: got normal 2-d level domain %s.%s", part1, part2);
+ }
+ g_free (part1);
+ g_free (part2);
+ return result;
+ }
+
+ g_match_info_free (info);
+ *host_end = NULL;
+ return NULL;
}
-static void
-make_surbl_requests (struct uri* url, struct worker_task *task, GTree *tree, struct suffix_item *suffix)
-{
- char *surbl_req;
- f_str_t f;
- GError *err = NULL;
- struct dns_param *param;
- char *host_end;
-
- f.begin = url->host;
- f.len = url->hostlen;
-
- if (check_view (task->cfg->views, suffix->symbol, task)) {
- if ((surbl_req = format_surbl_request (task->task_pool, &f, suffix, &host_end, TRUE, &err)) != NULL) {
- if (g_tree_lookup (tree, surbl_req) == NULL) {
- g_tree_insert (tree, surbl_req, surbl_req);
- param = memory_pool_alloc (task->task_pool, sizeof (struct dns_param));
- param->url = url;
- param->task = task;
- param->suffix = suffix;
- *host_end = '\0';
- param->host_resolve = memory_pool_strdup (task->task_pool, surbl_req);
- *host_end = '.';
- msg_debug ("surbl_test_url: send surbl dns request %s", surbl_req);
- if (evdns_resolve_ipv4 (surbl_req, DNS_QUERY_NO_SEARCH, dns_callback, (void *)param) == 0) {
- param->task->save.saved ++;
- register_async_event (task->s, (event_finalizer_t)dns_callback, NULL, TRUE);
- }
- }
- else {
- msg_debug ("make_surbl_requests: request %s is already sent", surbl_req);
- }
- }
- else if (err != NULL && err->code != WHITELIST_ERROR) {
- msg_info ("surbl_test_url: cannot format url string for surbl %s, %s", struri (url), err->message);
- g_error_free (err);
- return;
- }
- else if (err != NULL) {
- g_error_free (err);
- }
- }
- else {
- msg_debug ("make_surbl_requests: skipping symbol that is not in view: %s", suffix->symbol);
- }
+static void
+make_surbl_requests (struct uri *url, struct worker_task *task, GTree * tree, struct suffix_item *suffix)
+{
+ char *surbl_req;
+ f_str_t f;
+ GError *err = NULL;
+ struct dns_param *param;
+ char *host_end;
+
+ f.begin = url->host;
+ f.len = url->hostlen;
+
+ if (check_view (task->cfg->views, suffix->symbol, task)) {
+ if ((surbl_req = format_surbl_request (task->task_pool, &f, suffix, &host_end, TRUE, &err)) != NULL) {
+ if (g_tree_lookup (tree, surbl_req) == NULL) {
+ g_tree_insert (tree, surbl_req, surbl_req);
+ param = memory_pool_alloc (task->task_pool, sizeof (struct dns_param));
+ param->url = url;
+ param->task = task;
+ param->suffix = suffix;
+ *host_end = '\0';
+ param->host_resolve = memory_pool_strdup (task->task_pool, surbl_req);
+ *host_end = '.';
+ msg_debug ("surbl_test_url: send surbl dns request %s", surbl_req);
+ if (evdns_resolve_ipv4 (surbl_req, DNS_QUERY_NO_SEARCH, dns_callback, (void *)param) == 0) {
+ param->task->save.saved++;
+ register_async_event (task->s, (event_finalizer_t) dns_callback, NULL, TRUE);
+ }
+ }
+ else {
+ msg_debug ("make_surbl_requests: request %s is already sent", surbl_req);
+ }
+ }
+ else if (err != NULL && err->code != WHITELIST_ERROR) {
+ msg_info ("surbl_test_url: cannot format url string for surbl %s, %s", struri (url), err->message);
+ g_error_free (err);
+ return;
+ }
+ else if (err != NULL) {
+ g_error_free (err);
+ }
+ }
+ else {
+ msg_debug ("make_surbl_requests: skipping symbol that is not in view: %s", suffix->symbol);
+ }
}
static void
process_dns_results (struct worker_task *task, struct suffix_item *suffix, char *url, uint32_t addr)
{
- char *c, *symbol;
- GList *cur;
- struct surbl_bit_item *bit;
- int len, found = 0;
-
- if ((c = strchr (suffix->symbol, '%')) != NULL && *(c + 1) == 'b') {
- cur = g_list_first (surbl_module_ctx->bits);
-
- while (cur) {
- bit = (struct surbl_bit_item *)cur->data;
- msg_debug ("process_dns_results: got result(%d) AND bit(%d): %d", (int)addr, (int)ntohl(bit->bit),
- (int)bit->bit & (int)ntohl (addr));
- if (((int)bit->bit & (int)ntohl (addr)) != 0) {
- len = strlen (suffix->symbol) - 2 + strlen (bit->symbol) + 1;
- *c = '\0';
- symbol = memory_pool_alloc (task->task_pool, len);
- snprintf (symbol, len, "%s%s%s", suffix->symbol, bit->symbol, c + 2);
- *c = '%';
- insert_result (task, surbl_module_ctx->metric, symbol, 1,
- g_list_prepend (NULL, memory_pool_strdup (task->task_pool, url)));
- found = 1;
- }
- cur = g_list_next (cur);
- }
-
- if (!found) {
- insert_result (task, surbl_module_ctx->metric, suffix->symbol, 1,
- g_list_prepend (NULL, memory_pool_strdup (task->task_pool, url)));
- }
- }
- else {
- insert_result (task, surbl_module_ctx->metric, suffix->symbol, 1,
- g_list_prepend (NULL, memory_pool_strdup (task->task_pool, url)));
- }
+ char *c, *symbol;
+ GList *cur;
+ struct surbl_bit_item *bit;
+ int len, found = 0;
+
+ if ((c = strchr (suffix->symbol, '%')) != NULL && *(c + 1) == 'b') {
+ cur = g_list_first (surbl_module_ctx->bits);
+
+ while (cur) {
+ bit = (struct surbl_bit_item *)cur->data;
+ msg_debug ("process_dns_results: got result(%d) AND bit(%d): %d", (int)addr, (int)ntohl (bit->bit), (int)bit->bit & (int)ntohl (addr));
+ if (((int)bit->bit & (int)ntohl (addr)) != 0) {
+ len = strlen (suffix->symbol) - 2 + strlen (bit->symbol) + 1;
+ *c = '\0';
+ symbol = memory_pool_alloc (task->task_pool, len);
+ snprintf (symbol, len, "%s%s%s", suffix->symbol, bit->symbol, c + 2);
+ *c = '%';
+ insert_result (task, surbl_module_ctx->metric, symbol, 1, g_list_prepend (NULL, memory_pool_strdup (task->task_pool, url)));
+ found = 1;
+ }
+ cur = g_list_next (cur);
+ }
+
+ if (!found) {
+ insert_result (task, surbl_module_ctx->metric, suffix->symbol, 1, g_list_prepend (NULL, memory_pool_strdup (task->task_pool, url)));
+ }
+ }
+ else {
+ insert_result (task, surbl_module_ctx->metric, suffix->symbol, 1, g_list_prepend (NULL, memory_pool_strdup (task->task_pool, url)));
+ }
}
-static void
+static void
dns_callback (int result, char type, int count, int ttl, void *addresses, void *data)
{
- struct dns_param *param = (struct dns_param *)data;
-
- msg_debug ("dns_callback: in surbl request callback");
- /* If we have result from DNS server, this url exists in SURBL, so increase score */
- if (result == DNS_ERR_NONE && type == DNS_IPv4_A) {
- msg_info ("surbl_check: <%s> domain [%s] is in surbl %s",
- param->task->message_id, param->host_resolve, param->suffix->suffix);
- process_dns_results (param->task, param->suffix, param->host_resolve, (uint32_t)(((in_addr_t *)addresses)[0]));
- }
- else {
- msg_debug ("surbl_check: <%s> domain [%s] is not in surbl %s",
- param->task->message_id, param->host_resolve, param->suffix->suffix);
- }
-
- param->task->save.saved --;
- if (param->task->save.saved == 0) {
- /* Call other filters */
- param->task->save.saved = 1;
- process_filters (param->task);
- }
- remove_forced_event (param->task->s, (event_finalizer_t)dns_callback);
+ struct dns_param *param = (struct dns_param *)data;
+
+ msg_debug ("dns_callback: in surbl request callback");
+ /* If we have result from DNS server, this url exists in SURBL, so increase score */
+ if (result == DNS_ERR_NONE && type == DNS_IPv4_A) {
+ msg_info ("surbl_check: <%s> domain [%s] is in surbl %s", param->task->message_id, param->host_resolve, param->suffix->suffix);
+ process_dns_results (param->task, param->suffix, param->host_resolve, (uint32_t) (((in_addr_t *) addresses)[0]));
+ }
+ else {
+ msg_debug ("surbl_check: <%s> domain [%s] is not in surbl %s", param->task->message_id, param->host_resolve, param->suffix->suffix);
+ }
+
+ param->task->save.saved--;
+ if (param->task->save.saved == 0) {
+ /* Call other filters */
+ param->task->save.saved = 1;
+ process_filters (param->task);
+ }
+ remove_forced_event (param->task->s, (event_finalizer_t) dns_callback);
}
-static void
-memcached_callback (memcached_ctx_t *ctx, memc_error_t error, void *data)
+static void
+memcached_callback (memcached_ctx_t * ctx, memc_error_t error, void *data)
{
- struct memcached_param *param = (struct memcached_param *)data;
- int *url_count;
-
- switch (ctx->op) {
- case CMD_CONNECT:
- if (error != OK) {
- msg_info ("memcached_callback: memcached returned error %s on CONNECT stage", memc_strerror (error));
- memc_close_ctx (param->ctx);
- param->task->save.saved --;
- if (param->task->save.saved == 0) {
- /* Call other filters */
- param->task->save.saved = 1;
- process_filters (param->task);
- }
- }
- else {
- memc_get (param->ctx, param->ctx->param);
- }
- break;
- case CMD_READ:
- if (error != OK) {
- msg_info ("memcached_callback: memcached returned error %s on READ stage", memc_strerror (error));
- memc_close_ctx (param->ctx);
- param->task->save.saved --;
- if (param->task->save.saved == 0) {
- /* Call other filters */
- param->task->save.saved = 1;
- process_filters (param->task);
- }
- }
- else {
- url_count = (int *)param->ctx->param->buf;
- /* Do not check DNS for urls that have count more than max_urls */
- if (*url_count > surbl_module_ctx->max_urls) {
- msg_info ("memcached_callback: url '%s' has count %d, max: %d", struri (param->url), *url_count, surbl_module_ctx->max_urls);
- /*
- * XXX: try to understand why we should use memcached here
- * insert_result (param->task, surbl_module_ctx->metric, surbl_module_ctx->symbol, 1);
- */
- }
- (*url_count) ++;
- memc_set (param->ctx, param->ctx->param, surbl_module_ctx->url_expire);
- }
- break;
- case CMD_WRITE:
- if (error != OK) {
- msg_info ("memcached_callback: memcached returned error %s on WRITE stage", memc_strerror (error));
- }
- memc_close_ctx (param->ctx);
- param->task->save.saved --;
- if (param->task->save.saved == 0) {
- /* Call other filters */
- param->task->save.saved = 1;
- process_filters (param->task);
- }
- make_surbl_requests (param->url, param->task, param->tree, param->suffix);
- break;
- default:
- return;
- }
+ struct memcached_param *param = (struct memcached_param *)data;
+ int *url_count;
+
+ switch (ctx->op) {
+ case CMD_CONNECT:
+ if (error != OK) {
+ msg_info ("memcached_callback: memcached returned error %s on CONNECT stage", memc_strerror (error));
+ memc_close_ctx (param->ctx);
+ param->task->save.saved--;
+ if (param->task->save.saved == 0) {
+ /* Call other filters */
+ param->task->save.saved = 1;
+ process_filters (param->task);
+ }
+ }
+ else {
+ memc_get (param->ctx, param->ctx->param);
+ }
+ break;
+ case CMD_READ:
+ if (error != OK) {
+ msg_info ("memcached_callback: memcached returned error %s on READ stage", memc_strerror (error));
+ memc_close_ctx (param->ctx);
+ param->task->save.saved--;
+ if (param->task->save.saved == 0) {
+ /* Call other filters */
+ param->task->save.saved = 1;
+ process_filters (param->task);
+ }
+ }
+ else {
+ url_count = (int *)param->ctx->param->buf;
+ /* Do not check DNS for urls that have count more than max_urls */
+ if (*url_count > surbl_module_ctx->max_urls) {
+ msg_info ("memcached_callback: url '%s' has count %d, max: %d", struri (param->url), *url_count, surbl_module_ctx->max_urls);
+ /*
+ * XXX: try to understand why we should use memcached here
+ * insert_result (param->task, surbl_module_ctx->metric, surbl_module_ctx->symbol, 1);
+ */
+ }
+ (*url_count)++;
+ memc_set (param->ctx, param->ctx->param, surbl_module_ctx->url_expire);
+ }
+ break;
+ case CMD_WRITE:
+ if (error != OK) {
+ msg_info ("memcached_callback: memcached returned error %s on WRITE stage", memc_strerror (error));
+ }
+ memc_close_ctx (param->ctx);
+ param->task->save.saved--;
+ if (param->task->save.saved == 0) {
+ /* Call other filters */
+ param->task->save.saved = 1;
+ process_filters (param->task);
+ }
+ make_surbl_requests (param->url, param->task, param->tree, param->suffix);
+ break;
+ default:
+ return;
+ }
}
static void
-register_memcached_call (struct uri *url, struct worker_task *task, GTree *url_tree, struct suffix_item *suffix)
+register_memcached_call (struct uri *url, struct worker_task *task, GTree * url_tree, struct suffix_item *suffix)
{
- struct memcached_param *param;
- struct memcached_server *selected;
- memcached_param_t *cur_param;
- gchar *sum_str;
- int *url_count;
-
- param = memory_pool_alloc (task->task_pool, sizeof (struct memcached_param));
- cur_param = memory_pool_alloc0 (task->task_pool, sizeof (memcached_param_t));
- url_count = memory_pool_alloc (task->task_pool, sizeof (int));
-
- param->url = url;
- param->task = task;
- param->tree = url_tree;
- param->suffix = suffix;
-
- param->ctx = memory_pool_alloc0 (task->task_pool, sizeof (memcached_ctx_t));
-
- cur_param->buf = (u_char *)url_count;
- cur_param->bufsize = sizeof (int);
-
- sum_str = g_compute_checksum_for_string (G_CHECKSUM_MD5, struri (url), -1);
- g_strlcpy (cur_param->key, sum_str, sizeof (cur_param->key));
- g_free (sum_str);
-
- selected = (struct memcached_server *) get_upstream_by_hash ((void *)task->cfg->memcached_servers,
- task->cfg->memcached_servers_num, sizeof (struct memcached_server),
- time (NULL), task->cfg->memcached_error_time, task->cfg->memcached_dead_time, task->cfg->memcached_maxerrors,
- cur_param->key, strlen(cur_param->key));
- if (selected == NULL) {
- msg_err ("surbl_register_memcached_call: no memcached servers can be selected");
- return;
- }
- param->ctx->callback = memcached_callback;
- param->ctx->callback_data = (void *)param;
- param->ctx->protocol = task->cfg->memcached_protocol;
- memcpy(¶m->ctx->addr, &selected->addr, sizeof (struct in_addr));
- param->ctx->port = selected->port;
- param->ctx->timeout.tv_sec = task->cfg->memcached_connect_timeout / 1000;
- param->ctx->timeout.tv_sec = task->cfg->memcached_connect_timeout - param->ctx->timeout.tv_sec * 1000;
- param->ctx->sock = -1;
+ struct memcached_param *param;
+ struct memcached_server *selected;
+ memcached_param_t *cur_param;
+ gchar *sum_str;
+ int *url_count;
+
+ param = memory_pool_alloc (task->task_pool, sizeof (struct memcached_param));
+ cur_param = memory_pool_alloc0 (task->task_pool, sizeof (memcached_param_t));
+ url_count = memory_pool_alloc (task->task_pool, sizeof (int));
+
+ param->url = url;
+ param->task = task;
+ param->tree = url_tree;
+ param->suffix = suffix;
+
+ param->ctx = memory_pool_alloc0 (task->task_pool, sizeof (memcached_ctx_t));
+
+ cur_param->buf = (u_char *) url_count;
+ cur_param->bufsize = sizeof (int);
+
+ sum_str = g_compute_checksum_for_string (G_CHECKSUM_MD5, struri (url), -1);
+ g_strlcpy (cur_param->key, sum_str, sizeof (cur_param->key));
+ g_free (sum_str);
+
+ selected = (struct memcached_server *)get_upstream_by_hash ((void *)task->cfg->memcached_servers,
+ task->cfg->memcached_servers_num, sizeof (struct memcached_server),
+ time (NULL), task->cfg->memcached_error_time, task->cfg->memcached_dead_time, task->cfg->memcached_maxerrors, cur_param->key, strlen (cur_param->key));
+ if (selected == NULL) {
+ msg_err ("surbl_register_memcached_call: no memcached servers can be selected");
+ return;
+ }
+ param->ctx->callback = memcached_callback;
+ param->ctx->callback_data = (void *)param;
+ param->ctx->protocol = task->cfg->memcached_protocol;
+ memcpy (¶m->ctx->addr, &selected->addr, sizeof (struct in_addr));
+ param->ctx->port = selected->port;
+ param->ctx->timeout.tv_sec = task->cfg->memcached_connect_timeout / 1000;
+ param->ctx->timeout.tv_sec = task->cfg->memcached_connect_timeout - param->ctx->timeout.tv_sec * 1000;
+ param->ctx->sock = -1;
#ifdef WITH_DEBUG
- param->ctx->options = MEMC_OPT_DEBUG;
+ param->ctx->options = MEMC_OPT_DEBUG;
#else
- param->ctx->options = 0;
+ param->ctx->options = 0;
#endif
- param->ctx->param = cur_param;
- memc_init_ctx (param->ctx);
+ param->ctx->param = cur_param;
+ memc_init_ctx (param->ctx);
}
static void
free_redirector_session (void *ud)
{
- struct redirector_param *param = (struct redirector_param *)ud;
+ struct redirector_param *param = (struct redirector_param *)ud;
event_del (¶m->ev);
close (param->sock);
- param->task->save.saved --;
+ param->task->save.saved--;
make_surbl_requests (param->url, param->task, param->tree, param->suffix);
if (param->task->save.saved == 0) {
/* Call other filters */
param->task->save.saved = 1;
process_filters (param->task);
}
-
+
}
static void
redirector_callback (int fd, short what, void *arg)
{
- struct redirector_param *param = (struct redirector_param *)arg;
- char url_buf[1024];
- int r;
- struct timeval *timeout;
- char *p, *c;
-
- switch (param->state) {
- case STATE_CONNECT:
- /* We have write readiness after connect call, so reinit event */
- if (what == EV_WRITE) {
- timeout = memory_pool_alloc (param->task->task_pool, sizeof (struct timeval));
- timeout->tv_sec = surbl_module_ctx->read_timeout / 1000;
- timeout->tv_usec = surbl_module_ctx->read_timeout - timeout->tv_sec * 1000;
- event_del (¶m->ev);
- event_set (¶m->ev, param->sock, EV_READ | EV_PERSIST, redirector_callback, (void *)param);
- event_add (¶m->ev, timeout);
- r = snprintf (url_buf, sizeof (url_buf), "GET %s HTTP/1.0\r\n\r\n", struri (param->url));
- if (write (param->sock, url_buf, r) == -1) {
- msg_err ("redirector_callback: write failed %s", strerror (errno));
- remove_normal_event (param->task->s, free_redirector_session, param);
- return;
- }
- param->state = STATE_READ;
- }
- else {
- msg_info ("redirector_callback: <%s> connection to redirector timed out while waiting for write",
- param->task->message_id);
+ struct redirector_param *param = (struct redirector_param *)arg;
+ char url_buf[1024];
+ int r;
+ struct timeval *timeout;
+ char *p, *c;
+
+ switch (param->state) {
+ case STATE_CONNECT:
+ /* We have write readiness after connect call, so reinit event */
+ if (what == EV_WRITE) {
+ timeout = memory_pool_alloc (param->task->task_pool, sizeof (struct timeval));
+ timeout->tv_sec = surbl_module_ctx->read_timeout / 1000;
+ timeout->tv_usec = surbl_module_ctx->read_timeout - timeout->tv_sec * 1000;
+ event_del (¶m->ev);
+ event_set (¶m->ev, param->sock, EV_READ | EV_PERSIST, redirector_callback, (void *)param);
+ event_add (¶m->ev, timeout);
+ r = snprintf (url_buf, sizeof (url_buf), "GET %s HTTP/1.0\r\n\r\n", struri (param->url));
+ if (write (param->sock, url_buf, r) == -1) {
+ msg_err ("redirector_callback: write failed %s", strerror (errno));
remove_normal_event (param->task->s, free_redirector_session, param);
return;
- }
- break;
- case STATE_READ:
- if (what == EV_READ) {
- r = read (param->sock, url_buf, sizeof (url_buf));
- if ((p = strstr (url_buf, "Uri: ")) != NULL) {
- p += sizeof ("Uri: ") - 1;
- c = p;
- while (p++ < url_buf + sizeof (url_buf) - 1) {
- if (*p == '\r' || *p == '\n') {
- *p = '\0';
- break;
- }
- }
- if (*p == '\0') {
- msg_debug ("redirector_callback: <%s> got reply from redirector: '%s' -> '%s'",
- param->task->message_id, struri (param->url), c);
- parse_uri (param->url, memory_pool_strdup (param->task->task_pool, c), param->task->task_pool);
- }
- }
- remove_normal_event (param->task->s, free_redirector_session, param);
- }
- else {
- msg_info ("redirector_callback: <%s> reading redirector timed out, while waiting for read",
- param->task->message_id);
- remove_normal_event (param->task->s, free_redirector_session, param);
- }
- break;
- }
+ }
+ param->state = STATE_READ;
+ }
+ else {
+ msg_info ("redirector_callback: <%s> connection to redirector timed out while waiting for write", param->task->message_id);
+ remove_normal_event (param->task->s, free_redirector_session, param);
+ return;
+ }
+ break;
+ case STATE_READ:
+ if (what == EV_READ) {
+ r = read (param->sock, url_buf, sizeof (url_buf));
+ if ((p = strstr (url_buf, "Uri: ")) != NULL) {
+ p += sizeof ("Uri: ") - 1;
+ c = p;
+ while (p++ < url_buf + sizeof (url_buf) - 1) {
+ if (*p == '\r' || *p == '\n') {
+ *p = '\0';
+ break;
+ }
+ }
+ if (*p == '\0') {
+ msg_debug ("redirector_callback: <%s> got reply from redirector: '%s' -> '%s'", param->task->message_id, struri (param->url), c);
+ parse_uri (param->url, memory_pool_strdup (param->task->task_pool, c), param->task->task_pool);
+ }
+ }
+ remove_normal_event (param->task->s, free_redirector_session, param);
+ }
+ else {
+ msg_info ("redirector_callback: <%s> reading redirector timed out, while waiting for read", param->task->message_id);
+ remove_normal_event (param->task->s, free_redirector_session, param);
+ }
+ break;
+ }
}
static void
-register_redirector_call (struct uri *url, struct worker_task *task, GTree *url_tree, struct suffix_item *suffix)
+register_redirector_call (struct uri *url, struct worker_task *task, GTree * url_tree, struct suffix_item *suffix)
{
- int s;
- struct redirector_param *param;
- struct timeval *timeout;
-
- s = make_tcp_socket (&surbl_module_ctx->redirector_addr, surbl_module_ctx->redirector_port, FALSE, TRUE);
-
- if (s == -1) {
- msg_info ("register_redirector_call: <%s> cannot create tcp socket failed: %s",
- task->message_id, strerror (errno));
- task->save.saved --;
- make_surbl_requests (url, task, url_tree, suffix);
- return;
- }
-
- param = memory_pool_alloc (task->task_pool, sizeof (struct redirector_param));
- param->url = url;
- param->task = task;
- param->state = STATE_CONNECT;
- param->sock = s;
- param->tree = url_tree;
- param->suffix = suffix;
- timeout = memory_pool_alloc (task->task_pool, sizeof (struct timeval));
- timeout->tv_sec = surbl_module_ctx->connect_timeout / 1000;
- timeout->tv_usec = surbl_module_ctx->connect_timeout - timeout->tv_sec * 1000;
- event_set (¶m->ev, s, EV_WRITE, redirector_callback, (void *)param);
- event_add (¶m->ev, timeout);
+ int s;
+ struct redirector_param *param;
+ struct timeval *timeout;
+
+ s = make_tcp_socket (&surbl_module_ctx->redirector_addr, surbl_module_ctx->redirector_port, FALSE, TRUE);
+
+ if (s == -1) {
+ msg_info ("register_redirector_call: <%s> cannot create tcp socket failed: %s", task->message_id, strerror (errno));
+ task->save.saved--;
+ make_surbl_requests (url, task, url_tree, suffix);
+ return;
+ }
+
+ param = memory_pool_alloc (task->task_pool, sizeof (struct redirector_param));
+ param->url = url;
+ param->task = task;
+ param->state = STATE_CONNECT;
+ param->sock = s;
+ param->tree = url_tree;
+ param->suffix = suffix;
+ timeout = memory_pool_alloc (task->task_pool, sizeof (struct timeval));
+ timeout->tv_sec = surbl_module_ctx->connect_timeout / 1000;
+ timeout->tv_usec = surbl_module_ctx->connect_timeout - timeout->tv_sec * 1000;
+ event_set (¶m->ev, s, EV_WRITE, redirector_callback, (void *)param);
+ event_add (¶m->ev, timeout);
register_async_event (task->s, free_redirector_session, param, FALSE);
}
-static gboolean
+static gboolean
tree_url_callback (gpointer key, gpointer value, void *data)
{
- struct redirector_param *param = data;
- struct uri *url = value;
- f_str_t f;
- char *urlstr, *host_end;
- GError *err = NULL;
-
- msg_debug ("surbl_test_url: check url %s", struri (url));
-
-
- if (surbl_module_ctx->use_redirector) {
- f.begin = url->host;
- f.len = url->hostlen;
- if ((urlstr = format_surbl_request (param->task->task_pool, &f, NULL, &host_end, FALSE, &err)) != NULL) {
- if (g_hash_table_lookup (surbl_module_ctx->redirector_hosts, urlstr) != NULL) {
- register_redirector_call (url, param->task, param->tree, param->suffix);
- param->task->save.saved++;
- return FALSE;
- }
- }
- make_surbl_requests (url, param->task, param->tree, param->suffix);
- }
- else {
- if (param->task->worker->srv->cfg->memcached_servers_num > 0) {
- register_memcached_call (url, param->task, param->tree, param->suffix);
- param->task->save.saved++;
- }
- else {
- make_surbl_requests (url, param->task, param->tree, param->suffix);
- }
- }
-
- return FALSE;
+ struct redirector_param *param = data;
+ struct uri *url = value;
+ f_str_t f;
+ char *urlstr, *host_end;
+ GError *err = NULL;
+
+ msg_debug ("surbl_test_url: check url %s", struri (url));
+
+
+ if (surbl_module_ctx->use_redirector) {
+ f.begin = url->host;
+ f.len = url->hostlen;
+ if ((urlstr = format_surbl_request (param->task->task_pool, &f, NULL, &host_end, FALSE, &err)) != NULL) {
+ if (g_hash_table_lookup (surbl_module_ctx->redirector_hosts, urlstr) != NULL) {
+ register_redirector_call (url, param->task, param->tree, param->suffix);
+ param->task->save.saved++;
+ return FALSE;
+ }
+ }
+ make_surbl_requests (url, param->task, param->tree, param->suffix);
+ }
+ else {
+ if (param->task->worker->srv->cfg->memcached_servers_num > 0) {
+ register_memcached_call (url, param->task, param->tree, param->suffix);
+ param->task->save.saved++;
+ }
+ else {
+ make_surbl_requests (url, param->task, param->tree, param->suffix);
+ }
+ }
+
+ return FALSE;
}
static void
surbl_test_url (struct worker_task *task, void *user_data)
{
- GTree *url_tree;
- GList *cur;
- struct mime_text_part *part;
- struct redirector_param param;
- struct suffix_item *suffix = user_data;
-
- url_tree = g_tree_new ((GCompareFunc)g_ascii_strcasecmp);
-
- param.tree = url_tree;
- param.task = task;
- param.suffix = suffix;
- cur = task->text_parts;
- while (cur) {
- part = cur->data;
- if (part->urls) {
- g_tree_foreach (part->urls, tree_url_callback, ¶m);
- }
- if (part->html_urls) {
- g_tree_foreach (part->html_urls, tree_url_callback, ¶m);
- }
-
- cur = g_list_next (cur);
- }
-
- memory_pool_add_destructor (task->task_pool, (pool_destruct_func)g_tree_destroy, url_tree);
+ GTree *url_tree;
+ GList *cur;
+ struct mime_text_part *part;
+ struct redirector_param param;
+ struct suffix_item *suffix = user_data;
+
+ url_tree = g_tree_new ((GCompareFunc) g_ascii_strcasecmp);
+
+ param.tree = url_tree;
+ param.task = task;
+ param.suffix = suffix;
+ cur = task->text_parts;
+ while (cur) {
+ part = cur->data;
+ if (part->urls) {
+ g_tree_foreach (part->urls, tree_url_callback, ¶m);
+ }
+ if (part->html_urls) {
+ g_tree_foreach (part->html_urls, tree_url_callback, ¶m);
+ }
+
+ cur = g_list_next (cur);
+ }
+
+ memory_pool_add_destructor (task->task_pool, (pool_destruct_func) g_tree_destroy, url_tree);
}
static int
surbl_filter (struct worker_task *task)
{
- /* XXX: remove this shit */
- return 0;
+ /* XXX: remove this shit */
+ return 0;
}
-static int
+static int
urls_command_handler (struct worker_task *task)
{
- GList *cur;
- char *outbuf, *urlstr;
- int r, num = 0, buflen;
- struct uri *url;
- GError *err = NULL;
- GTree *url_tree;
- f_str_t f;
- char *host_end;
-
- url_tree = g_tree_new ((GCompareFunc)g_ascii_strcasecmp);
-
- /* First calculate buffer length */
- cur = g_list_first (task->urls);
- buflen = 0;
- while (cur) {
- url = cur->data;
- buflen += strlen (struri (url)) + url->hostlen + sizeof (" <\"\">, ") - 1;
- cur = g_list_next (cur);
- }
-
- buflen += sizeof (RSPAMD_REPLY_BANNER " 0 OK" CRLF CRLF "URLs: ");
-
- outbuf = memory_pool_alloc (task->task_pool, buflen * sizeof (char));
-
- r = snprintf (outbuf, buflen, "%s 0 %s" CRLF, (task->proto == SPAMC_PROTO) ? SPAMD_REPLY_BANNER : RSPAMD_REPLY_BANNER, "OK");
-
- r += snprintf (outbuf + r, buflen - r - 2, "URLs: ");
-
- cur = g_list_first (task->urls);
-
- while (cur) {
- num ++;
- url = cur->data;
- if (g_tree_lookup (url_tree, struri (url)) == NULL) {
- g_tree_insert (url_tree, struri (url), url);
- f.begin = url->host;
- f.len = url->hostlen;
- if ((urlstr = format_surbl_request (task->task_pool, &f, NULL, &host_end, FALSE, &err)) != NULL) {
- if (g_list_next (cur) != NULL) {
- r += snprintf (outbuf + r, buflen - r - 2, "%s <\"%s\">, ", (char *)urlstr, struri (url));
- }
- else {
- r += snprintf (outbuf + r, buflen - r - 2, "%s <\"%s\">", (char *)urlstr, struri (url));
- }
- }
- }
- cur = g_list_next (cur);
- }
-
- outbuf[r++] = '\r'; outbuf[r++] = '\n';
-
- rspamd_dispatcher_write (task->dispatcher, outbuf, r, FALSE, TRUE);
- msg_info ("process_message: msg ok, id: <%s>, %d urls extracted", task->message_id, num);
- g_tree_destroy (url_tree);
-
- return 0;
+ GList *cur;
+ char *outbuf, *urlstr;
+ int r, num = 0, buflen;
+ struct uri *url;
+ GError *err = NULL;
+ GTree *url_tree;
+ f_str_t f;
+ char *host_end;
+
+ url_tree = g_tree_new ((GCompareFunc) g_ascii_strcasecmp);
+
+ /* First calculate buffer length */
+ cur = g_list_first (task->urls);
+ buflen = 0;
+ while (cur) {
+ url = cur->data;
+ buflen += strlen (struri (url)) + url->hostlen + sizeof (" <\"\">, ") - 1;
+ cur = g_list_next (cur);
+ }
+
+ buflen += sizeof (RSPAMD_REPLY_BANNER " 0 OK" CRLF CRLF "URLs: ");
+
+ outbuf = memory_pool_alloc (task->task_pool, buflen * sizeof (char));
+
+ r = snprintf (outbuf, buflen, "%s 0 %s" CRLF, (task->proto == SPAMC_PROTO) ? SPAMD_REPLY_BANNER : RSPAMD_REPLY_BANNER, "OK");
+
+ r += snprintf (outbuf + r, buflen - r - 2, "URLs: ");
+
+ cur = g_list_first (task->urls);
+
+ while (cur) {
+ num++;
+ url = cur->data;
+ if (g_tree_lookup (url_tree, struri (url)) == NULL) {
+ g_tree_insert (url_tree, struri (url), url);
+ f.begin = url->host;
+ f.len = url->hostlen;
+ if ((urlstr = format_surbl_request (task->task_pool, &f, NULL, &host_end, FALSE, &err)) != NULL) {
+ if (g_list_next (cur) != NULL) {
+ r += snprintf (outbuf + r, buflen - r - 2, "%s <\"%s\">, ", (char *)urlstr, struri (url));
+ }
+ else {
+ r += snprintf (outbuf + r, buflen - r - 2, "%s <\"%s\">", (char *)urlstr, struri (url));
+ }
+ }
+ }
+ cur = g_list_next (cur);
+ }
+
+ outbuf[r++] = '\r';
+ outbuf[r++] = '\n';
+
+ rspamd_dispatcher_write (task->dispatcher, outbuf, r, FALSE, TRUE);
+ msg_info ("process_message: msg ok, id: <%s>, %d urls extracted", task->message_id, num);
+ g_tree_destroy (url_tree);
+
+ return 0;
}
#define MSG_CMD_SKIP "skip"
/*
* Return a confirmation that spamd is alive
- */
+ */
#define MSG_CMD_PING "ping"
/*
* Process this message as described above and return modified message
#define USER_HEADER "User"
#define DELIVER_TO_HEADER "Deliver-To"
-static GList *custom_commands = NULL;
+static GList *custom_commands = NULL;
-static char *
-separate_command (f_str_t *in, char c)
+static char *
+separate_command (f_str_t * in, char c)
{
- int r = 0;
- char *p = in->begin, *b;
+ int r = 0;
+ char *p = in->begin, *b;
b = p;
while (r < in->len) {
in->len -= r + 1;
return b;
}
- p ++;
- r ++;
+ p++;
+ r++;
}
return NULL;
}
static int
-parse_command (struct worker_task *task, f_str_t *line)
+parse_command (struct worker_task *task, f_str_t * line)
{
- char *token;
- struct custom_command *cmd;
- GList *cur;
+ char *token;
+ struct custom_command *cmd;
+ GList *cur;
token = separate_command (line, ' ');
if (line == NULL || token == NULL) {
}
switch (token[0]) {
- case 'c':
- case 'C':
- /* check */
- if (g_ascii_strcasecmp (token + 1, MSG_CMD_CHECK + 1) == 0) {
- task->cmd = CMD_CHECK;
- }
- else {
- msg_debug ("parse_command: bad command: %s", token);
- return -1;
- }
- break;
- case 's':
- case 'S':
- /* symbols, skip */
- if (g_ascii_strcasecmp (token + 1, MSG_CMD_SYMBOLS + 1) == 0) {
- task->cmd = CMD_SYMBOLS;
- }
- else if (g_ascii_strcasecmp (token + 1, MSG_CMD_SKIP + 1) == 0) {
- task->cmd = CMD_SKIP;
- }
- else {
- msg_debug ("parse_command: bad command: %s", token);
- return -1;
- }
- break;
- case 'p':
- case 'P':
- /* ping, process */
- if (g_ascii_strcasecmp (token + 1, MSG_CMD_PING + 1) == 0) {
- task->cmd = CMD_PING;
- }
- else if (g_ascii_strcasecmp (token + 1, MSG_CMD_PROCESS + 1) == 0) {
- task->cmd = CMD_PROCESS;
- }
- else {
- msg_debug ("parse_command: bad command: %s", token);
- return -1;
- }
- break;
- case 'r':
- case 'R':
- /* report, report_ifspam */
- if (g_ascii_strcasecmp (token + 1, MSG_CMD_REPORT + 1) == 0) {
- task->cmd = CMD_REPORT;
- }
- else if (g_ascii_strcasecmp (token + 1, MSG_CMD_REPORT_IFSPAM + 1) == 0) {
- task->cmd = CMD_REPORT_IFSPAM;
- }
- else {
- msg_debug ("parse_command: bad command: %s", token);
- return -1;
- }
- break;
- default:
- cur = custom_commands;
- while (cur) {
- cmd = cur->data;
- if (g_ascii_strcasecmp (token, cmd->name) == 0) {
- task->cmd = CMD_OTHER;
- task->custom_cmd = cmd;
- break;
- }
- cur = g_list_next (cur);
+ case 'c':
+ case 'C':
+ /* check */
+ if (g_ascii_strcasecmp (token + 1, MSG_CMD_CHECK + 1) == 0) {
+ task->cmd = CMD_CHECK;
+ }
+ else {
+ msg_debug ("parse_command: bad command: %s", token);
+ return -1;
+ }
+ break;
+ case 's':
+ case 'S':
+ /* symbols, skip */
+ if (g_ascii_strcasecmp (token + 1, MSG_CMD_SYMBOLS + 1) == 0) {
+ task->cmd = CMD_SYMBOLS;
+ }
+ else if (g_ascii_strcasecmp (token + 1, MSG_CMD_SKIP + 1) == 0) {
+ task->cmd = CMD_SKIP;
+ }
+ else {
+ msg_debug ("parse_command: bad command: %s", token);
+ return -1;
+ }
+ break;
+ case 'p':
+ case 'P':
+ /* ping, process */
+ if (g_ascii_strcasecmp (token + 1, MSG_CMD_PING + 1) == 0) {
+ task->cmd = CMD_PING;
+ }
+ else if (g_ascii_strcasecmp (token + 1, MSG_CMD_PROCESS + 1) == 0) {
+ task->cmd = CMD_PROCESS;
+ }
+ else {
+ msg_debug ("parse_command: bad command: %s", token);
+ return -1;
+ }
+ break;
+ case 'r':
+ case 'R':
+ /* report, report_ifspam */
+ if (g_ascii_strcasecmp (token + 1, MSG_CMD_REPORT + 1) == 0) {
+ task->cmd = CMD_REPORT;
+ }
+ else if (g_ascii_strcasecmp (token + 1, MSG_CMD_REPORT_IFSPAM + 1) == 0) {
+ task->cmd = CMD_REPORT_IFSPAM;
+ }
+ else {
+ msg_debug ("parse_command: bad command: %s", token);
+ return -1;
+ }
+ break;
+ default:
+ cur = custom_commands;
+ while (cur) {
+ cmd = cur->data;
+ if (g_ascii_strcasecmp (token, cmd->name) == 0) {
+ task->cmd = CMD_OTHER;
+ task->custom_cmd = cmd;
+ break;
}
+ cur = g_list_next (cur);
+ }
- if (cur == NULL) {
- msg_debug ("parse_command: bad command: %s", token);
- return -1;
- }
- break;
+ if (cur == NULL) {
+ msg_debug ("parse_command: bad command: %s", token);
+ return -1;
+ }
+ break;
}
if (strncasecmp (line->begin, RSPAMC_GREETING, sizeof (RSPAMC_GREETING) - 1) == 0) {
task->proto = RSPAMC_PROTO;
}
- else if (strncasecmp (line->begin, SPAMC_GREETING, sizeof (SPAMC_GREETING) -1) == 0) {
+ else if (strncasecmp (line->begin, SPAMC_GREETING, sizeof (SPAMC_GREETING) - 1) == 0) {
task->proto = SPAMC_PROTO;
}
else {
}
static int
-parse_header (struct worker_task *task, f_str_t *line)
+parse_header (struct worker_task *task, f_str_t * line)
{
- char *headern, *err, *tmp;
-
+ char *headern, *err, *tmp;
+
/* Check end of headers */
if (line->len == 0) {
msg_debug ("parse_header: got empty line, assume it as end of headers");
}
else {
if (task->content_length > 0) {
- rspamd_set_dispatcher_policy (task->dispatcher, BUFFER_CHARACTER, task->content_length);
+ rspamd_set_dispatcher_policy (task->dispatcher, BUFFER_CHARACTER, task->content_length);
task->state = READ_MESSAGE;
}
else {
fstrstrip (line);
switch (headern[0]) {
- case 'c':
- case 'C':
- /* content-length */
- if (strncasecmp (headern, CONTENT_LENGTH_HEADER, sizeof (CONTENT_LENGTH_HEADER) - 1) == 0) {
- if (task->content_length == 0) {
- tmp = memory_pool_fstrdup (task->task_pool, line);
- task->content_length = strtoul (tmp, &err, 10);
- msg_debug ("parse_header: read Content-Length header, value: %lu", (unsigned long int)task->content_length);
- }
- }
- else {
- msg_info ("parse_header: wrong header: %s", headern);
- return -1;
- }
- break;
- case 'd':
- case 'D':
- /* Deliver-To */
- if (strncasecmp (headern, DELIVER_TO_HEADER, sizeof (DELIVER_TO_HEADER) - 1) == 0) {
- task->deliver_to = memory_pool_fstrdup (task->task_pool, line);
- msg_debug ("parse_header: read deliver-to header, value: %s", task->deliver_to);
- }
- else {
- msg_info ("parse_header: wrong header: %s", headern);
- return -1;
- }
- break;
- case 'h':
- case 'H':
- /* helo */
- if (strncasecmp (headern, HELO_HEADER, sizeof (HELO_HEADER) - 1) == 0) {
- task->helo = memory_pool_fstrdup (task->task_pool, line);
- msg_debug ("parse_header: read helo header, value: %s", task->helo);
- }
- else {
- msg_info ("parse_header: wrong header: %s", headern);
- return -1;
- }
- break;
- case 'f':
- case 'F':
- /* from */
- if (strncasecmp (headern, FROM_HEADER, sizeof (FROM_HEADER) - 1) == 0) {
- task->from = memory_pool_fstrdup (task->task_pool, line);
- msg_debug ("parse_header: read from header, value: %s", task->from);
- }
- else {
- msg_info ("parse_header: wrong header: %s", headern);
- return -1;
- }
- break;
- case 'q':
- case 'Q':
- /* Queue id */
- if (strncasecmp (headern, QUEUE_ID_HEADER, sizeof (QUEUE_ID_HEADER) - 1) == 0) {
- task->queue_id = memory_pool_fstrdup (task->task_pool, line);
- msg_debug ("parse_header: read queue_id header, value: %s", task->queue_id);
- }
- else {
- msg_info ("parse_header: wrong header: %s", headern);
- return -1;
- }
- break;
- case 'r':
- case 'R':
- /* rcpt */
- if (strncasecmp (headern, RCPT_HEADER, sizeof (RCPT_HEADER) - 1) == 0) {
- tmp = memory_pool_fstrdup (task->task_pool, line);
- task->rcpt = g_list_prepend (task->rcpt, tmp);
- msg_debug ("parse_header: read rcpt header, value: %s", tmp);
- }
- else if (strncasecmp (headern, NRCPT_HEADER, sizeof (NRCPT_HEADER) - 1) == 0) {
- tmp = memory_pool_fstrdup (task->task_pool, line);
- task->nrcpt = strtoul (tmp, &err, 10);
- msg_debug ("parse_header: read rcpt header, value: %d", (int)task->nrcpt);
- }
- else {
- msg_info ("parse_header: wrong header: %s", headern);
- return -1;
- }
- break;
- case 'i':
- case 'I':
- /* ip_addr */
- if (strncasecmp (headern, IP_ADDR_HEADER, sizeof (IP_ADDR_HEADER) - 1) == 0) {
+ case 'c':
+ case 'C':
+ /* content-length */
+ if (strncasecmp (headern, CONTENT_LENGTH_HEADER, sizeof (CONTENT_LENGTH_HEADER) - 1) == 0) {
+ if (task->content_length == 0) {
tmp = memory_pool_fstrdup (task->task_pool, line);
- if (!inet_aton (tmp, &task->from_addr)) {
- msg_info ("parse_header: bad ip header: '%s'", tmp);
- return -1;
- }
- msg_debug ("parse_header: read IP header, value: %s", tmp);
- }
- else {
- msg_info ("parse_header: wrong header: %s", headern);
- return -1;
- }
- break;
- case 'u':
- case 'U':
- if (strncasecmp (headern, USER_HEADER, sizeof (USER_HEADER) - 1) == 0) {
- /* XXX: use this header somehow */
- task->user = memory_pool_fstrdup (task->task_pool, line);
+ task->content_length = strtoul (tmp, &err, 10);
+ msg_debug ("parse_header: read Content-Length header, value: %lu", (unsigned long int)task->content_length);
}
- else {
+ }
+ else {
+ msg_info ("parse_header: wrong header: %s", headern);
+ return -1;
+ }
+ break;
+ case 'd':
+ case 'D':
+ /* Deliver-To */
+ if (strncasecmp (headern, DELIVER_TO_HEADER, sizeof (DELIVER_TO_HEADER) - 1) == 0) {
+ task->deliver_to = memory_pool_fstrdup (task->task_pool, line);
+ msg_debug ("parse_header: read deliver-to header, value: %s", task->deliver_to);
+ }
+ else {
+ msg_info ("parse_header: wrong header: %s", headern);
+ return -1;
+ }
+ break;
+ case 'h':
+ case 'H':
+ /* helo */
+ if (strncasecmp (headern, HELO_HEADER, sizeof (HELO_HEADER) - 1) == 0) {
+ task->helo = memory_pool_fstrdup (task->task_pool, line);
+ msg_debug ("parse_header: read helo header, value: %s", task->helo);
+ }
+ else {
+ msg_info ("parse_header: wrong header: %s", headern);
+ return -1;
+ }
+ break;
+ case 'f':
+ case 'F':
+ /* from */
+ if (strncasecmp (headern, FROM_HEADER, sizeof (FROM_HEADER) - 1) == 0) {
+ task->from = memory_pool_fstrdup (task->task_pool, line);
+ msg_debug ("parse_header: read from header, value: %s", task->from);
+ }
+ else {
+ msg_info ("parse_header: wrong header: %s", headern);
+ return -1;
+ }
+ break;
+ case 'q':
+ case 'Q':
+ /* Queue id */
+ if (strncasecmp (headern, QUEUE_ID_HEADER, sizeof (QUEUE_ID_HEADER) - 1) == 0) {
+ task->queue_id = memory_pool_fstrdup (task->task_pool, line);
+ msg_debug ("parse_header: read queue_id header, value: %s", task->queue_id);
+ }
+ else {
+ msg_info ("parse_header: wrong header: %s", headern);
+ return -1;
+ }
+ break;
+ case 'r':
+ case 'R':
+ /* rcpt */
+ if (strncasecmp (headern, RCPT_HEADER, sizeof (RCPT_HEADER) - 1) == 0) {
+ tmp = memory_pool_fstrdup (task->task_pool, line);
+ task->rcpt = g_list_prepend (task->rcpt, tmp);
+ msg_debug ("parse_header: read rcpt header, value: %s", tmp);
+ }
+ else if (strncasecmp (headern, NRCPT_HEADER, sizeof (NRCPT_HEADER) - 1) == 0) {
+ tmp = memory_pool_fstrdup (task->task_pool, line);
+ task->nrcpt = strtoul (tmp, &err, 10);
+ msg_debug ("parse_header: read rcpt header, value: %d", (int)task->nrcpt);
+ }
+ else {
+ msg_info ("parse_header: wrong header: %s", headern);
+ return -1;
+ }
+ break;
+ case 'i':
+ case 'I':
+ /* ip_addr */
+ if (strncasecmp (headern, IP_ADDR_HEADER, sizeof (IP_ADDR_HEADER) - 1) == 0) {
+ tmp = memory_pool_fstrdup (task->task_pool, line);
+ if (!inet_aton (tmp, &task->from_addr)) {
+ msg_info ("parse_header: bad ip header: '%s'", tmp);
return -1;
}
- break;
- default:
+ msg_debug ("parse_header: read IP header, value: %s", tmp);
+ }
+ else {
msg_info ("parse_header: wrong header: %s", headern);
return -1;
+ }
+ break;
+ case 'u':
+ case 'U':
+ if (strncasecmp (headern, USER_HEADER, sizeof (USER_HEADER) - 1) == 0) {
+ /* XXX: use this header somehow */
+ task->user = memory_pool_fstrdup (task->task_pool, line);
+ }
+ else {
+ return -1;
+ }
+ break;
+ default:
+ msg_info ("parse_header: wrong header: %s", headern);
+ return -1;
}
return 0;
}
int
-read_rspamd_input_line (struct worker_task *task, f_str_t *line)
+read_rspamd_input_line (struct worker_task *task, f_str_t * line)
{
switch (task->state) {
- case READ_COMMAND:
- return parse_command (task, line);
- break;
- case READ_HEADER:
- return parse_header (task, line);
- break;
- default:
- return -1;
+ case READ_COMMAND:
+ return parse_command (task, line);
+ break;
+ case READ_HEADER:
+ return parse_header (task, line);
+ break;
+ default:
+ return -1;
}
return -1;
}
struct metric_callback_data {
- struct worker_task *task;
- char *log_buf;
- int log_offset;
- int log_size;
+ struct worker_task *task;
+ char *log_buf;
+ int log_offset;
+ int log_size;
};
static void
show_url_header (struct worker_task *task)
{
- int r = 0;
- char outbuf[OUTBUFSIZ], c;
- struct uri *url;
- GList *cur;
- f_str_t host;
+ int r = 0;
+ char outbuf[OUTBUFSIZ], c;
+ struct uri *url;
+ GList *cur;
+ f_str_t host;
r = snprintf (outbuf, sizeof (outbuf), "Urls: ");
cur = task->urls;
}
/* Do header folding */
if (host.len + r >= OUTBUFSIZ - 3) {
- outbuf[r ++] = '\r'; outbuf[r ++] = '\n'; outbuf[r] = ' ';
+ outbuf[r++] = '\r';
+ outbuf[r++] = '\n';
+ outbuf[r] = ' ';
rspamd_dispatcher_write (task->dispatcher, outbuf, r, TRUE, FALSE);
r = 0;
}
static void
metric_symbols_callback (gpointer key, gpointer value, void *user_data)
{
- struct metric_callback_data *cd = (struct metric_callback_data *)user_data;
- struct worker_task *task = cd->task;
- int r = 0;
- char outbuf[OUTBUFSIZ];
- struct symbol *s = (struct symbol *)value;
- GList *cur;
+ struct metric_callback_data *cd = (struct metric_callback_data *)user_data;
+ struct worker_task *task = cd->task;
+ int r = 0;
+ char outbuf[OUTBUFSIZ];
+ struct symbol *s = (struct symbol *)value;
+ GList *cur;
if (s->options) {
r = snprintf (outbuf, OUTBUFSIZ, "Symbol: %s; ", (char *)key);
else {
r = snprintf (outbuf, OUTBUFSIZ, "Symbol: %s" CRLF, (char *)key);
}
- cd->log_offset += snprintf (cd->log_buf + cd->log_offset, cd->log_size - cd->log_offset,
- "%s,", (char *)key);
+ cd->log_offset += snprintf (cd->log_buf + cd->log_offset, cd->log_size - cd->log_offset, "%s,", (char *)key);
rspamd_dispatcher_write (task->dispatcher, outbuf, r, FALSE, FALSE);
}
static void
show_metric_symbols (struct metric_result *metric_res, struct metric_callback_data *cd)
{
- int r = 0;
- GList *symbols, *cur;
- char outbuf[OUTBUFSIZ];
+ int r = 0;
+ GList *symbols, *cur;
+ char outbuf[OUTBUFSIZ];
if (cd->task->proto == SPAMC_PROTO) {
symbols = g_hash_table_get_keys (metric_res->symbols);
static void
show_metric_result (gpointer metric_name, gpointer metric_value, void *user_data)
{
- struct metric_callback_data *cd = (struct metric_callback_data *)user_data;
- struct worker_task *task = cd->task;
- int r;
- char outbuf[OUTBUFSIZ];
- struct metric_result *metric_res = (struct metric_result *)metric_value;
- struct metric *m;
- int is_spam = 0;
- double ms;
-
+ struct metric_callback_data *cd = (struct metric_callback_data *)user_data;
+ struct worker_task *task = cd->task;
+ int r;
+ char outbuf[OUTBUFSIZ];
+ struct metric_result *metric_res = (struct metric_result *)metric_value;
+ struct metric *m;
+ int is_spam = 0;
+ double ms;
+
if (metric_name == NULL || metric_value == NULL) {
m = g_hash_table_lookup (task->cfg->metrics, "default");
ms = m->required_score;
}
if (task->proto == SPAMC_PROTO) {
- r = snprintf (outbuf, sizeof (outbuf), "Spam: False ; 0 / %.2f" CRLF,
- m != NULL ? ms : 0);
+ r = snprintf (outbuf, sizeof (outbuf), "Spam: False ; 0 / %.2f" CRLF, m != NULL ? ms : 0);
}
else {
- r = snprintf (outbuf, sizeof (outbuf), "Metric: default; False; 0 / %.2f" CRLF,
- m != NULL ? ms : 0);
+ r = snprintf (outbuf, sizeof (outbuf), "Metric: default; False; 0 / %.2f" CRLF, m != NULL ? ms : 0);
}
- cd->log_offset += snprintf (cd->log_buf + cd->log_offset, cd->log_size - cd->log_offset,
- "(%s: F: [0/%.2f] [", "default", m != NULL ? ms : 0);
+ cd->log_offset += snprintf (cd->log_buf + cd->log_offset, cd->log_size - cd->log_offset, "(%s: F: [0/%.2f] [", "default", m != NULL ? ms : 0);
}
else {
if (!check_metric_settings (task, metric_res->metric, &ms)) {
is_spam = 1;
}
if (task->proto == SPAMC_PROTO) {
- r = snprintf (outbuf, sizeof (outbuf), "Spam: %s ; %.2f / %.2f" CRLF,
- (is_spam) ? "True" : "False", metric_res->score, ms);
+ r = snprintf (outbuf, sizeof (outbuf), "Spam: %s ; %.2f / %.2f" CRLF, (is_spam) ? "True" : "False", metric_res->score, ms);
}
else {
- r = snprintf (outbuf, sizeof (outbuf), "Metric: %s; %s; %.2f / %.2f" CRLF, (char *)metric_name,
- (is_spam) ? "True" : "False", metric_res->score, ms);
+ r = snprintf (outbuf, sizeof (outbuf), "Metric: %s; %s; %.2f / %.2f" CRLF, (char *)metric_name, (is_spam) ? "True" : "False", metric_res->score, ms);
}
- cd->log_offset += snprintf (cd->log_buf + cd->log_offset, cd->log_size - cd->log_offset,
- "(%s: %s: [%.2f/%.2f] [", (char *)metric_name, is_spam ? "T" : "F",
- metric_res->score, ms);
+ cd->log_offset += snprintf (cd->log_buf + cd->log_offset, cd->log_size - cd->log_offset, "(%s: %s: [%.2f/%.2f] [", (char *)metric_name, is_spam ? "T" : "F", metric_res->score, ms);
}
if (task->cmd == CMD_PROCESS) {
#ifndef GMIME24
}
}
cd->log_offset += snprintf (cd->log_buf + cd->log_offset, cd->log_size - cd->log_offset, "]), len: %ld, time: %sms",
- (long int)task->msg->len, calculate_check_time (&task->ts, task->cfg->clock_res));
+ (long int)task->msg->len, calculate_check_time (&task->ts, task->cfg->clock_res));
}
static int
write_check_reply (struct worker_task *task)
{
- int r;
- char outbuf[OUTBUFSIZ], logbuf[OUTBUFSIZ];
- struct metric_result *metric_res;
- struct metric_callback_data cd;
+ int r;
+ char outbuf[OUTBUFSIZ], logbuf[OUTBUFSIZ];
+ struct metric_result *metric_res;
+ struct metric_callback_data cd;
r = snprintf (outbuf, sizeof (outbuf), "%s 0 %s" CRLF, (task->proto == SPAMC_PROTO) ? SPAMD_REPLY_BANNER : RSPAMD_REPLY_BANNER, "OK");
rspamd_dispatcher_write (task->dispatcher, outbuf, r, TRUE, FALSE);
show_metric_result (NULL, NULL, (void *)&cd);
}
else {
- show_metric_result ((gpointer)"default", (gpointer)metric_res, (void *)&cd);
+ show_metric_result ((gpointer) "default", (gpointer) metric_res, (void *)&cd);
}
}
else {
show_metric_result (NULL, NULL, (void *)&cd);
}
else {
- show_metric_result ((gpointer)"default", (gpointer)metric_res, (void *)&cd);
+ show_metric_result ((gpointer) "default", (gpointer) metric_res, (void *)&cd);
}
g_hash_table_remove (task->results, "default");
static int
write_process_reply (struct worker_task *task)
{
- int r;
- char *outmsg;
- char outbuf[OUTBUFSIZ], logbuf[OUTBUFSIZ];
- struct metric_result *metric_res;
- struct metric_callback_data cd;
+ int r;
+ char *outmsg;
+ char outbuf[OUTBUFSIZ], logbuf[OUTBUFSIZ];
+ struct metric_result *metric_res;
+ struct metric_callback_data cd;
- r = snprintf (outbuf, sizeof (outbuf), "%s 0 %s" CRLF "Content-Length: %zd" CRLF CRLF,
- (task->proto == SPAMC_PROTO) ? SPAMD_REPLY_BANNER : RSPAMD_REPLY_BANNER, "OK", task->msg->len);
+ r = snprintf (outbuf, sizeof (outbuf), "%s 0 %s" CRLF "Content-Length: %zd" CRLF CRLF, (task->proto == SPAMC_PROTO) ? SPAMD_REPLY_BANNER : RSPAMD_REPLY_BANNER, "OK", task->msg->len);
cd.task = task;
cd.log_buf = logbuf;
show_metric_result (NULL, NULL, (void *)&cd);
}
else {
- show_metric_result ((gpointer)"default", (gpointer)metric_res, (void *)&cd);
+ show_metric_result ((gpointer) "default", (gpointer) metric_res, (void *)&cd);
}
}
else {
show_metric_result (NULL, NULL, (void *)&cd);
}
else {
- show_metric_result ((gpointer)"default", (gpointer)metric_res, (void *)&cd);
+ show_metric_result ((gpointer) "default", (gpointer) metric_res, (void *)&cd);
}
g_hash_table_remove (task->results, "default");
rspamd_dispatcher_write (task->dispatcher, outbuf, r, TRUE, FALSE);
rspamd_dispatcher_write (task->dispatcher, outmsg, strlen (outmsg), FALSE, TRUE);
- memory_pool_add_destructor (task->task_pool, (pool_destruct_func)g_free, outmsg);
+ memory_pool_add_destructor (task->task_pool, (pool_destruct_func) g_free, outmsg);
return 0;
}
int
write_reply (struct worker_task *task)
{
- int r;
- char outbuf[OUTBUFSIZ];
+ int r;
+ char outbuf[OUTBUFSIZ];
msg_debug ("write_reply: writing reply to client");
if (task->error_code != 0) {
msg_debug ("write_reply: writing error: %s", outbuf);
}
else {
- r = snprintf (outbuf, sizeof (outbuf), "%s %d %s" CRLF "%s: %s" CRLF CRLF, RSPAMD_REPLY_BANNER, task->error_code,
- SPAMD_ERROR, ERROR_HEADER, task->last_error);
+ r = snprintf (outbuf, sizeof (outbuf), "%s %d %s" CRLF "%s: %s" CRLF CRLF, RSPAMD_REPLY_BANNER, task->error_code, SPAMD_ERROR, ERROR_HEADER, task->last_error);
msg_debug ("write_reply: writing error: %s", outbuf);
}
/* Write to bufferevent error message */
}
else {
switch (task->cmd) {
- case CMD_REPORT_IFSPAM:
- case CMD_REPORT:
- case CMD_CHECK:
- case CMD_SYMBOLS:
- return write_check_reply (task);
- break;
- case CMD_PROCESS:
- return write_process_reply (task);
- break;
- case CMD_SKIP:
- r = snprintf (outbuf, sizeof (outbuf), "%s 0 %s" CRLF, (task->proto == SPAMC_PROTO) ? SPAMD_REPLY_BANNER : RSPAMD_REPLY_BANNER,
- SPAMD_OK);
- rspamd_dispatcher_write (task->dispatcher, outbuf, r, FALSE, FALSE);
- break;
- case CMD_PING:
- r = snprintf (outbuf, sizeof (outbuf), "%s 0 PONG" CRLF, (task->proto == SPAMC_PROTO) ? SPAMD_REPLY_BANNER : RSPAMD_REPLY_BANNER);
- rspamd_dispatcher_write (task->dispatcher, outbuf, r, FALSE, FALSE);
- break;
- case CMD_OTHER:
- return task->custom_cmd->func (task);
+ case CMD_REPORT_IFSPAM:
+ case CMD_REPORT:
+ case CMD_CHECK:
+ case CMD_SYMBOLS:
+ return write_check_reply (task);
+ break;
+ case CMD_PROCESS:
+ return write_process_reply (task);
+ break;
+ case CMD_SKIP:
+ r = snprintf (outbuf, sizeof (outbuf), "%s 0 %s" CRLF, (task->proto == SPAMC_PROTO) ? SPAMD_REPLY_BANNER : RSPAMD_REPLY_BANNER, SPAMD_OK);
+ rspamd_dispatcher_write (task->dispatcher, outbuf, r, FALSE, FALSE);
+ break;
+ case CMD_PING:
+ r = snprintf (outbuf, sizeof (outbuf), "%s 0 PONG" CRLF, (task->proto == SPAMC_PROTO) ? SPAMD_REPLY_BANNER : RSPAMD_REPLY_BANNER);
+ rspamd_dispatcher_write (task->dispatcher, outbuf, r, FALSE, FALSE);
+ break;
+ case CMD_OTHER:
+ return task->custom_cmd->func (task);
}
}
return 0;
}
-void
+void
register_protocol_command (const char *name, protocol_reply_func func)
{
- struct custom_command *cmd;
+ struct custom_command *cmd;
cmd = g_malloc (sizeof (struct custom_command));
cmd->name = name;
#include "radix.h"
#include "mem_pool.h"
-static void *radix_alloc (radix_tree_t *tree);
+static void *radix_alloc (radix_tree_t * tree);
-radix_tree_t *
+radix_tree_t *
radix_tree_create ()
{
- radix_tree_t *tree;
+ radix_tree_t *tree;
- tree = g_malloc (sizeof(radix_tree_t));
+ tree = g_malloc (sizeof (radix_tree_t));
if (tree == NULL) {
return NULL;
}
-
- tree->pool = memory_pool_new (memory_pool_get_size ());
+
+ tree->pool = memory_pool_new (memory_pool_get_size ());
tree->size = 0;
tree->root = radix_alloc (tree);
tree->root->left = NULL;
tree->root->parent = NULL;
tree->root->value = RADIX_NO_VALUE;
-
+
return tree;
}
int
-radix32tree_insert (radix_tree_t *tree, uint32_t key, uint32_t mask,
- unsigned char value)
+radix32tree_insert (radix_tree_t * tree, uint32_t key, uint32_t mask, unsigned char value)
{
- uint32_t bit;
- radix_node_t *node, *next;
+ uint32_t bit;
+ radix_node_t *node, *next;
bit = 0x80000000;
if (key & bit) {
next = node->right;
- } else {
+ }
+ else {
next = node->left;
}
}
/* Inserting value in trie creating all path components */
while (bit & mask) {
- next = radix_alloc(tree);
+ next = radix_alloc (tree);
if (next == NULL) {
return -1;
}
if (key & bit) {
node->right = next;
- } else {
+ }
+ else {
node->left = next;
}
int
-radix32tree_delete (radix_tree_t *tree, uint32_t key, uint32_t mask)
+radix32tree_delete (radix_tree_t * tree, uint32_t key, uint32_t mask)
{
- uint32_t bit;
- radix_node_t *node;
- radix_node_t *tmp;
+ uint32_t bit;
+ radix_node_t *node;
+ radix_node_t *tmp;
bit = 0x80000000;
node = tree->root;
if (key & bit) {
node = node->right;
- } else {
+ }
+ else {
node = node->left;
}
return -1;
}
- for ( ;; ) {
+ for (;;) {
if (node->parent->right == node) {
node->parent->right = NULL;
- } else {
+ }
+ else {
node->parent->left = NULL;
}
unsigned char
-radix32tree_find (radix_tree_t *tree, uint32_t key)
+radix32tree_find (radix_tree_t * tree, uint32_t key)
{
- uint32_t bit;
- uintptr_t value;
- radix_node_t *node;
+ uint32_t bit;
+ uintptr_t value;
+ radix_node_t *node;
bit = 0x80000000;
value = RADIX_NO_VALUE;
if (key & bit) {
node = node->right;
- } else {
+ }
+ else {
node = node->left;
}
}
-static void *
-radix_alloc (radix_tree_t *tree)
+static void *
+radix_alloc (radix_tree_t * tree)
{
- char *p;
+ char *p;
- p = memory_pool_alloc (tree->pool, sizeof(radix_node_t));
+ p = memory_pool_alloc (tree->pool, sizeof (radix_node_t));
tree->size += sizeof (radix_node_t);
}
void
-radix_tree_free (radix_tree_t *tree)
+radix_tree_free (radix_tree_t * tree)
{
-
+
g_return_if_fail (tree != NULL);
memory_pool_delete (tree->pool);
g_free (tree);
#include "json/jansson.h"
struct json_buf {
- GHashTable *table;
- u_char *buf;
- u_char *pos;
- size_t buflen;
+ GHashTable *table;
+ u_char *buf;
+ u_char *pos;
+ size_t buflen;
};
static void
settings_free (gpointer data)
{
- struct rspamd_settings *s = data;
+ struct rspamd_settings *s = data;
if (s->statfile_alias) {
g_free (s->statfile_alias);
}
-u_char*
-json_read_cb (memory_pool_t *pool, u_char *chunk, size_t len, struct map_cb_data *data)
+u_char *
+json_read_cb (memory_pool_t * pool, u_char * chunk, size_t len, struct map_cb_data *data)
{
- struct json_buf *jb;
- size_t free, off;
+ struct json_buf *jb;
+ size_t free, off;
if (data->cur_data == NULL) {
jb = g_malloc (sizeof (struct json_buf));
memcpy (jb->pos, chunk, len);
jb->pos += len;
-
+
/* Say not to copy any part of this buffer */
return NULL;
}
void
-json_fin_cb (memory_pool_t *pool, struct map_cb_data *data)
-{
- struct json_buf *jb;
- int nelts, i;
- json_t *js, *cur_elt, *cur_nm, *it_val;
- json_error_t je;
- struct rspamd_settings *cur_settings;
- char *cur_name;
- void *json_it;
- double *score;
+json_fin_cb (memory_pool_t * pool, struct map_cb_data *data)
+{
+ struct json_buf *jb;
+ int nelts, i;
+ json_t *js, *cur_elt, *cur_nm, *it_val;
+ json_error_t je;
+ struct rspamd_settings *cur_settings;
+ char *cur_name;
+ void *json_it;
+ double *score;
if (data->prev_data) {
jb = data->prev_data;
}
nelts = json_array_size (js);
- for (i = 0; i < nelts; i ++) {
+ for (i = 0; i < nelts; i++) {
cur_settings = g_malloc (sizeof (struct rspamd_settings));
cur_settings->metric_scores = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
cur_settings->factors = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
while (json_it) {
it_val = json_object_iter_value (json_it);
if (it_val && json_is_string (it_val)) {
- g_hash_table_insert (cur_settings->factors, g_strdup (json_object_iter_key (json_it)),
- g_strdup (json_string_value (it_val)));
+ g_hash_table_insert (cur_settings->factors, g_strdup (json_object_iter_key (json_it)), g_strdup (json_string_value (it_val)));
}
- json_it = json_object_iter_next(cur_nm, json_it);
+ json_it = json_object_iter_next (cur_nm, json_it);
}
}
/* Metrics object */
if (it_val && json_is_number (it_val)) {
score = g_malloc (sizeof (double));
*score = json_number_value (it_val);
- g_hash_table_insert (cur_settings->metric_scores, g_strdup (json_object_iter_key (json_it)),
- score);
+ g_hash_table_insert (cur_settings->metric_scores, g_strdup (json_object_iter_key (json_it)), score);
}
- json_it = json_object_iter_next(cur_nm, json_it);
+ json_it = json_object_iter_next (cur_nm, json_it);
}
}
/* Want spam */
cur_settings->want_spam = TRUE;
}
}
- g_hash_table_insert (((struct json_buf*)data->cur_data)->table, cur_name, cur_settings);
+ g_hash_table_insert (((struct json_buf *)data->cur_data)->table, cur_name, cur_settings);
}
json_decref (js);
}
gboolean
-read_settings (const char *path, struct config_file *cfg, GHashTable *table)
+read_settings (const char *path, struct config_file *cfg, GHashTable * table)
{
- struct json_buf *jb = g_malloc (sizeof (struct json_buf)), **pjb;
+ struct json_buf *jb = g_malloc (sizeof (struct json_buf)), **pjb;
pjb = g_malloc (sizeof (struct json_buf *));
-
+
jb->table = table;
jb->buf = NULL;
*pjb = jb;
msg_err ("read_settings: cannot add map %s", path);
return FALSE;
}
-
+
return TRUE;
}
cfg->user_settings = g_hash_table_new_full (rspamd_strcase_hash, rspamd_strcase_equal, g_free, settings_free);
}
-static gboolean
+static gboolean
check_setting (struct worker_task *task, struct rspamd_settings **user_settings, struct rspamd_settings **domain_settings)
{
- char *field = NULL, *domain = NULL;
+ char *field = NULL, *domain = NULL;
if (task->deliver_to != NULL) {
/* First try to use deliver-to field */
}
}
if (domain != NULL) {
- domain ++;
+ domain++;
}
-
+
/* First try to search per-user settings */
if (field != NULL) {
*user_settings = g_hash_table_lookup (task->cfg->user_settings, field);
return FALSE;
}
-gboolean
-check_metric_settings (struct worker_task *task, struct metric *metric, double *score)
+gboolean
+check_metric_settings (struct worker_task * task, struct metric * metric, double *score)
{
- struct rspamd_settings *us, *ds;
- double *sc;
+ struct rspamd_settings *us, *ds;
+ double *sc;
if (check_setting (task, &us, &ds)) {
if (us != NULL) {
}
}
}
-
+
return FALSE;
}
-gboolean
-check_factor_settings (struct worker_task *task, const char *symbol, double *factor)
+gboolean
+check_factor_settings (struct worker_task * task, const char *symbol, double *factor)
{
- struct rspamd_settings *us, *ds;
- double *fc;
+ struct rspamd_settings *us, *ds;
+ double *fc;
if (check_setting (task, &us, &ds)) {
if (us != NULL) {
}
}
}
-
+
return FALSE;
}
-gboolean
-check_want_spam (struct worker_task *task)
+gboolean
+check_want_spam (struct worker_task * task)
{
- struct rspamd_settings *us, *ds;
+ struct rspamd_settings *us, *ds;
if (check_setting (task, &us, &ds)) {
if (us != NULL) {
}
}
}
-
+
return FALSE;
}
static int
cmpstatfile (const void *a, const void *b)
{
- const stat_file_t *s1 = a, *s2 = b;
+ const stat_file_t *s1 = a, *s2 = b;
return g_ascii_strcasecmp (s1->filename, s2->filename);
}
/* Check whether specified file is statistic file and calculate its len in blocks */
static int
-statfile_pool_check (stat_file_t *file)
+statfile_pool_check (stat_file_t * file)
{
- struct stat_file *f;
- char *c;
+ struct stat_file *f;
+ char *c;
if (!file || !file->map) {
return -1;
/* Check first section and set new offset */
file->cur_section.code = f->section.code;
file->cur_section.length = f->section.length;
- if (file->cur_section.length * sizeof (struct stat_file_block) > file->len) {
- msg_info ("statfile_pool_check: file %s is truncated: %zd, must be %zd", file->filename,
- file->len, file->cur_section.length * sizeof (struct stat_file_block));
+ if (file->cur_section.length * sizeof (struct stat_file_block) > file->len) {
+ msg_info ("statfile_pool_check: file %s is truncated: %zd, must be %zd", file->filename, file->len, file->cur_section.length * sizeof (struct stat_file_block));
return -1;
- }
+ }
file->seek_pos = sizeof (struct stat_file) - sizeof (struct stat_file_block);
-
+
return 0;
}
struct expiration_data {
- statfile_pool_t *pool;
- uint64_t oldest;
- char *filename;
+ statfile_pool_t *pool;
+ uint64_t oldest;
+ char *filename;
};
static int
-statfile_pool_expire (statfile_pool_t *pool)
+statfile_pool_expire (statfile_pool_t * pool)
{
- struct expiration_data exp;
- stat_file_t *file;
- int i;
+ struct expiration_data exp;
+ stat_file_t *file;
+ int i;
if (pool->opened == 0) {
return -1;
for (i = 0; i < pool->opened; i++) {
file = &pool->files[i];
- if ((uint64_t)file->access_time < exp.oldest) {
+ if ((uint64_t) file->access_time < exp.oldest) {
exp.oldest = file->access_time;
exp.filename = file->filename;
}
return 0;
}
-statfile_pool_t*
+statfile_pool_t *
statfile_pool_new (size_t max_size)
{
- statfile_pool_t *new;
+ statfile_pool_t *new;
new = g_malloc (sizeof (statfile_pool_t));
bzero (new, sizeof (statfile_pool_t));
new->pool = memory_pool_new (memory_pool_get_size ());
new->max = max_size;
new->files = memory_pool_alloc_shared (new->pool, STATFILES_MAX * sizeof (stat_file_t));
- new->lock = memory_pool_get_mutex (new->pool);
+ new->lock = memory_pool_get_mutex (new->pool);
return new;
}
-stat_file_t *
-statfile_pool_open (statfile_pool_t *pool, char *filename)
+stat_file_t *
+statfile_pool_open (statfile_pool_t * pool, char *filename)
{
- struct stat st;
- stat_file_t *new_file;
-
+ struct stat st;
+ stat_file_t *new_file;
+
if ((new_file = statfile_pool_is_open (pool, filename)) != NULL) {
return new_file;
}
if (pool->opened >= STATFILES_MAX - 1) {
- msg_err ("sttafile_pool_open: reached hard coded limit of statfiles opened: %d", STATFILES_MAX);
+ msg_err ("sttafile_pool_open: reached hard coded limit of statfiles opened: %d", STATFILES_MAX);
return NULL;
}
msg_info ("statfile_pool_open: cannot stat file %s, error %s, %d", filename, strerror (errno), errno);
return NULL;
}
-
+
if (st.st_size > pool->max) {
- msg_info ("statfile_pool_open: cannot attach file to pool, too large: %zd", (size_t)st.st_size);
+ msg_info ("statfile_pool_open: cannot attach file to pool, too large: %zd", (size_t) st.st_size);
return NULL;
}
return NULL;
}
}
-
- memory_pool_lock_mutex (pool->lock);
- new_file = &pool->files[pool->opened ++];
- bzero (new_file, sizeof (stat_file_t));
- if ((new_file->fd = open (filename, O_RDWR)) == -1 ) {
+
+ memory_pool_lock_mutex (pool->lock);
+ new_file = &pool->files[pool->opened++];
+ bzero (new_file, sizeof (stat_file_t));
+ if ((new_file->fd = open (filename, O_RDWR)) == -1) {
msg_info ("statfile_pool_open: cannot open file %s, error %d, %s", filename, errno, strerror (errno));
- memory_pool_unlock_mutex (pool->lock);
- pool->opened --;
+ memory_pool_unlock_mutex (pool->lock);
+ pool->opened--;
return NULL;
}
-
+
if ((new_file->map = mmap (NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, new_file->fd, 0)) == MAP_FAILED) {
close (new_file->fd);
- memory_pool_unlock_mutex (pool->lock);
+ memory_pool_unlock_mutex (pool->lock);
msg_info ("statfile_pool_open: cannot mmap file %s, error %d, %s", filename, errno, strerror (errno));
- pool->opened --;
+ pool->opened--;
return NULL;
-
+
}
-
+
g_strlcpy (new_file->filename, filename, sizeof (new_file->filename));
new_file->len = st.st_size;
if (statfile_pool_check (new_file) == -1) {
- pool->opened --;
- memory_pool_unlock_mutex (pool->lock);
+ pool->opened--;
+ memory_pool_unlock_mutex (pool->lock);
return NULL;
}
new_file->open_time = time (NULL);
new_file->access_time = new_file->open_time;
new_file->lock = memory_pool_get_mutex (pool->pool);
-
+
/* Keep sorted */
qsort (pool->files, pool->opened, sizeof (stat_file_t), cmpstatfile);
- memory_pool_unlock_mutex (pool->lock);
+ memory_pool_unlock_mutex (pool->lock);
return new_file;
}
int
-statfile_pool_close (statfile_pool_t *pool, stat_file_t *file, gboolean keep_sorted)
+statfile_pool_close (statfile_pool_t * pool, stat_file_t * file, gboolean keep_sorted)
{
- stat_file_t *pos;
+ stat_file_t *pos;
if ((pos = statfile_pool_is_open (pool, file->filename)) == NULL) {
msg_info ("statfile_pool_open: file %s is not opened", file->filename);
return -1;
}
-
- memory_pool_lock_mutex (pool->lock);
+
+ memory_pool_lock_mutex (pool->lock);
if (file->lock) {
memory_pool_lock_mutex (file->lock);
}
close (file->fd);
}
pool->occupied -= file->len;
- pool->opened --;
+ pool->opened--;
if (keep_sorted) {
memmove (pos, &pool->files[pool->opened], sizeof (stat_file_t));
/* Keep sorted */
qsort (pool->files, pool->opened, sizeof (stat_file_t), cmpstatfile);
}
- memory_pool_unlock_mutex (pool->lock);
+ memory_pool_unlock_mutex (pool->lock);
return 0;
}
int
-statfile_pool_create (statfile_pool_t *pool, char *filename, size_t blocks)
+statfile_pool_create (statfile_pool_t * pool, char *filename, size_t blocks)
{
- struct stat_file_header header = {
+ struct stat_file_header header = {
.magic = {'r', 's', 'd'},
.version = {1, 0},
.padding = {0, 0, 0},
};
- struct stat_file_section section = {
+ struct stat_file_section section = {
.code = STATFILE_SECTION_COMMON,
};
- struct stat_file_block block = {0, 0, 0, 0};
- int fd;
-
+ struct stat_file_block block = { 0, 0, 0, 0 };
+ int fd;
+
if (statfile_pool_is_open (pool, filename) != NULL) {
msg_info ("statfile_pool_open: file %s is already opened", filename);
return 0;
}
- memory_pool_lock_mutex (pool->lock);
+ memory_pool_lock_mutex (pool->lock);
- if ((fd = open (filename, O_RDWR | O_TRUNC | O_CREAT, S_IWUSR | S_IRUSR)) == -1 ) {
+ if ((fd = open (filename, O_RDWR | O_TRUNC | O_CREAT, S_IWUSR | S_IRUSR)) == -1) {
msg_info ("statfile_pool_create: cannot create file %s, error %d, %s", filename, errno, strerror (errno));
- memory_pool_unlock_mutex (pool->lock);
+ memory_pool_unlock_mutex (pool->lock);
return -1;
}
- header.create_time = (uint64_t)time (NULL);
+ header.create_time = (uint64_t) time (NULL);
if (write (fd, &header, sizeof (header)) == -1) {
msg_info ("statfile_pool_create: cannot write header to file %s, error %d, %s", filename, errno, strerror (errno));
close (fd);
- memory_pool_unlock_mutex (pool->lock);
+ memory_pool_unlock_mutex (pool->lock);
return -1;
}
-
- section.length = (uint64_t)blocks;
+
+ section.length = (uint64_t) blocks;
if (write (fd, §ion, sizeof (section)) == -1) {
msg_info ("statfile_pool_create: cannot write section header to file %s, error %d, %s", filename, errno, strerror (errno));
close (fd);
- memory_pool_unlock_mutex (pool->lock);
+ memory_pool_unlock_mutex (pool->lock);
return -1;
}
-
- while (blocks --) {
+
+ while (blocks--) {
if (write (fd, &block, sizeof (block)) == -1) {
msg_info ("statfile_pool_create: cannot write block to file %s, error %d, %s", filename, errno, strerror (errno));
close (fd);
- memory_pool_unlock_mutex (pool->lock);
+ memory_pool_unlock_mutex (pool->lock);
return -1;
}
}
close (fd);
- memory_pool_unlock_mutex (pool->lock);
-
+ memory_pool_unlock_mutex (pool->lock);
+
return 0;
}
void
-statfile_pool_delete (statfile_pool_t *pool)
+statfile_pool_delete (statfile_pool_t * pool)
{
- int i;
+ int i;
- for (i = 0; i < pool->opened; i ++) {
+ for (i = 0; i < pool->opened; i++) {
statfile_pool_close (pool, &pool->files[i], FALSE);
}
memory_pool_delete (pool->pool);
}
void
-statfile_pool_lock_file (statfile_pool_t *pool, stat_file_t *file)
+statfile_pool_lock_file (statfile_pool_t * pool, stat_file_t * file)
{
memory_pool_lock_mutex (file->lock);
}
void
-statfile_pool_unlock_file (statfile_pool_t *pool, stat_file_t *file)
+statfile_pool_unlock_file (statfile_pool_t * pool, stat_file_t * file)
{
memory_pool_unlock_mutex (file->lock);
}
float
-statfile_pool_get_block (statfile_pool_t *pool, stat_file_t *file, uint32_t h1, uint32_t h2, time_t now)
+statfile_pool_get_block (statfile_pool_t * pool, stat_file_t * file, uint32_t h1, uint32_t h2, time_t now)
{
- struct stat_file_block *block;
- struct stat_file_header *header;
- unsigned int i, blocknum;
- u_char *c;
-
-
+ struct stat_file_block *block;
+ struct stat_file_header *header;
+ unsigned int i, blocknum;
+ u_char *c;
+
+
file->access_time = now;
if (!file->map) {
return 0;
}
-
+
blocknum = h1 % file->cur_section.length;
header = (struct stat_file_header *)file->map;
- c = (u_char *)file->map + file->seek_pos + blocknum * sizeof (struct stat_file_block);
+ c = (u_char *) file->map + file->seek_pos + blocknum * sizeof (struct stat_file_block);
block = (struct stat_file_block *)c;
- for (i = 0; i < CHAIN_LENGTH; i ++) {
+ for (i = 0; i < CHAIN_LENGTH; i++) {
if (i + blocknum > file->cur_section.length) {
break;
}
if (block->hash1 == h1 && block->hash2 == h2) {
- block->last_access = now - (time_t)header->create_time;
+ block->last_access = now - (time_t) header->create_time;
return block->value;
}
c += sizeof (struct stat_file_block);
}
void
-statfile_pool_set_block (statfile_pool_t *pool, stat_file_t *file, uint32_t h1, uint32_t h2, time_t now, float value)
+statfile_pool_set_block (statfile_pool_t * pool, stat_file_t * file, uint32_t h1, uint32_t h2, time_t now, float value)
{
- struct stat_file_block *block, *to_expire = NULL;
- struct stat_file_header *header;
- unsigned int i, blocknum, oldest = 0;
- u_char *c;
-
-
+ struct stat_file_block *block, *to_expire = NULL;
+ struct stat_file_header *header;
+ unsigned int i, blocknum, oldest = 0;
+ u_char *c;
+
+
file->access_time = now;
if (!file->map) {
return;
}
-
+
blocknum = h1 % file->cur_section.length;
header = (struct stat_file_header *)file->map;
- c = (u_char *)file->map + file->seek_pos + blocknum * sizeof (struct stat_file_block);
+ c = (u_char *) file->map + file->seek_pos + blocknum * sizeof (struct stat_file_block);
block = (struct stat_file_block *)c;
- for (i = 0; i < CHAIN_LENGTH; i ++) {
+ for (i = 0; i < CHAIN_LENGTH; i++) {
if (i + blocknum > file->cur_section.length) {
/* Need to expire some block in chain */
msg_debug ("statfile_pool_set_block: chain %u is full, starting expire", blocknum);
}
/* First try to find block in chain */
if (block->hash1 == h1 && block->hash2 == h2) {
- block->last_access = now - (time_t)header->create_time;
+ block->last_access = now - (time_t) header->create_time;
block->value = value;
return;
}
block->hash1 = h1;
block->hash2 = h2;
block->value = value;
- block->last_access = now - (time_t)header->create_time;
+ block->last_access = now - (time_t) header->create_time;
return;
}
if (block->last_access > oldest) {
}
else {
/* Expire first block in chain */
- c = (u_char *)file->map + file->seek_pos + blocknum * sizeof (struct stat_file_block);
+ c = (u_char *) file->map + file->seek_pos + blocknum * sizeof (struct stat_file_block);
block = (struct stat_file_block *)c;
}
- block->last_access = now - (time_t)header->create_time;
+ block->last_access = now - (time_t) header->create_time;
block->hash1 = h1;
block->hash2 = h2;
block->value = value;
}
-stat_file_t *
-statfile_pool_is_open (statfile_pool_t *pool, char *filename)
+stat_file_t *
+statfile_pool_is_open (statfile_pool_t * pool, char *filename)
{
- static stat_file_t f, *ret;
+ static stat_file_t f, *ret;
g_strlcpy (f.filename, filename, sizeof (f.filename));
ret = bsearch (&f, pool->files, pool->opened, sizeof (stat_file_t), cmpstatfile);
return ret;
}
uint32_t
-statfile_pool_get_section (statfile_pool_t *pool, stat_file_t *file)
+statfile_pool_get_section (statfile_pool_t * pool, stat_file_t * file)
{
return file->cur_section.code;
}
-gboolean
-statfile_pool_set_section (statfile_pool_t *pool, stat_file_t *file, uint32_t code, gboolean from_begin)
+gboolean
+statfile_pool_set_section (statfile_pool_t * pool, stat_file_t * file, uint32_t code, gboolean from_begin)
{
- struct stat_file_section *sec;
- off_t cur_offset;
+ struct stat_file_section *sec;
+ off_t cur_offset;
+
-
/* Try to find section */
if (from_begin) {
cur_offset = sizeof (struct stat_file_header);
return FALSE;
}
-gboolean
-statfile_pool_add_section (statfile_pool_t *pool, stat_file_t *file, uint32_t code, uint64_t length)
+gboolean
+statfile_pool_add_section (statfile_pool_t * pool, stat_file_t * file, uint32_t code, uint64_t length)
{
- struct stat_file_section sect;
- struct stat_file_block block = {0, 0, 0, 0};
-
+ struct stat_file_section sect;
+ struct stat_file_block block = { 0, 0, 0, 0 };
+
if (lseek (file->fd, 0, SEEK_END) == -1) {
msg_info ("statfile_pool_add_section: cannot lseek file %s, error %d, %s", file->filename, errno, strerror (errno));
return FALSE;
}
-
+
sect.code = code;
sect.length = length;
return FALSE;
}
- while (length --) {
+ while (length--) {
if (write (file->fd, &block, sizeof (block)) == -1) {
msg_info ("statfile_pool_add_section: cannot write block to file %s, error %d, %s", file->filename, errno, strerror (errno));
return FALSE;
}
}
-
+
/* Lock statfile to remap memory */
statfile_pool_lock_file (pool, file);
munmap (file->map, file->len);
fsync (file->fd);
file->len += length;
-
+
if (file->len > pool->max) {
msg_info ("statfile_pool_open: cannot attach file to pool, too large: %lu", (long int)file->len);
return FALSE;
}
-uint32_t
+uint32_t
statfile_get_section_by_name (const char *name)
{
if (g_ascii_strcasecmp (name, "common") == 0) {
#define MIN_CACHE 17
-static uint64_t total_frequency;
-static uint32_t nsymbols;
+static uint64_t total_frequency;
+static uint32_t nsymbols;
int
cache_cmp (const void *p1, const void *p2)
{
- const struct cache_item *i1 = p1, *i2 = p2;
-
+ const struct cache_item *i1 = p1, *i2 = p2;
+
return strcmp (i1->s->symbol, i2->s->symbol);
}
int
cache_logic_cmp (const void *p1, const void *p2)
{
- const struct cache_item *i1 = p1, *i2 = p2;
- double w1, w2;
- double f1 = 0, f2 = 0;
-
+ const struct cache_item *i1 = p1, *i2 = p2;
+ double w1, w2;
+ double f1 = 0, f2 = 0;
+
if (total_frequency > 0) {
f1 = ((double)i1->s->frequency * nsymbols) / (double)total_frequency;
f2 = ((double)i2->s->frequency * nsymbols) / (double)total_frequency;
}
- w1 = abs (i1->s->weight) * WEIGHT_MULT +
- f1 * FREQUENCY_MULT +
- i1->s->avg_time * TIME_MULT;
- w2 = abs (i2->s->weight) * WEIGHT_MULT +
- f2 * FREQUENCY_MULT +
- i2->s->avg_time * TIME_MULT;
-
+ w1 = abs (i1->s->weight) * WEIGHT_MULT + f1 * FREQUENCY_MULT + i1->s->avg_time * TIME_MULT;
+ w2 = abs (i2->s->weight) * WEIGHT_MULT + f2 * FREQUENCY_MULT + i2->s->avg_time * TIME_MULT;
+
return (int)w2 - w1;
}
static void
grow_cache (struct symbols_cache *cache)
{
- guint old = cache->cur_items, i;
- void *new;
+ guint old = cache->cur_items, i;
+ void *new;
cache->cur_items = cache->cur_items * 2;
new = g_new0 (struct cache_item, cache->cur_items);
cache->items = new;
/* Create new saved_cache_items */
- for (i = old; i < cache->cur_items; i ++) {
+ for (i = old; i < cache->cur_items; i++) {
cache->items[i].s = g_new0 (struct saved_cache_item, 1);
}
}
-static GChecksum *
+static GChecksum *
get_mem_cksum (struct symbols_cache *cache)
{
- int i;
- GChecksum *result;
-
+ int i;
+ GChecksum *result;
+
result = g_checksum_new (G_CHECKSUM_SHA1);
- for (i = 0; i < cache->used_items; i ++) {
+ for (i = 0; i < cache->used_items; i++) {
if (cache->items[i].s->symbol[0] != '\0') {
g_checksum_update (result, cache->items[i].s->symbol, strlen (cache->items[i].s->symbol));
}
static void
post_cache_init (struct symbols_cache *cache)
{
- int i;
-
+ int i;
+
total_frequency = 0;
nsymbols = cache->used_items;
- for (i = 0; i < cache->used_items; i ++) {
+ for (i = 0; i < cache->used_items; i++) {
total_frequency += cache->items[i].s->frequency;
}
qsort (cache->items, cache->used_items, sizeof (struct cache_item), cache_logic_cmp);
}
-static gboolean
+static gboolean
mmap_cache_file (struct symbols_cache *cache, int fd)
{
- void *map;
- int i;
+ void *map;
+ int i;
map = mmap (NULL, cache->used_items * sizeof (struct saved_cache_item), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (map == MAP_FAILED) {
/* Close descriptor as it would never be used */
close (fd);
/* Now free old values for saved cache items and fill them with mmapped ones */
- for (i = 0; i < cache->used_items; i ++) {
+ for (i = 0; i < cache->used_items; i++) {
g_free (cache->items[i].s);
cache->items[i].s = ((struct saved_cache_item *)map) + i;
}
}
/* Fd must be opened for writing, after creating file is mmapped */
-static gboolean
+static gboolean
create_cache_file (struct symbols_cache *cache, const char *filename, int fd)
{
- int i;
- GChecksum *cksum;
- u_char *digest;
- gsize cklen;
+ int i;
+ GChecksum *cksum;
+ u_char *digest;
+ gsize cklen;
/* Calculate checksum */
cksum = get_mem_cksum (cache);
g_checksum_get_digest (cksum, digest, &cklen);
/* Now write data to file */
- for (i = 0; i < cache->used_items; i ++) {
+ for (i = 0; i < cache->used_items; i++) {
if (write (fd, cache->items[i].s, sizeof (struct saved_cache_item)) == -1) {
msg_err ("create_cache_file: cannot write to file %d, %s", errno, strerror (errno));
close (fd);
return mmap_cache_file (cache, fd);
}
-void
+void
register_symbol (struct symbols_cache **cache, const char *name, double weight, symbol_func_t func, gpointer user_data)
{
- struct cache_item *item = NULL;
- int i;
-
+ struct cache_item *item = NULL;
+ int i;
+
if (*cache == NULL) {
*cache = g_new0 (struct symbols_cache, 1);
}
(*cache)->cur_items = MIN_CACHE;
(*cache)->used_items = 0;
(*cache)->items = g_new0 (struct cache_item, (*cache)->cur_items);
- for (i = 0; i < (*cache)->cur_items; i ++) {
+ for (i = 0; i < (*cache)->cur_items; i++) {
(*cache)->items[i].s = g_new0 (struct saved_cache_item, 1);
}
}
-
+
if ((*cache)->used_items >= (*cache)->cur_items) {
grow_cache (*cache);
/* Call once more */
}
item = &(*cache)->items[(*cache)->used_items];
-
+
g_strlcpy (item->s->symbol, name, sizeof (item->s->symbol));
item->func = func;
item->user_data = user_data;
item->s->weight = weight;
- (*cache)->used_items ++;
+ (*cache)->used_items++;
set_counter (item->s->symbol, 0);
}
-gboolean
-init_symbols_cache (memory_pool_t *pool, struct symbols_cache *cache, const char *filename)
+gboolean
+init_symbols_cache (memory_pool_t * pool, struct symbols_cache *cache, const char *filename)
{
- struct stat st;
- int fd;
- GChecksum *cksum;
- u_char *mem_sum, *file_sum;
- gsize cklen;
+ struct stat st;
+ int fd;
+ GChecksum *cksum;
+ u_char *mem_sum, *file_sum;
+ gsize cklen;
if (cache == NULL || cache->items == NULL) {
return FALSE;
}
-
+
/* Sort items in cache */
qsort (cache->items, cache->used_items, sizeof (struct cache_item), cache_cmp);
/* Init locking */
cache->lock = memory_pool_get_rwlock (pool);
-
+
/* Just in-memory cache */
if (filename == NULL) {
post_cache_init (cache);
/* Check errno */
if (errno == ENOENT) {
/* Try to create file */
- if ((fd = open (filename, O_RDWR | O_TRUNC | O_CREAT, S_IWUSR | S_IRUSR)) == -1 ) {
+ if ((fd = open (filename, O_RDWR | O_TRUNC | O_CREAT, S_IWUSR | S_IRUSR)) == -1) {
msg_info ("load_symbols_cache: cannot create file %s, error %d, %s", filename, errno, strerror (errno));
return FALSE;
}
g_checksum_free (cksum);
msg_info ("load_symbols_cache: checksum mismatch, recreating file");
/* Reopen with rw permissions */
- if ((fd = open (filename, O_RDWR | O_TRUNC | O_CREAT, S_IWUSR | S_IRUSR)) == -1 ) {
+ if ((fd = open (filename, O_RDWR | O_TRUNC | O_CREAT, S_IWUSR | S_IRUSR)) == -1) {
msg_info ("load_symbols_cache: cannot create file %s, error %d, %s", filename, errno, strerror (errno));
return FALSE;
}
}
gboolean
-call_symbol_callback (struct worker_task *task, struct symbols_cache *cache, struct cache_item **saved_item)
+call_symbol_callback (struct worker_task * task, struct symbols_cache * cache, struct cache_item ** saved_item)
{
- struct timespec ts1, ts2;
- uint64_t diff;
- struct cache_item *item;
+ struct timespec ts1, ts2;
+ uint64_t diff;
+ struct cache_item *item;
if (*saved_item == NULL) {
if (cache == NULL) {
return FALSE;
}
- if (cache->uses ++ >= MAX_USES) {
+ if (cache->uses++ >= MAX_USES) {
msg_info ("call_symbols_callback: resort symbols cache");
memory_pool_wlock_rwlock (cache->lock);
cache->uses = 0;
/* Minimum length of token */
#define MIN_LEN 4
-extern const int primes[];
+extern const int primes[];
int
-osb_tokenize_text (struct tokenizer *tokenizer, memory_pool_t *pool, f_str_t *input, GTree **tree)
+osb_tokenize_text (struct tokenizer *tokenizer, memory_pool_t * pool, f_str_t * input, GTree ** tree)
{
- token_node_t *new = NULL;
- f_str_t token = { NULL, 0, 0 }, *res;
- uint32_t hashpipe[FEATURE_WINDOW_SIZE], h1, h2;
- int i;
+ token_node_t *new = NULL;
+ f_str_t token = { NULL, 0, 0 }, *res;
+ uint32_t hashpipe[FEATURE_WINDOW_SIZE], h1, h2;
+ int i;
/* First set all bytes of hashpipe to some common value */
- for (i = 0; i < FEATURE_WINDOW_SIZE; i ++) {
+ for (i = 0; i < FEATURE_WINDOW_SIZE; i++) {
hashpipe[i] = 0xABCDEF;
}
-
+
if (*tree == NULL) {
*tree = g_tree_new (token_node_compare_func);
- memory_pool_add_destructor (pool, (pool_destruct_func)g_tree_destroy, *tree);
+ memory_pool_add_destructor (pool, (pool_destruct_func) g_tree_destroy, *tree);
}
msg_debug ("osb_tokenize_text: got input length: %zd", input->len);
continue;
}
/* Shift hashpipe */
- for (i = FEATURE_WINDOW_SIZE - 1; i > 0; i --) {
+ for (i = FEATURE_WINDOW_SIZE - 1; i > 0; i--) {
hashpipe[i] = hashpipe[i - 1];
}
hashpipe[0] = fstrhash (&token);
-
- for (i = 1; i < FEATURE_WINDOW_SIZE; i ++) {
- h1 = hashpipe[0]* primes[0] + hashpipe[i] * primes[i<<1];
- h2 = hashpipe[0] * primes[1] + hashpipe[i] * primes[(i<<1)-1];
+
+ for (i = 1; i < FEATURE_WINDOW_SIZE; i++) {
+ h1 = hashpipe[0] * primes[0] + hashpipe[i] * primes[i << 1];
+ h2 = hashpipe[0] * primes[1] + hashpipe[i] * primes[(i << 1) - 1];
new = memory_pool_alloc (pool, sizeof (token_node_t));
new->h1 = h1;
new->h2 = h2;
#include "../main.h"
#include "tokenizers.h"
-struct tokenizer tokenizers[] = {
- {"osb-text", osb_tokenize_text, get_next_word },
+struct tokenizer tokenizers[] = {
+ {"osb-text", osb_tokenize_text, get_next_word},
};
-const int primes[] = {
+const int primes[] = {
1, 7,
3, 13,
5, 29,
797, 3277,
};
-struct tokenizer*
+struct tokenizer *
get_tokenizer (char *name)
{
- int i;
+ int i;
- for (i = 0; i < sizeof (tokenizers) / sizeof (tokenizers[0]); i ++) {
+ for (i = 0; i < sizeof (tokenizers) / sizeof (tokenizers[0]); i++) {
if (strcmp (tokenizers[i].name, name) == 0) {
return &tokenizers[i];
}
return NULL;
}
-int
+int
token_node_compare_func (gconstpointer a, gconstpointer b)
{
- const token_node_t *aa = a, *bb = b;
-
+ const token_node_t *aa = a, *bb = b;
+
if (aa->h1 == bb->h1) {
return aa->h2 - bb->h2;
}
}
/* Get next word from specified f_str_t buf */
-f_str_t *
-get_next_word (f_str_t *buf, f_str_t *token)
+f_str_t *
+get_next_word (f_str_t * buf, f_str_t * token)
{
- size_t remain;
- unsigned char *pos;
-
+ size_t remain;
+ unsigned char *pos;
+
if (buf == NULL) {
return NULL;
}
token->begin = token->begin + token->len;
token->len = 0;
-
+
remain = buf->len - (token->begin - buf->begin);
if (remain <= 0) {
return NULL;
pos = token->begin;
/* Skip non graph symbols */
while (remain > 0 && (!g_ascii_isgraph (*pos) && *pos < 127)) {
- token->begin ++;
- pos ++;
- remain --;
+ token->begin++;
+ pos++;
+ remain--;
}
while (remain > 0 && (g_ascii_isgraph (*pos) || *pos > 127)) {
- token->len ++;
- pos ++;
- remain --;
+ token->len++;
+ pos++;
+ remain--;
}
if (token->len == 0) {
return NULL;
}
-
+
return token;
}
int
-tokenize_urls (memory_pool_t *pool, struct worker_task *task, GTree **tree)
+tokenize_urls (memory_pool_t * pool, struct worker_task *task, GTree ** tree)
{
- token_node_t *new = NULL;
- f_str_t url_domain;
- struct uri *url;
- GList *cur;
- uint32_t h;
+ token_node_t *new = NULL;
+ f_str_t url_domain;
+ struct uri *url;
+ GList *cur;
+ uint32_t h;
if (*tree == NULL) {
*tree = g_tree_new (token_node_compare_func);
- memory_pool_add_destructor (pool, (pool_destruct_func)g_tree_destroy, *tree);
+ memory_pool_add_destructor (pool, (pool_destruct_func) g_tree_destroy, *tree);
}
-
+
cur = task->urls;
while (cur) {
url = cur->data;
/* Struct to access gmime headers */
struct raw_header {
- struct raw_header *next;
- char *name;
- char *value;
+ struct raw_header *next;
+ char *name;
+ char *value;
};
typedef struct _GMimeHeader {
- GHashTable *hash;
- GHashTable *writers;
- struct raw_header *headers;
+ GHashTable *hash;
+ GHashTable *writers;
+ struct raw_header *headers;
} local_GMimeHeader;
int
-tokenize_headers (memory_pool_t *pool, struct worker_task *task, GTree **tree)
+tokenize_headers (memory_pool_t * pool, struct worker_task *task, GTree ** tree)
{
- token_node_t *new = NULL;
- f_str_t headername;
- f_str_t headervalue;
+ token_node_t *new = NULL;
+ f_str_t headername;
+ f_str_t headervalue;
if (*tree == NULL) {
*tree = g_tree_new (token_node_compare_func);
- memory_pool_add_destructor (pool, (pool_destruct_func)g_tree_destroy, *tree);
+ memory_pool_add_destructor (pool, (pool_destruct_func) g_tree_destroy, *tree);
}
#ifndef GMIME24
- struct raw_header *h;
+ struct raw_header *h;
- h = GMIME_OBJECT(task->message)->headers->headers;
+ h = GMIME_OBJECT (task->message)->headers->headers;
while (h) {
if (h->name && h->value) {
new = memory_pool_alloc (pool, sizeof (token_node_t));
h = h->next;
}
#else
- GMimeHeaderList *ls;
- GMimeHeaderIter *iter;
- const char *name;
- const char *value;
+ GMimeHeaderList *ls;
+ GMimeHeaderIter *iter;
+ const char *name;
+ const char *value;
- ls = GMIME_OBJECT(task->message)->headers;
+ ls = GMIME_OBJECT (task->message)->headers;
if (g_mime_header_list_get_iter (ls, iter)) {
while (g_mime_header_iter_is_valid (iter)) {
*/
#ifdef _THREAD_SAFE
-#include <pthread.h>
+# include <pthread.h>
#endif
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#ifdef HAVE_STDINT_H
-#include <stdint.h>
+# include <stdint.h>
#endif
#ifdef HAVE_INTTYPES_H
-#include <inttypes.h>
+# include <inttypes.h>
#endif
#include <limits.h>
#ifdef WITH_DEBUG
-#include <syslog.h>
+# include <syslog.h>
#endif
#include "upstream.h"
#ifdef WITH_DEBUG
-#define msg_debug(args...) syslog(LOG_DEBUG, ##args)
+# define msg_debug(args...) syslog(LOG_DEBUG, ##args)
#else
-#define msg_debug(args...) do {} while(0)
+# define msg_debug(args...) do {} while(0)
#endif
#ifdef _THREAD_SAFE
-pthread_rwlock_t upstream_mtx = PTHREAD_RWLOCK_INITIALIZER;
-#define U_RLOCK() do { pthread_rwlock_rdlock (&upstream_mtx); } while (0)
-#define U_WLOCK() do { pthread_rwlock_wrlock (&upstream_mtx); } while (0)
-#define U_UNLOCK() do { pthread_rwlock_unlock (&upstream_mtx); } while (0)
+pthread_rwlock_t upstream_mtx = PTHREAD_RWLOCK_INITIALIZER;
+# define U_RLOCK() do { pthread_rwlock_rdlock (&upstream_mtx); } while (0)
+# define U_WLOCK() do { pthread_rwlock_wrlock (&upstream_mtx); } while (0)
+# define U_UNLOCK() do { pthread_rwlock_unlock (&upstream_mtx); } while (0)
#else
-#define U_RLOCK() do {} while (0)
-#define U_WLOCK() do {} while (0)
-#define U_UNLOCK() do {} while (0)
+# define U_RLOCK() do {} while (0)
+# define U_WLOCK() do {} while (0)
+# define U_UNLOCK() do {} while (0)
#endif
#define MAX_TRIES 20
* Init: 0x0
*/
-static const uint32_t crc32lookup[256] = {
- 0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x076dc419U, 0x706af48fU,
- 0xe963a535U, 0x9e6495a3U, 0x0edb8832U, 0x79dcb8a4U, 0xe0d5e91eU, 0x97d2d988U,
- 0x09b64c2bU, 0x7eb17cbdU, 0xe7b82d07U, 0x90bf1d91U, 0x1db71064U, 0x6ab020f2U,
- 0xf3b97148U, 0x84be41deU, 0x1adad47dU, 0x6ddde4ebU, 0xf4d4b551U, 0x83d385c7U,
- 0x136c9856U, 0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU, 0x14015c4fU, 0x63066cd9U,
- 0xfa0f3d63U, 0x8d080df5U, 0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U, 0xa2677172U,
- 0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU, 0x35b5a8faU, 0x42b2986cU,
- 0xdbbbc9d6U, 0xacbcf940U, 0x32d86ce3U, 0x45df5c75U, 0xdcd60dcfU, 0xabd13d59U,
- 0x26d930acU, 0x51de003aU, 0xc8d75180U, 0xbfd06116U, 0x21b4f4b5U, 0x56b3c423U,
- 0xcfba9599U, 0xb8bda50fU, 0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0xb10be924U,
- 0x2f6f7c87U, 0x58684c11U, 0xc1611dabU, 0xb6662d3dU, 0x76dc4190U, 0x01db7106U,
- 0x98d220bcU, 0xefd5102aU, 0x71b18589U, 0x06b6b51fU, 0x9fbfe4a5U, 0xe8b8d433U,
- 0x7807c9a2U, 0x0f00f934U, 0x9609a88eU, 0xe10e9818U, 0x7f6a0dbbU, 0x086d3d2dU,
- 0x91646c97U, 0xe6635c01U, 0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0xf262004eU,
- 0x6c0695edU, 0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U, 0x65b0d9c6U, 0x12b7e950U,
- 0x8bbeb8eaU, 0xfcb9887cU, 0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U, 0xfbd44c65U,
- 0x4db26158U, 0x3ab551ceU, 0xa3bc0074U, 0xd4bb30e2U, 0x4adfa541U, 0x3dd895d7U,
- 0xa4d1c46dU, 0xd3d6f4fbU, 0x4369e96aU, 0x346ed9fcU, 0xad678846U, 0xda60b8d0U,
- 0x44042d73U, 0x33031de5U, 0xaa0a4c5fU, 0xdd0d7cc9U, 0x5005713cU, 0x270241aaU,
- 0xbe0b1010U, 0xc90c2086U, 0x5768b525U, 0x206f85b3U, 0xb966d409U, 0xce61e49fU,
- 0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 0x59b33d17U, 0x2eb40d81U,
- 0xb7bd5c3bU, 0xc0ba6cadU, 0xedb88320U, 0x9abfb3b6U, 0x03b6e20cU, 0x74b1d29aU,
- 0xead54739U, 0x9dd277afU, 0x04db2615U, 0x73dc1683U, 0xe3630b12U, 0x94643b84U,
- 0x0d6d6a3eU, 0x7a6a5aa8U, 0xe40ecf0bU, 0x9309ff9dU, 0x0a00ae27U, 0x7d079eb1U,
- 0xf00f9344U, 0x8708a3d2U, 0x1e01f268U, 0x6906c2feU, 0xf762575dU, 0x806567cbU,
- 0x196c3671U, 0x6e6b06e7U, 0xfed41b76U, 0x89d32be0U, 0x10da7a5aU, 0x67dd4accU,
- 0xf9b9df6fU, 0x8ebeeff9U, 0x17b7be43U, 0x60b08ed5U, 0xd6d6a3e8U, 0xa1d1937eU,
- 0x38d8c2c4U, 0x4fdff252U, 0xd1bb67f1U, 0xa6bc5767U, 0x3fb506ddU, 0x48b2364bU,
- 0xd80d2bdaU, 0xaf0a1b4cU, 0x36034af6U, 0x41047a60U, 0xdf60efc3U, 0xa867df55U,
- 0x316e8eefU, 0x4669be79U, 0xcb61b38cU, 0xbc66831aU, 0x256fd2a0U, 0x5268e236U,
- 0xcc0c7795U, 0xbb0b4703U, 0x220216b9U, 0x5505262fU, 0xc5ba3bbeU, 0xb2bd0b28U,
- 0x2bb45a92U, 0x5cb36a04U, 0xc2d7ffa7U, 0xb5d0cf31U, 0x2cd99e8bU, 0x5bdeae1dU,
- 0x9b64c2b0U, 0xec63f226U, 0x756aa39cU, 0x026d930aU, 0x9c0906a9U, 0xeb0e363fU,
- 0x72076785U, 0x05005713U, 0x95bf4a82U, 0xe2b87a14U, 0x7bb12baeU, 0x0cb61b38U,
- 0x92d28e9bU, 0xe5d5be0dU, 0x7cdcefb7U, 0x0bdbdf21U, 0x86d3d2d4U, 0xf1d4e242U,
- 0x68ddb3f8U, 0x1fda836eU, 0x81be16cdU, 0xf6b9265bU, 0x6fb077e1U, 0x18b74777U,
- 0x88085ae6U, 0xff0f6a70U, 0x66063bcaU, 0x11010b5cU, 0x8f659effU, 0xf862ae69U,
- 0x616bffd3U, 0x166ccf45U, 0xa00ae278U, 0xd70dd2eeU, 0x4e048354U, 0x3903b3c2U,
- 0xa7672661U, 0xd06016f7U, 0x4969474dU, 0x3e6e77dbU, 0xaed16a4aU, 0xd9d65adcU,
- 0x40df0b66U, 0x37d83bf0U, 0xa9bcae53U, 0xdebb9ec5U, 0x47b2cf7fU, 0x30b5ffe9U,
- 0xbdbdf21cU, 0xcabac28aU, 0x53b39330U, 0x24b4a3a6U, 0xbad03605U, 0xcdd70693U,
- 0x54de5729U, 0x23d967bfU, 0xb3667a2eU, 0xc4614ab8U, 0x5d681b02U, 0x2a6f2b94U,
- 0xb40bbe37U, 0xc30c8ea1U, 0x5a05df1bU, 0x2d02ef8dU
+static const uint32_t crc32lookup[256] = {
+ 0x00000000U, 0x77073096U, 0xee0e612cU, 0x990951baU, 0x076dc419U, 0x706af48fU,
+ 0xe963a535U, 0x9e6495a3U, 0x0edb8832U, 0x79dcb8a4U, 0xe0d5e91eU, 0x97d2d988U,
+ 0x09b64c2bU, 0x7eb17cbdU, 0xe7b82d07U, 0x90bf1d91U, 0x1db71064U, 0x6ab020f2U,
+ 0xf3b97148U, 0x84be41deU, 0x1adad47dU, 0x6ddde4ebU, 0xf4d4b551U, 0x83d385c7U,
+ 0x136c9856U, 0x646ba8c0U, 0xfd62f97aU, 0x8a65c9ecU, 0x14015c4fU, 0x63066cd9U,
+ 0xfa0f3d63U, 0x8d080df5U, 0x3b6e20c8U, 0x4c69105eU, 0xd56041e4U, 0xa2677172U,
+ 0x3c03e4d1U, 0x4b04d447U, 0xd20d85fdU, 0xa50ab56bU, 0x35b5a8faU, 0x42b2986cU,
+ 0xdbbbc9d6U, 0xacbcf940U, 0x32d86ce3U, 0x45df5c75U, 0xdcd60dcfU, 0xabd13d59U,
+ 0x26d930acU, 0x51de003aU, 0xc8d75180U, 0xbfd06116U, 0x21b4f4b5U, 0x56b3c423U,
+ 0xcfba9599U, 0xb8bda50fU, 0x2802b89eU, 0x5f058808U, 0xc60cd9b2U, 0xb10be924U,
+ 0x2f6f7c87U, 0x58684c11U, 0xc1611dabU, 0xb6662d3dU, 0x76dc4190U, 0x01db7106U,
+ 0x98d220bcU, 0xefd5102aU, 0x71b18589U, 0x06b6b51fU, 0x9fbfe4a5U, 0xe8b8d433U,
+ 0x7807c9a2U, 0x0f00f934U, 0x9609a88eU, 0xe10e9818U, 0x7f6a0dbbU, 0x086d3d2dU,
+ 0x91646c97U, 0xe6635c01U, 0x6b6b51f4U, 0x1c6c6162U, 0x856530d8U, 0xf262004eU,
+ 0x6c0695edU, 0x1b01a57bU, 0x8208f4c1U, 0xf50fc457U, 0x65b0d9c6U, 0x12b7e950U,
+ 0x8bbeb8eaU, 0xfcb9887cU, 0x62dd1ddfU, 0x15da2d49U, 0x8cd37cf3U, 0xfbd44c65U,
+ 0x4db26158U, 0x3ab551ceU, 0xa3bc0074U, 0xd4bb30e2U, 0x4adfa541U, 0x3dd895d7U,
+ 0xa4d1c46dU, 0xd3d6f4fbU, 0x4369e96aU, 0x346ed9fcU, 0xad678846U, 0xda60b8d0U,
+ 0x44042d73U, 0x33031de5U, 0xaa0a4c5fU, 0xdd0d7cc9U, 0x5005713cU, 0x270241aaU,
+ 0xbe0b1010U, 0xc90c2086U, 0x5768b525U, 0x206f85b3U, 0xb966d409U, 0xce61e49fU,
+ 0x5edef90eU, 0x29d9c998U, 0xb0d09822U, 0xc7d7a8b4U, 0x59b33d17U, 0x2eb40d81U,
+ 0xb7bd5c3bU, 0xc0ba6cadU, 0xedb88320U, 0x9abfb3b6U, 0x03b6e20cU, 0x74b1d29aU,
+ 0xead54739U, 0x9dd277afU, 0x04db2615U, 0x73dc1683U, 0xe3630b12U, 0x94643b84U,
+ 0x0d6d6a3eU, 0x7a6a5aa8U, 0xe40ecf0bU, 0x9309ff9dU, 0x0a00ae27U, 0x7d079eb1U,
+ 0xf00f9344U, 0x8708a3d2U, 0x1e01f268U, 0x6906c2feU, 0xf762575dU, 0x806567cbU,
+ 0x196c3671U, 0x6e6b06e7U, 0xfed41b76U, 0x89d32be0U, 0x10da7a5aU, 0x67dd4accU,
+ 0xf9b9df6fU, 0x8ebeeff9U, 0x17b7be43U, 0x60b08ed5U, 0xd6d6a3e8U, 0xa1d1937eU,
+ 0x38d8c2c4U, 0x4fdff252U, 0xd1bb67f1U, 0xa6bc5767U, 0x3fb506ddU, 0x48b2364bU,
+ 0xd80d2bdaU, 0xaf0a1b4cU, 0x36034af6U, 0x41047a60U, 0xdf60efc3U, 0xa867df55U,
+ 0x316e8eefU, 0x4669be79U, 0xcb61b38cU, 0xbc66831aU, 0x256fd2a0U, 0x5268e236U,
+ 0xcc0c7795U, 0xbb0b4703U, 0x220216b9U, 0x5505262fU, 0xc5ba3bbeU, 0xb2bd0b28U,
+ 0x2bb45a92U, 0x5cb36a04U, 0xc2d7ffa7U, 0xb5d0cf31U, 0x2cd99e8bU, 0x5bdeae1dU,
+ 0x9b64c2b0U, 0xec63f226U, 0x756aa39cU, 0x026d930aU, 0x9c0906a9U, 0xeb0e363fU,
+ 0x72076785U, 0x05005713U, 0x95bf4a82U, 0xe2b87a14U, 0x7bb12baeU, 0x0cb61b38U,
+ 0x92d28e9bU, 0xe5d5be0dU, 0x7cdcefb7U, 0x0bdbdf21U, 0x86d3d2d4U, 0xf1d4e242U,
+ 0x68ddb3f8U, 0x1fda836eU, 0x81be16cdU, 0xf6b9265bU, 0x6fb077e1U, 0x18b74777U,
+ 0x88085ae6U, 0xff0f6a70U, 0x66063bcaU, 0x11010b5cU, 0x8f659effU, 0xf862ae69U,
+ 0x616bffd3U, 0x166ccf45U, 0xa00ae278U, 0xd70dd2eeU, 0x4e048354U, 0x3903b3c2U,
+ 0xa7672661U, 0xd06016f7U, 0x4969474dU, 0x3e6e77dbU, 0xaed16a4aU, 0xd9d65adcU,
+ 0x40df0b66U, 0x37d83bf0U, 0xa9bcae53U, 0xdebb9ec5U, 0x47b2cf7fU, 0x30b5ffe9U,
+ 0xbdbdf21cU, 0xcabac28aU, 0x53b39330U, 0x24b4a3a6U, 0xbad03605U, 0xcdd70693U,
+ 0x54de5729U, 0x23d967bfU, 0xb3667a2eU, 0xc4614ab8U, 0x5d681b02U, 0x2a6f2b94U,
+ 0xb40bbe37U, 0xc30c8ea1U, 0x5a05df1bU, 0x2d02ef8dU
};
/*
{
if (up->dead) {
if (now - up->time >= revive_timeout) {
- msg_debug ("check_upstream: reviving upstream after %ld seconds", (long int) now - up->time);
+ msg_debug ("check_upstream: reviving upstream after %ld seconds", (long int)now - up->time);
U_WLOCK ();
up->dead = 0;
up->errors = 0;
}
else {
if (now - up->time >= error_timeout && up->errors >= max_errors) {
- msg_debug ("check_upstream: marking upstreams as dead after %ld errors", (long int) up->errors);
+ msg_debug ("check_upstream: marking upstreams as dead after %ld errors", (long int)up->errors);
U_WLOCK ();
up->dead = 1;
up->time = now;
upstream_fail (struct upstream *up, time_t now)
{
if (up->time != 0) {
- up->errors ++;
+ up->errors++;
}
else {
U_WLOCK ();
up->time = now;
- up->errors ++;
+ up->errors++;
U_UNLOCK ();
}
}
+
/*
* Call this function after successfull upstream request
*/
U_UNLOCK ();
}
- up->weight --;
+ up->weight--;
}
+
/*
* Mark all upstreams as active. This function is used when all upstreams are marked as inactive
*/
void
-revive_all_upstreams (void *ups, size_t members, size_t msize)
+revive_all_upstreams (void *ups, size_t members, size_t msize)
{
- int i;
- struct upstream *cur;
- u_char *p;
+ int i;
+ struct upstream *cur;
+ u_char *p;
U_WLOCK ();
msg_debug ("revive_all_upstreams: starting reviving all upstreams");
*/
static int
rescan_upstreams (void *ups, size_t members, size_t msize, time_t now, time_t error_timeout, time_t revive_timeout, size_t max_errors)
-{
- int i, alive;
- struct upstream *cur;
- u_char *p;
-
+{
+ int i, alive;
+ struct upstream *cur;
+ u_char *p;
+
/* Recheck all upstreams */
p = ups;
alive = members;
alive -= cur->dead;
p += msize;
}
-
+
/* All upstreams are dead */
if (alive == 0) {
revive_all_upstreams (ups, members, msize);
}
msg_debug ("rescan_upstreams: %d upstreams alive", alive);
-
+
return alive;
}
/* Return alive upstream by its number */
-static struct upstream *
+static struct upstream *
get_upstream_by_number (void *ups, size_t members, size_t msize, int selected)
{
- int i;
- u_char *p, *c;
- struct upstream *cur;
+ int i;
+ u_char *p, *c;
+ struct upstream *cur;
i = 0;
p = ups;
/*
* Get hash key for specified key (perl hash)
*/
-static uint32_t
+static uint32_t
get_hash_for_key (uint32_t hash, char *key, size_t keylen)
{
- uint32_t h, index;
- const char *end = key + keylen;
+ uint32_t h, index;
+ const char *end = key + keylen;
h = ~hash;
while (key < end) {
- index = (h ^ (u_char) *key) & 0x000000ffU;
+ index = (h ^ (u_char) * key) & 0x000000ffU;
h = (h >> 8) ^ crc32lookup[index];
++key;
}
/*
* Recheck all upstreams and return random active upstream
*/
-struct upstream *
+struct upstream *
get_random_upstream (void *ups, size_t members, size_t msize, time_t now, time_t error_timeout, time_t revive_timeout, size_t max_errors)
{
- int alive, selected;
-
+ int alive, selected;
+
alive = rescan_upstreams (ups, members, msize, now, error_timeout, revive_timeout, max_errors);
selected = rand () % alive;
msg_debug ("get_random_upstream: return upstream with number %d of %d", selected, alive);
-
- return get_upstream_by_number (ups, members, msize, selected);
+
+ return get_upstream_by_number (ups, members, msize, selected);
}
/*
* Return upstream by hash, that is calculated from active upstreams number
*/
-struct upstream *
-get_upstream_by_hash (void *ups, size_t members, size_t msize, time_t now,
- time_t error_timeout, time_t revive_timeout, size_t max_errors,
- char *key, size_t keylen)
+struct upstream *
+get_upstream_by_hash (void *ups, size_t members, size_t msize, time_t now, time_t error_timeout, time_t revive_timeout, size_t max_errors, char *key, size_t keylen)
{
- int alive, tries = 0, r;
- uint32_t h = 0, ht;
- char *p, numbuf[4];
- struct upstream *cur;
-
+ int alive, tries = 0, r;
+ uint32_t h = 0, ht;
+ char *p, numbuf[4];
+ struct upstream *cur;
+
alive = rescan_upstreams (ups, members, msize, now, error_timeout, revive_timeout, max_errors);
if (alive == 0) {
#endif
h %= members;
msg_debug ("get_upstream_by_hash: try to select upstream number %d of %zd, tries: %d", h, members, tries);
- tries ++;
+ tries++;
if (tries > MAX_TRIES) {
msg_debug ("get_upstream_by_hash: max tries exceed, returning NULL");
return NULL;
}
}
-
+
U_RLOCK ();
p = ups;
U_UNLOCK ();
/*
* Recheck all upstreams and return upstream in round-robin order according to weight and priority
*/
-struct upstream *
+struct upstream *
get_upstream_round_robin (void *ups, size_t members, size_t msize, time_t now, time_t error_timeout, time_t revive_timeout, size_t max_errors)
{
- int alive, max_weight, i;
- struct upstream *cur, *selected = NULL;
- u_char *p;
-
+ int alive, max_weight, i;
+ struct upstream *cur, *selected = NULL;
+ u_char *p;
+
/* Recheck all upstreams */
alive = rescan_upstreams (ups, members, msize, now, error_timeout, revive_timeout, max_errors);
p = ups;
U_WLOCK ();
for (i = 0; i < members; i++) {
- cur = (struct upstream *)p;
+ cur = (struct upstream *)p;
cur->weight = cur->priority;
if (!cur->dead) {
if (max_weight < cur->priority) {
/*
* Recheck all upstreams and return upstream in round-robin order according to only priority (master-slaves)
*/
-struct upstream *
+struct upstream *
get_upstream_master_slave (void *ups, size_t members, size_t msize, time_t now, time_t error_timeout, time_t revive_timeout, size_t max_errors)
{
- int alive, max_weight, i;
- struct upstream *cur, *selected = NULL;
- u_char *p;
-
+ int alive, max_weight, i;
+ struct upstream *cur, *selected = NULL;
+ u_char *p;
+
/* Recheck all upstreams */
alive = rescan_upstreams (ups, members, msize, now, error_timeout, revive_timeout, max_errors);
static int
ketama_sort_cmp (const void *a1, const void *a2)
{
- return *((uint32_t *)a1) - *((uint32_t *)a2);
+ return *((uint32_t *) a1) - *((uint32_t *) a2);
}
/*
int
upstream_ketama_add (struct upstream *up, char *up_key, size_t keylen, size_t keypoints)
{
- uint32_t h = 0;
- char tmp[4];
- int i;
+ uint32_t h = 0;
+ char tmp[4];
+ int i;
/* Allocate ketama points array */
if (up->ketama_points == NULL) {
tmp[1] = (i >> 8) & 0xff;
tmp[2] = (i >> 16) & 0xff;
tmp[3] = (i >> 24) & 0xff;
-
+
h = get_hash_for_key (h, tmp, sizeof (tmp) * sizeof (char));
up->ketama_points[i] = h;
}
/*
* Return upstream by hash and find nearest ketama point in some server
*/
-struct upstream *
-get_upstream_by_hash_ketama (void *ups, size_t members, size_t msize, time_t now,
- time_t error_timeout, time_t revive_timeout, size_t max_errors,
- char *key, size_t keylen)
+struct upstream *
+get_upstream_by_hash_ketama (void *ups, size_t members, size_t msize, time_t now, time_t error_timeout, time_t revive_timeout, size_t max_errors, char *key, size_t keylen)
{
- int alive, i;
- uint32_t h = 0, step, middle, d, min_diff = UINT_MAX;
- char *p;
- struct upstream *cur = NULL, *nearest = NULL;
-
+ int alive, i;
+ uint32_t h = 0, step, middle, d, min_diff = UINT_MAX;
+ char *p;
+ struct upstream *cur = NULL, *nearest = NULL;
+
alive = rescan_upstreams (ups, members, msize, now, error_timeout, revive_timeout, max_errors);
if (alive == 0) {
}
h = get_hash_for_key (h, key, keylen);
-
+
U_RLOCK ();
p = ups;
nearest = (struct upstream *)p;
(LOWEST_PORT <= (port) && (port) <= HIGHEST_PORT)
struct _proto {
- unsigned char *name;
- int port;
- uintptr_t *unused;
- unsigned int need_slashes:1;
- unsigned int need_slash_after_host:1;
- unsigned int free_syntax:1;
- unsigned int need_ssl:1;
+ unsigned char *name;
+ int port;
+ uintptr_t *unused;
+ unsigned int need_slashes:1;
+ unsigned int need_slash_after_host:1;
+ unsigned int free_syntax:1;
+ unsigned int need_ssl:1;
};
-static const char *text_url = "((https?|ftp)://)?"
-"(\\b(?<![.\\@A-Za-z0-9-])"
-"(?: [A-Za-z0-9][A-Za-z0-9-]*(?:\\.[A-Za-z0-9-]+)*\\."
-"(?i:com|net|org|biz|edu|gov|info|name|int|mil|aero|coop|jobs|mobi|museum|pro|travel"
-"|cc|[rs]u|uk|ua|by|de|jp|fr|fi|no|no|ca|it|ro|cn|nl|at|nu|se"
-"|[a-z]{2}"
-"(?(1)|(?=/)))"
-"(?!\\w)"
-"|(?:\\d{1,3}\\.){3}\\d{1,3}(?(1)|(?=[/:]))" /* ip in dotted view */
-"|\\d{5,20}(?(1)|(?=[/:]))" /* ip in numeric view */
-")"
-"(?::\\d{1,5})?" /* port */
-"(?!\\.\\w)" /* host part ended, no more of this further on */
-"(?:[/?][;/?:@&=+\\$,[\\]\\-_.!~*'()A-Za-z0-9#%]*)?" /* path (&query) */
-"(?<![\\s>?!),.'\"\\]:])"
-"(?!@)"
-")";
-static const char *html_url = "(?: src|href)=\"?("
-"((https?|ftp)://)?"
-"(\\b(?<![.\\@A-Za-z0-9-])"
-"(?: [A-Za-z0-9][A-Za-z0-9-]*(?:\\.[A-Za-z0-9-]+)*\\."
-"(?i:com|net|org|biz|edu|gov|info|name|int|mil|aero|coop|jobs|mobi|museum|pro|travel"
-"|[rs]u|uk|ua|by|de|jp|fr|fi|no|no|ca|it|ro|cn|nl|at|nu|se"
-"|[a-z]{2}"
-"(?(1)|(?=/)))"
-"(?!\\w)"
-"|(?:\\d{1,3}\\.){3}\\d{1,3}(?(1)|(?=[/:]))"
-")"
-"(?::\\d{1,5})?" /* port */
-"(?!\\.\\w)" /* host part ended, no more of this further on */
-"(?:[/?][;/?:@&=+\\$,[\\]\\-_.!~*'()A-Za-z0-9#%]*)?" /* path (&query) */
-"(?<![\\s>?!),.'\"\\]:])"
-"(?!@)"
-"))\"?";
-
-static short url_initialized = 0;
-GRegex *text_re, *html_re;
-
-static const struct _proto protocol_backends[] = {
- { "file", 0, NULL, 1, 0, 0, 0 },
- { "ftp", 21, NULL, 1, 1, 0, 0 },
- { "http", 80, NULL, 1, 1, 0, 0 },
- { "https", 443, NULL, 1, 1, 0, 1 },
+static const char *text_url = "((https?|ftp)://)?" "(\\b(?<![.\\@A-Za-z0-9-])" "(?: [A-Za-z0-9][A-Za-z0-9-]*(?:\\.[A-Za-z0-9-]+)*\\." "(?i:com|net|org|biz|edu|gov|info|name|int|mil|aero|coop|jobs|mobi|museum|pro|travel" "|cc|[rs]u|uk|ua|by|de|jp|fr|fi|no|no|ca|it|ro|cn|nl|at|nu|se" "|[a-z]{2}" "(?(1)|(?=/)))" "(?!\\w)" "|(?:\\d{1,3}\\.){3}\\d{1,3}(?(1)|(?=[/:]))" /* ip in dotted view */
+ "|\\d{5,20}(?(1)|(?=[/:]))" /* ip in numeric view */
+ ")" "(?::\\d{1,5})?" /* port */
+ "(?!\\.\\w)" /* host part ended, no more of this further on */
+ "(?:[/?][;/?:@&=+\\$,[\\]\\-_.!~*'()A-Za-z0-9#%]*)?" /* path (&query) */
+ "(?<![\\s>?!),.'\"\\]:])" "(?!@)" ")";
+static const char *html_url = "(?: src|href)=\"?(" "((https?|ftp)://)?" "(\\b(?<![.\\@A-Za-z0-9-])" "(?: [A-Za-z0-9][A-Za-z0-9-]*(?:\\.[A-Za-z0-9-]+)*\\." "(?i:com|net|org|biz|edu|gov|info|name|int|mil|aero|coop|jobs|mobi|museum|pro|travel" "|[rs]u|uk|ua|by|de|jp|fr|fi|no|no|ca|it|ro|cn|nl|at|nu|se" "|[a-z]{2}" "(?(1)|(?=/)))" "(?!\\w)" "|(?:\\d{1,3}\\.){3}\\d{1,3}(?(1)|(?=[/:]))" ")" "(?::\\d{1,5})?" /* port */
+ "(?!\\.\\w)" /* host part ended, no more of this further on */
+ "(?:[/?][;/?:@&=+\\$,[\\]\\-_.!~*'()A-Za-z0-9#%]*)?" /* path (&query) */
+ "(?<![\\s>?!),.'\"\\]:])" "(?!@)" "))\"?";
+
+static short url_initialized = 0;
+GRegex *text_re, *html_re;
+
+static const struct _proto protocol_backends[] = {
+ {"file", 0, NULL, 1, 0, 0, 0},
+ {"ftp", 21, NULL, 1, 1, 0, 0},
+ {"http", 80, NULL, 1, 1, 0, 0},
+ {"https", 443, NULL, 1, 1, 0, 1},
/* Keep these last! */
- { NULL, 0, NULL, 0, 0, 1, 0 },
+ {NULL, 0, NULL, 0, 0, 1, 0},
};
/*
lookup. This code assumes ASCII character set and 8-bit chars. */
enum {
- /* rfc1738 reserved chars + "$" and ",". */
- urlchr_reserved = 1,
+ /* rfc1738 reserved chars + "$" and ",". */
+ urlchr_reserved = 1,
- /* rfc1738 unsafe chars, plus non-printables. */
- urlchr_unsafe = 2
+ /* rfc1738 unsafe chars, plus non-printables. */
+ urlchr_unsafe = 2
};
#define urlchr_test(c, mask) (urlchr_table[(unsigned char)(c)] & (mask))
#define U urlchr_unsafe
#define RU R|U
-static const unsigned char urlchr_table[256] =
-{
- U, U, U, U, U, U, U, U, /* NUL SOH STX ETX EOT ENQ ACK BEL */
- U, U, U, U, U, U, U, U, /* BS HT LF VT FF CR SO SI */
- U, U, U, U, U, U, U, U, /* DLE DC1 DC2 DC3 DC4 NAK SYN ETB */
- U, U, U, U, U, U, U, U, /* CAN EM SUB ESC FS GS RS US */
- U, 0, U, RU, R, U, R, 0, /* SP ! " # $ % & ' */
- 0, 0, 0, R, R, 0, 0, R, /* ( ) * + , - . / */
- 0, 0, 0, 0, 0, 0, 0, 0, /* 0 1 2 3 4 5 6 7 */
- 0, 0, RU, R, U, R, U, R, /* 8 9 : ; < = > ? */
- RU, 0, 0, 0, 0, 0, 0, 0, /* @ A B C D E F G */
- 0, 0, 0, 0, 0, 0, 0, 0, /* H I J K L M N O */
- 0, 0, 0, 0, 0, 0, 0, 0, /* P Q R S T U V W */
- 0, 0, 0, RU, U, RU, U, 0, /* X Y Z [ \ ] ^ _ */
- U, 0, 0, 0, 0, 0, 0, 0, /* ` a b c d e f g */
- 0, 0, 0, 0, 0, 0, 0, 0, /* h i j k l m n o */
- 0, 0, 0, 0, 0, 0, 0, 0, /* p q r s t u v w */
- 0, 0, 0, U, U, U, 0, U, /* x y z { | } ~ DEL */
-
- U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U,
- U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U,
- U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U,
- U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U,
-
- U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U,
- U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U,
- U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U,
- U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U,
+static const unsigned char urlchr_table[256] = {
+ U, U, U, U, U, U, U, U, /* NUL SOH STX ETX EOT ENQ ACK BEL */
+ U, U, U, U, U, U, U, U, /* BS HT LF VT FF CR SO SI */
+ U, U, U, U, U, U, U, U, /* DLE DC1 DC2 DC3 DC4 NAK SYN ETB */
+ U, U, U, U, U, U, U, U, /* CAN EM SUB ESC FS GS RS US */
+ U, 0, U, RU, R, U, R, 0, /* SP ! " # $ % & ' */
+ 0, 0, 0, R, R, 0, 0, R, /* ( ) * + , - . / */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* 0 1 2 3 4 5 6 7 */
+ 0, 0, RU, R, U, R, U, R, /* 8 9 : ; < = > ? */
+ RU, 0, 0, 0, 0, 0, 0, 0, /* @ A B C D E F G */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* H I J K L M N O */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* P Q R S T U V W */
+ 0, 0, 0, RU, U, RU, U, 0, /* X Y Z [ \ ] ^ _ */
+ U, 0, 0, 0, 0, 0, 0, 0, /* ` a b c d e f g */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* h i j k l m n o */
+ 0, 0, 0, 0, 0, 0, 0, 0, /* p q r s t u v w */
+ 0, 0, 0, U, U, U, 0, U, /* x y z { | } ~ DEL */
+
+ U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U,
+ U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U,
+ U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U,
+ U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U,
+
+ U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U,
+ U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U,
+ U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U,
+ U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U,
};
+
#undef R
#undef U
#undef RU
-static const char *
+static const char *
url_strerror (enum uri_errno err)
{
switch (err) {
- case URI_ERRNO_OK:
- return "Parsing went well";
- case URI_ERRNO_EMPTY:
- return "The URI string was empty";
- case URI_ERRNO_INVALID_PROTOCOL:
- return "No protocol was found";
- case URI_ERRNO_NO_SLASHES:
- return "Slashes after protocol missing";
- case URI_ERRNO_TOO_MANY_SLASHES:
- return "Too many slashes after protocol";
- case URI_ERRNO_TRAILING_DOTS:
- return "'.' after host";
- case URI_ERRNO_NO_HOST:
- return "Host part is missing";
- case URI_ERRNO_NO_PORT_COLON:
- return "':' after host without port";
- case URI_ERRNO_NO_HOST_SLASH:
- return "Slash after host missing";
- case URI_ERRNO_IPV6_SECURITY:
- return "IPv6 security bug detected";
- case URI_ERRNO_INVALID_PORT:
- return "Port number is bad";
- case URI_ERRNO_INVALID_PORT_RANGE:
- return "Port number is not within 0-65535";
+ case URI_ERRNO_OK:
+ return "Parsing went well";
+ case URI_ERRNO_EMPTY:
+ return "The URI string was empty";
+ case URI_ERRNO_INVALID_PROTOCOL:
+ return "No protocol was found";
+ case URI_ERRNO_NO_SLASHES:
+ return "Slashes after protocol missing";
+ case URI_ERRNO_TOO_MANY_SLASHES:
+ return "Too many slashes after protocol";
+ case URI_ERRNO_TRAILING_DOTS:
+ return "'.' after host";
+ case URI_ERRNO_NO_HOST:
+ return "Host part is missing";
+ case URI_ERRNO_NO_PORT_COLON:
+ return "':' after host without port";
+ case URI_ERRNO_NO_HOST_SLASH:
+ return "Slash after host missing";
+ case URI_ERRNO_IPV6_SECURITY:
+ return "IPv6 security bug detected";
+ case URI_ERRNO_INVALID_PORT:
+ return "Port number is bad";
+ case URI_ERRNO_INVALID_PORT_RANGE:
+ return "Port number is not within 0-65535";
}
return NULL;
}
static inline int
-end_of_dir(unsigned char c)
+end_of_dir (unsigned char c)
{
return c == POST_CHAR || c == '#' || c == ';' || c == '?';
}
static inline int
-is_uri_dir_sep(struct uri *uri, unsigned char pos)
+is_uri_dir_sep (struct uri *uri, unsigned char pos)
{
return (pos == '/');
}
static int
-check_uri_file(unsigned char *name)
+check_uri_file (unsigned char *name)
{
- static const unsigned char chars[] = POST_CHAR_S "#?";
+ static const unsigned char chars[] = POST_CHAR_S "#?";
- return strcspn(name, chars);
+ return strcspn (name, chars);
}
static int
url_init (void)
{
- GError *err = NULL;
+ GError *err = NULL;
if (url_initialized == 0) {
- text_re = g_regex_new (text_url, G_REGEX_CASELESS | G_REGEX_MULTILINE | G_REGEX_OPTIMIZE | G_REGEX_EXTENDED, 0, &err);
+ text_re = g_regex_new (text_url, G_REGEX_CASELESS | G_REGEX_MULTILINE | G_REGEX_OPTIMIZE | G_REGEX_EXTENDED, 0, &err);
if (err != NULL) {
msg_info ("url_init: cannot init text url parsing regexp: %s", err->message);
g_error_free (err);
}
enum protocol
-get_protocol(unsigned char *name, int namelen)
+get_protocol (unsigned char *name, int namelen)
{
/* These are really enum protocol values but can take on negative
* values and since 0 <= -1 for enum values it's better to use clean
* integer type. */
- int start, end;
- enum protocol protocol;
- unsigned char *pname;
- int pnamelen, minlen, compare;
+ int start, end;
+ enum protocol protocol;
+ unsigned char *pname;
+ int pnamelen, minlen, compare;
/* Almost dichotomic search is used here */
/* Starting at the HTTP entry which is the most common that will make
* file and NNTP the next entries checked and amongst the third checks
* are proxy and FTP. */
- start = 0;
- end = PROTOCOL_UNKNOWN - 1;
+ start = 0;
+ end = PROTOCOL_UNKNOWN - 1;
protocol = PROTOCOL_HTTP;
while (start <= end) {
int
-get_protocol_port(enum protocol protocol)
+get_protocol_port (enum protocol protocol)
{
return protocol_backends[protocol].port;
}
int
-get_protocol_need_slashes(enum protocol protocol)
+get_protocol_need_slashes (enum protocol protocol)
{
return protocol_backends[protocol].need_slashes;
}
int
-get_protocol_need_slash_after_host(enum protocol protocol)
+get_protocol_need_slash_after_host (enum protocol protocol)
{
return protocol_backends[protocol].need_slash_after_host;
}
int
-get_protocol_free_syntax(enum protocol protocol)
+get_protocol_free_syntax (enum protocol protocol)
{
return protocol_backends[protocol].free_syntax;
}
static int
-get_protocol_length(const unsigned char *url)
+get_protocol_length (const unsigned char *url)
{
- unsigned char *end = (unsigned char *) url;
+ unsigned char *end = (unsigned char *)url;
/* Seek the end of the protocol name if any. */
/* RFC1738:
static unsigned int
url_calculate_escaped_hostlen (char *host, unsigned int hostlen)
{
- unsigned int i, result = hostlen;
- char *p = host, c;
+ unsigned int i, result = hostlen;
+ char *p = host, c;
- for (i = 0; i < hostlen; i ++, p ++) {
+ for (i = 0; i < hostlen; i++, p++) {
if (*p == '%' && g_ascii_isxdigit (*(p + 1)) && g_ascii_isxdigit (*(p + 2)) && i < hostlen - 2) {
c = X2DIGITS_TO_NUM (*(p + 1), *(p + 2));
if (c != '\0') {
static void
url_unescape (char *s)
{
- char *t = s; /* t - tortoise */
- char *h = s; /* h - hare */
-
+ char *t = s; /* t - tortoise */
+ char *h = s; /* h - hare */
+
for (; *h; h++, t++) {
if (*h != '%') {
- copychar:
+ copychar:
*t = *h;
}
- else {
- char c;
+ else {
+ char c;
/* Do nothing if '%' is not followed by two hex digits. */
if (!h[1] || !h[2] || !(g_ascii_isxdigit (h[1]) && g_ascii_isxdigit (h[2])))
goto copychar;
static void
url_strip (char *s)
{
- char *t = s; /* t - tortoise */
- char *h = s; /* h - hare */
-
- while (*h) {
- if (g_ascii_isgraph (*h)) {
- *t = *h;
- t ++;
- }
- h++;
- }
- *t = '\0';
+ char *t = s; /* t - tortoise */
+ char *h = s; /* h - hare */
+
+ while (*h) {
+ if (g_ascii_isgraph (*h)) {
+ *t = *h;
+ t++;
+ }
+ h++;
+ }
+ *t = '\0';
}
/* The core of url_escape_* functions. Escapes the characters that
will be returned unchanged. If ALLOW_PASSTHROUGH is zero, a
freshly allocated string will be returned in all cases. */
-static char *
-url_escape_1 (const char *s, unsigned char mask, int allow_passthrough, memory_pool_t *pool)
+static char *
+url_escape_1 (const char *s, unsigned char mask, int allow_passthrough, memory_pool_t * pool)
{
- const char *p1;
- char *p2, *newstr;
- int newlen;
- int addition = 0;
+ const char *p1;
+ char *p2, *newstr;
+ int newlen;
+ int addition = 0;
for (p1 = s; *p1; p1++)
if (urlchr_test (*p1, mask))
}
newlen = (p1 - s) + addition;
- newstr = (char *) memory_pool_alloc (pool, newlen + 1);
+ newstr = (char *)memory_pool_alloc (pool, newlen + 1);
p1 = s;
p2 = newstr;
while (*p1) {
/* Quote the characters that match the test mask. */
if (urlchr_test (*p1, mask)) {
- unsigned char c = *p1++;
+ unsigned char c = *p1++;
*p2++ = '%';
*p2++ = XNUM_TO_DIGIT (c >> 4);
*p2++ = XNUM_TO_DIGIT (c & 0xf);
/* URL-escape the unsafe characters (see urlchr_table) in a given
string, returning a freshly allocated string. */
-char *
-url_escape (const char *s, memory_pool_t *pool)
+char *
+url_escape (const char *s, memory_pool_t * pool)
{
return url_escape_1 (s, urlchr_unsafe, 0, pool);
}
/* URL-escape the unsafe characters (see urlchr_table) in a given
string. If no characters are unsafe, S is returned. */
-static char *
-url_escape_allow_passthrough (const char *s, memory_pool_t *pool)
+static char *
+url_escape_allow_passthrough (const char *s, memory_pool_t * pool)
{
return url_escape_1 (s, urlchr_unsafe, 1, pool);
}
further transformations of the result yield the same output.
*/
-static char *
-reencode_escapes (char *s, memory_pool_t *pool)
+static char *
+reencode_escapes (char *s, memory_pool_t * pool)
{
- const char *p1;
- char *newstr, *p2;
- int oldlen, newlen;
+ const char *p1;
+ char *newstr, *p2;
+ int oldlen, newlen;
- int encode_count = 0;
+ int encode_count = 0;
/* First pass: inspect the string to see if there's anything to do,
and to calculate the new length. */
p2 = newstr;
while (*p1)
- if (char_needs_escaping (p1)) {
- unsigned char c = *p1++;
- *p2++ = '%';
- *p2++ = XNUM_TO_DIGIT (c >> 4);
- *p2++ = XNUM_TO_DIGIT (c & 0xf);
- }
- else {
- *p2++ = *p1++;
- }
+ if (char_needs_escaping (p1)) {
+ unsigned char c = *p1++;
+ *p2++ = '%';
+ *p2++ = XNUM_TO_DIGIT (c >> 4);
+ *p2++ = XNUM_TO_DIGIT (c & 0xf);
+ }
+ else {
+ *p2++ = *p1++;
+ }
*p2 = '\0';
return newstr;
}
+
/* Unescape CHR in an otherwise escaped STR. Used to selectively
escaping of certain characters, such as "/" and ":". Returns a
count of unescaped chars. */
static void
unescape_single_char (char *str, char chr)
{
- const char c1 = XNUM_TO_DIGIT (chr >> 4);
- const char c2 = XNUM_TO_DIGIT (chr & 0xf);
- char *h = str; /* hare */
- char *t = str; /* tortoise */
+ const char c1 = XNUM_TO_DIGIT (chr >> 4);
+ const char c2 = XNUM_TO_DIGIT (chr & 0xf);
+ char *h = str; /* hare */
+ char *t = str; /* tortoise */
for (; *h; h++, t++) {
if (h[0] == '%' && h[1] == c1 && h[2] == c2) {
*t = chr;
h += 2;
}
- else {
+ else {
*t = *h;
}
}
/* Escape unsafe and reserved characters, except for the slash
characters. */
-static char *
-url_escape_dir (const char *dir, memory_pool_t *pool)
+static char *
+url_escape_dir (const char *dir, memory_pool_t * pool)
{
- char *newdir = url_escape_1 (dir, urlchr_unsafe | urlchr_reserved, 1, pool);
+ char *newdir = url_escape_1 (dir, urlchr_unsafe | urlchr_reserved, 1, pool);
if (newdir == dir)
return (char *)dir;
static int
path_simplify (char *path)
{
- char *h = path; /* hare */
- char *t = path; /* tortoise */
- char *beg = path; /* boundary for backing the tortoise */
- char *end = path + strlen (path);
+ char *h = path; /* hare */
+ char *t = path; /* tortoise */
+ char *beg = path; /* boundary for backing the tortoise */
+ char *end = path + strlen (path);
while (h < end) {
/* Hare should be at the beginning of a path element. */
if (h[0] == '.' && (h[1] == '/' || h[1] == '\0')) {
- /* Ignore "./". */
- h += 2;
+ /* Ignore "./". */
+ h += 2;
}
else if (h[0] == '.' && h[1] == '.' && (h[2] == '/' || h[2] == '\0')) {
- /* Handle "../" by retreating the tortoise by one path
- element -- but not past beggining. */
+ /* Handle "../" by retreating the tortoise by one path
+ element -- but not past beggining. */
if (t > beg) {
- /* Move backwards until T hits the beginning of the
- previous path element or the beginning of path. */
+ /* Move backwards until T hits the beginning of the
+ previous path element or the beginning of path. */
for (--t; t > beg && t[-1] != '/'; t--);
- }
- else {
- /* If we're at the beginning, copy the "../" literally
- move the beginning so a later ".." doesn't remove
- it. */
+ }
+ else {
+ /* If we're at the beginning, copy the "../" literally
+ move the beginning so a later ".." doesn't remove
+ it. */
beg = t + 3;
goto regular;
}
h += 3;
}
else {
- regular:
+ regular:
/* A regular path element. If H hasn't advanced past T,
- simply skip to the next path element. Otherwise, copy
- the path element until the next slash. */
+ simply skip to the next path element. Otherwise, copy
+ the path element until the next slash. */
if (t == h) {
- /* Skip the path element, including the slash. */
+ /* Skip the path element, including the slash. */
while (h < end && *h != '/')
t++, h++;
if (h < end)
t++, h++;
- }
- else {
- /* Copy the path element, including the final slash. */
- while (h < end && *h != '/')
+ }
+ else {
+ /* Copy the path element, including the final slash. */
+ while (h < end && *h != '/')
*t++ = *h++;
- if (h < end)
+ if (h < end)
*t++ = *h++;
- }
+ }
}
}
}
enum uri_errno
-parse_uri(struct uri *uri, unsigned char *uristring, memory_pool_t *pool)
+parse_uri (struct uri *uri, unsigned char *uristring, memory_pool_t * pool)
{
- unsigned char *prefix_end, *host_end, *p;
- unsigned char *lbracket, *rbracket;
- int datalen, n, addrlen;
- unsigned char *frag_or_post, *user_end, *port_end;
+ unsigned char *prefix_end, *host_end, *p;
+ unsigned char *lbracket, *rbracket;
+ int datalen, n, addrlen;
+ unsigned char *frag_or_post, *user_end, *port_end;
memset (uri, 0, sizeof (*uri));
/* Nothing to do for an empty url. */
- if (!*uristring) return URI_ERRNO_EMPTY;
-
+ if (!*uristring)
+ return URI_ERRNO_EMPTY;
+
uri->string = reencode_escapes (uristring, pool);
msg_debug ("parse_uri: reencoding escapes in original url: '%s'", struri (uri));
uri->protocollen = get_protocol_length (struri (uri));
/* Assume http as default protocol */
- if (!uri->protocollen || (uri->protocol = get_protocol (struri(uri), uri->protocollen)) == PROTOCOL_UNKNOWN) {
+ if (!uri->protocollen || (uri->protocol = get_protocol (struri (uri), uri->protocollen)) == PROTOCOL_UNKNOWN) {
p = g_strconcat ("http://", uri->string, NULL);
uri->string = memory_pool_strdup (pool, p);
g_free (p);
/* Figure out whether the protocol is known */
msg_debug ("parse_uri: getting protocol from url: %d", uri->protocol);
- prefix_end = struri (uri) + uri->protocollen; /* ':' */
+ prefix_end = struri (uri) + uri->protocollen; /* ':' */
/* Check if there's a digit after the protocol name. */
if (g_ascii_isdigit (*prefix_end)) {
prefix_end += 2;
- } else {
+ }
+ else {
msg_debug ("parse_uri: no '/' in uri");
return URI_ERRNO_NO_SLASHES;
}
uri->datalen = strlen (prefix_end);
return URI_ERRNO_OK;
- } else if (uri->protocol == PROTOCOL_FILE) {
+ }
+ else if (uri->protocol == PROTOCOL_FILE) {
datalen = check_uri_file (prefix_end);
frag_or_post = prefix_end + datalen;
if (datalen >= 0) {
if (*frag_or_post == '#') {
uri->fragment = frag_or_post + 1;
- uri->fragmentlen = strcspn(uri->fragment, POST_CHAR_S);
+ uri->fragmentlen = strcspn (uri->fragment, POST_CHAR_S);
frag_or_post = uri->fragment + uri->fragmentlen;
}
if (*frag_or_post == POST_CHAR) {
uri->post = frag_or_post + 1;
}
- } else {
- datalen = strlen(prefix_end);
+ }
+ else {
+ datalen = strlen (prefix_end);
}
uri->data = prefix_end;
uri->ipv6 = 1;
else
lbracket = rbracket = NULL;
- } else {
+ }
+ else {
rbracket = NULL;
}
/* Possibly skip auth part */
host_end = prefix_end + strcspn (prefix_end, "@");
- if (prefix_end + strcspn (prefix_end, "/") > host_end
- && *host_end) { /* we have auth info here */
+ if (prefix_end + strcspn (prefix_end, "/") > host_end && *host_end) { /* we have auth info here */
/* Allow '@' in the password component */
while (strcspn (host_end + 1, "@") < strcspn (host_end + 1, "/?"))
if (!user_end || user_end > host_end) {
uri->user = prefix_end;
uri->userlen = host_end - prefix_end;
- } else {
+ }
+ else {
uri->user = prefix_end;
uri->userlen = user_end - prefix_end;
uri->password = user_end + 1;
uri->host = lbracket + 1;
uri->hostlen = addrlen;
- } else {
+ }
+ else {
uri->host = prefix_end;
uri->hostlen = host_end - prefix_end;
return URI_ERRNO_TRAILING_DOTS;
}
- if (*host_end == ':') { /* we have port here */
+ if (*host_end == ':') { /* we have port here */
port_end = host_end + 1 + strcspn (host_end + 1, "/");
host_end++;
if (*host_end == '/') {
host_end++;
- } else if (get_protocol_need_slash_after_host (uri->protocol) && *host_end != '?') {
+ }
+ else if (get_protocol_need_slash_after_host (uri->protocol) && *host_end != '?') {
/* The need for slash after the host component depends on the
* need for a host component. -- The dangerous mind of Jonah */
if (!uri->hostlen)
if (*prefix_end == POST_CHAR) {
uri->post = prefix_end + 1;
}
-
+
convert_to_lowercase (uri->string, uri->protocollen);
convert_to_lowercase (uri->host, uri->hostlen);
/* Decode %HH sequences in host name. This is important not so much
- to support %HH sequences in host names (which other browser
- don't), but to support binary characters (which will have been
- converted to %HH by reencode_escapes). */
+ to support %HH sequences in host names (which other browser
+ don't), but to support binary characters (which will have been
+ converted to %HH by reencode_escapes). */
if (strchr (uri->host, '%')) {
uri->hostlen = url_calculate_escaped_hostlen (uri->host, uri->hostlen);
}
return URI_ERRNO_OK;
}
-void
-url_parse_text (memory_pool_t *pool, struct worker_task *task, struct mime_text_part *part, gboolean is_html)
+void
+url_parse_text (memory_pool_t * pool, struct worker_task *task, struct mime_text_part *part, gboolean is_html)
{
- GMatchInfo *info;
- GError *err = NULL;
- int rc;
- char *url_str = NULL;
- struct uri *new;
-
+ GMatchInfo *info;
+ GError *err = NULL;
+ int rc;
+ char *url_str = NULL;
+ struct uri *new;
+
if (!part->orig->data || part->orig->len == 0) {
msg_warn ("url_parse_text: got empty text part");
return;
}
else {
rc = g_regex_match_full (text_re, (const char *)part->content->data, part->content->len, 0, 0, &info, &err);
-
+
}
if (rc) {
while (g_match_info_matches (info)) {
}
}
}
- memory_pool_add_destructor (task->task_pool, (pool_destruct_func)g_free, url_str);
+ memory_pool_add_destructor (task->task_pool, (pool_destruct_func) g_free, url_str);
/* Get next match */
g_match_info_next (info, &err);
}
#define CONNECT_TIMEOUT 3
#ifdef RSPAMD_MAIN
-sig_atomic_t do_reopen_log = 0;
-extern rspamd_hash_t *counters;
+sig_atomic_t do_reopen_log = 0;
+extern rspamd_hash_t *counters;
#endif
struct logger_params {
- GLogFunc log_func;
- struct config_file *cfg;
+ GLogFunc log_func;
+ struct config_file *cfg;
};
-static struct logger_params log_params;
+static struct logger_params log_params;
/* Here would be put log messages intensity */
-static uint32_t log_written;
-static time_t last_check;
-static char *io_buf = NULL;
-static gboolean log_buffered = FALSE;
+static uint32_t log_written;
+static time_t last_check;
+static char *io_buf = NULL;
+static gboolean log_buffered = FALSE;
int
make_socket_nonblocking (int fd)
{
- int ofl;
+ int ofl;
ofl = fcntl (fd, F_GETFL, 0);
int
make_socket_blocking (int fd)
-{
- int ofl;
+{
+ int ofl;
ofl = fcntl (fd, F_GETFL, 0);
return 0;
}
-int
+int
poll_sync_socket (int fd, int timeout, short events)
{
- int r;
- struct pollfd fds[1];
+ int r;
+ struct pollfd fds[1];
fds->fd = fd;
fds->events = events;
static int
make_inet_socket (int family, struct in_addr *addr, u_short port, gboolean is_server, gboolean async)
{
- int fd, r, optlen, on = 1, s_error;
- int serrno;
- struct sockaddr_in sin;
-
+ int fd, r, optlen, on = 1, s_error;
+ int serrno;
+ struct sockaddr_in sin;
+
/* Create socket */
fd = socket (AF_INET, family, 0);
if (fd == -1) {
if (make_socket_nonblocking (fd) < 0) {
goto out;
}
-
+
/* Set close on exec */
if (fcntl (fd, F_SETFD, FD_CLOEXEC) == -1) {
msg_warn ("make_tcp_socket: fcntl failed: %d, '%s'", errno, strerror (errno));
goto out;
}
-
+
/* Bind options */
sin.sin_family = AF_INET;
sin.sin_port = htons (port);
sin.sin_addr.s_addr = addr->s_addr;
-
+
if (is_server) {
- setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (const void *) &on, sizeof(int));
+ setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&on, sizeof (int));
r = bind (fd, (struct sockaddr *)&sin, sizeof (struct sockaddr_in));
}
else {
}
else {
/* Still need to check SO_ERROR on socket */
- optlen = sizeof(s_error);
- getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&s_error, &optlen);
+ optlen = sizeof (s_error);
+ getsockopt (fd, SOL_SOCKET, SO_ERROR, (void *)&s_error, &optlen);
if (s_error) {
errno = s_error;
goto out;
return (fd);
- out:
+ out:
serrno = errno;
close (fd);
errno = serrno;
int
make_tcp_socket (struct in_addr *addr, u_short port, gboolean is_server, gboolean async)
{
- return make_inet_socket (SOCK_STREAM, addr, port, is_server, async);
+ return make_inet_socket (SOCK_STREAM, addr, port, is_server, async);
}
int
make_udp_socket (struct in_addr *addr, u_short port, gboolean is_server, gboolean async)
{
- return make_inet_socket (SOCK_DGRAM, addr, port, is_server, async);
+ return make_inet_socket (SOCK_DGRAM, addr, port, is_server, async);
}
int
-accept_from_socket (int listen_sock, struct sockaddr *addr, socklen_t *len)
+accept_from_socket (int listen_sock, struct sockaddr *addr, socklen_t * len)
{
- int nfd;
- int serrno;
+ int nfd;
+ int serrno;
if ((nfd = accept (listen_sock, addr, len)) == -1) {
if (errno == EAGAIN) {
- return 0;
+ return 0;
}
msg_warn ("accept_from_socket: accept failed: %d, '%s'", errno, strerror (errno));
return -1;
}
- if (make_socket_nonblocking(nfd) < 0) {
+ if (make_socket_nonblocking (nfd) < 0) {
goto out;
}
-
+
/* Set close on exec */
if (fcntl (nfd, F_SETFD, FD_CLOEXEC) == -1) {
msg_warn ("accept_from_socket: fcntl failed: %d, '%s'", errno, strerror (errno));
return (nfd);
- out:
+ out:
serrno = errno;
close (nfd);
errno = serrno;
int
make_unix_socket (const char *path, struct sockaddr_un *addr, gboolean is_server)
{
- size_t len = strlen (path);
- int fd, s_error, r, optlen, serrno, on = 1;
+ size_t len = strlen (path);
+ int fd, s_error, r, optlen, serrno, on = 1;
- if (len > sizeof (addr->sun_path) - 1 || path == NULL) return -1;
-
- #ifdef FREEBSD
+ if (len > sizeof (addr->sun_path) - 1 || path == NULL)
+ return -1;
+
+#ifdef FREEBSD
addr->sun_len = sizeof (struct sockaddr_un);
- #endif
+#endif
addr->sun_family = AF_UNIX;
-
+
strncpy (addr->sun_path, path, len);
-
+
fd = socket (PF_LOCAL, SOCK_STREAM, 0);
-
+
if (fd == -1) {
msg_warn ("make_unix_socket: socket failed: %d, '%s'", errno, strerror (errno));
return -1;
}
- if (make_socket_nonblocking(fd) < 0) {
+ if (make_socket_nonblocking (fd) < 0) {
goto out;
}
-
+
/* Set close on exec */
if (fcntl (fd, F_SETFD, FD_CLOEXEC) == -1) {
msg_warn ("make_unix_socket: fcntl failed: %d, '%s'", errno, strerror (errno));
goto out;
}
if (is_server) {
- setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (const void *) &on, sizeof(int));
+ setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (const void *)&on, sizeof (int));
r = bind (fd, (struct sockaddr *)addr, sizeof (struct sockaddr_in));
}
else {
}
else {
/* Still need to check SO_ERROR on socket */
- optlen = sizeof(s_error);
+ optlen = sizeof (s_error);
getsockopt (fd, SOL_SOCKET, SO_ERROR, (void *)&s_error, &optlen);
if (s_error) {
errno = s_error;
return (fd);
- out:
+ out:
serrno = errno;
close (fd);
errno = serrno;
int
write_pid (struct rspamd_main *main)
{
- pid_t pid;
+ pid_t pid;
main->pfh = pidfile_open (main->cfg->pid_file, 0644, &pid);
if (main->pfh == NULL) {
void
init_signals (struct sigaction *signals, sig_t sig_handler)
{
- struct sigaction sigpipe_act;
+ struct sigaction sigpipe_act;
/* Setting up signal handlers */
/* SIGUSR1 - reopen config file */
/* SIGUSR2 - worker is ready for accept */
sigaction (SIGUSR1, signals, NULL);
sigaction (SIGUSR2, signals, NULL);
sigaction (SIGALRM, signals, NULL);
-
+
/* Ignore SIGPIPE as we handle write errors manually */
sigemptyset (&sigpipe_act.sa_mask);
sigaddset (&sigpipe_act.sa_mask, SIGPIPE);
}
void
-pass_signal_worker (GList *workers, int signo)
+pass_signal_worker (GList * workers, int signo)
{
- struct rspamd_worker *cur;
- GList *l;
+ struct rspamd_worker *cur;
+ GList *l;
l = workers;
while (l) {
}
}
-void convert_to_lowercase (char *str, unsigned int size)
+void
+convert_to_lowercase (char *str, unsigned int size)
{
while (size--) {
*str = g_ascii_tolower (*str);
- str ++;
+ str++;
}
}
#ifndef HAVE_SETPROCTITLE
-static char *title_buffer = 0;
-static size_t title_buffer_size = 0;
-static char *title_progname, *title_progname_full;
+static char *title_buffer = 0;
+static size_t title_buffer_size = 0;
+static char *title_progname, *title_progname_full;
int
setproctitle (const char *fmt, ...)
memset (title_buffer, '\0', title_buffer_size);
- ssize_t written;
+ ssize_t written;
if (fmt) {
- ssize_t written2;
- va_list ap;
+ ssize_t written2;
+ va_list ap;
written = snprintf (title_buffer, title_buffer_size, "%s: ", title_progname);
if (written < 0 || (size_t) written >= title_buffer_size)
return -1;
va_start (ap, fmt);
- written2 =
- vsnprintf (title_buffer + written,
- title_buffer_size - written, fmt, ap);
+ written2 = vsnprintf (title_buffer + written, title_buffer_size - written, fmt, ap);
va_end (ap);
- if (written2 < 0
- || (size_t) written2 >= title_buffer_size - written)
+ if (written2 < 0 || (size_t) written2 >= title_buffer_size - written)
return -1;
- } else {
- written =
- snprintf (title_buffer, title_buffer_size, "%s",
- title_progname);
+ }
+ else {
+ written = snprintf (title_buffer, title_buffer_size, "%s", title_progname);
if (written < 0 || (size_t) written >= title_buffer_size)
return -1;
}
int
init_title (int argc, char *argv[], char *envp[])
{
- char *begin_of_buffer = 0, *end_of_buffer = 0;
- int i;
+ char *begin_of_buffer = 0, *end_of_buffer = 0;
+ int i;
for (i = 0; i < argc; ++i) {
if (!begin_of_buffer)
if (!begin_of_buffer)
begin_of_buffer = envp[i];
if (!end_of_buffer || end_of_buffer + 1 == envp[i])
- end_of_buffer = envp[i] + strlen(envp[i]);
+ end_of_buffer = envp[i] + strlen (envp[i]);
}
if (!end_of_buffer)
return 0;
- char **new_environ = g_malloc ((i + 1) * sizeof (envp[0]));
+ char **new_environ = g_malloc ((i + 1) * sizeof (envp[0]));
if (!new_environ)
return 0;
if (!title_progname_full)
goto cleanup_enomem;
- char *p = strrchr (title_progname_full, '/');
+ char *p = strrchr (title_progname_full, '/');
if (p)
title_progname = p + 1;
return 0;
- cleanup_enomem:
+ cleanup_enomem:
for (--i; i >= 0; --i) {
g_free (new_environ[i]);
}
#endif
#ifndef HAVE_PIDFILE
-extern char * __progname;
-static int _pidfile_remove (struct pidfh *pfh, int freeit);
+extern char *__progname;
+static int _pidfile_remove (struct pidfh *pfh, int freeit);
static int
pidfile_verify (struct pidfh *pfh)
{
- struct stat sb;
+ struct stat sb;
if (pfh == NULL || pfh->pf_fd == -1)
return (-1);
}
static int
-pidfile_read (const char *path, pid_t *pidptr)
+pidfile_read (const char *path, pid_t * pidptr)
{
- char buf[16], *endptr;
- int error, fd, i;
+ char buf[16], *endptr;
+ int error, fd, i;
fd = open (path, O_RDONLY);
if (fd == -1)
return (errno);
- i = read (fd, buf, sizeof(buf) - 1);
- error = errno; /* Remember errno in case close() wants to change it. */
+ i = read (fd, buf, sizeof (buf) - 1);
+ error = errno; /* Remember errno in case close() wants to change it. */
close (fd);
if (i == -1)
return error;
return 0;
}
-struct pidfh *
-pidfile_open (const char *path, mode_t mode, pid_t *pidptr)
+struct pidfh *
+pidfile_open (const char *path, mode_t mode, pid_t * pidptr)
{
- struct pidfh *pfh;
- struct stat sb;
- int error, fd, len, count;
- struct timespec rqtp;
+ struct pidfh *pfh;
+ struct stat sb;
+ int error, fd, len, count;
+ struct timespec rqtp;
- pfh = g_malloc (sizeof(*pfh));
+ pfh = g_malloc (sizeof (*pfh));
if (pfh == NULL)
return NULL;
if (path == NULL)
- len = snprintf (pfh->pf_path, sizeof(pfh->pf_path),
- "/var/run/%s.pid", __progname);
+ len = snprintf (pfh->pf_path, sizeof (pfh->pf_path), "/var/run/%s.pid", __progname);
else
- len = snprintf (pfh->pf_path, sizeof(pfh->pf_path),
- "%s", path);
+ len = snprintf (pfh->pf_path, sizeof (pfh->pf_path), "%s", path);
if (len >= (int)sizeof (pfh->pf_path)) {
g_free (pfh);
errno = ENAMETOOLONG;
* PID file will be truncated again in pidfile_write(), so
* pidfile_write() can be called multiple times.
*/
- fd = open (pfh->pf_path,
- O_WRONLY | O_CREAT | O_TRUNC | O_NONBLOCK, mode);
+ fd = open (pfh->pf_path, O_WRONLY | O_CREAT | O_TRUNC | O_NONBLOCK, mode);
flock (fd, LOCK_EX | LOCK_NB);
if (fd == -1) {
count = 0;
rqtp.tv_sec = 0;
rqtp.tv_nsec = 5000000;
if (errno == EWOULDBLOCK && pidptr != NULL) {
- again:
+ again:
errno = pidfile_read (pfh->pf_path, pidptr);
if (errno == 0)
errno = EEXIST;
int
pidfile_write (struct pidfh *pfh)
{
- char pidstr[16];
- int error, fd;
+ char pidstr[16];
+ int error, fd;
/*
* Check remembered descriptor, so we don't overwrite some other
return -1;
}
- snprintf (pidstr, sizeof(pidstr), "%u", getpid ());
- if (pwrite (fd, pidstr, strlen (pidstr), 0) != (ssize_t)strlen (pidstr)) {
+ snprintf (pidstr, sizeof (pidstr), "%u", getpid ());
+ if (pwrite (fd, pidstr, strlen (pidstr), 0) != (ssize_t) strlen (pidstr)) {
error = errno;
_pidfile_remove (pfh, 0);
errno = error;
int
pidfile_close (struct pidfh *pfh)
{
- int error;
+ int error;
error = pidfile_verify (pfh);
if (error != 0) {
static int
_pidfile_remove (struct pidfh *pfh, int freeit)
{
- int error;
+ int error;
error = pidfile_verify (pfh);
if (error != 0) {
open_log (struct config_file *cfg)
{
switch (cfg->log_type) {
- case RSPAMD_LOG_CONSOLE:
- /* Do nothing with console */
- return 0;
- case RSPAMD_LOG_SYSLOG:
- openlog ("rspamd", LOG_NDELAY | LOG_PID, cfg->log_facility);
- return 0;
- case RSPAMD_LOG_FILE:
- cfg->log_fd = open (cfg->log_file, O_CREAT | O_WRONLY | O_APPEND, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
- if (cfg->log_fd == -1) {
- fprintf (stderr, "open_log: cannot open desired log file: %s, %s", cfg->log_file, strerror (errno));
- return -1;
- }
- cfg->logf = fdopen (cfg->log_fd, "w");
- /* Set line buffering */
- setvbuf (cfg->logf, (char *) NULL, _IOLBF, 0);
- return 0;
+ case RSPAMD_LOG_CONSOLE:
+ /* Do nothing with console */
+ return 0;
+ case RSPAMD_LOG_SYSLOG:
+ openlog ("rspamd", LOG_NDELAY | LOG_PID, cfg->log_facility);
+ return 0;
+ case RSPAMD_LOG_FILE:
+ cfg->log_fd = open (cfg->log_file, O_CREAT | O_WRONLY | O_APPEND, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
+ if (cfg->log_fd == -1) {
+ fprintf (stderr, "open_log: cannot open desired log file: %s, %s", cfg->log_file, strerror (errno));
+ return -1;
+ }
+ cfg->logf = fdopen (cfg->log_fd, "w");
+ /* Set line buffering */
+ setvbuf (cfg->logf, (char *)NULL, _IOLBF, 0);
+ return 0;
}
return -1;
}
-void
+void
close_log (struct config_file *cfg)
{
switch (cfg->log_type) {
- case RSPAMD_LOG_CONSOLE:
- /* Do nothing with console */
- break;
- case RSPAMD_LOG_SYSLOG:
- closelog ();
- break;
- case RSPAMD_LOG_FILE:
- if (cfg->logf != NULL) {
- if (fsync (cfg->log_fd) == -1) {
- msg_err ("close_log: error syncing log file: %s", strerror (errno));
- }
- fclose (cfg->logf);
- /* XXX: I think this is not needed */
- close (cfg->log_fd);
+ case RSPAMD_LOG_CONSOLE:
+ /* Do nothing with console */
+ break;
+ case RSPAMD_LOG_SYSLOG:
+ closelog ();
+ break;
+ case RSPAMD_LOG_FILE:
+ if (cfg->logf != NULL) {
+ if (fsync (cfg->log_fd) == -1) {
+ msg_err ("close_log: error syncing log file: %s", strerror (errno));
}
- break;
+ fclose (cfg->logf);
+ /* XXX: I think this is not needed */
+ close (cfg->log_fd);
+ }
+ break;
}
}
void
rspamd_log_function (GLogLevelFlags log_level, const char *fmt, ...)
{
- static char logbuf[BUFSIZ];
- va_list vp;
+ static char logbuf[BUFSIZ];
+ va_list vp;
if (log_level <= log_params.cfg->log_level) {
va_start (vp, fmt);
}
void
-syslog_log_function (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer arg)
+syslog_log_function (const gchar * log_domain, GLogLevelFlags log_level, const gchar * message, gpointer arg)
{
- struct config_file *cfg = (struct config_file *)arg;
+ struct config_file *cfg = (struct config_file *)arg;
#ifdef RSPAMD_MAIN
if (do_reopen_log) {
reopen_log (cfg);
}
void
-file_log_function (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer arg)
+file_log_function (const gchar * log_domain, GLogLevelFlags log_level, const gchar * message, gpointer arg)
{
- struct config_file *cfg = (struct config_file *)arg;
- char tmpbuf[128], timebuf[32];
- time_t now;
- struct tm *tms;
-
+ struct config_file *cfg = (struct config_file *)arg;
+ char tmpbuf[128], timebuf[32];
+ time_t now;
+ struct tm *tms;
+
if (cfg->log_fd == -1 || cfg->logf == NULL) {
return;
}
strftime (timebuf, sizeof (timebuf), "%b %d %H:%M:%S", tms);
snprintf (tmpbuf, sizeof (tmpbuf), "#%d: %s rspamd ", (int)getpid (), timebuf);
fprintf (cfg->logf, "%s%s" CRLF, tmpbuf, message);
- log_written ++;
+ log_written++;
}
}
/* Replace %r with rcpt value and %f with from value, new string is allocated in pool */
-char *
-resolve_stat_filename (memory_pool_t *pool, char *pattern, char *rcpt, char *from)
+char *
+resolve_stat_filename (memory_pool_t * pool, char *pattern, char *rcpt, char *from)
{
- int need_to_format = 0, len = 0;
- int rcptlen, fromlen;
- char *c = pattern, *new, *s;
-
+ int need_to_format = 0, len = 0;
+ int rcptlen, fromlen;
+ char *c = pattern, *new, *s;
+
if (rcpt) {
rcptlen = strlen (rcpt);
}
need_to_format = 1;
continue;
}
- len ++;
+ len++;
}
-
+
/* Do not allocate extra memory if we do not need to format string */
if (!need_to_format) {
return pattern;
}
-
+
/* Allocate new string */
new = memory_pool_alloc (pool, len);
c = pattern;
s = new;
-
+
/* Format string */
- while (*c ++) {
+ while (*c++) {
if (*c == '%' && *(c + 1) == 'r') {
c += 2;
memcpy (s, rcpt, rcptlen);
s += fromlen;
continue;
}
- *s ++ = *c;
+ *s++ = *c;
}
-
+
*s = '\0';
return new;
}
-const char *
+const char *
calculate_check_time (struct timespec *begin, int resolution)
{
- struct timespec ts;
- double diff;
- static char res[sizeof("100000.000")];
- static char fmt[sizeof("%.10f")];
-
+ struct timespec ts;
+ double diff;
+ static char res[sizeof ("100000.000")];
+ static char fmt[sizeof ("%.10f")];
+
#ifdef HAVE_CLOCK_PROCESS_CPUTIME_ID
clock_gettime (CLOCK_PROCESS_CPUTIME_ID, &ts);
#elif defined(HAVE_CLOCK_VIRTUAL)
clock_gettime (CLOCK_REALTIME, &ts);
#endif
- diff = (ts.tv_sec - begin->tv_sec) * 1000. + /* Seconds */
- (ts.tv_nsec - begin->tv_nsec) / 1000000.; /* Nanoseconds */
+ diff = (ts.tv_sec - begin->tv_sec) * 1000. + /* Seconds */
+ (ts.tv_nsec - begin->tv_nsec) / 1000000.; /* Nanoseconds */
sprintf (fmt, "%%.%df", resolution);
snprintf (res, sizeof (res), fmt, diff);
set_counter (const char *name, long int value)
{
#ifdef RSPAMD_MAIN
- struct counter_data *cd;
- double alpha;
- char *key;
-
- cd = rspamd_hash_lookup (counters, (gpointer)name);
+ struct counter_data *cd;
+ double alpha;
+ char *key;
+
+ cd = rspamd_hash_lookup (counters, (gpointer) name);
if (cd == NULL) {
cd = memory_pool_alloc_shared (counters->pool, sizeof (struct counter_data));
cd->value = value;
cd->number = 0;
key = memory_pool_strdup_shared (counters->pool, name);
- rspamd_hash_insert (counters, (gpointer)key, (gpointer)cd);
+ rspamd_hash_insert (counters, (gpointer) key, (gpointer) cd);
}
else {
/* Calculate new value */
}
#ifndef g_tolower
-#define g_tolower(x) (((x) >= 'A' && (x) <= 'Z') ? (x) - 'A' + 'a' : (x))
+# define g_tolower(x) (((x) >= 'A' && (x) <= 'Z') ? (x) - 'A' + 'a' : (x))
#endif
gboolean
rspamd_strcase_equal (gconstpointer v, gconstpointer v2)
{
- if (g_ascii_strcasecmp ((const char *) v, (const char *) v2) == 0) {
+ if (g_ascii_strcasecmp ((const char *)v, (const char *)v2) == 0) {
return TRUE;
}
guint
rspamd_strcase_hash (gconstpointer key)
{
- const char *p = key;
- guint h = 0;
-
+ const char *p = key;
+ guint h = 0;
+
while (*p != '\0') {
h = (h << 5) - h + g_tolower (*p);
p++;
}
-
+
return h;
}
-void
+void
gperf_profiler_init (struct config_file *cfg, const char *descr)
{
#if defined(WITH_GPERF_TOOLS) && defined(RSPAMD_MAIN)
- char prof_path[PATH_MAX];
+ char prof_path[PATH_MAX];
- if (getenv("CPUPROFILE")) {
+ if (getenv ("CPUPROFILE")) {
/* disable inherited Profiler enabled in master process */
ProfilerStop ();
snprintf (prof_path, sizeof (prof_path), "%s-%s.%d", cfg->profile_path, descr, (int)getpid ());
if (ProfilerStart (prof_path)) {
/* start ITIMER_PROF timer */
- ProfilerRegisterThread();
+ ProfilerRegisterThread ();
}
else {
msg_warn ("gperf_frofiler_init: cannot start google perftools profiler");
#include "cfg_file.h"
#include "map.h"
-struct rspamd_view*
-init_view (memory_pool_t *pool)
+struct rspamd_view *
+init_view (memory_pool_t * pool)
{
- struct rspamd_view *new;
+ struct rspamd_view *new;
new = memory_pool_alloc0 (pool, sizeof (struct rspamd_view));
new->from_hash = g_hash_table_new (rspamd_strcase_hash, rspamd_strcase_equal);
new->symbols_hash = g_hash_table_new (rspamd_strcase_hash, rspamd_strcase_equal);
- memory_pool_add_destructor (new->pool, (pool_destruct_func)g_hash_table_destroy, new->from_hash);
- memory_pool_add_destructor (new->pool, (pool_destruct_func)g_hash_table_destroy, new->symbols_hash);
+ memory_pool_add_destructor (new->pool, (pool_destruct_func) g_hash_table_destroy, new->from_hash);
+ memory_pool_add_destructor (new->pool, (pool_destruct_func) g_hash_table_destroy, new->symbols_hash);
return new;
}
-gboolean
-add_view_from (struct rspamd_view *view, char *line)
+gboolean
+add_view_from (struct rspamd_view * view, char *line)
{
- struct rspamd_regexp *re = NULL;
+ struct rspamd_regexp *re = NULL;
if (add_map (line, read_host_list, fin_host_list, (void **)&view->from_hash)) {
return TRUE;
return FALSE;
}
-gboolean
-add_view_symbols (struct rspamd_view *view, char *line)
+gboolean
+add_view_symbols (struct rspamd_view * view, char *line)
{
- struct rspamd_regexp *re = NULL;
- GList *symbols;
+ struct rspamd_regexp *re = NULL;
+ GList *symbols;
if (add_map (line, read_host_list, fin_host_list, (void **)&view->symbols_hash)) {
return TRUE;
}
-gboolean
-add_view_ip (struct rspamd_view *view, char *line)
+gboolean
+add_view_ip (struct rspamd_view * view, char *line)
{
if (add_map (line, read_radix_list, fin_radix_list, (void **)&view->ip_tree)) {
return TRUE;
}
-struct rspamd_view *
-find_view_by_ip (GList *views, struct worker_task *task)
+struct rspamd_view *
+find_view_by_ip (GList * views, struct worker_task *task)
{
- GList *cur;
- struct rspamd_view *v;
+ GList *cur;
+ struct rspamd_view *v;
if (task->from_addr.s_addr == INADDR_NONE) {
return NULL;
}
-
+
cur = views;
while (cur) {
v = cur->data;
return NULL;
}
-struct rspamd_view *
-find_view_by_from (GList *views, struct worker_task *task)
+struct rspamd_view *
+find_view_by_from (GList * views, struct worker_task *task)
{
- GList *cur, *cur_re;
- struct rspamd_view *v;
- struct rspamd_regexp *re;
+ GList *cur, *cur_re;
+ struct rspamd_view *v;
+ struct rspamd_regexp *re;
if (task->from == NULL) {
return NULL;
}
-
+
cur = views;
while (cur) {
v = cur->data;
return NULL;
}
-static gboolean
+static gboolean
match_view_symbol (struct rspamd_view *v, const char *symbol)
{
- GList *cur;
- struct rspamd_regexp *re;
+ GList *cur;
+ struct rspamd_regexp *re;
/* First try to lookup in hashtable */
if (g_hash_table_lookup (v->symbols_hash, symbol) != NULL) {
return FALSE;
}
-gboolean
-check_view (GList *views, const char *symbol, struct worker_task *task)
+gboolean
+check_view (GList * views, const char *symbol, struct worker_task * task)
{
- struct rspamd_view *selected = NULL;
+ struct rspamd_view *selected = NULL;
if (views == NULL || (task->view == NULL && task->view_checked == TRUE)) {
/* If now views defined just return TRUE to check each symbol */
return TRUE;
}
-
+
if (task->view != NULL) {
goto check_symbol;
}
return TRUE;
}
}
-
+
task->view_checked = TRUE;
task->view = selected;
-check_symbol:
+ check_symbol:
/* selected is now not NULL */
if (match_view_symbol (task->view, symbol)) {
return TRUE;
#include <evdns.h>
#ifndef WITHOUT_PERL
-#include <EXTERN.h> /* from the Perl distribution */
-#include <perl.h> /* from the Perl distribution */
+# include <EXTERN.h> /* from the Perl distribution */
+# include <perl.h> /* from the Perl distribution */
-extern PerlInterpreter *perl_interpreter;
+extern PerlInterpreter *perl_interpreter;
#endif
#ifdef WITH_GPERF_TOOLS
-#include <glib/gprintf.h>
+# include <glib/gprintf.h>
#endif
-static struct timeval io_tv;
+static struct timeval io_tv;
-static gboolean write_socket (void *arg);
+static gboolean write_socket (void *arg);
-static
-void sig_handler (int signo)
+static
+ void
+sig_handler (int signo)
{
switch (signo) {
- case SIGINT:
- case SIGTERM:
+ case SIGINT:
+ case SIGTERM:
#ifdef WITH_GPERF_TOOLS
- ProfilerStop ();
+ ProfilerStop ();
#endif
#ifdef WITH_PROFILER
- exit (0);
+ exit (0);
#else
- _exit (1);
+ _exit (1);
#endif
- break;
+ break;
}
}
static void
sigusr_handler (int fd, short what, void *arg)
{
- struct rspamd_worker *worker = (struct rspamd_worker *)arg;
+ struct rspamd_worker *worker = (struct rspamd_worker *)arg;
/* Do not accept new connections, preparing to end worker's process */
- struct timeval tv;
+ struct timeval tv;
tv.tv_sec = SOFT_SHUTDOWN_TIME;
tv.tv_usec = 0;
event_del (&worker->sig_ev);
static void
rcpt_destruct (void *pointer)
{
- struct worker_task *task = (struct worker_task *)pointer;
+ struct worker_task *task = (struct worker_task *)pointer;
if (task->rcpt) {
g_list_free (task->rcpt);
void
free_task (struct worker_task *task, gboolean is_soft)
{
- GList *part;
- struct mime_part *p;
+ GList *part;
+ struct mime_part *p;
if (task) {
msg_debug ("free_task: free pointer %p", task);
}
}
-static void
+static void
free_task_hard (void *ud)
{
- struct worker_task *task = ud;
+ struct worker_task *task = ud;
free_task (task, FALSE);
}
/*
* Callback that is called when there is data to read in buffer
*/
-static gboolean
-read_socket (f_str_t *in, void *arg)
+static gboolean
+read_socket (f_str_t * in, void *arg)
{
- struct worker_task *task = (struct worker_task *)arg;
- ssize_t r;
+ struct worker_task *task = (struct worker_task *)arg;
+ ssize_t r;
switch (task->state) {
- case READ_COMMAND:
- case READ_HEADER:
- if (read_rspamd_input_line (task, in) != 0) {
- task->last_error = "Read error";
- task->error_code = RSPAMD_NETWORK_ERROR;
- task->state = WRITE_ERROR;
- }
- if (task->state == WRITE_REPLY || task->state == WRITE_ERROR) {
- write_socket (task);
- }
- break;
- case READ_MESSAGE:
- task->msg = memory_pool_alloc (task->task_pool, sizeof (f_str_t));
- task->msg->begin = in->begin;
- task->msg->len = in->len;
- msg_debug ("read_socket: got string of length %ld", (long int)task->msg->len);
- r = process_message (task);
- if (r == -1) {
- msg_warn ("read_socket: processing of message failed");
- task->last_error = "MIME processing error";
- task->error_code = RSPAMD_FILTER_ERROR;
- task->state = WRITE_ERROR;
- write_socket (task);
- }
- if (task->cmd == CMD_OTHER) {
- /* Skip filters */
- task->state = WRITE_REPLY;
- write_socket (task);
- return TRUE;
- }
- r = process_filters (task);
- if (r == -1) {
- task->last_error = "Filter processing error";
- task->error_code = RSPAMD_FILTER_ERROR;
- task->state = WRITE_ERROR;
- write_socket (task);
- }
- else if (r == 0) {
- task->state = WAIT_FILTER;
- rspamd_dispatcher_pause (task->dispatcher);
- }
- else {
- process_statfiles (task);
- write_socket (task);
- }
- break;
- default:
- msg_debug ("read_socket: invalid state on reading stage");
- break;
+ case READ_COMMAND:
+ case READ_HEADER:
+ if (read_rspamd_input_line (task, in) != 0) {
+ task->last_error = "Read error";
+ task->error_code = RSPAMD_NETWORK_ERROR;
+ task->state = WRITE_ERROR;
+ }
+ if (task->state == WRITE_REPLY || task->state == WRITE_ERROR) {
+ write_socket (task);
+ }
+ break;
+ case READ_MESSAGE:
+ task->msg = memory_pool_alloc (task->task_pool, sizeof (f_str_t));
+ task->msg->begin = in->begin;
+ task->msg->len = in->len;
+ msg_debug ("read_socket: got string of length %ld", (long int)task->msg->len);
+ r = process_message (task);
+ if (r == -1) {
+ msg_warn ("read_socket: processing of message failed");
+ task->last_error = "MIME processing error";
+ task->error_code = RSPAMD_FILTER_ERROR;
+ task->state = WRITE_ERROR;
+ write_socket (task);
+ }
+ if (task->cmd == CMD_OTHER) {
+ /* Skip filters */
+ task->state = WRITE_REPLY;
+ write_socket (task);
+ return TRUE;
+ }
+ r = process_filters (task);
+ if (r == -1) {
+ task->last_error = "Filter processing error";
+ task->error_code = RSPAMD_FILTER_ERROR;
+ task->state = WRITE_ERROR;
+ write_socket (task);
+ }
+ else if (r == 0) {
+ task->state = WAIT_FILTER;
+ rspamd_dispatcher_pause (task->dispatcher);
+ }
+ else {
+ process_statfiles (task);
+ write_socket (task);
+ }
+ break;
+ default:
+ msg_debug ("read_socket: invalid state on reading stage");
+ break;
}
return TRUE;
/*
* Callback for socket writing
*/
-static gboolean
+static gboolean
write_socket (void *arg)
{
- struct worker_task *task = (struct worker_task *)arg;
-
+ struct worker_task *task = (struct worker_task *)arg;
+
switch (task->state) {
- case WRITE_REPLY:
- write_reply (task);
- destroy_session (task->s);
- return FALSE;
- break;
- case WRITE_ERROR:
- write_reply (task);
- destroy_session (task->s);
- return FALSE;
- break;
- case CLOSING_CONNECTION:
- msg_debug ("write_socket: normally closing connection");
- destroy_session (task->s);
- return FALSE;
- break;
- default:
- msg_info ("write_socket: abnormally closing connection");
- destroy_session (task->s);
- return FALSE;
- break;
+ case WRITE_REPLY:
+ write_reply (task);
+ destroy_session (task->s);
+ return FALSE;
+ break;
+ case WRITE_ERROR:
+ write_reply (task);
+ destroy_session (task->s);
+ return FALSE;
+ break;
+ case CLOSING_CONNECTION:
+ msg_debug ("write_socket: normally closing connection");
+ destroy_session (task->s);
+ return FALSE;
+ break;
+ default:
+ msg_info ("write_socket: abnormally closing connection");
+ destroy_session (task->s);
+ return FALSE;
+ break;
}
return TRUE;
}
* Called if something goes wrong
*/
static void
-err_socket (GError *err, void *arg)
+err_socket (GError * err, void *arg)
{
- struct worker_task *task = (struct worker_task *)arg;
+ struct worker_task *task = (struct worker_task *)arg;
msg_info ("err_socket: abnormally closing connection, error: %s", err->message);
/* Free buffers */
destroy_session (task->s);
}
-struct worker_task *
+struct worker_task *
construct_task (struct rspamd_worker *worker)
{
- struct worker_task *new_task;
-
+ struct worker_task *new_task;
+
new_task = g_malloc (sizeof (struct worker_task));
msg_debug ("accept_socket: new task allocated: %p", new_task);
io_tv.tv_usec = 0;
new_task->task_pool = memory_pool_new (memory_pool_get_size ());
/* Add destructor for recipients list (it would be better to use anonymous function here */
- memory_pool_add_destructor (new_task->task_pool, (pool_destruct_func)rcpt_destruct, new_task);
+ memory_pool_add_destructor (new_task->task_pool, (pool_destruct_func) rcpt_destruct, new_task);
new_task->results = g_hash_table_new (g_str_hash, g_str_equal);
- memory_pool_add_destructor (new_task->task_pool, (pool_destruct_func)g_hash_table_destroy, new_task->results);
+ memory_pool_add_destructor (new_task->task_pool, (pool_destruct_func) g_hash_table_destroy, new_task->results);
new_task->re_cache = g_hash_table_new (g_str_hash, g_str_equal);
- memory_pool_add_destructor (new_task->task_pool, (pool_destruct_func)g_hash_table_destroy, new_task->re_cache);
+ memory_pool_add_destructor (new_task->task_pool, (pool_destruct_func) g_hash_table_destroy, new_task->re_cache);
new_task->s = new_async_session (new_task->task_pool, free_task_hard, new_task);
new_task->sock = -1;
static void
accept_socket (int fd, short what, void *arg)
{
- struct rspamd_worker *worker = (struct rspamd_worker *)arg;
- struct sockaddr_storage ss;
- struct sockaddr_in *sin;
- struct worker_task *new_task;
- socklen_t addrlen = sizeof(ss);
- int nfd;
-
+ struct rspamd_worker *worker = (struct rspamd_worker *)arg;
+ struct sockaddr_storage ss;
+ struct sockaddr_in *sin;
+ struct worker_task *new_task;
+ socklen_t addrlen = sizeof (ss);
+ int nfd;
+
if ((nfd = accept_from_socket (fd, (struct sockaddr *)&ss, &addrlen)) == -1) {
msg_warn ("accept_socket: accept failed: %s", strerror (errno));
return;
msg_info ("accept_socket: accepted connection from unix socket");
}
else if (ss.ss_family == AF_INET) {
- sin = (struct sockaddr_in *) &ss;
+ sin = (struct sockaddr_in *)&ss;
msg_info ("accept_socket: accepted connection from %s port %d", inet_ntoa (sin->sin_addr), ntohs (sin->sin_port));
}
new_task = construct_task (worker);
- new_task->sock = nfd;
- worker->srv->stat->connections_count ++;
+ new_task->sock = nfd;
+ worker->srv->stat->connections_count++;
/* Set up dispatcher */
- new_task->dispatcher = rspamd_create_dispatcher (nfd, BUFFER_LINE, read_socket,
- write_socket, err_socket, &io_tv,
- (void *)new_task);
+ new_task->dispatcher = rspamd_create_dispatcher (nfd, BUFFER_LINE, read_socket, write_socket, err_socket, &io_tv, (void *)new_task);
}
void
start_worker (struct rspamd_worker *worker)
{
- struct sigaction signals;
+ struct sigaction signals;
#ifdef WITH_PROFILER
- extern void _start (void), etext (void);
- monstartup ((u_long) &_start, (u_long) &etext);
+ extern void _start (void), etext (void);
+ monstartup ((u_long) & _start, (u_long) & etext);
#endif
gperf_profiler_init (worker->srv->cfg, "worker");
sigprocmask (SIG_UNBLOCK, &signals.sa_mask, NULL);
/* SIGUSR2 handler */
- signal_set (&worker->sig_ev, SIGUSR2, sigusr_handler, (void *) worker);
+ signal_set (&worker->sig_ev, SIGUSR2, sigusr_handler, (void *)worker);
signal_add (&worker->sig_ev, NULL);
/* Accept event */
- event_set(&worker->bind_ev, worker->cf->listen_sock, EV_READ | EV_PERSIST, accept_socket, (void *)worker);
- event_add(&worker->bind_ev, NULL);
+ event_set (&worker->bind_ev, worker->cf->listen_sock, EV_READ | EV_PERSIST, accept_socket, (void *)worker);
+ event_add (&worker->bind_ev, NULL);
/* Maps events */
start_map_watch ();