Overview
| Comment: | further iteration on media |
|---|---|
| Downloads: | Tarball | ZIP archive | SQL archive |
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA3-256: |
af5ed65b68e96856432eb7477e8852b2 |
| User & Date: | lexi on 2021-01-07 09:39:29 |
| Other Links: | manifest | tags |
Context
|
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 | |
| 07:35 | tentative beginnings of upload + media management system check-in: f4c6e72a22 user: lexi tags: trunk | |
Changes
Modified backend/pgsql.t from [5d4cebec04] to [fc1c52be55].
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 1613 |
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) var url = lib.str.acc{}:init(48):lpush('/media/a/'):push(&idbuf[0],idlen):finalize() defer url:free() 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 = {`url.ptr, `url.ct + 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]; post_attach_ctl = [terra( src: &lib.store.source, post: uint64, artifact: uint64, detach: bool ): {} |
< | > > > > > > > > > > > > > > > > |
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 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 |
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 mime = r:String(0,1)
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
): {}
|
Modified math.t from [1d1d177061] to [60110bc615].
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 |
var sz: intptr = 0 for i = 0, f.ct do if f(i) == @',' then goto skip end if f(i) >= 0x30 and f(i) <= 0x39 then sz = sz * 10 sz = sz + f(i) - 0x30 else if i+1 == f.ct or f(i) == 0 then return sz, true end if i+2 == f.ct or f(i+1) == 0 then if f(i) == @'b' then return sz/8, true end -- bits else var s: intptr = 0 if i+3 == f.ct or f(i+2) == 0 then s = i + 1 elseif (i+4 == f.ct or f(i+3) == 0) and f(i+1) == @'i' then -- grudgingly tolerate ~mebibits~ and its ilk, without -- affecting the result in any way s = i + 2 else return 0, false end if f(s) == @'b' then sz = sz/8 -- bits elseif f(s) ~= @'B' then return 0, false end -- wth end var c = f(i) if c >= @'A' and c <= @'Z' then c = c - 0x20 end switch c do -- normal char literal syntax doesn't work here, leads to llvm error (!!) case [uint8]([string.byte('k')]) then return sz * [1024ULL ^ 1], true end case [uint8]([string.byte('m')]) then return sz * [1024ULL ^ 2], true end case [uint8]([string.byte('g')]) then return sz * [1024ULL ^ 3], true end case [uint8]([string.byte('t')]) then return sz * [1024ULL ^ 4], true end case [uint8]([string.byte('e')]) then return sz * [1024ULL ^ 5], true end case [uint8]([string.byte('y')]) then return sz * [1024ULL ^ 6], true end else return sz, true end end ::skip::end return sz, true end return m |
| | | | | > | > | | |
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 |
var sz: intptr = 0 for i = 0, f.ct do if f(i) == @',' then goto skip end if f(i) >= 0x30 and f(i) <= 0x39 then sz = sz * 10 sz = sz + f(i) - 0x30 else if i+0 == f.ct or f(i) == 0 then return sz, true end if i+1 == f.ct or f(i+1) == 0 then if f(i) == @'b' then return sz/8, true end -- bits else var s: intptr = 0 if i+2 == f.ct or f(i+2) == 0 then s = i + 1 elseif (i+3 == f.ct or f(i+3) == 0) and f(i+1) == @'i' then -- grudgingly tolerate ~mebibits~ and its ilk, without -- affecting the result in any way s = i + 2 else return 0, false end if f(s) == @'b' then sz = sz/8 -- bits elseif f(s) ~= @'B' then return 0, false end -- wth end var c = f(i) if c >= @'A' and c <= @'Z' then c = c + 0x20 end switch c do -- normal char literal syntax doesn't work here, leads to llvm error (!!) case [uint8]([string.byte('k')]) then return sz * [1024ULL ^ 1], true end case [uint8]([string.byte('m')]) then return sz * [1024ULL ^ 2], true end case [uint8]([string.byte('g')]) then return sz * [1024ULL ^ 3], true end case [uint8]([string.byte('t')]) then return sz * [1024ULL ^ 4], true end case [uint8]([string.byte('p')]) then return sz * [1024ULL ^ 5], true end case [uint8]([string.byte('e')]) then return sz * [1024ULL ^ 6], true end case [uint8]([string.byte('z')]) then return sz * [1024ULL ^ 7], true end case [uint8]([string.byte('y')]) then return sz * [1024ULL ^ 8], true end else return 0, false end end ::skip::end return sz, true end return m |
Modified render/media-gallery.t from [79b3557b2e] to [7a98efa9ff].
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 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 |
-- vim: ft=terra
local pstr = lib.str.t
local P = lib.str.plit
local terra cs(s: rawstring)
return pstr { ptr = s, ct = lib.str.sz(s) }
end
local show_all,show_new,show_files,show_vid,show_img=1,2,3,4,5
local terra
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 view = data.view.media_gallery {
menu = pstr{'',0};
folders = pstr{'',0};
directory = pstr{'',0};
images = pstr{'',0};
}
if owner then
view.menu = P'<a class="pos" href="/media/upload">upload</a><hr>'
end
var mode: uint8 = show_new
var folder: pstr
if mode == show_new then
folder = lib.str.plit''
elseif mode == show_all then
folder = pstr.null()
-- else get folder from query str
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="')
if not owner then
gallery:lpush('/')
if ou(0).origin ~= 0 then gallery:lpush('@') end
gallery:push(ou(0).xid,0):lpush('/')
end
gallery:push(md(i)(0).url,0)
:lpush('"><img src="') :push(md(i)(0).url,0)
:lpush('/raw"><div class="caption">') :push(md(i)(0).desc,0)
:lpush('</div></a>')
else
files:lpush('<a class="file" href="')
if not owner then
gallery:lpush('/')
if ou(0).origin ~= 0 then gallery:lpush('@') end
gallery:push(ou(0).xid,0):lpush('/')
end
files: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
var pg = view:tostr() defer pg:free()
co:stdpage([lib.srv.convo.page] {
title = P'media';
class = P'media manager';
cache = false;
body = pg;
})
end
view.images:free()
view.directory:free()
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
|
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > < < < < < < < < | < < < < < | < | | < < < < < < | > > > > |
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 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 |
-- vim: ft=terra
local pstr = lib.str.t
local P = lib.str.plit
local terra cs(s: rawstring)
return pstr { ptr = s, ct = lib.str.sz(s) }
end
local show_all,show_new,show_unfiled,show_files,show_vid,show_img=1,2,3,4,5,6
local terra
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
|
Modified route.t from [af3d41e739] to [8605ea50bd].
404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 ... 505 506 507 508 509 510 511 512 513 514 515 516 517 518 ... 526 527 528 529 530 531 532 533 534 535 536 537 538 539 ... 551 552 553 554 555 556 557 558 559 560 561 562 563 564 |
end terra http.media_manager(co: &lib.srv.convo, path: hpath, meth: method.t) if meth == method.post then goto badop end if path.ct == 1 or (path.ct >= 3 and path(1):cmp(lib.str.lit'a')) then if meth == method.post then goto badop end lib.render.media_gallery(co,path,co.who.id,nil) elseif path.ct == 2 then if path(1):cmp(lib.str.lit'upload') and co.who.rights.powers.artifact() then if meth == method.get then var view = data.view.media_upload { folders = '' } var pg = view:tostr() defer pg:free() co:stdpage([lib.srv.convo.page] { title = lib.str.plit'media :: upload'; class = lib.str.plit'media upload'; cache = false; body = pg; }) elseif meth == method.post_file then var desc = pstring.null() var folder = pstring.null() var mime = pstring.null() var name = pstring.null() var body = binblob.null() for i=0, co.uploads.sz do var up = co.uploads.storage.ptr + i if up.body.ct > 0 then if up.field:cmp(lib.str.plit'desc') then desc = up.body elseif up.field:cmp(lib.str.plit'folder') then folder = up.body elseif up.field:cmp(lib.str.plit'file') then mime = up.ctype body = binblob {ptr = [&uint8](up.body.ptr), ct = up.body.ct} name = up.filename end end end if not body then goto badop end if body.ct > co.srv.cfg.maxupsz then co:complain(403, 'file too long', "the file you have attempted to upload exceeds the maximum length permitted by this server's upload policy. if it is an image or video, try compressing it at a lower quality setting or resolution") return end var id = co.srv:artifact_instantiate(body,mime) if id == 0 then co:complain(500,'upload failed','artifact rejected. either the server is running out of space or this file is banned from the server') return end co.srv:artifact_expropriate(co.who.id,id,desc,folder) var idbuf: int8[lib.math.shorthand.maxlen] var idlen = lib.math.shorthand.gen(id,&idbuf[0]) var url = lib.str.acc{}:compose('/media/a/',pstring{&idbuf[0],idlen}):finalize() co:reroute(url.ptr) url:free() else goto badop end end else goto e404 end do return end ::badop:: do co:complain(405, 'invalid operation', 'the operation you have attempted on this post is not meaningful') return end ::e404:: do co:complain(404, 'artifact not found', 'no such artifact has been uploaded by this user') return end end do local branches = quote end ................................................................................ end terra http.local_avatar(co: &lib.srv.convo, handle: lib.mem.ptr(int8)) -- TODO retrieve user avatars co:reroute('/s/default-avatar.webp') end -- entry points terra r.dispatch_http(co: &lib.srv.convo, uri: lib.mem.ptr(int8), meth: method.t) lib.dbg('handling URI of form ', {uri.ptr,uri.ct}) co.navbar = lib.render.nav(co) -- some routes are non-hierarchical, and can be resolved with a simple strcmp -- we run through those first before giving up and parsing the URI ................................................................................ elseif uri.ptr[1] == @'@' then http.actor_profile_xid(co, uri, meth) elseif uri.ptr[1] == @'s' and uri.ptr[2] == @'/' and uri.ct > 3 then if not meth_get(meth) then goto wrongmeth end if not http.static_content(co, uri.ptr + 3, uri.ct - 3) then goto notfound end elseif lib.str.ncmp('/avi/', uri.ptr, 5) == 0 then http.local_avatar(co, [lib.mem.ptr(int8)] {ptr = uri.ptr + 5, ct = uri.ct - 5}) elseif uri:cmp(lib.str.plit '/notices') then if co.aid == 0 then co:reroute('/login') return end http.user_notices(co,meth) elseif uri:cmp(lib.str.plit '/compose') then if co.aid == 0 then co:reroute('/login') return end http.post_compose(co,meth) elseif uri:cmp(lib.str.plit '/login') then ................................................................................ if path.ct > 1 and path(0):cmp(lib.str.lit('user')) then http.actor_profile_uid(co, path, meth) elseif path.ct > 1 and path(0):cmp(lib.str.lit('post')) then http.tweet_page(co, path, meth) elseif path(0):cmp(lib.str.lit('tl')) then http.timeline(co, path) elseif path(0):cmp(lib.str.lit('media')) then http.media_manager(co, path, meth) elseif path(0):cmp(lib.str.lit('doc')) then if not meth_get(meth) then goto wrongmeth end http.documentation(co, path) elseif path(0):cmp(lib.str.lit('conf')) then if co.aid == 0 then goto unauth end http.configure(co,path,meth) |
< < < < | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | > > > | < > > > > > > > > > > > > > > > > > |
404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 ... 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 ... 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 ... 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 |
end terra http.media_manager(co: &lib.srv.convo, path: hpath, meth: method.t) if meth == method.post then goto badop end if path.ct == 2 and path(1):cmp(lib.str.lit'upload') and co.who.rights.powers.artifact() then if meth == method.get then var view = data.view.media_upload { folders = '' } var pg = view:tostr() defer pg:free() co:stdpage([lib.srv.convo.page] { title = lib.str.plit'media :: upload'; class = lib.str.plit'media upload'; cache = false; body = pg; }) elseif meth == method.post_file then var desc = pstring.null() var folder = pstring.null() var mime = pstring.null() var name = pstring.null() var body = binblob.null() for i=0, co.uploads.sz do var up = co.uploads.storage.ptr + i if up.body.ct > 0 then if up.field:cmp(lib.str.plit'desc') then desc = up.body elseif up.field:cmp(lib.str.plit'folder') then folder = up.body elseif up.field:cmp(lib.str.plit'file') then mime = up.ctype body = binblob {ptr = [&uint8](up.body.ptr), ct = up.body.ct} name = up.filename end end end if not body then goto badop end if body.ct > co.srv.cfg.maxupsz then co:complain(403, 'file too long', "the file you have attempted to upload exceeds the maximum length permitted by this server's upload policy. if it is an image or video, try compressing it at a lower quality setting or resolution") return end var id = co.srv:artifact_instantiate(body,mime) if id == 0 then co:complain(500,'upload failed','artifact rejected. either the server is running out of space or this file is banned from the server') return end co.srv:artifact_expropriate(co.who.id,id,desc,folder) var idbuf: int8[lib.math.shorthand.maxlen] var idlen = lib.math.shorthand.gen(id,&idbuf[0]) var url = lib.str.acc{}:compose('/media/a/',pstring{&idbuf[0],idlen}):finalize() co:reroute(url.ptr) url:free() else goto badop end else if meth == method.post then goto badop end lib.render.media_gallery(co,path,co.who.id,nil) end do return end ::badop:: do co:complain(405, 'invalid operation', 'the operation you have attempted on this post is not meaningful') return end ::e404:: do co:complain(404, 'artifact not found', 'no such artifact has been uploaded by this user') return end end do local branches = quote end ................................................................................ end terra http.local_avatar(co: &lib.srv.convo, handle: lib.mem.ptr(int8)) -- TODO retrieve user avatars co:reroute('/s/default-avatar.webp') end 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 -- entry points terra r.dispatch_http(co: &lib.srv.convo, uri: lib.mem.ptr(int8), meth: method.t) lib.dbg('handling URI of form ', {uri.ptr,uri.ct}) co.navbar = lib.render.nav(co) -- some routes are non-hierarchical, and can be resolved with a simple strcmp -- we run through those first before giving up and parsing the URI ................................................................................ elseif uri.ptr[1] == @'@' then http.actor_profile_xid(co, uri, meth) elseif uri.ptr[1] == @'s' and uri.ptr[2] == @'/' and uri.ct > 3 then if not meth_get(meth) then goto wrongmeth end if not http.static_content(co, uri.ptr + 3, uri.ct - 3) then goto notfound end elseif lib.str.ncmp('/avi/', uri.ptr, 5) == 0 then http.local_avatar(co, [lib.mem.ptr(int8)] {ptr = uri.ptr + 5, ct = uri.ct - 5}) elseif lib.str.ncmp('/file/', uri.ptr, 6) == 0 then http.file_serve_raw(co, [lib.mem.ptr(int8)] {ptr = uri.ptr + 6, ct = uri.ct - 6}) elseif uri:cmp(lib.str.plit '/notices') then if co.aid == 0 then co:reroute('/login') return end http.user_notices(co,meth) elseif uri:cmp(lib.str.plit '/compose') then if co.aid == 0 then co:reroute('/login') return end http.post_compose(co,meth) elseif uri:cmp(lib.str.plit '/login') then ................................................................................ if path.ct > 1 and path(0):cmp(lib.str.lit('user')) then http.actor_profile_uid(co, path, meth) elseif path.ct > 1 and path(0):cmp(lib.str.lit('post')) then http.tweet_page(co, path, meth) elseif path(0):cmp(lib.str.lit('tl')) then http.timeline(co, path) elseif path(0):cmp(lib.str.lit('media')) then if co.aid == 0 then goto unauth end http.media_manager(co, path, meth) elseif path(0):cmp(lib.str.lit('doc')) then if not meth_get(meth) then goto wrongmeth end http.documentation(co, path) elseif path(0):cmp(lib.str.lit('conf')) then if co.aid == 0 then goto unauth end http.configure(co,path,meth) |
Modified srv.t from [a1d0408148] to [31acbbce83].
526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 ... 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 ... 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 ... 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 |
end -- check for a content-type header, and see if it's a multipart/ -- form-data encoded POST request so we can handle file uploads co.uploads.sz = 0 co.uploads.run = 0 if co.method == [lib.http.method.post] then var ctt = lib.http.findheader(msg, 'Content-Type') if ctt ~= nil then lib.dbg('found content type', {ctt.ptr,ctt.ct}) if lib.str.ncmp(ctt.ptr,'multipart/form-data;',20) == 0 then var p = lib.str.ffw(ctt.ptr + 20,ctt.ct-20) if lib.str.ncmp(p,'boundary=',9) ~= 0 then co:complain(400,'bad request','unrecognized content-type') goto fail end var boundary = pstring {ptr=p+9,ct=ctt.ct - ((p - ctt.ptr) + 9)} lib.dbg('got boundary ',{boundary.ptr,boundary.ct}) co.method = lib.http.method.post_file co.uploads:init(8) var bsr = (lib.str.acc{}):compose('\r\n--',boundary,'\r\n'):finalize() var upmap = lib.str.splitmap(co.body,bsr,8) -- first entry may not be preceded by header-break ................................................................................ lsent.ct = halt.ptr - lsent.ptr end lsr:free() end for i=0,upmap.ct do var hdrbrk = lib.str.find(upmap(i), lib.str.plit'\r\n\r\n') if hdrbrk:ref() then lib.dbg('got new entry') var hdrtxt = pstring {upmap(i).ptr,upmap(i).ct - hdrbrk.ct} var hdrs = lib.str.splitmap(hdrtxt, '\r\n',6) var ctt = pstring.null() var ctd = pstring.null() for j=0, hdrs.ct do var brk = lib.str.find(hdrs(j),lib.str.plit':') if brk:ref() then ................................................................................ ctd = val end end end if ctd:ref() then var ctdvals = lib.str.splitmap(ctd, ';', 4) defer ctdvals:free() if ctdvals(0):cmp(lib.str.plit'form-data') and ctdvals.ct > 1 then lib.dbg('found form data') var fld = pstring.null() var file = pstring.null() for j=1, ctdvals.ct do var v = ctdvals(j):ffw() var x = lib.str.find(v,lib.str.plit'=') if x:ref() then var key = pstring{v.ptr, v.ct - x.ct} var val = pstring{x.ptr + 1, x.ct - 1} ................................................................................ end end end return 0 end --9twh8y94i5c1qqr7hxu20fyd terra cfgcache.methods.load :: {&cfgcache} -> {} terra cfgcache:init(o: &srv) self.overlord = o self:load() end terra srv:setup(befile: rawstring) |
< < < < < |
526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 ... 559 560 561 562 563 564 565 566 567 568 569 570 571 572 ... 578 579 580 581 582 583 584 585 586 587 588 589 590 591 ... 772 773 774 775 776 777 778 779 780 781 782 783 784 785 |
end
-- check for a content-type header, and see if it's a multipart/
-- form-data encoded POST request so we can handle file uploads
co.uploads.sz = 0 co.uploads.run = 0
if co.method == [lib.http.method.post] then
var ctt = lib.http.findheader(msg, 'Content-Type')
if ctt ~= nil then
if lib.str.ncmp(ctt.ptr,'multipart/form-data;',20) == 0 then
var p = lib.str.ffw(ctt.ptr + 20,ctt.ct-20)
if lib.str.ncmp(p,'boundary=',9) ~= 0 then
co:complain(400,'bad request','unrecognized content-type')
goto fail
end
var boundary = pstring {ptr=p+9,ct=ctt.ct - ((p - ctt.ptr) + 9)}
co.method = lib.http.method.post_file
co.uploads:init(8)
var bsr = (lib.str.acc{}):compose('\r\n--',boundary,'\r\n'):finalize()
var upmap = lib.str.splitmap(co.body,bsr,8)
-- first entry may not be preceded by header-break
................................................................................
lsent.ct = halt.ptr - lsent.ptr
end
lsr:free() end
for i=0,upmap.ct do
var hdrbrk = lib.str.find(upmap(i), lib.str.plit'\r\n\r\n')
if hdrbrk:ref() then
var hdrtxt = pstring {upmap(i).ptr,upmap(i).ct - hdrbrk.ct}
var hdrs = lib.str.splitmap(hdrtxt, '\r\n',6)
var ctt = pstring.null()
var ctd = pstring.null()
for j=0, hdrs.ct do
var brk = lib.str.find(hdrs(j),lib.str.plit':')
if brk:ref() then
................................................................................
ctd = val
end
end
end
if ctd:ref() then
var ctdvals = lib.str.splitmap(ctd, ';', 4) defer ctdvals:free()
if ctdvals(0):cmp(lib.str.plit'form-data') and ctdvals.ct > 1 then
var fld = pstring.null()
var file = pstring.null()
for j=1, ctdvals.ct do var v = ctdvals(j):ffw()
var x = lib.str.find(v,lib.str.plit'=')
if x:ref() then
var key = pstring{v.ptr, v.ct - x.ct}
var val = pstring{x.ptr + 1, x.ct - 1}
................................................................................
end
end
end
return 0
end
terra cfgcache.methods.load :: {&cfgcache} -> {}
terra cfgcache:init(o: &srv)
self.overlord = o
self:load()
end
terra srv:setup(befile: rawstring)
|
Modified static/live.js from [45ade869ea] to [76c21b64a1].
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
if (ert != null) { lede = post; post = ert; }
let purl = posturl(post);
let url = null;
if (lede == null) {url = purl;} else {
url = lede.querySelector('a[href].del').
attributes.getNamedItem('href').value;
}
console.log('post',post,'lede',lede,url);
if (last == null) { newmap.first = url; } else {
newmap.map.get(last).next = url;
}
newmap.map.set(url, {me: post, go: purl, prev: last, next: null})
last = url;
if (window._liveTweetMap &&
|
< |
117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
if (ert != null) { lede = post; post = ert; }
let purl = posturl(post);
let url = null;
if (lede == null) {url = purl;} else {
url = lede.querySelector('a[href].del').
attributes.getNamedItem('href').value;
}
if (last == null) { newmap.first = url; } else {
newmap.map.get(last).next = url;
}
newmap.map.set(url, {me: post, go: purl, prev: last, next: null})
last = url;
if (window._liveTweetMap &&
|
Modified static/style.scss from [7f55f7d5d1] to [f5bd822625].
1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 |
background: tone(-55%,-0.5);
border: 1px solid tone(-60%);
padding: 0.2in;
display: flex;
flex-wrap: wrap;
}
.gallery {
grid-row: 1/2; grid-column: 2/3;
margin-left: 0.1in;
flex-flow: row;
> a[href].thumb {
display: block;
width: 1.5in;
padding: 0.1in;
height: max-content;
> img {
width: 1.5in; height: 1.5in;
}
> .caption {
text-align: center;
font-size: 80%;
}
}
}
.dir {
grid-row: 2/3; grid-column: 1/3;
margin-top: 0.1in;
flex-flow: column;
flex-grow: 1;
> a[href].file {
padding: 0.1in 0.15in;
text-decoration: none;
height: max-content;
background-image: url(/s/file.webp); //TODO different icons for different mime types
|
| | > > > > > > > > > | | |
1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 |
background: tone(-55%,-0.5);
border: 1px solid tone(-60%);
padding: 0.2in;
display: flex;
flex-wrap: wrap;
}
.gallery {
grid-row: 2/3; grid-column: 1/3;
margin-top: 0.1in;
flex-flow: row;
padding: 0 0.1in;
> a[href].thumb {
background: linear-gradient(to top, tone(10%,-0.8), tone(10%,-0.94) 30%, transparent);
border-radius: 4px;
border-bottom: 1px solid tone(15%, -0.5);
display: block;
width: 1.5in;
padding: 0.1in;
height: max-content;
margin: 0.1in;
> img {
width: 1.5in; height: 1.5in;
object-fit: contain;
object-position: center;
outline: none;
}
> .caption {
text-align: center;
font-size: 80%;
text-shadow: 1px 1px 0 black;
}
}
}
.dir {
grid-row: 1/2; grid-column: 2/3;
margin-left: 0.1in;
flex-flow: column;
flex-grow: 1;
> a[href].file {
padding: 0.1in 0.15in;
text-decoration: none;
height: max-content;
background-image: url(/s/file.webp); //TODO different icons for different mime types
|
Modified view/media-gallery.tpl from [d752c55f41] to [18862037ee].
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<menu>@menu
<a href="/media">new uploads</a>
<a href="/media/unfiled">unfiled</a>
<hr>
@folders
<a href="/media/all">all uploads</a>
<a href="/media/kind/img">all images</a>
<a href="/media/kind/vid">all videos</a>
<a href="/media/kind/txt">all text files</a>
<a href="/media/king/misc">all others</a>
</menu>
<div class="dir">
@directory
</div>
<div class="gallery">
@images
</div>
|
| | | | | | | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<menu>@menu <a href="@pfx/media">new uploads</a> <a href="@pfx/media/unfiled">unfiled</a> <hr> @folders <a href="@pfx/media/all">all uploads</a> <a href="@pfx/media/kind/img">all images</a> <a href="@pfx/media/kind/vid">all videos</a> <a href="@pfx/media/kind/txt">all text files</a> <a href="@pfx/media/kind/misc">all others</a> </menu> <div class="dir"> @directory </div> <div class="gallery"> @images </div> |