static gint rspamd_control_finish_handler (struct rspamd_http_connection *conn, struct rspamd_http_message *msg) { struct ucl_parser *parser; ucl_object_t *obj; rspamd_fstring_t *out; const gchar *body; gsize body_len; struct rspamadm_control_cbdata *cbdata = conn->ud; body = rspamd_http_message_get_body (msg, &body_len); parser = ucl_parser_new (0); if (!body || !ucl_parser_add_chunk (parser, body, body_len)) { rspamd_fprintf (stderr, "cannot parse server's reply: %s\n", ucl_parser_get_error (parser)); ucl_parser_free (parser); } else { obj = ucl_parser_get_object (parser); out = rspamd_fstring_new (); if (json) { rspamd_ucl_emit_fstring (obj, UCL_EMIT_JSON, &out); } else if (compact) { rspamd_ucl_emit_fstring (obj, UCL_EMIT_JSON_COMPACT, &out); } else { if (strcmp (cbdata->path, "/fuzzystat") == 0) { rspamadm_execute_lua_ucl_subr (cbdata->L, cbdata->argc, cbdata->argv, obj, rspamadm_script_fuzzy_stat); rspamd_fstring_free (out); ucl_object_unref (obj); ucl_parser_free (parser); return 0; } else { rspamd_ucl_emit_fstring (obj, UCL_EMIT_CONFIG, &out); } } rspamd_fprintf (stdout, "%V", out); rspamd_fstring_free (out); ucl_object_unref (obj); ucl_parser_free (parser); } return 0; }
static void rspamd_ucl_fin_cb (rspamd_mempool_t * pool, struct map_cb_data *data) { struct rspamd_ucl_map_cbdata *cbdata = data->cur_data, *prev = data->prev_data; ucl_object_t *obj; struct ucl_parser *parser; guint32 checksum; ucl_object_iter_t it = NULL; const ucl_object_t *cur; struct rspamd_config *cfg = data->map->cfg; if (prev != NULL) { if (prev->buf != NULL) { g_string_free (prev->buf, TRUE); } g_free (prev); } if (cbdata == NULL) { msg_err_config ("map fin error: new data is NULL"); return; } checksum = XXH64 (cbdata->buf->str, cbdata->buf->len, 0); if (data->map->checksum != checksum) { /* New data available */ parser = ucl_parser_new (0); if (!ucl_parser_add_chunk (parser, cbdata->buf->str, cbdata->buf->len)) { msg_err_config ("cannot parse map %s: %s", data->map->uri, ucl_parser_get_error (parser)); ucl_parser_free (parser); } else { obj = ucl_parser_get_object (parser); ucl_parser_free (parser); it = NULL; while ((cur = ucl_iterate_object (obj, &it, true))) { ucl_object_replace_key (cbdata->cfg->rcl_obj, (ucl_object_t *)cur, cur->key, cur->keylen, false); } ucl_object_unref (obj); data->map->checksum = checksum; } } else { msg_info_config ("do not reload map %s, checksum is the same: %d", data->map->uri, checksum); } }
static gint rspamd_client_finish_handler (struct rspamd_http_connection *conn, struct rspamd_http_message *msg) { struct rspamd_client_request *req = (struct rspamd_client_request *)conn->ud; struct rspamd_client_connection *c; struct ucl_parser *parser; GError *err; c = req->conn; if (!c->req_sent) { c->req_sent = TRUE; rspamd_http_connection_reset (c->http_conn); rspamd_http_connection_read_message (c->http_conn, c->req, c->fd, &c->timeout, c->ev_base); return 0; } else { if (rspamd_http_message_get_body (msg, NULL) == NULL || msg->code != 200) { err = g_error_new (RCLIENT_ERROR, msg->code, "HTTP error: %d, %.*s", msg->code, (gint)msg->status->len, msg->status->str); req->cb (c, msg, c->server_name->str, NULL, req->input, req->ud, err); g_error_free (err); return 0; } parser = ucl_parser_new (0); if (!ucl_parser_add_chunk (parser, msg->body_buf.begin, msg->body_buf.len)) { err = g_error_new (RCLIENT_ERROR, msg->code, "Cannot parse UCL: %s", ucl_parser_get_error (parser)); ucl_parser_free (parser); req->cb (c, msg, c->server_name->str, NULL, req->input, req->ud, err); g_error_free (err); return 0; } req->cb (c, msg, c->server_name->str, ucl_parser_get_object ( parser), req->input, req->ud, NULL); ucl_parser_free (parser); } return 0; }
static ucl_object_t * keyword_open_schema(void) { struct ucl_parser *parser; static const char keyword_schema_str[] = "" "{" " type = object;" " properties {" " actions = { " " type = array; " " items = { type = string }; " " uniqueItems: true " " }; " " attributes = { " " type = object; " " properties { " " owner = { type = string }; " " group = { type = string }; " " mode = { oneOf: [ { type = integer }, { type = string } ] }; " " }" " }; " " pre-install = { type = string }; " " post-install = { type = string }; " " pre-deinstall = { type = string }; " " post-deinstall = { type = string }; " " pre-upgrade = { type = string }; " " post-upgrade = { type = string }; " " }" "}"; if (keyword_schema != NULL) return (keyword_schema); parser = ucl_parser_new(0); if (!ucl_parser_add_chunk(parser, keyword_schema_str, sizeof(keyword_schema_str) -1)) { pkg_emit_error("Cannot parse schema for keywords: %s", ucl_parser_get_error(parser)); ucl_parser_free(parser); return (NULL); } keyword_schema = ucl_parser_get_object(parser); ucl_parser_free(parser); return (keyword_schema); }
void parse_conf(jail_conf_t *jail_conf, uint8_t *buf, size_t len) { struct ucl_parser *parser = ucl_parser_new(UCL_PARSER_NO_TIME); ucl_parser_add_chunk(parser, buf, len); if (ucl_parser_get_error(parser)) die("Config: Could not parse"); // TODO: output the error ucl_object_t *root = ucl_parser_get_object(parser); jail_conf->hostname = NULL; jail_conf->jailname = NULL; jail_conf->net_iface = NULL; jail_conf->script = NULL; jail_conf->securelevel = 3; jail_conf->devfs_ruleset = 4; bzero(jail_conf->ipv4, sizeof(jail_conf->ipv4)); bzero(jail_conf->ipv6, sizeof(jail_conf->ipv6)); bzero(jail_conf->limits, sizeof(jail_conf->limits)); bzero(jail_conf->mounts, sizeof(jail_conf->mounts)); ucl_iterate(root, true, ^(ucl_object_t *cur) { char *key = ucl_object_key(cur); if (strcmp(key, "hostname") == 0) { STR_TO_ARENA(jail_conf->hostname, ucl_object_tostring_forced(cur)); } else if (strcmp(key, "jailname") == 0) { STR_TO_ARENA(jail_conf->jailname, ucl_object_tostring_forced(cur)); } else if (strcmp(key, "script") == 0) { STR_TO_ARENA(jail_conf->script, ucl_object_tostring_forced(cur)); } else if (strcmp(key, "net_iface") == 0) { STR_TO_ARENA(jail_conf->net_iface, ucl_object_tostring_forced(cur)); } else if (strcmp(key, "securelevel") == 0) { int64_t int_val = -1; if (ucl_object_toint_safe(cur, &int_val) != true) die("Config: securelevel is not a number"); jail_conf->securelevel = (int8_t)int_val; } else if (strcmp(key, "devfs_ruleset") == 0) { int64_t int_val = -1; if (ucl_object_toint_safe(cur, &int_val) != true) die("Config: devfs_ruleset is not a number"); jail_conf->devfs_ruleset = (int16_t)int_val; } else if (strcmp(key, "ipv4") == 0) { __block size_t i = 0; ucl_iterate(cur, false, ^(ucl_object_t *val) { if (i > IPV4_ADDRS_LEN) die("Config: Too many IPv4 addresses"); STR_TO_ARENA(jail_conf->ipv4[i], ucl_object_tostring_forced(val)); i++; });
/*** * @function rspamd_cryptobox_keypair.create(ucl_data) * Loads public key from UCL data * @param {string} ucl_data ucl to load * @return {cryptobox_keypair} new keypair */ static gint lua_cryptobox_keypair_create (lua_State *L) { struct rspamd_cryptobox_keypair *kp, **pkp; const gchar *buf; gsize len; struct ucl_parser *parser; ucl_object_t *obj; buf = luaL_checklstring (L, 1, &len); if (buf != NULL) { parser = ucl_parser_new (0); if (!ucl_parser_add_chunk (parser, buf, len)) { msg_err ("cannot open keypair from data: %s", ucl_parser_get_error (parser)); ucl_parser_free (parser); lua_pushnil (L); } else { obj = ucl_parser_get_object (parser); kp = rspamd_keypair_from_ucl (obj); ucl_parser_free (parser); if (kp == NULL) { msg_err ("cannot load keypair from data"); ucl_object_unref (obj); lua_pushnil (L); } else { pkp = lua_newuserdata (L, sizeof (gpointer)); *pkp = kp; rspamd_lua_setclass (L, "rspamd{cryptobox_keypair}", -1); ucl_object_unref (obj); } } } else { luaL_error (L, "bad input arguments"); } return 1; }
int main(int argc, char **argv) { const char *fn = NULL; unsigned char *inbuf; struct ucl_parser *parser; int k, ret = 0, r = 0; ssize_t bufsize; ucl_object_t *obj = NULL; const ucl_object_t *par; FILE *in; if (argc > 1) { fn = argv[1]; } if (fn != NULL) { in = fopen (fn, "r"); if (in == NULL) { exit (-errno); } } else { in = stdin; } parser = ucl_parser_new (0); inbuf = malloc (BUFSIZ); bufsize = BUFSIZ; r = 0; while (!feof (in) && !ferror (in)) { if (r == bufsize) { inbuf = realloc (inbuf, bufsize * 2); bufsize *= 2; if (inbuf == NULL) { perror ("realloc"); exit (EXIT_FAILURE); } } r += fread (inbuf + r, 1, bufsize - r, in); } if (ferror (in)) { fprintf (stderr, "Failed to read the input file.\n"); exit (EXIT_FAILURE); } ucl_parser_add_chunk (parser, inbuf, r); fclose (in); if (ucl_parser_get_error(parser)) { printf ("Error occured: %s\n", ucl_parser_get_error(parser)); ret = 1; goto end; } obj = ucl_parser_get_object (parser); if (ucl_parser_get_error (parser)) { printf ("Error occured: %s\n", ucl_parser_get_error(parser)); ret = 1; goto end; } if (argc > 2) { for (k = 2; k < argc; k++) { printf ("search for \"%s\"... ", argv[k]); par = ucl_object_find_key (obj, argv[k]); printf ("%sfound\n", (par == NULL )?"not ":""); ucl_obj_dump (par, 0); } } else { ucl_obj_dump (obj, 0); } end: if (parser != NULL) { ucl_parser_free (parser); } if (obj != NULL) { ucl_object_unref (obj); } return ret; }
int main (int argc, char **argv) { char inbuf[8192], *test_in = NULL; struct ucl_parser *parser = NULL, *parser2 = NULL; ucl_object_t *obj; FILE *in, *out; unsigned char *emitted = NULL; const char *fname_in = NULL, *fname_out = NULL; int ret = 0, inlen, opt, json = 0, compact = 0, yaml = 0; while ((opt = getopt(argc, argv, "jcy")) != -1) { switch (opt) { case 'j': json = 1; break; case 'c': compact = 1; break; case 'y': yaml = 1; break; default: /* '?' */ fprintf (stderr, "Usage: %s [-jcy] [in] [out]\n", argv[0]); exit (EXIT_FAILURE); } } argc -= optind; argv += optind; switch (argc) { case 1: fname_in = argv[0]; break; case 2: fname_in = argv[0]; fname_out = argv[1]; break; } if (fname_in != NULL) { in = fopen (fname_in, "r"); if (in == NULL) { exit (-errno); } } else { in = stdin; } parser = ucl_parser_new (UCL_PARSER_KEY_LOWERCASE); ucl_parser_register_variable (parser, "ABI", "unknown"); if (fname_in != NULL) { ucl_parser_set_filevars (parser, fname_in, true); } while (!feof (in)) { memset (inbuf, 0, sizeof (inbuf)); if (fread (inbuf, 1, sizeof (inbuf) - 1, in) == 0) { break; } inlen = strlen (inbuf); test_in = malloc (inlen); memcpy (test_in, inbuf, inlen); ucl_parser_add_chunk (parser, test_in, inlen); } fclose (in); if (fname_out != NULL) { out = fopen (fname_out, "w"); if (out == NULL) { exit (-errno); } } else { out = stdout; } if (ucl_parser_get_error (parser) != NULL) { fprintf (out, "Error occurred: %s\n", ucl_parser_get_error(parser)); ret = 1; goto end; } obj = ucl_parser_get_object (parser); if (json) { if (compact) { emitted = ucl_object_emit (obj, UCL_EMIT_JSON_COMPACT); } else { emitted = ucl_object_emit (obj, UCL_EMIT_JSON); } } else if (yaml) { emitted = ucl_object_emit (obj, UCL_EMIT_YAML); } else { emitted = ucl_object_emit (obj, UCL_EMIT_CONFIG); } ucl_parser_free (parser); ucl_object_unref (obj); parser2 = ucl_parser_new (UCL_PARSER_KEY_LOWERCASE); ucl_parser_add_string (parser2, emitted, 0); if (ucl_parser_get_error(parser2) != NULL) { fprintf (out, "Error occurred: %s\n", ucl_parser_get_error(parser2)); fprintf (out, "%s\n", emitted); ret = 1; goto end; } if (emitted != NULL) { free (emitted); } obj = ucl_parser_get_object (parser2); if (json) { if (compact) { emitted = ucl_object_emit (obj, UCL_EMIT_JSON_COMPACT); } else { emitted = ucl_object_emit (obj, UCL_EMIT_JSON); } } else if (yaml) { emitted = ucl_object_emit (obj, UCL_EMIT_YAML); } else { emitted = ucl_object_emit (obj, UCL_EMIT_CONFIG); } fprintf (out, "%s\n", emitted); ucl_object_unref (obj); end: if (emitted != NULL) { free (emitted); } if (parser2 != NULL) { ucl_parser_free (parser2); } if (test_in != NULL) { free (test_in); } fclose (out); return ret; }
int main(int argc, char **argv) { const char *fn = NULL; char inbuf[8192]; struct ucl_parser *parser; int k, ret = 0, r = 0; ucl_object_t *obj = NULL; const ucl_object_t *par; FILE *in; if (argc > 1) { fn = argv[1]; } if (fn != NULL) { in = fopen (fn, "r"); if (in == NULL) { exit (-errno); } } else { in = stdin; } parser = ucl_parser_new (0); while (!feof (in) && r < (int)sizeof (inbuf)) { r += fread (inbuf + r, 1, sizeof (inbuf) - r, in); } ucl_parser_add_chunk (parser, inbuf, r); fclose (in); if (ucl_parser_get_error(parser)) { printf ("Error occured: %s\n", ucl_parser_get_error(parser)); ret = 1; goto end; } obj = ucl_parser_get_object (parser); if (ucl_parser_get_error (parser)) { printf ("Error occured: %s\n", ucl_parser_get_error(parser)); ret = 1; goto end; } if (argc > 2) { for (k = 2; k < argc; k++) { printf ("search for \"%s\"... ", argv[k]); par = ucl_object_find_key (obj, argv[k]); printf ("%sfound\n", (par == NULL )?"not ":""); ucl_obj_dump (par, 0); } } else { ucl_obj_dump (obj, 0); } end: if (parser != NULL) { ucl_parser_free (parser); } if (obj != NULL) { ucl_object_unref (obj); } return ret; }
gboolean rspamd_task_load_message (struct rspamd_task *task, struct rspamd_http_message *msg, const gchar *start, gsize len) { guint control_len, r; struct ucl_parser *parser; ucl_object_t *control_obj; gchar filepath[PATH_MAX], *fp; gint fd, flen; gpointer map; struct stat st; if (msg) { rspamd_protocol_handle_headers (task, msg); } if (task->flags & RSPAMD_TASK_FLAG_FILE) { g_assert (task->msg.len > 0); r = rspamd_strlcpy (filepath, task->msg.start, MIN (sizeof (filepath), task->msg.len + 1)); rspamd_decode_url (filepath, filepath, r + 1); flen = strlen (filepath); if (filepath[0] == '"' && flen > 2) { /* We need to unquote filepath */ fp = &filepath[1]; fp[flen - 2] = '\0'; } else { fp = &filepath[0]; } if (access (fp, R_OK) == -1 || stat (fp, &st) == -1) { g_set_error (&task->err, rspamd_task_quark(), RSPAMD_PROTOCOL_ERROR, "Invalid file (%s): %s", fp, strerror (errno)); return FALSE; } fd = open (fp, O_RDONLY); if (fd == -1) { g_set_error (&task->err, rspamd_task_quark(), RSPAMD_PROTOCOL_ERROR, "Cannot open file (%s): %s", fp, strerror (errno)); return FALSE; } map = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0); if (map == MAP_FAILED) { close (fd); g_set_error (&task->err, rspamd_task_quark(), RSPAMD_PROTOCOL_ERROR, "Cannot mmap file (%s): %s", fp, strerror (errno)); return FALSE; } close (fd); task->msg.start = map; task->msg.len = st.st_size; rspamd_mempool_add_destructor (task->task_pool, rspamd_task_unmapper, task); } else { debug_task ("got input of length %z", task->msg.len); task->msg.start = start; task->msg.len = len; if (task->msg.len == 0) { msg_warn_task ("message has invalid message length: %ud", task->msg.len); g_set_error (&task->err, rspamd_task_quark(), RSPAMD_PROTOCOL_ERROR, "Invalid length"); return FALSE; } if (task->flags & RSPAMD_TASK_FLAG_HAS_CONTROL) { /* We have control chunk, so we need to process it separately */ if (task->msg.len < task->message_len) { msg_warn_task ("message has invalid message length: %ud and total len: %ud", task->message_len, task->msg.len); g_set_error (&task->err, rspamd_task_quark(), RSPAMD_PROTOCOL_ERROR, "Invalid length"); return FALSE; } control_len = task->msg.len - task->message_len; if (control_len > 0) { parser = ucl_parser_new (UCL_PARSER_KEY_LOWERCASE); if (!ucl_parser_add_chunk (parser, task->msg.start, control_len)) { msg_warn_task ("processing of control chunk failed: %s", ucl_parser_get_error (parser)); ucl_parser_free (parser); } else { control_obj = ucl_parser_get_object (parser); ucl_parser_free (parser); rspamd_protocol_handle_control (task, control_obj); ucl_object_unref (control_obj); } task->msg.start += control_len; task->msg.len -= control_len; } } } return TRUE; }
void json_config_fin_cb (rspamd_mempool_t * pool, struct map_cb_data *data) { struct config_json_buf *jb; ucl_object_t *top; struct ucl_parser *parser; if (data->prev_data) { jb = data->prev_data; /* Clean prev data */ if (jb->buf) { g_free (jb->buf); } g_free (jb); } /* Now parse json */ if (data->cur_data) { jb = data->cur_data; } else { msg_err ("no data read"); return; } if (jb->buf == NULL) { msg_err ("no data read"); return; } /* NULL terminate current buf */ *jb->pos = '\0'; parser = ucl_parser_new (0); if (!ucl_parser_add_chunk (parser, jb->buf, jb->pos - jb->buf)) { msg_err ("cannot load json data: parse error %s", ucl_parser_get_error (parser)); ucl_parser_free (parser); return; } top = ucl_parser_get_object (parser); ucl_parser_free (parser); if (ucl_object_type (top) != UCL_ARRAY) { ucl_object_unref (top); msg_err ("loaded json is not an array"); return; } jb->cfg->current_dynamic_conf = NULL; ucl_object_unref (jb->obj); jb->obj = top; /* * Note about thread safety: we are updating values that are gdoubles so it is not atomic in general case * but on the other hand all that data is used only in the main thread, so why it is *likely* safe * to do this task in this way without explicit lock. */ apply_dynamic_conf (jb->obj, jb->cfg); jb->cfg->current_dynamic_conf = jb->obj; }
static gboolean rspamd_symbols_cache_load_items (struct symbols_cache *cache, const gchar *name) { struct rspamd_symbols_cache_header *hdr; struct stat st; struct ucl_parser *parser; ucl_object_t *top; const ucl_object_t *cur, *elt; ucl_object_iter_t it; struct cache_item *item, *parent; const guchar *p; gint fd; gpointer map; double w; fd = open (name, O_RDONLY); if (fd == -1) { msg_info ("cannot open file %s, error %d, %s", name, errno, strerror (errno)); return FALSE; } if (fstat (fd, &st) == -1) { close (fd); msg_info ("cannot stat file %s, error %d, %s", name, errno, strerror (errno)); return FALSE; } if (st.st_size < (gint)sizeof (*hdr)) { close (fd); errno = EINVAL; msg_info ("cannot use file %s, error %d, %s", name, errno, strerror (errno)); return FALSE; } map = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0); if (map == MAP_FAILED) { close (fd); msg_info ("cannot mmap file %s, error %d, %s", name, errno, strerror (errno)); return FALSE; } close (fd); hdr = map; if (memcmp (hdr->magic, rspamd_symbols_cache_magic, sizeof (rspamd_symbols_cache_magic)) != 0) { msg_info ("cannot use file %s, bad magic", name); munmap (map, st.st_size); return FALSE; } parser = ucl_parser_new (0); p = (const guchar *)(hdr + 1); if (!ucl_parser_add_chunk (parser, p, st.st_size - sizeof (*hdr))) { msg_info ("cannot use file %s, cannot parse: %s", name, ucl_parser_get_error (parser)); munmap (map, st.st_size); ucl_parser_free (parser); return FALSE; } top = ucl_parser_get_object (parser); munmap (map, st.st_size); ucl_parser_free (parser); if (top == NULL || ucl_object_type (top) != UCL_OBJECT) { msg_info ("cannot use file %s, bad object", name); ucl_object_unref (top); return FALSE; } it = ucl_object_iterate_new (top); while ((cur = ucl_object_iterate_safe (it, true))) { item = g_hash_table_lookup (cache->items_by_symbol, ucl_object_key (cur)); if (item) { /* Copy saved info */ elt = ucl_object_find_key (cur, "weight"); if (elt) { w = ucl_object_todouble (elt); if (w != 0) { item->weight = w; } } elt = ucl_object_find_key (cur, "time"); if (elt) { item->avg_time = ucl_object_todouble (elt); } elt = ucl_object_find_key (cur, "count"); if (elt) { item->avg_counter = ucl_object_toint (elt); } elt = ucl_object_find_key (cur, "frequency"); if (elt) { item->frequency = ucl_object_toint (elt); } if (item->type == SYMBOL_TYPE_VIRTUAL && item->parent != -1) { g_assert (item->parent < (gint)cache->items_by_id->len); parent = g_ptr_array_index (cache->items_by_id, item->parent); if (parent->weight < item->weight) { parent->weight = item->weight; } /* * We maintain avg_time for virtual symbols equal to the * parent item avg_time */ parent->avg_time = item->avg_time; parent->avg_counter = item->avg_counter; } if (fabs (item->weight) > cache->max_weight) { cache->max_weight = fabs (item->weight); } cache->total_freq += item->frequency; } } ucl_object_iterate_free (it); ucl_object_unref (top); return TRUE; }
int main(int argc, char **argv) { char ch; FILE *in = stdin, *out = stdout; const char *schema = NULL; unsigned char *buf = NULL; size_t size = 0, r = 0; struct ucl_parser *parser = NULL; ucl_object_t *obj = NULL; ucl_emitter_t emitter = UCL_EMIT_CONFIG; while((ch = getopt_long(argc, argv, "hi:o:s:f:", opts, NULL)) != -1) { switch (ch) { case 'i': in = fopen(optarg, "r"); if (in == NULL) { perror("fopen on input file"); exit(EXIT_FAILURE); } break; case 'o': out = fopen(optarg, "w"); if (out == NULL) { perror("fopen on output file"); exit(EXIT_FAILURE); } break; case 's': schema = optarg; break; case 'f': if (strcmp(optarg, "ucl") == 0) { emitter = UCL_EMIT_CONFIG; } else if (strcmp(optarg, "json") == 0) { emitter = UCL_EMIT_JSON; } else if (strcmp(optarg, "yaml") == 0) { emitter = UCL_EMIT_YAML; } else if (strcmp(optarg, "compact_json") == 0) { emitter = UCL_EMIT_JSON_COMPACT; } else if (strcmp(optarg, "msgpack") == 0) { emitter = UCL_EMIT_MSGPACK; } else { fprintf(stderr, "Unknown output format: %s\n", optarg); exit(EXIT_FAILURE); } break; case 'h': usage(argv[0], stdout); exit(0); default: usage(argv[0], stderr); exit(EXIT_FAILURE); break; } } parser = ucl_parser_new(0); buf = malloc(BUFSIZ); size = BUFSIZ; while(!feof(in) && !ferror(in)) { if (r == size) { buf = realloc(buf, size*2); size *= 2; if (buf == NULL) { perror("realloc"); exit(EXIT_FAILURE); } } r += fread(buf + r, 1, size - r, in); } if (ferror(in)) { fprintf(stderr, "Failed to read the input file.\n"); exit(EXIT_FAILURE); } fclose(in); if (!ucl_parser_add_chunk(parser, buf, r)) { fprintf(stderr, "Failed to parse input file: %s\n", ucl_parser_get_error(parser)); exit(EXIT_FAILURE); } if ((obj = ucl_parser_get_object(parser)) == NULL) { fprintf(stderr, "Failed to get root object: %s\n", ucl_parser_get_error(parser)); exit(EXIT_FAILURE); } if (schema != NULL) { struct ucl_parser *schema_parser = ucl_parser_new(0); ucl_object_t *schema_obj = NULL; struct ucl_schema_error error; if (!ucl_parser_add_file(schema_parser, schema)) { fprintf(stderr, "Failed to parse schema file: %s\n", ucl_parser_get_error(schema_parser)); exit(EXIT_FAILURE); } if ((schema_obj = ucl_parser_get_object(schema_parser)) == NULL) { fprintf(stderr, "Failed to get root object: %s\n", ucl_parser_get_error(schema_parser)); exit(EXIT_FAILURE); } if (!ucl_object_validate(schema_obj, obj, &error)) { fprintf(stderr, "Validation failed: %s\n", error.msg); exit(EXIT_FAILURE); } } if (emitter != UCL_EMIT_MSGPACK) { fprintf(out, "%s\n", ucl_object_emit(obj, emitter)); } else { size_t len; unsigned char *res; res = ucl_object_emit_len(obj, emitter, &len); fwrite(res, 1, len, out); } return 0; }
static gint rspamd_client_finish_handler (struct rspamd_http_connection *conn, struct rspamd_http_message *msg) { struct rspamd_client_request *req = (struct rspamd_client_request *)conn->ud; struct rspamd_client_connection *c; struct ucl_parser *parser; GError *err; const rspamd_ftok_t *tok; c = req->conn; if (!c->req_sent) { c->req_sent = TRUE; rspamd_http_connection_reset (c->http_conn); rspamd_http_connection_read_message (c->http_conn, c->req, c->fd, &c->timeout, c->ev_base); return 0; } else { if (rspamd_http_message_get_body (msg, NULL) == NULL || msg->code != 200) { err = g_error_new (RCLIENT_ERROR, msg->code, "HTTP error: %d, %.*s", msg->code, (gint)msg->status->len, msg->status->str); req->cb (c, msg, c->server_name->str, NULL, req->input, req->ud, err); g_error_free (err); return 0; } tok = rspamd_http_message_find_header (msg, "compression"); if (tok) { /* Need to uncompress */ rspamd_ftok_t t; t.begin = "zstd"; t.len = 4; if (rspamd_ftok_casecmp (tok, &t) == 0) { ZSTD_DStream *zstream; ZSTD_inBuffer zin; ZSTD_outBuffer zout; guchar *out; gsize outlen, r; zstream = ZSTD_createDStream (); ZSTD_initDStream (zstream); zin.pos = 0; zin.src = msg->body_buf.begin; zin.size = msg->body_buf.len; if ((outlen = ZSTD_getDecompressedSize (zin.src, zin.size)) == 0) { outlen = ZSTD_DStreamOutSize (); } out = g_malloc (outlen); zout.dst = out; zout.pos = 0; zout.size = outlen; while (zin.pos < zin.size) { r = ZSTD_decompressStream (zstream, &zout, &zin); if (ZSTD_isError (r)) { err = g_error_new (RCLIENT_ERROR, 500, "Decompression error: %s", ZSTD_getErrorName (r)); req->cb (c, msg, c->server_name->str, NULL, req->input, req->ud, err); g_error_free (err); ZSTD_freeDStream (zstream); g_free (out); return 0; } if (zout.pos == zout.size) { /* We need to extend output buffer */ zout.size = zout.size * 1.5 + 1.0; zout.dst = g_realloc (zout.dst, zout.size); } } ZSTD_freeDStream (zstream); parser = ucl_parser_new (0); if (!ucl_parser_add_chunk (parser, zout.dst, zout.pos)) { err = g_error_new (RCLIENT_ERROR, msg->code, "Cannot parse UCL: %s", ucl_parser_get_error (parser)); ucl_parser_free (parser); req->cb (c, msg, c->server_name->str, NULL, req->input, req->ud, err); g_error_free (err); g_free (zout.dst); return 0; } g_free (zout.dst); } else { err = g_error_new (RCLIENT_ERROR, 500, "Invalid compression method"); req->cb (c, msg, c->server_name->str, NULL, req->input, req->ud, err); g_error_free (err); return 0; } } else { parser = ucl_parser_new (0); if (!ucl_parser_add_chunk (parser, msg->body_buf.begin, msg->body_buf.len)) { err = g_error_new (RCLIENT_ERROR, msg->code, "Cannot parse UCL: %s", ucl_parser_get_error (parser)); ucl_parser_free (parser); req->cb (c, msg, c->server_name->str, NULL, req->input, req->ud, err); g_error_free (err); return 0; } } req->cb (c, msg, c->server_name->str, ucl_parser_get_object ( parser), req->input, req->ud, NULL); ucl_parser_free (parser); } return 0; }