js_msgbase.c 44.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 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 50
/* js_msgbase.c */

/* Synchronet JavaScript "MsgBase" Object */

/* $Id$ */

/****************************************************************************
 * @format.tab-size 4		(Plain Text/Source Code File Header)			*
 * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
 *																			*
 * Copyright 2001 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"

#ifdef JAVASCRIPT

static scfg_t* scfg=NULL;

typedef struct
{
	smb_t	smb;
	BOOL	debug;

} private_t;

51 52
static const char* getprivate_failure = "line %d %s JS_GetPrivate failed";

53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
/* 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 */

72 73 74 75 76 77
static JSBool
js_open(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	private_t* p;
	
	if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
78
		JS_ReportError(cx,getprivate_failure,WHERE);
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
		return(JS_FALSE);
	}

	*rval = 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);
		return(JS_TRUE);
	}

	if(smb_open(&(p->smb))!=0)
		return(JS_TRUE);

	*rval = JSVAL_TRUE;
	return(JS_TRUE);
}


99 100 101 102 103
static JSBool
js_close(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	private_t* p;
	
104
	if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
105
		JS_ReportError(cx,getprivate_failure,WHERE);
106
		return(JS_FALSE);
107
	}
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124

	smb_close(&(p->smb));

	*rval = JSVAL_VOID;
	return(JS_TRUE);
}

static JSClass js_msghdr_class = {
     "MsgHeader"				/* name			*/
    ,JSCLASS_HAS_PRIVATE	/* flags		*/
	,JS_PropertyStub		/* addProperty	*/
	,JS_PropertyStub		/* delProperty	*/
	,JS_PropertyStub		/* getProperty	*/
	,JS_PropertyStub		/* setProperty	*/
	,JS_EnumerateStub		/* enumerate	*/
	,JS_ResolveStub			/* resolve		*/
	,JS_ConvertStub			/* convert		*/
125
	,JS_FinalizeStub		/* finalize		*/
126 127
};

