END_TEST START_TEST(test_nodeprep_validate) { char *longnode; fail_unless(jabber_nodeprep_validate(NULL)); fail_unless(jabber_nodeprep_validate("foo")); fail_unless(jabber_nodeprep_validate("%d")); fail_unless(jabber_nodeprep_validate("y\\z")); longnode = g_strnfill(1023, 'a'); fail_unless(jabber_nodeprep_validate(longnode)); g_free(longnode); }
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); }
END_TEST START_TEST(test_nodeprep_validate_too_long) { char *longnode = g_strnfill(1024, 'a'); fail_if(jabber_nodeprep_validate(longnode)); g_free(longnode); }
END_TEST START_TEST(test_nodeprep_validate_illegal_chars) { fail_if(jabber_nodeprep_validate("don't")); fail_if(jabber_nodeprep_validate("m@ke")); fail_if(jabber_nodeprep_validate("\"me\"")); fail_if(jabber_nodeprep_validate("&ngry")); fail_if(jabber_nodeprep_validate("c:")); fail_if(jabber_nodeprep_validate("a/b")); fail_if(jabber_nodeprep_validate("4>2")); fail_if(jabber_nodeprep_validate("4<7")); }
JabberID* jabber_id_new(const char *str) { char *at; char *slash; JabberID *jid; if(!str || !g_utf8_validate(str, -1, NULL)) return NULL; jid = g_new0(JabberID, 1); at = g_utf8_strchr(str, -1, '@'); slash = g_utf8_strchr(str, -1, '/'); if(at) { jid->node = g_utf8_normalize(str, at-str, G_NORMALIZE_NFKC); if(slash) { jid->domain = g_utf8_normalize(at+1, slash-(at+1), G_NORMALIZE_NFKC); jid->resource = g_utf8_normalize(slash+1, -1, G_NORMALIZE_NFKC); } else { jid->domain = g_utf8_normalize(at+1, -1, G_NORMALIZE_NFKC); } } else { if(slash) { jid->domain = g_utf8_normalize(str, slash-str, G_NORMALIZE_NFKC); jid->resource = g_utf8_normalize(slash+1, -1, G_NORMALIZE_NFKC); } else { jid->domain = g_utf8_normalize(str, -1, G_NORMALIZE_NFKC); } } if(!jabber_nodeprep_validate(jid->node) || !jabber_nameprep_validate(jid->domain) || !jabber_resourceprep_validate(jid->resource)) { jabber_id_free(jid); return NULL; } return jid; }
void jabber_chat_join(PurpleConnection *gc, GHashTable *data) { JabberChat *chat; char *room, *server, *handle, *passwd; xmlnode *presence, *x; char *tmp, *room_jid, *full_jid; JabberStream *js = gc->proto_data; PurplePresence *gpresence; PurpleStatus *status; JabberBuddyState state; char *msg; int priority; 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); g_free(buf); return; } else if(!jabber_nameprep_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); 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); } if(jabber_chat_find(js, room, server)) return; tmp = g_strdup_printf("%s@%s", room, server); room_jid = g_strdup(jabber_normalize(NULL, tmp)); g_free(tmp); chat = g_new0(JabberChat, 1); chat->js = gc->proto_data; chat->room = g_strdup(room); chat->server = g_strdup(server); chat->handle = g_strdup(handle); chat->members = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, (GDestroyNotify)jabber_chat_member_free); g_hash_table_insert(js->chats, room_jid, chat); gpresence = purple_account_get_presence(gc->account); status = purple_presence_get_active_status(gpresence); purple_status_to_jabber(status, &state, &msg, &priority); presence = jabber_presence_create(state, msg, priority); full_jid = g_strdup_printf("%s/%s", room_jid, handle); xmlnode_set_attrib(presence, "to", full_jid); g_free(full_jid); g_free(msg); x = xmlnode_new_child(presence, "x"); xmlnode_set_namespace(x, "http://jabber.org/protocol/muc"); if(passwd && *passwd) { xmlnode *password = xmlnode_new_child(x, "password"); xmlnode_insert_data(password, passwd, -1); } jabber_send(js, presence); xmlnode_free(presence); }
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 */ }