summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorleonklingele <git@leonklingele.de>2020-03-16 06:46:08 +0900
committerGitHub <noreply@github.com>2020-03-15 16:46:08 -0500
commit70cbe91776d1de10f2767c6a5ad5912fd705bdd3 (patch)
tree2ab21e5b82d7018c766253008076c8e49c3aa5e5 /src
parentf92027c44b043c19188ce9945c3f05e6dc90de5a (diff)
downloadinvidious-70cbe91776d1de10f2767c6a5ad5912fd705bdd3.tar.gz
invidious-70cbe91776d1de10f2767c6a5ad5912fd705bdd3.tar.bz2
invidious-70cbe91776d1de10f2767c6a5ad5912fd705bdd3.zip
Migrate to a good Content Security Policy (#1023)
So attacks such as XSS (see [0]) will no longer be of an issue. [0]: https://github.com/omarroth/invidious/issues/1022
Diffstat (limited to 'src')
-rw-r--r--src/invidious.cr20
-rw-r--r--src/invidious/comments.cr8
-rw-r--r--src/invidious/views/add_playlist_items.ecr6
-rw-r--r--src/invidious/views/community.ecr16
-rw-r--r--src/invidious/views/components/item.ecr15
-rw-r--r--src/invidious/views/components/player.ecr17
-rw-r--r--src/invidious/views/components/player_sources.ecr1
-rw-r--r--src/invidious/views/components/subscribe_widget.ecr16
-rw-r--r--src/invidious/views/embed.ecr33
-rw-r--r--src/invidious/views/history.ecr10
-rw-r--r--src/invidious/views/playlist.ecr6
-rw-r--r--src/invidious/views/preferences.ecr10
-rw-r--r--src/invidious/views/subscription_manager.ecr33
-rw-r--r--src/invidious/views/subscriptions.ecr6
-rw-r--r--src/invidious/views/template.ecr9
-rw-r--r--src/invidious/views/token_manager.ecr33
-rw-r--r--src/invidious/views/watch.ecr34
17 files changed, 100 insertions, 173 deletions
diff --git a/src/invidious.cr b/src/invidious.cr
index e89c2c37..800af0dd 100644
--- a/src/invidious.cr
+++ b/src/invidious.cr
@@ -248,10 +248,20 @@ spawn do
end
before_all do |env|
- host_url = make_host_url(config, Kemal.config)
+ begin
+ preferences = Preferences.from_json(env.request.cookies["PREFS"]?.try &.value || "{}")
+ rescue
+ preferences = Preferences.from_json("{}")
+ end
+
env.response.headers["X-XSS-Protection"] = "1; mode=block"
env.response.headers["X-Content-Type-Options"] = "nosniff"
- env.response.headers["Content-Security-Policy"] = "default-src blob: data: 'self' #{host_url} 'unsafe-inline' 'unsafe-eval'; media-src blob: 'self' #{host_url} https://*.googlevideo.com:443"
+ extra_media_csp = ""
+ if CONFIG.disabled?("local") || !preferences.local
+ extra_media_csp += " https://*.googlevideo.com:443"
+ end
+ # TODO: Remove style-src's 'unsafe-inline', requires to remove all inline styles (<style> [..] </style>, style=" [..] ")
+ env.response.headers["Content-Security-Policy"] = "default-src 'none'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self'; media-src 'self' blob:#{extra_media_csp}"
env.response.headers["Referrer-Policy"] = "same-origin"
if (Kemal.config.ssl || config.https_only) && config.hsts
@@ -269,12 +279,6 @@ before_all do |env|
"/latest_version",
}.any? { |r| env.request.resource.starts_with? r }
- begin
- preferences = Preferences.from_json(env.request.cookies["PREFS"]?.try &.value || "{}")
- rescue
- preferences = Preferences.from_json("{}")
- end
-
if env.request.cookies.has_key? "SID"
sid = env.request.cookies["SID"].value
diff --git a/src/invidious/comments.cr b/src/invidious/comments.cr
index 2938247a..4a048d7a 100644
--- a/src/invidious/comments.cr
+++ b/src/invidious/comments.cr
@@ -294,7 +294,7 @@ def template_youtube_comments(comments, locale, thin_mode)
<div class="pure-u-23-24">
<p>
<a href="javascript:void(0)" data-continuation="#{child["replies"]["continuation"]}"
- onclick="get_youtube_replies(this)">#{translate(locale, "View `x` replies", number_with_separator(child["replies"]["replyCount"]))}</a>
+ data-onclick="get_youtube_replies">#{translate(locale, "View `x` replies", number_with_separator(child["replies"]["replyCount"]))}</a>
</p>
</div>
</div>
@@ -413,7 +413,7 @@ def template_youtube_comments(comments, locale, thin_mode)
<div class="pure-u-1">
<p>
<a href="javascript:void(0)" data-continuation="#{comments["continuation"]}"
- onclick="get_youtube_replies(this, true)">#{translate(locale, "Load more")}</a>
+ data-onclick="get_youtube_replies" data-load-more>#{translate(locale, "Load more")}</a>
</p>
</div>
</div>
@@ -451,7 +451,7 @@ def template_reddit_comments(root, locale)
html << <<-END_HTML
<p>
- <a href="javascript:void(0)" onclick="toggle_parent(this)">[ - ]</a>
+ <a href="javascript:void(0)" data-onclick="toggle_parent">[ - ]</a>
<b><a href="https://www.reddit.com/user/#{child.author}">#{child.author}</a></b>
#{translate(locale, "`x` points", number_with_separator(child.score))}
<span title="#{child.created_utc.to_s(translate(locale, "%a %B %-d %T %Y UTC"))}">#{translate(locale, "`x` ago", recode_date(child.created_utc, locale))}</span>
@@ -556,7 +556,7 @@ def content_to_comment_html(content)
video_id = watch_endpoint["videoId"].as_s
if length_seconds
- text = %(<a href="javascript:void(0)" onclick="player.currentTime(#{length_seconds})">#{text}</a>)
+ text = %(<a href="javascript:void(0)" data-onclick="jump_to_time" data-jump-time="#{length_seconds}">#{text}</a>)
else
text = %(<a href="/watch?v=#{video_id}">#{text}</a>)
end
diff --git a/src/invidious/views/add_playlist_items.ecr b/src/invidious/views/add_playlist_items.ecr
index f1899faa..dff0b549 100644
--- a/src/invidious/views/add_playlist_items.ecr
+++ b/src/invidious/views/add_playlist_items.ecr
@@ -20,9 +20,9 @@
<div class="pure-u-1 pure-u-lg-1-5"></div>
</div>
-<script>
-var playlist_data = {
- csrf_token: '<%= URI.encode_www_form(env.get?("csrf_token").try &.as(String) || "") %>',
+<script id="playlist_data" type="application/json">
+{
+ "csrf_token": "<%= URI.encode_www_form(env.get?("csrf_token").try &.as(String) || "") %>"
}
</script>
<script src="/js/playlist_widget.js"></script>
diff --git a/src/invidious/views/community.ecr b/src/invidious/views/community.ecr
index 218cc2d4..fca8c0b6 100644
--- a/src/invidious/views/community.ecr
+++ b/src/invidious/views/community.ecr
@@ -71,14 +71,14 @@
</div>
<% end %>
-<script>
-var community_data = {
- ucid: '<%= channel.ucid %>',
- youtube_comments_text: '<%= HTML.escape(translate(locale, "View YouTube comments")) %>',
- comments_text: '<%= HTML.escape(translate(locale, "View `x` comments", "{commentCount}")) %>',
- hide_replies_text: '<%= HTML.escape(translate(locale, "Hide replies")) %>',
- show_replies_text: '<%= HTML.escape(translate(locale, "Show replies")) %>',
- preferences: <%= env.get("preferences").as(Preferences).to_json %>,
+<script id="community_data" type="application/json">
+{
+ "ucid": "<%= channel.ucid %>",
+ "youtube_comments_text": "<%= HTML.escape(translate(locale, "View YouTube comments")) %>",
+ "comments_text": "<%= HTML.escape(translate(locale, "View `x` comments", "{commentCount}")) %>",
+ "hide_replies_text": "<%= HTML.escape(translate(locale, "Hide replies")) %>",
+ "show_replies_text": "<%= HTML.escape(translate(locale, "Show replies")) %>",
+ "preferences": <%= env.get("preferences").as(Preferences).to_json %>
}
</script>
<script src="/js/community.js?v=<%= ASSET_COMMIT %>"></script>
diff --git a/src/invidious/views/components/item.ecr b/src/invidious/views/components/item.ecr
index 9669aaeb..e9baba2c 100644
--- a/src/invidious/views/components/item.ecr
+++ b/src/invidious/views/components/item.ecr
@@ -57,10 +57,10 @@
<div class="thumbnail">
<img class="thumbnail" src="/vi/<%= item.id %>/mqdefault.jpg"/>
<% if plid = env.get?("remove_playlist_items") %>
- <form onsubmit="return false" action="/playlist_ajax?action_remove_video=1&set_video_id=<%= item.index %>&playlist_id=<%= plid %>&referer=<%= env.get("current_page") %>" method="post">
+ <form data-onsubmit="return_false" action="/playlist_ajax?action_remove_video=1&set_video_id=<%= item.index %>&playlist_id=<%= plid %>&referer=<%= env.get("current_page") %>" method="post">
<input type="hidden" name="csrf_token" value="<%= URI.encode_www_form(env.get?("csrf_token").try &.as(String) || "") %>">
<p class="watched">
- <a onclick="remove_playlist_item(this)" data-index="<%= item.index %>" data-plid="<%= plid %>" href="javascript:void(0)">
+ <a data-onclick="remove_playlist_item" data-index="<%= item.index %>" data-plid="<%= plid %>" href="javascript:void(0)">
<button type="submit" style="all:unset">
<i class="icon ion-md-trash"></i>
</button>
@@ -103,13 +103,12 @@
<div class="thumbnail">
<img class="thumbnail" src="/vi/<%= item.id %>/mqdefault.jpg"/>
<% if env.get? "show_watched" %>
- <form onsubmit="return false" action="/watch_ajax?action_mark_watched=1&id=<%= item.id %>&referer=<%= env.get("current_page") %>" method="post">
+ <form data-onsubmit="return_false" action="/watch_ajax?action_mark_watched=1&id=<%= item.id %>&referer=<%= env.get("current_page") %>" method="post">
<input type="hidden" name="csrf_token" value="<%= URI.encode_www_form(env.get?("csrf_token").try &.as(String) || "") %>">
<p class="watched">
- <a onclick="mark_watched(this)" data-id="<%= item.id %>" href="javascript:void(0)">
+ <a data-onclick="mark_watched" data-id="<%= item.id %>" href="javascript:void(0)">
<button type="submit" style="all:unset">
- <i onmouseenter='this.setAttribute("class", "icon ion-ios-eye-off")'
- onmouseleave='this.setAttribute("class", "icon ion-ios-eye")'
+ <i data-mouse="switch_classes" data-switch-classes="ion-ios-eye-off,ion-ios-eye"
class="icon ion-ios-eye">
</i>
</button>
@@ -117,10 +116,10 @@
</p>
</form>
<% elsif plid = env.get? "add_playlist_items" %>
- <form onsubmit="return false" action="/playlist_ajax?action_add_video=1&video_id=<%= item.id %>&playlist_id=<%= plid %>&referer=<%= env.get("current_page") %>" method="post">
+ <form data-onsubmit="return_false" action="/playlist_ajax?action_add_video=1&video_id=<%= item.id %>&playlist_id=<%= plid %>&referer=<%= env.get("current_page") %>" method="post">
<input type="hidden" name="csrf_token" value="<%= URI.encode_www_form(env.get?("csrf_token").try &.as(String) || "") %>">
<p class="watched">
- <a onclick="add_playlist_item(this)" data-id="<%= item.id %>" data-plid="<%= plid %>" href="javascript:void(0)">
+ <a data-onclick="add_playlist_item" data-id="<%= item.id %>" data-plid="<%= plid %>" href="javascript:void(0)">
<button type="submit" style="all:unset">
<i class="icon ion-md-add"></i>
</button>
diff --git a/src/invidious/views/components/player.ecr b/src/invidious/views/components/player.ecr
index ba6311cb..520d72dd 100644
--- a/src/invidious/views/components/player.ecr
+++ b/src/invidious/views/components/player.ecr
@@ -1,8 +1,5 @@
<video style="outline:none;width:100%;background-color:#000" playsinline poster="<%= thumbnail %>" title="<%= HTML.escape(video.title) %>"
- id="player" class="video-js player-style-<%= params.player_style %>"
- onmouseenter='this["data-title"]=this["title"];this["title"]=""'
- onmouseleave='this["title"]=this["data-title"];this["data-title"]=""'
- oncontextmenu='this["title"]=this["data-title"]'
+ id="player" class="on-video_player video-js player-style-<%= params.player_style %>"
<% if params.autoplay %>autoplay<% end %>
<% if params.video_loop %>loop<% end %>
<% if params.controls %>controls<% end %>>
@@ -39,12 +36,12 @@
<% end %>
</video>
-<script>
-var player_data = {
- aspect_ratio: '<%= aspect_ratio %>',
- title: "<%= video.title.dump_unquoted %>",
- description: "<%= HTML.escape(video.short_description) %>",
- thumbnail: "<%= thumbnail %>"
+<script id="player_data" type="application/json">
+{
+ "aspect_ratio": "<%= aspect_ratio %>",
+ "title": "<%= video.title.dump_unquoted %>",
+ "description": "<%= HTML.escape(video.short_description) %>",
+ "thumbnail": "<%= thumbnail %>"
}
</script>
<script src="/js/player.js?v=<%= ASSET_COMMIT %>"></script>
diff --git a/src/invidious/views/components/player_sources.ecr b/src/invidious/views/components/player_sources.ecr
index d950e0da..8162546e 100644
--- a/src/invidious/views/components/player_sources.ecr
+++ b/src/invidious/views/components/player_sources.ecr
@@ -3,6 +3,7 @@
<link rel="stylesheet" href="/css/videojs.markers.min.css?v=<%= ASSET_COMMIT %>">
<link rel="stylesheet" href="/css/videojs-share.css?v=<%= ASSET_COMMIT %>">
<link rel="stylesheet" href="/css/videojs-vtt-thumbnails.css?v=<%= ASSET_COMMIT %>">
+<script src="/js/global.js?v=<%= ASSET_COMMIT %>"></script>
<script src="/js/video.min.js?v=<%= ASSET_COMMIT %>"></script>
<script src="/js/videojs-contrib-quality-levels.min.js?v=<%= ASSET_COMMIT %>"></script>
<script src="/js/videojs-http-source-selector.min.js?v=<%= ASSET_COMMIT %>"></script>
diff --git a/src/invidious/views/components/subscribe_widget.ecr b/src/invidious/views/components/subscribe_widget.ecr
index 471e6c1c..7c579a8a 100644
--- a/src/invidious/views/components/subscribe_widget.ecr
+++ b/src/invidious/views/components/subscribe_widget.ecr
@@ -19,14 +19,14 @@
</p>
<% end %>
- <script>
- var subscribe_data = {
- ucid: '<%= ucid %>',
- author: '<%= HTML.escape(author) %>',
- sub_count_text: '<%= HTML.escape(sub_count_text) %>',
- csrf_token: '<%= URI.encode_www_form(env.get?("csrf_token").try &.as(String) || "") %>',
- subscribe_text: '<%= HTML.escape(translate(locale, "Subscribe")) %>',
- unsubscribe_text: '<%= HTML.escape(translate(locale, "Unsubscribe")) %>'
+ <script id="subscribe_data" type="application/json">
+ {
+ "ucid": "<%= ucid %>",
+ "author": "<%= HTML.escape(author) %>",
+ "sub_count_text": "<%= HTML.escape(sub_count_text) %>",
+ "csrf_token": "<%= URI.encode_www_form(env.get?("csrf_token").try &.as(String) || "") %>",
+ "subscribe_text": "<%= HTML.escape(translate(locale, "Subscribe")) %>",
+ "unsubscribe_text": "<%= HTML.escape(translate(locale, "Unsubscribe")) %>"
}
</script>
<script src="/js/subscribe_widget.js?v=<%= ASSET_COMMIT %>"></script>
diff --git a/src/invidious/views/embed.ecr b/src/invidious/views/embed.ecr
index 6c06bf2e..ff8277e8 100644
--- a/src/invidious/views/embed.ecr
+++ b/src/invidious/views/embed.ecr
@@ -10,32 +10,21 @@
<script src="/js/videojs-overlay.min.js?v=<%= ASSET_COMMIT %>"></script>
<link rel="stylesheet" href="/css/default.css?v=<%= ASSET_COMMIT %>">
<link rel="stylesheet" href="/css/darktheme.css?v=<%= ASSET_COMMIT %>">
+ <link rel="stylesheet" href="/css/embed.css?v=<%= ASSET_COMMIT %>">
<title><%= HTML.escape(video.title) %> - Invidious</title>
- <style>
- #player {
- position: fixed;
- right: 0;
- bottom: 0;
- min-width: 100%;
- min-height: 100%;
- width: auto;
- height: auto;
- z-index: -100;
- }
- </style>
</head>
<body>
-<script>
-var video_data = {
- id: '<%= video.id %>',
- index: '<%= continuation %>',
- plid: '<%= plid %>',
- length_seconds: '<%= video.length_seconds.to_f %>',
- video_series: <%= video_series.to_json %>,
- params: <%= params.to_json %>,
- preferences: <%= preferences.to_json %>,
- premiere_timestamp: <%= video.premiere_timestamp.try &.to_unix || "null" %>
+<script id="video_data" type="application/json">
+{
+ "id": "<%= video.id %>",
+ "index": "<%= continuation %>",
+ "plid": "<%= plid %>",
+ "length_seconds": "<%= video.length_seconds.to_f %>",
+ "video_series": <%= video_series.to_json %>,
+ "params": <%= params.to_json %>,
+ "preferences": <%= preferences.to_json %>,
+ "premiere_timestamp": <%= video.premiere_timestamp.try &.to_unix || "null" %>
}
</script>
diff --git a/src/invidious/views/history.ecr b/src/invidious/views/history.ecr
index 7d7ded2c..2aa8adf7 100644
--- a/src/invidious/views/history.ecr
+++ b/src/invidious/views/history.ecr
@@ -18,9 +18,9 @@
</div>
</div>
-<script>
-var watched_data = {
- csrf_token: '<%= URI.encode_www_form(env.get?("csrf_token").try &.as(String) || "") %>',
+<script id="watched_data" type="application/json">
+{
+ "csrf_token": "<%= URI.encode_www_form(env.get?("csrf_token").try &.as(String) || "") %>"
}
</script>
<script src="/js/watched_widget.js"></script>
@@ -34,10 +34,10 @@ var watched_data = {
<% if !env.get("preferences").as(Preferences).thin_mode %>
<div class="thumbnail">
<img class="thumbnail" src="/vi/<%= item %>/mqdefault.jpg"/>
- <form onsubmit="return false" action="/watch_ajax?action_mark_unwatched=1&id=<%= item %>&referer=<%= env.get("current_page") %>" method="post">
+ <form data-onsubmit="return_false" action="/watch_ajax?action_mark_unwatched=1&id=<%= item %>&referer=<%= env.get("current_page") %>" method="post">
<input type="hidden" name="csrf_token" value="<%= URI.encode_www_form(env.get?("csrf_token").try &.as(String) || "") %>">
<p class="watched">
- <a onclick="mark_unwatched(this)" data-id="<%= item %>" href="javascript:void(0)">
+ <a data-onclick="mark_unwatched" data-id="<%= item %>" href="javascript:void(0)">
<button type="submit" style="all:unset">
<i class="icon ion-md-trash"></i>
</button>
diff --git a/src/invidious/views/playlist.ecr b/src/invidious/views/playlist.ecr
index cb643aaa..eff12c48 100644
--- a/src/invidious/views/playlist.ecr
+++ b/src/invidious/views/playlist.ecr
@@ -69,9 +69,9 @@
</div>
<% if playlist.is_a?(InvidiousPlaylist) && playlist.author == user.try &.email %>
-<script>
-var playlist_data = {
- csrf_token: '<%= URI.encode_www_form(env.get?("csrf_token").try &.as(String) || "") %>',
+<script id="playlist_data" type="application/json">
+{
+ "csrf_token": "<%= URI.encode_www_form(env.get?("csrf_token").try &.as(String) || "") %>"
}
</script>
<script src="/js/playlist_widget.js"></script>
diff --git a/src/invidious/views/preferences.ecr b/src/invidious/views/preferences.ecr
index 17e5804e..7e899133 100644
--- a/src/invidious/views/preferences.ecr
+++ b/src/invidious/views/preferences.ecr
@@ -2,12 +2,6 @@
<title><%= translate(locale, "Preferences") %> - Invidious</title>
<% end %>
-<script>
-function update_value(element) {
- document.getElementById('volume-value').innerText = element.value;
-}
-</script>
-
<div class="h-box">
<form class="pure-form pure-form-aligned" action="/preferences?referer=<%= URI.encode_www_form(referer) %>" method="post">
<fieldset>
@@ -65,7 +59,7 @@ function update_value(element) {
<div class="pure-control-group">
<label for="volume"><%= translate(locale, "Player volume: ") %></label>
- <input name="volume" id="volume" oninput="update_value(this);" type="range" min="0" max="100" step="5" value="<%= preferences.volume %>">
+ <input name="volume" id="volume" data-onrange="update_volume_value" type="range" min="0" max="100" step="5" value="<%= preferences.volume %>">
<span class="pure-form-message-inline" id="volume-value"><%= preferences.volume %></span>
</div>
@@ -205,7 +199,7 @@ function update_value(element) {
<% # Web notifications are only supported over HTTPS %>
<% if Kemal.config.ssl || config.https_only %>
<div class="pure-control-group">
- <a href="#" onclick="Notification.requestPermission()"><%= translate(locale, "Enable web notifications") %></a>
+ <a href="#" data-onclick="notification_requestPermission"><%= translate(locale, "Enable web notifications") %></a>
</div>
<% end %>
<% end %>
diff --git a/src/invidious/views/subscription_manager.ecr b/src/invidious/views/subscription_manager.ecr
index 43d14b37..6cddcd6c 100644
--- a/src/invidious/views/subscription_manager.ecr
+++ b/src/invidious/views/subscription_manager.ecr
@@ -37,9 +37,9 @@
<div class="pure-u-2-5"></div>
<div class="pure-u-1-5" style="text-align:right">
<h3 style="padding-right:0.5em">
- <form onsubmit="return false" action="/subscription_ajax?action_remove_subscriptions=1&c=<%= channel.id %>&referer=<%= env.get("current_page") %>" method="post">
+ <form data-onsubmit="return_false" action="/subscription_ajax?action_remove_subscriptions=1&c=<%= channel.id %>&referer=<%= env.get("current_page") %>" method="post">
<input type="hidden" name="csrf_token" value="<%= URI.encode_www_form(env.get?("csrf_token").try &.as(String) || "") %>">
- <a onclick="remove_subscription(this)" data-ucid="<%= channel.id %>" href="#">
+ <a data-onclick="remove_subscription" data-ucid="<%= channel.id %>" href="#">
<input style="all:unset" type="submit" value="<%= translate(locale, "unsubscribe") %>">
</a>
</form>
@@ -52,32 +52,3 @@
<% end %>
</div>
<% end %>
-
-<script>
-function remove_subscription(target) {
- var row = target.parentNode.parentNode.parentNode.parentNode.parentNode;
- row.style.display = 'none';
- var count = document.getElementById('count');
- count.innerText = count.innerText - 1;
-
- var url = '/subscription_ajax?action_remove_subscriptions=1&redirect=false' +
- '&referer=<%= env.get("current_page") %>' +
- '&c=' + target.getAttribute('data-ucid');
- var xhr = new XMLHttpRequest();
- xhr.responseType = 'json';
- xhr.timeout = 10000;
- xhr.open('POST', url, true);
- xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
-
- xhr.onreadystatechange = function() {
- if (xhr.readyState == 4) {
- if (xhr.status != 200) {
- count.innerText = parseInt(count.innerText) + 1;
- row.style.display = '';
- }
- }
- }
-
- xhr.send('csrf_token=<%= URI.encode_www_form(env.get?("csrf_token").try &.as(String) || "") %>');
-}
-</script>
diff --git a/src/invidious/views/subscriptions.ecr b/src/invidious/views/subscriptions.ecr
index ee31d241..93c58471 100644
--- a/src/invidious/views/subscriptions.ecr
+++ b/src/invidious/views/subscriptions.ecr
@@ -45,9 +45,9 @@
<hr>
</div>
-<script>
-var watched_data = {
- csrf_token: '<%= URI.encode_www_form(env.get?("csrf_token").try &.as(String) || "") %>',
+<script id="watched_data" type="application/json">
+{
+ "csrf_token": "<%= URI.encode_www_form(env.get?("csrf_token").try &.as(String) || "") %>"
}
</script>
<script src="/js/watched_widget.js"></script>
diff --git a/src/invidious/views/template.ecr b/src/invidious/views/template.ecr
index d2ef9c7e..b239d22a 100644
--- a/src/invidious/views/template.ecr
+++ b/src/invidious/views/template.ecr
@@ -147,13 +147,14 @@
</div>
<div class="pure-u-1 pure-u-md-2-24"></div>
</div>
+ <script src="/js/handlers.js?v=<%= ASSET_COMMIT %>"></script>
<script src="/js/themes.js?v=<%= ASSET_COMMIT %>"></script>
<% if env.get? "user" %>
<script src="/js/sse.js?v=<%= ASSET_COMMIT %>"></script>
- <script>
- var notification_data = {
- upload_text: '<%= HTML.escape(translate(locale, "`x` uploaded a video")) %>',
- live_upload_text: '<%= HTML.escape(translate(locale, "`x` is live")) %>',
+ <script id="notification_data" type="application/json">
+ {
+ "upload_text": "<%= HTML.escape(translate(locale, "`x` uploaded a video")) %>",
+ "live_upload_text": "<%= HTML.escape(translate(locale, "`x` is live")) %>"
}
</script>
<script src="/js/notifications.js?v=<%= ASSET_COMMIT %>"></script>
diff --git a/src/invidious/views/token_manager.ecr b/src/invidious/views/token_manager.ecr
index b626d99c..e48aec2f 100644
--- a/src/invidious/views/token_manager.ecr
+++ b/src/invidious/views/token_manager.ecr
@@ -29,9 +29,9 @@
</div>
<div class="pure-u-1-5" style="text-align:right">
<h3 style="padding-right:0.5em">
- <form onsubmit="return false" action="/token_ajax?action_revoke_token=1&session=<%= token[:session] %>&referer=<%= env.get("current_page") %>" method="post">
+ <form data-onsubmit="return_false" action="/token_ajax?action_revoke_token=1&session=<%= token[:session] %>&referer=<%= env.get("current_page") %>" method="post">
<input type="hidden" name="csrf_token" value="<%= URI.encode_www_form(env.get?("csrf_token").try &.as(String) || "") %>">
- <a onclick="revoke_token(this)" data-session="<%= token[:session] %>" href="#">
+ <a data-onclick="revoke_token" data-session="<%= token[:session] %>" href="#">
<input style="all:unset" type="submit" value="<%= translate(locale, "revoke") %>">
</a>
</form>
@@ -44,32 +44,3 @@
<% end %>
</div>
<% end %>
-
-<script>
-function revoke_token(target) {
- var row = target.parentNode.parentNode.parentNode.parentNode.parentNode;
- row.style.display = 'none';
- var count = document.getElementById('count');
- count.innerText = count.innerText - 1;
-
- var url = '/token_ajax?action_revoke_token=1&redirect=false' +
- '&referer=<%= env.get("current_page") %>' +
- '&session=' + target.getAttribute('data-session');
- var xhr = new XMLHttpRequest();
- xhr.responseType = 'json';
- xhr.timeout = 10000;
- xhr.open('POST', url, true);
- xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
-
- xhr.onreadystatechange = function() {
- if (xhr.readyState == 4) {
- if (xhr.status != 200) {
- count.innerText = parseInt(count.innerText) + 1;
- row.style.display = '';
- }
- }
- }
-
- xhr.send('csrf_token=<%= URI.encode_www_form(env.get?("csrf_token").try &.as(String) || "") %>');
-}
-</script>
diff --git a/src/invidious/views/watch.ecr b/src/invidious/views/watch.ecr
index df61abc5..16ac71eb 100644
--- a/src/invidious/views/watch.ecr
+++ b/src/invidious/views/watch.ecr
@@ -26,23 +26,23 @@
<title><%= HTML.escape(video.title) %> - Invidious</title>
<% end %>
-<script>
-var video_data = {
- id: '<%= video.id %>',
- index: '<%= continuation %>',
- plid: '<%= plid %>',
- length_seconds: <%= video.length_seconds.to_f %>,
- play_next: <%= !rvs.empty? && !plid && params.continue %>,
- next_video: '<%= rvs.select { |rv| rv["id"]? }[0]?.try &.["id"] %>',
- youtube_comments_text: '<%= HTML.escape(translate(locale, "View YouTube comments")) %>',
- reddit_comments_text: '<%= HTML.escape(translate(locale, "View Reddit comments")) %>',
- reddit_permalink_text: '<%= HTML.escape(translate(locale, "View more comments on Reddit")) %>',
- comments_text: '<%= HTML.escape(translate(locale, "View `x` comments", "{commentCount}")) %>',
- hide_replies_text: '<%= HTML.escape(translate(locale, "Hide replies")) %>',
- show_replies_text: '<%= HTML.escape(translate(locale, "Show replies")) %>',
- params: <%= params.to_json %>,
- preferences: <%= preferences.to_json %>,
- premiere_timestamp: <%= video.premiere_timestamp.try &.to_unix || "null" %>
+<script id="video_data" type="application/json">
+{
+ "id": "<%= video.id %>",
+ "index": "<%= continuation %>",
+ "plid": "<%= plid %>",
+ "length_seconds": <%= video.length_seconds.to_f %>,
+ "play_next": <%= !rvs.empty? && !plid && params.continue %>,
+ "next_video": "<%= rvs.select { |rv| rv["id"]? }[0]?.try &.["id"] %>",
+ "youtube_comments_text": "<%= HTML.escape(translate(locale, "View YouTube comments")) %>",
+ "reddit_comments_text": "<%= HTML.escape(translate(locale, "View Reddit comments")) %>",
+ "reddit_permalink_text": "<%= HTML.escape(translate(locale, "View more comments on Reddit")) %>",
+ "comments_text": "<%= HTML.escape(translate(locale, "View `x` comments", "{commentCount}")) %>",
+ "hide_replies_text": "<%= HTML.escape(translate(locale, "Hide replies")) %>",
+ "show_replies_text": "<%= HTML.escape(translate(locale, "Show replies")) %>",
+ "params": <%= params.to_json %>,
+ "preferences": <%= preferences.to_json %>,
+ "premiere_timestamp": <%= video.premiere_timestamp.try &.to_unix || "null" %>
}
</script>