Search in sources :

Example 1 with IMimeType

use of com.helger.commons.mime.IMimeType in project ph-css by phax.

the class CSSDataURLHelper method parseDataURL.

/**
 * Parse a data URL into this type.
 *
 * <pre>
 * Syntax
 *   dataurl    := "data:" [ mediatype ] [ ";base64" ] "," data
 *   mediatype  := [ type "/" subtype ] *( ";" parameter )
 *   data       := *urlchar
 *   parameter  := attribute "=" value
 * </pre>
 *
 * @param sDataURL
 *        The data URL to be parsed. May be <code>null</code>.
 * @return <code>null</code> if parsing failed
 */
@Nullable
public static CSSDataURL parseDataURL(@Nullable final String sDataURL) {
    if (!isDataURL(sDataURL))
        return null;
    // Skip the constant prefix
    final String sRest = sDataURL.trim().substring(PREFIX_DATA_URL.length());
    if (StringHelper.hasNoText(sRest)) {
        // Plain "data:" URL - no content
        return new CSSDataURL();
    }
    // comma is a special character and must be quoted in MIME type parameters
    final int nIndexComma = sRest.indexOf(SEPARATOR_CONTENT);
    int nIndexBase64 = sRest.indexOf(BASE64_MARKER);
    boolean bBase64EncodingUsed = false;
    int nMIMETypeEnd;
    if (nIndexBase64 >= 0) {
        // We have Base64
        if (nIndexBase64 < nIndexComma || nIndexComma < 0) {
            // the comma).
            while (true) {
                final int nIndexEquals = sRest.indexOf(CMimeType.SEPARATOR_PARAMETER_NAME_VALUE, nIndexBase64);
                if (nIndexEquals < 0 || nIndexEquals > nIndexComma || nIndexComma < 0) {
                    // It's a real base64 indicator
                    nMIMETypeEnd = nIndexBase64;
                    bBase64EncodingUsed = true;
                    break;
                }
                // base64 as a MIME type parameter - check for next ;base64
                nIndexBase64 = sRest.indexOf(BASE64_MARKER, nIndexBase64 + BASE64_MARKER.length());
                if (nIndexBase64 < 0) {
                    // Found no base64 encoding
                    nMIMETypeEnd = nIndexComma;
                    break;
                }
            // Found another base64 marker -> continue
            }
        } else {
            // Base64 as part of data!
            nMIMETypeEnd = nIndexComma;
        }
    } else {
        // No Base64 found
        nMIMETypeEnd = nIndexComma;
    }
    String sMimeType = nMIMETypeEnd < 0 ? null : sRest.substring(0, nMIMETypeEnd).trim();
    IMimeType aMimeType;
    Charset aCharset = null;
    if (StringHelper.hasNoText(sMimeType)) {
        // If no MIME type is specified, the default is used
        aMimeType = DEFAULT_MIME_TYPE.getClone();
        aCharset = DEFAULT_CHARSET;
    } else {
        // A MIME type is present
        if (sMimeType.charAt(0) == CMimeType.SEPARATOR_PARAMETER) {
            // Weird stuff from the specs: if only ";charset=utf-8" is present than
            // text/plain should be used
            sMimeType = DEFAULT_MIME_TYPE.getAsStringWithoutParameters() + sMimeType;
        }
        // try to parse it
        aMimeType = MimeTypeParser.safeParseMimeType(sMimeType, EMimeQuoting.URL_ESCAPE);
        if (aMimeType == null) {
            LOGGER.warn("Data URL contains invalid MIME type: '" + sMimeType + "'");
            return null;
        }
        // Check if a "charset" MIME type parameter is present
        final String sCharsetParam = MimeTypeHelper.getCharsetNameFromMimeType(aMimeType);
        if (sCharsetParam != null) {
            aCharset = CharsetHelper.getCharsetFromNameOrNull(sCharsetParam);
            if (aCharset == null) {
                LOGGER.warn("Illegal charset '" + sCharsetParam + "' contained. Defaulting to '" + DEFAULT_CHARSET.name() + "'");
            }
        }
        if (aCharset == null)
            aCharset = DEFAULT_CHARSET;
    }
    // Get the main content data
    String sContent = nIndexComma < 0 ? "" : sRest.substring(nIndexComma + 1).trim();
    byte[] aContent = sContent.getBytes(aCharset);
    if (bBase64EncodingUsed) {
        // Base64 decode the content data
        aContent = Base64.safeDecode(aContent);
        if (aContent == null) {
            LOGGER.warn("Failed to decode Base64 value: " + sContent);
            return null;
        }
        // Ignore the String content (and don't create it) because for binary
        // stuff like images, it does not make sense and it is most likely, that
        // the String content will never be used. In case it is required, the
        // String content is lazily initialized.
        sContent = null;
    }
    return new CSSDataURL(aMimeType, bBase64EncodingUsed, aContent, aCharset, sContent);
}
Also used : IMimeType(com.helger.commons.mime.IMimeType) Charset(java.nio.charset.Charset) Nullable(javax.annotation.Nullable)

