15 #include <sys/types.h>
19 #ifdef THREADED_CLIENT
23 #include "citadel_ipc.h"
24 #include "client_crypto.h"
27 #ifdef THREADED_CLIENT
28 pthread_mutex_t rwlock;
30 extern char express_msgs;
32 static volatile int download_in_progress = 0; /* download file open */
33 static volatile int upload_in_progress = 0; /* upload file open */
34 /* static volatile int serv_sock; /* Socket on which we talk to server */
38 * Does nothing. The server should always return 200.
56 * Does nothing interesting. The server should always return 200
57 * along with your string.
59 int CtdlIPCEcho(const char *arg, char *cret)
67 aaa = (char *)malloc(strlen(arg) + 6);
70 sprintf(aaa, "ECHO %s", arg);
71 ret = CtdlIPCGenericCommand(aaa, NULL, 0, NULL, NULL, cret);
78 * Asks the server to close the connecction.
79 * Should always return 200.
96 * Asks the server to logout. Should always return 200, even if no user
97 * was logged in. The user will not be logged in after this!
99 int CtdlIPCLogout(void)
114 * First stage of authentication - pass the username. Returns 300 if the
115 * username is able to log in, with the username correctly spelled in cret.
116 * Returns various 500 error codes if the user doesn't exist, etc.
118 int CtdlIPCTryLogin(const char *username, char *cret)
123 if (!username) return -2;
124 if (!cret) return -2;
126 aaa = (char *)malloc(strlen(username) + 6);
129 sprintf(aaa, "USER %s", username);
130 ret = CtdlIPCGenericCommand(aaa, NULL, 0, NULL, NULL, cret);
137 * Second stage of authentication - provide password. The server returns
138 * 200 and several arguments in cret relating to the user's account.
140 int CtdlIPCTryPassword(const char *passwd, char *cret)
145 if (!passwd) return -2;
146 if (!cret) return -2;
148 aaa = (char *)malloc(strlen(passwd) + 6);
151 sprintf(aaa, "PASS %s", passwd);
152 ret = CtdlIPCGenericCommand(aaa, NULL, 0, NULL, NULL, cret);
159 * Create a new user. This returns 200 plus the same arguments as TryPassword
160 * unless there was a problem creating the account.
162 int CtdlIPCCreateUser(const char *username, char *cret)
167 if (!username) return -2;
168 if (!cret) return -2;
170 aaa = (char *)malloc(strlen(username) + 6);
173 sprintf(aaa, "NEWU %s", username);
174 ret = CtdlIPCGenericCommand(aaa, NULL, 0, NULL, NULL, cret);
181 * Changes the user's password. Returns 200 if changed, errors otherwise.
183 int CtdlIPCChangePassword(const char *passwd, char *cret)
188 if (!passwd) return -2;
189 if (!cret) return -2;
191 aaa = (char *)malloc(strlen(passwd) + 6);
194 sprintf(aaa, "SETP %s", passwd);
195 ret = CtdlIPCGenericCommand(aaa, NULL, 0, NULL, NULL, cret);
202 /* Caller must free the march list */
203 /* which is 0 = LRMS, 1 = LKRN, 2 = LKRO, 3 = LKRA, 4 = LZRM */
204 /* floor is -1 for all, or floornum */
205 int CtdlIPCKnownRooms(int which, int floor, char *cret, struct march **listing)
208 struct march *march = NULL;
209 static char *proto[] = {"LRMS", "LKRN", "LKRO", "LKRA", "LZRM" };
214 if (!listing) return -2;
215 if (*listing) return -2; /* Free the listing first */
216 if (!cret) return -2;
217 if (which < 0 || which > 4) return -2;
218 if (floor < -1) return -2; /* Can't validate upper bound, sorry */
220 sprintf(aaa, "%s %d", proto[which], floor);
221 ret = CtdlIPCGenericCommand(aaa, NULL, 0, &bbb, &bbbsize, cret);
222 if (ret / 100 == 1) {
225 while (strlen(bbb)) {
228 extract_token(aaa, bbb, 0, '\n');
230 memmove(aaa, bbb + a + 1, strlen(bbb) - a - 1);
231 mptr = (struct march *) malloc(sizeof (struct march));
234 extract(mptr->march_name, aaa, 0);
235 mptr->march_floor = (char) extract_int(aaa, 2);
236 mptr->march_order = (char) extract_int(aaa, 3);
243 while (mptr2->next != NULL)
256 /* Caller must free the struct usersupp; caller may pass an existing one */
257 int CtdlIPCGetConfig(struct usersupp **uret, char *cret)
261 if (!cret) return -2;
262 if (!uret) return -2;
263 if (!*uret) *uret = (struct usersupp *)calloc(1, sizeof (struct usersupp));
264 if (!*uret) return -1;
266 ret = CtdlIPCGenericCommand("GETU", NULL, 0, NULL, NULL, cret);
267 if (ret / 100 == 2) {
268 uret[0]->USscreenwidth = extract_int(cret, 0);
269 uret[0]->USscreenheight = extract_int(cret, 1);
270 uret[0]->flags = extract_int(cret, 2);
277 int CtdlIPCSetConfig(struct usersupp *uret, char *cret)
281 if (!uret) return -2;
282 if (!cret) return -2;
284 sprintf(aaa, "SETU %d|%d|%d",
285 uret->USscreenwidth, uret->USscreenheight,
287 return CtdlIPCGenericCommand(aaa, NULL, 0, NULL, NULL, cret);
292 int CtdlIPCGotoRoom(const char *room, const char *passwd,
293 struct ctdlipcroom **rret, char *cret)
298 if (!cret) return -2;
299 if (!rret) return -2;
300 if (!*rret) *rret = (struct ctdlipcroom *)calloc(1, sizeof (struct ctdlipcroom));
301 if (!*rret) return -1;
304 aaa = (char *)malloc(strlen(room) + strlen(passwd) + 7);
309 sprintf(aaa, "GOTO %s|%s", room, passwd);
311 aaa = (char *)malloc(strlen(room) + 6);
316 sprintf(aaa, "GOTO %s", room);
318 ret = CtdlIPCGenericCommand(aaa, NULL, 0, NULL, NULL, cret);
319 if (ret / 100 == 2) {
320 extract(rret[0]->RRname, cret, 0);
321 rret[0]->RRunread = extract_long(cret, 1);
322 rret[0]->RRtotal = extract_long(cret, 2);
323 rret[0]->RRinfoupdated = extract_int(cret, 3);
324 rret[0]->RRflags = extract_int(cret, 4);
325 rret[0]->RRhighest = extract_long(cret, 5);
326 rret[0]->RRlastread = extract_long(cret, 6);
327 rret[0]->RRismailbox = extract_int(cret, 7);
328 rret[0]->RRaide = extract_int(cret, 8);
329 rret[0]->RRnewmail = extract_long(cret, 9);
330 rret[0]->RRfloor = extract_int(cret, 10);
339 /* which is 0 = all, 1 = old, 2 = new, 3 = last, 4 = first, 5 = gt, 6 = lt */
340 /* whicharg is number of messages, applies to last, first, gt, lt */
341 int CtdlIPCGetMessages(int which, int whicharg, const char *template,
342 long **mret, char *cret)
345 register long count = 0;
346 static char *proto[] =
347 { "ALL", "OLD", "NEW", "LAST", "FIRST", "GT", "LT" };
352 if (!cret) return -2;
353 if (!mret) return -2;
354 if (*mret) return -2;
355 if (which < 0 || which > 6) return -2;
358 sprintf(aaa, "MSGS %s||%d", proto[which],
361 sprintf(aaa, "MSGS %s|%d|%d", proto[which], whicharg,
363 if (template) count = strlen(template);
364 ret = CtdlIPCGenericCommand(aaa, template, count, &bbb, &bbbsize, cret);
366 while (strlen(bbb)) {
369 extract_token(aaa, bbb, 0, '\n');
371 memmove(aaa, bbb + a + 1, strlen(bbb) - a - 1);
372 *mret = (long *)realloc(mret, (count + 1) * sizeof (long));
374 *mret[count++] = atol(aaa);
382 int CtdlIPCGetSingleMessage(long msgnum, int headers, int as_mime,
383 struct ctdlipcmessage **mret, char *cret)
390 if (!cret) return -1;
391 if (!mret) return -1;
392 if (!*mret) *mret = (struct ctdlipcmessage *)calloc(1, sizeof (struct ctdlipcmessage));
393 if (!*mret) return -1;
394 if (!msgnum) return -1;
396 sprintf(aaa, "MSG%c %ld|%d", as_mime ? '2' : '0', msgnum, headers);
397 ret = CtdlIPCGenericCommand(aaa, NULL, 0, &bbb, &bbbsize, cret);
398 if (ret / 100 == 1) {
400 while (strlen(bbb) > 4 && bbb[4] == '=') {
403 extract_token(aaa, bbb, 0, '\n');
405 memmove(aaa, bbb + a + 1, strlen(bbb) - a - 1);
407 if (!strncasecmp(aaa, "nhdr=yes", 8))
409 else if (!strncasecmp(aaa, "from=", 5))
410 strcpy(mret[0]->author, &aaa[5]);
411 else if (!strncasecmp(aaa, "type=", 5))
412 mret[0]->type = atoi(&aaa[5]);
413 else if (!strncasecmp(aaa, "msgn=", 5))
414 strcpy(mret[0]->msgid, &aaa[5]);
415 else if (!strncasecmp(aaa, "subj=", 5))
416 strcpy(mret[0]->subject, &aaa[5]);
417 else if (!strncasecmp(aaa, "rfca=", 5))
418 strcpy(mret[0]->email, &aaa[5]);
419 else if (!strncasecmp(aaa, "hnod=", 5))
420 strcpy(mret[0]->hnod, &aaa[5]);
421 else if (!strncasecmp(aaa, "room=", 5))
422 strcpy(mret[0]->room, &aaa[5]);
423 else if (!strncasecmp(aaa, "node=", 5))
424 strcpy(mret[0]->node, &aaa[5]);
425 else if (!strncasecmp(aaa, "rcpt=", 5))
426 strcpy(mret[0]->recipient, &aaa[5]);
427 else if (!strncasecmp(aaa, "time=", 5))
428 mret[0]->time = atol(&aaa[5]);
429 else if (!strncasecmp(aaa, "part=", 5)) {
430 struct parts *ptr, *chain;
432 ptr = (struct parts *)calloc(1, sizeof (struct parts));
434 extract(ptr->name, &aaa[5], 0);
435 extract(ptr->filename, &aaa[5], 1);
436 extract(ptr->number, &aaa[5], 2);
437 extract(ptr->disposition, &aaa[5], 3);
438 extract(ptr->mimetype, &aaa[5], 4);
439 ptr->length = extract_long(&aaa[5], 5);
440 if (!mret[0]->attachments)
441 mret[0]->attachments = ptr;
443 chain = mret[0]->attachments;
453 bbb = (char *)realloc(bbb, strlen(bbb) + 1);
464 int CtdlIPCWhoKnowsRoom(char **listing, char *cret)
469 if (!cret) return -2;
470 if (!listing) return -2;
471 if (*listing) return -2;
473 ret = CtdlIPCGenericCommand("WHOK", NULL, 0, listing, &bytes, cret);
479 int CtdlIPCServerInfo(char **listing, char *cret)
484 if (!cret) return -2;
485 if (!listing) return -2;
486 if (*listing) return -2;
488 ret = CtdlIPCGenericCommand("INFO", NULL, 0, listing, &bytes, cret);
494 int CtdlIPCReadDirectory(char **listing, char *cret)
499 if (!cret) return -2;
500 if (!listing) return -2;
501 if (*listing) return -2;
503 ret = CtdlIPCGenericCommand("RDIR", NULL, 0, listing, &bytes, cret);
509 * Set last-read pointer in this room to msgnum, or 0 for HIGHEST.
511 int CtdlIPCSetLastRead(long msgnum, char *cret)
516 if (!cret) return -2;
519 sprintf(aaa, "SLRP %ld", msgnum);
521 sprintf(aaa, "SLRP HIGHEST");
522 ret = CtdlIPCGenericCommand(aaa, NULL, 0, NULL, NULL, cret);
528 int CtdlIPCInviteUserToRoom(const char *username, char *cret)
533 if (!cret) return -2;
534 if (!username) return -2;
536 aaa = (char *)malloc(strlen(username) + 6);
539 sprintf(aaa, "INVT %s", username);
540 ret = CtdlIPCGenericCommand(aaa, NULL, 0, NULL, NULL, cret);
547 int CtdlIPCKickoutUserFromRoom(const char *username, char *cret)
552 if (!cret) return -1;
553 if (!username) return -1;
555 aaa = (char *)malloc(strlen(username) + 6);
557 sprintf(aaa, "KICK %s", username);
558 ret = CtdlIPCGenericCommand(aaa, NULL, 0, NULL, NULL, cret);
565 int CtdlIPCGetRoomAttributes(struct quickroom **qret, char *cret)
569 if (!cret) return -2;
570 if (!qret) return -2;
571 if (!*qret) *qret = (struct quickroom *)calloc(1, sizeof (struct quickroom));
572 if (!*qret) return -1;
574 ret = CtdlIPCGenericCommand("GETR", NULL, 0, NULL, NULL, cret);
575 if (ret / 100 == 2) {
576 extract(qret[0]->QRname, cret, 0);
577 extract(qret[0]->QRpasswd, cret, 1);
578 extract(qret[0]->QRdirname, cret, 2);
579 qret[0]->QRflags = extract_int(cret, 3);
580 qret[0]->QRfloor = extract_int(cret, 4);
581 qret[0]->QRorder = extract_int(cret, 5);
588 /* set forget to kick all users out of room */
589 int CtdlIPCSetRoomAttributes(int forget, struct quickroom *qret, char *cret)
594 if (!cret) return -2;
595 if (!qret) return -2;
597 aaa = (char *)malloc(strlen(qret->QRname) + strlen(qret->QRpasswd) +
598 strlen(qret->QRdirname) + 52);
601 sprintf(aaa, "SETR %s|%s|%s|%d|%d|%d|%d",
602 qret->QRname, qret->QRpasswd, qret->QRdirname,
603 qret->QRflags, forget, qret->QRfloor, qret->QRorder);
604 ret = CtdlIPCGenericCommand(aaa, NULL, 0, NULL, NULL, cret);
611 int CtdlIPCGetRoomAide(char *cret)
613 if (!cret) return -1;
615 return CtdlIPCGenericCommand("GETA", NULL, 0, NULL, NULL, cret);
620 int CtdlIPCSetRoomAide(const char *username, char *cret)
625 if (!cret) return -2;
626 if (!username) return -2;
628 aaa = (char *)malloc(strlen(username) + 6);
631 sprintf(aaa, "SETA %s", username);
632 ret = CtdlIPCGenericCommand(aaa, NULL, 0, NULL, NULL, cret);
639 int CtdlIPCPostMessage(int flag, const struct ctdlipcmessage *mr, char *cret)
644 if (!cret) return -2;
647 aaa = (char *)malloc(strlen(mr->recipient) + strlen(mr->author) + 40);
650 sprintf(aaa, "ENT0 %d|%s|%d|%d|%s", flag, mr->recipient, mr->anonymous,
651 mr->type, mr->author);
652 ret = CtdlIPCGenericCommand(aaa, mr->text, strlen(mr->text), NULL,
660 int CtdlIPCRoomInfo(char **iret, char *cret)
664 if (!cret) return -2;
665 if (!iret) return -2;
666 if (*iret) return -2;
668 return CtdlIPCGenericCommand("RINF", NULL, 0, iret, &bytes, cret);
673 int CtdlIPCDeleteMessage(long msgnum, char *cret)
677 if (!cret) return -2;
678 if (!msgnum) return -2;
680 sprintf(aaa, "DELE %ld", msgnum);
681 return CtdlIPCGenericCommand(aaa, NULL, 0, NULL, NULL, cret);
686 int CtdlIPCMoveMessage(int copy, long msgnum, const char *destroom, char *cret)
691 if (!cret) return -2;
692 if (!destroom) return -2;
693 if (!msgnum) return -2;
695 aaa = (char *)malloc(strlen(destroom) + 28);
698 sprintf(aaa, "MOVE %ld|%s|%d", msgnum, destroom, copy);
699 ret = CtdlIPCGenericCommand(aaa, NULL, 0, NULL, NULL, cret);
706 int CtdlIPCDeleteRoom(int for_real, char *cret)
710 if (!cret) return -2;
712 sprintf(aaa, "KILL %d", for_real);
713 return CtdlIPCGenericCommand(aaa, NULL, 0, NULL, NULL, cret);
718 int CtdlIPCCreateRoom(int for_real, const char *roomname, int type,
719 const char *password, int floor, char *cret)
724 if (!cret) return -2;
725 if (!roomname) return -2;
728 aaa = (char *)malloc(strlen(roomname) + strlen(password) + 40);
730 sprintf(aaa, "CRE8 %d|%s|%d|%s|%d", for_real, roomname, type,
733 aaa = (char *)malloc(strlen(roomname) + 40);
735 sprintf(aaa, "CRE8 %d|%s|%d||%d", for_real, roomname, type,
738 ret = CtdlIPCGenericCommand(aaa, NULL, 0, NULL, NULL, cret);
745 int CtdlIPCForgetRoom(char *cret)
747 if (!cret) return -2;
749 return CtdlIPCGenericCommand("FORG", NULL, 0, NULL, NULL, cret);
754 int CtdlIPCSystemMessage(const char *message, char **mret, char *cret)
760 if (!cret) return -2;
761 if (!mret) return -2;
762 if (*mret) return -2;
763 if (!message) return -2;
765 aaa = (char *)malloc(strlen(message) + 6);
768 sprintf(aaa, "MESG %s", message);
769 ret = CtdlIPCGenericCommand(aaa, NULL, 0, mret, &bytes, cret);
776 int CtdlIPCNextUnvalidatedUser(char *cret)
778 if (!cret) return -2;
780 return CtdlIPCGenericCommand("GNUR", NULL, 0, NULL, NULL, cret);
785 int CtdlIPCGetUserRegistration(const char *username, char **rret, char *cret)
791 if (!cret) return -2;
792 if (!rret) return -2;
793 if (*rret) return -2;
796 aaa = (char *)malloc(strlen(username) + 6);
798 aaa = (char *)malloc(12);
802 sprintf(aaa, "GREG %s", username);
804 sprintf(aaa, "GREG _SELF_");
805 ret = CtdlIPCGenericCommand(aaa, NULL, 0, rret, &bytes, cret);
812 int CtdlIPCValidateUser(const char *username, int axlevel, char *cret)
817 if (!cret) return -2;
818 if (!username) return -2;
819 if (axlevel < 0 || axlevel > 7) return -2;
821 aaa = (char *)malloc(strlen(username) + 17);
824 sprintf(aaa, "VALI %s|%d", username, axlevel);
825 ret = CtdlIPCGenericCommand(aaa, NULL, 0, NULL, NULL, cret);
832 int CtdlIPCSetRoomInfo(int for_real, const char *info, char *cret)
836 if (!cret) return -1;
837 if (!info) return -1;
839 sprintf(aaa, "EINF %d", for_real);
840 return CtdlIPCGenericCommand(aaa, NULL, 0, NULL, NULL, cret);
845 int CtdlIPCUserListing(char **listing, char *cret)
849 if (!cret) return -1;
850 if (!listing) return -1;
851 if (*listing) return -1;
853 return CtdlIPCGenericCommand("LIST", NULL, 0, listing, &bytes, cret);
858 int CtdlIPCSetRegistration(const char *info, char *cret)
860 if (!cret) return -1;
861 if (!info) return -1;
863 return CtdlIPCGenericCommand("REGI", info, strlen(info),
869 int CtdlIPCMiscCheck(struct ctdlipcmisc *chek, char *cret)
873 if (!cret) return -1;
874 if (!chek) return -1;
876 ret = CtdlIPCGenericCommand("CHEK", NULL, 0, NULL, NULL, cret);
877 if (ret / 100 == 2) {
878 chek->newmail = extract_long(cret, 0);
879 chek->needregis = extract_int(cret, 1);
880 chek->needvalid = extract_int(cret, 2);
887 int CtdlIPCDeleteFile(const char *filename, char *cret)
892 if (!cret) return -2;
893 if (!filename) return -2;
895 aaa = (char *)malloc(strlen(filename) + 6);
898 sprintf(aaa, "DELF %s", filename);
899 ret = CtdlIPCGenericCommand(aaa, NULL, 0, NULL, NULL, cret);
906 int CtdlIPCMoveFile(const char *filename, const char *destroom, char *cret)
911 if (!cret) return -2;
912 if (!filename) return -2;
913 if (!destroom) return -2;
915 aaa = (char *)malloc(strlen(filename) + strlen(destroom) + 7);
918 sprintf(aaa, "MOVF %s|%s", filename, destroom);
919 ret = CtdlIPCGenericCommand(aaa, NULL, 0, NULL, NULL, cret);
926 int CtdlIPCNetSendFile(const char *filename, const char *destnode, char *cret)
931 if (!cret) return -2;
932 if (!filename) return -2;
933 if (!destnode) return -2;
935 aaa = (char *)malloc(strlen(filename) + strlen(destnode) + 7);
938 sprintf(aaa, "NETF %s|%s", filename, destnode);
939 ret = CtdlIPCGenericCommand(aaa, NULL, 0, NULL, NULL, cret);
946 int CtdlIPCOnlineUsers(char **listing, time_t *stamp, char *cret)
951 if (!cret) return -1;
952 if (!listing) return -1;
953 if (*listing) return -1;
955 *stamp = CtdlIPCServerTime(cret);
958 ret = CtdlIPCGenericCommand("RWHO", NULL, 0, listing, &bytes, cret);
964 int CtdlIPCFileDownload(const char *filename, void **buf, char *cret)
972 if (!cret) return -2;
973 if (!filename) return -2;
976 if (download_in_progress) return -2;
978 aaa = (char *)malloc(strlen(filename) + 6);
981 sprintf(aaa, "OPEN %s", filename);
982 ret = CtdlIPCGenericCommand(aaa, NULL, 0, NULL, NULL, cret);
984 /* FIXME: Possible race condition */
985 if (ret / 100 == 2) {
986 download_in_progress = 1;
987 bytes = extract_long(cret, 0);
988 last_mod = extract_int(cret, 1);
989 extract(mimetype, cret, 2);
990 ret = CtdlIPCReadDownload(buf, bytes, cret);
991 ret = CtdlIPCEndDownload(cret);
993 sprintf(cret, "%d|%ld|%s|%s", bytes, last_mod,
1001 int CtdlIPCAttachmentDownload(long msgnum, const char *part, void **buf,
1011 if (!cret) return -2;
1012 if (!buf) return -2;
1013 if (*buf) return -2;
1014 if (!part) return -2;
1015 if (!msgnum) return -2;
1016 if (download_in_progress) return -2;
1018 aaa = (char *)malloc(strlen(part) + 17);
1019 if (!aaa) return -1;
1021 sprintf(aaa, "OPNA %ld|%s", msgnum, part);
1022 ret = CtdlIPCGenericCommand(aaa, NULL, 0, NULL, NULL, cret);
1024 /* FIXME: Possible race condition */
1025 if (ret / 100 == 2) {
1026 download_in_progress = 1;
1027 bytes = extract_long(cret, 0);
1028 last_mod = extract_int(cret, 1);
1029 extract(mimetype, cret, 2);
1030 ret = CtdlIPCReadDownload(buf, bytes, cret);
1031 ret = CtdlIPCEndDownload(cret);
1033 sprintf(cret, "%d|%ld|%s|%s", bytes, last_mod,
1034 filename, mimetype);
1041 int CtdlIPCImageDownload(const char *filename, void **buf, char *cret)
1049 if (!cret) return -1;
1050 if (!buf) return -1;
1051 if (*buf) return -1;
1052 if (!filename) return -1;
1053 if (download_in_progress) return -1;
1055 aaa = (char *)malloc(strlen(filename) + 6);
1056 if (!aaa) return -1;
1058 sprintf(aaa, "OIMG %s", filename);
1059 ret = CtdlIPCGenericCommand(aaa, NULL, 0, NULL, NULL, cret);
1061 /* FIXME: Possible race condition */
1062 if (ret / 100 == 2) {
1063 download_in_progress = 1;
1064 bytes = extract_long(cret, 0);
1065 last_mod = extract_int(cret, 1);
1066 extract(mimetype, cret, 2);
1067 ret = CtdlIPCReadDownload(buf, bytes, cret);
1068 ret = CtdlIPCEndDownload(cret);
1070 sprintf(cret, "%d|%ld|%s|%s", bytes, last_mod,
1071 filename, mimetype);
1078 int CtdlIPCFileUpload(const char *filename, const char *comment, void *buf,
1079 size_t bytes, char *cret)
1084 if (!cret) return -1;
1085 if (!filename) return -1;
1086 if (!comment) return -1;
1087 if (upload_in_progress) return -1;
1089 aaa = (char *)malloc(strlen(filename) + strlen(comment) + 7);
1090 if (!aaa) return -1;
1092 sprintf(aaa, "UOPN %s|%s", filename, comment);
1093 ret = CtdlIPCGenericCommand(aaa, NULL, 0, NULL, NULL, cret);
1095 /* FIXME: Possible race condition */
1097 upload_in_progress = 1;
1098 ret = CtdlIPCWriteUpload(buf, bytes, cret);
1099 ret = CtdlIPCEndUpload(cret);
1105 int CtdlIPCImageUpload(int for_real, const char *filename, size_t bytes,
1111 if (!cret) return -1;
1112 if (!filename) return -1;
1113 if (upload_in_progress) return -1;
1115 aaa = (char *)malloc(strlen(filename) + 17);
1116 if (!aaa) return -1;
1118 sprintf(aaa, "UIMG %d|%s", for_real, filename);
1119 ret = CtdlIPCGenericCommand(aaa, NULL, 0, NULL, NULL, cret);
1121 /* FIXME: Possible race condition */
1123 upload_in_progress = 1;
1129 int CtdlIPCQueryUsername(const char *username, char *cret)
1134 if (!cret) return -2;
1135 if (!username) return -2;
1137 aaa = (char *)malloc(strlen(username) + 6);
1138 if (!aaa) return -1;
1140 sprintf(aaa, "QUSR %s", username);
1141 ret = CtdlIPCGenericCommand(aaa, NULL, 0, NULL, NULL, cret);
1148 int CtdlIPCFloorListing(char **listing, char *cret)
1152 if (!cret) return -2;
1153 if (!listing) return -2;
1154 if (*listing) return -2;
1156 return CtdlIPCGenericCommand("LFLR", NULL, 0, listing, &bytes, cret);
1161 int CtdlIPCCreateFloor(int for_real, const char *name, char *cret)
1166 if (!cret) return -2;
1167 if (!name) return -2;
1169 aaa = (char *)malloc(strlen(name) + 17);
1170 if (!aaa) return -1;
1172 sprintf(aaa, "CFLR %s|%d", name, for_real);
1173 ret = CtdlIPCGenericCommand(aaa, NULL, 0, NULL, NULL, cret);
1180 int CtdlIPCDeleteFloor(int for_real, int floornum, char *cret)
1184 if (!cret) return -1;
1185 if (floornum < 0) return -1;
1187 sprintf(aaa, "KFLR %d|%d", floornum, for_real);
1188 return CtdlIPCGenericCommand(aaa, NULL, 0, NULL, NULL, cret);
1193 int CtdlIPCEditFloor(int floornum, const char *floorname, char *cret)
1198 if (!cret) return -2;
1199 if (!floorname) return -2;
1200 if (floornum < 0) return -2;
1202 aaa = (char *)malloc(strlen(floorname) + 17);
1203 if (!aaa) return -1;
1205 sprintf(aaa, "EFLR %d|%s", floornum, floorname);
1206 ret = CtdlIPCGenericCommand(aaa, NULL, 0, NULL, NULL, cret);
1213 int CtdlIPCIdentifySoftware(int developerid, int clientid, int revision,
1214 const char *software_name, const char *hostname, char *cret)
1219 if (developerid < 0) return -2;
1220 if (clientid < 0) return -2;
1221 if (revision < 0) return -2;
1222 if (!software_name) return -2;
1223 if (!hostname) return -2;
1225 aaa = (char *)malloc(strlen(software_name) + strlen(hostname) + 29);
1226 if (!aaa) return -1;
1228 sprintf(aaa, "IDEN %d|%d|%d|%s|%s", developerid, clientid,
1229 revision, software_name, hostname);
1230 ret = CtdlIPCGenericCommand(aaa, NULL, 0, NULL, NULL, cret);
1237 int CtdlIPCSendInstantMessage(const char *username, const char *text,
1243 if (!cret) return -2;
1244 if (!username) return -2;
1246 aaa = (char *)malloc(strlen(username) + 8);
1247 if (!aaa) return -1;
1250 sprintf(aaa, "SEXP %s|-", username);
1251 ret = CtdlIPCGenericCommand(aaa, text, strlen(text),
1254 sprintf(aaa, "SEXP %s||", username);
1255 ret = CtdlIPCGenericCommand(aaa, NULL, 0, NULL, NULL, cret);
1263 int CtdlIPCGetInstantMessage(char **listing, char *cret)
1267 if (!cret) return -2;
1268 if (!listing) return -2;
1269 if (*listing) return -2;
1271 return CtdlIPCGenericCommand("GEXP", NULL, 0, listing, &bytes, cret);
1276 /* mode is 0 = enable, 1 = disable, 2 = status */
1277 int CtdlIPCEnableInstantMessageReceipt(int mode, char *cret)
1281 if (!cret) return -2;
1283 sprintf(aaa, "DEXP %d", mode);
1284 return CtdlIPCGenericCommand(aaa, NULL, 0, NULL, NULL, cret);
1289 int CtdlIPCSetBio(char *bio, char *cret)
1291 if (!cret) return -2;
1292 if (!bio) return -2;
1294 return CtdlIPCGenericCommand("EBIO", bio, strlen(bio),
1300 int CtdlIPCGetBio(const char *username, char **listing, char *cret)
1306 if (!cret) return -2;
1307 if (!username) return -2;
1308 if (!listing) return -2;
1309 if (*listing) return -2;
1311 aaa = (char *)malloc(strlen(username) + 6);
1312 if (!aaa) return -1;
1314 sprintf(aaa, "RBIO %s", username);
1315 ret = CtdlIPCGenericCommand(aaa, NULL, 0, listing, &bytes, cret);
1322 int CtdlIPCListUsersWithBios(char **listing, char *cret)
1326 if (!cret) return -2;
1327 if (!listing) return -2;
1328 if (*listing) return -2;
1330 return CtdlIPCGenericCommand("LBIO", NULL, 0, listing, &bytes, cret);
1335 int CtdlIPCStealthMode(int mode, char *cret)
1339 if (!cret) return -1;
1341 sprintf(aaa, "STEL %d", mode ? 1 : 0);
1342 return CtdlIPCGenericCommand(aaa, NULL, 0, NULL, NULL, cret);
1347 int CtdlIPCTerminateSession(int sid, char *cret)
1351 if (!cret) return -1;
1353 sprintf(aaa, "TERM %d", sid);
1354 return CtdlIPCGenericCommand(aaa, NULL, 0, NULL, NULL, cret);
1359 int CtdlIPCTerminateServerNow(char *cret)
1361 if (!cret) return -1;
1363 return CtdlIPCGenericCommand("DOWN", NULL, 0, NULL, NULL, cret);
1368 int CtdlIPCTerminateServerScheduled(int mode, char *cret)
1372 if (!cret) return -1;
1374 sprintf(aaa, "SCDN %d", mode ? 1 : 0);
1375 return CtdlIPCGenericCommand(aaa, NULL, 0, NULL, NULL, cret);
1380 int CtdlIPCEnterSystemMessage(const char *filename, const char *text,
1386 if (!cret) return -2;
1387 if (!text) return -2;
1388 if (!filename) return -2;
1390 aaa = (char *)malloc(strlen(filename) + 6);
1391 if (!aaa) return -1;
1393 sprintf(aaa, "EMSG %s", filename);
1394 ret = CtdlIPCGenericCommand(aaa, text, strlen(text), NULL, NULL, cret);
1401 int CtdlIPCChangeHostname(const char *hostname, char *cret)
1406 if (!cret) return -2;
1407 if (!hostname) return -2;
1409 aaa = (char *)malloc(strlen(hostname) + 6);
1410 if (!aaa) return -1;
1412 sprintf(aaa, "HCHG %s", hostname);
1413 ret = CtdlIPCGenericCommand(aaa, NULL, 0, NULL, NULL, cret);
1420 int CtdlIPCChangeRoomname(const char *roomname, char *cret)
1425 if (!cret) return -2;
1426 if (!roomname) return -2;
1428 aaa = (char *)malloc(strlen(roomname) + 6);
1429 if (!aaa) return -1;
1431 sprintf(aaa, "RCHG %s", roomname);
1432 ret = CtdlIPCGenericCommand(aaa, NULL, 0, NULL, NULL, cret);
1439 int CtdlIPCChangeUsername(const char *username, char *cret)
1444 if (!cret) return -2;
1445 if (!username) return -2;
1447 aaa = (char *)malloc(strlen(username) + 6);
1448 if (!aaa) return -1;
1450 sprintf(aaa, "UCHG %s", username);
1451 ret = CtdlIPCGenericCommand(aaa, NULL, 0, NULL, NULL, cret);
1458 /* This function returns the actual server time reported, or 0 if error */
1459 time_t CtdlIPCServerTime(char *cret)
1461 register time_t tret;
1464 ret = CtdlIPCGenericCommand("TIME", NULL, 0, NULL, NULL, cret);
1465 if (ret / 100 == 2) {
1466 tret = extract_long(cret, 0);
1475 int CtdlIPCAideGetUserParameters(struct usersupp **uret, char *cret)
1480 if (!cret) return -2;
1481 if (!uret) return -2;
1482 if (!*uret) return -2;
1484 aaa = (char *)malloc(strlen(uret[0]->fullname) + 6);
1485 if (!aaa) return -1;
1487 sprintf(aaa, "AGUP %s", uret[0]->fullname);
1488 ret = CtdlIPCGenericCommand(aaa, NULL, 0, NULL, NULL, cret);
1489 if (ret / 100 == 2) {
1490 extract(uret[0]->fullname, cret, 0);
1491 extract(uret[0]->password, cret, 1);
1492 uret[0]->flags = extract_int(cret, 2);
1493 uret[0]->timescalled = extract_long(cret, 3);
1494 uret[0]->posted = extract_long(cret, 4);
1495 uret[0]->axlevel = extract_int(cret, 5);
1496 uret[0]->usernum = extract_long(cret, 6);
1497 uret[0]->lastcall = extract_long(cret, 7);
1498 uret[0]->USuserpurge = extract_int(cret, 8);
1506 int CtdlIPCAideSetUserParameters(const struct usersupp *uret, char *cret)
1511 if (!cret) return -2;
1512 if (!uret) return -2;
1514 aaa = (char *)malloc(strlen(uret->fullname) + strlen(uret->password) + 84);
1515 if (!aaa) return -1;
1517 sprintf(aaa, "ASUP %s|%s|%d|%ld|%ld|%d|%ld|%ld|%d",
1518 uret->fullname, uret->password, uret->flags,
1519 uret->timescalled, uret->posted, uret->axlevel,
1520 uret->usernum, uret->lastcall, uret->USuserpurge);
1521 ret = CtdlIPCGenericCommand(aaa, NULL, 0, NULL, NULL, cret);
1528 /* which is 0 = room, 1 = floor, 2 = site */
1529 int CtdlIPCGetMessageExpirationPolicy(int which, char *cret)
1531 static char *proto[] = {"room", "floor", "site"};
1534 if (!cret) return -2;
1535 if (which < 0 || which > 2) return -2;
1537 sprintf(aaa, "GPEX %s", proto[which]);
1538 return CtdlIPCGenericCommand(aaa, NULL, 0, NULL, NULL, cret);
1543 /* which is 0 = room, 1 = floor, 2 = site */
1544 /* policy is 0 = inherit, 1 = no purge, 2 = by count, 3 = by age (days) */
1545 int CtdlIPCSetMessageExpirationPolicy(int which, int policy, int value,
1550 if (!cret) return -2;
1551 if (which < 0 || which > 2) return -2;
1552 if (policy < 0 || policy > 3) return -2;
1553 if (policy >= 2 && value < 1) return -2;
1555 sprintf(aaa, "SPEX %d|%d|%d", which, policy, value);
1556 return CtdlIPCGenericCommand(aaa, NULL, 0, NULL, NULL, cret);
1561 int CtdlGetSystemConfig(char **listing, char *cret)
1565 if (!cret) return -2;
1566 if (!listing) return -2;
1567 if (*listing) return -2;
1569 return CtdlIPCGenericCommand("CONF GET", NULL, 0,
1570 listing, &bytes, cret);
1575 int CtdlSetSystemConfig(const char *listing, char *cret)
1577 if (!cret) return -2;
1578 if (!listing) return -2;
1580 return CtdlIPCGenericCommand("CONF SET", listing, strlen(listing),
1586 int CtdlIPCModerateMessage(long msgnum, int level, char *cret)
1590 if (!cret) return -2;
1591 if (!msgnum) return -2;
1593 sprintf(aaa, "MMOD %ld|%d", msgnum, level);
1594 return CtdlIPCGenericCommand(aaa, NULL, 0, NULL, NULL, cret);
1599 int CtdlIPCRequestClientLogout(int session, char *cret)
1603 if (!cret) return -2;
1604 if (session < 0) return -2;
1606 sprintf(aaa, "REQT %d", session);
1607 return CtdlIPCGenericCommand(aaa, NULL, 0, NULL, NULL, cret);
1612 int CtdlIPCSetMessageSeen(long msgnum, int seen, char *cret)
1616 if (!cret) return -2;
1617 if (msgnum < 0) return -2;
1619 sprintf(aaa, "SEEN %ld|%d", msgnum, seen ? 1 : 0);
1620 return CtdlIPCGenericCommand(aaa, NULL, 0, NULL, NULL, cret);
1625 int CtdlIPCStartEncryption(char *cret)
1627 return CtdlIPCGenericCommand("STLS", NULL, 0, NULL, NULL, cret);
1649 /* ************************************************************************** */
1650 /* Stuff below this line is not for public consumption */
1651 /* ************************************************************************** */
1654 inline void netio_lock(void)
1656 #ifdef THREADED_CLIENT
1657 pthread_mutex_lock(&rwlock);
1662 inline void netio_unlock(void)
1664 #ifdef THREADED_CLIENT
1665 pthread_mutex_unlock(&rwlock);
1670 /* Read a listing from the server up to 000. Append to dest if it exists */
1671 char *CtdlIPCReadListing(char *dest)
1678 if (ret) length = strlen(ret);
1679 while (serv_gets(aaa), strcmp(aaa, "000")) {
1680 ret = (char *)realloc(ret, length + strlen(aaa) + 1);
1682 strcpy(&ret[length], aaa);
1688 /* Send a listing to the server; generate the ending 000. */
1689 int CtdlIPCSendListing(const char *listing)
1693 text = (char *)malloc(strlen(listing) + 5);
1695 strcpy(text, listing);
1696 if (text[strlen(text) - 1] == '\n')
1697 text[strlen(text) - 1] = '\0';
1698 strcat(text, "000");
1703 /* Malloc failed but we are committed to send */
1704 /* This may result in extra blanks at the bottom */
1712 /* Partial read of file from server */
1713 size_t CtdlIPCPartialRead(void **buf, size_t offset, size_t bytes, char *cret)
1715 register size_t len = 0;
1718 if (!buf) return -1;
1719 if (!cret) return -1;
1720 if (bytes < 1) return -1;
1721 if (offset < 0) return -1;
1724 sprintf(aaa, "READ %d|%d", offset, bytes);
1728 strcpy(cret, &aaa[4]);
1730 len = extract_long(&aaa[4], 0);
1731 *buf = (void *)realloc(*buf, offset + len);
1733 /* I know what I'm doing */
1734 serv_read((char *)&buf[offset], len);
1736 /* We have to read regardless */
1737 serv_read(aaa, len);
1747 int CtdlIPCEndDownload(char *cret)
1751 if (!cret) return -2;
1752 if (!download_in_progress) return -2;
1754 ret = CtdlIPCGenericCommand("CLOS", NULL, 0, NULL, NULL, cret);
1756 download_in_progress = 0;
1762 int CtdlIPCReadDownload(void **buf, size_t bytes, char *cret)
1764 register size_t len;
1766 if (!cret) return -1;
1767 if (!buf) return -1;
1768 if (*buf) return -1;
1769 if (!download_in_progress) return -1;
1772 while (len < bytes) {
1773 len = CtdlIPCPartialRead(buf, len, 4096, cret);
1784 int CtdlIPCEndUpload(char *cret)
1788 if (!cret) return -1;
1789 if (!upload_in_progress) return -1;
1791 ret = CtdlIPCGenericCommand("UCLS", NULL, 0, NULL, NULL, cret);
1793 upload_in_progress = 0;
1799 int CtdlIPCWriteUpload(void *buf, size_t bytes, char *cret)
1801 register int ret = -1;
1802 register size_t offset;
1805 if (!cret) return -1;
1806 if (!buf) return -1;
1807 if (bytes < 1) return -1;
1810 while (offset < bytes) {
1811 sprintf(aaa, "WRIT %d", bytes - offset);
1814 strcpy(cret, &aaa[4]);
1816 if (aaa[0] == '7') {
1817 register size_t to_write;
1819 to_write = extract_long(&aaa[4], 0);
1820 serv_write(buf + offset, to_write);
1831 * Generic command method. This method should handle any server command
1832 * except for CHAT. It takes the following arguments:
1834 * command Preformatted command to send to server
1835 * to_send A text or binary file to send to server
1836 * (only sent if server requests it)
1837 * bytes_to_send The number of bytes in to_send (required if
1838 * sending binary, optional if sending listing)
1839 * to_receive Pointer to a NULL pointer, if the server
1840 * sends text or binary we will allocate memory
1841 * for the file and stuff it here
1842 * bytes_to_receive If a file is received, we will store its
1844 * proto_response The protocol response. Caller must provide
1845 * this buffer and ensure that it is at least
1846 * 128 bytes in length.
1848 * This function returns a number equal to the protocol response number,
1849 * -1 if an internal error occurred, -2 if caller provided bad values,
1850 * or 0 - the protocol response number if bad values were found during
1851 * the protocol exchange.
1852 * It stores the protocol response string (minus the number) in
1853 * protocol_response as described above. Some commands send additional
1854 * data in this string.
1856 int CtdlIPCGenericCommand(const char *command, const char *to_send,
1857 size_t bytes_to_send, char **to_receive,
1858 size_t *bytes_to_receive, char *proto_response)
1863 if (!command) return -2;
1864 if (!proto_response) return -2;
1867 serv_puts((char *)command);
1869 serv_gets(proto_response);
1870 if (proto_response[3] == '*')
1872 ret = atoi(proto_response);
1873 memmove(proto_response, &proto_response[4],
1874 strlen(proto_response) - 3);
1875 switch (ret / 100) {
1876 default: /* Unknown, punt */
1878 case 3: /* MORE_DATA */
1880 /* Don't need to do anything */
1882 case 1: /* LISTING_FOLLOWS */
1883 if (to_receive && !*to_receive && bytes_to_receive) {
1884 *to_receive = CtdlIPCReadListing(NULL);
1885 } else { /* Drain */
1886 while (serv_gets(buf), strcmp(buf, "000")) ;
1890 case 4: /* SEND_LISTING */
1892 CtdlIPCSendListing(to_send);
1894 /* No listing given, fake it */
1899 case 6: /* BINARY_FOLLOWS */
1900 if (to_receive && !*to_receive && bytes_to_receive) {
1902 extract_long(proto_response, 0);
1903 *to_receive = (char *)malloc(*bytes_to_receive);
1907 serv_read(*to_receive,
1914 drain = extract_long(proto_response, 0);
1915 while (drain > SIZ) {
1916 serv_read(buf, SIZ);
1919 serv_read(buf, drain);
1923 case 7: /* SEND_BINARY */
1924 if (to_send && bytes_to_send) {
1925 serv_write((char *)to_send, bytes_to_send);
1926 } else if (bytes_to_send) {
1927 /* Fake it, send nulls */
1930 fake = bytes_to_send;
1931 memset(buf, '\0', SIZ);
1932 while (fake > SIZ) {
1933 serv_write(buf, SIZ);
1936 serv_write(buf, fake);
1938 } /* else who knows? DANGER WILL ROBINSON */
1940 case 8: /* START_CHAT_MODE */
1941 if (!strncasecmp(command, "CHAT", 4)) {
1942 /* Don't call chatmode with generic! */
1946 /* In this mode we send then receive listing */
1948 CtdlIPCSendListing(to_send);
1950 /* No listing given, fake it */
1954 if (to_receive && !*to_receive
1955 && bytes_to_receive) {
1956 *to_receive = CtdlIPCReadListing(NULL);
1957 } else { /* Drain */
1958 while (serv_gets(buf),
1959 strcmp(buf, "000")) ;
1964 case 9: /* ASYNC_MSG */
1965 /* CtdlIPCDoAsync(ret, proto_response); */
1966 free(CtdlIPCReadListing(NULL)); /* STUB FIXME */