Work on v2 frame files

This commit is contained in:
2024-12-03 21:36:03 +11:00
parent 991a31e957
commit f7a581fa30
20 changed files with 200 additions and 221 deletions

View File

@@ -62,19 +62,19 @@ const MODE_RFERROR = 6;
// @todo Change these to bits
/* Information Frame, requires no response after viewed */
const FRAME_TYPE_INFO = 'i';
const FRAME_TYPE_INFO = 0; //'i';
/* Terminate Frame, contents displayed and then carrier dropped */
const FRAME_TYPE_TERMINATE = 't';
const FRAME_TYPE_TERMINATE = 15; //'t';
/**
* Frame the calls an External Method
* Contents indicate the method to be called with arguments
*/
const FRAME_TYPE_EXTERNAL = 'x';
const FRAME_TYPE_EXTERNAL = 13; //'x';
/**
* Frame calls a door
* Contents indicate the name of the door
*/
const FRAME_TYPE_DOOR = 'X';
const FRAME_TYPE_DOOR = 11; //'X';
/**
* Frame renders a BBS from sbbslist
* Contents can be:
@@ -86,13 +86,13 @@ const FRAME_TYPE_BBS = 'b';
* Response frame, input fields are embedded in the frame and after input the
* response will be submitted to the Service Provider, or to a method
*/
const FRAME_TYPE_RESPONSE = 'r';
const FRAME_TYPE_RESPONSE = 1; //'r';
/* Login frame, enables the user to authenticate to the system, or to a CUG */
const FRAME_TYPE_LOGIN = 'l';
const FRAME_TYPE_LOGIN = 12; //'l';
/* Mail template frames - mail templates will have the user's stats for the area passed to render() */
const FRAME_TYPE_MAIL_TEMPLATE = 'm';
/* Frame is a message */
const FRAME_TYPE_MESSAGE = 'M';
const FRAME_TYPE_MESSAGE = 2; // 'M';
/* Disable *# going backwards for the following frames */
const FRAMES_NO_HISTORY = ['980a','98b','981a','982a','983a','998a'];

View File

