diff --git a/public/index.html b/public/index.html
index 8b8b89c..e415752 100644
--- a/public/index.html
+++ b/public/index.html
@@ -71,6 +71,8 @@
+
+
diff --git a/public/script/app.js b/public/script/app.js
index a71f6df..062561a 100644
--- a/public/script/app.js
+++ b/public/script/app.js
@@ -671,6 +671,7 @@ angular
$scope.terms = "";
$scope.defaultTerms = "";
$scope.branches = [];
+ $scope.repositories = [];
$scope.source = {
type: "GitHubDownload",
branch: "",
@@ -709,6 +710,7 @@ angular
if (cb) cb();
});
}
+
getDefault(() => {
if ($routeParams.repoId && $routeParams.repoId != "") {
$scope.isUpdate = true;
@@ -753,8 +755,6 @@ angular
}
});
- $scope.repositories = [];
-
$scope.getRepositories = (force) => {
$http
.get("/api/user/all_repositories", {
@@ -798,46 +798,6 @@ angular
};
$('[data-toggle="tooltip"]').tooltip();
- $scope.$watch("source.branch", async (v) => {
- const selected = $scope.branches.filter(
- (f) => f.name == $scope.source.branch
- )[0];
- if ($scope.details && $scope.details.hasPage) {
- $scope.anonymize.page.$$element[0].disabled = false;
- if ($scope.details.pageSource.branch != $scope.source.branch) {
- $scope.anonymize.page.$$element[0].disabled = true;
- }
- }
-
- if (selected) {
- $scope.source.commit = selected.commit;
- $scope.readme = selected.readme;
- await getReadme();
- anonymize();
- $scope.$apply();
- }
- });
-
- $scope.$watch("options.mode", (v) => {
- if (v == "GitHubStream") {
- $scope.options.page = false;
- $scope.anonymize.page.$$element[0].disabled = true;
- } else {
- $scope.anonymize.page.$$element[0].disabled = false;
- }
- });
-
- function parseGithubUrl(url) {
- var matches = url.match(/.*?github.com\/([\w-\._]+)\/([\w-\._]+)/);
- if (matches && matches.length == 3) {
- return {
- owner: matches[1],
- repo: matches[2],
- };
- } else {
- throw "Invalid url";
- }
- }
$scope.getBranches = async (force) => {
const o = parseGithubUrl($scope.repoUrl);
const branches = await $http.get(
@@ -857,14 +817,7 @@ angular
}
$scope.$apply();
};
- function generateRandomId(length) {
- const alphabet = "ABCDEF0123456789";
- let output = "";
- for (let index = 0; index < length; index++) {
- output += alphabet[Math.round(Math.random() * (alphabet.length - 1))];
- }
- return output;
- }
+
async function getDetails() {
const o = parseGithubUrl($scope.repoUrl);
try {
@@ -962,7 +915,7 @@ angular
}
$scope.anonymize_readme = content;
- let html = marked($scope.anonymize_readme);
+ const html = marked($scope.anonymize_readme);
$scope.html_readme = $sce.trustAsHtml(html);
setTimeout(Prism.highlightAll, 150);
}
@@ -1026,13 +979,11 @@ angular
};
}
- $scope.anonymizeRepo = async (event) => {
- event.target.disabled = true;
+ async function sendRepo(url) {
resetValidity();
-
const newRepo = getRepo();
try {
- await $http.post("/api/repo/", newRepo, {
+ await $http.post(url, newRepo, {
headers: { "Content-Type": "application/json" },
});
window.location.href = "/status/" + $scope.repoId;
@@ -1045,34 +996,54 @@ angular
} else {
console.error(error);
}
- } finally {
- event.target.disabled = false;
}
- $scope.$apply();
+ }
+
+ $scope.anonymizeRepo = (event) => {
+ event.target.disabled = true;
+ sendRepo("/api/repo/").finally(() => {
+ event.target.disabled = false;
+ $scope.$apply();
+ });
};
$scope.updateRepo = async (event) => {
event.target.disabled = true;
- resetValidity();
-
- const newRepo = getRepo();
- try {
- await $http.post("/api/repo/" + newRepo.repoId, newRepo, {
- headers: { "Content-Type": "application/json" },
- });
- window.location.href = "/status/" + $scope.repoId;
- } catch (error) {
- if (error.data) {
- displayErrorMessage(error.data.error);
- } else {
- console.error(error);
- }
- } finally {
+ sendRepo("/api/repo/" + $scope.repoId).finally(() => {
event.target.disabled = false;
- }
- $scope.$apply();
+ $scope.$apply();
+ });
};
+ $scope.$watch("source.branch", async (v) => {
+ const selected = $scope.branches.filter(
+ (f) => f.name == $scope.source.branch
+ )[0];
+ if ($scope.details && $scope.details.hasPage) {
+ $scope.anonymize.page.$$element[0].disabled = false;
+ if ($scope.details.pageSource.branch != $scope.source.branch) {
+ $scope.anonymize.page.$$element[0].disabled = true;
+ }
+ }
+
+ if (selected) {
+ $scope.source.commit = selected.commit;
+ $scope.readme = selected.readme;
+ await getReadme();
+ anonymize();
+ $scope.$apply();
+ }
+ });
+
+ $scope.$watch("source.type", (v) => {
+ if (v == "GitHubStream") {
+ $scope.options.page = false;
+ $scope.anonymize.page.$$element[0].disabled = true;
+ } else {
+ $scope.anonymize.page.$$element[0].disabled = false;
+ }
+ });
+
$scope.$watch("terms", anonymize);
$scope.$watch("options.image", anonymize);
$scope.$watch("options.link", anonymize);
@@ -1206,7 +1177,7 @@ angular
}
if ($scope.type == "md") {
- const md = res.data;
+ const md = contentAbs2Relative(res.data);
$scope.content = marked(md, { baseUrl: $location.url() });
$scope.type = "html";
}
diff --git a/public/script/utils.js b/public/script/utils.js
new file mode 100644
index 0000000..ab87298
--- /dev/null
+++ b/public/script/utils.js
@@ -0,0 +1,104 @@
+function urlRel2abs(url) {
+ /* Only accept commonly trusted protocols:
+ * Only data-image URLs are accepted, Exotic flavours (escaped slash,
+ * html-entitied characters) are not supported to keep the function fast */
+ if (
+ /^(https?|file|ftps?|mailto|javascript|data:image\/[^;]{2,9};):/i.test(url)
+ ) {
+ return url; //Url is already absolute
+ }
+ var base_url = location.href.match(/^(.+)\/?(?:#.+)?$/)[0] + "/";
+ if (url.substring(0, 2) == "//") return location.protocol + url;
+ else if (url.charAt(0) == "/")
+ return location.protocol + "//" + location.host + url;
+ else if (url.substring(0, 2) == "./") url = "." + url;
+ else if (/^\s*$/.test(url)) return "";
+ //Empty = Return nothing
+ else url = "../" + url;
+
+ url = base_url + url;
+ var i = 0;
+ while (/\/\.\.\//.test((url = url.replace(/[^\/]+\/+\.\.\//g, ""))));
+
+ /* Escape certain characters to prevent XSS */
+ url = url
+ .replace(/\.$/, "")
+ .replace(/\/\./g, "")
+ .replace(/"/g, "%22")
+ .replace(/'/g, "%27")
+ .replace(//g, "%3E");
+ return url;
+}
+
+const charactersAttributes = "[^-a-z0-9:._]";
+const allTagCharacters = "(?:[^>\"']*(?:\"[^\"]*\"|'[^']*'))*?[^>]*";
+
+function by(match, group1, group2, group3) {
+ /* Note that this function can also be used to remove links:
+ * return group1 + "javascript://" + group3; */
+ return group1 + urlRel2abs(group2) + group3;
+}
+
+function cr(html, selector, attribute) {
+ if (typeof selector == "string") selector = new RegExp(selector, "gi");
+ attribute = charactersAttributes + attribute;
+ const marker = "\\s*=\\s*";
+ const end = ")(";
+ var re1 = new RegExp("(" + attribute + marker + '")([^"]+)()', "gi");
+ var re2 = new RegExp("(" + attribute + marker + "')([^']+)()", "gi");
+ var re3 = new RegExp(
+ "(" + attribute + marker + ")([^\"'][^\\s>]*" + end + ")",
+ "gi"
+ );
+ html = html.replace(selector, function (match) {
+ return match.replace(re1, by).replace(re2, by).replace(re3, by);
+ });
+ return html;
+}
+
+function contentAbs2Relative(content) {
+ if (!content) return content;
+ content = cr(
+ content,
+ "<" +
+ allTagCharacters +
+ charactersAttributes +
+ "href\\s*=" +
+ allTagCharacters +
+ ">",
+ "href"
+ );
+ content = cr(
+ content,
+ "<" +
+ allTagCharacters +
+ charactersAttributes +
+ "src\\s*=" +
+ allTagCharacters +
+ ">",
+ "src"
+ );
+ return content;
+}
+
+function generateRandomId(length) {
+ const alphabet = "ABCDEF0123456789";
+ let output = "";
+ for (let index = 0; index < length; index++) {
+ output += alphabet[Math.round(Math.random() * (alphabet.length - 1))];
+ }
+ return output;
+}
+
+function parseGithubUrl(url) {
+ var matches = url.match(/.*?github.com\/([\w-\._]+)\/([\w-\._]+)/);
+ if (matches && matches.length == 3) {
+ return {
+ owner: matches[1],
+ repo: matches[2],
+ };
+ } else {
+ throw "Invalid url";
+ }
+}