Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions lib/LANraragi/Utils/Routing.pm
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,18 @@ sub apply_routes {
# Routers used for all loginless routes
my $public_routes = $self->routes;

$public_routes->get( '/js/:version/*filepath' => [ version => qr/\d+\.\d+\.\d+/ ] )->to(
Copy link
Copy Markdown
Contributor

@psilabs-dev psilabs-dev May 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

paths need sanitization

Image

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Big oof!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The mojolicious path class is a bit "special" (never got mergeand contains to do anything useful), but I think I've managed to block that stuff now, albeit a bit heavy-handed.

cb => sub {
my $c = shift;

my $relFilePath = Mojo::Path->new( "/js/" . $c->stash('filepath') )->canonicalize;
return $c->reply->exception('Bad Request') unless index( $relFilePath, ".." ) == -1;

$c->res->headers->cache_control('public, max-age=31536000, immutable');
$c->reply->static($relFilePath);
}
);

# Normal route to controller
$public_routes->get('/login')->to('login#index');
$public_routes->post('/login')->to('login#check');
Expand Down
4 changes: 2 additions & 2 deletions public/js/backup.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
/**
* Backup Operations
*/
import * as Server from "mod/server";
import * as LRR from "mod/common";
import * as Server from "./mod/server.js";
import * as LRR from "./mod/common.js";
import I18N from "i18n";

let currentJob = null;

Check warning on line 8 in public/js/backup.js

View workflow job for this annotation

GitHub Actions / ESLint

'currentJob' is assigned a value but never used. Allowed unused vars must match /^_/u

function initializeAll() {
// bind events to DOM
Expand Down
4 changes: 2 additions & 2 deletions public/js/batch.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/**
* Batch Operations
*/
import * as LRR from "mod/common";
import * as Server from "mod/server";
import * as LRR from "./mod/common.js";
import * as Server from "./mod/server.js";
import I18N from "i18n";

const Batch = {};
Expand Down Expand Up @@ -42,7 +42,7 @@
return;
}
} catch (e) {
console.warn("Failed to parse msmSelection:", e);

Check warning on line 45 in public/js/batch.js

View workflow job for this annotation

GitHub Actions / ESLint

Unexpected console statement
}
}

Expand Down
4 changes: 2 additions & 2 deletions public/js/category.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
* Category Operations
*/

import * as LRR from "mod/common";
import * as Server from "mod/server";
import * as LRR from "./mod/common.js";
import * as Server from "./mod/server.js";
import I18N from "i18n";

const Category = {};
Expand Down
4 changes: 2 additions & 2 deletions public/js/config.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/**
* Config Operations
*/
import * as Server from "mod/server";
import * as LRR from "mod/common";
import * as Server from "./mod/server.js";
import * as LRR from "./mod/common.js";
import I18N from "i18n";

const Config = {};
Expand Down
4 changes: 2 additions & 2 deletions public/js/duplicates.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/**
* Duplicate Operations
*/
import * as LRR from "mod/common";
import * as Server from "mod/server";
import * as LRR from "./mod/common.js";
import * as Server from "./mod/server.js";
import I18N from "i18n";

