Fix memory leaks, add logic to remove reacts, rename files/folders in HTTP submodules, rework timeline filtering, move http common files to new submodules, have the react result field 'me' filled in correctly

master
teknomunk 2 years ago
parent 27180caf5d
commit a917c223e0

11
.gitmodules vendored

@ -1,8 +1,8 @@
[submodule "src/json"]
path = src/json
url = https://gitea.polaris-1.work/teknomunk/json.git
[submodule "src/http_server"]
path = src/http_server
[submodule "src/http/server"]
path = src/http/server
url = https://gitea.polaris-1.work/teknomunk/http_server.git
[submodule "tools/builder"]
path = tools/builder
@ -16,9 +16,12 @@
[submodule "src/rdf"]
path = src/rdf
url = https://gitea.polaris-1.work/teknomunk/rdf.git
[submodule "src/http_client"]
path = src/http_client
[submodule "src/http/client"]
path = src/http/client
url = https://gitea.polaris-1.work/teknomunk/http_client.git
[submodule "src/ffdb"]
path = src/ffdb
url = https://gitea.polaris-1.work/teknomunk/ffdb.git
[submodule "src/http"]
path = src/http
url = https://gitea.polaris-1.work/teknomunk/http-common.git

@ -1 +1 @@
Subproject commit 1e91a6c2f2d504e74fe1cb325b49b1b0f5383bf0
Subproject commit 54ff2ecda5cd74f5c1b6e2a14cc47360af9d0628

@ -3,7 +3,7 @@
#include "form.h"
#include "json/json.h"
#include "json/layout.h"
#include "http_server/http_request.h"
#include "http/server/request.h"
#include "model/client_app.h"

@ -1,7 +1,7 @@
#include "notice.h"
// Submodules
#include "http_server/http_request.h"
#include "http/server/request.h"
#include "ffdb/fs_list.h"
#include "model/notification.h"
#include "collections/array.h"

@ -2,7 +2,7 @@
#include "json/json.h"
#include "http_server/http_request.h"
#include "http/server/request.h"
#include "model/status.h"
#include "model/status/react.h"
#include "model/account.h"

@ -1,7 +1,7 @@
#include "inbox.h"
// Submodules
#include "http_server/http_request.h"
#include "http/server/request.h"
#include "json/json.h"
#include "ffdb/fs_list.h"

@ -1,4 +1,4 @@
#include "http_server/http_request.h"
#include "http/server/request.h"
#include "controller/mastodon_api.h"
#include "controller/oauth.h"