128
static BOOL parse_header_object(JSContext* cx, private_t* p, JSObject* hdr, smbmsg_t* msg)
129 130
{
	char*		cp;
131 132
	char		to[256];
	char		from[256];
133
	ushort		nettype;
134
	ushort		type;
135 136
	ushort		agent;
	int32		i32;
137
	jsval		val;
138 139 140
	JSObject*	array;
	JSObject*	field;
	jsuint		i,len;
141

142 143 144
	if(hdr==NULL)
		return(FALSE);

145
	/* Required Header Fields */
146
	if(JS_GetProperty(cx, hdr, "subject", &val) && val!=JSVAL_VOID) {
147
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
148 149 150 151
			return(FALSE);
	} else
		cp="";
	smb_hfield(msg, SUBJECT, (ushort)strlen(cp), cp);
152
	msg->idx.subj=subject_crc(cp);
153

154
	if(JS_GetProperty(cx, hdr, "to", &val) && val!=JSVAL_VOID) {
155
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
156 157
			return(FALSE);
	} else {
158 159
		if(p->smb.status.attr&SMB_EMAIL)	/* e-mail */
			return(FALSE);					/* "to" property required */
160 161 162
		cp="All";
	}
	smb_hfield(msg, RECIPIENT, (ushort)strlen(cp), cp);
163
	if(!(p->smb.status.attr&SMB_EMAIL)) {
164 165 166
		SAFECOPY(to,cp);
		strlwr(to);
		msg->idx.to=crc16(to);
167
	}
168

169
	if(JS_GetProperty(cx, hdr, "from", &val) && val!=JSVAL_VOID) {
170
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
171 172 173 174
			return(FALSE);
	} else
		return(FALSE);	/* "from" property required */
	smb_hfield(msg, SENDER, (ushort)strlen(cp), cp);
175
	if(!(p->smb.status.attr&SMB_EMAIL)) {
176 177 178
		SAFECOPY(from,cp);
		strlwr(from);
		msg->idx.from=crc16(from);
179
	}
180 181

	/* Optional Header Fields */
182
	if(JS_GetProperty(cx, hdr, "from_ext", &val) && val!=JSVAL_VOID) {
183
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
184 185
			return(FALSE);
		smb_hfield(msg, SENDEREXT, (ushort)strlen(cp), cp);
186
		if(p->smb.status.attr&SMB_EMAIL)
187 188 189
			msg->idx.from=atoi(cp);
	}

190
	if(JS_GetProperty(cx, hdr, "from_org", &val) && val!=JSVAL_VOID) {
191
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
192 193 194 195
			return(FALSE);
		smb_hfield(msg, SENDERORG, (ushort)strlen(cp), cp);
	}

196
	if(JS_GetProperty(cx, hdr, "from_net_type", &val) && val!=JSVAL_VOID) {
197 198
		JS_ValueToInt32(cx,val,&i32);
		nettype=(ushort)i32;
199
		smb_hfield(msg, SENDERNETTYPE, sizeof(nettype), &nettype);
200
		if(p->smb.status.attr&SMB_EMAIL && nettype!=NET_NONE)
201 202 203
			msg->idx.from=0;
	}

204
	if(JS_GetProperty(cx, hdr, "from_net_addr", &val) && val!=JSVAL_VOID) {
205
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
206 207 208 209
			return(FALSE);
		smb_hfield(msg, SENDERNETADDR, (ushort)strlen(cp), cp);
	}

210
	if(JS_GetProperty(cx, hdr, "from_agent", &val) && val!=JSVAL_VOID) {
211 212 213 214 215
		JS_ValueToInt32(cx,val,&i32);
		agent=(ushort)i32;
		smb_hfield(msg, SENDERAGENT, sizeof(agent), &agent);
	}

216
	if(JS_GetProperty(cx, hdr, "to_ext", &val) && val!=JSVAL_VOID) {
217
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
218 219
			return(FALSE);
		smb_hfield(msg, RECIPIENTEXT, (ushort)strlen(cp), cp);
220
		if(p->smb.status.attr&SMB_EMAIL)
221 222 223
			msg->idx.to=atoi(cp);
	}

224
	if(JS_GetProperty(cx, hdr, "to_org", &val) && val!=JSVAL_VOID) {
225 226 227 228 229
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
			return(FALSE);
		smb_hfield(msg, RECIPIENTORG, (ushort)strlen(cp), cp);
	}

230
	if(JS_GetProperty(cx, hdr, "to_net_type", &val) && val!=JSVAL_VOID) {
231 232
		JS_ValueToInt32(cx,val,&i32);
		nettype=(ushort)i32;
233
		smb_hfield(msg, RECIPIENTNETTYPE, sizeof(nettype), &nettype);
234
		if(p->smb.status.attr&SMB_EMAIL && nettype!=NET_NONE)
235 236 237
			msg->idx.to=0;
	}

238
	if(JS_GetProperty(cx, hdr, "to_net_addr", &val) && val!=JSVAL_VOID) {
239
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
240 241 242
			return(FALSE);
		smb_hfield(msg, RECIPIENTNETADDR, (ushort)strlen(cp), cp);
	}
243

244
	if(JS_GetProperty(cx, hdr, "to_agent", &val) && val!=JSVAL_VOID) {
245 246 247 248 249
		JS_ValueToInt32(cx,val,&i32);
		agent=(ushort)i32;
		smb_hfield(msg, RECIPIENTAGENT, sizeof(agent), &agent);
	}

250
	if(JS_GetProperty(cx, hdr, "replyto", &val) && val!=JSVAL_VOID) {
251
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
252 253 254 255
			return(FALSE);
		smb_hfield(msg, REPLYTO, (ushort)strlen(cp), cp);
	}

256
	if(JS_GetProperty(cx, hdr, "replyto_ext", &val) && val!=JSVAL_VOID) {
257
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
258 259 260 261
			return(FALSE);
		smb_hfield(msg, REPLYTOEXT, (ushort)strlen(cp), cp);
	}

262
	if(JS_GetProperty(cx, hdr, "replyto_org", &val) && val!=JSVAL_VOID) {
263 264 265 266 267
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
			return(FALSE);
		smb_hfield(msg, REPLYTOORG, (ushort)strlen(cp), cp);
	}

268
	if(JS_GetProperty(cx, hdr, "replyto_net_type", &val) && val!=JSVAL_VOID) {
269 270
		JS_ValueToInt32(cx,val,&i32);
		nettype=(ushort)i32;
271 272 273
		smb_hfield(msg, REPLYTONETTYPE, sizeof(nettype), &nettype);
	}

274
	if(JS_GetProperty(cx, hdr, "replyto_net_addr", &val) && val!=JSVAL_VOID) {
275
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
276 277 278 279
			return(FALSE);
		smb_hfield(msg, REPLYTONETADDR, (ushort)strlen(cp), cp);
	}

280
	if(JS_GetProperty(cx, hdr, "replyto_agent", &val) && val!=JSVAL_VOID) {
281 282 283 284 285
		JS_ValueToInt32(cx,val,&i32);
		agent=(ushort)i32;
		smb_hfield(msg, REPLYTOAGENT, sizeof(agent), &agent);
	}

286
	/* RFC822 headers */
287
	if(JS_GetProperty(cx, hdr, "id", &val) && val!=JSVAL_VOID) {
288
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
289 290 291 292
			return(FALSE);
		smb_hfield(msg, RFC822MSGID, (ushort)strlen(cp), cp);
	}

293
	if(JS_GetProperty(cx, hdr, "reply_id", &val) && val!=JSVAL_VOID) {
294
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
295 296 297 298
			return(FALSE);
		smb_hfield(msg, RFC822REPLYID, (ushort)strlen(cp), cp);
	}

299
	if(JS_GetProperty(cx, hdr, "reverse_path", &val) && val!=JSVAL_VOID) {
300
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
301 302 303 304
			return(FALSE);
		smb_hfield(msg, SMTPREVERSEPATH, (ushort)strlen(cp), cp);
	}

305
	/* USENET headers */
306
	if(JS_GetProperty(cx, hdr, "path", &val) && val!=JSVAL_VOID) {
307
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
308 309 310 311
			return(FALSE);
		smb_hfield(msg, USENETPATH, (ushort)strlen(cp), cp);
	}

312
	if(JS_GetProperty(cx, hdr, "newsgroups", &val) && val!=JSVAL_VOID) {
313
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
314 315 316 317 318
			return(FALSE);
		smb_hfield(msg, USENETNEWSGROUPS, (ushort)strlen(cp), cp);
	}

	/* FTN headers */
319
	if(JS_GetProperty(cx, hdr, "ftn_msgid", &val) && val!=JSVAL_VOID) {
320
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
321 322 323 324
			return(FALSE);
		smb_hfield(msg, FIDOMSGID, (ushort)strlen(cp), cp);
	}

325
	if(JS_GetProperty(cx, hdr, "ftn_reply", &val) && val!=JSVAL_VOID) {
326
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
327 328 329 330
			return(FALSE);
		smb_hfield(msg, FIDOREPLYID, (ushort)strlen(cp), cp);
	}

331
	if(JS_GetProperty(cx, hdr, "ftn_area", &val) && val!=JSVAL_VOID) {
332
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
333 334 335 336
			return(FALSE);
		smb_hfield(msg, FIDOAREA, (ushort)strlen(cp), cp);
	}

337
	if(JS_GetProperty(cx, hdr, "ftn_flags", &val) && val!=JSVAL_VOID) {
338
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
339 340 341 342
			return(FALSE);
		smb_hfield(msg, FIDOFLAGS, (ushort)strlen(cp), cp);
	}

343
	if(JS_GetProperty(cx, hdr, "ftn_pid", &val) && val!=JSVAL_VOID) {
344
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
345 346 347 348
			return(FALSE);
		smb_hfield(msg, FIDOPID, (ushort)strlen(cp), cp);
	}

349
	if(JS_GetProperty(cx, hdr, "ftn_tid", &val) && val!=JSVAL_VOID) {
350
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
351 352 353 354
			return(FALSE);
		smb_hfield(msg, FIDOTID, (ushort)strlen(cp), cp);
	}

355
	if(JS_GetProperty(cx, hdr, "date", &val) && val!=JSVAL_VOID) {
356
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
357 358 359
			return(FALSE);
		msg->hdr.when_written=rfc822date(cp);
	}
360 361
	
	/* Numeric Header Fields */
362
	if(JS_GetProperty(cx, hdr, "attr", &val) && val!=JSVAL_VOID) {
363 364
		JS_ValueToInt32(cx,val,&i32);
		msg->hdr.attr=(ushort)i32;
365 366
		msg->idx.attr=msg->hdr.attr;
	}
367
	if(JS_GetProperty(cx, hdr, "auxattr", &val) && val!=JSVAL_VOID) {
368 369 370
		JS_ValueToInt32(cx,val,&i32);
		msg->hdr.auxattr=i32;
	}
371
	if(JS_GetProperty(cx, hdr, "netattr", &val) && val!=JSVAL_VOID) {
372 373 374
		JS_ValueToInt32(cx,val,&i32);
		msg->hdr.netattr=i32;
	}
375
	if(JS_GetProperty(cx, hdr, "when_written_time", &val) && val!=JSVAL_VOID)  {
376 377 378
		JS_ValueToInt32(cx,val,&i32);
		msg->hdr.when_written.time=i32;
	}
379
	if(JS_GetProperty(cx, hdr, "when_written_zone", &val) && val!=JSVAL_VOID) {
380 381 382
		JS_ValueToInt32(cx,val,&i32);
		msg->hdr.when_written.zone=(short)i32;
	}
383
	if(JS_GetProperty(cx, hdr, "when_imported_time", &val) && val!=JSVAL_VOID) {
384 385 386
		JS_ValueToInt32(cx,val,&i32);
		msg->hdr.when_imported.time=i32;
	}
387
	if(JS_GetProperty(cx, hdr, "when_imported_zone", &val) && val!=JSVAL_VOID) {
388 389 390 391
		JS_ValueToInt32(cx,val,&i32);
		msg->hdr.when_imported.zone=(short)i32;
	}

392
	if(JS_GetProperty(cx, hdr, "thread_orig", &val) && val!=JSVAL_VOID) {
393 394 395
		JS_ValueToInt32(cx,val,&i32);
		msg->hdr.thread_orig=i32;
	}
396
	if(JS_GetProperty(cx, hdr, "thread_next", &val) && val!=JSVAL_VOID) {
397 398 399
		JS_ValueToInt32(cx,val,&i32);
		msg->hdr.thread_next=i32;
	}
400
	if(JS_GetProperty(cx, hdr, "thread_first", &val) && val!=JSVAL_VOID) {
401 402 403
		JS_ValueToInt32(cx,val,&i32);
		msg->hdr.thread_first=i32;
	}
404

405 406 407
	if(JS_GetProperty(cx, hdr, "field_list", &val) && JSVAL_IS_OBJECT(val)) {
		array=JSVAL_TO_OBJECT(val);
		len=0;
408 409
		if(!JS_GetArrayLength(cx, array, &len))
			return(FALSE);
410 411 412 413 414 415 416

		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);
417
			if(!JS_GetProperty(cx, field, "type", &val))
418
				continue;
419 420 421
			JS_ValueToInt32(cx,val,&i32);
			type=(ushort)i32;
			if(!JS_GetProperty(cx, field, "data", &val))
422
				continue;
423
			if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
424 425 426 427 428
				return(FALSE);
			smb_hfield(msg, type, (ushort)strlen(cp), cp);
		}
	}

