js_msgbase.c 51.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
/* 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)		*
 *																			*
11
 * Copyright 2003 Rob Swindell - http://www.synchro.net/copyright.html		*
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
 *																			*
 * 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

	smb_close(&(p->smb));

	*rval = JSVAL_VOID;
	return(JS_TRUE);
}

115
static BOOL parse_recipient_object(JSContext* cx, private_t* p, JSObject* hdr, smbmsg_t* msg)
116 117
{
	char*		cp;
118
	char		to[256];
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
	ushort		nettype;
	ushort		agent;
	int32		i32;
	jsval		val;

	if(JS_GetProperty(cx, hdr, "to", &val) && val!=JSVAL_VOID) {
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
			return(FALSE);
	} else {
		if(p->smb.status.attr&SMB_EMAIL)	/* e-mail */
			return(FALSE);					/* "to" property required */
		cp="All";
	}
	smb_hfield_str(msg, RECIPIENT, cp);
	if(!(p->smb.status.attr&SMB_EMAIL)) {
		SAFECOPY(to,cp);
		strlwr(to);
		msg->idx.to=crc16(to,0);
	}

rswindell's avatar
rswindell committed
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
	if(JS_GetProperty(cx, hdr, "to_ext", &val) && val!=JSVAL_VOID) {
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
			return(FALSE);
		smb_hfield_str(msg, RECIPIENTEXT, cp);
		if(p->smb.status.attr&SMB_EMAIL)
			msg->idx.to=atoi(cp);
	}

	if(JS_GetProperty(cx, hdr, "to_org", &val) && val!=JSVAL_VOID) {
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
			return(FALSE);
		smb_hfield_str(msg, RECIPIENTORG, cp);
	}

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

	if(JS_GetProperty(cx, hdr, "to_net_addr", &val) && val!=JSVAL_VOID) {
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
			return(FALSE);
		smb_hfield_str(msg, RECIPIENTNETADDR, cp);
	}

	if(JS_GetProperty(cx, hdr, "to_agent", &val) && val!=JSVAL_VOID) {
		JS_ValueToInt32(cx,val,&i32);
		agent=(ushort)i32;
		smb_hfield(msg, RECIPIENTAGENT, sizeof(agent), &agent);
	}
172 173 174 175 176 177 178 179

	return(TRUE);
}

