Skip to content

Commit 16db66e

Browse files
author
ComputerElite
committed
add downgrading support
1 parent 7255cfa commit 16db66e

25 files changed

+1950
-33
lines changed

Assets/html/downgrade.html

Lines changed: 565 additions & 0 deletions
Large diffs are not rendered by default.

Assets/html/index.html

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
</div>
1515
</div>
1616
<div class="menuItem" section="backup">Backup</div>
17+
<div class="menuItem" section="downgrade">Downgrade</div>
18+
<div class="menuItem" section="download">Download progress</div>
1719
<div class="menuItem selected" section="tools">Tools & Options</div>
1820
</div>
1921
<div class="content">
@@ -56,6 +58,15 @@
5658
<div id="backupTextBox" class="textBox"></div>
5759
</div>
5860
</div>
61+
<div class="contentItem hidden" id="downgrade" style="padding: 0px;">
62+
<iframe src="downgrade.html" style="width: 100%; height: 100%; border: none; overflow-y: visible;"></iframe>
63+
</div>
64+
<div class="contentItem hidden" id="download">
65+
<div id="progressBarContainers">
66+
67+
</div>
68+
69+
</div>
5970
<div class="contentItem" id="tools">
6071
<div class="contentHeader">
6172
Tools
@@ -69,6 +80,27 @@
6980
<div class="button" id="changeApp">Change app</div>
7081
<div class="buttonLabel">Change the app you want to manage</div>
7182
</div>
83+
84+
<div class="space">
85+
<div class="contentHeader">
86+
Token Section
87+
<div class="contentHeaderDescription">Set your token for downgrading games</div>
88+
</div>
89+
<div class="buttonContainer">
90+
<div>Oculus Token <a style="text-weight: bold;" href="https://computerelite.github.io/tools/Oculus/ObtainToken.html">Guide to get the token</a></div>
91+
<input type="password" placeholder="Token" id="token" class="buttonLabel" style="width: 600px;">
92+
</div>
93+
<div class="buttonContainer">
94+
<div>Password for encryption (This password will encrypt your token. Make sure you've used it nowhere else)</div>
95+
<input type="password" placeholder="Password" id="password" class="buttonLabel" style="width: 600px;">
96+
</div>
97+
<div class="buttonContainer">
98+
<div class="button" id="saveToken">Save Token</div>
99+
<div class="buttonLabel">Saves the token so you can downgrade games</div>
100+
</div>
101+
<div id="tokenTextBox" class="textBox"></div>
102+
</div>
103+
72104
<div class="space">
73105
All Backups together take up <b class="inline totalSize"></b> of space on your Device.
74106
<br>
@@ -243,6 +275,44 @@
243275
document.getElementById("appListContainer").className = "listContainer hidden"
244276
}
245277

278+
document.getElementById("saveToken").onclick = () => {
279+
if(!document.getElementById("token").value.startsWith("OC")) {
280+
TextBoxError("tokenTextBox", "Please copy your token again. It is not valid")
281+
return
282+
}
283+
if(document.getElementById("password").value.length < 8) {
284+
TextBoxError("tokenTextBox", "Password must be at least 8 characters long")
285+
return
286+
}
287+
fetch("/token", {
288+
method: "POST",
289+
body: JSON.stringify({
290+
token: document.getElementById("token").value,
291+
password: document.getElementById("password").value
292+
})
293+
}).then(res => {
294+
TextBoxGood("tokenTextBox", "Token set. You can now downgrade games")
295+
})
296+
}
297+
298+
setInterval(() => {
299+
fetch("/downloads").then(res => {
300+
res.json().then(json => {
301+
document.getElementById("progressBarContainers").innerHTML = ""
302+
json.forEach(d => {
303+
document.getElementById("progressBarContainers").innerHTML += `<div class="downloadContainer">
304+
<div class="downloadProgressContainer">
305+
<div class="downloadProgressBar" style="width: ${d.percentage * 100}%;"></div>
306+
</div>
307+
<div class="DownloadText" style="color: ${d.textColor};">
308+
${d.backupName} ${d.percentageString} ${d.doneString} / ${d.totalString} ${d.speedString} ETA ${d.eTAString}
309+
</div>
310+
</div>`
311+
})
312+
})
313+
})
314+
}, 500)
315+
246316
function ShowAppList() {
247317
document.getElementById("appList").innerHTML = undefinedLoader
248318
document.getElementById("appList").className = "list"

Assets/html/style.css

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,32 @@
1414

1515
}
1616

