/*******************************************************************************
 * Copyright (c) 2002-2005 IBM Corporation and others.
 * All rights reserved.   This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *   IBM - Initial API and implementation
 *******************************************************************************/
package org.eclipse.wst.wsi.internal.core.profile.validator.impl.message;

import java.util.ArrayList;
import java.util.Iterator;

import org.eclipse.wst.wsi.internal.core.WSIException;
import org.eclipse.wst.wsi.internal.core.analyzer.AssertionFailException;
import org.eclipse.wst.wsi.internal.core.log.MimePart;
import org.eclipse.wst.wsi.internal.core.log.MimeParts;
import org.eclipse.wst.wsi.internal.core.profile.TestAssertion;
import org.eclipse.wst.wsi.internal.core.profile.validator.EntryContext;
import org.eclipse.wst.wsi.internal.core.profile.validator.impl.AssertionProcess;
import org.eclipse.wst.wsi.internal.core.profile.validator.impl.BaseMessageValidator;
import org.eclipse.wst.wsi.internal.core.report.AssertionResult;
import org.eclipse.wst.wsi.internal.core.util.HTTPConstants;
import org.eclipse.wst.wsi.internal.core.util.HTTPUtils;
import org.eclipse.wst.wsi.internal.core.util.Utils;

/**
 * AP1935
 *
 * <context>For a candidate part of a multipart/related message</context>
 * <assertionDescription>The encoding of the body of a part in a
 * multipart/related message conforms to the encoding indicated by the
 * Content-Transfer-Encoding field-value,
 * as specified by RFC2045.</assertionDescription>
 */
public class AP1935 extends AssertionProcess
{
  private final BaseMessageValidator validator;

  /**
   * @param WSDLValidatorImpl
   */
  public AP1935(BaseMessageValidator impl)
  {
    super(impl);
    this.validator = impl;
  }

  /* Validates the test assertion.
  * @see org.wsi.test.profile.validator.impl.BaseValidatorImpl.AssertionProcess#validate(org.wsi.test.profile.TestAssertion, org.wsi.test.profile.validator.EntryContext)
  */
  public AssertionResult validate(
    TestAssertion testAssertion,
    EntryContext entryContext)
    throws WSIException
  {
    if(!entryContext.getMessageEntry().isMimeContent())
    {
      result = AssertionResult.RESULT_NOT_APPLICABLE;
    } 
    else 
    {
      // get MIME parts
      MimeParts parts = entryContext.getMessageEntry().getMimeParts();
      if(parts.count() == 0)
      {
        result = AssertionResult.RESULT_NOT_APPLICABLE;
      }
      else
      {
        // check each part for the encoding match
      	Iterator iparts = parts.getParts().iterator();
      	int i = 0;
      	MimePart root = parts.getRootPart();
        while (iparts.hasNext())
        {
          i = i = 1;
          try
          {
        	MimePart part = (MimePart)iparts.next();
        	
            // get encoding from header
            String encoding =  HTTPUtils.getHttpHeaderAttribute(part.getHeaders(), 
            	HTTPConstants.HEADER_CONTENT_TRANSFER_ENCODING);
          
           	if ((part == root) || 
           		((encoding != null) && encoding.equalsIgnoreCase("base64")))
              checkPart(part, encoding, false);
          	else 
          	  checkPart(part, encoding, true);
          } catch (AssertionFailException e)
          {
            result = AssertionResult.RESULT_FAILED;
            failureDetail = validator.createFailureDetail(
                "part "+(i+1)+" Error: " + e.getMessage(), entryContext);
          }
        }
      }
    }
    // Return assertion result
    return validator.createAssertionResult(
      testAssertion, result, failureDetail);
  }
  /**
   * Check message entry to encoding conformity 
   * @param entry message entry
   * @throws AssertionFailException if message does not encoding conformity  
   * @throws WSIException 
   */
  private void checkPart(MimePart part, String  encoding, boolean encoded) 
    throws AssertionFailException, WSIException
  {
    String content = null;
    if (encoded)
       content = new String(Utils.decodeBase64(part.getContent()));
     else
    	content = part.getContent();
    
    if(encoding == null) 
    {
      result = AssertionResult.RESULT_NOT_APPLICABLE;
    // check 7bit
    } else if(encoding.equalsIgnoreCase("7bit")) {
      checkOn7bit(content);
    // check 8bit
    } else if(encoding.equalsIgnoreCase("8bit")) {
      checkOn8bit(content);
    // check quoted-printable
    } else if(encoding.equalsIgnoreCase("quoted-printable")) {
      checkOnQuotedPrintable(content);
    // check base64
    } else if(encoding.equalsIgnoreCase("base64")) {
      checkOnBase64(content);
    }
    // we dont check binary encoding, since message can contains any chars 
  }

