telepathygabble/src/util.c
changeset 10 59927b2d3b75
parent 0 d0f3a028347a
equal deleted inserted replaced
0:d0f3a028347a 10:59927b2d3b75
     1 /*
       
     2  * util.c - Source for Gabble utility functions
       
     3  * Copyright (C) 2006 Collabora Ltd.
       
     4  * 
       
     5  *   @author Robert McQueen <robert.mcqueen@collabora.co.uk>
       
     6  *
       
     7  * This library is free software; you can redistribute it and/or
       
     8  * modify it under the terms of the GNU Lesser General Public
       
     9  * License as published by the Free Software Foundation; either
       
    10  * version 2.1 of the License, or (at your option) any later version.
       
    11  *
       
    12  * This library is distributed in the hope that it will be useful,
       
    13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    15  * Lesser General Public License for more details.
       
    16  *
       
    17  * You should have received a copy of the GNU Lesser General Public
       
    18  * License along with this library; if not, write to the Free Software
       
    19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
       
    20  */
       
    21 
       
    22 #include <glib.h>
       
    23 #include <string.h>
       
    24 #include <stdio.h>
       
    25 #include "namespaces.h"
       
    26 #include "gabble-connection.h"
       
    27 
       
    28 #include "util.h"
       
    29 #include "sha1.h"
       
    30 
       
    31 gchar *
       
    32 sha1_hex (const gchar *bytes, guint len)
       
    33 {
       
    34   SHA1Context sc;
       
    35   uint8_t hash[SHA1_HASH_SIZE];
       
    36   gchar *hex_hash = g_malloc (SHA1_HASH_SIZE*2 + 1);
       
    37   int i;
       
    38 
       
    39   SHA1Init (&sc);
       
    40   SHA1Update (&sc, bytes, len);
       
    41   SHA1Final (&sc, hash);
       
    42 
       
    43   for (i = 0; i < SHA1_HASH_SIZE; i++)
       
    44     {
       
    45       sprintf (hex_hash + 2 * i, "%02x", (unsigned int) hash[i]);
       
    46     }
       
    47 
       
    48   return hex_hash;
       
    49 }
       
    50 
       
    51 gboolean
       
    52 g_strdiff (const gchar *left, const gchar *right)
       
    53 {
       
    54   if ((NULL == left) != (NULL == right))
       
    55     return TRUE;
       
    56 
       
    57   else if (left == right)
       
    58     return FALSE;
       
    59 
       
    60   else
       
    61     return (0 != strcmp (left, right));
       
    62 }
       
    63 
       
    64 static void
       
    65 lm_message_node_add_nick (LmMessageNode *node, const gchar *nick)
       
    66 {
       
    67   LmMessageNode *nick_node;
       
    68 
       
    69   nick_node = lm_message_node_add_child (node, "nick", nick);
       
    70   lm_message_node_set_attribute (nick_node, "xmlns", NS_NICK);
       
    71 }
       
    72 
       
    73 void
       
    74 lm_message_node_add_own_nick (LmMessageNode *node,
       
    75                               GabbleConnection *connection)
       
    76 {
       
    77   gchar *nick;
       
    78   GabbleConnectionAliasSource source;
       
    79 
       
    80   source = _gabble_connection_get_cached_alias (connection,
       
    81         connection->self_handle, &nick);
       
    82 
       
    83   if (source > GABBLE_CONNECTION_ALIAS_FROM_JID)
       
    84     lm_message_node_add_nick (node, nick);
       
    85 
       
    86   g_free (nick);
       
    87 }
       
    88 
       
    89 void
       
    90 lm_message_node_steal_children (LmMessageNode *snatcher,
       
    91                                 LmMessageNode *mum)
       
    92 {
       
    93   LmMessageNode *baby;
       
    94 
       
    95   g_return_if_fail (snatcher->children == NULL);
       
    96 
       
    97   if (mum->children == NULL)
       
    98     return;
       
    99 
       
   100   snatcher->children = mum->children;
       
   101   mum->children = NULL;
       
   102 
       
   103   for (baby = snatcher->children;
       
   104        baby != NULL;
       
   105        baby = baby->next)
       
   106     baby->parent = snatcher;
       
   107 }
       
   108 
       
   109 gboolean
       
   110 lm_message_node_has_namespace (LmMessageNode *node,
       
   111                                const gchar *ns,
       
   112                                const gchar *tag)
       
   113 {
       
   114   gchar *attribute = NULL;
       
   115   const gchar *node_ns;
       
   116   gboolean ret;
       
   117 
       
   118   if (tag != NULL)
       
   119     attribute = g_strconcat ("xmlns:", tag, NULL);
       
   120 
       
   121   node_ns = lm_message_node_get_attribute (node,
       
   122       tag != NULL ? attribute : "xmlns");
       
   123 
       
   124   ret = !g_strdiff (node_ns, ns);
       
   125 
       
   126   g_free (attribute);
       
   127 
       
   128   return ret;
       
   129 }
       
   130 
       
   131 LmMessageNode *
       
   132 lm_message_node_get_child_with_namespace (LmMessageNode *node,
       
   133                                           const gchar *name,
       
   134                                           const gchar *ns)
       
   135 {
       
   136   LmMessageNode *tmp;
       
   137 
       
   138   for (tmp = node->children;
       
   139        tmp != NULL;
       
   140        tmp = tmp->next)
       
   141     {
       
   142       gchar *tag = NULL;
       
   143       gboolean found;
       
   144 
       
   145       if (g_strdiff (tmp->name, name))
       
   146         {
       
   147           const gchar *suffix;
       
   148 
       
   149           suffix = strchr (tmp->name, ':');
       
   150 
       
   151           if (suffix == NULL)
       
   152             continue;
       
   153           else
       
   154             suffix++;
       
   155 
       
   156           if (g_strdiff (suffix, name))
       
   157             continue;
       
   158 
       
   159           tag = g_strndup (tmp->name, suffix - tmp->name - 1);
       
   160         }
       
   161 
       
   162       found = lm_message_node_has_namespace (tmp, ns, tag);
       
   163 
       
   164       g_free (tag);
       
   165 
       
   166       if (found)
       
   167         return tmp;
       
   168     }
       
   169 
       
   170   return NULL;
       
   171 }
       
   172 
       
   173 /**
       
   174  * gabble_decode_jid
       
   175  *
       
   176  * Parses a JID which may be one of the following forms:
       
   177  *  server
       
   178  *  server/resource
       
   179  *  username@server
       
   180  *  username@server/resource
       
   181  *  room@service/nick
       
   182  * and sets the caller's username_room, server_service and resource_nick
       
   183  * pointers to the username/room, server/service and resource/nick parts
       
   184  * respectively, if available in the provided JID. The caller may set any of
       
   185  * the pointers to NULL if they are not interested in a certain component.
       
   186  *
       
   187  * The returned values may be NULL or zero-length if a component was either
       
   188  * not present or zero-length respectively in the given JID. The username/room
       
   189  * and server/service are lower-cased because the Jabber protocol treats them
       
   190  * case-insensitively.
       
   191  */
       
   192 void
       
   193 gabble_decode_jid (const gchar *jid,
       
   194                    gchar **username_room,
       
   195                    gchar **server_service,
       
   196                    gchar **resource_nick)
       
   197 {
       
   198   char *tmp_jid, *tmp_username, *tmp_server, *tmp_resource;
       
   199 
       
   200   g_assert (jid != NULL);
       
   201   g_assert (*jid != '\0');
       
   202 
       
   203   if (username_room != NULL)
       
   204     *username_room = NULL;
       
   205 
       
   206   if (server_service != NULL)
       
   207     *server_service = NULL;
       
   208 
       
   209   if (resource_nick != NULL)
       
   210     *resource_nick = NULL;
       
   211 
       
   212   /* take a local copy so we don't modify the caller's string */
       
   213   tmp_jid = g_strdup (jid);
       
   214 
       
   215   /* find an @ in username, truncate username to that length, and point
       
   216    * 'server' to the byte afterwards */
       
   217   tmp_server = strchr (tmp_jid, '@');
       
   218   if (tmp_server)
       
   219     {
       
   220       tmp_username = tmp_jid;
       
   221 
       
   222       *tmp_server = '\0';
       
   223       tmp_server++;
       
   224 
       
   225       /* store the username if the user provided a pointer */
       
   226       if (username_room != NULL)
       
   227         *username_room = g_utf8_strdown (tmp_username, -1);
       
   228     }
       
   229   else
       
   230     {
       
   231       tmp_username = NULL;
       
   232       tmp_server = tmp_jid;
       
   233     }
       
   234 
       
   235   /* if we have a server, find a / in it, truncate it to that length, and point
       
   236    * 'resource' to the byte afterwards. otherwise, do the same to username to
       
   237    * find any resource there. */
       
   238   tmp_resource = strchr (tmp_server, '/');
       
   239   if (tmp_resource)
       
   240     {
       
   241       *tmp_resource = '\0';
       
   242       tmp_resource++;
       
   243 
       
   244       /* store the resource if the user provided a pointer */
       
   245       if (resource_nick != NULL)
       
   246         *resource_nick = g_strdup (tmp_resource);
       
   247     }
       
   248 
       
   249   /* the server must be stored after the resource, in case we truncated a
       
   250    * resource from it */
       
   251   if (server_service != NULL)
       
   252     *server_service = g_utf8_strdown (tmp_server, -1);
       
   253 
       
   254   /* free our working copy */
       
   255   g_free (tmp_jid);
       
   256 }
       
   257 
       
   258 /* extend a pointer by an offset, provided the offset is not 0 */
       
   259 gpointer
       
   260 gabble_mixin_offset_cast (gpointer instance,
       
   261                           guint offset)
       
   262 {
       
   263   g_return_val_if_fail (offset != 0, NULL);
       
   264 
       
   265   return ((guchar *) instance + offset);
       
   266 }
       
   267