Example 2 with IMimeType

use of com.helger.commons.mime.IMimeType in project phase4 by phax.

the class AS4IncomingHandler method parseAS4Message.

public static void parseAS4Message(@Nonnull final IAS4IncomingAttachmentFactory aIAF, @Nonnull @WillNotClose final AS4ResourceHelper aResHelper, @Nonnull final IAS4IncomingMessageMetadata aMessageMetadata, @Nonnull @WillClose final InputStream aPayloadIS, @Nonnull final HttpHeaderMap aHttpHeaders, @Nonnull final IAS4ParsedMessageCallback aCallback, @Nullable final IAS4IncomingDumper aIncomingDumper) throws Phase4Exception, IOException, MessagingException, WSSecurityException {
    // Determine content type
    final String sContentType = aHttpHeaders.getFirstHeaderValue(CHttpHeader.CONTENT_TYPE);
    if (StringHelper.hasNoText(sContentType))
        throw new Phase4Exception("Content-Type header is missing");
    if (LOGGER.isDebugEnabled())
        LOGGER.debug("Received Content-Type string: '" + sContentType + "'");
    final IMimeType aContentType = MimeTypeParser.safeParseMimeType(sContentType);
    if (LOGGER.isDebugEnabled())
        LOGGER.debug("Received Content-Type object: " + aContentType);
    if (aContentType == null)
        throw new Phase4Exception("Failed to parse Content-Type '" + sContentType + "'");
    final IMimeType aPlainContentType = aContentType.getCopyWithoutParameters();
    // Fallback to global dumper if none is provided
    final IAS4IncomingDumper aRealIncomingDumper = aIncomingDumper != null ? aIncomingDumper : AS4DumpManager.getIncomingDumper();
    Document aSoapDocument = null;
    ESoapVersion eSoapVersion = null;
    final ICommonsList<WSS4JAttachment> aIncomingAttachments = new CommonsArrayList<>();
    final Wrapper<OutputStream> aDumpOSHolder = new Wrapper<>();
    if (aPlainContentType.equals(AS4RequestHandler.MT_MULTIPART_RELATED)) {
        // MIME message
        if (LOGGER.isDebugEnabled())
            LOGGER.debug("Received MIME message");
        final String sBoundary = aContentType.getParameterValueWithName("boundary");
        if (StringHelper.hasNoText(sBoundary))
            throw new Phase4Exception("Content-Type '" + sContentType + "' misses 'boundary' parameter");
        if (LOGGER.isDebugEnabled())
            LOGGER.debug("MIME Boundary: '" + sBoundary + "'");
        // Ensure the stream gets closed correctly
        try (final InputStream aRequestIS = AS4DumpManager.getIncomingDumpAwareInputStream(aRealIncomingDumper, aPayloadIS, aMessageMetadata, aHttpHeaders, aDumpOSHolder)) {
            // PARSING MIME Message via MultipartStream
            final MultipartStream aMulti = new MultipartStream(aRequestIS, sBoundary.getBytes(StandardCharsets.ISO_8859_1), (MultipartProgressNotifier) null);
            int nIndex = 0;
            while (true) {
                final boolean bHasNextPart = nIndex == 0 ? aMulti.skipPreamble() : aMulti.readBoundary();
                if (!bHasNextPart)
                    break;
                if (LOGGER.isDebugEnabled())
                    LOGGER.debug("Found MIME part #" + nIndex);
                try (final MultipartItemInputStream aBodyPartIS = aMulti.createInputStream()) {
                    // Read headers AND content
                    final MimeBodyPart aBodyPart = new MimeBodyPart(aBodyPartIS);
                    if (nIndex == 0) {
                        // First MIME part -> SOAP document
                        if (LOGGER.isDebugEnabled())
                            LOGGER.debug("Parsing first MIME part as SOAP document");
                        // Read SOAP document
                        aSoapDocument = DOMReader.readXMLDOM(aBodyPart.getInputStream());
                        IMimeType aPlainPartMT = MimeTypeParser.safeParseMimeType(aBodyPart.getContentType());
                        if (aPlainPartMT != null)
                            aPlainPartMT = aPlainPartMT.getCopyWithoutParameters();
                        // Determine SOAP version from MIME part content type
                        eSoapVersion = ESoapVersion.getFromMimeTypeOrNull(aPlainPartMT);
                        if (eSoapVersion != null && LOGGER.isDebugEnabled())
                            LOGGER.debug("Determined SOAP version " + eSoapVersion + " from Content-Type");
                        if (eSoapVersion == null && aSoapDocument != null) {
                            // Determine SOAP version from the read document
                            eSoapVersion = ESoapVersion.getFromNamespaceURIOrNull(XMLHelper.getNamespaceURI(aSoapDocument));
                            if (eSoapVersion != null && LOGGER.isDebugEnabled())
                                LOGGER.debug("Determined SOAP version " + eSoapVersion + " from XML root element namespace URI");
                        }
                    } else {
                        // MIME Attachment (index is gt 0)
                        if (LOGGER.isDebugEnabled())
                            LOGGER.debug("Parsing MIME part #" + nIndex + " as attachment");
                        final WSS4JAttachment aAttachment = aIAF.createAttachment(aBodyPart, aResHelper);
                        aIncomingAttachments.add(aAttachment);
                    }
                }
                nIndex++;
            }
        }
        if (LOGGER.isDebugEnabled())
            LOGGER.debug("Read MIME message with " + aIncomingAttachments.size() + " attachment(s)");
    } else {
        if (LOGGER.isDebugEnabled())
            LOGGER.debug("Received plain message");
        // Expect plain SOAP - read whole request to DOM
        // Note: this may require a huge amount of memory for large requests
        aSoapDocument = DOMReader.readXMLDOM(AS4DumpManager.getIncomingDumpAwareInputStream(aRealIncomingDumper, aPayloadIS, aMessageMetadata, aHttpHeaders, aDumpOSHolder));
        if (LOGGER.isDebugEnabled())
            if (aSoapDocument != null)
                LOGGER.debug("Successfully parsed payload as XML");
            else
                LOGGER.debug("Failed to parse payload as XML");
        if (aSoapDocument != null) {
            // Determine SOAP version from the read document
            eSoapVersion = ESoapVersion.getFromNamespaceURIOrNull(XMLHelper.getNamespaceURI(aSoapDocument));
            if (eSoapVersion != null && LOGGER.isDebugEnabled())
                LOGGER.debug("Determined SOAP version " + eSoapVersion + " from XML root element namespace URI");
        }
        if (eSoapVersion == null) {
            // Determine SOAP version from content type
            eSoapVersion = ESoapVersion.getFromMimeTypeOrNull(aPlainContentType);
            if (eSoapVersion != null && LOGGER.isDebugEnabled())
                LOGGER.debug("Determined SOAP version " + eSoapVersion + " from Content-Type");
        }
    }
    try {
        if (aSoapDocument == null) {
            // We don't have a SOAP document
            throw new Phase4Exception(eSoapVersion == null ? "Failed to parse incoming message!" : "Failed to parse incoming SOAP " + eSoapVersion.getVersion() + " document!");
        }
        if (eSoapVersion == null) {
            // We're missing a SOAP version
            throw new Phase4Exception("Failed to determine SOAP version of XML document!");
        }
        aCallback.handle(aHttpHeaders, aSoapDocument, eSoapVersion, aIncomingAttachments);
    } finally {
        // Here, the incoming dump is finally ready closed and usable
        if (aRealIncomingDumper != null && aDumpOSHolder.isSet())
            try {
                aRealIncomingDumper.onEndRequest(aMessageMetadata);
            } catch (final Exception ex) {
                LOGGER.error("IncomingDumper.onEndRequest failed. Dumper=" + aRealIncomingDumper + "; MessageMetadata=" + aMessageMetadata, ex);
            }
    }
}
Also used : Wrapper(com.helger.commons.wrapper.Wrapper) IAS4IncomingDumper(com.helger.phase4.dump.IAS4IncomingDumper) MultipartItemInputStream(com.helger.web.multipart.MultipartStream.MultipartItemInputStream) NonBlockingByteArrayInputStream(com.helger.commons.io.stream.NonBlockingByteArrayInputStream) HasInputStream(com.helger.commons.io.stream.HasInputStream) IHasInputStream(com.helger.commons.io.IHasInputStream) InputStream(java.io.InputStream) OutputStream(java.io.OutputStream) Document(org.w3c.dom.Document) AS4DecompressException(com.helger.phase4.attachment.AS4DecompressException) MessagingException(javax.mail.MessagingException) WSSecurityException(org.apache.wss4j.common.ext.WSSecurityException) Phase4Exception(com.helger.phase4.util.Phase4Exception) IOException(java.io.IOException) Phase4Exception(com.helger.phase4.util.Phase4Exception) IMimeType(com.helger.commons.mime.IMimeType) MultipartItemInputStream(com.helger.web.multipart.MultipartStream.MultipartItemInputStream) ESoapVersion(com.helger.phase4.soap.ESoapVersion) MimeBodyPart(javax.mail.internet.MimeBodyPart) MultipartStream(com.helger.web.multipart.MultipartStream) CommonsArrayList(com.helger.commons.collection.impl.CommonsArrayList) WSS4JAttachment(com.helger.phase4.attachment.WSS4JAttachment)

