aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog7
-rw-r--r--ChangeLog.ja8
-rw-r--r--libsylph/session.c54
-rw-r--r--libsylph/session.h6
-rw-r--r--libsylph/smtp.c7
-rw-r--r--libsylph/smtp.h4
-rw-r--r--libsylph/utils.c60
-rw-r--r--libsylph/utils.h1
-rw-r--r--src/send_message.c16
9 files changed, 129 insertions, 34 deletions
diff --git a/ChangeLog b/ChangeLog
index 92fd46f6..dbe5f1fa 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
2005-11-22
+ * libsylph/utils.[ch]
+ libsylph/session.[ch]
+ libsylph/smtp.[ch]
+ src/send_message.c: reduced memory usage on SMTP session.
+
+2005-11-22
+
* libsylph/imap.c: QUOTE_IF_REQUIRED(): add "[]&" to characters to be
quoted (for courier-imap).
diff --git a/ChangeLog.ja b/ChangeLog.ja
index 6ecdfc37..ac4e09ea 100644
--- a/ChangeLog.ja
+++ b/ChangeLog.ja
@@ -1,5 +1,13 @@
2005-11-22
+ * libsylph/utils.[ch]
+ libsylph/session.[ch]
+ libsylph/smtp.[ch]
+ src/send_message.c: SMTP セッションでのメモリ消費量を削減。
+
+
+2005-11-22
+
* libsylph/imap.c: QUOTE_IF_REQUIRED(): "[]&" をクオートする文字に
追加(courier-imap 対策)。
diff --git a/libsylph/session.c b/libsylph/session.c
index 2560c014..7fcc744c 100644
--- a/libsylph/session.c
+++ b/libsylph/session.c
@@ -87,8 +87,8 @@ void session_init(Session *session)
session->write_buf_p = NULL;
session->write_buf_len = 0;
- session->write_data = NULL;
- session->write_data_p = NULL;
+ session->write_data_fp = NULL;
+ session->write_data_pos = 0;
session->write_data_len = 0;
session->timeout_tag = 0;
@@ -377,18 +377,18 @@ static gboolean session_recv_msg_idle_cb(gpointer data)
return FALSE;
}
-gint session_send_data(Session *session, const guchar *data, guint size)
+gint session_send_data(Session *session, FILE *data_fp, guint size)
{
gboolean ret;
- g_return_val_if_fail(session->write_data == NULL, -1);
- g_return_val_if_fail(data != NULL, -1);
+ g_return_val_if_fail(session->write_data_fp == NULL, -1);
+ g_return_val_if_fail(data_fp != NULL, -1);
g_return_val_if_fail(size != 0, -1);
session->state = SESSION_SEND;
- session->write_data = data;
- session->write_data_p = session->write_data;
+ session->write_data_fp = data_fp;
+ session->write_data_pos = 0;
session->write_data_len = size;
g_get_current_time(&session->tv_prev);
@@ -673,19 +673,23 @@ static gint session_write_buf(Session *session)
static gint session_write_data(Session *session)
{
+ gchar buf[SESSION_BUFFSIZE];
gint write_len;
gint to_write_len;
- g_return_val_if_fail(session->write_data != NULL, -1);
- g_return_val_if_fail(session->write_data_p != NULL, -1);
+ g_return_val_if_fail(session->write_data_fp != NULL, -1);
+ g_return_val_if_fail(session->write_data_pos >= 0, -1);
g_return_val_if_fail(session->write_data_len > 0, -1);
- to_write_len = session->write_data_len -
- (session->write_data_p - session->write_data);
+ to_write_len = session->write_data_len - session->write_data_pos;
to_write_len = MIN(to_write_len, SESSION_BUFFSIZE);
+ if (fread(buf, to_write_len, 1, session->write_data_fp) < 1) {
+ g_warning("session_write_data: reading data from file failed\n");
+ session->state = SESSION_ERROR;
+ return -1;
+ }
- write_len = sock_write(session->sock, (gchar *)session->write_data_p,
- to_write_len);
+ write_len = sock_write(session->sock, buf, to_write_len);
if (write_len < 0) {
switch (errno) {
@@ -700,14 +704,21 @@ static gint session_write_data(Session *session)
}
/* incomplete write */
- if (session->write_data_p - session->write_data + write_len <
- session->write_data_len) {
- session->write_data_p += write_len;
+ if (session->write_data_pos + write_len < session->write_data_len) {
+ session->write_data_pos += write_len;
+ if (write_len < to_write_len) {
+ if (fseek(session->write_data_fp,
+ session->write_data_pos, SEEK_SET) < 0) {
+ g_warning("session_write_data: file seek failed\n");
+ session->state = SESSION_ERROR;
+ return -1;
+ }
+ }
return 1;
}
- session->write_data = NULL;
- session->write_data_p = NULL;
+ session->write_data_fp = NULL;
+ session->write_data_pos = 0;
session->write_data_len = 0;
return 0;
@@ -750,8 +761,8 @@ static gboolean session_write_data_cb(SockInfo *source,
gint ret;
g_return_val_if_fail(condition == G_IO_OUT, FALSE);
- g_return_val_if_fail(session->write_data != NULL, FALSE);
- g_return_val_if_fail(session->write_data_p != NULL, FALSE);
+ g_return_val_if_fail(session->write_data_fp != NULL, FALSE);
+ g_return_val_if_fail(session->write_data_pos >= 0, FALSE);
g_return_val_if_fail(session->write_data_len > 0, FALSE);
write_data_len = session->write_data_len;
@@ -771,8 +782,7 @@ static gboolean session_write_data_cb(SockInfo *source,
session_set_timeout(session, session->timeout_interval);
session->send_data_progressive_notify
(session,
- session->write_data_p - session->write_data,
- write_data_len,
+ session->write_data_pos, write_data_len,
session->send_data_progressive_notify_data);
g_get_current_time(&session->tv_prev);
}
diff --git a/libsylph/session.h b/libsylph/session.h
index b1239624..988349d7 100644
--- a/libsylph/session.h
+++ b/libsylph/session.h
@@ -121,8 +121,8 @@ struct _Session
gint write_buf_len;
/* buffer for large data */
- const guchar *write_data;
- const guchar *write_data_p;
+ FILE *write_data_fp;
+ gint write_data_pos;
gint write_data_len;
guint timeout_tag;
@@ -196,7 +196,7 @@ gint session_send_msg (Session *session,
const gchar *msg);
gint session_recv_msg (Session *session);
gint session_send_data (Session *session,
- const guchar *data,
+ FILE *data_fp,
guint size);
gint session_recv_data (Session *session,
guint size,
diff --git a/libsylph/smtp.c b/libsylph/smtp.c
index 896547b5..2ee725ee 100644
--- a/libsylph/smtp.c
+++ b/libsylph/smtp.c
@@ -87,7 +87,7 @@ Session *smtp_session_new(void)
session->to_list = NULL;
session->cur_to = NULL;
- session->send_data = NULL;
+ session->send_data_fp = NULL;
session->send_data_len = 0;
session->avail_auth_type = 0;
@@ -109,7 +109,8 @@ static void smtp_session_destroy(Session *session)
g_free(smtp_session->pass);
g_free(smtp_session->from);
- g_free(smtp_session->send_data);
+ if (smtp_session->send_data_fp)
+ fclose(smtp_session->send_data_fp);
g_free(smtp_session->error_msg);
}
@@ -418,7 +419,7 @@ static gint smtp_send_data(SMTPSession *session)
{
session->state = SMTP_SEND_DATA;
- session_send_data(SESSION(session), session->send_data,
+ session_send_data(SESSION(session), session->send_data_fp,
session->send_data_len);
return SM_OK;
diff --git a/libsylph/smtp.h b/libsylph/smtp.h
index 554d4f04..4bb10b6e 100644
--- a/libsylph/smtp.h
+++ b/libsylph/smtp.h
@@ -101,8 +101,8 @@ struct _SMTPSession
GSList *to_list;
GSList *cur_to;
- guchar *send_data;
- guint send_data_len;
+ FILE *send_data_fp;
+ gint send_data_len;
SMTPAuthType avail_auth_type;
SMTPAuthType forced_auth_type;
diff --git a/libsylph/utils.c b/libsylph/utils.c
index 2d441163..8f531967 100644
--- a/libsylph/utils.c
+++ b/libsylph/utils.c
@@ -2757,6 +2757,66 @@ gchar *normalize_newlines(const gchar *str)
return out;
}
+FILE *get_outgoing_rfc2822_file(FILE *fp)
+{
+ gchar buf[BUFFSIZE];
+ FILE *outfp;
+
+ outfp = my_tmpfile();
+ if (!outfp) {
+ FILE_OP_ERROR("get_outgoing_rfc2822_file", "my_tmpfile");
+ return NULL;
+ }
+
+ /* output header part */
+ while (fgets(buf, sizeof(buf), fp) != NULL) {
+ strretchomp(buf);
+ if (!g_ascii_strncasecmp(buf, "Bcc:", 4)) {
+ gint next;
+
+ for (;;) {
+ next = fgetc(fp);
+ if (next == EOF)
+ break;
+ else if (next != ' ' && next != '\t') {
+ ungetc(next, fp);
+ break;
+ }
+ if (fgets(buf, sizeof(buf), fp) == NULL)
+ break;
+ }
+ } else {
+ if (fputs(buf, outfp) == EOF)
+ goto file_error;
+ if (fputs("\r\n", outfp) == EOF)
+ goto file_error;
+ if (buf[0] == '\0')
+ break;
+ }
+ }
+
+ /* output body part */
+ while (fgets(buf, sizeof(buf), fp) != NULL) {
+ strretchomp(buf);
+ if (buf[0] == '.') {
+ if (fputc('.', outfp) == EOF)
+ goto file_error;
+ }
+ if (fputs(buf, outfp) == EOF)
+ goto file_error;
+ if (fputs("\r\n", outfp) == EOF)
+ goto file_error;
+ }
+
+ rewind(outfp);
+ return outfp;
+
+file_error:
+ g_warning("get_outgoing_rfc2822_file(): writing to temporary file failed.\n");
+ fclose(outfp);
+ return NULL;
+}
+
gchar *get_outgoing_rfc2822_str(FILE *fp)
{
gchar buf[BUFFSIZE];
diff --git a/libsylph/utils.h b/libsylph/utils.h
index b5cb3a76..48d9e507 100644
--- a/libsylph/utils.h
+++ b/libsylph/utils.h
@@ -421,6 +421,7 @@ gint uncanonicalize_file_replace(const gchar *file);
gchar *normalize_newlines (const gchar *str);
+FILE *get_outgoing_rfc2822_file (FILE *fp);
gchar *get_outgoing_rfc2822_str (FILE *fp);
gchar *generate_mime_boundary (const gchar *prefix);
diff --git a/src/send_message.c b/src/send_message.c
index 8072622a..ab67e90a 100644
--- a/src/send_message.c
+++ b/src/send_message.c
@@ -451,7 +451,7 @@ static gint send_message_smtp(PrefsAccount *ac_prefs, GSList *to_list, FILE *fp)
{
Session *session;
SMTPSession *smtp_session;
- gchar *out_str;
+ FILE *out_fp;
gushort port;
SendProgressDialog *dialog;
gchar buf[BUFFSIZE];
@@ -517,9 +517,17 @@ static gint send_message_smtp(PrefsAccount *ac_prefs, GSList *to_list, FILE *fp)
smtp_session->to_list = to_list;
smtp_session->cur_to = to_list;
- out_str = get_outgoing_rfc2822_str(fp);
- smtp_session->send_data = (guchar *)out_str;
- smtp_session->send_data_len = strlen(out_str);
+ out_fp = get_outgoing_rfc2822_file(fp);
+ if (!out_fp) {
+ session_destroy(session);
+ return -1;
+ }
+ smtp_session->send_data_fp = out_fp;
+ smtp_session->send_data_len = get_left_file_size(out_fp);
+ if (smtp_session->send_data_len < 0) {
+ session_destroy(session);
+ return -1;
+ }
#if USE_SSL
port = ac_prefs->set_smtpport ? ac_prefs->smtpport :