Overview
| Comment: | media uploads work now, some types can be viewed |
|---|---|
| Downloads: | Tarball | ZIP archive | SQL archive |
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA3-256: |
93aea04a05d7e6e0ea44a8a308c0f7d3 |
| User & Date: | lexi on 2021-01-07 20:39:57 |
| Other Links: | manifest | tags |
Context
|
2021-01-08
| ||
| 05:58 | enable passwords check-in: d6024624c6 user: lexi tags: trunk | |
|
2021-01-07
| ||
| 20:39 | media uploads work now, some types can be viewed check-in: 93aea04a05 user: lexi tags: trunk | |
| 09:39 | further iteration on media check-in: af5ed65b68 user: lexi tags: trunk | |
Changes
Modified backend/pgsql.t from [fc1c52be55] to [cb3e1743a5].
550 551 552 553 554 555 556 557 558 559 560 561 562 563 ... 826 827 828 829 830 831 832 833 834 835 836 837 838 839 .... 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 .... 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 |
from parsav_artifact_claims as a where uid = $1::bigint and rid = $2::bigint
]];
};
artifact_load = {
params = {uint64}, sql = [[
select content, mime from parsav_artifacts where id = $1::bigint
]];
};
post_attach_ctl_ins = {
params = {uint64, uint64}, cmd=true, sql = [[
update parsav_posts set
artifacts = artifacts || $2::bigint
where id = $1::bigint and not
artifacts @> array[$2::bigint] -- prevent duplication
................................................................................
lib.pq.PQclear(res)
return pqr {0, nil}
else
return pqr {ct, res}
end
end
end
local terra row_to_post(r: &pqr, row: intptr): lib.mem.ptr(lib.store.post)
var subj: rawstring, sblen: intptr
var cvhu: rawstring, cvhlen: intptr
if r:null(row,3)
then subj = nil sblen = 0
else subj = r:string(row,3) sblen = r:len(row,3)+1
................................................................................
uid: uint64,
folder: pstring
)
var res = queries.artifact_enum_uid.exec(src,uid,folder)
if res.sz > 0 then
var m = lib.mem.heapa([lib.mem.ptr(lib.store.artifact)], res.sz)
for i=0,res.sz do
var id = res:int(uint64,i,0)
var idbuf: int8[lib.math.shorthand.maxlen]
var idlen = lib.math.shorthand.gen(id, &idbuf[0])
var desc = res:_string(i,2)
var folder = res:_string(i,3)
var mime = res:_string(i,4)
m.ptr[i] = [ lib.str.encapsulate(lib.store.artifact, {
desc = {`desc.ptr, `desc.ct + 1};
folder = {`folder.ptr, `folder.ct + 1};
mime = {`mime.ptr, `mime.ct + 1};
url = {`&idbuf[0], `idlen + 1};
}) ]
m(i).ptr.rid = id
m(i).ptr.owner = uid
end
return m
else return [lib.mem.lstptr(lib.store.artifact)].null() end
end];
artifact_load = [terra(
src: &lib.store.source,
rid: uint64
): {binblob, pstring}
var r = queries.artifact_load.exec(src,rid)
if r.sz == 0 then return binblob.null(), pstring.null() end
................................................................................
var mbin = r:bin(0,0)
var bin = lib.mem.heapa(uint8,mbin.ct)
lib.mem.cpy(bin.ptr, mbin.ptr, bin.ct)
r:free()
return bin, mime
end];
post_attach_ctl = [terra(
src: &lib.store.source,
post: uint64,
artifact: uint64,
detach: bool
): {}
|
> > > > > > > > > > > > > > > > > > > > > > > > | < < < < < < < < < < < < > > > > > > > > > > > > > > > > > > > > > > > > > > > |
550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 ... 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 .... 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 .... 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 |
from parsav_artifact_claims as a where uid = $1::bigint and rid = $2::bigint
]];
};
artifact_load = {
params = {uint64}, sql = [[
select content, mime from parsav_artifacts where id = $1::bigint
]];
};
artifact_folder_enum = {
params = {uint64}, sql = [[
select distinct folder from parsav_artifact_claims where
uid = $1::bigint and folder is not null
order by folder
]];
};
post_attach_ctl_ins = {
params = {uint64, uint64}, cmd=true, sql = [[
update parsav_posts set
artifacts = artifacts || $2::bigint
where id = $1::bigint and not
artifacts @> array[$2::bigint] -- prevent duplication
................................................................................
lib.pq.PQclear(res)
return pqr {0, nil}
else
return pqr {ct, res}
end
end
end
local terra row_to_artifact(res: &pqr, i: intptr): lib.mem.ptr(lib.store.artifact)
var id = res:int(uint64,i,0)
var idbuf: int8[lib.math.shorthand.maxlen]
var idlen = lib.math.shorthand.gen(id, &idbuf[0])
var desc = res:_string(i,2)
var folder = res:_string(i,3)
var mime = res:_string(i,4)
var m = [ lib.str.encapsulate(lib.store.artifact, {
desc = {`desc.ptr, `desc.ct + 1};
folder = {`folder.ptr, `folder.ct + 1};
mime = {`mime.ptr, `mime.ct + 1};
url = {`&idbuf[0], `idlen + 1};
}) ]
m.ptr.rid = id
return m
end
local terra row_to_post(r: &pqr, row: intptr): lib.mem.ptr(lib.store.post)
var subj: rawstring, sblen: intptr
var cvhu: rawstring, cvhlen: intptr
if r:null(row,3)
then subj = nil sblen = 0
else subj = r:string(row,3) sblen = r:len(row,3)+1
................................................................................
uid: uint64,
folder: pstring
)
var res = queries.artifact_enum_uid.exec(src,uid,folder)
if res.sz > 0 then
var m = lib.mem.heapa([lib.mem.ptr(lib.store.artifact)], res.sz)
for i=0,res.sz do
m.ptr[i] = row_to_artifact(&res, i)
m(i).ptr.owner = uid
end
return m
else return [lib.mem.lstptr(lib.store.artifact)].null() end
end];
artifact_fetch = [terra(
src: &lib.store.source,
uid: uint64,
rid: uint64
)
var res = queries.artifact_fetch.exec(src,uid,rid)
if res.sz > 0 then
var a = row_to_artifact(&res, 0)
a.ptr.owner = uid
res:free()
return a
end
return [lib.mem.ptr(lib.store.artifact)].null()
end];
artifact_load = [terra(
src: &lib.store.source,
rid: uint64
): {binblob, pstring}
var r = queries.artifact_load.exec(src,rid)
if r.sz == 0 then return binblob.null(), pstring.null() end
................................................................................
var mbin = r:bin(0,0)
var bin = lib.mem.heapa(uint8,mbin.ct)
lib.mem.cpy(bin.ptr, mbin.ptr, bin.ct)
r:free()
return bin, mime
end];
artifact_folder_enum = [terra(
src: &lib.store.source,
uid: uint64
)
var r = queries.artifact_folder_enum.exec(src,uid)
if r.sz == 0 then return [lib.mem.ptr(pstring)].null() end
defer r:free()
var lst = lib.mem.heapa(pstring, r.sz)
for i=0,r.sz do lst.ptr[i] = r:String(i,0) end
return lst
end];
post_attach_ctl = [terra(
src: &lib.store.source,
post: uint64,
artifact: uint64,
detach: bool
): {}
|
Modified html.t from [ee4d50abb4] to [f6f8bc0dcc].
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
-- vim: ft=terra
local m={}
local pstr = lib.mem.ptr(int8)
terra m.sanitize(txt: pstr, quo: bool)
var a: lib.str.acc a:init(txt.ct*1.3)
for i=0,txt.ct do
if txt(i) == @'<' then a:lpush('<')
elseif txt(i) == @'>' then a:lpush('>')
elseif txt(i) == @'&' then a:lpush('&')
elseif quo and txt(i) == @'"' then a:lpush('"')
else a:push(&txt(i),1) end
end
return a:finalize()
end
return m
|
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
-- vim: ft=terra
local m={}
local pstr = lib.mem.ptr(int8)
terra m.sanitize(txt: pstr, quo: bool)
if txt.ptr == nil then return pstr.null() end
if txt.ct == 0 then txt.ct = lib.str.sz(txt.ptr) end
var a: lib.str.acc a:init(txt.ct*1.3)
for i=0,txt.ct do
if txt(i) == @'<' then a:lpush('<')
elseif txt(i) == @'>' then a:lpush('>')
elseif txt(i) == @'&' then a:lpush('&')
elseif quo and txt(i) == @'"' then a:lpush('"')
else a:push(&txt(i),1) end
end
return a:finalize()
end
terra m.hexdgt(i: uint8)
if i >= 10 then
return @'A' + (i - 10)
else return 0x30 + i end
end
terra m.hexbyte(i: uint8): int8[2]
return arrayof(int8,
m.hexdgt(i / 0x10),
m.hexdgt(i % 0x10))
end
terra m.urlenc(txt: pstr, qparam: bool)
if txt.ptr == nil then return pstr.null() end
if txt.ct == 0 then txt.ct = lib.str.sz(txt.ptr) end
var a: lib.str.acc a:init(txt.ct*1.3)
for i=0,txt.ct do
if txt(i) == @' ' then a:lpush('+')
elseif txt(i) == @'&' and not qparam then a:lpush('&')
elseif (txt(i) < 0x2c or
(txt(i) > @';' and txt(i) < @'@') or
(txt(i) > @'Z' and txt(i) < @'a') or
(txt(i) >= 0x7b and txt(i) <= 0x7f)) and
txt(i) ~= @'_' and (qparam == true or txt(i) ~= @'=') then
var str = m.hexbyte(txt(i))
a:lpush('%'):push(&str[0], 2)
else a:push(&txt(i),1) end
end
return a:finalize()
end
return m
|
Modified render/media-gallery.t from [7a98efa9ff] to [da27a31f83].
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
render_media_gallery(co: &lib.srv.convo, path: lib.mem.ptr(lib.mem.ref(int8)), uid: uint64, acc: &lib.str.acc) -- note that when calling this function, path must be adjusted so that path(0) -- eq "media" var owner = false if co.aid ~= 0 and co.who.id == uid then owner = true end var ou = co.srv:actor_fetch_uid(uid) if not ou then goto e404 end var mode: uint8 = show_new var folder: pstr if path.ct == 2 then if path(1):cmp(lib.str.lit'unfiled') then mode=show_unfiled elseif path(1):cmp(lib.str.lit'all') then mode=show_all else goto e404 end elseif path.ct == 3 and path(1):cmp(lib.str.lit'kind') then end if mode == show_new then folder = lib.str.plit'' elseif mode == show_all then folder = pstr.null() elseif mode == show_unfiled then folder = lib.str.plit'' -- TODO -- else get folder from query str end var view = data.view.media_gallery { menu = pstr{'',0}; folders = pstr{'',0}; directory = pstr{'',0}; images = pstr{'',0}; pfx = pstr{'',0}; } if not owner then var pa: lib.str.acc pa:init(32) pa:lpush('/') if ou(0).origin ~= 0 then pa:lpush('@') end pa:push(ou(0).xid,0) view.pfx = pa:finalize() end if owner then view.menu = P'<a class="pos" href="/media/upload">upload</a><hr>' end var md = co.srv:artifact_enum_uid(uid, folder) var gallery: lib.str.acc gallery:init(256) var files: lib.str.acc files:init(256) for i=0,md.ct do if lib.str.ncmp(md(i)(0).mime, 'image/', 6) == 0 then gallery:lpush('<a class="thumb" href="'):ppush(view.pfx):lpush('/media/a/') :push(md(i)(0).url,0):lpush('"><img src="/file/'):push(md(i)(0).url,0) :lpush('"><div class="caption">'):push(md(i)(0).desc,0) :lpush('</div></a>') else files:lpush('<a class="file" href="'):ppush(view.pfx):lpush('/media/a/') :push(md(i)(0).url,0):lpush('"><span class="label">'):push(md(i)(0).desc,0) :lpush('</span> <span class="mime">'):push(md(i)(0).mime,0) :lpush('</span></a>') end md(i):free() end view.images = gallery:finalize() view.directory = files:finalize() if acc ~= nil then view:append(acc) else lib.dbg('emitting page') var pg = view:tostr() defer pg:free() lib.dbg('compiled page') co:stdpage([lib.srv.convo.page] { title = P'media'; class = P'media manager'; cache = false; body = pg; }) lib.dbg('sent page') end view.images:free() view.directory:free() if not owner then view.pfx:free() end if md:ref() then md:free() end do return end ::e404:: co:complain(404,'media not found','no such media exists on this server') end return render_media_gallery |
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | | | | | | | > > | | | | < < < | | | | | | | | < > > | > > > > > > > > > > > > | < < | > | | | | | | | | > | | | | | | > | | | | | | | | | | | | | | | | | | | | | | | | | < > > | > > | |
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
render_media_gallery(co: &lib.srv.convo, path: lib.mem.ptr(lib.mem.ref(int8)), uid: uint64, acc: &lib.str.acc) -- note that when calling this function, path must be adjusted so that path(0) -- eq "media" var owner = false if co.aid ~= 0 and co.who.id == uid then owner = true end var ou = co.srv:actor_fetch_uid(uid) if not ou then goto e404 end do defer ou:free() var pfx = pstr.null() if not owner then var pa: lib.str.acc pa:init(32) pa:lpush('/') if ou(0).origin ~= 0 then pa:lpush('@') end pa:push(ou(0).xid,0) pfx = pa:finalize() end if path.ct >= 3 and path(1):cmp(lib.str.lit'a') then var id, idok = lib.math.shorthand.parse(path(2).ptr, path(2).ct) if not idok then goto e404 end var art = co.srv:artifact_fetch(uid, id) if not art then goto e404 end if path.ct == 3 then -- sniff out the artifact type and display the appropriate viewer var artid = cs(art(0).url) var btns: lib.str.acc if owner then btns:compose('<a class="neg button" href="',pfx,'/media/a/',artid,'/del">delete</a><a class="button" href="',pfx,'/media/a/',artid,'/edit">alter</a>') else btns:compose('<a class="pos button" href="',pfx,'/media/a/',artid,'/collect">collect</a>') end var btntxt = btns:finalize() defer btntxt:free() var desc = lib.smackdown.html(pstr{art(0).desc,0}, true) defer desc:free() var viewerprops = { pfx = pfx, desc = desc; id = artid; btns = btntxt; } if lib.str.ncmp(art(0).mime, 'image/', 6) == 0 then var view = data.view.media_image(viewerprops) var pg = view:tostr() co:stdpage([lib.srv.convo.page] { title = lib.str.plit'media :: image'; class = lib.str.plit'media viewer img'; cache = false, body = pg; }) pg:free() elseif lib.str.cmp(art(0).mime, 'text/markdown') == 0 then var view = data.view.media_text(viewerprops) var text, mime = co.srv:artifact_load(id) mime:free() view.text = lib.smackdown.html(pstr{[rawstring](text.ptr),text.ct}, false) text:free() var pg = view:tostr() view.text:free() co:stdpage([lib.srv.convo.page] { title = lib.str.plit'media :: text'; class = lib.str.plit'media viewer text'; cache = false, body = pg; }) pg:free() elseif lib.str.ncmp(art(0).mime, 'text/', 5) == 0 or lib.str.cmp(art(0).mime, 'application/x-perl') == 0 or lib.str.cmp(art(0).mime, 'application/sql') == 0 -- and so on (we need a mimelib at some point) -- then var view = data.view.media_text(viewerprops) var text, mime = co.srv:artifact_load(id) mime:free() var san = lib.html.sanitize(pstr{[rawstring](text.ptr),text.ct}, false) text:free() view.text = lib.str.acc{}:compose('<pre>',san,'</pre>'):finalize() san:free() var pg = view:tostr() view.text:free() co:stdpage([lib.srv.convo.page] { title = lib.str.plit'media :: text'; class = lib.str.plit'media viewer text'; cache = false, body = pg; }) pg:free() else co:complain(500,'bad file type','this file type is not supported') end elseif path.ct == 4 then var act = path(3) var curl = lib.str.acc{}:compose(pfx, '/media/a/', path(2)):finalize() defer curl:free() if act:cmp(lib.str.lit'avi') and lib.str.ncmp(art(0).mime, 'image/', 6) == 0 then co:confirm('set avatar', 'are you sure you want this image to be your new avatar?',curl) elseif act:cmp(lib.str.lit'del') then co:confirm('delete', 'are you sure you want to permanently delete this artifact?',curl) else goto e404 end end else var mode: uint8 = show_new var folder: pstr if path.ct == 2 then if path(1):cmp(lib.str.lit'unfiled') then mode=show_unfiled elseif path(1):cmp(lib.str.lit'all') then mode=show_all else goto e404 end elseif path.ct == 3 and path(1):cmp(lib.str.lit'kind') then end var folders = co.srv:artifact_folder_enum(uid) if mode == show_new then folder = lib.str.plit'' elseif mode == show_all or mode == show_unfiled then folder = pstr.null() end var view = data.view.media_gallery { menu = pstr{'',0}; folders = pstr{'',0}; directory = pstr{'',0}; images = pstr{'',0}; pfx = pfx; } if folders.ct > 0 then var fa: lib.str.acc fa:init(128) var fldr = co:pgetv('folder') for i=0,folders.ct do var ule = lib.html.urlenc(folders(i), true) defer ule:free() var san = lib.html.sanitize(folders(i), true) defer san:free() fa:lpush('<a href="'):ppush(pfx):lpush('/media?folder='):ppush(ule) :lpush('">'):ppush(san):lpush('</a>') lib.dbg('checking folder ',{fldr.ptr,fldr.ct},' against ',{folders(i).ptr,folders(i).ct}) if fldr:ref() and folders(i):cmp(fldr) then folder = folders(i) lib.dbg('folder match ',{fldr.ptr,fldr.ct}) else folders(i):free() end end fa:lpush('<hr>') view.folders = fa:finalize() folders:free() end if owner then view.menu = P'<a class="pos" href="/media/upload">upload</a><hr>' end var md = co.srv:artifact_enum_uid(uid, folder) var gallery: lib.str.acc gallery:init(256) var files: lib.str.acc files:init(256) for i=0,md.ct do var desc = lib.smackdown.html(pstr{md(i)(0).desc,0}, true) defer desc:free() if lib.str.ncmp(md(i)(0).mime, 'image/', 6) == 0 then gallery:lpush('<a class="thumb" href="'):ppush(pfx):lpush('/media/a/') :push(md(i)(0).url,0):lpush('"><img src="/file/'):push(md(i)(0).url,0) :lpush('"><div class="caption">'):ppush(desc) :lpush('</div></a>') else var mime = lib.html.sanitize(pstr{md(i)(0).mime,0}, true) defer mime:free() --just in case files:lpush('<a class="file" href="'):ppush(pfx):lpush('/media/a/') :push(md(i)(0).url,0):lpush('"><span class="label">'):ppush(desc) :lpush('</span> <span class="mime">'):ppush(mime) :lpush('</span></a>') end md(i):free() end view.images = gallery:finalize() view.directory = files:finalize() if acc ~= nil then view:append(acc) else lib.dbg('emitting page') var pg = view:tostr() defer pg:free() lib.dbg('compiled page') co:stdpage([lib.srv.convo.page] { title = P'media'; class = P'media manager'; cache = false; body = pg; }) lib.dbg('sent page') end view.images:free() view.directory:free() if view.folders.ct > 0 then view.folders:free() end if folder.ct > 0 then folder:free() end if md:ref() then md:free() end end if not owner then pfx:free() end return end ::e404:: co:complain(404,'media not found','no such media exists on this server') end return render_media_gallery |
Modified route.t from [8605ea50bd] to [881176d2e1].
510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 |
terra http.file_serve_raw(co: &lib.srv.convo, id: lib.mem.ptr(int8))
var id, idok = lib.math.shorthand.parse(id.ptr, id.ct)
if not idok then goto e404 end
var data, mime = co.srv:artifact_load(id)
if not data then goto e404 end
do defer data:free() defer mime:free()
lib.net.mg_printf(co.con, 'HTTP/1.1 200 OK\r\nContent-Type: %.*s\r\nContent-Length: %llu\r\n\r\n', mime.ct, mime.ptr, data.ct + 2)
lib.net.mg_send(co.con, data.ptr, data.ct)
lib.net.mg_send(co.con, '\r\n', 2)
return end
::e404:: do co:complain(404, 'artifact not found', 'no such artifact has been uploaded to this instance') return end
end
|
| > > > > > > > > > > > > > > |
510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 |
terra http.file_serve_raw(co: &lib.srv.convo, id: lib.mem.ptr(int8)) var id, idok = lib.math.shorthand.parse(id.ptr, id.ct) if not idok then goto e404 end var data, mime = co.srv:artifact_load(id) if not data then goto e404 end do defer data:free() defer mime:free() var safemime = mime -- TODO this is not a satisfactory solution; it's a bandaid on a gaping -- chest wound. ultimately we need to compile a whitelist of safe mime -- types as part of mimelib, but that is no small task. for now, this -- will keep the patient from immediately bleeding out if mime:cmp(lib.str.plit'text/html') or mime:cmp(lib.str.plit'text/xml') or mime:cmp(lib.str.plit'application/xhtml+xml') or mime:cmp(lib.str.plit'application/vnd.wap.xhtml+xml') then -- danger will robinson safemime = lib.str.plit'text/plain' elseif mime:cmp(lib.str.plit'application/x-shockwave-flash') then safemime = lib.str.plit'application/octet-stream' end lib.net.mg_printf(co.con, "HTTP/1.1 200 OK\r\nContent-Type: %.*s\r\nContent-Length: %llu\r\nContent-Security-Policy: sandbox; default-src 'none'; form-action 'none'; navigate-to 'none';\r\nX-Content-Options: nosniff\r\n\r\n", safemime.ct, safemime.ptr, data.ct + 2) lib.net.mg_send(co.con, data.ptr, data.ct) lib.net.mg_send(co.con, '\r\n', 2) return end ::e404:: do co:complain(404, 'artifact not found', 'no such artifact has been uploaded to this instance') return end end |
Modified smackdown.t from [926ec15b69] to [e99ea3e622].
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
do return l+i end
::nexti::end
end
local terra scanline_wordend(l: rawstring, max: intptr, n: rawstring, nc: intptr)
var sl = scanline(l,max,n,nc)
if sl == nil then return nil else sl = sl + nc end
if sl >= l+max or isws(@sl) then return sl-nc end
return nil
end
terra m.html(input: pstr, firstline: bool)
if input.ct == 0 then input.ct = lib.str.sz(input.ptr) end
var md = lib.html.sanitize(input,false)
var styled: lib.str.acc styled:init(md.ct)
do var i = 0 while i < md.ct do
var wordstart = (i == 0 or isws(md.ptr[i-1]))
var wordend = (i == md.ct - 1 or isws(md.ptr[i+1]))
var here = md.ptr + i
var rem = md.ct - i
if @here == @'[' then
var sep = scanline(here,rem, '](', 2)
var term = scanline(sep+2,rem - ((sep+2)-here), ')', 1)
if sep ~= nil and term ~= nil then
|
| > | | > > |
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
do return l+i end ::nexti::end end local terra scanline_wordend(l: rawstring, max: intptr, n: rawstring, nc: intptr) var sl = scanline(l,max,n,nc) if sl == nil then return nil else sl = sl + nc end if sl >= l+max or not isws(@(sl-1)) then return sl-nc end return nil end terra m.html(input: pstr, firstline: bool) if input.ptr == nil then return pstr.null() end if input.ct == 0 then input.ct = lib.str.sz(input.ptr) end var md = lib.html.sanitize(input,false) var styled: lib.str.acc styled:init(md.ct) do var i = 0 while i < md.ct do --var wordstart = (i == 0 or isws(md.ptr[i-1])) --var wordend = (i == md.ct - 1 or isws(md.ptr[i+1])) var wordstart = (i + 1 < md.ct and not isws(md.ptr[i+1])) var wordend = (i == md.ct - 1 or not isws(md.ptr[i-1])) var here = md.ptr + i var rem = md.ct - i if @here == @'[' then var sep = scanline(here,rem, '](', 2) var term = scanline(sep+2,rem - ((sep+2)-here), ')', 1) if sep ~= nil and term ~= nil then |
Modified srv.t from [31acbbce83] to [ca6d27c8d7].
280 281 282 283 284 285 286 287 288 289 290 291 292 293 |
} self:statpage(code, body) body.title:free() body.body:free() end convo.methods.assertpow = macro(function(self, pow) return quote var ok = true if self.aid == 0 or self.who.rights.powers.[pow:asvalue()]() == false then ok = false self:complain(403,'insufficient privileges',['you lack the <strong>'..pow:asvalue()..'</strong> power and cannot perform this action']) |
> > > > > > > > > > > > > > > > > |
280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 |
} self:statpage(code, body) body.title:free() body.body:free() end terra convo:confirm(title: pstring, msg: pstring, cancel: pstring) var conf = data.view.confirm { title = title; query = msg; cancel = cancel; } var ti: lib.str.acc ti:compose('confirm :: ', title) var body = conf:tostr() defer body:free() var cf = [convo.page] { title = ti:finalize(); class = lib.str.plit 'query'; body = body; cache = false; } self:stdpage(cf) cf.title:free() end convo.methods.assertpow = macro(function(self, pow) return quote var ok = true if self.aid == 0 or self.who.rights.powers.[pow:asvalue()]() == false then ok = false self:complain(403,'insufficient privileges',['you lack the <strong>'..pow:asvalue()..'</strong> power and cannot perform this action']) |
Modified static/style.scss from [f5bd822625] to [fb57063208].
281 282 283 284 285 286 287 288 289 290 291 292 293 294 ... 487 488 489 490 491 492 493 494 495 496 497 498 499 500 .... 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 .... 1073 1074 1075 1076 1077 1078 1079 |
grid-row: 1 / 2;
display: grid;
grid-template-columns: 1.1in 1fr;
grid-template-rows: max-content 1fr;
> .avatar {
display: block;
width: 1in; height: 1in;
grid-column: 1 / 2;
grid-row: 1 / 3;
border: 1px solid black;
}
> .id {
grid-column: 2 / 3;
grid-row: 1 / 2;
................................................................................
font-size: 1.5ex !important;
letter-spacing: 1.3px;
padding-bottom: 3px;
border-radius: 2px;
vertical-align: baseline;
box-shadow: 1px 1px 1px black;
}
div.thread {
margin-left: 0.3in;
& + article.post { margin-top: 0.3in; }
}
a[href].username {
................................................................................
height: max-content;
background-image: url(/s/file.webp); //TODO different icons for different mime types
background-repeat: no-repeat;
background-position: left;
padding-left: 0.4in;
> .label {
text-decoration: underline;
}
> .mime {
font-style: italic;
opacity: 60%;
margin-left: 0.5ex;
}
}
................................................................................
}
}
.media.upload form {
padding: 0.1in 0.2in;
@extend %box;
}
|
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 ... 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 .... 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 .... 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 |
grid-row: 1 / 2;
display: grid;
grid-template-columns: 1.1in 1fr;
grid-template-rows: max-content 1fr;
> .avatar {
display: block;
width: 1in; height: 1in;
object-fit: contain;
grid-column: 1 / 2;
grid-row: 1 / 3;
border: 1px solid black;
}
> .id {
grid-column: 2 / 3;
grid-row: 1 / 2;
................................................................................
font-size: 1.5ex !important;
letter-spacing: 1.3px;
padding-bottom: 3px;
border-radius: 2px;
vertical-align: baseline;
box-shadow: 1px 1px 1px black;
}
pre { @extend %teletype; white-space: pre-wrap; }
div.thread {
margin-left: 0.3in;
& + article.post { margin-top: 0.3in; }
}
a[href].username {
................................................................................
height: max-content;
background-image: url(/s/file.webp); //TODO different icons for different mime types
background-repeat: no-repeat;
background-position: left;
padding-left: 0.4in;
> .label {
text-decoration: underline;
text-decoration-width: 1px;
text-underline-offset: 0.1em;
text-decoration-color: tone(10%,-0.5);
}
&:hover > .label {
}
> .mime {
font-style: italic;
opacity: 60%;
margin-left: 0.5ex;
}
}
................................................................................
}
}
.media.upload form {
padding: 0.1in 0.2in;
@extend %box;
}
body.media div.viewer {
@extend %box;
padding: 0.2in;
margin-bottom: 0.2in;
&.img {
> img {
display: block;
max-width: 100%;
margin: auto;
}
.caption {
margin-top: 0.2in;
text-align: center;
&:empty {margin: 0;}
}
}
&.text {
> .desc {
border-bottom: 1px solid tone(-5%);
box-shadow: 0 2px 0 black;
margin-bottom: 0.1in;
padding-bottom: 0.1in;
}
> article {
font-size: 90%;
padding: 0 0.2in;
max-height: calc(100vh - 3in);
overflow-y: scroll;
text-align: justify;
}
}
}
|
Modified store.t from [fdc1c1d9e2] to [eca94a58d5].
488 489 490 491 492 493 494 495 496 497 498 499 500 501 |
-- restricted by folder (empty string = new only)
artifact_fetch: {&m.source, uint64, uint64} -> lib.mem.ptr(m.artifact)
-- fetch a user's view of an artifact
-- uid: uint64
-- rid: uint64
artifact_load: {&m.source, uint64} -> {lib.mem.ptr(uint8),lib.str.t}
-- load the body of an artifact into memory (also returns mime)
nkvd_report_issue: {&m.source, &m.kompromat} -> {}
-- an incidence of Badthink has been detected. report it immediately
-- to the Supreme Soviet
nkvd_reports_enum: {&m.source, &m.kompromat} -> lib.mem.ptr(m.kompromat)
-- search through the Archives
-- proto: kompromat (null for all records, or a prototype describing the records to return)
|
> > |
488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 |
-- restricted by folder (empty string = new only)
artifact_fetch: {&m.source, uint64, uint64} -> lib.mem.ptr(m.artifact)
-- fetch a user's view of an artifact
-- uid: uint64
-- rid: uint64
artifact_load: {&m.source, uint64} -> {lib.mem.ptr(uint8),lib.str.t}
-- load the body of an artifact into memory (also returns mime)
artifact_folder_enum: {&m.source, uint64} -> lib.mem.ptr(lib.str.t)
-- enumerate all of a user's folders
nkvd_report_issue: {&m.source, &m.kompromat} -> {}
-- an incidence of Badthink has been detected. report it immediately
-- to the Supreme Soviet
nkvd_reports_enum: {&m.source, &m.kompromat} -> lib.mem.ptr(m.kompromat)
-- search through the Archives
-- proto: kompromat (null for all records, or a prototype describing the records to return)
|
Modified view/load.lua from [fbf23a2927] to [9f4f065de0].
9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
'tweet'; 'profile'; 'compose'; 'notice'; 'media-gallery'; 'media-upload'; 'login-username'; 'login-challenge'; 'conf'; 'conf-profile'; 'conf-sec'; |
> > |
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
'tweet'; 'profile'; 'compose'; 'notice'; 'media-gallery'; 'media-upload'; 'media-image'; 'media-text'; 'login-username'; 'login-challenge'; 'conf'; 'conf-profile'; 'conf-sec'; |
Added view/media-image.tpl version [df3a1820c7].
> > > > > > > > > > |
1 2 3 4 5 6 7 8 9 10 |
<div class="viewer img"> <img src="/file/@id"> <div class="caption">@desc</div> </div> <menu class="choice horizontal"> <a class="button" href="@pfx/media">index</a> <a class="button" href="@pfx/media/a/@id/avi">set as avatar</a> @btns <a class="button" href="/file/@id" download>download</a> </menu> |
Added view/media-text.tpl version [73c12d23b4].
> > > > > > > > > |
1 2 3 4 5 6 7 8 9 |
<div class="viewer text"> <div class="desc">@desc</div> <article>@text</article> </div> <menu class="choice horizontal"> <a class="button" href="@pfx/media">index</a> @btns <a class="button" href="/file/@id" download>download</a> </menu> |