anchor.diff:        (log-id3-frame "v21 tag: ~a" (vpprint me nil)))))
   
   (defclass id3-ext-header ()
  -  ((size    :accessor size    :initarg :size    :initform 0)
  -   (flags   :accessor flags   :initarg :flags   :initform 0)
  -   (padding :accessor padding :initarg :padding :initform 0)
  -   (crc     :accessor crc     :initarg :crc     :initform nil))
  +  ((size         :accessor size         :initarg :size         :initform 0)
  +   (flags        :accessor flags        :initarg :flags        :initform 0)
  +   (padding      :accessor padding      :initarg :padding      :initform 0)
  +   (crc          :accessor crc          :initarg :crc          :initform nil)
  +   (is-update    :accessor is-update    :initarg :is-update    :initform nil)
  +   (restrictions :accessor restrictions :initarg :restrictions :initform 0))
     (:documentation "Class representing a V2.3/4 extended header"))
   
  -(defmacro ext-header-crc-p    (flags) `(logbitp 14 ,flags))
  -
  -;;; XXX I almost certainly don't have handling of extended headers complete/correct wrt FLAGS
  -(defmethod initialize-instance ((me id3-ext-header) &key instream)
  +(defmethod initialize-instance :after ((me id3-ext-header) &key instream version)
     "Read in the extended header.  Caller will have stream-seek'ed to correct location in file.
  -Note: extended headers are subject to unsynchronization, so make sure that INSTREAM has been made sync-safe."
  -  (with-slots (size flags padding crc) me
  +Note: extended headers are subject to unsynchronization, so make sure that INSTREAM has been made sync-safe.
  +NB: 2.3 and 2.4 extended flags are different..."
  +  (with-slots (size flags padding crc is-update restrictions) me
       (setf size (stream-read-u32 instream))
  -    (setf flags (stream-read-u16 instream))
  -    (setf padding (stream-read-u32 instream))
  -    (when (not (zerop flags))
  -
  -      ;; at this point, we have to potentially read in other fields depending on flags.
  -      ;; for now, just error out...
  -      (assert (zerop flags) () "non-zero extended header flags = ~x, check validity")
  -      ;;(when (ext-header-crc-p flags)
  -      ;;  (setf crc (stream-read-u32 instream)))))
  -      )))
  +    (setf flags (stream-read-u16 instream)) ; reading in flags fields, must discern below 2.3/2.4
  +    (log-id3-frame "making id3-ext-header: version = ~d, size = ~d, flags = ~x"
  +                   version size flags)
  +    (ecase version
  +      (3
  +       (setf padding (stream-read-u32 instream))
  +       (when (logand flags #x8000)
  +         (if (not (= size 10))
  +             (warn-user "CRC bit set in extended header, but not enough bytes to read")
  +             (setf crc (stream-read-u32 instream)))))
  +      (4
  +       (when (not (= (logand #xff00 flags) 1))
  +         (warn-user "v2.4 extended flags length is not 1"))
  +       (setf flags (logand flags #xff)) ; lop off type byte (the flags length)
  +       (let ((len 0))
  +         (when (logand #x3000 flags)
  +           (setf len (stream-read-u8 instream))
  +           (when (not (zerop len)) (warn-user "v2.4 extended header is-tag length is ~d" len))
  +           (setf is-update t))
  +         (when (logand #x2000 flags)
  +           (setf len (stream-read-u8 instream))
  +           (when (not (= 5 len)) (warn-user "v2.4 extended header crc length is ~d" len))
  +           (setf crc (stream-read-u32 instream :bits-per-byte 7)))
  +         (when (logand #x1000 flags)
  +           (setf len (stream-read-u8 instream))
  +           (when (not (= 5 1)) (warn-user "v2.4 extended header restrictions length is ~d" len))
  +           (setf restrictions (stream-read-u8 instream))))))))
  +
  +(defun ext-header-restrictions-grok (r)
  +  "Return a string that shows what restrictions are in an ext-header"
  +  (if (zerop r)
  +      "No restrictions"
  +      (with-output-to-string (s)
  +        (format s "Tag size restictions: ~a/"
  +                (ecase (ash (logand #xc0 r) -6)
  +                  (0 "No more than 128 frames and 1 MB total tag size")
  +                  (1 "No more than 64 frames and 128 KB total tag size")
  +                  (2 "No more than 32 frames and 40 KB total tag size")
  +                  (3 "No more than 32 frames and 4 KB total tag size")))
  +        (format s "Tag encoding restictions: ~a/"
  +                (ecase (ash (logand #x20 r) -5)
  +                  (0 "No restrictions")
  +                  (1 "Strings are only encoded with ISO-8859-1 [ISO-8859-1] or UTF-8 [UTF-8]")))
  +        (format s "Tag field size restictions: ~a/"
  +                (ecase (ash (logand #x18 r) -3)
  +                  (0 "No restrictions")
  +                  (1 "No string is longer than 1024 characters")
  +                  (2 "No string is longer than 128 characters")
  +                  (3 "No string is longer than 30 characters")))
  +        (format s "Tag image encoding restrictions: ~a/"
  +                (ecase (ash (logand #x04 r) -2)
  +                  (0 "No restrictions")
  +                  (1 "Images are encoded only with PNG [PNG] or JPEG [JFIF]")))
  +        (format s "Tag image size restrictions: ~a"
  +                (ecase (logand #x04 r)
  +                  (0 "No restrictions")
  +                  (1 "All images are 256x256 pixels or smaller.")
  +                  (2 "All images are 64x64 pixels or smaller.")
  +                  (3 "All images are exactly 64x64 pixels, unless required otherwise."))))))
   
   (defmethod vpprint ((me id3-ext-header) stream)
  -  (with-slots (size flags padding crc) me
  -    (format stream "extended header: size: ~d, flags: ~x, padding ~:d, crc = ~x~%"
  -            size flags padding crc)))
  +  (with-slots (size flags padding crc is-update restrictions) me
  +    (format stream "extended header: size: ~d, flags: ~x, padding ~:d, crc = ~x is-update ~a, restrictions = ~x/~a~%"
  +            size flags padding crc is-update restrictions (ext-header-restrictions-grok restrictions))))
   
   ;;; NB: v2.2 only really defines bit-7. It does document bit-6 as being the compression flag, but then states
   ;;; that if it is set, the software should "ignore the entire tag if this (bit-6) is set"
  
positive.code:     (format stream "title = <~a>, artist = <~a>, album = <~a>, year = <~a>, comment = <~a>, track = <~d>, genre = ~d (~a)"
              title artist album year comment track genre (mp3-tag:get-id3v1-genre genre))))
  
  (defmethod initialize-instance ((me v21-tag-header) &key instream)
    "Read in a V2.1 tag.  Caller will have stream-seek'ed file to correct location and ensured that TAG was present"
    (log5:with-context "v21-frame-initializer"
      (log-id3-frame "reading v2.1 tag")
  
negative.code:             (with-output-to-string (s)
                (format s "Header: version/revision: ~d/~d, flags: ~a, size = ~:d bytes; ~a; ~a"
                        version revision (print-header-flags nil flags) size
                        (if (and (header-extended-p flags) ext-header)
                            (concatenate 'string "Extended header: " (vpprint ext-header nil))
                            "No extended header")
                        (if v21-tag-header
  