// disfluid, implementation of the Solid specification // Copyright (C) 2020, 2021 Vivien Kraus // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . #include #include #include struct DisfluidApi { SCM scm_make_client; SCM scm_get_client_id; SCM scm_get_key_pair; SCM scm_get_redirect_uri; }; struct user_code { DisfluidUser func; void *data; }; static void * inner_guile (void *data) { struct user_code *user = data; struct DisfluidApi api; api.scm_make_client = scm_c_public_ref ("webid-oidc client reverse-stubs", "make-client"); api.scm_get_client_id = scm_c_public_ref ("webid-oidc client reverse-stubs", "get-client-id"); api.scm_get_key_pair = scm_c_public_ref ("webid-oidc client reverse-stubs", "get-key-pair"); api.scm_get_redirect_uri = scm_c_public_ref ("webid-oidc client reverse-stubs", "get-redirect-uri"); return user->func (&api, user->data); } void * disfluid_api_init (DisfluidUser func, void *data) { struct user_code code; code.func = func; code.data = data; return scm_with_guile (inner_guile, &code); } struct DisfluidClient { SCM object; }; struct DisfluidClient * disfluid_client_make (const struct DisfluidApi *api, const char *client_id, const char *redirect_uri, const char *jwk) { SCM scm_client_id = scm_from_utf8_string (client_id); SCM scm_redirect_uri = scm_from_utf8_string (redirect_uri); SCM scm_jwk = SCM_BOOL_F; if (jwk) { scm_jwk = scm_from_utf8_string (jwk); } SCM object = scm_call_3 (api->scm_make_client, scm_client_id, scm_redirect_uri, scm_jwk); scm_dynwind_begin (0); struct DisfluidClient *ret = scm_malloc (sizeof (struct DisfluidClient)); scm_dynwind_unwind_handler (free, ret, 0); ret->object = scm_gc_protect_object (object); scm_dynwind_end (); return ret; } void disfluid_client_free (struct DisfluidClient *client) { scm_gc_unprotect_object (client->object); free (client); } static size_t copy_scm_string (SCM string, size_t start, size_t max, char *dest) { size_t total_length = 0; scm_dynwind_begin (0); char *all_bytes = scm_to_utf8_stringn (string, &total_length); scm_dynwind_free (all_bytes); const size_t requested_length = max; const size_t available_length = total_length - start; size_t copied_length = requested_length; if (available_length < copied_length) { copied_length = available_length; } memcpy (dest, all_bytes + start, copied_length); if (copied_length < max) { dest[copied_length] = '\0'; } scm_dynwind_end (); return total_length; } size_t disfluid_client_get_id (const struct DisfluidApi *api, const struct DisfluidClient *client, size_t start, size_t max, char *id) { SCM scm_id = scm_call_1 (api->scm_get_client_id, client->object); return copy_scm_string (scm_id, start, max, id); } size_t disfluid_client_get_key_pair (const struct DisfluidApi *api, const struct DisfluidClient *client, size_t start, size_t max, char *jwk) { SCM scm_jwk = scm_call_1 (api->scm_get_key_pair, client->object); return copy_scm_string (scm_jwk, start, max, jwk); } size_t disfluid_client_get_redirect_uri (const struct DisfluidApi *api, const struct DisfluidClient *client, size_t start, size_t max, char *redirect_uri) { SCM scm_uri = scm_call_1 (api->scm_get_redirect_uri, client->object); return copy_scm_string (scm_uri, start, max, redirect_uri); }