static BOOL parse_header_object(JSContext* cx, private_t* p, JSObject* hdr, smbmsg_t* msg
								,BOOL recipient)
{
	char*		cp;
180
	char		from[256];
181
	ushort		nettype;
182
	ushort		type;
183
	ushort		agent;
184
	ushort		port;
185
	int32		i32;
186
	jsval		val;
187 188 189
	JSObject*	array;
	JSObject*	field;
	jsuint		i,len;
190

191 192 193
	if(hdr==NULL)
		return(FALSE);

194 195 196
	if(recipient && !parse_recipient_object(cx,p,hdr,msg))
		return(FALSE);

197
	/* Required Header Fields */
198
	if(JS_GetProperty(cx, hdr, "subject", &val) && val!=JSVAL_VOID) {
199
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
200 201 202
			return(FALSE);
	} else
		cp="";
203
	smb_hfield_str(msg, SUBJECT, cp);
204
	msg->idx.subj=subject_crc(cp);
205

206
	if(JS_GetProperty(cx, hdr, "from", &val) && val!=JSVAL_VOID) {
207
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
208 209 210
			return(FALSE);
	} else
		return(FALSE);	/* "from" property required */
211
	smb_hfield_str(msg, SENDER, cp);
212
	if(!(p->smb.status.attr&SMB_EMAIL)) {
213 214
		SAFECOPY(from,cp);
		strlwr(from);
215
		msg->idx.from=crc16(from,0);
216
	}
217 218

	/* Optional Header Fields */
219
	if(JS_GetProperty(cx, hdr, "from_ext", &val) && val!=JSVAL_VOID) {
220
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
221
			return(FALSE);
222
		smb_hfield_str(msg, SENDEREXT, cp);
223
		if(p->smb.status.attr&SMB_EMAIL)
224 225 226
			msg->idx.from=atoi(cp);
	}

227
	if(JS_GetProperty(cx, hdr, "from_org", &val) && val!=JSVAL_VOID) {
228
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
229
			return(FALSE);
230
		smb_hfield_str(msg, SENDERORG, cp);
231 232
	}

233
	if(JS_GetProperty(cx, hdr, "from_net_type", &val) && val!=JSVAL_VOID) {
234 235
		JS_ValueToInt32(cx,val,&i32);
		nettype=(ushort)i32;
236
		smb_hfield(msg, SENDERNETTYPE, sizeof(nettype), &nettype);
237
		if(p->smb.status.attr&SMB_EMAIL && nettype!=NET_NONE)
238 239 240
			msg->idx.from=0;
	}

241
	if(JS_GetProperty(cx, hdr, "from_net_addr", &val) && val!=JSVAL_VOID) {
242
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
243
			return(FALSE);
244
		smb_hfield_str(msg, SENDERNETADDR, cp);
245 246
	}

247
	if(JS_GetProperty(cx, hdr, "from_agent", &val) && val!=JSVAL_VOID) {
248 249 250 251 252
		JS_ValueToInt32(cx,val,&i32);
		agent=(ushort)i32;
		smb_hfield(msg, SENDERAGENT, sizeof(agent), &agent);
	}

253 254 255 256 257 258 259 260 261 262 263 264
	if(JS_GetProperty(cx, hdr, "from_ip_addr", &val) && val!=JSVAL_VOID) {
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
			return(FALSE);
		smb_hfield_str(msg, SENDERIPADDR, cp);
	}

	if(JS_GetProperty(cx, hdr, "from_host_name", &val) && val!=JSVAL_VOID) {
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
			return(FALSE);
		smb_hfield_str(msg, SENDERHOSTNAME, cp);
	}

265 266 267 268 269 270 271 272 273 274 275 276
	if(JS_GetProperty(cx, hdr, "from_protocol", &val) && val!=JSVAL_VOID) {
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
			return(FALSE);
		smb_hfield_str(msg, SENDERPROTOCOL, cp);
	}

	if(JS_GetProperty(cx, hdr, "from_port", &val) && val!=JSVAL_VOID) {
		JS_ValueToInt32(cx,val,&i32);
		port=(ushort)i32;
		smb_hfield(msg, SENDERPORT, sizeof(port), &port);
	}

277
	if(JS_GetProperty(cx, hdr, "replyto", &val) && val!=JSVAL_VOID) {
278
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
279
			return(FALSE);
280
		smb_hfield_str(msg, REPLYTO, cp);
281 282
	}

283
	if(JS_GetProperty(cx, hdr, "replyto_ext", &val) && val!=JSVAL_VOID) {
284
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
285
			return(FALSE);
286
		smb_hfield_str(msg, REPLYTOEXT, cp);
287 288
	}

289
	if(JS_GetProperty(cx, hdr, "replyto_org", &val) && val!=JSVAL_VOID) {
290 291
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
			return(FALSE);
292
		smb_hfield_str(msg, REPLYTOORG, cp);
293 294
	}

295
	if(JS_GetProperty(cx, hdr, "replyto_net_type", &val) && val!=JSVAL_VOID) {
296 297
		JS_ValueToInt32(cx,val,&i32);
		nettype=(ushort)i32;
298 299 300
		smb_hfield(msg, REPLYTONETTYPE, sizeof(nettype), &nettype);
	}

301
	if(JS_GetProperty(cx, hdr, "replyto_net_addr", &val) && val!=JSVAL_VOID) {
302
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
303
			return(FALSE);
304
		smb_hfield_str(msg, REPLYTONETADDR, cp);
305 306
	}

307
	if(JS_GetProperty(cx, hdr, "replyto_agent", &val) && val!=JSVAL_VOID) {
308 309 310 311 312
		JS_ValueToInt32(cx,val,&i32);
		agent=(ushort)i32;
		smb_hfield(msg, REPLYTOAGENT, sizeof(agent), &agent);
	}

313
	/* RFC822 headers */
314
	if(JS_GetProperty(cx, hdr, "id", &val) && val!=JSVAL_VOID) {
315
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
316
			return(FALSE);
317
		smb_hfield_str(msg, RFC822MSGID, cp);
318 319
	}

320
	if(JS_GetProperty(cx, hdr, "reply_id", &val) && val!=JSVAL_VOID) {
321
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
322
			return(FALSE);
323
		smb_hfield_str(msg, RFC822REPLYID, cp);
324 325
	}

326
	if(JS_GetProperty(cx, hdr, "reverse_path", &val) && val!=JSVAL_VOID) {
327
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
328
			return(FALSE);
329
		smb_hfield_str(msg, SMTPREVERSEPATH, cp);
330 331
	}

332
	/* USENET headers */
333
	if(JS_GetProperty(cx, hdr, "path", &val) && val!=JSVAL_VOID) {
334
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
335
			return(FALSE);
336
		smb_hfield_str(msg, USENETPATH, cp);
337 338
	}

339
	if(JS_GetProperty(cx, hdr, "newsgroups", &val) && val!=JSVAL_VOID) {
340
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
341
			return(FALSE);
342
		smb_hfield_str(msg, USENETNEWSGROUPS, cp);
343 344 345
	}

	/* FTN headers */
346
	if(JS_GetProperty(cx, hdr, "ftn_msgid", &val) && val!=JSVAL_VOID) {
347
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
348
			return(FALSE);
349
		smb_hfield_str(msg, FIDOMSGID, cp);
350 351
	}

352
	if(JS_GetProperty(cx, hdr, "ftn_reply", &val) && val!=JSVAL_VOID) {
353
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
354
			return(FALSE);
355
		smb_hfield_str(msg, FIDOREPLYID, cp);
356 357
	}

358
	if(JS_GetProperty(cx, hdr, "ftn_area", &val) && val!=JSVAL_VOID) {
359
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
360
			return(FALSE);
361
		smb_hfield_str(msg, FIDOAREA, cp);
362 363
	}

364
	if(JS_GetProperty(cx, hdr, "ftn_flags", &val) && val!=JSVAL_VOID) {
365
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
366
			return(FALSE);
367
		smb_hfield_str(msg, FIDOFLAGS, cp);
368 369
	}

370
	if(JS_GetProperty(cx, hdr, "ftn_pid", &val) && val!=JSVAL_VOID) {
371
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
372
			return(FALSE);
373
		smb_hfield_str(msg, FIDOPID, cp);
374 375
	}

376
	if(JS_GetProperty(cx, hdr, "ftn_tid", &val) && val!=JSVAL_VOID) {
377
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
378
			return(FALSE);
379
		smb_hfield_str(msg, FIDOTID, cp);
380 381
	}

382
	if(JS_GetProperty(cx, hdr, "date", &val) && val!=JSVAL_VOID) {
383
		if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
384 385 386
			return(FALSE);
		msg->hdr.when_written=rfc822date(cp);
	}
387 388
	
	/* Numeric Header Fields */
389
	if(JS_GetProperty(cx, hdr, "attr", &val) && val!=JSVAL_VOID) {
390 391
		JS_ValueToInt32(cx,val,&i32);
		msg->hdr.attr=(ushort)i32;
392 393
		msg->idx.attr=msg->hdr.attr;
	}
394
	if(JS_GetProperty(cx, hdr, "auxattr", &val) && val!=JSVAL_VOID) {
395 396 397
		JS_ValueToInt32(cx,val,&i32);
		msg->hdr.auxattr=i32;
	}
398
	if(JS_GetProperty(cx, hdr, "netattr", &val) && val!=JSVAL_VOID) {
399 400 401
		JS_ValueToInt32(cx,val,&i32);
		msg->hdr.netattr=i32;
	}
402
	if(JS_GetProperty(cx, hdr, "when_written_time", &val) && val!=JSVAL_VOID)  {
403 404 405
		JS_ValueToInt32(cx,val,&i32);
		msg->hdr.when_written.time=i32;
	}
406
	if(JS_GetProperty(cx, hdr, "when_written_zone", &val) && val!=JSVAL_VOID) {
407 408 409
		JS_ValueToInt32(cx,val,&i32);
		msg->hdr.when_written.zone=(short)i32;
	}
410
	if(JS_GetProperty(cx, hdr, "when_imported_time", &val) && val!=JSVAL_VOID) {
411 412 413
		JS_ValueToInt32(cx,val,&i32);
		msg->hdr.when_imported.time=i32;
	}
414
	if(JS_GetProperty(cx, hdr, "when_imported_zone", &val) && val!=JSVAL_VOID) {
415 416 417 418
		JS_ValueToInt32(cx,val,&i32);
		msg->hdr.when_imported.zone=(short)i32;
	}

419
	if(JS_GetProperty(cx, hdr, "thread_orig", &val) && val!=JSVAL_VOID) {
420 421 422
		JS_ValueToInt32(cx,val,&i32);
		msg->hdr.thread_orig=i32;
	}
423
	if(JS_GetProperty(cx, hdr, "thread_next", &val) && val!=JSVAL_VOID) {
424 425 426
		JS_ValueToInt32(cx,val,&i32);
		msg->hdr.thread_next=i32;
	}
427
	if(JS_GetProperty(cx, hdr, "thread_first", &val) && val!=JSVAL_VOID) {
428 429 430
		JS_ValueToInt32(cx,val,&i32);
		msg->hdr.thread_first=i32;
	}
431

432 433 434
	if(JS_GetProperty(cx, hdr, "field_list", &val) && JSVAL_IS_OBJECT(val)) {
		array=JSVAL_TO_OBJECT(val);
		len=0;
435 436
		if(!JS_GetArrayLength(cx, array, &len))
			return(FALSE);
437 438 439 440 441 442 443

		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);
444
			if(!JS_GetProperty(cx, field, "type", &val))
445
				continue;
446 447 448 449 450 451
			if(JSVAL_IS_STRING(val))
				type=smb_hfieldtypelookup(JS_GetStringBytes(JS_ValueToString(cx,val)));
			else {
				JS_ValueToInt32(cx,val,&i32);
				type=(ushort)i32;
			}
452
			if(!JS_GetProperty(cx, field, "data", &val))
453
				continue;
454
			if((cp=JS_GetStringBytes(JS_ValueToString(cx,val)))==NULL)
455
				return(FALSE);
456
			smb_hfield_str(msg, type, cp);
457 458 459
		}
	}

