|
|
1.1 root 1: /* js_msg_area.c */
2:
3: /* Synchronet JavaScript "Message Area" Object */
4:
5: /* $Id: js_msg_area.c,v 1.51 2006/12/28 02:45:27 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 2006 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 BUILD_JSDOCS
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 BUILD_JSDOCS
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: "MsgSub" /* 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 BUILD_JSDOCS
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: val=OBJECT_TO_JSVAL(grpobj);
386: grp_index=-1;
387: if(user==NULL || chk_ar(cfg,cfg->grp[l]->ar,user)) {
388:
389: if(!JS_GetArrayLength(cx, grp_list, &grp_index))
390: return(NULL);
391:
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 BUILD_JSDOCS
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: val=OBJECT_TO_JSVAL(subobj);
450: sub_index=-1;
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: if(!JS_SetElement(cx, sub_list, sub_index, &val))
457: return(NULL);
458: }
459:
460: /* Add as property (associative array element) */
461: if(!JS_DefineProperty(cx, allsubs, cfg->sub[d]->code, val
462: ,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE))
463: return(NULL);
464:
465: val=INT_TO_JSVAL(sub_index);
466: if(!JS_SetProperty(cx, subobj, "index", &val))
467: return(NULL);
468:
469: val=INT_TO_JSVAL(grp_index);
470: if(!JS_SetProperty(cx, subobj, "grp_index", &val))
471: return(NULL);
472:
473: if(!js_CreateMsgAreaProperties(cx, cfg, subobj, d))
474: return(NULL);
475:
476: if(user==NULL || chk_ar(cfg,cfg->sub[d]->read_ar,user))
477: val=BOOLEAN_TO_JSVAL(JS_TRUE);
478: else
479: val=BOOLEAN_TO_JSVAL(JS_FALSE);
480: if(!JS_SetProperty(cx, subobj, "can_read", &val))
481: return(NULL);
482:
483: if(user==NULL)
484: val=BOOLEAN_TO_JSVAL(JS_TRUE);
485: else if(cfg->sub[d]->misc&(SUB_QNET|SUB_FIDO|SUB_PNET|SUB_INET)
486: && user->rest&FLAG('N')) /* network restriction? */
487: val=BOOLEAN_TO_JSVAL(JS_FALSE);
488: else if(!chk_ar(cfg,cfg->sub[d]->post_ar,user)
489: || user->rest&FLAG('P')) /* post restriction? */
490: val=BOOLEAN_TO_JSVAL(JS_FALSE);
491: else
492: val=BOOLEAN_TO_JSVAL(JS_TRUE);
493: if(!JS_SetProperty(cx, subobj, "can_post", &val))
494: return(NULL);
495:
496: if(user!=NULL &&
497: (user->level>=SYSOP_LEVEL ||
498: (cfg->sub[d]->op_ar[0]!=0 && chk_ar(cfg,cfg->sub[d]->op_ar,user))))
499: val=BOOLEAN_TO_JSVAL(JS_TRUE);
500: else
501: val=BOOLEAN_TO_JSVAL(JS_FALSE);
502: if(!JS_SetProperty(cx, subobj, "is_operator", &val))
503: return(NULL);
504:
505: if(cfg->sub[d]->mod_ar[0]!=0 && user!=NULL
506: && chk_ar(cfg,cfg->sub[d]->mod_ar,user))
507: val=BOOLEAN_TO_JSVAL(JS_TRUE);
508: else
509: val=BOOLEAN_TO_JSVAL(JS_FALSE);
510: if(!JS_SetProperty(cx, subobj, "is_moderated", &val))
511: return(NULL);
512:
513: if(!JS_DefineProperties(cx, subobj, js_sub_properties))
514: return(NULL);
515:
516: #ifdef BUILD_JSDOCS
517: js_DescribeSyncObject(cx,subobj,"Message Sub-boards (current user has access to)</h2>"
518: "(all properties are <small>READ ONLY</small> except for "
519: "<i>scan_ptr</i>, <i>scan_cfg</i>, and <i>last_read</i>)"
520: ,310);
521: #endif
522:
523: }
524:
525: #ifdef BUILD_JSDOCS
526: js_CreateArrayOfStrings(cx, grpobj, "_property_desc_list", msg_grp_prop_desc, JSPROP_READONLY);
527: #endif
528: }
529:
530: #ifdef BUILD_JSDOCS
531: js_DescribeSyncObject(cx,allgrps,"Associative array of all groups (use name as index)",312);
532: JS_DefineProperty(cx,allgrps,"_dont_document",JSVAL_TRUE,NULL,NULL,JSPROP_READONLY);
533: #endif
534:
535: #ifdef BUILD_JSDOCS
536: js_DescribeSyncObject(cx,allsubs,"Associative array of all sub-boards (use internal code as index)",311);
537: JS_DefineProperty(cx,allsubs,"_dont_document",JSVAL_TRUE,NULL,NULL,JSPROP_READONLY);
538: #endif
539:
540: return(areaobj);
541: }
542:
543: #endif /* JAVSCRIPT */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.