comparison src/c/openid.c @ 3:f59083771ee2

Saving associations
author Adam Chlipala <adam@chlipala.net>
date Sun, 26 Dec 2010 15:11:23 -0500
parents b757dc2bd2f6
children 2d409aff8800
comparison
equal deleted inserted replaced
2:b757dc2bd2f6 3:f59083771ee2
3 #include <openssl/sha.h> 3 #include <openssl/sha.h>
4 #include <curl/curl.h> 4 #include <curl/curl.h>
5 #include <expat.h> 5 #include <expat.h>
6 6
7 #include <openid.h> 7 #include <openid.h>
8
9 #define BUF_MAX 10240
10 #define BUF_INIT 1024
8 11
9 struct uw_OpenidFfi_discovery { 12 struct uw_OpenidFfi_discovery {
10 uw_Basis_string endpoint, localId; 13 uw_Basis_string endpoint, localId;
11 }; 14 };
12 15
70 } 73 }
71 74
72 typedef struct { 75 typedef struct {
73 XML_Parser parser; 76 XML_Parser parser;
74 int any_errors; 77 int any_errors;
75 } curl_data; 78 } curl_discovery_data;
76 79
77 static size_t write_data(void *buffer, size_t size, size_t nmemb, void *userp) { 80 static size_t write_discovery_data(void *buffer, size_t size, size_t nmemb, void *userp) {
78 curl_data *d = userp; 81 curl_discovery_data *d = userp;
79 82
80 if (!XML_Parse(d->parser, buffer, size * nmemb, 0)) 83 if (!XML_Parse(d->parser, buffer, size * nmemb, 0))
81 d->any_errors = 1; 84 d->any_errors = 1;
82 85
83 return size * nmemb; 86 return size * nmemb;
84 } 87 }
85 88
86 uw_OpenidFfi_discovery *uw_OpenidFfi_discover(uw_context ctx, uw_Basis_string id) { 89 uw_OpenidFfi_discovery *uw_OpenidFfi_discover(uw_context ctx, uw_Basis_string id) {
87 char *s; 90 char *s;
88 CURL *c = curl(ctx); 91 CURL *c = curl(ctx);
89 curl_data cd = {}; 92 curl_discovery_data cd = {};
90 uw_OpenidFfi_discovery dy = uw_malloc(ctx, sizeof(struct uw_OpenidFfi_discovery)); 93 uw_OpenidFfi_discovery dy = uw_malloc(ctx, sizeof(struct uw_OpenidFfi_discovery));
91 endpoint ep = {ctx, dy}; 94 endpoint ep = {ctx, dy};
92 CURLcode code; 95 CURLcode code;
93 96
94 dy->endpoint = dy->localId = NULL; 97 dy->endpoint = dy->localId = NULL;
108 XML_SetUserData(cd.parser, &ep); 111 XML_SetUserData(cd.parser, &ep);
109 uw_push_cleanup(ctx, (void (*)(void *))XML_ParserFree, cd.parser); 112 uw_push_cleanup(ctx, (void (*)(void *))XML_ParserFree, cd.parser);
110 XML_SetElementHandler(cd.parser, startElement, endElement); 113 XML_SetElementHandler(cd.parser, startElement, endElement);
111 114
112 curl_easy_setopt(c, CURLOPT_URL, id); 115 curl_easy_setopt(c, CURLOPT_URL, id);
113 curl_easy_setopt(c, CURLOPT_WRITEFUNCTION, write_data); 116 curl_easy_setopt(c, CURLOPT_WRITEFUNCTION, write_discovery_data);
114 curl_easy_setopt(c, CURLOPT_WRITEDATA, &cd); 117 curl_easy_setopt(c, CURLOPT_WRITEDATA, &cd);
115 118
116 code = curl_easy_perform(c); 119 code = curl_easy_perform(c);
117 uw_pop_cleanup(ctx); 120 uw_pop_cleanup(ctx);
118 121
122 uw_OpenidFfi_discovery *dyp = malloc(sizeof(uw_OpenidFfi_discovery)); 125 uw_OpenidFfi_discovery *dyp = malloc(sizeof(uw_OpenidFfi_discovery));
123 *dyp = ep.d; 126 *dyp = ep.d;
124 return dyp; 127 return dyp;
125 } 128 }
126 } 129 }
130
131 uw_OpenidFfi_inputs uw_OpenidFfi_createInputs(uw_context ctx) {
132 uw_buffer *r = uw_malloc(ctx, sizeof(uw_buffer));
133 uw_buffer_init(BUF_MAX, r, BUF_INIT);
134 return r;
135 }
136
137 static int okForPost(const char *s) {
138 for (; *s; ++s)
139 if (*s == '=' || *s == '&')
140 return 0;
141 return 1;
142 }
143
144 uw_unit uw_OpenidFfi_addInput(uw_context ctx, uw_OpenidFfi_inputs buf, uw_Basis_string key, uw_Basis_string value) {
145 if (!okForPost(key))
146 uw_error(ctx, FATAL, "Invalid key for OpenID inputs");
147 if (!okForPost(value))
148 uw_error(ctx, FATAL, "Invalid value for OpenID inputs");
149
150 if (uw_buffer_used(buf) > 0)
151 uw_buffer_append(buf, "&", 1);
152
153 uw_buffer_append(buf, key, strlen(key));
154 uw_buffer_append(buf, "=", 1);
155 uw_buffer_append(buf, value, strlen(value));
156
157 return uw_unit_v;
158 }
159
160 uw_Basis_string uw_OpenidFfi_getOutput(uw_context ctx, uw_OpenidFfi_outputs buf, uw_Basis_string key) {
161 char *s = buf->start;
162
163 for (; *s; s = strchr(strchr(s, 0)+1, 0)+1)
164 if (!strcmp(key, s))
165 return strchr(s, 0)+1;
166
167 return NULL;
168 }
169
170 static size_t write_buffer_data(void *buffer, size_t size, size_t nmemb, void *userp) {
171 uw_buffer *buf = userp;
172
173 uw_buffer_append(buf, buffer, size * nmemb);
174
175 return size * nmemb;
176 }
177
178 const char curl_failure[] = "error\0Error fetching URL";
179
180 uw_OpenidFfi_outputs uw_OpenidFfi_indirect(uw_context ctx, uw_Basis_string url, uw_OpenidFfi_inputs inps) {
181 uw_buffer *buf = uw_malloc(ctx, sizeof(uw_buffer));
182 CURL *c = curl(ctx);
183 CURLcode code;
184
185 uw_buffer_init(BUF_MAX, buf, BUF_INIT);
186
187 uw_buffer_append(inps, "", 1);
188
189 curl_easy_setopt(c, CURLOPT_URL, url);
190 curl_easy_setopt(c, CURLOPT_POSTFIELDS, inps->start);
191 curl_easy_setopt(c, CURLOPT_WRITEFUNCTION, write_buffer_data);
192 curl_easy_setopt(c, CURLOPT_WRITEDATA, buf);
193
194 code = curl_easy_perform(c);
195
196 uw_buffer_append(buf, "", 1);
197
198 if (code) {
199 uw_buffer_reset(buf);
200 uw_buffer_append(buf, curl_failure, sizeof curl_failure);
201 } else {
202 char *s;
203
204 s = buf->start;
205 while (*s) {
206 char *colon = strchr(s, ':'), *newline;
207
208 if (!colon) {
209 *s = 0;
210 break;
211 }
212
213 newline = strchr(colon+1, '\n');
214
215 if (!newline) {
216 *s = 0;
217 break;
218 }
219
220 *colon = 0;
221 *newline = 0;
222 s = newline+1;
223 }
224 }
225
226 return buf;
227 }