@ -1,8 +1,9 @@
#include "mastodon_api.h"
#include "http_server/http_request.h"
#include "http/server/request.h"
#include "form.h"
#include "json/json.h"
#include "http/query.h"
#include "model/status.h"
#include "model/account.h"
@ -16,6 +17,7 @@
#include "api/status.h"
#include "api/notice.h"
#include <stddef.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
@ -29,14 +31,32 @@ enum timeline_ids {
bool handle_timeline( struct http_request* req, int timeline_id )
{
bool hide_muted = true;
unsigned int limit = 32;
int max_id = INT_MAX;
int since_id = 0;
struct params_t {
int since_id;
int max_id;
int limit;
bool hide_muted;
} params = {
.since_id = 0,
.limit = 32,
.max_id = INT_MAX,
.hide_muted = true,
};
static struct http_query_fields fields[] = {
{ "since_id", offsetof(struct params_t,since_id), qf_string },
{ "limit", offsetof(struct params_t,limit), qf_integer },
{ "max_id", offsetof(struct params_t,max_id), qf_integer },
{ "hide_muted", offsetof(struct params_t,hide_muted), qf_bool },
{ NULL },
};
// handle query parameters
// TODO: split this off into a generic filter handling
if( http_request_route( req, "?" ) ) {
http_query_parse( req, fields, &params );
}
/*
const char* key;
while( key = http_request_route_query_key(req) ) {
const char* value = http_request_route_query_value(req);
@ -57,7 +77,9 @@ bool handle_timeline( struct http_request* req, int timeline_id )
}
//printf( "Filter: limit=%d, max_id=%d, since_id=%d\n", limit, max_id, since_id );
}
}
}*/
if( params.limit > 32 ) { params.limit = 32; }
struct timeline* tl = timeline_from_id( timeline_id );
if( !tl ) {
@ -67,24 +89,30 @@ bool handle_timeline( struct http_request* req, int timeline_id )
return true;
}
struct status* ss[limit];
int count = timeline_load_statuses( tl, 0, limit, ss );
struct status* ss[params.limit];
struct status* items[params.limit];
struct {
struct status** items;
int count;
} show = {
.items = items,
.count = 0
};
int count = timeline_load_statuses( tl, 0, params.limit, ss );
// Filter
for( int i = 0; i < count; ++i ) {
if( ss[i]->id <= since_id ) {
count = i;
break;
}
}
int base = 0;
for( int i = 0; i < count; ++i ) {
if( ss[i]->id >= max_id ) {
base = i + 1;
}
struct status* s = ss[i];
if( s->id <= params.since_id ) { continue; }
if( s->id >= params.max_id ) { continue; };
show.items[show.count] = s;
show.count += 1;
}
//printf( "limit=%d, since_id=%d, base=%d\n", limit, since_id, base );
//printf( "count=%d\n", count - base );
show_statuses( req, &ss[base], count - base );
show_statuses( req, show.items, show.count );
for( int i = 0; i < count; ++i ) {
status_free( ss[i] );
@ -105,47 +133,6 @@ bool handle_mastodon_api_show_account( struct http_request* req, struct account*
return true;
}
struct query_fields
{
const char* field_name;
int offset;
void (*handle)( void* ptr, const char* value );
};
#include <stddef.h>
void qf_string( void* ptr, const char* value )
{
*(const char**)ptr = value;
}
void qf_integer( void* ptr, const char* value )
{
*(int*)ptr = atoi(value);
}
void qf_bool( void* ptr, const char* value )
{
if( 0 == strcmp(value,"true") ) {
*(bool*)ptr = true;
}
}
void parse_query( struct http_request* req, struct query_fields* fields, void* ptr )
{
char* data = ptr;
const char* key;
while( key = http_request_route_query_key(req) ) {
const char* value = http_request_route_query_value(req);
printf( "%s = %s\n", key, value );
for( struct query_fields* i = fields; i->field_name; ++i ) {
if( 0 == strcmp(i->field_name,key) ) {
i->handle( &data[i->offset], value );
}
}
}
}
static bool handle_search( struct http_request* req )
{
struct params_t
@ -157,7 +144,7 @@ static bool handle_search( struct http_request* req )
} params;
memset(&params,0,sizeof(params));
static struct query_fields fields[] = {
static struct http_query_fields fields[] = {
{ "q", offsetof(struct params_t,q), qf_string },
{ "limit", offsetof(struct params_t,limit), qf_integer },
{ "resolve", offsetof(struct params_t,resolve), qf_bool },
@ -165,18 +152,7 @@ static bool handle_search( struct http_request* req )
{ NULL },
};
parse_query( req, fields, &params );
printf( "params = {\n"
"\t.q = %s\n"
"\t.limit = %d\n"
"\t.resolve = %c\n"
"\t.following = %c\n",
params.q,
params.limit,
params.resolve ? 'T' : 'F',
params.following ? 'T' : 'F'
);
http_query_parse( req, fields, &params );
http_request_send_headers( req, 200, "application/json", true );
FILE* f = http_request_get_response_body( req );
@ -191,6 +167,8 @@ static bool handle_search( struct http_request* req )
api_account_write_as_json(a,f);
fprintf( f, "]" );
account_free(a);
return true;
}

@ -1,6 +1,6 @@
#include "nodeinfo.h"
#include "http_server/http_request.h"
#include "http/server/request.h"
#include "model/server.h"
#include <stdio.h>

@ -1,6 +1,6 @@
#include "oauth.h"
#include "http_server/http_request.h"
#include "http_server/escape.h"
#include "http/server/request.h"
#include "http/server/escape.h"
#include "model/client_app.h"
#include "model/account.h"

@ -3,7 +3,7 @@
// Submodules
#include "ffdb/fs_list.h"
#include "collections/array.h"
#include "http_client/client.h"
#include "http/client/client.h"
// Model
#include "model/server.h"

@ -1,6 +1,6 @@
#include "owner.h"
#include "http_server/http_request.h"
#include "http/server/request.h"
#include "model/server.h"

@ -1,7 +1,7 @@
#include "pleroma_api.h"
#include "http/cgi.h"
#include "http_server/http_request.h"
#include "http/server/request.h"
#include "model/account.h"
#include "model/status.h"
@ -17,13 +17,24 @@ bool http_request_route_id( struct http_request* req, int* id );
static bool route_status( struct http_request* req, struct status* s )
{
if( http_request_route( req, "reactions/" ) ) {
int method = -1;
if( http_request_route_method( req, "PUT" ) ) {
method = 1;
} else if( http_request_route_method( req, "DELETE" ) ) {
method = 0;
}
if( method != -1 ) {
char* react_cgi = http_request_route_get_dir_or_file( req );
char* react = cgi_unescape(react_cgi);
free(react_cgi);
struct account* owner = account_from_id( owner_account_id );
status_add_react( s, react, owner );
if( method ) {
status_add_react( s, react, owner );
} else {
status_remove_react( s, react, owner );
}
free(react);
account_free(owner);

@ -1,6 +1,6 @@
#include "crypto.h"
#include "http_server/header.h"
#include "http/server/header.h"
#include "model/ap/inbox_envelope.h"
#include "model/crypto/keys.h"
#include "model/crypto/http_sign.h"

@ -1,6 +1,6 @@
#include "webfinger.h"
#include "http_server/http_request.h"
#include "http/server/request.h"
#include <string.h>

@ -1,27 +0,0 @@
#include "cgi.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
char* cgi_unescape( const char* str )
{
int size = strlen(str);
char* result = malloc(size+1);
char* o = result;
for( const char* i = str; *i; ++i ) {
if( *i == '%' ) {
int code;
sscanf( &i[1], "%02X", &code );
*o = code;
++o;
i += 2;
} else {
*o = *i;
}
}
*o = '\0';
return result;
}

@ -1,4 +0,0 @@
#pragma once
char* cgi_unescape( const char* str );

@ -0,0 +1 @@
Subproject commit 910be4ad221a2f379f30cafa4967949248e07962

@ -1 +0,0 @@
Subproject commit e13505a72597bcaff2cba02726a90488bd0700e1

@ -7,8 +7,8 @@
#include <sys/prctl.h>
#include "app_args.h"
#include "http_server/http_server.h"
#include "http_server/http_request.h"
#include "http/server/server.h"
#include "http/server/request.h"
#include "controller/main.h"
#include "controller/inbox.h"
@ -32,10 +32,10 @@ void handle_request( struct http_request* req, void* )
if( !route_request( req ) ) {
FILE* f = http_request_get_response_body( req );
http_request_send_headers( req, 404, "text/html", true );
#define RENDER
#include "view/404.html.inc"
#undef RENDER
#include "view/404.html.inc"
}
fflush(stdout);
}
bool run_webserver( struct app_args* args )

@ -4,7 +4,7 @@
// Submodules
#include "json/json.h"
#include "json/layout.h"
#include "http_client/client.h"
#include "http/client/client.h"
#include "ffdb/fs_list.h"
#include "ffdb/hash_index.h"
#include "ffdb/trie.h"

@ -4,7 +4,8 @@
// Submodules
#include "json/json.h"
#include "json/layout.h"
#include "http_server/http_request.h"
#include "http/server/request.h"
#include "http/server/header.h"
#include "ffdb/fs_list.h"
#include "collections/collection.h"
#include "collections/array.h"

@ -2,8 +2,6 @@
#include "activity.h"
#include "http_server/header.h"
#include <stdbool.h>
struct ap_envelope

@ -1,6 +1,8 @@
#include "http_sign.h"
#include "sha256/sha256.h"
#include "http/server/header.h"
#include "model/account.h"
#include "model/crypto/keys.h"
#include "model/crypto/base64.h"

@ -22,7 +22,7 @@ static struct json_object_field status_layout[] = {
{ "account_id", offsetof( struct status, account_id ), true, &json_field_integer },
{ "url", offsetof( struct status, url ), false, &json_field_string },
{ "content", offsetof( struct status, source ), false, &json_field_string },
//{ "content", offsetof( struct status, source ), false, &json_field_string },
{ "source", offsetof( struct status, source ), false, &json_field_string },
{ "sensitive", offsetof( struct status, sensitive ), true, &json_field_bool },
@ -161,19 +161,24 @@ void status_free( struct status* s )
{
if( !s ) { return; }
free(s->url);
free(s->content);
free(s->source);
// Free media
for( int i = 0; i < s->media.count; ++i ) {
free(s->media.items[i]);
}
free(s->media.items);
// Free reactions
for( int i = 0; i < s->reacts.count; ++i ) {
free(s->reacts.items[i]);
status_react_free(s->reacts.items[i]);
}
free(s->reacts.items);
free(s->likes.items);
free(s->reposts.items);
free(s->content);
free(s);
}
@ -218,6 +223,42 @@ update_entry:
done:
status_save(s);
}
void status_remove_react( struct status* s, const char* react, struct account* a )
{
// TODO generate outbox element
printf( "TODO: generate outbox activity for removing reaction '%s' to status #%d by account #%d\n", react, s->id, a->id );
// TODO: generate notification
if( s->account_id == owner_account_id && a->id != owner_account_id ) {
// Create notification for liking the owner's post
struct notification* note = notification_new();
note->type = nt_react;
note->account_id = a->id;
note->react = strdup(react);
note->created_at = time(NULL);
notification_save( note );
notification_free( note );
}
struct status_react* re = NULL;
for( int i = 0; i < s->reacts.count; ++i ) {
if( 0 == strcmp( s->reacts.items[i]->code, react ) ) {
re = s->reacts.items[i];
goto update_entry;
}
}
return;
update_entry:
array_delete( &re->accounts, sizeof(a->id), &a->id );
if( re->accounts.count == 0 ) {
array_delete( &s->reacts, sizeof(re), &re );
status_react_free(re);
}
status_save(s);
}
void status_add_like( struct status* s, struct account* a )
{
for( int i = 0; i < s->likes.count; ++i ) {

@ -49,7 +49,9 @@ void status_save( struct status* s );
void status_free( struct status* s );
void status_add_react( struct status* s, const char* react, struct account* a );
void status_remove_react( struct status* s, const char* react, struct account* a );
void status_add_like( struct status* s, struct account* a );
void status_remove_like( struct status* s, struct account* a );
char* status_render_source( struct status* s );

@ -66,11 +66,18 @@ static void* alloc()
return react;
}
void status_react_free( struct status_react* re )
{
if( !re ) { return; }
free(re->accounts.items);
free(re->code);
free(re);
}
static void free_react( void* ptr )
{
struct status_react* react = ptr;
free(react->accounts.items);
free(react);
status_react_free(ptr);
}
struct json_field_type status_react_type = {

@ -13,6 +13,10 @@ char* status_render_source( struct status* s )
if( s->content ) {
goto done;
}
if( !s->source ) {
s->content = strdup("");
goto done;
}
char* result = NULL;
size_t size = 0;

@ -44,9 +44,17 @@
"conversation_id": 2935699,
"direct_conversation_id": null,
"emoji_reactions": [%( for( int i = 0; i < s->reacts.count; ++i ) { struct status_react* sr = s->reacts.items[i];)
%(
bool includes_me( struct status_react* sr ) {
for( int i = 0; i < sr->accounts.count; ++i ) {
if( sr->accounts.items[i] == owner_account_id ) { return true; }
}
return false;
}
)
{
"count": %d{ sr->accounts.count },
"me": false,
"me": %s{ includes_me(sr) ? "true" : "false" },
"name": %( json_write_string( f, sr->code ); )
}%s{ i != s->reacts.count-1 ? "," : "" }
%( } )],

Loading…
Cancel
Save