Esempio n. 1
0
static
int translate_TCON(struct id3_frame *frame, char const *oldid,
        id3_byte_t const *data, id3_length_t length)
{
    id3_byte_t const *end;
    enum id3_field_textencoding encoding;
    id3_ucs4_t *string = 0, *ptr, *endptr;
    int result = 0;
    (void)oldid;

    /* translate old TCON syntax into multiple strings */

    assert(frame->nfields == 2);

    encoding = ID3_FIELD_TEXTENCODING_ISO_8859_1;

    end = data + length;

    if(id3_field_parse(&frame->fields[0], &data, end - data, &encoding) == -1)
        goto fail;

    string = id3_parse_string(&data, end - data, encoding, 0);
    if(string == 0)
        goto fail;

    ptr = string;
    while(*ptr == '(')
    {
        if(*++ptr == '(')
            break;

        endptr = ptr;
        while(*endptr && *endptr != ')')
            ++endptr;

        if(*endptr)
            *endptr++ = 0;

        if(id3_field_addstring(&frame->fields[1], ptr) == -1)
            goto fail;

        ptr = endptr;
    }

    if(*ptr && id3_field_addstring(&frame->fields[1], ptr) == -1)
        goto fail;

    if(0)
    {
fail:
        result = -1;
    }

    if(string)
        free(string);

    return result;
}
Esempio n. 2
0
/*
 * NAME:	field->parse()
 * DESCRIPTION:	parse a field value
 */
int id3_field_parse(union id3_field *field, id3_byte_t const **ptr,
		    id3_length_t length, enum id3_field_textencoding *encoding)
{
  assert(field);

  id3_field_finish(field);

  switch (field->type) {
  case ID3_FIELD_TYPE_INT32:
    if (length < 4)
      goto fail;

    field->number.value = id3_parse_uint(ptr, 4);
    break;

  case ID3_FIELD_TYPE_INT24:
    if (length < 3)
      goto fail;

    field->number.value = id3_parse_uint(ptr, 3);
    break;

  case ID3_FIELD_TYPE_INT16:
    if (length < 2)
      goto fail;

    field->number.value = id3_parse_uint(ptr, 2);
    break;

  case ID3_FIELD_TYPE_INT8:
  case ID3_FIELD_TYPE_TEXTENCODING:
    if (length < 1)
      goto fail;

    field->number.value = id3_parse_uint(ptr, 1);

    if (field->type == ID3_FIELD_TYPE_TEXTENCODING)
      *encoding = field->number.value;
    break;

  case ID3_FIELD_TYPE_LANGUAGE:
    if (length < 3)
      goto fail;

    id3_parse_immediate(ptr, 3, field->immediate.value);
    break;

  case ID3_FIELD_TYPE_FRAMEID:
    if (length < 4)
      goto fail;

    id3_parse_immediate(ptr, 4, field->immediate.value);
    break;

  case ID3_FIELD_TYPE_DATE:
    if (length < 8)
      goto fail;

    id3_parse_immediate(ptr, 8, field->immediate.value);
    break;

  case ID3_FIELD_TYPE_LATIN1:
  case ID3_FIELD_TYPE_LATIN1FULL:
    {
      id3_latin1_t *latin1;

      latin1 = id3_parse_latin1(ptr, length,
				field->type == ID3_FIELD_TYPE_LATIN1FULL);
      if (latin1 == 0)
	goto fail;

      field->latin1.ptr = latin1;
    }
    break;

  case ID3_FIELD_TYPE_LATIN1LIST:
    {
      id3_byte_t const *end;
      id3_latin1_t *latin1, **strings;

      end = *ptr + length;

      while (end - *ptr > 0) {
	latin1 = id3_parse_latin1(ptr, end - *ptr, 0);
	if (latin1 == 0)
	  goto fail;

	strings = realloc(field->latin1list.strings,
			  (field->latin1list.nstrings + 1) * sizeof(*strings));
	if (strings == 0) {
	  free(latin1);
	  goto fail;
	}

	field->latin1list.strings = strings;
	field->latin1list.strings[field->latin1list.nstrings++] = latin1;
      }
    }
    break;

  case ID3_FIELD_TYPE_STRING:
  case ID3_FIELD_TYPE_STRINGFULL:
    {
      id3_ucs4_t *ucs4;

      ucs4 = id3_parse_string(ptr, length, *encoding,
			      field->type == ID3_FIELD_TYPE_STRINGFULL);
      if (ucs4 == 0)
	goto fail;

      field->string.ptr = ucs4;
    }
    break;

  case ID3_FIELD_TYPE_STRINGLIST:
    {
      id3_byte_t const *end;
      id3_ucs4_t *ucs4, **strings;

      end = *ptr + length;

      while (end - *ptr > 0) {
	ucs4 = id3_parse_string(ptr, end - *ptr, *encoding, 0);
	if (ucs4 == 0)
	  goto fail;

	strings = realloc(field->stringlist.strings,
			  (field->stringlist.nstrings + 1) * sizeof(*strings));
	if (strings == 0) {
	  free(ucs4);
	  goto fail;
	}

	field->stringlist.strings = strings;
	field->stringlist.strings[field->stringlist.nstrings++] = ucs4;
      }
    }
    break;

  case ID3_FIELD_TYPE_INT32PLUS:
  case ID3_FIELD_TYPE_BINARYDATA:
    {
      id3_byte_t *data;

      data = id3_parse_binary(ptr, length);
      if (data == 0)
	goto fail;

      field->binary.data   = data;
      field->binary.length = length;
    }
    break;
  }

  return 0;

 fail:
  return -1;
}
Esempio n. 3
0
/*
 * NAME:    compat->fixup()
 * DESCRIPTION: finish compatibility translations
 */
