/*
* AENCID3V2Frame.java
*
* Created on Jan 17, 2004
*
* Copyright (C)2004,2005 Paul Grebenc
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* $Id: AENCID3V2Frame.java,v 1.10 2005/02/06 18:11:20 paul Exp $
*/
package org.blinkenlights.jid3.v2;
import java.io.*;
import java.util.*;
import org.blinkenlights.jid3.*;
import org.blinkenlights.jid3.io.*;
import org.blinkenlights.jid3.util.*;
/**
* @author paul
*
* Frame containing audio encryption information.
*/
public class AENCID3V2Frame extends ID3V2Frame
{
private String m_sOwnerIdentifier = null;
private int m_iPreviewStartFrame;
private int m_iPreviewLengthFrames;
private byte[] m_abyEncryptionInfo = null;
/** Constructor.
*
* @param sOwnerIdentifier an URL or email address, providing detail regarding the encryption of this file,
* or null if not used
* @param iPreviewStartFrame the number of the first frame of this file which is not encrypted, or zero if
* the entire file is encrypted
* @param iPreviewLengthFrames the length in frames of the unencrypted preview portion of the file, or zero
* if the entire file is encrypted
* @param abyEncryptionInfo any data which is required for decryption, as defined by the method used, or null
* if not required
* @throws ID3Exception if either iPreviewStartFrame or iPreviewLengthFrames are negative, or greater than 65535
*/
public AENCID3V2Frame(String sOwnerIdentifier,
int iPreviewStartFrame,
int iPreviewLengthFrames,
byte[] abyEncryptionInfo)
throws ID3Exception
{
// owner identifier (if null replace with zero-length string)
m_sOwnerIdentifier = sOwnerIdentifier;
if (m_sOwnerIdentifier == null)
{
m_sOwnerIdentifier = "";
}
if ((iPreviewStartFrame < 0) || (iPreviewStartFrame > 65535))
{
throw new ID3Exception("Preview start frame must be unsigned 16-bit integer values.");
}
m_iPreviewStartFrame = iPreviewStartFrame;
if ((iPreviewLengthFrames < 0) || (iPreviewLengthFrames > 65535))
{
throw new ID3Exception("Preview length in frames must be unsinged 16-bit integer values.");
}
m_iPreviewLengthFrames = iPreviewLengthFrames;
// encryption info (if null replace with zero-length byte array)
m_abyEncryptionInfo = abyEncryptionInfo;
if (m_abyEncryptionInfo == null)
{
m_abyEncryptionInfo = new byte[0];
}
}
public AENCID3V2Frame(InputStream oIS)
throws ID3Exception
{
// Parse out the text encoding and text string from the raw data
try
{
ID3DataInputStream oFrameDataID3DIS = new ID3DataInputStream(oIS);
// owner identifier (read to null)
ByteArrayOutputStream oOwnerIdentifierBAOS = new ByteArrayOutputStream();
int iOwnerIdentifierByte;
do
{
iOwnerIdentifierByte = oFrameDataID3DIS.readUnsignedByte();
if (iOwnerIdentifierByte != 0)
{
oOwnerIdentifierBAOS.write(iOwnerIdentifierByte);
}
}
while (iOwnerIdentifierByte != 0);
if (oOwnerIdentifierBAOS.size() > 0)
{
byte[] abyOwnerIdentifier = oOwnerIdentifierBAOS.toByteArray();
m_sOwnerIdentifier = new String(abyOwnerIdentifier);
}
// start frame of preview
m_iPreviewStartFrame = oFrameDataID3DIS.readBEUnsigned16();
// length in frames of preview
m_iPreviewLengthFrames = oFrameDataID3DIS.readBEUnsigned16();
// encryption info
m_abyEncryptionInfo = new byte[oFrameDataID3DIS.available()];
oFrameDataID3DIS.readFully(m_abyEncryptionInfo);
}
catch (Exception e)
{
throw new InvalidFrameID3Exception(e);
}
}
public void accept(ID3Visitor oID3Visitor)
{
oID3Visitor.visitAENCID3V2Frame(this);
}
/** Set the owner identifier for the encryption described in this frame.
*
* @param sOwnerIdentifier an URL or an email address where the user can find information on decrypting this file
* @throws ID3Exception if this frame is in a tag with another AENC frame which would have the same owner identifier
*/
public void setOwnerIdentifier(String sOwnerIdentifier)
throws ID3Exception
{
String sOrigOwnerIdentifier = m_sOwnerIdentifier;
m_sOwnerIdentifier = sOwnerIdentifier;
if (m_sOwnerIdentifier == null)
{
m_sOwnerIdentifier = "";
}
// try this update, and reverse it if it generates and error
try
{
notifyID3Observers();
}
catch (ID3Exception e)
{
m_sOwnerIdentifier = sOrigOwnerIdentifier;
throw e;
}
}
/** Get the owner identifier for the encryption described in this frame.
*
* @return an URL or an email address where the user can find information on decrypting this file
*/
public String getOwnerIdentifier()
{
return m_sOwnerIdentifier;
}
/** Set the range of the unencrypted preview section of this file.
*
* @param iPreviewStartFrame the number of the first frame of this file which is not encrypted, or zero if
* the entire file is encrypted
* @param iPreviewLengthFrames the length in frames of the unencrypted preview portion of the file, or zero
* if the entire file is encrypted
* @throws ID3Exception if either iPreviewStartFrame or iPreviewLengthFrames are negative, or greater than 65535
*/
public void setPreviewRange(int iPreviewStartFrame, int iPreviewLengthFrames)
throws ID3Exception
{
if ((iPreviewStartFrame < 0) || (iPreviewStartFrame > 65535) ||
(iPreviewLengthFrames < 0) || (iPreviewLengthFrames > 65535))
{
throw new ID3Exception("Preview start frame and frames length must be unsigned 16-bit integer values.");
}
m_iPreviewStartFrame = iPreviewStartFrame;
m_iPreviewLengthFrames = iPreviewLengthFrames;
}
/** Get the starting frame of the unencrypted preview section of this file.
*
* @return the starting frame number, or zero if there is no preview section
*/
public int getPreviewStartFrame()
{
return m_iPreviewStartFrame;
}
/** Get the length in frames of the preview section of this file.
*
* @return the length in frames, or zero if there is no preview section
*/
public int getPreviewFramesLength()
{
return m_iPreviewLengthFrames;
}
/** Set any additional encryption info which will be required for the decryption of this file, based
* on the particular encryption method in use.
*
* @param abyEncryptionInfo any data which is required for decryption, as defined by the method used, or null
* if not required
*/
public void setEncryptionInfo(byte[] abyEncryptionInfo)
{
m_abyEncryptionInfo = abyEncryptionInfo;
if (m_abyEncryptionInfo == null)
{
m_abyEncryptionInfo = new byte[0];
}
}
/** Get additional encryption info required for the particular method used.
*
* @return any additional encryption info, if required, or null
*/
public byte[] getEncryptionInfo()
{
return m_abyEncryptionInfo;
}
protected byte[] getFrameId()
{
return "AENC".getBytes();
}
public String toString()
{
return "Audio encryption: Owner identifier=[" + m_sOwnerIdentifier + "], Preview start frame = " +
m_iPreviewStartFrame + ", Preview length = " + m_iPreviewLengthFrames + ", Encryption info=[" +
ID3Util.convertBytesToHexString(m_abyEncryptionInfo, true) + "]";
}
protected void writeBody(ID3DataOutputStream oIDOS)
throws IOException
{
// owner information
oIDOS.write(m_sOwnerIdentifier.getBytes());
oIDOS.writeUnsignedByte(0);
// preview start frame
oIDOS.writeBEUnsigned16(m_iPreviewStartFrame);
// preview length in frames
oIDOS.writeBEUnsigned16(m_iPreviewLengthFrames);
// encryption info
oIDOS.write(m_abyEncryptionInfo);
}
public boolean equals(Object oOther)
{
if ((oOther == null) || (!(oOther instanceof AENCID3V2Frame)))
{
return false;
}
AENCID3V2Frame oOtherAENC = (AENCID3V2Frame)oOther;
return (m_sOwnerIdentifier.equals(oOtherAENC.m_sOwnerIdentifier) &&
(m_iPreviewStartFrame == oOtherAENC.m_iPreviewStartFrame) &&
(m_iPreviewLengthFrames == oOtherAENC.m_iPreviewLengthFrames) &&
Arrays.equals(m_abyEncryptionInfo, oOtherAENC.m_abyEncryptionInfo));
}
}