460 461 462
	return(TRUE);
}

463
BOOL msg_offset_by_id(scfg_t* scfg, smb_t* smb, char* id, ulong* offset)
464 465 466
{
	smbmsg_t msg;

467
	if(!get_msg_by_id(scfg,smb,id,&msg))
468 469 470 471 472 473 474 475
		return(FALSE);

	smb_freemsgmem(&msg);

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

476 477 478 479
static JSBool
js_get_msg_index(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
	uintN		n;
480
	jsval		val;
481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500
	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]);
501
		else if(JSVAL_IS_NUMBER(argv[n])) {
502
			if(by_offset)							/* Get by offset */
503
				JS_ValueToInt32(cx,argv[n],(int32*)&msg.offset);
504
			else									/* Get by number */
505
				JS_ValueToInt32(cx,argv[n],(int32*)&msg.hdr.number);
506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531

			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);

532 533
	JS_NewNumberValue(cx,msg.idx.offset,&val);
	JS_DefineProperty(cx, idxobj, "offset", val
534 535
		,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE);

536 537
	JS_NewNumberValue(cx,msg.idx.time,&val);
	JS_DefineProperty(cx, idxobj, "time", val
538 539 540 541 542 543 544
		,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE);

	*rval = OBJECT_TO_JSVAL(idxobj);

	return(JS_TRUE);
}

