+void HFreePropertyHandler(void *FreeMe)
+{
+ free(FreeMe);
+}
+
+void HDeleteTokenHandler(void *FreeMe)
+{
+ TokenHandler *th = (TokenHandler *) FreeMe;
+ DeleteHash(&th->Properties);
+ free(th);
+}
+
+void XMPP_RegisterTokenProperty(const char *NS, long NSLen,
+ const char *Token, long TLen,
+ const char *Property, long PLen,
+ GetTokenDataFunc GetToken,
+ long offset)
+{
+ void *pv;
+ HashList *ThisNamespace = NULL;
+ PropertyHandler *h;
+ TokenHandler *th;
+
+ h = (PropertyHandler*) malloc(sizeof(PropertyHandler));
+ h->NameSpace = NS;
+ h->NameSpaceLen = NSLen;
+ h->Token = Token;
+ h->TokenLen = TLen;
+ h->Property = Property;
+ h->PropertyLen = PLen;
+ h->offset = offset;
+
+ if (!GetHash(XMPP_SupportedNamespaces, NS, NSLen, &pv))
+ {
+ Put(XMPP_SupportedNamespaces, NS, NSLen, NewStrBufPlain(NS, NSLen), HFreeStrBuf);
+ }
+
+
+ if (GetHash(XMPP_NameSpaces, NS, NSLen, &pv))
+ {
+ ThisNamespace = pv;
+ }
+ else
+ {
+ ThisNamespace = NewHash(1, NULL);
+ Put(XMPP_NameSpaces, NS, NSLen, ThisNamespace, HDeleteHash);
+ }
+
+ if (GetHash(ThisNamespace, Token, TLen, &pv))
+ {
+ th = pv;
+ }
+ else
+ {
+ th = (TokenHandler*) malloc (sizeof(TokenHandler));
+ th->GetToken = GetToken;
+ th->Properties = NewHash(1, NULL);
+ Put(ThisNamespace, Token, TLen, th, HDeleteTokenHandler);
+ }
+
+
+ if (PLen > 0)
+ Put(th->Properties, Property, PLen, h, HFreePropertyHandler);
+ /*
+ if (!GetHash(FlatToken, Token, TLen, &pv))
+ {
+ // todo mark pv as non uniq
+ Put(FlatToken, Token, TLen, ThisToken, reference_free_handler);
+ }
+ */
+}
+
+void xmpp_cleanup(void)
+{
+ DeleteHash(&XMPP_StartHandlers);
+ DeleteHash(&XMPP_EndHandlers);
+ DeleteHash(&XMPP_SupportedNamespaces);
+ DeleteHash(&XMPP_NameSpaces);
+ DeleteHash(&FlatToken);
+}
+