Package org.eclipse.wst.wsi.internal.core.profile.validator.impl.message

Source Code of org.eclipse.wst.wsi.internal.core.profile.validator.impl.message.AP1935

/*******************************************************************************
* 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 = 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)));
  }
}
TOP

Related Classes of org.eclipse.wst.wsi.internal.core.profile.validator.impl.message.AP1935

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.