Compare commits

6 Commits

Author SHA1 Message Date
Ryder
8089bd4439 Remove redundant files 2026-05-08 00:35:58 +01:00
zefie
750435fc83 small cleanup 2026-05-05 14:39:39 -04:00
zefie
fd67132da9 store the msntv2 token so we can look it up later 2026-05-05 14:35:37 -04:00
zefie
43a87347b8 some more msntv2 updates 2026-05-05 09:20:31 -04:00
zefie
e1d2c59ed5 some updates 2026-05-05 07:43:40 -04:00
2d64acaab6 Merge pull request 'Fix TV2 support' (#1) from feature/FixTv2 into dev
Reviewed-on: #1
2026-05-05 02:20:34 +02:00
31 changed files with 885 additions and 1616 deletions

View File

@@ -1,27 +1,29 @@
-----BEGIN CERTIFICATE----- -----BEGIN CERTIFICATE-----
MIIEqzCCA5OgAwIBAgIQ3Zq6hcFrpKh4v3/G9sTw3DANBgkqhkiG9w0BAQUFADBw MIIE8TCCA9mgAwIBAgIQhTOF71uduRa0SXk4z+A7ujANBgkqhkiG9w0BAQUFADB0
MQswCQYDVQQGEwJVUzELMAkGA1UECAwCT0gxEzARBgNVBAcMCkJ1dHQgQ3JhY2sx MRkwFwYDVQQDDBBtaW5pc3J2IHNlcnZpY2VzMREwDwYDVQQIDAhOZXcgWW9yazEL
IDAeBgNVBAoMF1VuZGVyd2VhciBJbnNwZWN0b3IgIzEyMR0wGwYDVQQLDBRUaGlu MAkGA1UEBhMCVVMxHjAcBgkqhkiG9w0BCQEWD3plZmllQHplZmllLm5ldDEXMBUG
ZyBMb29rZXIgRXhwZXJ0czAgFw0wMDAxMDExMjAwMDBaGA8yMDk5MTIzMTIzNTk1 A1UECgwOWmVmaWUgTmV0d29ya3MwIBcNMDAwMTAxMTIwMDAwWhgPMjA5OTEyMzEy
OVowUTEpMCcGA1UEAxMgaGVhZHdhaXRlci50cnVzdGVkLm1zbnR2Lm1zbi5jb20x MzU5NTlaMFExKTAnBgNVBAMTIGhlYWR3YWl0ZXIudHJ1c3RlZC5tc250di5tc24u
FzAVBgNVBAoTDlplZmllIE5ldHdvcmtzMQswCQYDVQQGEwJVUzCCASIwDQYJKoZI Y29tMRcwFQYDVQQKEw5aZWZpZSBOZXR3b3JrczELMAkGA1UEBhMCVVMwggEiMA0G
hvcNAQEBBQADggEPADCCAQoCggEBAMtl9J068AFSHykffAlcpspq3D7mE7fFRoyf CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6pNNH2lF7SFx8cEIF1ImA7AI4bv/W
+tQCM3Wy7PqJvDAegoI4Zf/QdToTJMS6dkcsEx+dgD01VKJ1B0RdHbg6rFQfymc4 qvbErvUYJOfrOLXOfvXnxWEbEfDk9+XEf+JD8PQo2rvze1cVcXjVO7i2m+c4jdWw
GKyNk6tuqp7YQqElCUc91oFz4pJaJaOYaNBqkAG3MfTg+tSoBXl2YyjPrT0TPhXX X/VPdRM0NpoppFXbWC7nWNuXhZD/S7f6pUEJez7BYUpEeBFdR9eFb8VPo8+kefMz
1Cm7BuFZORqNhvTdf33QXzgCQVso9U5X9YBgDaiTcu55etjFKUBEYhSYwTHmennA inYznvP1UAn9wwoSIFDglX9QbijkJ/ZKtOY3vxCMVBZedWVnMPEJt928NJBNDGcC
FWOjY7ux6HFXBfKAz1QeCE6+corl5+6srCfh7Uz3ZFV9vntEYnyzbJuo6gR5P7GI VeV1thEAAVbQBf5nyhF9VfblTzEHoxq+d6rvi4rVkd0ZYqQPCcafDFccXf6YNQcz
IYsygkADQAETHivl6GxeB7SEUfYLnfrZFwZc235tUz7USBdg3gcCAwEAAaOCAVww 8cmwzha61bgLbJLPNPiSqbqL8GNfsHbt2vyX6OhYpKwF+Y2CCp0xbGflAgMBAAGj
ggFYMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMB ggGeMIIBmjAJBgNVHRMEAjAAMAsGA1UdDwQEAwIFoDATBgNVHSUEDDAKBggrBgEF
MIIBJwYDVR0RBIIBHjCCARqCIGhlYWR3YWl0ZXIudHJ1c3RlZC5tc250di5tc24u BQcDATCCAWkGA1UdEQSCAWAwggFcgiBoZWFkd2FpdGVyLnRydXN0ZWQubXNudHYu
Y29tghcqLnRydXN0ZWQubXNudHYubXNuLmNvbYINbXNudHYubXNuLmNvbYIWbWFp bXNuLmNvbYIZc2cxLnRydXN0ZWQubXNudHYubXNuLmNvbYIZc2cyLnRydXN0ZWQu
bC5zZXJ2aWNlcy5saXZlLmNvbYIObG9naW4ubGl2ZS5jb22CEXBvcHRpbWl6ZS5t bXNudHYubXNuLmNvbYIZc2czLnRydXN0ZWQubXNudHYubXNuLmNvbYIZc2c0LnRy
c24uY29tghFmYXZvcml0ZXMubXNuLmNvbYIRbWVzc2VuZ2VyLm1zbi5jb22CEWxp dXN0ZWQubXNudHYubXNuLmNvbYINbXNudHYubXNuLmNvbYIWbWFpbC5zZXJ2aWNl
dmVmaWxlc3RvcmUuY29tghZ1c2Vycy5zdG9yYWdlLmxpdmUuY29tgglnLm1zbi5j cy5saXZlLmNvbYIObG9naW4ubGl2ZS5jb22CEXBvcHRpbWl6ZS5tc24uY29tghFm
b22CF21zbmlhbG9naW4ucGFzc3BvcnQuY29tgg1taW5pc3J2LmxvY2Fsgg8qLm1p YXZvcml0ZXMubXNuLmNvbYIRbWVzc2VuZ2VyLm1zbi5jb22CEWxpdmVmaWxlc3Rv
bmlzcnYubG9jYWwwDQYJKoZIhvcNAQEFBQADggEBAAGEINTBTrkbpO0CJPv9w4Nj cmUuY29tghZ1c2Vycy5zdG9yYWdlLmxpdmUuY29tgglnLm1zbi5jb22CF21zbmlh
IMuOSZETA7uXWyPwoLBIa57yTjNEVvWmjAc2nnrI3D6ijLMiF1eDIEsP4DI/qfMs bG9naW4ucGFzc3BvcnQuY29tgg1taW5pc3J2LmxvY2FsMA0GCSqGSIb3DQEBBQUA
J82cS/IOIxXCmReU132NaZ6mSNEZx9QDkz/R8rFq5jKPRYSeguZSsWDxYlaQsbRr A4IBAQAZTy82heE64hCFxEiIFIxglGyPVU14wA2gXrv82mci/U0h/xBHfIfQWY8d
qxQsKkRIOpm5pIOA/UT2gwV0L84a/NHXHNfc+CnPvvy7R9kmUC0XynsqU3lkj4Ah ULM6dO6kEk2DriBbo2ET10rkBwCTqa1iSDRN1eg0umdT2vbEYigjOelZJQqJi3Ua
SNZOgYyWkGWW7AytQWnMxyWm+xQjG4Fwl1Os9en4qwCK0ADyMCQyG3O68Gffu2go LGBrPh8PK7juGa37aEdMWFLxmDtfEXE//OmMiliXU6bIi44pqM571X3Q3WPh3C3K
YciXaJquI52fEKDQV4mDxy4B1V8BQ3ywm1iGebLzLgrKK7xPucUU5fqz7v2IUIs= xOCOwQMgTPovLJDwRIJNyTrnb0kI+1s7oOtZ+QUQa7frY0Bgxn4IMEnZoIkOcAkh
R1m/OKyjjqQ8EVM73dTeiNr0yByG64C8dsVhJVXPT3GZOl7p5Pof9VfQg9Qr39Vh
ds7T/BVzQ79G8IXQ+AgZnZHu7pnn
-----END CERTIFICATE----- -----END CERTIFICATE-----

View File

@@ -1,27 +1,27 @@
-----BEGIN RSA PRIVATE KEY----- -----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY----- -----END RSA PRIVATE KEY-----

View File

@@ -1,5 +1,8 @@
const minisrv_service_file = true; const minisrv_service_file = true;
const crypto = require('crypto');
if (!session_data) {
session_data = new WTVClientSessionData(minisrv_config, (socket.ssid || null))
}
// Sorry Zef :kek // Sorry Zef :kek
// https://git.computernewb.com/yellows111/msnp-wiki/src/branch/master/docs/services/rst.md // https://git.computernewb.com/yellows111/msnp-wiki/src/branch/master/docs/services/rst.md
@@ -93,7 +96,7 @@ function extractTokenFromCipherValue(xml) {
let cipherValue = match[1].trim(); let cipherValue = match[1].trim();
if (cipherValue && cipherValue.length > 0) { if (cipherValue && cipherValue.length > 0) {
token = cipherValue; token = cipherValue;
console.log("Found CipherValue token:", token.substring(0, 50) + "..."); debug("Found CipherValue token:", token.substring(0, 50) + "...");
break; break;
} }
} }
@@ -118,7 +121,7 @@ function validateTokenAndGetUser(token) {
email = `user_${userId.substring(0, 8)}@example.com`; email = `user_${userId.substring(0, 8)}@example.com`;
} }
console.log(`Token validated - UserId: ${userId}, Email: ${email}`); debug(`Token validated - UserId: ${userId}, Email: ${email}`);
return { success: true, userId, email }; return { success: true, userId, email };
} catch (error) { } catch (error) {
console.error("Token validation error:", error); console.error("Token validation error:", error);
@@ -139,7 +142,7 @@ function generateErrorResponse(errorCode, errorText) {
<psf:authstate>0x80048800</psf:authstate> <psf:authstate>0x80048800</psf:authstate>
<psf:reqstatus>${errorCode}</psf:reqstatus> <psf:reqstatus>${errorCode}</psf:reqstatus>
<psf:serverInfo Path="Live1" RollingUpgradeState="ExclusiveNew" LocVersion="0" ServerTime="${now}"> <psf:serverInfo Path="Live1" RollingUpgradeState="ExclusiveNew" LocVersion="0" ServerTime="${now}">
NOBELLIUM 16.0.30846.6 ${minisrv_config.config.service_name} [minisrv ${minisrv_config.config.hide_minisrv_version ? "beta" : minisrv_version_string.replace("zefie's wtv minisrv ","")}]
</psf:serverInfo> </psf:serverInfo>
<psf:cookies></psf:cookies> <psf:cookies></psf:cookies>
<psf:response></psf:response> <psf:response></psf:response>
@@ -205,6 +208,7 @@ function generateSuccessResponse(requestBody, userId, email, firstName, lastName
const needsProofToken = policy === "MBI_KEY_OLD"; const needsProofToken = policy === "MBI_KEY_OLD";
const token = generateRandomToken(userId, appliesTo, isLegacy); const token = generateRandomToken(userId, appliesTo, isLegacy);
wtvshared.storeToken(token, socket.ssid, userId, expiresTime);
const tokenId = isLegacy ? `BinaryDAToken${rstIndex}` : `Compact${rstIndex}`; const tokenId = isLegacy ? `BinaryDAToken${rstIndex}` : `Compact${rstIndex}`;
const binarySecret = crypto.randomBytes(32).toString('base64'); const binarySecret = crypto.randomBytes(32).toString('base64');
@@ -267,6 +271,7 @@ function generateSuccessResponse(requestBody, userId, email, firstName, lastName
if (!foundRst) { if (!foundRst) {
const defaultToken = generateRandomToken(userId, "urn:passport:compact", false); const defaultToken = generateRandomToken(userId, "urn:passport:compact", false);
wtvshared.storeToken(defaultToken, socket.ssid, userId, expiresTime);
responses.push(` responses.push(`
<wst:RequestSecurityTokenResponse> <wst:RequestSecurityTokenResponse>
<wst:TokenType>urn:passport:compact</wst:TokenType> <wst:TokenType>urn:passport:compact</wst:TokenType>
@@ -350,12 +355,12 @@ function rstHandler() {
requestBody = JSON.stringify(request_headers.post_data); requestBody = JSON.stringify(request_headers.post_data);
} }
} else { } else {
console.log("No post_data found. Available keys:", Object.keys(request_headers)); debug("No post_data found. Available keys:", Object.keys(request_headers));
return generateErrorResponse("0x80048820", "No POST data received"); return generateErrorResponse("0x80048820", "No POST data received");
} }
if (!requestBody || requestBody.trim() === '') { if (!requestBody || requestBody.trim() === '') {
console.log("Empty request body"); debug("Empty request body");
return generateErrorResponse("0x80048820", "Empty request body"); return generateErrorResponse("0x80048820", "Empty request body");
} }
@@ -369,7 +374,7 @@ function rstHandler() {
let lastName = "User"; let lastName = "User";
if ((!email || !password) && requestBody.includes('CipherValue')) { if ((!email || !password) && requestBody.includes('CipherValue')) {
console.log("No username/password found, trying token authentication..."); debug("No username/password found, trying token authentication...");
const token = extractTokenFromCipherValue(requestBody); const token = extractTokenFromCipherValue(requestBody);
if (token) { if (token) {
@@ -377,7 +382,7 @@ function rstHandler() {
if (tokenValidation.success) { if (tokenValidation.success) {
userId = tokenValidation.userId; userId = tokenValidation.userId;
userEmail = tokenValidation.email; userEmail = tokenValidation.email;
console.log(`Token authentication successful for: ${userEmail} (${userId})`); debug(`Token authentication successful for: ${userEmail} (${userId})`);
if (request_headers.cookie) { if (request_headers.cookie) {
const cookieEmail = getCookie(request_headers.cookie, 'RST_Email'); const cookieEmail = getCookie(request_headers.cookie, 'RST_Email');
@@ -386,34 +391,40 @@ function rstHandler() {
if (cookieUsername) firstName = cookieUsername; if (cookieUsername) firstName = cookieUsername;
} }
} else { } else {
console.log("Token validation failed"); debug("Token validation failed");
return generateErrorResponse("0x80048821", "Invalid token"); return generateErrorResponse("0x80048821", "Invalid token");
} }
} else { } else {
console.log("No token found in CipherValue"); debug("No token found in CipherValue");
return generateErrorResponse("0x80048820", "Missing credentials/token"); return generateErrorResponse("0x80048820", "Missing credentials/token");
} }
} }
else if (email && password) { else if (email && password) {
console.log(`Extracted - Email: ${email}, Password: ${password ? '***' : 'empty'}`); debug(`Extracted - Email: ${email}, Password: ${password ? '***' : 'empty'}`);
if (email && email.indexOf('@') < 0) { if (email && email.indexOf('@') < 0) {
const domain = (minisrv_config && minisrv_config.config && minisrv_config.config.domain_name) || 'wtv.zefie.com'; const domain = minisrv_config.config.domain_name || 'minisrv.local';
email = `${email}@${domain}`; email = `${email}@${domain}`;
} }
userEmail = email; userEmail = email;
firstName = email.split('@')[0]; firstName = email.split('@')[0];
userId = crypto.createHash('md5').update(email).digest('hex'); userId = crypto.createHash('md5').update(email).digest('hex');
console.log(`Authentication successful for: ${userEmail} (${userId})`); const validAuth = validateCredentials(email, password);
if (!validAuth) {
debug("Invalid credentials");
return generateErrorResponse("0x80048821", "Invalid credentials");
} else {
debug(`Authentication successful for: ${userEmail} (${userId})`);
}
} }
else { else {
console.log("Missing both credentials and token"); debug("Missing both credentials and token");
return generateErrorResponse("0x80048820", "Missing credentials/token"); return generateErrorResponse("0x80048820", "Missing credentials/token");
} }
if (!userId || !userEmail) { if (!userId || !userEmail) {
console.log("Failed to get user identity"); debug("Failed to get user identity");
return generateErrorResponse("0x80048821", "User identity not found"); return generateErrorResponse("0x80048821", "User identity not found");
} }
@@ -438,6 +449,21 @@ function rstHandler() {
} }
} }
function validateCredentials(email, password) {
username = email.split('@')[0];
result_ary = session_data.findAccountByUsername(username);
if (result_ary[0]) {
if (!socket.ssid) {
socket.ssid = result_ary[1];
// second arg should handle secondary users
session_data.setSSID(socket.ssid, result_ary[2]);
}
return session_data.validateUserPassword(password);
}
return false;
}
let result = rstHandler(); let result = rstHandler();
if (result) { if (result) {
data = result; data = result;

View File

@@ -1,629 +0,0 @@
@page "/Pages/Home/Home.aspx"
@using MSNTV2MainServer.Components.Layout
@using Microsoft.AspNetCore.Http
@using Microsoft.AspNetCore.Components
@using MSNTV2MainServer.Components.APIs
@inject IHttpContextAccessor httpContextAccessor
@layout EmptyLayout
@if (IsTV2)
{
MarkupString htmlContent = new MarkupString($@"
<html xmlns:msntv>
<?import namespace=""msntv"" implementation=""Shared/Anduril/HTC/en-us/TruncatedHtml.htc""?>
<head><title>Home</title>
<?import namespace=""msntv"" implementation=""HTC/Shared/CustomButton.htc""?>
<?import namespace=""msntv"" implementation=""/Pages/Home/Shared/BaseClient/HTCTransforms/en-us/LoopingDIV.htc""?>
<script src=""/Include/2.0.261.900/localhost-1700/Shared/BaseClient/JsTransforms/en-us/PaneHelp.js"" language=""javascript"" defer=""true""></script>
<link href=""/Include/2.0.261.778/localhost-1700/Home/Anduril/CssTransforms/en-us/Home.css"" type=""text/css"" rel=""StyleSheet"">
<script src=""/Include/2.0.261.778/localhost-1700/Home/Anduril/JsTransforms/en-us/Home.js"" language=""javascript""></script>
<script>
var forceReload = false;
var l = 'd:' + new Date().valueOf() + '|';
function setCookie(name, value) {{
{{
var now = new Date();
var expires = new Date(now.getFullYear() + 1, now.getMonth(), now.getDate());
document.cookie = escape(name) + '=' + escape(value) + ';expires=' + expires.toGMTString() + ';path=/';
}}
}}
function getCookie(name) {{
{{
var str = document.cookie;
var arr = str.split('; ');
for (var i = arr.length - 1; i >= 0; i--) {{
{{
var c = arr[i].split('=');
if (c.length != 2)
continue;
if (unescape(c[0]) == name)
return unescape(c[1]);
}}
}}
return null;
}}
}}
function syncCookie(cookieName, propValue) {{
{{
var c = getCookie(cookieName);
l += 'g:' + cookieName + ':' + c + '|';
if (c != propValue) {{
{{
setCookie(cookieName, propValue);
l += 's:' + cookieName + ':' + propValue + '|';
var check = getCookie(cookieName);
if (check == propValue)
forceReload = true;
}}
}}
}}
}}
var d = new Date();
var utcOffset = d.getTimezoneOffset();
syncCookie('UserUtcOffset', utcOffset);
var connSpeed;
try {{ {{ connSpeed = window.external.ClientCaps.connectionType; }} }}
catch (e) {{
{{
connSpeed = ""undetected"";
}}
}}
syncCookie('UserConnectionSpeed', connSpeed);
try {{
{{
top.log(l);
}}
}}
catch (e) {{
{{
}}
}}
if (forceReload)
location.replace(location.href);
</script></head>
<body>
<body onload=""initPage();"" scroll=""no"" tabindex=""-1"">
<div id=""focdiv"" style=""position:absolute;top:314px;left:27px;width:70px;height:70px;"" onclick=""goToMail();"">
</div>
<script>
document.all[""focdiv""].focus();
// when looping div is ready, you can hide the invisible rectangle used for holding Mail's
function handleLoopingDivReady()
{{
document.all[""focdiv""].style.display = ""none"";
}}
</script>
<div class=""topdiv"">
<div class=""textMenu"">
<script xmlns:msntvuxp=""msntvuxp.microsoft.com"">
function goToService(serviceName) {{window.location = window.external.SafeGetServiceURL(serviceName);}}
function goToCenter(URL) {{window.location = URL;}}
</script>
<div style=""position:absolute; left:0px; top:0px"" xmlns:msntvuxp=""msntvuxp.microsoft.com"">
<table border=""0"" class=""TextMenuTbl"">
<tr height=""34"" style=""background-color: transparent;"">
<td class=""leftGradientTD""></td><td class=""rightGradientTD"">
</td>
</tr>
</table>
</div>
<div style=""position:absolute; left:0px; top:0px"" xmlns:msntvuxp=""msntvuxp.microsoft.com"">
<table border=""0"" class=""TextMenuTbl"">
<tr>
<td style=""background-color: transparent;"" width=""8"">
<img height=""1"" src=""/Images/Shared/s.gif"" width=""8"">
</td>
<td style=""background-color: transparent;"" align=""left"" width=""162"">
<a class=""TextMenuLink"" href=""javascript:goToCenter('/Pages/UsingMSNTV/Main');"" id=""UsingMSNTVLinkID"" onblur=""umtvHasFocus=false"">Using MSN TV</a>
</td>
<div>
<span style=""position:absolute;left:0;top:35px;width:100%;height:2px;background-color:#8fc3d6;"">
</span>
</div>
<td style=""background-color: transparent;"" align=""left"" width=""115"">
<a class=""TextMenuLink"" href=""javascript:void(window.open(' ', 'signout', 'msntv:panel'));"" id=""SignoutLinkID"">Sign Out</a>
</td>
<div>
<span style=""position:absolute;left:0;top:35px;width:100%;height:2px;background-color:#8fc3d6;""></span>
</div>
<td style=""background-color: transparent;"" align=""left"" width=""106"">
<a class=""TextMenuLink"" href=""javascript:goToService('UAM::UAMbase');"" id=""AccountLinkID"">Account</a>
</td>
<div>
<span style=""position:absolute;left:0;top:35px;width:100%;height:2px;background-color:#8fc3d6;"">
</span>
</div>
<td style=""background-color: transparent;"" align=""left"" width=""109"">
<a class=""TextMenuLink"" href=""javascript:goToService('settings::mainindex');"" id=""SettingsLinkID"">Settings</a>
</td>
<div><span style=""position:absolute;left:0;top:35px;width:100%;height:2px;background-color:#8fc3d6;"">
</span>
</div>
<td style=""background-color: transparent;"" align=""left"" width=""78"">
<a href='javascript:CallPaneHelp(PH_TOC);' id=""HelpLinkID"">
<table><tr>
<td valign=""middle"" class=""TextMenuLinkSimulation"">Help</td>
<td valign=""middle"" width=""30"" height=""20"">
<span id=""helpIcon"" style='src:url(msntv:/Shared/Images/Icon_Help_RelatedLink.png);'></span>
</td>
</tr>
</table>
</a>
</td>
<div>
<span style=""position:absolute;left:0;top:35px;width:100%;height:2px;background-color:#8fc3d6;"">
</span>
</div>
</tr>
</table>
</div>
</div>
<div class=""infoPaneDiv"">
<div class=""promoImgDiv"">
<div style=""position:absolute; left:0px; top:0px"">
<img id=""PromoImageID"" width=""178"" height=""135"" border=""0"" hspace=""0"" alt=""Promotional Image"" src=""/Pages/Home/ads/webtv3.gif"">
</div>
<div style=""position:absolute; left:5px; top:0px""><a id=""PromoImageLinkID"" href="""">
<table width=""173"" height=""135""><tr><td></td></tr></table></a>
</div>
</div>
<div id=""timerRotatorDiv"" class=""personalPanelDiv"" onclick=""ClickRotator()"">
<div>
<div style=""top:0px; left:0px; width:176px; height:105px;"" xmlns:msntvuxp=""msntvuxp.microsoft.com"">
<div class=""PNGImage"" style=""width:176px;height:105px;src:/images/Home/HomeRotatorBGWeather.png;""></div>
</div>
<div style=""position:absolute; top:0px; left:0px; width:178px; height:107px;"" xmlns:msntvuxp=""msntvuxp.microsoft.com"">
<table class=""wthrTbl"" border=""0"" cellpadding=""1"" cellspacing=""0"">
<tr>
<td height=""4"" width=""4"" rowspan=""4""><img src=""images/Shared/s.gif"" height=""4"" width=""4""></td>
<td height=""4"" width=""45""><img src=""images/Shared/s.gif"" height=""4"" width=""45""></td>
<td height=""4"" width=""10""><img src=""images/Shared/s.gif"" height=""4"" width=""10""></td>
<td height=""4"" width=""65""><img src=""images/Shared/s.gif"" height=""4"" width=""65""></td>
</tr>
<tr>
<td id=""CityCellID"" class=""wthrCityCell"" colspan=""3"" valign=""top"">
<span class=""wthrCityText"">{@Weather.City}</span>
</td>
</tr>
<tr>
<td id=""TRCID"" class=""wthrTempCond"">
<table>
<tr>
<td id=""TemperatureCellID"" class=""wthrTempCell"">
<span class=""wthrTempTxt"">{@Weather.Temp}°F</span>
</td>
</tr>
<tr>
<td id=""ConditionCellID"" class=""wthrCondCell"">
<span class=""wthrCondTxt"">{Weather?.Description}</span>
</td>
</tr>
</table>
</td>
<td id=""PaddingID"" width=""10""><img src=""images/Shared/s.gif"" height=""1"" width=""10""></td>
<td id=""ConditionIconID"" class=""wthrCondIcon"">
<img src=""{@Weather?.Icon}"" alt=""Weather icon"" style=""width:65px;height:61px;"">
</td>
</tr>
<tr>
<td id=""ProviderID"" class=""wthrProvider"" colspan=""3"">
Open-Meteo
</td>
</tr>
</table>
</div>
<script xmlns:msntvuxp=""msntvuxp.microsoft.com"">
function clickPageRotatePanel() {{
location.href = ""/Pages/weather/yourcity"";
}}
</script>
</div>
</div>
<script>
InitRotator(timerRotatorDiv, 5000, new Array(""/home/MoneyModule.aspx"",""/Pages/weather/WeatherModule""));
</script>
<div ID=""clockID"" class=""clockDiv"">
</div>
<script>clockID.innerHTML = formClockLink();</script>
<div class=""newsHdlnDiv"">
<div class=""newsHdlnTitleDiv""><span class=""newsHdlnTitleText"">Today on TV2</span></div><table style=""top:0px;left:0px;width:365px;height:78px;""><tr><td><a class=""newsHdlnLink"" id=""newsHdlnLinkID1"" href=""{@NewsLink1}"">{NewsTitle1}</a></td></tr><tr><td><a class=""newsHdlnLink"" id=""newsHdlnLinkID2"" href=""{@NewsLink2}"">{NewsTitle2}</a></td></tr><tr><td><a class=""newsHdlnLink"" id=""newsHdlnLinkID3"" href=""{@NewsLink3}"">{NewsTitle3}</a></td></tr></table></td></tr></table><div class=""moreNewsDiv""><table><tr><td><img src=""msntv:/Shared/images/BulletCustom.gif"" height=""14"" width=""7""></td><td><img src=""images/Shared/s.gif"" height=""1"" width=""4""></td><td style=""height:37px""><a id=""moreNewsLinkID"" class=""moreNewsLink"" href=""../pages/TopStories"">More MSN news</a></td></tr></table></div>
</div>
<div class=""promoPanelDiv"">
<div style=""position:absolute; width:355px; height:70px;"">
<table style=""width:365px;""><td class=""promoHdlnTitle"" style=""color:#1D704C"">Using MSN TV</td><tr>
<td class=""promoHdlnCell""><a class=""promoHdlnLink"" id=""promoHdlnLinkID1"" href=""http://msntv.msn.com/pages/usingmsntv/tippage.aspx?id=set15"">Tip: Turn on audible dialing </a></td></tr><tr>
<td class=""promoHdlnCell""><a class=""promoHdlnLink"" id=""promoHdlnLinkID2"" href=""http://msntv.msn.com/pages/UsingMSNTV/Article.aspx?id=feature3"">Get better printing results</a></td></tr>
</table>
</div>
<div style=""position:absolute; left:161px; top:74px; width:200px;"">
<table class=""MoreUsingLinkTable""><tr><td><img src=""msntv:/Shared/Images/BulletCustom.gif"" height=""14"" width=""7""></td><td><img src=""/Images/Shared/s.gif"" height=""1"" width=""4""></td><td>
<a id=""MoreUsingLinkID"" class=""MoreNewsLink"" href=""http://headwaiter.trusted.msntv.msn.com/Pages/UsingMSNTV/Main"">Go to Using MSN TV</a>
</td></tr>
</table>
</div>
</div>
</div>
<div id=""searchID"" class=""searchDiv"">
<div class=""searchCenterDiv"">
<script>
function doSearch(country){{
if (searchFormID.searchFieldID.value == """")
{{
window.location = window.external.SafeGetServiceURL('search::search'); + ""?FORM=WEBTV&cfg=MSTVXML&v=1&c=""+country+""&x=26&y=14"";
}}
else
{{
window.location = window.external.SafeGetServiceURL('search::search') + ""?FORM=WEBTV&cfg=MSTVXML&v=1&c=""+country+""&x=26&y=14&q="" + escape(searchFormID.searchFieldID.value);
}}
}}
</script>
<div style=""position:absolute; z-index:1; left:0; top:0px; width:100%; height:2px; background-color:#0c7faa;"">
<table style="" width:100%; height:2px;"">
<tr>
<td height=""2"">
</td>
</tr>
</table>
</div>
<table class=""searchTbl"">
<form id=""searchFormID"" action=""javascript:doSearch('US')"">
<tr>
<td width=""10"">
</td><td>
<a class=""searchLink"" href=""
javascript:doSearch('US');
"">Search</a><span class=""searchLabelText""> or type www</span>
</td><td></td><td><span class=""searchFieldText""><input id=""searchFieldID"" name=""searchFieldName"" class=""searchField"" type=""text"" size=""28""></span></td><td></td>
<td valign=""center""><msntv:custombutton id=""GoButtonID"" onClick=""doSearch('US');"" label=""Go"" /></td></tr></form></table><div style=""position:absolute; left:0; top:33px; width:100%; height:2px; background-color:#1c4373;""><table style="" width:100%; height:2px;""><tr><td height=""2""></td></tr></table></div>
</div>
</div>
<div id=""iconNavBarID"" class=""iconNavBar"">
<table class=""iconNavBarMasterTbl"">
<tr>
<td align=""center"" valign=""middle"">
<table class=""iconNavBarTbl"">
<tr>
<td class=""iconNavBarTblFrameCell"">
<table class=""ApolloIcons"" xmlns:msntv=""http://tv.msn.com"">
<tr height=""70"">
<td>
<msntv:loopingDIV id=""navbar"" hasInitialFocus=""true"" divWidthPX=""554"" onLoopingDivReady=""handleLoopingDivReady()"" />
</td>
</tr>
<script>
var nIcons;
var ImgURL = new Array();
var ImgWidth = new Array();
var ImgOverURL = new Array();
var URL = new Array();
function goToFavorites() {{
window.open("" "", ""favoritespanel"", ""msntv:panel"");
}}
function goToMessenger() {{
if (window.external.SafeGetServiceURL('messenger::root') != null && window.external.SafeGetServiceURL('messenger::root') != """") window.open("" "", ""impanel"", ""msntv:panel"");
else
window.location = ""msntv:/OLTK/IMBlock.html"";
}}
function goToMail() {{
if (window.external.SafeGetServiceURL('mail::listmail') != null && window.external.SafeGetServiceURL('mail::listmail') != """") window.location = window.external.SafeGetServiceURL('mail::listmail');
else
window.location = ""msntv:/OLTK/EmailBlock.html"";
}}
function goToChat() {{
if (window.external.SafeGetServiceURL('chat::home') != null && window.external.SafeGetServiceURL('chat::home') != """") window.location = window.external.SafeGetServiceURL('chat::home');
else
window.location = ""msntv:/OLTK/chatBlock.html"";
}}
function goToSearch() {{
window.location = window.external.SafeGetServiceURL('search::main');
}}
function goToMaps() {{
window.location = window.external.SafeGetServiceURL('maps::main');
}}
function goToMusicHome() {{
window.location = window.external.SafeGetServiceURL('Music::Home');
}}
function goToVideoHome() {{
window.location = window.external.SafeGetServiceURL('Video::Home');
}}
function goToNetwork() {{
window.location = window.external.SafeGetServiceURL('Settings::HomeNetwork');
}}
function goToAccount() {{
window.location = window.external.SafeGetServiceURL('UAM::UAMbase');
}}
function goToSettings() {{
window.location = window.external.SafeGetServiceURL('settings::mainindex');
}}
function goToCenter(URL) {{
window.location = URL;
}}
function goToPhotosApp() {{
window.location = window.external.SafeGetServiceURL('Photos');
}}
function goToPhotosHome() {{
window.location = window.external.SafeGetServiceURL('Photo::Home');
}}
function initIcons() {{
for (index = 0; index < nIcons; index++) {{
var realIndex = (index + nIcons - 1) % nIcons;
var cellHTML = ""<span"" + "" onFocus=\""ImgObjs"" + realIndex + "".src='"" + ImgOverURL[realIndex] + ""'\"""" + "" onBlur=\""ImgObjs"" + realIndex + "".src='"" + ImgURL[realIndex] + ""'\"""";
cellHTML += "" onClick=\"""" + URL[realIndex] + ""\"""";
cellHTML += "">"" + ""<img"" + "" id='ImgObjs"" + realIndex + ""'"" + "" src='"" + ImgURL[realIndex] + ""' width="" + ImgWidth[realIndex] + "" height=61 border=0>"" + ""</span>"";
navbar.AddCellHTML(cellHTML, ImgWidth[realIndex]);
}}
}}
ImgURL[0] = ""/Images/Home/HomeIconFav.jpg"";
ImgOverURL[0] = ""/Images/Home/HomeIconFavOver.jpg"";
ImgWidth[0] = 87;
URL[0] = ""javascript:goToFavorites();"";
ImgURL[1] = ""/Images/Home/HomeIconMail.jpg"";
ImgOverURL[1] = ""/Images/Home/HomeIconMailOver.jpg"";
ImgWidth[1] = 70;
URL[1] = ""javascript:goToMail();"";
ImgURL[2] = ""/Images/Home/HomeIconMsgr.jpg"";
ImgOverURL[2] = ""/Images/Home/HomeIconMsgrOver.jpg"";
ImgWidth[2] = 99;
URL[2] = ""javascript:goToMessenger();"";
ImgURL[3] = ""/Images/Home/HomeIconMaps.jpg"";
ImgOverURL[3] = ""/Images/Home/HomeIconMapsOver.jpg"";
ImgWidth[3] = 60;
URL[3] = ""javascript:goToMaps();"";
ImgURL[4] = ""/Images/Home/HomeIconPhoto.jpg"";
ImgOverURL[4] = ""/Images/Home/HomeIconPhotoOver.jpg"";
ImgWidth[4] = 70;
URL[4] = ""javascript:goToPhotosApp();"";
ImgURL[5] = ""/Images/Home/HomeIconVideos.jpg"";
ImgOverURL[5] = ""/Images/Home/HomeIconVideosOver.jpg"";
ImgWidth[5] = 70;
URL[5] = ""javascript:goToVideoHome();"";
ImgURL[6] = ""/Images/Home/HomeIconMusic.jpg"";
ImgOverURL[6] = ""/Images/Home/HomeIconMusicOver.jpg"";
ImgWidth[6] = 66;
URL[6] = ""javascript:goToMusicHome();"";
ImgURL[7] = ""/Images/Home/HomeIconDiscuss.jpg"";
ImgOverURL[7] = ""/Images/Home/HomeIconDiscussOver.jpg"";
ImgWidth[7] = 72;
URL[7] = ""javascript:goToCenter('/Pages/Discuss/Home.aspx');"";
ImgURL[8] = ""/Images/Home/HomeIconMSNBC.jpg"";
ImgOverURL[8] = ""/Images/Home/HomeIconMSNBCOver.jpg"";
ImgWidth[8] = 68;
URL[8] = ""javascript:goToCenter('/Pages/News/TopStories.aspx');"";
ImgURL[9] = ""/Images/Home/HomeIconTWC.jpg"";
ImgOverURL[9] = ""/Images/Home/HomeIconTWCOver.jpg"";
ImgWidth[9] = 81;
URL[9] = ""javascript:goToCenter('/Pages/Weather/MyCity.aspx');"";
ImgURL[10] = ""/Images/Home/HomeIconEnt.jpg"";
ImgOverURL[10] = ""/Images/Home/HomeIconEntOver.jpg"";
ImgWidth[10] = 125;
URL[10] = ""javascript:goToCenter('/Pages/Entertainment/Home.aspx');"";
ImgURL[11] = ""/Images/Home/HomeIconTVListings.jpg"";
ImgOverURL[11] = ""/Images/Home/HomeIconTVListingsOver.jpg"";
ImgWidth[11] = 96;
URL[11] = ""javascript:goToCenter('http://tv.msn.com/tv/guide');"";
ImgURL[12] = ""/Images/Home/HomeIconSports.jpg"";
ImgOverURL[12] = ""/Images/Home/HomeIconSportsOver.jpg"";
ImgWidth[12] = 82;
URL[12] = ""javascript:goToCenter('/Pages/Sports/Main.aspx');"";
ImgURL[13] = ""/Images/Home/HomeIconMoney.jpg"";
ImgOverURL[13] = ""/Images/Home/HomeIconMoneyOver.jpg"";
ImgWidth[13] = 68;
URL[13] = ""javascript:goToCenter('/Pages/Money/Home.aspx');"";
ImgURL[14] = ""/Images/Home/HomeIconShopping.jpg"";
ImgOverURL[14] = ""/Images/Home/HomeIconShoppingOver.jpg"";
ImgWidth[14] = 62;
URL[14] = ""javascript:goToCenter('/Pages/Shopping/Main.aspx');"";
ImgURL[15] = ""/Images/Home/HomeIconGames.jpg"";
ImgOverURL[15] = ""/Images/Home/HomeIconGamesOver.jpg"";
ImgWidth[15] = 70;
URL[15] = ""javascript:goToCenter('/Pages/Games/Home.aspx');"";
ImgURL[16] = ""/Images/Home/HomeIconEncarta.jpg"";
ImgOverURL[16] = ""/Images/Home/HomeIconEncartaOver.jpg"";
ImgWidth[16] = 74;
URL[16] = ""javascript:goToCenter('http://g.msn.com/5TVANDURIL/1505')"";
ImgURL[17] = ""/Images/Home/HomeIconChat.jpg"";
ImgOverURL[17] = ""/Images/Home/HomeIconChatOver.jpg"";
ImgWidth[17] = 55;
URL[17] = ""javascript:goToChat();"";
ImgURL[18] = ""/Images/Home/HomeIconUsingMSN.jpg"";
ImgOverURL[18] = ""/Images/Home/HomeIconUsingMSNOver.jpg"";
ImgWidth[18] = 127;
URL[18] = ""javascript:goToCenter('/Pages/UsingMSNTV/Main');"";
ImgURL[19] = ""/Images/Home/HomeIconTTT.jpg"";
ImgOverURL[19] = ""/Images/Home/HomeIconTTTOver.jpg"";
ImgWidth[19] = 116;
URL[19] = ""javascript:goToCenter('/Pages/UsingMSNTV/ThingstoTry');"";
ImgURL[20] = ""/Images/Home/HomeIconSearch.jpg"";
ImgOverURL[20] = ""/Images/Home/HomeIconSearchOver.jpg"";
ImgWidth[20] = 84;
URL[20] = ""javascript:goToSearch();"";
ImgObjs = new Array();
ImgOverObjs = new Array();
nIcons = ImgURL.length;
ImgOverObjs[0] = new Image();
ImgOverObjs[0].src = ImgOverURL[0];
for (var i = 0; i < nIcons; i++) {{
ImgObjs[i] = new Image();
ImgObjs[i].src = ImgURL[i];
}}
for (var i = 1; i < nIcons; i++) {{
ImgOverObjs[i] = new Image();
ImgOverObjs[i].src = ImgOverURL[i];
}}
initIcons();
</script>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</div>
<script>
function callCGif()
{{
var i = new Image();
i.src = ""http://c.msn.com/c.gif?DI=1455&PI=68206&PS=45577&TP=http://msntv.msn.com/HomePage.htm&RF="";
}}
window.attachEvent(""onload"", callCGif);
</script>
</div>
</body></html>
");
@((MarkupString)htmlContent)
}
else
{
<PageTitle>Home</PageTitle>
<h1>Hello, world!</h1>
<footer>
<div style="position:fixed; left: 0px; bottom: 20px; width: 100vw;">
<TV2PCHomeNavBar />
</div>
<div style="position:fixed; left: 0px; bottom: 0; width: 100vw; height: 40px;">
<table cellpadding="0" cellspacing="0" width="100%" height="100%">
<tr>
<td width="560">
<img src="/Images/TV2PC/StatusBarBG.jpg" style="width: 100vw; height: 40px; object-fit: fill;"/>
<img src="/Images/TV2PC/Logo_MSNTVStatusBar.png" alt="Overlay Logo" class="overlay-logo" style="position: absolute; right: 0.1vw; bottom: 5px; max-width: 150%; z-index: 1001;" />
</td>
</tr>
</table>
</div>
</footer>
}
@code {
string userAgent { get; set; }
bool IsTV2 = false;
// News
string NewsLink1 = "http://sg1.trusted.msntv.msn.com/Pages/Tricks/he.mp3";
string NewsLink2 = "http://sg1.trusted.msntv.msn.com/Pages/Tricks/pokemon-black-2.mp3";
string NewsLink3 = "http://sg1.trusted.msntv.msn.com/Pages/Tricks/he.mp3";
string NewsTitle1 = "Ryder Smells";
string NewsTitle2 = "Ryder Smells";
string NewsTitle3 = "Ryder Smells";
// Weather mock
WeatherData Weather = new WeatherData
{
City = "San Jose",
Temp = "72",
Description = "Sunny",
Icon = "/Pages/Home/Weather/26.gif"
};
// Date data
DateData date = new DateData();
protected override void OnInitialized()
{
var request = httpContextAccessor.HttpContext?.Request;
IsTV2 = request != null && SecurityHandler.IsMsnTvClient(request) && SecurityHandler.IsTrustedDomain(request);
}
class WeatherData
{
public string City { get; set; }
public string Temp { get; set; }
public string Description { get; set; }
public string Icon { get; set; }
}
class DateData
{
public string date { get; }
public DateData()
{
date = DateTime.Now.ToString("dddd, MMMM d");
}
}
}

View File

@@ -1,164 +0,0 @@
@page "/Pages/Home/MoneyModule.aspx"
@using MSNTV2MainServer.Components.Layout
@using Microsoft.AspNetCore.Http
@using Microsoft.AspNetCore.Components;
@inject IHttpContextAccessor httpContextAccessor
<!-- Nulled layout as it is defined manually-->
@layout EmptyLayout
@if (IsTV2)
{
MarkupString htmlContent = new MarkupString($@"
<html>
<head>
<script>
var forceReload = false;
var l = 'd:' + new Date().valueOf() + '|';
function setCookie(name, value) {{
var now = new Date();
var expires = new Date(now.getFullYear() + 1, now.getMonth(), now.getDate());
document.cookie = escape(name) + '=' + escape(value) + ';expires=' + expires.toGMTString() + ';path=/';
}}
function getCookie(name) {{
var str = document.cookie;
var arr = str.split('; ');
for (var i = arr.length - 1; i >= 0; i--) {{
var c = arr[i].split('=');
if (c.length != 2) continue;
if (unescape(c[0]) == name) return unescape(c[1]);
}}
return null;
}}
function syncCookie(cookieName, propValue) {{
var c = getCookie(cookieName);
l += 'g:' + cookieName + ':' + c + '|';
if (c != propValue) {{
setCookie(cookieName, propValue);
l += 's:' + cookieName + ':' + propValue + '|';
var check = getCookie(cookieName);
if (check == propValue) forceReload = true;
}}
}}
var d = new Date();
var utcOffset = d.getTimezoneOffset();
syncCookie('UserUtcOffset', utcOffset);
var connSpeed;
try {{
connSpeed = window.external.ClientCaps.connectionType;
}} catch (e) {{
connSpeed = ""undetected"";
}}
syncCookie('UserConnectionSpeed', connSpeed);
try {{
top.log(l);
}} catch (e) {{}}
if (forceReload) location.replace(location.href);
</script>
</head>
<body>
<div style=""top:0px; left:0px; width:176px; height:105px;"">
<div class=""PNGImage"" style=""width:176px;height:105px;src:/Images/Home/HomeRotatorBGStock.png;""></div>
</div>
<table cellpadding=""0"" cellspacing=""0"" class=""stocksTbl"">
<tbody>
<tr height=""8"">
<td width=""7""></td>
<td width=""75""></td>
<td width=""5""></td>
<td width=""14""></td>
<td width=""7""></td>
<td width=""65""></td>
<td width=""5""></td>
</tr>
<tr>
<td></td>
<td class=""stocksCell"" style=""font-weight:bold; overflow:hidden; text-overflow:ellipsis"">Dow</td>
<td></td>
<td>
<div class=""PNGImage"" style=""src:/Images/Home/HomeStocksUpArrow.png; width:14px; height:24px""></div>
</td>
<td></td>
<td class=""stocksCell"" style=""text-align: right;"">+54.11</td>
<td></td>
</tr>
<tr>
<td class=""stocksRule"" colspan=""7""></td>
</tr>
<tr>
<td></td>
<td class=""stocksCell"" style=""font-weight:bold; overflow:hidden; text-overflow:ellipsis"">Nasdaq</td>
<td></td>
<td>
<div class=""PNGImage"" style=""src:/Images/Home/HomeStocksUpArrow.png; width:14px; height:24px""></div>
</td>
<td></td>
<td class=""stocksCell"" style=""text-align: right;"">+6.31</td>
<td></td>
</tr>
<tr>
<td class=""stocksRule"" colspan=""7""></td>
</tr>
<tr>
<td></td>
<td class=""stocksCell"" style=""font-weight:bold; overflow:hidden; text-overflow:ellipsis"">S&amp;P</td>
<td></td>
<td>
<div class=""PNGImage"" style=""src:/Images/Home/HomeStocksUpArrow.png; width:14px; height:24px""></div>
</td>
<td></td>
<td class=""stocksCell"" style=""text-align: right;"">+3.19</td>
<td></td>
</tr>
<tr>
<td class=""stocksRule"" colspan=""7""></td>
</tr>
<tr>
<td id=""ProviderID"" class=""wthrProvider"" colspan=""6"">Source: MSN Money</td>
</tr>
</tbody>
</table>
<!--<ROTATOR_FEEDBACK></ROTATOR_FEEDBACK>--><!--<ROTATOR_CLICKTHROUGH>/Pages/Money/MyStocks.aspx</ROTATOR_CLICKTHROUGH>-->
<script>
function clickPageRotatePanel() {{
location.href = ""/Pages/Money/MyStocks.aspx"";
}}
</script>
</body>
</html>
");
@((MarkupString)htmlContent)
}
else
{
<PageTitle>Home</PageTitle>
}
@code
{
string userAgent { get; set; }
bool IsTV2 = false;
protected override void OnInitialized()
{
userAgent = httpContextAccessor.HttpContext.Request.Headers["User-Agent"];
//Check if the client is an MSNTV2 box. If it is, we should return the TV2 page and not the Blazor based Page.
if(userAgent.Contains("MSNTV"))
{
IsTV2 = true;
StateHasChanged();
}
}
}

View File

@@ -1,166 +0,0 @@
@page "/Pages/Home/WeatherModule.aspx"
@using MSNTV2MainServer.Components.Layout
@using Microsoft.AspNetCore.Http
@using Microsoft.AspNetCore.Components;
@inject IHttpContextAccessor httpContextAccessor
<!-- Nulled layout as it is defined manually-->
@layout EmptyLayout
@if (IsTV2)
{
MarkupString htmlContent = new MarkupString($@"
<html>
<head>
<script>
var forceReload = false;
var l = 'd:' + new Date().valueOf() + '|';
function setCookie(name, value) {{
var now = new Date();
var expires = new Date(now.getFullYear() + 1, now.getMonth(), now.getDate());
document.cookie = escape(name) + '=' + escape(value) + ';expires=' + expires.toGMTString() + ';path=/';
}}
function getCookie(name) {{
var str = document.cookie;
var arr = str.split('; ');
for (var i = arr.length - 1; i >= 0; i--) {{
var c = arr[i].split('=');
if (c.length != 2) continue;
if (unescape(c[0]) == name) return unescape(c[1]);
}}
return null;
}}
function syncCookie(cookieName, propValue) {{
var c = getCookie(cookieName);
l += 'g:' + cookieName + ':' + c + '|';
if (c != propValue) {{
setCookie(cookieName, propValue);
l += 's:' + cookieName + ':' + propValue + '|';
var check = getCookie(cookieName);
if (check == propValue) forceReload = true;
}}
}}
var d = new Date();
var utcOffset = d.getTimezoneOffset();
syncCookie('UserUtcOffset', utcOffset);
var connSpeed;
try {{
connSpeed = window.external.ClientCaps.connectionType;
}} catch (e) {{
connSpeed = ""undetected"";
}}
syncCookie('UserConnectionSpeed', connSpeed);
try {{
top.log(l);
}} catch (e) {{}}
if (forceReload) location.replace(location.href);
</script>
</head>
<body>
<div style=""top:0px; left:0px; width:176px; height:105px;"" xmlns:msntvuxp=""msntvuxp.microsoft.com"">
<div class=""PNGImage"" style=""width:176px;height:105px;src:/Images/Home/HomeRotatorBGWeather.png;""></div>
</div>
<div style=""position:absolute; top:0px; left:0px; width:178px; height:107px;"" xmlns:msntvuxp=""msntvuxp.microsoft.com"">
<table class=""wthrTbl"" border=""0"" cellpadding=""1"" cellspacing=""0"">
<tbody>
<tr>
<td height=""4"" width=""4"" rowspan=""4""><img src=""/Images/Shared/s.gif"" height=""4"" width=""4""></td>
<td height=""4"" width=""45""><img src=""/Images/Shared/s.gif"" height=""4"" width=""45""></td>
<td height=""4"" width=""10""><img src=""/Images/Shared/s.gif"" height=""4"" width=""10""></td>
<td height=""4"" width=""65""><img src=""/Images/Shared/s.gif"" height=""4"" width=""65""></td>
<td height=""4"" width=""10"" rowspan=""4""><img src=""/Images/Shared/s.gif"" height=""4"" width=""10""></td>
</tr>
<tr>
<td id=""CityCellID"" class=""wthrCityCell"" colspan=""3"" valign=""top""><span class=""wthrCityText"">Your City</span></td>
</tr>
<tr>
<td id=""TRCID"" class=""wthrTempCond"">
<table>
<tbody>
<tr>
<td id=""TemperatureCellID"" class=""wthrTempCell""><span class=""wthrTempTxt"">63°/50</span></td>
</tr>
<tr>
<td id=""ConditionCellID"" class=""wthrCondCell""><span class=""wthrCondTxt"">Mostly</span><br><span class=""wthrCondTxt""> Cloudy</span></td>
</tr>
</tbody>
</table>
</td>
<td id=""PaddingID"" width=""10""><img src=""/Images/Shared/s.gif"" height=""1"" width=""10""></td>
<td id=""ConditionIconID"" class=""wthrCondIcon""><span class=""PNGImage"" style=""src:/Images/Shared/Weather/28.png;width:65px;height:61px;""></span></td>
</tr>
<tr>
<td id=""ProviderID"" class=""wthrProvider"" colspan=""3"">The Weather Channel ®</td>
</tr>
</tbody>
</table>
</div>
<!--<ROTATOR_FEEDBACK></ROTATOR_FEEDBACK>--><!--<ROTATOR_CLICKTHROUGH>/Pages/Weather/YourCity.aspx</ROTATOR_CLICKTHROUGH>-->
<script xmlns:msntvuxp=""msntvuxp.microsoft.com"">
function clickPageRotatePanel() {{
location.href = ""/Pages/Weather/YourCity.aspx"";
}}
</script>
</body>
</html>
");
@((MarkupString)htmlContent)
}
else
{
<PageTitle>Home</PageTitle>
<h1>Hello, world!</h1>
<footer>
<div style="position:fixed; left: 0px; bottom: 20px; width: 100vw;">
<TV2PCHomeNavBar />
</div>
<div style="position:fixed; left: 0px; bottom: 0; width: 100vw; height: 40px;">
<table cellpadding="0" cellspacing="0" width="100%" height="100%">
<tr>
<td width="560">
<img src="/Images/TV2PC/StatusBarBG.jpg" style=" width: 100vw; height: 40px; object-fit: fill;"/>
<img src="/Images/TV2PC/Logo_MSNTVStatusBar.png" alt="Overlay Logo" class="overlay-logo" style="position: absolute; right: 0.1vw; bottom: 5px; max-width: 150%; z-index: 1001;" />
</td>
</tr>
</table>
</div>
</footer>
}
@code
{
string userAgent { get; set; }
bool IsTV2 = false;
string NewsLink1 = "https://google.com";
string NewsLink2 = "https://yahoo.com";
string NewsLink3 = "https://bing.com";
string NewsTitle1 = "Google reigns superior over the universe";
string NewsTitle2 = "Who even uses Yahoo anymore?";
string NewsTitle3 = "Oh god, it's Bing! (Now with extra piss)";
protected override void OnInitialized()
{
userAgent = httpContextAccessor.HttpContext.Request.Headers["User-Agent"];
//Check if the client is an MSNTV2 box. If it is, we should return the TV2 page and not the Blazor based Page.
@if(userAgent.Contains("MSNTV"))
{
IsTV2 = true;
StateHasChanged();
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 300 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 300 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 292 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 292 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 B

View File

@@ -0,0 +1,502 @@
const minisrv_service_file = true;
const wtv_news_service_name = minisrv_config.services[service_name].usenet_service;
const wtvnews = new WTVNews(minisrv_config, wtv_news_service_name);
const service_config = minisrv_config.services[wtv_news_service_name];
if (service_config.local_nntp_port && wtvnewsserver) {
const tls_options = {
ca: this.wtvshared.getServiceDep('wtv-news/localserver_ca.pem'),
key: this.wtvshared.getServiceDep('wtv-news/localserver_key.pem'),
cert: this.wtvshared.getServiceDep('wtv-news/localserver_cert.pem'),
checkServerIdentity: () => { return null; }
}
if (wtvnewsserver.username)
wtvnews.initializeUsenet("127.0.0.1", service_config.local_nntp_port, tls_options, wtvnewsserver.username, wtvnewsserver.password);
else
wtvnews.initializeUsenet("127.0.0.1", service_config.local_nntp_port, tls_options);
} else {
if (service_config.upstream_auth)
wtvnews.initializeUsenet(service_config.upstream_address, service_config.upstream_port, service_config.upstream_tls || null, service_config.upstream_auth.username || null, service_config.upstream_auth.password || null);
else
wtvnews.initializeUsenet(service_config.upstream_address, service_config.upstream_port, service_config.upstream_tls || null);
}
async function throwError(e) {
console.log(e);
const errpage = wtvshared.doErrorPage(400 + " " + e.toString(), null, e.toString());
sendToClient(socket, errpage[0], errpage[1]);
}
function isToday (chkdate) {
const today = new Date()
return chkdate.getDate() === today.getDate() &&
chkdate.getMonth() === today.getMonth() &&
chkdate.getFullYear() === today.getFullYear()
}
async function WebTVListGroup(group) {
const page_limit_default = 100;
wtvnews.connectUsenet().then(() => {
wtvnews.selectGroup(group).then((response) => {
let limit_per_page = (request_headers.query.limit) ? parseInt(request_headers.query.limit) : page_limit_default;
const page = (request_headers.query.chunk) ? parseInt(request_headers.query.chunk) : 0;
let page_start = (limit_per_page * page) + 1;
let page_end = (page + 1) * limit_per_page;
if (page_end > response.group.high) {
page_end = response.group.high;
limit_per_page = (page_end - (limit_per_page / (page + 1))) + limit_per_page;
}
wtvnews.listGroup(group, page, limit_per_page).then((response) => {
if (response.code === 211) {
let NGCount = response.group.number;
const NGArticles = response.group.articleNumbers;
page_start = (limit_per_page * page) + 1;
page_end = (page + 1) * limit_per_page;
wtvnews.getHeaderObj(NGArticles).then((messages) => {
NGCount = NGArticles.length;
messages = wtvnews.sortByResponse(messages);
wtvnews.quitUsenet();
headers = `200 OK
Connection: Keep-Alive
Content-Type: text/html
wtv-expire: News.aspx?group=${request_headers.query.group}`
data = `<HTML>
<HEAD>
<script language=javascript>
if (top.frames.length > 1)
top.location="news:${request_headers.query.group}";
</script>
<TITLE>${request_headers.query.group}</TITLE>
</HEAD>
<body bgcolor="191919" text="42BD52" link="1bb0f1" vlink="826f7e">
<table cellspacing=0 cellpadding=0>
<td height=31 valign=top>
<font size="+1" color="E7CE4A">
<blackface>
<shadow>
Group: ${request_headers.query.group}
</shadow>
</blackface>
</font>
</table>
<font size=4>
`
if (NGCount === 0 || isNaN(NGCount)) {
data += `This group has no postings`;
} else {
data += NGCount + " posting";
if (NGCount !== 1)
data += "s"
}
data += `
</font>
<br>
<img src="wtv-home:/ROMCache/Spacer.gif" width=0 height=8>
`;
if (NGCount > 0) {
data += `
<td width=180 valign=bottom align=right>
<table cellspacing=0 cellpadding=0>
<td rowspan=4 height=26 width=30>
${(page > 0) ? `<a href="News.aspx?group=${group}&chunk=${page - 1}${(limit_per_page !== page_limit_default) ? `&limit=${limit_per_page}` : ''}"><img src="ListPrevious.gif"></a>` : `<img src="ListPrevious_D.gif">`}
<td rowspan=4 height=26 width=11>
<img src="ListLeftEdge.gif">
<td height=2 valign=top align=left bgcolor="2b2b2b">
<td rowspan=4 height=26 width=11>
<img src="ListRightEdge.gif">
<td rowspan=4 height=26 width=30>
${(page_end < NGCount) ? `<a href="News.aspx?group=${group}&chunk=${page + 1}${(limit_per_page !== page_limit_default) ? `&limit=${limit_per_page}` : ''}"><img src="ListNext.gif"></a>` : `<img src="ListNext_D.gif">`}
<td rowspan=4 width=5>
<tr>
<td height=2 valign=top align=left>
<img src="wtv-home:/ROMCache/Spacer.gif" width=1 height=1>
<tr>
<td height=20 valign=middle align=center>
${page_start}-${page_end}
<tr>
<td height=2 valign=top align=left bgcolor="000000">
<img src="wtv-home:/ROMCache/Spacer.gif" width=1 height=1>
<tr>
<td colspan=5 height=3>
</table> `;
}
data += `</table>
<TABLE width=446 cellspacing=0 cellpadding=0>
<tr>
<td rowspan=4>
<tr>
<img src="wtv-home:/ROMCache/Spacer.gif" width=10 height=1>
<td height=2 width=436 bgcolor="2B2B2B">
<img src="wtv-home:/ROMCache/Spacer.gif" width=436 height=1>
<tr>
<td height=1>
<tr>
<td height=2 bgcolor="0D0D0D">
<img src="wtv-home:/ROMCache/Spacer.gif" width=1 height=1>
<tr>
<td height=6>
</TABLE>`
if (NGCount > 0) {
Object.keys(messages).forEach(function (k) {
const message = messages[k].article;
const has_relation = (messages[k].relation !== null) ? true : false;
const date_obj = new Date(Date.parse(message.headers.DATE));
const date = (isToday(date_obj)) ? strftime("%I:%M %p", date_obj) : strftime("%b %d '%y", date_obj)
data += `
<table cellspacing=0 cellpadding=0>
<tr>
<td abswidth=10>
<td abswidth=426 height=42 valign=bottom>
<table cellspacing=0 cellpadding=0 nocolor selected>
<tr>
${(has_relation) ? `<td abswidth=20 rowspan=2 valign=top><font size="+2">&#149;` : ''}
<td abswidth=426 maxlines=1>
<a href="News.aspx?group=${request_headers.query.group}&article=${message.articleNumber}" id="${message.messageId}">
<font color=1bb0f1>${(message.headers.SUBJECT) ? wtvshared.htmlEntitize(message.headers.SUBJECT) : "(No Subject)"}
</a>
<tr>
<td maxlines=1>
<font size="-1" color=544f53><b>
${(message.headers.FROM.indexOf(' ') > 0) ? message.headers.FROM.split(' ')[0] : message.headers.FROM}, ${date}
</table>
<td abswidth=10>
</table>`;
});
}
data += `
<img src="wtv-home:/ROMCache/Spacer.gif" width=1 height=6><br>
<TABLE width=446 cellspacing=0 cellpadding=0>
<tr>
<td rowspan=4 width=10 height=1>
<img src="wtv-home:/ROMCache/Spacer.gif" width=436 height=1>
<tr>
<td height=1>
<tr>
<td height=2 bgcolor="0D0D0D">
<img src="wtv-home:/ROMCache/Spacer.gif" width=1 height=1>
<tr>
<td height=6>
</TABLE>
<table cellspacing=0 cellpadding=0>
<tr>
<td width=10 height=1 valign=top align=left>
<img src="wtv-home:/ROMCache/Spacer.gif" width=10 height=1>
<td height=33 width=256 valign=bottom>
</BODY>
</HTML>`;
sendToClient(socket, headers, data);
}).catch((e) => {
// getHeaderObj err
throwError(e)
});;
}
}).catch((e) => {
// listGroup error
throwError("No such group");
});
}).catch((e) => {
// selectGroup error
throwError("No such group")
});
}).catch((e) => {
// connect error
throwError(e)
});
}
async function WebTVShowMessage(group, article) {
const theArticle = parseInt(article);
wtvnews.connectUsenet().then(() => {
wtvnews.selectGroup(group).then((response) => {
wtvnews.getArticle(theArticle).then((response) => {
wtvnews.quitUsenet();
headers = `200 OK
Content-type: text/html`;
let signature = null;
let message_colors = session_data.mailstore.defaultColors;
const display_signature = true; // todo make a toggle
const message = wtvnews.parseAttachments(response);
const message_body = message.text;
let attachments = null;
let signature_index = null;
wtvnews.debug(message);
if (message.attachments) attachments = message.attachments;
if (attachments) {
if (Object.keys(attachments).length > 0) {
Object.keys(attachments).forEach((k) => {
if (attachments[k].filename === "wtv_signature.html" && attachments[k].content_type.match(/text\/html/)) {
signature = attachments[k].data;
signature_index = k;
return false;
}
});
if (signature_index) attachments.splice(signature_index, 1);
}
}
if (message_body.indexOf("<body")) {
const default_colors = session_data.mailstore.defaultColors;
message_colors = session_data.mailstore.getSignatureColors(message_body);
if ((message_colors === default_colors) && signature) message_colors = null;
}
if (!message_colors && signature) message_colors = session_data.mailstore.getSignatureColors(signature);
if (signature) message_colors = session_data.mailstore.getSignatureColors(signature);
data = `<head>
<sendpanel
action="/Post.aspx?message_forward_id=1&mailbox_name=inbox"
message="Forward this post to someone else."
label="Forward">
<title>
${(response.article.headers.SUBJECT) ? wtvshared.htmlEntitize(response.article.headers.SUBJECT) : '(No subject)'}
</title>
</head>
<print blackandwhite>
<body bgcolor=${message_colors.bgcolor}
text=${message_colors.text}
link=${message_colors.link}
vlink=${message_colors.vlink}
vspace=0
hspace=0>
<table cellspacing=0 cellpadding=0>
<tr>
<td abswidth=10 rowspan=99>
<td height=16>
<td rowspan=99>&nbsp;&nbsp;
<td>
<td abswidth=20 rowspan=99>
<tr>
<td colspan=3 height=39 valign=top>
<font color="E7CE4A" size=+1><blackface><shadow>
Post
<tr>
<td valign=top>
Group:
<td>
${wtvshared.htmlEntitize(response.article.headers.NEWSGROUPS)}
<tr>
<td valign=top>
Date: <td>
${strftime("%a, %b %e, %Y, %I:%M%P", new Date(Date.parse(response.article.headers.DATE)))}
<tr>
<td valign=top>
From:
<td>`;
if (message.from_name !== message.from_addr) {
data += `<a href="client:showalert?sound=none&message=Would%20you%20like%20to%20add%20%3Cblackface%3E${wtvshared.htmlEntitize(message.from_name)}%3C%2Fblackface%3E%20to%20your%20address%20list%3F&buttonlabel2=No&buttonaction2=client:donothing&buttonlabel1=Yes&buttonaction1=wtv-mail:/addressbook%3Faction%3Deditfromheader%26noresponse%3Dtrue%26nickname%3D${wtvshared.escape(wtvshared.escape(message.from_name))}%26address%3D${wtvshared.escape(wtvshared.escape(message.from_addr))}%26new_address%3Dtrue">${wtvshared.htmlEntitize(message.from_addr)} </a>`;
} else {
data += `${wtvshared.htmlEntitize(response.article.headers.FROM)}`;
}
data += `<tr>
<td nowrap valign=top>
<td>
<tr>
<td valign=top>Subject:
<td>${(response.article.headers.SUBJECT) ? wtvshared.htmlEntitize(response.article.headers.SUBJECT) : '(No subject)'}
</table>
<br><br>
<table cellspacing=0 cellpadding=0>
<tr>
<td abswidth=10 rowspan=99>
<tr>
<td>
`;
let allow_html = false;
let body_data = '';
let attachment_data = '';
let signature_data = '';
if (message_body) {
if (message_body.indexOf("<html>") >= 0) {
allow_html = true;
}
body_data += (allow_html) ? wtvshared.sanitizeSignature(message_body) : wtvshared.htmlEntitize(message_body, true)
body_data += `<br><br>`;
}
if (signature) signature_data += wtvshared.sanitizeSignature(signature);
if (attachments) {
if (attachments[0]) {
if (attachments[0].filename === "message.html") {
body_data += wtvshared.sanitizeSignature(attachments[0].data);
delete attachments[0];
}
}
const supported_images = /image\/(jpe?g|png|gif|x-wtv-bitmap)/;
const supported_audio = /audio\/(mp[eg|2|3]|midi?|wav|x-wav|mod|x-mod)/;
attachments.forEach((v, k) => {
if (v.content_type) {
if (v.content_type.match(supported_images))
attachment_data += `<img border=2 src="attachment.aspx?group=${group}&article=${article}&attachment_id=${k}&wtv-title=Video%20Snapshot"><br><br>`;
else if (v.content_type.match(supported_audio))
attachment_data += `<table href="attachment.aspx?group=${group}&article=${article}&attachment_id=${k}" width=386 cellspacing=0 cellpadding=0>
<td align=left valign=middle><img src="FileSound.gif" align=absmiddle><font color="#189CD6">&nbsp;&nbsp;${(v.filename) ? (v.filename) : "Audio file"} (${v.content_type.split('/')[1]} attachment)</font>
<td align=right valign=middle>
</table><br><br>`;
else if (v.content_type.match("text/html"))
attachment_data += wtvshared.sanitizeSignature(v.data);
else
attachment_data += `<table width=386><td><td align=left valign=middle><font color="#565656"><i>A file ${(v.filename) ? `(${v.filename}) ` : ''}that WebTV cannot use, with type ${v.content_type} is attached to this message.</i></font>`
}
});
}
/*
if (message.url) {
data += `Included Page: <a href="${(message.url)}">${wtvshared.htmlEntitize(message.url_title).replace(/&apos;/gi, "'")}`;
}
*/
data += body_data;
data += signature_data + "<p>";
data += attachment_data;
data += "</table></body></html>";
sendToClient(socket, headers, data);
}).catch((e) => {
// no such article
const post_unavailable_file = this.wtvshared.getServiceDep('wtv-news/post-unavailable.html');
console.log(e);
if (fs.existsSync(post_unavailable_file)) {
headers = "200 OK\nContent-type: text/html";
data = fs.readFileSync(post_unavailable_file).toString('ascii').replace("${group}", group).replace("${minisrv_config.config.service_logo}", minisrv_config.config.service_logo).replace("${message_colors.bgcolor}",session_data.mailstore.defaultColors.bgcolor);
sendToClient(socket, headers, data);
} else {
throwError(e);
}
});
}).catch((e) => {
// no such group
throwError(e);
});
}).catch((e) => {
//no connection
throwError(e);
});
}
function WebTVSearchGroups(search) {
wtvnews.connectUsenet().then(() => {
wtvnews.listGroups(search).then((response) => {
wtvnews.quitUsenet();
headers = `200 OK
Content-type: text/html
wtv-expire-all: News.aspx?search=`;
data = `<HTML>
<HEAD>
<DISPLAY fontsize=medium>
<TITLE>${(response.length === 0) ? "No " : ""}Discussion groups found</TITLE>
</HEAD>
<body
bgcolor="191919" text="42BD52" link="189CD6"
vlink="189CD6"
hspace=0
vspace=0>
<table cellspacing=0 cellpadding=0>
<tr>
<td abswidth=10>
<td colspan=3>
<table cellspacing=0 cellpadding=0>
<tr>
<td valign=center absheight=80>
<font size="+2" color="E7CE4A"><blackface><shadow>
${(response.length === 0) ? "No " : ""}Discussion groups found
</table>
<td abswidth=20>
<tr>
<td>
<td WIDTH=198 HEIGHT=200 VALIGN=top ALIGN=left>`;
if (response.length === 0) {
data += `There are no discussion groups that match your request. Do you want to look for something else?`;
} else {
response.forEach((group) => {
data += `<hr width=436>
<IMG src="wtv-home:/ROMCache/Spacer.gif" width=1 height=6><br>
<table cellspacing=0 cellpadding=0>
<tr>
<td width=10>
<td width=426> <table selected cellspacing=0 cellpadding=0>
<tr>
<td abswidth=401 height=19 valign=top>
<a href="News.aspx?group=${group.name}"><shadow><b>${group.name}</b></shadow></a>
<td width=10>
`
if (group.description) {
data += `<tr><td colspan=3 width=10 height=6><tr><td width=10><td colspan=99><i><font color=828282>${group.description}</font></i>`
}
data += "</table>";
});
}
data += `
</table>
<TABLE width=446 cellspacing=0 cellpadding=0>
<tr>
<td rowspan=3 width=10 height=1>
<img src="wtv-home:/ROMCache/Spacer.gif" width=10 height=1>
<td height=2 width=436 bgcolor="2B2B2B">
<img src="wtv-home:/ROMCache/Spacer.gif" width=436 height=1>
<tr>
<td height=1>
<tr>
<td height=2 bgcolor="0D0D0D">
<img src="wtv-home:/ROMCache/Spacer.gif" width=1 height=1>
</TABLE>
<table cellspacing=0 cellpadding=0>
<tr>
<td rowspan=2 abswidth=10>
<td absheight=10>
<tr>
<td abswidth=416 valign=top align=left>
Do you want to look for something else?<br>
<img src="/ROMCache/Spacer.gif" width=1 height=4>
<form action="News.aspx">
<input name="search" bgcolor=#202020 cursor=#cc9933 text="E7CE4A" font=proportional value="${request_headers.query.search}" SIZE=28 MAXLENGTH=100>
&nbsp;
<font color=E7CE4A><shadow>
<input type=submit borderimage="file://ROM/Borders/ButtonBorder2.bif" value="Look for" usestyle>
</shadow></font>
</form>
</table>
</BODY>
</HTML>`;
sendToClient(socket, headers, data);
}).catch((e) => {
// listGroups error
throwError(e);
});
}).catch((e) => {
// no connection
throwError(e);
});
}
if (!wtvnews.client) {
const errpage = wtvshared.doErrorPage();
headers = errpage[0];
data = errpage[1];
} else {
request_is_async = true;
if (request_headers.query.search) {
WebTVSearchGroups(request_headers.query.search)
} else if (request_headers.query.group) {
if (request_headers.query.article) {
WebTVShowMessage(request_headers.query.group, request_headers.query.article);
} else {
WebTVListGroup(request_headers.query.group);
}
} else {
// redirect to lobby if no understandable queries passed
headers = "300 OK\nLocation: wtv-news:/lobby";
sendToClient(socket, headers, null);
}
}

View File

@@ -0,0 +1,72 @@
const minisrv_service_file = true;
// max of 6, any more will be ignored
headers = `200 OK
Connection: Keep-Alive
Content-Type: text/html`
data = `<HTML>
<HEAD>
<DISPLAY fontsize=medium>
<TITLE>Featured discussion groups</TITLE>
</HEAD>
<body
bgcolor="191919" text="42BD52" link="189CD6"
vlink="189CD6"
hspace=0
vspace=0>
<table cellspacing=0 cellpadding=0>
<tr>
<td abswidth=10>
<td colspan=3>
<table cellspacing=0 cellpadding=0>
<tr>
<td valign=center absheight=80>
<font size="+2" color="E7CE4A"><blackface><shadow>
Featured discussions
</table>
<td abswidth=20>
<tr>
<td>
<td WIDTH=198 HEIGHT=200 VALIGN=top ALIGN=left>`;
const featuredGroups = minisrv_config.services[minisrv_config.services[service_name].usenet_service].featuredGroups;
const limit = 6;
while (featuredGroups.length > limit) featuredGroups.pop(); // remove anything passing our limit
function printGroup(group) {
return `<a href="News.aspx?group=${group.group}"><b>${group.name}</b></a><br>${group.description}<BR>`;
}
// evens
Object.keys(featuredGroups).forEach((k) => { if (k % 2 === 0) { data += printGroup(featuredGroups[k]); } });
if (featuredGroups.length > 1) data += `<td WIDTH=20><td WIDTH=198 HEIGHT=220 VALIGN=top ALIGN=left>`;
// odds
Object.keys(featuredGroups).forEach((k) => { if (k % 2 !== 0) data += printGroup(featuredGroups[k]); });
data += `
</table>
<hr>
<table cellspacing=0 cellpadding=0>
<tr>
<td rowspan=2 abswidth=10>
<td absheight=10>
<tr>
<td abswidth=416 valign=top align=left>
Type a discussion topic<br>
<img src="/ROMCache/Spacer.gif" width=1 height=4>
<form action="News.aspx" method="GET">
<input name="search" bgcolor=#202020 cursor=#cc9933 text="E7CE4A" font=proportional value="" SIZE=28 MAXLENGTH=100>
&nbsp;
<font color=E7CE4A><shadow>
<input type=submit borderimage="file://ROM/Borders/ButtonBorder2.bif" value="Look for" usestyle>
</shadow></font>
</form>
</table>
</BODY>
</HTML>`;

View File

@@ -53,6 +53,8 @@ data = `<HTML xmlns:msntv>
</p> </p>
<p style="display: inline; left: 76px; position: relative;">Example:</p> <p style="display: inline; left: 76px; position: relative;">Example:</p>
<p style="display: inline; left: 110px; position: relative;">ABCEAZ82KDKA</p> <p style="display: inline; left: 110px; position: relative;">ABCEAZ82KDKA</p>
<p>&nbsp;</p>
<p>One day, certain promotion codes will unlock special features or content on minisrv. But for now, this is just a placeholder page.</p>
</DIV> </DIV>
<div id="footer"> <div id="footer">
<msntv:CustomButton id="continue" label="Continue" href="javascript:SubmitForm()" /> <msntv:CustomButton id="continue" label="Continue" href="javascript:SubmitForm()" />

View File

@@ -86,7 +86,7 @@ data = `<HTML xmlns:msntv>
<tr style="margin: 0; padding: 0; top: 2px; position: relative;"> <tr style="margin: 0; padding: 0; top: 2px; position: relative;">
<td style="margin: 0; padding: 0; vertical-align: middle; top: 2px; position: relative;"><img src="msntv:/Shared/Images/BulletCustom.gif" height="14" width="7" alt="Bullet"></td> <td style="margin: 0; padding: 0; vertical-align: middle; top: 2px; position: relative;"><img src="msntv:/Shared/Images/BulletCustom.gif" height="14" width="7" alt="Bullet"></td>
<td style="margin: 0; padding: 0; width: 4px;"></td> <td style="margin: 0; padding: 0; width: 4px;"></td>
<td style="margin: 0; padding: 0; font:bold 18; line-height: 20px;"><a class="shrLnk2" href="https://headwaiter.trusted.msntv.msn.com/connection/boxcheck.html" style="display: inline-block; line-height: 20px;">I want to start over</a></td> <td style="margin: 0; padding: 0; font:bold 18; line-height: 20px;"><a class="shrLnk2" href="msntv:/Registration/pages/Welcome.html" style="display: inline-block; line-height: 20px;">I want to start over</a></td>
</tr> </tr>
</table> </table>
</div> </div>

View File

@@ -4,7 +4,7 @@ headers = `Status: 200 OK
Content-type: text/html`; Content-type: text/html`;
data = `<HTML xmlns:msntv> data = `<HTML xmlns:msntv>
<?import namespace="msntv" implementation="HTC/Shared/CustomButton.htc"> <?import namespace="msntv" implementation="https://sg1.trusted.msntv.msn.com/Include/HTC/Shared/CustomButton.htc">
<HEAD> <HEAD>
<title id="title">Learning to use the keyboard</title> <title id="title">Learning to use the keyboard</title>
<meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5"> <meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5">
@@ -32,26 +32,24 @@ data = `<HTML xmlns:msntv>
<BODY width="520" height="388"> <BODY width="520" height="388">
<DIV id="title">Logging into your account</DIV> <DIV id="title">Logging into your account</DIV>
<DIV id="main"> <DIV id="main">
<p>When using MSNTV2, you can access the same minisrv account as your WebTV.</p> <p>When using MSNTV2, you can use an existing minisrv account.</p>
<br> <br>
<p>Type your existing primary username in the box below:</p> <p>Type your existing primary username in the box below:</p>
<div class="input-container"> <div class="input-container">
<textarea name="username" id="username" rows="1" cols="15"></textarea> <textarea name="username" id="username" rows="1" cols="15"></textarea>
<p style="display: inline;">@${minisrv_config.config.service_name}</p> <p style="display: inline;">@${minisrv_config.config.domain_name}</p>
</div> </div>
<br> <br>
<div class="input-container"> <div class="input-container">
<textarea name="password" id="password" rows="1" cols="15"></textarea> <textarea name="password" id="password" rows="1" cols="15"></textarea>
</div> </div>
<br> <br>
If you don't have an existing minisrv account, select the <EM>Back</EM> Button. If you do not have a password set on your primary user account, you will need to set one up on your WebTV before you can connect it to this MSNTV2.
If you do not have a password set on your primary user account, you will need to set one up on your WebTV before you can log in here. After entering your username and password, select the <EM>Continue</EM> Button. After entering your username and password, select the <EM>Continue</EM> Button.
</DIV> </DIV>
<div id="footer"> <div id="footer">
<msntv:CustomButton id="continue" label="Continue" href="/Register/ConnectionType.aspx"/> <msntv:CustomButton id="continue2" label="Back" href="/Register/Establish-your-MSN-TV-Account.html"/>
</div> <msntv:CustomButton id="continue" label="Continue" disabled="true" href="/Register/Validate-account.aspx"/>
<div id="Back">
<msntv:CustomButton id="continue2" label="Back" href="/Register/ConnectionType.aspx"/>
</div> </div>
</BODY> </BODY>
</HTML>`; </HTML>`;

View File

@@ -1,6 +1,9 @@
const minisrv_service_file = true; const minisrv_service_file = true;
// TODO: if the user hits back, and removes the password from the user/pass page, any previously entered password
// will still be in the cookie and they will skip the password page.
// We should probably clear the password cookie when they hit back from the password page, but how?
// We can't assume password = '' means they hit back, because some pages will not send it.
let email = request_headers.query.email || ''; let email = request_headers.query.email || '';
if (Array.isArray(email)) email = email[0]; if (Array.isArray(email)) email = email[0];
if (!email && request_headers.cookie) { if (!email && request_headers.cookie) {
@@ -31,14 +34,16 @@ data = "";
} }
} }
if (!password) { if (!password && !headers) {
headers = `Status: 302 Found headers = `Status: 302 Found
Location: https://sg1.trusted.msntv.msn.com/Register/Password-Required.aspx`; Location: https://sg1.trusted.msntv.msn.com/Register/Password-Required.aspx`;
data = ""; data = "";
deleteCookie('register_password', { path: '/' });
} else {
setCookie('register_password', password, { path: '/' });
} }
if (userAvail && password) { if (userAvail && password) {
if (password) setCookie('register_password', password, { path: '/' });
headers = `Status: 200 OK headers = `Status: 200 OK
Content-type: text/html`; Content-type: text/html`;
@@ -75,7 +80,7 @@ data = `<HTML xmlns:msntv>
<tr style="margin: 0; padding: 0; top: 2px; position: relative;"> <tr style="margin: 0; padding: 0; top: 2px; position: relative;">
<td style="margin: 0; padding: 0; vertical-align: middle; top: 2px; position: relative;"><img src="msntv:/Shared/Images/BulletCustom.gif" height="14" width="7" alt="Bullet"></td> <td style="margin: 0; padding: 0; vertical-align: middle; top: 2px; position: relative;"><img src="msntv:/Shared/Images/BulletCustom.gif" height="14" width="7" alt="Bullet"></td>
<td style="margin: 0; padding: 0; width: 4px;"></td> <td style="margin: 0; padding: 0; width: 4px;"></td>
<td style="margin: 0; padding: 0; font-size: 24px; font:bold 18; line-height: 20px;"><a class="shrLnk2" href="/Register/Enter-Promotion-Code.aspx" style="display: inline-block; line-height: 20px;">Yes, I have a Promotion Code.</a></td> <td style="margin: 0; padding: 0; font-size: 24px; font:bold 18; line-height: 20px;"><a class="shrLnk2" href="/Register/Enter-Promotion-Code.aspx" style="display: inline-block; line-height: 20px;">Yes, I have a Promotion Code.</a> (TODO)</td>
</tr> </tr>
</table> </table>
</div> </div>

View File

@@ -6,7 +6,7 @@ Content-type: text/html`;
data = `<HTML xmlns:msntv> data = `<HTML xmlns:msntv>
<?import namespace="msntv" implementation="/Include/HTC/Shared/CustomButton.htc"> <?import namespace="msntv" implementation="/Include/HTC/Shared/CustomButton.htc">
<HEAD> <HEAD>
<title id="title">Login to Passport</title> <title id="title">Username Not Available</title>
<meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5"> <meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5">
<link rel="stylesheet" type="text/css" href="msntv:/Registration/css/Registration.css"> <link rel="stylesheet" type="text/css" href="msntv:/Registration/css/Registration.css">
<STYLE> <STYLE>

View File

@@ -38,7 +38,7 @@ if (!session_data && BoxId) {
let registered = false; let registered = false;
let username = ''; let username = '';
let Profile_Picture let Profile_Picture = '';
if (session_data) { if (session_data) {
registered = session_data.isRegistered(); registered = session_data.isRegistered();
if (registered) { if (registered) {
@@ -285,21 +285,34 @@ switch (phase) {
} }
} }
var hasIDCRL = false;
try {
hasIDCRL = (typeof TVShell.LoginManager.IDCRLInitialize === "unknown" ||
typeof TVShell.LoginManager.IDCRLInitialize === "function");
} catch (e) {
hasIDCRL = false;
}
if (currentUser != null) { if (currentUser != null) {
// Check if We can do IDCRL if not fall back to Legacy XMLlogin // Check if We can do IDCRL if not fall back to Legacy XMLlogin
if (TVShell.LoginManager.IDCRLInitialize) { try {
DoIDCRLLogin(); if (hasIDCRL) {
} else { DoIDCRLLogin();
// Non IDCRL Auth Code (Pre 5.x) } else {
Sink.AttachEvent(TVShell.LoginManager, 'OnLoginResult', OnLoginResult); // Non IDCRL Auth Code (Pre 5.x)
TVShell.LoginManager.PassportSiteIDs = '507'; Sink.AttachEvent(TVShell.LoginManager, 'OnLoginResult', OnLoginResult);
TVShell.LoginManager.LoginURL = "https://login.live.com/ppsecure/clientpost.srf"; TVShell.LoginManager.PassportSiteIDs = '507';
TVShell.LoginManager.LogoutURL = "https://login.live.com/ppsecure/logoutxml.srf"; TVShell.LoginManager.LoginURL = "https://login.live.com/ppsecure/clientpost.srf";
TVShell.LoginManager.ResetPasswordURL = "https://login.live.com/ppsecure/MSRV_ResetPW_ClientPost.srf"; TVShell.LoginManager.LogoutURL = "https://login.live.com/ppsecure/logoutxml.srf";
TVShell.LoginManager.ChangePasswordURL = "https://login.live.com/ppsecure/MSRV_ChangePW_ClientPost.srf"; TVShell.LoginManager.ResetPasswordURL = "https://login.live.com/ppsecure/MSRV_ResetPW_ClientPost.srf";
TVShell.LoginManager.RequestProfileURL = "https://login.live.com/ppsecure/ClientProfileRequest.srf"; TVShell.LoginManager.ChangePasswordURL = "https://login.live.com/ppsecure/MSRV_ChangePW_ClientPost.srf";
TVShell.LoginManager.UpdateProfileURL = "https://login.live.com/ClientEditProf.srf"; TVShell.LoginManager.RequestProfileURL = "https://login.live.com/ppsecure/ClientProfileRequest.srf";
TVShell.LoginManager.Authenticate(email, "", "https://login.live.com/ppsecure/clientpost.srf"); TVShell.LoginManager.UpdateProfileURL = "https://login.live.com/ClientEditProf.srf";
TVShell.LoginManager.Authenticate(email, "", "https://login.live.com/ppsecure/clientpost.srf");
}
} catch (e) {
TVShell.EventLog.Important("Login error: " + e.message);
} }
} }
} }

View File

@@ -1,317 +0,0 @@
const minisrv_service_file = true;
let BoxId = request_headers.query.BoxId;
if (Array.isArray(BoxId)) BoxId = BoxId[0];
let clientIp = socket.remoteAddress;
let banned = false;
let sessionId = null;
// Use the shared MSNTV2 helper injected by WTV-MSNTV2 VM context.
if (BoxId) {
if (!BoxId || BoxId.length != 20 || !/^\d+$/.test(BoxId))
{
console.warn("Invalid BoxId format "+BoxId+" from "+clientIp);
banned = true;
} else {
sessionId = encodeSessionID(BoxId);
}
} else if (request_headers.cookie && request_headers.cookie.SessionID) {
BoxID = decodeSessionID(request_headers.cookie.SessionID);
sessionId = request_headers.cookie.SessionID;
} else {
console.warn("No BoxId provided by client "+clientIp);
banned = true;
}
if (!sessionId && !banned) {
banned = true;
}
if (!session_data && BoxId) {
console.log("Missing session_data for BoxId %s", BoxId);
}
let registered = false;
let username = '';
if (session_data) {
registered = session_data.isRegistered();
if (registered) {
username = session_data.getSessionData("subscriber_username") || '';
Profile_Picture = session_data.getSessionData('ProfilePicture') || '';
}
}
// Current UTC time
const now = new Date();
// Time data object
const timeData = {
hh: now.getUTCHours(),
mm: now.getUTCMinutes(),
ss: now.getUTCSeconds(),
mo: now.getUTCMonth() + 1, // JS months are 0-based
dd: now.getUTCDate(),
yyyy: now.getUTCFullYear()
};
// Timezone mapping (C# tuple → JS array or object)
const timezoneMap = {
"UTC": {
standardName: "UTC",
standardOffset: 0,
daylightName: "UTC",
daylightOffset: 0
}
};
// Destructure like the C# tuple deconstruction
const {
standardName,
standardOffset,
daylightName,
daylightOffset
} = timezoneMap["UTC"];
// Set session cookie on the client
if (sessionId) {
setCookie('SessionID', sessionId, { path: '/' });
}
headers = `200 OK
Content-type: text/html`
data = `<html>
<head>
<title id="title"></title>
</head>
<body>
<iframe id="checkmail" style="display:none"></iframe>
<script src="msntv:/Javascript/TVShell.js" language="javascript"></script>
<script src="msntv:/Javascript/ServiceList.js" language="javascript"></script>
<script src="msntv:/Javascript/GuestUser.js" language="javascript"></script>
<script language="javascript">
try {
var TVShell = new ActiveXObject("MSNTV.TVShell");
var sink = new ActiveXObject("MSNTV.MultipleEventSink");
function getIDCRLCode(value) {
return value & 0xFFFF;
}
function isIDCRLErrorCode(value) {
return (value >>> 16) != 0;
}
var email = TVShell.UserManager.EMail;
var wanProvider = TVShell.ConnectionManager.WANProvider;
var banned = ${banned};
var registered = ${registered};
var username = "${username}";
var picture = "${Profile_Picture}";
InitializeGuestMode();
RemoveGuestUsers();
if (!banned) {
// DEBUG ONLY! USE WITH CAUTION!
TVShell.AddSecretCode(10000); // Power-on for nightly update
TVShell.AddSecretCode(10001); // Power-on for nightly email check at anchor time
TVShell.AddSecretCode(10002); // Power-on for nightly email check at non-anchor time
TVShell.AddSecretCode(77437); // spooky dialing options
TVShell.AddSecretCode(93288); // Service Selection Page
TVShell.AddSecretCode(6145539); // crash the system
TVShell.AddSecretCode(3932397); // update loop test
}
function CheckForUser(usernameToCheck) {
var UserManager = TVShell.UserManager;
for (var i=0; i<UserManager.Count; i++) {
var user = UserManager.Item(i);
if (user == usernameToCheck) {
return true;
}
}
return false;
}
function DoLogin() {
var currentUser = TVShell.UserManager.CurrentUser;
if (currentUser == null) {
if (banned === true) {
var url = 'https://sg1.trusted.msntv.msn.com/connection/banned.html';
var myPanel = TVShell.PanelManager.Item('main');
if (myPanel) myPanel.GotoURL(url);
} else {
if (registered === true) {
if (!CheckForUser(username)) {
var user = TVShell.UserManager.AddNew(username);
if (user) {
user.IsPersistent = true;
user.setAttribute("GuestUser", false);
var dt = new Date();
TVShell.UserManager.LastLoginTime = dt.getTime() / 1000 + dt.getTimezoneOffset() * 60;
TVShell.UserManager.OfflineAppMaxAccessDays = 20;
TVShell.UserManager.OfflineAppMaxAccessTimes = 20;
TVShell.UserManager.CurrentUser = user;
user.LargeIcon = "msntv:/SignInPics/big/"+ picture + ".png";
user.SmallIcon = "msntv:/SignInPics/small/"+ picture + ".gif";
TVShell.UserManager.Save();
entry = TVShell.ServiceList.Add('connection::login');
entry.URL = 'https://headwaiter.trusted.msntv.msn.com/connection/GatePage.aspx?phase=Bootstrap&purpose=Authorize';
entry.Description = '${minisrv_config.config.service_name}/sg1 [${minisrv_config.config.hide_minisrv_version ? "beta" : minisrv_version_string.replace("zefie's wtv minisrv ","")}]';
TVShell.ServiceList.Save();
}
}
}
var myPanel = TVShell.PanelManager.Item('main')
if (registered === true) {
var signon = TVShell.BuiltinServiceList.Item("SignOn");
var panel = TVShell.PanelManager.FocusedPanel;
var atLogin = false;
TVShell.ConnectionManager.ServiceState = 'ReSignIn';
if ( signon && panel && panel.Name == "main" )
{
if ( IsMainPanelOnPage( signon.URL ) ) atLogin = true;
}
if (!atLogin) {
myPanel.ClearTravelLog();
myPanel.NoBackToMe = true;
GotoSignOn();
}
} else {
if (myPanel) myPanel.GotoURL('https://sg1.trusted.msntv.msn.com/Register/Establish-your-MSN-TV-Account.html');
}
if (myPanel) {
myPanel.ClearTravelLog();
myPanel.NoBackToMe = true;
}
}
} else {
if (banned === true) {
var url = 'https://sg1.trusted.msntv.msn.com/connection/banned.html';
var myPanel = TVShell.PanelManager.Item('service');
if (myPanel) myPanel.GotoURL(url);
}
}
if (currentUser != null) {
var serviceArgs = new Array();
var ProductionArgs = new Array("msntv.msn.com", "MBI", 0, 0,
"mail.services.live.com", "MBI", 0, 0,
"livefilestore.com", "MBI", 0, 0,
"messenger.msn.com", "?id=507", 0, 0,
"spaces.live.com", "MBI", 0, 0
);
serviceArgs[0] = ProductionArgs;
try {
TVShell.LoginManager.IDCRLInitialize(0);
TVShell.LoginManager.IDCRLLogonAndAuthToServices(serviceArgs[0]);
} catch (e) {
if (window.console) console.log("IDCRL error: " + e.message);
}
GoToUserCheck();
}
}
function DoPoptimization() {
if (wanProvider === "MSNIANB") {
var connector = GetConnectorByName("LocalPOP");
if (connector == null) {
connector = TVShell.ConnectionManager.MSNIAManager.Connectors.Add("modem");
connector.AreaCode = "";
connector.Exchange = "";
connector.DialingFlags = 0x00001000;
connector.Name = "LocalPOP";
connector.LocationName = "LocalPOP";
TVShell.ConnectionManager.Save();
connector.Poptimize("0", connector.AreaCode, connector.Exchange);
}
if (connector.Phonebook == null || connector.Phonebook.length === 0) {
if (connector.AreaCode && connector.Exchange) {
connector.Poptimize(connector.AreaCode, connector.Exchange);
}
}
}
}
function GetConnectorByName(name) {
var connectors = TVShell.ConnectionManager.MSNIAManager.Connectors;
for (var i = 0; i < connectors.length; i++) {
if (connectors[i].Name === name) {
return connectors[i];
}
}
return null;
}
function GoToUserCheck() {
if (banned === true) {
var url = 'https://sg1.trusted.msntv.msn.com/connection/banned.html';
var myPanel = TVShell.PanelManager.Item('service');
if (myPanel) myPanel.GotoURL(url);
} else if (registered) {
var url = 'https://sg1.trusted.msntv.msn.com/connection/usercheck.html';
var myPanel = tvShell.PanelManager.Item('service');
if (myPanel) myPanel.GotoURL(url);
}
}
function SetProgress(text, percent) {
if (progressPanel) {
progressPanel.Document.SetProgressText(text);
progressPanel.Document.SetProgressPercent(percent);
}
}
var progressPanel = TVShell.PanelManager.Item('progress');
function IsServicePanel() {
if ((window.name == null) || ((window.name != null) && (window.name.toLowerCase() != 'service'))) {
return false;
}
return true;
}
function DontContinue() {
var currentUser = TVShell.UserManager.CurrentUser;
if (currentUser != null && currentUser.IsAuthorized) {
window.location.replace(TVShell.UserManager.CurrentUser.ServiceList.Item('home::home').URL);
} else {
TVShell.ConnectionManager.ServiceState = 'ReSignIn';
}
}
if (!IsServicePanel()) {
DontContinue();
} else {
DoPoptimization();
DoLogin();
try {
TVShell.DeviceControl.SetTimeZone(${standardOffset}, "${standardName}", 0, "");
} catch (e) {
if (window.console) console.log("SetTimeZone error: " + e.message);
}
try {
TVShell.DeviceControl.SetClock(${timeData.hh}, ${timeData.mm}, ${timeData.ss}, ${timeData.mo}, ${timeData.dd}, ${timeData.yyyy});
TVShell.DeviceControl.ClockSet = true;
} catch (e) {
if (window.console) console.log("SetClock error: " + e.message);
}
}
} catch (e) {
if (window.console) console.log("Error in boxcheck: " + e.message);
var myPanel = TVShell ? TVShell.PanelManager.Item('main') : null;
if (myPanel) myPanel.GotoURL('https://sg1.trusted.msntv.msn.com/connection/error.html');
}
</script>
</body>
</html>`;

View File

@@ -1,193 +0,0 @@
const minisrv_service_file = true;
headers = `Content-type: text/html`;
data = `<html>
<head>
<title id="title"></title>
</head>
<body>
<iframe id="checkmail" style="display:none"></iframe>
<script language="javascript">
var tvShell = new ActiveXObject("MSNTV.TVShell");
var wanProvider = tvShell.ConnectionManager.WANProvider;
function SetServiceList() {
var entry;
// BuiltinServiceList - for main MSN TV services
tvShell.UserManager.CurrentUser.ServiceList.Clear(); //Always clear the list first to avoid dupes.
entry = tvShell.UserManager.CurrentUser.ServiceList.Add('home::home');
entry.URL = 'http://sg1.trusted.msntv.msn.com/Pages/Home/Home.aspx';
entry.KeyCode = 0xAC; // VK_BROWSER_HOME
entry.Safe = true;
entry = tvShell.UserManager.CurrentUser.ServiceList.Add('home::bgmusic');
entry.URL = '}';
entry.Safe = true;
entry = tvShell.UserManager.CurrentUser.ServiceList.Add('home::backendproxy');
entry.URL = 'http://sg1.trusted.msntv.msn.com/BackendProxy';
entry.Safe = true;
entry = tvShell.UserManager.CurrentUser.ServiceList.Add('home::radioplus');
entry.URL = 'http://sg1.trusted.msntv.msn.com/Stations.xml';
entry.Safe = true;
entry = tvShell.UserManager.CurrentUser.ServiceList.Add('mail::listmail');
entry.URL = 'http://sg1.trusted.msntv.msn.com/Pages/Mail/listmail.aspx';
entry.KeyCode = 0xB4; // VK_LAUNCH_MAIL
entry.Safe = true;
entry = tvShell.UserManager.CurrentUser.ServiceList.Add('mail::writemail');
entry.URL = 'http://sg1.trusted.msntv.msn.com/Pages/Mail/writemail.aspx';
entry.Safe = true;
entry = tvShell.UserManager.CurrentUser.ServiceList.Add('chat::home');
entry.URL = 'http://sg1.trusted.msntv.msn.com/Pages/Chat/Chat.html';
entry.Safe = true;
entry = tvShell.UserManager.CurrentUser.ServiceList.Add('messenger::root');
entry.URL = 'http://login.live.com:1863';
entry.Safe = true;
entry = tvShell.UserManager.CurrentUser.ServiceList.Add('messenger::passport');
entry.URL = 'https://login.live.com';
entry = tvShell.UserManager.CurrentUser.ServiceList.Add('search::search');
entry.URL = 'http://sg1.trusted.msntv.msn.com/Pages/Search/search.html';
entry.Safe = true;
entry = tvShell.UserManager.CurrentUser.ServiceList.Add('search::main');
entry.URL = 'http://sg1.trusted.msntv.msn.com/Pages/Search/categories.html';
entry.Safe = true;
entry = tvShell.UserManager.CurrentUser.ServiceList.Add('discuss::home');
entry.URL = 'http://sg1.trusted.msntv.msn.com/';
entry.Safe = true;
entry = tvShell.UserManager.CurrentUser.ServiceList.Add('maps::main');
entry.URL = 'http://sg1.trusted.msntv.msn.com/';
entry.Safe = true;
entry = tvShell.UserManager.CurrentUser.ServiceList.Add('Settings::HomeNetwork');
entry.URL = 'msntv:/Settings/Network/HomeNetworking.html';
entry.Safe = true;
entry = tvShell.UserManager.CurrentUser.ServiceList.Add('settings::mainindex');
entry.URL = 'http://sg1.trusted.msntv.msn.com/settings/main.aspx';
entry.Safe = true;
entry = tvShell.UserManager.CurrentUser.ServiceList.Add('UAM::UAMbase');
entry.URL = 'http://sg1.trusted.msntv.msn.com/';
entry.Safe = true;
entry = tvShell.UserManager.CurrentUser.ServiceList.Add('Photo::Home');
entry.URL = 'msntv:/Photo/PhotoHome.html';
entry.Safe = true;
entry = tvShell.UserManager.CurrentUser.ServiceList.Add('Photos');
entry.URL = 'msntv:/Photo/PhotoHome.html';
entry.Safe = true;
// Add services to ServiceList
tvShell.ServiceList.Clear();
entry = tvShell.ServiceList.Add('home::cinemanow');
entry.URL = 'http://g.msn.com/5TVANDURIL/4000';
entry = tvShell.ServiceList.Add('msn::radioplus');
entry.URL = 'http://radio.msn.com/asx/generate';
entry = tvShell.ServiceList.Add('music::radiohome');
entry.URL = 'http://radio.msn.com/asx/generate';
entry = tvShell.ServiceList.Add('msn::musicnews');
entry.URL = 'http://www.msnbc.msn.com/id/3032433/';
entry = tvShell.ServiceList.Add('connection::popupcontrol');
entry.URL = 'http://sg1.trusted.msntv.msn.com/connection/PopupControlWhiteList.ashx';
entry = tvShell.ServiceList.Add('connection::reconnect');
entry.URL = 'http://headwaiter.trusted.msntv.msn.com/connection/GatePage.aspx?phase=Bootstrap&purpose=Authorize';
entry = tvShell.ServiceList.Add('connection::nightly_login');
entry.URL = 'http://headwaiter.trusted.msntv.msn.com/connection/GatePage.aspx?phase=Bootstrap&purpose=Nightly';
entry = tvShell.ServiceList.Add('mail::check');
entry.URL = 'http://sg1.trusted.msntv.msn.com/apps/connection/CheckMail.aspx?phase=CheckMail&purpose=CheckMail';
entry.Safe = true;
if (wanProvider === "MSNIANB") {
entry = tvShell.ServiceList.Add('home::videoplus');
entry.URL = 'msntv:/Video/VideoHome.html';
entry.Safe = true;
} else {
entry = tvShell.ServiceList.Add('home::videoplus');
entry.URL = 'http://sg1.trusted.msntv.msn.com/pages/msnvideo/main';
entry.Safe = true;
}
if (wanProvider === "MSNIANB") {
entry = tvShell.ServiceList.Add('home::musicvideo');
entry.URL = 'msntv:/Music/MusicHome.html';
entry.Safe = true;
} else {
entry = tvShell.ServiceList.Add('home::musicvideo');
entry.URL = 'http://sg1.trusted.msntv.msn.com/pages/msnvideo/main?p=music';
entry.Safe = true;
}
entry = tvShell.ServiceList.Add('connection::resetpassword');
entry.URL = 'http://sg1.trusted.msntv.msn.com/connection/GatePage?phase=Bootstrap&purpose=ResetPassword';
entry = tvShell.ServiceList.Add('connection::pagepatch');
entry.URL = 'http://sg1.trusted.msntv.msn.com/connection/PagePatch.ashx';
entry = tvShell.ServiceList.Add('connection::login');
entry.URL = 'http://headwaiter.trusted.msntv.msn.com/connection/GatePage.aspx?phase=Bootstrap&purpose=Authorize';
entry.Description = '${minisrv_config.config.service_name}/sg1 [${minisrv_config.config.hide_minisrv_version ? "beta" : minisrv_version_string.replace("zefie's wtv minisrv ","")}]';
entry = tvShell.ServiceList.Add('ctags::main');
entry.URL = 'http://c.msn.com/c.gif?di=1455&pi=68206&tp=http%3a%2f%2fmsntv.msn.com%2fclient%2f';
tvShell.ServiceList.Save();
}
function IsServicePanel() {
if ((window.name == null) || ((window.name != null) && (window.name.toLowerCase() != 'service'))) {
return false;
}
return true;
}
function DontContinue() {
var currentUser = tvShell.UserManager.CurrentUser;
if (currentUser != null && currentUser.IsAuthorized) {
tvShell.PanelManager.Item('main').GotoURL(tvShell.UserManager.CurrentUser.ServiceList.Item('home::home').URL);
tvShell.PanelManager.Item('main').ClearTravelLog();
tvShell.PanelManager.Item('main').NoBackToMe = true;
} else {
tvShell.ConnectionManager.ServiceState = 'ReSignIn';
}
}
if (!IsServicePanel()) {
DontContinue();
} else {
SetServiceList();
tvShell.UserManager.SetCurrentUserIsAuthorized(true);
tvShell.ConnectionManager.ServiceState = 'Authorized';
var dt = new Date();
tvShell.UserManager.LastLoginTime = dt.getTime() / 1000 + dt.getTimezoneOffset() * 60;
tvShell.UserManager.OfflineAppMaxAccessDays = 20;
tvShell.UserManager.OfflineAppMaxAccessTimes = 20;
tvShell.UserManager.Save();
tvShell.PanelManager.Item('main').GotoURL(tvShell.UserManager.CurrentUser.ServiceList.Item('home::home').URL);
tvShell.PanelManager.Item('main').ClearTravelLog();
tvShell.PanelManager.Item('main').NoBackToMe = true;
}
</script>
</body>
</html>`;

View File

@@ -27,6 +27,7 @@ class WTVMSNTV2 {
this.tlsContext = this.loadTlsContext(); this.tlsContext = this.loadTlsContext();
this.forgeTlsCredentials = this.loadForgeTlsCredentials(); this.forgeTlsCredentials = this.loadForgeTlsCredentials();
this.server = net.createServer((socket) => this.handleConnection(socket)); this.server = net.createServer((socket) => this.handleConnection(socket));
this.tokens = {};
this.mimeTypes = { this.mimeTypes = {
html: 'text/html', html: 'text/html',
htm: 'text/html', htm: 'text/html',
@@ -129,7 +130,13 @@ class WTVMSNTV2 {
socket.rawDataListener = (chunk) => this.handleData(socket, chunk); socket.rawDataListener = (chunk) => this.handleData(socket, chunk);
socket.on('data', socket.rawDataListener); socket.on('data', socket.rawDataListener);
socket.on('error', (err) => { socket.on('error', (err) => {
if (this.service_config.debug) console.error('[WTV-MSNTV2] socket error:', err.message); if (this.service_config.debug) {
if (err.message == 'read ECONNRESET') {
console.warn('[WTV-MSNTV2] Client disconnected');
} else {
console.error('[WTV-MSNTV2] socket error:', err.message);
}
}
}); });
} }
@@ -1522,6 +1529,16 @@ class WTVMSNTV2 {
const self = this; const self = this;
const responseCookies = []; const responseCookies = [];
// try to make the debug name
let debug_name = (filepath) ? filepath.split(path.sep) : null;
if (debug_name) {
if (this.wtvshared.isConfiguredService(debug_name[debug_name.length - 2]))
// service:/filename
debug_name = debug_name[debug_name.length - 2] + ":/" + debug_name[debug_name.length - 1];
else
// filename
debug_name = debug_name[debug_name.length - 1];
}
const contextObj = { const contextObj = {
socket, socket,
request_headers, request_headers,
@@ -1545,6 +1562,7 @@ class WTVMSNTV2 {
cwd: path.dirname(filepath), cwd: path.dirname(filepath),
// Cookie helpers available to scripts // Cookie helpers available to scripts
response_cookies: responseCookies, response_cookies: responseCookies,
debug: require('debug')((debug_name) ? debug_name : 'service_script'),
setCookie(name, value, opts) { setCookie(name, value, opts) {
opts = opts || {}; opts = opts || {};
let s = `${encodeURIComponent(name)}=${encodeURIComponent(value)}`; let s = `${encodeURIComponent(name)}=${encodeURIComponent(value)}`;
@@ -1593,6 +1611,9 @@ class WTVMSNTV2 {
if (socket.ssid && this.ssid_sessions && vmResult.session_data !== undefined) { if (socket.ssid && this.ssid_sessions && vmResult.session_data !== undefined) {
this.ssid_sessions[socket.ssid] = vmResult.session_data; this.ssid_sessions[socket.ssid] = vmResult.session_data;
} }
if (vmResult.socket !== socket) {
socket = vmResult.socket;
}
if (!vmResult.request_is_async) { if (!vmResult.request_is_async) {
this._sendScriptResult(socket, request_headers, vmResult.headers, vmResult.data, responseCookies); this._sendScriptResult(socket, request_headers, vmResult.headers, vmResult.data, responseCookies);
} }

View File

@@ -282,7 +282,7 @@ class WTVClientSessionData {
/** /**
* Finds an account's SSID and User ID from just the username * Finds an account's SSID and User ID from just the username
* @param {string} username The username to search for * @param {string} username The username to search for
* @returns {Array} [found {boolean}, account_dir {string|null}, user_id {number|null}] * @returns {Array} [found {boolean}, ssid {string|null}, user_id {number|null}]
*/ */
findAccountByUsername(username) { findAccountByUsername(username) {
const accounts_dir = this.getAccountStoreDirectory(); const accounts_dir = this.getAccountStoreDirectory();

View File

@@ -21,6 +21,7 @@ class WTVShared {
process = require('process'); process = require('process');
shenanigans = null; shenanigans = null;
appdir = this.path.resolve(__dirname + this.path.sep + ".." + this.path.sep + ".."); appdir = this.path.resolve(__dirname + this.path.sep + ".." + this.path.sep + "..");
tokens = {};
minisrv_config = []; minisrv_config = [];
@@ -629,6 +630,97 @@ class WTVShared {
return this.fixPathSlashes(check_path); return this.fixPathSlashes(check_path);
} }
/**
* Get the session data (BoxID, UserID, creation time, expiry) associated with a given token, also deletes the token if expired.
* @param {string} token
* @return {object|null} { boxID, userId, created, expires } for the token, or null if token is invalid/expired
*/
getTokenData(token) {
const session = this.tokens[token];
if (session && session.expires > Date.now()) {
return { boxID: session.boxID, userId: session.userId, created: session.timestamp, expires: session.expires };
}
this.deleteToken(token);
return null;
}
/**
* Checks if a token is valid (exists and not expired)
* @param {string} token The token to check
* @returns {boolean} true if valid, false if not
*/
isTokenValid(token) {
const session = this.tokens[token];
if (session && session.expires > Date.now()) {
return true;
}
this.deleteToken(token);
return false;
}
/**
* Deletes a token from the token store.
* @param {string} token The token to delete
*/
deleteToken(token) {
delete this.tokens[token];
this.saveTokens();
}
mkdirRecursive(dirPath) {
if (!this.path.isAbsolute(dirPath)) {
dirPath = this.getAbsolutePath(this.parentDirectory + this.path.sep + dirPath);
}
const parts = dirPath.split(this.path.sep);
let currentPath = '';
for (const part of parts) {
if (part) {
if (currentPath === '') {
currentPath = part;
} else {
currentPath += this.path.sep + part;
}
if (!this.fs.existsSync(currentPath)) {
try {
this.fs.mkdirSync(currentPath);
} catch (e) {
if (e.code !== 'EEXIST') {
throw e;
}
}
}
}
}
}
saveTokens() {
const session_store = this.minisrv_config.config.SessionStore + this.path.sep + "msntv2";
if (!this.fs.existsSync(session_store)) {
this.mkdirRecursive(session_store);
}
const tokenFile = this.getAbsolutePath(this.path.join(session_store, `tokens.json`));
this.fs.writeFile(tokenFile, JSON.stringify(this.tokens), (err) => {
if (err) {
console.error('[WTV-MSNTV2] Error writing token file:', err);
}
});
}
/**
* Store a token with its associated BoxID and UserID.
* @param {string} token
* @param {string} boxID
* @param {number} userId
* @param {string|null} expiresTime - Optional expiration time for the token, otherwise uses server config defaults
*/
storeToken(token, boxID, userId, expiresTime = null) {
delete this.tokens[token]; // ensure any existing token with the same value is removed before storing new data
this.tokens[token] = { boxID, userId, timestamp: Date.now(), expires: expiresTime ? new Date(expiresTime).getTime() : Date.now() + (this.minisrv_config.services[this.service_name]?.token_expiry || 3600) * 1000 }; // 1 hour expiry
this.saveTokens();
this.debug(" * MSNTV2 stored token for BoxID %s (UserID: %s), token expires in %d seconds", boxID, userId, (this.tokens[token].expires - Date.now()) / 1000);
}
/** /**
* Detects if the client is in MiniBrowser mode * Detects if the client is in MiniBrowser mode
* @param {object} ssid_session * @param {object} ssid_session

View File

@@ -527,8 +527,10 @@
"key": "%ServiceDeps%/msntv2/minisrv.key" "key": "%ServiceDeps%/msntv2/minisrv.key"
}, },
"modules": [ "modules": [
"WTVRegister" "WTVRegister",
] "WTVNews"
],
"usenet_service": "wtv-news"
} }
}, },
"favorites": { "favorites": {

View File

@@ -10,7 +10,10 @@ const msnDir = path.join(workspaceRoot, '..', 'includes', 'ServiceDeps', 'msntv2
const domains = [ const domains = [
"headwaiter.trusted.msntv.msn.com", "headwaiter.trusted.msntv.msn.com",
"*.trusted.msntv.msn.com", "sg1.trusted.msntv.msn.com",
"sg2.trusted.msntv.msn.com",
"sg3.trusted.msntv.msn.com",
"sg4.trusted.msntv.msn.com",
"msntv.msn.com", "msntv.msn.com",
"mail.services.live.com", "mail.services.live.com",
"login.live.com", "login.live.com",
@@ -21,8 +24,7 @@ const domains = [
"users.storage.live.com", "users.storage.live.com",
"g.msn.com", "g.msn.com",
"msnialogin.passport.com", "msnialogin.passport.com",
"minisrv.local", "minisrv.local"
"*.minisrv.local"
] ]
const defaultCaCertPath = path.join(msnDir, 'emac.crt'); const defaultCaCertPath = path.join(msnDir, 'emac.crt');

View File

@@ -1,28 +1,29 @@
-----BEGIN CERTIFICATE----- -----BEGIN CERTIFICATE-----
MIIErzCCA5egAwIBAgIQ/K/Ib/7QA0rO4hjgM53sGDANBgkqhkiG9w0BAQUFADB0 MIIE8TCCA9mgAwIBAgIQoRyc0ioSEdkYGPQxwYXUDjANBgkqhkiG9w0BAQUFADB0
MRkwFwYDVQQDDBBtaW5pc3J2IHNlcnZpY2VzMREwDwYDVQQIDAhOZXcgWW9yazEL MRkwFwYDVQQDDBBtaW5pc3J2IHNlcnZpY2VzMREwDwYDVQQIDAhOZXcgWW9yazEL
MAkGA1UEBhMCVVMxHjAcBgkqhkiG9w0BCQEWD3plZmllQHplZmllLm5ldDEXMBUG MAkGA1UEBhMCVVMxHjAcBgkqhkiG9w0BCQEWD3plZmllQHplZmllLm5ldDEXMBUG
A1UECgwOWmVmaWUgTmV0d29ya3MwIBcNMDAwMTAxMTIwMDAwWhgPMjA5OTEyMzEy A1UECgwOWmVmaWUgTmV0d29ya3MwIBcNMDAwMTAxMTIwMDAwWhgPMjA5OTEyMzEy
MzU5NTlaMFExKTAnBgNVBAMTIGhlYWR3YWl0ZXIudHJ1c3RlZC5tc250di5tc24u MzU5NTlaMFExKTAnBgNVBAMTIGhlYWR3YWl0ZXIudHJ1c3RlZC5tc250di5tc24u
Y29tMRcwFQYDVQQKEw5aZWZpZSBOZXR3b3JrczELMAkGA1UEBhMCVVMwggEiMA0G Y29tMRcwFQYDVQQKEw5aZWZpZSBOZXR3b3JrczELMAkGA1UEBhMCVVMwggEiMA0G
CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDhh5bdTvB2q03vo/hwikBsfRt3p5Sg CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCbEGP/jBpuLj8aDzeIzcN+HWaorttU
Y7N6+e+UfUK8LxZRLwLwk3TIS7LcU+RE6d8UHO8A68joX61kYggtMAGEvYC2JWGC WKqF5IY5s/nRm4WHdYUaKgDf9ksBJm2+igB0XSI1d06hvrI1VkMejvJzZpq+RNJe
XiUb37CZBJrIMTqU+tFn2zTyCvpNBU7Pv6t/PAKPc0XztrQEZ7RmqywDMbWu2B1M TqMy7cp5zPcLLymUkb8a1ziY6ZjezHMLCRyfU2zyMR3yqHCAaYP6JtEZqc3Ht4o6
86eil0HN4n4fGMYkVmVjkHJJYNChck+edkL4rDkKnbg4Ar37lYYHofrQDWTAW9eD NfVCF4A8uynHZEGW47Iz4e6gLnzXutN7/ngDPw2hi/2XKN/E5djBg1yXHeQ+Y14n
QSxXBPQbbqDIDHMdXwHnfCbJZIkgQ7ClK78PN6s9DRgagvnXI8vclyW38YQ/cqlk Ab0sHO4DgsUOYruTZu/TyO1A2ewpsGC40cRsbPAkeHtViOqVBUegDTfiqxbGpxaQ
DNkGDGcfAOg9BGtwTAUd7Bu/pAjrAR/WRY5jdv3++4/taibz5hKildA7AgMBAAGj Qfdq/b8NYQmaRO/I/kH1IfYMiI+RxeBhUiBYlSEwOBNcJrc4etIzdYOVAgMBAAGj
ggFcMIIBWDAJBgNVHRMEAjAAMAsGA1UdDwQEAwIFoDATBgNVHSUEDDAKBggrBgEF ggGeMIIBmjAJBgNVHRMEAjAAMAsGA1UdDwQEAwIFoDATBgNVHSUEDDAKBggrBgEF
BQcDATCCAScGA1UdEQSCAR4wggEagiBoZWFkd2FpdGVyLnRydXN0ZWQubXNudHYu BQcDATCCAWkGA1UdEQSCAWAwggFcgiBoZWFkd2FpdGVyLnRydXN0ZWQubXNudHYu
bXNuLmNvbYIXKi50cnVzdGVkLm1zbnR2Lm1zbi5jb22CDW1zbnR2Lm1zbi5jb22C bXNuLmNvbYIZc2cxLnRydXN0ZWQubXNudHYubXNuLmNvbYIZc2cyLnRydXN0ZWQu
Fm1haWwuc2VydmljZXMubGl2ZS5jb22CDmxvZ2luLmxpdmUuY29tghFwb3B0aW1p bXNudHYubXNuLmNvbYIZc2czLnRydXN0ZWQubXNudHYubXNuLmNvbYIZc2c0LnRy
emUubXNuLmNvbYIRZmF2b3JpdGVzLm1zbi5jb22CEW1lc3Nlbmdlci5tc24uY29t dXN0ZWQubXNudHYubXNuLmNvbYINbXNudHYubXNuLmNvbYIWbWFpbC5zZXJ2aWNl
ghFsaXZlZmlsZXN0b3JlLmNvbYIWdXNlcnMuc3RvcmFnZS5saXZlLmNvbYIJZy5t cy5saXZlLmNvbYIObG9naW4ubGl2ZS5jb22CEXBvcHRpbWl6ZS5tc24uY29tghFm
c24uY29tghdtc25pYWxvZ2luLnBhc3Nwb3J0LmNvbYINbWluaXNydi5sb2NhbIIP YXZvcml0ZXMubXNuLmNvbYIRbWVzc2VuZ2VyLm1zbi5jb22CEWxpdmVmaWxlc3Rv
Ki5taW5pc3J2LmxvY2FsMA0GCSqGSIb3DQEBBQUAA4IBAQBRY2KlKxhVUCv0h86q cmUuY29tghZ1c2Vycy5zdG9yYWdlLmxpdmUuY29tgglnLm1zbi5jb22CF21zbmlh
J66TAJocqyPEwnnvuEAxM209DhO84GR4+D9r+/U3aV18MN0tUEFOy/qx918zpwgC bG9naW4ucGFzc3BvcnQuY29tgg1taW5pc3J2LmxvY2FsMA0GCSqGSIb3DQEBBQUA
kNghNmtydvW9phMFB//tX56c8UUT0rYESylKCdYDraCh9G3avI8A5hgJQCgfeUGA A4IBAQBCeWJbS8JJNlC6OIgUQue4bkDk5bNDUFuktAWXqmoM7Kt4MLDB1O60ez/T
l0XJvc/yA3piNAPohLB1zyOBlIONLWJxI4kyKjhOM2mkIkJWmLKXOHGPnnqCUAx+ 9cSGqU9QicSn1eL0O7ETpEPO4tSDU0KB9GnulndWbyI/OgaVOC6ON7v4Uv0z7+nw
+NzEZiJst22sngmHikN53zKyUfp2DO9CUY7hbjctAKo0GUC/Q0yQmL95idqnw56j ninT66R+wajuSf9HyC8HA2FSMcIdiLBDtzUsSIxxG/EneEuxkBv31kQkHbWubIY4
Gv1deZcTth/1qUqcZRbQDT+546d87rDJLcQDXs/Q34IcmZa0v7jsIL5hJP+/PtOs 9SJeIF5evjQZOC3KRVlfa9nwM3qon7RUfLWF1CZlRmaFfZQf2r0cH5cVt13kyxKI
fpyG gc8rwbGGOGsQFlw6GzGTUNQSv35xOCRNDvPtkp+dJ4GFMCbrg2OVk8n0Ecwu9jma
TSZ7B6w5w/1YzXyFlcZolxrxrupi
-----END CERTIFICATE----- -----END CERTIFICATE-----

View File

@@ -1,27 +1,27 @@
-----BEGIN RSA PRIVATE KEY----- -----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA4YeW3U7wdqtN76P4cIpAbH0bd6eUoGOzevnvlH1CvC8WUS8C MIIEpAIBAAKCAQEAmxBj/4wabi4/Gg83iM3Dfh1mqK7bVFiqheSGObP50ZuFh3WF
8JN0yEuy3FPkROnfFBzvAOvI6F+tZGIILTABhL2AtiVhgl4lG9+wmQSayDE6lPrR GioA3/ZLASZtvooAdF0iNXdOob6yNVZDHo7yc2aavkTSXk6jMu3Kecz3Cy8plJG/
Z9s08gr6TQVOz7+rfzwCj3NF87a0BGe0ZqssAzG1rtgdTPOnopdBzeJ+HxjGJFZl Gtc4mOmY3sxzCwkcn1Ns8jEd8qhwgGmD+ibRGanNx7eKOjX1QheAPLspx2RBluOy
Y5BySWDQoXJPnnZC+Kw5Cp24OAK9+5WGB6H60A1kwFvXg0EsVwT0G26gyAxzHV8B M+HuoC5817rTe/54Az8NoYv9lyjfxOXYwYNclx3kPmNeJwG9LBzuA4LFDmK7k2bv
53wmyWSJIEOwpSu/DzerPQ0YGoL51yPL3Jclt/GEP3KpZAzZBgxnHwDoPQRrcEwF 08jtQNnsKbBguNHEbGzwJHh7VYjqlQVHoA034qsWxqcWkEH3av2/DWEJmkTvyP5B
Hewbv6QI6wEf1kWOY3b9/vuP7Wom8+YSopXQOwIDAQABAoIBAGQK4Q3f2ARUHhjZ 9SH2DIiPkcXgYVIgWJUhMDgTXCa3OHrSM3WDlQIDAQABAoIBABsMUiEgp3iaLQwm
HDpT4ZsebiJIaMIzJ+k72J5+aC2RF63AlGXCi3HUPo3E+wPk2KuT4COA9Fi8JG7c 5N1CZSwhxUc9zwjouYAHA4nbtMNFEVb2XywX8RSgAefWs/R1XoxttXqlj8wDd1L5
m7Lr0iifZWqnL1eEyqJQOobOR5jZWZq/nkebMiPSYdDrs1ettvYUWTBoGpYvLDCu 89XIAg8yseHoH9ju9yU6WOQDpoEnLiXaAX+VVKxJrQ6KE7Q0V++Lzhh2DF8IVi10
DhTjBn2OPgFG5cx+YxTZUvvw5jCFV7u7CDzC3dD/KvPuGdQPOjBnFM9p9NL7AfRw Gl8fd8B1/+zrPVuXj2tCra4KSMiclRBEvj0DjMlCHzR+JXDU8AVDg8KVi7ZQeKkx
qOF4lw5M8ZT9caDuM/J77MuPXLVh5p6LlV9auVeo3s03E7BOw6Iutje0ZcBqKkjr kYEFzEwtzuOEOZQte7I1mqZ6Uns5tnpkcJISS9p8OzOK8+FvQY+w/Ya1g5bS8wXk
lDV1QPkXCbbywW1YQDVv1kv9KgAEG1ftbGzq1REEX8SxNWDSzHl1Q04erqsJAI2y e56UtjZ33myUzwaVUEIBqSXEsAAFvnvvvv95LQPd0CRppOJWxGPcFTrW9Lsc38Ex
eO4RRVUCgYEA/8vgxZAF38605YPcddSzYzQLLABbQJP+1LFXM8fjpI7I5kb34QNN 5k/0TOkCgYEAzaF/j6de4dq7r5WMk+ZYOWJpoT56SEJiEPhOCOZEA0eiBhKpwsE7
YY6tjhuha9fyOdFTZb3Qj5bA661Hh26BCwA9mc/X/49SJqzriQiZt9ZXVJ3ri8Xv U/qOYaJdS8nR5XPz9H5fNn0cs+1f4Em6vUSHZHfSJ20ovwxH4Dgoa4MTJg7dRe4H
N6N87ELr0uneVeP2zzjJS3E9G2fGqb2ZnRV3sdKpW2m+BNgOEmSdFrUCgYEA4bWL Bw9PQLSy8EIYYjjmbHbTNvdx947eW3SCqEE+hKPhuI0vHTYA19gLIckCgYEAwQv/
RhrnN9ZNHWRQTLZSX1ixb9HtFV9AbiPrVPbmzLiqmoV/kppIinr94T3ymlygBTBS E8qNkXhJg5vCUrWXWyi1BOF5pHMLE2YY4S5744w5fy4rQ7Squrx22nE8pvSmNOs+
mowlQViQbEfivmG12QNIs3W3nxBc2jw7vz3XYA/TANdQeNCW5mmgdKGN8IukVLHe 2ZMk9J2RKry6ZHG6tx8mlstHJFdkVUeYo4Dx6K5C0YH5+0j6VLEdnRPt5gCDhOAp
tO4Vu5L7lOck+W+LYVgOTgp/c5tFSMPKB4COMS8CgYBbtfRDwQxqHsl61JkRYg5j l/vmMK3vaPwm3sN9k1dvfS6Nu6HKf3dF+U7PmW0CgYEAx11xA6JOR8N+fLoN1cda
DgDHaOVOtQETrvWN6ifzEwJylZVABpgS1z3gioWIjecZ1bQp8TE6mhlXJkxUAUmg eiiEKSUeAbj6w2E6pz45asSkviaSGJSoJL+kE90Lf1NpAYHuYHm1bmrWzUuzzQ0u
8Rgk8oEF7pPMrAjSm9PJNr8e5nPSLEhFUYdzidbVSuZdMxuFVl3Nf68iCUYQC5ts 1BoA+tOBGWCoRLJvbWCFL9ehVSDMP+SLQ7kAKcgIRRCP+4sXPMnn9j7qbA5EX38S
14qPpfD0hmgLgo8hBxPPVQKBgEfy0gmv68K92mkjIAHEIK/qGu21MmkcqvIxGwRD vnajWo5ZZkjcCQI2xw5bnKECgYBkxQBXsmoHv4SQYKQlTIk/mpYzgAdhYnQroiXm
jED4INIO+iKmcbdLC4DweVRBcHUW+U3wnLOe4rLRm3LqvMgHpvYl8TmQQrkCeF02 lb8x3qa8zrri0tI0O+DG0klY1WhVQ19Bb9/gmMeISY/6kqtmn6ojGOWAAOZs5by1
/l/Ny4o6GJnajC+4vgBPu2pRaTniVUbBmkXnzbCimgO1Te3i3vR7njMg7M4MM2t+ zL96OEzE1FZLZ6LUxsewkRCj+SyuFd1gaquUSZcpdEZODjnkycV20PBHO4Na2kX6
zFTbAoGBAKh9KJs6t6K6bK4I7L7zmRME4L7TCvzXfnqTJHYjXUIuAPDqTaNZAgCd h7syWQKBgQC8SNTXuawSYMH8KZk8WmxgejSz1t67CkZduhErKzci8iuR+WKtB24J
pV45DfUWIIAis/RswLuR3yT6aH3Wpxx7fTW/DTInvBKfU7Kw2Oyko1jWboS/2E3D EvAWfMeWUTW5vGokHJrillrrWdw1J7QivcxXXZ48GNQKxbXFUY4KBB67v8wIu0lq
0HWVZzdbU4Hj48XGeldjgPV0D1/vr1JRTYJGXtjcNDkRMk3U3xrT O+tlfmj14IJeXc4u1S/I5lSKnG+niIBYzqXeyxNWwd4H1zncP+dssg==
-----END RSA PRIVATE KEY----- -----END RSA PRIVATE KEY-----