  /**
   * Validate a 7bit encoded message (RFC2045)
   * @param message message to check
   * @throws AssertionFailException if message does not conform
   */
  private void checkOn7bit(String message) 
    throws AssertionFailException
  {
    String[] strs = split(message);
    for (int i = 0; i < strs.length; i++)
    {
      String str = strs[i];
      
      // check string length
      if(str.length() > 998) 
      {
        throw new AssertionFailException("The length (" + str.length() + 
            ") of the line (" + (i+1) + ") greater than 998");
      }
      // No octets with decimal values greater than 127
      // are allowed and neither are NULs (octets with decimal value 0).  CR
      //(decimal value 13) and LF (decimal value 10) octets only occur as
      // part of CRLF line separation sequences.
      char[] chars = str.toCharArray();
      for (int j = 0; j < chars.length; j++)
      {
        if((chars[j] > 127) || (chars[j] == 0) || 
            (chars[j] == 10) || (chars[j] == 13))
        {
          throw new AssertionFailException("The char (" + chars[j] + 
              ")[code=" + (byte) chars[j] + " position=" + j + 
              "] does not allows in 7bit encoding content");
        }
      }
    }
  }

  /**
   * Validate an 8bit encoded message (RFC2045)
   * @param message message to check
   * @throws AssertionFailException if message does not conform
   */
  private void checkOn8bit(String message) 
    throws AssertionFailException
  {
    String[] strs = split(message);
    for (int i = 0; i < strs.length; i++)
    {
      String str = strs[i];
      
      // check string length
      if(str.length() > 998) 
      {
        throw new AssertionFailException("The length (" + str.length() + 
            ") of the line (" + (i+1) + ") greater than 998");
      }
      // octets with decimal values greater than 127
      // may be used.  As with "7bit data" CR and LF octets only occur as part
      // of CRLF line separation sequences and no NULs are allowed. 
      char[] chars = str.toCharArray();
      for (int j = 0; j < chars.length; j++)
      {
        if((chars[j] == 0) || (chars[j] == 10) || (chars[j] == 13))
        {
          throw new AssertionFailException("The char (" + chars[j] + 
              ")[code=" + (byte) chars[j] + " position=" + j + 
              "] does not allows in 8bit encoding content");
        }
      }
    }
  }