429 430 431
	return(TRUE);
}

432
BOOL msg_offset_by_id(scfg_t* scfg, smb_t* smb, char* id, ulong* offset)
433 434 435
{
	smbmsg_t msg;

436
	if(!get_msg_by_id(scfg,smb,id,&msg))
437 438 439 440 441 442 443 444
		return(FALSE);

	smb_freemsgmem(&msg);

	*offset = msg.offset;
	return(TRUE);
}

445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510
static JSBool
js_get_msg_index(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	uintN		n;
	smbmsg_t	msg;
	JSObject*	idxobj;
	JSBool		by_offset=JS_FALSE;
	private_t*	p;

	*rval = JSVAL_NULL;
	
	if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
		JS_ReportError(cx,getprivate_failure,WHERE);
		return(JS_FALSE);
	}

	if(!SMB_IS_OPEN(&(p->smb)))
		return(JS_TRUE);

	memset(&msg,0,sizeof(msg));

	for(n=0;n<argc;n++) {
		if(JSVAL_IS_BOOLEAN(argv[n]))
			by_offset=JSVAL_TO_BOOLEAN(argv[n]);
		else if(JSVAL_IS_INT(argv[n])) {
			if(by_offset)							/* Get by offset */
				msg.offset=JSVAL_TO_INT(argv[n]);
			else									/* Get by number */
				msg.hdr.number=JSVAL_TO_INT(argv[n]);

			if(smb_getmsgidx(&(p->smb), &msg)!=0)
				return(JS_TRUE);

			break;
		}
	}

	if((idxobj=JS_NewObject(cx,NULL,NULL,obj))==NULL)
		return(JS_TRUE);

	JS_DefineProperty(cx, idxobj, "number", INT_TO_JSVAL(msg.idx.number)
		,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE);

	JS_DefineProperty(cx, idxobj, "to" ,INT_TO_JSVAL(msg.idx.to)
		,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE);

	JS_DefineProperty(cx, idxobj, "from" ,INT_TO_JSVAL(msg.idx.from)
		,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE);

	JS_DefineProperty(cx, idxobj, "subject" ,INT_TO_JSVAL(msg.idx.subj)
		,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE);

	JS_DefineProperty(cx, idxobj, "attr" ,INT_TO_JSVAL(msg.idx.attr)
		,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE);

	JS_DefineProperty(cx, idxobj, "offset" ,INT_TO_JSVAL(msg.idx.offset)
		,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE);

	JS_DefineProperty(cx, idxobj, "time" ,INT_TO_JSVAL(msg.idx.time)
		,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE);

	*rval = OBJECT_TO_JSVAL(idxobj);

	return(JS_TRUE);
}

