diff --git a/docs/examples.rst b/docs/examples.rst
index 07664e1..c71ab89 100644
--- a/docs/examples.rst
+++ b/docs/examples.rst
@@ -26,6 +26,11 @@ Nginx Configuration
client_body_buffer_size 128k;
server_name your.server.url;
+
+ proxy_connect_timeout 300;
+ proxy_send_timeout 300;
+ proxy_read_timeout 300;
+ send_timeout 300;
location / {
# If using Cloudflare
diff --git a/internal/models/UploadStatus.go b/internal/models/UploadStatus.go
index 13c1f12..7dcedb0 100644
--- a/internal/models/UploadStatus.go
+++ b/internal/models/UploadStatus.go
@@ -14,10 +14,13 @@ type UploadStatus struct {
CurrentStatus int `json:"currentstatus"`
// LastUpdate indicates the last status change
LastUpdate int64 `json:"lastupdate"`
+ // Type is the type of the message and is always "uploadstatus"
+ Type string `json:"type"`
}
// ToJson returns the struct as a Json byte array
func (u *UploadStatus) ToJson() ([]byte, error) {
+ u.Type = "uploadstatus"
return json.Marshal(u)
}
diff --git a/internal/webserver/Webserver.go b/internal/webserver/Webserver.go
index 8d0fa76..8ac94b8 100644
--- a/internal/webserver/Webserver.go
+++ b/internal/webserver/Webserver.go
@@ -84,6 +84,7 @@ func Start() {
mux := http.NewServeMux()
sseServer = sse.New()
+ sseServer.Headers["X-Accel-Buffering"] = "no"
sseServer.CreateStream("changes")
processingstatus.Init(sseServer)
@@ -145,13 +146,13 @@ func Start() {
ssl.GenerateIfInvalidCert(configuration.Get().ServerUrl, false)
fmt.Println(infoMessage)
err = srv.ListenAndServeTLS(ssl.GetCertificateLocations())
- if err != nil && err != http.ErrServerClosed {
+ if err != nil && !errors.Is(err, http.ErrServerClosed) {
log.Fatal(err)
}
} else {
fmt.Println(infoMessage)
err = srv.ListenAndServe()
- if err != nil && err != http.ErrServerClosed {
+ if err != nil && !errors.Is(err, http.ErrServerClosed) {
log.Fatal(err)
}
}
diff --git a/internal/webserver/web/static/js/admin.js b/internal/webserver/web/static/js/admin.js
index 0b7228d..98a9c9f 100644
--- a/internal/webserver/web/static/js/admin.js
+++ b/internal/webserver/web/static/js/admin.js
@@ -226,22 +226,22 @@ function editFile() {
button.disabled = true;
let apiUrl = './api/files/modify';
- let allowedDownloads = document.getElementById('mi_edit_down').value;
- let expiryTimestamp = document.getElementById('mi_edit_expiry').value;
- let password = document.getElementById('mi_edit_pw').value;
- let originalPassword = (password === '(unchanged)');
-
+ let allowedDownloads = document.getElementById('mi_edit_down').value;
+ let expiryTimestamp = document.getElementById('mi_edit_expiry').value;
+ let password = document.getElementById('mi_edit_pw').value;
+ let originalPassword = (password === '(unchanged)');
+
if (!document.getElementById('mc_download').checked) {
- allowedDownloads = 0;
+ allowedDownloads = 0;
}
if (!document.getElementById('mc_expiry').checked) {
- expiryTimestamp = 0;
+ expiryTimestamp = 0;
}
if (!document.getElementById('mc_password').checked) {
- originalPassword = false;
- password = "";
- }
-
+ originalPassword = false;
+ password = "";
+ }
+
const requestOptions = {
method: 'PUT',
headers: {
@@ -360,14 +360,14 @@ function selectTextForPw(input) {
}
function add14DaysIfBeforeCurrentTime(unixTimestamp) {
- let currentTime = Date.now();
- let timestampInMilliseconds = unixTimestamp * 1000;
- if (timestampInMilliseconds < currentTime) {
- let newTimestamp = currentTime + (14 * 24 * 60 * 60 * 1000);
- return Math.floor(newTimestamp / 1000);
- } else {
- return unixTimestamp;
- }
+ let currentTime = Date.now();
+ let timestampInMilliseconds = unixTimestamp * 1000;
+ if (timestampInMilliseconds < currentTime) {
+ let newTimestamp = currentTime + (14 * 24 * 60 * 60 * 1000);
+ return Math.floor(newTimestamp / 1000);
+ } else {
+ return unixTimestamp;
+ }
}
function changeApiPermission(apiKey, permission, buttonId) {
@@ -454,9 +454,25 @@ function parseData(data) {
function registerChangeHandler() {
const source = new EventSource("./uploadStatus?stream=changes")
source.onmessage = (event) => {
- let eventData = JSON.parse(event.data);
- setProgressStatus(eventData.chunkid, eventData.currentstatus);
+ try {
+ let eventData = JSON.parse(event.data);
+ setProgressStatus(eventData.chunkid, eventData.currentstatus);
+ } catch (e) {
+ console.error("Failed to parse event data:", e);
+ }
}
+ source.onerror = (error) => {
+
+ // Check for net::ERR_HTTP2_PROTOCOL_ERROR 200 (OK) and ignore it
+ if (error.target.readyState !== EventSource.CLOSED) {
+ source.close();
+ }
+
+
+ console.log("Reconnecting to SSE...");
+ // Attempt to reconnect after a delay
+ setTimeout(registerChangeHandler, 1000);
+ };
}
var statusItemCount = 0;
diff --git a/internal/webserver/web/static/js/min/admin.min.js b/internal/webserver/web/static/js/min/admin.min.js
index 94069a5..ff30619 100644
--- a/internal/webserver/web/static/js/min/admin.min.js
+++ b/internal/webserver/web/static/js/min/admin.min.js
@@ -1 +1 @@
-var clipboard=new ClipboardJS(".btn"),dropzoneObject,calendarInstance,statusItemCount,isE2EEnabled=!1,isUploading=!1,rowCount=-1;window.addEventListener("beforeunload",e=>{isUploading&&(e.returnValue="Upload is still in progress. Do you want to close this page?")}),Dropzone.options.uploaddropzone={paramName:"file",dictDefaultMessage:"Drop files, paste or click here to upload",createImageThumbnails:!1,chunksUploaded:function(e,t){sendChunkComplete(e,t)},init:function(){dropzoneObject=this,this.on("addedfile",e=>{addFileProgress(e)}),this.on("queuecomplete",function(){isUploading=!1}),this.on("sending",function(){isUploading=!0}),this.on("error",function(e,t,n){n&&n.status===413?showError(e,"File too large to upload. If you are using a reverse proxy, make sure that the allowed body size is at least 50MB."):showError(e,"Server responded with code "+n.status)}),this.on("uploadprogress",function(e,t,n){updateProgressbar(e,t,n)}),isE2EEnabled&&(dropzoneObject.disable(),dropzoneObject.options.dictDefaultMessage="Loading end-to-end encryption...",document.getElementsByClassName("dz-button")[0].innerText="Loading end-to-end encryption...",setE2eUpload())}};function updateProgressbar(e,t,n){let o=e.upload.uuid,i=document.getElementById(`us-container-${o}`);if(i==null||i.getAttribute("data-complete")==="true")return;let s=Math.round(t);s<0&&(s=0),s>100&&(s=100);let a=Date.now()-i.getAttribute("data-starttime"),r=n/(a/1e3)/1024/1024,c=Math.round(r*10)/10;document.getElementById(`us-progressbar-${o}`).style.width=s+"%",document.getElementById(`us-progress-info-${o}`).innerText=s+"% - "+c+"MB/s"}function setProgressStatus(e,t){let s=document.getElementById(`us-container-${e}`);if(s==null)return;s.setAttribute("data-complete","true");let n;switch(t){case 0:n="Processing file...";break;case 1:n="Uploading file...";break}document.getElementById(`us-progress-info-${e}`).innerText=n}function addFileProgress(e){addFileStatus(e.upload.uuid,e.upload.filename)}document.onpaste=function(e){if(dropzoneObject.disabled)return;var t,n=(e.clipboardData||e.originalEvent.clipboardData).items;for(index in n)t=n[index],t.kind==="file"&&dropzoneObject.addFile(t.getAsFile()),t.kind==="string"&&t.getAsString(function(e){const t=/
/gi;if(t.test(e)===!1){let t=new Blob([e],{type:"text/plain"}),n=new File([t],"Pasted Text.txt",{type:"text/plain",lastModified:new Date(0)});dropzoneObject.addFile(n)}})};function urlencodeFormData(e){let t="";function s(e){return encodeURIComponent(e).replace(/%20/g,"+")}for(var n of e.entries())typeof n[1]=="string"&&(t+=(t?"&":"")+s(n[0])+"="+s(n[1]));return t}function sendChunkComplete(e,t){var s=new XMLHttpRequest;s.open("POST","./uploadComplete",!0),s.setRequestHeader("Content-Type","application/x-www-form-urlencoded");let n=new FormData;n.append("allowedDownloads",document.getElementById("allowedDownloads").value),n.append("expiryDays",document.getElementById("expiryDays").value),n.append("password",document.getElementById("password").value),n.append("isUnlimitedDownload",!document.getElementById("enableDownloadLimit").checked),n.append("isUnlimitedTime",!document.getElementById("enableTimeLimit").checked),n.append("chunkid",e.upload.uuid),e.isEndToEndEncrypted===!0?(n.append("filesize",e.sizeEncrypted),n.append("filename","Encrypted File"),n.append("filecontenttype",""),n.append("isE2E","true"),n.append("realSize",e.size)):(n.append("filesize",e.size),n.append("filename",e.name),n.append("filecontenttype",e.type)),s.onreadystatechange=function(){if(this.readyState==4)if(this.status==200){let n=addRow(s.response);if(e.isEndToEndEncrypted===!0){try{let s=GokapiE2EAddFile(e.upload.uuid,n,e.name);if(s instanceof Error)throw s;let t=GokapiE2EInfoEncrypt();if(t instanceof Error)throw t;storeE2EInfo(t)}catch(t){e.accepted=!1,dropzoneObject._errorProcessing([e],t);return}GokapiE2EDecryptMenu()}removeFileStatus(e.upload.uuid),t()}else{e.accepted=!1;let t=getErrorMessage(s.responseText);dropzoneObject._errorProcessing([e],t),showError(e,t)}},s.send(urlencodeFormData(n))}function getErrorMessage(e){let t;try{t=JSON.parse(e)}catch{return"Unknown error: Server could not process file"}return"Error: "+t.ErrorMessage}function showError(e,t){let n=e.upload.uuid;document.getElementById(`us-progressbar-${n}`).style.width="100%",document.getElementById(`us-progressbar-${n}`).style.backgroundColor="red",document.getElementById(`us-progress-info-${n}`).innerText=t,document.getElementById(`us-progress-info-${n}`).classList.add("uploaderror")}function editFile(){const e=document.getElementById("mb_save");e.disabled=!0;let i="./api/files/modify",n=document.getElementById("mi_edit_down").value,s=document.getElementById("mi_edit_expiry").value,t=document.getElementById("mi_edit_pw").value,o=t==="(unchanged)";document.getElementById("mc_download").checked||(n=0),document.getElementById("mc_expiry").checked||(s=0),document.getElementById("mc_password").checked||(o=!1,t="");const a={method:"PUT",headers:{"Content-Type":"application/json",id:e.getAttribute("data-fileid"),allowedDownloads:n,expiryTimestamp:s,password:t,originalPassword:o}};fetch(i,a).then(e=>{if(!e.ok)throw new Error(`Request failed with status: ${e.status}`)}).then(e=>{location.reload()}).catch(t=>{alert("Unable to edit file: "+t),console.error("Error:",t),e.disabled=!1})}calendarInstance=null;function createCalendar(e){const t=new Date(e*1e3);calendarInstance=flatpickr("#mi_edit_expiry",{enableTime:!0,dateFormat:"U",altInput:!0,altFormat:"Y-m-d H:i",allowInput:!0,time_24hr:!0,defaultDate:t,minDate:"today"})}function handleEditCheckboxChange(e){var t=document.getElementById(e.getAttribute("data-toggle-target")),n=e.getAttribute("data-timestamp");e.checked?(t.classList.remove("disabled"),t.removeAttribute("disabled"),n!=null&&(calendarInstance._input.disabled=!1)):(n!=null&&(calendarInstance._input.disabled=!0),t.classList.add("disabled"),t.setAttribute("disabled",!0))}function showEditModal(e,t,n,s,o,i,a){document.getElementById("m_filenamelabel").innerHTML=e,document.getElementById("mc_expiry").setAttribute("data-timestamp",s),document.getElementById("mb_save").setAttribute("data-fileid",t),createCalendar(s),i?(document.getElementById("mi_edit_down").value="1",document.getElementById("mi_edit_down").disabled=!0,document.getElementById("mc_download").checked=!1):(document.getElementById("mi_edit_down").value=n,document.getElementById("mi_edit_down").disabled=!1,document.getElementById("mc_download").checked=!0),a?(document.getElementById("mi_edit_expiry").value=add14DaysIfBeforeCurrentTime(s),document.getElementById("mi_edit_expiry").disabled=!0,document.getElementById("mc_expiry").checked=!1,calendarInstance._input.disabled=!0):(document.getElementById("mi_edit_expiry").value=s,document.getElementById("mi_edit_expiry").disabled=!1,document.getElementById("mc_expiry").checked=!0,calendarInstance._input.disabled=!1),o?(document.getElementById("mi_edit_pw").value="(unchanged)",document.getElementById("mi_edit_pw").disabled=!1,document.getElementById("mc_password").checked=!0):(document.getElementById("mi_edit_pw").value="",document.getElementById("mi_edit_pw").disabled=!0,document.getElementById("mc_password").checked=!1),new bootstrap.Modal("#modaledit",{}).show()}function selectTextForPw(e){e.value==="(unchanged)"&&e.setSelectionRange(0,e.value.length)}function add14DaysIfBeforeCurrentTime(e){let t=Date.now(),n=e*1e3;if(n{if(!e.ok)throw new Error(`Request failed with status: ${e.status}`)}).then(e=>{o?s.classList.add("apiperm-notgranted"):s.classList.add("apiperm-granted"),s.classList.remove("apiperm-processing")}).catch(e=>{o?s.classList.add("apiperm-granted"):s.classList.add("apiperm-notgranted"),s.classList.remove("apiperm-processing"),alert("Unable to set permission: "+e),console.error("Error:",e)})}function checkBoxChanged(e,t){let n=!e.checked;n?document.getElementById(t).setAttribute("disabled",""):document.getElementById(t).removeAttribute("disabled"),t==="password"&&n&&(document.getElementById("password").value="")}function parseData(e){return e?typeof e=="object"?e:typeof e=="string"?JSON.parse(e):{Result:"error"}:{Result:"error"}}function registerChangeHandler(){const e=new EventSource("./uploadStatus?stream=changes");e.onmessage=e=>{let t=JSON.parse(e.data);setProgressStatus(t.chunkid,t.currentstatus)}}statusItemCount=0;function addFileStatus(e,t){const n=document.createElement("div");n.setAttribute("id",`us-container-${e}`),n.classList.add("us-container");const a=document.createElement("div");a.classList.add("filename"),a.textContent=t,n.appendChild(a);const s=document.createElement("div");s.classList.add("upload-progress-container"),s.setAttribute("id",`us-progress-container-${e}`);const r=document.createElement("div");r.classList.add("upload-progress-bar");const o=document.createElement("div");o.setAttribute("id",`us-progressbar-${e}`),o.classList.add("upload-progress-bar-progress"),o.style.width="0%",r.appendChild(o);const i=document.createElement("div");i.setAttribute("id",`us-progress-info-${e}`),i.classList.add("upload-progress-info"),i.textContent="0%",s.appendChild(r),s.appendChild(i),n.appendChild(s),n.setAttribute("data-starttime",Date.now()),n.setAttribute("data-complete","false");const c=document.getElementById("uploadstatus");c.appendChild(n),c.style.visibility="visible",statusItemCount++}function removeFileStatus(e){const t=document.getElementById(`us-container-${e}`);if(t==null)return;t.remove(),statusItemCount--,statusItemCount<1&&(document.getElementById("uploadstatus").style.visibility="hidden")}function addRow(e){let s=parseData(e);if(s.Result!=="OK"){alert("Failed to upload file!"),location.reload();return}let t=s.FileInfo,p=document.getElementById("downloadtable"),o=p.insertRow(0),r=o.insertCell(0),a=o.insertCell(1),i=o.insertCell(2),c=o.insertCell(3),l=o.insertCell(4),d=o.insertCell(5),u=o.insertCell(6),h="";t.IsPasswordProtected===!0&&(h=' '),r.innerText=t.Name,r.id="cell-name-"+t.Id,a.innerText=t.Size,t.UnlimitedDownloads?i.innerText="Unlimited":i.innerText=t.DownloadsRemaining,t.UnlimitedTime?c.innerText="Unlimited":c.innerText=t.ExpireAtString,l.innerHTML="0",d.innerHTML=''+t.Id+""+h;let n=' ';t.HotlinkId!==""?n=n+' ':t.RequiresClientSideDecryption===!0||t.IsPasswordProtected===!0?n=n+' ':n=n+' ',n=n+` `,n=n+` ',n=n+``,u.innerHTML=n,r.style.backgroundColor="green",a.style.backgroundColor="green",a.setAttribute("data-order",s.FileInfo.SizeBytes),i.style.backgroundColor="green",c.style.backgroundColor="green",l.style.backgroundColor="green",d.style.backgroundColor="green",u.style.backgroundColor="green";let m=$("#maintable").DataTable();rowCount==-1&&(rowCount=m.rows().count()),rowCount=rowCount+1,m.row.add(o);let f=document.getElementsByClassName("dataTables_empty")[0];return typeof f!="undefined"?f.innerText="Files stored: "+rowCount:document.getElementsByClassName("dataTables_info")[0].innerText="Files stored: "+rowCount,t.Id}function hideQrCode(){document.getElementById("qroverlay").style.display="none",document.getElementById("qrcode").innerHTML=""}function showQrCode(e){const t=document.getElementById("qroverlay");t.style.display="block",new QRCode(document.getElementById("qrcode"),{text:e,width:200,height:200,colorDark:"#000000",colorLight:"#ffffff",correctLevel:QRCode.CorrectLevel.H}),t.addEventListener("click",hideQrCode)}function showToast(){let e=document.getElementById("toastnotification");e.classList.add("show"),setTimeout(()=>{e.classList.remove("show")},1e3)}
\ No newline at end of file
+var clipboard=new ClipboardJS(".btn"),dropzoneObject,calendarInstance,statusItemCount,isE2EEnabled=!1,isUploading=!1,rowCount=-1;window.addEventListener("beforeunload",e=>{isUploading&&(e.returnValue="Upload is still in progress. Do you want to close this page?")}),Dropzone.options.uploaddropzone={paramName:"file",dictDefaultMessage:"Drop files, paste or click here to upload",createImageThumbnails:!1,chunksUploaded:function(e,t){sendChunkComplete(e,t)},init:function(){dropzoneObject=this,this.on("addedfile",e=>{addFileProgress(e)}),this.on("queuecomplete",function(){isUploading=!1}),this.on("sending",function(){isUploading=!0}),this.on("error",function(e,t,n){n&&n.status===413?showError(e,"File too large to upload. If you are using a reverse proxy, make sure that the allowed body size is at least 50MB."):showError(e,"Server responded with code "+n.status)}),this.on("uploadprogress",function(e,t,n){updateProgressbar(e,t,n)}),isE2EEnabled&&(dropzoneObject.disable(),dropzoneObject.options.dictDefaultMessage="Loading end-to-end encryption...",document.getElementsByClassName("dz-button")[0].innerText="Loading end-to-end encryption...",setE2eUpload())}};function updateProgressbar(e,t,n){let o=e.upload.uuid,i=document.getElementById(`us-container-${o}`);if(i==null||i.getAttribute("data-complete")==="true")return;let s=Math.round(t);s<0&&(s=0),s>100&&(s=100);let a=Date.now()-i.getAttribute("data-starttime"),r=n/(a/1e3)/1024/1024,c=Math.round(r*10)/10;document.getElementById(`us-progressbar-${o}`).style.width=s+"%",document.getElementById(`us-progress-info-${o}`).innerText=s+"% - "+c+"MB/s"}function setProgressStatus(e,t){let s=document.getElementById(`us-container-${e}`);if(s==null)return;s.setAttribute("data-complete","true");let n;switch(t){case 0:n="Processing file...";break;case 1:n="Uploading file...";break}document.getElementById(`us-progress-info-${e}`).innerText=n}function addFileProgress(e){addFileStatus(e.upload.uuid,e.upload.filename)}document.onpaste=function(e){if(dropzoneObject.disabled)return;var t,n=(e.clipboardData||e.originalEvent.clipboardData).items;for(index in n)t=n[index],t.kind==="file"&&dropzoneObject.addFile(t.getAsFile()),t.kind==="string"&&t.getAsString(function(e){const t=/
/gi;if(t.test(e)===!1){let t=new Blob([e],{type:"text/plain"}),n=new File([t],"Pasted Text.txt",{type:"text/plain",lastModified:new Date(0)});dropzoneObject.addFile(n)}})};function urlencodeFormData(e){let t="";function s(e){return encodeURIComponent(e).replace(/%20/g,"+")}for(var n of e.entries())typeof n[1]=="string"&&(t+=(t?"&":"")+s(n[0])+"="+s(n[1]));return t}function sendChunkComplete(e,t){var s=new XMLHttpRequest;s.open("POST","./uploadComplete",!0),s.setRequestHeader("Content-Type","application/x-www-form-urlencoded");let n=new FormData;n.append("allowedDownloads",document.getElementById("allowedDownloads").value),n.append("expiryDays",document.getElementById("expiryDays").value),n.append("password",document.getElementById("password").value),n.append("isUnlimitedDownload",!document.getElementById("enableDownloadLimit").checked),n.append("isUnlimitedTime",!document.getElementById("enableTimeLimit").checked),n.append("chunkid",e.upload.uuid),e.isEndToEndEncrypted===!0?(n.append("filesize",e.sizeEncrypted),n.append("filename","Encrypted File"),n.append("filecontenttype",""),n.append("isE2E","true"),n.append("realSize",e.size)):(n.append("filesize",e.size),n.append("filename",e.name),n.append("filecontenttype",e.type)),s.onreadystatechange=function(){if(this.readyState==4)if(this.status==200){let n=addRow(s.response);if(e.isEndToEndEncrypted===!0){try{let s=GokapiE2EAddFile(e.upload.uuid,n,e.name);if(s instanceof Error)throw s;let t=GokapiE2EInfoEncrypt();if(t instanceof Error)throw t;storeE2EInfo(t)}catch(t){e.accepted=!1,dropzoneObject._errorProcessing([e],t);return}GokapiE2EDecryptMenu()}removeFileStatus(e.upload.uuid),t()}else{e.accepted=!1;let t=getErrorMessage(s.responseText);dropzoneObject._errorProcessing([e],t),showError(e,t)}},s.send(urlencodeFormData(n))}function getErrorMessage(e){let t;try{t=JSON.parse(e)}catch{return"Unknown error: Server could not process file"}return"Error: "+t.ErrorMessage}function showError(e,t){let n=e.upload.uuid;document.getElementById(`us-progressbar-${n}`).style.width="100%",document.getElementById(`us-progressbar-${n}`).style.backgroundColor="red",document.getElementById(`us-progress-info-${n}`).innerText=t,document.getElementById(`us-progress-info-${n}`).classList.add("uploaderror")}function editFile(){const e=document.getElementById("mb_save");e.disabled=!0;let i="./api/files/modify",n=document.getElementById("mi_edit_down").value,s=document.getElementById("mi_edit_expiry").value,t=document.getElementById("mi_edit_pw").value,o=t==="(unchanged)";document.getElementById("mc_download").checked||(n=0),document.getElementById("mc_expiry").checked||(s=0),document.getElementById("mc_password").checked||(o=!1,t="");const a={method:"PUT",headers:{"Content-Type":"application/json",id:e.getAttribute("data-fileid"),allowedDownloads:n,expiryTimestamp:s,password:t,originalPassword:o}};fetch(i,a).then(e=>{if(!e.ok)throw new Error(`Request failed with status: ${e.status}`)}).then(e=>{location.reload()}).catch(t=>{alert("Unable to edit file: "+t),console.error("Error:",t),e.disabled=!1})}calendarInstance=null;function createCalendar(e){const t=new Date(e*1e3);calendarInstance=flatpickr("#mi_edit_expiry",{enableTime:!0,dateFormat:"U",altInput:!0,altFormat:"Y-m-d H:i",allowInput:!0,time_24hr:!0,defaultDate:t,minDate:"today"})}function handleEditCheckboxChange(e){var t=document.getElementById(e.getAttribute("data-toggle-target")),n=e.getAttribute("data-timestamp");e.checked?(t.classList.remove("disabled"),t.removeAttribute("disabled"),n!=null&&(calendarInstance._input.disabled=!1)):(n!=null&&(calendarInstance._input.disabled=!0),t.classList.add("disabled"),t.setAttribute("disabled",!0))}function showEditModal(e,t,n,s,o,i,a){document.getElementById("m_filenamelabel").innerHTML=e,document.getElementById("mc_expiry").setAttribute("data-timestamp",s),document.getElementById("mb_save").setAttribute("data-fileid",t),createCalendar(s),i?(document.getElementById("mi_edit_down").value="1",document.getElementById("mi_edit_down").disabled=!0,document.getElementById("mc_download").checked=!1):(document.getElementById("mi_edit_down").value=n,document.getElementById("mi_edit_down").disabled=!1,document.getElementById("mc_download").checked=!0),a?(document.getElementById("mi_edit_expiry").value=add14DaysIfBeforeCurrentTime(s),document.getElementById("mi_edit_expiry").disabled=!0,document.getElementById("mc_expiry").checked=!1,calendarInstance._input.disabled=!0):(document.getElementById("mi_edit_expiry").value=s,document.getElementById("mi_edit_expiry").disabled=!1,document.getElementById("mc_expiry").checked=!0,calendarInstance._input.disabled=!1),o?(document.getElementById("mi_edit_pw").value="(unchanged)",document.getElementById("mi_edit_pw").disabled=!1,document.getElementById("mc_password").checked=!0):(document.getElementById("mi_edit_pw").value="",document.getElementById("mi_edit_pw").disabled=!0,document.getElementById("mc_password").checked=!1),new bootstrap.Modal("#modaledit",{}).show()}function selectTextForPw(e){e.value==="(unchanged)"&&e.setSelectionRange(0,e.value.length)}function add14DaysIfBeforeCurrentTime(e){let t=Date.now(),n=e*1e3;if(n{if(!e.ok)throw new Error(`Request failed with status: ${e.status}`)}).then(e=>{o?s.classList.add("apiperm-notgranted"):s.classList.add("apiperm-granted"),s.classList.remove("apiperm-processing")}).catch(e=>{o?s.classList.add("apiperm-granted"):s.classList.add("apiperm-notgranted"),s.classList.remove("apiperm-processing"),alert("Unable to set permission: "+e),console.error("Error:",e)})}function checkBoxChanged(e,t){let n=!e.checked;n?document.getElementById(t).setAttribute("disabled",""):document.getElementById(t).removeAttribute("disabled"),t==="password"&&n&&(document.getElementById("password").value="")}function parseData(e){return e?typeof e=="object"?e:typeof e=="string"?JSON.parse(e):{Result:"error"}:{Result:"error"}}function registerChangeHandler(){const e=new EventSource("./uploadStatus?stream=changes");e.onmessage=e=>{try{let t=JSON.parse(e.data);setProgressStatus(t.chunkid,t.currentstatus)}catch(e){console.error("Failed to parse event data:",e)}},e.onerror=t=>{t.target.readyState!==EventSource.CLOSED&&e.close(),console.log("Reconnecting to SSE..."),setTimeout(registerChangeHandler,1e3)}}statusItemCount=0;function addFileStatus(e,t){const n=document.createElement("div");n.setAttribute("id",`us-container-${e}`),n.classList.add("us-container");const a=document.createElement("div");a.classList.add("filename"),a.textContent=t,n.appendChild(a);const s=document.createElement("div");s.classList.add("upload-progress-container"),s.setAttribute("id",`us-progress-container-${e}`);const r=document.createElement("div");r.classList.add("upload-progress-bar");const o=document.createElement("div");o.setAttribute("id",`us-progressbar-${e}`),o.classList.add("upload-progress-bar-progress"),o.style.width="0%",r.appendChild(o);const i=document.createElement("div");i.setAttribute("id",`us-progress-info-${e}`),i.classList.add("upload-progress-info"),i.textContent="0%",s.appendChild(r),s.appendChild(i),n.appendChild(s),n.setAttribute("data-starttime",Date.now()),n.setAttribute("data-complete","false");const c=document.getElementById("uploadstatus");c.appendChild(n),c.style.visibility="visible",statusItemCount++}function removeFileStatus(e){const t=document.getElementById(`us-container-${e}`);if(t==null)return;t.remove(),statusItemCount--,statusItemCount<1&&(document.getElementById("uploadstatus").style.visibility="hidden")}function addRow(e){let s=parseData(e);if(s.Result!=="OK"){alert("Failed to upload file!"),location.reload();return}let t=s.FileInfo,p=document.getElementById("downloadtable"),o=p.insertRow(0),r=o.insertCell(0),a=o.insertCell(1),i=o.insertCell(2),c=o.insertCell(3),l=o.insertCell(4),d=o.insertCell(5),u=o.insertCell(6),h="";t.IsPasswordProtected===!0&&(h=' '),r.innerText=t.Name,r.id="cell-name-"+t.Id,a.innerText=t.Size,t.UnlimitedDownloads?i.innerText="Unlimited":i.innerText=t.DownloadsRemaining,t.UnlimitedTime?c.innerText="Unlimited":c.innerText=t.ExpireAtString,l.innerHTML="0",d.innerHTML=''+t.Id+""+h;let n=' ';t.HotlinkId!==""?n=n+' ':t.RequiresClientSideDecryption===!0||t.IsPasswordProtected===!0?n=n+' ':n=n+' ',n=n+` `,n=n+` ',n=n+``,u.innerHTML=n,r.style.backgroundColor="green",a.style.backgroundColor="green",a.setAttribute("data-order",s.FileInfo.SizeBytes),i.style.backgroundColor="green",c.style.backgroundColor="green",l.style.backgroundColor="green",d.style.backgroundColor="green",u.style.backgroundColor="green";let m=$("#maintable").DataTable();rowCount==-1&&(rowCount=m.rows().count()),rowCount=rowCount+1,m.row.add(o);let f=document.getElementsByClassName("dataTables_empty")[0];return typeof f!="undefined"?f.innerText="Files stored: "+rowCount:document.getElementsByClassName("dataTables_info")[0].innerText="Files stored: "+rowCount,t.Id}function hideQrCode(){document.getElementById("qroverlay").style.display="none",document.getElementById("qrcode").innerHTML=""}function showQrCode(e){const t=document.getElementById("qroverlay");t.style.display="block",new QRCode(document.getElementById("qrcode"),{text:e,width:200,height:200,colorDark:"#000000",colorLight:"#ffffff",correctLevel:QRCode.CorrectLevel.H}),t.addEventListener("click",hideQrCode)}function showToast(){let e=document.getElementById("toastnotification");e.classList.add("show"),setTimeout(()=>{e.classList.remove("show")},1e3)}
\ No newline at end of file