Example 3 with IMimeType

use of com.helger.commons.mime.IMimeType in project ph-web by phax.

the class UnifiedResponse method setMimeTypeString.

@Nonnull
public final UnifiedResponse setMimeTypeString(@Nonnull @Nonempty final String sMimeType) {
    ValueEnforcer.notEmpty(sMimeType, "MimeType");
    final IMimeType aMimeType = MimeTypeParser.safeParseMimeType(sMimeType);
    if (aMimeType != null)
        setMimeType(aMimeType);
    else
        logError("Failed to resolve mime type from '" + sMimeType + "'");
    return this;
}
Also used : IMimeType(com.helger.commons.mime.IMimeType) Nonnull(javax.annotation.Nonnull)

Example 4 with IMimeType

use of com.helger.commons.mime.IMimeType in project ph-web by phax.

the class MockHttpServletResponse method setContentType.

public void setContentType(@Nullable final String sContentType) {
    m_sContentType = sContentType;
    if (sContentType != null) {
        try {
            final IMimeType aContentType = MimeTypeParser.parseMimeType(sContentType);
            final String sEncoding = MimeTypeHelper.getCharsetNameFromMimeType(aContentType);
            if (sEncoding != null)
                setCharacterEncoding(sEncoding);
        } catch (final MimeTypeParserException ex) {
            LOGGER.warn("Passed content type '" + sContentType + "' cannot be parsed as a MIME type");
        }
    }
}
Also used : IMimeType(com.helger.commons.mime.IMimeType) MimeTypeParserException(com.helger.commons.mime.MimeTypeParserException)

