content: /*
   * Copyright (C) 2007-2008 Esmertec AG.
   * Copyright (C) 2007-2008 The Android Open Source Project
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package spam.blocker.util.pdu.pdu;
  
  import android.net.Uri;
  
  import java.util.HashMap;
  import java.util.Map;
  
  /**
   * The pdu part.
   */
  public class PduPart {
      /**
       * Well-Known Parameters.
       */
      public static final int P_Q                  = 0x80;
      public static final int P_CHARSET            = 0x81;
      public static final int P_LEVEL              = 0x82;
      public static final int P_TYPE               = 0x83;
      public static final int P_DEP_NAME           = 0x85;
      public static final int P_DEP_FILENAME       = 0x86;
      public static final int P_DIFFERENCES        = 0x87;
      public static final int P_PADDING            = 0x88;
      // This value of "TYPE" s used with Content-Type: multipart/related
      public static final int P_CT_MR_TYPE         = 0x89;
      public static final int P_DEP_START          = 0x8A;
      public static final int P_DEP_START_INFO     = 0x8B;
      public static final int P_DEP_COMMENT        = 0x8C;
      public static final int P_DEP_DOMAIN         = 0x8D;
      public static final int P_MAX_AGE            = 0x8E;
      public static final int P_DEP_PATH           = 0x8F;
      public static final int P_SECURE             = 0x90;
      public static final int P_SEC                = 0x91;
      public static final int P_MAC                = 0x92;
      public static final int P_CREATION_DATE      = 0x93;
      public static final int P_MODIFICATION_DATE  = 0x94;
      public static final int P_READ_DATE          = 0x95;
      public static final int P_SIZE               = 0x96;
      public static final int P_NAME               = 0x97;
      public static final int P_FILENAME           = 0x98;
      public static final int P_START              = 0x99;
      public static final int P_START_INFO         = 0x9A;
      public static final int P_COMMENT            = 0x9B;
      public static final int P_DOMAIN             = 0x9C;
      public static final int P_PATH               = 0x9D;
  
      /**
       *  Header field names.
       */
       public static final int P_CONTENT_TYPE       = 0x91;
       public static final int P_CONTENT_LOCATION   = 0x8E;
       public static final int P_CONTENT_ID         = 0xC0;
       public static final int P_DEP_CONTENT_DISPOSITION = 0xAE;
       public static final int P_CONTENT_DISPOSITION = 0xC5;
      // The next header is unassigned header, use reserved header(0x48) value.
       public static final int P_CONTENT_TRANSFER_ENCODING = 0xC8;
  
       /**
        * Content=Transfer-Encoding string.
        */
       public static final String CONTENT_TRANSFER_ENCODING =
               "Content-Transfer-Encoding";
  
       /**
        * Value of Content-Transfer-Encoding.
        */
       public static final String P_BINARY = "binary";
       public static final String P_7BIT = "7bit";
       public static final String P_8BIT = "8bit";
       public static final String P_BASE64 = "base64";
       public static final String P_QUOTED_PRINTABLE = "quoted-printable";
  
       /**
        * Value of disposition can be set to PduPart when the value is octet in
        * the PDU.
        * "from-data" instead of Form-data<Octet 128>.
        * "attachment" instead of Attachment<Octet 129>.
        * "inline" instead of Inline<Octet 130>.
        */
       static final byte[] DISPOSITION_FROM_DATA = "from-data".getBytes();
       static final byte[] DISPOSITION_ATTACHMENT = "attachment".getBytes();
       static final byte[] DISPOSITION_INLINE = "inline".getBytes();
  
       /**
        * Content-Disposition value.
        */
       public static final int P_DISPOSITION_FROM_DATA  = 0x80;
       public static final int P_DISPOSITION_ATTACHMENT = 0x81;
       public static final int P_DISPOSITION_INLINE     = 0x82;
  
       /**
        * Header of part.
        */
       private Map<Integer, Object> mPartHeader = null;
  
       /**
        * Data uri.
        */
       private Uri mUri = null;
  
       /**
        * Part data.
        */
       private byte[] mPartData = null;
  
       private static final String TAG = "PduPart";
  
       /**
        * Empty Constructor.
        */
       public PduPart() {
           mPartHeader = new HashMap<Integer, Object>();
       }
  
       /**
        * Set part data. The data are stored as byte array.
        *
        * @param data the data
        */
       public void setData(byte[] data) {
           if(data == null) {
              return;
          }
  
           mPartData = new byte[data.length];
           System.arraycopy(data, 0, mPartData, 0, data.length);
       }
  
       /**
        * @return A copy of the part data or null if the data wasn't set or
        *         the data is stored as Uri.
        * @see #getDataUri
        */
       public byte[] getData() {
           if(mPartData == null) {
              return null;
           }
  
           byte[] byteArray = new byte[mPartData.length];
           System.arraycopy(mPartData, 0, byteArray, 0, mPartData.length);
           return byteArray;
       }
  
      /**
       * @return The length of the data, if this object have data, else 0.
       */
       public int getDataLength() {
           if(mPartData != null){
               return mPartData.length;
           } else {
               return 0;
           }
       }
  
  
       /**
        * Set data uri. The data are stored as Uri.
        *
        * @param uri the uri
        */
       public void setDataUri(Uri uri) {
           mUri = uri;
       }
  
       /**
        * @return The Uri of the part data or null if the data wasn't set or
        *         the data is stored as byte array.
        * @see #getData
        */
       public Uri getDataUri() {
           return mUri;
       }
  
       /**
        * Set Content-id value
        *
        * @param contentId the content-id value
        * @throws NullPointerException if the value is null.
        */
       public void setContentId(byte[] contentId) {
           if((contentId == null) || (contentId.length == 0)) {
               throw new IllegalArgumentException(
                       "Content-Id may not be null or empty.");
           }
  
           if ((contentId.length > 1)
                   && ((char) contentId[0] == '<')
                   && ((char) contentId[contentId.length - 1] == '>')) {
               mPartHeader.put(P_CONTENT_ID, contentId);
               return;
           }
  
           // Insert beginning '<' and trailing '>' for Content-Id.
           byte[] buffer = new byte[contentId.length + 2];
           buffer[0] = (byte) (0xff & '<');
           buffer[buffer.length - 1] = (byte) (0xff & '>');
           System.arraycopy(contentId, 0, buffer, 1, contentId.length);
           mPartHeader.put(P_CONTENT_ID, buffer);
       }
  
       /**
        * Get Content-id value.
        *
        * @return the value
        */
       public byte[] getContentId() {
           return (byte[]) mPartHeader.get(P_CONTENT_ID);
       }
  
       /**
        * Set Char-set value.
        *
        * @param charset the value
        */
       public void setCharset(int charset) {
           mPartHeader.put(P_CHARSET, charset);
       }
  
       /**
        * Get Char-set value
        *
        * @return the charset value. Return 0 if charset was not set.
        */
       public int getCharset() {
           Integer charset = (Integer) mPartHeader.get(P_CHARSET);
           if(charset == null) {
               return 0;
           } else {
               return charset.intValue();
           }
       }
  
       /**
        * Set Content-Location value.
        *
        * @param contentLocation the value
        * @throws NullPointerException if the value is null.
        */
       public void setContentLocation(byte[] contentLocation) {
           if(contentLocation == null) {
               throw new NullPointerException("null content-location");
           }
  
           mPartHeader.put(P_CONTENT_LOCATION, contentLocation);
       }
  
       /**
        * Get Content-Location value.
        *
        * @return the value
        *     return PduPart.disposition[0] instead of <Octet 128> (Form-data).
        *     return PduPart.disposition[1] instead of <Octet 129> (Attachment).
        *     return PduPart.disposition[2] instead of <Octet 130> (Inline).
        */
       public byte[] getContentLocation() {
           return (byte[]) mPartHeader.get(P_CONTENT_LOCATION);
       }
  
       /**
        * Set Content-Disposition value.
        * Use PduPart.disposition[0] instead of <Octet 128> (Form-data).
        * Use PduPart.disposition[1] instead of <Octet 129> (Attachment).
        * Use PduPart.disposition[2] instead of <Octet 130> (Inline).
        *
        * @param contentDisposition the value
        * @throws NullPointerException if the value is null.
        */
       public void setContentDisposition(byte[] contentDisposition) {
           if(contentDisposition == null) {
               throw new NullPointerException("null content-disposition");
           }
  
           mPartHeader.put(P_CONTENT_DISPOSITION, contentDisposition);
       }
  
       /**
        * Get Content-Disposition value.
        *
        * @return the value
        */
       public byte[] getContentDisposition() {
           return (byte[]) mPartHeader.get(P_CONTENT_DISPOSITION);
       }
  
       /**
        *  Set Content-Type value.
        *
        *  @throws NullPointerException if the value is null.
        */
       public void setContentType(byte[] contentType) {
           if(contentType == null) {
               throw new NullPointerException("null content-type");
           }
  
           mPartHeader.put(P_CONTENT_TYPE, contentType);
       }
  
       /**
        * Get Content-Type value of part.
        *
        * @return the value
        */
       public byte[] getContentType() {
           return (byte[]) mPartHeader.get(P_CONTENT_TYPE);
       }
  
       /**
        * Set Content-Transfer-Encoding value
        *
        * @throws NullPointerException if the value is null.
        */
       public void setContentTransferEncoding(byte[] contentTransferEncoding) {
           if(contentTransferEncoding == null) {
               throw new NullPointerException("null content-transfer-encoding");
           }
  
           mPartHeader.put(P_CONTENT_TRANSFER_ENCODING, contentTransferEncoding);
       }
  
       /**
        * Get Content-Transfer-Encoding value.
        *
        * @return the value
        */
       public byte[] getContentTransferEncoding() {
           return (byte[]) mPartHeader.get(P_CONTENT_TRANSFER_ENCODING);
       }
  
       /**
        * Set Content-type parameter: name.
        *
        * @param name the name value
        * @throws NullPointerException if the value is null.
        */
       public void setName(byte[] name) {
           if(null == name) {
               throw new NullPointerException("null content-id");
           }
  
           mPartHeader.put(P_NAME, name);
       }
  
       /**
        *  Get content-type parameter: name.
        *
        *  @return the name
        */
       public byte[] getName() {
           return (byte[]) mPartHeader.get(P_NAME);
       }
  
       /**
        * Get Content-disposition parameter: filename
        *
        * @param fileName the filename value
        * @throws NullPointerException if the value is null.
        */
       public void setFilename(byte[] fileName) {
           if(null == fileName) {
               throw new NullPointerException("null content-id");
           }
  
           mPartHeader.put(P_FILENAME, fileName);
       }
  
       /**
        * Set Content-disposition parameter: filename
        *
        * @return the filename
        */
       public byte[] getFilename() {
           return (byte[]) mPartHeader.get(P_FILENAME);
       }
  
      public String generateLocation() {
          // Assumption: At least one of the content-location / name / filename
          // or content-id should be set. This is guaranteed by the PduParser
          // for incoming messages and by MM composer for outgoing messages.
          byte[] location = (byte[]) mPartHeader.get(P_NAME);
          if(null == location) {
              location = (byte[]) mPartHeader.get(P_FILENAME);
  
              if (null == location) {
                  location = (byte[]) mPartHeader.get(P_CONTENT_LOCATION);
              }
          }
  
          if (null == location) {
              byte[] contentId = (byte[]) mPartHeader.get(P_CONTENT_ID);
              return "cid:" + new String(contentId);
          } else {
              return new String(location);
          }
      }
  }
  
  