From 4a468c2c09e69f053cb3948ec41716e2aa68bd07 Mon Sep 17 00:00:00 2001 From: hiro Date: Mon, 5 Dec 2005 09:21:32 +0000 Subject: imap_cmd_append(): send message contents all at once. git-svn-id: svn://sylpheed.sraoss.jp/sylpheed/trunk@800 ee746299-78ed-0310-b773-934348b2243d --- libsylph/imap.c | 27 +++++++++++++-------- libsylph/utils.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ libsylph/utils.h | 2 ++ 3 files changed, 90 insertions(+), 10 deletions(-) (limited to 'libsylph') diff --git a/libsylph/imap.c b/libsylph/imap.c index 2698581f..b2458adf 100644 --- a/libsylph/imap.c +++ b/libsylph/imap.c @@ -3582,16 +3582,22 @@ static gint imap_cmd_append(IMAPSession *session, const gchar *destfolder, gchar *ret = NULL; gchar buf[BUFFSIZE]; FILE *fp; + FILE *tmp; + size_t read_len; GPtrArray *argbuf; gchar *resp_str; g_return_val_if_fail(file != NULL, IMAP_ERROR); - size = get_file_size_as_crlf(file); if ((fp = g_fopen(file, "rb")) == NULL) { FILE_OP_ERROR(file, "fopen"); return -1; } + tmp = canonicalize_file_stream(fp, &size); + fclose(fp); + if (!tmp) + return -1; + QUOTE_IF_REQUIRED(destfolder_, destfolder); flag_str = imap_get_flag_str(flags); imap_cmd_gen_send(session, "APPEND %s (%s) {%d}", @@ -3602,30 +3608,31 @@ static gint imap_cmd_append(IMAPSession *session, const gchar *destfolder, if (ok != IMAP_SUCCESS || ret[0] != '+' || ret[1] != ' ') { log_warning(_("can't append %s to %s\n"), file, destfolder_); g_free(ret); - fclose(fp); + fclose(tmp); return IMAP_ERROR; } g_free(ret); log_print("IMAP4> %s\n", _("(sending file...)")); - while (fgets(buf, sizeof(buf), fp) != NULL) { - strretchomp(buf); - if (sock_puts(SESSION(session)->sock, buf) < 0) { - fclose(fp); + while ((read_len = fread(buf, 1, sizeof(buf), tmp)) > 0) { + if (read_len < sizeof(buf) && ferror(tmp)) + break; + if (sock_write_all(SESSION(session)->sock, buf, read_len) < 0) { + fclose(tmp); return -1; } } - if (ferror(fp)) { - FILE_OP_ERROR(file, "fgets"); - fclose(fp); + if (ferror(tmp)) { + FILE_OP_ERROR(file, "fread"); + fclose(tmp); return -1; } sock_puts(SESSION(session)->sock, ""); - fclose(fp); + fclose(tmp); if (new_uid != NULL) *new_uid = 0; diff --git a/libsylph/utils.c b/libsylph/utils.c index 8f531967..cfa223a7 100644 --- a/libsylph/utils.c +++ b/libsylph/utils.c @@ -2665,6 +2665,77 @@ gint canonicalize_file_replace(const gchar *file) return 0; } +FILE *canonicalize_file_stream(FILE *src_fp, gint *length) +{ + FILE *dest_fp; + gchar buf[BUFFSIZE]; + gint len; + gint length_ = 0; + gboolean err = FALSE; + gboolean last_linebreak = FALSE; + + if ((dest_fp = my_tmpfile()) == NULL) + return NULL; + + while (fgets(buf, sizeof(buf), src_fp) != NULL) { + gint r = 0; + + len = strlen(buf); + if (len == 0) break; + last_linebreak = FALSE; + + if (buf[len - 1] != '\n') { + last_linebreak = TRUE; + r = fputs(buf, dest_fp); + length_ += len; + } else if (len > 1 && buf[len - 1] == '\n' && buf[len - 2] == '\r') { + r = fputs(buf, dest_fp); + length_ += len; + } else { + if (len > 1) { + r = fwrite(buf, len - 1, 1, dest_fp); + if (r != 1) + r = EOF; + else + length_ += len - 1; + } + if (r != EOF) { + r = fputs("\r\n", dest_fp); + length_ += 2; + } + } + + if (r == EOF) { + g_warning("writing to temporary file failed.\n"); + fclose(dest_fp); + return NULL; + } + } + + if (last_linebreak == TRUE) { + if (fputs("\r\n", dest_fp) == EOF) + err = TRUE; + else + length_ += 2; + } + + if (ferror(src_fp)) { + FILE_OP_ERROR("canonicalize_file_stream", "fgets"); + err = TRUE; + } + + if (err) { + fclose(dest_fp); + return NULL; + } + + if (length) + *length = length_; + + rewind(dest_fp); + return dest_fp; +} + gint uncanonicalize_file(const gchar *src, const gchar *dest) { FILE *src_fp, *dest_fp; diff --git a/libsylph/utils.h b/libsylph/utils.h index 48d9e507..92fd831e 100644 --- a/libsylph/utils.h +++ b/libsylph/utils.h @@ -415,6 +415,8 @@ gchar *canonicalize_str (const gchar *str); gint canonicalize_file (const gchar *src, const gchar *dest); gint canonicalize_file_replace (const gchar *file); +FILE *canonicalize_file_stream (FILE *fp, + gint *length); gint uncanonicalize_file (const gchar *src, const gchar *dest); gint uncanonicalize_file_replace(const gchar *file); -- cgit v1.2.3