@@ -123,14 +123,15 @@ function Page(debug) {
this.__properties__ = {
name: new PageObject,
type: undefined, // Frame type
//type: undefined, // Frame type (deprecated, see attrs)
attrs: 0, // (Type 0, CUG 0 (public), Hidden=false)
input_fields: [], // Array of our input fields
dynamic_fields: [], // Array of our dynamic fields
isAccessible: undefined, // Is this page visible to all users
//isAccessible: undefined, // Is this page visible to all users (deprecated, see attrs)
// If FALSE, only the SP can view/edit the frame
isPublic: undefined, // Is this page visible to public (not CUG) users
//isPublic: undefined, // Is this page visible to public (not CUG) users (deprecated, see attrs)
// If FALSE user must be a member of the CUG to view the frame
// All users, including unauthenticated, are members of 'system' (owner = 0)
// Frame's owned by the system where:
@@ -197,57 +198,89 @@ function Page(debug) {
}
}
// @todo change this to Object.defineProperty() - see page.js
/**
* Determine if this frame is accessible to the current user
*/
Page.prototype.__defineGetter__('accessible',function() {
log(LOG_DEBUG,'- Checking if user ['+user.number+'] can access frame: '+this.name.toString());
log(LOG_DEBUG,'|* Frame Owner: '+JSON.stringify(this.pageowner)+', System Frame: '+(this.pageowner === SYSTEM_OWNER));
log(LOG_DEBUG,'|* Accessible: '+JSON.stringify(this.__properties__.isAccessible));
log(LOG_DEBUG,'|* Public: '+JSON.stringify(this.__properties__.isPublic));
log(LOG_DEBUG,'|* Member: '+JSON.stringify(this.isMember));
Object.defineProperty(this,'accessible',{
get: function() {
log(LOG_DEBUG,'- Checking if user ['+user.number+'] can access frame: '+this.name.toString());
log(LOG_DEBUG,'|* Frame Owner: '+this.owner+', System Frame: '+this.isSystemPage);
log(LOG_DEBUG,'|* Accessible: '+this.isAccessible);
log(LOG_DEBUG,'|* Public: '+this.isPublic);
log(LOG_DEBUG,'|* Member: '+this.isMember);
// user.number 0 is unidentified user.
if (user.number) {
return (
(this.__properties__.isAccessible && this.pageowner === SYSTEM_OWNER && ! this.__properties__.isPublic) ||
(this.__properties__.isAccessible && this.__properties__.isPublic) ||
(this.__properties__.isAccessible && ! this.__properties__.isPublic && this.isMember) ||
(pageEditor(this.name.frame))
);
// user.number 0 is unidentified user.
if (user.number) {
return (
(this.isAccessible && this.isSystemPage && ! this.isPublic) ||
(this.isAccessible && this.isPublic) ||
(this.isAccessible && ! this.isPublic && this.isMember) ||
(pageEditor(this.name.frame))
);
} else {
return this.__properties__.isAccessible && (this.pageowner === SYSTEM_OWNER) && this.__properties__.isPublic;
} else {
return this.isAccessible && this.isSystemPage && this.isPublic;
}
}
});
Page.prototype.__defineGetter__('cost',function() {
return Number(this.__properties__.cost);
// The page attributes, which determine accessible, public, cug and frame type
Object.defineProperty(this,'attrs',{
get: function() {
return this.__properties__.attrs;
},
/* Frame attributes are bit items, bits:
* 1-4 TYPE
* 5-7 CUG
* 8 accessible
*/
set: function(int) {
if (int === undefined)
int = 0;
this.__properties__.attrs = int;
}
});
Page.prototype.__defineSetter__('cost',function(int) {
if (typeof int !== 'number')
throw new Error('Cost must be a number');
this.__properties__.cost = int;
Object.defineProperty(this,'cost',{
get: function() {
return Number(this.__properties__.cost);
},
if ((''+int).length > FRAME_COST_LENGTH-1-FRAME_ATTR_LENGTH)
throw new Error('Cost too large');
set: function(int) {
if (int === undefined)
int = 0;
// Populate the cost window
switch (SESSION_EXT) {
case 'tex':
this.__window__.cost.__properties__.content = rawtoattrs(ESC+'[1;32m'+padright(int,FRAME_COST_LENGTH-1-FRAME_ATTR_LENGTH,' ')+FRAME_COSTUNIT).content;
if (typeof int !== 'number')
throw new Error('Cost must be a number');
break;
this.__properties__.cost = int;
case 'vtx':
this.__window__.cost.__properties__.content = rawtoattrs(VIEWDATA_BIN_GREEN+padright(int,FRAME_COST_LENGTH-1-FRAME_ATTR_LENGTH,' ')+FRAME_COSTUNIT).content;
if ((''+int).length > FRAME_COST_LENGTH-1-FRAME_ATTR_LENGTH)
throw new Error('Cost too large');
break;
// Populate the cost window
switch (SESSION_EXT) {
case 'tex':
this.__window__.cost.__properties__.content = rawtoattrs(ESC+'[1;32m'+padright(int,FRAME_COST_LENGTH-1-FRAME_ATTR_LENGTH,' ')+FRAME_COSTUNIT).content;
default:
throw new Error(SESSION_EXT+' type not implemented');
break;
case 'vtx':
this.__window__.cost.__properties__.content = rawtoattrs(VIEWDATA_BIN_GREEN+padright(int,FRAME_COST_LENGTH-1-FRAME_ATTR_LENGTH,' ')+FRAME_COSTUNIT).content;
break;
default:
throw new Error(SESSION_EXT+' type not implemented');
}
}
});
Object.defineProperty(this,'cug',{
get: function() {
return ((this.__properties__.attrs >> 4) & 0x7);
}
});
@@ -273,26 +306,34 @@ function Page(debug) {
this.__properties__.input_fields = array;
});
Page.prototype.__defineSetter__('isAccessible',function(bool) {
if (typeof bool !== 'boolean')
throw new Error('isAccessible must be a boolean');
this.__properties__.isAccessible = bool;
Object.defineProperty(this,'isAccessible',{
get: function() {
return (this.__properties__.attrs >> 7 !== 1);
}
});
/**
* Check if the user is already a member of the CUG
*/
Page.prototype.__defineGetter__('isMember',function() {
// @todo Implement CUGs, this would be "=== SERVICE_PROVIDER" and user is a member of SERVICE_PROVIDER
return user.number && (this.pageowner === SYSTEM_OWNER);
Object.defineProperty(this,'isMember',{
get: function() {
// @todo Implement CUGs, this would be "=== SERVICE_PROVIDER" and user is a member of SERVICE_PROVIDER
return (user.number > 0) && this.isSystemPage;
}
});
Page.prototype.__defineSetter__('isPublic',function(bool) {
if (typeof bool !== 'boolean')
throw new Error('isPublic must be a boolean');
// Is the page public or CUG
Object.defineProperty(this,'isPublic',{
get: function() {
return (this.cug === 0);
}
});
this.__properties__.isPublic = bool;
// Is this a system page
Object.defineProperty(this,'isSystemPage',{
get: function() {
return (this.owner === SYSTEM_OWNER);
}
});
// Key Array
@@ -337,12 +378,20 @@ function Page(debug) {
}
});
// Display who owns the page
Object.defineProperty(this,'owner',{
get: function() {
return pageOwner(this.__properties__.name.frame).prefix;
},
});
Page.prototype.__defineGetter__('pagenext',function() {
return this.__properties__.name.next;
});
/**
* Determine who the owner of a page is
* @deprecated use owner
*/
Page.prototype.__defineGetter__('pageowner',function() {
return pageOwner(this.__properties__.name.frame).prefix;
@@ -386,6 +435,12 @@ function Page(debug) {
this.__window__.header.visible = bool;
});
Object.defineProperty(this,'type',{
get: function() {
return this.__properties__.attrs & 0xf;
},
});
Page.prototype.__defineGetter__('type',function() {
return this.__properties__.type;
});
@@ -839,8 +894,10 @@ function Page(debug) {
if (!(page instanceof PageObject))
throw new Error('page must be a PageObject');
this.name = page;
// Load a page from disk first if it exists
if (FRAMES_MSG_FILES && this.import(FRAMES_HOME+SESSION_EXT+'/'+page.toString(),SESSION_EXT))
if (FRAMES_MSG_FILES && this.import(FRAMES_HOME+page.toString(),SESSION_EXT))
return true;
// Fall back to loading from msgbase
@@ -1192,9 +1249,34 @@ function Page(debug) {
break;
case 2:
// Load the page content
var content_file = FRAMES_HOME+SESSION_EXT+'/'+this.name.toString()+'.'+CONTENT_EXT;
log(LOG_DEBUG,'|-- Importing frame content: ['+content_file+']');
var f = new File(content_file);
if (! f.exists || ! f.open('rb',true)) {
log(LOG_ERROR,'|? File doesnt exist: ['+content_file+']');
this.get(new PageObject(FRAME_SYSTEM_ERROR));
break;
}
this.__properties__.raw = f.read();
f.close();
var page = rawtoattrs(this.__properties__.raw,this.width,this.__window__.body.y,this.__window__.body.x);
this.__window__.body.__properties__.content = page.content;
this.dynamic_fields = page.dynamic_fields;
// Our fields are sorted in x descending order
if (page.input_fields.length)
this.input_fields = page.input_fields.sort(function(a,b) { return a.x < b.x ? 1 : -1; });
// Work out frame type
writeln(JSON.stringify(contents));
exit(2);
this.attrs = contents.attrs;
this.cost = contents.cost;
this.key = contents.key;
break;
default:
@@ -1354,11 +1436,19 @@ function PageObject(frame,index) {
this.__properties__.frame = frame.frame.toString();
this.index = frame.index;
} else {
this.__properties__.frame = frame;
} else if ((frame !== undefined) && (index === undefined)) {
if (/^\d+[a-z]$/.test(frame)) {
var split = frame.split(/(\d+)/);
this.__properties__.frame = split[1];
this.index = split[2];
if (index)
this.index = index;
} else {
this.__properties__.frame = frame;
}
} else if ((frame !== undefined) && (index !== undefined)) {
this.__properties__.frame = frame;
this.index = index;
}
}

View File

@@ -1,5 +1,5 @@
const SESSION_ANSITEX = (1<<1);
var SESSION_EXT = 'tex';
var CONTENT_EXT = 'ans';
var FRAME_WIDTH = 80;
var FRAME_HEIGHT = 22;

View File

@@ -1,5 +1,5 @@
const SESSION_VIEWDATA = (1<<2);
var SESSION_EXT = 'vtx';
var CONTENT_EXT = 'bin';
var FRAME_WIDTH = 40;
var FRAME_HEIGHT = 22;

View File

@@ -944,13 +944,15 @@ function Char(ch,attr) {
ansi.push(r);
}
if (false && debug)
if (debug)
writeln(' - ansi:'+ansi);
return ansi.length ? (debug ? '': '\x1b')+'['+ansi.join(';')+'m' : undefined;
case 'vtx':
log(LOG_DEBUG,'+ last:'+last+', attr ('+this.attr+')');
if (debug)
log(LOG_DEBUG,'+ last:'+last+', attr ('+this.attr+')');
switch (this.attr) {
// \x08
case BLINK:
@@ -1039,7 +1041,9 @@ function Char(ch,attr) {
}
}
log(LOG_DEBUG,'= result:'+r.charCodeAt(0)+', ('+r+')');
if (debug)
log(LOG_DEBUG,'= result:'+r.charCodeAt(0)+', ('+r+')');
return ESC+r;
default: