parsav  Diff

Differences From Artifact [af3d41e739]:

To Artifact [8605ea50bd]:


404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463



464
465
466
467
468
469
470
471
472
...
505
506
507
508
509
510
511














512
513
514
515
516
517
518
...
526
527
528
529
530
531
532


533
534
535
536
537
538
539
...
551
552
553
554
555
556
557

558
559
560
561
562
563
564
end

terra http.media_manager(co: &lib.srv.convo, path: hpath, meth: method.t)
	if meth == method.post then
		goto badop
	end

	if path.ct == 1 or (path.ct >= 3 and path(1):cmp(lib.str.lit'a')) then
		if meth == method.post then goto badop end
		lib.render.media_gallery(co,path,co.who.id,nil)
	elseif path.ct == 2 then
		if path(1):cmp(lib.str.lit'upload') and co.who.rights.powers.artifact() then
			if meth == method.get then
				var view = data.view.media_upload {
					folders = ''
				}
				var pg = view:tostr() defer pg:free()
				co:stdpage([lib.srv.convo.page] {
					title = lib.str.plit'media :: upload';
					class = lib.str.plit'media upload';
					cache = false; body = pg;
				})
			elseif meth == method.post_file then
				var desc = pstring.null()
				var folder = pstring.null()
				var mime = pstring.null()
				var name = pstring.null()
				var body = binblob.null()
				for i=0, co.uploads.sz do var up = co.uploads.storage.ptr + i
					if up.body.ct > 0 then
						if up.field:cmp(lib.str.plit'desc') then
							desc = up.body
						elseif up.field:cmp(lib.str.plit'folder') then
							folder = up.body
						elseif up.field:cmp(lib.str.plit'file') then
							mime = up.ctype
							body = binblob {ptr = [&uint8](up.body.ptr), ct = up.body.ct}
							name = up.filename
						end
					end
				end
				if not body then goto badop end
				if body.ct > co.srv.cfg.maxupsz then
					co:complain(403, 'file too long', "the file you have attempted to upload exceeds the maximum length permitted by this server's upload policy. if it is an image or video, try compressing it at a lower quality setting or resolution")
					return
				end
				var id = co.srv:artifact_instantiate(body,mime)
				if id == 0 then
					co:complain(500,'upload failed','artifact rejected. either the server is running out of space or this file is banned from the server')
					return
				end
				co.srv:artifact_expropriate(co.who.id,id,desc,folder)

				var idbuf: int8[lib.math.shorthand.maxlen]
				var idlen = lib.math.shorthand.gen(id,&idbuf[0])

				var url = lib.str.acc{}:compose('/media/a/',pstring{&idbuf[0],idlen}):finalize()
				co:reroute(url.ptr)
				url:free()
			else goto badop end



		end
	else goto e404 end
	do return end

	::badop:: do co:complain(405, 'invalid operation', 'the operation you have attempted on this post is not meaningful') return end
	::e404:: do co:complain(404, 'artifact not found', 'no such artifact has been uploaded by this user') return end
end

do local branches = quote end
................................................................................
end


terra http.local_avatar(co: &lib.srv.convo, handle: lib.mem.ptr(int8))
	-- TODO retrieve user avatars
	co:reroute('/s/default-avatar.webp')
end















-- entry points
terra r.dispatch_http(co: &lib.srv.convo, uri: lib.mem.ptr(int8), meth: method.t)
	lib.dbg('handling URI of form ', {uri.ptr,uri.ct})
	co.navbar = lib.render.nav(co)
	-- some routes are non-hierarchical, and can be resolved with a simple strcmp
	-- we run through those first before giving up and parsing the URI
................................................................................
	elseif uri.ptr[1] == @'@' then
		http.actor_profile_xid(co, uri, meth)
	elseif uri.ptr[1] == @'s' and uri.ptr[2] == @'/' and uri.ct > 3 then
		if not meth_get(meth) then goto wrongmeth end
		if not http.static_content(co, uri.ptr + 3, uri.ct - 3) then goto notfound end
	elseif lib.str.ncmp('/avi/', uri.ptr, 5) == 0 then
		http.local_avatar(co, [lib.mem.ptr(int8)] {ptr = uri.ptr + 5, ct = uri.ct - 5})


	elseif uri:cmp(lib.str.plit '/notices') then
		if co.aid == 0 then co:reroute('/login') return end
		http.user_notices(co,meth)
	elseif uri:cmp(lib.str.plit '/compose') then
		if co.aid == 0 then co:reroute('/login') return end
		http.post_compose(co,meth)
	elseif uri:cmp(lib.str.plit '/login') then
................................................................................
		if path.ct > 1 and path(0):cmp(lib.str.lit('user')) then
			http.actor_profile_uid(co, path, meth)
		elseif path.ct > 1 and path(0):cmp(lib.str.lit('post')) then
			http.tweet_page(co, path, meth)
		elseif path(0):cmp(lib.str.lit('tl')) then
			http.timeline(co, path)
		elseif path(0):cmp(lib.str.lit('media')) then

			http.media_manager(co, path, meth)
		elseif path(0):cmp(lib.str.lit('doc')) then
			if not meth_get(meth) then goto wrongmeth end
			http.documentation(co, path)
		elseif path(0):cmp(lib.str.lit('conf')) then
			if co.aid == 0 then goto unauth end
			http.configure(co,path,meth)







<
<
<
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|

|
|
|
|
>
>
>
|
<







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>







 







>







404
405
406
407
408
409
410




411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463

464
465
466
467
468
469
470
...
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
...
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
...
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
end

