Changeset 2875

Show
Ignore:
Timestamp:
10/24/07 09:42:37
Author:
pvanhoof
Message:

2007-10-24 Philip Van Hoof <pvanhoof@gnome.org>

        • Improvements for the IDLE support. The Nonblocking read is now

actually used correctly, various racy situations should be fixed now
and instant event throwing is put in place (during IDLE state).

        • Removed the (*read_idle) funcptr from CamelTcpStream?, as this is no longer

required. This to reduce the complexity of the IDLE patch so that we
can later, perhaps, more easily bring this feature to upstream Camel.

        • Updating unread and total count if necessary (due to IDLE events)

O

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/ChangeLog

    r2874 r2875  
     12007-10-24  Philip Van Hoof  <pvanhoof@gnome.org> 
     2 
     3        * Improvements for the IDLE support. The Nonblocking read is now 
     4        actually used correctly, various racy situations should be fixed now 
     5        and instant event throwing is put in place (during IDLE state). 
     6        * Removed the (*read_idle) funcptr from CamelTcpStream, as this is no longer 
     7        required. This to reduce the complexity of the IDLE patch so that we 
     8        can later, perhaps, more easily bring this feature to upstream Camel. 
     9        * Updating unread and total count if necessary (due to IDLE events) 
     10 
    1112007-10-23  Philip Van Hoof  <pvanhoof@gnome.org> 
    212 
    313        * Reference count problem in TnyCamelHeader 
    4         * priv->folder_name in TnyCamelFolder sometimes is NULL, which doesn't 
    5         seem right (and is racy). 
     14        * priv->folder_name in TnyCamelFolder sometimes is NULL, which 
     15        doesn't seem right (and is racy). 
    616 
    7172007-10-19  Philip Van Hoof  <pvanhoof@gnome.org> 
  • trunk/libtinymail-camel/camel-lite/camel/camel-file-utils.c

    r2823 r2875  
    704704 
    705705 
    706  
    707 ssize_t 
    708 camel_read_idle (int fd, char *buf, size_t n) 
    709 { 
    710         ssize_t nread; 
    711  
    712         int errnosav, flags, fdmax; 
    713         fd_set rdset; 
    714          
    715         flags = fcntl (fd, F_GETFL); 
    716         fcntl (fd, F_SETFL, flags | O_NONBLOCK); 
    717          
    718         do { 
    719                 struct timeval tv; 
    720                 int res; 
    721  
    722                 FD_ZERO (&rdset); 
    723                 FD_SET (fd, &rdset); 
    724                 fdmax = fd + 1; 
    725                 tv.tv_sec = IDLE_READ_TIMEOUT; 
    726                 tv.tv_usec = 0; 
    727                 nread = -1; 
    728  
    729                 res = select(fdmax, &rdset, 0, 0, &tv); 
    730                 if (res == -1) 
    731                         ; 
    732                 else if (res == 0) 
    733                         errno = ETIMEDOUT; 
    734                 else { 
    735                         do { 
    736                                 nread = read (fd, buf, n); 
    737                         } while (0 && (nread == -1 && errno == EINTR)); 
    738                 } 
    739         } while (0 && (nread == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK))); 
    740  
    741         errnosav = errno; 
    742         fcntl (fd, F_SETFL, flags); 
    743         errno = errnosav; 
    744  
    745         return nread; 
    746 } 
    747  
    748  
    749706/** 
    750707 * camel_read_socket: 
     
    842799 
    843800 
    844 ssize_t 
    845 camel_read_socket_idle (int fd, char *buf, size_t n) 
    846 { 
    847 #ifndef G_OS_WIN32 
    848         return camel_read_idle (fd, buf, n); 
    849 #else 
    850         ssize_t nread; 
    851         int cancel_fd; 
    852          
    853         if (camel_operation_cancel_check (NULL)) { 
    854                 errno = EINTR; 
    855                 return -1; 
    856         } 
    857         cancel_fd = camel_operation_cancel_fd (NULL); 
    858  
    859         if (cancel_fd == -1) { 
    860  
    861                 int fdmax; 
    862                 fd_set rdset; 
    863                 u_long yes = 1; 
    864  
    865                 ioctlsocket (fd, FIONBIO, &yes); 
    866                 fdmax = fd + 1; 
    867                 do { 
    868                         struct timeval tv; 
    869                         int res; 
    870  
    871                         FD_ZERO (&rdset); 
    872                         FD_SET (fd, &rdset); 
    873                         tv.tv_sec = IDLE_READ_TIMEOUT; 
    874                         tv.tv_usec = 0; 
    875                         nread = -1; 
    876  
    877                         res = select(fdmax, &rdset, 0, 0, &tv); 
    878                         if (res == -1) 
    879                                 ; 
    880                         else if (res == 0) 
    881                                 errno = ETIMEDOUT; 
    882                         } else {                                 
    883                                 nread = recv (fd, buf, n, 0); 
    884                         } 
    885                 } while ((nread == -1 && WSAGetLastError () == WSAEWOULDBLOCK)); 
    886  
    887         } else { 
    888                 int fdmax; 
    889                 fd_set rdset; 
    890                 u_long yes = 1; 
    891  
    892                 ioctlsocket (fd, FIONBIO, &yes); 
    893                 fdmax = MAX (fd, cancel_fd) + 1; 
    894                 do { 
    895                         struct timeval tv; 
    896                         int res; 
    897  
    898                         FD_ZERO (&rdset); 
    899                         FD_SET (fd, &rdset); 
    900                         FD_SET (cancel_fd, &rdset); 
    901                         tv.tv_sec = IDLE_READ_TIMEOUT; 
    902                         tv.tv_usec = 0; 
    903                         nread = -1; 
    904  
    905                         res = select(fdmax, &rdset, 0, 0, &tv); 
    906                         if (res == -1) 
    907                                 ; 
    908                         else if (res == 0) 
    909                                 errno = ETIMEDOUT; 
    910                         else if (FD_ISSET (cancel_fd, &rdset)) { 
    911                                 errno = EINTR; 
    912                                 goto failed; 
    913                         } else {                                 
    914                                 nread = recv (fd, buf, n, 0); 
    915                         } 
    916                 } while ((nread == -1 && WSAGetLastError () == WSAEWOULDBLOCK)); 
    917         failed: 
    918                 ; 
    919         } 
    920          
    921         return nread; 
    922 #endif 
    923 } 
    924801ssize_t 
    925802camel_read_socket_nb (int fd, char *buf, size_t n) 
  • trunk/libtinymail-camel/camel-lite/camel/camel-file-utils.h

    r2823 r2875  
    8989ssize_t camel_write (int fd, const char *buf, size_t n); 
    9090 
    91 ssize_t camel_read_socket_idle (int fd, char *buf, size_t n); 
    9291ssize_t camel_write_socket (int fd, const char *buf, size_t n); 
    9392 
  • trunk/libtinymail-camel/camel-lite/camel/camel-stream-buffer.c

    r2823 r2875  
    430430 
    431431 
    432  
    433432int 
    434 camel_stream_buffer_gets_idle (CamelStreamBuffer *sbf, char *buf, unsigned int max) 
     433camel_tcp_stream_buffer_gets_nb (CamelStreamBuffer *sbf, char *buf, unsigned int max) 
    435434{ 
    436435        register char *outptr, *inptr, *inend, c, *outend; 
     
    455454                        break; 
    456455 
    457                 bytes_read = camel_stream_read_idle (sbf->stream, (char*)sbf->buf, sbf->size); 
    458                 if (bytes_read == -1) { 
    459                         if (buf == outptr) 
    460                                 return -1; 
    461                         else 
    462                                 bytes_read = 0; 
    463                 } 
    464                 sbf->ptr = sbf->buf; 
    465                 sbf->end = sbf->buf + bytes_read; 
    466                 inptr = (char*)sbf->ptr; 
    467                 inend = (char*)sbf->end; 
    468         } while (bytes_read>0); 
    469  
    470         sbf->ptr = (unsigned char*)inptr; 
    471         *outptr = 0; 
    472  
    473         return (int)(outptr - buf); 
    474 } 
    475  
    476 int 
    477 camel_tcp_stream_buffer_gets_nb (CamelStreamBuffer *sbf, char *buf, unsigned int max) 
    478 { 
    479         register char *outptr, *inptr, *inend, c, *outend; 
    480         int bytes_read; 
    481  
    482         outptr = buf; 
    483         inptr = (char*)sbf->ptr; 
    484         inend = (char*)sbf->end; 
    485         outend = buf+max-1;     /* room for NUL */ 
    486  
    487         do { 
    488                 while (inptr<inend && outptr<outend) { 
    489                         c = *inptr++; 
    490                         *outptr++ = c; 
    491                         if (c == '\n') { 
    492                                 *outptr = 0; 
    493                                 sbf->ptr = (unsigned char*) inptr; 
    494                                 return outptr-buf; 
    495                         } 
    496                 } 
    497                 if (outptr == outend) 
    498                         break; 
    499  
    500456                bytes_read = camel_tcp_stream_read_nb ((CamelTcpStream *)sbf->stream, (char*)sbf->buf, sbf->size); 
    501457                if (bytes_read == -1) { 
  • trunk/libtinymail-camel/camel-lite/camel/camel-stream-buffer.h

    r2823 r2875  
    9696char *camel_stream_buffer_read_line (CamelStreamBuffer *sbf); 
    9797int camel_tcp_stream_buffer_gets_nb (CamelStreamBuffer *sbf, char *buf, unsigned int max); 
    98 int camel_stream_buffer_gets_idle (CamelStreamBuffer *sbf, char *buf, unsigned int max); 
    9998 
    10099 
  • trunk/libtinymail-camel/camel-lite/camel/camel-stream.c

    r2823 r2875  
    9999} 
    100100 
    101 ssize_t 
    102 camel_stream_read_idle (CamelStream *stream, char *buffer, size_t n) 
    103 { 
    104         g_return_val_if_fail (CAMEL_IS_STREAM (stream), -1); 
    105         g_return_val_if_fail (n == 0 || buffer, -1); 
    106  
    107         /* Default impl */ 
    108         if (!CS_CLASS (stream)->read_idle) 
    109                 return (CS_CLASS (stream)->read) (stream, buffer, n); 
    110  
    111         return (CS_CLASS (stream)->read_idle) (stream, buffer, n); 
    112 } 
    113101 
    114102 
  • trunk/libtinymail-camel/camel-lite/camel/camel-stream.h

    r2823 r2875  
    5757        int       (*reset)      (CamelStream *stream); 
    5858 
    59         ssize_t   (*read_idle)  (CamelStream *stream, char *buffer, size_t n); 
    60  
    6159} CamelStreamClass; 
    6260 
     
    6563 
    6664/* public methods */ 
    67 ssize_t    camel_stream_read_idle  (CamelStream *stream, char *buffer, size_t n); 
    6865 
    6966ssize_t    camel_stream_read       (CamelStream *stream, char *buffer, size_t n); 
  • trunk/libtinymail-camel/camel-lite/camel/camel-tcp-stream-openssl.c

    r2823 r2875  
    6262#define CTSR_CLASS(so) CAMEL_TCP_STREAM_SSL_CLASS (CAMEL_OBJECT_GET_CLASS (so)) 
    6363 
    64 static ssize_t stream_read_idle (CamelStream *stream, char *buffer, size_t n); 
    6564static ssize_t stream_read_nb (CamelTcpStream *stream, char *buffer, size_t n); 
    6665static ssize_t stream_read (CamelStream *stream, char *buffer, size_t n); 
     
    101100 
    102101        parent_class = CAMEL_TCP_STREAM_CLASS (camel_type_get_global_classfuncs (camel_tcp_stream_get_type ())); 
    103          
    104         /* virtual method overload */ 
    105         camel_stream_class->read_idle = stream_read_idle; 
    106102 
    107103        camel_stream_class->read = stream_read; 
     
    289285         
    290286        return 0; 
    291 } 
    292  
    293 static ssize_t  
    294 stream_read_idle (CamelStream *stream, char *buffer, size_t n) 
    295 { 
    296         CamelTcpStreamSSL *openssl = CAMEL_TCP_STREAM_SSL (stream); 
    297         SSL *ssl = openssl->priv->ssl; 
    298         ssize_t nread; 
    299  
    300         int error, flags, fdmax; 
    301         struct timeval timeout; 
    302         fd_set rdset; 
    303         int res; 
    304  
    305         flags = fcntl (openssl->priv->sockfd, F_GETFL); 
    306         fcntl (openssl->priv->sockfd, F_SETFL, flags | O_NONBLOCK); 
    307          
    308         fdmax = openssl->priv->sockfd + 1; 
    309          
    310         do { 
    311                 FD_ZERO (&rdset); 
    312                 FD_SET (openssl->priv->sockfd, &rdset); 
    313                 nread = -1; 
    314                 timeout.tv_sec = IDLE_READ_TIMEOUT; 
    315                 timeout.tv_usec = 0; 
    316                 res = select (fdmax, &rdset, 0, 0, &timeout); 
    317                  
    318                 if (res == -1) 
    319                         ; 
    320                 else if (res == 0) 
    321                         errno = ETIMEDOUT; 
    322                 else { 
    323  
    324                   do { 
    325                         if (ssl) { 
    326                                 nread = SSL_read (ssl, buffer, n); 
    327                                 if (nread < 0) 
    328                                         errno = ssl_errno (ssl, nread); 
    329                         } else { 
    330                                 nread = read (openssl->priv->sockfd, buffer, n); 
    331                         } 
    332                   } while (0 && (nread < 0 && errno == EINTR)); 
    333                 } 
    334         } while (0 && (nread < 0 && (errno == EAGAIN || errno == EWOULDBLOCK))); 
    335          
    336         error = errno; 
    337         fcntl (openssl->priv->sockfd, F_SETFL, flags); 
    338         errno = error; 
    339  
    340  
    341         return nread; 
    342287} 
    343288 
  • trunk/libtinymail-camel/camel-lite/camel/camel-tcp-stream-raw.c

    r2823 r2875  
    6666static struct sockaddr *stream_get_remote_address (CamelTcpStream *stream, socklen_t *len); 
    6767static ssize_t stream_read_nb (CamelTcpStream *stream, char *buffer, size_t n); 
    68 static ssize_t stream_read_idle (CamelStream *stream, char *buffer, size_t n); 
    6968 
    7069 
     
    8079 
    8180        /* virtual method overload */ 
    82         camel_stream_class->read_idle = stream_read_idle; 
    8381        camel_stream_class->read = stream_read; 
    8482        camel_stream_class->write = stream_write; 
     
    259257} 
    260258 
    261  
    262 static ssize_t  
    263 stream_read_idle (CamelStream *stream, char *buffer, size_t n) 
    264 { 
    265         CamelTcpStreamRaw *raw = CAMEL_TCP_STREAM_RAW (stream); 
    266          
    267         return camel_read_socket_idle (raw->sockfd, buffer, n); 
    268 } 
    269  
    270259static ssize_t 
    271260stream_read_nb (CamelTcpStream *stream, char *buffer, size_t n) 
  • trunk/libtinymail-camel/camel-lite/camel/camel-tcp-stream-ssl.c

    r2824 r2875  
    8585static struct sockaddr *stream_get_remote_address (CamelTcpStream *stream, socklen_t *len); 
    8686static ssize_t stream_read_nb (CamelTcpStream *stream, char *buffer, size_t n); 
    87 static ssize_t stream_read_idle (CamelStream *stream, char *buffer, size_t n); 
    8887 
    8988struct _CamelTcpStreamSSLPrivate { 
     
    107106         
    108107        parent_class = CAMEL_TCP_STREAM_CLASS (camel_type_get_global_classfuncs (camel_tcp_stream_get_type ())); 
    109          
    110         /* virtual method overload */ 
    111         camel_stream_class->read_idle = stream_read_idle; 
    112108 
    113109        camel_stream_class->read = stream_read; 
     
    511507 
    512508                        res = PR_Poll(pollfds, 2, PR_TicksPerSecond () * BLOCKING_READ_TIMEOUT); 
    513  
    514                         if (res == -1) 
    515                                 set_errno(PR_GetError()); 
    516                         else if (res == 0) { 
    517 #ifdef ETIMEDOUT 
    518                                 errno = ETIMEDOUT; 
    519 #else 
    520                                 errno = EIO; 
    521 #endif 
    522                         } else if (pollfds[1].out_flags == PR_POLL_READ) { 
    523                                 errno = EINTR; 
    524                                 goto failed; 
    525                         } else { 
    526                                 do { 
    527                                         nread = PR_Read (tcp_stream_ssl->priv->sockfd, buffer, n); 
    528                                         if (nread == -1) 
    529                                                 set_errno (PR_GetError ()); 
    530                                 } while (nread == -1 && PR_GetError () == PR_PENDING_INTERRUPT_ERROR); 
    531                         } 
    532                 } while (nread == -1 && (PR_GetError () == PR_PENDING_INTERRUPT_ERROR || 
    533                                          PR_GetError () == PR_IO_PENDING_ERROR || 
    534                                          PR_GetError () == PR_WOULD_BLOCK_ERROR)); 
    535                  
    536                 /* restore O_NONBLOCK options */ 
    537         failed: 
    538                 error = errno; 
    539                 sockopts.option = PR_SockOpt_Nonblocking; 
    540                 sockopts.value.non_blocking = nonblock; 
    541                 PR_SetSocketOption (tcp_stream_ssl->priv->sockfd, &sockopts); 
    542                 errno = error; 
    543         } 
    544          
    545         return nread; 
    546 } 
    547  
    548  
    549  
    550 static ssize_t  
    551 stream_read_idle (CamelStream *stream, char *buffer, size_t n) 
    552 { 
    553         CamelTcpStreamSSL *tcp_stream_ssl = CAMEL_TCP_STREAM_SSL (stream); 
    554         PRFileDesc *cancel_fd; 
    555         ssize_t nread; 
    556          
    557         if (camel_operation_cancel_check (NULL)) { 
    558                 errno = EINTR; 
    559                 return -1; 
    560         } 
    561          
    562         cancel_fd = camel_operation_cancel_prfd (NULL); 
    563         if (cancel_fd == NULL) { 
    564  
    565                 PRSocketOptionData sockopts; 
    566                 PRPollDesc pollfds[1]; 
    567                 gboolean nonblock; 
    568                 int error; 
    569                  
    570                 /* get O_NONBLOCK options */ 
    571                 sockopts.option = PR_SockOpt_Nonblocking; 
    572                 PR_GetSocketOption (tcp_stream_ssl->priv->sockfd, &sockopts); 
    573                 sockopts.option = PR_SockOpt_Nonblocking; 
    574                 nonblock = sockopts.value.non_blocking; 
    575                 sockopts.value.non_blocking = TRUE; 
    576                 PR_SetSocketOption (tcp_stream_ssl->priv->sockfd, &sockopts); 
    577  
    578                 pollfds[0].fd = tcp_stream_ssl->priv->sockfd; 
    579                 pollfds[0].in_flags = PR_POLL_READ; 
    580  
    581                 do { 
    582                         PRInt32 res; 
    583  
    584                         pollfds[0].out_flags = 0; 
    585                         nread = -1; 
    586  
    587                         res = PR_Poll(pollfds, 1, PR_TicksPerSecond () * IDLE_READ_TIMEOUT); 
    588  
    589                         if (res == -1) 
    590                                 set_errno(PR_GetError()); 
    591                         else if (res == 0) { 
    592 #ifdef ETIMEDOUT 
    593                                 errno = ETIMEDOUT; 
    594 #else 
    595                                 errno = EIO; 
    596 #endif 
    597                         } else { 
    598                                 do { 
    599                                         nread = PR_Read (tcp_stream_ssl->priv->sockfd, buffer, n); 
    600                                         if (nread == -1) 
    601                                                 set_errno (PR_GetError ()); 
    602                                 } while (nread == -1 && PR_GetError () == PR_PENDING_INTERRUPT_ERROR); 
    603                         } 
    604                 } while (nread == -1 && (PR_GetError () == PR_PENDING_INTERRUPT_ERROR || 
    605                                          PR_GetError () == PR_IO_PENDING_ERROR || 
    606                                          PR_GetError () == PR_WOULD_BLOCK_ERROR)); 
    607                  
    608                 /* restore O_NONBLOCK options */ 
    609                 error = errno; 
    610                 sockopts.option = PR_SockOpt_Nonblocking; 
    611                 sockopts.value.non_blocking = nonblock; 
    612                 PR_SetSocketOption (tcp_stream_ssl->priv->sockfd, &sockopts); 
    613                 errno = error; 
    614  
    615  
    616         } else { 
    617                 PRSocketOptionData sockopts; 
    618                 PRPollDesc pollfds[2]; 
    619                 gboolean nonblock; 
    620                 int error; 
    621                  
    622                 /* get O_NONBLOCK options */ 
    623                 sockopts.option = PR_SockOpt_Nonblocking; 
    624                 PR_GetSocketOption (tcp_stream_ssl->priv->sockfd, &sockopts); 
    625                 sockopts.option = PR_SockOpt_Nonblocking; 
    626                 nonblock = sockopts.value.non_blocking; 
    627                 sockopts.value.non_blocking = TRUE; 
    628                 PR_SetSocketOption (tcp_stream_ssl->priv->sockfd, &sockopts); 
    629  
    630                 pollfds[0].fd = tcp_stream_ssl->priv->sockfd; 
    631                 pollfds[0].in_flags = PR_POLL_READ; 
    632                 pollfds[1].fd = cancel_fd; 
    633                 pollfds[1].in_flags = PR_POLL_READ; 
    634                  
    635                 do { 
    636                         PRInt32 res; 
    637  
    638                         pollfds[0].out_flags = 0; 
    639                         pollfds[1].out_flags = 0; 
    640                         nread = -1; 
    641  
    642                         res = PR_Poll(pollfds, 2, PR_TicksPerSecond () * IDLE_READ_TIMEOUT); 
    643509 
    644510                        if (res == -1) 
  • trunk/libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-command.c

    r2862 r2875  
    4848#include "camel-imap-utils.h" 
    4949#include "camel-imap-summary.h" 
     50 
     51#include "camel-string-utils.h" 
    5052 
    5153extern int camel_verbose_debug; 
     
    6163static char *imap_command_strdup_printf (CamelImapStore *store, 
    6264                                         const char *fmt, ...); 
    63  
    64 static char * imap_read_untagged_idle (CamelImapStore *store, char *line, CamelException *ex); 
    6565 
    6666 
     
    539539        char *respbuf; 
    540540 
    541         if (camel_imap_store_readline_idle (store, &respbuf, ex) < 0) 
     541        if (camel_imap_store_readline_nl (store, &respbuf, ex) < 0) 
    542542                return CAMEL_IMAP_RESPONSE_ERROR; 
     543 
     544        imap_debug ("(.., ..) <- %s (IDLE response)\n", respbuf); 
    543545 
    544546        switch (*respbuf) { 
     
    559561                /* Read the rest of the response. */ 
    560562                type = CAMEL_IMAP_RESPONSE_UNTAGGED; 
    561                 respbuf = imap_read_untagged_idle (store, respbuf, ex); 
     563                respbuf = imap_read_untagged (store, respbuf, ex); 
    562564                if (!respbuf) 
    563565                        type = CAMEL_IMAP_RESPONSE_ERROR; 
     
    581583                break; 
    582584        default: 
    583                 type = CAMEL_IMAP_RESPONSE_TAGGED; 
     585                if (camel_strstrcase (respbuf, "OK") != NULL ||  
     586                        camel_strstrcase (respbuf, "NO") != NULL || 
     587                        camel_strstrcase (respbuf, "BAD") != NULL) { 
     588 
     589                        type = CAMEL_IMAP_RESPONSE_TAGGED; 
     590 
     591                } else  
     592                        type = CAMEL_IMAP_RESPONSE_UNTAGGED; 
    584593                break; 
    585594        } 
     
    818827 
    819828 
    820  
    821 static char * 
    822 imap_read_untagged_idle (CamelImapStore *store, char *line, CamelException *ex) 
    823 { 
    824         int fulllen, ldigits, nread, n, i, sexp = 0; 
    825         unsigned int length; 
    826         GPtrArray *data; 
    827         GString *str; 
    828         char *end, *p, *s, *d; 
    829          
    830         p = strrchr (line, '{'); 
    831         if (!p) 
    832                 return line; 
    833          
    834         data = g_ptr_array_new (); 
    835         fulllen = 0; 
    836          
    837         while (1) { 
    838                 str = g_string_new (line); 
    839                 g_free (line); 
    840                 fulllen += str->len; 
    841                 g_ptr_array_add (data, str); 
    842                  
    843                 if (!(p = strrchr (str->str, '{')) || p[1] == '-') 
    844                         break; 
    845                  
    846                 /* HACK ALERT: We scan the non-literal part of the string, looking for possible s expression braces. 
    847                    This assumes we're getting s-expressions, which we should be. 
    848                    This is so if we get a blank line after a literal, in an s-expression, we can keep going, since 
    849                    we do no other parsing at this level. 
    850                    TODO: handle quoted strings? */ 
    851                 for (s=str->str; s<p; s++) { 
    852                         if (*s == '(') 
    853                                 sexp++; 
    854                         else if (*s == ')') 
    855                                 sexp--; 
    856                 } 
    857                  
    858                 length = strtoul (p + 1, &end, 10); 
    859                 if (*end != '}' || *(end + 1) || end == p + 1 || length >= UINT_MAX - 2) 
    860                         break; 
    861                 ldigits = end - (p + 1); 
    862                  
    863                 /* Read the literal */ 
    864                 str = g_string_sized_new (length + 2); 
    865                 str->str[0] = '\n'; 
    866                 nread = 0; 
    867                  
    868                 do { 
    869                         if ((n = camel_stream_read_idle (store->istream, str->str + nread + 1, length - nread)) == -1) { 
    870                                 if (errno == EINTR) { 
    871                                         CamelException mex = CAMEL_EXCEPTION_INITIALISER; 
    872                                         camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, 
    873                                                              _("Operation cancelled")); 
    874                                         camel_imap_recon (store, &mex); 
    875                                         imap_debug ("Recon in untagged idle: %s\n", camel_exception_get_description (&mex)); 
    876                                 } else { 
    877                                         camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, 
    878                                                              g_strerror (errno)); 
    879                                         camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL); 
    880                                 } 
    881                                 g_string_free (str, TRUE); 
    882                                 goto lose; 
    883                         } 
    884                          
    885                         nread += n; 
    886                 } while (n > 0 && nread < length); 
    887                  
    888                 if (nread < length) { 
    889                         if (errno == EINTR) { 
    890                                 CamelException mex = CAMEL_EXCEPTION_INITIALISER; 
    891                                 camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, 
    892                                                      _("Operation cancelled")); 
    893                                 camel_imap_recon (store, &mex); 
    894                                 imap_debug ("Recon in untagged idle: %s\n", camel_exception_get_description (&mex)); 
    895                         }  else { 
    896                                 camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, 
    897                                              _("Server response ended too soon.")); 
    898                                 camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL); 
    899                         } 
    900                         g_string_free (str, TRUE); 
    901                         goto lose; 
    902                 } 
    903                 str->str[length + 1] = '\0'; 
    904  
    905                 if (camel_debug("imap")) { 
    906                         printf("Literal: -->"); 
    907                         fwrite(str->str+1, 1, length, stdout); 
    908                         printf("<--\n"); 
    909                 } 
    910                  
    911                 /* Fix up the literal, turning CRLFs into LF. Also, if 
    912                  * we find any embedded NULs, strip them. This is 
    913                  * dubious, but: 
    914                  *   - The IMAP grammar says you can't have NULs here 
    915                  *     anyway, so this will not affect our behavior 
    916                  *     against any completely correct server. 
    917                  *   - WU-imapd 12.264 (at least) will cheerily pass 
    918                  *     NULs along if they are embedded in the message 
    919                  */ 
    920                  
    921                 s = d = str->str + 1; 
    922                 end = str->str + 1 + length; 
    923                 while (s < end) { 
    924                         while (s < end && *s == '\0') { 
    925                                 s++; 
    926                                 length--; 
    927                         } 
    928                         if (*s == '\r' && *(s + 1) == '\n') { 
    929                                 s++; 
    930                                 length--; 
    931                         } 
    932                         *d++ = *s++; 
    933                 } 
    934                 *d = '\0'; 
    935                 str->len = length + 1; 
    936                  
    937                 /* p points to the "{" in the line that starts the 
    938                  * literal. The length of the CR-less response must be 
    939                  * less than or equal to the length of the response 
    940                  * with CRs, therefore overwriting the old value with 
    941                  * the new value cannot cause an overrun. However, we 
    942                  * don't want it to be shorter either, because then the 
    943                  * GString's length would be off... 
    944                  */ 
    945                 sprintf (p, "{%0*u}", ldigits, length); 
    946                  
    947                 fulllen += str->len; 
    948                 g_ptr_array_add (data, str); 
    949  
    950                 /* Read the next line. */ 
    951                 do { 
    952                         if (camel_imap_store_readline_idle (store, &line, ex) < 0) 
    953                                 goto lose; 
    954  
    955                         /* MAJOR HACK ALERT, gropuwise sometimes sends an extra blank line after literals, check that here 
    956                            But only do it if we're inside an sexpression */ 
    957                         if (line[0] == 0 && sexp > 0) 
    958                                 g_warning("Server sent empty line after a literal, assuming in error"); 
    959                 } while (line[0] == 0 && sexp > 0); 
    960         } 
    961          
    962         /* Now reassemble the data. */ 
    963         p = line = g_malloc (fulllen + 1); 
    964         for (i = 0; i < data->len; i++) { 
    965                 str = data->pdata[i]; 
    966                 memcpy (p, str->str, str->len); 
    967                 p += str->len; 
    968                 g_string_free (str, TRUE); 
    969         } 
    970         *p = '\0'; 
    971         g_ptr_array_free (data, TRUE); 
    972         return line; 
    973          
    974  lose: 
    975         for (i = 0; i < data->len; i++) 
    976                 g_string_free (data->pdata[i], TRUE); 
    977         g_ptr_array_free (data, TRUE); 
    978         return NULL; 
    979 } 
    980  
    981829/** 
    982830 * camel_imap_response_free: 
  • trunk/libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-folder.c

    r2870 r2875  
    3939#include <config.h>  
    4040 
     41#include <sched.h> 
     42 
    4143#include <ctype.h> 
    4244#include <errno.h> 
     
    162164static GData *parse_fetch_response (CamelImapFolder *imap_folder, char *msg_att); 
    163165static void camel_imap_folder_changed_for_idle (CamelFolder *folder, int exists, 
    164                            GArray *expunged, CamelException *ex, CamelFolderChangeInfo *changes); 
     166                           GArray *expunged, CamelException *ex, CamelFolderChangeInfo *changes, gboolean exists_happened); 
    165167 
    166168GPtrArray* _camel_imap_store_get_recent_messages (CamelImapStore *imap_store, const char *folder_name, int *messages, int *unseen, gboolean withthem); 
     
    761763        } 
    762764 
    763         if (idle) 
    764                 camel_imap_folder_start_idle (folder); 
    765765} 
    766766 
     
    908908                imap_rescan (folder, camel_folder_summary_count (folder->summary), ex); 
    909909        } else { 
     910 
    910911#if 0 
    911912                /* on some servers need to CHECKpoint INBOX to recieve new messages?? */ 
     
    914915                        response = camel_imap_command (imap_store, folder, ex, "CHECK"); 
    915916                        camel_imap_response_free (imap_store, response); 
    916                         camel_imap_folder_start_idle (folder); 
    917917                } 
    918918#endif 
    919919                response = camel_imap_command (imap_store, folder, ex, "NOOP"); 
    920920                camel_imap_response_free (imap_store, response); 
    921                 camel_imap_folder_start_idle (folder); 
    922921        } 
    923922 
     
    940939 
    941940        camel_folder_summary_save(folder->summary, ex); 
    942  
    943941        camel_store_summary_save((CamelStoreSummary *)((CamelImapStore *)folder->parent_store)->summary, ex); 
     942 
     943        camel_imap_folder_start_idle (folder); 
     94