parsav  Diff

Differences From Artifact [a9eb70a00e]:

To Artifact [f59188addc]:


     2      2   local r = lib.srv.route
     3      3   local method = lib.http.method
     4      4   local pstring = lib.mem.ptr(int8)
     5      5   local rstring = lib.mem.ref(int8)
     6      6   local hpath = lib.mem.ptr(rstring)
     7      7   local http = {}
     8      8   
            9  +terra meth_get(meth: method.t) return (meth == method.get) or (meth == method.head) end
     9     10   terra http.actor_profile_xid(co: &lib.srv.convo, uri: lib.mem.ptr(int8), meth: method.t)
    10     11   	var handle = [lib.mem.ptr(int8)] { ptr = &uri.ptr[2], ct = 0 }
    11     12   	for i=2,uri.ct do
    12     13   		if uri.ptr[i] == @'/' or uri.ptr[i] == 0 then handle.ct = i - 2 break end
    13     14   	end
    14     15   	if handle.ct == 0 then
    15     16   		handle.ct = uri.ct - 2
................................................................................
    56     57   	end
    57     58   	defer actor:free()
    58     59   
    59     60   	lib.render.user_page(co, actor.ptr)
    60     61   end
    61     62   
    62     63   terra http.login_form(co: &lib.srv.convo, meth: method.t)
    63         -	if meth == method.get then
           64  +	if meth_get(meth) then
    64     65   		-- request a username
    65     66   		lib.render.login(co, nil, nil, lib.str.plit(nil))
    66     67   	elseif meth == method.post then
    67     68   		var usn, usnl = co:postv('user')
    68     69   		var am, aml = co:postv('authmethod')
    69     70   		var chrs, chrsl = co:postv('response')
    70     71   		var cs, authok = co.srv:actor_auth_how(co.peer, usn)
................................................................................
   122    123   end
   123    124   
   124    125   terra http.post_compose(co: &lib.srv.convo, meth: method.t)
   125    126   	if not co:assertpow('post') then return end
   126    127   	--if co.who.rights.powers.post() == false then
   127    128   		--co:complain(403,'insufficient privileges','you lack the <strong>post</strong> power and cannot perform this action')
   128    129   
   129         -	if meth == method.get then
          130  +	if meth_get(meth) then
   130    131   		lib.render.compose(co, nil, nil)
   131    132   	elseif meth == method.post then
   132    133   		var text, textlen = co:postv("post")
   133    134   		var acl, acllen = co:postv("acl")
   134    135   		var subj, subjlen = co:postv("subject")
   135    136   		if text == nil or acl == nil then
   136    137   			co:complain(405, 'invalid post', 'every post must have at least body text and an ACL')
................................................................................
   138    139   		end
   139    140   		if subj == nil then subj = '' end
   140    141   
   141    142   		var p = lib.store.post {
   142    143   			author = co.who.id, acl = acl;
   143    144   			body = text, subject = subj;
   144    145   		}
   145         -		var newid = co.srv:post_create(&p)
          146  +		var newid = p:publish(co.srv)
   146    147   
   147    148   		var idbuf: int8[lib.math.shorthand.maxlen]
   148    149   		var idlen = lib.math.shorthand.gen(newid, idbuf)
   149    150   		var redirto: lib.str.acc redirto:compose('/post/',{idbuf,idlen}) defer redirto:free()
   150    151   		co:reroute(redirto.buf)
   151    152   	end
   152    153   end
................................................................................
   181    182   	if path.ct == 3 then
   182    183   		var lnk: lib.str.acc lnk:compose('/post/', path(1))
   183    184   		var lnkp = lnk:finalize() defer lnkp:free()
   184    185   		if post(0).author ~= co.who.id then
   185    186   			co:complain(403, 'forbidden', 'you cannot alter other people\'s posts')
   186    187   			return
   187    188   		elseif path(2):cmp(lib.str.lit 'edit') then
   188         -			if meth == method.get then
          189  +			if meth_get(meth) then
   189    190   				lib.render.compose(co, post.ptr, nil)
   190    191   				return
   191    192   			elseif meth == method.post then
   192    193   				var newbody = co:postv('post')._0
   193    194   				var newacl = co:postv('acl')._0
   194    195   				var newsubj = co:postv('subject')._0
   195    196   				if newbody ~= nil then post(0).body = newbody end
