From 8c621b46145e07e3eb3515a58f44ae6cd62caf0d Mon Sep 17 00:00:00 2001 From: defanor Date: Fri, 27 Mar 2020 21:07:10 +0300 Subject: Move roster functions into a separate file --- src/Makefile.am | 7 ++- src/rexmpp.c | 135 +----------------------------------------------- src/rexmpp.h | 4 ++ src/rexmpp_roster.c | 146 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/rexmpp_roster.h | 20 +++++++ 5 files changed, 176 insertions(+), 136 deletions(-) create mode 100644 src/rexmpp_roster.c create mode 100644 src/rexmpp_roster.h diff --git a/src/Makefile.am b/src/Makefile.am index c3a62bf..741add0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -8,7 +8,10 @@ AM_CFLAGS = -Werror -Wall -Wextra -Wno-pointer-sign -Wno-unused-parameter lib_LTLIBRARIES = librexmpp.la -librexmpp_la_SOURCES = rexmpp_tcp.h rexmpp_tcp.c rexmpp_socks.h rexmpp_socks.c rexmpp.h rexmpp.c -include_HEADERS = rexmpp_tcp.h rexmpp_socks.h rexmpp.h +librexmpp_la_SOURCES = rexmpp_roster.h rexmpp_roster.c \ + rexmpp_tcp.h rexmpp_tcp.c \ + rexmpp_socks.h rexmpp_socks.c \ + rexmpp.h rexmpp.c +include_HEADERS = rexmpp_roster.h rexmpp_tcp.h rexmpp_socks.h rexmpp.h librexmpp_la_CFLAGS = $(AM_CFLAGS) $(LIBXML_CFLAGS) $(GNUTLS_CFLAGS) $(GSASL_CFLAGS) $(CARES_CFLAGS) librexmpp_la_LIBADD = $(LIBXML_LIBS) $(GNUTLS_LIBS) $(GSASL_LIBS) $(CARES_LIBS) diff --git a/src/rexmpp.c b/src/rexmpp.c index 51229b7..fe04481 100644 --- a/src/rexmpp.c +++ b/src/rexmpp.c @@ -23,7 +23,7 @@ #include "rexmpp.h" #include "rexmpp_tcp.h" #include "rexmpp_socks.h" - +#include "rexmpp_roster.h" void rexmpp_sax_start_elem_ns (rexmpp_t *s, const char *localname, @@ -1082,139 +1082,6 @@ void rexmpp_iq_discovery_info (rexmpp_t *s, } } -xmlNodePtr rexmpp_roster_find_item (rexmpp_t *s, - const char *jid, - xmlNodePtr *prev_item) -{ - xmlNodePtr prev = NULL, cur = s->roster_items; - while (cur != NULL) { - char *cur_jid = xmlGetProp(cur, "jid"); - if (cur_jid == NULL) { - rexmpp_log(s, LOG_ALERT, "No jid found in a roster item."); - return NULL; - } - int match = (strcmp(cur_jid, jid) == 0); - free(cur_jid); - if (match) { - if (prev_item != NULL) { - *prev_item = prev; - } - return cur; - } - prev = cur; - cur = cur->next; - } - return NULL; -} - -rexmpp_err_t rexmpp_modify_roster (rexmpp_t *s, xmlNodePtr item) { - rexmpp_err_t ret = REXMPP_SUCCESS; - if (! rexmpp_xml_match(item, "jabber:iq:roster", "item")) { - rexmpp_log(s, LOG_ERR, "No roster item."); - return REXMPP_E_PARAM; - } - char *subscription = xmlGetProp(item, "subscription"); - char *jid = xmlGetProp(item, "jid"); - if (subscription != NULL && strcmp(subscription, "remove") == 0) { - /* Delete the item. */ - xmlNodePtr prev, cur; - cur = rexmpp_roster_find_item(s, jid, &prev); - if (cur != NULL) { - if (prev != NULL) { - prev->next = cur->next; - } else { - s->roster_items = cur->next; - } - xmlFreeNode(cur); - } else { - ret = REXMPP_E_ROSTER_ITEM_NOT_FOUND; - } - } else { - /* Add or modify the item. */ - xmlNodePtr cur, prev; - cur = rexmpp_roster_find_item(s, jid, &prev); - /* Remove the item if it was in the roster before. */ - if (cur != NULL) { - if (prev != NULL) { - prev->next = cur->next; - } else { - s->roster_items = cur->next; - } - xmlFreeNode(cur); - } - /* Add the new item. */ - xmlNodePtr new_item = xmlCopyNode(item, 1); - new_item->next = s->roster_items; - s->roster_items = new_item; - } - free(jid); - if (subscription != NULL) { - free(subscription); - } - return ret; -} - -void rexmpp_roster_set (rexmpp_t *s, xmlNodePtr query) { - if (s->roster_items != NULL) { - xmlFreeNodeList(s->roster_items); - } - if (s->roster_ver != NULL) { - free(s->roster_ver); - } - s->roster_ver = xmlGetProp(query, "ver"); - s->roster_items = xmlCopyNodeList(xmlFirstElementChild(query)); -} - -void rexmpp_roster_cache_read (rexmpp_t *s) { - if (s->roster_cache_file == NULL) { - rexmpp_log(s, LOG_WARNING, "No roster cache file path is set."); - return; - } - xmlDocPtr doc = xmlReadFile(s->roster_cache_file, "utf-8", XML_PARSE_NONET); - xmlNodePtr query = xmlDocGetRootElement(doc); - rexmpp_roster_set(s, query); - xmlFreeDoc(doc); -} - -void rexmpp_roster_cache_write (rexmpp_t *s) { - if (s->roster_cache_file == NULL) { - rexmpp_log(s, LOG_WARNING, "No roster cache file path is set."); - return; - } - xmlDocPtr doc = xmlNewDoc("1.0"); - xmlNodePtr query = xmlNewDocNode(doc, NULL, "query", NULL); - xmlDocSetRootElement(doc, query); - xmlNewNs(query, "jabber:iq:roster", NULL); - if (s->roster_ver != NULL) { - xmlNewProp(query, "ver", s->roster_ver); - } - if (s->roster_items != NULL) { - xmlAddChild(query, xmlDocCopyNodeList(doc, s->roster_items)); - } - xmlSaveFileEnc(s->roster_cache_file, doc, "utf-8"); - xmlFreeDoc(doc); -} - -void rexmpp_iq_roster_get (rexmpp_t *s, - xmlNodePtr req, - xmlNodePtr response, - int success) -{ - if (! success) { - rexmpp_log(s, LOG_ERR, "Roster loading failed."); - return; - } - xmlNodePtr query = xmlFirstElementChild(response); - if (! rexmpp_xml_match(query, "jabber:iq:roster", "query")) { - rexmpp_log(s, LOG_DEBUG, "No roster query in reply."); - return; - } - rexmpp_roster_set(s, query); - if (s->roster_cache_file != NULL) { - rexmpp_roster_cache_write(s); - } -} - void rexmpp_stream_is_ready(rexmpp_t *s) { s->stream_state = REXMPP_STREAM_READY; rexmpp_resend_stanzas(s); diff --git a/src/rexmpp.h b/src/rexmpp.h index c7b07b0..7679546 100644 --- a/src/rexmpp.h +++ b/src/rexmpp.h @@ -390,4 +390,8 @@ int rexmpp_fds (rexmpp_t *s, fd_set *read_fds, fd_set *write_fds); char *rexmpp_xml_serialize (xmlNodePtr node); xmlNodePtr rexmpp_xml_add_id (rexmpp_t *s, xmlNodePtr node); +void rexmpp_log (rexmpp_t *s, int priority, const char *format, ...); +int rexmpp_xml_match (xmlNodePtr node, + const char *namespace, + const char *name); #endif diff --git a/src/rexmpp_roster.c b/src/rexmpp_roster.c new file mode 100644 index 0000000..8479c14 --- /dev/null +++ b/src/rexmpp_roster.c @@ -0,0 +1,146 @@ +/** + @file rexmpp_roster.c + @brief Roster-related functions. + @author defanor + @date 2020 + @copyright MIT license. +*/ + +#include "rexmpp.h" +#include +#include +#include +#include + +xmlNodePtr rexmpp_roster_find_item (rexmpp_t *s, + const char *jid, + xmlNodePtr *prev_item) +{ + xmlNodePtr prev = NULL, cur = s->roster_items; + while (cur != NULL) { + char *cur_jid = xmlGetProp(cur, "jid"); + if (cur_jid == NULL) { + rexmpp_log(s, LOG_ALERT, "No jid found in a roster item."); + return NULL; + } + int match = (strcmp(cur_jid, jid) == 0); + free(cur_jid); + if (match) { + if (prev_item != NULL) { + *prev_item = prev; + } + return cur; + } + prev = cur; + cur = cur->next; + } + return NULL; +} + +rexmpp_err_t rexmpp_modify_roster (rexmpp_t *s, xmlNodePtr item) { + rexmpp_err_t ret = REXMPP_SUCCESS; + if (! rexmpp_xml_match(item, "jabber:iq:roster", "item")) { + rexmpp_log(s, LOG_ERR, "No roster item."); + return REXMPP_E_PARAM; + } + char *subscription = xmlGetProp(item, "subscription"); + char *jid = xmlGetProp(item, "jid"); + if (subscription != NULL && strcmp(subscription, "remove") == 0) { + /* Delete the item. */ + xmlNodePtr prev, cur; + cur = rexmpp_roster_find_item(s, jid, &prev); + if (cur != NULL) { + if (prev != NULL) { + prev->next = cur->next; + } else { + s->roster_items = cur->next; + } + xmlFreeNode(cur); + } else { + ret = REXMPP_E_ROSTER_ITEM_NOT_FOUND; + } + } else { + /* Add or modify the item. */ + xmlNodePtr cur, prev; + cur = rexmpp_roster_find_item(s, jid, &prev); + /* Remove the item if it was in the roster before. */ + if (cur != NULL) { + if (prev != NULL) { + prev->next = cur->next; + } else { + s->roster_items = cur->next; + } + xmlFreeNode(cur); + } + /* Add the new item. */ + xmlNodePtr new_item = xmlCopyNode(item, 1); + new_item->next = s->roster_items; + s->roster_items = new_item; + } + free(jid); + if (subscription != NULL) { + free(subscription); + } + return ret; +} + +void rexmpp_roster_set (rexmpp_t *s, xmlNodePtr query) { + if (s->roster_items != NULL) { + xmlFreeNodeList(s->roster_items); + } + if (s->roster_ver != NULL) { + free(s->roster_ver); + } + s->roster_ver = xmlGetProp(query, "ver"); + s->roster_items = xmlCopyNodeList(xmlFirstElementChild(query)); +} + +void rexmpp_roster_cache_read (rexmpp_t *s) { + if (s->roster_cache_file == NULL) { + rexmpp_log(s, LOG_WARNING, "No roster cache file path is set."); + return; + } + xmlDocPtr doc = xmlReadFile(s->roster_cache_file, "utf-8", XML_PARSE_NONET); + xmlNodePtr query = xmlDocGetRootElement(doc); + rexmpp_roster_set(s, query); + xmlFreeDoc(doc); +} + +void rexmpp_roster_cache_write (rexmpp_t *s) { + if (s->roster_cache_file == NULL) { + rexmpp_log(s, LOG_WARNING, "No roster cache file path is set."); + return; + } + xmlDocPtr doc = xmlNewDoc("1.0"); + xmlNodePtr query = xmlNewDocNode(doc, NULL, "query", NULL); + xmlDocSetRootElement(doc, query); + xmlNewNs(query, "jabber:iq:roster", NULL); + if (s->roster_ver != NULL) { + xmlNewProp(query, "ver", s->roster_ver); + } + if (s->roster_items != NULL) { + xmlAddChild(query, xmlDocCopyNodeList(doc, s->roster_items)); + } + xmlSaveFileEnc(s->roster_cache_file, doc, "utf-8"); + xmlFreeDoc(doc); +} + +void rexmpp_iq_roster_get (rexmpp_t *s, + xmlNodePtr req, + xmlNodePtr response, + int success) +{ + if (! success) { + rexmpp_log(s, LOG_ERR, "Roster loading failed."); + return; + } + xmlNodePtr query = xmlFirstElementChild(response); + if (! rexmpp_xml_match(query, "jabber:iq:roster", "query")) { + rexmpp_log(s, LOG_DEBUG, "No roster query in reply."); + return; + } + rexmpp_roster_set(s, query); + if (s->roster_cache_file != NULL) { + rexmpp_roster_cache_write(s); + } +} diff --git a/src/rexmpp_roster.h b/src/rexmpp_roster.h new file mode 100644 index 0000000..d9e41fd --- /dev/null +++ b/src/rexmpp_roster.h @@ -0,0 +1,20 @@ +/** + @file rexmpp_roster.h + @brief Roster-related functions. + @author defanor + @date 2020 + @copyright MIT license. +*/ + + +xmlNodePtr rexmpp_roster_find_item (rexmpp_t *s, + const char *jid, + xmlNodePtr *prev_item); +rexmpp_err_t rexmpp_modify_roster (rexmpp_t *s, xmlNodePtr item); +void rexmpp_roster_set (rexmpp_t *s, xmlNodePtr query); +void rexmpp_roster_cache_read (rexmpp_t *s); +void rexmpp_roster_cache_write (rexmpp_t *s); +void rexmpp_iq_roster_get (rexmpp_t *s, + xmlNodePtr req, + xmlNodePtr response, + int success); -- cgit v1.2.3