Skip to content

Commit

Permalink
Add WebUI for managing cookies
Browse files Browse the repository at this point in the history
  • Loading branch information
Piccirello committed Sep 15, 2024
1 parent 8532981 commit a44e606
Show file tree
Hide file tree
Showing 5 changed files with 207 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/webui/www/private/images/browser-cookies.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/webui/www/private/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ <h1 class="applicationTitle">qBittorrent Web User Interface <span class="version
<ul>
<li><a id="preferencesLink"><img class="MyMenuIcon" src="images/configure.svg" alt="QBT_TR(Options...)QBT_TR[CONTEXT=MainWindow]" width="16" height="16">QBT_TR(Options...)QBT_TR[CONTEXT=MainWindow]</a></li>
<li><a id="registerMagnetHandlerLink"><img class="MyMenuIcon" src="images/torrent-magnet.svg" alt="QBT_TR(Register to handle magnet links...)QBT_TR[CONTEXT=HttpServer]" width="16" height="16">QBT_TR(Register to handle magnet links...)QBT_TR[CONTEXT=HttpServer]</a></li>
<li><a id="manageCookiesLink"><img class="MyMenuIcon" src="images/browser-cookies.svg" alt="QBT_TR(Manage Cookies...)QBT_TR[CONTEXT=HttpServer]" width="16" height="16">QBT_TR(Manage Cookies...)QBT_TR[CONTEXT=HttpServer]</a></li>
</ul>
</li>
<li>
Expand Down
21 changes: 21 additions & 0 deletions src/webui/www/private/scripts/mocha-init.js
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,27 @@ const initializeWindows = function() {
});
});

addClickEvent("manageCookies", (e) => {
e.preventDefault();
e.stopPropagation();

const id = "cookiesPage";
new MochaUI.Window({
id: id,
title: "QBT_TR(Manage Cookies)QBT_TR[CONTEXT=CookiesDialog]",
loadMethod: "xhr",
contentURL: new URI("views/cookies.html").toString(),
maximizable: false,
paddingVertical: 0,
paddingHorizontal: 0,
width: loadWindowWidth(id, 900),
height: loadWindowHeight(id, 400),
onResize: function() {
saveWindowSize(id);
}
});
});

addClickEvent("upload", (e) => {
e.preventDefault();
e.stopPropagation();
Expand Down
182 changes: 182 additions & 0 deletions src/webui/www/private/views/cookies.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
<style>
#manageCookiesContainer {
margin: 10px;

.buttonContainer {
text-align: center;
margin-top: 1em;
}
}

#manageCookiesTable {
tbody {
td input {
width: 140px;
}

td.expDate input {
width: 190px;
}
}

thead td {
width: 150px;

.expDate {
width: 200px;
}

.actionColumn {
width: 30px;
}
}

.removeCookie,
.addCookie {
height: 16px;
width: 16px;
padding-left: 10px;
vertical-align: middle;
cursor: pointer;
}
}
</style>

<div id="manageCookiesContainer">
<table id="manageCookiesTable">
<thead>
<tr>
<td class="domain">QBT_TR(Domain)QBT_TR[CONTEXT=CookiesDialog]</td>
<td class="path">QBT_TR(Path)QBT_TR[CONTEXT=CookiesDialog]</td>
<td class="name">QBT_TR(Name)QBT_TR[CONTEXT=CookiesDialog]</td>
<td class="value">QBT_TR(Value)QBT_TR[CONTEXT=CookiesDialog]</td>
<td class="expDate">QBT_TR(Expiration Date)QBT_TR[CONTEXT=CookiesDialog]</td>
<td class="actionColumn"></td>
</tr>
</thead>
<tbody>
<tr class="invisible newRow">
<td class="domain"><input type="text" aria-label="QBT_TR(Domain)QBT_TR[CONTEXT=CookiesDialog]" autocomplete="off" autocorrect="off" autocapitalize="none"></td>
<td class="path"><input type="text" aria-label="QBT_TR(Path)QBT_TR[CONTEXT=CookiesDialog]" autocomplete="off" autocorrect="off" autocapitalize="none"></td>
<td class="name"><input type="text" aria-label="QBT_TR(Name)QBT_TR[CONTEXT=CookiesDialog]" autocomplete="off" autocorrect="off" autocapitalize="none"></td>
<td class="value"><input type="text" aria-label="QBT_TR(Value)QBT_TR[CONTEXT=CookiesDialog]" autocomplete="off" autocorrect="off" autocapitalize="none"></td>
<td class="expDate"><input type="datetime-local" aria-label="QBT_TR(Expiration Date)QBT_TR[CONTEXT=CookiesDialog]"></td>
<td><img class="removeCookie" src="images/list-remove.svg" onclick="qBittorrent.ManageCookies.deleteCookie(this);" alt="QBT_TR(Remove)QBT_TR[CONTEXT=CookiesDialog]"></td>
</tr>
</tbody>
<tfoot>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td><img class="addCookie" src="images/list-add.svg" onclick="qBittorrent.ManageCookies.addCookie();" alt="QBT_TR(Add Cookie)QBT_TR[CONTEXT=CookiesDialog]"></td>
</tr>
</tfoot>
</table>

