/******************************************************************************
* Copyright © 2013-2016 The Nxt Core Developers. *
* *
* See the AUTHORS.txt, DEVELOPER-AGREEMENT.txt and LICENSE.txt files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* Nxt software, including this file, may be copied, modified, propagated, *
* or distributed except according to the terms contained in the LICENSE.txt *
* file. *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
package nxt.http;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.NotFoundException;
import com.google.zxing.Result;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.HybridBinarizer;
import nxt.NxtException;
import nxt.util.Convert;
import nxt.util.Logger;
import org.json.simple.JSONObject;
import org.json.simple.JSONStreamAware;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Base64;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
/**
* <p>The DecodeQRCode API converts a base64-encoded image of a
* 2-D QR (Quick Response) code to a UTF-8 string, using the ZXing library.
* </p>
*
* <p>The input qrCodeBase64 can be the output of the DecodeQRCode API.</p>
*
* <p>Request parameters:</p>
*
* <ul>
* <li>qrCodeBase64 - A base64 string encoded from an image of a QR code.
* The length of the string must be less than the jetty server maximum allowed
* parameter length, currently 200,000 bytes.
* </li>
* </ul>
*
* <p>Response fields:</p>
*
* <ul>
* <li>qrCodeData - A UTF-8 string decoded from the QR code.</li>
* </ul>
*/
public final class DecodeQRCode extends APIServlet.APIRequestHandler {
static final DecodeQRCode instance = new DecodeQRCode();
private DecodeQRCode() {
super(new APITag[] {APITag.UTILS}, "qrCodeBase64");
}
@Override
JSONStreamAware processRequest(HttpServletRequest request)
throws NxtException {
String qrCodeBase64 = Convert.nullToEmpty(request.getParameter("qrCodeBase64"));
JSONObject response = new JSONObject();
try {
BinaryBitmap binaryBitmap = new BinaryBitmap(
new HybridBinarizer(new BufferedImageLuminanceSource(
ImageIO.read(new ByteArrayInputStream(
Base64.getDecoder().decode(qrCodeBase64)
))
))
);
Map hints = new HashMap();
hints.put(DecodeHintType.POSSIBLE_FORMATS, EnumSet.of(BarcodeFormat.QR_CODE));
hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");
Result qrCodeData = new MultiFormatReader().decode(binaryBitmap, hints);
response.put("qrCodeData", qrCodeData.getText());
} catch(IOException ex) {
String errorMessage = "Error reading base64 byte stream";
Logger.logErrorMessage(errorMessage, ex);
JSONData.putException(response, ex, errorMessage);
} catch(NullPointerException ex) {
String errorMessage = "Invalid base64 image";
Logger.logErrorMessage(errorMessage, ex);
JSONData.putException(response, ex, errorMessage);
} catch(NotFoundException ex) {
response.put("qrCodeData", "");
}
return response;
}
@Override
final boolean requirePost() {
return true;
}
@Override
boolean allowRequiredBlockParameters() {
return false;
}
@Override
boolean requireBlockchain() {
return false;
}
}