17+
.downloadContainer {
18+
width: 100%;
19+
display: flex;
20+
margin-bottom: 20px;
21+
}
22+
23+
.downloadProgressContainer {
24+
min-width: 500px;
25+
height: 20px;
26+
background-color: #777777;
27+
}
28+
29+
.downloadProgressBar {
30+
height: 100%;
31+
background-color: #1a83da;
32+
}
33+
1734
.sidebar {
1835
background-color: #242424;
1936
width: fit-content;
2037
}
2138

39+
.downloadText {
40+
margin-left: 10px;
41+
}
42+
2243
.content {
2344
height: 100%;
2445
width: 100%;

ClientModels.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,35 @@ public class BackupList
3333
public long backupsSize { get; set; } = 0;
3434
public string backupsSizeString { get; set; } = "";
3535
}
36+
37+
public class TokenRequest
38+
{
39+
public string token { get; set; } = "";
40+
public string password { get; set; } = "";
41+
}
42+
43+
public class DownloadRequest
44+
{
45+
public long binaryId { get; set; } = 0;
46+
public string password { get; set; } = "";
47+
public string version { get; set; } = "";
48+
public string app { get; set; } = "";
49+
}
50+
51+
public class DownloadProgress
52+
{
53+
public double percentage { get; set; } = 0.0;
54+
public string percentageString { get; set; } = "";
55+
public long done { get; set; } = 0;
56+
public long total { get; set; } = 0;
57+
public long speed { get; set; } = 0;
58+
public long eTASeconds { get; set; } = 0;
59+
public string doneString { get; set; } = "0 Bytes";
60+
public string totalString { get; set; } = "0 Bytes";
61+
public string speedString { get; set; } = "0 Bytes/s";
62+
public string eTAString { get; set; } = "";
63+
public string name { get; set; } = "";
64+
public string backupName { get; set; } = "";
65+
public string textColor { get; set; } = "#EEEEEE";
66+
}
3667
}

Core/CoreService.cs renamed to CoreService.cs

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using Android.Content.Res;
55
using Android.Webkit;
66
using AndroidX.Core.App;
7+
using ComputerUtils.Android.FileManaging;
78
using ComputerUtils.Android.Logging;
89
using System;
910
using System.IO;
@@ -17,7 +18,7 @@ namespace QuestAppVersionSwitcher.Core
1718
public class CoreService
1819
{
1920
public static WebView browser = null;
20-
public static QAVSWebserver qPWebserver = new QAVSWebserver();
21+
public static QAVSWebserver qAVSWebserver = new QAVSWebserver();
2122
public static CoreVars coreVars = new CoreVars();
2223
public static Version version = Assembly.GetExecutingAssembly().GetName().Version;
2324
public void Start()
@@ -45,16 +46,12 @@ public void Start()
4546
browser.Settings.UseWideViewPort = true;
4647

4748
// Create all directories and files
48-
if (!Directory.Exists(coreVars.QAVSDir)) Directory.CreateDirectory(coreVars.QAVSDir);
49-
if (!Directory.Exists(coreVars.QAVSBackupDir)) Directory.CreateDirectory(coreVars.QAVSBackupDir);
50-
if (File.Exists(coreVars.QAVSConfigLocation))
51-
{
52-
coreVars = JsonSerializer.Deserialize<CoreVars>(File.ReadAllText(coreVars.QAVSConfigLocation));
53-
} else
54-
{
55-
File.WriteAllText(coreVars.QAVSConfigLocation, JsonSerializer.Serialize(coreVars));
56-
}
57-
qPWebserver.Start();
49+
FileManager.CreateDirectoryIfNotExisting(coreVars.QAVSDir);
50+
FileManager.CreateDirectoryIfNotExisting(coreVars.QAVSBackupDir);
51+
FileManager.RecreateDirectoryIfExisting(coreVars.QAVDTmpDowngradeDir);
52+
if (!File.Exists(coreVars.QAVSConfigLocation)) File.WriteAllText(coreVars.QAVSConfigLocation, JsonSerializer.Serialize(coreVars));
53+
coreVars = JsonSerializer.Deserialize<CoreVars>(File.ReadAllText(coreVars.QAVSConfigLocation));
54+
qAVSWebserver.Start();
5855
}
5956
}
6057
}