511 512 513
static JSBool
js_get_msg_header(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
514
	char		date[128];
515 516
	char		msg_id[256];
	char		reply_id[256];
517
	char*		val;
518
	int			i;
519
	ulong		l;
520
	uintN		n;
521
	smbmsg_t	msg;
522
	smbmsg_t	orig_msg;
523
	JSObject*	hdrobj;
524 525
	JSObject*	array;
	JSObject*	field;
526
	JSString*	js_str;
527
	jsint		items;
528
	JSBool		by_offset=JS_FALSE;
529 530 531 532
	private_t*	p;

	*rval = JSVAL_NULL;
	
533
	if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) {
534
		JS_ReportError(cx,getprivate_failure,WHERE);
535
		return(JS_FALSE);
536
	}
537

538 539 540
	if(!SMB_IS_OPEN(&(p->smb)))
		return(JS_TRUE);

541 542
	memset(&msg,0,sizeof(msg));

543 544 545 546 547 548 549 550
	for(n=0;n<argc;n++) {
		if(JSVAL_IS_BOOLEAN(argv[n]))
			by_offset=JSVAL_TO_BOOLEAN(argv[n]);
		else if(JSVAL_IS_INT(argv[n])) {
			if(by_offset)							/* Get by offset */
				msg.offset=JSVAL_TO_INT(argv[n]);
			else									/* Get by number */
				msg.hdr.number=JSVAL_TO_INT(argv[n]);
551 552 553 554 555 556 557 558 559 560 561 562 563

			if(smb_getmsgidx(&(p->smb), &msg)!=0)
				return(JS_TRUE);

			if(smb_lockmsghdr(&(p->smb),&msg)!=0)
				return(JS_TRUE);

			if(smb_getmsghdr(&(p->smb), &msg)!=0) {
				smb_unlockmsghdr(&(p->smb),&msg); 
				return(JS_TRUE);
			}

			smb_unlockmsghdr(&(p->smb),&msg); 
564 565
			break;
		} else if(JSVAL_IS_STRING(argv[n]))	{		/* Get by ID */
566
			if(!get_msg_by_id(scfg,&(p->smb)
567
				,JS_GetStringBytes(JSVAL_TO_STRING(argv[n]))
568
				,&msg))
569
				return(JS_TRUE);	/* ID not found */
570

571 572 573
			break;
		}
	}
