// Submodules #include "http/client/client.h" #include "json/layout.h" #include "util/format.h" // Standard Library #include #include #include #include struct link { char* href; char* rel; char* type; }; #define OBJ_TYPE struct link static struct json_object_field link_layout[] = { JSON_FIELD_STRING( href, false ), JSON_FIELD_STRING( rel, false ), JSON_FIELD_STRING( type, false ), JSON_FIELD_END, }; #undef OBJ_TYPE void link_free( struct link* l ) { if( !l ) { return; } free(l->href); free(l->type); free(l->rel); free(l); } JSON_FIELD_TYPE_OBJECT_LAYOUT_WITH_DEFAULTS( link ); struct result { struct { struct link** items; int count; } links; }; #define OBJ_TYPE struct result static struct json_object_field result_layout[] = { JSON_FIELD_ARRAY_OF_TYPE( links, true, link_type ), JSON_FIELD_END, }; #undef OBJ_TYPE 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 url[512]; mkdir( "data/webfinger/", 0755 ); const char* uri = format( url, sizeof(url), "https://%s/.well-known/webfinger?resource=acct:%s", server, handle ); char filename[512]; snprintf( filename, sizeof(filename), "data/webfinger/%s.json", handle ); printf( "* Fetching %s\n", uri ); char tmp_filename[512]; FILE* f = fopen(format(tmp_filename,512,"%s.tmp",filename),"w"); if( !f ) { return NULL; } long status_code = -1; const void* request[] = { HTTP_REQ_URL, uri, HTTP_REQ_OUTFILE, f, HTTP_REQ_RESULT_STATUS, &status_code, NULL, }; if( !http_client_do( request ) ) { printf( "! Unable to fetch %s\n", uri ); fclose(f); return NULL; } fclose(f); printf( "status_code = %ld\n", status_code ); if( status_code != 200 ) { return NULL; } rename(tmp_filename,filename); // Get the href value requested struct result r; memset(&r,0,sizeof(r)); json_read_object_layout_from_file( filename, result_layout, &r ); char* value = NULL; for( int i = 0; i < r.links.count; ++i ) { if( !r.links.items[i]->rel ) { goto next; } if( !r.links.items[i]->type ) { goto next; } if( 0 != strcmp( rel, r.links.items[i]->rel ) ) { goto next; } if( 0 == strcmp( type, r.links.items[i]->type ) ) { free(value); value = strdup(r.links.items[i]->href); } next: link_free(r.links.items[i]); } free(r.links.items); return value; }