divan/GanjooRazor/Pages/GanjoorPage.cshtml
Hamid Reza Mohammadi af75cc18d9 xss vulnerability fix
2026-09-25 17:46:22 +03:30

252 lines
9.6 KiB
Plaintext

@page
@model GanjoorPageModel
@{
Layout = "_Layout";
}
@if (Model.GanjoorPage == null)
{
return;
}
@section Head {
<script src="/js/chart.js"></script>
<script src="/js/jquery.mark.min.js"></script>
<script>
var cookieValue = getCookie("lineNumbers");
var lineNumbers = cookieValue != "false";
</script>
@if ((Model.GanjoorPage != null && Model.GanjoorPage.NoIndex) || !string.IsNullOrEmpty(Model.PinterestUrl))
{
<meta name="robots" content="noindex, nofollow">
}
@if (Model.GanjoorPage != null)
{
<link rel="canonical" href="@Model.CanonicalUrl">
if (Model.IsPoemPage)
{
<script>
var currentPoemId = @Model.GanjoorPage.Id;
$(document).ready(function() {
checkWebShareSupport();
if (lineNumbers) {
btshmr(@Model.GanjoorPage.Id);
}
checkIfBookmarked(@Model.GanjoorPage.Id);
paginateComments();
revealCommentFromUrlHash();
});
</script>
}
<script type="application/ld+json">
{
@Html.Raw(@ViewData["BrearCrumpList"])
}
</script>
}
@if ((Model.IsCatPage || Model.IsPoetPage) && Model.CategoryPoemGeoDateTags != null && Model.CategoryPoemGeoDateTags.Length > 0)
{
<link rel="stylesheet" href="/css/leaflet.css?version=2">
<style>
.leaflet-container {
background-color: #c5e8ff;
}
.leaflet-popup-content {
font-family: 'Vazirmatn'
}
</style>
<script src="~/js/leaflet.js"></script>
<script src="~/js/leaflet-providers.js"></script>
@if (!Model.OfflineMode)
{
<script src="https://cdnjs.cloudflare.com/ajax/libs/OverlappingMarkerSpiderfier-Leaflet/0.2.6/oms.min.js"></script>
}
}
@if (Model.IsPoemPage && Model.GanjoorPage.Poem.GeoDateTags.Length > 0)
{
<link rel="stylesheet" href="/css/leaflet.css?version=2">
<style>
.leaflet-container {
background-color: #c5e8ff;
}
.leaflet-popup-content {
font-family: 'Vazirmatn'
}
</style>
<script src="~/js/leaflet.js"></script>
<script src="~/js/leaflet-providers.js"></script>
@if (!Model.OfflineMode)
{
<script src="https://cdnjs.cloudflare.com/ajax/libs/OverlappingMarkerSpiderfier-Leaflet/0.2.6/oms.min.js"></script>
}
}
}
@if (Model.OfflineMode)
{
<div class="notice">
<p>
از آنجا که شما با شبکهٔ داخلی اطلاعات ایران وصل شده‌اید در حال مشاهدهٔ یک نسخهٔ آفلاین از گنجور هستید.
</p>
<p>
این یک نسخهٔ آفلاین با اطلاعات قدیمی از سایت گنجور است که برای ایرانیان داخل کشور که اینترنتشان قطع است در دسترس قرار گرفته است.
</p>
<p>
بعضی امکاناتِ نیازمند اینترنت حذف شده و برخی قابلیتها نیز ممکن است به درستی کار نکند.
</p>
<p>
امکانات نام‌نویسی و درج حاشیه نیز در آن غیرفعال است. اگر می‌توانید جایی اطلاعاتی وارد کنید انتظار ذخیرهٔ آن را به طور دائم نداشته باشید.
</p>
<p>
نسخهٔ به‌روز گنجور روی اینترنت تا پایان قطعی اینترنت در ایران برای آی.پی‌های خارج از ایران در دسترس است.
</p>
</div>
}
else if (Model.ReadOnlyMode)
{
<div class="notice">
<p>
گنجور در حال حاضر در وضعیت فقط‌خواندنی است.
</p>
<p>
امکانات نام‌نویسی و درج حاشیه نیز در آن غیرفعال است. اگر می‌توانید جایی اطلاعاتی وارد کنید انتظار ذخیرهٔ آن را به طور دائم نداشته باشید.
</p>
</div>
}
<partial name="_SearchHeaderPartial" model="@(new _SearchHeaderPartialModel()
{
Poets = Model.Poets,
SelectedPoetId = Model.GanjoorPage?.PoetOrCat?.Poet?.Id ?? 0,
CurrentCategory = (!Model.IsPoetPage && Model.GanjoorPage?.PoetOrCat != null) ? Model.GanjoorPage.PoetOrCat.Cat : null,
WideCategorySelect = false
})" /><!-- #hdr2 -->
<div id="fa">
<partial name="_InlineLoginPartial" model="Model" />
<div id="maincnt">
@if (!string.IsNullOrEmpty(Model.LastError))
{
<div class="poem">
@Model.LastError
</div>
}
else
{
@if (Model.IsPoetPage)
{
<partial name="Partials/GanjoorPage/PageTypes/_PoetPagePartial" model="Model" />
}
else if (Model.IsCatPage)
{
<partial name="Partials/GanjoorPage/PageTypes/_CatPagePartial" model="Model" />
}
else if (Model.IsPoemPage)
{
<partial name="Partials/GanjoorPage/PageTypes/_PoemPagePartial" model="Model" />
}
else
{
<partial name="Partials/GanjoorPage/PageTypes/_GenericPagePartial" model="Model" />
}
}
</div>
<partial name="_FooterPartial" model=@(new _FooterPartialModel() { StickyEnabled = true, GanjoorPage = Model.GanjoorPage }) />
</div>
@{
if (!string.IsNullOrEmpty(Model.PinterestUrl))
{
// PinterestUrl comes straight from the untrusted "pinterest_url" query string
// (see GanjoorPage.cshtml.cs). It must never be emitted with @Html.Raw into a
// <script> block - that allowed a reflected XSS via payloads such as
// "</script><script>alert(document.cookie)</script>". Instead it is serialized
// as a JSON string literal (which escapes '<', '>', '&', quotes, etc.) and then
// URL-encoded again before being appended to href values.
<script>
$(function() {
var pinterestUrl = @Html.Raw(System.Text.Json.JsonSerializer.Serialize(Model.PinterestUrl));
$("a").attr('href', function(i, h) {
if (h != null) {
return h + (h.indexOf('?') != -1 ? "&pinterest_url=" + encodeURIComponent(pinterestUrl) : "?pinterest_url=" + encodeURIComponent(pinterestUrl));
}
return h;
});
});
</script>
}
}
@if (Model.IsPoemPage)
{
<script src="/lib/tinymce/tinymce.min.js"></script>
<script>
var userNotifiedOnEditInsteadOfComment = false;
function createInformationNotification() {
tinymce.activeEditor.notificationManager.open({
text: 'تمنا می‌کنیم که به جای گوشزد کردن خطاهای املایی و تایپی در حاشیه‌ها از دکمهٔ «ویرایش» استفاده کنید و خطا را تصحیح کنید.',
type: 'info'
});
}
tinymce.init({
selector: 'textarea.editor',
language: 'fa_IR',
menubar: false,
plugins: 'link paste image',
toolbar: 'undo redo | alignleft aligncenter alignright alignjustify | link',
contextmenu: false,
paste_auto_cleanup_on_paste: true,
paste_remove_styles: true,
paste_remove_styles_if_webkit: true,
paste_strip_class_attributes: true,
a11y_advanced_options: true,
skin: (window.matchMedia("(prefers-color-scheme: dark)").matches && localStorage.getItem("scheme") != "light" ? "oxide-dark" : localStorage.getItem("scheme") == "dark" ? "oxide-dark" : "oxide"),
content_css: (window.matchMedia("(prefers-color-scheme: dark)").matches && localStorage.getItem("scheme") != "light" ? "dark" : localStorage.getItem("scheme") == "dark" ? "dark" : false),
setup: function(editor) {
editor.on('tap', function(e, f) {
var editor_id = e.view.frameElement.id.slice(0, -4);
if (editor_id != 'editNoteText') {
if (userNotifiedOnEditInsteadOfComment == false) {
userNotifiedOnEditInsteadOfComment = true;
createInformationNotification();
}
}
},
);
editor.on('click', function(e, f) {
var editor_id = e.view.frameElement.id.slice(0, -4);
if (editor_id != 'editNoteText') {
if (userNotifiedOnEditInsteadOfComment == false) {
userNotifiedOnEditInsteadOfComment = true;
createInformationNotification();
}
}
},
);
},
});
</script>
}
@if (ViewData["TrackingScript"] != null && !string.IsNullOrEmpty(ViewData["TrackingScript"].ToString()))
{
@Html.Raw(ViewData["TrackingScript"])
}
<script>
document.addEventListener("DOMContentLoaded", function() {
document.querySelectorAll("table.stats").forEach(table => {
plotChart(table.getAttribute("id"));
});
});
</script>