summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tails-download-and-verify/conf.json2
-rw-r--r--tails-download-and-verify/lib/downloader.js95
2 files changed, 79 insertions, 18 deletions
diff --git a/tails-download-and-verify/conf.json b/tails-download-and-verify/conf.json
index 02be0a7..59afc60 100644
--- a/tails-download-and-verify/conf.json
+++ b/tails-download-and-verify/conf.json
@@ -1,7 +1,7 @@
{
"descriptor": "https://tails.boum.org/install/v1/Tails/i386/stable/latest.yml",
"fallback_download_url_prefix": "http://dl.amnesia.boum.org/tails",
- "mirror_pool_url": "https://tails.boum.org/example-mirrors.json",
+ "mirror_pool_url": "https://tails.boum.org/mirrors.json",
"pinGlobally": true,
"pins": {
"domains": {
diff --git a/tails-download-and-verify/lib/downloader.js b/tails-download-and-verify/lib/downloader.js
index 00a41dc..1eaf056 100644
--- a/tails-download-and-verify/lib/downloader.js
+++ b/tails-download-and-verify/lib/downloader.js
@@ -75,7 +75,11 @@ function startDownload(source, target, prompt = lastPrompt) {
});
return;
}
- source = { url: url, isPrivate: true };
+ let tab = require("sdk/tabs").activeTab;
+ source = { url: url };
+ if (tab && require("sdk/private-browsing").isPrivate(tab)) {
+ source.isPrivate = true;
+ }
Downloads.createDownload({source: source, target: { path: target.path || target, partFilePath: `${target}.part` }})
.then(download => {
download.tryToKeepPartialData = true;
@@ -97,9 +101,6 @@ function tailsReconnectionFailure(download) {
try {
let f = file(target.path);
let targetFile = f.clone();
- try {
- } catch (e) {
- }
const permissions = parseInt("700", 8);
try {
f.permissions = permissions;
@@ -123,14 +124,51 @@ function tailsReconnectionFailure(download) {
return true;
}
+// Return another, random mirror download URL & exclude the current mirror.
+function tryAnotherMirror(download, fallback_download_url_prefix=blob.fallback_download_url_prefix, url_suffix=blob.url_suffix, mirrors=blob.mirrors) {
+ if (! download.source.url.endsWith(url_suffix)) {
+ throw new Error(`${download.source.url} must end with ${url_suffix}`);
+ }
+ let current_mirror = compareUrlToMirrors(download.source.url, mirrors, url_suffix);
+ if (current_mirror !== false) {
+ delete mirrors.mirrors[current_mirror];
+ }
+ blob.url = download.source.url = require('./mirror-dispatcher').transformURL(
+ fallback_download_url_prefix + url_suffix,
+ fallback_download_url_prefix,
+ mirrors
+ );
+ console.log("Trying to resume download from another mirror: " + download.source.url);
+ return download;
+}
+
+// Return the index, in the mirror list, of the mirror corresponding to a given
+// URL, if one is found. Else, return false.
+function compareUrlToMirrors(testurl, mirrors, url_suffix=blob.url_suffix) {
+ if (! testurl.endsWith(url_suffix)) {
+ throw new Error(`${testurl} must end with ${url_suffix}`);
+ }
+ console.log("Tested URL to compare against mirrors: " + testurl);
+ for (let m_url = 0; m_url < mirrors.length; m_url++) {
+ console.log("Mirror URL to compare against " + mirrors.mirrors[m_url].url_prefix + url_suffix);
+ if (mirrors.mirrors[m_url].url_prefix + url_suffix == testurl && mirrors.mirrors[m_url].weight > 0) {
+ console.log("Download URL corresponds to a known active mirror: " + mirrors.mirrors[m_url].url_prefix);
+ return m_url; // just return the index.
+ }
+ }
+ return false;
+}
function checkDownload(download, batch) {
+
if (!blob.url || /^verif/.test(status.phase) && !status.failed) return false;
+
if (download === curDownload) return true;
console.log(`checkDownload: ${curDownload}
${download.source.url}/${blob.url}
${download.currentBytes}, ${download.stopped}, ${download.error}
`);
+
if (download.source.url !== blob.url ||
download.currentBytes === 0 && download.stopped && !download.error) return false;
if (curDownload) {
@@ -303,7 +341,7 @@ function selectDescriptor(contentURL) {
}
function setup(contentURL) {
- var fallback_download_url_prefix = Config.fallback_download_url_prefix;
+ var fallback_download_url_prefix = blob.fallback_download_url_prefix = Config.fallback_download_url_prefix;
var mirrors;
var mirror_pool_url = Config.mirror_pool_url;
@@ -321,30 +359,49 @@ function setup(contentURL) {
let df = require('./df').parse(data);
if (!df) fail(`Could not parse ${url}\n${data}`);
else {
- if (data !== cachedDescriptor || status.phase === 'init') {
+ if (data !== cachedDescriptor || status.phase === 'init') {
reset();
cachedDescriptor = data;
Object.assign(blob, df);
+
+ if (! blob.url.startsWith(fallback_download_url_prefix)) {
+ throw new Error(`${blob.url} must start with ${fallback_download_url_prefix}`);
+ }
+ // Store url_suffix in blob, tryAnotherMirror needs it
+ blob.url_suffix = blob.url.substr(fallback_download_url_prefix.length)
+
// instead of using the URL from the YAML, we want to use a URL from our new mirror pool
- console.log("Unmodified download URL: ", blob.url)
+ console.log("Unmodified download URL: ", blob.url);
blob.url = require('./mirror-dispatcher').transformURL(blob.url, fallback_download_url_prefix, mirrors);
- console.log("Modified download URL: ", blob.url)
- }
- if (!curDownload || curDownload.source.url !== blob.url) {
+ console.log("Modified download URL: ", blob.url);
+
+ // Assigning mirrors to blob so that we can later use them to check against existing downloads. Mirrors are stored as JSON array.
+ blob.mirrors = mirrors;
+ }
+
+ // check if any of the mirror urls matches with curDownload.source.url
+ // if yes, assign curDownload.source.url to blob.url so that we can continue the download.
+ if (blob.mirrors) {
+ if (curDownload && compareUrlToMirrors(curDownload.source.url, blob.mirrors, blob.url_suffix) !== false) {
+ blob.url = curDownload.source.url;
+ }
+ }
+
+ if (!curDownload || curDownload.source.url !== blob.url) {
curDownload = null;
status.phase = 'ready';
- }
- checkDownloadList();
- if (curDownload && status.phase === 'init') status.phase = 'started';
- console.log(`Setup ${curDownload} phase ${status.phase}`);
- notify();
+ }
+ checkDownloadList();
+ if (curDownload && status.phase === 'init') status.phase = 'started';
+ console.log(`Setup ${curDownload} phase ${status.phase}`);
+ notify();
}
}, fail);
}, fail);
}
function notify(statusChanges) {
-
+
if (statusChanges) Object.assign(status, statusChanges);
if (curDownload && /^download/.test(status.phase)) {
status.downloadInfo = {
@@ -399,9 +456,13 @@ var api = {
this.start();
}
},
+
resume() {
reset(status.phase);
- if (curDownload && !tailsReconnectionFailure(curDownload)) {
+ if (curDownload) {
+ if (curDownload.error && curDownload.error.becauseSourceFailed) {
+ curDownload = tryAnotherMirror(curDownload);
+ }
curDownload.start();
}
},