545 546 547
static JSBool
js_get_msg_header(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
548
	char		date[128];
549 550
	char		msg_id[256];
	char		reply_id[256];
551
	char*		val;
552
	ushort*		port;
553
	int			i;
554
	uintN		n;
555
	smbmsg_t	msg;
556
	smbmsg_t	orig_msg;
557
	JSObject*	hdrobj;
558 559
	JSObject*	array;
	JSObject*	field;
560
	JSString*	js_str;
561
	jsint		items;
562
	jsval		v;
563
	JSBool		by_offset=JS_FALSE;
564
	JSBool		expand_fields=JS_TRUE;
565 566 567 568
	private_t*	p;

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

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

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

579
	/* Parse boolean arguments first */
580
	for(n=0;n<argc;n++) {
581 582 583 584 585
		if(!JSVAL_IS_BOOLEAN(argv[n]))
			continue;
		if(n)
			expand_fields=JSVAL_TO_BOOLEAN(argv[n]);
		else
586
			by_offset=JSVAL_TO_BOOLEAN(argv[n]);
587 588 589 590 591
	}

	/* Now parse message offset/id and get message */
	for(n=0;n<argc;n++) {
		if(JSVAL_IS_NUMBER(argv[n])) {
592
			if(by_offset)							/* Get by offset */
593
				JS_ValueToInt32(cx,argv[n],(int32*)&msg.offset);
594
			else									/* Get by number */
595
				JS_ValueToInt32(cx,argv[n],(int32*)&msg.hdr.number);
596 597 598 599 600 601 602 603 604 605 606 607 608

			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); 
609 610
			break;
		} else if(JSVAL_IS_STRING(argv[n]))	{		/* Get by ID */
611
			if(!get_msg_by_id(scfg,&(p->smb)
612
				,JS_GetStringBytes(JSVAL_TO_STRING(argv[n]))
613
				,&msg))
614
				return(JS_TRUE);	/* ID not found */
615

616 617 618
			break;
		}
	}
