masqmail-0.2

annotate src/message.c @ 179:ec3fe72a3e99

Fixed an important bug with folded headers! g_strconcat() returns a *copy* of the string, but hdr->value still pointed to the old header (which probably was a memory leak, too). If the folded part had been quite small it was likely that the new string was at the same position as the old one, thus making everything go well. But if pretty long headers were folded several times it was likely that the new string was allocated somewhere else in memory, thus breaking things. In result mails to lots of recipients (folded header) were frequently only sent to the ones in the first line. Sorry for the inconvenience.
author meillo@marmaro.de
date Fri, 03 Jun 2011 09:52:17 +0200
parents 7f1f364c2a29
children
rev   line source
meillo@0 1 /* MasqMail
meillo@0 2 Copyright (C) 1999-2001 Oliver Kurth
meillo@174 3 Copyright (C) 2010 markus schnalke <meillo@marmaro.de>
meillo@0 4
meillo@0 5 This program is free software; you can redistribute it and/or modify
meillo@0 6 it under the terms of the GNU General Public License as published by
meillo@0 7 the Free Software Foundation; either version 2 of the License, or
meillo@0 8 (at your option) any later version.
meillo@0 9
meillo@0 10 This program is distributed in the hope that it will be useful,
meillo@0 11 but WITHOUT ANY WARRANTY; without even the implied warranty of
meillo@0 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
meillo@0 13 GNU General Public License for more details.
meillo@0 14
meillo@0 15 You should have received a copy of the GNU General Public License
meillo@0 16 along with this program; if not, write to the Free Software
meillo@0 17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
meillo@0 18 */
meillo@0 19
meillo@0 20 #include "masqmail.h"
meillo@0 21
meillo@10 22 message*
meillo@10 23 create_message()
meillo@0 24 {
meillo@10 25 message *msg = (message *) g_malloc(sizeof(message));
meillo@10 26 if (msg) {
meillo@10 27 memset(msg, 0, sizeof(message));
meillo@10 28 msg->data_size = -1;
meillo@10 29 }
meillo@10 30 return msg;
meillo@0 31 }
meillo@0 32
meillo@118 33 /*
meillo@118 34 This function is currently (0.2.24) only used for client side SMTP
meillo@118 35 SIZE support (RFC 1870). The flag is_smtp is always true therefore.
meillo@118 36
meillo@118 37 Their definition of the message size in RFC 1870 is:
meillo@118 38
meillo@118 39 The message size is defined as the number of octets, including
meillo@118 40 CR-LF pairs, but not the SMTP DATA command's terminating dot
meillo@118 41 or doubled quoting dots, to be transmitted by the SMTP client
meillo@118 42 after receiving reply code 354 to the DATA command.
meillo@118 43
meillo@118 44 l_cnt (line count) covers '\r' characters which are not present in
meillo@118 45 masqmail's internal format. Dots are also not stuffed in the
meillo@118 46 internal format. Dot-stuffing is ignored in the size.
meillo@118 47 */
meillo@10 48 gint
meillo@10 49 msg_calc_size(message * msg, gboolean is_smtp)
meillo@0 50 {
meillo@10 51 GList *node;
meillo@118 52 gint l_cnt = 0; /* line count (we need to add so many '\r' for SMTP) */
meillo@118 53 gint c_cnt = 0; /* character count */
meillo@0 54
meillo@118 55 /* message header size */
meillo@10 56 if (msg->hdr_list) {
meillo@10 57 for (node = g_list_first(msg->hdr_list); node; node = g_list_next(node)) {
meillo@10 58 if (node->data) {
meillo@10 59 header *hdr = (header *) (node->data);
meillo@10 60 if (hdr->header) {
meillo@10 61 char *p = hdr->header;
meillo@10 62 while (*p) {
meillo@10 63 if (*p++ == '\n')
meillo@10 64 l_cnt++;
meillo@10 65 c_cnt++;
meillo@10 66 }
meillo@10 67 }
meillo@10 68 }
meillo@10 69 }
meillo@0 70 }
meillo@0 71
meillo@10 72 /* empty line separating headers from data: */
meillo@10 73 c_cnt++;
meillo@10 74 l_cnt++;
meillo@0 75
meillo@118 76 /* message data size */
meillo@10 77 if (msg->data_list) {
meillo@10 78 for (node = g_list_first(msg->data_list); node; node = g_list_next(node)) {
meillo@10 79 if (node->data) {
meillo@10 80 char *p = node->data;
meillo@10 81 while (*p) {
meillo@10 82 if (*p++ == '\n')
meillo@10 83 l_cnt++;
meillo@10 84 c_cnt++;
meillo@10 85 }
meillo@10 86 }
meillo@10 87 }
meillo@0 88 }
meillo@0 89
meillo@10 90 return is_smtp ? c_cnt + l_cnt : c_cnt;
meillo@0 91 }
meillo@0 92
meillo@10 93 void
meillo@10 94 msg_free_data(message * msg)
meillo@0 95 {
meillo@10 96 GList *node;
meillo@0 97
meillo@10 98 if (msg->data_list) {
meillo@10 99 for (node = g_list_first(msg->data_list); node; node = g_list_next(node)) {
meillo@10 100 if (node->data)
meillo@10 101 g_free(node->data);
meillo@10 102 }
meillo@10 103 g_list_free(msg->data_list);
meillo@10 104 msg->data_list = NULL;
meillo@10 105 }
meillo@0 106 }
meillo@0 107
meillo@10 108 void
meillo@10 109 destroy_message(message * msg)
meillo@0 110 {
meillo@10 111 GList *node;
meillo@0 112
meillo@81 113 if (!msg) {
meillo@81 114 return;
meillo@81 115 }
meillo@81 116
meillo@10 117 if (msg->uid)
meillo@10 118 g_free(msg->uid);
meillo@10 119 if (msg->ident)
meillo@10 120 g_free(msg->ident);
meillo@10 121 if (msg->return_path)
meillo@10 122 g_free(msg->return_path);
meillo@0 123
meillo@10 124 if (msg->rcpt_list) {
meillo@10 125 for (node = g_list_first(msg->rcpt_list); node; node = g_list_next(node)) {
meillo@10 126 if (node->data)
meillo@10 127 g_free(node->data);
meillo@10 128 }
meillo@10 129 g_list_free(msg->rcpt_list);
meillo@10 130 }
meillo@10 131 if (msg->hdr_list) {
meillo@10 132 for (node = g_list_first(msg->hdr_list); node; node = g_list_next(node)) {
meillo@10 133 if (node->data) {
meillo@10 134 header *hdr = (header *) (node->data);
meillo@10 135 if (hdr->header)
meillo@10 136 g_free(hdr->header);
meillo@10 137 g_free(node->data);
meillo@10 138 }
meillo@10 139 }
meillo@10 140 g_list_free(msg->hdr_list);
meillo@10 141 }
meillo@0 142
meillo@10 143 if (msg->full_sender_name)
meillo@10 144 g_free(msg->full_sender_name);
meillo@0 145
meillo@10 146 msg_free_data(msg);
meillo@0 147
meillo@10 148 g_free(msg);
meillo@0 149 }
meillo@0 150
meillo@10 151 void
meillo@10 152 destroy_msg_list(GList * msg_list)
meillo@0 153 {
meillo@10 154 GList *msg_node;
meillo@0 155
meillo@10 156 foreach(msg_list, msg_node) {
meillo@10 157 message *msg = (message *) (msg_node->data);
meillo@10 158 destroy_message(msg);
meillo@10 159 }
meillo@10 160 g_list_free(msg_list);
meillo@0 161 }
meillo@0 162
meillo@10 163 msg_out*
meillo@10 164 create_msg_out(message * msg)
meillo@0 165 {
meillo@10 166 msg_out *msgout = NULL;
meillo@0 167
meillo@10 168 msgout = g_malloc(sizeof(msg_out));
meillo@10 169 if (msgout) {
meillo@10 170 msgout->msg = msg;
meillo@10 171 msgout->return_path = NULL;
meillo@10 172 msgout->rcpt_list = NULL;
meillo@10 173
meillo@10 174 msgout->hdr_list = NULL;
meillo@10 175 msgout->xtra_hdr_list = NULL;
meillo@10 176 }
meillo@10 177 return msgout;
meillo@0 178 }
meillo@0 179
meillo@10 180 msg_out*
meillo@10 181 clone_msg_out(msg_out * msgout_orig)
meillo@0 182 {
meillo@10 183 if (msgout_orig) {
meillo@10 184 msg_out *msgout = create_msg_out(msgout_orig->msg);
meillo@10 185 if (msgout) {
meillo@10 186 msgout->msg = msgout_orig->msg;
meillo@10 187 if (msgout_orig->return_path)
meillo@10 188 msgout->return_path = copy_address(msgout_orig->return_path);
meillo@10 189 if (msgout_orig->hdr_list)
meillo@10 190 msgout->hdr_list = g_list_copy(msgout_orig->hdr_list);
meillo@10 191 /* FIXME: if this lives longer than the original
meillo@10 192 and we access one of the xtra hdrs, we will segfault
meillo@10 193 or cause some weird bugs: */
meillo@10 194 msgout->xtra_hdr_list = NULL;
meillo@10 195 if (msgout_orig->rcpt_list)
meillo@10 196 msgout->rcpt_list = g_list_copy(msgout_orig->rcpt_list);
meillo@10 197 }
meillo@10 198 return msgout;
meillo@10 199 }
meillo@10 200 return NULL;
meillo@0 201 }
meillo@0 202
meillo@10 203 GList*
meillo@10 204 create_msg_out_list(GList * msg_list)
meillo@0 205 {
meillo@10 206 GList *msgout_list = NULL;
meillo@10 207 GList *msg_node;
meillo@0 208
meillo@10 209 foreach(msg_list, msg_node) {
meillo@10 210 message *msg = (message *) (msg_node->data);
meillo@10 211 msgout_list = g_list_append(msgout_list, create_msg_out(msg));
meillo@10 212 }
meillo@10 213 return msgout_list;
meillo@0 214 }
meillo@0 215
meillo@10 216 void
meillo@10 217 destroy_msg_out(msg_out * msgout)
meillo@0 218 {
meillo@10 219 if (msgout) {
meillo@10 220 if (msgout->return_path)
meillo@10 221 destroy_address(msgout->return_path);
meillo@10 222 if (msgout->hdr_list)
meillo@10 223 g_list_free(msgout->hdr_list);
meillo@10 224 if (msgout->xtra_hdr_list) {
meillo@10 225 GList *hdr_node;
meillo@10 226 foreach(msgout->xtra_hdr_list, hdr_node) {
meillo@10 227 header *hdr = (header *) (hdr_node->data);
meillo@10 228 destroy_header(hdr);
meillo@10 229 }
meillo@10 230 g_list_free(msgout->xtra_hdr_list);
meillo@10 231 }
meillo@10 232 g_free(msgout);
meillo@10 233 }
meillo@0 234 }
meillo@0 235
meillo@10 236 void
meillo@10 237 destroy_msg_out_list(GList * msgout_list)
meillo@0 238 {
meillo@10 239 GList *msgout_node;
meillo@0 240
meillo@10 241 foreach(msgout_list, msgout_node) {
meillo@10 242 msg_out *msgout = (msg_out *) (msgout_node->data);
meillo@10 243 destroy_msg_out(msgout);
meillo@10 244 }
meillo@10 245 g_list_free(msgout_list);
meillo@0 246 }