Add custom QZ Tray fork with pairing key authentication
- Custom fork of QZ Tray 2.2.x with certificate validation bypassed - Implemented pairing key (HMAC) authentication as replacement - Modified files: PrintSocketClient.java (certificate check disabled) - New files: PairingAuth.java, PairingConfigDialog.java - Excluded build artifacts (out/, lib/javafx*) from repository - Library JARs included for dependency management
This commit is contained in:
242
tray/src/qz/printer/PrintServiceMatcher.java
Normal file
242
tray/src/qz/printer/PrintServiceMatcher.java
Normal file
@@ -0,0 +1,242 @@
|
||||
/**
|
||||
* @author Tres Finocchiaro
|
||||
*
|
||||
* Copyright (C) 2016 Tres Finocchiaro, QZ Industries, LLC
|
||||
*
|
||||
* LGPL 2.1 This is free software. This software and source code are released under
|
||||
* the "LGPL 2.1 License". A copy of this license should be distributed with
|
||||
* this software. http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
|
||||
package qz.printer;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.codehaus.jettison.json.JSONArray;
|
||||
import org.codehaus.jettison.json.JSONException;
|
||||
import org.codehaus.jettison.json.JSONObject;
|
||||
import qz.printer.info.CachedPrintServiceLookup;
|
||||
import qz.printer.info.NativePrinter;
|
||||
import qz.printer.info.NativePrinterMap;
|
||||
import qz.utils.SystemUtilities;
|
||||
|
||||
import javax.print.PrintService;
|
||||
import javax.print.PrintServiceLookup;
|
||||
import javax.print.attribute.ResolutionSyntax;
|
||||
import javax.print.attribute.standard.*;
|
||||
import java.util.*;
|
||||
|
||||
public class PrintServiceMatcher {
|
||||
private static final Logger log = LogManager.getLogger(PrintServiceMatcher.class);
|
||||
|
||||
// PrintService is slow in CUPS, use a cache instead per JDK-7001133
|
||||
// TODO: Include JDK version test for caching when JDK-7001133 is fixed upstream
|
||||
private static final boolean useCache = SystemUtilities.isUnix();
|
||||
|
||||
public static NativePrinterMap getNativePrinterList(boolean silent, boolean withAttributes) {
|
||||
NativePrinterMap printers = NativePrinterMap.getInstance();
|
||||
printers.putAll(true, lookupPrintServices());
|
||||
if (withAttributes) { printers.values().forEach(NativePrinter::getDriverAttributes); }
|
||||
if (!silent) { log.debug("Found {} printers", printers.size()); }
|
||||
return printers;
|
||||
}
|
||||
|
||||
private static PrintService[] lookupPrintServices() {
|
||||
return useCache ? CachedPrintServiceLookup.lookupPrintServices() :
|
||||
PrintServiceLookup.lookupPrintServices(null, null);
|
||||
}
|
||||
|
||||
private static PrintService lookupDefaultPrintService() {
|
||||
return useCache ? CachedPrintServiceLookup.lookupDefaultPrintService() :
|
||||
PrintServiceLookup.lookupDefaultPrintService();
|
||||
}
|
||||
|
||||
public static NativePrinterMap getNativePrinterList(boolean silent) {
|
||||
return getNativePrinterList(silent, false);
|
||||
}
|
||||
|
||||
public static NativePrinterMap getNativePrinterList() {
|
||||
return getNativePrinterList(false);
|
||||
}
|
||||
|
||||
public static NativePrinter getDefaultPrinter() {
|
||||
PrintService defaultService = lookupDefaultPrintService();
|
||||
|
||||
if(defaultService == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
NativePrinterMap printers = NativePrinterMap.getInstance();
|
||||
if (!printers.contains(defaultService)) {
|
||||
printers.putAll(false, defaultService);
|
||||
}
|
||||
|
||||
return printers.get(defaultService);
|
||||
}
|
||||
|
||||
public static String findPrinterName(String query) throws JSONException {
|
||||
NativePrinter printer = PrintServiceMatcher.matchPrinter(query);
|
||||
|
||||
if (printer != null) {
|
||||
return printer.getPrintService().value().getName();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds {@code PrintService} by looking at any matches to {@code printerSearch}.
|
||||
*
|
||||
* @param printerSearch Search query to compare against service names.
|
||||
*/
|
||||
public static NativePrinter matchPrinter(String printerSearch, boolean silent) {
|
||||
NativePrinter exact = null;
|
||||
NativePrinter begins = null;
|
||||
NativePrinter partial = null;
|
||||
|
||||
if (!silent) { log.debug("Searching for PrintService matching {}", printerSearch); }
|
||||
|
||||
// Fix for https://github.com/qzind/tray/issues/931
|
||||
// This is more than an optimization, removal will lead to a regression
|
||||
NativePrinter defaultPrinter = getDefaultPrinter();
|
||||
if (defaultPrinter != null && printerSearch.equals(defaultPrinter.getName())) {
|
||||
if (!silent) { log.debug("Matched default printer, skipping further search"); }
|
||||
return defaultPrinter;
|
||||
}
|
||||
|
||||
printerSearch = printerSearch.toLowerCase(Locale.ENGLISH);
|
||||
|
||||
// Search services for matches
|
||||
for(NativePrinter printer : getNativePrinterList(silent).values()) {
|
||||
if (printer.getName() == null) {
|
||||
continue;
|
||||
}
|
||||
String printerName = printer.getName().toLowerCase(Locale.ENGLISH);
|
||||
if (printerName.equals(printerSearch)) {
|
||||
exact = printer;
|
||||
break;
|
||||
}
|
||||
if (printerName.startsWith(printerSearch)) {
|
||||
begins = printer;
|
||||
continue;
|
||||
}
|
||||
if (printerName.contains(printerSearch)) {
|
||||
partial = printer;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (SystemUtilities.isMac()) {
|
||||
// 1.9 compat: fallback for old style names
|
||||
PrinterName name = printer.getLegacyName();
|
||||
if (name == null || name.getValue() == null) { continue; }
|
||||
printerName = name.getValue().toLowerCase(Locale.ENGLISH);
|
||||
if (printerName.equals(printerSearch)) {
|
||||
exact = printer;
|
||||
continue;
|
||||
}
|
||||
if (printerName.startsWith(printerSearch)) {
|
||||
begins = printer;
|
||||
continue;
|
||||
}
|
||||
if (printerName.contains(printerSearch)) {
|
||||
partial = printer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return closest match
|
||||
NativePrinter use = null;
|
||||
if (exact != null) {
|
||||
use = exact;
|
||||
} else if (begins != null) {
|
||||
use = begins;
|
||||
} else if (partial != null) {
|
||||
use = partial;
|
||||
}
|
||||
|
||||
if (use != null) {
|
||||
if(!silent) log.debug("Found match: {}", use.getPrintService().value().getName());
|
||||
} else {
|
||||
log.warn("Printer not found: {}", printerSearch);
|
||||
}
|
||||
|
||||
return use;
|
||||
}
|
||||
|
||||
public static NativePrinter matchPrinter(String printerSearch) {
|
||||
return matchPrinter(printerSearch, false);
|
||||
}
|
||||
|
||||
public static JSONArray getPrintersJSON(boolean includeDetails) throws JSONException {
|
||||
JSONArray list = new JSONArray();
|
||||
|
||||
PrintService defaultService = lookupDefaultPrintService();
|
||||
|
||||
boolean mediaTrayCrawled = false;
|
||||
|
||||
for(NativePrinter printer : getNativePrinterList().values()) {
|
||||
PrintService ps = printer.getPrintService().value();
|
||||
JSONObject jsonService = new JSONObject();
|
||||
jsonService.put("name", ps.getName());
|
||||
|
||||
if (includeDetails) {
|
||||
jsonService.put("driver", printer.getDriver().value());
|
||||
jsonService.put("connection", printer.getConnection());
|
||||
jsonService.put("default", ps == defaultService);
|
||||
|
||||
if (!mediaTrayCrawled) {
|
||||
log.info("Gathering printer MediaTray information...");
|
||||
mediaTrayCrawled = true;
|
||||
}
|
||||
|
||||
HashSet<String> uniqueSizes = new HashSet<>(); // prevents duplicates
|
||||
JSONArray trays = new JSONArray();
|
||||
JSONArray sizes = new JSONArray();
|
||||
|
||||
for(Media m : (Media[])ps.getSupportedAttributeValues(Media.class, null, null)) {
|
||||
if (m instanceof MediaTray) { trays.put(m.toString()); }
|
||||
if (m instanceof MediaSizeName) {
|
||||
if(uniqueSizes.add(m.toString())) {
|
||||
MediaSize mediaSize = MediaSize.getMediaSizeForName((MediaSizeName)m);
|
||||
if(mediaSize == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
JSONObject size = new JSONObject();
|
||||
size.put("name", m.toString());
|
||||
|
||||
JSONObject in = new JSONObject();
|
||||
in.put("width", mediaSize.getX(MediaPrintableArea.INCH));
|
||||
in.put("height", mediaSize.getY(MediaPrintableArea.INCH));
|
||||
size.put("in", in);
|
||||
|
||||
JSONObject mm = new JSONObject();
|
||||
mm.put("width", mediaSize.getX(MediaPrintableArea.MM));
|
||||
mm.put("height", mediaSize.getY(MediaPrintableArea.MM));
|
||||
size.put("mm", mm);
|
||||
|
||||
sizes.put(size);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if(trays.length() > 0) {
|
||||
jsonService.put("trays", trays);
|
||||
}
|
||||
if(sizes.length() > 0) {
|
||||
jsonService.put("sizes", sizes);
|
||||
}
|
||||
|
||||
PrinterResolution res = printer.getResolution().value();
|
||||
int density = -1; if (res != null) { density = res.getFeedResolution(ResolutionSyntax.DPI); }
|
||||
jsonService.put("density", density);
|
||||
}
|
||||
|
||||
list.put(jsonService);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user