<commit_before>
#define _GNU_SOURCE
#include "config.h"
#include "conn-location.h"

#include <string.h>
#include <stdlib.h>
#include <time.h>

#define DEBUG_FLAG GABBLE_DEBUG_LOCATION

#include "debug.h"
#include "extensions/extensions.h"
#include "namespaces.h"
#include "pubsub.h"
#include "presence-cache.h"

static gboolean update_location_from_msg (GabbleConnection *conn,
    const gchar *from, LmMessage *msg);

static gboolean
validate_contacts (TpBaseConnection *base,
                   DBusGMethodInvocation *context,
                   const GArray *contacts)
{
  TpHandleRepoIface *contact_handles = tp_base_connection_get_handles (base,
      TP_HANDLE_TYPE_CONTACT);
  GError *error = NULL;

  if (!tp_handles_are_valid (contact_handles, contacts, TRUE, &error))
    {
      dbus_g_method_return_error (context, error);
      g_error_free (error);
      return FALSE;
    }

  return TRUE;
}

static gboolean
lm_message_node_get_double (LmMessageNode *node,
                            gdouble *d)
{
  const gchar *value;
  gchar *end;

  value = lm_message_node_get_value (node);

  if (value == NULL)
    return FALSE;

  *d = strtod (value, &end);

  if (end == value)
    return FALSE;

  return TRUE;
}

static gboolean
lm_message_node_get_string (LmMessageNode *node,
                            gchar **s)
{
  const gchar *value;

  value = lm_message_node_get_value (node);

  if (value == NULL)
    return FALSE;

  *s = g_strdup (value);
  return TRUE;
}

static LmHandlerResult
pep_reply_cb (GabbleConnection *conn,
              LmMessage *sent_msg,
              LmMessage *reply_msg,
              GObject *object,
              gpointer user_data)
{
  const gchar *from;

  from = lm_message_node_get_attribute (reply_msg->node, "from");

  if (from != NULL)
    update_location_from_msg (conn, from, reply_msg);

  return LM_HANDLER_RESULT_REMOVE_MESSAGE;
}

static void
location_get_locations (GabbleSvcConnectionInterfaceLocation *iface,
                        const GArray *contacts,
                        DBusGMethodInvocation *context)
{
  GabbleConnection *conn = GABBLE_CONNECTION (iface);
  TpBaseConnection *base = (TpBaseConnection *) conn;
  guint i;
  GHashTable *return_locations = g_hash_table_new_full (g_direct_hash,
      g_direct_equal, NULL, (GDestroyNotify) g_hash_table_destroy);

  DEBUG ("GetLocation for contacts:");

  gabble_connection_ensure_capabilities (conn, PRESENCE_CAP_GEOLOCATION);
  if (!validate_contacts (base, context, contacts))
    return;

  for (i = 0; i < contacts->len; i++)
    {
      TpHandleRepoIface *contact_repo;
      const gchar *jid;
      GHashTable *location;
      TpHandle contact = g_array_index (contacts, TpHandle, i);

      contact_repo = tp_base_connection_get_handles (base,
          TP_HANDLE_TYPE_CONTACT);
      jid = tp_handle_inspect (contact_repo, contact);

      location = gabble_presence_cache_get_location (conn->presence_cache,
          contact);
      if (location != NULL)
        {
          DEBUG (" - %s: cached", jid);
          g_hash_table_insert (return_locations, GINT_TO_POINTER (contact),
              location);
        }
      else if (!pubsub_query (conn, jid, NS_GEOLOC, pep_reply_cb, NULL))
        {
          GError error = { TP_ERRORS, TP_ERROR_NETWORK_ERROR,
              "Sending PEP location query failed" };

          dbus_g_method_return_error (context, &error);
          g_hash_table_unref (return_locations);

          return;
        } else
           DEBUG (" - %s: requested", jid);
    }

  gabble_svc_connection_interface_location_return_from_get_locations
      (context, return_locations);
  g_hash_table_unref (return_locations);

}