................................................................................
   196    197   				if newacl  ~= nil then post(0).acl = newacl end
   197    198   				if newsubj ~= nil then post(0).subject = newsubj end
   198    199   				post(0):save(true)
   199    200   				co:reroute(lnkp.ptr)
   200    201   			end
   201    202   			return
   202    203   		elseif path(2):cmp(lib.str.lit 'del') then
   203         -			if meth == method.get then
          204  +			if meth_get(meth) then
   204    205   				var conf = data.view.confirm {
   205    206   					title = lib.str.plit 'delete post';
   206    207   					query = lib.str.plit 'are you sure you want to delete this post?';
   207    208   					cancel = lnkp
   208    209   				}
   209    210   				var body = conf:tostr() defer body:free()
   210    211   				co:stdpage([lib.srv.convo.page] {
................................................................................
   220    221   					co:reroute('/') -- TODO maybe return to parent or conversation if possible
   221    222   					return
   222    223   				else goto badop end
   223    224   			end
   224    225   		else goto badurl end
   225    226   	end
   226    227   
   227         -	if meth == method.post then goto badop end
          228  +	if meth == method.post then
          229  +		var replytext = co:ppostv('post')
          230  +		var acl = co:ppostv('acl')
          231  +		var subj = co:ppostv('subject')
          232  +		if not acl then acl = lib.str.plit 'all' end
          233  +		if not replytext then goto badop end
          234  +		
          235  +		var reply = lib.store.post {
          236  +			author = co.who.id, parent = pid;
          237  +			subject = subj.ptr, acl = acl.ptr, body = replytext.ptr;
          238  +		}
          239  +
          240  +		reply:publish(co.srv)
          241  +	end
   228    242   
   229    243   	lib.render.tweet_page(co, path, post.ptr)
   230    244   	do return end
   231    245   
   232    246   	::badurl:: do co:complain(404, 'invalid URL', 'this URL does not reference extant content or functionality') return end
   233    247   	::badop :: do co:complain(405, 'invalid operation', 'the operation you have attempted on this post is not meaningful') return end
   234    248   end
................................................................................
   240    254   		if path(1):cmp(lib.str.lit 'profile') then
   241    255   			lib.dbg('updating profile')
   242    256   			co.who.bio = co:postv('bio')._0
   243    257   			co.who.nym = co:postv('nym')._0
   244    258   			if co.who.bio ~= nil and @co.who.bio == 0 then co.who.bio = nil end
   245    259   			if co.who.nym ~= nil and @co.who.nym == 0 then co.who.nym = nil end
   246    260   			co.who.source:actor_save(co.who)
          261  +
          262  +			var act = co:ppostv('act')
          263  +			var resethue = false
          264  +			if act:ref() then
          265  +				resethue = act:cmp(lib.str.plit 'reset-hue')
          266  +			end
          267  +
          268  +			if not resethue then
          269  +				var shue = co:ppostv('hue')
          270  +				var nhue, okhue = lib.math.decparse(shue)
          271  +				if okhue and nhue ~= co.ui_hue then
          272  +					if nhue == co.srv.cfg.ui_hue
          273  +						then resethue = true
          274  +						else co.srv:actor_conf_int_set(co.who.id, 'ui-accent', nhue)
          275  +					end
          276  +					co.ui_hue = nhue
          277  +				end
          278  +			end
          279  +			if resethue then
          280  +				co.srv:actor_conf_int_reset(co.who.id, 'ui-accent')
          281  +				co.ui_hue = co.srv.cfg.ui_hue
          282  +			end
          283  +
   247    284   			msg = lib.str.plit 'profile changes saved'
   248    285   			--user_refresh = true -- not really necessary here, actually
   249    286   		elseif path(1):cmp(lib.str.lit 'srv') then
   250    287   			if not co.who.rights.powers.config() then goto nopriv end
   251    288   		elseif path(1):cmp(lib.str.lit 'brand') then
   252    289   			if not co.who.rights.powers.rebrand() then goto nopriv end
   253    290   		elseif path(1):cmp(lib.str.lit 'users') then
................................................................................
   322    359   
   323    360   -- entry points
   324    361   terra r.dispatch_http(co: &lib.srv.convo, uri: lib.mem.ptr(int8), meth: method.t)
   325    362   	lib.dbg('handling URI of form ', {uri.ptr,uri.ct})
   326    363   	co.navbar = lib.render.nav(co)
   327    364   	-- some routes are non-hierarchical, and can be resolved with a simple strcmp
   328    365   	-- we run through those first before giving up and parsing the URI
   329         -	if uri.ptr[0] ~= @'/' then
          366  +	if uri.ptr == nil or uri.ptr[0] ~= @'/' then
   330    367   		co:complain(404, 'what the hell', 'how did you do that')
   331         -		return
   332    368   	elseif uri.ct == 1 then -- root
   333    369   		if (co.srv.cfg.pol_sec == lib.srv.secmode.private or
   334    370   		   co.srv.cfg.pol_sec == lib.srv.secmode.lockdown) and co.aid == 0 then
   335    371   		   http.login_form(co, meth)
   336         -		else
   337         -			-- FIXME display home screen
   338         -			http.timeline(co, hpath {ptr=nil})
   339         -			goto notfound
   340         -		end
   341         -		return
          372  +		else http.timeline(co, hpath {ptr=nil}) end
   342    373   	elseif uri.ptr[1] == @'@' then
   343    374   		http.actor_profile_xid(co, uri, meth)
   344         -		return
   345    375   	elseif uri.ptr[1] == @'s' and uri.ptr[2] == @'/' and uri.ct > 3 then
   346         -		if meth ~= method.get then goto wrongmeth end
          376  +		if not meth_get(meth) then goto wrongmeth end
   347    377   		if not http.static_content(co, uri.ptr + 3, uri.ct - 3) then goto notfound end
   348         -		return
   349    378   	elseif lib.str.ncmp('/avi/', uri.ptr, 5) == 0 then
   350    379   		http.local_avatar(co, [lib.mem.ptr(int8)] {ptr = uri.ptr + 5, ct = uri.ct - 5})
   351         -		return
   352    380   	elseif lib.str.ncmp('/compose', uri.ptr, lib.math.biggest(uri.ct,8)) == 0 then
   353    381   		if co.aid == 0 then co:reroute('/login') return end
   354    382   		http.post_compose(co,meth)
   355         -		return
   356    383   	elseif lib.str.ncmp('/login', uri.ptr, lib.math.biggest(uri.ct,6)) == 0 then
   357    384   		if co.aid == 0
   358    385   			then http.login_form(co, meth)
   359    386   			else co:reroute('/')
   360    387   		end
   361         -		return
   362    388   	elseif lib.str.ncmp('/logout', uri.ptr, lib.math.biggest(uri.ct,7)) == 0 then
   363    389   		if co.aid == 0
   364    390   			then goto notfound
   365    391   			else co:reroute_cookie('/','auth=; Path=/')
   366    392   		end
   367         -		return
   368    393   	else -- hierarchical routes
   369    394   		var path = lib.http.hier(uri) defer path:free()
   370    395   		if path.ct > 1 and path(0):cmp(lib.str.lit('user')) then
   371    396   			http.actor_profile_uid(co, path, meth)
   372    397   		elseif path.ct > 1 and path(0):cmp(lib.str.lit('post')) then
   373    398   			http.tweet_page(co, path, meth)
   374    399   		elseif path(0):cmp(lib.str.lit('tl')) then
   375    400   			http.timeline(co, path)
   376    401   		elseif path(0):cmp(lib.str.lit('doc')) then
   377         -			if meth ~= method.get and meth ~= method.head then goto wrongmeth end
          402  +			if not meth_get(meth) then goto wrongmeth end
   378    403   			http.documentation(co, path)
   379    404   		elseif path(0):cmp(lib.str.lit('conf')) then
   380    405   			if co.aid == 0 then goto unauth end
   381    406   			http.configure(co,path,meth)
   382    407   		else goto notfound end
   383         -		return
   384    408   	end
          409  +	do return end
   385    410   
   386    411   	::wrongmeth:: co:complain(405, 'method not allowed', 'that method is not meaningful for this endpoint') do return end
   387    412   	::notfound:: co:complain(404, 'not found', 'no such resource available') do return end
   388    413   	::unauth:: co:complain(401, 'unauthorized', 'this content is not available at your clearance level') do return end
   389    414   end