Example 5 with IMimeType

use of com.helger.commons.mime.IMimeType in project ph-web by phax.

the class AcceptMimeTypeHandler method getAcceptMimeTypes.

@Nonnull
public static AcceptMimeTypeList getAcceptMimeTypes(@Nullable final String sAcceptMimeTypes) {
    final AcceptMimeTypeList ret = new AcceptMimeTypeList();
    if (StringHelper.hasNoText(sAcceptMimeTypes)) {
        // No definition - access all
        ret.addMimeType(ANY_MIMETYPE, QValue.MAX_QUALITY);
    } else {
        // MIME types are separated by "," or ", "
        for (final String sItem : StringHelper.getExploded(',', sAcceptMimeTypes)) {
            // Qualities are separated by ";"
            final String[] aParts = StringHelper.getExplodedArray(';', sItem.trim(), 2);
            // Default quality is 1
            double dQuality = QValue.MAX_QUALITY;
            if (aParts.length == 2 && aParts[1].trim().startsWith("q="))
                dQuality = StringParser.parseDouble(aParts[1].trim().substring(2), QValue.MAX_QUALITY);
            final String sMimeType = aParts[0];
            IMimeType aMimeType = MimeTypeParser.safeParseMimeType(sMimeType);
            if (aMimeType != null) {
                if (aMimeType.hasAnyParameters()) {
                    if (LOGGER.isWarnEnabled())
                        LOGGER.warn("Ignoring all contained MIME type parameter from '" + sMimeType + "'!");
                    aMimeType = aMimeType.getCopyWithoutParameters();
                }
                ret.addMimeType(aMimeType, dQuality);
            } else if ("*".equals(sMimeType))
                ret.addMimeType(ANY_MIMETYPE, dQuality);
            else {
                // ignored
                if (!"xml/xml".equals(sMimeType)) {
                    if (LOGGER.isWarnEnabled())
                        LOGGER.warn("Failed to parse Mime type '" + sMimeType + "' as part of '" + sAcceptMimeTypes + "'!");
                }
            }
        }
    }
    return ret;
}
Also used : IMimeType(com.helger.commons.mime.IMimeType) Nonnull(javax.annotation.Nonnull)

