Skip to main content

This CGIT instance is deprecated, and repositories have been moved to Gitlab or Github. See the repository descriptions for specific locations.

summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'bundles/org.eclipse.wst.wsi/src/org/eclipse/wst/wsi/internal/core/profile/validator/impl/message/AP1935.java')
-rw-r--r--bundles/org.eclipse.wst.wsi/src/org/eclipse/wst/wsi/internal/core/profile/validator/impl/message/AP1935.java348
1 files changed, 348 insertions, 0 deletions
diff --git a/bundles/org.eclipse.wst.wsi/src/org/eclipse/wst/wsi/internal/core/profile/validator/impl/message/AP1935.java b/bundles/org.eclipse.wst.wsi/src/org/eclipse/wst/wsi/internal/core/profile/validator/impl/message/AP1935.java
new file mode 100644
index 000000000..4d8fce7fc
--- /dev/null
+++ b/bundles/org.eclipse.wst.wsi/src/org/eclipse/wst/wsi/internal/core/profile/validator/impl/message/AP1935.java
@@ -0,0 +1,348 @@
+/*******************************************************************************
+ * 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)));
+ }
+} \ No newline at end of file

Back to the top