[PATCH] Prepare for detecting offset of trailing metadata in =

David Byron none dbyron
Mon Sep 27 10:40:09 CEST 2010


=0A=
- add ff_ape_offset, call it from ff_ape_parse_tag=0A=
- validate size from APE footer against file size=0A=
- validate that APE header exists where advertised by the=0A=
APE footer=0A=
---=0A=
 libavformat/apetag.c |  138 =
++++++++++++++++++++++++++++++++++++++++++-------=0A=
 libavformat/apetag.h |   30 +++++++++++-=0A=
 2 files changed, 147 insertions(+), 21 deletions(-)=0A=
=0A=
diff --git a/libavformat/apetag.c b/libavformat/apetag.c=0A=
index d30c132..460d510 100644=0A=
--- a/libavformat/apetag.c=0A=
+++ b/libavformat/apetag.c=0A=
@@ -65,48 +65,146 @@ static int ape_tag_read_field(AVFormatContext *s)=0A=
 =0A=
 void ff_ape_parse_tag(AVFormatContext *s)=0A=
 {=0A=
+    int64_t ape_offset;=0A=
+    uint64_t ape_size;=0A=
+    uint32_t i, fields;=0A=
+    int ret;=0A=
+=0A=
+    ret =3D ff_ape_offset(s,-1,&ape_offset,&ape_size,&fields);=0A=
+    if (ret >=3D 0) {=0A=
+        url_fseek(s->pb, ape_offset, SEEK_SET);=0A=
+=0A=
+    for (i=3D0; i<fields; i++)=0A=
+        if (ape_tag_read_field(s) < 0) break;=0A=
+    }=0A=
+}=0A=
+=0A=
+int ff_ape_offset(AVFormatContext *s,=0A=
+                  int64_t override_end_offset,=0A=
+                  int64_t *ape_offset,=0A=
+                  uint64_t *ape_size,=0A=
+                  uint32_t *num_fields )=0A=
+{=0A=
     ByteIOContext *pb =3D s->pb;=0A=
-    int file_size =3D url_fsize(pb);=0A=
-    uint32_t val, fields, tag_bytes;=0A=
+    int64_t file_size;=0A=
+    uint32_t flags;=0A=
+    uint32_t fields;=0A=
+    uint64_t tag_bytes; /* 32 bits from the APE footer, but=0A=
+                           could be 32 bytes bigger if=0A=
+                           there's a header as well so don't=0A=
+                           use a 32 bit type */=0A=
+    uint32_t version;=0A=
     uint8_t buf[8];=0A=
-    int i;=0A=
+    int has_header;=0A=
+    int ret;=0A=
+=0A=
+    *ape_offset =3D -1;=0A=
+    *ape_size =3D 0;=0A=
+    if (num_fields)=0A=
+        *num_fields =3D 0;=0A=
+=0A=
+    if (override_end_offset =3D=3D -1) {=0A=
+        file_size =3D url_fsize(pb);=0A=
+        if (file_size < 0)=0A=
+            return file_size; /* here filesize is actually an error */=0A=
+    } else=0A=
+        file_size =3D override_end_offset;=0A=
 =0A=
     if (file_size < APE_TAG_FOOTER_BYTES)=0A=
-        return;=0A=
+        return 0;=0A=
 =0A=
-    url_fseek(pb, file_size - APE_TAG_FOOTER_BYTES, SEEK_SET);=0A=
+    ret =3D url_fseek(pb, file_size - APE_TAG_FOOTER_BYTES, SEEK_SET);=0A=
+    if (ret < 0)=0A=
+        return ret;=0A=
 =0A=
-    get_buffer(pb, buf, 8);    /* APETAGEX */=0A=
-    if (strncmp(buf, "APETAGEX", 8)) {=0A=
-        return;=0A=
-    }=0A=
+    ret =3D get_buffer(pb, buf, 8);    /* APETAGEX */=0A=
+    if (ret < 0)=0A=
+        return ret;=0A=
+=0A=
+    assert(ret =3D=3D 8);=0A=
+    if (memcmp(buf, "APETAGEX", 8))=0A=
+        return 0;=0A=
 =0A=
-    val =3D get_le32(pb);        /* APE tag version */=0A=
-    if (val > APE_TAG_VERSION) {=0A=
+    version =3D get_le32(pb);        /* APE tag version */=0A=
+    if (version > APE_TAG_VERSION) {=0A=
         av_log(s, AV_LOG_ERROR, "Unsupported tag version. (>=3D%d)\n", =
APE_TAG_VERSION);=0A=
-        return;=0A=
+        return 0;=0A=
     }=0A=
 =0A=
     tag_bytes =3D get_le32(pb);  /* tag size */=0A=
     if (tag_bytes - APE_TAG_FOOTER_BYTES > (1024 * 1024 * 16)) {=0A=
         av_log(s, AV_LOG_ERROR, "Tag size is way too big\n");=0A=
-        return;=0A=
+        return 0;=0A=
     }=0A=
 =0A=
     fields =3D get_le32(pb);     /* number of fields */=0A=
+    if (num_fields)=0A=
+        *num_fields =3D fields;=0A=
     if (fields > 65536) {=0A=
         av_log(s, AV_LOG_ERROR, "Too many tag fields (%d)\n", fields);=0A=
-        return;=0A=
+        return 0;=0A=
     }=0A=
 =0A=
-    val =3D get_le32(pb);        /* flags */=0A=
-    if (val & APE_TAG_FLAG_IS_HEADER) {=0A=
+    flags =3D get_le32(pb);        /* flags */=0A=
+    if (flags & APE_TAG_FLAG_IS_HEADER) {=0A=
         av_log(s, AV_LOG_ERROR, "APE Tag is a header\n");=0A=
-        return;=0A=
+        return 0;=0A=
     }=0A=
 =0A=
-    url_fseek(pb, file_size - tag_bytes, SEEK_SET);=0A=
+    /* We've got a legit APE tag footer but there's more to=0A=
+       do before we know how big the tag is, as well as if=0A=
+       the tag is valid */=0A=
+    has_header =3D (version =3D=3D 2000) && (flags & =
APE_TAG_FLAG_CONTAINS_HEADER);=0A=
 =0A=
-    for (i=3D0; i<fields; i++)=0A=
-        if (ape_tag_read_field(s) < 0) break;=0A=
+    if (has_header) {=0A=
+        av_log(s, AV_LOG_VERBOSE,"%s: \"%s\": APE Tag contains =
header\n",=0A=
+               __FUNCTION__, s->filename);=0A=
+        tag_bytes +=3D 32;=0A=
+    } else {=0A=
+        av_log(s, AV_LOG_VERBOSE, "%s: \"%s\": APE Tag does not contain =
a "=0A=
+               "header\n", __FUNCTION__, s->filename);=0A=
+    }=0A=
+=0A=
+    /* It's possible that the size indicated in the tag is=0A=
+       bigger than the file.  To be safe, interpret this as=0A=
+       an invalid tag and don't do anything */=0A=
+    if (tag_bytes > file_size) {=0A=
+        av_log(s, AV_LOG_WARNING, "%s: \"%s\": APE size%s is %" PRId64 =
"(0x%"=0A=
+               PRIx64 ") byte(s), but file is only %" PRId64 "(0x%" =
PRIx64=0A=
+               ") byte(s)\n", __FUNCTION__, s->filename,=0A=
+               has_header ? " (including header)" : "", tag_bytes, =
tag_bytes,=0A=
+               file_size, file_size);=0A=
+        return 0;=0A=
+    }=0A=
+=0A=
+    if (has_header) {=0A=
+        /* Read 8 bytes where the header is supposed to be=0A=
+           to make sure it says "APETAGEX" */=0A=
+        ret =3D url_fseek(pb, file_size - tag_bytes, SEEK_SET);=0A=
+        if (ret < 0)=0A=
+            return ret;=0A=
+        ret =3D get_buffer(pb, buf, 8);=0A=
+        if (ret < 0)=0A=
+            return ret;=0A=
+=0A=
+        assert(ret =3D=3D 8);=0A=
+=0A=
+        if (memcmp(buf, "APETAGEX", 8)) {=0A=
+            av_log(s, AV_LOG_WARNING, "%s: \"%s\": offset %" PRId64 =
"(0x%"=0A=
+                   PRIx64 ") is not APETAGEX -- not a valid APE tag\n",=0A=
+                   __FUNCTION__, s->filename, file_size - tag_bytes,=0A=
+                   file_size - tag_bytes);=0A=
+            return 0;=0A=
+        }=0A=
+    }=0A=
+=0A=
+    /* Finally, the APE tag is valid */=0A=
+    *ape_size =3D tag_bytes;=0A=
+    *ape_offset =3D file_size - tag_bytes;=0A=
+=0A=
+    av_log(s, AV_LOG_VERBOSE, "%s: \"%s\": %" PRId64 " byte APE tag at "=0A=
+           "offset %" PRId64 "(0x%" PRIx64 ")\n", __FUNCTION__, =
s->filename,=0A=
+           *ape_size, *ape_offset, *ape_offset);=0A=
+=0A=
+    return 0;=0A=
 }=0A=
diff --git a/libavformat/apetag.h b/libavformat/apetag.h=0A=
index 8aaef68..b7dd7aa 100644=0A=
--- a/libavformat/apetag.h=0A=
+++ b/libavformat/apetag.h=0A=
@@ -30,4 +30,32 @@=0A=
  */=0A=
 void ff_ape_parse_tag(AVFormatContext *s);=0A=
 =0A=
-#endif /* AVFORMAT_ID3V2_H */=0A=
+/**=0A=
+ * Determine the offset of an APE tag at the end of a file=0A=
+ *=0A=
+ * @param override_end_offset ignored if -1, otherwise=0A=
+ * consider it the offset of the end of the file=0A=
+ *=0A=
+ * @param ape_offset populated with -1 if no APE tag,=0A=
+ * otherwise the offset of the APE tag=0A=
+ *=0A=
+ * @param ape_size populated with the size of the APE tag in=0A=
+ * @p filename (or 0 if none was found)=0A=
+ *=0A=
+ * @param num_fields if not NULL, populated with the number=0A=
+ * of fields in the APE tag (0 if there is no APE tag)=0A=
+ *=0A=
+ * @retval 0 successfully determined offset of the APE tag=0A=
+ * (or that there isn't one).  The stream position is=0A=
+ * undefined.=0A=
+ *=0A=
+ * @retval < 0 error looking for the offset of the APE tag.=0A=
+ * The stream position is undefined.=0A=
+ */=0A=
+int ff_ape_offset(AVFormatContext *s,=0A=
+                  int64_t override_end_offset,=0A=
+                  int64_t *ape_offset,=0A=
+                  uint64_t *ape_size,=0A=
+                  uint32_t *num_fields );=0A=
+=0A=
+#endif /* AVFORMAT_APETAG_H */=0A=
-- =0A=
1.6.0.4=0A=
=0A=

------=_NextPart_000_004D_01CB5E5B.BC517140
Content-Type: application/octet-stream;
	name="0002-Prepare-for-detecting-offset-of-trailing-metadata-in.patch"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="0002-Prepare-for-detecting-offset-of-trailing-metadata-in.patch"




More information about the ffmpeg-devel mailing list