/* Cancels subscription of given id */
static void
cancel_subscription_thread (GTask        *task,
                            gpointer      source_object,
                            gpointer      task_data,
                            GCancellable *cancellable)
{
  ipp_t *request;
  ipp_t *response = NULL;
  gint   id = GPOINTER_TO_INT (task_data);

  if (id >= 0)
    {
      request = ippNewRequest (IPP_CANCEL_SUBSCRIPTION);
      ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_URI,
                    "printer-uri", NULL, "/");
      ippAddString (request, IPP_TAG_OPERATION, IPP_TAG_NAME,
                    "requesting-user-name", NULL, cupsUser ());
      ippAddInteger (request, IPP_TAG_OPERATION, IPP_TAG_INTEGER,
                     "notify-subscription-id", id);
      response = cupsDoRequest (CUPS_HTTP_DEFAULT, request, "/");
    }

  g_task_return_boolean (task, response != NULL && ippGetStatusCode (response) <= IPP_OK);

  ippDelete (response);
}
Exemple #2
0
static cups_ptype_t			/* O - printer-type value */
get_printer_type(http_t *http,		/* I - Server connection */
                 char   *printer,	/* I - Printer name */
		 char   *uri,		/* I - URI buffer */
                 size_t urisize)	/* I - Size of URI buffer */
{
  ipp_t			*request,	/* IPP request */
			*response;	/* IPP response */
  ipp_attribute_t	*attr;		/* printer-type attribute */
  cups_ptype_t		type;		/* printer-type value */


 /*
  * Build a GET_PRINTER_ATTRIBUTES request, which requires the following
  * attributes:
  *
  *    attributes-charset
  *    attributes-natural-language
  *    printer-uri
  *    requested-attributes
  *    requesting-user-name
  */

  httpAssembleURIf(HTTP_URI_CODING_ALL, uri, urisize, "ipp", NULL, "localhost",
                   ippPort(), "/printers/%s", printer);

  request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);
  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
               "printer-uri", NULL, uri);
  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
               "requested-attributes", NULL, "printer-type");
  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
               "requesting-user-name", NULL, cupsUser());

 /*
  * Do the request...
  */

  response = cupsDoRequest(http, request, "/");
  if ((attr = ippFindAttribute(response, "printer-type",
                               IPP_TAG_ENUM)) != NULL)
  {
    type = (cups_ptype_t)attr->values[0].integer;

    if (type & CUPS_PRINTER_CLASS)
      httpAssembleURIf(HTTP_URI_CODING_ALL, uri, urisize, "ipp", NULL,
		       "localhost", ippPort(), "/classes/%s", printer);
  }
  else
    type = CUPS_PRINTER_LOCAL;

  ippDelete(response);

  return (type);
}
Exemple #3
0
http_status_t				/* O - HTTP status of request */
cupsStartDocument(
    http_t     *http,			/* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
    const char *name,			/* I - Destination name */
    int        job_id,			/* I - Job ID from @link cupsCreateJob@ */
    const char *docname,		/* I - Name of document */
    const char *format,			/* I - MIME type or @code CUPS_FORMAT_foo@ */
    int        last_document)		/* I - 1 for last document in job, 0 otherwise */
{
  char		resource[1024],		/* Resource for destinatio */
		printer_uri[1024];	/* Printer URI */
  ipp_t		*request;		/* Send-Document request */
  http_status_t	status;			/* HTTP status */


 /*
  * Create a Send-Document request...
  */

  if ((request = ippNewRequest(IPP_SEND_DOCUMENT)) == NULL)
  {
    _cupsSetError(IPP_INTERNAL_ERROR, strerror(ENOMEM), 0);
    return (HTTP_ERROR);
  }

  httpAssembleURIf(HTTP_URI_CODING_ALL, printer_uri, sizeof(printer_uri), "ipp",
                   NULL, "localhost", ippPort(), "/printers/%s", name);
  snprintf(resource, sizeof(resource), "/printers/%s", name);

  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
               NULL, printer_uri);
  ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", job_id);
  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
               NULL, cupsUser());
  if (docname)
    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "document-name",
                 NULL, docname);
  if (format)
    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE,
                 "document-format", NULL, format);
  ippAddBoolean(request, IPP_TAG_OPERATION, "last-document", last_document);

 /*
  * Send and delete the request, then return the status...
  */

  status = cupsSendRequest(http, request, resource, CUPS_LENGTH_VARIABLE);

  ippDelete(request);

  return (status);
}
Exemple #4
0
static int				/* O - 0 on success, 1 on fail */
enable_printer(http_t *http,		/* I - Server connection */
               char   *printer)		/* I - Printer to enable */
{
  ipp_t		*request;		/* IPP Request */
  char		uri[HTTP_MAX_URI];	/* URI for printer/class */


  DEBUG_printf(("enable_printer(%p, \"%s\")\n", http, printer));

 /*
  * Build a CUPS_ADD_MODIFY_PRINTER or CUPS_ADD_MODIFY_CLASS request, which
  * require the following attributes:
  *
  *    attributes-charset
  *    attributes-natural-language
  *    printer-uri
  *    requesting-user-name
  *    printer-state
  *    printer-is-accepting-jobs
  */

  if (get_printer_type(http, printer, uri, sizeof(uri)) & CUPS_PRINTER_CLASS)
    request = ippNewRequest(CUPS_ADD_MODIFY_CLASS);
  else
    request = ippNewRequest(CUPS_ADD_MODIFY_PRINTER);

  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
               "printer-uri", NULL, uri);
  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
               "requesting-user-name", NULL, cupsUser());
  ippAddInteger(request, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state",
                IPP_PRINTER_IDLE);
  ippAddBoolean(request, IPP_TAG_PRINTER, "printer-is-accepting-jobs", 1);

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

  ippDelete(cupsDoRequest(http, request, "/admin/"));

  if (cupsLastError() > IPP_OK_CONFLICT)
  {
    _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString());

    return (1);
  }
  else
    return (0);
}
Exemple #5
0
static int				/* O - 0 on success, 1 on fail */
delete_printer_option(http_t *http,	/* I - Server connection */
                      char   *printer,	/* I - Printer */
		      char   *option)	/* I - Option to delete */
{
  ipp_t		*request;		/* IPP request */
  char		uri[HTTP_MAX_URI];	/* URI for printer/class */


 /*
  * Build a CUPS_ADD_MODIFY_PRINTER or CUPS_ADD_MODIFY_CLASS request, which
  * requires the following attributes:
  *
  *    attributes-charset
  *    attributes-natural-language
  *    printer-uri
  *    requesting-user-name
  *    option with deleteAttr tag
  */

  if (get_printer_type(http, printer, uri, sizeof(uri)) & CUPS_PRINTER_CLASS)
    request = ippNewRequest(CUPS_ADD_MODIFY_CLASS);
  else
    request = ippNewRequest(CUPS_ADD_MODIFY_PRINTER);

  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
               "printer-uri", NULL, uri);
  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
               "requesting-user-name", NULL, cupsUser());
  ippAddInteger(request, IPP_TAG_PRINTER, IPP_TAG_DELETEATTR, option, 0);

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

  ippDelete(cupsDoRequest(http, request, "/admin/"));

  if (cupsLastError() > IPP_OK_CONFLICT)
  {
    _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString());

    return (1);
  }
  else
    return (0);
}
Exemple #6
0
static int				/* O - 0 on success, 1 on fail */
default_printer(http_t *http,		/* I - Server connection */
                char   *printer)	/* I - Printer name */
{
  ipp_t		*request;		/* IPP Request */
  char		uri[HTTP_MAX_URI];	/* URI for printer/class */


  DEBUG_printf(("default_printer(%p, \"%s\")\n", http, printer));

 /*
  * Build a CUPS_SET_DEFAULT request, which requires the following
  * attributes:
  *
  *    attributes-charset
  *    attributes-natural-language
  *    printer-uri
  *    requesting-user-name
  */

  httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
                   "localhost", 0, "/printers/%s", printer);

  request = ippNewRequest(CUPS_SET_DEFAULT);

  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
               "printer-uri", NULL, uri);
  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
               NULL, cupsUser());

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

  ippDelete(cupsDoRequest(http, request, "/admin/"));

  if (cupsLastError() > IPP_OK_CONFLICT)
  {
    _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString());

    return (1);
  }
  else
    return (0);
}
void KCupsConnection::cancelDBusSubscription()
{
    do {
        ipp_t *request;

        // Lets create the request
        request = ippNewRequest(IPP_CANCEL_SUBSCRIPTION);
        ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
                     KCUPS_PRINTER_URI, NULL, "/");
        ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
                     "requesting-user-name", NULL, cupsUser());
        ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER,
                      "notify-subscription-id", m_subscriptionId);

        // Do the request
        ippDelete(cupsDoRequest(CUPS_HTTP_DEFAULT, request, "/"));
    } while (retry("/"));

    // Reset the subscription id
    m_subscriptionId = -1;
}
Exemple #8
0
int					/* O - Number of jobs */
cupsGetJobs2(http_t     *http,		/* I - HTTP connection */
             cups_job_t **jobs,		/* O - Job data */
             const char *mydest,	/* I - NULL = all destinations,       *
	                                 *     otherwise show jobs for mydest */
             int        myjobs,		/* I - 0 = all users, 1 = mine */
             int        completed)	/* I - -1 = show all, 0 = active, *
	                                 *     1 = completed jobs         */
{
    int		n;			/* Number of jobs */
    ipp_t		*request,		/* IPP Request */
                *response;		/* IPP Response */
    ipp_attribute_t *attr;		/* Current attribute */
    cups_job_t	*temp;			/* Temporary pointer */
    int		id,			/* job-id */
            priority,		/* job-priority */
            size;			/* job-k-octets */
    ipp_jstate_t	state;			/* job-state */
    time_t	completed_time,		/* time-at-completed */
            creation_time,		/* time-at-creation */
            processing_time;	/* time-at-processing */
    const char	*dest,			/* job-printer-uri */
           *format,		/* document-format */
           *title,			/* job-name */
           *user;			/* job-originating-user-name */
    char		uri[HTTP_MAX_URI];	/* URI for jobs */
    _cups_globals_t *cg = _cupsGlobals();	/* Pointer to library globals */
    static const char * const attrs[] =	/* Requested attributes */
    {
        "job-id",
        "job-priority",
        "job-k-octets",
        "job-state",
        "time-at-completed",
        "time-at-creation",
        "time-at-processing",
        "job-printer-uri",
        "document-format",
        "job-name",
        "job-originating-user-name"
    };


    /*
     * Range check input...
     */

    if (!http || !jobs)
    {
        _cupsSetError(IPP_INTERNAL_ERROR, NULL);

        return (-1);
    }

    /*
     * Get the right URI...
     */

    if (mydest)
    {
        if (httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
                             "localhost", 0, "/printers/%s", mydest) != HTTP_URI_OK)
        {
            _cupsSetError(IPP_INTERNAL_ERROR, NULL);

            return (-1);
        }
    }
    else
        strcpy(uri, "ipp://localhost/jobs");


    /*
     * Build an IPP_GET_JOBS request, which requires the following
     * attributes:
     *
     *    attributes-charset
     *    attributes-natural-language
     *    printer-uri
     *    requesting-user-name
     *    which-jobs
     *    my-jobs
     *    requested-attributes
     */

    request = ippNewRequest(IPP_GET_JOBS);

    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
                 "printer-uri", NULL, uri);

    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
                 "requesting-user-name", NULL, cupsUser());

    if (myjobs)
        ippAddBoolean(request, IPP_TAG_OPERATION, "my-jobs", 1);

    if (completed > 0)
        ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
                     "which-jobs", NULL, "completed");
    else if (completed < 0)
        ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
                     "which-jobs", NULL, "all");

    ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
                  "requested-attributes", sizeof(attrs) / sizeof(attrs[0]),
                  NULL, attrs);

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

    n     = 0;
    *jobs = NULL;

    if ((response = cupsDoRequest(http, request, "/")) != NULL)
    {
        for (attr = response->attrs; attr != NULL; attr = attr->next)
        {
            /*
             * Skip leading attributes until we hit a job...
             */

            while (attr != NULL && attr->group_tag != IPP_TAG_JOB)
                attr = attr->next;

            if (attr == NULL)
                break;

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

            id              = 0;
            size            = 0;
            priority        = 50;
            state           = IPP_JOB_PENDING;
            user            = "******";
            dest            = NULL;
            format          = "application/octet-stream";
            title           = "untitled";
            creation_time   = 0;
            completed_time  = 0;
            processing_time = 0;

            while (attr != NULL && attr->group_tag == IPP_TAG_JOB)
            {
                if (strcmp(attr->name, "job-id") == 0 &&
                        attr->value_tag == IPP_TAG_INTEGER)
                    id = attr->values[0].integer;
                else if (strcmp(attr->name, "job-state") == 0 &&
                         attr->value_tag == IPP_TAG_ENUM)
                    state = (ipp_jstate_t)attr->values[0].integer;
                else if (strcmp(attr->name, "job-priority") == 0 &&
                         attr->value_tag == IPP_TAG_INTEGER)
                    priority = attr->values[0].integer;
                else if (strcmp(attr->name, "job-k-octets") == 0 &&
                         attr->value_tag == IPP_TAG_INTEGER)
                    size = attr->values[0].integer;
                else if (strcmp(attr->name, "time-at-completed") == 0 &&
                         attr->value_tag == IPP_TAG_INTEGER)
                    completed_time = attr->values[0].integer;
                else if (strcmp(attr->name, "time-at-creation") == 0 &&
                         attr->value_tag == IPP_TAG_INTEGER)
                    creation_time = attr->values[0].integer;
                else if (strcmp(attr->name, "time-at-processing") == 0 &&
                         attr->value_tag == IPP_TAG_INTEGER)
                    processing_time = attr->values[0].integer;
                else if (strcmp(attr->name, "job-printer-uri") == 0 &&
                         attr->value_tag == IPP_TAG_URI)
                {
                    if ((dest = strrchr(attr->values[0].string.text, '/')) != NULL)
                        dest ++;
                }
                else if (strcmp(attr->name, "job-originating-user-name") == 0 &&
                         attr->value_tag == IPP_TAG_NAME)
                    user = attr->values[0].string.text;
                else if (strcmp(attr->name, "document-format") == 0 &&
                         attr->value_tag == IPP_TAG_MIMETYPE)
                    format = attr->values[0].string.text;
                else if (strcmp(attr->name, "job-name") == 0 &&
                         (attr->value_tag == IPP_TAG_TEXT ||
                          attr->value_tag == IPP_TAG_NAME))
                    title = attr->values[0].string.text;

                attr = attr->next;
            }

            /*
             * See if we have everything needed...
             */

            if (dest == NULL || id == 0)
            {
                if (attr == NULL)
                    break;
                else
                    continue;
            }

            /*
             * Allocate memory for the job...
             */

            if (n == 0)
                temp = malloc(sizeof(cups_job_t));
            else
                temp = realloc(*jobs, sizeof(cups_job_t) * (n + 1));

            if (temp == NULL)
            {
                /*
                 * Ran out of memory!
                 */

                cupsFreeJobs(n, *jobs);
                *jobs = NULL;

                ippDelete(response);
                return (0);
            }

            *jobs = temp;
            temp  += n;
            n ++;

            /*
             * Copy the data over...
             */

            temp->dest            = strdup(dest);
            temp->user            = strdup(user);
            temp->format          = strdup(format);
            temp->title           = strdup(title);
            temp->id              = id;
            temp->priority        = priority;
            temp->state           = state;
            temp->size            = size;
            temp->completed_time  = completed_time;
            temp->creation_time   = creation_time;
            temp->processing_time = processing_time;

            if (attr == NULL)
                break;
        }

        ippDelete(response);
    }

    if (n == 0 && cg->last_error >= IPP_BAD_REQUEST)
        return (-1);
    else
        return (n);
}
Exemple #9
0
int					/* O - 1 on success, 0 on failure */
cupsCancelJob(const char *name,		/* I - Name of printer or class */
              int        job)		/* I - Job ID */
{
    char		printer[HTTP_MAX_URI],	/* Printer name */
                hostname[HTTP_MAX_URI],	/* Hostname */
                uri[HTTP_MAX_URI];	/* Printer URI */
    ipp_t		*request,		/* IPP request */
                *response;		/* IPP response */
    _cups_globals_t *cg = _cupsGlobals();	/* Pointer to library globals */


    /*
     * See if we can connect to the server...
     */

    if (!cups_connect(name, printer, hostname))
    {
        DEBUG_puts("Unable to connect to server!");

        return (0);
    }

    /*
     * Create a printer URI...
     */

    if (httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
                         "localhost", 0, "/printers/%s", printer) != HTTP_URI_OK)
    {
        _cupsSetError(IPP_INTERNAL_ERROR, NULL);

        return (0);
    }

    /*
     * Build an IPP_CANCEL_JOB request, which requires the following
     * attributes:
     *
     *    attributes-charset
     *    attributes-natural-language
     *    printer-uri
     *    job-id
     *    [requesting-user-name]
     */

    request = ippNewRequest(IPP_CANCEL_JOB);

    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
                 NULL, uri);

    ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", job);

    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
                 NULL, cupsUser());

    /*
     * Do the request...
     */

    if ((response = cupsDoRequest(cg->http, request, "/jobs/")) != NULL)
        ippDelete(response);

    return (cg->last_error < IPP_REDIRECTION_OTHER_SITE);
}
Exemple #10
0
int					/* O - Exit status */
main(int  argc,				/* I - Number of command-line arguments */
     char *argv[])			/* I - Command-line arguments */
{
  int		i;			/* Looping var */
  char		*command,		/* Command to do */
		*opt,			/* Option pointer */
		uri[1024],		/* Printer URI */
		*reason;		/* Reason for reject/disable */
  ipp_t		*request;		/* IPP request */
  ipp_op_t	op;			/* Operation */
  int		cancel;			/* Cancel jobs? */


  _cupsSetLocale(argv);

 /*
  * See what operation we're supposed to do...
  */

  if ((command = strrchr(argv[0], '/')) != NULL)
    command ++;
  else
    command = argv[0];

  cancel = 0;

  if (!strcmp(command, "cupsaccept"))
    op = CUPS_ACCEPT_JOBS;
  else if (!strcmp(command, "cupsreject"))
    op = CUPS_REJECT_JOBS;
  else if (!strcmp(command, "cupsdisable"))
    op = IPP_PAUSE_PRINTER;
  else if (!strcmp(command, "cupsenable"))
    op = IPP_RESUME_PRINTER;
  else
  {
    _cupsLangPrintf(stderr, _("%s: Don't know what to do."), command);
    return (1);
  }

  reason = NULL;

 /*
  * Process command-line arguments...
  */

  for (i = 1; i < argc; i ++)
  {
    if (!strcmp(argv[i], "--help"))
      usage(command);
    else if (!strcmp(argv[i], "--hold"))
      op = IPP_HOLD_NEW_JOBS;
    else if (!strcmp(argv[i], "--release"))
      op = IPP_RELEASE_HELD_NEW_JOBS;
    else if (argv[i][0] == '-')
    {
      for (opt = argv[i] + 1; *opt; opt ++)
      {
	switch (*opt)
	{
	  case 'E' : /* Encrypt */
#ifdef HAVE_SSL
	      cupsSetEncryption(HTTP_ENCRYPT_REQUIRED);
#else
	      _cupsLangPrintf(stderr, _("%s: Sorry, no encryption support."), command);
#endif /* HAVE_SSL */
	      break;

	  case 'U' : /* Username */
	      if (opt[1] != '\0')
	      {
		cupsSetUser(opt + 1);
		opt += strlen(opt) - 1;
	      }
	      else
	      {
		i ++;
		if (i >= argc)
		{
		  _cupsLangPrintf(stderr, _("%s: Error - expected username after \"-U\" option."), command);
		  usage(command);
		}

		cupsSetUser(argv[i]);
	      }
	      break;

	  case 'c' : /* Cancel jobs */
	      cancel = 1;
	      break;

	  case 'h' : /* Connect to host */
	      if (opt[1] != '\0')
	      {
		cupsSetServer(opt + 1);
		opt += strlen(opt) - 1;
	      }
	      else
	      {
		i ++;
		if (i >= argc)
		{
		  _cupsLangPrintf(stderr, _("%s: Error - expected hostname after \"-h\" option."), command);
		  usage(command);
		}

		cupsSetServer(argv[i]);
	      }
	      break;

	  case 'r' : /* Reason for cancellation */
	      if (opt[1] != '\0')
	      {
		reason = opt + 1;
		opt += strlen(opt) - 1;
	      }
	      else
	      {
		i ++;
		if (i >= argc)
		{
		  _cupsLangPrintf(stderr, _("%s: Error - expected reason text after \"-r\" option."), command);
		  usage(command);
		}

		reason = argv[i];
	      }
	      break;

	  default :
	      _cupsLangPrintf(stderr, _("%s: Error - unknown option \"%c\"."), command, *opt);
	      usage(command);
	}
      }
    }
    else
    {
     /*
      * Accept/disable/enable/reject a destination...
      */

      request = ippNewRequest(op);

      httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
                       "localhost", 0, "/printers/%s", argv[i]);
      ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
                   "printer-uri", NULL, uri);

      ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
                   "requesting-user-name", NULL, cupsUser());

      if (reason != NULL)
	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_TEXT,
                     "printer-state-message", NULL, reason);

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

      ippDelete(cupsDoRequest(CUPS_HTTP_DEFAULT, request, "/admin/"));

      if (cupsLastError() > IPP_OK_CONFLICT)
      {
	_cupsLangPrintf(stderr,
			_("%s: Operation failed: %s"),
			command, ippErrorString(cupsLastError()));
	return (1);
      }

     /*
      * Cancel all jobs if requested...
      */

      if (cancel)
      {
       /*
	* Build an IPP_PURGE_JOBS request, which requires the following
	* attributes:
	*
	*    attributes-charset
	*    attributes-natural-language
	*    printer-uri
	*/

	request = ippNewRequest(IPP_PURGE_JOBS);

	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
                     "printer-uri", NULL, uri);

	ippDelete(cupsDoRequest(CUPS_HTTP_DEFAULT, request, "/admin/"));

        if (cupsLastError() > IPP_OK_CONFLICT)
	{
	  _cupsLangPrintf(stderr, "%s: %s", command, cupsLastErrorString());
	  return (1);
	}
      }
    }
  }

  return (0);
}
Exemple #11
0
int					/* O - Job ID */
cupsPrintFiles2(http_t        *http,	/* I - HTTP connection */
                const char    *name,	/* I - Printer or class name */
                int           num_files,/* I - Number of files */
                const char    **files,	/* I - File(s) to print */
                const char    *title,	/* I - Title of job */
                int           num_options,
                /* I - Number of options */
                cups_option_t *options)	/* I - Options */
{
    int		i;			/* Looping var */
    const char	*val;			/* Pointer to option value */
    ipp_t		*request;		/* IPP request */
    ipp_t		*response;		/* IPP response */
    ipp_attribute_t *attr;		/* IPP job-id attribute */
    char		uri[HTTP_MAX_URI];	/* Printer URI */
    int		jobid;			/* New job ID */
    const char	*base;			/* Basename of current filename */


    DEBUG_printf(("cupsPrintFiles(http=%p, name=\"%s\", num_files=%d, "
                  "files=%p, title=\"%s\", num_options=%d, options=%p)\n",
                  http, name, num_files, files, title, num_options, options));

    /*
     * Range check input...
     */

    if (!http || !name || num_files < 1 || files == NULL)
    {
        _cupsSetError(IPP_INTERNAL_ERROR, NULL);

        return (0);
    }

    /*
     * Setup the printer URI...
     */

    if (httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
                         "localhost", 0, "/printers/%s", name) != HTTP_URI_OK)
    {
        _cupsSetError(IPP_INTERNAL_ERROR, NULL);

        return (0);
    }

    /*
     * Build a standard CUPS URI for the printer and fill the standard IPP
     * attributes...
     */

    if ((request = ippNewRequest(num_files == 1 ? IPP_PRINT_JOB :
                                 IPP_CREATE_JOB)) == NULL)
    {
        _cupsSetError(IPP_INTERNAL_ERROR, NULL);

        return (0);
    }

    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
                 NULL, uri);

    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
                 NULL, cupsUser());

    if (title)
        ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL,
                     title);

    /*
     * Then add all options...
     */

    cupsEncodeOptions(request, num_options, options);

    /*
     * Do the request...
     */

    snprintf(uri, sizeof(uri), "/printers/%s", name);

    if (num_files == 1)
        response = cupsDoFileRequest(http, request, uri, *files);
    else
        response = cupsDoRequest(http, request, uri);

    if (response == NULL)
        jobid = 0;
    else if (response->request.status.status_code > IPP_OK_CONFLICT)
    {
        DEBUG_printf(("IPP response code was 0x%x!\n",
                      response->request.status.status_code));
        jobid = 0;
    }
    else if ((attr = ippFindAttribute(response, "job-id", IPP_TAG_INTEGER)) == NULL)
    {
        DEBUG_puts("No job ID!");

        _cupsSetError(IPP_INTERNAL_ERROR, NULL);

        jobid = 0;
    }
    else
        jobid = attr->values[0].integer;

    if (response != NULL)
        ippDelete(response);

    /*
     * Handle multiple file jobs if the create-job operation worked...
     */

    if (jobid > 0 && num_files > 1)
        for (i = 0; i < num_files; i ++)
        {
            /*
             * Build a standard CUPS URI for the job and fill the standard IPP
             * attributes...
             */

            if ((request = ippNewRequest(IPP_SEND_DOCUMENT)) == NULL)
                return (0);

            snprintf(uri, sizeof(uri), "ipp://localhost/jobs/%d", jobid);

            ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri",
                         NULL, uri);

            /*
             * Handle raw print files...
             */

            if (cupsGetOption("raw", num_options, options))
                ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE,
                             "document-format", NULL, "application/vnd.cups-raw");
            else if ((val = cupsGetOption("document-format", num_options,
                                          options)) != NULL)
                ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE,
                             "document-format", NULL, val);
            else
                ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE,
                             "document-format", NULL, "application/octet-stream");

            ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
                         "requesting-user-name", NULL, cupsUser());

            /*
             * Add the original document filename...
             */

            if ((base = strrchr(files[i], '/')) != NULL)
                base ++;
            else
                base = files[i];

            ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "document-name",
                         NULL, base);

            /*
             * Is this the last document?
             */

            if (i == (num_files - 1))
                ippAddBoolean(request, IPP_TAG_OPERATION, "last-document", 1);

            /*
             * Send the file...
             */

            snprintf(uri, sizeof(uri), "/printers/%s", name);

            if ((response = cupsDoFileRequest(http, request, uri,
                                              files[i])) != NULL)
                ippDelete(response);
        }

    return (jobid);
}
Exemple #12
0
///////////////////////////////////////////////////////////////////////////////////////////
//
// CS     : PRIVATE gint getJobID(gchar *pDestName, gchar *pURI, gchar *pServerName, gint *pJobID)
// IN     : gchar *pDestName : Printer name.
//          gchar *pURI : Printer URI.
//          gchar *pServerName : CUPS server name.
// OUT    : gint *pJobID : Job ID.
// RETURN : ID_ERR_NO_ERROR : No error.
//          ID_ERR_CUPS_API_FAILED : Error occured in CUPS API.
//
PRIVATE gint getJobID(gchar *pDestName, gchar *pURI, gchar *pServerName, gint *pJobID)
{
/*** Parameters start ***/
	http_t			*pHTTP;									// Pointer to HTTP connection.
	ipp_t			*pRequest,								// Pointer to CUPS IPP request.
					*pResponse;								// Pointer to CUPS IPP response.
	ipp_attribute_t	*pAttribute;							// Pointer to CUPS attributes.
	cups_lang_t		*pLanguage;								// Pointer to language.
	ipp_jstate_t	jobState = 0;							// Job state.
	gint			jobID = 0;								// Job ID.
	gchar			*pJobUserName = NULL;					// User name of print job.
	uid_t			userID;									// User ID.
	struct passwd	*pPasswd;								// Pointer to password structure.
	gint			retVal = ID_ERR_PRINT_JOB_NOT_EXIST;	// Return value.
/*** Parameters end ***/

	// Get login name.
	userID = getuid();
	pPasswd = getpwuid(userID);

	// CUPS http connect.
	if ((pHTTP = httpConnectEncrypt(pServerName, ippPort(), cupsEncryption())) == NULL) {
		retVal = ID_ERR_CUPS_API_FAILED;
	}
	else {
		pRequest = ippNew();

		ippSetOperation(pRequest, IPP_GET_JOBS);
		ippSetRequestId(pRequest, 1);

		pLanguage = bjcupsLangDefault();	// cupsLangDefault() -> bjcupsLangDefault() for cups-1.1.19

		ippAddString(pRequest, IPP_TAG_OPERATION, IPP_TAG_CHARSET, "attributes-charset", NULL, cupsLangEncoding(pLanguage));
		ippAddString(pRequest, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, "attributes-natural-language", NULL, pLanguage->language);
		ippAddString(pRequest, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, pURI);
		ippAddString(pRequest, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser());

		if ((pResponse = cupsDoRequest(pHTTP, pRequest, "/")) != NULL) {
            int statusCode = ippGetStatusCode(pResponse);
			if (statusCode > IPP_OK_CONFLICT) {
				retVal = ID_ERR_CUPS_API_FAILED;
			}
			else {
				pAttribute = ippFirstAttribute(pResponse);

				while (pAttribute != NULL) {
					while (pAttribute != NULL && ippGetGroupTag(pAttribute) != IPP_TAG_JOB) {
						pAttribute = bjcups_ippNextAttribute(pResponse, pAttribute);
					}
					if (pAttribute == NULL) {
						break;
					}

					while (pAttribute != NULL && ippGetGroupTag(pAttribute) == IPP_TAG_JOB) {
						if (strcmp(ippGetName(pAttribute), "job-id") == 0 && ippGetValueTag(pAttribute) == IPP_TAG_INTEGER) {
							jobID = ippGetInteger(pAttribute, 0);
						}
						if (strcmp(ippGetName(pAttribute), "job-uri") == 0 && ippGetValueTag(pAttribute) == IPP_TAG_URI) {
							pJobUserName=getJobState(pDestName,ippGetString(pAttribute, 0, NULL),pServerName,&jobState,pJobUserName);
						}
						pAttribute = bjcups_ippNextAttribute(pRequest, pAttribute);
					}
					if (jobState == IPP_JOB_PROCESSING) {
						if (pJobUserName != NULL) {
							if (strcmp(pPasswd->pw_name, pJobUserName) == 0) {
								retVal = ID_ERR_NO_ERROR;
							}
							else if (pJobUserName[0] == '\0') {
								retVal = ID_ERR_NO_ERROR;
							}
						}
						break;
					}

					if (pAttribute != NULL)
						pAttribute = bjcups_ippNextAttribute(pRequest, pAttribute);
				}
			}

			ippDelete(pResponse);
		}
		else {
			retVal = ID_ERR_CUPS_API_FAILED;
		}

		cupsLangFree(pLanguage);
		httpClose(pHTTP);
	}

	if (retVal == ID_ERR_NO_ERROR && pJobID != NULL) {
		*pJobID = jobID;
	}

	return(retVal);
}// End getJobID
Exemple #13
0
int					/* O - Exit status */
main(int  argc,				/* I - Number of command-line arguments */
     char *argv[])			/* I - Command-line arguments */
{
  http_t	*http;			/* HTTP connection to server */
  int		i;			/* Looping var */
  int		job_id;			/* Job ID */
  int		num_dests;		/* Number of destinations */
  cups_dest_t	*dests;			/* Destinations */
  char		*dest,			/* Destination printer */
		*job,			/* Job ID pointer */
		*user;			/* Cancel jobs for a user */
  int		purge;			/* Purge or cancel jobs? */
  char		uri[1024];		/* Printer or job URI */
  ipp_t		*request;		/* IPP request */
  ipp_t		*response;		/* IPP response */
  ipp_op_t	op;			/* Operation */


  _cupsSetLocale(argv);

 /*
  * Setup to cancel individual print jobs...
  */

  op        = IPP_CANCEL_JOB;
  purge     = 0;
  dest      = NULL;
  user      = NULL;
  http      = NULL;
  num_dests = 0;
  dests     = NULL;


 /*
  * Process command-line arguments...
  */

  for (i = 1; i < argc; i ++)
    if (argv[i][0] == '-' && argv[i][1])
      switch (argv[i][1])
      {
        case 'E' : /* Encrypt */
#ifdef HAVE_SSL
	    cupsSetEncryption(HTTP_ENCRYPT_REQUIRED);

	    if (http)
	      httpEncryption(http, HTTP_ENCRYPT_REQUIRED);
#else
            _cupsLangPrintf(stderr,
	                    _("%s: Sorry, no encryption support compiled in!\n"),
	                    argv[0]);
#endif /* HAVE_SSL */
	    break;

        case 'U' : /* Username */
	    if (argv[i][2] != '\0')
	      cupsSetUser(argv[i] + 2);
	    else
	    {
	      i ++;
	      if (i >= argc)
	      {
	        _cupsLangPrintf(stderr,
		                _("%s: Error - expected username after "
				  "\'-U\' option!\n"),
		        	argv[0]);
	        return (1);
	      }

              cupsSetUser(argv[i]);
	    }
	    break;
	    
        case 'a' : /* Cancel all jobs */
	    purge = 1;
	    op    = IPP_PURGE_JOBS;
	    break;

        case 'h' : /* Connect to host */
	    if (http != NULL)
	    {
	      httpClose(http);
	      http = NULL;
	    }

	    if (argv[i][2] != '\0')
              cupsSetServer(argv[i] + 2);
	    else
	    {
	      i ++;

	      if (i >= argc)
	      {
	        _cupsLangPrintf(stderr,
		        	_("%s: Error - expected hostname after "
			          "\'-h\' option!\n"),
				argv[0]);
		return (1);
              }
	      else
                cupsSetServer(argv[i]);
	    }
	    break;

        case 'u' : /* Username */
	    op = IPP_PURGE_JOBS;

	    if (argv[i][2] != '\0')
	      user = argv[i] + 2;
	    else
	    {
	      i ++;

	      if (i >= argc)
	      {
	        _cupsLangPrintf(stderr,
		        	_("%s: Error - expected username after "
			          "\'-u\' option!\n"),
				argv[0]);
		return (1);
              }
	      else
		user = argv[i];
	    }
	    break;

	default :
	    _cupsLangPrintf(stderr,
	                    _("%s: Error - unknown option \'%c\'!\n"),
			    argv[0], argv[i][1]);
	    return (1);
      }
    else
    {
     /*
      * Cancel a job or printer...
      */

      if (num_dests == 0)
        num_dests = cupsGetDests(&dests);

      if (!strcmp(argv[i], "-"))
      {
       /*
        * Delete the current job...
	*/

        dest   = "";
	job_id = 0;
      }
      else if (cupsGetDest(argv[i], NULL, num_dests, dests) != NULL)
      {
       /*
        * Delete the current job on the named destination...
	*/

        dest   = argv[i];
	job_id = 0;
      }
      else if ((job = strrchr(argv[i], '-')) != NULL && isdigit(job[1] & 255))
      {
       /*
        * Delete the specified job ID.
	*/

        dest   = NULL;
	op     = IPP_CANCEL_JOB;
        job_id = atoi(job + 1);
      }
      else if (isdigit(argv[i][0] & 255))
      {
       /*
        * Delete the specified job ID.
	*/

        dest   = NULL;
	op     = IPP_CANCEL_JOB;
        job_id = atoi(argv[i]);
      }
      else
      {
       /*
        * Bad printer name!
	*/

        _cupsLangPrintf(stderr,
	                _("%s: Error - unknown destination \"%s\"!\n"),
			argv[0], argv[i]);
	return (1);
      }

     /*
      * For Solaris LP compatibility, ignore a destination name after
      * cancelling a specific job ID...
      */

      if (job_id && (i + 1) < argc &&
          cupsGetDest(argv[i + 1], NULL, num_dests, dests) != NULL)
        i ++;

     /*
      * Open a connection to the server...
      */

      if (http == NULL)
	if ((http = httpConnectEncrypt(cupsServer(), ippPort(),
	                               cupsEncryption())) == NULL)
	{
	  _cupsLangPrintf(stderr,
	                  _("%s: Unable to contact server!\n"),
			  argv[0]);
	  return (1);
	}

     /*
      * Build an IPP request, which requires the following
      * attributes:
      *
      *    attributes-charset
      *    attributes-natural-language
      *    printer-uri + job-id *or* job-uri
      *    [requesting-user-name]
      */

      request = ippNewRequest(op);

      if (dest)
      {
	httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
	                 "localhost", 0, "/printers/%s", dest);
	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
	             "printer-uri", NULL, uri);
	ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id",
	              job_id);
      }
      else
      {
        sprintf(uri, "ipp://localhost/jobs/%d", job_id);
	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL,
	             uri);
      }

      if (user)
      {
	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
                     "requesting-user-name", NULL, user);
	ippAddBoolean(request, IPP_TAG_OPERATION, "my-jobs", 1);
      }
      else
	ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
                     "requesting-user-name", NULL, cupsUser());

      if (op == IPP_PURGE_JOBS)
	ippAddBoolean(request, IPP_TAG_OPERATION, "purge-jobs", purge);

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

      if (op == IPP_PURGE_JOBS && (!user || strcasecmp(user, cupsUser())))
        response = cupsDoRequest(http, request, "/admin/");
      else
        response = cupsDoRequest(http, request, "/jobs/");

      if (response == NULL ||
          response->request.status.status_code > IPP_OK_CONFLICT)
      {
	_cupsLangPrintf(stderr, _("%s: %s failed: %s\n"), argv[0],
	        	op == IPP_PURGE_JOBS ? "purge-jobs" : "cancel-job",
        		cupsLastErrorString());

	if (response)
	  ippDelete(response);

	return (1);
      }

      ippDelete(response);
    }

  if (num_dests == 0 && op == IPP_PURGE_JOBS)
  {
   /*
    * Open a connection to the server...
    */

    if (http == NULL)
      if ((http = httpConnectEncrypt(cupsServer(), ippPort(),
	                             cupsEncryption())) == NULL)
      {
	_cupsLangPrintf(stderr, _("%s: Unable to contact server!\n"),
	                argv[0]);
	return (1);
      }

   /*
    * Build an IPP request, which requires the following
    * attributes:
    *
    *    attributes-charset
    *    attributes-natural-language
    *    printer-uri + job-id *or* job-uri
    *    [requesting-user-name]
    */

    request = ippNewRequest(op);

    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
	         "printer-uri", NULL, "ipp://localhost/printers/");

    if (user)
    {
      ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
                   "requesting-user-name", NULL, user);
      ippAddBoolean(request, IPP_TAG_OPERATION, "my-jobs", 1);
    }
    else
      ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
                   "requesting-user-name", NULL, cupsUser());

    ippAddBoolean(request, IPP_TAG_OPERATION, "purge-jobs", purge);

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

    response = cupsDoRequest(http, request, "/admin/");

    if (response == NULL ||
        response->request.status.status_code > IPP_OK_CONFLICT)
    {
      _cupsLangPrintf(stderr, _("%s: %s failed: %s\n"), argv[0],
		      op == IPP_PURGE_JOBS ? "purge-jobs" : "cancel-job",
        	      cupsLastErrorString());

      if (response)
	ippDelete(response);

      return (1);
    }

    ippDelete(response);
  }

  return (0);
}
Exemple #14
0
http_status_t				/* O - Status of document creation */
cupsStartDestDocument(
    http_t        *http,		/* I - Connection to destination */
    cups_dest_t   *dest,		/* I - Destination */
    cups_dinfo_t  *info, 		/* I - Destination information */
    int           job_id,		/* I - Job ID */
    const char    *docname,		/* I - Document name */
    const char    *format,		/* I - Document format */
    int           num_options,		/* I - Number of document options */
    cups_option_t *options,		/* I - Document options */
    int           last_document)	/* I - 1 if this is the last document */
{
  ipp_t		*request;		/* Send-Document request */
  http_status_t	status;			/* HTTP status */


  DEBUG_printf(("cupsStartDestDocument(http=%p, dest=%p(%s/%s), info=%p, "
                "job_id=%d, docname=\"%s\", format=\"%s\", num_options=%d, "
                "options=%p, last_document=%d)",
                http, dest, dest ? dest->name : NULL,
                dest ? dest->instance : NULL, info, job_id, docname, format,
                num_options, options, last_document));

 /*
  * Range check input...
  */

  if (!http || !dest || !info || job_id <= 0)
  {
    _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);
    DEBUG_puts("1cupsStartDestDocument: Bad arguments.");
    return (HTTP_STATUS_ERROR);
  }

 /*
  * Create a Send-Document request...
  */

  if ((request = ippNewRequest(IPP_OP_SEND_DOCUMENT)) == NULL)
  {
    _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(ENOMEM), 0);
    DEBUG_puts("1cupsStartDestDocument: Unable to create Send-Document "
               "request.");
    return (HTTP_STATUS_ERROR);
  }

  ippSetVersion(request, info->version / 10, info->version % 10);

  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
               NULL, info->uri);
  ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", job_id);
  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
               NULL, cupsUser());
  if (docname)
    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "document-name",
                 NULL, docname);
  if (format)
    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE,
                 "document-format", NULL, format);
  ippAddBoolean(request, IPP_TAG_OPERATION, "last-document", last_document);

  cupsEncodeOptions2(request, num_options, options, IPP_TAG_OPERATION);
  cupsEncodeOptions2(request, num_options, options, IPP_TAG_DOCUMENT);

 /*
  * Send and delete the request, then return the status...
  */

  status = cupsSendRequest(http, request, info->resource, CUPS_LENGTH_VARIABLE);

  ippDelete(request);

  return (status);
}
Exemple #15
0
static int				/* O - 0 on success, 1 on fail */
add_printer_to_class(http_t *http,	/* I - Server connection */
                     char   *printer,	/* I - Printer to add */
		     char   *pclass)	/* I - Class to add to */
{
  int		i;			/* Looping var */
  ipp_t		*request,		/* IPP Request */
		*response;		/* IPP Response */
  ipp_attribute_t *attr,		/* Current attribute */
		*members;		/* Members in class */
  char		uri[HTTP_MAX_URI];	/* URI for printer/class */


  DEBUG_printf(("add_printer_to_class(%p, \"%s\", \"%s\")\n", http,
                printer, pclass));

 /*
  * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following
  * attributes:
  *
  *    attributes-charset
  *    attributes-natural-language
  *    printer-uri
  *    requesting-user-name
  */

  request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);

  httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
                   "localhost", 0, "/classes/%s", pclass);
  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
               "printer-uri", NULL, uri);
  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
               NULL, cupsUser());

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

  response = cupsDoRequest(http, request, "/");

 /*
  * Build a CUPS_ADD_MODIFY_CLASS request, which requires the following
  * attributes:
  *
  *    attributes-charset
  *    attributes-natural-language
  *    printer-uri
  *    requesting-user-name
  *    member-uris
  */

  request = ippNewRequest(CUPS_ADD_MODIFY_CLASS);

  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
               "printer-uri", NULL, uri);
  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
               NULL, cupsUser());

 /*
  * See if the printer is already in the class...
  */

  if (response != NULL &&
      (members = ippFindAttribute(response, "member-names",
                                  IPP_TAG_NAME)) != NULL)
    for (i = 0; i < members->num_values; i ++)
      if (_cups_strcasecmp(printer, members->values[i].string.text) == 0)
      {
        _cupsLangPrintf(stderr,
	                _("lpadmin: Printer %s is already a member of class "
			  "%s."), printer, pclass);
        ippDelete(request);
	ippDelete(response);
	return (0);
      }

 /*
  * OK, the printer isn't part of the class, so add it...
  */

  httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
                   "localhost", 0, "/printers/%s", printer);

  if (response != NULL &&
      (members = ippFindAttribute(response, "member-uris",
                                  IPP_TAG_URI)) != NULL)
  {
   /*
    * Add the printer to the existing list...
    */

    attr = ippAddStrings(request, IPP_TAG_PRINTER, IPP_TAG_URI,
                         "member-uris", members->num_values + 1, NULL, NULL);
    for (i = 0; i < members->num_values; i ++)
      attr->values[i].string.text =
          _cupsStrAlloc(members->values[i].string.text);

    attr->values[i].string.text = _cupsStrAlloc(uri);
  }
  else
    ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "member-uris", NULL,
                 uri);

 /*
  * Then send the request...
  */

  ippDelete(response);

  ippDelete(cupsDoRequest(http, request, "/admin/"));
  if (cupsLastError() > IPP_OK_CONFLICT)
  {
    _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString());

    return (1);
  }
  else
    return (0);
}
Exemple #16
0
static int				/* O - 0 if available */
					/*     1 if not available */
					/*    -1 error */