  /**
   * Validate a quoted-printable encoded message (RFC2045)
   * @param message message to check
   * @throws AssertionFailException if message does not conform
   */
  private void checkOnQuotedPrintable(String message)
    throws AssertionFailException
  {
    String[] strs = split(message);
    for (int i = 0; i < strs.length; i++)
    {
      // check length
      // RFC2045
      // (5)   (Soft Line Breaks) The Quoted-Printable encoding
      //REQUIRES that encoded lines be no more than 76
      //characters long.  If longer lines are to be encoded
      //with the Quoted-Printable encoding, "soft" line breaks
      //must be used.  An equal sign as the last character on a
      //encoded line indicates such a non-significant ("soft")
      //line break in the encoded text.
      if(((strs[i].indexOf("\t") != -1) || (strs[i].indexOf(" ") != -1)) &&
          (strs[i].length() > 76))
      {
        throw new AssertionFailException("The length (" + strs[i].length() + 
            ") of the line (" + (i+1) + 
            ") greater than 76, \"soft\" line breaks must be used");
      }

      char[] chars = strs[i].toCharArray();
      for (int j = 0; j < chars.length; j++)
      {
        //(1)   (General 8bit representation) Any octet, except a CR or
        //LF that is part of a CRLF line break of the canonical
        //(standard) form of the data being encoded, may be
        //represented by an "=" followed by a two digit
        //hexadecimal representation of the octet's value.  The
        //digits of the hexadecimal alphabet, for this purpose,
        //are "0123456789ABCDEF".  Uppercase letters must be
        //used; lowercase letters are not allowed.  Thus, for
        //example, the decimal value 12 (US-ASCII form feed) can
        //be represented by "=0C", and the decimal value 61 (US-
        //ASCII EQUAL SIGN) can be represented by "=3D".  This
        //rule must be followed except when the following rules
        //allow an alternative encoding.
        // (2)   (Literal representation) Octets with decimal values of
        //33 through 60 inclusive, and 62 through 126, inclusive,
        //MAY be represented as the US-ASCII characters which
        //correspond to those octets (EXCLAMATION POINT through
        //LESS THAN, and GREATER THAN through TILDE,
        //respectively).
        if((chars[j] == 61) && (chars.length > j+2)) 
        {
          if(!isHex(chars[j+1]) || !isHex(chars[j+2]))
          {
            throw new AssertionFailException("the quoted char (" + 
                 chars[j] + chars[j+1] + chars[j+2] + ") is incorrect");
          } else {
            j += 2;
          }
        } 
        // check for space and tab
        else if((chars[j] != 9) && (chars[j] != 32))
        {
          // check invalid symbol
          if((chars[j] == 0) || (chars[j] == 10) || (chars[j] == 13) ||
             (chars[j] < 33) || (chars[j] > 126) || (chars[j] == 61))
          {
            throw new AssertionFailException("The char (" + chars[j] + 
                ")[code=" + (byte) chars[j] + " position=" + j + 
                "] must be quoted");
          }
        }
      }
    }
  }

  /**
   * Validate a base64 encoded message (RFC3548)
   * @param message message to check
   * @throws AssertionFailException if message does not conform
   */
  private void checkOnBase64(String message)
  throws AssertionFailException
  {
    String[] strs = split(message);
    for (int i = 0; i < strs.length; i++)
    {
      String str = strs[i];
      
      // check string length
      if(str.length() > 76) 
      {
        throw new AssertionFailException("The length (" + str.length() + 
            ") of the line (" + (i+1) + ") greater than 998");
      }
      // check for "ABCDEFGHIJKLMNOPQRSTUVWXYZabcefghijklmnopqrstuvwxyz0123456789/+"
      char[] chars = str.toCharArray();
      for (int j = 0; j < chars.length; j++)
      {
        char c = chars[i];
        if((c < 47) || (c > 122) || ((c > 57) && (c < 65)) || 
           ((c > 90) && (c < 97)))
        {
          throw new AssertionFailException("The char (" + chars[j] + 
              ")[code=" + (byte) chars[j] + " position=" + j + 
              "] does not allows in base64 encoding content");
        }
      }
    }
  }
  
  /**
   * split string to array of strings and use as delimeter CRLF
   * @param str original string
   * @return array of strings
   */
  private String[] split(String str)
  {
    ArrayList list = new ArrayList();
    for(int idx = str.indexOf("\r\n"); idx != -1; idx = str.indexOf("\r\n"))
    {
      list.add(str.substring(0, idx));
      str = str.substring(idx+2);
    }
    list.add(str);
    return (String[]) list.toArray(new String[list.size()]);
  }
  
  /**
   * Returns true if byte is "0123456789ABCDEF" range, false othewise
   * @param c char
   * @return true if byte is "0123456789ABCDEF" range, false othewise
   */
  private boolean isHex(char c) {
    return (((c >= 48) && (c <= 57)) || ((c >= 65) && (c <= 70))); 
  }
}