re-write security system to be more like WNI
- can get telly and reach stage-two - narrow whitelist of allowed URLS in WTVClientSessionData constructor - enough to show wtv-1800:/unauthorized with trust priv - Times out lockeddown users really fast ;) - untested disk error page
This commit is contained in:
@@ -162,8 +162,8 @@ if (ssid_sessions[socket.ssid].data_store.wtvsec_login) {
|
|||||||
|
|
||||||
if (bf0app_update) headers += getServiceString('wtv-star', { "no_star_word": true }) + "\n";
|
if (bf0app_update) headers += getServiceString('wtv-star', { "no_star_word": true }) + "\n";
|
||||||
else headers += getServiceString('wtv-star') + "\n";
|
else headers += getServiceString('wtv-star') + "\n";
|
||||||
if (request_headers.query.reconnect && !ssid_sessions[socket.ssid].getSessionData("registered")) headers += getServiceString('wtv-register') + "\n";
|
if (request_headers.query.reconnect && !ssid_sessions[socket.ssid].getSessionData("registered") && !ssid_sessions[socket.ssid].lockdown) headers += getServiceString('wtv-register') + "\n";
|
||||||
headers += getServiceString('wtv-flashrom') + "\n";
|
if (!ssid_sessions[socket.ssid].lockdown) headers += getServiceString('wtv-flashrom') + "\n";
|
||||||
if (bf0app_update) headers += "wtv-boot-url: " + gourl + "\n";
|
if (bf0app_update) headers += "wtv-boot-url: " + gourl + "\n";
|
||||||
else {
|
else {
|
||||||
headers += "wtv-boot-url: wtv-head-waiter:/relogin?relogin=true";
|
headers += "wtv-boot-url: wtv-head-waiter:/relogin?relogin=true";
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
<html>
|
headers = `200 OK
|
||||||
|
Content-type: text/html`;
|
||||||
|
|
||||||
|
data = `<html>
|
||||||
<head>
|
<head>
|
||||||
<title>
|
<title>
|
||||||
Access Denied
|
Access Denied
|
||||||
@@ -48,7 +51,7 @@ Access Denied
|
|||||||
<td width=104 valign=middle align=center>
|
<td width=104 valign=middle align=center>
|
||||||
<td width=20 valign=middle align=center>
|
<td width=20 valign=middle align=center>
|
||||||
<td colspan=9 width=100 height=258 valign=top align=left>
|
<td colspan=9 width=100 height=258 valign=top align=left>
|
||||||
<font size=-1>You are not authorized to use this service. <p>Reason: ${REASON} </font>
|
<font size=-1>You are not authorized to use this service. <p>Reason: ${ssid_sessions[socket.ssid].lockdownReason}</font>
|
||||||
<tr>
|
<tr>
|
||||||
<td width=104 valign=middle align=center>
|
<td width=104 valign=middle align=center>
|
||||||
<td width=20 valign=middle align=center>
|
<td width=20 valign=middle align=center>
|
||||||
@@ -89,4 +92,4 @@ type=submit Value=Continue name="Continue" borderimage="file://ROM/Borders/Butto
|
|||||||
<td width=20 valign=middle align=center>
|
<td width=20 valign=middle align=center>
|
||||||
</table>
|
</table>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>`;
|
||||||
@@ -80,9 +80,9 @@ Updating now
|
|||||||
<td width=20 valign=middle align=center>
|
<td width=20 valign=middle align=center>
|
||||||
<td colspan=9 width=100 height=258 valign=top align=left>
|
<td colspan=9 width=100 height=258 valign=top align=left>
|
||||||
<font size=+1>
|
<font size=+1>
|
||||||
Your WebTV Unit is being<br>updated automatically.
|
Your ${ssid_sessions[socket.ssid].getBoxName()} is being<br>updated automatically.
|
||||||
<p> <font size=+1>
|
<p> <font size=+1>
|
||||||
This will take a while, and<br>then you can use your WebTV again.
|
This will take a while, and<br>then you can use your ${ssid_sessions[socket.ssid].getBoxName()} again.
|
||||||
`;
|
`;
|
||||||
if (flashrom_info.is_bootrom && flashrom_info.part_number == (flashrom_info.part_count - 1)) {
|
if (flashrom_info.is_bootrom && flashrom_info.part_number == (flashrom_info.part_count - 1)) {
|
||||||
data += `<p>
|
data += `<p>
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ Updating complete
|
|||||||
<font size=+1>
|
<font size=+1>
|
||||||
The update is complete.<br>
|
The update is complete.<br>
|
||||||
<p><font size=+1>Choose <b>Connect Now</b> if you<br>want to connect to ${minisrv_config.config.service_name}.
|
<p><font size=+1>Choose <b>Connect Now</b> if you<br>want to connect to ${minisrv_config.config.service_name}.
|
||||||
<p><font size=+1>Press the <b>power</b> button to switch<br>off your unit.
|
<p><font size=+1>Press the <b>power</b> button to switch<br>off your ${ssid_sessions[socket.ssid].getBoxName()}.
|
||||||
</font>
|
</font>
|
||||||
<tr>
|
<tr>
|
||||||
<td width=104 valign=middle align=center>
|
<td width=104 valign=middle align=center>
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ data = `<html>
|
|||||||
We ran into a technical problem while updating
|
We ran into a technical problem while updating
|
||||||
your unit. (Error: ${error})
|
your unit. (Error: ${error})
|
||||||
Choose <b>Try Again</b> to try again now.
|
Choose <b>Try Again</b> to try again now.
|
||||||
<p><font size=+1>Press the <b>power</b> button to switch off your unit.
|
<p><font size=+1>Press the <b>power</b> button to switch off your ${ssid_sessions[socket.ssid].getBoxName()}.
|
||||||
<tr>
|
<tr>
|
||||||
<td width=104 valign=middle align=center>
|
<td width=104 valign=middle align=center>
|
||||||
<td width=20 valign=middle align=center>
|
<td width=20 valign=middle align=center>
|
||||||
|
|||||||
63
zefie_wtvp_minisrv/ServiceVault/wtv-head-waiter/bad-disk.js
Normal file
63
zefie_wtvp_minisrv/ServiceVault/wtv-head-waiter/bad-disk.js
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
var minisrv_service_file = true;
|
||||||
|
|
||||||
|
ssid_sessions[socket.ssid].disableLockdown();
|
||||||
|
|
||||||
|
data += `<html>
|
||||||
|
<head>
|
||||||
|
<display switchtowebmode nooptions nostatus skipback clearback> <title>Please Call</title>
|
||||||
|
</head>
|
||||||
|
<body bgcolor="#191919" text="#42CC55" link="36d5ff" fontsize="large" hspace=0 vspace=0>
|
||||||
|
<table cellspacing=0 cellpadding=0>
|
||||||
|
<tr><td width=104 height=74 valign=middle align=center bgcolor="3B3A4D">
|
||||||
|
<img src="wtv-flashrom:/ROMCache/WebTVLogoJewel.gif" width=86 height=64><td width=20 valign=top align=left bgcolor="3B3A4D">
|
||||||
|
<img src="ROMCache/Spacer.gif"
|
||||||
|
width=1 height=1>
|
||||||
|
<td colspan=10 width=436 valign=middle align=left bgcolor="3B3A4D">
|
||||||
|
<font color="D6DFD0" size="+2">
|
||||||
|
<blackface>
|
||||||
|
<shadow>
|
||||||
|
<img src="ROMCache/Spacer.gif"
|
||||||
|
width=1 height=4>
|
||||||
|
<br>
|
||||||
|
Please Call
|
||||||
|
</shadow>
|
||||||
|
</blackface>
|
||||||
|
</font>
|
||||||
|
<tr>
|
||||||
|
<td colspan=12 width=560 height=10 valign=top align=left>
|
||||||
|
<img src="file://ROM/Cache/Shadow.gif" width=560 height=6>
|
||||||
|
<tr>
|
||||||
|
<td width=104 height=10 valign=top align=left>
|
||||||
|
<td width=20 valign=top align=left>
|
||||||
|
<td width=67 valign=top align=left>
|
||||||
|
<td width=20 valign=top align=left>
|
||||||
|
<td width=67 valign=top align=left>
|
||||||
|
<td width=20 valign=top align=left>
|
||||||
|
<td width=67 valign=top align=left>
|
||||||
|
<td width=20 valign=top align=left>
|
||||||
|
<td width=67 valign=top align=left>
|
||||||
|
<td width=20 valign=top align=left>
|
||||||
|
<td width=68 valign=top align=left>
|
||||||
|
<td width=20 valign=top align=left>
|
||||||
|
<tr>
|
||||||
|
<td width=104 valign=middle align=center>
|
||||||
|
<td width=20 valign=middle align=center>
|
||||||
|
<td colspan=9 width=100 height=258 valign=top align=left>
|
||||||
|
<font size=+1>
|
||||||
|
Your Internet terminal needs to be repaired
|
||||||
|
or replaced before you can connect to WebTV.
|
||||||
|
<!-- Disabled until we can reliably grab the user's box manufacturer
|
||||||
|
<p>Call Philips customer service at<br>1-888-813-7069 -->
|
||||||
|
<tr><td colspan=2>
|
||||||
|
<td colspan=99 abswidth=436 absheight=2 bgcolor=2B2B2B> <img src="wtv-flashrom:/ROMCache/Spacer.gif" width=1 height=1> <tr><td absheight=1>
|
||||||
|
<tr><td colspan=2>
|
||||||
|
<td colspan=99 abswidth=436 absheight=2 bgcolor=0D0D0D> <img src="wtv-flashrom:/ROMCache/Spacer.gif" width=1 height=1> <tr><td height=7>
|
||||||
|
<tr>
|
||||||
|
<td width=104 valign=middle align=center> <td width=20 valign=middle align=center> <td colspan=9 width=416 valign=top align=left> <table cellspacing=0 cellpadding=0>
|
||||||
|
<tr>
|
||||||
|
<td width=306 valign=top align=right><td width=20> <td width=112 valign=top align=right>
|
||||||
|
<form action="client:poweroff"> <FONT COLOR="#E7CE4A" SIZE=-1><input type="Submit" value="Power Off" BORDERIMAGE="file://ROM/Borders/ButtonBorder2.bif" usestyle selected></font>
|
||||||
|
<input type="Hidden" name="version" value=""> </form>
|
||||||
|
</table>
|
||||||
|
</BODY>
|
||||||
|
</html>`;
|
||||||
@@ -53,7 +53,10 @@ Content-type: text/html`;
|
|||||||
data = '';
|
data = '';
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (request_headers.query.guest_login && minisrv_config.config.allow_guests) {
|
if (ssid_sessions[socket.ssid].lockdown) {
|
||||||
|
home_url = minisrv_config.config.unauthorized_url;
|
||||||
|
}
|
||||||
|
else if (request_headers.query.guest_login && minisrv_config.config.allow_guests) {
|
||||||
var namerand = Math.floor(Math.random() * 100000);
|
var namerand = Math.floor(Math.random() * 100000);
|
||||||
var nickname = (minisrv_config.config.service_name + '_' + namerand)
|
var nickname = (minisrv_config.config.service_name + '_' + namerand)
|
||||||
var human_name = nickname;
|
var human_name = nickname;
|
||||||
@@ -89,42 +92,66 @@ wtv-expire-all: client:closeallpanels
|
|||||||
wtv-transition-override: off
|
wtv-transition-override: off
|
||||||
wtv-force-lightweight-targets: webtv.net:/
|
wtv-force-lightweight-targets: webtv.net:/
|
||||||
wtv-smartcard-inserted-message: Contacting service
|
wtv-smartcard-inserted-message: Contacting service
|
||||||
wtv-bypass-proxy: false
|
wtv-bypass-proxy: false`;
|
||||||
|
if (!ssid_sessions[socket.ssid].lockdown) {
|
||||||
|
headers += `
|
||||||
wtv-offline-user-list: ${offline_user_list}
|
wtv-offline-user-list: ${offline_user_list}
|
||||||
wtv-messenger-authorized: ${messenger_authorized}
|
wtv-messenger-authorized: ${messenger_authorized}
|
||||||
wtv-messenger-enable: ${messenger_enabled}
|
wtv-messenger-enable: ${messenger_enabled}`;
|
||||||
|
}
|
||||||
|
headers += `
|
||||||
wtv-noback-all: wtv-
|
wtv-noback-all: wtv-
|
||||||
wtv-service: reset
|
wtv-service: reset
|
||||||
`+ getServiceString('all', { "exceptions": ["wtv-register"] }) + `
|
`;
|
||||||
|
if (!ssid_sessions[socket.ssid].lockdown) {
|
||||||
|
headers += getServiceString('all', { "exceptions": ["wtv-register"] });
|
||||||
|
} else {
|
||||||
|
headers += getServiceString('wtv-1800') + "\n";
|
||||||
|
headers += getServiceString('wtv-head-waiter') + "\n";
|
||||||
|
headers += getServiceString('wtv-star') + "\n";
|
||||||
|
}
|
||||||
|
headers += `
|
||||||
|
wtv-ticket: ${wtvsec_login.ticket_b64}`;
|
||||||
|
if (!ssid_sessions[socket.ssid].lockdown) {
|
||||||
|
headers += `
|
||||||
user-id: ${userid}
|
user-id: ${userid}
|
||||||
wtv-human-name: ${human_name}
|
wtv-human-name: ${human_name}
|
||||||
${ssid_sessions[socket.ssid].setIRCNick(nickname)}
|
${ssid_sessions[socket.ssid].setIRCNick(nickname)}
|
||||||
wtv-domain: wtv.zefie.com
|
wtv-domain: ${minisrv_config.config.domain_name}
|
||||||
wtv-input-timeout: 14400
|
|
||||||
wtv-ticket: ${wtvsec_login.ticket_b64}
|
|
||||||
wtv-messagewatch-checktimeoffset: off
|
wtv-messagewatch-checktimeoffset: off
|
||||||
wtv-input-timeout: 14400
|
wtv-input-timeout: 14400
|
||||||
wtv-connection-timeout: 90
|
wtv-connection-timeout: 1440
|
||||||
wtv-fader-timeout: 900
|
wtv-fader-timeout: 1440
|
||||||
wtv-smartcard-inserted-message: Contacting service
|
wtv-inactive-timeout: 1440`;
|
||||||
wtv-inactive-timeout: 0
|
} else {
|
||||||
wtv-connection-timeout: 90
|
headers += `
|
||||||
wtv-show-time-enabled: true
|
user-id: 0
|
||||||
wtv-fader-timeout: 900
|
wtv-human-name: Unauthorized User
|
||||||
wtv-tourist-enabled: true`
|
wtv-domain: ${minisrv_config.config.domain_name}
|
||||||
|
wtv-input-timeout: 30
|
||||||
|
wtv-connection-timeout: 60
|
||||||
|
wtv-fader-timeout: 60
|
||||||
|
wtv-inactive-timeout: 60`;
|
||||||
|
}
|
||||||
|
|
||||||
headers += "\nwtv-relogin-url: wtv-head-waiter:/relogin?relogin=true";
|
headers += "\nwtv-relogin-url: wtv-head-waiter:/relogin?relogin=true";
|
||||||
if (request_headers.query.guest_login) headers += "&guest_login=true";
|
if (request_headers.query.guest_login) headers += "&guest_login=true";
|
||||||
|
|
||||||
headers += "\nwtv-reconnect-url: wtv-head-waiter:/login-stage-two?reconnect=true";
|
headers += "\nwtv-reconnect-url: wtv-head-waiter:/login-stage-two?reconnect=true";
|
||||||
if (request_headers.query.guest_login) headers += "&guest_login=true";
|
if (request_headers.query.guest_login) headers += "&guest_login=true";
|
||||||
|
|
||||||
headers += "\nwtv-boot-url: wtv-head-waiter:/relogin?relogin=true";
|
headers += "\nwtv-boot-url: wtv-head-waiter:/relogin?relogin=true";
|
||||||
if (request_headers.query.guest_login) headers += "&guest_login=true";
|
if (request_headers.query.guest_login) headers += "&guest_login=true";
|
||||||
headers += "\nwtv-allow-dsc: true";
|
|
||||||
headers += "\nwtv-home-url: wtv-home:/home?";
|
|
||||||
|
|
||||||
if (ssid_sessions[socket.ssid].get('wtv-need-upgrade') != 'true' && !request_headers.query.reconnect) {
|
if (!ssid_sessions[socket.ssid].lockdown) headers += "\nwtv-home-url: wtv-home:/home?";
|
||||||
|
|
||||||
|
if (ssid_sessions[socket.ssid].get('wtv-need-upgrade') != 'true' && !request_headers.query.reconnect && !ssid_sessions[socket.ssid].lockdown)
|
||||||
headers += "\nwtv-settings-url: wtv-setup:/get";
|
headers += "\nwtv-settings-url: wtv-setup:/get";
|
||||||
}
|
|
||||||
headers += `
|
headers += `
|
||||||
|
wtv-show-time-enabled: true
|
||||||
|
wtv-allow-dsc: true
|
||||||
|
wtv-tourist-enabled: true
|
||||||
wtv-log-url: wtv-log:/log
|
wtv-log-url: wtv-log:/log
|
||||||
wtv-ssl-log-url: wtv-log:/log
|
wtv-ssl-log-url: wtv-log:/log
|
||||||
wtv-ssl-timeout: 240
|
wtv-ssl-timeout: 240
|
||||||
|
|||||||
@@ -1,31 +1,41 @@
|
|||||||
var minisrv_service_file = true;
|
var minisrv_service_file = true;
|
||||||
|
|
||||||
var settings_obj = ssid_sessions[socket.ssid].getSessionData("wtv-setup");
|
if (ssid_sessions[socket.ssid].lockdown) {
|
||||||
if (settings_obj === null) settings_obj = {};
|
headers = `200 OK
|
||||||
|
wtv-printer-model: -1,-1
|
||||||
|
wtv-printer-pen: 0,0,1,0
|
||||||
|
wtv-printer-setup: 0,0,1,0
|
||||||
|
wtv-language-header: en-US,en
|
||||||
|
Content-Type: text/html`;
|
||||||
|
data = "";
|
||||||
|
} else {
|
||||||
|
|
||||||
settings_obj["from-server"] = 1;
|
var settings_obj = ssid_sessions[socket.ssid].getSessionData("wtv-setup");
|
||||||
|
if (settings_obj === null) settings_obj = {};
|
||||||
|
|
||||||
// defaults
|
settings_obj["from-server"] = 1;
|
||||||
if (!settings_obj["setup-advanced-options"]) settings_obj["setup-advanced-options"] = 0;
|
|
||||||
if (!settings_obj["setup-play-bgm"]) settings_obj["setup-play-bgm"] = 0;
|
|
||||||
if (!settings_obj["setup-bgm-tempo"]) settings_obj["setup-bgm-tempo"] = -1;
|
|
||||||
if (!settings_obj["setup-bgm-volume"]) settings_obj["setup-bgm-volume"] = 100;
|
|
||||||
if (!settings_obj["setup-background-color"]) settings_obj["setup-background-color"] = "c6c6c6";
|
|
||||||
if (!settings_obj["setup-font-sizes"]) settings_obj["setup-font-sizes"] = "medium";
|
|
||||||
if (!settings_obj["setup-in-stereo"]) settings_obj["setup-in-stereo"] = 1;
|
|
||||||
if (!settings_obj["setup-keyboard"]) settings_obj["setup-keyboard"] = "alphabetical";
|
|
||||||
if (!settings_obj["setup-link-color"]) settings_obj["setup-link-color"] = "2222bb";
|
|
||||||
if (!settings_obj["setup-play-songs"]) settings_obj["setup-play-songs"] = 1;
|
|
||||||
if (!settings_obj["setup-play-sounds"]) settings_obj["setup-play-sounds"] = 1;
|
|
||||||
if (!settings_obj["setup-text-color"]) settings_obj["setup-text-color"] = 0;
|
|
||||||
if (!settings_obj["setup-visited-color"]) settings_obj["setup-visited-color"] = "8822bb";
|
|
||||||
if (!settings_obj["setup-japan-keyboard"]) settings_obj["setup-japan-keyboard"] = "roman";
|
|
||||||
if (!settings_obj["setup-japan-softkeyboard"]) settings_obj["setup-japan-softkeyboard"] = "roman"
|
|
||||||
if (!settings_obj["setup-chat-access-level"]) settings_obj["setup-chat-access-level"] = 0;
|
|
||||||
if (!settings_obj["setup-chat-on-nontrusted-pages"]) settings_obj["setup-chat-on-nontrusted-pages"] = 1;
|
|
||||||
if (!settings_obj["setup-tv-chat-level"]) settings_obj["setup-tv-chat-level"] = 2;
|
|
||||||
|
|
||||||
headers = `200 OK
|
// defaults
|
||||||
|
if (!settings_obj["setup-advanced-options"]) settings_obj["setup-advanced-options"] = 0;
|
||||||
|
if (!settings_obj["setup-play-bgm"]) settings_obj["setup-play-bgm"] = 0;
|
||||||
|
if (!settings_obj["setup-bgm-tempo"]) settings_obj["setup-bgm-tempo"] = -1;
|
||||||
|
if (!settings_obj["setup-bgm-volume"]) settings_obj["setup-bgm-volume"] = 100;
|
||||||
|
if (!settings_obj["setup-background-color"]) settings_obj["setup-background-color"] = "c6c6c6";
|
||||||
|
if (!settings_obj["setup-font-sizes"]) settings_obj["setup-font-sizes"] = "medium";
|
||||||
|
if (!settings_obj["setup-in-stereo"]) settings_obj["setup-in-stereo"] = 1;
|
||||||
|
if (!settings_obj["setup-keyboard"]) settings_obj["setup-keyboard"] = "alphabetical";
|
||||||
|
if (!settings_obj["setup-link-color"]) settings_obj["setup-link-color"] = "2222bb";
|
||||||
|
if (!settings_obj["setup-play-songs"]) settings_obj["setup-play-songs"] = 1;
|
||||||
|
if (!settings_obj["setup-play-sounds"]) settings_obj["setup-play-sounds"] = 1;
|
||||||
|
if (!settings_obj["setup-text-color"]) settings_obj["setup-text-color"] = 0;
|
||||||
|
if (!settings_obj["setup-visited-color"]) settings_obj["setup-visited-color"] = "8822bb";
|
||||||
|
if (!settings_obj["setup-japan-keyboard"]) settings_obj["setup-japan-keyboard"] = "roman";
|
||||||
|
if (!settings_obj["setup-japan-softkeyboard"]) settings_obj["setup-japan-softkeyboard"] = "roman"
|
||||||
|
if (!settings_obj["setup-chat-access-level"]) settings_obj["setup-chat-access-level"] = 0;
|
||||||
|
if (!settings_obj["setup-chat-on-nontrusted-pages"]) settings_obj["setup-chat-on-nontrusted-pages"] = 1;
|
||||||
|
if (!settings_obj["setup-tv-chat-level"]) settings_obj["setup-tv-chat-level"] = 2;
|
||||||
|
|
||||||
|
headers = `200 OK
|
||||||
wtv-backgroundmusic-load-playlist: wtv-setup:/get-playlist
|
wtv-backgroundmusic-load-playlist: wtv-setup:/get-playlist
|
||||||
wtv-printer-model: -1,-1
|
wtv-printer-model: -1,-1
|
||||||
wtv-printer-pen: 0,0,1,0
|
wtv-printer-pen: 0,0,1,0
|
||||||
@@ -33,10 +43,11 @@ wtv-printer-setup: 0,0,1,0
|
|||||||
wtv-language-header: en-US,en
|
wtv-language-header: en-US,en
|
||||||
Content-Type: text/html`;
|
Content-Type: text/html`;
|
||||||
|
|
||||||
data = "";
|
data = "";
|
||||||
|
|
||||||
Object.keys(settings_obj).forEach(function (k, v) {
|
Object.keys(settings_obj).forEach(function (k, v) {
|
||||||
data += k + "=" + escape(settings_obj[k]) + "&";
|
data += k + "=" + escape(settings_obj[k]) + "&";
|
||||||
});
|
});
|
||||||
|
|
||||||
data = data.substring(0, (data.length - 1));
|
data = data.substring(0, (data.length - 1));
|
||||||
|
}
|
||||||
@@ -14,6 +14,10 @@ class WTVClientSessionData {
|
|||||||
minisrv_config = [];
|
minisrv_config = [];
|
||||||
wtvshared = null;
|
wtvshared = null;
|
||||||
wtvmime = null;
|
wtvmime = null;
|
||||||
|
lockdown = null;
|
||||||
|
lockdownReason = null;
|
||||||
|
lockdownWhitelist = null;
|
||||||
|
clientAddress = null;
|
||||||
|
|
||||||
constructor(minisrv_config, ssid) {
|
constructor(minisrv_config, ssid) {
|
||||||
if (!minisrv_config) throw ("minisrv_config required");
|
if (!minisrv_config) throw ("minisrv_config required");
|
||||||
@@ -22,10 +26,19 @@ class WTVClientSessionData {
|
|||||||
this.minisrv_config = minisrv_config;
|
this.minisrv_config = minisrv_config;
|
||||||
this.wtvshared = new WTVShared(minisrv_config);
|
this.wtvshared = new WTVShared(minisrv_config);
|
||||||
this.wtvmime = new WTVMime(minisrv_config);
|
this.wtvmime = new WTVMime(minisrv_config);
|
||||||
|
this.lockdown = false;
|
||||||
this.ssid = ssid;
|
this.ssid = ssid;
|
||||||
this.data_store = new Array();
|
this.data_store = new Array();
|
||||||
this.session_store = {};
|
this.session_store = {};
|
||||||
|
this.lockdownWhitelist = [
|
||||||
|
"wtv-1800:/preregister",
|
||||||
|
"wtv-head-waiter:/login",
|
||||||
|
"wtv-head-waiter:/relogin",
|
||||||
|
"wtv-head-waiter:/login-stage-two",
|
||||||
|
"wtv-head-waiter:/bad-disk",
|
||||||
|
"wtv-log:/log"
|
||||||
|
];
|
||||||
|
this.lockdownWhitelist.push(minisrv_config.config.unauthorized_url);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -393,6 +406,159 @@ class WTVClientSessionData {
|
|||||||
if (key === null) throw ("ClientSessionData.delete(): invalid key provided");
|
if (key === null) throw ("ClientSessionData.delete(): invalid key provided");
|
||||||
delete this.data_store[key];
|
delete this.data_store[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getBoxName() {
|
||||||
|
switch (this.get("wtv-client-rom-type")) {
|
||||||
|
case "US-DTV-disk-0MB-16MB-softmodem-CPU5230":
|
||||||
|
case "US-DTV-disk-0MB-32MB-softmodem-CPU5230":
|
||||||
|
return "UltimateTV Satellite receiver";
|
||||||
|
|
||||||
|
case "US-WEBSTAR-disk-0MB-8MB-softmodem-CPU5230":
|
||||||
|
case "US-WEBSTAR-disk-0MB-16MB-softmodem-CPU5230":
|
||||||
|
return "WebTV Satellite receiver";
|
||||||
|
|
||||||
|
case "US-LC2-flashdisk-0MB-16MB-softmodem-CPU5230":
|
||||||
|
case "US-LC2-disk-0MB-8MB":
|
||||||
|
case "US-LC2-flash-2MB-8MB":
|
||||||
|
case "JP-LC2-disk-0MB-8MB":
|
||||||
|
case "JP-LC2-flash-2MB-8MB":
|
||||||
|
case "US-LC2-disk-0MB-8MB-softmodem-CPU5230":
|
||||||
|
case "US-LC2-flash-2MB-8MB-softmodem-CPU5230 ":
|
||||||
|
case "US-LC2-disk-0MB-8MB-CPU5230":
|
||||||
|
case "US-LC2-flash-2MB-8MB-CPU5230":
|
||||||
|
case "JP-LC2-disk-0MB-8MB-CPU5230":
|
||||||
|
case "JP-LC2-disk-0MB-16MB-CPU5230":
|
||||||
|
case "JP-LC2-flash-2MB-8MB-CPU5230":
|
||||||
|
return "WebTV Plus receiver";
|
||||||
|
|
||||||
|
default:
|
||||||
|
return "WebTV Internet receiver";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
checkSecurity() {
|
||||||
|
var self = this;
|
||||||
|
var rejectReason = null;
|
||||||
|
var ip2long = function (ip) {
|
||||||
|
var components;
|
||||||
|
|
||||||
|
if (components = ip.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/)) {
|
||||||
|
var iplong = 0;
|
||||||
|
var power = 1;
|
||||||
|
for (var i = 4; i >= 1; i -= 1) {
|
||||||
|
iplong += power * parseInt(components[i]);
|
||||||
|
power *= 256;
|
||||||
|
}
|
||||||
|
return iplong;
|
||||||
|
}
|
||||||
|
else return -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
var isInSubnet = function (ip, subnet) {
|
||||||
|
var mask, base_ip, long_ip = ip2long(ip);
|
||||||
|
if ((mask = subnet.match(/^(.*?)\/(\d{1,2})$/)) && ((base_ip = ip2long(mask[1])) >= 0)) {
|
||||||
|
var freedom = Math.pow(2, 32 - parseInt(mask[2]));
|
||||||
|
return (long_ip > base_ip) && (long_ip < base_ip + freedom - 1);
|
||||||
|
}
|
||||||
|
else return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
var rejectSSIDConnection = function (blacklist) {
|
||||||
|
if (blacklist) {
|
||||||
|
rejectReason = self.ssid + " is in the blacklist.";
|
||||||
|
console.log(" * Request from SSID", self.wtvshared.filterSSID(self.ssid), "(" + self.clientAddress + "), but that SSID is in the blacklist.");
|
||||||
|
} else {
|
||||||
|
rejectReason = self.ssid + " is not in the whitelist.";
|
||||||
|
console.log(" * Request from SSID", self.wtvshared.filterSSID(self.ssid), "(" + self.clientAddress + "), but that SSID is not in the whitelist.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var checkSSIDIPWhitelist = function (ssid, blacklist) {
|
||||||
|
var ssid_access_list_ip_override = false;
|
||||||
|
if (self.minisrv_config.config.ssid_ip_allow_list) {
|
||||||
|
if (self.minisrv_config.config.ssid_ip_allow_list[self.ssid]) {
|
||||||
|
Object.keys(self.minisrv_config.config.ssid_ip_allow_list[self.ssid]).forEach(function (k) {
|
||||||
|
if (self.minisrv_config.config.ssid_ip_allow_list[self.ssid][k].indexOf('/') > 0) {
|
||||||
|
if (isInSubnet(self.clientAddress, self.minisrv_config.config.ssid_ip_allow_list[self.ssid][k])) {
|
||||||
|
// remoteAddr is in allowed subnet
|
||||||
|
ssid_access_list_ip_override = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (self.clientAddress == self.minisrv_config.config.ssid_ip_allow_list[self.ssid][k]) {
|
||||||
|
// remoteAddr directly matches IP
|
||||||
|
ssid_access_list_ip_override = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (!ssid_access_list_ip_override) rejectSSIDConnection(self.ssid, blacklist);
|
||||||
|
} else {
|
||||||
|
rejectSSIDConnection(blacklist);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rejectSSIDConnection(blacklist);
|
||||||
|
}
|
||||||
|
if (ssid_access_list_ip_override && self.minisrv_config.config.debug_flags.debug) console.log(" * Request from disallowed SSID", wtvshared.filterSSID(ssid), "was allowed due to IP address whitelist");
|
||||||
|
}
|
||||||
|
|
||||||
|
// process whitelist first
|
||||||
|
if (self.ssid && self.minisrv_config.config.ssid_allow_list) {
|
||||||
|
var ssid_is_in_whitelist = self.minisrv_config.config.ssid_allow_list.findIndex(element => element == self.ssid);
|
||||||
|
if (ssid_is_in_whitelist == -1) {
|
||||||
|
// no whitelist match, but lets see if the remoteAddress is allowed
|
||||||
|
checkSSIDIPWhitelist(self.ssid, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// now check blacklist
|
||||||
|
if (self.ssid && self.minisrv_config.config.ssid_block_list) {
|
||||||
|
var ssid_is_in_blacklist = self.minisrv_config.config.ssid_block_list.findIndex(element => element == self.ssid);
|
||||||
|
if (ssid_is_in_blacklist != -1) {
|
||||||
|
// blacklist match, but lets see if the remoteAddress is allowed
|
||||||
|
checkSSIDIPWhitelist(self.ssid, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (rejectReason === null) {
|
||||||
|
// Passed Security
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
// Failed security
|
||||||
|
this.enableLockdown(rejectReason);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
isAuthorized(url) {
|
||||||
|
// not in lockdown so just return true
|
||||||
|
if (!this.lockdown) return true;
|
||||||
|
|
||||||
|
// in lockdown, check whitelisted urls
|
||||||
|
var self = this;
|
||||||
|
var authorized = false;
|
||||||
|
Object.keys(this.lockdownWhitelist).forEach(function (k) {
|
||||||
|
if (self.lockdownWhitelist[k].substring(0, url.length) == url) authorized = true;
|
||||||
|
});
|
||||||
|
return authorized;
|
||||||
|
}
|
||||||
|
|
||||||
|
enableLockdown(reason) {
|
||||||
|
this.lockdown = true;
|
||||||
|
this.lockdownReason = reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
disableLockdown() {
|
||||||
|
this.lockdown = false;
|
||||||
|
this.lockdownReason = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
setClientAddress(addr) {
|
||||||
|
this.clientAddress = addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
getClientAddress() {
|
||||||
|
return this.clientAddress;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = WTVClientSessionData;
|
module.exports = WTVClientSessionData;
|
||||||
@@ -297,6 +297,7 @@ async function processURL(socket, request_headers) {
|
|||||||
} else {
|
} else {
|
||||||
shortURL = unescape(request_headers.request_url);
|
shortURL = unescape(request_headers.request_url);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request_headers['wtv-request-type']) socket_sessions[socket.id].wtv_request_type = request_headers['wtv-request-type'];
|
if (request_headers['wtv-request-type']) socket_sessions[socket.id].wtv_request_type = request_headers['wtv-request-type'];
|
||||||
|
|
||||||
if (request_headers.post_data) {
|
if (request_headers.post_data) {
|
||||||
@@ -361,6 +362,23 @@ async function processURL(socket, request_headers) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// check security
|
||||||
|
if (!ssid_sessions[socket.ssid].isAuthorized(shortURL)) {
|
||||||
|
// lockdown mode and URL not authorized
|
||||||
|
//socket_sessions[socket.id].close_me = true;
|
||||||
|
headers = "300 Unauthorized\n";
|
||||||
|
headers += "Location: " + minisrv_config.config.unauthorized_url + "\n";
|
||||||
|
data = "";
|
||||||
|
sendToClient(socket, headers, data);
|
||||||
|
console.log(" * Lockdown rejected request for " + shortURL + " on socket ID", socket.id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ssid_sessions[socket.ssid].get("wtv-my-disk-sucks-sucks-sucks")) {
|
||||||
|
// psuedo lockdown, will unlock on the disk warning page, but prevents minisrv access until they read the error
|
||||||
|
ssid_sessions[socket.ssid].lockdown = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (shortURL.indexOf(':/') >= 0 && shortURL.indexOf('://') < 0) {
|
if (shortURL.indexOf(':/') >= 0 && shortURL.indexOf('://') < 0) {
|
||||||
var ssid = socket.ssid;
|
var ssid = socket.ssid;
|
||||||
@@ -840,101 +858,6 @@ function moveObjectElement(currentKey, afterKey, obj) {
|
|||||||
if (next !== -1) return result; else return obj;
|
if (next !== -1) return result; else return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkSecurity(socket) {
|
|
||||||
var out = null;
|
|
||||||
var ip2long = function (ip) {
|
|
||||||
var components;
|
|
||||||
|
|
||||||
if (components = ip.match(/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/)) {
|
|
||||||
var iplong = 0;
|
|
||||||
var power = 1;
|
|
||||||
for (var i = 4; i >= 1; i -= 1) {
|
|
||||||
iplong += power * parseInt(components[i]);
|
|
||||||
power *= 256;
|
|
||||||
}
|
|
||||||
return iplong;
|
|
||||||
}
|
|
||||||
else return -1;
|
|
||||||
};
|
|
||||||
|
|
||||||
var isInSubnet = function (ip, subnet) {
|
|
||||||
var mask, base_ip, long_ip = ip2long(ip);
|
|
||||||
if ((mask = subnet.match(/^(.*?)\/(\d{1,2})$/)) && ((base_ip = ip2long(mask[1])) >= 0)) {
|
|
||||||
var freedom = Math.pow(2, 32 - parseInt(mask[2]));
|
|
||||||
return (long_ip > base_ip) && (long_ip < base_ip + freedom - 1);
|
|
||||||
}
|
|
||||||
else return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
var rejectSSIDConnection = function (ssid, blacklist) {
|
|
||||||
var rejectReason = null;
|
|
||||||
if (blacklist) {
|
|
||||||
rejectReason = ssid + " is in the blacklist.";
|
|
||||||
console.log(" * Request from SSID", wtvshared.filterSSID(ssid), "(" + socket.remoteAddress + "), but that SSID is in the blacklist, rejecting.");
|
|
||||||
} else {
|
|
||||||
rejectReason = ssid + " is not in the whitelist.";
|
|
||||||
console.log(" * Request from SSID", wtvshared.filterSSID(socket.ssid), "(" + socket.remoteAddress + "), but that SSID is not in the whitelist, rejecting.");
|
|
||||||
}
|
|
||||||
if (fs.existsSync(__dirname + '/ServiceDeps/TOS.html')) {
|
|
||||||
var tosErrorPage = fs.readFileSync(__dirname + '/ServiceDeps/TOS.html').toString();
|
|
||||||
out = new Array(`200 Goodbye
|
|
||||||
wtv-service: reset
|
|
||||||
Connection: close
|
|
||||||
Content-type: text/html`, tosErrorPage.replace('\$\{REASON\}', rejectReason));
|
|
||||||
} else {
|
|
||||||
var errpage = wtvshared.doErrorPage(401, "Access to this service is denied.");
|
|
||||||
out = errpage;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var checkSSIDIPWhitelist = function (ssid, blacklist) {
|
|
||||||
var ssid_access_list_ip_override = false;
|
|
||||||
if (minisrv_config.config.ssid_ip_allow_list) {
|
|
||||||
if (minisrv_config.config.ssid_ip_allow_list[socket.ssid]) {
|
|
||||||
Object.keys(minisrv_config.config.ssid_ip_allow_list[socket.ssid]).forEach(function (k) {
|
|
||||||
if (minisrv_config.config.ssid_ip_allow_list[socket.ssid][k].indexOf('/') > 0) {
|
|
||||||
if (isInSubnet(socket.remoteAddress, minisrv_config.config.ssid_ip_allow_list[socket.ssid][k])) {
|
|
||||||
// remoteAddr is in allowed subnet
|
|
||||||
ssid_access_list_ip_override = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (socket.remoteAddress == minisrv_config.config.ssid_ip_allow_list[socket.ssid][k]) {
|
|
||||||
// remoteAddr directly matches IP
|
|
||||||
ssid_access_list_ip_override = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (!ssid_access_list_ip_override) rejectSSIDConnection(socket.ssid, blacklist);
|
|
||||||
} else {
|
|
||||||
rejectSSIDConnection(socket.ssid, blacklist);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
rejectSSIDConnection(socket.ssid, blacklist);
|
|
||||||
}
|
|
||||||
if (ssid_access_list_ip_override && minisrv_config.config.debug_flags.debug) console.log(" * Request from disallowed SSID", wtvshared.filterSSID(ssid), "was allowed due to IP address whitelist");
|
|
||||||
}
|
|
||||||
|
|
||||||
// process whitelist first
|
|
||||||
if (socket.ssid && minisrv_config.config.ssid_allow_list) {
|
|
||||||
var ssid_is_in_whitelist = minisrv_config.config.ssid_allow_list.findIndex(element => element == socket.ssid);
|
|
||||||
if (ssid_is_in_whitelist == -1) {
|
|
||||||
// no whitelist match, but lets see if the remoteAddress is allowed
|
|
||||||
checkSSIDIPWhitelist(socket.ssid, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// now check blacklist
|
|
||||||
if (socket.ssid && minisrv_config.config.ssid_block_list) {
|
|
||||||
var ssid_is_in_blacklist = minisrv_config.config.ssid_block_list.findIndex(element => element == socket.ssid);
|
|
||||||
if (ssid_is_in_blacklist != -1) {
|
|
||||||
// blacklist match, but lets see if the remoteAddress is allowed
|
|
||||||
checkSSIDIPWhitelist(socket.ssid, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Passed Security
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
function isUnencryptedString(string, verbose = false) {
|
function isUnencryptedString(string, verbose = false) {
|
||||||
// a generic "isAscii" check is not sufficient, as the test will see the binary
|
// a generic "isAscii" check is not sufficient, as the test will see the binary
|
||||||
@@ -1019,19 +942,12 @@ async function processRequest(socket, data_hex, skipSecure = false, encryptedReq
|
|||||||
ssid_sessions[socket.ssid].SaveIfRegistered();
|
ssid_sessions[socket.ssid].SaveIfRegistered();
|
||||||
}
|
}
|
||||||
if (!ssid_sessions[socket.ssid].data_store.sockets) ssid_sessions[socket.ssid].data_store.sockets = new Set();
|
if (!ssid_sessions[socket.ssid].data_store.sockets) ssid_sessions[socket.ssid].data_store.sockets = new Set();
|
||||||
ssid_sessions[socket.ssid].ssid = socket.ssid;
|
|
||||||
ssid_sessions[socket.ssid].data_store.sockets.add(socket);
|
ssid_sessions[socket.ssid].data_store.sockets.add(socket);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var failed_security = checkSecurity(socket);
|
if (!ssid_sessions[socket.ssid].getClientAddress()) ssid_sessions[socket.ssid].setClientAddress(socket.remoteAddress);
|
||||||
if (failed_security) {
|
ssid_sessions[socket.ssid].checkSecurity();
|
||||||
socket_sessions[socket.id].close_me = true;
|
|
||||||
headers = failed_security[0];
|
|
||||||
data = failed_security[1];
|
|
||||||
sendToClient(socket, headers, data);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (headers["wtv-capability-flags"] != null) {
|
if (headers["wtv-capability-flags"] != null) {
|
||||||
if (!ssid_sessions[socket.ssid]) {
|
if (!ssid_sessions[socket.ssid]) {
|
||||||
|
|||||||
@@ -24,7 +24,9 @@
|
|||||||
"pc_server_hidden_service_enabled": false,
|
"pc_server_hidden_service_enabled": false,
|
||||||
"show_detailed_splash": true,
|
"show_detailed_splash": true,
|
||||||
"show_diskmap": false,
|
"show_diskmap": false,
|
||||||
"allow_guests": true
|
"unauthorized_url": "wtv-1800:/unauthorized?",
|
||||||
|
"allow_guests": true,
|
||||||
|
"domain_name": "wtv.zefie.com"
|
||||||
},
|
},
|
||||||
"services": {
|
"services": {
|
||||||
"wtv-head-waiter": {
|
"wtv-head-waiter": {
|
||||||
|
|||||||
@@ -38,7 +38,6 @@
|
|||||||
<Content Include="ServiceDeps\premade_tellyscripts\LC2\LC2_OpenISP_56k.tok" />
|
<Content Include="ServiceDeps\premade_tellyscripts\LC2\LC2_OpenISP_56k.tok" />
|
||||||
<Content Include="ServiceDeps\premade_tellyscripts\LC2\LC2_WTV_18006138199.detok.txt" />
|
<Content Include="ServiceDeps\premade_tellyscripts\LC2\LC2_WTV_18006138199.detok.txt" />
|
||||||
<Content Include="ServiceDeps\premade_tellyscripts\LC2\LC2_WTV_18006138199.tok" />
|
<Content Include="ServiceDeps\premade_tellyscripts\LC2\LC2_WTV_18006138199.tok" />
|
||||||
<Content Include="ServiceDeps\TOS.html" />
|
|
||||||
<Content Include="ServiceVault\http_pc\get.js" />
|
<Content Include="ServiceVault\http_pc\get.js" />
|
||||||
<Content Include="ServiceVault\http_pc\index.js" />
|
<Content Include="ServiceVault\http_pc\index.js" />
|
||||||
<Content Include="ServiceVault\wtv-1800\noflash.js" />
|
<Content Include="ServiceVault\wtv-1800\noflash.js" />
|
||||||
@@ -88,6 +87,7 @@
|
|||||||
<Content Include="ServiceVault\wtv-flashrom\ROMCache\up-arrows.swf" />
|
<Content Include="ServiceVault\wtv-flashrom\ROMCache\up-arrows.swf" />
|
||||||
<Content Include="ServiceVault\wtv-flashrom\ROMCache\WebTVLogoJewel.gif" />
|
<Content Include="ServiceVault\wtv-flashrom\ROMCache\WebTVLogoJewel.gif" />
|
||||||
<Content Include="ServiceVault\wtv-flashrom\willie.js" />
|
<Content Include="ServiceVault\wtv-flashrom\willie.js" />
|
||||||
|
<Content Include="ServiceVault\wtv-head-waiter\bad-disk.js" />
|
||||||
<Content Include="ServiceVault\wtv-head-waiter\relogin.js">
|
<Content Include="ServiceVault\wtv-head-waiter\relogin.js">
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</Content>
|
</Content>
|
||||||
@@ -234,6 +234,7 @@
|
|||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</Content>
|
</Content>
|
||||||
<Content Include="ServiceVault\wtv-register\splash.js" />
|
<Content Include="ServiceVault\wtv-register\splash.js" />
|
||||||
|
<Content Include="ServiceVault\wtv-1800\unauthorized.js" />
|
||||||
<Content Include="ServiceVault\wtv-setup\adjust-brightness.js" />
|
<Content Include="ServiceVault\wtv-setup\adjust-brightness.js" />
|
||||||
<Content Include="ServiceVault\wtv-setup\adjust-contrast.js" />
|
<Content Include="ServiceVault\wtv-setup\adjust-contrast.js" />
|
||||||
<Content Include="ServiceVault\wtv-setup\adjust-display-intro.js" />
|
<Content Include="ServiceVault\wtv-setup\adjust-display-intro.js" />
|
||||||
|
|||||||
Reference in New Issue
Block a user