diff options
Diffstat (limited to 'src/client/libwebidoidc-client.c')
-rw-r--r-- | src/client/libwebidoidc-client.c | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/src/client/libwebidoidc-client.c b/src/client/libwebidoidc-client.c new file mode 100644 index 0000000..8c22cc6 --- /dev/null +++ b/src/client/libwebidoidc-client.c @@ -0,0 +1,144 @@ +// 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 <https://www.gnu.org/licenses/>. + +#include <Disfluid-0.h> +#include <libguile.h> +#include <string.h> + +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); +} |