Exemple #1
0
static rstatus_t
conf_validate_server(struct conf *cf, struct conf_pool *cp)
{
    uint32_t i, nserver;
    bool valid;

    nserver = array_n(&cp->server);
    if (nserver == 0) {
        log_error("conf: pool '%.*s' has no servers", cp->name.len,
                  cp->name.data);
        return NC_ERROR;
    }

    /*
     * Disallow duplicate servers - servers with identical "host:port:weight"
     * or "name" combination are considered as duplicates
     */
    array_sort(&cp->server, conf_server_pname_cmp);
    for (valid = true, i = 0; i < nserver - 1; i++) {
        struct conf_server *cs1, *cs2;

        cs1 = array_get(&cp->server, i);
        cs2 = array_get(&cp->server, i + 1);

        if (string_compare(&cs1->pname, &cs2->pname) == 0) {
            log_error("conf: pool '%.*s' has servers with same name '%.*s'",
                    cp->name.len, cp->name.data, cs1->pname.len,
                    cs1->pname.data);
            valid = false;
            break;
        }
    }
    if (!valid) {
        return NC_ERROR;
    }

    array_sort(&cp->server, conf_server_name_cmp);
    for (valid = true, i = 0; i < nserver - 1; i++) {
        struct conf_server *cs1, *cs2;

        cs1 = array_get(&cp->server, i);
        cs2 = array_get(&cp->server, i + 1);

        if (string_compare(&cs1->name, &cs2->name) == 0) {
            log_error("conf: pool '%.*s' has servers with same name '%.*s'",
                      cp->name.len, cp->name.data, cs1->name.len, 
                      cs1->name.data);
            valid = false;
            break;
        }
    }
    if (!valid) {
        return NC_ERROR;
    }

    return NC_OK;
}
Exemple #2
0
/**
 * Creates an event for the unfolding
 */
event_t *nc_event_new(trans_t *tr, array_t *pre, array_t *read)
{
	event_t *ev = (event_t*)MYmalloc(sizeof(event_t));
	ev->num = event_last++;
	
	ev->origin = tr;
	ev->preset = pre;
	ev->readarcs = read;
	
	// Adds a new condition for each place in the postset:
	array_t *post = ev->postset = array_new(tr->postset_size);
	nodelist_t *ps = tr->postset;
	while (ps) {
		cond_t *cond = nc_cond_new(ps->node, ev);
		array_append(post, cond);
		ps = ps->next;
	}
	array_sort(post);
#ifdef __DEBUG__
	g_assert(array_ordered(post));
#endif

	ev->hist = g_hash_table_new(NULL, NULL);
	
	return ev;
}
Exemple #3
0
static int
conf_validate_group(struct conf *cf, struct conf_pool *cp)
{
    uint32_t i, n;
    bool valid;

    n = array_n(&cp->groups);
    if (n == 0) {
        log_error("conf: pool '%.*s' has no groups", cp->name.len,
                  cp->name.data);
        return NC_ERROR;
    }

    array_sort(&cp->groups, conf_group_name_cmp);
    for (valid = true, i = 0; i < n -1; i++) {
        struct string *s1, *s2;

        s1 = array_get(&cp->groups, i);
        s2 = array_get(&cp->groups, i + 1);

        if (string_compare(s1, s2) == 0) {
            log_error("conf: pool '%.*s' has group with same name '%.*s'",
                      cp->name.len, cp->name.data, s1->len, s1->data);
            valid = false;
            break;
        }
    }
    if (!valid) {
        return NC_ERROR;
    }

    return NC_OK;
}
Exemple #4
0
static uint32_t
maildir_save_set_recent_flags(struct maildir_save_context *ctx)
{
	struct maildir_mailbox *mbox = ctx->mbox;
	ARRAY_TYPE(seq_range) saved_sorted_uids;
	const struct seq_range *uids;
	unsigned int i, count;
	uint32_t uid;

	count = array_count(&ctx->ctx.transaction->changes->saved_uids);
	if (count == 0)
		return 0;

	t_array_init(&saved_sorted_uids, count);
	array_append_array(&saved_sorted_uids,
			   &ctx->ctx.transaction->changes->saved_uids);
	array_sort(&saved_sorted_uids, seq_range_cmp);

	uids = array_get(&saved_sorted_uids, &count);
	for (i = 0; i < count; i++) {
		for (uid = uids[i].seq1; uid <= uids[i].seq2; uid++)
			mailbox_recent_flags_set_uid(&mbox->box, uid);
	}
	return uids[count-1].seq2 + 1;
}
Exemple #5
0
void acl_rights_sort(struct acl_object *aclobj)
{
	struct acl_rights *rights;
	unsigned int i, dest, count;

	if (!array_is_created(&aclobj->rights))
		return;

	array_sort(&aclobj->rights, acl_rights_cmp);

	/* merge identical identifiers */
	rights = array_get_modifiable(&aclobj->rights, &count);
	for (dest = 0, i = 1; i < count; i++) {
		if (acl_rights_cmp(&rights[i], &rights[dest]) == 0) {
			/* add i's rights to dest and delete i */
			acl_right_names_merge(aclobj->rights_pool,
					      &rights[dest].rights,
					      rights[i].rights, FALSE);
			acl_right_names_merge(aclobj->rights_pool,
					      &rights[dest].neg_rights,
					      rights[i].neg_rights, FALSE);
		} else {
			if (++dest != i)
				rights[dest] = rights[i];
		}
	}
	if (++dest != count)
		array_delete(&aclobj->rights, dest, count - dest);
}
void mail_index_transaction_sort_expunges(struct mail_index_transaction *t)
{
	if (!t->expunges_nonsorted)
		return;

	array_sort(&t->expunges, mail_transaction_expunge_guid_cmp);
	t->expunges_nonsorted = FALSE;
}
Exemple #7
0
struct command *command_find(const char *name)
{
	if (commands_unsorted) {
		array_sort(&managesieve_commands, command_cmp);
		commands_unsorted = FALSE;
	}

