X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=citadel%2Fcitadel_ipc.c;h=ef902281dd69ae44310bc98799eb5de28abae09a;hb=4eb74b26380dfde31c86c685f0589e0c653aebf0;hp=a9114889e1b972ff4036e971ee3427b59ce7d608;hpb=59f848b5ef248343efdeb2f2a1cc71ce4f7262c8;p=citadel.git diff --git a/citadel/citadel_ipc.c b/citadel/citadel_ipc.c index a9114889e..ef902281d 100644 --- a/citadel/citadel_ipc.c +++ b/citadel/citadel_ipc.c @@ -1,4 +1,21 @@ -/* $Id$ */ +/* $Id$ + * + * Copyright (c) 1987-2009 by the citadel.org team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ #include "sysdep.h" #if TIME_WITH_SYS_TIME @@ -29,11 +46,11 @@ #ifdef THREADED_CLIENT #include #endif +#include #include "citadel.h" #include "citadel_ipc.h" #include "citadel_decls.h" -#include "tools.h" - +#include "citadel_dirs.h" #ifdef THREADED_CLIENT pthread_mutex_t rwlock; #endif @@ -71,7 +88,6 @@ static void serv_write(CtdlIPC *ipc, const char *buf, unsigned int nbytes); #ifdef HAVE_OPENSSL static void serv_read_ssl(CtdlIPC *ipc, char *buf, unsigned int bytes); static void serv_write_ssl(CtdlIPC *ipc, const char *buf, unsigned int nbytes); -static void ssl_lock(int mode, int n, const char *file, int line); static void endtls(SSL *ssl); #ifdef THREADED_CLIENT static unsigned long id_callback(void); @@ -81,6 +97,9 @@ static void CtdlIPC_getline(CtdlIPC* ipc, char *buf); static void CtdlIPC_putline(CtdlIPC *ipc, const char *buf); + +const char *svn_revision(void); + /* * Does nothing. The server should always return 200. */ @@ -121,7 +140,7 @@ int CtdlIPCEcho(CtdlIPC *ipc, const char *arg, char *cret) int CtdlIPCQuit(CtdlIPC *ipc) { register int ret = 221; /* Default to successful quit */ - char aaa[128]; + char aaa[SIZ]; CtdlIPC_lock(ipc); if (ipc->sock > -1) { @@ -143,13 +162,13 @@ int CtdlIPCQuit(CtdlIPC *ipc) /* - * Asks the server to logout. Should always return 200, even if no user + * Asks the server to log out. Should always return 200, even if no user * was logged in. The user will not be logged in after this! */ int CtdlIPCLogout(CtdlIPC *ipc) { register int ret; - char aaa[128]; + char aaa[SIZ]; CtdlIPC_lock(ipc); CtdlIPC_putline(ipc, "LOUT"); @@ -327,6 +346,7 @@ int CtdlIPCKnownRooms(CtdlIPC *ipc, enum RoomList which, int floor, struct march } } *listing = march; + if (bbb) free(bbb); return ret; } @@ -367,6 +387,22 @@ int CtdlIPCSetConfig(CtdlIPC *ipc, struct ctdluser *uret, char *cret) } +/* RENU */ +int CtdlIPCRenameUser(CtdlIPC *ipc, char *oldname, char *newname, char *cret) +{ + register int ret; + char cmd[256]; + + if (!oldname) return -2; + if (!newname) return -2; + if (!cret) return -2; + + snprintf(cmd, sizeof cmd, "RENU %s|%s", oldname, newname); + ret = CtdlIPCGenericCommand(ipc, cmd, NULL, 0, NULL, NULL, cret); + return ret; +} + + /* GOTO */ int CtdlIPCGotoRoom(CtdlIPC *ipc, const char *room, const char *passwd, struct ctdlipcroom **rret, char *cret) @@ -407,9 +443,12 @@ int CtdlIPCGotoRoom(CtdlIPC *ipc, const char *room, const char *passwd, rret[0]->RRaide = extract_int(cret, 8); rret[0]->RRnewmail = extract_long(cret, 9); rret[0]->RRfloor = extract_int(cret, 10); + rret[0]->RRflags2 = extract_int(cret, 14); } else { free(*rret); + *rret = NULL; } + free(aaa); return ret; } @@ -474,6 +513,7 @@ int CtdlIPCGetSingleMessage(CtdlIPC *ipc, long msgnum, int headers, int as_mime, size_t bbb_len; int multipart_hunting = 0; char multipart_prefix[128]; + char encoding[256]; if (!cret) return -1; if (!mret) return -1; @@ -481,6 +521,7 @@ int CtdlIPCGetSingleMessage(CtdlIPC *ipc, long msgnum, int headers, int as_mime, if (!*mret) return -1; if (!msgnum) return -1; + strcpy(encoding, ""); strcpy(mret[0]->content_type, ""); sprintf(aaa, "MSG%d %ld|%d", as_mime, msgnum, headers); ret = CtdlIPCGenericCommand(ipc, aaa, NULL, 0, &bbb, &bbb_len, cret); @@ -511,6 +552,8 @@ int CtdlIPCGetSingleMessage(CtdlIPC *ipc, long msgnum, int headers, int as_mime, safestrncpy(mret[0]->node, &aaa[5], SIZ); else if (!strncasecmp(aaa, "rcpt=", 5)) safestrncpy(mret[0]->recipient, &aaa[5], SIZ); + else if (!strncasecmp(aaa, "wefw=", 5)) + safestrncpy(mret[0]->references, &aaa[5], SIZ); else if (!strncasecmp(aaa, "time=", 5)) mret[0]->time = atol(&aaa[5]); @@ -574,10 +617,9 @@ int CtdlIPCGetSingleMessage(CtdlIPC *ipc, long msgnum, int headers, int as_mime, /* If doing a MIME thing, pull out the extra headers */ if (as_mime == 4) { do { - if (!strncasecmp(bbb, "Content-type: ", 14)) { + if (!strncasecmp(bbb, "Content-type:", 13)) { extract_token(mret[0]->content_type, bbb, 0, '\n', sizeof mret[0]->content_type); - strcpy(mret[0]->content_type, - &mret[0]->content_type[14]); + strcpy(mret[0]->content_type, &mret[0]->content_type[13]); striplt(mret[0]->content_type); /* strip out ";charset=" portion. FIXME do something with @@ -589,6 +631,16 @@ int CtdlIPCGetSingleMessage(CtdlIPC *ipc, long msgnum, int headers, int as_mime, } } + if (!strncasecmp(bbb, "X-Citadel-MSG4-Partnum:", 23)) { + extract_token(mret[0]->mime_chosen, bbb, 0, '\n', sizeof mret[0]->mime_chosen); + strcpy(mret[0]->mime_chosen, &mret[0]->mime_chosen[23]); + striplt(mret[0]->mime_chosen); + } + if (!strncasecmp(bbb, "Content-transfer-encoding:", 26)) { + extract_token(encoding, bbb, 0, '\n', sizeof encoding); + strcpy(encoding, &encoding[26]); + striplt(encoding); + } remove_token(bbb, 0, '\n'); } while ((bbb[0] != 0) && (bbb[0] != '\n')); remove_token(bbb, 0, '\n'); @@ -597,8 +649,25 @@ int CtdlIPCGetSingleMessage(CtdlIPC *ipc, long msgnum, int headers, int as_mime, } if (strlen(bbb)) { + + if ( (!strcasecmp(encoding, "base64")) || (!strcasecmp(encoding, "quoted-printable")) ) { + char *ccc = NULL; + int bytes_decoded = 0; + ccc = malloc(strlen(bbb) + 32768); + if (!strcasecmp(encoding, "base64")) { + bytes_decoded = CtdlDecodeBase64(ccc, bbb, strlen(bbb)); + } + else if (!strcasecmp(encoding, "quoted-printable")) { + bytes_decoded = CtdlDecodeQuotedPrintable(ccc, bbb, strlen(bbb)); + } + ccc[bytes_decoded] = 0; + free(bbb); + bbb = ccc; + } + /* FIXME: Strip trailing whitespace */ bbb = (char *)realloc(bbb, (size_t)(strlen(bbb) + 1)); + } else { bbb = (char *)realloc(bbb, 1); *bbb = '\0'; @@ -668,10 +737,27 @@ int CtdlIPCServerInfo(CtdlIPC *ipc, char *cret) break; case 14: ipc->ServInfo.supports_ldap = atoi(buf); break; + case 15: ipc->ServInfo.newuser_disabled = atoi(buf); + break; + case 16: strcpy(ipc->ServInfo.default_cal_zone, buf); + break; + case 17: ipc->ServInfo.load_avg = atof(buf); + break; + case 18: ipc->ServInfo.worker_avg = atof(buf); + break; + case 19: ipc->ServInfo.thread_count = atoi(buf); + break; + case 20: ipc->ServInfo.has_sieve = atoi(buf); + break; + case 21: ipc->ServInfo.fulltext_enabled = atoi(buf); + break; + case 22: strcpy(ipc->ServInfo.svn_revision, buf); + break; } } } + if (listing) free(listing); return ret; } @@ -827,19 +913,34 @@ int CtdlIPCSetRoomAide(CtdlIPC *ipc, const char *username, char *cret) /* ENT0 */ -int CtdlIPCPostMessage(CtdlIPC *ipc, int flag, const struct ctdlipcmessage *mr, char *cret) +int CtdlIPCPostMessage(CtdlIPC *ipc, int flag, int *subject_required, struct ctdlipcmessage *mr, char *cret) { register int ret; char cmd[SIZ]; + char *ptr; if (!cret) return -2; if (!mr) return -2; + if (mr->references) { + for (ptr=mr->references; *ptr != 0; ++ptr) { + if (*ptr == '|') *ptr = '!'; + } + } + snprintf(cmd, sizeof cmd, - "ENT0 %d|%s|%d|%d|%s|%s", flag, mr->recipient, - mr->anonymous, mr->type, mr->subject, mr->author); + "ENT0 %d|%s|%d|%d|%s|%s||||||%s|", flag, mr->recipient, + mr->anonymous, mr->type, mr->subject, mr->author, mr->references); ret = CtdlIPCGenericCommand(ipc, cmd, mr->text, strlen(mr->text), NULL, NULL, cret); + if ((flag == 0) && (subject_required != NULL)) { + /* Is the server strongly recommending that the user enter a message subject? */ + if ((cret[3] != '\0') && (cret[4] != '\0')) { + *subject_required = extract_int(&cret[4], 1); + } + + + } return ret; } @@ -1118,26 +1219,6 @@ int CtdlIPCMoveFile(CtdlIPC *ipc, const char *filename, const char *destroom, ch } -/* NETF */ -int CtdlIPCNetSendFile(CtdlIPC *ipc, const char *filename, const char *destnode, char *cret) -{ - register int ret; - char *aaa; - - if (!cret) return -2; - if (!filename) return -2; - if (!destnode) return -2; - - aaa = (char *)malloc(strlen(filename) + strlen(destnode) + 7); - if (!aaa) return -1; - - sprintf(aaa, "NETF %s|%s", filename, destnode); - ret = CtdlIPCGenericCommand(ipc, aaa, NULL, 0, NULL, NULL, cret); - free(aaa); - return ret; -} - - /* RWHO */ int CtdlIPCOnlineUsers(CtdlIPC *ipc, char **listing, time_t *stamp, char *cret) { @@ -1284,14 +1365,18 @@ int CtdlIPCImageDownload(CtdlIPC *ipc, const char *filename, void **buf, /* UOPN */ -int CtdlIPCFileUpload(CtdlIPC *ipc, const char *save_as, const char *comment, - const char *path, +int CtdlIPCFileUpload(CtdlIPC *ipc, const char *save_as, const char *comment, + const char *path, void (*progress_gauge_callback) (CtdlIPC*, unsigned long, unsigned long), char *cret) { register int ret; char *aaa; + FILE *uploadFP; + char MimeTestBuf[64]; + const char *MimeType; + long len; if (!cret) return -1; if (!save_as) return -1; @@ -1300,15 +1385,24 @@ int CtdlIPCFileUpload(CtdlIPC *ipc, const char *save_as, const char *comment, if (!*path) return -1; if (ipc->uploading) return -1; + uploadFP = fopen(path, "r"); + if (!uploadFP) return -2; + + len = fread(&MimeTestBuf[0], 1, 64, uploadFP); + rewind (uploadFP); + if (len < 0) + return -3; + + MimeType = GuessMimeType(&MimeTestBuf[0], len); aaa = (char *)malloc(strlen(save_as) + strlen(comment) + 7); if (!aaa) return -1; - sprintf(aaa, "UOPN %s|%s", save_as, comment); + sprintf(aaa, "UOPN %s|%s|%s", save_as, MimeType, comment); ret = CtdlIPCGenericCommand(ipc, aaa, NULL, 0, NULL, NULL, cret); free(aaa); if (ret / 100 == 2) { ipc->uploading = 1; - ret = CtdlIPCWriteUpload(ipc, path, progress_gauge_callback, cret); + ret = CtdlIPCWriteUpload(ipc, uploadFP, progress_gauge_callback, cret); ret = CtdlIPCEndUpload(ipc, (ret == -2 ? 1 : 0), cret); ipc->uploading = 0; } @@ -1324,7 +1418,11 @@ int CtdlIPCImageUpload(CtdlIPC *ipc, int for_real, const char *path, char *cret) { register int ret; + FILE *uploadFP; char *aaa; + char MimeTestBuf[64]; + const char *MimeType; + long len; if (!cret) return -1; if (!save_as) return -1; @@ -1335,12 +1433,21 @@ int CtdlIPCImageUpload(CtdlIPC *ipc, int for_real, const char *path, aaa = (char *)malloc(strlen(save_as) + 17); if (!aaa) return -1; - sprintf(aaa, "UIMG %d|%s", for_real, save_as); + uploadFP = fopen(path, "r"); + if (!uploadFP) return -2; + + len = fread(&MimeTestBuf[0], 1, 64, uploadFP); + rewind (uploadFP); + if (len < 0) + return -3; + MimeType = GuessMimeType(&MimeTestBuf[0], 64); + + sprintf(aaa, "UIMG %d|%s|%s", for_real, MimeType, save_as); ret = CtdlIPCGenericCommand(ipc, aaa, NULL, 0, NULL, NULL, cret); free(aaa); if (ret / 100 == 2 && for_real) { ipc->uploading = 1; - ret = CtdlIPCWriteUpload(ipc, path, progress_gauge_callback, cret); + ret = CtdlIPCWriteUpload(ipc, uploadFP, progress_gauge_callback, cret); ret = CtdlIPCEndUpload(ipc, (ret == -2 ? 1 : 0), cret); ipc->uploading = 0; } @@ -1754,7 +1861,7 @@ int CtdlIPCGetMessageExpirationPolicy(CtdlIPC *ipc, int which, struct ExpirePolicy **policy, char *cret) { static char *proto[] = {"room", "floor", "site", "mailboxes" }; - char aaa[11]; + char cmd[256]; register int ret; if (!cret) return -2; @@ -1763,14 +1870,13 @@ int CtdlIPCGetMessageExpirationPolicy(CtdlIPC *ipc, int which, if (!*policy) return -1; if (which < 0 || which > 3) return -2; - sprintf(aaa, "GPEX %s", proto[which]); - ret = CtdlIPCGenericCommand(ipc, aaa, NULL, 0, NULL, NULL, cret); + sprintf(cmd, "GPEX %s", proto[which]); + ret = CtdlIPCGenericCommand(ipc, cmd, NULL, 0, NULL, NULL, cret); if (ret / 100 == 2) { policy[0]->expire_mode = extract_int(cret, 0); policy[0]->expire_value = extract_int(cret, 1); } return ret; - } @@ -1824,6 +1930,7 @@ int CtdlIPCSetSystemConfig(CtdlIPC *ipc, const char *listing, char *cret) int CtdlIPCGetSystemConfigByType(CtdlIPC *ipc, const char *mimetype, char **listing, char *cret) { + register int ret; char *aaa; size_t bytes; @@ -1835,8 +1942,10 @@ int CtdlIPCGetSystemConfigByType(CtdlIPC *ipc, const char *mimetype, aaa = malloc(strlen(mimetype) + 13); if (!aaa) return -1; sprintf(aaa, "CONF GETSYS|%s", mimetype); - return CtdlIPCGenericCommand(ipc, aaa, NULL, 0, + ret = CtdlIPCGenericCommand(ipc, aaa, NULL, 0, listing, &bytes, cret); + free(aaa); + return ret; } @@ -1844,6 +1953,7 @@ int CtdlIPCGetSystemConfigByType(CtdlIPC *ipc, const char *mimetype, int CtdlIPCSetSystemConfigByType(CtdlIPC *ipc, const char *mimetype, const char *listing, char *cret) { + register int ret; char *aaa; if (!cret) return -2; @@ -1853,8 +1963,10 @@ int CtdlIPCSetSystemConfigByType(CtdlIPC *ipc, const char *mimetype, aaa = malloc(strlen(mimetype) + 13); if (!aaa) return -1; sprintf(aaa, "CONF PUTSYS|%s", mimetype); - return CtdlIPCGenericCommand(ipc, aaa, listing, strlen(listing), + ret = CtdlIPCGenericCommand(ipc, aaa, listing, strlen(listing), NULL, NULL, cret); + free(aaa); + return ret; } @@ -1931,8 +2043,8 @@ int CtdlIPCStartEncryption(CtdlIPC *ipc, char *cret) 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"); @@ -2006,6 +2118,7 @@ static void endtls(SSL *ssl) /* QDIR */ int CtdlIPCDirectoryLookup(CtdlIPC *ipc, const char *address, char *cret) { + register int ret; char *aaa; if (!address) return -2; @@ -2015,7 +2128,9 @@ int CtdlIPCDirectoryLookup(CtdlIPC *ipc, const char *address, char *cret) if (!aaa) return -1; sprintf(aaa, "QDIR %s", address); - return CtdlIPCGenericCommand(ipc, aaa, NULL, 0, NULL, NULL, cret); + ret = CtdlIPCGenericCommand(ipc, aaa, NULL, 0, NULL, NULL, cret); + free(aaa); + return ret; } @@ -2297,7 +2412,7 @@ int CtdlIPCEndUpload(CtdlIPC *ipc, int discard, char *cret) /* WRIT */ -int CtdlIPCWriteUpload(CtdlIPC *ipc, const char *path, +int CtdlIPCWriteUpload(CtdlIPC *ipc, FILE *uploadFP, void (*progress_gauge_callback) (CtdlIPC*, unsigned long, unsigned long), char *cret) @@ -2307,14 +2422,10 @@ int CtdlIPCWriteUpload(CtdlIPC *ipc, const char *path, size_t bytes; char aaa[SIZ]; char buf[4096]; - FILE *fd; + FILE *fd = uploadFP; + int ferr; if (!cret) return -1; - if (!path) return -1; - if (!*path) return -1; - - fd = fopen(path, "r"); - if (!fd) return -2; fseek(fd, 0L, SEEK_END); bytes = ftell(fd); @@ -2352,7 +2463,9 @@ int CtdlIPCWriteUpload(CtdlIPC *ipc, const char *path, } if (progress_gauge_callback) progress_gauge_callback(ipc, 1, 1); - return (!ferror(fd) ? ret : -2); + ferr = ferror(fd); + fclose(fd); + return (!ferr ? ret : -2); } @@ -2611,7 +2724,7 @@ static void serv_read(CtdlIPC *ipc, char *buf, unsigned int bytes) /* * send binary to server */ -static void serv_write(CtdlIPC *ipc, const char *buf, unsigned int nbytes) +void serv_write(CtdlIPC *ipc, const char *buf, unsigned int nbytes) { unsigned int bytes_written = 0; int retval; @@ -2661,11 +2774,17 @@ static void serv_read_ssl(CtdlIPC* ipc, char *buf, unsigned int bytes) sleep(1); continue; } +/*** + Not sure why we'd want to handle these error codes any differently, + but this definitely isn't the way to handle them. Someone must have + naively assumed that we could fall back to unencrypted communications, + but all it does is just recursively blow the stack. if (errval == SSL_ERROR_ZERO_RETURN || errval == SSL_ERROR_SSL) { serv_read(ipc, &buf[len], bytes - len); return; } + ***/ error_printf("SSL_read in serv_read: %s\n", ERR_reason_error_string(ERR_peek_error())); connection_died(ipc, 1); @@ -2719,6 +2838,17 @@ static void serv_write_ssl(CtdlIPC *ipc, const char *buf, unsigned int nbytes) } +#ifdef THREADED_CLIENT +static void ssl_lock(int mode, int n, const char *file, int line) +{ + if (mode & CRYPTO_LOCK) + pthread_mutex_lock(Critters[n]); + else + pthread_mutex_unlock(Critters[n]); +} +#endif /* THREADED_CLIENT */ + + static void CtdlIPC_init_OpenSSL(void) { int a; @@ -2799,15 +2929,6 @@ static void CtdlIPC_init_OpenSSL(void) } -static void ssl_lock(int mode, int n, const char *file, int line) -{ -#ifdef THREADED_CLIENT - if (mode & CRYPTO_LOCK) - pthread_mutex_lock(Critters[n]); - else - pthread_mutex_unlock(Critters[n]); -#endif /* THREADED_CLIENT */ -} #ifdef THREADED_CLIENT static unsigned long id_callback(void) { @@ -2817,9 +2938,178 @@ static unsigned long id_callback(void) { #endif /* HAVE_OPENSSL */ +int +ReadNetworkChunk(CtdlIPC* ipc) +{ + fd_set read_fd; + int tries; + int ret = 0; + int err = 0; + struct timeval tv; + size_t n; + + tv.tv_sec = 1; + tv.tv_usec = 1000; + tries = 0; + n = 0; + while (1) + { + errno=0; + FD_ZERO(&read_fd); + FD_SET(ipc->sock, &read_fd); + ret = select(ipc->sock+1, &read_fd, NULL, NULL, &tv); + +// fprintf(stderr, "\nselect failed: %d %d %s\n", ret, err, strerror(err)); + + if (ret > 0) { + + *(ipc->BufPtr) = '\0'; +// n = read(ipc->sock, ipc->BufPtr, ipc->BufSize - (ipc->BufPtr - ipc->Buf) - 1); + n = recv(ipc->sock, ipc->BufPtr, ipc->BufSize - (ipc->BufPtr - ipc->Buf) - 1, 0); + if (n > 0) { + ipc->BufPtr[n]='\0'; + ipc->BufUsed += n; + return n; + } + else + return n; + } + else if (ret < 0) { + if (!(errno == EINTR || errno == EAGAIN)) + error_printf( "\nselect failed: %d %s\n", err, strerror(err)); + return -1; + }/* + else { + tries ++; + if (tries >= 10) + n = read(ipc->sock, ipc->BufPtr, ipc->BufSize - (ipc->BufPtr - ipc->Buf) - 1); + if (n > 0) { + ipc->BufPtr[n]='\0'; + ipc->BufUsed += n; + return n; + } + else { + connection_died(ipc, 0); + return -1; + } + }*/ + } +} + /* * input string from socket - implemented in terms of serv_read() */ +#ifdef CHUNKED_READ + +static void CtdlIPC_getline(CtdlIPC* ipc, char *buf) +{ + int i, ntries; + char *aptr, *bptr, *aeptr, *beptr; + +// error_printf("---\n"); + + beptr = buf + SIZ; +#if defined(HAVE_OPENSSL) + if (ipc->ssl) { + + /* Read one character at a time. */ + for (i = 0;; i++) { + serv_read(ipc, &buf[i], 1); + if (buf[i] == '\n' || i == (SIZ-1)) + break; + } + + /* If we got a long line, discard characters until the newline. */ + if (i == (SIZ-1)) + while (buf[i] != '\n') + serv_read(ipc, &buf[i], 1); + + /* Strip the trailing newline (and carriage return, if present) */ + if (i>=0 && buf[i] == 10) buf[i--] = 0; + if (i>=0 && buf[i] == 13) buf[i--] = 0; + } + else +#endif + { + if (ipc->Buf == NULL) + { + ipc->BufSize = SIZ; + ipc->Buf = (char*) malloc(ipc->BufSize + 10); + *(ipc->Buf) = '\0'; + ipc->BufPtr = ipc->Buf; + } + + ntries = 0; +// while ((ipc->BufUsed == 0)||(ntries++ > 10)) + if (ipc->BufUsed == 0) + ReadNetworkChunk(ipc); + +//// if (ipc->BufUsed != 0) while (1) + bptr = buf; + + while (1) + { + aptr = ipc->BufPtr; + aeptr = ipc->Buf + ipc->BufSize; + while ((aptr < aeptr) && + (bptr < beptr) && + (*aptr != '\0') && + (*aptr != '\n')) + *(bptr++) = *(aptr++); + if ((*aptr == '\n') && (aptr < aeptr)) + { + /* Terminate it right, remove the line breaks */ + while ((aptr < aeptr) && ((*aptr == '\n') || (*aptr == '\r'))) + aptr ++; + while ((aptr < aeptr ) && (*(aptr + 1) == '\0') ) + aptr ++; + *(bptr++) = '\0'; +// fprintf(stderr, "parsing %d %d %d - %d %d %d %s\n", ipc->BufPtr - ipc->Buf, aptr - ipc->BufPtr, ipc->BufUsed , *aptr, *(aptr-1), *(aptr+1), buf); + if ((bptr > buf + 1) && (*(bptr-1) == '\r')) + *(--bptr) = '\0'; + + /* is there more in the buffer we need to read later? */ + if (ipc->Buf + ipc->BufUsed > aptr) + { + ipc->BufPtr = aptr; + } + else + { + ipc->BufUsed = 0; + ipc->BufPtr = ipc->Buf; + } +// error_printf("----bla6\n"); + return; + + }/* should we move our read stuf to the bufferstart so we have more space at the end? */ + else if ((ipc->BufPtr != ipc->Buf) && + (ipc->BufUsed > (ipc->BufSize - (ipc->BufSize / 4)))) + { + size_t NewBufSize = ipc->BufSize * 2; + int delta = (ipc->BufPtr - ipc->Buf); + char *NewBuf; + + /* if the line would end after our buffer, we should use a bigger buffer. */ + NewBuf = (char *)malloc (NewBufSize + 10); + memcpy (NewBuf, ipc->BufPtr, ipc->BufUsed - delta); + free(ipc->Buf); + ipc->Buf = ipc->BufPtr = NewBuf; + ipc->BufUsed -= delta; + ipc->BufSize = NewBufSize; + } + if (ReadNetworkChunk(ipc) <0) + { +// error_printf("----bla\n"); + return; + } + } +/// error_printf("----bl45761%s\nipc->BufUsed"); + } +// error_printf("----bla1\n"); +} + +#else /* CHUNKED_READ */ + static void CtdlIPC_getline(CtdlIPC* ipc, char *buf) { int i; @@ -2837,10 +3127,14 @@ static void CtdlIPC_getline(CtdlIPC* ipc, char *buf) serv_read(ipc, &buf[i], 1); /* Strip the trailing newline (and carriage return, if present) */ - if (buf[i] == 10) buf[i--] = 0; - if (buf[i] == 13) buf[i--] = 0; + if (i>=0 && buf[i] == 10) buf[i--] = 0; + if (i>=0 && buf[i] == 13) buf[i--] = 0; } + +#endif /* CHUNKED_READ */ + + void CtdlIPC_chat_recv(CtdlIPC* ipc, char* buf) { CtdlIPC_getline(ipc, buf); @@ -2905,6 +3199,9 @@ CtdlIPC* CtdlIPC_new(int argc, char **argv, char *hostbuf, char *portbuf) ipc->uploading = 0; ipc->last_command_sent = 0L; ipc->network_status_cb = NULL; + ipc->Buf = NULL; + ipc->BufUsed = 0; + ipc->BufPtr = NULL; strcpy(cithost, DEFAULT_HOST); /* default host */ strcpy(citport, DEFAULT_PORT); /* default port */ @@ -2940,12 +3237,10 @@ CtdlIPC* CtdlIPC_new(int argc, char **argv, char *hostbuf, char *portbuf) /* If we're using a unix domain socket we can do a bunch of stuff */ if (!strcmp(cithost, UDS)) { if (!strcasecmp(citport, DEFAULT_PORT)) { - snprintf(sockpath, sizeof sockpath, "%s%s", - CTDLDIR, "/citadel.socket"); + snprintf(sockpath, sizeof sockpath, file_citadel_socket); } else { - snprintf(sockpath, sizeof sockpath, "%s%s", - citport, "/citadel.socket"); + snprintf(sockpath, sizeof sockpath, "%s/%s", citport, "citadel.socket"); } ipc->sock = uds_connectsock(&(ipc->isLocal), sockpath); if (ipc->sock == -1) { @@ -2984,6 +3279,10 @@ void CtdlIPC_delete(CtdlIPC* ipc) shutdown(ipc->sock, 2); /* Close it up */ ipc->sock = -1; } + if (ipc->Buf != NULL) + free (ipc->Buf); + ipc->Buf = NULL; + ipc->BufPtr = NULL; ifree(ipc); }