Core/CoreVars.cs renamed to CoreVars.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ namespace QuestAppVersionSwitcher.Core
66
public class CoreVars // aka config
77
{
88
public string currentApp { get; set; } = "";
9+
public string token { get; set; } = "";
910
public readonly string QAVSDir = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath + "/QuestAppVersionSwitcher/";
11+
public readonly string QAVDTmpDowngradeDir = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath + "/QuestAppVersionSwitcher/tmpDowngrade/";
1012
public readonly string QAVSBackupDir = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath + "/QuestAppVersionSwitcher/Backups/";
1113
public readonly string QAVSConfigLocation = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath + "/QuestAppVersionSwitcher/config.json";
1214
public readonly string AndroidAppLocation = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath + "/Android/data/";

DownloadManager.cs

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
using ComputerUtils.Android.Encryption;
2+
using ComputerUtils.Android.Logging;
3+
using ComputerUtils.Android.VarUtils;
4+
using QuestAppVersionSwitcher.ClientModels;
5+
using QuestAppVersionSwitcher.Core;
6+
using System;
7+
using System.Collections.Generic;
8+
using System.IO;
9+
using System.Net;
10+
using System.Text.Json;
11+
12+
namespace QuestAppVersionSwitcher
13+
{
14+
public class DownloadManager : DownloadProgress
15+
{
16+
public delegate void DownloadFinished(DownloadManager manager);
17+
public event DownloadFinished DownloadFinishedEvent;
18+
public string tmpPath = "";
19+
20+
public void StartDownload(long binaryid, string password, string version, string app)
21+
{
22+
string decodedToken = PasswordEncryption.Decrypt(CoreService.coreVars.token, password);
23+
WebClient downloader = new WebClient();
24+
tmpPath = CoreService.coreVars.QAVDTmpDowngradeDir + DateTime.Now.Ticks + ".apk";
25+
List<long> lastBytesPerSec = new List<long>();
26+
DateTime lastUpdate = DateTime.Now;
27+
bool locked = false;
28+
long BytesToRecieve = 0;
29+
long lastBytes = 0;
30+
this.name = app + " " + version;
31+
this.backupName = this.name + " Downgraded";
32+
foreach (char r in QAVSWebserver.ReservedChars)
33+
{
34+
this.backupName = this.backupName.Replace(r, '_');
35+
}
36+
downloader.DownloadProgressChanged += (o, e) =>
37+
{
38+
if (locked) return;
39+
40+
locked = true;
41+
double secondsPassed = (DateTime.Now - lastUpdate).TotalSeconds;
42+
if (secondsPassed >= 0.5)
43+
{
44+
BytesToRecieve = e.TotalBytesToReceive;
45+
string current = SizeConverter.ByteSizeToString(e.BytesReceived);
46+
string total = SizeConverter.ByteSizeToString(BytesToRecieve);
47+
long bytesPerSec = (long)Math.Round((e.BytesReceived - lastBytes) / secondsPassed);
48+
lastBytesPerSec.Add(bytesPerSec);
49+
if (lastBytesPerSec.Count > 5) lastBytesPerSec.RemoveAt(0);
50+
lastBytes = e.BytesReceived;
51+
long avg = 0;
52+
foreach (long l in lastBytesPerSec) avg += l;
53+
avg = avg / lastBytesPerSec.Count;
54+
this.done = e.BytesReceived;
55+
this.total = BytesToRecieve;
56+
this.speed = bytesPerSec;
57+
this.eTASeconds = (e.TotalBytesToReceive - e.BytesReceived) / avg;
58+
this.doneString = SizeConverter.ByteSizeToString(this.done);
59+
this.totalString = SizeConverter.ByteSizeToString(this.total);
60+
this.speedString = SizeConverter.ByteSizeToString(this.speed, 0) + "/s";
61+
this.eTAString = SizeConverter.SecondsToBetterString(this.eTASeconds);
62+
this.percentage = this.done / (double)this.total;
63+
this.percentageString = String.Format("{0:0.#}", this.percentage * 100) + "%";
64+
lastUpdate = DateTime.Now;
65+
}
66+
locked = false;
67+
};
68+
downloader.DownloadFileCompleted += (o, e) =>
69+
{
70+
if (e.Error != null)
71+
{
72+
Logger.Log(e.Error.ToString(), LoggingType.Error);
73+
if (File.Exists(tmpPath)) File.Delete(tmpPath);
74+
SetEmpty();
75+
this.backupName = "Unknown Error: Have you entered your token in the Tools & Options section? Doing this is needed. Otherwise you don't own the game you are trying to download.";
76+
this.textColor = "#EE0000";
77+
}
78+
else
79+
{
80+
DownloadFinishedEvent(this);
81+
this.backupName = "Done: restore " + backupName + " to downgrade your game any time";
82+
this.textColor = "#30e34b";
83+
}
84+
};
85+
downloader.DownloadFileAsync(new Uri("https://securecdn.oculus.com/binaries/download/?id=" + binaryid + "&access_token=" + decodedToken), tmpPath);
86+
}
87+
88+
public void SetEmpty(bool alsoSize = true)
89+
{
90+
91+
this.speed = 0;
92+
this.eTASeconds = 0;
93+
if(alsoSize)
94+
{
95+
this.done = 0;
96+
this.total = 0;
97+
this.doneString = "";
98+
this.totalString = "";
99+
this.percentage = 0;
100+
this.percentageString = "";
101+
}
102+
this.speedString = "";
103+
this.eTAString = "";
104+
}
105+
}
106+
}

Properties/AndroidManifest.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?xml version="1.0" encoding="utf-8"?>
2-
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="1.0.2" package="com.ComputerElite.questappversionswitcher" android:installLocation="preferExternal" android:versionCode="3">
2+
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="1.1.0" package="com.ComputerElite.questappversionswitcher" android:installLocation="preferExternal" android:versionCode="4">
33
<uses-sdk android:minSdkVersion="29" android:targetSdkVersion="29" />
44
<uses-permission android:name="oculus.permission.handtracking" />
55
<uses-permission android:name="com.oculus.permission.HAND_TRACKING" />

Properties/AssemblyInfo.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,5 @@
2222
// Minor Version
2323
// Build Number
2424
// Revision
25-
[assembly: AssemblyVersion("1.0.0.0")]
26-
[assembly: AssemblyFileVersion("1.0.0.0")]
25+
[assembly: AssemblyVersion("1.1.0.0")]
26+
[assembly: AssemblyFileVersion("1.1.0.0")]

QuestAppVersionSwitcher.csproj

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
</PropertyGroup>
6363
<ItemGroup>
6464
<Reference Include="System" />
65+
<Reference Include="System.IO.Compression.FileSystem" />
6566
<Reference Include="System.Json" />
6667
<Reference Include="System.Xml" />
6768
<Reference Include="System.Core" />
@@ -71,14 +72,29 @@
7172
</ItemGroup>
7273
<ItemGroup>
7374
<Compile Include="ClientModels.cs" />
74-
<Compile Include="Core\CoreService.cs" />
75-
<Compile Include="Core\CoreVars.cs" />
75+
<Compile Include="CoreService.cs" />
76+
<Compile Include="CoreVars.cs" />
77+
<Compile Include="DownloadManager.cs" />
7678
<Compile Include="MainActivity.cs" />
79+
<Compile Include="QuestPatcher.Axaml\AttributeType.cs" />
80+
<Compile Include="QuestPatcher.Axaml\AxmlAttribute.cs" />
81+
<Compile Include="QuestPatcher.Axaml\AxmlElement.cs" />
82+
<Compile Include="QuestPatcher.Axaml\AxmlLoader.cs" />
83+
<Compile Include="QuestPatcher.Axaml\AxmlParseException.cs" />
84+
<Compile Include="QuestPatcher.Axaml\AxmlSaver.cs" />
85+
<Compile Include="QuestPatcher.Axaml\BinaryStreamExtensions.cs" />
86+
<Compile Include="QuestPatcher.Axaml\ResourceType.cs" />
87+
<Compile Include="QuestPatcher.Axaml\SavingContext.cs" />
88+
<Compile Include="QuestPatcher.Axaml\StringPool.cs" />
89+
<Compile Include="QuestPatcher.Axaml\WrappedValue.cs" />
7790
<Compile Include="Resources\Resource.designer.cs" />
7891
<Compile Include="Properties\AssemblyInfo.cs" />
7992
<Compile Include="WebServer.cs" />
8093
</ItemGroup>
8194
<ItemGroup>
95+
<None Include="QuestPatcher.Axaml\LICENSE" />
96+
<None Include="QuestPatcher.Axaml\QuestPatcher.Axml.csproj" />
97+
<None Include="QuestPatcher.Axaml\README.md" />
8298
<None Include="Resources\AboutResources.txt" />
8399
<None Include="Properties\AndroidManifest.xml" />
84100
<None Include="Assets\AboutAssets.txt" />
@@ -113,6 +129,9 @@
113129
<Folder Include="Resources\drawable\" />
114130
</ItemGroup>
115131
<ItemGroup>
132+
<PackageReference Include="System.IO.Compression">
133+
<Version>4.3.0</Version>
134+
</PackageReference>
116135
<PackageReference Include="System.Text.Json">
117136
<Version>5.0.2</Version>
118137
</PackageReference>
@@ -134,6 +153,7 @@
134153
</ItemGroup>
135154
<ItemGroup>
136155
<Content Include=".gitignore" />
156+
<AndroidAsset Include="Assets\html\downgrade.html" />
137157
</ItemGroup>
138158
<ItemGroup>
139159
<ProjectReference Include="..\..\ComputerUtils\ComputerUtils.Android\ComputerUtils.Android.csproj">

0 commit comments

Comments
 (0)