parsav  Diff

Differences From Artifact [325df84c8e]:

To Artifact [db07af2616]:


    93     93   	if not go or go(0) ~= @'/' then
    94     94   		lib.render.user_page(co, actor, &rel)
    95     95   	else
    96     96   		co:reroute(go.ptr)
    97     97   	end
    98     98   end
    99     99   
   100         -terra http.actor_profile_xid(co: &lib.srv.convo, uri: lib.mem.ptr(int8), meth: method.t)
          100  +terra http.actor_dispatch_mime(co: &lib.srv.convo, actor: &lib.store.actor)
          101  +	if co:matchmime(lib.http.mime.html) then
          102  +		http.actor_profile(co,actor,co.method)
          103  +	elseif co:matchmime(lib.http.mime.json) then
          104  +		lib.api.lp.actor(co, actor)
          105  +	else co:fail(406) end
          106  +end
          107  +
          108  +terra http.actor_profile_xid(co: &lib.srv.convo, uri: lib.mem.ptr(int8))
   101    109   	var handle = [lib.mem.ptr(int8)] { ptr = &uri.ptr[2], ct = 0 }
   102    110   	for i=2,uri.ct do
   103    111   		if uri.ptr[i] == @'/' or uri.ptr[i] == 0 then handle.ct = i - 2 break end
   104    112   	end
   105    113   	if handle.ct == 0 then
   106    114   		handle.ct = uri.ct - 2
   107    115   		uri:advance(uri.ct)
................................................................................
   114    122   	var actor = co.srv:actor_fetch_xid(handle)
   115    123   	if actor.ptr == nil then
   116    124   		co:complain(404,'no such user','no such user known to this server')
   117    125   		return
   118    126   	end
   119    127   	defer actor:free()
   120    128   
   121         -	http.actor_profile(co,actor.ptr,meth)
          129  +	http.actor_dispatch_mime(co, actor.ptr)
   122    130   end
   123    131   
   124    132   terra http.actor_profile_uid (
   125    133   	co: &lib.srv.convo,
   126         -	path: lib.mem.ptr(lib.mem.ref(int8)),
   127         -	meth: method.t
          134  +	path: lib.mem.ptr(lib.mem.ref(int8))
   128    135   )
   129    136   	if path.ct < 2 then
   130    137   		co:complain(404,'bad url','invalid user url')
   131    138   		return
   132    139   	end
   133    140   
   134    141   	var uid, ok = lib.math.shorthand.parse(path.ptr[1].ptr, path.ptr[1].ct)
................................................................................
   140    147   	var actor = co.srv:actor_fetch_uid(uid)
   141    148   	if actor.ptr == nil then
   142    149   		co:complain(404, 'no such user', 'no user by that ID is known to this instance')
   143    150   		return
   144    151   	end
   145    152   	defer actor:free()
   146    153   
   147         -	http.actor_profile(co,actor.ptr,meth)
          154  +	http.actor_dispatch_mime(co, actor.ptr)
   148    155   end
   149    156   
   150    157   terra http.login_form(co: &lib.srv.convo, meth: method.t)
   151    158   	if meth_get(meth) then
   152    159   		-- request a username
   153    160   		lib.render.login(co, nil, nil, pstring.null())
   154    161   	elseif meth == method.post then
................................................................................
   225    232   				lib.render.login(co, nil, nil,  'authentication failure')
   226    233   			else
   227    234   				co:installkey('/',aid)
   228    235   			end
   229    236   		end
   230    237   		if act.ptr ~= nil and fakeact == false then act:free() end
   231    238   	else
   232         -		::wrongmeth:: co:complain(405, 'method not allowed', 'that method is not meaningful for this endpoint') do return end
          239  +		::wrongmeth:: co:fail(405) do return end
   233    240   	end
   234    241   	return
   235    242   end
   236    243   
   237    244   terra http.post_compose(co: &lib.srv.convo, meth: method.t)
   238    245   	if not co:assertpow('post') then return end
   239    246   	--if co.who.rights.powers.post() == false then