574

575 576 577
	if(msg.hdr.number==0)	/* No valid message number/id/offset specified */
		return(JS_TRUE);

rswindell's avatar
rswindell committed
578 579
	if((hdrobj=JS_NewObject(cx,&js_msghdr_class,NULL,obj))==NULL) {
		smb_freemsgmem(&msg);
580
		return(JS_TRUE);
rswindell's avatar
rswindell committed
581
	}
582 583

	JS_DefineProperty(cx, hdrobj, "number", INT_TO_JSVAL(msg.hdr.number)
584
		,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE);
585 586 587

	if((js_str=JS_NewStringCopyZ(cx,truncsp(msg.to)))==NULL)
		return(JS_FALSE);
588
	JS_DefineProperty(cx, hdrobj, "to"
589
		,STRING_TO_JSVAL(js_str)
590
		,NULL,NULL,JSPROP_ENUMERATE);
591 592 593

	if((js_str=JS_NewStringCopyZ(cx,truncsp(msg.from)))==NULL)
		return(JS_FALSE);
594
	JS_DefineProperty(cx, hdrobj, "from"
595
		,STRING_TO_JSVAL(js_str)
596
		,NULL,NULL,JSPROP_ENUMERATE);
597 598 599

	if((js_str=JS_NewStringCopyZ(cx,truncsp(msg.subj)))==NULL)
		return(JS_FALSE);
600
	JS_DefineProperty(cx, hdrobj, "subject"
601
		,STRING_TO_JSVAL(js_str)
602
		,NULL,NULL,JSPROP_ENUMERATE);
603 604
	if(msg.summary!=NULL 
		&& (js_str=JS_NewStringCopyZ(cx,truncsp(msg.summary)))!=NULL)
