444 lines
14 KiB
Plaintext
444 lines
14 KiB
Plaintext
{%
|
|
local obj, files, usedSpace, tags, tagcount
|
|
if DB.isobjhexvalid(request:path():sub(7, 7 + 31)) then
|
|
obj = DB.getobj(DB.objshowid(request:path():sub(7, 7 + 31)))
|
|
end
|
|
|
|
function recalcfiles()
|
|
local virt = "/objd/" .. DB.objhideid(obj.id) .. "/"
|
|
local phys = DB.urltophysical(virt)
|
|
|
|
files = {}
|
|
usedSpace = 0
|
|
for f in LFS.dir(phys) do
|
|
if f ~= "." and f ~= ".." then
|
|
local attribs = LFS.attributes(phys .. f)
|
|
table.insert(files, {name = f, size = attribs.size, modtime = attribs.modification, phys = phys .. f, virt = virt .. f})
|
|
usedSpace = usedSpace + attribs.size
|
|
end
|
|
end
|
|
table.sort(files, function(a,b)
|
|
if a.modtime == b.modtime then
|
|
return a.name < b.name
|
|
else
|
|
return a.modtime < b.modtime
|
|
end
|
|
end)
|
|
end
|
|
|
|
if obj then
|
|
-- !!!CHECK IF OWNER HAPPENS HERE!!!
|
|
if verified and (verified.id ~= obj.owner) then
|
|
verified = nil
|
|
end
|
|
|
|
recalcfiles()
|
|
|
|
tags, tagcount = DB.getobjtags(obj.id)
|
|
|
|
if verified then
|
|
obj.sizequota = BigGlobe.cfg.maxtotalobjsize * 1024 -- Temporary
|
|
|
|
local post = request:post()
|
|
if post and post.csrf and DB.csrfverify(verified.id, Escapes.urlunescape(tostring(post.csrf))) then
|
|
if post["createfiles"] then
|
|
local sztoadd = 0
|
|
for fn, sz in post["createfiles"]:gmatch"([^;]+);(%d+)" do
|
|
sztoadd = sztoadd + sz
|
|
end
|
|
if usedSpace + sztoadd > obj.sizequota then
|
|
response:statusCode(409)
|
|
else
|
|
for fn, sz in post["createfiles"]:gmatch"([^;]+);(%d+)" do
|
|
DB.createfile(obj.id, Escapes.urlunescape(fn), tonumber(sz))
|
|
end
|
|
end
|
|
return
|
|
elseif post["upchu"] then
|
|
DB.updatefile(obj.id, post["upchu"], tonumber(post["offset"]), post["data"].data)
|
|
return
|
|
elseif post["remfiles"] then
|
|
for d in post["remfiles"]:gmatch"(%d+)" do
|
|
DB.remfilefromobj(obj.id, files[tonumber(d) + 1].name)
|
|
end
|
|
return
|
|
else
|
|
recalcfiles()
|
|
|
|
if tonumber(post.newthumbnail) and files[tonumber(post.newthumbnail)] then
|
|
DB.genobjthumbnail(obj.id, files[tonumber(post.newthumbnail)].name, obj.sizequota - usedSpace)
|
|
recalcfiles()
|
|
end
|
|
|
|
if post["objname"] then
|
|
local newname = Escapes.urlunescape(post["objname"])
|
|
local newpublished = usedSpace > 0
|
|
if newname ~= obj.name or obj.published ~= newpublished then
|
|
if DB.objupdate(obj.id, newname, newpublished) then
|
|
obj.name = newname
|
|
obj.published = newpublished
|
|
end
|
|
end
|
|
end
|
|
|
|
if post["objtags"] then
|
|
local newtagset = {}
|
|
for m in post["objtags"]:gmatch"%d+" do
|
|
newtagset[tonumber(m)] = true
|
|
end
|
|
|
|
local tagstoremove = {}
|
|
for k,_ in pairs(tags) do
|
|
if not newtagset[k] then
|
|
table.insert(tagstoremove, k)
|
|
end
|
|
end
|
|
|
|
local tagstoadd = {}
|
|
for k,_ in pairs(newtagset) do
|
|
if not tags[k] then
|
|
table.insert(tagstoadd, k)
|
|
end
|
|
end
|
|
|
|
DB.remtagsfromobj(obj.id, tagstoremove)
|
|
DB.addtagstoobj(obj.id, tagstoadd)
|
|
|
|
tags, tagcount = DB.getobjtags(obj.id)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
title = BigGlobe.cfg.sitename .. " - Editing " .. (obj and obj.name or "Object not found")
|
|
|
|
function content() %}
|
|
{% if obj then %}
|
|
{% if verified then %}
|
|
<form method="post" enctype="multipart/form-data" action="#" id="editform">
|
|
<div style="display:inline-block;vertical-align:top;width:49%;">
|
|
<h2>Editing object</h2>
|
|
<input type="hidden" name="csrf" value="{{ Escapes.htmlescape(DB.csrf(verified.id)) }}" />
|
|
|
|
<div><label>Name: </label><input type="text" name="objname" autocomplete="off" value="{{ Escapes.htmlescape(obj.name) }}" /></div>
|
|
|
|
<div><p>Once files are uploaded, the object will be considered published.</p></div>
|
|
|
|
<div><p>Object sized at <strong>{{ (usedSpace + 1023) // 1024 }}kB</strong> out of <strong>{{ (obj.sizequota + 1023) // 1024 }}kB</strong> maximum (<strong>{{math.floor(usedSpace / obj.sizequota * 1000 + 0.5) / 10}}%</strong>) </p></div>
|
|
|
|
<table style="margin-top:1em"><thead><tr><td>File</td><td>Size</td><td colspan="3">Actions</td></tr></thead><tbody>
|
|
{% for idx,f in pairs(files) do %}
|
|
<tr>
|
|
<td>{{ Escapes.htmlescape(f.name) }}</td>
|
|
<td>{{ (f.size + 1023) // 1024 }}kB</td>
|
|
<td><input type="checkbox" id="delcb{{ idx }}"><label for="delcb{{ idx }}">Delete</label></td>
|
|
</tr>
|
|
{% end %}
|
|
<tr style="{% if #files >= BigGlobe.cfg.maxfilesperobj then %}display:none;{% end %}"><td><input type="file" /><button type="button" style="margin:0;" onclick="clearfile(this)">Clear</button></td><td></td><td></td></tr>
|
|
</tbody></table>
|
|
|
|
<select name="newthumbnail" style="margin-top: 1em; margin-bottom: 1em; display: block;">
|
|
<option value="none" selected>Generate thumbnail from image file...</option>
|
|
{% for idx,f in pairs(files) do %}
|
|
<option value="{{idx}}">{{ Escapes.htmlescape(f.name) }}</option>
|
|
{% end %}
|
|
</select>
|
|
</div>
|
|
<div style="display:inline-block;vertical-align:top;width:49%;">
|
|
<h2>Tags</h2>
|
|
<div style="position:relative;width:80%;" class="tagbox" data-formid="editform" data-formparaminputid="objtagsparam" data-unknowntags="">
|
|
<p{% if tagcount > 0 then %} style="visibility:hidden;"{% end %}>Enter tags...</p>
|
|
{% for _, tag in pairs(tags) do %}
|
|
<div class="tag tc{{ tag.category }}" data-tagid="{{ tag.id }}">{{ Escapes.htmlescape(tag.name) }}</div>
|
|
{% end %}
|
|
<span style="position:relative;min-width:4px;left:0;" contenteditable></span>
|
|
</div>
|
|
<div class="autocomplete" style="visibility:hidden;width:80%;"></div>
|
|
<input type="hidden" id="objtagsparam" name="objtags" value="" />
|
|
|
|
{% if BigGlobe.cfg.enable18plus then %}
|
|
<ul class="over18" style="width: 80%;">
|
|
<li>
|
|
<input type="radio" name="a" value="-1" id="o18h" onchange="upd(false)" />
|
|
<label for="o18h">Hide 18+</label>
|
|
</li><li>
|
|
<input type="radio" name="a" value="0" id="o18s" onchange="upd(true)" />
|
|
<label for="o18s">Show 18+</label>
|
|
</li>
|
|
</ul>
|
|
{% end %}
|
|
</div>
|
|
<div style="text-align:center;">
|
|
<input type="submit" value="Submit" />
|
|
<progress id="proggers" max="1" value="0" />
|
|
</div>
|
|
</form>
|
|
|
|
<div id="newtagsform" class="hidden">
|
|
<p>There are unknown tags in your submission. Please assign them categories.</p>
|
|
|
|
<table>{% --[[
|
|
<select style="border: 0;"><option value="a">A</option><option value="b">B</option></select>
|
|
]] %}</table>
|
|
|
|
<button>Submit</button>
|
|
</div>
|
|
|
|
<script>
|
|
{% if BigGlobe.cfg.enable18plus then %}
|
|
function upd(over18) {
|
|
document.querySelector(".tagbox").setAttribute("data-over18", +over18 != -1)
|
|
}
|
|
var activeo18
|
|
if(window.localStorage.getItem("o18")) {
|
|
activeo18 = window.localStorage.getItem("o18")
|
|
}
|
|
if(!activeo18 || activeo18 == 1) {
|
|
activeo18 = 0; // Make "Show 18+", not "Only 18+"
|
|
}
|
|
upd(activeo18)
|
|
document.querySelector("ul.over18 input[type=\"radio\"][value=\"" + activeo18 + "\"]").checked = true
|
|
{% end %}
|
|
|
|
var totalfiles = {{ #files }}
|
|
|
|
function clearfile(el) {
|
|
var inp = el.parentElement.querySelector("input")
|
|
inp.value = ""
|
|
|
|
var allofem = Array.from(document.querySelectorAll("input[type='file']"))
|
|
|
|
var idx = allofem.indexOf(inp)
|
|
if(idx != allofem.length - 1) {
|
|
// remove row
|
|
el.parentElement.parentElement.parentElement.removeChild(el.parentElement.parentElement)
|
|
|
|
if(totalfiles == {{ BigGlobe.cfg.maxfilesperobj }}) {
|
|
allofem[allofem.length - 1].parentElement.parentElement.style.display = ""
|
|
}
|
|
|
|
totalfiles--
|
|
}
|
|
}
|
|
|
|
function rebind() {
|
|
var v = document.querySelectorAll("input[type='file']")
|
|
var last = v[v.length - 1]
|
|
last.onchange = function(ev) {
|
|
last.onchange = undefined
|
|
|
|
var tablerow = this.parentElement.parentElement
|
|
var clond = tablerow.cloneNode(true)
|
|
tablerow.parentElement.appendChild(clond)
|
|
clond.querySelector("input").value = ""
|
|
|
|
totalfiles++
|
|
|
|
if(totalfiles == {{ BigGlobe.cfg.maxfilesperobj }}) {
|
|
clond.style.display = "none"
|
|
}
|
|
|
|
rebind()
|
|
}
|
|
}
|
|
|
|
rebind()
|
|
|
|
var CHUNK_SIZE = 1024 * 512
|
|
|
|
var files
|
|
|
|
var totalsizetoupload
|
|
var totaluploaded
|
|
|
|
function send(fileidx, offset) {
|
|
var xhr = new XMLHttpRequest()
|
|
xhr.open("POST", "#", true)
|
|
|
|
var sz = Math.min(CHUNK_SIZE, files[fileidx].files[0].size - offset)
|
|
|
|
var formData = new FormData()
|
|
formData.append("csrf", document.querySelector("[name='csrf']").value)
|
|
formData.append("upchu", encodeURIComponent(files[fileidx].files[0].name))
|
|
formData.append("offset", offset)
|
|
formData.append("data", files[fileidx].files[0].slice(offset, offset + sz))
|
|
xhr.onreadystatechange = function() {
|
|
if(xhr.readyState == XMLHttpRequest.DONE) {
|
|
if(xhr.status == 200) {
|
|
document.getElementById("proggers").value = totaluploaded / totalsizetoupload
|
|
totaluploaded += sz
|
|
|
|
if(sz < CHUNK_SIZE) {
|
|
if(fileidx < files.length - 1) {
|
|
send(fileidx + 1, 0)
|
|
} else {
|
|
var daform = document.getElementById("editform")
|
|
for(var i = 0; i < files.length; i++) files[i].disabled = true
|
|
daform.submit()
|
|
}
|
|
} else {
|
|
send(fileidx, offset + sz)
|
|
}
|
|
} else {
|
|
send(fileidx, offset)
|
|
}
|
|
}
|
|
}
|
|
xhr.send(formData)
|
|
}
|
|
|
|
function testsizes() {
|
|
var xhr = new XMLHttpRequest()
|
|
xhr.open("POST", "#", true)
|
|
|
|
var formData = new FormData()
|
|
formData.append("csrf", document.querySelector("[name='csrf']").value)
|
|
formData.append("createfiles", files.map(function(x) {return [encodeURIComponent(x.files[0].name), x.files[0].size]}).flat().join(";"))
|
|
|
|
totalsizetoupload = files.map(function(x) {return x.files[0].size}).reduce(function(x,y){return x+y}, 0)
|
|
totaluploaded = 0
|
|
|
|
xhr.onreadystatechange = function() {
|
|
if(xhr.readyState == XMLHttpRequest.DONE) {
|
|
if(xhr.status == 200) {
|
|
send(0, 0)
|
|
} else {
|
|
alert("Too much space.")
|
|
window.location.href = window.location.href.split("#")[0]
|
|
}
|
|
}
|
|
}
|
|
xhr.send(formData)
|
|
}
|
|
|
|
function doremoves() {
|
|
var xhr = new XMLHttpRequest()
|
|
xhr.open("POST", "#", true)
|
|
|
|
var idxs = []
|
|
|
|
var remchecks = document.querySelectorAll("#editform input[type='checkbox']")
|
|
for(var i = 0; i < remchecks.length; i++) {
|
|
if(remchecks[i].checked) idxs.push(i)
|
|
}
|
|
|
|
var formData = new FormData()
|
|
formData.append("csrf", document.querySelector("[name='csrf']").value)
|
|
formData.append("remfiles", idxs.join(";"))
|
|
|
|
xhr.onreadystatechange = function() {
|
|
if(xhr.readyState == XMLHttpRequest.DONE) {
|
|
if(xhr.status == 200) {
|
|
if(files.length > 0) {
|
|
testsizes()
|
|
} else {
|
|
document.getElementById("editform").submit()
|
|
}
|
|
} else {
|
|
window.location.href = window.location.href.split("#")[0]
|
|
}
|
|
}
|
|
}
|
|
xhr.send(formData)
|
|
}
|
|
|
|
function fixnewtags(afterfunc) {
|
|
var newtagsform = document.querySelector("div#newtagsform")
|
|
var tbl = newtagsform.querySelector("table")
|
|
|
|
var newTags = document.querySelectorAll("div.tagbox div.tag.tcNew")
|
|
|
|
for(var i = 0; i < newTags.length; i++) {
|
|
var row = tbl.insertRow(-1)
|
|
|
|
var sel = document.createElement("select")
|
|
{% for tc = 1, #BigGlobe.cfg.tc do if BigGlobe.cfg.tc[tc].name ~= "" then %}
|
|
{
|
|
var opt = document.createElement("option")
|
|
opt.textContent = "{{ Escapes.htmlescape(BigGlobe.cfg.tc[tc].name) }}"
|
|
opt.value = {{ tc - 1 }}
|
|
sel.appendChild(opt)
|
|
}
|
|
{% end end %}
|
|
|
|
var adult = document.createElement("input")
|
|
adult.type = "checkbox"
|
|
adult.checked = false
|
|
adult.id = "boobietc" + i
|
|
|
|
var adultLbl = document.createElement("label")
|
|
adultLbl.htmlFor = adult.id
|
|
adultLbl.textContent = "18+"
|
|
|
|
row.insertCell(-1).appendChild(sel)
|
|
row.insertCell(-1).textContent = newTags[i].textContent
|
|
|
|
var c = row.insertCell(-1)
|
|
c.appendChild(adult)
|
|
c.appendChild(adultLbl)
|
|
}
|
|
|
|
newtagsform.classList.toggle("hidden")
|
|
|
|
var btn = newtagsform.querySelector("button")
|
|
|
|
btn.onclick = function() {
|
|
btn.toggleAttribute("disabled")
|
|
|
|
var xhr = new XMLHttpRequest()
|
|
xhr.open("POST", "/addtags", true)
|
|
|
|
var formData = new FormData()
|
|
formData.append("csrf", document.querySelector("[name='csrf']").value)
|
|
|
|
for(var i = 0; i < newTags.length; i++) {
|
|
formData.append("name[]", tbl.rows[i].cells[1].textContent)
|
|
formData.append("tc[]", tbl.rows[i].cells[0].querySelector("select").value)
|
|
formData.append("adult[]", tbl.rows[i].cells[2].querySelector("input").checked ? "1" : "0")
|
|
}
|
|
|
|
xhr.onreadystatechange = function() {
|
|
if(xhr.readyState == XMLHttpRequest.DONE && xhr.status == 200) {
|
|
var resp = xhr.responseText.split(",")
|
|
|
|
// Set data-tagids so they object may be updated with the new tags
|
|
for(var i = 0; i < newTags.length; i++) {
|
|
newTags[i].setAttribute("data-tagid", resp[i])
|
|
}
|
|
|
|
tagbox_updateformdata()
|
|
|
|
afterfunc()
|
|
}
|
|
}
|
|
|
|
xhr.send(formData);
|
|
}
|
|
}
|
|
|
|
document.getElementById("editform").addEventListener("submit", function(ev) {
|
|
ev.preventDefault()
|
|
|
|
files = Array.from(document.querySelectorAll("input[type='file']"))
|
|
files.pop() // don't count empty input box
|
|
|
|
var newTags = document.querySelectorAll("div.tagbox div.tag.tcNew")
|
|
if(newTags.length != 0) {
|
|
fixnewtags(doremoves)
|
|
} else {
|
|
doremoves()
|
|
}
|
|
})
|
|
</script>
|
|
<script src="/static/tagbox.js"></script>
|
|
{% else %}
|
|
<p>You are not eligible to edit this object.</p>
|
|
{% end %}
|
|
{% else %}
|
|
<p>Object was not found.</p>
|
|
{% end %}
|
|
{% end %}
|
|
|
|
{# base.inc
|