copy_printer_attrs(
    cupsd_client_t  *con,		/* I - Client connection */
    cupsd_printer_t *printer,		/* I - Printer */
    cups_array_t    *ra)		/* I - Requested attributes array */
{
  char			printer_uri[HTTP_MAX_URI];
					/* Printer URI */
  char			printer_icons[HTTP_MAX_URI];
					/* Printer icons */
  time_t		curtime;	/* Current time */
  int			i;		/* Looping var */


 /*
  * Copy the printer attributes to the response using requested-attributes
  * and document-format attributes that may be provided by the client.
  */

  curtime = time(NULL);

  if (!ra || cupsArrayFind(ra, "marker-change-time"))
    ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
                  "marker-change-time", printer->marker_time);

  if (printer->num_printers > 0 &&
      (!ra || cupsArrayFind(ra, "member-uris")))
  {
    ipp_attribute_t	*member_uris;	/* member-uris attribute */
    cupsd_printer_t	*p2;		/* Printer in class */
    ipp_attribute_t	*p2_uri;	/* printer-uri-supported for class printer */


    if ((member_uris = ippAddStrings(con->response, IPP_TAG_PRINTER,
                                     IPP_TAG_URI, "member-uris",
				     printer->num_printers, NULL,
				     NULL)) != NULL)
    {
      for (i = 0; i < printer->num_printers; i ++)
      {
        p2 = printer->printers[i];

        if ((p2_uri = ippFindAttribute(p2->attrs, "printer-uri-supported",
	                               IPP_TAG_URI)) != NULL)
          member_uris->values[i].string.text =
	      _cupsStrRetain(p2_uri->values[0].string.text);
        else
	{
	  httpAssembleURIf(HTTP_URI_CODING_ALL, printer_uri,
	                   sizeof(printer_uri), "ipp", NULL, con->clientname,
			   con->clientport,
			   (p2->type & CUPS_PRINTER_CLASS) ?
			       "/classes/%s" : "/printers/%s", p2->name);
	  member_uris->values[i].string.text = _cupsStrAlloc(printer_uri);
        }
      }
    }
  }

  if (printer->alert && (!ra || cupsArrayFind(ra, "printer-alert")))
    ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_STRING,
                 "printer-alert", NULL, printer->alert);

  if (printer->alert_description &&
      (!ra || cupsArrayFind(ra, "printer-alert-description")))
    ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_TEXT,
                 "printer-alert-description", NULL,
		 printer->alert_description);

  if (!ra || cupsArrayFind(ra, "printer-config-change-date-time"))
    ippAddDate(con->response, IPP_TAG_PRINTER, "printer-config-change-date-time", ippTimeToDate(printer->config_time));

  if (!ra || cupsArrayFind(ra, "printer-config-change-time"))
    ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
                  "printer-config-change-time", printer->config_time);

  if (!ra || cupsArrayFind(ra, "printer-current-time"))
    ippAddDate(con->response, IPP_TAG_PRINTER, "printer-current-time",
               ippTimeToDate(curtime));

#if defined(HAVE_DNSSD) || defined(HAVE_AVAHI)
  if (!ra || cupsArrayFind(ra, "printer-dns-sd-name"))
  {
    if (printer->reg_name)
      ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_NAME,
                   "printer-dns-sd-name", NULL, printer->reg_name);
    else
      ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_NOVALUE,
                   "printer-dns-sd-name", 0);
  }
