#include "../object.h" #include "json/layout.h" #include #include #include #include extern struct json_field_type ap_signature_composite_type; extern struct json_field_type ap_activity_source_type; // https://www.w3.org/TR/activitystreams-vocabulary/#h-activity-types struct json_enum ap_object_type_enum[] = { { "Undo", ap_Undo }, { "Follow", ap_Follow }, { "Delete", ap_Delete }, { "Accept", ap_Accept }, { "Create", ap_Create }, { "TentativeAccept", ap_TentativeAccept }, { "Add", ap_Add }, { "Arrive", ap_Arrive }, { "Ignore", ap_Ignore }, { "Join", ap_Join }, { "Leave", ap_Leave }, { "Like", ap_Like }, { "Offer", ap_Offer }, { "Invite", ap_Invite }, { "Reject", ap_Reject }, { "TentativeReject", ap_TentativeReject }, { "Remove", ap_Remove }, { "Update", ap_Update }, { "View", ap_View }, { "Listen", ap_Listen }, { "Read", ap_Read }, { "Move", ap_Move }, { "Travel", ap_Travel }, { "Announce", ap_Announce }, { "Block", ap_Block }, { "Flag", ap_Flag }, { "Dislike", ap_Dislike }, { "EmojiReact", pleroma_EmojiReact }, { "Note", ap_Note }, { "Question", ap_Question }, { "Document", ap_Document }, { "Image", ap_Image }, { "Tombstone", ap_Tombstone }, { "Person", ap_Person }, { "Service", ap_Service }, { "Application", ap_Application }, { "Group", ap_Group }, { "Organization", ap_Organization }, { "Collection", ap_Collection }, { "CollectionPage", ap_CollectionPage }, { "OrderedCollection", ap_OrderedCollection }, { "OrderedCollectionPage", ap_OrderedCollectionPage }, // Musicbox Types { "Track", mb_Track }, { "Album", mb_Album }, // Forge Types // Schema Types { "PropertyValue", schema_PropertyValue }, { NULL, 0 }, }; extern struct json_field_type ap_object_ptr_or_ref_type; struct json_tagged_union_typelist signature_types[] = { { .tag_value = 1, .offset = offsetof( struct ap_object, signature ), .type = &ap_signature_composite_type, }, JSON_TAGGED_UNION_TYPELIST_END, }; extern struct json_field_type endpoints_type; extern struct json_field_type image_type; extern struct json_field_type capabilities_type; #define OBJ_TYPE struct ap_public_key static struct json_object_field ap_public_key_layout[] = { JSON_FIELD_STRING( id, true ), JSON_FIELD_STRING( owner, true ), { .key = "publicKeyPem", .offset = offsetof( OBJ_TYPE, public_key ), .required = true, .type = &json_field_string, }, JSON_FIELD_END, }; #undef OBJ_TYPE void ap_public_key_free( struct ap_public_key* pk ) { if( !pk ) { return; } free( pk->id ); free( pk->owner ); free( pk->public_key ); free( pk ); } JSON_FIELD_TYPE_OBJECT_LAYOUT_WITH_DEFAULTS( ap_public_key ); #define OBJ_TYPE struct ap_object struct json_object_field ap_object_layout[] = { { .key = "@context", .offset = offsetof( OBJ_TYPE, ap_context ), .required = false, .type = &ap_activity_context_type }, JSON_FIELD_STRING(id,false), JSON_FIELD_STRING(actor,false), JSON_FIELD_STRING(name,false), JSON_FIELD_STRING(state,false), JSON_FIELD_STRING(inbox,false), JSON_FIELD_STRING(outbox,false), { .key = "preferredUsername", .offset = offsetof( OBJ_TYPE, preferred_username ), .required = false, .type = &json_field_string, }, JSON_FIELD_STRING(url,false), { .key = "endpoints", .offset = 0, .required = false, .type = &endpoints_type, }, JSON_FIELD_STRING( featured, false ), JSON_FIELD_STRING( following, false ), JSON_FIELD_STRING( followers, false ), { .key = "icon", .offset = offsetof( OBJ_TYPE, avatar ), .required = false, .type = &image_type, }, { .key = "image", .offset = offsetof( OBJ_TYPE, banner ), .required = false, .type = &image_type, }, { .key = "capabilities", .offset = 0, .required = false, .type = &capabilities_type, }, JSON_FIELD_BOOL( discoverable, false ), { .key = "manuallyApprovesFollowers", .offset = offsetof( OBJ_TYPE, manually_approves_followers ), .required = false, .type = &json_field_bool, }, { .key = "publicKey", .offset = offsetof( OBJ_TYPE, public_key ), .required = false, .type = &ap_public_key_type, }, { .key = "content", .offset = offsetof( OBJ_TYPE, content ), .required = false, .type = &ap_activity_source_type }, JSON_FIELD_STRING(conversation,false), JSON_FIELD_DATETIME(published,false), { .key = "sensitive", .offset = offsetof( OBJ_TYPE, sensitive ), .required = false, .type = &json_field_bool_or_null }, { .key = "source", .offset = offsetof( OBJ_TYPE, source ), .required = false, .type = &ap_activity_source_type }, JSON_FIELD_STRING(summary,false), { .key = "inReplyTo", .offset = offsetof( OBJ_TYPE, in_reply_to ), .required = false, .type = &json_field_string }, { .key = "tag", .offset = offsetof( OBJ_TYPE, tags ), .required = false, .type = &json_field_array_of, .allow_drop_empty_array = true, .array_item_type = &ap_activity_tag_type }, { .key = "alsoKnownAs", .offset = offsetof( OBJ_TYPE, also_known_as ), .required = false, .allow_drop_empty_array = true, .type = &json_field_array_of, .array_item_type = &json_field_string, }, JSON_FIELD_STRING(context,false), { .key = "attributedTo", .required = false, .offset = offsetof(OBJ_TYPE,attributed_to), .type = &json_field_string, }, JSON_FIELD_STRING( target, false ), { .key = "directMessage", .offset = offsetof( OBJ_TYPE, direct_message ), .required = false, .type = &json_field_bool }, { .key = "attachment", .offset = offsetof( OBJ_TYPE, attachments ), .required = false, .allow_drop_empty_array = true, .type = &json_field_array_of, .array_item_type = &ap_attachment_type }, { .key = "to", .offset = offsetof( OBJ_TYPE, to ), .required = false, .allow_drop_empty_array = true, .type = &json_field_single_or_array_of, .array_item_type = &json_field_string, }, { .key = "cc", .offset = offsetof( OBJ_TYPE, cc ), .required = false, .allow_drop_empty_array = true, .type = &json_field_single_or_array_of, .array_item_type = &json_field_string, }, { .key = "bcc", .offset = offsetof( OBJ_TYPE, bcc ), .required = false, .allow_drop_empty_array = true, .type = &json_field_single_or_array_of, .array_item_type = &json_field_string, }, { .key = "object", .offset = offsetof( OBJ_TYPE, object ), .required = false, .type = &ap_object_ptr_or_ref_type, }, { .key = "signature", .offset = offsetof( OBJ_TYPE, has_signature ), .required = false, .type = &json_field_tagged_union, .tagged_item_types = signature_types }, { .key = "first", .offset = offsetof( OBJ_TYPE, first ), .required = false, .type = &ap_object_ptr_or_ref_type, }, JSON_FIELD_STRING( next, false ), JSON_FIELD_STRING( prev, false ), { .key = "partOf", .offset = offsetof( OBJ_TYPE, part_of ), .required = false, .type = &json_field_string, }, { .key = "totalItems", .offset = offsetof( struct ap_object, total_items ), .required = false, .type = &json_field_integer, }, { .key = "items", .offset = offsetof( OBJ_TYPE, collection_items ), .allow_drop_empty_array = true, .type = &json_field_array_of, .array_item_type = &ap_object_ptr_or_ref_type, }, JSON_FIELD_ENUM( type, ap_object_type_enum, true ), JSON_FIELD_END, }; #undef OBJ_TYPE JSON_FIELD_TYPE_OBJECT_LAYOUT_WITH_DEFAULTS( ap_object ); struct ap_object* ap_object_from_FILE( FILE* f ) { struct ap_object* act = malloc(sizeof(struct ap_object)); memset(act,0,sizeof(*act)); if( !json_read_object_layout_from_FILE( f, ap_object_layout, act ) ) { ap_object_free(act); return NULL; } return act; } struct ap_object* ap_object_from_file( const char* filename ) { FILE* f = fopen(filename,"r"); if( !f ) { return NULL; } struct ap_object* obj = ap_object_from_FILE(f); return obj; } void ap_object_write_to_FILE( struct ap_object* obj, FILE* f ) { struct json_writer jw = { .f = f, .indentation = "\t", .indent = 0, }; if( !obj ) { fprintf( f, "null" ); return; } json_write_pretty_object_layout( &jw, ap_object_layout, obj ); }