Example #1
0
ipp_t *					/* O - Response data */
cupsDoFileRequest(http_t     *http,	/* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
                  ipp_t      *request,	/* I - IPP request */
                  const char *resource,	/* I - HTTP resource for POST */
		  const char *filename)	/* I - File to send or @code NULL@ for none */
{
  ipp_t		*response;		/* IPP response data */
  int		infile;			/* Input file */


  DEBUG_printf(("cupsDoFileRequest(http=%p, request=%p(%s), resource=\"%s\", "
                "filename=\"%s\")", http, request,
		request ? ippOpString(request->request.op.operation_id) : "?",
		resource, filename));

  if (filename)
  {
    if ((infile = open(filename, O_RDONLY | O_BINARY)) < 0)
    {
     /*
      * Can't get file information!
      */

      _cupsSetError(errno == ENOENT ? IPP_STATUS_ERROR_NOT_FOUND : IPP_STATUS_ERROR_NOT_AUTHORIZED,
                    NULL, 0);

      ippDelete(request);

      return (NULL);
    }
  }
  else
    infile = -1;

  response = cupsDoIORequest(http, request, resource, infile, -1);

  if (infile >= 0)
    close(infile);

  return (response);
}
Example #2
0
http_status_t				/* O - Initial HTTP status */
cupsSendRequest(http_t     *http,	/* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
                ipp_t      *request,	/* I - IPP request */
                const char *resource,	/* I - Resource path */
		size_t     length)	/* I - Length of data to follow or @code CUPS_LENGTH_VARIABLE@ */
{
  http_status_t		status;		/* Status of HTTP request */
  int			got_status;	/* Did we get the status? */
  ipp_state_t		state;		/* State of IPP processing */
  http_status_t		expect;		/* Expect: header to use */


  DEBUG_printf(("cupsSendRequest(http=%p, request=%p(%s), resource=\"%s\", "
                "length=" CUPS_LLFMT ")", http, request,
		request ? ippOpString(request->request.op.operation_id) : "?",
		resource, CUPS_LLCAST length));

 /*
  * Range check input...
  */

  if (!request || !resource)
  {
    _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);

    return (HTTP_STATUS_ERROR);
  }

 /*
  * Get the default connection as needed...
  */

  if (!http)
    if ((http = _cupsConnect()) == NULL)
      return (HTTP_STATUS_SERVICE_UNAVAILABLE);

 /*
  * If the prior request was not flushed out, do so now...
  */

  if (http->state == HTTP_STATE_GET_SEND ||
      http->state == HTTP_STATE_POST_SEND)
  {
    DEBUG_puts("2cupsSendRequest: Flush prior response.");
    httpFlush(http);
  }
  else if (http->state != HTTP_STATE_WAITING)
  {
    DEBUG_printf(("1cupsSendRequest: Unknown HTTP state (%d), "
                  "reconnecting.", http->state));
    if (httpReconnect2(http, 30000, NULL))
      return (HTTP_STATUS_ERROR);
  }

#ifdef HAVE_SSL
 /*
  * See if we have an auth-info attribute and are communicating over
  * a non-local link.  If so, encrypt the link so that we can pass
  * the authentication information securely...
  */

  if (ippFindAttribute(request, "auth-info", IPP_TAG_TEXT) &&
      !httpAddrLocalhost(http->hostaddr) && !http->tls &&
      httpEncryption(http, HTTP_ENCRYPTION_REQUIRED))
  {
    DEBUG_puts("1cupsSendRequest: Unable to encrypt connection.");
    return (HTTP_STATUS_SERVICE_UNAVAILABLE);
  }
