MailServlet.java 14.2 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  com.day.cq.mailer.MailService
 *  javax.servlet.Servlet
 *  javax.servlet.ServletException
 *  javax.servlet.ServletRequest
 *  javax.servlet.http.HttpServletRequest
 *  org.apache.commons.mail.ByteArrayDataSource
 *  org.apache.commons.mail.Email
 *  org.apache.commons.mail.EmailException
 *  org.apache.commons.mail.MultiPartEmail
 *  org.apache.commons.mail.SimpleEmail
 *  org.apache.felix.scr.annotations.Component
 *  org.apache.felix.scr.annotations.Properties
 *  org.apache.felix.scr.annotations.Property
 *  org.apache.felix.scr.annotations.Reference
 *  org.apache.felix.scr.annotations.ReferenceCardinality
 *  org.apache.felix.scr.annotations.ReferencePolicy
 *  org.apache.felix.scr.annotations.Service
 *  org.apache.sling.api.SlingHttpServletRequest
 *  org.apache.sling.api.SlingHttpServletResponse
 *  org.apache.sling.api.request.RequestParameter
 *  org.apache.sling.api.request.RequestPathInfo
 *  org.apache.sling.api.resource.Resource
 *  org.apache.sling.api.resource.ResourceUtil
 *  org.apache.sling.api.resource.ValueMap
 *  org.apache.sling.api.servlets.OptingServlet
 *  org.apache.sling.api.servlets.SlingAllMethodsServlet
 *  org.apache.sling.auth.core.AuthUtil
 *  org.apache.sling.commons.osgi.OsgiUtil
 *  org.osgi.service.component.ComponentContext
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.day.cq.wcm.foundation.forms.impl;

