@@ -1,2 +1,4 @@ | |||
User-agent: * | |||
Disallow: / | |||
User-agent: * | |||
Disallow: /Content/ | |||
Disallow: /Scripts/ | |||
Disallow: /Images/ |
@@ -1,4 +1,4 @@ | |||
using System.Web; | |||
using System.Web; | |||
using System.Web.Optimization; | |||
using Teknik.Configuration; | |||
using Teknik.Utilities; |
@@ -1,4 +1,4 @@ | |||
@model Teknik.Areas.Admin.ViewModels.UploadResultViewModel | |||
@model Teknik.Areas.Admin.ViewModels.UploadResultViewModel | |||
@using Teknik.Utilities | |||
@@ -23,11 +23,11 @@ | |||
<label for="downloads">Downloads</label> | |||
<p id="downloads">@Model.Downloads</p> | |||
</div> | |||
<div class="col-sm-2 text-center" style="overflow-x: hidden"> | |||
<div class="col-sm-2 text-center"> | |||
@{ | |||
string deleteUrl = (string.IsNullOrEmpty(Model.DeleteKey)) ? string.Empty : Url.SubRouteUrl("u", "Upload.Delete", new { file = Model.Url, key = Model.DeleteKey }); | |||
} | |||
<p id="delete-upload"><button role="button" class="btn btn-danger delete-upload-button" id="@deleteUrl" data-upload-id="@Model.Url">Delete</button></p> | |||
</div> | |||
</div> | |||
</div> | |||
</div> |
@@ -1,8 +1,8 @@ | |||
@model Teknik.Areas.Admin.ViewModels.UploadSearchViewModel | |||
@model Teknik.Areas.Admin.ViewModels.UploadSearchViewModel | |||
@using Teknik.Utilities | |||
<script> | |||
<script nonce="@Context.Items[Constants.NONCE_KEY]"> | |||
// We need to define the action URLs for the script | |||
var searchResultsURL = '@Url.SubRouteUrl("admin", "Admin.Action", new { action = "GetUploadSearchResults" })'; | |||
var generateDeleteKeyURL = '@Url.SubRouteUrl("u", "Upload.GenerateDeleteKey")'; | |||
@@ -25,4 +25,4 @@ | |||
<div class="results" id="results"></div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> |
@@ -2,7 +2,7 @@ | |||
@using Teknik.Utilities | |||
<script> | |||
<script nonce="@Context.Items[Constants.NONCE_KEY]"> | |||
// We need to define the action URLs for the script | |||
var homeUrl = '@Url.SubRouteUrl("admin", "Admin.UserSearch")'; | |||
var deleteUserURL = '@Url.SubRouteUrl("admin", "Admin.Action", new { action = "DeleteAccount" })'; |
@@ -2,7 +2,7 @@ | |||
@using Teknik.Utilities | |||
<script> | |||
<script nonce="@Context.Items[Constants.NONCE_KEY]"> | |||
// We need to define the action URLs for the script | |||
var userSearchResultsURL = '@Url.SubRouteUrl("admin", "Admin.Action", new { action = "GetUserSearchResults" })'; | |||
</script> |
@@ -1,8 +1,8 @@ | |||
@model Teknik.Areas.Blog.ViewModels.BlogViewModel | |||
@model Teknik.Areas.Blog.ViewModels.BlogViewModel | |||
@using Teknik.Utilities | |||
<script> | |||
<script nonce="@Context.Items[Constants.NONCE_KEY]"> | |||
// We need to define the action URLs for the script | |||
var uploadURL = '@Url.SubRouteUrl("upload", "Upload.Upload")'; | |||
var helpURL = '@Url.SubRouteUrl("help", "Help.Markdown")'; | |||
@@ -49,7 +49,7 @@ | |||
if (Model.HasPosts) | |||
{ | |||
<div class="blog-main" id="@Model.BlogId"></div> | |||
<script> | |||
<script nonce="@Context.Items[Constants.NONCE_KEY]"> | |||
var posts = @Model.Config.BlogConfig.PostsToLoad; | |||
var start_post = 0; | |||
loadMorePosts(start_post, posts); | |||
@@ -73,4 +73,4 @@ | |||
</div> | |||
</div> | |||
} | |||
</div> | |||
</div> |
@@ -1,8 +1,8 @@ | |||
@model Teknik.Areas.Blog.ViewModels.PostViewModel | |||
@model Teknik.Areas.Blog.ViewModels.PostViewModel | |||
@using Teknik.Utilities | |||
<script> | |||
<script nonce="@Context.Items[Constants.NONCE_KEY]"> | |||
// We need to define the action URLs for the script | |||
var helpURL = '@Url.SubRouteUrl("help", "Help.Markdown")'; | |||
</script> | |||
@@ -56,4 +56,4 @@ | |||
</div> | |||
</div> | |||
</form> | |||
</div> | |||
</div> |
@@ -1,8 +1,8 @@ | |||
@model Teknik.Areas.Blog.ViewModels.BlogViewModel | |||
@model Teknik.Areas.Blog.ViewModels.BlogViewModel | |||
@using Teknik.Utilities | |||
<script> | |||
<script nonce="@Context.Items[Constants.NONCE_KEY]"> | |||
// We need to define the action URLs for the script | |||
var helpURL = '@Url.SubRouteUrl("help", "Help.Markdown")'; | |||
</script> | |||
@@ -56,4 +56,4 @@ | |||
</div> | |||
</div> | |||
</form> | |||
</div> | |||
</div> |
@@ -1,8 +1,8 @@ | |||
@model Teknik.Areas.Blog.ViewModels.PostViewModel | |||
@model Teknik.Areas.Blog.ViewModels.PostViewModel | |||
@using Teknik.Utilities | |||
<script> | |||
<script nonce="@Context.Items[Constants.NONCE_KEY]"> | |||
// We need to define the action URLs for the script | |||
var uploadURL = '@Url.SubRouteUrl("upload", "Upload.Upload")'; | |||
var helpURL = '@Url.SubRouteUrl("help", "Help.Markdown")'; | |||
@@ -92,7 +92,7 @@ | |||
} | |||
<a name="replies"></a> | |||
<div class="post-comments" id="@Model.PostId"></div> | |||
<script> | |||
<script nonce="@Context.Items[Constants.NONCE_KEY]"> | |||
linkPostDelete('.delete_post'); | |||
linkPostPublish('.publish_post'); | |||
linkPostUnpublish('.unpublish_post'); | |||
@@ -112,4 +112,4 @@ else | |||
</div> | |||
</div> | |||
} | |||
</div> | |||
</div> |
@@ -3,7 +3,7 @@ | |||
@using Teknik.Utilities | |||
@Scripts.Render("~/bundles/error") | |||
<script> | |||
<script nonce="@Context.Items[Constants.NONCE_KEY]"> | |||
var submitErrorReportURL = '@Url.SubRouteUrl("error", "Error.Action", new { action = "SubmitErrorReport" })'; | |||
</script> | |||
@@ -3,7 +3,7 @@ | |||
@using Teknik.Utilities | |||
@Scripts.Render("~/bundles/error") | |||
<script> | |||
<script nonce="@Context.Items[Constants.NONCE_KEY]"> | |||
var submitErrorReportURL = '@Url.SubRouteUrl("error", "Error.Action", new { action = "SubmitErrorReport" })'; | |||
</script> | |||
@@ -1,11 +1,11 @@ | |||
@model Teknik.Areas.Paste.ViewModels.PasteViewModel | |||
@model Teknik.Areas.Paste.ViewModels.PasteViewModel | |||
@using Teknik.Utilities | |||
@using Teknik.Areas.Vault.Models | |||
@Styles.Render("~/Content/paste") | |||
<script type="text/javascript"> | |||
<script nonce="@Context.Items[Constants.NONCE_KEY]"> | |||
var createVaultURL = '@Url.SubRouteUrl("vault", "Vault.NewVaultFromService", new { type = "Paste" })'; | |||
</script> | |||
@@ -42,4 +42,4 @@ | |||
</div> | |||
</div> | |||
@Scripts.Render("~/bundles/paste") | |||
@Scripts.Render("~/bundles/paste") |
@@ -1,4 +1,4 @@ | |||
@model Teknik.Areas.Paste.ViewModels.PasteCreateViewModel | |||
@model Teknik.Areas.Paste.ViewModels.PasteCreateViewModel | |||
@using Teknik.Utilities | |||
@using Teknik.Pygments | |||
@@ -83,7 +83,7 @@ | |||
</div> | |||
</div> | |||
<script> | |||
<script nonce="@Context.Items[Constants.NONCE_KEY]"> | |||
$("select[name='ExpireUnit']").change(function () { | |||
if ($(this).val() == "never") { | |||
$('#length-div').addClass("hidden"); | |||
@@ -96,4 +96,4 @@ | |||
$('#unit-div').addClass("col-sm-2"); | |||
} | |||
}); | |||
</script> | |||
</script> |
@@ -1,4 +1,6 @@ | |||
@model Teknik.Areas.Paste.ViewModels.PasteViewModel | |||
@model Teknik.Areas.Paste.ViewModels.PasteViewModel | |||
@using Teknik.Utilities | |||
@{ | |||
Layout = ""; | |||
string syntax = string.Empty; | |||
@@ -24,8 +26,8 @@ | |||
</head> | |||
<body data-twttr-rendered="true"> | |||
@Html.Raw(Model.Content) | |||
<script> | |||
<script nonce="@Context.Items[Constants.NONCE_KEY]"> | |||
function pageloadStopTimer() { } | |||
</script> | |||
</body> | |||
</html> | |||
</html> |
@@ -1,8 +1,8 @@ | |||
@model Teknik.Areas.Podcast.ViewModels.MainViewModel | |||
@model Teknik.Areas.Podcast.ViewModels.MainViewModel | |||
@using Teknik.Utilities | |||
<script> | |||
<script nonce="@Context.Items[Constants.NONCE_KEY]"> | |||
// We need to define the action URLs for the script | |||
var uploadURL = '@Url.SubRouteUrl("upload", "Upload.Upload")'; | |||
@@ -146,7 +146,7 @@ | |||
@if (!Model.Error) | |||
{ | |||
<div class="podcast-main"></div> | |||
<script> | |||
<script nonce="@Context.Items[Constants.NONCE_KEY]"> | |||
var podcasts = @Model.Config.PodcastConfig.PodcastsToLoad; | |||
var startPodcast = 0; | |||
loadMorePodcasts(startPodcast, podcasts); |
@@ -1,8 +1,8 @@ | |||
@model Teknik.Areas.Podcast.ViewModels.PodcastViewModel | |||
@model Teknik.Areas.Podcast.ViewModels.PodcastViewModel | |||
@using Teknik.Utilities | |||
<script> | |||
<script nonce="@Context.Items[Constants.NONCE_KEY]"> | |||
// We need to define the action URLs for the script | |||
var uploadURL = '@Url.SubRouteUrl("upload", "Upload.Upload")'; | |||
@@ -144,7 +144,7 @@ | |||
} | |||
<a name="replies"></a> | |||
<div class="post-comments" id="@Model.PodcastId"></div> | |||
<script> | |||
<script nonce="@Context.Items[Constants.NONCE_KEY]"> | |||
var comments = @Model.Config.PodcastConfig.CommentsToLoad; | |||
var startComment = 0; | |||
loadMoreComments(startComment, comments); |
@@ -1,4 +1,4 @@ | |||
@model Teknik.Areas.Status.ViewModels.StatusViewModel | |||
@model Teknik.Areas.Status.ViewModels.StatusViewModel | |||
@using Teknik.Utilities | |||
@using Teknik.Areas.Status.Models | |||
@@ -7,7 +7,7 @@ | |||
@Scripts.Render("~/signalr/hubs") | |||
@Scripts.Render("~/bundles/status") | |||
<script type="text/javascript"> | |||
<script nonce="@Context.Items[Constants.NONCE_KEY]"> | |||
var getVisitorDataURL = '@Url.SubRouteUrl("status", "Status.Action", new { action = "GetVisitorData" })'; | |||
var showWebCPU = @Model.Config.StatusConfig.ShowWebStatus.ToString().ToLower(); | |||
var showDatabaseCPU = @Model.Config.StatusConfig.ShowDatabaseStatus.ToString().ToLower(); |
@@ -1,4 +1,4 @@ | |||
self.addEventListener('message', function (e) { | |||
self.addEventListener('message', function (e) { | |||
importScripts(e.data.script); | |||
var bytes = new Uint8Array(e.data.file); | |||
@@ -33,7 +33,7 @@ | |||
var curBytes = bytes.subarray(startByte, endByte); | |||
//var b64encoded = btoa(String.fromCharCode.apply(null, curBytes)); | |||
var wordArray = CryptoJS.lib.WordArray.create(curBytes) | |||
var wordArray = CryptoJS.lib.WordArray.create(curBytes); | |||
// encrypt the passed in file data | |||
var enc = aesCrypto.process(wordArray); | |||
@@ -112,4 +112,4 @@ function Uint8Concat(first, second) { | |||
result.set(second, firstLength); | |||
return result; | |||
} | |||
} |
@@ -2,6 +2,15 @@ $(document).ready(function () { | |||
$("#upload-links").css('display', 'none', 'important'); | |||
$("#upload-links").html(''); | |||
$('[data-toggle="popover"]').popover(); | |||
$('[data-toggle="popover"]').on('shown.bs.popover', function () { | |||
var $this = $(this); | |||
setTimeout(function () { | |||
$this.popover('hide'); | |||
}, 3000); | |||
}); | |||
$("[name='encrypt']").bootstrapSwitch(); | |||
linkCopyAll($('#copy-all')); | |||
@@ -14,9 +23,15 @@ $(document).ready(function () { | |||
function linkUploadDelete(element, deleteUrl) { | |||
element.click(function () { | |||
bootbox.dialog({ | |||
var dialog = bootbox.dialog({ | |||
title: "Direct Deletion URL", | |||
message: '<input type="text" class="form-control" id="deletionLink" onClick="this.select();" value="' + deleteUrl + '">' | |||
message: '<input type="text" class="form-control" id="deletionLink" value="' + deleteUrl + '">' | |||
}); | |||
dialog.init(function() { | |||
dialog.find('#deletionLink').click(function() { | |||
$(this).select(); | |||
}); | |||
}); | |||
return false; | |||
}); | |||
@@ -76,6 +91,7 @@ function linkCopyAll(element) { | |||
var urlList = allUploads.join(); | |||
copyTextToClipboard(urlList); | |||
} | |||
element.popover('show'); | |||
}); | |||
} | |||
@@ -1,8 +1,8 @@ | |||
@model Teknik.Areas.Upload.ViewModels.DownloadViewModel | |||
@model Teknik.Areas.Upload.ViewModels.DownloadViewModel | |||
@using Teknik.Utilities | |||
<script> | |||
<script nonce="@Context.Items[Constants.NONCE_KEY]"> | |||
var encScriptSrc = '@Scripts.Url("~/bundles/cryptoWorker")'; | |||
var aesScriptSrc = '@Scripts.Url("~/bundles/crypto")'; | |||
var downloadDataUrl = '@Url.SubRouteUrl("upload", "Upload.Action", new { action = "DownloadData" })'; |
@@ -1,4 +1,4 @@ | |||
@model Teknik.Areas.Upload.ViewModels.UploadViewModel | |||
@model Teknik.Areas.Upload.ViewModels.UploadViewModel | |||
@using Teknik.Utilities | |||
@using Teknik.Areas.Vault.Models | |||
@@ -15,7 +15,7 @@ | |||
} | |||
} | |||
<script> | |||
<script nonce="@Context.Items[Constants.NONCE_KEY]"> | |||
var encScriptSrc = '@Scripts.Url("~/bundles/cryptoWorker")'; | |||
var aesScriptSrc = '@Scripts.Url("~/bundles/crypto")'; | |||
var uploadFileURL = '@Url.SubRouteUrl(Model.CurrentSub, "Upload.Action", new { action = "Upload" })'; | |||
@@ -64,7 +64,7 @@ | |||
<div class="row" id="upload-action-buttons" style="display: none"> | |||
<div class="col-sm-12"> | |||
<div class="btn-group pull-right" role="group"> | |||
<button type="button" class="btn btn-default btn-sm" id="copy-all"><i class="fa fa-clipboard"></i> Copy All Links</button> | |||
<button type="button" class="btn btn-default btn-sm" id="copy-all" data-toggle="popover" data-trigger="manual" data-placement="top" data-content="Copied to Clipboard" data-container="body"><i class="fa fa-clipboard"></i> Copy All Links</button> | |||
<button type="button" class="btn btn-default btn-sm" id="create-vault"><i class="fa fa-folder"></i> Create Vault</button> | |||
@if (User.Identity.IsAuthenticated && Model.Vaults != null && Model.Vaults.Any()) | |||
{ |
@@ -7,12 +7,18 @@ $(document).ready(function () { | |||
$this.popover('hide'); | |||
}, 3000); | |||
}); | |||
}); | |||
function copyCode(inviteCodeId, inviteCode) { | |||
copyTextToClipboard(inviteCode); | |||
$('#copyCode_' + inviteCodeId + '').popover('show'); | |||
} | |||
$(".copyCodeBtn").click(function () { | |||
var code = $(this).attr("data-code"); | |||
copyTextToClipboard(code); | |||
$(this).popover('show'); | |||
}); | |||
$(".extCodeBtn").click(function () { | |||
var codeId = $(this).attr("data-codeid"); | |||
createExternalLink(codeId); | |||
}); | |||
}); | |||
function createExternalLink(inviteCodeId) { | |||
$.ajax({ | |||
@@ -21,9 +27,15 @@ function createExternalLink(inviteCodeId) { | |||
data: AddAntiForgeryToken({ inviteCodeId: inviteCodeId }), | |||
success: function (response) { | |||
if (response.result) { | |||
bootbox.dialog({ | |||
var dialog = bootbox.dialog({ | |||
title: "Send this link to someone to claim this invite code.", | |||
message: '<input type="text" class="form-control" id="inviteCodeLink" onClick="this.select();" value="' + response.result + '">' | |||
message: '<input type="text" class="form-control" id="inviteCodeLink" value="' + response.result + '">' | |||
}); | |||
dialog.init(function () { | |||
dialog.find('#inviteCodeLink').click(function () { | |||
$(this).select(); | |||
}); | |||
}); | |||
} | |||
else { |
@@ -58,4 +58,8 @@ $(document).ready(function () { | |||
} | |||
}); | |||
}); | |||
$('#pgpKeyBlock').click(function () { | |||
SelectAll('pgpKeyBlock'); | |||
}); | |||
}); |
@@ -79,7 +79,7 @@ $(document).ready(function () { | |||
data: AddAntiForgeryToken({ name: result }), | |||
success: function (response) { | |||
if (response.result) { | |||
bootbox.dialog({ | |||
var dialog = bootbox.dialog({ | |||
closeButton: false, | |||
buttons: { | |||
close: { | |||
@@ -89,12 +89,33 @@ $(document).ready(function () { | |||
if ($('#noAuthTokens')) { | |||
$('#noAuthTokens').remove(); | |||
} | |||
$('#authTokenList').append(response.result.html); | |||
var item = $(response.result.html); | |||
var deleteBtn = item.find('.deleteAuthToken'); | |||
var editBtn = item.find('.editAuthToken'); | |||
deleteBtn.click(function () { | |||
var authTokenId = $(this).attr("data-authid"); | |||
deleteAuthToken(authTokenId); | |||
}); | |||
editBtn.click(function () { | |||
var authTokenId = $(this).attr("data-authid"); | |||
editAuthToken(authTokenId); | |||
}); | |||
$('#authTokenList').append(item); | |||
} | |||
} | |||
}, | |||
title: "Authentication Token", | |||
message: '<label for="authToken">Make sure to copy your new personal access token now.<br />You won\'t be able to see it again!</label><input type="text" class="form-control" id="authToken" onClick="this.select();" value="' + response.result.token + '">', | |||
message: '<label for="authToken">Make sure to copy your new personal access token now.<br />You won\'t be able to see it again!</label><input type="text" class="form-control" id="authToken" value="' + response.result.token + '">', | |||
}); | |||
dialog.init(function () { | |||
dialog.find('#authToken').click(function () { | |||
$(this).select(); | |||
}); | |||
}); | |||
} | |||
else { | |||
@@ -223,6 +244,16 @@ $(document).ready(function () { | |||
}); | |||
return false; | |||
}); | |||
$(".deleteAuthToken").click(function() { | |||
var authTokenId = $(this).attr("data-authid"); | |||
deleteAuthToken(authTokenId); | |||
}); | |||
$(".editAuthToken").click(function () { | |||
var authTokenId = $(this).attr("data-authid"); | |||
editAuthToken(authTokenId); | |||
}); | |||
}); | |||
function editAuthToken(authTokenId) { |
@@ -1,9 +1,9 @@ | |||
@model Teknik.Areas.Users.ViewModels.AuthTokenViewModel | |||
@model Teknik.Areas.Users.ViewModels.AuthTokenViewModel | |||
<li class="list-group-item" id="authToken_@Model.AuthTokenId"> | |||
<div class="btn-group btn-group-sm pull-right" role="group" aria-label="..."> | |||
<button type="button" class="btn btn-default" onclick="editAuthToken(@Model.AuthTokenId)">Edit</button> | |||
<button type="button" class="btn btn-danger text-danger" onclick="deleteAuthToken(@Model.AuthTokenId)">Delete</button> | |||
<button type="button" class="btn btn-default editAuthToken" id="editAuthToken_@Model.AuthTokenId" data-authId="@Model.AuthTokenId">Edit</button> | |||
<button type="button" class="btn btn-danger text-danger deleteAuthToken" id="deleteAuthToken_@Model.AuthTokenId" data-authId="@Model.AuthTokenId">Delete</button> | |||
</div> | |||
<h4 class="list-group-item-heading" id="authTokenName_@Model.AuthTokenId">@Model.Name</h4> | |||
@if (Model.LastDateUsed.HasValue) |
@@ -7,7 +7,7 @@ | |||
Layout = "~/Areas/User/Views/User/Settings/Settings.cshtml"; | |||
} | |||
<script> | |||
<script nonce="@Context.Items[Constants.NONCE_KEY]"> | |||
var editURL = '@Url.SubRouteUrl("user", "User.Action", new { action = "EditBlog" })'; | |||
</script> | |||
@@ -9,8 +9,8 @@ | |||
@if (!codeClaimed) | |||
{ | |||
<div class="btn-group btn-group-sm pull-right" role="group" aria-label="..."> | |||
<button type="button" class="btn btn-default" id="copyCode_@Model.InviteCodeId" onclick="copyCode(@(Model.InviteCodeId), '@(Model.Code)');" data-toggle="popover" data-trigger="manual" data-placement="top" data-content="Copied to Clipboard" data-container="body"><i class="fa fa-clipboard"></i></button> | |||
<button type="button" class="btn btn-default" onclick="createExternalLink(@Model.InviteCodeId);"><i class="fa fa-external-link"></i></button> | |||
<button type="button" class="btn btn-default copyCodeBtn" id="copyCodeBtn_@Model.InviteCodeId" data-code="@Model.Code" data-toggle="popover" data-trigger="manual" data-placement="top" data-content="Copied to Clipboard" data-container="body"><i class="fa fa-clipboard"></i></button> | |||
<button type="button" class="btn btn-default extCodeBtn" id="extCodeBtn_@Model.InviteCodeId" data-codeid="@Model.InviteCodeId"><i class="fa fa-external-link"></i></button> | |||
</div> | |||
} | |||
<h4 class="list-group-item-heading" id="inviteCode_Code_@Model.InviteCodeId">@Model.Code</h4> |
@@ -10,7 +10,7 @@ | |||
@Styles.Render("~/Content/user/settings/invite") | |||
@Scripts.Render("~/bundles/user/settings/invite") | |||
<script> | |||
<script nonce="@Context.Items[Constants.NONCE_KEY]"> | |||
var createExternalLinkURL = '@Url.SubRouteUrl("user", "User.Action", new { action = "CreateInviteCodeLink" })'; | |||
</script> | |||
@@ -7,7 +7,7 @@ | |||
Layout = "~/Areas/User/Views/User/Settings/Settings.cshtml"; | |||
} | |||
<script> | |||
<script nonce="@Context.Items[Constants.NONCE_KEY]"> | |||
var editURL = '@Url.SubRouteUrl("user", "User.Action", new { action = "EditProfile" })'; | |||
</script> | |||
@@ -7,7 +7,7 @@ | |||
Layout = "~/Areas/User/Views/User/Settings/Settings.cshtml"; | |||
} | |||
<script> | |||
<script nonce="@Context.Items[Constants.NONCE_KEY]"> | |||
var homeUrl = '@Url.SubRouteUrl("www", "Home.Index")'; | |||
var editURL = '@Url.SubRouteUrl("user", "User.Action", new { action = "EditSecurity" })'; | |||
var resendVerifyURL = '@Url.SubRouteUrl("user", "User.Action", new { action = "ResendVerifyRecoveryEmail"})'; |
@@ -10,7 +10,7 @@ | |||
@Styles.Render("~/Content/user/settings") | |||
@Scripts.Render("~/bundles/user/settings") | |||
<script> | |||
<script nonce="@Context.Items[Constants.NONCE_KEY]"> | |||
var homeUrl = '@Url.SubRouteUrl("www", "Home.Index")'; | |||
var deleteUserURL = '@Url.SubRouteUrl("user", "User.Action", new { action = "Delete" })'; | |||
</script> |
@@ -7,7 +7,7 @@ | |||
Layout = "~/Areas/User/Views/User/Settings/Settings.cshtml"; | |||
} | |||
<script> | |||
<script nonce="@Context.Items[Constants.NONCE_KEY]"> | |||
var homeUrl = '@Url.SubRouteUrl("www", "Home.Index")'; | |||
var editURL = '@Url.SubRouteUrl("user", "User.Action", new { action = "EditUpload" })'; | |||
</script> |
@@ -1,8 +1,8 @@ | |||
@model Teknik.Areas.Users.ViewModels.TwoFactorViewModel | |||
@model Teknik.Areas.Users.ViewModels.TwoFactorViewModel | |||
@using Teknik.Utilities | |||
<script> | |||
<script nonce="@Context.Items[Constants.NONCE_KEY]"> | |||
var confirmAuthCodeURL = '@Url.SubRouteUrl("user", "User.Action", new { action = "ConfirmAuthenticatorCode" })'; | |||
</script> | |||
@@ -48,4 +48,4 @@ | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> |
@@ -3,7 +3,7 @@ | |||
@using Teknik.Utilities | |||
@using Teknik.Utilities.Cryptography | |||
<script> | |||
<script nonce="@Context.Items[Constants.NONCE_KEY]"> | |||
var generateDeleteKeyURL = '@Url.SubRouteUrl("u", "Upload.GenerateDeleteKey")'; | |||
var deleteVaultURL = '@Url.SubRouteUrl("v", "Vault.DeleteVault")'; | |||
</script> | |||
@@ -73,7 +73,7 @@ | |||
<br /> | |||
<div class="row"> | |||
<div class="col-sm-12"> | |||
<textarea class="form-control wmd-input" name="pgpKeyBlock" id="pgpKeyBlock" title="Public Key" rows="10" onClick="SelectAll('pgpKeyBlock');" readonly>@Model.SecuritySettings.PGPSignature</textarea> | |||
<textarea class="form-control wmd-input" name="pgpKeyBlock" id="pgpKeyBlock" title="Public Key" rows="10" readonly>@Model.SecuritySettings.PGPSignature</textarea> | |||
</div> | |||
</div> | |||
</div> |
@@ -1,4 +1,4 @@ | |||
@model Teknik.Areas.Vault.ViewModels.ModifyVaultViewModel | |||
@model Teknik.Areas.Vault.ViewModels.ModifyVaultViewModel | |||
@using Teknik.Utilities | |||
@using Teknik.Areas.Vault.ViewModels | |||
@@ -10,7 +10,7 @@ | |||
string title = (Model.isEdit) ? "Edit Vault" : "Create a New Vault"; | |||
} | |||
<script type="text/javascript"> | |||
<script nonce="@Context.Items[Constants.NONCE_KEY]"> | |||
var helpURL = '@Url.SubRouteUrl("help", "Help.Markdown")'; | |||
var validateItemURL = '@Url.SubRouteUrl(Model.CurrentSub, "Vault.Action", new { action = "ValidateItem" })'; |
@@ -1,4 +1,5 @@ | |||
@model Teknik.Areas.Vault.ViewModels.ModifyVaultItemViewModel | |||
@model Teknik.Areas.Vault.ViewModels.ModifyVaultItemViewModel | |||
@using Teknik.Utilities | |||
@{ | |||
bool isTemplate = (Model.isTemplate); | |||
} | |||
@@ -47,7 +48,7 @@ | |||
</div> | |||
@if (!isTemplate) | |||
{ | |||
<script type="text/javascript"> | |||
<script nonce="@Context.Items[Constants.NONCE_KEY]"> | |||
$(document).ready(function () { | |||
var itemDiv = $('#vault-item-@Model.index'); | |||
@@ -62,4 +63,4 @@ | |||
}); | |||
</script> | |||
} | |||
</div> | |||
</div> |
@@ -1,4 +1,4 @@ | |||
@model Teknik.Areas.Vault.ViewModels.VaultViewModel | |||
@model Teknik.Areas.Vault.ViewModels.VaultViewModel | |||
@using Teknik.Areas.Vault.ViewModels | |||
@using Teknik.Utilities | |||
@@ -6,7 +6,7 @@ | |||
@Styles.Render("~/Content/vault") | |||
<script type="text/javascript"> | |||
<script nonce="@Context.Items[Constants.NONCE_KEY]"> | |||
var helpURL = '@Url.SubRouteUrl("help", "Help.Markdown")'; | |||
var validateItemURL = '@Url.SubRouteUrl(Model.CurrentSub, "Vault.Action", new { action = "ValidateItem" })'; | |||
var modifyVaultURL = '@Url.SubRouteUrl(Model.CurrentSub, "Vault.Action", new { action = "EditVault" })'; | |||
@@ -63,4 +63,4 @@ | |||
} | |||
</div> | |||
@Scripts.Render("~/bundles/vault") | |||
@Scripts.Render("~/bundles/vault") |
@@ -43,8 +43,12 @@ namespace Teknik | |||
{ | |||
// Start the generation time stopwatcher | |||
var stopwatch = new Stopwatch(); | |||
HttpContext.Current.Items["Stopwatch"] = stopwatch; | |||
HttpContext.Current.Items[Constants.PERF_KEY] = stopwatch; | |||
stopwatch.Start(); | |||
// Generate the NONCE used for this request | |||
string nonce = Convert.ToBase64String(Encoding.UTF8.GetBytes(StringHelper.RandomString(24))); | |||
HttpContext.Current.Items[Constants.NONCE_KEY] = nonce; | |||
} | |||
protected void Application_PreSendRequestHeaders(object sender, EventArgs e) | |||
@@ -60,20 +64,13 @@ namespace Teknik | |||
HttpContext context = HttpContext.Current; | |||
// Set the generation time in the header | |||
Stopwatch stopwatch = (Stopwatch)context.Items["Stopwatch"]; | |||
Stopwatch stopwatch = (Stopwatch)context.Items[Constants.PERF_KEY]; | |||
stopwatch.Stop(); | |||
TimeSpan ts = stopwatch.Elapsed; | |||
string elapsedTime = String.Format("{0} seconds", ts.TotalSeconds); | |||
context.Response.AppendHeader("GenerationTime", elapsedTime); | |||
// Allow this domain, or everything if local | |||
string origin = (Request.IsLocal) ? "*" : context.Request.Headers.Get("Origin"); | |||
if (!string.IsNullOrEmpty(origin)) | |||
{ | |||
context.Response.AppendHeader("Access-Control-Allow-Origin", origin); | |||
} | |||
} | |||
catch (Exception ex) | |||
{ |
@@ -0,0 +1,45 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Web; | |||
using Teknik.Configuration; | |||
using Teknik.Utilities; | |||
namespace Teknik.Modules | |||
{ | |||
public class CORSModule : IHttpModule | |||
{ | |||
public void Dispose() | |||
{ | |||
} | |||
public void Init(HttpApplication context) | |||
{ | |||
context.PreSendRequestHeaders += delegate(object sender, EventArgs args) | |||
{ | |||
HttpContext requestContext = ((HttpApplication)sender).Context; | |||
Config config = Config.Load(); | |||
// Allow this domain, or everything if local | |||
string origin = (requestContext.Request.IsLocal) ? "*" : requestContext.Request.Headers.Get("Origin"); | |||
string domain = (string.IsNullOrEmpty(origin)) ? string.Empty : origin.GetDomain(); | |||
if (string.IsNullOrEmpty(origin)) | |||
{ | |||
string sub = requestContext.Request.Url.Host.GetSubdomain(); | |||
origin = (string.IsNullOrEmpty(sub)) ? config.Host : sub + "." + config.Host; | |||
} | |||
else | |||
{ | |||
if (domain != config.Host) | |||
{ | |||
string sub = origin.GetSubdomain(); | |||
origin = (string.IsNullOrEmpty(sub)) ? config.Host : sub + "." + config.Host; | |||
} | |||
} | |||
requestContext.Response.AppendHeader("Access-Control-Allow-Origin", origin); | |||
}; | |||
} | |||
} | |||
} |
@@ -0,0 +1,49 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Web; | |||
using Teknik.Configuration; | |||
using Teknik.Utilities; | |||
namespace Teknik.Modules | |||
{ | |||
public class CSPModule : IHttpModule | |||
{ | |||
public void Dispose() | |||
{ | |||
} | |||
public void Init(HttpApplication context) | |||
{ | |||
context.PreSendRequestHeaders += delegate (object sender, EventArgs args) | |||
{ | |||
HttpContext requestContext = ((HttpApplication)sender).Context; | |||
if (!requestContext.Request.IsLocal) | |||
{ | |||
// Default to nothing allowed | |||
string allowedDomain = "'none'"; | |||
// Allow this domain | |||
string host = requestContext.Request.Url.Host; | |||
if (!string.IsNullOrEmpty(host)) | |||
{ | |||
string domain = host.GetDomain(); | |||
string sub = host.GetSubdomain(); | |||
allowedDomain = string.Format("{0}.{1} {1}", (string.IsNullOrEmpty(sub) ? "*" : sub), domain); | |||
} | |||
// If a CDN is enabled, then add the cdn host | |||
Config config = Config.Load(); | |||
if (config.UseCdn) | |||
{ | |||
allowedDomain += " " + config.CdnHost; | |||
} | |||
requestContext.Response.AppendHeader("Content-Security-Policy", string.Format("default-src 'none'; script-src blob: 'unsafe-eval' 'nonce-{1}' {0}; style-src 'unsafe-inline' {0}; img-src data: *; font-src data: {0}; connect-src wss: blob: data: {0}; media-src *; worker-src blob: mediastream: {0}; form-action {0}; base-uri {0}; frame-ancestors {0};", allowedDomain, requestContext.Items[Constants.NONCE_KEY])); | |||
} | |||
}; | |||
} | |||
} | |||
} |
@@ -1,4 +1,4 @@ | |||
using System; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Diagnostics; | |||
using System.Linq; | |||
@@ -6,6 +6,7 @@ using System.Text; | |||
using System.Threading.Tasks; | |||
using System.Web; | |||
using System.Web.Mvc; | |||
using Teknik.Utilities; | |||
namespace Teknik.Modules | |||
{ | |||
@@ -35,7 +36,7 @@ namespace Teknik.Modules | |||
string result = string.Format("{0:F0}", ms); | |||
requestContext.Response.Write( | |||
"<script type=\"text/javascript\">" + | |||
"<script nonce=\"" + requestContext.Items[Constants.NONCE_KEY] + "\">" + | |||
"var pageGenerationTime = '" + result + "';" + | |||
"pageloadStopTimer();" + | |||
"</script >"); |
@@ -79,6 +79,8 @@ $(document).ready(function () { | |||
}); | |||
return false; | |||
}); | |||
}); | |||
$(function () { | |||
@@ -107,7 +109,9 @@ $(function () { | |||
} | |||
// Auo-select bitcoin address | |||
$('#bitcoin_address_footer').on('click', 'input[type=text]', function () { this.select(); }); | |||
$('#bitcoin_address_footer').click(function() { | |||
SelectAll('bitcoin_address_footer'); | |||
}); | |||
// Setup anti-forgery functions | |||
$.appendAntiForgeryToken = function (data, token) { |
@@ -317,6 +317,8 @@ | |||
<Compile Include="Attributes\TeknikAuthorizeAttribute.cs" /> | |||
<Compile Include="Hubs\IRCClientHub.cs" /> | |||
<Compile Include="Modules\BlacklistModule.cs" /> | |||
<Compile Include="Modules\CORSModule.cs" /> | |||
<Compile Include="Modules\CSPModule.cs" /> | |||
<Compile Include="Modules\UserAuthModule.cs" /> | |||
<Compile Include="Security\ITeknikPrincipal.cs" /> | |||
<Compile Include="Security\TeknikPrincipal.cs" /> |
@@ -32,7 +32,7 @@ | |||
<div class="form-group"> | |||
<div class="input-group"> | |||
<span class="input-group-addon" id="basic-addon1"><i class="fa fa-bitcoin"></i></span> | |||
<input type="text" class="form-control input-sm" name="bitcoin_address_footer" id="bitcoin_address_footer" value="@Model.Config.BitcoinAddress" onClick="this.setSelectionRange(0, this.value.length)" readonly> | |||
<input type="text" class="form-control input-sm" name="bitcoin_address_footer" id="bitcoin_address_footer" value="@Model.Config.BitcoinAddress" readonly> | |||
</div> | |||
</div> | |||
</form> |
@@ -25,7 +25,7 @@ | |||
<meta name="wot-verification" content="e858b91d99b767ad70db" /> | |||
<!-- Start of page 'load' --> | |||
<script type="text/javascript"> | |||
<script nonce="@Context.Items[Constants.NONCE_KEY]"> | |||
var startTime = new Date(); | |||
</script> | |||
@@ -71,7 +71,7 @@ | |||
</div> | |||
@Html.Partial("_Footer") | |||
<script type="text/javascript"> | |||
<script nonce="@Context.Items[Constants.NONCE_KEY]"> | |||
$(document).ready(function () {pageloadDoTimer();}); | |||
</script> | |||
</body> |
@@ -57,6 +57,8 @@ | |||
<add name="PerfModule" type="Teknik.Modules.PerformanceMonitorModule, Teknik" /> | |||
<add name="UserAuthModule" type="Teknik.Modules.UserAuthModule, Teknik" /> | |||
<add name="BlacklistModule" type="Teknik.Modules.BlacklistModule, Teknik" /> | |||
<add name="CORSModule" type="Teknik.Modules.CORSModule, Teknik"/> | |||
<add name="CSPModule" type="Teknik.Modules.CSPModule, Teknik"/> | |||
<remove name="UrlRoutingModule-4.0" /> | |||
<add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" preCondition="" /> | |||
</modules> | |||
@@ -135,6 +137,9 @@ | |||
<add name="Access-Control-Allow-Headers" value="Authorization, Accept, Origin, Content-Type, X-Requested-With, Connection, Transfer-Encoding" /> | |||
<add name="strict-transport-security" value="max-age=31536000; includeSubdomains; preload" /> | |||
<add name="X-XSS-Protection" value="1; mode=block" /> | |||
<add name="X-Content-Type-Options" value="nosniff"/> | |||
<add name="Referrer-Policy" value="no-referrer, strict-origin-when-cross-origin"/> | |||
<add name="Public-Key-Pins" value="max-age=300; includeSubDomains; pin-sha256="grX4Ta9HpZx6tSHkmCrvpApTQGo67CYDnvprLg5yRME="; pin-sha256="C5+lpZ7tcVwmwQIMcRtPbsQtWLABXhQzejna0wHFr8M=";"/> | |||
<add name="Vary" value="Origin" /> | |||
</customHeaders> | |||
</httpProtocol> | |||
@@ -190,16 +195,16 @@ | |||
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" /> | |||
</providers> | |||
</entityFramework> | |||
<system.data> | |||
<DbProviderFactories> | |||
<remove invariant="MySql.Data.MySqlClient" /> | |||
<add description=".Net Framework Data Provider for MySQL" invariant="MySql.Data.MySqlClient" name="MySQL Data Provider" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.10.6.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" /> | |||
</DbProviderFactories> | |||
</system.data> | |||
<system.codedom> | |||
<compilers> | |||
<compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.8.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:1659;1699;1701" /> | |||
<compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.8.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:41008 /define:_MYTYPE=\"Web\" /optionInfer+" /> | |||
</compilers> | |||
</system.codedom> | |||
<system.data> | |||
<DbProviderFactories> | |||
<remove invariant="MySql.Data.MySqlClient" /> | |||
<add description=".Net Framework Data Provider for MySQL" invariant="MySql.Data.MySqlClient" name="MySQL Data Provider" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.10.6.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" /> | |||
</DbProviderFactories> | |||
</system.data> | |||
<system.codedom> | |||
<compilers> | |||
<compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.8.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:1659;1699;1701" /> | |||
<compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.8.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:41008 /define:_MYTYPE=\"Web\" /optionInfer+" /> | |||
</compilers> | |||
</system.codedom> | |||
</configuration> |
@@ -1,4 +1,4 @@ | |||
using System; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Security.Cryptography; | |||
@@ -39,22 +39,15 @@ namespace Teknik.Utilities | |||
} | |||
public virtual void Process(BundleContext context, BundleResponse response) | |||
{ | |||
// Don't continue if we aren't using a CDN | |||
if (!context.BundleCollection.UseCdn) | |||
{ | |||
{ | |||
// If we are using a CDN, then set the host as the CDN host | |||
if (!context.BundleCollection.UseCdn || string.IsNullOrEmpty(CdnHost)) | |||
return; | |||
} | |||
// Get the directory and filename for the bundle | |||
var dir = VirtualPathUtility.GetDirectory(context.BundleVirtualPath).TrimStart('/').TrimStart('~').TrimStart('/').TrimEnd('/'); | |||
var file = VirtualPathUtility.GetFileName(context.BundleVirtualPath); | |||
var group = string.Format("{0}{1}", file, Ext); | |||
if (string.IsNullOrEmpty(CdnHost)) | |||
{ | |||
return; | |||
} | |||
var group = $"{file}{Ext}"; | |||
using (var hashAlgorithm = Cryptography.SHA256.CreateHashAlgorithm()) | |||
{ |
@@ -1,4 +1,4 @@ | |||
namespace Teknik.Utilities | |||
namespace Teknik.Utilities | |||
{ | |||
public static class Constants | |||
{ | |||
@@ -9,5 +9,9 @@ | |||
public const string ROBOTS_PATH = "~/App_Data/robots.txt"; | |||
public const string LOG_FILE_NAME_PREFIX = "Teknik"; | |||
public const string LOG_FILE_EXT = ".log"; | |||
public const string PERF_KEY = "Stopwatch"; | |||
public const string NONCE_KEY = "Nonce"; | |||
} | |||
} |