619

620
	if(msg.hdr.number==0) /* No valid message number/id/offset specified */
621 622
		return(JS_TRUE);

623
	if((hdrobj=JS_NewObject(cx,NULL,NULL,obj))==NULL) {
rswindell's avatar
rswindell committed
624
		smb_freemsgmem(&msg);
625
		return(JS_TRUE);
rswindell's avatar
rswindell committed
626
	}
627

628 629
	JS_NewNumberValue(cx,msg.hdr.number,&v);
	JS_DefineProperty(cx, hdrobj, "number", v, NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE);
630 631 632

	if((js_str=JS_NewStringCopyZ(cx,truncsp(msg.to)))==NULL)
		return(JS_FALSE);
633
	JS_DefineProperty(cx, hdrobj, "to"
634
		,STRING_TO_JSVAL(js_str)
635
		,NULL,NULL,JSPROP_ENUMERATE);
636 637 638

	if((js_str=JS_NewStringCopyZ(cx,truncsp(msg.from)))==NULL)
		return(JS_FALSE);
639
	JS_DefineProperty(cx, hdrobj, "from"
640
		,STRING_TO_JSVAL(js_str)
641
		,NULL,NULL,JSPROP_ENUMERATE);
642 643 644

	if((js_str=JS_NewStringCopyZ(cx,truncsp(msg.subj)))==NULL)
		return(JS_FALSE);
645
	JS_DefineProperty(cx, hdrobj, "subject"
646
		,STRING_TO_JSVAL(js_str)
647
		,NULL,NULL,JSPROP_ENUMERATE);
648 649
	if(msg.summary!=NULL 
		&& (js_str=JS_NewStringCopyZ(cx,truncsp(msg.summary)))!=NULL)
650
		JS_DefineProperty(cx, hdrobj, "summary"
651
			,STRING_TO_JSVAL(js_str)
652
			,NULL,NULL,JSPROP_ENUMERATE);
653 654
	if(msg.to_ext!=NULL 
		&& (js_str=JS_NewStringCopyZ(cx,truncsp(msg.to_ext)))!=NULL)
655
		JS_DefineProperty(cx, hdrobj, "to_ext"
656
			,STRING_TO_JSVAL(js_str)
657
			,NULL,NULL,JSPROP_ENUMERATE);
658 659
	if(msg.from_ext!=NULL 
		&& (js_str=JS_NewStringCopyZ(cx,truncsp(msg.from_ext)))!=NULL)
660
		JS_DefineProperty(cx, hdrobj, "from_ext"
661
			,STRING_TO_JSVAL(js_str)
662
			,NULL,NULL,JSPROP_ENUMERATE);
663 664
	if(msg.from_org!=NULL
		&& (js_str=JS_NewStringCopyZ(cx,truncsp(msg.from_org)))!=NULL)
665
		JS_DefineProperty(cx, hdrobj, "from_org"
666
			,STRING_TO_JSVAL(js_str)
667
			,NULL,NULL,JSPROP_ENUMERATE);
668 669
	if(msg.replyto!=NULL
		&& (js_str=JS_NewStringCopyZ(cx,truncsp(msg.replyto)))!=NULL)
670
		JS_DefineProperty(cx, hdrobj, "replyto"
671
			,STRING_TO_JSVAL(js_str)
672
			,NULL,NULL,JSPROP_ENUMERATE);
673 674
	if(msg.replyto_ext!=NULL
		&& (js_str=JS_NewStringCopyZ(cx,truncsp(msg.replyto_ext)))!=NULL)
675
		JS_DefineProperty(cx, hdrobj, "replyto_ext"
676
			,STRING_TO_JSVAL(js_str)
677
			,NULL,NULL,JSPROP_ENUMERATE);
678 679
	if(msg.reverse_path!=NULL
		&& (js_str=JS_NewStringCopyZ(cx,truncsp(msg.reverse_path)))!=NULL)
