In trying to figure out what is going on in imclient_write, I simplified
struct imclient, and moved from pointers to indices - a matter of taste,
I know, but it seems the reply buffer is handled that way..
(One could also s/writelen/imclient->outlen/g)

Cheers,

Patrick


Index: imclient.c
===================================================================
RCS file: /cvs/src/cyrus/lib/imclient.c,v
retrieving revision 1.77
diff -u -r1.77 imclient.c
--- imclient.c  13 Feb 2003 20:15:40 -0000      1.77
+++ imclient.c  4 Apr 2003 19:37:33 -0000
@@ -120,9 +120,7 @@
 
     /* Data to be output to server */
     char outbuf[IMCLIENT_BUFSIZE];
-    char *outptr;
-    size_t outleft;
-    char *outstart;
+    size_t outlen;
 
     /* Replies being received from server */
     char *replybuf;
@@ -263,8 +261,10 @@
     (*imclient)->saslconn = NULL;
     (*imclient)->saslcompleted = 0;
     (*imclient)->servername = xstrdup(hp->h_name);
-    (*imclient)->outptr = (*imclient)->outstart = (*imclient)->outbuf;
-    (*imclient)->outleft = (*imclient)->maxplain = sizeof((*imclient)->outbuf);
+    (*imclient)->outlen = 0;
+    (*imclient)->replylen = 0;
+    (*imclient)->alloc_replybuf = 0;
+       (*imclient)->maxplain = sizeof((*imclient)->outbuf);
     (*imclient)->interact_results = NULL;
     imclient_addcallback(*imclient,
                 "", 0, (imclient_proc_t *) 0, (void *)0,
@@ -626,41 +625,50 @@
  */
 void imclient_write(struct imclient *imclient, const char *s, size_t len)
 {
+       size_t outleft;
+
     assert(imclient);
     assert(s);
     
-    /* If no data pending for output, reset the buffer */
-    if (imclient->outptr == imclient->outstart) {
-       imclient->outstart = imclient->outptr = imclient->outbuf;
-       imclient->outleft = imclient->maxplain;
-    }
-
+       outleft = imclient->maxplain - imclient->outlen;
     /* While we don't have room to buffer all the output */
-    while (len > imclient->outleft) {
-       /* Copy as much data as will fit in output buffer */
-       memcpy(imclient->outptr, s, imclient->outleft);
-       imclient->outptr += imclient->outleft;
-       s += imclient->outleft;
-       len -= imclient->outleft;
-       imclient->outleft = 0;
-
-       /* Process events until output buffer is flushed */
-       while (imclient->outptr != imclient->outstart) {
-           imclient_processoneevent(imclient);
-       }
-
-       /* Reset the buffer */
-       imclient->outstart = imclient->outptr = imclient->outbuf;
-       imclient->outleft = imclient->maxplain;
+    while (len > outleft) {
+               /* Copy as much data as will fit in output buffer */
+               memcpy(imclient->outbuf+imclient->outlen, s, outleft);
+               imclient->outlen += outleft;
+               s += outleft;
+               len -= outleft;
+
+               /* Process events until output buffer is flushed */
+               while (imclient->outlen) {
+               imclient_processoneevent(imclient);
+               } /* Should only be called once. If not, then not all plain text
+                  * was successfully writen in non sasl case
+           */
+               outleft = imclient->maxplain; /*  - imclient->outlen; == 0 */
     }
 
     /* Copy remaining data to output buffer */
-    memcpy(imclient->outptr, s, len);
-    imclient->outptr += len;
-    imclient->outleft -= len;
+    memcpy(imclient->outbuf+imclient->outlen, s, len);
+    imclient->outlen += len;
 }
 
 /*
+ * http://bugzilla.andrew.cmu.edu/show_bug.cgi?id=333
+ *
+ * Opened: 2000-10-13 00:02
+ * 
+ * imclient doesn't correctly parse literals.  this will bite any
+ * serious imclient application that consistently fetches things with
+ * literals.
+ * 
+ * imclient.c, around line 730, uses the variable 'len' in a place
+ * where it clearly isn't applicable.  this is the heart of the bug,
+ * but we need to fix it so that literals that don't end lines are
+ * still handled correctly.
+ */
+
+/*
  * On the connection 'imclient', handle the input 'buf' of size 'len'
  * from the server.  Invoke callbacks as appropriate.
  */
@@ -1006,13 +1014,13 @@
     assert(imclient);
 
     for (;;) {
-       writelen = imclient->outptr - imclient->outstart;
+       writelen = imclient->outlen;
 
        if ((imclient->saslcompleted==1) && (writelen>0)) {
            unsigned int cryptlen=0;
            const char *cryptptr=NULL;
 
-         if (sasl_encode(imclient->saslconn, imclient->outstart, writelen,
+         if (sasl_encode(imclient->saslconn, imclient->outbuf, writelen,
                          &cryptptr,&cryptlen)!=SASL_OK)
          {
              /* XXX encoding error */
@@ -1032,7 +1040,7 @@
 #endif /* HAVE_SSL */
                  
          if (n > 0) {      
-           imclient->outstart += writelen;
+           imclient->outlen = 0; /* what if cryptlen != n ? */
            return;
          }
 
@@ -1047,17 +1055,17 @@
 #ifdef HAVE_SSL
          if (imclient->tls_on==1)
          {
-           n = SSL_write(imclient->tls_conn, imclient->outstart, writelen);
+           n = SSL_write(imclient->tls_conn, imclient->outbuf, writelen);
          } else {
-           n = write(imclient->fd, imclient->outstart, writelen);
+           n = write(imclient->fd, imclient->outbuf, writelen);
          }
 #else  /* HAVE_SSL */
-         n = write(imclient->fd, imclient->outstart, writelen);
+         n = write(imclient->fd, imclient->outbuf, writelen);
 #endif /* HAVE_SSL */
 
 
            if (n > 0) {
-               imclient->outstart += n;
+               imclient->outlen -= n;
                return;
            }
            /* XXX Also EPIPE & the like? */

Reply via email to