const Duplicates = {};
Expand Down Expand Up @@ -72,7 +72,7 @@
Server.checkJobStatus(
job,
true,
(d) => {

Check warning on line 75 in public/js/duplicates.js

View workflow job for this annotation

GitHub Actions / ESLint

'd' is defined but never used. Allowed unused args must match /^_/u
// Refresh the window so that the newly found duplicates are shown.
// Make sure the URL doesn't contain delete=1 so we don't instantly delete them.
if (window.location.href.includes("delete=1")) {
Expand All @@ -93,7 +93,7 @@
);
}

Duplicates.drawCallbackDataTable = function (settings) {

Check warning on line 96 in public/js/duplicates.js

View workflow job for this annotation

GitHub Actions / ESLint

'settings' is defined but never used. Allowed unused args must match /^_/u
var groupColumn = 0;
var api = this.api();
var rows = api.rows({ page: "current" }).nodes();
Expand Down
4 changes: 2 additions & 2 deletions public/js/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
* JS functions meant for use in the Edit page.
* Mostly dealing with plugins.
*/
import * as Server from "mod/server";
import * as LRR from "mod/common";
import * as Server from "./mod/server.js";
import * as LRR from "./mod/common.js";
import I18N from "i18n";

const Edit = {};
Expand Down Expand Up @@ -83,7 +83,7 @@
};

Edit.addArchiveToTank = function () {
const tankId = $("#archiveID").val();

Check warning on line 86 in public/js/edit.js

View workflow job for this annotation

GitHub Actions / ESLint

'tankId' is assigned a value but never used. Allowed unused vars must match /^_/u
const arcId = $("#add-archive-id").val().trim();
if (!arcId) return;

Expand Down Expand Up @@ -233,7 +233,7 @@
Edit.hideTags();
const id = $("#archiveID").val();

let fetchPromise;

Check warning on line 236 in public/js/edit.js

View workflow job for this annotation

GitHub Actions / ESLint

'fetchPromise' is defined but never used. Allowed unused vars must match /^_/u

if (Edit.isTank) {
const metadata = {
Expand Down
2 changes: 1 addition & 1 deletion public/js/logs.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* Logs Operations
*/
import * as LRR from "mod/common";
import * as LRR from "./mod/common.js";
import I18N from "i18n";

const Logs = {};
Expand Down
6 changes: 3 additions & 3 deletions public/js/mod/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
import Swal from "sweetalert2";
import { ToastContainer, toast as emitToast } from "react-toastify";

import * as Index from "mod/index";
import * as Server from "mod/server";
import * as IndexTable from "mod/index_datatables";
import * as Index from "./index.js";
import * as Server from "./server.js";
import * as IndexTable from "./index_datatables.js";
import I18N from "i18n";

let toastsInitialized = false;
Expand All @@ -18,7 +18,7 @@
let cookies = document.cookie;
let val = cookies.split("; ").find((r) => r.startsWith("lrr_baseurl="))?.split("=")[1];
if (val === undefined) {
console.warn("lrr_baseurl cookie undefined, must be set by backend");

Check warning on line 21 in public/js/mod/common.js

View workflow job for this annotation

GitHub Actions / ESLint

Unexpected console statement
val = "";
}
return val;
Expand Down Expand Up @@ -50,7 +50,7 @@
this.load_url = load_url;
}
if (!this.load_url.startsWith("/")) {
console.trace("passed non-absolute URL to ApiURL");

Check warning on line 53 in public/js/mod/common.js

View workflow job for this annotation

GitHub Actions / ESLint

Unexpected console statement
this.load_url = "/" + this.load_url;
}
}
Expand Down
6 changes: 3 additions & 3 deletions public/js/mod/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
* Non-DataTables Index functions.
* (The split is there to permit easier switch if we ever yeet datatables from the main UI)
*/
import * as LRR from "mod/common";
import * as Server from "mod/server";
import * as IndexTable from "mod/index_datatables";
import * as LRR from "./common.js";
import * as Server from "./server.js";
import * as IndexTable from "./index_datatables.js";
import I18N from "i18n";
import * as marked from "marked";
import DOMPurify from "dompurify";

let selectedCategory = "";
let awesomplete = {};

Check warning on line 13 in public/js/mod/index.js

View workflow job for this annotation

GitHub Actions / ESLint

'awesomplete' is assigned a value but never used. Allowed unused vars must match /^_/u
let carouselInitialized = false;
let swiper = {};
let serverVersion = "";
Expand Down Expand Up @@ -233,7 +233,7 @@
Server.loadBookmarkCategoryId()
.then(() => loadCategories())
.then(() => IndexTable.initializeAll())
.catch(error => console.error("Error initializing index:", error));

Check warning on line 236 in public/js/mod/index.js

View workflow job for this annotation

GitHub Actions / ESLint

Unexpected console statement
});

const columnCountSelect = document.getElementById("columnCount");
Expand Down
4 changes: 2 additions & 2 deletions public/js/mod/index_datatables.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/**
* All the Archive Index functions related to DataTables.
*/
import * as LRR from "mod/common";
import * as Index from "mod/index";
import * as LRR from "./common.js";
import * as Index from "./index.js";
import I18N from "i18n";

export let dataTable = {};
Expand Down
2 changes: 1 addition & 1 deletion public/js/mod/server.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* Functions for Generic API calls.
*/
import * as LRR from "mod/common";
import * as LRR from "./common.js";
import I18N from "i18n";

let isScriptRunning = false;
Expand Down
4 changes: 2 additions & 2 deletions public/js/plugins.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/**
* Plugins Operations
*/
import * as Server from "mod/server";
import * as LRR from "mod/common";
import * as Server from "./mod/server.js";
import * as LRR from "./mod/common.js";
import I18N from "i18n";

const Plugins = {};
Expand Down
4 changes: 2 additions & 2 deletions public/js/reader.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
* Functions to navigate in reader with the keyboard.
* Also handles the thumbnail archive explorer.
*/
import * as Server from "mod/server";
import * as LRR from "mod/common";
import * as Server from "./mod/server.js";
import * as LRR from "./mod/common.js";
import I18N from "i18n";
import fscreen from "fscreen";

