int do_dangling_aliases(void) { int count = 0; int result = 0; GList *aliases = NULL; if (no_to_all) qprintf("\nCounting aliases with nonexistent delivery userid's...\n"); if (yes_to_all) qprintf("\nRemoving aliases with nonexistent delivery userid's...\n"); aliases = auth_get_known_aliases(); aliases = g_list_dedup(aliases, (GCompareFunc)strcmp, TRUE); aliases = g_list_first(aliases); while (aliases) { char deliver_to[21]; GList *dangling = find_dangling_aliases(aliases->data); dangling = g_list_first(dangling); while (dangling) { count++; g_snprintf(deliver_to, 21, "%" PRIu64 "", *(uint64_t *)dangling->data); qverbosef("Dangling alias [%s] delivers to nonexistent user [%s]\n", (char *)aliases->data, deliver_to); if (yes_to_all) { if (auth_removealias_ext(aliases->data, deliver_to) < 0) { qerrorf("Error: could not remove alias [%s] deliver to [%s] \n", (char *)aliases->data, deliver_to); serious_errors = 1; result = -1; } } if (!g_list_next(dangling)) break; dangling = g_list_next(dangling); } g_list_destroy(g_list_first(dangling)); if (! g_list_next(aliases)) break; aliases = g_list_next(aliases); } g_list_destroy(g_list_first(aliases)); if (count > 0) { qerrorf("Ok. Found [%d] dangling aliases.\n", count); has_errors = 1; } else { qprintf("Ok. Found [%d] dangling aliases.\n", count); } return result; }
void client_session_reset(ClientSession_t * session) { dsnuser_free_list(session->rcpt); session->rcpt = NULL; g_list_destroy(session->from); session->from = NULL; if (session->apop_stamp) { g_free(session->apop_stamp); session->apop_stamp = NULL; } if (session->username) { g_free(session->username); session->username = NULL; } if (session->password) { g_free(session->password); session->password = NULL; } session->state = CLIENTSTATE_INITIAL_CONNECT; client_session_reset_parser(session); }
static long long int _update_recent(volatile GList *slices, uint64_t seq) { INIT_QUERY; Connection_T c; volatile long long int count = 0; if (! (slices = g_list_first(slices))) return count; c = db_con_get(); TRY db_begin_transaction(c); while (slices) { Connection_execute(c, "UPDATE %smessages SET recent_flag = 0, seq = %" PRIu64 " WHERE recent_flag = 1 AND seq < %" PRIu64 " AND message_idnr IN (%s)", DBPFX, seq, seq, (gchar *)slices->data); count += Connection_rowsChanged(c); if (! g_list_next(slices)) break; slices = g_list_next(slices); } db_commit_transaction(c); CATCH(SQLException) LOG_SQLERROR; count = DM_EQUERY; db_rollback_transaction(c); FINALLY db_con_close(c); g_list_destroy(slices); END_TRY; return count; }
static void db_session_cleanup(ClientSession_t * session_ptr) { /* cleanups a session removes a list and all references */ session_ptr->totalsize = 0; session_ptr->virtual_totalsize = 0; session_ptr->totalmessages = 0; session_ptr->virtual_totalmessages = 0; g_list_destroy(session_ptr->messagelst); }
int auth_check_user_ext(const char *username, GList **userids, GList **fwds, int checks) { int occurences = 0; GList *d = NULL; char *endptr; uint64_t id, *uid; if (checks > 20) { TRACE(TRACE_ERR,"too many checks. Possible loop detected."); return 0; } TRACE(TRACE_DEBUG, "[%d] checking user [%s] in alias table", checks, username); d = user_get_deliver_to(username); if (! d) { if (checks == 0) { TRACE(TRACE_DEBUG, "user %s not in aliases table", username); return 0; } /* found the last one, this is the deliver to * but checks needs to be bigger then 0 because * else it could be the first query failure */ id = strtoull(username, &endptr, 10); if (*endptr == 0) { /* numeric deliver-to --> this is a userid */ uid = g_new0(uint64_t,1); *uid = id; *(GList **)userids = g_list_prepend(*(GList **)userids, uid); } else { *(GList **)fwds = g_list_prepend(*(GList **)fwds, g_strdup(username)); } TRACE(TRACE_DEBUG, "adding [%s] to deliver_to address", username); return 1; } while (d) { /* do a recursive search for deliver_to */ char *deliver_to = (char *)d->data; TRACE(TRACE_DEBUG, "checking user %s to %s", username, deliver_to); occurences += auth_check_user_ext(deliver_to, userids, fwds, checks+1); if (! g_list_next(d)) break; d = g_list_next(d); } g_list_destroy(d); return occurences; }
void client_session_reset_parser(ClientSession_t *session) { session->parser_state = FALSE; session->command_type = FALSE; if (session->rbuff) { g_string_truncate(session->rbuff,0); g_string_maybe_shrink(session->rbuff); } if (session->args) { g_list_destroy(session->args); session->args = NULL; } }
void dm_ldap_freeresult(GList *entlist) { GList *fldlist, *attlist; entlist = g_list_first(entlist); while (entlist) { fldlist = entlist->data; while(fldlist) { attlist = fldlist->data; g_list_destroy(attlist); if (! g_list_next(fldlist)) break; fldlist = g_list_next(fldlist); } g_list_free(g_list_first(fldlist)); if (! g_list_next(entlist)) break; entlist = g_list_next(entlist); } g_list_free(g_list_first(entlist)); }
static int do_rfc_size(void) { time_t start, stop; GList *lost = NULL; if (no_to_all) { qprintf("\nChecking DBMAIL for rfcsize field...\n"); } if (yes_to_all) { qprintf("\nRepairing DBMAIL for rfcsize field...\n"); } time(&start); if (db_icheck_rfcsize(&lost) < 0) { qerrorf("Failed. An error occured. Please check log.\n"); serious_errors = 1; return -1; } if (g_list_length(lost) > 0) { qerrorf("Ok. Found [%d] missing rfcsize values.\n", g_list_length(lost)); has_errors = 1; } else { qprintf("Ok. Found [%d] missing rfcsize values.\n", g_list_length(lost)); } if (yes_to_all) { if (db_update_rfcsize(lost) < 0) { qerrorf("Error setting the rfcsize values"); has_errors = 1; } } g_list_destroy(lost); time(&stop); qverbosef("--- checking rfcsize field took %g seconds\n", difftime(stop, start)); return 0; }
END_TEST START_TEST(test_dbmail_message_get_header_addresses) { GList * result; GString *s; DbmailMessage *m; s = g_string_new(multipart_message); m = dbmail_message_new(); m = dbmail_message_init_with_string(m,s); result = dbmail_message_get_header_addresses(m, "Cc"); result = g_list_first(result); fail_unless(result != NULL, "dbmail_message_get_header_addresses failed"); fail_unless(g_list_length(result)==2,"dbmail_message_get_header_addresses failed"); fail_unless(strcmp((char *)result->data,"*****@*****.**")==0, "dbmail_message_get_header_addresses failed"); g_list_destroy(result); dbmail_message_free(m); g_string_free(s,TRUE); }
int do_check_integrity(void) { time_t start, stop; GList *lost = NULL; const char *action; gboolean cleanup; long count = 0; if (yes_to_all) { action = "Repairing"; cleanup = TRUE; } else { action = "Checking"; cleanup = FALSE; } qprintf("\n%s DBMAIL message integrity...\n", action); /* This is what we do: 3. Check for loose physmessages 4. Check for loose partlists 5. Check for loose mimeparts */ /* part 3 */ start = stop; qprintf("\n%s DBMAIL physmessage integrity...\n", action); if ((count = db_icheck_physmessages(cleanup)) < 0) { qerrorf("Failed. An error occurred. Please check log.\n"); serious_errors = 1; return -1; } if (count > 0) { qerrorf("Ok. Found [%ld] unconnected physmessages.\n", count); if (cleanup) { qerrorf("Ok. Orphaned physmessages deleted.\n"); } } else { qprintf("Ok. Found [%ld] unconnected physmessages.\n", count); } time(&stop); qverbosef("--- %s unconnected physmessages took %g seconds\n", action, difftime(stop, start)); /* end part 3 */ /* part 4 */ start = stop; qprintf("\n%s DBMAIL partlists integrity...\n", action); if ((count = db_icheck_partlists(cleanup)) < 0) { qerrorf("Failed. An error occurred. Please check log.\n"); serious_errors = 1; return -1; } if (count > 0) { qerrorf("Ok. Found [%ld] unconnected partlists.\n", count); if (cleanup) { qerrorf("Ok. Orphaned partlists deleted.\n"); } } else { qprintf("Ok. Found [%ld] unconnected partlists.\n", count); } time(&stop); qverbosef("--- %s unconnected partlists took %g seconds\n", action, difftime(stop, start)); /* end part 4 */ /* part 5 */ start = stop; qprintf("\n%s DBMAIL mimeparts integrity...\n", action); if ((count = db_icheck_mimeparts(cleanup)) < 0) { qerrorf("Failed. An error occurred. Please check log.\n"); serious_errors = 1; return -1; } if (count > 0) { qerrorf("Ok. Found [%ld] unconnected mimeparts.\n", count); if (cleanup) { qerrorf("Ok. Orphaned mimeparts deleted.\n"); } } else { qprintf("Ok. Found [%ld] unconnected mimeparts.\n", count); } time(&stop); qverbosef("--- %s unconnected mimeparts took %g seconds\n", action, difftime(stop, start)); /* end part 5 */ g_list_destroy(lost); lost = NULL; time(&stop); qverbosef("--- %s block integrity took %g seconds\n", action, difftime(stop, start)); /* end part 6 */ return 0; }
//--------------------------------------------------------------------------------------// void Http_getUsers(T R) { struct evbuffer *buf; char *username = NULL; uint64_t id = 0; if (Request_getId(R)) { /* * id can be specified both by name and number * * C < /users/testuser1 * C < /users/123 * */ if ((id = strtoull(Request_getId(R), NULL, 10))) username = auth_get_userid(id); else if (auth_user_exists(Request_getId(R), &id)) username = g_strdup(Request_getId(R)); if (! (username && id)) Request_error(R, HTTP_NOTFOUND, "User not found"); } buf = evbuffer_new(); if (Request_getMethod(R) == NULL) { GList *users = NULL; if (username) { MailboxState_T M; const char *mailbox; uint64_t mboxid; /* * retrieve user meta-data * C < /users/testuser1 * create/delete mailbox for user * POST C < /users/testuser1 */ if ((mailbox = evhttp_find_header(Request_getPOST(R),"create"))) { const char *message; if (db_mailbox_create_with_parents(mailbox, BOX_COMMANDLINE, id, &mboxid, &message)) { Request_error(R, HTTP_BADREQUEST, message); evbuffer_free(buf); return; } } if ((mailbox = evhttp_find_header(Request_getPOST(R),"delete"))) { int access; /* check if there is an attempt to delete inbox */ if (MATCH(mailbox, "INBOX")) { Request_error(R, HTTP_BADREQUEST, "NO cannot delete special mailbox INBOX"); evbuffer_free(buf); return; } if (! (db_findmailbox(mailbox, id, &mboxid)) ) { Request_error(R, HTTP_NOTFOUND, "NO mailbox doesn't exists"); evbuffer_free(buf); return; } /* Check if the user has ACL delete rights to this mailbox */ M = MailboxState_new(mboxid); access = acl_has_right(M, id, ACL_RIGHT_DELETE); if (access != 1) { Request_error(R, HTTP_BADREQUEST, "NO permission denied"); evbuffer_free(buf); return; } /* ok remove mailbox */ if (db_delete_mailbox(mboxid, 0, 1)) { Request_error(R, HTTP_SERVUNAVAIL, "NO delete failed"); evbuffer_free(buf); return; } } users = g_list_append_printf(users, "%s", username); } else { /* * list all users * C < /users/ * * create,edit,delete user * POST C < /users/ */ const char *user = NULL; if ((user = evhttp_find_header(Request_getPOST(R),"create"))) { const char *password, *encoding, *quota; password = evhttp_find_header(Request_getPOST(R), "password"); encoding = evhttp_find_header(Request_getPOST(R), "encoding"); quota = evhttp_find_header(Request_getPOST(R), "quota"); TRACE(TRACE_DEBUG, "create user: [%s] password: [%s] encoding [%s] quota [%s]", user, password, encoding, quota); } else if ((user = evhttp_find_header(Request_getPOST(R),"edit"))) { TRACE(TRACE_DEBUG, "edit user: [%s]", user); } else if ((user = evhttp_find_header(Request_getPOST(R),"delete"))) { TRACE(TRACE_DEBUG, "delete user: [%s]", user); } users = auth_get_known_users(); } Request_setContentType(R,"application/json; charset=utf-8"); evbuffer_add_printf(buf, "{\"users\": {\n"); while(users->data) { uint64_t id; if (auth_user_exists((char *)users->data, &id)) evbuffer_add_printf(buf, " \"%lu\":{\"name\":\"%s\"}", id, (char *)users->data); if (! g_list_next(users)) break; users = g_list_next(users); evbuffer_add_printf(buf,",\n"); } evbuffer_add_printf(buf, "\n}}\n"); g_list_destroy(users); } else if (MATCH(Request_getMethod(R),"mailboxes")) { GList *mailboxes = NULL; if (! username) { Request_error(R, HTTP_NOTFOUND, "User not found"); evbuffer_free(buf); return; } /* * list mailboxes for user * GET C < /users/testuser1/mailboxes * */ db_findmailbox_by_regex(id, "*", &mailboxes, FALSE); Request_setContentType(R,"application/json; charset=utf-8"); evbuffer_add_printf(buf, "{\"mailboxes\": {\n"); while (mailboxes->data) { MailboxState_T b = MailboxState_new(*((uint64_t *)mailboxes->data)); MailboxState_setOwner(b, id); //if (MailboxState_reload(b) == DM_SUCCESS) evbuffer_add_printf(buf, " \"%lu\":{\"name\":\"%s\",\"exists\":%u}", MailboxState_getId(b), MailboxState_getName(b), MailboxState_getExists(b)); MailboxState_free(&b); if (! g_list_next(mailboxes)) break; mailboxes = g_list_next(mailboxes); evbuffer_add_printf(buf,",\n"); } evbuffer_add_printf(buf, "\n}}\n"); } if (EVBUFFER_LENGTH(buf)) Request_send(R, HTTP_OK, "OK", buf); else Request_error(R, HTTP_SERVUNAVAIL, "Server error"); if (username) g_free(username); evbuffer_free(buf); }
int tims(ClientSession_t *session) { /* returns values: * 0 to quit * -1 on failure * 1 on success */ char *arg; size_t scriptlen = 0; int ret; char *script = NULL, *scriptname = NULL; sort_result_t *sort_result = NULL; clientbase_t *ci = session->ci; TRACE(TRACE_DEBUG,"[%p] [%d][%s]", session, session->command_type, commands[session->command_type]); switch (session->command_type) { case TIMS_LOUT: ci_write(ci, "OK \"Bye.\"\r\n"); session->state = QUIT; return 1; case TIMS_STLS: ci_write(ci, "NO\r\n"); return 1; case TIMS_CAPA: send_greeting(session); return 1; case TIMS_AUTH: /* We currently only support plain authentication, * which means that the command we accept will look * like this: Authenticate "PLAIN" "base64-password" * */ session->args = g_list_first(session->args); if (! (session->args && session->args->data)) return 1; arg = (char *)session->args->data; if (strcasecmp(arg, "PLAIN") == 0) { int i = 0; u64_t useridnr; if (! g_list_next(session->args)) return tims_error(session, "NO \"Missing argument.\"\r\n"); session->args = g_list_next(session->args); arg = (char *)session->args->data; char **tmp64 = NULL; tmp64 = base64_decodev(arg); if (tmp64 == NULL) return tims_error(session, "NO \"SASL decode error.\"\r\n"); for (i = 0; tmp64[i] != NULL; i++) ; if (i < 3) tims_error(session, "NO \"Too few encoded SASL arguments.\"\r\n"); /* The protocol specifies that the base64 encoding * be made up of three parts: proxy, username, password * Between them are NULLs, which are conveniently encoded * by the base64 process... */ if (auth_validate(ci, tmp64[1], tmp64[2], &useridnr) == 1) { ci_authlog_init(ci, THIS_MODULE, tmp64[1], AUTHLOG_ACT); ci_write(ci, "OK\r\n"); session->state = AUTH; session->useridnr = useridnr; session->username = g_strdup(tmp64[1]); session->password = g_strdup(tmp64[2]); client_session_set_timeout(session, server_conf->timeout); } else { ci_authlog_init(ci, THIS_MODULE, tmp64[1], AUTHLOG_ERR); g_strfreev(tmp64); return tims_error(session, "NO \"Username or password incorrect.\"\r\n"); } g_strfreev(tmp64); } else return tims_error(session, "NO \"Authentication scheme not supported.\"\r\n"); return 1; case TIMS_PUTS: if (session->state != AUTH) { ci_write(ci, "NO \"Please authenticate first.\"\r\n"); break; } session->args = g_list_first(session->args); if (! (session->args && session->args->data)) return 1; scriptname = (char *)session->args->data; session->args = g_list_next(session->args); assert(session->args); script = (char *)session->args->data; scriptlen = strlen(script); TRACE(TRACE_INFO, "Client sending script of length [%ld]", scriptlen); if (scriptlen >= UINT_MAX) return tims_error(session, "NO \"Invalid script length.\"\r\n"); if (dm_sievescript_quota_check(session->useridnr, scriptlen)) return tims_error(session, "NO \"Script exceeds available space.\"\r\n"); /* Store the script temporarily, * validate it, then rename it. */ if (dm_sievescript_add(session->useridnr, "@!temp-script!@", script)) { dm_sievescript_delete(session->useridnr, "@!temp-script!@"); return tims_error(session, "NO \"Error inserting script.\"\r\n"); } sort_result = sort_validate(session->useridnr, "@!temp-script!@"); if (sort_result == NULL) { dm_sievescript_delete(session->useridnr, "@!temp-script!@"); return tims_error(session, "NO \"Error inserting script.\"\r\n"); } else if (sort_get_error(sort_result) > 0) { dm_sievescript_delete(session->useridnr, "@!temp-script!@"); return tims_error(session, "NO \"Script error: %s.\"\r\n", sort_get_errormsg(sort_result)); } /* According to the draft RFC, a script with the same * name as an existing script should [atomically] replace it. */ if (dm_sievescript_rename(session->useridnr, "@!temp-script!@", scriptname)) return tims_error(session, "NO \"Error inserting script.\"\r\n"); ci_write(ci, "OK \"Script successfully received.\"\r\n"); break; case TIMS_SETS: if (session->state != AUTH) { ci_write(ci, "NO \"Please authenticate first.\"\r\n"); break; } scriptname = NULL; session->args = g_list_first(session->args); if ((session->args && session->args->data)) scriptname = (char *)session->args->data; if (strlen(scriptname)) { if (! dm_sievescript_activate(session->useridnr, scriptname)) ci_write(ci, "NO \"Error activating script.\"\r\n"); else ci_write(ci, "OK \"Script activated.\"\r\n"); } else { ret = dm_sievescript_get(session->useridnr, &scriptname); if (scriptname == NULL) { ci_write(ci, "OK \"No scripts are active at this time.\"\r\n"); } else { if (! dm_sievescript_deactivate(session->useridnr, scriptname)) ci_write(ci, "NO \"Error deactivating script.\"\r\n"); else ci_write(ci, "OK \"All scripts deactivated.\"\r\n"); g_free(scriptname); } } return 1; case TIMS_GETS: if (session->state != AUTH) { ci_write(ci, "NO \"Please authenticate first.\"\r\n"); break; } session->args = g_list_first(session->args); if (! (session->args && session->args->data)) return 1; scriptname = (char *)session->args->data; if (! strlen(scriptname)) return tims_error(session, "NO \"Script name required.\"\r\n"); ret = dm_sievescript_getbyname(session->useridnr, scriptname, &script); if (script == NULL) { return tims_error(session, "NO \"Script not found.\"\r\n"); } else if (ret < 0) { g_free(script); return tims_error(session, "NO \"Internal error.\"\r\n"); } else { ci_write(ci, "{%u+}\r\n", (unsigned int)strlen(script)); ci_write(ci, "%s\r\n", script); ci_write(ci, "OK\r\n"); g_free(script); } return 1; case TIMS_DELS: if (session->state != AUTH) { ci_write(ci, "NO \"Please authenticate first.\"\r\n"); break; } session->args = g_list_first(session->args); if (! (session->args && session->args->data)) return 1; scriptname = (char *)session->args->data; if (! strlen(scriptname)) return tims_error(session, "NO \"Script name required.\"\r\n"); if (! dm_sievescript_delete(session->useridnr, scriptname)) return tims_error(session, "NO \"Error deleting script.\"\r\n"); else ci_write(ci, "OK \"Script deleted.\"\r\n", scriptname); return 1; case TIMS_SPAC: if (session->state != AUTH) { ci_write(ci, "NO \"Please authenticate first.\"\r\n"); break; } // Command is in format: HAVESPACE "scriptname" 12345 // TODO: this is a fake if (dm_sievescript_quota_check(session->useridnr, 12345) == DM_SUCCESS) ci_write(ci, "OK (QUOTA)\r\n"); else ci_write(ci, "NO (QUOTA) \"Quota exceeded\"\r\n"); return 1; case TIMS_LIST: if (session->state != AUTH) { ci_write(ci, "NO \"Please authenticate first.\"\r\n"); break; } GList *scriptlist = NULL; if (dm_sievescript_list (session->useridnr, &scriptlist) < 0) { ci_write(ci, "NO \"Internal error.\"\r\n"); } else { if (g_list_length(scriptlist) == 0) { /* The command hasn't failed, but there aren't any scripts */ ci_write(ci, "OK \"No scripts found.\"\r\n"); } else { scriptlist = g_list_first(scriptlist); while (scriptlist) { sievescript_info_t *info = (sievescript_info_t *) scriptlist->data; ci_write(ci, "\"%s\"%s\r\n", info->name, (info-> active == 1 ? " ACTIVE" : "")); if (! g_list_next(scriptlist)) break; scriptlist = g_list_next(scriptlist); } ci_write(ci, "OK\r\n"); } g_list_destroy(scriptlist); } return 1; default: return tims_error(session, "NO \"What are you trying to say here?\"\r\n"); } if (sort_result) sort_free_result(sort_result); return 1; }
static void MessageInfo_free(MessageInfo *m) { g_list_destroy(m->keywords); g_free(m); }
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; }
int do_check_integrity(void) { time_t start, stop; GList *lost = NULL; const char *action; gboolean cleanup; long count = 0; if (yes_to_all) { action = "Repairing"; cleanup = TRUE; } else { action = "Checking"; cleanup = FALSE; } qprintf("\n%s DBMAIL message integrity...\n", action); /* This is what we do: 3. Check for loose physmessages 4. Check for loose partlists 5. Check for loose mimeparts 6. Check for loose headernames 7. Check for loose headervalues */ /* part 3 */ time(&start); qprintf("\n%s DBMAIL physmessage integrity...\n", action); if ((count = db_icheck_physmessages(cleanup)) < 0) { qerrorf("Failed. An error occurred. Please check log.\n"); serious_errors = 1; return -1; } if (count > 0) { qerrorf("Ok. Found [%ld] unconnected physmessages.\n", count); if (cleanup) { qerrorf("Ok. Orphaned physmessages deleted.\n"); } } else { qprintf("Ok. Found [%ld] unconnected physmessages.\n", count); } time(&stop); qverbosef("--- %s unconnected physmessages took %g seconds\n", action, difftime(stop, start)); /* end part 3 */ /* part 4 */ start = stop; qprintf("\n%s DBMAIL partlists integrity...\n", action); if ((count = db_icheck_partlists(cleanup)) < 0) { qerrorf("Failed. An error occurred. Please check log.\n"); serious_errors = 1; return -1; } if (count > 0) { qerrorf("Ok. Found [%ld] unconnected partlists.\n", count); if (cleanup) { qerrorf("Ok. Orphaned partlists deleted.\n"); } } else { qprintf("Ok. Found [%ld] unconnected partlists.\n", count); } time(&stop); qverbosef("--- %s unconnected partlists took %g seconds\n", action, difftime(stop, start)); /* end part 4 */ /* part 5 */ start = stop; qprintf("\n%s DBMAIL mimeparts integrity...\n", action); if ((count = db_icheck_mimeparts(cleanup)) < 0) { qerrorf("Failed. An error occurred. Please check log.\n"); serious_errors = 1; return -1; } if (count > 0) { qerrorf("Ok. Found [%ld] unconnected mimeparts.\n", count); if (cleanup) { qerrorf("Ok. Orphaned mimeparts deleted.\n"); } } else { qprintf("Ok. Found [%ld] unconnected mimeparts.\n", count); } time(&stop); qverbosef("--- %s unconnected mimeparts took %g seconds\n", action, difftime(stop, start)); /* end part 5 */ /* part 6 */ Field_T config; bool cache_readonly = false; config_get_value("header_cache_readonly", "DBMAIL", config); if (strlen(config)) { if (MATCH(config, "true") || MATCH(config, "yes")) { cache_readonly = true; } } if (! cache_readonly) { start = stop; qprintf("\n%s DBMAIL headernames integrity...\n", action); if ((count = db_icheck_headernames(cleanup)) < 0) { qerrorf("Failed. An error occurred. Please check log.\n"); serious_errors = 1; return -1; } qprintf("Ok. Found [%ld] unconnected headernames.\n", count); if (count > 0 && cleanup) { qerrorf("Ok. Orphaned headernames deleted.\n"); } time(&stop); qverbosef("--- %s unconnected headernames took %g seconds\n", action, difftime(stop, start)); } /* end part 6 */ /* part 7 */ start = stop; qprintf("\n%s DBMAIL headervalues integrity...\n", action); if ((count = db_icheck_headervalues(cleanup)) < 0) { qerrorf("Failed. An error occurred. Please check log.\n"); serious_errors = 1; return -1; } qprintf("Ok. Found [%ld] unconnected headervalues.\n", count); if (count > 0 && cleanup) { qerrorf("Ok. Orphaned headervalues deleted.\n"); } time(&stop); qverbosef("--- %s unconnected headervalues took %g seconds\n", action, difftime(stop, start)); /* end part 7 */ g_list_destroy(lost); lost = NULL; time(&stop); qverbosef("--- %s block integrity took %g seconds\n", action, difftime(stop, start)); return 0; }
static int do_export(char *user, char *base_mailbox, char *basedir, char *outfile, char *search, int delete_after_dump, int recursive) { u64_t user_idnr = 0, owner_idnr = 0, mailbox_idnr = 0; char *dumpfile = NULL, *mailbox = NULL, *search_mailbox = NULL, *dir = NULL; GList *children = NULL; int result = 0; /* Verify the existence of this user */ if (! auth_user_exists(user, &user_idnr)) { qerrorf("Error: user [%s] does not exist.\n", user); result = -1; goto cleanup; } mailbox = g_new0(char, IMAP_MAX_MAILBOX_NAMELEN); if (!base_mailbox) { /* Always recursive without a mailbox base */ search_mailbox = g_strdup("*"); } else if (recursive) { /* Base and everything below */ search_mailbox = g_strdup_printf("%s*", base_mailbox); } else if (!recursive) { /* Should yield same results as plain db_findmailbox */ search_mailbox = g_strdup_printf("%s", base_mailbox); } /* FIXME: What are the possible error conditions here? */ db_findmailbox_by_regex(user_idnr, search_mailbox, &children, 0); /* Decision process for basedir vs. outfile: * If we're dumping one mailbox for one user, it goes to * stdout. If we've been given -o -, dump everything to * stdout (e.g., one giant mbox). If we've been given foo */ if (!outfile && !basedir) { /* Default is to use basedir of . */ basedir = "."; } else if (outfile) { /* Everything goes into this one file */ dumpfile = outfile; } children = g_list_first(children); qerrorf("Exporting [%u] mailboxes for [%s]\n", g_list_length(children), user); while (children) { mailbox_idnr = *(u64_t *)children->data; db_getmailboxname(mailbox_idnr, user_idnr, mailbox); if (! db_get_mailbox_owner(mailbox_idnr, &owner_idnr)) { qerrorf("Error checking mailbox ownership"); goto cleanup; } if (owner_idnr == user_idnr) { if (basedir) { /* Prepare the directory */ dumpfile = g_strdup_printf("%s/%s/%s.mbox", basedir, user, mailbox); dir = g_path_get_dirname(dumpfile); if (g_mkdir_with_parents(dir, 0700)) { qerrorf("can't create directory [%s]\n", dir); result = -1; goto cleanup; } } qerrorf(" export mailbox %s -> %s\n", mailbox, dumpfile); if ((result = mailbox_dump(mailbox_idnr, dumpfile, search, delete_after_dump)) != 0) { qerrorf("error exporting mailbox %s -> %s\n", mailbox, dumpfile); goto cleanup; } if (delete_after_dump) db_update("UPDATE %smailboxes SET seq=seq+1 WHERE mailbox_idnr=%d",DBPFX,mailbox_idnr); if (basedir) { g_free(dir); g_free(dumpfile); } } if (! g_list_next(children)) break; children = g_list_next(children); } cleanup: g_list_destroy(children); g_free(search_mailbox); g_free(mailbox); return result; }
END_TEST START_TEST(test_internet_address_list_parse_string) { char * trythese [][2] = { { "undisclosed-recipients", "((NIL NIL \"undisclosed-recipients\" NIL))"}, { "undisclosed-recipients;", "((NIL NIL \"undisclosed-recipients\" NIL))"}, { "undisclosed-recipients:", "((NIL NIL \"undisclosed-recipients\" NIL)(NIL NIL NIL NIL))"}, { "undisclosed-recipients:;", "((NIL NIL \"undisclosed-recipients\" NIL)(NIL NIL NIL NIL))"}, { "undisclosed-recipients: ;", "((NIL NIL \"undisclosed-recipients\" NIL)(NIL NIL NIL NIL))"}, { NULL, NULL } }; int i; for (i = 0; trythese[i][0] != NULL; i++) { char *input = trythese[i][0]; char *expect = trythese[i][1]; char *t, *result; InternetAddressList *alist; GList *list = NULL; t = imap_cleanup_address(input); alist = internet_address_list_parse_string(t); g_free(t); list = dbmail_imap_append_alist_as_plist(list, alist); g_object_unref(alist); alist = NULL; result = dbmail_imap_plist_as_string(list); fail_unless(strcmp(result,expect)==0, "internet_address_list_parse_string failed to generate correct undisclosed-recipients plist " "for [%s], expected\n[%s] got\n[%s]", input, expect, result); g_list_destroy(list); g_free(result); } char * testlist[][2] = { { "<*****@*****.**>", "((NIL NIL \"i_am_not\" \"broken.org\"))" }, { "Break me: <*****@*****.**>", "((NIL NIL \"Break me\" NIL)(NIL NIL \"foo\" \"bar.org\")(NIL NIL NIL NIL))" }, { "Joe's Friends: [email protected], [email protected], [email protected];", "((NIL NIL \"Joe's Friends\" NIL)(NIL NIL \"mary\" \"joe.com\")" "(NIL NIL \"joe\" \"joe.com\")(NIL NIL \"jane\" \"joe.com\")(NIL NIL NIL NIL))" }, // These have the wrong separator; ms lookout style. { "[email protected];[email protected]", "((NIL NIL \"one\" \"my.dom\")(NIL NIL \"two\" \"my.dom\"))" }, { "[email protected]; [email protected]", "((NIL NIL \"one\" \"my.dom\")(NIL NIL \"two\" \"my.dom\"))" }, { "Group: [email protected];, [email protected]", "((NIL NIL \"Group\" NIL)(NIL NIL \"one\" \"my.dom\")(NIL NIL NIL NIL)(NIL NIL \"two\" \"my.dom\"))" }, { NULL, NULL } }; char *input, *expect; for (i = 0; testlist[i][0] != NULL; i++) { input = testlist[i][0]; expect = testlist[i][1]; InternetAddressList *alist; GList *list = NULL; char *result; int res; char *t; t = imap_cleanup_address(input); alist = internet_address_list_parse_string(t); list = dbmail_imap_append_alist_as_plist(list, alist); result = dbmail_imap_plist_as_string(list); res = strcmp(result, expect); fail_unless(res == 0, "dbmail_imap_append_alist_as_plist failed, expected:\n[%s]\ngot:\n[%s]\n", expect, result); g_object_unref(alist); alist = NULL; g_list_destroy(list); g_free(result); g_free(t); } }
int main(int argc, char *argv[]) { int opt = 0, opt_prev = 0; int show_help = 0; int result = 0, delete_after_dump = 0, recursive = 0; char *user=NULL, *mailbox=NULL, *outfile=NULL, *basedir=NULL, *search=NULL; openlog(PNAME, LOG_PID, LOG_MAIL); setvbuf(stdout, 0, _IONBF, 0); g_mime_init(0); /* get options */ opterr = 0; /* suppress error message from getopt() */ while ((opt = getopt(argc, argv, "-u:m:o:b:s:dDr" /* Major modes */ "f:qvVh" /* Common options */ )) != -1) { /* The initial "-" of optstring allows unaccompanied * options and reports them as the optarg to opt 1 (not '1') */ if (opt == 1) opt = opt_prev; opt_prev = opt; switch (opt) { /* export specific options */ case 'u': if (optarg && strlen(optarg)) user = optarg; break; case 'm': if (optarg && strlen(optarg)) mailbox = optarg; break; case 'b': if (optarg && strlen(optarg)) basedir = optarg; break; case 'o': if (optarg && strlen(optarg)) outfile = optarg; break; case 'd': delete_after_dump |= 1; break; case 'D': delete_after_dump |= 2; break; case 'r': recursive = 1; break; case 's': if (optarg && strlen(optarg)) search = optarg; else { qerrorf("dbmail-mailbox: -s requires a value\n\n"); result = 1; } break; /* Common options */ case 'f': if (optarg && strlen(optarg) > 0) configFile = optarg; else { qerrorf("dbmail-mailbox: -f requires a filename\n\n"); result = 1; } break; case 'h': show_help = 1; break; case 'q': /* If we get q twice, be really quiet! */ if (quiet) reallyquiet = 1; if (!verbose) quiet = 1; break; case 'v': if (!quiet) verbose = 1; break; case 'V': /* Show the version and return non-zero. */ PRINTF_THIS_IS_DBMAIL; result = 1; break; default: /* printf("unrecognized option [%c], continuing...\n",optopt); */ break; } /* If there's a non-negative return code, * it's time to free memory and bail out. */ if (result) goto freeall; } /* If nothing is happening, show the help text. */ if (!user || (basedir && outfile) || show_help) { do_showhelp(); result = 1; goto freeall; } /* read the config file */ if (config_read(configFile) == -1) { qerrorf("Failed. Unable to read config file %s\n", configFile); result = -1; goto freeall; } SetTraceLevel("DBMAIL"); GetDBParams(); /* open database connection */ if (db_connect() != 0) { qerrorf ("Failed. Could not connect to database (check log)\n"); result = -1; goto freeall; } /* open authentication connection */ if (auth_connect() != 0) { qerrorf("Failed. Could not connect to authentication (check log)\n"); result = -1; goto freeall; } /* Loop over all user accounts if there's a wildcard. */ if (strchr(user, '?') || strchr(user, '*')) { GList *all_users = auth_get_known_users(); GList *matching_users = match_glob_list(user, all_users); GList *users = g_list_first(matching_users); if (!users) { qerrorf("Error: no users matching [%s] were found.\n", user); g_list_destroy(all_users); result = -1; goto freeall; } while (users) { result = do_export(users->data, mailbox, basedir, outfile, search, delete_after_dump, recursive); if (!g_list_next(users)) break; users = g_list_next(users); } g_list_destroy(all_users); g_list_destroy(matching_users); } else { /* No globbing, just run with this one user. */ result = do_export(user, mailbox, basedir, outfile, search, delete_after_dump, recursive); } /* Here's where we free memory and quit. * Be sure that all of these are NULL safe! */ freeall: db_disconnect(); auth_disconnect(); config_free(); g_mime_shutdown(); if (result < 0) qerrorf("Command failed.\n"); return result; }