adam@1: #include adam@1: adam@0: #include adam@0: #include adam@1: #include adam@0: adam@1: #include adam@0: adam@0: uw_unit uw_OpenidFfi_init(uw_context ctx) { adam@0: curl_global_init(CURL_GLOBAL_ALL); adam@0: adam@0: return uw_unit_v; adam@0: } adam@1: adam@1: static CURL *curl(uw_context ctx) { adam@1: CURL *r; adam@1: adam@1: if (!(r = uw_get_global(ctx, "curl"))) { adam@1: r = curl_easy_init(); adam@1: if (r) adam@1: uw_set_global(ctx, "curl", r, curl_easy_cleanup); adam@1: } adam@1: adam@1: return r; adam@1: } adam@1: adam@1: typedef struct { adam@1: uw_context ctx; adam@1: char *result; adam@1: } endpoint; adam@1: adam@1: static void XMLCALL startElement(void *userData, const XML_Char *name, const XML_Char **atts) { adam@1: endpoint *ep = userData; adam@1: adam@1: if (!strcmp(name, "link")) { adam@1: const XML_Char **attp; adam@1: int found = 0; adam@1: adam@1: for (attp = atts; *attp; attp += 2) { adam@1: if (!strcmp(attp[0], "rel") && !strcmp(attp[1], "openid2.provider")) { adam@1: found = 1; adam@1: break; adam@1: } adam@1: } adam@1: adam@1: if (found) { adam@1: for (attp = atts; *attp; attp += 2) { adam@1: if (!strcmp(attp[0], "href")) { adam@1: ep->result = uw_strdup(ep->ctx, attp[1]); adam@1: return; adam@1: } adam@1: } adam@1: } adam@1: } adam@1: } adam@1: adam@1: static void XMLCALL endElement(void *userData, const XML_Char *name) { adam@1: } adam@1: adam@1: typedef struct { adam@1: XML_Parser parser; adam@1: int any_errors; adam@1: } curl_data; adam@1: adam@1: static size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp) { adam@1: curl_data *d = userp; adam@1: adam@1: if (!XML_Parse(d->parser, buffer, size * nmemb, 0)) adam@1: d->any_errors = 1; adam@1: adam@1: return size * nmemb; adam@1: } adam@1: adam@1: uw_Basis_string uw_OpenidFfi_discover(uw_context ctx, uw_Basis_string id) { adam@1: char *s; adam@1: CURL *c = curl(ctx); adam@1: curl_data cd = {}; adam@1: endpoint ep = {ctx}; adam@1: CURLcode code; adam@1: adam@1: if (!strchr(id, ':')) { adam@1: id = uw_Basis_strcat(ctx, "http://", id); adam@1: if ((s = strchr(id, '#')) != NULL) adam@1: *s = 0; adam@1: } else if ((s = strchr(id, '#')) != NULL) { adam@1: char *id2 = uw_malloc(ctx, s - id + 1); adam@1: memcpy(id2, s, s - id); adam@1: id2[s - id] = 0; adam@1: id = id2; adam@1: } adam@1: adam@1: cd.parser = XML_ParserCreate(NULL); adam@1: XML_SetUserData(cd.parser, &ep); adam@1: uw_push_cleanup(ctx, (void (*)(void *))XML_ParserFree, cd.parser); adam@1: XML_SetElementHandler(cd.parser, startElement, endElement); adam@1: adam@1: curl_easy_setopt(c, CURLOPT_URL, id); adam@1: curl_easy_setopt(c, CURLOPT_WRITEFUNCTION, write_data); adam@1: curl_easy_setopt(c, CURLOPT_WRITEDATA, &cd); adam@1: adam@1: code = curl_easy_perform(c); adam@1: uw_pop_cleanup(ctx); adam@1: adam@1: if (code) adam@1: return NULL; adam@1: else adam@1: return ep.result; adam@1: }