@ -8,8 +8,10 @@
// Model
# include "model/server.h"
# include "model/account.h"
# include "model/notification.h"
# include "model/ap/activity.h"
# include "model/ap/inbox_envelope.h"
# include "model/ap/outbox_envelope.h"
# include "model/crypto/http_sign.h"
// Stdlib
@ -35,19 +37,9 @@ bool route_inbox( struct http_request* req )
return true ;
}
bool route_undo_activity ( struct ap_activity * act )
{
if ( act - > object . tag ! = apaot_activity ) {
// Don't undo activities that are references
return false ;
}
if ( ! act - > object . ptr ) {
printf ( " No object in activity \n " ) ;
return false ;
}
switch ( act - > object . ptr - > type ) {
case apat_follow :
static bool route_undo_follow ( struct ap_activity * act )
{
const char * target = act - > object . ptr - > object . ref ;
struct account * a = account_from_uri ( target ) ;
if ( ! a | | 0 ! = strcmp ( a - > server , g_server_name ) ) {
@ -61,17 +53,14 @@ bool route_undo_activity( struct ap_activity* act )
return true ;
}
printf ( " TODO: undo %s following %s \n " , act - > actor , target ) ;
return false ;
default :
printf ( " Unhandled object activity type %d in undo \n " , act - > object . ptr - > type ) ;
return false ;
} ;
account_remove_follower ( a , follower ) ;
return false ;
// TODO: create a notification for unfollow
return true ;
}
bool route_follow ( struct ap_activity * act )
static bool route_follow ( struct ap_activity * act )
{
struct account * follower = NULL ;
bool res = false ;
@ -80,11 +69,13 @@ bool route_follow( struct ap_activity* act )
const char * target = act - > object . ref ;
struct account * a = account_from_uri ( target ) ;
// Don't process follows for remote users
if ( ! a | | 0 ! = strcmp ( a - > server , g_server_name ) ) {
printf ( " Unfollow not targeted at local account. Discarding. \n " ) ;
goto success ;
}
// Get account for the follower
follower = account_from_uri ( act - > actor ) ;
if ( ! follower ) {
follower = account_fetch_from_uri ( act - > actor ) ;
@ -94,17 +85,26 @@ bool route_follow( struct ap_activity* act )
goto failed ;
}
// Add the follower
account_add_follower ( a , follower ) ;
// Create Accept activity
accept = ap_activity_create_accept ( act ) ;
char filename [ 512 ] ; snprintf ( filename , 512 , " data/outbox/%d.json " , accept - > local_id ) ;
char tmp_filename [ 512 ] ; snprintf ( tmp_filename , 512 , " %s.tmp " , filename ) ;
FILE * f = fopen ( tmp_filename , " w " ) ;
fprintf ( f , " to: %d \n " , follower - > id ) ;
ap_activity_write_to_FILE ( accept , f ) ;
fclose ( f ) ;
rename ( tmp_filename , filename ) ;
ap_activity_save ( accept ) ;
struct outbox_envelope * env = outbox_envelope_new ( ) ;
env - > activity_id = accept - > local_id ;
env - > account_id = follower - > id ;
outbox_envelope_save ( env ) ;
outbox_envelope_free ( env ) ;
// Create notification for follow
struct notification * note = notification_new ( ) ;
note - > type = nt_follow ;
note - > account_id = follower - > id ;
note - > created_at = time ( NULL ) ;
notification_save ( note ) ;
notification_free ( note ) ;
success :
res = true ;
@ -113,15 +113,33 @@ cleanup:
account_free ( a ) ;
account_free ( follower ) ;
exit ( 0 ) ;
return res ;
failed :
res = false ;
goto cleanup ;
}
bool route_activity ( struct ap_activity * act )
static bool route_undo_activity ( struct ap_activity * act )
{
if ( act - > object . tag ! = apaot_activity ) {
// Don't undo activities that are references
return false ;
}
if ( ! act - > object . ptr ) {
printf ( " No object in activity \n " ) ;
return false ;
}
switch ( act - > object . ptr - > type ) {
case apat_follow : return route_undo_follow ( act ) ;
default :
printf ( " Unhandled object activity type %d in undo \n " , act - > object . ptr - > type ) ;
return false ;
} ;
return false ;
}
static bool route_activity ( struct ap_activity * act )
{
switch ( act - > type ) {
case apat_undo : return route_undo_activity ( act ) ;
@ -132,7 +150,7 @@ bool route_activity( struct ap_activity* act )
return false ;
}
bool process_one ( )
static bool process_one ( )
{
// Items requiring cleanup
struct ap_activity * act = NULL ;
@ -156,9 +174,6 @@ bool process_one()
return false ;
}
// Validate signature
env - > validated = http_signature_validate ( env , " post /inbox " ) ;
// Load activity
FILE * f = fmemopen ( env - > body , strlen ( env - > body ) , " r " ) ;
act = ap_activity_from_FILE ( f ) ;
@ -167,16 +182,19 @@ bool process_one()
// Discard delete requests
if ( act - > type = = apat_delete ) {
step_tail = true ;
goto step ;
goto discard ;
}
// Validate signature
env - > validated = http_signature_validate ( env , " post /inbox " ) ;
if ( ! env - > validated ) { goto failed ; }
printf ( " Processing %d \n " , id ) ;
step_tail = route_activity ( act ) ;
finished :
printf ( " handled: %c\n " , step_tail ? ' T ' : ' F ' ) ;
printf ( " step_tail= %c\n " , step_tail ? ' T ' : ' F ' ) ;
if ( step_tail ) {
fs_list_set ( " data/inbox/TAIL " , id ) ;
result = true ;
@ -184,16 +202,17 @@ finished:
ap_activity_free ( act ) ;
ap_envelope_free ( env ) ;
printf ( " result=%c \n " , result ? ' T ' : ' F ' ) ;
return result ;
failed :
result = false ;
goto finished ;
step :
discard :
result = true ;
goto finished ;
}
bool cleanup_inbox ( )
static bool cleanup_inbox ( )
{
int tail_pos = fs_list_get ( " data/inbox/TAIL " ) ;
int dead_pos = fs_list_get ( " data/inbox/DEAD " ) ;
@ -225,15 +244,11 @@ void process_inbox()
while ( ! terminate ) {
bool activity = false ;
activity | = process_one ( ) ;
if ( ! activity ) {
printf ( " TODO: unhandled activity \n " ) ;
exit ( 1 ) ;
}
activity | = cleanup_inbox ( ) ;
if ( ! activity ) {
fflush ( stdout ) ;
sleep ( 1 0 ) ;
sleep ( 1 ) ;
}
}
}