Exemple #1
0
server_jreason_t			/* O - Bits */
serverGetJobStateReasonsBits(
    ipp_attribute_t *attr)		/* I - "job-state-reasons" attribute */
{
  int			i, j,		/* Looping vars */
			count;		/* Number of "job-state-reasons" values */
  const char		*keyword;	/* "job-state-reasons" value */
  server_jreason_t	jreasons = SERVER_JREASON_NONE;
					/* Bits for "job-state-reasons" values */


  count = ippGetCount(attr);
  for (i = 0; i < count; i ++)
  {
    keyword = ippGetString(attr, i, NULL);

    for (j = 0; j < (int)(sizeof(server_jreasons) / sizeof(server_jreasons[0])); j ++)
    {
      if (!strcmp(keyword, server_jreasons[j]))
      {
        jreasons |= (server_jreason_t)(1 << j);
	break;
      }
    }
  }

  return (jreasons);
}
Exemple #2
0
const char *
gtk_cups_request_ipp_get_string (GtkCupsRequest *request,
                                 ipp_tag_t       tag,
                                 const char     *name)
{
  ipp_attribute_t *attribute = NULL;

  if (request != NULL && request->ipp_request != NULL)
    attribute = ippFindAttribute (request->ipp_request,
                                  name,
                                  tag);

  if (attribute != NULL && ippGetCount (attribute) > 0)
      return ippGetString (attribute, 0, NULL);
  else
    return NULL;
}
std::unordered_set<std::string> destination_implObj::supported_options() const
{
	std::unordered_set<std::string> s;

	info_t::lock lock{*this};

	auto attrs=cupsFindDestSupported(lock->http, lock->dest,
					 lock->info,
					 "job-creation-attributes");

	if (!attrs)
		return s;

	auto count=ippGetCount(attrs);

	for (decltype (count) i=0; i<count; i++)
	{
		s.insert(ippGetString(attrs, i, nullptr));
	}
	return s;
}
Exemple #4
0
int					/* O - Exit status */
main(int  argc,				/* I - Number of command-line args */
     char *argv[])			/* I - Command-line arguments */
{
  ipp_t			*msg;		/* Event message from scheduler */
  ipp_state_t		state;		/* IPP event state */
  struct sigaction	action;		/* POSIX sigaction data */
  DBusConnection	*con = NULL;	/* Connection to DBUS server */
  DBusError		error;		/* Error, if any */
  DBusMessage		*message;	/* Message to send */
  DBusMessageIter	iter;		/* Iterator for message data */
  int			lock_fd = -1;	/* Lock file descriptor */


 /*
  * Don't buffer stderr...
  */

  setbuf(stderr, NULL);

 /*
  * Ignore SIGPIPE signals...
  */

  memset(&action, 0, sizeof(action));
  action.sa_handler = SIG_IGN;
  sigaction(SIGPIPE, &action, NULL);

 /*
  * Validate command-line options...
  */

  if (argc != 3)
  {
    fputs("Usage: dbus dbus:/// notify-user-data\n", stderr);
    return (1);
  }

  if (strncmp(argv[1], "dbus:", 5))
  {
    fprintf(stderr, "ERROR: Bad URI \"%s\"!\n", argv[1]);
    return (1);
  }

 /*
  * Loop forever until we run out of events...
  */

  for (;;)
  {
    ipp_attribute_t	*attr;		/* Current attribute */
    const char		*event;		/* Event name */
    const char		*signame = NULL;/* DBUS signal name */
    char		*printer_reasons = NULL;
					/* Printer reasons string */
    char		*job_reasons = NULL;
					/* Job reasons string */
    const char		*nul = "";	/* Empty string value */
    int			no = 0;		/* Boolean "no" value */
    int			params = PARAMS_NONE;
					/* What parameters to include? */


   /*
    * Get the next event...
    */

    msg = ippNew();
    while ((state = ippReadFile(0, msg)) != IPP_DATA)
    {
      if (state <= IPP_IDLE)
        break;
    }

    fprintf(stderr, "DEBUG: state=%d\n", state);

    if (state == IPP_ERROR)
      fputs("DEBUG: ippReadFile() returned IPP_ERROR!\n", stderr);

    if (state <= IPP_IDLE)
    {
     /*
      * Out of messages, free memory and then exit...
      */

      ippDelete(msg);
      break;
    }

   /*
    * Verify connection to DBUS server...
    */

    if (con && !dbus_connection_get_is_connected(con))
    {
      dbus_connection_unref(con);
      con = NULL;
    }

    if (!con)
    {
      dbus_error_init(&error);

      con = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
      if (!con)
	dbus_error_free(&error);
      else
	fputs("DEBUG: Connected to D-BUS\n", stderr);
    }

    if (!con)
      continue;

    if (lock_fd == -1 &&
        acquire_lock(&lock_fd, lock_filename, sizeof(lock_filename)))
      continue;

    attr = ippFindAttribute(msg, "notify-subscribed-event",
			    IPP_TAG_KEYWORD);
    if (!attr)
      continue;

    event = ippGetString(attr, 0, NULL);
    if (!strncmp(event, "server-", 7))
    {
      const char *word2 = event + 7;	/* Second word */

      if (!strcmp(word2, "restarted"))
	signame = "ServerRestarted";
      else if (!strcmp(word2, "started"))
	signame = "ServerStarted";
      else if (!strcmp(word2, "stopped"))
	signame = "ServerStopped";
      else if (!strcmp(word2, "audit"))
	signame = "ServerAudit";
      else
	continue;
    }
    else if (!strncmp(event, "printer-", 8))
    {
      const char *word2 = event + 8;	/* Second word */

      params = PARAMS_PRINTER;
      if (!strcmp(word2, "restarted"))
	signame = "PrinterRestarted";
      else if (!strcmp(word2, "shutdown"))
	signame = "PrinterShutdown";
      else if (!strcmp(word2, "stopped"))
	signame = "PrinterStopped";
      else if (!strcmp(word2, "state-changed"))
	signame = "PrinterStateChanged";
      else if (!strcmp(word2, "finishings-changed"))
	signame = "PrinterFinishingsChanged";
      else if (!strcmp(word2, "media-changed"))
	signame = "PrinterMediaChanged";
      else if (!strcmp(word2, "added"))
	signame = "PrinterAdded";
      else if (!strcmp(word2, "deleted"))
	signame = "PrinterDeleted";
      else if (!strcmp(word2, "modified"))
	signame = "PrinterModified";
      else
	continue;
    }
    else if (!strncmp(event, "job-", 4))
    {
      const char *word2 = event + 4;	/* Second word */

      params = PARAMS_JOB;
      if (!strcmp(word2, "state-changed"))
	signame = "JobState";
      else if (!strcmp(word2, "created"))
	signame = "JobCreated";
      else if (!strcmp(word2, "completed"))
	signame = "JobCompleted";
      else if (!strcmp(word2, "stopped"))
	signame = "JobStopped";
      else if (!strcmp(word2, "config-changed"))
	signame = "JobConfigChanged";
      else if (!strcmp(word2, "progress"))
	signame = "JobProgress";
      else
	continue;
    }
    else
      continue;

    /*
     * Create and send the new message...
     */

    fprintf(stderr, "DEBUG: %s\n", signame);
    message = dbus_message_new_signal("/org/cups/cupsd/Notifier",
				      "org.cups.cupsd.Notifier",
				      signame);

    dbus_message_append_iter_init(message, &iter);
    attr = ippFindAttribute(msg, "notify-text", IPP_TAG_TEXT);
    if (attr)
    {
      const char *val = ippGetString(attr, 0, NULL);
      if (!dbus_message_iter_append_string(&iter, &val))
        goto bail;
    }
    else
      goto bail;

    if (params >= PARAMS_PRINTER)
    {
      char	*p;			/* Pointer into printer_reasons */
      size_t	reasons_length;		/* Required size of printer_reasons */
      int	i;			/* Looping var */
      int	have_printer_params = 1;/* Do we have printer URI? */

      /* STRING printer-uri or "" */
      attr = ippFindAttribute(msg, "notify-printer-uri", IPP_TAG_URI);
      if (attr)
      {
        const char *val = ippGetString(attr, 0, NULL);
        if (!dbus_message_iter_append_string(&iter, &val))
	  goto bail;
      }
      else
      {
	have_printer_params = 0;
	dbus_message_iter_append_string(&iter, &nul);
      }

      /* STRING printer-name */
      if (have_printer_params)
      {
	attr = ippFindAttribute(msg, "printer-name", IPP_TAG_NAME);
        if (attr)
        {
          const char *val = ippGetString(attr, 0, NULL);
          if (!dbus_message_iter_append_string(&iter, &val))
            goto bail;
        }
        else
          goto bail;
      }
      else
	dbus_message_iter_append_string(&iter, &nul);

      /* UINT32 printer-state */
      if (have_printer_params)
      {
	attr = ippFindAttribute(msg, "printer-state", IPP_TAG_ENUM);
	if (attr)
	{
	  dbus_uint32_t val = ippGetInteger(attr, 0);
	  dbus_message_iter_append_uint32(&iter, &val);
	}
	else
	  goto bail;
      }
      else
	dbus_message_iter_append_uint32(&iter, &no);

      /* STRING printer-state-reasons */
      if (have_printer_params)
      {
	attr = ippFindAttribute(msg, "printer-state-reasons",
				IPP_TAG_KEYWORD);
	if (attr)
	{
	  int num_values = ippGetCount(attr);
	  for (reasons_length = 0, i = 0; i < num_values; i++)
	    /* All need commas except the last, which needs a nul byte. */
	    reasons_length += 1 + strlen(ippGetString(attr, i, NULL));
	  printer_reasons = malloc(reasons_length);
	  if (!printer_reasons)
	    goto bail;
	  p = printer_reasons;
	  for (i = 0; i < num_values; i++)
	  {
	    if (i)
	      *p++ = ',';

	    strlcpy(p, ippGetString(attr, i, NULL),
	            reasons_length - (p - printer_reasons));
	    p += strlen(p);
	  }
	  if (!dbus_message_iter_append_string(&iter, &printer_reasons))
	    goto bail;
	}
	else
	  goto bail;
      }
      else
	dbus_message_iter_append_string(&iter, &nul);

      /* BOOL printer-is-accepting-jobs */
      if (have_printer_params)
      {
	attr = ippFindAttribute(msg, "printer-is-accepting-jobs",
				IPP_TAG_BOOLEAN);
	if (attr)
	{
	  dbus_bool_t val = ippGetBoolean(attr, 0);
	  dbus_message_iter_append_boolean(&iter, &val);
	}
	else
	  goto bail;
      }
      else
	dbus_message_iter_append_boolean(&iter, &no);
    }

    if (params >= PARAMS_JOB)
    {
      char	*p;			/* Pointer into job_reasons */
      size_t	reasons_length;		/* Required size of job_reasons */
      int	i;			/* Looping var */

      /* UINT32 job-id */
      attr = ippFindAttribute(msg, "notify-job-id", IPP_TAG_INTEGER);
      if (attr)
      {
        dbus_uint32_t val = ippGetInteger(attr, 0);
        dbus_message_iter_append_uint32(&iter, &val);
      }
      else
	goto bail;

      /* UINT32 job-state */
      attr = ippFindAttribute(msg, "job-state", IPP_TAG_ENUM);
      if (attr)
      {
        dbus_uint32_t val = ippGetInteger(attr, 0);
        dbus_message_iter_append_uint32(&iter, &val);
      }
      else
	goto bail;

      /* STRING job-state-reasons */
      attr = ippFindAttribute(msg, "job-state-reasons", IPP_TAG_KEYWORD);
      if (attr)
      {
	int num_values = ippGetCount(attr);
	for (reasons_length = 0, i = 0; i < num_values; i++)
	  /* All need commas except the last, which needs a nul byte. */
	  reasons_length += 1 + strlen(ippGetString(attr, i, NULL));
	job_reasons = malloc(reasons_length);
	if (!job_reasons)
	  goto bail;
	p = job_reasons;
	for (i = 0; i < num_values; i++)
	{
	  if (i)
	    *p++ = ',';

	  strlcpy(p, ippGetString(attr, i, NULL),
	          reasons_length - (p - job_reasons));
	  p += strlen(p);
	}
	if (!dbus_message_iter_append_string(&iter, &job_reasons))
	  goto bail;
      }
      else
	goto bail;

      /* STRING job-name or "" */
      attr = ippFindAttribute(msg, "job-name", IPP_TAG_NAME);
      if (attr)
      {
        const char *val = ippGetString(attr, 0, NULL);
        if (!dbus_message_iter_append_string(&iter, &val))
          goto bail;
      }
      else
	dbus_message_iter_append_string(&iter, &nul);

      /* UINT32 job-impressions-completed */
      attr = ippFindAttribute(msg, "job-impressions-completed",
			      IPP_TAG_INTEGER);
      if (attr)
      {
        dbus_uint32_t val = ippGetInteger(attr, 0);
        dbus_message_iter_append_uint32(&iter, &val);
      }
      else
	goto bail;
    }

    dbus_connection_send(con, message, NULL);
    dbus_connection_flush(con);

   /*
    * Cleanup...
    */

    bail:

    dbus_message_unref(message);

    if (printer_reasons)
      free(printer_reasons);

    if (job_reasons)
      free(job_reasons);

    ippDelete(msg);
  }

 /*
  * Remove lock file...
  */

  if (lock_fd >= 0)
  {
    close(lock_fd);
    release_lock();
  }

  return (0);
}
static void
_pp_maintenance_command_execute_thread (GSimpleAsyncResult *res,
                                        GObject            *object,
                                        GCancellable       *cancellable)
{
  PpMaintenanceCommand        *command = (PpMaintenanceCommand *) object;
  PpMaintenanceCommandPrivate *priv = command->priv;
  static const char           *attrs[] = {"printer-commands"};
  ipp_attribute_t             *attr = NULL;
  gboolean                     success = FALSE;
  GError                      *error = NULL;
  ipp_t                       *request;
  ipp_t                       *response = NULL;
  gchar                       *printer_uri;
  gchar                       *printer_commands = NULL;
  gchar                       *printer_commands_lowercase = NULL;
  gchar                       *command_lowercase;
  gchar                       *file_name = NULL;
  int                          fd = -1;

  printer_uri = g_strdup_printf ("ipp://localhost/printers/%s",
                                 priv->printer_name);

  request = ippNewRequest (IPP_GET_PRINTER_ATTRIBUTES);
  ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_URI,
                "printer-uri", NULL, printer_uri);
  ippAddStrings (request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
                 "requested-attributes", 1, NULL, attrs);
  response = cupsDoRequest (CUPS_HTTP_DEFAULT, request, "/");

  if (response)
    {
      if (ippGetStatusCode (response) <= IPP_OK_CONFLICT)
        {
          attr = ippFindAttribute (response, "printer-commands", IPP_TAG_ZERO);
          if (attr && ippGetCount (attr) > 0 && ippGetValueTag (attr) != IPP_TAG_NOVALUE)
            {
              if (ippGetValueTag (attr) == IPP_TAG_KEYWORD)
                {
                  printer_commands = g_strdup (ippGetString (attr, 0, NULL));
                }
            }
          else
            {
              success = TRUE;
            }
        }

      ippDelete (response);
    }

  if (printer_commands)
    {
      command_lowercase = g_ascii_strdown (priv->command, -1);
      printer_commands_lowercase = g_ascii_strdown (printer_commands, -1);

      if (g_strrstr (printer_commands_lowercase, command_lowercase))
        {
          request = ippNewRequest (IPP_PRINT_JOB);

          ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_URI,
                        "printer-uri", NULL, printer_uri);
          ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_NAME,
                        "job-name", NULL, priv->title);
          ippAddString (request, IPP_TAG_JOB, IPP_TAG_MIMETYPE,
                        "document-format", NULL, "application/vnd.cups-command");

          fd = g_file_open_tmp ("ccXXXXXX", &file_name, &error);

          if (fd != -1)
            {
              FILE *file;

              file = fdopen (fd, "w");
              fprintf (file, "#CUPS-COMMAND\n");
              fprintf (file, "%s\n", priv->command);
              fclose (file);

              response = cupsDoFileRequest (CUPS_HTTP_DEFAULT, request, "/", file_name);
              g_unlink (file_name);

              if (response)
                {
                  if (ippGetStatusCode (response) <= IPP_OK_CONFLICT)
                    {
                      success = TRUE;
                    }

                  ippDelete (response);
                }
            }

          g_free (file_name);
        }
      else
        {
          success = TRUE;
        }

      g_free (command_lowercase);
      g_free (printer_commands_lowercase);
      g_free (printer_commands);
    }

  g_free (printer_uri);

  if (!success)
    {
      g_simple_async_result_set_error (res,
                                       G_IO_ERROR,
                                       G_IO_ERROR_FAILED,
                                       "Execution of maintenance command failed.");
    }

  g_simple_async_result_set_op_res_gboolean (res, success);
}
bool iprint_cache_reload(void)
{
	http_t		*http = NULL;		/* HTTP connection to server */
	ipp_t		*request = NULL,	/* IPP Request */
			*response = NULL;	/* IPP Response */
	ipp_attribute_t	*attr;			/* Current attribute */
	cups_lang_t	*language = NULL;	/* Default language */
	int		i;
	bool ret = False;

	DEBUG(5, ("reloading iprint printcap cache\n"));

       /*
	* Make sure we don't ask for passwords...
	*/

	cupsSetPasswordCB(iprint_passwd_cb);

       /*
	* Try to connect to the server...
	*/

	if ((http = httpConnect(iprint_server(), ippPort())) == NULL) {
		DEBUG(0,("Unable to connect to iPrint server %s - %s\n", 
			 iprint_server(), strerror(errno)));
		goto out;
	}

       /*
	* Build a OPERATION_NOVELL_LIST_PRINTERS request, which requires the following attributes:
	*
	*    attributes-charset
	*    attributes-natural-language
	*/

	request = ippNew();

	ippSetOperation(request, (ipp_op_t)OPERATION_NOVELL_LIST_PRINTERS);
	ippSetRequestId(request, 1);

	language = cupsLangDefault();

	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
	             "attributes-charset", NULL, "utf-8");

	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
	             "attributes-natural-language", NULL, language->language);

	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
	             "ipp-server", NULL, "ippSrvr");

       /*
	* Do the request and get back a response...
	*/

	if ((response = cupsDoRequest(http, request, "/ipp")) == NULL) {
		DEBUG(0,("Unable to get printer list - %s\n",
			 ippErrorString(cupsLastError())));
		goto out;
	}

	for (attr = ippFirstAttribute(response); attr != NULL;) {
	       /*
		* Skip leading attributes until we hit a printer...
		*/

		while (attr != NULL && ippGetGroupTag(attr) != IPP_TAG_PRINTER)
			attr = ippNextAttribute(response);

		if (attr == NULL)
			break;

	       /*
		* Pull the needed attributes from this printer...
		*/

		while (attr != NULL && ippGetGroupTag(attr) == IPP_TAG_PRINTER)
		{
			if (strcmp(ippGetName(attr), "printer-name") == 0 &&
			    (ippGetValueTag(attr) == IPP_TAG_URI ||
			     ippGetValueTag(attr) == IPP_TAG_NAME ||
			     ippGetValueTag(attr) == IPP_TAG_TEXT ||
			     ippGetValueTag(attr) == IPP_TAG_NAMELANG ||
			     ippGetValueTag(attr) == IPP_TAG_TEXTLANG))
			{
				for (i = 0; i<ippGetCount(attr); i++)
				{
					char *url = ippGetString(attr, i, NULL);
					if (!url || !strlen(url))
						continue;
					iprint_cache_add_printer(http, i+2, url);
				}
			}
			attr = ippNextAttribute(response);
		}
	}

	ret = True;

 out:
	if (response)
		ippDelete(response);

	if (language)
		cupsLangFree(language);

	if (http)
		httpClose(http);

	return ret;
}
Exemple #7
0
static void
show_supported(http_t       *http,	/* I - Connection to destination */
	       cups_dest_t  *dest,	/* I - Destination */
	       cups_dinfo_t *dinfo,	/* I - Destination information */
	       const char   *option,	/* I - Option, if any */
	       const char   *value)	/* I - Value, if any */
{
  ipp_attribute_t	*attr;		/* Attribute */
  int			i,		/* Looping var */
			count;		/* Number of values */


  if (!option)
  {
    attr = cupsFindDestSupported(http, dest, dinfo, "job-creation-attributes");
    if (attr)
    {
      count = ippGetCount(attr);
      for (i = 0; i < count; i ++)
        show_supported(http, dest, dinfo, ippGetString(attr, i, NULL), NULL);
    }
    else
    {
      static const char * const options[] =
      {					/* List of standard options */
        CUPS_COPIES,
	CUPS_FINISHINGS,
	CUPS_MEDIA,
	CUPS_NUMBER_UP,
	CUPS_ORIENTATION,
	CUPS_PRINT_COLOR_MODE,
	CUPS_PRINT_QUALITY,
	CUPS_SIDES
      };

      puts("No job-creation-attributes-supported attribute, probing instead.");

      for (i = 0; i < (int)(sizeof(options) / sizeof(options[0])); i ++)
        if (cupsCheckDestSupported(http, dest, dinfo, options[i], NULL))
	  show_supported(http, dest, dinfo, options[i], NULL);
    }
  }
  else if (!value)
  {
    printf("%s (%s)\n", option, cupsCheckDestSupported(http, dest, dinfo, option, NULL) ? "supported" : "not-supported");

    if ((attr = cupsFindDestSupported(http, dest, dinfo, option)) != NULL)
    {
      count = ippGetCount(attr);

      switch (ippGetValueTag(attr))
      {
        case IPP_TAG_INTEGER :
	    for (i = 0; i < count; i ++)
              printf("  %d\n", ippGetInteger(attr, i));
	    break;

        case IPP_TAG_ENUM :
	    for (i = 0; i < count; i ++)
              printf("  %s\n", ippEnumString(option, ippGetInteger(attr, i)));
	    break;

        case IPP_TAG_RANGE :
	    for (i = 0; i < count; i ++)
	    {
	      int upper, lower = ippGetRange(attr, i, &upper);

              printf("  %d-%d\n", lower, upper);
	    }
	    break;

        case IPP_TAG_RESOLUTION :
	    for (i = 0; i < count; i ++)
	    {
	      int xres, yres;
	      ipp_res_t units;
	      xres = ippGetResolution(attr, i, &yres, &units);

              if (xres == yres)
                printf("  %d%s\n", xres, units == IPP_RES_PER_INCH ? "dpi" : "dpcm");
	      else
                printf("  %dx%d%s\n", xres, yres, units == IPP_RES_PER_INCH ? "dpi" : "dpcm");
	    }
	    break;

	case IPP_TAG_TEXTLANG :
	case IPP_TAG_NAMELANG :
	case IPP_TAG_TEXT :
	case IPP_TAG_NAME :
	case IPP_TAG_KEYWORD :
	case IPP_TAG_URI :
	case IPP_TAG_URISCHEME :
	case IPP_TAG_CHARSET :
	case IPP_TAG_LANGUAGE :
	case IPP_TAG_MIMETYPE :
	    for (i = 0; i < count; i ++)
              printf("  %s\n", ippGetString(attr, i, NULL));
	    break;

        case IPP_TAG_STRING :
	    for (i = 0; i < count; i ++)
	    {
	      int j, len;
	      unsigned char *data = ippGetOctetString(attr, i, &len);

              fputs("  ", stdout);
	      for (j = 0; j < len; j ++)
	      {
	        if (data[j] < ' ' || data[j] >= 0x7f)
		  printf("<%02X>", data[j]);
		else
		  putchar(data[j]);
              }
              putchar('\n');
	    }
	    break;

        case IPP_TAG_BOOLEAN :
	    break;

        default :
	    printf("  %s\n", ippTagString(ippGetValueTag(attr)));
	    break;
      }
    }

  }
  else if (cupsCheckDestSupported(http, dest, dinfo, option, value))
    puts("YES");
  else
    puts("NO");
}
option_values_t
destination_implObj::parse_attribute_values(info_t::lock &lock,
					    ipp_attribute_t *attrs,
					    const char *option_s,
					    bool unicode_flag)
{
	if (!attrs)
		return {};

	auto count=ippGetCount(attrs);

	auto tag_value=ippGetValueTag(attrs);

	switch (tag_value) {
	case IPP_TAG_NOVALUE:
		return {};
	case IPP_TAG_RANGE:
		{
			std::vector<std::tuple<int, int>> v;

			v.reserve(count);

			for (decltype (count) i=0; i<count; i++)
			{
				int upper;

				int lower=ippGetRange(attrs, i, &upper);

				v.emplace_back(lower, upper);
			}
			return v;
		}
	case IPP_TAG_RESOLUTION:
		{
			std::vector<resolution> v;

			v.reserve(count);

			for (decltype (count) i=0; i<count; i++)
			{
				resolution res;
				ipp_res_t units;

				res.xres=ippGetResolution(attrs, i,
							  &res.yres, &units);

				switch (units) {
				case IPP_RES_PER_INCH:
					res.units=res.per_inch;
					break;
				case IPP_RES_PER_CM:
					res.units=res.per_cm;
					break;
				default:
					res.units=res.unknown;
				}
				v.push_back(res);
			}
			return v;
		}

	case IPP_TAG_INTEGER:
		{
			std::unordered_set<int> v;

			for (decltype (count) i=0; i<count; i++)
			{
				v.insert(ippGetInteger(attrs, i));
			}
			return v;
		}
	case IPP_TAG_BOOLEAN:
		{
			std::unordered_set<bool> v;

			for (decltype (count) i=0; i<count; i++)
			{
				v.insert(ippGetBoolean(attrs, i));
			}
			return v;
		}
	case IPP_TAG_ENUM:
		if (unicode_flag)
		{
			auto l=locale::base::global();

			std::unordered_map<int, std::u32string> v;

			for (decltype (count) i=0; i<count; i++)
			{
				auto value=ippGetInteger(attrs, i);

				auto s=enum_string(option_s, value);

				auto us=unicode::iconvert::tou
					::convert(s, l->charset()).first;

				v.emplace(value, us);
			}
			return v;
		}
		else
		{
			std::unordered_map<int, std::string> v;

			for (decltype (count) i=0; i<count; i++)
			{
				auto value=ippGetInteger(attrs, i);


				v.emplace(value, enum_string(option_s, value));
			}
			return v;
		}
	case IPP_TAG_BEGIN_COLLECTION:
		{
			std::vector<const_collection> v;

			v.reserve(count);

			for (decltype (count) i=0; i<count; i++)
			{
				auto ippc=ippGetCollection(attrs, i);

				auto c=collection::create();

				for (auto attr=ippFirstAttribute(ippc);
				     attr;
				     attr=ippNextAttribute(ippc))
				{
					std::string n=ippGetName(attr);
					c->emplace(n, parse_attribute_values
						   (lock, attr, n.c_str(),
						    unicode_flag));
				}
				v.push_back(c);
			}
			return v;
		}
	default:
		break;
	}

	std::unordered_map<std::string, std::string> v;

	bool is_media=strcmp(option_s, CUPS_MEDIA) == 0;

	auto localizer=strcmp(option_s, CUPS_SIDES) == 0
		? sides
		: strcmp(option_s, CUPS_PRINT_COLOR_MODE) == 0
		? print_color_mode
		: no_localizer;

	for (decltype (count) i=0; i<count; i++)
	{
		const char *lang=0;

		auto val=ippGetString(attrs, i, &lang);

		if (!val)
		{

			std::ostringstream o;

			o << "{unknown tag "
			  << ippTagString(ippGetValueTag(attrs)) << "}";
			v.emplace(o.str(), "");
			continue;
		}

		std::string lang_s;

		if (is_media)
		{
			cups_size_t size;

			lang_s=val;

			if (cupsGetDestMediaByName(lock->http,
						   lock->dest,
						   lock->info,
						   val,
						   CUPS_MEDIA_FLAGS_DEFAULT,
						   &size))
			{
				auto l=cupsLocalizeDestMedia
					(lock->http,
					 lock->dest,
					 lock->info,
					 CUPS_MEDIA_FLAGS_DEFAULT,
					 &size);

				if (l)
					lang_s=l;
			}
		}
		else
		{
			auto c=cupsLocalizeDestValue(lock->http,
						     lock->dest,
						     lock->info,
						     option_s,
						     val);

			if (c && strcmp(c, val))
			{
				lang_s=c;
			}
			else
			{
				lang_s=localizer(val);
			}
		}
		v.emplace(val, lang_s);
	}

	if (!unicode_flag)
		return v;

	auto l=locale::base::global();

	std::unordered_map<std::string, std::u32string> uv;

	for (const auto &s:v)
	{
		auto n=s.first;


		uv.emplace(s.first,
			   unicode::iconvert::tou::convert(s.second,
							   l->charset())
			   .first);
	}
	return uv;
}
static gboolean
_pp_maintenance_command_is_supported (const gchar *printer_name,
                                      const gchar *command)
{
  ipp_attribute_t   *attr = NULL;
  gboolean           is_supported = FALSE;
  ipp_t             *request;
  ipp_t             *response = NULL;
  gchar             *printer_uri;
  gchar             *command_lowercase;
  GPtrArray         *available_commands = NULL;
  int                i;

  printer_uri = g_strdup_printf ("ipp://localhost/printers/%s",
                                 printer_name);

  request = ippNewRequest (IPP_GET_PRINTER_ATTRIBUTES);
  ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_URI,
                "printer-uri", NULL, printer_uri);
  ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
                "requested-attributes", NULL, "printer-commands");
  response = cupsDoRequest (CUPS_HTTP_DEFAULT, request, "/");
  if (response != NULL)
    {
      if (ippGetStatusCode (response) <= IPP_OK_CONFLICT)
        {
          int commands_count;

          attr = ippFindAttribute (response, "printer-commands", IPP_TAG_ZERO);
          commands_count = attr != NULL ? ippGetCount (attr) : 0;
          if (commands_count > 0 &&
              ippGetValueTag (attr) != IPP_TAG_NOVALUE &&
              (ippGetValueTag (attr) == IPP_TAG_KEYWORD))
            {
              available_commands = g_ptr_array_new_full (commands_count, g_free);
              for (i = 0; i < commands_count; ++i)
                {
                  /* Array gains ownership of the lower-cased string */
                  g_ptr_array_add (available_commands, g_ascii_strdown (ippGetString (attr, i, NULL), -1));
                }
            }
        }

      ippDelete (response);
    }

  if (available_commands != NULL)
    {
      command_lowercase = g_ascii_strdown (command, -1);
      for (i = 0; i < available_commands->len; ++i)
        {
          const gchar *available_command = g_ptr_array_index (available_commands, i);
          if (g_strcmp0 (available_command, command_lowercase) == 0)
            {
              is_supported = TRUE;
              break;
            }
        }

      g_free (command_lowercase);
      g_ptr_array_free (available_commands, TRUE);
    }

  g_free (printer_uri);

  return is_supported;
}
Exemple #10
0
static ipp_t *				/* O  - Collection value */
get_collection(cups_file_t *fp,		/* I  - File to read from */
               const char  *filename,	/* I  - Attributes filename */
	       int         *linenum)	/* IO - Line number */
{
  char		token[1024],		/* Token from file */
		attr[128];		/* Attribute name */
  ipp_tag_t	value;			/* Current value type */
  ipp_t		*col = ippNew();	/* Collection value */
  ipp_attribute_t *lastcol = NULL;	/* Last collection attribute */


  while (get_token(fp, token, sizeof(token), linenum) != NULL)
  {
    if (!strcmp(token, "}"))
      break;
    else if (!strcmp(token, "{") && lastcol)
    {
     /*
      * Another collection value
      */

      ipp_t	*subcol = get_collection(fp, filename, linenum);
					/* Collection value */

      if (subcol)
        ippSetCollection(col, &lastcol, ippGetCount(lastcol), subcol);
      else
	goto col_error;
    }
    else if (!_cups_strcasecmp(token, "MEMBER"))
    {
     /*
      * Attribute...
      */

      lastcol = NULL;

      if (!get_token(fp, token, sizeof(token), linenum))
      {
	fprintf(stderr, "ippserver: Missing MEMBER value tag on line %d of \"%s\".\n", *linenum, filename);
	goto col_error;
      }

      if ((value = ippTagValue(token)) == IPP_TAG_ZERO)
      {
	fprintf(stderr, "ippserver: Bad MEMBER value tag \"%s\" on line %d of \"%s\".\n", token, *linenum, filename);
	goto col_error;
      }

      if (!get_token(fp, attr, sizeof(attr), linenum))
      {
	fprintf(stderr, "ippserver: Missing MEMBER name on line %d of \"%s\".\n", *linenum, filename);
	goto col_error;
      }

      if (!get_token(fp, token, sizeof(token), linenum))
      {
	fprintf(stderr, "ippserver: Missing MEMBER value on line %d of \"%s\".\n", *linenum, filename);
	goto col_error;
      }

      switch (value)
      {
	case IPP_TAG_BOOLEAN :
	    if (!_cups_strcasecmp(token, "true"))
	      ippAddBoolean(col, IPP_TAG_ZERO, attr, 1);
	    else
	      ippAddBoolean(col, IPP_TAG_ZERO, attr, (char)atoi(token));
	    break;

	case IPP_TAG_INTEGER :
	case IPP_TAG_ENUM :
	    ippAddInteger(col, IPP_TAG_ZERO, value, attr, atoi(token));
	    break;

	case IPP_TAG_RESOLUTION :
	    {
	      int	xres,		/* X resolution */
			yres;		/* Y resolution */
	      char	units[6];	/* Units */

	      if (sscanf(token, "%dx%d%5s", &xres, &yres, units) != 3 ||
		  (_cups_strcasecmp(units, "dpi") &&
		   _cups_strcasecmp(units, "dpc") &&
		   _cups_strcasecmp(units, "dpcm") &&
		   _cups_strcasecmp(units, "other")))
	      {
		fprintf(stderr, "ippserver: Bad resolution value \"%s\" on line %d of \"%s\".\n", token, *linenum, filename);
		goto col_error;
	      }

	      if (!_cups_strcasecmp(units, "dpi"))
		ippAddResolution(col, IPP_TAG_ZERO, attr, IPP_RES_PER_INCH, xres, yres);
	      else if (!_cups_strcasecmp(units, "dpc") ||
	               !_cups_strcasecmp(units, "dpcm"))
		ippAddResolution(col, IPP_TAG_ZERO, attr, IPP_RES_PER_CM, xres, yres);
	      else
		ippAddResolution(col, IPP_TAG_ZERO, attr, (ipp_res_t)0, xres, yres);
	    }
	    break;

	case IPP_TAG_RANGE :
	    {
	      int	lowers[4],	/* Lower value */
			uppers[4],	/* Upper values */
			num_vals;	/* Number of values */


	      num_vals = sscanf(token, "%d-%d,%d-%d,%d-%d,%d-%d",
				lowers + 0, uppers + 0,
				lowers + 1, uppers + 1,
				lowers + 2, uppers + 2,
				lowers + 3, uppers + 3);

	      if ((num_vals & 1) || num_vals == 0)
	      {
		fprintf(stderr, "ippserver: Bad rangeOfInteger value \"%s\" on line %d of \"%s\".\n", token, *linenum, filename);
		goto col_error;
	      }

	      ippAddRanges(col, IPP_TAG_ZERO, attr, num_vals / 2, lowers,
			   uppers);
	    }
	    break;

	case IPP_TAG_BEGIN_COLLECTION :
	    if (!strcmp(token, "{"))
	    {
	      ipp_t	*subcol = get_collection(fp, filename, linenum);
				      /* Collection value */

	      if (subcol)
	      {
		lastcol = ippAddCollection(col, IPP_TAG_ZERO, attr, subcol);
		ippDelete(subcol);
	      }
	      else
		goto col_error;
	    }
	    else
	    {
	      fprintf(stderr, "ippserver: Bad collection value on line %d of \"%s\".\n", *linenum, filename);
	      goto col_error;
	    }
	    break;
	case IPP_TAG_STRING :
	    ippAddOctetString(col, IPP_TAG_ZERO, attr, token, (int)strlen(token));
	    break;

	default :
	    if (!strchr(token, ','))
	      ippAddString(col, IPP_TAG_ZERO, value, attr, NULL, token);
	    else
	    {
	     /*
	      * Multiple string values...
	      */

	      int	num_values;	/* Number of values */
	      char	*values[100],	/* Values */
			*ptr;		/* Pointer to next value */


	      values[0]  = token;
	      num_values = 1;

	      for (ptr = strchr(token, ','); ptr; ptr = strchr(ptr, ','))
	      {
		*ptr++ = '\0';
		values[num_values] = ptr;
		num_values ++;
		if (num_values >= (int)(sizeof(values) / sizeof(values[0])))
		  break;
	      }

	      ippAddStrings(col, IPP_TAG_ZERO, value, attr, num_values,
			    NULL, (const char **)values);
	    }
	    break;
      }
    }
  }

  return (col);

 /*
  * If we get here there was a parse error; free memory and return.
  */

  col_error:

  ippDelete(col);

  return (NULL);
}
Exemple #11
0
ipp_t *					/* O - Attributes */
serverLoadAttributes(
    const char *filename,		/* I - File to load */
    char       **authtype,		/* O - Authentication type, if any */
    char       **command,		/* O - Command to run, if any */
    char       **device_uri,		/* O - Device URI, if any */
    char       **make,			/* O - Manufacturer */
    char       **model,			/* O - Model */
    char       **proxy_user)		/* O - Proxy user, if any */
{
  ipp_t		*attrs;			/* Attributes to return */
  cups_file_t	*fp;			/* File */
  int		linenum = 0;		/* Current line number */
  char		attr[128],		/* Attribute name */
		token[1024],		/* Token from file */
		*tokenptr;		/* Pointer into token */
  ipp_tag_t	value;			/* Current value type */
  ipp_attribute_t *attrptr;		/* Attribute pointer */


  if ((fp = cupsFileOpen(filename, "r")) == NULL)
  {
    serverLog(SERVER_LOGLEVEL_ERROR, "Unable to open \"%s\": %s", filename, strerror(errno));
    return (NULL);
  }

  attrs = ippNew();

  while (get_token(fp, token, sizeof(token), &linenum) != NULL)
  {
    if (!_cups_strcasecmp(token, "ATTR"))
    {
     /*
      * Attribute...
      */

      if (!get_token(fp, token, sizeof(token), &linenum))
      {
	serverLog(SERVER_LOGLEVEL_ERROR, "Missing ATTR value tag on line %d of \"%s\".", linenum, filename);
        goto load_error;
      }

      if ((value = ippTagValue(token)) == IPP_TAG_ZERO)
      {
	serverLog(SERVER_LOGLEVEL_ERROR, "Bad ATTR value tag \"%s\" on line %d of \"%s\".", token, linenum, filename);
        goto load_error;
      }

      if (!get_token(fp, attr, sizeof(attr), &linenum))
      {
	serverLog(SERVER_LOGLEVEL_ERROR, "Missing ATTR name on line %d of \"%s\".", linenum, filename);
        goto load_error;
      }

      if (!get_token(fp, token, sizeof(token), &linenum))
      {
	serverLog(SERVER_LOGLEVEL_ERROR, "Missing ATTR value on line %d of \"%s\".", linenum, filename);
        goto load_error;
      }

      attrptr = NULL;

      switch (value)
      {
	case IPP_TAG_BOOLEAN :
	    if (!_cups_strcasecmp(token, "true"))
	      attrptr = ippAddBoolean(attrs, IPP_TAG_PRINTER, attr, 1);
	    else
	      attrptr = ippAddBoolean(attrs, IPP_TAG_PRINTER, attr, (char)atoi(token));
	    break;

	case IPP_TAG_INTEGER :
	case IPP_TAG_ENUM :
	    if (!strchr(token, ','))
	      attrptr = ippAddInteger(attrs, IPP_TAG_PRINTER, value, attr, (int)strtol(token, &tokenptr, 0));
	    else
	    {
	      int	values[100],	/* Values */
			num_values = 1;	/* Number of values */

	      values[0] = (int)strtol(token, &tokenptr, 10);
	      while (tokenptr && *tokenptr &&
		     num_values < (int)(sizeof(values) / sizeof(values[0])))
	      {
		if (*tokenptr == ',')
		  tokenptr ++;
		else if (!isdigit(*tokenptr & 255) && *tokenptr != '-')
		  break;

		values[num_values] = (int)strtol(tokenptr, &tokenptr, 0);
		num_values ++;
	      }

	      attrptr = ippAddIntegers(attrs, IPP_TAG_PRINTER, value, attr, num_values, values);
	    }

	    if (!tokenptr || *tokenptr)
	    {
	      serverLog(SERVER_LOGLEVEL_ERROR, "Bad %s value \"%s\" on line %d of \"%s\".", ippTagString(value), token, linenum, filename);
              goto load_error;
	    }
	    break;

	case IPP_TAG_RESOLUTION :
	    {
	      int	xres,		/* X resolution */
			yres;		/* Y resolution */
	      ipp_res_t	units;		/* Units */
	      char	*start,		/* Start of value */
			*ptr,		/* Pointer into value */
			*next = NULL;	/* Next value */

	      for (start = token; start; start = next)
	      {
		xres = yres = (int)strtol(start, (char **)&ptr, 10);
		if (ptr > start && xres > 0)
		{
		  if (*ptr == 'x')
		    yres = (int)strtol(ptr + 1, (char **)&ptr, 10);
		}

		if (ptr && (next = strchr(ptr, ',')) != NULL)
		  *next++ = '\0';

		if (ptr <= start || xres <= 0 || yres <= 0 || !ptr ||
		    (_cups_strcasecmp(ptr, "dpi") &&
		     _cups_strcasecmp(ptr, "dpc") &&
		     _cups_strcasecmp(ptr, "dpcm") &&
		     _cups_strcasecmp(ptr, "other")))
		{
		  serverLog(SERVER_LOGLEVEL_ERROR, "Bad resolution value \"%s\" on line %d of \"%s\".", token, linenum, filename);
                  goto load_error;
		}

		if (!_cups_strcasecmp(ptr, "dpc") || !_cups_strcasecmp(ptr, "dpcm"))
		  units = IPP_RES_PER_CM;
		else
		  units = IPP_RES_PER_INCH;

                if (attrptr)
		  ippSetResolution(attrs, &attrptr, ippGetCount(attrptr), units, xres, yres);
		else
		  attrptr = ippAddResolution(attrs, IPP_TAG_PRINTER, attr, units, xres, yres);
	      }
	    }
	    break;

	case IPP_TAG_RANGE :
	    {
	      int	lowers[4],	/* Lower value */
			uppers[4],	/* Upper values */
			num_vals;	/* Number of values */


	      num_vals = sscanf(token, "%d-%d,%d-%d,%d-%d,%d-%d",
				lowers + 0, uppers + 0,
				lowers + 1, uppers + 1,
				lowers + 2, uppers + 2,
				lowers + 3, uppers + 3);

	      if ((num_vals & 1) || num_vals == 0)
	      {
		serverLog(SERVER_LOGLEVEL_ERROR, "Bad rangeOfInteger value \"%s\" on line %d of \"%s\".", token, linenum, filename);
                goto load_error;
	      }

	      attrptr = ippAddRanges(attrs, IPP_TAG_PRINTER, attr, num_vals / 2, lowers,
				     uppers);
	    }
	    break;

	case IPP_TAG_BEGIN_COLLECTION :
	    if (!strcmp(token, "{"))
	    {
	      ipp_t	*col = get_collection(fp, filename, &linenum);
				    /* Collection value */

	      if (col)
	      {
		attrptr = ippAddCollection(attrs, IPP_TAG_PRINTER, attr, col);
		ippDelete(col);
	      }
	      else
		exit(1);
	    }
	    else
	    {
	      serverLog(SERVER_LOGLEVEL_ERROR, "Bad ATTR collection value on line %d of \"%s\".", linenum, filename);
              goto load_error;
	    }

	    do
	    {
	      ipp_t	*col;			/* Collection value */
	      long	pos = cupsFileTell(fp);	/* Save position of file */

	      if (!get_token(fp, token, sizeof(token), &linenum))
		break;

	      if (strcmp(token, ","))
	      {
		cupsFileSeek(fp, pos);
		break;
	      }

	      if (!get_token(fp, token, sizeof(token), &linenum) || strcmp(token, "{"))
	      {
		serverLog(SERVER_LOGLEVEL_ERROR, "Unexpected \"%s\" on line %d of \"%s\".", token, linenum, filename);
                goto load_error;
	      }

	      if ((col = get_collection(fp, filename, &linenum)) == NULL)
		break;

	      ippSetCollection(attrs, &attrptr, ippGetCount(attrptr), col);
	    }
	    while (!strcmp(token, "{"));
	    break;

	case IPP_TAG_STRING :
	    attrptr = ippAddOctetString(attrs, IPP_TAG_PRINTER, attr, token, (int)strlen(token));
	    break;

	default :
	    serverLog(SERVER_LOGLEVEL_ERROR, "Unsupported ATTR value tag %s on line %d of \"%s\".", ippTagString(value), linenum, filename);
            goto load_error;

	case IPP_TAG_TEXTLANG :
	case IPP_TAG_NAMELANG :
	case IPP_TAG_TEXT :
	case IPP_TAG_NAME :
	case IPP_TAG_KEYWORD :
	case IPP_TAG_URI :
	case IPP_TAG_URISCHEME :
	case IPP_TAG_CHARSET :
	case IPP_TAG_LANGUAGE :
	case IPP_TAG_MIMETYPE :
	    if (!strchr(token, ','))
	      attrptr = ippAddString(attrs, IPP_TAG_PRINTER, value, attr, NULL, token);
	    else
	    {
	     /*
	      * Multiple string values...
	      */

	      int	num_values;	/* Number of values */
	      char	*values[100],	/* Values */
			*ptr;		/* Pointer to next value */


	      values[0]  = token;
	      num_values = 1;

	      for (ptr = strchr(token, ','); ptr; ptr = strchr(ptr, ','))
	      {
		if (ptr > token && ptr[-1] == '\\')
		  _cups_strcpy(ptr - 1, ptr);
		else
		{
		  *ptr++ = '\0';
		  values[num_values] = ptr;
		  num_values ++;
		  if (num_values >= (int)(sizeof(values) / sizeof(values[0])))
		    break;
		}
	      }

	      attrptr = ippAddStrings(attrs, IPP_TAG_PRINTER, value, attr, num_values, NULL, (const char **)values);
	    }
	    break;
      }

      if (!attrptr)
      {
        serverLog(SERVER_LOGLEVEL_ERROR, "Unable to add attribute on line %d of \"%s\": %s", linenum, filename, cupsLastErrorString());
        goto load_error;
      }
    }
    else if (!_cups_strcasecmp(token, "AUTHTYPE") && authtype)
    {
      if (!get_token(fp, token, sizeof(token), &linenum))
      {
	serverLog(SERVER_LOGLEVEL_ERROR, "Missing AUTHTYPE value on line %d of \"%s\".", linenum, filename);
        goto load_error;
      }

      *authtype = strdup(token);
    }
    else if (!_cups_strcasecmp(token, "COMMAND") && command)
    {
      if (!get_token(fp, token, sizeof(token), &linenum))
      {
	serverLog(SERVER_LOGLEVEL_ERROR, "Missing COMMAND value on line %d of \"%s\".", linenum, filename);
        goto load_error;
      }

      *command = strdup(token);
    }
    else if (!_cups_strcasecmp(token, "DEVICEURI") && device_uri)
    {
      if (!get_token(fp, token, sizeof(token), &linenum))
      {
	serverLog(SERVER_LOGLEVEL_ERROR, "Missing DEVICE-URI value on line %d of \"%s\".", linenum, filename);
        goto load_error;
      }

      *device_uri = strdup(token);
    }
    else if (!_cups_strcasecmp(token, "MAKE") && make)
    {
      if (!get_token(fp, token, sizeof(token), &linenum))
      {
	serverLog(SERVER_LOGLEVEL_ERROR, "Missing MAKE value on line %d of \"%s\".", linenum, filename);
        goto load_error;
      }

      *make = strdup(token);
    }
    else if (!_cups_strcasecmp(token, "MODEL") && model)
    {
      if (!get_token(fp, token, sizeof(token), &linenum))
      {
	serverLog(SERVER_LOGLEVEL_ERROR, "Missing MODEL value on line %d of \"%s\".", linenum, filename);
        goto load_error;
      }

      *model = strdup(token);
    }
    else if (!_cups_strcasecmp(token, "PROXYUSER") && proxy_user)
    {
      if (!get_token(fp, token, sizeof(token), &linenum))
      {
	serverLog(SERVER_LOGLEVEL_ERROR, "Missing PROXY-USER value on line %d of \"%s\".", linenum, filename);
        goto load_error;
      }

      *proxy_user = strdup(token);
    }
    else
    {
      serverLog(SERVER_LOGLEVEL_ERROR, "Unknown directive \"%s\" on line %d of \"%s\".", token, linenum, filename);
      goto load_error;
    }
  }

  cupsFileClose(fp);

  return (attrs);

 /*
  * If we get here something bad happened...
  */

  load_error:

  cupsFileClose(fp);

  ippDelete(attrs);

  return (NULL);
}