import com.day.cq.mailer.MailService;
import com.day.cq.wcm.foundation.forms.FieldDescription;
import com.day.cq.wcm.foundation.forms.FieldHelper;
import com.day.cq.wcm.foundation.forms.FormsHelper;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Dictionary;
import java.util.Iterator;
import java.util.Locale;
import java.util.ResourceBundle;
import javax.activation.DataSource;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.mail.ByteArrayDataSource;
import org.apache.commons.mail.Email;
import org.apache.commons.mail.EmailException;
import org.apache.commons.mail.MultiPartEmail;
import org.apache.commons.mail.SimpleEmail;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.ReferencePolicy;
import org.apache.felix.scr.annotations.Service;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.request.RequestParameter;
import org.apache.sling.api.request.RequestPathInfo;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceUtil;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.api.servlets.OptingServlet;
import org.apache.sling.api.servlets.SlingAllMethodsServlet;
import org.apache.sling.auth.core.AuthUtil;
import org.apache.sling.commons.osgi.OsgiUtil;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Component(metatype=1, label="Adobe CQ Form Mail Servlet", description="Accepts posting to a form start component and performs validations")
@Service(value={Servlet.class})
@Properties(value={@Property(name="sling.servlet.resourceTypes", value={"foundation/components/form/start"}, propertyPrivate=1), @Property(name="sling.servlet.methods", value={"POST"}, propertyPrivate=1), @Property(name="sling.servlet.selectors", value={"mail"}, propertyPrivate=1), @Property(name="service.description", value={"Form Mail Servlet"})})
public class MailServlet
extends SlingAllMethodsServlet
implements OptingServlet {
    protected static final String EXTENSION = "html";
    protected static final String MAILTO_PROPERTY = "mailto";
    protected static final String CC_PROPERTY = "cc";
    protected static final String BCC_PROPERTY = "bcc";
    protected static final String SUBJECT_PROPERTY = "subject";
    protected static final String FROM_PROPERTY = "from";
    protected final Logger logger;
    @Reference(policy=ReferencePolicy.DYNAMIC, cardinality=ReferenceCardinality.OPTIONAL_UNARY)
    protected volatile MailService mailService;
    @Property(value={"/content", "/home"}, label="Resource Whitelist", description="List of paths under which servlet will only accept requests.")
    private static final String PROPERTY_RESOURCE_WHITELIST = "resource.whitelist";
    private String[] resourceWhitelist;
    @Property(value={"/content/usergenerated"}, label="Resource Blacklist", description="List of paths under which servlet will reject requests.")
    private static final String PROPERTY_RESOURCE_BLACKLIST = "resource.blacklist";
    private String[] resourceBlacklist;

    public MailServlet() {
        this.logger = LoggerFactory.getLogger(this.getClass());
    }

    protected void activate(ComponentContext componentContext) {
        Dictionary properties = componentContext.getProperties();
        this.resourceWhitelist = OsgiUtil.toStringArray(properties.get("resource.whitelist"));
        this.resourceBlacklist = OsgiUtil.toStringArray(properties.get("resource.blacklist"));
    }

    public boolean accepts(SlingHttpServletRequest request) {
        boolean acceptable = "html".equals(request.getRequestPathInfo().getExtension());
        if (!acceptable) {
            return acceptable;
        }
        Resource resource = request.getResource();
        this.logger.debug("checking for acceptance of resource {} ", (Object)resource.getPath());
        for (String path2 : this.resourceBlacklist) {
            if (!resource.getPath().startsWith(path2)) continue;
            return false;
        }
        for (String path2 : this.resourceWhitelist) {
            if (!resource.getPath().startsWith(path2)) continue;
            return true;
        }
        return false;
    }

    protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }

    protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {
        MailService localService = this.mailService;
        if (!this.accepts(request)) {
            this.logger.debug("Resource not accepted.");
            response.setStatus(500);
            return;
        }
        if (ResourceUtil.isNonExistingResource((Resource)request.getResource())) {
            this.logger.debug("Received fake request!");
            response.setStatus(500);
            return;
        }
        ResourceBundle resBundle = request.getResourceBundle(null);
        ValueMap values = ResourceUtil.getValueMap((Resource)request.getResource());
        String[] mailTo = (String[])values.get("mailto", String[].class);
        int status = 200;
        if (mailTo == null || mailTo.length == 0 || mailTo[0].length() == 0) {
            this.logger.error("The mailto configuration is missing in the form begin at " + request.getResource().getPath());
            status = 500;
        } else if (localService == null) {
            this.logger.error("The mail service is currently not available! Unable to send form mail.");
            status = 500;
        } else {
            try {
                SimpleEmail email;
                String[] bccRecs;
                StringBuilder builder = new StringBuilder();
                builder.append(request.getScheme());
                builder.append("://");
                builder.append(request.getServerName());
                if (request.getServerPort() >= 0 && (request.getScheme().equals("https") && request.getServerPort() != 443 || request.getScheme().equals("http") && request.getServerPort() != 80)) {
                    builder.append(':');
                    builder.append(request.getServerPort());
                }
                builder.append(request.getRequestURI());
                StringBuilder buffer = new StringBuilder();
                String text = resBundle.getString("You've received a new form based mail from {0}.");
                text = text.replace("{0}", builder.toString());
                buffer.append(text);
                buffer.append("\n\n");
                buffer.append(resBundle.getString("Values"));
                buffer.append(":\n\n");
                ArrayList<String> contentNamesList = new ArrayList<String>();
                Iterator<String> names = FormsHelper.getContentRequestParameterNames(request);
                while (names.hasNext()) {
                    String name = names.next();
                    contentNamesList.add(name);
                }
                Collections.sort(contentNamesList);
                ArrayList<String> namesList = new ArrayList<String>();
                Iterator<Resource> fields = FormsHelper.getFormElements(request.getResource());
                while (fields.hasNext()) {
                    FieldDescription[] descs;
                    Resource field = fields.next();
                    for (FieldDescription desc : descs = FieldHelper.getFieldDescriptions(request, field)) {
                        contentNamesList.remove(desc.getName());
                        if (desc.isPrivate()) continue;
                        namesList.add(desc.getName());
                    }
                }
                namesList.addAll(contentNamesList);
                ArrayList<RequestParameter> attachments = new ArrayList<RequestParameter>();
                for (String name : namesList) {
                    RequestParameter rp = request.getRequestParameter(name);
                    if (rp == null) {
                        this.logger.debug("skipping form element {} from mail content because it's not in the request", (Object)name);
                        continue;
                    }
                    if (rp.isFormField()) {
                        String[] pValues;
                        buffer.append(name);
                        buffer.append(" : \n");
                        for (String v : pValues = request.getParameterValues(name)) {
                            buffer.append(v);
                            buffer.append("\n");
                        }
                        buffer.append("\n");
                        continue;
                    }
                    if (rp.getSize() <= 0) continue;
                    attachments.add(rp);
                }
                if (attachments.size() > 0) {
                    buffer.append("\n");
                    buffer.append(resBundle.getString("Attachments"));
                    buffer.append(":\n");
                    MultiPartEmail mpEmail = new MultiPartEmail();
                    email = mpEmail;
                    for (RequestParameter rp : attachments) {
                        ByteArrayDataSource ea = new ByteArrayDataSource(rp.getInputStream(), rp.getContentType());
                        mpEmail.attach((DataSource)ea, rp.getFileName(), rp.getFileName());
                        buffer.append("- ");
                        buffer.append(rp.getFileName());
                        buffer.append("\n");
                    }
                } else {
                    email = new SimpleEmail();
                }
                email.setCharset("utf-8");
                email.setMsg(buffer.toString());
                for (FieldDescription rec : mailTo) {
                    email.addTo((String)((Object)rec));
                }
                String[] ccRecs = (String[])values.get("cc", String[].class);
                if (ccRecs != null) {
                    String[] arr$ = ccRecs;
                    int len$ = arr$.length;
                    boolean i$ = false;
                    while (++i$ < len$) {
                        String rec2 = arr$[i$];
                        email.addCc(rec2);
                    }
                }
                if ((bccRecs = (String[])values.get("bcc", String[].class)) != null) {
                    for (String rec3 : bccRecs) {
                        email.addBcc(rec3);
                    }
                }
                String subject = (String)values.get("subject", (Object)resBundle.getString("Form Mail"));
                email.setSubject(subject);
                String fromAddress = (String)values.get("from", (Object)"");
                if (fromAddress.length() > 0) {
                    email.setFrom(fromAddress);
                }
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Sending form activated mail: fromAddress={}, to={}, subject={}, text={}.", new Object[]{fromAddress, mailTo, subject, buffer});
                }
                localService.sendEmail((Email)email);
            }
            catch (EmailException e) {
                this.logger.error("Error sending email: " + e.getMessage(), (Throwable)e);
                status = 500;
            }
        }
        String redirectTo = request.getParameter(":redirect");
        if (redirectTo != null) {
            if (AuthUtil.isRedirectValid((HttpServletRequest)request, (String)redirectTo) || redirectTo.equals(FormsHelper.getReferrer((HttpServletRequest)request))) {
                int pos;
                redirectTo = redirectTo + ((pos = redirectTo.indexOf(63)) == -1 ? '?' : '&') + "status=" + status;
                response.sendRedirect(redirectTo);
            } else {
                this.logger.error("Invalid redirect specified: {}", new Object[]{redirectTo});
                response.sendError(403);
            }
            return;
        }
        if (FormsHelper.isRedirectToReferrer((ServletRequest)request)) {
            FormsHelper.redirectToReferrer(request, response, Collections.singletonMap("stats", new String[]{String.valueOf(status)}));
            return;
        }
        response.setStatus(status);
    }

    protected void bindMailService(MailService mailService) {
        this.mailService = mailService;
    }

    protected void unbindMailService(MailService mailService) {
        if (this.mailService == mailService) {
            this.mailService = null;
        }
    }
}