cups_local_auth(http_t *http)		/* I - HTTP connection to server */
{
#if defined(WIN32) || defined(__EMX__)
 /*
  * Currently WIN32 and OS-2 do not support the CUPS server...
  */

  return (1);
#else
  int			pid;		/* Current process ID */
  FILE			*fp;		/* Certificate file */
  char			trc[16],	/* Try Root Certificate parameter */
			filename[1024];	/* Certificate filename */
  _cups_globals_t *cg = _cupsGlobals();	/* Global data */
#  if defined(HAVE_AUTHORIZATION_H)
  OSStatus		status;		/* Status */
  AuthorizationItem	auth_right;	/* Authorization right */
  AuthorizationRights	auth_rights;	/* Authorization rights */
  AuthorizationFlags	auth_flags;	/* Authorization flags */
  AuthorizationExternalForm auth_extrn;	/* Authorization ref external */
  char			auth_key[1024];	/* Buffer */
  char			buffer[1024];	/* Buffer */
#  endif /* HAVE_AUTHORIZATION_H */


  DEBUG_printf(("7cups_local_auth(http=%p) hostaddr=%s, hostname=\"%s\"",
                http, httpAddrString(http->hostaddr, filename, sizeof(filename)), http->hostname));

 /*
  * See if we are accessing localhost...
  */

  if (!httpAddrLocalhost(http->hostaddr) &&
      _cups_strcasecmp(http->hostname, "localhost") != 0)
  {
    DEBUG_puts("8cups_local_auth: Not a local connection!");
    return (1);
  }

#  if defined(HAVE_AUTHORIZATION_H)
 /*
  * Delete any previous authorization reference...
  */

  if (http->auth_ref)
  {
    AuthorizationFree(http->auth_ref, kAuthorizationFlagDefaults);
    http->auth_ref = NULL;
  }

  if (!getenv("GATEWAY_INTERFACE") &&
      httpGetSubField2(http, HTTP_FIELD_WWW_AUTHENTICATE, "authkey",
		       auth_key, sizeof(auth_key)))
  {
    status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment,
				 kAuthorizationFlagDefaults, &http->auth_ref);
    if (status != errAuthorizationSuccess)
    {
      DEBUG_printf(("8cups_local_auth: AuthorizationCreate() returned %d (%s)",
		    (int)status, cssmErrorString(status)));
      return (-1);
    }

    auth_right.name        = auth_key;
    auth_right.valueLength = 0;
    auth_right.value       = NULL;
    auth_right.flags       = 0;

    auth_rights.count = 1;
    auth_rights.items = &auth_right;

    auth_flags = kAuthorizationFlagDefaults |
		 kAuthorizationFlagPreAuthorize |
		 kAuthorizationFlagInteractionAllowed |
		 kAuthorizationFlagExtendRights;

    status = AuthorizationCopyRights(http->auth_ref, &auth_rights,
				     kAuthorizationEmptyEnvironment,
				     auth_flags, NULL);
    if (status == errAuthorizationSuccess)
      status = AuthorizationMakeExternalForm(http->auth_ref, &auth_extrn);

    if (status == errAuthorizationSuccess)
    {
     /*
      * Set the authorization string and return...
      */

      httpEncode64_2(buffer, sizeof(buffer), (void *)&auth_extrn,
		     sizeof(auth_extrn));

      httpSetAuthString(http, "AuthRef", buffer);

      DEBUG_printf(("8cups_local_auth: Returning authstring=\"%s\"",
		    http->authstring));
      return (0);
    }
    else if (status == errAuthorizationCanceled)
      return (-1);

    DEBUG_printf(("9cups_local_auth: AuthorizationCopyRights() returned %d (%s)",
		  (int)status, cssmErrorString(status)));

  /*
   * Fall through to try certificates...
   */
  }