int id3_compat_fixup(struct id3_tag *tag)
{
    struct id3_frame *frame;
    unsigned int index;
    id3_ucs4_t timestamp[17] = { 0 };
    int result = 0;

    /* create a TDRC frame from obsolete TYER/TDAT/TIME frames */

    /*
     * TYE/TYER: YYYY
     * TDA/TDAT: DDMM
     * TIM/TIME: HHMM
     *
     * TDRC: yyyy-MM-ddTHH:mm
     */

    index = 0;
    while((frame = id3_tag_findframe(tag, ID3_FRAME_OBSOLETE, index++)))
    {
        char const *id;
        id3_byte_t const *data, *end;
        id3_length_t length;
        enum id3_field_textencoding encoding;
        id3_ucs4_t *string;

        id = id3_field_getframeid(&frame->fields[0]);
        assert(id);

        if(strcmp(id, "TYER") != 0 && strcmp(id, "YTYE") != 0 &&
           strcmp(id, "TDAT") != 0 && strcmp(id, "YTDA") != 0 &&
           strcmp(id, "TIME") != 0 && strcmp(id, "YTIM") != 0)
            continue;

        data = id3_field_getbinarydata(&frame->fields[1], &length);
        assert(data);

        if(length < 1)
            continue;

        end = data + length;

        encoding = (enum id3_field_textencoding)id3_parse_uint(&data, 1);
        string   = id3_parse_string(&data, end - data, encoding, 0);

        if(id3_ucs4_length(string) < 4)
        {
            free(string);
            continue;
        }

        if(strcmp(id, "TYER") == 0 ||
           strcmp(id, "YTYE") == 0)
        {
            timestamp[0] = string[0];
            timestamp[1] = string[1];
            timestamp[2] = string[2];
            timestamp[3] = string[3];
        }
        else if(strcmp(id, "TDAT") == 0 ||
                strcmp(id, "YTDA") == 0)
        {
            timestamp[4] = '-';
            timestamp[5] = string[2];
            timestamp[6] = string[3];
            timestamp[7] = '-';
            timestamp[8] = string[0];
            timestamp[9] = string[1];
        }
        else    /* TIME or YTIM */
        {
            timestamp[10] = 'T';
            timestamp[11] = string[0];
            timestamp[12] = string[1];
            timestamp[13] = ':';
            timestamp[14] = string[2];
            timestamp[15] = string[3];
        }

        free(string);
    }

    if(timestamp[0])
    {
        id3_ucs4_t *strings;

        frame = id3_frame_new("TDRC");
        if(frame == 0)
            goto fail;

        strings = timestamp;

        if(id3_field_settextencoding(&frame->fields[0],
                                     ID3_FIELD_TEXTENCODING_ISO_8859_1) == -1 ||
           id3_field_setstrings(&frame->fields[1], 1, &strings) == -1 ||
           id3_tag_attachframe(tag, frame) == -1)
        {
            id3_frame_delete(frame);
            goto fail;
        }
    }

    if(0)
    {
fail:
        result = -1;
    }

    return result;
}