	return array_bsearch(&managesieve_commands, name, command_bsearch);
}
Exemple #8
0
static void
index_sort_list_finish_size(struct mail_search_sort_program *program)
{
	ARRAY_TYPE(mail_sort_node_size) *nodes = program->context;

	array_sort(nodes, sort_node_size_cmp);
	memcpy(&program->seqs, nodes, sizeof(program->seqs));
	i_free(nodes);
	program->context = NULL;
}
Exemple #9
0
int rotate_log(struct rotator *rr,char *filename) {
  char *dir,*base,*oldname,*newname;
  DIR *dirh;
  struct dirent des,*de;
  struct array *names;
  struct assoc *changes,*orders;
  int order,i,n;

  dirbasename(filename,&dir,&base);
  log_debug(("Rotating in '%s'",dir));
  dirh = opendir(dir);
  if(!dirh) {
    log_error(("Could not rotate log file"));
    return 1;
  }
  names = array_create(type_free,0);
  changes = assoc_create(0,0,type_free,0);
  orders = assoc_create(0,0,type_free,0);
  while(1) {
    if(readdir_r(dirh,&des,&de)) {
      log_error(("Problem reading directory during log rotation"));
      break;
    }
    if(!de) { break; }
    order = matching_file(rr,filename,de->d_name,&newname);
    if(order == MATCH_IGNORE) { continue; }
    if(order == MATCH_DELETE) {
      log_debug(("delete %s",de->d_name));
      unlink(de->d_name);
    } else {
      oldname = strdup(de->d_name);
      array_insert(names,oldname);
      assoc_set(changes,oldname,newname);
      assoc_set(orders,oldname,make_int(order));
    }
  }
  if(closedir(dirh)) {
    log_error(("Could not closedir during log rotation!"));
    /* But continue: what else to do? */
  }
  array_sort(names,sort_names,orders);
  n = array_length(names);
  for(i=0;i<n;i++) {
    oldname = array_index(names,i);
    newname = assoc_lookup(changes,oldname);
    log_warn(("name=%s -> %s",oldname,newname));
    rename_file(rr,dir,oldname,newname);
  }
  assoc_release(changes);
  assoc_release(orders);
  array_release(names);
  free(dir);
  free(base);
  return 0;
}
const struct mail_search_register_arg *
mail_search_register_get(struct mail_search_register *reg,
			 unsigned int *count_r)
{
	if (!reg->args_sorted) {
		array_sort(&reg->args, mail_search_register_arg_cmp);
		reg->args_sorted = TRUE;
	}

	return array_get(&reg->args, count_r);
}
TEST(cpp_sorter_test, char_arr_sort)
{
    char arr[] = {'a','b','c','d','e','f','g','h','a','b'};
    char eq[]  = {'a','a','b','b','c','d','e','f','g','h'};
    int sz = sizeof(arr)/sizeof(arr[0]);

    array_sort(arr, sz);

    for(int i=0; i<sz; i++)
	EXPECT_EQ(arr[i], eq[i]);
}
Exemple #12
0
static struct smtp_server_command_reg *
smtp_server_command_find(struct smtp_server *server, const char *name)
{
	if (server->commands_unsorted) {
		array_sort(&server->commands_reg, smtp_server_command_cmp);
		server->commands_unsorted = FALSE;
	}

	return array_bsearch(&server->commands_reg,
		name, smtp_server_command_bsearch);
}
TEST(cpp_sorter_test, null_term_str_sort)
{
    char arr[] = "abcdefghab";
    char eq[]  = "aabbcdefgh";
    int sz = sizeof(arr)/sizeof(arr[0]) - 1; // we need it, to avoid terminating \0 in "" definition case

    array_sort(arr, sz);

    for(int i=0; i<sz; i++)
	EXPECT_EQ(arr[i], eq[i]);
}
Exemple #14
0
int set_init()
{
    fs_file fin;
    char *name;

    Array items;
    int i;

    if (sets)
        set_quit();

    sets = array_new(sizeof (struct set));
    curr = 0;

    /*
     * First, load the sets listed in the set file, preserving order.
     */

    if ((fin = fs_open(SET_FILE, "r")))
    {
        while (read_line(&name, fin))
        {
            struct set *s = array_add(sets);

            if (!set_load(s, name))
                array_del(sets);

            free(name);
        }
        fs_close(fin);
    }

    /*
     * Then, scan for any remaining set description files, and add
     * them after the first group in alphabetic order.
     */

    if ((items = fs_dir_scan("", is_unseen_set)))
    {
        array_sort(items, cmp_dir_items);

        for (i = 0; i < array_len(items); i++)
        {
            struct set *s = array_add(sets);

            if (!set_load(s, DIR_ITEM_GET(items, i)->path))
                array_del(sets);
        }

        fs_dir_free(items);
    }

    return array_len(sets);
}
const struct mail_search_register_arg *
mail_search_register_find(struct mail_search_register *reg, const char *key)
{
	struct mail_search_register_arg arg;

	if (!reg->args_sorted) {
		array_sort(&reg->args, mail_search_register_arg_cmp);
		reg->args_sorted = TRUE;
	}

	arg.key = key;
	return array_bsearch(&reg->args, &arg, mail_search_register_arg_cmp);
}
static bool stats_top_round(struct top_context *ctx)
{
#define TOP_CMD "EXPORT\tsession\tconnected\n"
	const char *const *args;
	pool_t tmp_pool;

	if (write_full(ctx->fd, TOP_CMD, strlen(TOP_CMD)) < 0)
		i_fatal("write(%s) failed: %m", ctx->path);

	/* read header */
	if (ctx->headers != NULL) {
		args = read_next_line(ctx->input);
		if (args == NULL)
			i_fatal("read(%s) unexpectedly disconnected", ctx->path);
		if (*args == NULL)
			return TRUE;
		if (str_array_length(args) != ctx->headers_count)
			i_fatal("headers changed");
	} else {
		ctx->headers = p_read_next_line(default_pool, ctx->input);
		if (ctx->headers == NULL)
			i_fatal("read(%s) unexpectedly disconnected", ctx->path);
		if (*ctx->headers == NULL) {
			i_free_and_null(ctx->headers);
			return FALSE;
		}
		ctx->headers_count = str_array_length((void *)ctx->headers);
		if (!stats_header_find(ctx, "last_update", &ctx->last_update_idx))
			i_fatal("last_update header missing");
		if (!stats_header_find(ctx, "user", &ctx->user_idx))
			i_fatal("user header missing");
		stats_top_get_sorting(ctx);
	}

	array_clear(&ctx->lines);
	p_clear(ctx->prev_pool);
	tmp_pool = ctx->prev_pool;
	ctx->prev_pool = ctx->cur_pool;
	ctx->cur_pool = tmp_pool;

	ctx->flip = !ctx->flip;
	stats_read(ctx);
	stats_drop_stale(ctx);

	sort_ctx = ctx;
	array_sort(&ctx->lines, *ctx->lines_sort);
	sort_ctx = NULL;
	return TRUE;
}
Exemple #17
0
static void
index_sort_list_finish_float(struct mail_search_sort_program *program)
{
	ARRAY_TYPE(mail_sort_node_float) *nodes = program->context;

	/* NOTE: higher relevancy is returned first, unlike with all
	   other number based sort keys, so temporarily reverse the search */
	static_node_cmp_context.reverse = !static_node_cmp_context.reverse;
	array_sort(nodes, sort_node_float_cmp);
	static_node_cmp_context.reverse = !static_node_cmp_context.reverse;

	memcpy(&program->seqs, nodes, sizeof(program->seqs));
	i_free(nodes);
	program->context = NULL;
}
Exemple #18
0
static void add_archives(const char *path)
{
    Array archives;
    int i;

    if ((archives = dir_scan(path, is_archive, NULL, NULL)))
    {
        array_sort(archives, cmp_dir_items);

        for (i = 0; i < array_len(archives); i++)
            fs_add_path(DIR_ITEM_GET(archives, i)->path);

        dir_free(archives);
    }
}
Exemple #19
0
void course_init()
{
    fs_file fin;
    char *line;

    Array items;
    int i;

    if (course_state)
        course_free();

    count = 0;

    if ((fin = fs_open(COURSE_FILE, "r")))
    {
        while (count < MAXCRS && read_line(&line, fin))
        {
            if (course_load(&course_v[count], line))
                count++;

            free(line);
        }

        fs_close(fin);

        course_state = 1;
    }

    if ((items = fs_dir_scan("", is_unseen_course)))
    {
        array_sort(items, cmp_dir_items);

        for (i = 0; i < array_len(items) && count < MAXCRS; i++)
            if (course_load(&course_v[count], DIR_ITEM_GET(items, i)->path))
                count++;

        fs_dir_free(items);

        course_state = 1;
    }
}
Exemple #20
0
static rstatus_t
conf_validate_sentinel(struct conf *cf, struct conf_pool *cp)
{
    uint32_t i, n;
    bool valid;

    n = array_n(&cp->sentinels);
    if (n == 0) {
        log_error("conf: pool '%.*s' has no sentinels", cp->name.len,
                  cp->name.data);
        return NC_ERROR;
    }

    /*
     * Disallow duplicate sentinels - sentinels with identical "host:port:weight"
     * or "name" combination are considered as duplicates. When sentinel name
     * is configured, we only check for duplicate "name" and not for duplicate
     * "host:port:weight"
     */
    array_sort(&cp->sentinels, conf_sentinel_name_cmp);
    for (valid = true, i = 0; i < n - 1; i++) {
        struct conf_server *cs1, *cs2;

        cs1 = array_get(&cp->sentinels, i);
        cs2 = array_get(&cp->sentinels, i + 1);

        if (string_compare(&cs1->name, &cs2->name) == 0) {
            log_error("conf: pool '%.*s' has sentinel with same name '%.*s'",
                      cp->name.len, cp->name.data, cs1->name.len,
                      cs1->name.data);
            valid = false;
            break;
        }
    }
    if (!valid) {
        return NC_ERROR;
    }

    return NC_OK;
}
Exemple #21
0
void array_nub(array *array) {
  assert(array != NULL);

  array_sort(array);

  if (array->size < 2)
    return;

  for (int i = 1; i < array->size; i++) {
    void *e, *p;
    e = array_index(array, i);
    p = e - array->el_size;

    if (memcmp(p, e, array->el_size) == 0) {
      array->size--;

      if (i != array->size) {
        memmove(e, e + array->el_size, array->el_size * (array->size - i));
        i--;
      }
    }
  }
}
static int pop3_uidl_assign_by_hdr_hash(struct mailbox *box)
{
	struct pop3_migration_mail_storage *mstorage =
		POP3_MIGRATION_CONTEXT(box->storage);
	struct pop3_migration_mailbox *mbox = POP3_MIGRATION_CONTEXT(box);
	struct pop3_uidl_map *pop3_map;
	struct imap_msg_map *imap_map;
	unsigned int pop3_idx, imap_idx, pop3_count, imap_count;
	unsigned int first_seq, missing_uids_count;
	int ret;

	first_seq = mbox->first_unfound_idx+1;
	if (pop3_map_read_hdr_hashes(box->storage, first_seq) < 0 ||
	    imap_map_read_hdr_hashes(box) < 0)
		return -1;

	array_sort(&mstorage->pop3_uidl_map, pop3_uidl_map_hdr_cmp);
	array_sort(&mbox->imap_msg_map, imap_msg_map_hdr_cmp);

	pop3_map = array_get_modifiable(&mstorage->pop3_uidl_map, &pop3_count);
	imap_map = array_get_modifiable(&mbox->imap_msg_map, &imap_count);

	pop3_idx = imap_idx = 0;
	while (pop3_idx < pop3_count && imap_idx < imap_count) {
		if (!pop3_map[pop3_idx].hdr_sha1_set ||
		    pop3_map[pop3_idx].imap_uid != 0) {
			pop3_idx++;
			continue;
		}
		if (!imap_map[imap_idx].hdr_sha1_set ||
		    imap_map[imap_idx].pop3_uidl != NULL) {
			imap_idx++;
			continue;
		}
		ret = memcmp(pop3_map[pop3_idx].hdr_sha1,
			     imap_map[imap_idx].hdr_sha1,
			     sizeof(pop3_map[pop3_idx].hdr_sha1));
		if (ret < 0)
			pop3_idx++;
		else if (ret > 0)
			imap_idx++;
		else {
			pop3_map[pop3_idx].imap_uid = imap_map[imap_idx].uid;
			imap_map[imap_idx].pop3_uidl =
				pop3_map[pop3_idx].pop3_uidl;
			imap_map[imap_idx].pop3_seq =
				pop3_map[pop3_idx].pop3_seq;
		}
	}
	missing_uids_count = 0;
	for (pop3_idx = 0; pop3_idx < pop3_count; pop3_idx++) {
		if (pop3_map[pop3_idx].imap_uid == 0)
			missing_uids_count++;
	}
	if (missing_uids_count > 0 && !mstorage->all_mailboxes) {
		i_warning("pop3_migration: %u POP3 messages have no "
			  "matching IMAP messages", missing_uids_count);
	}
	array_sort(&mstorage->pop3_uidl_map, pop3_uidl_map_pop3_seq_cmp);
	array_sort(&mbox->imap_msg_map, imap_msg_map_uid_cmp);
	return 0;
}
static void index_mail_parse_header_finish(struct index_mail *mail)
{
	struct mail *_mail = &mail->mail.mail;
	const struct index_mail_line *lines;
	const unsigned char *header, *data;
	const uint8_t *match;
	buffer_t *buf;
	size_t data_size;
	unsigned int i, j, count, match_idx, match_count;
	bool noncontiguous;

	/* sort it first so fields are grouped together and ordered by
	   line number */
	array_sort(&mail->header_lines, header_line_cmp);

	lines = array_get(&mail->header_lines, &count);
	match = array_get(&mail->header_match, &match_count);
	header = buffer_get_data(mail->header_data, NULL);
	buf = buffer_create_dynamic(pool_datastack_create(), 256);

	/* go through all the header lines we found */
	for (i = match_idx = 0; i < count; i = j) {
		/* matches and header lines are both sorted, all matches
		   until lines[i] weren't found */
		while (match_idx < lines[i].field_idx &&
		       match_idx < match_count) {
			if (HEADER_MATCH_USABLE(mail, match[match_idx]) &&
			    mail_cache_field_can_add(_mail->transaction->cache_trans,
						     _mail->seq, match_idx)) {
				/* this header doesn't exist. remember that. */
				i_assert((match[match_idx] &
					  HEADER_MATCH_FLAG_FOUND) == 0);
				index_mail_cache_add_idx(mail, match_idx,
							 "", 0);
			}
			match_idx++;
		}

		if (match_idx < match_count) {
			/* save index to first header line */
			j = i + 1;
			array_idx_set(&mail->header_match_lines, match_idx, &j);
			match_idx++;
		}

		if (!mail_cache_field_can_add(_mail->transaction->cache_trans,
					      _mail->seq, lines[i].field_idx)) {
			/* header is already cached */
			j = i + 1;
			continue;
		}

		/* buffer contains: { uint32_t line_num[], 0, header texts }
		   noncontiguous is just a small optimization.. */
		buffer_set_used_size(buf, 0);
		buffer_append(buf, &lines[i].line_num,
			      sizeof(lines[i].line_num));

		noncontiguous = FALSE;
		for (j = i+1; j < count; j++) {
			if (lines[j].field_idx != lines[i].field_idx)
				break;

			if (lines[j].start_pos != lines[j-1].end_pos)
				noncontiguous = TRUE;
			buffer_append(buf, &lines[j].line_num,
				      sizeof(lines[j].line_num));
		}
		buffer_append_zero(buf, sizeof(uint32_t));

		if (noncontiguous) {
			for (; i < j; i++) {
				buffer_append(buf, header + lines[i].start_pos,
					      lines[i].end_pos -
					      lines[i].start_pos);
			}
			i--;
		} else {
			buffer_append(buf, header + lines[i].start_pos,
				      lines[j-1].end_pos - lines[i].start_pos);
		}

		data = buffer_get_data(buf, &data_size);
		index_mail_cache_add_idx(mail, lines[i].field_idx,
					 data, data_size);
	}

	for (; match_idx < match_count; match_idx++) {
		if (HEADER_MATCH_USABLE(mail, match[match_idx]) &&
		    mail_cache_field_can_add(_mail->transaction->cache_trans,
					     _mail->seq, match_idx)) {
			/* this header doesn't exist. remember that. */
			i_assert((match[match_idx] &
				  HEADER_MATCH_FLAG_FOUND) == 0);
			index_mail_cache_add_idx(mail, match_idx, "", 0);
		}
	}

	mail->data.dont_cache_field_idx = UINT_MAX;
}
Exemple #24
0
void sort_list(struct ptr_list **plist, int (*cmp)(const void *, const void *))
{
	struct ptr_list *head = *plist, *list = head;
	int blocks = 1;

	if (!head)
		return;

	// Sort all the sub-lists
	do {
		array_sort(list->list, list->nr, cmp);
#ifdef PARANOIA
		verify_seq_sorted (list, 1, cmp);
#endif
		list = list->next;
	} while (list != head);

	// Merge the damn things together
	while (1) {
		struct ptr_list *block1 = head;

		do {
			struct ptr_list *block2 = block1;
			struct ptr_list *next, *newhead;
			int i;

			for (i = 0; i < blocks; i++) {
				block2 = block2->next;
				if (block2 == head) {
					if (block1 == head) {
						BEEN_THERE('A');
						*plist = head;
						return;
					}
					BEEN_THERE('B');
					goto next_pass;
				}						
			}

			next = block2;
			for (i = 0; i < blocks; ) {
				next = next->next;
				i++;
				if (next == head) {
					BEEN_THERE('C');
					break;
				}
				BEEN_THERE('D');
			}

			newhead = merge_block_seqs (block1, blocks,
						    block2, i,
						    cmp);
#ifdef PARANOIA
			verify_seq_sorted (newhead, blocks + i, cmp);
#endif
			if (block1 == head) {
				BEEN_THERE('E');
				head = newhead;
			}
			block1 = next;
		} while (block1 != head);
	next_pass:
		blocks <<= 1;
	}
}
Exemple #25
0
static rstatus_t
conf_post_validate(struct conf *cf)
{
    rstatus_t status;
    uint32_t i, npool;
    bool valid;

    ASSERT(cf->sound && cf->parsed);
    ASSERT(!cf->valid);

    npool = array_n(&cf->pool);
    if (npool == 0) {
        log_error("conf: '%.*s' has no pools", cf->fname);
        return NC_ERROR;
    }

    /* validate pool */
    for (i = 0; i < npool; i++) {
        struct conf_pool *cp = array_get(&cf->pool, i);

        status = conf_validate_pool(cf, cp);
        if (status != NC_OK) {
            return status;
        }
    }

    /* disallow pools with duplicate listen: key values */
    array_sort(&cf->pool, conf_pool_listen_cmp);
    for (valid = true, i = 0; i < npool - 1; i++) {
        struct conf_pool *p1, *p2;

        p1 = array_get(&cf->pool, i);
        p2 = array_get(&cf->pool, i + 1);

        if (string_compare(&p1->listen.pname, &p2->listen.pname) == 0) {
            log_error("conf: pools '%.*s' and '%.*s' have the same listen "
                      "address '%.*s'", p1->name.len, p1->name.data,
                      p2->name.len, p2->name.data, p1->listen.pname.len,
                      p1->listen.pname.data);
            valid = false;
            break;
        }
    }
    if (!valid) {
        return NC_ERROR;
    }

    /* disallow pools with duplicate names */
    array_sort(&cf->pool, conf_pool_name_cmp);
    for (valid = true, i = 0; i < npool - 1; i++) {
        struct conf_pool *p1, *p2;

        p1 = array_get(&cf->pool, i);
        p2 = array_get(&cf->pool, i + 1);

        if (string_compare(&p1->name, &p2->name) == 0) {
            log_error("conf: '%s' has pools with same name %.*s'", cf->fname,
                      p1->name.len, p1->name.data);
            valid = false;
            break;
        }
    }
    if (!valid) {
        return NC_ERROR;
    }

    return NC_OK;
}
int rfc2231_parse(struct rfc822_parser_context *ctx,
                  const char *const **result_r)
{
    ARRAY_TYPE(const_string) result;
    ARRAY(struct rfc2231_parameter) rfc2231_params_arr;
    struct rfc2231_parameter rfc2231_param;
    const struct rfc2231_parameter *rfc2231_params;
    const char *key, *value, *p, *p2;
    string_t *str;
    unsigned int i, j, count, next, next_idx;
    bool ok, have_extended, broken = FALSE;
    int ret;

    /* Get a list of all parameters. RFC 2231 uses key*<n>[*]=value pairs,
       which we want to merge to a key[*]=value pair. Save them to a
       separate array. */
    memset(&rfc2231_param, 0, sizeof(rfc2231_param));
    t_array_init(&result, 8);
    t_array_init(&rfc2231_params_arr, 8);
    while ((ret = rfc822_parse_content_param(ctx, &key, &value)) != 0) {
        if (ret < 0) {
            /* try to continue anyway.. */
            broken = TRUE;
            if (ctx->data == ctx->end)
                break;
            ctx->data++;
            continue;
        }
        p = strchr(key, '*');
        if (p != NULL) {
            p2 = p;
            if (p[1] != '\0') {
                p++;
                rfc2231_param.idx = 0;
                for (; *p >= '0' && *p <= '9'; p++) {
                    rfc2231_param.idx =
                        rfc2231_param.idx*10 + *p - '0';
                }
            }
            if (*p != '*')
                rfc2231_param.extended = FALSE;
            else {
                rfc2231_param.extended = TRUE;
                p++;
            }
            if (*p != '\0')
                p = NULL;
            else {
                rfc2231_param.key = t_strdup_until(key, p2);
                rfc2231_param.value = value;
                array_append(&rfc2231_params_arr,
                             &rfc2231_param, 1);
            }
        }
        if (p == NULL) {
            array_append(&result, &key, 1);
            array_append(&result, &value, 1);
        }
    }

    if (array_count(&rfc2231_params_arr) == 0) {
        /* No RFC 2231 parameters */
        array_append_zero(&result); /* NULL-terminate */
        *result_r = array_idx(&result, 0);
        return broken ? -1 : 0;
    }

    /* Merge the RFC 2231 parameters. Since their order isn't guaranteed to
       be ascending, start by sorting them. */
    array_sort(&rfc2231_params_arr, rfc2231_parameter_cmp);
    rfc2231_params = array_get(&rfc2231_params_arr, &count);

    /* keys are now sorted primarily by their name and secondarily by
       their index. If any indexes are missing, fallback to assuming
       these aren't RFC 2231 encoded parameters. */
    str = t_str_new(64);
    for (i = 0; i < count; i = next) {
        ok = TRUE;
        have_extended = FALSE;
        next_idx = 0;
        for (j = i; j < count; j++) {
            if (strcasecmp(rfc2231_params[i].key,
                           rfc2231_params[j].key) != 0)
                break;
            if (rfc2231_params[j].idx != next_idx) {
                /* missing indexes */
                ok = FALSE;
            }
            if (rfc2231_params[j].extended)
                have_extended = TRUE;
            next_idx++;
        }
        next = j;

        if (!ok) {
            /* missing indexes */
            for (j = i; j < next; j++) {
                key = t_strdup_printf(
                          rfc2231_params[j].extended ?
                          "%s*%u*" : "%s*%u",
                          rfc2231_params[j].key,
                          rfc2231_params[j].idx);
                array_append(&result, &key, 1);
                array_append(&result,
                             &rfc2231_params[j].value, 1);
            }
        } else {
            /* everything was successful */
            str_truncate(str, 0);
            if (!rfc2231_params[i].extended && have_extended)
                str_append(str, "''");
            for (j = i; j < next; j++) {
                if (!rfc2231_params[j].extended &&
                        have_extended) {
                    rfc2231_escape(str,
                                   rfc2231_params[j].value);
                } else {
                    str_append(str,
                               rfc2231_params[j].value);
                }
            }
            key = rfc2231_params[i].key;
            if (have_extended)
                key = t_strconcat(key, "*", NULL);
            value = t_strdup(str_c(str));
            array_append(&result, &key, 1);
            array_append(&result, &value, 1);
        }
    }
    array_append_zero(&result); /* NULL-terminate */
    *result_r = array_idx(&result, 0);
    return broken ? -1 : 0;
}
Exemple #27
0
static void
dsync_cache_fields_update(const struct dsync_mailbox *local_box,
			  const struct dsync_mailbox *remote_box,
			  struct mailbox_update *update)
{
	ARRAY_TYPE(mailbox_cache_field) local_sorted, remote_sorted, changes;
	const struct mailbox_cache_field *local_fields, *remote_fields;
	unsigned int li, ri, local_count, remote_count;
	time_t drop_older_timestamp;
	int ret;