<div class="buttonContainer">
<button type="button" onclick="qBittorrent.ManageCookies.save();">QBT_TR(Save)QBT_TR[CONTEXT=HttpServer]</button>
</div>
</div>

<script>
"use strict";

window.qBittorrent ??= {};
window.qBittorrent.ManageCookies ??= (() => {
const exports = () => {
return {
setup: setup,
addCookie: addCookie,
deleteCookie: deleteCookie,
save: save
};
};

const addCookie = function() {
const newRow = document.querySelector("#manageCookiesTable tr.newRow").cloneNode(true);
newRow.classList.remove("invisible");
document.querySelector("#manageCookiesTable tbody").append(newRow);
return newRow;
};

const deleteCookie = function(element) {
element.closest("tr").destroy();
};

const save = function() {
const rows = [...document.querySelectorAll("#manageCookiesTable tbody tr")].filter(e => !e.hasClass("invisible"));
const cookies = rows.map(row => {
const expDateValue = row.querySelector("td.expDate input").valueAsNumber;
// remove ms from string
const expDate = Number.isInteger(expDateValue) ? Number(String(expDateValue).slice(0, -3)) : 0;

return {
domain: row.querySelector("td.domain input").value,
path: row.querySelector("td.path input").value,
name: row.querySelector("td.name input").value,
value: row.querySelector("td.value input").value,
expirationDate: expDate,
};
});

new Request({
url: "api/v2/app/setCookies",
method: "post",
noCache: true,
data: {
cookies: JSON.stringify(cookies)
},
onFailure: (response) => {
let error = "Unable to save cookies";
if (response?.responseText)
error += `: ${response.responseText}`;
alert(error);
},
onSuccess: (response) => {
window.qBittorrent.Client.closeWindow("cookiesPage");
}
}).send();
};

const loadCookies = function() {
new Request.JSON({
url: "api/v2/app/cookies",
method: "get",
onFailure: (response) => {
let error = "Unable to load cookies";
if (response?.responseText)
error += `: ${response.responseText}`;
alert(error);
},
onSuccess: (response) => {
for (const cookie of response) {
const row = addCookie();
row.querySelector("td.domain input").value = cookie.domain;
row.querySelector("td.path input").value = cookie.path;
row.querySelector("td.name input").value = cookie.name;
row.querySelector("td.value input").value = cookie.value;
if (cookie.expirationDate > 0) {
// remove seconds + milliseconds, if any, to ensure seconds aren't displayed in input field
const date = new Date(cookie.expirationDate * 1000);
date.setSeconds(0);
date.setMilliseconds(0);
row.querySelector("td.expDate input").valueAsNumber = date.getTime();
}
}
}
}).send();
};

const setup = function() {
loadCookies();
};

return exports();
})();
Object.freeze(window.qBittorrent.ManageCookies);

window.qBittorrent.ManageCookies.setup();
</script>
2 changes: 2 additions & 0 deletions src/webui/www/webui.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
<file>private/images/application-rss.svg</file>
<file>private/images/application-url.svg</file>
<file>private/images/arrow-right.gif</file>
<file>private/images/browser-cookies.svg</file>
<file>private/images/checked-completed.svg</file>
<file>private/images/collapse.svg</file>
<file>private/images/configure.svg</file>
Expand Down Expand Up @@ -420,6 +421,7 @@
<file>private/views/about.html</file>
<file>private/views/aboutToolbar.html</file>
<file>private/views/confirmdeletion.html</file>
<file>private/views/cookies.html</file>
<file>private/views/filters.html</file>
<file>private/views/installsearchplugin.html</file>
<file>private/views/log.html</file>
Expand Down

0 comments on commit a44e606

Please sign in to comment.