citadel
About: Citadel is an advanced messaging and collaboration system for groupware and BBS applications (preferred OS: Linux).
  Fossies Dox: citadel.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

euidindex.c
Go to the documentation of this file.
1/*
2 * Index messages by EUID per room.
3 *
4 * Copyright (c) 1987-2020 by the citadel.org team
5 *
6 * This program is open source software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License, version 3.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#include "sysdep.h"
16#include <stdio.h>
17#include <libcitadel.h>
18
19#include "citserver.h"
20#include "room_ops.h"
21
22/*
23 * The structure of an euidindex record *key* is:
24 *
25 * |----room_number----|----------EUID-------------|
26 * (sizeof long) (actual length of euid)
27 *
28 *
29 * The structure of an euidindex record *value* is:
30 *
31 * |-----msg_number----|----room_number----|----------EUID-------------|
32 * (sizeof long) (sizeof long) (actual length of euid)
33 *
34 */
35
36/*
37 * Return nonzero if the supplied room is one which should have
38 * an EUID index.
39 */
41
42 switch(qrbuf->QRdefaultview) {
43 case VIEW_BBS: return(0);
44 case VIEW_MAILBOX: return(0);
45 case VIEW_ADDRESSBOOK: return(1);
46 case VIEW_DRAFTS: return(0);
47 case VIEW_CALENDAR: return(1);
48 case VIEW_TASKS: return(1);
49 case VIEW_NOTES: return(1);
50 case VIEW_WIKI: return(1);
51 case VIEW_BLOG: return(1);
52 }
53
54 return(0);
55}
56
57
58/*
59 * Locate a message in a given room with a given euid, and return
60 * its message number.
61 */
62long locate_message_by_euid(char *euid, struct ctdlroom *qrbuf) {
63 return CtdlLocateMessageByEuid (euid, qrbuf);
64}
65
66
67long CtdlLocateMessageByEuid(char *euid, struct ctdlroom *qrbuf) {
68 char *key;
69 int key_len;
70 struct cdbdata *cdb_euid;
71 long msgnum = (-1L);
72
73 syslog(LOG_DEBUG, "euidindex: searching for EUID <%s> in <%s>", euid, qrbuf->QRname);
74
75 key_len = strlen(euid) + sizeof(long) + 1;
76 key = malloc(key_len);
77 memcpy(key, &qrbuf->QRnumber, sizeof(long));
78 strcpy(&key[sizeof(long)], euid);
79
80 cdb_euid = cdb_fetch(CDB_EUIDINDEX, key, key_len);
81 free(key);
82
83 if (cdb_euid == NULL) {
84 msgnum = (-1L);
85 }
86 else {
87 /* The first (sizeof long) of the record is what we're
88 * looking for. Throw away the rest.
89 */
90 memcpy(&msgnum, cdb_euid->ptr, sizeof(long));
91 cdb_free(cdb_euid);
92 }
93 syslog(LOG_DEBUG, "euidindex: returning msgnum = %ld", msgnum);
94 return(msgnum);
95}
96
97
98/*
99 * Store the euid index for a message, which has presumably just been
100 * stored in this room by the caller.
101 */
102void index_message_by_euid(char *euid, struct ctdlroom *qrbuf, long msgnum) {
103 char *key;
104 int key_len;
105 char *data;
106 int data_len;
107
108 syslog(LOG_DEBUG, "euidindex: indexing message #%ld <%s> in <%s>", msgnum, euid, qrbuf->QRname);
109
110 key_len = strlen(euid) + sizeof(long) + 1;
111 key = malloc(key_len);
112 memcpy(key, &qrbuf->QRnumber, sizeof(long));
113 strcpy(&key[sizeof(long)], euid);
114
115 data_len = sizeof(long) + key_len;
116 data = malloc(data_len);
117
118 memcpy(data, &msgnum, sizeof(long));
119 memcpy(&data[sizeof(long)], key, key_len);
120
121 cdb_store(CDB_EUIDINDEX, key, key_len, data, data_len);
122 free(key);
123 free(data);
124}
125
126
127/*
128 * Called by rebuild_euid_index_for_room() to index one message.
129 */
130void rebuild_euid_index_for_msg(long msgnum, void *userdata) {
131 struct CtdlMessage *msg = NULL;
132
133 msg = CtdlFetchMessage(msgnum, 0);
134 if (msg == NULL) return;
135 if (!CM_IsEmpty(msg, eExclusiveID)) {
136 index_message_by_euid(msg->cm_fields[eExclusiveID], &CC->room, msgnum);
137 }
138 CM_Free(msg);
139}
140
141
142void rebuild_euid_index_for_room(struct ctdlroom *qrbuf, void *data) {
143 static struct RoomProcList *rplist = NULL;
144 struct RoomProcList *ptr;
145 struct ctdlroom qr;
146
147 /* Lazy programming here. Call this function as a CtdlForEachRoom backend
148 * in order to queue up the room names, or call it with a null room
149 * to make it do the processing.
150 */
151 if (qrbuf != NULL) {
152 ptr = (struct RoomProcList *)
153 malloc(sizeof (struct RoomProcList));
154 if (ptr == NULL) return;
155
156 safestrncpy(ptr->name, qrbuf->QRname, sizeof ptr->name);
157 ptr->next = rplist;
158 rplist = ptr;
159 return;
160 }
161
162 while (rplist != NULL) {
163 if (CtdlGetRoom(&qr, rplist->name) == 0) {
165 syslog(LOG_DEBUG,
166 "euidindex: rebuilding EUID index for <%s>",
167 rplist->name);
168 CtdlUserGoto(rplist->name, 0, 0, NULL, NULL, NULL, NULL);
169 CtdlForEachMessage(MSGS_ALL, 0L, NULL, NULL, NULL, rebuild_euid_index_for_msg, NULL);
170 }
171 }
172 ptr = rplist;
173 rplist = rplist->next;
174 free(ptr);
175 }
176}
177
178
179/*
180 * Globally rebuild the EUID indices in every room.
181 */
183 cdb_trunc(CDB_EUIDINDEX); /* delete the old indices */
184 CtdlForEachRoom(rebuild_euid_index_for_room, NULL); /* enumerate rm names */
185 rebuild_euid_index_for_room(NULL, NULL); /* and index them */
186}
187
188
189/*
190 * Server command to fetch a message number given an euid.
191 */
192void cmd_euid(char *cmdbuf) {
193 char euid[256];
194 long msgnum;
195 struct cdbdata *cdbfr;
196 long *msglist = NULL;
197 int num_msgs = 0;
198 int i;
199
201
202 extract_token(euid, cmdbuf, 0, '|', sizeof euid);
203 msgnum = CtdlLocateMessageByEuid(euid, &CC->room);
204 if (msgnum <= 0L) {
205 cprintf("%d not found\n", ERROR + MESSAGE_NOT_FOUND);
206 return;
207 }
208
209 cdbfr = cdb_fetch(CDB_MSGLISTS, &CC->room.QRnumber, sizeof(long));
210 if (cdbfr != NULL) {
211 num_msgs = cdbfr->len / sizeof(long);
212 msglist = (long *) cdbfr->ptr;
213 for (i = 0; i < num_msgs; ++i) {
214 if (msglist[i] == msgnum) {
215 cdb_free(cdbfr);
216 cprintf("%d %ld\n", CIT_OK, msgnum);
217 return;
218 }
219 }
220 cdb_free(cdbfr);
221 }
222
223 cprintf("%d not found\n", ERROR + MESSAGE_NOT_FOUND);
224}
225
226
228{
229 if (!threading) {
230 CtdlRegisterProtoHook(cmd_euid, "EUID", "Perform operations on Extended IDs for messages");
231 }
232 /* return our Subversion id for the Log */
233 return "euidindex";
234}
#define CC
Definition: context.h:140
int CtdlAccessCheck(int)
Definition: user_ops.c:387
int CtdlGetRoom(struct ctdlroom *qrbuf, const char *room_name)
Definition: room_ops.c:342
void CtdlForEachRoom(ForEachRoomCallBack CB, void *in_data)
Definition: room_ops.c:606
@ ac_logged_in_or_guest
Definition: ctdl_module.h:243
void CtdlUserGoto(char *where, int display_result, int transiently, int *msgs, int *new, long *oldest, long *newest)
Definition: room_ops.c:702
void CtdlRegisterProtoHook(void(*handler)(char *), char *cmd, char *desc)
#define CTDL_MODULE_INIT(module_name)
Definition: ctdl_module.h:50
void cdb_free(struct cdbdata *cdb)
Definition: database.c:609
int cdb_store(int cdb, const void *ckey, int ckeylen, void *cdata, int cdatalen)
Definition: database.c:397
struct cdbdata * cdb_fetch(int cdb, const void *key, int keylen)
Definition: database.c:546
void cdb_trunc(int cdb)
Definition: database.c:726
void rebuild_euid_index(void)
Definition: euidindex.c:182
long CtdlLocateMessageByEuid(char *euid, struct ctdlroom *qrbuf)
Definition: euidindex.c:67
void cmd_euid(char *cmdbuf)
Definition: euidindex.c:192
long locate_message_by_euid(char *euid, struct ctdlroom *qrbuf)
Definition: euidindex.c:62
void index_message_by_euid(char *euid, struct ctdlroom *qrbuf, long msgnum)
Definition: euidindex.c:102
void rebuild_euid_index_for_room(struct ctdlroom *qrbuf, void *data)
Definition: euidindex.c:142
int DoesThisRoomNeedEuidIndexing(struct ctdlroom *qrbuf)
Definition: euidindex.c:40
void rebuild_euid_index_for_msg(long msgnum, void *userdata)
Definition: euidindex.c:130
#define CIT_OK
Definition: ipcdef.h:6
#define ERROR
Definition: ipcdef.h:9
#define MESSAGE_NOT_FOUND
Definition: ipcdef.h:34
void CM_Free(struct CtdlMessage *msg)
Definition: msgbase.c:310
int CtdlForEachMessage(int mode, long ref, char *search_string, char *content_type, struct CtdlMessage *compare, ForEachMsgCallback CallBack, void *userdata)
Definition: msgbase.c:626
struct CtdlMessage * CtdlFetchMessage(long msgnum, int with_body)
Definition: msgbase.c:1135
int CM_IsEmpty(struct CtdlMessage *Msg, eMsgField which)
Definition: msgbase.c:137
@ MSGS_ALL
Definition: msgbase.h:6
void * malloc(size_t)
void free(void *)
struct ctdlroom qrbuf
Definition: serv_migrate.c:497
@ eExclusiveID
Definition: server.h:309
@ CDB_EUIDINDEX
Definition: server.h:195
@ CDB_MSGLISTS
Definition: server.h:189
char * cm_fields[256]
Definition: server.h:37
struct RoomProcList * next
Definition: citserver.h:21
char name[128]
Definition: citserver.h:22
size_t len
Definition: server.h:203
char * ptr
Definition: server.h:204
char QRname[128]
Definition: citadel.h:108
long QRnumber
Definition: citadel.h:119
int QRdefaultview
Definition: citadel.h:122
void cprintf(const char *format,...)
Definition: sysdep.c:381