pidgin/pidgin

Revert my previous change.

2017-01-08, Mark Doliner
7ccb54f5d342
Revert my previous change.

Apparently it caused `make distcheck` to fail which caused a Bitbucket build pipeline to fail: https://bitbucket.org/pidgin/main/addon/pipelines/home#!/results/%7B9f059724-78b4-4a5e-9780-9a614c7c2742%7D

Not sure how to fix this.

FYI there's a daily cronjob on... rock? in that calls /srv/trac/developer.pidgin.im/mercurial_support/nightly_update.sh which updates https://developer.pidgin.im/l10n/ It's been failing for a few months.
/**
* @file tlv.c MSN TLV functions
*
* 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.
*
* 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 "tlv.h"
#include "msnutils.h"
static msn_tlv_t *
createtlv(guint8 type, guint8 length, guint8 *value)
{
msn_tlv_t *ret;
ret = g_new(msn_tlv_t, 1);
ret->type = type;
ret->length = length;
ret->value = value;
return ret;
}
static void
freetlv(msn_tlv_t *oldtlv)
{
g_free(oldtlv->value);
g_free(oldtlv);
}
GSList *
msn_tlvlist_read(const char *bs, size_t bs_len)
{
GSList *list = NULL;
while (bs_len > 0) {
guint8 type, length;
msn_tlv_t *tlv;
if (bs_len == 3 && *bs == 0) {
/* Padding to multiple of 4 */
break;
} else if (bs_len == 2 && *bs == 0) {
/* Padding to multiple of 4 */
break;
} else if (bs_len == 1) {
if (*bs == 0) {
/* Padding to multiple of 4 */
break;
} else {
/* TLV is not small enough to fit here */
msn_tlvlist_free(list);
return NULL;
}
}
type = msn_pop8(bs);
length = msn_pop8(bs);
bs_len -= 2;
if (length > bs_len) {
msn_tlvlist_free(list);
return NULL;
}
tlv = createtlv(type, length, NULL);
if (length > 0) {
tlv->value = g_memdup(bs, length);
if (!tlv->value) {
freetlv(tlv);
msn_tlvlist_free(list);
return NULL;
}
}
bs_len -= length;
bs += length;
list = g_slist_prepend(list, tlv);
}
return g_slist_reverse(list);
}
GSList *
msn_tlvlist_copy(GSList *orig)
{
GSList *new = NULL;
msn_tlv_t *tlv;
while (orig != NULL) {
tlv = orig->data;
msn_tlvlist_add_raw(&new, tlv->type, tlv->length, (const char *)tlv->value);
orig = orig->next;
}
return new;
}
gboolean
msn_tlvlist_equal(GSList *one, GSList *two)
{
while (one && two) {
msn_tlv_t *a = one->data;
msn_tlv_t *b = two->data;
if (a->type != b->type)
return FALSE;
else if (a->length != b->length)
return FALSE;
else if (!a->value && b->value)
return FALSE;
else if (a->value && !b->value)
return FALSE;
else if (a->value && b->value && memcmp(a->value, b->value, a->length) != 0)
return FALSE;
one = one->next;
two = two->next;
}
return one == two;
}
void
msn_tlvlist_free(GSList *list)
{
while (list != NULL) {
freetlv(list->data);
list = g_slist_delete_link(list, list);
}
}
int
msn_tlvlist_count(GSList *list)
{
return g_slist_length(list);
}
size_t
msn_tlvlist_size(GSList *list)
{
int size;
if (list == NULL)
return 0;
for (size = 0; list; list = list->next)
size += (2 + ((msn_tlv_t *)list->data)->length);
return size;
}
int
msn_tlvlist_add_raw(GSList **list, const guint8 type, const guint8 length, const char *value)
{
msn_tlv_t *tlv;
if (list == NULL)
return 0;
tlv = createtlv(type, length, NULL);
if (length > 0)
tlv->value = g_memdup(value, length);
*list = g_slist_append(*list, tlv);
return tlv->length;
}
int
msn_tlvlist_add_8(GSList **list, const guint8 type, const guint8 value)
{
char v8[1];
msn_write8(v8, value);
return msn_tlvlist_add_raw(list, type, 1, v8);
}
int
msn_tlvlist_add_16(GSList **list, const guint8 type, const guint16 value)
{
char v16[2];
msn_write16be(v16, value);
return msn_tlvlist_add_raw(list, type, 2, v16);
}
int
msn_tlvlist_add_32(GSList **list, const guint8 type, const guint32 value)
{
char v32[4];
msn_write32be(v32, value);
return msn_tlvlist_add_raw(list, type, 4, v32);
}
int
msn_tlvlist_add_str(GSList **list, const guint8 type, const char *value)
{
return msn_tlvlist_add_raw(list, type, strlen(value), value);
}
int
msn_tlvlist_add_empty(GSList **list, const guint8 type)
{
return msn_tlvlist_add_raw(list, type, 0, NULL);
}
int
msn_tlvlist_add_tlv(GSList **list, const msn_tlv_t *tlv)
{
return msn_tlvlist_add_raw(list, tlv->type, tlv->length, (const char *)tlv->value);
}
int
msn_tlvlist_replace_raw(GSList **list, const guint8 type, const guint8 length, const char *value)
{
GSList *cur;
msn_tlv_t *tlv;
if (list == NULL)
return 0;
for (cur = *list; cur != NULL; cur = cur->next) {
tlv = cur->data;
if (tlv->type == type)
break;
}
if (cur == NULL)
/* TLV does not exist, so add a new one */
return msn_tlvlist_add_raw(list, type, length, value);
g_free(tlv->value);
tlv->length = length;
if (length > 0) {
tlv->value = g_memdup(value, length);
} else
tlv->value = NULL;
return length;
}
int
msn_tlvlist_replace_str(GSList **list, const guint8 type, const char *str)
{
return msn_tlvlist_replace_raw(list, type, strlen(str), str);
}
int
msn_tlvlist_replace_empty(GSList **list, const guint8 type)
{
return msn_tlvlist_replace_raw(list, type, 0, NULL);
}
int
msn_tlvlist_replace_8(GSList **list, const guint8 type, const guint8 value)
{
char v8[1];
msn_write8(v8, value);
return msn_tlvlist_replace_raw(list, type, 1, v8);
}
int
msn_tlvlist_replace_32(GSList **list, const guint8 type, const guint32 value)
{
char v32[4];
msn_write32be(v32, value);
return msn_tlvlist_replace_raw(list, type, 4, v32);
}
int
msn_tlvlist_replace_tlv(GSList **list, const msn_tlv_t *tlv)
{
return msn_tlvlist_replace_raw(list, tlv->type, tlv->length, (const char *)tlv->value);
}
void
msn_tlvlist_remove(GSList **list, const guint8 type)
{
GSList *cur, *next;
msn_tlv_t *tlv;
if (list == NULL || *list == NULL)
return;
cur = *list;
while (cur != NULL) {
tlv = cur->data;
next = cur->next;
if (tlv->type == type) {
/* Delete this TLV */
*list = g_slist_delete_link(*list, cur);
g_free(tlv->value);
g_free(tlv);
}
cur = next;
}
}
char *
msn_tlvlist_write(GSList *list, guint8 *out_len)
{
char *buf;
char *tmp;
size_t bytes_left;
size_t total_len;
tmp = buf = g_malloc(256);
bytes_left = total_len = 256;
for (; list; list = g_slist_next(list)) {
msn_tlv_t *tlv = (msn_tlv_t *)list->data;
if (G_UNLIKELY((gsize)tlv->length + 2 > bytes_left)) {
buf = g_realloc(buf, total_len + 256);
bytes_left += 256;
total_len += 256;
tmp = buf + (total_len - bytes_left);
}
msn_push8(tmp, tlv->type);
msn_push8(tmp, tlv->length);
memcpy(tmp, tlv->value, tlv->length);
tmp += tlv->length;
bytes_left -= (tlv->length + 2);
}
/* Align length to multiple of 4 */
total_len = total_len - bytes_left;
bytes_left = 4 - total_len % 4;
if (bytes_left != 4)
memset(tmp, 0, bytes_left);
else
bytes_left = 0;
*out_len = total_len + bytes_left;
return buf;
}
msn_tlv_t *
msn_tlv_gettlv(GSList *list, const guint8 type, const int nth)
{
msn_tlv_t *tlv;
int i;
for (i = 0; list != NULL; list = list->next) {
tlv = list->data;
if (tlv->type == type)
i++;
if (i >= nth)
return tlv;
}
return NULL;
}
int
msn_tlv_getlength(GSList *list, const guint8 type, const int nth)
{
msn_tlv_t *tlv;
tlv = msn_tlv_gettlv(list, type, nth);
if (tlv == NULL)
return -1;
return tlv->length;
}
char *
msn_tlv_getvalue_as_string(msn_tlv_t *tlv)
{
char *ret;
ret = g_malloc(tlv->length + 1);
memcpy(ret, tlv->value, tlv->length);
ret[tlv->length] = '\0';
return ret;
}
char *
msn_tlv_getstr(GSList *list, const guint8 type, const int nth)
{
msn_tlv_t *tlv;
tlv = msn_tlv_gettlv(list, type, nth);
if (tlv == NULL)
return NULL;
return msn_tlv_getvalue_as_string(tlv);
}
guint8
msn_tlv_get8(GSList *list, const guint8 type, const int nth)
{
msn_tlv_t *tlv;
tlv = msn_tlv_gettlv(list, type, nth);
if (tlv == NULL)
return 0; /* erm */
return msn_read8((const char *)tlv->value);
}
guint16
msn_tlv_get16(GSList *list, const guint8 type, const int nth)
{
msn_tlv_t *tlv;
tlv = msn_tlv_gettlv(list, type, nth);
if (tlv == NULL)
return 0; /* erm */
return msn_read16be((const char *)tlv->value);
}
guint32
msn_tlv_get32(GSList *list, const guint8 type, const int nth)
{
msn_tlv_t *tlv;
tlv = msn_tlv_gettlv(list, type, nth);
if (tlv == NULL)
return 0; /* erm */
return msn_read32be((const char *)tlv->value);
}