annotate src/c/openid.c @ 2:b757dc2bd2f6

Discovery returns a record
author Adam Chlipala <adam@chlipala.net>
date Sun, 26 Dec 2010 13:28:06 -0500
parents c230e6da3ff6
children f59083771ee2
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@2 9 struct uw_OpenidFfi_discovery {
adam@2 10 uw_Basis_string endpoint, localId;
adam@2 11 };
adam@2 12
adam@2 13 uw_Basis_string uw_OpenidFfi_endpoint(uw_context ctx, uw_OpenidFfi_discovery d) {
adam@2 14 return d->endpoint;
adam@2 15 }
adam@2 16
adam@2 17 uw_Basis_string uw_OpenidFfi_localId(uw_context ctx, uw_OpenidFfi_discovery d) {
adam@2 18 return d->localId;
adam@2 19 }
adam@2 20
adam@0 21 uw_unit uw_OpenidFfi_init(uw_context ctx) {
adam@0 22 curl_global_init(CURL_GLOBAL_ALL);
adam@0 23
adam@0 24 return uw_unit_v;
adam@0 25 }
adam@1 26
adam@1 27 static CURL *curl(uw_context ctx) {
adam@1 28 CURL *r;
adam@1 29
adam@1 30 if (!(r = uw_get_global(ctx, "curl"))) {
adam@1 31 r = curl_easy_init();
adam@1 32 if (r)
adam@1 33 uw_set_global(ctx, "curl", r, curl_easy_cleanup);
adam@1 34 }
adam@1 35
adam@1 36 return r;
adam@1 37 }
adam@1 38
adam@1 39 typedef struct {
adam@1 40 uw_context ctx;
adam@2 41 uw_OpenidFfi_discovery d;
adam@1 42 } endpoint;
adam@1 43
adam@1 44 static void XMLCALL startElement(void *userData, const XML_Char *name, const XML_Char **atts) {
adam@1 45 endpoint *ep = userData;
adam@1 46
adam@1 47 if (!strcmp(name, "link")) {
adam@1 48 const XML_Char **attp;
adam@1 49 int found = 0;
adam@1 50
adam@1 51 for (attp = atts; *attp; attp += 2) {
adam@1 52 if (!strcmp(attp[0], "rel") && !strcmp(attp[1], "openid2.provider")) {
adam@1 53 found = 1;
adam@1 54 break;
adam@1 55 }
adam@1 56 }
adam@1 57
adam@1 58 if (found) {
adam@1 59 for (attp = atts; *attp; attp += 2) {
adam@1 60 if (!strcmp(attp[0], "href")) {
adam@2 61 ep->d->endpoint = uw_strdup(ep->ctx, attp[1]);
adam@1 62 return;
adam@1 63 }
adam@1 64 }
adam@1 65 }
adam@1 66 }
adam@1 67 }
adam@1 68
adam@1 69 static void XMLCALL endElement(void *userData, const XML_Char *name) {
adam@1 70 }
adam@1 71
adam@1 72 typedef struct {
adam@1 73 XML_Parser parser;
adam@1 74 int any_errors;
adam@1 75 } curl_data;
adam@1 76
adam@1 77 static size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp) {
adam@1 78 curl_data *d = userp;
adam@1 79
adam@1 80 if (!XML_Parse(d->parser, buffer, size * nmemb, 0))
adam@1 81 d->any_errors = 1;
adam@1 82
adam@1 83 return size * nmemb;
adam@1 84 }
adam@1 85
adam@2 86 uw_OpenidFfi_discovery *uw_OpenidFfi_discover(uw_context ctx, uw_Basis_string id) {
adam@1 87 char *s;
adam@1 88 CURL *c = curl(ctx);
adam@1 89 curl_data cd = {};
adam@2 90 uw_OpenidFfi_discovery dy = uw_malloc(ctx, sizeof(struct uw_OpenidFfi_discovery));
adam@2 91 endpoint ep = {ctx, dy};
adam@1 92 CURLcode code;
adam@1 93
adam@2 94 dy->endpoint = dy->localId = NULL;
adam@2 95
adam@1 96 if (!strchr(id, ':')) {
adam@1 97 id = uw_Basis_strcat(ctx, "http://", id);
adam@1 98 if ((s = strchr(id, '#')) != NULL)
adam@1 99 *s = 0;
adam@1 100 } else if ((s = strchr(id, '#')) != NULL) {
adam@1 101 char *id2 = uw_malloc(ctx, s - id + 1);
adam@1 102 memcpy(id2, s, s - id);
adam@1 103 id2[s - id] = 0;
adam@1 104 id = id2;
adam@1 105 }
adam@1 106
adam@1 107 cd.parser = XML_ParserCreate(NULL);
adam@1 108 XML_SetUserData(cd.parser, &ep);
adam@1 109 uw_push_cleanup(ctx, (void (*)(void *))XML_ParserFree, cd.parser);
adam@1 110 XML_SetElementHandler(cd.parser, startElement, endElement);
adam@1 111
adam@1 112 curl_easy_setopt(c, CURLOPT_URL, id);
adam@1 113 curl_easy_setopt(c, CURLOPT_WRITEFUNCTION, write_data);
adam@1 114 curl_easy_setopt(c, CURLOPT_WRITEDATA, &cd);
adam@1 115
adam@1 116 code = curl_easy_perform(c);
adam@1 117 uw_pop_cleanup(ctx);
adam@1 118
adam@2 119 if (code || !ep.d->endpoint)
adam@1 120 return NULL;
adam@2 121 else {
adam@2 122 uw_OpenidFfi_discovery *dyp = malloc(sizeof(uw_OpenidFfi_discovery));
adam@2 123 *dyp = ep.d;
adam@2 124 return dyp;
adam@2 125 }
adam@1 126 }