680
		JS_DefineProperty(cx, hdrobj, "reverse_path"
681
			,STRING_TO_JSVAL(js_str)
682
			,NULL,NULL,JSPROP_ENUMERATE);
683

684 685 686 687 688 689 690 691 692
	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);
693

694 695 696
	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);
697 698
	if(msg.to_net.type
		&& (js_str=JS_NewStringCopyZ(cx,net_addr(&msg.to_net)))!=NULL)
699
		JS_DefineProperty(cx, hdrobj, "to_net_addr"
700
			,STRING_TO_JSVAL(js_str)
701
			,NULL,NULL,JSPROP_ENUMERATE);
702

703 704 705
	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);
706 707
	if(msg.from_net.type
		&& (js_str=JS_NewStringCopyZ(cx,net_addr(&msg.from_net)))!=NULL)
708
		JS_DefineProperty(cx, hdrobj, "from_net_addr"
709
			,STRING_TO_JSVAL(js_str)
710
			,NULL,NULL,JSPROP_ENUMERATE);
711

712 713 714 715

	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);
716 717
	if(msg.replyto_net.type
		&& (js_str=JS_NewStringCopyZ(cx,net_addr(&msg.replyto_net)))!=NULL)
718
		JS_DefineProperty(cx, hdrobj, "replyto_net_addr"
719
			,STRING_TO_JSVAL(js_str)
720
			,NULL,NULL,JSPROP_ENUMERATE);
721

722 723 724 725 726 727 728 729 730 731 732
	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);
733 734 735 736 737 738 739 740 741 742 743

	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);
744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759
	
	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);
	}
760

761
	/* Fixed length portion of msg header */
762
	JS_DefineProperty(cx, hdrobj, "type", INT_TO_JSVAL(msg.hdr.type)
763
		,NULL,NULL,JSPROP_ENUMERATE);
764
	JS_DefineProperty(cx, hdrobj, "version", INT_TO_JSVAL(msg.hdr.version)
765
		,NULL,NULL,JSPROP_ENUMERATE);
766
	JS_DefineProperty(cx, hdrobj, "attr", INT_TO_JSVAL(msg.hdr.attr)
767
		,NULL,NULL,JSPROP_ENUMERATE);
768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797
	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_orig,&v);
	JS_DefineProperty(cx, hdrobj, "thread_orig", v, NULL,NULL,JSPROP_ENUMERATE);
	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);
798

799 800
	if((js_str=JS_NewStringCopyZ(cx,msgdate(msg.hdr.when_written,date)))==NULL)
		return(JS_FALSE);
801
	JS_DefineProperty(cx, hdrobj, "date"
802
		,STRING_TO_JSVAL(js_str)
803
		,NULL,NULL,JSPROP_ENUMERATE);
804

805
	/* Reply-ID (References) */
806
	if(msg.reply_id!=NULL)
807 808 809
		val=msg.reply_id;
	else {
		reply_id[0]=0;
810
		if(expand_fields && msg.hdr.thread_orig) {
811 812 813 814 815
			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
816
				SAFECOPY(reply_id,get_msgid(scfg,p->smb.subnum,&orig_msg));
817
		}
818 819
		val=reply_id;
	}
820
	if(val[0] && (js_str=JS_NewStringCopyZ(cx,truncsp(val)))!=NULL)
821
		JS_DefineProperty(cx, hdrobj, "reply_id"
822
			, STRING_TO_JSVAL(js_str)
823
			,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE);
824 825

	/* Message-ID */
826 827 828 829 830 831 832 833 834
	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_READONLY|JSPROP_ENUMERATE);
	}
835

836
	/* USENET Fields */
837 838
	if(msg.path!=NULL
		&& (js_str=JS_NewStringCopyZ(cx,truncsp(msg.path)))!=NULL)
839
		JS_DefineProperty(cx, hdrobj, "path"
840
			,STRING_TO_JSVAL(js_str)
841
			,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE);
842 843
	if(msg.newsgroups!=NULL
		&& (js_str=JS_NewStringCopyZ(cx,truncsp(msg.newsgroups)))!=NULL)
844
		JS_DefineProperty(cx, hdrobj, "newsgroups"
845
			,STRING_TO_JSVAL(js_str)
846 847
			,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE);

848
	/* FidoNet Header Fields */
849 850
	if(msg.ftn_msgid!=NULL
		&& (js_str=JS_NewStringCopyZ(cx,truncsp(msg.ftn_msgid)))!=NULL)