libpurple/protocols/gg/utils.c

Sun, 11 Sep 2016 11:25:03 -0500

author
Mike Ruprecht <cmaiku@gmail.com>
date
Sun, 11 Sep 2016 11:25:03 -0500
changeset 38139
42143502b9d0
parent 36047
2d7d55acd82c
child 38358
30ba44276e74
permissions
-rw-r--r--

gg: Port to Gio

This patch ports the Gadu-Gadu protocol plugin to use Gio internally.
Unfortunately libgg deals a lot with raw socket style API, which
isn't ideal. This patch therefore uses the pollable interface.

It would be nice to use the native asynchronous Gio API, but
I'm not certain that's possible without modifying libgg itself.
Perhaps someone more familiar with the protocol plugin would be
able to improve this.

/* purple
 *
 * Purple is the legal property of its developers, whose names are too numerous
 * to list here.  Please refer to the COPYRIGHT file distributed with this
 * source distribution.
 *
 * Rewritten from scratch during Google Summer of Code 2012
 * by Tomek Wasilczyk (http://www.wasilczyk.pl).
 *
 * Previously implemented by:
 *  - Arkadiusz Miskiewicz <misiek@pld.org.pl> - first implementation (2001);
 *  - Bartosz Oler <bartosz@bzimage.us> - reimplemented during GSoC 2005;
 *  - Krzysztof Klinikowski <grommasher@gmail.com> - some parts (2009-2011).
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
 */

#include "utils.h"

#include "gg.h"

#include <debug.h>

uin_t ggp_str_to_uin(const char *str)
{
	char *endptr;
	uin_t uin;

	if (!str || str[0] < '0' || str[0] > '9')
		return 0;

	errno = 0;
	uin = strtoul(str, &endptr, 10);

	if (errno == ERANGE || endptr[0] != '\0')
		return 0;

	return uin;
}

const char * ggp_uin_to_str(uin_t uin)
{
	static char buff[GGP_UIN_LEN_MAX + 1];

	g_snprintf(buff, GGP_UIN_LEN_MAX + 1, "%u", uin);

	return buff;
}

uin_t ggp_get_my_uin(PurpleConnection *gc)
{
	g_return_val_if_fail(gc != NULL, 0);

	return ggp_str_to_uin(purple_account_get_username(
		purple_connection_get_account(gc)));
}

static gchar * ggp_convert(const gchar *src, const char *srcenc,
	const char *dstenc)
{
	gchar *dst;
	GError *err = NULL;

	if (src == NULL)
		return NULL;

	dst = g_convert_with_fallback(src, strlen(src), dstenc, srcenc, "?",
		NULL, NULL, &err);
	if (err != NULL) {
		purple_debug_error("gg", "error converting from %s to %s: %s\n",
			srcenc, dstenc, err->message);
		g_error_free(err);
	}

	if (dst == NULL)
		dst = g_strdup(src);

	return dst;
}

gchar * ggp_convert_to_cp1250(const gchar *src)
{
	return ggp_convert(src, "UTF-8", "CP1250");
}

gchar * ggp_convert_from_cp1250(const gchar *src)
{
	return ggp_convert(src, "CP1250", "UTF-8");
}

gboolean ggp_password_validate(const gchar *password)
{
	const int len = strlen(password);
	if (len < 6 || len > 15)
		return FALSE;
	return g_regex_match_simple("^[ a-zA-Z0-9~`!@#$%^&*()_+=[\\]{};':\",./?"
		"<>\\\\|-]+$", password, 0, 0);
}

gchar * ggp_utf8_strndup(const gchar *str, gsize n)
{
	size_t raw_len;
	gchar *end_ptr;
	if (str == NULL)
		return NULL;
	raw_len = strlen(str);
	if (raw_len <= n)
		return g_strdup(str);

	end_ptr = g_utf8_offset_to_pointer(str, g_utf8_pointer_to_offset(str, &str[n]));
	raw_len = end_ptr - str;

	if (raw_len > n) {
		end_ptr = g_utf8_prev_char(end_ptr);
		raw_len = end_ptr - str;
	}

	g_assert(raw_len <= n);

	return g_strndup(str, raw_len);
}

GSList * ggp_list_copy_to_slist_deep(GList *list, GCopyFunc func,
	gpointer user_data)
{
	GSList *new_list = NULL;
	GList *it;

	it = g_list_first(list);
	while (it) {
		new_list = g_slist_append(new_list, func(it->data, user_data));
		it = g_list_next(it);
	}
	return new_list;
}

GList * ggp_strsplit_list(const gchar *string, const gchar *delimiter,
	gint max_tokens)
{
	gchar **splitted, **it;
	GList *list = NULL;

	it = splitted = g_strsplit(string, delimiter, max_tokens);
	while (*it) {
		list = g_list_append(list, *it);
		it++;
	}
	g_free(splitted);

	return list;
}

gchar * ggp_strjoin_list(const gchar *separator, GList *list)
{
	gchar **str_array;
	gchar *joined;
	gint list_len, i;
	GList *it;

	list_len = g_list_length(list);
	str_array = g_new(gchar*, list_len + 1);

	it = g_list_first(list);
	i = 0;
	while (it) {
		str_array[i++] = it->data;
		it = g_list_next(it);
	}
	str_array[i] = NULL;

	joined = g_strjoinv(separator, str_array);
	g_free(str_array);

	return joined;
}

const gchar * ggp_ipv4_to_str(uint32_t raw_ip)
{
	static gchar buff[INET_ADDRSTRLEN];
	buff[0] = '\0';

	g_snprintf(buff, sizeof(buff), "%d.%d.%d.%d",
		((raw_ip >>  0) & 0xFF),
		((raw_ip >>  8) & 0xFF),
		((raw_ip >> 16) & 0xFF),
		((raw_ip >> 24) & 0xFF));

	return buff;
}

GList * ggp_list_truncate(GList *list, guint length, GDestroyNotify free_func)
{
	while (g_list_length(list) > length) {
		GList *last = g_list_last(list);
		free_func(last->data);
		list = g_list_delete_link(list, last);
	}
	return list;
}

gchar * ggp_free_if_equal(gchar *str, const gchar *pattern)
{
	if (g_strcmp0(str, pattern) == 0) {
		g_free(str);
		return NULL;
	}
	return str;
}

const gchar * ggp_date_strftime(const gchar *format, time_t date)
{
	GDate g_date;
	static gchar buff[30];

	g_date_set_time_t(&g_date, date);
	if (0 == g_date_strftime(buff, sizeof(buff), format, &g_date))
		return NULL;
	return buff;
}

time_t ggp_date_from_iso8601(const gchar *str)
{
	GTimeVal g_timeval;

	if (!str)
		return 0;
	if (!g_time_val_from_iso8601(str, &g_timeval))
		return 0;
	return g_timeval.tv_sec;
}

uint64_t * ggp_uint64dup(uint64_t val)
{
	uint64_t *ptr = g_new(uint64_t, 1);
	*ptr = val;
	return ptr;
}

gint ggp_int64_compare(gconstpointer _a, gconstpointer _b)
{
	const int64_t *ap = _a, *bp = _b;
	const int64_t a = *ap, b = *bp;
	if (a == b)
		return 0;
	if (a < b)
		return -1;
	else
		return 1;
}

JsonParser * ggp_json_parse(const gchar *data)
{
	JsonParser *parser;

	parser = json_parser_new();
	if (json_parser_load_from_data(parser, data, -1, NULL))
		return parser;

	if (purple_debug_is_unsafe())
		purple_debug_warning("gg", "Invalid JSON: %s\n", data);
	return NULL;
}

mercurial