Merge in latest ap and json libraries, switch to latest builder, expand status media beyond URL, fix command handling, changes for -Wall, format.h->util/format.h, remove dead code

master
teknomunk 1 year ago
parent bf37930623
commit ea1bcff61b

3
.gitmodules vendored

@ -25,3 +25,6 @@
[submodule "src/rsa-signature-2017"]
path = src/rsa-signature-2017
url = https://gitea.polaris-1.work/teknomunk/rsa-signature-2017.git
[submodule "src/src/reflect"]
path = src/reflect
url = https://gitea.polaris-1.work/teknomunk/reflect.git

@ -7,8 +7,8 @@ find src | grep -E "\.template$" | while read FILE; do
ruby src/embed.rb "$FILE"
done
ruby tools/builder/build.rb --code src
mv src.bin apogee.debug
ruby tools/builder/build.rb src/apogee.build.json
mv obj/apogee.bin apogee.debug
cp apogee.debug{,.tmp}
mv apogee.debug.tmp apogee
strip apogee

@ -1 +1 @@
Subproject commit eb512d0d70a3095eed12c4cb866ffc9215b95cfe
Subproject commit 7f73d77dd53ce619d2000bec8b5a706b3ba1b366

@ -3,7 +3,7 @@
// Submodules
#include "http/server/request.h"
#include "collections/array.h"
#include "format.h"
#include "util/format.h"
#include "ap/object.h"
// Model
@ -93,7 +93,7 @@ bool route_ap_outbox( struct http_request* req )
if( !page_str || (1 != sscanf(page_str,"%d",&page) ) || page < 0 ) { goto failed; }
struct ap_object* outbox_page = account_ap_outbox_page( owner_account, page );
if( !outbox_page ) { return false; }
if( !outbox_page ) { goto failed; }
http_request_send_headers( req, 200, "application/ld+json", true );
FILE* f = http_request_get_response_body( req );
@ -102,6 +102,7 @@ bool route_ap_outbox( struct http_request* req )
ap_object_free(outbox_page);
}
goto success;
failed:
result = false;
goto cleanup;
@ -111,6 +112,6 @@ success:
cleanup:
account_free(owner_account);
return true;
return result;
}

@ -2,6 +2,7 @@
#include "http/server/request.h"
#include "json/layout.h"
#include "json/json.h"
#include "http/query.h"
#include "model/account.h"
@ -35,7 +36,7 @@ success:
result = true;
cleanup:
free(id_str);
return true;
return result;
failed:
result = false;
goto cleanup;

