protected void writeBody(ID3DataOutputStream oIDOS) throws IOException {
    // text encoding
    oIDOS.writeUnsignedByte(m_oTextEncoding.getEncodingValue());
    // price string
    oIDOS.write(m_sPrice.getBytes());
    oIDOS.writeUnsignedByte(0);
    // valid until
    oIDOS.write(m_sValidUntil.getBytes());
    // contact url
    oIDOS.write(m_sContactUrl.getBytes());
    oIDOS.writeUnsignedByte(0);
    // received as
    oIDOS.writeUnsignedByte(m_byReceivedAs);
    // name of seller
    if (m_sNameOfSeller != null) {
      oIDOS.write(m_sNameOfSeller.getBytes(m_oTextEncoding.getEncodingString()));
    }
    // null terminating optional name of seller
    if (m_oTextEncoding.equals(TextEncoding.ISO_8859_1)) {
      oIDOS.writeUnsignedByte(0);
    } else {
      oIDOS.writeUnsignedByte(0);
      oIDOS.writeUnsignedByte(0);
    }
    // description
    if (m_sDescription != null) {
      oIDOS.write(m_sDescription.getBytes(m_oTextEncoding.getEncodingString()));
    }
    // null terminating optional description
    if (m_oTextEncoding.equals(TextEncoding.ISO_8859_1)) {
      oIDOS.writeUnsignedByte(0);
    } else {
      oIDOS.writeUnsignedByte(0);
      oIDOS.writeUnsignedByte(0);
    }
    // optional company logo image
    if (m_abySellerLogoData != null) {
      // image mime type (optional, "image/" assumed if not set)
      if (m_sPictureMimeType != null) {
        oIDOS.write(m_sPictureMimeType.getBytes());
      }
      oIDOS.writeUnsignedByte(0); // terminating null

      // actual image data
      oIDOS.write(m_abySellerLogoData);
    }
  }
  public boolean equals(Object oOther) {
    if ((oOther == null) || (!(oOther instanceof COMRID3V2Frame))) {
      return false;
    }

    COMRID3V2Frame oOtherCOMR = (COMRID3V2Frame) oOther;

    return (m_oTextEncoding.equals(oOtherCOMR.m_oTextEncoding)
        && m_sPrice.equals(oOtherCOMR.m_sPrice)
        && m_sValidUntil.equals(oOtherCOMR.m_sValidUntil)
        && m_sContactUrl.equals(oOtherCOMR.m_sContactUrl)
        && (m_byReceivedAs == oOtherCOMR.m_byReceivedAs)
        && m_sNameOfSeller.equals(oOtherCOMR.m_sNameOfSeller)
        && m_sDescription.equals(oOtherCOMR.m_sDescription)
        && m_sPictureMimeType.equals(oOtherCOMR.m_sPictureMimeType)
        && Arrays.equals(m_abySellerLogoData, oOtherCOMR.m_abySellerLogoData));
  }
 /**
  * Constructor.
  *
  * @param sPrice a price(s) string (a price string consists of a three letter ISO-4217 currency
  *     code, followed by an amount, where "." is used as the decimal separator). Multiple prices
  *     may be separated by a "/" characters.
  * @param sValidUntil the date the prices offer is valid until, in the format YYYYMMDD
  * @param sContactUrl an URL at which contact can be made with the seller
  * @param byReceivedAs byte specifying how the track will be delivered when purchased
  * @param sNameOfSeller the name of the seller
  * @param sDescription short description of the product
  * @param sPictureMimeType the mime type of the picture (only "image/jpeg" and "image/png" are
  *     allowed by the ID3 specification)
  * @param abySellerLogoData the image data containing the seller's logo
  * @throws org.blinkenlights.jid3.ID3Exception if sPrice is null or invalid
  * @throws org.blinkenlights.jid3.ID3Exception if sValidUntil is null or invalid
  * @throws org.blinkenlights.jid3.ID3Exception if sContactUrl is null
  * @throws org.blinkenlights.jid3.ID3Exception if sNameOfSeller is null
  * @throws org.blinkenlights.jid3.ID3Exception if sDecription is null
  */
 public COMRID3V2Frame(
     String sPrice,
     String sValidUntil,
     String sContactUrl,
     byte byReceivedAs,
     String sNameOfSeller,
     String sDescription,
     String sPictureMimeType,
     byte[] abySellerLogoData)
     throws ID3Exception {
   m_oTextEncoding = TextEncoding.getDefaultTextEncoding();
   if (sPrice == null) {
     throw new ID3Exception("Price required in COMR frame.");
   }
   if (!sPrice.matches("(?uis)(\\w{3}\\d*\\.?\\d+/?)+")) {
     throw new ID3Exception("Invalid COMR frame price string.");
   }
   m_sPrice = sPrice;
   if (sValidUntil == null) {
     throw new ID3Exception("Valid until valud required in COMR frame.");
   }
   if (!sValidUntil.matches("(?uis)\\d{8}")) {
     throw new ID3Exception("Invalid COMR frame valid until date.");
   }
   m_sValidUntil = sValidUntil;
   if (sContactUrl == null) {
     throw new ID3Exception("Contact URL required in COMR frame.");
   }
   m_sContactUrl = sContactUrl;
   m_byReceivedAs = byReceivedAs;
   if (sNameOfSeller == null) {
     throw new ID3Exception("Name of seller required in COMR frame.");
   }
   m_sNameOfSeller = sNameOfSeller;
   if (sDescription == null) {
     throw new ID3Exception("Description required in COMR frame.");
   }
   m_sDescription = sDescription;
   m_sPictureMimeType = sPictureMimeType;
   if (m_sPictureMimeType == null) {
     m_sPictureMimeType = "image/";
   }
   m_abySellerLogoData = abySellerLogoData;
 }
  public COMRID3V2Frame(InputStream oIS) throws ID3Exception {
    // Parse out the text encoding and text string from the raw data
    try {
      ID3DataInputStream oFrameDataID3DIS = new ID3DataInputStream(oIS);

      // text encoding
      m_oTextEncoding = TextEncoding.getTextEncoding(oFrameDataID3DIS.readUnsignedByte());

      // price (read to null)
      m_sPrice = oFrameDataID3DIS.readStringToNull();

      // valid until
      byte[] abyValidUntil = new byte[8];
      oFrameDataID3DIS.readFully(abyValidUntil);
      m_sValidUntil = new String(abyValidUntil);

      // contact url (read to null)
      m_sContactUrl = oFrameDataID3DIS.readStringToNull();

      // received as
      m_byReceivedAs = (byte) oFrameDataID3DIS.readUnsignedByte();

      // name of seller (read to null)
      m_sNameOfSeller = oFrameDataID3DIS.readStringToNull(m_oTextEncoding);

      // description (read to null)
      m_sDescription = oFrameDataID3DIS.readStringToNull(m_oTextEncoding);

      // is there a company logo picture coming?
      if (oFrameDataID3DIS.available() > 0) {
        // company logo mime type (read to null)
        m_sPictureMimeType = oFrameDataID3DIS.readStringToNull();

        // company logo picture data
        m_abySellerLogoData = new byte[oFrameDataID3DIS.available()];
        oFrameDataID3DIS.readFully(m_abySellerLogoData);
      }
    } catch (Exception e) {
      throw new InvalidFrameID3Exception(e);
    }
  }