#endif /* HAVE_SSL */

 /*
  * Reconnect if the last response had a "Connection: close"...
  */

  if (!_cups_strcasecmp(http->fields[HTTP_FIELD_CONNECTION], "close"))
  {
    DEBUG_puts("2cupsSendRequest: Connection: close");
    httpClearFields(http);
    if (httpReconnect2(http, 30000, NULL))
    {
      DEBUG_puts("1cupsSendRequest: Unable to reconnect.");
      return (HTTP_STATUS_SERVICE_UNAVAILABLE);
    }
  }

 /*
  * Loop until we can send the request without authorization problems.
  */

  expect = HTTP_STATUS_CONTINUE;

  for (;;)
  {
    DEBUG_puts("2cupsSendRequest: Setup...");

   /*
    * Setup the HTTP variables needed...
    */

    httpClearFields(http);
    httpSetExpect(http, expect);
    httpSetField(http, HTTP_FIELD_CONTENT_TYPE, "application/ipp");
    httpSetLength(http, length);

#ifdef HAVE_GSSAPI
    if (http->authstring && !strncmp(http->authstring, "Negotiate", 9))
    {
     /*
      * Do not use cached Kerberos credentials since they will look like a
      * "replay" attack...
      */

      _cupsSetNegotiateAuthString(http, "POST", resource);
    }
#endif /* HAVE_GSSAPI */

    httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring);

    DEBUG_printf(("2cupsSendRequest: authstring=\"%s\"", http->authstring));

   /*
    * Try the request...
    */

    DEBUG_puts("2cupsSendRequest: Sending HTTP POST...");

    if (httpPost(http, resource))
    {
      DEBUG_puts("2cupsSendRequest: POST failed, reconnecting.");
      if (httpReconnect2(http, 30000, NULL))
      {
        DEBUG_puts("1cupsSendRequest: Unable to reconnect.");
        return (HTTP_STATUS_SERVICE_UNAVAILABLE);
      }
      else
        continue;
    }

   /*
    * Send the IPP data...
    */

    DEBUG_puts("2cupsSendRequest: Writing IPP request...");

    request->state = IPP_STATE_IDLE;
    status         = HTTP_STATUS_CONTINUE;
    got_status     = 0;

    while ((state = ippWrite(http, request)) != IPP_STATE_DATA)
      if (state == IPP_STATE_ERROR)
	break;
      else if (httpCheck(http))
      {
        got_status = 1;

        _httpUpdate(http, &status);
	if (status >= HTTP_STATUS_MULTIPLE_CHOICES)
	  break;
      }

    if (state == IPP_STATE_ERROR)
    {
      DEBUG_puts("1cupsSendRequest: Unable to send IPP request.");

      http->status = HTTP_STATUS_ERROR;
      http->state  = HTTP_STATE_WAITING;

      return (HTTP_STATUS_ERROR);
    }

   /*
    * Wait up to 1 second to get the 100-continue response as needed...
    */

    if (!got_status)
    {
      if (expect == HTTP_STATUS_CONTINUE)
      {
	DEBUG_puts("2cupsSendRequest: Waiting for 100-continue...");

	if (httpWait(http, 1000))
	  _httpUpdate(http, &status);
      }
      else if (httpCheck(http))
	_httpUpdate(http, &status);
    }

    DEBUG_printf(("2cupsSendRequest: status=%d", status));

   /*
    * Process the current HTTP status...
    */

    if (status >= HTTP_STATUS_MULTIPLE_CHOICES)
    {
      int temp_status;			/* Temporary status */

      _cupsSetHTTPError(status);

      do
      {
	temp_status = httpUpdate(http);
      }
      while (temp_status != HTTP_STATUS_ERROR &&
             http->state == HTTP_STATE_POST_RECV);

      httpFlush(http);
    }

    switch (status)
    {
      case HTTP_STATUS_CONTINUE :
      case HTTP_STATUS_OK :
      case HTTP_STATUS_ERROR :
          DEBUG_printf(("1cupsSendRequest: Returning %d.", status));
          return (status);

      case HTTP_STATUS_UNAUTHORIZED :
          if (cupsDoAuthentication(http, "POST", resource))
	  {
            DEBUG_puts("1cupsSendRequest: Returning HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED.");
	    return (HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED);
	  }

          DEBUG_puts("2cupsSendRequest: Reconnecting after HTTP_STATUS_UNAUTHORIZED.");

	  if (httpReconnect2(http, 30000, NULL))
	  {
	    DEBUG_puts("1cupsSendRequest: Unable to reconnect.");
	    return (HTTP_STATUS_SERVICE_UNAVAILABLE);
	  }
	  break;

#ifdef HAVE_SSL
      case HTTP_STATUS_UPGRADE_REQUIRED :
	 /*
	  * Flush any error message, reconnect, and then upgrade with
	  * encryption...
	  */

          DEBUG_puts("2cupsSendRequest: Reconnecting after "
	             "HTTP_STATUS_UPGRADE_REQUIRED.");

	  if (httpReconnect2(http, 30000, NULL))
	  {
	    DEBUG_puts("1cupsSendRequest: Unable to reconnect.");
	    return (HTTP_STATUS_SERVICE_UNAVAILABLE);
	  }

	  DEBUG_puts("2cupsSendRequest: Upgrading to TLS.");
	  if (httpEncryption(http, HTTP_ENCRYPTION_REQUIRED))
	  {
	    DEBUG_puts("1cupsSendRequest: Unable to encrypt connection.");
	    return (HTTP_STATUS_SERVICE_UNAVAILABLE);
	  }
	  break;
#endif /* HAVE_SSL */

      case HTTP_STATUS_EXPECTATION_FAILED :
	 /*
	  * Don't try using the Expect: header the next time around...
	  */

	  expect = (http_status_t)0;

          DEBUG_puts("2cupsSendRequest: Reconnecting after "
	             "HTTP_EXPECTATION_FAILED.");

	  if (httpReconnect2(http, 30000, NULL))
	  {
	    DEBUG_puts("1cupsSendRequest: Unable to reconnect.");
	    return (HTTP_STATUS_SERVICE_UNAVAILABLE);
	  }
	  break;

      default :
         /*
	  * Some other error...
	  */

	  return (status);
    }
  }
}
Example #3
0
ipp_t *					/* O - Response data */
cupsDoIORequest(http_t     *http,	/* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
                ipp_t      *request,	/* I - IPP request */
                const char *resource,	/* I - HTTP resource for POST */
		int        infile,	/* I - File to read from or -1 for none */
		int        outfile)	/* I - File to write to or -1 for none */
{
  ipp_t		*response = NULL;	/* IPP response data */
  size_t	length = 0;		/* Content-Length value */
  http_status_t	status;			/* Status of HTTP request */
  struct stat	fileinfo;		/* File information */
  int		bytes;			/* Number of bytes read/written */
  char		buffer[32768];		/* Output buffer */


  DEBUG_printf(("cupsDoIORequest(http=%p, request=%p(%s), resource=\"%s\", "
                "infile=%d, outfile=%d)", http, request,
		request ? ippOpString(request->request.op.operation_id) : "?",
		resource, infile, outfile));

 /*
  * Range check input...
  */

  if (!request || !resource)
  {
    ippDelete(request);

    _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);

    return (NULL);
  }

 /*
  * Get the default connection as needed...
  */

  if (!http)
    if ((http = _cupsConnect()) == NULL)
    {
      ippDelete(request);

      return (NULL);
    }

 /*
  * See if we have a file to send...
  */

  if (infile >= 0)
  {
    if (fstat(infile, &fileinfo))
    {
     /*
      * Can't get file information!
      */

      _cupsSetError(errno == EBADF ? IPP_STATUS_ERROR_NOT_FOUND : IPP_STATUS_ERROR_NOT_AUTHORIZED,
                    NULL, 0);

      ippDelete(request);

      return (NULL);
    }

#ifdef WIN32
    if (fileinfo.st_mode & _S_IFDIR)
#else
    if (S_ISDIR(fileinfo.st_mode))
#endif /* WIN32 */
    {
     /*
      * Can't send a directory...
      */

      ippDelete(request);

      _cupsSetError(IPP_STATUS_ERROR_NOT_POSSIBLE, strerror(EISDIR), 0);

      return (NULL);
    }

#ifndef WIN32
    if (!S_ISREG(fileinfo.st_mode))
      length = 0;			/* Chunk when piping */
    else
#endif /* !WIN32 */
    length = ippLength(request) + fileinfo.st_size;
  }
  else
    length = ippLength(request);

  DEBUG_printf(("2cupsDoIORequest: Request length=%ld, total length=%ld",
                (long)ippLength(request), (long)length));

 /*
  * Clear any "Local" authentication data since it is probably stale...
  */

  if (http->authstring && !strncmp(http->authstring, "Local ", 6))
    httpSetAuthString(http, NULL, NULL);

 /*
  * Loop until we can send the request without authorization problems.
  */

  while (response == NULL)
  {
    DEBUG_puts("2cupsDoIORequest: setup...");

   /*
    * Send the request...
    */

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

    DEBUG_printf(("2cupsDoIORequest: status=%d", status));

    if (status == HTTP_STATUS_CONTINUE && request->state == IPP_STATE_DATA && infile >= 0)
    {
      DEBUG_puts("2cupsDoIORequest: file write...");

     /*
      * Send the file with the request...
      */

#ifndef WIN32
      if (S_ISREG(fileinfo.st_mode))
#endif /* WIN32 */
      lseek(infile, 0, SEEK_SET);

      while ((bytes = (int)read(infile, buffer, sizeof(buffer))) > 0)
      {
        if ((status = cupsWriteRequestData(http, buffer, bytes))
                != HTTP_STATUS_CONTINUE)
	  break;
      }
    }

   /*
    * Get the server's response...
    */

    if (status != HTTP_STATUS_ERROR)
    {
      response = cupsGetResponse(http, resource);
      status   = httpGetStatus(http);
    }

    DEBUG_printf(("2cupsDoIORequest: status=%d", status));

    if (status == HTTP_STATUS_ERROR ||
        (status >= HTTP_STATUS_BAD_REQUEST && status != HTTP_STATUS_UNAUTHORIZED &&
	 status != HTTP_STATUS_UPGRADE_REQUIRED))
    {
      _cupsSetHTTPError(status);
      break;
    }

    if (response && outfile >= 0)
    {
     /*
      * Write trailing data to file...
      */

      while ((bytes = (int)httpRead2(http, buffer, sizeof(buffer))) > 0)
	if (write(outfile, buffer, bytes) < bytes)
	  break;
    }

    if (http->state != HTTP_STATE_WAITING)
    {
     /*
      * Flush any remaining data...
      */

      httpFlush(http);
    }
  }

 /*
  * Delete the original request and return the response...
  */

  ippDelete(request);

  return (response);
}
cups_array_t *				/* O - Array or NULL for no restrictions */
cupsdGetPrivateAttrs(
    cupsd_policy_t  *policy,		/* I - Policy */
    cupsd_client_t  *con,		/* I - Client connection */
    cupsd_printer_t *printer,		/* I - Printer, if any */
    const char      *owner)		/* I - Owner of object */
{
  char		*name;			/* Current name in access list */
  cups_array_t	*access_ptr,		/* Access array */
		*attrs_ptr;		/* Attributes array */
  const char	*username;		/* Username associated with request */
  ipp_attribute_t *attr;		/* Attribute from request */
  struct passwd	*pw;			/* User info */


#ifdef DEBUG
  cupsdLogMessage(CUPSD_LOG_DEBUG2,
                  "cupsdGetPrivateAttrs(policy=%p(%s), con=%p(%d), "
		  "printer=%p(%s), owner=\"%s\")", policy, policy->name, con,
		  con->http.fd, printer, printer ? printer->name : "", owner);
#endif /* DEBUG */

 /*
  * Get the access and attributes lists that correspond to the request...
  */

#ifdef DEBUG
  cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdGetPrivateAttrs: %s",
                  ippOpString(con->request->request.op.operation_id));