#  endif /* HAVE_AUTHORIZATION_H */

#  if defined(SO_PEERCRED) && defined(AF_LOCAL)
 /*
  * See if we can authenticate using the peer credentials provided over a
  * domain socket; if so, specify "PeerCred username" as the authentication
  * information...
  */

  if (
#    ifdef HAVE_GSSAPI
      _cups_strncasecmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Negotiate", 9) &&
#    endif /* HAVE_GSSAPI */
#    ifdef HAVE_AUTHORIZATION_H
      !httpGetSubField2(http, HTTP_FIELD_WWW_AUTHENTICATE, "authkey",
		        auth_key, sizeof(auth_key)) &&
#    endif /* HAVE_AUTHORIZATION_H */
      http->hostaddr->addr.sa_family == AF_LOCAL &&
      !getenv("GATEWAY_INTERFACE"))	/* Not via CGI programs... */
  {
   /*
    * Verify that the current cupsUser() matches the current UID...
    */

    struct passwd	*pwd;		/* Password information */
    const char		*username;	/* Current username */

    username = cupsUser();

    if ((pwd = getpwnam(username)) != NULL && pwd->pw_uid == getuid())
    {
      httpSetAuthString(http, "PeerCred", username);

      DEBUG_printf(("8cups_local_auth: Returning authstring=\"%s\"",
		    http->authstring));

      return (0);
    }
  }
