Skip to content

Commit

Permalink
add an option to disable csrf (+ more js fixes)
Browse files Browse the repository at this point in the history
make it so that uploads will have extensions even if they are derived from a canvas (drawings, avatars)
fix uploads happening like 20 times when you drag or paste sometimes
fix notification links requiring you to hit back twice to go back to the notifications page for
  • Loading branch information
ariankordi committed May 20, 2023
1 parent c6a5bbe commit 965aa22
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 103 deletions.
26 changes: 16 additions & 10 deletions assets/js/indigo.js
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,7 @@ var Olv = Olv || {};
onDataHrefClick: function(c) {
if (a(c.target).attr("data-href")) {
b.Net.go($(this).attr("data-href"));
return;
}
if (!c.isDefaultPrevented() && !a(c.target).closest("a,button").length) {
var d = a(this);
Expand Down Expand Up @@ -3782,33 +3783,38 @@ function updateTime() {
var timestamp = timestamps.eq(i);
var since = new Date().getTime() - timestamp.attr('time');
var time = new Date(since);
var timestampText;
if(time < 1000) {
timestamp.text('Less than a second ago');
timestampText = 'Less than a second ago';
} else if(time < 2000) {
timestamp.text('1 second ago');
timestampText = '1 second ago';
} else if(time < 60000) {
timestamp.text(Math.floor(since / 1000) + ' seconds ago');
timestampText = Math.floor(since / 1000) + ' seconds ago';
} else if(time < 120000) {
timestamp.text('1 minute ago');
timestampText = '1 minute ago';
} else if(time < 3600000) {
timestamp.text(Math.floor(since / 1000 / 60) + ' minutes ago');
timestampText = Math.floor(since / 1000 / 60) + ' minutes ago';
} else if(time < 7200000) {
timestamp.text('1 hour ago');
timestampText = '1 hour ago';
} else if(time < 86400000) {
timestamp.text(Math.floor(since / 1000 / 60 / 60) + ' hours ago');
timestampText = Math.floor(since / 1000 / 60 / 60) + ' hours ago';
} else if(time < 172800000) {
timestamp.text('1 day ago');
timestampText = '1 day ago';
} else if(time < 345600000) {
timestamp.text(Math.floor(since / 1000 / 60 / 60 / 24) + ' days ago');
timestampText = Math.floor(since / 1000 / 60 / 60 / 24) + ' days ago';
} else {
var dateTime = new Date(parseInt(timestamp.attr('time')));
var mariosPrincessSex = dateTime.getHours() % 12;
if(mariosPrincessSex == 0) {
mariosPrincessSex = 12;
}
timestamp.text((dateTime.getMonth() + 1).toString().padStart(2, "0") + "/" + dateTime.getDate().toString().padStart(2, "0") + "/" + dateTime.getFullYear() + " " + mariosPrincessSex + ":" + dateTime.getMinutes().toString().padStart(2, "0") + " " + (dateTime.getHours() >= 12 ? "PM" : "AM"));
timestampText = (dateTime.getMonth() + 1).toString().padStart(2, "0") + "/" + dateTime.getDate().toString().padStart(2, "0") + "/" + dateTime.getFullYear() + " " + mariosPrincessSex + ":" + dateTime.getMinutes().toString().padStart(2, "0") + " " + (dateTime.getHours() >= 12 ? "PM" : "AM");
timestamp.removeClass('update');
}
// only update the timestamp in the dom if it actually changed
if(timestamp[0].innerHTML != timestampText) {
timestamp.text(timestampText);
}
}
}
updateTime();
Expand Down
176 changes: 92 additions & 84 deletions assets/js/upload.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,96 +84,104 @@ function postFile(file, fileType, isDrawing, inputName) {
}
});
}
function init() {
$(".file-button").off().on("change", function(event) {
console.log(event);
var inputName = "image";
if($(this).attr("id") !== undefined) inputName = $(this).attr("id");
if(this.files.length) {
Olv.Form.toggleDisabled($("input.post-button"), true);
$("input[name=" + inputName + "]").siblings(".file-button").attr("disabled", "disabled");
$("input[name=" + inputName + "]").siblings(".file-upload-button").text("Uploading...");
var fileType = this.files[0].type;
var file = this.files[0];
if(($(".file-upload-button").hasClass("for-avatar") || inputName === "icon") && fileType !== "image/gif") {
var img = new Image();
img.src = URL.createObjectURL(file);
img.onload = function() {
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
ctx.imageSmoothingQuality = "high";
var size = 128, factor, startX, startY, resizeWidth, resizeHeight;
canvas.width = size;
canvas.height = size;
if(img.width > img.height) {
factor = img.width / img.height;
startX = (img.width - img.height) / 2;
startY = 0;
resizeWidth = size * factor;
resizeHeight = size;
} else if(img.height > img.width) {
factor = img.height / img.width;
startX = 0;
startY = (img.height - img.width) / 2;
resizeWidth = size;
resizeHeight = size * factor;
} else {
factor = 1;
startX = 0;
startY = 0;
resizeWidth = size;
resizeHeight = size;
}
ctx.drawImage(img, startX, startY, img.width, img.height, 0, 0, resizeWidth, resizeHeight);
canvas.toBlob(function(blob) {
postFile(blob, fileType, false, inputName);
});


function handleChange(event) {
console.log(event);
var inputName = "image";
if($(this).attr("id") !== undefined) inputName = $(this).attr("id");
if(this.files.length) {
Olv.Form.toggleDisabled($("input.post-button"), true);
$("input[name=" + inputName + "]").siblings(".file-button").attr("disabled", "disabled");
$("input[name=" + inputName + "]").siblings(".file-upload-button").text("Uploading...");
var fileType = this.files[0].type;
var file = this.files[0];
if(($(".file-upload-button").hasClass("for-avatar") || inputName === "icon") && fileType !== "image/gif") {
var img = new Image();
img.src = URL.createObjectURL(file);
img.onload = function() {
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
ctx.imageSmoothingQuality = "high";
var size = 128, factor, startX, startY, resizeWidth, resizeHeight;
canvas.width = size;
canvas.height = size;
if(img.width > img.height) {
factor = img.width / img.height;
startX = (img.width - img.height) / 2;
startY = 0;
resizeWidth = size * factor;
resizeHeight = size;
} else if(img.height > img.width) {
factor = img.height / img.width;
startX = 0;
startY = (img.height - img.width) / 2;
resizeWidth = size;
resizeHeight = size * factor;
} else {
factor = 1;
startX = 0;
startY = 0;
resizeWidth = size;
resizeHeight = size;
}
} else {
postFile(file, fileType, false, inputName);
ctx.drawImage(img, startX, startY, img.width, img.height, 0, 0, resizeWidth, resizeHeight);
canvas.toBlob(function(blob) {
postFile(blob, fileType, false, inputName);
});
}
} else {
$("input[name=image]").val("");
if(!$(".file-upload-button").hasClass("for-avatar")) {
$(".preview-container").css("display", "none");
checkForm();
} else {
postFile(file, fileType, false, inputName);
}
} else {
$("input[name=image]").val("");
if(!$(".file-upload-button").hasClass("for-avatar")) {
$(".preview-container").css("display", "none");
checkForm();
}
});
$(document).on("dragover dragenter", function(event) {
event.stopPropagation();
event.preventDefault();
event.originalEvent.dataTransfer.dropEffect = "copy";
});
$(document).on("drop paste", function(event) {
if($(this).siblings(".file-button").attr("disabled")) {
return;
}
var files;
switch(event.type) {
case "drop":
files = event.originalEvent.dataTransfer.files;
break;
case "paste":
if(event.originalEvent.clipboardData.files.length == 0) {
return;
}
files = event.originalEvent.clipboardData.files;
break;
default:
}
}

function handleDropPaste(event) {
if($(this).siblings(".file-button").attr("disabled")) {
return;
}
var files;
switch(event.type) {
case "drop":
files = event.originalEvent.dataTransfer.files;
break;
case "paste":
if(event.originalEvent.clipboardData.files.length == 0) {
return;
}
event.stopPropagation();
event.preventDefault();
}
files = event.originalEvent.clipboardData.files;
break;
default:
return;
}
event.stopPropagation();
event.preventDefault();

if(files[0].type.startsWith("image/") || files[0].type.startsWith("audio/") || files[0].type.startsWith("video/")) {
$(".file-button")[0].files = files;
$(".file-button").trigger("change");
} else {
Olv.showMessage("Attachment upload failed", "You can only upload images, audio or videos.");
}
});
if(files[0].type.startsWith("image/") || files[0].type.startsWith("audio/") || files[0].type.startsWith("video/")) {
$(".file-button")[0].files = files;
$(".file-button").trigger("change");
} else {
Olv.showMessage("Attachment upload failed", "You can only upload images, audio or videos.");
}
}

function handleDrag(event) {
event.stopPropagation();
event.preventDefault();
event.originalEvent.dataTransfer.dropEffect = "copy";
}

function init() {
$(".file-button").off().on("change", handleChange);
$(document).off("dragover dragenter").on("dragover dragenter", handleDrag);
$(document).off("drop paste").on("drop paste", handleDropPaste);
}

$(document).off("ready, pjax:end", init).on("ready, pjax:end", init);
$(document).off("ready", init).off("pjax:end", init).on("ready", init).on("pjax:end", init);
init();
1 change: 1 addition & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"SocketOwner": "www-data",
"Port": ":80",
"GzipEnabled": true,
"CSRFProtectDisable": true,
"SSL": {
"Enabled": false,
"Certificate": "cert.pem",
Expand Down
11 changes: 10 additions & 1 deletion handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"io"
"io/ioutil"
"path/filepath"
"mime"
"mime/multipart"
"net"
"net/http"
Expand Down Expand Up @@ -6281,7 +6282,15 @@ func uploadImage(w http.ResponseWriter, r *http.Request) {
return
}
case "local":
imageFilePath := settings.ImageHost.ImageEndpoint + "/" + hash + filepath.Ext(handler.Filename)
fileExtension := filepath.Ext(handler.Filename)
if fileExtension == "" {
// if extension is not provided then use mime type
extensions, err := mime.ExtensionsByType(handler.Header.Get("Content-Type"))
if err == nil && len(extensions) != 0 {
fileExtension = extensions[0] // Use the first extension in the list
}
}
imageFilePath := settings.ImageHost.ImageEndpoint + "/" + hash + fileExtension
outputFile, err := os.Create(imageFilePath)
if err != nil {
http.Error(w, "Could not create output file: " + err.Error(), http.StatusInternalServerError)
Expand Down
16 changes: 10 additions & 6 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -291,13 +291,17 @@ func main() {
r.PathPrefix("/assets/").Handler(http.StripPrefix("/assets/", http.FileServer(http.Dir("assets"))))
r.PathPrefix("/images/").Handler(http.StripPrefix("/images/", http.FileServer(http.Dir("images"))))

// Tell the http server to handle routing with the router we just made.
var handler http.Handler = r

if !settings.CSRFProtectDisable {
handler = CSRF(r)
}
if settings.GzipEnabled {
http.Handle("/", gziphandler.GzipHandler(CSRF(r)))
} else {
http.Handle("/", CSRF(r))
handler = gziphandler.GzipHandler(handler)
}

// Tell the http server to handle routing with the router we just made.
http.Handle("/", handler)
// Tell the person who started this that we are starting the server.
log.Printf("listening on " + settings.Port)

Expand All @@ -308,10 +312,10 @@ func main() {

unixListener, err := net.Listen("unix", settings.Port)
if err != nil {
log.Fatal("cannot listen on unix socket:", err)
log.Fatal("cannot listen on unix socket: ", err)
}

// hac
// set socket owner but only if the value is not blank
if settings.SocketOwner != "" {
socketUser, err := osUser.Lookup(settings.SocketOwner)
if err != nil {
Expand Down
8 changes: 6 additions & 2 deletions types.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,16 @@ type community struct {
type config struct {
// if this is true, then it will listen on a unix socket instead of a tcp port
ListenSocket bool
// this can be left blank if you are listening and accessing as the same user
SocketOwner string
// if listensocket is true then port is the socket
Port string
// whether to enable gzip compression, unnecessary with a reverse proxy, absolutely necessary without one
// whether to enable gzip compression
// unnecessary with a reverse proxy, absolutely necessary without one
GzipEnabled bool
SSL struct {
// will disable csrf protection which you probably want to do because it's annoying
CSRFProtectDisable bool
SSL struct {
Enabled bool
Certificate string
Key string
Expand Down

0 comments on commit 965aa22

Please sign in to comment.