Example #1
0
void MailboxState_remap(T M)
{
	GList *ids = NULL;
	uint64_t *uid, *msn = NULL, rows = 1;
	MessageInfo *msginfo;

	MailboxState_uid_msn_new(M);

	ids = g_tree_keys(M->msginfo);
	ids = g_list_first(ids);
	while (ids) {
		uid = (uint64_t *)ids->data;

		msginfo = g_tree_lookup(M->msginfo, uid);
		if (msginfo->status < MESSAGE_STATUS_DELETE) {
			msn = g_new0(uint64_t,1);
			*msn = msginfo->msn = rows++;

			g_tree_insert(M->ids, uid, msn);
			g_tree_insert(M->msn, msn, uid);
		}

		if (! g_list_next(ids)) break;
		ids = g_list_next(ids);
	}

	g_list_free(g_list_first(ids));
}
Example #2
0
int MailboxState_flush_recent(T M) 
{
	GList *recent;

	if ((!M) || (M && MailboxState_getPermission(M) != IMAPPERM_READWRITE))
		return DM_SUCCESS;

	if (! g_tree_nnodes(M->recent_queue))
		return DM_SUCCESS;

	TRACE(TRACE_DEBUG,"flush [%d] recent messages", g_tree_nnodes(M->recent_queue));

	recent = g_tree_keys(M->recent_queue);

	if (recent) {
		long long int changed = 0;
		uint64_t seq = MailboxState_getSeq(M);
		changed = _update_recent(g_list_slices_u64(recent,100), seq+1);
		if (changed)
			db_mailbox_seq_update(MailboxState_getId(M), 0);
	}

	g_list_free(g_list_first(recent));

	g_tree_foreach(M->recent_queue, (GTraverseFunc)_free_recent_queue, M);
	g_tree_destroy(M->recent_queue);
	M->recent_queue = g_tree_new((GCompareFunc)ucmp);

	return 0;
}
Example #3
0
char * MailboxState_flags(T M)
{
	char *s = NULL;
	GString *string = g_string_new("\\Seen \\Answered \\Deleted \\Flagged \\Draft");
	assert(M);

	if (M->keywords) {
		GList *k = g_tree_keys(M->keywords);
		GString *keywords = g_list_join(k," ");
		g_string_append_printf(string, " %s", keywords->str);
		g_string_free(keywords,TRUE);
		g_list_free(g_list_first(k));
	}

	s = string->str;
	g_string_free(string, FALSE);
	return g_strchomp(s);
}
Example #4
0
//--------------------------------------------------------------------------------------//
void Http_getMailboxes(T R)
{
	const char *mailbox = Request_getId(R);

	TRACE(TRACE_DEBUG,"mailbox [%s]", mailbox);
	char *endptr = NULL;
	struct evbuffer *buf;
	uint64_t id = 0;

	if (! mailbox) {
		Request_error(R, HTTP_SERVUNAVAIL, "Server error");
		return;
	}	

	if (! (id = strtoull(mailbox, &endptr, 10))) {
		Request_error(R, HTTP_NOTFOUND, "Not found");
		return;
	}

	TRACE(TRACE_DEBUG,"mailbox id [%lu]", id);
	buf = evbuffer_new();
	Request_setContentType(R,"application/json; charset=utf-8");

	if (Request_getMethod(R) == NULL) {

		/*
		 * retrieve mailbox meta-data
		 * C < GET /mailboxes/876
		 *
		 * or
		 *
		 * append a new message
		 * C < POST /mailboxes/876 
		 */

		const char *msg;
		uint64_t msg_id = 0;
		MailboxState_T b = MailboxState_new(id);
		unsigned exists = MailboxState_getExists(b);

		if ((msg = evhttp_find_header(Request_getPOST(R),"message"))) {
			if (! db_append_msg(msg, MailboxState_getId(b), MailboxState_getOwner(b), NULL, &msg_id, TRUE))
				exists++;		
		}
		evbuffer_add_printf(buf, "{\"mailboxes\": {\n");
		evbuffer_add_printf(buf, "    \"%lu\":{\"name\":\"%s\",\"exists\":%d}", MailboxState_getId(b), MailboxState_getName(b), exists);
		evbuffer_add_printf(buf, "\n}}\n");
		MailboxState_free(&b);

	} else if (MATCH(Request_getMethod(R),"messages")) {

		/*
		 * list messages in mailbox
		 * C < GET /mailboxes/876/messages
		 */

		MailboxState_T b = MailboxState_new(id);
		GTree *msns = MailboxState_getMsn(b);
		GList *ids = g_tree_keys(msns);
		GTree *msginfo = MailboxState_getMsginfo(b);

		evbuffer_add_printf(buf, "{\"messages\": {\n");
		while (ids && ids->data) {
			uint64_t *msn = (uint64_t *)ids->data;
			uint64_t *uid = (uint64_t *)g_tree_lookup(msns, msn);
			MessageInfo *info = (MessageInfo *)g_tree_lookup(msginfo, uid);
			evbuffer_add_printf(buf, "    \"%lu\":{\"size\":%lu}", *uid, info->rfcsize);
			if (! g_list_next(ids)) break;
			ids = g_list_next(ids);
			evbuffer_add_printf(buf,",\n");
		}
		evbuffer_add_printf(buf, "\n}}\n");
	
		if (ids) g_list_free(g_list_first(ids));
		MailboxState_free(&b);
	}

	if (EVBUFFER_LENGTH(buf))
		Request_send(R, HTTP_OK, "OK", buf);
	else		
		Request_error(R, HTTP_SERVUNAVAIL, "Server error");
	evbuffer_free(buf);
}
Example #5
0
GTree * MailboxState_get_set(MailboxState_T M, const char *set, gboolean uid)
{
	GTree *inset, *a, *b;
	GList *sets = NULL;
	GString *t;
	uint64_t lo = 0, hi = 0;
	gboolean error = FALSE;

	if (uid)
		inset = MailboxState_getIds(M);
	else
		inset = MailboxState_getMsn(M);

	a = g_tree_new_full((GCompareDataFunc)ucmpdata,NULL, (GDestroyNotify)uint64_free, (GDestroyNotify)uint64_free);
	b = g_tree_new_full((GCompareDataFunc)ucmpdata,NULL, (GDestroyNotify)uint64_free, (GDestroyNotify)uint64_free);

	if (! uid) {
		lo = 1;
		hi = MailboxState_getExists(M);
	} else {
		GList *ids = g_tree_keys(inset);
		if (ids) {
			ids = g_list_last(ids);
			hi = *((uint64_t *)ids->data);
			ids = g_list_first(ids);
			lo = *((uint64_t *)ids->data);
			g_list_free(g_list_first(ids));
		}
	}

	t = g_string_new(set);
	sets = g_string_split(t,",");
	g_string_free(t,TRUE);

	sets = g_list_first(sets);
	while(sets) {
		uint64_t l = 0, r = 0;
		
		char *rest = (char *)sets->data;

		if (strlen(rest) < 1) break;

		if (g_tree_nnodes(inset) == 0) { // empty box
			if (rest[0] == '*') {
				uint64_t *k = mempool_pop(small_pool, sizeof(uint64_t));
				uint64_t *v = mempool_pop(small_pool, sizeof(uint64_t));

				*k = 1;
				*v = MailboxState_getUidnext(M);

				g_tree_insert(b, k, v);
			} else {
				if (! (l = dm_strtoull(sets->data, &rest, 10))) {
					error = TRUE;
					break;
				}
				if (rest[0]) {
					if (rest[0] != ':') {
						error = TRUE;
						break;
					}
					rest++;
					if ((rest[0] != '*') && (! dm_strtoull(rest, NULL, 10))) {
						error = TRUE;
						break;
					}
				}
				uint64_t *k = mempool_pop(small_pool, sizeof(uint64_t));
				uint64_t *v = mempool_pop(small_pool, sizeof(uint64_t));

				*k = 1;
				*v = MailboxState_getUidnext(M);

				g_tree_insert(b, k, v);
			}
		} else {
			if (rest[0] == '*') {
				l = hi;
				r = l;
				if (strlen(rest) > 1)
					rest++;
			} else {
				if (! (l = dm_strtoull(sets->data,&rest,10))) {
					error = TRUE;
					break;
				}

				if (l == 0xffffffff) l = hi; // outlook

				l = max(l,lo);
				r = l;
			}
			
			if (rest[0]==':') {
				if (strlen(rest)>1) rest++;
				if (rest[0] == '*') r = hi;
				else {
					if (! (r = dm_strtoull(rest,NULL,10))) {
						error = TRUE;
						break;
					}

					if (r == 0xffffffff) r = hi; // outlook
				}
				
				if (!r) break;
			}
		
			if (! (l && r)) break;

			find_range(inset, min(l,r), max(l,r), a, uid);

			if (g_tree_merge(b,a,IST_SUBSEARCH_OR)) {
				error = TRUE;
				TRACE(TRACE_ERR, "cannot compare null trees");
				break;
			}
		}

		if (! g_list_next(sets)) break;
		sets = g_list_next(sets);
	}

	g_list_destroy(sets);

	if (a) g_tree_destroy(a);

	if (error) {
		g_tree_destroy(b);
		b = NULL;
		TRACE(TRACE_DEBUG, "return NULL");
	}

	return b;
}
Example #6
0
static int mailbox_dump(u64_t mailbox_idnr, const char *dumpfile,
		const char *search, int delete_after_dump)
{
	FILE *ostream;
	DbmailMailbox *mb = NULL;
	ImapSession *s = NULL;
	int result = 0;

	/* 
	 * For dbmail the usual filesystem semantics don't really 
	 * apply. Mailboxes can contain other mailboxes as well as
	 * messages. For now however, this is solved by appending
	 * the mailboxname with .mbox
	 *
	 * TODO: facilitate maildir type exports
	 */
	mb = dbmail_mailbox_new(mailbox_idnr);
	if (search) {
		s = dbmail_imap_session_new();
		s->ci = client_init(NULL);
		if (! (imap4_tokenizer_main(s, search))) {
			qerrorf("error parsing search string");
			dbmail_imap_session_delete(&s);
			dbmail_mailbox_free(mb);
			return 1;
		}
	
		if (dbmail_mailbox_build_imap_search(mb, s->args, &(s->args_idx), SEARCH_UNORDERED) < 0) {
			qerrorf("invalid search string");
			dbmail_imap_session_delete(&s);
			dbmail_mailbox_free(mb);
			return 1;
		}
		dbmail_mailbox_search(mb);
		dbmail_imap_session_delete(&s);	
	}

	if (strcmp(dumpfile, "-") == 0) {
		ostream = stdout;
	} else if (! (ostream = fopen(dumpfile, "a"))) {
		int err = errno;
		qerrorf("opening [%s] failed [%s]\n", dumpfile, strerror(err));
		result = -1;
		goto cleanup;
	}

	if (dbmail_mailbox_dump(mb, ostream) < 0) {
		qerrorf("Export failed\n");
		result = -1;
		goto cleanup;
	}

	if (delete_after_dump) {
		int deleted_flag[IMAP_NFLAGS];
		memset(deleted_flag, 0, IMAP_NFLAGS * sizeof(int));
		deleted_flag[IMAP_FLAG_DELETED] = 1;

		GList *ids = g_tree_keys(MailboxState_getIds(mb->mbstate));

                while (ids) {
			// Flag the selected messages \\Deleted
			// Following this, dbmail-util -d sets deleted status
			if (delete_after_dump & 1) {
				if (db_set_msgflag(*(u64_t *)ids->data, deleted_flag, NULL, IMAPFA_ADD, NULL) < 0) {
					qerrorf("Error setting flags for message [%llu]\n", *(u64_t *)ids->data);
					result = -1;
				}
			}

			// Set deleted status on each message
			// Following this, dbmail-util -p sets purge status
			if (delete_after_dump & 2) {
				if (! db_set_message_status(*(u64_t *)ids->data, MESSAGE_STATUS_DELETE)) {
					qerrorf("Error setting status for message [%llu]\n", *(u64_t *)ids->data);
					result = -1;
				}
			}

			if (!g_list_next(ids))
				break;
			ids = g_list_next(ids);
		}

		g_list_free(g_list_first(ids));
	}

cleanup:
	if (mb)
		dbmail_mailbox_free(mb);
	if ((ostream) && (ostream != stdout))
		fclose(ostream);

	return result;
}