+ char *desired_name = NULL;
+ char new_password[32];
+ long len;
+
+ if (config.c_auth_mode != AUTHMODE_NATIVE) return(1);
+ if (config.c_disable_newu) return(2);
+ if (CC->logged_in) return(3);
+ if (!GetHash(sreg_keys, "sreg.nickname", 13, (void *) &desired_name)) return(4);
+
+ syslog(LOG_DEBUG, "The desired account name is <%s>", desired_name);
+
+ len = cutuserkey(desired_name);
+ if (!CtdlGetUser(&CC->user, desired_name)) {
+ syslog(LOG_DEBUG, "<%s> is already taken by another user.", desired_name);
+ memset(&CC->user, 0, sizeof(struct ctdluser));
+ return(5);
+ }
+
+ /* The desired account name is available. Create the account and log it in! */
+ if (create_user(desired_name, len, 1)) return(6);
+
+ snprintf(new_password, sizeof new_password, "%08lx%08lx", random(), random());
+ CtdlSetPassword(new_password);
+ attach_openid(&CC->user, claimed_id);
+ populate_vcard_from_sreg(sreg_keys);
+ return(0);
+}
+
+
+/*
+ * If a user account exists which is associated with the Claimed ID, log it in and return zero.
+ * Otherwise it returns nonzero.
+ */
+int login_via_openid(StrBuf *claimed_id)
+{
+ struct cdbdata *cdboi;
+ long usernum = 0;
+
+ cdboi = cdb_fetch(CDB_OPENID, ChrPtr(claimed_id), StrLength(claimed_id));
+ if (cdboi == NULL) {
+ return(-1);
+ }
+
+ memcpy(&usernum, cdboi->ptr, sizeof(long));
+ cdb_free(cdboi);
+
+ if (!CtdlGetUserByNumber(&CC->user, usernum)) {
+ /* Now become the user we just created */
+ safestrncpy(CC->curr_user, CC->user.fullname, sizeof CC->curr_user);
+ do_login();
+ return(0);
+ }
+ else {
+ memset(&CC->user, 0, sizeof(struct ctdluser));
+ return(-1);
+ }
+}
+
+
+
+
+/**************************************************************************/
+/* */
+/* Functions in this section handle OpenID protocol */
+/* */
+/**************************************************************************/
+
+
+/*
+ * Locate a <link> tag and, given its 'rel=' parameter, return its 'href' parameter
+ */
+void extract_link(StrBuf *target_buf, const char *rel, long repllen, StrBuf *source_buf)
+{
+ int i;
+ const char *ptr;
+ const char *href_start = NULL;
+ const char *href_end = NULL;
+ const char *link_tag_start = NULL;
+ const char *link_tag_end = NULL;
+ const char *rel_start = NULL;
+ const char *rel_end = NULL;
+
+ if (!target_buf) return;
+ if (!rel) return;
+ if (!source_buf) return;
+
+ ptr = ChrPtr(source_buf);
+
+ FlushStrBuf(target_buf);
+ while (ptr = cbmstrcasestr(ptr, "<link"), ptr != NULL) {
+
+ link_tag_start = ptr;
+ link_tag_end = strchr(ptr, '>');
+ if (link_tag_end == NULL)
+ break;
+ for (i=0; i < 1; i++ ){
+ rel_start = cbmstrcasestr(link_tag_start, "rel=");
+ if ((rel_start == NULL) ||
+ (rel_start > link_tag_end))
+ continue;
+
+ rel_start = strchr(rel_start, '\"');
+ if ((rel_start == NULL) ||
+ (rel_start > link_tag_end))
+ continue;
+ ++rel_start;
+ rel_end = strchr(rel_start, '\"');
+ if ((rel_end == NULL) ||
+ (rel_end == rel_start) ||
+ (rel_end >= link_tag_end) )
+ continue;
+ if (strncasecmp(rel, rel_start, repllen)!= 0)
+ continue; /* didn't match? never mind... */
+
+ href_start = cbmstrcasestr(link_tag_start, "href=");
+ if ((href_start == NULL) ||
+ (href_start >= link_tag_end))
+ continue;
+ href_start = strchr(href_start, '\"');
+ if ((href_start == NULL) |
+ (href_start >= link_tag_end))
+ continue;
+ ++href_start;
+ href_end = strchr(href_start, '\"');
+ if ((href_end == NULL) ||
+ (href_end == href_start) ||
+ (href_start >= link_tag_end))
+ continue;
+ StrBufPlain(target_buf, href_start, href_end - href_start);
+ }
+ ptr = link_tag_end;
+ }
+}
+