Index: math.t ================================================================== --- math.t +++ math.t @@ -1,8 +1,11 @@ -- vim: ft=terra local m = { - shorthand = {maxlen = 14} + shorthand = {maxlen = 14}; + ll = { + ctpop_u8 = terralib.intrinsic('llvm.ctpop.i8', uint8 -> uint8); + }; } local pstring = lib.mem.ptr(int8) -- swap in place -- faster on little endian @@ -54,10 +57,16 @@ ch = 38 + (ch - 0x61) else return 0, false end return ch, true end + +terra m.pow(n: intptr, fac: intptr): intptr + var o = n + for i=0,fac do n = n * o end + return n +end terra m.shorthand.gen(val: uint64, dest: rawstring): ptrdiff var lst = "0123456789-ABCDEFGHIJKLMNOPQRSTUVWXYZ:abcdefghijklmnopqrstuvwxyz" var buf: int8[m.shorthand.maxlen] var ptr = [&int8](buf) Index: mgtool.t ================================================================== --- mgtool.t +++ mgtool.t @@ -117,11 +117,11 @@ else tmppw[i] = tmppw[i] + 0x30 end end lib.dbg('assigning temporary password') dlg:auth_attach_pw(uid, reset, pstr { ptr = [rawstring](tmppw), ct = 32 }, - lib.str.plit 'temporary password'); + 'temporary password'); end local terra ipc_report(acks: lib.mem.ptr(lib.ipc.ack), rep: rawstring) var decbuf: int8[21] for i=0,acks.ct do @@ -381,13 +381,13 @@ return 1 end if cfmode.arglist.ct == 1 then var am = dlg:conf_get('credential-store') var mg: bool - if (not am) or am:cmp(lib.str.plit 'managed') then + if (not am) or am:cmp('managed') then mg = true - elseif am:cmp(lib.str.plit 'unmanaged') then + elseif am:cmp('unmanaged') then lib.warn('credential store is unmanaged; you will need to create credentials for the new root user manually!') mg = false else lib.bail('unknown credential store mode "',{am.ptr,am.ct},'"; should be either "managed" or "unmanaged"') end var kbuf: uint8[lib.crypt.const.maxdersz] var root = lib.store.actor.mk(&kbuf[0]) Index: parsav.t ================================================================== --- parsav.t +++ parsav.t @@ -274,10 +274,20 @@ if o[val] == nil then error('value ' .. val .. ' not in set') end return `bit { _v=[o[val] - 1], _set = &(obj) } end) terra set:sz() var ct: intptr = 0 + --for i = 0, [math.floor(#tbl/8)] do + -- ct = ct + lib.math.ll.ctpop_u8(self._store[i]) + --end + --[(function() + -- if #tbl % 8 ~= 0 then + -- local last = #tbl-1 + -- local msk = (2 ^ (#tbl % 8)) - 1 + -- return quote ct = ct + lib.math.ll.ctpop_u8(self._store[last] and [uint8](msk)) end + -- else return {} end + --end)()] for i = 0, [#tbl] do if (self._store[i/8] and (1 << i % 8)) ~= 0 then ct = ct + 1 end end return ct end @@ -453,10 +463,11 @@ 'render:docpage'; 'render:conf:profile'; 'render:conf:sec'; 'render:conf:users'; + 'render:conf:avi'; 'render:conf'; 'route'; } do Index: render/compose.t ================================================================== --- render/compose.t +++ render/compose.t @@ -17,15 +17,15 @@ if acc ~= nil then form:append(acc) return end var cotxt = form:poolstr(&co.srv.pool) -- defer cotxt:free() var doc = [lib.srv.convo.page] { - title = lib.str.plit 'compose'; + title = 'compose'; body = cotxt; - class = lib.str.plit 'compose'; + class = 'compose'; cache = true; } co:stdpage(doc) end return render_compose Index: render/conf.t ================================================================== --- render/conf.t +++ render/conf.t @@ -2,11 +2,11 @@ local pstr = lib.mem.ptr(int8) local pref = lib.mem.ref(int8) local mappings = { {url = 'profile', title = 'account profile', render = 'profile'}; - {url = 'avi', title = 'avatar', render = 'avatar'}; + {url = 'avi', title = 'avatar', render = 'avi'}; {url = 'ui', title = 'user interface', render = 'ui'}; {url = 'sec', title = 'security', render = 'sec_overlay'}; {url = 'rel', title = 'relationships', render = 'rel'}; {url = 'qnt', title = 'quarantine', render = 'quarantine'}; {url = 'acl', title = 'access control shortcuts', render = 'acl'}; @@ -85,13 +85,13 @@ else pgt = pg:poolstr(&co.srv.pool) end --defer pgt:free() co:stdpage([lib.srv.convo.page] { title = 'configure'; body = pgt; - class = lib.str.plit 'conf'; + class = 'conf'; cache = false; }) --if panel.ct ~= 0 then panel:free() end end return render_conf ADDED render/conf/avi.t Index: render/conf/avi.t ================================================================== --- render/conf/avi.t +++ render/conf/avi.t @@ -0,0 +1,15 @@ +-- vim: ft=terra +local pstr = lib.mem.ptr(int8) +local pref = lib.mem.ref(int8) + +local terra +render_conf_avi(co: &lib.srv.convo, path: lib.mem.ptr(pref)): pstr + var a = co:stra(128) + a:lpush '

this is your current avatar. if you want to change it, you can reset it to the default, or pick a new image in your media library to represent yourself with.

' + if co.who.avatarid ~= 0 then + a:lpush 'open image' + end + return a:finalize() +end + +return render_conf_avi Index: render/conf/sec.t ================================================================== --- render/conf/sec.t +++ render/conf/sec.t @@ -37,11 +37,11 @@ credmgr.credlist = cl:finalize() end credmgr:append(&a) --if credmgr.credlist.ct > 0 then credmgr.credlist:free() end else - if new:cmp(lib.str.plit'pw') then + if new:cmp('pw') then var d: data.view.conf_sec_pwnew var time = lib.osclock.time(nil) var timestr: int8[26] lib.osclock.ctime_r(&time, ×tr[0]) var cmt = co:stra(48) cmt:lpush('enrolled over http on '):push(×tr[0],0) @@ -48,16 +48,16 @@ d.comment = cmt:finalize() var st = d:poolstr(&co.srv.pool) --d.comment:free() return st - elseif new:cmp(lib.str.plit'challenge') then + elseif new:cmp('challenge') then -- we're going to break the rules a bit and do database munging from -- the rendering code, because doing otherwise in this case would be -- genuinely nightmarish - elseif new:cmp(lib.str.plit'otp') then - elseif new:cmp(lib.str.plit'api') then + elseif new:cmp('otp') then + elseif new:cmp('api') then else return pstr.null() end end else body:append(&a) end return a:finalize() Index: render/conf/users.t ================================================================== --- render/conf/users.t +++ render/conf/users.t @@ -1,9 +1,8 @@ -- vim: ft=terra local pstr = lib.mem.ptr(int8) local pref = lib.mem.ref(int8) -local P = lib.str.plit local terra cs(s: rawstring) return pstr { ptr = s, ct = lib.str.sz(s) } end @@ -16,76 +15,83 @@ case [uint16](4) then acc:lpush('🗡') end case [uint16](5) then acc:lpush('🗝') end else acc:lpush('🕴') end end + +local splitwords = macro(function(str) + local words = {} + for w in str:asvalue():gmatch('(%g+)') do words[#words + 1] = w end + return `arrayof(pstr, [words]) +end) local rnd = lib.crypt.random local terra suggest_handle(a: &lib.str.acc) var start = a.sz var puncts = array('.','_','-') var xXx = rnd(uint8, 0, 9) == 0 var leet = rnd(uint8, 0, 8) == 0 - var caps = rnd(uint8, 0, 5) + var caps = rnd(uint8, 0, 10) var punct: rawstring = nil var useadj = rnd(uint8, 0, 4) == 0 if rnd(uint8, 0, 4) == 0 then punct = puncts[rnd(intptr,0,[puncts.type.N])] end - var nouns = array( - 'thunder','bride','blaze','doom','squad','gun','lord','blaster', - 'fuck','hell','hound','piss','shit','killa','terror', 'horror', - 'fear', 'slaughter','murder','general','commander', 'commissar', - 'terrorist','infinity','slut','cunt','whore','bitch', 'bastard', - 'cock','prince','princess','pimp','gay','cop','slayer', 'vampire', - 'vampyre','blood','pain','brute','wolf','sword','star','sun','moon', - 'killer','murderer','thief','arson','fire','ice','frost','hack', - 'hacker','god','master','mistress','slave','rage','freeze','flayer', - 'pirate','ninja','shadow','fog','mist','misery','glory','bear', - 'king','queen','empress','emperor','majesty','space','martian', - 'winter','fall','monk','katana','420','warrior','banana','demon', - 'devil','ghost','wraith','cuck','legend','hero','heroine','goblin', - 'gremlin','troll','dragon','evil','overlord','radiance' - ) - var adjs = array( - 'dark','super','supreme','ultra','ultimate','total','infinite', - 'omnipotent','crazy','final','deathless','immortal', 'elite', - 'leet','1337','bloody','fearless','headless','screaming','insane', - 'brutal','legendary','space','frozen','flaming','burning', - 'mighty','flayed','hidden','secret','lost','mystery','glorious', - 'nude','naked','bare','first','radiant','martian','fallen', - 'wandering','dank','demonic','satanic','invisible','based','woke', - 'deadly','lethal','heroic','evil','majestic','luminous' - ) + var nouns = splitwords [[ + thunder bride blaze doom squad gun lord blaster + fuck hell hound piss shit killa terror horror + fear slaughter murder general commander commissar + terrorist infinity slut cunt whore bitch bastard + cock prince princess pimp gay cop slayer vampire + vampyre blood pain brute wolf sword star sun moon + killer murderer thief arson fire ice frost hack + hacker god master mistress slave rage freeze flayer + pirate ninja shadow fog mist misery glory bear + king queen empress emperor majesty space martian + winter fall monk katana 420 warrior banana demon + devil ghost wraith cuck legend hero heroine goblin + gremlin troll dragon evil overlord radiance slop + operator rage hog bog roach wizard + ]] + var adjs = splitwords [[ + dark super supreme ultra ultimate total infinite + omnipotent crazy final deathless immortal elite + leet 1337 bloody fearless headless screaming insane + brutal legendary space frozen flaming burning + mighty flayed hidden secret lost mystery glorious + nude naked bare first radiant martian fallen bog + wandering dank demonic satanic invisible based woke + deadly lethal heroic evil majestic luminous ethereal + ]] if xXx then a:lpush('xXx_') end if useadj then var len = rnd(uint8,1,3) for i = 0, len do var sz = a.sz - a:push(adjs[rnd(intptr,0,[adjs.type.N])], 0) + a:ppush(adjs[rnd(intptr,0,[adjs.type.N])]) if punct ~= nil then a:push(punct, 1) end if caps == 1 then a.buf[sz] = lib.str.cupcase(a.buf[sz]) end end end var nounct = rnd(uint8,1,3) for i = 0, nounct do var sz = a.sz - a:push(nouns[rnd(intptr,0,[nouns.type.N])], 0) + a:ppush(nouns[rnd(intptr,0,[nouns.type.N])]) if punct ~= nil and i+1 ~= nounct then a:push(punct, 1) end if caps == 1 then a.buf[sz] = lib.str.cupcase(a.buf[sz]) end end - if leet or caps == 2 then for i=start, a.sz do - if caps == 2 and rnd(uint8,0,5)==0 then + if leet or caps == 9 then for i=start, a.sz do + if caps == 9 and rnd(uint8,0,5)==0 then a.buf[i] = lib.str.cupcase(a.buf[i]) end if leet then switch lib.str.cdowncase(a.buf[i]) do case [uint8]([string.byte('e')]) then a.buf[i] = @'3' end @@ -99,20 +105,55 @@ end end end if (nounct == 1 and not useadj) or rnd(uint8, 0, 5) == 0 then if punct ~= nil then a:push(punct, 1) end - a:ipush(rnd(uint16,0,65535)) + a:ipush(rnd(uint32,0,lib.math.pow(10,rnd(uint8,1,4)))) end if xXx then a:lpush('_xXx') end end local terra suggest_domain(a: &lib.str.acc) - var tlds = array('tld','club','town','space','xxx') + var words = splitwords [[ + flop slop hop wiggle wriggle bug snoot boop jorts horse rad + witch witches cum code spank grump grumps slap spoop spoopy + spook wobble flip jock nerd dope dork slab drug funk gay + hex node snack weed pot slug worm fur fuzz fuzzy game gamer + rock smack drank wack wild sexy hot sin cock fuck piss man + wank fae weird woke slurp spine skull fail elf elves mom + dad dog cat kitten snake troll top bottom chungus dong wang + 420 hog lover lovers best worst love hate big bigger tiny + little teeny spunky jazz wrack rump kink kinky crack meth + whore cam live over under turbo pizza rat rats crotch crank + chunky funky butt grab grabber grabbers thief steal slave + slaves hug hugs hag hags hogs wimp thieves wizard wizards + pussy pansy dark doom stank spunk dumb rage + ]] + var tlds = splitwords [[ + tld club town space xxx house land ranch horse com io online + shop site vip ltd win men lgbt cat adult army analytics art + associates bar bible biz black blog broker cam camp careers + catering church city coop dad date dating direct diy dog + duck dot enterprises esq estate expert express fail farm foo + forsale fun fund forum foundation gay global golf gop guru + group hangout hot industries international info investments + jobs land law life limited live lol mom network now party + porn productions pub rehab rocks school sex sexy singles + social software solutions space spot store sucks supplies + systems university vacations ventures wang website work + wow wtf world xyz soy live gym park + ]] + var sub = rnd(uint8,0,10) == 0 + if sub then a:ppush(words[rnd(intptr,0,[words.type.N])]):lpush('.') end + a:ppush(words[rnd(intptr,0,[words.type.N])]) + if rnd(uint8,0,3) == 0 or not sub then + a:ppush(words[rnd(intptr,0,[words.type.N])]) + end + a:lpush('.'):ppush(tlds[rnd(intptr,0,[tlds.type.N])]) end local push_num_field = macro(function(acc,name,lbl,min,max,value,disable) name = name:asvalue() lbl = lbl:asvalue() @@ -292,11 +333,11 @@ --if ctlbox.btns.ct > 0 then ctlbox.btns:free() end return pg:finalize() end else - var modes = array(P'local', P'remote', P'staff', P'titled', P'peons', P'all') + var modes = arrayof(pstr,'local', 'remote', 'staff', 'titled', 'peons', 'all') var idbuf: int8[lib.math.shorthand.maxlen] var ulst = co:stra(256) var mode: uint8 = mode_local var modestr = co:pgetv('show') ulst:lpush('
showing ') @@ -347,11 +388,13 @@ if co.who.rights.powers.invite() or co.who.rights.invites > 0 then ulst:lpush('
create new user
') end - ulst:lpush('
instantiate remote actor
') + ulst:lpush('
instantiate remote actor
') return ulst:finalize() end do return pstr.null() end ::e404:: co:complain(404, 'not found', 'there is no user or resource by that identifier on this server') goto quit Index: render/docpage.t ================================================================== --- render/docpage.t +++ render/docpage.t @@ -1,11 +1,9 @@ -- vim: ft=terra local page = lib.srv.convo.page local pstr = lib.mem.ptr(int8) local pref = lib.mem.ref(int8) -local P = lib.str.plit -local R = lib.str.lit local topics = lib.util.keys(data.doc) local topicidxt = {} table.sort(topics) -- because deterministic builds are good local branches = {} @@ -38,18 +36,18 @@ for _,v in pairs(t.meta.priv) do setbits = quote [setbits]; (restrict.[v] << true) end end end allpages[i] = quote var [restrict]; [setbits] in pgpair { - name = R(v); + name = [v]; parent = par; priv = restrict; - title = R(t.meta.title); + title = [t.meta.title]; content = page { title = ['documentation :: ' .. t.meta.title]; body = [ t.text ]; - class = P'doc article'; + class = 'doc article'; cache = true; }; } end end @@ -109,12 +107,12 @@ list:lpush('') co:stdpage(page { title = 'documentation'; body = list:finalize(); - class = P'doc listing'; + class = 'doc listing'; cache = false; }) else showpage(co, pg) end end return render_docpage Index: render/login.t ================================================================== --- render/login.t +++ render/login.t @@ -1,22 +1,21 @@ -- vim: ft=terra local pstr = lib.mem.ptr(int8) -local P = lib.str.plit local terra login_form(co: &lib.srv.convo, user: &lib.store.actor, creds: &lib.store.credset, msg: pstr) var doc = [lib.srv.convo.page] { - title = lib.str.plit 'instance logon'; - class = lib.str.plit 'login'; + title = 'instance logon'; + class = 'login'; cache = false; } if user == nil then var form = data.view.login_username { loginmsg = msg; } if form.loginmsg.ptr == nil then - form.loginmsg = lib.str.plit 'identify yourself for access to this instance.' + form.loginmsg = 'identify yourself for access to this instance.' end doc.body = form:tostr() elseif creds:sz() == 0 then co:complain(403,'access denied','your host is not eligible to authenticate as this user') return @@ -29,24 +28,24 @@ var ch = data.view.login_challenge { handle = user.handle; name = lib.coalesce(user.nym, user.handle); } if creds.pw() then - ch.challenge = P'enter the password associated with your account' - ch.label = P'password' - ch.method = P'pw' - ch.auto = P'current-password'; + ch.challenge = 'enter the password associated with your account' + ch.label = 'password' + ch.method = 'pw' + ch.auto = 'current-password'; elseif creds.otp() then - ch.challenge = P'enter a valid one-time password for your account' - ch.label = P'OTP code' - ch.method = P'otp' - ch.auto = P'one-time-code'; + ch.challenge = 'enter a valid one-time password for your account' + ch.label = 'OTP code' + ch.method = 'otp' + ch.auto = 'one-time-code'; elseif creds.challenge() then - ch.challenge = P'sign the challenge token: ...' - ch.label = P'digest' - ch.method = P'challenge' - ch.auto = P'one-time-code'; + ch.challenge = 'sign the challenge token: ...' + ch.label = 'digest' + ch.method = 'challenge' + ch.auto = 'one-time-code'; else co:complain(500,'login failure','unknown login method') return end Index: render/media-gallery.t ================================================================== --- render/media-gallery.t +++ render/media-gallery.t @@ -1,8 +1,7 @@ -- 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 @@ -23,11 +22,11 @@ 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 + if path.ct >= 3 and path(1):cmp('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 @@ -47,12 +46,12 @@ } if lib.str.ncmp(art(0).mime, 'image/', 6) == 0 then var view = data.view.media_image(viewerprops) var pg = view:poolstr(&co.srv.pool) co:stdpage([lib.srv.convo.page] { - title = lib.str.plit'media :: image'; - class = lib.str.plit'media viewer img'; + title = 'media :: image'; + class = '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) @@ -60,12 +59,12 @@ view.text = lib.smackdown.html(&co.srv.pool, pstr{[rawstring](text.ptr),text.ct}, false) text:free() var pg = view:poolstr(&co.srv.pool) --view.text:free() co:stdpage([lib.srv.convo.page] { - title = lib.str.plit'media :: text'; - class = lib.str.plit'media viewer text'; + title = 'media :: text'; + class = 'media viewer text'; cache = false, body = pg; }) --pg:free() elseif lib.str.ncmp(art(0).mime, 'text/', 5) == 0 or @@ -80,42 +79,42 @@ view.text = co:qstr('
',san,'
') --san:free() var pg = view:poolstr(&co.srv.pool) --view.text:free() co:stdpage([lib.srv.convo.page] { - title = lib.str.plit'media :: text'; - class = lib.str.plit'media viewer text'; + title = 'media :: text'; + class = '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 = co:qstr('/media/a/', path(2)) -- defer curl:free() - if act:cmp(lib.str.lit'avi') and lib.str.ncmp(art(0).mime, 'image/', 6) == 0 then + if act:cmp('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 + elseif act:cmp('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 + if path(1):cmp('unfiled') then mode=show_unfiled - elseif path(1):cmp(lib.str.lit'all') then + elseif path(1):cmp('all') then mode=show_all else goto e404 end - elseif path.ct == 3 and path(1):cmp(lib.str.lit'kind') then + elseif path.ct == 3 and path(1):cmp('kind') then end var folders = co.srv:artifact_folder_enum(uid) if mode == show_new then - folder = lib.str.plit'' + folder = '' elseif mode == show_all or mode == show_unfiled then folder = pstr.null() end var view = data.view.media_gallery { @@ -144,11 +143,11 @@ view.folders = fa:finalize() folders:free() end if owner then - view.menu = P'upload
' + view.menu = 'upload
' end var md = co.srv:artifact_enum_uid(uid, folder) var gallery: lib.str.acc gallery:pool(&co.srv.pool,256) var files: lib.str.acc files:pool(&co.srv.pool,256) @@ -175,12 +174,12 @@ if acc ~= nil then view:append(acc) else var pg = view:poolstr(&co.srv.pool) -- defer pg:free() co:stdpage([lib.srv.convo.page] { - title = P'media'; - class = P'media manager'; + title = 'media'; + class = 'media manager'; cache = false; body = pg; }) end Index: render/notices.t ================================================================== --- render/notices.t +++ render/notices.t @@ -1,8 +1,7 @@ -- vim: ft=terra local pstr = lib.mem.ptr(int8) -local P = lib.str.plit local terra cs(s: rawstring) return pstr { ptr = s, ct = lib.str.sz(s) } end local terra @@ -35,25 +34,25 @@ pflink = pstr{ptr = pflink.buf; ct = pflink.sz}; } var notweet, nopost = true, false switch notes(i).kind do case lib.store.noticetype.rt then - n.kind = P'rt' - n.act = P'retweeted your post' + n.kind = 'rt' + n.act = 'retweeted your post' end case lib.store.noticetype.like then - n.kind = P'like' - n.act = P'likes your post' + n.kind = 'like' + n.act = 'likes your post' end case lib.store.noticetype.reply then - n.kind = P'reply' - n.act = P'replied to your post' + n.kind = 'reply' + n.act = 'replied to your post' notweet = false end case lib.store.noticetype.follow then - n.kind = P'follow' - n.act = P'followed you!' + n.kind = 'follow' + n.act = 'followed you!' nopost = true end else goto skip end if not nopost then var what = co.srv:post_fetch(notes(i).what) defer what:free() @@ -73,12 +72,12 @@ body:reset() end --pflink:free() pg:lpush('
') co:livepage([lib.srv.convo.page] { - title = P'notices', class = P'notices'; + title = 'notices', class = 'notices'; body = pstr {ptr = pg.buf, ct = pg.sz}; cache = false; }, latest) end return render_notices Index: render/profile.t ================================================================== --- render/profile.t +++ render/profile.t @@ -34,19 +34,19 @@ var stats = co.srv:actor_stats(actor.id) var sn_posts = cs(lib.math.decstr_friendly(stats.posts, &strfbuf[ [strfbuf.type.N - 1] ])) var sn_follows = cs(lib.math.decstr_friendly(stats.follows, sn_posts.ptr - 1)) var sn_followers = cs(lib.math.decstr_friendly(stats.followers, sn_follows.ptr - 1)) var sn_mutuals = cs(lib.math.decstr_friendly(stats.mutuals, sn_followers.ptr - 1)) - var bio = lib.str.plit 'tall, dark, and mysterious' + var bio = pstr 'tall, dark, and mysterious' if actor.bio ~= nil then bio = lib.smackdown.html(&co.srv.pool,cs(actor.bio),false) end var fullname = lib.render.nym(actor,0,nil,false) defer fullname:free() var comments = co:stra(64) if co.srv.cfg.master == actor.id then - var foundertxt = lib.str.plit 'founder' + var foundertxt = pstr 'founder' if co.srv.cfg.ui_cue_founder:ref() then if co.srv.cfg.ui_cue_founder.ct == 0 -- empty string, suppress field then foundertxt = pstr.null() else foundertxt = co.srv.cfg.ui_cue_founder end @@ -55,11 +55,11 @@ if foundertxt:ref() then comments:lpush('
  • '):ppush(foundertxt):lpush('
  • ') end end if co.aid ~= 0 and actor.rights.rank ~= 0 then - var stafftxt = lib.str.plit 'site staff' + var stafftxt = pstr 'site staff' if co.srv.cfg.ui_cue_staff:ref() then if co.srv.cfg.ui_cue_staff.ct == 0 -- empty string, suppress field then stafftxt = pstr.null() else stafftxt = co.srv.cfg.ui_cue_staff end @@ -90,11 +90,11 @@ avatar = cs(actor.avatar); nposts = sn_posts, nfollows = sn_follows; nfollowers = sn_followers, nmutuals = sn_mutuals; tweetday = cs(timestr); - timephrase = lib.trn(actor.origin == 0, lib.str.plit'joined', lib.str.plit'known since'); + timephrase = lib.trn(actor.origin == 0, pstr 'joined', pstr 'known since'); remarks = ''; auxbtn = auxp; } Index: render/timeline.t ================================================================== --- render/timeline.t +++ render/timeline.t @@ -24,11 +24,11 @@ }) elseif mode == modes.fediglobal then elseif mode == modes.circle then end - var acc: lib.str.acc acc:pool(&co.srv.pool,1024) + var acc = co:stra(1024) acc:lpush('
    ') var newest: lib.store.timepoint = 0 for i = 0, posts.sz do lib.render.tweet(co, posts(i).ptr, &acc) var t = lib.math.biggest(lib.math.biggest(posts(i).ptr.posted, posts(i).ptr.discovered),posts(i).ptr.edited) @@ -37,14 +37,14 @@ end posts:free() acc:lpush('
    ') var doc = [lib.srv.convo.page] { - title = lib.str.plit'timeline'; + title = 'timeline'; body = acc:finalize(); - class = lib.str.plit'timeline'; + class = 'timeline'; cache = false; } co:livepage(doc,newest) --doc.body:free() end return render_timeline Index: render/tweet-page.t ================================================================== --- render/tweet-page.t +++ render/tweet-page.t @@ -62,14 +62,14 @@ lib.render.compose(co, nil, &pg) end var ppg = pg:finalize() --defer ppg:free() co:livepage([lib.srv.convo.page] { - title = lib.str.plit 'post'; cache = false; - class = lib.str.plit 'post'; body = ppg; + title = 'post'; cache = false; + class = 'post'; body = ppg; }, livetime) -- TODO display conversation -- perhaps display descendant nodes here, and have a link to the top of the whole tree? end return render_tweet_page Index: render/user-page.t ================================================================== --- render/user-page.t +++ render/user-page.t @@ -36,14 +36,14 @@ acc:lpush('
    ') var bdf = acc:finalize() co:livepage([lib.srv.convo.page] { title = tiptr; body = bdf; - class = lib.str.plit 'profile'; + class = 'profile'; cache = false; }, newest) tiptr:free() --bdf:free() end return render_userpage Index: route.t ================================================================== --- route.t +++ route.t @@ -453,10 +453,17 @@ msg = 'profile changes saved' --user_refresh = true -- not really necessary here, actually elseif path(1):cmp('sec') then credsec_for_uid(co, co.who.id) + elseif path(1):cmp('avi') then + var act = co:ppostv('act') + if act:ref() and act:cmp('clear') then + co.who.avatarid = 0 + co.who.source:actor_save(co.who) + msg = 'avatar reset to default' + else goto badop end elseif path(1):cmp('users') then if path.ct >= 3 then var userid, ok = lib.math.shorthand.parse(path(2).ptr, path(2).ct) if ok then var usr = co.srv:actor_fetch_uid(userid) Index: srv.t ================================================================== --- srv.t +++ srv.t @@ -239,18 +239,18 @@ terra convo:bytestream(mime: pstring, data: lib.mem.ptr(uint8)) -- 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') + if mime:cmp('text/html') or + mime:cmp('text/xml') or + mime:cmp('application/xhtml+xml') or + mime:cmp('application/vnd.wap.xhtml+xml') then -- danger will robinson - mime = lib.str.plit'text/plain' - elseif mime:cmp(lib.str.plit'application/x-shockwave-flash') then - mime = lib.str.plit'application/octet-stream' + mime = 'text/plain' + elseif mime:cmp('application/x-shockwave-flash') then + mime = 'application/octet-stream' end lib.net.mg_printf(self.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", mime.ct, mime.ptr, data.ct + 2) lib.net.mg_send(self.con, data.ptr, data.ct) lib.net.mg_send(self.con, '\r\n', 2) end @@ -295,11 +295,11 @@ var ti: lib.str.acc ti:compose('error :: ', title) var bo: lib.str.acc bo:compose('

    ',title,'

    ',msg,'

    ') var body = [convo.page] { title = ti:finalize(); body = bo:finalize(); - class = lib.str.plit 'error'; + class = 'error'; cache = false; } self:statpage(code, body) @@ -315,11 +315,11 @@ } var ti: lib.str.acc ti:pcompose(&self.srv.pool,'confirm :: ', title) var body = conf:poolstr(&self.srv.pool) -- defer body:free() var cf = [convo.page] { title = ti:finalize(); - class = lib.str.plit 'query'; + class = 'query'; body = body; cache = false; } self:stdpage(cf) --cf.title:free() end @@ -631,42 +631,42 @@ 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') + var hdrbrk = lib.str.find(upmap(i), '\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':') + var brk = lib.str.find(hdrs(j),':') if brk:ref() then var hdr = pstring{hdrs(j).ptr,hdrs(j).ct - brk.ct} var val = pstring{brk.ptr+1, brk.ct-1}:ffw() - if hdr:cmp(lib.str.plit'Content-Type') then + if hdr:cmp('Content-Type') then ctt = val - elseif hdr:cmp(lib.str.plit'Content-Disposition') then + elseif hdr:cmp('Content-Disposition') 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 + if ctdvals(0):cmp('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'=') + var x = lib.str.find(v,'=') if x:ref() then var key = pstring{v.ptr, v.ct - x.ct} var val = pstring{x.ptr + 1, x.ct - 1} var decval, ofs, sp = lib.str.toknext(val,@';',true) - if key:cmp(lib.str.plit'name') then + if key:cmp('name') then fld = decval - elseif key:cmp(lib.str.plit'filename') then + elseif key:cmp('filename') then file = decval else decval:free() end end end if fld:ref() then @@ -939,15 +939,15 @@ end terra cfgcache:cfbool(name: rawstring, default: bool) var str = self.overlord:conf_get(name) if str.ptr ~= nil then - if str:cmp(lib.str.plit 'true') or str:cmp(lib.str.plit 'on') or - str:cmp(lib.str.plit 'yes') or str:cmp(lib.str.plit '1') then + if str:cmp('true') or str:cmp('on') or + str:cmp('yes') or str:cmp('1') then default = true - elseif str:cmp(lib.str.plit 'false') or str:cmp(lib.str.plit 'off') or - str:cmp(lib.str.plit 'no') or str:cmp(lib.str.plit '0') then + elseif str:cmp('false') or str:cmp('off') or + str:cmp('no') or str:cmp('0') then default = false else lib.warn('invalid configuration setting ',name,'="',{str.ptr,str.ct},'", expected boolean; using default value instead') end str:free() Index: static/style.scss ================================================================== --- static/style.scss +++ static/style.scss @@ -289,11 +289,11 @@ grid-template-columns: 1.1in 1fr; grid-template-rows: max-content 1fr; > .avatar { display: block; width: 1in; height: 1in; - object-fit: contain; + object-fit: cover; grid-column: 1 / 2; grid-row: 1 / 3; border: 1px solid black; } > .id { @@ -528,10 +528,11 @@ grid-column: 1/2; grid-row: 1/2; background: linear-gradient(to bottom, tone(-53%), tone(-57%)); img { display: block; width: 1in; height: 1in; margin:0; border-right: 1px solid tone(-65%); + object-fit: cover; } } >a[href].username { display: block; grid-column: 1/3; @@ -667,11 +668,21 @@ border: 1px solid tone(-55%); border-left: none; text-shadow: 1px 1px 0 black; } } - + img.avatar.big { + display:block; + width: 70%; + height: auto; + margin: 0.2in auto; + border: 1px solid tone(-45%); + border-top-color: tone(-40%); + border-bottom: 2px solid tone(-60%); + object-fit: cover; + border-radius: 3px; + } } hr { border: none; border-top: 1px solid tone(-30%); Index: store.t ================================================================== --- store.t +++ store.t @@ -61,11 +61,11 @@ local struct pt { name:lib.mem.ptr(int8), val:set } for k,v in pairs(set.members) do map[#map + 1] = quote var ps: set ps:clear() (ps.[v] << true) - in pt {name = lib.str.plit(v), val = ps} end + in pt {name = [v], val = ps} end end return map end m.powmap = setmap(m.powerset) m.privmap = setmap(m.privset) Index: str.t ================================================================== --- str.t +++ str.t @@ -38,11 +38,10 @@ local byteptr = (lib.mem.ptr(uint8)) local function install_funcs(ty) ty.metamethods.__cast = function(from,to,e) local v = e:asvalue() if type(v) == 'string' then - print('hard-coding pstr',v,#v) return `ty {ptr = v, ct = [#v]} elseif from == &int8 then return `ty {ptr = e, ct = m.sz(e)} elseif to == &int8 then return e.ptr