Fix memory leaks, implement bookmarks

master
teknomunk 1 year ago
parent 34135f9da0
commit ed4fbf7fde

@ -219,3 +219,97 @@ failed:
goto cleanup;
}
// Route: POST /api/v1/statuses/%d{id}/bookmark
bool handle_bookmark( struct http_request* req, struct status* s )
{
status_set_bookmark( s );
show_status( req, s );
return true;
}
// Route: POST /api/v1/statuses/%d{id}/unbookmark
bool handle_unbookmark( struct http_request* req, struct status* s )
{
status_clear_bookmark( s );
show_status( req, s );
return true;
}
// route: GET /api/v1/bookmarks
bool handle_show_bookmarks( struct http_request* req )
{
struct {
struct status** items;
int count;
} results;
memset(&results,0,sizeof(results));
status_get_bookmarks( 0, 100, &results );
show_statuses( req, results.items, results.count );
for( int i = 0; i < results.count; ++i ) {
status_free(results.items[i]);
}
free(results.items);
return true;
}
bool http_request_route_id( struct http_request* req, int* id )
{
char* id_str = http_request_route_get_dir_or_file(req);
if( !id_str || !*id_str ) { return false; }
*id = -1;
sscanf( id_str, "%d", id );
free(id_str);
if( *id == -1 ) { return false; }
return true;
}
// Route: /api/v1/statuses/%d{id}/
bool route_statuses( struct http_request* req )
{
bool result = false;
struct status* s = NULL;
if( http_request_route_term( req, "" ) ) {
if( http_request_route_method( req, "POST" ) ) {
struct account* owner = account_from_id(owner_account_id);
bool res = handle_post(req, owner);
account_free(owner);
return res;
}
return false;
}
if( !http_request_route( req, "/" ) ) { return false; }
int id = -1;
if( !http_request_route_id( req, &id ) ) { goto failed; }
s = status_from_id(id);
if( !s ) { goto failed; }
if( http_request_route( req, "context" ) ) {
show_status_context( req, s );
goto success;
} else if( http_request_route_term( req, "reblog" ) ) {
if( handle_repost( req, s ) ) { goto success; }
} else if( http_request_route_term( req, "bookmark" ) ) {
if( handle_bookmark( req, s ) ) { goto success; }
} else if( http_request_route_term( req, "unbookmark" ) ) {
if( handle_unbookmark( req, s ) ) { goto success; }
} else if( http_request_route_term( req, "" ) ) {
show_status( req, s );
goto success;
}
failed:
result = false;
cleanup:
status_free(s);
return result;
success:
result = true;
goto cleanup;
}

@ -13,4 +13,7 @@ void show_statuses( struct http_request* req, struct status** ss, int count );
bool handle_post( struct http_request* req, struct account* a );
bool handle_repost( struct http_request* req, struct status* s );
bool handle_show_bookmarks( struct http_request* req );
bool route_statuses( struct http_request* req );

