コード例 #1
0
ファイル: buddy.c プロジェクト: dylex/pidgin
void silcpurple_buddy_set_icon(PurpleConnection *gc, PurpleStoredImage *img)
{
	SilcPurple sg = gc->proto_data;
	SilcClient client = sg->client;
	SilcClientConnection conn = sg->conn;
	SilcMime mime;
	char type[32];
	unsigned char *icon;
	const char *t;
	SilcAttributeObjMime obj;

	/* Remove */
	if (!img) {
		silc_client_attribute_del(client, conn,
					  SILC_ATTRIBUTE_USER_ICON, NULL);
		return;
	}

	/* Add */
	mime = silc_mime_alloc();
	if (!mime)
		return;

	t = purple_imgstore_get_extension(img);
	if (!t || purple_strequal(t, "icon")) {
		silc_mime_free(mime);
		return;
	}
	if (purple_strequal(t, "jpg"))
		t = "jpeg";
	g_snprintf(type, sizeof(type), "image/%s", t);
	silc_mime_add_field(mime, "Content-Type", type);
	silc_mime_add_data(mime, purple_imgstore_get_data(img), purple_imgstore_get_size(img));

	obj.mime = icon = silc_mime_encode(mime, &obj.mime_len);
	if (obj.mime)
		silc_client_attribute_add(client, conn,
					  SILC_ATTRIBUTE_USER_ICON, &obj, sizeof(obj));

	silc_free(icon);
	silc_mime_free(mime);
}
コード例 #2
0
ファイル: silcattrs.c プロジェクト: TabTwo/silc-client
static unsigned char *
silc_attribute_payload_encode_int(SilcAttribute attribute,
				  SilcAttributeFlags flags,
				  void *object,
				  SilcUInt32 object_size,
				  SilcUInt32 *ret_len)
{
  SilcBuffer tmpbuf = NULL;
  unsigned char tmp[4], *str = NULL, *ret;
  SilcUInt32 len;

  /* Encode according to attribute type */
  if (flags & SILC_ATTRIBUTE_FLAG_VALID) {
    if (!object && !object_size)
      return NULL;

    switch (attribute) {

    case SILC_ATTRIBUTE_USER_INFO:
      {
	SilcVCard vcard = object;
	if (object_size != sizeof(*vcard))
	  return NULL;
	str = silc_vcard_encode(vcard, &object_size);
	if (!str)
	  return NULL;
	object = str;
      }
      break;

    case SILC_ATTRIBUTE_SERVICE:
      {
	SilcAttributeObjService *service = object;
	SilcUInt32 len2;
	if (object_size != sizeof(*service))
	  return NULL;
	len = strlen(service->address);
	len2 = strlen(service->signon);
	tmpbuf = silc_buffer_alloc_size(13 + len + len2);
	if (!tmpbuf)
	  return NULL;
	silc_buffer_format(tmpbuf,
			   SILC_STR_UI_INT(service->port),
			   SILC_STR_UI_SHORT(len),
			   SILC_STR_UI_XNSTRING(service->address, len),
			   SILC_STR_UI_CHAR(service->status),
			   SILC_STR_UI_SHORT(len2),
			   SILC_STR_UI_XNSTRING(service->signon, len2),
			   SILC_STR_UI_INT(service->idle),
			   SILC_STR_END);
	object = tmpbuf->data;
	object_size = silc_buffer_len(tmpbuf);
      }
      break;

    case SILC_ATTRIBUTE_STATUS_MOOD:
    case SILC_ATTRIBUTE_PREFERRED_CONTACT:
      {
	SilcUInt32 mask = SILC_PTR_TO_32(object);
	if (object_size != sizeof(SilcUInt32))
	  return NULL;
	SILC_PUT32_MSB(mask, tmp);
	object = tmp;
	object_size = sizeof(SilcUInt32);
      }
      break;

    case SILC_ATTRIBUTE_STATUS_FREETEXT:
    case SILC_ATTRIBUTE_PREFERRED_LANGUAGE:
    case SILC_ATTRIBUTE_TIMEZONE:
      {
	unsigned char *string = object;
	str = silc_malloc(2 + object_size);
	if (!str)
	  return NULL;
	SILC_PUT16_MSB(object_size, str);
	memcpy(str + 2, string, object_size);
	object = str;
	object_size += 2;
      }
      break;

    case SILC_ATTRIBUTE_STATUS_MESSAGE:
    case SILC_ATTRIBUTE_EXTENSION:
    case SILC_ATTRIBUTE_USER_ICON:
      {
	SilcMime mime = object;
	if (object_size != sizeof(*mime))
	  return NULL;
	str = silc_mime_encode(mime, &object_size);
	if (!str)
	  return NULL;
	object = str;
      }
      break;

    case SILC_ATTRIBUTE_GEOLOCATION:
      {
	SilcAttributeObjGeo *geo = object;
	SilcUInt32 len1, len2, len3, len4;
	if (object_size != sizeof(*geo))
	  return NULL;
	len1 = (geo->longitude ? strlen(geo->longitude) : 0);
	len2 = (geo->latitude  ? strlen(geo->latitude)  : 0);
	len3 = (geo->altitude  ? strlen(geo->altitude)  : 0);
	len4 = (geo->accuracy  ? strlen(geo->accuracy)  : 0);
	if (len1 + len2 + len3 + len4 == 0)
	  return NULL;
	len = len1 + len2 + len3 + len4;
	tmpbuf = silc_buffer_alloc_size(8 + len);
	if (!tmpbuf)
	  return NULL;
	silc_buffer_format(tmpbuf,
			   SILC_STR_UI_SHORT(len1),
			   SILC_STR_UI16_STRING(len1 ? geo->longitude : ""),
			   SILC_STR_UI_SHORT(len2),
			   SILC_STR_UI16_STRING(len2 ? geo->latitude : ""),
			   SILC_STR_UI_SHORT(len3),
			   SILC_STR_UI16_STRING(len3 ? geo->altitude : ""),
			   SILC_STR_UI_SHORT(len4),
			   SILC_STR_UI16_STRING(len4 ? geo->accuracy : ""),
			   SILC_STR_END);
	object = tmpbuf->data;
	object_size = silc_buffer_len(tmpbuf);
      }
      break;

    case SILC_ATTRIBUTE_DEVICE_INFO:
      {
	SilcAttributeObjDevice *dev = object;
	SilcUInt32 len1, len2, len3, len4;
	if (object_size != sizeof(*dev))
	  return NULL;
	len1 = (dev->manufacturer ? strlen(dev->manufacturer) : 0);
	len2 = (dev->version      ? strlen(dev->version)      : 0);
	len3 = (dev->model        ? strlen(dev->model)        : 0);
	len4 = (dev->language     ? strlen(dev->language)     : 0);
	if (len1 + len2 + len3 + len4 == 0)
	  return NULL;
	len = len1 + len2 + len3 + len4;
	tmpbuf = silc_buffer_alloc_size(4 + 8 + len);
	if (!tmpbuf)
	  return NULL;
	silc_buffer_format(tmpbuf,
			   SILC_STR_UI_INT(dev->type),
			   SILC_STR_UI_SHORT(len1),
			   SILC_STR_UI16_STRING(len1 ? dev->manufacturer : ""),
			   SILC_STR_UI_SHORT(len2),
			   SILC_STR_UI16_STRING(len2 ? dev->version : ""),
			   SILC_STR_UI_SHORT(len3),
			   SILC_STR_UI16_STRING(len3 ? dev->model : ""),
			   SILC_STR_UI_SHORT(len4),
			   SILC_STR_UI16_STRING(len4 ? dev->language : ""),
			   SILC_STR_END);
	object = tmpbuf->data;
	object_size = silc_buffer_len(tmpbuf);
      }
      break;

    case SILC_ATTRIBUTE_PHONE_NUMBER:
      {
	SilcAttributeObjPN *pn = object;
	if (object_size != sizeof(*pn))
	  return NULL;
	if (!pn->number || strlen(pn->number) < 5)
	  return NULL;
	tmpbuf = silc_buffer_alloc(0);
	if (!tmpbuf)
	  return NULL;
	if (silc_buffer_format(tmpbuf,
			       SILC_STR_UI_INT(pn->format),
			       SILC_STR_UI_SHORT(strlen(pn->number)),
			       SILC_STR_UI16_STRING(pn->number),
			       SILC_STR_END) < 0)
	  return NULL;
	object = tmpbuf->data;
	object_size = silc_buffer_len(tmpbuf);
      }
      break;

    case SILC_ATTRIBUTE_USER_PUBLIC_KEY:
    case SILC_ATTRIBUTE_SERVER_PUBLIC_KEY:
      {
	SilcAttributeObjPk *pk = object;
	if (object_size != sizeof(*pk))
	  return NULL;
	len = (pk->type ? strlen(pk->type) : 0);
	tmpbuf = silc_buffer_alloc_size(2 + len + pk->data_len);
	if (!tmpbuf)
	  return NULL;
	silc_buffer_format(tmpbuf,
			   SILC_STR_UI_SHORT(len),
			   SILC_STR_UI16_STRING(pk->type),
			   SILC_STR_UI_XNSTRING(pk->data, pk->data_len),
			   SILC_STR_END);
	object = tmpbuf->data;
	object_size = silc_buffer_len(tmpbuf);
      }
      break;

    case SILC_ATTRIBUTE_USER_DIGITAL_SIGNATURE:
    case SILC_ATTRIBUTE_SERVER_DIGITAL_SIGNATURE:
      {
	SilcAttributeObjPk *pk = object;
	if (object_size != sizeof(*pk))
	  return NULL;
	object = pk->data;
	object_size = pk->data_len;
      }
      break;

    default:
      return NULL;
      break;
    }

    ret = silc_memdup(object, object_size);

    if (tmpbuf)
      silc_buffer_free(tmpbuf);
    silc_free(str);

    if (ret_len)
      *ret_len = object_size;

    return ret;
  }

  return NULL;
}
コード例 #3
0
ファイル: silcmime.c プロジェクト: TabTwo/silc-server
SilcDList silc_mime_encode_partial(SilcMime mime, int max_size)
{
    unsigned char *buf, *tmp;
    SilcUInt32 buf_len, len, tmp_len, off;
    SilcDList list;
    SilcBuffer buffer;
    SilcMime partial;
    char type[128], id[64];
    int num;

    SILC_LOG_DEBUG(("Fragmenting MIME message"));

    /* Encode as normal */
    buf = silc_mime_encode(mime, &buf_len);
    if (!buf)
        return NULL;

    list = silc_dlist_init();

    /* Fragment if it is too large */
    if (buf_len > max_size) {
        memset(id, 0, sizeof(id));
        memset(type, 0, sizeof(type));
        gethostname(type, sizeof(type) - 1);
        srand((time(NULL) + buf_len) ^ rand());
        silc_snprintf(id, sizeof(id) - 1, "%X%X%X%s",
                      (unsigned int)rand(), (unsigned int)time(NULL),
                      (unsigned int)buf_len, type);

        SILC_LOG_DEBUG(("Fragment ID %s", id));

        partial = silc_mime_alloc();
        if (!partial)
            return NULL;

        silc_mime_add_field(partial, "MIME-Version", "1.0");
        memset(type, 0, sizeof(type));
        silc_snprintf(type, sizeof(type) - 1,
                      "message/partial; id=\"%s\"; number=1", id);
        silc_mime_add_field(partial, "Content-Type", type);
        silc_mime_add_data(partial, buf, max_size);

        tmp = silc_mime_encode(partial, &tmp_len);
        if (!tmp)
            return NULL;
        silc_mime_free(partial);

        /* Add to list */
        buffer = silc_buffer_alloc_size(tmp_len);
        if (!buffer)
            return NULL;
        silc_buffer_put(buffer, tmp, tmp_len);
        silc_dlist_add(list, buffer);
        silc_free(tmp);

        len = buf_len - max_size;
        off = max_size;
        num = 2;
        while (len > 0) {
            partial = silc_mime_alloc();
            if (!partial)
                return NULL;

            memset(type, 0, sizeof(type));
            silc_mime_add_field(partial, "MIME-Version", "1.0");

            if (len > max_size) {
                silc_snprintf(type, sizeof(type) - 1,
                              "message/partial; id=\"%s\"; number=%d",
                              id, num++);
                silc_mime_add_data(partial, buf + off, max_size);
                off += max_size;
                len -= max_size;
            } else {
                silc_snprintf(type, sizeof(type) - 1,
                              "message/partial; id=\"%s\"; number=%d; total=%d",
                              id, num, num);
                silc_mime_add_data(partial, buf + off, len);
                len = 0;
            }

            silc_mime_add_field(partial, "Content-Type", type);

            tmp = silc_mime_encode(partial, &tmp_len);
            if (!tmp)
                return NULL;
            silc_mime_free(partial);

            /* Add to list */
            buffer = silc_buffer_alloc_size(tmp_len);
            if (!buffer)
                return NULL;
            silc_buffer_put(buffer, tmp, tmp_len);
            silc_dlist_add(list, buffer);
            silc_free(tmp);
        }
    } else {
        /* No need to fragment */
        buffer = silc_buffer_alloc_size(buf_len);
        if (!buffer)
            return NULL;
        silc_buffer_put(buffer, buf, buf_len);
        silc_dlist_add(list, buffer);
    }

    silc_free(buf);

    return list;
}
コード例 #4
0
ファイル: silcmime.c プロジェクト: TabTwo/silc-server
unsigned char *silc_mime_encode(SilcMime mime, SilcUInt32 *encoded_len)
{
    SilcMime part;
    SilcHashTableList htl;
    SilcBufferStruct buf;
    SilcBuffer buffer;
    char *field, *value, tmp[1024], tmp2[4];
    unsigned char *ret;
    int i;

    SILC_LOG_DEBUG(("Encoding MIME message"));

    if (!mime)
        return NULL;

    memset(&buf, 0, sizeof(buf));

    /* Encode the headers. Order doesn't matter */
    i = 0;
    silc_hash_table_list(mime->fields, &htl);
    while (silc_hash_table_get(&htl, (void *)&field, (void *)&value)) {
        memset(tmp, 0, sizeof(tmp));
        SILC_LOG_DEBUG(("Header %s: %s", field, value));
        silc_snprintf(tmp, sizeof(tmp) - 1, "%s: %s\r\n", field, value);
        silc_buffer_strformat(&buf, tmp, SILC_STRFMT_END);
        i++;
    }
    silc_hash_table_list_reset(&htl);
    if (i)
        silc_buffer_strformat(&buf, "\r\n", SILC_STRFMT_END);

    /* Assemble the whole buffer */
    buffer = silc_buffer_alloc_size(mime->data_len + silc_buffer_len(&buf));
    if (!buffer)
        return NULL;

    /* Add headers */
    if (silc_buffer_len(&buf)) {
        silc_buffer_put(buffer, buf.head, silc_buffer_len(&buf));
        silc_buffer_pull(buffer, silc_buffer_len(&buf));
        silc_buffer_purge(&buf);
    }

    /* Add data */
    if (mime->data) {
        SILC_LOG_DEBUG(("Data len %d", mime->data_len));
        silc_buffer_put(buffer, mime->data, mime->data_len);
    }

    /* Add multiparts */
    if (mime->multiparts) {
        SILC_LOG_DEBUG(("Encoding multiparts"));

        silc_dlist_start(mime->multiparts);
        i = 0;
        while ((part = silc_dlist_get(mime->multiparts)) != SILC_LIST_END) {
            unsigned char *pd;
            SilcUInt32 pd_len;

            /* Recursive encoding */
            pd = silc_mime_encode(part, &pd_len);
            if (!pd)
                return NULL;

            memset(tmp, 0, sizeof(tmp));
            memset(tmp2, 0, sizeof(tmp2));

            /* If fields are not present, add extra CRLF */
            if (!silc_hash_table_count(part->fields))
                silc_snprintf(tmp2, sizeof(tmp2) - 1, "\r\n");
            silc_snprintf(tmp, sizeof(tmp) - 1, "%s--%s\r\n%s",
                          i != 0 ? "\r\n" : "", mime->boundary, tmp2);
            i = 1;

            buffer = silc_buffer_realloc(buffer, silc_buffer_truelen(buffer) +
                                         pd_len + strlen(tmp));
            if (!buffer)
                return NULL;
            silc_buffer_put_tail(buffer, tmp, strlen(tmp));
            silc_buffer_pull_tail(buffer, strlen(tmp));
            silc_buffer_put_tail(buffer, pd, pd_len);
            silc_buffer_pull_tail(buffer, pd_len);
            silc_free(pd);
        }

        memset(tmp, 0, sizeof(tmp));
        silc_snprintf(tmp, sizeof(tmp) - 1, "\r\n--%s--\r\n", mime->boundary);
        buffer = silc_buffer_realloc(buffer, silc_buffer_truelen(buffer) +
                                     strlen(tmp));
        if (!buffer)
            return NULL;
        silc_buffer_put_tail(buffer, tmp, strlen(tmp));
        silc_buffer_pull_tail(buffer, strlen(tmp));
    }

    ret = silc_buffer_steal(buffer, encoded_len);
    silc_buffer_free(buffer);

    return ret;
}