#endif /* HAVE_DNSSD || HAVE_AVAHI */

  if (!ra || cupsArrayFind(ra, "printer-error-policy"))
    ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_NAME,
        	 "printer-error-policy", NULL, printer->error_policy);

  if (!ra || cupsArrayFind(ra, "printer-error-policy-supported"))
  {
    static const char * const errors[] =/* printer-error-policy-supported values */
		  {
		    "abort-job",
		    "retry-current-job",
		    "retry-job",
		    "stop-printer"
		  };

    if (printer->type & CUPS_PRINTER_CLASS)
      ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_NAME | IPP_TAG_COPY,
                   "printer-error-policy-supported", NULL, "retry-current-job");
    else
      ippAddStrings(con->response, IPP_TAG_PRINTER, IPP_TAG_NAME | IPP_TAG_COPY,
		    "printer-error-policy-supported",
		    sizeof(errors) / sizeof(errors[0]), NULL, errors);
  }

  if (!ra || cupsArrayFind(ra, "printer-icons"))
  {
    httpAssembleURIf(HTTP_URI_CODING_ALL, printer_icons, sizeof(printer_icons),
                     "http", NULL, con->clientname, con->clientport,
		     "/icons/%s.png", printer->name);
    ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-icons",
                 NULL, printer_icons);
    cupsdLogMessage(CUPSD_LOG_DEBUG2, "printer-icons=\"%s\"", printer_icons);
  }

  if (!ra || cupsArrayFind(ra, "printer-is-accepting-jobs"))
    ippAddBoolean(con->response, IPP_TAG_PRINTER, "printer-is-accepting-jobs", (char)printer->accepting);

  if (!ra || cupsArrayFind(ra, "printer-is-shared"))
    ippAddBoolean(con->response, IPP_TAG_PRINTER, "printer-is-shared", (char)printer->shared);

  if (!ra || cupsArrayFind(ra, "printer-is-temporary"))
    ippAddBoolean(con->response, IPP_TAG_PRINTER, "printer-is-temporary", (char)printer->temporary);

  if (!ra || cupsArrayFind(ra, "printer-more-info"))
  {
    httpAssembleURIf(HTTP_URI_CODING_ALL, printer_uri, sizeof(printer_uri),
                     "http", NULL, con->clientname, con->clientport,
		     (printer->type & CUPS_PRINTER_CLASS) ?
		         "/classes/%s" : "/printers/%s", printer->name);
    ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_URI,
        	 "printer-more-info", NULL, printer_uri);
  }

  if (!ra || cupsArrayFind(ra, "printer-op-policy"))
    ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_NAME,
        	 "printer-op-policy", NULL, printer->op_policy);

  if (!ra || cupsArrayFind(ra, "printer-state"))
    ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state",
                  printer->state);

  if (!ra || cupsArrayFind(ra, "printer-state-change-date-time"))
    ippAddDate(con->response, IPP_TAG_PRINTER, "printer-state-change-date-time", ippTimeToDate(printer->state_time));

  if (!ra || cupsArrayFind(ra, "printer-state-change-time"))
    ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
                  "printer-state-change-time", printer->state_time);

  if (!ra || cupsArrayFind(ra, "printer-state-message"))
    ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_TEXT,
        	 "printer-state-message", NULL, printer->state_message);

  if (!ra || cupsArrayFind(ra, "printer-state-reasons"))
    add_printer_state_reasons(con, printer);

  if (!ra || cupsArrayFind(ra, "printer-type"))
  {
    cups_ptype_t type;			/* printer-type value */

   /*
    * Add the CUPS-specific printer-type attribute...
    */

    type = printer->type;

    if (printer == DefaultPrinter)
      type |= CUPS_PRINTER_DEFAULT;

    if (!printer->accepting)
      type |= CUPS_PRINTER_REJECTING;

    if (!printer->shared)
      type |= CUPS_PRINTER_NOT_SHARED;

    ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-type", (int)type);
  }

  if (!ra || cupsArrayFind(ra, "printer-up-time"))
    ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
                  "printer-up-time", curtime);

  if (!ra || cupsArrayFind(ra, "printer-uri-supported"))
  {
    httpAssembleURIf(HTTP_URI_CODING_ALL, printer_uri, sizeof(printer_uri),
                     "ipp", NULL, con->clientname, con->clientport,
		     (printer->type & CUPS_PRINTER_CLASS) ?
		         "/classes/%s" : "/printers/%s", printer->name);
    ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_URI,
        	 "printer-uri-supported", NULL, printer_uri);
    cupsdLogMessage(CUPSD_LOG_DEBUG2, "printer-uri-supported=\"%s\"",
                    printer_uri);
  }

  if (!ra || cupsArrayFind(ra, "queued-job-count"))
    add_queued_job_count(con, printer);

  copy_attrs(con->response, printer->attrs, ra, IPP_TAG_ZERO, 0, NULL);
  if (printer->ppd_attrs)
    copy_attrs(con->response, printer->ppd_attrs, ra, IPP_TAG_ZERO, 0, NULL);
  copy_attrs(con->response, CommonData, ra, IPP_TAG_ZERO, IPP_TAG_COPY, NULL);
}