Differences From
Artifact [881176d2e1]:
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