annotate 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
rev   line source
adam@1 1 #include <string.h>
adam@1 2
adam@0 3 #include <openssl/sha.h>
adam@0 4 #include <curl/curl.h>
adam@1 5 #include <expat.h>
adam@0 6
adam@1 7 #include <openid.h>
adam@0 8
adam@0 9 uw_unit uw_OpenidFfi_init(uw_context ctx) {
adam@0 10 curl_global_init(CURL_GLOBAL_ALL);
adam@0 11
adam@0 12 return uw_unit_v;
adam@0 13 }
adam@1 14
adam@1 15 static CURL *curl(uw_context ctx) {
adam@1 16 CURL *r;
adam@1 17
adam@1 18 if (!(r = uw_get_global(ctx, "curl"))) {
adam@1 19 r = curl_easy_init();
adam@1 20 if (r)
adam@1 21 uw_set_global(ctx, "curl", r, curl_easy_cleanup);
adam@1 22 }
adam@1 23
adam@1 24 return r;
adam@1 25 }
adam@1 26
adam@1 27 typedef struct {
adam@1 28 uw_context ctx;
adam@1 29 char *result;
adam@1 30 } endpoint;
adam@1 31
adam@1 32 static void XMLCALL startElement(void *userData, const XML_Char *name, const XML_Char **atts) {
adam@1 33 endpoint *ep = userData;
adam@1 34
adam@1 35 if (!strcmp(name, "link")) {
adam@1 36 const XML_Char **attp;
adam@1 37 int found = 0;
adam@1 38
adam@1 39 for (attp = atts; *attp; attp += 2) {
adam@1 40 if (!strcmp(attp[0], "rel") && !strcmp(attp[1], "openid2.provider")) {
adam@1 41 found = 1;
adam@1 42 break;
adam@1 43 }
adam@1 44 }
adam@1 45
adam@1 46 if (found) {
adam@1 47 for (attp = atts; *attp; attp += 2) {
adam@1 48 if (!strcmp(attp[0], "href")) {
adam@1 49 ep->result = uw_strdup(ep->ctx, attp[1]);
adam@1 50 return;
adam@1 51 }
adam@1 52 }
adam@1 53 }
adam@1 54 }
adam@1 55 }
adam@1 56
adam@1 57 static void XMLCALL endElement(void *userData, const XML_Char *name) {
adam@1 58 }
adam@1 59
adam@1 60 typedef struct {
adam@1 61 XML_Parser parser;
adam@1 62 int any_errors;
adam@1 63 } curl_data;
adam@1 64
adam@1 65 static size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp) {
adam@1 66 curl_data *d = userp;
adam@1 67
adam@1 68 if (!XML_Parse(d->parser, buffer, size * nmemb, 0))
adam@1 69 d->any_errors = 1;
adam@1 70
adam@1 71 return size * nmemb;
adam@1 72 }
adam@1 73
adam@1 74 uw_Basis_string uw_OpenidFfi_discover(uw_context ctx, uw_Basis_string id) {
adam@1 75 char *s;
adam@1 76 CURL *c = curl(ctx);
adam@1 77 curl_data cd = {};
adam@1 78 endpoint ep = {ctx};
adam@1 79 CURLcode code;
adam@1 80
adam@1 81 if (!strchr(id, ':')) {
adam@1 82 id = uw_Basis_strcat(ctx, "http://", id);
adam@1 83 if ((s = strchr(id, '#')) != NULL)
adam@1 84 *s = 0;
adam@1 85 } else if ((s = strchr(id, '#')) != NULL) {
adam@1 86 char *id2 = uw_malloc(ctx, s - id + 1);
adam@1 87 memcpy(id2, s, s - id);
adam@1 88 id2[s - id] = 0;
adam@1 89 id = id2;
adam@1 90 }
adam@1 91
adam@1 92 cd.parser = XML_ParserCreate(NULL);
adam@1 93 XML_SetUserData(cd.parser, &ep);
adam@1 94 uw_push_cleanup(ctx, (void (*)(void *))XML_ParserFree, cd.parser);
adam@1 95 XML_SetElementHandler(cd.parser, startElement, endElement);
adam@1 96
adam@1 97 curl_easy_setopt(c, CURLOPT_URL, id);
adam@1 98 curl_easy_setopt(c, CURLOPT_WRITEFUNCTION, write_data);
adam@1 99 curl_easy_setopt(c, CURLOPT_WRITEDATA, &cd);
adam@1 100
adam@1 101 code = curl_easy_perform(c);
adam@1 102 uw_pop_cleanup(ctx);
adam@1 103
adam@1 104 if (code)
adam@1 105 return NULL;
adam@1 106 else
adam@1 107 return ep.result;
adam@1 108 }