Aggregations

IMimeType (com.helger.commons.mime.IMimeType)11 Nonnull (javax.annotation.Nonnull)5 MimeTypeParserException (com.helger.commons.mime.MimeTypeParserException)3 Charset (java.nio.charset.Charset)3 ICommonsList (com.helger.commons.collection.impl.ICommonsList)2 HttpHeaderMap (com.helger.commons.http.HttpHeaderMap)2 IHasInputStream (com.helger.commons.io.IHasInputStream)2 NonBlockingByteArrayInputStream (com.helger.commons.io.stream.NonBlockingByteArrayInputStream)2 EMandatory (com.helger.commons.state.EMandatory)2 Phase4Exception (com.helger.phase4.util.Phase4Exception)2 IOException (java.io.IOException)2 Nullable (javax.annotation.Nullable)2 MessagingException (javax.mail.MessagingException)2 WSSecurityException (org.apache.wss4j.common.ext.WSSecurityException)2 CommonsArrayList (com.helger.commons.collection.impl.CommonsArrayList)1 CommonsLinkedHashMap (com.helger.commons.collection.impl.CommonsLinkedHashMap)1 ICommonsMap (com.helger.commons.collection.impl.ICommonsMap)1 ICommonsOrderedMap (com.helger.commons.collection.impl.ICommonsOrderedMap)1 HasInputStream (com.helger.commons.io.stream.HasInputStream)1 Wrapper (com.helger.commons.wrapper.Wrapper)1