/* $Id$ */
-#define UDS "_UDS_"
-#define DEFAULT_HOST UDS
-#define DEFAULT_PORT "citadel"
-
#include "sysdep.h"
#if TIME_WITH_SYS_TIME
# include <sys/time.h>
}
-char express_msgs = 0;
+char instant_msgs = 0;
static void serv_read(CtdlIPC *ipc, char *buf, unsigned int bytes);
static unsigned long id_callback(void);
#endif /* THREADED_CLIENT */
#endif /* HAVE_OPENSSL */
+static void CtdlIPC_getline(CtdlIPC* ipc, char *buf);
+static void CtdlIPC_putline(CtdlIPC *ipc, const char *buf);
/*
*/
int CtdlIPCQuit(CtdlIPC *ipc)
{
- register int ret;
+ register int ret = 221; /* Default to successful quit */
char aaa[128];
CtdlIPC_lock(ipc);
- CtdlIPC_putline(ipc, "QUIT");
- CtdlIPC_getline(ipc, aaa);
- ret = atoi(aaa);
+ if (ipc->sock > -1) {
+ CtdlIPC_putline(ipc, "QUIT");
+ CtdlIPC_getline(ipc, aaa);
+ ret = atoi(aaa);
+ }
+#ifdef HAVE_OPENSSL
+ if (ipc->ssl)
+ SSL_shutdown(ipc->ssl);
+ ipc->ssl = NULL;
+#endif
+ if (ipc->sock)
+ shutdown(ipc->sock, 2); /* Close connection; we're dead */
+ ipc->sock = -1;
CtdlIPC_unlock(ipc);
return ret;
}
{"LKRA", "LKRN", "LKRO", "LZRM", "LRMS", "LPRM" };
char aaa[SIZ];
char *bbb = NULL;
- size_t bbbsize;
+ size_t bbb_len;
if (!listing) return -2;
if (*listing) return -2; /* Free the listing first */
if (floor < -1) return -2; /* Can't validate upper bound, sorry */
sprintf(aaa, "%s %d", proto[which], floor);
- ret = CtdlIPCGenericCommand(ipc, aaa, NULL, 0, &bbb, &bbbsize, cret);
+ ret = CtdlIPCGenericCommand(ipc, aaa, NULL, 0, &bbb, &bbb_len, cret);
if (ret / 100 == 1) {
struct march *mptr;
while (bbb && strlen(bbb)) {
int a;
- extract_token(aaa, bbb, 0, '\n');
+ extract_token(aaa, bbb, 0, '\n', sizeof aaa);
a = strlen(aaa);
memmove(bbb, bbb + a + 1, strlen(bbb) - a);
mptr = (struct march *) malloc(sizeof (struct march));
if (mptr) {
mptr->next = NULL;
- extract(mptr->march_name, aaa, 0);
+ extract_token(mptr->march_name, aaa, 0, '|', sizeof mptr->march_name);
mptr->march_flags = (unsigned int) extract_int(aaa, 1);
mptr->march_floor = (char) extract_int(aaa, 2);
mptr->march_order = (char) extract_int(aaa, 3);
+ mptr->march_flags2 = (unsigned int) extract_int(aaa, 4);
+ mptr->march_access = (char) extract_int(aaa, 5);
if (march == NULL)
march = mptr;
else {
/* GETU */
-/* Caller must free the struct usersupp; caller may pass an existing one */
-int CtdlIPCGetConfig(CtdlIPC *ipc, struct usersupp **uret, char *cret)
+/* Caller must free the struct ctdluser; caller may pass an existing one */
+int CtdlIPCGetConfig(CtdlIPC *ipc, struct ctdluser **uret, char *cret)
{
register int ret;
if (!cret) return -2;
if (!uret) return -2;
- if (!*uret) *uret = (struct usersupp *)calloc(1, sizeof (struct usersupp));
+ if (!*uret) *uret = (struct ctdluser *)calloc(1, sizeof (struct ctdluser));
if (!*uret) return -1;
ret = CtdlIPCGenericCommand(ipc, "GETU", NULL, 0, NULL, NULL, cret);
/* SETU */
-int CtdlIPCSetConfig(CtdlIPC *ipc, struct usersupp *uret, char *cret)
+int CtdlIPCSetConfig(CtdlIPC *ipc, struct ctdluser *uret, char *cret)
{
char aaa[48];
}
ret = CtdlIPCGenericCommand(ipc, aaa, NULL, 0, NULL, NULL, cret);
if (ret / 100 == 2) {
- extract(rret[0]->RRname, cret, 0);
+ extract_token(rret[0]->RRname, cret, 0, '|', sizeof rret[0]->RRname);
rret[0]->RRunread = extract_long(cret, 1);
rret[0]->RRtotal = extract_long(cret, 2);
rret[0]->RRinfoupdated = extract_int(cret, 3);
/* MSGS */
/* which is 0 = all, 1 = old, 2 = new, 3 = last, 4 = first, 5 = gt, 6 = lt */
/* whicharg is number of messages, applies to last, first, gt, lt */
-int CtdlIPCGetMessages(CtdlIPC *ipc, int which, int whicharg,
- const char *mtemplate, long **mret, char *cret)
+int CtdlIPCGetMessages(CtdlIPC *ipc, enum MessageList which, int whicharg,
+ const char *mtemplate, unsigned long **mret, char *cret)
{
register int ret;
register unsigned long count = 0;
static char *proto[] =
{ "ALL", "OLD", "NEW", "LAST", "FIRST", "GT", "LT" };
char aaa[33];
- char *bbb;
- size_t bbbsize;
+ char *bbb = NULL;
+ size_t bbb_len;
if (!cret) return -2;
if (!mret) return -2;
sprintf(aaa, "MSGS %s|%d|%d", proto[which], whicharg,
(mtemplate) ? 1 : 0);
if (mtemplate) count = strlen(mtemplate);
- ret = CtdlIPCGenericCommand(ipc, aaa, mtemplate, count, &bbb, &bbbsize, cret);
+ ret = CtdlIPCGenericCommand(ipc, aaa, mtemplate, count, &bbb, &bbb_len, cret);
+ if (ret / 100 != 1)
+ return ret;
count = 0;
- while (strlen(bbb)) {
- int a;
-
- extract_token(aaa, bbb, 0, '\n');
- a = strlen(aaa);
- memmove(aaa, bbb + a + 1, strlen(bbb) - a - 1);
- *mret = (long *)realloc(mret,
- (size_t)((count + 1) * sizeof (long)));
- if (*mret)
- *mret[count++] = atol(aaa);
- *mret[count] = 0L;
+ *mret = (unsigned long *)calloc(1, sizeof(unsigned long));
+ if (!*mret)
+ return -1;
+ while (bbb && strlen(bbb)) {
+ extract_token(aaa, bbb, 0, '\n', sizeof aaa);
+ remove_token(bbb, 0, '\n');
+ *mret = (unsigned long *)realloc(*mret, (size_t)((count + 2) *
+ sizeof (unsigned long)));
+ if (*mret) {
+ (*mret)[count++] = atol(aaa);
+ (*mret)[count] = 0L;
+ } else {
+ break;
+ }
}
+ if (bbb) free(bbb);
return ret;
}
register int ret;
char aaa[SIZ];
char *bbb = NULL;
- size_t bbbsize;
+ size_t bbb_len;
int multipart_hunting = 0;
- char multipart_prefix[SIZ];
+ char multipart_prefix[128];
if (!cret) return -1;
if (!mret) return -1;
strcpy(mret[0]->content_type, "");
sprintf(aaa, "MSG%d %ld|%d", as_mime, msgnum, headers);
- ret = CtdlIPCGenericCommand(ipc, aaa, NULL, 0, &bbb, &bbbsize, cret);
+ ret = CtdlIPCGenericCommand(ipc, aaa, NULL, 0, &bbb, &bbb_len, cret);
if (ret / 100 == 1) {
if (as_mime != 2) {
strcpy(mret[0]->mime_chosen, "1"); /* Default chosen-part is "1" */
while (strlen(bbb) > 4 && bbb[4] == '=') {
- extract_token(aaa, bbb, 0, '\n');
+ extract_token(aaa, bbb, 0, '\n', sizeof aaa);
remove_token(bbb, 0, '\n');
if (!strncasecmp(aaa, "nhdr=yes", 8))
mret[0]->nhdr = 1;
else if (!strncasecmp(aaa, "from=", 5))
- strcpy(mret[0]->author, &aaa[5]);
+ safestrncpy(mret[0]->author, &aaa[5], SIZ);
else if (!strncasecmp(aaa, "type=", 5))
mret[0]->type = atoi(&aaa[5]);
else if (!strncasecmp(aaa, "msgn=", 5))
- strcpy(mret[0]->msgid, &aaa[5]);
+ safestrncpy(mret[0]->msgid, &aaa[5], SIZ);
else if (!strncasecmp(aaa, "subj=", 5))
- strcpy(mret[0]->subject, &aaa[5]);
+ safestrncpy(mret[0]->subject, &aaa[5], SIZ);
else if (!strncasecmp(aaa, "rfca=", 5))
- strcpy(mret[0]->email, &aaa[5]);
+ safestrncpy(mret[0]->email, &aaa[5], SIZ);
else if (!strncasecmp(aaa, "hnod=", 5))
- strcpy(mret[0]->hnod, &aaa[5]);
+ safestrncpy(mret[0]->hnod, &aaa[5], SIZ);
else if (!strncasecmp(aaa, "room=", 5))
- strcpy(mret[0]->room, &aaa[5]);
+ safestrncpy(mret[0]->room, &aaa[5], SIZ);
else if (!strncasecmp(aaa, "node=", 5))
- strcpy(mret[0]->node, &aaa[5]);
+ safestrncpy(mret[0]->node, &aaa[5], SIZ);
else if (!strncasecmp(aaa, "rcpt=", 5))
- strcpy(mret[0]->recipient, &aaa[5]);
+ safestrncpy(mret[0]->recipient, &aaa[5], SIZ);
else if (!strncasecmp(aaa, "time=", 5))
mret[0]->time = atol(&aaa[5]);
* us to determine which part we want to download.
*/
else if (!strncasecmp(aaa, "pref=", 5)) {
- extract(multipart_prefix, &aaa[5], 1);
+ extract_token(multipart_prefix, &aaa[5], 1, '|', sizeof multipart_prefix);
if (!strcasecmp(multipart_prefix,
"multipart/alternative")) {
++multipart_hunting;
}
}
else if (!strncasecmp(aaa, "suff=", 5)) {
- extract(multipart_prefix, &aaa[5], 1);
+ extract_token(multipart_prefix, &aaa[5], 1, '|', sizeof multipart_prefix);
if (!strcasecmp(multipart_prefix,
"multipart/alternative")) {
++multipart_hunting;
if (ptr) {
/* Fill the buffers for the caller */
- extract(ptr->name, &aaa[5], 0);
- extract(ptr->filename, &aaa[5], 1);
- extract(ptr->number, &aaa[5], 2);
- extract(ptr->disposition, &aaa[5], 3);
- extract(ptr->mimetype, &aaa[5], 4);
+ extract_token(ptr->name, &aaa[5], 0, '|', sizeof ptr->name);
+ extract_token(ptr->filename, &aaa[5], 1, '|', sizeof ptr->filename);
+ extract_token(ptr->number, &aaa[5], 2, '|', sizeof ptr->number);
+ extract_token(ptr->disposition, &aaa[5], 3, '|', sizeof ptr->disposition);
+ extract_token(ptr->mimetype, &aaa[5], 4, '|', sizeof ptr->mimetype);
ptr->length = extract_long(&aaa[5], 5);
if (!mret[0]->attachments)
mret[0]->attachments = ptr;
if (as_mime == 4) {
do {
if (!strncasecmp(bbb, "Content-type: ", 14)) {
- extract_token(mret[0]->content_type, bbb, 0, '\n');
+ extract_token(mret[0]->content_type, bbb, 0, '\n', sizeof mret[0]->content_type);
strcpy(mret[0]->content_type,
&mret[0]->content_type[14]);
striplt(mret[0]->content_type);
+
+ /* strip out ";charset=" portion. FIXME do something with
+ * the charset (like... convert it) instead of just throwing
+ * it away
+ */
+ if (strstr(mret[0]->content_type, ";") != NULL) {
+ strcpy(strstr(mret[0]->content_type, ";"), "");
+ }
+
}
remove_token(bbb, 0, '\n');
} while ((bbb[0] != 0) && (bbb[0] != '\n'));
+ remove_token(bbb, 0, '\n');
}
}
if (strlen(bbb)) {
- /* Strip trailing whitespace */
+ /* FIXME: Strip trailing whitespace */
bbb = (char *)realloc(bbb, (size_t)(strlen(bbb) + 1));
} else {
bbb = (char *)realloc(bbb, 1);
/* INFO */
-int CtdlIPCServerInfo(CtdlIPC *ipc, struct CtdlServInfo *ServInfo, char *cret)
+int CtdlIPCServerInfo(CtdlIPC *ipc, char *cret)
{
register int ret;
size_t bytes;
char buf[SIZ];
if (!cret) return -2;
- if (!ServInfo) return -2;
ret = CtdlIPCGenericCommand(ipc, "INFO", NULL, 0, &listing, &bytes, cret);
if (ret / 100 == 1) {
int line = 0;
while (*listing && strlen(listing)) {
- extract_token(buf, listing, 0, '\n');
+ extract_token(buf, listing, 0, '\n', sizeof buf);
remove_token(listing, 0, '\n');
switch (line++) {
- case 0: ServInfo->serv_pid = atoi(buf);
+ case 0: ipc->ServInfo.pid = atoi(buf);
break;
- case 1: strcpy(ServInfo->serv_nodename,buf);
+ case 1: strcpy(ipc->ServInfo.nodename,buf);
break;
- case 2: strcpy(ServInfo->serv_humannode,buf);
+ case 2: strcpy(ipc->ServInfo.humannode,buf);
break;
- case 3: strcpy(ServInfo->serv_fqdn,buf);
+ case 3: strcpy(ipc->ServInfo.fqdn,buf);
break;
- case 4: strcpy(ServInfo->serv_software,buf);
+ case 4: strcpy(ipc->ServInfo.software,buf);
break;
- case 5: ServInfo->serv_rev_level = atoi(buf);
+ case 5: ipc->ServInfo.rev_level = atoi(buf);
break;
- case 6: strcpy(ServInfo->serv_bbs_city,buf);
+ case 6: strcpy(ipc->ServInfo.site_location,buf);
break;
- case 7: strcpy(ServInfo->serv_sysadm,buf);
+ case 7: strcpy(ipc->ServInfo.sysadm,buf);
break;
- case 9: strcpy(ServInfo->serv_moreprompt,buf);
+ case 9: strcpy(ipc->ServInfo.moreprompt,buf);
break;
- case 10: ServInfo->serv_ok_floors = atoi(buf);
+ case 10: ipc->ServInfo.ok_floors = atoi(buf);
break;
- case 11: ServInfo->serv_paging_level = atoi(buf);
+ case 11: ipc->ServInfo.paging_level = atoi(buf);
break;
- case 13: ServInfo->serv_supports_qnop = atoi(buf);
+ case 13: ipc->ServInfo.supports_qnop = atoi(buf);
+ break;
+ case 14: ipc->ServInfo.supports_ldap = atoi(buf);
break;
}
}
if (!cret) return -2;
- if (msgnum)
+ if (msgnum) {
sprintf(aaa, "SLRP %ld", msgnum);
- else
+ }
+ else {
sprintf(aaa, "SLRP HIGHEST");
+ }
ret = CtdlIPCGenericCommand(ipc, aaa, NULL, 0, NULL, NULL, cret);
return ret;
}
/* GETR */
-int CtdlIPCGetRoomAttributes(CtdlIPC *ipc, struct quickroom **qret, char *cret)
+int CtdlIPCGetRoomAttributes(CtdlIPC *ipc, struct ctdlroom **qret, char *cret)
{
register int ret;
if (!cret) return -2;
if (!qret) return -2;
- if (!*qret) *qret = (struct quickroom *)calloc(1, sizeof (struct quickroom));
+ if (!*qret) *qret = (struct ctdlroom *)calloc(1, sizeof (struct ctdlroom));
if (!*qret) return -1;
ret = CtdlIPCGenericCommand(ipc, "GETR", NULL, 0, NULL, NULL, cret);
if (ret / 100 == 2) {
- extract(qret[0]->QRname, cret, 0);
- extract(qret[0]->QRpasswd, cret, 1);
- extract(qret[0]->QRdirname, cret, 2);
+ extract_token(qret[0]->QRname, cret, 0, '|', sizeof qret[0]->QRname);
+ extract_token(qret[0]->QRpasswd, cret, 1, '|', sizeof qret[0]->QRpasswd);
+ extract_token(qret[0]->QRdirname, cret, 2, '|', sizeof qret[0]->QRdirname);
qret[0]->QRflags = extract_int(cret, 3);
qret[0]->QRfloor = extract_int(cret, 4);
qret[0]->QRorder = extract_int(cret, 5);
/* SETR */
/* set forget to kick all users out of room */
-int CtdlIPCSetRoomAttributes(CtdlIPC *ipc, int forget, struct quickroom *qret, char *cret)
+int CtdlIPCSetRoomAttributes(CtdlIPC *ipc, int forget, struct ctdlroom *qret, char *cret)
{
register int ret;
char *aaa;
if (!qret) return -2;
aaa = (char *)malloc(strlen(qret->QRname) + strlen(qret->QRpasswd) +
- strlen(qret->QRdirname) + 52);
+ strlen(qret->QRdirname) + 64);
if (!aaa) return -1;
- sprintf(aaa, "SETR %s|%s|%s|%d|%d|%d|%d",
+ sprintf(aaa, "SETR %s|%s|%s|%d|%d|%d|%d|%d|%d",
qret->QRname, qret->QRpasswd, qret->QRdirname,
- qret->QRflags, forget, qret->QRfloor, qret->QRorder);
+ qret->QRflags, forget, qret->QRfloor, qret->QRorder,
+ qret->QRdefaultview, qret->QRflags2);
ret = CtdlIPCGenericCommand(ipc, aaa, NULL, 0, NULL, NULL, cret);
free(aaa);
return ret;
int CtdlIPCPostMessage(CtdlIPC *ipc, int flag, const struct ctdlipcmessage *mr, char *cret)
{
register int ret;
- char *aaa;
+ char cmd[SIZ];
if (!cret) return -2;
if (!mr) return -2;
- aaa = (char *)malloc(strlen(mr->recipient) + strlen(mr->author) + 40);
- if (!aaa) return -1;
-
- sprintf(aaa, "ENT0 %d|%s|%d|%d|%s", flag, mr->recipient, mr->anonymous,
- mr->type, mr->author);
- ret = CtdlIPCGenericCommand(ipc, aaa, mr->text, strlen(mr->text), NULL,
+ snprintf(cmd, sizeof cmd,
+ "ENT0 %d|%s|%d|%d|%s|%s", flag, mr->recipient,
+ mr->anonymous, mr->type, mr->subject, mr->author);
+ ret = CtdlIPCGenericCommand(ipc, cmd, mr->text, strlen(mr->text), NULL,
NULL, cret);
- free(aaa);
return ret;
}
/* LIST */
-int CtdlIPCUserListing(CtdlIPC *ipc, char **listing, char *cret)
+int CtdlIPCUserListing(CtdlIPC *ipc, char *searchstring, char **listing, char *cret)
{
size_t bytes;
+ char *cmd;
+ int ret;
if (!cret) return -1;
if (!listing) return -1;
if (*listing) return -1;
+ if (!searchstring) return -1;
+
+ cmd = malloc(strlen(searchstring) + 10);
+ sprintf(cmd, "LIST %s", searchstring);
- return CtdlIPCGenericCommand(ipc, "LIST", NULL, 0, listing, &bytes, cret);
+ ret = CtdlIPCGenericCommand(ipc, cmd, NULL, 0, listing, &bytes, cret);
+ free(cmd);
+ return(ret);
}
/* OPEN */
int CtdlIPCFileDownload(CtdlIPC *ipc, const char *filename, void **buf,
size_t resume,
- void (*progress_gauge_callback)(unsigned long, unsigned long),
+ void (*progress_gauge_callback)
+ (CtdlIPC*, unsigned long, unsigned long),
char *cret)
{
register int ret;
ipc->downloading = 1;
bytes = extract_long(cret, 0);
last_mod = extract_int(cret, 1);
- extract(mimetype, cret, 2);
- ret = CtdlIPCReadDownload(ipc, buf, bytes, resume, progress_gauge_callback, cret);
-/* ret = CtdlIPCHighSpeedReadDownload(ipc, buf, bytes, resume, progress_gauge_callback, cret); */
+ extract_token(mimetype, cret, 2, '|', sizeof mimetype);
+
+ ret = CtdlIPCReadDownload(ipc, buf, bytes, resume,
+ progress_gauge_callback, cret);
+ /*
+ ret = CtdlIPCHighSpeedReadDownload(ipc, buf, bytes, resume,
+ progress_gauge_callback, cret);
+ */
+
ret = CtdlIPCEndDownload(ipc, cret);
if (ret / 100 == 2)
sprintf(cret, "%d|%ld|%s|%s", (int)bytes, last_mod,
/* OPNA */
int CtdlIPCAttachmentDownload(CtdlIPC *ipc, long msgnum, const char *part,
void **buf,
- void (*progress_gauge_callback)(unsigned long, unsigned long),
+ void (*progress_gauge_callback)
+ (CtdlIPC*, unsigned long, unsigned long),
char *cret)
{
register int ret;
time_t last_mod;
char filename[SIZ];
char mimetype[SIZ];
- char *aaa;
+ char aaa[SIZ];
if (!cret) return -2;
if (!buf) return -2;
if (!msgnum) return -2;
if (ipc->downloading) return -2;
- aaa = (char *)malloc(strlen(part) + 17);
- if (!aaa) return -1;
-
sprintf(aaa, "OPNA %ld|%s", msgnum, part);
ret = CtdlIPCGenericCommand(ipc, aaa, NULL, 0, NULL, NULL, cret);
- free(aaa);
if (ret / 100 == 2) {
ipc->downloading = 1;
bytes = extract_long(cret, 0);
last_mod = extract_int(cret, 1);
- extract(mimetype, cret, 2);
+ extract_token(filename, cret, 2, '|', sizeof filename);
+ extract_token(mimetype, cret, 3, '|', sizeof mimetype);
+ /* ret = CtdlIPCReadDownload(ipc, buf, bytes, 0, progress_gauge_callback, cret); */
ret = CtdlIPCHighSpeedReadDownload(ipc, buf, bytes, 0, progress_gauge_callback, cret);
ret = CtdlIPCEndDownload(ipc, cret);
if (ret / 100 == 2)
/* OIMG */
int CtdlIPCImageDownload(CtdlIPC *ipc, const char *filename, void **buf,
- void (*progress_gauge_callback)(unsigned long, unsigned long),
+ void (*progress_gauge_callback)
+ (CtdlIPC*, unsigned long, unsigned long),
char *cret)
{
register int ret;
ipc->downloading = 1;
bytes = extract_long(cret, 0);
last_mod = extract_int(cret, 1);
- extract(mimetype, cret, 2);
- ret = CtdlIPCReadDownload(ipc, buf, bytes, 0, progress_gauge_callback, cret);
+ extract_token(mimetype, cret, 2, '|', sizeof mimetype);
+/* ret = CtdlIPCReadDownload(ipc, buf, bytes, 0, progress_gauge_callback, cret); */
+ ret = CtdlIPCHighSpeedReadDownload(ipc, buf, bytes, 0, progress_gauge_callback, cret);
ret = CtdlIPCEndDownload(ipc, cret);
if (ret / 100 == 2)
sprintf(cret, "%d|%ld|%s|%s", (int)bytes, last_mod,
/* UOPN */
int CtdlIPCFileUpload(CtdlIPC *ipc, const char *save_as, const char *comment,
const char *path,
- void (*progress_gauge_callback)(unsigned long, unsigned long),
+ void (*progress_gauge_callback)
+ (CtdlIPC*, unsigned long, unsigned long),
char *cret)
{
register int ret;
/* UIMG */
int CtdlIPCImageUpload(CtdlIPC *ipc, int for_real, const char *path,
const char *save_as,
- void (*progress_gauge_callback)(unsigned long, unsigned long),
+ void (*progress_gauge_callback)
+ (CtdlIPC*, unsigned long, unsigned long),
char *cret)
{
register int ret;
int CtdlIPCCreateFloor(CtdlIPC *ipc, int for_real, const char *name, char *cret)
{
register int ret;
- char *aaa;
+ char aaa[SIZ];
if (!cret) return -2;
if (!name) return -2;
- aaa = (char *)malloc(strlen(name) + 17);
- if (!aaa) return -1;
-
sprintf(aaa, "CFLR %s|%d", name, for_real);
ret = CtdlIPCGenericCommand(ipc, aaa, NULL, 0, NULL, NULL, cret);
- free(aaa);
return ret;
}
/* KFLR */
int CtdlIPCDeleteFloor(CtdlIPC *ipc, int for_real, int floornum, char *cret)
{
- char aaa[27];
+ char aaa[SIZ];
if (!cret) return -1;
if (floornum < 0) return -1;
int CtdlIPCEditFloor(CtdlIPC *ipc, int floornum, const char *floorname, char *cret)
{
register int ret;
- char *aaa;
+ char aaa[SIZ];
if (!cret) return -2;
if (!floorname) return -2;
if (floornum < 0) return -2;
- aaa = (char *)malloc(strlen(floorname) + 17);
- if (!aaa) return -1;
-
sprintf(aaa, "EFLR %d|%s", floornum, floorname);
ret = CtdlIPCGenericCommand(ipc, aaa, NULL, 0, NULL, NULL, cret);
- free(aaa);
return ret;
}
-/* IDEN */
-int CtdlIPCIdentifySoftware(CtdlIPC *ipc, int developerid, int clientid, int revision,
- const char *software_name, const char *hostname, char *cret)
+/*
+ * IDEN
+ *
+ * You only need to fill out hostname, the defaults will be used if any of the
+ * other fields are not set properly.
+ */
+int CtdlIPCIdentifySoftware(CtdlIPC *ipc, int developerid, int clientid,
+ int revision, const char *software_name, const char *hostname,
+ char *cret)
{
register int ret;
char *aaa;
- if (developerid < 0) return -2;
- if (clientid < 0) return -2;
- if (revision < 0) return -2;
- if (!software_name) return -2;
+ if (developerid < 0 || clientid < 0 || revision < 0 ||
+ !software_name) {
+ developerid = 8;
+ clientid = 0;
+ revision = REV_LEVEL - 600;
+ software_name = "Citadel (libcitadel)";
+ }
if (!hostname) return -2;
aaa = (char *)malloc(strlen(software_name) + strlen(hostname) + 29);
/* AGUP */
int CtdlIPCAideGetUserParameters(CtdlIPC *ipc, const char *who,
- struct usersupp **uret, char *cret)
+ struct ctdluser **uret, char *cret)
{
register int ret;
char aaa[SIZ];
if (!cret) return -2;
if (!uret) return -2;
- if (!*uret) *uret = (struct usersupp *)calloc(1, sizeof(struct usersupp));
+ if (!*uret) *uret = (struct ctdluser *)calloc(1, sizeof(struct ctdluser));
if (!*uret) return -1;
sprintf(aaa, "AGUP %s", who);
ret = CtdlIPCGenericCommand(ipc, aaa, NULL, 0, NULL, NULL, cret);
if (ret / 100 == 2) {
- extract(uret[0]->fullname, cret, 0);
- extract(uret[0]->password, cret, 1);
+ extract_token(uret[0]->fullname, cret, 0, '|', sizeof uret[0]->fullname);
+ extract_token(uret[0]->password, cret, 1, '|', sizeof uret[0]->password);
uret[0]->flags = extract_int(cret, 2);
uret[0]->timescalled = extract_long(cret, 3);
uret[0]->posted = extract_long(cret, 4);
/* ASUP */
-int CtdlIPCAideSetUserParameters(CtdlIPC *ipc, const struct usersupp *uret, char *cret)
+int CtdlIPCAideSetUserParameters(CtdlIPC *ipc, const struct ctdluser *uret, char *cret)
{
register int ret;
char *aaa;
/* GPEX */
-/* which is 0 = room, 1 = floor, 2 = site */
+/* which is 0 = room, 1 = floor, 2 = site, 3 = default for mailboxes */
/* caller must free the struct ExpirePolicy */
int CtdlIPCGetMessageExpirationPolicy(CtdlIPC *ipc, int which,
struct ExpirePolicy **policy, char *cret)
{
- static char *proto[] = {"room", "floor", "site"};
+ static char *proto[] = {"room", "floor", "site", "mailboxes" };
char aaa[11];
register int ret;
if (!policy) return -2;
if (!*policy) *policy = (struct ExpirePolicy *)calloc(1, sizeof(struct ExpirePolicy));
if (!*policy) return -1;
- if (which < 0 || which > 2) return -2;
+ if (which < 0 || which > 3) return -2;
sprintf(aaa, "GPEX %s", proto[which]);
ret = CtdlIPCGenericCommand(ipc, aaa, NULL, 0, NULL, NULL, cret);
/* SPEX */
-/* which is 0 = room, 1 = floor, 2 = site */
+/* which is 0 = room, 1 = floor, 2 = site, 3 = default for mailboxes */
/* policy is 0 = inherit, 1 = no purge, 2 = by count, 3 = by age (days) */
int CtdlIPCSetMessageExpirationPolicy(CtdlIPC *ipc, int which,
struct ExpirePolicy *policy, char *cret)
{
char aaa[38];
+ char *whichvals[] = { "room", "floor", "site", "mailboxes" };
if (!cret) return -2;
- if (which < 0 || which > 2) return -2;
+ if (which < 0 || which > 3) return -2;
if (!policy) return -2;
if (policy->expire_mode < 0 || policy->expire_mode > 3) return -2;
if (policy->expire_mode >= 2 && policy->expire_value < 1) return -2;
- sprintf(aaa, "SPEX %d|%d|%d", which,
+ sprintf(aaa, "SPEX %s|%d|%d", whichvals[which],
policy->expire_mode, policy->expire_value);
return CtdlIPCGenericCommand(ipc, aaa, NULL, 0, NULL, NULL, cret);
}
/* CONF GET */
-int CtdlGetSystemConfig(CtdlIPC *ipc, char **listing, char *cret)
+int CtdlIPCGetSystemConfig(CtdlIPC *ipc, char **listing, char *cret)
{
size_t bytes;
/* CONF SET */
-int CtdlSetSystemConfig(CtdlIPC *ipc, const char *listing, char *cret)
+int CtdlIPCSetSystemConfig(CtdlIPC *ipc, const char *listing, char *cret)
{
if (!cret) return -2;
if (!listing) return -2;
/* CONF GETSYS */
-int CtdlGetSystemConfigByType(CtdlIPC *ipc, const char *mimetype,
+int CtdlIPCGetSystemConfigByType(CtdlIPC *ipc, const char *mimetype,
char **listing, char *cret)
{
char *aaa;
/* CONF PUTSYS */
-int CtdlSetSystemConfigByType(CtdlIPC *ipc, const char *mimetype,
+int CtdlIPCSetSystemConfigByType(CtdlIPC *ipc, const char *mimetype,
const char *listing, char *cret)
{
char *aaa;
NULL, NULL, cret);
}
-/* MMOD */
-int CtdlIPCModerateMessage(CtdlIPC *ipc, long msgnum, int level, char *cret)
+
+/* GNET */
+int CtdlIPCGetRoomNetworkConfig(CtdlIPC *ipc, char **listing, char *cret)
{
- char aaa[27];
+ size_t bytes;
if (!cret) return -2;
- if (!msgnum) return -2;
+ if (!listing) return -2;
+ if (*listing) return -2;
- sprintf(aaa, "MMOD %ld|%d", msgnum, level);
- return CtdlIPCGenericCommand(ipc, aaa, NULL, 0, NULL, NULL, cret);
+ return CtdlIPCGenericCommand(ipc, "GNET", NULL, 0,
+ listing, &bytes, cret);
+}
+
+
+/* SNET */
+int CtdlIPCSetRoomNetworkConfig(CtdlIPC *ipc, const char *listing, char *cret)
+{
+ if (!cret) return -2;
+ if (!listing) return -2;
+
+ return CtdlIPCGenericCommand(ipc, "SNET", listing, strlen(listing),
+ NULL, NULL, cret);
}
}
/* Pointless flag waving */
#if SSLEAY_VERSION_NUMBER >= 0x0922
- SSL_set_session_id_context(temp_ssl, "Citadel/UX SID", 14);
+ SSL_set_session_id_context(temp_ssl, "Citadel SID", 14);
#endif
- if (!access("/var/run/egd-pool", F_OK))
- RAND_egd("/var/run/egd-pool");
+ if (!access(EGD_POOL, F_OK))
+ RAND_egd(EGD_POOL);
if (!RAND_status()) {
error_printf("PRNG not properly seeded\n");
}
+/* FSCK */
+int CtdlIPCMessageBaseCheck(CtdlIPC *ipc, char **mret, char *cret)
+{
+ size_t size = 0;
+
+ if (!cret) return -2;
+ if (!mret) return -2;
+ if (*mret) return -2;
+
+ return CtdlIPCGenericCommand(ipc, "FSCK", NULL, 0, mret, &size, cret);
+}
+
+
/*
* Not implemented:
*
/* ************************************************************************** */
-inline void CtdlIPC_lock(CtdlIPC *ipc)
+INLINE void CtdlIPC_lock(CtdlIPC *ipc)
{
if (ipc->network_status_cb) ipc->network_status_cb(1);
#ifdef THREADED_CLIENT
}
-inline void CtdlIPC_unlock(CtdlIPC *ipc)
+INLINE void CtdlIPC_unlock(CtdlIPC *ipc)
{
#ifdef THREADED_CLIENT
pthread_mutex_unlock(&(ipc->mutex));
{
size_t length = 0;
size_t linelength;
- char *ret;
+ char *ret = NULL;
char aaa[SIZ];
ret = dest;
if (ret != NULL) {
length = strlen(ret);
- }
- else {
- ret = strdup("");
+ } else {
length = 0;
}
if (!buf) return 0;
if (!cret) return 0;
if (bytes < 1) return 0;
- if (offset < 0) return 0;
CtdlIPC_lock(ipc);
sprintf(aaa, "READ %d|%d", (int)offset, (int)bytes);
*buf = (void *)realloc(*buf, (size_t)(offset + len));
if (*buf) {
/* I know what I'm doing */
- serv_read(ipc, (*buf + offset), len);
+ serv_read(ipc, ((char *)(*buf) + offset), len);
} else {
/* We have to read regardless */
serv_read(ipc, aaa, len);
/* READ */
int CtdlIPCReadDownload(CtdlIPC *ipc, void **buf, size_t bytes, size_t resume,
- void (*progress_gauge_callback)(unsigned long, unsigned long),
+ void (*progress_gauge_callback)
+ (CtdlIPC*, unsigned long, unsigned long),
char *cret)
{
register size_t len;
len = resume;
if (progress_gauge_callback)
- progress_gauge_callback(len, bytes);
+ progress_gauge_callback(ipc, len, bytes);
while (len < bytes) {
register size_t block;
}
len += block;
if (progress_gauge_callback)
- progress_gauge_callback(len, bytes);
+ progress_gauge_callback(ipc, len, bytes);
}
return len;
}
-
/* READ - pipelined */
int CtdlIPCHighSpeedReadDownload(CtdlIPC *ipc, void **buf, size_t bytes,
size_t resume,
- void (*progress_gauge_callback)(unsigned long, unsigned long),
+ void (*progress_gauge_callback)
+ (CtdlIPC*, unsigned long, unsigned long),
char *cret)
{
register size_t len;
len = 0;
CtdlIPC_lock(ipc);
if (progress_gauge_callback)
- progress_gauge_callback(len, bytes);
+ progress_gauge_callback(ipc, len, bytes);
/* How many calls will be in the pipeline? */
calls = (bytes - resume) / 4096;
else {
len = extract_long(&aaa[4], 0);
/* I know what I'm doing */
- serv_read(ipc, ((*buf) + (i * 4096)), len);
+ serv_read(ipc, ((char *)(*buf) + (i * 4096)), len);
}
if (progress_gauge_callback)
- progress_gauge_callback(i * 4096 + len, bytes);
+ progress_gauge_callback(ipc, i * 4096 + len, bytes);
}
CtdlIPC_unlock(ipc);
return len;
/* WRIT */
int CtdlIPCWriteUpload(CtdlIPC *ipc, const char *path,
- void (*progress_gauge_callback)(unsigned long, unsigned long),
+ void (*progress_gauge_callback)
+ (CtdlIPC*, unsigned long, unsigned long),
char *cret)
{
register int ret = -1;
rewind(fd);
if (progress_gauge_callback)
- progress_gauge_callback(0, bytes);
+ progress_gauge_callback(ipc, 0, bytes);
while (offset < bytes) {
register size_t to_write;
serv_write(ipc, buf, to_write);
offset += to_write;
if (progress_gauge_callback)
- progress_gauge_callback(offset, bytes);
+ progress_gauge_callback(ipc, offset, bytes);
/* Detect short reads and back up if needed */
/* offset will never be negative anyway */
fseek(fd, (signed)offset, SEEK_SET);
}
}
if (progress_gauge_callback)
- progress_gauge_callback(1, 1);
+ progress_gauge_callback(ipc, 1, 1);
return (!ferror(fd) ? ret : -2);
}
while (1) {
CtdlIPC_getline(ipc, proto_response);
if (proto_response[3] == '*')
- express_msgs = 1;
+ instant_msgs = 1;
ret = atoi(proto_response);
strcpy(proto_response, &proto_response[4]);
switch (ret / 100) {
}
if (connect(s, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
+ close(s);
return -1;
}
}
if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ close(s);
return -1;
}
while (len < bytes) {
rlen = read(ipc->sock, &buf[len], bytes - len);
if (rlen < 1) {
- connection_died(ipc);
+ connection_died(ipc, 0);
return;
}
len += rlen;
retval = write(ipc->sock, &buf[bytes_written],
nbytes - bytes_written);
if (retval < 1) {
- connection_died(ipc);
+ connection_died(ipc, 0);
return;
}
bytes_written += retval;
serv_read(ipc, &buf[len], bytes - len);
return;
}
- error_printf("SSL_read in serv_read:\n");
- ERR_print_errors_fp(stderr);
- connection_died(NULL);
+ error_printf("SSL_read in serv_read: %s\n",
+ ERR_reason_error_string(ERR_peek_error()));
+ connection_died(ipc, 1);
return;
}
len += rlen;
nbytes - bytes_written);
return;
}
- error_printf("SSL_write in serv_write:\n");
- ERR_print_errors_fp(stderr);
- connection_died(NULL);
+ error_printf("SSL_write in serv_write: %s\n",
+ ERR_reason_error_string(ERR_peek_error()));
+ connection_died(ipc, 1);
return;
}
bytes_written += retval;
}
/* Get started */
+ a = 0;
ssl_ctx = NULL;
dh = NULL;
SSL_load_error_strings();
/*
* input string from socket - implemented in terms of serv_read()
*/
-void CtdlIPC_getline(CtdlIPC* ipc, char *buf)
+static void CtdlIPC_getline(CtdlIPC* ipc, char *buf)
{
int i;
while (buf[i] != '\n')
serv_read(ipc, &buf[i], 1);
- /* Strip the trailing newline.
- */
- buf[i] = 0;
+ /* Strip the trailing newline (and carriage return, if present) */
+ if (buf[i] == 10) buf[i--] = 0;
+ if (buf[i] == 13) buf[i--] = 0;
}
+void CtdlIPC_chat_recv(CtdlIPC* ipc, char* buf)
+{
+ CtdlIPC_getline(ipc, buf);
+}
/*
* send line to server - implemented in terms of serv_write()
*/
-void CtdlIPC_putline(CtdlIPC *ipc, const char *buf)
+static void CtdlIPC_putline(CtdlIPC *ipc, const char *buf)
{
- /* error_printf("< %s\n", buf); */
- serv_write(ipc, buf, strlen(buf));
- serv_write(ipc, "\n", 1);
+ char *cmd = NULL;
+ int len;
+
+ len = strlen(buf);
+ cmd = malloc(len + 2);
+ if (!cmd) {
+ /* This requires no extra memory */
+ serv_write(ipc, buf, len);
+ serv_write(ipc, "\n", 1);
+ } else {
+ /* This is network-optimized */
+ strncpy(cmd, buf, len);
+ strcpy(cmd + len, "\n");
+ serv_write(ipc, cmd, len + 1);
+ free(cmd);
+ }
ipc->last_command_sent = time(NULL);
}
+void CtdlIPC_chat_send(CtdlIPC* ipc, const char* buf)
+{
+ CtdlIPC_putline(ipc, buf);
+}
+
/*
* attach to server
char cithost[SIZ];
char citport[SIZ];
char sockpath[SIZ];
+ CtdlIPC* ipc;
- CtdlIPC *ipc = ialloc(CtdlIPC);
+ ipc = ialloc(CtdlIPC);
if (!ipc) {
return 0;
}
strcpy(cithost, DEFAULT_HOST); /* default host */
strcpy(citport, DEFAULT_PORT); /* default port */
+ /* Allow caller to supply our values (Windows) */
+ if (hostbuf && strlen(hostbuf) > 0)
+ strcpy(cithost, hostbuf);
+ if (portbuf && strlen(portbuf) > 0)
+ strcpy(citport, portbuf);
+
+ /* Read host/port from command line if present */
for (a = 0; a < argc; ++a) {
if (a == 0) {
/* do nothing */
/* If we're using a unix domain socket we can do a bunch of stuff */
if (!strcmp(cithost, UDS)) {
- snprintf(sockpath, sizeof sockpath, BBSDIR "/citadel.socket");
+ if (!strcasecmp(citport, DEFAULT_PORT)) {
+ snprintf(sockpath, sizeof sockpath, "%s%s",
+#ifndef HAVE_RUN_DIR
+ CTDLDIR
+#else
+ RUN_DIR
+#endif
+ , "/citadel.socket");
+ }
+ else {
+ snprintf(sockpath, sizeof sockpath, "%s%s",
+ citport,
+#ifndef HAVE_RUN_DIR
+ CTDLDIR
+#else
+ RUN_DIR
+#endif
+ "/citadel.socket");
+ }
ipc->sock = uds_connectsock(&(ipc->isLocal), sockpath);
if (ipc->sock == -1) {
ifree(ipc);
return ipc;
}
+
+/*
+ * Disconnect and delete the IPC class (destructor)
+ */
+void CtdlIPC_delete(CtdlIPC* ipc)
+{
+#ifdef HAVE_OPENSSL
+ if (ipc->ssl) {
+ SSL_shutdown(ipc->ssl);
+ SSL_free(ipc->ssl);
+ ipc->ssl = NULL;
+ }
+#endif
+ if (ipc->sock > -1) {
+ shutdown(ipc->sock, 2); /* Close it up */
+ ipc->sock = -1;
+ }
+ ifree(ipc);
+}
+
+
+/*
+ * Disconnect and delete the IPC class (destructor)
+ * Also NULLs out the pointer
+ */
+void CtdlIPC_delete_ptr(CtdlIPC** pipc)
+{
+ CtdlIPC_delete(*pipc);
+ *pipc = NULL;
+}
+
+
/*
* return the file descriptor of the server socket so we can select() on it.
*