#endif /* DEBUG */

  switch (con->request->request.op.operation_id)
  {
    case IPP_GET_SUBSCRIPTIONS :
    case IPP_GET_SUBSCRIPTION_ATTRIBUTES :
    case IPP_GET_NOTIFICATIONS :
        access_ptr = policy->sub_access;
	attrs_ptr  = policy->sub_attrs;
	break;

    default :
        access_ptr = policy->job_access;
	attrs_ptr  = policy->job_attrs;
        break;
  }

 /*
  * If none of the attributes are private, return NULL now...
  */

  if ((name = (char *)cupsArrayFirst(attrs_ptr)) != NULL &&
      !_cups_strcasecmp(name, "none"))
  {
#ifdef DEBUG
    cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdGetPrivateAttrs: Returning NULL.");
#endif /* DEBUG */

    return (NULL);
  }

 /*
  * Otherwise check the user against the access list...
  */

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

  if (username[0])
  {
    pw = getpwnam(username);
    endpwent();
  }
  else
    pw = NULL;

#ifdef DEBUG
  cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdGetPrivateAttrs: username=\"%s\"",
                  username);
#endif /* DEBUG */

 /*
  * Otherwise check the user against the access list...
  */

  for (name = (char *)cupsArrayFirst(access_ptr);
       name;
       name = (char *)cupsArrayNext(access_ptr))
  {
#ifdef DEBUG
    cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdGetPrivateAttrs: name=%s", name);
#endif /* DEBUG */

    if (printer && !_cups_strcasecmp(name, "@ACL"))
    {
      char	*acl;			/* Current ACL user/group */

      for (acl = (char *)cupsArrayFirst(printer->users);
	   acl;
	   acl = (char *)cupsArrayNext(printer->users))
      {
	if (acl[0] == '@')
	{
	 /*
	  * Check group membership...
	  */

	  if (cupsdCheckGroup(username, pw, acl + 1))
	    break;
	}
	else if (acl[0] == '#')
	{
	 /*
	  * Check UUID...
	  */

	  if (cupsdCheckGroup(username, pw, acl))
	    break;
	}
	else if (!_cups_strcasecmp(username, acl))
	  break;
      }
    }
    else if (owner && !_cups_strcasecmp(name, "@OWNER") &&
             !_cups_strcasecmp(username, owner))
    {
#ifdef DEBUG
      cupsdLogMessage(CUPSD_LOG_DEBUG2,
		      "cupsdGetPrivateAttrs: Returning NULL.");
#endif /* DEBUG */

      return (NULL);
    }
    else if (!_cups_strcasecmp(name, "@SYSTEM"))
    {
      int i;				/* Looping var */

      for (i = 0; i < NumSystemGroups; i ++)
	if (cupsdCheckGroup(username, pw, SystemGroups[i]))
	{
#ifdef DEBUG
	  cupsdLogMessage(CUPSD_LOG_DEBUG2,
	                  "cupsdGetPrivateAttrs: Returning NULL.");
#endif /* DEBUG */

	  return (NULL);
	}
    }
    else if (name[0] == '@')
    {
      if (cupsdCheckGroup(username, pw, name + 1))
      {
#ifdef DEBUG
        cupsdLogMessage(CUPSD_LOG_DEBUG2,
	                "cupsdGetPrivateAttrs: Returning NULL.");
#endif /* DEBUG */

	return (NULL);
      }
    }
    else if (!_cups_strcasecmp(username, name))
    {
#ifdef DEBUG
      cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdGetPrivateAttrs: Returning NULL.");
#endif /* DEBUG */

      return (NULL);
    }
  }

 /*
  * No direct access, so return private attributes list...
  */

