set_printer_defaults(
    cupsd_client_t  *con,		/* I - Client connection */
    cupsd_printer_t *printer)		/* I - Printer */
{
  int			i;		/* Looping var */
  ipp_attribute_t 	*attr;		/* Current attribute */
  size_t		namelen;	/* Length of attribute name */
  char			name[256],	/* New attribute name */
			value[256];	/* String version of integer attrs */


  for (attr = con->request->attrs; attr; attr = attr->next)
  {
   /*
    * Skip non-printer attributes...
    */

    if (attr->group_tag != IPP_TAG_PRINTER || !attr->name)
      continue;

    cupsdLogMessage(CUPSD_LOG_DEBUG2, "set_printer_defaults: %s", attr->name);

    if (!strcmp(attr->name, "job-sheets-default"))
    {
     /*
      * Only allow keywords and names...
      */

      if (attr->value_tag != IPP_TAG_NAME && attr->value_tag != IPP_TAG_KEYWORD)
        continue;

     /*
      * Only allow job-sheets-default to be set when running without a
      * system high classification level...
      */

      if (Classification)
        continue;

      cupsdSetString(&printer->job_sheets[0], attr->values[0].string.text);

      if (attr->num_values > 1)
	cupsdSetString(&printer->job_sheets[1], attr->values[1].string.text);
      else
	cupsdSetString(&printer->job_sheets[1], "none");
    }
    else if (!strcmp(attr->name, "requesting-user-name-allowed"))
    {
      cupsdFreeStrings(&(printer->users));

      printer->deny_users = 0;

      if (attr->value_tag == IPP_TAG_NAME &&
          (attr->num_values > 1 ||
	   strcmp(attr->values[0].string.text, "all")))
      {
	for (i = 0; i < attr->num_values; i ++)
	  cupsdAddString(&(printer->users), attr->values[i].string.text);
      }
    }
    else if (!strcmp(attr->name, "requesting-user-name-denied"))
    {
      cupsdFreeStrings(&(printer->users));

      printer->deny_users = 1;

      if (attr->value_tag == IPP_TAG_NAME &&
          (attr->num_values > 1 ||
	   strcmp(attr->values[0].string.text, "none")))
      {
	for (i = 0; i < attr->num_values; i ++)
	  cupsdAddString(&(printer->users), attr->values[i].string.text);
      }
    }
    else if (!strcmp(attr->name, "job-quota-period"))
    {
      if (attr->value_tag != IPP_TAG_INTEGER)
        continue;

      cupsdLogMessage(CUPSD_LOG_DEBUG, "Setting job-quota-period to %d...",
        	      attr->values[0].integer);
      cupsdFreeQuotas(printer);

      printer->quota_period = attr->values[0].integer;
    }
    else if (!strcmp(attr->name, "job-k-limit"))
    {
      if (attr->value_tag != IPP_TAG_INTEGER)
        continue;

      cupsdLogMessage(CUPSD_LOG_DEBUG, "Setting job-k-limit to %d...",
        	      attr->values[0].integer);
      cupsdFreeQuotas(printer);

      printer->k_limit = attr->values[0].integer;
    }
    else if (!strcmp(attr->name, "job-page-limit"))
    {
      if (attr->value_tag != IPP_TAG_INTEGER)
        continue;

      cupsdLogMessage(CUPSD_LOG_DEBUG, "Setting job-page-limit to %d...",
        	      attr->values[0].integer);
      cupsdFreeQuotas(printer);

      printer->page_limit = attr->values[0].integer;
    }
    else if (!strcmp(attr->name, "printer-op-policy"))
    {
      cupsd_policy_t *p;		/* Policy */


      if (attr->value_tag != IPP_TAG_NAME)
        continue;

      if ((p = cupsdFindPolicy(attr->values[0].string.text)) != NULL)
      {
	cupsdLogMessage(CUPSD_LOG_DEBUG,
                	"Setting printer-op-policy to \"%s\"...",
                	attr->values[0].string.text);
	cupsdSetString(&printer->op_policy, attr->values[0].string.text);
	printer->op_policy_ptr = p;
      }
      else
      {
	send_ipp_status(con, IPP_NOT_POSSIBLE,
                	_("Unknown printer-op-policy \"%s\"."),
                	attr->values[0].string.text);
	return (0);
      }
    }
    else if (!strcmp(attr->name, "printer-error-policy"))
    {
      if (attr->value_tag != IPP_TAG_NAME && attr->value_tag != IPP_TAG_KEYWORD)
        continue;

      if (strcmp(attr->values[0].string.text, "retry-current-job") &&
          ((printer->type & CUPS_PRINTER_CLASS) ||
	   (strcmp(attr->values[0].string.text, "abort-job") &&
	    strcmp(attr->values[0].string.text, "retry-job") &&
	    strcmp(attr->values[0].string.text, "stop-printer"))))
      {
	send_ipp_status(con, IPP_NOT_POSSIBLE,
                	_("Unknown printer-error-policy \"%s\"."),
                	attr->values[0].string.text);
	return (0);
      }

      cupsdLogMessage(CUPSD_LOG_DEBUG,
                      "Setting printer-error-policy to \"%s\"...",
                      attr->values[0].string.text);
      cupsdSetString(&printer->error_policy, attr->values[0].string.text);
    }

   /*
    * Skip any other non-default attributes...
    */

    namelen = strlen(attr->name);
    if (namelen < 9 || strcmp(attr->name + namelen - 8, "-default") ||
        namelen > (sizeof(name) - 1) || attr->num_values != 1)
      continue;

   /*
    * OK, anything else must be a user-defined default...
    */

    strlcpy(name, attr->name, sizeof(name));
    name[namelen - 8] = '\0';		/* Strip "-default" */

    switch (attr->value_tag)
    {
      case IPP_TAG_DELETEATTR :
          printer->num_options = cupsRemoveOption(name,
						  printer->num_options,
						  &(printer->options));
          cupsdLogMessage(CUPSD_LOG_DEBUG,
	                  "Deleting %s", attr->name);
          break;

      case IPP_TAG_NAME :
      case IPP_TAG_TEXT :
      case IPP_TAG_KEYWORD :
      case IPP_TAG_URI :
          printer->num_options = cupsAddOption(name,
	                                       attr->values[0].string.text,
					       printer->num_options,
					       &(printer->options));
          cupsdLogMessage(CUPSD_LOG_DEBUG,
	                  "Setting %s to \"%s\"...", attr->name,
			  attr->values[0].string.text);
          break;

      case IPP_TAG_BOOLEAN :
          printer->num_options = cupsAddOption(name,
	                                       attr->values[0].boolean ?
					           "true" : "false",
					       printer->num_options,
					       &(printer->options));
          cupsdLogMessage(CUPSD_LOG_DEBUG,
	                  "Setting %s to %s...", attr->name,
			  attr->values[0].boolean ? "true" : "false");
          break;

      case IPP_TAG_INTEGER :
      case IPP_TAG_ENUM :
          sprintf(value, "%d", attr->values[0].integer);
          printer->num_options = cupsAddOption(name, value,
					       printer->num_options,
					       &(printer->options));
          cupsdLogMessage(CUPSD_LOG_DEBUG,
	                  "Setting %s to %s...", attr->name, value);
          break;

      case IPP_TAG_RANGE :
          sprintf(value, "%d-%d", attr->values[0].range.lower,
	          attr->values[0].range.upper);
          printer->num_options = cupsAddOption(name, value,
					       printer->num_options,
					       &(printer->options));
          cupsdLogMessage(CUPSD_LOG_DEBUG,
	                  "Setting %s to %s...", attr->name, value);
          break;

      case IPP_TAG_RESOLUTION :
          sprintf(value, "%dx%d%s", attr->values[0].resolution.xres,
	          attr->values[0].resolution.yres,
		  attr->values[0].resolution.units == IPP_RES_PER_INCH ?
		      "dpi" : "dpcm");
          printer->num_options = cupsAddOption(name, value,
					       printer->num_options,
					       &(printer->options));
          cupsdLogMessage(CUPSD_LOG_DEBUG,
	                  "Setting %s to %s...", attr->name, value);
          break;

      default :
          /* Do nothing for other values */
	  break;
    }
  }

  return (1);
}