Split json layout from ap_activity, fill out more of the ap_activity structure

master
teknomunk 1 year ago
parent 5955acaeec
commit 391049c46f

1
.gitignore vendored

@ -7,3 +7,4 @@ debug
release
data/
assets/soapbox/
backup/

@ -1 +1 @@
Subproject commit 4a6ee5f1edb61cf893a12446da7e5ba4652a8b67
Subproject commit da39f4eda56b559e54c4f50364aa28efed7699f1

@ -177,6 +177,7 @@ bool route_activity( struct ap_activity* act )
bool validate_signature( struct ap_envelope* env )
{
// TODO: validate signature
printf( "TODO: validate signature\n" );
return false;
}
@ -194,7 +195,10 @@ bool process_one()
struct ap_envelope* env = ap_envelope_from_id(id);
bool step_tail = false;
if( !env ) { return false; }
if( !env ) {
printf( "Failed to parse envelope+activity for data/inbox/%d.json\n", id );
return false;
}
validate_signature(env);
// Discard delete requests
@ -252,9 +256,14 @@ 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(10);
}
}

@ -1 +1 @@
Subproject commit d90a7bdd6d814df9c6260da5d8c7d2423675a2ff
Subproject commit 3b055f3b60cd0dde22c84e3bf5092d815f63ec13

@ -1,7 +1,7 @@
#define _GNU_SOURCE
#include "activity.h"
#include "activity/context.h"
#include "json/json.h"
#include "ffdb/fs_list.h"
#include "collections/array.h"
@ -12,52 +12,6 @@
#include <stdio.h>
#include <string.h>
static struct json_enum ap_signature_type_enum[] = {
{ "RsaSignature2017", 1 },
{ NULL, 0 },
};
static struct json_object_field ap_signature_layout[] = {
{ "type", offsetof( struct ap_signature, type ), true, &json_field_enum, ap_signature_type_enum },
{ "creator", offsetof( struct ap_signature, creator ), true, &json_field_string },
{ "created", offsetof( struct ap_signature, created ), true, &json_field_date_time },
{ "signatureValue", offsetof( struct ap_signature, value ), true, &json_field_string },
{ NULL },
};
// https://www.w3.org/TR/activitystreams-vocabulary/#h-activity-types
struct json_enum ap_activity_type_enum[] = {
{ "Undo", apat_undo },
{ "Follow", apat_follow },
{ "Delete", apat_delete },
{ "Accept", apat_accept },
{ "Create", apat_create },
{ "TentativeAccept", apat_tentative_accept },
{ "Add", apat_add },
{ "Arrive", apat_arrive },
{ "Ignore", apat_ignore },
{ "Join", apat_join },
{ "Leave", apat_leave },
{ "Like", apat_like },
{ "Offer", apat_offer },
{ "Invite", apat_invite },
{ "Reject", apat_reject },
{ "TentativeReject", apat_tentative_reject },
{ "Remove", apat_remove },
{ "Update", apat_update },
{ "View", apat_view },
{ "Listen", apat_listen },
{ "Read", apat_read },
{ "Move", apat_move },
{ "Travel", apat_travel },
{ "Announce", apat_announce },
{ "Block", apat_block },
{ "Flag", apat_flag },
{ "Dislike", apat_dislike },
{ "Question", apat_question },
{ NULL, 0 },
};
struct ap_activity* ap_activity_new()
{
struct ap_activity* act = malloc(sizeof(struct ap_activity));
@ -65,18 +19,6 @@ struct ap_activity* ap_activity_new()
return act;
}
struct ap_activity* ap_activity_from_FILE( FILE* f )
{
struct ap_activity* act = malloc(sizeof(struct ap_activity));
memset(act,0,sizeof(*act));
if( !json_read_object_layout_from_FILE( f, ap_activity_layout, act ) ) {
ap_activity_free(act);
return NULL;
}
return act;
}
struct ap_activity* ap_activity_dup( struct ap_activity* act )
{
struct ap_activity* new_act = ap_activity_new();
@ -124,10 +66,6 @@ struct ap_activity* ap_activity_dup( struct ap_activity* act )
return new_act;
}
static void* ap_activity_alloc()
{
return (void*)ap_activity_new();
}
void ap_activity_free( struct ap_activity* act )
{
if( !act ) { return; }
@ -168,58 +106,6 @@ void ap_activity_free_composite( struct ap_activity* act )
free( act->signature.creator );
free( act->signature.value );
}
static void ap_activity_free2( void* ptr )
{
ap_activity_free(ptr);
}
struct json_field_type ap_activity_type = {
.reader = json_field_object_type_reader,
.writer = json_field_object_type_writer,
.size = sizeof(struct ap_activity),
.layout = ap_activity_layout,
.alloc = ap_activity_alloc,
.free = ap_activity_free2,
};
struct json_object_field activity_ref_types[] = {
{ (char*)apaot_ref, offsetof( struct ap_activity, object.ref ), false, &json_field_string },
{ (char*)apaot_activity, offsetof( struct ap_activity, object.ptr ), false, &json_field_object_pointer, ap_activity_layout },
{ NULL },
};
struct json_object_field signature_types[] = {
{ (char*)1, offsetof( struct ap_activity, signature ), false, &json_field_object_composite, ap_signature_layout },
{ NULL },
};
struct json_object_field ap_activity_layout[] = {
{ "@context", 0, false, &json_field_fixed_string, "https://www.w3.org/ns/activitystreams" },
{ "id", offsetof( struct ap_activity, id ), true, &json_field_string },
{ "actor", offsetof( struct ap_activity, actor ), true, &json_field_string },
{ "state", offsetof( struct ap_activity, state ), false, &json_field_string },
{ "to", offsetof( struct ap_activity, to ), true, &json_field_array_of, &json_field_string },
{ "cc", offsetof( struct ap_activity, cc ), false, &json_field_array_of, &json_field_string },
{ "bcc", offsetof( struct ap_activity, bcc ), false, &json_field_array_of, &json_field_string },
{ "object", offsetof( struct ap_activity, object.tag ), false, &json_field_tagged_union, &activity_ref_types },
{ "signature", offsetof( struct ap_activity, has_signature ), false, &json_field_tagged_union, &signature_types },
{ "type", offsetof( struct ap_activity, type ), true, &json_field_enum, ap_activity_type_enum },
{ NULL, 0, true, NULL, &ap_activity_type },
};
void ap_activity_write_to_FILE( struct ap_activity* act, FILE* f )
{
struct json_writer jw = {
.f = f,
.indentation = "\t",
.indent = 0,
};
json_write_pretty_object_layout( &jw, ap_activity_layout, act );
}
struct ap_activity* ap_activity_create_accept( struct ap_activity* act )
{
@ -240,13 +126,6 @@ struct ap_activity* ap_activity_create_accept( struct ap_activity* act )
array_append( &accept->to, sizeof(char*), &new_act_actor );
accept->object.tag = apaot_activity;
accept->object.ptr = ap_activity_dup(act);
/*
accept->has_signature = 1;
accept->signature.type = apst_rsa_signature_2017;
accept->signature.creator = strdup(actor);
accept->signature.created = strdup("TBD");
accept->signature.value = strdup("TBD");
*/
return accept;
}