	if (array_count(&remote_box->cache_fields) == 0) {
		/* remote has no cached fields. there's nothing to update. */
		return;
	}

	t_array_init(&local_sorted, array_count(&local_box->cache_fields));
	t_array_init(&remote_sorted, array_count(&remote_box->cache_fields));
	array_append_array(&local_sorted, &local_box->cache_fields);
	array_append_array(&remote_sorted, &remote_box->cache_fields);
	array_sort(&local_sorted, mailbox_cache_field_name_cmp);
	array_sort(&remote_sorted, mailbox_cache_field_name_cmp);

	if (array_count(&local_sorted) == 0) {
		/* local has no cached fields. set them to same as remote. */
		array_append_zero(&remote_sorted);
		update->cache_updates = array_idx(&remote_sorted, 0);
		return;
	}

	/* figure out what to change */
	local_fields = array_get(&local_sorted, &local_count);
	remote_fields = array_get(&remote_sorted, &remote_count);
	t_array_init(&changes, local_count + remote_count);
	drop_older_timestamp = ioloop_time - MAIL_CACHE_FIELD_DROP_SECS;

	for (li = ri = 0; li < local_count || ri < remote_count; ) {
		ret = li == local_count ? 1 :
			ri == remote_count ? -1 :
			strcmp(local_fields[li].name, remote_fields[ri].name);
		if (ret == 0) {
			/* field exists in both local and remote */
			const struct mailbox_cache_field *lf = &local_fields[li];
			const struct mailbox_cache_field *rf = &remote_fields[ri];

			if (lf->last_used > rf->last_used ||
			    (lf->last_used == rf->last_used &&
			     lf->decision > rf->decision)) {
				/* use local decision and timestamp */
			} else {
				array_append(&changes, rf, 1);
			}
			li++; ri++;
		} else if (ret < 0) {
			/* remote field doesn't exist */
			li++;
		} else {
			/* local field doesn't exist */
			if (remote_fields[ri].last_used < drop_older_timestamp) {
				/* field hasn't be used for a long time, remote
				   will probably drop this soon as well */
			} else {
				array_append(&changes, &remote_fields[ri], 1);
			}
			ri++;
		}
	}
	i_assert(li == local_count && ri == remote_count);
	if (array_count(&changes) > 0) {
		array_append_zero(&changes);
		update->cache_updates = array_idx(&changes, 0);
	}
}
Exemple #28
0
int set_init()
{
    fs_file fin;
    char *name;

    Array items;
    int i;

    if (sets)
        set_quit();

    sets = array_new(sizeof (struct set));
    curr = 0;

    /*
     * First, load the sets listed in the set file, preserving order.
     */

    if ((fin = fs_open(SET_FILE, "r")))
    {
        while (read_line(&name, fin))
        {
            struct set *s = array_add(sets);

            if (!set_load(s, name))
                array_del(sets);

            free(name);
        }
        fs_close(fin);
    }

    //senquack - added error reporting after getting random errors opening set files:
#ifdef GCWZERO
    else {
        log_printf("Error opening sets file %s\n", SET_FILE);
        log_printf(fs_error());
    }
#endif //GCWZERO

    /*
     * Then, scan for any remaining set description files, and add
     * them after the first group in alphabetic order.
     */

    if ((items = fs_dir_scan("", is_unseen_set)))
    {
        array_sort(items, cmp_dir_items);

        for (i = 0; i < array_len(items); i++)
        {
            struct set *s = array_add(sets);

            if (!set_load(s, DIR_ITEM_GET(items, i)->path))
                array_del(sets);
        }

        fs_dir_free(items);
    }

    return array_len(sets);
}
static void
maildir_sync_mail_keywords(struct maildir_index_sync_context *ctx, uint32_t seq)
{
	struct mailbox *box = &ctx->mbox->box;
	struct mail_keywords *kw;
	unsigned int i, j, old_count, new_count;
	const unsigned int *old_indexes, *new_indexes;
	bool have_indexonly_keywords;
	int diff;

	mail_index_lookup_keywords(ctx->view, seq, &ctx->idx_keywords);
	if (index_keyword_array_cmp(&ctx->keywords, &ctx->idx_keywords)) {
		/* no changes - we should get here usually */
		return;
	}

	/* sort the keywords */
	array_sort(&ctx->idx_keywords, uint_cmp);
	array_sort(&ctx->keywords, uint_cmp);

	/* drop keywords that are in index-only. we don't want to touch them. */
	old_indexes = array_get(&ctx->idx_keywords, &old_count);
	have_indexonly_keywords = FALSE;
	for (i = old_count; i > 0; i--) {
		if (maildir_keywords_idx_char(ctx->keywords_sync_ctx,
					      old_indexes[i-1]) == '\0') {
			have_indexonly_keywords = TRUE;
			array_delete(&ctx->idx_keywords, i-1, 1);
		}
	}

	if (!have_indexonly_keywords) {
		/* no index-only keywords found, so something changed.
		   just replace them all. */
		kw = mail_index_keywords_create_from_indexes(box->index,
							     &ctx->keywords);
		mail_index_update_keywords(ctx->trans, seq, MODIFY_REPLACE, kw);
		mail_index_keywords_unref(&kw);
		return;
	}

	/* check again if non-index-only keywords changed */
	if (index_keyword_array_cmp(&ctx->keywords, &ctx->idx_keywords))
		return;

	/* we can't reset all the keywords or we'd drop indexonly keywords too.
	   so first remove the unwanted keywords and then add back the wanted
	   ones. we can get these lists easily by removing common elements
	   from old and new keywords. */
	new_indexes = array_get(&ctx->keywords, &new_count);
	for (i = j = 0; i < old_count && j < new_count; ) {
		diff = (int)old_indexes[i] - (int)new_indexes[j];
		if (diff == 0) {
			array_delete(&ctx->keywords, j, 1);
			array_delete(&ctx->idx_keywords, i, 1);
			old_indexes = array_get(&ctx->idx_keywords, &old_count);
			new_indexes = array_get(&ctx->keywords, &new_count);
		} else if (diff < 0) {
			i++;
		} else {
			j++;
		}
	}

	if (array_count(&ctx->idx_keywords) > 0) {
		kw = mail_index_keywords_create_from_indexes(box->index,
							     &ctx->idx_keywords);
		mail_index_update_keywords(ctx->trans, seq, MODIFY_REMOVE, kw);
		mail_index_keywords_unref(&kw);
	}

	if (array_count(&ctx->keywords) > 0) {
		kw = mail_index_keywords_create_from_indexes(box->index,
							     &ctx->keywords);
		mail_index_update_keywords(ctx->trans, seq, MODIFY_ADD, kw);
		mail_index_keywords_unref(&kw);
	}
}
static int
mail_storage_service_lookup_real(struct mail_storage_service_ctx *ctx,
				 const struct mail_storage_service_input *input,
				 bool update_log_prefix,
				 struct mail_storage_service_user **user_r,
				 const char **error_r)
{
	enum mail_storage_service_flags flags;
	struct mail_storage_service_user *user;
	const char *username = input->username;
	const struct setting_parser_info *user_info;
	const struct mail_user_settings *user_set;
	const char *const *userdb_fields, *error;
	struct auth_user_reply reply;
	const struct setting_parser_context *set_parser;
	void **sets;
	pool_t user_pool, temp_pool;
	int ret = 1;

	user_pool = pool_alloconly_create(MEMPOOL_GROWING"mail storage service user", 1024*6);
	flags = mail_storage_service_input_get_flags(ctx, input);

	if ((flags & MAIL_STORAGE_SERVICE_FLAG_TEMP_PRIV_DROP) != 0 &&
	    geteuid() != 0) {
		/* we dropped privileges only temporarily. switch back to root
		   before reading settings, so we'll definitely have enough
		   permissions to connect to the config socket. */
		mail_storage_service_seteuid_root();
	}

	if (mail_storage_service_read_settings(ctx, input, user_pool,
					       &user_info, &set_parser,
					       &error) < 0) {
		if (ctx->config_permission_denied) {
			/* just restart and maybe next time we will open the
			   config socket before dropping privileges */
			i_fatal("%s", error);
		}
		i_error("%s", error);
		pool_unref(&user_pool);
		*error_r = MAIL_ERRSTR_CRITICAL_MSG;
		return -1;
	}

	if ((flags & MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT) == 0 &&
	    !ctx->log_initialized) {
		/* initialize logging again, in case we only read the
		   settings for the first above */
		ctx->log_initialized = TRUE;
		master_service_init_log(ctx->service,
			t_strconcat(ctx->service->name, ": ", NULL));
		update_log_prefix = TRUE;
	}
	sets = master_service_settings_parser_get_others(master_service,
							 set_parser);
	user_set = sets[0];

	if (update_log_prefix)
		mail_storage_service_set_log_prefix(ctx, user_set, NULL, input, NULL);

	if (ctx->conn == NULL)
		mail_storage_service_first_init(ctx, user_info, user_set);
	/* load global plugins */
	if (mail_storage_service_load_modules(ctx, user_info, user_set, &error) < 0) {
		i_error("%s", error);
		pool_unref(&user_pool);
		*error_r = MAIL_ERRSTR_CRITICAL_MSG;
		return -1;
	}

	if (ctx->userdb_next_pool == NULL)
		temp_pool = pool_alloconly_create("userdb lookup", 2048);
	else {
		temp_pool = ctx->userdb_next_pool;
		ctx->userdb_next_pool = NULL;
		pool_ref(temp_pool);
	}
	if ((flags & MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP) != 0) {
		ret = service_auth_userdb_lookup(ctx, input, temp_pool,
						 &username, &userdb_fields,
						 error_r);
		if (ret <= 0) {
			pool_unref(&temp_pool);
			pool_unref(&user_pool);
			return ret;
		}
		if (ctx->userdb_next_fieldsp != NULL)
			*ctx->userdb_next_fieldsp = userdb_fields;
	} else {
		userdb_fields = input->userdb_fields;
	}

	user = p_new(user_pool, struct mail_storage_service_user, 1);
	user->service_ctx = ctx;
	user->pool = user_pool;
	user->input = *input;
	user->input.userdb_fields = userdb_fields == NULL ? NULL :
		p_strarray_dup(user_pool, userdb_fields);
	user->input.username = p_strdup(user_pool, username);
	user->input.session_id = p_strdup(user_pool, input->session_id);
	if (user->input.session_id == NULL) {
		user->input.session_id =
			mail_storage_service_generate_session_id(user_pool,
				input->session_id_prefix);
	}
	user->user_info = user_info;
	user->flags = flags;

	user->set_parser = settings_parser_dup(set_parser, user_pool);

	sets = master_service_settings_parser_get_others(master_service,
							 user->set_parser);
	user->user_set = sets[0];
	user->gid_source = "mail_gid setting";
	user->uid_source = "mail_uid setting";

	if ((flags & MAIL_STORAGE_SERVICE_FLAG_DEBUG) != 0)
		(void)settings_parse_line(user->set_parser, "mail_debug=yes");

	if ((flags & MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP) == 0) {
		const char *home = getenv("HOME");
		if (home != NULL)
			set_keyval(ctx, user, "mail_home", home);
	}

	if (userdb_fields != NULL) {
		auth_user_fields_parse(userdb_fields, temp_pool, &reply);
		array_sort(&reply.extra_fields, extra_field_key_cmp_p);
		if (user_reply_handle(ctx, user, &reply, &error) < 0) {
			i_error("Invalid settings in userdb: %s", error);
			*error_r = ERRSTR_INVALID_USER_SETTINGS;
			ret = -2;
		}
	}
	if (ret > 0 && !settings_parser_check(user->set_parser, user_pool, &error)) {
		i_error("Invalid settings (probably caused by userdb): %s", error);
		*error_r = ERRSTR_INVALID_USER_SETTINGS;
		ret = -2;
	}
	pool_unref(&temp_pool);

	/* load per-user plugins */
	if (ret > 0) {
		if (mail_storage_service_load_modules(ctx, user_info,
						      user->user_set,
						      &error) < 0) {
			i_error("%s", error);
			*error_r = MAIL_ERRSTR_CRITICAL_MSG;
			ret = -2;
		}
	}

	*user_r = user;
	return ret;
}