605
		JS_DefineProperty(cx, hdrobj, "summary"
606
			,STRING_TO_JSVAL(js_str)
607
			,NULL,NULL,JSPROP_ENUMERATE);
608 609
	if(msg.to_ext!=NULL 
		&& (js_str=JS_NewStringCopyZ(cx,truncsp(msg.to_ext)))!=NULL)
610
		JS_DefineProperty(cx, hdrobj, "to_ext"
611
			,STRING_TO_JSVAL(js_str)
612
			,NULL,NULL,JSPROP_ENUMERATE);
613 614
	if(msg.from_ext!=NULL 
		&& (js_str=JS_NewStringCopyZ(cx,truncsp(msg.from_ext)))!=NULL)
615
		JS_DefineProperty(cx, hdrobj, "from_ext"
616
			,STRING_TO_JSVAL(js_str)
617
			,NULL,NULL,JSPROP_ENUMERATE);
618 619
	if(msg.from_org!=NULL
		&& (js_str=JS_NewStringCopyZ(cx,truncsp(msg.from_org)))!=NULL)
620
		JS_DefineProperty(cx, hdrobj, "from_org"
621
			,STRING_TO_JSVAL(js_str)
622
			,NULL,NULL,JSPROP_ENUMERATE);
623 624
	if(msg.replyto!=NULL
		&& (js_str=JS_NewStringCopyZ(cx,truncsp(msg.replyto)))!=NULL)
625
		JS_DefineProperty(cx, hdrobj, "replyto"
626
			,STRING_TO_JSVAL(js_str)
627
			,NULL,NULL,JSPROP_ENUMERATE);
628 629
	if(msg.replyto_ext!=NULL
		&& (js_str=JS_NewStringCopyZ(cx,truncsp(msg.replyto_ext)))!=NULL)
630
		JS_DefineProperty(cx, hdrobj, "replyto_ext"
631
			,STRING_TO_JSVAL(js_str)
632
			,NULL,NULL,JSPROP_ENUMERATE);
633 634
	if(msg.reverse_path!=NULL
		&& (js_str=JS_NewStringCopyZ(cx,truncsp(msg.reverse_path)))!=NULL)
635
		JS_DefineProperty(cx, hdrobj, "reverse_path"
636
			,STRING_TO_JSVAL(js_str)
637
			,NULL,NULL,JSPROP_ENUMERATE);
638

639
	JS_DefineProperty(cx, hdrobj, "to_agent",INT_TO_JSVAL(msg.to_agent)
640
		,NULL,NULL,JSPROP_ENUMERATE);
641
	JS_DefineProperty(cx, hdrobj, "from_agent",INT_TO_JSVAL(msg.from_agent)
642
		,NULL,NULL,JSPROP_ENUMERATE);
643
	JS_DefineProperty(cx, hdrobj, "replyto_agent",INT_TO_JSVAL(msg.replyto_agent)
644
		,NULL,NULL,JSPROP_ENUMERATE);
645 646

	JS_DefineProperty(cx, hdrobj, "to_net_type",INT_TO_JSVAL(msg.to_net.type)
647
		,NULL,NULL,JSPROP_ENUMERATE);
648 649
	if(msg.to_net.type
		&& (js_str=JS_NewStringCopyZ(cx,net_addr(&msg.to_net)))!=NULL)
650
		JS_DefineProperty(cx, hdrobj, "to_net_addr"
651
			,STRING_TO_JSVAL(js_str)
652
			,NULL,NULL,JSPROP_ENUMERATE);
653 654

	JS_DefineProperty(cx, hdrobj, "from_net_type",INT_TO_JSVAL(msg.from_net.type)
655
		,NULL,NULL,JSPROP_ENUMERATE);
656 657
	if(msg.from_net.type
		&& (js_str=JS_NewStringCopyZ(cx,net_addr(&msg.from_net)))!=NULL)
658
		JS_DefineProperty(cx, hdrobj, "from_net_addr"
659
			,STRING_TO_JSVAL(js_str)
660
			,NULL,NULL,JSPROP_ENUMERATE);
661 662

	JS_DefineProperty(cx, hdrobj, "replyto_net_type",INT_TO_JSVAL(msg.replyto_net.type)
663
		,NULL,NULL,JSPROP_ENUMERATE);
664 665
	if(msg.replyto_net.type
		&& (js_str=JS_NewStringCopyZ(cx,net_addr(&msg.replyto_net)))!=NULL)
666
		JS_DefineProperty(cx, hdrobj, "replyto_net_addr"
667
			,STRING_TO_JSVAL(js_str)
668
			,NULL,NULL,JSPROP_ENUMERATE);