#  endif /* SO_PEERCRED && AF_LOCAL */

 /*
  * Try opening a certificate file for this PID.  If that fails,
  * try the root certificate...
  */

  pid = getpid();
  snprintf(filename, sizeof(filename), "%s/certs/%d", cg->cups_statedir, pid);
  if ((fp = fopen(filename, "r")) == NULL && pid > 0)
  {
   /*
    * No certificate for this PID; see if we can get the root certificate...
    */

    DEBUG_printf(("9cups_local_auth: Unable to open file %s: %s",
                  filename, strerror(errno)));

#  ifdef HAVE_GSSAPI
    if (!_cups_strncasecmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Negotiate", 9))
    {
     /*
      * Kerberos required, don't try the root certificate...
      */

      return (1);
    }
#  endif /* HAVE_GSSAPI */

#  ifdef HAVE_AUTHORIZATION_H
    if (httpGetSubField2(http, HTTP_FIELD_WWW_AUTHENTICATE, "authkey",
		         auth_key, sizeof(auth_key)))
    {
     /*
      * Don't use the root certificate as a replacement for an authkey...
      */

      return (1);
    }
#  endif /* HAVE_AUTHORIZATION_H */
    if (!httpGetSubField2(http, HTTP_FIELD_WWW_AUTHENTICATE, "trc", trc,
	                  sizeof(trc)))
    {
     /*
      * Scheduler doesn't want us to use the root certificate...
      */

      return (1);
    }

    snprintf(filename, sizeof(filename), "%s/certs/0", cg->cups_statedir);
    fp = fopen(filename, "r");
  }

  if (fp)
  {
   /*
    * Read the certificate from the file...
    */

    char	certificate[33],	/* Certificate string */
		*certptr;		/* Pointer to certificate string */

    certptr = fgets(certificate, sizeof(certificate), fp);
    fclose(fp);

    if (certptr)
    {
     /*
      * Set the authorization string and return...
      */

      httpSetAuthString(http, "Local", certificate);

      DEBUG_printf(("8cups_local_auth: Returning authstring=\"%s\"",
		    http->authstring));

      return (0);
    }
  }

  return (1);
#endif /* WIN32 || __EMX__ */
}
Exemple #17
0
static int				/* O - Status from cups-lpd */
print_job(int  outfd,			/* I - Command file descriptor */
          int  infd,			/* I - Response file descriptor */
	  char *dest,			/* I - Destination */
	  char **args)			/* I - Arguments */
{
  int		fd;			/* Print file descriptor */
  char		command[1024],		/* Command buffer */
		control[1024],		/* Control file */
		buffer[8192];		/* Print buffer */
  int		status;			/* Status of command */
  struct stat	fileinfo;		/* File information */
  char		*jobname;		/* Job name */
  int		sequence;		/* Sequence number */
  ssize_t	bytes;			/* Bytes read/written */


 /*
  * Check the print file...
  */

  if (stat(args[0], &fileinfo))
  {
    perror(args[0]);
    return (-1);
  }

  if ((fd = open(args[0], O_RDONLY)) < 0)
  {
    perror(args[0]);
    return (-1);
  }

 /*
  * Send the "receive print job" command...
  */

  snprintf(command, sizeof(command), "\002%s\n", dest);
  if ((status = do_command(outfd, infd, command)) != 0)
  {
    close(fd);
    return (status);
  }

 /*
  * Format a control file string that will be used to submit the job...
  */

  if ((jobname = strrchr(args[0], '/')) != NULL)
    jobname ++;
  else
    jobname = args[0];

  sequence = (int)getpid() % 1000;

  snprintf(control, sizeof(control),
           "Hlocalhost\n"
           "P%s\n"
           "J%s\n"
           "ldfA%03dlocalhost\n"
           "UdfA%03dlocalhost\n"
           "N%s\n",
	   cupsUser(), jobname, sequence, sequence, jobname);

 /*
  * Send the control file...
  */

  bytes = (ssize_t)strlen(control);

  snprintf(command, sizeof(command), "\002%d cfA%03dlocalhost\n",
           (int)bytes, sequence);

  if ((status = do_command(outfd, infd, command)) != 0)
  {
    close(fd);
    return (status);
  }

  bytes ++;

  if (write(outfd, control, (size_t)bytes) < bytes)
  {
    printf("CONTROL: Unable to write %d bytes!\n", (int)bytes);
    close(fd);
    return (-1);
  }

  printf("CONTROL: Wrote %d bytes.\n", (int)bytes);

  if (read(infd, command, 1) < 1)
  {
    puts("STATUS: ERROR");
    close(fd);
    return (-1);
  }
  else
  {
    status = command[0];

    printf("STATUS: %d\n", status);
  }

 /*
  * Send the data file...
  */

  snprintf(command, sizeof(command), "\003%d dfA%03dlocalhost\n",
           (int)fileinfo.st_size, sequence);

  if ((status = do_command(outfd, infd, command)) != 0)
  {
    close(fd);
    return (status);
  }

  while ((bytes = read(fd, buffer, sizeof(buffer))) > 0)
  {
    if (write(outfd, buffer, (size_t)bytes) < bytes)
    {
      printf("DATA: Unable to write %d bytes!\n", (int)bytes);
      close(fd);
      return (-1);
    }
  }

  write(outfd, "", 1);

  close(fd);

  printf("DATA: Wrote %d bytes.\n", (int)fileinfo.st_size);

  if (read(infd, command, 1) < 1)
  {
    puts("STATUS: ERROR");
    close(fd);
    return (-1);
  }
  else
  {
    status = command[0];

    printf("STATUS: %d\n", status);
  }

  return (status);
}
Exemple #18
0
int					/* O - 0 on success, -1 on error */
cupsDoAuthentication(
    http_t     *http,			/* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
    const char *method,			/* I - Request method ("GET", "POST", "PUT") */
    const char *resource)		/* I - Resource path */
{
  const char	*password,		/* Password string */
		*www_auth;		/* WWW-Authenticate header */
  char		prompt[1024],		/* Prompt for user */
		realm[HTTP_MAX_VALUE],	/* realm="xyz" string */
		nonce[HTTP_MAX_VALUE];	/* nonce="xyz" string */
  int		localauth;		/* Local authentication result */
  _cups_globals_t *cg;			/* Global data */


  DEBUG_printf(("cupsDoAuthentication(http=%p, method=\"%s\", resource=\"%s\")",
                http, method, resource));

  if (!http)
    http = _cupsConnect();

  if (!http || !method || !resource)
    return (-1);

  DEBUG_printf(("2cupsDoAuthentication: digest_tries=%d, userpass=\"%s\"",
                http->digest_tries, http->userpass));
  DEBUG_printf(("2cupsDoAuthentication: WWW-Authenticate=\"%s\"",
                httpGetField(http, HTTP_FIELD_WWW_AUTHENTICATE)));

 /*
  * Clear the current authentication string...
  */

  httpSetAuthString(http, NULL, NULL);

 /*
  * See if we can do local authentication...
  */

  if (http->digest_tries < 3)
  {
    if ((localauth = cups_local_auth(http)) == 0)
    {
      DEBUG_printf(("2cupsDoAuthentication: authstring=\"%s\"",
                    http->authstring));

      if (http->status == HTTP_STATUS_UNAUTHORIZED)
	http->digest_tries ++;

      return (0);
    }
    else if (localauth == -1)
    {
      http->status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED;
      return (-1);			/* Error or canceled */
    }
  }

 /*
  * Nope, see if we should retry the current username:password...
  */

  www_auth = http->fields[HTTP_FIELD_WWW_AUTHENTICATE];

  if ((http->digest_tries > 1 || !http->userpass[0]) &&
      (!_cups_strncasecmp(www_auth, "Basic", 5) ||
       !_cups_strncasecmp(www_auth, "Digest", 6)))
  {
   /*
    * Nope - get a new password from the user...
    */

    char default_username[HTTP_MAX_VALUE];
					/* Default username */

    cg = _cupsGlobals();

    if (!cg->lang_default)
      cg->lang_default = cupsLangDefault();

    if (httpGetSubField(http, HTTP_FIELD_WWW_AUTHENTICATE, "username",
                        default_username))
      cupsSetUser(default_username);

    snprintf(prompt, sizeof(prompt),
             _cupsLangString(cg->lang_default, _("Password for %s on %s? ")),
	     cupsUser(),
	     http->hostname[0] == '/' ? "localhost" : http->hostname);

    http->digest_tries  = _cups_strncasecmp(www_auth, "Digest", 6) != 0;
    http->userpass[0]   = '\0';

    if ((password = cupsGetPassword2(prompt, http, method, resource)) == NULL)
    {
      http->status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED;
      return (-1);
    }

    snprintf(http->userpass, sizeof(http->userpass), "%s:%s", cupsUser(),
             password);
  }
  else if (http->status == HTTP_STATUS_UNAUTHORIZED)
    http->digest_tries ++;

  if (http->status == HTTP_STATUS_UNAUTHORIZED && http->digest_tries >= 3)
  {
    DEBUG_printf(("1cupsDoAuthentication: Too many authentication tries (%d)",
		  http->digest_tries));

    http->status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED;
    return (-1);
  }

 /*
  * Got a password; encode it for the server...
  */

#ifdef HAVE_GSSAPI
  if (!_cups_strncasecmp(www_auth, "Negotiate", 9))
  {
   /*
    * Kerberos authentication...
    */

    if (_cupsSetNegotiateAuthString(http, method, resource))
    {
      http->status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED;
      return (-1);
    }
  }
  else
#endif /* HAVE_GSSAPI */
  if (!_cups_strncasecmp(www_auth, "Basic", 5))
  {
   /*
    * Basic authentication...
    */

    char	encode[256];		/* Base64 buffer */


    httpEncode64_2(encode, sizeof(encode), http->userpass,
                   (int)strlen(http->userpass));
    httpSetAuthString(http, "Basic", encode);
  }
  else if (!_cups_strncasecmp(www_auth, "Digest", 6))
  {
   /*
    * Digest authentication...
    */

    char	encode[33],		/* MD5 buffer */
		digest[1024];		/* Digest auth data */

    httpGetSubField(http, HTTP_FIELD_WWW_AUTHENTICATE, "realm", realm);
    httpGetSubField(http, HTTP_FIELD_WWW_AUTHENTICATE, "nonce", nonce);

    httpMD5(cupsUser(), realm, strchr(http->userpass, ':') + 1, encode);
    httpMD5Final(nonce, method, resource, encode);
    snprintf(digest, sizeof(digest),
	     "username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", "
	     "response=\"%s\"", cupsUser(), realm, nonce, resource, encode);
    httpSetAuthString(http, "Digest", digest);
  }
  else
  {
    DEBUG_printf(("1cupsDoAuthentication: Unknown auth type: \"%s\"",
                  www_auth));
    http->status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED;
    return (-1);
  }

  DEBUG_printf(("1cupsDoAuthentication: authstring=\"%s\"", http->authstring));

  return (0);
}
int KCupsConnection::renewDBusSubscription(int subscriptionId, int leaseDuration, const QStringList &events)
{
    int ret = -1;

    if (!readyToStart()) {
        kWarning() << "Tryied to run on the wrong thread";
        return subscriptionId; // This is not intended to be used in the gui thread
    }

    ipp_t *response = NULL;
    do {
        ipp_t *request;
        ipp_op_e operation;

        // check if we have a valid subscription ID
        if (subscriptionId >= 0) {
            // Add the "notify-events" values to the request
            operation = IPP_RENEW_SUBSCRIPTION;
        } else {
            operation = IPP_CREATE_PRINTER_SUBSCRIPTION;
        }

        // Lets create the request
        request = ippNewRequest(operation);
        ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
                     KCUPS_PRINTER_URI, NULL, "/");
        ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
                     "requesting-user-name", NULL, cupsUser());

        if (operation == IPP_CREATE_PRINTER_SUBSCRIPTION) {
            // Add the "notify-events" values to the request
            QVariantHash values;
            values["notify-events"] = events;
            requestAddValues(request, values);

            ippAddString(request, IPP_TAG_SUBSCRIPTION, IPP_TAG_KEYWORD,
                         "notify-pull-method", NULL, "ippget");
            ippAddString(request, IPP_TAG_SUBSCRIPTION, IPP_TAG_URI,
                         "notify-recipient-uri", NULL, "dbus://");
            ippAddInteger(request, IPP_TAG_SUBSCRIPTION, IPP_TAG_INTEGER,
                          "notify-lease-duration", leaseDuration);
        } else {
            ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER,
                          "notify-subscription-id", subscriptionId);
            ippAddInteger(request, IPP_TAG_SUBSCRIPTION, IPP_TAG_INTEGER,
                          "notify-lease-duration", leaseDuration);
        }

        // Do the request
        response = cupsDoRequest(CUPS_HTTP_DEFAULT, request, "/");
    } while (retry("/"));

