parsav  Diff

Differences From Artifact [ae96c17fe6]:

To Artifact [2469fad253]:


    10     10   	var handle = [lib.mem.ptr(int8)] { ptr = &uri.ptr[2], ct = 0 }
    11     11   	for i=2,uri.ct do
    12     12   		if uri.ptr[i] == @'/' or uri.ptr[i] == 0 then handle.ct = i - 2 break end
    13     13   	end
    14     14   	if handle.ct == 0 then
    15     15   		handle.ct = uri.ct - 2
    16     16   		uri:advance(uri.ct)
    17         -	else
    18         -		if handle.ct + 2 < uri.ct then
    19         -			uri:advance(handle.ct + 2)
    20         -			--uri.ptr = uri.ptr + (handle.ct + 2)
    21         -			--uri.ct = uri.ct - (handle.ct + 2)
    22         -		end
    23         -	end
           17  +	elseif handle.ct + 2 < uri.ct then uri:advance(handle.ct + 2) end
    24     18   
    25     19   	lib.dbg('looking up user by xid "', {handle.ptr,handle.ct} ,'", path: ', {uri.ptr,uri.ct})
    26     20   
    27     21   	var path = lib.http.hier(uri) defer path:free()
    28     22   	for i=0,path.ct do
    29     23   		lib.dbg('got path component ', {path.ptr[i].ptr, path.ptr[i].ct})
    30     24   	end
................................................................................
    32     26   	var actor = co.srv:actor_fetch_xid(handle)
    33     27   	if actor.ptr == nil then
    34     28   		co:complain(404,'no such user','no such user known to this server')
    35     29   		return
    36     30   	end
    37     31   	defer actor:free()
    38     32   
    39         -	lib.render.userpage(co, actor.ptr)
           33  +	lib.render.user_page(co, actor.ptr)
    40     34   end
    41     35   
    42         -terra http.actor_profile_uid(co: &lib.srv.convo, path: lib.mem.ptr(lib.mem.ref(int8)), meth: method.t)
           36  +terra http.actor_profile_uid (
           37  +	co: &lib.srv.convo,
           38  +	path: lib.mem.ptr(lib.mem.ref(int8)),
           39  +	meth: method.t
           40  +)
    43     41   	if path.ct < 2 then
    44     42   		co:complain(404,'bad url','invalid user url')
    45     43   		return
    46     44   	end
    47     45   
    48     46   	var uid, ok = lib.math.shorthand.parse(path.ptr[1].ptr, path.ptr[1].ct)
    49     47   	if not ok then
................................................................................
    54     52   	var actor = co.srv:actor_fetch_uid(uid)
    55     53   	if actor.ptr == nil then
    56     54   		co:complain(404, 'no such user', 'no user by that ID is known to this instance')
    57     55   		return
    58     56   	end
    59     57   	defer actor:free()
    60     58   
    61         -	lib.render.userpage(co, actor.ptr)
           59  +	lib.render.user_page(co, actor.ptr)
    62     60   end
    63     61   
    64     62   terra http.login_form(co: &lib.srv.convo, meth: method.t)
    65     63   	if meth == method.get then
    66     64   		-- request a username
    67     65   		lib.render.login(co, nil, nil, lib.str.plit(nil))
    68     66   	elseif meth == method.post then