669 670

	JS_DefineProperty(cx, hdrobj, "forwarded",INT_TO_JSVAL(msg.forwarded)
671
		,NULL,NULL,JSPROP_ENUMERATE);
672
	JS_DefineProperty(cx, hdrobj, "expiration",INT_TO_JSVAL(msg.expiration)
673
		,NULL,NULL,JSPROP_ENUMERATE);
674 675 676 677 678
	JS_DefineProperty(cx, hdrobj, "priority",INT_TO_JSVAL(msg.priority)
		,NULL,NULL,JSPROP_ENUMERATE);
	JS_DefineProperty(cx, hdrobj, "cost",INT_TO_JSVAL(msg.cost)
		,NULL,NULL,JSPROP_ENUMERATE);

679 680

	JS_DefineProperty(cx, hdrobj, "type", INT_TO_JSVAL(msg.hdr.type)
681
		,NULL,NULL,JSPROP_ENUMERATE);
682
	JS_DefineProperty(cx, hdrobj, "version", INT_TO_JSVAL(msg.hdr.version)
683
		,NULL,NULL,JSPROP_ENUMERATE);
684
	JS_DefineProperty(cx, hdrobj, "attr", INT_TO_JSVAL(msg.hdr.attr)
685
		,NULL,NULL,JSPROP_ENUMERATE);
686
	JS_DefineProperty(cx, hdrobj, "auxattr", INT_TO_JSVAL(msg.hdr.auxattr)
687
		,NULL,NULL,JSPROP_ENUMERATE);
688
	JS_DefineProperty(cx, hdrobj, "netattr", INT_TO_JSVAL(msg.hdr.netattr)
689
		,NULL,NULL,JSPROP_ENUMERATE);
690 691

	JS_DefineProperty(cx, hdrobj, "when_written_time", INT_TO_JSVAL(msg.hdr.when_written.time)
692
		,NULL,NULL,JSPROP_ENUMERATE);
693
	JS_DefineProperty(cx, hdrobj, "when_written_zone", INT_TO_JSVAL(msg.hdr.when_written.zone)
694
		,NULL,NULL,JSPROP_ENUMERATE);
695
	JS_DefineProperty(cx, hdrobj, "when_imported_time", INT_TO_JSVAL(msg.hdr.when_imported.time)
696
		,NULL,NULL,JSPROP_ENUMERATE);
697
	JS_DefineProperty(cx, hdrobj, "when_imported_zone", INT_TO_JSVAL(msg.hdr.when_imported.zone)
698
		,NULL,NULL,JSPROP_ENUMERATE);
699 700

	JS_DefineProperty(cx, hdrobj, "thread_orig", INT_TO_JSVAL(msg.hdr.thread_orig)
701
		,NULL,NULL,JSPROP_ENUMERATE);
702
	JS_DefineProperty(cx, hdrobj, "thread_next", INT_TO_JSVAL(msg.hdr.thread_next)
703
		,NULL,NULL,JSPROP_ENUMERATE);
704
	JS_DefineProperty(cx, hdrobj, "thread_first", INT_TO_JSVAL(msg.hdr.thread_first)
705
		,NULL,NULL,JSPROP_ENUMERATE);
706 707

	JS_DefineProperty(cx, hdrobj, "delivery_attempts", INT_TO_JSVAL(msg.hdr.delivery_attempts)
708
		,NULL,NULL,JSPROP_ENUMERATE);
709 710 711 712
	JS_DefineProperty(cx, hdrobj, "last_downloaded", INT_TO_JSVAL(msg.hdr.last_downloaded)
		,NULL,NULL,JSPROP_ENUMERATE);
	JS_DefineProperty(cx, hdrobj, "times_downloaded", INT_TO_JSVAL(msg.hdr.times_downloaded)
		,NULL,NULL,JSPROP_ENUMERATE);
713 714 715

	l=smb_getmsgdatlen(&msg);
	JS_DefineProperty(cx, hdrobj, "data_length", INT_TO_JSVAL(l)
716
		,NULL,NULL,JSPROP_ENUMERATE);
717

718 719
	if((js_str=JS_NewStringCopyZ(cx,msgdate(msg.hdr.when_written,date)))==NULL)
		return(JS_FALSE);
720
	JS_DefineProperty(cx, hdrobj, "date"
721
		,STRING_TO_JSVAL(js_str)
722
		,NULL,NULL,JSPROP_ENUMERATE);
723

724
	/* Reply-ID (References) */