Expand Down
4 changes: 2 additions & 2 deletions public/js/stats.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
/**
* Stats Operations
*/
import * as Server from "mod/server";
import * as LRR from "mod/common";
import * as Server from "./mod/server.js";
import * as LRR from "./mod/common.js";
import I18N from "i18n";

const Stats = {};
Expand Down
4 changes: 2 additions & 2 deletions public/js/upload.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
* Scripting for the Upload page
*/

import * as LRR from "mod/common";
import * as Server from "mod/server";
import * as LRR from "./mod/common.js";
import * as Server from "./mod/server.js";
import I18N from "i18n";

let processingArchives = 0;
Expand Down
26 changes: 11 additions & 15 deletions templates/common/importmap.html.tt2
Original file line number Diff line number Diff line change
@@ -1,26 +1,22 @@
<script type="importmap">
{
"imports": {
"mod/common": "[% c.url_for("/js/mod/common.js?$version") %]",
"mod/server": "[% c.url_for("/js/mod/server.js?$version") %]",
"mod/index": "[% c.url_for("/js/mod/index.js?$version") %]",
"mod/index_datatables": "[% c.url_for("/js/mod/index_datatables.js?$version") %]",
"i18n": "[% c.url_for("/js/i18n.js?$version") %]",
"fscreen": "[% c.url_for("/js/vendor/fscreen.esm.js") %]",
"fscreen": "[% c.url_for("/js/$version/vendor/fscreen.esm.js") %]",

"preact": "[% c.url_for("/js/vendor/preact.module.js") %]",
"preact/hooks": "[% c.url_for("/js/vendor/hooks.module.js") %]",
"preact/compat": "[% c.url_for("/js/vendor/compat.module.js") %]",
"clsx": "[% c.url_for("/js/vendor/clsx.m.js") %]",
"react-toastify": "[% c.url_for("/js/vendor/react-toastify.esm.js") %]",
"preact": "[% c.url_for("/js/$version/vendor/preact.module.js") %]",
"preact/hooks": "[% c.url_for("/js/$version/vendor/hooks.module.js") %]",
"preact/compat": "[% c.url_for("/js/$version/vendor/compat.module.js") %]",
"clsx": "[% c.url_for("/js/$version/vendor/clsx.m.js") %]",
"react-toastify": "[% c.url_for("/js/$version/vendor/react-toastify.esm.js") %]",

"react": "[% c.url_for("/js/vendor/compat.module.js") %]",
"react-dom": "[% c.url_for("/js/vendor/compat.module.js") %]",
"react": "[% c.url_for("/js/$version/vendor/compat.module.js") %]",
"react-dom": "[% c.url_for("/js/$version/vendor/compat.module.js") %]",

"marked": "[% c.url_for("/js/vendor/marked.esm.js?$version") %]",
"dompurify": "[% c.url_for("/js/vendor/purify.js?$version") %]",
"marked": "[% c.url_for("/js/$version/vendor/marked.esm.js?$version") %]",
"dompurify": "[% c.url_for("/js/$version/vendor/purify.js?$version") %]",

"sweetalert2": "[% c.url_for("/js/vendor/sweetalert2.esm.min.js") %]"
"sweetalert2": "[% c.url_for("/js/$version/vendor/sweetalert2.esm.min.js") %]"
}
}
</script>
2 changes: 1 addition & 1 deletion templates/edit.html.tt2
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
<script src="[% c.url_for("/js/edit.js?$version") %]" type="module"></script>

<script type="module">
import * as IndexTable from "mod/index_datatables";
import * as IndexTable from "[% c.url_for("/js/$version/mod/index_datatables.js") %]";

jQuery(() => {
window.IndexTable = IndexTable;
Expand Down
8 changes: 4 additions & 4 deletions templates/index.html.tt2
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@
<script src="[% c.url_for("/js/vendor/clipboard.min.js") %]" type="text/JAVASCRIPT"></script>

<script type="module">
import * as Index from "mod/index";
import * as IndexTable from "mod/index_datatables";
import * as LRR from "mod/common";
import * as Index from "[% c.url_for("/js/$version/mod/index.js") %]";
import * as IndexTable from "[% c.url_for("/js/$version/mod/index_datatables.js") %]";
import * as LRR from "[% c.url_for("/js/$version/mod/common.js") %]";

jQuery(() => {
Index.initializeAll();
Expand Down Expand Up @@ -195,7 +195,7 @@
<button id="pseudo-copy-btn" data-clipboard-text="" style="display: none">click me</button>

<script type="module">
import * as Index from "mod/index";
import * as Index from "[% c.url_for("/js/$version/mod/index.js") %]";
import I18N from "i18n";

// Last few remains of JS using server-provided data
Expand Down
Loading