|
|
1.1 root 1: /* js_msg_area.c */
2:
3: /* Synchronet JavaScript "Message Area" Object */
4:
5: /* $Id: js_msg_area.c,v 1.47 2004/12/31 02:39:19 rswindell Exp $ */
6:
7: /****************************************************************************
8: * @format.tab-size 4 (Plain Text/Source Code File Header) *
9: * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
10: * *
11: * Copyright 2004 Rob Swindell - http://www.synchro.net/copyright.html *
12: * *
13: * This program is free software; you can redistribute it and/or *
14: * modify it under the terms of the GNU General Public License *
15: * as published by the Free Software Foundation; either version 2 *
16: * of the License, or (at your option) any later version. *
17: * See the GNU General Public License for more details: gpl.txt or *
18: * http://www.fsf.org/copyleft/gpl.html *
19: * *
20: * Anonymous FTP access to the most recent released source is available at *
21: * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
22: * *
23: * Anonymous CVS access to the development source and modification history *
24: * is available at cvs.synchro.net:/cvsroot/sbbs, example: *
25: * cvs -d :pserver:[email protected]:/cvsroot/sbbs login *
26: * (just hit return, no password is necessary) *
27: * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src *
28: * *
29: * For Synchronet coding style and modification guidelines, see *
30: * http://www.synchro.net/source.html *
31: * *
32: * You are encouraged to submit any modifications (preferably in Unix diff *
33: * format) via e-mail to [email protected] *
34: * *
35: * Note: If this box doesn't appear square, then you need to fix your tabs. *
36: ****************************************************************************/
37:
38: #include "sbbs.h"
39:
40: #ifdef JAVASCRIPT
41:
42: enum { /* msg_area Object Properties */
43: PROP_MAX_QWK_MSGS
44: };
45:
46: #ifdef _DEBUG
47:
48: static char* msg_grp_prop_desc[] = {
49: "index into grp_list array (or -1 if not in array) <i>(introduced in v3.12)</i>"
50: ,"unique number for this message group"
51: ,"group name"
52: ,"group description"
53: ,"group access requirements"
54: ,NULL
55: };
56:
57: static char* msg_area_prop_desc[] = {
58:
59: "index into sub_list array (or -1 if not in array) <i>(introduced in v3.12)</i>"
60: ,"group's index into grp_list array <i>(introduced in v3.12)</i>"
61: ,"unique number for this sub-board"
62: ,"group number"
63: ,"group name <i>(introduced in v3.12)</i>"
64: ,"sub-board internal code"
65: ,"sub-board name"
66: ,"sub-board description"
67: ,"sub-board QWK name"
68: ,"newsgroup name (as configured or dymamically generated)"
69: ,"sub-board access requirements"
70: ,"sub-board reading requirements"
71: ,"sub-board posting requirements"
72: ,"sub-board operator requirements"
73: ,"sub-board moderated-user requirements (if non-blank)"
74: ,"sub-board data storage location"
75: ,"FidoNet origin line"
76: ,"QWK Network tagline"
77: ,"toggle options (bitfield)"
78: ,"index into message scan configuration/pointer file"
79: ,"QWK conference number"
80: ,"configured maximum number of message CRCs to store (for dupe checking)"
81: ,"configured maximum number of messages before purging"
82: ,"configured maximum age (in days) of messages before expiration"
83: /* Insert here */
84: ,"user has sufficient access to read messages"
85: ,"user has sufficient access to post messages"
86: ,"user has operator access to this message area"
87: ,"user's posts are moderated"
88: ,"user's current new message scan pointer (highest-read message number)"
89: ,"user's message scan configuration (bitfield) see <tt>SCAN_CFG_*</tt> in <tt>sbbsdefs.js</tt> for valid bits"
90: ,"user's last-read message number"
91: ,NULL
92: };
93: #endif
94:
95: BOOL DLLCALL js_CreateMsgAreaProperties(JSContext* cx, scfg_t* cfg, JSObject* subobj, uint subnum)
96: {
97: char str[128];
98: int c;
99: JSString* js_str;
100: jsval val;
101: sub_t* sub;
102:
103: if(subnum==INVALID_SUB || subnum>=cfg->total_subs)
104: return(FALSE);
105:
106: sub=cfg->sub[subnum];
107:
108: if(!JS_DefineProperty(cx, subobj, "number", INT_TO_JSVAL(subnum)
109: ,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY))
110: return(FALSE);
111:
112: if(!JS_DefineProperty(cx, subobj, "grp_number", INT_TO_JSVAL(sub->grp)
113: ,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY))
114: return(FALSE);
115:
116: if((js_str=JS_NewStringCopyZ(cx, cfg->grp[sub->grp]->sname))==NULL)
117: return(FALSE);
118: if(!JS_DefineProperty(cx, subobj, "grp_name", STRING_TO_JSVAL(js_str)
119: ,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY))
120: return(FALSE);
121:
122: if((js_str=JS_NewStringCopyZ(cx, sub->code))==NULL)
123: return(FALSE);
124: if(!JS_DefineProperty(cx, subobj, "code", STRING_TO_JSVAL(js_str)
125: ,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY))
126: return(FALSE);
127:
128: if((js_str=JS_NewStringCopyZ(cx, sub->sname))==NULL)
129: return(FALSE);
130: if(!JS_DefineProperty(cx, subobj, "name", STRING_TO_JSVAL(js_str)
131: ,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY))
132: return(FALSE);
133:
134: if((js_str=JS_NewStringCopyZ(cx, sub->lname))==NULL)
135: return(FALSE);
136: if(!JS_DefineProperty(cx, subobj, "description", STRING_TO_JSVAL(js_str)
137: ,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY))
138: return(FALSE);
139:
140: if((js_str=JS_NewStringCopyZ(cx, sub->qwkname))==NULL)
141: return(FALSE);
142: if(!JS_DefineProperty(cx, subobj, "qwk_name", STRING_TO_JSVAL(js_str)
143: ,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY))
144: return(FALSE);
145:
146: if(sub->newsgroup[0])
147: SAFECOPY(str,sub->newsgroup);
148: else {
149: sprintf(str,"%s.%s",cfg->grp[sub->grp]->sname,sub->sname);
150: for(c=0;str[c];c++)
151: if(str[c]==' ')
152: str[c]='_';
153: }
154: if((js_str=JS_NewStringCopyZ(cx, str))==NULL)
155: return(FALSE);
156: if(!JS_DefineProperty(cx, subobj, "newsgroup", STRING_TO_JSVAL(js_str)
157: ,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY))
158: return(FALSE);
159:
160: if((js_str=JS_NewStringCopyZ(cx, sub->arstr))==NULL)
161: return(FALSE);
162: if(!JS_DefineProperty(cx, subobj, "ars", STRING_TO_JSVAL(js_str)
163: ,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY))
164: return(FALSE);
165:
166: if((js_str=JS_NewStringCopyZ(cx, sub->read_arstr))==NULL)
167: return(FALSE);
168: if(!JS_DefineProperty(cx, subobj, "read_ars", STRING_TO_JSVAL(js_str)
169: ,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY))
170: return(FALSE);
171:
172: if((js_str=JS_NewStringCopyZ(cx, sub->post_arstr))==NULL)
173: return(FALSE);
174: if(!JS_DefineProperty(cx, subobj, "post_ars", STRING_TO_JSVAL(js_str)
175: ,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY))
176: return(FALSE);
177:
178: if((js_str=JS_NewStringCopyZ(cx, sub->op_arstr))==NULL)
179: return(FALSE);
180: if(!JS_DefineProperty(cx, subobj, "operator_ars", STRING_TO_JSVAL(js_str)
181: ,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY))
182: return(FALSE);
183:
184: if((js_str=JS_NewStringCopyZ(cx, sub->mod_arstr))==NULL)
185: return(FALSE);
186: if(!JS_DefineProperty(cx, subobj, "moderated_ars", STRING_TO_JSVAL(js_str)
187: ,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY))
188: return(FALSE);
189:
190: if((js_str=JS_NewStringCopyZ(cx, sub->data_dir))==NULL)
191: return(FALSE);
192: if(!JS_DefineProperty(cx, subobj, "data_dir", STRING_TO_JSVAL(js_str)
193: ,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY))
194: return(FALSE);
195:
196: if((js_str=JS_NewStringCopyZ(cx, sub->origline))==NULL)
197: return(FALSE);
198: if(!JS_DefineProperty(cx, subobj, "fidonet_origin", STRING_TO_JSVAL(js_str)
199: ,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY))
200: return(FALSE);
201:
202: if((js_str=JS_NewStringCopyZ(cx, sub->tagline))==NULL)
203: return(FALSE);
204: if(!JS_DefineProperty(cx, subobj, "qwknet_tagline", STRING_TO_JSVAL(js_str)
205: ,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY))
206: return(FALSE);
207:
208: if(!JS_NewNumberValue(cx,sub->misc,&val))
209: return(FALSE);
210: if(!JS_DefineProperty(cx, subobj, "settings", val
211: ,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY))
212: return(FALSE);
213:
214: if(!JS_DefineProperty(cx, subobj, "ptridx", INT_TO_JSVAL(sub->ptridx)
215: ,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY))
216: return(FALSE);
217:
218: if(!JS_DefineProperty(cx, subobj, "qwk_conf", INT_TO_JSVAL(sub->qwkconf)
219: ,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY))
220: return(FALSE);
221:
222: if(!JS_DefineProperty(cx, subobj, "max_crcs", INT_TO_JSVAL(sub->maxcrcs)
223: ,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY))
224: return(FALSE);
225:
226: if(!JS_DefineProperty(cx, subobj, "max_msgs", INT_TO_JSVAL(sub->maxmsgs)
227: ,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY))
228: return(FALSE);
229:
230: if(!JS_DefineProperty(cx, subobj, "max_age", INT_TO_JSVAL(sub->maxage)
231: ,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY))
232: return(FALSE);
233:
234: #ifdef _DEBUG
235: js_CreateArrayOfStrings(cx, subobj, "_property_desc_list", msg_area_prop_desc, JSPROP_READONLY);
236: #endif
237:
238: return(TRUE);
239: }
240:
241: /*******************************************/
242: /* Re-writable Sub-board Object Properites */
243: /*******************************************/
244: enum {
245: SUB_PROP_SCAN_PTR
246: ,SUB_PROP_SCAN_CFG
247: ,SUB_PROP_LAST_READ
248: };
249:
250:
251: static JSBool js_sub_get(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
252: {
253: jsint tiny;
254: subscan_t* scan;
255:
256: if((scan=(subscan_t*)JS_GetPrivate(cx,obj))==NULL)
257: return(JS_TRUE);
258:
259: tiny = JSVAL_TO_INT(id);
260:
261: switch(tiny) {
262: case SUB_PROP_SCAN_PTR:
263: JS_NewNumberValue(cx,scan->ptr,vp);
264: break;
265: case SUB_PROP_SCAN_CFG:
266: JS_NewNumberValue(cx,scan->cfg,vp);
267: break;
268: case SUB_PROP_LAST_READ:
269: JS_NewNumberValue(cx,scan->last,vp);
270: break;
271: }
272:
273: return(JS_TRUE);
274: }
275:
276: static JSBool js_sub_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
277: {
278: int32 val=0;
279: jsint tiny;
280: subscan_t* scan;
281:
282: if((scan=(subscan_t*)JS_GetPrivate(cx,obj))==NULL)
283: return(JS_TRUE);
284:
285: tiny = JSVAL_TO_INT(id);
286:
287: switch(tiny) {
288: case SUB_PROP_SCAN_PTR:
289: JS_ValueToInt32(cx, *vp, (int32*)&scan->ptr);
290: break;
291: case SUB_PROP_SCAN_CFG:
292: JS_ValueToInt32(cx, *vp, &val);
293: scan->cfg=(ushort)val;
294: break;
295: case SUB_PROP_LAST_READ:
296: JS_ValueToInt32(cx, *vp, (int32*)&scan->last);
297: break;
298: }
299:
300: return(JS_TRUE);
301: }
302:
303: static struct JSPropertySpec js_sub_properties[] = {
304: /* name ,tinyid ,flags */
305:
306: { "scan_ptr" ,SUB_PROP_SCAN_PTR ,JSPROP_ENUMERATE|JSPROP_SHARED },
307: { "scan_cfg" ,SUB_PROP_SCAN_CFG ,JSPROP_ENUMERATE|JSPROP_SHARED },
308: { "lead_read" ,SUB_PROP_LAST_READ ,JSPROP_ENUMERATE|JSPROP_SHARED },
309: {0}
310: };
311:
312:
313: static JSClass js_sub_class = {
314: "Message Sub-board" /* name */
315: ,JSCLASS_HAS_PRIVATE /* flags */
316: ,JS_PropertyStub /* addProperty */
317: ,JS_PropertyStub /* delProperty */
318: ,js_sub_get /* getProperty */
319: ,js_sub_set /* setProperty */
320: ,JS_EnumerateStub /* enumerate */
321: ,JS_ResolveStub /* resolve */
322: ,JS_ConvertStub /* convert */
323: ,JS_FinalizeStub /* finalize */
324: };
325:
326: JSObject* DLLCALL js_CreateMsgAreaObject(JSContext* cx, JSObject* parent, scfg_t* cfg
327: ,user_t* user, subscan_t* subscan)
328: {
329: JSObject* areaobj;
330: JSObject* allgrps;
331: JSObject* allsubs;
332: JSObject* grpobj;
333: JSObject* subobj;
334: JSObject* grp_list;
335: JSObject* sub_list;
336: JSString* js_str;
337: jsval val;
338: jsuint grp_index;
339: jsuint sub_index;
340: uint l,d;
341:
342: /* Return existing object if it's already been created */
343: if(JS_GetProperty(cx,parent,"msg_area",&val) && val!=JSVAL_VOID)
344: areaobj = JSVAL_TO_OBJECT(val);
345: else
346: areaobj = JS_DefineObject(cx, parent, "msg_area", NULL
347: , NULL, JSPROP_ENUMERATE|JSPROP_READONLY);
348:
349: if(areaobj==NULL)
350: return(NULL);
351:
352: #ifdef _DEBUG
353: js_DescribeSyncObject(cx,areaobj,"Message Areas",310);
354: #endif
355:
356: /* msg_area.grp[] */
357: if((allgrps=JS_NewObject(cx, NULL, NULL, areaobj))==NULL)
358: return(NULL);
359:
360: val=OBJECT_TO_JSVAL(allgrps);
361: if(!JS_SetProperty(cx, areaobj, "grp", &val))
362: return(NULL);
363:
364: /* msg_area.sub[] */
365: if((allsubs=JS_NewObject(cx, NULL, NULL, areaobj))==NULL)
366: return(NULL);
367:
368: val=OBJECT_TO_JSVAL(allsubs);
369: if(!JS_SetProperty(cx, areaobj, "sub", &val))
370: return(NULL);
371:
372: /* msg_area.grp_list[] */
373: if((grp_list=JS_NewArrayObject(cx, 0, NULL))==NULL)
374: return(NULL);
375:
376: val=OBJECT_TO_JSVAL(grp_list);
377: if(!JS_SetProperty(cx, areaobj, "grp_list", &val))
378: return(NULL);
379:
380: for(l=0;l<cfg->total_grps;l++) {
381:
382: if((grpobj=JS_NewObject(cx, NULL, NULL, NULL))==NULL)
383: return(NULL);
384:
385: grp_index=-1;
386: if(user==NULL || chk_ar(cfg,cfg->grp[l]->ar,user)) {
387:
388: if(!JS_GetArrayLength(cx, grp_list, &grp_index))
389: return(NULL);
390:
391: val=OBJECT_TO_JSVAL(grpobj);
392: if(!JS_SetElement(cx, grp_list, grp_index, &val))
393: return(NULL);
394: }
395:
396: /* Add as property (associative array element) */
397: if(!JS_DefineProperty(cx, allgrps, cfg->grp[l]->sname, val
398: ,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE))
399: return(NULL);
400:
401: val=INT_TO_JSVAL(grp_index);
402: if(!JS_SetProperty(cx, grpobj, "index", &val))
403: return(NULL);
404:
405: val=INT_TO_JSVAL(l);
406: if(!JS_SetProperty(cx, grpobj, "number", &val))
407: return(NULL);
408:
409: if((js_str=JS_NewStringCopyZ(cx, cfg->grp[l]->sname))==NULL)
410: return(NULL);
411: val=STRING_TO_JSVAL(js_str);
412: if(!JS_SetProperty(cx, grpobj, "name", &val))
413: return(NULL);
414:
415: if((js_str=JS_NewStringCopyZ(cx, cfg->grp[l]->lname))==NULL)
416: return(NULL);
417: val=STRING_TO_JSVAL(js_str);
418: if(!JS_SetProperty(cx, grpobj, "description", &val))
419: return(NULL);
420:
421: if((js_str=JS_NewStringCopyZ(cx, cfg->grp[l]->arstr))==NULL)
422: return(NULL);
423: if(!JS_DefineProperty(cx, grpobj, "ars", STRING_TO_JSVAL(js_str)
424: ,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY))
425: return(NULL);
426:
427: #ifdef _DEBUG
428: js_DescribeSyncObject(cx,grpobj,"Message Groups (current user has access to)",310);
429: #endif
430:
431: /* sub_list[] */
432: if((sub_list=JS_NewArrayObject(cx, 0, NULL))==NULL)
433: return(NULL);
434:
435: val=OBJECT_TO_JSVAL(sub_list);
436: if(!JS_SetProperty(cx, grpobj, "sub_list", &val))
437: return(NULL);
438:
439: for(d=0;d<cfg->total_subs;d++) {
440: if(cfg->sub[d]->grp!=l)
441: continue;
442:
443: if((subobj=JS_NewObject(cx, &js_sub_class, NULL, NULL))==NULL)
444: return(NULL);
445:
446: if(subscan!=NULL)
447: JS_SetPrivate(cx,subobj,&subscan[d]);
448:
449: sub_index=-1;
450:
451: if(user==NULL || chk_ar(cfg,cfg->sub[d]->ar,user)) {
452:
453: if(!JS_GetArrayLength(cx, sub_list, &sub_index))
454: return(NULL);
455:
456: val=OBJECT_TO_JSVAL(subobj);
457: if(!JS_SetElement(cx, sub_list, sub_index, &val))
458: return(NULL);
459: }
460:
461: /* Add as property (associative array element) */
462: if(!JS_DefineProperty(cx, allsubs, cfg->sub[d]->code, val
463: ,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE))
464: return(NULL);
465:
466: val=INT_TO_JSVAL(sub_index);
467: if(!JS_SetProperty(cx, subobj, "index", &val))
468: return(NULL);
469:
470: val=INT_TO_JSVAL(grp_index);
471: if(!JS_SetProperty(cx, subobj, "grp_index", &val))
472: return(NULL);
473:
474: if(!js_CreateMsgAreaProperties(cx, cfg, subobj, d))
475: return(NULL);
476:
477: if(user==NULL || chk_ar(cfg,cfg->sub[d]->read_ar,user))
478: val=BOOLEAN_TO_JSVAL(JS_TRUE);
479: else
480: val=BOOLEAN_TO_JSVAL(JS_FALSE);
481: if(!JS_SetProperty(cx, subobj, "can_read", &val))
482: return(NULL);
483:
484: if(user==NULL)
485: val=BOOLEAN_TO_JSVAL(JS_TRUE);
486: else if(cfg->sub[d]->misc&(SUB_QNET|SUB_FIDO|SUB_PNET|SUB_INET)
487: && user->rest&FLAG('N')) /* network restriction? */
488: val=BOOLEAN_TO_JSVAL(JS_FALSE);
489: else if(!chk_ar(cfg,cfg->sub[d]->post_ar,user)
490: || user->rest&FLAG('P')) /* post restriction? */
491: val=BOOLEAN_TO_JSVAL(JS_FALSE);
492: else
493: val=BOOLEAN_TO_JSVAL(JS_TRUE);
494: if(!JS_SetProperty(cx, subobj, "can_post", &val))
495: return(NULL);
496:
497: if(user!=NULL &&
498: (user->level>=SYSOP_LEVEL ||
499: (cfg->sub[d]->op_ar[0]!=0 && chk_ar(cfg,cfg->sub[d]->op_ar,user))))
500: val=BOOLEAN_TO_JSVAL(JS_TRUE);
501: else
502: val=BOOLEAN_TO_JSVAL(JS_FALSE);
503: if(!JS_SetProperty(cx, subobj, "is_operator", &val))
504: return(NULL);
505:
506: if(cfg->sub[d]->mod_ar[0]!=0 && user!=NULL
507: && chk_ar(cfg,cfg->sub[d]->mod_ar,user))
508: val=BOOLEAN_TO_JSVAL(JS_TRUE);
509: else
510: val=BOOLEAN_TO_JSVAL(JS_FALSE);
511: if(!JS_SetProperty(cx, subobj, "is_moderated", &val))
512: return(NULL);
513:
514: if(!JS_DefineProperties(cx, subobj, js_sub_properties))
515: return(NULL);
516:
517: #ifdef _DEBUG
518: js_DescribeSyncObject(cx,subobj,"Message Sub-boards (current user has access to)</h2>"
519: "(all properties are <small>READ ONLY</small> except for "
520: "<i>scan_ptr</i>, <i>scan_cfg</i>, and <i>last_read</i>)"
521: ,310);
522: #endif
523:
524: }
525:
526: #ifdef _DEBUG
527: js_CreateArrayOfStrings(cx, grpobj, "_property_desc_list", msg_grp_prop_desc, JSPROP_READONLY);
528: #endif
529: }
530:
531: #ifdef _DEBUG
532: js_DescribeSyncObject(cx,allgrps,"Associative array of all groups (use name as index)",312);
533: JS_DefineProperty(cx,allgrps,"_dont_document",JSVAL_TRUE,NULL,NULL,JSPROP_READONLY);
534: #endif
535:
536: #ifdef _DEBUG
537: js_DescribeSyncObject(cx,allsubs,"Associative array of all sub-boards (use internal code as index)",311);
538: JS_DefineProperty(cx,allsubs,"_dont_document",JSVAL_TRUE,NULL,NULL,JSPROP_READONLY);
539: #endif
540:
541: return(areaobj);
542: }
543:
544: #endif /* JAVSCRIPT */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.