#ifdef HAVE_CUPS_1_6
    if (response && ippGetStatusCode(response) == IPP_OK) {
#else
    if (response && response->request.status.status_code == IPP_OK) {
#endif // HAVE_CUPS_1_6
        ipp_attribute_t *attr;
        if (subscriptionId >= 0) {
            // Request was ok, just return the current subscription
            ret = subscriptionId;
        } else if ((attr = ippFindAttribute(response,
                                            "notify-subscription-id",
                                            IPP_TAG_INTEGER)) == NULL) {
            kWarning() << "No notify-subscription-id in response!";
            ret = -1;
        } else {
#ifdef HAVE_CUPS_1_6
            ret = ippGetInteger(attr, 0);
        }
    } else if (subscriptionId >= 0 && response && ippGetStatusCode(response) == IPP_NOT_FOUND) {
        kDebug() << "Subscription not found";
        // When the subscription is not found try to get a new one
        return renewDBusSubscription(-1, leaseDuration, events);
#else
            ret = attr->values[0].integer;
        }
    } else if (subscriptionId >= 0 && response && response->request.status.status_code == IPP_NOT_FOUND) {
        kDebug() << "Subscription not found";
        // When the subscription is not found try to get a new one
        return renewDBusSubscription(-1, leaseDuration, events);
#endif // HAVE_CUPS_1_6
    } else {
        kWarning() << "Request failed" << lastError();
        // When the server stops/restarts we will have some error so ignore it
        ret = subscriptionId;
    }

    ippDelete(response);

    return ret;
}
ReturnArguments KCupsConnection::request(ipp_op_e operation,
                                         const char *resource,
                                         const QVariantHash &reqValues,
                                         bool needResponse)
{
    ReturnArguments ret;

    if (!readyToStart()) {
        return ret; // This is not intended to be used in the gui thread
    }

    ipp_t *response = NULL;
    bool needDestName = false;
    int group_tag = IPP_TAG_PRINTER;
    do {
        ipp_t *request;
        bool isClass = false;
        QString filename;
        QVariantHash values = reqValues;

        ippDelete(response);

        if (values.contains(QLatin1String("printer-is-class"))) {
            isClass = values.take(QLatin1String("printer-is-class")).toBool();
        }
        if (values.contains(QLatin1String("need-dest-name"))) {
            needDestName = values.take(QLatin1String("need-dest-name")).toBool();
        }
        if (values.contains(QLatin1String("group-tag-qt"))) {
            group_tag = values.take(QLatin1String("group-tag-qt")).toInt();
        }

        if (values.contains(QLatin1String("filename"))) {
            filename = values.take(QLatin1String("filename")).toString();
        }

        // Lets create the request
        if (values.contains(QLatin1String(KCUPS_PRINTER_NAME))) {
            request = ippNewDefaultRequest(values.take(QLatin1String(KCUPS_PRINTER_NAME)).toString(),
                                           isClass,
                                           operation);
        } else {
            request = ippNewRequest(operation);
        }

        // send our user name on the request too
        ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
                     "requesting-user-name", NULL, cupsUser());

        // Add the requested values to the request
        requestAddValues(request, values);

        // Do the request
        // do the request deleting the response
        if (filename.isEmpty()) {
            response = cupsDoRequest(CUPS_HTTP_DEFAULT, request, resource);
        } else {
            response = cupsDoFileRequest(CUPS_HTTP_DEFAULT, request, resource, filename.toUtf8());
        }
    } while (retry(resource));

    if (response != NULL && needResponse) {
        ret = parseIPPVars(response, group_tag, needDestName);
    }
    ippDelete(response);

    return ret;
}
Exemple #21
0
int					/* O - Exit status */
main(int  argc,				/* I - Number of command-line arguments */
     char *argv[])			/* I - Command-line arguments */
{
  int		i;			/* Looping var */
  http_t	*http;			/* HTTP connection */
  const char	*server = NULL;		/* Hostname from command-line */
  int		port = 0;		/* Port number */
  const char	*cipherName = "UNKNOWN";/* Cipher suite name */
  int		dhBits = 0;		/* Diffie-Hellman bits */
  int		tlsVersion = 0;		/* TLS version number */
  char		uri[1024],		/* Printer URI */
		scheme[32],		/* URI scheme */
		host[256],		/* Hostname */
		userpass[256],		/* Username/password */
		resource[256];		/* Resource path */
  int		af = AF_UNSPEC,		/* Address family */
		tls_options = _HTTP_TLS_NONE,
					/* TLS options */
		tls_min_version = _HTTP_TLS_1_0,
		tls_max_version = _HTTP_TLS_MAX,
		verbose = 0;		/* Verbosity */
  ipp_t		*request,		/* IPP Get-Printer-Attributes request */
		*response;		/* IPP Get-Printer-Attributes response */
  ipp_attribute_t *attr;		/* Current attribute */
  const char	*name;			/* Attribute name */
  char		value[1024];		/* Attribute (string) value */
  static const char * const pattrs[] =	/* Requested attributes */
  {
    "color-supported",
    "compression-supported",
    "document-format-supported",
    "pages-per-minute",
    "printer-location",
    "printer-make-and-model",
    "printer-state",
    "printer-state-reasons",
    "sides-supported",
    "uri-authentication-supported",
    "uri-security-supported"
  };


  for (i = 1; i < argc; i ++)
  {
    if (!strcmp(argv[i], "--dh"))
    {
      tls_options |= _HTTP_TLS_ALLOW_DH;
    }
    else if (!strcmp(argv[i], "--no-cbc"))
    {
      tls_options |= _HTTP_TLS_DENY_CBC;
    }
    else if (!strcmp(argv[i], "--no-tls10"))
    {
      tls_min_version = _HTTP_TLS_1_1;
    }
    else if (!strcmp(argv[i], "--tls10"))
    {
      tls_min_version = _HTTP_TLS_1_0;
      tls_max_version = _HTTP_TLS_1_0;
    }
    else if (!strcmp(argv[i], "--rc4"))
    {
      tls_options |= _HTTP_TLS_ALLOW_RC4;
    }
    else if (!strcmp(argv[i], "--verbose") || !strcmp(argv[i], "-v"))
    {
      verbose = 1;
    }
    else if (!strcmp(argv[i], "-4"))
    {
      af = AF_INET;
    }
    else if (!strcmp(argv[i], "-6"))
    {
      af = AF_INET6;
    }
    else if (argv[i][0] == '-')
    {
      printf("tlscheck: Unknown option '%s'.\n", argv[i]);
      usage();
    }
    else if (!server)
    {
      if (!strncmp(argv[i], "ipps://", 7))
      {
        httpSeparateURI(HTTP_URI_CODING_ALL, argv[i], scheme, sizeof(scheme), userpass, sizeof(userpass), host, sizeof(host), &port, resource, sizeof(resource));
        server = host;
      }
      else
      {
        server = argv[i];
        strlcpy(resource, "/ipp/print", sizeof(resource));
      }
    }
    else if (!port && (argv[i][0] == '=' || isdigit(argv[i][0] & 255)))
    {
      if (argv[i][0] == '=')
	port = atoi(argv[i] + 1);
      else
	port = atoi(argv[i]);
    }
    else
    {
      printf("tlscheck: Unexpected argument '%s'.\n", argv[i]);
      usage();
    }
  }

  if (!server)
    usage();

  if (!port)
    port = 631;

  _httpTLSSetOptions(tls_options, tls_min_version, tls_max_version);

  http = httpConnect2(server, port, NULL, af, HTTP_ENCRYPTION_ALWAYS, 1, 30000, NULL);
  if (!http)
  {
    printf("%s: ERROR (%s)\n", server, cupsLastErrorString());
    return (1);
  }

#ifdef __APPLE__
  SSLProtocol protocol;
  SSLCipherSuite cipher;
  char unknownCipherName[256];
  int paramsNeeded = 0;
  const void *params;
  size_t paramsLen;
  OSStatus err;

  if ((err = SSLGetNegotiatedProtocolVersion(http->tls, &protocol)) != noErr)
  {
    printf("%s: ERROR (No protocol version - %d)\n", server, (int)err);
    httpClose(http);
    return (1);
  }

  switch (protocol)
  {
    default :
        tlsVersion = 0;
        break;
    case kSSLProtocol3 :
        tlsVersion = 30;
        break;
    case kTLSProtocol1 :
        tlsVersion = 10;
        break;
    case kTLSProtocol11 :
        tlsVersion = 11;
        break;
    case kTLSProtocol12 :
        tlsVersion = 12;
        break;
  }

  if ((err = SSLGetNegotiatedCipher(http->tls, &cipher)) != noErr)
  {
    printf("%s: ERROR (No cipher suite - %d)\n", server, (int)err);
    httpClose(http);
    return (1);
  }

  switch (cipher)
  {
    case TLS_NULL_WITH_NULL_NULL:
	cipherName = "TLS_NULL_WITH_NULL_NULL";
	break;
    case TLS_RSA_WITH_NULL_MD5:
	cipherName = "TLS_RSA_WITH_NULL_MD5";
	break;
    case TLS_RSA_WITH_NULL_SHA:
	cipherName = "TLS_RSA_WITH_NULL_SHA";
	break;
    case TLS_RSA_WITH_RC4_128_MD5:
	cipherName = "TLS_RSA_WITH_RC4_128_MD5";
	break;
    case TLS_RSA_WITH_RC4_128_SHA:
	cipherName = "TLS_RSA_WITH_RC4_128_SHA";
	break;
    case TLS_RSA_WITH_3DES_EDE_CBC_SHA:
	cipherName = "TLS_RSA_WITH_3DES_EDE_CBC_SHA";
	break;
    case TLS_RSA_WITH_NULL_SHA256:
	cipherName = "TLS_RSA_WITH_NULL_SHA256";
	break;
    case TLS_RSA_WITH_AES_128_CBC_SHA256:
	cipherName = "TLS_RSA_WITH_AES_128_CBC_SHA256";
	break;
    case TLS_RSA_WITH_AES_256_CBC_SHA256:
	cipherName = "TLS_RSA_WITH_AES_256_CBC_SHA256";
	break;
    case TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA:
	cipherName = "TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA";
	paramsNeeded = 1;
	break;
    case TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA:
	cipherName = "TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA";
	paramsNeeded = 1;
	break;
    case TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
	cipherName = "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA";
	paramsNeeded = 1;
	break;
    case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
	cipherName = "TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA";
	paramsNeeded = 1;
	break;
    case TLS_DH_DSS_WITH_AES_128_CBC_SHA256:
	cipherName = "TLS_DH_DSS_WITH_AES_128_CBC_SHA256";
	paramsNeeded = 1;
	break;
    case TLS_DH_RSA_WITH_AES_128_CBC_SHA256:
	cipherName = "TLS_DH_RSA_WITH_AES_128_CBC_SHA256";
	paramsNeeded = 1;
	break;
    case TLS_DHE_DSS_WITH_AES_128_CBC_SHA256:
	cipherName = "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256";
	paramsNeeded = 1;
	break;
    case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
	cipherName = "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256";
	paramsNeeded = 1;
	break;
    case TLS_DH_DSS_WITH_AES_256_CBC_SHA256:
	cipherName = "TLS_DH_DSS_WITH_AES_256_CBC_SHA256";
	paramsNeeded = 1;
	break;
    case TLS_DH_RSA_WITH_AES_256_CBC_SHA256:
	cipherName = "TLS_DH_RSA_WITH_AES_256_CBC_SHA256";
	paramsNeeded = 1;
	break;
    case TLS_DHE_DSS_WITH_AES_256_CBC_SHA256:
	cipherName = "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256";
	paramsNeeded = 1;
	break;
    case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
	cipherName = "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256";
	paramsNeeded = 1;
	break;
    case TLS_DH_anon_WITH_RC4_128_MD5:
	cipherName = "TLS_DH_anon_WITH_RC4_128_MD5";
	paramsNeeded = 1;
	break;
    case TLS_DH_anon_WITH_3DES_EDE_CBC_SHA:
	cipherName = "TLS_DH_anon_WITH_3DES_EDE_CBC_SHA";
	paramsNeeded = 1;
	break;
    case TLS_DH_anon_WITH_AES_128_CBC_SHA256:
	cipherName = "TLS_DH_anon_WITH_AES_128_CBC_SHA256";
	paramsNeeded = 1;
	break;
    case TLS_DH_anon_WITH_AES_256_CBC_SHA256:
	cipherName = "TLS_DH_anon_WITH_AES_256_CBC_SHA256";
	paramsNeeded = 1;
	break;
    case TLS_PSK_WITH_RC4_128_SHA:
	cipherName = "TLS_PSK_WITH_RC4_128_SHA";
	break;
    case TLS_PSK_WITH_3DES_EDE_CBC_SHA:
	cipherName = "TLS_PSK_WITH_3DES_EDE_CBC_SHA";
	break;
    case TLS_PSK_WITH_AES_128_CBC_SHA:
	cipherName = "TLS_PSK_WITH_AES_128_CBC_SHA";
	break;
    case TLS_PSK_WITH_AES_256_CBC_SHA:
	cipherName = "TLS_PSK_WITH_AES_256_CBC_SHA";
	break;
    case TLS_DHE_PSK_WITH_RC4_128_SHA:
	cipherName = "TLS_DHE_PSK_WITH_RC4_128_SHA";
	paramsNeeded = 1;
	break;
    case TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA:
	cipherName = "TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA";
	paramsNeeded = 1;
	break;
    case TLS_DHE_PSK_WITH_AES_128_CBC_SHA:
	cipherName = "TLS_DHE_PSK_WITH_AES_128_CBC_SHA";
	paramsNeeded = 1;
	break;
    case TLS_DHE_PSK_WITH_AES_256_CBC_SHA:
	cipherName = "TLS_DHE_PSK_WITH_AES_256_CBC_SHA";
	paramsNeeded = 1;
	break;
    case TLS_RSA_PSK_WITH_RC4_128_SHA:
	cipherName = "TLS_RSA_PSK_WITH_RC4_128_SHA";
	break;
    case TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA:
	cipherName = "TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA";
	break;
    case TLS_RSA_PSK_WITH_AES_128_CBC_SHA:
	cipherName = "TLS_RSA_PSK_WITH_AES_128_CBC_SHA";
	break;
    case TLS_RSA_PSK_WITH_AES_256_CBC_SHA:
	cipherName = "TLS_RSA_PSK_WITH_AES_256_CBC_SHA";
	break;
    case TLS_PSK_WITH_NULL_SHA:
	cipherName = "TLS_PSK_WITH_NULL_SHA";
	break;
    case TLS_DHE_PSK_WITH_NULL_SHA:
	cipherName = "TLS_DHE_PSK_WITH_NULL_SHA";
	paramsNeeded = 1;
	break;
    case TLS_RSA_PSK_WITH_NULL_SHA:
	cipherName = "TLS_RSA_PSK_WITH_NULL_SHA";
	break;
    case TLS_RSA_WITH_AES_128_GCM_SHA256:
	cipherName = "TLS_RSA_WITH_AES_128_GCM_SHA256";
	break;
    case TLS_RSA_WITH_AES_256_GCM_SHA384:
	cipherName = "TLS_RSA_WITH_AES_256_GCM_SHA384";
	break;
    case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
	cipherName = "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256";
	paramsNeeded = 1;
	break;
    case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:
	cipherName = "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384";
	paramsNeeded = 1;
	break;
    case TLS_DH_RSA_WITH_AES_128_GCM_SHA256:
	cipherName = "TLS_DH_RSA_WITH_AES_128_GCM_SHA256";
	paramsNeeded = 1;
	break;
    case TLS_DH_RSA_WITH_AES_256_GCM_SHA384:
	cipherName = "TLS_DH_RSA_WITH_AES_256_GCM_SHA384";
	paramsNeeded = 1;
	break;
    case TLS_DHE_DSS_WITH_AES_128_GCM_SHA256:
	cipherName = "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256";
	paramsNeeded = 1;
	break;
    case TLS_DHE_DSS_WITH_AES_256_GCM_SHA384:
	cipherName = "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384";
	paramsNeeded = 1;
	break;
    case TLS_DH_DSS_WITH_AES_128_GCM_SHA256:
	cipherName = "TLS_DH_DSS_WITH_AES_128_GCM_SHA256";
	paramsNeeded = 1;
	break;
    case TLS_DH_DSS_WITH_AES_256_GCM_SHA384:
	cipherName = "TLS_DH_DSS_WITH_AES_256_GCM_SHA384";
	paramsNeeded = 1;
	break;
    case TLS_DH_anon_WITH_AES_128_GCM_SHA256:
	cipherName = "TLS_DH_anon_WITH_AES_128_GCM_SHA256";
	paramsNeeded = 1;
	break;
    case TLS_DH_anon_WITH_AES_256_GCM_SHA384:
	cipherName = "TLS_DH_anon_WITH_AES_256_GCM_SHA384";
	paramsNeeded = 1;
	break;
    case TLS_PSK_WITH_AES_128_GCM_SHA256:
	cipherName = "TLS_PSK_WITH_AES_128_GCM_SHA256";
	break;
    case TLS_PSK_WITH_AES_256_GCM_SHA384:
	cipherName = "TLS_PSK_WITH_AES_256_GCM_SHA384";
	break;
    case TLS_DHE_PSK_WITH_AES_128_GCM_SHA256:
	cipherName = "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256";
	paramsNeeded = 1;
	break;
    case TLS_DHE_PSK_WITH_AES_256_GCM_SHA384:
	cipherName = "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384";
	paramsNeeded = 1;
	break;
    case TLS_RSA_PSK_WITH_AES_128_GCM_SHA256:
	cipherName = "TLS_RSA_PSK_WITH_AES_128_GCM_SHA256";
	break;
    case TLS_RSA_PSK_WITH_AES_256_GCM_SHA384:
	cipherName = "TLS_RSA_PSK_WITH_AES_256_GCM_SHA384";
	break;
    case TLS_PSK_WITH_AES_128_CBC_SHA256:
	cipherName = "TLS_PSK_WITH_AES_128_CBC_SHA256";
	break;
    case TLS_PSK_WITH_AES_256_CBC_SHA384:
	cipherName = "TLS_PSK_WITH_AES_256_CBC_SHA384";
	break;
    case TLS_PSK_WITH_NULL_SHA256:
	cipherName = "TLS_PSK_WITH_NULL_SHA256";
	break;
    case TLS_PSK_WITH_NULL_SHA384:
	cipherName = "TLS_PSK_WITH_NULL_SHA384";
	break;
    case TLS_DHE_PSK_WITH_AES_128_CBC_SHA256:
	cipherName = "TLS_DHE_PSK_WITH_AES_128_CBC_SHA256";
	paramsNeeded = 1;
	break;
    case TLS_DHE_PSK_WITH_AES_256_CBC_SHA384:
	cipherName = "TLS_DHE_PSK_WITH_AES_256_CBC_SHA384";
	paramsNeeded = 1;
	break;
    case TLS_DHE_PSK_WITH_NULL_SHA256:
	cipherName = "TLS_DHE_PSK_WITH_NULL_SHA256";
	paramsNeeded = 1;
	break;
    case TLS_DHE_PSK_WITH_NULL_SHA384:
	cipherName = "TLS_DHE_PSK_WITH_NULL_SHA384";
	paramsNeeded = 1;
	break;
    case TLS_RSA_PSK_WITH_AES_128_CBC_SHA256:
	cipherName = "TLS_RSA_PSK_WITH_AES_128_CBC_SHA256";
	break;
    case TLS_RSA_PSK_WITH_AES_256_CBC_SHA384:
	cipherName = "TLS_RSA_PSK_WITH_AES_256_CBC_SHA384";
	break;
    case TLS_RSA_PSK_WITH_NULL_SHA256:
	cipherName = "TLS_RSA_PSK_WITH_NULL_SHA256";
	break;
    case TLS_RSA_PSK_WITH_NULL_SHA384:
	cipherName = "TLS_RSA_PSK_WITH_NULL_SHA384";
	break;
    case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
	cipherName = "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256";
	paramsNeeded = 1;
	break;
    case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:
	cipherName = "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384";
	paramsNeeded = 1;
	break;
    case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:
	cipherName = "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256";
	paramsNeeded = 1;
	break;
    case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384:
	cipherName = "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384";
	paramsNeeded = 1;
	break;
    case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
	cipherName = "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256";
	paramsNeeded = 1;
	break;
    case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:
	cipherName = "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384";
	paramsNeeded = 1;
	break;
    case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256:
	cipherName = "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256";
	paramsNeeded = 1;
	break;
    case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384:
	cipherName = "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384";
	paramsNeeded = 1;
	break;
    case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
	cipherName = "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256";
	paramsNeeded = 1;
	break;
    case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
	cipherName = "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384";
	paramsNeeded = 1;
	break;
    case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
	cipherName = "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256";
	paramsNeeded = 1;
	break;
    case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:
	cipherName = "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384";
	paramsNeeded = 1;
	break;
    case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
	cipherName = "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256";
	paramsNeeded = 1;
	break;
    case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
	cipherName = "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384";
	paramsNeeded = 1;
	break;
    case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:
	cipherName = "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256";
	paramsNeeded = 1;
	break;
    case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:
	cipherName = "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384";
	paramsNeeded = 1;
	break;
    case TLS_RSA_WITH_AES_128_CBC_SHA:
	cipherName = "TLS_RSA_WITH_AES_128_CBC_SHA";
	break;
    case TLS_DH_DSS_WITH_AES_128_CBC_SHA:
	cipherName = "TLS_DH_DSS_WITH_AES_128_CBC_SHA";
	paramsNeeded = 1;
	break;
    case TLS_DH_RSA_WITH_AES_128_CBC_SHA:
	cipherName = "TLS_DH_RSA_WITH_AES_128_CBC_SHA";
	paramsNeeded = 1;
	break;
    case TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
	cipherName = "TLS_DHE_DSS_WITH_AES_128_CBC_SHA";
	paramsNeeded = 1;
	break;
    case TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
	cipherName = "TLS_DHE_RSA_WITH_AES_128_CBC_SHA";
	paramsNeeded = 1;
	break;
    case TLS_DH_anon_WITH_AES_128_CBC_SHA:
	cipherName = "TLS_DH_anon_WITH_AES_128_CBC_SHA";
	paramsNeeded = 1;
	break;
    case TLS_RSA_WITH_AES_256_CBC_SHA:
	cipherName = "TLS_RSA_WITH_AES_256_CBC_SHA";
	break;
    case TLS_DH_DSS_WITH_AES_256_CBC_SHA:
	cipherName = "TLS_DH_DSS_WITH_AES_256_CBC_SHA";
	paramsNeeded = 1;
	break;
    case TLS_DH_RSA_WITH_AES_256_CBC_SHA:
	cipherName = "TLS_DH_RSA_WITH_AES_256_CBC_SHA";
	paramsNeeded = 1;
	break;
    case TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
	cipherName = "TLS_DHE_DSS_WITH_AES_256_CBC_SHA";
	paramsNeeded = 1;
	break;
    case TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
	cipherName = "TLS_DHE_RSA_WITH_AES_256_CBC_SHA";
	paramsNeeded = 1;
	break;
    case TLS_DH_anon_WITH_AES_256_CBC_SHA:
	cipherName = "TLS_DH_anon_WITH_AES_256_CBC_SHA";
	paramsNeeded = 1;
	break;
    case TLS_ECDH_ECDSA_WITH_NULL_SHA:
	cipherName = "TLS_ECDH_ECDSA_WITH_NULL_SHA";
	paramsNeeded = 1;
	break;
    case TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
	cipherName = "TLS_ECDH_ECDSA_WITH_RC4_128_SHA";
	paramsNeeded = 1;
	break;
    case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
	cipherName = "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA";
	paramsNeeded = 1;
	break;
    case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
	cipherName = "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA";
	paramsNeeded = 1;
	break;
    case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
	cipherName = "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA";
	paramsNeeded = 1;
	break;
    case TLS_ECDHE_ECDSA_WITH_NULL_SHA:
	cipherName = "TLS_ECDHE_ECDSA_WITH_NULL_SHA";
	paramsNeeded = 1;
	break;
    case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
	cipherName = "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA";
	paramsNeeded = 1;
	break;
    case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
	cipherName = "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA";
	paramsNeeded = 1;
	break;
    case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
	cipherName = "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA";
	paramsNeeded = 1;
	break;
    case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
	cipherName = "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA";
	paramsNeeded = 1;
	break;
    case TLS_ECDH_RSA_WITH_NULL_SHA:
	cipherName = "TLS_ECDH_RSA_WITH_NULL_SHA";
	paramsNeeded = 1;
	break;
    case TLS_ECDH_RSA_WITH_RC4_128_SHA:
	cipherName = "TLS_ECDH_RSA_WITH_RC4_128_SHA";
	paramsNeeded = 1;
	break;
    case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
	cipherName = "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA";
	paramsNeeded = 1;
	break;
    case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
	cipherName = "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA";
	paramsNeeded = 1;
	break;
    case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
	cipherName = "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA";
	paramsNeeded = 1;
	break;
    case TLS_ECDHE_RSA_WITH_NULL_SHA:
	cipherName = "TLS_ECDHE_RSA_WITH_NULL_SHA";
	paramsNeeded = 1;
	break;
    case TLS_ECDHE_RSA_WITH_RC4_128_SHA:
	cipherName = "TLS_ECDHE_RSA_WITH_RC4_128_SHA";
	paramsNeeded = 1;
	break;
    case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
	cipherName = "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA";
	paramsNeeded = 1;
	break;
    case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
	cipherName = "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA";
	paramsNeeded = 1;
	break;
    case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
	cipherName = "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA";
	paramsNeeded = 1;
	break;
    case TLS_ECDH_anon_WITH_NULL_SHA:
	cipherName = "TLS_ECDH_anon_WITH_NULL_SHA";
	paramsNeeded = 1;
	break;
    case TLS_ECDH_anon_WITH_RC4_128_SHA:
	cipherName = "TLS_ECDH_anon_WITH_RC4_128_SHA";
	paramsNeeded = 1;
	break;
    case TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA:
	cipherName = "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA";
	paramsNeeded = 1;
	break;
    case TLS_ECDH_anon_WITH_AES_128_CBC_SHA:
	cipherName = "TLS_ECDH_anon_WITH_AES_128_CBC_SHA";
	paramsNeeded = 1;
	break;
    case TLS_ECDH_anon_WITH_AES_256_CBC_SHA:
	cipherName = "TLS_ECDH_anon_WITH_AES_256_CBC_SHA";
	paramsNeeded = 1;
	break;
    default :
        snprintf(unknownCipherName, sizeof(unknownCipherName), "UNKNOWN_%04X", cipher);
        cipherName = unknownCipherName;
        break;
  }

  if (cipher == TLS_RSA_WITH_RC4_128_MD5 ||
      cipher == TLS_RSA_WITH_RC4_128_SHA)
  {
    printf("%s: ERROR (Printers MUST NOT negotiate RC4 cipher suites.)\n", server);
    httpClose(http);
    return (1);
  }

  if ((err = SSLGetDiffieHellmanParams(http->tls, &params, &paramsLen)) != noErr && paramsNeeded)
  {
    printf("%s: ERROR (Unable to get Diffie-Hellman parameters - %d)\n", server, (int)err);
    httpClose(http);
    return (1);
  }

  if (paramsLen < 128 && paramsLen != 0)
  {
    printf("%s: ERROR (Diffie-Hellman parameters MUST be at least 2048 bits, but Printer uses only %d bits/%d bytes)\n", server, (int)paramsLen * 8, (int)paramsLen);
    httpClose(http);
    return (1);
  }

  dhBits = (int)paramsLen * 8;
#endif /* __APPLE__ */

  if (dhBits > 0)
    printf("%s: OK (TLS: %d.%d, %s, %d DH bits)\n", server, tlsVersion / 10, tlsVersion % 10, cipherName, dhBits);
  else
    printf("%s: OK (TLS: %d.%d, %s)\n", server, tlsVersion / 10, tlsVersion % 10, cipherName);

  if (verbose)
  {
    httpAssembleURI(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipps", NULL, host, port, resource);
    request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES);
    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri);
    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser());
    ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", (int)(sizeof(pattrs) / sizeof(pattrs[0])), NULL, pattrs);

    response = cupsDoRequest(http, request, resource);

    for (attr = ippFirstAttribute(response); attr; attr = ippNextAttribute(response))
    {
      if (ippGetGroupTag(attr) != IPP_TAG_PRINTER)
        continue;

      if ((name = ippGetName(attr)) == NULL)
        continue;

      ippAttributeString(attr, value, sizeof(value));
      printf("    %s=%s\n", name, value);
    }

    ippDelete(response);
  }

  httpClose(http);

  return (0);
}
Exemple #22
0
static int				/* O - 0 on success, 1 on fail */
delete_printer_from_class(
    http_t *http,			/* I - Server connection */
    char   *printer,			/* I - Printer to remove */
    char   *pclass)	  		/* I - Class to remove from */
{
  int		i, j, k;		/* Looping vars */
  ipp_t		*request,		/* IPP Request */
		*response;		/* IPP Response */
  ipp_attribute_t *attr,		/* Current attribute */
		*members;		/* Members in class */
  char		uri[HTTP_MAX_URI];	/* URI for printer/class */


  DEBUG_printf(("delete_printer_from_class(%p, \"%s\", \"%s\")\n", http,
                printer, pclass));

 /*
  * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following
  * attributes:
  *
  *    attributes-charset
  *    attributes-natural-language
  *    printer-uri
  *    requesting-user-name
  */

  request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);

  httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
                   "localhost", 0, "/classes/%s", pclass);
  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
               "printer-uri", NULL, uri);
  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
               NULL, cupsUser());

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

  if ((response = cupsDoRequest(http, request, "/classes/")) == NULL ||
      response->request.status.status_code == IPP_NOT_FOUND)
  {
    _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString());

    ippDelete(response);

    return (1);
  }

 /*
  * See if the printer is already in the class...
  */

  if ((members = ippFindAttribute(response, "member-names", IPP_TAG_NAME)) == NULL)
  {
    _cupsLangPuts(stderr, _("lpadmin: No member names were seen."));

    ippDelete(response);

    return (1);
  }

  for (i = 0; i < members->num_values; i ++)
    if (!_cups_strcasecmp(printer, members->values[i].string.text))
      break;

  if (i >= members->num_values)
  {
    _cupsLangPrintf(stderr,
                    _("lpadmin: Printer %s is not a member of class %s."),
	            printer, pclass);

    ippDelete(response);

    return (1);
  }

  if (members->num_values == 1)
  {
   /*
    * Build a CUPS_DELETE_CLASS request, which requires the following
    * attributes:
    *
    *    attributes-charset
    *    attributes-natural-language
    *    printer-uri
    *    requesting-user-name
    */

    request = ippNewRequest(CUPS_DELETE_CLASS);

    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
        	 "printer-uri", NULL, uri);
    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
                 "requesting-user-name", NULL, cupsUser());
  }
  else
  {
   /*
    * Build a CUPS_ADD_MODIFY_CLASS request, which requires the following
    * attributes:
    *
    *    attributes-charset
    *    attributes-natural-language
    *    printer-uri
    *    requesting-user-name
    *    member-uris
    */

    request = ippNewRequest(CUPS_ADD_MODIFY_CLASS);

    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
        	 "printer-uri", NULL, uri);
    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
                 "requesting-user-name", NULL, cupsUser());

   /*
    * Delete the printer from the class...
    */

    members = ippFindAttribute(response, "member-uris", IPP_TAG_URI);
    attr = ippAddStrings(request, IPP_TAG_PRINTER, IPP_TAG_URI,
                         "member-uris", members->num_values - 1, NULL, NULL);

    for (j = 0, k = 0; j < members->num_values; j ++)
      if (j != i)
        attr->values[k ++].string.text =
	    _cupsStrAlloc(members->values[j].string.text);
  }

 /*
  * Then send the request...
  */

  ippDelete(response);

  ippDelete(cupsDoRequest(http, request, "/admin/"));

  if (cupsLastError() > IPP_OK_CONFLICT)
  {
    _cupsLangPrintf(stderr, _("%s: %s"), "lpadmin", cupsLastErrorString());

    return (1);
  }
  else
    return (0);
}
Exemple #23
0
int					/* O - 0 on success, -1 on error */
_cupsSetNegotiateAuthString(
    http_t     *http,			/* I - Connection to server */
    const char *method,			/* I - Request method ("GET", "POST", "PUT") */
    const char *resource)		/* I - Resource path */
{
  OM_uint32	minor_status,		/* Minor status code */
		major_status;		/* Major status code */
  gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
					/* Output token */


  (void)method;
  (void)resource;

#  ifdef __APPLE__
 /*
  * If the weak-linked GSSAPI/Kerberos library is not present, don't try
  * to use it...
  */

  if (&gss_init_sec_context == NULL)
  {
    DEBUG_puts("1_cupsSetNegotiateAuthString: Weak-linked GSSAPI/Kerberos "
               "framework is not present");
    return (-1);
  }
#  endif /* __APPLE__ */

  if (http->gssname == GSS_C_NO_NAME)
  {
    http->gssname = cups_gss_getname(http, _cupsGSSServiceName());
  }

  if (http->gssctx != GSS_C_NO_CONTEXT)
  {
    gss_delete_sec_context(&minor_status, &http->gssctx, GSS_C_NO_BUFFER);
    http->gssctx = GSS_C_NO_CONTEXT;
  }

  major_status = gss_init_sec_context(&minor_status, GSS_C_NO_CREDENTIAL,
				      &http->gssctx,
				      http->gssname, http->gssmech,
				      GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG,
				      GSS_C_INDEFINITE,
				      GSS_C_NO_CHANNEL_BINDINGS,
				      GSS_C_NO_BUFFER, &http->gssmech,
				      &output_token, NULL, NULL);

#ifdef HAVE_GSS_ACQUIRE_CRED_EX_F
  if (major_status == GSS_S_NO_CRED)
  {
   /*
    * Ask the user for credentials...
    */

    char		prompt[1024],	/* Prompt for user */
			userbuf[256];	/* Kerberos username */
    const char		*username,	/* Username string */
			*password;	/* Password string */
    _cups_gss_acquire_t	data;		/* Callback data */
    gss_auth_identity_desc identity;	/* Kerberos user identity */
    _cups_globals_t	*cg = _cupsGlobals();
					/* Per-thread global data */

    if (!cg->lang_default)
      cg->lang_default = cupsLangDefault();

    snprintf(prompt, sizeof(prompt),
             _cupsLangString(cg->lang_default, _("Password for %s on %s? ")),
	     cupsUser(), http->gsshost);

    if ((password = cupsGetPassword2(prompt, http, method, resource)) == NULL)
      return (-1);

   /*
    * Try to acquire credentials...
    */

    username = cupsUser();
    if (!strchr(username, '@'))
    {
      snprintf(userbuf, sizeof(userbuf), "%s@%s", username, http->gsshost);
      username = userbuf;
    }

    identity.type           = GSS_AUTH_IDENTITY_TYPE_1;
    identity.flags          = 0;
    identity.username       = (char *)username;
    identity.realm          = (char *)"";
    identity.password       = (char *)password;
    identity.credentialsRef = NULL;

    data.sem   = dispatch_semaphore_create(0);
    data.major = 0;
    data.creds = NULL;

    if (data.sem)
    {
      major_status = gss_acquire_cred_ex_f(NULL, GSS_C_NO_NAME, 0,
				           GSS_C_INDEFINITE, GSS_KRB5_MECHANISM,
					   GSS_C_INITIATE, &identity, &data,
					   cups_gss_acquire);

      if (major_status == GSS_S_COMPLETE)
      {
	dispatch_semaphore_wait(data.sem, DISPATCH_TIME_FOREVER);
	major_status = data.major;
      }

      dispatch_release(data.sem);

      if (major_status == GSS_S_COMPLETE)
      {
        OM_uint32	release_minor;	/* Minor status from releasing creds */

	major_status = gss_init_sec_context(&minor_status, data.creds,
					    &http->gssctx,
					    http->gssname, http->gssmech,
					    GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG,
					    GSS_C_INDEFINITE,
					    GSS_C_NO_CHANNEL_BINDINGS,
					    GSS_C_NO_BUFFER, &http->gssmech,
					    &output_token, NULL, NULL);
        gss_release_cred(&release_minor, &data.creds);
      }
    }
  }
#endif /* HAVE_GSS_ACQUIRED_CRED_EX_F */

  if (GSS_ERROR(major_status))
  {
    cups_gss_printf(major_status, minor_status,
		    "_cupsSetNegotiateAuthString: Unable to initialize "
		    "security context");
    return (-1);
  }

#ifdef DEBUG
  else if (major_status == GSS_S_CONTINUE_NEEDED)
    cups_gss_printf(major_status, minor_status,
		    "_cupsSetNegotiateAuthString: Continuation needed!");
#endif /* DEBUG */

  if (output_token.length > 0 && output_token.length <= 65536)
  {
   /*
    * Allocate the authorization string since Windows KDCs can have
    * arbitrarily large credentials...
    */

    int authsize = 10 +			/* "Negotiate " */
		   (int)output_token.length * 4 / 3 + 1 + 1;
		   			/* Base64 + nul */

    httpSetAuthString(http, NULL, NULL);

    if ((http->authstring = malloc((size_t)authsize)) == NULL)
    {
      http->authstring = http->_authstring;
      authsize         = sizeof(http->_authstring);
    }

    strlcpy(http->authstring, "Negotiate ", (size_t)authsize);
    httpEncode64_2(http->authstring + 10, authsize - 10, output_token.value,
		   (int)output_token.length);

    gss_release_buffer(&minor_status, &output_token);
  }
  else
  {
    DEBUG_printf(("1_cupsSetNegotiateAuthString: Kerberos credentials too "
                  "large - %d bytes!", (int)output_token.length));
    gss_release_buffer(&minor_status, &output_token);

    return (-1);
  }

  return (0);
}
Exemple #24
0
ipp_status_t
cupsCancelDestJob(http_t      *http,	/* I - Connection to destination */
                  cups_dest_t *dest,	/* I - Destination */
                  int         job_id)	/* I - Job ID */
{
  cups_dinfo_t	*info;			/* Destination information */


  if ((info = cupsCopyDestInfo(http, dest)) != NULL)
  {
    ipp_t	*request;		/* Cancel-Job request */

    request = ippNewRequest(IPP_OP_CANCEL_JOB);

    ippSetVersion(request, info->version / 10, info->version % 10);

    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, info->uri);
    ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", job_id);
    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser());

    ippDelete(cupsDoRequest(http, request, info->resource));
    cupsFreeDestInfo(info);
  }

  return (cupsLastError());
}
Exemple #25
0
GtkCupsRequest *
gtk_cups_request_new_with_username (http_t             *connection,
                                    GtkCupsRequestType  req_type, 
                                    gint                operation_id,
                                    GIOChannel         *data_io,
                                    const char         *server,
                                    const char         *resource,
                                    const char         *username)
{
  GtkCupsRequest *request;
  cups_lang_t *language;
  
  request = g_new0 (GtkCupsRequest, 1);
  request->result = g_new0 (GtkCupsResult, 1);

  request->result->error_msg = NULL;
  request->result->ipp_response = NULL;

  request->result->is_error = FALSE;
  request->result->is_ipp_response = FALSE;

  request->type = req_type;
  request->state = GTK_CUPS_REQUEST_START;

  request->password_state = GTK_CUPS_PASSWORD_NONE;

   if (server)
    request->server = g_strdup (server);
  else
    request->server = g_strdup (cupsServer ());


  if (resource)
    request->resource = g_strdup (resource);
  else
    request->resource = g_strdup ("/");
 
  if (connection != NULL)
    {
      request->http = connection;
      request->own_http = FALSE;
    }
  else
    {
      request->http = NULL;
      request->http = httpConnectEncrypt (request->server, 
                                          ippPort (), 
                                          cupsEncryption ());

      if (request->http)
        httpBlocking (request->http, 0);
        
      request->own_http = TRUE;
    }

  request->last_status = HTTP_CONTINUE;

  request->attempts = 0;
  request->data_io = data_io;

  request->ipp_request = ippNew ();
  ippSetOperation (request->ipp_request, operation_id);
  ippSetRequestId (request->ipp_request, 1);

  language = cupsLangDefault ();

  gtk_cups_request_ipp_add_string (request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
                                   "attributes-charset", 
                                   NULL, "utf-8");
	
  gtk_cups_request_ipp_add_string (request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
                                   "attributes-natural-language", 
                                   NULL, language->language);

  if (username != NULL)
    gtk_cups_request_ipp_add_string (request, IPP_TAG_OPERATION, IPP_TAG_NAME,
                                     "requesting-user-name",
                                     NULL, username);
  else
    gtk_cups_request_ipp_add_string (request, IPP_TAG_OPERATION, IPP_TAG_NAME,
                                     "requesting-user-name",
                                     NULL, cupsUser ());

  request->auth_info_required = NULL;
  request->auth_info = NULL;
  request->need_auth_info = FALSE;

  cupsLangFree (language);

  return request;
}
int
main(int  argc,				/* I - Number of command-line arguments */
     char *argv[])			/* I - Command-line arguments */
{
  int		i;			/* Looping var */
  const char	*uri;			/* URI to use */
  int		num_events;		/* Number of events */
  const char	*events[100];		/* Events */
  int		subscription_id,	/* notify-subscription-id */
		sequence_number,	/* notify-sequence-number */
		interval;		/* Interval between polls */
  http_t	*http;			/* HTTP connection */
  ipp_t		*request,		/* IPP request */
		*response;		/* IPP response */
  ipp_attribute_t *attr;		/* Current attribute */
#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
  struct sigaction action;		/* Actions for POSIX signals */
#endif /* HAVE_SIGACTION && !HAVE_SIGSET */


 /*
  * Parse command-line...
  */

  num_events = 0;
  uri        = NULL;

  for (i = 1; i < argc; i ++)
    if (!strcmp(argv[i], "-E"))
      cupsSetEncryption(HTTP_ENCRYPT_REQUIRED);
    else if (!strcmp(argv[i], "-e"))
    {
      i ++;
      if (i >= argc || num_events >= 100)
        usage();

      events[num_events] = argv[i];
      num_events ++;
    }
    else if (!strcmp(argv[i], "-h"))
    {
      i ++;
      if (i >= argc)
        usage();

      cupsSetServer(argv[i]);
    }
    else if (uri || strncmp(argv[i], "ipp://", 6))
      usage();
    else
      uri = argv[i];

  if (!uri)
    usage();

  if (num_events == 0)
  {
    events[0]  = "all";
    num_events = 1;
  }

 /*
  * Connect to the server...
  */

  if ((http = httpConnectEncrypt(cupsServer(), ippPort(),
                                 cupsEncryption())) == NULL)
  {
    perror(cupsServer());
    return (1);
  }

 /*
  * Catch CTRL-C and SIGTERM...
  */

#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
  sigset(SIGINT, sigterm_handler);
  sigset(SIGTERM, sigterm_handler);
#elif defined(HAVE_SIGACTION)
  memset(&action, 0, sizeof(action));

  sigemptyset(&action.sa_mask);
  action.sa_handler = sigterm_handler;
  sigaction(SIGINT, &action, NULL);
  sigaction(SIGTERM, &action, NULL);
#else
  signal(SIGINT, sigterm_handler);
  signal(SIGTERM, sigterm_handler);
#endif /* HAVE_SIGSET */

 /*
  * Create the subscription...
  */

  if (strstr(uri, "/jobs/"))
  {
    request = ippNewRequest(IPP_CREATE_JOB_SUBSCRIPTION);
    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri);
  }
  else
  {
    request = ippNewRequest(IPP_CREATE_PRINTER_SUBSCRIPTION);
    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL,
                 uri);
  }

  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
               NULL, cupsUser());

  ippAddStrings(request, IPP_TAG_SUBSCRIPTION, IPP_TAG_KEYWORD, "notify-events",
                num_events, NULL, events);
  ippAddString(request, IPP_TAG_SUBSCRIPTION, IPP_TAG_KEYWORD,
               "notify-pull-method", NULL, "ippget");

  response = cupsDoRequest(http, request, uri);
  if (cupsLastError() >= IPP_BAD_REQUEST)
  {
    fprintf(stderr, "Create-%s-Subscription: %s\n",
            strstr(uri, "/jobs") ? "Job" : "Printer", cupsLastErrorString());
    ippDelete(response);
    httpClose(http);
    return (1);
  }

  if ((attr = ippFindAttribute(response, "notify-subscription-id",
                               IPP_TAG_INTEGER)) == NULL)
  {
    fputs("ERROR: No notify-subscription-id in response!\n", stderr);
    ippDelete(response);
    httpClose(http);
    return (1);
  }

  subscription_id = attr->values[0].integer;

  printf("Create-%s-Subscription: notify-subscription-id=%d\n",
         strstr(uri, "/jobs/") ? "Job" : "Printer", subscription_id);

  ippDelete(response);

 /*
  * Monitor for events...
  */

  sequence_number = 0;

  while (!terminate)
  {
   /*
    * Get the current events...
    */

    printf("\nGet-Notifications(%d,%d):", subscription_id, sequence_number);
    fflush(stdout);

    request = ippNewRequest(IPP_GET_NOTIFICATIONS);

    if (strstr(uri, "/jobs/"))
      ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri);
    else
      ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL,
                   uri);

    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
                 "requesting-user-name", NULL, cupsUser());

    ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER,
                  "notify-subscription-ids", subscription_id);
    if (sequence_number)
      ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER,
                    "notify-sequence-numbers", sequence_number + 1);

    response = cupsDoRequest(http, request, uri);

    printf(" %s\n", ippErrorString(cupsLastError()));

    if (cupsLastError() >= IPP_BAD_REQUEST)
      fprintf(stderr, "Get-Notifications: %s\n", cupsLastErrorString());
    else if (response)
    {
      print_attributes(response, 0);

      for (attr = ippFindAttribute(response, "notify-sequence-number",
                                   IPP_TAG_INTEGER);
           attr;
	   attr = ippFindNextAttribute(response, "notify-sequence-number",
	                               IPP_TAG_INTEGER))
        if (attr->values[0].integer > sequence_number)
	  sequence_number = attr->values[0].integer;
    }

    if ((attr = ippFindAttribute(response, "notify-get-interval",
                                 IPP_TAG_INTEGER)) != NULL &&
        attr->values[0].integer > 0)
      interval = attr->values[0].integer;
    else
      interval = 5;

    ippDelete(response);
    sleep(interval);
  }

 /*
  * Cancel the subscription...
  */

  printf("\nCancel-Subscription:");
  fflush(stdout);

  request = ippNewRequest(IPP_CANCEL_SUBSCRIPTION);

  if (strstr(uri, "/jobs/"))
    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri", NULL, uri);
  else
    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL,
                 uri);

  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
               NULL, cupsUser());

  ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER,
                "notify-subscription-id", subscription_id);

  ippDelete(cupsDoRequest(http, request, uri));

  printf(" %s\n", ippErrorString(cupsLastError()));

  if (cupsLastError() >= IPP_BAD_REQUEST)
    fprintf(stderr, "Cancel-Subscription: %s\n", cupsLastErrorString());

 /*
  * Close the connection and return...
  */

  httpClose(http);

  return (0);
}
Exemple #27
0
ipp_status_t				/* O - IPP status code */
cupsCreateDestJob(
    http_t        *http,		/* I - Connection to destination */
    cups_dest_t   *dest,		/* I - Destination */
    cups_dinfo_t  *info, 		/* I - Destination information */
    int           *job_id,		/* O - Job ID or 0 on error */
    const char    *title,		/* I - Job name */
    int           num_options,		/* I - Number of job options */
    cups_option_t *options)		/* I - Job options */
{
  ipp_t			*request,	/* Create-Job request */
			*response;	/* Create-Job response */
  ipp_attribute_t	*attr;		/* job-id attribute */


  DEBUG_printf(("cupsCreateDestJob(http=%p, dest=%p(%s/%s), info=%p, "
                "job_id=%p, title=\"%s\", num_options=%d, options=%p)",
                http, dest, dest ? dest->name : NULL,
                dest ? dest->instance : NULL, info, job_id, title, num_options,
                options));

 /*
  * Range check input...
  */

  if (job_id)
    *job_id = 0;

  if (!http || !dest || !info || !job_id)
  {
    _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);
    DEBUG_puts("1cupsCreateDestJob: Bad arguments.");
    return (IPP_STATUS_ERROR_INTERNAL);
  }

 /*
  * Build a Create-Job request...
  */

  if ((request = ippNewRequest(IPP_OP_CREATE_JOB)) == NULL)
  {
    _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(ENOMEM), 0);
    DEBUG_puts("1cupsCreateDestJob: Unable to create Create-Job request.");
    return (IPP_STATUS_ERROR_INTERNAL);
  }

  ippSetVersion(request, info->version / 10, info->version % 10);

  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
               NULL, info->uri);
  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
               NULL, cupsUser());
  if (title)
    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL,
                 title);

  cupsEncodeOptions2(request, num_options, options, IPP_TAG_OPERATION);
  cupsEncodeOptions2(request, num_options, options, IPP_TAG_JOB);
  cupsEncodeOptions2(request, num_options, options, IPP_TAG_SUBSCRIPTION);

 /*
  * Send the request and get the job-id...
  */

  response = cupsDoRequest(http, request, info->resource);

  if ((attr = ippFindAttribute(response, "job-id", IPP_TAG_INTEGER)) != NULL)
  {
    *job_id = attr->values[0].integer;
    DEBUG_printf(("1cupsCreateDestJob: job-id=%d", *job_id));
  }

  ippDelete(response);

 /*
  * Return the status code from the Create-Job request...
  */

  DEBUG_printf(("1cupsCreateDestJob: %s (%s)", ippErrorString(cupsLastError()),
                cupsLastErrorString()));

  return (cupsLastError());
}
static int				/* O - Number of jobs in queue */
show_jobs(const char *command,		/* I - Command name */
          http_t     *http,		/* I - HTTP connection to server */
          const char *dest,		/* I - Destination */
	  const char *user,		/* I - User */
	  const int  id,		/* I - Job ID */
	  const int  longstatus)	/* I - 1 if long report desired */
{
  ipp_t		*request,		/* IPP Request */
		*response;		/* IPP Response */
  ipp_attribute_t *attr;		/* Current attribute */
  const char	*jobdest,		/* Pointer into job-printer-uri */
		*jobuser,		/* Pointer to job-originating-user-name */
		*jobname;		/* Pointer to job-name */
  ipp_jstate_t	jobstate;		/* job-state */
  int		jobid,			/* job-id */
		jobsize,		/* job-k-octets */
#ifdef __osf__
		jobpriority,		/* job-priority */
#endif /* __osf__ */
		jobcount,		/* Number of jobs */
		jobcopies,		/* Number of copies */
		rank;			/* Rank of job */
  char		resource[1024];		/* Resource string */
  char		rankstr[255];		/* Rank string */
  char		namestr[1024];		/* Job name string */
  static const char * const jobattrs[] =/* Job attributes we want to see */
		{
		  "copies",
		  "job-id",
		  "job-k-octets",
		  "job-name",
		  "job-originating-user-name",
		  "job-printer-uri",
		  "job-priority",
		  "job-state"
		};
  static const char * const ranks[10] =	/* Ranking strings */
		{
		  "th",
		  "st",
		  "nd",
		  "rd",
		  "th",
		  "th",
		  "th",
		  "th",
		  "th",
		  "th"
		};


  DEBUG_printf(("show_jobs(http=%p, dest=%p, user=%p, id=%d, longstatus%d)\n",
                http, dest, user, id, longstatus));

  if (http == NULL)
    return (0);

 /*
  * Build an IPP_GET_JOBS or IPP_GET_JOB_ATTRIBUTES request, which requires
  * the following attributes:
  *
  *    attributes-charset
  *    attributes-natural-language
  *    job-uri or printer-uri
  *    requested-attributes
  *    requesting-user-name
  */

  request = ippNewRequest(id ? IPP_GET_JOB_ATTRIBUTES : IPP_GET_JOBS);

  if (id)
  {
    snprintf(resource, sizeof(resource), "ipp://localhost/jobs/%d", id);
    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri",
                 NULL, resource);
  }
  else if (dest)
  {
    httpAssembleURIf(HTTP_URI_CODING_ALL, resource, sizeof(resource), "ipp",
                     NULL, "localhost", 0, "/printers/%s", dest);

    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
                 NULL, resource);
  }
  else
    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
                 NULL, "ipp://localhost/");

  if (user)
  {
    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
                 "requesting-user-name", NULL, user);
    ippAddBoolean(request, IPP_TAG_OPERATION, "my-jobs", 1);
  }
  else
    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
                 "requesting-user-name", NULL, cupsUser());

  ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
                "requested-attributes",
                (int)(sizeof(jobattrs) / sizeof(jobattrs[0])), NULL, jobattrs);

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

  jobcount = 0;

  if ((response = cupsDoRequest(http, request, "/")) != NULL)
  {
    if (response->request.status.status_code > IPP_OK_CONFLICT)
    {
      _cupsLangPrintf(stderr, "%s: %s", command, cupsLastErrorString());
      ippDelete(response);
      return (0);
    }

    rank = 1;

   /*
    * Loop through the job list and display them...
    */

    for (attr = response->attrs; attr != NULL; attr = attr->next)
    {
     /*
      * Skip leading attributes until we hit a job...
      */

      while (attr != NULL && attr->group_tag != IPP_TAG_JOB)
        attr = attr->next;

      if (attr == NULL)
        break;

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

      jobid       = 0;
      jobsize     = 0;
#ifdef __osf__
      jobpriority = 50;
#endif /* __osf__ */
      jobstate    = IPP_JOB_PENDING;
      jobname     = "unknown";
      jobuser     = "******";
      jobdest     = NULL;
      jobcopies   = 1;

      while (attr != NULL && attr->group_tag == IPP_TAG_JOB)
      {
        if (!strcmp(attr->name, "job-id") &&
	    attr->value_tag == IPP_TAG_INTEGER)
	  jobid = attr->values[0].integer;

        if (!strcmp(attr->name, "job-k-octets") &&
	    attr->value_tag == IPP_TAG_INTEGER)
	  jobsize = attr->values[0].integer;

#ifdef __osf__
        if (!strcmp(attr->name, "job-priority") &&
	    attr->value_tag == IPP_TAG_INTEGER)
	  jobpriority = attr->values[0].integer;
#endif /* __osf__ */

        if (!strcmp(attr->name, "job-state") &&
	    attr->value_tag == IPP_TAG_ENUM)
	  jobstate = (ipp_jstate_t)attr->values[0].integer;

        if (!strcmp(attr->name, "job-printer-uri") &&
	    attr->value_tag == IPP_TAG_URI)
	  if ((jobdest = strrchr(attr->values[0].string.text, '/')) != NULL)
	    jobdest ++;

        if (!strcmp(attr->name, "job-originating-user-name") &&
	    attr->value_tag == IPP_TAG_NAME)
	  jobuser = attr->values[0].string.text;

        if (!strcmp(attr->name, "job-name") &&
	    attr->value_tag == IPP_TAG_NAME)
	  jobname = attr->values[0].string.text;

        if (!strcmp(attr->name, "copies") &&
	    attr->value_tag == IPP_TAG_INTEGER)
	  jobcopies = attr->values[0].integer;

        attr = attr->next;
      }

     /*
      * See if we have everything needed...
      */

      if (jobdest == NULL || jobid == 0)
      {
        if (attr == NULL)
	  break;
	else
          continue;
      }

      if (!longstatus && jobcount == 0)
#ifdef __osf__
	_cupsLangPuts(stdout,
	              /* TRANSLATORS: Pri is job priority. */
	              _("Rank   Owner      Pri  Job        Files"
		        "                       Total Size"));
#else
	_cupsLangPuts(stdout,
	              _("Rank    Owner   Job     File(s)"
		        "                         Total Size"));
#endif /* __osf__ */

      jobcount ++;

     /*
      * Display the job...
      */

      if (jobstate == IPP_JOB_PROCESSING)
	strlcpy(rankstr, "active", sizeof(rankstr));
      else
      {
       /*
        * Make the rank show the "correct" suffix for each number
	* (11-13 are the only special cases, for English anyways...)
	*/

	if ((rank % 100) >= 11 && (rank % 100) <= 13)
	  snprintf(rankstr, sizeof(rankstr), "%dth", rank);
	else
	  snprintf(rankstr, sizeof(rankstr), "%d%s", rank, ranks[rank % 10]);

	rank ++;
      }

      if (longstatus)
      {
        _cupsLangPuts(stdout, "\n");

        if (jobcopies > 1)
	  snprintf(namestr, sizeof(namestr), "%d copies of %s", jobcopies,
	           jobname);
	else
	  strlcpy(namestr, jobname, sizeof(namestr));

        _cupsLangPrintf(stdout, _("%s: %-33.33s [job %d localhost]"),
	                jobuser, rankstr, jobid);
        _cupsLangPrintf(stdout, _("        %-39.39s %.0f bytes"),
	                namestr, 1024.0 * jobsize);
      }
      else
#ifdef __osf__
        _cupsLangPrintf(stdout,
	                _("%-6s %-10.10s %-4d %-10d %-27.27s %.0f bytes"),
			rankstr, jobuser, jobpriority, jobid, jobname,
			1024.0 * jobsize);
#else
        _cupsLangPrintf(stdout,
	                _("%-7s %-7.7s %-7d %-31.31s %.0f bytes"),
			rankstr, jobuser, jobid, jobname, 1024.0 * jobsize);
#endif /* __osf */

      if (attr == NULL)
        break;
    }

    ippDelete(response);
  }
  else
  {
    _cupsLangPrintf(stderr, "%s: %s", command, cupsLastErrorString());
    return (0);
  }

  if (jobcount == 0)
    _cupsLangPuts(stdout, _("no entries"));

  return (jobcount);
}
Exemple #29
0
ipp_status_t				/* O - IPP status code */
cupsCloseDestJob(
    http_t       *http,			/* I - Connection to destination */
    cups_dest_t  *dest,			/* I - Destination */
    cups_dinfo_t *info, 		/* I - Destination information */
    int          job_id)		/* I - Job ID */
{
  int			i;		/* Looping var */
  ipp_t			*request = NULL;/* Close-Job/Send-Document request */
  ipp_attribute_t	*attr;		/* operations-supported attribute */


  DEBUG_printf(("cupsCloseDestJob(http=%p, dest=%p(%s/%s), info=%p, job_id=%d)",
                http, dest, dest ? dest->name : NULL,
                dest ? dest->instance : NULL, info, job_id));

 /*
  * Range check input...
  */

  if (!http || !dest || !info || job_id <= 0)
  {
    _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);
    DEBUG_puts("1cupsCloseDestJob: Bad arguments.");
    return (IPP_STATUS_ERROR_INTERNAL);
  }

 /*
  * Build a Close-Job or empty Send-Document request...
  */

  if ((attr = ippFindAttribute(info->attrs, "operations-supported",
                               IPP_TAG_ENUM)) != NULL)
  {
    for (i = 0; i < attr->num_values; i ++)
      if (attr->values[i].integer == IPP_OP_CLOSE_JOB)
      {
        request = ippNewRequest(IPP_OP_CLOSE_JOB);
        break;
      }
  }

  if (!request)
    request = ippNewRequest(IPP_OP_SEND_DOCUMENT);

  if (!request)
  {
    _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(ENOMEM), 0);
    DEBUG_puts("1cupsCloseDestJob: Unable to create Close-Job/Send-Document "
               "request.");
    return (IPP_STATUS_ERROR_INTERNAL);
  }

  ippSetVersion(request, info->version / 10, info->version % 10);

  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
               NULL, info->uri);
  ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id",
                job_id);
  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
               NULL, cupsUser());
  if (ippGetOperation(request) == IPP_OP_SEND_DOCUMENT)
    ippAddBoolean(request, IPP_TAG_OPERATION, "last-document", 1);

 /*
  * Send the request and return the status...
  */

  ippDelete(cupsDoRequest(http, request, info->resource));

  DEBUG_printf(("1cupsCloseDestJob: %s (%s)", ippErrorString(cupsLastError()),
                cupsLastErrorString()));

  return (cupsLastError());
}
Exemple #30
0
///////////////////////////////////////////////////////////////////////////////////////////
//
// CS     : PUBLIC gint removeJob(gchar *pDestName)
// IN     : gchar *pDestName : Printer name.
// OUT    : None.
// RETURN : ID_ERR_NO_ERROR : No error.
//          ID_ERR_CUPS_API_FAILED : Error occured in CUPS API.
//
PUBLIC gint removeJob(gchar *pDestName)
{
/*** Parameters start ***/
	http_t			*pHTTP;						// Pointer to HTTP connection.
	ipp_t			*pRequest,					// Pointer to CUPS IPP request.
					*pResponse;					// Pointer to CUPS IPP response.
	cups_lang_t		*pLanguage;					// Pointer to language.
	gchar			printerURI[HTTP_MAX_URI];	// Printer URI.
	gchar			serverName[HTTP_MAX_URI];	// CUPS server name.
	gint			jobID = 0;					// Job ID.
	gint			retVal = ID_ERR_NO_ERROR;	// Return value.
/*** Parameters end ***/

	// Initialize buffer.
	memset(printerURI, 0, sizeof(printerURI));
	memset(serverName, 0, sizeof(serverName));

	// Get printer URI and CUPS server name.
	retVal = getPrinterURI(pDestName, printerURI, serverName, HTTP_MAX_URI);
	if (retVal == ID_ERR_NO_ERROR) {
		retVal = getJobID(pDestName, printerURI, serverName, &jobID);
		if (retVal == ID_ERR_PRINT_JOB_NOT_EXIST) {
			retVal = ID_ERR_NO_ERROR;
		}

		if (retVal == ID_ERR_NO_ERROR) {
			// CUPS http connect.
			if ((pHTTP = httpConnectEncrypt(serverName, ippPort(), cupsEncryption())) == NULL) {
				retVal = ID_ERR_CUPS_API_FAILED;
			}
			else {
				pRequest = ippNew();

				ippSetOperation(pRequest, IPP_CANCEL_JOB);
				ippSetRequestId(pRequest, 1);

				pLanguage = bjcupsLangDefault();		// cupsLangDefault() -> bjcupsLangDefault() for cups-1.1.19

				ippAddString(pRequest, IPP_TAG_OPERATION, IPP_TAG_CHARSET, "attributes-charset", NULL, cupsLangEncoding(pLanguage));
				ippAddString(pRequest, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, "attributes-natural-language", NULL, pLanguage->language);
				ippAddString(pRequest, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, printerURI);
				ippAddInteger(pRequest, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", jobID);
				ippAddString(pRequest, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, cupsUser());

				if ((pResponse = cupsDoRequest(pHTTP, pRequest, "/jobs/")) != NULL) {
					if (ippGetStatusCode(pResponse) > IPP_OK_CONFLICT) {
						retVal = ID_ERR_CUPS_API_FAILED;
					}
					ippDelete(pResponse);
				}
				else {
					retVal = ID_ERR_CUPS_API_FAILED;
				}

				cupsLangFree(pLanguage);
				httpClose(pHTTP);
			}
		}
	}

	return(retVal);
}// End removeJob