@ -41,7 +41,7 @@ bool handle_mastodon_api_apps( struct http_request* req )
if( !fp ) { return false; }
char* key;
while( key = form_pull_parser_read_key( fp ) ) {
while(( key = form_pull_parser_read_key( fp ) )) {
if( 0 == strcmp( "client_name", key ) ) {
data.client_name = strdup( form_pull_parser_read_value(fp) );
} else if( 0 == strcmp( "redirect_uris", key ) ) {

@ -1,7 +1,7 @@
#include "emoji.h"
#include "http/server/request.h"
#include "format.h"
#include "util/format.h"
#include "model/server.h"
#include "model/emoji.h"
@ -25,7 +25,7 @@ bool route_custom_emojis( struct http_request* req )
DIR* d = opendir( "data/emoji" );
struct dirent* ent;
bool first = true;
while( ent = readdir(d) ) {
while(( ent = readdir(d) )) {
if( ent->d_name[0] != '.' && !index(ent->d_name,' ') ) {
if( !first ) {
fprintf( f, "," );

@ -74,7 +74,6 @@ bool handle_notifications( struct http_request* req )
for( int note_id = note_count; (notes.count < params.limit) && ( note_id > params.since_id ); note_id -= 1 ) {
struct notification* n = notification_from_id(note_id);
bool include = true;
// Apply filters
if( !n ) { goto exclude; }
@ -82,6 +81,7 @@ bool handle_notifications( struct http_request* req )
// if( n->muted && !params.with_muted ) { goto exclude; }
}
goto include;
include:
array_append( &notes, sizeof(void*), &n );
continue;

@ -5,7 +5,7 @@
#include "json/json.h"
#include "json/layout.h"
#include "collections/array.h"
#include "format.h"
#include "util/format.h"
// Model
#include "model/server.h"
@ -123,9 +123,7 @@ bool handle_post( struct http_request* req, struct account* a )
#undef OBJ_TYPE
FILE* data = http_request_get_request_data( req );
if( !json_read_object_layout_from_FILE( data, layout, &params ) ) {
return false;
}
if( !json_read_object_layout_from_FILE( data, layout, &params ) ) { goto failed; }
s = malloc(sizeof(struct status));
memset(s,0,sizeof(*s));
@ -178,12 +176,15 @@ bool handle_repost( struct http_request* req, struct status* s )
{
bool result = false;
struct account* owner = account_from_id(owner_account_id);
if( !owner ) { goto failed; }
// Federate
struct status* repost = account_announce( owner, s, NULL, NULL );
if( !repost ) { goto failed; }
// Show the new status as the response
show_status( req, repost );
goto success;
success:
result = true;
cleanup:
@ -306,4 +307,5 @@ success:
goto cleanup;
failed:
result = false;
goto cleanup;
}

@ -71,9 +71,9 @@ bool handle_timeline( struct http_request* req, int timeline_id )
int count = 0;
int max_loops = 5;
load_statuses:
printf( "loading offset=%d,limit=%d\n", offset, params.limit );
//printf( "loading offset=%d,limit=%d\n", offset, params.limit );
count = timeline_load_statuses( tl, offset, params.limit, ss );
printf( "count=%d\n", count );
//printf( "count=%d\n", count );
if( count == 0 ) { goto done; }
// Filter

@ -1,7 +1,7 @@
#include "cli.h"
// Submodules
#include "format.h"
#include "util/format.h"
#include "json/json.h"
#include "ap/object.h"
@ -112,6 +112,8 @@ static bool handle_command_status_import( struct cli_request* req )
printf( "Status id=%d\n", s->id );
status_free(s);
}
return true;
}
static bool handle_command_status_sync( struct cli_request* req )
{
@ -152,6 +154,7 @@ static bool handle_command_reindex( struct cli_request* req )
if( res != 1 ) { return !!res; }
account_reindex();
return true;
}
static bool handle_command_test( struct cli_request* req )
{
@ -221,7 +224,7 @@ done:
goto cleanup;
}
void handle_command( char** argv, int argc )
bool handle_command( char** argv, int argc )
{
struct cli_request req = {
.argv = &argv[1],
@ -239,7 +242,7 @@ void handle_command( char** argv, int argc )
|| handle_command_test(&req)
|| handle_command_update(&req)
|| handle_command_gc(&req)
) { return; }
) { return true; }
printf( "Unknown command %s\n", argv[1] );
return false;
}

@ -1,4 +1,6 @@
#pragma once
void handle_command( char** argv, int argc );
#include <stdbool.h>
bool handle_command( char** argv, int argc );

@ -5,7 +5,7 @@
#include "json/json.h"
#include "ffdb/fs_list.h"
#include "collections/array.h"
#include "format.h"
#include "util/format.h"
#include "ap/object.h"
// Model
@ -217,6 +217,7 @@ static bool route_emoji_react( struct ap_object* act )
if( !s || !reactor ) { goto failed; }
status_add_react( s, act->content.content, reactor );
goto discard;
discard:
result = true;
goto cleanup;
@ -294,7 +295,6 @@ static bool route_move( struct ap_object* act )
if( !a ) { goto discard; }
// Verify the target is an existing alias
bool is_alias = false;
for( int i = 0; i < a->aliases.count; ++i ) {
if( 0 == strcmp( a->aliases.items[i], act->target ) ) {
goto is_alias;
@ -302,9 +302,8 @@ static bool route_move( struct ap_object* act )
}
goto failed;
is_alias:
account_move( a, act->target );
goto discard;
discard:
result = true;
goto cleanup;
@ -326,7 +325,7 @@ static bool route_create( struct ap_object* act )
// Requires an object
if( act->object.tag != apaot_activity ) {
printf( "TODO: fetch activity from %s\n", act->object.ref );
return false;
goto failed;
}
struct ap_object* obj = act->object.ptr;
@ -344,7 +343,6 @@ static bool route_create( struct ap_object* act )
if( tag->type != aptag_mention ) { continue; }
if( 0 == strcmp(tag->href, owner_url) ) {
mentions_me = true;
int id = owner_account_id;
goto check_is_follower;
}
}

@ -72,9 +72,11 @@ cleanup:
discard:
result = true;
goto cleanup;
/*
failed:
result = false;
goto cleanup;
*/
}

@ -15,7 +15,6 @@ bool route_follow( struct ap_object* act )
{
struct account* follower = NULL;
bool res = false;
struct ap_object* accept = NULL;
const char* target = act->object.ref;
struct account* a = account_from_uri( target );
@ -46,6 +45,7 @@ bool route_follow( struct ap_object* act )
// Create Accept activity
activity_accept( act, follower->id );
goto success;
success:
res = true;
goto cleanup;

@ -1,8 +1,12 @@
// Submodules
#include "http/server/request.h"
#include "format.h"
#include "util/format.h"
// Model
#include "model/media.h"
// Controller
#include "controller/mastodon_api.h"
#include "controller/pleroma_api.h"
#include "controller/oauth.h"
@ -13,6 +17,7 @@
#include "controller/activity_pub.h"
#include "controller/api/emoji.h"
// Standard Library
#include <string.h>
#include <stdlib.h>
@ -187,6 +192,8 @@ bool route_request( struct http_request* req )
} else {
return route_asset(req);
}
return false;
}
if( http_request_route( req, "/api/v1/" ) ) {

@ -6,7 +6,7 @@
#include "json/json.h"
#include "http/query.h"
#include "ffdb/fs_list.h"
#include "format.h"
#include "util/format.h"
#include "ap/object.h"
// Model
@ -52,7 +52,7 @@ bool http_request_write_multipart_to_FILE( struct http_request* req, FILE* f, ch
size_t n;
// lineptr should match the contents of the Content-Type boundary= parametera
ssize_t res = getline_stripped( &line, &n, data );
/*ssize_t res = */getline_stripped( &line, &n, data );
boundary = aformat( "\r\n%s", line );
int boundary_size = strlen(boundary);
@ -75,6 +75,7 @@ bool http_request_write_multipart_to_FILE( struct http_request* req, FILE* f, ch
if( rb->count >= rb->limit ) { return false; }
rb->data[ ( rb->head + rb->count ) % rb->limit ] = ch;
rb->count += 1;
return true;
}
bool ring_buffer_pop_front( struct ring_buffer* rb, char* ch )
{
@ -86,7 +87,6 @@ bool http_request_write_multipart_to_FILE( struct http_request* req, FILE* f, ch
}
bool ring_buffer_compare_prefix( struct ring_buffer* rb, const char* str )
{
int i = 0;
for( int i = 0; i < rb->count; ++i, ++str ) {
if( !*str ) {
// String matches start of buffer
@ -102,8 +102,6 @@ bool http_request_write_multipart_to_FILE( struct http_request* req, FILE* f, ch
}
memset( buffer.data, 0, boundary_size );
int pos = 0;
bool filled = false;
// Eat all header data
while( getline_stripped( &line, &n, data ) > 0 ) {

@ -30,7 +30,7 @@ static bool handle_oauth_authorize( struct http_request* req )
// Parse query parameters
{
const char* key;
while( key = http_request_route_query_key(req) ) {
while(( key = http_request_route_query_key(req) )) {
if( 0 == strcmp(key,"client_id") ) {
client_id = strdup(http_request_route_query_value(req));
} else if( 0 == strcmp(key,"redirect_uri") ) {
@ -54,7 +54,7 @@ static bool handle_oauth_authorize( struct http_request* req )
char* resume = scope;
char* item;
while( item = strtok_r( NULL, " ", &resume ) ) {
while(( item = strtok_r( NULL, " ", &resume ) )) {
if( 0 == strcmp(item,"read") ) {
scopes.read = true;
} else if( 0 == strcmp(item,"write") ) {
@ -114,7 +114,7 @@ static bool handle_oauth_do_authorize( struct http_request* req )
}
char* key;
while( key = form_pull_parser_read_key( fp ) ) {
while(( key = form_pull_parser_read_key( fp ) )) {
if( 0 == strcmp(key,"password") ) {
password = strdup(form_pull_parser_read_value(fp));
} else if( 0 == strcmp(key,"state") ) {
@ -211,7 +211,7 @@ static bool handle_oauth_get_token( struct http_request* req )
char* key;
// TODO: extend form parser to use a data layout
while( key = form_pull_parser_read_key( fp ) ) {
while(( key = form_pull_parser_read_key( fp ) )) {
if( 0 == strcmp(key,"grant_type") ) {
data.grant_type = strdup(form_pull_parser_read_value(fp));

@ -128,7 +128,7 @@ static bool process_envelope( struct outbox_envelope* env )
printf( "Submitted successfully\n" );
goto discard;
} else {
printf( "\nServer returned status code %d\n", status_code );
printf( "\nServer returned status code %ld\n", status_code );
if( env->retry_after ) {
env->retries += 1;
}

@ -8,7 +8,6 @@
#include "model/server.h"
// View
#include "view/layout.h"
// Standard Library
#include <stdio.h>
@ -57,18 +56,19 @@ static bool handle_followers( struct http_request* req )
ap_object_write_to_FILE( obj, f );
ap_object_free(obj);
}
goto success;
succeded:
cleanup:
account_free( owner_account );
return result;
success:
result = true;
goto cleanup;
failed:
printf( "! failed\n" );
result = false;
goto cleanup;
cleanup:
account_free( owner_account );
return result;
}
static bool handle_following( struct http_request* req )
{
@ -101,7 +101,8 @@ static bool handle_following( struct http_request* req )
ap_object_free(obj);
}
succeded:
goto success;
success:
result = true;
goto cleanup;
failed:

@ -50,6 +50,8 @@ static bool handle_reactions( struct http_request* req, struct status* s )
printf( "TODO: get who react information\n" );
return false;
}
return false;
}
// Route: /api/v1/pleroma/statuses

@ -2,7 +2,7 @@
// Submodules
#include "http/server/header.h"
#include "format.h"
#include "util/format.h"
// Model
#include "model/inbox_envelope.h"
@ -121,7 +121,6 @@ failed:
bool test_crypto()
{
bool result = true;
if( !test_signatures() ) { printf( "[FAIL] test_signatures()\n" ); return false; }
if( !test_http_signature() ) { printf( "[FAIL] test_http_signature()\n" ); return false; }
if( !test_http_signature_2() ) { printf( "[FAIL] test_http_signature_2()\n" ); return false; }

@ -1,7 +1,9 @@
#include "webfinger.h"
// Submodules
#include "http/server/request.h"
// Standard Library
#include <string.h>
#include <stdlib.h>
@ -12,7 +14,7 @@ bool route_wellknown_webfinger( struct http_request* req )
char* resource;
char* resource_orig;
while( key = http_request_route_query_key( req ) ) {
while(( key = http_request_route_query_key( req ) )) {
if( 0 == strcmp(key,"resource") ) {
resource_orig = resource = strdup(http_request_route_query_value(req) );
} else {
@ -22,7 +24,7 @@ bool route_wellknown_webfinger( struct http_request* req )
char* server;
strtok_r( resource, ":", &resource );
char* account_name = strtok_r( resource, "@", &server );
/*char* account_name = */strtok_r( resource, "@", &server );
// Verify the server name matches this instance
// if( 0 != strcmp( server, this_server_hostname() ) ) { return false; }

@ -1,19 +1,20 @@
#define _GNU_SOURCE
// Submodules
#include "ffdb/fs_list.h"
#include "ffdb/trie.h"
#include "ap/object.h"
//#include "ap/object/rsa_signature_2017.h"
#include "collections/array.h"
#include "util/format.h"
// Model
#include "model/account.h"
#include "model/activity.h"
#include "model/outbox_envelope.h"
#include "model/status.h"
#include "model/server.h"
#include "format.h"
// Standard Library
#include <string.h>
#include <stdlib.h>
#include <time.h>

@ -1 +1 @@
Subproject commit 2126183e06ae69fc29561f1d8a3d500cca66d5e2
Subproject commit 819e69f095f203dc44846f5d8a9e9b685a57c838

@ -1,7 +1 @@
#pragma once
const char* format( char* buffer, int size, const char* f, ... );
char* aformat( const char* f, ... );
char* safe_strdup( const char* str );
void mkdir_p( const char* ch, int mode );
#include "util/format.h"

@ -1 +1 @@
Subproject commit 9b1a1397a4e030ae7b42d2c27445b36073f9225e
Subproject commit 4a87d9f268e91e22a377c82d2d25faefebd928ba

@ -1 +1 @@
Subproject commit 95ced0973dd1d8d6068a16f678d0060cdc1a829e
Subproject commit c29aaf998512a6789833b4d0c394e3ba9c652eb6

@ -79,7 +79,6 @@ bool run_everything( struct app_args* args )
}
//*/
int code = 0;
if( !run_webserver(args) ) { return false; }
return true;
@ -94,12 +93,13 @@ int main( int argc, char* argv[] )
signal(SIGINT, handle_ctrl_c);
signal(SIGPIPE, SIG_IGN);
app_args_new( argc, argv );
if( !g_server ) {
if( !app_args_new( argc, argv ) ) {
return 1;
}
int code = 0;
printf( "section = %d\n", g_server->section );
fflush(stdout);
switch(g_server->section) {
case 0: code = !run_webserver(g_server); break;
case 1: process_inbox(); break;
@ -111,7 +111,6 @@ int main( int argc, char* argv[] )
default: code = !run_everything(g_server); break;
}
exit:
curl_global_cleanup();
app_args_release(g_server);

@ -7,7 +7,7 @@
#include "ffdb/fs_list.h"
#include "ffdb/hash_index.h"
#include "ffdb/trie.h"
#include "format.h"
#include "util/format.h"
#include "collections/array.h"
#include "ap/object.h"
@ -17,6 +17,7 @@
#include "model/crypto/keys.h"
#include "model/notification.h"
// View
#include "view/api/Relationship.h"
// Stdlib
@ -28,16 +29,6 @@
#include <time.h>
bool pull_remote_file( const char* filename, const char* uri );
static const char* safe( const char* value, const char* other )
{
if( !value ) { return other; }
return value;
}
static const char* b(bool value)
{
return value ? "true" : "false";
}
static struct json_enum account_types_enum[] = {
{ "owner", at_owner },
{ "bot", at_bot },
@ -198,8 +189,6 @@ struct account* account_from_uri( const char* uri )
{
if( !uri ) { return NULL; }
struct account* result = NULL;
// Handle owner as special case
char buffer[512];
snprintf( buffer, 512, "https://%s/owner/actor", g_server->domain );

@ -1,7 +1,7 @@
#include "model/account.h"
// Submodules
#include "format.h"
#include "util/format.h"
#include "ffdb/trie.h"
#include "collections/array.h"
#include "ap/object.h"

@ -2,7 +2,7 @@
// Submodules
#include "collections/array.h"
#include "format.h"
#include "util/format.h"
#include "ap/object.h"
// Standard Library

@ -1,7 +1,7 @@
#include "model/account.h"
// Submodules
#include "format.h"
#include "util/format.h"
#include "ffdb/trie.h"
#include "collections/array.h"
#include "ap/object.h"
@ -20,7 +20,7 @@
void account_deliver_activity( struct account* a, struct ap_object* act, struct outbox_envelope_list* oel )
{
if( a->defunct ) {
printf( "Account %s id defunct, not delivering activity\n" );
printf( "Account %s id defunct, not delivering activity\n", a->account_url );
return;
}
printf( "Delivering activity %s to account %s\n", act->id, a->account_url );
@ -149,6 +149,7 @@ struct status* account_announce( struct account* a, struct status* original_post
status_add_repost( original_post, local_repost );
status_save(original_post);
goto cleanup;
cleanup:
ap_object_free(act);

@ -2,7 +2,7 @@
#include "activity.h"
// Submodules
#include "format.h"
#include "util/format.h"
#include "ffdb/fs_list.h"
#include "collections/array.h"
#include "ap/object.h"
@ -67,7 +67,7 @@ struct ap_object* activity_create_Accept( struct ap_object* act )
ap_object_add_context( accept, "https://www.w3.org/ns/activitystreams");
ap_object_add_context( accept, "https://apogee.polaris-1.work/schemas/litepub-0.1.jsonld");
asprintf( &accept->id,"https://%s/activity/%d", g_server->domain, accept->id );
asprintf( &accept->id,"https://%s/activity/%d", g_server->domain, accept->local_id );
accept->type = ap_Accept;
asprintf( &accept->actor, "https://%s/owner/actor", g_server->domain );
char* new_act_actor = strdup(act->actor);
@ -301,7 +301,7 @@ struct ap_object* activity_create_Note( struct status* s )
att->type = ap_Document;
att->url = strdup(s->media.items[i]);
att->mediaType = strdup(m->content_type);
att->media_type = strdup(m->content_type);
att->name = strdup("");
array_append( &act->attachments, sizeof(att), &att );

@ -7,21 +7,6 @@
#include <string.h>
#include <stddef.h>
static char* nullify_empty( char* str )
{
if( !*str ) {
free(str);
return NULL;
}
return str;
}
static char* safe( char* str )
{
if( !str ) { return ""; }
return str;
}
#define OBJ_TYPE struct client_app
static struct json_object_field client_app_layout[] = {
{

@ -14,7 +14,6 @@ char* base64_strict_encode( void* v_binary, size_t len )
uint8_t* binary = v_binary;
const int groups = ( len + 2 ) / 3;
const int padding = len % 3;
char* result = malloc( groups * 4 + 1 );
result[groups*4] = '\0';

@ -2,7 +2,7 @@
#include "sha256/sha256.h"
#include "http/server/header.h"
#include "format.h"
#include "util/format.h"
#include "model/account.h"
#include "model/crypto/keys.h"
@ -48,7 +48,7 @@ bool http_signature_make( const char* inbox, struct crypto_keys* keys, struct ht
sign->date = strdup(date);
// Calculate Digest
char raw_hash[32];
unsigned char raw_hash[32];
sign->content_length = strlen(postdata);
sha256_easy_hash( postdata, sign->content_length, raw_hash );
char* base64_hash = base64_strict_encode(raw_hash,32);
@ -57,7 +57,7 @@ bool http_signature_make( const char* inbox, struct crypto_keys* keys, struct ht
// Build hash line
char hash_line[512];
int size = snprintf( hash_line, 512,
snprintf( hash_line, 512,
"(request-target): post %s\nhost: %s\ndate: %s\ncontent-length: %d\ndigest: %s",
path, host, date, sign->content_length, sign->digest
);
@ -69,19 +69,6 @@ bool http_signature_make( const char* inbox, struct crypto_keys* keys, struct ht
return true;
}
static void print_downcase( FILE* f, const char* str )
{
for(;*str;++str) {
switch( *str ) {
case 'A' ... 'Z':
fputc( *str - 'A' + 'a', f );
break;
default:
fputc( *str, f );
break;
}
}
}
void print_header_line( FILE* hl, struct ap_envelope* env, const char* header_name )
{
@ -138,7 +125,7 @@ static bool validate_body_digest( struct ap_envelope* env )
if( 0 != strcmp( algo, "SHA-256") ) { goto failed; }
// Calculate sha-256 hash
char raw_hash[32];
unsigned char raw_hash[32];
sha256_easy_hash( env->body, content_length, raw_hash );
hash = base64_strict_encode(raw_hash,32);
@ -185,7 +172,7 @@ bool http_signature_validate( struct ap_envelope* env, const char* request_targe
// Break apart the header
char* rem = NULL;
char* algorithm = NULL;
//char* algorithm = NULL;
char* key_id = NULL;
char* headers = NULL;
char* signature = NULL;
@ -205,8 +192,10 @@ bool http_signature_validate( struct ap_envelope* env, const char* request_targe
// Handle parts
if( 0 == strcmp(key,"keyId") ) {
key_id = value;
/*
} else if( 0 == strcmp(key,"algorithm") ) {
algorithm = value;
*/
} else if( 0 == strcmp(key,"headers") ) {
headers = value;
} else if( 0 == strcmp(key,"signature") ) {

@ -70,13 +70,13 @@ bool crypto_keys_load_public( struct crypto_keys* keys, const char* filename )
char* crypto_keys_sign( struct crypto_keys* keys, void* data, unsigned int size )
{
char* result = NULL;
char* sign_binary = NULL;
unsigned char* sign_binary = NULL;
EVP_PKEY_CTX* ctx = NULL;
if( !keys->privkey ) { return NULL; }
// hash data with SHA-256
char hash[32];
unsigned char hash[32];
sha256_easy_hash( data, size, hash );
// Setup for signature
@ -115,14 +115,13 @@ failed:
bool crypto_keys_verify( struct crypto_keys* keys, void* data, unsigned int size, char* signature )
{
bool result = false;
char* sign_binary = NULL;
EVP_PKEY_CTX* ctx = NULL;
char* signature_bin = NULL;
unsigned char* signature_bin = NULL;
if( !keys->pubkey ) { goto failed; }
// hash data with SHA-256
char hash[32];
unsigned char hash[32];
sha256_easy_hash( data, size, hash );
// Decode the signature

@ -1,10 +1,13 @@
#include "emoji.h"
// Submodules
#include "json/layout.h"
#include "format.h"
#include "util/format.h"
// Model
#include "model/server.h"
// Standard Library
#include <dirent.h>
#include <string.h>
#include <stdlib.h>
@ -25,8 +28,7 @@ char* filename_for_shortcode( const char* shortcode )
DIR* d = opendir( "data/emoji" );
struct dirent* ent;
char* filename = NULL;
while( ent = readdir(d) ) {
while(( ent = readdir(d) )) {
if( 0 == strncmp( shortcode, ent->d_name, len ) && ent->d_name[len] == '.' ) {
char* res = strdup(ent->d_name);
closedir(d);

@ -102,7 +102,7 @@ bool envelope_create_from_request( struct http_request* req )
struct timespec ts;
clock_gettime( CLOCK_REALTIME, &ts );
time_ns = (uint64_t)ts.tv_sec * 1000000000 + (uint64_t)ts.tv_nsec;
asprintf( &env.when, "%llu", time_ns );
asprintf( &env.when, "%lu", time_ns );
// Get request headers
struct collection c = {

@ -1,21 +1,34 @@
#include "media.h"
// Submodules
#include "json/layout.h"
#include "format.h"
#include "util/format.h"
// Model
#include "model/server.h"
// Standard Library
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#define OBJ_TYPE struct media
static struct json_object_field media_layout[] = {
JSON_FIELD_STRING( content_type, true ),
struct json_object_field media_layout[] = {
JSON_FIELD_STRING( content_type, false ),
JSON_FIELD_STRING( preview_url, false ),
JSON_FIELD_STRING( remote_url, false ),
JSON_FIELD_END,
};
#undef OBJ_TYPE
struct media* media_new()
{
struct media* res;
res = malloc(sizeof(*res));
memset(res,0,sizeof(*res));
return res;
}
struct media* media_from_id( int id )
{
if( id == 0 ) { return NULL; }
@ -51,7 +64,9 @@ struct media* media_from_local_uri( const char* uri )
int id = atoi(uri);
if( id == 0 ) { return NULL; }
return media_from_id(id);
struct media* result = media_from_id(id);
result->remote_url = strdup(uri);
return result;
}
void media_free( struct media* m )
{
@ -68,3 +83,6 @@ void media_save( struct media* m )
char filename[512];
json_write_object_layout_to_file( format(filename,sizeof(filename),"data/media/%d.json", m->id ), "\t", media_layout, m );
}
JSON_FIELD_TYPE_OBJECT_LAYOUT_WITH_DEFAULTS( media );

@ -1,13 +1,21 @@
#pragma once
#include "json/layout.h"
struct media
{
int id;
char* remote_url;
char* preview_url;
char* content_type;
};
struct media* media_new();
struct media* media_from_id( int id );
struct media* media_from_local_uri( const char* uri );
void media_free( struct media* m );
void media_save( struct media* m );
extern struct json_object_field media_layout[];
extern struct json_field_type media_type;

@ -11,7 +11,7 @@
#include "sha256/sha256.h"
#include "collections/array.h"
#include "http/client/client.h"
#include "format.h"
#include "util/format.h"
#include "ap/object.h"
// Model
@ -21,6 +21,7 @@
#include "model/notification.h"
#include "model/timeline.h"
#include "model/emoji.h"
#include "model/media.h"
// Standard Library
#include <stdio.h>
@ -50,6 +51,7 @@ static struct json_object_field status_layout[] = {
JSON_FIELD_INTEGER( reposted_status_id, false ),
JSON_FIELD_ARRAY_OF_STRINGS( media, false ),
JSON_FIELD_ARRAY_OF_TYPE( media2, false, media_type ),
JSON_FIELD_ARRAY_OF_TYPE( reacts, false, status_react_type ),
JSON_FIELD_ARRAY_OF_INTS( likes, false ),
@ -98,6 +100,8 @@ static FILE* open_status_data_file( unsigned int id, const char* mode )
//printf( "Using existing location at %s\n", filename );
return f;
}
return NULL;
}
struct status* status_from_id( unsigned int id )
@ -118,6 +122,29 @@ struct status* status_from_id( unsigned int id )
return NULL;
}
// Convert media to media2
if( s->media.count != 0 ) {
for( int i = 0; i < s->media.count; ++i ) {
struct media* local = media_from_local_uri( s->media.items[i] );
if( local ) {
array_append( &s->media2, sizeof(local), &local );
continue;
}
struct media* remote = media_new();
remote->preview_url = strdup(s->media.items[i]);
remote->remote_url = strdup(s->media.items[i]);
remote->content_type = strdup("image/*");
array_append( &s->media2, sizeof(remote), &remote );
free(s->media.items[i] );
}
free( s->media.items );
memset( &s->media, 0, sizeof(s->media) );
status_save(s);
}
if( !s->source ) {
s->source = strdup("");
}
@ -179,7 +206,6 @@ void status_add_reply( struct status* s, struct status* child )
{
if( child->id == 0 ) { return; }
bool is_already_parent_reply = false;
for( int i = 0; i < s->replies.count; ++i ) {
if( s->replies.items[i] == child->id ) {
return;
@ -281,12 +307,20 @@ bool status_sync_from_activity_pub( struct status* s, struct ap_object* act )
free(s->media.items);
memset(&s->media,0,sizeof(s->media));
for( int i = 0; i < s->media2.count; ++i ) {
media_free( s->media2.items[i] );
}
free(s->media2.items);
memset(&s->media2,0,sizeof(s->media2));
// Recreate the media field
for( int i = 0; i < act->attachments.count; ++i ) {
struct ap_object* att = act->attachments.items[i];
if( att && att->url ) {
char* media = strdup( att->url );
array_append( &s->media, sizeof(char*), &media );
struct media* media = media_new();
media->remote_url = strdup( att->url );
media->content_type = strdup(att->media_type);
array_append( &s->media2, sizeof(char*), &media );
}
}
@ -321,7 +355,7 @@ bool pull_remote_file( const char* filename, const char* uri )
return false;
}
printf( "status_code = %d\n", status_code );
printf( "status_code = %ld\n", status_code );
if( status_code == 200 ) {
// success
fclose(f);
@ -540,6 +574,10 @@ void status_free( struct status* s )
free(s->media.items[i]);
}
free(s->media.items);
for( int i = 0; i < s->media2.count; ++i ) {
media_free(s->media2.items[i] );
}
free(s->media2.items);
// Free reactions
for( int i = 0; i < s->reacts.count; ++i ) {
@ -654,7 +692,7 @@ void status_add_react( struct status* s, const char* react, struct account* a )
if( a->id == owner_account_id ) {
if( s->account_id == owner_account_id ) {
// De
printf( "TODO: generate outbox activity for adding reaction '%s' to status #%d by account #%d, deliver to followers\n", react, s->id );
printf( "TODO: generate outbox activity for adding reaction '%s' to status #%u by account #%u, deliver to followers\n", react, s->id, a->id );
} else {
// Deliver react to post owner
//printf( "TODO: generate outbox activity for adding reaction '%s' to status #%d by account #%d, deliver to account #%d\n", react, s->id, a->id, s->account_id );

@ -6,6 +6,7 @@
struct account;
struct emoji;
struct media;
struct status
{
@ -34,6 +35,11 @@ struct status
int count;
} media;
struct {
struct media** items;
int count;
} media2;
struct {
struct status_react** items;
int count;

@ -7,7 +7,7 @@
#include <stdlib.h>
#include <string.h>
static bool reader( struct json_pull_parser* jpp, void* field_data, struct json_object_field* layout_field_data )
static bool reader( struct json_pull_parser* jpp, void* field_data, struct json_reflection* layout_field_data, int offset )
{
int save;
if( !json_pull_parser_begin_object( jpp, &save ) ) {
@ -40,7 +40,7 @@ static bool reader( struct json_pull_parser* jpp, void* field_data, struct json_
return true;
}
static bool writer( struct json_writer* jw, const char* field_name, void* field_data, struct json_object_field* layout_field_data )
static bool writer( struct json_writer* jw, const char* field_name, void* field_data, struct json_reflection* layout_field_data, int offset )
{
struct status_react* sr = *(void**)field_data;

@ -1,11 +1,14 @@
#include "model/status.h"
// Submodules
#include "collections/array.h"
#include "format.h"
#include "util/format.h"
// Model
#include "model/account.h"
#include "model/emoji.h"
// Standard Library
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

@ -3,7 +3,7 @@
#include "json/json.h"
#include "json/layout.h"
#include "ffdb/trie.h"
#include "format.h"
#include "util/format.h"
#include "model/status.h"
@ -23,6 +23,10 @@ struct timeline* timeline_from_id( int id )
}
struct timeline* timeline_new()
{
struct timeline* tl;
tl = malloc(sizeof(*tl));
memset(tl,0,sizeof(*tl));
return tl;
}
void timeline_free( struct timeline* tl )
{

@ -1,8 +1,10 @@
// Submodules
#include "http/client/client.h"
#include "json/layout.h"
#include "format.h"
#include "util/format.h"
// Standard Library
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -52,7 +54,7 @@ char* webfinger_query( const char* handle, const char* rel, const char* type )
char handle2[512];
strncpy( handle2, handle, 512 );
char* server = NULL;
char* username = strtok_r( handle2, "@", &server );
/*char* username = */strtok_r( handle2, "@", &server );
char url[512];
mkdir( "data/webfinger/", 0755 );
@ -81,7 +83,7 @@ char* webfinger_query( const char* handle, const char* rel, const char* type )
}
fclose(f);
printf( "status_code = %d\n", status_code );
printf( "status_code = %ld\n", status_code );
if( status_code != 200 ) {
return NULL;
}

@ -1 +1 @@
Subproject commit 7038bf6470e752db79517e518e0cefcef27da474
Subproject commit eba19cae4622a68bb5a545f21ebcbfd3a372e4d5

@ -0,0 +1 @@
Subproject commit 37d111960ba44b5bd721074c14f12f1bd66e69ed

@ -1 +1 @@
Subproject commit b03cfa9b35141ea395ad0b839a4129b5bab4b6e5
Subproject commit 9d574afe5ed85c64fc006ffbc2c78aafa6d2503f

@ -0,0 +1,7 @@
#pragma once
const char* format( char* buffer, int size, const char* f, ... );
char* aformat( const char* f, ... );
char* safe_strdup( const char* str );
void mkdir_p( const char* ch, int mode );

@ -2,7 +2,7 @@
#include "json/json.h"
#include "json/layout.h"
#include "format.h"
#include "util/format.h"
#include "model/account.h"
@ -10,16 +10,6 @@
#include <string.h>
static const char* safe( const char* value, const char* other )
{
if( !value ) { return other; }
return value;
}
static const char* b(bool value)
{
return value ? "true" : "false";
}
#define OBJ_TYPE struct account
static struct json_object_field pleroma_layout[] = {
JSON_FIELD_FIXED_BOOL( accepts_chat_messages, false ),
@ -75,14 +65,18 @@ static bool acct_callback( void* field_data, bool is_read, char** res )
} else {
*res = strdup( a->handle );
}
return true;
}
return false;
}
static bool display_name_callback( void* field_data, bool is_read, char** res )
{
struct account* a = field_data;
if( !is_read ) {
*res = strdup( a->display_name ? a->display_name : a->handle );
return true;
}
return false;
}
static bool fqn_callback( void* field_data, bool is_read, char** res )
{
@ -91,6 +85,7 @@ static bool fqn_callback( void* field_data, bool is_read, char** res )
*res = aformat( "%s@%s", a->handle, a->server );
return true;
}
return false;
}
bool int_to_string_callback( void* field_data, bool is_read, char** res )
{
@ -101,6 +96,7 @@ bool int_to_string_callback( void* field_data, bool is_read, char** res )
*res = aformat( "%018u", *field );
return true;
}
return false;
}
struct json_object_field api_Account_layout[] = {
{
@ -188,7 +184,7 @@ struct json_object_field api_Account_layout[] = {
};
#undef OBJ_TYPE
static bool api_Account_writer( struct json_writer* jw, const char* field_name, void* field_data, struct json_object_field* layout_field_data )
static bool api_Account_writer( struct json_writer* jw, const char* field_name, void* field_data, struct json_reflection* layout_field_data, int offset )
{
int account_id = *(int*)field_data;

@ -1,7 +1,8 @@
#include "Attachement.h"
#include "json/json.h"
#include "json/layout.h"
#include "format.h"
#include "util/format.h"
#include "model/server.h"
#include "model/media.h"

@ -1,5 +1,6 @@
#include "Emoji.h"
#include "json/json.h"
#include "json/layout.h"
#include "model/emoji.h"

@ -2,7 +2,7 @@
#include "json/json.h"
#include "json/layout.h"
#include "format.h"
#include "util/format.h"
#include "model/notification.h"
#include "model/status.h"

@ -1,7 +1,8 @@
#include "Relationship.h"
#include "json/json.h"
#include "json/layout.h"
#include "format.h"
#include "util/format.h"
#include "model/account.h"
@ -50,7 +51,7 @@ void api_Relationship_write( struct account* a, struct account* rel, FILE* f, in
free(r.id);
}
static bool api_Relationship_to_owner_writer( struct json_writer* jw, const char* field_name, void* field_data, struct json_object_field* layout_field_data )
static bool api_Relationship_to_owner_writer( struct json_writer* jw, const char* field_name, void* field_data, struct json_reflection* layout_field_data, int offset )
{
json_write_field_name( jw, field_name );

@ -2,12 +2,13 @@
#include "json/json.h"
#include "json/layout.h"
#include "format.h"
#include "util/format.h"
#include "model/server.h"
#include "model/status.h"
#include "model/status/react.h"
#include "model/account.h"
#include "model/media.h"
#include "view/api/Account.h"
@ -27,7 +28,25 @@ bool post_reposted( void* field_data, bool is_read, bool* val )
return true;
}
static bool write_in_reply_to( struct json_writer* jw, const char* field_name, void* field_data, struct json_object_field* layout_field_data )
bool owner_favorited_callback( void* field_data, bool is_read, bool* value )
{
struct status* s = field_data;
if( !is_read ) {
for( int i = 0; i < s->likes.count; ++i ) {
if( s->likes.items[i] == owner_account_id ) {
*value = true;
return true;
}
}
*value = false;
return true;
}
return false;
}
static bool write_in_reply_to( struct json_writer* jw, const char* field_name, void* field_data, struct json_reflection* layout_field_data, int offset )
{
struct status* s = field_data;
struct status* in_reply_to = status_from_id( s->in_reply_to );
@ -57,7 +76,7 @@ static struct json_field_type in_reply_to = {
};
static bool write_status_reference( struct json_writer* jw, const char* field_name, void* field_data, struct json_object_field* layout_field_data )
static bool write_status_reference( struct json_writer* jw, const char* field_name, void* field_data, struct json_reflection* layout_field_data, int offset )
{
json_write_field_name(jw,field_name);
int id = *(int*)field_data;
@ -90,12 +109,14 @@ static struct json_object_field MediaAttachment_Pleroma_layout[] = {
JSON_FIELD_FIXED_STRING( mime_type, "image/png", true ),
JSON_FIELD_END
};
#define OBJ_TYPE struct media
static struct json_object_field MediaAttachment_layout[] = {
JSON_FIELD_FIXED_STRING( blurhash, "eRH.A}xs0Kxv00xYR,R+t5R+9Gt6xaNG%%2-;xaM{NGRjD%%Rjs:xaxu", true ),
JSON_FIELD_FIXED_NULL( description ),
{
.key = "id",
.offset = 0,
.offset = offsetof( OBJ_TYPE, remote_url ),
.type = &json_field_string,
},
{
@ -106,32 +127,33 @@ static struct json_object_field MediaAttachment_layout[] = {
},
{
.key = "preview_url",
.offset = 0,
.offset = offsetof( OBJ_TYPE, preview_url ),
.type = &json_field_string,
},
{
.key = "remote_url",
.offset = 0,
.offset = offsetof( OBJ_TYPE, remote_url ),
.type = &json_field_string,
},
{
.key = "text_url",
.offset = 0,
.offset = offsetof( OBJ_TYPE, remote_url ),
.type = &json_field_string,
},
JSON_FIELD_FIXED_STRING( type, "image", true ),
{
.key = "url",
.offset = 0,
.offset = offsetof( OBJ_TYPE, remote_url ),
.type = &json_field_string,
},
JSON_FIELD_END,
};
#undef OBJ_TYPE
static struct json_field_type MediaAttachment_type = {
.layout = MediaAttachment_layout,
.reader = json_field_object_composite_reader,
.writer = json_field_object_composite_writer,
.reader = json_field_object_type_reader,
.writer = json_field_object_type_writer,
.size = sizeof(char*),
};
@ -171,7 +193,7 @@ static struct json_object_field api_Mention_layout[] = {
};
#undef OBJ_TYPE
static bool Mention_from_id_writer( struct json_writer* jw, const char* field_name, void* field_data, struct json_object_field* layout_field_data )
static bool Mention_from_id_writer( struct json_writer* jw, const char* field_name, void* field_data, struct json_reflection* layout_field_data, int offset )
{
json_write_field_name(jw,field_name);
int id = *(int*)field_data;
@ -246,12 +268,14 @@ bool context_url_callback( void* field_data, bool is_read, char** res )
struct status* s = field_data;
if( !is_read ) {
*res = aformat( "https://%s/contexts/%d", g_server->domain, s->root_status_id );
return true;
}
return false;
}
bool is_local_callback( void* field_data, bool is_read, bool* val )
{
struct status* s = field_data;
*val = false;
*val = !s->remote;
return true;
}
@ -353,8 +377,8 @@ struct json_object_field api_Status_layout[] = {
.key = "favourited",
.required = true,
.offset = 0,
.type = &json_field_fixed_bool,
.fixed_bool = false,
.type = &json_field_bool_callback,
.bool_callback = owner_favorited_callback,
},
{
.key = "favourites_count",
@ -378,7 +402,7 @@ struct json_object_field api_Status_layout[] = {
JSON_FIELD_FIXED_NULL( language ),
{
.key = "media_attachments",
.offset = offsetof( OBJ_TYPE, media ),
.offset = offsetof( OBJ_TYPE, media2 ),
.type = &json_field_array_of,
.array_item_type = &MediaAttachment_type,
},
@ -433,7 +457,7 @@ struct json_object_field api_Status_layout[] = {
};
#undef OBJ_TYPE
static bool api_Status_writer( struct json_writer* jw, const char* field_name, void* field_data, struct json_object_field* layout_field_data )
static bool api_Status_writer( struct json_writer* jw, const char* field_name, void* field_data, struct json_reflection* layout_field_data, int offset )
{
int status_id = *(int*)field_data;

@ -1,17 +0,0 @@
#include "layout.h"
void view_begin_layout( FILE* f, const char* title )
{
#define RENDER
#define BEGIN
#include "src/view/layout.html.inc"
#undef BEGIN
#undef RENDER
}
void view_end_layout( FILE* f )
{
#define RENDER
#include "src/view/layout.html.inc"
#undef RENDER
}

@ -1,7 +0,0 @@
#pragma once
#include <stdio.h>
void view_begin_layout( FILE* f, const char* title );
void view_end_layout( FILE* f );

@ -1,12 +0,0 @@
%( #ifdef BEGIN )
<html>
<head>
<title>%s{title}</title>
</head>
<body>
%( #else )
</body>
</html>
%( #endif )

@ -1 +1 @@
Subproject commit 8cb6d34eefd03de6fc0addbaef1768b492d9e081
Subproject commit d94711a32676c69ecf492a50f030e132acd1647a
Loading…
Cancel
Save