Newer
Older
/* Synchronet JavaScript "MsgBase" Object */
/* $Id$ */
// vi: tabstop=4
/****************************************************************************
* @format.tab-size 4 (Plain Text/Source Code File Header) *
* @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
* *
* Copyright Rob Swindell - http://www.synchro.net/copyright.html *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation; either version 2 *
* of the License, or (at your option) any later version. *
* See the GNU General Public License for more details: gpl.txt or *
* http://www.fsf.org/copyleft/gpl.html *
* *
* Anonymous FTP access to the most recent released source is available at *
* ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
* *
* Anonymous CVS access to the development source and modification history *
* is available at cvs.synchro.net:/cvsroot/sbbs, example: *
* cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login *
* (just hit return, no password is necessary) *
* cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src *
* *
* For Synchronet coding style and modification guidelines, see *
* http://www.synchro.net/source.html *
* *
* You are encouraged to submit any modifications (preferably in Unix diff *
* format) via e-mail to mods@synchro.net *
* *
* Note: If this box doesn't appear square, then you need to fix your tabs. *
****************************************************************************/
#include "sbbs.h"
#include "js_request.h"
#include "userdat.h"
#ifdef JAVASCRIPT
typedef struct
{
smb_t smb;
int status;
BOOL debug;
} private_t;
typedef struct
{
private_t *p;
BOOL expand_fields;
smbmsg_t msg;
} privatemsg_t;
static const char* getprivate_failure = "line %d %s %s JS_GetPrivate failed";
JSBool JS_ValueToUint32(JSContext *cx, jsval v, uint32 *ip)
{
jsdouble d;
if(!JS_ValueToNumber(cx, v, &d))
return JS_FALSE;
*ip = (uint32)d;
return JS_TRUE;
}
/* Destructor */
static void js_finalize_msgbase(JSContext *cx, JSObject *obj)
{
private_t* p;
if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL)
return;
if(SMB_IS_OPEN(&(p->smb)))
smb_close(&(p->smb));
free(p);
JS_SetPrivate(cx, obj, NULL);
}
/* Methods */
static JSBool
js_open(JSContext *cx, uintN argc, jsval *arglist)
JSObject *obj=JS_THIS_OBJECT(cx, arglist);
private_t* p;
if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
JS_ReportError(cx,getprivate_failure,WHERE);
}
JS_SET_RVAL(cx, arglist, JSVAL_FALSE);
if(p->smb.subnum==INVALID_SUB
&& strchr(p->smb.file,'/')==NULL
&& strchr(p->smb.file,'\\')==NULL) {
JS_ReportError(cx,"Unrecognized msgbase code: %s",p->smb.file);
}
rc=JS_SUSPENDREQUEST(cx);
if((p->status=smb_open(&(p->smb)))!=SMB_SUCCESS) {
JS_RESUMEREQUEST(cx, rc);
JS_RESUMEREQUEST(cx, rc);
JS_SET_RVAL(cx, arglist, JSVAL_TRUE);
}
js_close(JSContext *cx, uintN argc, jsval *arglist)
JSObject *obj=JS_THIS_OBJECT(cx, arglist);
if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
JS_ReportError(cx,getprivate_failure,WHERE);
JS_SET_RVAL(cx, arglist, JSVAL_VOID);
rc=JS_SUSPENDREQUEST(cx);
smb_close(&(p->smb));
JS_RESUMEREQUEST(cx, rc);
static BOOL parse_recipient_object(JSContext* cx, private_t* p, JSObject* hdr, smbmsg_t* msg)
char* cp=NULL;
size_t cp_sz=0;
char to[256];
ushort nettype=NET_UNKNOWN;
ushort agent;
int32 i32;
jsval val;
scfg_t* scfg;
scfg = JS_GetRuntimePrivate(JS_GetRuntime(cx));
if(JS_GetProperty(cx, hdr, "to", &val) && !JSVAL_NULL_OR_VOID(val)) {
JSVALUE_TO_RASTRING(cx, val, cp, &cp_sz, NULL);
HANDLE_PENDING(cx, cp);
if(cp==NULL) {
JS_ReportError(cx, "Invalid \"to\" string in recipient object");
return(FALSE);
} else {
if(p->smb.status.attr&SMB_EMAIL) { /* e-mail */
JS_ReportError(cx, "\"to\" property not included in email recipient object");
return(FALSE); /* "to" property required */
}
if((p->status=smb_hfield_str(msg, RECIPIENT, cp))!=SMB_SUCCESS) {
JS_ReportError(cx, "Error %d adding RECIPIENT field to message header", p->status);
return(FALSE);
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) && !JSVAL_NULL_OR_VOID(val)) {
JSVALUE_TO_RASTRING(cx, val, cp, &cp_sz, NULL);
HANDLE_PENDING(cx, cp);
if(cp==NULL) {
JS_ReportError(cx, "Invalid \"to_ext\" string in recipient object");
}
if((p->status=smb_hfield_str(msg, RECIPIENTEXT, cp))!=SMB_SUCCESS) {
JS_ReportError(cx, "Error %d adding RECIPIENTEXT field to message header", p->status);
return(FALSE);
if(p->smb.status.attr&SMB_EMAIL)
msg->idx.to=atoi(cp);
}
if(JS_GetProperty(cx, hdr, "to_org", &val) && !JSVAL_NULL_OR_VOID(val)) {
JSVALUE_TO_RASTRING(cx, val, cp, &cp_sz, NULL);
HANDLE_PENDING(cx, cp);
if(cp==NULL) {
JS_ReportError(cx, "Invalid \"to_org\" string in recipient object");
}
if((p->status=smb_hfield_str(msg, RECIPIENTORG, cp))!=SMB_SUCCESS) {
JS_ReportError(cx, "Error %d adding RECIPIENTORG field to message header", p->status);
return(FALSE);
if(JS_GetProperty(cx, hdr, "to_net_type", &val) && !JSVAL_NULL_OR_VOID(val)) {
if(!JS_ValueToInt32(cx,val,&i32)) {
free(cp);
return(FALSE);
if(JS_GetProperty(cx, hdr, "to_net_addr", &val) && !JSVAL_NULL_OR_VOID(val)) {
JSVALUE_TO_RASTRING(cx, val, cp, &cp_sz, NULL);
HANDLE_PENDING(cx, cp);
if(cp==NULL) {
JS_ReportError(cx, "Invalid \"to_net_addr\" string in recipient object");
if((p->status=smb_hfield_netaddr(msg, RECIPIENTNETADDR, cp, &nettype))!=SMB_SUCCESS) {
JS_ReportError(cx, "Error %d adding RECIPIENTADDR field to message header", p->status);
return(FALSE);
if(nettype!=NET_UNKNOWN && nettype!=NET_NONE) {
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
if(p->smb.status.attr&SMB_EMAIL) {
if(nettype==NET_QWK && msg->idx.to==0) {
char fulladdr[128];
msg->idx.to = qwk_route(scfg, msg->to_net.addr, fulladdr, sizeof(fulladdr)-1);
if(fulladdr[0]==0) {
JS_ReportError(cx, "Unrouteable QWKnet \"to_net_addr\" (%s) in recipient object"
,msg->to_net.addr);
return(FALSE);
}
if((p->status=smb_hfield_str(msg, RECIPIENTNETADDR, fulladdr))!=SMB_SUCCESS) {
JS_ReportError(cx, "Error %d adding RECIPIENTADDR field to message header"
,p->status);
return(FALSE);
}
if(msg->idx.to != 0) {
char ext[32];
sprintf(ext,"%u",msg->idx.to);
if((p->status=smb_hfield_str(msg, RECIPIENTEXT, ext))!=SMB_SUCCESS) {
JS_ReportError(cx, "Error %d adding RECIPIENTEXT field to message header"
,p->status);
return(FALSE);
}
}
} else
msg->idx.to=0;
}
if((p->status=smb_hfield_bin(msg, RECIPIENTNETTYPE, nettype))!=SMB_SUCCESS) {
JS_ReportError(cx, "Error %d adding RECIPIENTNETTYPE field to message header", p->status);
return(FALSE);
if(JS_GetProperty(cx, hdr, "to_agent", &val) && !JSVAL_NULL_OR_VOID(val)) {
if(!JS_ValueToInt32(cx,val,&i32))
return FALSE;
if((p->status=smb_hfield_bin(msg, RECIPIENTAGENT, agent))!=SMB_SUCCESS) {
JS_ReportError(cx, "Error %d adding RECIPIENTAGENT field to message header", p->status);
return(FALSE);
return(TRUE);
}
static BOOL parse_header_object(JSContext* cx, private_t* p, JSObject* hdr, smbmsg_t* msg
,BOOL recipient)
{
char* cp=NULL;
size_t cp_sz=0;
char from[256];
ushort nettype=NET_UNKNOWN;
ushort type;
ushort agent;
int32 i32;
JSObject* array;
JSObject* field;
jsuint i,len;
if(hdr==NULL) {
JS_ReportError(cx, "NULL header object");
if(recipient && !parse_recipient_object(cx,p,hdr,msg))
if(msg->hdr.type != SMB_MSG_TYPE_BALLOT) {
/* Required Header Fields */
if(JS_GetProperty(cx, hdr, "subject", &val) && !JSVAL_NULL_OR_VOID(val)) {
JSVALUE_TO_RASTRING(cx, val, cp, &cp_sz, NULL);
HANDLE_PENDING(cx, cp);
if(cp==NULL) {
JS_ReportError(cx, "Invalid \"subject\" string in header object");
goto err;
}
} else
cp=strdup("");
if((p->status=smb_hfield_str(msg, SUBJECT, cp))!=SMB_SUCCESS) {
JS_ReportError(cx, "Error %d adding SUBJECT field to message header", p->status);
msg->idx.subj=smb_subject_crc(cp);
if(JS_GetProperty(cx, hdr, "from", &val) && !JSVAL_NULL_OR_VOID(val)) {
JSVALUE_TO_RASTRING(cx, val, cp, &cp_sz, NULL);
HANDLE_PENDING(cx, cp);
if(cp==NULL) {
JS_ReportError(cx, "Invalid \"from\" string in header object");
}
} else {
JS_ReportError(cx, "\"from\" property required in header");
goto err; /* "from" property required */
}
if((p->status=smb_hfield_str(msg, SENDER, cp))!=SMB_SUCCESS) {
JS_ReportError(cx, "Error %d adding SENDER field to message header", p->status);
if(!(p->smb.status.attr&SMB_EMAIL) && msg->hdr.type != SMB_MSG_TYPE_BALLOT) {
SAFECOPY(from,cp);
strlwr(from);
msg->idx.from=crc16(from,0);
}
if(JS_GetProperty(cx, hdr, "from_ext", &val) && !JSVAL_NULL_OR_VOID(val)) {
JSVALUE_TO_RASTRING(cx, val, cp, &cp_sz, NULL);
HANDLE_PENDING(cx, cp);
if(cp==NULL) {
JS_ReportError(cx, "Invalid \"from_ext\" string in header object");
}
if((p->status=smb_hfield_str(msg, SENDEREXT, cp))!=SMB_SUCCESS) {
JS_ReportError(cx, "Error %d adding SENDEREXT field to message header", p->status);
if(p->smb.status.attr&SMB_EMAIL)
if(JS_GetProperty(cx, hdr, "from_org", &val) && !JSVAL_NULL_OR_VOID(val)) {
JSVALUE_TO_RASTRING(cx, val, cp, &cp_sz, NULL);
HANDLE_PENDING(cx, cp);
if(cp==NULL) {
JS_ReportError(cx, "Invalid \"from_org\" string in header object");
}
if((p->status=smb_hfield_str(msg, SENDERORG, cp))!=SMB_SUCCESS) {
JS_ReportError(cx, "Error %d adding SENDERORG field to message header", p->status);
if(JS_GetProperty(cx, hdr, "from_net_type", &val) && !JSVAL_NULL_OR_VOID(val)) {
if(!JS_ValueToInt32(cx,val,&i32)) {
goto err;
}
nettype=(ushort)i32;
if(JS_GetProperty(cx, hdr, "from_net_addr", &val) && !JSVAL_NULL_OR_VOID(val)) {
JSVALUE_TO_RASTRING(cx, val, cp, &cp_sz, NULL);
HANDLE_PENDING(cx, cp);
if(cp==NULL) {
JS_ReportError(cx, "Invalid \"from_net_addr\" string in header object");
if((p->status=smb_hfield_netaddr(msg, SENDERNETADDR, cp, &nettype))!=SMB_SUCCESS) {
JS_ReportError(cx, "Error %d adding SENDERNETADDR field to message header", p->status);
}
if(nettype!=NET_UNKNOWN && nettype!=NET_NONE) {
if(p->smb.status.attr&SMB_EMAIL)
msg->idx.from=0;
if((p->status=smb_hfield_bin(msg, SENDERNETTYPE, nettype))!=SMB_SUCCESS) {
JS_ReportError(cx, "Error %d adding SENDERNETTYPE field to message header", p->status);
if(JS_GetProperty(cx, hdr, "from_agent", &val) && !JSVAL_NULL_OR_VOID(val)) {
if(!JS_ValueToInt32(cx,val,&i32))
agent=(ushort)i32;
if((p->status=smb_hfield_bin(msg, SENDERAGENT, agent))!=SMB_SUCCESS) {
JS_ReportError(cx, "Error %d adding SENDERAGENT field to message header", p->status);
if(JS_GetProperty(cx, hdr, "from_ip_addr", &val) && !JSVAL_NULL_OR_VOID(val)) {
JSVALUE_TO_RASTRING(cx, val, cp, &cp_sz, NULL);
HANDLE_PENDING(cx, cp);
if(cp==NULL) {
JS_ReportError(cx, "Invalid \"from_ip_addr\" string in header object");
}
if((p->status=smb_hfield_str(msg, SENDERIPADDR, cp))!=SMB_SUCCESS) {
JS_ReportError(cx, "Error %d adding SENDERIPADDR field to message header", p->status);
if(JS_GetProperty(cx, hdr, "from_host_name", &val) && !JSVAL_NULL_OR_VOID(val)) {
JSVALUE_TO_RASTRING(cx, val, cp, &cp_sz, NULL);
HANDLE_PENDING(cx, cp);
if(cp==NULL) {
JS_ReportError(cx, "Invalid \"from_host_name\" string in header object");
}
if((p->status=smb_hfield_str(msg, SENDERHOSTNAME, cp))!=SMB_SUCCESS) {
JS_ReportError(cx, "Error %d adding SENDERHOSTNAME field to message header", p->status);
if(JS_GetProperty(cx, hdr, "from_protocol", &val) && !JSVAL_NULL_OR_VOID(val)) {
JSVALUE_TO_RASTRING(cx, val, cp, &cp_sz, NULL);
HANDLE_PENDING(cx, cp);
if(cp==NULL) {
JS_ReportError(cx, "Invalid \"from_protocol\" string in header object");
}
if((p->status=smb_hfield_str(msg, SENDERPROTOCOL, cp))!=SMB_SUCCESS) {
JS_ReportError(cx, "Error %d adding SENDERPROTOCOL field to message header", p->status);
}
if(JS_GetProperty(cx, hdr, "from_port", &val) && !JSVAL_NULL_OR_VOID(val)) {
JSVALUE_TO_RASTRING(cx, val, cp, &cp_sz, NULL);
HANDLE_PENDING(cx, cp);
if(cp==NULL) {
JS_ReportError(cx, "Invalid \"from_port\" string in header object");
}
if((p->status=smb_hfield_str(msg, SENDERPORT, cp))!=SMB_SUCCESS) {
JS_ReportError(cx, "Error %d adding SENDERPORT field to message header", p->status);
}
if(JS_GetProperty(cx, hdr, "sender_userid", &val) && !JSVAL_NULL_OR_VOID(val)) {
JSVALUE_TO_RASTRING(cx, val, cp, &cp_sz, NULL);
HANDLE_PENDING(cx, cp);
if(cp==NULL) {
JS_ReportError(cx, "Invalid \"sender_userid\" string in header object");
}
if((p->status=smb_hfield_str(msg, SENDERUSERID, cp))!=SMB_SUCCESS) {
JS_ReportError(cx, "Error %d adding SENDERUSERID field to message header", p->status);
}
}
if(JS_GetProperty(cx, hdr, "sender_server", &val) && !JSVAL_NULL_OR_VOID(val)) {
JSVALUE_TO_RASTRING(cx, val, cp, &cp_sz, NULL);
HANDLE_PENDING(cx, cp);
if(cp==NULL) {
JS_ReportError(cx, "Invalid \"sender_server\" string in header object");
}
if((p->status=smb_hfield_str(msg, SENDERSERVER, cp))!=SMB_SUCCESS) {
JS_ReportError(cx, "Error %d adding SENDERSERVER field to message header", p->status);
}
}
if(JS_GetProperty(cx, hdr, "sender_time", &val) && !JSVAL_NULL_OR_VOID(val)) {
JSVALUE_TO_RASTRING(cx, val, cp, &cp_sz, NULL);
HANDLE_PENDING(cx, cp);
if(cp==NULL) {
JS_ReportError(cx, "Invalid \"sender_time\" string in header object");
}
if((p->status=smb_hfield_str(msg, SENDERTIME, cp))!=SMB_SUCCESS) {
JS_ReportError(cx, "Error %d adding SENDERTIME field to message header", p->status);
}
}
if(JS_GetProperty(cx, hdr, "replyto", &val) && !JSVAL_NULL_OR_VOID(val)) {
JSVALUE_TO_RASTRING(cx, val, cp, &cp_sz, NULL);
HANDLE_PENDING(cx, cp);
if(cp==NULL) {
JS_ReportError(cx, "Invalid \"replyto\" string in header object");
}
if((p->status=smb_hfield_str(msg, REPLYTO, cp))!=SMB_SUCCESS) {
JS_ReportError(cx, "Error %d adding REPLYTO field to message header", p->status);
}
if(JS_GetProperty(cx, hdr, "replyto_ext", &val) && !JSVAL_NULL_OR_VOID(val)) {
JSVALUE_TO_RASTRING(cx, val, cp, &cp_sz, NULL);
HANDLE_PENDING(cx, cp);
if(cp==NULL) {
JS_ReportError(cx, "Invalid \"replyto_ext\" string in header object");
}
if((p->status=smb_hfield_str(msg, REPLYTOEXT, cp))!=SMB_SUCCESS) {
JS_ReportError(cx, "Error %d adding REPLYTOEXT field to message header", p->status);
}
if(JS_GetProperty(cx, hdr, "replyto_org", &val) && !JSVAL_NULL_OR_VOID(val)) {
JSVALUE_TO_RASTRING(cx, val, cp, &cp_sz, NULL);
HANDLE_PENDING(cx, cp);
if(cp==NULL) {
JS_ReportError(cx, "Invalid \"replyto_org\" string in header object");
}
if((p->status=smb_hfield_str(msg, REPLYTOORG, cp))!=SMB_SUCCESS) {
JS_ReportError(cx, "Error %d adding REPLYTOORG field to message header", p->status);
nettype=NET_UNKNOWN;
if(JS_GetProperty(cx, hdr, "replyto_net_type", &val) && !JSVAL_NULL_OR_VOID(val)) {
if(!JS_ValueToInt32(cx,val,&i32))
nettype=(ushort)i32;
if(JS_GetProperty(cx, hdr, "replyto_net_addr", &val) && !JSVAL_NULL_OR_VOID(val)) {
JSVALUE_TO_RASTRING(cx, val, cp, &cp_sz, NULL);
HANDLE_PENDING(cx, cp);
if(cp==NULL) {
JS_ReportError(cx, "Invalid \"replyto_net_addr\" string in header object");
if((p->status=smb_hfield_netaddr(msg, REPLYTONETADDR, cp, &nettype))!=SMB_SUCCESS) {
JS_ReportError(cx, "Error %d adding REPLYTONETADDR field to message header", p->status);
}
if(nettype!=NET_UNKNOWN && nettype!=NET_NONE) {
if((p->status=smb_hfield_bin(msg, REPLYTONETTYPE, nettype))!=SMB_SUCCESS) {
JS_ReportError(cx, "Error %d adding REPLYTONETTYPE field to message header", p->status);
}
if(JS_GetProperty(cx, hdr, "replyto_agent", &val) && !JSVAL_NULL_OR_VOID(val)) {
if(!JS_ValueToInt32(cx,val,&i32))
agent=(ushort)i32;
if((p->status=smb_hfield_bin(msg, REPLYTOAGENT, agent))!=SMB_SUCCESS) {
JS_ReportError(cx, "Error %d adding REPLYTOAGENT field to message header", p->status);
/* RFC822 headers */
if(JS_GetProperty(cx, hdr, "id", &val) && !JSVAL_NULL_OR_VOID(val)) {
JSVALUE_TO_RASTRING(cx, val, cp, &cp_sz, NULL);
HANDLE_PENDING(cx, cp);
if(cp==NULL) {
JS_ReportError(cx, "Invalid \"id\" string in header object");
}
if((p->status=smb_hfield_str(msg, RFC822MSGID, cp))!=SMB_SUCCESS) {
JS_ReportError(cx, "Error %d adding RFC822MSGID field to message header", p->status);
}
if(JS_GetProperty(cx, hdr, "reply_id", &val) && !JSVAL_NULL_OR_VOID(val)) {
JSVALUE_TO_RASTRING(cx, val, cp, &cp_sz, NULL);
HANDLE_PENDING(cx, cp);
if(cp==NULL) {
JS_ReportError(cx, "Invalid \"reply_id\" string in header object");
}
if((p->status=smb_hfield_str(msg, RFC822REPLYID, cp))!=SMB_SUCCESS) {
JS_ReportError(cx, "Error %d adding RFC822REPLYID field to message header", p->status);
}
/* SMTP headers */
if(JS_GetProperty(cx, hdr, "reverse_path", &val) && !JSVAL_NULL_OR_VOID(val)) {
JSVALUE_TO_RASTRING(cx, val, cp, &cp_sz, NULL);
HANDLE_PENDING(cx, cp);
if(cp==NULL) {
JS_ReportError(cx, "Invalid \"reverse_path\" string in header object");
}
if((p->status=smb_hfield_str(msg, SMTPREVERSEPATH, cp))!=SMB_SUCCESS) {
JS_ReportError(cx, "Error %d adding SMTPREVERSEPATH field to message header", p->status);
}
if(JS_GetProperty(cx, hdr, "forward_path", &val) && !JSVAL_NULL_OR_VOID(val)) {
JSVALUE_TO_RASTRING(cx, val, cp, &cp_sz, NULL);
HANDLE_PENDING(cx, cp);
if(cp==NULL) {
JS_ReportError(cx, "Invalid \"forward_path\" string in header object");
}
if((p->status=smb_hfield_str(msg, SMTPFORWARDPATH, cp))!=SMB_SUCCESS) {
JS_ReportError(cx, "Error %d adding SMTPFORWARDPATH field to message header", p->status);
}
/* USENET headers */
if(JS_GetProperty(cx, hdr, "path", &val) && !JSVAL_NULL_OR_VOID(val)) {
JSVALUE_TO_RASTRING(cx, val, cp, &cp_sz, NULL);
HANDLE_PENDING(cx, cp);
if(cp==NULL) {
JS_ReportError(cx, "Invalid \"path\" string in header object");
}
if((p->status=smb_hfield_str(msg, USENETPATH, cp))!=SMB_SUCCESS) {
JS_ReportError(cx, "Error %d adding USENETPATH field to message header", p->status);
}
if(JS_GetProperty(cx, hdr, "newsgroups", &val) && !JSVAL_NULL_OR_VOID(val)) {
JSVALUE_TO_RASTRING(cx, val, cp, &cp_sz, NULL);
HANDLE_PENDING(cx, cp);
if(cp==NULL) {
JS_ReportError(cx, "Invalid \"newsgroups\" string in header object");
}
if((p->status=smb_hfield_str(msg, USENETNEWSGROUPS, cp))!=SMB_SUCCESS) {
JS_ReportError(cx, "Error %d adding USENETNEWSGROUPS field to message header", p->status);
}
/* FTN headers */
if(JS_GetProperty(cx, hdr, "ftn_msgid", &val) && !JSVAL_NULL_OR_VOID(val)) {
JSVALUE_TO_RASTRING(cx, val, cp, &cp_sz, NULL);
HANDLE_PENDING(cx, cp);
if(cp==NULL) {
JS_ReportError(cx, "Invalid \"ftn_msgid\" string in header object");
}
if((p->status=smb_hfield_str(msg, FIDOMSGID, cp))!=SMB_SUCCESS) {
JS_ReportError(cx, "Error %d adding FIDOMSGID field to message header", p->status);
if(JS_GetProperty(cx, hdr, "ftn_reply", &val) && !JSVAL_NULL_OR_VOID(val)) {
JSVALUE_TO_RASTRING(cx, val, cp, &cp_sz, NULL);
HANDLE_PENDING(cx, cp);
if(cp==NULL) {
JS_ReportError(cx, "Invalid \"ftn_reply\" string in header object");
}
if((p->status=smb_hfield_str(msg, FIDOREPLYID, cp))!=SMB_SUCCESS) {
JS_ReportError(cx, "Error %d adding FIDOREPLYID field to message header", p->status);
if(JS_GetProperty(cx, hdr, "ftn_area", &val) && !JSVAL_NULL_OR_VOID(val)) {
JSVALUE_TO_RASTRING(cx, val, cp, &cp_sz, NULL);
HANDLE_PENDING(cx, cp);
if(cp==NULL) {
JS_ReportError(cx, "Invalid \"ftn_area\" string in header object");
}
if((p->status=smb_hfield_str(msg, FIDOAREA, cp))!=SMB_SUCCESS) {
JS_ReportError(cx, "Error %d adding FIDOAREA field to message header", p->status);
if(JS_GetProperty(cx, hdr, "ftn_flags", &val) && !JSVAL_NULL_OR_VOID(val)) {
JSVALUE_TO_RASTRING(cx, val, cp, &cp_sz, NULL);
HANDLE_PENDING(cx, cp);
if(cp==NULL) {
JS_ReportError(cx, "Invalid \"ftn_flags\" string in header object");
}
if((p->status=smb_hfield_str(msg, FIDOFLAGS, cp))!=SMB_SUCCESS) {
JS_ReportError(cx, "Error %d adding FIDOFLAGS field to message header", p->status);
if(JS_GetProperty(cx, hdr, "ftn_pid", &val) && !JSVAL_NULL_OR_VOID(val)) {
JSVALUE_TO_RASTRING(cx, val, cp, &cp_sz, NULL);
HANDLE_PENDING(cx, cp);
if(cp==NULL) {
JS_ReportError(cx, "Invalid \"ftn_pid\" string in header object");
}
if((p->status=smb_hfield_str(msg, FIDOPID, cp))!=SMB_SUCCESS) {
JS_ReportError(cx, "Error %d adding FIDOPID field to message header", p->status);
if(JS_GetProperty(cx, hdr, "ftn_tid", &val) && !JSVAL_NULL_OR_VOID(val)) {
JSVALUE_TO_RASTRING(cx, val, cp, &cp_sz, NULL);
HANDLE_PENDING(cx, cp);
if(cp==NULL) {
JS_ReportError(cx, "Invalid \"ftn_tid\" string in header object");
}
if((p->status=smb_hfield_str(msg, FIDOTID, cp))!=SMB_SUCCESS) {
JS_ReportError(cx, "Error %d adding FIDOTID field to message header", p->status);
}
if(JS_GetProperty(cx, hdr, "date", &val) && !JSVAL_NULL_OR_VOID(val)) {
JSVALUE_TO_RASTRING(cx, val, cp, &cp_sz, NULL);
HANDLE_PENDING(cx, cp);
if(cp==NULL) {
JS_ReportError(cx, "Invalid \"date\" string in header object");
msg->hdr.when_written=rfc822date(cp);
}
if(JS_GetProperty(cx, hdr, "attr", &val) && !JSVAL_NULL_OR_VOID(val)) {
if(!JS_ValueToInt32(cx,val,&i32))
msg->hdr.attr=(ushort)i32;
msg->idx.attr=msg->hdr.attr;
}
if(JS_GetProperty(cx, hdr, "votes", &val) && !JSVAL_NULL_OR_VOID(val)) {
if(!JS_ValueToInt32(cx,val,&i32))
goto err;
msg->hdr.votes=(ushort)i32;
if(msg->hdr.type == SMB_MSG_TYPE_BALLOT)
msg->idx.votes=msg->hdr.votes;
if(JS_GetProperty(cx, hdr, "auxattr", &val) && !JSVAL_NULL_OR_VOID(val)) {
if(JS_GetProperty(cx, hdr, "netattr", &val) && !JSVAL_NULL_OR_VOID(val)) {
if(!JS_ValueToInt32(cx,val,&i32))
msg->hdr.netattr=i32;
}
if(JS_GetProperty(cx, hdr, "when_written_time", &val) && !JSVAL_NULL_OR_VOID(val)) {
if(!JS_ValueToInt32(cx,val,&i32))
msg->hdr.when_written.time=i32;
}
if(JS_GetProperty(cx, hdr, "when_written_zone", &val) && !JSVAL_NULL_OR_VOID(val)) {
if(!JS_ValueToInt32(cx,val,&i32))
msg->hdr.when_written.zone=(short)i32;
}
if(JS_GetProperty(cx, hdr, "when_imported_time", &val) && !JSVAL_NULL_OR_VOID(val)) {
if(!JS_ValueToInt32(cx,val,&i32))
msg->hdr.when_imported.time=i32;
}
if(JS_GetProperty(cx, hdr, "when_imported_zone", &val) && !JSVAL_NULL_OR_VOID(val)) {
if(!JS_ValueToInt32(cx,val,&i32))
msg->hdr.when_imported.zone=(short)i32;
}
if(JS_GetProperty(cx, hdr, "thread_id", &val) && !JSVAL_NULL_OR_VOID(val)) {
if(!JS_ValueToInt32(cx,val,&i32))
msg->hdr.thread_id=i32;
}
if((JS_GetProperty(cx, hdr, "thread_orig", &val) && (!JSVAL_NULL_OR_VOID(val)))
|| (JS_GetProperty(cx, hdr, "thread_back", &val) && !JSVAL_NULL_OR_VOID(val))) {
if(!JS_ValueToInt32(cx,val,&i32))
msg->hdr.thread_back=i32;
if(JS_GetProperty(cx, hdr, "thread_next", &val) && !JSVAL_NULL_OR_VOID(val)) {
if(!JS_ValueToInt32(cx,val,&i32))
msg->hdr.thread_next=i32;
}
if(JS_GetProperty(cx, hdr, "thread_first", &val) && !JSVAL_NULL_OR_VOID(val)) {
if(!JS_ValueToInt32(cx,val,&i32))
msg->hdr.thread_first=i32;
}
if(JS_GetProperty(cx, hdr, "field_list", &val) && JSVAL_IS_OBJECT(val)) {
array=JSVAL_TO_OBJECT(val);
len=0;
if(!JS_GetArrayLength(cx, array, &len)) {
JS_ReportError(cx, "Invalid \"field_list\" array in header object");
for(i=0;i<len;i++) {
if(!JS_GetElement(cx, array, i, &val))
continue;
if(!JSVAL_IS_OBJECT(val))
continue;
field=JSVAL_TO_OBJECT(val);
if(!JS_GetProperty(cx, field, "type", &val))
continue;
JSVALUE_TO_RASTRING(cx, val, cp, &cp_sz, NULL);
HANDLE_PENDING(cx, cp);
else {
if(!JS_ValueToInt32(cx,val,&i32))
type=(ushort)i32;
}
if(!JS_GetProperty(cx, field, "data", &val))
continue;
JSVALUE_TO_RASTRING(cx, val, cp, &cp_sz, NULL);
HANDLE_PENDING(cx, cp);
if(cp==NULL) {
JS_ReportError(cx, "Invalid data string in \"field_list\" array");
}
if((p->status=smb_hfield_str(msg, type, cp))!=SMB_SUCCESS) {
JS_ReportError(cx, "Error %d adding field (type %02Xh) to message header", p->status, type);
}
}
if(msg->hdr.number==0 && JS_GetProperty(cx, hdr, "number", &val) && !JSVAL_NULL_OR_VOID(val)) {
if(!JS_ValueToInt32(cx,val,&i32))
msg->hdr.number=i32;
}
return(TRUE);
err:
if(cp)
free(cp);
return(FALSE);
}
/* obj must've been previously returned from get_msg_header() */
BOOL DLLCALL js_ParseMsgHeaderObject(JSContext* cx, JSObject* obj, smbmsg_t* msg)
{
private_t* p;
if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
JS_ReportError(cx,getprivate_failure,WHERE);
return(FALSE);
}
if(!parse_header_object(cx, p, obj, msg, /* recipient */ TRUE)) {
smb_freemsgmem(msg);
return(FALSE);
}
static BOOL msg_offset_by_id(private_t* p, char* id, int32_t* offset)
{
smbmsg_t msg;
if((p->status=smb_getmsgidx_by_msgid(&(p->smb),&msg,id))!=SMB_SUCCESS)
return(FALSE);
*offset = msg.offset;
return(TRUE);
}
static JSBool
js_get_msg_index(JSContext *cx, uintN argc, jsval *arglist)
JSObject *obj=JS_THIS_OBJECT(cx, arglist);
jsval *argv=JS_ARGV(cx, arglist);
uintN n;
smbmsg_t msg;
JSObject* idxobj;
JSBool by_offset=JS_FALSE;
JSBool include_votes=JS_FALSE;
private_t* p;
JSObject* proto;
JS_SET_RVAL(cx, arglist, JSVAL_NULL);
if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
JS_ReportError(cx,getprivate_failure,WHERE);
}
if(!SMB_IS_OPEN(&(p->smb)))
memset(&msg,0,sizeof(msg));
if(n < argc && JSVAL_IS_BOOLEAN(argv[n]))
by_offset = JSVAL_TO_BOOLEAN(argv[n++]);
for(;n<argc;n++) {
if(JSVAL_IS_BOOLEAN(argv[n]))
include_votes = JSVAL_TO_BOOLEAN(argv[n]);
else if(JSVAL_IS_NUMBER(argv[n])) {
if(by_offset) { /* Get by offset */
if(!JS_ValueToInt32(cx, argv[n], (int32*)&msg.offset))
return JS_FALSE;
}
else { /* Get by number */
if(!JS_ValueToInt32(cx, argv[n], (int32*)&msg.hdr.number))
return JS_FALSE;
}
}
}
rc=JS_SUSPENDREQUEST(cx);
p->status = smb_getmsgidx(&(p->smb), &msg);
JS_RESUMEREQUEST(cx, rc);
if(p->status != SMB_SUCCESS)
return JS_TRUE;
if(!include_votes && (msg.idx.attr&MSG_VOTE))
return JS_TRUE;
if(JS_GetProperty(cx, JS_GetGlobalObject(cx), "MsgBase", &val) && !JSVAL_NULL_OR_VOID(val)) {
JS_ValueToObject(cx,val,&proto);
if(JS_GetProperty(cx, proto, "IndexPrototype", &val) && !JSVAL_NULL_OR_VOID(val))
JS_ValueToObject(cx,val,&proto);
else
proto=NULL;
}
else
proto=NULL;
if((idxobj=JS_NewObject(cx,NULL,proto,obj))==NULL)
val=UINT_TO_JSVAL(msg.idx.number);
JS_DefineProperty(cx, idxobj, "number" ,val
,NULL,NULL,JSPROP_ENUMERATE);
if(msg.idx.attr&MSG_VOTE && !(msg.idx.attr&MSG_POLL)) {
val=UINT_TO_JSVAL(msg.idx.votes);
JS_DefineProperty(cx, idxobj, "votes" ,val
,NULL,NULL,JSPROP_ENUMERATE);
val=UINT_TO_JSVAL(msg.idx.remsg);
JS_DefineProperty(cx, idxobj, "remsg" ,val
,NULL,NULL,JSPROP_ENUMERATE);
} else { /* normal message */
val=UINT_TO_JSVAL(msg.idx.to);
JS_DefineProperty(cx, idxobj, "to" ,val
,NULL,NULL,JSPROP_ENUMERATE);
val=UINT_TO_JSVAL(msg.idx.from);
JS_DefineProperty(cx, idxobj, "from" ,val
,NULL,NULL,JSPROP_ENUMERATE);
val=UINT_TO_JSVAL(msg.idx.subj);
JS_DefineProperty(cx, idxobj, "subject" ,val
,NULL,NULL,JSPROP_ENUMERATE);
}
val=UINT_TO_JSVAL(msg.idx.attr);
JS_DefineProperty(cx, idxobj, "attr" ,val
,NULL,NULL,JSPROP_ENUMERATE);
val=UINT_TO_JSVAL(msg.offset);
JS_DefineProperty(cx, idxobj, "offset" ,val
,NULL,NULL,JSPROP_ENUMERATE);