get_ppds(cupsd_client_t *con)		/* I - Client connection */
{
  http_status_t		status;		/* Policy status */
  ipp_attribute_t	*limit,		/* Limit attribute */
			*device,	/* ppd-device-id attribute */
			*language,	/* ppd-natural-language attribute */
			*make,		/* ppd-make attribute */
			*model,		/* ppd-make-and-model attribute */
			*model_number,	/* ppd-model-number attribute */
			*product,	/* ppd-product attribute */
			*psversion,	/* ppd-psverion attribute */
			*type,		/* ppd-type attribute */
			*requested,	/* requested-attributes attribute */
			*exclude,	/* exclude-schemes attribute */
			*include;	/* include-schemes attribute */
  char			command[1024],	/* cups-driverd command */
			options[4096],	/* Options to pass to command */
			device_str[256],/* Escaped ppd-device-id string */
			language_str[256],
					/* Escaped ppd-natural-language */
			make_str[256],	/* Escaped ppd-make string */
			model_str[256],	/* Escaped ppd-make-and-model string */
			model_number_str[256],
					/* ppd-model-number string */
			product_str[256],
					/* Escaped ppd-product string */
			psversion_str[256],
					/* Escaped ppd-psversion string */
			type_str[256],	/* Escaped ppd-type string */
			requested_str[256],
					/* String for requested attributes */
			exclude_str[512],
					/* String for excluded schemes */
			include_str[512];
					/* String for included schemes */


  cupsdLogMessage(CUPSD_LOG_DEBUG2, "get_ppds(%p[%d])", con, con->number);

 /*
  * Check policy...
  */

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

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

  limit        = ippFindAttribute(con->request, "limit", IPP_TAG_INTEGER);
  device       = ippFindAttribute(con->request, "ppd-device-id", IPP_TAG_TEXT);
  language     = ippFindAttribute(con->request, "ppd-natural-language",
                                  IPP_TAG_LANGUAGE);
  make         = ippFindAttribute(con->request, "ppd-make", IPP_TAG_TEXT);
  model        = ippFindAttribute(con->request, "ppd-make-and-model",
                                  IPP_TAG_TEXT);
  model_number = ippFindAttribute(con->request, "ppd-model-number",
                                  IPP_TAG_INTEGER);
  product      = ippFindAttribute(con->request, "ppd-product", IPP_TAG_TEXT);
  psversion    = ippFindAttribute(con->request, "ppd-psversion", IPP_TAG_TEXT);
  type         = ippFindAttribute(con->request, "ppd-type", IPP_TAG_KEYWORD);
  requested    = ippFindAttribute(con->request, "requested-attributes",
                                  IPP_TAG_KEYWORD);
  exclude      = ippFindAttribute(con->request, "exclude-schemes",
                                  IPP_TAG_NAME);
  include      = ippFindAttribute(con->request, "include-schemes",
                                  IPP_TAG_NAME);

  if (requested)
    url_encode_attr(requested, requested_str, sizeof(requested_str));
  else
    strlcpy(requested_str, "requested-attributes=all", sizeof(requested_str));

  if (device)
    url_encode_attr(device, device_str, sizeof(device_str));
  else
    device_str[0] = '\0';

  if (language)
    url_encode_attr(language, language_str, sizeof(language_str));
  else
    language_str[0] = '\0';

  if (make)
    url_encode_attr(make, make_str, sizeof(make_str));
  else
    make_str[0] = '\0';

  if (model)
    url_encode_attr(model, model_str, sizeof(model_str));
  else
    model_str[0] = '\0';

  if (model_number)
    snprintf(model_number_str, sizeof(model_number_str), "ppd-model-number=%d",
             model_number->values[0].integer);
  else
    model_number_str[0] = '\0';

  if (product)
    url_encode_attr(product, product_str, sizeof(product_str));
  else
    product_str[0] = '\0';

  if (psversion)
    url_encode_attr(psversion, psversion_str, sizeof(psversion_str));
  else
    psversion_str[0] = '\0';

  if (type)
    url_encode_attr(type, type_str, sizeof(type_str));
  else
    type_str[0] = '\0';

  if (exclude)
    url_encode_attr(exclude, exclude_str, sizeof(exclude_str));
  else
    exclude_str[0] = '\0';

  if (include)
    url_encode_attr(include, include_str, sizeof(include_str));
  else
    include_str[0] = '\0';

  snprintf(command, sizeof(command), "%s/daemon/cups-driverd", ServerBin);
  snprintf(options, sizeof(options),
           "list+%d+%d+%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
           con->request->request.op.request_id,
           limit ? limit->values[0].integer : 0,
	   requested_str,
	   device ? "%20" : "", device_str,
	   language ? "%20" : "", language_str,
	   make ? "%20" : "", make_str,
	   model ? "%20" : "", model_str,
	   model_number ? "%20" : "", model_number_str,
	   product ? "%20" : "", product_str,
	   psversion ? "%20" : "", psversion_str,
	   type ? "%20" : "", type_str,
	   exclude_str[0] ? "%20" : "", exclude_str,
	   include_str[0] ? "%20" : "", include_str);

  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."));
  }
}