8181571: printing to CUPS fails on mac sandbox app

Reviewed-by: prr
This commit is contained in:
Alexander Scherbatiy 2022-03-31 08:32:22 +00:00
parent ef51dfd153
commit 3d4be14eba
2 changed files with 102 additions and 9 deletions
src/java.desktop/unix
classes/sun/print
native/common/awt

@ -53,6 +53,7 @@ public class CUPSPrinter {
private static native String getCupsServer();
private static native int getCupsPort();
private static native String getCupsDefaultPrinter();
private static native String[] getCupsDefaultPrinters();
private static native boolean canConnect(String server, int port);
private static native boolean initIDs();
// These functions need to be synchronized as
@ -77,6 +78,7 @@ public class CUPSPrinter {
private static boolean libFound;
private static String cupsServer = null;
private static String domainSocketPathname = null;
private static int cupsPort = 0;
static {
@ -96,6 +98,13 @@ public class CUPSPrinter {
libFound = initIDs();
if (libFound) {
cupsServer = getCupsServer();
// Is this a local domain socket pathname?
if (cupsServer != null && cupsServer.startsWith("/")) {
if (isSandboxedApp()) {
domainSocketPathname = cupsServer;
}
cupsServer = "localhost";
}
cupsPort = getCupsPort();
}
}
@ -381,6 +390,20 @@ public class CUPSPrinter {
* Get list of all CUPS printers using IPP.
*/
static String[] getAllPrinters() {
if (getDomainSocketPathname() != null) {
String[] printerNames = getCupsDefaultPrinters();
if (printerNames != null && printerNames.length > 0) {
String[] printerURIs = new String[printerNames.length];
for (int i=0; i< printerNames.length; i++) {
printerURIs[i] = String.format("ipp://%s:%d/printers/%s",
getServer(), getPort(), printerNames[i]);
}
return printerURIs;
}
return null;
}
try {
URL url = new URL("http", getServer(), getPort(), "");
@ -464,15 +487,39 @@ public class CUPSPrinter {
return cupsPort;
}
/**
* Returns CUPS domain socket pathname.
*/
private static String getDomainSocketPathname() {
return domainSocketPathname;
}
@SuppressWarnings("removal")
private static boolean isSandboxedApp() {
if (PrintServiceLookupProvider.isMac()) {
return java.security.AccessController
.doPrivileged((java.security.PrivilegedAction<Boolean>) () ->
System.getenv("APP_SANDBOX_CONTAINER_ID") != null);
}
return false;
}
/**
* Detects if CUPS is running.
*/
public static boolean isCupsRunning() {
IPPPrintService.debug_println(debugPrefix+"libFound "+libFound);
if (libFound) {
IPPPrintService.debug_println(debugPrefix+"CUPS server "+getServer()+
" port "+getPort());
return canConnect(getServer(), getPort());
String server = getDomainSocketPathname() != null
? getDomainSocketPathname()
: getServer();
IPPPrintService.debug_println(debugPrefix+"CUPS server "+server+
" port "+getPort()+
(getDomainSocketPathname() != null
? " use domain socket pathname"
: ""));
return canConnect(server, getPort());
} else {
return false;
}

@ -172,12 +172,7 @@ Java_sun_print_CUPSPrinter_getCupsServer(JNIEnv *env,
jstring cServer = NULL;
const char* server = j2d_cupsServer();
if (server != NULL) {
// Is this a local domain socket?
if (strncmp(server, "/", 1) == 0) {
cServer = JNU_NewStringPlatform(env, "localhost");
} else {
cServer = JNU_NewStringPlatform(env, server);
}
cServer = JNU_NewStringPlatform(env, server);
}
return cServer;
}
@ -219,6 +214,57 @@ Java_sun_print_CUPSPrinter_getCupsDefaultPrinter(JNIEnv *env,
return cDefPrinter;
}
/*
* Returns list of default local printers
*/
JNIEXPORT jobjectArray JNICALL
Java_sun_print_CUPSPrinter_getCupsDefaultPrinters(JNIEnv *env,
jobject printObj)
{
cups_dest_t *dests;
int i, j, num_dests;
jstring utf_str;
jclass cls;
jobjectArray nameArray = NULL;
cls = (*env)->FindClass(env, "java/lang/String");
CHECK_NULL_RETURN(cls, NULL);
num_dests = j2d_cupsGetDests(&dests);
if (dests == NULL) {
return NULL;
}
nameArray = (*env)->NewObjectArray(env, num_dests, cls, NULL);
if (nameArray == NULL) {
j2d_cupsFreeDests(num_dests, dests);
DPRINTF("CUPSfuncs::bad alloc new array\n", "")
return NULL;
}
for (i = 0; i < num_dests; i++) {
utf_str = JNU_NewStringPlatform(env, dests[i].name);
if (utf_str == NULL) {
for (j = i - 1; j >= 0; j--) {
utf_str = (*env)->GetObjectArrayElement(env, nameArray, j);
(*env)->SetObjectArrayElement(env, nameArray, j, NULL);
(*env)->DeleteLocalRef(env, utf_str);
utf_str = NULL;
}
j2d_cupsFreeDests(num_dests, dests);
(*env)->DeleteLocalRef(env, nameArray);
DPRINTF("CUPSfuncs::bad alloc new string ->name\n", "")
return NULL;
}
(*env)->SetObjectArrayElement(env, nameArray, i, utf_str);
(*env)->DeleteLocalRef(env, utf_str);
}
j2d_cupsFreeDests(num_dests, dests);
return nameArray;
}
/*
* Checks if connection can be made to the server.
*