get_printers(cupsd_client_t *con,	/* I - Client connection */
             int            type)	/* I - 0 or CUPS_PRINTER_CLASS */
{
  http_status_t	status;			/* Policy status */
  ipp_attribute_t *attr;		/* Current attribute */
  int		limit;			/* Max number of printers to return */
  int		count;			/* Number of printers that match */
  cupsd_printer_t *printer;		/* Current printer pointer */
  cups_ptype_t	printer_type,		/* printer-type attribute */
		printer_mask;		/* printer-type-mask attribute */
  char		*location;		/* Location string */
  const char	*username;		/* Current user */
  char		*first_printer_name;	/* first-printer-name attribute */
  cups_array_t	*ra;			/* Requested attributes array */
  int		local;			/* Local connection? */


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

 /*
  * Check policy...
  */

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

 /*
  * Check for printers...
  */

  if (!Printers || !cupsArrayCount(Printers))
  {
    send_ipp_status(con, IPP_NOT_FOUND, _("No destinations added."));
    return;
  }

 /*
  * See if they want to limit the number of printers reported...
  */

  if ((attr = ippFindAttribute(con->request, "limit",
                               IPP_TAG_INTEGER)) != NULL)
    limit = attr->values[0].integer;
  else
    limit = 10000000;

  if ((attr = ippFindAttribute(con->request, "first-printer-name",
                               IPP_TAG_NAME)) != NULL)
    first_printer_name = attr->values[0].string.text;
  else
    first_printer_name = NULL;

 /*
  * Support filtering...
  */

  if ((attr = ippFindAttribute(con->request, "printer-type",
                               IPP_TAG_ENUM)) != NULL)
    printer_type = (cups_ptype_t)attr->values[0].integer;
  else
    printer_type = (cups_ptype_t)0;

  if ((attr = ippFindAttribute(con->request, "printer-type-mask",
                               IPP_TAG_ENUM)) != NULL)
    printer_mask = (cups_ptype_t)attr->values[0].integer;
  else
    printer_mask = (cups_ptype_t)0;

  local = httpAddrLocalhost(&(con->clientaddr));

  if ((attr = ippFindAttribute(con->request, "printer-location",
                               IPP_TAG_TEXT)) != NULL)
    location = attr->values[0].string.text;
  else
    location = NULL;

  if (con->username[0])
    username = con->username;
  else if ((attr = ippFindAttribute(con->request, "requesting-user-name",
                                    IPP_TAG_NAME)) != NULL)
    username = attr->values[0].string.text;
  else
    username = NULL;

  ra = create_requested_array(con->request);

 /*
  * OK, build a list of printers for this printer...
  */

  if (first_printer_name)
  {
    if ((printer = cupsdFindDest(first_printer_name)) == NULL)
      printer = (cupsd_printer_t *)cupsArrayFirst(Printers);
  }
  else
    printer = (cupsd_printer_t *)cupsArrayFirst(Printers);

  for (count = 0;
       count < limit && printer;
       printer = (cupsd_printer_t *)cupsArrayNext(Printers))
  {
    if (!local && !printer->shared)
      continue;

    if ((!type || (printer->type & CUPS_PRINTER_CLASS) == type) &&
        (printer->type & printer_mask) == printer_type &&
	(!location ||
	 (printer->location && !_cups_strcasecmp(printer->location, location))))
    {
     /*
      * If a username is specified, see if it is allowed or denied
      * access...
      */

      if (cupsArrayCount(printer->users) && username &&
	  !user_allowed(printer, username))
        continue;

     /*
      * Add the group separator as needed...
      */

      if (count > 0)
        ippAddSeparator(con->response);

      count ++;

     /*
      * Send the attributes...
      */

      copy_printer_attrs(con, printer, ra);
    }
  }

  cupsArrayDelete(ra);

  con->response->request.status.status_code = IPP_OK;
}