-/*
- * 'cupsGetPPD()' - Get the PPD file for a printer on the default server.
- *
- * For classes, @code cupsGetPPD@ returns the PPD file for the first printer
- * in the class.
- *
- * The returned filename is stored in a static buffer and is overwritten with
- * each call to @code cupsGetPPD@ or @link cupsGetPPD2@. The caller "owns" the
- * file that is created and must @code unlink@ the returned filename.
- */
-
-const char * /* O - Filename for PPD file */
-cupsGetPPD(const char *name) /* I - Destination name */
-{
- _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
- time_t modtime = 0; /* Modification time */
-
-
- /*
- * Return the PPD file...
- */
-
- cg->ppd_filename[0] = '\0';
-
- if (cupsGetPPD3(CUPS_HTTP_DEFAULT, name, &modtime, cg->ppd_filename,
- sizeof(cg->ppd_filename)) == HTTP_OK)
- return (cg->ppd_filename);
- else
- return (NULL);
-}
-
-
-/*
- * 'cupsGetPPD2()' - Get the PPD file for a printer from the specified server.
- *
- * For classes, @code cupsGetPPD2@ returns the PPD file for the first printer
- * in the class.
- *
- * The returned filename is stored in a static buffer and is overwritten with
- * each call to @link cupsGetPPD@ or @code cupsGetPPD2@. The caller "owns" the
- * file that is created and must @code unlink@ the returned filename.
- *
- * @since CUPS 1.1.21/Mac OS X 10.4@
- */
-
-const char * /* O - Filename for PPD file */
-cupsGetPPD2(http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
- const char *name) /* I - Destination name */
-{
- _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
- time_t modtime = 0; /* Modification time */
-
-
- cg->ppd_filename[0] = '\0';
-
- if (cupsGetPPD3(http, name, &modtime, cg->ppd_filename,
- sizeof(cg->ppd_filename)) == HTTP_OK)
- return (cg->ppd_filename);
- else
- return (NULL);
-}
-
-
-/*
- * 'cupsGetPPD3()' - Get the PPD file for a printer on the specified
- * server if it has changed.
- *
- * The "modtime" parameter contains the modification time of any
- * locally-cached content and is updated with the time from the PPD file on
- * the server.
- *
- * The "buffer" parameter contains the local PPD filename. If it contains
- * the empty string, a new temporary file is created, otherwise the existing
- * file will be overwritten as needed. The caller "owns" the file that is
- * created and must @code unlink@ the returned filename.
- *
- * On success, @code HTTP_OK@ is returned for a new PPD file and
- * @code HTTP_NOT_MODIFIED@ if the existing PPD file is up-to-date. Any other
- * status is an error.
- *
- * For classes, @code cupsGetPPD3@ returns the PPD file for the first printer
- * in the class.
- *
- * @since CUPS 1.4/Mac OS X 10.6@
- */
-
-http_status_t /* O - HTTP status */
-cupsGetPPD3(http_t *http, /* I - HTTP connection or @code CUPS_HTTP_DEFAULT@ */
- const char *name, /* I - Destination name */
- time_t *modtime, /* IO - Modification time */
- char *buffer, /* I - Filename buffer */
- size_t bufsize) /* I - Size of filename buffer */
-{
- int http_port; /* Port number */
- char http_hostname[HTTP_MAX_HOST];
- /* Hostname associated with connection */
- http_t *http2; /* Alternate HTTP connection */
- int fd; /* PPD file */
- char localhost[HTTP_MAX_URI],/* Local hostname */
- hostname[HTTP_MAX_URI], /* Hostname */
- resource[HTTP_MAX_URI]; /* Resource name */
- int port; /* Port number */
- http_status_t status; /* HTTP status from server */
- _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
-
-
- /*
- * Range check input...
- */
-
- DEBUG_printf(("cupsGetPPD3(http=%p, name=\"%s\", modtime=%p(%d), buffer=%p, "
- "bufsize=%d)", http, name, modtime,
- modtime ? (int)*modtime : 0, buffer, (int)bufsize));
-
- if (!name)
- {
- _cupsSetError(IPP_INTERNAL_ERROR, _("No printer name"), 1);
- return (HTTP_NOT_ACCEPTABLE);
- }
-
- if (!modtime)
- {
- _cupsSetError(IPP_INTERNAL_ERROR, _("No modification time"), 1);
- return (HTTP_NOT_ACCEPTABLE);
- }
-
- if (!buffer || bufsize <= 1)
- {
- _cupsSetError(IPP_INTERNAL_ERROR, _("Bad filename buffer"), 1);
- return (HTTP_NOT_ACCEPTABLE);
- }
-
-#ifndef WIN32
- /*
- * See if the PPD file is available locally...
- */
-
- if (!cg->servername[0])
- cupsServer();
-
- if (!strcasecmp(cg->servername, "localhost"))
- {
- char ppdname[1024]; /* PPD filename */
- struct stat ppdinfo; /* PPD file information */
-
-
- snprintf(ppdname, sizeof(ppdname), "%s/ppd/%s.ppd", cg->cups_serverroot,
- name);
- if (!stat(ppdname, &ppdinfo))
- {
- /*
- * OK, the file exists, use it!
- */
-
- if (buffer[0])
- {
- unlink(buffer);
-
- if (symlink(ppdname, buffer) && errno != EEXIST)
- {
- _cupsSetError(IPP_INTERNAL_ERROR, NULL, 0);
-
- return (HTTP_SERVER_ERROR);
- }
- }
- else
- {
- int tries; /* Number of tries */
- const char *tmpdir; /* TMPDIR environment variable */
- struct timeval curtime; /* Current time */
-
- /*
- * Previously we put root temporary files in the default CUPS temporary
- * directory under /var/spool/cups. However, since the scheduler cleans
- * out temporary files there and runs independently of the user apps, we
- * don't want to use it unless specifically told to by cupsd.
- */
-
- if ((tmpdir = getenv("TMPDIR")) == NULL)
-# ifdef __APPLE__
- tmpdir = "/private/tmp"; /* /tmp is a symlink to /private/tmp */
-# else
- tmpdir = "/tmp";
-# endif /* __APPLE__ */
-
- /*
- * Make the temporary name using the specified directory...
- */
-
- tries = 0;
-
- do
- {
- /*
- * Get the current time of day...
- */
-
- gettimeofday(&curtime, NULL);
-
- /*
- * Format a string using the hex time values...
- */
-
- snprintf(buffer, bufsize, "%s/%08lx%05lx", tmpdir,
- (unsigned long)curtime.tv_sec,
- (unsigned long)curtime.tv_usec);
-
- /*
- * Try to make a symlink...
- */
-
- if (!symlink(ppdname, buffer))
- break;
-
- tries ++;
- }
- while (tries < 1000);
-
- if (tries >= 1000)
- {
- _cupsSetError(IPP_INTERNAL_ERROR, NULL, 0);
-
- return (HTTP_SERVER_ERROR);
- }
- }
-
- if (*modtime >= ppdinfo.st_mtime)
- return (HTTP_NOT_MODIFIED);
- else
- {
- *modtime = ppdinfo.st_mtime;
- return (HTTP_OK);
- }
- }
- }
-#endif /* !WIN32 */
-
- /*
- * Try finding a printer URI for this printer...
- */
-
- if (!http)
- if ((http = _cupsConnect()) == NULL)
- return (HTTP_SERVICE_UNAVAILABLE);
-
- if (!cups_get_printer_uri(http, name, hostname, sizeof(hostname), &port,
- resource, sizeof(resource), 0))
- return (HTTP_NOT_FOUND);
-
- DEBUG_printf(("2cupsGetPPD3: Printer hostname=\"%s\", port=%d", hostname,
- port));
-
- /*
- * Remap local hostname to localhost...
- */
-
- httpGetHostname(NULL, localhost, sizeof(localhost));
-
- DEBUG_printf(("2cupsGetPPD3: Local hostname=\"%s\"", localhost));
-
- if (!strcasecmp(localhost, hostname))
- strcpy(hostname, "localhost");
-
- /*
- * Get the hostname and port number we are connected to...
- */
-
- httpGetHostname(http, http_hostname, sizeof(http_hostname));
- http_port = _httpAddrPort(http->hostaddr);
-
- DEBUG_printf(("2cupsGetPPD3: Connection hostname=\"%s\", port=%d",
- http_hostname, http_port));
-
- /*
- * Reconnect to the correct server as needed...
- */
-
- if (!strcasecmp(http_hostname, hostname) && port == http_port)
- http2 = http;
- else if ((http2 = httpConnectEncrypt(hostname, port,
- cupsEncryption())) == NULL)
- {
- DEBUG_puts("1cupsGetPPD3: Unable to connect to server");
-
- return (HTTP_SERVICE_UNAVAILABLE);
- }
-
- /*
- * Get a temp file...
- */
-
- if (buffer[0])
- fd = open(buffer, O_CREAT | O_TRUNC | O_WRONLY, 0600);
- else
- fd = cupsTempFd(buffer, bufsize);
-
- if (fd < 0)
- {
- /*
- * Can't open file; close the server connection and return NULL...
- */
-
- _cupsSetError(IPP_INTERNAL_ERROR, NULL, 0);
-
- if (http2 != http)
- httpClose(http2);
-
- return (HTTP_SERVER_ERROR);
- }
-
- /*
- * And send a request to the HTTP server...
- */
-
- strlcat(resource, ".ppd", sizeof(resource));
-
- if (*modtime > 0)
- httpSetField(http2, HTTP_FIELD_IF_MODIFIED_SINCE,
- httpGetDateString(*modtime));
-
- status = cupsGetFd(http2, resource, fd);
-
- close(fd);
-
- /*
- * See if we actually got the file or an error...
- */
-
- if (status == HTTP_OK)
- *modtime = httpGetDateTime(httpGetField(http2, HTTP_FIELD_DATE));
- else if (status != HTTP_NOT_MODIFIED)
- {
- _cupsSetHTTPError(status);
-
- unlink(cg->ppd_filename);
- }
-
- if (http2 != http)
- httpClose(http2);
-
- /*
- * Return the PPD file...
- */
-
- DEBUG_printf(("1cupsGetPPD3: Returning status %d", status));
-
- return (status);
-}
-
-