static void
create_msg_foreach (gpointer key,
                    gpointer value,
                    gpointer user_data)
{
  LmMessageNode *geoloc = (LmMessageNode *) user_data;

  if (G_VALUE_TYPE (value) == G_TYPE_UINT64)
    {
      time_t stamp = g_value_get_uint64 (value);
      struct tm *ptm = gmtime (&stamp);
      gchar str[30];

      if (strftime (str, 30, "%Y%m%dT%TZ", ptm) == 0)
        return;

      lm_message_node_add_child (geoloc, key, str);
      DEBUG ("\t - %s: %s", (gchar*) key, str);
      g_free (str);
    }
  if (G_VALUE_TYPE (value) == G_TYPE_DOUBLE)
    {
      gchar *str;
      str = g_strdup_printf ("%.6f", g_value_get_double (value));
      lm_message_node_add_child (geoloc, key, str);
      DEBUG ("\t - %s: %s", (gchar*) key, str);
      g_free (str);
    }
  else if (G_VALUE_TYPE (value) == G_TYPE_STRING)<commit_msg>Location: don't use hardcoded value<commit_after>
#define _GNU_SOURCE
#include "config.h"
#include "conn-location.h"

#include <string.h>
#include <stdlib.h>
#include <time.h>

#define DEBUG_FLAG GABBLE_DEBUG_LOCATION

#include "debug.h"
#include "extensions/extensions.h"
#include "namespaces.h"
#include "pubsub.h"
#include "presence-cache.h"

static gboolean update_location_from_msg (GabbleConnection *conn,
    const gchar *from, LmMessage *msg);

static gboolean
validate_contacts (TpBaseConnection *base,
                   DBusGMethodInvocation *context,
                   const GArray *contacts)
{
  TpHandleRepoIface *contact_handles = tp_base_connection_get_handles (base,
      TP_HANDLE_TYPE_CONTACT);
  GError *error = NULL;

  if (!tp_handles_are_valid (contact_handles, contacts, TRUE, &error))
    {
      dbus_g_method_return_error (context, error);
      g_error_free (error);
      return FALSE;
    }

  return TRUE;
}

static gboolean
lm_message_node_get_double (LmMessageNode *node,
                            gdouble *d)
{
  const gchar *value;
  gchar *end;

  value = lm_message_node_get_value (node);

  if (value == NULL)
    return FALSE;

  *d = strtod (value, &end);

  if (end == value)
    return FALSE;

  return TRUE;
}

static gboolean
lm_message_node_get_string (LmMessageNode *node,
                            gchar **s)
{
  const gchar *value;

  value = lm_message_node_get_value (node);

  if (value == NULL)
    return FALSE;

  *s = g_strdup (value);
  return TRUE;
}

static LmHandlerResult
pep_reply_cb (GabbleConnection *conn,
              LmMessage *sent_msg,
              LmMessage *reply_msg,
              GObject *object,
              gpointer user_data)
{
  const gchar *from;

  from = lm_message_node_get_attribute (reply_msg->node, "from");

  if (from != NULL)
    update_location_from_msg (conn, from, reply_msg);

  return LM_HANDLER_RESULT_REMOVE_MESSAGE;
}

static void
location_get_locations (GabbleSvcConnectionInterfaceLocation *iface,
                        const GArray *contacts,
                        DBusGMethodInvocation *context)
{
  GabbleConnection *conn = GABBLE_CONNECTION (iface);
  TpBaseConnection *base = (TpBaseConnection *) conn;
  guint i;
  GHashTable *return_locations = g_hash_table_new_full (g_direct_hash,
      g_direct_equal, NULL, (GDestroyNotify) g_hash_table_destroy);

  DEBUG ("GetLocation for contacts:");

  gabble_connection_ensure_capabilities (conn, PRESENCE_CAP_GEOLOCATION);
  if (!validate_contacts (base, context, contacts))
    return;

  for (i = 0; i < contacts->len; i++)
    {
      TpHandleRepoIface *contact_repo;
      const gchar *jid;
      GHashTable *location;
      TpHandle contact = g_array_index (contacts, TpHandle, i);

      contact_repo = tp_base_connection_get_handles (base,
          TP_HANDLE_TYPE_CONTACT);
      jid = tp_handle_inspect (contact_repo, contact);

      location = gabble_presence_cache_get_location (conn->presence_cache,
          contact);
      if (location != NULL)
        {
          DEBUG (" - %s: cached", jid);
          g_hash_table_insert (return_locations, GINT_TO_POINTER (contact),
              location);
        }
      else if (!pubsub_query (conn, jid, NS_GEOLOC, pep_reply_cb, NULL))
        {
          GError error = { TP_ERRORS, TP_ERROR_NETWORK_ERROR,
              "Sending PEP location query failed" };

          dbus_g_method_return_error (context, &error);
          g_hash_table_unref (return_locations);

          return;
        } else
           DEBUG (" - %s: requested", jid);
    }

  gabble_svc_connection_interface_location_return_from_get_locations
      (context, return_locations);
  g_hash_table_unref (return_locations);

}

static void
create_msg_foreach (gpointer key,
                    gpointer value,
                    gpointer user_data)
{
  LmMessageNode *geoloc = (LmMessageNode *) user_data;

  if (G_VALUE_TYPE (value) == G_TYPE_UINT64)
    {
      time_t stamp = g_value_get_uint64 (value);
      struct tm *ptm = gmtime (&stamp);
      gchar str[30];

      if (strftime (str, sizeof(str), "%Y%m%dT%TZ", ptm) == 0)
        return;

      lm_message_node_add_child (geoloc, key, str);
      DEBUG ("\t - %s: %s", (gchar*) key, str);
      g_free (str);
    }
  if (G_VALUE_TYPE (value) == G_TYPE_DOUBLE)
    {
      gchar *str;
      str = g_strdup_printf ("%.6f", g_value_get_double (value));
      lm_message_node_add_child (geoloc, key, str);
      DEBUG ("\t - %s: %s", (gchar*) key, str);
      g_free (str);
    }
  else if (G_VALUE_TYPE (value) == G_TYPE_STRING)
{'fraction_non_alphanumeric': 0.1016763449107045, 'fraction_numerical': 0.0021913005368686313, 'mean_word_length': 2.9600867678958784, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6917595', 'n_tokens_mistral': 3194, 'n_tokens_neox': 3084, 'n_words': 697}