Compare commits
6 Commits
0c5dc17ae6
...
feature/Fi
| Author | SHA1 | Date | |
|---|---|---|---|
| 17e0e6e526 | |||
|
|
02a3eef5e7 | ||
|
|
11d2ab8c86 | ||
|
|
778c0a2827 | ||
|
|
00e385cdbe | ||
|
|
cf9cc22a1c |
@@ -382,7 +382,7 @@ const runScriptInVM = function (script_data, user_contextObj = {}, privileged =
|
||||
"service_vaults": service_vaults,
|
||||
"service_deps": service_deps,
|
||||
"ssid_sessions": ssid_sessions,
|
||||
"moveArrayKey": wtvshared.moveArrayKey,
|
||||
"moveArrayKey": wtvshared.moveArrayKey, // deprecated - use wtvshared.moveArrayKey() instead
|
||||
"cwd": (filename) ? path.dirname(filename) : __dirname, // current working directory
|
||||
|
||||
// Our prototype overrides
|
||||
@@ -2704,9 +2704,11 @@ if (protocolHandledPorts.size > 0) console.log(` * Started ${protocolHandledPort
|
||||
const listening_ip_string = (minisrv_config.config.bind_ip !== "0.0.0.0") ? "IP: " + minisrv_config.config.bind_ip : "all interfaces";
|
||||
console.log(" * Listening on", listening_ip_string, "~", "Service IP:", service_ip);
|
||||
|
||||
// Security warning for default user data encryption key
|
||||
if (minisrv_config.config.keys.user_data_key === "PNa$WN7gz}!T=t6X7^=|Ii##CEB~p\\EP") {
|
||||
console.log(" * WARNING: You are using the default user data encryption key. This is not secure, and you should change it in the configuration file before registering any users.");
|
||||
console.log(" * To generate a random key in bash or PowerShell, you can run: node ./tools/configurator.js config.keys.user_data_key $(openssl rand -base64 32)");
|
||||
console.log(" * After changing the key in the user_config, you can run tools/update_user_data_key.js to update existing accounts with the new key.");
|
||||
console.log(" * After changing the key in the user_config, please restart the server.");
|
||||
console.log(" * If you had existing users prior to changing the key, you can run tools/update_user_data_key.js to update existing accounts with the new key.");
|
||||
console.log(" * Making a backup of your user accounts before doing this is highly recommended, in case something goes wrong during the update process.");
|
||||
}
|
||||
27
zefie_wtvp_minisrv/includes/ServiceDeps/msntv2/minisrv.crt
Normal file
@@ -0,0 +1,27 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEqzCCA5OgAwIBAgIQ3Zq6hcFrpKh4v3/G9sTw3DANBgkqhkiG9w0BAQUFADBw
|
||||
MQswCQYDVQQGEwJVUzELMAkGA1UECAwCT0gxEzARBgNVBAcMCkJ1dHQgQ3JhY2sx
|
||||
IDAeBgNVBAoMF1VuZGVyd2VhciBJbnNwZWN0b3IgIzEyMR0wGwYDVQQLDBRUaGlu
|
||||
ZyBMb29rZXIgRXhwZXJ0czAgFw0wMDAxMDExMjAwMDBaGA8yMDk5MTIzMTIzNTk1
|
||||
OVowUTEpMCcGA1UEAxMgaGVhZHdhaXRlci50cnVzdGVkLm1zbnR2Lm1zbi5jb20x
|
||||
FzAVBgNVBAoTDlplZmllIE5ldHdvcmtzMQswCQYDVQQGEwJVUzCCASIwDQYJKoZI
|
||||
hvcNAQEBBQADggEPADCCAQoCggEBAMtl9J068AFSHykffAlcpspq3D7mE7fFRoyf
|
||||
+tQCM3Wy7PqJvDAegoI4Zf/QdToTJMS6dkcsEx+dgD01VKJ1B0RdHbg6rFQfymc4
|
||||
GKyNk6tuqp7YQqElCUc91oFz4pJaJaOYaNBqkAG3MfTg+tSoBXl2YyjPrT0TPhXX
|
||||
1Cm7BuFZORqNhvTdf33QXzgCQVso9U5X9YBgDaiTcu55etjFKUBEYhSYwTHmennA
|
||||
FWOjY7ux6HFXBfKAz1QeCE6+corl5+6srCfh7Uz3ZFV9vntEYnyzbJuo6gR5P7GI
|
||||
IYsygkADQAETHivl6GxeB7SEUfYLnfrZFwZc235tUz7USBdg3gcCAwEAAaOCAVww
|
||||
ggFYMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMB
|
||||
MIIBJwYDVR0RBIIBHjCCARqCIGhlYWR3YWl0ZXIudHJ1c3RlZC5tc250di5tc24u
|
||||
Y29tghcqLnRydXN0ZWQubXNudHYubXNuLmNvbYINbXNudHYubXNuLmNvbYIWbWFp
|
||||
bC5zZXJ2aWNlcy5saXZlLmNvbYIObG9naW4ubGl2ZS5jb22CEXBvcHRpbWl6ZS5t
|
||||
c24uY29tghFmYXZvcml0ZXMubXNuLmNvbYIRbWVzc2VuZ2VyLm1zbi5jb22CEWxp
|
||||
dmVmaWxlc3RvcmUuY29tghZ1c2Vycy5zdG9yYWdlLmxpdmUuY29tgglnLm1zbi5j
|
||||
b22CF21zbmlhbG9naW4ucGFzc3BvcnQuY29tgg1taW5pc3J2LmxvY2Fsgg8qLm1p
|
||||
bmlzcnYubG9jYWwwDQYJKoZIhvcNAQEFBQADggEBAAGEINTBTrkbpO0CJPv9w4Nj
|
||||
IMuOSZETA7uXWyPwoLBIa57yTjNEVvWmjAc2nnrI3D6ijLMiF1eDIEsP4DI/qfMs
|
||||
J82cS/IOIxXCmReU132NaZ6mSNEZx9QDkz/R8rFq5jKPRYSeguZSsWDxYlaQsbRr
|
||||
qxQsKkRIOpm5pIOA/UT2gwV0L84a/NHXHNfc+CnPvvy7R9kmUC0XynsqU3lkj4Ah
|
||||
SNZOgYyWkGWW7AytQWnMxyWm+xQjG4Fwl1Os9en4qwCK0ADyMCQyG3O68Gffu2go
|
||||
YciXaJquI52fEKDQV4mDxy4B1V8BQ3ywm1iGebLzLgrKK7xPucUU5fqz7v2IUIs=
|
||||
-----END CERTIFICATE-----
|
||||
27
zefie_wtvp_minisrv/includes/ServiceDeps/msntv2/minisrv.key
Normal file
@@ -0,0 +1,27 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEAy2X0nTrwAVIfKR98CVymymrcPuYTt8VGjJ/61AIzdbLs+om8
|
||||
MB6Cgjhl/9B1OhMkxLp2RywTH52APTVUonUHRF0duDqsVB/KZzgYrI2Tq26qnthC
|
||||
oSUJRz3WgXPiklolo5ho0GqQAbcx9OD61KgFeXZjKM+tPRM+FdfUKbsG4Vk5Go2G
|
||||
9N1/fdBfOAJBWyj1Tlf1gGANqJNy7nl62MUpQERiFJjBMeZ6ecAVY6Nju7HocVcF
|
||||
8oDPVB4ITr5yiuXn7qysJ+HtTPdkVX2+e0RifLNsm6jqBHk/sYghizKCQANAARMe
|
||||
K+XobF4HtIRR9gud+tkXBlzbfm1TPtRIF2DeBwIDAQABAoIBAADoPGfDhQfq4IyA
|
||||
gVjRvhHmDLbTgOACp1aZbUPeNKUmpKVWniCOA+GZZ2V1ZEIOwGaH0sVtF8xXmZeF
|
||||
5UUKOS7GLL7b6CJB6z2vNt3CJ35av03d3UI2iSzCEYxadd0jcMqJGfwsyLKkdgd6
|
||||
rDO5m7ikdtT0qpGjEQi46AKkCZseSdIZqtgm1t0NupbXuBKbR13N6iNOr6eVnEpZ
|
||||
tTrwIvw/OZ3Wf9tVW0DzjB1ejUYXCYAd6mHskMRrNfu/11x2pyXMHOSl24sVZxHe
|
||||
Dxe+cYjw61/5pMMBq6ZQ61SPvAWZbIOA/PINHIUjisIGxpeqluz0zb+SLLrZnBe5
|
||||
i9WEHsUCgYEA5lKEc5w02/n9+6wZCK/sPWhNJF3cPw2E0O+kqHPWLx2qPNhKf2Zh
|
||||
8RycdVCnCcEXVQedYnNpBeAktMNGxAR9IhiVhfwiG0dFYXNUHBIHgVBZqtOeW8sS
|
||||
uy4/fOw/qCCLWDfnDaozj8RnKsvu6zLm4c73Q4FEr4R6rk4EjfsGA90CgYEA4hMD
|
||||
9PBdIWAYapP2FRangOmP50YNQVznrmDsfFlm2vh3aFrx83f0IFjYxeUI7OdTjkk3
|
||||
7m5pEeV/liQwB/D7uXF+gNoUQab61QRhuKd58TbQELJkeBwevUb3rWVZ3LiFNNVB
|
||||
vcunKTsL4qEADw56qMaczuZ27xXwatgUVtOdbTMCgYAmOA0ojgQreIlPyNgCnAas
|
||||
jfE3Fqgkgl7GuO1u0oH5IYgNPqrmBxw7gU7pHLALK1Ju1qukGZiU1APjRwAoKMKG
|
||||
9ONi71rNgf8eU5/iZI+AQtAOS71caA88pkj8tss9X+Efi2840kRqF+IytNJ5juHH
|
||||
GKvpNLssEOS2pdWVpdDytQKBgF47WNne2qLPwD2kYN1XbQhh0lavL1VAWV2pDsmi
|
||||
Jio9iOAZkGJQbJSTFAAgwICmx4A2arbalLcd9vlpKhAVVYdtlDI3NFxNMp5ZzjW+
|
||||
sShnFYDwKsqZxgJVM2W2KifDTdrAzT9ERO/9qa2UOEcOXPg+mRvwmkB735NZb9jl
|
||||
KehbAoGBANXDltYtJh28hMopP2sZUEx/4A2fnGjVMxBmpSsrk6irz5u/wdhimlDP
|
||||
+JHZZXrb/OTU2BjCPjCCOj953XUqsCpBvWgGdX8uab0O4Gg8x8ucu/K6/kp0X0jN
|
||||
EWQYaMAXJlLQM+k7bXrABNIGu8BF3JzC9oYjlKiFpLqNOQpfHdbK
|
||||
-----END RSA PRIVATE KEY-----
|
||||
@@ -1,29 +0,0 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIFCzCCA/OgAwIBAgIQdCYWD0et5QHOJ3OYuF0r2TANBgkqhkiG9w0BAQUFADBw
|
||||
MQswCQYDVQQGEwJVUzELMAkGA1UECAwCT0gxEzARBgNVBAcMCkJ1dHQgQ3JhY2sx
|
||||
IDAeBgNVBAoMF1VuZGVyd2VhciBJbnNwZWN0b3IgIzEyMR0wGwYDVQQLDBRUaGlu
|
||||
ZyBMb29rZXIgRXhwZXJ0czAeFw0yNjA1MDEwMjMzMDhaFw00MTA0MjgwMjMzMDha
|
||||
MFExKTAnBgNVBAMTIGhlYWR3YWl0ZXIudHJ1c3RlZC5tc250di5tc24uY29tMRcw
|
||||
FQYDVQQKEw5aZWZpZSBOZXR3b3JrczELMAkGA1UEBhMCVVMwggEiMA0GCSqGSIb3
|
||||
DQEBAQUAA4IBDwAwggEKAoIBAQCpSe+Vpv9qwb5aDgMNfWRTeXAGvTzhP+olLX+J
|
||||
2WczAXr4FUSLE4LPyD43se26u4GBvGmKD9512/GZKCtMbKPmfBdIqeq/CF2gx8xh
|
||||
e55qF8OuOdxMukOLXsTmvf4slwp3/N6gyze/PMmX+ku/gbotwPL0sv/9Vf1+PVTY
|
||||
6Fje2EU0ra6xJADeL9gazdl6QBxiJ+py+49SiZMS8N4MICOfklykENmjDoM211W6
|
||||
mIRgRZebxijNiZNFeWeXzjxzAAWi701TDs8ksNHSRBG2pajDZ+XgB8D1T+yXWbPz
|
||||
zylePg6HlG8n+asd43wakF8aER26eCT5hyCb4+SkkRClRXLHAgMBAAGjggG+MIIB
|
||||
ujAJBgNVHRMEAjAAMAsGA1UdDwQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcDATCC
|
||||
AYkGA1UdEQSCAYAwggF8giBoZWFkd2FpdGVyLnRydXN0ZWQubXNudHYubXNuLmNv
|
||||
bYIZc2cxLnRydXN0ZWQubXNudHYubXNuLmNvbYIZc2cyLnRydXN0ZWQubXNudHYu
|
||||
bXNuLmNvbYIZc2czLnRydXN0ZWQubXNudHYubXNuLmNvbYIZc2c0LnRydXN0ZWQu
|
||||
bXNudHYubXNuLmNvbYINbXNudHYubXNuLmNvbYIWbWFpbC5zZXJ2aWNlcy5saXZl
|
||||
LmNvbYIec3luYy1zZzEudHJ1c3RlZC5tc250di5tc24uY29tgg5sb2dpbi5saXZl
|
||||
LmNvbYIRcG9wdGltaXplLm1zbi5jb22CEWZhdm9yaXRlcy5tc24uY29tghFtZXNz
|
||||
ZW5nZXIubXNuLmNvbYIRbGl2ZWZpbGVzdG9yZS5jb22CFnVzZXJzLnN0b3JhZ2Uu
|
||||
bGl2ZS5jb22CCWcubXNuLmNvbYIXbXNuaWFsb2dpbi5wYXNzcG9ydC5jb22CDW1p
|
||||
bmlzcnYubG9jYWwwDQYJKoZIhvcNAQEFBQADggEBAD9O6j8bWtsX9OGf0kT3u1dy
|
||||
n6F+MQWX+vI4C9131Nso7cf7/+FyPcg17ewKw1MJ33ZpzCqhupAnN1lZPikGnl+t
|
||||
VacegsqI2mX1ycD11s1EleobHLc28uEQHDd79Dwn6fA2/EOijyqsILJHB6kzLjH6
|
||||
DV/sapv4JtNMlKDjfHDhtiI2jtpYTfkoZqjs7WsNmaJBcJ/NgTtl3hFSMiN/MLQ0
|
||||
O9wyrvNheINIJ01trpcgLDpmwCG0lYoa8AOdRZccl0KR7IsdVBcV1ANFguepQXI5
|
||||
dc/VJcFWsYs0puGdhPPZHgiZV4pzmfU+rCM/AoNxDdRBrVSal6Um5YyhlmFtobA=
|
||||
-----END CERTIFICATE-----
|
||||
@@ -1,27 +0,0 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEAqUnvlab/asG+Wg4DDX1kU3lwBr084T/qJS1/idlnMwF6+BVE
|
||||
ixOCz8g+N7HturuBgbxpig/eddvxmSgrTGyj5nwXSKnqvwhdoMfMYXueahfDrjnc
|
||||
TLpDi17E5r3+LJcKd/zeoMs3vzzJl/pLv4G6LcDy9LL//VX9fj1U2OhY3thFNK2u
|
||||
sSQA3i/YGs3ZekAcYifqcvuPUomTEvDeDCAjn5JcpBDZow6DNtdVupiEYEWXm8Yo
|
||||
zYmTRXlnl848cwAFou9NUw7PJLDR0kQRtqWow2fl4AfA9U/sl1mz888pXj4Oh5Rv
|
||||
J/mrHeN8GpBfGhEdungk+Ycgm+PkpJEQpUVyxwIDAQABAoIBAAeA8Rr4Irs/wtqU
|
||||
17BXv20LyGXG+74z3oKu/iTFKfyYnAUfDaouqB+z0z4tG+yo/B3XIK0BC8sY3NpD
|
||||
EKPkkfi19B0qD0xnUON5LA//j0l4lI3dtrHpaSJ9nRCvatuANa2sOPzqIiZDVYLB
|
||||
Y8qCkP+yLqn71HSY81dUl4Zgsznr7w0VGXLzJd3nUKYL/FRVpsBPy7uHsUemB8YO
|
||||
mgGIVg7l7SpVX/tzZFnoQyPeiABv3hHTWoquxQfT9fqGQEm66cmzQP8yefaVvw1l
|
||||
Eiikx/QWX2SsXfqXdMmiQUI/y+1WV2XL955e9BFzlH6HrePaj9CIrP3+HLtw1fMZ
|
||||
It20WqECgYEA6FWcM2auqqVWrbee8oaoUT/XlQH8TZndlbWGSsFcQZptVTyB+ZMf
|
||||
DyDBAAh18ix7XVEtm6+2pioBZtou5Vp/RjWM1OI3f0mvVgVi2zFIIy52WrWxTHiv
|
||||
OSZpAv3NZEoiq/K3InrF3RolVklfQFv9TJBLmfNfTVtuEd47eBiLZckCgYEAuohW
|
||||
n0pPQhnBb1OiDv82GfyUVORVX4zcjvFGnTbqHiyH1l3+KNBtWQ2Wy5TsBifhXk5h
|
||||
TbGydO4RePeCaUBf4QFtABFsGH+et7Ci5ALvZBTLbCouvZRcDINnKsF0Wd1ZP9TW
|
||||
F7ToN6q3vkhbHIpY59Il96Ije7F6CwV7SQR0nA8CgYBcgzpffVOvv4Z0RdmU2OnM
|
||||
8I73VoMQo2QIaO/AdJ43wTYn6qAWsO59J52yVawhcnTtA5YVmDIymCdWvSpPSWnE
|
||||
my4o1qsilEStDBgBD+6Zk7atCAxBVwzuxMyr1EQk2yBTN6KUqC6BjBex9CVpizeh
|
||||
dROlibM5Kl753nPvrlZTgQKBgQC0fi6LbgUpafChv6RlrI/2L1B8oID3tz7IVjFE
|
||||
+RkrX12FkWfYqG3WqO6MSark/fv2HBPNcS/EM4TWr3ESVUcxWwbU9QbK4dp71kCY
|
||||
LzrjdbetD1gw+3jiZtgSKCVku2mb+V+8isHU861eQ3deM4R5tQAmEU8SZpY4SfKU
|
||||
oeoQAwKBgDhaHQinuYCa1w9Mzy6/AagSmS9yhXX1zR4OSgvF2lU0hT18CAR6LgOR
|
||||
gHOc6OscxDxheS38dHSIyRqD7F5hu1mO0KsGSCdmWIEKMkge8/yjrg4E4CPB5ICZ
|
||||
RcKZRL/rSQZIsdeVJM9i5FiDUaJUX+cvLJQAC1XLfRrBxCHsY0E1
|
||||
-----END RSA PRIVATE KEY-----
|
||||
@@ -1,17 +0,0 @@
|
||||
headwaiter.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
|
||||
mail.services.live.com
|
||||
sync-sg1.trusted.msntv.msn.com
|
||||
login.live.com
|
||||
poptimize.msn.com
|
||||
favorites.msn.com
|
||||
messenger.msn.com
|
||||
livefilestore.com
|
||||
users.storage.live.com
|
||||
g.msn.com
|
||||
msnialogin.passport.com
|
||||
minisrv.local
|
||||
@@ -1,5 +0,0 @@
|
||||
-----BEGIN DH PARAMETERS-----
|
||||
MIGHAoGBAOjeZEDvMxiY+T4AMUIJ6jPFhflzUwO6EPBc0+Fn3C13WGQgsx9N3Rjg
|
||||
bZsF4Sbqs62+KFTYb5/1PVPSOxyif0CJLRC8VhvCl5CZ2DsS6nJ3sstPxtfhQdn+
|
||||
X1kbvqAbHlvNtE6w5ketHv3gK6y4d9qdVnwicZW3uV1sJ2dg4RfDAgEC
|
||||
-----END DH PARAMETERS-----
|
||||
@@ -27,7 +27,7 @@ data = `<HTML>
|
||||
}
|
||||
}
|
||||
function GotoBoxCheck() {
|
||||
var url = 'https://headwaiter.trusted.msntv.msn.com/connection/boxcheck.html';
|
||||
var url = 'https://sg1.trusted.msntv.msn.com/connection/GatePage.aspx?phase=BoxCheck&purpose=Authorize';
|
||||
var parms='';
|
||||
parms += 'BoxId=' + tvShell.SystemInfo.BoxIDService + '&';
|
||||
parms += 'WANProvider=' + tvShell.ConnectionManager.WANProvider + '&';
|
||||
@@ -73,4 +73,4 @@ data = `<HTML>
|
||||
</script>
|
||||
</body>
|
||||
</HTML>
|
||||
`;
|
||||
`;
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
const minisrv_service_file = true;
|
||||
|
||||
// Todo: auth if not guest
|
||||
|
||||
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 UserManager = tvShell.UserManager;
|
||||
|
||||
var home = "https://sg1.trusted.msntv.msn.com/Home/Home.aspx";
|
||||
tvShell.ConnectionManager.ServiceState = 'Authorized';
|
||||
UserManager.SetCurrentUserIsAuthorized(true);
|
||||
var currentUser = UserManager.CurrentUser;
|
||||
if (currentUser != null) {
|
||||
currentUser.IsAuthorized = true;
|
||||
}
|
||||
var myPanel = tvShell.PanelManager.Item('main');
|
||||
if (myPanel) {
|
||||
myPanel.ClearTravelLog();
|
||||
myPanel.NoBackToMe = true;
|
||||
myPanel.GotoURL(home);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>`;
|
||||
@@ -0,0 +1,444 @@
|
||||
const minisrv_service_file = true;
|
||||
const crypto = require('crypto');
|
||||
|
||||
// Sorry Zef :kek
|
||||
// https://git.computernewb.com/yellows111/msnp-wiki/src/branch/master/docs/services/rst.md
|
||||
// the RST_ cookie stuff was code that was temp until we had proper token authentication
|
||||
const NS = {
|
||||
SOAP: "http://schemas.xmlsoap.org/soap/envelope/",
|
||||
WSSE: "http://schemas.xmlsoap.org/ws/2003/06/secext",
|
||||
WSP: "http://schemas.xmlsoap.org/ws/2002/12/policy",
|
||||
WSU: "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd",
|
||||
WSA: "http://schemas.xmlsoap.org/ws/2004/03/addressing",
|
||||
WST: "http://schemas.xmlsoap.org/ws/2004/04/trust",
|
||||
PSF: "http://schemas.microsoft.com/Passport/SoapServices/SOAPFault",
|
||||
ENC: "http://www.w3.org/2001/04/xmlenc#",
|
||||
DS: "http://www.w3.org/2000/09/xmldsig#"
|
||||
};
|
||||
|
||||
function getCookie(cookieString, name) {
|
||||
if (!cookieString) return null;
|
||||
const match = cookieString.match(new RegExp(`(?:^|;\\s*)${name}=([^;]*)`));
|
||||
return match ? decodeURIComponent(match[1]) : null;
|
||||
}
|
||||
|
||||
function setCookie(name, value, options = {}) {
|
||||
const cookie = `${name}=${encodeURIComponent(value)}`;
|
||||
const path = options.path || '/';
|
||||
const expires = options.expires || '';
|
||||
return `${cookie}; path=${path}${expires ? `; expires=${expires}` : ''}`;
|
||||
}
|
||||
|
||||
function formatDateTime(dt) {
|
||||
return dt.toISOString().replace(/\.\d{3}Z$/, 'Z');
|
||||
}
|
||||
|
||||
function getClientIP() {
|
||||
const forwarded = request_headers['x-forwarded-for'];
|
||||
if (forwarded) {
|
||||
const ips = forwarded.split(',');
|
||||
return ips[0].trim();
|
||||
}
|
||||
return request_headers['x-real-ip'] || '127.0.0.1';
|
||||
}
|
||||
|
||||
function generateRandomToken(userId, appliesTo, isLegacy = false) {
|
||||
const timestamp = Date.now();
|
||||
const randomPart = crypto.randomBytes(32).toString('hex');
|
||||
|
||||
if (isLegacy) {
|
||||
const tokenData = `${userId}|${appliesTo}|${timestamp}|${randomPart}`;
|
||||
return crypto.createHash('sha256').update(tokenData).digest('hex');
|
||||
} else {
|
||||
const tokenData = {
|
||||
uid: userId,
|
||||
app: appliesTo,
|
||||
ts: timestamp,
|
||||
rand: randomPart,
|
||||
ver: '1.0'
|
||||
};
|
||||
return Buffer.from(JSON.stringify(tokenData)).toString('base64');
|
||||
}
|
||||
}
|
||||
|
||||
function extractXmlValue(xml, elementName) {
|
||||
if (!xml) return null;
|
||||
|
||||
const patterns = [
|
||||
new RegExp(`<${elementName}>([\\s\\S]*?)</${elementName}>`, 'i'),
|
||||
new RegExp(`<wsse:${elementName}>([\\s\\S]*?)</wsse:${elementName}>`, 'i'),
|
||||
new RegExp(`<wst:${elementName}>([\\s\\S]*?)</wst:${elementName}>`, 'i'),
|
||||
new RegExp(`<ps:${elementName}>([\\s\\S]*?)</ps:${elementName}>`, 'i')
|
||||
];
|
||||
|
||||
for (const regex of patterns) {
|
||||
const match = xml.match(regex);
|
||||
if (match && match[1]) {
|
||||
let value = match[1].trim();
|
||||
value = value.replace(/</g, '<').replace(/>/g, '>').replace(/&/g, '&');
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function extractTokenFromCipherValue(xml) {
|
||||
if (!xml) return null;
|
||||
|
||||
const cipherRegex = /<CipherValue>([\s\S]*?)<\/CipherValue>/gi;
|
||||
let match;
|
||||
let token = null;
|
||||
|
||||
while ((match = cipherRegex.exec(xml)) !== null) {
|
||||
let cipherValue = match[1].trim();
|
||||
if (cipherValue && cipherValue.length > 0) {
|
||||
token = cipherValue;
|
||||
console.log("Found CipherValue token:", token.substring(0, 50) + "...");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
function validateTokenAndGetUser(token) {
|
||||
try {
|
||||
let userId = null;
|
||||
let email = null;
|
||||
|
||||
if (request_headers.cookie) {
|
||||
userId = getCookie(request_headers.cookie, 'RST_Auth');
|
||||
email = getCookie(request_headers.cookie, 'RST_Email');
|
||||
if (!email) email = getCookie(request_headers.cookie, 'rst_email');
|
||||
if (!email) email = getCookie(request_headers.cookie, 'rst_username');
|
||||
}
|
||||
|
||||
if (!userId) {
|
||||
userId = crypto.createHash('md5').update(token).digest('hex');
|
||||
email = `user_${userId.substring(0, 8)}@example.com`;
|
||||
}
|
||||
|
||||
console.log(`Token validated - UserId: ${userId}, Email: ${email}`);
|
||||
return { success: true, userId, email };
|
||||
} catch (error) {
|
||||
console.error("Token validation error:", error);
|
||||
return { success: false, userId: null, email: null };
|
||||
}
|
||||
}
|
||||
|
||||
function generateErrorResponse(errorCode, errorText) {
|
||||
const now = formatDateTime(new Date());
|
||||
headers = `Status: 200 OK
|
||||
Content-type: text/xml; charset=utf-8`;
|
||||
|
||||
return `<?xml version="1.0" encoding="utf-8"?>
|
||||
<S:Envelope xmlns:S="${NS.SOAP}" xmlns:psf="${NS.PSF}">
|
||||
<S:Header>
|
||||
<psf:pp>
|
||||
<psf:serverVersion>1</psf:serverVersion>
|
||||
<psf:authstate>0x80048800</psf:authstate>
|
||||
<psf:reqstatus>${errorCode}</psf:reqstatus>
|
||||
<psf:serverInfo Path="Live1" RollingUpgradeState="ExclusiveNew" LocVersion="0" ServerTime="${now}">
|
||||
NOBELLIUM 16.0.30846.6
|
||||
</psf:serverInfo>
|
||||
<psf:cookies></psf:cookies>
|
||||
<psf:response></psf:response>
|
||||
</psf:pp>
|
||||
</S:Header>
|
||||
<S:Body>
|
||||
<S:Fault>
|
||||
<S:Code>
|
||||
<S:Value>S:Sender</S:Value>
|
||||
<S:Subcode>
|
||||
<S:Value>wst:FailedAuthentication</S:Value>
|
||||
</S:Subcode>
|
||||
</S:Code>
|
||||
<S:Reason>
|
||||
<S:Text xml:lang="en-US">Authentication Failure</S:Text>
|
||||
</S:Reason>
|
||||
<S:Detail>
|
||||
<psf:error>
|
||||
<psf:value>${errorCode}</psf:value>
|
||||
<psf:internalerror>
|
||||
<psf:code>0x80041012</psf:code>
|
||||
<psf:text>${errorText}</psf:text>
|
||||
</psf:internalerror>
|
||||
</psf:error>
|
||||
</S:Detail>
|
||||
</S:Fault>
|
||||
</S:Body>
|
||||
</S:Envelope>`;
|
||||
}
|
||||
|
||||
function generateSuccessResponse(requestBody, userId, email, firstName, lastName) {
|
||||
const now = new Date();
|
||||
const tomorrow = new Date(now.getTime() + 24 * 60 * 60 * 1000);
|
||||
|
||||
const createdTime = formatDateTime(now);
|
||||
const expiresTime = formatDateTime(tomorrow);
|
||||
|
||||
const puid = crypto.randomBytes(16).toString('hex').toUpperCase();
|
||||
const cid = crypto.randomBytes(8).toString('hex').toUpperCase();
|
||||
|
||||
const safeFirstName = firstName || email.split('@')[0] || "User";
|
||||
const safeLastName = lastName || "User";
|
||||
const clientIp = getClientIP();
|
||||
|
||||
const rstRegex = /<wst:RequestSecurityToken[\s\S]*?<\/wst:RequestSecurityToken>/gi;
|
||||
const responses = [];
|
||||
let match;
|
||||
let foundRst = false;
|
||||
let rstIndex = 0;
|
||||
|
||||
while ((match = rstRegex.exec(requestBody)) !== null) {
|
||||
foundRst = true;
|
||||
const rstBlock = match[0];
|
||||
|
||||
const addressMatch = rstBlock.match(/<wsa:Address>(.*?)<\/wsa:Address>/i);
|
||||
let appliesTo = addressMatch ? addressMatch[1] : "urn:passport:compact";
|
||||
|
||||
const policyMatch = rstBlock.match(/<wsse:PolicyReference\s+URI="([^"]+)"/i);
|
||||
const policy = policyMatch ? policyMatch[1] : null;
|
||||
|
||||
const isLegacy = appliesTo.includes("Passport.NET");
|
||||
const tokenType = isLegacy ? "urn:passport:legacy" : "urn:passport:compact";
|
||||
const needsProofToken = policy === "MBI_KEY_OLD";
|
||||
|
||||
const token = generateRandomToken(userId, appliesTo, isLegacy);
|
||||
const tokenId = isLegacy ? `BinaryDAToken${rstIndex}` : `Compact${rstIndex}`;
|
||||
const binarySecret = crypto.randomBytes(32).toString('base64');
|
||||
|
||||
let requestedSecurityToken;
|
||||
if (isLegacy) {
|
||||
requestedSecurityToken = `
|
||||
<wst:RequestedSecurityToken>
|
||||
<EncryptedData xmlns="${NS.ENC}" Id="${tokenId}" Type="http://www.w3.org/2001/04/xmlenc#Element">
|
||||
<EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc"/>
|
||||
<ds:KeyInfo xmlns:ds="${NS.DS}">
|
||||
<ds:KeyName>http://Passport.NET/STS</ds:KeyName>
|
||||
</ds:KeyInfo>
|
||||
<CipherData>
|
||||
<CipherValue>${token}</CipherValue>
|
||||
</CipherData>
|
||||
</EncryptedData>
|
||||
</wst:RequestedSecurityToken>`;
|
||||
} else {
|
||||
let tokenValue = `t=${token}`;
|
||||
if (needsProofToken) {
|
||||
tokenValue += `&p=profile`;
|
||||
}
|
||||
requestedSecurityToken = `
|
||||
<wst:RequestedSecurityToken>
|
||||
<wsse:BinarySecurityToken Id="${tokenId}">${tokenValue}</wsse:BinarySecurityToken>
|
||||
</wst:RequestedSecurityToken>`;
|
||||
}
|
||||
|
||||
let responseXml = `
|
||||
<wst:RequestSecurityTokenResponse>
|
||||
<wst:TokenType>${tokenType}</wst:TokenType>
|
||||
<wsp:AppliesTo xmlns:wsa="${NS.WSA}">
|
||||
<wsa:EndpointReference>
|
||||
<wsa:Address>${appliesTo}</wsa:Address>
|
||||
</wsa:EndpointReference>
|
||||
</wsp:AppliesTo>
|
||||
<wst:LifeTime>
|
||||
<wsu:Created>${createdTime}</wsu:Created>
|
||||
<wsu:Expires>${expiresTime}</wsu:Expires>
|
||||
</wst:LifeTime>
|
||||
${requestedSecurityToken}
|
||||
<wst:RequestedTokenReference>
|
||||
<wsse:KeyIdentifier ValueType="${tokenType}"/>
|
||||
<wsse:Reference URI="#${tokenId}"/>
|
||||
</wst:RequestedTokenReference>`;
|
||||
|
||||
if (needsProofToken || isLegacy) {
|
||||
responseXml += `
|
||||
<wst:RequestedProofToken>
|
||||
<wst:BinarySecret>${binarySecret}</wst:BinarySecret>
|
||||
</wst:RequestedProofToken>`;
|
||||
}
|
||||
|
||||
responseXml += `
|
||||
</wst:RequestSecurityTokenResponse>`;
|
||||
|
||||
responses.push(responseXml);
|
||||
rstIndex++;
|
||||
}
|
||||
|
||||
if (!foundRst) {
|
||||
const defaultToken = generateRandomToken(userId, "urn:passport:compact", false);
|
||||
responses.push(`
|
||||
<wst:RequestSecurityTokenResponse>
|
||||
<wst:TokenType>urn:passport:compact</wst:TokenType>
|
||||
<wst:RequestedSecurityToken>
|
||||
<wsse:BinarySecurityToken Id="Compact0">t=${defaultToken}</wsse:BinarySecurityToken>
|
||||
</wst:RequestedSecurityToken>
|
||||
<wst:LifeTime>
|
||||
<wsu:Created>${createdTime}</wsu:Created>
|
||||
<wsu:Expires>${expiresTime}</wsu:Expires>
|
||||
</wst:LifeTime>
|
||||
</wst:RequestSecurityTokenResponse>`);
|
||||
}
|
||||
|
||||
headers = `Status: 200 OK
|
||||
Content-type: text/xml; charset=utf-8
|
||||
Set-Cookie: RST_Auth=${userId}; path=/; HttpOnly
|
||||
Set-Cookie: RST_Email=${email}; path=/`;
|
||||
|
||||
return `<?xml version="1.0" encoding="utf-8"?>
|
||||
<S:Envelope xmlns:S="${NS.SOAP}">
|
||||
<S:Header>
|
||||
<psf:pp xmlns:psf="${NS.PSF}">
|
||||
<psf:serverVersion>1</psf:serverVersion>
|
||||
<psf:PUID>${puid}</psf:PUID>
|
||||
<psf:configVersion>16.000.26889.00</psf:configVersion>
|
||||
<psf:uiVersion>3.100.2179.0</psf:uiVersion>
|
||||
<psf:mobileConfigVersion>16.000.26208.0</psf:mobileConfigVersion>
|
||||
<psf:authstate>0x48803</psf:authstate>
|
||||
<psf:reqstatus>0x0</psf:reqstatus>
|
||||
<psf:serverInfo Path="Live1" RollingUpgradeState="ExclusiveNew" LocVersion="0" ServerTime="${now.toISOString()}">
|
||||
NOBELLIUM 16.0.30846.6
|
||||
</psf:serverInfo>
|
||||
<psf:cookies></psf:cookies>
|
||||
<psf:browserCookies>
|
||||
<psf:browserCookie Name="MH" URL="http://www.msn.com">MSFT; path=/; domain=.msn.com; expires=Wed, 30-Dec-2037 16:00:00 GMT</psf:browserCookie>
|
||||
<psf:browserCookie Name="MH" URL="http://www.live.com">MSFT; path=/; domain=.live.com; expires=Wed, 30-Dec-2037 16:00:00 GMT</psf:browserCookie>
|
||||
</psf:browserCookies>
|
||||
<psf:credProperties>
|
||||
<psf:credProperty Name="MainBrandID">MSFT</psf:credProperty>
|
||||
<psf:credProperty Name="IsWinLiveUser">true</psf:credProperty>
|
||||
<psf:credProperty Name="CID">${cid}</psf:credProperty>
|
||||
<psf:credProperty Name="AuthMembername">${email}</psf:credProperty>
|
||||
<psf:credProperty Name="Country">US</psf:credProperty>
|
||||
<psf:credProperty Name="Language">1033</psf:credProperty>
|
||||
<psf:credProperty Name="FirstName">${safeFirstName}</psf:credProperty>
|
||||
<psf:credProperty Name="LastName">${safeLastName}</psf:credProperty>
|
||||
<psf:credProperty Name="Flags">40100643</psf:credProperty>
|
||||
<psf:credProperty Name="IP">${clientIp}</psf:credProperty>
|
||||
</psf:credProperties>
|
||||
<psf:extProperties>
|
||||
<psf:extProperty Name="CID">${cid}</psf:extProperty>
|
||||
</psf:extProperties>
|
||||
<psf:response></psf:response>
|
||||
</psf:pp>
|
||||
</S:Header>
|
||||
<S:Body>
|
||||
<wst:RequestSecurityTokenResponseCollection
|
||||
xmlns:wst="${NS.WST}"
|
||||
xmlns:wsse="${NS.WSSE}"
|
||||
xmlns:wsu="${NS.WSU}"
|
||||
xmlns:wsp="${NS.WSP}"
|
||||
xmlns:psf="${NS.PSF}">
|
||||
${responses.join('\n ')}
|
||||
</wst:RequestSecurityTokenResponseCollection>
|
||||
</S:Body>
|
||||
</S:Envelope>`;
|
||||
}
|
||||
|
||||
|
||||
function rstHandler() {
|
||||
try {
|
||||
|
||||
// Get POST data
|
||||
let requestBody = '';
|
||||
if (request_headers.post_data) {
|
||||
if (Buffer.isBuffer(request_headers.post_data)) {
|
||||
requestBody = request_headers.post_data.toString('utf8');
|
||||
} else if (typeof request_headers.post_data === 'string') {
|
||||
requestBody = request_headers.post_data;
|
||||
} else if (typeof request_headers.post_data === 'object') {
|
||||
requestBody = JSON.stringify(request_headers.post_data);
|
||||
}
|
||||
} else {
|
||||
console.log("No post_data found. Available keys:", Object.keys(request_headers));
|
||||
return generateErrorResponse("0x80048820", "No POST data received");
|
||||
}
|
||||
|
||||
if (!requestBody || requestBody.trim() === '') {
|
||||
console.log("Empty request body");
|
||||
return generateErrorResponse("0x80048820", "Empty request body");
|
||||
}
|
||||
|
||||
// Authentication
|
||||
let email = extractXmlValue(requestBody, 'Username');
|
||||
let password = extractXmlValue(requestBody, 'Password');
|
||||
|
||||
let userId = null;
|
||||
let userEmail = null;
|
||||
let firstName = "User";
|
||||
let lastName = "User";
|
||||
|
||||
if ((!email || !password) && requestBody.includes('CipherValue')) {
|
||||
console.log("No username/password found, trying token authentication...");
|
||||
const token = extractTokenFromCipherValue(requestBody);
|
||||
|
||||
if (token) {
|
||||
const tokenValidation = validateTokenAndGetUser(token);
|
||||
if (tokenValidation.success) {
|
||||
userId = tokenValidation.userId;
|
||||
userEmail = tokenValidation.email;
|
||||
console.log(`Token authentication successful for: ${userEmail} (${userId})`);
|
||||
|
||||
if (request_headers.cookie) {
|
||||
const cookieEmail = getCookie(request_headers.cookie, 'RST_Email');
|
||||
const cookieUsername = getCookie(request_headers.cookie, 'rst_username');
|
||||
if (cookieEmail) userEmail = cookieEmail;
|
||||
if (cookieUsername) firstName = cookieUsername;
|
||||
}
|
||||
} else {
|
||||
console.log("Token validation failed");
|
||||
return generateErrorResponse("0x80048821", "Invalid token");
|
||||
}
|
||||
} else {
|
||||
console.log("No token found in CipherValue");
|
||||
return generateErrorResponse("0x80048820", "Missing credentials/token");
|
||||
}
|
||||
}
|
||||
else if (email && password) {
|
||||
console.log(`Extracted - Email: ${email}, Password: ${password ? '***' : 'empty'}`);
|
||||
|
||||
if (email && email.indexOf('@') < 0) {
|
||||
const domain = (minisrv_config && minisrv_config.config && minisrv_config.config.domain_name) || 'wtv.zefie.com';
|
||||
email = `${email}@${domain}`;
|
||||
}
|
||||
|
||||
userEmail = email;
|
||||
firstName = email.split('@')[0];
|
||||
userId = crypto.createHash('md5').update(email).digest('hex');
|
||||
console.log(`Authentication successful for: ${userEmail} (${userId})`);
|
||||
}
|
||||
else {
|
||||
console.log("Missing both credentials and token");
|
||||
return generateErrorResponse("0x80048820", "Missing credentials/token");
|
||||
}
|
||||
|
||||
if (!userId || !userEmail) {
|
||||
console.log("Failed to get user identity");
|
||||
return generateErrorResponse("0x80048821", "User identity not found");
|
||||
}
|
||||
|
||||
const cookieHeaders = [
|
||||
setCookie('rst_email', userEmail, { path: '/' }),
|
||||
setCookie('rst_username', firstName, { path: '/' }),
|
||||
setCookie('rst_authenticated', 'true', { path: '/', expires: 'Wed, 30-Dec-2037 16:00:00 GMT' })
|
||||
];
|
||||
|
||||
const response = generateSuccessResponse(requestBody, userId, userEmail, firstName, lastName);
|
||||
|
||||
for (const cookie of cookieHeaders) {
|
||||
headers += `\nSet-Cookie: ${cookie}`;
|
||||
}
|
||||
|
||||
return response;
|
||||
|
||||
} catch (error) {
|
||||
console.error("RST Handler Error:", error);
|
||||
console.error("Error stack:", error.stack);
|
||||
return generateErrorResponse("0x80048820", `Internal error: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
let result = rstHandler();
|
||||
if (result) {
|
||||
data = result;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
const minisrv_service_file = true;
|
||||
|
||||
// Wrong email return: <LoginResponse Success="false"><Error Code="e5b"/></LoginResponse>
|
||||
// Wrong Password return: <LoginResponse Success="false"><Error Code="e5a"/></LoginResponse>
|
||||
|
||||
// Example Client request: <LoginRequest><ClientInfo name="MSNTV" version="1.35"/><User><SignInName>example@example.com</SignInName><Password>example</Password><SavePassword>false</SavePassword></User><DAOption>1</DAOption><TargetOption>1</TargetOption></LoginRequest>
|
||||
|
||||
data = `<LoginResponse Success="true"><TnP>t=Disabled&p=Disabled</TnP></LoginResponse>`; // T and P cant be nulled they have to have some content in it
|
||||
|
||||
headers = `200 OK
|
||||
Content-Type: text/xml`;
|
||||
|
||||
console.log(request_headers.query);
|
||||
@@ -4,15 +4,15 @@ const minisrv_service_file = true;
|
||||
const WeatherCity = 'Your City';
|
||||
const WeatherTemp = '72';
|
||||
const WeatherDescription = 'Sunny';
|
||||
const WeatherIcon = '/Pages/Home/Weather/26.gif';
|
||||
const WeatherIcon = '/Home/Weather/26.gif';
|
||||
|
||||
// News headlines
|
||||
const NewsLink1 = 'http://sg1.trusted.msntv.msn.com/Pages/Tricks/he.mp3';
|
||||
const NewsLink2 = 'http://sg1.trusted.msntv.msn.com/Pages/Tricks/pokemon-black-2.mp3';
|
||||
const NewsLink3 = 'http://sg1.trusted.msntv.msn.com/Pages/Tricks/he.mp3';
|
||||
const NewsTitle1 = 'Ryder Smells';
|
||||
const NewsTitle2 = 'Ryder Smells';
|
||||
const NewsTitle3 = 'Ryder Smells';
|
||||
const NewsLink1 = '';
|
||||
const NewsLink2 = '';
|
||||
const NewsLink3 = '';
|
||||
const NewsTitle1 = '...';
|
||||
const NewsTitle2 = '...';
|
||||
const NewsTitle3 = '...';
|
||||
|
||||
headers = `200 OK
|
||||
Content-type: text/html`;
|
||||
@@ -22,7 +22,7 @@ data = `<html xmlns:msntv>
|
||||
|
||||
<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"?>
|
||||
<?import namespace="msntv" implementation="/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">
|
||||
@@ -187,7 +187,7 @@ data = `<html xmlns:msntv>
|
||||
|
||||
<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">
|
||||
<img id="PromoImageID" width="178" height="135" border="0" hspace="0" alt="Promotional Image" src="/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>
|
||||
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 771 B |
|
After Width: | Height: | Size: 685 B |
|
After Width: | Height: | Size: 806 B |
|
After Width: | Height: | Size: 175 B |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 383 B |
|
After Width: | Height: | Size: 403 B |
@@ -75,29 +75,42 @@ data = `<html xmlns:msntv>
|
||||
</STYLE>
|
||||
|
||||
<script>
|
||||
var tvShell = new ActiveXObject("MSNTV.TVShell");
|
||||
tvShell.UserManager.SetCurrentUserIsAuthorized(false);
|
||||
var TVShell = new ActiveXObject("MSNTV.TVShell");
|
||||
TVShell.UserManager.SetCurrentUserIsAuthorized(false);
|
||||
|
||||
function AddUser() {
|
||||
var user = tvShell.UserManager.AddNew("${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();
|
||||
} else {
|
||||
user = tvShell.UserManager.Item("${username}");
|
||||
user = TVShell.UserManager.Item("${username}");
|
||||
if (user && !user.IsPersistent) {
|
||||
user.IsPersistent = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (user) {
|
||||
user.LargeIcon = "msntv:/tvshell/images/${picture}.png";
|
||||
user.SmallIcon = "msntv:/tvshell/images/${picture}.gif";
|
||||
}
|
||||
function GobacktoSignon() {
|
||||
entry = TVShell.ServiceList.Add('connection::login');
|
||||
entry.URL = 'https://sg1.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();
|
||||
TVShell.ConnectionManager.ServiceState = 'ReSignIn';
|
||||
}
|
||||
|
||||
AddUser();
|
||||
tvShell.UserManager.Save();
|
||||
</script>
|
||||
</head>
|
||||
|
||||
@@ -116,7 +129,7 @@ data = `<html xmlns:msntv>
|
||||
<table class="ApolloIcons" tabindex="-1">
|
||||
<tr height="70">
|
||||
<td tabindex="-1">
|
||||
<span style='display:inline-block; width:142px; height:158px; behavior:url(#default#alphaImageLoader); src:url(msntv:/SignInPics/Big/${picture}.png);'></span>
|
||||
<span style='display:inline-block; width:142px; height:158px; behavior:url(#default#alphaImageLoader); src:url(msntv:/SignInPics/big/${picture}.png);'></span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
@@ -139,9 +152,9 @@ data = `<html xmlns:msntv>
|
||||
</p>
|
||||
|
||||
<div id="footer">
|
||||
<msntv:CustomButton id="continue" label="Continue" href="/Home/Home.aspx" />
|
||||
<msntv:CustomButton id="continue" label="Continue" onclick="GobacktoSignon()" />
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>`;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ if (!password && request_headers.cookie) {
|
||||
if (pm) password = decodeURIComponent(pm[1]);
|
||||
}
|
||||
|
||||
if (email && email.indexOf('@') < 0) email += "@"+minisrv_config.config.service_name;
|
||||
if (email && email.indexOf('@') < 0) email += "@"+minisrv_config.config.domain_name;
|
||||
let userAvail = false;
|
||||
|
||||
if (email) {
|
||||
@@ -83,4 +83,4 @@ data = `<HTML xmlns:msntv>
|
||||
</BODY>
|
||||
</HTML>`;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ data = `<HTML xmlns:msntv>
|
||||
<p>Type your minisrv username:</p>
|
||||
<div class="input-container">
|
||||
<td><input type="text" id="email" class="inputText" name="email" maxlength="32" size="25"> </td>
|
||||
<p style="display: inline; bottom: 4px; position: relative;">@${minisrv_config.config.service_name}</p>
|
||||
<p style="display: inline; bottom: 4px; position: relative;">@${minisrv_config.config.domain_name}</p>
|
||||
</div>
|
||||
<br>
|
||||
<p>Next, enter a password:</p>
|
||||
|
||||
@@ -0,0 +1,706 @@
|
||||
const minisrv_service_file = true;
|
||||
|
||||
// Get the phase parameter from the query string
|
||||
let phase = request_headers.query.phase;
|
||||
if (Array.isArray(phase)) phase = phase[0];
|
||||
|
||||
let BoxId = request_headers.query.BoxId;
|
||||
if (Array.isArray(BoxId)) BoxId = BoxId[0];
|
||||
let clientIp = socket.remoteAddress;
|
||||
let banned = false;
|
||||
let sessionId = null;
|
||||
ServiceDomain = minisrv_config.config.domain_name;
|
||||
|
||||
// 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 = '';
|
||||
let Profile_Picture
|
||||
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();
|
||||
|
||||
const timeData = {
|
||||
hh: now.getUTCHours(),
|
||||
mm: now.getUTCMinutes(),
|
||||
ss: now.getUTCSeconds(),
|
||||
mo: now.getUTCMonth() + 1,
|
||||
dd: now.getUTCDate(),
|
||||
yyyy: now.getUTCFullYear()
|
||||
};
|
||||
|
||||
const timezoneMap = {
|
||||
"UTC": {
|
||||
standardName: "UTC",
|
||||
standardOffset: 0,
|
||||
daylightName: "UTC",
|
||||
daylightOffset: 0
|
||||
}
|
||||
};
|
||||
|
||||
const {
|
||||
standardName,
|
||||
standardOffset,
|
||||
daylightName,
|
||||
daylightOffset
|
||||
} = timezoneMap["UTC"];
|
||||
|
||||
// Set session cookie on the client
|
||||
if (sessionId) {
|
||||
setCookie('SessionID', sessionId, { path: '/' });
|
||||
}
|
||||
|
||||
// Handle different phases
|
||||
switch (phase) {
|
||||
case "Bootstrap":
|
||||
headers = `200 OK
|
||||
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");
|
||||
function IsNightlyEnabled() {
|
||||
var taskScheduler = TVShell.TaskScheduler;
|
||||
var updateTask = null;
|
||||
for (var i = 0; ((i < taskScheduler.Count) && (updateTask == null)); i++) {
|
||||
if (taskScheduler.Item(i).Caller == 'NightlyUpdate') {
|
||||
updateTask = taskScheduler.Item(i);
|
||||
}
|
||||
}
|
||||
if (updateTask != null) {
|
||||
return(true);
|
||||
}
|
||||
else {
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
function GotoBoxCheck() {
|
||||
var url = 'https://sg1.trusted.msntv.msn.com/connection/GatePage.aspx?phase=BoxCheck&purpose=Authorize';
|
||||
var parms='';
|
||||
parms += 'BoxId=' + TVShell.SystemInfo.BoxIDService + '&';
|
||||
parms += 'WANProvider=' + TVShell.ConnectionManager.WANProvider + '&';
|
||||
parms += 'version=' + encodeURIComponent(TVShell.SystemInfo.LastVersion) + '&';
|
||||
if ((TVShell.ConnectionManager.MSNIAManager != null) && (TVShell.ConnectionManager.MSNIAManager.CurrentConnector != null)) parms += 'ConnectorName=' + encodeURIComponent(TVShell.ConnectionManager.MSNIAManager.CurrentConnector.Name) + '&';
|
||||
if (TVShell.UserManager.CurrentUser != null) parms += 'domain=' + encodeURIComponent(TVShell.UserManager.CurrentUser.Domain) + '&';
|
||||
parms += 'NumRedirects=0&';
|
||||
parms += 'NightlyEnabled=' + IsNightlyEnabled() + '&';
|
||||
parms += 'x=y';
|
||||
var myPanel = TVShell.PanelManager.Item('service');
|
||||
if (myPanel) myPanel.PostToURL(url, parms);
|
||||
}
|
||||
var progressPanel = TVShell.PanelManager.Item('progress');
|
||||
function SetProgress(text, percent) {
|
||||
if (progressPanel) {
|
||||
progressPanel.Document.SetProgressText(text);
|
||||
progressPanel.Document.SetProgressPercent(percent);
|
||||
}
|
||||
}
|
||||
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 {
|
||||
TVShell.MeteringManager.Stop();
|
||||
SetProgress('Please wait while we sign you into MSN TV.', 10);
|
||||
GotoBoxCheck();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</HTML>`;
|
||||
break;
|
||||
|
||||
case "BoxCheck":
|
||||
|
||||
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");
|
||||
var email = TVShell.UserManager.EMail;
|
||||
var wanProvider = TVShell.ConnectionManager.WANProvider;
|
||||
|
||||
var banned = ${banned};
|
||||
var registered = ${registered};
|
||||
var username = "${username}";
|
||||
var picture = "${Profile_Picture}";
|
||||
var ServiceDomain = "${ServiceDomain}";
|
||||
var MSNTVToken = "";
|
||||
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;
|
||||
|
||||
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 isIDCRLErrorCode( theCode )
|
||||
{
|
||||
// when high bit is set, it is an error
|
||||
if ( theCode & 0x80000000 )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function getIDCRLCode( theCode )
|
||||
{
|
||||
return (theCode & 0xFF);
|
||||
}
|
||||
|
||||
/*
|
||||
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) {
|
||||
var user = TVShell.UserManager.AddNew(username + '@' + ServiceDomain);
|
||||
if (user) {
|
||||
var useroptions = UserManager.Item(username + '@' + ServiceDomain);
|
||||
useroptions.IsPersistent = true;
|
||||
//user.setAttribute("GuestUser", false);
|
||||
useroptions.LargeIcon = "msntv:/SignInPics/big/"+ picture + ".png";
|
||||
useroptions.SmallIcon = "msntv:/SignInPics/small/"+ picture + ".gif";
|
||||
TVShell.UserManager.Save();
|
||||
}
|
||||
}
|
||||
var myPanel = TVShell.PanelManager.Item('main')
|
||||
if (registered === true) {
|
||||
entry = TVShell.ServiceList.Add('connection::login');
|
||||
entry.URL = 'https://sg1.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 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) {
|
||||
// Check if We can do IDCRL if not fall back to Legacy XMLlogin
|
||||
if (TVShell.LoginManager.IDCRLInitialize) {
|
||||
DoIDCRLLogin();
|
||||
} else {
|
||||
// Non IDCRL Auth Code (Pre 5.x)
|
||||
Sink.AttachEvent(TVShell.LoginManager, 'OnLoginResult', OnLoginResult);
|
||||
TVShell.LoginManager.PassportSiteIDs = '507';
|
||||
TVShell.LoginManager.LoginURL = "https://login.live.com/ppsecure/clientpost.srf";
|
||||
TVShell.LoginManager.LogoutURL = "https://login.live.com/ppsecure/logoutxml.srf";
|
||||
TVShell.LoginManager.ResetPasswordURL = "https://login.live.com/ppsecure/MSRV_ResetPW_ClientPost.srf";
|
||||
TVShell.LoginManager.ChangePasswordURL = "https://login.live.com/ppsecure/MSRV_ChangePW_ClientPost.srf";
|
||||
TVShell.LoginManager.RequestProfileURL = "https://login.live.com/ppsecure/ClientProfileRequest.srf";
|
||||
TVShell.LoginManager.UpdateProfileURL = "https://login.live.com/ClientEditProf.srf";
|
||||
TVShell.LoginManager.Authenticate(email, "", "https://login.live.com/ppsecure/clientpost.srf");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function OnLoginResult(hr,t,p)
|
||||
{
|
||||
MSNTVToken = t;
|
||||
GoToUserCheck();
|
||||
}
|
||||
|
||||
function DoIDCRLLogin()
|
||||
{
|
||||
try {
|
||||
TVShell.LoginManager.IDCRLInitialize(0);
|
||||
Sink.AttachEvent(TVShell.LoginManager, "IDCRLOnAuthStateChanged",IDCRLOnAuthStateChanged);
|
||||
TVShell.LoginManager.IDCRLLogonAndAuthToServices(serviceArgs[0]);
|
||||
} catch (e) {
|
||||
TVShell.EventLog.Important("IDCRL error: " + e.message);
|
||||
}
|
||||
}
|
||||
|
||||
function IDCRLOnAuthStateChanged(result, authState, requestStatus, user, serviceTarget, servicePolicy, token, webFlowUrl)
|
||||
{
|
||||
// Find the matching policy in ProductionArgs for this serviceTarget
|
||||
var expectedPolicy = "";
|
||||
for(var i = 0; i < ProductionArgs.length; i++) {
|
||||
if(ProductionArgs[i] == serviceTarget && i+1 < ProductionArgs.length) {
|
||||
expectedPolicy = ProductionArgs[i+1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Now check with the correctly matched policy
|
||||
if(TVShell.UserManager.CurrentUser.EMail != user ||
|
||||
ProductionArgs[0] != serviceTarget ||
|
||||
expectedPolicy != servicePolicy ||
|
||||
(isIDCRLErrorCode(authState) || getIDCRLCode(authState) != 0x03) ||
|
||||
(isIDCRLErrorCode(requestStatus) || getIDCRLCode(requestStatus) != 0x00)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (token != ""){
|
||||
var tIndex = token.indexOf("t=");
|
||||
var pIndex = token.indexOf("&p=");
|
||||
// make sure there is only the "t" token exists, this is for RPS compact ticket
|
||||
// it is possible that compact ticket contains empty p parameter.
|
||||
MSNTVToken = token;
|
||||
GoToUserCheck();
|
||||
}
|
||||
else
|
||||
TVShell.EventLog.Important("No token");
|
||||
}
|
||||
|
||||
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/GatePage.aspx?phase=UserCheck&purpose=Authorize&t=' + MSNTVToken ;
|
||||
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) {
|
||||
TVShell.EventLog.Important("SetTimeZone error: " + e.message);
|
||||
}
|
||||
|
||||
try {
|
||||
TVShell.DeviceControl.SetClock(${timeData.hh}, ${timeData.mm}, ${timeData.ss}, ${timeData.mo}, ${timeData.dd}, ${timeData.yyyy});
|
||||
} catch (e) {
|
||||
TVShell.EventLog.Important("SetClock error: " + e.message);
|
||||
}
|
||||
|
||||
}
|
||||
} catch (e) {
|
||||
TVShell.EventLog.Important("Error in boxcheck: " + e.message);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>`;
|
||||
break;
|
||||
|
||||
case "UserCheck":
|
||||
headers = `Content-type: text/html`;
|
||||
|
||||
// Check if the msntv.msn.com token is correct TODO
|
||||
|
||||
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('help::help');
|
||||
entry.URL = 'http://sg1.msntv.msn.com/health/Help.aspx';
|
||||
entry.KeyCode = 0xAC; // VK_BROWSER_HOME
|
||||
entry.Safe = true;
|
||||
|
||||
entry = TVShell.UserManager.CurrentUser.ServiceList.Add('home::home');
|
||||
entry.URL = 'http://sg1.trusted.msntv.msn.com/Home/Home.aspx?WANProvider=' + wanProvider;
|
||||
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 = 'https://sg1.trusted.msntv.msn.com/BackendProxy';
|
||||
entry.Safe = true;
|
||||
|
||||
entry = TVShell.UserManager.CurrentUser.ServiceList.Add('home::radioplus');
|
||||
entry.URL = 'https://sg1.trusted.msntv.msn.com/Stations.xml';
|
||||
entry.Safe = true;
|
||||
|
||||
entry = TVShell.ServiceList.Add('music::radiohome');
|
||||
entry.URL = 'http://msntv.msn.com/pages/radio/home.aspx';
|
||||
entry.Safe = true;
|
||||
|
||||
entry = TVShell.UserManager.CurrentUser.ServiceList.Add('Livefilestore::AuthServer');
|
||||
entry.URL = 'livefilestore.com';
|
||||
entry.Description = 'MBI'
|
||||
entry.Safe = true;
|
||||
|
||||
entry = TVShell.UserManager.CurrentUser.ServiceList.Add('Skydrive::AuthServer');
|
||||
entry.URL = 'favorites.live.com';
|
||||
entry.Description = 'MBI'
|
||||
|
||||
entry = TVShell.UserManager.CurrentUser.ServiceList.Add('Skydrive::Browse');
|
||||
// entry.URL = 'users.storage.live.com';
|
||||
entry.URL = 'favorites.msn.com';
|
||||
entry.Safe = true;
|
||||
|
||||
entry = TVShell.UserManager.CurrentUser.ServiceList.Add('Skydrive::AppId');
|
||||
entry.Description = '1'
|
||||
|
||||
entry = TVShell.UserManager.CurrentUser.ServiceList.Add('Skydrive::ApiServer');
|
||||
entry.URL = 'api.live.net';
|
||||
entry.Safe = true;
|
||||
|
||||
entry = TVShell.UserManager.CurrentUser.ServiceList.Add('onlinestorage::root');
|
||||
entry.URL = 'https://livefilestore/onlinestorage/';
|
||||
entry.Safe = true;
|
||||
|
||||
entry = TVShell.UserManager.CurrentUser.ServiceList.Add('Favorites::RoamingServer');
|
||||
entry.URL = 'https://livefilestore.com/onlinestorage/';
|
||||
entry.Safe = true;
|
||||
|
||||
entry = TVShell.UserManager.CurrentUser.ServiceList.Add('Favorites::Migration');
|
||||
entry.URL = 'https://livefilestore.com/onlinestorage/';
|
||||
entry.Safe = true;
|
||||
|
||||
entry = TVShell.UserManager.CurrentUser.ServiceList.Add('Favorites::SyncServer');
|
||||
entry.URL = 'https://livefilestore.com/onlinestorage/';
|
||||
entry.Safe = true;
|
||||
|
||||
entry = TVShell.UserManager.CurrentUser.ServiceList.Add('onlinestorage::authServer');
|
||||
entry.URL = 'http://77.68.90.130/';
|
||||
entry.Description = 'MBI'
|
||||
entry.Safe = true;
|
||||
|
||||
entry = TVShell.UserManager.CurrentUser.ServiceList.Add('mail::listmail');
|
||||
entry.URL = 'http://mail-sgN.msntv.msn.com/apps/mail/listmail.aspx';
|
||||
entry.KeyCode = 0xB4; // VK_LAUNCH_MAIL
|
||||
entry.Safe = true;
|
||||
|
||||
entry = TVShell.UserManager.CurrentUser.ServiceList.Add('mail::writemail');
|
||||
entry.URL = 'http://mail-sg1.trusted.msntv.msn.com/apps/mail/writemail.aspx';
|
||||
entry.Safe = true;
|
||||
|
||||
entry = TVShell.UserManager.CurrentUser.ServiceList.Add('chat::home');
|
||||
entry.URL = 'https://sg1.trusted.msntv.msn.com/Pages/Chat/Chat.aspx';
|
||||
entry.Safe = true;
|
||||
|
||||
entry = TVShell.UserManager.CurrentUser.ServiceList.Add('chat::ServiceTarget');
|
||||
entry.URL = 'chat.msn.com';
|
||||
entry.Description = '?id=2260'
|
||||
entry.Safe = true;
|
||||
|
||||
entry = TVShell.UserManager.CurrentUser.ServiceList.Add('messenger::root');
|
||||
entry.URL = 'http://ms.msgrsvcs.ctsrv.gay:1863';
|
||||
entry.Safe = true;
|
||||
|
||||
entry = TVShell.UserManager.CurrentUser.ServiceList.Add('messenger::passport');
|
||||
entry.URL = 'https://login.live.com/messenger';
|
||||
|
||||
entry = TVShell.UserManager.CurrentUser.ServiceList.Add('messenger::ServiceTarget');
|
||||
entry.URL = 'messenger.msn.com';
|
||||
|
||||
entry = TVShell.UserManager.CurrentUser.ServiceList.Add('search::search');
|
||||
entry.URL = 'https://sg1.trusted.msntv.msn.com/Pages/Search/search.html';
|
||||
entry.Safe = true;
|
||||
|
||||
entry = TVShell.UserManager.CurrentUser.ServiceList.Add('search::main');
|
||||
entry.URL = 'https://sg1.msntv.msn.com/search/Search.aspx';
|
||||
entry.Safe = true;
|
||||
|
||||
entry = TVShell.UserManager.CurrentUser.ServiceList.Add('discuss::home');
|
||||
entry.URL = 'http://sg1.msntv.msn.com/apps/discuss/DiscussLobby.aspx';
|
||||
entry.Safe = true;
|
||||
|
||||
entry = TVShell.UserManager.CurrentUser.ServiceList.Add('maps::main');
|
||||
entry.URL = 'https://sg1.msntv.msn.com/apps/maps/GetMap.aspx';
|
||||
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 = 'https://sg1.trusted.msntv.msn.com/apps/settings/MainIndex.aspx';
|
||||
entry.Safe = true;
|
||||
|
||||
entry = TVShell.UserManager.CurrentUser.ServiceList.Add('UAM::UAMbase');
|
||||
entry.URL = 'https://sg1.trusted.msntv.msn.com/apps/uam/pages/settings.aspx';
|
||||
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('msn::musicnews');
|
||||
entry.URL = 'http://www.msnbc.msn.com/id/3032433/';
|
||||
|
||||
entry = TVShell.ServiceList.Add('connection::popupcontrol');
|
||||
entry.URL = 'https://sg1.trusted.msntv.msn.com/connection/PopupControlWhiteList.ashx';
|
||||
|
||||
entry = TVShell.ServiceList.Add('connection::reconnect');
|
||||
entry.URL = 'https://sg1.trusted.msntv.msn.com/connection/GatePage.aspx?phase=Bootstrap&purpose=ReAuthorize';
|
||||
|
||||
entry = TVShell.ServiceList.Add('connection::nightly_login');
|
||||
entry.URL = 'https://sg1.trusted.msntv.msn.com/connection/GatePage.aspx?phase=Bootstrap&purpose=Nightly';
|
||||
|
||||
entry = TVShell.ServiceList.Add('mail::check');
|
||||
entry.URL = 'https://sg1.trusted.msntv.msn.com/apps/connection/CheckMail.aspx?phase=CheckMail&purpose=CheckMail';
|
||||
entry.Safe = true;
|
||||
|
||||
if (wanProvider === "BYOA") {
|
||||
entry = TVShell.ServiceList.Add('home::videoplus');
|
||||
entry.URL = 'http://msntv.msn.com/pages/msnvideo/main.aspx';
|
||||
entry.Safe = true;
|
||||
}
|
||||
|
||||
if (wanProvider === "BYOA") {
|
||||
entry = TVShell.ServiceList.Add('home::musicvideo');
|
||||
entry.URL = 'http://msntv.msn.com/pages/msnvideo/main.aspx?p=music';
|
||||
entry.Safe = true;
|
||||
}
|
||||
|
||||
entry = TVShell.ServiceList.Add('connection::resetpassword');
|
||||
entry.URL = 'https://sg1.trusted.msntv.msn.com/connection/GatePage.aspx?phase=Bootstrap&purpose=ResetPassword';
|
||||
|
||||
entry = TVShell.ServiceList.Add('connection::pagepatch');
|
||||
entry.URL = 'https://sg1.trusted.msntv.msn.com/connection/PagePatch.ashx';
|
||||
|
||||
entry = TVShell.ServiceList.Add('connection::login');
|
||||
entry.URL = 'https://sg1.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>`;
|
||||
break;
|
||||
|
||||
default:
|
||||
headers = `200 OK
|
||||
Content-type: text/html`;
|
||||
|
||||
data = `<HTML>
|
||||
<HEAD>
|
||||
<title id="title"></title>
|
||||
</HEAD>
|
||||
</HTML>`;
|
||||
break;
|
||||
}
|
||||
@@ -37,6 +37,8 @@ if (session_data) {
|
||||
registered = session_data.isRegistered();
|
||||
if (registered) {
|
||||
username = session_data.getSessionData("subscriber_username") || '';
|
||||
Profile_Picture = session_data.getSessionData('ProfilePicture') || '';
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,23 +105,23 @@ data = `<html>
|
||||
var email = TVShell.UserManager.EMail;
|
||||
var wanProvider = TVShell.ConnectionManager.WANProvider;
|
||||
|
||||
var banned = ${banned}; // JavaScript boolean value
|
||||
var registered = ${registered}; // JavaScript boolean value
|
||||
var username = "${username}"; // JavaScript string value
|
||||
var banned = ${banned};
|
||||
var registered = ${registered};
|
||||
var username = "${username}";
|
||||
var picture = "${Profile_Picture}";
|
||||
|
||||
InitializeGuestMode();
|
||||
RemoveGuestUsers();
|
||||
InitializeGuestMode();
|
||||
RemoveGuestUsers();
|
||||
|
||||
if (!banned) {
|
||||
TVShell.AddSecretCode(10000); // sync shit
|
||||
TVShell.AddSecretCode(10001); // sync shit
|
||||
TVShell.AddSecretCode(10002); // sync shit
|
||||
TVShell.AddSecretCode(93288); // Service Select
|
||||
TVShell.AddSecretCode(77437); // Spooky Options
|
||||
TVShell.AddSecretCode(6145539); // Force Crash
|
||||
var entry = TVShell.ServiceList.Add("connection::login");
|
||||
entry.URL = "https://headwaiter.trusted.msntv.msn.com/connection/login.aspx?BoxId=${BoxId}";
|
||||
TVShell.ServiceList.Save();
|
||||
// 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) {
|
||||
@@ -129,11 +131,11 @@ data = `<html>
|
||||
if (user == usernameToCheck) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function DoLogin() {
|
||||
function DoLogin() {
|
||||
var currentUser = TVShell.UserManager.CurrentUser;
|
||||
if (currentUser == null) {
|
||||
if (banned === true) {
|
||||
@@ -146,15 +148,30 @@ data = `<html>
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
SetProgress('Welcome, New User!', 100);
|
||||
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;
|
||||
@@ -165,7 +182,7 @@ data = `<html>
|
||||
GotoSignOn();
|
||||
}
|
||||
} else {
|
||||
if (myPanel) myPanel.GotoURL('https://sg1.trusted.msntv.msn.com/register/Establish-your-MSN-TV-Account.html');
|
||||
if (myPanel) myPanel.GotoURL('https://sg1.trusted.msntv.msn.com/Register/Establish-your-MSN-TV-Account.html');
|
||||
}
|
||||
if (myPanel) {
|
||||
myPanel.ClearTravelLog();
|
||||
@@ -180,27 +197,23 @@ data = `<html>
|
||||
}
|
||||
}
|
||||
|
||||
if (currentUser != null) {
|
||||
if (currentUser != null) {
|
||||
var serviceArgs = new Array();
|
||||
var ProductionArgs = new Array("msntv.msn.com", "MBI", 0, 0,
|
||||
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
|
||||
);
|
||||
var PPEArgs = new Array();
|
||||
var INTArgs = new Array();
|
||||
serviceArgs[0] = ProductionArgs;
|
||||
serviceArgs[1] = PPEArgs;
|
||||
serviceArgs[2] = INTArgs;
|
||||
try {
|
||||
TVShell.LoginManager.IDCRLInitialize(0);
|
||||
TVShell.LoginManager.IDCRLLogonAndAuthToServices(serviceArgs[0]);
|
||||
} catch (e) {
|
||||
if (window.console) console.log("IDCRL error: " + e.message);
|
||||
}
|
||||
|
||||
GoToUserCheck();
|
||||
|
||||
GoToUserCheck();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -236,20 +249,18 @@ data = `<html>
|
||||
return null;
|
||||
}
|
||||
|
||||
function CheckBoxID() {
|
||||
SetProgress("${minisrv_config.config.service_name} [${minisrv_config.config.hide_minisrv_version ? "beta" : minisrv_version_string.replace("zefie's wtv minisrv ","")}] Welcome, ${username != '' ? username : 'Guest'}!", 20);
|
||||
}
|
||||
|
||||
function GoToUserCheck() {
|
||||
if (banned === true) {
|
||||
var url = 'https://headwaiter.trusted.msntv.msn.com/connection/banned.html';
|
||||
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) {
|
||||
GotoSignOn();
|
||||
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);
|
||||
@@ -278,7 +289,6 @@ data = `<html>
|
||||
if (!IsServicePanel()) {
|
||||
DontContinue();
|
||||
} else {
|
||||
CheckBoxID();
|
||||
DoPoptimization();
|
||||
DoLogin();
|
||||
|
||||
@@ -287,21 +297,21 @@ data = `<html>
|
||||
} 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://headwaiter.trusted.msntv.msn.com/connection/error.html');
|
||||
if (myPanel) myPanel.GotoURL('https://sg1.trusted.msntv.msn.com/connection/error.html');
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>`;
|
||||
</html>`;
|
||||
@@ -0,0 +1,193 @@
|
||||
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>`;
|
||||
@@ -197,10 +197,12 @@ if (minisrv_config.services["wtv-author"].max_pages) {
|
||||
</table>
|
||||
<p>A maximum of <b>${minisrv_config.services["wtv-author"].max_pages}</b> pages can be created, regardless of publish status.
|
||||
<br><br>
|
||||
Your published pages are available at<br>
|
||||
`
|
||||
if (numofpages > 0) {
|
||||
`Your published pages are available at<br>
|
||||
<a href="http://${site}/${session_data.getSessionData("subscriber_username")}/">http://${site}/${session_data.getSessionData("subscriber_username")}/</a>
|
||||
</table>`
|
||||
|
||||
}
|
||||
}
|
||||
data += `
|
||||
<SCRIPT language=JavaScript>
|
||||
|
||||
@@ -38,6 +38,7 @@ async function processLC2DownloadPage(flashrom_info, headers, numparts = null) {
|
||||
if (!flashrom_info.part_count) flashrom_info.part_count = parseInt(flashrom_info.message.slice(flashrom_info.message.length - 4).replace(/\D/g, ''));
|
||||
if (parseInt(flashrom_info.part_number) >= 0 && flashrom_info.rompath && flashrom_info.next_rompath) {
|
||||
if (!flashrom_info.message && flashrom_info.is_bootrom) {
|
||||
flashrom_info.part_count = 16;
|
||||
flashrom_info.message = "BootRom Part " + (flashrom_info.part_number + 1) + " of " + flashrom_info.part_count;
|
||||
}
|
||||
|
||||
@@ -72,6 +73,8 @@ async function processLC2DownloadPage(flashrom_info, headers, numparts = null) {
|
||||
downloadTime = elapsedMinutes * remainingParts;
|
||||
}
|
||||
session.lastDownloadTime = now;
|
||||
|
||||
if (isNaN(downloadTime) || downloadTime < 1) downloadTime = 1;
|
||||
|
||||
|
||||
headers = `200 OK
|
||||
@@ -127,7 +130,7 @@ Updating now
|
||||
<font size=+1>
|
||||
Your ${session_data.getBoxName()} is being<br>updated automatically.
|
||||
<p> <font size=+1>
|
||||
This will take about ${downloadTime} minutes and<br>then you can use your ${session_data.getBoxName()} again.
|
||||
This will take about ${downloadTime} minute${downloadTime !== 1 ? "s" : ""} and<br>then you can use your ${session_data.getBoxName()} again.
|
||||
`;
|
||||
if (flashrom_info.is_bootrom && flashrom_info.part_number === (flashrom_info.part_count - 1)) {
|
||||
data += `<p>
|
||||
|
||||
@@ -1163,23 +1163,11 @@ class WTVMSNTV2 {
|
||||
|
||||
loadTlsContext() {
|
||||
try {
|
||||
const certCandidates = [
|
||||
['msntv2/msn_domains.crt', 'msntv2/msn_domains.key']
|
||||
];
|
||||
let certFile = null;
|
||||
let keyFile = null;
|
||||
for (const [certPath, keyPath] of certCandidates) {
|
||||
const candidateCert = this.wtvshared.getServiceDep(certPath, true);
|
||||
const candidateKey = this.wtvshared.getServiceDep(keyPath, true);
|
||||
if (candidateCert && candidateKey) {
|
||||
certFile = candidateCert;
|
||||
keyFile = candidateKey;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!certFile || !keyFile) return null;
|
||||
const certPem = fs.readFileSync(certFile);
|
||||
const keyPem = fs.readFileSync(keyFile);
|
||||
const candidateCert = (this.service_config.ssl) ? this.wtvshared.parseConfigVars(this.service_config.ssl.cert) : null;
|
||||
const candidateKey = (this.service_config.ssl) ? this.wtvshared.parseConfigVars(this.service_config.ssl.key) : null;
|
||||
if (!candidateCert || !candidateKey) return null;
|
||||
const certPem = fs.readFileSync(candidateCert);
|
||||
const keyPem = fs.readFileSync(candidateKey);
|
||||
return tls.createSecureContext({
|
||||
cert: certPem,
|
||||
key: keyPem,
|
||||
@@ -1195,23 +1183,12 @@ class WTVMSNTV2 {
|
||||
|
||||
loadForgeTlsCredentials() {
|
||||
try {
|
||||
const certCandidates = [
|
||||
['msntv2/msn_domains.crt', 'msntv2/msn_domains.key']
|
||||
];
|
||||
let certFile = null;
|
||||
let keyFile = null;
|
||||
for (const [certPath, keyPath] of certCandidates) {
|
||||
const candidateCert = this.wtvshared.getServiceDep(certPath, true);
|
||||
const candidateKey = this.wtvshared.getServiceDep(keyPath, true);
|
||||
if (candidateCert && candidateKey) {
|
||||
certFile = candidateCert;
|
||||
keyFile = candidateKey;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!certFile || !keyFile) return null;
|
||||
const certPem = fs.readFileSync(certFile, 'utf8');
|
||||
const keyPem = fs.readFileSync(keyFile, 'utf8');
|
||||
const candidateCert = (this.service_config.ssl) ? this.wtvshared.parseConfigVars(this.service_config.ssl.cert) : null;
|
||||
const candidateKey = (this.service_config.ssl) ? this.wtvshared.parseConfigVars(this.service_config.ssl.key) : null;
|
||||
|
||||
if (!candidateCert || !candidateKey) return null;
|
||||
const certPem = fs.readFileSync(candidateCert, 'utf8');
|
||||
const keyPem = fs.readFileSync(candidateKey, 'utf8');
|
||||
return {
|
||||
certPem,
|
||||
keyPem,
|
||||
|
||||
@@ -56,18 +56,32 @@ class WTVClientSessionData {
|
||||
this.loginWhitelist.push("wtv-head-waiter:/confirm-transfer");
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns a new WTVMail instance to the session's mailstore property, using the current minisrv_config and session data.
|
||||
*/
|
||||
assignMailStore() {
|
||||
this.mailstore = new WTVMail(this.minisrv_config, this)
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns a new WTVFavorites instance to the session's favstore property, using the current minisrv_config and session data.
|
||||
*/
|
||||
assignFavoriteStore() {
|
||||
this.mailstore = this.favstore = new WTVFavorites(this.minisrv_config, this)
|
||||
this.favstore = new WTVFavorites(this.minisrv_config, this)
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new WTVSec session. Used for RC4 SECURE ON requests.
|
||||
* @returns {WTVSec} A new WTVSec session instance
|
||||
*/
|
||||
createWTVSecSession() {
|
||||
return new WTVSec(this.minisrv_config)
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the total number of unread messages for the primary account.
|
||||
* @returns {number} Number of unread messages
|
||||
*/
|
||||
getAccountTotalUnreadMessages() {
|
||||
if (!this.isRegistered()) return false; // unregistered
|
||||
if (this.user_id > 0) return false; // not primary user or pre-login
|
||||
@@ -88,6 +102,9 @@ class WTVClientSessionData {
|
||||
return total_unread_messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all user session data from memory, including session store and data store, and resets mail and favorite stores.
|
||||
*/
|
||||
clearUserSessionMemory() {
|
||||
this.setUserLoggedIn(false);
|
||||
this.data_store = [];
|
||||
@@ -96,6 +113,13 @@ class WTVClientSessionData {
|
||||
this.assignMailStore()
|
||||
}
|
||||
|
||||
/**
|
||||
* Switches the current user ID and optionally updates related data stores.
|
||||
* @param {number} user_id The user ID to switch to
|
||||
* @param {boolean} update_mail Whether to update the mail store
|
||||
* @param {boolean} update_ticket Whether to update the ticket data
|
||||
* @param {boolean} update_favorite Whether to update the favorite store
|
||||
*/
|
||||
switchUserID(user_id, update_mail = true, update_ticket = true, update_favorite = true) {
|
||||
this.user_id = parseInt(user_id);
|
||||
if (user_id !== null) {
|
||||
@@ -143,6 +167,11 @@ class WTVClientSessionData {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a given mail address is in the address book.
|
||||
* @param {string} addr The mail address to check against the address book
|
||||
* @returns {boolean} True if the address is in the address book, false otherwise
|
||||
*/
|
||||
isAddressInAddressBook(addr) {
|
||||
const addresses = this.getSessionData("address_book");
|
||||
if (addresses) {
|
||||
@@ -156,6 +185,11 @@ class WTVClientSessionData {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the first available user slot for a new user.
|
||||
* Can only be used by the primary account (user_id 0).
|
||||
* @returns {number|boolean} The first available user slot index, or false if no slots are available
|
||||
*/
|
||||
findFreeUserSlot() {
|
||||
if (this.user_id !== 0) return false; // subscriber only command
|
||||
const master_directory = this.getUserStoreDirectory(true);
|
||||
@@ -170,16 +204,30 @@ class WTVClientSessionData {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the display name of the current user.
|
||||
* @returns {string} The subscriber's display name if user_id is 0, otherwise the current user's display name.
|
||||
*/
|
||||
getDisplayName() {
|
||||
return (this.user_id === 0) ? this.getSessionData("subscriber_name") : this.getSessionData("display_name");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of users for this SSID.
|
||||
* Can only be used by the primary account (user_id 0).
|
||||
* @returns {number} The number of users this SSID has
|
||||
*/
|
||||
getNumberOfUserAccounts() {
|
||||
if (!this.isRegistered()) return false;
|
||||
if (this.user_id !== 0) return false; // subscriber only command
|
||||
return Object.keys(this.listPrimaryAccountUsers()).length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists all primary account users for this SSID.
|
||||
*
|
||||
* @returns {Array} An array containing the account data of all users for this SSID
|
||||
*/
|
||||
listPrimaryAccountUsers() {
|
||||
if (this.user_id !== 0) return false; // subscriber only command
|
||||
|
||||
@@ -206,6 +254,10 @@ class WTVClientSessionData {
|
||||
return account_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively creates directories for the given path.
|
||||
* @param {string} thedir The directory path to create
|
||||
*/
|
||||
mkdirRecursive(thedir) {
|
||||
thedir.split(this.path.sep).reduce(
|
||||
(directories, directory) => {
|
||||
@@ -307,6 +359,13 @@ class WTVClientSessionData {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* A part of the account transfer process, creates a pending transfer file in both the source and target account
|
||||
* store directories with the relevant SSID and transfer type (source or target) for each account.
|
||||
* This allows the transfer process to be completed or cancelled later, and ensures that only accounts
|
||||
* with a pending transfer can complete the transfer process.
|
||||
* @param {string} ssid
|
||||
*/
|
||||
setPendingTransfer(ssid) {
|
||||
const pending_file = this.getUserStoreDirectory(true) + this.path.sep + "pending_transfer.json";
|
||||
let ssidobj = { "ssid": ssid, "type": "source" };
|
||||
@@ -319,6 +378,10 @@ class WTVClientSessionData {
|
||||
this.fs.writeFileSync(dest_pending_file, JSON.stringify(ssidobj));
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels a pending account transfer, if it exists.
|
||||
* @returns {string|null} The SSID of the cancelled transfer if a pending transfer was found and cancelled, or null if no pending transfer was found
|
||||
*/
|
||||
cancelPendingTransfer() {
|
||||
const pending_file = this.getUserStoreDirectory(true) + this.path.sep + "pending_transfer.json";
|
||||
if (this.fs.existsSync(pending_file)) {
|
||||
@@ -334,6 +397,10 @@ class WTVClientSessionData {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finalize the transfer, completely moving all user data from the source account to the target account, and removing the pending transfer files.
|
||||
* @returns {boolean} Success of the transfer
|
||||
*/
|
||||
finalizePendingTransfer() {
|
||||
const pending_file = this.getUserStoreDirectory(true) + this.path.sep + "pending_transfer.json";
|
||||
const file = this.fs.readFileSync(pending_file)
|
||||
@@ -353,13 +420,18 @@ class WTVClientSessionData {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if there is a pending transfer for this account, and optionally check if the pending transfer type matches the specified dtype.
|
||||
* @param {string} dtype {source|target} If specified, only returns the SSID if the pending transfer type matches the specified dtype. If null, returns the pending transfer object with ssid and type.
|
||||
* @returns {string|object|boolean} The SSID of the pending transfer if dtype matches, the pending transfer object if dtype is null, or false if no pending transfer is found
|
||||
*/
|
||||
hasPendingTransfer(dtype = null) {
|
||||
const pending_file = this.getUserStoreDirectory(true) + this.path.sep + "pending_transfer.json";
|
||||
if (this.fs.existsSync(pending_file)) {
|
||||
const ssidobj = JSON.parse(this.fs.readFileSync(pending_file));
|
||||
console.log(ssidobj)
|
||||
if (dtype) {
|
||||
(ssidobj.type === dtype) ? ssidobj.ssid : false;
|
||||
return (ssidobj.type === dtype) ? ssidobj.ssid : false;
|
||||
}
|
||||
else {
|
||||
return ssidobj;
|
||||
@@ -402,6 +474,10 @@ class WTVClientSessionData {
|
||||
return result !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the user has a scrapbook directory.
|
||||
* @returns {boolean} True if the scrapbook directory exists, false otherwise.
|
||||
*/
|
||||
scrapbookExists() {
|
||||
if (this.scrapbook_dir === null) {
|
||||
const userstore_dir = this.getUserStoreDirectory();
|
||||
@@ -411,6 +487,10 @@ class WTVClientSessionData {
|
||||
return this.fs.existsSync(this.scrapbook_dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a scrapbook directory for the user if it does not already exist.
|
||||
* @returns {boolean} Success of the creation
|
||||
*/
|
||||
createScrapbook() {
|
||||
if (!this.scrapbookExists()) {
|
||||
try {
|
||||
@@ -421,6 +501,10 @@ class WTVClientSessionData {
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* A wrapper that returns the scrapbook directory, and creates it if it doesn't exist.
|
||||
* @returns {string} The path to the scrapbook directory
|
||||
*/
|
||||
scrapbookDir() {
|
||||
if (!this.scrapbookExists()) {
|
||||
this.createScrapbook();
|
||||
@@ -428,6 +512,10 @@ class WTVClientSessionData {
|
||||
return this.scrapbook_dir;
|
||||
}
|
||||
|
||||
/**
|
||||
* List the files in the user's scrapbook directory, sorted in ascending order, and excluding any .meta files.
|
||||
* @returns {Array} A filelist of the user's scrapbook files
|
||||
*/
|
||||
listScrapbook() {
|
||||
if (!this.scrapbookExists()) {
|
||||
this.createScrapbook();
|
||||
@@ -442,6 +530,10 @@ class WTVClientSessionData {
|
||||
return filteredFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the next available ID slot for a new scrapbook entry.
|
||||
* @returns {number} An available ID slot
|
||||
*/
|
||||
getFreeScrapbookID() {
|
||||
if (!this.scrapbookExists()) {
|
||||
this.createScrapbook();
|
||||
@@ -458,6 +550,10 @@ class WTVClientSessionData {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the total size of the user's scrapbook directory.
|
||||
* @returns {number} The total size in bytes
|
||||
*/
|
||||
getScrapbookUsage() {
|
||||
if (!this.scrapbookExists()) {
|
||||
this.createScrapbook();
|
||||
@@ -475,6 +571,10 @@ class WTVClientSessionData {
|
||||
return total_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the percentage of the scrapbook storage space that is in use.
|
||||
* @returns {number} Percentage of the scrapbook storage space that is in use, out of the total allotted.
|
||||
*/
|
||||
getScrapbookUsagePercent() {
|
||||
if (!this.scrapbookExists()) {
|
||||
this.createScrapbook();
|
||||
@@ -486,6 +586,11 @@ class WTVClientSessionData {
|
||||
return Math.round(usage_percent, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a scrapbook image by its ID.
|
||||
* @param {number} id
|
||||
* @returns {Buffer|null} The image data as a Buffer, or null if the image does not exist
|
||||
*/
|
||||
getScrapbookImage(id) {
|
||||
if (!this.scrapbookExists()) {
|
||||
this.createScrapbook();
|
||||
|
||||
@@ -70,7 +70,7 @@ class WTVFTP {
|
||||
stream.on('data', (chunk) => {
|
||||
chunks.push(chunk);
|
||||
totalsize += chunk.length;
|
||||
if (totalsize > 1024 * 1024 * 4) {
|
||||
if (totalsize > 1024 * 1024 * this.minisrv_config.services[this.service_name].max_response_size) {
|
||||
this.sendToClient(socket, { 'Status': '413 The item chosen contains too much information to be used.', 'Content-Type': 'text/plain' }, 'Item too large');
|
||||
ftpClient.end();
|
||||
return;
|
||||
|
||||
@@ -1130,6 +1130,7 @@ class WTVShared {
|
||||
// DON'T USE THIS
|
||||
// Saved for reference until I come up with a better way
|
||||
// If used, this will exceed the stack limit over time
|
||||
/*
|
||||
unloadModule(moduleName) {
|
||||
// Prevent usage
|
||||
return;
|
||||
@@ -1141,7 +1142,8 @@ class WTVShared {
|
||||
delete require.cache[resolvedPath];
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns an absolute path without an trailing path seperator
|
||||
* @param {string} path
|
||||
|
||||
@@ -351,6 +351,7 @@
|
||||
"ftp": {
|
||||
"port": 1650,
|
||||
"connections": 3,
|
||||
"max_response_size": 8, // Megabytes
|
||||
"handler_module": "WTVFTP",
|
||||
"handler_extra_vars": ["wtvmime"]
|
||||
},
|
||||
@@ -521,6 +522,10 @@
|
||||
],
|
||||
"handler_extra_vars": ["runScriptInVM", "handlePHP", "handleCGI", "ssid_sessions", "WTVClientSessionData", "socket_sessions"],
|
||||
"show_verbose_errors": false,
|
||||
"ssl": {
|
||||
"cert": "%ServiceDeps%/msntv2/minisrv.crt",
|
||||
"key": "%ServiceDeps%/msntv2/minisrv.key"
|
||||
},
|
||||
"modules": [
|
||||
"WTVRegister"
|
||||
]
|
||||
|
||||
@@ -14,5 +14,13 @@
|
||||
"message": "getServiceString() is deprecated and will be removed",
|
||||
"removeVersion": "0.9.80",
|
||||
"replacement": "Use wtvshared.getServiceString() instead"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "moveArrayKey",
|
||||
"pattern": "(?<!wtvshared\\.)moveArrayKey\\s*\\(",
|
||||
"flags": "g",
|
||||
"message": "moveArrayKey() is deprecated and will be removed",
|
||||
"removeVersion": "0.9.80",
|
||||
"replacement": "Use wtvshared.moveArrayKey() instead"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -225,45 +225,33 @@ function buildWebTVPS(videoES, audioES, outputPath, audioIntervalOverride, baHea
|
||||
return false;
|
||||
}
|
||||
|
||||
// Match known-working WebTV cadence (attract.mpg is ~1 audio per 7 video packs)
|
||||
const inferredInterval = Math.max(1, Math.round(vChunks.length / aChunks.length));
|
||||
// Use natural A/V ratio — matches actual bitrate split in the encoded file.
|
||||
// attract.mpg uses 7 because its video bitrate is ~7x its audio bitrate.
|
||||
// Our encoded video is lower bitrate so the natural ratio is ~3.
|
||||
const naturalInterval = Math.max(1, Math.round(vChunks.length / aChunks.length));
|
||||
const audioInterval = Number.isFinite(audioIntervalOverride) && audioIntervalOverride > 0
|
||||
? Math.floor(audioIntervalOverride)
|
||||
: Math.max(1, Math.round((inferredInterval + 7) / 2));
|
||||
: naturalInterval;
|
||||
console.log(`[*] ${vChunks.length} video chunks, ${aChunks.length} audio chunks, ` +
|
||||
`1 audio per ~${audioInterval} video`);
|
||||
|
||||
const packs = [];
|
||||
let aIdx = 0;
|
||||
|
||||
// Pre-fill: 3 audio packs to prime the WebTV audio buffer
|
||||
// Pre-fill: 3 audio packs to prime the WebTV audio buffer (matches attract.mpg)
|
||||
const preFill = Math.min(3, aChunks.length);
|
||||
for (let k = 0; k < preFill; k++, aIdx++) {
|
||||
packs.push(makePack(0xC0, aChunks[aIdx]));
|
||||
}
|
||||
|
||||
// Simple fixed-interval interleave: emit audioInterval video packs, then 1 audio pack
|
||||
let vIdx = 0;
|
||||
|
||||
// Spread audio over the full video timeline to avoid starving early playback
|
||||
// and dumping remaining audio at EOF.
|
||||
while (vIdx < vChunks.length || aIdx < aChunks.length) {
|
||||
if (vIdx >= vChunks.length) {
|
||||
packs.push(makePack(0xC0, aChunks[aIdx++]));
|
||||
continue;
|
||||
}
|
||||
if (aIdx >= aChunks.length) {
|
||||
for (let k = 0; k < audioInterval && vIdx < vChunks.length; k++) {
|
||||
packs.push(makePack(0xE0, vChunks[vIdx++]));
|
||||
continue;
|
||||
}
|
||||
|
||||
const videoProgress = vIdx / vChunks.length;
|
||||
const audioProgress = aIdx / aChunks.length;
|
||||
|
||||
// Prefer video until audio falls behind target cadence.
|
||||
if (audioProgress + (1 / Math.max(1, audioInterval * aChunks.length)) < videoProgress) {
|
||||
if (aIdx < aChunks.length) {
|
||||
packs.push(makePack(0xC0, aChunks[aIdx++]));
|
||||
} else {
|
||||
packs.push(makePack(0xE0, vChunks[vIdx++]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,12 +7,28 @@ const forge = require('node-forge');
|
||||
const workspaceRoot = __dirname;
|
||||
const httpsDir = path.join(workspaceRoot, '..', 'includes', 'ServiceDeps', 'https');
|
||||
const msnDir = path.join(workspaceRoot, '..', 'includes', 'ServiceDeps', 'msntv2');
|
||||
const domainsFile = path.join(msnDir, 'msn_domains.txt');
|
||||
|
||||
const defaultCaCertPath = path.join(msnDir, 'msntv2.crt');
|
||||
const defaultCaKeyPath = path.join(msnDir, 'msntv2.key');
|
||||
const defaultOutCertPath = path.join(msnDir, 'msn_domains.crt');
|
||||
const defaultOutKeyPath = path.join(msnDir, 'msn_domains.key');
|
||||
const domains = [
|
||||
"headwaiter.trusted.msntv.msn.com",
|
||||
"*.trusted.msntv.msn.com",
|
||||
"msntv.msn.com",
|
||||
"mail.services.live.com",
|
||||
"login.live.com",
|
||||
"poptimize.msn.com",
|
||||
"favorites.msn.com",
|
||||
"messenger.msn.com",
|
||||
"livefilestore.com",
|
||||
"users.storage.live.com",
|
||||
"g.msn.com",
|
||||
"msnialogin.passport.com",
|
||||
"minisrv.local",
|
||||
"*.minisrv.local"
|
||||
]
|
||||
|
||||
const defaultCaCertPath = path.join(msnDir, 'emac.crt');
|
||||
const defaultCaKeyPath = path.join(msnDir, 'emac.key');
|
||||
const defaultOutCertPath = path.join(msnDir, 'minisrv.crt');
|
||||
const defaultOutKeyPath = path.join(msnDir, 'minisrv.key');
|
||||
|
||||
function parseArgs(argv) {
|
||||
const out = {};
|
||||
@@ -31,42 +47,6 @@ function parseArgs(argv) {
|
||||
return out;
|
||||
}
|
||||
|
||||
function extractDomainsFromRedirectMap(text) {
|
||||
const found = [];
|
||||
const seen = new Set();
|
||||
const re = /"([A-Za-z0-9.-]+\.)"\s*:\s*self\.redirect_ip/g;
|
||||
let match;
|
||||
while ((match = re.exec(text))) {
|
||||
const clean = match[1].replace(/\.$/, '').toLowerCase();
|
||||
if (!seen.has(clean)) {
|
||||
seen.add(clean);
|
||||
found.push(clean);
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
function loadDomains(args) {
|
||||
if (args['from-map-file']) {
|
||||
const mapText = fs.readFileSync(path.resolve(workspaceRoot, args['from-map-file']), 'utf8');
|
||||
const domains = extractDomainsFromRedirectMap(mapText);
|
||||
if (!domains.length) {
|
||||
throw new Error('No domains were extracted from --from-map-file.');
|
||||
}
|
||||
return domains;
|
||||
}
|
||||
|
||||
if (!fs.existsSync(domainsFile)) {
|
||||
throw new Error('Domain file not found: ' + domainsFile);
|
||||
}
|
||||
|
||||
const domains = fs.readFileSync(domainsFile, 'utf8')
|
||||
.split(/\r?\n/)
|
||||
.map((s) => s.trim().toLowerCase())
|
||||
.filter((s) => s && !s.startsWith('#'));
|
||||
|
||||
return Array.from(new Set(domains));
|
||||
}
|
||||
|
||||
function loadPemOrThrow(filePath, label) {
|
||||
if (!fs.existsSync(filePath)) {
|
||||
@@ -99,9 +79,8 @@ function generateCert({ domains, caCertPem, caKeyPem, outCertPath, outKeyPath, y
|
||||
cert.publicKey = keys.publicKey;
|
||||
cert.serialNumber = forge.util.bytesToHex(forge.random.getBytesSync(16));
|
||||
|
||||
const now = new Date();
|
||||
cert.validity.notBefore = new Date(now.getTime() - 24 * 60 * 60 * 1000);
|
||||
cert.validity.notAfter = new Date(now.getTime() + years * 365 * 24 * 60 * 60 * 1000);
|
||||
cert.validity.notBefore = new Date('2000-01-01T12:00:00Z');
|
||||
cert.validity.notAfter = new Date('2099-12-31T23:59:59Z');
|
||||
|
||||
const cn = domains[0] || 'headwaiter.trusted.msntv.msn.com';
|
||||
cert.setSubject([
|
||||
@@ -141,7 +120,6 @@ function main() {
|
||||
const years = Number(args.years || 15);
|
||||
const sig = String(args.sig || 'sha1');
|
||||
|
||||
const domains = loadDomains(args);
|
||||
const caCertPem = loadPemOrThrow(caCertPath, 'CA cert');
|
||||
const caKeyPem = loadPemOrThrow(caKeyPath, 'CA key');
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIErzCCA5egAwIBAgIQ/K/Ib/7QA0rO4hjgM53sGDANBgkqhkiG9w0BAQUFADB0
|
||||
MRkwFwYDVQQDDBBtaW5pc3J2IHNlcnZpY2VzMREwDwYDVQQIDAhOZXcgWW9yazEL
|
||||
MAkGA1UEBhMCVVMxHjAcBgkqhkiG9w0BCQEWD3plZmllQHplZmllLm5ldDEXMBUG
|
||||
A1UECgwOWmVmaWUgTmV0d29ya3MwIBcNMDAwMTAxMTIwMDAwWhgPMjA5OTEyMzEy
|
||||
MzU5NTlaMFExKTAnBgNVBAMTIGhlYWR3YWl0ZXIudHJ1c3RlZC5tc250di5tc24u
|
||||
Y29tMRcwFQYDVQQKEw5aZWZpZSBOZXR3b3JrczELMAkGA1UEBhMCVVMwggEiMA0G
|
||||
CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDhh5bdTvB2q03vo/hwikBsfRt3p5Sg
|
||||
Y7N6+e+UfUK8LxZRLwLwk3TIS7LcU+RE6d8UHO8A68joX61kYggtMAGEvYC2JWGC
|
||||
XiUb37CZBJrIMTqU+tFn2zTyCvpNBU7Pv6t/PAKPc0XztrQEZ7RmqywDMbWu2B1M
|
||||
86eil0HN4n4fGMYkVmVjkHJJYNChck+edkL4rDkKnbg4Ar37lYYHofrQDWTAW9eD
|
||||
QSxXBPQbbqDIDHMdXwHnfCbJZIkgQ7ClK78PN6s9DRgagvnXI8vclyW38YQ/cqlk
|
||||
DNkGDGcfAOg9BGtwTAUd7Bu/pAjrAR/WRY5jdv3++4/taibz5hKildA7AgMBAAGj
|
||||
ggFcMIIBWDAJBgNVHRMEAjAAMAsGA1UdDwQEAwIFoDATBgNVHSUEDDAKBggrBgEF
|
||||
BQcDATCCAScGA1UdEQSCAR4wggEagiBoZWFkd2FpdGVyLnRydXN0ZWQubXNudHYu
|
||||
bXNuLmNvbYIXKi50cnVzdGVkLm1zbnR2Lm1zbi5jb22CDW1zbnR2Lm1zbi5jb22C
|
||||
Fm1haWwuc2VydmljZXMubGl2ZS5jb22CDmxvZ2luLmxpdmUuY29tghFwb3B0aW1p
|
||||
emUubXNuLmNvbYIRZmF2b3JpdGVzLm1zbi5jb22CEW1lc3Nlbmdlci5tc24uY29t
|
||||
ghFsaXZlZmlsZXN0b3JlLmNvbYIWdXNlcnMuc3RvcmFnZS5saXZlLmNvbYIJZy5t
|
||||
c24uY29tghdtc25pYWxvZ2luLnBhc3Nwb3J0LmNvbYINbWluaXNydi5sb2NhbIIP
|
||||
Ki5taW5pc3J2LmxvY2FsMA0GCSqGSIb3DQEBBQUAA4IBAQBRY2KlKxhVUCv0h86q
|
||||
J66TAJocqyPEwnnvuEAxM209DhO84GR4+D9r+/U3aV18MN0tUEFOy/qx918zpwgC
|
||||
kNghNmtydvW9phMFB//tX56c8UUT0rYESylKCdYDraCh9G3avI8A5hgJQCgfeUGA
|
||||
l0XJvc/yA3piNAPohLB1zyOBlIONLWJxI4kyKjhOM2mkIkJWmLKXOHGPnnqCUAx+
|
||||
+NzEZiJst22sngmHikN53zKyUfp2DO9CUY7hbjctAKo0GUC/Q0yQmL95idqnw56j
|
||||
Gv1deZcTth/1qUqcZRbQDT+546d87rDJLcQDXs/Q34IcmZa0v7jsIL5hJP+/PtOs
|
||||
fpyG
|
||||
-----END CERTIFICATE-----
|
||||
@@ -0,0 +1,27 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEA4YeW3U7wdqtN76P4cIpAbH0bd6eUoGOzevnvlH1CvC8WUS8C
|
||||
8JN0yEuy3FPkROnfFBzvAOvI6F+tZGIILTABhL2AtiVhgl4lG9+wmQSayDE6lPrR
|
||||
Z9s08gr6TQVOz7+rfzwCj3NF87a0BGe0ZqssAzG1rtgdTPOnopdBzeJ+HxjGJFZl
|
||||
Y5BySWDQoXJPnnZC+Kw5Cp24OAK9+5WGB6H60A1kwFvXg0EsVwT0G26gyAxzHV8B
|
||||
53wmyWSJIEOwpSu/DzerPQ0YGoL51yPL3Jclt/GEP3KpZAzZBgxnHwDoPQRrcEwF
|
||||
Hewbv6QI6wEf1kWOY3b9/vuP7Wom8+YSopXQOwIDAQABAoIBAGQK4Q3f2ARUHhjZ
|
||||
HDpT4ZsebiJIaMIzJ+k72J5+aC2RF63AlGXCi3HUPo3E+wPk2KuT4COA9Fi8JG7c
|
||||
m7Lr0iifZWqnL1eEyqJQOobOR5jZWZq/nkebMiPSYdDrs1ettvYUWTBoGpYvLDCu
|
||||
DhTjBn2OPgFG5cx+YxTZUvvw5jCFV7u7CDzC3dD/KvPuGdQPOjBnFM9p9NL7AfRw
|
||||
qOF4lw5M8ZT9caDuM/J77MuPXLVh5p6LlV9auVeo3s03E7BOw6Iutje0ZcBqKkjr
|
||||
lDV1QPkXCbbywW1YQDVv1kv9KgAEG1ftbGzq1REEX8SxNWDSzHl1Q04erqsJAI2y
|
||||
eO4RRVUCgYEA/8vgxZAF38605YPcddSzYzQLLABbQJP+1LFXM8fjpI7I5kb34QNN
|
||||
YY6tjhuha9fyOdFTZb3Qj5bA661Hh26BCwA9mc/X/49SJqzriQiZt9ZXVJ3ri8Xv
|
||||
N6N87ELr0uneVeP2zzjJS3E9G2fGqb2ZnRV3sdKpW2m+BNgOEmSdFrUCgYEA4bWL
|
||||
RhrnN9ZNHWRQTLZSX1ixb9HtFV9AbiPrVPbmzLiqmoV/kppIinr94T3ymlygBTBS
|
||||
mowlQViQbEfivmG12QNIs3W3nxBc2jw7vz3XYA/TANdQeNCW5mmgdKGN8IukVLHe
|
||||
tO4Vu5L7lOck+W+LYVgOTgp/c5tFSMPKB4COMS8CgYBbtfRDwQxqHsl61JkRYg5j
|
||||
DgDHaOVOtQETrvWN6ifzEwJylZVABpgS1z3gioWIjecZ1bQp8TE6mhlXJkxUAUmg
|
||||
8Rgk8oEF7pPMrAjSm9PJNr8e5nPSLEhFUYdzidbVSuZdMxuFVl3Nf68iCUYQC5ts
|
||||
14qPpfD0hmgLgo8hBxPPVQKBgEfy0gmv68K92mkjIAHEIK/qGu21MmkcqvIxGwRD
|
||||
jED4INIO+iKmcbdLC4DweVRBcHUW+U3wnLOe4rLRm3LqvMgHpvYl8TmQQrkCeF02
|
||||
/l/Ny4o6GJnajC+4vgBPu2pRaTniVUbBmkXnzbCimgO1Te3i3vR7njMg7M4MM2t+
|
||||
zFTbAoGBAKh9KJs6t6K6bK4I7L7zmRME4L7TCvzXfnqTJHYjXUIuAPDqTaNZAgCd
|
||||
pV45DfUWIIAis/RswLuR3yT6aH3Wpxx7fTW/DTInvBKfU7Kw2Oyko1jWboS/2E3D
|
||||
0HWVZzdbU4Hj48XGeldjgPV0D1/vr1JRTYJGXtjcNDkRMk3U3xrT
|
||||
-----END RSA PRIVATE KEY-----
|
||||
@@ -262,7 +262,7 @@ function main() {
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
const configuredVaults = getConfiguredVaults(options.configPath, options.baseConfigPath);
|
||||
const configuredVaults = getConfiguredVaults(options.configPath, options.baseConfigPath);
|
||||
const explicitVaults = options.vaults.map((vault) => (
|
||||
path.isAbsolute(vault) ? path.resolve(vault) : path.resolve(process.cwd(), vault)
|
||||
));
|
||||
@@ -307,6 +307,7 @@ function main() {
|
||||
console.log(JSON.stringify(payload, null, 2));
|
||||
} else {
|
||||
console.log('ServiceVault deprecation scan');
|
||||
console.log('- Deprecation count: ' + deprecationPatterns.length);
|
||||
console.log(`- Vault roots: ${vaultsToScan.length}`);
|
||||
console.log(`- Missing vault roots: ${missingVaults.length}`);
|
||||
console.log(`- Files scanned: ${filesToScan.length}`);
|
||||
|
||||