................................................................................
   242    249   	if meth_get(meth) then
   243    250   		lib.render.compose(co, nil, nil)
   244    251   	elseif meth == method.post then
   245    252   		var text, textlen = co:postv("post")
   246    253   		var acl, acllen = co:postv("acl")
   247    254   		var subj, subjlen = co:postv("subject")
   248    255   		if text == nil or acl == nil then
   249         -			co:complain(405, 'invalid post', 'every post must have at least body text and an ACL')
          256  +			co:complain(400, 'invalid post', 'every post must have at least body text and an ACL')
   250    257   			return
   251    258   		end
   252    259   		if subj == nil then subj = '' end
   253    260   
   254    261   		var p = lib.store.post {
   255    262   			author = co.who.id, acl = acl;
   256    263   			body = text, subject = subj;
................................................................................
   404    411   	end
   405    412   
   406    413   	if not post then goto badurl end
   407    414   
   408    415   	lib.render.tweet_page(co, path, post.ptr)
   409    416   	do return end
   410    417   
   411         -	::badurl:: do co:complain(404, 'invalid URL', 'this URL does not reference extant content or functionality') return end
   412         -	::badop :: do co:complain(405, 'invalid operation', 'the operation you have attempted on this post is not meaningful') return end
   413         -	::noauth:: do co:complain(401, 'unauthorized', 'you have not supplied the necessary credentials to perform this operation') return end
          418  +	::noauth:: do co:fail(401) return end
          419  +	::badurl:: do co:fail(404) return end
          420  +	::badop :: do co:fail(405) return end
   414    421   end
   415    422   
   416    423   local terra 
   417    424   credsec_for_uid(co: &lib.srv.convo, uid: uint64)
   418    425   	var act = co:ppostv('act')
   419    426   	if not act then return true end
   420    427   	lib.dbg('handling credential action')
................................................................................
   921    928   	do defer data:free() defer mime:free()
   922    929   		co:bytestream(mime,data)
   923    930   	return end
   924    931   
   925    932   	::e404:: do co:complain(404, 'artifact not found', 'no such artifact has been uploaded to this instance') return end
   926    933   end
   927    934   
   928         -local json = {}
   929         -
   930         -do wftpl = lib.tpl.mk [[{
   931         -		"subject": @$subj,
   932         -		"links": [
   933         -			{ "rel": "self", "type": "application/ld+json", "href": @$href }
   934         -		]
   935         -	}]]
   936         -	terra json.webfinger(co: &lib.srv.convo)
   937         -		var res = co:pgetv('resource')
   938         -		if (not res) or not res:startswith 'acct:' then goto err end
   939         -		
   940         -		-- technically we should look this user up in the database to make sure
   941         -		-- they actually exist, buuut that's costly and i doubt that's actually
   942         -		-- necessary for webfinger to do its job. so we cheat and just do string
   943         -		-- munging so lookups are as cheap as possible. TODO make sure this works
   944         -		-- in practice and doesn't cause any weird security problems
   945         -		var acct = res + 5
   946         -		var svp = lib.str.find(acct, '@')
   947         -		if svp:ref() then
   948         -			acct.ct = (svp.ptr - acct.ptr)
   949         -			svp:advance(1)
   950         -			if not svp:cmp(co.srv.cfg.domain) then goto err end
   951         -		end
   952         -		var tp = wftpl {
   953         -			subj = res;
   954         -			href = co:qstr('https://', co.srv.cfg.domain, '/@', acct);
   955         -		}
   956         -		co:json(tp:poolstr(&co.srv.pool))
   957         -
   958         -		do return end -- error conditions
   959         -		::err:: do co:json('{}') return end
   960         -	end
   961         -end
   962    935   
   963    936   -- entry points
   964         -terra r.dispatch_http(co: &lib.srv.convo, uri: lib.mem.ptr(int8), meth: method.t)
          937  +terra r.dispatch_http(co: &lib.srv.convo, uri: lib.mem.ptr(int8))
   965    938   	lib.dbg('handling URI of form ', {uri.ptr,uri.ct})
   966    939   	co.navbar = lib.render.nav(co)
   967    940   	-- some routes are non-hierarchical, and can be resolved with a simple strcmp
   968    941   	-- we run through those first before giving up and parsing the URI
          942  +	var meth = co.method -- TODO unfuck this legacy bat shit
   969    943   	if uri.ptr == nil or uri.ptr[0] ~= @'/' then
   970    944   		co:complain(404, 'what the hell', 'how did you do that')
   971    945   	elseif uri.ct == 1 then -- root
   972    946   		if (co.srv.cfg.pol_sec == lib.srv.secmode.private or
   973    947   		   co.srv.cfg.pol_sec == lib.srv.secmode.lockdown) and co.aid == 0 then
   974    948   		   http.login_form(co, meth)
   975    949   		else http.timeline(co, hpath {ptr=nil,ct=0}) end
   976    950   	elseif uri.ptr[1] == @'@' then
   977         -		http.actor_profile_xid(co, uri, meth)
          951  +		http.actor_profile_xid(co, uri)
   978    952   	elseif uri.ptr[1] == @'s' and uri.ptr[2] == @'/' and uri.ct > 3 then
   979    953   		if not meth_get(meth) then goto wrongmeth end
   980    954   		if not http.static_content(co, uri.ptr + 3, uri.ct - 3) then goto notfound end
   981    955   	elseif lib.str.ncmp('/avi/', uri.ptr, 5) == 0 then
   982    956   		http.local_avatar(co, [lib.mem.ptr(int8)] {ptr = uri.ptr + 5, ct = uri.ct - 5})
   983    957   	elseif lib.str.ncmp('/file/', uri.ptr, 6) == 0 then
   984    958   		http.file_serve_raw(co, [lib.mem.ptr(int8)] {ptr = uri.ptr + 6, ct = uri.ct - 6})
................................................................................
   997    971   		if co.aid == 0
   998    972   			then goto notfound
   999    973   			else co:reroute_cookie('/','auth=; Path=/')
  1000    974   		end
  1001    975   	else -- hierarchical routes
  1002    976   		var path = lib.http.hier(&co.srv.pool, uri) --defer path:free()
  1003    977   		if path.ct > 1 and path(0):cmp('user') then
  1004         -			http.actor_profile_uid(co, path, meth)
          978  +			http.actor_profile_uid(co, path)
  1005    979   		elseif path.ct > 1 and path(0):cmp('post') then
  1006    980   			http.tweet_page(co, path, meth)
  1007    981   		elseif path(0):cmp('tl') then
  1008    982   			http.timeline(co, path)
  1009    983   		elseif path(0):cmp('.well-known') then
  1010    984   			if path(1):cmp('webfinger') then
  1011         -				json.webfinger(co)
          985  +				if not co:matchmime(lib.http.mime.json) then goto nacc end
          986  +				lib.api.webfinger(co)
  1012    987   			end
          988  +		elseif path(0):cmp('api') then
          989  +			if path(1):cmp('parsav') then -- native API
          990  +			elseif path(1):cmp('v1') then -- mastodon client api :/
          991  +			elseif path(1):cmp('lp') then -- litepub endpoints
          992  +				if path(2):cmp('outbox') then
          993  +					lib.api.lp.outbox(co,uri,path + 3)
          994  +				elseif path(2):cmp('inbox') then
          995  +				end
          996  +			else goto notfound end
  1013    997   		elseif path(0):cmp('media') then
  1014    998   			if co.aid == 0 then goto unauth end
  1015    999   			http.media_manager(co, path, meth, co.who.id)
  1016   1000   		elseif path(0):cmp('doc') then
  1017   1001   			if not meth_get(meth) then goto wrongmeth end
  1018   1002   			http.documentation(co, path)
  1019   1003   		elseif path(0):cmp('conf') then
  1020   1004   			if co.aid == 0 then goto unauth end
  1021   1005   			http.configure(co,path,meth)
  1022   1006   		else goto notfound end
  1023   1007   	end
  1024   1008   	do return end
  1025   1009   
  1026         -	::wrongmeth:: co:complain(405, 'method not allowed', 'that method is not meaningful for this endpoint') do return end
  1027         -	::notfound:: co:complain(404, 'not found', 'no such resource available') do return end
  1028         -	::unauth:: co:complain(401, 'unauthorized', 'this content is not available at your clearance level') do return end
         1010  +	::wrongmeth:: co:fail(405) do return end
         1011  +	::nacc     :: co:fail(406) do return end
         1012  +	::notfound :: co:fail(404) do return end
         1013  +	::unauth   :: co:fail(401) do return end
  1029   1014   end