aboutsummaryrefslogtreecommitdiffstats
path: root/facebook/facebook-util.c
diff options
context:
space:
mode:
authorjgeboski <jgeboski@gmail.com>2015-08-24 17:01:16 -0400
committerjgeboski <jgeboski@gmail.com>2015-08-24 17:01:16 -0400
commit53cedfaca78278a64cc347e8ed51bb67363b3dcc (patch)
treedd2c6cac0c3d5d4af1cccaa9cbbc7a6ca4522572 /facebook/facebook-util.c
parent60a42307f24c617029efbb7bcd432d162706c692 (diff)
downloadbitlbee-facebook-53cedfaca78278a64cc347e8ed51bb67363b3dcc.tar.gz
bitlbee-facebook-53cedfaca78278a64cc347e8ed51bb67363b3dcc.tar.bz2
bitlbee-facebook-53cedfaca78278a64cc347e8ed51bb67363b3dcc.tar.xz
Imported changes from purple-facebook
Diffstat (limited to 'facebook/facebook-util.c')
-rw-r--r--facebook/facebook-util.c383
1 files changed, 259 insertions, 124 deletions
diff --git a/facebook/facebook-util.c b/facebook/facebook-util.c
index 4b959ac..dba7b82 100644
--- a/facebook/facebook-util.c
+++ b/facebook/facebook-util.c
@@ -15,80 +15,170 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <bitlbee.h>
+#include <sha1.h>
#include <stdarg.h>
#include <string.h>
#include <zlib.h>
#include "facebook-util.h"
-/**
- * Determines the debugging state of the plugin.
- *
- * @return TRUE if debugging is enabled, otherwise FALSE.
- **/
-#ifdef DEBUG_FACEBOOK
-gboolean fb_util_debugging(void)
+GQuark
+fb_util_error_quark(void)
+{
+ static GQuark q = 0;
+
+ if (G_UNLIKELY(q == 0)) {
+ q = g_quark_from_static_string("fb-util-error-quark");
+ }
+
+ return q;
+}
+
+void
+fb_util_debug(FbDebugLevel level, const gchar *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ fb_util_vdebug(level, format, ap);
+ va_end(ap);
+}
+
+void
+fb_util_vdebug(FbDebugLevel level, const gchar *format, va_list ap)
{
+ const gchar *lstr;
+ gchar *str;
+
static gboolean debug = FALSE;
static gboolean setup = FALSE;
+ g_return_if_fail(format != NULL);
+
if (G_UNLIKELY(!setup)) {
- debug = g_getenv("BITLBEE_DEBUG") ||
- g_getenv("BITLBEE_DEBUG_FACEBOOK");
+ debug = (g_getenv("BITLBEE_DEBUG") != NULL) ||
+ (g_getenv("BITLBEE_DEBUG_FACEBOOK") != NULL);
setup = TRUE;
}
- return debug;
+ if (!debug) {
+ return;
+ }
+
+ switch (level) {
+ case FB_UTIL_DEBUG_LEVEL_MISC:
+ lstr = "MISC";
+ break;
+ case FB_UTIL_DEBUG_LEVEL_INFO:
+ lstr = "INFO";
+ break;
+ case FB_UTIL_DEBUG_LEVEL_WARN:
+ lstr = "WARN";
+ break;
+ case FB_UTIL_DEBUG_LEVEL_ERROR:
+ lstr = "ERROR";
+ break;
+ case FB_UTIL_DEBUG_LEVEL_FATAL:
+ lstr = "FATAL";
+ break;
+
+ default:
+ g_return_if_reached();
+ return;
+ }
+
+ str = g_strdup_vprintf(format, ap);
+ g_print("[%s] %s: %s\n", lstr, "facebook", str);
+ g_free(str);
}
-#endif /* DEBUG_FACEBOOK */
-/**
- * Dumps a #GByteArray to the debugging stream. This formats the output
- * similar to that of `hexdump -C`.
- *
- * @param bytes The #GByteArray.
- * @param indent The indent width.
- * @param fmt The format string or NULL.
- * @param ... The format arguments.
- **/
-#ifdef DEBUG_FACEBOOK
-void fb_util_hexdump(const GByteArray *bytes, guint indent,
- const gchar *fmt, ...)
+void
+fb_util_debug_misc(const gchar *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ fb_util_vdebug(FB_UTIL_DEBUG_LEVEL_MISC, format, ap);
+ va_end(ap);
+}
+
+void
+fb_util_debug_info(const gchar *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ fb_util_vdebug(FB_UTIL_DEBUG_LEVEL_INFO, format, ap);
+ va_end(ap);
+}
+
+void
+fb_util_debug_warn(const gchar *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ fb_util_vdebug(FB_UTIL_DEBUG_LEVEL_WARN, format, ap);
+ va_end(ap);
+}
+
+void
+fb_util_debug_error(const gchar *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ fb_util_vdebug(FB_UTIL_DEBUG_LEVEL_ERROR, format, ap);
+ va_end(ap);
+}
+
+void
+fb_util_debug_fatal(const gchar *format, ...)
{
+ va_list ap;
+
+ va_start(ap, format);
+ fb_util_vdebug(FB_UTIL_DEBUG_LEVEL_FATAL, format, ap);
+ va_end(ap);
+}
+
+void
+fb_util_debug_hexdump(FbDebugLevel level, const GByteArray *bytes,
+ const gchar *format, ...)
+{
+ gchar c;
+ guint i;
+ guint j;
GString *gstr;
- va_list ap;
- gchar *instr;
- guint i;
- guint j;
- gchar c;
-
- if (fmt != NULL) {
- va_start(ap, fmt);
- instr = g_strdup_vprintf(fmt, ap);
- FB_UTIL_DEBUGLN("%s", instr);
- g_free(instr);
+ va_list ap;
+
+ static const gchar *indent = " ";
+
+ g_return_if_fail(bytes != NULL);
+
+ if (format != NULL) {
+ va_start(ap, format);
+ fb_util_vdebug(level, format, ap);
va_end(ap);
}
- instr = g_strnfill(indent, ' ');
- gstr = g_string_sized_new(80);
- i = 0;
+ gstr = g_string_sized_new(80);
- if (G_UNLIKELY(bytes == NULL))
- goto finish;
-
- for (; i < bytes->len; i += 16) {
- g_string_append_printf(gstr, "%s%08x ", instr, i);
+ for (i = 0; i < bytes->len; i += 16) {
+ g_string_append_printf(gstr, "%s%08x ", indent, i);
for (j = 0; j < 16; j++) {
if ((i + j) < bytes->len) {
- g_string_append_printf(gstr, "%02x ", bytes->data[i + j]);
+ g_string_append_printf(gstr, "%02x ",
+ bytes->data[i + j]);
} else {
g_string_append(gstr, " ");
}
- if (j == 7)
+ if (j == 7) {
g_string_append_c(gstr, ' ');
+ }
}
g_string_append(gstr, " |");
@@ -96,81 +186,138 @@ void fb_util_hexdump(const GByteArray *bytes, guint indent,
for (j = 0; (j < 16) && ((i + j) < bytes->len); j++) {
c = bytes->data[i + j];
- if (!g_ascii_isprint(c) || g_ascii_isspace(c))
+ if (!g_ascii_isprint(c) || g_ascii_isspace(c)) {
c = '.';
+ }
g_string_append_c(gstr, c);
}
g_string_append_c(gstr, '|');
- FB_UTIL_DEBUGLN("%s", gstr->str);
+ fb_util_debug(level, "%s", gstr->str);
g_string_erase(gstr, 0, -1);
}
-finish:
- g_string_append_printf(gstr, "%s%08x", instr, i);
- FB_UTIL_DEBUGLN("%s", gstr->str);
-
+ g_string_append_printf(gstr, "%s%08x", indent, i);
+ fb_util_debug(level, "%s", gstr->str);
g_string_free(gstr, TRUE);
- g_free(instr);
}
-#endif /* DEBUG_FACEBOOK */
-/**
- * Compare two strings case insensitively. This is useful for where
- * the return value must be a boolean, such as with a #GEqualFunc.
- *
- * @param s1 The first string.
- * @param s2 The second string.
- *
- * @return TRUE if the strings are equal, otherwise FALSE.
- **/
-gboolean fb_util_str_iequal(const gchar *s1, const gchar *s2)
+gchar *
+fb_util_locale_str(void)
{
- return g_ascii_strcasecmp(s1, s2) == 0;
+ const gchar * const *langs;
+ const gchar *lang;
+ gchar *chr;
+ guint i;
+
+ static const gchar chrs[] = {'.', '@'};
+
+ langs = g_get_language_names();
+ lang = langs[0];
+
+ if (g_strcmp0(lang, "C") == 0) {
+ return g_strdup("en_US");
+ }
+
+ for (i = 0; i < G_N_ELEMENTS(chrs); i++) {
+ chr = strchr(lang, chrs[i]);
+
+ if (chr != NULL) {
+ return g_strndup(lang, chr - lang);
+ }
+ }
+
+ return g_strdup(lang);
}
-/**
- * Implemented #alloc_func for #g_malloc().
- *
- * @param opaque The user-defined data, which is NULL.
- * @param items The number of items.
- * @param size The size of each item.
- *
- * @return The pointer to the allocated memory.
- **/
-static voidpf fb_util_zalloc(voidpf opaque, uInt items, uInt size)
+gchar *
+fb_util_randstr(gsize size)
+{
+ gchar *ret;
+ GRand *rand;
+ guint i;
+ guint j;
+
+ static const gchar chars[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789";
+ static const gsize charc = G_N_ELEMENTS(chars) - 1;
+
+ if (G_UNLIKELY(size < 1)) {
+ return NULL;
+ }
+
+ rand = g_rand_new();
+ ret = g_new(gchar, size + 1);
+
+ for (i = 0; i < size; i++) {
+ j = g_rand_int_range(rand, 0, charc);
+ ret[i] = chars[j];
+ }
+
+ ret[size] = 0;
+ g_rand_free(rand);
+ return ret;
+}
+
+gboolean
+fb_util_str_is(const gchar *str, GAsciiType type)
+{
+ gsize i;
+ gsize size;
+ guchar c;
+
+ g_return_val_if_fail(str != NULL, FALSE);
+ size = strlen(str);
+
+ for (i = 0; i < size; i++) {
+ c = (guchar) str[i];
+
+ if ((g_ascii_table[c] & type) == 0) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+gchar *
+fb_util_uuid(void)
+{
+ guint8 buf[50];
+ sha1_state_t sha;
+
+ sha1_init(&sha);
+ random_bytes(buf, sizeof buf);
+ sha1_append(&sha, buf, sizeof buf);
+ return sha1_random_uuid(&sha);
+}
+
+static voidpf
+fb_util_zalloc(voidpf opaque, uInt items, uInt size)
{
return g_malloc(size * items);
}
-/**
- * Implemented #free_func for #g_free().
- *
- * @param opaque The user-defined data, which is NULL.
- * @param address The pointer address.
- **/
-static void fb_util_zfree(voidpf opaque, voidpf address)
+static void
+fb_util_zfree(voidpf opaque, voidpf address)
{
g_free(address);
}
-/**
- * Determines if a #GByteArray is zlib compressed.
- *
- * @param bytes The #GByteArray.
- *
- * @return TRUE if the #GByteArray is compressed, otherwise FALSE.
- **/
-gboolean fb_util_zcompressed(const GByteArray *bytes)
+gboolean
+fb_util_zcompressed(const GByteArray *bytes)
{
guint8 b0;
guint8 b1;
g_return_val_if_fail(bytes != NULL, FALSE);
- if (bytes->len < 2)
+ if (bytes->len < 2) {
return FALSE;
+ }
b0 = *(bytes->data + 0);
b1 = *(bytes->data + 1);
@@ -179,38 +326,32 @@ gboolean fb_util_zcompressed(const GByteArray *bytes)
((b0 & 0x0F) == Z_DEFLATED); /* Check the method */
}
-/**
- * Compresses a #GByteArray with zlib. The returned #GByteArray should
- * be freed with #g_byte_array_free() when no longer needed.
- *
- * @param bytes The #GByteArray.
- *
- * @return The resulting #GByteArray, or NULL on error.
- **/
-GByteArray *fb_util_zcompress(const GByteArray *bytes)
+GByteArray *
+fb_util_zcompress(const GByteArray *bytes)
{
GByteArray *ret;
- z_stream zs;
- gsize size;
- gint res;
+ gint res;
+ gsize size;
+ z_stream zs;
g_return_val_if_fail(bytes != NULL, NULL);
memset(&zs, 0, sizeof zs);
- zs.zalloc = fb_util_zalloc;
- zs.zfree = fb_util_zfree;
- zs.next_in = bytes->data;
+ zs.zalloc = fb_util_zalloc;
+ zs.zfree = fb_util_zfree;
+ zs.next_in = bytes->data;
zs.avail_in = bytes->len;
- if (deflateInit(&zs, Z_BEST_COMPRESSION) != Z_OK)
+ if (deflateInit(&zs, Z_BEST_COMPRESSION) != Z_OK) {
return NULL;
+ }
size = compressBound(bytes->len);
- ret = g_byte_array_new();
+ ret = g_byte_array_new();
g_byte_array_set_size(ret, size);
- zs.next_out = ret->data;
+ zs.next_out = ret->data;
zs.avail_out = size;
res = deflate(&zs, Z_FINISH);
@@ -228,36 +369,30 @@ GByteArray *fb_util_zcompress(const GByteArray *bytes)
return ret;
}
-/**
- * Uncompresses a zlib compressed #GByteArray. The returned #GByteArray
- * should be freed with #g_byte_array_free() when no longer needed.
- *
- * @param bytes The #GByteArray.
- *
- * @return The resulting #GByteArray, or NULL on error.
- **/
-GByteArray *fb_util_zuncompress(const GByteArray *bytes)
+GByteArray *
+fb_util_zuncompress(const GByteArray *bytes)
{
GByteArray *ret;
- z_stream zs;
- guint8 out[1024];
- gint res;
+ gint res;
+ guint8 out[1024];
+ z_stream zs;
g_return_val_if_fail(bytes != NULL, NULL);
memset(&zs, 0, sizeof zs);
- zs.zalloc = fb_util_zalloc;
- zs.zfree = fb_util_zfree;
- zs.next_in = bytes->data;
+ zs.zalloc = fb_util_zalloc;
+ zs.zfree = fb_util_zfree;
+ zs.next_in = bytes->data;
zs.avail_in = bytes->len;
- if (inflateInit(&zs) != Z_OK)
+ if (inflateInit(&zs) != Z_OK) {
return NULL;
+ }
ret = g_byte_array_new();
do {
- zs.next_out = out;
+ zs.next_out = out;
zs.avail_out = sizeof out;
res = inflate(&zs, Z_NO_FLUSH);