@ -2,6 +2,9 @@
#include "json/layout.h"
#include "activity/context.h"
#include "activity/tag.h"
#include <time.h>
enum ap_signature_type
@ -55,14 +58,43 @@ enum ap_activity_object_type {
struct ap_activity
{
struct ap_activity_context ap_context;
char* id;
char* actor;
int local_id;
int type;
char* actor;
char* context;
int context_id;
bool direct_message;
char* attributed_to;
char* content;
char* conversation;
time_t published;
char* source;
char* summary;
bool sensitive;
struct {
struct tag** items;
int count;
} tags;
struct {
char** items;
int count;
} attachments;
struct {
char** items;
int count;
} to, cc, bcc;
struct {
int tag;
union {
@ -70,6 +102,7 @@ struct ap_activity
struct ap_activity* ptr;
};
} object;
char* state;
int has_signature;

@ -0,0 +1,103 @@
#include "context.h"
#include "json/layout.h"
#include "json/json.h"
#include "collections/array.h"
#include "collections/item_type/string.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static bool context_reader( struct json_pull_parser* jpp, void* field_data, struct json_object_field* layout_field_data )
{
printf( "context_reader\n" );
struct ap_activity_context* ctx = field_data;
char* str = json_pull_parser_read_string(jpp);
if( str ) {
if( 0 != strcmp(str,"https://www.w3.org/ns/activitystreams") ) {
free(str);
return false;
}
free(str);
return true;
}
int save;
if( !json_pull_parser_begin_array(jpp,&save) ) {
return false;
}
struct collection c = {
.ptr = &ctx->extra,
.vtable = &array_iface,
.itable = &itv_string,
};
while( !json_pull_parser_end_array( jpp, &save ) ) {
str = json_pull_parser_read_string(jpp);
if( str ) {
array_append_c( c, &str );
} else {
int save2;
if( !json_pull_parser_begin_object( jpp, &save2 ) ) {
return false;
}
char* key = json_pull_parser_read_object_key(jpp);
if( 0 != strcmp("@language",key) ) {
return false;
}
free(key);
char* lang = json_pull_parser_read_string(jpp);
if( !lang ) {
return false;
}
static const char* langs[] = {
"und",
};
ctx->language = clang_unknown;
for( int i = 0; i < 1; ++i ) {
if( 0 == strcmp(langs[i],lang) ) {
ctx->language = i+1;
}
}
if( ctx->language == clang_unknown ) {
printf( "unknown language: %s\n", lang );
return false;
}
if( !json_pull_parser_end_object(jpp,&save2) ) {
printf( "Object failed\n" );
return false;
}
}
}
return true;
}
static bool context_writer( struct json_writer* jw, const char* field_name, void* field_data, struct json_object_field* layout_field_data )
{
json_write_field_name( jw, field_name );
struct ap_activity_context* ctx = field_data;
int items = 1 + ctx->extra.count + (ctx->language ? 1 : 0 );
if( items == 1 ) {
json_write_string( jw->f, "https://www.w3.org/ns/activitystreams" );
} else {
printf( "TODO: context_writer, handle array\n" );
exit(1);
}
}
struct json_field_type ap_activity_context_type = {
.reader = context_reader,
.writer = context_writer,
.size = sizeof(struct ap_activity_context)
};

@ -0,0 +1,22 @@
#pragma once
enum context_language
{
clang_unspecified = 0,
clang_undefined = 1,
clang_unknown = 999999,
};
struct ap_activity_context
{
struct {
char** items;
int count;
} extra;
int language;
};
extern struct json_field_type ap_activity_context_type;

@ -0,0 +1,146 @@
#include "../activity.h"
#include "json/layout.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
static struct json_enum ap_signature_type_enum[] = {
{ "RsaSignature2017", 1 },
{ NULL, 0 },
};
static struct json_object_field ap_signature_layout[] = {
{ "type", offsetof( struct ap_signature, type ), true, &json_field_enum, ap_signature_type_enum },
{ "creator", offsetof( struct ap_signature, creator ), true, &json_field_string },
{ "created", offsetof( struct ap_signature, created ), true, &json_field_date_time },
{ "signatureValue", offsetof( struct ap_signature, value ), true, &json_field_string },
{ NULL },
};
// https://www.w3.org/TR/activitystreams-vocabulary/#h-activity-types
struct json_enum ap_activity_type_enum[] = {
{ "Undo", apat_undo },
{ "Follow", apat_follow },
{ "Delete", apat_delete },
{ "Accept", apat_accept },
{ "Create", apat_create },
{ "TentativeAccept", apat_tentative_accept },
{ "Add", apat_add },
{ "Arrive", apat_arrive },
{ "Ignore", apat_ignore },
{ "Join", apat_join },
{ "Leave", apat_leave },
{ "Like", apat_like },
{ "Offer", apat_offer },
{ "Invite", apat_invite },
{ "Reject", apat_reject },
{ "TentativeReject", apat_tentative_reject },
{ "Remove", apat_remove },
{ "Update", apat_update },
{ "View", apat_view },
{ "Listen", apat_listen },
{ "Read", apat_read },
{ "Move", apat_move },
{ "Travel", apat_travel },
{ "Announce", apat_announce },
{ "Block", apat_block },
{ "Flag", apat_flag },
{ "Dislike", apat_dislike },
{ "Question", apat_question },
{ NULL, 0 },
};
struct json_object_field activity_ref_types[] = {
{ (char*)apaot_ref, offsetof( struct ap_activity, object.ref ), false, &json_field_string },
{ (char*)apaot_activity, offsetof( struct ap_activity, object.ptr ), false, &json_field_object_pointer, ap_activity_layout },
{ NULL },
};
struct json_object_field signature_types[] = {
{ (char*)1, offsetof( struct ap_activity, signature ), false, &json_field_object_composite, ap_signature_layout },
{ NULL },
};
struct json_object_field ap_activity_layout[] = {
{ "@context", offsetof( struct ap_activity, ap_context ), false, &ap_activity_context_type },
{ "id", offsetof( struct ap_activity, id ), true, &json_field_string },
{ "actor", offsetof( struct ap_activity, actor ), true, &json_field_string },
{ "state", offsetof( struct ap_activity, state ), false, &json_field_string },
{ "state", offsetof( struct ap_activity, state ), false, &json_field_string },
{ "content", offsetof( struct ap_activity, content ), false, &json_field_string },
{ "conversation", offsetof( struct ap_activity, conversation ), false, &json_field_string },
{ "published", offsetof( struct ap_activity, published ), false, &json_field_date_time },
{ "sensitive", offsetof( struct ap_activity, sensitive ), false, &json_field_bool },
{ "source", offsetof( struct ap_activity, source ), false, &json_field_string },
{ "summary", offsetof( struct ap_activity, summary), false, &json_field_string },
{ "tag", offsetof( struct ap_activity, tags ), false, &json_field_array_of, &ap_activity_tag_type },
{ "context", offsetof( struct ap_activity, context ), false, &json_field_string },
{ "context_id", offsetof( struct ap_activity, context_id ), false, &json_field_integer },
{ "attributedTo", offsetof( struct ap_activity, attributed_to ), false, &json_field_string },
{ "directMessage", offsetof( struct ap_activity, direct_message ), false, &json_field_bool },
{ "attachment", offsetof( struct ap_activity, attachments ), false, &json_field_array_of, &json_field_string },
{ "to", offsetof( struct ap_activity, to ), true, &json_field_array_of, &json_field_string },
{ "cc", offsetof( struct ap_activity, cc ), false, &json_field_array_of, &json_field_string },
{ "bcc", offsetof( struct ap_activity, bcc ), false, &json_field_array_of, &json_field_string },
{ "object", offsetof( struct ap_activity, object.tag ), false, &json_field_tagged_union, &activity_ref_types },
{ "signature", offsetof( struct ap_activity, has_signature ), false, &json_field_tagged_union, &signature_types },
{ "type", offsetof( struct ap_activity, type ), true, &json_field_enum, ap_activity_type_enum },
{ NULL, 0, true, NULL, &ap_activity_type },
};
static void ap_activity_free_shim( void* ptr )
{
ap_activity_free(ptr);
}
static void* ap_activity_alloc()
{
return (void*)ap_activity_new();
}
struct json_field_type ap_activity_type = {
.reader = json_field_object_type_reader,
.writer = json_field_object_type_writer,
.size = sizeof(struct ap_activity),
.layout = ap_activity_layout,
.alloc = ap_activity_alloc,
.free = ap_activity_free_shim,
};
struct ap_activity* ap_activity_from_FILE( FILE* f )
{
struct ap_activity* act = malloc(sizeof(struct ap_activity));
memset(act,0,sizeof(*act));
if( !json_read_object_layout_from_FILE( f, ap_activity_layout, act ) ) {
ap_activity_free(act);
return NULL;
}
return act;
}
void ap_activity_write_to_FILE( struct ap_activity* act, FILE* f )
{
struct json_writer jw = {
.f = f,
.indentation = "\t",
.indent = 0,
};
json_write_pretty_object_layout( &jw, ap_activity_layout, act );
}

@ -0,0 +1,50 @@
#include "tag.h"
#include "json/layout.h"
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
static struct json_enum ap_activity_tag_enum[] = {
{ "Mention", aptag_mention },
{ NULL, 0 },
};
static struct json_object_field ap_activity_tag_layout[] = {
{ "type", offsetof( struct ap_activity_tag, type ), true, &json_field_enum, ap_activity_tag_enum },
{ "href", offsetof( struct ap_activity_tag, href ), false, &json_field_string },
{ "name", offsetof( struct ap_activity_tag, name ), false, &json_field_string },
{ NULL },
};
void ap_activity_tag_free( struct ap_activity_tag* tag )
{
if( !tag ) { return; }
free(tag->href);
free(tag->name);
memset(tag,0,sizeof(*tag));
free(tag);
}
static void* alloc()
{
struct ap_activity_tag* ptr = malloc(sizeof(struct ap_activity_tag));
memset(ptr,0,sizeof(*ptr));
return ptr;
}
static void free_shim( void* ptr )
{
ap_activity_tag_free(ptr);
}
struct json_field_type ap_activity_tag_type = {
.reader = json_field_object_type_reader,
.writer = json_field_object_type_writer,
.size = sizeof( struct ap_activity_tag ),
.layout = ap_activity_tag_layout,
.alloc = alloc,
.free = free_shim,
};

@ -0,0 +1,16 @@
#pragma once
enum {
aptag_mention = 1,
};
struct ap_activity_tag
{
int type;
char* href;
char* name;
};
extern struct json_field_type ap_activity_tag_type;

@ -25,7 +25,7 @@ struct ap_envelope* ap_envelope_from_id( int id )
struct ap_envelope* env = malloc(sizeof(struct ap_envelope));
memset(env,0,sizeof(struct ap_envelope));
if( !json_read_object_layout_from_file( filename, envelope_layout, env ) ) {
if( !json_read_object_layout_from_file_ex( filename, envelope_layout, env, jrol_flag_dont_ignore_unhandled ) ) {
ap_envelope_free(env);
return NULL;
}

Loading…
Cancel
Save