4 * Citadel Dynamic Loading Module
5 * Written by Brian Costello <btx@calyx.net>
13 #include <sys/types.h>
18 #include <libcitadel.h>
21 #include "serv_extensions.h"
22 #include "sysdep_decls.h"
26 #include "modules/crypto/serv_crypto.h" /* Needed until a universal crypto startup hook is implimented for CtdlStartTLS */
28 #include "ctdl_module.h"
35 struct CleanupFunctionHook
*CleanupHookTable
= NULL
;
36 struct SessionFunctionHook
*SessionHookTable
= NULL
;
37 struct UserFunctionHook
*UserHookTable
= NULL
;
38 struct XmsgFunctionHook
*XmsgHookTable
= NULL
;
39 struct MessageFunctionHook
*MessageHookTable
= NULL
;
40 struct NetprocFunctionHook
*NetprocHookTable
= NULL
;
41 struct DeleteFunctionHook
*DeleteHookTable
= NULL
;
42 struct ServiceFunctionHook
*ServiceHookTable
= NULL
;
43 struct FixedOutputHook
*FixedOutputTable
= NULL
;
44 struct RoomFunctionHook
*RoomHookTable
= NULL
;
45 struct SearchFunctionHook
*SearchFunctionHookTable
= NULL
;
47 struct ProtoFunctionHook
{
48 void (*handler
) (char *cmdbuf
);
51 struct ProtoFunctionHook
*next
;
52 } *ProtoHookList
= NULL
;
55 struct DirectoryServiceHook
{
56 int (*handler
) (char *cn
, char *ou
, void **object
);
59 struct DirectoryServiceHook
*next
;
60 } *DirectoryServiceHookList
= NULL
;
62 struct DirectoryObject
{
65 struct DirectoryObject
*next
;
68 #define ERR_PORT (1 << 1)
71 static char *portlist
= NULL
;
72 static size_t nSizPort
= 0;
74 static char *errormessages
= NULL
;
75 size_t nSizErrmsg
= 0;
78 long DetailErrorFlags
;
80 char *ErrSubject
= "Startup Problems";
81 char *ErrGeneral
= "Citadel had trouble on starting up. %s This means, citadel won't be the service provider for a specific service you configured it to.\n\n"
82 "If you don't want citadel to provide these services, turn them off in WebCit via %s%s\n\n%s\n\n"
83 "To make both ways actualy take place restart the citserver with \"sendcommand down\"\n\n"
84 "The errors returned by the system were:\n%s\n"
85 "You can recheck the above if you follow this faq item:\n"
86 "http://www.citadel.org/doku.php/faq:mastering_your_os:net#netstat";
89 char *ErrPortShort
= "We couldn't bind all ports you configured to be provided by citadel server.";
90 char *ErrPortWhere
= "Admin->System Preferences->Network.\n\nThe failed ports and sockets are: ";
91 char *ErrPortHint
= "If you want citadel to provide you with that functionality, "
92 "check the output of \"netstat -lnp\" on linux Servers or \"netstat -na\" on *BSD"
93 " and stop the programm, that binds these ports. You should eventually remove "
94 " their initscripts in /etc/init.d so that you won't get this trouble once more.\n"
95 " After that goto Administration -> Shutdown Citadel to make Citadel retry to bind this port.\n";
98 void LogPrintMessages(long err
)
100 char *List
, *DetailList
, *Short
, *Where
, *Hint
, *Message
;
101 int n
= nSizPort
+ nSizErrmsg
+ 5;
103 Message
= (char*) malloc(n
* SIZ
);
105 DetailErrorFlags
= DetailErrorFlags
& ~err
;
110 Short
= ErrPortShort
;
111 Where
= ErrPortWhere
;
114 DetailList
= errormessages
;
125 snprintf(Message
, n
* SIZ
, ErrGeneral
, Short
, Where
, List
, Hint
, DetailList
);
127 CtdlLogPrintf(0,Message
);
128 CtdlLogPrintf(0,ErrSubject
);
129 quickie_message("Citadel", NULL
, NULL
, AIDEROOM
, Message
, FMT_FIXED
, ErrSubject
);
130 if (errormessages
!=NULL
) free (errormessages
);
131 errormessages
= NULL
;
132 if (portlist
!=NULL
) free (portlist
);
139 void AppendString(char **target
, char *append
, size_t *len
, size_t rate
)
145 AddLen
= strlen(append
);
151 *target
= (char*)malloc (*len
* SIZ
);
155 oLen
= strlen(*target
);
156 RelPtr
= strlen(*target
);
157 if (oLen
+ AddLen
+ 2 > *len
* SIZ
)
159 char *Buff
= *target
;
160 size_t NewSiz
= *len
+ 10;
161 *target
= malloc (NewSiz
* SIZ
);
162 memcpy (*target
, Buff
, NewSiz
* SIZ
);
166 memcpy (*target
+ oLen
, append
, AddLen
);
167 (*target
)[oLen
+ AddLen
+ 1] = '\n';
168 (*target
)[oLen
+ AddLen
+ 2] = '\0';
171 void AddPortError(char *Port
, char *ErrorMessage
)
176 DetailErrorFlags
|= ERR_PORT
;
178 AppendString(&errormessages
, ErrorMessage
, &nSizErrmsg
, 10);
179 AppendString(&portlist
, Port
, &nSizPort
, 2);
181 pos
= strchr (portlist
, ':');
182 if (pos
!= NULL
) *pos
= ';';
184 len
= strlen (errormessages
);
185 if (nSizErrmsg
* SIZ
> len
+ 3)
187 errormessages
[len
] = ';';
188 errormessages
[len
+1] = ' ';
189 errormessages
[len
+2] = '\0';
194 int DLoader_Exec_Cmd(char *cmdbuf
)
196 struct ProtoFunctionHook
*p
;
198 for (p
= ProtoHookList
; p
; p
= p
->next
) {
199 if (!strncasecmp(cmdbuf
, p
->cmd
, 4)) {
200 p
->handler(&cmdbuf
[5]);
208 void CtdlRegisterProtoHook(void (*handler
) (char *), char *cmd
, char *desc
)
210 struct ProtoFunctionHook
*p
;
212 p
= (struct ProtoFunctionHook
*)
213 malloc(sizeof(struct ProtoFunctionHook
));
216 fprintf(stderr
, "can't malloc new ProtoFunctionHook\n");
219 p
->handler
= handler
;
222 p
->next
= ProtoHookList
;
224 CtdlLogPrintf(CTDL_INFO
, "Registered server command %s (%s)\n", cmd
, desc
);
228 void CtdlUnregisterProtoHook(void (*handler
) (char *), char *cmd
)
230 struct ProtoFunctionHook
*cur
= NULL
;
231 struct ProtoFunctionHook
*p
= NULL
;
232 struct ProtoFunctionHook
*lastcur
= NULL
;
234 for (cur
= ProtoHookList
;
236 cur
= (cur
!= NULL
)? cur
->next
: NULL
) {
237 /* This will also remove duplicates if any */
238 while (cur
!= NULL
&&
239 handler
== cur
->handler
&&
240 !strcmp(cmd
, cur
->cmd
)) {
241 CtdlLogPrintf(CTDL_INFO
, "Unregistered server command %s (%s)\n",
244 if (cur
== ProtoHookList
) {
247 else if (lastcur
!= NULL
)
258 void CtdlDestroyProtoHooks(void)
260 struct ProtoFunctionHook
*cur
, *p
;
265 CtdlLogPrintf(CTDL_INFO
, "Destroyed server command %s (%s)\n",
266 cur
->cmd
, cur
->desc
);
271 ProtoHookList
= NULL
;
275 void CtdlRegisterCleanupHook(void (*fcn_ptr
) (void))
278 struct CleanupFunctionHook
*newfcn
;
280 newfcn
= (struct CleanupFunctionHook
*)
281 malloc(sizeof(struct CleanupFunctionHook
));
282 newfcn
->next
= CleanupHookTable
;
283 newfcn
->h_function_pointer
= fcn_ptr
;
284 CleanupHookTable
= newfcn
;
286 CtdlLogPrintf(CTDL_INFO
, "Registered a new cleanup function\n");
290 void CtdlUnregisterCleanupHook(void (*fcn_ptr
) (void))
292 struct CleanupFunctionHook
*cur
, *p
;
294 for (cur
= CleanupHookTable
; cur
!= NULL
; cur
= cur
->next
) {
295 /* This will also remove duplicates if any */
296 while (cur
!= NULL
&&
297 fcn_ptr
== cur
->h_function_pointer
) {
298 CtdlLogPrintf(CTDL_INFO
, "Unregistered cleanup function\n");
300 if (cur
== CleanupHookTable
) {
301 CleanupHookTable
= p
;
309 void CtdlDestroyCleanupHooks(void)
311 struct CleanupFunctionHook
*cur
, *p
;
313 cur
= CleanupHookTable
;
316 CtdlLogPrintf(CTDL_INFO
, "Destroyed cleanup function\n");
321 CleanupHookTable
= NULL
;
325 void CtdlRegisterSessionHook(void (*fcn_ptr
) (void), int EventType
)
328 struct SessionFunctionHook
*newfcn
;
330 newfcn
= (struct SessionFunctionHook
*)
331 malloc(sizeof(struct SessionFunctionHook
));
332 newfcn
->next
= SessionHookTable
;
333 newfcn
->h_function_pointer
= fcn_ptr
;
334 newfcn
->eventtype
= EventType
;
335 SessionHookTable
= newfcn
;
337 CtdlLogPrintf(CTDL_INFO
, "Registered a new session function (type %d)\n",
342 void CtdlUnregisterSessionHook(void (*fcn_ptr
) (void), int EventType
)
344 struct SessionFunctionHook
*cur
, *p
;
346 for (cur
= SessionHookTable
; cur
!= NULL
; cur
= cur
->next
) {
347 /* This will also remove duplicates if any */
348 while (cur
!= NULL
&&
349 fcn_ptr
== cur
->h_function_pointer
&&
350 EventType
== cur
->eventtype
) {
351 CtdlLogPrintf(CTDL_INFO
, "Unregistered session function (type %d)\n",
354 if (cur
== SessionHookTable
) {
355 SessionHookTable
= p
;
363 void CtdlDestroySessionHooks(void)
365 struct SessionFunctionHook
*cur
, *p
;
367 cur
= SessionHookTable
;
370 CtdlLogPrintf(CTDL_INFO
, "Destroyed session function\n");
375 SessionHookTable
= NULL
;
379 void CtdlRegisterUserHook(void (*fcn_ptr
) (struct ctdluser
*), int EventType
)
382 struct UserFunctionHook
*newfcn
;
384 newfcn
= (struct UserFunctionHook
*)
385 malloc(sizeof(struct UserFunctionHook
));
386 newfcn
->next
= UserHookTable
;
387 newfcn
->h_function_pointer
= fcn_ptr
;
388 newfcn
->eventtype
= EventType
;
389 UserHookTable
= newfcn
;
391 CtdlLogPrintf(CTDL_INFO
, "Registered a new user function (type %d)\n",
396 void CtdlUnregisterUserHook(void (*fcn_ptr
) (struct ctdluser
*), int EventType
)
398 struct UserFunctionHook
*cur
, *p
;
400 for (cur
= UserHookTable
; cur
!= NULL
; cur
= cur
->next
) {
401 /* This will also remove duplicates if any */
402 while (cur
!= NULL
&&
403 fcn_ptr
== cur
->h_function_pointer
&&
404 EventType
== cur
->eventtype
) {
405 CtdlLogPrintf(CTDL_INFO
, "Unregistered user function (type %d)\n",
408 if (cur
== UserHookTable
) {
417 void CtdlDestroyUserHooks(void)
419 struct UserFunctionHook
*cur
, *p
;
424 CtdlLogPrintf(CTDL_INFO
, "Destroyed user function \n");
429 UserHookTable
= NULL
;
433 void CtdlRegisterMessageHook(int (*handler
)(struct CtdlMessage
*),
437 struct MessageFunctionHook
*newfcn
;
439 newfcn
= (struct MessageFunctionHook
*)
440 malloc(sizeof(struct MessageFunctionHook
));
441 newfcn
->next
= MessageHookTable
;
442 newfcn
->h_function_pointer
= handler
;
443 newfcn
->eventtype
= EventType
;
444 MessageHookTable
= newfcn
;
446 CtdlLogPrintf(CTDL_INFO
, "Registered a new message function (type %d)\n",
451 void CtdlUnregisterMessageHook(int (*handler
)(struct CtdlMessage
*),
454 struct MessageFunctionHook
*cur
, *p
;
456 for (cur
= MessageHookTable
; cur
!= NULL
; cur
= cur
->next
) {
457 /* This will also remove duplicates if any */
458 while (cur
!= NULL
&&
459 handler
== cur
->h_function_pointer
&&
460 EventType
== cur
->eventtype
) {
461 CtdlLogPrintf(CTDL_INFO
, "Unregistered message function (type %d)\n",
464 if (cur
== MessageHookTable
) {
465 MessageHookTable
= p
;
473 void CtdlDestroyMessageHook(void)
475 struct MessageFunctionHook
*cur
, *p
;
477 cur
= MessageHookTable
;
480 CtdlLogPrintf(CTDL_INFO
, "Destroyed message function (type %d)\n", cur
->eventtype
);
485 MessageHookTable
= NULL
;
489 void CtdlRegisterRoomHook(int (*fcn_ptr
)(struct ctdlroom
*))
491 struct RoomFunctionHook
*newfcn
;
493 newfcn
= (struct RoomFunctionHook
*)
494 malloc(sizeof(struct RoomFunctionHook
));
495 newfcn
->next
= RoomHookTable
;
496 newfcn
->fcn_ptr
= fcn_ptr
;
497 RoomHookTable
= newfcn
;
499 CtdlLogPrintf(CTDL_INFO
, "Registered a new room function\n");
503 void CtdlUnregisterRoomHook(int (*fcn_ptr
)(struct ctdlroom
*))
505 struct RoomFunctionHook
*cur
, *p
;
507 for (cur
= RoomHookTable
; cur
!= NULL
; cur
= cur
->next
) {
508 while (cur
!= NULL
&& fcn_ptr
== cur
->fcn_ptr
) {
509 CtdlLogPrintf(CTDL_INFO
, "Unregistered room function\n");
511 if (cur
== RoomHookTable
) {
521 void CtdlDestroyRoomHooks(void)
523 struct RoomFunctionHook
*cur
, *p
;
528 CtdlLogPrintf(CTDL_INFO
, "Destroyed room function\n");
533 RoomHookTable
= NULL
;
536 void CtdlRegisterNetprocHook(int (*handler
)(struct CtdlMessage
*, char *) )
538 struct NetprocFunctionHook
*newfcn
;
540 newfcn
= (struct NetprocFunctionHook
*)
541 malloc(sizeof(struct NetprocFunctionHook
));
542 newfcn
->next
= NetprocHookTable
;
543 newfcn
->h_function_pointer
= handler
;
544 NetprocHookTable
= newfcn
;
546 CtdlLogPrintf(CTDL_INFO
, "Registered a new netproc function\n");
550 void CtdlUnregisterNetprocHook(int (*handler
)(struct CtdlMessage
*, char *) )
552 struct NetprocFunctionHook
*cur
, *p
;
554 for (cur
= NetprocHookTable
; cur
!= NULL
; cur
= cur
->next
) {
555 /* This will also remove duplicates if any */
556 while (cur
!= NULL
&&
557 handler
== cur
->h_function_pointer
) {
558 CtdlLogPrintf(CTDL_INFO
, "Unregistered netproc function\n");
560 if (cur
== NetprocHookTable
) {
561 NetprocHookTable
= p
;
569 void CtdlDestroyNetprocHooks(void)
571 struct NetprocFunctionHook
*cur
, *p
;
573 cur
= NetprocHookTable
;
576 CtdlLogPrintf(CTDL_INFO
, "Destroyed netproc function\n");
581 NetprocHookTable
= NULL
;
585 void CtdlRegisterDeleteHook(void (*handler
)(char *, long) )
587 struct DeleteFunctionHook
*newfcn
;
589 newfcn
= (struct DeleteFunctionHook
*)
590 malloc(sizeof(struct DeleteFunctionHook
));
591 newfcn
->next
= DeleteHookTable
;
592 newfcn
->h_function_pointer
= handler
;
593 DeleteHookTable
= newfcn
;
595 CtdlLogPrintf(CTDL_INFO
, "Registered a new delete function\n");
599 void CtdlUnregisterDeleteHook(void (*handler
)(char *, long) )
601 struct DeleteFunctionHook
*cur
, *p
;
603 for (cur
= DeleteHookTable
; cur
!= NULL
; cur
= cur
->next
) {
604 /* This will also remove duplicates if any */
605 while (cur
!= NULL
&&
606 handler
== cur
->h_function_pointer
) {
607 CtdlLogPrintf(CTDL_INFO
, "Unregistered delete function\n");
609 if (cur
== DeleteHookTable
) {
617 void CtdlDestroyDeleteHooks(void)
619 struct DeleteFunctionHook
*cur
, *p
;
621 cur
= DeleteHookTable
;
624 CtdlLogPrintf(CTDL_INFO
, "Destroyed delete function\n");
629 DeleteHookTable
= NULL
;
635 void CtdlRegisterFixedOutputHook(char *content_type
, void (*handler
)(char *, int) )
637 struct FixedOutputHook
*newfcn
;
639 newfcn
= (struct FixedOutputHook
*)
640 malloc(sizeof(struct FixedOutputHook
));
641 newfcn
->next
= FixedOutputTable
;
642 newfcn
->h_function_pointer
= handler
;
643 safestrncpy(newfcn
->content_type
, content_type
, sizeof newfcn
->content_type
);
644 FixedOutputTable
= newfcn
;
646 CtdlLogPrintf(CTDL_INFO
, "Registered a new fixed output function for %s\n", newfcn
->content_type
);
650 void CtdlUnregisterFixedOutputHook(char *content_type
)
652 struct FixedOutputHook
*cur
, *p
;
654 for (cur
= FixedOutputTable
; cur
!= NULL
; cur
= cur
->next
) {
655 /* This will also remove duplicates if any */
656 while (cur
!= NULL
&& (!strcasecmp(content_type
, cur
->content_type
))) {
657 CtdlLogPrintf(CTDL_INFO
, "Unregistered fixed output function for %s\n", content_type
);
659 if (cur
== FixedOutputTable
) {
660 FixedOutputTable
= p
;
668 void CtdlDestroyFixedOutputHooks(void)
670 struct FixedOutputHook
*cur
, *p
;
672 cur
= FixedOutputTable
;
675 CtdlLogPrintf(CTDL_INFO
, "Destroyed fixed output function for %s\n", cur
->content_type
);
681 FixedOutputTable
= NULL
;
684 /* returns nonzero if we found a hook and used it */
685 int PerformFixedOutputHooks(char *content_type
, char *content
, int content_length
)
687 struct FixedOutputHook
*fcn
;
689 for (fcn
= FixedOutputTable
; fcn
!= NULL
; fcn
= fcn
->next
) {
690 if (!strcasecmp(content_type
, fcn
->content_type
)) {
691 (*fcn
->h_function_pointer
) (content
, content_length
);
702 void CtdlRegisterXmsgHook(int (*fcn_ptr
) (char *, char *, char *, char *), int order
)
705 struct XmsgFunctionHook
*newfcn
;
707 newfcn
= (struct XmsgFunctionHook
*) malloc(sizeof(struct XmsgFunctionHook
));
708 newfcn
->next
= XmsgHookTable
;
709 newfcn
->order
= order
;
710 newfcn
->h_function_pointer
= fcn_ptr
;
711 XmsgHookTable
= newfcn
;
712 CtdlLogPrintf(CTDL_INFO
, "Registered a new x-msg function (priority %d)\n", order
);
716 void CtdlUnregisterXmsgHook(int (*fcn_ptr
) (char *, char *, char *, char *), int order
)
718 struct XmsgFunctionHook
*cur
, *p
;
720 for (cur
= XmsgHookTable
; cur
!= NULL
; cur
= cur
->next
) {
721 /* This will also remove duplicates if any */
722 while (cur
!= NULL
&&
723 fcn_ptr
== cur
->h_function_pointer
&&
724 order
== cur
->order
) {
725 CtdlLogPrintf(CTDL_INFO
, "Unregistered x-msg function "
726 "(priority %d)\n", order
);
728 if (cur
== XmsgHookTable
) {
737 void CtdlDestroyXmsgHooks(void)
739 struct XmsgFunctionHook
*cur
, *p
;
744 CtdlLogPrintf(CTDL_INFO
, "Destroyed x-msg function "
745 "(priority %d)\n", cur
->order
);
751 XmsgHookTable
= NULL
;
755 void CtdlRegisterServiceHook(int tcp_port
,
757 void (*h_greeting_function
) (void),
758 void (*h_command_function
) (void),
759 void (*h_async_function
) (void),
760 const char *ServiceName
)
762 struct ServiceFunctionHook
*newfcn
;
767 newfcn
= (struct ServiceFunctionHook
*)
768 malloc(sizeof(struct ServiceFunctionHook
));
769 message
= (char*) malloc (SIZ
);
771 newfcn
->next
= ServiceHookTable
;
772 newfcn
->tcp_port
= tcp_port
;
773 newfcn
->sockpath
= sockpath
;
774 newfcn
->h_greeting_function
= h_greeting_function
;
775 newfcn
->h_command_function
= h_command_function
;
776 newfcn
->h_async_function
= h_async_function
;
777 newfcn
->ServiceName
= ServiceName
;
779 if (sockpath
!= NULL
) {
780 newfcn
->msock
= ig_uds_server(sockpath
, config
.c_maxsessions
, &error
);
781 snprintf(message
, SIZ
, "Unix domain socket '%s': ", sockpath
);
783 else if (tcp_port
<= 0) { /* port -1 to disable */
784 CtdlLogPrintf(CTDL_INFO
, "Service %s has been manually disabled, skipping\n", ServiceName
);
790 newfcn
->msock
= ig_tcp_server(config
.c_ip_addr
,
792 config
.c_maxsessions
,
794 snprintf(message
, SIZ
, "TCP port %s:%d: (%s) ",
795 config
.c_ip_addr
, tcp_port
, ServiceName
);
798 if (newfcn
->msock
> 0) {
799 ServiceHookTable
= newfcn
;
800 strcat(message
, "registered.");
801 CtdlLogPrintf(CTDL_INFO
, "%s\n", message
);
804 AddPortError(message
, error
);
805 strcat(message
, "FAILED.");
806 CtdlLogPrintf(CTDL_CRIT
, "%s\n", message
);
814 void CtdlUnregisterServiceHook(int tcp_port
, char *sockpath
,
815 void (*h_greeting_function
) (void),
816 void (*h_command_function
) (void),
817 void (*h_async_function
) (void)
820 struct ServiceFunctionHook
*cur
, *p
;
822 for (cur
= ServiceHookTable
; cur
!= NULL
; cur
= cur
->next
) {
823 /* This will also remove duplicates if any */
824 while (cur
!= NULL
&&
825 !(sockpath
&& cur
->sockpath
&&
826 strcmp(sockpath
, cur
->sockpath
)) &&
827 h_greeting_function
== cur
->h_greeting_function
&&
828 h_command_function
== cur
->h_command_function
&&
829 h_async_function
== cur
->h_async_function
&&
830 tcp_port
== cur
->tcp_port
) {
833 CtdlLogPrintf(CTDL_INFO
, "Closed UNIX domain socket %s\n",
835 } else if (tcp_port
) {
836 CtdlLogPrintf(CTDL_INFO
, "Closed TCP port %d\n", tcp_port
);
838 CtdlLogPrintf(CTDL_INFO
, "Unregistered service \"%s\"\n", cur
->ServiceName
);
841 if (cur
== ServiceHookTable
) {
842 ServiceHookTable
= p
;
850 void CtdlDestroyServiceHook(void)
852 struct ServiceFunctionHook
*cur
, *p
;
854 cur
= ServiceHookTable
;
859 CtdlLogPrintf(CTDL_INFO
, "Closed UNIX domain socket %s\n",
861 } else if (cur
->tcp_port
) {
862 CtdlLogPrintf(CTDL_INFO
, "Closed TCP port %d\n", cur
->tcp_port
);
864 CtdlLogPrintf(CTDL_INFO
, "Destroyed service \"%s\"\n", cur
->ServiceName
);
870 ServiceHookTable
= NULL
;
873 void CtdlRegisterSearchFuncHook(void (*fcn_ptr
)(int *, long **, char *), char *name
)
875 struct SearchFunctionHook
*newfcn
;
877 if (!name
|| !fcn_ptr
) {
881 newfcn
= (struct SearchFunctionHook
*)
882 malloc(sizeof(struct SearchFunctionHook
));
883 newfcn
->next
= SearchFunctionHookTable
;
885 newfcn
->fcn_ptr
= fcn_ptr
;
886 SearchFunctionHookTable
= newfcn
;
888 CtdlLogPrintf(CTDL_INFO
, "Registered a new search function (%s)\n", name
);
891 void CtdlUnregisterSearchFuncHook(void (*fcn_ptr
)(int *, long **, char *), char *name
)
893 struct SearchFunctionHook
*cur
, *p
;
895 for (cur
= SearchFunctionHookTable
; cur
!= NULL
; cur
= cur
->next
) {
896 while (fcn_ptr
&& (cur
->fcn_ptr
== fcn_ptr
) && name
&& !strcmp(name
, cur
->name
)) {
897 CtdlLogPrintf(CTDL_INFO
, "Unregistered search function(%s)\n", name
);
899 if (cur
== SearchFunctionHookTable
) {
900 SearchFunctionHookTable
= p
;
908 void CtdlModuleDoSearch(int *num_msgs
, long **search_msgs
, char *search_string
, char *func_name
)
910 struct SearchFunctionHook
*fcn
= NULL
;
912 for (fcn
= SearchFunctionHookTable
; fcn
!= NULL
; fcn
= fcn
->next
) {
913 if (!func_name
|| !strcmp(func_name
, fcn
->name
)) {
914 (*fcn
->fcn_ptr
) (num_msgs
, search_msgs
, search_string
);
922 void PerformSessionHooks(int EventType
)
924 struct SessionFunctionHook
*fcn
= NULL
;
926 for (fcn
= SessionHookTable
; fcn
!= NULL
; fcn
= fcn
->next
) {
927 if (fcn
->eventtype
== EventType
) {
928 (*fcn
->h_function_pointer
) ();
933 void PerformUserHooks(struct ctdluser
*usbuf
, int EventType
)
935 struct UserFunctionHook
*fcn
= NULL
;
937 for (fcn
= UserHookTable
; fcn
!= NULL
; fcn
= fcn
->next
) {
938 if (fcn
->eventtype
== EventType
) {
939 (*fcn
->h_function_pointer
) (usbuf
);
944 int PerformMessageHooks(struct CtdlMessage
*msg
, int EventType
)
946 struct MessageFunctionHook
*fcn
= NULL
;
947 int total_retval
= 0;
949 /* Other code may elect to protect this message from server-side
950 * handlers; if this is the case, don't do anything.
951 CtdlLogPrintf(CTDL_DEBUG, "** Event type is %d, flags are %d\n",
952 EventType, msg->cm_flags);
954 if (msg
->cm_flags
& CM_SKIP_HOOKS
) {
955 CtdlLogPrintf(CTDL_DEBUG
, "Skipping hooks\n");
959 /* Otherwise, run all the hooks appropriate to this event type.
961 for (fcn
= MessageHookTable
; fcn
!= NULL
; fcn
= fcn
->next
) {
962 if (fcn
->eventtype
== EventType
) {
963 total_retval
= total_retval
+
964 (*fcn
->h_function_pointer
) (msg
);
968 /* Return the sum of the return codes from the hook functions. If
969 * this is an EVT_BEFORESAVE event, a nonzero return code will cause
970 * the save operation to abort.
976 int PerformRoomHooks(struct ctdlroom
*target_room
)
978 struct RoomFunctionHook
*fcn
;
979 int total_retval
= 0;
981 CtdlLogPrintf(CTDL_DEBUG
, "Performing room hooks for <%s>\n", target_room
->QRname
);
983 for (fcn
= RoomHookTable
; fcn
!= NULL
; fcn
= fcn
->next
) {
984 total_retval
= total_retval
+ (*fcn
->fcn_ptr
) (target_room
);
987 /* Return the sum of the return codes from the hook functions.
993 int PerformNetprocHooks(struct CtdlMessage
*msg
, char *target_room
)
995 struct NetprocFunctionHook
*fcn
;
996 int total_retval
= 0;
998 for (fcn
= NetprocHookTable
; fcn
!= NULL
; fcn
= fcn
->next
) {
999 total_retval
= total_retval
+
1000 (*fcn
->h_function_pointer
) (msg
, target_room
);
1003 /* Return the sum of the return codes from the hook functions.
1004 * A nonzero return code will cause the message to *not* be imported.
1006 return total_retval
;
1010 void PerformDeleteHooks(char *room
, long msgnum
)
1012 struct DeleteFunctionHook
*fcn
;
1014 for (fcn
= DeleteHookTable
; fcn
!= NULL
; fcn
= fcn
->next
) {
1015 (*fcn
->h_function_pointer
) (room
, msgnum
);
1023 int PerformXmsgHooks(char *sender
, char *sender_email
, char *recp
, char *msg
)
1025 struct XmsgFunctionHook
*fcn
;
1029 for (p
=0; p
<MAX_XMSG_PRI
; ++p
) {
1030 for (fcn
= XmsgHookTable
; fcn
!= NULL
; fcn
= fcn
->next
) {
1031 if (fcn
->order
== p
) {
1033 (*fcn
->h_function_pointer
)
1034 (sender
, sender_email
, recp
, msg
);
1037 /* Break out of the loop if a higher-priority function
1038 * successfully delivered the message. This prevents duplicate
1039 * deliveries to local users simultaneously signed onto
1042 if (total_sent
) break;
1050 int CtdlRegisterDirectoryServiceFunc(int (*func
)(char *cn
, char *ou
, void **object
), int cmd
, char *module
)
1052 struct DirectoryServiceHook
*newfcn
;
1054 newfcn
= DirectoryServiceHookList
;
1057 if (newfcn
->cmd
== cmd
&& !strcmp(newfcn
->module
, module
))
1059 CtdlLogPrintf(CTDL_ERR
, "Directory service function already handled by module %s\n", module
);
1062 newfcn
= newfcn
->next
;
1065 newfcn
= (struct DirectoryServiceHook
*) malloc (sizeof(struct DirectoryServiceHook
));
1066 newfcn
->handler
= func
;
1068 newfcn
->module
= module
;
1069 newfcn
->next
= DirectoryServiceHookList
;
1070 DirectoryServiceHookList
= newfcn
;
1072 CtdlLogPrintf(CTDL_INFO
, "Registered a new directory service function from module %s\n", module
);
1076 int CtdlDoDirectoryServiceFunc(char *cn
, char *ou
, void **object
, char *module
, int cmd
)
1078 struct DirectoryServiceHook
*curfcn
;
1079 struct DirectoryObject
*our_object_list
= NULL
;
1080 struct DirectoryObject
*newobject
= NULL
;
1081 struct DirectoryObject
*oldobject
= NULL
;
1084 curfcn
= DirectoryServiceHookList
;
1086 our_object_list
= (struct DirectoryObject
*) *object
;
1090 if (curfcn
->cmd
== cmd
)
1094 if (cmd
== DIRECTORY_CREATE_OBJECT
)
1096 newobject
= (struct DirectoryObject
*) malloc (sizeof(struct DirectoryObject
));
1097 newobject
->module
= curfcn
->module
;
1098 newobject
->object
= NULL
;
1099 newobject
->next
= our_object_list
;
1100 our_object_list
= newobject
;
1102 if (our_object_list
)
1104 for(newobject
= our_object_list
; newobject
; newobject
=newobject
->next
)
1106 if (!strcmp(newobject
->module
, curfcn
->module
))
1107 (void) curfcn
->handler(cn
, ou
, &newobject
->object
);
1111 (void) curfcn
->handler(cn
, ou
, NULL
);
1117 if(!strcmp(curfcn
->module
, module
))
1119 if (cmd
== DIRECTORY_CREATE_OBJECT
)
1121 newobject
= (struct DirectoryObject
*) malloc (sizeof(struct DirectoryObject
));
1122 newobject
->module
= module
;
1123 newobject
->object
= NULL
;
1124 newobject
->next
= our_object_list
;
1125 our_object_list
= newobject
;
1127 if (our_object_list
)
1129 for(newobject
= our_object_list
; newobject
; newobject
=newobject
->next
)
1131 if (!strcmp(newobject
->module
, curfcn
->module
))
1132 (void) curfcn
->handler(cn
, ou
, &newobject
->object
);
1136 (void) (curfcn
->handler(cn
, ou
, NULL
));
1142 curfcn
=curfcn
->next
;
1144 if (our_object_list
)
1146 *object
= our_object_list
;
1147 if (cmd
== DIRECTORY_FREE_OBJECT
)
1148 { // The objects pointed to by the list should have been freed by the module that created it
1149 for(newobject
= our_object_list
; newobject
; )
1151 oldobject
=newobject
;
1152 newobject
=newobject
->next
;
1161 void CtdlDestroyDirectoryServiceFuncs(void)
1163 struct DirectoryServiceHook
*cur
, *next
;
1165 cur
= DirectoryServiceHookList
;
1166 DirectoryServiceHookList
= NULL
;
1170 CtdlLogPrintf(CTDL_INFO
, "Destroyed directory service function for module %s.\n", cur
->module
);
1177 * Dirty hack until we impliment a hook mechanism for this
1179 void CtdlModuleStartCryptoMsgs(char *ok_response
, char *nosup_response
, char *error_response
)
1182 CtdlStartTLS (ok_response
, nosup_response
, error_response
);