/* $Id$ */
-#define UDS "_UDS_"
-#ifdef __CYGWIN__
-#define DEFAULT_HOST "localhost"
-#else
-#define DEFAULT_HOST UDS
-#endif
-#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;
}
/* 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];
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]);
/* 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) {
extract_token(buf, listing, 0, '\n');
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.bbs_city,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;
}
}
/* 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);
/* 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;
/* 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;
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);
+
+ 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;
/* 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;
/* 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;
developerid = 8;
clientid = 0;
revision = REV_LEVEL - 600;
- software_name = "Citadel/UX (libcitadel)";
+ software_name = "Citadel (libcitadel)";
}
if (!hostname) return -2;
/* 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);
/* 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" };
+ 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;
}
+/* GNET */
+int CtdlIPCGetRoomNetworkConfig(CtdlIPC *ipc, char **listing, char *cret)
+{
+ size_t bytes;
+
+ if (!cret) return -2;
+ if (!listing) return -2;
+ if (*listing) return -2;
+
+ 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);
+}
+
+
/* REQT */
int CtdlIPCRequestClientLogout(CtdlIPC *ipc, int session, char *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))
/* ************************************************************************** */
-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));
/* 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;
serv_read(ipc, ((*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) {
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(ipc);
+ 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(ipc);
+ error_printf("SSL_write in serv_write: %s\n",
+ ERR_reason_error_string(ERR_peek_error()));
+ connection_died(ipc, 1);
return;
}
bytes_written += retval;
/*
* 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;
if (buf[i] == 13) buf[i--] = 0;
}
+void CtdlIPC_chat_recv(CtdlIPC* ipc, char* buf)
+{
+ return 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));
ipc->last_command_sent = time(NULL);
}
+void CtdlIPC_chat_send(CtdlIPC* ipc, const char* buf)
+{
+ return 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;
}
/* 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",
+ BBSDIR, "/citadel.socket");
+ }
+ else {
+ snprintf(sockpath, sizeof sockpath, "%s%s",
+ citport, "/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.
*