terra http.media_manager(co: &lib.srv.convo, path: hpath, meth: method.t)
	if meth == method.post then
		goto badop
	end





	if path.ct == 2 and path(1):cmp(lib.str.lit'upload') and co.who.rights.powers.artifact() then
		if meth == method.get then
			var view = data.view.media_upload {
				folders = ''
			}
			var pg = view:tostr() defer pg:free()
			co:stdpage([lib.srv.convo.page] {
				title = lib.str.plit'media :: upload';
				class = lib.str.plit'media upload';
				cache = false; body = pg;
			})
		elseif meth == method.post_file then
			var desc = pstring.null()
			var folder = pstring.null()
			var mime = pstring.null()
			var name = pstring.null()
			var body = binblob.null()
			for i=0, co.uploads.sz do var up = co.uploads.storage.ptr + i
				if up.body.ct > 0 then
					if up.field:cmp(lib.str.plit'desc') then
						desc = up.body
					elseif up.field:cmp(lib.str.plit'folder') then
						folder = up.body
					elseif up.field:cmp(lib.str.plit'file') then
						mime = up.ctype
						body = binblob {ptr = [&uint8](up.body.ptr), ct = up.body.ct}
						name = up.filename
					end
				end
			end
			if not body then goto badop end
			if body.ct > co.srv.cfg.maxupsz then
				co:complain(403, 'file too long', "the file you have attempted to upload exceeds the maximum length permitted by this server's upload policy. if it is an image or video, try compressing it at a lower quality setting or resolution")
				return
			end
			var id = co.srv:artifact_instantiate(body,mime)
			if id == 0 then
				co:complain(500,'upload failed','artifact rejected. either the server is running out of space or this file is banned from the server')
				return
			end
			co.srv:artifact_expropriate(co.who.id,id,desc,folder)

			var idbuf: int8[lib.math.shorthand.maxlen]
			var idlen = lib.math.shorthand.gen(id,&idbuf[0])

			var url = lib.str.acc{}:compose('/media/a/',pstring{&idbuf[0],idlen}):finalize()
			co:reroute(url.ptr)
			url:free()
		else goto badop end
	else
		if meth == method.post then goto badop end
		lib.render.media_gallery(co,path,co.who.id,nil)
	end

	do return end

	::badop:: do co:complain(405, 'invalid operation', 'the operation you have attempted on this post is not meaningful') return end
	::e404:: do co:complain(404, 'artifact not found', 'no such artifact has been uploaded by this user') return end
end

do local branches = quote end
................................................................................
end


terra http.local_avatar(co: &lib.srv.convo, handle: lib.mem.ptr(int8))
	-- TODO retrieve user avatars
	co:reroute('/s/default-avatar.webp')
end

terra http.file_serve_raw(co: &lib.srv.convo, id: lib.mem.ptr(int8))
	var id, idok = lib.math.shorthand.parse(id.ptr, id.ct)
	if not idok then goto e404 end
	var data, mime = co.srv:artifact_load(id)
	if not data then goto e404 end
	do defer data:free() defer mime:free()
		lib.net.mg_printf(co.con, 'HTTP/1.1 200 OK\r\nContent-Type: %.*s\r\nContent-Length: %llu\r\n\r\n', mime.ct, mime.ptr, data.ct + 2)
		lib.net.mg_send(co.con, data.ptr, data.ct)
		lib.net.mg_send(co.con, '\r\n', 2)
	return end

	::e404:: do co:complain(404, 'artifact not found', 'no such artifact has been uploaded to this instance') return end
end

-- entry points
terra r.dispatch_http(co: &lib.srv.convo, uri: lib.mem.ptr(int8), meth: method.t)
	lib.dbg('handling URI of form ', {uri.ptr,uri.ct})
	co.navbar = lib.render.nav(co)
	-- some routes are non-hierarchical, and can be resolved with a simple strcmp
	-- we run through those first before giving up and parsing the URI
................................................................................
	elseif uri.ptr[1] == @'@' then
		http.actor_profile_xid(co, uri, meth)
	elseif uri.ptr[1] == @'s' and uri.ptr[2] == @'/' and uri.ct > 3 then
		if not meth_get(meth) then goto wrongmeth end
		if not http.static_content(co, uri.ptr + 3, uri.ct - 3) then goto notfound end
	elseif lib.str.ncmp('/avi/', uri.ptr, 5) == 0 then
		http.local_avatar(co, [lib.mem.ptr(int8)] {ptr = uri.ptr + 5, ct = uri.ct - 5})
	elseif lib.str.ncmp('/file/', uri.ptr, 6) == 0 then
		http.file_serve_raw(co, [lib.mem.ptr(int8)] {ptr = uri.ptr + 6, ct = uri.ct - 6})
	elseif uri:cmp(lib.str.plit '/notices') then
		if co.aid == 0 then co:reroute('/login') return end
		http.user_notices(co,meth)
	elseif uri:cmp(lib.str.plit '/compose') then
		if co.aid == 0 then co:reroute('/login') return end
		http.post_compose(co,meth)
	elseif uri:cmp(lib.str.plit '/login') then
................................................................................
		if path.ct > 1 and path(0):cmp(lib.str.lit('user')) then
			http.actor_profile_uid(co, path, meth)
		elseif path.ct > 1 and path(0):cmp(lib.str.lit('post')) then
			http.tweet_page(co, path, meth)
		elseif path(0):cmp(lib.str.lit('tl')) then
			http.timeline(co, path)
		elseif path(0):cmp(lib.str.lit('media')) then
			if co.aid == 0 then goto unauth end
			http.media_manager(co, path, meth)
		elseif path(0):cmp(lib.str.lit('doc')) then
			if not meth_get(meth) then goto wrongmeth end
			http.documentation(co, path)
		elseif path(0):cmp(lib.str.lit('conf')) then
			if co.aid == 0 then goto unauth end
			http.configure(co,path,meth)