Changeset 2050
- Timestamp:
- 05/26/07 16:03:07
- Files:
-
- trunk/ChangeLog (modified) (1 diff)
- trunk/libtinymail-camel/camel-lite/camel/camel-file-utils.c (modified) (3 diffs)
- trunk/libtinymail-camel/camel-lite/camel/camel-file-utils.h (modified) (1 diff)
- trunk/libtinymail-camel/camel-lite/camel/camel-stream-buffer.c (modified) (2 diffs)
- trunk/libtinymail-camel/camel-lite/camel/camel-stream-buffer.h (modified) (1 diff)
- trunk/libtinymail-camel/camel-lite/camel/camel-stream.c (modified) (1 diff)
- trunk/libtinymail-camel/camel-lite/camel/camel-stream.h (modified) (2 diffs)
- trunk/libtinymail-camel/camel-lite/camel/camel-tcp-stream-raw.c (modified) (3 diffs)
- trunk/libtinymail-camel/camel-lite/camel/camel-tcp-stream-ssl.c (modified) (3 diffs)
- trunk/libtinymail-camel/camel-lite/camel/camel-tcp-stream.c (modified) (1 diff)
- trunk/libtinymail-camel/camel-lite/camel/camel-tcp-stream.h (modified) (1 diff)
- trunk/libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-command.c (modified) (4 diffs)
- trunk/libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-folder.c (modified) (2 diffs)
- trunk/libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-store.c (modified) (3 diffs)
- trunk/libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-store.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/ChangeLog
r2048 r2050 1 2007-05-26 Philip Van Hoof <pvanhoof@gnome.org> 2 3 * Experimental connection recovery for IMAP 4 * Letting IDLE support cope with connection failures 5 1 6 2007-05-25 Philip Van Hoof <pvanhoof@gnome.org> 2 7 trunk/libtinymail-camel/camel-lite/camel/camel-file-utils.c
r1943 r2050 501 501 fdmax = fd + 1; 502 502 tv.tv_sec = 0; 503 tv.tv_usec = 0; 504 nread = -1; 505 506 res = select(fdmax, &rdset, 0, 0, &tv); 507 if (res == -1) 508 ; 509 else if (res == 0) 510 errno = ETIMEDOUT; 511 else { 512 do { 513 nread = read (fd, buf, n); 514 } while (0 && (nread == -1 && errno == EINTR)); 515 } 516 } while (0 && (nread == -1 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK))); 517 518 errnosav = errno; 519 fcntl (fd, F_SETFL, flags); 520 errno = errnosav; 521 522 return nread; 523 } 524 525 526 527 ssize_t 528 camel_read_idle (int fd, char *buf, size_t n) 529 { 530 ssize_t nread; 531 532 int errnosav, flags, fdmax; 533 fd_set rdset; 534 535 flags = fcntl (fd, F_GETFL); 536 fcntl (fd, F_SETFL, flags | O_NONBLOCK); 537 538 do { 539 struct timeval tv; 540 int res; 541 542 FD_ZERO (&rdset); 543 FD_SET (fd, &rdset); 544 fdmax = fd + 1; 545 tv.tv_sec = 5; 503 546 tv.tv_usec = 0; 504 547 nread = -1; … … 685 728 } 686 729 730 731 ssize_t 732 camel_read_socket_idle (int fd, char *buf, size_t n) 733 { 734 #ifndef G_OS_WIN32 735 return camel_read_idle (fd, buf, n); 736 #else 737 ssize_t nread; 738 int cancel_fd; 739 740 if (camel_operation_cancel_check (NULL)) { 741 errno = EINTR; 742 return -1; 743 } 744 cancel_fd = camel_operation_cancel_fd (NULL); 745 746 if (cancel_fd == -1) { 747 do { 748 nread = recv (fd, buf, n, 0); 749 } while ((nread == SOCKET_ERROR && WSAGetLastError () == WSAEWOULDBLOCK)); 750 } else { 751 int fdmax; 752 fd_set rdset; 753 u_long yes = 1; 754 755 ioctlsocket (fd, FIONBIO, &yes); 756 fdmax = MAX (fd, cancel_fd) + 1; 757 do { 758 struct timeval tv; 759 int res; 760 761 FD_ZERO (&rdset); 762 FD_SET (fd, &rdset); 763 FD_SET (cancel_fd, &rdset); 764 tv.tv_sec = 1; 765 tv.tv_usec = 0; 766 nread = -1; 767 768 res = select(fdmax, &rdset, 0, 0, &tv); 769 if (res == -1) 770 ; 771 else if (res == 0) 772 errno = ETIMEDOUT; 773 else if (FD_ISSET (cancel_fd, &rdset)) { 774 errno = EINTR; 775 goto failed; 776 } else { 777 nread = recv (fd, buf, n, 0); 778 } 779 } while ((nread == -1 && WSAGetLastError () == WSAEWOULDBLOCK)); 780 failed: 781 ; 782 } 783 784 return nread; 785 #endif 786 } 687 787 ssize_t 688 788 camel_read_socket_nb (int fd, char *buf, size_t n) … … 741 841 #endif 742 842 } 843 844 743 845 744 846 /** trunk/libtinymail-camel/camel-lite/camel/camel-file-utils.h
r1943 r2050 74 74 ssize_t camel_write (int fd, const char *buf, size_t n); 75 75 76 ssize_t camel_read_socket (int fd, char *buf, size_t n);76 ssize_t camel_read_socket_idle (int fd, char *buf, size_t n); 77 77 ssize_t camel_write_socket (int fd, const char *buf, size_t n); 78 78 79 ssize_t camel_read_socket (int fd, char *buf, size_t n); 79 80 ssize_t camel_read_socket_nb (int fd, char *buf, size_t n); 80 81 trunk/libtinymail-camel/camel-lite/camel/camel-stream-buffer.c
r1943 r2050 430 430 431 431 432 432 433 int 433 camel_ tcp_stream_buffer_gets_nb(CamelStreamBuffer *sbf, char *buf, unsigned int max)434 camel_stream_buffer_gets_idle (CamelStreamBuffer *sbf, char *buf, unsigned int max) 434 435 { 435 436 register char *outptr, *inptr, *inend, c, *outend; … … 454 455 break; 455 456 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 456 500 bytes_read = camel_tcp_stream_read_nb ((CamelTcpStream *)sbf->stream, (char*)sbf->buf, sbf->size); 457 501 if (bytes_read == -1) { trunk/libtinymail-camel/camel-lite/camel/camel-stream-buffer.h
r1943 r2050 96 96 char *camel_stream_buffer_read_line (CamelStreamBuffer *sbf); 97 97 int 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); 99 98 100 99 101 G_END_DECLS trunk/libtinymail-camel/camel-lite/camel/camel-stream.c
r1014 r2050 97 97 98 98 return (CS_CLASS (stream)->read) (stream, buffer, n); 99 } 100 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); 99 112 } 100 113 trunk/libtinymail-camel/camel-lite/camel/camel-stream.h
r1943 r2050 57 57 int (*reset) (CamelStream *stream); 58 58 59 ssize_t (*read_idle) (CamelStream *stream, char *buffer, size_t n); 60 59 61 } CamelStreamClass; 60 62 … … 63 65 64 66 /* public methods */ 67 ssize_t camel_stream_read_idle (CamelStream *stream, char *buffer, size_t n); 68 65 69 ssize_t camel_stream_read (CamelStream *stream, char *buffer, size_t n); 66 70 ssize_t camel_stream_write (CamelStream *stream, const char *buffer, size_t n); trunk/libtinymail-camel/camel-lite/camel/camel-tcp-stream-raw.c
r1943 r2050 66 66 static struct sockaddr *stream_get_remote_address (CamelTcpStream *stream, socklen_t *len); 67 67 static 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); 68 69 69 70 static void signal_swallow( int num ) … … 85 86 86 87 /* virtual method overload */ 88 camel_stream_class->read_idle = stream_read_idle; 87 89 camel_stream_class->read = stream_read; 88 90 camel_stream_class->write = stream_write; 89 91 camel_stream_class->flush = stream_flush; 90 92 camel_stream_class->close = stream_close; 91 93 92 94 camel_tcp_stream_class->read_nb = stream_read_nb; 93 95 camel_tcp_stream_class->connect = stream_connect; … … 263 265 } 264 266 267 268 static ssize_t 269 stream_read_idle (CamelStream *stream, char *buffer, size_t n) 270 { 271 CamelTcpStreamRaw *raw = CAMEL_TCP_STREAM_RAW (stream); 272 273 return camel_read_socket_idle (raw->sockfd, buffer, n); 274 } 275 265 276 static ssize_t 266 277 stream_read_nb (CamelTcpStream *stream, char *buffer, size_t n) trunk/libtinymail-camel/camel-lite/camel/camel-tcp-stream-ssl.c
r1943 r2050 88 88 static struct sockaddr *stream_get_remote_address (CamelTcpStream *stream, socklen_t *len); 89 89 static ssize_t stream_read_nb (CamelTcpStream *stream, char *buffer, size_t n); 90 static ssize_t stream_read_idle (CamelStream *stream, char *buffer, size_t n); 90 91 91 92 struct _CamelTcpStreamSSLPrivate { … … 110 111 111 112 /* virtual method overload */ 113 camel_stream_class->read_idle = stream_read_idle; 114 112 115 camel_stream_class->read = stream_read; 113 116 camel_stream_class->write = stream_write; … … 475 478 return nread; 476 479 } 480 481 482 483 static ssize_t 484 stream_read_idle (CamelStream *stream, char *buffer, size_t n) 485 { 486 CamelTcpStreamSSL *tcp_stream_ssl = CAMEL_TCP_STREAM_SSL (stream); 487 PRFileDesc *cancel_fd; 488 ssize_t nread; 489 490 if (camel_operation_cancel_check (NULL)) { 491 errno = EINTR; 492 return -1; 493 } 494 495 cancel_fd = camel_operation_cancel_prfd (NULL); 496 if (cancel_fd == NULL) { 497 do { 498 nread = PR_Read (tcp_stream_ssl->priv->sockfd, buffer, n); 499 if (nread == -1) 500 set_errno (PR_GetError ()); 501 } while (nread == -1 && (PR_GetError () == PR_PENDING_INTERRUPT_ERROR || 502 PR_GetError () == PR_IO_PENDING_ERROR || 503 PR_GetError () == PR_WOULD_BLOCK_ERROR)); 504 } else { 505 PRSocketOptionData sockopts; 506 PRPollDesc pollfds[2]; 507 gboolean nonblock; 508 int error; 509 510 /* get O_NONBLOCK options */ 511 sockopts.option = PR_SockOpt_Nonblocking; 512 PR_GetSocketOption (tcp_stream_ssl->priv->sockfd, &sockopts); 513 sockopts.option = PR_SockOpt_Nonblocking; 514 nonblock = sockopts.value.non_blocking; 515 sockopts.value.non_blocking = TRUE; 516 PR_SetSocketOption (tcp_stream_ssl->priv->sockfd, &sockopts); 517 518 pollfds[0].fd = tcp_stream_ssl->priv->sockfd; 519 pollfds[0].in_flags = PR_POLL_READ; 520 pollfds[1].fd = cancel_fd; 521 pollfds[1].in_flags = PR_POLL_READ; 522 523 do { 524 PRInt32 res; 525 526 pollfds[0].out_flags = 0; 527 pollfds[1].out_flags = 0; 528 nread = -1; 529 530 res = PR_Poll(pollfds, 2, 5); 531 532 if (res == -1) 533 set_errno(PR_GetError()); 534 else if (res == 0) { 535 #ifdef ETIMEDOUT 536 errno = ETIMEDOUT; 537 #else 538 errno = EIO; 539 #endif 540 } else if (pollfds[1].out_flags == PR_POLL_READ) { 541 errno = EINTR; 542 goto failed; 543 } else { 544 do { 545 nread = PR_Read (tcp_stream_ssl->priv->sockfd, buffer, n); 546 if (nread == -1) 547 set_errno (PR_GetError ()); 548 } while (nread == -1 && PR_GetError () == PR_PENDING_INTERRUPT_ERROR); 549 } 550 } while (nread == -1 && (PR_GetError () == PR_PENDING_INTERRUPT_ERROR || 551 PR_GetError () == PR_IO_PENDING_ERROR || 552 PR_GetError () == PR_WOULD_BLOCK_ERROR)); 553 554 /* restore O_NONBLOCK options */ 555 failed: 556 error = errno; 557 sockopts.option = PR_SockOpt_Nonblocking; 558 sockopts.value.non_blocking = nonblock; 559 PR_SetSocketOption (tcp_stream_ssl->priv->sockfd, &sockopts); 560 errno = error; 561 } 562 563 return nread; 564 } 565 477 566 478 567 static ssize_t trunk/libtinymail-camel/camel-lite/camel/camel-tcp-stream.c
r1548 r2050 91 91 } 92 92 93 94 93 95 static int 94 96 tcp_connect (CamelTcpStream *stream, struct addrinfo *host) trunk/libtinymail-camel/camel-lite/camel/camel-tcp-stream.h
r1943 r2050 108 108 struct sockaddr * (*get_remote_address) (CamelTcpStream *stream, socklen_t *len); 109 109 ssize_t (*read_nb) (CamelTcpStream *stream, char *buffer, size_t n); 110 111 110 } CamelTcpStreamClass; 112 111 trunk/libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-command.c
r2041 r2050 61 61 const char *fmt, ...); 62 62 63 63 static char * imap_read_untagged_idle (CamelImapStore *store, char *line, CamelException *ex); 64 64 65 65 … … 444 444 char *respbuf; 445 445 446 if (camel_imap_store_readline (store, &respbuf, ex) < 0)446 if (camel_imap_store_readline_idle (store, &respbuf, ex) < 0) 447 447 return CAMEL_IMAP_RESPONSE_ERROR; 448 448 … … 464 464 /* Read the rest of the response. */ 465 465 type = CAMEL_IMAP_RESPONSE_UNTAGGED; 466 respbuf = imap_read_untagged (store, respbuf, ex);466 respbuf = imap_read_untagged_idle (store, respbuf, ex); 467 467 if (!respbuf) 468 468 type = CAMEL_IMAP_RESPONSE_ERROR; … … 708 708 } 709 709 710 711 712 static char * 713 imap_read_untagged_idle (CamelImapStore *store, char *line, CamelException *ex) 714 { 715 int fulllen, ldigits, nread, n, i, sexp = 0; 716 unsigned int length; 717 GPtrArray *data; 718 GString *str; 719 char *end, *p, *s, *d; 720 721 p = strrchr (line, '{'); 722 if (!p) 723 return line; 724 725 data = g_ptr_array_new (); 726 fulllen = 0; 727 728 while (1) { 729 str = g_string_new (line); 730 g_free (line); 731 fulllen += str->len; 732 g_ptr_array_add (data, str); 733 734 if (!(p = strrchr (str->str, '{')) || p[1] == '-') 735 break; 736 737 /* HACK ALERT: We scan the non-literal part of the string, looking for possible s expression braces. 738 This assumes we're getting s-expressions, which we should be. 739 This is so if we get a blank line after a literal, in an s-expression, we can keep going, since 740 we do no other parsing at this level. 741 TODO: handle quoted strings? */ 742 for (s=str->str; s<p; s++) { 743 if (*s == '(') 744 sexp++; 745 else if (*s == ')') 746 sexp--; 747 } 748 749 length = strtoul (p + 1, &end, 10); 750 if (*end != '}' || *(end + 1) || end == p + 1 || length >= UINT_MAX - 2) 751 break; 752 ldigits = end - (p + 1); 753 754 /* Read the literal */ 755 str = g_string_sized_new (length + 2); 756 str->str[0] = '\n'; 757 nread = 0; 758 759 do { 760 if ((n = camel_stream_read_idle (store->istream, str->str + nread + 1, length - nread)) == -1) { 761 if (errno == EINTR) 762 camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, 763 _("Operation cancelled")); 764 else 765 camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, 766 g_strerror (errno)); 767 camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL); 768 g_string_free (str, TRUE); 769 goto lose; 770 } 771 772 nread += n; 773 } while (n > 0 && nread < length); 774 775 if (nread < length) { 776 camel_exception_set (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, 777 _("Server response ended too soon.")); 778 camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL); 779 g_string_free (str, TRUE); 780 goto lose; 781 } 782 str->str[length + 1] = '\0'; 783 784 if (camel_debug("imap")) { 785 printf("Literal: -->"); 786 fwrite(str->str+1, 1, length, stdout); 787 printf("<--\n"); 788 } 789 790 /* Fix up the literal, turning CRLFs into LF. Also, if 791 * we find any embedded NULs, strip them. This is 792 * dubious, but: 793 * - The IMAP grammar says you can't have NULs here 794 * anyway, so this will not affect our behavior 795 * against any completely correct server. 796 * - WU-imapd 12.264 (at least) will cheerily pass 797 * NULs along if they are embedded in the message 798 */ 799 800 s = d = str->str + 1; 801 end = str->str + 1 + length; 802 while (s < end) { 803 while (s < end && *s == '\0') { 804 s++; 805 length--; 806 } 807 if (*s == '\r' && *(s + 1) == '\n') { 808 s++; 809 length--; 810 } 811 *d++ = *s++; 812 } 813 *d = '\0'; 814 str->len = length + 1; 815 816 /* p points to the "{" in the line that starts the 817 * literal. The length of the CR-less response must be 818 * less than or equal to the length of the response 819 * with CRs, therefore overwriting the old value with 820 * the new value cannot cause an overrun. However, we 821 * don't want it to be shorter either, because then the 822 * GString's length would be off... 823 */ 824 sprintf (p, "{%0*u}", ldigits, length); 825 826 fulllen += str->len; 827 g_ptr_array_add (data, str); 828 829 /* Read the next line. */ 830 do { 831 if (camel_imap_store_readline_idle (store, &line, ex) < 0) 832 goto lose; 833 834 /* MAJOR HACK ALERT, gropuwise sometimes sends an extra blank line after literals, check that here 835 But only do it if we're inside an sexpression */ 836 if (line[0] == 0 && sexp > 0) 837 g_warning("Server sent empty line after a literal, assuming in error"); 838 } while (line[0] == 0 && sexp > 0); 839 } 840 841 /* Now reassemble the data. */ 842 p = line = g_malloc (fulllen + 1); 843 for (i = 0; i < data->len; i++) { 844 str = data->pdata[i]; 845 memcpy (p, str->str, str->len); 846 p += str->len; 847 g_string_free (str, TRUE); 848 } 849 *p = '\0'; 850 g_ptr_array_free (data, TRUE); 851 return line; 852 853 lose: 854 for (i = 0; i < data->len; i++) 855 g_string_free (data->pdata[i], TRUE); 856 g_ptr_array_free (data, TRUE); 857 return NULL; 858 } 710 859 711 860 /** trunk/libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-folder.c
r2041 r2050 3399 3399 3400 3400 g_mutex_lock (store->stream_lock); 3401 store->idle_prefix = g_strdup_printf ("%c%.5u", 3402 store->tag_prefix, store->command++); 3403 camel_stream_printf (store->ostream, "%s IDLE\r\n", 3404 store->idle_prefix); 3401 if (store->ostream && store->istream && CAMEL_IS_STREAM (store->ostream)) 3402 { 3403 store->idle_prefix = g_strdup_printf ("%c%.5u", 3404 store->tag_prefix, store->command++); 3405 camel_stream_printf (store->ostream, "%s IDLE\r\n", 3406 store->idle_prefix); 3407 } else { 3408 idle_debug ("idle_real_start connection lost\n"); 3409 goto errh; 3410 } 3405 3411 3406 3412 /* The IDLE command is sent from the client to the server when the … … 3435 3441 g_free (resp); 3436 3442 3443 errh: 3437 3444 g_mutex_unlock (store->stream_lock); 3438 3445 trunk/libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-store.c
r2049 r2050 3743 3743 3744 3744 3745 3746 /* FIXME: please god, when will the hurting stop? Thus function is so 3747 fucking broken it's not even funny. */ 3745 3748 ssize_t 3746 camel_imap_store_readline_ nl(CamelImapStore *store, char **dest, CamelException *ex)3749 camel_imap_store_readline_idle (CamelImapStore *store, char **dest, CamelException *ex) 3747 3750 { 3748 3751 CamelStreamBuffer *stream; … … 3764 3767 return -1; 3765 3768 3769 g_mutex_lock (store->stream_lock); 3766 3770 camel_imap_store_restore_stream_buffer (store); 3767 3768 if (!store->istream)3769 return -1;3770 3771 3771 stream = CAMEL_STREAM_BUFFER (store->istream); 3772 3772 3773 3773 ba = g_byte_array_new (); 3774 while ((nread = camel_stream_buffer_gets (stream, linebuf, sizeof (linebuf))) > 0) {3774 while ((nread = camel_stream_buffer_gets_idle (stream, linebuf, sizeof (linebuf))) > 0) { 3775 3775 g_byte_array_append (ba, (const guchar*) linebuf, nread); 3776 3776 if (linebuf[nread - 1] == '\n') 3777 3777 break; 3778 3778 } 3779 g_mutex_unlock (store->stream_lock); 3779 3780 3780 3781 if (nread <= 0) { … … 3817 3818 3818 3819 ssize_t 3820 camel_imap_store_readline_nl (CamelImapStore *store, char **dest, CamelException *ex) 3821 { 3822 CamelStreamBuffer *stream; 3823 char linebuf[1024] = {0}; 3824 GByteArray *ba; 3825 ssize_t nread; 3826 3827 g_return_val_if_fail (CAMEL_IS_IMAP_STORE (store), -1); 3828 g_return_val_if_fail (dest, -1); 3829 3830 *dest = NULL; 3831 3832 /* Check for connectedness. Failed (or cancelled) operations will 3833 * close the connection. We can't expect a read to have any 3834 * meaning if we reconnect, so always set an exception. 3835 */ 3836 3837 if (!camel_disco_store_check_online((CamelDiscoStore *)store, ex)) 3838 return -1; 3839 3840 camel_imap_store_restore_stream_buffer (store); 3841 3842 if (!store->istream) 3843 return -1; 3844 3845 stream = CAMEL_STREAM_BUFFER (store->istream); 3846 3847 ba = g_byte_array_new (); 3848 while ((nread = camel_stream_buffer_gets (stream, linebuf, sizeof (linebuf))) > 0) { 3849 g_byte_array_append (ba, (const guchar*) linebuf, nread); 3850 if (linebuf[nread - 1] == '\n') 3851 break; 3852 } 3853 3854 if (nread <= 0) { 3855 if (errno == EINTR) 3856 { 3857 CamelException mex = CAMEL_EXCEPTION_INITIALISER; 3858 camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL, _("Operation cancelled")); 3859 camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL); 3860 camel_service_connect (CAMEL_SERVICE (store), &mex); 3861 } else { 3862 camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE, 3863 _("Server unexpectedly disconnected: %s"), 3864 g_strerror (errno)); 3865 camel_service_disconnect (CAMEL_SERVICE (store), FALSE, NULL); 3866 } 3867 3868 g_byte_array_free (ba, TRUE); 3869 return -1; 3870 } 3871 3872 if (camel_verbose_debug) { 3873 fprintf (stderr, "received: "); 3874 fwrite (ba->data, 1, ba->len, stderr); 3875 } 3876 3877 /* camel-imap-command.c:imap_read_untagged expects the CRLFs 3878 to be stripped off and be nul-terminated *sigh* */ 3879 nread = ba->len - 1; 3880 ba->data[nread] = '\0'; 3881 if (ba->data[nread - 1] == '\r') { 3882 ba->data[nread - 1] = '\0'; 3883 nread--; 3884 } 3885 3886 *dest = (char *) ba->data; 3887 g_byte_array_free (ba, FALSE); 3888 3889 return nread; 3890 } 3891 3892 ssize_t 3819 3893 camel_imap_store_readline_nb (CamelImapStore *store, char **dest, CamelException *ex) 3820 3894 { trunk/libtinymail-camel/camel-lite/camel/providers/imap/camel-imap-store.h
r2000 r2050 180 180 ssize_t camel_imap_store_readline_nb (CamelImapStore *store, char **dest, CamelException *ex); 181 181 ssize_t camel_imap_store_readline (CamelImapStore *store, char **dest, CamelException *ex); 182 ssize_t camel_imap_store_readline_idle (CamelImapStore *store, char **dest, CamelException *ex); 182 183 gboolean camel_imap_service_connect (CamelService *service, CamelException *ex); 183 184