@ -31,60 +31,6 @@
#include <stdlib.h>
#include <string.h>
bool http_request_route_id( struct http_request* req, int* id )
{
char* id_str = http_request_route_get_dir_or_file(req);
if( !id_str || !*id_str ) { return false; }
*id = -1;
sscanf( id_str, "%d", id );
free(id_str);
if( *id == -1 ) { return false; }
return true;
}
// Route: /api/v1/statuses/%d{id}/
bool route_statuses_1f( struct http_request* req )
{
bool result = false;
struct status* s = NULL;
if( http_request_route_term( req, "" ) ) {
if( http_request_route_method( req, "POST" ) ) {
struct account* owner = account_from_id(owner_account_id);
bool res = handle_post(req, owner);
account_free(owner);
return res;
}
return false;
}
if( !http_request_route( req, "/" ) ) { return false; }
int id = -1;
if( !http_request_route_id( req, &id ) ) { goto failed; }
s = status_from_id(id);
if( !s ) { goto failed; }
if( http_request_route( req, "context" ) ) {
show_status_context( req, s );
goto success;
} else if( http_request_route_term( req, "reblog" ) ) {
if( handle_repost( req, s ) ) { goto success; }
} else if( http_request_route_term( req, "" ) ) {
show_status( req, s );
goto success;
}
failed:
result = false;
cleanup:
status_free(s);
return result;
success:
result = true;
goto cleanup;
}
bool handle_scheduled_statuses( struct http_request* req )
{
http_request_send_headers( req, 200, "application/json", true );
@ -273,7 +219,7 @@ bool route_mastodon_api( struct http_request* req )
fprintf( f, "[]" );
return true;
} else if( http_request_route( req, "statuses" ) ) {
return route_statuses_1f(req);
return route_statuses(req);
} else if( http_request_route_term( req, "scheduled_statuses" ) ) {
return handle_scheduled_statuses(req);
} else if( http_request_route( req, "timelines/" ) ) {
@ -284,6 +230,8 @@ bool route_mastodon_api( struct http_request* req )
}
} else if( http_request_route_term( req, "media" ) ) {
return handle_media(req);
} else if( http_request_route_term( req, "bookmarks" ) ) {
return handle_show_bookmarks( req );
} else if( http_request_route( req, "apps/" ) ) {
if( http_request_route( req, "verify_credentials" ) ) {

@ -1 +1 @@
Subproject commit 1ff6bad820c11291302efb084992b719e27b1c52
Subproject commit e991549cae6ef7c9c50e62cbc3fac86515360220

@ -1 +1 @@
Subproject commit aa8efbacff4ac3d4b80e3ad7d5033e0450d0d28a
Subproject commit a7f65a8bba29c33e7432d8029576040b8330c0cf

@ -307,4 +307,6 @@ void http_signature_free( struct http_signature* sign )
free(sign->host);
free(sign->date);
free(sign->signature);
free(sign->digest);
}

@ -13,6 +13,7 @@
#include "json/json.h"
#include "json/layout.h"
#include "ffdb/hash_index.h"
#include "ffdb/trie.h"
#include "sha256/sha256.h"
#include "collections/array.h"
#include "http/client/client.h"
@ -35,6 +36,7 @@ static struct json_object_field status_layout[] = {
JSON_FIELD_STRING( content, false ),
JSON_FIELD_STRING( source, false ),
JSON_FIELD_BOOL( pinned, false ),
JSON_FIELD_BOOL( bookmarked, false ),
JSON_FIELD_DATETIME( published, false ),
JSON_FIELD_INTEGER( in_reply_to, false ),
@ -170,6 +172,8 @@ struct status* status_from_uri( const char* uri )
}
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 ) {
@ -746,4 +750,48 @@ void status_add_like( struct status* s, struct account* a )
status_save(s);
}
void status_set_bookmark( struct status* s )
{
s->bookmarked = true;
mkdir( "data/bookmarks", 0755 );
char key[32];
ffdb_trie_set( "data/owner/bookmarks", format(key,32,"%d",s->id), "T" );
status_save(s);
}
void status_clear_bookmark( struct status* s )
{
s->bookmarked = false;
mkdir( "data/bookmarks", 0755 );
char key[32];
ffdb_trie_set( "data/owner/bookmarks", format(key,32,"%d",s->id), NULL );
status_save(s);
}
void status_get_bookmarks( int offset, int limit, void* results_ptr )
{
struct {
char** items;
int count;
} keys;
memset( &keys, 0, sizeof(keys) );
struct {
struct status** items;
int count;
} *results = results_ptr;
results->count = 0;
ffdb_trie_list( "data/owner/bookmarks", offset, limit, &keys, NULL );
for( int i = 0; i < keys.count; ++i ) {
int id;
if( 1 == sscanf( keys.items[i], "%d", &id ) ) {
struct status* s = status_from_id(id);
if( s ) {
array_append( results_ptr, sizeof(s), &s );
}
}
free( keys.items[i] );
}
free( keys.items );
}

@ -20,6 +20,7 @@ struct status
char* source;
bool sensitive;
bool pinned;
bool bookmarked;
time_t published;
int in_reply_to;
@ -95,6 +96,10 @@ 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 );
void status_set_bookmark( struct status* s );
void status_clear_bookmark( struct status* s );
char* status_render_source( struct status* s );
void status_get_bookmarks( int offset, int limit, void* results_ptr );

@ -327,7 +327,7 @@ struct json_object_field api_Status_layout[] = {
.type = &api_Account_type,
},
JSON_FIELD_FIXED_NULL( application ),
JSON_FIELD_FIXED_BOOL( bookmarked, false ),
JSON_FIELD_BOOL( bookmarked, true ),
JSON_FIELD_FIXED_NULL( card ),
{
.key = "content",

Loading…
Cancel
Save