T p_string_new(Mempool_T pool, const char * s) { T S; assert(pool); assert(s); size_t l = strlen(s); S = mempool_pop(pool, sizeof(*S)); S->pool = pool; S->len = l; S->str = (char *)mempool_pop(S->pool, SIZE(S)); memcpy(S->str, s, l); S->used = l; return S; }
T Capa_new(Mempool_T pool) { Field_T val; char maxcapa[MAX_CAPASIZE]; T A; A = mempool_pop(pool, sizeof(*A)); A->pool = pool; char **v, **h; memset(&maxcapa,0,sizeof(maxcapa)); GETCONFIGVALUE("capability", "IMAP", val); if (strlen(val) > 0) strncpy((char *)maxcapa, val, MAX_CAPASIZE-1); else strncpy((char *)maxcapa, IMAP_CAPABILITY_STRING, MAX_CAPASIZE-1); A->max_set = p_list_new(A->pool); A->current_set = p_list_new(A->pool); h = v = g_strsplit(maxcapa, " ", -1); while (*v) { String_T S = p_string_new(A->pool, *v++); A->max_set = p_list_append(A->max_set, S); A->current_set = p_list_append(A->current_set, S); assert(A->current_set); } g_strfreev(h); A->dirty = TRUE; return A; }
static gboolean mailbox_build_recent(uint64_t *uid, MessageInfo *msginfo, T M) { if (msginfo->flags[IMAP_FLAG_RECENT]) { uint64_t *copy = mempool_pop(M->pool, sizeof(uint64_t)); *copy = *uid; g_tree_insert(M->recent_queue, copy, copy); } return FALSE; }
static int filter_range(gpointer key, gpointer value, gpointer data) { uint64_t *k, *v; struct filter_range_helper *d = (struct filter_range_helper *)data; if (*(uint64_t *)key < d->min) return FALSE; // skip if (*(uint64_t *)key > d->max) return TRUE; // done k = mempool_pop(small_pool, sizeof(uint64_t)); v = mempool_pop(small_pool, sizeof(uint64_t)); *k = *(uint64_t *)key; *v = *(uint64_t *)value; if (d->uid) g_tree_insert(d->a, k, v); else g_tree_insert(d->a, v, k); return FALSE; }
T MailboxState_new(Mempool_T pool, uint64_t id) { T M; Connection_T c; volatile int t = DM_SUCCESS; gboolean freepool = FALSE; if (! pool) { pool = mempool_open(); freepool = TRUE; } M = mempool_pop(pool, sizeof(*M)); M->pool = pool; M->freepool = freepool; if (! id) return M; M->id = id; M->recent_queue = g_tree_new((GCompareFunc)ucmp); M->keywords = g_tree_new_full((GCompareDataFunc)_compare_data,NULL,g_free,NULL); c = db_con_get(); TRY db_begin_transaction(c); // we need read-committed isolation state_load_metadata(M, c); state_load_messages(M, c); CATCH(SQLException) LOG_SQLERROR; t = DM_EQUERY; FINALLY db_commit_transaction(c); db_con_close(c); END_TRY; if (t == DM_EQUERY) { TRACE(TRACE_ERR, "Error opening mailbox"); MailboxState_free(&M); } return 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; }
static int db_createsession(uint64_t user_idnr, ClientSession_T * session) { Connection_T c; ResultSet_T r; volatile int t = DM_SUCCESS; struct message *tmpmessage; int message_counter = 0; const char *query_result; uint64_t mailbox_idnr; INIT_QUERY; if (db_find_create_mailbox("INBOX", BOX_DEFAULT, user_idnr, &mailbox_idnr) < 0) { TRACE(TRACE_NOTICE, "find_create INBOX for user [%" PRIu64 "] failed, exiting..", user_idnr); return DM_EQUERY; } g_return_val_if_fail(mailbox_idnr > 0, DM_EQUERY); /* query is < MESSAGE_STATUS_DELETE because we don't want deleted * messages */ snprintf(query, DEF_QUERYSIZE-1, "SELECT pm.messagesize, msg.message_idnr, msg.status, " "msg.unique_id FROM %smessages msg, %sphysmessage pm " "WHERE msg.mailbox_idnr = %" PRIu64 " " "AND msg.status < %d " "AND msg.physmessage_id = pm.id " "ORDER BY msg.message_idnr ASC",DBPFX,DBPFX, mailbox_idnr, MESSAGE_STATUS_DELETE); c = db_con_get(); TRY r = db_query(c, query); session->totalmessages = 0; session->totalsize = 0; /* messagecounter is total message, +1 tot end at message 1 */ message_counter = 1; /* filling the list */ TRACE(TRACE_DEBUG, "adding items to list"); while (db_result_next(r)) { tmpmessage = mempool_pop(session->pool, sizeof(struct message)); /* message size */ tmpmessage->msize = db_result_get_u64(r,0); /* real message id */ tmpmessage->realmessageid = db_result_get_u64(r,1); /* message status */ tmpmessage->messagestatus = db_result_get_u64(r,2); /* virtual message status */ tmpmessage->virtual_messagestatus = tmpmessage->messagestatus; /* unique id */ query_result = db_result_get(r,3); if (query_result) strncpy(tmpmessage->uidl, query_result, UID_SIZE-1); session->totalmessages++; session->totalsize += tmpmessage->msize; tmpmessage->messageid = (uint64_t) message_counter; session->messagelst = p_list_append(session->messagelst, tmpmessage); message_counter++; } CATCH(SQLException) LOG_SQLERROR; t = DM_EQUERY; FINALLY db_con_close(c); END_TRY; if (t == DM_EQUERY) return t; if (message_counter == 1) { /* there are no messages for this user */ return DM_EGENERAL; } TRACE(TRACE_DEBUG, "adding succesful"); /* setting all virtual values */ session->virtual_totalmessages = session->totalmessages; session->virtual_totalsize = session->totalsize; return DM_EGENERAL; }
void imap_handle_input(ImapSession *session) { char buffer[MAX_LINESIZE]; char *alloc_buf = NULL; uint64_t alloc_size = 0; int l, result; assert(session && session->ci && session->ci->write_buffer); // first flush the output buffer if (p_string_len(session->ci->write_buffer)) { TRACE(TRACE_DEBUG,"[%p] write buffer not empty", session); ci_write(session->ci, NULL); } // nothing left to handle if (p_string_len(session->ci->read_buffer) == 0) { TRACE(TRACE_DEBUG,"[%p] read buffer empty", session); return; } // command in progress if (session->command_state == FALSE && session->parser_state == TRUE) { TRACE(TRACE_DEBUG,"[%p] command in-progress", session); return; } // reset if we're done with the previous command if (session->command_state == TRUE) imap_session_reset(session); // Read in a line at a time if we don't have a string literal size defined // Otherwise read in rbuff_size amount of data while (TRUE) { char *input = NULL; FREE_ALLOC_BUF memset(buffer, 0, sizeof(buffer)); if (session->ci->rbuff_size <= 0) { l = ci_readln(session->ci, buffer); } else { alloc_size = session->ci->rbuff_size+1; alloc_buf = mempool_pop(session->pool, alloc_size); l = ci_read(session->ci, alloc_buf, session->ci->rbuff_size); } if (l == 0) break; // done if (session->error_count >= MAX_FAULTY_RESPONSES) { imap_session_printf(session, "* BYE [TRY RFC]\r\n"); imap_handle_abort(session); break; } // session is in a IDLE loop if (session->command_type == IMAP_COMM_IDLE && session->command_state == IDLE) { if (strlen(buffer) > 4 && strncasecmp(buffer,"DONE",4)==0) imap_session_printf(session, "%s OK IDLE terminated\r\n", session->tag); else imap_session_printf(session,"%s BAD Expecting DONE\r\n", session->tag); session->command_state = TRUE; // done imap_session_reset(session); continue; } if (alloc_buf != NULL) input = alloc_buf; else input = buffer; if (! imap4_tokenizer(session, input)) { FREE_ALLOC_BUF continue; } if ( session->parser_state < 0 ) { imap_session_printf(session, "%s BAD parse error\r\n", session->tag); imap_handle_retry(session); break; } if ( session->parser_state ) { result = imap4(session); TRACE(TRACE_DEBUG,"imap4 returned [%d]", result); if (result || (session->command_type == IMAP_COMM_IDLE && session->command_state == IDLE)) { imap_handle_exit(session, result); } break; } if (session->state == CLIENTSTATE_ERROR) { TRACE(TRACE_NOTICE, "session->state: ERROR. abort"); break; } }