diff --git a/scheduler/ipp.c b/scheduler/ipp.c index 9984b79..dd85173 100644 --- a/scheduler/ipp.c +++ b/scheduler/ipp.c @@ -5898,6 +5898,11 @@ create_local_printer( *nameptr, /* Pointer into name */ uri[1024]; /* printer-uri-supported value */ const char *ptr; /* Pointer into attribute value */ + char scheme[HTTP_MAX_URI], /* Scheme portion of URI */ + userpass[HTTP_MAX_URI], /* Username portion of URI */ + host[HTTP_MAX_URI], /* Host portion of URI */ + resource[HTTP_MAX_URI]; /* Resource portion of URI */ + int port; /* Port portion of URI */ /* @@ -5961,6 +5966,13 @@ create_local_printer( return; } + ptr = ippGetString(device_uri, 0, NULL); + if (!ptr || !ptr[0]) + { + send_ipp_status(con, IPP_STATUS_ERROR_BAD_REQUEST, _("Attribute \"%s\" has empty value."), "device-uri"); + + return; + } printer_geo_location = ippFindAttribute(con->request, "printer-geo-location", IPP_TAG_URI); printer_info = ippFindAttribute(con->request, "printer-info", IPP_TAG_TEXT); @@ -5989,7 +6001,65 @@ create_local_printer( printer->shared = 0; printer->temporary = 1; - cupsdSetDeviceURI(printer, ippGetString(device_uri, 0, NULL)); + /* + * Check device URI if it has the same hostname as we have, if so, replace + * the hostname by localhost. This way we assure that local-only services + * like ipp-usb or Printer Applications always work. + * + * When comparing our hostname with the one in the device URI, + * consider names with or without trailing dot ('.') the same. Also + * compare case-insensitively. + */ + +#ifdef HAVE_DNSSD + if (DNSSDHostName) + nameptr = DNSSDHostName; + else +#endif + if (ServerName) + nameptr = ServerName; + else + nameptr = NULL; + + if (nameptr) + { + int host_len, + server_name_len; + + /* Get host name of device URI */ + httpSeparateURI(HTTP_URI_CODING_ALL, ptr, + scheme, sizeof(scheme), userpass, sizeof(userpass), host, + sizeof(host), &port, resource, sizeof(resource)); + + /* Take trailing dot out of comparison */ + host_len = strlen(host); + if (host_len > 1 && host[host_len - 1] == '.') + host_len --; + + server_name_len = strlen(nameptr); + if (server_name_len > 1 && nameptr[server_name_len - 1] == '.') + server_name_len --; + + /* + * If we have no DNSSDHostName but only a ServerName (if we are not + * sharing printers, Browsing = Off) the ServerName has no ".local" + * but the requested device URI has. Take this into account. + */ + + if (nameptr == ServerName && host_len >= 6 && (server_name_len < 6 || strcmp(nameptr + server_name_len - 6, ".local") != 0) && strcmp(host + host_len - 6, ".local") == 0) + host_len -= 6; + + if (host_len == server_name_len && strncasecmp(host, nameptr, host_len) == 0) + ptr = "localhost"; + else + ptr = host; + + httpAssembleURI(HTTP_URI_CODING_ALL, uri, sizeof(uri), scheme, userpass, + ptr, port, resource); + cupsdSetDeviceURI(printer, uri); + } + else + cupsdSetDeviceURI(printer, ptr); if (printer_geo_location) cupsdSetString(&printer->geo_location, ippGetString(printer_geo_location, 0, NULL));