Mercurial > openid
diff src/c/openid.c @ 1:c230e6da3ff6
Discovered LiveJournal endpoint
author | Adam Chlipala <adam@chlipala.net> |
---|---|
date | Sun, 26 Dec 2010 13:10:36 -0500 |
parents | 3c209338e596 |
children | b757dc2bd2f6 |
line wrap: on
line diff
--- a/src/c/openid.c Sun Dec 26 12:04:08 2010 -0500 +++ b/src/c/openid.c Sun Dec 26 13:10:36 2010 -0500 @@ -1,10 +1,108 @@ +#include <string.h> + #include <openssl/sha.h> #include <curl/curl.h> +#include <expat.h> -#include <urweb/urweb.h> +#include <openid.h> uw_unit uw_OpenidFfi_init(uw_context ctx) { curl_global_init(CURL_GLOBAL_ALL); return uw_unit_v; } + +static CURL *curl(uw_context ctx) { + CURL *r; + + if (!(r = uw_get_global(ctx, "curl"))) { + r = curl_easy_init(); + if (r) + uw_set_global(ctx, "curl", r, curl_easy_cleanup); + } + + return r; +} + +typedef struct { + uw_context ctx; + char *result; +} endpoint; + +static void XMLCALL startElement(void *userData, const XML_Char *name, const XML_Char **atts) { + endpoint *ep = userData; + + if (!strcmp(name, "link")) { + const XML_Char **attp; + int found = 0; + + for (attp = atts; *attp; attp += 2) { + if (!strcmp(attp[0], "rel") && !strcmp(attp[1], "openid2.provider")) { + found = 1; + break; + } + } + + if (found) { + for (attp = atts; *attp; attp += 2) { + if (!strcmp(attp[0], "href")) { + ep->result = uw_strdup(ep->ctx, attp[1]); + return; + } + } + } + } +} + +static void XMLCALL endElement(void *userData, const XML_Char *name) { +} + +typedef struct { + XML_Parser parser; + int any_errors; +} curl_data; + +static size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp) { + curl_data *d = userp; + + if (!XML_Parse(d->parser, buffer, size * nmemb, 0)) + d->any_errors = 1; + + return size * nmemb; +} + +uw_Basis_string uw_OpenidFfi_discover(uw_context ctx, uw_Basis_string id) { + char *s; + CURL *c = curl(ctx); + curl_data cd = {}; + endpoint ep = {ctx}; + CURLcode code; + + if (!strchr(id, ':')) { + id = uw_Basis_strcat(ctx, "http://", id); + if ((s = strchr(id, '#')) != NULL) + *s = 0; + } else if ((s = strchr(id, '#')) != NULL) { + char *id2 = uw_malloc(ctx, s - id + 1); + memcpy(id2, s, s - id); + id2[s - id] = 0; + id = id2; + } + + cd.parser = XML_ParserCreate(NULL); + XML_SetUserData(cd.parser, &ep); + uw_push_cleanup(ctx, (void (*)(void *))XML_ParserFree, cd.parser); + XML_SetElementHandler(cd.parser, startElement, endElement); + + curl_easy_setopt(c, CURLOPT_URL, id); + curl_easy_setopt(c, CURLOPT_WRITEFUNCTION, write_data); + curl_easy_setopt(c, CURLOPT_WRITEDATA, &cd); + + code = curl_easy_perform(c); + uw_pop_cleanup(ctx); + + if (code) + return NULL; + else + return ep.result; +}