QRCodeImageGenerator.java 8.3 KB
/*
 * Decompiled with CFR 0_118.
 * 
 * Could not load the following classes:
 *  com.day.cq.commons.Externalizer
 *  com.day.cq.wcm.commons.AbstractImageServlet
 *  com.day.cq.wcm.commons.AbstractImageServlet$ImageContext
 *  com.day.image.Layer
 *  javax.jcr.Node
 *  javax.jcr.RepositoryException
 *  javax.servlet.Servlet
 *  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.Service
 *  org.apache.sling.api.SlingHttpServletRequest
 *  org.apache.sling.api.SlingHttpServletResponse
 *  org.apache.sling.api.request.RequestPathInfo
 *  org.apache.sling.api.resource.Resource
 *  org.apache.sling.api.resource.ResourceResolver
 *  org.apache.sling.api.resource.ValueMap
 *  org.apache.sling.commons.osgi.OsgiUtil
 *  org.osgi.service.component.ComponentContext
 *  org.slf4j.Logger
 *  org.slf4j.LoggerFactory
 */
package com.adobe.cq.wcm.mobile.qrcode.servlet;

import com.day.cq.commons.Externalizer;
import com.day.cq.wcm.commons.AbstractImageServlet;
import com.day.image.Layer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.google.zxing.qrcode.encoder.Encoder;
import com.google.zxing.qrcode.encoder.QRCode;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Dictionary;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.servlet.Servlet;
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.Service;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.request.RequestPathInfo;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ValueMap;
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="AEM WCM QR-Code Generator Servlet", immediate=1)
@Service(value={Servlet.class})
@Properties(value={@Property(name="service.description", value={"QR Code Image Generator"}), @Property(name="sling.servlet.paths", value={"/libs/wcm/mobile/qrcode"}, propertyPrivate=1), @Property(name="sling.servlet.extensions", value={"png"}, propertyPrivate=1), @Property(name="sling.servlet.methods", value={"GET"}, propertyPrivate=1)})
public class QRCodeImageGenerator
extends AbstractImageServlet {
    @Reference
    private Externalizer externalizer = null;
    private static final int QR_MARGIN = 2;
    private static final String DATA_NAME_WHITELIST = "cq.wcm.qrcode.servlet.whitelist";
    private static final String DATA_WHITELIST_LABEL = "Whitelist URL";
    private static final String DATA_WHITELIST_DESC = "List of regular expressions (regex) indicating which URLs are allowed for the creation of QR Codes images. The Author and Publish servers, based on the Externalizer service, are automatically whitelisted.";
    private static final String DATA_WHITELIST_VALUE1 = "(https://build.phonegap.com/.*)";
    @Property(name="cq.wcm.qrcode.servlet.whitelist", label="Whitelist URL", value={"(https://build.phonegap.com/.*)"}, description="List of regular expressions (regex) indicating which URLs are allowed for the creation of QR Codes images. The Author and Publish servers, based on the Externalizer service, are automatically whitelisted.", propertyPrivate=0, cardinality=1)
    private String[] dataNameWhitelist;
    private String author;
    private String publish;
    private String errMessage;
    private static final Logger log = LoggerFactory.getLogger(QRCodeImageGenerator.class);

    protected void activate(ComponentContext componentContext) {
        Dictionary properties = componentContext.getProperties();
        this.dataNameWhitelist = OsgiUtil.toStringArray(properties.get("cq.wcm.qrcode.servlet.whitelist"));
        if (this.externalizer != null) {
            this.author = this.externalizer.authorLink(null, "");
            this.publish = this.externalizer.publishLink(null, "");
        }
    }

    protected Layer createLayer(AbstractImageServlet.ImageContext c) throws RepositoryException, IOException {
        Layer layer = null;
        String url = (String)c.properties.get("url", (Object)"");
        if (url == null || url.length() == 0) {
            url = c.request.getParameter("url");
        }
        int size = Integer.parseInt((String)c.properties.get("size", (Object)"100"));
        if (url != null && !url.isEmpty()) {
            boolean matchesWhiteListEntry;
            boolean bl = matchesWhiteListEntry = url.startsWith(this.author) || url.startsWith(this.publish);
            if (!matchesWhiteListEntry) {
                for (String filterRegex : this.dataNameWhitelist) {
                    if (!url.matches(filterRegex)) continue;
                    matchesWhiteListEntry = true;
                    break;
                }
            }
            if (matchesWhiteListEntry) {
                String selector = c.request.getRequestPathInfo().getSelectorString();
                if (selector != null && selector.length() > 0) {
                    size = Integer.parseInt(selector);
                }
                try {
                    QRCode qrcode = new QRCode();
                    Encoder.encode(url, ErrorCorrectionLevel.L, qrcode);
                    int qrBaseSize = qrcode.getMatrixWidth();
                    int baseSize = qrBaseSize + 4;
                    if (size < baseSize) {
                        size = baseSize;
                    }
                    int qrActualSize = size / baseSize;
                    int remainder = size % baseSize;
                    int startPos = (remainder > 0 ? remainder / 2 : qrActualSize) + 2 * qrActualSize;
                    BufferedImage qrImage = new BufferedImage(size, size, 1);
                    qrImage.createGraphics();
                    Graphics2D graphics = (Graphics2D)qrImage.getGraphics();
                    graphics.setColor(Color.WHITE);
                    graphics.fillRect(0, 0, size, size);
                    graphics.setColor(Color.BLACK);
                    for (int i = 0; i < qrBaseSize; ++i) {
                        for (int j = 0; j < qrBaseSize; ++j) {
                            if (qrcode.at(i, j) != 1) continue;
                            graphics.fillRect(startPos + i * qrActualSize, startPos + j * qrActualSize, qrActualSize, qrActualSize);
                        }
                    }
                    layer = new Layer(qrImage);
                }
                catch (Exception e) {
                    this.errMessage = e.getMessage();
                    layer = null;
                }
            } else {
                this.errMessage = "The following URL in the QR Code request did not match white list of servers: " + url;
            }
        } else {
            this.errMessage = "QR Code reguest did not contain an url parameter.";
        }
        return layer;
    }

    protected void writeLayer(SlingHttpServletRequest req, SlingHttpServletResponse resp, AbstractImageServlet.ImageContext c, Layer layer) throws IOException, RepositoryException {
        if (layer == null) {
            if (this.errMessage != null) {
                log.error(this.errMessage);
                resp.sendError(403, this.errMessage);
                this.errMessage = null;
            } else {
                resp.sendError(403);
            }
            return;
        }
        super.writeLayer(req, resp, c, layer);
    }

    protected boolean checkModifiedSince(SlingHttpServletRequest req, SlingHttpServletResponse resp) {
        if (req.getResource().adaptTo(Node.class) != null) {
            return super.checkModifiedSince(req, resp);
        }
        return false;
    }

    protected void bindExternalizer(Externalizer externalizer) {
        this.externalizer = externalizer;
    }

    protected void unbindExternalizer(Externalizer externalizer) {
        if (this.externalizer == externalizer) {
            this.externalizer = null;
        }
    }
}