All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.adobe.cq.wcm.mobile.qrcode.servlet.QRCodeImageGenerator Maven / Gradle / Ivy

There is a newer version: 6.5.21
Show newest version
/*************************************************************************
 *
 * ADOBE CONFIDENTIAL
 * __________________
 *
 *  Copyright 2015 Adobe Systems Incorporated
 *  All Rights Reserved.
 *
 * NOTICE:  All information contained herein is, and remains
 * the property of Adobe Systems Incorporated and its suppliers,
 * if any.  The intellectual and technical concepts contained
 * herein are proprietary to Adobe Systems Incorporated and its
 * suppliers and are protected by trade secret or copyright law.
 * Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained
 * from Adobe Systems Incorporated.
 **************************************************************************/
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 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.commons.osgi.OsgiUtil;
import org.osgi.framework.Constants;
import org.osgi.service.component.ComponentContext;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.servlet.Servlet;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Dictionary;

@Component(metatype=true,
           label="AEM WCM QR-Code Generator Servlet",
           immediate=true)
@Service(value=Servlet.class)
@Properties( {
        @Property(name=Constants.SERVICE_DESCRIPTION,
                  value="QR Code Image Generator"),
        @Property(name="sling.servlet.paths",
                  value="/libs/wcm/mobile/qrcode",
                  propertyPrivate=true),
        @Property(name="sling.servlet.extensions",
                  value="png",
                  propertyPrivate=true),
        @Property(name="sling.servlet.methods",
                  value="GET",
                  propertyPrivate=true)
    } )
@SuppressWarnings("serial")
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=QRCodeImageGenerator.DATA_NAME_WHITELIST,
              label=QRCodeImageGenerator.DATA_WHITELIST_LABEL,
              value={QRCodeImageGenerator.DATA_WHITELIST_VALUE1},
              description=QRCodeImageGenerator.DATA_WHITELIST_DESC,
              propertyPrivate=false,
              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();
        dataNameWhitelist = OsgiUtil.toStringArray(properties.get(DATA_NAME_WHITELIST));

        if (externalizer != null) {
            author = externalizer.authorLink(null, "");
            publish = externalizer.publishLink(null, "");
        }
    }

    protected Layer createLayer(ImageContext c) throws RepositoryException, IOException {
        Layer layer = null;

        // Look for url property in image context
        String url = c.properties.get("url", "");

        // Look for url property in query string
        if (url == null || url.length() == 0) {
            url = c.request.getParameter("url");
        }

        int size = Integer.parseInt(c.properties.get("size", "100"));

        if (url != null && !url.isEmpty()) {
            boolean matchesWhiteListEntry = (url.startsWith(author) || url.startsWith(publish));

            // If not the author or publish servers, check the white list of external servers.
            if (!matchesWhiteListEntry) {
                for (String filterRegex : dataNameWhitelist) {
                    if (url.matches(filterRegex)) {
                        matchesWhiteListEntry = true;
                        break;
                    }
                }
            }

            if (matchesWhiteListEntry) {
                String selector = c.request.getRequestPathInfo().getSelectorString();
                if (selector != null && selector.length() > 0) {
                    size = Integer.parseInt(selector);
                }

                // Generate the actual QR Code image
                try {
                    QRCode qrcode = new QRCode();
                    Encoder.encode(url, ErrorCorrectionLevel.L, qrcode);
                    int qrBaseSize = qrcode.getMatrixWidth();

                    int baseSize = qrBaseSize + (2 * QR_MARGIN);
                    if (size < baseSize) size = baseSize;
                    int qrActualSize = size / baseSize;
                    int remainder = size % baseSize;
                    int startPos = ((remainder > 0) ? remainder / 2 : qrActualSize) + (QR_MARGIN * qrActualSize);

                    // Make BufferedImage to hold QR code
                    BufferedImage qrImage = new BufferedImage(size, size, BufferedImage.TYPE_INT_RGB);
                    qrImage.createGraphics();
                    Graphics2D graphics = (Graphics2D) qrImage.getGraphics();
                    graphics.setColor(Color.WHITE);
                    graphics.fillRect(0, 0, size, size);

                    // Add QR Code to buffered image
                    graphics.setColor(Color.BLACK);
                    for (int i = 0; i < qrBaseSize; i++) {
                        for (int j = 0; j < qrBaseSize; j++) {
                            if (qrcode.at(i, j) == 1) {
                                graphics.fillRect(startPos + i * qrActualSize, startPos + j * qrActualSize, qrActualSize, qrActualSize);
                            }
                        }
                    }

                    layer = new Layer(qrImage);

                } catch (Exception e) {
                    errMessage = e.getMessage();
                    layer = null;
                }
            } else {
                errMessage = "The following URL in the QR Code request did not match white list of servers: " + url;
            }
        } else {
            errMessage = "QR Code reguest did not contain an url parameter.";
        }

        return layer;
    }

    protected void writeLayer(SlingHttpServletRequest req, SlingHttpServletResponse resp, ImageContext c, Layer layer)
                throws IOException, RepositoryException {
        if (layer == null) {
            if (errMessage != null) {
                log.error(errMessage);
                resp.sendError(HttpServletResponse.SC_FORBIDDEN, errMessage);
                errMessage = null;
            } else {
                resp.sendError(HttpServletResponse.SC_FORBIDDEN);
            }
            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);
        } else {
            return false;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy