parsav  Diff

Differences From Artifact [881176d2e1]:

To Artifact [b4f49ac3f6]:


   284    284   	lib.render.tweet_page(co, path, post.ptr)
   285    285   	do return end
   286    286   
   287    287   	::badurl:: do co:complain(404, 'invalid URL', 'this URL does not reference extant content or functionality') return end
   288    288   	::badop :: do co:complain(405, 'invalid operation', 'the operation you have attempted on this post is not meaningful') return end
   289    289   	::noauth:: do co:complain(401, 'unauthorized', 'you have not supplied the necessary credentials to perform this operation') return end
   290    290   end
          291  +
          292  +local terra 
          293  +credsec_for_uid(co: &lib.srv.convo, uid: uint64)
          294  +	var act = co:ppostv('act')
          295  +	if act:cmp(lib.str.plit 'invalidate') then
          296  +		lib.dbg('setting user\'s cookie validation time to now')
          297  +		co.who.source:auth_sigtime_user_alter(uid, lib.osclock.time(nil))
          298  +		-- 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
          299  +		co:installkey('/conf/sec',co.aid)
          300  +		return
          301  +	elseif act:cmp(lib.str.plit 'newcred') then
          302  +		var cmt = co:ppostv('comment')
          303  +		var pw = co:ppostv('newpw')
          304  +		if pw:ref() then
          305  +			var cpw = co:ppostv('rptpw')
          306  +			if not pw:cmp(cpw) then
          307  +				co:complain(400,'enrollment failure','the passwords you supplied do not match')
          308  +				return
          309  +			end
          310  +			co.srv:auth_attach_pw(uid, false, pw, cmt)
          311  +			co:reroute('?')
          312  +			return
          313  +		else
          314  +			var key = co:ppostv('newkey')
          315  +			if key:ref() then
          316  +
          317  +			end
          318  +		end
          319  +	end
          320  +	co:complain(400,'bad request','the operation you have requested is not meaningful in this context')
          321  +end
   291    322   
   292    323   terra http.configure(co: &lib.srv.convo, path: hpath, meth: method.t)
   293    324   	var msg = pstring.null()
   294    325   	-- first things first, do priv checks
   295    326   	if path.ct >= 1 then
   296    327   		if not co.who.rights.powers.config() and (
   297    328   			path(1):cmp(lib.str.lit 'srv')   or
................................................................................
   345    376   				co.ui_hue = co.srv.cfg.ui_hue
   346    377   			end
   347    378   
   348    379   			msg = lib.str.plit 'profile changes saved'
   349    380   			--user_refresh = true -- not really necessary here, actually
   350    381   
   351    382   		elseif path(1):cmp(lib.str.lit 'sec') then
   352         -			var act = co:ppostv('act')
   353         -			if act:cmp(lib.str.plit 'invalidate') then
   354         -				lib.dbg('setting user\'s cookie validation time to now')
   355         -				co.who.source:auth_sigtime_user_alter(co.who.id, lib.osclock.time(nil))
   356         -				-- 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
   357         -				co:installkey('/conf/sec',co.aid)
   358         -				return
   359         -			end
          383  +			credsec_for_uid(co, co.who.id)
   360    384   		elseif path(1):cmp(lib.str.lit 'users') then
   361    385   			if path.ct >= 3 then
   362    386   				var userid, ok = lib.math.shorthand.parse(path(2).ptr, path(2).ct)
   363    387   				if ok then
   364    388   					var usr = co.srv:actor_fetch_uid(userid)
   365    389   					if usr:ref() then defer usr:free()
   366    390   						if not co.who:overpowers(usr.ptr) then goto nopriv end
   367    391   					end
   368    392   				end
   369         -			elseif path.ct == 2 then
          393  +			elseif path.ct == 2 and meth == method.post then
          394  +				var act = co:ppostv('act')
          395  +				if act:cmp(lib.str.plit'create') then
          396  +					var newname = co:ppostv('handle')
          397  +					if not newname or not lib.store.actor.handle_validate(newname.ptr) then
          398  +						co:complain(400,'invalid handle','the handle you have requested is not valid')
          399  +					end
          400  +					var tu = co.srv:actor_fetch_xid(newname)
          401  +					if tu:ref() then tu:free()
          402  +						co:complain(409,'handle clash','that handle conflicts with one that already exists')
          403  +						return
          404  +					end
          405  +					var kbuf: uint8[lib.crypt.const.maxdersz]
          406  +					var na = lib.store.actor.mk(&kbuf[0])
          407  +					na.handle = newname.ptr
          408  +					var newuid = co.srv:actor_create(&na)
          409  +					var shid: int8[lib.math.shorthand.maxlen]
          410  +					var shidlen = lib.math.shorthand.gen(newuid, &shid[0])
          411  +					var url = lib.str.acc{}:compose('/conf/users/',pstring{&shid[0],shidlen}):finalize() defer url:free()
          412  +					co:reroute(url.ptr)
          413  +					return
          414  +				elseif act:cmp(lib.str.plit'inst') then
          415  +				else goto badop end
   370    416   			end
   371    417   		end
   372    418   
   373    419   		if user_refresh then -- refresh the user info for the renderer
   374    420   			var usr = co.srv:actor_fetch_uid(co.who.id)
   375    421   			lib.mem.heapf(co.who)
   376    422   			co.who = usr.ptr
................................................................................
   380    426   			co:reroute(go)
   381    427   			return
   382    428   		end
   383    429   	end
   384    430   	lib.render.conf(co,path,msg)
   385    431   	do return end
   386    432   
   387         -	::nopriv:: co:complain(403,'insufficient privileges','you do not have the necessary powers to perform this action')
          433  +	::nopriv:: do co:complain(403,'insufficient privileges','you do not have the necessary powers to perform this action') return end
          434  +	::badop:: do co:complain(400,'bad request','the operation you have requested is not meaningful in this context') return end
   388    435   end
   389    436   
   390    437   terra http.user_notices(co: &lib.srv.convo, meth: method.t)
   391    438   	if meth == method.post then
   392    439   		var act = co:ppostv('act')
   393    440   		if act:cmp(lib.str.plit'clear') then
   394    441   			co.srv:actor_conf_int_set(co.who.id, 'notice-clear-time', lib.osclock.time(nil))
................................................................................
   399    446   
   400    447   	lib.render.notices(co)
   401    448   	do return end
   402    449   
   403    450   	::badop:: do co:complain(405, 'invalid operation', 'the operation you have attempted on this post is not meaningful') return end
   404    451   end
   405    452   
   406         -terra http.media_manager(co: &lib.srv.convo, path: hpath, meth: method.t)
   407         -	if meth == method.post then
   408         -		goto badop
   409         -	end
   410         -
   411         -	if path.ct == 2 and path(1):cmp(lib.str.lit'upload') and co.who.rights.powers.artifact() then
          453  +terra http.media_manager(co: &lib.srv.convo, path: hpath, meth: method.t, uid: uint64)
          454  +	if co.aid ~= 0 and co.who.id == uid and path.ct == 2 and path(1):cmp(lib.str.lit'upload') and co.who.rights.powers.artifact() then
   412    455   		if meth == method.get then
   413    456   			var view = data.view.media_upload {
   414    457   				folders = ''
   415    458   			}
   416    459   			var pg = view:tostr() defer pg:free()
   417    460   			co:stdpage([lib.srv.convo.page] {
   418    461   				title = lib.str.plit'media :: upload';
................................................................................
   453    496   			var idbuf: int8[lib.math.shorthand.maxlen]
   454    497   			var idlen = lib.math.shorthand.gen(id,&idbuf[0])
   455    498   
   456    499   			var url = lib.str.acc{}:compose('/media/a/',pstring{&idbuf[0],idlen}):finalize()
   457    500   			co:reroute(url.ptr)
   458    501   			url:free()
   459    502   		else goto badop end
          503  +	elseif co.aid ~= 0 and path.ct == 4 and path(1):cmp(lib.str.lit'a') and meth==method.post then 
          504  +		var act = co:ppostv('act')
          505  +		if not act or not act:cmp(lib.str.plit'confirm') then goto badop end
          506  +		var artid, aok = lib.math.shorthand.parse(path(2).ptr,path(2).ct)
          507  +		if not aok then goto e404 end
          508  +		var art = co.srv:artifact_fetch(uid,artid)
          509  +		if not art then goto e404 end
          510  +		defer art:free()
          511  +
          512  +		if path(3):cmp(lib.str.lit'avi') then
          513  +		 -- user wants to set avatar
          514  +			co.who.avatarid = artid
          515  +			co.srv:actor_save(co.who)
          516  +			co:reroute('/conf/avi')
          517  +		elseif path(3):cmp(lib.str.lit'del') then 
          518  +			co.srv:artifact_disclaim(co.who.id, artid)
          519  +			co:reroute('/media')
          520  +		else goto badop end
   460    521   	else
   461    522   		if meth == method.post then goto badop end
   462         -		lib.render.media_gallery(co,path,co.who.id,nil)
          523  +		lib.render.media_gallery(co,path,uid,nil)
   463    524   	end
   464    525   	do return end
   465    526   
   466    527   	::badop:: do co:complain(405, 'invalid operation', 'the operation you have attempted on this post is not meaningful') return end
   467    528   	::e404:: do co:complain(404, 'artifact not found', 'no such artifact has been uploaded by this user') return end
   468    529   end
   469    530   
................................................................................
   501    562   		::[send]:: page:send(co.con) return true
   502    563   	end
   503    564   end
   504    565   
   505    566   
   506    567   terra http.local_avatar(co: &lib.srv.convo, handle: lib.mem.ptr(int8))
   507    568   	-- TODO retrieve user avatars
   508         -	co:reroute('/s/default-avatar.webp')
          569  +	var usr = co.srv:actor_fetch_xid(handle)
          570  +	if not usr then
          571  +	goto default end
          572  +	if usr(0).origin == 0 then
          573  +		if usr(0).avatarid == 0 then goto default end
          574  +		var avi, mime = co.srv:artifact_load(usr(0).avatarid)
          575  +		if not avi then goto default end
          576  +		defer avi:free() defer mime:free()
          577  +		co:bytestream(mime,avi)
          578  +	else
          579  +		co:reroute(usr(0).avatar)
          580  +	end
          581  +	do return end
          582  +	::default:: co:reroute('/s/default-avatar.webp')
   509    583   end
   510    584   
   511    585   terra http.file_serve_raw(co: &lib.srv.convo, id: lib.mem.ptr(int8))
   512    586   	var id, idok = lib.math.shorthand.parse(id.ptr, id.ct)
   513    587   	if not idok then goto e404 end
   514    588   	var data, mime = co.srv:artifact_load(id)
   515    589   	if not data then goto e404 end
   516    590   	do defer data:free() defer mime:free()
   517         -		var safemime = mime
   518         -		-- TODO this is not a satisfactory solution; it's a bandaid on a gaping
   519         -		-- chest wound. ultimately we need to compile a whitelist of safe mime
   520         -		-- types as part of mimelib, but that is no small task. for now, this
   521         -		-- will keep the patient from immediately bleeding out
   522         -		if mime:cmp(lib.str.plit'text/html') or
   523         -			mime:cmp(lib.str.plit'text/xml') or
   524         -			mime:cmp(lib.str.plit'application/xhtml+xml') or
   525         -			mime:cmp(lib.str.plit'application/vnd.wap.xhtml+xml')
   526         -		then -- danger will robinson
   527         -			safemime = lib.str.plit'text/plain'
   528         -		elseif mime:cmp(lib.str.plit'application/x-shockwave-flash') then
   529         -			safemime = lib.str.plit'application/octet-stream'
   530         -		end
   531         -		lib.net.mg_printf(co.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", safemime.ct, safemime.ptr, data.ct + 2)
   532         -		lib.net.mg_send(co.con, data.ptr, data.ct)
   533         -		lib.net.mg_send(co.con, '\r\n', 2)
          591  +		co:bytestream(mime,data)
   534    592   	return end
   535    593   
   536    594   	::e404:: do co:complain(404, 'artifact not found', 'no such artifact has been uploaded to this instance') return end
   537    595   end
   538    596   
   539    597   -- entry points
   540    598   terra r.dispatch_http(co: &lib.srv.convo, uri: lib.mem.ptr(int8), meth: method.t)
................................................................................
   580    638   			http.actor_profile_uid(co, path, meth)
   581    639   		elseif path.ct > 1 and path(0):cmp(lib.str.lit('post')) then
   582    640   			http.tweet_page(co, path, meth)
   583    641   		elseif path(0):cmp(lib.str.lit('tl')) then
   584    642   			http.timeline(co, path)
   585    643   		elseif path(0):cmp(lib.str.lit('media')) then
   586    644   			if co.aid == 0 then goto unauth end
   587         -			http.media_manager(co, path, meth)
          645  +			http.media_manager(co, path, meth, co.who.id)
   588    646   		elseif path(0):cmp(lib.str.lit('doc')) then
   589    647   			if not meth_get(meth) then goto wrongmeth end
   590    648   			http.documentation(co, path)
   591    649   		elseif path(0):cmp(lib.str.lit('conf')) then
   592    650   			if co.aid == 0 then goto unauth end
   593    651   			http.configure(co,path,meth)
   594    652   		else goto notfound end