#ifdef DEBUG
  cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdGetPrivateAttrs: Returning list.");
#endif /* DEBUG */

  return (attrs_ptr);
}
size_t					/* O - Number of bytes less nul */
_ippAttrString(ipp_attribute_t *attr,	/* I - Attribute */
               char            *buffer,	/* I - String buffer or NULL */
               size_t          bufsize)	/* I - Size of string buffer */
{
    int		i;			/* Looping var */
    char		*bufptr,		/* Pointer into buffer */
                *bufend,		/* End of buffer */
                temp[256];		/* Temporary string */
    const char	*ptr;			/* Pointer into string */
    ipp_value_t	*val;			/* Current value */


    if (!attr || !attr->name)
    {
        if (buffer)
            *buffer = '\0';

        return (0);
    }

    bufptr = buffer;
    if (buffer)
        bufend = buffer + bufsize - 1;
    else
        bufend = NULL;

    for (i = attr->num_values, val = attr->values; i > 0; i --, val ++)
    {
        if (val > attr->values)
        {
            if (buffer && bufptr < bufend)
                *bufptr++ = ',';
            else
                bufptr ++;
        }

        switch (attr->value_tag & ~IPP_TAG_COPY)
        {
        case IPP_TAG_ENUM :
            if (!strcmp(attr->name, "printer-state") &&
                    val->integer >= IPP_PRINTER_IDLE &&
                    val->integer <= IPP_PRINTER_STOPPED)
            {
                ptr = printer_states[val->integer - IPP_PRINTER_IDLE];

                if (buffer && bufptr < bufend)
                    strlcpy(bufptr, ptr, bufend - bufptr + 1);

                bufptr += strlen(ptr);
                break;
            }
            else if (!strcmp(attr->name, "job-state") &&
                     val->integer >= IPP_JOB_PENDING &&
                     val->integer <= IPP_JOB_COMPLETED)
            {
                ptr = job_states[val->integer - IPP_JOB_PENDING];

                if (buffer && bufptr < bufend)
                    strlcpy(bufptr, ptr, bufend - bufptr + 1);

                bufptr += strlen(ptr);
                break;
            }
            else if (!strcmp(attr->name, "operations-supported"))
            {
                ptr = ippOpString(val->integer);

                if (buffer && bufptr < bufend)
                    strlcpy(bufptr, ptr, bufend - bufptr + 1);

                bufptr += strlen(ptr);
                break;
            }

        case IPP_TAG_INTEGER :
            if (buffer && bufptr < bufend)
                bufptr += snprintf(bufptr, bufend - bufptr + 1, "%d", val->integer);
            else
                bufptr += snprintf(temp, sizeof(temp), "%d", val->integer);
            break;

        case IPP_TAG_BOOLEAN :
            if (buffer && bufptr < bufend)
                strlcpy(bufptr, val->boolean ? "true" : "false",
                        bufend - bufptr + 1);

            bufptr += val->boolean ? 4 : 5;
            break;

        case IPP_TAG_RANGE :
            if (buffer && bufptr < bufend)
                bufptr += snprintf(bufptr, bufend - bufptr + 1, "%d-%d",
                                   val->range.lower, val->range.upper);
            else
                bufptr += snprintf(temp, sizeof(temp), "%d-%d", val->range.lower,
                                   val->range.upper);
            break;

        case IPP_TAG_RESOLUTION :
            if (buffer && bufptr < bufend)
                bufptr += snprintf(bufptr, bufend - bufptr + 1, "%dx%d%s",
                                   val->resolution.xres, val->resolution.yres,
                                   val->resolution.units == IPP_RES_PER_INCH ?
                                   "dpi" : "dpc");
            else
                bufptr += snprintf(temp, sizeof(temp), "%dx%d%s",
                                   val->resolution.xres, val->resolution.yres,
                                   val->resolution.units == IPP_RES_PER_INCH ?
                                   "dpi" : "dpc");
            break;

        case IPP_TAG_DATE :
        {
            unsigned year;		/* Year */

            year = (val->date[0] << 8) + val->date[1];

            if (val->date[9] == 0 && val->date[10] == 0)
                snprintf(temp, sizeof(temp), "%04u-%02u-%02uT%02u:%02u:%02uZ",
                         year, val->date[2], val->date[3], val->date[4],
                         val->date[5], val->date[6]);
            else
                snprintf(temp, sizeof(temp),
                         "%04u-%02u-%02uT%02u:%02u:%02u%c%02u%02u",
                         year, val->date[2], val->date[3], val->date[4],
                         val->date[5], val->date[6], val->date[8], val->date[9],
                         val->date[10]);

            if (buffer && bufptr < bufend)
                strlcpy(bufptr, temp, bufend - bufptr + 1);

            bufptr += strlen(temp);
        }
        break;

        case IPP_TAG_TEXT :
        case IPP_TAG_NAME :
        case IPP_TAG_KEYWORD :
        case IPP_TAG_CHARSET :
        case IPP_TAG_URI :
        case IPP_TAG_URISCHEME :
        case IPP_TAG_MIMETYPE :
        case IPP_TAG_LANGUAGE :
        case IPP_TAG_TEXTLANG :
        case IPP_TAG_NAMELANG :
            if (!val->string.text)
                break;

            for (ptr = val->string.text; *ptr; ptr ++)
            {
                if (*ptr == '\\' || *ptr == '\"')
                {
                    if (buffer && bufptr < bufend)
                        *bufptr = '\\';
                    bufptr ++;
                }

                if (buffer && bufptr < bufend)
                    *bufptr = *ptr;
                bufptr ++;
            }
            break;

        case IPP_TAG_BEGIN_COLLECTION :
            if (buffer && bufptr < bufend)
                bufptr += ipp_col_string(val->collection, bufptr,
                                         bufend - bufptr + 1);
            else
                bufptr += ipp_col_string(val->collection, NULL, 0);
            break;

        case IPP_TAG_STRING :
            for (ptr = val->string.text; *ptr; ptr ++)
            {
                if (*ptr == '\\' || _cups_isspace(*ptr))
                {
                    if (buffer && bufptr < bufend)
                        *bufptr = '\\';
                    bufptr ++;

                    if (buffer && bufptr < bufend)
                        *bufptr = *ptr;
                    bufptr ++;
                }
                else if (!isprint(*ptr & 255))
                {
                    if (buffer && bufptr < bufend)
                        bufptr += snprintf(bufptr, bufend - bufptr + 1, "\\%03o",
                                           *ptr & 255);
                    else
                        bufptr += snprintf(temp, sizeof(temp), "\\%03o",
                                           *ptr & 255);
                }
                else
                {
                    if (buffer && bufptr < bufend)
                        *bufptr = *ptr;
                    bufptr ++;
                }
            }
            break;

        default :
            ptr = ippTagString(attr->value_tag);
            if (buffer && bufptr < bufend)
                strlcpy(bufptr, ptr, bufend - bufptr + 1);
            bufptr += strlen(ptr);
            break;
        }
    }

    if (buffer && bufptr < bufend)
        *bufptr = '\0';
    else if (bufend)
        *bufend = '\0';

    return (bufptr - buffer);
}
Example #6
0
static int				/* O - Exit status */
do_test(const char        *server,	/* I - Server to use */
        int               port,		/* I - Port number to use */
        http_encryption_t encryption,	/* I - Encryption to use */
	int               requests,	/* I - Number of requests to send */
	const char        *opstring,	/* I - Operation string */
	int               verbose)	/* I - Verbose output? */
{
  int		i;			/* Looping var */
  http_t	*http;			/* Connection to server */
  ipp_t		*request;		/* IPP Request */
  struct timeval start,			/* Start time */
		end;			/* End time */
  double	reqtime,		/* Time for this request */
		elapsed;		/* Elapsed time */
  int		op;			/* Current operation */
  static ipp_op_t ops[5] =		/* Operations to test... */
		{
		  IPP_PRINT_JOB,
		  CUPS_GET_DEFAULT,
		  CUPS_GET_PRINTERS,
		  CUPS_GET_CLASSES,
		  IPP_GET_JOBS
		};


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

  if ((http = httpConnectEncrypt(server, port, encryption)) == NULL)
  {
    printf("testspeed(%d): unable to connect to server - %s\n", (int)getpid(),
           strerror(errno));
    return (1);
  }

 /*
  * Do multiple requests...
  */

  for (elapsed = 0.0, i = 0; i < requests; i ++)
  {
   /*
    * Build a request which requires the following attributes:
    *
    *    attributes-charset
    *    attributes-natural-language
    *
    * In addition, IPP_GET_JOBS needs a printer-uri attribute.
    */

    if (opstring)
      op = ippOpValue(opstring);
    else
      op = ops[i % (int)(sizeof(ops) / sizeof(ops[0]))];

    request = ippNewRequest(op);

    gettimeofday(&start, NULL);

    if (verbose)
      printf("testspeed(%d): %.6f %s ", (int)getpid(), elapsed,
	     ippOpString(op));

    switch (op)
    {
      case IPP_GET_JOBS :
	  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
                       NULL, "ipp://localhost/printers/");

      default :
	  ippDelete(cupsDoRequest(http, request, "/"));
          break;

      case IPP_PRINT_JOB :
	  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
                       NULL, "ipp://localhost/printers/test");
	  ippDelete(cupsDoFileRequest(http, request, "/printers/test",
	                              "../data/testprint.ps"));
          break;
    }

    gettimeofday(&end, NULL);

    reqtime = (end.tv_sec - start.tv_sec) +
              0.000001 * (end.tv_usec - start.tv_usec);
    elapsed += reqtime;

    switch (cupsLastError())
    {
      case IPP_OK :
      case IPP_NOT_FOUND :
          if (verbose)
	  {
	    printf("succeeded: %s (%.6f)\n", cupsLastErrorString(), reqtime);
	    fflush(stdout);
	  }
          break;

      default :
          if (!verbose)
	    printf("testspeed(%d): %s ", (int)getpid(),
	           ippOpString(ops[i & 3]));

	  printf("failed: %s\n", cupsLastErrorString());
          httpClose(http);
	  return (1);
    }
  }

  httpClose(http);

  printf("testspeed(%d): %d requests in %.1fs (%.3fs/r, %.1fr/s)\n",
         (int)getpid(), i, elapsed, elapsed / i, i / elapsed);

  return (0);
}
Example #7
0
File: encode.c Project: aosm/cups
void
cupsEncodeOptions2(
    ipp_t         *ipp,			/* I - Request to add to */
    int           num_options,		/* I - Number of options */
    cups_option_t *options,		/* I - Options */
    ipp_tag_t     group_tag)		/* I - Group to encode */
{
  int			i, j;		/* Looping vars */
  int			count;		/* Number of values */
  char			*s,		/* Pointer into option value */
			*val,		/* Pointer to option value */
			*copy,		/* Copy of option value */
			*sep,		/* Option separator */
			quote;		/* Quote character */
  ipp_attribute_t	*attr;		/* IPP attribute */
  ipp_tag_t		value_tag;	/* IPP value tag */
  cups_option_t		*option;	/* Current option */
  ipp_t			*collection;	/* Collection value */
  int			num_cols;	/* Number of collection values */
  cups_option_t		*cols;		/* Collection values */
  ipp_op_t		op;		/* Operation for this request */
  const ipp_op_t	*ops;		/* List of allowed operations */


  DEBUG_printf(("cupsEncodeOptions2(ipp=%p(%s), num_options=%d, options=%p, "
                "group_tag=%x)", ipp,
                ipp ? ippOpString(ippGetOperation(ipp)) : "", num_options,
                options, group_tag));

 /*
  * Range check input...
  */

  if (!ipp || num_options < 1 || !options)
    return;

 /*
  * Do special handling for the document-format/raw options...
  */

  op = ippGetOperation(ipp);

  if (group_tag == IPP_TAG_OPERATION &&
      (op == IPP_OP_PRINT_JOB || op == IPP_OP_PRINT_URI ||
       op == IPP_OP_SEND_DOCUMENT || op == IPP_OP_SEND_URI))
  {
   /*
    * Handle the document format stuff first...
    */

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

 /*
  * Then loop through the options...
  */

  for (i = num_options, option = options; i > 0; i --, option ++)
  {
    _ipp_option_t	*match;		/* Matching attribute */


   /*
    * Skip document format options that are handled above...
    */

    if (!_cups_strcasecmp(option->name, "raw") ||
        !_cups_strcasecmp(option->name, "document-format") ||
	!option->name[0])
      continue;

   /*
    * Figure out the proper value and group tags for this option...
    */

    if ((match = _ippFindOption(option->name)) != NULL)
    {
      if (match->group_tag != group_tag && match->alt_group_tag != group_tag)
        continue;

      value_tag = match->value_tag;

      if (match->operations)
        ops = match->operations;
      else if (group_tag == IPP_TAG_JOB)
        ops = ipp_job_creation;
      else if (group_tag == IPP_TAG_DOCUMENT)
        ops = ipp_doc_creation;
      else if (group_tag == IPP_TAG_SUBSCRIPTION)
        ops = ipp_sub_creation;
      else if (group_tag == IPP_TAG_PRINTER)
        ops = ipp_set_printer;
      else
      {
	DEBUG_printf(("2cupsEncodeOptions2: Skipping \"%s\".", option->name));
        continue;
      }
    }
    else
    {
      int	namelen;		/* Length of name */


      namelen = (int)strlen(option->name);

      if (namelen < 10 ||
          (strcmp(option->name + namelen - 8, "-default") &&
           strcmp(option->name + namelen - 10, "-supported")))
      {
	if (group_tag != IPP_TAG_JOB && group_tag != IPP_TAG_DOCUMENT)
	{
	  DEBUG_printf(("2cupsEncodeOptions2: Skipping \"%s\".", option->name));
          continue;
        }
      }
      else if (group_tag != IPP_TAG_PRINTER)
      {
	DEBUG_printf(("2cupsEncodeOptions2: Skipping \"%s\".", option->name));
        continue;
      }

      if (group_tag == IPP_TAG_JOB)
        ops = ipp_job_creation;
      else if (group_tag == IPP_TAG_DOCUMENT)
        ops = ipp_doc_creation;
      else
        ops = ipp_set_printer;

      if (!_cups_strcasecmp(option->value, "true") ||
          !_cups_strcasecmp(option->value, "false"))
	value_tag = IPP_TAG_BOOLEAN;
      else
	value_tag = IPP_TAG_NAME;
    }

   /*
    * Verify that we send this attribute for this operation...
    */

    while (*ops != IPP_OP_CUPS_NONE)
      if (op == *ops)
        break;
      else
        ops ++;

    if (*ops == IPP_OP_CUPS_NONE && op != IPP_OP_CUPS_NONE)
    {
      DEBUG_printf(("2cupsEncodeOptions2: Skipping \"%s\".", option->name));
      continue;
    }

   /*
    * Count the number of values...
    */

    if (match && match->multivalue)
    {
      for (count = 1, sep = option->value, quote = 0; *sep; sep ++)
      {
	if (*sep == quote)
	  quote = 0;
	else if (!quote && (*sep == '\'' || *sep == '\"'))
	{
	 /*
	  * Skip quoted option value...
	  */

	  quote = *sep++;
	}
	else if (*sep == ',' && !quote)
	  count ++;
	else if (*sep == '\\' && sep[1])
	  sep ++;
      }
    }
    else
      count = 1;

    DEBUG_printf(("2cupsEncodeOptions2: option=\"%s\", count=%d",
                  option->name, count));

   /*
    * Allocate memory for the attribute values...
    */

    if ((attr = ippAddStrings(ipp, group_tag, value_tag, option->name, count,
                              NULL, NULL)) == NULL)
    {
     /*
      * Ran out of memory!
      */

      DEBUG_puts("1cupsEncodeOptions2: Ran out of memory for attributes!");
      return;
    }

    if (count > 1)
    {
     /*
      * Make a copy of the value we can fiddle with...
      */

      if ((copy = strdup(option->value)) == NULL)
      {
       /*
	* Ran out of memory!
	*/

	DEBUG_puts("1cupsEncodeOptions2: Ran out of memory for value copy!");
	ippDeleteAttribute(ipp, attr);
	return;
      }

      val = copy;
    }
    else
    {
     /*
      * Since we have a single value, use the value directly...
      */

      val  = option->value;
      copy = NULL;
    }

   /*
    * Scan the value string for values...
    */

    for (j = 0, sep = val; j < count; val = sep, j ++)
    {
     /*
      * Find the end of this value and mark it if needed...
      */

      if (count > 1)
      {
	for (quote = 0; *sep; sep ++)
	{
	  if (*sep == quote)
	  {
	   /*
	    * Finish quoted value...
	    */

	    quote = 0;
	  }
	  else if (!quote && (*sep == '\'' || *sep == '\"'))
	  {
	   /*
	    * Handle quoted option value...
	    */

	    quote = *sep;
	  }
	  else if (*sep == ',' && count > 1)
	    break;
	  else if (*sep == '\\' && sep[1])
	  {
	   /*
	    * Skip quoted character...
	    */

	    sep ++;
	  }
	}

	if (*sep == ',')
	  *sep++ = '\0';
      }

     /*
      * Copy the option value(s) over as needed by the type...
      */

      switch (attr->value_tag)
      {
	case IPP_TAG_INTEGER :
	case IPP_TAG_ENUM :
	   /*
	    * Integer/enumeration value...
	    */

            attr->values[j].integer = (int)strtol(val, &s, 10);

            DEBUG_printf(("2cupsEncodeOptions2: Added integer option value "
	                  "%d...", attr->values[j].integer));
            break;

	case IPP_TAG_BOOLEAN :
	    if (!_cups_strcasecmp(val, "true") ||
	        !_cups_strcasecmp(val, "on") ||
	        !_cups_strcasecmp(val, "yes"))
	    {
	     /*
	      * Boolean value - true...
	      */

	      attr->values[j].boolean = 1;

              DEBUG_puts("2cupsEncodeOptions2: Added boolean true value...");
	    }
	    else
	    {
	     /*
	      * Boolean value - false...
	      */

	      attr->values[j].boolean = 0;

              DEBUG_puts("2cupsEncodeOptions2: Added boolean false value...");
	    }
            break;

	case IPP_TAG_RANGE :
	   /*
	    * Range...
	    */

            if (*val == '-')
	    {
	      attr->values[j].range.lower = 1;
	      s = val;
	    }
	    else
	      attr->values[j].range.lower = (int)strtol(val, &s, 10);

	    if (*s == '-')
	    {
	      if (s[1])
		attr->values[j].range.upper = (int)strtol(s + 1, NULL, 10);
	      else
		attr->values[j].range.upper = 2147483647;
            }
	    else
	      attr->values[j].range.upper = attr->values[j].range.lower;

	    DEBUG_printf(("2cupsEncodeOptions2: Added range option value "
	                  "%d-%d...", attr->values[j].range.lower,
			  attr->values[j].range.upper));
            break;

	case IPP_TAG_RESOLUTION :
	   /*
	    * Resolution...
	    */

	    attr->values[j].resolution.xres = (int)strtol(val, &s, 10);

	    if (*s == 'x')
	      attr->values[j].resolution.yres = (int)strtol(s + 1, &s, 10);
	    else
	      attr->values[j].resolution.yres = attr->values[j].resolution.xres;

	    if (!_cups_strcasecmp(s, "dpc") ||
	        !_cups_strcasecmp(s, "dpcm"))
              attr->values[j].resolution.units = IPP_RES_PER_CM;
            else
              attr->values[j].resolution.units = IPP_RES_PER_INCH;

	    DEBUG_printf(("2cupsEncodeOptions2: Added resolution option value "
	                  "%s...", val));
            break;

	case IPP_TAG_STRING :
           /*
	    * octet-string
	    */

            attr->values[j].unknown.length = (int)strlen(val);
	    attr->values[j].unknown.data   = strdup(val);

            DEBUG_printf(("2cupsEncodeOptions2: Added octet-string value "
	                  "\"%s\"...", (char *)attr->values[j].unknown.data));
            break;

        case IPP_TAG_BEGIN_COLLECTION :
	   /*
	    * Collection value
	    */

	    num_cols   = cupsParseOptions(val, 0, &cols);
	    if ((collection = ippNew()) == NULL)
	    {
	      cupsFreeOptions(num_cols, cols);

	      if (copy)
	        free(copy);

	      ippDeleteAttribute(ipp, attr);
	      return;
            }

	    attr->values[j].collection = collection;
	    cupsEncodeOptions2(collection, num_cols, cols, IPP_TAG_JOB);
            cupsFreeOptions(num_cols, cols);
	    break;

	default :
	    if ((attr->values[j].string.text = _cupsStrAlloc(val)) == NULL)
	    {
	     /*
	      * Ran out of memory!
	      */

	      DEBUG_puts("1cupsEncodeOptions2: Ran out of memory for string!");

	      if (copy)
	        free(copy);

	      ippDeleteAttribute(ipp, attr);
	      return;
	    }

	    DEBUG_printf(("2cupsEncodeOptions2: Added string value \"%s\"...",
	                  val));
            break;
      }
    }

    if (copy)
      free(copy);
  }
}
Example #8
0
File: request.c Project: apple/cups
ipp_t *					/* O - Response data */
cupsDoRequest(http_t     *http,		/* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
              ipp_t      *request,	/* I - IPP request */
              const char *resource)	/* I - HTTP resource for POST */
{
    DEBUG_printf(("cupsDoRequest(http=%p, request=%p(%s), resource=\"%s\")", (void *)http, (void *)request, request ? ippOpString(request->request.op.operation_id) : "?", resource));

    return (cupsDoIORequest(http, request, resource, -1, -1));
}