Skip to content
Snippets Groups Projects
Commit 340116b4 authored by rswindell's avatar rswindell
Browse files

Bugfix: memory leak in MsgBase.save_msg() - wasn't freeing msg header memory.

MsgBase.save_msg() now supports an optional recipient_list argument (array of
header objects) to send a single message to multiple recipients (e.g. bulkmail).
parent 6b4c4382
Branches
Tags
No related merge requests found
......@@ -112,10 +112,71 @@ js_close(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
return(JS_TRUE);
}
static BOOL parse_header_object(JSContext* cx, private_t* p, JSObject* hdr, smbmsg_t* msg)
static BOOL parse_recipient_object(JSContext* cx, private_t* p, JSObject* hdr, smbmsg_t* msg)
{
char* cp;
char to[256];
ushort nettype;
ushort agent;
int32 i32;
jsval val;
if(JS_GetProperty(cx, hdr, "to", &val) && val!=JSVAL_VOID) {
if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
return(FALSE);
} else {
if(p->smb.status.attr&SMB_EMAIL) /* e-mail */
return(FALSE); /* "to" property required */
cp="All";
}
smb_hfield_str(msg, RECIPIENT, cp);
if(!(p->smb.status.attr&SMB_EMAIL)) {
SAFECOPY(to,cp);
strlwr(to);
msg->idx.to=crc16(to,0);
}
if(JS_GetProperty(cx, hdr, "to_ext", &val) && val!=JSVAL_VOID) {
if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
return(FALSE);
smb_hfield_str(msg, RECIPIENTEXT, cp);
if(p->smb.status.attr&SMB_EMAIL)
msg->idx.to=atoi(cp);
}
if(JS_GetProperty(cx, hdr, "to_org", &val) && val!=JSVAL_VOID) {
if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
return(FALSE);
smb_hfield_str(msg, RECIPIENTORG, cp);
}
if(JS_GetProperty(cx, hdr, "to_net_type", &val) && val!=JSVAL_VOID) {
JS_ValueToInt32(cx,val,&i32);
nettype=(ushort)i32;
smb_hfield(msg, RECIPIENTNETTYPE, sizeof(nettype), &nettype);
if(p->smb.status.attr&SMB_EMAIL && nettype!=NET_NONE)
msg->idx.to=0;
}
if(JS_GetProperty(cx, hdr, "to_net_addr", &val) && val!=JSVAL_VOID) {
if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
return(FALSE);
smb_hfield_str(msg, RECIPIENTNETADDR, cp);
}
if(JS_GetProperty(cx, hdr, "to_agent", &val) && val!=JSVAL_VOID) {
JS_ValueToInt32(cx,val,&i32);
agent=(ushort)i32;
smb_hfield(msg, RECIPIENTAGENT, sizeof(agent), &agent);
}
return(TRUE);
}
static BOOL parse_header_object(JSContext* cx, private_t* p, JSObject* hdr, smbmsg_t* msg
,BOOL recipient)
{
char* cp;
char from[256];
ushort nettype;
ushort type;
......@@ -130,6 +191,9 @@ static BOOL parse_header_object(JSContext* cx, private_t* p, JSObject* hdr, smbm
if(hdr==NULL)
return(FALSE);
if(recipient && !parse_recipient_object(cx,p,hdr,msg))
return(FALSE);
/* Required Header Fields */
if(JS_GetProperty(cx, hdr, "subject", &val) && val!=JSVAL_VOID) {
if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
......@@ -139,21 +203,6 @@ static BOOL parse_header_object(JSContext* cx, private_t* p, JSObject* hdr, smbm
smb_hfield_str(msg, SUBJECT, cp);
msg->idx.subj=subject_crc(cp);
if(JS_GetProperty(cx, hdr, "to", &val) && val!=JSVAL_VOID) {
if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
return(FALSE);
} else {
if(p->smb.status.attr&SMB_EMAIL) /* e-mail */
return(FALSE); /* "to" property required */
cp="All";
}
smb_hfield_str(msg, RECIPIENT, cp);
if(!(p->smb.status.attr&SMB_EMAIL)) {
SAFECOPY(to,cp);
strlwr(to);
msg->idx.to=crc16(to,0);
}
if(JS_GetProperty(cx, hdr, "from", &val) && val!=JSVAL_VOID) {
if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
return(FALSE);
......@@ -225,40 +274,6 @@ static BOOL parse_header_object(JSContext* cx, private_t* p, JSObject* hdr, smbm
smb_hfield(msg, SENDERPORT, sizeof(port), &port);
}
if(JS_GetProperty(cx, hdr, "to_ext", &val) && val!=JSVAL_VOID) {
if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
return(FALSE);
smb_hfield_str(msg, RECIPIENTEXT, cp);
if(p->smb.status.attr&SMB_EMAIL)
msg->idx.to=atoi(cp);
}
if(JS_GetProperty(cx, hdr, "to_org", &val) && val!=JSVAL_VOID) {
if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
return(FALSE);
smb_hfield_str(msg, RECIPIENTORG, cp);
}
if(JS_GetProperty(cx, hdr, "to_net_type", &val) && val!=JSVAL_VOID) {
JS_ValueToInt32(cx,val,&i32);
nettype=(ushort)i32;
smb_hfield(msg, RECIPIENTNETTYPE, sizeof(nettype), &nettype);
if(p->smb.status.attr&SMB_EMAIL && nettype!=NET_NONE)
msg->idx.to=0;
}
if(JS_GetProperty(cx, hdr, "to_net_addr", &val) && val!=JSVAL_VOID) {
if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
return(FALSE);
smb_hfield_str(msg, RECIPIENTNETADDR, cp);
}
if(JS_GetProperty(cx, hdr, "to_agent", &val) && val!=JSVAL_VOID) {
JS_ValueToInt32(cx,val,&i32);
agent=(ushort)i32;
smb_hfield(msg, RECIPIENTAGENT, sizeof(agent), &agent);
}
if(JS_GetProperty(cx, hdr, "replyto", &val) && val!=JSVAL_VOID) {
if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
return(FALSE);
......@@ -898,7 +913,7 @@ js_put_msg_header(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *
JSObject* hdr=NULL;
private_t* p;
*rval = BOOLEAN_TO_JSVAL(JS_FALSE);
*rval = JSVAL_FALSE;
if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
JS_ReportError(cx,getprivate_failure,WHERE);
......@@ -952,13 +967,13 @@ js_put_msg_header(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *
smb_freemsghdrmem(&msg); /* prevent duplicate header fields */
if(!parse_header_object(cx, p, hdr, &msg))
if(!parse_header_object(cx, p, hdr, &msg, TRUE))
break;
if(smb_putmsg(&(p->smb), &msg)!=0)
break;
*rval = BOOLEAN_TO_JSVAL(JS_TRUE);
*rval = JSVAL_TRUE;
} while(0);
smb_unlockmsghdr(&(p->smb),&msg);
......@@ -976,7 +991,7 @@ js_remove_msg(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval
smbmsg_t msg;
private_t* p;
*rval = BOOLEAN_TO_JSVAL(JS_FALSE);
*rval = JSVAL_FALSE;
if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
JS_ReportError(cx,getprivate_failure,WHERE);
......@@ -1031,7 +1046,7 @@ js_remove_msg(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval
if(smb_putmsg(&(p->smb), &msg)!=0)
break;
*rval = BOOLEAN_TO_JSVAL(JS_TRUE);
*rval = JSVAL_TRUE;
} while(0);
smb_unlockmsghdr(&(p->smb),&msg);
......@@ -1243,12 +1258,18 @@ js_save_msg(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
char* body=NULL;
uintN n;
jsuint i;
jsuint rcpt_list_length;
jsval val;
JSObject* hdr=NULL;
JSObject* objarg;
JSObject* rcpt_list=NULL;
smbmsg_t rcpt_msg;
smbmsg_t msg;
jsval open_rval;
private_t* p;
*rval = BOOLEAN_TO_JSVAL(JS_FALSE);
*rval = JSVAL_FALSE;
if(argc<2)
return(JS_TRUE);
......@@ -1268,8 +1289,13 @@ js_save_msg(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
memset(&msg,0,sizeof(msg));
for(n=0;n<argc;n++) {
if(JSVAL_IS_OBJECT(argv[n]))
hdr = JSVAL_TO_OBJECT(argv[n]);
if(JSVAL_IS_OBJECT(argv[n])) {
objarg = JSVAL_TO_OBJECT(argv[n]);
if(JS_IsArrayObject(cx, objarg)) /* recipient_list is an array of objects */
rcpt_list = objarg;
else
hdr = objarg;
}
else if(JSVAL_IS_STRING(argv[n])) {
if((body=JS_GetStringBytes(JSVAL_TO_STRING(argv[n])))==NULL) {
JS_ReportError(cx,"JS_GetStringBytes failed");
......@@ -1281,17 +1307,52 @@ js_save_msg(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
if(hdr==NULL || body==NULL)
return(JS_TRUE);
if(!parse_header_object(cx, p, hdr, &msg))
return(JS_TRUE);
if(rcpt_list!=NULL) {
if(!JS_GetArrayLength(cx, rcpt_list, &rcpt_list_length))
return(JS_TRUE);
if(!rcpt_list_length)
return(JS_TRUE);
}
if(msg.hdr.when_written.time==0) {
msg.hdr.when_written.time=time(NULL);
msg.hdr.when_written.zone=sys_timezone(scfg);
if(parse_header_object(cx, p, hdr, &msg, rcpt_list==NULL)) {
truncsp(body);
if(savemsg(scfg, &(p->smb), &msg, body)==0)
*rval = JSVAL_TRUE;
if(rcpt_list!=NULL) { /* Sending to a list of recipients */
*rval = JSVAL_FALSE; /* failure, by default */
memset(&rcpt_msg, 0, sizeof(rcpt_msg));
for(i=0;i<rcpt_list_length;i++) {
if(!JS_GetElement(cx, rcpt_list, i, &val))
break;
if(!JSVAL_IS_OBJECT(val))
break;
if(smb_copymsgmem(&(p->smb), &rcpt_msg, &msg)!=0)
break;
if(!parse_recipient_object(cx, p, JSVAL_TO_OBJECT(val), &rcpt_msg))
break;
if(smb_addmsghdr(&(p->smb), &rcpt_msg, SMB_SELFPACK)!=0)
break;
smb_freemsgmem(&rcpt_msg);
}
smb_freemsgmem(&rcpt_msg); /* just in case we broke the loop */
if(i==rcpt_list_length)
*rval = JSVAL_TRUE; /* success */
}
}
truncsp(body);
if(savemsg(scfg, &(p->smb), &msg, body)==0)
*rval = BOOLEAN_TO_JSVAL(JS_TRUE);
smb_freemsgmem(&msg);
return(JS_TRUE);
}
......@@ -1514,7 +1575,7 @@ static jsSyncMethodSpec js_msgbase_functions[] = {
,JSDOCSTR("mark message as deleted")
,311
},
{"save_msg", js_save_msg, 2, JSTYPE_BOOLEAN, JSDOCSTR("object header, string body_text")
{"save_msg", js_save_msg, 2, JSTYPE_BOOLEAN, JSDOCSTR("object header, string body_text [,array rcpt_list]")
,JSDOCSTR("create a new message in message base, the <i>header</i> object may contain the following properties:<br>"
"<table>"
"<tr><td><tt>subject</tt><td>Message subject <i>(required)</i>"
......@@ -1563,7 +1624,13 @@ static jsSyncMethodSpec js_msgbase_functions[] = {
"<tr><td><tt>thread_first</tt><td>Number of first reply to this message"
"<tr><td><tt>field_list[].type</tt><td>Other SMB header fields (type)"
"<tr><td><tt>field_list[].data</tt><td>Other SMB header fields (data)"
"</table>")
"</table>"
"<br>"
"The optional <i>rcpt_list</i> is an array of objects that specifies multiple recipients "
"for a single message (e.g. bulk e-mail). Each object in the array may include the following header properties "
"(described above): <br>"
"<i>to</i>, <i>to_ext</i>, <i>to_org</i>, <i>to_net_type</i>, <i>to_net_addr</i>, and <i>to_agent</i>"
)
,310
},
{0}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment