void jabber_chat_join(PurpleConnection *gc, GHashTable *data) { char *room, *server, *handle, *passwd; JabberID *jid; JabberStream *js = gc->proto_data; char *tmp; room = g_hash_table_lookup(data, "room"); server = g_hash_table_lookup(data, "server"); handle = g_hash_table_lookup(data, "handle"); passwd = g_hash_table_lookup(data, "password"); if(!room || !server) return; if(!handle) handle = js->user->node; if(!jabber_nodeprep_validate(room)) { char *buf = g_strdup_printf(_("%s is not a valid room name"), room); purple_notify_error(gc, _("Invalid Room Name"), _("Invalid Room Name"), buf); purple_serv_got_join_chat_failed(gc, data); g_free(buf); return; } else if(!jabber_domain_validate(server)) { char *buf = g_strdup_printf(_("%s is not a valid server name"), server); purple_notify_error(gc, _("Invalid Server Name"), _("Invalid Server Name"), buf); purple_serv_got_join_chat_failed(gc, data); g_free(buf); return; } else if(!jabber_resourceprep_validate(handle)) { char *buf = g_strdup_printf(_("%s is not a valid room handle"), handle); purple_notify_error(gc, _("Invalid Room Handle"), _("Invalid Room Handle"), buf); purple_serv_got_join_chat_failed(gc, data); g_free(buf); return; } /* Normalize the room and server parameters */ tmp = g_strdup_printf("%s@%s", room, server); jid = jabber_id_new(tmp); g_free(tmp); if (jid == NULL) { /* TODO: Error message */ g_return_if_reached(); } /* * Now that we've done all that nice core-interface stuff, let's join * this room! */ jabber_join_chat(js, jid->node, jid->domain, handle, passwd, data); jabber_id_free(jid); }
static JabberID* jabber_id_new_internal(const char *str, gboolean allow_terminating_slash) { const char *at = NULL; const char *slash = NULL; const char *c; gboolean needs_validation = FALSE; #if 0 gboolean node_is_required = FALSE; #endif #ifndef USE_IDN char *node = NULL; char *domain; #endif JabberID *jid; if (!str) return NULL; for (c = str; *c != '\0'; c++) { switch (*c) { case '@': if (!slash) { if (at) { /* Multiple @'s in the node/domain portion, not a valid JID! */ return NULL; } if (c == str) { /* JIDs cannot start with @ */ return NULL; } if (c[1] == '\0') { /* JIDs cannot end with @ */ return NULL; } at = c; } break; case '/': if (!slash) { if (c == str) { /* JIDs cannot start with / */ return NULL; } if (c[1] == '\0' && !allow_terminating_slash) { /* JIDs cannot end with / */ return NULL; } slash = c; } break; default: /* characters allowed everywhere */ if ((*c >= 'a' && *c <= 'z') || (*c >= '0' && *c <= '9') || (*c >= 'A' && *c <= 'Z') || *c == '.' || *c == '-') /* We're good */ break; #if 0 if (slash != NULL) { /* characters allowed only in the resource */ if (implement_me) /* We're good */ break; } /* characters allowed only in the node */ if (implement_me) { /* * Ok, this character is valid, but only if it's a part * of the node and not the domain. But we don't know * if "c" is a part of the node or the domain until after * we've found the @. So set a flag for now and check * that we found an @ later. */ node_is_required = TRUE; break; } #endif /* * Hmm, this character is a bit more exotic. Better fall * back to using the more expensive UTF-8 compliant * stringprep functions. */ needs_validation = TRUE; break; } } #if 0 if (node_is_required && at == NULL) /* Found invalid characters in the domain */ return NULL; #endif if (!needs_validation) { /* JID is made of only ASCII characters--just lowercase and return */ jid = g_new0(JabberID, 1); if (at) { jid->node = g_ascii_strdown(str, at - str); if (slash) { jid->domain = g_ascii_strdown(at + 1, slash - (at + 1)); if (*(slash + 1)) jid->resource = g_strdup(slash + 1); } else { jid->domain = g_ascii_strdown(at + 1, -1); } } else { if (slash) { jid->domain = g_ascii_strdown(str, slash - str); if (*(slash + 1)) jid->resource = g_strdup(slash + 1); } else { jid->domain = g_ascii_strdown(str, -1); } } return jid; } /* * If we get here, there are some non-ASCII chars in the string, so * we'll need to validate it, normalize, and finally do a full jabber * nodeprep on the jid. */ if (!g_utf8_validate(str, -1, NULL)) return NULL; #ifdef USE_IDN return jabber_idn_validate(str, at, slash, c /* points to the null */); #else /* USE_IDN */ jid = g_new0(JabberID, 1); /* normalization */ if(at) { node = g_utf8_casefold(str, at-str); if(slash) { domain = g_utf8_casefold(at+1, slash-(at+1)); if (*(slash + 1)) jid->resource = g_utf8_normalize(slash+1, -1, G_NORMALIZE_NFKC); } else { domain = g_utf8_casefold(at+1, -1); } } else { if(slash) { domain = g_utf8_casefold(str, slash-str); if (*(slash + 1)) jid->resource = g_utf8_normalize(slash+1, -1, G_NORMALIZE_NFKC); } else { domain = g_utf8_casefold(str, -1); } } if (node) { jid->node = g_utf8_normalize(node, -1, G_NORMALIZE_NFKC); g_free(node); } if (domain) { jid->domain = g_utf8_normalize(domain, -1, G_NORMALIZE_NFKC); g_free(domain); } /* and finally the jabber nodeprep */ if(!jabber_nodeprep_validate(jid->node) || !jabber_domain_validate(jid->domain) || !jabber_resourceprep_validate(jid->resource)) { jabber_id_free(jid); return NULL; } return jid; #endif /* USE_IDN */ }