#include "model/status.h" // Submodules #include "collections/array.h" #include "util/format.h" // Model #include "model/account.h" #include "model/emoji.h" // Standard Library #include #include #include #include #include char* status_render_source( struct status* s ) { if( s->content ) { goto done; } if( !s->source ) { s->content = strdup(""); goto done; } char account_server[50]; { struct account* status_account = account_from_id(s->account_id); strncpy( account_server, status_account->server, 50 ); account_free(status_account); } char* result = NULL; size_t size = 0; FILE* f = open_memstream(&result,&size); for( char* i = s->source; *i; ++i ) { // Handle URLs if( 0 == strncmp( i, "https://", 8 ) ) { char* start = i; while( *i && !index(" ,\r\n\t",*i) ) ++i; char* url = strndup( start, i - start ); fprintf( f, "%s", url, url ); free(url); } else if( isalpha(i[1]) && *i == '@' ) { char* start = i; while( *i && !index(" ,\r\n",*i) ) ++i; char* handle = strndup( start, i - start ); struct account* user = account_from_webfinger( &handle[1] ); if( !user ) { char buffer[512]; format( buffer, 512, "%s@%s", handle, account_server ); user = account_from_webfinger( &handle[1] ); } if( user ) { status_add_mention( s, user->id ); fprintf( f, "" "" "@%s" "" "", user->account_url, user->handle ); account_free(user); } else { fprintf( f, "%s", handle ); } free(handle); } else if( *i == ':' ) { // Emoji ++i; char* start = i; while( *i && !index(" ,:",*i) ) ++i; char* shortcode = strndup( start, i - start ); // Check if shortcode is already present in status for( int i = 0; i < s->emoji.count; ++i ) { struct emoji* e = s->emoji.items[i]; if( 0 == strcmp( e->shortcode, shortcode ) ) { goto already_has_emoji; } } struct emoji* e = emoji_from_shortcode( shortcode ); if( e ) { array_append( &s->emoji, sizeof(e), &e ); } already_has_emoji: fprintf( f, ":%s", shortcode ); free(shortcode); } else if( *i == '\n' ) { fprintf( f, "
" ); continue; } else if( *i == '\r' ) { // Ignore } if( !*i ) { break; } fputc( *i, f ); } fputc( '\0', f ); fclose(f); s->content = result; done: status_save(s); return s->content; }