implement preprocessor for tsf format
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
/* TLLY ver=77 */
|
||||
/* *=* Copyright 1996, 1997 WebTV Networks, Inc. All rights reserved. */
|
||||
#ifndef FIJI
|
||||
/*
|
||||
* This is the "base" TellyScript Fragment. It is suppressed for FIJI
|
||||
* (see comments below).
|
||||
@@ -164,11 +165,12 @@ char* gPAPPassword; /* box's PAP password, embedded in script by the
|
||||
int gEnable56K; /* if set, allow 56K connections; if not, don't */
|
||||
int gDisguiseRate; /* if set, reverse the DTE and DCE rates */
|
||||
int gFlexKnob=5; /* 56k knob for Rockwell, 5=most aggressive (default) */
|
||||
|
||||
#endif /*!FIJI*/
|
||||
/* FIJI doesn't have these built-in */
|
||||
int gBlock911=1; /* This flag is now set for all services. */
|
||||
int gWantsVideoAd; /* if set, user wants to download Video Ads */
|
||||
/* This flag is not needed anymore, left here for future use */
|
||||
#ifndef FIJI
|
||||
|
||||
/*
|
||||
* ===========================================================================
|
||||
@@ -431,6 +433,97 @@ GetPhoneSettings(int* pSettingsVersion)
|
||||
* ===========================================================================
|
||||
*/
|
||||
|
||||
#ifndef CLASSIC
|
||||
/*
|
||||
* GetHardwareInfo - figure out some things about the platform we're
|
||||
* running on.
|
||||
*
|
||||
* "*pIsEarlyK56" is set if we're using Rockwell's v1.0 K56 firmware.
|
||||
* "*pAcceptsS220" is set if the modem recognizes S220 as a valid S-register.
|
||||
*
|
||||
* Assumes that the modem is happy and in V1E0 (verbose result code, no
|
||||
* echo) mode.
|
||||
*
|
||||
* NOTE: we don't really check for and try to handle the case where the
|
||||
* modem goes out to lunch and we're hitting the getline() timeouts. Since
|
||||
* we've already talked to the modem a little before getting here, I think
|
||||
* it's safe to assume that we won't fail here and then succeed later. If
|
||||
* the information we get from this function is more critical than what we
|
||||
* have now, we should be more careful.
|
||||
*
|
||||
* Returns 0 if all went well, nonzero on error.
|
||||
*/
|
||||
GetHardwareInfo(int* pIsEarlyK56, int* pAcceptsS220, int* pIsRockwell,
|
||||
int* pAcceptsAmpP, int* pAcceptsPlusMR)
|
||||
{
|
||||
char resultBuf[64];
|
||||
|
||||
/* look for v1.0 Rockwell K56 firmware... if found, limit to <= V.34 */
|
||||
flush();
|
||||
sendstr("ATI3\r"); /* modem firmware query */
|
||||
printf("TS: SENT ATI3");
|
||||
getline(resultBuf, 63, 300); /* throw out the first one */
|
||||
if (!getline(resultBuf, 63, 300)) /* keep 2nd; note it has leading '\r' */
|
||||
return 1;
|
||||
printf("TS: fw query got '%s'", resultBuf+1);
|
||||
setfirmwareversion(resultBuf+1);
|
||||
resultBuf[21] = '\0'; /* me falta strncmp in 1.0 */
|
||||
*pIsEarlyK56 = 0;
|
||||
if (strcmp(resultBuf+1, "V1.001_WEBTV-K56_DLP") == 0)
|
||||
*pIsEarlyK56 = 1;
|
||||
|
||||
/*
|
||||
* Softmodem can't handle AT+MS, so try to detect Rockwell. Sadly,
|
||||
* there doesn't seem to be a simple way to do this.
|
||||
*/
|
||||
*pIsRockwell = 0;
|
||||
if (strcmp(resultBuf+11, "TV-K56_DLP") == 0)
|
||||
*pIsRockwell = 1;
|
||||
resultBuf[15] = '\0'; /* do we have strncmp in 2.0? */
|
||||
if (strcmp(resultBuf+8, "K56_DLP") == 0) /* V2.200-K56_DLP_RAM */
|
||||
*pIsRockwell = 1;
|
||||
printf("TS: isRockwell=%d", *pIsRockwell);
|
||||
|
||||
/* see if it's a Rockwell that supports +MR */
|
||||
*pAcceptsPlusMR = 0;
|
||||
if (*pIsRockwell) {
|
||||
flush();
|
||||
sendstr("AT+MR=0\r");
|
||||
getline(resultBuf, 63, 300); /* throw out 1st */
|
||||
if (!getline(resultBuf, 63, 300)) /* keep 2nd */
|
||||
return 1;
|
||||
printf("TS: +MR=0 test returned '%s'", resultBuf+1);
|
||||
if (strcmp(resultBuf+1, "OK") == 0)
|
||||
*pAcceptsPlusMR = 1;
|
||||
}
|
||||
|
||||
/* see if it will take an S220 command */
|
||||
flush();
|
||||
sendstr("ATS220=0\r"); /* JP CW --> extremely insensitive */
|
||||
printf("TS: SENT ATS220=0");
|
||||
getline(resultBuf, 63, 300); /* throw out 1st */
|
||||
if (!getline(resultBuf, 63, 300)) /* keep 2nd */
|
||||
return 1;
|
||||
printf("TS: S220 test returned '%s'", resultBuf+1);
|
||||
*pAcceptsS220 = 0;
|
||||
if (strcmp(resultBuf+1, "OK") == 0)
|
||||
*pAcceptsS220 = 1;
|
||||
|
||||
/* see if it will take an &Pn command -- desktop Supras won't */
|
||||
flush();
|
||||
sendstr("AT&P0\r");
|
||||
printf("TS: SENT AT&P0");
|
||||
getline(resultBuf, 63, 300); /* throw out 1st */
|
||||
if (!getline(resultBuf, 63, 300)) /* keep 2nd */
|
||||
return 1;
|
||||
printf("TS: AT&P0 test returned '%s'", resultBuf+1);
|
||||
*pAcceptsAmpP = 0;
|
||||
if (strcmp(resultBuf+1, "OK") == 0)
|
||||
*pAcceptsAmpP = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Initialize - set up the modem configuration and dialing commands, and
|
||||
@@ -454,6 +547,11 @@ Initialize(char* staticConfigBuf, char* dynamicConfigBuf)
|
||||
char dialSpeed = settings[104];
|
||||
char cwSensitivity = extendedSettings[105]; /* version >= 7 */
|
||||
char *cwValue = "14";
|
||||
#ifndef CLASSIC
|
||||
char *s220Value;
|
||||
int isEarlyK56, acceptsS220, isRockwell, acceptsAmpP, acceptsPlusMR;
|
||||
char *flexKnobStr; /* sairam testing */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Talk to the modem.
|
||||
@@ -466,7 +564,40 @@ Initialize(char* staticConfigBuf, char* dynamicConfigBuf)
|
||||
if (SendAndWaitForOK("AT&D2V1E0\r", "OK"))
|
||||
return 3; /* kTellyConfigurationError */
|
||||
|
||||
#ifndef CLASSIC
|
||||
/* figure out what we got? */
|
||||
if (GetHardwareInfo(&isEarlyK56, &acceptsS220, &isRockwell, &acceptsAmpP,
|
||||
&acceptsPlusMR))
|
||||
return 3; /* kTellyConfigurationError */
|
||||
if (isEarlyK56)
|
||||
printf("TS: found v1.0 K56 fw, disabling 56K");
|
||||
|
||||
strcpy(staticConfigBuf, "AT");
|
||||
if (isRockwell) {
|
||||
if (isEarlyK56 || !gEnable56K) {
|
||||
strcat(staticConfigBuf, "+MS=11,1"); /* disable 56K */
|
||||
}
|
||||
/*
|
||||
else {
|
||||
/+ Rockwell 56k Aggressiveness knob - sairam testing +/
|
||||
if (isRockwell) {
|
||||
sprintf(staticConfigBuf+2, "!0049=0%d", gFlexKnob);
|
||||
printf("TS: setting 56k knob to %d", gFlexKnob);
|
||||
}
|
||||
}
|
||||
*/
|
||||
} else {
|
||||
/* assume softmodem */
|
||||
if (!gEnable56K) {
|
||||
strcat(staticConfigBuf, "S51=31"); /* disable 56K */
|
||||
}
|
||||
}
|
||||
|
||||
if (acceptsPlusMR) /* suppress extended result codes we don't parse */
|
||||
strcat(staticConfigBuf, "+MR=0");
|
||||
#else
|
||||
strcpy(staticConfigBuf, "AT"); /* CLASSIC doesn't support 56K */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Modem configuration. This sets things so we connect with V.34 only,
|
||||
@@ -528,6 +659,26 @@ Initialize(char* staticConfigBuf, char* dynamicConfigBuf)
|
||||
strcat(dynamicConfigBuf, "S10=");
|
||||
strcat(dynamicConfigBuf, cwValue);
|
||||
|
||||
#ifndef CLASSIC
|
||||
/* set the JP "catch-phone" sensitivity; this is *in addition* to S10 */
|
||||
if (acceptsS220) {
|
||||
if (cwSensitivity == 1) /* most likely to hang up */
|
||||
s220Value = "32";
|
||||
else if (cwSensitivity == 2)
|
||||
s220Value = "21";
|
||||
else if (cwSensitivity == 3)
|
||||
s220Value = "11";
|
||||
else /* == 4 or bogus */ /* most likely to ignore calls */
|
||||
s220Value = "1";
|
||||
|
||||
printf("TS: setting S220=%s", s220Value);
|
||||
strcat(dynamicConfigBuf, "S220=");
|
||||
strcat(dynamicConfigBuf, s220Value);
|
||||
} else {
|
||||
printf("TS: not setting S220"); /* CLASSIC boxes; others? */
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Set the dial speed.
|
||||
*/
|
||||
@@ -541,6 +692,22 @@ Initialize(char* staticConfigBuf, char* dynamicConfigBuf)
|
||||
strcat(dynamicConfigBuf, "S11=1"); /* blazing (not in UI) */
|
||||
}
|
||||
|
||||
#ifndef CLASSIC
|
||||
/*
|
||||
* Set the pulse speed. &P0 is default for US, but we use JP pulse
|
||||
* values for now since they seem to work anyway. Some desktop Supra
|
||||
* modems don't understand "&Pn", and will fail to configure, so we
|
||||
* use the "acceptsAmpP" auto-detect value.
|
||||
*/
|
||||
if (acceptsAmpP) {
|
||||
if (dialSpeed == 0 || dialSpeed == 1) {
|
||||
strcat(dynamicConfigBuf, "&P1"); /* 10PPS 33% */
|
||||
} else if (dialSpeed == 2 || dialSpeed == 3) {
|
||||
strcat(dynamicConfigBuf, "&P3"); /* 20PPS 33% */
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* put a carriage return on the end */
|
||||
strcat(dynamicConfigBuf, "\r");
|
||||
@@ -699,6 +866,18 @@ ParseResult(int result)
|
||||
int retcode;
|
||||
char* comment = "";
|
||||
|
||||
#ifndef CLASSIC /* no CLASSIC box supports modem_parsersult() */
|
||||
retcode = modem_parseresult(&result, &gDTERate, &gDCERate, &gCompression,
|
||||
&gProtocol, &gConnected, &comment);
|
||||
if (retcode != 0x42554646) {
|
||||
printf("TS: parseresult -- %d %s (retcode=%d)", result,
|
||||
comment, retcode);
|
||||
if (gDCERate && gDCERate < 14400) {
|
||||
retcode = 14; /* kTellyVerySlowConnect */
|
||||
}
|
||||
return retcode;
|
||||
}
|
||||
#endif
|
||||
retcode = 0;
|
||||
|
||||
if (result == 0) /* OK */
|
||||
@@ -1285,11 +1464,34 @@ DialByIndex(char* staticConfig, char* dynamicConfig, char* sequence)
|
||||
return err;
|
||||
} else {
|
||||
dialerror(err);
|
||||
#ifndef CLASSIC
|
||||
/* 101223/093628
|
||||
* Make sure that MsgWatch calls are
|
||||
* limited to the primary POP only,
|
||||
* and to the first trial!
|
||||
*/
|
||||
if (idx == nextNumber) {
|
||||
if (getconnectreason() == 1) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} else if (status == 2 || idx == sequenceLen-1) {
|
||||
return err;
|
||||
} else /*status==1*/ {
|
||||
dialerror(err);
|
||||
#ifndef CLASSIC
|
||||
/* 101223/093628
|
||||
* Make sure that MsgWatch calls are
|
||||
* limited to the primary POP only
|
||||
*/
|
||||
if (idx == nextNumber) {
|
||||
if (getconnectreason() == 1) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1369,6 +1571,9 @@ main()
|
||||
return result;
|
||||
}
|
||||
}
|
||||
#endif /* !FIJI */
|
||||
|
||||
/* --- base.tsf END --- */
|
||||
|
||||
/*
|
||||
* Locale-specific stuff for USA.
|
||||
@@ -1,5 +1,6 @@
|
||||
var minisrv_service_file = true;
|
||||
var template_path = "";
|
||||
var template = "";
|
||||
var template_preprocessor = {};
|
||||
|
||||
var gourl = "wtv-head-waiter:/login?";
|
||||
|
||||
@@ -109,7 +110,8 @@ if (session_data.data_store.wtvsec_login) {
|
||||
case "bf0app":
|
||||
prereg_contype = "text/tellyscript";
|
||||
// if wtv-open-access: true then client expects OpenISP
|
||||
template = wtvshared.getServiceDep("/wtv-1800/tellyscripts/bf0app/bf0app.base.template.txt")
|
||||
template = wtvshared.getServiceDep("/wtv-1800/tellyscripts/base.template.txt")
|
||||
template_preprocessor = { 'CLASSIC': true }
|
||||
if (session_data.get("wtv-open-access")) template += wtvshared.getServiceDep("/wtv-1800/tellyscripts/bf0app/bf0app.openisp.template.txt");
|
||||
else template += wtvshared.getServiceDep("/wtv-1800/tellyscripts/bf0app/bf0app.normal.template.txt");
|
||||
//else file_path = wtvshared.getServiceDep("/wtv-1800/tellyscripts/bf0app/bf0app_WTV_18006138199.tok", true);
|
||||
@@ -119,6 +121,7 @@ if (session_data.data_store.wtvsec_login) {
|
||||
|
||||
case "JP-Fiji":
|
||||
prereg_contype = "text/tellyscript";
|
||||
template_preprocessor = { 'FIJI': true }
|
||||
// if wtv-open-access: true then client expects OpenISP
|
||||
if (session_data.get("wtv-open-access")) var file_path = wtvshared.getServiceDep("/wtv-1800/tellyscripts/FIJI/dc_production_normal.tok", true);
|
||||
else var file_path = wtvshared.getServiceDep("/wtv-1800/tellyscripts/FIJI/dc_production_normal.tok", true);
|
||||
@@ -201,11 +204,11 @@ if (session_data.data_store.wtvsec_login) {
|
||||
});
|
||||
} else if (template) {
|
||||
request_is_async = true;
|
||||
telly = new WTVTellyScript(template, 2); // 2 = Untokenized
|
||||
telly = new WTVTellyScript(template, 2, template_preprocessor, session_data.get("wtv-open-access") ? 3 : 1); // dataState 2 = Untokenized
|
||||
telly.setTemplateVars(minisrv_config.config.service_name, minisrv_config.services[service_name].dialin_number, minisrv_config.services[service_name].dns1ip, minisrv_config.services[service_name].dns2ip);
|
||||
telly.minify();
|
||||
telly.tokenize();
|
||||
telly.pack((session_data.get("wtv-open-access")) ? 3 : 1);
|
||||
telly.pack();
|
||||
sendToClient(socket, headers, telly.packed_data);
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -1053,17 +1053,93 @@ class WTVTellyScript {
|
||||
* @param {Uint8Array|string} data - The TellyScript data (either packed, tokenized, or raw).
|
||||
* @param {number} dataState - One of TellyScriptState (default: PACKED).
|
||||
* @param {number} tellyscriptType - One of TellyScriptType (default: ORIGINAL).
|
||||
* @param {object} preprocessor_definitions - A dictionary of preprocessor definitions.
|
||||
* @param {number} version_minor - The minor version number (default: 1).
|
||||
*/
|
||||
constructor(data, dataState = TellyScriptState.PACKED, tellyscriptType = TellyScriptType.ORIGINAL) {
|
||||
constructor(data, dataState = TellyScriptState.PACKED, preprocessor_definitions = {}, version_minor = 1, tellyscriptType = TellyScriptType.ORIGINAL) {
|
||||
this.tellyscript_type = tellyscriptType;
|
||||
this.packed_data = null;
|
||||
this.packed_header = null;
|
||||
this.tokenized_data = null;
|
||||
this.raw_data = null;
|
||||
this.preprocessor_definitions = preprocessor_definitions;
|
||||
this.version_minor = version_minor;
|
||||
|
||||
this.process(data, dataState);
|
||||
}
|
||||
|
||||
preprocess() {
|
||||
var definitions = this.preprocessor_definitions || {};
|
||||
// Split input into lines (handling CRLF and LF)
|
||||
const lines = this.raw_data.split(/\r?\n/);
|
||||
const output = [];
|
||||
// A stack to track whether the current block is active.
|
||||
// Start with "true" so that top-level lines are output.
|
||||
const stateStack = [true];
|
||||
|
||||
// Process each line one by one.
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const line = lines[i];
|
||||
|
||||
// Only process directives if they are left-aligned.
|
||||
if (line.startsWith("#")) {
|
||||
if (/^#ifdef\b/.test(line)) {
|
||||
// Get the label immediately after "#ifdef"
|
||||
const token = line.slice(6).split(/\s/)[0];
|
||||
const condition = !!definitions[token];
|
||||
// The block is active only if the parent block is active and condition is true.
|
||||
const active = stateStack[stateStack.length - 1] && condition;
|
||||
stateStack.push(active);
|
||||
continue; // Do not output this directive line.
|
||||
} else if (/^#ifndef\b/.test(line)) {
|
||||
const token = line.slice(7).split(/\s/)[0];
|
||||
const condition = !definitions[token];
|
||||
const active = stateStack[stateStack.length - 1] && condition;
|
||||
stateStack.push(active);
|
||||
continue;
|
||||
} else if (/^#if\b/.test(line)) {
|
||||
// Expect exactly "#if 1" or "#if 0" (no extra spaces allowed).
|
||||
const token = line.slice(3).split(/\s/)[0];
|
||||
if (token !== "1" && token !== "0") {
|
||||
throw new Error(
|
||||
`Invalid #if condition at line ${i + 1}: "${line}"`
|
||||
);
|
||||
}
|
||||
const condition = token === "1";
|
||||
const active = stateStack[stateStack.length - 1] && condition;
|
||||
stateStack.push(active);
|
||||
continue;
|
||||
} else if (/^#else\b/.test(line)) {
|
||||
if (stateStack.length <= 1) {
|
||||
throw new Error(`#else without matching #if at line ${i + 1}`);
|
||||
}
|
||||
// Flip the state of the current block while considering the parent's state.
|
||||
const previous = stateStack.pop();
|
||||
const newState = stateStack[stateStack.length - 1] && !previous;
|
||||
stateStack.push(newState);
|
||||
continue;
|
||||
} else if (/^#endif\b/.test(line)) {
|
||||
if (stateStack.length <= 1) {
|
||||
throw new Error(`#endif without matching #if at line ${i + 1}`);
|
||||
}
|
||||
stateStack.pop();
|
||||
continue;
|
||||
} else if (/^#include\b/.test(line)) {
|
||||
// Silently remove #include directives.
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// For non-directive lines (or lines with unrecognized directives),
|
||||
// output them only if the current block is active.
|
||||
if (stateStack[stateStack.length - 1]) {
|
||||
output.push(line);
|
||||
}
|
||||
}
|
||||
|
||||
this.raw_data = output.join("\n");
|
||||
}
|
||||
|
||||
|
||||
minify() {
|
||||
let minifier = new WTVTellyScriptMinifier();
|
||||
this.raw_data = minifier.minify(this);
|
||||
@@ -1218,12 +1294,13 @@ class WTVTellyScript {
|
||||
this.pack();
|
||||
this.detokenize();
|
||||
} else if (dataState === TellyScriptState.RAW) {
|
||||
// For RAW byte data, convert to string (assuming UTF-8)
|
||||
// For RAW byte data, convert to string (assuming UTF-8)
|
||||
this.process(new TextDecoder().decode(data), dataState);
|
||||
}
|
||||
} else if (typeof data === "string") {
|
||||
if (dataState === TellyScriptState.RAW) {
|
||||
this.raw_data = data;
|
||||
this.preprocess()
|
||||
this.tokenize();
|
||||
this.pack();
|
||||
} else if (dataState === TellyScriptState.PACKED || dataState === TellyScriptState.TOKENIZED) {
|
||||
@@ -1275,7 +1352,7 @@ class WTVTellyScript {
|
||||
}
|
||||
|
||||
// --- Packing ---
|
||||
pack(version_minor = 1) {
|
||||
pack() {
|
||||
// Compress tokenized data using LZSS.
|
||||
const comp = new LZSS();
|
||||
const compressed_data = comp.compress(this.tokenized_data);
|
||||
@@ -1295,7 +1372,7 @@ class WTVTellyScript {
|
||||
this.packed_header = {
|
||||
magic: (this.tellyscript_type === TellyScriptType.DIALSCRIPT) ? "VKAT" : "ANDY",
|
||||
version_major: (this.packed_header && this.packed_header.version_major) ? this.packed_header.version_major : 1,
|
||||
version_minor: (this.packed_header && this.packed_header.version_minor) ? this.packed_header.version_minor : version_minor,
|
||||
version_minor: (this.packed_header && this.packed_header.version_minor) ? this.packed_header.version_minor : this.version_minor,
|
||||
script_id: script_id,
|
||||
script_mod: Math.floor(Date.now() / 1000),
|
||||
compressed_data_length: compressed_data.length,
|
||||
|
||||
@@ -22,7 +22,6 @@ wtv-system-version: 7181
|
||||
wtv-capability-flags: 10935ffc8f
|
||||
wtv-client-bootrom-version: 2046
|
||||
wtv-client-rom-type: bf0app
|
||||
wtv-open-access: true
|
||||
wtv-system-chipversion: 51511296
|
||||
User-Agent: Mozilla/4.0 WebTV/2.2.6.1 (compatible; MSIE 4.0)
|
||||
wtv-encryption: true
|
||||
@@ -30,6 +29,7 @@ wtv-script-id: 0
|
||||
wtv-script-mod: 0
|
||||
|
||||
`
|
||||
//wtv-open-access: true
|
||||
|
||||
|
||||
//wtv-client-rom-type: US-LC2-disk-0MB-8MB
|
||||
@@ -62,7 +62,7 @@ client.on('data', (chunk) => {
|
||||
|
||||
telly = new WTVTellyScript(accumulatedBuffer)
|
||||
console.log(telly.packed_header)
|
||||
console.log(telly.raw_data)
|
||||
// console.log(telly.raw_data)
|
||||
// Optionally, close the connection after receiving data
|
||||
client.end();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user