From: Art Cancro Date: Thu, 27 Jan 2011 23:11:22 +0000 (-0500) Subject: Replaced cached_msglist array with a btree persistent through the session. X-Git-Tag: v8.11~878 X-Git-Url: https://code.citadel.org/?p=citadel.git;a=commitdiff_plain;h=2da538b2dcf832611d6a81b233bab64c7bf9b009 Replaced cached_msglist array with a btree persistent through the session. --- diff --git a/citadel/citserver.c b/citadel/citserver.c index 86bd0687c..3f9ac42ab 100644 --- a/citadel/citserver.c +++ b/citadel/citserver.c @@ -907,7 +907,6 @@ void begin_session(CitContext *con) con->download_fp = NULL; con->upload_fp = NULL; con->cached_msglist = NULL; - con->cached_num_msgs = 0; con->FirstExpressMessage = NULL; time(&con->lastcmd); time(&con->lastidle); diff --git a/citadel/context.c b/citadel/context.c index 2b1cce1b0..32b306bf9 100644 --- a/citadel/context.c +++ b/citadel/context.c @@ -369,7 +369,7 @@ void RemoveContext (CitContext *con) FreeStrBuf(&con->MigrateBuf); FreeStrBuf(&con->RecvBuf.Buf); if (con->cached_msglist) { - free(con->cached_msglist); + seenit_free(&con->cached_msglist); } syslog(LOG_DEBUG, "Done with RemoveContext()\n"); diff --git a/citadel/context.h b/citadel/context.h index 224b468f9..f7f17b624 100644 --- a/citadel/context.h +++ b/citadel/context.h @@ -135,7 +135,7 @@ struct CitContext { void (*h_async_function) (void) ; /* do async msgs function */ void (*h_greeting_function) (void) ; /* greeting function for session startup */ - long *cached_msglist; /* results of the previous CtdlForEachMessage() */ + struct seenit *cached_msglist; /* results of the previous CtdlForEachMessage() */ int cached_num_msgs; }; diff --git a/citadel/msgbase.c b/citadel/msgbase.c index 7f337d3ab..7b46dbee5 100644 --- a/citadel/msgbase.c +++ b/citadel/msgbase.c @@ -593,6 +593,56 @@ void CtdlSetSeen(long *target_msgnums, int num_target_msgnums, } + +/* store a value in the binary tree */ +void seenit_store(struct seenit **si, long msgnum) { + struct seenit *this_si; + + if (*si == NULL) { /* store now */ + *si = malloc(sizeof(struct seenit)); + this_si = *si; + this_si->l = NULL; + this_si->r = NULL; + this_si->msgnum = msgnum; + return; + } + + this_si = *si; + if (msgnum < this_si->msgnum) { + seenit_store(&this_si->l, msgnum); + } + else if (msgnum > this_si->msgnum) { + seenit_store(&this_si->r, msgnum); + } + else { + return; + } +} + + +/* search for a value in the binary tree */ +int seenit_isthere(struct seenit *si, long msgnum) { + if (!si) return(0); /* not there */ + if (msgnum < si->msgnum) return(seenit_isthere(si->l, msgnum)); + if (msgnum > si->msgnum) return(seenit_isthere(si->r, msgnum)); + return(1); /* found it */ +} + + +/* free the binary tree */ +void seenit_free(struct seenit **si) { + struct seenit *this_si = *si; + if (!this_si) return; + seenit_free(&this_si->l); + seenit_free(&this_si->r); + free(this_si); + *si = NULL; +} + + + + + /* * API function to perform an operation for each qualifying message in the * current room. (Returns the number of messages processed.) @@ -644,23 +694,18 @@ int CtdlForEachMessage(int mode, long ref, char *search_string, cdbfr->ptr = NULL; /* clear this so that cdb_free() doesn't free it */ cdb_free(cdbfr); /* we own this memory now */ - /* - * We cache the most recent msglist in order to do security checks later - */ - if (CC->client_socket > 0) { - if (CC->cached_msglist != NULL) { - free(CC->cached_msglist); - } - - CC->cached_msglist = msglist; - CC->cached_num_msgs = num_msgs; - } - /* * Now begin the traversal. */ if (num_msgs > 0) for (a = 0; a < num_msgs; ++a) { + /* + * cache the msgnums we've seen in order to perform security checks later + */ + if (CC->client_socket > 0) { + seenit_store(&CC->cached_msglist, msglist[a]); + } + /* If the caller is looking for a specific MIME type, filter * out all messages which are not of the type requested. */ @@ -787,7 +832,7 @@ int CtdlForEachMessage(int mode, long ref, char *search_string, } } if (need_to_free_re) regfree(&re); - if (CC->client_socket <= 0) free(msglist); + free(msglist); return num_processed; } @@ -1556,24 +1601,9 @@ int check_cached_msglist(long msgnum) { if (!CC) return om_ok; /* not a session */ if (CC->client_socket <= 0) return om_ok; /* not a client session */ if (CC->cached_msglist == NULL) return om_access_denied; /* no msglist fetched */ - if (CC->cached_num_msgs == 0) return om_access_denied; /* nothing to check */ - - /* Do a binary search within the cached_msglist for the requested msgnum */ - int min = 0; - int max = (CC->cached_num_msgs - 1); - - while (max >= min) { - int middle = min + (max-min) / 2 ; - if (msgnum == CC->cached_msglist[middle]) { - return om_ok; - } - if (msgnum > CC->cached_msglist[middle]) { - min = middle + 1; - } - else { - max = middle - 1; - } + if (seenit_isthere(CC->cached_msglist, msgnum)) { + return om_ok; } return om_access_denied; @@ -1632,10 +1662,7 @@ int CtdlOutputMsg(long msg_num, /* message number (local) to fetch */ r = check_cached_msglist(msg_num); if (r != om_ok) { - syslog(LOG_DEBUG, "\033[31m SECURITY CHECK FAIL \033[0m\n"); -/* - * FIXME enable this section when the security check yields no false positives - * + syslog(LOG_DEBUG, "Denying access to message %ld - not yet listed\n", msg_num); if (do_proto) { if (r == om_access_denied) { cprintf("%d Message %ld was not found in this room.\n", @@ -1648,7 +1675,6 @@ int CtdlOutputMsg(long msg_num, /* message number (local) to fetch */ } return(r); } -*/ } /* diff --git a/citadel/msgbase.h b/citadel/msgbase.h index 3171fbd75..084e5189b 100644 --- a/citadel/msgbase.h +++ b/citadel/msgbase.h @@ -237,6 +237,11 @@ int CtdlIsMe(char *addr, int addr_buf_len); */ void aide_message(char *text, char *subject) __attribute__ ((deprecated)); +void seenit_store(struct seenit **si, long msgnum); +int seenit_isthere(struct seenit *si, long msgnum); +void seenit_free(struct seenit **si); + + /* * loading messages async via an FD: diff --git a/citadel/server.h b/citadel/server.h index 70770a15a..b0a1d8655 100644 --- a/citadel/server.h +++ b/citadel/server.h @@ -268,6 +268,14 @@ struct UseTable { }; +/* "seenit" is a simple binary tree storing the message pointers we've seen */ +struct seenit { + struct seenit *l; + struct seenit *r; + long msgnum; +}; + + /* Preferred field order */ /* ********** Important fields */ diff --git a/webcit/calendar.c b/webcit/calendar.c index fe81b9597..273df3bc8 100644 --- a/webcit/calendar.c +++ b/webcit/calendar.c @@ -806,7 +806,9 @@ void display_edit_event(void) { } /* - * save an edited event + * Save an edited event. If there is an older version of this event in the store, + * we first load it into memory and then apply the changes, so that any fields which + * Citael does not know how to handle will be preserved as-is. */ void save_event(void) { long msgnum = 0L;