/* * Copyright (C) 2005 Kouji TAKAO * * 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 Library 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifdef HAVE_CONFIG_H # include #endif #include #include #include #include "gpass/pack.h" void gpass_pack_number(gint number, GString **buffer) { if (number == 0) { *buffer = g_string_append_c(*buffer, 0); return; } number = GINT_TO_LE(number); while (number > 0) { div_t d; guchar c; d = div(number, 0x80); number = d.quot; c = (guchar) d.rem; if (number > 0) { c |= 0x80; } *buffer = g_string_append_c(*buffer, c); } } GError * gpass_unpack_number(const guchar *buffer, gint len, gint *result, gint *read_len) { gint val = 0, base = 1, i = 0; const guchar *ptr = buffer, *ptr_end = buffer + len; GError *error = NULL; while (ptr < ptr_end && i <= 5) { if (*ptr & 0x80) { val += base * (*ptr & 0x7f); base *= 0x80; ptr++; } else { val += base * (*ptr); *result = GINT_FROM_LE(val); *read_len = (ptr + 1) - buffer; return NULL; } i++; } if (i <= 5) { g_set_error(&error, 0, 0, _("buffer is too short")); } else { g_set_error(&error, 0, 0, _("invalid buffer")); } return error; } void gpass_pack_string(const gchar *str, GString **buffer) { if (str == NULL || *str == '\0') { gpass_pack_number(0, buffer); } else { gint len; len = strlen(str); gpass_pack_number(len, buffer); *buffer = g_string_append_len(*buffer, str, len); } } GError * gpass_unpack_string(const guchar *buffer, gint len, GString **str, gint *read_len) { gint str_len; GError *error; error = gpass_unpack_number(buffer, len, &str_len, read_len); if (error != NULL) { return error; } if (str_len == 0) { return NULL; } if (str_len > (len - *read_len)) { g_set_error(&error, 0, 0, _("buffer is too short")); return error; } *str = g_string_append_len(*str, buffer + *read_len, str_len); (*read_len) += str_len; return NULL; }