--- sbbs/src/sbbs3/js_msgbase.c 2018/04/24 16:41:23 1.1.1.1 +++ sbbs/src/sbbs3/js_msgbase.c 2018/04/24 16:43:37 1.1.1.2 @@ -2,13 +2,13 @@ /* Synchronet JavaScript "MsgBase" Object */ -/* $Id: js_msgbase.c,v 1.1.1.1 2018/04/24 16:41:23 root Exp $ */ +/* $Id: js_msgbase.c,v 1.1.1.2 2018/04/24 16:43:37 root Exp $ */ /**************************************************************************** * @format.tab-size 4 (Plain Text/Source Code File Header) * * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) * * * - * Copyright 2006 Rob Swindell - http://www.synchro.net/copyright.html * + * Copyright 2011 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 * @@ -36,10 +36,11 @@ ****************************************************************************/ #include "sbbs.h" +#include "js_request.h" #ifdef JAVASCRIPT -static scfg_t* scfg=NULL; +static scfg_t* scfg=NULL; typedef struct { @@ -49,6 +50,14 @@ typedef struct } private_t; +typedef struct +{ + private_t *p; + BOOL expand_fields; + smbmsg_t msg; + +} privatemsg_t; + static const char* getprivate_failure = "line %d %s JS_GetPrivate failed"; /* Destructor */ @@ -74,6 +83,7 @@ static JSBool js_open(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { private_t* p; + jsrefcount rc; if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) { JS_ReportError(cx,getprivate_failure,WHERE); @@ -89,8 +99,12 @@ js_open(JSContext *cx, JSObject *obj, ui return(JS_TRUE); } - if((p->status=smb_open(&(p->smb)))!=SMB_SUCCESS) + rc=JS_SUSPENDREQUEST(cx); + if((p->status=smb_open(&(p->smb)))!=SMB_SUCCESS) { + JS_RESUMEREQUEST(cx, rc); return(JS_TRUE); + } + JS_RESUMEREQUEST(cx, rc); *rval = JSVAL_TRUE; return(JS_TRUE); @@ -101,13 +115,16 @@ static JSBool js_close(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { private_t* p; + jsrefcount rc; if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) { JS_ReportError(cx,getprivate_failure,WHERE); return(JS_FALSE); } + rc=JS_SUSPENDREQUEST(cx); smb_close(&(p->smb)); + JS_RESUMEREQUEST(cx, rc); return(JS_TRUE); } @@ -129,6 +146,7 @@ static BOOL parse_recipient_object(JSCon return(FALSE); /* "to" property required */ cp="All"; } + if((p->status=smb_hfield_str(msg, RECIPIENT, cp))!=SMB_SUCCESS) return(FALSE); if(!(p->smb.status.attr&SMB_EMAIL)) { @@ -190,7 +208,6 @@ static BOOL parse_header_object(JSContex ushort nettype=NET_UNKNOWN; ushort type; ushort agent; - ushort port; int32 i32; jsval val; JSObject* array; @@ -291,9 +308,9 @@ static BOOL parse_header_object(JSContex } if(JS_GetProperty(cx, hdr, "from_port", &val) && !JSVAL_NULL_OR_VOID(val)) { - JS_ValueToInt32(cx,val,&i32); - port=(ushort)i32; - if((p->status=smb_hfield_bin(msg, SENDERPORT, port))!=SMB_SUCCESS) + if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL) + return(FALSE); + if((p->status=smb_hfield_str(msg, SENDERPORT, cp))!=SMB_SUCCESS) return(FALSE); } @@ -535,7 +552,7 @@ BOOL DLLCALL js_ParseMsgHeaderObject(JSC return(TRUE); } -static BOOL msg_offset_by_id(private_t* p, char* id, long* offset) +static BOOL msg_offset_by_id(private_t* p, char* id, int32_t* offset) { smbmsg_t msg; @@ -555,6 +572,8 @@ js_get_msg_index(JSContext *cx, JSObject JSObject* idxobj; JSBool by_offset=JS_FALSE; private_t* p; + jsrefcount rc; + JSObject* proto; *rval = JSVAL_NULL; @@ -569,22 +588,37 @@ js_get_msg_index(JSContext *cx, JSObject memset(&msg,0,sizeof(msg)); for(n=0;nstatus=smb_getmsgidx(&(p->smb), &msg))!=SMB_SUCCESS) + rc=JS_SUSPENDREQUEST(cx); + if((p->status=smb_getmsgidx(&(p->smb), &msg))!=SMB_SUCCESS) { + JS_RESUMEREQUEST(cx, rc); return(JS_TRUE); + } + JS_RESUMEREQUEST(cx, rc); break; } } - if((idxobj=JS_NewObject(cx,NULL,NULL,obj))==NULL) + 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) return(JS_TRUE); JS_NewNumberValue(cx, msg.idx.number ,&val); @@ -620,6 +654,298 @@ js_get_msg_index(JSContext *cx, JSObject return(JS_TRUE); } +#define LAZY_INTEGER(PropName, PropValue, flags) \ + if(name==NULL || strcmp(name, (PropName))==0) { \ + JS_NewNumberValue(cx,(PropValue),&v); \ + JS_DefineProperty(cx, obj, (PropName), v, NULL,NULL,flags); \ + if(name) return(JS_TRUE); \ + } + +#define LAZY_INTEGER_EXPAND(PropName, PropValue, flags) \ + if(name==NULL || strcmp(name, (PropName))==0) { \ + if(p->expand_fields || (PropValue)) { \ + JS_NewNumberValue(cx,(PropValue),&v); \ + JS_DefineProperty(cx, obj, (PropName), v, NULL,NULL,flags); \ + if(name) return(JS_TRUE); \ + } \ + else if(name) return(JS_TRUE); \ + } + +#define LAZY_INTEGER_COND(PropName, Condition, PropValue, flags) \ + if(name==NULL || strcmp(name, (PropName))==0) { \ + if(Condition) { \ + JS_NewNumberValue(cx,(PropValue),&v); \ + JS_DefineProperty(cx, obj, (PropName), v, NULL,NULL,flags); \ + if(name) return(JS_TRUE); \ + } \ + else if(name) return(JS_TRUE); \ + } + +#define LAZY_STRING(PropName, PropValue, flags) \ + if(name==NULL || strcmp(name, (PropName))==0) { \ + if((js_str=JS_NewStringCopyZ(cx, (PropValue)))!=NULL) { \ + JS_DefineProperty(cx, obj, PropName, STRING_TO_JSVAL(js_str), NULL, NULL, flags); \ + if(name) return(JS_TRUE); \ + } \ + else if(name) return(JS_TRUE); \ + } + +#define LAZY_STRING_TRUNCSP(PropName, PropValue, flags) \ + if(name==NULL || strcmp(name, (PropName))==0) { \ + if((js_str=JS_NewStringCopyZ(cx, truncsp(PropValue)))!=NULL) { \ + JS_DefineProperty(cx, obj, PropName, STRING_TO_JSVAL(js_str), NULL, NULL, flags); \ + if(name) return(JS_TRUE); \ + } \ + else if(name) return(JS_TRUE); \ + } + +#define LAZY_STRING_COND(PropName, Condition, PropValue, flags) \ + if(name==NULL || strcmp(name, (PropName))==0) { \ + if((Condition) && (js_str=JS_NewStringCopyZ(cx, (PropValue)))!=NULL) { \ + JS_DefineProperty(cx, obj, PropName, STRING_TO_JSVAL(js_str), NULL, NULL, flags); \ + if(name) return(JS_TRUE); \ + } \ + else if(name) return(JS_TRUE); \ + } + +#define LAZY_STRING_TRUNCSP_NULL(PropName, PropValue, flags) \ + if(name==NULL || strcmp(name, (PropName))==0) { \ + if((PropValue) != NULL && (js_str=JS_NewStringCopyZ(cx, truncsp(PropValue)))!=NULL) { \ + JS_DefineProperty(cx, obj, PropName, STRING_TO_JSVAL(js_str), NULL, NULL, flags); \ + if(name) return(JS_TRUE); \ + } \ + else if(name) return(JS_TRUE); \ + } + +static JSBool js_get_msg_header_resolve(JSContext *cx, JSObject *obj, jsval id) +{ + char date[128]; + char msg_id[256]; + char reply_id[256]; + char tmp[128]; + char* val; + int i; + smbmsg_t remsg; + JSObject* array; + JSObject* field; + JSString* js_str; + jsint items; + jsval v; + privatemsg_t* p; + char* name=NULL; + jsrefcount rc; + + if(id != JSVAL_NULL) + name=JS_GetStringBytes(JSVAL_TO_STRING(id)); + + /* If we have already enumerated, we're done here... */ + if((p=(privatemsg_t*)JS_GetPrivate(cx,obj))==NULL) + return(JS_TRUE); + + if((p->msg).hdr.number==0) /* No valid message number/id/offset specified */ + return(JS_TRUE); + + LAZY_INTEGER("number", p->msg.hdr.number, JSPROP_ENUMERATE); + LAZY_INTEGER("offset", p->msg.offset, JSPROP_ENUMERATE); + LAZY_STRING_TRUNCSP("to",p->msg.to, JSPROP_ENUMERATE); + LAZY_STRING_TRUNCSP("from",p->msg.from, JSPROP_ENUMERATE); + LAZY_STRING_TRUNCSP("subject",p->msg.subj, JSPROP_ENUMERATE); + LAZY_STRING_TRUNCSP_NULL("summary", p->msg.summary, JSPROP_ENUMERATE); + LAZY_STRING_TRUNCSP_NULL("to_ext", p->msg.to_ext, JSPROP_ENUMERATE); + LAZY_STRING_TRUNCSP_NULL("from_ext", p->msg.from_ext, JSPROP_ENUMERATE); + LAZY_STRING_TRUNCSP_NULL("from_org", p->msg.from_org, JSPROP_ENUMERATE); + LAZY_STRING_TRUNCSP_NULL("replyto", p->msg.replyto, JSPROP_ENUMERATE); + LAZY_STRING_TRUNCSP_NULL("replyto_ext", p->msg.replyto_ext, JSPROP_ENUMERATE); + LAZY_STRING_TRUNCSP_NULL("reverse_path", p->msg.reverse_path, JSPROP_ENUMERATE); + LAZY_STRING_TRUNCSP_NULL("forward_path", p->msg.forward_path, JSPROP_ENUMERATE); + LAZY_INTEGER_EXPAND("to_agent", p->msg.to_agent, JSPROP_ENUMERATE); + LAZY_INTEGER_EXPAND("from_agent", p->msg.from_agent, JSPROP_ENUMERATE); + LAZY_INTEGER_EXPAND("replyto_agent", p->msg.replyto_agent, JSPROP_ENUMERATE); + LAZY_INTEGER_EXPAND("to_net_type", p->msg.to_net.type, JSPROP_ENUMERATE); + LAZY_STRING_COND("to_net_addr", p->msg.to_net.type && p->msg.to_net.addr, smb_netaddrstr(&(p->msg).to_net,tmp), JSPROP_ENUMERATE); + LAZY_INTEGER_EXPAND("from_net_type", p->msg.from_net.type, JSPROP_ENUMERATE); + /* exception here because p->msg.from_net is NULL */ + LAZY_STRING_COND("from_net_addr", p->msg.from_net.type && p->msg.from_net.addr, smb_netaddrstr(&(p->msg).from_net,tmp), JSPROP_ENUMERATE); + LAZY_INTEGER_EXPAND("replyto_net_type", p->msg.replyto_net.type, JSPROP_ENUMERATE); + LAZY_STRING_COND("replyto_net_addr", p->msg.replyto_net.type && p->msg.replyto_net.addr, smb_netaddrstr(&(p->msg).replyto_net,tmp), JSPROP_ENUMERATE); + LAZY_STRING_COND("from_ip_addr", (val=smb_get_hfield(&(p->msg),SENDERIPADDR,NULL))!=NULL, val, JSPROP_ENUMERATE); + LAZY_STRING_COND("from_host_name", (val=smb_get_hfield(&(p->msg),SENDERHOSTNAME,NULL))!=NULL, val, JSPROP_ENUMERATE); + LAZY_STRING_COND("from_protocol", (val=smb_get_hfield(&(p->msg),SENDERPROTOCOL,NULL))!=NULL, val, JSPROP_ENUMERATE); + LAZY_STRING_COND("from_port", (val=smb_get_hfield(&(p->msg),SENDERPORT,NULL))!=NULL, val, JSPROP_ENUMERATE); + LAZY_INTEGER_EXPAND("forwarded", p->msg.forwarded, JSPROP_ENUMERATE); + LAZY_INTEGER_EXPAND("expiration", p->msg.expiration, JSPROP_ENUMERATE); + LAZY_INTEGER_EXPAND("priority", p->msg.priority, JSPROP_ENUMERATE); + LAZY_INTEGER_EXPAND("cost", p->msg.cost, JSPROP_ENUMERATE); + + /* Fixed length portion of msg header */ + LAZY_INTEGER("type", p->msg.hdr.type, JSPROP_ENUMERATE); + LAZY_INTEGER("version", p->msg.hdr.version, JSPROP_ENUMERATE); + LAZY_INTEGER("attr", p->msg.hdr.attr, JSPROP_ENUMERATE); + LAZY_INTEGER("auxattr", p->msg.hdr.auxattr, JSPROP_ENUMERATE); + LAZY_INTEGER("netattr", p->msg.hdr.netattr, JSPROP_ENUMERATE); + LAZY_INTEGER("when_written_time", p->msg.hdr.when_written.time, JSPROP_ENUMERATE); + LAZY_INTEGER("when_written_zone", p->msg.hdr.when_written.zone, JSPROP_ENUMERATE); + LAZY_INTEGER("when_written_zone_offset", smb_tzutc(p->msg.hdr.when_written.zone), JSPROP_ENUMERATE|JSPROP_READONLY); + LAZY_INTEGER("when_imported_time", p->msg.hdr.when_imported.time, JSPROP_ENUMERATE); + LAZY_INTEGER("when_imported_zone", p->msg.hdr.when_imported.zone, JSPROP_ENUMERATE); + LAZY_INTEGER("when_imported_zone_offset", smb_tzutc(p->msg.hdr.when_imported.zone), JSPROP_ENUMERATE|JSPROP_READONLY); + LAZY_INTEGER("thread_back", p->msg.hdr.thread_back, JSPROP_ENUMERATE); + LAZY_INTEGER("thread_orig", p->msg.hdr.thread_back, JSPROP_ENUMERATE); + LAZY_INTEGER("thread_next", p->msg.hdr.thread_next, JSPROP_ENUMERATE); + LAZY_INTEGER("thread_first", p->msg.hdr.thread_first, JSPROP_ENUMERATE); + LAZY_INTEGER("delivery_attempts", p->msg.hdr.delivery_attempts, JSPROP_ENUMERATE); + LAZY_INTEGER("last_downloaded", p->msg.hdr.last_downloaded, JSPROP_ENUMERATE); + LAZY_INTEGER("times_downloaded", p->msg.hdr.times_downloaded, JSPROP_ENUMERATE); + LAZY_INTEGER("data_length", smb_getmsgdatlen(&(p->msg)), JSPROP_ENUMERATE); + LAZY_STRING("date", msgdate((p->msg).hdr.when_written,date), JSPROP_ENUMERATE); + + if(name==NULL || strcmp(name,"reply_id")==0) { + /* Reply-ID (References) */ + if((p->msg).reply_id!=NULL) + val=(p->msg).reply_id; + else { + reply_id[0]=0; + if(p->expand_fields && (p->msg).hdr.thread_back) { + rc=JS_SUSPENDREQUEST(cx); + memset(&remsg,0,sizeof(remsg)); + remsg.hdr.number=(p->msg).hdr.thread_back; + if(smb_getmsgidx(&(p->p->smb), &remsg)) + SAFEPRINTF(reply_id,"<%s>",p->p->smb.last_error); + else + get_msgid(scfg,p->p->smb.subnum,&remsg,reply_id,sizeof(reply_id)); + JS_RESUMEREQUEST(cx, rc); + } + val=reply_id; + } + if(val[0] && (js_str=JS_NewStringCopyZ(cx,truncsp(val)))!=NULL) { + JS_DefineProperty(cx, obj, "reply_id" + , STRING_TO_JSVAL(js_str) + ,NULL,NULL,JSPROP_ENUMERATE); + if (name) + return(JS_TRUE); + } + else if (name) + return(JS_TRUE); + } + + /* Message-ID */ + if(name==NULL || strcmp(name,"id")==0) { + if(p->expand_fields || (p->msg).id!=NULL) { + get_msgid(scfg,p->p->smb.subnum,&(p->msg),msg_id,sizeof(msg_id)); + val=msg_id; + if((js_str=JS_NewStringCopyZ(cx,truncsp(val)))!=NULL) { + JS_DefineProperty(cx, obj, "id" + ,STRING_TO_JSVAL(js_str) + ,NULL,NULL,JSPROP_ENUMERATE); + if (name) + return(JS_TRUE); + } + else if (name) + return(JS_TRUE); + } + else if (name) + return(JS_TRUE); + } + + /* USENET Fields */ + LAZY_STRING_TRUNCSP_NULL("path", p->msg.path, JSPROP_ENUMERATE); + LAZY_STRING_TRUNCSP_NULL("newsgroups", p->msg.newsgroups, JSPROP_ENUMERATE); + + /* FidoNet Header Fields */ + LAZY_STRING_TRUNCSP_NULL("ftn_msgid", p->msg.ftn_msgid, JSPROP_ENUMERATE); + LAZY_STRING_TRUNCSP_NULL("ftn_reply", p->msg.ftn_reply, JSPROP_ENUMERATE); + LAZY_STRING_TRUNCSP_NULL("ftn_pid", p->msg.ftn_pid, JSPROP_ENUMERATE); + LAZY_STRING_TRUNCSP_NULL("ftn_tid", p->msg.ftn_tid, JSPROP_ENUMERATE); + LAZY_STRING_TRUNCSP_NULL("ftn_area", p->msg.ftn_area, JSPROP_ENUMERATE); + LAZY_STRING_TRUNCSP_NULL("ftn_flags", p->msg.ftn_flags, JSPROP_ENUMERATE); + + if(name==NULL || strcmp(name,"field_list")==0) { + /* Create hdr.field_list[] with repeating header fields (including type and data) */ + if((array=JS_NewArrayObject(cx,0,NULL))!=NULL) { + JS_DefineProperty(cx,obj,"field_list",OBJECT_TO_JSVAL(array) + ,NULL,NULL,JSPROP_ENUMERATE); + items=0; + for(i=0;i<(p->msg).total_hfields;i++) { + switch((p->msg).hfield[i].type) { + case SMB_COMMENT: + case SMB_CARBONCOPY: + case SMB_GROUP: + case FILEATTACH: + case DESTFILE: + case FILEATTACHLIST: + case DESTFILELIST: + case FILEREQUEST: + case FILEPASSWORD: + case FILEREQUESTLIST: + case FILEPASSWORDLIST: + case FIDOCTRL: + case FIDOSEENBY: + case FIDOPATH: + case RFC822HEADER: + case UNKNOWNASCII: + /* only support these header field types */ + break; + default: + /* dupe or possibly binary header field */ + continue; + } + if((field=JS_NewObject(cx,NULL,NULL,array))==NULL) + continue; + JS_DefineProperty(cx,field,"type" + ,INT_TO_JSVAL((p->msg).hfield[i].type) + ,NULL,NULL,JSPROP_ENUMERATE); + if((js_str=JS_NewStringCopyN(cx,(p->msg).hfield_dat[i],(p->msg).hfield[i].length))==NULL) + break; + JS_DefineProperty(cx,field,"data" + ,STRING_TO_JSVAL(js_str) + ,NULL,NULL,JSPROP_ENUMERATE); + JS_DefineElement(cx,array,items,OBJECT_TO_JSVAL(field) + ,NULL,NULL,JSPROP_ENUMERATE); + items++; + } + if (name) + return(JS_TRUE); + } + else if (name) + return(JS_TRUE); + } + + /* DO NOT RETURN JS_FALSE on unknown names */ + /* Doing so will preven toString() among others from working. */ + + return(JS_TRUE); +} + +static JSBool js_get_msg_header_enumerate(JSContext *cx, JSObject *obj) +{ + privatemsg_t* p; + + js_get_msg_header_resolve(cx, obj, JSVAL_NULL); + + if((p=(privatemsg_t*)JS_GetPrivate(cx,obj))==NULL) + return(JS_TRUE); + + smb_freemsgmem(&(p->msg)); + free(p); + + JS_SetPrivate(cx, obj, NULL); + + return(JS_TRUE); +} + +static void js_get_msg_header_finalize(JSContext *cx, JSObject *obj) +{ + privatemsg_t* p; + + if((p=(privatemsg_t*)JS_GetPrivate(cx,obj))==NULL) + return; + + smb_freemsgmem(&(p->msg)); + free(p); + + JS_SetPrivate(cx, obj, NULL); +} + static JSClass js_msghdr_class = { "MsgHeader" /* name */ ,JSCLASS_HAS_PRIVATE /* flags */ @@ -627,53 +953,50 @@ static JSClass js_msghdr_class = { ,JS_PropertyStub /* delProperty */ ,JS_PropertyStub /* getProperty */ ,JS_PropertyStub /* setProperty */ - ,JS_EnumerateStub /* enumerate */ - ,JS_ResolveStub /* resolve */ + ,js_get_msg_header_enumerate /* enumerate */ + ,js_get_msg_header_resolve /* resolve */ ,JS_ConvertStub /* convert */ - ,JS_FinalizeStub /* finalize */ + ,js_get_msg_header_finalize /* finalize */ }; - static JSBool js_get_msg_header(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { - char date[128]; - char msg_id[256]; - char reply_id[256]; - char* val; - ushort* port; - int i; uintN n; - smbmsg_t msg; - smbmsg_t remsg; JSObject* hdrobj; - JSObject* array; - JSObject* field; - JSString* js_str; - jsint items; - jsval v; JSBool by_offset=JS_FALSE; - JSBool expand_fields=JS_TRUE; - private_t* p; + jsrefcount rc; + char* cstr; + privatemsg_t* p; + JSObject* proto; + jsval val; *rval = JSVAL_NULL; - - if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) { + + if((p=(privatemsg_t*)malloc(sizeof(privatemsg_t)))==NULL) { + JS_ReportError(cx,"malloc failed"); + return(JS_FALSE); + } + + memset(p,0,sizeof(privatemsg_t)); + + if((p->p=(private_t*)JS_GetPrivate(cx,obj))==NULL) { JS_ReportError(cx,getprivate_failure,WHERE); return(JS_FALSE); } - if(!SMB_IS_OPEN(&(p->smb))) + if(!SMB_IS_OPEN(&(p->p->smb))) { + free(p); return(JS_TRUE); - - memset(&msg,0,sizeof(msg)); + } /* Parse boolean arguments first */ + p->expand_fields=JS_TRUE; /* This parameter defaults to true */ for(n=0;nexpand_fields=JSVAL_TO_BOOLEAN(argv[n]); else by_offset=JSVAL_TO_BOOLEAN(argv[n]); } @@ -682,353 +1005,67 @@ js_get_msg_header(JSContext *cx, JSObjec for(n=0;nmsg).offset); else /* Get by number */ - JS_ValueToInt32(cx,argv[n],(int32*)&msg.hdr.number); + JS_ValueToInt32(cx,argv[n],(int32*)&(p->msg).hdr.number); - if((p->status=smb_getmsgidx(&(p->smb), &msg))!=SMB_SUCCESS) + rc=JS_SUSPENDREQUEST(cx); + if((p->p->status=smb_getmsgidx(&(p->p->smb), &(p->msg)))!=SMB_SUCCESS) { + JS_RESUMEREQUEST(cx, rc); return(JS_TRUE); + } - if((p->status=smb_lockmsghdr(&(p->smb),&msg))!=SMB_SUCCESS) + if((p->p->status=smb_lockmsghdr(&(p->p->smb),&(p->msg)))!=SMB_SUCCESS) { + JS_RESUMEREQUEST(cx, rc); return(JS_TRUE); + } - if((p->status=smb_getmsghdr(&(p->smb), &msg))!=SMB_SUCCESS) { - smb_unlockmsghdr(&(p->smb),&msg); + if((p->p->status=smb_getmsghdr(&(p->p->smb), &(p->msg)))!=SMB_SUCCESS) { + smb_unlockmsghdr(&(p->p->smb),&(p->msg)); + JS_RESUMEREQUEST(cx, rc); return(JS_TRUE); } - smb_unlockmsghdr(&(p->smb),&msg); + smb_unlockmsghdr(&(p->p->smb),&(p->msg)); + JS_RESUMEREQUEST(cx, rc); break; } else if(JSVAL_IS_STRING(argv[n])) { /* Get by ID */ - if((p->status=smb_getmsghdr_by_msgid(&(p->smb),&msg - ,JS_GetStringBytes(JSVAL_TO_STRING(argv[n]))))!=SMB_SUCCESS) + cstr=JS_GetStringBytes(JSVAL_TO_STRING(argv[n])); + rc=JS_SUSPENDREQUEST(cx); + if((p->p->status=smb_getmsghdr_by_msgid(&(p->p->smb),&(p->msg) + ,cstr))!=SMB_SUCCESS) { + JS_RESUMEREQUEST(cx, rc); return(JS_TRUE); /* ID not found */ + } + JS_RESUMEREQUEST(cx, rc); break; } } - if(msg.hdr.number==0) /* No valid message number/id/offset specified */ + if((p->msg).hdr.number==0) /* No valid message number/id/offset specified */ return(JS_TRUE); - if((hdrobj=JS_NewObject(cx,&js_msghdr_class,NULL,obj))==NULL) { - smb_freemsgmem(&msg); + if(JS_GetProperty(cx, JS_GetGlobalObject(cx), "MsgBase", &val) && !JSVAL_NULL_OR_VOID(val)) { + JS_ValueToObject(cx,val,&proto); + if(JS_GetProperty(cx, proto, "HeaderPrototype", &val) && !JSVAL_NULL_OR_VOID(val)) + JS_ValueToObject(cx,val,&proto); + else + proto=NULL; + } + else + proto=NULL; + + if((hdrobj=JS_NewObject(cx,&js_msghdr_class,proto,obj))==NULL) { + smb_freemsgmem(&(p->msg)); return(JS_TRUE); } if(!JS_SetPrivate(cx, hdrobj, p)) { - smb_freemsgmem(&msg); JS_ReportError(cx,"JS_SetPrivate failed"); + free(p); return(JS_FALSE); } - JS_NewNumberValue(cx,msg.hdr.number,&v); - JS_DefineProperty(cx, hdrobj, "number", v, NULL,NULL,JSPROP_ENUMERATE); - - JS_NewNumberValue(cx,msg.offset,&v); - JS_DefineProperty(cx, hdrobj, "offset", v, NULL,NULL,JSPROP_ENUMERATE); - - if((js_str=JS_NewStringCopyZ(cx,truncsp(msg.to)))==NULL) - return(JS_FALSE); - JS_DefineProperty(cx, hdrobj, "to" - ,STRING_TO_JSVAL(js_str) - ,NULL,NULL,JSPROP_ENUMERATE); - - if((js_str=JS_NewStringCopyZ(cx,truncsp(msg.from)))==NULL) - return(JS_FALSE); - JS_DefineProperty(cx, hdrobj, "from" - ,STRING_TO_JSVAL(js_str) - ,NULL,NULL,JSPROP_ENUMERATE); - - if((js_str=JS_NewStringCopyZ(cx,truncsp(msg.subj)))==NULL) - return(JS_FALSE); - JS_DefineProperty(cx, hdrobj, "subject" - ,STRING_TO_JSVAL(js_str) - ,NULL,NULL,JSPROP_ENUMERATE); - if(msg.summary!=NULL - && (js_str=JS_NewStringCopyZ(cx,truncsp(msg.summary)))!=NULL) - JS_DefineProperty(cx, hdrobj, "summary" - ,STRING_TO_JSVAL(js_str) - ,NULL,NULL,JSPROP_ENUMERATE); - if(msg.to_ext!=NULL - && (js_str=JS_NewStringCopyZ(cx,truncsp(msg.to_ext)))!=NULL) - JS_DefineProperty(cx, hdrobj, "to_ext" - ,STRING_TO_JSVAL(js_str) - ,NULL,NULL,JSPROP_ENUMERATE); - if(msg.from_ext!=NULL - && (js_str=JS_NewStringCopyZ(cx,truncsp(msg.from_ext)))!=NULL) - JS_DefineProperty(cx, hdrobj, "from_ext" - ,STRING_TO_JSVAL(js_str) - ,NULL,NULL,JSPROP_ENUMERATE); - if(msg.from_org!=NULL - && (js_str=JS_NewStringCopyZ(cx,truncsp(msg.from_org)))!=NULL) - JS_DefineProperty(cx, hdrobj, "from_org" - ,STRING_TO_JSVAL(js_str) - ,NULL,NULL,JSPROP_ENUMERATE); - if(msg.replyto!=NULL - && (js_str=JS_NewStringCopyZ(cx,truncsp(msg.replyto)))!=NULL) - JS_DefineProperty(cx, hdrobj, "replyto" - ,STRING_TO_JSVAL(js_str) - ,NULL,NULL,JSPROP_ENUMERATE); - if(msg.replyto_ext!=NULL - && (js_str=JS_NewStringCopyZ(cx,truncsp(msg.replyto_ext)))!=NULL) - JS_DefineProperty(cx, hdrobj, "replyto_ext" - ,STRING_TO_JSVAL(js_str) - ,NULL,NULL,JSPROP_ENUMERATE); - if(msg.reverse_path!=NULL - && (js_str=JS_NewStringCopyZ(cx,truncsp(msg.reverse_path)))!=NULL) - JS_DefineProperty(cx, hdrobj, "reverse_path" - ,STRING_TO_JSVAL(js_str) - ,NULL,NULL,JSPROP_ENUMERATE); - if(msg.forward_path!=NULL - && (js_str=JS_NewStringCopyZ(cx,truncsp(msg.forward_path)))!=NULL) - JS_DefineProperty(cx, hdrobj, "forward_path" - ,STRING_TO_JSVAL(js_str) - ,NULL,NULL,JSPROP_ENUMERATE); - - if(expand_fields || msg.to_agent) - JS_DefineProperty(cx, hdrobj, "to_agent",INT_TO_JSVAL(msg.to_agent) - ,NULL,NULL,JSPROP_ENUMERATE); - if(expand_fields || msg.from_agent) - JS_DefineProperty(cx, hdrobj, "from_agent",INT_TO_JSVAL(msg.from_agent) - ,NULL,NULL,JSPROP_ENUMERATE); - if(expand_fields || msg.replyto_agent) - JS_DefineProperty(cx, hdrobj, "replyto_agent",INT_TO_JSVAL(msg.replyto_agent) - ,NULL,NULL,JSPROP_ENUMERATE); - - if(expand_fields || msg.to_net.type) - JS_DefineProperty(cx, hdrobj, "to_net_type",INT_TO_JSVAL(msg.to_net.type) - ,NULL,NULL,JSPROP_ENUMERATE); - if(msg.to_net.type - && (js_str=JS_NewStringCopyZ(cx,smb_netaddr(&msg.to_net)))!=NULL) - JS_DefineProperty(cx, hdrobj, "to_net_addr" - ,STRING_TO_JSVAL(js_str) - ,NULL,NULL,JSPROP_ENUMERATE); - - if(expand_fields || msg.from_net.type) - JS_DefineProperty(cx, hdrobj, "from_net_type",INT_TO_JSVAL(msg.from_net.type) - ,NULL,NULL,JSPROP_ENUMERATE); - if(msg.from_net.type - && (js_str=JS_NewStringCopyZ(cx,smb_netaddr(&msg.from_net)))!=NULL) - JS_DefineProperty(cx, hdrobj, "from_net_addr" - ,STRING_TO_JSVAL(js_str) - ,NULL,NULL,JSPROP_ENUMERATE); - - - if(expand_fields || msg.replyto_net.type) - JS_DefineProperty(cx, hdrobj, "replyto_net_type",INT_TO_JSVAL(msg.replyto_net.type) - ,NULL,NULL,JSPROP_ENUMERATE); - if(msg.replyto_net.type - && (js_str=JS_NewStringCopyZ(cx,smb_netaddr(&msg.replyto_net)))!=NULL) - JS_DefineProperty(cx, hdrobj, "replyto_net_addr" - ,STRING_TO_JSVAL(js_str) - ,NULL,NULL,JSPROP_ENUMERATE); - - if((val=smb_get_hfield(&msg,SENDERIPADDR,NULL))!=NULL - && (js_str=JS_NewStringCopyZ(cx,val))!=NULL) - JS_DefineProperty(cx, hdrobj, "from_ip_addr" - ,STRING_TO_JSVAL(js_str) - ,NULL,NULL,JSPROP_ENUMERATE); - - if((val=smb_get_hfield(&msg,SENDERHOSTNAME,NULL))!=NULL - && (js_str=JS_NewStringCopyZ(cx,val))!=NULL) - JS_DefineProperty(cx, hdrobj, "from_host_name" - ,STRING_TO_JSVAL(js_str) - ,NULL,NULL,JSPROP_ENUMERATE); - - if((val=smb_get_hfield(&msg,SENDERPROTOCOL,NULL))!=NULL - && (js_str=JS_NewStringCopyZ(cx,val))!=NULL) - JS_DefineProperty(cx, hdrobj, "from_protocol" - ,STRING_TO_JSVAL(js_str) - ,NULL,NULL,JSPROP_ENUMERATE); - - if((port=smb_get_hfield(&msg,SENDERPORT,NULL))!=NULL) - JS_DefineProperty(cx, hdrobj, "from_port" - ,INT_TO_JSVAL(*port) - ,NULL,NULL,JSPROP_ENUMERATE); - - if(expand_fields || msg.forwarded) - JS_DefineProperty(cx, hdrobj, "forwarded",INT_TO_JSVAL(msg.forwarded) - ,NULL,NULL,JSPROP_ENUMERATE); - if(expand_fields || msg.expiration) { - JS_NewNumberValue(cx,msg.expiration,&v); - JS_DefineProperty(cx, hdrobj, "expiration",v,NULL,NULL,JSPROP_ENUMERATE); - } - if(expand_fields || msg.priority) { - JS_NewNumberValue(cx,msg.priority,&v); - JS_DefineProperty(cx, hdrobj, "priority",v,NULL,NULL,JSPROP_ENUMERATE); - } - if(expand_fields || msg.cost) { - JS_NewNumberValue(cx,msg.cost,&v); - JS_DefineProperty(cx, hdrobj, "cost",v,NULL,NULL,JSPROP_ENUMERATE); - } - - /* Fixed length portion of msg header */ - JS_DefineProperty(cx, hdrobj, "type", INT_TO_JSVAL(msg.hdr.type) - ,NULL,NULL,JSPROP_ENUMERATE); - JS_DefineProperty(cx, hdrobj, "version", INT_TO_JSVAL(msg.hdr.version) - ,NULL,NULL,JSPROP_ENUMERATE); - JS_DefineProperty(cx, hdrobj, "attr", INT_TO_JSVAL(msg.hdr.attr) - ,NULL,NULL,JSPROP_ENUMERATE); - JS_NewNumberValue(cx,msg.hdr.auxattr,&v); - JS_DefineProperty(cx, hdrobj, "auxattr", v, NULL,NULL,JSPROP_ENUMERATE); - JS_NewNumberValue(cx,msg.hdr.netattr,&v); - JS_DefineProperty(cx, hdrobj, "netattr", v, NULL,NULL,JSPROP_ENUMERATE); - - JS_NewNumberValue(cx,msg.hdr.when_written.time,&v); - JS_DefineProperty(cx, hdrobj, "when_written_time", v, NULL,NULL,JSPROP_ENUMERATE); - JS_NewNumberValue(cx,msg.hdr.when_written.zone,&v); - JS_DefineProperty(cx, hdrobj, "when_written_zone", v, NULL,NULL,JSPROP_ENUMERATE); - JS_NewNumberValue(cx,msg.hdr.when_imported.time,&v); - JS_DefineProperty(cx, hdrobj, "when_imported_time", v, NULL,NULL,JSPROP_ENUMERATE); - JS_NewNumberValue(cx,msg.hdr.when_imported.zone,&v); - JS_DefineProperty(cx, hdrobj, "when_imported_zone", v, NULL,NULL,JSPROP_ENUMERATE); - - JS_NewNumberValue(cx,msg.hdr.thread_back,&v); - JS_DefineProperty(cx, hdrobj, "thread_back", v, NULL,NULL,JSPROP_ENUMERATE); - JS_DefineProperty(cx, hdrobj, "thread_orig", v, NULL,NULL,0); - JS_NewNumberValue(cx,msg.hdr.thread_next,&v); - JS_DefineProperty(cx, hdrobj, "thread_next", v, NULL,NULL,JSPROP_ENUMERATE); - JS_NewNumberValue(cx,msg.hdr.thread_first,&v); - JS_DefineProperty(cx, hdrobj, "thread_first", v, NULL,NULL,JSPROP_ENUMERATE); - - JS_NewNumberValue(cx,msg.hdr.delivery_attempts,&v); - JS_DefineProperty(cx, hdrobj, "delivery_attempts", v, NULL,NULL,JSPROP_ENUMERATE); - JS_NewNumberValue(cx,msg.hdr.last_downloaded,&v); - JS_DefineProperty(cx, hdrobj, "last_downloaded", v, NULL,NULL,JSPROP_ENUMERATE); - JS_NewNumberValue(cx,msg.hdr.times_downloaded,&v); - JS_DefineProperty(cx, hdrobj, "times_downloaded", v, NULL,NULL,JSPROP_ENUMERATE); - - JS_NewNumberValue(cx,smb_getmsgdatlen(&msg),&v); - JS_DefineProperty(cx, hdrobj, "data_length", v, NULL,NULL,JSPROP_ENUMERATE); - - if((js_str=JS_NewStringCopyZ(cx,msgdate(msg.hdr.when_written,date)))==NULL) - return(JS_FALSE); - JS_DefineProperty(cx, hdrobj, "date" - ,STRING_TO_JSVAL(js_str) - ,NULL,NULL,JSPROP_ENUMERATE); - - /* Reply-ID (References) */ - if(msg.reply_id!=NULL) - val=msg.reply_id; - else { - reply_id[0]=0; - if(expand_fields && msg.hdr.thread_back) { - memset(&remsg,0,sizeof(remsg)); - remsg.hdr.number=msg.hdr.thread_back; - if(smb_getmsgidx(&(p->smb), &remsg)) - sprintf(reply_id,"<%s>",p->smb.last_error); - else - SAFECOPY(reply_id,get_msgid(scfg,p->smb.subnum,&remsg)); - } - val=reply_id; - } - if(val[0] && (js_str=JS_NewStringCopyZ(cx,truncsp(val)))!=NULL) - JS_DefineProperty(cx, hdrobj, "reply_id" - , STRING_TO_JSVAL(js_str) - ,NULL,NULL,JSPROP_ENUMERATE); - - /* Message-ID */ - if(expand_fields || msg.id!=NULL) { - SAFECOPY(msg_id,get_msgid(scfg,p->smb.subnum,&msg)); - val=msg_id; - if((js_str=JS_NewStringCopyZ(cx,truncsp(val)))==NULL) - return(JS_FALSE); - JS_DefineProperty(cx, hdrobj, "id" - ,STRING_TO_JSVAL(js_str) - ,NULL,NULL,JSPROP_ENUMERATE); - } - - /* USENET Fields */ - if(msg.path!=NULL - && (js_str=JS_NewStringCopyZ(cx,truncsp(msg.path)))!=NULL) - JS_DefineProperty(cx, hdrobj, "path" - ,STRING_TO_JSVAL(js_str) - ,NULL,NULL,JSPROP_ENUMERATE); - if(msg.newsgroups!=NULL - && (js_str=JS_NewStringCopyZ(cx,truncsp(msg.newsgroups)))!=NULL) - JS_DefineProperty(cx, hdrobj, "newsgroups" - ,STRING_TO_JSVAL(js_str) - ,NULL,NULL,JSPROP_ENUMERATE); - - /* FidoNet Header Fields */ - if(msg.ftn_msgid!=NULL - && (js_str=JS_NewStringCopyZ(cx,truncsp(msg.ftn_msgid)))!=NULL) - JS_DefineProperty(cx, hdrobj, "ftn_msgid" - ,STRING_TO_JSVAL(js_str) - ,NULL,NULL,JSPROP_ENUMERATE); - if(msg.ftn_reply!=NULL - && (js_str=JS_NewStringCopyZ(cx,truncsp(msg.ftn_reply)))!=NULL) - JS_DefineProperty(cx, hdrobj, "ftn_reply" - ,STRING_TO_JSVAL(js_str) - ,NULL,NULL,JSPROP_ENUMERATE); - if(msg.ftn_pid!=NULL - && (js_str=JS_NewStringCopyZ(cx,truncsp(msg.ftn_pid)))!=NULL) - JS_DefineProperty(cx, hdrobj, "ftn_pid" - ,STRING_TO_JSVAL(js_str) - ,NULL,NULL,JSPROP_ENUMERATE); - if(msg.ftn_tid!=NULL - && (js_str=JS_NewStringCopyZ(cx,truncsp(msg.ftn_tid)))!=NULL) - JS_DefineProperty(cx, hdrobj, "ftn_tid" - ,STRING_TO_JSVAL(js_str) - ,NULL,NULL,JSPROP_ENUMERATE); - if(msg.ftn_area!=NULL - && (js_str=JS_NewStringCopyZ(cx,truncsp(msg.ftn_area)))!=NULL) - JS_DefineProperty(cx, hdrobj, "ftn_area" - ,STRING_TO_JSVAL(js_str) - ,NULL,NULL,JSPROP_ENUMERATE); - if(msg.ftn_flags!=NULL - && (js_str=JS_NewStringCopyZ(cx,truncsp(msg.ftn_flags)))!=NULL) - JS_DefineProperty(cx, hdrobj, "ftn_flags" - ,STRING_TO_JSVAL(js_str) - ,NULL,NULL,JSPROP_ENUMERATE); - - /* Create hdr.field_list[] with repeating header fields (including type and data) */ - if((array=JS_NewArrayObject(cx,0,NULL))!=NULL) { - JS_DefineProperty(cx,hdrobj,"field_list",OBJECT_TO_JSVAL(array) - ,NULL,NULL,JSPROP_ENUMERATE); - items=0; - for(i=0;istatus=smb_getmsgidx(&(p->smb), &msg))!=SMB_SUCCESS) + rc=JS_SUSPENDREQUEST(cx); + if((p->status=smb_getmsgidx(&(p->smb), &msg))!=SMB_SUCCESS) { + JS_RESUMEREQUEST(cx, rc); return(JS_TRUE); + } - if((p->status=smb_lockmsghdr(&(p->smb),&msg))!=SMB_SUCCESS) + if((p->status=smb_lockmsghdr(&(p->smb),&msg))!=SMB_SUCCESS) { + JS_RESUMEREQUEST(cx, rc); return(JS_TRUE); + } do { if((p->status=smb_getmsghdr(&(p->smb), &msg))!=SMB_SUCCESS) @@ -1098,10 +1147,12 @@ js_put_msg_header(JSContext *cx, JSObjec smb_freemsghdrmem(&msg); /* prevent duplicate header fields */ + JS_RESUMEREQUEST(cx, rc); if(!parse_header_object(cx, p, hdr, &msg, TRUE)) { - sprintf(p->smb.last_error,"Header parsing failure (required field missing?)"); + SAFECOPY(p->smb.last_error,"Header parsing failure (required field missing?)"); break; } + rc=JS_SUSPENDREQUEST(cx); if((p->status=smb_putmsg(&(p->smb), &msg))!=SMB_SUCCESS) break; @@ -1111,6 +1162,7 @@ js_put_msg_header(JSContext *cx, JSObjec smb_unlockmsghdr(&(p->smb),&msg); smb_freemsgmem(&msg); + JS_RESUMEREQUEST(cx, rc); return(JS_TRUE); } @@ -1123,6 +1175,8 @@ js_remove_msg(JSContext *cx, JSObject *o JSBool msg_specified=JS_FALSE; smbmsg_t msg; private_t* p; + char* cstr; + jsrefcount rc; *rval = JSVAL_FALSE; @@ -1148,10 +1202,15 @@ js_remove_msg(JSContext *cx, JSObject *o n++; break; } else if(JSVAL_IS_STRING(argv[n])) { /* Get by ID */ + cstr=JS_GetStringBytes(JSVAL_TO_STRING(argv[n])); + rc=JS_SUSPENDREQUEST(cx); if(!msg_offset_by_id(p - ,JS_GetStringBytes(JSVAL_TO_STRING(argv[n])) - ,&msg.offset)) + ,cstr + ,&msg.offset)) { + JS_RESUMEREQUEST(cx, rc); return(JS_TRUE); /* ID not found */ + } + JS_RESUMEREQUEST(cx, rc); msg_specified=JS_TRUE; n++; break; @@ -1161,6 +1220,7 @@ js_remove_msg(JSContext *cx, JSObject *o if(!msg_specified) return(JS_TRUE); + rc=JS_SUSPENDREQUEST(cx); if((p->status=smb_getmsgidx(&(p->smb), &msg))==SMB_SUCCESS && (p->status=smb_getmsghdr(&(p->smb), &msg))==SMB_SUCCESS) { @@ -1171,6 +1231,7 @@ js_remove_msg(JSContext *cx, JSObject *o } smb_freemsgmem(&msg); + JS_RESUMEREQUEST(cx, rc); return(JS_TRUE); } @@ -1199,20 +1260,8 @@ static char* get_msg_text(private_t* p, smb_unlockmsghdr(&(p->smb), msg); smb_freemsgmem(msg); - if(strip_ctrl_a) { - char* newbuf; - if((newbuf=malloc(strlen(buf)+1))!=NULL) { - int i,j; - for(i=j=0;buf[i];i++) { - if(buf[i]==CTRL_A && buf[i+1]!=0) - i++; - else newbuf[j++]=buf[i]; - } - newbuf[j]=0; - strcpy(buf,newbuf); - free(newbuf); - } - } + if(strip_ctrl_a) + remove_ctrl_a(buf, buf); if(rfc822) { /* must escape lines starting with dot ('.') */ char* newbuf; @@ -1245,6 +1294,8 @@ js_get_msg_body(JSContext *cx, JSObject JSBool msg_specified=JS_FALSE; JSString* js_str; private_t* p; + char* cstr; + jsrefcount rc; *rval = JSVAL_NULL; @@ -1270,10 +1321,15 @@ js_get_msg_body(JSContext *cx, JSObject n++; break; } else if(JSVAL_IS_STRING(argv[n])) { /* Get by ID */ + cstr=JS_GetStringBytes(JSVAL_TO_STRING(argv[n])); + rc=JS_SUSPENDREQUEST(cx); if(!msg_offset_by_id(p - ,JS_GetStringBytes(JSVAL_TO_STRING(argv[n])) - ,&msg.offset)) + ,cstr + ,&msg.offset)) { + JS_RESUMEREQUEST(cx, rc); return(JS_TRUE); /* ID not found */ + } + JS_RESUMEREQUEST(cx, rc); msg_specified=JS_TRUE; n++; break; @@ -1292,7 +1348,9 @@ js_get_msg_body(JSContext *cx, JSObject if(nname,"Client")==0) { client=JS_GetPrivate(cx,objarg); @@ -1450,41 +1517,43 @@ js_save_msg(JSContext *cx, JSObject *obj if(body[0]) truncsp(body); - if(savemsg(scfg, &(p->smb), &msg, client, body)==0) + if((p->status=savemsg(scfg, &(p->smb), &msg, client, /* ToDo server hostname: */NULL, body))==SMB_SUCCESS) { *rval = JSVAL_TRUE; - if(rcpt_list!=NULL) { /* Sending to a list of recipients */ + if(rcpt_list!=NULL) { /* Sending to a list of recipients */ - *rval = JSVAL_FALSE; /* failure, by default */ + *rval = JSVAL_FALSE; /* failure, by default */ + SAFECOPY(p->smb.last_error,"Recipient list parsing failure"); - memset(&rcpt_msg, 0, sizeof(rcpt_msg)); + memset(&rcpt_msg, 0, sizeof(rcpt_msg)); - for(i=0;istatus=smb_copymsgmem(&(p->smb), &rcpt_msg, &msg))!=SMB_SUCCESS) - break; + if((p->status=smb_copymsgmem(&(p->smb), &rcpt_msg, &msg))!=SMB_SUCCESS) + break; - if(!parse_recipient_object(cx, p, JSVAL_TO_OBJECT(val), &rcpt_msg)) - break; + if(!parse_recipient_object(cx, p, JSVAL_TO_OBJECT(val), &rcpt_msg)) + break; - if((p->status=smb_addmsghdr(&(p->smb), &rcpt_msg, SMB_SELFPACK))!=SMB_SUCCESS) - break; + if((p->status=smb_addmsghdr(&(p->smb), &rcpt_msg, SMB_SELFPACK))!=SMB_SUCCESS) + break; - smb_freemsgmem(&rcpt_msg); - } - smb_freemsgmem(&rcpt_msg); /* just in case we broke the loop */ + smb_freemsgmem(&rcpt_msg); + } + smb_freemsgmem(&rcpt_msg); /* just in case we broke the loop */ - if(i==rcpt_list_length) - *rval = JSVAL_TRUE; /* success */ + if(i==rcpt_list_length) + *rval = JSVAL_TRUE; /* success */ + } } } else - sprintf(p->smb.last_error,"Header parsing failure (required field missing?)"); + SAFECOPY(p->smb.last_error,"Header parsing failure (required field missing?)"); smb_freemsgmem(&msg); @@ -1544,6 +1613,7 @@ static JSBool js_msgbase_get(JSContext * jsint tiny; idxrec_t idx; private_t* p; + jsrefcount rc; if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) { JS_ReportError(cx,getprivate_failure,WHERE); @@ -1572,16 +1642,22 @@ static JSBool js_msgbase_get(JSContext * *vp = INT_TO_JSVAL(p->debug); break; case SMB_PROP_FIRST_MSG: + rc=JS_SUSPENDREQUEST(cx); memset(&idx,0,sizeof(idx)); smb_getfirstidx(&(p->smb),&idx); + JS_RESUMEREQUEST(cx, rc); JS_NewNumberValue(cx,idx.number,vp); break; case SMB_PROP_LAST_MSG: + rc=JS_SUSPENDREQUEST(cx); smb_getstatus(&(p->smb)); + JS_RESUMEREQUEST(cx, rc); JS_NewNumberValue(cx,p->smb.status.last_msg,vp); break; case SMB_PROP_TOTAL_MSGS: + rc=JS_SUSPENDREQUEST(cx); smb_getstatus(&(p->smb)); + JS_RESUMEREQUEST(cx, rc); JS_NewNumberValue(cx,p->smb.status.total_msgs,vp); break; case SMB_PROP_MAX_CRCS: @@ -1652,26 +1728,12 @@ static char* msgbase_prop_desc[] = { ,"maximum number of messages before expiration - READ ONLY" ,"maximum age (in days) of messages to store - READ ONLY" ,"message base attributes - READ ONLY" - ,"sub-board number (0-based, -1 for e-mail) - READ ONLY" + ,"sub-board number (0-based, 65535 for e-mail) - READ ONLY" ,"true if the message base has been opened successfully - READ ONLY" ,NULL }; #endif - -static JSClass js_msgbase_class = { - "MsgBase" /* name */ - ,JSCLASS_HAS_PRIVATE /* flags */ - ,JS_PropertyStub /* addProperty */ - ,JS_PropertyStub /* delProperty */ - ,js_msgbase_get /* getProperty */ - ,js_msgbase_set /* setProperty */ - ,JS_EnumerateStub /* enumerate */ - ,JS_ResolveStub /* resolve */ - ,JS_ConvertStub /* convert */ - ,js_finalize_msgbase /* finalize */ -}; - static jsSyncMethodSpec js_msgbase_functions[] = { {"open", js_open, 0, JSTYPE_BOOLEAN, JSDOCSTR("") ,JSDOCSTR("open message base") @@ -1693,7 +1755,7 @@ static jsSyncMethodSpec js_msgbase_funct }, {"get_msg_body", js_get_msg_body, 2, JSTYPE_STRING, JSDOCSTR("[by_offset=false,] number_or_id [,strip_ctrl_a=false] " "[,rfc822_encoded=false] [,include_tails=true]") - ,JSDOCSTR("returns the body text of a specific message, null on failure. " + ,JSDOCSTR("returns the entire body text of a specific message as a single String, null on failure. " "The default behavior is to leave Ctrl-A codes intact, perform no RFC-822 encoding, and to include tails (if any) in the " "returned body text." ) @@ -1764,9 +1826,11 @@ static jsSyncMethodSpec js_msgbase_funct "auxattrAuxillary attribute bitfield" "netattrNetwork attribute bitfield" "when_written_timeDate/time (in time_t format)" - "when_written_zoneTime zone" + "when_written_zoneTime zone (in SMB format)" + "when_written_zone_offsetTime zone in minutes east of UTC" "when_imported_timeDate/time message was imported" - "when_imported_zoneTime zone" + "when_imported_zoneTime zone (in SMB format)" + "when_imported_zone_offsetTime zone in minutes east of UTC" "thread_backMessage number that this message is a reply to" "thread_nextMessage number of the next reply to the original message in this thread" "thread_firstMessage number of the first reply to this message" @@ -1787,6 +1851,34 @@ static jsSyncMethodSpec js_msgbase_funct {0} }; +static JSBool js_msgbase_resolve(JSContext *cx, JSObject *obj, jsval id) +{ + char* name=NULL; + + if(id != JSVAL_NULL) + name=JS_GetStringBytes(JSVAL_TO_STRING(id)); + + return(js_SyncResolve(cx, obj, name, js_msgbase_properties, js_msgbase_functions, NULL, 0)); +} + +static JSBool js_msgbase_enumerate(JSContext *cx, JSObject *obj) +{ + return(js_msgbase_resolve(cx, obj, JSVAL_NULL)); +} + +static JSClass js_msgbase_class = { + "MsgBase" /* name */ + ,JSCLASS_HAS_PRIVATE /* flags */ + ,JS_PropertyStub /* addProperty */ + ,JS_PropertyStub /* delProperty */ + ,js_msgbase_get /* getProperty */ + ,js_msgbase_set /* setProperty */ + ,js_msgbase_enumerate /* enumerate */ + ,js_msgbase_resolve /* resolve */ + ,JS_ConvertStub /* convert */ + ,js_finalize_msgbase /* finalize */ +}; + /* MsgBase Constructor (open message base) */ static JSBool @@ -1816,11 +1908,6 @@ js_msgbase_constructor(JSContext *cx, JS return(JS_FALSE); } - if(!js_DefineSyncProperties(cx,obj,js_msgbase_properties)) { - free(p); - return(JS_FALSE); - } - #ifdef BUILD_JSDOCS js_DescribeSyncObject(cx,obj,"Class used for accessing message bases",310); js_DescribeSyncConstructor(cx,obj,"To create a new MsgBase object: " @@ -1836,6 +1923,132 @@ js_msgbase_constructor(JSContext *cx, JS for(p->smb.subnum=0;p->smb.subnumtotal_subs;p->smb.subnum++) { if(!stricmp(scfg->sub[p->smb.subnum]->code,base)) /* null ptr dereference here Apr-16-2003 */ break; /* and again, Aug-18-2004 upon recycle */ +/* One more time, Mon Jan 26 22:44:23 PST 2009 */ +/* +#0 0x282d61b6 in js_msgbase_constructor (cx=0x288bf180, obj=0x29e39460, argc=1, argv=0x28e7413c, rval=0xbf0e8b30) + at js_msgbase.c:1905 +#1 0x2813cb9f in js_Invoke (cx=0x288bf180, argc=1, flags=1) at jsinterp.c:1375 +#2 0x2813e6c7 in js_InvokeConstructor (cx=0x288bf180, vp=0x28e74134, argc=1) at jsinterp.c:1947 +#3 0x28146a3b in js_Interpret (cx=0x288bf180, pc=0x28e828dd "#", result=0xbf0e9450) at jsinterp.c:3396 +#4 0x2813d669 in js_Execute (cx=0x288bf180, chain=0x288c79a0, script=0x28e82800, down=0x0, flags=0, + result=0xbf0e9a60) at jsinterp.c:1633 +#5 0x2810208a in JS_ExecuteScript (cx=0x288bf180, obj=0x288c79a0, script=0x28e82800, rval=0xbf0e9a60) + at jsapi.c:4188 +#6 0x282c4f1f in js_load (cx=0x288bf180, obj=0x288c66c0, argc=1, argv=0x28e74024, rval=0xbf0e9a60) + at js_global.c:364 +#7 0x2813cb9f in js_Invoke (cx=0x288bf180, argc=1, flags=0) at jsinterp.c:1375 +#8 0x2814bfe3 in js_Interpret (cx=0x288bf180, pc=0x28e17a97 ":", result=0xbf0ea300) at jsinterp.c:3944 +#9 0x2813d669 in js_Execute (cx=0x288bf180, chain=0x288c79a0, script=0x28e17a60, down=0x0, flags=0, + result=0xbf0eabc0) at jsinterp.c:1633 +#10 0x2810208a in JS_ExecuteScript (cx=0x288bf180, obj=0x288c79a0, script=0x28e17a60, rval=0xbf0eabc0) + at jsapi.c:4188 +#11 0x2828c066 in sbbs_t::js_execfile (this=0x28ac8000, cmd=0x28ad178e "chinkmaster.js") at exec.cpp:645 +#12 0x283725c7 in sbbs_t::external (this=0x28ac8000, cmdline=0x28ad178d "?chinkmaster.js", mode=256, + startup_dir=0x28a2bcaa "") at xtrn.cpp:1318 +#13 0x283068d9 in event_thread (arg=0x28ac8000) at main.cpp:2713 +#14 0x28550a99 in pthread_getprio () from /lib/libthr.so.3 +#15 0x00000000 in ?? () +(gdb) print scfg +$1 = (scfg_t *) 0x2842f480 +(gdb) print scfg->sub +$2 = (sub_t **) 0x0 +(gdb) print scfg->sub +$3 = (sub_t **) 0x0 +(gdb) print p +$4 = (private_t *) 0x29e3c000 +(gdb) print *scfg +$5 = {size = 23200, prepped = 1, grp = 0x0, total_grps = 3, sub = 0x0, total_subs = 79, lib = 0x0, + total_libs = 6, dir = 0x0, total_dirs = 232, txtsec = 0x0, total_txtsecs = 0, xtrnsec = 0x0, + total_xtrnsecs = 3, xtrn = 0x0, total_xtrns = 44, mdm_result = 0x0, mdm_results = 3, prot = 0x0, + total_prots = 9, fextr = 0x0, total_fextrs = 3, fcomp = 0x0, total_fcomps = 3, fview = 0x0, total_fviews = 12, + ftest = 0x0, total_ftests = 5, xedit = 0x0, total_xedits = 4, qhub = 0x0, total_qhubs = 1, phub = 0x0, + total_phubs = 0, chan = 0x0, total_chans = 3, chatact = 0x0, total_chatacts = 132, actset = 0x0, + total_actsets = 1, page = 0x0, total_pages = 2, event = 0x0, total_events = 16, dlevent = 0x0, + total_dlevents = 0, faddr = 0x0, total_faddrs = 0, swap = 0x0, total_swaps = 19, natvpgm = 0x0, + total_natvpgms = 10, guru = 0x0, total_gurus = 1, shell = 0x0, total_shells = 11, hotkey = 0x0, + total_hotkeys = 0, com_base = 15, com_irq = 3, com_rate = 2400, com_port = 1 '\001', + mdm_init = "AT&FS0=0S2=128E0V0X4&C1&D2", '\0' , mdm_spec = '\0' , + mdm_term = "ATE1V1", '\0' , mdm_dial = "ATDT", '\0' , + mdm_offh = "ATM0H1", '\0' , mdm_answ = "ATA", '\0' , + mdm_hang = '\0' , mdm_misc = 0, mdm_reinit = 0, mdm_ansdelay = 5, mdm_rings = 1 '\001', + sys_misc = -2045643832, sys_pass = "XXXXXXXX", '\0' , + sys_name = "Synchronix", '\0' , sys_id = "SYNCNIX\000", sys_psname = '\0' , + sys_psnum = 0, sys_inetaddr = "nix.synchro.net", '\0' , + sys_location = "Springside, SK", '\0' , sys_timezone = 16864, + sys_daily = '\0' , sys_logon = '\0' , sys_logout = '\0' , + sys_pwdays = 0, sys_deldays = 14, sys_autodel = 180, sys_nodes = 4, sys_op = "Deuce", '\0' , + sys_guru = "The Guru", '\0' , sys_exp_warn = 30 '\036', sys_def_stat = 1 '\001', + sys_phonefmt = '!' , sys_lastnode = 250, sys_autonode = 1, + sys_chat_arstr = '\0' , sys_chat_ar = 0x2837ca04 "", msg_misc = -65536, file_misc = 0, + xtrn_misc = 0, node_comspec = '\0' , node_editor = '\0' , + node_viewer = "%!list %f", '\0' , node_daily = '\0' , + node_scrnlen = 0 '\0', node_scrnblank = 0 '\0', node_misc = 33298, node_valuser = 1, node_ivt = 1, + node_swap = 2 '\002', node_swapdir = '\0' , node_minbps = 300, node_num = 1, + node_phone = "XXX-XXX-XXXX", node_name = "Node 1", '\0' , + node_arstr = '\0' , node_ar = 0x2837ca04 "", node_cost = 0, node_dollars_per_call = 0 '\0', + node_sem_check = 5, node_stat_check = 5, new_install = 0 '\0', new_pass = '\0' , + new_magic = '\0' , new_sif = "\000\000\000\000\000\000\000\000", + new_sof = "\000\000\000\000\000\000\000\000", new_level = 50 '2', new_flags1 = 0, new_flags2 = 0, + new_flags3 = 0, new_flags4 = 0, new_exempt = 0, new_rest = 0, new_cdt = 10485760, new_min = 0, + new_xedit = "\000\000\000\000\000\000\000\000", new_shell = 0, new_misc = 26896, new_expire = 0, + new_prot = 90 'Z', val_level = "\n\n\024\036(2 to continue, or q to quit--- + level_expireto = '\0' , level_timepercall = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 10, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 240, 51, 52, 53, 54, 55, 56, 57, 58, 59, 90, 120, 90, 63, 64, 65, 66, 67, + 68, 69, 120, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 120, 120, 120, 120, 120, + 120, 120, 120, 120, 480, 500}, level_timeperday = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 20, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 49, 480, 51, 52, 53, 54, 55, 56, 57, 58, 59, 120, 120, 120, 63, 64, 65, 66, 67, 68, 69, + 120, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 480, 240, 240, 240, 240, 240, + 240, 240, 240, 500, 500}, level_callsperday = {0, 1, 2, 3, 4, 4, 4, 4, 4, 4, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, + 4 , 50, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 10, 8, 8, 8, 8, 8, 8, 8, 10 , 4, + 4, 4, 4, 4, 4, 4, 4, 200, 500, 500, 500, 500, 500, 500, 500, 500, 500, 500}, level_linespermsg = { + 20 , 40 , 200, 50, 50, 50, 50, 50, 50, 50, 50, 50, 60 , + 70, 70, 70, 70, 70, 70, 70, 70, 70, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 9999}, level_postsperday = {50 , 20, 50 , 500}, level_emailperday = { + 50 , 20, 50 , 500}, level_freecdtperday = {0 , 4194304, + 0 }, level_misc = {0 }, expired_level = 0 '\0', expired_flags1 = 0, + expired_flags2 = 0, expired_flags3 = 0, expired_flags4 = 0, expired_exempt = 0, expired_rest = 0, + min_dspace = 4096, max_batup = 25, max_batdn = 100, max_userxfer = 5, max_minutes = 0, max_qwkmsgs = 10000, + preqwk_arstr = '\0' , preqwk_ar = 0x2837ca04 "", cdt_min_value = 6, cdt_per_dollar = 2097152, + cdt_up_pct = 100, cdt_dn_pct = 90, node_dir = "/synchronet/sbbs/node1/", '\0' , + ctrl_dir = "/synchronet/sbbs/ctrl/", '\0' , + data_dir = "/synchronet/sbbs/data/", '\0' , + text_dir = "/synchronet/sbbs/text/", '\0' , + exec_dir = "/synchronet/sbbs/exec/", '\0' , + temp_dir = "/tmp/SyncTemp/", '\0' , + mods_dir = "/synchronet/sbbs/mods/", '\0' , + logs_dir = "/synchronet/sbbs/data/", '\0' , node_path = { + "/synchronet/sbbs/node1/", '\0' , "/synchronet/sbbs/node2/", '\0' , + "/synchronet/sbbs/node3/", '\0' , "/synchronet/sbbs/node4/", '\0' , + '\0' }, sysop_dir = 11, user_dir = 12, upload_dir = 10, altpath = 0x0, + altpaths = 0, leech_pct = 0, leech_sec = 60, netmail_cost = 0, + netmail_dir = "/synchronet/sbbs/fido/outbound/", '\0' , netmail_misc = 41, + inetmail_misc = 17, inetmail_cost = 0, smtpmail_sem = '\0' , + inetmail_sem = '\0' , echomail_dir = '\0' , + fidofile_dir = "/synchronet/sbbs/fido/inbsecure/", '\0' , + netmail_sem = "%jfidoout.now", '\0' , + echomail_sem = "%jfidoout.now", '\0' , origline = '\0' , + qnet_tagline = "My Brand-New BBS (All the cool SysOps run STOCK!)", '\0' , uq = 151027, +---Type to continue, or q to quit--- + mail_maxcrcs = 0, mail_maxage = 0, dflt_faddr = {zone = 0, net = 0, node = 0, point = 0}, + logon_mod = "logon\000\000\000", logoff_mod = "\000\000\000\000\000\000\000\000", newuser_mod = "newuser\000", + login_mod = "login\000\000\000", logout_mod = "\000\000\000\000\000\000\000\000", + sync_mod = "\000\000\000\000\000\000\000\000", expire_mod = "\000\000\000\000\000\000\000\000", + scfg_cmd = "%!scfg %k /t%w", '\0' , smb_retry_time = 30 '\036', sec_warn = 180, + sec_hangup = 300, color = 0x0, total_colors = 0, ctrlkey_passthru = 0, wfc_cmd = {'\0' , + "%!list ..\\data\\error.log", '\0' , "%!list ..\\data\\guru.log", '\0' , + "%!list ..\\data\\logons.lst", '\0' , '\0' , '\0' , + '\0' , '\0' , '\0' , '\0' }, + wfc_scmd = {"%!qnet", '\0' , "%!pnet", '\0' , '\0' , + '\0' , '\0' , '\0' , '\0' , + '\0' , '\0' , '\0' , '\0' , + '\0' }, user_backup_level = 5, mail_backup_level = 5} +*/ } if(p->smb.subnumtotal_subs) { cfgobj=JS_NewObject(cx,NULL,NULL,obj); @@ -1865,17 +2078,22 @@ js_msgbase_constructor(JSContext *cx, JS } } - if(!js_DefineSyncMethods(cx, obj, js_msgbase_functions, FALSE)) { - JS_ReportError(cx,"js_DefineSyncMethods failed"); - return(JS_FALSE); - } - return(JS_TRUE); } +static struct JSPropertySpec js_msgbase_static_properties[] = { +/* name ,tinyid ,flags, getter, setter */ + + { "IndexPrototype" ,0 ,JSPROP_ENUMERATE|JSPROP_PERMANENT, NULL,NULL}, + { "HeaderPrototype" ,0 ,JSPROP_ENUMERATE|JSPROP_PERMANENT, NULL,NULL}, + {0} +}; + JSObject* DLLCALL js_CreateMsgBaseClass(JSContext* cx, JSObject* parent, scfg_t* cfg) { JSObject* obj; + JSObject* constructor; + jsval val; scfg = cfg; obj = JS_InitClass(cx, parent, NULL @@ -1884,7 +2102,14 @@ JSObject* DLLCALL js_CreateMsgBaseClass( ,1 /* number of constructor args */ ,NULL /* js_msgbase_properties */ ,NULL /* js_msgbase_functions */ - ,NULL,NULL); + ,js_msgbase_static_properties,NULL); + + + if(JS_GetProperty(cx, parent, js_msgbase_class.name, &val) && !JSVAL_NULL_OR_VOID(val)) { + JS_ValueToObject(cx,val,&constructor); + JS_DefineObject(cx,constructor,"IndexPrototype",NULL,NULL,JSPROP_PERMANENT|JSPROP_ENUMERATE); + JS_DefineObject(cx,constructor,"HeaderPrototype",NULL,NULL,JSPROP_PERMANENT|JSPROP_ENUMERATE); + } return(obj); }