get_ppd(cupsd_client_t  *con,		/* I - Client connection */
        ipp_attribute_t *uri)		/* I - Printer URI or PPD name */
{
  http_status_t		status;		/* Policy status */
  cupsd_printer_t	*dest;		/* Destination */
  cups_ptype_t		dtype;		/* Destination type */


  cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_ppd(%p[%d], %p[%s=%s])", con,
                  con->number, uri, uri->name, uri->values[0].string.text);

  if (!strcmp(ippGetName(uri), "ppd-name"))
  {
   /*
    * Return a PPD file from cups-driverd...
    */

    const char *ppd_name = ippGetString(uri, 0, NULL);
					/* ppd-name value */
    char	command[1024],		/* cups-driverd command */
		options[1024],		/* Options to pass to command */
		oppd_name[1024];	/* Escaped ppd-name */

   /*
    * Check policy...
    */

    if ((status = cupsdCheckPolicy(DefaultPolicyPtr, con, NULL)) != HTTP_OK)
    {
      send_http_error(con, status, NULL);
      return;
    }

   /*
    * Check ppd-name value...
    */

    if (strstr(ppd_name, "../"))
    {
      send_ipp_status(con, IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES, _("Invalid ppd-name value."));
      return;
    }

   /*
    * Run cups-driverd command with the given options...
    */

    snprintf(command, sizeof(command), "%s/daemon/cups-driverd", ServerBin);
    url_encode_string(ppd_name, oppd_name, sizeof(oppd_name));
    snprintf(options, sizeof(options), "get+%d+%s", ippGetRequestId(con->request), oppd_name);

    if (cupsdSendCommand(con, command, options, 0))
    {
     /*
      * Command started successfully, don't send an IPP response here...
      */

      ippDelete(con->response);
      con->response = NULL;
    }
    else
    {
     /*
      * Command failed, return "internal error" so the user knows something
      * went wrong...
      */

      send_ipp_status(con, IPP_INTERNAL_ERROR, _("cups-driverd failed to execute."));
    }
  }
  else if (!strcmp(ippGetName(uri), "printer-uri") && cupsdValidateDest(ippGetString(uri, 0, NULL), &dtype, &dest))
  {
    int 	i;			/* Looping var */
    char	filename[1024];		/* PPD filename */

   /*
    * Check policy...
    */

    if ((status = cupsdCheckPolicy(dest->op_policy_ptr, con, NULL)) != HTTP_OK)
    {
      send_http_error(con, status, dest);
      return;
    }

   /*
    * See if we need the PPD for a class or remote printer...
    */

    snprintf(filename, sizeof(filename), "%s/ppd/%s.ppd", ServerRoot, dest->name);

    if ((dtype & CUPS_PRINTER_REMOTE) && access(filename, 0))
    {
      send_ipp_status(con, IPP_STATUS_CUPS_SEE_OTHER, _("See remote printer."));
      ippAddString(con->response, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, dest->uri);
      return;
    }
    else if (dtype & CUPS_PRINTER_CLASS)
    {
      for (i = 0; i < dest->num_printers; i ++)
        if (!(dest->printers[i]->type & CUPS_PRINTER_CLASS))
	{
	  snprintf(filename, sizeof(filename), "%s/ppd/%s.ppd", ServerRoot, dest->printers[i]->name);

          if (!access(filename, 0))
	    break;
        }

      if (i < dest->num_printers)
        dest = dest->printers[i];
      else
      {
	send_ipp_status(con, IPP_STATUS_CUPS_SEE_OTHER, _("See remote printer."));
        ippAddString(con->response, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, dest->printers[0]->uri);
        return;
      }
    }

   /*
    * Found the printer with the PPD file, now see if there is one...
    */

    if ((con->file = open(filename, O_RDONLY)) < 0)
    {
      send_ipp_status(con, IPP_STATUS_ERROR_NOT_FOUND, _("The PPD file \"%s\" could not be opened: %s"), ippGetString(uri, 0, NULL), strerror(errno));
      return;
    }

    fcntl(con->file, F_SETFD, fcntl(con->file, F_GETFD) | FD_CLOEXEC);

    con->pipe_pid = 0;

    ippSetStatusCode(con->response, IPP_STATUS_OK);
  }
  else
    send_ipp_status(con, IPP_STATUS_ERROR_NOT_FOUND, _("The PPD file \"%s\" could not be found."), ippGetString(uri, 0, NULL));
}