725
	if(msg.reply_id!=NULL)
726 727 728
		val=msg.reply_id;
	else {
		reply_id[0]=0;
729
		if(msg.hdr.thread_orig) {
730 731 732 733 734
			memset(&orig_msg,0,sizeof(orig_msg));
			orig_msg.hdr.number=msg.hdr.thread_orig;
			if(smb_getmsgidx(&(p->smb), &orig_msg))
				sprintf(reply_id,"<%s>",p->smb.last_error);
			else
735
				SAFECOPY(reply_id,get_msgid(scfg,p->smb.subnum,&orig_msg));
736
		}
737 738
		val=reply_id;
	}
739
	if(val[0] && (js_str=JS_NewStringCopyZ(cx,truncsp(val)))!=NULL)
740
		JS_DefineProperty(cx, hdrobj, "reply_id"
741
			, STRING_TO_JSVAL(js_str)
742
			,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE);
743 744

	/* Message-ID */
745 746
	SAFECOPY(msg_id,get_msgid(scfg,p->smb.subnum,&msg));
	val=msg_id;
747 748
	if((js_str=JS_NewStringCopyZ(cx,truncsp(val)))==NULL)
		return(JS_FALSE);
749
	JS_DefineProperty(cx, hdrobj, "id"
750
		,STRING_TO_JSVAL(js_str)
751 752
		,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE);

753
	/* USENET Fields */
754 755
	if(msg.path!=NULL
		&& (js_str=JS_NewStringCopyZ(cx,truncsp(msg.path)))!=NULL)
756
		JS_DefineProperty(cx, hdrobj, "path"
757
			,STRING_TO_JSVAL(js_str)
758
			,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE);
759 760
	if(msg.newsgroups!=NULL
		&& (js_str=JS_NewStringCopyZ(cx,truncsp(msg.newsgroups)))!=NULL)
761
		JS_DefineProperty(cx, hdrobj, "newsgroups"
762
			,STRING_TO_JSVAL(js_str)
763 764
			,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE);

765
	/* FidoNet Header Fields */
766 767
	if(msg.ftn_msgid!=NULL
		&& (js_str=JS_NewStringCopyZ(cx,truncsp(msg.ftn_msgid)))!=NULL)
768
		JS_DefineProperty(cx, hdrobj, "ftn_msgid"
769
			,STRING_TO_JSVAL(js_str)
770
			,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE);
771 772
	if(msg.ftn_reply!=NULL
		&& (js_str=JS_NewStringCopyZ(cx,truncsp(msg.ftn_reply)))!=NULL)
773
		JS_DefineProperty(cx, hdrobj, "ftn_reply"
774
			,STRING_TO_JSVAL(js_str)
775
			,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE);
776 777
	if(msg.ftn_pid!=NULL
		&& (js_str=JS_NewStringCopyZ(cx,truncsp(msg.ftn_pid)))!=NULL)
778
		JS_DefineProperty(cx, hdrobj, "ftn_pid"
779
			,STRING_TO_JSVAL(js_str)
780
			,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE);
781 782
	if(msg.ftn_tid!=NULL
		&& (js_str=JS_NewStringCopyZ(cx,truncsp(msg.ftn_tid)))!=NULL)
783
		JS_DefineProperty(cx, hdrobj, "ftn_tid"
784
			,STRING_TO_JSVAL(js_str)
785
			,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE);
786 787
	if(msg.ftn_area!=NULL
		&& (js_str=JS_NewStringCopyZ(cx,truncsp(msg.ftn_area)))!=NULL)
788
		JS_DefineProperty(cx, hdrobj, "ftn_area"
789
			,STRING_TO_JSVAL(js_str)
790
			,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE);
791 792
	if(msg.ftn_flags!=NULL
		&& (js_str=JS_NewStringCopyZ(cx,truncsp(msg.ftn_flags)))!=NULL)
793
		JS_DefineProperty(cx, hdrobj, "ftn_flags"
794
			,STRING_TO_JSVAL(js_str)
795 796
			,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE);

797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828
	/* Create hdr.field_list[] with repeating header fields (including type and data) */
	if((array=JS_NewArrayObject(cx,0,NULL))!=NULL) {
		items=0;
		for(i=0;i<msg.total_hfields;i++) {
			switch(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(msg.hfield[i].type)
				,NULL,NULL,JSPROP_ENUMERATE);
829 830
			if((js_str=JS_NewStringCopyN(cx,msg.hfield_dat[i],msg.hfield[i].length))==NULL)
				break;
rswindell's avatar