................................................................................
   103    101   			if lib.str.ncmp('pw', am, lib.math.biggest(2,aml)) == 0 and chrs ~= nil then
   104    102   				aid = co.srv:actor_auth_pw(co.peer,
   105    103   					[lib.mem.ptr(int8)]{ptr=usn,ct=usnl},
   106    104   					[lib.mem.ptr(int8)]{ptr=chrs,ct=chrsl})
   107    105   			elseif lib.str.ncmp('otp', am, lib.math.biggest(2,aml)) == 0 and chrs ~= nil then
   108    106   				lib.dbg('using otp auth')
   109    107   				-- ยทยทยท --
   110         -			else
   111         -				lib.dbg('invalid auth method')
   112         -			end
          108  +			else lib.dbg('invalid auth method') end
   113    109   
   114    110   			-- error out
   115    111   			if aid == 0 then
   116    112   				lib.render.login(co, nil, nil, lib.str.plit 'authentication failure')
   117    113   			else
   118         -				var sesskey: int8[lib.session.maxlen + #lib.session.cookiename + #"=; Path=/" + 1]
   119         -				do var p = &sesskey[0]
   120         -					p = lib.str.ncpy(p, [lib.session.cookiename .. '='], [#lib.session.cookiename + 1])
   121         -					p = p + lib.session.cookie_gen(co.srv.cfg.secret, aid, lib.osclock.time(nil), p)
   122         -					lib.dbg('sending cookie ',{&sesskey[0],15})
   123         -					p = lib.str.ncpy(p, '; Path=/', 9)
   124         -				end
   125         -				co:reroute_cookie('/', &sesskey[0])
          114  +				co:installkey('/',aid)
   126    115   			end
   127    116   		end
   128    117   		if act.ptr ~= nil and fakeact == false then act:free() end
   129    118   	else
   130    119   		::wrongmeth:: co:complain(405, 'method not allowed', 'that method is not meaningful for this endpoint') do return end
   131    120   	end
   132    121   	return
................................................................................
   134    123   
   135    124   terra http.post_compose(co: &lib.srv.convo, meth: method.t)
   136    125   	if not co:assertpow('post') then return end
   137    126   	--if co.who.rights.powers.post() == false then
   138    127   		--co:complain(403,'insufficient privileges','you lack the <strong>post</strong> power and cannot perform this action')
   139    128   
   140    129   	if meth == method.get then
   141         -		lib.render.compose(co, nil)
          130  +		lib.render.compose(co, nil, nil)
   142    131   	elseif meth == method.post then
   143    132   		var text, textlen = co:postv("post")
   144    133   		var acl, acllen = co:postv("acl")
   145    134   		var subj, subjlen = co:postv("subject")
   146    135   		if text == nil or acl == nil then
   147    136   			co:complain(405, 'invalid post', 'every post must have at least body text and an ACL')
   148    137   			return
................................................................................
   171    160   		lib.render.docpage(co,path(1))
   172    161   	elseif path.ct == 1 then
   173    162   		lib.render.docpage(co, rstring.null())
   174    163   	else
   175    164   		co:complain(404, 'no such documentation', 'invalid documentation URL')
   176    165   	end
   177    166   end
          167  +
          168  +terra http.tweet_page(co: &lib.srv.convo, path: hpath, meth: method.t)
          169  +	var pid, ok = lib.math.shorthand.parse(path(1).ptr, path(1).ct)
          170  +	if not ok then
          171  +		co:complain(400, 'bad post ID', 'that post ID is not valid')
          172  +		return
          173  +	end
          174  +	var post = co.srv:post_fetch(pid)
          175  +	if not post then
          176  +		co:complain(404, 'post not found', 'no such post is known to this server')
          177  +		return
          178  +	end
          179  +	defer post:free()
          180  +
          181  +	if path.ct == 3 then
          182  +		if path(2):cmp(lib.str.lit 'edit') then
          183  +			if post(0).author ~= co.who.id then
          184  +				co:complain(403, 'forbidden', 'you cannot edit other people\'s posts')
          185  +				return
          186  +			end
          187  +
          188  +			if meth == method.get then
          189  +				lib.render.compose(co, post.ptr, nil)
          190  +				return
          191  +			elseif meth == method.post then
          192  +				var newbody = co:postv('post')._0
          193  +				var newacl = co:postv('acl')._0
          194  +				var newsubj = co:postv('subject')._0
          195  +				if newbody ~= nil then post(0).body = newbody end
          196  +				if newacl  ~= nil then post(0).acl = newacl end
          197  +				if newsubj ~= nil then post(0).subject = newsubj end
          198  +				post(0):save(true)
          199  +
          200  +				var lnk: lib.str.acc lnk:compose('/post/', path(1))
          201  +				co:reroute(lnk.buf)
          202  +				lnk:free()
          203  +			end
          204  +			return
          205  +		else goto badurl end
          206  +	end
          207  +
          208  +	if meth == method.post then
          209  +		co:complain(405, 'invalid operation', 'the operation you have attempted on this post is not meaningful')
          210  +		return
          211  +	end
          212  +
          213  +	lib.render.tweet_page(co, path, post.ptr)
          214  +	do return end
          215  +
          216  +	::badurl:: co:complain(404, 'invalid URL', 'this URL does not reference extant content or functionality')
          217  +end
   178    218   
   179    219   terra http.configure(co: &lib.srv.convo, path: hpath, meth: method.t)
   180    220   	var msg = pstring.null()
   181    221   	if meth == method.post and path.ct >= 1 then
   182    222   		var user_refresh = false var fail = false
   183    223   		if path(1):cmp(lib.str.lit 'profile') then
          224  +			lib.dbg('updating profile')
   184    225   			co.who.bio = co:postv('bio')._0
   185    226   			co.who.nym = co:postv('nym')._0
   186    227   			if co.who.bio ~= nil and @co.who.bio == 0 then co.who.bio = nil end
   187    228   			if co.who.nym ~= nil and @co.who.nym == 0 then co.who.nym = nil end
   188    229   			co.who.source:actor_save(co.who)
   189    230   			msg = lib.str.plit 'profile changes saved'
   190    231   			--user_refresh = true -- not really necessary here, actually
   191    232   		elseif path(1):cmp(lib.str.lit 'srv') then
   192    233   		elseif path(1):cmp(lib.str.lit 'users') then
   193         -
          234  +		elseif path(1):cmp(lib.str.lit 'sec') then
          235  +			var act = co:ppostv('act')
          236  +			if act:cmp(lib.str.plit 'invalidate') then
          237  +				lib.dbg('setting user\'s cookie validation time to now')
          238  +				co.who.source:auth_sigtime_user_alter(co.who.id, lib.osclock.time(nil))
          239  +				-- the current session has been invalidated as well, so we need to immediately install a new authentication cookie with the same aid so the user doesn't need to log back in all over again
          240  +				co:installkey('/conf/sec',co.aid)
          241  +				return
          242  +			end
   194    243   		end
   195    244   
   196    245   		if user_refresh then -- refresh the user info for the renderer
   197    246   			var usr = co.srv:actor_fetch_uid(co.who.id)
   198    247   			lib.mem.heapf(co.who)
   199    248   			co.who = usr.ptr
   200    249   		end
................................................................................
   222    271   					ct  = storage[([i-1])].ct;
   223    272   				}
   224    273   				goto [send]
   225    274   			end
   226    275   		end
   227    276   	end
   228    277   	terra http.static_content(co: &lib.srv.convo, [filename], [flen])
   229         -		var hdrs = array(lib.http.header{'Content-Type',nil})
          278  +		var hdrs = array(
          279  +		lib.http.header{'Content-Type',nil})
   230    280   		var [page] = lib.http.page {
   231    281   			respcode = 200;
   232    282   			headers = [lib.mem.ptr(lib.http.header)] {
   233    283   				ptr = &hdrs[0], ct = 1
   234    284   			}
   235    285   		}
   236    286   		[branches]
................................................................................
   288    338   		if co.aid == 0
   289    339   			then goto notfound
   290    340   			else co:reroute_cookie('/','auth=; Path=/')
   291    341   		end
   292    342   		return
   293    343   	else -- hierarchical routes
   294    344   		var path = lib.http.hier(uri) defer path:free()
   295         -		if path.ptr[0]:cmp(lib.str.lit('user')) then
          345  +		if path.ct > 1 and path(0):cmp(lib.str.lit('user')) then
   296    346   			http.actor_profile_uid(co, path, meth)
   297         -		elseif path.ptr[0]:cmp(lib.str.lit('tl')) then
          347  +		elseif path.ct > 1 and path(0):cmp(lib.str.lit('post')) then
          348  +			http.tweet_page(co, path, meth)
          349  +		elseif path(0):cmp(lib.str.lit('tl')) then
   298    350   			http.timeline(co, path)
   299         -		elseif path.ptr[0]:cmp(lib.str.lit('doc')) then
          351  +		elseif path(0):cmp(lib.str.lit('doc')) then
   300    352   			if meth ~= method.get and meth ~= method.head then goto wrongmeth end
   301    353   			http.documentation(co, path)
   302         -		elseif path.ptr[0]:cmp(lib.str.lit('conf')) then
          354  +		elseif path(0):cmp(lib.str.lit('conf')) then
   303    355   			if co.aid == 0 then goto unauth end
   304    356   			http.configure(co,path,meth)
   305    357   		else goto notfound end
   306    358   		return
   307    359   	end
   308    360   
   309    361   	::wrongmeth:: co:complain(405, 'method not allowed', 'that method is not meaningful for this endpoint') do return end
   310    362   	::notfound:: co:complain(404, 'not found', 'no such resource available') do return end
   311    363   	::unauth:: co:complain(401, 'unauthorized', 'this content is not available at your clearance level') do return end
   312    364   end