4 * Index messages by EUID per room.
14 #if TIME_WITH_SYS_TIME
15 # include <sys/time.h>
19 # include <sys/time.h>
32 #include <libcitadel.h>
38 #include "sysdep_decls.h"
39 #include "citserver.h"
45 #include "euidindex.h"
48 * The structure of an euidindex record *key* is:
50 * |----room_number----|----------EUID-------------|
51 * (sizeof long) (actual length of euid)
54 * The structure of an euidindex record *value* is:
56 * |-----msg_number----|----room_number----|----------EUID-------------|
57 * (sizeof long) (sizeof long) (actual length of euid)
64 * Return nonzero if the supplied room is one which should have
67 int DoesThisRoomNeedEuidIndexing(struct ctdlroom
*qrbuf
) {
69 switch(qrbuf
->QRdefaultview
) {
70 case VIEW_BBS
: return(0);
71 case VIEW_MAILBOX
: return(0);
72 case VIEW_ADDRESSBOOK
: return(1);
73 case VIEW_CALENDAR
: return(1);
74 case VIEW_TASKS
: return(1);
75 case VIEW_NOTES
: return(1);
76 case VIEW_WIKI
: return(1);
88 * Locate a message in a given room with a given euid, and return
91 long locate_message_by_euid(char *euid
, struct ctdlroom
*qrbuf
) {
94 struct cdbdata
*cdb_euid
;
97 CtdlLogPrintf(CTDL_DEBUG
, "Searching for EUID <%s> in <%s>\n", euid
, qrbuf
->QRname
);
99 key_len
= strlen(euid
) + sizeof(long) + 1;
100 key
= malloc(key_len
);
101 memcpy(key
, &qrbuf
->QRnumber
, sizeof(long));
102 strcpy(&key
[sizeof(long)], euid
);
104 cdb_euid
= cdb_fetch(CDB_EUIDINDEX
, key
, key_len
);
107 if (cdb_euid
== NULL
) {
111 /* The first (sizeof long) of the record is what we're
112 * looking for. Throw away the rest.
114 memcpy(&msgnum
, cdb_euid
->ptr
, sizeof(long));
117 CtdlLogPrintf(CTDL_DEBUG
, "returning msgnum = %ld\n", msgnum
);
123 * Store the euid index for a message, which has presumably just been
124 * stored in this room by the caller.
126 void index_message_by_euid(char *euid
, struct ctdlroom
*qrbuf
, long msgnum
) {
132 CtdlLogPrintf(CTDL_DEBUG
, "Indexing message #%ld <%s> in <%s>\n", msgnum
, euid
, qrbuf
->QRname
);
134 key_len
= strlen(euid
) + sizeof(long) + 1;
135 key
= malloc(key_len
);
136 memcpy(key
, &qrbuf
->QRnumber
, sizeof(long));
137 strcpy(&key
[sizeof(long)], euid
);
139 data_len
= sizeof(long) + key_len
;
140 data
= malloc(data_len
);
142 memcpy(data
, &msgnum
, sizeof(long));
143 memcpy(&data
[sizeof(long)], key
, key_len
);
145 cdb_store(CDB_EUIDINDEX
, key
, key_len
, data
, data_len
);
153 * Called by rebuild_euid_index_for_room() to index one message.
155 void rebuild_euid_index_for_msg(long msgnum
, void *userdata
) {
156 struct CtdlMessage
*msg
= NULL
;
158 msg
= CtdlFetchMessage(msgnum
, 0);
159 if (msg
== NULL
) return;
160 if (msg
->cm_fields
['E'] != NULL
) {
161 index_message_by_euid(msg
->cm_fields
['E'], &CC
->room
, msgnum
);
163 CtdlFreeMessage(msg
);
167 void rebuild_euid_index_for_room(struct ctdlroom
*qrbuf
, void *data
) {
168 static struct RoomProcList
*rplist
= NULL
;
169 struct RoomProcList
*ptr
;
172 /* Lazy programming here. Call this function as a ForEachRoom backend
173 * in order to queue up the room names, or call it with a null room
174 * to make it do the processing.
177 ptr
= (struct RoomProcList
*)
178 malloc(sizeof (struct RoomProcList
));
179 if (ptr
== NULL
) return;
181 safestrncpy(ptr
->name
, qrbuf
->QRname
, sizeof ptr
->name
);
187 while (rplist
!= NULL
) {
188 if (getroom(&qr
, rplist
->name
) == 0) {
189 if (DoesThisRoomNeedEuidIndexing(&qr
)) {
190 CtdlLogPrintf(CTDL_DEBUG
,
191 "Rebuilding EUID index for <%s>\n",
193 usergoto(rplist
->name
, 0, 0, NULL
, NULL
);
194 CtdlForEachMessage(MSGS_ALL
, 0L, NULL
, NULL
, NULL
,
195 rebuild_euid_index_for_msg
, NULL
);
199 rplist
= rplist
->next
;
206 * Globally rebuild the EUID indices in every room.
208 void rebuild_euid_index(void) {
209 cdb_trunc(CDB_EUIDINDEX
); /* delete the old indices */
210 ForEachRoom(rebuild_euid_index_for_room
, NULL
); /* enumerate rm names */
211 rebuild_euid_index_for_room(NULL
, NULL
); /* and index them */
217 * Server command to fetch a message number given an euid.
219 void cmd_euid(char *cmdbuf
) {
222 struct cdbdata
*cdbfr
;
223 long *msglist
= NULL
;
227 if (CtdlAccessCheck(ac_logged_in
)) return;
229 extract_token(euid
, cmdbuf
, 0, '|', sizeof euid
);
230 msgnum
= locate_message_by_euid(euid
, &CC
->room
);
232 cprintf("%d not found\n", ERROR
+ MESSAGE_NOT_FOUND
);
236 cdbfr
= cdb_fetch(CDB_MSGLISTS
, &CC
->room
.QRnumber
, sizeof(long));
238 num_msgs
= cdbfr
->len
/ sizeof(long);
239 msglist
= (long *) cdbfr
->ptr
;
240 for (i
= 0; i
< num_msgs
; ++i
) {
241 if (msglist
[i
] == msgnum
) {
243 cprintf("%d %ld\n", CIT_OK
, msgnum
);
250 cprintf("%d not found\n", ERROR
+ MESSAGE_NOT_FOUND
);